跳转至

执行单元与数据通路:从 Issue 到 Writeback

本文解释 XiangShan DefaultConfig 后端执行侧:Issue Queue 如何选择 uop、操作数怎样经过物理寄存器文件和旁路网络、整数/浮点/向量功能单元如何分配端口,以及为什么“操作数 ready”仍可能不能发射。目标是把软件性能现象映射到可验证的硬件资源。

版本与结论边界

  • 固定提交:c7b373b
  • 默认配置:DefaultConfigEnableBackendV2Config=falseParameters.scala:117-153
  • 文中“延迟”若来自 FuConfig,只表示配置中的流水延迟,不等于从软件视角测得的总 latency。
  • 源码事实 / 软件侧推导 / 待验证的含义与《后端总览》一致。

执行侧全景

flowchart LR
    DIS["Dispatch"] --> IQI["Integer / Memory IQ"]
    DIS --> IQF["FP IQ"]
    DIS --> IQV["Vector IQ"]

    IQI --> ARBI["Oldest-ready + FU/WB gate"]
    IQF --> ARBF["Oldest-ready + FU/WB gate"]
    IQV --> ARBV["Oldest-ready + FU/WB gate"]

    ARBI --> RFI["Int RF / RegCache"]
    ARBF --> RFF["FP RF"]
    ARBV --> RFV["VF / V0 / VL RF"]

    RFI --> BN["Forward / Bypass"]
    RFF --> BN
    RFV --> BN

    BN --> INT["ALU / MUL / DIV / BJU"]
    BN --> FP["FALU / FMAC / FDIV / FCVT"]
    BN --> VEC["Vector arithmetic + OG2"]
    BN --> LSU["LDU / STA / STD / VLSU"]

    INT --> WBA["Per-regfile WB arbiters"]
    FP --> WBA
    VEC --> WBA
    LSU --> WBA
    WBA --> PRF["Physical Register Files"]
    WBA --> ROB["ROB completion"]

    LSU -. "cancel / replay" .-> IQI
    VEC -. "OG failure" .-> IQV

每个执行 Region 都由 Issue Queue、DataPath、BypassNetwork、ExuBlock 和写回路径构成。Region.scala:38-57 ExuBlock 按参数实例化执行单元,并导出 BJU resolve、跨域数据和每个 EXU 的 fire 统计。ExuBlock.scala:18-95

DefaultConfig 的执行端口地图

以下是源码配置,不是对峰值吞吐的承诺。完整定义见 Parameters.scala:341-474

整数、分支与标量访存

Issue block 功能单元 支持的主要 FuType 关键写回
Int IQ0 ALU0 + BJU0 ALU、CSR、Fence;Branch、Jump Int WB0
Int IQ1 ALU1 + BJU1 ALU、Div;Branch、Jump Int WB1
Int IQ2 ALU2 + BJU2 ALU、I2F、I2V、VSet;Branch、Jump Int WB2,并跨写 FP/VF/V0/VL
Int IQ3 ALU3 ALU、BKU Int WB3
Int IQ4 ALU4 ALU、Mul Int WB4
Int IQ5 ALU5 ALU、Mul Int WB5
Load IQ0–2 LDU0–2 标量 Load Int WB6–8,也可写 FP
Store addr IQ0–1 STA0–1 Store 地址 无普通数据目的写回
Store data IQ0–1 STD0–1 Store 数据 无普通寄存器写回

直接的软件含义:

  • 简单整数 ALU 有 6 条候选通路,但 Div 只在 ALU1,BKU 只在 ALU3,Mul 只在 ALU4/5;特定 FuType 的真实吞吐远小于“6 ALU”。
  • 分支/跳转有 3 个 BJU 候选,仍会受到共享 IQ、整数源读取和 redirect 仲裁限制。
  • 有 3 个 LDU 不代表每周期必然完成 3 个 load;LQ、TLB、DCache bank、MSHR、地址依赖、写回端口和 replay 都可能限速。

浮点

Issue block 功能单元 能力
FP IQ0 FEX0 FALU、FMAC、FCVT、FCMP、F2V;可跨写 Int/VF/V0
FP IQ1 FEX1 FALU、FMAC、FDiv
FP IQ2 FEX2 FALU、FMAC、FDiv
FP IQ3 FEX3 FALU、FMAC

