Lint 与 SpyGlass waiver 签核:规则违例怎么分级、怎么豁免
更新时间:2026-09-14。本文是数字验证系列第 9 篇。前面讲的仿真、覆盖率、UVM、Formal 都依赖“人写的检查或激励”,而 Lint 是零激励静态扫描:今天修一个锁存器,可能比三周后门级仿真少查一个通宵。CDC/RDC 专项见 CDC/RDC 报告分诊。
一、Lint 在流程中的位置
| 阶段 | 检查目标 | 典型规则 |
|---|---|---|
| RTL 提交 | 编码风格、位宽、敏感列表、不可综合写法 | W 类 warning |
| 子系统冻结 | latch、组合环路、无复位 FF、case 不全 | Error / Critical |
| 综合前 | 三态、黑盒、悬空/短接、不可达逻辑 | synthesis lint |
| 网表阶段 | DFT 规则、时钟/复位网络、test mode 差异 | DFT lint |
Lint 不能证明功能对,但能抓“语言合法、硬件危险”的代码:仿真可能恰好没走到,综合器却按自己的解释生成电路。
二、最常见的高危违例
- 意外 latch:
always_comb中某分支未给变量赋值,保持旧值需要存储元件。 - 组合环路:组合输出绕回输入,延迟不可预测,可能振荡。
- 多位宽截断/符号扩展:32 位赋给 16 位,
signed与unsigned混用。 - 复位不一致:部分触发器无复位、同域复位极性不同、数据条件参与复位。
- 敏感列表不完整:老式
always @(*)之外的 Verilog 写法导致仿真/综合不一致。 - case 缺 default 且非 full-case:FSM 可能落入未定义状态。
- 模块端口悬空、常量短接、黑盒未定义:顶层集成最常见。
// 高危:en=0 时 q 未赋值,推断 latch
always_comb begin
if (en) q = d;
end
// 推荐:给默认值
always_comb begin
q = '0;
if (en) q = d;
end三、报告怎么读
一条违例至少包含:rule name、severity、层次路径、文件行号、触发代码片段。分诊顺序:
- 先看 Ac_unsync / W164 / STARC 等规则集里被项目设为 Error 的项。
- 再看汇总中的 violation count、waived count、unwaived count。
- 同一根因的成百上千条不要逐条修:例如顶层总线低 8 位悬空,修一次端口连接即可批量消失。
- 对黑盒、IP、SRAM 要确认是否有约束/模型,而不是简单豁免。
- 每次综合、DFT 插入后重新跑,确认 waiver 仍匹配到预期实例。
四、waiver 不是“点忽略”
waiver 的本质是带证据的设计决策,至少包含:
| 字段 | 要求 |
|---|---|
| 规则/违例 ID | 精确到 rule,不使用过宽通配符 |
| 实例/文件/行 | 优先实例级,不全局豁免 |
| 原因 | 为什么该结构安全、由什么机制兜底 |
| 证明 | 波形、SVA、Formal、协议、IP 手册 |
| 申请人/批准人 | RTL owner、验证/设计负责人双签 |
| 有效期 | 版本、milestone、过期条件 |
waive -rule W164a \
-du u_dbg_i2c \
-instance {top.u_soc.u_dbg} \
-comment "debug only, gated by reset and fuse default-off; DV test dbg_i2c_waiver_01 passed; owner: zhang; expire: tapeout-B"五、推荐门禁
- 新 RTL:Error 必须清零,Warning 给例外清单。
- 子系统 signoff:unwaived critical = 0;所有 waiver 可追溯。
- 顶层冻结:不允许新增“全局 waiver”;已有 waiver 重新审核。
- 网表/DFT/ECO 后:waiver 命中数若变化,必须解释。
- waiver 入库版本化,不能只存在工程师本地脚本中。
六、常见坑
- 用
// synopsys translate_off把真实问题代码藏掉。 - 为了过 lint 把所有 warning 全局 waive。
- 用
default: q = q;显式写 latch,却没说明这是有意存储。 - DFT test mode 下新增 mux 没有重新检查时钟/复位。
- IP 黑盒端口“看起来接上了”,实际 tie-off 极性错误。
七、规则集、误报与回归节奏
不同规则集不要混在一起解读。STARC、DesignWare、RMM、厂商 synthesis lint、DFT lint 的关注点不同:有的偏编码风格,有的偏可综合性,有的偏测试结构。项目应在开始阶段冻结一份规则集,并区分“必须失败”“可批准例外”“仅提示”三级。不要在流片前一周临时改规则严重等级,否则大量历史 waiver 会失去意义。
误报通常来自三类原因:工具不认识项目的同步器模板、宏/黑盒边界缺少模型、设计模式需要结构约束。处理顺序应是先补库和约束,让工具识别真实结构;仍无法识别时才 waiver。例如项目统一的 2-FF 同步器可以登记为 waiver 模板,但必须限定模块、实例和下游用途,且在综合网表后确认没有被替换或打散。
推荐在 RTL 生命周期中设三个检查点:个人提交前跑本地轻量 lint;子系统每周跑完整规则并对比新增违例;冻结和 ECO 后跑无缓存全量检查。每次报告至少保存原始日志、waiver 文件、规则版本、PDK/工具版本和 summary。评审时不只看总数,还要看新增、消失、waiver 未命中三类变化:waiver 突然未命中,往往意味着代码结构已经改变,原来的安全理由可能失效。
Checklist
- [ ] Error/Critical 全部清零或有批准 waiver。
- [ ] 无意外 latch、组合环路、不可达 FSM 状态。
- [ ] 复位、时钟、test mode 规则过签。
- [ ] waiver 精确、带证据、带 owner 和过期条件。
- [ ] 每次大改后重跑并比较新增/消失违例。
相关与延伸
CDC/RDC 见 CDC/RDC 报告分诊;复位设计见 复位设计;FSM 与锁存器问题可结合 RTL 设计规范 与 DFT 可测性设计。
总结
Lint 抓的是“仿真未必走到、硅上一定算数”的结构错误;waiver 只能豁免已证明安全的例外,必须精确到实例、带证据、有 owner 和过期条件,不能成为团队掩盖风险的垃圾桶。