ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

数字后端CTS实战:从时钟信号原理到Innovus时钟树综合优化

数字后端CTS实战:从时钟信号原理到Innovus时钟树综合优化 做数字后端这几年我越来越觉得时钟树综合CTS是整个流程里最考验“感觉”的一步。布局布线做得再漂亮时钟信号处理不好芯片一跑起来就是各种时序violation甚至直接functional fail。很多刚入行的朋友总觉得CTS就是把工具跑一遍看看skew达标就完事了但实际上真正理解时钟信号本身的行为才是把这步做好的前提。这篇笔记我就把自己学习CTS时关于时钟信号的心得整理出来从概念到实操再到我们趟过的坑一次性说清楚。这篇内容适合正在学习数字IC后端设计的学生、刚转行做物理实现的工程师以及那些被CTS结果反复折磨的同行。我会尽量避开教科书式的堆砌多用我们项目里真实遇到的情况来解释希望能帮你在CTS这条路上少走点弯路。1. 时钟信号为什么这么难伺候1.1 理想时钟与真实时钟的差距在学校里我们学数字电路时钟就是一个完美的方波上升沿一到所有触发器同时采样。但真实芯片里时钟信号是实实在在的物理信号从一个点传到另一个点需要时间而且每个触发器的距离不一样到达时间也就不一样。这就引出了时钟树综合的第一个核心矛盾我们想要的是一个“同时到达”的理想时钟但物理世界给我们的却是“有先有后”的真实时钟。时钟信号在芯片里的传播就像一群人听口令做动作。如果指挥官站在操场中央声音传到每个学生耳朵里的时间不一样那大家起跑的时间自然不一样。时钟树综合要做的就是通过各种缓冲器、反相器的组合让“指挥官的声音”尽可能同时传到每个“学生”耳朵里或者按照我们想要的时间差到达。这里有个概念必须分清楚时钟偏斜clock skew和时钟延迟clock latency。时钟延迟指的是时钟信号从源头到某个触发器时钟端的绝对传播时间偏斜则是不同触发器之间到达时间之差。很多初学者会把这两个搞混实际项目里我们更关心的是偏斜因为它直接影响时序收敛的难度。1.2 CTS在数字后端流程中的位置数字后端的标准流程大致是综合synthesis→ 布局规划floorplan→ 标准单元摆放placement→ 时钟树综合CTS→ 布线routing→ 时序修复timing closure。CTS位于布局和布线之间这个位置非常关键此时各单元的位置已经固定CTS在真实的物理位置上构建时钟网络得出比综合阶段更精确的时钟延迟信息。为什么CTS不在综合阶段就做掉因为综合阶段还没有真实的物理信息单元的位置都是估算的那时候做出来的时钟树不落地到了后端还是要推翻。在Innovus这类工具里CTS之后会进行一次带真实时钟延迟的时序分析这次分析的结果比综合阶段的“理想时钟”分析可信得多很多setup/hold问题的端倪就是在这个时候暴露出来的。1.3 时钟信号的特殊之处时钟信号和普通数据信号最大的区别在于它要同时到达成千上万个触发器而且每到一个地方都要驱动一个不小的负载。这就让时钟网络变成了芯片里扇出最大、走线最长、翻转率最高的信号网络之一。如果处理不好它不仅是时序问题的根源还是功耗和信号完整性问题的高发区。时钟树综合本质上就是在设计一棵“树”树根是时钟源比如PLL的输出或芯片的clock input树叶是各个触发器的时钟端中间的枝干就是各级缓冲器。工具要自动决定这棵树怎么长让所有叶子端到达的时钟沿满足时序要求。这里头涉及一个很朴素的问题这棵树用什么单元来搭搭成什么样才能让延迟尽量均衡2. 时钟树综合前的准备功课2.1 必要的SDC约束设置CTS不是凭空跑的它的输入除了布局后的设计数据库就是约束文件。用Innovus做CTS之前我习惯把SDC文件里跟时钟相关的约束先梳理一遍。create_clock定义时钟的周期和波形这是最基本的set_clock_uncertainty设置时钟不确定性里面包含了jitter和skew的预算set_clock_transition设置时钟边沿的最大上升下降时间set_clock_latency是源端延迟一般由PLL或片外时钟路径决定。这里我想多说一句set_clock_uncertainty。很多项目为了给后续留余量会把uncertainty设得比较大这在CTS之前还能接受但如果你把所有margin都压在uncertainty里工具在构建时钟树时就会过度约束导致插入过多的缓冲器延迟和功耗双双上涨。合理的做法是把能预估的jitter放在uncertainty里skew部分留给CTS通过物理实现去优化不要把所有东西都混在一起。2.2 时钟单元库检查与选择CTS需要使用专门的时钟单元最常见的是时钟缓冲器clock buffer和时钟反相器clock inverter。这些单元和普通逻辑单元最大的不同是它们的驱动能力强、延时曲线对称性好、对不同负载的延滞变化更平滑而且通常不带使能端逻辑功能非常简单纯粹。用Innovus做CTS前我会确认库里有没有足够的时钟单元族每个驱动强度档位是否齐全。一个常见问题是有些库的时钟单元数量不足工具在需要平衡负载时没有合适的选择只能过度使用某一档位的单元导致树层级不平衡。另外时钟反相器对的使用也是一个心得反相器对invinv比单个buffer在P/N管尺寸匹配上更好做对占空比失真和电源噪声的抵抗力更强。很多先进工艺节点上CTS工具默认就更青睐反相器对方案。2.3 时钟网络定义与排除工具怎么知道哪些pin应该接时钟树这需要我们在约束或设置里明确指定。Innovus里通常通过specifyClockTree或类似的命令来定义时钟树的根节点、叶子节点以及需要走时钟网络的单元。标准做法是让工具根据SDC里的时钟定义自动推导出来但对于一些特殊的时钟网络比如门控时钟的使能端、分频器的输出可能需要手动补充定义。还有一个必须做的功课是set_clock_tree_exceptions用来排除掉不需要CTS优化的引脚比如某些慢速接口的时钟端或者一些已经确定不需要平衡的sink。如果不做排除工具浪费资源去平衡一个无关紧要的路径反而让关键路径的优化受影响。我们项目里就遇到过因为忘记排除一个测试模式的时钟端导致主时钟的skew被拖累的情况。3. 时钟树综合的核心原理与实操记录3.1 时钟树怎么“长”出来的时钟树综合的过程可以理解为从根节点开始逐级插入缓冲器把信号分配给下面所有叶子节点。工具内部会采用类似聚类算法的办法先把所有sink按照位置和负载聚类成若干组每组分配一个公共的缓冲器然后递归向上构建直到回到根节点。每一级的目标是让所有叶子到根的距离近似相等最终实现延迟平衡。实际芯片中触发器的分布往往不均匀有的地方密集有的地方稀疏。如果密度差异太大工具就需要在稀疏区域绕长线或者插入冗余负载来匹配延迟。这就是为什么我们经常在floorplan阶段就要关注时钟单元的分布情况——时钟树综合虽然能优化但它的优化范围是有限的如果floorplan本身不友好工具再努力也白搭。3.2 从长时钟到短时钟的演变这里聊聊我对时钟树长度控制的理解。早期工艺节点大家都希望时钟树延迟尽量小因为延迟越小整个芯片的时序越容易收敛。但在先进工艺下情况发生变化太短的时钟树意味着缓冲器级数少抗片上误差on-chip variation的能力就会下降因为每级缓冲器都能起到一定的“重新定时”效果抵消部分前面的偏差。所以现在的CTS工具里我们经常需要设置一个目标延迟范围比如300ps到500ps让工具在这个范围内优化。过短不行过长功耗和延迟都受不了。设置这个值的时候我是参考工艺库中单元延时的统计数据来定的没有固定公式但可以根据前几轮CTS的平均延迟来微调。3.3 Innovus实操核心命令与流程示例下面我给出一个简化版但流程完整的Innovus CTS脚本框架这是基于我们实际项目的经验整理出来的# 1. 设置时钟树综合模式 set_db cts_enable_ccd_restructure true set_db cts_target_max_transition_time 0.1ns set_db opt_clock_tns_target_percentage 30 # 2. 指定时钟树端点排除不需要的引脚 specifyClockTree -net clk -root clk_port set_clock_tree_exceptions -dont_buffer_pin [get_pins {u_test_mux/a}] # 3. 定义CTS阶段的时序和功耗目标 set_db cts_buffer_max_skew 0.05ns set_db cts_leaf_max_skew 0.08ns set_db cts_use_inverters true # 4. 运行时钟树综合 ctsDesign # 5. 生成报告检查质量 report_clock_tree_summary report_clock_timing -type skew report_ccopt_skew这段脚本里ctsDesign是整个CTS阶段的核心命令它会同步完成时钟树的构建、优化和初步时序分析。cts_target_max_transition_time这个参数非常关键它限制了时钟信号的边沿速率如果设得太松信号边沿过缓会导致时序计算不准确和功耗上升设得太紧工具会插入大量缓冲器来满足面积和功耗急剧增加。一般来说先进工艺项目我习惯设置在周期的2%~3%左右。3.4 平衡策略与useful skew的应用经典的CTS目标是让所有sink的到达时间尽量一致也就是zero skew。但实际项目中我们往往可以利用useful skew来改善时序如果某个数据路径的setup余量特别紧张就可以让这条路径的终点触发器时钟晚到一点给数据多留一点到达时间反过来对hold问题也可以通过时钟提前来改善。在Innovus里实现useful skew比较直接工具会在ctsDesign之后根据时序分析结果自动调整部分时钟路径的长度来改善寄存器到寄存器的时序。当然前提是约束和时序报告足够准确。我们在跑完CTS之后一定会检查一次setup和hold的违例情况尤其是hold违例。因为CTS之后很多hold违例会暴露出来这些都需要记录下来留给后续的布线阶段或ECO阶段去修复。4. 常见时钟信号问题与排查技巧4.1 时钟偏斜超标的排查思路CTS跑完之后如果发现时钟偏斜报告里的数值远超预期比如目标0.05ns但实际到了0.15ns先不要急着怀疑工具坏了。我的排查顺序是先看报告里偏差最大的sink聚在后端还是前端如果都是集中在某个角落赶紧打开布局界面看那个区域的拥塞情况大概率是布线资源紧张导致工具无法找到合适位置插入缓冲器。还有一种隐蔽的情况是时钟树路径上经过了macros硬核模块的区域这些区域上面不能摆放缓冲器工具只能从旁边绕不仅绕线延迟大而且绕线路径未必一致偏斜自然就上去了。处理方案一般是在floorplan阶段给这些macros留出足够的绕线通道空间或者在CTS阶段用set_clock_tree_exceptions对那些绕远路的sink做特殊处理允许它们存在较大的延迟而不去强行平衡。4.2 CTS后的setup和hold违例CTS之后的第一轮时序分析最有价值因为这是第一次用真实的时钟延迟来分析时序。这时候最常出现的情况是hold违例突然增多。原因是综合阶段假设的是理想时钟hold分析往往非常乐观CTS后引入了真实的时钟延迟数据路径的延迟和时钟路径的延迟一旦不匹配hold就出问题了。遇到这种情况我一般先看违例的路径是不是集中在某些特定模块内如果是说明这些模块内部时钟偏差出现了问题优先去调整局部时钟网络。如果违例分散且数量多那就需要检查set_clock_uncertainty是否合理或者看看CTS阶段是否有单元尺寸选择不合理的情况。记住一个原则CTS阶段尽量把hold问题的苗头处理好越到后端修复成本越高。4.3 报告怎么读才有用Innovus的CTS报告信息量很大但我观察很多人只看最后的skew数值。我的习惯是分三步看先看report_clock_tree_summary里的整体结构确认树的级数、每级缓冲器数量和总延迟是否符合预期再看report_clock_timing -type skew里的具体sink分布找最大值和位置最后打开时钟树视图盯着可疑区域看具体路径走向。另外可以对比前一轮和后一轮CTS的关键指标来辅助判断。表格可以做出来给新同学也直观一些指标上一轮当前轮分析时钟总延迟780ps520ps明显下降注意对OCV的影响全局偏斜0.09ns0.04ns达标检查是否过约束缓冲器数量482366面积和功耗改善违规路径数120条45条时序收敛趋势良好看到总延迟下降的时候不用忙着高兴先进工艺下延迟太短反而要警惕因为OCV的影响占比会变大跨die的偏差可能把收益吃回去。4.4 时钟信号完整性与布线注意时钟网络在整个芯片里属于“重要干线”布线阶段一般会特殊照顾走线更宽、间距更大、周围加屏蔽线这些都是为了减少信号完整性问题。CTS本身不做这些操作但它决定了时钟网络的拓扑结构这个结构直接影响信号完整性。我遇到过一个问题CTS之后的时钟树某一条主干路径穿过了高翻转率的逻辑区域导致后端布线阶段出现严重的串扰时序结果反复横跳。后来检查发现CTS时如果提前设置了时钟网络的preferred routing layer和spacing rule让工具在构建时钟树时就把这些信息考虑进去这种问题完全可以避免。所以CTS阶段不能只想着时序还要把布线阶段的规则提前告诉工具让它统筹规划。5. 从CTS阶段延伸的几点学习建议学了CTS之后再回头看前面的布局和综合会有不一样的理解。比如在综合阶段我们给时钟设置ideal network就是为了让工具在优化逻辑时不考虑时钟延迟但到了CTS阶段所有时序分析都必须基于真实时钟。这种“理想”到“现实”的切换是数字后端学习过程中非常关键的一次思维转变。我建议新同学不要只停留在跑通流程的层面可以多尝试改几个参数看看结果怎么变。比如把cts_use_inverters从true改成false对比一下时钟树的级数和功耗把cts_buffer_max_skew从0.05ns改到0.02ns看看工具会不会插入更多缓冲器。这种“动参数、看报告、想原因”的训练比闷头看十篇文档都管用。我自己在CTS学习上还有一个深刻的体会早点建立“时钟树是整个芯片时序的骨架”这个意识。数据路径的一切努力最终都要落到与时钟沿的对齐关系上。理解了这一点你在看setup/hold、看OCV、看useful skew这些概念时都会通透不少。
返回列表