clock tree
检查设计是否准备好 CTS
check_design -checks pre_clock_tree_stage
检查 的内容有
clock definition & propagation;
reference cells
有没有标记 dont touch的参考单元
skew balancing : 多个时钟之间的 冲突 的平衡;
multi_voltage :对于 multi voltage 的设计 需要插入 AON 的bufs / invs ; 会检查 这些bufs 是否是AON的;
capacitance and transition constraints
other issues : 在clock网络中 存在 dont_touch 的nets;
对于 时钟树综合的 modes / corners;
ICC II 是针对所有的 active(有效的)scenarios 创建时钟树的;
时钟树综合 也会执行 时钟网络的 逻辑DRC 的修复,包括 max_transition &/or max_capacitance
如果你不希望在CTS 的时候 针对某一场景进行优化, 使用:
set_scenario_status -active false {S1}
hold fixing
hold time 的修复是发生在所有的scenario中的;
set_scenario_status {s2} -hold true
ICC 会自动选择 那些库中标记 optimization purpose 为hold 的最好的library cell 去完成 hold fixing;
#控制 hold fixing 的effort
set_app_options -list {clock_opt.hold.effort none|low|medium|high}
#根据需要选择不同的优化级别
最小化scan path 中的hold time 的violations
打卡 scanchain 的reorder 选项 最小化分支交叉;
set_app_options -list {opt.dft.clock_aware_scan_reorder true}
在placement 时候 那时候 reorder scan chain 是为了解congestion 的;
而在CTS 之前 此时的scanchain reorder 是为了 优化 timing 的;
CRPR (clock reconvergence(融合) pessimism remove)
是对过度悲观情况的一种剔除; 联系OCV launch path 和 capture path 的OCV 系数是不相同的 一个大于一 一个小于一 对于下面的和条路径:
为了减少 OCV的影响 ,clock trees 的创建会尽可能多的分享buffers;
移除掉由于分享时钟路径 造成的在时序计算中的过度悲观的情况 ;(对于上面这条路径来说 虽然lunch path 和 capture path 共享 U1 U2 U3 U4 但是乘的OCV 不同,造成过度悲观)
set_app_optons -anme time.remove_clock_reconvergence_pessimism -value true
在 timing report 中会多出一项来 clock reconvergence pessimism
拥塞敏感的 initial CTS (初始化CTS)
初始化的 clock tree synthesis (built_clock) 并不是 congestion aware,默认是局域 virtual routing(虚拟布线)
对于大的 复杂的设计 这可能会导致,
布线之前与布线之后 在clock skew latency logical DRC 等方面的下降;
拥塞的Hotspots
布线时的DRC 违例;
用global routing 进行拥塞的估计 以及 在拥塞已知情况下 的时钟树在 built_clock阶段的 约束的设置:
set_app_options -list {cts.compile.enable_global_route true}
# 选用global_route的布线引擎 代替virtual route,得到拥塞信息 在CCD 的时候是自动打开的, 而在CTS 时候是关闭的.
CCD current clock & data
时序优化一般只考虑data path,CCD利用useful skew技术同时优化了clock path(调节clock arrival time)。如果reg to reg延时大于clock cycle,说明由setup violation,CCD一方面优化data path,另一方便调节clock skew来修复violation。如果reg to reg延时小于clock cycle,说明data path拥有positive slack,CCD希望通过优化这样的路径去改善其他路径的时序。
local skew 优化
global skew : 比如一个时钟 ,有2万个sink,在CTS 的时候 他会找latency最长的一条路径 1.2ns 最短的一条 1.0ns 那么global skew 是200ps; 不管sink之间有没有 launch 和capture 的关系;
local skew : 就是在launch 和 capture之间的关系,计算skew, local skew 决定着两个触发器之间有没有 timing violation;
执行 timing aware的聚类 (相对于 基于位置的)
优化local skew directly for setup and hold 提名 critical pairs
能够放松可能节省时钟buffer 面积的地方的 skew target;
restricting (限制) CCD skew 的数量;
默认 CCD skew 和需要满足的时序的数量一样多;
根据需要 可以限制 CDD skew 的数量
set_app_options -name ccd.amx_preone -value 0.2
#最大的允许的一个sink的latency 的减少
set_app_options -anme ccd.max_postpone -value 0.4
#最大的latency的增加
#最大在时钟周期的10% -20% 之间
# 默认是-1000
设置限制能够影响到时序的QoR
skipping path group during CCD (跳过分组)
在时钟 latency的调整过程中 你可以配置 CCD 跳过那些属于特定组的 clock pin;
例如在CCD中 由于一些路径的latency 本来就没设好,很容易产生violation 你又不想让CCD去修,就可以把他跳过去;
或者你手动 摆好的一个critical path 时序已经是最小的,你不要CCD去都动就可以 skip掉;
数据路径的优化在这些组中仍然是有效的:
set_app_options -nameccd.skip_path_groups -value {pathgroup {scenarios}}
忽略I/O上的时序, 边缘register 的skew
可以将I/O上的timing path 加到 skip group中
一般 top 层给的i/O的约束都是比较紧的,防止到后期不能收敛,所以 I-reg的路径一般都是整个设计中最坏的路径;
很容易出现violation ,在CCD flow 工具会尽量修存在于边界寄存器的违例 这是我们不太希望的;
group_path -name MY_IN -from [get_ports In*]
set_app_options -name ccd.skip_path_groups -value {MY_IN}
clock_opt
CCD optimization & boundary register
默认 ,CCD 会skews 所有的寄存器 包括边界的寄存器;
为了避免边界寄存器上的latency adjustment (延迟调整),使用以下命令:
ccd.optimize_boundary_timing false
#这是假设在严重影响CCD 的优化潜能的时候 对所有的边界寄存器执行prevent,
#建议在十分必要的时候再使用
#相比 上一部分只是prevent 一组;
主要的端口 被用来区分边界和内部的FFs;
使用以下命令 忽略scan reset ports:
ccd.ignore_scan_reset_for_boundary_identification true
#忽略指定的端口:
set_app_options -name ccd.ignore_ports_for_boundary_identification -value {my_en en_a}
在CCD flow中优先解决hold
尽管在CCD 的优化中 是 hold Ware 的 但是 在修setup的时候 会或多或少对 hold 造成一定的影响;
经常 datapath 的优化 能有解决这些hold 的违例;
如果你想在CCD中优先解决hold问题,比如对于你的设计 fix hold 是困难的 或者你的社会是area-critical的 对于hold-buffer 面积的增加是必须要避免的,就需要在CCD的时候 优先解决hold;
ccg.hold_control_effort medium| high| ultra
# 建议仅在 hold timing critical的时候使用 ,因为他会影响setup 优化的效果
#仅仅会影响final_opto 以及 在route_opt期间的CCD优化过程;
让CCD 解决sub_critical path 次关键路径
CCD 在默认情况下 解决的是每个路径组中 最坏的路径 WNS path , 次关键路径是不会在CCD中得到优化的;
# 让CCD 优化每个路径组中 worst 300条次关键路径
ccd.enable_top_wns_optimization true
在其他的sub-critical path上 使用 targeted CCD (有目标的CCD)
上述的铁兴 只会应用在 place_opt 和clock_opt 的build_clock 阶段
traget_CCD
#CCD集中解决关键路径组
set_app_options -name ccd.target_ccd_path_groups \
-value {pathgroup_icgs pathgroup_ram1_in}
## 集中解决 critical endpoints (关键的终点节点违例) endpoints 被放在一个文件中;
set_app_options -name ccd.target_ccd_end_points_file
-value ccd_ep.txt
# 如果 你既指定了 目标组 也指定了 目标endpoint 那么CCD 只会对存在于指定组的指定的endpoints 有效;
# 建议 仅指定 timing critical path group 和 endpoints 不要冒险将所有的路径组放进去;
需要考虑的额外的设置 additional settings to consider;
# 回顾在CTS之前需要考虑的设置
# 1. 解决 一个过渡约束的设计
cts.commom.enbale_dirty_design_mode
#2. 在 CTS 之后 fix the clock tree sinks
cts.compile.fix_clock_tree_sinks
#3. 在 clock_opt 期间 提高 placement 的effort
clock_opt.place.effort
#4. 提高拥塞的解决能力
clock_opt.congestion.effort
#5. 控制是否允许 CTS 移动已经存在的门;
cts.compile.enable_cell_relocation
#6. 在多电压域的设计中 允许physical feedthroughs
经典的CTS和 CCD 的执行
# 时钟树的综合 时钟树的布线 数据路径的优化 都被以下指令执行
clock_opt
# CCD 默认是打开的 有以下选项控制
clock_opt.flow.enable_ccd
clock_opt 的四个阶段:
build_clock route_clock final_opto global_route_opt(是可选的)
在将CCD选项关闭的情况的下 clock_opt各阶段的执行情况有所不同.
build_clock: 创建 GR clock tree 执行内部时钟网络的skew的平衡
route_clock: 为时钟网络布线 更新 I/O 的延迟
final_opto : 执行数据路径的优化 让设计满足时序和DRCS的要求
同样你可以使用 -from/-to 来控制 clock_opt 执行的阶段
clock_opt -to build_clock
对应的真个clock_opt 的流程 ICC II也有对应的原子指令 贯穿整个CTS 的各个阶段;
当你有分析中间阶段的需要 的时候 可以使用原子属性
CCD flow 的执行阶段
当将CCD选项设为true;
build_clock : 创建时序驱动的 GR clock tree, 执行内部的clock balancing 提高setup/hold 的时序情况以及 DRC;
route_clock :为时钟网络布线 并更新 I/O 延迟信息;
final_opto :优化数据路径逻辑的同时优化时钟逻辑 进一步提高 setup hold 的时序情况 以及DRCs;
post_CTS : 在时钟树布线之后的优化
问题:
build_clock阶段的global_route 与route_clock阶段的detail route 之间的差别 可能会造成时钟树QoR 的下降;
时钟树的QoR 还会由于 串扰和coupling capacitance (耦合电容)的影响进一步降低;
解决方法:
synthesize_clock_tree -postroute
# 这个选项的作用就是 针对已经route的时钟树 通过插buffer buffer sizing,gate sizing 来优化变差的结果
# 只适用于 classic CTS
# 在使用CCD时 建议不要使用;
使用CCD 引擎优化 power &area
CCD引擎能够从 时钟树网络中回收power 或者area;
这种 power/area 的recover 是不会对时序的QoR产生影响的;
优化包含 repeater removal, 时钟单元以及寄存器的sizing;
在classical CTS 和CCD flow中都能被应用
在clock_opt 的最后阶段 final_opto执行,同样能够在布线后的优化中被使用,route_opt;
在power 和area 之间做出选择:
power: 需要使用精确 的SAIF 文件 去计算精确的动态功耗;
area: 在SAIF 文件不可用的时候 或者 面积是一个优化目标的时候 自动应用;
使用以下选项控制:
set_app_options -name clock_opt.flow.enable_clock_power_recovery \
-value area| power| auto | none
clock_opt
在 CCD flow中 useful skew 同时被用来优化时序和power/area
在 classical CTS flow中 useful skew 仅仅被用来优化 power/area; -> global skew/latency 会降低
默认的设置: 在CCD flow中 如果scenario 有power 的配置 那么power 的recovery是打开的, 否则就是 area recovery;
在 非CCD flow 是没有 recovery 发生的;
CCD clock power recovery: leakage dynamic or total
基于 scenario的唯一的配置 clock power recovery 会减少leakage dynamic or total power 其中的一项
set_scenario_status func.ss_125c -dynamic_power true -leakage_power true
#根据需要 改变scenario 的power status
# 为了获得更好的姐夫哦 确保你允许CTS 去 size register 以及 ICGs(会在下一单元介绍)
#如果你只打开了leakage power 那么在 clock_opt final_opto阶段是没有power recovery发生的 仅会在 route_opt阶段执行
GRO global_route_optimization 全局布线优化
这是clock_opt 4各阶段中的最后可选阶段;
优化是基于 完整的单词global route 和global route timing;
包括 setup hold delay的优化 逻辑 DRC 的解决 以及 leakage 的优化;与布线后的布线优化 route_opt 类似 附加 HFN rebuffering 高扇出网络的buffer调整;
大多数的设计是可以从 GRO 上得到预期的优化的;
GRO 在整个流程中的位置
执行了 global_route_opt之后 clock_opt 的输出是完整的全局布线的结果 随后的单词布线的流程会自动从 track routing阶段开始;
使用 CRO
默认在clock_opt 阶段 GRO 是跳过的
set_app_options -name clock_opt.flow.enable_global_route_opt \
-value true
clock_opt -from glocal_rout_opt
# 之后的 global route指令都会被跳过.包括 route_global route_auto
# 所有的 布线相关的app_options 需要在执行 GRO 之前应用
# 信号的preroute 是需要在执行GRO 之前完成的 使用 route_group 指令;
实例脚本
open_lib design.dlib
open_block placed
## CTS setup (会在之后的内容中提到 )
source clock_tree_balance.tcl
source clock_preexisting_cells.tcl
source clock_routing_rules.tcl
source clock_constraints.tcl
## 应用 CTS傲的配置设置根据需要
set_scenario_status -active true [all_scenarios]
set_scenario_status {s2 s3} -hold true
seT_app_options -list {
clock_opt.hold.effort high
time.remove_clock_recovergence_pessimism true
cts.compile.enable_global_route true
opt.common.allow_physical_feedthrough true}
## 如果是可应用的,打开CCD
set_app_options -name clock_opt.flow.enable_ccd -value true
clock_opt
对CTS结果进行分析
report_clock_qor
#后面可以跟很多选项
[-type area| balance_groups | drc_violators | latency | local_skew | power | robustness | structure | summary ]
[histogram_type latency | transition| level]
[-modes]
[-corners]
#timing report
# 报告相关路径当前的 relevant skew ,latency ,inter-clock latency 等
#包括 early/late timing derate 的影响
report_clock_timing
-type summary| transition | latency
-mode
-corner
这里的skew 是local skew 由于考虑到 derate 所以report_clock_timing 报出来的skew 有可能比qor 的大
使用 CTS GUI 分析
CTS browser
CTS schematic
clock tree levelized graph 时钟树的层级图示
clock tree latency graph per Corner 时钟树每个Corner 的延迟图示
在CTS之前 时钟网络的延迟是理想的
默认 clock_latency 是0ns
时序分析 使用理想的时钟latency的约束值 也就是 set_clock_latency 所设置的值;
在CTS之后 需要更新latency
在 clock_opt 的build_clock 阶段 应用 set_propagated_clock 到时钟源;
在route_clock 阶段会自动更新 时钟网络的 latency;
此时的latency 是当前block实际衍生的时钟网络的latency
在所有的scenario 中更新latency
默认是仅在当前的scenario 是被propagated 能够被更新 latency
如果在CTS 期间并不是所有的scenario都是active 的话 ,就需要我们手动的在CTS之后为所有的scenario跟新latency;
他也会让那些没有propagated 的时钟源propagated
clock_opt
set_scenario_status -active true [all_scenarios]
compute_clock_latency
对virtual clock 自动更新
延迟也能够为那些约束了虚拟时钟的I/O 更新latency ,前提是你定义了相关的参考时钟; 比如吧virtual clock 参考到我真实的clock上 当真实的clock 由于时钟树综合latency发生变化,我虚拟时钟也会发生变化;
#添加参考时钟
foreach_in_collection mode [all_modes] {
current_mode $mode
set_latency_adjustment_option \
-reference_clock CLK \
-clock_to_update V_clk
}
clock_opt
限制自动的latency 更新
clock_opt 默认情况下就会对latency进行更新; 其中对应的原子指令时 compute_clock_latency,发生在clock_route 阶段;
你可以使用以下选项配置 i/olatency 的更新:
set_latency_adjustment_options
默认所有的I/O 都会被更新;
使用以下指令关闭所有clock 的自动latency更新
set_latency_adjustment_options -exclude_clocks [get_clocks all_clocks]
place_opt的时候 CCD flow
CCD 默认是在place_opt阶段执行的;和clock_opt 中使用的相同 的skew 的计算引擎;
place_opt.flow.enable_ccd true (默认)
在place_opt阶段的CCD 计算skew使用的是ideal latency
应用到所有寄存器时钟引脚的clock network latency 会进行独立的调整 来提高整个路径的时序情况;
就是slack 不够往前借 往后借 来提高时序;
clock balance point delay 时钟平衡点的延迟;
CCD 应用的 时钟引脚的network latency 会影响 CTS 之前的 数据路径的时序分析和优化 但是在CTS 的时候会被忽略;
因此 CCD 的优化也会应用 在CTS使用的clock balance point delays , 使得intended useful skew 生效
不要使用 set_clock_latency -offset 来指定用户的skew,这都是有工具生成的;
-offset 仅会在place_opt阶段会用到 在CTS之后会被移除;
如果你想输出 CCD latency 使用 write_script, write_sdc 指令不会输出 CCD的latency 关于-offset的信息
报告时钟引脚的latency 以及 balance point delays
CCD 的scenario范围以及对hold 时序的优化
CCD 的优化时发生在所有的active 的scenario中 的,确保你打开了所有的你计划对CTS使用的scenarios 去避免miscorrelation;
这里建议打开红绿灯 scenarios 即使在place_opt 阶段没有进行hold的优化;
hold scenario 仅会在CCD 计算 useful skew 的时候考虑;
hold degradation 被选项 ccd.hold_control_effort;
就是 虽然在CCD 阶段不修hold 但是要把hold 的情况考虑在内 以防造成在后期fix hold 时 无法修复的问题;
控制 palce_opt 的CCD
控制amount of skewing
ccd.max_postpone 200ps
ccd.max_prepone 300ps
#在place_opt 阶段 工具会使用上述的默认值
#在clock-opt 阶段以及 route_opt 阶段 默认值 是无限大
其他 CCD 的application options 像 ccd.optimize_boundary_timing ccd.skip_path_groups 等 也会在 palce_opt 阶段被调用 所以需要在布局之前根据需要应用掉;
summary
经典的CTS 和优化流程 以及 concurrent clock_and_data flow CCD流程
报告 分析结果
控制 CTS 之后的 自动 latencygengxin
在place_opt阶段使用 CCD