乱序执行 — Out-of-Order Execution
指令乱序但结果正确
📖 为什么需要乱序执行?
顺序执行(In-Order)处理器遇到长延迟指令(如Cache缺失、除法)时,后续独立指令只能等待。乱序执行(OoO)允许就绪的指令先执行,提高指令级并行度(ILP)。
顺序执行:
C1: ADD x5, x1, x2 ────┐
C2: (stall) ────┤ 等待L1缺失
C3: (stall) ────┤
C4: SUB x6, x3, x4 ────┘ SUB必须等ADD完成
乱序执行:
C1: ADD x5, x1, x2 ────┐ L1缺失...
C1: SUB x6, x3, x4 ─┐ │ 立即执行!
C4: ADD完成,提交结果 ─┘──┘ 按程序序提交
关键: SUB不依赖ADD的结果,所以可以提前执行
乱序执行的核心保证
虽然指令乱序执行,但提交(Commit)必须按程序顺序。这保证了:
- 异常/中断的行为与顺序执行一致
- 内存可见性与程序序一致
- 程序员模型不变——看到的是顺序执行的效果
🔬 乱序执行流水线结构
OoO处理器核心流水线:
┌──────────────────────────────────────────────┐
│ 取指 (Fetch) │
│ ↓ │
│ 译码 (Decode) │
│ ↓ │
│ 发射/重命名 (Dispatch/Rename) │
│ ↓ ↘ │
│ 保留站 ←── ROB(重排序缓冲) │
│ ↓ ↗ │
│ 执行 (Execute) — 可能乱序 │
│ ↓ │
│ 写回 (Writeback/CDB) │
│ ↓ │
│ 提交 (Commit/Retire) — 必须按序 │
└──────────────────────────────────────────────┘
关键组件:
• 寄存器重命名: 消除WAW/WAR假依赖
• 保留站: 等待操作数就绪
• ROB: 跟踪指令顺序,保证按序提交
• CDB: 广播结果,唤醒等待的指令
| 组件 | 功能 | 关键数据结构 |
| 寄存器重命名 | 消除假依赖 | RAT (Register Alias Table) |
| 保留站 | 等待操作数就绪 | 源操作数+标签 |
| ROB | 按序提交 | 循环缓冲区 |
| CDB | 广播结果 | 标签+数据 |
| Load/Store队列 | 内存操作排序 | 地址+数据+顺序 |
🔗 OoO在RISC-V中的实现
RISC-V的乱序处理器实现包括:
- BOOM (Berkeley Out-of-Order Machine) — UC Berkeley开源OoO核心,学术标杆
- Sifive P870 — 商用高性能OoO核心,8发射,2024年发布
- 香山 (XiangShan) — 中科院开源高性能RISC-V处理器,南湖架构
- SiPearl Rhea — 欧洲处理器计划,基于RISC-V的OoO核心
BOOM核心是学习OoO设计的最佳参考——用Chisel/Scala编写,结构清晰,文档完善。从BOOM可以学到完整的Rename→Issue→Execute→Writeback→Commit流程。
🖥️ Verilog实现:简化OoO核心
// Lesson 15: Out-of-Order Execution Core
// Dispatch → Execute(OoO) → Commit(In-Order)
module oob_core(
input wire clk, rst_n,
input wire dispatch_valid,
input wire [6:0] dispatch_opcode,
input wire [4:0] dispatch_rd, dispatch_rs1, dispatch_rs2,
input wire [31:0] dispatch_imm,
output reg [4:0] commit_rd,
output reg [31:0] commit_data,
output reg commit_valid
);
parameter NUM_ROB = 8, NUM_RS = 4;
// ROB + Reservation Station + Register File
reg [4:0] rob_rd [0:NUM_ROB-1];
reg [31:0] rob_result [0:NUM_ROB-1];
reg rob_valid [0:NUM_ROB-1];
reg rob_ready [0:NUM_ROB-1];
reg [2:0] rob_head, rob_tail;
// ... 保留站、寄存器文件等
// 完整代码见 verilog/oob_core.v
endmodule
Verilator仿真验证通过 — 乱序执行核心正确:指令乱序执行,按序提交
代码解析
- Dispatch:为每条指令分配ROB项和保留站项
- Execute:保留站中操作数就绪的指令可执行——不按程序顺序
- Commit:ROB头指针处指令完成后才提交——保证程序序
- 关键:即使ADD在第5拍完成、SUB在第3拍完成,ADD仍然先提交
📊 乱序执行性能对比
| 处理器 | 发射宽度 | ROB大小 | IPC(SPEC) | 年份 |
| BOOM v3 | 3 | 40 | ~1.5 | 2023 |
| SiFive P870 | 8 | 128+ | ~2.5 | 2024 |
| 香山南湖 | 6 | 96 | ~2.0 | 2024 |
| ARM Cortex-A76 | 4 | 128 | ~2.3 | 2018 |
| Apple M1 Firestorm | 8 | ~350 | ~3.5 | 2020 |
ROB大小直接影响乱序窗口大小——更大的ROB意味着可以"看"到更远的指令,找到更多并行性。Apple M1的超大ROB是其高IPC的关键之一。
🔧 乱序执行的挑战
- 功耗:OoO核心功耗是顺序核心的3-5倍,主要是CAM查找功耗
- 面积:BOOM v3的面积约为同配置Rocket的4倍
- 验证复杂度:需要证明所有可能的执行顺序都产生正确结果
- 分支预测失败代价:OoO核心需要冲刷更多状态
2024年研究:对于嵌入式和IoT场景,顺序核心(如Rocket)的能效比仍然优于OoO核心。OoO适合需要最大性能的场景。
🧪 实验练习
- 添加寄存器重命名:用物理寄存器替代架构寄存器
- 实现CDB(公共数据总线):广播结果到所有保留站
- 添加分支预测失败恢复:冲刷ROB和保留站
- 实现多发射:每周期dispatch/execute多条指令
指令乱序但结果正确 — OoO核心的基本原理
思考题:如果ADD x5, x1, x2和SUB x6, x5, x3连续执行,SUB什么时候可以在OoO核心中执行?需要什么条件?
参考资料:BOOM处理器文档 docs.boom-core.org | Computer Architecture §3-4 | RISC-V OoO设计 ScienceDirect 2024
📊 乱序执行性能对比
| 处理器 | 发射宽度 | ROB大小 | IPC(SPEC) | 年份 |
| BOOM v3 | 3 | 40 | ~1.5 | 2023 |
| SiFive P870 | 8 | 128+ | ~2.5 | 2024 |
| 香山南湖 | 6 | 96 | ~2.0 | 2024 |
| ARM Cortex-A76 | 4 | 128 | ~2.3 | 2018 |
| Apple M1 Firestorm | 8 | ~350 | ~3.5 | 2020 |
ROB大小直接影响乱序窗口大小——更大的ROB意味着可以"看"到更远的指令,找到更多并行性。Apple M1的超大ROB是其高IPC的关键之一。
🔧 乱序执行的挑战
- 功耗:OoO核心功耗是顺序核心的3-5倍,主要是CAM查找功耗
- 面积:BOOM v3的面积约为同配置Rocket的4倍
- 验证复杂度:需要证明所有可能的执行顺序都产生正确结果
- 分支预测失败代价:OoO核心需要冲刷更多状态
2024年研究:对于嵌入式和IoT场景,顺序核心(如Rocket)的能效比仍然优于OoO核心。OoO适合需要最大性能的场景。
🎯 本课与整体课程的关系
处理器性能优化知识图谱:
┌─────────────────────────────────────────────┐
│ 顺序执行 (L01-14) │
│ 特权架构→CSR→异常→中断→PLIC→CLINT │
│ 虚拟内存→TLB→Cache→乘除法 │
│ ↓ │
│ ┌─────────────────────────────────────┐ │
│ │ 乱序执行 (L15-19) │ │
│ │ OoO核心→ROB→寄存器重命名→记分牌 │ │
│ │ →Tomasulo算法 │ │
│ └─────────────────┬───────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────┐ │
│ │ 分支预测 (L20-21) │ │
│ │ 2位预测→BTB │ │
│ └─────────────────┬───────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────┐ │
│ │ RISC-V扩展 (L22-26) │ │
│ │ RVC→RVM→RVA→RVF→RVD │ │
│ └─────────────────┬───────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────┐ │
│ │ 系统集成 (L27-30) │ │
│ │ PMP→解码器→SoC→启动流程 │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────┘