“load use互锁和转发是一套共同协议:互锁保证EX不会要求尚未可用的最近写值,转发保证可用时选到它。单独证明其中一个选择器的优先级正确,还不能证明流水线无数据错误。”
形式陈述
在固定五级模型中,load在MEM末才得到数据,紧随它的依赖指令原本要在同周期EX使用该值。本文禁止MEM末到同周期EX的逆时序通路,因此必须让消费者晚一周期进入EX。
当ID/EX中是有效load且rd非零,IF/ID的指令又在EX需要这个rd作为真实源时,互锁动作是:PC保持,IF/ID保持,ID/EX下一值为无效,EX/MEM与MEM/WB正常推进。保持留住等待者,气泡隔开等待者与load,后端推进使数据最终就绪。
本页store的base与data都在EX消费,因此二者都参与检测。若另一个实现能在store的MEM阶段补送data,它的 lw→sw 数据依赖可能少停一次;必须先改变旁路契约再改周期表。
直觉
转发能够省掉“已经有值却等写回”的时间,不能省掉“值还没有算出”的时间。load-use是后者。正确问题不是“有没有一根线”,而是生产者的数据何时稳定,消费者最迟何时必须拿到。
暂停整个流水线反而可能永远等不到值:load也被冻住,无法离开EX去访问内存。互锁只冻结需要等待的前端,让解决依赖的后端继续工作。
例子与边界
一周期互锁的全动作
初始x2=5,内存word值为0,执行 lw x2,0(x1); add x3,x2,x6,其中x6=9。关键周期如下:
| 周期 | load | add | 前端与值的动作 |
|---|---|---|---|
| 1 | IF | — | 取load |
| 2 | ID | IF | 正常推进 |
| 3 | EX | ID | 检出依赖,保持PC/IF-ID,插气泡 |
| 4 | MEM | ID保持 | load末尾产出0,EX是气泡 |
| 5 | WB | EX | MEM/WB转发0,算出9 |
| 6 | — | MEM | 携带9 |
| 7 | — | WB | x3写成9 |
若不插气泡,周期4的EX只能误用旧x2=5,或把load地址当值。后面load写回0,不会自动修正已经算出的错误和。
只保持PC仍会漏掉指令
如果PC保持但IF/ID继续被下一条取指覆盖,等待中的add就丢了。如果IF/ID保持但ID/EX也重复接收它,add会多次进入后端。三项控制必须一起满足,不能把“stall=true”当作没有定义的万能动作。
指令间隔和需求时机
lw x2,0(x1); addi x7,x0,1; add x3,x2,x6 已有一个独立指令间隔,消费者EX与load的WB同周期,可直接转发,无需本页的额外气泡。把中间指令改成依赖load的add,则无法充当自由的间隔。
lw x2,0(x1); sw x2,4(x1) 在本文也停一周期,因为store数据在EX选好。仅凭“store真正写在MEM”而取消停顿,会漏掉本模型并不存在的晚旁路。
推论与应用
互锁检测应由寄存器源使用标记、目的写使能与结果就绪条件组成。对 lw x0,...,后续读x0没有数据依赖,但load本身仍须正常执行;“不需要转发”不等于“可以删除指令”。
共同终点程序把load-use放在算术和分支两种消费者前。两次停顿相同,值随后去向不同;这样可以检查互锁是否只覆盖了ALU而漏了比较器。
参考资料
- UC Berkeley CS61C,Data Hazards,课程笔记,访问于 2026-10-08,load结果就绪与停顿背景。
- David A. Patterson and John L. Hennessy, Computer Organization and Design RISC-V Edition, 2nd ed., 2021,Ch. 4。本文冻结和气泡规则、store消费时机为独立声明的教学实现。