在采用“取指、译码/取数、执行、访存、写回”5段流水线的 RISC 处理器中,执行如下指令序列 (第一列为指令序号),其中s0 、s1 、s2 、s3和t2 表示寄存器编号。
I1 add s2,s1,s0 //R[s2]←R[s1]+R[s0]
I2 load s3,0(s2) //R[s3]←M[R[s2]+0]
I3 beq t2,s3,L1 //if R[t2]=R[s3]jump to L1
I4 addi t2,t2, 20 //R[t2]←R[t2]+20 I5 L1:
若采用转发(旁路)技术处理数据冒险,采用硬件阻塞方式处理控制冒险,则在 I1~I4 执行过程中,发生 流水线阻塞的指令有()。
A. 仅 I3
B. 仅 I2 、I4
C. 仅 I3 、I4
D. 仅 I2 、I3 、I4
20. 某存储器总线宽度为64 位,总线时钟频率为 1 GHz, 在总线上传输一个数据或地址需要一个的时钟 周期,不支持突发传送方式,若通过该总线连接 CPU 和主存,主存每次准备一个64位数据需要6ns, 主存块大小为32B, 则读取一个主存块需要的时间为()。
A.8ns
B.11ns
C.26ns
D.32ns
[tag_link]
正确答案:C
在以下指令序列中: I1 :写寄存器 R[s2] I2 :使用 R[s2] 计算访存地址 I3 :使用 R[s3] 进行比较跳转 I4 :紧跟在 beq 指令之后执行 I2 与 I1 之间:写后读数据冒险(RAW Hazard) 指令 I1 将结果写入寄存器 R[s2] ,但这个值直到 I1 的 写回(WB)阶段 才会更新。而 I2 在其 执行(EX)阶段 就需要用到 R[s2] 来计算访存地址,因此存在写后读的数据冒险。幸运的是,I1 在 EX阶段末尾 就已生成结果并存储在 EX→M 流水段寄存器中。此时如果使用 旁路转发 ,可以直接将这个值从流水段寄存器中转发到 I2 的 ALU 输入端,避免等待 WB 阶段,从而解决了这个 RAW 冒险。I3 与 I2 之间: 装入-使用 数据冒险(Load-Use Hazard) I2 是一条 load 指令,它需要从内存中将数据装入寄存器 R[s3] 。而 I3 在它的 EX 阶段就要用到 R[s3] 的值。如果像前面那样尝试用旁路技术从 I2 的 EX→M 寄存器转发数据,会失败——因为此时的数据尚未从内存中读出。只有等到 I2 的 访存(M)阶段结束 ,数据才真正从内存中取回,存放在 M→WB 流水段寄存器。因此, 仅靠转发线路无法解决装入-使用冒险 。需要采取的办法是:对 I3 硬件阻塞一个周期 ,等待 I2 的 M 阶段完成,然后通过转发将 R[s3] 的新值从 M→WB 段寄存器送入 I3 的 ALU,以确保其操作正确。I4 与 I3 之间:控制冒险(Control Hazard) I3 是一条 beq 分支指令。该指令在 EX 阶段比较寄存器值,在 M 阶段才判断跳转是否成立 并更新 PC(程序计数器)。因此,在得知是否跳转前, I4 的取指(IF)阶段必须等待 I3 的 M 阶段完成 。这就导致 I4 的执行被 阻塞 3 个时钟周期 ,以确保其是否被执行是基于正确的控制流判断。最终,系统采用 硬件阻塞机制 来处理上述数据和控制冒险,下图展示了指令执行过程中各阶段的具体安排: