简介:《ConfigureDebugComplexClockNetworkCCOpt.pdf》是面向已具备集成电路设计基础、使用 Cadence Innovus 进行物理实现的工程师的官方技术文档,聚焦 Innovus 18.1/19.1 中 CCOpt 工具对复杂时钟网络的配置与调试。内容围绕时钟网络分析、时钟树构建、时钟优化、后处理验证四个阶段的调试点展开,并给出基本属性检查、CCOpt 时钟树调试器、时钟路径追踪与跨视图探测、报告命令、属性洞察等调试手段,还涉及人为偏斜、分离时钟树平衡、从属时钟与复杂控制逻辑等架构级时钟控制议题,可帮助读者降低时钟抖动、满足严格时序要求。资源为单个 pdf 文件,压缩包约 1.3MB,轻量便携,适合随查随用。目前已有 211 人学习浏览,说明其在 CTS 调试场景中具备一定参考价值。
1. 复杂时钟网络为什么不能只靠 SDC:CCOpt 的定位与这份笔记的读法
一块多时钟域设计里,CCOpt 跑完 timing 看着干净,clock tree 却多出几百个 buffer,这种场景我见过不止一次。Innovus CTS 流程里的 CCOpt 不是简单的 clock buffer 插入器,它把时钟网络合成和 datapath 优化放在一起跑;复杂时钟网络一旦 SDC 表达不完整,工具就会按自己的理解建树。这份《ConfigureDebugComplexClockNetworkCCOpt》应用笔记的价值在于:它假定你已经会跑命令,专门讲配置和调试策略,尤其是 skew group、sink_type、cluster/trial/full 各阶段能看出什么。适合正在用 Innovus 18.1/19.1 做物理实现、手里有多路 clock mux、DFT 分支、macro feedthrough 的后端工程师。读的时候别把它当命令手册,把它当停站检查表。
2. 跑 CCOpt 前的配置清单:单元、目标与 sink_type 怎么设
真到跑 CCOpt 那天,最容易翻车的不是命令拼错,而是设置放错位置。CCOpt 能从库、设计和 SDC 里自动提取大部分选项,但自动提取的目标是“能跑”,不是“跑得省”。尤其是复杂时钟网络,工具对 clock tree 的初始划分会直接决定后面 cluster 阶段怎么聚类、trial 阶段怎么试建树。配置清单要放在 extraction 之前,因为提取过程会被全局属性和 pin 级属性改掉;等树建完再回头改,很多时候只能重跑。
2.1 单元列表与 dont_use/dont_touch 的边界
单元选择是第一个要盯死的点。CCOpt 会从库里挑 buffer、inverter、clock gating cell 和 logic cell,你不给列表,它就按库属性和约束自己筛;筛出来的结果可能包含低驱动、低 Vt 或者你本来不想用在 clock network 上的单元。更隐蔽的是空列表:空列表不是“没有单元”,而是“所有单元都可被考虑”,这个特殊含义在文档里写得很清楚,也不推荐这么干。always-on 单元如果不在列表里,工具不会主动帮你加进去,低功耗域里就会漏掉。
# legacy 写法:显式给出 clock network 可用的单元列表 set_ccopt_property buffer_cells {BUF_X1 BUF_X2 BUF_X4 BUF_X8} set_ccopt_property inverter_cells {INV_X1 INV_X2 INV_X4} set_ccopt_property clock_gating_cells {CKGATE_X1 CKGATE_X2} set_ccopt_property logic_cells {AND2_X1 OR2_X1 MUX2_X1} # CUI/Stylus 写法:同一语义,实际跑的时候只留一套 set_db cts_buffer_cells {BUF_X1 BUF_X2 BUF_X4 BUF_X8} set_db cts_inverter_cells {INV_X1 INV_X2 INV_X4} set_db cts_clock_gating_cells {CKGATE_X1 CKGATE_X2} set_db cts_logic_cells {AND2_X1 OR2_X1 MUX2_X1} # 单元列表给完后,查工具为什么过滤掉某些单元 report_ccopt_cell_filtering_reasons report_cts_cell_filtering_reasons这段代码的重点不是单元名,而是“显式给列表”这个动作。buffer 和 inverter 按驱动分档,别只放 X1 和 X16 两个极端;clock gating cell 要把 always-on 版本单独加进去;logic cell 只放确实允许出现在 clock network 里的组合逻辑,不要把普通数据路径单元混进来。report_ccopt_cell_filtering_reasons和report_cts_cell_filtering_reasons是查过滤原因的命令,跑完看哪些单元因为 Vt、驱动、dont_use 或 dont_touch 被筛掉。参数上,列表越窄,工具可选空间越小,过度缓冲的风险越低,但局部驱动不足时也更容易出现 transition 违规;列表越宽,工具灵活,但容易挑到你不想用的单元。
还要区分dont_use和dont_touch。文档里提到,CCOpt 属性里设置的 cell list 会覆盖 library 定义的dont_use;从 18.1 开始,用户施加的dont_touch会被尊重。这两个词在项目里经常被混着说,实际边界不一样:dont_use更像库级建议,cell list 可以把它破掉;dont_touch是用户级锁死,18.1 之后 CCOpt 会认。我的习惯是,真正不想让 clock network 碰的单元用set_dont_touch明确锁住,而不是只依赖 library 的dont_use;同时把 cell list 收窄,别让工具在边界上猜。
| 单元类别 | 在 CCOpt 里的作用 | 常见误设 | 检查方式 |
|---|---|---|---|
| buffer_cells | 建树、修 transition、补驱动 | 只放高驱动,局部过冲 | report_ccopt_cell_filtering_reasons |
| inverter_cells | 反相器配对建树 | 和 buffer 列表驱动档不匹配 | 看 full 后 level 和 transition |
| clock_gating_cells | 优化 clock gating 分支 | 漏掉 always-on 版本 | 查低功耗域是否报 missing cell |
| logic_cells | 允许 clock network 里的组合逻辑 | 把数据路径单元放进来 | 看 clock tree debugger 是否穿逻辑 |
提示:cell list 不是越长越安全。列表里每多一个低驱动单元,工具就多一个“省面积”的选择,后面 full 阶段出现长串 buffer 时,先回头查列表。
2.2 transition/skew 目标与低功耗的取舍
target_max_trans和target_skew是影响时钟网络面积和功耗最大的两个旋钮,也是最容易被拍脑袋设错的两个。transition 目标收紧,工具会插更多 buffer 把边沿做陡,DRV 好看,但 clock network 的电容和功耗上去;目标放宽,buffer 少,低功耗设计舒服,但 leaf 端的 transition 可能踩库上限。常见做法是先按库推荐上限的 60%~70% 起步,跑完 full 看 leaf transition 和 DRV 报告,再决定收紧还是放宽。不要一上来就按 signoff 的极限值设,CCOpt 会为了这个目标过度建树。
skew 目标更玄学。设得太紧,工具会在本来不需要平衡的分支之间反复插 buffer,level 变深,power 上去,timing 未必改善;设得太松,跨 clock domain 的 setup 可能修不回来。我的经验是先按时钟周期的 5% 左右给一个粗目标,复杂分支再按 skew group 局部收紧。文档里特别提醒,SDC 派生的 transition/skew 目标只有在没有全局目标时才会被用;所以全局目标一设,SDC 里的值就被盖住了,调试时要知道当前生效的是哪一层。
# 全局目标:先给一个能跑 full 的粗值,单位是 ns set_ccopt_property target_max_trans 0.120 set_ccopt_property target_skew 0.080 # CUI/Stylus 写法 set_db cts_target_max_transition_time 0.120 set_db cts_target_skew 0.080 # 提取后如果某个 clock tree 需要更紧的 transition,再局部覆盖 set_ccopt_property target_max_trans 0.080 -clock_tree clk_core这段代码里,target_max_trans 0.120和target_skew 0.080只是占位值,实际要按工艺库、时钟频率和 signoff 要求改。全局目标放在 extraction 之前,局部覆盖放在 extraction 之后;-clock_tree这种限定符让目标只作用于某棵时钟树,不会把全局值改掉。参数含义上,target_max_trans是工具建树时追求的 transition 上限,不是最终 signoff 的 DRV 上限;target_skew是同一 skew group 内 leaf 之间的偏斜目标,不是跨 group 的约束。低功耗项目里,我一般会把全局 skew 放宽一点,把真正紧的分支拆成独立 skew group 再收紧,避免全局过紧导致整棵树过度平衡。
还有一个细节:cell list 和 target 是联动的。列表里高驱动单元多,工具更容易满足紧 transition;列表里只有低驱动单元,紧 transition 就只能靠堆 buffer,面积反而更差。调 target 之前先看report_ccopt_cell_filtering_reasons,确认工具手里有可用的驱动档,不然调参就是盲调。
2.3 sink_type 与路由规则:先框住时钟提取范围
复杂时钟网络里,CCOpt 最怕的是“追错 sink”。时钟路径经过 clock mux、DFT 分支、macro feedthrough 时,工具可能把数据路径上的 pin 也当成 clock leaf,或者把不该平衡的分支拉进同一棵树。sink_type就是用来框提取范围的属性,常见值有stop、ignore、exclude。三个词看着像,边界不一样:stop是在某个 pin 上停止继续追踪,适合 clock mux 输出、macro feedthrough 边界;ignore是让这个 sink 不参与平衡,但还在时钟网络里;exclude是把整条分支从时钟网络提取中排除,适合 DFT/test 分支。用错一个,后面 debugger 里就会看到奇怪的 leaf。
# 示意写法:属性选项顺序随版本略有差异,跑之前先 man set_ccopt_property 确认 # 在 clock mux 输出处停止追踪,避免追进数据路径 set_ccopt_property sink_type stop -pin u_clk_mux/Z # 某个 scan clock gate 不参与平衡,但保留在时钟网络里 set_ccopt_property sink_type ignore -pin u_scan_cg/CK # 把整条 DFT 分支从时钟提取中排除 set_ccopt_property sink_type exclude -pin u_dft_leaf/CK # 查某个 pin 当前生效的 sink_type get_ccopt_property sink_type -pin u_clk_mux/Z这段代码的关键是三个值的适用场景,不是命令顺序。stop用在“再往下追就不是时钟”的边界,比如 clock mux 输出、macro 的 clock feedthrough 输出;ignore用在“它还是时钟 sink,但我不想让它参与平衡”的点,比如某些控制逻辑的 clock pin;exclude用在“这条分支根本不该进时钟网络”的场景,比如测试分支、调试分支。设置之前先用get_ccopt_property查当前值,避免把上层继承下来的属性覆盖错。参数上,-pin限定到具体 instance pin,不要图省事设到整个 clock tree,否则后面很难定位是哪一层把分支砍掉的。
路由规则也要在 extraction 前设。时钟网络通常要用非默认规则,top、trunk、leaf 三档可以分别给。文档里的做法是先create_route_type建一个规则,再用set_ccopt_property route_type -net_type {leaf trunk top}绑到三档网络上。CUI 写法对应set_db cts_route_type_top、set_db cts_route_type_trunk、set_db cts_route_type_leaf。这一步不做,clock net 可能按 default rule 走,SI 和 EM 后面再修就贵了。
# 建一个 clock 专用的非默认路由规则 create_route_type -name clock_ndr_1 # 把规则绑到 leaf、trunk、top 三档 clock net set_ccopt_property route_type -net_type {leaf trunk top} clock_ndr_1 # CUI/Stylus 写法 set_db cts_route_type_top clock_ndr_1 set_db cts_route_type_trunk clock_ndr_1 set_db cts_route_type_leaf clock_ndr_1create_route_type -name clock_ndr_1只是建规则名,规则里的宽度、间距、屏蔽要按项目 NDR 填;-net_type {leaf trunk top}是把同一套规则绑到三档,实际项目里 top 和 leaf 经常用不同规则,按需拆开。CUI 三行是同一语义的另一种写法,跑的时候只留一套。路由规则放在 extraction 前,是因为提取时钟网络时工具会参考路由约束估算 RC;extraction 之后再改,树已经按旧规则建好了,只能重跑。
3. 把流程拆成可停靠的站点:cluster、trial、full 各阶段看什么
CCOpt 默认可以一口气跑完,复杂时钟网络却值得拆开跑。文档里把流程拆成 post-CTS 设置、路由规则、提取、修改 clock/skew group、clock construction(cluster/trial/full)、early global route、Nanoroute、datapath optimization 这些站点。拆开的目的不是炫技,是让每个阶段的结果都能被检查:cluster 阶段看聚类是否合理,trial 阶段看试建树的 buffer 和 level,full 阶段看最终收敛。等 full 跑完再看,很多结构性问题已经被优化掩盖了。
3.1 前置设置:post-CTS 时序模式与 latency 更新
post-CTS 的设置要最小,只放捕获约束模式的关键项。文档里特别提到update_io_latency false,原因是 chip-level 和某些复杂架构里,工具修改 IO latency 会把 clock 到达时间改掉,接口时序对不上。这个设置不是每个项目都要关,但复杂时钟网络里,关掉更可控。OCV delay mode 按项目 signoff 填,不要在这里自创参数;CCOpt 只需要知道用哪套延迟计算模式。
# legacy:关闭 latency 修改,chip-level 和复杂架构常用 set_ccopt_property update_io_latency false # CUI/Stylus:同一语义 set_db cts_update_clock_latency false # OCV 延迟模式按项目 signoff 填,下面只给占位注释 # setDelayCalMode <按 signoff 的 OCV 参数> setAnalysisMode -analysisType onChipVariation set_db timing_analysis_type ocv这段代码里,update_io_latency false和cts_update_clock_latency false是同一件事的两套写法,跑的时候只留一套。setAnalysisMode -analysisType onChipVariation是 legacy 的 OCV 分析模式,CUI 对应set_db timing_analysis_type ocv;setDelayCalMode的具体参数各项目不同,不要照抄别人的值。参数说明上,update_io_latency控制工具是否改 IO latency,关掉之后 clock tree 的 insertion delay 更贴近真实约束;OCV 模式影响 timing 分析,不是建树本身,但建树后的优化会按这个模式修 timing,所以要在 CCOpt 前设好。
| 设置项 | 作用 | 什么时候改 |
|---|---|---|
update_io_latency false | 阻止工具改 IO latency | chip-level、复杂架构、接口时序紧 |
| OCV delay mode | 指定延迟计算模式 | 按 signoff 策略,跑 CCOpt 前 |
setAnalysisMode | legacy 时序分析模式 | 与项目 timing 脚本一致 |
set_db timing_analysis_type | CUI 时序分析模式 | 与 legacy 二选一 |
注意:post-CTS 设置不是越多越好。这里只放影响时钟网络配置和 timing 模式的项,别把完整 signoff 脚本整段搬进来,否则 CCOpt 会被无关约束带偏。
3.2 提取之后改 clock/skew group 的时机
提取之后再改 clock/skew group,是 CCOpt 调试的核心动作。提取前你只能设全局属性,工具怎么分 clock tree、怎么分 skew group 还不知道;提取后能看到工具的理解,再决定增删 skew group、改某个 group 的 target、把 SDC 派生目标覆盖掉。文档里列的动作包括修改已创建的 clock/skew group、增加或删除 skew group、按 clock 或 skew group 设属性、修改从 SDC 提取的目标。顺序上,先看报告,再改属性,改完再跑 construction。
# 提取后先看工具分出了哪些 clock tree 和 skew group report_ccopt_clock_trees report_ccopt_skew_groups # 对某棵 clock tree 收紧 transition,对某个 skew group 收紧 skew # 选项顺序以本机 man 页为准,数值单位 ns set_ccopt_property target_max_trans 0.080 -clock_tree clk_core set_ccopt_property target_skew 0.050 -skew_group sg_core # 查属性当前生效值,确认是全局继承还是局部覆盖 get_ccopt_property target_skew -skew_group sg_core这段代码先报告再设属性,逻辑是“先看工具怎么分,再决定改哪一层”。report_ccopt_clock_trees看 clock tree 列表和每棵树的 sink 范围,report_ccopt_skew_groups看 skew group 和 clock tree 的对应关系;多数设计里两者是 1:1,复杂结构可能一棵 clock tree 对应几个 skew group。-clock_tree和-skew_group是局部限定符,只改指定对象,不影响全局。get_ccopt_property用来确认当前值是全局继承来的还是局部覆盖的,调试时经常需要这一句,不然改了半天不知道改的是哪一层。
参数上,target_max_trans 0.080比全局 0.120 紧,适合 core clock 这种对边沿敏感的分支;target_skew 0.050比全局 0.080 紧,适合跨 domain 的 capture 分支。改完不要直接跑 full,先跑 trial 看 buffer 数和 level 有没有爆炸,再决定是否继续。提取后改 skew group 的另一个用途是拆不相交树:工具默认可能把同源但不相交的树放进一个 group,手动拆开之后,平衡行为会更符合架构意图。
3.3 三个构建阶段与不可重启的坑
clock construction 分 cluster、trial、full 三个阶段。cluster 阶段在聚类 sink,决定初步结构;trial 阶段试建树,估算 buffer 数量和 level;full 阶段完整建树,后面接 route 和 datapath optimization。每个阶段能看的东西不一样:cluster 阶段看 sink 分组有没有明显错误,比如 DFT 分支被聚进 core clock;trial 阶段看试建树的 level 和 buffer 数是否符合预期;full 阶段看最终 transition、skew、DRV 和 timing。文档里有一句很关键:在 cluster 或 trial 阶段停止后,不能 restart CCOpt。这个坑我踩过,停完改参数想接着跑,结果工具不认,只能重来。
# 常见做法:把 ccopt_design 拆成多次调用,先只跑到 CTS # 具体开关随版本不同,跑之前先 man ccopt_design 确认 ccopt_design -cts # 停在这里看 clock tree debugger 和报告,确认结构后再继续 route/opt # 注意:在 cluster/trial 阶段停止后不能 restart,改参数要重新跑这段代码是流程拆分的示意,ccopt_design -cts只跑到 CTS 阶段,后面的 route 和 datapath optimization 单独跑。具体开关各版本有差异,先查 man 页。重点在注释里的那句:cluster/trial 停止不能 restart,所以停之前要想好这次要检查什么,改完参数就重新从提取或 construction 开始跑。我的习惯是,在 trial 阶段停一次,把report_ccopt_clock_trees、report_ccopt_skew_groups和 clock tree debugger 截图存到项目目录,改参数后重跑,和上一版对照。这样虽然多跑一次,但比 full 跑完发现结构错了再回退便宜。
| 阶段 | 工具在做什么 | 主要看什么 | 能否停后 restart |
|---|---|---|---|
| cluster | 聚类 sink,划初步结构 | sink 分组、DFT 分支是否混入 | 不能 |
| trial | 试建树,估 buffer/level | level 深度、buffer 数、transition 趋势 | 不能 |
| full | 完整建树并接后续优化 | 最终 skew、DRV、timing、power | 按流程继续 |
提示:trial 阶段是最后能低成本改结构的站点。停在这里把 clock tree debugger 看一遍,比 full 后对着几百个 buffer 猜原因有效。
4. 复杂时钟的架构控制:阻断、故意偏斜与不相交树
复杂时钟网络的调试,很多时候不是命令问题,是架构表达问题。SDC 能写时钟周期、波形、不确定性,但写不出“这棵子树不要和那棵平衡”“这个 mux 后面是数据路径不是时钟”“这个 macro 的 clock 是穿过去的”。CCOpt 提供了一组架构控制手段:阻断数据路径进入时钟网络、故意偏斜、平衡不相交树、防止 slave clock 被平衡、处理 macro feedthrough、禁用某些时钟合成、防止过度缓冲。这些手段在多数设计里用不上,但复杂时钟里,少做一条就可能多出几百个 buffer。
4.1 阻断数据路径与控制逻辑进入时钟网络
时钟网络里经常混着数据路径的 mux、comb 和控制逻辑。工具提取时钟时,只要看到 pin 上有 clock 属性,就可能把它当 sink 追下去;追进数据路径之后,clock tree 会穿过组合逻辑,平衡出一棵又深又怪的树。阻断的办法是在边界上设sink_type stop,让提取到那里为止。控制逻辑也一样,某些 clock gating 的控制端、test 模式的 mux 选择端,不应该参与 clock skew 平衡,设ignore或stop更合适。
# 在 clock mux 输出停止追踪,防止追进数据路径 set_ccopt_property sink_type stop -pin u_clk_mux/Z # 控制逻辑的 clock pin 不参与平衡,但保留在时钟网络里 set_ccopt_property sink_type ignore -pin u_ctrl_reg/CK # 查设置后的 sink 列表,确认没有把真 leaf 砍掉 report_ccopt_clock_trees这段代码的动作很小,影响很大。stop放在 clock mux 输出,等于告诉工具“后面是数据路径,不要再追”;ignore放在控制逻辑的 clock pin,等于说“它还是时钟 sink,但不要拿它做平衡”。设完必须跑report_ccopt_clock_trees看 sink 列表,确认没有把真正的 leaf 砍掉。参数上,-pin要落到具体 instance pin,不要设到 module 级;设之前先用get_ccopt_property sink_type -pin查当前值,避免覆盖上层继承。阻断做得好,clock tree 的 level 会明显变浅,buffer 数也会降;做得过头,某些 leaf 没被平衡,setup 会反过来变差,所以每次改完都要看 timing。
4.2 故意偏斜与不相交树:什么时候该“不平衡”
故意偏斜是 CCOpt 里比较反直觉的功能。默认思路是 clock skew 越小越好,但跨 clock domain 的 launch/capture 路径,适当偏斜可以借时间;某些输出引脚逻辑,保持相似偏斜比强行平衡更稳。文档里把 deliberate skewing 单独列出来,前提是先把目标分支拆成独立 skew group,再对该 group 设带符号的 skew 目标。全局target_skew不要拿来干这件事,否则整棵树都会被带偏。
不相交时钟树是另一个场景。两棵树同源但物理上不相交,工具默认可能把它们放一个 skew group 里强行平衡,结果为了几皮秒的 skew 插了一堆 buffer。正确做法是创建 exclusive skew group,把不相交树分开,让它们各自平衡。公共 master 派生出的 slave clock 也要注意:它们本来有固定相位关系,强行平衡会破坏架构意图,应该阻止工具把它们当普通 slave 平衡。
| 场景 | 目标 | 设置方向 | 风险 |
|---|---|---|---|
| 跨 domain 借时间 | 故意偏斜 | 独立 skew group 上设带符号目标 | 偏斜过大导致 hold 难修 |
| 不相交树 | 各自平衡 | exclusive skew group 拆开 | 拆错 group 导致同源树失衡 |
| 公共 master 派生 slave | 保持相位关系 | 阻止 slave 被平衡 | 误设后接口时序漂移 |
| 输出引脚逻辑 | 保持相似 skew | 对 output 分支单独设目标 | 全局目标覆盖局部 |
注意:故意偏斜不是全局旋钮。先拆 group,再设目标,最后用 debugger 看 leaf 的实际 insertion delay,别只看报告里的 skew 数字。
4.3 公共 master 派生 slave clock 与 macro feedthrough
公共 master 派生 slave clock 的坑很隐蔽。工具看到两个 clock 同源,容易把它们放进同一棵 clock tree 平衡;但 slave clock 可能经过分频、mux 或 gate,相位关系是架构定好的,平衡之后反而破坏设计意图。处理办法是在 slave clock 的根或边界设sink_type stop,或者拆成独立 skew group,让工具不要跨边界平衡。macro feedthrough 同理:clock 穿过 macro 时,工具可能把 macro 当 buffer 继续追,或者把 feedthrough 后面的 leaf 拉进同一棵树。设stop在 macro 输出,或者给 feedthrough 分支单独建 group,能避免树穿进 macro。
禁用某些时钟合成也是架构控制的一部分。test clock、debug clock、DFT 分支,不是每个都需要 CCOpt 建树;设exclude或stop把它们从主时钟网络里摘出去,能减少无谓的 buffer 和平衡。防止过度缓冲则要回到 target 和 cell list:target_max_trans别设得太紧,cell list 别只放高驱动,exclusive skew group 别拆得太碎。文档里还提到“保持驱动输出引脚逻辑的相似 skew”,意思是输出引脚前面的时钟分支不要被全局目标带跑,单独给一个目标更稳。这些手段不需要全用,按设计里实际存在的结构挑两三条,先跑 trial 看效果,再决定是否进 full。
5. 调试与排查:clock tree debugger 和五条踩坑记录
CCOpt 跑完不看 debugger,等于闭着眼睛调参。clock tree debugger 能看树结构、level、buffer 数、transition、latency、skew,还能 cross probe 到 layout 和 schematic;路径追踪能从 clock source 一路看到 leaf,确认中间经过了哪些 buffer、mux、macro。报告命令和属性透视是辅助,用来确认工具当前生效的设置。真正花时间的往往是排查:为什么这棵树的 buffer 比上一版多,为什么某个 sink 没被平衡,为什么 trial 能过 full 却报错。下面几条踩坑记录,都是按“现象 → 原因 → 解决”整理的。
5.1 基本检查与 clock tree debugger
基本检查先看四件事:clock root 数量对不对、sink 数量对不对、skew group 和 clock tree 的对应关系对不对、有没有 clock 穿过数据路径。clock root 多了,可能是 test clock 没被 exclude;sink 少了,可能是sink_type把真 leaf 砍了;skew group 和 clock tree 不是 1:1,可能是复杂结构被工具合在一起;clock 穿过数据路径,debugger 里能看到树经过组合逻辑,这种树后面 timing 一定难修。clock tree debugger 打开后先看 level 分布,level 突然变深的分支,多半是 target 过紧或 cell list 驱动不够。
路径追踪用来确认单条路径。从 clock source 选到某个 leaf,看中间每一级的 cell、transition、latency;如果中间出现不该有的 mux 或 macro,回到sink_type检查。cross probing 到 layout 看物理走向,能发现绕线导致的
本文还有配套的精品资源,点击获取