| 1.假设最复杂的一条指令所用的组合逻辑分成6块,依次为A~F,其延迟分别为80ps、30ps、60ps、50ps、70ps、10ps,最后一个寄存器延迟为20ps。在这些组合逻辑块之间插入必要的流水线寄存器就可实现相应的指令流水线。理想情况下,以下各种方式所得到的时钟周期、指令吞吐率和指令执行时间各是多少?应该在哪里插入流水线寄存器?(假定插入的流水线寄存器的延时为20ps)
A. 插入一个流水线寄存器,得到一个两级流水线
B.
插入两个流水线寄存器,得到一个三级流水线
C.
插入三个流水线寄存器,得到一个四级流水线
D.
吞吐量最大的流水线
| 简要分析:
A.两级流水线的平衡点在C和D之间,其前面一个流水段的组合逻辑延时为80+30+60=170ps,后面一个流水段的组合逻辑延时为50+70+10=130ps。这样每个流水段都以最长延时调整为170+20=190ps,故时钟周期为190ps,指令吞吐率为1/190ps=5.26GOPS,每个指令的执行时间为2x190=380ps。
B.两个流水线寄存器分别插在B和C、D和E之间,这样第一个流水段的组合逻辑延时为80+30=110ps,中间第二段的时延为60+50=110ps,最后一个段延时为70+10=80ps。这样每个流水段都以最长延时调整为110+20=130ps,故时钟周期为130ps,指令吞吐率为1/130ps=7.69GOPS,每个指令的执行时间为3x130=390ps。
C.三个流水线寄存器分别插在A和B、C和D、D和E之间,这样第一个流水段的组合逻辑延时为80ps,第二段时延为30+60=90ps,第三段时延为50ps,最后一段延时为70+10=80ps。这样每个流水段都以最长延时调整为90+20=110ps,故时钟周期为110ps,指令吞吐率为1/110ps=9.09GOPS,每个指令的执行时间为4x110=440ps。
D.因为所有组合逻辑块中最长延时为80ps,所以,达到最大可能吞吐率的划分应该是以一个流水段延时为80ps+20ps来进行,因此,至少按五段来划分,分别把流水线寄存器插入在A和B、B和C、C和D、D和E之间,这样第一段的组合逻辑延时为80ps,第二段为30ps,第三段为60ps,第四段为50ps,最后一段为70+10=80ps。这样每个流水段都以最长延时调整为80+20=100ps,故时钟周期为100ps,指令吞吐率为1/100ps=10GOPS,每个指令的执行时间为5x100=500ps。
|
2.下面有关指令流水线的叙述中,错误的是(
)。
A.
流水段个数按同一个流水线中最复杂指令的功能来确定
B.
每个流水段的时间相同,等于一个CPU时钟的宽度
C.
每个时钟都会有一条指令执行完
D.
流水线方式不能使一条指令的执行时间缩短,但能使整个程序的执行时间缩短
|
简要分析:
选项A:流水线方式下,一条指令的执行过程被分成了若干个操作子过程。由于每条指令所完成的功能不同,所包含的操作过程就不同。有的指令完成寄存器的内容的传送;有的是简单的加/减运算;还有的是复杂的乘/除运算。这些操作所花的时间相差很大,所以,这些指令如果都在同一个流水线中执行的话,就必须按最复杂的指令来设计流水线的流水段个数。
选项B:流水线中指令执行的每个子过程由独立的功能部件来完成,以最复杂的子过程所花时间为准设计时钟周期。这样,使得每个流水段的时间都等于CPU时钟的宽度。
选项C:理想情况下,经过若干时钟周期后,流水线能在每个周期内执行完一条指令。但是,当程序中出现以下情况时,流水线被破坏:(1)
当有多条指令的不同阶段都要用到同一个功能部件时(资源冲突),后面指令要延时执行;(2)当程序的执行流程发生改变时(控制相关),原来按顺序取出的指令无效;(3)当后面指令的操作数是前面指令的运行结果时(数据相关),后面指令要延时执行。所以,并不是任何时候每个时钟内都会有一条指令执行完。
选项D:对于每条指令来说,它在流水线中还是要经过若干子过程才能完成,所以一条指令的执行时间并没有变短。但整个程序的执行时间大大缩短了。
综上所述,错误的应该是C。
|
3.下面是一段指令序列:
add $t1, $s1, $s0
sub
$t2, $s0, $s3
add
$t1, $t1, $t2
以上指令序列中,哪一条指令发生数据相关?假定采用"取指、译码/取数、执行、访存、写回"这种五段流水线方式,那么不用"转发"技术的话,需要在发生数据相关的指令前加入几条nop指令才能使这段程序避免数据冒险?如果采用"转发"是否可以完全解决数据冒险?不行的话,需要在发生数据相关的指令前加入几条nop指令才能使这段程序不发生数据冒险?
|
参考答案:第三条指令发生了数据相关,不进行“转发”处理的话,需要在第三条指令前加入三条nop指令才能避免数据冒险。通过“转发”可以完全避免数据冒险,无需加入nop指令。 |
|
简要分析:
因为第一条和第二条指令会更新第三条指令用到的寄存器的值,有可能导致第三条指令取操作数时得到的是更新前的数据,这样第三条指令就不能正确执行,所以第三条指令发生数据相关。
不进行“转发”的话,就只能通过在第三条指令前加nop指令来延迟第三条指令的执行。因为只有第二条指令把数据写回到$t2,第三条指令才能从$t2取到正确的值,所以,第二条指令的“回写”流水段后面是第三条指令的“译码/取数”流水段,为此,在第二和第三条指令之间必须插入三条nop指令。
采用“转发”技术,上述程序段可以完全避免数据冒险。只要把第一条指令“访存”段结束时在流水线寄存器中的$t1的值和第二条指令“执行”段结束时在流水线寄存器中的$t2
的值同时“转发”到第三条指令的“执行”段ALU的两个输入端,这样,在ALU中运算的两个操作数都是正确的值。不会发生数据冒险。
|
4.下面是一段指令序列:
loop:
add $t1,$s3,$s3
add
$t1,$t1,$t1
add
$t1, $t1,$s6
lw
$t0,0($t1)
bne
$t0,$s5,Exit
add
$s3,$s3,$s4
j
Loop
Exit:
分析以上指令序列,要求:
(1)指出哪些指令产生数据相关?哪些指令发生控制相关?
(2)如果不用“转发”或“分支预测”来进行冒险处理,而是简单地通过加入nop指令来避免冒险,那么加入nop指令后的指令序列是怎样的?
(3)假定采用“转发”进行数据冒险处理,并在必要时在相应阶段加入“气泡”来阻塞流水线,使流水线停顿一个周期,那么,在哪条指令的哪个阶段需要加入“气泡”呢?
|
参考答案:
(1)发生数据相关的是第2、3、4、5行指令,发生控制相关的是第5行指令。
(2)如果不用“转发”或“分支预测”来进行冒险处理,而是简单地通过加入nop指令来避免冒险,那么加入nop指令后的指令序列如下:
loop: add $t1,$s3,$s3
nop
nop
nop
add $t1,$t1,$t1
nop
nop
nop
add $t1, $t1,$s6
nop
nop
nop
lw $t0,0($t1)
nop
nop
nop
bne $t0,$s5,Exit
nop
nop
nop
add $s3,$s3,$s4
j Loop
Exit:
以上每个数据相关指令前加3条nop指令,使得所用数据写回到寄存器堆后再由数据相关指令取出;在控制相关指令(即分支指令)后面也需要加3条nop指令,使得分支指令在“访存”流水段把新的PC值写到PC后再取出下条指令执行。所以,共需多加15条指令,大大降低指令执行效率。
(3)大多数情况下的数据冒险都可以通过“转发”来解决,如:第2、3、4条数据相关指令引起的数据冒险。但遇到取数指令后面一条指令马上就要用到取出的数据时,就不能用“转发”完全解决问题了,因为数据只有在“访存”阶段才能得到,来不及在下一条指令取数时就得到(如:第4条取数指令和第5条分支指令),这样必须在下一条指令的译码/取数阶段插入一个“气泡”,使流水线停顿一个时钟,等到上条指令在“访存”阶段取得数据后“转发”到下条指令。
|
|