# 算力单元

# 算力单元详细设计

把 [[Pipe]] 第 6 节 §208 的算力单元抽象展开到 RTL 起手前。每个计算实例 = 一条 engine pipe 实例。

#### 0. 与 DMA 的同构关系

算力单元与 [[DMA]] **结构同构**：都是"engine pipe 集合 + sync pool + 控制接口 + 共享数据 fabric master"。差别仅在执行通路：

| | DMA | 算力单元 |
|---|---|---|
| 执行通路 | 读 → transform → 写 | 读 → 计算阵列 → 写 |
| 数据端 | 被动单元（L1、DRAM） | 被动单元（L1、DRAM） |
| 内部状态 | transform buffer | L0 寄存器组 |
| cmd_desc 专属字段 | xform_flags, xform_params | compute_op, loop, dtype, accum |

下文凡是结构与 DMA 一致的，引用 [[DMA]] 不重复展开；只描述差异。

#### 1. 顶层参数

| 参数 | 含义 | 默认 | 备注 |
|---|---|---|---|
| `N_CU` | 计算实例数（每个 = 一条 engine pipe） | 4 | 可异质（见 §13） |
| `N_SYNC` | sync counter 数 | 32 | |
| `Q_MAX` | 单实例命令队列硬件上限 | 16 | 2 的幂 |
| `K_IN / K_OUT / K_SIG` | cmd_desc 列表上限 | 4/4/4 | |
| `N_L0_VEC` | 每实例 L0 向量寄存器数 | 8 | |
| `N_L0_TEN` | 每实例 L0 张量寄存器数 | 4 | |
| `VEC_LANE` | 向量阵列 lane 数 | 16 | INT8 lane |
| `MAC_M / MAC_K` | 2D MAC 阵列尺寸 | 8 / 8 | systolic |
| `MAC_ACC_W` | MAC 累加器位宽 | 32 | INT32 |
| `OUT_TYPE_SET` | 可选输出位宽 | {8, 16, 32} | round/sat 软件控 |
| `LOOP_W` | inner-loop 计数器位宽 | 16 | |
| `STRIDE_DIM / STRIDE_W / SHAPE_W` | 同 [[DMA]] | 3 / 32 / 24 | |
| 其他 `COUNT_W / HANDLE_W / ADDR_W / NOC_W` | 同 [[DMA]] | | |

#### 2. 顶层框图

```
                    ┌────────────────── 算力单元 ────────────────┐
ctrl_s ──────────► │ ctrl 解码 + 路由 ─► CU Pool Mgr            │
ctrl_s ◄────────── │                  ─► Sync Pool              │
                   │                                              │
                   │   ┌───────── CU[0] ─────────────┐            │
ctrl_m ◄───────────┤   │  cmd queue (SRAM, Q_MAX)    │            │
ctrl_m ──────────► │   │  完成计数器                  │            │
                   │   │  执行 FSM                    │            │
                   │   │  in/out 地址生成器           │            │
                   │   │  L0 vreg[]  treg[]           │            │
                   │   │  计算阵列(标量/向量/2D MAC)   │            │
                   │   │  Notify FIFO                 │            │
                   │   └─┬─────────────────┬──────────┘            │
                   │     │                 │                       │
                   │   CU[1] ...        CU[N_CU-1]                 │
                   │     │                 │                       │
noc_rd ◄───────────┤   NoC 读仲裁 ◄──── 各 CU 的 LOAD 通路         │
noc_wr ◄───────────┤   NoC 写仲裁 ◄──── 各 CU 的 STORE 通路        │
                   └─────────────────────────────────────────────────┘
```

#### 3. 顶层端口

完全复用 [[DMA]] §3 的端口。差别：
- `noc_rd_*` / `noc_wr_*` 可对接任意被动单元（L1、DRAM），目标由 cmd_desc 内的 in/out handle.unit_addr 决定
- `ctrl_s_*` / `ctrl_m_*` 协议完全一致

#### 4. cmd_desc 字段编码

总宽 ≤ 1024 bit。与 [[DMA]] §4 同构，差别在 `op + 专属参数区`。

