这个章节的主要学习目标如下:
1)时钟树综合前的准备工作熟悉
2)时钟树综合的跑法
3)时钟树结果分析
4)时钟树综合后的时序优化(PostCTS的timing优化)
首先,我们按照lab的要求来打开pr.inv这个数据。
我们可以直接用我们打开数据的命令:
restoreDesign ../saved/pr.inv.dat DTMF_CHIP
打开数据后,我们要读入做时钟树综合前的一些设置,比如这个lab中的dtmf.ccopt。这个文件的内容如下(用gvim dtmf.ccopt即可打开该文件):
1 | set_ccopt_property buffer_cells [ list CLKBUFX1 CLKBUFX12 CLKBUFX16 CLKBUFX2 CLKBUFX20 CLKBUFX3 CLKBUFX4 CLKBUFX8 CLKBUFXL ] |
这两句其实就是设置工具长时钟树时可用的clock buffer和clock inverter cell list 。
很多新手肯定会有疑问,我是初学者,我哪里能知道做时钟树前要设置哪些设置,而且我压根不知道ccopt有哪些相关的property。
这里教大家一个大招,可以通过下面的命令来报告出所有ccopt相关的property。至于要设置哪些,这是慢慢积累的一个过程。刚开始只要知道设置一些常用的设置即可,等后续经验多了,自然就都会了。
CTS 中 Buffer 和 Inverter 的区别与使用场景
1. 基本概念
在 CTS(Clock Tree Synthesis,时钟树综合)阶段,工具会插入时钟 buffer 或时钟 inverter 来构建时钟树,从而满足时钟网络的驱动能力、时钟偏斜、时钟延迟和 transition 等要求。
常见脚本如下:
1 | set_ccopt_property buffer_cells [ list CLKBUFX1 CLKBUFX2 CLKBUFX4 CLKBUFX8 ... ] |
这两条命令的作用是告诉 Innovus/CCOpt:
buffer_cells:CTS 阶段允许使用哪些时钟缓冲器;inverter_cells:CTS 阶段允许使用哪些时钟反相器。
2. Buffer 和 Inverter 的逻辑区别
2.1 Buffer
Buffer 不改变信号极性,逻辑功能为:
1 | Y = A |
也就是:
1 | A = 0 → Y = 0 |
Buffer 的主要作用不是改变逻辑,而是增强驱动能力、改善 transition、分担扇出和控制时延。
2.2 Inverter
Inverter 会改变信号极性,逻辑功能为:
1 | Y = ~A |
也就是:
1 | A = 0 → Y = 1 |
如果单独插入 inverter,会导致信号反相,因此在不能改变逻辑功能的路径上需要谨慎使用。
3. 工程中 Buffer 的常见用途
Buffer 通常用于不希望改变逻辑功能,只希望改善物理或时序特性的场景。
3.1 增强驱动能力
当一个信号需要驱动很多负载时,原始驱动单元可能无法满足 transition 或 fanout 要求,此时可以插入 buffer。
1 | driver → buffer → many loads |
作用:
- 降低前级负载;
- 改善 transition;
- 减少 slew violation;
- 提高信号传播质量。
3.2 修复 Hold 违例
Hold 违例通常是数据路径太短,数据到达下一级寄存器太快。此时可以在数据路径上插入 buffer 增加延迟。
1 | Reg1/Q → buffer → Reg2/D |
作用:
- 增加 data path delay;
- 修复 hold violation。
3.3 长线中继
如果一根连线较长,RC 寄生较大,直接驱动会导致延迟和 transition 变差,可以在中间插入 buffer 作为中继。
1 | driver → long wire → buffer → long wire → load |
3.4 CTS 时钟树构建
在 CTS 中,clock buffer 是最常用的时钟树单元,用于构建多级时钟网络。
1 | clock source → CLKBUF → CLKBUF → register clock pin |
作用:
- 增强时钟驱动能力;
- 控制 clock transition;
- 平衡 clock skew;
- 控制 clock latency;
- 驱动大量寄存器 clock pin。
4. 工程中 Inverter 的常见用途
4.1 实现逻辑取反
Inverter 最直接的作用是实现信号反相,例如:
1 | reset_n → inverter → reset |
或者:
1 | enable → inverter → disable |
4.2 两个 Inverter 串联等价于 Buffer
两个 inverter 串联后,最终逻辑极性不变:
1 | A → INV → INV → Y |
因为:
1 | Y = ~~A = A |
因此在工程中,有时会使用 inverter pair 来实现类似 buffer 的作用。
使用 inverter pair 的原因可能包括:
- inverter 面积更小;
- inverter 延迟更合适;
- inverter 驱动档位更多;
- 工具优化选择更灵活;
- rise/fall transition 更容易调整。
4.3 CTS 中参与时钟树优化
在 CTS 阶段,clock inverter 也可以参与时钟树构建。工具可以追踪时钟极性,因此中间节点允许出现反相时钟,只要最终到达寄存器 clock pin 的时钟极性满足要求即可。
常见情况是成对使用 inverter:
1 | clk → CLKINV → CLKINV → clk |
这样最终时钟极性不变,但工具可以利用 inverter 的延迟、驱动和边沿特性优化时钟树。
5. CTS 中什么时候用 Buffer,什么时候用 Inverter?
在实际 CTS 中,通常不是工程师手动决定每一级使用 buffer 还是 inverter,而是由 CCOpt/CTS 工具根据目标自动选择。
工具会综合考虑:
- clock skew;
- clock latency;
- clock transition;
- fanout;
- insertion delay;
- 功耗;
- 面积;
- 布线拥塞;
- 时钟极性。
5.1 优先使用 Clock Buffer 的场景
Clock buffer 不改变时钟极性,因此是 CTS 中最直接、最安全的选择。
适合场景:
- 保持时钟极性;
- 增强时钟驱动能力;
- 驱动大扇出寄存器;
- 切分长时钟线;
- 改善 clock transition;
- 平衡不同分支 latency;
- 控制 clock skew。
示意:
1 | clk_root |
5.2 使用 Clock Inverter 的场景
Clock inverter 会改变时钟极性,因此不能随意单独使用。但在 CTS 中,工具可以合理使用 inverter 来优化时钟树。
常见场景包括:
1)两个 inverter 成对使用
1 | clk → CLKINV → CLKINV → clk |
最终极性不变,相当于 buffer,但可能在延迟、面积、功耗或 transition 上更有优势。
2)调整 rise/fall transition
Inverter 会交换上升沿和下降沿的传播特性,因此工具有时会使用 inverter 来优化时钟边沿质量。
3)中间节点允许反相
CTS 工具能够追踪 clock polarity,因此时钟树中间节点可以是反相的,只要最终到达 sink 的时钟极性正确即可。
4)特殊时钟相位需求
某些特殊单元、latch 或 clock gating 结构可能需要特定极性的时钟,此时可以通过 inverter 生成反相时钟。
6. Buffer 和 Inverter 的工程区别总结
| 对比项 | Buffer | Inverter |
|---|---|---|
| 逻辑功能 | 不改变极性 | 改变极性 |
| 表达式 | Y = A |
Y = ~A |
| 是否影响功能 | 一般不影响 | 单独使用会影响 |
| 常见用途 | 增强驱动、修 transition、修 hold、长线中继 | 逻辑取反、极性调整、成对作为 buffer |
| CTS 中使用 | 最常用,直接构建时钟树 | 可使用,但要注意极性 |
| ECO 修 hold | 常用 | 通常需要成对使用 |
| 工具优化 | 稳定直接 | 更灵活,但需管理极性 |
7. 手动 ECO 时的注意事项
在手动 ECO 中,如果只是想增加延迟或者增强驱动,通常优先插入 buffer:
1 | Reg1/Q → BUFX1 → Reg2/D |
如果使用 inverter,则需要成对插入,避免改变逻辑功能:
1 | Reg1/Q → INV → INV → Reg2/D |
否则单独插入一个 inverter 会导致逻辑反相,可能造成功能错误。
8. 一句话总结
Buffer 是不改变极性的时钟/信号中继单元,主要用于增强驱动、改善 transition、修复 hold 和构建时钟树;Inverter 会改变极性,主要用于逻辑取反,也可以在 CTS 中成对使用来辅助优化时钟树。CTS 阶段具体使用 buffer 还是 inverter,通常由工具根据 skew、latency、transition、功耗和面积自动决定。
1 | innovus 5> innovus 5> set_ccopt_property * -help |
设置好ccopt相关的设置后,我们需要基于sdc和这些ccopt property来产生clock tree spec文件。因为工具长tree会根据这个spec文件来做tree。
create_ccopt_clock_tree_spec
spec产生后,我们就可以使用下面的命令来跑时钟树综合和时钟树综合后的时序优化。
Innovus CTS 中 create_ccopt_clock_tree_spec 和 Spec 的作用
1. spec 是什么?
spec 是英文单词 specification 的缩写,中文通常翻译为:
- 规格
- 规范
- 说明
- 约束说明
- 配置说明文件
在 EDA 流程中,spec 通常指工具执行某个任务时需要遵守的规则或配置说明。
常见例子:
| 英文 | 中文含义 |
|---|---|
| design spec | 设计规格 |
| timing spec | 时序规格 |
| interface spec | 接口规格 |
| clock tree spec | 时钟树规格文件 |
2. Clock Tree Spec 是什么?
在 CTS(Clock Tree Synthesis,时钟树综合)阶段,clock tree spec 可以理解为:
时钟树综合的规则说明文件,也可以理解为 CTS 的“施工图”。
它告诉工具应该如何搭建时钟树。
Clock tree spec 中通常会包含:
- 设计中有哪些 clock;
- clock root 在哪里;
- clock sink 有哪些;
- CTS 可以使用哪些 clock buffer;
- CTS 可以使用哪些 clock inverter;
- 目标 clock skew 是多少;
- 目标 clock transition 是多少;
- 目标 clock latency 是多少;
- 是否存在 clock gating;
- 是否有特殊 clock 处理规则。
3. 为什么需要 Clock Tree Spec?
CTS 工具不能随便插入 buffer 或 inverter,它需要知道建树规则。
例如,工具需要知道:
1 | 哪些时钟需要建树? |
因此,在真正跑 CTS 之前,需要先根据 SDC 约束和 CCOpt 设置生成 clock tree spec。
可以这样理解:
1 | SDC 时序约束 |
4. create_ccopt_clock_tree_spec 是什么?
命令如下:
1 | create_ccopt_clock_tree_spec |
可以拆开理解:
1 | create 创建 |
所以它的作用是:
根据当前设计中的 SDC 约束和 CCOpt 属性设置,生成 CCOpt/CTS 使用的 clock tree spec 文件。
5. SDC 和 CCOpt Property 分别提供什么?
5.1 SDC 提供时序约束
SDC 文件中通常包含:
1 | create_clock -name clk -period 1.0 [get_ports clk] |
SDC 主要告诉工具:
- 设计中有哪些时钟;
- 时钟周期是多少;
- 输入输出延迟是多少;
- 哪些路径是假路径;
- 时序分析应该按照什么约束进行。
5.2 CCOpt Property 提供建树规则
CCOpt property 用来告诉工具 CTS 应该怎么做。
常见设置包括:
1 | set_ccopt_property buffer_cells [...] |
它们主要告诉工具:
- CTS 可以使用哪些 clock buffer;
- CTS 可以使用哪些 clock inverter;
- 目标 skew 是多少;
- 目标 transition 是多少;
- 时钟树优化目标是什么。
6. 生成 Spec 后做什么?
生成 clock tree spec 后,就可以开始跑时钟树综合。
常见命令类似:
1 | create_ccopt_clock_tree_spec |
或者有些流程会分开写:
1 | ccopt_design -cts |
具体命令会根据 Innovus 版本和脚本流程有所不同。
7. CTS 做了什么?
CTS 会根据 clock tree spec 插入 clock buffer 和 clock inverter,建立真实的时钟树。
在 Place 阶段,时钟通常还是:
1 | ideal clock |
CTS 之后,时钟变成:
1 | propagated clock |
也就是说,工具开始考虑真实的:
- clock latency;
- clock skew;
- clock transition;
- clock insertion delay。
8. 为什么 CTS 后还要做时序优化?
时钟树建立之后,时钟到达不同寄存器的时间不再完全相同,因此原来的时序情况可能发生变化。
CTS 后可能出现:
- setup 违例;
- hold 违例;
- clock gating check 违例;
- transition 违例;
- skew 不满足要求。
所以 CTS 后通常还需要进行 post-CTS optimization,用来修复时序问题。
常见优化包括:
- 修复 setup;
- 修复 hold;
- 调整 clock buffer;
- 优化 clock gating 路径;
- 改善 transition;
- 降低 clock skew。
9. 类比理解
可以把 CTS 类比成修建一条“时钟高速公路”。
1 | SDC = 告诉工具时钟周期和时序要求 |
10. 一句话总结
spec是 specification 的缩写,表示“规格/规范”。在 CTS 中,clock tree spec是时钟树综合的规则说明文件,create_ccopt_clock_tree_spec会根据 SDC 和 CCOpt property 生成该文件,后续 CTS 工具会按照这个 spec 插入 clock buffer/inverter,搭建真实时钟树,并进行 CTS 后时序优化。
利用GUI图形界面分析时钟树质量 (CTD)
Clock—-Ccopt Clock Tree Debugger
点击OK后弹出如下结果。
这里要求大家熟悉下图中所框出来的三个地方。通过这个CTD还可以来trace设计的时钟结构。
图片当中的sink是啥意思:
这里的 sink 在 CTS / clock tree 里可以理解为:
时钟树的终点,也就是 clock 最终要送到的负载点。
在数字后端里,最常见的 sink 就是:
1 | 寄存器 / 触发器的 clock pin |
比如:
1 | clk root → clock buffer → clock buffer → DFF/CLK |
这里最后的 DFF/CLK 就是一个 clock sink。
1. sink 为啥叫 sink?
sink 英文原意有“汇入点、终点、接收端”的意思。
在时钟树里:
1 | clock source / root → clock network → clock sinks |
可以理解为:
1 | 时钟源头 → 时钟树传播 → 各个寄存器时钟端 |
所以:
| 名词 | 含义 |
|---|---|
| clock source / root | 时钟源头 |
| clock tree | 时钟分发网络 |
| clock sink | 时钟终点 / 时钟负载 |
| sink pin | 接收时钟的 pin,比如 DFF 的 CK |
2. 图里“大部分 sink 落在 0.5–0.55ns”是什么意思?
你图里说:
1 | 大部分 sink 落在 0.5–0.55ns 这个区间 |
意思是:
大多数寄存器的 clock pin,从 clock root 到达该 pin 的 clock latency 大约是 0.5ns 到 0.55ns。
也就是:
1 | clock root 出发 |
这个时间就是 clock tree latency / insertion delay。
3. 举个简单例子
假设有三个寄存器:
1 | clk root |
那么:
1 | reg_A/CK 是一个 sink |
如果工具报告:
1 | reg_A/CK latency = 0.51ns |
那就说明这些 sink 的时钟到达时间都集中在 0.5ns 左右。
4. sink 分布集中说明什么?
如果大部分 sink 的 latency 都集中在一个比较窄的范围,比如:
1 | 0.50ns ~ 0.55ns |
通常说明时钟树比较均衡,clock 到达不同寄存器的时间差不大。
这个时间差就和 clock skew 有关。
简单说:
1 | latency:clock 从 root 到某个 sink 的延迟 |
例如:
1 | sink1 latency = 0.50ns |
那么这两个 sink 之间的 skew 大约就是:
1 | 0.55 - 0.50 = 0.05ns |
5. 一句话总结
sink 就是时钟树的终点,通常是寄存器的 clock pin。图里说大部分 sink 落在 0.5–0.55ns,意思是大多数寄存器的时钟到达延迟集中在这个范围,说明 clock tree 的 latency 分布比较集中。
通过这个CTD分析的一个好处是我们可以在CTD窗口任意选择一颗cell,此时layout上会同步高亮显示出这颗cell。而且还能高亮当前sink点对应的clock path走向。
除了分析时钟树质量和时钟树结构外,我们还需要关心设计的时序Timing情况。
我们可以通过timeDesign来报告出当前设计的时序。
第一个就是报告postCTS阶段的timing,因为此时我们就是做完了CTS,所以此时我们应该带上PostCTS来报timing。
第二个命令又再加了一个 -hold选项,这个代表是我们想让工具报出当前阶段的hold time情况。
【思考题】 为何这个阶段要看hold time?
优化时序方法
如果工具自己做完时钟树综合和时序优化后的timing还有较大violation,我们还可以通过命令自带的时序优化命令来做时序的优化——optDesign -postCTS -setup (-hold 代表我们希望让工具优化hold time)
这里也可以直接使用innovus的GUI界面直接打印出相关的Timing信息
Post-CTS 阶段为什么要检查 Hold Time?
1. 背景
在 Innovus 后端流程中,完成 CTS(Clock Tree Synthesis,时钟树综合)之后,需要重新报告 timing。
常见命令包括:
1 | report_timing -postCTS |
其中:
-postCTS:表示报告 CTS 之后的时序情况;-hold:表示报告 hold timing,也就是保持时间检查。
2. CTS 前后的 Clock 状态区别
CTS 之前:Ideal Clock
在 Place 阶段,时钟树还没有真正建立,clock 通常是 ideal clock。
1 | clock latency ≈ 0 |
此时工具假设时钟几乎同时到达所有寄存器,因此 hold 分析不够真实,主要关注 setup。
CTS 之后:Propagated Clock
完成 CTS 后,工具已经插入 clock buffer / clock inverter,建立了真实时钟树。
此时 clock 变成 propagated clock,会产生真实的:
1 | clock latency |
不同寄存器的 clock pin 收到时钟的时间不再完全相同,因此需要重新检查 setup 和 hold。
3. 为什么 Post-CTS 要重点看 Hold?
Hold 检查关注的是:
数据不能太早到达下一级寄存器。
如果数据路径太短,或者 CTS 后 capture clock 比 launch clock 晚很多,就可能导致数据过早到达,从而产生 hold violation。
例如:
1 | Reg1/Q → 很短组合逻辑 → Reg2/D |
CTS 前可能认为两个寄存器同时收到时钟:
1 | Reg1 clock latency ≈ 0 |
CTS 后可能变成:
1 | Reg1 clock latency = 0.20 ns |
此时 capture clock 比 launch clock 晚,短数据路径就可能出现 hold 违例。
4. 为什么 Place 阶段不重点看 Hold,而 CTS 后要看?
| 阶段 | Clock 状态 | 主要关注 | 原因 |
|---|---|---|---|
| Place 阶段 | ideal clock | setup | 时钟树未建立,主要优化长数据路径 |
| Post-CTS 阶段 | propagated clock | setup + hold | 真实 clock latency 和 skew 已出现 |
| Post-Route 阶段 | propagated clock + 真实 RC | setup + hold | 时序更接近 signoff 结果 |
Place 阶段不重点看 hold,是因为 clock tree 还没有建立,hold 结果容易失真。
CTS 之后必须看 hold,是因为真实 clock skew 已经出现,短路径问题可能被暴露出来。
5. optDesign -postCTS -setup 的作用
1 | optDesign -postCTS -setup |
该命令用于 CTS 后的 setup 优化。
Setup 违例通常说明数据路径太慢,工具可能通过以下方式优化:
- 换更大驱动能力的 cell;
- 优化长组合逻辑路径;
- 调整 buffer;
- 改善 transition;
- 局部移动 cell。
6. optDesign -postCTS -hold 的作用
1 | optDesign -postCTS -hold |
该命令用于 CTS 后的 hold 优化。
Hold 违例通常说明数据路径太快,常见修复方法是:
- 插入 delay buffer;
- 增加短路径延迟;
- 调整 buffer / inverter;
- 优化 clock skew;
- 修复过短的数据路径。
简单理解:
1 | setup 违例:数据来得太晚,需要让数据路径更快 |
7. 思考题答案整理
CTS 之前,时钟树尚未真实建立,clock 仍为 ideal clock,工具无法准确获得不同寄存器之间的 clock latency 和 clock skew,因此 hold 分析参考意义有限。
完成 CTS 后,工具已经插入 clock buffer / inverter 并生成真实时钟树,clock 由 ideal clock 变为 propagated clock。此时不同 clock sink 的时钟到达时间产生差异,真实 clock skew 和 insertion delay 开始影响寄存器之间的时序关系。
Hold 检查对 clock skew 和最小数据路径延迟非常敏感。CTS 后,一些在 ideal clock 下不明显的短路径问题可能暴露出来,因此 postCTS 阶段需要报告 hold timing,检查是否存在数据过早到达导致的 hold violation。若存在 hold 违例,可以使用 optDesign -postCTS -hold 进行优化,通过插入 buffer、增加短路径延迟等方式修复 hold 问题。
8. 一句话总结
CTS 后时钟树已经真实存在,clock latency 和 clock skew 会影响寄存器之间的数据保持时间,因此 postCTS 阶段必须开始检查并修复 hold violation。
可以使用下面的ECO直接对CTS之后的setup和hold违例进行修复
ECO配置的参数如下: