ICC时钟树综合

时钟树综合就是指从某个clock的root点长到各个sink点的clock buffer/inverter tree。工具试图将某个clock所属的所有sinks做到相同长度,即尽可能的使一个时钟信号到达各个终端节点的时间相同。

               

在没有进行时钟树综合之前,时钟树暂未生成,时钟逻辑结构如左图所示,一个时钟源端(root)最终扇出到很多寄存器的时钟端。但是我们知道,时钟源到达不同寄存器所经历路径的驱动和负载的不同,使得时钟信号到达各个寄存器时钟端的时间也不一样,将到达不同寄存器的时间偏差称为偏差(skew),传统CTS就是为了减小skew。

 

                                                                                                

经过了时钟树综合,通过加入如右图中三种颜色三角形的三级buffer等方式形成一个时钟树,时钟信号会先到达各级buffer使得最终到达各个寄存器时钟端的时间几乎相同。

所以,时钟树综合的目的有两个:

                 1、clock skew尽量小,特别是对时钟质量要求比较高或者高频时钟;

                 2、clock latency尽量短。

 

首先对于一个设计,要进行时钟树综合,开始最重要的一步就是定义好时钟端,root和sink都需要知晓,软件根据定义计算延迟。

                                                            

首先定义时钟的root点,使用create_clock定义时钟的root点

如果是generated clock(生成时钟)需要使用create_generated_clock定义,它的master clock需要定义清楚。同时要求generate clock与master clock是可以trace通的。

                                                       

                                                               

如上图所示的Master clock,CLKP以及Generated clock 命名为CLKPDIV2,使用命令定义:

Icc_shell>create_clock -name CLKP  [get_pins UPLL0/CLKOUT]

Icc_shell>create_generated_clock  -name CLKPDIV2  -source UPLL0/CLKOUT   -add    -master_clock CLKP  -divide_by 2 [get_pins UFF0/Q]

master clock就是通过create_clock定义的主时钟,图中即为CLKP;通过命令将分频时钟定义为生成时钟。

在genereated clock的时候一定要明确generated clock与master clock的相位关系(rise->rise or rise->fall or fall->rise or fall->fall), 这些关系由桥梁source clock嫁接,所以有了generated clock和source clock,以及source clock和master clock的关系。

(个人理解:source)

上图中source clock即为master clock,但是如果根据声明找到的generated clock和master clock的关系和实际的关系不一致,否则会造成一些分析错误。

                                                

如图所示,master clock为CLK ,生成时钟为uDIV。

如果定义:create_clock -period 10 clk

                      create_generated_clock  -name CLKdiv2    -divide_by 2   -source clk  [get_pins Udiv/Q]

那么根据定义,master clock 和gerenated clock的相位关系如图所示:

                                                            

根据上面定义,generated_clock是定义在二分频的输出端Q上,其source为CLK。但是我们看到Udiv这个寄存器的时钟端CK与CLK是反相的(即相位差180度)。

实际上master clock 和gerenated clock的相位关系应为:

                                                             

修正的方法一是改变generated clock的source,即让generated clock和source clock的路径唯一且单一(单一是指,声明的相位边沿关系和实际的相位边沿关系一致)。一般做法就是将source clock设置在触发器的clock端。

对应的命令应为create_generated_clock -name CLKdiv2 -divide_by 2  -source [get_pins Udiv/Clk] [get_pins Udiv/Q]

二是直接声明generated clock和master clock的相位边沿关系。如下:

create_generated_clock  -name CLKdiv2   -edges {2 4 6}  -source CLK  [get_pins Udiv/Q]

考虑到后期review constraint的便利性,强烈建议使用第二种方式来实现(实际项目中都是采用这种方法)。

