尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

时钟树综合(CTS)核心概念与实战:从Skew、Latency到时序收敛

时钟树综合(CTS)核心概念与实战:从Skew、Latency到时序收敛 做数字后端的人应该都有体会流片回来如果时钟有问题整颗芯片基本就废了。时序违例还能靠ECO补救时钟偏斜如果控不住尤其是那种跨die的偏斜可能连基本功能都跑不起来。所以时钟树综合CTS在整个数字后端流程里可以说是最考验功力的环节之一。这篇笔记想聊的就是CTS里头最核心的主角——时钟信号本身从定义、参数到工具里的处理方式再到实际项目中常见的坑尽量一次说透。这篇内容适合刚接触数字后端、准备跑第一个CTS的工程师也适合那些已经跑过几步流程但对工具报告里的Jitter、Skew、Latency还一知半解的朋友。我会从概念讲起但重点会放在工具实操和项目经验上毕竟那些报告和命令才是每天要面对的东西。1. 内容整体设计与思路拆解1.1 为什么CTS在数字后端里地位这么特殊做数字后端的人常说一句话Floorplan是骨架Placement是血肉CTS是神经系统。前两步把逻辑放对位置CTS则决定了这些逻辑之间能不能按时通信。举一个很直观的例子假设一个数据路径源寄存器到目的寄存器的组合逻辑延迟只有2ns但是时钟到达这两个寄存器的时刻差了0.5ns。如果数据是时钟上升沿发出、上升沿采到那这0.5ns会直接影响建立时间裕量。更麻烦的是如果在物理上离得很近的两个寄存器因为时钟路径上负载不同出现了0.3ns的偏斜那数据路径本来算好的时序就有可能在真实硅片上直接翻转结果。这就是CTS存在的意义在物理上构建时钟网络把时钟信号的到达时间差Skew控制到可接受范围同时减小延迟Latency保证芯片能在一个合理的主频下稳定工作。我见过不少刚入行的同事觉得CTS无非是让工具自动插buffer跑通就行。但实际上CTS的质量直接决定后续route的时序收敛难度也直接决定芯片能不能跑到目标频率。工具默认参数确实可以跑出结果但那个结果通常是“能用”而不是“好用”。想要“好用”必须自己理解时钟信号的特性并且愿意花时间去调。1.2 时钟信号在芯片里的三种存在形态理解CTS之前先要清楚时钟信号在芯片里是怎么演变的这决定了工具在各阶段如何处理它。第一个阶段是真实物理时钟也就是从芯片外部PAD进来的时钟或者由内部PLL产生的时钟。这个时候的时钟是真实存在的物理信号有RC延迟会受到工艺波动影响也是CTS要最终构建出来的对象。第二个阶段是理想时钟Ideal Clock。在综合和布局阶段工具假设时钟到达每个寄存器的时间完全相同没有延迟、没有偏斜、没有抖动。这时候做的STA静态时序分析只是一个非常粗粒度的检查只能用来排除明显的逻辑问题不能用来做精确的时序收敛。所有数字后端工具在place阶段都是按照理想时钟来优化逻辑只关注数据路径的物理距离和拥塞情况。第三个阶段是传播时钟Propagated Clock。CTS工具会用真实单元和真实绕线把时钟网络物理实现出来。时钟从源头到达各个寄存器走的是一条实实在在的RC网络每一段都有延迟每个单元都有delay不同路径之间的延迟差就是Skew。只有到了这个阶段时序分析才真正贴近实际硅片的行为。这个演化过程想说明一件事CTS是把“理想”变为“真实”的分水岭。在做CTS之前时序分析是虚的做完CTS之后时序分析才落地。这也是为什么业界常说CTS是数字后端最核心的环节之一。1.3 整篇笔记的内容走向接下来的章节我是这么安排的先从时钟信号的参数定义讲起帮你构建一个“什么是好的时钟”的认知框架。然后深入到CTS的核心实现环节解析工具如何从无到有构建时钟树包括长中短时钟树的策略选择。接着讲实操层面的核心技术比如Skew Group、有用偏差、报告分析这些每天都要用的东西。最后是信号完整性和实际项目中的问题排查把那些“跑完就挂”的典型案例摆出来分析。这样一条线走下来你既能理解CTS背后的逻辑也能在工具里实操落地。2. 核心概念时钟信号的参数与质量衡量2.1 时钟信号的三个核心参数Skew、Latency、Jitter围绕时钟信号有三个参数是天天要看的Skew、Latency、Jitter。它们分别刻画了时钟信号在“空间不一致性、时间延迟、瞬时波动”三个维度上的表现。Latency中文叫时钟延迟指时钟信号从源头到达某个寄存器时钟端的时间。它由两部分组成Source Latency时钟源到时钟树根节点的延迟包含片外走线或PLL内部延迟和Network Latency时钟树根节点到各寄存器端点的延迟。在物理设计里我们最头疼的往往是Network Latency因为它直接受时钟树缓冲器级数和绕线长度影响。工具会在约束里给你一个target latency的期望但实际是否满足取决于时钟树构建质量。Skew时钟偏斜指同一时钟域内时钟信号到达各个寄存器的时间差。这个差的本质是不同路径长度和负载不同导致的delay差。Skew是CTS要解决的头号问题。假设一个时钟域里有1万个寄存器工具希望到达这1万个寄存器的时钟沿尽量对齐。但物理上这是不可能的因为位置有远有近负载有大有小。工具能做的是把Skew压制到一个足够小的范围内让时序预算里的不确定性足够低。Jitter时钟抖动指时钟信号在时域上每个周期的边沿位置相对理想位置有微小随机偏移。这个偏移来自PLL自身的噪声、电源噪声、串扰是物理世界无法消除的。Jitter在CTS阶段通常作为外部约束输入你没法通过物理实现手段去消除它只能在时序分析时把它当作uncertainty的一部分扣除。从业这么多年我遇到过不少新人混淆这三个概念。其实有个很简单的类比Latency像是公交车从总站到达某一站的时间Skew是不同站点的公交车到达时间差Jitter则是同一辆车每次到达同一站点的时间波动。CTS管的是Skew同时尽量压低Latency而Jitter更多是设计架构和电源网络的范畴。2.2 全局偏斜与局部偏斜哪个更重要Skew还有全局和局部之分这个区分在实际项目中非常关键。Global Skew是时钟源到达时钟域内所有寄存器端点的最大时间差。Local Skew则是时钟源到达彼此有时序关系的两个寄存器比如一条数据路径上的源寄存器和目的寄存器的时间差。从时序分析的角度看Local Skew才是真正影响路径时序的。因为一条时序路径上只有两个端点源寄存器和目的寄存器。它们之间的时钟到达时间差直接影响这条路径的建立和保持时间裕量。但是关键在于CTS工具优化的主要目标通常是Global Skew因为让所有叶子尽量对齐是最简单、最robust的策略。这样做的好处是对于任意一条路径Local Skew的上限天然就被Global Skew限制住了不需要逐一分析。这种设计哲学很像“宁可同归于尽也要绝对公平”——把时钟偏差压到全局统一换来时序稳定。不过Global Skew压得太低也是有代价的。把一片片上物理位置差距极大的寄存器都对齐到同一个时钟边沿意味着要为远的寄存器插入更多buffer增加延迟和功耗也增加布线资源占用。所以实际项目中高扇出、大时钟域一般不追求极致低的Global Skew而是追求“足够好”的Local Skew。这一点后面讲Skew Group的时候会再展开。2.3 从约束角度看时钟定义是CTS的输入前提CTS不是一个凭空的物理构建过程它的行为完全受约束驱动。时钟定义不对后面做得再漂亮也是错的。这里就涉及SDCSynopsys Design Constraints里的核心时钟约束命令。用得最多的就是两个create_clock和create_generated_clock。create_clock用于定义原始时钟通常定义在芯片的输入端口或者PLL输出端口。它需要指定周期period、波形waveform还可以定义不确定性uncertainty和延迟latency。如果你定义了一个错误的周期比如周期写小了后续所有CTS优化都会按照过紧的时序预算去跑工具会插一大批多余的buffer功耗和面积直接爆掉。反过来周期写大了CTS跑出来的时钟树松垮垮时序检查过于宽松流片回来大概率翻车。create_generated_clock用于定义分频、倍频、多路选择后的时钟。它需要指定源时钟master clock和分频系数或倍频系数。这个命令在CTS中同样重要因为工具需要知道哪些时钟是从哪些源演变来的才能正确判断时钟域之间的关系和时钟树结构的归属。所以在启动CTS之前我强烈的建议是先花一个小时把SDC里的时钟定义逐条看一遍。确认每个时钟定义在正确的端口、周期正确、generated clock的主时钟源正确。这一步省下来的时间至少是后排查CTS问题时间的五倍。很多人CTS跑完发现Skew报告乱得没法看回头一查果然是时钟定义里有个master pin选错了。这种事情我几乎每做一个项目都能碰上至少一次。3. CTS的实现机制从短时钟树到长时钟树3.1 为什么不能用简单buffer链搞定CTS很多人对CTS的理解是插buffer把信号从根节点送到所有终点。听上去简单为什么工具实现起来这么费劲核心原因有三个。第一分支路径绝对不可能等长。芯片上寄存器的物理位置分布极不均匀有的在时钟网络根节点旁边有的在die的对角。要把这些位置完全不同的点串成一棵树自然会出现路径长短不一的情况。第二每个节点的负载不同。寄存器的时钟输入端电容、时钟网络的走线长度都会影响delay。负载大的分支天然更慢负载小的分支天然更快不加以干预Skew自然就形成了。第三前级buffer的驱动能力有限。一个buffer能驱动的负载是有上限的负载超过上限delay会急剧增大甚至导致信号边沿变缓引发保持时间问题。所以CTS本质上是一个需要不断插入buffer、调整buffer尺寸、调整树的拓扑反复迭代收敛的过程。3.2 短时钟树策略面向低频与少量寄存器在进入工具如何构建长时钟树之前先说说“短时钟树”这个概念。因为很多人做项目面对的其实不是那种动辄几万寄存器的超高频时钟域而是一两个甚至十几个寄存器的小模块。如果一个时钟域只有二十个寄存器分布在一块很小的区域里离时钟源端口也很近这时候CTS就走短时钟树比如单一层或两层buffer就够了。短时钟树的优势是延迟小、功耗低、面积小且天然Skew小因为你不需要为了平衡远处寄存器而人为拖慢近处寄存器。工具一般是根据扇出和物理分布自动决定时钟树层级的。但如果你的约束里对某些时钟设置了非常严格的target latency工具就可能被迫多插几层buffer把短时钟树变成中时钟树。这时候你的约束就起到了反作用——非但没有让时钟更好反而让功耗和面积白白浪费了。所以在写SDC的时钟约束时不要想当然地给时钟加一个特别小的latency期望。除了少数高频接口时钟大多数内部时钟latency大一点小一点并没有那么关键关键是Skew和transition达标。这个观念一定要扭转过来。3.3 长时钟树策略平衡偏斜与延迟的全局考量当寄存器数量上去了比如上万物理范围铺满了整个芯片CTS就不得不用长时钟树策略了。长时钟树通常是H-tree或者在工具看来是“多级平衡树”的形式。工具构建长时钟树时逻辑上会经历这样几步第一步确定叶子节点集合。工具从时钟根节点出发沿着时钟网络去追踪所有终点通常是寄存器的clock pin。这个过程在Innovus里可以通过report_clock_tree来查看工具会列出所有sink以及它们所属的时钟域。第二步分层构建。工具不会从根节点直接接一长串buffer把每个sink都驱动起来而是先驱动一个大buffer作为“大干线”再从大干线分出几条支路每条支路再驱动下一级buffer逐级展开直到覆盖所有叶子。每一级都在做一个子树的平衡最终整棵树近似平衡。第三步插入延迟单元。为了平衡整体Skew光靠选对buffer尺寸还不够有时候必须牺牲某些路径的延迟来配合全局。一个常见的做法是在较短路径上插入额外的delay单元让该路径的延迟与其他路径拉齐。这个做法在时序分析里有专门的名字——useful skew我们放到后面讲。第四步迭代修正。工具会根据当前树的实测delay和Skew情况重新调整buffer的尺寸和位置。这个过程在Innovus的CTS log里能看到多次迭代的记录。每次迭代都会更新wire load模型和RC值逐步逼近收敛。对于长时钟树有一个容易被忽视的点时钟树的顶层走线宽度和处理方式与普通信号完全不同。在Innovus里你通常会为时钟树专门定义一组宽金属、低电阻的route层并且允许它使用比普通信号更宽的线宽。这不是为了好看而是为了降低电阻减小RC延迟保证时钟信号在长距离传输过程中的边沿不会恶化。3.4 时钟树参考单元与硬件准备CTS要能跑起来除了逻辑本身还必须有时钟树参考单元也就是CTS库通常在.lib文件里标记为clock_gating_integration_cell、clock_buffer、ct_cell等属性的单元。这些参考单元主要分三类时钟缓冲器Clock Buffer专用buffer特点是延迟对负载的敏感性较低、输入电容匹配好、rise/fall延迟对称性好。对称性在时钟树里特别重要。因为时钟信号在传递个几百个寄存器的过程中如果rise delay和fall delay不一致高电平占空比会逐渐失真导致时序分析时遇到底部偏移的问题。时钟反相器Clock Inverter在某些工艺节点上clock inverter因为本身结构简单延迟波动更小反而更能做出低Skew的树。不过用inverter搭时钟树会带来相位翻转的问题工具需要额外处理。时钟门控单元ICG用于时钟门控在低功耗设计里是标配。ICG通常自带latch和AND门结构能避免门控时钟产生毛刺。在定义CTS参考单元的时候有两种策略一种是限制工具只能使用指定的几组buffer另一种是放开让工具从标准单元库中自动选择。我的建议是除非你的库非常成熟、参考单元分类很良好否则尽量手动指定一个或几个尺寸的buffer。工具自动选库里的所有单元去优化时钟树虽然理论上能找到一个更优的尺寸点但在库里混杂了通用逻辑buffer、低功耗buffer的情况下工具选出来的单元未必适合时钟用途容易在后期出现transition违例。手动圈定一个缓冲器集合既是经验之谈也是逼着自己去熟悉库里的单元特性。4. 实操要点Skew Group、有用偏差与时钟树质量评估4.1 Innovus中CTS的基本流程与常用命令进入工具实操环节。这里以Innovus为例因为目前业界用的最多。流程上place做完之后跑CTS之前有几件事是必须做的第一件确认clock定义无误。可以通过report_clock -summary快速浏览所有时钟。重点看周期、主时钟、group。如果发现group是默认的最好手动分组。第二件设置CTS专用变量。Innovus里有大量与CTS相关的变量其中最重要的几个包括cts.target_max_trans目标transition时间、cts.target_skew目标偏斜值、cts.max_fanout最大扇出限制、cts.buffer_cells允许使用的buffer列表。这些变量在开始之前就要设置好。第三件执行时钟树综合。在Innovus里直接跑clock_design就能启动CTS。跑的过程中工具会打印出很多信息包括正在建的树、当前延迟、Skew收敛情况等。第一次跑CTS不要着急去翻tcl脚本细节先关注三个内容log里是否有warning/error、报告出来的Skew是多少、tree的depth是多少。第四件做post-CTS的时序分析。跑完CTS之后需要把时钟设为propagated重新做一次时序检查。命令是set_propagated_clock [all_clocks]然后重跑STA。这时候的结果比place阶段要真实得多可以看出来CTS到底合不合格。我个人的习惯是跑CTS之前先手动创建一个“时钟树调试用”的工程目录备份。这样如果在CTS后发现是时钟定义的问题可以快速回到place阶段重新来过不用再做一次place。这个习惯救过我很多次尤其是处理一些上百个宏单元、多时钟域混杂的复杂设计时。4.2 Skew Group为什么应该手动划分时钟组默认情况下Innovus的CTS会为每个时钟自动建一个时钟组Clock Group。但实际设计中一个时钟域内部由于数据流的关系并不是所有寄存器都需要被严格对齐的。最典型的场景是可测性设计DFT。在shift模式下scan链上的寄存器要求时钟能够同时翻转这需要一个极低的Skew。但在功能模式下扫描链路两端的时序要求可能是完全不同的。如果工具按照功能模式下的时钟约束去建树得到的Skew可能在shift模式下不满足。这时候就需要手动把同一个时钟里的寄存器划分成不同的Skew Group让工具在不同的组间做有倾向性的优化。比如scan时钟域可以建立一个专门的group要求极低global skew而功能时钟域只要保证local skew够好就行。Innovus里划分Skew Group用create_clock_tree_group命令。你可以根据时钟树根节点和组内sink来划分也可以指定一组特定的寄存器pin作为组内成员。比如create_clock_tree_group -name func_group -clock CLK -sinks [get_pins ...list_of_ff_ck_pins...]实际项目管理中我们通常先跑一版默认CTS然后从报告里看哪些路径的时序最差再针对性地把这些路径上的寄存器划到同一个group里做精细优化。这个过程要迭代好几轮也正是数字后端工程师最耗时间的地方。4.3 有用偏差Useful Skew的高级用法讲到Skew Group就绕不开Useful Skew。这个概念前文提过一句这里展开讲透。传统CTS的目标是把全局Skew压到最小。但如果我们放宽这一目标允许一定的偏斜利用它去“帮忙”修复时序那就是Useful Skew。它本质上是一种主动地、有方向性地控制Skew的行为。举一个具象的例子假设有一条数据路径从FF_A到FF_B路径延迟是2.2ns而时钟周期是2ns正常时序无法满足。如果我们能让时钟到达FF_B的时间比到达FF_A的时间晚0.3ns那么在数据沿到达FF_B之前时钟沿还没到来目的寄存器“晚一点采样”就多给了0.3ns的建立时间预算。这条路径就修好了。反过来对于保持时间的违例我们可以让FF_B的时钟比FF_A早一点到这样数据变化沿到达之前旧数据已经被采样过了从而消除保持时间违例。这就是保持时间方向上的Useful Skew。但是Useful Skew是一把双刃剑。你今天让FF_B晚采0.3ns虽然满足了FF_A到FF_B的时序但FF_B它自己作为源寄存器到达下游FF_C的数据路径是独立的一条它的晚采样不一定能保证下游路径。如果下游路径也是紧的那你用Skew补了上游漏了下游反而可能越调越乱。所以实际工程中Useful Skew通常不是手工去调的而是交给工具。Innovus里有一个专门的模式——在时钟树综合时允许工具利用skew来修复时序比如set_analysis_mode配合时序预算、或者时钟树选项ccopt_useful_skew相关的变量。新手阶段我不建议手动做useful skew经历不够的话非常容易把自己绕进去。4.4 怎么通过报告评估时钟树质量CTS跑完怎么判断质量好坏我一般按这个顺序看报告。先看report_clock_tree -detail里面每一层有Cell count、Net Length、Cpin等。重点看第一列根节点到sink的延迟Latency以及sink之间的Skew。如果延迟异常大排除时钟定义或库的问题后很可能是工具用了太多级的buffer可以考虑换更大的主干buffer。再看report_clock_timing -type skew或report_clock_timing -type latency这里展示每个时钟域的skew统计和latency。Skew达标与否不光看平均还要看最大差值。有的工具报告显示平均skew是几十ps但max差值可能几百ps这种情况说明少数sink拖了后腿需要单独检查这些sink的物理位置。再然后看report_timing -from [时钟根] -to [哪个sink]用于逐条分析延迟构成。如果发现某一段延迟异常要看是不是因为绕线太长或者经过的特殊单元太多。最后看transition报告。时钟信号的transition如果太大不只影响本路径还会影响下级寄存器的时钟输入端的建立和保持时间计算。Innovus里CTS做完后如果check_report说有transition violation你可以在工具里设set_clock_tree_options -target_max_trans来收紧目标或者调整clock buffer的尺寸。看这些报告最忌讳的就是只看一个数字然后下结论。时钟树是一个整体网络局部指标好不代表整体好整体skew达标也可能存在局部transition问题。要结合起来看。5. 时钟树的信号完整性与可靠性问题5.1 时钟树上的串扰与噪声到了深亚微米工艺之后时钟树的信号完整性问题越来越突出。时钟树是全局网络中走线最长、buffer级数最多的网络之一天然容易受到相邻信号的干扰。串扰导致的结果有两类一类是串扰延迟即相邻信号的翻转改变了时钟信号的传播速度另一类是串扰噪声即相邻信号翻转时在时钟信号线上感应出电压脉冲严重时可能导致时钟沿提前或延迟到达。在Innovus里CTS做完后一般会有一个ccopt_design或post-CTS的SI分析环节。如果报告显示时钟树上有明显的SI问题常见处理手段包括将时钟网络的绕线间距扩大double spacing减少与相邻signal net的耦合电容。对关键时钟网络做特殊绕线屏蔽shielding但这会占用大量绕线资源一般只用在高频超关键路径上。调整时钟网络所在的金属层让它们避开拥塞区域减少串扰风险。需要注意的是这些SI修复手段都会额外增加绕线资源和功耗所以不是所有时钟网络都需要做一般只对high-frequency clock或high-fanout clock做。低频时钟串扰的影响相对有限放宽一点也没有关系。5.2 时钟树上的IR Drop与电源噪声再说电源问题。时钟buffer在翻转的瞬间会抽取瞬时大电流如果供电网络不好局部的IR Drop会很大。而IR Drop又直接影响了buffer本身的延迟导致不同位置的时钟buffer延迟不一致间接恶化Skew。这就是为什么在时钟树优化时除了看时序报告还要关注电源域划分和power mesh的密度。如果某个角落的IR-drop报告特别严重就得提前在物理实现阶段把power mesh加密而不是在CTS阶段想着靠插buffer去弥补。工具再强也补不出电源质量问题。另外时钟树本身也会消耗不小的动态功耗。时钟每翻转一次所有clock buffer以及所有寄存器的clock pin都要跟着翻转。一个几万寄存器的时钟域时钟树的动态功耗可能是整体芯片功耗的15%到25%。如果你做的是低功耗设计CTS阶段就要考虑如何减小时钟树深度、减少高功耗buffer的使用。5.3 时钟门控Clock Gating的注意事项低功耗设计里ICGIntegrated Clock Gating cell用得非常多。时钟门控的引入带来一个CTS里特有的副作用它把时钟树的负载切成了几个子域并且每个ICG输出的时钟信号只有在使能时才翻转这就导致每个ICG输出的子时钟树虽然在物理上是同一根时钟网路上分出去的但在逻辑上可能在某些时间点是相对独立的。CTS工具在构建时钟树时会把每一个ICG视为一个“半透明”的节点。也就是说时钟到达ICG输入端之前要走一段公共路径到达ICG之后各子树单独平衡。这个结构带来一个麻烦如果ICG的EN信号质量不好或者ICG本身的delay在不同电压温度下差异大那么ICG之后的子时钟树之间会产生额外的skew。在检查CTS报告时额外关注一下ICG的输出端到叶子之间的延迟。如果发现不同ICG下的子树skew偏大极有可能是因为ICG插入位置不合理比如某些ICG离时钟根节点太近某些又太远。这时可以通过移动ICG的位置、或者在ICG输入端加缓冲器来重新平衡各子树。6. 常见问题与排查技巧实录6.1 问题一CTS后Skew反而恶化我遇到最多的情况是CTS跑完后报告里的Skew比预估的还要大。排查思路如下。先确认时钟定义。在Innovus里执行report_clock -summary -skew看这个时钟域的sink数量是不是异常多。有些时候时钟定义没有正确排除DFT mux导致工具把scan时钟和功能时钟当作同一棵时钟树来建工具为了平衡两边的延迟只能靠加buffer最终结果就是Skew变大、面积变大两边都没讨好。其次看sink的分布。用GUI或命令打开sink的物理坐标如果发现sink分布呈现两个极端比如大部分集中在左上角少部分跑到右下角说明工具为了平衡全局必然要把左上角也拉长到和右下角一样的delaySkew自然就大了。这时候的思路是拆成多组时钟树而不是死磕单一平衡树。6.2 问题二transition时间过大导致setup违例时钟信号transition过大本质是驱动能力不够或者绕线过长。排查方式很简单在报告里找到transition违例的时钟网络去GUI里看它的物理路径看是不是绕了一圈才到达端点。如果是绕线过长手段是换驱动能力更大的clock buffer或者让工具把该时钟网络的绕线层限制到低电阻层。如果是因为负载太重先看sink数量是不是一个buffer带了异常多的寄存器可以通过set_clock_tree_options -max_fanout限制最大扇出让工具手动多插一级buffer。但要小心分叉层级的增加会直接增加latency而latency增大会影响hold margin的计算。所以transition和latency是CTS里一对需要平衡的矛盾指标。修transition时要时刻关注latency的变化不要按下葫芦浮起瓢。6.3 问题三多个时钟域交互处的CTS优化多个时钟域交互CDC是CTS里的一块硬骨头。异步时钟域之间不用做同步但时钟树物理上如果重叠工具会默认去平衡两个域的skew导致两边都做不好。这里的关键是把异步时钟域的CTS约束隔离开。在Innovus里可以用set_clock_groups -asynchronous把时钟组之间的时序路径设为false path让工具不去优化它们之间的时序。这样做之后CTS会更加“自私”地优化各自域内的skew效果通常立竿见影。另外一个常见陷阱是跨时钟域的保持时间违例。因为异步域数据不是同步的可能会有偶尔的保持违例命中。处理办法是检查SDC里是否对CDC路径做了set_false_path或set_max_delay约束。如果没做请尽快补上。6.4 项目实战中的经验心得总结做CTS这几年最大的感受是CTS最难的从来不是工具怎么用而是你怎么理解你的设计。工具是一个高度智能的求解器你给它正确的约束它能给你一个高质量解你给它糊涂的约束它只会装模作样地“优化”出一个满足你错误约束的糊涂结果。有几个原则是我一直坚持的时钟定义一定自己过一遍不要轻信综合脚本里的SDC。综合工程师可能为了时序收敛在SDC里写了各种奇怪的时钟约束这些约束在逻辑阶段是好的但到后端阶段可能变成CTS的枷锁。CTS之前先做floorplan review。寄存器密度、macro位置、电源网络密度这些都会深刻影响时钟树质量。如果floorplan里macro摆放把一块时钟区域切割得支离破碎再厉害的CTS也建不出漂亮的树。与其在CTS阶段折腾不如回到floorplan阶段把关键模块调整好。每个项目都要积累属于自己的CTS check list。把上一步骤、本步骤、下一步骤的检查项目列表记录下来每次做新项目都翻一下按顺序打钩。CTS环节的不少问题都有强烈的上下文依赖性换一个设计、换一个工艺库之前管用的参数可能就不管用了但检查清单是通用的。写在最后时钟树综合是一面镜子照见的是你对芯片物理本质的理解程度。理解了时钟信号的传输特性理解了Skew、Latency、Jitter在时序分析中的角色理解了工具优化目标的取舍逻辑你才能真正驾驭CTS而不是被工具的报告追着跑。这一篇侧重的是时钟信号本身的原理和CTS的整体框架下一期我打算结合具体的Innovus脚本来做一次完整的CTS实战演示包括约束设置、时钟树选项调优、时钟树报告解读那个环节。如果你们在项目里遇到过什么特别的CTS问题欢迎在评论区聊我尽量都回复。
返回列表