使用NOP而不是停顿有什么不同。在流水线操作的情况下,两者都碰巧执行相同的任务。我不明白
我觉得你的术语很混乱。
处理器将一个停顿注入管道以解决数据危险(处理指令所需的数据尚不可用的情况.NOP
只是一个没有副作用的指令。
回想一下5管道阶段classic RISC pipeline:
考虑代码段:
add $t0, $t1, $t1
sub $t2, $t0, $t0
从这里可以看出,第二条指令依赖于第一条指令的结果。这是一个data hazard:Read After Write(RAW);一个真正的依赖。
sub
在其EX阶段需要add
的值,但add
将仅处于其MEM阶段 - 在WB阶段之前该值将不可用:
+------------------------------+----+----+----+-----+----+---+---+---+---+
| | CPU Cycles |
+------------------------------+----+----+----+-----+----+---+---+---+---+
| Instruction | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
+------------------------------------------------------------------------+
| 0 | add $t0, $t1, $t1 | IF | ID | EX | MEM | WB | | | | |
| 1 | sub $t2, $t0, $t0 | | IF | ID | EX | | | | | |
+---------+--------------------+----+----+----+-----+----+---+---+---+---+
One solution这个问题是处理器插入停顿或冒泡管道直到数据可用。
+------------------------------+----+----+----+-----+----+----+-----+---+----+
| | CPU Cycles |
+------------------------------+----+----+----+-----+----+----+-----+----+---+
| Instruction | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
+----------------------------------------------------------------------------+
| 0 | add $t0, $t1, $t1 | IF | ID | EX | MEM | WB | | | | |
| 1 | sub $t2, $t0, $t0 | | IF | ID | S | S | EX | MEM | WB | |
+----------+-------------------+----+----+----+-----+----+---+---+---+-------+
NOP
是一种什么都不做的指令(没有副作用)。 MIPS汇编程序通常支持nop
指令,但在MIPS this is equivalent to sll $zero $zero 0
中。
该指令将占用管道的所有5个阶段。它最常用于填充跳跃或分支的branch delay slot,当没有其他任何有用的东西可以在那个插槽中完成。
j label
nop # nothing useful to put here
如果您使用的是MIPS仿真器,则可能需要启用分支延迟时隙仿真才能看到此情况。 (例如,在spim
中使用-delayed_branches
参数)