(个人想法。在ICC man page中,对于create_generated_clock的 -source master_pin选项
Specifies  the  master clock pin, which is either a master clock source pin or a pin in the fanout of the master clock and  driving  the  generated clock definition pin.  The clock waveform at the master pin is used for deriving the  generated  clock  waveform.

也就是说 -source 选项后面接的可以是驱动生成时钟的触发器的clock引脚?对于source clock的概念不是很理解。

                                

像这样的多级分频时钟,对于FFdiv3的定义为

Create_generated_clock -name CLK_mux_div3            -divide_by 3   -source FFdiv3/CK -master CLK_mux -add

Create_generated_clock -name CLKdiv2_mux_div3   -divide_by 3   -source FFdiv3/CK -master CLKdiv2_mux -add

Create_generated_clock -name CLKdiv4_mux_div3   -divide_by 3   -source FFdiv3/CK -master CLKdiv4_mux -add)

 

定义好了时钟源端之后,需要对时序路径的端点。

Pin类型

别名

解释

工具的处理

 

Stop pin

Sink pin/sync pin

 

需要平衡的节点

CTS会优化时序DRC以及时钟树的skew和insertion delay

 

 

Exclude pin

 

 

Ignore pin

 

 

不用平衡的节点

CTS会忽略insertion delay和skew的优化

但仍会修复时钟树上的时序DRC

 

Non_stop pin

 

 

信号穿过这个节点

穿过这个节点找到最终的sink计算并优化insertion delay和skew

 

Float pin

 

 

最终节点“藏”在后面

与stop pin的处理相同,不过clock pin上认为具有一些延迟

设置时钟树例外的优先级(set_clock_tree_exceptions)

1、不间断引脚(-non_stop_pins) 2、排除引脚(-exclude_pins)3、 停止引脚(-stop_pins)4、浮动引脚(-float_pins)

Others: 5、勿触碰子树(-dont_touch_subtrees)

 

1、Nonstop pins

不间断引脚:ICC会穿过不间断引脚以跟踪查找真正的时钟树端点。驱动生成时钟的时序单元的时钟引脚是隐式不间断引脚。

Icc_shell>set_clock_tree_exceptions -non_stop_pins { list of pins }

                                                    

·ICC认为集成时钟门控ICG(integrated clock-gating)单元的时钟输入引脚是隐式不间断引脚,不用手动对其设置,如图中①所示。(clock gating cell是降低动态功耗(dynamic power)不可缺少的一个单元。而ICG还可以消除毛刺。)

·若时序单元的扇出驱动的是生成时钟(generated clock),即该时序单元用于分频用,用于产生生成时钟,如图中②。ICC将该时序单元的时钟引脚时为隐式不间断引脚(implicit nonstop pins),并穿过该时序单元追踪定位真正的时钟树端点。

 

2、Exclude pins(Ignore pins)

排除引脚:时钟树时序计算和优化中排除的时钟树端点,即不进行时钟树的balance。ICC仅在计算和优化设计规则约束(逻辑DRC,即max_cap / max_tran / max_fanout / max_length)中使用Exclude pins。

Icc_shell>set_clock_tree_exceptions -exclude_pins { list of pins }

·Implicit exclude pins(隐式排除引脚)

ICC会从clock source向后trace,自动确定implicit stop pins和implicit exclude pins(自动确定的,所以称为implicit)。

ICC将以下时钟端点定义为隐式排除引脚:

           ·另一个时钟扇出时钟树的源引脚(Source pins)    

           •时序单元的非时钟输入引脚

           •多路选择器选择引脚              

           •三态使能引脚                  

           •输出端口

           •定义不正确的时钟引脚(例如,时钟引脚没有触发边沿信息或没有到输出引脚的时序弧)

           •保持恒定的缓冲器或反相器的输入引脚(通过使用set_case_analysis)

           •没有任何扇出或没有任何启用的时序弧的组合逻辑单元或集成时钟门控单元的输入引脚

所有非时钟引脚(如FF的D引脚或组合逻辑的输入)都称为排除(忽略)引脚。在时钟树传播期间不需要考虑这些管脚,不需要balance。

