OpenSTA 时钟门控检查流程:set_clock_gating_check 与 gating 报告怎么读
更新时间:2026-11-04。做 静态时序分析是什么 时,绝大多数路径都是触发器到触发器:起点是一个 FF 的 Q,终点是另一个 FF 的 D,检查沿是同一个时钟沿。门控时钟路径是少数派:终点不是数据引脚 D,而是与门(或 ICG 单元)的使能引脚,检查沿也错了半拍。本篇的 OpenSTA 时钟门控检查流程,就把这条特殊路径在 OpenSTA 2.0.17 里从头跑通。检查窗口为什么长这样的原理背景见 时钟门控时序检查,本篇只讲工具怎么操作、报告怎么读。
本文要回答的问题
- 门控时钟在网表里长什么样,OpenSTA 凭什么把一条路径认成 gating check 而不是普通 reg2reg?
set_clock_gating_check在 2.0.17 里真实支持哪些选项,不加它就没有检查了吗?report_checks输出里**clock_gating_default**路径组、gating-check endpoint、下降沿捕获分别怎么读?- 使能信号 EN 路径太短或太长时,setup/hold 违例各自长什么样,怎么从报告里定位?
这张卡是全篇的结论先行。注意第三栏:在周期 2.0ns、EN 只经过一级 0.20ns 缓冲的标称设计里,门控 setup 充裕(+1.55),门控 hold 却是 −0.70 违例——不是设计写错了,而是门控 hold 要求 EN 的到达时间晚于时钟下降沿,短路径天然吃亏,这与普通 hold「数据别到太早」的直觉方向一致但参考沿完全不同。
一、这一步在流程里的位置
时钟门控检查发生在常规 STA 已经能跑之后:库、网表、create_clock 都就绪了,你需要额外确认时钟树穿过了哪些组合单元、这些单元的使能端由谁驱动。上游是带门控结构的网表和 SDC;下游是 **clock_gating_default** 组的 setup/hold 报告与修违例动作。
读图抓住一个关键结构:clk 不是直接接在 u_dff 的 C 上,而是先进入 AND2 的 A 端、与 EN 相与之后才变成 gclk。OpenSTA 发现一条时钟网络穿过组合单元、该单元还有别的数据输入(B 端),就把 B 端自动识别为门控使能端,对它建一条 gating check 路径。真实芯片里 AND2 通常换成 ICG 单元(低电平透明锁存器加与门),结构等价,库单元名不同。原理层面的锁存器窗口解释见 时钟门控时序检查,普通单角 STA 流程见 OpenSTA 第一份时序报告。
二、命令逐段解读:真机 help 为准
先在容器里用 sta -no_init 确认真机语法,2.0.17 的 help 原文只有一行选项表:
set_clock_gating_check
[-setup setup_time] [-hold hold_time] [-rise] [-fall] [-low] [-high] [objects]完整脚本 case_b_check.tcl 的核心只有五行:
read_liberty teaching.lib
read_verilog top.v
link_design top
create_clock -name clk -period 2.0 [get_ports clk]
set_clock_gating_check -setup 0.10 -hold 0.05 [get_pins u_gate/B]objects 是门控单元的使能引脚(本例 u_gate/B),也可以给一个 pin 集合批量约束;它不像 create_clock 那样带时钟参数,检查所用时钟由工具从门控单元的时钟输入端自动追踪。-setup/-hold 后面直接跟时间值(ns,跟随库的 time_unit),含义是 ICG 单元库里规定的使能建立/保持要求——产线流程里这两个数来自 ICG liberty,教学库里没有 ICG,才手工补上。-rise/-fall 选择检查 EN 的哪个跳变沿;-high/-low 选择门控有效电平,默认按单元功能推断(AND 功能推断为 active high)。实测对同一个 AND 单元加 -low 后,报告终点从 rising clock gating-check end-point 变成 falling,要求时间从上升沿 2.0ns 改落到下降沿 1.0ns——它是真实生效的选项,不是摆设。
| 选项 | 作用 | 不用会怎样 |
|---|---|---|
objects(使能 pin) | 指定门控检查施加对象 | 不给对象命令不生效;但结构推断的检查仍在(见第四节案例 A) |
-setup t | 使能端建立时间要求 | 用推断默认值 0.00 |
-hold t | 使能端保持时间要求 | 用推断默认值 0.00 |
-rise/-fall | 限定 EN 跳变方向 | 两个方向都检查 |
-high/-low | 门控有效电平 | 按单元逻辑功能自动推断 |
报告侧仍用 report_checks,真机 help 中与本篇相关的是 -group_count path_count(每个路径组各报最差 N 条)和 -path_group group_name(只看某个组)。门控路径不属于任何时钟名分组,而是落在固定组 **clock_gating_default**,所以只查门控违例最省事的写法是 report_checks -path_delay min_max -path_group {**clock_gating_default**}。想看全芯片按组归类的最差路径,用 report_checks -group_count 1,gating 组与 clk 组会分段各出一条。
三、输入输出文件
吃三类输入。一是 liberty:teaching.lib 是自写教学库,含 BUF_X1(0.20ns)、BUF_D1(1.60ns,用来故意拉长 EN 路径)、AND2_X1(0.10ns)和 DFF_X1(CLK→Q 0.15ns,setup 0.10、hold 0.05),标量延时,不对应任何真实工艺,产线请替换为 PDK 签核库;库结构与阈值写法复用自多角实验的 ss.lib。二是网表 top.v:EN 触发器 u_enff 的 Q 经一级 BUF 接到 AND2 的 B 端,clk 接 A 端,AND2 输出 gclk 驱动 u_dff。三是 SDC 约束:2.0ns 时钟加输入延时,再加可选的 set_clock_gating_check。
输出是纯文本报告。门控路径的报告头有三个识别标志,缺一不可:
Startpoint: u_enff (rising edge-triggered flip-flop clocked by clk)
Endpoint: u_gate (rising clock gating-check end-point clocked by clk)
Path Group: **clock_gating_default**起点仍是普通触发器,但终点写的是单元 u_gate 而不是某个数据引脚,并明确标注 clock gating-check end-point;路径组固定是 **clock_gating_default**。正文里 setup 检查的捕获沿是下一个时钟上升沿、扣减行写作 clock gating setup time;hold 检查的捕获沿是同一周期的下降沿(报告里 clock clk (fall edge) 时间 1.00ns),扣减行写作 clock gating hold time。这两个名字是它与普通路径 library setup/hold time 的肉眼区别。字段逐行读法与普通报告一致,见 OpenSTA report_checks 报告解读。
四、常见错与检查点
| 现象 | 先查什么 | 纠正 |
|---|---|---|
| 报告里根本没有 gating 路径 | clk 是否直接接了 FF,没穿过任何组合门;门控单元的库功能是否正确 | 确认网表存在「时钟穿与门」结构;AND2 的 function 必须能被解析 |
| 加了命令还看不到路径 | 对象是否真是使能 pin;起点是否有受约束的发送寄存器 | 用 [get_pins 单元/使能脚];EN 起点接时钟或给 set_input_delay |
| gating 组消失、clk 变成一条 unconstrained 数据路径 | 时钟是否被当成数据穿过与门 | 检查时钟定义点与 set_propagated_clock,必要时对 gclk 用 create_generated_clock 显式声明 |
| hold 常年违例、修不动 | EN 路径是否太短(直接来自邻位 FF) | 真实 ICG 靠低电平透明锁存器吸收,不要硬插延时;先确认库模型是否含锁存器 |
一个必须亲眼验证的反直觉事实:不加 set_clock_gating_check,门控检查照样存在。案例 A 只写时钟与输入延时,报告里 gating 组照常出现,只是扣减行是 clock gating setup/hold time 0.00——检查弧是工具从网表结构推断出来的,SDC 命令的作用是把库规定的非零窗口值覆盖上去。所以「我没写约束所以门控没问题」是错误推理;反过来,案例 B 写入 0.10/0.05 后,setup slack 从 +1.65 变 +1.55、hold 从 −0.65 变 −0.70,数字严格跟随命令变化,这是确认约束生效的机械方法。
五、真实跑一遍:三组对照与违例读数
案例 B(标称 EN 路径,写入 0.10/0.05 检查值)的门控 setup 报告如下:
读这张报告抓两边:EN 自 u_enff 的 C 沿出发,CLK→Q 0.15 加缓冲 0.20,0.35ns 到达 u_gate/B;要求侧是下一个上升沿 2.00ns 扣掉 gating setup 0.10,等于 1.90ns;slack 1.90−0.35 = +1.55,MET。同一份脚本的 hold 报告中,要求侧改用下降沿 1.00ns 加 hold 0.05 = 1.05ns,而 EN 0.35ns 就到了,slack −0.70 VIOLATED——短 EN 路径撞上的是门控 hold,这是 ICG 单元内置锁存器要解决的典型场景,而不是靠加缓冲。
把 EN 路径换成两级 1.60ns 慢缓冲(top_slow.v,到达 3.55ns),违例形态整个翻转:
EN 3.55ns 才到,远超 2.0ns 周期,setup slack = 1.90−3.55 = −1.65 VIOLATED(使能来得太晚,门该开时没开);同一个迟到在 hold 侧反而让 EN 稳稳晚于下降沿,slack +2.50 MET。这组对照说明门控 setup/hold 是一对方向相反的约束,修违例要先看 **clock_gating_default** 组里违例的是 max 还是 min、终点沿是 rise 还是 fall,再决定动 EN 路径延时还是检查模型,不能照搬 reg2reg 的修法。多角环境下同样的命令逐角生效,做法见 OpenSTA 多角分析流程。
实验环境
- 机器/系统:本地 Docker 容器,Ubuntu 24.04;宿主为 macOS(Apple Silicon)。
- 工具版本:
sta -version输出OpenSTA 2.0.17(镜像 geek-eda:0.4-flow)。 - 日期:2026-11-04。
- 完整命令:
docker run --rm -v "$PWD":/work -w /work geek-eda:0.4-flow bash run.sh,依次执行 help 打印与 case_a_nocmd / case_b_check / case_c_slow 三个脚本(等价于make run)。 - 实验边界:liberty 为教学用最小库,标量延时,全部数值只用于演示检查机制,不能外推为任何工艺的签核结论。
代码获取
教学库、两份网表与三组对照脚本位于 geek-doc.cn/experiments/flow-opensta-clock-gating-check,克隆后进入该目录执行 make run 即可在 geek-eda:0.4-flow 容器中复现全篇报告;把 top.v 换成 top_slow.v 对照只需改脚本里的 read_verilog 行。
这一篇在知识体系里的位置
本篇讲 OpenSTA 里门控检查这一步怎么操作:先补检查窗口的原理与 active high/low 语义,读 时钟门控时序检查;报告字段的通用读法,读 OpenSTA report_checks 报告解读;要把同一套检查放到多个工艺角下签核,读 OpenSTA 多角分析流程;门控在时钟树综合阶段如何被特殊对待,读 CTS 的门控感知时钟树。
总结
OpenSTA 时钟门控检查流程的要点是:只要时钟在网表里穿过与门或 ICG 单元,工具就自动对使能引脚建立 gating check,路径固定落在 **clock_gating_default** 组、终点标注 clock gating-check end-point,无需任何 SDC 也会以 0.00 窗口值运行;set_clock_gating_check [-setup] [-hold] [-rise] [-fall] [-high] [-low] <使能 pin> 的作用是用库规定的真实窗口覆盖推断值,选项均经 2.0.17 真机 help 验证。读报告时抓住两条特殊沿:setup 对下一个上升沿、hold 对同一周期下降沿。最小网表的三组真机对照显示:短 EN 路径(0.35ns)hold −0.70 违例而 setup +1.55 充裕,长 EN 路径(3.55ns)翻转为 setup −1.65 违例、hold +2.50 满足,修违例前必须先分清 max/min 与捕获沿,这正是它区别于普通 reg2reg 路径的全部原因。