简介SpyGlass LintRules Reference Guide 是 Synopsys 官方发布的静态分析工具参考手册版本 Q-2020.03-SP1面向从事 IC 设计验证的工程师及学习 Verilog、VHDL 硬件描述语言的进阶读者。它系统梳理了 SpyGlass lint 产品的全部规则集覆盖设计风格、时序分析、功耗优化、设计约束与接口检查等方向每条规则均给出规则 ID、目的描述、示例代码、修改方案及严重性等级并说明如何按项目需求启用、禁用或自定义规则集。资源包为单一 PDF 文件共 1 个文件大小约 2.04MB便于随查随用。目前已有 4457 人学习下载读者可借此在设计早期定位语法与编码规范问题理解规则背后的检查逻辑减少后期返工提升设计可靠性与验证效率。1. SpyGlass Lint Rules Reference 到底在查什么从一条报错说起跑完综合SpyGlass 甩出几百条WARNING其中一条写着RegOutputsClk你盯着 RTL 看了半天时钟明明接在寄存器上为什么工具说有问题翻手册翻到SpyGlass_LintRules_Reference.pdf才发现这条规则查的不是「时钟有没有接」而是「寄存器输出是否直接驱动了时钟端口」。这就是 Lint Rules Reference 的价值它把每条规则背后的检查意图、触发条件、豁免方式写清楚让你从「报错看不懂」变成「知道该改哪里、该不该改」。这份文档本质上是 SpyGlass Lint 规则集的字典覆盖 STARC、RMM、CDC 等主流规则包每条规则包含规则名、所属包、严重级别、检查逻辑、示例代码和 waiver 写法。它解决的核心问题是综合前把 RTL 里的结构性隐患提前抓出来避免跑到后端才发现跨时钟域没同步、复位极性接反、组合逻辑成环。适合谁看写 RTL 的、跑 Lint 的、做 CDC 检查的、以及被几百条 warning 淹没不知道从哪下手的验证和前端工程师。下面按「规则怎么读 → 环境怎么搭 → 规则怎么调 → 坑在哪 → 怎么进阶」的顺序拆开讲。2. 把 Lint Rules Reference 读成可执行清单规则分类与优先级判断2.1 规则包的分层逻辑STARC、RMM、CDC 各管什么SpyGlass 的 Lint 规则不是一锅乱炖而是按规则包组织。常见的有三类STARC 管 RTL 结构性检查比如RegOutputsClk、ComboLoop、LatchInferredRMM 管可综合性和可测性比如NoResetToReg、SyncResetMuxCDC 管跨时钟域比如ClockDomainCrossing、SyncMissing。每条规则在 Reference 里都有唯一名字名字本身就是检索关键词。读 Reference 时不要从第一页翻到最后一页而是按项目阶段选包。RTL 刚写完先跑 STARC 把组合环、锁存器、时钟用法问题清掉准备综合前跑 RMM 确认复位和可测性有多时钟域时CDC 包必须单独跑。优先级判断原则先修Error级别再修Warning级别Info级别可以批量 waiver。因为 Error 通常意味着功能可能出错Warning 可能是风格问题。提示Reference 里每条规则的Severity字段是默认级别项目可以在.prj文件里覆盖。不要直接改 Reference改项目配置。2.2 从规则名反查检查意图以 RegOutputsClk 为例规则名通常是驼峰式英文短语拆开就能猜出检查对象。RegOutputsClk Register Outputs Clock查的是寄存器输出直接当时钟用。Reference 里会给出反例和正例// 反例寄存器输出直接驱动时钟 always (posedge clk) begin div_clk ~div_clk; end always (posedge div_clk) begin // 这里触发 RegOutputsClk data din; end // 正例用时钟使能或 PLL 分频 always (posedge clk) begin if (clk_en) data din; end逻辑说明SpyGlass 在 Elaboration 阶段构建时钟树发现div_clk的驱动源是寄存器输出而非时钟端口或 PLL 输出就报RegOutputsClk。参数说明该规则属于 STARC 包默认Warning可通过-severity改为Error。豁免方式是在规则名后加-waive并写理由但不要滥用因为寄存器分频确实会引入时钟偏差。2.3 规则严重级别的项目化调整别让 Warning 淹没 Error默认规则集跑下来Warning 数量可能是 Error 的几十倍。如果全部修工期不允许如果全部 waiveLint 就白跑。我的做法是分三批处理第一批修所有Error和Fatal第二批修与 CDC、复位相关的Warning第三批对纯风格类Warning做批量 waiver但要在 waiver 文件里写清楚原因和负责人。在.prj文件里调整严重级别的写法# 将 RegOutputsClk 从 Warning 提升为 Error set_rule_severity -rule RegOutputsClk -severity Error # 将 WidthMismatch 从 Warning 降为 Info set_rule_severity -rule WidthMismatch -severity Info逻辑说明set_rule_severity是 SpyGlass 的 Tcl 命令在read_verilog之后、run_goal之前执行。参数说明-rule后跟规则名必须与 Reference 里的名字完全一致大小写敏感-severity可选Fatal、Error、Warning、Info。改完后重新跑lint/lint_rtlgoal看报告里级别是否生效。3. 本地跑通 SpyGlass Lint 的最小环境与命令3.1 环境准备License、版本与目录结构SpyGlass 是商业工具需要 License。本地跑通的最小环境包括SpyGlass 安装目录假设$SPYGLASS_HOME、License 文件路径、一个待检查的 RTL 文件、一个.prj项目文件。版本方面不同版本规则集有差异Reference 的版本要和工具版本匹配否则规则名可能对不上。常见做法是查$SPYGLASS_HOME/doc下的 Release Notes 确认规则变更。目录结构建议这样组织project/ ├── rtl/ │ └── top.v ├── spyglass/ │ ├── top.prj │ └── waiver.tcl └── reports/逻辑说明rtl/放设计文件spyglass/放项目配置和 waiverreports/放输出报告。参数说明.prj文件里用read_file指定 RTL 路径用set_option指定顶层模块名。3.2 最小 .prj 文件与运行命令一个能跑起来的最小.prj文件# top.prj read_file -type verilog ../rtl/top.v set_option top top set_option language_mode verilog set_option enableSV no set_option projectwdir ./work current_goal lint/lint_rtl run_goal逻辑说明read_file读入 RTLset_option top指定顶层current_goal选择 lint_rtl 目标run_goal执行。参数说明language_mode可选verilog或vhdlenableSV控制是否启用 SystemVerilog 支持projectwdir是工作目录存放中间文件。运行命令spyglass -project top.prj -batch逻辑说明-batch表示非交互模式适合脚本化。参数说明-project指定.prj文件路径如果要生成 HTML 报告加-report html。跑完后在reports/下找spyglass_reports/lint/lint_rtl/目录里面按规则名分文件列出违规。3.3 报告解读从汇总页定位到具体行号SpyGlass 报告首页是汇总表列出每条规则的违规数量和严重级别。点击规则名进入详情页会显示文件名、行号、代码片段和规则描述。Reference 里的规则描述和报告里的描述一致所以可以对照看。如果报告里某条规则你不认识直接拿规则名去 Reference 里搜。常见做法是先把报告导出为 CSV用脚本统计每条规则的违规数按数量排序优先处理数量多且级别高的。导出命令spyglass -project top.prj -batch -export csv -report_dir ./reports逻辑说明-export csv生成 CSV 格式报告方便用 Excel 或 Python 分析。参数说明-report_dir指定报告输出目录默认是./spyglass_reports。4. 规则调优与 Waiver 写法让 Lint 结果可落地4.1 Waiver 的三种写法与适用场景Waiver 是 Lint 流程里最容易出问题的地方。写得太宽等于没查写得太窄每次跑都报。Reference 里每条规则都会给出 waiver 示例常见有三种按规则名全局 waive、按文件行号 waive、按信号名 waive。# 方式一全局 waive 某条规则慎用 waive -rule RegOutputsClk # 方式二按文件行号 waive精准 waive -rule RegOutputsClk -file top.v -line 42 # 方式三按信号名 waive适合跨文件 waive -rule RegOutputsClk -signal div_clk逻辑说明方式一适合确认项目里不会出现该问题的场景方式二适合已知某行是例外方式三适合信号在多个模块里出现但都合规的情况。参数说明-file后跟文件名必须与报告里一致-line是行号-signal是信号名大小写敏感。注意waiver 文件要纳入版本管理每次新增 waiver 都要写注释说明原因和负责人否则半年后没人知道为什么 waive。4.2 用参数覆盖规则默认行为以 WidthMismatch 为例有些规则的行为可以通过参数调整。比如WidthMismatch默认检查所有赋值语句的位宽但项目里可能有故意截断的情况。Reference 里会列出该规则支持的参数比如-allow_truncation。# 允许显式截断但保留隐式截断检查 set_rule_param -rule WidthMismatch -param allow_truncation -value yes逻辑说明set_rule_param在.prj里设置规则参数。参数说明-param后跟参数名-value后跟值。不同规则支持的参数不同必须查 Reference 确认不要猜。4.3 增量跑 Lint只查改动模块全芯片跑 Lint 可能几十分钟改一行 RTL 就全跑不现实。SpyGlass 支持增量模式只重新检查受影响的模块。在.prj里加set_option incremental yes set_option incremental_db ./work/incr_db逻辑说明第一次跑全量生成增量数据库后续跑时只分析改动文件及其依赖。参数说明incremental_db指定数据库路径不要放在临时目录否则清理后失效。增量模式对 CDC 规则支持有限CDC 建议全量跑。5. SpyGlass Lint 避坑五条血泪经验5.1 规则名大小写写错导致 waiver 不生效现象明明在 waiver 文件里写了waive -rule regoutputsclk跑完还是报RegOutputsClk。原因SpyGlass 规则名大小写敏感Reference 里是RegOutputsClk写成全小写不匹配。解决直接从报告里复制规则名不要手打。报告里的规则名和 Reference 完全一致。5.2 顶层模块设错导致大量 Undefined Module现象跑 Lint 报几百条UndefinedModule但 RTL 里模块明明存在。原因set_option top指定的顶层模块名和实际不一致或者文件读取顺序导致模块没被 Elaborate。解决确认top值与 RTL 里module后的名字完全一致如果有多文件用read_file按依赖顺序读入或用-f文件列表。5.3 忽略 CDC 规则导致跨时钟域问题漏到后端现象Lint 跑完没报 CDC 问题但后端发现跨时钟域没同步。原因默认lint_rtlgoal 不包含 CDC 规则包需要单独跑cdc/cdc_setup或cdc/cdc_check。解决在.prj里加current_goal cdc/cdc_setup和current_goal cdc/cdc_check并确保时钟定义正确。5.4 Waiver 文件路径写错导致规则没被豁免现象waiver 文件里写了规则但报告里还在报。原因.prj里没有read_filewaiver 文件或者路径是相对路径但工作目录不对。解决在.prj里显式加read_file -type waiver ./waiver.tcl路径用绝对路径或确认相对路径基准。5.5 版本升级后规则名变更导致旧 waiver 失效现象升级 SpyGlass 后原来 waive 的规则又开始报。原因新版本可能重命名规则或拆分规则包Reference 版本和工具版本不匹配。解决升级前查 Release Notes 里的规则变更列表升级后重新跑一遍对比报告差异更新 waiver 文件。6. 进阶用 Tcl 脚本批量分析 Lint 报告并自动分类跑完 Lint 只是开始真正费时间的是从几百条违规里挑出必须修的。我的习惯是写一个 Tcl 脚本把报告解析成结构化数据按规则名、文件、行号、严重级别分类然后自动生成待办列表。下面是一个最小可用脚本# analyze_lint.tcl set report_file ./reports/spyglass_reports/lint/lint_rtl/lint_rtl.csv set fp [open $report_file r] set data [read $fp] close $fp set lines [split $data \n] set rule_count [dict create] foreach line $lines { if {[string match *Rule*File*Line* $line]} { continue } set fields [split $line ,] if {[llength $fields] 4} { continue } set rule [lindex $fields 0] set file [lindex $fields 1] set line_no [lindex $fields 2] set severity [lindex $fields 3] dict incr rule_count $rule puts \[$severity\] $rule - $file:$line_no } puts \n 规则违规统计 foreach rule [lsort [dict keys $rule_count]] { puts $rule: [dict get $rule_count $rule] }逻辑说明脚本读取 CSV 报告逐行解析用dict incr统计每条规则的违规数最后按规则名排序输出。参数说明report_file路径根据实际报告位置调整CSV 列顺序可能因版本不同先用head -1确认列名。这个脚本可以扩展成自动生成 waiver 模板或者按严重级别过滤只输出 Error。另一个实用技巧是结合grep快速定位# 统计每条规则的违规数 grep -oP ^\w reports/lint_rtl.csv | sort | uniq -c | sort -rn # 只看 Error 级别 grep ,Error, reports/lint_rtl.csv | head -50逻辑说明grep -oP提取每行开头的规则名sort | uniq -c计数sort -rn按数量降序。参数说明-o只输出匹配部分-P启用 Perl 正则。这两个命令在报告文件很大时比打开 Excel 快得多。我自己的习惯是每次跑完 Lint先跑一遍统计脚本把 Error 和 CDC 相关 Warning 挑出来剩下的批量 waiver 前再扫一眼有没有新规则出现。这个习惯帮我省过好几次——有一次新版本加了一条ResetPolarity规则默认 Warning但项目里复位极性确实接反了差点漏到后端。希望帮到你。本文还有配套的精品资源点击获取