第二章证明结果分析与调试
理解证明状态
| 状态 | 含义 | 下一步操作 |
|---|---|---|
proven | 属性在所有可达状态中成立(full proof) | ✓ 无需进一步操作 |
failed | 找到了违反属性的反例波形 | 🔧 分析波形,定位 bug 或添加约束 |
bounded | 在 trace length 范围内成立但未 complete proof | ⏫ 增大 trace length 或换引擎 |
unknown | 引擎超时/资源不足 | ⚙️ 调整引擎、添加抽象、简化属性 |
调试失败的断言
当断言失败时,JasperGold 会生成一个反例波形(counterexample trace)。这是一个最小长度的输入序列,可以触发属性违反。
反例调试步骤
- 在 Property Table 中双击 failed 属性
- Visualize 窗口自动打开,显示反例波形
- 追踪波形,找到第一个不满足属性的时钟周期
- 检查该周期的信号值,确定是设计 bug 还是输入约束缺失
- 如果是约束缺失,添加 assume 约束后重新证明
- 如果是设计 bug,修复 RTL 后重新运行
Verification Status Indicators
JasperGold GUI 中使用一系列图标表示验证状态:
- ✅ 绿色对勾:proven
- ❌ 红色叉号:failed
- ⚠️ 黄色三角:bounded(有界证明)
- ⏸️ 灰色方块:not run / unknown
- 🔵 蓝色圆点:covered(覆盖点命中)
处理 Bounded 和 Unknown 属性
增大 Trace Length
set_max_trace_length 100
prove -property <property_name>
切换引擎模式
# 尝试不同的引擎组合
set_engine_mode {K I N B L P}
prove -property <property_name>
添加抽象
对于复杂设计,可以手动添加抽象(abstraction)来减少状态空间:
# 抽象掉数据路径,只验证控制逻辑
abstract -signal data_bus
# 或使用黑盒
blackbox -module complex_datapath
常见证明问题排查
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| 大量 failed | 缺少输入约束 | 添加 assume 约束合法输入 |
| 所有属性轻易 proven | 过约束 | 添加 cover 点验证可达性 |
| 长时间 unknown | 状态空间太大 | 分模块验证、添加抽象、使用 ProofGrid |
| Bounded 不收敛 | 深度超过 BMC 能力 | 使用 K-Induction 或 PDR 引擎 |
界面截图


结果诊断方法论:四种结果的决策树
证明完成后,面对 Property Table 中的各种颜色,新手往往不知道接下来该做什么。以下是每种结果的系统化处理方法。
🟢 Proven(绿色):别着急庆祝
绿色表示引擎在给定约束和深度内证明了属性成立,但在 signoff 之前需要问自己几个问题:
- 这是我想证明的属性吗?检查属性的自然语言含义,确保 SVA 写的是你真正想验证的东西
- 约束是否过强?如果约束把输入空间限制得太小,属性可能只是在一个不现实的子空间内成立。用 cover 属性验证:关键合法场景是否能被覆盖到?
- 是否为 bounded proof?bounded(黄色)只证明了有限深度内成立,不是完整证明
- 黑盒是否合理?被黑盒化的模块如果应该参与该属性的逻辑,可能导致假 proven
一个好的实践:对于每个关键断言,写一个对应的 cover 属性来"证伪"约束的合理性。例如断言"grant 始终 one-hot",可以加 cover "看到四次不同的请求分别被 grant",确保约束允许所有合法仲裁场景。
🔴 Failed(红色):分三类排查
红色反例是调试的起点,但不是终点。反例可能来自三种原因,排查顺序很重要:
| 原因 | 特征 | 处理方法 |
|---|---|---|
| 设计 Bug | 反例波形中输入完全合法,输出违反了预期协议 | 修复 RTL,重新 prove |
| 约束缺失 | 反例波形中输入出现了不合法的组合(如同时要求两个互斥操作) | 添加 assume 约束排除非法输入 |
| 属性写错 | 仔细读 SVA,发现断言逻辑本身有误(如用了 |-> 而不是 |=>) | 修正 SVA,重新 prove |
调试顺序建议:先看反例波形中输入信号是否合法。如果输入本身就违反了设计协议(如复位期间就发请求),那是约束问题;如果输入合法但输出错误,那是设计 bug。
🟡 Bounded(黄色):加深或换引擎
Bounded 证明意味着引擎在当前 trace length 内没有找到反例,但也没有完整证明。处理方式:
- 逐步增大
set_max_trace_length(每次加 20-50) - 切换引擎:BMC 做有界检查,换 K-Induction(K、N 引擎)尝试完整证明
- 如果加深后转为绿色 → 完成;如果变红 → 反例;如果一直黄色且超时 → 考虑抽象
⚪ Unknown/Timeout(灰色):复杂度问题
引擎在规定时间内无法确定属性真假,通常是因为设计太复杂。解决思路:
- 增大时间限制:给引擎更多时间(注意 diminishing returns)
- 黑盒化非关键模块:用
-bbox_m黑盒掉不参与当前属性的子模块 - 添加 cutpoint:在不影响属性的信号上插入 cutpoint 切断状态空间
- 分模块验证:先在块级验证子模块,再到芯片级
- 使用抽象:数据路径抽象(将宽数据路径替换为自由变量)
反例波形调试方法论
当属性失败时,visualize -violation 打开反例波形。高效的调试思路:
- 从波形末尾倒推:找到断言失败的那个时钟周期,看那个周期的信号值
- 关注红色标记:Visualize 中红色高亮的信号参与了失败路径
- 使用 Why 分析:右键信号 → Why,自动解释该信号为什么是当前值(展示驱动逻辑)
- Relevant Logic:自动过滤出与反例相关的信号和逻辑,隐藏无关信号
- 追踪到输入:从失败点沿着逻辑锥(COI)向前追踪,找到导致错误的根本原因
常见误诊:新手看到红色就去改 RTL,但很多"失败"其实是因为约束不够——工具自由驱动了输入端口,产生了设计规范中不允许的输入组合。先检查反例的输入是否合法!
来源文档
jaspergold_apps_userguide.pdf Ch.7jaspergold_apps_userguide.pdf Appendix B