Lec 9 超标量处理器
MIT 6.1920 · Constructive Computer Architecture 讲师:Martin Chan / Thomas Bourgeat · 日期:2024-03-07
1. 超标量的动机
提高 IPC(Instructions Per Cycle)的思路:
前面各节解决了分支/缓存缺失等问题,但 IPC 仍 ≤ 1。超标量(Superscalar)的思路:每周期同时发射(issue)和执行多条指令。
超标量处理器每周期可以取指、译码、执行、写回两条或更多条指令。宽度(issue width)为 2 的处理器称为 2-wide superscalar,理论 IPC 上限为 2。
2. Fetch 阶段扩展
挑战:同时取两条指令要求它们在同一 I-Cache 行中。
// 返回 1 或 2 条指令
typedef struct {Word ins1; Maybe#(Word) ins2;} OneOrTwoWords;
rule fetch;
toImem.enq(pcf);
f2d.enq1(F2D{pc: pcf, ppc: pcf+4, epoch: epoch});
if (!notLineBoundary(pcf)) begin // 同一 Cache 行
f2d.enq2(F2D{pc: pcf+4, ppc: pcf+8, epoch: epoch});
pcf <= pcf + 8;
end else
pcf <= pcf + 4;
endrule超标量 FIFO(SuperFIFO):支持每周期最多 2 次入队/出队:
interface SuperFIFO#(type t);
method Action enq1(t x);
method Action enq2(t x); // 隐含 enq1 已调用
method Action deq1;
method Action deq2; // 隐含 deq1 已调用
method t first1;
method t first2;
endinterface旋转实现(Rotating FIFO):用 2 个内部队列,轮换追踪最旧元素(currentDeq)和下一个写入位置(currentEnq)。
3. Decode 阶段扩展
同时译码两条指令,需处理指令间依赖:
if (noDependency(ins1, sb) && noDependency(ins2, sb) && noDependencyBetween(ins1, ins2)) begin
d2e.enq1("ins1"); d2e.enq2("ins2");
f2d.deq1; f2d.deq2;
end else if (noDependency(ins1, sb)) begin
d2e.enq1("ins1"); f2d.deq1; // 部分停顿(partial stall)
end
// else:完全停顿指令间依赖(Inter-Instruction Dependency):ins2 的源寄存器与 ins1 的目标寄存器相同时,ins2 必须等待 ins1 完成写回后才能读取正确值(或通过旁路解决)。
对所有(ins1, ins2)情况分类:
| ins1 状态 | ins2 状态 | ins2 依赖 ins1? | 操作 |
|---|---|---|---|
| 无依赖 | 无依赖 | 否 | 双发射 |
| 无依赖 | 无依赖 | 是 | 仅发射 ins1 |
| 有依赖(stall) | — | — | 停顿 |
Sol:覆盖所有 3×3 情况(ins1 ok/stall/cond × ins2 的对称情况),并在单元测试中逐一验证。
4. Execute 阶段扩展
结构冒险(Structural Hazard):
- ALU × 2:可以,复制两个 ALU
- 访存(Load/Store)× 2:困难(同一 D-Cache 端口冲突)
- 控制流 × 2:困难(分支重定向逻辑复杂)
实用简化策略:
- 两条均为 ALU → 双发射
- 任一含 Load/Store/Branch → 单发射
let ins1 = d2e.first1();
let ins2 = d2e.first2();
d2e.deq1(); // 至少处理 ins1
if (ins1 epoch 错误 && ins2 epoch 错误) begin
d2e.deq2(); squash both;
end else if (ins1 epoch 错误) begin
squash ins1; // ins2 下周期重试
end else if (isALU(ins1) && isALU(ins2) && ins2 epoch 正确) begin
d2e.deq2();
// 双 ALU 执行
end
// 其他情况只执行 ins15. Writeback 阶段扩展
- 寄存器文件需要 2 个写端口
- 计分板需要 2 个 insert / 2 个 search
- 若两条指令写同一寄存器:通常由硬件保证后者覆盖(ins2 > ins1)
EHR 与多端口:扩展 EHR 端口数以支持同周期多写,面积代价可通过 BRAM 替代 RegFile 来控制。
6. 性能提升
未来方向:同时多线程(Simultaneous Multithreading, SMT) — 多个线程共享同一超标量处理器,每周期从不同线程发射指令,填充单线程无法利用的槽位。
本讲总结
超标量处理器在每个流水线阶段都需要宽化:SuperFIFO 支持多路 enq/deq,Decode 处理指令间依赖矩阵,Execute 通过双 ALU 实现双发射(访存/控制仍单发),Writeback 需要多写端口;EHR 是解决多端口读写冲突的关键 BSV 原语。