无WB→DEC转发的RISC-V流水线第三行指令后需2条NOP的原因
RISC-V流水线NOP插入需求分析
首先明确该流水线的核心约束:经典5级RISC-V流水线,支持EXE/MEM/WB到EXE阶段的常规转发,不支持寄存器文件WB阶段到DEC阶段的内部转发,无硬件自动停顿机制,所有数据依赖需要软件插入NOP解决。
原思路的核心错误
你默认分支指令beq的源操作数t0、t1是在EXE阶段才需要使用,因此认为可以通过EXE阶段的转发拿到正确值,但该推论存在两个问题:
- 该流水线实现中分支比较逻辑提前到DEC阶段执行:为了降低分支惩罚,绝大多数RISC-V流水线会将分支的源寄存器比较操作放在DEC阶段完成,这意味着
beq在进入DEC阶段时就需要拿到t0、t1的正确值。 - 架构不支持WB→DEC的转发:DEC阶段读取寄存器值时,只能获取已经完成WB阶段、写入到寄存器文件中的值,无法直接拿WB阶段还未写入寄存器文件的结果,也没有转发路径支持将其他阶段的结果直接送到DEC阶段。
时序验证
我们按经典5级流水线(IF→DEC→EXE→MEM→WB)的周期排布验证两种插入方案的正确性:
仅插入1条NOP的情况
各指令的阶段排布(每周期前进一级):
| 周期 | 指令1addi t0 | 指令2addi t1 | 指令3addi s1 | NOP | 指令4beq |
|---|---|---|---|---|---|
| 1 | IF | ||||
| 2 | DEC | IF | |||
| 3 | EXE | DEC | IF | ||
| 4 | MEM | EXE | DEC | IF | |
| 5 | WB | MEM | EXE | DEC | IF |
| 6 | WB | MEM | EXE | DEC |
可以看到,beq在周期6进入DEC阶段需要读t1时,指令2addi t1刚好处于WB阶段,由于没有WB→DEC的转发路径,寄存器文件还未写入t1的新值,beq读到的仍然是t1的旧值,运行错误。
插入2条NOP的情况
| 周期 | 指令1addi t0 | 指令2addi t1 | 指令3addi s1 | NOP1 | NOP2 | 指令4beq |
|---|---|---|---|---|---|---|
| 1 | IF | |||||
| 2 | DEC | IF | ||||
| 3 | EXE | DEC | IF | |||
| 4 | MEM | EXE | DEC | IF | ||
| 5 | WB | MEM | EXE | DEC | IF | |
| 6 | WB | MEM | EXE | DEC | IF | |
| 7 | WB | MEM | EXE | DEC |
此时beq在周期7进入DEC阶段读寄存器时,指令2已经在周期6完成了WB阶段,寄存器文件中t1的值已经更新为正确的5,读取结果正确,程序可以正常运行。
内容的提问来源于stack exchange,提问作者kal_elk122
相关产品推荐
相关产品推荐