除了ICC推断的排除引脚(隐式排除引脚)外,ICC还支持用户定义(或显式)排除引脚。例如,您可以定义一个排除引脚来排除从某些组合逻辑引出的时钟树的所有分支(如下图所示),或者排除隐式停止引脚。

                                                      

 

3、Stop pins(Sink pins)

停止引脚:用于平衡延迟的时钟树的端点。在时钟树综合期间,ICC将使用Stop pins来计算和优化设计规则约束和时钟树时序(Skew和插入延迟)。Stop pins也称为Sink pins,也就是我们所说时钟树进行balance的sink端。

Icc_shell>set_clock_tree_exceptions -stop_pins { list of pins }

##FF的所有时钟引脚称为停止(同步)引脚。到达SYC/STOP引脚后,时钟信号不应传播。

默认时钟汇点是隐式停止引脚。此外,ICC支持用户定义(或显式)停止引脚。例如,可以定义一个停止引脚来结束在组合单元输入上的分支,或者使用隐式排除引脚作为时钟汇点。

ICC为所有停止引脚(隐式和显式)分配零相位延迟,并在延迟平衡期间使用此延迟。

所以工具只对stop pins的delays(minimize skew)进行balance,如果需要对其他pins需要进行优化,需要对pins进行设置告诉ICC。

 

4、Float pins

                                 

浮动引脚:具有特殊插入延迟要求的时钟引脚。与停止引脚(stop pins)类似,但在构建时钟树时会考虑该引脚的内部时钟延迟。工具在计算到该Float Pins的插入延时(Insertion delay)时,将把Float Pin延迟(正或负)添加到计算Insertion delay中去。

如上图所示,它是硬宏(hard macro)的时钟输入管脚,在构建时钟树时需要考虑它。但在将其视为同步管脚之前,需要平衡宏的内部树。最终节点藏在后面。

Icc_shell>set_clock_tree_exceptions    -float_pins [get_pins pin_list]

• -float_pin_max_delay_fall max_delay_fall_value

• -float_pin_max_delay_rise max_delay_rise_value

• -float_pin_min_delay_fall min_delay_fall_value

• -float_pin_min_delay_rise min_delay_rise_value

• -float_pin_logic_level logic_level_value

PS:使用-float_pins,必须至少指定一个浮动引脚延迟选项

 

# Specifying a negative float pin

Icc_shell>set_clock_tree_exceptions -float_pins U1/CLK   -float_pin_max_delay_rise -0.5 -float_pin_max_delay_fall -0.5

# Specifying a positive float pin

Icc_shell>set_clock_tree_exceptions -float_pins U4/CLK   -float_pin_max_delay_rise 0.5 -float_pin_max_delay_fall 0.5

增加引脚insertion delay,指定负引脚延迟(negative float pins)

减小引脚insertion delay,指定正引脚延迟(positive float pins)

                                            

Hard macro的内部延迟信息在单元的时序模型中表示(.lib)。ICC使用该模型确定Hard macro的外部时钟引脚,作为时钟汇点。CTS时,ICC对macro外部时钟引脚平衡skew并最小化插入延迟。

当需要改变Hard macro时序特征时才需要使用浮动引脚来指定Hard macro内部时钟树的时序特征。

 

     

                                        

以student guide中的例子解释这几种引脚。如图所示,macro的引脚被定义为隐式排除引脚Implicit exclude pin,所以ICC不会计算引脚之后,即macro的skew和insertion delay

                                    

通过set_clock_tree_exceptions -stop_pins命令,将macro的引脚定义为stop pin,ICC能够优化其skew和insertion delay,但是图中我们发现,ICC将clock到IP_CLK端和clock到FF的clk端间进行了balance,而未考虑macro内部的延迟。

                                   

而将IP_CLK设置为float pin时,可以考虑macro内部时钟树的时序特征,使得clock到macro内部的FF的insertion delay与clock到外部FF的insertion delay进行了balance。Clock。

 

5、Dont_touch_subtrees

