# 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/ 生成的寄存器 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 的"可治理性"来自五个机制: 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//doc/` + `data/ip_block.hjson` | | 读某 IP 的手写 RTL | `hw/ip//rtl/`(跳过 reg/,那是生成物) | | 看某 IP 怎么被验证 | `hw/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_.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/ 目录。*