3. 时序报告基础
在 PrimeTime 中,时序签核的结论最终都要落到“报告”上。工具不会直接告诉你“设计能不能签核”,它给出的是一组可读、可筛选、可追溯的时序数据。理解 report_timing、report_constraint 与 report_analysis_coverage 三条命令的分工,是读懂这些数据的前提。三条命令分别回答三个不同层次的问题:某一条路径到底差多少?所有约束里哪些没满足?这些结论覆盖了设计中的哪些时序弧?
一、slack、arrival 与 required 的符号约定
先固定参照约定,全文与图示保持一致。PrimeTime 默认采用“到达时间—要求时间”的差值定义 slack:
slack = required_time - arrival_time
其中 arrival_time 是信号沿路径传播后实际到达捕获端时钟引脚的时间,required_time 是捕获时钟沿减去建立时间(setup)或加上保持时间(hold)后允许的最晚/最早到达时刻。按此定义,slack 为正表示满足约束,为负表示违反约束,负得越多越严重。setup 检查中 required 是“最晚允许到达”,hold 检查中 required 是“最早允许到达”,两者方向相反,但 slack 的符号含义一致。
一条路径的 arrival 由起点时钟沿、时钟网络延迟、数据路径单元延迟和线延迟累加得到;required 由捕获时钟沿、时钟网络延迟、建立/保持时间以及时钟不确定性(uncertainty)共同决定。因此当 slack 为负时,不能只盯着数据路径,还要看时钟偏斜(skew)、uncertainty 和库单元延迟是否被高估或低估。
二、report_timing:单条路径的细节视图
report_timing 是使用频率最高的命令,它输出一条或多条路径的完整时序明细。典型用法如下:
report_timing -to [get_pins U_ALU/reg_out/D] \
-delay_type max \
-max_paths 5 \
-nworst 1 \
-input_pins \
-transition_time \
-capacitance
关键选项的含义需要分清:-delay_type max 检查 setup,-delay_type min 检查 hold;-max_paths 限制报告路径条数;-nworst 控制每个端点报告最差几条;-input_pins 展开单元输入引脚,便于定位是哪一级门延迟过大;-transition_time 与 -capacitance 则把转换时间和负载电容一并列出,用于判断是否由驱动能力不足导致延迟偏大。
报告中的每一行通常包含 point、incr、path 三列。point 是路径上的引脚或端口,incr 是该级增量延迟,path 是从起点累加到该点的总延迟。读报告时先看最后一行 slack 的正负,再自下而上找 incr 最大的几级,往往就是优化重点。若某级 incr 明显异常,应检查其输入转换时间与输出负载是否超出库单元的工作范围。
三、report_constraint:全局约束的满足情况
如果说 report_timing 是“显微镜”,report_constraint 就是“体检表”。它按约束类型汇总所有违反项,常用形式为:
report_constraint -all_violators -verbose
report_constraint -max_delay -significant_digits 3
-all_violators 只列出未满足的约束,-verbose 展开每条违反的细节,-max_delay 则把范围限定在建立时间检查。报告会按 max_delay、min_delay、max_transition、max_capacitance 等类别分组,每类给出违反数量与最差 slack。它的价值在于快速判断“问题集中在哪一类约束”,例如 max_transition 违反很多,说明驱动与负载匹配是主要矛盾,而不是逻辑级数太深。
四、report_analysis_coverage:结论覆盖了哪些时序弧
前两条命令告诉你“结果是什么”,report_analysis_coverage 告诉你“这些结果是否可信”。它统计设计中所有时序弧的检查覆盖情况:
report_analysis_coverage -status detailed
report_analysis_coverage -exclude_untested
输出通常把时序弧分为 met、violated、untested 三类。untested 表示该弧没有被任何约束或时钟关系覆盖,常见原因包括:缺少 create_clock、时钟之间没有 set_clock_groups 或 false path 声明、生成时钟未正确定义、以及被 set_disable_timing 屏蔽。若 untested 比例偏高,即使 report_timing 显示 slack 为正,也不能认为设计已经签核,因为大量路径根本没有被检查。
五、路径分组:让报告可比较
PrimeTime 按捕获时钟把路径划分到不同 path group。默认情况下,report_timing 会在每个组内分别报告最差路径,而不是把所有路径混在一起排序。这一点非常重要:一个 2 GHz 的 core 时钟组 slack 为 −0.05 ns,与一个 50 MHz 的 USB 时钟组 slack 为 −0.30 ns,后者数值更差,但前者对签核的紧迫性可能更高。使用 -group clk_core 可以只看某一组,使用 report_timing -group [all_clocks] 则逐组汇总。
路径分组还决定了优化优先级。通常先处理高频组内的负 slack,再处理低频组;同一组内优先处理 slack 最负且逻辑级数最多的路径。若某组长期无法收敛,应回到约束层面检查时钟定义、uncertainty 和 IO 延迟是否设置过紧。
六、三条命令的联合使用顺序
一个可复用的检查顺序是:先跑 report_analysis_coverage 确认 untested 比例在可接受范围(例如低于 1%~2%),再跑 report_constraint -all_violators 看违反集中在哪类约束,最后用 report_timing 对最差路径逐条展开。若 coverage 显示大量 untested,应先补时钟与例外约束,而不是急着优化路径,否则优化目标本身就是错的。
把这三条命令当作一套组合工具:coverage 回答“查得全不全”,constraint 回答“哪里不满足”,timing 回答“具体差多少、差在哪一级”。只有三者一致,时序签核的结论才站得住。