# -*- encoding: utf-8 -*- """ @File : execute_instruction.py @License : (C)Copyright 2021-2023 @Modify Time @Author @Version @Description ------------ ------- -------- ----------- 2023/11/10 17:14 zart20 1.0 None """ import re import time from tkinter import filedialog from gui import * inscode_map = { '取数': '000001', '存数': '000010', '加法': '000011', '减法': '000111', '乘法': '000100', '除法': '001000', '打印': '000101', '停机': '000110', '跳转': '001001' } class ExecInstructWithText: def __init__(self): self.wait_time = 0.1 # 节拍计时 self.gui = GUISim() # 主界面显示 self.alu = self.gui.alu # alu实例化 self.memo = self.gui.memo # memo 实例化 self.sing = self.gui.sigctrl # 信号实例化 self.textbox = self.gui.textbox # 信息输入框实例化 self.regs = {"R1": self.alu.r1, "R2": self.alu.r2, "R3": self.alu.r3, "R4": self.alu.r4} # 寄存器值槽 self.sing_times1 = 0 # 取数指令的节拍计数变量 self.sing_times2 = 0 # 存数指令的节拍 self.menu_test() self.show_msg() # 显示消息框 self.manual_opera_step = 0 self.entry_replace(self.sing.pc_reg, f"{0:016b}") self.ctrl_stop = False self.register_mapping = { "01": (self.alu.r2, "mco-r2"), "10": (self.alu.r3, "mco-r3"), "11": (self.alu.r4, "mco-r4"), "00": (self.alu.r1, "mco-r1"), } # self.textbox.msg_box("kkxs") def reset(self): self.__init__() self.textbox.clear() def stop_exec(self): if self.ctrl_stop == True: self.ctrl_stop = False self.ctrl_exec.config(text="暂停执行") self.exec_auto() else: self.ctrl_stop = True self.ctrl_exec.config(text="继续执行") def show_msg(self): """显示固定信息""" self.textbox.reset_button.configure(command=self.reset) self.textbox.canvas.delete("button") self.textbox.main_msg_box("系统控制", 0, 0) self.textbox.create_button("自动执行指令", x=1, y=0, command=self.exec_auto) self.ctrl_exec = self.textbox.create_button("暂停执行", x=1, y=1, command=self.stop_exec) self.prev_button = self.textbox.create_button("上一步", x=2, y=0, command=self.prev) self.next_button = self.textbox.create_button("下一步", x=2, y=1, command=self.exec_next) page2 = self.textbox.page2 self.textbox.main_msg_box("运算器控制", 0, 0, page2) self.textbox.create_button("更改运算", x=1, y=0, frame=page2, command=self.manual_opera_io) self.textbox.create_button("更改输入输出", x=1, y=1, frame=page2, command=self.manual_opera_io) self.textbox.create_button("更改R1-R4", x=3, y=1, frame=page2, command=self.manual_reg) self.alu_reg = self.textbox.create_combobox(x=3, y=0, frame=page2, values=["R1", "R2", "R3", "R4"]) self.alu_reg_value = self.textbox.create_entry(x=2, y=0, frame=page2) page3 = self.textbox.page3 self.textbox.main_msg_box("信号控制", 0, 0, page3) self.textbox.create_button("自动连续执行", x=1, y=0, frame=page3, command=self.exec_auto) self.textbox.create_button("单指令执行", x=2, y=0, frame=page3, command=self.one_instruct) self.textbox.create_button("更改信号", x=3, y=0, frame=page3, command=self.modify_sing) self.textbox.create_button("更改REG", x=1, y=1, frame=page3, command=self.modify_ctrl_reg) sing_obj = ['->R1', '->R2', '->R3', '->R4', '->IR', '->ALU', '->PC+1', '->Memory'] self.sing_single = self.textbox.create_combobox(x=3, y=1, frame=page3, values=list(sing_obj)) sing_inscode = inscode_map.keys() # 获取指令 self.sing_instruct = self.textbox.create_combobox(x=2, y=1, frame=page3, values=list(sing_inscode)) page4 = self.textbox.page4 self.textbox.main_msg_box("内存控制", 0, 0, page4) self.textbox.create_button("更改内存REG", x=1, y=0, frame=page4, command=self.modify_memo_reg) self.textbox.create_button("更改部分储存", x=1, y=1, frame=page4, command=self.manual_input) self.textbox.create_button("装载一段程序", x=2, y=0, frame=page4, command=self.read_file) self.textbox.create_button("装载一批数据", x=2, y=1, frame=page4, command=self.load_many_data) def one_instruct(self): inscode = self.sing_instruct.get() inscode = inscode_map[inscode] self.exe_one_instruct(inscode) def modify_sing(self): sing = self.sing_single.get() cpu_data.SigObj[sing][1] = True self.sing.show_singe() print(sing) def manual_reg(self): # 手动更改寄存器 reg = self.alu_reg.get() value = self.alu_reg_value.get() self.entry_replace(self.regs[reg], value) self.textbox.send_msg("更改成功") def modify_memo_reg(self): # 更改控制器寄存器 def n_mco_button(): value = self.n_mco.get() self.entry_replace(self.memo.mco, value) self.textbox.send_msg("更改成功") def n_mad_button(): value = self.n_mad.get() self.memo.show_maddr(value) self.textbox.send_msg("更改成功") top = tk.Toplevel() top.title("内存寄存器修改") # top.geometry(f"{460}x{200}") tk.Label(top, text="新Mcontent值:", font=('微软雅黑', 16)).grid(row=0, column=0, padx=5, pady=5, sticky="e") self.n_mco = tk.Entry(top, font=('微软雅黑', 12), width=16) self.n_mco.grid(row=0, column=1, padx=5, pady=5) tk.Button(top, text="确定", font=('微软雅黑', 12), width=10, bg="white", command=n_mco_button) \ .grid(row=0, column=2, padx=5, pady=5) tk.Label(top, text="新Maddr值:", font=('微软雅黑', 16)).grid(row=1, column=0, padx=5, pady=5, sticky="e") self.n_mad = tk.Entry(top, font=('微软雅黑', 12), width=16) self.n_mad.grid(row=1, column=1, padx=5, pady=5) tk.Button(top, text="确定", font=('微软雅黑', 12), width=10, bg="white", command=n_mad_button) \ .grid(row=1, column=2, padx=5, pady=5) def load_many_data(self): # 更改控制器寄存器 def load_memo_finish(): start = self.memo_addr.get() start = int(start, 16) data = self.memo_text.get("1.0", "end") data = data.split("\n") for index, line in enumerate(data): line = line.replace("\n", "") if index+start < 20 and re.match("^[01]{16}$", line): self.memo.mem_save(index+start, line, load=True) self.textbox.send_msg(f"【{index+start:02X}】数据装载完成") else: if index+start > 19: break elif line == "": self.textbox.send_msg(f"【{index+start:02X}】数据异常请检查") top = tk.Toplevel() top.title("装载一批数据") top.geometry(f"{245}x{330}") tk.Label(top, text="起始地址:", font=('微软雅黑', 16)).grid(row=0, column=0, padx=5, pady=5, sticky="e") self.memo_addr = ttk.Combobox(top, values=[f"{i:02X}" for i in range(20)], width=10, font=('微软雅黑', 12)) self.memo_addr.grid(row=0, column=1, padx=5, pady=5) self.memo_text = tk.Text(top, font=('微软雅黑', 12), width=16, height=10) self.memo_text.grid(row=1, column=0, columnspan=2, padx=5, pady=5) tk.Button(top, text="确定", font=('微软雅黑', 12), width=10, bg="white", command=load_memo_finish) \ .grid(row=2, column=1, padx=5, pady=5) def modify_ctrl_reg(self): # 更改控制器寄存器 def n_pc_button(): value = self.n_pc.get() self.entry_replace(self.sing.pc_reg, value) self.textbox.send_msg("更改成功") def n_ir_button(): value = self.n_ir.get() self.entry_replace(self.sing.ir_reg, value) self.sing.ir_reg_value() # 更新IR的值 self.textbox.send_msg("更改成功") def n_clock_button(): value = self.n_clock.get() self.sing.clo_mark(int(value) - 1) self.textbox.send_msg("更改成功") def n_inscode_button(): value = self.n_inscode.get() self.entry_replace(self.sing.ins, value) self.textbox.send_msg("更改成功") top = tk.Toplevel() top.title("控制器控制") top.geometry(f"{450}x{200}") tk.Label(top, text="新PC值:", font=('微软雅黑', 16)).grid(row=0, column=0, padx=5, pady=5, sticky="e") self.n_pc = tk.Entry(top, font=('微软雅黑', 12), width=16) self.n_pc.grid(row=0, column=1, padx=5, pady=5) tk.Button(top, text="确定", font=('微软雅黑', 12), width=10, bg="white", command=n_pc_button) \ .grid(row=0, column=2, padx=5, pady=5) tk.Label(top, text="新IR值:", font=('微软雅黑', 16)).grid(row=1, column=0, padx=5, pady=5, sticky="e") self.n_ir = tk.Entry(top, font=('微软雅黑', 12), width=16) self.n_ir.grid(row=1, column=1, padx=5, pady=5) tk.Button(top, text="确定", font=('微软雅黑', 12), width=10, bg="white", command=n_ir_button) \ .grid(row=1, column=2, padx=5, pady=5) tk.Label(top, text="新Clock值:", font=('微软雅黑', 16)).grid(row=2, column=0, padx=5, pady=5, sticky="e") self.n_clock = tk.Entry(top, font=('微软雅黑', 12), width=16) self.n_clock.grid(row=2, column=1, padx=5, pady=5) tk.Button(top, text="确定", font=('微软雅黑', 12), width=10, bg="white", command=n_clock_button) \ .grid(row=2, column=2, padx=5, pady=5) tk.Label(top, text="新Inscode值:", font=('微软雅黑', 16)).grid(row=3, column=0, padx=5, pady=5, sticky="e") self.n_inscode = tk.Entry(top, font=('微软雅黑', 12), width=16) self.n_inscode.grid(row=3, column=1, padx=5, pady=5) tk.Button(top, text="确定", font=('微软雅黑', 12), width=10, bg="white", command=n_inscode_button) \ .grid(row=3, column=2, padx=5, pady=5) def manual_opera_io(self): # 手动更改运算 values = list(cpu_data.ALUio.keys()) def ok(): in1_val = self.in1.get() in2_val = self.in2.get() out_val = self.out.get() opera_val = self.opera_op.get() for io in cpu_data.ALUio: cpu_data.ALUio[io] = False # 重置所有输入输出 cpu_data.ALUio[in1_val] = True cpu_data.ALUio[in2_val] = True cpu_data.ALUio[out_val] = True self.alu.show_alu_line(cpu_data.ALUio) # 显示数据控制线 for op in cpu_data.ALUop: cpu_data.ALUop[op] = False # 重置所有操作 cpu_data.ALUop[opera_val] = True self.alu.alu_operation() top = tk.Toplevel() top.title("运算器控制") top.geometry(f"{360}x{180}") tk.Label(top, text="ALU输入", font=('微软雅黑', 16)).grid(row=0, column=0, padx=5, pady=5) tk.Label(top, text="ALU输出", font=('微软雅黑', 16)).grid(row=1, column=0, padx=5, pady=5) tk.Label(top, text="运算符", font=('微软雅黑', 16)).grid(row=2, column=0, padx=5, pady=5) self.in1 = ttk.Combobox(top, values=values, width=10, font=('微软雅黑', 12)) self.in1.set(values[0]) # 设置默认选项 self.in1.grid(row=0, column=1, padx=5, pady=5) self.in2 = ttk.Combobox(top, values=values, width=10, font=('微软雅黑', 12)) self.in2.set(values[0]) # 设置默认选项 self.in2.grid(row=0, column=2, padx=5, pady=5) self.out = ttk.Combobox(top, values=values, width=10, font=('微软雅黑', 12)) self.out.set(values[0]) # 设置默认选项 self.out.grid(row=1, column=1, padx=5, pady=5) self.opera_op = ttk.Combobox(top, values=["+", "-", "x", "÷"], width=10, font=('微软雅黑', 12)) self.opera_op.set("+") # 设置默认选项 self.opera_op.grid(row=2, column=1, padx=5, pady=5) tk.Button(top, text="确定", font=('微软雅黑', 12), width=10, bg="white", command=ok) \ .grid(row=8, column=1, padx=5, pady=5) def menu_test(self): menu_bar = tk.Menu(root) root.config(menu=menu_bar) font = ("son", 12) lode_menu = tk.Menu(menu_bar, tearoff=0) menu_bar.add_cascade(label="装载程序", menu=lode_menu, font=font) lode_menu.add_command(label="从文件装载", command=self.read_file, font=font) lode_menu.add_command(label="手动输入", command=self.manual_input, font=font) file_menu = tk.Menu(menu_bar, tearoff=0) menu_bar.add_cascade(label="单指令执行", menu=file_menu) file_menu.add_command(label="取数", command=lambda: self.exe_one_instruct("000001")) file_menu.add_command(label="存数", command=lambda: self.exe_one_instruct("000010")) file_menu.add_command(label="加法", command=lambda: self.exe_one_instruct("000011")) file_menu.add_command(label="减法", command=lambda: self.exe_one_instruct("000111")) file_menu.add_command(label="乘法", command=lambda: self.exe_one_instruct("000100")) file_menu.add_command(label="除法", command=lambda: self.exe_one_instruct("001000")) file_menu.add_command(label="打印", command=lambda: self.exe_one_instruct("000101")) file_menu.add_command(label="停机", command=lambda: self.exe_one_instruct("000110")) file_menu.add_command(label="顺序执行", command=lambda: self.exec_auto()) def entry_replace(self, entry: tk.Entry, value): entry.delete(0, tk.END) entry.insert(0, value) def binary_addition(self, num1, num2): result = bin_to_dec(num1) + bin_to_dec(num2) # 转为10进制的加 result_binary = dec_to_bin(result) return result_binary def binary_subtraction(self, num1, num2): result = bin_to_dec(num1) - bin_to_dec(num2) # 转为10进制的减 result_binary = dec_to_bin(result) return result_binary def binary_multiplication(self, num1, num2): result = bin_to_dec(num1) * bin_to_dec(num2) # 转为10进制的加 result_binary = dec_to_bin(result) return result_binary def binary_division(self, dividend, divisor): quotient = bin_to_dec(dividend) // bin_to_dec(divisor) result_binary = dec_to_bin(quotient) return result_binary # remainder = bin(int(dividend, 2) % int(divisor, 2))[2:] def reg_enhance_display(self, rx): """强化显示R1-R4""" self.alu.canvas.delete("reg") for i in range(4): if rx == f"R{i + 1}": self.alu.canvas.create_line(365, 120 + i * 90, 513, 120 + i * 90, width=8, fill="#00FF00", tag="reg") self.alu.canvas.create_line(365, 75 + i * 90, 513, 75 + i * 90, width=8, fill="#00FF00", tag="reg") def gen_opera(self, rx=None, ry=None, op=None, sing_num=None): # 一般计算规则 """ rx为小号寄存器,ry为大号寄存器 寄存器字母一定要填大写 """ for io in cpu_data.ALUio: cpu_data.ALUio[io] = False # 清空ALU的数据线 if op is not None: cpu_data.ALUop[op] = True # 设置ALU的操作 rt1, rt2 = None, None # 用于存储寄存器的实体框 for reg, entry in self.regs.items(): # 遍历寄存器编号和寄存器实体框 entry.config(bg=WHITE) # 寄存器恢复 if reg == rx: rt1 = entry if sing_num == 4: cpu_data.ALUio[f"{rx}_ALU_1"] = True if reg == ry: rt2 = entry if sing_num == 4: cpu_data.ALUio[f"{ry}_ALU_2"] = True if rx is not None and ry is not None: v1 = rt1.get() # 获取R1的值 v2 = rt2.get() # 获取R2的值 if sing_num == 4: self.alu.show_alu_line(cpu_data.ALUio) # 节拍5时显示寄存器到ALU的路线 self.alu.alu_operation() # 显示符号 rt1.config(bg=RED) rt2.config(bg=RED) if sing_num == 5: if op == "+": v = self.binary_addition(v1, v2) # 二进制加 elif op == "-": v = self.binary_subtraction(v1, v2) # 二进制减法 elif op == "x": v = self.binary_multiplication(v1, v2) # 二进制乘法 elif op == "÷": v = self.binary_division(v1, v2) # 二进制除法 else: v = None # alu_line.append(f"ALU_{rx}") # 用于显示ALU的数据线 cpu_data.ALUio[f"ALU_{rx}"] = True self.alu.alu_operation() # 显示符号 self.alu.show_alu_line(cpu_data.ALUio) # 显示数据控制线 self.entry_replace(rt1, f"{v}") # 替换R1中的值 rt1.config(bg=RED) def pc_add_one(self, b16): v = int(b16, 2) return f"{v + 1:016b}" def reg_update(self): self.sing.pc_reg.config(bg=WHITE) # 更新PC寄存器的背景显示 self.sing.ins.config(bg=WHITE) # 更新ins背景 self.sing.ir_reg.config(bg=WHITE) # 更新IR的颜色 self.alu.r1.config(bg=WHITE) self.alu.r2.config(bg=WHITE) self.alu.r3.config(bg=WHITE) self.alu.r4.config(bg=WHITE) # 储存寄存器在储存类中已经处理,这里不再重复处理 def read_file(self): filename = filedialog.askopenfilename(title="选择文件", filetypes=[("TXT文件", "*.txt")]) if filename: with open(filename, "r", encoding="utf8") as f: memo_line = f.readlines() # 按行读取文件信息 for index, line in enumerate(memo_line): line = line.replace("\n", "") # 去掉换行符 if index < 20 and re.match("^[01]{16}$", line): self.memo.mem_save(index, line, load=True) else: self.textbox.send_msg(f"【{index:02X}】数据异常请检查") if index > 19: break self.textbox.send_msg("装载完成") self.entry_replace(self.sing.pc_reg, f"{0:016b}") def on_inscode_select(self, event): # 获取选择的值 selected_value = self.inscode_input.get() inscode = inscode_map.get(selected_value) self.inscode_input.set(inscode) print(selected_value) def load_finish(self): self.child_window.destroy() self.entry_replace(self.sing.pc_reg, f"{0:016b}") self.textbox.send_msg("装载完成") def on_offset_select(self, event): ox16 = self.o_value_input.get() value = int(ox16, 16) self.o_value_input.set(f"{value:010b}") def data_to_mome(self, offset_input): data_input = self.d_value.get() if offset_input and data_input: offset = int(offset_input, 16) if re.match("^-?[01]{16}$", data_input): self.memo.mem_save(offset, data_input, load=True) self.textbox.send_msg("数据装载完成\n" + f"{offset:02X}:{data_input}") elif re.match("^-?\d+$", data_input) and len(data_input) < 7: # 如果是10进制数不可能多于7位 # data_input = f"{int(data_input):016b}" data_input = cpu_data.dec_to_bin(int(data_input)) self.memo.mem_save(offset, data_input, load=True) self.textbox.send_msg("数据装载完成\n" + f"{offset:02X}:{data_input}") else: if len(data_input) > 16: self.textbox.send_msg(f"{data_input}不是16位数。") else: self.textbox.send_msg(f"{data_input}不是规范的二进制数。") def save_to_mome(self, offset): inscode = self.inscode_input.get() value = self.o_value_input.get() if offset: offset = int(offset, 16) if inscode and value: value = inscode + value self.memo.mem_save(offset, value, load=True) self.textbox.send_msg(f"指令装载完成\n{offset:02X}:{value}") def manual_input(self): self.child_window = tk.Toplevel(root) self.child_window.title("手动输入程序") self.child_window.geometry("350x360") fram_down = tk.Frame(self.child_window) tk.Label(fram_down, text="指令输入", font=("微软雅黑", 16, "bold")).grid(row=0, column=0, columnspan=3) fram_down.place(x=0, y=0, width=350, height=360) offset_label = tk.Label(fram_down, text="地址", font=("微软雅黑", 16)) offset_label.grid(row=1, column=0, sticky="nsew") inscode_label = tk.Label(fram_down, text="指令", font=("微软雅黑", 16)) inscode_label.grid(row=1, column=1, sticky="nsew") o_value_label = tk.Label(fram_down, text="寻址地址", font=("微软雅黑", 16)) o_value_label.grid(row=1, column=2, sticky="nsew") hex_options = [f"{i:02X}" for i in range(20)] # 生成00-13的16进制选项 offset_input = ttk.Combobox(fram_down, values=hex_options, font=("微软雅黑", 12), width=1) offset_input.grid(row=2, column=0, sticky="nsew", padx=5) inscode_options = list(inscode_map.keys()) self.inscode_input = ttk.Combobox(fram_down, values=inscode_options, font=("微软雅黑", 12), width=6) self.inscode_input.grid(row=2, column=1, sticky="nsew", padx=5) self.inscode_input.bind("<>", self.on_inscode_select) bin_options = [f"{i:02X}" for i in range(20)] # 生成00-13的16进制选项 self.o_value_input = ttk.Combobox(fram_down, values=bin_options, font=("微软雅黑", 12), width=10) self.o_value_input.grid(row=2, column=2, sticky="nsew", padx=5) self.o_value_input.bind("<>", self.on_offset_select) save_b = tk.Button(fram_down, text="确认", bg=RED, font=("微软雅黑", 12), command=lambda: self.save_to_mome(offset_input.get())) save_b.grid(row=3, column=0, columnspan=3, sticky="nsew", padx=10, pady=4) tk.Label(fram_down, text="*" * 300, font=("微软雅黑", 16)).grid(row=4, column=0, columnspan=3) tk.Label(fram_down, text="数据输入", font=("微软雅黑", 16, "bold")).grid(row=5, column=0, columnspan=3) d_off = tk.Label(fram_down, text="地址", font=("微软雅黑", 16)) d_off.grid(row=6, column=0, sticky="nsew") d_value_lb = tk.Label(fram_down, text="数据", font=("微软雅黑", 16)) d_value_lb.grid(row=6, column=1, columnspan=2, sticky="nsew") hex_options = [f"{i:02X}" for i in range(20)] # 生成00-13的16进制选项 d_off_in = ttk.Combobox(fram_down, values=hex_options, font=("微软雅黑", 12), width=1) d_off_in.grid(row=7, column=0, sticky="nsew", padx=5) self.d_value = tk.Entry(fram_down, font=("微软雅黑", 12)) self.d_value.grid(row=7, column=1, columnspan=2, sticky="nsew") self.d_value.insert(0, "支持10进制和16位进制") d_save = tk.Button(fram_down, text="确认", bg=RED, font=("微软雅黑", 12), command=lambda: self.data_to_mome(d_off_in.get())) d_save.grid(row=8, column=0, columnspan=3, sticky="nsew", padx=10, pady=4) # 配置列权重,使它们按比例占据整个宽度 fram_down.columnconfigure(0, weight=2) fram_down.columnconfigure(1, weight=6) fram_down.columnconfigure(2, weight=10) finish = tk.Button(fram_down, text="装载完成", bg=GOLD, font=("微软雅黑", 12), command=self.load_finish) finish.grid(row=9, column=2, sticky="nsew", padx=10) def SimGet(self, sing_num, reg_code=None): """取数指令""" self.textbox.send_instr("取数") if sing_num == 3: self.textbox.send_msg(f"======Step{sing_num + 1}======") self.reg_update() # 恢复寄存器 self.sing.clo_mark(sing_num) # 显示节拍 cpu_data.SigObj['->Memory'][1] = True self.sing.show_singe() # 显示控制器信号 self.gui.addr_line() # 更新地址线 self.alu.show_alu_line() # 更新alu的数据线 self.memo.mad_to_memo(1) # 更新mad-mome的地址线,参数为真则显示 cpu_data.SigObj['Memory->Mcontent'][1] = True self.gui.singe_ctrl_line() # 显示控制线 if reg_code in self.register_mapping: # 选择寄存器 register, data_line = self.register_mapping[reg_code] self.gui.data_line(data_line) self.entry_replace(register, self.memo.mco.get()) register.config(bg=RED) canvas.update() def SimPut(self, sing_num, reg_code=None): """存数指令""" self.textbox.send_instr("存数") if sing_num == 3: self.textbox.send_msg(f"======Step{sing_num + 1}======") if reg_code in self.register_mapping: # 选择寄存器 register, data_line = self.register_mapping[reg_code] mco, reg = data_line.split("-") self.reg_update() # 恢复寄存器 self.sing.clo_mark(sing_num) cpu_data.SigObj['->Memory'][1] = True self.sing.show_singe() # 显示控制器信号 cpu_data.SigObj['Mcontent->Memory'][1] = True self.gui.singe_ctrl_line() self.gui.addr_line() # self.gui.data_line("r1-mco") self.alu.show_alu_line() # 更新alu的数据线 # self.memo.mad_to_memo() # 更新mad-mome的地址线,参数为真则显示 self.memo.mco_to_memo() # 更新储存的显示显示 self.gui.data_line(f"{reg}-{mco}") # 重构参数 self.entry_replace(self.memo.mco, register.get()) register.config(bg=RED) self.memo.mco_to_memo() # 显示 canvas.update() def SimAddr(self, sing_num, reg_code=None): """加法指令""" self.textbox.send_instr("加法") if sing_num == 3: self.textbox.send_msg(f"======Step{sing_num + 1}======") if reg_code in self.register_mapping: # 选择寄存器 register, data_line = self.register_mapping[reg_code] mco, reg = data_line.split("-") reg = int(reg[-1]) + 1 self.reg_update() self.sing.clo_mark(sing_num) # 显示节拍 cpu_data.SigObj['->Memory'][1] = True self.sing.show_singe() # 显示控制器信号 cpu_data.SigObj[f'Mcontent->R{reg}'][1] = True cpu_data.SigObj[f'->R{reg}'][1] = True self.gui.singe_ctrl_line() # 显示控制线 self.gui.addr_line() # 更新地址线 self.memo.mad_to_memo(1) # 更新mad-mome的地址线,参数为真则显示 self.gui.data_line(f"mco-r{reg}") # 更新数据线 self.alu.show_alu_line() # 更新alu的数据线 # self.memo.mad_to_memo() # 显示memo动画 self.entry_replace(eval(f'self.alu.r{reg}'), self.memo.mco.get()) # 更新显示R1中的值 canvas.update() if sing_num == 4: self.textbox.send_msg(f"======Step{sing_num + 1}======") if reg_code in self.register_mapping: # 选择寄存器 register, data_line = self.register_mapping[reg_code] mco, reg = data_line.split("-") reg = int(reg[-1]) + 1 self.reg_update() self.sing.clo_mark(sing_num) # 显示节拍 cpu_data.SigObj['->ALU'][1] = True self.sing.show_singe() # 显示控制器信号 cpu_data.SigObj['->ALU'][1] = True self.gui.singe_ctrl_line() # 显示控制线 self.gui.addr_line() # 更新地址线 self.gui.data_line() # 更新数据线 self.memo.mad_to_memo() # 更新mad-mome的地址线,参数为真则显示 self.alu.show_alu_line() # 更新alu的数据线 self.gen_opera(f"R{reg - 1}", f"R{reg}", "+", sing_num) canvas.update() if sing_num == 5: self.textbox.send_msg(f"======Step{sing_num + 1}======") if reg_code in self.register_mapping: # 查找寄存器 register, data_line = self.register_mapping[reg_code] mco, reg = data_line.split("-") reg = int(reg[-1]) + 1 self.reg_update() self.sing.clo_mark(sing_num) # 显示节拍 self.sing.show_singe() # 显示控制器信号 self.gui.singe_ctrl_line() # 显示控制线 self.gui.addr_line() # 更新地址线 self.gui.data_line() # 更新数据线 self.memo.mad_to_memo() # 更新mad-mome的地址线,参数为真则显示 self.alu.show_alu_line() # 更新alu的数据线 self.gen_opera(f"R{reg - 1}", f"R{reg}", "+", sing_num) canvas.update() def SimMinus(self, sing_num, reg_code): """减法指令""" self.textbox.send_instr(f"减法") register, data_line = self.register_mapping[reg_code] mco, reg = data_line.split("-") reg = int(reg[-1]) + 1 if sing_num == 3: self.textbox.send_msg(f"======Step{sing_num + 1}======") self.reg_update() self.sing.clo_mark(sing_num) # 显示节拍 cpu_data.SigObj['->Memory'][1] = True self.sing.show_singe() # 显示控制器信号 cpu_data.SigObj[f'Mcontent->R{reg}'][1] = True cpu_data.SigObj[f'->R{reg}'][1] = True self.gui.singe_ctrl_line() # 显示控制线 self.gui.addr_line() # 更新地址线 self.memo.mad_to_memo(1) # 更新mad-mome的地址线,参数为真则显示 self.gui.data_line(f"mco-r{reg}") # 更新数据线 self.alu.show_alu_line() # 更新alu的数据线 self.entry_replace(eval(f"self.alu.r{reg}"), self.memo.mco.get()) # 更新显示R2中的值 canvas.update() if sing_num == 4: self.textbox.send_msg(f"======Step{sing_num + 1}======") self.reg_update() self.sing.clo_mark(sing_num) # 显示节拍 cpu_data.SigObj['->ALU'][1] = True self.sing.show_singe() # 显示控制器信号 cpu_data.SigObj['->ALU'][1] = True self.gui.singe_ctrl_line() # 显示控制线 self.gui.addr_line() # 更新地址线 self.gui.data_line() # 更新数据线 self.memo.mad_to_memo() # 更新mad-mome的地址线,参数为真则显示 self.alu.show_alu_line() # 更新alu的数据线 self.gen_opera(f"R{reg - 1}", f"R{reg}", "-", sing_num) canvas.update() if sing_num == 5: self.textbox.send_msg(f"======Step{sing_num + 1}======") self.reg_update() self.sing.clo_mark(sing_num) # 显示节拍 self.sing.show_singe() # 显示控制器信号 self.gui.singe_ctrl_line() # 显示控制线 self.gui.addr_line() # 更新地址线 self.gui.data_line() # 更新数据线 self.memo.mad_to_memo() # 更新mad-mome的地址线,参数为真则显示 self.alu.show_alu_line() # 更新alu的数据线 self.gen_opera(f"R{reg - 1}", f"R{reg}", "-", sing_num) canvas.update() def SimProduct(self, sing_num, reg_code): """乘法指令""" self.textbox.send_instr(f"乘法") register, data_line = self.register_mapping[reg_code] mco, reg = data_line.split("-") reg = int(reg[-1]) + 1 if sing_num == 3: self.textbox.send_msg(f"======Step{sing_num + 1}======") self.reg_update() self.sing.clo_mark(sing_num) # 显示节拍 cpu_data.SigObj['->Memory'][1] = True self.sing.show_singe() # 显示控制器信号 cpu_data.SigObj[f'Mcontent->R{reg}'][1] = True cpu_data.SigObj[f'->R{reg}'][1] = True self.gui.singe_ctrl_line() # 显示控制线 self.gui.addr_line() # 更新地址线 self.memo.mad_to_memo(1) # 更新mad-mome的地址线,参数为真则显示 self.gui.data_line(f"mco-r{reg}") # 更新数据线 self.alu.show_alu_line() # 更新alu的数据线 self.entry_replace(eval(f"self.alu.r{reg}"), self.memo.mco.get()) # 更新显示R2中的值 canvas.update() if sing_num == 4: self.textbox.send_msg(f"======Step{sing_num + 1}======") self.reg_update() self.sing.clo_mark(sing_num) # 显示节拍 cpu_data.SigObj['->ALU'][1] = True self.sing.show_singe() # 显示控制器信号 cpu_data.SigObj['->ALU'][1] = True self.gui.singe_ctrl_line() # 显示控制线 self.gui.addr_line() # 更新地址线 self.gui.data_line() # 更新数据线 self.memo.mad_to_memo() # 更新mad-mome的地址线,参数为真则显示 self.alu.show_alu_line() # 更新alu的数据线 self.gen_opera(f"R{reg - 1}", f"R{reg}", "x", sing_num) canvas.update() if sing_num == 5: self.textbox.send_msg(f"======Step{sing_num + 1}======") self.reg_update() self.sing.clo_mark(sing_num) # 显示节拍 self.sing.show_singe() # 显示控制器信号 self.gui.singe_ctrl_line() # 显示控制线 self.gui.addr_line() # 更新地址线 self.gui.data_line() # 更新数据线 self.memo.mad_to_memo() # 更新mad-mome的地址线,参数为真则显示 self.alu.show_alu_line() # 更新alu的数据线 self.gen_opera(f"R{reg - 1}", f"R{reg}", "x", sing_num) canvas.update() def SimDiv(self, sing_num, reg_code): """除法指令""" self.textbox.send_instr(f"除法") register, data_line = self.register_mapping[reg_code] mco, reg = data_line.split("-") reg = int(reg[-1]) + 1 if sing_num == 3: self.textbox.send_msg(f"======Step{sing_num + 1}======") self.reg_update() self.sing.clo_mark(sing_num) # 显示节拍 cpu_data.SigObj['->Memory'][1] = True self.sing.show_singe() # 显示控制器信号 cpu_data.SigObj[f'Mcontent->R{reg}'][1] = True cpu_data.SigObj[f'->R{reg}'][1] = True self.gui.singe_ctrl_line() # 显示控制线 self.gui.addr_line() # 更新地址线 self.memo.mad_to_memo(1) # 更新mad-mome的地址线,参数为真则显示 self.gui.data_line(f"mco-r{reg}") # 更新数据线 self.alu.show_alu_line() # 更新alu的数据线 self.entry_replace(eval(f"self.alu.r{reg}"), self.memo.mco.get()) # 更新显示R2中的值 canvas.update() if sing_num == 4: self.textbox.send_msg(f"======Step{sing_num + 1}======") self.reg_update() self.sing.clo_mark(sing_num) # 显示节拍 cpu_data.SigObj['->ALU'][1] = True self.sing.show_singe() # 显示控制器信号 cpu_data.SigObj['->ALU'][1] = True self.gui.singe_ctrl_line() # 显示控制线 self.gui.addr_line() # 更新地址线 self.gui.data_line() # 更新数据线 self.memo.mad_to_memo() # 更新mad-mome的地址线,参数为真则显示 self.alu.show_alu_line() # 更新alu的数据线 self.gen_opera(f"R{reg - 1}", f"R{reg}", "÷", sing_num) canvas.update() if sing_num == 5: self.textbox.send_msg(f"======Step{sing_num + 1}======") self.reg_update() self.sing.clo_mark(sing_num) # 显示节拍 self.sing.show_singe() # 显示控制器信号 self.gui.singe_ctrl_line() # 显示控制线 self.gui.addr_line() # 更新地址线 self.gui.data_line() # 更新数据线 self.memo.mad_to_memo() # 更新mad-mome的地址线,参数为真则显示 self.alu.show_alu_line() # 更新alu的数据线0. self.gen_opera(f"R{reg - 1}", f"R{reg}", "÷", sing_num) canvas.update() def SimPrint(self, sing_num): self.textbox.send_instr("打印") if sing_num == 3: self.textbox.send_msg(f"======Step{sing_num + 1}======") self.reg_update() self.sing.clo_mark(sing_num) # 显示节拍 cpu_data.SigObj['->Memory'][1] = True self.sing.show_singe() # 显示控制器信号 cpu_data.SigObj['->R1'][1] = True cpu_data.SigObj['Mcontent->R1'][1] = True self.gui.singe_ctrl_line() # 显示控制线 self.gui.addr_line() # 更新地址线 self.memo.mad_to_memo(1) # 更新mad-mome的地址线,参数为真则显示 self.gui.data_line("mco-r1") # 更新数据线 self.alu.show_alu_line() # 更新alu的数据线 self.entry_replace(self.alu.r1, self.memo.mco.get()) # 更新显示R2中的值 canvas.update() if sing_num == 4: self.textbox.send_msg(f"======Step{sing_num + 1}======") self.reg_update() self.sing.clo_mark(sing_num) # 显示节拍 cpu_data.SigObj['->R1'][1] = True # 更新R1的值 self.sing.show_singe() # 显示控制器信号 cpu_data.SigObj['->R1'][1] = True # 更新R1的值 self.gui.singe_ctrl_line() # 显示控制线 self.gui.addr_line() # 更新地址线 self.gui.data_line() # 更新数据线 self.memo.mad_to_memo() # 更新mad-mome的地址线,参数为真则显示 self.alu.show_alu_line() # 更新alu的数据线 val = self.alu.r1.get() self.textbox.send_msg(f"打印输出:\n'{val}'") binary_string = bin_to_dec(val) self.textbox.send_msg(f"10进制转换:'{binary_string}'") canvas.update() # print(self.alu.r1.get()) def SimStop(self, sing_num): self.textbox.send_instr("停机") if sing_num == 3: self.textbox.send_msg(f"======Step{sing_num + 1}======") self.reg_update() self.sing.clo_mark(sing_num) # 显示节拍 cpu_data.SigObj['->PC+1'][1] = True # 更新PC+1的值 self.sing.show_singe() # 显示控制器信号 cpu_data.SigObj['->PC+1'][1] = True # 更新PC+1的值 self.gui.singe_ctrl_line() # 显示控制线 self.gui.addr_line() # 更新地址线 self.gui.data_line() # 更新数据线 self.memo.mad_to_memo() # 更新mad-mome的地址线,参数为真则显示 self.alu.show_alu_line() # 更新alu的数据线 self.sing.pc_value = f"{0:016b}" # PC 置0 self.sing.pc_reg_value() self.textbox.send_msg("PC = 0") self.sing.pc_reg.config(bg=RED) self.sing.ins.config(bg=RED) canvas.update() if sing_num == 4: self.textbox.send_msg(f"======Step{sing_num + 1}======") self.reg_update() self.sing.clo_mark() # 显示节拍 self.sing.show_singe() # 显示控制器信号 self.gui.singe_ctrl_line() # 显示控制线 self.gui.addr_line() # 更新地址线 self.gui.data_line() # 更新数据线 self.memo.mad_to_memo() # 更新mad-mome的地址线,参数为真则显示 self.alu.show_alu_line() # 更新alu的数据线 self.textbox.send_msg("系统停机") canvas.update() def SimGoto(self, sing_num): self.textbox.send_instr("跳转") if sing_num == 3: self.textbox.send_msg(f"======Step{sing_num + 1}======") self.reg_update() self.sing.clo_mark(sing_num) # 显示节拍 cpu_data.SigObj['->Memory'][1] = True # 更新Memory的值 self.sing.show_singe() # 显示控制器信号 cpu_data.SigObj['PC->Maddr'][1] = True cpu_data.SigObj['Mcontent->PC'][1] = True cpu_data.SigObj["->PC+1"][1] = True self.gui.singe_ctrl_line() # 显示控制线 self.gui.addr_line() # 更新地址线 self.memo.mad_to_memo(1) # 更新mad-mome的地址线,参数为真则显示 self.gui.data_line("mco-pc") # 更新数据线 self.alu.show_alu_line() # 更新alu的数据线 mco_value = self.memo.mco.get() self.entry_replace(self.sing.pc_reg, mco_value) self.memo.mco.config(bg=RED) self.sing.pc_reg.config(bg=RED) canvas.update() def lw_(self, one_inscode=None, is_meter=None, step=None): ''' 取指令 :param one_inscode: 执行模式,分单指令自动执行,和分节拍手动执行 :param is_meter: 控制是否为分节拍模式 True则表示分节拍执行 :param step: 节拍步骤 :return: 停机指令 ''' self.alu.show_alu_line(None) # 更新ALU的数据线 if step <= 2: # 前三节拍都更新取指令,后面的节拍更新其他指令 self.textbox.send_instr("取指令") if step == 0: self.textbox.send_msg(f"\n\n\n======Step{step + 1}======") self.reg_update() # 更新各个寄存器颜色为白色 self.sing.clo_mark(step) # 显示节拍 cpu_data.SigObj['->Memory'][1] = True # 更新Memory的值 self.sing.show_singe() # 显示控制器信号 cpu_data.SigObj['PC->Maddr'][1] = True # 更新PC->Maddr的值 self.gui.singe_ctrl_line() # 显示信号控制线 cpu_data.SigObj['PC->Maddr'][1] = True # 更新PC->Maddr的值 self.gui.addr_line() # 显示地址线 self.gui.data_line() # 更新数据线 self.memo.mad_to_memo() # 更新mad-mome的地址线 self.alu.alu_operation() # 更新alu的符号 canvas.update() # 刷新显示 maddr = self.sing.pc_reg.get() # 获取pc寄存器的值 self.sing.pc_reg.config(bg=RED) # 更新PC寄存器的背景显示 self.memo.show_maddr(maddr, 1) # 更新maddr的显示和值 self.alu.show_alu_line(None) # 显示ALU的数据线 if step == 1: self.textbox.send_msg(f"======Step{step + 1}======") self.reg_update() # 更新各个寄存器颜色为白色 self.sing.clo_mark(step) # 显示节拍 cpu_data.SigObj['->IR'][1] = True self.sing.show_singe() # 显示控制器信号 cpu_data.SigObj['->IR'][1] = True self.gui.singe_ctrl_line() # 显示控制线 self.gui.addr_line() # 更新显示地址线 self.memo.mad_to_memo(1) # 更新mad-mome的地址线,参数为真则显示 self.gui.data_line("mco-ir") # 更新数据线 data = self.memo.mco.get() # 取得mco中的值 self.sing.ir_value = data # 更新 ir的值 self.sing.ir_reg_value() # 显示IR self.sing.ir_reg.config(bg=RED) # 更新IR的颜色 canvas.update() # 刷新显示 if step >= 2: global inscode if step == 2: self.textbox.send_msg(f"======Step{step + 1}======") self.reg_update() # 更新各个寄存器颜色为白色 self.sing.clo_mark(step) # 显示节拍 cpu_data.SigObj['->PC+1'][1] = True # 更新PC+1的值 cpu_data.SigObj['->IR'][1] = True # 更新IR的值 self.sing.show_singe() # 显示控制器信号 cpu_data.SigObj['->PC+1'][1] = True # 更新PC+1的值 cpu_data.SigObj['->IR'][1] = True # 更新IR的值 self.gui.singe_ctrl_line() # 显示控制线 cpu_data.SigObj['IR->Maddr'][1] = True # 更新IR->Maddr的值 self.gui.addr_line() # 更新地址线 self.gui.data_line() # 更新数据线 self.memo.mad_to_memo() # 更新mad-mome的地址线,参数为真则显示 self.sing.pc_value = self.sing.pc_reg.get() self.sing.pc_value = self.pc_add_one(self.sing.pc_value) # pc+1 self.sing.pc_reg_value() # 更新PC显示 self.sing.pc_reg.config(bg=RED) # 更新PC背景 inscode, addr = self.sing.ir_value[:6], self.sing.ir_value[6:] # 拆分操作码和指令地址 self.sing.ir_reg.config(bg=RED) # 更新IR背景 self.entry_replace(self.sing.ins, inscode) # 更新 inscode值 self.sing.ins.config(bg=RED) # 更新insCode背景 self.memo.mad_value = f"{int(addr, 2):016b}" # 更新 maddr值 self.memo.show_maddr(self.memo.mad_value, 1) # 显示maddr值 canvas.update() # 刷新显示 if is_meter is None: time.sleep(self.wait_time) if one_inscode is not None: # 如果有单指令,直接执行指令 self.instruct(one_inscode) else: # 如果没有单指令,执行读取到的指令 if is_meter: # 如果是分节拍执行。 stop_tag = self.instruct(inscode, step) # 加入步骤参数 return stop_tag else: # 不分节拍执行 stop_tag = self.instruct(inscode) # 不加步骤参数 if stop_tag == "stop": return "stop" if is_meter is None and step < 2: # 不分节拍执行时,增加等待时间 time.sleep(self.wait_time) def instruct(self, inscode, step=None): com_code = inscode[2:] reg_code = inscode[:2] if com_code == '0001': # 取数指令 if step is not None: # 当有手动指令时执行手动指令 self.SimGet(step, reg_code) if step >= 3: return "end" else: for i in range(3, 4): self.SimGet(i, reg_code) time.sleep(self.wait_time) if com_code == "0010": # 存数指令 if step is not None: self.SimPut(step, reg_code) if step >= 3: return "end" else: for i in range(3, 4): self.SimPut(i, reg_code) time.sleep(self.wait_time) if com_code == "0011": if reg_code != "11": # 加法指令 if step is not None: self.SimAddr(step, reg_code) if step >= 5: return "end" else: for i in range(3, 6): self.SimAddr(i, reg_code) time.sleep(self.wait_time) else: self.textbox.send_msg("寄存器超限!!!", fg="#FF0000") if com_code == "0111": # 减法指令 if reg_code != "11": # 加法指令 if step is not None: self.SimMinus(step, reg_code) if step >= 5: return "end" else: for i in range(3, 6): self.SimMinus(i, reg_code) time.sleep(self.wait_time) else: self.textbox.send_msg("寄存器超限!!!", fg="#FF0000") if com_code == "0100": # 乘法指令 if reg_code != "11": if step is not None: self.SimProduct(step, reg_code) if step >= 5: return "end" else: for i in range(3, 6): self.SimProduct(i, reg_code) time.sleep(self.wait_time) else: self.textbox.send_msg("寄存器超限!!!", fg="#FF0000") if com_code == "1000": # 除法指令 if reg_code != "11": if step is not None: self.SimDiv(step, reg_code) if step >= 5: return "end" else: for i in range(3, 6): self.SimDiv(i, reg_code) time.sleep(self.wait_time) else: self.textbox.send_msg("寄存器超限!!!", fg="#FF0000") if com_code == "1001": # 跳转指令 if step is not None: self.SimGoto(step) if step >= 3: return "end" else: for i in range(3, 4): self.SimGoto(i) time.sleep(self.wait_time) if com_code == "0101": # 打印指令 if step is not None: self.SimPrint(step) if step >= 4: return "end" else: for i in range(3, 5): self.SimPrint(i) time.sleep(self.wait_time) if com_code == "0110": # 停机指令 if step is not None: self.SimStop(step) if step >= 4: return "stop" else: for i in range(3, 5): self.SimStop(i) time.sleep(self.wait_time) if i >= 4: return "stop" # 停机标志 def exe_one_instruct(self, inscode): """单指令执行""" for i in range(3): self.lw_(inscode, step=i) def exec_auto(self): # 自动执行储存程序 while True: instr_stute = None # 指令状态为"stop"时退出循环。 if self.ctrl_stop: break for i in range(3): instr_stute = self.lw_(step=i) if instr_stute == "stop": break def exec_next(self): # 执行下一步 statu = self.lw_(is_meter=True, step=self.manual_opera_step) # 执行指令 self.manual_opera_step += 1 if statu == "end" or self.manual_opera_step > 5: # 指令结束或者节拍序号大于5都将节拍重置鱼0 self.manual_opera_step = 0 elif statu == "stop": # 若上一条指令返回停机指令,则disable下一步按键 self.next_button.config(state=tk.DISABLED) if self.manual_opera_step > 0: self.prev_button.config(state=tk.NORMAL) def prev(self): # 执行上一步 self.next_button.config(state=tk.NORMAL) if self.manual_opera_step > 0: self.manual_opera_step -= 1 self.lw_(is_meter=True, step=self.manual_opera_step) else: self.prev_button.config(state=tk.DISABLED) def exec_manual_operation(self): '''分节拍顺序执行''' self.lw_(is_meter=True, step=self.manual_opera_step) def main(): SimMem[0] = f"0000010000001010" # SimMem[10] => r1 SimMem[1] = f"0000110000001011" # r1+SimMem[11] => r1 SimMem[2] = f"0001000000001100" # r1*SimMem[12] => r1 SimMem[3] = f"0010000000001101" # r1//SimMem[13] => r1 SimMem[4] = f"0001110000001110" # r1-SimMem[14] => r1 SimMem[5] = f"0000100000001111" # 存数到15地址 r1 => SimMem[15] SimMem[6] = f"0001010000001111" # 打印 SimMem[15] SimMem[7] = f"0001100000000000" # 停机 SimMem[10] = dec_to_bin(9) # 10 地址数据 SimMem[11] = dec_to_bin(11) # 11 地址数据 SimMem[12] = dec_to_bin(5) # 12 地址数据 SimMem[13] = dec_to_bin(10) # 13 号位的值 SimMem[14] = dec_to_bin(11) # 14 地址数据 exe = ExecInstructWithText() root.mainloop() if __name__ == '__main__': main()