xs-gem5: BTB-ITTAGE
xs-gem5 间接分支目标预测架构 (BTB-ITTAGE)
当前 xs-gem5 的 Kunminghu v3 默认前端(DecoupledBPUWithBTB)预测普通间接控制流的目标
- BTB 给出控制流候选和基础目标
- BTB-ITTAGE 用路径历史选择/覆盖普通间接分支目标
- RAS 覆盖 return
这里的“普通”指
isIndirect && !isReturn,涵盖间接 call 和非 return 的间接 jump;return 的目标由 RAS 处理,不是 ITTAGE 的职责
默认配置
configs/example/kmhv3.py 在 bp_type == DecoupledBPUWithBTB 时启用 mbtb、ittage、ras 等组件,并将 cpu.branchPred.ittage.resolvedUpdate = True, 并会使用 BTBITTAGE
BTBITTAGE 的默认参数定义在 src/cpu/pred/BranchPredictor.py:
| 项目 | 默认值 | 含义 |
|---|---|---|
| 表数 | 5 | 5 个 tagged 表 |
| 表项数 | [256, 256, 512, 512, 512] |
每张表直接索引的容量 |
| tag | 每表 9 bit | 与完整 entry.pc 二次核对共同防 alias |
| 历史长度 | [4, 8, 13, 16, 32] |
从短到长的路径相关性 |
| 索引块大小 | 32 B | index/tag 以 stream 的 32B 对齐块地址为 PC 成分 |
| 延迟 | 2 | 从 stagePreds[2] 起写入候选目标 |
| 每次分配 | 1 表项 | 一次失误至多分配一个更长历史表项 |
- 顶层
predictWidth是 64B,而 ITTAGE 的索引块是 32B;它使用预测 stream 的startPC(经>> 5)索引,而不是每一条间接分支的 PC - entry 同时保存完整的
pc,查找时要求tag和pc都一致
预测 Path
FullBTBPrediction::getEntryTarget() 是最终目标选择的唯一汇合点:
- 直接分支使用
BTBEntry::target - 普通间接分支先取
BTBEntry::target作为基础目标;如果indirectTargets中存在同一 branch PC 的条目,则使用 ITTAGE 给出的目标覆盖它 - return 无条件使用
returnTarget,即 RAS 结果;ITTAGE 从不查询、更新或统计 return。
因此,BTB target 既是 ITTAGE miss 的功能性回退,也是 ITTAGE 的 alternate/base 候选
createFetchTargetEntry() 会把已选择的最终 target 写进 predBranchInfo.target,随后前端据 finalPred.getTarget() 推进下一个 s0PC
顶层还记录 S3 归因:
- 当预测的 taken entry 是普通间接分支且
ittage->tageHit()为真时,finalPred.s3Source标为 ITTAGE - return 标为 RAS
BTB-ITTAGE lookup
BTBITTAGE::putPCHistory() 对当前 stream 仅为每张表读取一个 (index, tag, entry):
1 | index = ((startPC >> log2(32)) XOR folded_path_history) XOR ASID hash |
随后 lookupHelper() 遍历当前 stage 的 BTB entry,仅接受 valid && isIndirect && !isReturn 的 entry,并从最长表向最短表找两个命中:
- 命中条件:表项
valid、预测 tag 相等,且表项保存的完整pc == btb_entry.pc - 第一个命中是 main provider,第二个是 alternate provider;两者都没有时使用 BTB 基础 target
- main provider 的 2-bit
counter不为 0 时,使用 main 的 target:counter >= 2才会把该目标写入indirectTargetscounter == 1的 main 命中会提供目标但不产生覆盖条目,最终仍落回 BTB target
- main
counter == 0时,若存在 alternate 则由 alternate 决定;否则使用基础 BTB target。(这一类选择记为useAlt,其中也包括“不命中而用 BTB”)
当前实现将每表存储抽象为单个 TageEntry(不是 BTBTAGE 的多 way 结构):{valid, tag, target, 2-bit counter, useful, pc}。
虽然 ITTAGE 根据“最长优先”寻找多个命中,但每张表对一个 stream 只有一次读取,所以同一 stream 中不同间接 PC 会竞争同一索引位置;完整 PC 比较防止错误命中,但不能避免容量/冲突导致的 miss
BTB-ITTAGE Path History Register (PHR)
ITTAGE 使用 PHR,不用 GHR
- 每个硬件线程维护三组、每表一份的
PathFoldedHist:index folded history、tag folded history 与 alternate-tag folded history - PHR 只在预测到 taken 控制流时更新
- 顶层
getPHistUpdate()取最终 selected entry 的(pc, target) pHistShiftIn()将pathHash(pc, target)(branch PC 的 9 bit 与 target 的 15 bit 组合)混入 970-bit PHR- ITTAGE 同时用更新前的 PHR 调
PathFoldedHist::update(),确保下一次查表使用与顶层投机 PHR 一致的折叠值
每个 FTQ FetchTarget 保存预测时的 PHR 与各组件的 prediction meta;
ITTAGE meta 中还保存三组 folded history 和按 branch PC 保存的 provider/alternate 信息
squash recovery
控制流 squash 时:
- 顶层恢复 FTQ entry 保存的 PHR
BTBITTAGE::recoverPHist()从该 entry 的 meta 恢复 folded history- 用真实的
(squash PC, redirect target)重新注入正确的 taken path - 顶层也将相同真实路径写回 PHR
这避免错误间接 target 污染后续 ITTAGE 的 index/tag 路径上下文
训练 Path
默认 v3 的 ITTAGE 是 resolve-time training
fetch.cc 将 IEW 送来的 resolved CFI 聚合到 resolve queue;DecoupledBPUWithBTB::resolveUpdate() 对 resolvedUpdate 组件调用 doResolveUpdate(),其默认实现就是 update()。
(配置中 ITTAGE 的 resolvedUpdate=True,所以它不会在随后 commit 的 updatePredictorComponents() 再训练一次)
BTBITTAGE::update() 的训练集合为当前 FTQ stream 中的普通间接 branch;
在 resolved-update 模式下还要求 entry 已被 markCFIResolved() 标记
对每个 entry:
- 从 FTQ 保存的 meta 取 prediction 时的 main/alternate provider 和折叠历史,真实 target 为
stream.exeBranchInfo.target - 若 main 命中,以“main target 是否等于真实 target”更新 2-bit counter;
- counter 降到 0 时用真实 target 覆盖该表项 target
- main 与 alternate 的 taken 判断不同时,main entry 的
useful设为 main target 是否正确
- 若此次是该 branch 的 control squash,且不是“选择 alternate 但 main 恰好正确”,则尝试在 main provider 之后的更长历史表分配
- 只选
useful == 0的候选槽 - LFSR 随机选择后最多分配一个,初值为
{target=真实 target, counter=2, useful=false, pc=branch PC}
- 只选
- 若可分配槽长期耗尽,
usefulResetCnt累积到 256 后清零所有表项的 useful 位
相关代码
- 默认配置:
configs/example/kmhv3.py - 参数、时延与顶层配置:
src/cpu/pred/BranchPredictor.py - 最终间接/return target 覆盖规则:
src/cpu/pred/btb/common.hh:FullBTBPrediction::getEntryTarget() - 预测、S3 source、FTQ/meta 保存:
src/cpu/pred/btb/decoupled_bpred.cc:requestNewPrediction()、generateFinalPredAndCreateBubbles()、createFetchTargetEntry() - PHR 投机更新与 squash 恢复:
src/cpu/pred/btb/decoupled_bpred.cc:updateHistoryForPrediction()、recoverHistoryForSquash() - ITTAGE 查表、训练、恢复和提交统计:
src/cpu/pred/btb/btb_ittage.cc - resolve queue 到预测器训练的接口:
src/cpu/o3/fetch.cc、src/cpu/pred/btb/decoupled_bpred.cc:resolveUpdate()