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