我真的搞不清楚气泡、停顿和重复解码/获取之间的区别。我的文本是Patterson文本,第3版。
例一:
add $3, $4, $6
sub $5, $3, $2
lw $7, 100($5)
add $8, $7, $2
解决方案:
(使用图像,因为很难输入图像中的内容)
在此示例/解决方案中,五个气泡被插入到第3条和第4条指令之间的新行中。
例二:
lw $4, 100($2)
sub $6, $4, $3
add $2, $3, $5
溶液:
在本例中,一个磁泡在时钟周期4中包裹第2条和第3条指令。在时钟周期4中,I2重复解码,I3重复读取。
例1和例2有什么区别?为什么例1中插入了一行气泡,而例2中插入了一个气泡并重复解码/获取?它们的功能相同吗?如果功能相同,这是例1的有效解决方案吗?
I1: IF ID EX MEM WB
I2: IF ID EX MEM WB
I3: IF ID EX MEM WB
I4: IF NOP ID EX MEM WB
这是否也是示例1的有效解决方案?
I1: IF ID EX MEM WB
I2: IF ID EX MEM WB
I3: IF ID EX MEM WB
I4: NOP IF ID EX MEM WB
这是示例2的有效解决方案吗?
I1: IF ID EX MEM WB
I2: IF NOP ID EX MEM WB
I3: NOP IF ID EX MEM WB
这是否也是示例2的有效解决方案?
I1: IF ID EX MEM WB
I2: IF ID ID EX MEM WB
I3: IF IF ID EX MEM WB
2条答案
按热度按时间h6my8fg21#
流水线中的气泡(有时用NOP表示)是暂停1个周期的结果。
气泡是指在查看流水线图时看到和谈论的一些东西,这些流水线图显示了指令如何通过流水线,以及它们在任何给定的周期中处于哪个阶段。气泡在流水线中传播,因此它在每个阶段都出现一次。(对于结构性危险,如指令获取与数据加载/存储竞争,气泡将在IF中开始,如第一个示例。)
停顿是单个阶段决定执行的操作,根据停顿的时间长短创建一个或多个气泡。
指令的一行气泡与行内的一个气泡
注意,他们为通过流水线所有5个阶段的一个气泡添加了一个垂直行。就好像你在程序中编写了一个NOP来填充加载延迟槽(如果你不能调度其他指令来填充它,那么在MIPS I R2000 / R3000上是必需的;在以后的MIPS中,伊萨保证硬件将为您暂停)。除了机器码中的真
nop
仍然被获取和解码。MIPS没有用于nop
的特殊操作码,您将一个写为add $zero, $zero, $zero
或等效物,没有要暂停的输入,并且$zero
的输出忽略写,总是读为零。垂直行表示指令,而不是时间。停顿意味着后面的指令(或它们的阶段)从更右边开始,而不是在当前指令到达该阶段后的周期中。
该图可以通过在加载后跳过指令IF阶段的一个时钟周期(列)来指示相同的时序。您可以在IF的 * 左侧 * 画一个气泡,在获取
lw
后的周期中IF通常会获取它的位置。**该图不是真实的CPU执行示例1代码的方式。**您的问题中没有包括标题,这可能解释了为什么他们会这样画。也许在开始指令之前留下一个间隙 * 会 * 解决问题。
运行该代码的CPU在获取并解码
lw
之后的指令之前,不会知道该指令是否依赖于结果,这就是CPU检查危险的地方。*add $8, $7, $2
到达ID后的周期是IF空闲或重新获取add
之后的指令的时间。示例2是更常见的绘图方式,显示了加载延迟(在MIPS II或更高版本上),其中加载结果直到延迟一个周期后才可用于转发,因此ID执行此操作并设置转发。在管道中不向前移动的指令会留下一个气泡,您可以在接下来的几条指令中看到:注意,EX没有出现在循环4中。MEM没有出现在循环5中。等等。这是气泡随时间推移通过管道移动。
驻留在
reg reg
(解码)中的同一条指令是由暂停创建的背压,用于打开该气泡。由于指令获取时的结构性危险而导致一行5个气泡
**在我的Patterson & Hennesy(第2版)中,图3.7有一行5个气泡,**但原因与示例1不同,它讨论的是没有L1 i/L1 d分离缓存的机器,或者没有缓存和单端口内存,因此有IM/DM(指令内存/数据内存阶段)。
图3.7结构性危险导致插入流水线气泡。结果是在时钟周期8期间没有指令完成,而指令3通常已经完成。(假设指令1不是加载或存储;否则指令3不能开始执行)。
其“代号”及管线图见图3. 9:由于结构性危险而暂停的流水线-用一个存储器端口加载。
图3.6显示了如果你没有停顿/气泡的冲突。在第二版的书中,他们实际上把第一和第四流水线阶段都标为MEM,而不是IF/MEM或IM/DM。
我不知道我那本教科书后面讲到数据冒险时,是否有你这样的图表,我没有再看下去,也许他们是在展示一个空闲周期如何使依赖性工作,然后会继续展示真正发生了什么,CPU必须获取并解码才能发现冒险。
另一个答案是,停顿会让控制信号不加改变地沿流水线向下传输,而不是插入NOP,但这听起来不对,也不切实际。
让
add $8, $7, $2
在$7
输入值错误的情况下通过管道似乎没有直接的危害;标量有序流水线没有WAW或WAR冒险,因此让它到达WB阶段并将错误值写入寄存器文件不会损害其它指令的正确性;正确的值将在下一个周期写入,此时指令再次通过流水线,此时值是正确的......除非在寄存器文件保存错误值时在该周期中发生中断!!否则,存在架构上可见的错误值。如果内存操作在MEM阶段运行,并且在寻址模式下可能会出现错误指针,这也会给内存操作带来问题。您可能会得到虚假的TLB未命中或页面错误,或者存储到错误的位置。
因此,检测到暂停的级很可能会复用一些控制位,以沿管道向下发送NOP,或者NOP/bubble有一条专用控制线来停用级。
7fhtutme2#
我知道这个问题很老了,但我希望这能有所帮助。停滞和冒泡在不同的上下文中使用。停滞表示保持寄存器具有相同的输入,并继续使用相同的输入进入下一阶段,这意味着没有输出或没有寄存器输入是不同的,而冒泡表示NOP指令,这将使寄存器输入为0(如果我没有错的话)。现在你可以通过下面的例子来理解泡沫和失速的区别。在跳转预测错误的分支情况下,您必须遵循您还不知道它们是否将被执行的指令。出于延迟和带宽的成本目的,暂停将使解码阶段保持暂停。而如果将进入气泡,则将回到获取和解码两个阶段。在分支被良好地选择并且被停止的情况下,则恢复将已经在解码阶段中,而如果被冒泡,结果将不得不从取指令重新开始。我认为差异也是成本的,在添加输入到寄存器。