ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Innovus分段时钟网络:stop pin与ignore pin实战指南

2026/10/7 13:52:58 拓冰建站 浏览量
Innovus分段时钟网络:stop pin与ignore pin实战指南 1. 分段时钟网络为什么让人头疼做数字后端这行的估计没几个人没被时钟树平衡折磨过。尤其是碰到那种规模不大不小、但时钟结构特别拧巴的设计——比如一个模块内部有好几个时钟域每个域又只驱动一小撮寄存器工具默认的时钟树综合策略一跑要么是插入延迟大得离谱要么是几个分支之间怎么都平衡不了最后时序报告一片红。我印象特别深的是之前做过一个带传感器接口的芯片里面有个低速时钟域只驱动二十几个触发器但工具硬是给它建了一棵完整的时钟树buffer插了一长串skew倒是压下去了可功耗和面积全上去了而且跟主时钟域之间的平衡关系反而更难收敛。这种场景下分段时钟网络的概念就派上用场了。所谓分段就是把一个大的时钟树拆成几个相对独立的子网络每个子网络单独做综合和平衡最后再在顶层做整体协调。这样做的好处很明显局部时钟树的规模小了工具更容易找到最优解插入延迟可控功耗也更友好。但问题在于Innovus默认会把所有时钟引脚一视同仁地纳入全局时钟树综合它不知道你其实想把某几个分支单独拎出来处理。这时候就需要用到stop pin和ignore pin这两个看似不起眼、实则威力巨大的设置。这篇文章主要面向已经有一定Innovus使用经验的数字后端工程师尤其是那些正在被复杂时钟结构困扰、想找到更精细控制手段的人。我会从这两个概念的本质讲起结合我实际项目中的操作步骤把怎么设、为什么这么设、设完之后怎么验证一步步拆开来说。如果你之前只是听说过这两个词但没真正用过或者用过但效果不理想那接下来的内容应该能帮你省下不少试错时间。2. stop pin与ignore pin的本质区别2.1 从时钟树综合的视角理解这两个概念Innovus在做时钟树综合的时候会把时钟源到所有时钟端点之间的路径全部纳入考虑。这里的时钟端点通常包括触发器的时钟引脚、时钟门控单元的时钟输入、以及一些宏单元的时钟输入。工具会根据这些端点的分布和约束自动决定buffer的插入位置、数量以及连线方式。stop pin的作用是告诉工具时钟树综合到这里就停了不要再往这个引脚的下游继续建树。换句话说stop pin本身仍然会被纳入时钟树工具会保证它被正确地驱动和平衡但它下游的电路不会被当作时钟树的一部分来处理。这在你想要把某个分支单独拿出来做局部时钟树的时候特别有用。ignore pin则更彻底一些工具直接忽略这个引脚既不把它当时钟端点也不往它下游建树。这个引脚在时钟树综合阶段会被当作普通信号处理或者完全不被纳入时钟网络的分析范围。ignore pin通常用在那些你确定不需要做时钟树平衡、或者下游电路有时钟树但你想在后续阶段单独处理的场景。两者的核心区别可以用一句话概括stop pin是“到此为止但我在树上”ignore pin是“我不在树上别管我”。理解这一点后面所有的操作逻辑就都顺了。2.2 什么时候该用stop pin什么时候该用ignore pin这个问题我在实际项目中反复被问到也踩过不少坑。我的经验是判断标准主要看你对下游电路的控制意图。如果你希望下游电路仍然被当作时钟域的一部分来对待只是想把综合的粒度拆细一点那就用stop pin。比如一个时钟经过分频器之后驱动一个独立的低速模块你希望这个低速模块的时钟树单独做但最终还是要跟主时钟做平衡这时候在分频器的输出端设stop pin就非常合适。如果你压根不想让工具碰下游的时钟树或者下游电路有时钟但你不希望它影响当前时钟树的综合结果那就用ignore pin。典型场景是那些异步时钟域、或者你打算在顶层单独处理的时钟分支。还有一种情况是某些宏单元的时钟输入你不想让工具自动插buffer因为宏内部已经有自己的时钟处理逻辑这时候用ignore pin就能避免工具做无用功。注意ignore pin设置之后工具不会对该引脚下游做任何时钟树综合这意味着你需要自己确保下游电路的时钟质量。如果下游有时序要求后续必须通过其他手段来满足。2.3 两个设置在Innovus中的底层处理逻辑从工具实现的角度看stop pin和ignore pin都会影响时钟树综合阶段的“时钟端点识别”和“树构建范围”。Innovus在跑clock tree synthesis之前会先根据约束文件、SDC以及这些特殊设置生成一个内部的时钟树拓扑图。stop pin会被标记为“叶子节点但可继续驱动”而ignore pin则直接被排除在这个拓扑图之外。这个区别在log文件里其实能看出来。设了stop pin之后你会在时钟树综合的报告里看到这个引脚被列为一个sink但它的下游没有buffer插入记录。而ignore pin则完全不会出现在时钟树的sink列表里。我刚开始用的时候没注意看log结果设错了类型导致下游时钟根本没做树时序直接崩了。后来养成了习惯每次设完都要去log里确认一下工具到底怎么理解的。3. 在Innovus中设置stop/ignore pin的完整流程3.1 准备工作确认时钟结构和约束在动手设stop/ignore pin之前有几件事必须先做清楚。首先是用report_clock_tree或者check_clock_tree把当前的时钟结构摸一遍看看有哪些时钟域、各自的端点分布、有没有跨时钟域的路径。这一步很多人会跳过直接去设pin结果设完了发现跟预期完全不一样。其次是要确认SDC里的时钟定义是否完整。stop pin和ignore pin的设置是依附于时钟约束的如果某个时钟压根没在SDC里定义你设了stop pin工具也不会理你。我一般会先用report_clocks确认所有时钟都正确创建了再用report_clock_tree -structure看一下工具当前识别到的时钟树长什么样。还有一个容易被忽略的点是时钟门控单元的处理。如果你的设计里有ICGICG的时钟输入和输出在时钟树里的角色是不一样的。通常ICG的输入侧是时钟树的一部分输出侧则可能成为新的分支起点。如果你想在ICG输出侧设stop pin要确保工具能正确识别ICG的使能逻辑否则可能会出现时钟树断裂的情况。3.2 具体命令与参数详解Innovus里设置stop pin和ignore pin主要通过set_clock_tree_exceptions命令来完成。这个命令的参数比较多我挑最常用的几个来说。设置stop pin的基本语法是set_clock_tree_exceptions -stop_pins {pin_list}其中pin_list可以是具体的引脚名也可以是通配符匹配的一组引脚。比如你想把某个模块下所有分频器的输出端都设为stop pin可以这样写set_clock_tree_exceptions -stop_pins [get_pins u_div/*/Q]设置ignore pin的语法类似set_clock_tree_exceptions -ignore_pins {pin_list}这两个命令都可以配合-clock参数来限定只对某个时钟生效避免误伤其他时钟域。比如set_clock_tree_exceptions -stop_pins [get_pins u_slow_div/Q] -clock CLK_SLOW还有一个很实用的参数是-exclude_pins它跟ignore pin有点像但又不完全一样。-exclude_pins是把引脚从时钟树综合中排除但工具仍然知道它是个时钟引脚只是不主动去平衡它。这个在有些场景下比ignore pin更合适因为ignore pin会让工具完全“忘记”这个引脚的存在后续做时序分析时可能会出问题。提示设完这些exception之后一定要用report_clock_tree_exceptions确认一下工具实际生效的设置避免因为通配符写错或者时钟名不匹配导致设置没生效。3.3 设置后的验证与调试方法设完stop/ignore pin只是第一步更重要的是验证效果。我通常会用以下几个手段来检查第一跑一次clock_tree_synthesis然后看log里关于sink和buffer插入的记录。如果stop pin设置正确你应该能看到工具在这个引脚处停止了buffer插入下游没有新的时钟buffer。如果ignore pin设置正确这个引脚应该完全不出现在时钟树的sink列表里。第二用report_clock_tree -summary看各个时钟域的插入延迟和skew。分段之后每个子网络的skew应该更容易收敛整体插入延迟也可能有变化。如果发现某个分支的延迟突然变得很大可能是stop pin设得太靠前导致下游驱动能力不足。第三做时序分析。report_timing看时钟路径上的延迟是否合理特别是跨时钟域的路径。如果发现setup或hold出现异常要回头检查是不是ignore pin导致某个时钟分支没做树。我自己的习惯是每次调整stop/ignore pin之后都会保存一个版本然后跑一次完整的时序分析对比调整前后的WNS和TNS。这样能直观地看出设置的效果也方便回滚。4. 分段时钟网络的优化策略与实战案例4.1 一个真实项目的时钟结构拆解拿我之前做过的一个MCU项目来说里面有三个时钟域主时钟48MHz、低速时钟32kHz、以及一个调试用的10MHz时钟。主时钟驱动核心逻辑低速时钟只驱动RTC和几个always-on的寄存器调试时钟只在测试模式下用。工具默认跑时钟树综合的时候把三个时钟域全部纳入了一棵大树结果低速时钟那条分支插了十几个buffer延迟比主时钟还大而且因为驱动能力不匹配skew怎么都压不下去。调试时钟更离谱明明只在测试模式下用工具还是给它建了完整的树白白浪费面积和功耗。我的处理方式是在低速时钟的分频器输出端设stop pin让工具单独给这个分支做树在调试时钟的根节点设ignore pin让工具完全忽略它后续在顶层手动处理。这样调整之后主时钟树的规模缩小了将近三分之一插入延迟从原来的1.2ns降到了0.8ns低速时钟的skew也从150ps压到了40ps以内。4.2 分段后的平衡策略与参数调整分段之后每个子网络需要单独设置综合参数。Innovus里可以通过set_clock_tree_options来针对特定时钟或特定引脚设置不同的目标skew、最大插入延迟、buffer类型等。比如对低速时钟分支我会把目标skew设得宽松一些因为它的时序要求本来就不高没必要为了压skew浪费太多资源set_clock_tree_options -clock CLK_SLOW -target_skew 100ps -max_insertion_delay 1.5ns对主时钟分支则要严格一些set_clock_tree_options -clock CLK_MAIN -target_skew 50ps -max_insertion_delay 1.0ns还有一个关键点是跨时钟域的平衡。分段之后不同子网络之间的延迟差异可能会变大如果它们之间有数据交互就需要在顶层做额外的平衡。我通常会在分段综合完成后用report_clock_tree -cross_corner看一下各分支之间的延迟差如果超过半个时钟周期就要考虑在顶层加一些延迟补偿或者调整约束。4.3 功耗与面积的权衡取舍分段时钟网络的一个直接好处是功耗和面积的优化。因为每个子网络的规模小了工具不需要为了平衡全局而插入过多的buffer。但这里也有一个权衡如果分段太细每个子网络都需要自己的根buffer和驱动单元反而可能增加面积。我的经验是分段的数量控制在3到5个比较合适。太少了起不到优化效果太多了管理成本高且可能适得其反。具体怎么分要看时钟域的驱动规模和时序要求。一般来说驱动寄存器数量少于50个的时钟域可以考虑单独分段超过200个的最好还是跟主时钟一起做否则子网络的驱动能力可能不够。另外stop pin的位置也很关键。设得太靠前下游驱动能力不足设得太靠后分段效果不明显。我一般会在分频器或者时钟门控单元的输出端设stop pin这样既能保证上游有足够的驱动又能让下游独立做树。5. 常见问题与排查技巧实录5.1 stop pin设了没效果怎么办这是最常见的问题。明明设了stop pin但工具还是往 downstream 插了一堆buffer。原因通常有几个第一引脚名写错了。Innovus的引脚名是区分大小写的而且层次分隔符要用对。我建议用get_pins配合通配符来获取而不是手写。比如get_pins -hier *u_div/Q这样。第二时钟约束不完整。如果stop pin所在的时钟域没有在SDC里定义工具不会把它当作时钟路径来处理stop pin自然也不生效。用report_clocks确认一下。第三exception被后面的设置覆盖了。Innovus里时钟树exception是有优先级的如果后面又设了一个更宽泛的exception可能会把前面的覆盖掉。用report_clock_tree_exceptions看最终生效的是哪个。5.2 ignore pin导致时序违例的修复思路ignore pin用不好确实容易出问题因为它让工具完全忽略了一个时钟引脚。如果这个引脚下游有时序路径工具不会为它做任何时钟树优化时序违例几乎是必然的。修复的思路有两种一是改用stop pin让工具至少把这个引脚纳入时钟树保证基本的驱动和平衡二是在顶层手动为这个分支做时钟树比如用specify_clock_tree或者手动插入buffer。我个人的建议是除非你非常确定下游电路不需要时钟树优化否则尽量用stop pin而不是ignore pin。ignore pin更适合那些异步时钟域或者测试逻辑这些路径通常有时序例外或者不需要严格时序收敛。5.3 分段后skew反而变大的原因分析分段的目的本来是优化skew但有时候分段之后skew反而变大了。这种情况通常是因为子网络之间的平衡没做好。比如主时钟分支和低速分支之间的延迟差太大导致跨时钟域的路径时序变差。解决办法是在分段综合完成后做一次全局的时钟树平衡。Innovus提供了clock_tree_balance之类的命令可以在不改变各子网络内部结构的前提下调整它们之间的延迟关系。另外也可以通过调整各子网络的max_insertion_delay来间接控制它们之间的延迟差。还有一个可能的原因是buffer类型选择不当。不同子网络如果用了不同驱动能力的buffer延迟特性会不一样。我一般会在分段综合时统一指定buffer类型避免引入额外的偏差。5.4 常见问题速查表问题现象可能原因排查方法解决思路stop pin不生效引脚名错误或时钟未定义report_clock_tree_exceptions用get_pins重新获取引脚名确认SDCignore pin导致时序崩下游电路未做时钟树report_timing看时钟路径改用stop pin或手动做树分段后skew变大子网络间平衡未做好report_clock_tree -cross_corner调整max_insertion_delay或做全局平衡功耗反而增加分段过细导致根buffer增多对比分段前后的面积报告减少分段数量合并小分支工具报时钟树断裂stop pin设在了错误位置检查log中的时钟树拓扑调整stop pin位置到分频器输出端6. 一些实操心得与避坑建议6.1 我的调试习惯与版本管理做时钟树调试最怕的就是改来改去最后不知道哪个版本是对的。我的习惯是每次调整stop/ignore pin之前先保存一个版本然后在脚本里把这次调整的目的和预期效果写清楚。Innovus的脚本是可以加注释的别嫌麻烦过两天回头看的时候你会感谢自己。另外我建议把stop/ignore pin的设置单独放在一个tcl文件里跟主流程脚本分开。这样调试的时候只需要改这一个文件不用动整个流程。而且方便做A/B对比把不同设置的效果记录下来。6.2 跟其他时钟树约束的配合使用stop/ignore pin不是孤立的它需要跟其他时钟树约束配合才能发挥最大效果。比如set_clock_tree_options里的-target_skew、-max_insertion_delay、-buffer_list这些参数都会影响分段后的综合结果。我一般会先设好全局的时钟树选项再针对每个分段单独调整。还有一个容易忽略的是set_clock_gating_check和set_clock_groups。如果分段之后时钟域之间的关系变了这些约束也要相应更新否则时序分析的结果会不准确。6.3 对新手的一些建议如果你是刚开始接触Innovus的时钟树综合我的建议是先从简单的设计练起把stop pin和ignore pin的基本用法摸熟。不要一上来就在复杂设计上试出了问题很难定位。另外多看log。Innovus的log里其实信息很全工具怎么理解你的设置、怎么建树、插了哪些buffer都能从log里找到。我见过很多新手设完pin就不管了结果跑完发现效果不对又不知道从哪查起。养成看log的习惯能省很多时间。最后别怕试错。时钟树综合本身就是一个需要反复调整的过程没有一次就能设对的。我做了这么多年每次碰到新的时钟结构还是要试好几轮。关键是每次调整都要有明确的目的和验证手段这样才能积累经验。6.4 后续可以扩展的方向分段时钟网络这个思路其实还可以延伸到更多场景。比如多电源域的设计里不同电源域的时钟树可以分别做最后在顶层协调。再比如3D IC或者chiplet设计里跨die的时钟树也可以分段处理。这些场景下stop/ignore pin的用法会更复杂但核心逻辑是一样的明确哪些部分需要独立处理哪些部分需要统一平衡。另外Innovus的版本更新也会带来一些新的时钟树综合功能比如machine learning based的时钟树优化。这些新功能跟stop/ignore pin结合使用可能会有更好的效果。我最近在试的一个方向是用ML预测最优的stop pin位置初步结果还不错等成熟了再单独写一篇分享。