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

7 months ago
# -*- 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()