技术深度解析
riscv-formal的工作原理看似简单:将处理器核心视为一个带有标准化接口的黑盒,然后从数学上证明每条可能的指令序列都能产生正确的架构状态。其核心抽象是RISC-V形式接口(RVFI),这是一组每个核心必须暴露的信号——包括已退休指令、程序计数器、寄存器文件写入、CSR更新和内存事务。通过标准化这一接口,框架将验证逻辑与任何特定核心实现解耦。
验证引擎依赖两种互补技术:
- 有界模型检测(BMC):将处理器的状态机展开为固定数量的时钟周期(即边界),并检查在该边界内是否可达到违反规格说明的状态。对于在边界内显现的缺陷,该方法具有完备性,但无法证明边界之外是否存在缺陷。对于RISC-V核心,典型边界范围为20至100个周期。
- k-归纳法:一种更强的技术,可证明属性对所有状态成立,而不仅限于某个边界内。其工作原理是:如果某个属性在连续k个步骤中成立,则它在第(k+1)个步骤中也成立,从而形成归纳证明。这需要求解更复杂的SAT/SMT公式,并且通常需要额外的辅助不变量(例如“寄存器文件永远不会包含非法值”)才能收敛。
该框架使用SymbiYosys作为形式验证后端,后者又依赖Yosys进行RTL综合,并依赖ABC或SuperProve进行SAT/SMT求解。用户可根据设计复杂度选择不同的求解器(例如boolector、z3、yices)。
| 验证方法 | 范围 | 缺陷覆盖率 | 证明时间(典型值) | 误报 |
|---|---|---|---|---|
| 仿真(随机) | 有界,采样 | 约60-80%的边界情况 | 数小时(1亿周期) | 无 |
| 形式BMC(k=50) | 有界,穷举 | 边界内100% | 数分钟至数小时 | 无(若规格正确) |
| 形式k-归纳法 | 无界,穷举 | 100%(理论上) | 数小时至数天 | 可能(缺少不变量) |
| 形式等价性检查 | 组合逻辑 | 组合逻辑100% | 数分钟 | 无 |
数据洞察: 形式BMC提供了一个最佳平衡点——在实用边界内实现穷举覆盖,且所需时间仅为无界归纳法的一小部分。对于大多数RISC-V核心,边界为50-100个周期的BMC能捕获绝大多数实际缺陷,包括PicoRV32和VexRiscv中发现的所有已知缺陷。
该开源仓库的结构是一组检查脚本的集合,涵盖每条RISC-V指令(RV32I、RV64I、M、A、F、D扩展)以及CSR和陷阱处理。每条检查都是一个SystemVerilog断言(SVA)或用Verilog编写的形式属性。框架还包含一个用Verilog编写的RISC-V规格参考形式模型,核心的行为将与该模型进行比对。这种双模型方法——一个形式规格模型和一个形式实现模型——是硬件验证领域的黄金标准。
关键参与者与案例研究
riscv-formal项目由Clifford Wolf发起,他是Yosys(开源综合套件)的创建者,也是开源硬件运动的关键人物。Wolf创立的SymbioticEDA公司维护该项目,但贡献来自广泛的社区,包括lowRISC、Western Digital以及独立研究人员。该框架已被多个著名的开源RISC-V核心采用:
- PicoRV32(作者:Clifford Wolf):一个微小的32位微控制器级核心。riscv-formal发现了一个缺陷:当乘数为零时,`MULHU`指令产生错误结果——这是一个仿真未能捕获的边界情况。
- VexRiscv(作者:SpinalHDL):一个高度可配置的32位核心。形式验证暴露了加载-存储单元中的一个竞争条件,该条件在特定流水线交错下会导致数据冒险。
- SERV(作者:Olof Kindgren):一个位串行RISC-V核心。riscv-formal证明了其不寻常的串行化执行正确实现了ISA,为在安全关键应用中使用该核心提供了信心。
- CVA6(原名Ariane,作者:苏黎世联邦理工学院):一个64位应用级核心。该框架在地址转换单元中发现了一个微妙缺陷:在特定的TLB逐出模式下,会错误地引发页错误。
| 核心名称 | 架构 | 检查的形式属性数量 | 发现的缺陷数 | 证明时间 |
|---|---|---|---|---|
| PicoRV32 | RV32IM | 1,200+ | 3(MULHU、CSR、分支) | 12分钟(BMC,k=50) |
| VexRiscv | RV32IM | 2,400+ | 5(冒险、异常) | 45分钟(BMC,k=100) |
| SERV | RV32I(串行) | 800+ | 0(被证明正确) | 8小时(k-归纳法) |
| CVA6 | RV64IMAFD | 4,500+ | 2(TLB、浮点舍入) | 6小时(BMC,k=80) |
数据洞察: 发现的缺陷数量与核心的成熟度和复杂度相关。PicoRV32作为一个相对简单的核心,缺陷少于VexRiscv,后者具有更复杂的流水线结构。