勿触碰子树:在某些情况下,希望保留现有时钟树的一部分,需要这样设置。例如,当两个时钟网络共享多路选择器后面的某些时钟逻辑的一部分时。保留的时钟树的部分称为不触碰子树。

Icc_shell>set_clock_tree_exceptions -dont_touch_subtrees

                                       

当设计中存在已设计好的的时钟树(图中Pre-exisiting clock tree),可使用set_clock_tree_exceptions -dont_touch_subtrees $name 将其设为dont_touch属性,CTS将会将其他设计的时钟树与pre-existing时钟树进行balance

                                                         

或者通过remove_clock_tree命令将其移除,CTS将会重新计算自CLOCK到sink端的延迟。

 

 

上述为关于时钟端点的介绍。并且所说的都是在同一时钟下各个路径间进行balance。

若设计中存在多个create_clock定义的时钟root端,两个时钟并不是同步的,但是他们的某些register会进行talk。默认情况下,CTS build CLOCK1和CLOCK2时,会各自build clock tree,不会做inter-clock balance。

若要使多个时钟树之间进行balance,需要给工具添加命令。

                         

上图是未做inter-clock balance的两个clock

icc_shell>set_inter_clock_delay_options -balance_group "Clk1 Clk2" -balance_group_name group2

                    balance_inter_clock_delay -clock_trees { clock_1 clock_2 }

                                   

上图为inter-clock balance后的两个clock。PS:

TNS:total negative slack总的负时序时间之和,即小于0的slack之和

WNS: worst negative slack最差的负时序

THS:total hold slack总的保持时间的负时序之和

WHS:worst hold slack最差的保持时间的负时序

slack如果为正值,说明达到了设计时序要求;如果为负值,说明没有达到设计时序要求。

所以还需要对setup time进行修复。

                                   

-delay_offset指定延迟偏移值。

正值表示-offset_to选项中指定的时钟落后于-offset_from选项中指定的时钟。         

负值表示-offset_to选项中指定的时钟早于-offset_from选项中指定的时钟。

 

lab中教了一种检查时钟树的方法,有助于进行时钟端点的设置等。

·查看设计中的时钟偏移和属性ℹicc_shell>report_clock -skew -attributes

                                                            

通过报告可以查看设计中定义的时钟、生成时钟及其属性。

·查看时钟树总体情况 icc_shell>report_clock_tree -summary

               

可以查看时钟树的最大路径,即最大插入延迟,所驱动的sink端和插入的buffer的面积等,在还未进行CTS前暂未插入buffer,面积为0。同时可以发现SD_DDR_CLK所驱动的sink端为0。

通过之前report_clock,我们知道该时钟是生成时钟。

·查看它的source port        icc_shell>report_port  sd_CK

                                  

direction为out,  output的port 没有endpoint。

·查看设计中是否存在violation       icc_shell>report_constraint -all

                                   

该设计中只有hold的违例和面积违例,面积违例可以忽略,而在CTS之后才修复hold violation,此时设计符合CTS的条件。

 

·通过gui方式查看时钟树详细信息,可以帮助工程师快速理清clock的结构和debug clock tree 质量

GUI>Clock>New Interactive CTS Window

          

可以看到各个clk驱动的sink端的数目及cell例化的名字,以及时钟驱动这个cell使用上升沿驱动还是下降沿驱动等。

其中有些clock驱动的pin设置为exception:implicit_exclude_pin  这些pin都是MUX的select pins,需要被忽略,不做skew和latency的优化,通过查看schematic图可以更好的分析。

而该设计中,将MUX的引脚设定为stop pins。

icc_shell>set_clock_tree_exceptions -stop_pins {I_SDRAM_TOP/I_SDRAM_IF/sd_mux_*/S}    使用通配符*查找所有要求的端口            Gui>Clock>Set Clock Exceptions

此时,所有查找到的pins已被更改为stop pins,

 

在对时钟的root点和端点进行准确的定义后,开始进行对时钟树综合的设置。

·设置目标skew        

