computer-science - 序列重新排序以解决 RISC-V 汇编中的数据危害
问题描述
对于以下 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
解决方案
可以通过转发解决哪些数据危害完全取决于您使用的 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)add s3, s2, s0
和lw t0, 0(s3)
注册s3
在这里,寄存器s3
由 写入add
和读取lw
。新值是在第一条指令的 EX 阶段结束时计算的,并且在下一条指令的 EX 阶段开始时需要,因此可以通过转发来解决。
(3)lw t0, 0(s3)
和add t1, t2, t0
登记t0
在这里,寄存器t0
由 写入lw
和读取add
。新值是在第一条指令的 MEM 阶段结束时计算的,并且在下一条指令的 EX 阶段开始时需要,因此无法通过 forwarding 解决。
(4)add t1, t2, t0
并sw t1, 20(s3)
进行登记t1
在这里,寄存器t1
由 写入add
和读取sw
。新值在第一条指令的 EX 阶段结束时计算,并且在下一条指令的 MEM 阶段开始时需要,因此可以通过转发来解决。
(5)addi s1, s1, 1
并beq s1, s5, loop
进行登记s1
在这里,寄存器s1
由 写入addi
和读取beq
。新值在第一条指令的 EX 阶段结束时计算。通常对于没有针对控制风险进行任何优化的 RISC-V 流水线,对于分支指令,在 EX 期间将寄存器与程序计数器 + 偏移量的计算并行进行比较以获得分支目标。这里的控制风险是一个单独的问题,但数据风险可以通过转发来解决。
所以在这 5 种危害中,只有一种不能通过数据转发来解决。可以通过指令重新排序来解决吗?是的。看看addi s1, s1, 1
。在 之前addi
,s1
在 first 之后 是 不 被 任何 指令 读取 或 写入 的slli
. 如果我们移动该指令,则生成的代码如下所示:
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
新值时完成 MEM 阶段。t0
add t1, t2, t0
通过这种重新排序,所有数据危害都可以通过转发来解决,并且不需要停顿。
推荐阅读
- html - Bootstrap CSS 库不会加载
- sql - Oracle SQL - 不同 ID 格式的 substr 匹配
- python - 比较两个或多个 docx 文件
- java - 如何取消android studio中的特定线程?
- json - 使用 Jq 展平 JSON,并在输出中使用数组索引
- javascript - 将 Material UI 中的网格列表和图标按钮用作具有 onClick 操作的单独按钮?
- python - while 条件或条件循环的问题(初学者)
- google-apis-explorer - Google Photos API 问题:没有 mediaItems 的响应
- assembly - 使用循环 8051 程序集将字符串移入寄存器
- python - 在 matplotlib.pyplot 中绘图时如何命名单个函数/图形?