FDiv 仅出现在 FEX1/2;FCVT、FCMP 和 F2V 集中在 FEX0。混合这些操作时,不能只看“有 4 个 FP 执行单元”。

向量

Issue block 功能单元 能力
Vec IQ0 VFEX0 常用向量整数/浮点/乘加/转换/置 VL/移动
Vec IQ1 VFEX1 常用向量算术,另含 VFDiv、VIDiv
Vec mem IQ0 VLSU0 普通及 segment 向量 Load/Store
Vec mem IQ1 VLSU1 普通向量 Load/Store

向量算术通过额外的 OG2 阶段确认,向量访存进入 memory Region 后再合并写回。Region.scala:624-731 Og2ForVector.scala:15-70

Issue Queue:ready、selected、issued、success 是四件事

源码事实

IQ entry 分别保存 valid、issued、源 ready 和可发射状态。IssueQueue.scala:203-240

选择逻辑不仅检查所有源是否 ready,还检查目标 EXU 是否支持该 FuType、EXU 是否忙、预计写回端口是否忙。IssueQueue.scala:416-472

在符合条件的 entry 中,AgeDetector 优先选择程序顺序较老者。IssueQueue.scala:481-604 NewAgeDetector.scala:26-78

Div/FDiv 等不确定延迟单元使用专门的 wakeup queue;固定延迟结果则可按配置提前调度 wakeup。IssueQueue.scala:617-857

不同类型的 uop 会在 OG1、OG2、s0、s1、s2 或更后阶段才得到 finalSuccess;失败反馈会令 entry 保留或重试。IssueQueue.scala:1047-1083

软件侧推导

  • srcReady=1 只能证明依赖满足,不能证明有可用执行端口、RF 读口或 WB 时隙。
  • “issue 次数”对 load/向量工作可能包含最终失败的尝试;分析时应同时看 final success、cancel/replay。
  • oldest-ready 能改善公平性,但不会消除单一 FuType 的端口瓶颈,例如 Div、BKU、FCVT 或 segment VLS。

IQ 自带 enqueue/dequeue、占用、ready、issue 和数据来源统计。IssueQueue.scala:1092-1189

功能单元延迟:配置值与实测值的边界

CertainLatency 的总配置延迟由基础值和 extra latency 组成;UncertainLatency 用于除法、访存等完成时间不固定的操作。FuncUnit.scala:18-45

FuType 源码配置 备注
ALU / Branch / Jump 0 仍有 RF、选择、redirect 等外部阶段
Mul 2 默认有两条 Mul 候选通路
Div 不确定 仅 ALU1 支持
I2F 2 + 1 跨寄存器域
FALU 1
FMAC 3
FCVT 2 + 1 跨域结果可能共享低优先级端口
FDiv 不确定 仅 FEX1/2
VIALU 1 向量算术还经过 OG2
VIMAC 2 向量算术还经过 OG2
VFMA 3 向量算术还经过 OG2
VFDiv / VIDiv 不确定 集中在 VFEX1
Vector Load/Store 不确定 受 memory pipeline 和 replay 影响

配置来源:FuConfig.scala:229-386FuConfig.scala:545-900。向量 needOg2 和跨域额外延迟的组合见 ExeUnitParams.scala:188-269

待验证: 上表不能直接作为 llvm-mca、编译器 scheduling model 或手工汇编的最终 latency。应在目标生成 RTL 上测量 issue→wakeup、issue→WB 和 issue→commit,并区分依赖 latency 与吞吐。

物理寄存器文件与读取仲裁

寄存器文件的读地址寄存一拍,支持多写口;整数 x0 被硬连为零。另有 banked RF 实现。Regfile.scala:67-213

DataPath 分别实例化整数 RF/RegCache、FP RF、VF/V0/VL RF,并在 IQ 到 RF、RF 到执行输入之间执行端口仲裁。DataPath.scala:280-424 若读取或写回端口被阻塞,s0.ready 不能成立,失败会反馈 IQ。DataPath.scala:488-648

