# 04 验证方法与当前进展

## 1. 先分清三种“通过”

### 静态 artifact 通过

例如 ONNX 的 shape、SHA-256、graph manifest 和 boundary manifest 通过。这证明“输入模型和编译输入是固定且可检查的”，不证明硬件能跑完模型。

### 模块 RTL 通过

例如 D2D header、CRC、RX endpoint、scheduler 或 Conv pixel vector 的 XSim 通过。这证明一个模块在 testbench 覆盖的场景下行为正确。

### 系统级签核

需要全算子 lowering、代表性量化精度、多 die 数据面、真实周期/带宽、板级无 DDR 运行和 ASIC 物理结果。这是当前尚未完成的层次。

## 2. 当前已经有的强证据

| 主题 | 当前证据 | 能说明什么 |
|---|---|---|
| 模型身份 | 官方 v8.4.0 asset，SHA-256 固定 | 后续结果可以复现到同一个模型。 |
| 图和边界 | 384 nodes、629 tensors、六个真实跨 die tensor | 分区和 ABI 有明确输入。 |
| Conv 编译 | 102 个 Conv/DWConv 的 W8+B32+multiplier 常量 | 卷积常量生成路径存在。 |
| 非 Conv | SiLU LUT、Add、SPPF、resize、Concat、PSA 参考合约 | 算子接口和部分 reference 已建立。 |
| D2D 控制面 | Header/Trailer/CRC、credit、路由、RX policy、sequence guard | 控制面协议可独立回归。 |
| SRAM 条件方案 | 32 行 band、双缓冲、四 context metadata | 在假设下找到可放入 1.45 MiB 的分配。 |
| 算子原语 | Conv/DW、LUT、SPPF、PSA 部件、D3 tail 部件 | 局部硬件行为有证据。 |

## 3. 当前不能声称的事情

- 不能声称已经完成 YOLO26n 全图 W8A8 RTL。
- 不能把烟雾图像的 bit-exact 结果当作 COCO 精度。
- 不能把静态 D2D payload bytes 当作实测吞吐。
- 不能把 1.45 MiB 条件分配当作已完成地址、bank、周期和 lifetime 签核。
- 不能把 ZCU106 no-DDR BD 预检当作摄像头、XSA、bitstream 和板上运行。
- 不能把 3x3 mm、20 FPS 当作已经完成的 28 nm PPA/STA 结果。

## 4. 与旧需求文档的版本差异

`yolo26_accelerator/docs/01_REQUIREMENTS_SPEC.md` 是早期 ZCU106 需求，写的是 640x640、50 FPS、20 ms/frame 等指标；当前四 die MPW 方案写的是 512x512、20 FPS、运行时 0 B/frame 外部 DDR。阅读进展时要以当前 `multidie/STATUS.md` 和 2026-09-04/05 的方案文档为准，同时保留旧需求作为历史背景，不能混用验收口径。

## 5. 推荐的学习和复现顺序

1. 先运行 Python 参考回归，理解 shape、scale、rounding 和边界条件。
2. 再看一个最小 RTL testbench，例如 `tb_d2d_header_codec.sv` 或 `tb_conv_w8a8_pixel.sv`。
3. 用波形观察 valid/ready、地址、frame_id、commit 和 abort，而不是只看最终 PASS。
4. 运行 D2D、scheduler、target primitives 和 operators 的独立脚本。
5. 最后阅读容量审计，理解为什么“算得对”仍可能“放不下”或“跑不满”。

## 6. 目前最重要的下一步

1. 用至少 32 张代表性图像完成部署级校准和 COCO-512 精度报告。
2. 输出版本化的 all-operator lowering 和多层 RTL 等价向量。
3. 把 band/lifetime/bank/DMA/credit/micro-op 绑定成周期级模型。
4. 完成 D2D abort、清理、重放、PHY retrain 和四 context 长稳测试。
5. 在 ZCU106 完成无 DDR camera bridge、XSA、ELF、bitstream 和持续运行。
6. 获得 SRAM macro、综合、布局布线、STA、功耗、热和封装约束证据。

## 7. 读代码时的三个问题

每打开一个模块，先问：

1. 它在什么时钟域？输入是 valid/ready 还是固定周期？
2. 它保存哪些状态？状态属于当前 frame，还是跨 frame 的配置？
3. 出错时怎么结束？是 backpressure、丢弃 packet、frame abort，还是整个系统 fatal？

这三个问题能帮助初学者把“信号名”连接到真实的硬件生命周期。
