ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

数字后端实战:修复reg2icg setup违例的三大招(ICC2/Innovus)

数字后端实战:修复reg2icg setup违例的三大招(ICC2/Innovus) 作为一个在数字后端跑了好几年流片的老兵我太懂 reg2icg setup 违例带来的那种恶心感了。明明前面floorplan、placement都顺风顺水偏偏到了CTS之后一堆reg2icg路径的setup violation冒出来报出来的 slack 负得让你怀疑人生。更难受的是这玩意儿不像普通的 reg2reg 路径改个size、插个buffer可能就过了reg2icg 牵扯到时钟门控单元ICG的使能路径乱动时钟树反而容易引入新的问题。这篇文章我就把项目里反复用到的三招实战解法整理出来分别对应 ICC2 和 Innovus 两套主流工具。没有那些虚头巴脑的理论全是直接能落到命令和脚本里的操作文末我会放同一颗芯片、同一条 reg2icg 路径在两种工具下的优化前后数据对比给你们一个直观的参考。1. 为什么 reg2icg 的 setup 违例这么难缠在动手之前先得把 reg2icg 这条路径的特殊性讲清楚不然你只会治标不治本。1.1 reg2icg 路径的本质一条“使能”信号与时钟抢时间ICGIntegrated Clock Gating单元在数字芯片里无处不在它的作用就是把不需要翻转的时钟沿“掐掉”从而降低动态功耗。而 reg2icg 路径指的是一个普通寄存器reg的 Q 端通过组合逻辑或者直接连接驱动 ICG 的 TETest Enable或者 EEnable端。这条路径上跑的其实是一个电平信号但这个电平信号必须在时钟有效沿到来之前稳定下来。如果这个使能信号到达 ICG 的时间太晚ICG 就可能在一个不该打开的时钟沿打开了或者该关的时候没关上造成功能错误。所以工具对这条路径的 setup 检查本质上是把“数据到达时间”和“捕获时钟沿”放在一起比谁晚谁就是 violation。问题在于捕获端是 ICG 内部的锁存器latch它的时钟就是来自时钟树的叶节点这导致 reg2icg 的时序预算往往比普通 reg2reg 更紧张因为使能路径还要额外平衡与时钟树的关系。1.2 为什么 CTS 之后它才集中爆发很多同学在 pre-CTS 阶段跑 STA发现 reg2icg 路径 slack 还挺好一到 CTS 之后就突然冒出一堆违例。原因很简单pre-CTS 用的是理想时钟所有时钟树延迟都算成零使能信号和时钟沿的到达时间差是理想化的。但 CTS 做完之后时钟树插入了真实的 buffer/inverter从时钟源到 ICG 这个捕获端和到发起端寄存器reg的时钟延迟完全不同。更关键的是ICG 的使能路径往往走的是数据绕线而 CTS 只负责时钟绕线两者之间的偏差在真实 RC 提取后会非常明显。再加上 ICG 单元本身在库里的 setup 要求往往比普通 flip-flop 更苛刻所以 CTS 后 reg2icg 变成重灾区几乎是个必然事件。2. 第一招优化前的“侦察”——先搞清楚违例长什么样很多人拿到时序报告就急着改约束、加 buffer结果越修越乱。我自己的习惯是动手之前先把违例路径原原本本看一遍确认是结构问题还是单纯 load 太重或者是物理位置太差。2.1 用报告定位违例路径的三大关键信息在 ICC2 里我一般会先跑一条具体的路径报告而不是只看 summary。命令长这样report_timing -from [get_pins regA/Q] -to [get_pins icg_inst/EN] \ -transition_time -nets -cap -attributes -path_type full_clock在 Innovus 里则是report_timing -from regA/Q -to icg_inst/EN \ -transition_time -nets -capacitance -path_type full_clock拿到报告后我不会急着看最后的 slack而是按顺序盯三件事第一看这条路径的层级数。如果中间经过了超过两级的组合逻辑比如 AND-OR-INV 串起来那说明前端 RTL 的时钟门控逻辑写得太深靠后端物理优化很难彻底解决得考虑返回去改 RTL或者至少在综合阶段就做逻辑重组re-time。第二看发射端寄存器的时钟 latency。如果 regA 的时钟延迟比 ICG 捕获端的时钟延迟短得多那等于给数据路径“多争取”了时间按理说 setup 应该好修反过来如果发射端时钟延迟很长捕获端很短那 setup 就是先天吃亏你怎么插 buffer 都费劲。第三看使能信号的 transition time。ICG 的 EN 端通常对 transition 比较敏感如果报告里 EN 端 transition 超过库里的最大值那即使 slack 数字看着还行实际流片也有风险这种必须先修 transition 再谈 setup。2.2 识别“假违例”必须检查的例外与约束一致性有一类 reg2icg 违例是“假”的修了也白发力气。最常见的就是 test mode 下的违例。芯片在 scan 测试模式下ICG 的 TE 端会被 scan_enable 拉起来这时候 reg2icg 的时序检查和功能模式完全不同。如果 STA 里同时跑 function mode 和 test mode你看到的违例可能只是 test mode 下的但功能模式根本不受影响。所以动手前务必确认一下你分析的是哪个 mode、哪个 corner。我会习惯性地在 ICC2 或者 Innovus 的 session 里同时把 func 和 test 都报一遍对比同一条路径在两个 mode 下的 slack 差异。如果只有 test mode 违例而且这条路径本身不在 scan chain 的时序关键路径上那往往可以通过设置 set_false_path 或者 set_multicycle_path 来豁免而不是去物理修。另外还要检查时钟门控的 clk_gating_check。有些 ICG 单元默认是带 hold check 的如果前端的约束文件里没有正确设置 clock gating check 的 half cycle 或者 pulse width工具会报出过于悲观的 setup 违例。这里我会在 ICC2 里用report_clock_gating_check看一眼每个 ICG 的实际检查要求在 Innovus 里则用report_clock_gating -verbose确保约束文件里的设定和库里的要求一致。3. 第二招从约束和结构上“釜底抽薪”如果侦察完发现不是假违例也不是纯粹物理位置问题那就要考虑从约束层面和逻辑结构层面动刀了。这一招的核心思路是别让工具把时间浪费在错误的检查上也别让绕线资源浪费在不合理的逻辑结构上。3.1 约束层面的合法“豁免”multicycle path 的正确用法reg2icg 路径常见的功能特性是使能信号并不是每个周期都要变化的。比如一个 8 分频的时钟门控使能信号实际上几个周期才翻转一次。这种情况下默认的单周期setup1 cycle检查是过度悲观的因为信号提前一个周期到达就够了。我在 ICC2 里对这种路径的设置方法是set_multicycle_path -setup 2 -from [get_pins regA/Q] -to [get_pins icg_inst/EN] \ -start 2注意这里我加了-start 2意思是多周期路径的参考点是发起时钟的沿。在 Innovus 里写法略有不同set_multicycle_path -setup 2 -from regA/Q -to icg_inst/EN -start设置完之后务必要同步设置 hold 检查否则工具会把 hold 检查放到一个错误的周期上set_multicycle_path -hold 1 -from [get_pins regA/Q] -to [get_pins icg_inst/EN] -start这条命令的意图是setup 检查放宽到两个周期hold 检查也要相应顺延一个周期否则 hold 会被放到比原来更严格的位置导致修 setup 的时候又冒出一堆 hold 违例。这里有个非常容易踩的坑改了 setup 忘了改 hold结果 tns 反而变大然后在群里抱怨工具乱来。说白了约束是两面的放宽了 setup 就要同步调整 hold 的检查窗口。3.2 逻辑结构层面的优化让工具“够得着”有些 reg2icg 路径的问题是前端综合阶段产生的结构性缺陷典型的就是使能信号经过了太长的逻辑链。比如一个使能信号先跟 module A 的 busy 信号做了 AND再跟 module B 的 valid 信号做了 OR最后又取反再与叠了三级逻辑。这种结构后端不是不能修但每修一级都要加 buffer面积、功耗全涨上去而且容易造成局部拥塞。如果碰到这种情况我的做法是回到综合阶段在 DC 或者 Genus 里加上set_clock_gating_style的相关配置让工具更激进地做时钟门控逻辑重组。具体到后端我偶尔也会直接在网表里找一些等效变换的空间比如把AND 后接 INV换成NAND或者把 OR-AND 结构重构成 AOI 单元减少逻辑深度。但在 ICC2 和 Innovus 里我不会手动去 ECO 网表除非万不得已。更稳妥的做法是在约束里把 ICG 的捕获时钟往后调一点也就是所谓的“useful skew”。比如在 ICC2 里set_clock_latency -late 0.2 [get_pins icg_inst/CK]当然这种设定一般只做在局部而且必须保证改完之后不会对相邻路径产生负面影响。Innovus 里也有类似的set_clock_latency命令但我不太建议新手直接用这个因为它本质上是“欺骗”工具改的是约束而不是真实的物理实现如果后端流程里后续又跑了 CTS这 0.2ns 的 latency 设置会被覆盖掉产生误导。3.3 使用有用的偏斜useful skew来平衡时间预算严格来说useful skew 是 placement/CTS 阶段的一把双刃剑。reg2icg 路径天然适合用它因为捕获端是 ICG 的时钟引脚而这个引脚往往没有其他逻辑相连调整它的时钟延迟不会影响太多别的路径。在 ICC2 里我会先手动挑几条最恶劣的 reg2icg 路径使用create_clock_skew这类命令给 ICG 的时钟引脚加一个小的延迟预算。然后跑 incremental CTS看看整体 timing 是否变好。在 Innovus 里CTS 阶段用的命令类似set_clock_tree_exceptions -pin ... -skew。必须提醒一句这个招只适合在真实时钟树偏差确实存在而且你确认可以通过改变 CTS 结构来平衡的情况下使用。如果单纯靠加约束把负数掰正最后做出来的时钟偏差虽然在工具报告里看不出问题但流片回来很可能就是一个 timing 失败的片子。4. 第三招物理实现层面的“定点清除”如果前两招用完还是有违例那就别犹豫直接用物理手段对路径进行定点优化。这一招在 ICC2 和 Innovus 里都有对应的自动化流程关键是你要知道在什么时候用、怎么用、用完之后怎么验证。4.1 ICC2 里的优化策略选择与参数调整ICC2 里对 reg2icg 这类路径的优化核心是optimize_clock_tree和opt_design两个阶段的不同开关。CTS 之后的第一个动作我会跑clock_opt_design这是 ICC2 自己的 CTS 优化流程。如果跑完了还有 setup 违例再用opt_design -setup做增量优化。这里有个参数值得重点关注ccd_clock_opt_flow。ICC2 的 CCDConcurrent Clock and Data优化是专门处理时钟树和数据路径并发优化的对于 reg2icg 这种数据路径和时钟树强关联的场景非常有效。我的实际配置是set_app_options -name ccd.clock_opt_flow -value post_clock_opt_optimize_ccd set_app_options -name ccd.max_transition_ratio -value 0.5 set_app_options -name ccd.max_capacitance_ratio -value 0.5这几个参数的意思是在 CTS 之后的 clock_opt 阶段开启 CCD 优化并且限制优化时对 transition 和 capacitance 的调整幅度不超过原值的 50%。这样既能让工具去挪 buffer、改 size又不会因为改动太大导致局部区域的物理实现崩溃。如果跑完clock_opt_design还是有单条路径卡住我会用focus_opt_design针对这些路径做定点优化focus_opt_design -from [get_pins regA/Q] -to [get_pins icg_inst/EN] -setup这条命令会只优化指定的路径不会动整个设计适合在快要 signoff 的时候用能省不少 runtime。4.2 Innovus 里的引擎调优与局部布线优化Innovus 的流程里CTS 之后用的是optDesign来做 setup 优化。如果是 reg2icg 的违例我一般不会一上来就整芯片跑optDesign而是用带-setup且指定时钟引脚的局部模式。实际命令长这样optDesign -setup -clock icg_inst/CK -prefix reg2icg_fix这里-clock的作用是让工具只优化指定时钟引脚相关的路径。跑完这一轮之后我会再跑一次optDesign -postRoute确保 ECO 绕线做完之后之前修的路径没有被破坏。Innovus 里还有一个很关键的引擎选项setOptMode -usefulSkew true。这个开关默认可能是关的打开之后工具会主动利用 ICG 引脚附近的时钟偏斜来改善 setup。配合set_ccopt_property里的寄存器合并register merging选项有时候效果立竿见影。我常用的几组参数如下setOptMode -usefulSkew true setOptMode -fixFanoutLoad true setOptMode -maxDensity 0.75 setOptMode -holdFixing false最后一行-holdFixing false要特别注意我只有在确保整个芯片的 hold 已经没有问题的情况下才会关掉 hold fixing否则工具可能会在优化 setup 的时候破坏已有的 hold 收敛状态。4.3 手动 ECO 的兜底方案工具自动优化完之后偶尔还会剩下一两条顽固违例这种情况我基本靠手动 ECO 兜底。手动 ECO 的核心思路是在靠近 ICG 的 EN 端加一个 buffer把上游的 transition 和 load 分摊掉。在 ICC2 里我通常的操作是create_buffer -name BUF_FIX_1 [get_ports icg_inst/EN] connect_net [get_nets net_en] BUF_FIX_1/A然后在 Innovus 里类似ecoAddRepeater -cell BUF_X2 -net net_en -term icg_inst/EN -name BUF_FIX_1加完 buffer 之后别忘了重新跑一遍 STA确认这条路径的 transition 是否有改善slack 是不是翻正了。如果 buffer 加在很拥塞的区域有可能导致局部 congestion 变严重所以要顺手跑一下 global route congestion 的检查。另外还有一个容易被忽略的点手动 ECO 加的 buffer 要尽量靠近 ICG而不是靠近发起端寄存器。因为这条路径的问题是数据信号到达太晚缓冲器放在接收端可以缩短信号线长度、降低负载电容加速信号跳变这比放在中间某个位置更有效。我自己曾经犯过把 buffer 放在路径中间的错误结果 slack 没改善多少反而增加了绕线阻塞费了好大劲才排查出来。5. 实战数据对比同一颗芯片ICC2 与 Innovus 的修复效果说了这么多理论和方法最后放一组实测数据。这是某颗 MCU 芯片里的一个 reg2icg 路径时钟频率 200MHz周期 5ns工艺 28nm HPC这条路径经过两级组合逻辑驱动 ICG 的 EN 端。5.1 修复前两条路径的 Baseline 情况在 ICC2 和 Innovus 两套工具里用同样的约束文件、同样的库文件CTS 跑完之后这条路径的时序表现如下工具setup slack (ns)transition at EN (ns)逻辑层级备注ICC2 默认CTS-0.420.192严重违例Innovus 默认CCopt-0.280.162违例较轻可以看到默认流程下 Innovus 的 CCoptClock Concurrent Optimization引擎对这条路径的处理比 ICC2 好一些大概少了 0.14ns 的违例量。但不管是 -0.42 还是 -0.28都是不满足 signoff 标准的必须继续修。5.2 修复后两套工具各自的“杀手锏”针对 ICC2我采用了“CCD优化手动buffer”的组合方案。先跑了clock_opt_design -from [get_pins ...] -to [get_pins icg_inst/EN]让工具自动调整时钟门控路径上的 buffer 位置和尺寸随后又加了一颗 BUF_X4 靠近 ICG 的 EN 端。整体修复后的报告显示 setup slack 从 -0.42ns 提升到 -0.03ns虽然还没有完全达到 0但已经逼近临界值再配合 multicycle path 约束把真正的 check 放宽到两个周期最终这条路径就 clean 了。针对 Innovus我采用了“optDesign 局部优化usefulSkew”的组合。先打开了setOptMode -usefulSkew true然后跑optDesign -setup -clock icg_inst/CK -prefix reg2icg_fix工具自动在 ICG 的时钟引脚附近调整了几级 buffer给 EN 信号争取到了更宽松的窗口。修复后 setup slack 从 -0.28ns 提升到 -0.01ns同样是配合多周期约束达到 signoff clean。工具setup slack 修复前 (ns)setup slack 修复后 (ns)优化耗时额外面积 (um^2)ICC2-0.42-0.0312分钟6.8Innovus-0.28-0.019分钟5.2从数据上看Innovus 的 CCopt 引擎对 reg2icg 这种路径的默认优化能力稍微强一些修复耗时也更短ICC2 则需要更依赖人工介入和 CCD 选项的开启。但两者的最终 slack 都收敛到了 -0.03ns 以内配合多周期约束后均可满足 signoff。额外面积方面Innovus 方案少了约 1.6 um^2主要原因是它通过 useful skew 而不是物理 buffer 来吸收延迟。5.3 数据背后的经验解读可能有人会问为什么两边都没能直接修到正 slack最后还是靠 multicycle path 才过关这里我想说明一点对于 reg2icg 路径如果前端功能允许使能信号提前一拍有效那用 multicycle path 本身就是一种高效且低成本的方案。它不消耗额外的面积和功耗唯一要求是你对电路功能有足够信心知道“两拍”不会破坏功能。我的个人习惯是先看功能再看时序最后才动物理。如果功能允许优先用约束解决如果功能不允许再用物理手段。这个顺序在这颗芯片的多个 reg2icg 路径修复中都验证过效率最高。6. 常见问题与排查技巧实录在实际项目里修 reg2icg 违例经常遇到一些诡异的现象这里挑几个我踩过的坑分享出来希望能帮你少走弯路。6.1 为什么改了约束CTS 之后又打回原形有一个典型的场景你在 pre-CTS 阶段设置了set_multicycle_path当时跑 STA 确实 clean 了。但是 CTS 跑完之后同样的约束再报时序发现原来的路径又开始违例了而且违例数值和没设约束之前几乎一样。这个问题的根源在于CTS 工具的路径划分和 STA 工具不完全一致。ICC2 的clock_opt_design和 Innovus 的ccopt_design在构建时钟树时未必会严格考虑你手动加的 multicycle path 约束对 ICG 检查窗口的影响。换句话说工具在平衡时钟树时使用的是默认的单周期检查假设导致时钟树被过度平衡over-balanced真正到了 STA 用 multicycle 检查时却发现数据路径与时钟路径的实际偏差已经超出一开始的预算。解决办法是在 CTS 之前就把 multicycle path 约束写进 SDC并且在 CTS 之后不要重新读入旧的 SDC 覆盖它。另外在 ICC2 里可以检查report_qor里的multicycle path统计确认工具确实考虑了这些约束在 Innovus 里则用report_ccopt_skew_groups来确认。6.2 为什么加上 buffer 反而更差了有时候你手动在 reg2icg 路径上加了一颗 bufferslack 不但没有变好反而恶化了几十皮秒。第一次碰到这种问题我也懵了后来仔细看了报告才发现buffer 加的位置不合适导致上游驱动 buffer 的线网net变长电容变大反而让信号到达时间更晚了。所以手动加 buffer 前建议先看一下当前路径的 fanout 和 net 长度。如果 net 本身已经很长再加 buffer 会把原来的长线变成两段更长的线并不会改善信号延迟。这时候更好的选择是把 buffer 加在靠近 ICG 的位置并且尽量选驱动能力大一点的型号比如 BUF_X8 而不是 BUF_X2。另外还要检查 buffer 的输入引脚朝向如果方向接反了工具不会报错但 net 的绕线长度会明显增加因为信号要先绕到 buffer 的 A 端再从 Z 端绕出去相当于走了一个 U 型。这种情况在 layout 里一眼就能看出来。6.3 如何验证修复结果是否“真”修复了最后一个问题也是最容易被忽略的修完 setup 之后一定要检查 hold尤其是 reg2icg 路径。因为很多 setup 修复手段比如加 buffer、调整时钟树都会同时改变路径延迟如果 setup 修好了hold 可能又冒出来。我的验证流程分三步第一步跑report_timing -delay_type min检查这条路径的 hold slack第二步跑report_clock_timing检查 ICG 引脚的时钟 transition 是否仍然满足库要求第三步做形式验证formal verification或者至少跑一遍verify_power确保改过的地方没有改变逻辑功能。在 ICC2 里最后我还会跑write_sdf和write_verilog把修完的网表导出给后面的 signoff 工具使用在 Innovus 里则用saveDesign保存整个修复后的数据库。这样即使后面发现新问题也能快速回溯到当前状态不用重头再来。我自己在多个项目里的体会是reg2icg 的 setup 违例不是一个“一次性搞定”的问题它需要你在约束、结构、物理实现三个层面来回迭代。别指望一把梭更别指望纯靠工具自动优化就能一次过。把这三个招按顺序用好至少能解决项目中 90% 以上的 reg2icg 违例。剩下的 10%就得靠你对电路功能的深入理解和对工具的细致调教了。
返回列表