SpyGlass lint 信号被优化看不到:debug_access、保留层级与关优化速查
更新时间:2026-10-24。FAQ 速查页,属于 EDA 工具排错系列,总入口见 开源 EDA 报错排错中心。SpyGlass 在 elaboration 之后会对设计做一轮内部规整:常量传播、未驱动 nets 删除、无负载分支裁掉、部分层级打平(flatten),目的是让 lint 规则跑得更快更准。副作用是——你在 GUI 的 Hierarchy 浏览器、Waveform 关联视图或交叉探测里点某个信号,发现它「不存在」;或者规则报告里的路径名和你 RTL 里的写法对不上。本篇处理这类信号/层级被工具优化掉、观测不到的问题。它和 SpyGlass lint 引用无法解析速查 的分界是:那篇是名字绑定不上(编译期硬错误),本篇是设计编译成功、规则也跑完了,但你想看的对象被规整阶段删除或改名了。
本文要回答的问题
optimized away、removed、not found in the compiled design这些提示分别意味着什么?- GUI 里点不到的信号,是被删了还是被改名、被并入别的 net 了?
debug_access、保留层级、关优化三类手段各自的代价是什么,先动哪个?- 想让报告路径名稳定可追溯,工程配置应该固定哪几项?
一、报错原文与典型现象
这类问题通常不是一条红色 Error,而是 GUI 交互时的提示、报告里的注释行或 log 里的规整摘要(工程路径均为占位):
1. GUI 交叉探测点不到信号:
Warning: Signal 'demo_top.u_core.u_fifo.wr_ptr_gray[3]' not found in the compiled design.
Info: Object was optimized away during design compilation (constant or unobservable).2. log 里的规整摘要:
Info: [ELAB_OPTIMIZE] 214 nets removed (constant-propagated), 37 instances merged.
Info: [ELAB_OPTIMIZE] Module 'demo_skid' inlined into parent (hierarchy flattened).
Warning: Unconnected net 'demo_top.u_core.dbg_bus[7:0]' trimmed.3. 报告里的路径名变形:
Warning: [STARC05-1] Signal 'demo_top.u_core.u_fifo_mem_gen.mem_reg[0][3]' ...
(source RTL: u_fifo.mem[0][3], array expanded)典型现象三类:一是 GUI 里右键「Go to Source」跳不过去或报 not found;二是 violation 里的层次路径多出一截 u_xxx_gen 或实例名被加了后缀;三是 debug 总线、观察用寄存器在编译后整个消失。判据一句话:编译 0 Error、规则有结果,但观测对象缺失,就走本篇;编译本身就挂的请回引用/符号类篇目。还有一种容易误判的情形:信号在 RTL 里明明有赋值、有负载,照样消失——这通常说明它的负载链在某个参数取值下被整体裁成了死逻辑(例如参数化位宽把高几位裁空、配置寄存器写通道被 tie-off),工具按「不可观测」把它删了,这类要回到参数集去查,而不是直接怪优化。
二、病因处置速查表
| 现象 | 可能原因 | 处置 |
|---|---|---|
| 信号 not found in compiled design | 常量传播后该 net 被删除(如 tie-off、参数裁剪后恒值) | 确认它是否真为常量;要观测就加 debug_access 或改全可见模式 |
| 整根 debug 总线消失 | 无负载 nets 被默认 trim | .prj 加 set_option debug_access all 或对关键层级开 debug_access |
| 子模块整个找不到 | 模块被 inline、层级打平 | 开 set_option preserve_hierarchy,或按实例加保留属性 |
路径名带 _gen、下标展开 | generate 块展开是正常行为 | 报告按展开后路径读;写 waiver 用展开路径或通配 |
| 数组/存储器只剩几位 | 未引用的存储位被裁剪 | 接受裁剪(不影响功能),或对 mem 加保留观测属性 |
| 改代码后现象不变 | work/ 增量库沿用了旧规整结果 | 清 work/ 全量重跑再判断 |
| 同一信号时有时无 | 参数集(GENERIC/宏)切换导致常量关系变化 | 固定 .prj 的 parameter/define 集合后再观测 |
| 只有某个 goal 下看不到 | goal 专属 option 覆盖了全局 debug 设置 | 核 goal 的 goal_option 是否关掉可见性相关项 |
三、排查决策图
下面这张图按「观测对象是什么形态消失」分流:红色是现象入口,三个蓝色判定依次问「是常量被删、是层级被打平、还是参数集变了」,橙色一步处理增量缓存假象,绿色统一复验,紫色收尾把配置固化进工程。
读这张图抓一条主线:先判断消失的对象「在逻辑上还应不应该存在」——常量裁剪是正当优化,观测需求才是例外;只有观测需求真实存在时才付出 debug_access 的性能代价,不要一上来全局全开。
四、逐条排查展开
第一步:确认信号是「被删」还是「被改名」。 在 spyglass.log 里搜 ELAB_OPTIMIZE 摘要,看删除/合并计数是否异常;再到 GUI 的编译视图按 RTL 源行号反查——能从源码跳到编译对象说明只是改名(generate 展开、数组打平),跳不过去才是真被删。改名类不用修,waiver 与报告一律按展开后路径书写即可。
第二步:常量与无负载裁剪,用 debug_access 找回观测点。 SpyGlass 默认会删掉常量传播后的等价 net 和无负载分支。观测需求(调试总线、统计计数器、给波形对齐用的中间信号)通过 set_option debug_access all 全局打开可见性,或更精细地只对目标层级开:set_option debug_access {demo_top.u_core}。代价是编译变慢、内存变大,所以推荐按层级开而不是全局开。若该信号在功能上确实恒为常量,更经济的做法是接受裁剪,改观测它的上游驱动。一个实用判据:只想在报告里「看见它出现过几次、被谁驱动」,接受裁剪即可;要做跨探针跳转、和仿真波形逐拍对齐,才值得为它付出 debug_access 的成本。
第三步:层级打平用 preserve_hierarchy 挡。 模块被 inline 后,报告里的路径会丢掉一层,GUI 的层级树也少一支——对依赖层级做 waiver 划分、按模块统计违例的团队影响很大。set_option preserve_hierarchy 保留层级边界;只想保个别模块时,用厂商支持的保留属性标注对应实例。注意保层级同样会抬高内存与规则运行时间,大规模 SoC 上建议只保「要做违例归属统计」的那几层。判断是否被打平的一个快招:拿报告里的违例路径去 GUI 层级树逐级点,点到某一级不存在、而下一级内容直接挂在父层里,就是 inline 的现场;此时 waiver 里的旧路径全部失效,需要按打平后路径重写或先把层级保住再重跑。
第四步:排除增量缓存与参数集漂移。 规整结果缓存在 work/ 下,改过 RTL 或 option 后不重清,GUI 看到的可能是上一轮的对象集合——先删 work/ 与 goal 目录全量重跑再下结论。另一类漂移是参数集:同一份 RTL 在 GENERIC 取值不同或宏集合不同时,常量关系完全不同,昨天能看的信号今天被裁掉是正常结果;把 parameter 与 +define+ 集合固定在 .prj 里,观测结论才可复现。参数漂移引发的其他连锁报错可对照 SpyGlass lint 结果不确定速查。
五、规范做法与预防
- 观测需求显式登记:调试总线、统计寄存器进设计约定文档,对应层级在
.prj里固化debug_access,不靠个人记忆临时开。 - 按层级开可见性,不全局全开:全局
debug_access all在大设计上明显拖慢编译,只对调试层级开放。 - waiver 用展开后路径:generate 展开是确定的,
.awl条目按编译后路径书写,并配通配而非逐位枚举。 - 参数集冻结:
.prj固定 parameter 与 define 集合,评审通过才允许改,改动必须全量重跑。 - 每次规整类配置变更后清
work/:增量库缓存的是旧规整结果,重跑前清库作为固定动作。 - 报告路径命名约定入文档:团队约定 waiver、违例归属统计一律用编译后展开路径,新人培训时先讲 generate 展开规则,避免拿 RTL 原路径去匹配报告空查半天。
这一篇在知识体系里的位置
本篇是 EDA 排错速查簇的一员,总入口见 开源 EDA 报错排错中心。编译期名字绑定失败见 SpyGlass lint 引用无法解析速查,符号表查无此名见 SpyGlass 未定义符号速查;跑出来的结果时有时无对照 SpyGlass lint 结果不确定速查,规则体系整体定位见 RTL 静态检查(Lint):SpyGlass 规则体系与基线门禁。
一句话总结
SpyGlass lint 信号看不到,九成是 elaboration 后的正当规整:常量传播删 net、无负载裁剪、层级 inline、generate 展开改名。按「先分清删除还是改名 → 观测需求真实存在才按层级开 debug_access → 层级统计需求用 preserve_hierarchy → 参数集冻结并清 work 全量重跑」四步收敛;把可见性配置固化进 .prj,观测点才不会随优化级别漂移而时有时无。