OpenSTA set_input_delay 时钟引用错误:clock not found 三种触发排查
set_input_delay 1.0 -clock clk [get_ports d] 写完,脚本退出码是 0,report_checks 却没有输入路径——这是 OpenSTA 新手最容易误判的一类约束事故:-clock 后面的名字必须先由 create_clock 定义成时钟对象,名字对不上时工具只发一条 Warning,约束随即被静默丢弃。本篇用同一个最小设计实跑三种触发(忘建时钟、名字拼错或写成层次名、时钟建在错误端口),给出警告原文差异和修复验收。与 OpenSTA no clocks found:create_clock 缺失与端口名写错排查 相比,那篇查“时钟是否附着到端口”,本篇专查“-clock 引用能否解析到时钟对象”。
本文要回答的问题
set_input_delay -clock clk报clock arg 'clk' clock not found时,约束到底有没有生效?- 忘建时钟、时钟名拼错、把层次名
top/clk当时钟名,三种写法的警告有区别吗? - 为什么时钟对象存在、甚至
report_checks里已经有 slack (MET),输入路径仍可能是假的? - 修复后应该在报告里看到哪一行,才算输入延迟真正参与了时序检查?
这张流程卡对应全篇的排查主线:警告只是入口,report_clock_properties 列出的时钟名字与附着端口才是分诊依据;终验不看退出码,而看输入路径报告里有没有 input external delay 这一行。
一、完整报错原文:三种触发,两种措辞
实验设计只有一个 DFF 加一级输出缓冲,真实端口是 clk、d、q,OpenSTA 版本 2.0.17。第一组完全不建时钟,直接写输入、输出延迟。下面终端卡摘自真实运行日志,包含警告、未约束端点和空时钟表。
第 2、3 行两条警告一一对应 no_clock.sdc 的两条约束,措辞是 clock arg 'clk' clock not found——OpenSTA 找不到名为 clk 的时钟对象,于是把整条 set_input_delay 跳过,而不是中止脚本。随后的连锁反应都在卡里:clk 被当成“缺少 set_input_delay 的普通输入口”、u_stage/C unclocked、q 与 u_stage/D 两个未约束端点,时钟表只有表头,最后 No paths found,但 CASE_EXIT no_clock=0。
第二种触发是时钟建了、名字对不上,或者想当然地写成层次名。typo_hier.sdc 把时钟命名为 clck,引用处却写 clk,另有一行写成 top/clk:
CASE: typo_hier
Warning: typo_hier.sdc, 3 clock arg 'clk' clock not found.
Warning: typo_hier.sdc, 4 clock arg 'top/clk' clock not found.
Warning: typo_hier.sdc, 5 clock arg 'clk' clock not found.
Warning: There are 2 unconstrained endpoints.
q
u_stage/D
Clock Period Waveform
----------------------------------------------------
clck 10.00 0.00 5.00
No paths found.三条警告措辞完全相同,只是行号和引号内的名字不同——-clock 接受的是时钟对象名,不是引脚层次路径,写 top/clk 与拼错一样无法解析。注意这组时钟表里确实有一个 10ns 时钟 clck,寄存器也不再报 unclocked,但输入、输出约束引用的是不存在的 clk,端点 q、u_stage/D 依旧未约束。“有一个时钟对象”不等于“你的延迟约束挂上了它”。
第三种触发最隐蔽:时钟名字正好叫 clk,却建在了数据端口 d 上。这时警告换了措辞:
CASE: wrong_port
Warning: wrong_port.sdc, 3 set_input_delay relative to a clock defined on the same port/pin not allowed.
Warning: There is 1 input port missing set_input_delay.
clk
Warning: There is 1 unclocked register/latch pin.
u_stage/C
Warning: There are 2 unconstrained endpoints.
q
u_stage/D
clk 10.00 0.00 5.00
Startpoint: u_stage (rising edge-triggered flip-flop)
Endpoint: q (output port clocked by clk)relative to a clock defined on the same port/pin not allowed 的含义是:输入延迟不能相对定义在同一端口上的时钟。输入延迟被拒绝后,真正的时钟端口 clk 反而被列为“缺少 set_input_delay 的输入口”,DFF 的 u_stage/C 仍然 unclocked。更迷惑的是这组 report_checks 居然给出一条路径、slack (MET) 8.500——但起点描述是不带 clocked by 的寄存器,输出端只挂着那个建错位置的时钟名。这样的 MET 不能作为输入约束生效的证据。
二、工具与版本
全部实验在 Docker 镜像 geek-eda:0.3-sta 内完成:宿主为 macOS,容器是 Ubuntu 24.04,OpenSTA 为 Debian 官方独立包 2.0.17。设计是教学用的最小时序库 experiment.lib(只含 DFF_P 与 BUF_X1 两个单元的时序弧)加一个 DFF 顶层,四个用例各自独立启动一次 sta 进程,互不污染。文中每条警告、每个 slack 数值都来自 bash run.sh 的真实输出,未做改写。
三、根本原因:-clock 按名字解析,解析失败只警告
SDC 里 set_input_delay 的语义是“指定输入端口上的数据,相对某个时钟边沿提前多少时间到达”。因此 -clock 参数解析的是时钟对象的名字,而时钟对象只有执行 create_clock 才会诞生。解析分三步:按名字查时钟对象 → 没有则发 Warning 并丢弃整条约束 → 脚本继续执行。这解释了三个现象:
- 忘建时钟时,
clk在时钟表里根本不存在,警告后约束消失,退出码仍为 0; - 名字拼错或写层次名时,按字符串精确匹配,
clk、clck、top/clk是三个互不相同的名字,警告措辞不变; - 时钟建在错端口上时,对象名虽然能匹配,但 SDC 语义禁止“输入延迟相对同端口时钟”,于是换成另一条警告并拒绝约束。
读图抓住颜色分工:红色是失效现象,蓝色两步是分诊动作(先列对象、再对名字与端口),橙色按两类根因分开修复,绿色是唯一验收点。分叉的依据正是第一节两种警告措辞:看到 clock not found 走命名分支,看到 same port not allowed 走端口分支。
四、排查清单
| 检查项 | 忘建时钟 | 名字拼错/层次名 | 时钟建在错端口 |
|---|---|---|---|
| 警告原文 | clock arg 'clk' clock not found | 同左,名字为 clk/top/clk | clock defined on the same port/pin not allowed |
| 时钟属性表 | 空 | 有时钟,但名字是 clck | 有 clk,附着端口却是 d |
| unclocked 寄存器 | u_stage/C | 无(时钟恰好附着对了端口) | u_stage/C |
| 未约束端点 | q、u_stage/D | q、u_stage/D | q、u_stage/D |
| report_checks | No paths found | No paths found | 有路径且 MET,但起点无 clocked by |
| 修复动作 | 补 create_clock | 统一时钟名,勿写层次路径 | 把时钟改建到 clk 端口 |
操作顺序固定为四步:第一,通读 SDC 加载阶段的 Warning,不允许存“找不到时钟”类警告;第二,report_clock_properties 核对每个时钟的名字、周期;第三,check_setup -verbose 确认无 unclocked 寄存器与未约束端点;第四,才看 report_checks 的 slack。更大设计的端点覆盖统计可以配合 OpenSTA no clocks found 端点审计方法,约束写完后的系统化 lint 见 SDC 约束 lint:从警告到签核前检查。
五、修复代码与复跑确认
修复只改 SDC:时钟必须建在真实时钟端口 clk 上,名字与 -clock 引用完全一致,不写层次路径:
create_clock -name clk -period 10.0 [get_ports clk]
set_input_delay 1.0 -clock clk [get_ports d]
set_output_delay 1.0 -clock clk [get_ports q]复跑后 check_setup -verbose 不再输出任何警告,时钟表为 clk 10.00 0.00 5.00。专门报告输入路径(-from d -to u_stage/D)得到:
Startpoint: d (input port clocked by clk)
Endpoint: u_stage (rising edge-triggered flip-flop clocked by clk)
Path Group: clk
0.000 0.000 clock clk (rise edge)
0.000 0.000 clock network delay (ideal)
1.000 1.000 ^ input external delay
0.000 0.000 1.000 ^ d (in)
0.000 0.000 1.000 ^ u_stage/D (DFF_P)
1.000 data arrival time
10.000 clock clk (rise edge)
-0.100 9.900 library setup time
9.900 data required time
8.900 slack (MET)验收看三个位置同时成立:起点是 d (input port clocked by clk),数据到达时间里出现 1.000 input external delay(正是 set_input_delay 1.0 写入的值),终点寄存器带 clocked by clk 且 slack 8.900 MET。三者缺任何一个,都可能是 wrong_port 那种“有 MET 但约束没生效”的假通过。若时钟与端点都正常却仍有未约束警告,再按 unconstrained endpoint 排查 区分下游引用缺失与 false path。
代码获取:完整设计、教学库、四份 SDC/Tcl 与运行脚本位于 geek-doc.cn/experiments/ts-opensta-input-delay-no-clock,安装 OpenSTA 2.0.17 后执行 bash run.sh 可一次复现三组故障与修复对照。
实验环境
- 机器/系统:本地 Docker 容器,Ubuntu 24.04;宿主为 macOS。
- 工具版本:OpenSTA 2.0.17,Debian 官方独立二进制包(镜像 geek-eda:0.3-sta)。
- 日期:2026-11-02。
- 完整命令:在实验目录执行
bash run.sh,依次运行no_clock、typo_hier、wrong_port、fixed四个用例,合并 stdout/stderr 并记录各组退出码。 - 实验边界:
experiment.lib仅含 DFF/BUF 最小时序弧,数值用于演示约束解析,不能外推为任何工艺的签核结论。
这一篇在知识体系里的位置
本篇属于 SDC 约束故障层,上接 SDC 数据格式与生命周期 中“时钟对象先于 IO 约束存在”的顺序约束,与 OpenSTA no clocks found:create_clock 缺失与端口名写错排查 互为姊妹篇:那篇查时钟是否附着到端口,本篇查 -clock 名字能否解析到对象;端点覆盖与下游引用问题继续看 unconstrained endpoint 排查。
总结
OpenSTA set_input_delay 时钟引用错误的本质是 -clock 按名字查时钟对象:忘建时钟、名字拼错或写成层次名都会得到同一句 clock arg ... clock not found,时钟建在同端口则得到 same port/pin not allowed,两类警告后约束都被静默跳过而退出码仍为 0。排查按“警告 → report_clock_properties → check_setup -verbose → slack”的顺序,修复后必须同时看到起点 clocked by clk、路径中出现与约束值一致的 input external delay、终点 slack MET,才算输入延迟真正生效。