riscv-boom's btb

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) // 13-bit 有符号偏移
val extended = Bool() // 1-bit 扩展标志
}

class BTBMeta extends Bundle {
val is_br = Bool() // 是否是分支
val tag = UInt(tagSz.W) // 用于组内匹配的 Tag
}

并行读取

1
2
3
4
5
6
7
8
val s1_req_rmeta = Wire(Vec(nWays, Vec(bankWidth, new BTBMeta))) // nWays=2
val s1_req_rbtb = Wire(Vec(nWays, Vec(bankWidth, new BTBEntry)))
val s1_req_rebtb = Wire(UInt(vaddrBitsExtended.W)) // Extended BTB

// ... (SRAM or Flop 实现) ...
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 是分支预测器中提供目标地址预测的核心组件,它通过存储历史跳转信息来快速预测分支/跳转指令的目标地址,是实现高性能前端取指的关键。


riscv-boom's btb
http://blog.luliang.online/2025/12/02/分支预测器btb/
作者
Luyoung
发布于
2025年12月2日
许可协议