OpenSTA 多角分析流程:define_corners、read_liberty -corner 与逐角 report_checks
更新时间:2026-11-03。单角时序分析只回答「在一种 PVT 条件下时序过不过」,而签核要回答的是「所有工艺、电压、温度条件下过不过」。静态时序分析是什么 里说的慢角做 setup、快角做 hold,落到 OpenSTA 的命令行就是本篇的 OpenSTA 多角分析流程。全部数字来自 OpenSTA 2.0.17 对三档自写最小库的真实运行。
本文要回答的问题
- 多角(multi-corner)分析在整条 STA 流程里处于哪一步,输入输出各是什么?
- OpenSTA 2.0.17 里用哪些 Tcl 命令定义角、把库绑到角、按角出报告?
- 为什么 setup 要看慢角(ss)、hold 要看快角(ff),只跑一个 tt 角会漏掉什么?
- 定义了角却忘记给它读库、角名拼错、读库时漏
-corner,分别会发生什么? report_checks不带-corner时到底报的是哪个角?
这张卡是全篇的结论先行:同一条寄存器路径,门越慢数据到得越晚,setup 预算被吃掉;门越快数据到得越早,反而可能比捕获沿要求的保持时间还早到,hold 被破坏。三个角的数值来自同一份网表、同一份 SDC,唯一的变量是读进来的库——这正是多角流程要机械化保证的事情。
一、这一步在流程里的位置
多角分析发生在单角流程已经跑通之后:网表链接、时钟约束都没问题了,再把「一个库」换成「一组按角组织的库」,把「一份报告」换成「每个角一份、最后取最差」。它的上游是三档 liberty(ss/tt/ff)、一份网表、一份 SDC;下游是按角汇总的签核结论。
读图抓住一条主线:三个库不是三选一,而是同时进 STA 内核,同一条路径被算三遍。产线流程里还要再叠 RC 角(cworst/cbest)与多个工作模式,组成 MMMC 场景,那套方法论见 MMMC 场景定义与建立 与 PVT 与 RC 角的配对规则;本篇只把 OpenSTA 这一层的命令走通。教学库只有 DFF_P 与 BUF_X1 两个单元、标量延时,不对应任何真实工艺,产线请替换为 PDK 签核库。
二、命令逐段解读:从定义角到逐角报告
完整脚本 multi.tcl 只有九行:
define_corners ss tt ff
read_liberty -corner ss ss.lib
read_liberty -corner tt tt.lib
read_liberty -corner ff ff.lib
read_verilog top.v
link_design top
create_clock -name clk -period 1.2 [get_ports clk]
report_checks -corner ss -path_delay max
report_checks -corner ff -path_delay min第一段声明角、绑库。define_corners ss tt ff 一次声明三个工艺角,名字是自定义标识符,后续命令靠它引用,必须先定义后使用。read_liberty -corner ss ss.lib 把库读进来并绑定到指定角——多角模式下这个旗标是强制的,漏了会直接报错(见第四节)。三份库里单元名必须一一对应(本篇都叫 DFF_P、BUF_X1),区别只在延时数值:ss 档 CLK→Q 0.40ns、BUF 0.90ns;tt 档 0.20/0.30;ff 档 0.05/0.03。
第二段是与单角完全相同的固定动作:read_verilog + link_design 只做一次,网表在三个角间共享;create_clock 定义的时钟约束也只写一次、自动对所有角生效,不需要(也不应该)按角重复约束。
第三段按角出报告。report_checks -corner ss -path_delay max 在 ss 角下做 setup 检查(max = 取最大延时路径),-corner ff -path_delay min 在 ff 角下做 hold 检查(min)。报告头会多出一行 Corner: ss,标明数字来自哪个角的库。本篇实验脚本用 foreach corner {ss tt ff} 循环,把每个角的 max/min 各出一份。
| 命令/选项 | 作用 | 不用会怎样 |
|---|---|---|
define_corners | 声明工艺角集合 | 后续 -corner 全部无法引用,STA 退回单角 |
read_liberty -corner c f.lib | 把库绑到角 c | 多角模式下漏 -corner 直接报错中止 |
-min/-max(read_liberty) | 一个角内再分快/慢两套库(OCV 式 setup/hold 分账) | setup 与 hold 共用同一套延时,本篇即此简化情形 |
report_checks -corner c | 只出角 c 的报告 | 不带时 OpenSTA 自动在所有角里取最差角(见第五节实测) |
-path_delay max/min | setup/hold 切换 | 默认只出 max,hold 漏检 |
关于老资料里常见的 set_operating_conditions:它在 2.0.17 仍然存在,配合 -analysis_type bc_wc 在单个库内部按 operating_conditions 表项选标称条件,适合单库多工况;而 create_operating_conditions 在 2.0.17 中不是可用命令(实测返回 no commands match)。多库签角的主流写法就是上面的 define_corners + read_liberty -corner,本篇全部采用这一套。
三、输入输出文件
输入分三类。三档 liberty 结构完全相同,这里只摘 ss 档的两个关键数值块,ff/tt 只是数字不同:
timing() {
related_pin : "C";
timing_type : setup_rising;
rise_constraint(scalar) { values("0.15"); }
}
timing() {
related_pin : "C";
timing_type : rising_edge;
cell_rise(scalar) { values("0.40"); }
}网表 top.v 是两级 DFF 中间插一级 BUF 的 9 行结构(u_a/Q → BUF_X1 → u_b/D),三个角共用同一份。SDC 只有一条 1.2ns 周期时钟。输出是六份文本报告(三角 × setup/hold)加一份不带角标的全角最差报告;每份报告比单角报告只多一行角标,字段读法与 OpenSTA report_checks 报告解读 完全一致,不重复讲。
四、常见错与检查点
| 现象 | 先查什么 | 纠正 |
|---|---|---|
| tt 角全 MET,片上却偶发发不过 | 是否只签了典型角 | setup 必须加跑 ss 慢角,hold 必须加跑 ff 快角 |
报告头没有 Corner: 行 | 是否在单角模式 | 先 define_corners,读库带 -corner |
| 两个角的 slack 数字一模一样 | 角是否真的各自绑了库 | 见下方「静默回退」反例,逐角核对报告头与延时 |
-corner 报不是角名 | 是否拼写/未 define | 角名严格照抄 define_corners 清单 |
两个必须亲眼见过的报错。多角模式一旦开启,裸读库会被拒绝,错误信息是 -corner keyword required with multi-corner analysis——它防止你把一个库误挂到所有角;引用未定义角名则报 ff_x is not the name of process corner。两个错误都会让 sta 以非零状态中止,不会产生误导性报告。
真正危险的是不报错的坑:角定义了、也出了 Corner: ff 的报告,但忘了 read_liberty -corner ff ff.lib。实测此时 OpenSTA 静默借用别的角的库数据,报告头照样写 ff,数字却是 ss 的 0.40/0.90——一份「ff 角」报告长着 ss 的脸,比报错可怕得多。检查方法很机械:跑完先核对每角报告头后第一行数据路径延时,应当随角变化(本篇 1.30 / 0.50 / 0.08),三个角同数必有一个角没绑上库。
五、真实跑一遍:三角六份报告与最差角
时钟周期固定 1.2ns,先看 ss 慢角的 setup 报告:
ss 角下数据路径 CLK→Q 0.400 加 BUF 0.900,到达时间 1.300ns,而要求时间只有 1.050ns(1.2ns 周期扣 0.15ns setup),slack −0.250,VIOLATED。这是六个报告里最差的 setup。换到 ff 快角看 hold:
ff 角同一条路径只要 0.080ns 数据就到了捕获触发器 D 端,而库的 hold 要求 0.120ns,数据比同一捕获沿要求的保持窗口还早退,slack −0.040,VIOLATED。这是六个报告里最差的 hold,且与 ss 的 setup 违例出现在两个不同的角——这就是不能只签一个角的全部理由。tt 角 setup +0.600、hold +0.450 双 MET,正是「只跑典型角一切正常」的假象。
最后回答一个实操问题:report_checks 不带 -corner 报哪个角?实测它自动遍历全部角取最差:max 检查落在 ss(报告头 Corner: ss,slack −0.250),min 检查落在 ff(Corner: ff,slack −0.040)。做回归判退时可以直接用无角标命令拿全局最差,但签核留档仍要逐角报告齐全。另外与单角相同:路径 VIOLATED 时 sta 退出码仍是 0(log 中 MULTI_EXIT=0),判定必须读 slack 数字,负 slack 的含义见 OpenSTA slack 负裕量 VIOLATED 解读。
实验环境
- 机器/系统:本地 Docker 容器,Ubuntu 24.04;宿主为 macOS(Apple Silicon)。
- 工具版本:
sta -version输出2.0.17(镜像 geek-eda:0.3-sta,Debian 独立二进制包)。 - 日期:2026-11-03。
- 完整命令:
docker run --rm -v "$PWD":/work -w /work geek-eda:0.3-sta bash run.sh,依次执行multi.tcl与三个反例脚本(等价于make run)。 - 实验边界:三份 liberty 均为教学用最小库,两个单元、标量延时,数值只用于演示角间差异,不能外推为任何工艺的签核结论。
代码获取
三份角库、网表、多角脚本与三个反例脚本位于 geek-doc.cn/experiments/flow-opensta-multi-corner,克隆后进入该目录执行 make run 即可在 geek-eda:0.3-sta 容器中复现三角六份报告,本机装有 OpenSTA 时也可用 STA_BIN=sta bash run.sh 直接运行;修改库数值可用 make libs 重新生成。
这一篇在知识体系里的位置
本篇讲「多个工艺角怎么在 OpenSTA 里组织起来」:想先补单角流程,读 OpenSTA 建时钟与第一份时序报告 与 OpenSTA setup 检查原理实操;报告字段的逐行读法,读同簇的 OpenSTA report_checks 报告解读;要把角的概念扩展到 RC 角与模式组合,读 MMMC 场景定义与建立 与 PVT 与 RC 角配对。
总结
OpenSTA 多角分析流程的骨架是三步:define_corners ss tt ff 声明角集合,read_liberty -corner 把每档库强制绑定到对应角(多角模式下该旗标不可省),网表与时钟只读一次、约束对角全局生效,再用 report_checks -corner <角> -path_delay max/min 逐角出 setup/hold 报告。三档最小库的真实运行给出了签核铁律的数字证据:同一条路径在 ss 慢角 setup −0.250ns 违例、在 ff 快角 hold −0.040ns 违例,tt 角双 MET,两类违例分别藏在相反的角里;report_checks 不带角标会自动取全角最差(max 落 ss、min 落 ff)。最危险的坑不报错:角定义了却漏读库时,报告会顶着该角的角标静默借用别角数字,必须逐角核对数据路径延时是否随角变化;时序违例时退出码仍为 0,判定永远以 slack 数字为准。