Calibre 未定义符号:Undefined variable / not defined 速查
更新时间:2026-10-22。FAQ 速查页,属于 EDA 工具排错系列。Calibre 说的「未定义符号」不是 C 链接器那套
undefined reference,没有 .o、没有库扫描顺序:它的符号分四个世界——SVRF rule deck 里的 VARIABLE、宏与规则名,SPICE 网表里的子电路和器件 model,layer map 里的层号与 purpose,以及 PEX 连接语句里的 node。共同点是「文件都在、语法也对,但引用的名字查无定义」。rule deck 的五段结构见 Calibre SVRF rule deck 解剖,验证流程全貌见 Calibre 物理验证实操。名字对应的文件本身打不开的场景归 Calibre 模块/单元找不到,本篇只管「文件在读、符号没定义」。
本文要回答的问题
- transcript 里的
Undefined variable是 shell 环境变量没给,还是 deck 里 VARIABLE 没写? - LVS 报
Subcircuit ... is not defined,缺的是我自己的模块还是 PDK 器件 model? undefined layer和 layer 号报错为什么换一版 PDK 就冒出来?- 规则名、PEX node 报未定义,各自该回哪个文件里修?
一、报错原文与典型现象
Calibre 把未定义符号按它正在解析的世界分别报错,先认出符号属于哪一类,再决定去 deck、网表还是 layer map 里找。以下是四类典型 transcript 文案,工程名均已占位。
1. SVRF 变量或宏未定义(deck 展开期,最靠前):
***** ERROR: Undefined variable "PROJ_RULE_HOME" encountered while expanding INCLUDE statement.
***** ERROR: Unknown variable substitution "$DENSITY_TH" encountered in rule "M1.DENS.1".2. SPICE 子电路或器件 model 未定义(LVS 源网表读入期):
Error: Subcircuit "PLL300M" referenced by instance "u_core/u_pll" is not defined.
Error: Device model "nsvt_lp" used by instance "u0" is not defined in the source netlist.3. layer 号或 purpose 未登记(deck 与版图对照期):
***** ERROR: Layer number 118 is not defined in the rules file.
***** ERROR: Undefined layer/purpose "M1 pin" referenced in LVS TEXT mapping.4. 规则名或 PEX node 未定义(规则引用与寄生连接期):
***** ERROR: Rule name "M1_FILL" referenced in property check is not a previously defined rule.
***** ERROR: Undefined node "vssa_ana" encountered in PEX netlist connection statement.一句话根因:Calibre 只认真正展开过的文本里、以完全一致的名字出现过的定义。 名字查无定义,要么是定义压根没被展开到(VARIABLE 段没 include、PDK 变量没 export、网表漏 include),要么是定义排在引用之后(SPICE 先例化后见 .SUBCKT),要么是名字本身对不上(拼错、大小写、换 PDK 版本后层号/model 名改了)。器件识别的完整机制见 LVS 器件识别与抽取。
二、原因速查表
| 报错现象 | 可能原因 | 处置 |
|---|---|---|
| Undefined variable,路径里变量名原样残留 | shell 环境变量未 export,非交互 shell 没继承 | 在启动 calibre 的 shell 里 echo $变量名 验证,脚本显式 source 环境 |
| Unknown variable substitution 于某规则 | SVRF VARIABLE 未声明,或声明排在引用之后 | 全 deck grep 定义点,VARIABLE 集中放头部、先定义后引用 |
| 工艺厂原版 deck 能跑,加项目段就报变量未定义 | 项目段引用了主 deck 变量,但 INCLUDE 位置在定义段之前 | 调整 INCLUDE 顺序,项目段永远放最后 |
| Subcircuit ... is not defined(自己的模块名) | 源网表导出漏模块,或 .INC 片段没挂全 | 网表文件里 grep .SUBCKT 名字,缺啥回数字侧补导出 |
| Device model ... is not defined(PDK 器件名) | model 库未挂、.LIB 工艺角没选或选错角 | runset 挂 PDK model 文件,核对 .LIB 角名与 deck 配套 |
| 加了 include 仍说 subckt 未定义 | SPICE 顺序问题:例化语句出现在定义之前 | 调整 include 顺序,定义先于例化 |
| Layer number N is not defined | 引用了 deck 未声明的层号,常见于换 PDK 版本 | grep 层号定义点,在 layer map/LAYER 段补登记 |
| Undefined layer/purpose | purpose 名(drawing/pin/…)拼错或层别名未定义 | 照 PDK layer map 核对层别名与 purpose 原文 |
| Rule name ... not a previously defined rule | 规则名拼错,或被引用的规则在本段之后才定义 | grep 规则名定义点,统一命名并调整先后 |
| Undefined node(PEX 连接语句) | 网表中不存在该网名,常为电源网名拼错 | 回源网表 grep 网名,先修网表再谈 PEX |
三、逐条排查展开
第一步:grep 定义点,不要凭记忆判断。 报错原文已经把符号名给全了,拿它去全 deck 与全部 include 目录里搜,一分钟定性。SVRF 变量搜 VARIABLE 名字,自定义层或规则搜它的声明行,宏搜其定义语句:
grep -rn 'VARIABLE PROJ_RULE_HOME' rules/
grep -rn 'M1_FILL' rules/ | headgrep 不到任何定义,问题在「定义没进来」——继续第二步;grep 得到但行号晚于引用处,是顺序问题;grep 得到多处,警惕两个 deck 段各自定义、引用处吃到了错的那个。
第二步:展开 INCLUDE 序列,确认定义段真的被读到。 SVRF deck 靠 INCLUDE 拼起来,变量和层定义只在文本流里「先出现」才有效。项目自定义段 INCLUDE 在工艺厂环境段之前,或引用了主 deck 才定义的变量,都会报未定义。固定纪律是项目段永远挂在 deck 最后。另一类高频原因是定义来自 shell 环境:报错路径里变量名原样残留(字面的 $PDK_DIR 字样)就是一眼判据——在启动 calibre 的那个 shell 里 echo 验证,回归脚本开头显式 source PDK 的 setup 脚本,桌面终端里有值不代表调度系统里有。
第三步:SPICE 网表严格区分「自己的子电路」和「PDK 的 model」。 LVS 报 Subcircuit ... is not defined,先看名字:是自己的模块(如 PLL300M),grep 源网表有没有 .SUBCKT PLL300M,多半是网表导出漏了模块或 .INC 片段没挂全,回数字侧补;是 PDK 器件(如 nsvt_lp),问题在 model 库——runset 里没挂模型文件、.LIB 工艺角没选,或角名与当前 deck 版本不配套。注意 SPICE 是顺序语言:.SUBCKT/.MODEL 定义必须出现在例化之前,include 顺序放反时文件明明都在,照样报未定义。
.INC "smic41_lp.l"
.LIB "smic41_lp.l" tt
XU0 a b vss vss nsvt_lp W=1u L=0.04u最小判据仍是 grep:在实际被读入的全部网表片段里搜 .SUBCKT 名字 与 .MODEL 名字,搜不到就不用怀疑 LVS 开关。
第四步:layer 号/purpose 回 layer map 与 LAYER 段对账。 DRC/LVS deck 在前部声明合法层号与层别名,引用一个没声明的层号(118 这类数字)或 purpose(pin/drawing/net 等)就报 undefined。最常见触发点是换 PDK 版本:老工艺里 text 层在 118,新版挪了号,项目层照旧号写就失配。处置是照新版 PDK 的 layer map 逐字符核对层号、datatype 与 purpose 名,缺的层别名在项目段补声明,不要去改工艺厂原 deck。
第五步:规则名与 PEX node 各回各的源头修。 not a previously defined rule 的关键词是 previously——SVRF 要求规则先定义后引用,拼错规则名(M1_FILL 写成 M1_FIL)或引用排在定义之前都是这个报错。PEX 连接语句里的 Undefined node 则根本不是 deck 问题:node 名必须真实存在于网表,电源/地网名拼错(vssa_ana 对网表里的 VSSA)最典型,回源网表 grep 网名,先把网表修干净,PEX 这一层自然消解。
下面这张决策树按「符号首先出现在哪种文件」分叉,任何一条命中就在对应那一侧修,不要跨世界乱改:
读这张图抓住「按符号所属世界分诊」:红色入口只做一件事——判断报错名首先出现在 SVRF、SPICE 还是层映射文本里;三个蓝色分支互不串活,deck 的问题去 grep VARIABLE 与 INCLUDE 顺序,网表的问题去 grep .SUBCKT/.MODEL,层与 node 的问题去对 layer map 和网名;橙色修复叶节点统一以「干净目录重跑、transcript 0 Error」收口,报错变少不算修完。
四、预防与纪律
- 变量与层定义集中放 deck 头部,项目段只挂尾部:先定义后引用是 SVRF 的硬顺序,INCLUDE 序列固定后,未定义类报错不会随段落增删反复出现。
- 回归脚本环境自检前置:启动 calibre 前打印并
ls关键变量指向的文件,非交互 shell 显式 source 环境,不继承桌面终端的侥幸。 - 网表交付带清单:模块网表与 PDK model 分开列、
.LIB角名写进交付说明,LVS 报未定义时照清单 grep,五分钟定性是网表漏还是 model 没挂。 - PDK 升级先对差异表:层号、purpose 名、model 改名在升级评审时一次性过一遍,项目段引用的层号逐一对账,不混引新旧两套 deck。
- 改一处、干净重跑、只认第一条未定义:未定义符号常连环报(变量缺失导致其下游规则全部失配),修掉根因后连环错会成片消失,不要逐条追。
这一篇在知识体系里的位置
本篇是 EDA 排错速查簇的一员,总入口见 开源 EDA 报错排错中心;上游机制是 Calibre SVRF rule deck 解剖(VARIABLE、INCLUDE 与层声明都在五段骨架里),流程背景见 Calibre 物理验证实操,LVS 子电路/model 侧的器件对应原理见 LVS 器件识别与抽取。同系列两个近邻:文件本身打不开归 Calibre 模块/单元找不到,deck 解析不过归语法解析速查。数字综合侧「按名字找定义」的同构问题可对照阅读 Design Compiler 未定义符号速查。
一句话总结
Calibre 未定义符号按报错名所属的世界分诊:SVRF 变量、宏、规则名去 grep 定义点与 INCLUDE 顺序(VARIABLE 先定义后引用、PDK 变量在启动 shell 里 export),SPICE 子电路缺失回数字侧补网表、器件 model 缺失挂 PDK 模型库并保证定义先于例化,layer 号/purpose 照新版 layer map 补登记,PEX 的 undefined node 回网表核对网名;修完一律干净目录重跑到 transcript 0 Error,只认第一条根因报错。