SpyGlass 回归结果丢失:nightly lint 报告缺失速查
更新时间:2026-10-23。FAQ 速查页,属于 EDA 工具排错系列。早上打开 lint 回归汇总页,所有 block 的违规数和 waiver 数全是零——不是「清零通过」那种零(真实设计 lint 不可能一条违规没有),是结果根本没被收上来的空零;或者更直接的,某个 block 的整份 SpyGlass 报告文件在结果目录里找不到。这类「无声丢失」比报错难查,因为 SpyGlass 侧的 log 可能写得挺正常,断点发生在回归脚本和汇总环节。六成以上是脚本问题而非工具问题:退出码没检查、工作目录复用、输出路径跟版本漂移。退出码本身的排查见 SpyGlass 退出码非零,磁盘写满的专项见 SpyGlass 磁盘写满。
本文要回答的问题
- 汇总页零违规零 waiver,怎么判断是真干净还是结果没收到?
- 每个 block 的 sg_shell log 都在,为什么汇总页还是空?
- 只剩最后一次 run 的结果,前面的结果去哪了?
- 版本升级之后汇总脚本突然找不到报告,路径是谁改的?
- 怎么让「结果丢失」本身变成一个可见的失败?
一、报错原文与现象
# 回归汇总页(聚合报表)
block_a lint violations=0 waived=0 <- 不真实
block_b lint violations=0 waived=0 <- 不真实
# 结果目录
runs/block_a/ spyglass.log 存在,但 reports/ 下缺 violations.rpt
runs/block_c/ 目录存在,内容只有最后一次 rerun 的产物
# 汇总脚本日志
collect_results: WARNING: no report found for block_a, skipping先校准一个直觉:lint 回归全绿、零违规零 waiver,第一反应应该是「结果丢了」而不是「代码真干净」。真实设计挂 lint 不可能干干净净,汇总页的全零几乎总是「汇总脚本没收到任何有效结果时的默认填充值」。排查主线就是顺着「sg_shell run → 报告落盘 → 汇总收集 → 报表展示」这条链找断点。
二、可能原因总览
| 现象 | 可能原因 | 处置 |
|---|---|---|
| 汇总页全零 | sg_shell 中途失败但回归脚本没检查退出码,汇总继续跑拿空结果 | 每个 run 后断言退出码,失败即中止该 block 的汇总 |
| 只剩最后一次 run | 同名工作目录复用,后一个 run 覆盖前一个 | 工作目录带 run id 或时间戳,禁止复用 |
| 升级后报告找不到 | SpyGlass 默认输出目录随版本变了,汇总脚本还按旧路径找 | 对齐 release note 的默认路径变化,显式指定输出目录 |
| 汇总文件内容被截断/错乱 | 并行回归多个 job 同时写共享汇总文件互相截断 | 各 job 写独立分片,汇总阶段单点合并 |
| 最后几个 run 缺报告 | 磁盘满,前面的 run 看着正常、后面的写不出 | 查磁盘与配额,满盘报警前置到回归开始前 |
| 归档目录整个空 | 归档步骤走异地挂载,挂载掉线静默失败 | 归档后校验件数,掉线即非零退出 |
三、逐条排查展开
第一问:每个 run 的退出码检查了吗。 这是 SpyGlass 回归结果丢失的头号根因:sg_shell 中途挂了(license 拿不到、工程文件读失败、内部错误),但回归脚本只负责「启动 sg_shell 然后往下走」,从不看退出码。汇总脚本按时到岗,发现报告文件不存在,打个 WARNING 就 skip,最后汇总页填个零。特征非常典型:sg_shell 自己的 log 里有明确的 ERROR 甚至 ABORT,但回归整体状态是绿的。处置:每个 run 结束后立刻断言退出码与关键产物存在性,二者任一失败就把这个 block 标 FAIL 并中止后续汇总——别让汇总脚本在缺料的情况下「尽力而为」。退出码语义细节见 SpyGlass 退出码非零。
工作目录复用:只剩最后一次 run。 回归脚本给每个 block 分配工作目录时用了固定名字(如 runs/block_a/),同一个 block 当晚被 rerun 了两次(比如第一次失败后自动重试),第二次直接把第一次的目录清掉重来。如果第一次其实是成功的、第二次失败了,你就把一份好结果换成了一份空目录。特征:目录里的时间戳全部集中在最后一次 run 的时间窗,且 log 开头是干净的工具启动横幅而不是续跑。处置:工作目录固定带「block 名 + run id/时间戳」两段,历史 run 保留到汇总完成再统一清理。
输出路径随版本漂移。 SpyGlass 版本升级后默认输出目录结构变了(报告子目录名、顶层结果目录命名规则),汇总脚本里硬编码的旧路径一夜之间全部落空。这种故障的阴险之处在于回归本身完全正常,报告都好好写着,只是写在「新家」,而汇总脚本还在敲「旧门」。特征:升级后第一次回归全灭,手工按新路径找报告全在。处置:回归脚本显式用命令行选项指定输出目录,不吃工具默认值;升级版本时把 release note 里「默认路径/目录结构变化」列入升级检查单。
并行写共享汇总文件互相截断。 多个 block 的汇总 job 并行跑,都往同一个汇总 CSV/HTML 追加写,两个 job 同时打开、同时写、后写者覆盖先写者,或者写到一半互相截断。特征:汇总文件行数对不上 block 数,且缺哪几行每次回归都不一样(竞态,无规律)。处置:每个 job 只写自己的分片文件(一个 block 一个文件),汇总阶段由单一进程串行合并;写共享文件必须加文件锁,但更推荐分片制,锁在 NFS 上并不可靠。
磁盘满:前几个正常、后几个失踪。 磁盘或配额在回归中段写满,前面跑完的 block 报告齐全,磁盘满之后的 run 写报告失败——SpyGlass 写不出报告不一定让整个进程崩,有的版本只打一条写失败的告警就继续,回归脚本没检查产物存在性的话就一路绿灯。特征:缺失的 block 全部集中在时间线后段,df 一看磁盘是满的(或刚被清理出空间,但 inode/配额记录还在)。处置:回归开始前检查磁盘余量门槛,不足直接拒跑并报警;每个 run 收尾校验产物件数。专项排查见 SpyGlass 磁盘写满。
归档挂载掉线:最后一步静默蒸发。 结果都在本地跑出来了,归档脚本把结果 rsync 到归档服务器或共享存储,挂载点夜里掉线,rsync 失败但脚本没检查返回码,回归状态照旧是绿。第二天看归档目录整个是空的,本地结果又已被定时清理。特征:本地临时目录已被清理但归档目录空,归档脚本日志里有被忽略的连接错误。处置:归档后立刻对账「源端件数 vs 归档端件数」,不一致即非零退出;清理本地结果的策略改成「确认归档成功后才清」。
颜色按语义分角色:红是入口现象与三类已定位的根因,蓝是排查动作,绿是「该环节排除、转下一环」的分流判定,橙是修复动作,紫是防复发收尾。主线是「按链逐环排除」:先查退出码(工具侧死了没有),再查工作目录(结果被覆盖没有),再查输出路径(报告写去哪了),最后查汇总与存储侧(并行互截、磁盘满、挂载掉线)——四段链条各自独立,顺序排查才不会被「log 看着正常」带偏。
四、预防与纪律
- 退出码与产物双断言:每个 run 结束既查 sg_shell 退出码,又查关键报告文件存在且非空,任一失败即标 FAIL。
- 工作目录唯一化:block 名 + run id 两段命名,历史 run 保留到汇总完成再清理。
- 输出目录显式指定:不吃工具默认路径;版本升级把「默认输出结构变化」列入检查单。
- 汇总分片制:并行 job 各写各的分片,单点串行合并,杜绝共享文件竞态。
- 磁盘门槛前置:回归开始前查磁盘余量与配额,不足拒跑并报警。
- 归档对账:归档端件数与源端一致才允许清理本地结果;「提交 N 个 block、回收 N 份报告」的闭环对账每次回归自动跑,差集直接报警,不留白。
这一篇在知识体系里的位置
本篇是 EDA 排错速查簇中 SpyGlass 系列的「回归结果闭环」FAQ 页:退出码语义见 SpyGlass 退出码非零,磁盘写满专项见 SpyGlass 磁盘写满,回归体系与对账机制的建设背景见 ASIC CI/CD 回归;同型问题在实现工具侧的对照页见 Innovus/ICC2 回归结果缺失。
一句话总结
SpyGlass 回归结果丢失先认「汇总页全零即丢失」这个锚点,再按链逐环排查:sg_shell 失败但退出码没检查(头号根因)、工作目录同名复用被覆盖、版本升级改了默认输出路径、并行 job 互截共享汇总文件、磁盘满只丢后段 run、归档挂载掉线静默失败;治本靠每个 run 的「退出码 + 产物存在性」双断言、汇总分片制和「提交与回收」件数对账,让结果缺失本身成为一个显式报警的失败。