“条件分支的真实方向尚未算出时,取指可以先猜它会跳转还是顺序前进。分支冒险与错误路径清除给出了固定猜“不跳转”的实现,并说明猜错后如何取消年轻指令。本页把固定猜测换成一个会记住过去的方向接口;…”
形式陈述
在本单元五级模型中,beq在EX读取经过转发的两个源值,周期末决定是否跳转及目标;IF此前按PC+4连续取指。若跳转成立,本周期ID和IF中的两条年轻指令属于错误路径。
恢复动作是在该边沿把下一取指PC设为目标、将下一IF/ID和ID/EX置为无效。分支本身和更老指令继续前进。下一周期IF开始取目标,因此此模型的一次taken分支引入两个空发射位置。未跳转没有此罚时。
这里的“按未跳转预测”是实现策略,flush是取消错误推测的机制。RV32I没有架构可见的分支延迟槽,不允许把分支后的第一条错误路径指令保留下来执行。
双态分支方向预测用按PC索引的二位计数器替换固定猜测:先给方向,真实结果出现后才训练,允许不同PC共享同槽并互相干扰。它只改善可能的猜测,不提供目标地址或取消错误路径的机制;本页两槽清除结论仍受自己的EX末决断时序约束。
直觉
分支决断晚于取指,处理器先走了一段尚未获准的路。只要这些年轻指令还没有产生无法撤回的架构副作用,就可以把valid清零,再从正确目标重新开始。
清除的是指令的有效身份,不是把所有数据导线都擦成零。无效槽里即使还残留地址或旧值,也必须因valid和写使能的约束而不能写寄存器或内存。
例子与边界
被取到的store不应被执行
取下面片段,x4=0,x7=11:
0x10: beq x4,x0,+12
0x14: sw x7,0(x1)
0x18: addi x6,x0,99
0x1c: lw x5,0(x1)
当beq在EX时,store在ID、addi在IF。EX末比较相等,目标
数据冒险先决定分支条件
若beq紧随 lw x4,32(x1),且旧x4=1、load将读得0,应先经load-use互锁,随后用load的0作比较。用ID读出的旧1会错误地不跳转;即便flush逻辑本身正确,也救不了错误条件。
罚时不是指令集常量
另一个实现若到MEM才重定向,可能要清除三个年轻位置;若在ID可靠地完成比较,也可能更早恢复。两者都可以实现相同ISA。本文的两槽结论只由“EX末决断、每周期单发、下周期目标IF”三项条件推出。
若目标恰好已经在某个年轻槽内,本文仍按统一规则清除并重新取它,没有额外复用优化。计算周期不能一会儿采用统一flush,一会儿暗中保留碰巧正确的指令。
推论与应用
分支恢复的安全性来自副作用的先后关系:本文年轻store尚未到MEM,年轻寄存器写尚未到WB。更激进的实现必须用其他办法延迟提交,不能只照抄两个valid位的清零。
在更早的取指一侧,带标记目标缓冲先给出候选nextPC;命中只说明PC身份匹配,不保证这次目标正确。若年轻分支已修改历史或返回栈,多在途预测状态恢复还要取消其预测记录,恢复完整检查点,并把表训练推迟到按序提交。
内存依赖违例重放给出另一种年轻后缀取消:load先越过未知老写,老地址揭晓后以来源年龄检测冲突。恢复除清除load结果,还必须取消所有年轻衍生地址和store数据,并使旧代次token失效;顺序退休防止这些暂定值提前成为架构副作用。
完整终点任务在周期9做taken恢复;错误路径store正好是可核验反例。正确轨迹不含这次访问,因此缓存模拟器也不应凭“取指看见过store”就把它加入数据trace。
参考资料
- RISC-V International,RV32I 2.1,固定文档版 v20260120,§1.1.5,控制转移没有架构可见延迟槽。
- UC Berkeley CS61C,Control Hazards,课程笔记,访问于 2026-10-08。该笔记的示意模型在MEM重定向;本页明确选EX末重定向,清除数量由本页规则推导。