Gui>Clock>Set Clock Options

ICC默认target skew为0,但是设置可接受的skew可以减少run time         icc_shell>set_clock_tree_options -target_skew 0.1

同时可以设置target early delay(即insertion delay)一般可不设置

设置max_fanout , max_transition , max_capacitance

                  

 

·设置时钟树的references

时钟树综合前给软件指定创建时钟树的单元,一般用时钟buffer或时钟反相器。

Buffer:上升下降时间基本相同,逻辑简单,便于post-CTS对时钟树的修改;面积大,功耗大,insertion delay大。

反相器:面积小,功耗小,insertion delay小,对时钟duty cycle有利;不易做时钟树的修改。

一般库里的时钟buffer或inverter都是以CLK或CK开头,可用通配符查找

icc_shell>set_clock_tree_references -references { CLKBUFHSV12 ...$list}

                                 -references { list }  -sizing_only

                                 -references { list }  -delay_insertion_only

Gui>Clock>Set Clock Tree References

           

 

·时钟树布线规则的定义

                                                    

首先删除之前定义的NDR(non-default rule)         icc_shell>remove_routing_rules -all

为时钟线定义NDR(一般设置双倍线宽,双倍间距)

时钟的翻转频率较高,clock path 上受到的串扰以及 EM 影响也较大。因此,通常会采取双倍宽度的绕线宽度。默认的绕线规则都是单位宽度,就是指 technology lef 文件中定义的金属层宽度。

                                 

Icc_shell>define_routing_rule clk_rule(your rule name) -default_reference_rule -multiplier_spacing 2 -multiplier_width 2

或者

Icc_shell>define_routing_rule  CLOCK_DOUBLE_SPACING \

-spacings {METAL1 xx METAL2 xx METAL3 xx METAL4 xx METAL5 xx}  \

-widths {METAL1 xx METAL2 xx METAL3 xx METAL4 xx METAL5 xx}           xx是设置的参数

Gui>Route>Routing Setup>Define Routing Rule>New

为时钟布线选择自己定义的NDR以及金属层次。由于标准单元出pin大部分是M1/M2,如果设置ndr rule,会导致很多DRC。因此,在sink端使用默认规则(默认线宽、间距)进行布线。

                           

Icc_shell>set_clock_tree_options -routing_rule CLOCK_DOUBLE_SPACING   -layer_list {METAL3 METAL5}  \

                    -use_default_routing_for_sinks 1

                                                    

为了使得clock tree质量更好,我们往往将高层用来作为时钟信号的走线。

set_clock_tree_options -layer_list {M7 M8}

 

·时钟树综合前准备

查看时钟树综合设定,确认上述设定正确   icc_shell>report_clock_tree -settings

进行物理检查   icc_shell>check_physical_design -stage pre_clock_opt -display

设置时钟树延迟计算模式

arnoldi > awe > elmore 精确程度

icc_shell>set_delay_calculation_options  -preroute awe   -postroute arnoldi

-routed_clock arnoldi   -arnoldi_effort medium   -awe_effort medium

检查时钟树      icc_shell>check_clock_tree

 

·时钟树综合

 

①icc_shell>clock_opt -only_cts -no_clock_route

根据时钟域以及路径关系, skew 可以分为global skewlocal skewinterclock skew

·Global skew 是指,同一时钟域,任意两个路径的最大 skew 。任意两条路径,不管是不是timing path,都会算作gloabl skew计算的对象。CTS时,工具更关注的是global skew, 会尽可能地将global skew做小。

                                                 

icc_shell>report_clock_tree -summary    报告global skew

报告每个时钟树在CTS阶段插入的buffer数量和面积,时钟树的最长路径延时,最重要的是时钟skew的大小,即同一时钟域下,最大路径减最小路径的值。

·Local skew 是指,同一时钟域,任意两个有逻辑关联关系的路径最大 skew 。这边需要注明,必须是存在逻辑关系的path才会计算local skew,也就是说必须要是timing path。如下图所示,在分析timing的时候,更多地是关注local skew。

                                                    

