时序约束中一种特殊的情景分析

描述

1 问题

在做模块级约束的时候,外部的真实IO delay是还不知道的。为了让模块综合结果尽可能满足外部苛刻的条件,经验值是将IO delay设置为相关联的驱动时钟周期的60%,给模块内部的路径留下40%的时钟周期,这适用于

1.   INPUT->REG路径

2.   REG->OUTPUT路径

而对于INPUT->OUTPUT的路径(feedthrough),如果按照这样的设置,因为端口输入和输出延时已经占了60%+60%=120%的时钟周期,超过一个周期,这是不可能实现的约束,一般会把IO delay调节成IO 相关联的驱动时钟周期的40%,给模块内部的路径留下20%的时钟周期

但是对于下面这样一种电路,情况有些特殊,这也是实际设计中经常出现的电路:

电路

注意到这个电路的不同之处在于,INPUT不仅连接了INPUT->REG的路径,同时另一分支连接到OUTPUT。而OUTPUT也同时被COMBO-A和REG->OUTPUT的逻辑所驱动。对于这样的结构,

1.   对于INPUT->REG,和REG->OUTPUT,总是希望IO delay是60%的时钟周期的

2.   INPUT->OUTPUT的feedthrough约束为20%的时钟周期。

要怎样才能同时满足这两个需求呢?

2结论与解决方案

1. 在做模块级综合的时候,对于IO路径一般会使用60%的端口时钟进行约束,如果这样的路径涉及到feedthrough path,也就是INPUT->REG的路径同时有分支到INPUT->OUTPUT的路径,并且该OUTPUT同时被这段feedthrough logic以及REG驱动,全部按照端口60%驱动时钟的IO约束会造成无法优化的路径,也就是infeasible path

2. 对于infeasible path,dc不会做任何优化,如果不解决这样的问题,综合结果不是最优解

3. set_max_delay=input delay(60%CLK_V)+comb delay+output delay(60%CLK_V)可以解决这个问题,但当端口情况复杂的时候约束数量会很多,并且约束本身不便于理解

4. 在同一个端口既定义了专门使用于INPUT->REG和REG->OUTPUT的CLK_V,同时定义了专门使用于INPUT->OUTPUT的CLK_V_FEED,并设置相应的CLOCK GROUP或者false_path可以最好地满足这个需求。

3测试与实验

以下面RTL为例:

这样一个电路经过翻译之后(综合优化之前)大概是以下的电路,INPUT->OUTPUT的路径组合逻辑部分是两个乘法器,而INPUT->REG的组合逻辑部分是两个加法器(这里不过多关注具体的功能):

假设:

1.    周期设为2ns,500MHz的频率

2.    整个设计只有一个时钟

3.    每条路径都是单周期路径

4.    IO的相关寄存器都存在于block之外,需要设置Virtual clock

5.   INPUT端口(除去CLOCK)驱动为一个X1的buffer,OUTPUT端口的负载均为3个X1的buffer

如果我们按照传统的约束方法,将IOdelay设置为60%的时钟周期:

电路

经过DC综合之后,可以看到电路被优化成了以下结构,蓝圈部分是input port->reg的路径,以寄存器为终点。红圈部分是我们要重点关注的input port->output port的路径,也就是feedthrough path:

电路

我们使用report_timing看一下结果。

可以看到input port->reg(蓝)的路径主要是两个加法器,重点关注input delay的设置,成功地被设置成60%的时钟周期(2*0.6=1.2),这是符合预期的。并且这条路径满足时序要求:

然后我们再看下input port->output port的路径(红)。这块主要是两级乘法器的逻辑。因为这块逻辑包含了不止一条的路径,report_timing默认情况下选择最差的一条(in_3[0]->out_comb[1]):

可以看到这条路径被映射成了AND2X1->AND3X1->INVX1->AND3X1->XOR2X1,单就这一段组合逻辑的延时(算上端口上的延时)是0.59。因为input delay和output delay已经超过了一个时钟周期(6+6=12>10),所以无论这段逻辑如何优化,都会是违例路径。

另外我们注意到在使用report_timing的时候,DC显示了如下warning:

这里infeasible的意思为“不可实行的”,查看该warning的详细信息:

这段描述的重点在红线部分。Infeasible path指的是那些无论如何都不可能满足约束的路径,也就是我们这个例子中Input port->output port的这条路径。如果不加以处理,综合器对这种路径是不会做任何优化的,会影响到最后的QoR。

