btb
The Branch Target Buffer (BTB) caches branch target addresses to provide fast prediction of where branches will go.
Structure:
- Set-associative cache (default: 128 sets, 2 ways)
- Each entry stores: tag, target offset, is_br flag, extended flag
- Extended BTB (EBTB) for far jumps that exceed offset range
Operation:
- S0: Send read address to SRAM
- S1: Receive SRAM data, compute hit/target
- S2/F2: Output prediction response
- S3/F3: Registered F2 response
BTB 条目
1 2 3 4 5 6 7 8 9
| class BTBEntry extends Bundle { val offset = SInt(offsetSz.W) val extended = Bool() }
class BTBMeta extends Bundle { val is_br = Bool() val tag = UInt(tagSz.W) }
|
并行读取
1 2 3 4 5 6 7 8
| val s1_req_rmeta = Wire(Vec(nWays, Vec(bankWidth, new BTBMeta))) val s1_req_rbtb = Wire(Vec(nWays, Vec(bankWidth, new BTBEntry))) val s1_req_rebtb = Wire(UInt(vaddrBitsExtended.W))
s1_req_rmeta(w) := meta.read(s0_idx, s0_valid).map(...) s1_req_rbtb(w) := btb.read(s0_idx, s0_valid).map(...) s1_req_rebtb := ebtb.read(s0_idx, s0_valid)
|
Tag 匹配
1 2 3 4 5 6 7 8
| val s1_hit_ohs = VecInit((0 until bankWidth) map { i => VecInit((0 until nWays) map { w => s1_req_rmeta(w)(i).tag === s1_req_tag(tagSz-1,0) }) })) val s1_hits = s1_hit_ohs.map { oh => oh.reduce(_||_) } val s1_hit_ways = s1_hit_ohs.map { oh => PriorityEncoder(oh) }
|
目标地址计算
1 2 3 4 5 6 7 8 9 10
| for (w <- 0 until bankWidth) { for (b <- 0 until nWays) { val entry_btb = WireInit(s1_req_rbtb(b)(w)) s1_targs(b)(w) := Mux(entry_btb.extended, s1_req_rebtb, (s1_pc.asSInt + (w << 1).S + entry_btb.offset).asUInt) } s1_resp(w).bits := s1_targs(s1_hit_ways(w))(w) }
|
BTB (Branch Target Buffer) 分支目标缓冲器工作流程详解
1. 整体架构概览
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| ┌──────────────────────────────────────────────────────────────────────────────────┐ │ BTB Branch Predictor │ │ │ │ ┌─────────────────────────────────────────────────────────────────────────────┐ │ │ │ 主 BTB 存储 (nWays 路组相联) │ │ │ │ │ │ │ │ Way 0 Way 1 │ │ │ │ ┌──────────────────────────┐ ┌──────────────────────────┐ │ │ │ │ │ Meta SRAM │ │ Meta SRAM │ │ │ │ │ │ ┌─────┬─────┬─────┐ │ │ ┌─────┬─────┬─────┐ │ │ │ │ │ │ │tag │is_br│tag │... │ │ │tag │is_br│tag │... │ │ │ │ │ │ │ b0 │ b0 │ b1 │ │ │ │ b0 │ b0 │ b1 │ │ │ │ │ │ │ └─────┴─────┴─────┘ │ │ └─────┴─────┴─────┘ │ │ │ │ │ │ nSets = 128 行 │ │ nSets = 128 行 │ │ │ │ │ └──────────────────────────┘ └──────────────────────────┘ │ │ │ │ │ │ │ │ ┌──────────────────────────┐ ┌──────────────────────────┐ │ │ │ │ │ Data SRAM │ │ Data SRAM │ │ │ │ │ │ ┌─────────┬────────┐ │ │ ┌─────────┬────────┐ │ │ │ │ │ │ │ offset │extended│... │ │ │ offset │extended│... │ │ │ │ │ │ │ 13-bit │ 1-bit │ │ │ │ 13-bit │ 1-bit │ │ │ │ │ │ │ └─────────┴────────┘ │ │ └─────────┴────────┘ │ │ │ │ │ └──────────────────────────┘ └──────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────────────────────────────┐ │ │ │ 扩展 BTB (Extended BTB / EBTB) │ │ │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ │ │ 用于存储无法用 offset 编码的远跳转目标地址 │ │ │ │ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ │ │ │ │ 完整目标地址 (vaddrBitsExtended 位) │ │ │ │ │ │ │ │ extendedNSets = 128 条目 │ │ │ │ │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ │ └──────────────────────────────────────────────────────────────────────────────────┘
|
2. 数据结构详解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| ┌─────────────────────────────────────────────────────────────────────────────────┐ │ BTB 条目结构 │ └─────────────────────────────────────────────────────────────────────────────────┘
BTBEntry (Data SRAM 存储): ┌─────────────────────────────────────────────┐ │ btbEntrySz = 14 bits │ ├───────────────────────────┬─────────────────┤ │ offset (13 bits) │ extended (1b) │ │ 有符号偏移量 │ 是否使用 EBTB │ └───────────────────────────┴─────────────────┘
offset 范围: -4096 ~ +4095 (相对于当前 PC) 如果目标地址超出此范围,extended=1,需查 EBTB
BTBMeta (Meta SRAM 存储): ┌─────────────────────────────────────────────┐ │ btbMetaSz = tagSz + 1 bits │ ├───────────────────────────────┬─────────────┤ │ tag (tagSz bits) │ is_br (1b) │ │ 地址标签 │ 是否是分支 │ └───────────────────────────────┴─────────────┘
is_br = 1: 条件分支指令 (可能跳转/不跳转) is_br = 0: 无条件跳转 (JAL)
BTBPredictMeta (预测元数据,传递给更新逻辑): ┌─────────────────────────────────────────────┐ │ write_way (log2(nWays) bits) │ │ 记录命中/分配的路号 │ └─────────────────────────────────────────────┘
|
3. 索引与标签计算
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| ┌─────────────────────────────────────────────────────────────────────────────────┐ │ PC 地址分解 │ └─────────────────────────────────────────────────────────────────────────────────┘
PC (vaddrBitsExtended 位) ┌────────────────────────────────────────────────────────────────┐ │ 高位 (tag) │ 中间位 (index) │ 低位 (offset) │ │ tagSz bits │ log2(nSets) bits │ log2(fetchWidth)+1│ └────────────────────────────────────────────────────────────────┘ │ │ │ │ │ └─ 忽略 (字节/指令内) │ │ │ ▼ │ ┌─────────────────────────┐ │ │ s0_idx / s1_idx │ │ │ 选择 BTB 中的哪一行 │ │ └─────────────────────────┘ │ ▼ ┌─────────────────────────────────────┐ │ s1_req_tag = s1_idx >> log2(nSets) │ │ 用于与存储的 tag 比较 │ └─────────────────────────────────────┘
示例 (假设 vaddrBitsExtended=39, nSets=128, fetchWidth=8):
PC = 0x7F_FFFF_1234
index = PC[10:4] = 7 bits → 选择 set tag = PC[38:11] = 28 bits → 标签比较
|
4. 预测流水线时序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| ┌─────────────────────────────────────────────────────────────────────────────────┐ │ 预测流水线时序 │ └─────────────────────────────────────────────────────────────────────────────────┘
周期 S0 (取指请求) S1 (SRAM 输出) F2 (输出) F3 (延迟) │ │ │ │ │ ▼ ▼ ▼ ▼ ▼ ───────────────────────────────────────────────────────────────────────────────── │ │ │ │ │ ┌──────────────────┐ │ │ │ │ │ s0_idx 计算 │ │ │ │ │ │ 发起 SRAM 读请求 │──────────│ │ │ │ │ - meta.read() │ SyncRead │ │ │ │ │ - btb.read() │ │ │ │ │ │ - ebtb.read() │ │ │ │ │ └──────────────────┘ │ │ │ │ │ │ │ │ ┌──────▼──────┐ │ │ │ │ s1_req_rmeta│ │ │ │ │ s1_req_rbtb │ │ │ │ │ s1_req_rebtb│ │ │ │ │ │ │ │ │ │ 标签比较 │ │ │ │ │ s1_hit_ohs │ │ │ │ │ │ │ │ │ │ 目标地址计算 │────────────│ │ │ │ s1_targs │ RegNext │ │ │ │ │ │ │ │ │ s1_resp │ │ │ │ │ s1_is_br │ │ │ │ │ s1_is_jal │ │ │ │ └─────────────┘ │ │ │ │ │ │ ┌───────▼───────┐ │ │ │ io.resp.f2 │ │ │ │ predicted_pc │───────────│ │ │ is_br, is_jal │ RegNext │ │ │ taken (JAL) │ │ │ └───────────────┘ │ │ │ │ ┌───────▼───────┐ │ │ io.resp.f3 │ │ │ (同 f2 延迟) │ │ └───────────────┘ ─────────────────────────────────────────────────────────────────────────────────
|
关键点:
- BTB 在 S1 阶段就能提供预测结果 (比 BIM 早一拍)
- JAL 指令直接设置 taken=true (无条件跳转)
- 分支指令 (is_br=true) 需要等 BIM 等预测器提供 taken
5. 命中检测与路选择
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| ┌─────────────────────────────────────────────────────────────────────────────────┐ │ 命中检测逻辑 │ └─────────────────────────────────────────────────────────────────────────────────┘
对于每个 bank 位置 (w in 0..bankWidth):
s1_req_tag (来自 PC) │ ┌───────────────┼───────────────┐ │ │ │ ▼ ▼ ▼ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ Way 0 │ │ Way 1 │ │ Way N-1 │ │ meta.tag │ │ meta.tag │ │ meta.tag │ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ │ │ │ ▼ ▼ ▼ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ 比较 │ │ 比较 │ │ 比较 │ │ ==? │ │ ==? │ │ ==? │ └─────┬─────┘ └─────┴─────┘ └─────┴─────┘ │ │ │ ▼ ▼ ▼ s1_hit_ohs(w) = [hit_way0, hit_way1, ..., hit_wayN] │ ┌─────────────┴─────────────┐ │ │ ▼ ▼ ┌───────────────┐ ┌───────────────┐ │ s1_hits(w) │ │ s1_hit_ways(w)│ │ = OR reduce │ │ = PriorityEnc │ │ 是否有命中 │ │ 命中的路号 │ └───────────────┘ └───────────────┘
|
6. 目标地址计算
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| ┌─────────────────────────────────────────────────────────────────────────────────┐ │ 目标地址计算逻辑 │ └─────────────────────────────────────────────────────────────────────────────────┘
对于每个 bank w 和每个 way b:
entry_btb = s1_req_rbtb(b)(w) // 读出的 BTB 条目
┌─────────────────────────────────┐ │ entry_btb.extended? │ └────────────────┬────────────────┘ │ ┌────────────────┴────────────────┐ │ │ ▼ ▼ extended = 1 extended = 0 │ │ ▼ ▼ ┌───────────────────────┐ ┌───────────────────────────────┐ │ 使用 EBTB │ │ 相对地址计算 │ │ s1_req_rebtb │ │ s1_pc + (w << 1) + offset │ │ (完整目标地址) │ │ │ └───────────────────────┘ │ PC偏移 + bank内偏移 + offset │ │ └───────────────────────────────┘ │ │ └─────────────┬───────────────────┘ │ ▼ ┌─────────────────────────────────┐ │ s1_targs(b)(w) │ │ 该 way 该 bank 的目标地址 │ └─────────────────────────────────┘ │ ▼ ┌─────────────────────────────────┐ │ Mux by s1_hit_ways(w) │ │ 选择命中路的目标地址 │ └─────────────────────────────────┘ │ ▼ ┌─────────────────────────────────┐ │ s1_resp(w).bits │ │ 最终预测的目标地址 │ └─────────────────────────────────┘
|
注: (w << 1) 是因为每条指令占 2 字节 (压缩指令)
7. 路分配策略
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| ┌─────────────────────────────────────────────────────────────────────────────────┐ │ 路分配 (Allocation) 策略 │ └─────────────────────────────────────────────────────────────────────────────────┘
当发生 BTB 未命中时,需要选择一个路来存储新条目:
┌──────────────────────────────────────────────────────────────────┐ │ s1_hits.reduce(_||_)? │ └────────────────────────────┬─────────────────────────────────────┘ │ ┌────────────┴────────────┐ │ │ ▼ ▼ 命中 (Hit) 未命中 (Miss) │ │ ▼ ▼ ┌───────────────────────────┐ ┌───────────────────────────────────┐ │ write_way = 命中路 │ │ alloc_way 计算 │ │ PriorityEncoder(hit_ohs) │ │ │ └───────────────────────────┘ │ 伪随机分配 (基于 XOR hash) │ │ │ │ r_metas = Cat(所有way的tag, req_tag)│ │ │ │ 将 r_metas 分成多个 chunk │ │ 每个 chunk log2(nWays) 位 │ │ │ │ alloc_way = chunks.XOR_reduce │ └───────────────────────────────────┘
|
示例 (nWays = 2):
r_metas = [way1.tag, way0.tag, req_tag] 拼接
分成若干 1-bit chunk,全部 XOR
结果 0 或 1 → 选择替换 Way 0 或 Way 1
这种策略:
- 简单高效,无需额外状态
- 提供一定的伪随机性
- 与访问地址相关,可重现
8. 更新逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| ┌─────────────────────────────────────────────────────────────────────────────────┐ │ 更新流程 │ └─────────────────────────────────────────────────────────────────────────────────┘
s1_update (来自后端) │ ▼ ┌───────────────────────────────────────────────────────────────────────┐ │ 偏移量计算 │ │ │ │ new_offset = target - (pc + cfi_idx << 1) │ │ │ │ max_offset = +4095 (13位有符号最大正值) │ │ min_offset = -4096 (13位有符号最小负值) │ │ │ │ offset_is_extended = (new_offset > max) || (new_offset < min) │ └───────────────────────────────────────────────────────────────────────┘ │ ▼ ┌───────────────────────────────────────────────────────────────────────┐ │ 准备写入数据 │ │ │ │ s1_update_wbtb_data: │ │ .offset = new_offset (截断为 13 位) │ │ .extended = offset_is_extended │ │ │ │ s1_update_wmeta_data[w]: │ │ .tag = update_idx >> log2(nSets) 或 0 (如果误预测需清除) │ │ .is_br = br_mask[w] │ └───────────────────────────────────────────────────────────────────────┘ │ ▼ ┌───────────────────────────────────────────────────────────────────────┐ │ 写入掩码计算 │ │ │ │ s1_update_wbtb_mask: │ │ - 仅在 cfi_taken && is_commit_update 时写入 BTB data │ │ - UIntToOH(cfi_idx) 选择对应 bank │ │ │ │ s1_update_wmeta_mask: │ │ - commit_update 时: 写入 br_mask 标记的所有分支位置 │ │ - btb_mispredicts: 清除误预测的条目 (tag 设为 0) │ └───────────────────────────────────────────────────────────────────────┘ │ ┌───────────┴───────────┐ │ │ ▼ ▼ ┌───────────────────────┐ ┌───────────────────────┐ │ 写入主 BTB │ │ 写入 EBTB │ │ │ │ │ │ 条件: │ │ 条件: │ │ write_way 匹配 │ │ wbtb_mask != 0 │ │ │ │ && offset_is_extended│ │ 写入: │ │ │ │ - meta[idx] │ │ 写入: │ │ - btb[idx] │ │ - ebtb[idx] = target │ └───────────────────────┘ └───────────────────────┘
|
9. BTB 误预测处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| ┌─────────────────────────────────────────────────────────────────────────────────┐ │ 误预测处理 (btb_mispredicts) │ └─────────────────────────────────────────────────────────────────────────────────┘
场景: BTB 预测了一个跳转,但实际上: 1. 该位置不是分支/跳转指令 2. 或者目标地址错误
处理方式:
s1_update.bits.btb_mispredicts(w) = true │ ▼ ┌───────────────────────────────────────────────────────────────┐ │ s1_update_wmeta_data(w).tag := 0.U │ │ │ │ 将 tag 设为 0,使该条目在后续访问中不再命中 │ │ (因为有效的 tag 不可能全为 0) │ └───────────────────────────────────────────────────────────────┘
┌───────────────────────────────────────────────────────────────┐ │ s1_update_wmeta_mask 包含 btb_mispredicts │ │ 即使不是 commit_update 也会写入 (快速清除错误预测) │ └───────────────────────────────────────────────────────────────┘
|
这种”软删除”策略:
- 不需要真正删除数据
- 只需使 tag 失效
- 后续可以被正常分配覆盖
10. 复位逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| ┌─────────────────────────────────────────────────────────────────────────────────┐ │ 复位流程 │ └─────────────────────────────────────────────────────────────────────────────────┘
系统复位 │ ▼ doing_reset = true reset_idx = 0 │ ▼ ┌───────────────────────────────────────────────────────────────┐ │ 每个周期: │ │ 1. 向所有 Way 的 reset_idx 行写入: │ │ - btb: 全 0 (offset=0, extended=0) │ │ - meta: 全 0 (tag=0, is_br=0) │ │ 2. reset_idx++ │ │ 3. 预测输出被屏蔽 (!doing_reset) │ └───────────────────────────────────────────────────────────────┘ │ │ 经过 nSets (128) 个周期 ▼ reset_idx == nSets - 1 │ ▼ doing_reset = false │ ▼ 正常工作
|
注意:
- EBTB 在 SRAM 模式下不需要显式复位 (读出无效数据会因主 BTB 未命中而忽略)
- 复位期间所有预测结果无效 (s1_resp.valid = false)
11. 完整数据流图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| ┌─────────────────────────────────────────────────────────────────────────────────┐ │ BTB 完整数据流 │ └─────────────────────────────────────────────────────────────────────────────────┘
┌─────────────────┐ │ 取指请求 │ │ (s0_idx) │ └────────┬────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────────┐ │ S0: SRAM 读请求 │ │ │ │ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ │ │ Way0 Meta │ │ Way0 Data │ │ Way1 Meta │ │ Way1 Data │ ... │ │ │ .read() │ │ .read() │ │ .read() │ │ .read() │ │ │ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ │ │ │ │ │ │ │ └─────────┼────────────────┼────────────────┼────────────────┼─────────────────┘ │ │ │ │ │ ┌─────────┴────────────────┴────────────────┘ │ │ ▼ ▼ ▼ ┌─────────────┐ ┌─────────────────────────┐ │ EBTB │ │ S1: 数据返回 │ │ .read() │ └─────────────────────────┘ └──────┬──────┘ │ │ │ ▼ ▼ ▼ ┌──────────────────────────────────────────────────────────────────┐ │ S1: 命中检测与目标计算 │ │ │ │ ┌─────────────────┐ │ │ │ 标签比较 │ │ │ │ s1_req_tag vs │ │ │ │ meta.tag │ │ │ └────────┬────────┘ │ │ │ │ │ ┌────────▼────────┐ ┌─────────────────────────────────────┐ │ │ │ s1_hit_ohs │ │ 目标地址计算 │ │ │ │ s1_hits │ │ Mux(extended, ebtb, pc+offset) │ │ │ │ s1_hit_ways │ └─────────────────────────────────────┘ │ │ └────────┬────────┘ │ │ │ │ │ │ │ ┌────────▼─────────────────────────────────▼─────┐ │ │ │ s1_resp │ │ │ │ .valid = !doing_reset && s1_valid && hit │ │ │ │ .bits = s1_targs[hit_way] │ │ │ └────────────────────────────────────────────────┘ │ │ │ │ ┌────────────────────────────────────────────────┐ │ │ │ s1_is_br = resp.valid && meta.is_br │ │ │ │ s1_is_jal = resp.valid && !meta.is_br │ │ │ └────────────────────────────────────────────────┘ │ │ │ │ ┌────────────────────────────────────────────────┐ │ │ │ s1_meta.write_way = hit ? hit_way : alloc_way │ │ │ └────────────────────────────────────────────────┘ │ └───────────────────────────────────┬──────────────────────────────┘ │ │ RegNext ▼ ┌───────────────────────────────────────────────────────────────────┐ │ F2: 输出预测结果 │ │ │ │ io.resp.f2(w).predicted_pc := s1_resp (registered) │ │ io.resp.f2(w).is_br := s1_is_br (registered) │ │ io.resp.f2(w).is_jal := s1_is_jal (registered) │ │ io.resp.f2(w).taken := s1_is_jal (JAL 无条件跳转) │ │ │ │ (分支指令的 taken 由 BIM/TAGE 等预测器提供) │ └────────────────────────────────────┬──────────────────────────────┘ │ │ RegNext ▼ ┌───────────────────────────────────────────────────────────────────┐ │ F3: 延迟输出 │ │ │ │ io.resp.f3 := RegNext(io.resp.f2) │ │ io.f3_meta := RegNext(RegNext(s1_meta)) │ └───────────────────────────────────────────────────────────────────┘
|
12. 关键参数总结
| 参数 |
默认值 |
说明 |
| nSets |
128 |
BTB 行数 (索引范围) |
| nWays |
2 |
组相联路数 |
| offsetSz |
13 |
相对偏移位数 (±4096 范围) |
| extendedNSets |
128 |
EBTB 条目数 |
| tagSz |
vaddrBits - log2(nSets) - log2(fetchWidth) - 1 |
标签位数 |
| btbEntrySz |
14 |
Data SRAM 条目位宽 |
| btbMetaSz |
tagSz + 1 |
Meta SRAM 条目位宽 |
| useFlops |
false |
是否用寄存器代替 SRAM |
13. BTB 与 BIM 的协作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| ┌─────────────────────────────────────────────────────────────────────────────────┐ │ BTB + BIM 协作关系 │ └─────────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────┐ │ 取指 PC │ └─────────────────┬───────────────────┘ │ ┌─────────────────┴───────────────────┐ │ │ ▼ ▼ ┌───────────────┐ ┌───────────────┐ │ BTB │ │ BIM │ │ │ │ │ │ 提供: │ │ 提供: │ │ - 目标地址 │ │ - taken 预测 │ │ - is_br/jal │ │ - 2-bit 计数器│ └───────┬───────┘ └───────┬───────┘ │ │ │ ┌───────────────────────────┘ │ │ ▼ ▼ ┌─────────────────────────────────────┐ │ 最终预测结果 │ │ │ │ if (BTB.is_jal): │ │ taken = true (无条件) │ │ elif (BTB.is_br): │ │ taken = BIM.prediction │ │ target = BTB.predicted_pc │ └─────────────────────────────────────┘
|
BTB 负责: WHERE to go (跳转目标)
BIM 负责: WHETHER to go (是否跳转,仅对分支指令)
BTB 是分支预测器中提供目标地址预测的核心组件,它通过存储历史跳转信息来快速预测分支/跳转指令的目标地址,是实现高性能前端取指的关键。