icc_shell>report_clock_timing   -type skew -significant_digits 3      报告local skew

                                     

·interClock skew 是指,不同时钟域之间路径的最大 skew

                                                      

·icc_shell>report_timing       生成时序报告,主要检查slack为正,时序符合要求

                                                          

·icc_shell>report_constraint -all      查看违规报告

                                                           

如图中只存在的是hold和面积的违规,并且前面的报告分析CTS的质量满足,Pre-CTS完成。

 

·Post-CTS

clock的Timing分为两种模式,ideal clock和propagated clock。

CTS之前并没有clock, 因此我们需要建立一个ideal的clock,这时从clock端口到寄存器CK端口的network delay来自sdc中的set_clock_latency设置;

做完CTS,并且update好IO latency之后,我们的clock就会自动的转换成propagated的clock,这时network delay就是实际时钟互连线网络的RC extraction算出来的delay。

                                             

CTS之后由于时钟树已经建立,所以需要将时钟网络以及高扇出网络的理想属性移除,并开始修复hold违反。下面逐一进行讲解如何操作。

·在CTS后,工具会自动移除所有时钟的理想属性。最好也手工设置

icc_shell>remove_ideal_network [ all_fanout -flat -clock_tree ]

icc_shell>remove_clock_latency $clk

将其设置为icc_shell>set_propagate_clock [ get_attr $clock source ]

 

 

·重新定义关于clock uncertainty的定义,去掉其中估计的clock skew的部分

clock uncertainty分为setup和hold,preCTS和postCTS几种不同的情况
一般的处理原则是:
pre CTS,setup: uncertainty = PLL jitter + 预估的clock skew    pre CTS,hold: uncertainty = 预估的clock skew   

post CTS,set_propagate_clock [all_clocks] 

post CTS,setup: uncertainty = PLL jitter            post CTS,hold: uncertainty = 0
有时fundry要求hold uncertainty保留一定的量,这时就把那个保留量加到上面的公式中

icc_shell>set_clock_uncertainty  -setup 1 $clk                  icc_shell>set_clock_uncertainty  -hold 0.1 $clk

在移除理想属性以及sdc中的latency信息之后用update_clock_latency来更新latency信息。

icc_shell>update_clock_latency

                                

 

·CTS之后(post CTS)开始关心hold time

icc_shell>set_fix_hold [ all_clocks ]

查看设计的报告   icc_shell>report_qor (quality of result)

Psyn经常配合-area_recovery选项,对面积进行优化

设置icc_shell>set_max_area 0

icc_shell>set physopt_area_critical_range 0.2 该命令表示在timing slack 大于某个值的paths 上 optimize area(power)

指定若path存在指定的slack的值,则会对面积进行优化,因为对面积的优化会导致时序变差,只有有slack余量能对进行面积优化

一般给的建议是 place是 10% period       CTS 8% route 5%

Icc_shell>extract_rc          提取寄生参数

②icc_shell>clock_opt  -only_psyn  -area_recovery  -optimize_dft  -no_clock_route

Gui>Clock>Core CTS and Optimization

                                                          

icc_shell>report_qor

                                         

可以看到前后对比的qor 经过hold的修复 已经没有hold的WNS和TNS

icc_shell>report_constraint -all   查看违规

                                                 

经过hold修复,已经没有hold的违规

 

最后,进行时钟的绕线

③route_zrt_group -all_clock_nets -reuse_existing_global_route true

                                

icc_shell>report_constraint  -all    确认没有产生违规

icc_shell>report_design -physical

 

保存设计 save_mw_cel -as clock_opt_route

时钟树阶段完成

 

 

添加:

时钟树阶段完成后,由于设计插入了许多反相器或者buffer,这些单元也是一个个标准单元,需要重新使用

derive_pg_net将他们与P/G net和pin相连,否则在verify_lvs使会产生短路的error。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