| 偏移 | 位宽 | 字段 | 说明 |
|---:|---:|---|---|
| 0 | 4 | `op` | 0=SCALAR_ALU, 1=VEC_ALU, 2=VEC_REDUCE, 3=MAC_2D, 4=ELEMENTWISE_ACT(ReLU/GELU), 5=SOFTMAX_PARTIAL, ... |
| 4 | 4 | `dtype_in` | 0=I8, 1=I16, 2=I32, 3=FP8(预留), 4=FP16(预留) |
| 8 | 4 | `dtype_out` | 同上 |
| 12 | 2 | `accum_mode` | 0=覆盖, 1=累加（C += A*B）, 2=累加+饱和 |
| 14 | 2 | `act_kind` | ELEMENTWISE 时的激活函数选 |
| 16 | 16 | `loop_count` | inner-loop 次数；硬件按此自动 step 地址生成器 |
| 32 | 48 | `src_a_base` | byte_addr（落在某条被动单元 pipe 内，见 [[L1]] §4.1 / [[DRAM]] 地址映射） |
| 80 | 96 | `src_a_stride[3]` | |
| 176 | 72 | `src_a_shape[3]` | |
| 248 | 48 | `src_b_base` | MAC_2D / VEC_ALU 用 |
| 296 | 96 | `src_b_stride[3]` | |
| 368 | 48 | `dst_base` | |
| 416 | 96 | `dst_stride[3]` | |
| 512 | 72 | `dst_shape[3]` | |
| 584 | 8 | `l0_a_reg` | A 操作数落到哪个 L0 寄存器 |
| 592 | 8 | `l0_b_reg` | |
| 600 | 8 | `l0_c_reg` | 结果累加目标 |
| 608 | 4+4+4+4 | `n_in / n_out / n_sig / _` | |
| 624 | 96 | `in_list[4]` | 每项 {handle:16, delta:8} |
| 720 | 96 | `out_list[4]` | |
| 816 | 96 | `sig_list[4]` | |
| 912 | 112 | reserved/padding | |

`src_b_*` 仅对二元算子（MAC / VEC_ALU）有效；一元算子（激活、reduce）写 0。

#### 5. 控制总线协议

完全同 [[DMA]] §5。多 beat `PSEND` 同样 8 × 128 bit。opcode 表共享。

#### 6. CU Pool 管理器

结构同 [[DMA]] §6。差别：
- `meta[N_CU]` 多一个 `cu_class` 字段（标量 / 向量 / MAC，若异质例化）
- PALLOC 时 `params.cu_class` 必须与本实例 class 匹配；不匹配视为软件错（行为未定义）

#### 7. CU 执行通路（×N_CU）

##### 7.1 命令队列

完全同 [[DMA]] §7.1。

##### 7.2 完成计数器

完全同 [[DMA]] §7.2。

##### 7.3 执行 FSM

```
                  ┌────────────────────────────────────┐
                  ▼                                    │
            ┌─────────┐  queue 非空           ┌────────┴───┐
            │  IDLE   ├─────────────────────► │   FETCH    │
            └─────────┘                       └────────┬───┘
                                                       ▼
                                              ┌────────────┐
                                              │  WAIT_IN   │
                                              └────────┬───┘
                                          all in 到位   │
                                                       ▼
                                              ┌────────────────────┐
                                              │  ISSUE 流水         │
                                              │   ├─ LOAD  (L1→L0) │
                                              │   ├─ COMPUTE       │
                                              │   └─ STORE (L0→L1) │
                                              │   (loop_count 次)   │
                                              └────────┬───────────┘
                                                       ▼
                                              ┌────────────┐
                                              │  NOTIFY    │
                                              └────────┬───┘
                                                       ▼
                                              ┌────────────┐
                                              │  DONE      │  count++ tail++
                                              └────────┬───┘
                                                       └──► IDLE
```

| 状态 | 时长 | 行为 |
|---|---|---|
| IDLE | 1 cycle | |
| FETCH | 1 + (STRIDE_DIM-1) cycle | 读 cmd_desc + 预算 stride wrap_delta（同 DMA §7.4） |
| WAIT_IN | 不定 | 顺序 COUNT_QUERY in_list |
| ISSUE | 流水，见 §7.6 | |
| NOTIFY | (n_in + n_out + n_sig) cycle | 入 Notify FIFO |
| DONE | 1 cycle | |

##### 7.4 L0 寄存器组

