RKNPU 块内部结构解析

硬件架构 讲的是系统级结构(块、流水线、内存、核)。本页拆到 每个块的内部结构与寄存器语义:CNA 的两个加载器与权重解压、CORE 的 MAC/CACC、 DPU 的 SDP 流水与 LUT、PPU 的池化、以及 DMA 仲裁。素材仍来自 rockchip-npu-notes[1],证据标签保留。

1. 张量在块间的形态:cube 布局

NPU 以 NVDLA 式分块 cube 布局读写 DRAM,带一个原子通道块(记为 C2)。没有 寄存器能转换布局,所以权重必须在主机预打散;而矩阵乘的激活与输出可以只靠 stride 保持行主序[1]。逐数据类型的 A / B / C 布局(主机侧 packing 的目标)是[1]:

数据类型 A(feature) B(weight) C(output)
fp16 [K/8, M, 8] [N/16, K/32, 16, 32] fp32 [N/4, M, 4] / fp16-narrowed [N/8, M, 8]
int8 [K/16, M, 16] [N/32, K/32, 32, 32] int32 [N/4, M, 4]
int4 [K/32, M, 32] [N/64, K/32, 64, 32] int16 [N/8, M, 8]
int16/bf16 [K/8, M, 8] [N/16, K/32, 16, 32] int32/fp32 [N/4, M, 4]
tf32 [K/4, M, 4] [N/16, K/16, 16, 16] fp32 [N/4, M, 4]

三条通用规则[1]:

  • 特征原子 C2=16 B/元素字节C2 = 16\text{ B}/\text{元素字节}:fp16/bf16/int16 = 8,int8 = 16, int4 = 32,tf32 = 4;
  • 权重分组:N-group 随元素变小而变大(fp16 16 / int8 32 / int4 64), K-group 在 2 字节类型是 32,tf32 是 16(4 字节把 K-group 减半);tf32 仍是 1024 B 的 tile(16·16·4);
  • 输出 C2 只由输出元素大小决定:2 字节输出 C2=8C2=8,4 字节输出 C2=4C2=4。 fp16 输入的 fp32 累加输出与 int8/bf16/tf32 用的是同一个 C2=4 cube。
⚠️ 单 K-group 陷阱:在"只有一个 K 组"的形状上(K=32,或 tf32 的 K=16),权重

索引对任意分组都退化为行主序,无法区分 K-group 16 与 32。反推权重布局时必须在 K≥2×K \ge 2\times候选 K-group 处测。int4 的 N-group 64 有同型陷阱[1]。

2. CNA:两个加载器 + 权重解压

CNA 对应 NVDLA 的 CDMA(卷积 DMA)+ CSC(序列控制器),在 RK 上合成一个块[1], 内部可拆成三部分:

(a) 特征 / 权重加载器。 按行 stride 与面 stride 寻址,把 feature tile 与 weight tile 读进 CBUF。它只做寻址搬运,不重排——布局由主机负责[1]。

(b) DCOMP 权重解压。 DCOMP(NVDLA CC/CDMA 的对应物)把稀疏压缩的权重流展开并 跳过零权重。寄存器映射目前只解出 dense 直通模式:DCOMP_CTRL=0、 DCOMP_REGNUM=0、DCOMP_ADDR0=<weight base>。压缩格式是 NVDLA 的 CWT/WMB/WGS(压缩权重 / 位掩码 / 组大小),但没有压缩程序的实机 capture, 解压模式的使能值未确认[1]。整数与 fp16 的权重 tile 分组正好等于 CWT 的 kernel group (int8 = 32,fp16/int16 = 16)[1]。

(c) CBUF 配置。 CNA_CBUF_CON0(0x1040)同时携带 bank 计数与复用位[1]:

字段 位 含义
DATA_BANK[3:0] 3:0 特征 tile 占的 bank 数
WEIGHT_BANK[7:4] 7:4 权重 tile 占的 bank 数
FC_DATA_BANK[10:8] 10:8 全连接模式的起始 bank;conv 路径也生效,必须保持 0
DATA_REUSE 12 复用上一 task 的特征 tile
WEIGHT_REUSE 13 复用上一 task 的权重 tile

两个坑:int8 特征 DMA 会多读一个 bank,要 data_bank = ceil(bytes/bank)+1 (fp16 免疫)[1];FC_DATA_BANK 一旦置 1..7,conv/matmul 输出会大面积算错 (数据仍然按时算完,只是读了错的 bank)[1]。

卷积模式:CONV_CON1 是 4-bit CONV_MODE,已知只有 0(direct)在用;另有 Rockchip 追加的反卷积模式(CONV_CON1[16] DECONV + CONV_CON3 的 y/x stride), 可在一个 task 内算 power-of-two stride 的 ConvTranspose,NVDLA 无此引擎[1]。

3. CORE:MAC 阵列 + 宽累加

CORE 对应 NVDLA 的 CMAC + CACC[1]:

  • CACC 在一个硬件层内跨 stripe 累加,宽度 INT34 / INT48 / FP44,层末按 CORE_CLIP_TRUNCATE(0x301C)舍入并饱和到 INT32 / FP32;
  • 没有跨层累加,这是 K 分块必须回读的根因;
  • 输入 / MAC / 输出各级的精度由 3-bit precision 字段独立选择(见 硬件架构 §5)。
