Files
riscv-ulp-survey/opentitan/OpenTitan代码级综述.md

158 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# OpenTitan 代码级综述:一个量产级开源 SoC 仓库的结构解剖
**编制日期**2026 年 9 月 **数据来源**:本地克隆仓库实测(HEAD 2026-09 快照,git://lowRISC/opentitan
![仓库顶层地图](fig1_仓库顶层地图.png)
## 1. 总览:这不是一个"代码库",而是一条流水线
OpenTitan 的仓库体量为本次综述的 9 个开源项目之最:**3,995 个 RTL 文件、约 116 万行 RTL、821 个 FuseSoC .core 包、794 个 Bazel 构建文件、667 个 Python 工具脚本、12 条 GitHub Actions 流水线**,全仓库 8,992 个硬件文件与 3,743 个软件文件分布在十几个顶层目录中。
但读完本综述你会发现,单纯罗列数字会误导理解。OpenTitan 真正的结构特征是:**仓库里"手写的源"其实很少,大量文件是同一批机器可读规范在不同目的地的投影**。看懂三条生成链(寄存器链、模板链、集成链),比记住目录名重要得多。这也是它区别于其他开源项目(包括 PULPissimo 的 Bender 外拉模式)的根本所在——OpenTitan 把"规范、代码、文档、软件接口"全部收敛到一个仓库内,用工具保证一致性,而不是靠人肉同步。
下面按"顶层地图 → 硬件 → 生成体系 → 软件栈 → 验证 → 仓库治理"的顺序逐层展开。
## 2. 顶层目录地图
仓库顶层共 15 个目录 + 若干根文件(BUILD/Makefile 等)。按职责可归为五类(见图 1):
- **规范与文档**doc/、site/、release/、signing/)——安全架构白皮书、开发者指南、版本化发布快照与签名产物规范;
- **硬件 hw/**——本综述的核心,8,992 个文件,包含 45 个独立 IP、工艺基元层、芯片 top 与参数化 IP 模板;
- **软件 sw/**——从 mask ROM 到主机端 CLI 的完整软件栈,3,743 个文件;
- **工程基础设施**util/、ci/、rules/、third_party/、toolchain/)——491 个 Python 工具、Bazel 规则、内置三方依赖与工具链获取脚本;
- **质量与 CI**.github/、hw/lint、hw/cdc、hw/formal、hw/dv、hw/syn、quality/)——全仓库级静态检查、验证复用环境与质量门禁。
一个值得注意的顶层细节:hw/ 下同时存在 `top_earlgrey`(主力芯片)、`top_darjeeling`(第二种芯片配置)与 `top_englishbreakfast`(用于 Verilator/CW305 快速仿真的精简版),三者**共享同一套 hw/ip/ 目录**——这就是"多 top 共享 IP"的目录设计,一份 IP 源,多个芯片投影。
## 3. 硬件 hw/45 个 IP + 基元层 + 三个 top
### 3.1 hw/ip/:独立 IP 仓库
45 个 IP 子目录,每个都是完整的"小型仓库"(见图 2,以 aes 为例)。按功能可分组:
- **密码引擎**:aes(含掩码实现)、hmac、kmac、otbn(大数/椭圆曲线运算的独立 ISA 协处理器)、ascon(轻量密码);
- **熵与密钥**entropy_src、csrng、edn(熵源三件套)、keymgr、keymgr_dpe(密钥管理);
- **存储与启动**rom_ctrl、flash_ctrl、otp_ctrl、otp_macro、sram_ctrl、rram_ctrl、rram_macro
- **信任根与安全状态**:lc_ctrl(生命周期管理)、alert_handler、racl_ctrl(资源访问控制)、soc_dbg_ctrl
- **总线与核**rv_core_ibex、rv_dm(调试模块)、rv_timer、dma、mbx(邮箱);
- **通用外设**uart、gpio、i2c、i3c、spi_device、spi_host、usbdev、pattgen、sysrst_ctrl、adc_ctrl、aon_timer
- **基元层 prim/**:跨工艺共享的底座(仲裁器、CDC、差分信号、密码原语、LFSR 等 40+ 个 prim_* 子模块),并有 `prim_generic`(可仿真通用实现)、`prim_xilinx`FPGA 变体)、`prim_asap7`(学术工艺变体)等**工艺适配层**——同一接口,不同工艺的落地实现。
### 3.2 单个 IP 的标准解剖(以 aes 为例)
每个 IP 目录都有惊人一致的结构(这是 OpenTitan 治理强约束的结果):
```
hw/ip/aes/
├── data/ ip_block.hjson —— IP「身份证」:寄存器/中断/告警/参数规范
├── rtl/ aes.sv、aes_core.sv、aes_cipher_core.sv…(手写 RTL
├── reg/ ← util/regtool.py 从 data/ 生成的寄存器 RTLaes_reg_top.sv 等)
├── dv/ tb/UVM testbench+ env/ + tests/ + sva/(断言)+ cov/(覆盖率)
├── model/ aes_model_dpi —— C 参考模型(DPI 接口,与 RTL 逐周期比对)
├── pre_sca/ 侧信道攻击预研平台
├── pre_dv/ 轻量 mini-DV 环境
├── syn/ · pre_syn/ 综合脚本与约束(面积/时序评估)
├── lint/ IP 级 lint 配置
├── doc/ IP 说明文档
├── aes.core FuseSoC 包描述(全仓 821 个 .core 之一)
└── BUILD + defs.bzl Bazel 构建规则
```
关键理解:**rtl/ 与 reg/ 的分界线就是"手写"与"生成"的分界线**。工程师修改寄存器定义时只改 data/ip_block.hjson,然后运行 `util/regtool.py -r` 重新生成 reg/,寄存器 RTL、DIF 头文件、寄存器文档三者同步更新——这是"单一事实来源"Single Source of Truth)在 RTL 层的落地。
### 3.3 hw/ip_templates/ 与 hw/top_earlgrey/ip_autogen/:参数化 IP
13 个 IP 在仓库中以**模板**形式存在(clkmgr、rstmgr、pwrmgr、pinmux、otp_ctrl、alert_handler、rv_plic、gpio、pwm、flash_ctrl、rv_core_ibex、ac_range_check、racl_ctrl),由 `util/ipgen.py` 依据各 top 的参数集(如 Earl Grey 的时钟树/复位树/引脚配置)实例化到 `hw/top_earlgrey/ip_autogen/`,生成 9 个 top 专属 IP 实例。这一机制解决了"同一 IP 在不同芯片配置下需要不同参数"的问题——**模板写一次,每个 top 生成自己的实例**,避免手工 fork 出多个不同步的副本。
### 3.4 hw/top_earlgrey/:芯片集成层
这是芯片的"组装车间"
- `ip/`:top 专属手写模块(ast 模拟传感器抽象、sensor_ctrl、xbar 主互连);
- `ip_autogen/`:ipgen 生成物(9 个参数化 IP 实例,约 11.8 万行 RTL);
- `data/`top.hjson 等芯片级规范——**整颗芯片的 IP 清单、xbar 连接图、引脚复用、时钟/复位树、存储器映射全部在这份机器可读文件中声明**;
- `chip_earlgrey_asic.core` / `chip_earlgrey_cw340.core` / `chip_earlgrey_verilator.core`:同一芯片的三种顶层变体(ASIC 综合 / CW340 FPGA 板 / Verilator 仿真),共享同一套 IP 源;
- `dv/`:芯片级 UVM 环境(目标:验证 IP 集成正确性、XBAR 压力、地址空间自动化检查、FPV 连接性检查);
- `bitstream/`(含 cw340、vivado、universal):FPGA 比特流构建。
### 3.5 hw/vendor/:被"锁版本"收纳的三方 IP
Ibex 处理器核、PULP common cells、PULP riscv_dbg 三方代码**以 vendored 方式内置**在本仓库中(.lock.hjson 固定上游 commit.vendor.hjson 描述拷贝规则,patches/ 存放本地补丁)。这就是综述第 7 节所说"内置+锁版本"的机制实体——上游更新不会自动流入,必须走显式的 vendor 更新流程,保证任意时点 checkout 都能复现同一份构建。
## 4. 「规范 → 生成」管线:OpenTitan 的灵魂
见第 3 节图 2/图 3。仓库内四大生成器构成三条生成链:
| 生成器 | 输入 | 输出 | 一致性作用 |
|---|---|---|---|
| **util/regtool.py** | ip_block.hjson | reg/*.sv 寄存器 RTL + DIF 头文件 + 寄存器文档 | 寄存器三方一致 |
| **util/ipgen.py** | ip_templates/ + top 参数 | hw/top_*/ip_autogen/ | 模板→实例一致 |
| **util/topgen.py** | top.hjson | xbar_main/xbar_peri 互连 RTL + pinmux + 芯片级 RTL + 芯片级 DIF/头文件 | 集成层一致 |
| **util/dtgen.py** | 同 top 数据 | 设备树 APIdt_api.h 等 C 模板实例化) | 硬件↔软件视图一致 |
配套的文档生成器(util/mdbook_* 系列)把同一批 spec 渲染进 mdbook 文档站。**修改一个寄存器的完整成本 = 改一行 spec + 跑一遍生成器**,硬件 RTL、软件 DIF、文档三者同步更新,不会出现"文档落后于代码"的经典问题。这种机制在其他 8 个开源项目中无一具备——PULPissimo 用 Bender 解决的是"依赖从哪来",OpenTitan 用这些生成器解决的是"内部一致怎么保"。
## 5. 软件栈 sw/:从 mask ROM 到主机 CLI
sw/ 共 3,743 个文件,分为设备侧(device/)与主机侧(host/)两大阵营(见图 5):
- **sw/device/silicon_creator/****ROM 安全启动代码**——不可变第一级引导,含启动策略、密钥校验、防回滚(lib/ 子目录);
- **sw/device/silicon_owner/****ROM_EXT**——芯片所有者二级引导;
- **sw/device/lib/dif/****85 个 DIFDevice Interface Functions**——每个 IP 一份寄存器级 C APIdif_aes.c/h 等),并带 unittest.cc 单元测试;其中相当一部分由 autogen_dif + regtool 从 spec 生成;
- **sw/device/lib/**runtimehart/print 等)、crypto(密码库)、arch、base、peripherals、ujsonRPC 序列化);
- **sw/device/tests/ · examples/ · sca/**:芯片级测试、示例、侧信道采集(含 aes_serial、ecc384_serial、kmac_serial、otbn_vertical 等**串行化采集专用实现**);
- **sw/device/tock/**TockOS 移植;
- **sw/otbn/**OTBN 协处理器的汇编/驱动配套(crypto、kmac、mai、wfi 等子目录);
- **sw/host/****opentitantool / opentitanlib**——主机端统一 CLI(烧写、调试、UART/SPI/I2C/JTAG 传输),配套 hsmtool、provisioning(量产_prov 流程)、penetrationtests(渗透测试框架)、ot_certs(证书)。
**设备侧 + 主机侧在同一个仓库**是 OpenTitan 软件布局的关键决策:ROM/ROM_EXT/DIF 的任何修改都能同步反映到主机工具与测试中,"硬件在环"三载体(DV 仿真、FPGA、硅片)用同一套工具驱动。
## 6. 验证与质量体系
OpenTitan 的验证资产按"IP 级 → 芯片级"两层组织:
- **IP 级**(每个 IP 的 dv/):UVM testbench、SVA 断言、覆盖率收集计划(cov/)、dvsim 仿真配置(*_sim_cfg.hjson,声明测试集/仿真器/回归策略)、部分 IP 配 C 参考模型(aes、otbn、kmac 等 DPI 模型);
- **芯片级**hw/top_earlgrey/dv/):SV/UVM chip-level testbench,目标包括 IP 集成验证、XBAR 压力测试、地址空间自动化校验、时钟/复位域跨域检查、以及 **FPV 连接性检查**(验证 DV 中被排除的信号连接点 A→B 正确);
- **形式验证**hw/formal/ + util/fpvgen.py 为每个 IP 自动生成 FPV 配置;
- **静态检查**hw/lintVerilator/Verible 规则)、hw/cdc(时钟域)、hw/rdc(复位域);
- **侧信道/安全评估**:各密码 IP 的 pre_sca/ 平台 + sw/device/sca 串行化采集 + sw/host/penetrationtests
- **CI**12 条 GitHub Actions 流水线(含 cherrypick、pr_change_check、monthly 等),配套 util/dvsim.py 作为本地/CI 统一的仿真调度入口。
**util/dvsim.py 值得单独一提**:它是整个验证体系的"调度中枢"——IP 级 *_sim_cfg.hjson 与芯片级 testplan 都由它解析调度,同一入口覆盖 Verilator/VCS/Xcelium 等不同仿真器与 FPV/lint/cdc 各类工具,是"验证即代码"的工程化体现。
## 7. 仓库治理:让 116 万行代码不散架的机制
综合上述结构,OpenTitan 的"可治理性"来自五个机制:
1. **单一事实来源(SSOT**:寄存器、互连、引脚、时钟复位树全部声明在 hjson 规范中,代码与文档都是投影;
2. **生成式一致性**:四大生成器保证"改 spec → 全链同步",无手工同步环节;
3. **vendored 依赖 + 锁版本**:三方代码全部内置固定 commit(含 patches/),无外拉不确定性;
4. **多 top 共享 IP 池**:45 个 IP 独立于 top 存在,earlgrey/darjeeling/englishbreakfast 三个 top 共用,避免 fork
5. **模板化 + 参数化**:13 个 IP 模板按 top 参数实例化,同一逻辑不同配置不再手工复制。
这五个机制共同回答了综述第 7 节提出的问题——为什么 OpenTitan 是 9 个仓库中唯一达到"可量产交付"成熟度的项目:**它不是把代码放进仓库,而是把"生产代码的能力"放进了仓库**。克隆下来缺的不是文件,是理解这套流水线的视角;一旦理解,116 万行代码的组织方式反而比许多几万行的项目更清晰。
## 8. 快速导航:按目的找代码
| 你想做什么 | 去哪里看 |
|---|---|
| 理解某个 IP 的功能与寄存器 | `hw/ip/<ip>/doc/` + `data/ip_block.hjson` |
| 读某 IP 的手写 RTL | `hw/ip/<ip>/rtl/`(跳过 reg/,那是生成物) |
| 看某 IP 怎么被验证 | `hw/ip/<ip>/dv/` + `dvsim``*_sim_cfg.hjson` |
| 理解整芯片构成与地址映射 | `hw/top_earlgrey/data/top.hjson` |
| 找 xbar/pinmux/时钟树实现 | `hw/top_earlgrey/ip_autogen/`(生成物)+ `util/topgen.py`(生成逻辑) |
| 找 Ibex 处理器本体 | `hw/vendor/lowrisc_ibex/`vendored,含 patches/ |
| 看安全启动怎么写 | `sw/device/silicon_creator/rom/` |
| 写软件驱动某外设 | `sw/device/lib/dif/dif_<ip>.h` + 对应 .md |
| 主机端烧写/调试 | `sw/host/opentitantool/` |
| 给新 IP 建模板/加寄存器 | 参照 `hw/ip_templates/` + `util/make_new_dif.py` + `util/regtool.py` |
| 复现完整仿真/构建 | `util/dvsim.py`(验证)+ Bazel(软件)+ FuseSoCRTL 综合) |
## 9. 小结
OpenTitan 仓库的结构可以用一句话概括:**"规范驱动、生成器实现、供应商版本锁定、多 top 共享 IP 池、验证与软件同仓治理"**。它把开源硬件从"共享源代码"推进到"共享完整生产体系"——这既解释了它 116 万行的体量(大量是生成物与验证资产),也解释了它为什么能成为第一个走到商用量产的开源 SoC 设计。对于想学习"如何组织一个可信开源硬件项目"的团队,这个仓库本身就是最好的教材;对于想直接使用它的工程师,建议从第 8 节的导航表入手,先建立"规范 → 生成 → 代码"的映射习惯,再深入具体模块。
---
*附:本综述的架构图由 `make_figs.py` 生成(matplotlib + Noto Sans CJK),原始扫描数据与可复现脚本见同仓库 analysis/ 目录。*