PrimeTime时序路径分析入门:从建立保持时间到SDC约束实战
1. 时序路径分析到底在解决什么问题1.1 从一个真实场景说起芯片设计做到后端阶段最怕听到的一句话就是“时序不收敛”。你跑完综合、做完布局布线打开PrimeTime一跑报告里红彤彤一片violation这时候如果连“时序路径”这个概念都没吃透基本就是抓瞎。我见过不少刚入行的朋友拿到STA报告第一反应是去改约束结果越改越乱根本原因就是没搞清楚一条时序路径从哪开始、到哪结束、中间经过了什么。时序路径分析说白了就是回答一个问题数据信号从上一个触发器发出能不能在下一个触发器采样窗口之前稳定到达这个问题听起来简单但放到一颗几千万门甚至上亿门的SoC里就变成了一个极其复杂的图论问题。芯片里每一对触发器之间都可能存在路径路径上还可能穿过组合逻辑、时钟门控、多路选择器甚至跨时钟域。STA工具要做的事情就是把这些路径全部枚举出来算出每条路径的延迟然后跟时钟周期去比较看有没有余量。这个“余量”就是我们常说的slack。slack为正说明时序满足slack为负说明时序违例。听起来就一个减法但真正做过项目的人都知道难点从来不在减法本身而在于路径怎么找全、延迟怎么算准、约束怎么写对。这三个问题任何一个出岔子你看到的报告都是假的。1.2 为什么偏偏是PrimeTime市面上做STA的工具不止一家但PrimeTime基本上是事实上的行业标准。原因不复杂它跟Synopsys自家的综合工具Design Compiler、布局布线工具IC Compiler同出一源库文件格式、约束格式、时序模型都是一套体系数据传递损耗小。你用别的工具做综合再拿PrimeTime做签核中间往往要做格式转换转换过程里丢信息是常有的事。更重要的是PrimeTime的时序引擎经过这么多年迭代对先进工艺节点的支持是最成熟的。到了7nm、5nm这种节点互连延迟占比越来越高串扰、OCVon-chip variation、老化效应全都要建模进去PrimeTime在这些方面的模型精度是经过大量流片验证的。所以哪怕你前端用的是别的工具链最终签核阶段大概率还是要回到PrimeTime上跑一遍。SDC约束是PrimeTime的输入语言。你给它的所有信息——时钟定义、输入输出延迟、虚假路径、多周期路径——全部通过SDC描述。SDC写得好不好直接决定了PrimeTime报出来的结果有没有意义。我个人的经验是一个项目里SDC的质量往往比RTL代码质量更能决定时序收敛的难度。1.3 这篇文章适合谁看如果你正在学数字后端或者刚转岗做STA又或者你是前端设计工程师但想搞清楚自己写的RTL到底给后端带来了多大麻烦那这篇内容应该对你有用。我会从时序路径的基本分类讲起把建立时间、保持时间、时钟偏斜这些概念用实际路径拆开讲清楚然后落到PrimeTime的实际操作和SDC约束写法上。需要说明的是时序路径分析这个话题太大一篇文章不可能讲完。我把它拆成上下两篇上篇聚焦在路径分类、时序计算原理、基本约束方法这三块下篇再讲多时钟域、OCV建模、串扰分析、ECO修复这些进阶内容。你如果能把上篇的这些基础打牢后面遇到再复杂的场景至少知道该从哪里下手排查。2. 四条时序路径彻底拆解2.1 时序路径的四种基本类型STA工具把所有时序路径分成四类这个分类不是随便定的而是根据路径的起点和终点类型来划分的。理解这个分类是你读懂任何一份时序报告的前提。第一类触发器到触发器reg2reg。起点是发射触发器的时钟引脚终点是捕获触发器的数据引脚。这是芯片里数量最多、也最核心的路径类型。你跑STA90%以上的报告都是这类路径。它的特点是起点和终点都有明确的时钟定义时序关系由两个触发器的时钟相位决定。第二类输入端口到触发器in2reg。起点是芯片的输入引脚终点是内部触发器的数据引脚。这类路径的时序关系取决于外部器件什么时候把数据送过来以及芯片内部的时钟什么时候采样。所以你需要用set_input_delay来告诉工具外部数据相对于时钟的到达时间。第三类触发器到输出端口reg2out。起点是内部触发器的时钟引脚终点是芯片的输出引脚。这类路径的时序关系取决于外部器件什么时候需要拿到数据你用set_output_delay来描述这个需求。第四类输入端口到输出端口in2out。起点和终点都是芯片引脚中间只经过组合逻辑。这类路径通常出现在纯组合逻辑的直通路径上时序约束完全由外部环境决定。这四类路径里reg2reg是工具自动分析的只要你定义了时钟它就能找到路径并计算。另外三类必须靠SDC约束来“告诉”工具外部世界的情况你不写约束工具就默认没有时序要求报告里也不会报违例——但这不代表真的没问题只是你没告诉它要检查而已。2.2 一条完整路径上的关键节点我们拿一条典型的reg2reg路径来拆。假设有两个触发器FF1和FF2中间隔着几级组合逻辑时钟是CLK。数据从FF1的CK引脚触发经过FF1内部的CK-to-Q延迟到达FF1的Q输出。然后穿过中间的组合逻辑每一级门都有延迟互连线也有延迟。最后到达FF2的D引脚。这是数据路径。与此同时时钟信号从时钟源出发分别到达FF1的CK引脚和FF2的CK引脚。这两条时钟路径的延迟通常不一样差值就是时钟偏斜clock skew。这是时钟路径。FF2要在自己的CK上升沿采样D引脚上的数据但数据必须在CK上升沿之前一段时间就稳定下来这段时间叫建立时间setup time。如果数据到得太晚建立时间不够就是setup violation。FF2采样完之后数据还不能立刻变化必须在CK上升沿之后再保持一段时间这叫保持时间hold time。如果数据变化太早保持时间不够就是hold violation。所以一条路径的时序检查本质上就是比较数据到达时间和时钟要求时间。建立时间检查看的是“数据最晚什么时候到”保持时间检查看的是“数据最早什么时候变”。这两个检查用的是同一组路径但取的是延迟的不同的极值。2.3 建立时间与保持时间的计算逻辑建立时间的检查公式用最朴素的话说就是数据到达时间 建立时间要求 ≤ 时钟到达时间 时钟周期移项之后slack (时钟到达时间 时钟周期 - 建立时间要求) - 数据到达时间。数据到达时间取的是最大延迟因为我们要看最坏情况下数据能多晚到。时钟到达时间取的是最小延迟因为我们要看最坏情况下时钟能多早到。这种“数据取max、时钟取min”的组合就是所谓的WCworst-case分析。保持时间的检查公式反过来数据到达时间 ≥ 时钟到达时间 保持时间要求slack 数据到达时间 - 时钟到达时间 - 保持时间要求。这里数据到达时间取的是最小延迟时钟到达时间取的是最大延迟。因为保持时间检查关心的是数据不能变太早而时钟不能来太晚。我刚开始学的时候老是把这两个搞混后来自己总结了一个记忆方法建立时间怕数据慢、时钟快保持时间怕数据快、时钟慢。你把这个记牢看报告的时候就不会晕。2.4 为什么路径延迟要分max和min有人可能会问同一条路径延迟为什么会有最大值和最小值这不是工具在故弄玄虚而是因为芯片制造出来之后每一颗芯片的延迟都不一样。工艺偏差会导致晶体管的阈值电压、沟道长度有波动电压波动会影响驱动能力温度变化会影响载流子迁移率。这些因素叠加起来同一条路径在不同芯片、不同工作条件下的延迟可能相差百分之几十。到了先进工艺节点这个差异更大。所以STA要做corner分析也就是在几种极端条件下分别跑时序慢 corner慢工艺、低电压、高温用来检查建立时间快 corner快工艺、高电压、低温用来检查保持时间。PrimeTime里通过set_operating_conditions来指定当前分析用的corner。除了corner之外同一corner内部还要考虑OCV也就是on-chip variation。意思是同一颗芯片上不同位置的晶体管特性也会有差异时钟路径和数据路径的偏差方向可能不一致。这个我们在下篇会详细讲上篇你先记住max延迟和min延迟不是同一个数建立时间和保持时间用的是不同的极值组合。3. PrimeTime实操从读入设计到跑出第一份报告3.1 环境准备与设计读入PrimeTime的启动很简单命令行敲pt_shell就进去了。但进去之后第一件事不是急着读设计而是确认你的库文件路径对不对。库文件包括标准单元库、IO库、存储器库格式通常是.db或者.lib。.db是Synopsys的二进制格式读取速度快.lib是文本格式可读性好但体积大。读库用set link_path和read_dbset search_path [list . ./libs ./rtl] set link_path * slow.db fast.db io.db sram.db read_verilog ./netlist/top.v current_design top link_design这里有个坑我踩过好几次link_path里的*不能省它表示“已经读进来的库”。如果你写成set link_path slow.db fast.db工具在link的时候可能会找不到某些cell。另外如果你同时读了slow和fast两个库link的时候工具会按顺序匹配所以一般把当前corner要用的库放在前面。读网表的时候如果你的设计里有Memory或者IP网表里可能只有黑盒子的声明这时候需要额外读入对应的.db或者用create_cell手动例化。我一般会在读网表之前先read_db把所有需要的库都读进来避免link的时候报“cannot resolve reference”的错误。3.2 时钟约束怎么写才不出错时钟是STA的基准时钟约束写错了后面所有分析都是白搭。最基本的时钟定义create_clock -name CLK -period 10 -waveform {0 5} [get_ports CLK]这行命令定义了一个周期10ns、占空比50%的时钟上升沿在0ns下降沿在5ns。如果是差分时钟或者内部PLL产生的时钟你可能需要在特定引脚上创建时钟而不是在端口上。创建完时钟之后通常还要设置时钟的不确定性set_clock_uncertainty -setup 0.2 [get_clocks CLK] set_clock_uncertainty -hold 0.1 [get_clocks CLK]这个uncertainty包含了时钟抖动、时钟树偏差等所有不确定因素。setup的uncertainty一般比hold大因为setup分析要考虑更多悲观因素。具体给多少要看你的时钟源质量和时钟树综合的结果一般0.1~0.3ns是常见范围。还有一个容易忽略的是时钟延迟set_clock_latency -source 1.0 [get_clocks CLK] set_clock_latency 0.5 [get_clocks CLK]-source指的是时钟源到时钟定义点之间的延迟不带-source的是时钟定义点到触发器CK引脚之间的延迟。在时钟树综合之前你只能用latency来估算做完CTS之后PrimeTime可以直接从SPEF里读实际的时钟树延迟这时候就不需要手动设latency了。注意如果你在CTS之前用set_clock_latency估了一个值CTS之后忘了去掉会导致时序结果偏乐观或偏悲观。我一般会在脚本里用一个变量控制CTS前后切换。3.3 输入输出延迟的估算方法前面说过in2reg和reg2out路径的时序取决于外部环境你必须用set_input_delay和set_output_delay来描述。set_input_delay -clock CLK -max 2.0 [get_ports data_in*] set_input_delay -clock CLK -min 0.5 [get_ports data_in*] set_output_delay -clock CLK -max 3.0 [get_ports data_out*] set_output_delay -clock CLK -min 1.0 [get_ports data_out*]这里的max和min分别对应建立时间和保持时间检查。max值表示外部数据最晚到达的时间min值表示最早到达的时间。这些值怎么定看你的芯片跟外部器件的接口协议。比如你跟一个外部ADC对接ADC的数据在时钟上升沿之后2ns稳定那input delay的max就至少是2ns加上PCB走线延迟。如果接口协议里写了建立时间和保持时间要求你可以反推input_delay_max 时钟周期 - 外部器件的输出建立时间 input_delay_min 外部器件的输出保持时间输出延迟同理根据外部器件需要的建立保持时间反推。这些估算在项目初期就要做不然后端做完发现接口时序对不上返工成本极高。3.4 跑出第一份时序报告约束写完保存成SDC文件然后source ./constraints/top.sdc check_timing report_timing -max_paths 10 -nworst 1 -delay maxcheck_timing会检查你的约束有没有明显问题比如有没有时钟没定义、有没有端口没约束、有没有组合环路。这个命令一定要跑它报出来的warning很多时候就是时序违例的根源。report_timing是看时序报告的主力命令。-max_paths 10表示报最差的10条路径-nworst 1表示每个终点只报最差的一条-delay max表示看建立时间。如果你想看保持时间把max改成min。报告出来之后重点看几个东西slack是正是负、路径的起点和终点是谁、每一级的延迟是多少、时钟偏斜有多大。如果slack是负的先看是哪一级延迟特别大是组合逻辑太深还是互连太长然后针对性优化。4. 常见问题与排查技巧实录4.1 时序报告里的路径为什么跟我预期的不一样这是新手最常问的问题。你明明知道某两个触发器之间有路径但报告里就是找不到。原因通常有几个第一种可能路径被false path或者multicycle path屏蔽了。检查你的SDC里有没有set_false_path或者set_multicycle_path覆盖了这条路径。用report_timing -false_path可以看到被屏蔽的路径。第二种可能时钟没有正确传播。如果某个触发器的时钟引脚上没有时钟到达工具就不会分析它的时序路径。用report_clocks和report_timing -to [get_pins FF2/CK]来确认时钟有没有传到。第三种可能路径被优化掉了。综合工具可能会把一些逻辑优化掉导致路径不存在。检查网表里对应的逻辑还在不在。第四种可能你的起点或终点设错了。report_timing -from和-to的参数要写对触发器要写到引脚级别比如[get_pins FF1/CK]而不是[get_cells FF1]。4.2 约束冲突怎么排查SDC写多了很容易出现约束冲突。比如你给同一个端口既设了input delay又设了false path工具会按优先级处理但结果可能不是你想要的。排查约束冲突我一般用这几招report_sdc把当前生效的所有约束列出来看看有没有重复或者矛盾的。report_timing -justify这个命令会告诉你为什么某条路径被包含或排除在分析之外。check_timing -verbose比普通check_timing更详细会报出约束覆盖的问题。还有一个经验SDC的加载顺序很重要。后面的约束会覆盖前面的同名约束。我一般把时钟定义放在最前面然后是input/output delay再是false path和multicycle path最后是case analysis。这样优先级从高到低不容易乱。4.3 常见问题速查表问题现象可能原因排查方法解决思路报告里没有某条路径被false path屏蔽report_timing -false_path检查SDC中的false path设置slack异常大时钟没传播到终点report_clocks、report_timing -to检查时钟定义和传播设置setup和hold同时违例时钟偏斜过大report_clock_timing -type skew调整时钟树或约束路径延迟远超预期互连延迟占比高看报告里的net延迟检查布局布线结果或加buffer约束写了但不生效加载顺序或优先级问题report_sdc调整SDC加载顺序link_design报错库文件缺失或路径不对检查link_path和search_path补全库文件或修正路径4.4 几个我踩过的坑坑一忘了设operating condition。PrimeTime默认的operating condition可能跟你实际用的corner不一致导致延迟算出来偏乐观。一定要在脚本里显式set_operating_conditions。坑二时钟uncertainty给太小。有些人为了让时序好看故意把uncertainty设得很小结果流片回来发现时序挂了。uncertainty要基于时钟源的实际抖动和时钟树综合的偏差来定不能拍脑袋。坑三input/output delay用了同一个值。max和min要分别设而且通常不一样。如果你只写了一个值工具会同时用于setup和hold检查结果肯定不对。坑四忘了跑check_timing。这个命令花不了几秒钟但能帮你发现80%的约束问题。我现在的习惯是每次改完SDC都跑一遍。坑五报告只看slack不看路径。slack为负的时候一定要看路径的详细延迟分布。是逻辑太深、还是线太长、还是时钟偏斜太大不同的原因对应不同的修复策略。只看slack数字就动手改很容易白费功夫。4.5 一个实际的调试案例之前做过一个项目有一组reg2reg路径setup违例slack是-0.3ns。我先看报告发现数据路径延迟比预期大了将近1ns但组合逻辑级数并不多。仔细看每一级的延迟发现其中一条net的延迟占了0.8ns明显不正常。用report_net -connections查了这条net发现它跨了一个比较大的宏单元绕线很长。这种情况在布局阶段就埋下了隐患到了STA阶段才暴露出来。解决办法是在综合阶段加物理约束限制这个宏单元周围的标准单元密度或者手动加pipeline寄存器把长线打断。这个案例说明一个问题STA报出来的违例根因往往不在STA本身而在综合或布局阶段。你如果只盯着SDC改可能永远修不好。遇到违例先看路径的物理分布再决定是改约束还是改实现。5. 时序约束的进阶写法与实战建议5.1 多周期路径的正确设置方法多周期路径是指那些不需要在一个时钟周期内完成的数据传输。比如一个乘法器组合逻辑延迟是15ns但时钟周期只有10ns你不可能让它一个周期算完。这时候就要告诉工具这条路径允许两个周期。set_multicycle_path 2 -setup -from [get_cells mult_reg*] -to [get_cells result_reg*] set_multicycle_path 1 -hold -from [get_cells mult_reg*] -to [get_cells result_reg*]注意这里setup设了2hold要设1。为什么因为setup检查的参考沿往后移了一个周期hold检查的参考沿也要相应移动否则hold检查会变得过于严格。具体来说setup的捕获沿从第1个周期移到了第2个周期hold的捕获沿默认也跟着移但hold检查应该保持在原来的第1个周期所以要用-hold 1把它拉回来。这个“setup设Nhold设N-1”的规则我见过很多人搞错。你如果只设setup不设hold工具会用默认的hold检查结果就是hold违例一大堆但其实那些违例是假的。5.2 虚假路径的识别与设置虚假路径是指那些在功能上永远不会发生的路径。比如一个多路选择器选择信号固定为0那另一路输入就是死逻辑不需要做时序检查。set_false_path -from [get_ports test_mode] -to [get_cells *]这行命令告诉工具从test_mode端口出发的所有路径都不用检查。因为test_mode在功能模式下是固定的不会翻转。设置false path要非常小心因为一旦设错工具就会完全忽略这些路径哪怕它们真的有时序问题。我的原则是只有在你100%确定这条路径在功能模式下不会发生时才设false path。不确定的话宁可让它报违例也不要随便屏蔽。5.3 时钟组与异步时钟域处理芯片里通常有多个时钟有些时钟之间是同步的有些是异步的。对于异步时钟域之间的路径你需要用set_clock_groups来告诉工具不要分析set_clock_groups -asynchronous -group {CLK_A} -group {CLK_B}这行命令表示CLK_A和CLK_B是异步的它们之间的路径不需要做时序检查。但注意这并不意味着你可以随便跨时钟域传信号。异步时钟域之间需要用同步器比如两级触发器来处理否则会有亚稳态问题。STA工具不管亚稳态那是CDC检查工具的事。如果两个时钟之间有固定的相位关系比如一个是另一个的分频那它们就是同步的需要用set_clock_groups -logically_exclusive或者直接让工具分析它们之间的路径。具体用哪种取决于你的时钟架构。5.4 约束文件的组织与版本管理SDC文件是代码应该跟RTL一样纳入版本管理。我一般把SDC拆成几个文件clocks.sdc时钟定义和时钟属性io.sdc输入输出延迟exceptions.sdcfalse path、multicycle pathtiming_derates.sdcOCV derate设置然后在顶层用一个top.sdc把它们source进来。这样改哪部分就动哪个文件不会互相干扰。另外SDC里一定要写注释。我见过太多项目SDC写得跟天书一样换个人接手根本看不懂为什么某条路径要设false path。注释里写清楚原因比如“这条路径是测试模式专用功能模式下选择信号固定为0”后面的人就不会误删。5.5 一些实用的TCL脚本片段跑STA的时候手动敲命令效率太低我一般会写一些TCL脚本来自动化。比如批量报告所有违例路径set viol_paths [get_timing_paths -slack_lesser_than 0 -max_paths 1000] foreach_in_collection path $viol_paths { set slack [get_attribute $path slack] set startpoint [get_attribute $path startpoint] set endpoint [get_attribute $path endpoint] puts Slack: $slack, From: $startpoint, To: $endpoint }这个脚本会把所有slack小于0的路径列出来方便你快速定位问题。你还可以加上-delay max或者-delay min来分别看setup和hold违例。还有一个常用的脚本是统计违例路径的分布set setup_viol [get_timing_paths -delay max -slack_lesser_than 0 -max_paths 10000] set hold_viol [get_timing_paths -delay min -slack_lesser_than 0 -max_paths 10000] puts Setup violations: [sizeof_collection $setup_viol] puts Hold violations: [sizeof_collection $hold_viol]这个统计能让你对时序收敛的难度有个快速判断。如果setup违例几千条那说明综合阶段的问题比较大如果只有几十条那可能是局部布局问题修起来快。6. 从STA报告到实际修复的思路6.1 读懂报告里的每一列PrimeTime的时序报告信息量很大我拿一个典型的报告片段来说Startpoint: FF1 (rising edge-triggered flip-flop clocked by CLK) Endpoint: FF2 (rising edge-triggered flip-flop clocked by CLK) Path Group: CLK Path Type: max Point Incr Path --------------------------------------------------------------- clock CLK (rise edge) 0.00 0.00 clock network delay (ideal) 1.00 1.00 FF1/CK (DFF) 0.00 1.00 r FF1/Q (DFF) 0.15 1.15 f U1/A (AND2) 0.05 1.20 f U1/Y (AND2) 0.08 1.28 f ... FF2/D (DFF) 0.03 9.85 f data arrival time 9.85 clock CLK (rise edge) 10.00 10.00 clock network delay (ideal) 1.20 11.20 clock uncertainty -0.20 11.00 FF2/CK (DFF) 0.00 11.00 r library setup time -0.10 10.90 data required time 10.90 --------------------------------------------------------------- data required time 10.90 data arrival time -9.85 --------------------------------------------------------------- slack (MET) 0.05这个报告里Incr是每一级的增量延迟Path是累积延迟。r和f表示信号的跳变方向r是上升沿f是下降沿。最后slack是0.05刚好满足。看报告的时候重点看几个地方哪一级的Incr特别大、时钟网络延迟是多少、uncertainty扣了多少、library setup time是多少。如果slack是负的先看是哪一级拖了后腿。6.2 setup违例的修复优先级setup违例的修复我一般按这个优先级来第一优先级检查约束是否正确。很多时候违例是约束写错了导致的比如时钟周期设短了、uncertainty设大了、input delay估高了。先把约束确认一遍排除假违例。第二优先级优化组合逻辑。如果路径上组合逻辑级数太多可以考虑插入pipeline寄存器、重新分配逻辑、或者用更快的cell。在综合阶段可以用compile_ultra -retime让工具自动做寄存器重定时。第三优先级优化布局。如果组合逻辑级数不多但延迟还是大那可能是布局太差导致线延迟高。可以加物理约束、调整floorplan、或者手动加buffer。第四优先级降频或改架构。如果以上都试过了还是修不好那可能真的是架构问题需要考虑降低时钟频率或者修改设计。6.3 hold违例的修复思路hold违例的修复跟setup不太一样。hold违例通常是因为数据路径太快或者时钟偏斜太大。修复方法主要有加延迟单元。在数据路径上插入buffer或者delay cell增加数据到达时间。这是最直接的方法但要注意不要引入新的setup违例。调整时钟树。如果时钟偏斜是主因可以通过调整时钟树来减小偏斜。但这通常需要改CTS结果成本较高。换慢速cell。把数据路径上的快速cell换成慢速cell增加延迟。这个方法在ECO阶段很常用。hold修复的一个原则是不要为了修hold而引入setup违例。加延迟的时候要算好余量一般加到slack刚好为正再多一点余量就行不要加太多。6.4 ECO阶段的操作要点到了ECO阶段网表已经基本定型只能做局部修改。这时候修时序一般用PrimeTime的ECO功能fix_eco_timing -type setup -methods {size_cell insert_buffer} fix_eco_timing -type hold -methods {size_cell insert_buffer}这两个命令会让工具自动修复时序违例然后输出一个ECO脚本你拿这个脚本去改网表。但自动修复的结果不一定最优我一般会先让工具跑一遍看看它改了什么然后手动调整。ECO阶段有几个注意点一是不要改太多改得越多引入新问题的风险越大二是要验证改完之后一定要重新跑STA确认三是要记录每次ECO改了什么、为什么改都要记下来方便后面复盘。6.5 时序收敛的全局观最后说一点个人体会。时序收敛不是STA一个环节的事而是从架构设计、RTL编码、综合约束、布局布线到STA签核的全流程协同。你在STA阶段看到的违例根因可能在很早的阶段就埋下了。我现在的习惯是在项目初期就把时序预算做出来每个模块分多少时钟周期、允许多少逻辑级数、接口时序怎么定全部提前规划好。然后在综合阶段就用STA做预分析不要等到布局布线完了才发现问题。越早发现修复成本越低。还有一点不要迷信工具。PrimeTime报出来的结果你要理解它背后的假设和局限。比如它默认的OCV模型、串扰模型、老化模型可能跟你的实际应用场景有偏差。你要根据项目的特点去调整这些设置而不是直接用默认值。时序路径分析这个事说到底就是理解数据在芯片里怎么流动、时钟怎么约束这个流动、以及制造偏差怎么影响这个流动。你把这三个问题想透了剩下的就是熟练度和经验积累。上篇先到这里下篇我们聊多时钟域、OCV、串扰和ECO的进阶内容。