You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

945 lines
41 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# -*- 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("<Button-1>", self.on_left_click)
# root_right.bind("<Button-1>", 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()