“在固定五级模型中,load在MEM末才得到数据,紧随它的依赖指令原本要在同周期EX使用该值。本文禁止MEM末到同周期EX的逆时序通路,因此必须让消费者晚一周期进入EX。”
形式陈述
流水线把一条指令的工作分成多级,让不同指令同时占据不同级。本页实现五指令 RV32I 子集,固定为单发、顺序、五级教学模型:
| 级 | 本周期工作 | 末尾需保存的主要内容 |
|---|---|---|
| IF | 按取指PC读指令 | IF/ID:valid、指令、该指令PC |
| ID | 解码与读寄存器 | ID/EX:源编号/值、立即数、目的编号、控制位、PC |
| EX | ALU、地址或分支比较 | EX/MEM:结果/地址、store数据、目的编号、控制位 |
| MEM | 读写数据存储 | MEM/WB:最终写回值、目的编号、写使能 |
| WB | 写架构寄存器 | 本级不产生新的流水寄存器 |
所有流水寄存器遵守同时更新;表中的级内容指周期开始时已存入该级的指令。EX与MEM结果在周期末可用。每级用valid说明是否有真实指令;valid=false是气泡,必须禁止架构写入。
共同的时序契约
指令与数据存储分离,各固定一周期。WB在周期前半写、ID在后半读。EX/MEM的非load结果和MEM/WB的最终结果可转发到EX;store数据也在EX选好后携带至MEM,不设MEM阶段的额外store-data旁路。load结果在MEM末生成,下一周期才可给EX使用。
遇load-use时,冻结PC与IF/ID,向ID/EX插气泡,较老级继续前进。beq在EX末决断,默认取PC+4;taken时清除本周期IF和ID的年轻指令,下一周期IF取目标。分支重定向优先于年轻指令的阻塞。上述规则是本文的实现选择,不是RV32I规定的周期数。
直觉
流水线增加的是同时在途的工作,而非让每条指令跳过步骤。把五道工序排成连续生产线,填满后可能每周期有一个结果,但单件仍穿过五级。数据和控制都必须跟着自己的指令走,不能让本周期的opcode驱动另一个周期的结果。
气泡是一个无效位置,暂停则是某条指令留在原位。两者不同:暂停前端时,后端的旧指令应继续完成,才能解除等待。
例子与边界
没有冒险时的重叠
三条互不依赖的add从空流水线开始,分别在周期1、2、3进入IF,在周期5、6、7进入WB,最后一条于周期7写回。对
这不表示任意程序CPI等于1。有限片段有填充与排空成本,数据依赖、分支和存储等待又可能插入空位。即使周期数减少,时钟周期变长也可能抵消收益,必须同时报告周期长度。
结构冒险来自资源假设
若改用一个每周期只接受一次请求的统一存储端口,那么旧load在MEM读数据时,新指令不能同时IF取指。这个冲突无需寄存器依赖也会出现。本文通过分离I/D端口排除了它,不把排除后的周期表推广到单端口机器。
一份可核验的共同程序
从指令状态到缓存写回的完整任务给出同一段程序的顺序结果、21周期流水状态以及11次数据访存。两个load-use分别触发一周期互锁,一次taken分支清除两条错误路径指令;load→add、ALU→store-data、load→branch三条转发都有明确来源。
然后把这11次已确认的数据访问交给两种缓存。缓存缺失不回填到此固定一周期存储模型:前一个实验验证指令时序,后一个实验验证映射和数据搬运;要联合模拟,就须另加miss阻塞契约。
推论与应用
转发解决已经算出但尚未写回的值,互锁处理还没算出的值,分支清除处理根本不该执行的指令。这三个机制的对象不同。
正确性检查不能只数周期。每条有效指令应读到最近较老写者的值,每个错误路径valid都应被清除,store只在对应有效MEM槽产生一次副作用。精确异常进一步要求故障出现时保留一个正确的已完成前缀。
参考资料
- UC Berkeley CS61C,The RISC-V 5-Stage Pipeline 与 Data Hazards,课程笔记,访问于 2026-10-08;作为五级结构和旁路背景。
- David A. Patterson and John L. Hennessy, Computer Organization and Design RISC-V Edition, 2nd ed., 2021,Ch. 4。本页独立固定EX末分支决断;不能直接搬用在MEM决断的课程图所给清除条数。