LPV App低功耗形式验证实战:从UPF到电源域检查的完整指南
工试云启 考证服务中心整理

简介Cadence官方发布的JasperGold低功耗验证应用用户指南面向芯片设计验证工程师系统讲解形式验证在低功耗场景下的具体运用涵盖电源门控、多电压域、时钟门控等复杂功耗管理技术的验证要点。资料包仅含一个PDF文档整体大小约936KB轻量易用。目前已有181人学习下载。指南基于2020.03产品版本编写除工具功能概述外还深入介绍低功耗架构建模方法、从验证环境搭建到结果分析的完整流程、常用命令与脚本、典型案例研究以及错误处理与调试技巧。借助该指南读者可在芯片设计早期运用数学证明核对各电源状态下的行为及时发现并修复低功耗缺陷减少后期改动从而提升验证效率与流片成功率。内容还涉及与LSF、Linux及Excel等第三方软件的协作方式适合正在应用或计划引入JasperGold进行低功耗签核的IC验证团队参考。1. 为什么说 LPV App 是低功耗形式验证的“主战场”从 UPF 到电源域检查低功耗 SoC 在验证阶段最常见的翻车不是某个算法算错了而是某个休眠域的隔离单元没加、保持寄存器的 save/restore 控制信号接反、或者唤醒时序里电源上游还没稳住、复位就先释放了。这些问题都出在电源管理逻辑上仿真向量却很难把每条电源状态切换路径都走一遍。JasperGold Low Power VerificationLPVApp 就是专门干这件事的它把 RTL 和 UPF 读进来用形式验证formal 验证在数学层面证明设计在多个电压域和电源管理域下不会出错。我手里这份是 Cadence 官方 2020.03 版的用户指南面向芯片设计里做 IC 验证的工程师覆盖结构自动检查、复位检查、属性证明和反例调试下文按我实际拆解的顺序来讲。2. 跑通 LPV App 的第一轮检查GUI 流程、功率文件与电源模型构建LPV App 的整个使用流程是线性的先读 RTL再读 UPF 功率意图文件然后由工具创建内部功耗感知形式模型接下来才能谈检查和证明。很多刚上手的人习惯把检查命令一股脑敲进去结果模型根本没建起来工具只会给一堆看不懂的报错。这一章讲的就是怎么在 GUI 和命令行之间把第一轮检查顺利带出来。2.1 从 GUI 入口开始Setup 工具栏与功率文件加载用户指南里对 GUI 的定位写得很清楚LPV Setup Toolbar 是配置低功耗验证的入口。第一次用这个 App我建议别急着写 Tcl先把界面过一遍。我按自己读手册的习惯把 GUI 上几个关键区域列一下方便你对照。区域作用使用时机Power File 加载区指定 UPF 文件路径支持标准 UPF 格式读入 RTL 之后、构建模型之前Setup 工具栏勾选要做的结构检查、复位检查和属性验证构建模型之后、运行检查之前Checks / Run 区启动指定检查以列表形式呈现结果整个项目流程中反复使用Debug 窗口打开反例波形逐拍查看信号变化任意证明失败之后加载功率文件这一步容易踩的第一个坑是UPF 里引用的 supply port、supply net 如果不在顶层设计中工具会在加载阶段直接报错。这种问题通常和 RTL 层级对不上而不是 UPF 本身写法错误。我一般加载完成后会做的第一件事是在 GUI 里看 UPF 解析报告确认里头定义的 power domain 数量和预期一致。例如你 UPF 里写了 PD_CPU、PD_GPU、PD_SYS 三个域解析报告里就该看到三个 domain 节点多一个少一个都说明文件加载出了问题。2.2 构建电源模型之前必须核对的事工具读完 UPF 之后会按照功率分区规格创建内部功耗感知形式模型。这个模型包含每个电源域的供电关系、隔离单元、电平转换器、保持单元和电源开关状态后续所有检查和证明都在这个内部模型上跑。build 模型之前我通常核对三张表。第一张是电源域清单看每个 domain 的主供电和地网络是否对齐第二张是隔离单元清单确认哪些边界插了 isolation cell、clamp 值是 1 还是 0第三张是电源开关清单确认 switch 的控制信号和状态。这里有一个很关键的理解LPV App 不是在仿真相机上跑而是把 UPF 的功耗意图转成形式化约束再把这些约束施加到 RTL 门上构成一个可被数学推理的模型。所以模型建好之后你看到的设计其实是 RTL 逻辑加了一层电源管理状态机这也是后面为什么能证明“隔离使能时输出被钳位”这一类性质的原因。2.3 一个最简参考脚本让检查先跑起来虽然 GUI 是入口但项目一旦进入回归脚本化才是归宿。LPV App 的检查最终都会落到 Tcl 命令上。我会把第一轮检查组织成下面这个最小脚本后续所有调试都从它扩展。# 1. 读 RTL指定顶层和文件顺序 read_file -format sverilog -top tb_soc { rtl/soc_tb.sv rtl/dsp_core.sv rtl/lp_ctrl.sv rtl/gpu_core.sv } # 2. 读 UPF功率意图文件必须在 RTL 之后 read_file -format upf upf/soc.upf # 3. 构建内部电源模型失败时停下先查加载阶段 build_model # 4. 先跑结构性检查看隔离、保持、电源开关和供电规则 # 在 GUI 的 Setup 工具栏勾选对应项后再触发检查 report_checks -power -type structural # 5. 对关键性质做证明例如隔离功能或状态保持 prove -property lp_property_isolation_dsp脚本里最关键的是第二步和第三步之间的顺序关系。UPF 必须在 RTL 之后读因为 UPF 是对 RTL 层级做约束工具需要先有 hierarchy 才知道 domain 套在哪些 instance 上。第四步的 structural 检查是自动生成的不需要写任何断言工具会根据 UPF 自动生成一批检查项。必须说明的是Tcl 命令的准确拼写请以你安装版本的 GUI 导出脚本为准。我的习惯是用 GUI 把检查项勾好再另存为 Tcl 脚本在此基础上做参数修改比对着手册手敲命令可靠得多这也是碰过几次黑匣子报错之后换来的血泪经验。3. 结构检查是 LPV 的底盘隔离、保持、电源开关与供电规则的语义与参数用户指南把 LPV 的验证内容分成三大块低功耗结构检查、低功耗复位检查、低功耗属性验证。结构检查是最先跑、信息量也最大的一层它不看行为只看 UPF 指定的功耗意图有没有被正确实现。这一章逐个展开四个检查类别。3.1 Isolation Rules隔离规则检查的语义与参数隔离规则的目的是防止某一个电源域断电后输出的未知 X 值传进仍然上电的域。LPV 的结构性隔离检查验证的是每个隔离单元是否放在正确的边界上、隔离控制信号是否来自正确的电源域、clamp 值是否和 UPF 中定义一致。UPF 里 isolation 的典型写法是set_isolation iso_dsp_out -domain PD_DSP \ -isolation_power_net VDD \ -isolation_ground_net VSS \ -clamp_value 0 \ -applies_to outputs这里-clamp_value 0表示隔离使能时输出被固定在 0-applies_to outputs表示隔离单元作用在掉电域的输出端。还有一种常见配置是-applies_to inputs作用在接收域的输入端。两种接法物理上都存在但 LPV 检查的期望值完全来自 UPF如果 UPF 写 inputs、网表做成 outputs结构检查就会失败。参数核对上我一般盯四个点隔离单元所在的 domain、clamp 值、控制信号、隔离单元使能时的电源域。还有一个容易疏漏的多个隔离规则叠加在同一个边界上。如果同时设置了set_isolation和set_isolation_control结构检查会要求控制信号行为和隔离单元时序一致比如isolation_enable必须在上游域断电前有效。3.2 Retention Rules状态保持规则的检查重点保持规则用于那些断电后需要恢复状态的寄存器。LPV 结构检查会核对保持单元是否连接正确的保存和恢复控制信号以及保持单元在电源域关闭时是否依然有供电。UPF 里的定义大概是这样的set_retention ret_cpu_regs -domain PD_CPU \ -retention_power_net VDD \ -save_control {save_ok} \ -restore_control {restore_ok}-save_control和-restore_control分别指定保存和恢复的使能信号。这条规则的实现中寄存器会在 save 信号有效时把当前值锁存到保持单元里断电期间保持单元不掉电上电后 restore 再把值灌回来。LPV 检查这一类时最常出问题的不是 UPF 本身而是 RTL 里控制信号名字对不上。工具按信号名映射一旦名字在综合后发生变化映射失败就会报成 retention 结构错误。这种问题看波形完全正常但检查就是不通过属于典型的黑匣子行为往往要先查名字映射表。3.3 Power Switching Rules 与 Supply Rules电源开关和供电网络检查电源开关是低功耗设计的物理基础。结构检查会验证开关的驱动关系、开关本身是否跨越正确的电压域以及多个开关串联或并联时是否符合 UPF 定义。UPF 侧对应的代码长这样create_power_switch switch_iso -domain PD_GPU \ -input_supply_port {VDD VDD} \ -output_supply_port {VDDG VDDG} \ -control_port {on_off on_off} \ -on_state {on_state VDDG {on_off}} create_supply_net VDDG -domain PD_GPU connect_supply_net VDDG -ports {gpu_core/VDDG}-on_state定义了开关在 on_off 为某个逻辑值时导通的物理状态。这组命令在 LPV 内部会被解析成电源开关状态图后续属性验证基于这个状态图检查电源域的供电时序。电源开关检查常见的失败是 always-on 信号处理不对。有些开关控制信号来自另一个掉电域工具会把这种依赖识别为非法因为掉电域的信号自身都是未知的开关状态就会变成未知整个域的供电断言都会跟着失效。3.4 复位检查低功耗场景下最容易被误读的一类复位检查和结构检查不同它关注的是时序。LPV 的自动复位检查会验证复位信号在电源域上下电过程中的行为是否安全特别是上电后复位释放的时机以及复位信号本身是否来自一个没有掉电的域。实际项目里我见过很多复位检查失败的案例最典型的是隔离信号和复位释放顺序写反。比如隔离还没生效复位先释放目标域的寄存器就会采到 X 态后续所有逻辑都被污染。LPV 会把这种顺序违规直接报成反例。和纯功能验证最大的区别是这类复位问题在仿真里很难被敲出来因为唤醒路径的组合太多仿真平台通常只覆盖典型几条唤醒序列而形式化检查会把所有可能的电源状态序列都走到。所以 LPV 的复位检查在低功耗 SoC 里的定位基本属于兜底层它替你兜住了仿真没走到的那部分电源时序。4. 从结构检查到属性证明自动断言、隔离功能检查与反例调试结构检查通过只能说明单元摆放和连接符合预期不代表行为正确。低功耗属性验证把问题推进一步它通过自动断言来证明行为层面上的保真比如隔离使能时输出确实被钳住、状态保持寄存器确实保存了旧值。这一部分也是 LPV 比单纯 UPF 静态检查更值钱的地方。4.1 自动断言隔离功能、供电网络与切换行为的证明所谓自动断言是 LPV 根据 UPF 里的定义自动生成的属性不需要验证工程师手写。用户指南里至少覆盖下面几类。断言类别验证目标典型失败现场Isolation Functionality隔离使能时输出等于 clamp 值隔离单元接反或使能条件错误Power Supply Network and Switches开关状态与供电网络状态一致开关控制信号来自掉电域State Retention保存和恢复时序符合 UPF 描述恢复过早寄存器采到 XToggle Sanity电源管理控制信号能实际翻转控制信号被常值锁定这些断言是工具在build_model之后自动挂载的但证明动作通常需要单独触发。换句话说结构检查是即时反馈的属性证明需要消耗求解时间。在大型 SoC 上自动断言的证明耗时可能从几分钟到几小时不等正式回归时要按域拆分跑。一个值得强调的观点是属性证明失败不一定等于 RTL 实现错误还有可能是 UPF 给的功率意图本身自相矛盾。这两种情况的处理方向完全不同前者去改 RTL后者要去改 UPF 约束先分清楚再动手否则时间全浪费在错误的方向上。4.2 反例调试从反例波形反推问题来源LPV 的反例调试是 GUI 里最有价值的功能。看到一个证明失败时先不要急着翻代码按我习惯的顺序来第一步看反例波形里各电源域的上电状态序列确认波形描述的电源状态是否合法第二步看隔离信号和 clamp 输出的相对时序第三步看 retention 的 save/restore 信号第四步回头确认 UPF 里的状态定义。调试中最常遇到的情况是波形里隔离信号已经拉高了但输出没有变成 clamp 值或者在 clamp 生效前输出已经泄露出一个 X 拍。前者通常是隔离单元行为不匹配后者往往是电源状态序列不合法即工具走了一条 UPF 不允许的路径。另外形式验证的波形不像仿真波形需要长时间跑通常只有几十拍但这几十拍已经足够构造一个数学上完备的反例。形式验证反例调试最反直觉的一点是波形之间可能存在极短的 X 态窗口真实芯片里未必能观察到但工具认为在使能约束下逻辑上成立。遇到这种情况就要去核对约束是否过松而不是死磕 RTL。4.3 状态保持与黑盒实例上的功耗意图应用状态保持检查在结构层面看接线在属性层面看行为。自动断言会验证 round-trip 行为save 有效前寄存器值被保存断电后保持单元不掉电上电 restore 有效后值恢复。工具还要求 save 和 restore 不能同时有效这是一个默认的不变量。黑盒实例是 LPV 应用里一个容易忽略的边界情况。UPF 的功耗意图可以涉及黑盒实例所谓黑盒就是没有内部 RTL 视图的模块。对这种实例LPV 不会在内部逻辑上做结构检查而是把视角放到端口边界上检查隔离单元、电平转换器与黑盒端口之间的连接是否正确。检查对象有 RTL 视图黑盒实例内部隔离单元完整检查不检查边界隔离/保持单元完整检查检查端口连接属性证明可做内部行为证明以端口约束代替行为这个差异带来的实际影响是黑盒上的功耗意图错误会被部分静默吞掉。如果你把一个 set_isolation 设在没有内部视图的 IP 上结构检查可能什么都不报因为端口上看不出问题。因此我建议在做回归前先明确哪些实例是黑盒并单独评估丢失的验证覆盖率这个点放到下一章展开讲。5. LPV 实战避坑五条最常见的翻车现场与对策这一章是我在实际项目里和同类工具打交道的踩坑记录。每一条都按现象、原因、解决三步写尽量省掉多余铺垫。5.1 现象一UPF 加载顺序一换电源模型全乱现象同一个 UPF昨天跑得好好的今天换了一个读入脚本模型结构全变了隔离检查报了几十处失败。 原因UPF 加载顺序在 Tcl 脚本里被改了。RTL 必须先于 UPF 读取因为 UPF 引用的 instance 层级必须已经存在。顺序反了UPF 的匹配就会落到错误的对象上甚至部分命令被静默忽略。 解决把加载顺序作为脚本固定模板RTL 在前、UPF 紧跟其后、build_model 随后执行。团队内部把这段脚本统一封装成一个 proc禁止任何人单独改顺序。5.2 现象二隔离检查报几十个失败其实是 clamp 值设反了现象结构检查里 isolation 相关项全面飘红看起来像隔离单元整体没接上。 原因UPF 里set_isolation -clamp_value 0写的是 0实现端隔离单元钳的是 1两边不一致。工具按 UPF 的期望比对实现差一个 bit 就报失败。 解决先在 GUI 里看任何一个失败项的期望值如果期望是 0、实际是 1先全局查 clamp 值定义不要一头扎进网表。这种问题往往就是一行参数的事却经常被当成布线问题查一整天。5.3 现象三retention 属性证明跑飞不收敛现象自动断言里的 state retention 属性在 prove 时长时间不结束内存持续上涨。 原因某个保留寄存器的 restore 时序和时钟使能之间存在大范围自由状态求解器在枚举路径时空间爆炸。最常见的是 restore 信号由另一个域的分频时钟控制导致触发窗口宽度过大。 解决给相关信号增加辅助约束把 restore 的有效窗口限制在不超过几个周期的范围。也可以把域的开关序列固定成几条已知合法路径先证明局部再放开整体。5.4 现象四黑盒实例上的 set_isolation 被静默吞掉现象UPF 对某个 IP 的隔离约束完全没参与任何检查报告里干干净净你也说不清这算通过还是没查。 原因这些实例缺少内部 RTL 视图LPV 只做边界连接检查不验证内部隔离行为。如果连接端恰好都在驱动常量工具就直接判断通过实际覆盖率为零。 解决列出项目里全部 blackbox 清单对每个黑盒单独审视 UPF 约束是落在内部还是端口上。落在内部的一律挪到边界不能挪就补一层 wrapper model把内部行为建模出来后再跑证明。5.5 现象五整个域检查全通过但供电网络根本没接上现象power domain 的检查全部通过可我重新翻 UPF 时发现这个域的主供电网络只是名义上的没有任何物理 supply 连接到顶层端口。 原因UPF 里 create_supply_net 建了一个悬空网络工具把它当作合法存在结构检查只看网络名匹配不看它是否真的连到外部电源。 解决跑结构检查前先核对 supply network 的连接关系重点看每个 domain 的 primary supply 有没有连通到顶层 supply port。这条可以在 Tcl 脚本里强制打印 supply 清单并人工比对等检查通过后再来补供电返工成本极高。6. 半小时摸清电源控制信号的 toggle sanity一个让我少开三次会的小习惯LPV 的自动断言里有一类叫 Toggle Sanity我最初根本不重视后来发现它的排查效率远超预期。所谓 toggle sanity就是检查电源管理相关控制信号能不能在所有状态序列中至少翻转一次。如果某个控制信号在全部可达状态下都是常值工具会把它标记出来这往往意味着某个域永远不会按预期切换或某条控制通路被写死。我现在的做法很简单每次项目进入低功耗回归的头一天先跑一轮 toggle sanity 检查把全设计中所有电源管理控制信号的翻转情况拉成一张表任何翻转次数为零的信号都单独开会评审。实践中我遇到过一个几乎让整个芯片唤醒失败的案例排查了好几天最后就是 toggle sanity 报出来的。现象是某个域的iso_enable在整个可达状态空间里永远为 1等于说这个域一旦掉电隔离永远不退出唤醒流程直接卡死。当时仿真波形看起来信号是脉冲式的正常得不得了问题出在波形采样的窗口恰好都在隔离生效时间段内。形式化检查不需要采窗口它把整个可达空间走完一下子就把翻不了的现象锁死了。从那以后我每次跑 LPV 回归第一优先级都是先看 toggle sanity 的报告再决定要不要深挖结构检查的失败项。这个习惯帮我少开了太多次低效的会也避免过好几轮无头绪的定位。如果你手头正在做多电压域的低功耗验证建议第一次跑就顺手把这个检查打开输出的那个信号列表值得你花半小时认真看一遍。希望帮到你。本文还有配套的精品资源点击获取