| 项 | 规格 |
|---|---|
| `vreg[N_L0_VEC]` | 每个 `VEC_LANE × dtype_in_bits` 宽；存 vector 操作数 / 结果 |
| `treg[N_L0_TEN]` | 每个 `MAC_M × MAC_K × dtype_in_bits` 宽；存 tile 操作数 |
| 端口 | vreg: 2R/1W；treg: 2R/1W（FMA 类够用） |
| 复位 | **不复位**（undefined），软件必须先 LOAD 才用 |
| 共享 | 实例私有，不跨 CU 共享 |

实现：vreg 用 register file（small），treg 用 SRAM macro（一个 treg ≈ 8×8×8 = 512 bit，N_L0_TEN = 4 时 2 KiB）。treg SRAM 端口配 2R/1W 满足 MAC 2 输入 1 累加。

vreg 与 treg 物理分离 —— 二者访问宽度差很大。

##### 7.5 计算阵列

三类阵列共存（每个实例可裁掉某类，按 cu_class 决定）：

###### 7.5.1 标量

- 1 lane，宽度 `max(dtype_in, dtype_out)` ≤ 32 bit
- op：ADD/SUB/MUL/SHIFT/CMP/SELECT/BIT
- latency 1 cycle，throughput 1/cycle

###### 7.5.2 向量

- `VEC_LANE` 路并行 INT8 ALU + 16-bit accumulator option
- op：lane-wise ADD/SUB/MUL/MAC/CMP，跨 lane REDUCE_SUM/MAX/MIN
- latency 1-2 cycle，throughput 1/cycle
- elementwise activation：LUT 表（4 KiB ROM/SRAM）实现 ReLU / GELU / sigmoid 等

###### 7.5.3 2D MAC

- `MAC_M × MAC_K` systolic 阵列
- 单元：INT8 × INT8 → INT16 partial → 累加进 MAC_ACC_W 寄存器
- 输入：A treg (M × K), B treg (K × N，本设计 N = MAC_M)；权重和激活方向可在 cmd_desc 内对调
- 输出：C treg (M × N)，累加进已有 treg（accum_mode）
- pipeline depth = `MAC_K + 2` cycle
- 每 cycle 注入一行 A、一列 B；MAC_M = MAC_K = 8 时 8 cycle 填满，第 9 cycle 起每 cycle 一个稳态结果

下溢 / 上溢 / round：cmd_desc.dtype_out 与 accum_mode 决定输出阶段的 saturate + truncate / round_to_nearest。专用硬件块（输出后处理 stage）实现。

##### 7.6 LOAD/COMPUTE/STORE inner-loop 流水

把一条 cmd 拆成 `loop_count` 次 micro-op，三级流水：

```
cycle:  N   N+1   N+2   N+3   N+4   N+5
        │    │     │     │     │     │
LOAD    op0  op1   op2   op3   op4   op5
COMPUTE      op0   op1   op2   op3   op4
STORE              op0   op1   op2   op3
```

- L0 寄存器组作为级间 buffer：LOAD 写、COMPUTE 读 + 写、STORE 读
- 软件用 `l0_a_reg / l0_b_reg / l0_c_reg` 指定不同 op 用哪些 reg，硬件按 `op_id % N_L0_REG` 做 cyclic 调度避免读写冲突
- leading 2 cycle 只 LOAD（COMPUTE/STORE 等数据）；tailing 2 cycle 只 STORE
- inner-loop 内不可中断 / 不可被外部 stall（除 NoC backpressure）

##### 7.7 in / out 地址生成器

每实例 3 个独立累加器（A、B、C）。复用 [[DMA]] §7.4 的累加器实现。差别：

- 目标地址落在被动单元（L1 / DRAM）的地址空间内
- inner-loop 由 `loop_count` 驱动，与 `shape[3]` 一起决定终止
- 地址生成单次给一个 NoC 请求；burst 长度 = 一拍 L0 寄存器宽度 / NOC_W（典型 1 beat）

##### 7.8 Notify FIFO

完全同 [[DMA]] §7.6。

#### 8. Sync Pipe Pool

完全同 [[DMA]] §8。

#### 9. 共享资源仲裁

##### 9.1 NoC 读 / 写

结构同 [[DMA]] §9.1。NoC 主端可对接 L1 / DRAM；对接 L1 时可按低延迟假设缩 outstanding 深度，对接 DRAM 时按 DRAM 延迟特性配置。

##### 9.2 ctrl_m 主端

完全同 [[DMA]] §9.2。

##### 9.3 ctrl_s 解码路由

