# -*- encoding: utf-8 -*- """ @File : gui.py @License : (C)Copyright 2021-2023 @Modify Time @Author @Version @Description ------------ ------- -------- ----------- 2023/11/1 13:37 zart20 1.0 None """ import tkinter as tk from tkinter import scrolledtext, ttk import cpu_data from cpu_data import * WORD = '#00f5ff' BLACK = "#000000" WHITE = "#F0F0F0" DATALINE = "#0CB90C" ADDRLINE = "#f35555" RED = "#FFAAAA" GREY = '#808080' GOLD = '#FFD700' GREEN = '#00FA9A' BACK = '#0153d2' ORANGE = '#d3b719' MEMBACK = '#fba651' width = 1000 # 设置窗口宽度 height = 700 root = tk.Tk() root.title("16位简易CPU可视化") root.geometry(f"{1300}x{700}") canvas = tk.Canvas(root, bg='white', bd=2, relief="sunken", width=width + 300, height=height, background=BLACK, borderwidth=0, highlightthickness=0) canvas.place(x=0, y=0, anchor=tk.NW, width=1300, height=700) # root_right = tk.Frame(root, bg=WHITE, relief="groove", width=240, height=height - 40) # root_right.place(x=width+25, y=15, anchor=tk.NW) # 右边栏 def round_rectangle(x1, y1, x2, y2, r=25, **kwargs): points = ( x1 + r, y1, x1 + r, y1, x2 - r, y1, x2 - r, y1, x2, y1, x2, y1 + r, x2, y1 + r, x2, y2 - r, x2, y2 - r, x2, y2, x2 - r, y2, x2 - r, y2, x1 + r, y2, x1 + r, y2, x1, y2, x1, y2 - r, x1, y2 - r, x1, y1 + r, x1, y1 + r, x1, y1) return canvas.create_polygon(points, **kwargs, smooth=True) round_rectangle(width + 20, 15, width + 270, height - 25, r=25, fill=WHITE, width=0) round_rectangle(20, 15, 970, height - 25, r=25, fill=WHITE, width=0) class TextBox: def __init__(self, canvas: canvas): self.canvas = canvas self.frame_low = tk.Frame(self.canvas, bg=WHITE, relief="groove", width=220, height=height - 50) # 底层框架 self.frame_low.place(x=width + 25, y=15, anchor=tk.NW) # 右边栏 self.frame_msg = tk.Frame(self.frame_low, bg=WHITE, relief="groove") # 消息框 self.frame_msg.grid(row=1, column=0) # 创建一个样式对象 style = ttk.Style() # 定义选项卡标题的样式 style.configure("Custom.TNotebook.Tab", font=("微软雅黑", 14)) self.tab_control = ttk.Notebook(self.frame_low, style="Custom.TNotebook") # 创建一个Notebook组件 self.tab_control.grid(row=0, column=0) self.page1 = self.creat_page(self.tab_control, "流程") # 创建两个分页 self.page2 = self.creat_page(self.tab_control, "运算") # 创建两个分页 self.page3 = self.creat_page(self.tab_control, "信号") # 创建两个分页 self.page4 = self.creat_page(self.tab_control, "内存") # 创建两个分页 self.frame_midel = tk.Frame(self.frame_low, bg=WHITE, relief="groove") # 中间框架 self.frame_midel.grid(row=0, column=0) self.l_x = 1020 self.r_x = 1027 self.m_x = 1145 # 消息区X轴中线位置 self.m_y = 265 # 消息区y轴分割位置 tk.Label(self.frame_msg, text="系统消息", font=('微软雅黑', 16), bg=WHITE)\ .grid(row=0, column=1, padx=5, pady=5) tk.Button(self.frame_msg, text="X", font=('微软雅黑', 12), bg=WHITE, command=self.clear)\ .grid(row=0, column=2, padx=5, pady=5, sticky="w") self.reset_button = tk.Button(self.frame_msg, text="↺", font=('微软雅黑', 12), bg=WHITE) # 重置按钮 self.reset_button.grid(row=0, column=0, padx=5, pady=5, sticky="e") # 重置按钮 self.instr_label() # 显示指令 self.create_text_box() # 显示消息框 def creat_page(self, tab_control, title): """创建一个新的分页""" page = ttk.Frame(tab_control) tab_control.add(page, text=title) return page def main_msg_box(self, msg: str, r,c, frame=None): # 在Canvas上创建主要消息框 if frame is None:frame = self.page1 label1 = tk.Label(frame, text=msg, font=('微软雅黑', 20), bg=WHITE) label1.grid(row=r, column=c, padx=5, pady=5,columnspan=2) def create_button(self, text: str, x: int, y: int, command: callable, frame=None) -> tk.Button: # 创建文本按钮 if frame is None:frame = self.page1 button = tk.Button(frame, text=text, command=command, font=('微软雅黑', 12), width=10, bg=WHITE) button.grid(row=x, column=y, padx=5, pady=5) return button def create_combobox(self, x: int, y: int, values: list, frame=None) -> ttk.Combobox: # 创建下拉框 if frame is None:frame = self.page1 combobox = ttk.Combobox(frame, values=values, width=10, font=('微软雅黑', 12)) combobox.set(values[0]) # 设置默认选项 combobox.grid(row=x, column=y, padx=5, pady=5) return combobox # 创建当行输入框 def create_entry(self, x: int, y: int, frame=None) -> tk.Entry: if frame is None:frame = self.page1 entry = tk.Entry(frame, font=('微软雅黑', 12), width=16) entry.insert(0, "输入R(x)新值!") entry.grid(row=x, column=y, padx=5, columnspan=2, pady=5) return entry # print(cpu_data.ALUio) def instr_label(self) -> None: self.label = tk.Label(self.page1, font=('微软雅黑', 16), width=10) self.label.grid(row=3, column=0, padx=5, pady=5,columnspan=2) def send_instr(self, text: str) -> None: formatted_text = f"指令:{text}" # 如果你想更新 Label 的文本,使用 configure 而不是再次创建 Label self.label.config(text=formatted_text, bg=RED) def create_text_box(self): """创建多行输入框""" self.info_text = scrolledtext.ScrolledText(self.frame_low, wrap=tk.WORD, height=15, width=20) # self.info_text.place(x=1025, y=290, anchor=tk.NW) self.info_text.grid(row=2, column=0) self.info_text.config(font=("微软雅黑", 14)) def send_msg(self, text: str) -> None: '''向输入框发送系统消息''' self.info_text.insert(tk.END, text + "\n") self.info_text.see(tk.END) def clear(self) -> None: '''清空系统消息框''' if self.info_text.get("1.0", tk.END).strip() != "": # 检查文本框内容是否非空 self.info_text.delete("1.0", tk.END) textbox = TextBox(canvas) # 全局化消息框 class GUISim: def __init__(self): self.canvas = canvas self.canvas.bind("", self.on_left_click) # root_right.bind("", self.on_left_click) self.alu = ALU() self.memo = MEMO() self.sigctrl = SIGCtrl() self.textbox = textbox # 为了让引用GUIsim类的对象来使用消息框 self.singe_ctrl_line() self.addr_line() self.data_line() self.line_explain() # self.show_msg() def on_left_click(self, event): print(event.x, ",", event.y) def singe_ctrl_line(self): # 控制线 sings = [] for sing in cpu_data.SigObj: # 遍历信号字典 if cpu_data.SigObj[sing][1]: # 如果信号的值为True sings.append(sing) # 将信号的名字添加到列表中 # if sings is None: # sings = [] self.canvas.delete("ctrl_line") # alu line_points = [90, 575, 65, 575, 65, 235, 98, 235] self.canvas.create_line(line_points, width=5, fill=GREY, arrow=tk.LAST, tags="ctrl_line", dash=(10, 10)) self.alu.draw_circle(103, 235, 5, fill=GREY, tags="ctrl_line") # maddr line_points = [205, 630, 205, 660, 630, 660, 630, 545] self.canvas.create_line(line_points, width=5, fill=GREY, arrow=tk.LAST, tags="ctrl_line", dash=(10, 10)) # r1 line_points = [135, 630, 135, 660, 45, 660, 45, 30, 560, 30, 560, 95, 515, 95] self.canvas.create_line(line_points, width=5, fill=GREY, arrow=tk.LAST, tags="ctrl_line", dash=(10, 10)) # r2 line_points = [135, 630, 135, 660, 45, 660, 45, 30, 560, 30, 560, 189, 515, 189] self.canvas.create_line(line_points, width=5, fill=GREY, arrow=tk.LAST, tags="ctrl_line", dash=(10, 10)) # r3 line_points = [135, 630, 135, 660, 45, 660, 45, 30, 560, 30, 560, 276, 515, 276] self.canvas.create_line(line_points, width=5, fill=GREY, arrow=tk.LAST, tags="ctrl_line", dash=(10, 10)) # r4 line_points = [135, 630, 135, 660, 45, 660, 45, 30, 560, 30, 560, 368, 515, 368] self.canvas.create_line(line_points, width=5, fill=GREY, arrow=tk.LAST, tags="ctrl_line", dash=(10, 10)) # Mcontent line_points = [135, 630, 135, 660, 45, 660, 45, 30, 560, 30, 885, 30, 885, 215] self.canvas.create_line(line_points, width=5, fill=GREY, arrow=tk.LAST, tags="ctrl_line", dash=(10, 10)) # pc line_points = [280, 540, 350, 540, 350, 485] self.canvas.create_line(line_points, width=5, fill=GREY, arrow=tk.LAST, tags="ctrl_line", dash=(10, 10)) # IR line_points = [225, 630, 225, 650, 350, 650, 350, 590] self.canvas.create_line(line_points, width=5, fill=GREY, arrow=tk.LAST, tags="ctrl_line", dash=(10, 10)) # IR -> inscode line_points = [332, 575, 275, 575] self.canvas.create_line(line_points, width=2, fill="black", arrow=tk.LAST, tags="ctrl_line") # clock -> inscode line_points = [200, 495, 200, 523] self.canvas.create_line(line_points, width=2, fill="black", arrow=tk.LAST, tags="ctrl_line") for sing in sings: if sing == "->ALU": # alu line_points = [90, 575, 65, 575, 65, 235, 98, 235] self.canvas.create_line(line_points, width=5, fill="red", arrow=tk.LAST, tags="ctrl_line", dash=(10, 10)) self.alu.draw_circle(103, 235, 5, fill=GREEN, tags="ctrl_line") self.textbox.send_msg("Sig->ALU") cpu_data.SigObj[sing][1] = False # 重置信号 # if sing == "MAD": if sing =="IR->Maddr" or sing == "PC->Maddr": # maddr line_points = [205, 630, 205, 660, 630, 660, 630, 545] self.canvas.create_line(line_points, width=5, fill="red", arrow=tk.LAST, tags="ctrl_line", dash=(10, 10)) self.textbox.send_msg("Sig->MAD") cpu_data.SigObj[sing][1] = False # 重置信号 if sing == "->R1": # r1 line_points = [135, 630, 135, 660, 45, 660, 45, 30, 560, 30, 560, 95, 515, 95] self.canvas.create_line(line_points, width=5, fill="red", arrow=tk.LAST, tags="ctrl_line", dash=(10, 10)) self.textbox.send_msg("Sig->R1") cpu_data.SigObj[sing][1] = False # 重置信号 if sing == "->R2": # r2 line_points = [135, 630, 135, 660, 45, 660, 45, 30, 560, 30, 560, 189, 515, 189] self.canvas.create_line(line_points, width=5, fill="red", arrow=tk.LAST, tags="ctrl_line", dash=(10, 10)) self.textbox.send_msg("Sig->R2") cpu_data.SigObj[sing][1] = False # 重置信号 if sing == "->R3": # r3 line_points = [135, 630, 135, 660, 45, 660, 45, 30, 560, 30, 560, 276, 515, 276] self.canvas.create_line(line_points, width=5, fill="red", arrow=tk.LAST, tags="ctrl_line", dash=(10, 10)) self.textbox.send_msg("Sig->R3") cpu_data.SigObj[sing][1] = False # 重置信号 if sing == "->R4": # r4 line_points = [135, 630, 135, 660, 45, 660, 45, 30, 560, 30, 560, 368, 515, 368] self.canvas.create_line(line_points, width=5, fill="red", arrow=tk.LAST, tags="ctrl_line", dash=(10, 10)) self.textbox.send_msg("Sig->R4") cpu_data.SigObj[sing][1] = False # 重置信号 # if sing == "MCO": # if sing == "Mcontent->PC" or sing == "Memory->Mcontent": if sing.find("Mcontent") != -1: # 如果信号名字中包含Mcontent # Mcontent line_points = [135, 630, 135, 660, 45, 660, 45, 30, 560, 30, 885, 30, 885, 215] self.canvas.create_line(line_points, width=5, fill="red", arrow=tk.LAST, tags="ctrl_line", dash=(10, 10)) self.textbox.send_msg("Sig->MCO") cpu_data.SigObj[sing][1] = False # 重置信号 if sing == "->PC+1": # pc line_points = [280, 540, 350, 540, 350, 485] self.canvas.create_line(line_points, width=5, fill="red", arrow=tk.LAST, tags="ctrl_line", dash=(10, 10)) self.textbox.send_msg("Sig->PC+1") cpu_data.SigObj[sing][1] = False # 重置信号 if sing == "->IR": # IR line_points = [225, 630, 225, 650, 350, 650, 350, 590] self.canvas.create_line(line_points, width=5, fill="red", arrow=tk.LAST, tags="ctrl_line", dash=(10, 10)) self.textbox.send_msg("Sig->IR") cpu_data.SigObj[sing][1] = False # 重置信号 def addr_line(self): # 地址线 sings = [] for key, value in cpu_data.SigObj.items(): if value[1]: sings.append(value[0]) self.canvas.delete("addr_line") # IR -> Maddr line_points = [400, 560, 400, 515, 560, 515, 614, 515] self.canvas.create_line(line_points, width=4, fill=GREY, arrow=tk.LAST, tags="addr_line") # pc -> Maddr line_points = [485, 465, 615, 465] self.canvas.create_line(line_points, width=4, fill=GREY, arrow=tk.LAST, tags="addr_line") for sing in sings: if sing == "IR->Maddr": # IR -> Maddr line_points = [400, 560, 400, 515, 560, 515, 614, 515] self.canvas.create_line(line_points, width=4, fill=ADDRLINE, arrow=tk.LAST, tags="addr_line") self.textbox.send_msg("IR->MAD") cpu_data.SigObj["IR->Maddr"][1] = False # 重置信号 if sing == "PC->Maddr": # pc -> Maddr line_points = [485, 465, 615, 465] self.canvas.create_line(line_points, width=4, fill=ADDRLINE, arrow=tk.LAST, tags="addr_line") self.textbox.send_msg("PC->MAD") cpu_data.SigObj["PC->Maddr"][1] = False # 重置信号 def data_line(self, singe=None): # 数据线 self.canvas.delete("data_line") # mco -> r1 line_points = [765, 218, 765, 175, 570, 175, 570, 108, 518, 108] self.canvas.create_line(line_points, width=5, fill=GREY, tags="data_line") # r1 -> mco line_points = [765, 218, 765, 175, 570, 175, 570, 108, 518, 108] self.canvas.create_line(line_points, width=5, fill=GREY, tags="data_line") # mco -> r2 line_points = [765, 218, 765, 175, 570, 175, 570, 198, 518, 198] self.canvas.create_line(line_points, width=5, fill=GREY, tags="data_line") # r2 -> mco line_points = [765, 218, 765, 175, 570, 175, 570, 198, 518, 198] self.canvas.create_line(line_points, width=5, fill=GREY, tags="data_line") # mco -> r3 line_points = [765, 218, 765, 175, 570, 175, 570, 288, 518, 288] self.canvas.create_line(line_points, width=5, fill=GREY, tags="data_line") # r3 -> mco line_points = [765, 218, 765, 175, 570, 175, 570, 288, 518, 288] self.canvas.create_line(line_points, width=5, fill=GREY, tags="data_line") # mco -> r4 line_points = [765, 218, 765, 175, 570, 175, 570, 378, 518, 378] self.canvas.create_line(line_points, width=5, fill=GREY, tags="data_line") # r4 -> mco line_points = [765, 218, 765, 175, 570, 175, 570, 378, 518, 378] self.canvas.create_line(line_points, width=5, fill=GREY, tags="data_line") # mco -> ir line_points = [765, 218, 765, 175, 570, 175, 570, 575, 495, 575] self.canvas.create_line(line_points, width=5, fill=GREY, tags="data_line") # mco -> pc line_points = [765, 218, 765, 175, 570, 175, 570, 475, 485, 475] self.canvas.create_line(line_points, width=5, fill=GREY, tags="data_line") # # memo -> mco # line_points = [855, 245, 855, 275] # self.canvas.create_line(line_points, width=5, fill=GREY, arrow=tk.LAST, tags="data_line") # # mco -> memo # line_points = [875, 245, 875, 275] # self.canvas.create_line(line_points, width=5, fill=GREY, arrow=tk.FIRST, tags="data_line") # mco -> r1 if singe == "mco-r1": line_points = [765, 218, 765, 175, 570, 175, 570, 108, 518, 108] self.canvas.create_line(line_points, width=5, fill=DATALINE, arrow=tk.LAST, tags="data_line") self.textbox.send_msg("MCO->R1") self.alu.r1.config(bg=RED) # r1 -> mco if singe == "r1-mco": line_points = [765, 218, 765, 175, 570, 175, 570, 108, 518, 108] self.canvas.create_line(line_points, width=5, fill=DATALINE, arrow=tk.FIRST, tags="data_line") self.textbox.send_msg("R1->MCO") self.memo.mco.config(bg=RED) # mco -> r2 if singe == "mco-r2": line_points = [765, 218, 765, 175, 570, 175, 570, 198, 518, 198] self.canvas.create_line(line_points, width=5, fill=DATALINE, arrow=tk.LAST, tags="data_line") self.textbox.send_msg("MCO->R2") self.alu.r2.config(bg=RED) # r2 -> mco if singe == "r2-mco": line_points = [765, 218, 765, 175, 570, 175, 570, 198, 518, 198] self.canvas.create_line(line_points, width=5, fill=DATALINE, arrow=tk.FIRST, tags="data_line") self.textbox.send_msg("R2->MCO") self.memo.mco.config(bg=RED) # mco -> r3 if singe == "mco-r3": line_points = [765, 218, 765, 175, 570, 175, 570, 288, 518, 288] self.canvas.create_line(line_points, width=5, fill=DATALINE, arrow=tk.LAST, tags="data_line") self.textbox.send_msg("MCO->R3") self.alu.r3.config(bg=RED) # r3 -> mco if singe == "r3-mco": line_points = [765, 218, 765, 175, 570, 175, 570, 288, 518, 288] self.canvas.create_line(line_points, width=5, fill=DATALINE, arrow=tk.FIRST, tags="data_line") self.textbox.send_msg("R3->MCO") self.memo.mco.config(bg=RED) # mco -> r4 if singe == "mco-r4": line_points = [765, 218, 765, 175, 570, 175, 570, 378, 518, 378] self.canvas.create_line(line_points, width=5, fill=DATALINE, arrow=tk.LAST, tags="data_line") self.textbox.send_msg("MCO->R4") self.alu.r4.config(bg=RED) # r4 -> mco if singe == "r4-mco": line_points = [765, 218, 765, 175, 570, 175, 570, 378, 518, 378] self.canvas.create_line(line_points, width=5, fill=DATALINE, arrow=tk.FIRST, tags="data_line") self.textbox.send_msg("R4->MCO") self.memo.mco.config(bg=RED) # mco -> ir if singe == "mco-ir": line_points = [765, 218, 765, 175, 570, 175, 570, 575, 495, 575] self.canvas.create_line(line_points, width=5, fill=DATALINE, arrow=tk.LAST, tags="data_line") self.textbox.send_msg("MCO->IR") self.sigctrl.ir_reg.config(bg=RED) # mco -> pc if singe == "mco-pc": line_points = [765, 218, 765, 175, 570, 175, 570, 475, 485, 475] self.canvas.create_line(line_points, width=5, fill=DATALINE, arrow=tk.LAST, tags="data_line") self.textbox.send_msg("MCO->PC") def line_explain(self): """线的类型标签""" line_points = [640, 60, 705, 60] self.canvas.create_line(line_points, width=3, fill="red", tags="line", dash=(10, 10)) self.canvas.create_text(737, 60, text="控制线", anchor=tk.CENTER, font=('微软雅黑', 12)) line_points = [640, 90, 705, 90] self.canvas.create_line(line_points, width=4, fill=ADDRLINE, tags="line", ) self.canvas.create_text(737, 90, text="地址线", anchor=tk.CENTER, font=('微软雅黑', 12)) line_points = [640, 120, 705, 120] self.canvas.create_line(line_points, width=5, fill=DATALINE, tags="line", ) self.canvas.create_text(737, 120, text="数据线", anchor=tk.CENTER, font=('微软雅黑', 12)) class ALU: def __init__(self): self.canvas = canvas self.r1_entry() self.r2_entry() self.r3_entry() self.r4_entry() self.alu_draw() # alu 图样 self.alu_line_init() # alu 的描述 self.show_alu_line(None) # alu 数据线 self.show_alu_reg() # alu r1-r4 self.alu_operation() # alu 符号 def draw_circle(self, x, y, r, fill=None, tags=None): """根据圆心坐标和半径画圆""" # 圆外接矩形 x1, y1, x2, y2 = x - r, y - r, x + r, y + r self.canvas.create_oval(x1, y1, x2, y2, width=1, fill=fill, tags=tags) def alu_draw(self): """画alu形状""" # 定义倒梯形的顶点坐标 round_rectangle(74, 48, 533, 415, fill="#226DDD", width=0, ) Point = [90, 190, 120, 190, 130, 215, 205, 215, 215, 190, 245, 190, 220, 270, 115, 270] self.canvas.create_polygon(Point, fill="black") # 绘制运算器 self.draw_circle(103, 235, 5, fill=GREY, tags="alu_status") def alu_line_init(self): """ALU模块命名""" self.canvas.create_text(140, 183, text='ALU', font=('微软雅黑', 20), anchor=tk.NW, fill=WORD) self.canvas.create_text(345, 95, text="R1", font=('微软雅黑', 18), fill=WORD) self.canvas.create_text(345, 185, text="R2", font=('微软雅黑', 18), fill=WORD) self.canvas.create_text(345, 275, text="R3", font=('微软雅黑', 18), fill=WORD) self.canvas.create_text(345, 365, text="R4", font=('微软雅黑', 18), fill=WORD) def alu_operation(self): """加减乘除""" side = 30 n = 0 for i in "+-x÷": if cpu_data.ALUop[i]: cpu_data.ALUop[i] = False self.canvas.create_text(115 + n * side, 240, text=f'{i}', font=('微软雅黑', 16), anchor=tk.NW, fill="#FFFFCC") textbox.send_msg(f"运算符: {i}") else: self.canvas.create_text(115 + n * side, 240, text=f'{i}', font=('微软雅黑', 16), anchor=tk.NW, fill=GREY) n += 1 def alu_r1(self, singed=None): line_points = [170, 273, 170, 315, 270, 315, 270, 100, 330, 100, ] if singed: self.canvas.create_line(line_points, width=5, fill=DATALINE, arrow=tk.LAST, tags="alu_r_line") else: self.canvas.create_line(line_points, width=5, fill=GREY, arrow=tk.LAST, tags="alu_r_line") def alu_r2(self, singed=None): line_points = [170, 273, 170, 315, 270, 315, 270, 180, 330, 180, ] if singed: self.canvas.create_line(line_points, width=5, fill=DATALINE, arrow=tk.LAST, tags="alu_r_line") else: self.canvas.create_line(line_points, width=5, fill=GREY, arrow=tk.LAST, tags="alu_r_line") def alu_r3(self, singed=None): line_points = [170, 273, 170, 315, 270, 315, 270, 275, 330, 275, ] if singed: self.canvas.create_line(line_points, width=5, fill=DATALINE, arrow=tk.LAST, tags="alu_r_line") else: self.canvas.create_line(line_points, width=5, fill=GREY, arrow=tk.LAST, tags="alu_r_line") def alu_r4(self, singed=None): line_points = [170, 273, 170, 315, 270, 315, 270, 355, 330, 355, ] if singed: self.canvas.create_line(line_points, width=5, fill=DATALINE, arrow=tk.LAST, tags="alu_r_line") else: self.canvas.create_line(line_points, width=5, fill=GREY, arrow=tk.LAST, tags="alu_r_line") def r1_alu1(self, singed=None): line_points = [340, 80, 340, 65, 310, 65, 100, 65, 100, 190] if singed: self.canvas.create_line(line_points, width=5, fill=DATALINE, arrow=tk.LAST, tags="alu_r_line") else: self.canvas.create_line(line_points, width=5, fill=GREY, arrow=tk.LAST, tags="alu_r_line") def r2_alu1(self, singed=None): line_points = [340, 165, 340, 155, 310, 155, 310, 65, 100, 65, 100, 190] if singed: self.canvas.create_line(line_points, width=5, fill=DATALINE, arrow=tk.LAST, tags="alu_r_line") else: self.canvas.create_line(line_points, width=5, fill=GREY, arrow=tk.LAST, tags="alu_r_line") def r3_alu1(self, singed=None): line_points = [340, 245, 340, 235, 310, 235, 310, 65, 100, 65, 100, 190] if singed: self.canvas.create_line(line_points, width=5, fill=DATALINE, arrow=tk.LAST, tags="alu_r_line") else: self.canvas.create_line(line_points, width=5, fill=GREY, arrow=tk.LAST, tags="alu_r_line") def r4_alu1(self, singed=None): line_points = [340, 335, 340, 325, 310, 325, 310, 65, 100, 65, 100, 190] if singed: self.canvas.create_line(line_points, width=5, fill=DATALINE, arrow=tk.LAST, tags="alu_r_line") else: self.canvas.create_line(line_points, width=5, fill=GREY, arrow=tk.LAST, tags="alu_r_line") def r1_alu2(self, singed=None): line_points = [340, 110, 340, 130, 295, 130, 295, 240, 250, 240, 250, 160, 230, 160, 230, 190] if singed: self.canvas.create_line(line_points, width=5, fill=DATALINE, arrow=tk.LAST, tags="alu_r_line") else: self.canvas.create_line(line_points, width=5, fill=GREY, arrow=tk.LAST, tags="alu_r_line") def r2_alu2(self, singed=None): line_points = [340, 200, 340, 220, 295, 220, 295, 240, 250, 240, 250, 160, 230, 160, 230, 190] if singed: self.canvas.create_line(line_points, width=5, fill=DATALINE, arrow=tk.LAST, tags="alu_r_line") else: self.canvas.create_line(line_points, width=5, fill=GREY, arrow=tk.LAST, tags="alu_r_line") def r3_alu2(self, singed=None): line_points = [340, 290, 340, 310, 295, 310, 295, 240, 250, 240, 250, 160, 230, 160, 230, 190] if singed: self.canvas.create_line(line_points, width=5, fill=DATALINE, arrow=tk.LAST, tags="alu_r_line") else: self.canvas.create_line(line_points, width=5, fill=GREY, arrow=tk.LAST, tags="alu_r_line") def r4_alu2(self, singed=None): line_points = [340, 380, 340, 395, 295, 395, 295, 240, 250, 240, 250, 160, 230, 160, 230, 190] if singed: self.canvas.create_line(line_points, width=5, fill=DATALINE, arrow=tk.LAST, tags="alu_r_line") else: self.canvas.create_line(line_points, width=5, fill=GREY, arrow=tk.LAST, tags="alu_r_line") def r1_entry(self, str=f"{0:016b}"): self.r1 = tk.Entry(self.canvas) self.r1.insert(0, str) self.r1.config(width=16, font=('微软雅黑', 12)) ent_win = self.canvas.create_window(365, 85, window=self.r1, anchor=tk.NW) ent_win.conjugate() def r2_entry(self, str=f"{0:016b}"): self.r2 = tk.Entry(self.canvas) self.r2.insert(0, str) self.r2.config(width=16, font=('微软雅黑', 12)) ent_win = self.canvas.create_window(365, 175, window=self.r2, anchor=tk.NW) ent_win.conjugate() def r3_entry(self, str=f"{0:016b}"): self.r3 = tk.Entry(self.canvas) self.r3.insert(0, str) self.r3.config(width=16, font=('微软雅黑', 12)) ent_win = self.canvas.create_window(365, 265, window=self.r3, anchor=tk.NW) ent_win.conjugate() def r4_entry(self, str=f"{0:016b}"): self.r4 = tk.Entry(self.canvas) self.r4.insert(0, str) self.r4.config(width=16, font=('微软雅黑', 12)) ent_win = self.canvas.create_window(365, 355, window=self.r4, anchor=tk.NW) ent_win.conjugate() def show_alu_line(self, ALUio=None): singed = [] # 保存需要显示的数据线 if ALUio is not None: for io, torf in ALUio.items(): # 遍历数据线的字典 if torf: # 如果数据线的值为True singed.append(io) # 将数据线的名字添加到列表中 self.canvas.delete("alu_r_line") self.alu_r1() self.alu_r2() self.alu_r3() self.alu_r4() self.r1_alu1() self.r2_alu1() self.r3_alu1() self.r4_alu1() self.r1_alu2() self.r2_alu2() self.r3_alu2() self.r4_alu2() for singe in singed: if singe == "ALU_R1": self.alu_r1("ALU_R1") textbox.send_msg("ALU->R1") if singe == "ALU_R2": self.alu_r2("ALU_R2") textbox.send_msg("ALU->R2") if singe == "ALU_R3": self.alu_r3("ALU_R3") textbox.send_msg("ALU->R3") if singe == "ALU_R4": self.alu_r4("ALU_R4") textbox.send_msg("ALU->R4") if singe == "R1_ALU_1": self.r1_alu1("R1_ALU_1") textbox.send_msg("R1->ALU1") if singe == "R2_ALU_1": self.r2_alu1("R2_ALU_1") textbox.send_msg("R2->ALU1") if singe == "R3_ALU_1": self.r3_alu1("R3_ALU_1") textbox.send_msg("R3->ALU1") if singe == "R4_ALU_1": self.r4_alu1("R4_ALU_1") textbox.send_msg("R4->ALU1") if singe == "R1_ALU_2": self.r1_alu2("R1_ALU_2") textbox.send_msg("R1->ALU2") if singe == "R2_ALU_2": self.r2_alu2("R2_ALU_2") textbox.send_msg("R2->ALU2") if singe == "R3_ALU_2": self.r3_alu2("R3_ALU_2") textbox.send_msg("R3->ALU2") if singe == "R4_ALU_2": self.r4_alu2("R4_ALU_2") textbox.send_msg("R4->ALU2") def show_alu_reg(self, reg=None, str=None): if reg == "r1": self.r1.delete(0, tk.END);self.r1.insert(0, str) elif reg == "r2": self.r2.delete(0, tk.END);self.r2.insert(0, str) elif reg == "r3": self.r3.delete(0, tk.END);self.r3.insert(0, str) elif reg == "r4": self.r4.delete(0, tk.END);self.r4.insert(0, str) class MEMO: def __init__(self): self.canvas = canvas round_rectangle(597, 205, 928, 670, r=25, fill="#0153d2", width=0) round_rectangle(675, 275, 910, 660, r=25, fill="black", width=0) self.canvas.create_rectangle(720, 281, 903, 654, fill=MEMBACK, width=0) self.mad_value = f"{0:016b}" # 初始化Maddr的值 self.original_value = 9999 # 保存变量mad_value的原来值,用于检查值是否更新 self.show() self.show_maddr(self.mad_value) # 显示Maddr的值 self.show_mco() self.show_offset(cpu_data.SimMem) # 显示地址 self.load_memo_data(cpu_data.SimMem) # 显示内存数据 def draw_circle(self, x, y, r, fill=None, tags=None): """根据圆心坐标和半径画圆""" # 圆外接矩形 x1, y1, x2, y2 = x - r, y - r, x + r, y + r self.canvas.create_oval(x1, y1, x2, y2, width=1, fill=fill, tags=tags) def mad_to_memo(self, value=None): # value 用来控制地址线的显示 """mad指向内存""" self.show_maddr(self.mad_value) # 刷新Maddr的显示 if value: offset = int(self.mad_value, 2) # 转换为int self.show_maddr(self.mad_value, 1) # 显示Maddr的变化 else: offset = None self.mem_get(offset) # 从内存中获取响应地址的二进制值 def mco_to_memo(self): """mco指向内存""" offset = int(self.mad_value, 2) # int二进制转换 value = self.mco.get() self.mem_save(offset, value) # textbox.send_msg("MCO->memo") def show(self): self.canvas.create_text(670, 219, text='Mcontent', font=('微软雅黑', 12, 'bold'), anchor=tk.NW, fill=WORD) self.canvas.create_text(611, 356, text='Maddr', font=('微软雅黑', 12, 'bold'), anchor=tk.NW, fill=WORD) self.canvas.create_text(700, 260, text='地址', font=('time', 12,), anchor=tk.CENTER, fill='#ffd700') self.canvas.create_text(790, 260, text='在选单元', font=('time', 12,), anchor=tk.CENTER, fill='#ffd700') def show_mco(self): # 显示mco self.mco = tk.Entry(self.canvas) self.mco.insert(0, f"{0:016b}") self.mco.config(width=16, font=('微软雅黑', 12)) ent_win = self.canvas.create_window(753, 218, window=self.mco, anchor=tk.NW) ent_win.conjugate() def show_offset(self, SimMem): # 显示地址 for i in range(len(SimMem)): # 显示存储器各个单元的地址 self.canvas.create_text(688, 282 + 18.5 * i, text=f"{i:02X}", font=('微软雅黑', 12), anchor=tk.NW, fill=GOLD) def load_memo_data(self, SimMem): # 程序单元 self.canvas.delete("bin_code") for i in range(20): bin_str = SimMem[i] bin_str_spa = " ".join([bin_str[i:i + 8] for i in range(0, len(bin_str), 8)]) self.canvas.create_text(735, 282 + 18.5 * i, text=bin_str_spa, font=('微软雅黑', 12), anchor=tk.NW, fill="black", tags="bin_code") self.draw_circle(675, 293 + 18.5 * i, 5, fill=GREY, tags="bin_code") def mem_save(self, offset, value, SimMem=cpu_data.SimMem, load=None): """保存value到offset地址""" self.canvas.delete("bin_code") SimMem[offset] = value for i in range(20): bin_str = SimMem[i] bin_str_spa = " ".join([bin_str[i:i + 8] for i in range(0, len(bin_str), 8)]) self.canvas.create_text(735, 282 + 18.5 * i, text=bin_str_spa, font=('微软雅黑', 12), anchor=tk.NW, fill="black", tags="bin_code") if i == offset: y = 293 + 18.5 * i self.draw_circle(675, y, 7, fill=GREEN, tags="bin_code") # Maddr -> memo line_points = [650, y, 669, y] self.canvas.create_line(line_points, width=4, fill=ADDRLINE, arrow=tk.LAST, tags="bin_code") if load is None: textbox.send_msg(f"MAD->memo[{i:02X}]") # moo -> memo line_points = [855, 245, 855, 275] self.canvas.create_line(line_points, width=5, fill=DATALINE, arrow=tk.LAST, tags="bin_code") if load is None: textbox.send_msg(f"MCO->memo[{i:02X}]") else: self.draw_circle(675, 293 + 18.5 * i, 5, fill=GREY, tags="bin_code") def mem_get(self, offset): """获取offset地址的值""" self.canvas.delete("bin_code") # 更新内存显示值 self.mco.config(bg=WHITE) for i in range(20): bin_str = SimMem[i] bin_str_spa = " ".join([bin_str[i:i + 8] for i in range(0, len(bin_str), 8)]) self.canvas.create_text(735, 282 + 18.5 * i, text=bin_str_spa, font=('微软雅黑', 12), anchor=tk.NW, fill="black", tags="bin_code") # 当传入地址时,显示数据线指示 if i == offset: y = 293 + 18.5 * i self.draw_circle(675, y, 7, fill=RED, tags="bin_code") # 显示寻址单位激活态圆 # Maddr -> memo line_points = [650, y, 669, y] self.canvas.create_line(line_points, width=4, fill=ADDRLINE, arrow=tk.LAST, tags="bin_code") textbox.send_msg(f"MAD->memo[{offset:02X}]") # memo -> Mco line_points = [875, 245, 875, 275] self.canvas.create_line(line_points, width=5, fill=DATALINE, arrow=tk.FIRST, tags="bin_code") textbox.send_msg(f"memo[{offset:02X}]->MCO") self.mco.delete(0, tk.END) # 更新mco的值 self.mco.insert(0, SimMem[offset]) self.mco.config(bg=RED) else: self.draw_circle(675, 293 + 18.5 * i, 5, fill=GREY, tags="bin_code") def show_maddr(self, get_pc, col_tag=None): # 根据存储的数据显示当前Maddr的值 self.mad_value = get_pc self.canvas.delete("maddr") if col_tag is not None: self.canvas.create_rectangle(619, 383, 648, 541, fill=RED, width=0, tags="maddr") else: self.canvas.create_rectangle(619, 383, 648, 541, fill=WHITE, width=0, tags="maddr") self.canvas.create_text(620, 390, text=self.mad_value, font=('微软雅黑', 12), anchor=tk.NE, fill=BLACK, angle=90, tags="maddr") class SIGCtrl: def __init__(self): self.canvas = canvas round_rectangle(74, 434, 533, 642, r=25, fill=BACK, width=0) round_rectangle(97, 525, 276, 627, r=25, fill=BLACK, width=0) self.x0, self.y0, self.r = 113, 473, 15 # 时钟大小 self.bx2, self.by2, self.dx, self.dy = 105, 558, 120, 16 # 设置sig_ctrl文字间隔 self.ir_value = f"{0:016b}" self.pc_value = f"{0:016b}" self.clo_mark() self.show_tags() self.pc_reg_value() self.ir_reg_value() self.show_singe() self.insCode() def draw_circle(self, x, y, r, fill=WHITE, tags=None): """根据圆心坐标和半径画圆""" # 圆外接矩形 x1, y1, x2, y2 = x - r, y - r, x + r, y + r self.canvas.create_oval(x1, y1, x2, y2, width=1, fill=fill, tags=tags) def clo_mark(self, time_series: int = None): # 依据时钟周期显示时钟周期 self.canvas.delete("time") round_rectangle(95, 455, 95 + 213, 455 + 37, fill=WHITE, width=0, tags="time") for i in range(6): # 遍历六个时钟刻,绘制各个时钟 ClockStep[i] = True x = i * 35 + self.x0 self.draw_circle(x, self.y0, self.r, fill=WHITE, tags="time") if i == time_series: self.draw_circle(x, self.y0, self.r, fill=RED, tags="time") self.canvas.create_text(x, self.y0, text=f"{i + 1}", font=('微软雅黑', 16, 'bold'), anchor=tk.CENTER, fill=BLACK, tags='time') def show_tags(self): # 显示标签 self.canvas.create_text(95, 434, text='Clock', font=('微软雅黑', 12, 'bold'), anchor=tk.NW, fill=WORD) self.canvas.create_text(342, 434, text='PC', font=('微软雅黑', 12, 'bold'), anchor=tk.NW, fill=WORD) self.canvas.create_text(104, 500, text='SigCtrl', font=('微软雅黑', 12, 'bold'), anchor=tk.NW, fill=WORD) self.canvas.create_text(342, 540, text='IR', font=('微软雅黑', 12, 'bold'), anchor=tk.NW, fill=WORD) def pc_reg_value(self): self.pc_reg = tk.Entry(self.canvas) # PC 寄存器 self.pc_reg.config(width=16, font=('微软雅黑', 12)) self.pc_reg.insert(0, self.pc_value) self.canvas.create_window(335, 455, window=self.pc_reg, anchor=tk.NW) def ir_reg_value(self): value = self.ir_value self.canvas.delete("ir_reg") self.ir_reg = tk.Entry(self.canvas) # IR 寄存器 self.ir_reg.config(width=17, font=('微软雅黑', 12)) self.ir_reg.insert(0, value[:6] + " " + value[6:]) self.canvas.create_window(335, 565, window=self.ir_reg, anchor=tk.NW, tags="ir_reg") def insCode(self): self.ins = tk.Entry(self.canvas) self.ins.config(width=6, font=('微软雅黑', 12)) self.ins.insert(0, f"{0:06b}") self.canvas.create_window(203, 532, window=self.ins, anchor=tk.NW, tags="ins_code") def show_singe(self): sings = [] for sing in cpu_data.SigObj: # 遍历信号字典 if cpu_data.SigObj[sing][1]: # 如果信号的值为True sings.append(sing) # 将信号的名字添加到列表中 self.canvas.delete("sig_ctrl") self.canvas.create_text(110, 535, text="insCode", font=('微软雅黑', 12), fill=GOLD, anchor=tk.NW, tags="sig_ctrl") self.canvas.create_text(self.bx2, self.by2, text='->ALU', font=('微软雅黑', 10), anchor=tk.NW, tags="sig_ctrl", fill=GREY) self.canvas.create_text(self.bx2, self.by2 + self.dy, text='->IR', font=('微软雅黑', 10), anchor=tk.NW, tags="sig_ctrl", fill=GREY) self.canvas.create_text(self.bx2, self.by2 + self.dy * 2, text='->PC + 1', font=('微软雅黑', 10), anchor=tk.NW, tags="sig_ctrl", fill=GREY) self.canvas.create_text(self.bx2, self.by2 + self.dy * 3, text='->MEMORY', font=('微软雅黑', 10), anchor=tk.NW, tags="sig_ctrl", fill=GREY) self.canvas.create_text(self.bx2 + self.dx, self.by2, text='->R1', font=('微软雅黑', 10), anchor=tk.NW, tags="sig_ctrl", fill=GREY) self.canvas.create_text(self.bx2 + self.dx, self.by2 + self.dy, text='->R2', font=('微软雅黑', 10), anchor=tk.NW, tags="sig_ctrl", fill=GREY) self.canvas.create_text(self.bx2 + self.dx, self.by2 + self.dy * 2, text='->R3', font=('微软雅黑', 10), anchor=tk.NW, tags="sig_ctrl", fill=GREY) self.canvas.create_text(self.bx2 + self.dx, self.by2 + self.dy * 3, text='->R4', font=('微软雅黑', 10), anchor=tk.NW, tags="sig_ctrl", fill=GREY) for sing in sings: if sing == "->ALU": # if cpu_data.SigObj[sing][1]: self.canvas.create_text(self.bx2, self.by2, text='->ALU', font=('微软雅黑', 10), anchor=tk.NW, tags="sig_ctrl", fill=GOLD) cpu_data.SigObj[sing][1] = False if sing == "->IR": self.canvas.create_text(self.bx2, self.by2 + self.dy, text='->IR', font=('微软雅黑', 10), anchor=tk.NW, tags="sig_ctrl", fill=GOLD) cpu_data.SigObj[sing][1] = False if sing == "->PC+1": self.canvas.create_text(self.bx2, self.by2 + self.dy * 2, text='->PC + 1', font=('微软雅黑', 10), anchor=tk.NW, tags="sig_ctrl", fill=GOLD) cpu_data.SigObj[sing][1] = False if sing == "->Memory": self.canvas.create_text(self.bx2, self.by2 + self.dy * 3, text='->MEMORY', font=('微软雅黑', 10), anchor=tk.NW, tags="sig_ctrl", fill=GOLD) cpu_data.SigObj[sing][1] = False if sing == "->R1": self.canvas.create_text(self.bx2 + self.dx, self.by2, text='->R1', font=('微软雅黑', 10), anchor=tk.NW, tags="sig_ctrl", fill=GOLD) cpu_data.SigObj[sing][1] = False if sing == "->R2": self.canvas.create_text(self.bx2 + self.dx, self.by2 + self.dy, text='->R2', font=('微软雅黑', 10), anchor=tk.NW, tags="sig_ctrl", fill=GOLD) cpu_data.SigObj[sing][1] = False if sing == "->R3": self.canvas.create_text(self.bx2 + self.dx, self.by2 + self.dy * 2, text='->R3', font=('微软雅黑', 10), anchor=tk.NW, tags="sig_ctrl", fill=GOLD) cpu_data.SigObj[sing][1] = False if sing == "->R4": self.canvas.create_text(self.bx2 + self.dx, self.by2 + self.dy * 3, text='->R4', font=('微软雅黑', 10), anchor=tk.NW, tags="sig_ctrl", fill=GOLD) cpu_data.SigObj[sing][1] = False if __name__ == '__main__': gui = GUISim() alu = ALU() memo = MEMO() # memo.mem_get(12) sig = SIGCtrl() root.mainloop()