随着频率提高,时钟网络的功耗占比也越来越高,在满足时序约束和signoff要求的情况下clock buffer越少,功耗自然也就越小,而且,随之减短的latency也有助于时序收敛。
CTS阶段常用命令
放松target skew是降低整体buffer数量最有效的方法,仅少数设会有latency和skew的要求,大部分项目里只要时序能收敛,skew大也没什么。
set_clock_tree_options -target_skew 0.3 (default: 0)
挂的scenario能覆盖所有sdc即可,挂的越多,clock qor也并不会变得更好,反而run time更久,clock buffer也会更多。
set_scenario_status [get_scenarios -filter active] false
set_scenario_status $scenario -active true
在一些只有func和scan两个mode的项目里,可以考虑先长func tree设don't touch后再做scan tree,这样也可以减少clock buffer数量,但是这种方法有时候时序会不如一起长tree的方式。
set_scenario_status -active false [get_scenarios]
set_scenario_status -active true [get_scenarios FUNC]
clock_opt -from build_clock -to route_clock
set_dont_touch_network -clock_only [all_clocks]
set_scenario_status -active false [get_scenarios]
set_scenario_status -active true [get_scenarios {FUNC SCAN}]
clock_opt -from build_clock -to route_clock
latency长要么逻辑多,要么距离root远,要么就是时序单元有很长的内部延时,长tree算进去了。
CTS实例分析
innovus可以在长tree时用cluster的方案,只看不需要balance的情况下,clock tree都能长多长,ICC2没有这样的命令,需要的话可以自己ignore所有的sink pin。
set_clock_balance_points -consider_for_balance false -balance_points [get_clock_tree_pins -filter "is_sink == 1"]
CTS之后再remove_clock_balance_points,report_clock_qor即可。
1)针对逻辑多的问题,需要在CTS阶段,允许CTS优化tree上的组合逻辑,使用相同的VT。
set_dont_touch [get_flat_cells $clock_opt_cell_list ] false
set_lib_cell_purpose -include cts [get_flat_cells $clock_opt_cell_list]
2)物理距离远的情况,除非调floorplan,不然很难做短latency,有一种情况除外,那就是channel里没加soft blockage,导致寄存器放进去了,可以观察有没有detour的clock buffer,往往与channel里寄存器balance工具会插这类命名的buffer。
3)最后,一些sram内部有一部分延迟在CTS阶段算到clock tree上,导致长tree会拉长其他寄存器的latency。需要把这些pin抓出来,offset设成0。
set_clock_tree_options -offset 0 [get_pins $list]
如果只有timing check的寄存器之间需要balance,那clock buffer肯定就少了,然而传统的CTS只能balance global skew,顶多再针对local skew做优化。
优化local skew把cts.compile.enable_local_skew和cts.optimize.enable_local_skew设为true。
如果能确定哪些sink pin只有彼此间有timing check,可以只让他们balance。
set_clock_balance_points -consider_for_balancing true -balance_points [get_pins $list]