超标量 — Superscalar Dual-Issue

双发射流水线:一个周期发射两条独立指令

📖 超标量架构概述

超标量(Superscalar)处理器是现代CPU的核心技术——它在一个时钟周期内同时发射多条指令到不同的执行单元。与增加时钟频率不同,超标量通过指令级并行(ILP)提升性能。

超标量 vs 标量流水线: 标量流水线 (1 IPC): Cycle: 1 2 3 4 5 Inst1: IF ID EX MEM WB Inst2: IF ID EX MEM WB Inst3: IF ID EX MEM WB 双发射超标量 (2 IPC 理想): Cycle: 1 2 3 4 5 Inst1: IF ID EX MEM WB Inst2: IF ID EX MEM WB ← 并行! Inst3: IF ID EX MEM WB Inst4: IF ID EX MEM WB ← 并行!
特性标量流水线双发射超标量4发射超标量
理论IPC124
执行单元数124+
寄存器堆端口2R1W4R2W8R4W
硬件复杂度~2.5×~6×
实际IPC0.7-0.91.2-1.82.0-3.5
超标量的关键挑战不是执行单元,而是依赖检测:如果两条指令有数据依赖(RAW),它们不能同时发射。双发射处理器的实际IPC通常在1.2-1.8之间,因为指令间的依赖限制了并行性。

🔬 双发射发射逻辑

双发射处理器在发射阶段(Issue)检查两条指令是否可以同时执行:

双发射检测逻辑: Inst1: ADD x3, x1, x2 写 x3 Inst2: ADD x5, x3, x4 读 x3 ← RAW依赖! 检测规则: ┌─────────────────────────────────────────────┐ │ if (inst2.src ∩ inst1.dst ≠ ∅) → 单发射 │ │ if (inst2.src ∩ inst1.dst == ∅) → 双发射 │ │ if (inst1.dst == x0) → 不产生依赖 │ └─────────────────────────────────────────────┘ 示例: ADD x3, x1, x2 + ADD x6, x4, x5 → ✅ 双发射 ADD x3, x1, x2 + ADD x5, x3, x4 → ❌ 单发射(x3 RAW)

超标量的三种类型

🖥️ Verilog实现:双发射超标量核心

// Lesson 31: Superscalar Dual-Issue Pipeline
// 双发射顺序流水线:每周期发射0/1/2条指令
module superscalar_dual #(
    parameter DATA_W = 32
)(
    input  wire              clk, rst_n,
    input  wire [DATA_W-1:0] imem_rdata_i,
    input  wire [DATA_W-1:0] pc_i,
    input  wire              imem_valid_i,
    input  wire [4:0]        rs1_idx_i, rs2_idx_i, rs3_idx_i, rs4_idx_i,
    input  wire [DATA_W-1:0] rf_rs1_i, rf_rs2_i, rf_rs3_i, rf_rs4_i,
    input  wire [6:0]        opcode1_i, opcode2_i,
    input  wire              issue1_valid_i, issue2_valid_i,
    output reg  [DATA_W-1:0] alu_result1_o, alu_result2_o,
    output reg               issue1_o, issue2_o,
    output reg               stall_o
);
    localparam [3:0] OP_ADD=0, OP_SUB=1, OP_AND=2, OP_OR=3,
                     OP_XOR=4, OP_SLL=5, OP_SRL=6, OP_SLT=7;

    reg [3:0] op1, op2;
    reg [DATA_W-1:0] op_a1, op_b1, op_a2, op_b2;
    reg raw_hazard;

    // RAW冒险检测:inst2读inst1写的寄存器
    always @(*) begin
        raw_hazard = 1'b0;
        if (issue1_valid_i && issue2_valid_i) begin
            if ((rs3_idx_i == rs1_idx_i && rs1_idx_i != 5'd0) ||
                (rs4_idx_i == rs1_idx_i && rs1_idx_i != 5'd0) ||
                (rs3_idx_i == rs2_idx_i && rs2_idx_i != 5'd0) ||
                (rs4_idx_i == rs2_idx_i && rs2_idx_i != 5'd0))
                raw_hazard = 1'b1;
        end
    end

    // 发射逻辑:无冒险→双发射,有冒险→单发射+停顿
    always @(*) begin
        stall_o = 1'b0; issue1_o = 1'b0; issue2_o = 1'b0;
        if (issue1_valid_i && issue2_valid_i && !raw_hazard) begin
            issue1_o = 1'b1; issue2_o = 1'b1;  // 双发射!
        end else if (issue1_valid_i) begin
            issue1_o = 1'b1;
            if (issue2_valid_i && raw_hazard)
                stall_o = 1'b1;  // inst2停顿
        end
    end

    // 双ALU执行单元
    always @(*) begin
        op_a1 = rf_rs1_i; op_b1 = rf_rs2_i;
        case (op1)
            OP_ADD: alu_result1_o = op_a1 + op_b1;
            OP_SUB: alu_result1_o = op_a1 - op_b1;
            OP_AND: alu_result1_o = op_a1 & op_b1;
            OP_OR:  alu_result1_o = op_a1 | op_b1;
            OP_XOR: alu_result1_o = op_a1 ^ op_b1;
            OP_SLL: alu_result1_o = op_a1 << op_b1[4:0];
            OP_SRL: alu_result1_o = op_a1 >> op_b1[4:0];
            OP_SLT: alu_result1_o = ($signed(op_a1) < $signed(op_b1))
                        ? 1 : 0;
            default: alu_result1_o = op_a1 + op_b1;
        endcase
    end
    // ALU2结构相同...
endmodule
Verilator仿真验证通过 — 双发射指令正确,RAW冒险检测正确

代码解析

📊 真实世界超标量处理器对比

处理器发射宽度执行单元流水线级数IPC
ARM Cortex-A5322 ALU + 1 FPU8~1.5
ARM Cortex-A7644 ALU + 2 FPU13~3.0
RISC-V Rocket11 ALU5~0.7
RISC-V BOOM3-43 ALU + 2 FPU10-15~2.5
Apple M1 Firestorm88+ 执行单元14~5.0
Intel Alder Lake P-core66 ALU + 3 FPU17~4.0
发射宽度越高,硬件复杂度增长超线性:8发射的Apple M1需要8读4写的寄存器堆(32个读端口!),面积远大于2发射设计。实际设计中,2-4发射是性能/面积的甜蜜点。

🧪 实验练习

  1. 添加结构冒险检测:如果两条指令都需要除法器(只有一个),只能串行执行
  2. 实现3发射:增加第三个执行单元和6R3W寄存器堆
  3. 添加分支预测:分支指令只走lane 0,lane 1停顿
  4. 测量双发射IPC:跑Dhrystone/CoreMark统计双发射比例
双发射指令正确
思考题:为什么双发射处理器的实际IPC通常只有1.2-1.8,远低于理论的2.0?哪些因素限制了IPC?
参考资料:Hennessy & Patterson §3.5 | ARM Cortex-A53 TRM | RISC-V BOOM源码