参考原博地址:https://blog.csdn.net/weixin_46752319/article/details/107387584
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 skew,local skew,interclock 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。