按照manpage中的WHAT NEXT的方法,使用report_timing -attribute可以看到这段路径是infeasible的:

电路

既然问题是由于约束过紧导致,那么只要相应的放宽对这条路径的约束就可以了。之所以这个例子比较复杂,是因为我们如果不做特殊设置的话,无法兼顾到同时满足

1.   对于INPUT->REG,和REG->OUTPUT,总是希望IO delay是60%的时钟周期的

2.   INPUT->OUTPUT的feedthrough约束为20%的时钟周期。

为了解决这个问题,我们必须对此类路径做特殊设置。

方法1:

在约束中有一类特殊的约束叫exception,就是为了特殊情况而存在的。

可以使用set_max_delay的方法来对这样的路径进行单独约束,因为set_max_delay是一种exception,它可以覆盖原有的约束。举个例子,如果这条feedthrough path你所期望的延时是DELAY_COMB,并且端口的IO delay还是想保持原先的60%的时钟周期,那么可以通过设置max_delay=DELAY_COMB+0.6*P_VCLK*2。

这里可以看到这段INPUT->OUTPUT的max_delay被设置成了1.2倍的时钟周期外加一段延时的时间,这在现实中是不可能存在的路径。但这么设置并不意味着这条路径从外部起始寄存器->INPUT->COMB->OUTPUT->外部终点寄存器真的有超过一个时钟周期那么长(假设整个设计只存在一个时钟)。这样设置只是因为set_max_delay这个约束在进行分析的时候会天然考虑到input delay和output delay,而在这个方法中,并没有对端口的input delay和output delay进行改动,他们还是60%的时钟周期。这个约束的关键在于给予了中间这段从INPUT->OUTPUT的路径一段额外的DELAY_COMB的时间,而这个值是可以自己确定的。假设留给这段逻辑20%的时钟周期,也就是0.2*2=0.4,在约束中加入以下设置:

电路

综合之后的report_timing -from in_3[0] -to out_comb[1] -attribute结果:

电路

根据这个新的结果,我们可以看到

1.   之前的约束违例问这条路径不再是infeasible path

2.   之前这条路径是AND2X1->AND3X1->INVX1->AND3X1->XOR2X1,总的延时是0.59。DC没有做任何的优化。而在增加了max delay的约束之后,DC重新将这段路径优化成了NAND2X0->OR2X2->NBUFFX2->NAND2X0->XOR2X2,总的延时是0.5,以此来满足20%的时钟周期也就是0.4的约束。 虽然仍然有违例,但比起之前infeasible path没有得到优化,这段路径的在优化后延时减小了。

方法2

方法1使用set_max_delay来给这段INPUT->OUTPUT路径设置20%的时钟周期,对于一组的INPUT->OUTPUT,约束只需要加三行。

但实际上在综合之前,是不知道哪些INPUT->OUTPUT会存在这样的feedthrough的情况,因而为了保证结果,对于所有这样的路径都要进行max delay的设置来防止infeasible path的出现。实际的设计中端口不全是由是一样的外部时钟驱动,对于不同外部时钟驱动的端口,都要分别进行max delay的约束。假设这样的INPUT->OUTPUT组数特别多,方法1实际上是很繁琐的。比如如果有3个输入都是不同时钟驱动的,3个输出也都是不同时钟驱动的,那么一共有3*3=9组max_delay需要设置。

并且使用max delay的设置,从直观上并不利于理解。因为max delay设置的值实际上超过了一个时钟周期。

那么是否可以对feedthrough的IO端口额外做如下设置?

电路

通过使用set_input_delay -add,在IO端口额外加上一个40%VCLK的时钟。这样对于上述场景(3个输入都是不同时钟驱动的,3个输出也都是不同时钟驱动),只需要6条设置input delay和output delay的命令,不需要对于每一组可能情况都去进行设置。

并且这样对于INPUT->REG的路径,还是会使用60%VCLK的约束,满足需求。但是对于feedthrough path,因为IO同时存在40%VCLK和60%VCLK的约束,他们都是基于同一个时钟VCLK,实际上还是会使用更紧的60%VCLK-60%VCLK的约束,而忽略了40%VCLK的约束,问题还是没有得到解决。使用report_timing -from in_3[0] -to out_comb[1] -attribute观察路径:

电路

为了将feedthrough的路径和INPUT->REG/REG->OUTPUT的路径区分开来,需要在端口专门设置虚拟时钟CLK_V_FEED来进行约束:

电路

重新综合,使用report_timing -from in_3[0] -to out_comb[1] -attribute观察路径:

电路

可以看到这个infeasible的约束依然存在。

不同的地方在于,此时我们通过命令report_timing-from [get_clocks CLK_V_FEED] -to [get_clocks CLK_V_FEED] 观察同样的路径,可以看到相新设置的CLK_V_FEED已经设置到端口上了:

电路

如果能有一个办法来取消CLK_V到CLK_V的约束就好了。

在exception中,false path可以实现类似功能,在这里可以使用false path设置:

电路

重新综合,使用report_timing -from in_3[0] -to out_comb[1] -attribute观察综合后路径:

电路

可以看到这个时候这条路径的结果已经好于加false_path之前的结果。这是因为如果没有设置false_path,更紧的feedthrough约束60%CLK_V->60%CLK_V会占主导作用,DC发现有infeasible的约束时便不做任何优化,即便合理的约束也同时存在。而false path可以解决这个问题。

但使用false path与之前set_max_delay类似,因为必须是每组clock一一对应,当端口clock数量繁多的时候,会有设置繁琐的问题。

与false path相类似功能的,有另外一个命令是set_clock_groups,实现起来比较简单。被设置到同一个group的时钟之间存在约束,而被设置到不同group的时钟之间不存在约束。如果通过set_clock_groups将驱动INPUT的CLK_V时钟和OUTPUT驱动的寄存器CLK_V时钟分到不同的clock group,那么这个问题就能得到解决。

但由于这里驱动INPUT的CLK_V和OUTPUT驱动的寄存器的CLK_V是同一个时钟,一个时钟没法被分到不同的group,必须将CLK_V分为CLK_V_I和CLK_V_O:

电路

设置CLK_V_I和CLK_V_O到不同的clock group,可以取消CLK_V_I和CLK_V_O之间的约束,但在这一步之前,需要先确定好CLK_V_I/CLK_V_O和CLK以及CLK_V_FEED之间的关系。CLK_V_I/CLK_V_O与CLK之间的约束是需要的,这是INPUT->REG和REG->OUTPUT的关系,要把他们归到一个group。而CLK_V_I/CLK_V_O与CLK_V_FEED之间的关系是不需要的,因为这里只需要40%CLK_V_FEED->40%CLK_V_FEED的feedthrough约束,而不需要类似60%CLK_V_I->40%CLK_V_FEED这样的关系。

可以通过以下设置,其中第二个set_clock_group用于取消第一个set_clock_group里的CLK_V_I和CLK_V_O之间的关系:

电路

这样一来,CLK_V_I和CLK_V_O之间就不会存在约束。再次综合,使用report_timing -from [get_clocks CLK_V_I] -to [get_clocks CLK_V_O]:

电路

可以看到原先存在的60%CLK_V-60%CLK_V路径因为clock group的原因已经不存在了。

使用report_clock -groups来观察当前的clock group和false path情况,符合预期:

电路

最后使用report_timing -from in_3[0] -to out_comb[1] -attribute观察综合后路径:

1. 使用virtual clock的约束和之前使用set_max_delay的约束实现了同样的目标,给feedthrough path留下了2-0.8-0.8=0.4的时间,达到了目的。(注意到这和set_max_delay的综合结果并不一致,但路径都得到了优化)。

2.相比于set_max_delay,使用virtual clock约束更便于理解,当端口时钟情况复杂的时候设置起来更加便利。

3.false path 和 set_clock_group都能实现需求,但当外部clock数目很多的时候使用set_clock_group来定义clock之间的关系比set_false_path更为简洁明朗

4. false path只针对STA,set_clock_group可以选择logically exclusive, phisically exclusive。在后端做信号完整性分析的时候有区别。使用set_clock_group会更合理一些。

4补充

最后完整的sdc如下:

电路

这里提供了两种参考方法,但具体到实际项目中,不同的设计不同的情况不同的公司有不同的应对,大家在实际设计中都是如何处理这种情况的呢?欢迎留言讨论。如果文章中有任何错误,也请留言指出,大家一起学习进步~

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分