关键观测量包括:

  • IntRFReadBeforeArb / IntRFReadAfterArb
  • FpRFReadBeforeArb / FpRFReadAfterArb
  • VfRFReadBeforeArb / VfRFReadAfterArb
  • 每 EXU 的 forward、bypass、RegCache、RF、zero、immediate 来源

这些计数在 DataPath.scala:717-766 定义。

软件侧推导

BeforeArb - AfterArb 的持续差距,是 RF bank/读口压力比“高 IQ occupancy”更直接的证据。若 ready uop 很多、issue 很低且该差距明显,应优先研究寄存器读取压力、指令混排和跨域转换,而不是先归因于数据依赖。

Forward、Bypass 与 RegCache

BypassNetwork 支持同周期 forward、寄存一级 bypass,以及 vector/load 到 vector/memory consumer 的 bypass2。BypassNetwork.scala:103-143

每个源操作数可从 forward、bypass、bypass2、RF、RegCache、V0、zero 或 immediate 中选择。BypassNetwork.scala:180-220

软件侧推导

  • 短整数依赖链如果稳定命中 forward/bypass,可避免真正读取 RF;但消费者端口仍必须可用。
  • Load→use、FP→Int、Int→FP、Vector→Scalar 等路径的实际 latency 取决于跨 Region wakeup、旁路级和写回仲裁,不能套用简单 ALU 的经验值。
  • RegCache 命中率和 bypass 来源比例可帮助区分“物理 RF 压力”与“纯执行端口压力”。

Writeback:执行完成后仍可能排队

写回先按 Int、FP、VF、V0、VL 寄存器文件拆分并仲裁。向量 load 数据在进入公共写回前还要经过合并。WbArbiter.scala:112-253

不确定延迟执行单元允许被 backpressure;固定延迟单元若发生同端口碰撞则触发断言,要求参数配置从结构上避免冲突。只有真正 fire 的结果才会更新物理寄存器状态和 ROB。WbArbiter.scala:292-386

RFWBConflictChecker 为连续失败请求提高优先级,避免长期饿死。RFWBConflictChecker.scala:53-110

软件侧推导

  • Div、FDiv、Load 等不确定延迟结果同时返回时,可能在共享写回口排队。
  • I2F、F2I、FCVT、F2V、向量标量提取等跨域操作会使用其他寄存器文件的端口,有些配置为较低优先级;高密度转换代码需单独观察。
  • “EXU fire 很高但提交没有提升”时,应检查 WB fire、ROB 完成和 ROB head,而不是把发射率当作完成率。

整数、浮点、向量执行的边界

整数与分支

ExeUnit 根据配置实例化多个 FunctionUnit,在输入、控制和数据路径上加入相应流水级,并统一选择 Int/FP/Vec/V0/VL 结果。ExeUnit.scala:55-69 ExeUnit.scala:146-280

BranchUnit 检测方向或目标不一致并生成 redirect;JumpUnit 检查预测/固定目标并反馈误预测与训练信息。BranchUnit.scala:53-87 JumpUnit.scala:37-85

性能上需区分:分支执行端口是否饱和、预测是否错误、redirect 是否被更老事件覆盖,以及恢复 walk 是否成为主要代价。

浮点与跨域转换

FP 域既有确定延迟 FALU/FMAC,也有不确定延迟 FDiv。FEX0 还集中承担 FCVT、FCMP、F2V,并可能写回 Int/VF/V0 文件。默认 wakeup 拓扑允许 LDU 唤醒 FP consumer,并允许 FP 结果唤醒 store-data consumer。Parameters.scala:478-498

软件调优时,混合 FP compare/convert、FMA 和除法可能造成不均衡端口压力,即使总体 FP 指令比例不高。

向量算术与访存

向量算术写 VF,也可能写 V0、VL、Int 或 FP;其结果经过 OG2。向量访存 uop 则送到 memory Region,load 数据合并后返回向量写回。Region.scala:624-731

因此向量性能必须同时检查:

  1. Vec IQ 与特定 VFEX/VLSU 是否饱和。
  2. VF、V0、VL FreeList 是否短缺。
  3. old-vd、mask 和 VL 是否形成额外依赖。
  4. VF/V0/VL RF 读写仲裁。
  5. VLSU、DCache、TLB、LSQ 和 load replay。

