对于下面的RISC-V代码序列,我尝试识别无法通过数据转发解决的数据风险。有没有可能通过重新排序代码序列来克服这些风险?如果是,谁能展示新的序列?
下面是我的代码:
loop: slli s2, s1, 2
add s3, s2, s0
lw t0, 0(s3)
add t1, t2, t0
sw t1, 20(s3)
addi s1, s1, 1
beq s1, s5, loop发布于 2020-10-09 01:13:28
哪些数据风险可以通过转发解决,这完全取决于您正在使用的RISC-V架构的特定实现。我将假设Patterson & Hennessey教科书中提出的具有转发功能的传统5阶段RISC-V流水线,并尝试回答您的问题。
此流水线具有取指令(IF)、指令解码(ID)、执行(EX)、内存(MEM)和回写(WB)阶段。执行级计算寄存器-寄存器和寄存器-立即操作的值,并计算存储器( lw / sw )和控制转移(分支/跳转)操作的地址,而存储器级读取lw的数据并写入sw的数据。可以将数据从执行、存储器或写回级的末尾转发到用于后续指令的前一级的开头。
在您包含的代码片段中,会有5种数据风险:
(1) slli s2, s1, 2和add s3, s2, s0,用于寄存器s2
这里,寄存器s2由slli写入,由add读取。新值是在第一条指令的EX阶段结束时计算的,并且在下一条指令的EX阶段开始时需要,因此可以通过转发来解决。
(2)用于寄存器s3的add s3, s2, s0和lw t0, 0(s3)
这里,寄存器s3由add写入,由lw读取。新值是在第一条指令的EX阶段结束时计算的,并且在下一条指令的EX阶段开始时需要,因此可以通过转发来解决。
(3)用于寄存器t0的lw t0, 0(s3)和add t1, t2, t0
这里,寄存器t0由lw写入,由add读取。新值是在第一条指令的内存阶段结束时计算的,并且在下一条指令的EX阶段开始时需要,因此it canNOT可以通过转发来解析。
(4)用于寄存器t1的add t1, t2, t0和sw t1, 20(s3)
这里,寄存器t1由add写入,由sw读取。新值是在第一条指令的EX阶段结束时计算的,并且在下一条指令的MEM阶段开始时需要,因此可以通过转发来解决。
(5)用于寄存器s1的addi s1, s1, 1和beq s1, s5, loop
这里,寄存器s1由addi写入,由beq读取。新值在第一条指令的EX阶段结束时计算。通常,对于没有针对控制风险进行任何优化的RISC-V流水线,对于分支指令,在计算程序计数器+偏移量的同时,在EX期间比较寄存器以获得分支目的地。这里的控制风险是一个单独的问题,但数据风险可以通过转发来解决。
因此,在这5种危险中,只有一种是无法通过数据转发解决的。它可以通过指令重新排序来解决吗?是。看看addi s1, s1, 1吧。在addi之前,第一个slli之后的任何指令都不会读取或写入s1。如果我们移动该指令,那么结果代码如下所示:
loop: slli s2, s1, 2
add s3, s2, s0
lw t0, 0(s3)
addi s1, s1, 1
add t1, t2, t0
sw t1, 20(s3)
beq s1, s5, loop这样,当lw指令需要新值t0时,检索要写入t0的数据的add t1, t2, t0指令就已经完成了内存阶段。
通过这种重新排序,所有数据风险都可以通过转发来解决,并且不需要停顿。
https://stackoverflow.com/questions/64237292
复制相似问题