第三章 违例报告解读: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 如何快速定位问题

说了这么多,最后给你总结一个快速定位问题的方法。拿到报告后,按这个顺序查:

  1. 看slack值:正数还是负数?负数的话,是setup还是hold?
  2. 看路径长度:从起点到终点,有多少级cell?超过15级,大概率是路径太长
  3. 看transition:有没有哪一段的transition特别大?超过库规定的80%就要注意
  4. 看net delay:有没有哪一段的net delay特别大?超过0.2纳秒就要查走线和扇出
  5. 看clock skew:launch和capture的clock delay差了多少?差太多的话,hold违例基本跑不掉

嗯,这套方法我用了十几年,屡试不爽。你回去拿自己的项目试试看,保证能快速找到问题所在。

下一章,咱们聊聊怎么修这些违例。到时候我会分享一些实战技巧,包括怎么插buffer、怎么换cell、怎么调整时钟树。敬请期待。