诊断流程:从症状定位到硬件资源

flowchart TD
    A["IPC 或提交率低"] --> B{"ROB 接近满?"}
    B -->|是| C{"ROB head 等什么?"}
    C -->|Load| D["查 cache/TLB/LQ 与 replay causes"]
    C -->|Div/FDiv/VDiv| E["查长延迟依赖链与专用端口"]
    C -->|其他 EXU| F["查对应 IQ ready/issue/WB"]
    B -->|否| G{"Rename/Dispatch stall 高?"}
    G -->|FreeList| H["查 live range、展开、LMUL、提交延迟"]
    G -->|IQ/LSQ| I["查队列占用与结构限制"]
    G -->|否| J{"IQ ready 高但 issue 低?"}
    J -->|是| K["查 FU busy、WB busy、RF Before/AfterArb"]
    J -->|否| L["查数据依赖、wakeup 与前端供给"]

常见症状矩阵

现象 最有区分度的证据 典型解释 建议实验
IQ valid 高、ready 低 source-ready、select latency 真实数据依赖或生产者长延迟 改变展开/调度;缩短关键依赖链
ready 高、issue 低 FU/WB busy、RF Before/After 执行口、RF bank/读口或写回口竞争 改变指令混排;拆分跨域转换;降低同周期源读取
issue 高、WB/commit 低 WB fire、ROB completion/head 不确定延迟 WB 争用或 ROB 头阻塞 分离 Div/Load/转换;检查返回突发
Div/FDiv/VDiv head wait 高 对应 FuType latency、IQ occupancy 专用长延迟单元或串行依赖 reciprocal/strength reduction;增加独立工作
向量算术低吞吐 VecIQ、OG2 success、VF RF old-vd/mask/VL 或 VFEX 端口 调整 LMUL、tail/mask policy、展开
向量访存低吞吐 VLSU、replay、cache/TLB segment 单端口、未对齐、bank/地址依赖 对齐、改变 AoS/SoA、预取与访问顺序
分支多但 BJU 不忙 mispredict、recovery、walk 预测质量而非执行带宽 重排热路径、减少间接/数据相关分支

BackendV2Config:不要混用执行端口图

BackendV2ConfigEnableBackendV2Config 置真,并将 Decode/Rename 缩到 6、ROB 缩到 208、RAB 改为 256,同时改变物理寄存器 bank 配置。Configs.scala:447-490

它通过 BackendV2SchdParams 替换 DefaultConfig 的 scheduler:整数 ALU 从 6 个缩为 4 个,Mul/BKU 合并进 ALU2/3;FP 从 4 个 FEX 缩为 3 个;仍保留 3 LDU、2 STA、2 STD、2 个向量算术单元和 2 个 VLSU。BackendParams.scala:544-703

Parameters.scala 根据 EnableBackendV2Config 在默认 scheduler 和 V2 scheduler 间选择。Parameters.scala:503-517

因此:

  • 本文端口表仅适用于 DefaultConfig
  • V2 的 RF bank、端口编号、IQ 深度和 wakeup 图必须从 BackendV2SchdParams 单独阅读。
  • BackendV2Config 带弃用警告;除非目标 RTL 明确使用它,不应拿 V2 参数解释默认 XiangShan 性能。

待验证清单

  1. 用目标生成命令导出的最终参数确认 DefaultConfig 是否被 YAML、Config mixin 或本地 patch 覆写。
  2. 在仿真或 FPGA 上分别测量依赖 latency、执行吞吐、WB latency 和 commit latency;不要用 FuConfig 单一数字代替四者。
  3. 确认 XSPerf verbose/debug 计数是否综合进目标、是否接入 PMU,以及 Linux perf 驱动是否暴露。
  4. 对固定延迟 WB 冲突断言、RF bank 仲裁和跨域优先级,用生成 RTL/波形验证;源码参数描述的是构造规则,不是运行时测量。
  5. 向量 load 的“最终成功”路径与标量 load 不同,应在波形中同时观察 OG2、memory response、merge 和 WB fire。