💭 CORE 不是"输出尺寸 / 格式单元"。卷积的输出几何由 CNA 几何寄存器定义、

由 DPU 写出落实;CORE 只负责乘加与累加。

4. DPU:SDP 流水(BS → BN → EW/LUT → OUT_CVT)

DPU 对应 NVDLA 的 SDP,是后处理数据通路。与卷积 / matmul 相关的部分按级串联[1]:

flowchart LR A[conv / CACC 累加结果] --> BS[BS 级

per-channel 缩放] M[MRDMA / ERDMA] --> BS BS --> BN[BN 级

mul + bias] BN --> EW[EW 级

eltwise add/mul

LUT 查表] EW --> CVT[OUT_CVT

requant / 浮点仿射] CVT --> WDMA[WDMA 写回 DDR]
  • BS / BN / EW 对应 NVDLA 的 X1 / X2 / Y:BS 做逐输出通道缩放,BN 做仿射, EW 做逐元素 add/mul(残差、门控)。EW 还有整数模式(int8/int16/int32 的 MAX/MIN/ADD 等)[1]。
  • LUT 是 NVDLA 的 LE/LO hybrid:两张 513 项表(负/正分支)走 Q0.15, 硬件线性插值、越界按斜率外推。用它可以整块算 sigmoid / tanh / SiLU / GELU / sqrt / rsqrt / reciprocal / exp。LUT 走 BN→LUT→OUT_CVT 的独立 DPU pass, 不经过 CNA/CORE[1]。
  • OUT_CVT 是写回前最后一级[1]:
    • 整数 requant(matmul / conv 路径): y=sat(round(acc×SCALE≫SHIFT)+OFFSET)y=\mathrm{sat}\big(\mathrm{round}(\text{acc}\times\text{SCALE}\gg\text{SHIFT})+\text{OFFSET}\big), SCALE 是 带符号 15-bit 整数乘子(bit15 为符号),且 BS 级按输出通道逐个 缩放,可承载 TFLite 的 per-axis scale;
    • rounding:OUT_CVT_SHIFT[30] 选 half-to-even(默认,全体栈与厂商程序都写 0) 或 half-away-from-zero(NVDLA 文档规则);
    • 浮点仿射(LUT 路径):cvt_type=1 时 y=(q+offset)⋅2−minus_expy=(q+\text{offset})\cdot2^{-\text{minus\_exp}} 再窄化到 fp16。

DPU-RDMA 有两个读源:MRDMA(主数据)与 ERDMA(eltwise 操作数)。 DPU_RDMA_FEATURE_MODE_CFG(0x5044)用 flying_mode(bit0)与 mrdma_disable (bit4)控制。普通卷积 / matmul 必须 mrdma_disable=1,否则 RDMA 等一个永不到来的 数据、job 静默超时、输出未写(MRDMA trap);反过来,eltwise / fp16 K 累加路径又必须 把 MRDMA 供上、并 arm ERDMA[1]。配错会卡住 NPU,需要 rmmod/insmod 复位。

❗ 13-bit 立方体上限:DPU_DATA_CUBE_WIDTH/HEIGHT/CHANNEL 等字段是 13 bit,

上限 8191。踩到边界(如 cols=8191)会静默损坏少量元素;要远低于上限做 tile (栈用 DPU_LUT_MAXN=32768,cols=4096)。CNA 的输入宽高更窄,只有 11 bit, 是卷积的约束[1]。

5. PPU:平面池化

PPU 对应 NVDLA 的 PDP(+ PPU-RDMA 对应 PDP-RDMA),跑 max / average pooling, 按空间轴归约。它不能做通道轴归约——特征轴归约只能表达成"全 1 权重"的矩阵乘[1]。

6. DMA 与仲裁

DDMA / SDMA 对应 NVDLA 的 MCIF / SRAMIF:各有 5 个读客户端 (FEATURE / KERNEL / DPU / PDP / PC),带 per-client 仲裁权重与 2-bit QoS,另有 outstanding 上限与 AXI 属性。现有栈与 Mesa 都不写它们;idle 核上读 outstanding 已是 8-bit 上限、各客户端等权,默认读路径不受 outstanding 限制[1]。

7. 结构能力边界汇总

块 能做 不能做
CNA 特征 / 权重搬运、权重解压、direct / deconv 卷积几何 布局变换、gather/scatter、索引读
CORE MAC + 宽位累加、饱和截断 跨层累加
DPU BS/BN/EW 仿射、逐元素、LUT 非线性、整数 requant 通道轴归约(需要全 1 matmul)
PPU 空间轴 max/avg 池化 通道轴归约、de-tile
DDMA/SDMA 内存读写与仲裁 字节计数(无可用计数器)

参考文献

[1] GREGORDINARY. Rockchip NPU reverse-engineering notes[EB/OL]. (2026)[2026-10-09]. https://github.com/gregordinary/rockchip-npu-notes/tree/81b0d17da0b8a472c1a1e6f7d2ddba6b34d10111

[2] GREGORDINARY. rocket-userspace: include/npu_hw.h[EB/OL]. (2026)[2026-10-09]. https://github.com/gregordinary/rocket-userspace/blob/f86cf52c666b4eddadc17d80d6c558b4067c0d6b/include/npu_hw.h#L25-L33


© 2026 Yang Huan · yanghuan9812@qq.com

results matching ""

    No results matching ""