2026/10/7 23:37:10

芯片时序签核中OCV、set_timing_derate与CPPR实战解析

芯片时序签核中OCV、set_timing_derate与CPPR实战解析 1. 芯片时序签核里那个绕不开的OCV到底在卡什么做数字后端或者STA签核的兄弟大概率都经历过这样的场景综合完的网表跑PrimeTime时序报告一片飘红setup slack差个几十皮秒hold更离谱明明前端RTL仿真功能没问题怎么一到时序签核就过不了这时候老手第一反应往往不是去改逻辑而是先看一眼OCV derate是不是设得太狠了。OCV全称On-Chip Variation片上变化。它描述的是同一颗芯片内部由于制造工艺的微观波动、电压降、温度梯度等因素不同位置、不同路径上的标准单元和互连线其延迟表现并不完全一致。你在库文件里看到的那个标称延迟值只是一个统计意义上的典型值实际流片出来的芯片有的管子快一点有的慢一点有的线电阻大一点有的耦合电容多一点。STA如果只拿标称值去算那就是在赌运气而芯片这行当赌运气是要出人命的。所以签核阶段必须引入derate系数把标称延迟乘上一个大于1或小于1的因子人为地把悲观度加进去。这个动作就是set_timing_derate。它看起来只是几行约束命令但背后牵扯到的是整个签核策略的松紧尺度设松了芯片回来可能跑不起来设紧了面积功耗白白浪费甚至项目根本收敛不了。而CPPRClock Path Pessimism Removal时钟路径悲观度移除则是用来把公共时钟路径上被重复计算的悲观量拿掉让derate不至于把同一段时钟路径惩罚两次。这篇文章面向的是正在做STA签核的工程师不管你是刚接手PrimeTime脚本的新人还是已经调过几轮derate但总觉得心里没底的老手我都会把OCV、set_timing_derate、CPPR这几个东西掰开揉碎讲清楚。核心关键词OCV、set_timing_derate、STA、CPPR、PrimeTime会贯穿全文但我不会只给你念命令手册而是把每个参数背后的计算逻辑、实际项目里的取值经验、以及踩过的坑都摊开来说。读完你至少能做到知道derate该往哪个方向设、设多少有依据、CPPR什么时候开什么时候关、以及报告里那些数字到底是怎么算出来的。2. 先把OCV和derate的关系理清楚别一上来就抄命令2.1 OCV不是一种单一效应而是好几类偏差的统称很多人把OCV当成一个笼统的“悲观因子”这其实是个误区。在实际签核里OCV至少涵盖了几种不同的物理来源它们的表现方式和对时序的影响方向都不一样。第一种是工艺偏差也就是die-to-die和within-die的差异。同一批 wafer 上不同芯片之间以及同一颗芯片不同区域之间晶体管阈值电压、沟道长度这些参数会有微小浮动。这种偏差通常用全局derate和局部derate来区分建模。第二种是电压降引起的延迟变化也就是IR drop。芯片工作时电源网络上的电流流动会导致局部电压低于标称值电压低了单元延迟就变大。这种效应在先进工艺节点尤其明显而且它跟路径的翻转活动率相关不是静态的。第三种是温度梯度芯片上不同区域温度不同温度影响载流子迁移率进而影响延迟。温度对延迟的影响还跟电压有关存在所谓的温度反转效应低压下温度越高延迟反而越小这就让derate的方向判断变得更复杂。第四种是老化效应比如HCI、NBTI这些芯片用久了延迟会漂移。签核时通常用aging derate来覆盖但很多项目在初期会先忽略留到signoff后期再补。理解这些来源的意义在于你不能用一个统一的derate系数去覆盖所有效应否则要么过度悲观要么漏掉关键风险。合理的做法是分门别类针对setup和hold分别设置针对clock和data分别设置针对early和late分别设置。2.2 set_timing_derate的基本语法和参数含义PrimeTime里set_timing_derate的命令结构不算复杂但每个选项都有讲究。基本形式是这样的set_timing_derate -early 0.95 -late 1.05 -cell_delay -net_delay这里-early和-late分别对应早期路径和晚期路径。早期路径通常用于hold检查晚期路径用于setup检查。为什么hold用early、setup用late因为hold要保证数据不会太快到达所以取最快的情况setup要保证数据不会太慢到达所以取最慢的情况。这个逻辑如果搞反了时序报告就完全没意义了。-cell_delay和-net_delay分别指定derate作用于单元延迟和互连线延迟。有些项目会对两者用不同的系数因为单元和线的偏差特性不一样。比如先进工艺下线延迟受工艺波动的影响可能比单元更大那就需要给-net_delay设更大的derate。还可以用-clock和-data来区分时钟路径和数据路径。时钟路径通常走的是全局网络偏差相对小一些数据路径经过的组合逻辑多累积偏差可能更大。分开设置能让悲观度更精准。另外还有-rise和-fall选项用于区分上升沿和下降沿。一般情况下两者可以设成一样但如果你的设计里某些路径对上升下降敏感可以单独调。注意set_timing_derate是累积生效的。如果你先设了一个全局的derate又对某个特定路径设了derate最终生效的是两者的乘积。这个特性很容易导致过度悲观我在项目里见过有人设了三层derate结果slack直接崩掉查了半天才发现是系数叠乘了。2.3 derate系数到底该设多少有没有参考依据这是最常被问到的问题也是最没有标准答案的问题。derate系数的取值跟工艺节点、设计类型、签核阶段、甚至代工厂的推荐值都有关系。但也不是完全无迹可循我整理了一个大致的参考范围注意这只是经验值具体项目必须结合实际情况调整。工艺节点setup late deratehold early derate说明28nm及以上1.03~1.080.92~0.97偏差相对温和derate可以设小一些16nm/14nm1.05~1.120.88~0.95FinFET引入后偏差增大需要更悲观7nm/5nm1.08~1.150.85~0.92先进节点局部偏差显著derate明显加大3nm及以下1.12~1.200.80~0.90需要配合更精细的统计时序分析这个表里的数字只是给个感觉实际项目里我见过28nm设到1.15的也见过7nm设到1.05的差别在于设计对偏差的敏感度和签核策略的保守程度。关键是要有依据不能拍脑袋。依据从哪里来一是代工厂提供的PDK文档里面通常会有推荐的derate值或者统计分布参数二是历史项目数据如果之前同工艺的芯片回来测试结果和签核结果有偏差可以反推derate是否合理三是做灵敏度分析跑几组不同derate看slack变化找到收敛和风险的平衡点。3. CPPR到底在移除什么为什么不开它derate会虚高3.1 公共时钟路径被重复惩罚的问题要理解CPPR得先理解时钟路径在setup和hold检查里是怎么被计算的。假设有一个典型的触发器到触发器路径发射触发器和捕获触发器共享一段时钟树从时钟源到某个分叉点之前两个触发器走的是同一段物理路径。在setup检查里发射时钟路径用late derate捕获时钟路径用early derate。问题来了那段公共的时钟路径在发射端被乘了一个大于1的系数在捕获端被乘了一个小于1的系数。但物理上这段路径的延迟对两个触发器来说应该是同一个值不可能同时对发射端偏慢、对捕获端偏快。这种重复计算带来的悲观量就是CPPR要移除的东西。CPPR的全称是Clock Path Pessimism Removal有些工具里也叫Clock Reconvergence Pessimism RemovalCRPR。它的作用就是识别出时钟路径上的公共部分把这段路径上被重复施加的derate差异补偿回来。3.2 CPPR的计算逻辑和报告解读CPPR的补偿量怎么算简单来说对于公共时钟路径上的每个节点工具会计算late derate和early derate之间的差值然后把这个差值从时序裕量里加回去。举个例子假设公共时钟路径的标称延迟是100pslate derate是1.10early derate是0.90。那么发射端看到的延迟是110ps捕获端看到的是90ps两者差了20ps。但实际这段路径只有一个真实延迟假设就是100ps那么多算的20ps就是悲观量CPPR会把这20ps加回到slack里。在PrimeTime的时序报告里你通常会看到类似这样的行clock reconvergence pessimism 0.02这个0.02就是CPPR的补偿量单位是ns。它会让slack变好因为把过度悲观的部分去掉了。如果报告里这一行是0要么说明没有公共时钟路径要么说明CPPR没开。提示CPPR不是万能的它只能移除公共时钟路径上的重复悲观。如果两个触发器的时钟路径完全不共享那就没有CPPR可移除。所以在时钟树综合阶段合理规划时钟结构增加公共路径比例本身就能减少悲观度。3.3 什么时候必须开CPPR什么时候要小心绝大多数情况下CPPR都应该打开。PrimeTime默认在setup和hold检查里都会考虑CPPR但前提是你的时钟定义和约束是正确的。如果时钟定义有问题比如create_clock和create_generated_clock没设对工具可能识别不出公共路径CPPR就失效了。有一种情况需要小心当公共时钟路径上存在时钟门控或者多路选择器时公共路径的判定会变得复杂。工具需要知道在特定工作模式下信号实际走的是哪条路径。如果模式定义不完整CPPR可能算多了或者算少了。我遇到过一种情况时钟门控的使能信号在某个模式下是固定的但约束里没设case analysis工具把两条路径都当成可能的CPPR算出来的补偿量偏大导致hold检查过于乐观后来加了set_case_analysis才修正过来。还有一种情况是OCV derate本身设得比较小CPPR移除的量占比就很大这时候要确认CPPR的计算是否合理。如果CPPR补偿量超过了总slack的很大比例就要回头检查derate设置和时钟约束是不是有问题。4. 手把手实操从零配置一套可收敛的derate策略4.1 实操前的环境确认和约束检查在动手设derate之前有几项准备工作必须做扎实否则后面调半天都是白费功夫。第一确认时钟约束完整且正确。用report_clock检查所有时钟是否定义频率、占空比、不确定性是否合理。特别是generated clock要确认分频倍频关系正确。时钟约束错了derate和CPPR都无从谈起。第二确认时序豁免和case analysis设置到位。false path、multicycle path、case analysis这些如果没设工具会把不该检查的路径也纳入derate一加slack全红你根本分不清是derate的问题还是约束的问题。第三确认库文件版本和工艺角匹配。ss角配late derateff角配early derate这是基本常识。但有些项目会混用比如在ss角下检查hold这时候early derate的方向就要特别注意。第四先跑一版不加derate的基线时序记录下WNS和TNS。这是你的参照系后面每加一层derate都要跟基线对比看变化是否合理。4.2 分步设置derate并观察slack变化我通常采用渐进式的设置方法一层一层加每加一层看一次报告这样能清楚知道每个derate的影响。第一步设置全局的cell和net derate。先不加clock和data的区分就用最粗的粒度set_timing_derate -early 0.95 -late 1.05跑一次report_timing看WNS变化了多少。如果WNS从-0.1ns变成-0.3ns说明derate影响很大需要仔细评估如果只变了-0.02ns说明设计对derate不敏感可以适当加严。第二步区分clock和data路径。通常clock路径的derate可以比data路径小一点因为时钟树的结构相对规整偏差可控set_timing_derate -early 0.97 -late 1.03 -clock set_timing_derate -early 0.93 -late 1.07 -data注意这里clock和data的derate是分别设置的最终对一条完整路径的derate是两者按路径段组合。这样设置的好处是时钟路径不会被过度惩罚而数据路径的偏差被充分覆盖。第三步区分cell和net。先进工艺下net的偏差可能更大set_timing_derate -early 0.96 -late 1.04 -cell_delay set_timing_derate -early 0.92 -late 1.08 -net_delay第四步针对特定路径或特定单元做精细调整。比如某些关键路径经过的单元对偏差特别敏感可以单独设derate。但这一步要非常谨慎因为容易造成derate叠加过度。每步之后都要跑report_timing -delay_type max和report_timing -delay_type min分别看setup和hold的变化。同时用report_timing -derate可以看到每条路径上derate的具体施加情况这个报告在debug时非常有用。4.3 CPPR的开启和验证方法CPPR在PrimeTime里通常默认开启但为了确认可以在report_timing里加-input_pins或者直接看报告里的clock reconvergence pessimism行。如果这一行有非零值说明CPPR生效了。如果想手动控制可以用set_app_var timing_remove_clock_reconvergence_pessimism true来确保开启。有些老版本的工具可能需要显式设置。验证CPPR是否合理可以做一个简单的实验把CPPR关掉跑一次时序记录WNS再打开跑一次看WNS改善了多少。如果改善量在几十皮秒量级通常是正常的如果改善量达到几百皮秒甚至更大就要检查时钟树是不是公共路径特别长或者derate是不是设得太极端。还有一个技巧是用report_clock_timing -type skew来看时钟偏斜CPPR会影响skew的计算。如果skew报告里的值和你的预期差很多可能就是CPPR在起作用。5. 常见问题与排查技巧实录5.1 derate设完后slack大面积恶化怎么办这是最常见的情况。加了derate之后原本勉强能过的路径全红了WNS从-0.05ns掉到-0.5ns。这时候不要慌按下面的顺序排查。先确认derate是不是叠加了。用report_timing -derate看一条具体路径检查每个单元和每条net上实际生效的derate系数。如果发现某个单元被乘了两次甚至三次那就是叠加问题。解决办法是理清derate的层次避免重复设置。再确认CPPR是不是没生效。如果公共时钟路径很长CPPR没开的话悲观量会非常大。检查报告里的CPPR行如果是0去查时钟约束和工具设置。然后确认时序豁免是不是漏了。有些路径本来就不该检查比如跨时钟域的异步路径如果没设false pathderate一加就红了。用report_timing -exceptions检查例外设置。最后评估derate系数本身是否合理。如果设计在标称条件下slack就很小加derate后恶化是正常的这时候要考虑是不是设计本身需要优化而不是一味调derate。5.2 hold检查在ff角下early derate方向搞反这个问题很隐蔽但后果严重。hold检查要保证数据不会太快到达所以early derate应该小于1让延迟变小模拟最快的情况。但如果你的hold检查是在ff角下做的ff角本身的延迟就比tt角小这时候early derate如果还设成小于1就是双重悲观hold会过度检查。正确的做法是在ff角下做hold检查时early derate可以设成接近1甚至略大于1因为ff角已经覆盖了快工艺的情况。具体取值要看代工厂的推荐和项目的历史数据。我一般会在ff角下把early derate设成0.98~1.00而不是ss角下的0.90~0.95。注意不同工艺角下的derate策略必须分开管理。我习惯在脚本里用变量区分比如set derate_early_ss 0.93和set derate_early_ff 0.99然后在对应的角下读取对应的变量避免搞混。5.3 CPPR补偿量异常偏大或偏小CPPR补偿量偏大通常意味着公共时钟路径很长或者derate设得很极端。如果补偿量超过了slack的50%就要警惕了。先检查时钟树结构看是不是两个触发器的时钟路径共享了很大一段。如果是设计本身如此那CPPR大是合理的如果是约束错误导致工具误判公共路径就要修约束。CPPR补偿量偏小甚至为0可能是时钟路径完全不共享也可能是工具没识别出公共路径。检查report_clock_timing看时钟树结构确认create_clock和create_generated_clock的定义是否让工具能追踪到公共节点。还有一种情况是时钟门控导致的。如果公共路径上有时钟门控工具需要知道门控的使能状态。用set_case_analysis固定使能信号能让工具正确识别公共路径。5.4 常见问题速查表问题现象可能原因排查方法解决思路derate后slack大面积恶化derate叠加、CPPR未开、豁免遗漏report_timing -derate、检查CPPR行、report_timing -exceptions理清derate层次、开启CPPR、补全豁免hold在ff角过度悲观early derate方向错误检查ff角下的derate设置ff角下early derate调至接近1CPPR补偿量为0时钟路径不共享或约束错误report_clock_timing、检查时钟定义修时钟约束、检查公共路径CPPR补偿量过大公共路径过长或derate极端检查时钟树结构、评估derate系数优化时钟树、调整derate特定路径derate不生效路径被豁免或约束覆盖report_timing -derate看该路径检查例外设置、确认derate作用域6. 几个容易被忽略的细节和我的实操心得6.1 derate的作用域和优先级set_timing_derate的作用域是有优先级的。针对特定对象设置的derate会覆盖全局设置但如果是不同类型的derate比如一个针对cell一个针对net它们是分别作用的不会互相覆盖。这个特性要理解清楚否则容易设了一堆derate但不知道哪个在生效。我习惯在脚本里把derate设置集中在一个proc里按层次写清楚先全局再clock/data再cell/net最后特定路径。每层加注释说明为什么这么设。这样后面review或者交接时一目了然。6.2 跟OCV相关的其他约束别搞混OCV签核里还有几个容易跟set_timing_derate搞混的约束。比如set_clock_uncertainty它描述的是时钟抖动和偏斜的不确定度跟derate是两回事。uncertainty是在时钟约束阶段加的derate是在时序分析阶段加的两者会叠加影响slack。还有set_load和set_input_transition这些它们影响的是延迟的绝对值不直接是derate但会间接影响derate的效果。如果输入转换时间设得不对单元延迟本身就不准derate加再多也没意义。6.3 先进工艺下derate策略的演变到了7nm以下传统的单一derate系数越来越不够用了。代工厂开始推荐统计时序分析用分布而不是固定系数来描述偏差。但统计时序分析工具链复杂很多项目还是用derate加CPPR的组合。在先进工艺下我观察到几个趋势一是derate系数整体在变大因为局部偏差更显著二是分路径、分单元的精细derate越来越重要一刀切的做法收敛不了三是CPPR的作用更关键因为时钟树更长更复杂公共路径的悲观量占比更大。6.4 签核阶段derate的迭代节奏derate不是设一次就完事的。在签核的不同阶段derate策略要迭代。初期可以设得松一点先让设计收敛后期逐步加严逼近真实签核条件。每次迭代都要记录WNS和TNS的变化形成趋势图这样能判断设计是不是真的在改善还是只是derate在放水。我一般会在项目里维护一个derate迭代记录表列清楚每轮迭代的derate值、WNS、TNS、以及主要恶化的路径。这个表在项目复盘时特别有用能看出哪些路径对derate敏感哪些设计改动真正有效。6.5 一个实际项目的derate调优案例之前做过一个16nm的项目初期用全局derate 1.05/0.95WNS是-0.15ns怎么优化逻辑都收敛不了。后来把derate拆开clock用1.02/0.98data用1.08/0.92同时确认CPPR开启WNS变成-0.08ns。再进一步对net derate单独设成1.10/0.90cell derate保持1.05/0.95WNS降到-0.05ns。最后针对几条关键路径做了单元替换和缓冲器插入WNS收敛到0.02ns。这个案例说明derate的精细化管理本身就能带来可观的收敛收益不一定要大改逻辑。关键是理解每层derate在惩罚什么然后有针对性地调整。6.6 工具版本和脚本兼容性PrimeTime不同版本对set_timing_derate和CPPR的支持有差异。老版本可能不支持某些选项新版本可能默认行为变了。升级工具版本后一定要重新跑一遍时序对比derate和CPPR的结果。我遇到过升级后CPPR默认关闭的情况导致slack突然变差查了半天才发现是工具设置变了。脚本里最好显式设置CPPR的开关不要依赖默认值。这样不管工具版本怎么变行为都是一致的。7. 写在最后的一些个人体会调derate这件事说到底是在悲观和乐观之间找平衡。设得太松芯片回来可能翻车设得太紧项目收敛不了面积功耗都浪费。没有绝对正确的系数只有适合当前项目阶段的策略。我的经验是derate策略要跟设计阶段匹配。早期可以松给逻辑优化留空间中期逐步加严暴露真实问题后期按签核标准来确保芯片能跑。每个阶段都要有记录、有对比、有依据不能凭感觉调。CPPR能开就开它是把双刃剑用好了能去掉不必要的悲观用不好会掩盖真实风险。关键是理解它的计算逻辑知道它在移除什么才能判断补偿量是否合理。最后分享一个小技巧在PrimeTime里用report_timing -derate -path_type full_clock_expanded可以看到时钟路径的完整展开包括每个节点上的derate和CPPR补偿。这个报告在debug复杂时钟路径时特别好用能让你看清楚每一皮秒是怎么来的。