SpyGlass 模块/单元找不到:Undefined module 与 Cannot find file 速查
更新时间:2026-10-22。FAQ 速查页,属于 EDA 工具排错系列,总入口见 开源 EDA 报错排错中心。SpyGlass(Synopsys 的 SpyGlass Lint/CDC/RDC)是 goal-based 流程:
spyglass -project xxx.prj -goals lint/lint_rtl启动后,工具按.prj工程文件里的read_file指令把 RTL、filelist、waiver 逐个读进来再编译。新工程搭环境、接入新 IP、换服务器跑回归时最高频的一类报错就是「模块/单元找不到」:文件根本没读进来,或读进来了但按名字解析不到定义。SpyGlass 的规则体系与 waiver 治理见 RTL 静态检查(Lint):SpyGlass 规则体系与基线门禁,本篇只做报错收敛。
本文要回答的问题
Cannot find file和Undefined module在 SpyGlass 里分别断在哪一步?.prj里的read_file、-flist(-f)和set_option search各管什么?- include 头文件目录该用
+incdir+还是set_option incdir? - 第三方 IP 只有黑盒、VHDL 的 library/work 顺序、相对路径基准这三类变体怎么判?
- 为什么换个目录或换台机器启动,同一个工程就报找不到?
一、报错原文与典型现象
SpyGlass 的「找不到」在 spyglass.log 与 goal 报告(如 lint/lint_rtl/spyglass_reports/ 下的汇总报告)里主要有四种文案,先认清再动手(工程名已占位):
1. 源文件本身打不开(读入阶段就断,最靠前):
Error: Cannot find file 'rtl/axi_dma.v'
##[Error] File listed in -flist does not exist: ip/fifo/rtl/fifo_sync.v2. include 头文件打不开:
Error: Unable to open include file 'axi_defs.vh'3. 文件读了,但按例化名找不到定义(编译/elaborate 阶段):
Warning: Undefined module 'fifo_sync' instantiated in module 'top_chip'
Warning: Unable to find module/entity 'pll_clk' referenced by instance 'u_pll'4. waiver 或库文件找不到(治理/工艺侧输入缺失):
Warning: Cannot find waiver file 'lint/common.awl'
Error: Cannot open gates library file listed by read_file -type gateslib一句话根因:SpyGlass 按「.prj/filelist 里的字符串路径」读文件,再按「模块/实体名字符串」解析例化——前两段报错断在「文件没进来」(路径、搜索目录、filelist 顺序问题),第三段断在「进来了但查无此名」(漏读、黑盒未声明、VHDL 库映射不对)。这与综合器 link 阶段的同类问题形似而机制不同,对照见 Design Compiler 模块找不到速查。
二、排查决策树
下面这张决策树按 SpyGlass 的读入顺序分叉:先确认文件能否打开,再确认 include 目录,最后才查模块定义解析;任何一条命中就在那一层修,不要跳着改 .prj。
读这张图抓住「先后」二字:红色起点是报错现象,三个蓝色判定对应三类报错原文,第①层不过后面都免谈——设计根本没读全,goal 跑出来的违例计数是残的;灰色 Q4 专门收「文件确实在、名字也对得上」的两种合法/半合法情形(黑盒与 VHDL 库);绿色节点是统一复验动作。
三、原因速查表
| 报错现象 | 可能原因 | 处置 |
|---|---|---|
| Cannot find file,文件确实在仓库里 | .prj 漏写 read_file 或 filelist 漏列 | 补 read_file -type verilog/sverilog 条目或 filelist 行 |
| filelist 里有,仍报 does not exist | filelist 内相对路径基准与启动目录不一致 | 从工程根启动 spyglass,或 filelist 改绝对路径 |
| 交互跑能过,回归/nohup 跑找不到 | 非交互 shell 缺环境变量,路径出现空段 | 回归脚本显式 source 工程环境,不依赖登录环境 |
| Unable to open include file | 头文件目录未给 incdir/+incdir+ | .prj 加 set_option incdir,或 filelist 行加 +incdir+ |
| Undefined module,grep 能搜到定义 | 定义文件在 filelist 但读入时报错被跳过,或顺序在顶层之后 | 查日志前文 Error;package/子模块排到顶层之前 |
| Undefined module,grep 搜不到 | 子模块/IP 未交付、submodule 未拉全 | 回供应链补文件,不擅自造 stub 顶包 |
| 报第三方 IP/PLL/PHY 名找不到 | 黑盒未按流程声明,缺 stub | 补空壳 stub 或按项目黑盒/waiver 流程登记 |
| VHDL entity 找不到 | library 未 map 或 analyze 顺序错(package/被引用者在后) | set_option lib 显式入库,先 package 与被引用 entity |
| waiver/gateslib 文件找不到 | waiver 或工艺库路径随目录搬迁失效 | 核对 read_file -type waiver/gateslib 路径 |
| 报的名字大小写古怪 | Windows 来的文件大小写不一致 | find . -iname 定位真实名,全工程统一 |
四、逐条排查展开
第一步:grep 证明定义在仓库里。 报谁找不到就搜谁的定义,Verilog/SystemVerilog 搜 module,VHDL 搜 entity:
grep -rn "module[[:space:]]*fifo_sync" --include='*.v' --include='*.sv' .
grep -rni "entity[[:space:]]*fifo_sync" --include='*.vhd' --include='*.vhdl' .搜不到就是交付问题:子模块没拉、第三方 IP 没装、filelist 生成时漏了目录。搜到了才进入「SpyGlass 看不看得见它」。仿真器侧的同名问题对照见 Questa/ModelSim 模块/单元找不到速查,两边 grep 起步的思路一致,但喂文件的机制不同。
第二步:核对 read_file 与 filelist。 SpyGlass 读设计的入口是 .prj 里的指令,典型写法如下:
read_file -type sverilog {rtl/axi_pkg.sv rtl/axi_dma.sv}
read_file -type verilog -flist {filelists/top.f}
set_option search {ip/fifo/rtl ../common/rtl}
set_option top top_chipread_file -type verilog/sverilog/vhdl 是显式列文件;-flist(工程里也常写作 -f)把一个 filelist 展开读入;set_option search 给的是「按名字找文件」的搜索目录,类似仿真器的 -y。三个入口少配任何一个都会出现「文件就在仓库里但 SpyGlass 说没有」。常见错法是把 filelist 交给综合器的写法原样搬来,却漏了 SpyGlass 不认的仿真专用选项——以 SpyGlass 文档支持的 filelist 语法为准,+incdir+、+define+ 在 filelist 内可用,其余仿真器私货不要带。
第三步:include 目录走独立通道。 `include "axi_defs.vh" 的查找不走 search,只走 include 目录:.prj 里用 set_option incdir {rtl/include ip/xxx/include},或在 filelist 里写 +incdir+rtl/include。报 Unable to open include file 时不要去 filelist 里加文件本身——头文件不应作为独立编译单元列进 read_file,加目录才是对症修法。
第四步:Undefined module 先看「读入有没有中途报错」。 文件在 filelist 里不等于定义进了设计:该文件读入期若有语法 Error(缺 `endif、宏未定义、方言不支持),SpyGlass 会跳过它,到 elaborate 时统一报 Undefined module。排查时在完整 spyglass.log 里从前往后搜 Error,而不是只盯最后的 undefined 汇总。另一种高频情形是顺序:SystemVerilog package、被 include 的公共定义必须排在使用者之前,filelist 按「package/define → 子模块 → 顶层」三段组织最稳。宏挡住的定义同理:module 声明包在 `ifdef FEATURE_X 里而 filelist 没给 +define+FEATURE_X,文件读了、定义却被预处理器剔掉。
第五步:黑盒与 stub 是合法的「找不到」,但要显式登记。 第三方 IP(PLL、PHY、SerDes)在 lint 阶段常以黑盒形式参与:没有 RTL 实现,Undefined module 是预期现象。合规做法是提供只含端口声明的 stub 文件让结构完整,或按项目流程在黑盒/waiver 清单中声明,而不是对每个 undefined 名手工压制违例。判据是报错模块是否在项目约定的黑盒清单内——在清单内走 stub 流程,不在清单内就是真漏文件。waiver 的组织与基线纪律见 SpyGlass lint 上线与 waiver 基线 和 waiver 治理流程。
第六步:VHDL 工程查 library map 与 analyze 顺序。 VHDL 的「单元」归属于 library:默认进 work,工程自有库要用 set_option lib rtl_lib 之类的指令在 read_file -type vhdl 前指定,源码侧还要有对应的 library rtl_lib; 子句。两个典型断点:package/被引用 entity 的 analyze 排在使用者之后(VHDL 要求先分析后引用,不像 Verilog 能容忍先例化后定义);以及多语言混仿时 VHDL 顶层与 Verilog 模块的大小写名不一致。处置是把 filelist 按库分段、每库内部按依赖排序,不依赖工具的猜测顺序。
第七步:相对路径基准与大小写。 .prj 与 filelist 里的相对路径按启动 spyglass 进程时的工作目录解析,不是按 .prj 文件所在目录。同一份工程,在工程根启动能过、在别处 spyglass -project /path/to/run.prj 就报一片找不到,根因都在这里;团队纪律是启动脚本先 cd 工程根,或生成 filelist 时统一写绝对路径。Linux 文件系统大小写敏感:文件实际叫 FIFO_sync.v、filelist 写 fifo_sync.v,Windows 共享盘上能混过,Linux 服务器直接报错,用 find . -iname 'fifo_sync*' 找真实名统一。
五、预防与纪律
- filelist 脚本化生成并自检:生成后逐行
test -f校验文件存在,package → 子模块 → 顶层三段顺序固定,手维护的 filelist 必然腐烂。 - 新 IP 接入走 checklist:
read_file条目、search 目录、incdir 目录、宏 define、黑盒/stub 声明五项一次配齐,缺一项 lint 红灯。 - 启动脚本固化环境与工作目录:显式 source 工程环境、先
cd工程根再启动 spyglass,杜绝「交互能过、回归不过」。 - 干净 goal 目录复验:修完删掉对应 goal 目录全量重跑,确认
spyglass.log0 Error、undefined module 计数归零,再看违例治理,避免增量产物掩盖问题。 - 报错原文先存档再动手:完整日志连同
.prj、filelist 一起贴进问题单,改一处重跑一次,别同时改三处后不知道哪处生效。
这一篇在知识体系里的位置
本篇是 EDA 排错速查簇的一员,总入口见 开源 EDA 报错排错中心;上游方法学是 RTL 静态检查(Lint):SpyGlass 规则体系与基线门禁,违例治理延伸到 SpyGlass lint 上线与 waiver 基线 与 waiver 治理流程;综合侧的同类「按名字找定义」问题对照 Design Compiler 模块找不到速查,仿真侧对照 Questa/ModelSim 模块/单元找不到速查。
一句话总结
SpyGlass 的「模块/单元找不到」本质是两段通道断了一段:读入段按 .prj/filelist 路径找文件(先补 read_file、set_option search 与相对路径基准,include 另走 set_option incdir/+incdir+),解析段按名字找定义(查读入期被跳过的 Error、package 与子模块顺序、黑盒 stub 声明,VHDL 再查 library map 与 analyze 顺序);先 grep 证明定义存在,再按决策树分段收敛,配合 filelist 脚本化自检与干净 goal 目录复验,这类报错基本不会跨轮次残留。