您必须分解每条指令的作用。
例如,使用MIPS 绿卡。
所有 R-Type 指令共享某些控制信号,这些控制信号遵循它们的基本指令格式——例如它们的源/读取rs
&rt
和目标/写入到rd
,这意味着:
RegDest
是真的(rd
是写的,不是rt
)
RegWrite
是真的(写了一些 reg)
ALUSrc
为真(第二个 alu 输入来自寄存器,而不是立即数)
I-Type 指令都有一定的共享控制信号模式:
RegDest
为假(rt
已写,rd
I-Types 没有)
RegWrite
是真的(写了一些 reg)
ALUSrc
为假(第二个 alu 输入来自立即数,而不是来自寄存器)
除了加载和存储之外,没有指令触及内存,因此MemRead
对于MemWrite
所有其他指令都是错误的。 MemRead
仅适用于加载,仅MemWrite
适用于商店。
MemtoReg
对于加载结果为真,因为结果来自内存,但对于大多数其他指令为假,因为结果(如果有)来自 ALU。
对于许多指令,其中一些控制信号无关紧要,因此可以归类为“不关心”而不是真或假(硬件都可以)。例如,由于存储指令将数据发送到内存,因此它不会更新 CPU 寄存器 - 因此,MemToReg
对于那个无关紧要,因为无论如何都不会写入 reg (对于分支也是如此,因为它们也不写入 /更新寄存器)。
何时RegWrite
为假,则MemtoReg
无关紧要(不在乎)。
与其他大多数不同,ALUOp 是一个大于单个布尔值的控制信号。所以 ALU 需要知道要执行什么操作,对于 R-Type 指令,这来自funct
指令字段,而对于 I-Type 指令,这来自操作码字段本身。
对于加载和存储,ALU(在单周期 MIPS CPU 中)用于执行寻址模式计算,因此应该告诉 ALU 添加。
对于分支(在单周期 MIPS CPU 中),应该告诉 ALU 进行减法(即比较)。
高级:硬件是所有指令所需的所有组件的结合。控制信号用于为正在执行的任何单个指令“激活”适当的硬件组件——但是,诀窍是这些信号实际上并没有激活组件,而是选择在之后是接受还是忽略它们的输出给定正在执行的指令,它们分别计算出有用或无用的东西。
这有点麻烦,但是所有需要的硬件组件(对于每条可能的指令)的结合一直坐在那里做某事(除非使用非常先进的节能电路)。因此,控制信号所做的——而不是关闭对当前指令没有贡献的组件——只是简单地忽略它们的计算结果,而偏向于相关的东西。
例如,有效地,立即数硬件在每个指令的每个周期上对I-Type 16 位立即数进行符号扩展,但该计算值仅在指令实际上是 I-Type 时使用,否则由于控制而被忽略信号(ALUSrc)。
虽然我们可能认为这是低效的,但有一个值得赞赏的并行性能,即提前计算不必要的东西,以防万一需要它们,只有在以后知道更多时才抑制它们。