
简介这份PDF指南主要面向IC验证工程师与芯片设计人员系统讲解Cadence JasperGold工具中顺序等价检查Sequential Equivalence Checking应用的使用方法。形式验证是一种利用数学证明保证逻辑正确性的先进验证方法该应用专门用于确认行为级、寄存器传输级、门级等不同抽象层次之间设计的逻辑行为是否保持一致在系统级验证、IP复用以及综合后验证等场景中非常关键。资源包为单个PDF文件压缩后约3.21MB便于下载与离线阅读内容基于2020.03版本编写涵盖验证环境搭建、约束条件设置、时序问题处理、检查任务创建配置以及结果分析与调试等完整流程。读者可从中了解如何针对具体设计设置合理约束并借助工具的高级特性优化验证效率同时文档还附有第三方组件许可与商标声明方便合规使用。截至目前已有294人学习使用适合希望掌握形式验证方法、特别是顺序等价检查技巧的芯片验证工程师作为案头参考。1. JasperGold SEC 到底能干什么不是仿真是用数学证明给你看做芯片验证的人大多有过这种经历综合后的网表跟 RTL 对不上ECO 改了一处逻辑心里没底跑仿真跑到天荒地老也覆盖不全。JasperGold 的 Sequential Equivalence CheckingSECApp 就是干这个的——它不靠测试向量而是把 spec 和 imp 两条设计接成一个 miter 模型用形式化引擎去证明两个设计在所有可达状态下行为一致。这份用户指南是 Cadence 官方 2020.03 版本讲的就是怎么配环境、怎么映射信号、怎么收敛证明。适合三类人被低功耗改造和时钟门控折磨的验证工程师、做 IP 复用的设计人员、以及刚上手形式验证想少走弯路的新人。核心就一句话——它验证的是时序等价不是组合等价这意味着两个设计可以状态不匹配内部寄存器数量不一样也能比。2. 从搭环境到出结果SEC App 的标准工作流2.1 理解 SEC 为什么能吃下非状态匹配设计传统的组合等价检查CEC要求两个设计逐寄存器对应否则就没法比。SEC 的突破在于它不需要这个前提。指南里明确说SEC 检查的是两个设计在外部端口上是否表现一致内部寄存器可以多可以少甚至可以有不同的流水级数。这一点对实际项目极其重要因为低功耗改造、时钟门控插入、流水线重定时之后寄存器数量几乎必然变化。SEC App 的做法是把两个设计接进一个 miter 模型spec 和 imp 的输入按某种方式连接输出接成一个等价断言target assertion。证明引擎去验证这个断言是否在任何可达状态下都会被满足。如果被违反就给出一个 counterexample这个反例就是两个设计行为不一致的具体输入序列。2.2 用 Setup Wizard 走通前五个关键步骤启动 JasperGold 后第一步是加载设计和设置环境。指南里把流程拆得很清楚我按实际操作顺序给你梳理一遍读取 spec 和 imp 两个设计文件通常是 RTL 或网表设置顶层模块和时钟复位信号自动映射边界输入输出auto-map检查 interface 是否连接正确生成验证环境并运行证明每一步在 GUI 里都有对应面板。推荐新手直接用 Setup Wizard它会把上面的流程串起来。命令行党可以直接写 TCL 脚本常见的做法是先读文件再跑 setup类似这样# 读取设计和设置顶层 read_file -format verilog {spec.v imp.v} elaborate -top top_module # 自动映射边界信号 auto_map -top top_module # 检查映射是否完整 check_interface -summary这段脚本的含义是先用read_file加载两个设计文件elaborate做例化展开然后auto_map让工具自动匹配 spec 和 imp 的同名信号。最后check_interface输出一份映射完整性报告告诉你哪些信号映射上了、哪些还悬着。参数说明-top指定顶层模块名auto_map默认只映射同名同类型的信号如果两边信号名不一致后面需要手动做 mapping-summary让报告只输出汇总不看细节。第一次跑建议不加-summary把完整报告留档。2.3 看懂映射报告和 interface check做 SEC 最怕的是映射错误——你以为在比 A 和 B实际比的是 A 和 C。指南里有一节专门讲 checking the interface核心是检查两类东西边界输入和边界输出。边界输入包括黑盒输出、主输入、无驱动信号和reset_x。边界输出主要是 DUT 输出。auto_map会自动映射大部分信号但reset_x是个例外——它要求你先定义复位行为并做仿真之后才能参与映射。看报告时重点关注 unmapped 信号。常见的情况是 spec 里有个信号叫data_inimp 里改成了data_i自动映射失败这个输入就悬空了。这种悬空输入在证明时会被当成 free input可能导致证明结果不可信或者直接跑出一个假 counterexample。# 检查 interface 并输出详细的未映射信号列表 check_interface sec_interface_check.log grep -i unmapped sec_interface_check.log这条命令把报告写到日志文件再用grep过滤出未映射的信号。看到 unmapped 清单后逐个决定是补 mapping 还是加入 stopat 白名单。后者适用于你明确知道某些信号不影响等价性结论的场景。3. Mapping 是 SEC 的灵魂五类映射类型与实操3.1 理解 init mapping、connection mapping 和 target mapping指南的附录 B 把映射类型列得很全但实际项目里你打交道最多的就三类init mapping、connection mapping、target mapping。Init mapping 负责初始化状态——spec 和 imp 的寄存器初始值怎么对应。如果两边复位值不同证明开始前工具就知道差异后面所有结果都会受污染。Connection mapping 处理信号之间的连接关系包括时钟、复位、普通数据信号。Target mapping 指定你要证明的是什么——通常是 spec 和 imp 对应输出的等价断言。这三类映射的优先级是先做 init再做 connection最后挂 target。顺序反了容易出莫名其妙的问题比如你先挂了输出等价断言再去改 init mapping前面的证明结果就作废了。3.2 手工补映射什么时候该自己动手自动映射覆盖不了的情况很典型信号改名、总线拆分、向量与标量混合、层次结构不同。指南里讲了一个 vectoring 的例子——spec 是一个 32 位总线data_bus[31:0]imp 拆成了四个 8 位信号手工映射时要把它们合成一个向量映射过去。# 向量化映射将四个字节信号映射到一个总线上 create_map -type connection \ -from {data_byte0 data_byte1 data_byte2 data_byte3} \ -to data_bus -vectoring # 层次别名规则两个设计层次名不同但结构相同 create_hierarchy_alias -from {spec_top/core/data_path} \ -to {imp_top/u_data_path}逻辑说明create_map手动建立信号对应关系-type connection声明这是连接映射-from和-to指定来源和目的地。-vectoring是告诉工具把多个来源信号拼成一个目标向量这比逐个 bit 映射省事得多。create_hierarchy_alias处理层次名不一致的问题。实际项目中 spec 和 imp 的模块例化名经常不同不建 alias 的话信号全路径名对不上映射无从谈起。参数说明create_map还有-init和-target两种-type分别对应初始化映射和验证目标映射。创建完映射后用report_maps -verbose检查每一条映射的类型和方向确认无误再进证明阶段。3.3 stopat 映射和 gated clock 映射的隐蔽用法Stopat 是 SEC 里一个特别容易用错的功能。它的作用是告诉工具这个信号在这里停下来不再往上游追溯。用得好能大幅加速收敛用得不好会把 bug 藏掉。典型场景imp 里有一段新增的 DFT 逻辑不影响功能但SEC 引擎非要去分析它。把 DFT 控制信号设成 stopat证明引擎就不再展开这部分的逻辑锥。指南提醒stopat 必须配合完备性报告使用——你跳过了什么报告里必须有记录否则 signoff 过不了。Gated clock mapping 是另一个专项。低功耗设计里时钟门控是标配spec 没有门控imp 有直接映射时钟信号会失败。正确的做法是用 gated clock mapping 类型把门控时钟映射到源时钟上同时把门控使能信号纳入分析范围。# 门控时钟映射示例 create_map -type gated_clock \ -from imp_clk_gated -to spec_clk \ -gate_enable imp_clk_en这段命令的含义是把 imp 的门控时钟imp_clk_gated映射到 spec 的纯净时钟spec_clk上门控使能imp_clk_en会被工具自动纳入等价性分析。如果不做这条映射门控时钟会被当成独立时钟域处理证明效率急剧下降。4. 证明策略与收敛从 AutoProve 到 Cutpoint 的组合拳4.1 三层策略Basic、Design Style、Bug-Hunting指南把证明策略分成三个层次。Basic strategy 是最朴素的适合第一次跑、对设计行为不熟的情况它把所有映射点直接拿去证明结果可信但速度一般。Design Style 策略按设计类型调参数——数据通路密集的选 datapath 优化控制逻辑密集的选 control 优化混合型选默认。Bug-Hunting 策略是反过来的思路——不追求一次性证明通过而是开足马力找反例。适合你有强烈怀疑某个改动引入了 bug 的阶段。它内部会用更激进的抽象和启发式搜索跑得快但可能误报——叫 false negative就是其实等价它却报了个反例出来。实际项目中我的做法是先 Basic 跑一遍拿 baseline如果超时或不收敛换 Design Style 按设计类型调再不行用 Bug-Hunting 快速试探哪里可能有差异。三步走完还收敛不了才考虑上 cutpoint。4.2 Cutpoint用切点换收敛速度但必须做 sanity checkCutpoint 是 SEC 里最锋利也最危险的刀。原理是把某个中间信号从证明逻辑锥里剪断视为一个自由变量从而大幅降低证明复杂度。代价是——如果这个 cutpoint 位置的信号在 spec 和 imp 里实际不等价证明结果就不可信了。指南里专门有一节讲 sanity check for cutpoints意思是切完之后要验证这个切点在两边的行为确实一致。怎么验证把 cutpoint 处的信号定义成一条新的断言先证明它成立再基于它去做上层证明。# 选择内部信号作为 cutpoint 并做 sanity check create_cutpoint -signal {spec/mid_signal imp/mid_signal} # 对 cutpoint 生成等价断言并单独证明 prove_cutpoint_equivalence -cutpoint {spec/mid_signal imp/mid_signal}逻辑说明create_cutpoint声明 mid_signal 不再参与上层逻辑展开prove_cutpoint_equivalence先单独证明这个切点两侧等价。只有当切点本身的等价性成立上层证明才是有效的。参数说明cutpoint 选在寄存器输出端、而非组合逻辑深处效果最好。组合逻辑深处的信号受输入组合影响大切这里做 sanity check 时不收敛的风险高。4.3 Helper Assertion 和 Proof Cache 的工程意义Mapping pairs as helper assertions 是把已有的映射对提升为辅助断言让证明引擎在推理时使用这些中间结论。好处是减少重复推理坏处是如果 helper 本身没被证明过会引入循环依赖。工程上的纪律是helper 必须来自已经证明过的 mapping或者在一个独立的证明会话中先验证它。Proof cache 是纯赚的功能。同一份设计改了几个信号重新跑证明时cache 会复用之前已证结论只重新证明受改动影响的部分。指南里的数据我不重复但实际经验是ECO 场景下开 cache 能节省 80% 以上的重复算力。前提是设计的层次结构和映射设置没变变了 cache 会自动失效。5. 避坑指南SEC 实战中我踩过的五个坑5.1 悬空输入导致假反例现象证明报了一个 counterexample但手动分析波形觉得完全不合理。原因某个输入信号没有映射成功被当成 free input。SEC 引擎可以自由驱动这个信号去构造反例但实际设计中这个输入根本不存在。解决先跑check_interface把所有 unmapped 信号列出来。对每个 unmapped 输入要么补映射要么确认它是约束信号、用 assume 限定其行为。5.2 复位时序不一致导致的初始化失败现象init mapping 报错或者证明结果与仿真结果系统性不一致。原因spec 用异步复位imp 用同步复位复位释放的时序不同。工具在初始状态计算时拿到的是复位过程中某个中间态两边对不上。解决检查复位信号的映射类型reset_x需要先定义复位行为并模拟。常见做法是将两边复位统一设置为异步复位或者用create_map -type init在复位释放后的稳定态上做初始化映射。5.3 时钟门控没映射性能断崖式下降现象开始证明后引擎长时间不收敛内部节点数爆炸。原因imp 有门控时钟但映射时直接按普通时钟映射过去了。门控信号参与逻辑锥分析导致 BDD 或 SAT 求解器面对远超必要的状态空间。解决用create_map -type gated_clock做专门映射。如果门控逻辑很复杂——多级门控、异步门控——考虑把门控信号本身作为一个待证目标先证明门控逻辑等价再验证主功能逻辑。5.4 Cutpoint 用太狠sanity check 过不了现象prove_cutpoint_equivalence超时或者直接证明失败。原因cutpoint 选在了组合逻辑的关键路径上它的行为受大量输入影响单独证明的复杂度已经超过了上层原问题。有时候是 cutpoint 选多了多个切点之间存在循环依赖。解决把 cutpoint 移到寄存器输出端或者减少 cutpoint 数量只切最影响收敛的那几个点。如果切点本身是复杂运算的结果——比如乘法器输出——建议先证明运算单元等价再把输出作为 cutpoint。5.5 完备性报告被忽略signoff 时补课现象流片前的等价性检查汇报被问你在哪些信号上做了 stopat有没有记录原因证明过程中为了收敛加了 stopat 和 cutpoint但没有生成完备性报告。类似的问题也可能出现在做 exceptions 或 constraints 时——只记了加了什么约束没记约束覆盖了哪些逻辑路径。审阅者要求的是所有未验证路径都有据可查。解决跑验证完备性报告用run_completeness_report生成完整记录。报告会列出所有 unproven 的目标、停止点、未覆盖的逻辑锥。把这些作为 signoff 数据的一部分归档而不是等别人问了再补。6. 把 SEC 做到能给领导签字验证完备性报告和自动时钟门控签核验证的工作不只是跑通一个证明。真正能交付的是证明覆盖了哪些、跳过了哪些、为什么可以跳过这套记录而完备性报告就是把这套话变成可审计交付物的工具。6.1 完备性报告里到底看什么运行run_completeness_report之后重点看三类内容。第一类是未证明目标列表。每个被跳过的目标背后都有一个理由——stopat、cutpoint、约束。报告会列出每个目标对应的验证状态需要逐一确认这些理由站得住脚。比如 stopat 跳过的逻辑要确认它真的不影响端口行为。第二类是自动时钟门控检查结果。低功耗设计里时钟门控是 ECO 重灾区指南专门讲了 automatic clock gating signoff 的流程——它会自动检查所有 gated clock 上的门控逻辑是否与参考一致并且把检查结果合并进完备性报告。做 signoff 之前必须跑完这一项否则报告不完整。第三类是抽象层的覆盖范围。SEC 不一定只做顶层比对指南里讲了用 SEC App 检查子层次——把某个子模块单独提出来做等价验证。完备性报告要能反映你验证到了哪个层次哪些子模块是单独验证的、哪些是嵌在顶层一起验证的以明确责任的边界。6.2 我习惯的验证流程从初跑到最终签核第一步跑通加载设计和映射用 Basic Strategy 跑一遍确认接口连接正确、基本等价性成立。这一步失败先修映射而不是调策略。第二步收敛加速遇到不收敛按顺序尝试——加 proof cache、按设计风格换策略、选关键信号做 cutpoint。每次改动后重跑并且记录改动原因。第三步完整性确认跑run_completeness_report检查所有未证明项。对每个 skipped 项写清楚理由必要时补充证明或放宽约束。第四步回归验证改过任何映射或约束之后把之前的证明结果作废重跑。这一步最容易被偷懒跳过我吃过一次亏——ECO 后只重跑了改动相关的目标结果一个旧的证明结论因为映射变化而失效幸好回归测试兜住了。从那以后我每次改完映射都会强制走一遍完整回归出错也宁可让它早爆而不是等 signoff 会议上来个大眼瞪小眼。6.3 最后一个技巧用日志和报告做自检每跑完一轮证明保存三样东西证明日志、接口检查报告、完备性报告。回看时如果发现某轮结果和改动点对不上优先怀疑映射遗漏本质上是数据没对上就出了结论。如果对不上的是性能——同样的设计这次比上次慢很多——优先查是否多了映射或约束本质上是证明空间被无意扩大。希望这份手册的使用经验能帮到你至少让你在 JasperGold SEC App 上少折腾几个通宵。本文还有配套的精品资源点击获取