14 KiB
OpenTitan 代码级综述:一个量产级开源 SoC 仓库的结构解剖
编制日期:2026 年 9 月 | 数据来源:本地克隆仓库实测(HEAD 2026-09 快照,git://lowRISC/opentitan)
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/ 生成的寄存器 RTL(aes_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 数据 | 设备树 API(dt_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 个 DIF(Device Interface Functions)——每个 IP 一份寄存器级 C API(dif_aes.c/h 等),并带 unittest.cc 单元测试;其中相当一部分由 autogen_dif + regtool 从 spec 生成;
- sw/device/lib/:runtime(hart/print 等)、crypto(密码库)、arch、base、peripherals、ujson(RPC 序列化);
- 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/lint(Verilator/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 的"可治理性"来自五个机制:
- 单一事实来源(SSOT):寄存器、互连、引脚、时钟复位树全部声明在 hjson 规范中,代码与文档都是投影;
- 生成式一致性:四大生成器保证"改 spec → 全链同步",无手工同步环节;
- vendored 依赖 + 锁版本:三方代码全部内置固定 commit(含 patches/),无外拉不确定性;
- 多 top 共享 IP 池:45 个 IP 独立于 top 存在,earlgrey/darjeeling/englishbreakfast 三个 top 共用,避免 fork;
- 模板化 + 参数化: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(软件)+ FuseSoC(RTL 综合) |
9. 小结
OpenTitan 仓库的结构可以用一句话概括:"规范驱动、生成器实现、供应商版本锁定、多 top 共享 IP 池、验证与软件同仓治理"。它把开源硬件从"共享源代码"推进到"共享完整生产体系"——这既解释了它 116 万行的体量(大量是生成物与验证资产),也解释了它为什么能成为第一个走到商用量产的开源 SoC 设计。对于想学习"如何组织一个可信开源硬件项目"的团队,这个仓库本身就是最好的教材;对于想直接使用它的工程师,建议从第 8 节的导航表入手,先建立"规范 → 生成 → 代码"的映射习惯,再深入具体模块。
附:本综述的架构图由 make_figs.py 生成(matplotlib + Noto Sans CJK),原始扫描数据与可复现脚本见同仓库 analysis/ 目录。