完全同 [[DMA]] §9.3。差别：PALLOC 时 `params.cu_class` 决定走哪个 cu_class 的子池。

#### 10. 跨子模块协议要点

##### 10.1 CU ↔ pending wait CAM

同 [[DMA]] §10.1。

##### 10.2 CU ↔ ctrl_m

同 [[DMA]] §10.2。

##### 10.3 CU ↔ NoC（对接被动单元）

- LOAD：CU 发 noc_rd_req 给被动单元（L1 / DRAM，master），地址按 §7.7 生成；resp 数据按 req_id 路由到 CU 的 L0 写口
- STORE：CU 发 noc_wr_req + wr_data 给被动单元；不等 ack（fire-and-forget），NOTIFY 中的 COUNT_DELTA 由 CU 内部 FSM 在 STORE 流水尾部排出（保证落到目标单元后才发，由 NoC 同 id 同地址保序保证）

##### 10.4 同 cmd_desc 内 in 与 out 包含同一 pipe

参见 [[Pipe]] §289：合法用法。硬件执行顺序：
1. WAIT_IN 阶段查询该 pipe 的 count ≥ in 阈值
2. LOAD 阶段读被动单元（数据已在）
3. COMPUTE
4. STORE 阶段写被动单元
5. NOTIFY 阶段：对该 pipe 先发 `COUNT_DELTA(-in_delta)`，再发 `COUNT_DELTA(+out_delta)`

被动单元端按到达顺序应用即可。In-place 累加的语义保证依赖 NoC 同 id 同地址保序。

#### 11. 复位与启动

| 信号 / 状态 | 复位值 |
|---|---|
| 同 [[DMA]] §11 全部项 | |
| L0 vreg / treg | **不复位**（undefined） |
| 计算阵列 pipeline 寄存器 | 复位 |
| MAC 累加器 | 0 |

L0 不复位的影响：未 LOAD 就 COMPUTE 是软件 bug，硬件不阻止；结果未定义。

#### 12. 调试可观测点

同 [[DMA]] §12，加：

| 信号 | 宽度 | 用途 |
|---|---|---|
| `dbg_cu_state[N_CU]` | N_CU × 3 | 每 CU FSM 状态 |
| `dbg_mac_active[N_CU]` | N_CU | MAC 阵列在跑 |
| `dbg_inner_loop_idx[N_CU]` | N_CU × LOOP_W | 当前 micro-op 序号 |
| `dbg_l0_read_hazard[N_CU]` | N_CU | LOAD/COMPUTE 同 reg 冲突计数（应为 0） |
| `dbg_pipeline_stall_cycles[N_CU]` | N_CU × 16 | NoC backpressure 累计 stall |

#### 13. 待规格化参数

1. `N_CU` 与异质组合（如 1 个 2D MAC 实例 + 2 个向量实例 + 1 个标量实例 vs 同质）
2. `VEC_LANE / MAC_M / MAC_K` 实际规模 —— 直接决定算力
3. `dtype` 支持集合（INT4 / FP8 / FP16 / BF16）
4. MAC 阵列拓扑（systolic 1D vs 2D，weight-stationary vs output-stationary）
5. L0 寄存器组的实际端口数（FMA 用 3R+1W 还是分段 2R+1W）
6. inner-loop 流水级数（3 级 vs 4 级，多一级换 stall 余裕）
7. 输出 round / saturate 硬件块的位宽
8. 是否例化激活函数 LUT 共享还是 per-CU 独立

#### 14. 关联回 Pipe 抽象

| 抽象层概念 | 本文档落点 |
|---|---|
| engine pipe 契约 | §7.1 队列 + §7.2 count + §7.3 FSM |
| sync pipe 契约 | §8 |
| 落地 A | §6 + §8 各自独立 bitmap |
| 落地 B | §3 ctrl vs noc 物理分开 |
| 落地 D | §8 sync 独立 |
| 特性 3（单 pipe 不分叉） | §7.3 FSM 单 channel 严格串行 |
| 特性 6（硬件零检查） | §5 / §6 / §7.4 L0 未初始化不报警 |
| 特性 7（参数创建即不可变） | §6 alloc 后 cu_class / queue_depth 定死 |
| 特性 8（三类 pipe） | engine 在 §7，sync 在 §8 |
| §289（in/out 同 pipe） | §10.4 NOTIFY 顺序 |