第三章 违例报告解读:PrimeTime/Tempus报告结构、slack与transition、setup/hold违例的典型特征
各位同学,欢迎来到第三章。前两章我们聊了STA的基本概念和约束写法。今天咱们来点实在的——怎么读懂那些密密麻麻的时序报告。
说实话,我见过不少工程师,跑完PrimeTime或者Tempus,看到一堆红色违例就慌了。其实大可不必。报告这东西,说白了就是芯片的体检单。你得知道哪些指标是致命的,哪些只是小毛病。
我个人习惯,拿到报告先看三样东西:slack值、transition时间、还有违例类型。这三样看明白了,问题就解决了一半。
3.1 PrimeTime/Tempus报告结构
先说说报告长什么样。不管是PrimeTime还是Tempus,它们的报告结构其实大同小异。我以PrimeTime为例,给你拆解一下。
一份典型的时序报告,通常包含这几个部分:
- Header信息:告诉你这是哪个corner、哪个场景下的分析结果
- Path信息:从起点到终点的完整路径
- 时序计算明细:每一级cell的delay、net delay、transition
- Summary:最终的slack值、违例类型
举个例子,这是我从一个实际项目中截取的一段报告:
********************************************************************************
Startpoint: u_core/u_reg_data/Q
(rising edge-triggered flip-flop clocked by clk)
Endpoint: u_core/u_reg_addr/D
(rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: max (setup)
********************************************************************************
Point Incr Path
---------------------------------------------------------------- -----------
clock clk (rise edge) 0.0000 0.0000
clock network delay (propagated) 0.1500 0.1500
u_core/u_reg_data/Q (dff) 0.0000 0.1500 r
u_core/u_reg_data/Q (net) 0.0500 0.2000 r
u_core/U1/A (buf) 0.1200 0.3200 r
u_core/U1/Y (buf) 0.0800 0.4000 r
u_core/U1/Y (net) 0.0300 0.4300 r
u_core/U2/A (nand2) 0.1500 0.5800 r
u_core/U2/Y (nand2) 0.1000 0.6800 f
u_core/U2/Y (net) 0.0400 0.7200 f
u_core/u_reg_addr/D (dff) 0.0000 0.7200 f
-------- --------
data arrival time 0.7200
clock clk (rise edge) 1.0000 1.0000
clock network delay (propagated) 0.1500 1.1500
clock uncertainty -0.0500 1.1000
u_core/u_reg_addr/D (dff) 0.0000 1.1000 r
library setup time -0.0800 1.0200
-------- --------
data required time 1.0200
---------------------------------------------------------------------------
data required time 1.0200
data arrival time -0.7200
---------------------------------------------------------------------------
slack (MET) 0.3000
********************************************************************************
嗯,这里要注意,报告里每一行都对应一个物理单元。从起点到终点,你看到的每个cell、每段net,都是真实存在的。我个人习惯,先看最下面的slack值。如果是正数,说明这条路径通过了。如果是负数,那就得往下查。
3.2 slack与transition
slack这个词,直译过来是「松弛」。但在我们这行,它代表的是时序余量。说白了,就是你的数据到达时间比要求时间早了多少(setup)或者晚了多少(hold)。
我遇到过不少新手,看到slack是负的就开始慌。其实负slack也分情况:
- setup违例:slack为负,说明数据到得太晚了
- hold违例:slack为负,说明数据到得太早了
这两种情况,修复思路完全不同。setup慢了,你得想办法让数据跑快点。hold快了,你得让数据慢下来。听起来有点绕,但你想想看,setup和hold本来就是一对矛盾体。
再说说transition。transition就是信号从0到1或者从1到0的跳变时间。这个指标特别容易被忽略,但往往是大问题。
重要提醒:transition过大,会导致cell的delay变大,进而引发setup违例。transition过小,又可能引起信号完整性问题。我一般把transition控制在库要求的范围内,通常是上升沿和下降沿各不超过库规定的最大值的80%。
怎么在报告里看transition?很简单,看每一行最后那个字母后面的数字。比如上面报告里:
u_core/U1/A (buf) 0.1200 0.3200 r
这个「r」代表上升沿。但transition的具体值,PrimeTime默认不直接显示在路径报告里。你需要加个选项:
report_timing -transition_time -nets -significant_digits 4
加了之后,报告会变成这样:
Point Incr Path Trans
----------------------------------------------------------------- --------- ------
u_core/U1/A (buf) 0.1200 0.3200 r 0.0850
u_core/U1/Y (buf) 0.0800 0.4000 r 0.0920
看到没?最右边多了一列Trans。这个0.0850纳秒,就是U1/A引脚的transition时间。如果这个值超过了库规定的0.2纳秒,那就得想办法修了。
个人经验:我曾经在一个项目里,所有setup违例都修完了,但芯片还是跑不到目标频率。查了两天,最后发现是某条路径的transition超标了0.03纳秒。就这0.03,让整个路径慢了0.15纳秒。所以,transition这东西,千万别忽视。
3.3 setup违例的典型特征
setup违例,说白了就是数据跑得太慢了。它的典型特征有这些:
- 路径级数太多:一条路径上串了太多级逻辑,delay自然就大了
- 驱动能力不足:驱动cell太小,带不动后面的负载
- 线负载过大:长线或者扇出太多,net delay变大
- transition超标:信号跳变太慢,导致后续cell的delay变大
怎么从报告里判断?我教你一个方法。看Path那一列,从起点到终点,如果中间有超过15级cell,那基本就是路径太长了。再看Incr那一列,如果某一段的增量特别大,比如超过0.5纳秒,那这段就是瓶颈。
举个例子:
u_core/U15/Y (nand4) 0.4500 3.2000 f
u_core/U15/Y (net) 0.3800 3.5800 f
看到没?U15这个nand4的cell delay是0.45纳秒,但net delay有0.38纳秒。这个net delay明显偏大。我遇到这种情况,会先检查这个net的扇出和走线长度。
3.4 hold违例的典型特征
hold违例和setup正好相反。它是数据到得太早了,在时钟沿还没来之前就变了。典型特征:
- 路径太短:从起点到终点只有一两级逻辑
- 时钟偏斜太大:capture clock比launch clock晚太多
- cell delay太小:用了太大的cell,或者用了低阈值电压的cell
hold违例在报告里长这样:
********************************************************************************
Path Type: min (hold)
********************************************************************************
Point Incr Path
---------------------------------------------------------------- -----------
clock clk (rise edge) 0.0000 0.0000
clock network delay (propagated) 0.1500 0.1500
u_core/u_reg_data/Q (dff) 0.0000 0.1500 r
u_core/u_reg_data/Q (net) 0.0200 0.1700 r
u_core/u_reg_addr/D (dff) 0.0000 0.1700 r
-------- --------
data arrival time 0.1700
clock clk (rise edge) 0.0000 0.0000
clock network delay (propagated) 0.3500 0.3500
clock uncertainty 0.0500 0.4000
u_core/u_reg_addr/D (dff) 0.0000 0.4000 r
library hold time 0.1000 0.5000
-------- --------
data required time 0.5000
---------------------------------------------------------------------------
data required time 0.5000
data arrival time -0.1700
---------------------------------------------------------------------------
slack (VIOLATED) -0.3300
********************************************************************************
看到没?这条路径只有一级buffer,数据从起点到终点只用了0.17纳秒。但capture clock的network delay是0.35纳秒,比launch clock的0.15纳秒大了0.2纳秒。这就导致数据到得太早,hold违例了。
避坑指南:我曾经在一个项目里,把所有setup违例都修好了,结果hold违例冒出来一大堆。为什么?因为修setup的时候,我换上了更大的cell,让数据跑得更快。结果数据太快了,hold就出问题了。所以,setup和hold要一起看,不能顾此失彼。
3.5 如何快速定位问题
说了这么多,最后给你总结一个快速定位问题的方法。拿到报告后,按这个顺序查:
- 看slack值:正数还是负数?负数的话,是setup还是hold?
- 看路径长度:从起点到终点,有多少级cell?超过15级,大概率是路径太长
- 看transition:有没有哪一段的transition特别大?超过库规定的80%就要注意
- 看net delay:有没有哪一段的net delay特别大?超过0.2纳秒就要查走线和扇出
- 看clock skew:launch和capture的clock delay差了多少?差太多的话,hold违例基本跑不掉
嗯,这套方法我用了十几年,屡试不爽。你回去拿自己的项目试试看,保证能快速找到问题所在。
下一章,咱们聊聊怎么修这些违例。到时候我会分享一些实战技巧,包括怎么插buffer、怎么换cell、怎么调整时钟树。敬请期待。