一、表驱动控制:SimInstrCtrl 控制信号总表
数据结构
SimInstrCtrl:列表,每个元素为 [opcode, ClockSeq, BasicSig]
opcode:指令操作码,标识当前是哪条指令
ClockSeq:节拍号,标识指令执行到第几个节拍
BasicSig:该指令在该节拍要发出的控制信号串
公共取指阶段
opcode = "000000" 代表公共取指阶段
所有指令前 2 个节拍共用这一组控制信号
节拍 3 执行 PC+1
运行逻辑
按节拍遍历表,匹配「当前 opcode + 当前节拍」取出 BasicSig
信号串用于高亮对应数据线 / 控制线(传给绘图高亮接口)
识别带 -> 的传输信号,修改寄存器 / 内存的值
设计意义
把「指令 × 节拍 → 控制信号」集中成一张表,不再散落各函数
新增指令只需补表行,执行逻辑基本不动
二、变量约定(与作业保持一致)
控制与状态变量
self.SimInstrCtrl:控制信号总表
self.ClockSeq:当前节拍号
self.current_opcode:当前指令操作码
CPU 寄存器
self.pc:程序计数器
self.ir:指令寄存器
self.R1、self.R2、self.R3、self.R4:通用寄存器
存储与显示
self.SimMem:内存字典 {addr: bin16str}
self.highlight_sig(sig):工程里已有的高亮函数,传入信号串,高亮对应连线
三、指令集(X5 版本)
公共与数据传送
000000:取指(公共)
000001:LOAD,内存 → R1
000010:STORE,R1 → 内存
运算
000011:ADD,内存取出到 R2,R1 + R2 → R1
000100:MUL,内存取出到 R2,R1 * R2 → R1
四、函数实现
SimGet
函数:ExecInstructWithText.SimGet
输入:信号 sing_sum、指定的寄存器号 reg_code
输出:解析“取数指令”指令
功能:解析“取数指令”并将解析结果加入操作队列
lw_
函数:ExecInstructWithText.lw_
输入:one_inscode、is_meter、step
输出:取数指令至返回 IR、拆分指令码之前的 3 个节拍
功能:实现取数指令
exe_one_instruct
函数:ExecInstructWithText.exe_one_instruct
输入:inscode
输出:根据操作码解析指令,一次执行一个时钟刻
功能:根据操作码解析指令,一次执行一个时钟刻,并进行暂停
instruct
函数:ExecInstructWithText.instruct
输入:inscode
输出:无
功能:实现根据当前操作码自动执行指令
定位:指令分发器,每步判断指令类型并调用对应执行函数
五、编程实践
【编程6.12】编制程序:用函数仿真几条简单指令
围绕 SimInstrCtrl 表驱动,按节拍匹配信号并驱动界面高亮与数据变化
程序编写 1:SimGet
程序编写 2:lw_
【编程6.13】编制程序:程序中一条指令的执行
程序编写 1:exe_one_instruct,一次执行一个时钟刻并暂停
程序编写 2:SimGoto(见系统拓展一)
程序编写 3:instruct,按当前操作码自动执行指令
程序编写 4:SimGet,将存储器的值取到指定寄存器
题目两大任务
任务(1):在 6.8 版本加跳转指令 001001(SimGoto),并写含跳转的机器码程序跑通
任务(2):在 6.13 表驱动版本新增指令,如支持 R3、R4 读写并观察效果
六、系统拓展一:跳转指令 001001 与 SimGoto()
两件大事
用地址码去内存读出数字,放到 Mcontent
把 Mcontent 的数字送给 PC
PC 一改,下一条就跳去新地址执行
表驱动实现
在 SimInstrCtrl 中按 001001 + 各节拍补充控制信号行
信号串驱动“读内存 → 送 PC”的数据通路高亮与数据修改
函数定义
函数:ExecInstructWithText.SimGoto
输入:时钟信号 sing_num
输出:无
功能:实现自动执行跳转指令
七、系统拓展二:区分不同寄存器的操作
核心编码规则
inscode 前 2 位 = 选哪个寄存器
inscode[2:] 决定取数、存数还是加法
存数 / 取数指令(读写单个寄存器 R1/R2/R3/R4)
前两位编码:00 → R1
01 → R2
10 → R3
11 → R4
例:00 0001 → 前两位 00 为 R1,后段 0001 取数 → 给 R1 取数
例:10 0010 → 前两位 10 为 R3,后段 0010 存数 → 给 R3 存数
运算指令(两个寄存器送 ALU 相加)
前两位编码代表拿哪一对寄存器做加法
00:R1 + R2
01:R2 + R3
10:R3 + R4
11:不用(没有 R5 了)
例:10 0011 → R3 与 R4 相加,后段 0011 为加法
示例指令 10 0011 的完整 4 步顺序
先把内存读出的数据 Mcontent 送到 R4
把 R3、R4 里面的值送到 ALU
ALU 算 R3 + R4
算完的结果放回 R3
代码里怎么切分(重点)
inscode[:2]:取最前面 2 个 bit,用来选寄存器
inscode[2:]:第 3 位起判断动作(取数 / 存数 / 加法)
改 instruct 函数的大白话逻辑
① 切开头两位 reg_sel = inscode[:2],确定寄存器或寄存器对
② 切后面 op = inscode[2:],判断操作类型
③ 按两个结果跑控制信号、读写寄存器、启动 ALU