OpenSTA set_false_path 匹配不到对象:假豁免排查
SDC 里明明写了 set_false_path,报告里那条路径还在,slack 依旧红着——这是约束“假豁免”:命令执行了,但对象选择器一个 pin 都没匹配上。同类事故也会出现在 set_clock_groups 的 [get_clocks ...] 上。本篇用一个两级层次小网表做三组对照,专查对象名为什么匹配不上。与 unconstrained endpoint 排查讨论的“异常约束互相作用”不同,这里约束本身没有附着到任何对象。
本文要回答的问题
set_false_path写了、脚本也跑完了,为什么路径仍出现在report_checks里?- 层次 pin 名里的分隔符、通配符、
-hierarchy到底按什么规则匹配? - 没加
-regexp却写了正则元字符会怎样?-quiet会不会把警告也藏掉? - 为什么命令打印了 Error,OpenSTA 退出码还是 0?
- 在 OpenSTA 2.0.17 上用什么命令确认例外真的生效了?
这五步的核心在第一步:先确认选择器返回了几个对象,再谈约束语义。对象计数为 0 时,后面写 -from、-through 还是 -to 都没有意义,修约束措辞不如先修名字。
一、警告与错误原文:命令失败,路径照查
实验网表是两级层次:u_a/Q → u_buf/A → u_buf/Y → u_b/D,时钟周期 0.4ns,这条寄存器间路径固有延迟 0.500ns,正常分析时 slack 为 -0.200ns(VIOLATED)。第一组故意把层次分隔符写成点号 u_b.D,OpenSTA 2.0.17 的原始输出如下。
四行输出连起来读:先是 pin 'u_b.D' not found 的 Warning,紧接着 no valid objects specified for -to 与 set_false_path command failed 两个 Error。注意这不是“只给 Warning 不报错”的老版本行为——2.0.17 会明确报错,但错误只打印在日志里,Tcl 脚本继续往下执行,整组跑完退出码仍是 CASE_EXIT bad=0。紧随其后的 report_checks 照样给出完整路径和 -0.200ns 的违规。也就是说:退出码 0、命令历史里有 set_false_path、路径仍在分析,三者同时成立,这就是假豁免最危险的地方。
二、工具与版本:以 2.0.17 实测为准
实验全部在 Docker 镜像 geek-eda:0.3-sta 内运行,sta -version 输出 OpenSTA 2.0.17(Debian 官方独立包,Ubuntu 24.04)。有两个版本相关事实必须说清,避免读者照着别的版本教程对不上输出。
第一,空对象的处理随版本变化。部分旧版本对空选择器只留一句 Warning、set_false_path 静默吞掉;2.0.17 会追加 Error 并宣布命令失败,但不中止脚本、退出码仍为 0。若选择器加了 -quiet,连第一行 not found 的 Warning 都会被抑制,只剩失败信息——日志更干净,也更难发现。
第二,例外报告命令在本版本不全。实测 2.0.17 没有 report_exceptions(调用返回 invalid command name);report_disable 存在,但只报告 case analysis 与被禁时序弧,不列出 false path。因此本篇的验收手段是约束前后同一份 report_checks 对比:被豁免路径应直接从报告消失。
三、根本原因:选择器按什么规则找对象
set_false_path 自己不找对象,它把 -from/-through/-to 后面的集合原样收下。对象一个没匹配上,例外就没有附着点。匹配规则有四个高频踩坑点。
红色是三类匹配根因,蓝色是诊断动作,橙色是修复,绿色是验收。沿这张图解释四个规则:
- 层次分隔符是斜杠。链接后层次 pin 的全名是
实例名/引脚名,两级实例就是top/u_b/D形式;点号u_b.D在 SDC 里没有特殊含义,只会被当成一个不存在的字面名字。Verilog 层次引用用点、SDC 对象名用斜杠,两者不要混。 *与?按 glob 解释。*匹配任意串、?匹配单字符。默认搜索范围是当前层次(link 后的设计顶层),本设计里get_pins {u_*/D}能一次命中u_a/D、u_b/D两个 pin(实测计数为 2);要跨层次递归搜全名,必须显式加-hierarchy,否则深层 pin 匹配不到。- 正则元字符必须配
-regexp。默认模式是 glob 不是正则。第二组对照写成get_pins {u_b./D},本意让.匹配任意字符,实际点号只是普通字符,计数为 0;加上-regexp -hierarchy后u_b.D才能命中u_b/D(.匹配斜杠)。 - port、pin、cell 是三个命名空间。顶层端口用
get_ports、实例引脚用get_pins、单元实例用get_cells。把端口名喂给get_pins,或把实例名喂给get_ports,即使拼写和网表一致也是空集合。set_clock_groups -group [get_clocks ...]同理,时钟名拼错时得到空时钟组,异步关系根本没有建立。
四、排查清单
| 步骤 | 命令 / 动作 | 空匹配时的表现 |
|---|---|---|
| 计数先行 | llength [get_pins -quiet u_b/D] | 打印 0,且 -quiet 下无 Warning |
| 不加 quiet 复看 | get_pins u_b/D | 弹出 pin '...' not found |
| 核分隔符 | 层次路径是否误用点号 | u_b.D 计数 0,u_b/D 计数 1 |
| 核搜索范围 | 深层 pin 是否漏 -hierarchy | 不带开关计数 0,带上后命中 |
| 核模式方言 | glob 还是正则 | 元字符没配 -regexp 按字面量匹配 |
| 核对象类型 | get_ports / get_pins / get_cells / get_clocks 是否用错 | 命名空间不通用,必为空 |
| 验收 | 约束前后各跑一次 report_checks | 生效后该路径消失,或 WNS 数值改善 |
第二组对照的原始日志可以把“正则漏开关”与“脚本继续跑”一次看清:MATCH_COUNT=0 先证明选择器为空,随后 Warning 与两个 Error 照常出现,而路径报告仍然给出 -0.200ns。
CASE: regex metachar without -regexp
MATCH_COUNT=0
Warning: warn_empty.sdc, 2 pin 'u_b./D' not found.
Error: no valid objects specified for -to.
Error: warn_empty.sdc, 2 set_false_path command failed.
...
-0.200 slack (VIOLATED)大型设计不适合逐条肉眼核对时,可把计数固化成 lint:对每条例外先 llength 检查集合,为 0 就 error 中止或写进检查报告。系统的约束 lint 做法见 SDC 约束 lint 方法;与时钟创建相关的约束事故见 OpenSTA no clocks found。
五、修复代码与复跑确认
把选择器改成网表真实层次名,并在约束前先计数留痕:
# fixed.sdc:斜杠分层;先取集合、确认非空再下约束
set target_pins [get_pins u_b/D]
set_false_path -to $target_pins需要正则时写全开关:get_pins -regexp -hierarchical {u_b.D};跨层次 glob 递归用 get_pins -hierarchical {*/D}。修完后不要只看退出码——三个用例退出码都是 0。复跑 fixed 用例,先看到 MATCH_COUNT=1,随后同一份 report_checks 里那条路径整段消失。
CASE: fixed hierarchical pin name
MATCH_COUNT=1
REPORT_BEGIN
No paths found.
REPORT_END
CASE_EXIT fixed=0对比数字很直接:修复前 bad 与 warn_empty 两组的 u_a → u_b 路径均在报告中,data arrival 0.500ns、required 0.300ns、slack -0.200ns(VIOLATED);修复后选择器计数 1,该路径被正确豁免,report_checks 输出 No paths found.。注意“路径消失”只对这条被豁免路径成立——若全设计突然都 No paths,反而要按 负 slack 违规排查回头查时钟是不是没建起来。
代码获取:完整网表、教学用 Liberty、三份 Tcl/SDC 与运行脚本位于 geek-doc.cn/experiments/ts-opensta-false-path-no-match,安装 OpenSTA 2.0.17 后执行 bash run.sh(或用同目录 Docker 命令)可复现 bad、warn_empty、fixed 三组对照。
实验环境
- 机器/系统:本地 Docker 容器,Ubuntu 24.04;宿主为 macOS。
- 工具版本:OpenSTA 2.0.17,Debian 官方独立二进制包(镜像 geek-eda:0.3-sta);未使用 OpenLane。
- 日期:2026-11-02。
- 完整命令:在实验目录执行
bash run.sh,依次运行bad.tcl、warn_empty.tcl、fixed.tcl,合并 stdout/stderr 并记录各组退出码。 - 实验边界:
experiment.lib仅为含 DFF/BUF 最小时序弧的教学库,0.4ns 周期专为制造可复现违规;未跑物理实现,本文数值不能外推为任何工艺的签核结论。
这一篇在知识体系里的位置
本篇处于 SDC 数据格式与生命周期 之后的故障定位层,处理“约束语法合法但对象为空”的假豁免。端点覆盖统计方法见 未约束端点审计;约束对象存在、时钟本身却没建起来的情形回到 unconstrained endpoint 排查 与 no clocks found。
总结
OpenSTA set_false_path 匹配不到对象的本质是选择器返回空集合:层次分隔符要写斜杠 u_b/D 而不是点号,*? 默认按 glob 且只搜当前层次(深层加 -hierarchy),正则元字符必须配 -regexp,port/pin/cell/clock 各有命名空间不能混用。2.0.17 对空匹配会打印 Warning 加 Error 但不中止脚本、退出码仍为 0;排查时先用 llength [get_pins -quiet ...] 计数,再用约束前后同一份 report_checks 验收——被豁免路径从报告中消失(本例 slack 由 -0.200ns VIOLATED 变为 No paths found)才算真生效。