新增elf分析
This commit is contained in:
@@ -0,0 +1,489 @@
|
||||
# Calculet NPU CCU ELF 静态逆向初步调查
|
||||
|
||||
日期:2026-08-02
|
||||
状态:第一轮静态逆向;未执行样本,未修改设备或模型
|
||||
对象:本仓库 CalRT Python 测试目录中的 YOLOv5s 单芯粒 CCU ELF
|
||||
|
||||
## 1. 结论摘要
|
||||
|
||||
本地 YOLOv5s 样本的 `ccu0_chip0.elf` 和 `ccu1_chip0.elf` 是两个真实的、可直接读取的 NPU 控制程序,不是 Git LFS pointer。它们是 stripped、静态链接的 ELF32 RISC-V 可执行文件,运行于两套不同地址窗口中的 CCU 控制核。
|
||||
|
||||
ELF 并非只包含标准 RISC-V 指令,而是至少混合三类编码:
|
||||
|
||||
1. 标准 RV32I/M/F/Zicsr 指令,用于启动、寄存器准备、栈、分支和 MMIO。
|
||||
2. 使用 RISC-V 保留 custom opcode 的 32 位 Calculet 指令;已稳定识别 opcode `0x2b`。
|
||||
3. 标准 binutils 无法识别、呈规则 8 字节分组的 Calculet 私有 CCU 指令包。
|
||||
|
||||
`ccu0_chip0.elf` 的顶层调度器顺序调用 149 个编译器生成的执行块。每个执行块末尾都有相同四条 32 位 custom 指令,随后恢复寄存器并返回。执行块内部交替出现标准 RV32 指令和大量私有 64 位包。这更像完整展开的静态 NPU 执行计划,而不是通用固件或包含权重的数据文件。
|
||||
|
||||
目前能够确认 ELF 的加载布局、入口初始化、顶层调用图、私有包边界、部分 MMIO 地址和外围 CCU CSR;尚不能在缺少私有 ISA、compiler/oplib 和算子 YAML 的情况下,把每个私有 opcode 精确命名为 GEMM、DMA、Conv 或同步操作。
|
||||
|
||||
## 2. 证据等级
|
||||
|
||||
本文使用以下标记,避免把猜测写成事实:
|
||||
|
||||
| 等级 | 含义 |
|
||||
|---|---|
|
||||
| F0 | ELF 字节、ELF header 或当前源码直接证明 |
|
||||
| F1 | 两个 ELF 或 ELF 与 HostRT/CSR 头文件交叉一致 |
|
||||
| H1 | 结构性推断,证据较强但缺厂商定义 |
|
||||
| H2 | 工作假设,只用于指导后续验证 |
|
||||
|
||||
## 3. 样本与相关文件
|
||||
|
||||
样本根目录:
|
||||
|
||||
```text
|
||||
source/repositories-complete/calrt-exact/calrt/hostrt/python/test/yolo-0915/calbin/
|
||||
```
|
||||
|
||||
### 3.1 实体 ELF
|
||||
|
||||
| 文件 | 字节数 | SHA-256 |
|
||||
|---|---:|---|
|
||||
| `yolov5s.pt--W8A8-W4AF16/ccu0_chip0.elf` | 790,824 | `22c5cfd5a58f25dcaed55dc0a553c7ee8f351b48dfa171220dd5bf5955566ff2` |
|
||||
| `yolov5s.pt--W8A8-W4AF16/ccu1_chip0.elf` | 788,464 | `51ea1cb733d5f5d664bb3e08024b81ae2c06287ae98a153c1f1a78d334a1f060` |
|
||||
|
||||
### 3.2 可读元数据
|
||||
|
||||
| 文件 | 内容 | 状态 |
|
||||
|---|---|---|
|
||||
| `model_memory_reserved_info.txt` | 模型、设备、DRAM/SRAM reservation、参数映射 | 实体文本 |
|
||||
| `yolov5s.pt--W8A8-W4AF16/submodel_memory_reserved_info.txt` | I/O、CCU ELF、芯粒和计算单元声明 | 实体文本 |
|
||||
| `yolov5s.pt--W8A8-W4AF16/cpu_chip0_runtime_cmds.txt` | `POLLING_CCU_DONE` 和 `END` | 实体文本 |
|
||||
|
||||
### 3.3 当前不是实体内容的文件
|
||||
|
||||
以下文件当前只有约 126-133 字节,是 Git LFS pointer,不能按其工作树内容分析:
|
||||
|
||||
```text
|
||||
param_blk0.bin
|
||||
yolov5s.pt--W8A8-W4AF16_inputs[0].bin
|
||||
yolov5s.pt--W8A8-W4AF16_outputs[0].bin
|
||||
yolo_Compiler_golden.bin
|
||||
cpu_chip0_ping.bin
|
||||
cpu_chip0_pong.bin
|
||||
```
|
||||
|
||||
因此本文没有把这些 pointer 的字节当成参数、golden 或运行命令。
|
||||
|
||||
## 4. 模型与内存合同
|
||||
|
||||
元数据确认该样本为:
|
||||
|
||||
```text
|
||||
calcc_ver: v0.1
|
||||
device: ks1
|
||||
model_type: cnn
|
||||
model_arch: yolov5s.pt--W8A8-W4AF16
|
||||
n_batch: 1
|
||||
calc_mchip: schip
|
||||
calc_utype: [ccu]
|
||||
```
|
||||
|
||||
I/O 合同:
|
||||
|
||||
| 角色 | shape | dtype | 虚拟地址区间 | 字节数 |
|
||||
|---|---|---|---|---:|
|
||||
| Input | `[1,640,640,3]` | BF16 | `0xc0000000-0xc0258000` | 2,457,600 |
|
||||
| Output | `[1,1575,6,16,16]` | BF16 | `0xc051f000-0xc09bd000` | 4,838,400 |
|
||||
|
||||
reservation:
|
||||
|
||||
| 空间 | 起始地址 | 大小 |
|
||||
|---|---:|---:|
|
||||
| DRAM | `0xc0000000` | 15,049,728 |
|
||||
| SRAM | `0x08000000` | 16,784,768 |
|
||||
| Sync | `0x0a080000` | 2 |
|
||||
|
||||
这说明 ELF 代码、参数映射和 tensor 地址是不同资产:ELF 主要是 CCU 控制程序,权重本应由 `param_blk0.bin` 提供。
|
||||
|
||||
## 5. ELF 基本属性
|
||||
|
||||
两份文件共同属性:
|
||||
|
||||
```text
|
||||
Class: ELF32
|
||||
Endian: little-endian
|
||||
Machine: RISC-V
|
||||
Type: EXEC
|
||||
ABI: single-float ABI
|
||||
Link: statically linked
|
||||
Symbols: stripped
|
||||
RISC-V arch: rv32i2p1_m2p0_f2p2_zicsr2p0_zmmul1p0
|
||||
Stack alignment: 16 bytes
|
||||
```
|
||||
|
||||
没有发现:
|
||||
|
||||
```text
|
||||
符号表
|
||||
调试信息
|
||||
动态依赖
|
||||
函数名
|
||||
源文件路径
|
||||
可用的算子名称字符串
|
||||
```
|
||||
|
||||
## 6. CCU0 文件和地址布局
|
||||
|
||||
`ccu0_chip0.elf` 的 `.text` 恰好为 `0xc0000` 字节,即 768 KiB。
|
||||
|
||||
| 文件偏移 | CCU 虚拟地址 | 长度 | 解释 | 等级 |
|
||||
|---|---:|---:|---|---|
|
||||
| `0x000000-0x000fff` | 无 | 4 KiB | ELF header、program header、padding | F0 |
|
||||
| `0x001000-0x0010e7` | `0x0a210000` | 232 B | 启动和运行环境初始化 | F0 |
|
||||
| `0x0010e8-0x001377` | `0x0a2100e8` | 656 B | 顶层直线调度器 | F0 |
|
||||
| `0x001378-0x0c0fff` | `0x0a210378` | 约 767 KiB | 149 个编译器生成执行块 | F0/H1 |
|
||||
| `0x0c1000-0x0c1037` | 无 | 56 B | `.riscv.attributes` | F0 |
|
||||
| `0x0c1038` 以后 | 无 | 余量 | section string table/header | F0 |
|
||||
|
||||
地址换算:
|
||||
|
||||
```text
|
||||
CCU0 VA = 0x0a210000 + (file_offset - 0x1000)
|
||||
file_offset = 0x1000 + (CCU0 VA - 0x0a210000)
|
||||
```
|
||||
|
||||
## 7. CCU1 文件和地址布局
|
||||
|
||||
`ccu1_chip0.elf`:
|
||||
|
||||
```text
|
||||
入口 VA: 0x4a210000
|
||||
.text offset: 0x1000
|
||||
.text size: 0x0bf6c8
|
||||
.text end VA: 0x4a2cf6c8
|
||||
```
|
||||
|
||||
其物理加载地址在 Program Header 中为 `0x40010000`,虚拟地址为 `0x4a210000`。CCU0 与 CCU1 的启动结构和 149 段顶层调用框架高度相似,但代码体、目标地址和常量并不完全相同。
|
||||
|
||||
推断:两份 ELF 由同一图执行计划生成,分别控制不同 CCU/执行资源;不是同一文件的简单重定位副本。(F1/H1)
|
||||
|
||||
## 8. 启动代码逐段解释
|
||||
|
||||
### 8.1 私有 CSR 和机器状态
|
||||
|
||||
入口前几条指令:
|
||||
|
||||
```text
|
||||
0a210000: lui x5,0x400
|
||||
0a210004: csrrs x0,0x7c0,x5
|
||||
0a210008: lui x5,0x2
|
||||
0a21000c: csrrs x0,mstatus,x5
|
||||
```
|
||||
|
||||
随后将 `x1-x31` 清零,并继续配置:
|
||||
|
||||
| CSR | 写入值 | 证据 | 当前解释 |
|
||||
|---:|---:|---|---|
|
||||
| `0x7c0` | `0x00400000` | F0 | 厂商自定义状态/扩展开关,具体位未知 |
|
||||
| `mstatus` | `0x00002000`,后追加 `0x8` | F0 | 标准 RISC-V machine status |
|
||||
| `0x7c2` | `0x00030013` | F0 | 厂商自定义配置,字段未知 |
|
||||
| `0x7c1` | `0x0000007f` | F0 | 厂商自定义配置,字段未知 |
|
||||
| `0x7c5` | `0x0000610c` | F0 | 厂商自定义配置,字段未知 |
|
||||
|
||||
`0x7c0-0x7ff` 属于厂商自定义 CSR 范围。当前 HostRT 源码没有这些 CPU-local CSR 的位字段定义,不能仅按数值命名。
|
||||
|
||||
### 8.2 栈和 BSS
|
||||
|
||||
CCU0 设置栈指针到约 `0x0a208000`,然后按 ELF 的 BSS 边界执行清零循环。该样本 `.bss` 实际为空或接近为空。
|
||||
|
||||
CCU1 使用其独立地址窗口,栈和 `.text` 地址整体移到 `0x4a...` 区域。
|
||||
|
||||
### 8.3 跳入顶层调度器
|
||||
|
||||
启动代码通过 `jalr` 跳到 `0x0a2100e8`。顶层调度器先向以下 MMIO 地址写 `1`:
|
||||
|
||||
```text
|
||||
0x0a002000
|
||||
0x0a00200c
|
||||
```
|
||||
|
||||
仓库 `mem_map.h` 给出的 CCU 视角寄存器窗口从 `0x0a000000` 开始,因此这两个地址落在 CCU 本地寄存器空间。(F1)
|
||||
|
||||
具体寄存器名未出现在当前头文件中,可能是执行单元启用、状态清理或同步触发。(H2)
|
||||
|
||||
## 9. 顶层 149 段调用图
|
||||
|
||||
调度器从 `0x0a210110` 到 `0x0a210360` 连续发出 149 条直接 `jal`:
|
||||
|
||||
```text
|
||||
0x0a210378
|
||||
0x0a210990
|
||||
0x0a2149d0
|
||||
0x0a218ec4
|
||||
...
|
||||
0x0a2cfa08
|
||||
0x0a2cfc2c
|
||||
```
|
||||
|
||||
顶层没有发现复杂的请求级动态调度结构。它是一个顺序展开的调用表:
|
||||
|
||||
```text
|
||||
初始化 -> block[0] -> block[1] -> ... -> block[148] -> 完成 -> return
|
||||
```
|
||||
|
||||
块尺寸统计:
|
||||
|
||||
| 指标 | 字节数 |
|
||||
|---|---:|
|
||||
| 最小 | 480 |
|
||||
| 中位数 | 3,164 |
|
||||
| 平均 | 5,272.1 |
|
||||
| 最大 | 107,692 |
|
||||
|
||||
最大的执行块:
|
||||
|
||||
| block | VA | 字节 | 标准 RV32(启发式) | custom32 | custom64(启发式) |
|
||||
|---:|---:|---:|---:|---:|---:|
|
||||
| 14 | `0x0a22cacc` | 107,692 | 7,719 | 4 | 9,600 |
|
||||
| 33 | `0x0a25db00` | 25,692 | 1,619 | 4 | 2,400 |
|
||||
| 109 | `0x0a2aac28` | 25,668 | 1,613 | 4 | 2,400 |
|
||||
| 100 | `0x0a29a5b0` | 24,256 | 1,260 | 4 | 2,400 |
|
||||
| 99 | `0x0a295dac` | 18,436 | 1,961 | 4 | 1,322 |
|
||||
|
||||
块大小与私有包数量大体相关。大块可能对应计算或数据搬运量较大的图阶段,但没有算子清单时不能把 block 14 直接命名为某个 Conv。(H1/H2)
|
||||
|
||||
## 10. 第一执行块字节轨迹
|
||||
|
||||
范围:
|
||||
|
||||
```text
|
||||
block index: 0
|
||||
file offset: 0x1378-0x198f
|
||||
CCU0 VA: 0x0a210378-0x0a21098f
|
||||
size: 1,560 bytes
|
||||
```
|
||||
|
||||
可见结构:
|
||||
|
||||
1. 函数序言,栈减 96 字节。
|
||||
2. 保存 `ra` 及多个 callee-saved 寄存器。
|
||||
3. 用 `lui/addi` 构造大量常量、地址和字段值。
|
||||
4. 反复向 `0x0a002000/0x0a00200c` 写值。
|
||||
5. 标准 RV32 指令与规则 8 字节未知包交替。
|
||||
6. 执行四条固定的 32 位 custom 指令。
|
||||
7. 恢复寄存器并返回。
|
||||
|
||||
首批 8 字节包示例(按小端两个 32 位字展示):
|
||||
|
||||
| VA | low32 | high32 |
|
||||
|---:|---:|---:|
|
||||
| `0x0a2103c8` | `0xa72d8008` | `0x00000354` |
|
||||
| `0x0a2103e4` | `0xa775a014` | `0x00000000` |
|
||||
| `0x0a2103f4` | `0xf7adc014` | `0x00000000` |
|
||||
| `0x0a21040c` | `0x632dc014` | `0x00000000` |
|
||||
| `0x0a21044c` | `0x18e60920` | `0x00000039` |
|
||||
| `0x0a2104cc` | `0xa55e6030` | `0x00000422` |
|
||||
|
||||
## 11. 标准反汇编器为何失步
|
||||
|
||||
ELF 属性明确不含 RISC-V `C` 压缩扩展,但 GNU objdump 在上述区域输出大量:
|
||||
|
||||
```text
|
||||
.insn 2
|
||||
.insn 4
|
||||
```
|
||||
|
||||
并偶尔把私有包的中间字节误解成浮点、CSR 或分支指令。原因不是 ELF 损坏,而是标准解码器不知道 Calculet 私有编码格式。
|
||||
|
||||
因此:
|
||||
|
||||
- 启动代码、标准 opcode 和明确对齐的控制流可以相信。
|
||||
- 私有包区域中 objdump 显示的 `fmadd.s`、随机 CSR 等不能直接当作真实语义。
|
||||
- 对整个 ELF 做普通 mnemonic 频率统计会混入误解码结果。
|
||||
|
||||
## 12. 32 位 custom 指令
|
||||
|
||||
每个执行块末尾稳定出现以下四个 32 位字:
|
||||
|
||||
| 顺序 | 编码 | opcode[6:0] | funct3 | rd | rs1 | rs2 | funct7 |
|
||||
|---:|---:|---:|---:|---:|---:|---:|---:|
|
||||
| 1 | `0x0001f82b` | `0x2b` | 7 | 16 | 3 | 0 | 0 |
|
||||
| 2 | `0x0000092b` | `0x2b` | 0 | 18 | 0 | 0 | 0 |
|
||||
| 3 | `0x000008ab` | `0x2b` | 0 | 17 | 0 | 0 | 0 |
|
||||
| 4 | `0x1400102b` | `0x2b` | 1 | 0 | 0 | 0 | 10 |
|
||||
|
||||
计数:
|
||||
|
||||
```text
|
||||
149 blocks * 4 = 596 custom32 instructions
|
||||
```
|
||||
|
||||
确定事实:
|
||||
|
||||
- `0x2b` 属于 RISC-V custom opcode 空间。(F0)
|
||||
- 四条指令在 CCU0 每个块中各出现一次。(F0)
|
||||
- CCU1 也保持相同四条尾序列。(F1)
|
||||
|
||||
工作假设:
|
||||
|
||||
- 前三条可能从专用执行单元读取/同步状态或搬运结果。
|
||||
- 最后一条 `funct7=10, funct3=1` 可能提交、barrier 或完成一个编译块。
|
||||
|
||||
没有动态 trace 或 ISA 定义前,不给它们分配正式操作名。(H2)
|
||||
|
||||
## 13. 64 位私有包的启发式字段
|
||||
|
||||
### 13.1 边界恢复方法
|
||||
|
||||
第一轮 parser 使用如下规则:
|
||||
|
||||
1. `.text` 按小端读取。
|
||||
2. 如果低 7 位是 RV32I/M/F/Zicsr 已知 opcode,按 4 字节前进。
|
||||
3. 如果低 7 位是 RISC-V custom opcode `0x0b/0x2b/0x5b/0x7b`,按 4 字节 custom 记录。
|
||||
4. 其他位置按 8 字节候选私有包记录。
|
||||
5. 使用 149 个直接 `jal` 目标作为块边界,避免错误跨块传播。
|
||||
|
||||
这是一种启发式边界恢复,不是私有 ISA 的正式 decoder。私有包首 32 位偶然碰撞标准 opcode 时仍可能被误分类。
|
||||
|
||||
### 13.2 数量
|
||||
|
||||
对 CCU0 的估算:
|
||||
|
||||
```text
|
||||
标准 32 位字:约 83,854
|
||||
明确 custom32:596
|
||||
候选 custom64:约 55,968
|
||||
```
|
||||
|
||||
### 13.3 初步字段分解
|
||||
|
||||
暂以 64 位小端值表示:
|
||||
|
||||
```text
|
||||
bits 0..7 family/opcode candidate
|
||||
bits 8..31 payload0
|
||||
bits 32..63 payload1
|
||||
```
|
||||
|
||||
按最低字节统计的主要家族:
|
||||
|
||||
| family byte | CCU0 数量 | 样例 low32 | 样例 high32 |
|
||||
|---:|---:|---:|---:|
|
||||
| `0x0c` | 10,906 | `0xd519600c` | `0x00000000` |
|
||||
| `0x30` | 9,156 | `0xa55e6030` | `0x00000422` |
|
||||
| `0x08` | 8,851 | `0xa72d8008` | `0x00000354` |
|
||||
| `0x14` | 8,793 | `0xa775a014` | `0x00000000` |
|
||||
| `0x04` | 4,712 | `0x451e4004` | `0x00000015` |
|
||||
| `0x40` | 2,945 | `0xb858a440` | `0x00000011` |
|
||||
| `0x20` | 2,230 | `0x18e60920` | `0x00000039` |
|
||||
| `0xe0` | 1,740 | `0xb2c1e1e0` | `0x00000000` |
|
||||
|
||||
观察:
|
||||
|
||||
- family byte 集中在少数值,适合作为 opcode 或主格式字段。(H1)
|
||||
- high32 经常为 0、1、20、21 或较小数值,可能是长度、模式、通道、tile 或同步字段。(H2)
|
||||
- CCU0/CCU1 家族分布相近但参数和数量不同,符合相同图在两个控制单元上的不同资源分配。(H1)
|
||||
- 不能排除真正 opcode 位于低字节的部分位,而不是完整 8 位。(H2)
|
||||
|
||||
## 14. CCU 外围寄存器对照
|
||||
|
||||
当前源码提供了 Host/System 视角 CSR 地址:
|
||||
|
||||
```text
|
||||
CCU0 SCL CSR base: 0x0a230000
|
||||
CCU1 SCL CSR base: 0x0a234000
|
||||
Sync unit base: 0x0a080000
|
||||
D2D base: 0x0a2e0000
|
||||
```
|
||||
|
||||
已知 offset:
|
||||
|
||||
| offset | 名称 | 作用 |
|
||||
|---:|---|---|
|
||||
| `0x0000` | `scl_program_addr` | ELF/程序入口配置 |
|
||||
| `0x0004` | `scl_start` | 启动 CCU |
|
||||
| `0x0008` | `scl_done` | 完成状态 |
|
||||
| `0x000c` | `ddr_boundary` | DDR 边界 |
|
||||
| `0x0010` | `scl_ddr_offset` | scalar DDR offset |
|
||||
| `0x0014` | `nscl_ddr_offset` | non-scalar DDR offset |
|
||||
| `0x0018` | `pf_ctrl` | prefetch 控制 |
|
||||
| `0x001c` | `stk_init_ctrl` | 栈初始化 |
|
||||
| `0x1014` | `dm0_csr_fifo` | DM0 CSR FIFO |
|
||||
| `0x1018` | `dm0_csr_fifo_status` | DM0 FIFO 状态 |
|
||||
| `0x1024` | `dm0_function_en` | DM0 功能开关 |
|
||||
| `0x1028` | `dm0_instr_start_cmd` | DM0 指令窗口开始 |
|
||||
| `0x1414` | `dm1_csr_fifo` | DM1 CSR FIFO |
|
||||
| `0x1418` | `dm1_csr_fifo_status` | DM1 FIFO 状态 |
|
||||
| `0x2800` | `instr_counter_ctrl` | 指令计数器控制 |
|
||||
|
||||
这些字段证明硬件至少有两组 data mover、CSR FIFO、load/write/DDR counters、ping/pong model config 和指令计数器。但尚未证明某一个 64 位 family 与哪一个 CSR 一一对应。
|
||||
|
||||
## 15. HostRT 到 ELF 的加载和启动原理
|
||||
|
||||
HostRT 的 `genInferLauncher()`:
|
||||
|
||||
1. 从 calbin 获取 CCU0/CCU1 ELF program info。
|
||||
2. 计算 CCU scalar DDR offset 和两个程序的 mmap entry。
|
||||
3. 配置 CCU stack。
|
||||
4. 写 CCU0/CCU1 `scl_ddr_offset`。
|
||||
5. 生成 `CONFIG_CCU_CSR`,写两个 program address。
|
||||
6. 提交 launcher。
|
||||
7. runtime command 使用 `POLLING_CCU_DONE` 等待完成。
|
||||
|
||||
`cpu_chip0_runtime_cmds.txt` 只有:
|
||||
|
||||
```text
|
||||
cmdId 0x0c: POLLING_CCU_DONE
|
||||
cmdId 0x00: END
|
||||
```
|
||||
|
||||
这与 ELF 内部携带完整执行计划一致:Host 负责加载、启动和等待,细粒度算子/DMA 调度主要在 CCU ELF 内完成。(F1)
|
||||
|
||||
## 16. 当前可以和不能得到的内容
|
||||
|
||||
### 可以恢复
|
||||
|
||||
- ELF 入口、加载地址和 section 边界。
|
||||
- 标准 RV32 启动和控制代码。
|
||||
- 顶层 149 段顺序调用关系。
|
||||
- 每个执行块的地址、大小和私有包数量。
|
||||
- 32 位 custom opcode 和固定尾序列。
|
||||
- 64 位候选包的边界、频率和字段变化。
|
||||
- CCU/DM/同步外围寄存器地图。
|
||||
|
||||
### 当前不能可靠恢复
|
||||
|
||||
- 原始 C/C++/DSL kernel 源码。
|
||||
- 每个私有 opcode 的正式名称和精确位字段。
|
||||
- block 到 YOLO 算子名称的精确映射。
|
||||
- 私有指令的 cycle、hazard 和异常语义。
|
||||
- `calcc` 如何从图、oplib 和 kernel 生成这些编码。
|
||||
|
||||
## 17. 风险与误判防护
|
||||
|
||||
1. 不把 objdump 在私有包中误解码的浮点/CSR 指令当作事实。
|
||||
2. 不把 149 个块直接等同于 149 个 ONNX 节点;一个算子可能拆为多个阶段,也可能融合多个算子。
|
||||
3. 不把 high32 小值直接命名为长度或通道,只记录相关性。
|
||||
4. 不把 `ccu*.elf` 当作完整 NPU kernel 源码;它是控制程序与私有命令流的编译结果。
|
||||
5. 不在缺少签名/校验规则时修改 ELF 并上板执行。
|
||||
|
||||
## 18. 后续验证路线
|
||||
|
||||
按信息增益排序:
|
||||
|
||||
1. 下载该 YOLO 样本的 LFS 参数、input、golden 和 ping/pong,确认完整样本哈希。
|
||||
2. 从完整 CalRT Git bundle 恢复历史中的 `device_cmd_gen` 和 `calrt_config_ccu_csr.h`,寻找已删除的 CCU 编码定义。
|
||||
3. 获取 YOLO calbin 的算子 YAML/profparts,建立 block 地址到算子顺序的候选对应。
|
||||
4. 对 CCU0/CCU1 相同 block 做字段级差分,识别 unit/chip/DM 选择位。
|
||||
5. 用 Runtime trace、CCU instruction counter、DM0/DM1 counters 做无修改动态观测。
|
||||
6. 若厂商提供 ISA/oplib,编写正式 decoder,并用同一小算子的多个 shape 编译结果做受控差分。
|
||||
|
||||
## 19. 第一轮最终判断
|
||||
|
||||
当前最符合证据的模型是:
|
||||
|
||||
```text
|
||||
Host CalRT launcher
|
||||
-> 配置 CCU0/CCU1 ELF 地址、栈和 DDR offset
|
||||
-> 启动两个 RV32 CCU
|
||||
-> CCU 顶层调度器顺序调用 149 个生成块
|
||||
-> 每块用标准 RV32 准备参数和 MMIO
|
||||
-> 通过 Calculet 64 位私有包驱动计算/DMA/同步资源
|
||||
-> 用四条固定 custom-1 指令收尾
|
||||
-> Host 轮询 CCU done
|
||||
```
|
||||
|
||||
其中“149 个块”“四条固定 custom 指令”“主要 64 位 family 分布”已由字节分析直接得到;“计算/DMA/同步”的具体 opcode 对应仍是待动态 trace 或私有 ISA 验证的假设。
|
||||
@@ -47,6 +47,7 @@
|
||||
| [性能压测故障注入与验收规范](./Calculet-NPU-性能压测故障注入与验收规范-20260802.md) | 正确 TTFT/TPOT、JSONL schema、open-loop 负载、soak/fault/pass-fail |
|
||||
| [Batch、KV 与多模型调度实现规格](./Calculet-NPU-Batch-KV与多模型调度实现规格-20260802.md) | lane/profile、continuous batching、KV 状态、load/unload、公平性和配置 |
|
||||
| [双芯粒双模型独立服务可行性与实施规格](./Calculet-NPU-双芯粒双模型独立服务可行性与实施规格-20260802.md) | CalCore/芯粒边界、组合 calbin、chip session、双 worker、容量/并发/故障验收 |
|
||||
| [CCU ELF 静态逆向初步调查](./Calculet-NPU-CCU-ELF静态逆向初步调查-20260802.md) | 本地 YOLO ELF、RV32 启动、149 执行块、32/64 位私有编码、字段假设和验证路线 |
|
||||
|
||||
这些规格故意把“设计完成”和“硬件已支持”分开。凡涉及新 calbin、kernel、partition、单芯粒、多模型常驻或 batch>1 的部分仍标 C3,直到厂商产物通过 runner。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user