2. SpyGlass CDC工具环境搭建
SpyGlass 的 CDC 检查并不是“打开工具点一下 Run”就能得到可信结果的工作。它依赖一套稳定的工程环境:目录如何组织、工艺库如何映射、RTL 与 SGDC 约束如何读入、命令行与 GUI 如何启动、运行脚本如何固化参数。环境搭建得是否规范,直接决定后续 CDC 结果的可复现性。本节围绕这四件事展开,并给出可直接参考的目录骨架与运行脚本。
一、项目目录结构:把“输入、约束、脚本、输出”分开
SpyGlass 工程最常见的失败原因不是规则不会用,而是输入文件散落各处、约束与 RTL 版本不匹配、每次运行输出互相覆盖。建议在项目根目录下建立职责清晰的子目录,让“只读输入”和“可写输出”物理隔离:
cdc_project/
├── rtl/ # 设计源码(只读)
│ ├── top.sv
│ ├── clk_gen.v
│ └── sync_2ff.v
├── lib/ # 工艺库与标准单元库
│ ├── stdcell.lib
│ └── io.lib
├── sgdc/ # SpyGlass 约束文件
│ ├── top.sgdc
│ └── clocks.sgdc
├── scripts/ # 运行脚本
│ ├── run_cdc.prj # 工程文件
│ └── run_cdc.sh # 命令行入口
├── work/ # 工具工作目录(可写、可清理)
└── reports/ # 结果输出
├── cdc/
└── logs/
其中 rtl/、lib/、sgdc/ 属于版本管理对象,work/ 与 reports/ 属于每次运行可重建的产物,不应纳入版本库。这样做的价值在于:当 CDC 结果出现异常时,可以快速判断是设计改动、约束改动还是库映射改动导致的。
二、工艺库与设计读入:先解决“认不认识这个单元”
SpyGlass 读入设计时,需要知道每个模块、每个标准单元的行为与端口信息。对于纯 RTL 设计,工具可以直接解析 Verilog/SystemVerilog;但一旦设计中例化了工艺库单元(如标准单元、IO、存储器模型),就必须提供对应的库文件,否则会出现“模块未定义”或端口悬空,进而导致时钟树识别错误、CDC 路径漏报。
库读入通常通过 read_file 或工程文件中的库选项完成。以 Liberty 库为例,在工程文件中可写为:
read_file -type lib ./lib/stdcell.lib
read_file -type lib ./lib/io.lib
设计读入则按 RTL 文件列表进行,注意顶层模块名要与后续约束一致:
read_file -type verilog ./rtl/top.sv
read_file -type verilog ./rtl/clk_gen.v
read_file -type verilog ./rtl/sync_2ff.v
set_option top top
这里有一个容易被忽略的细节:set_option top 指定的顶层必须与 RTL 中实际例化的顶层模块名完全一致,大小写敏感。若顶层写错,工具可能仍能读入文件,但会以错误的层次展开,导致 CDC 分析范围不完整。
三、SGDC 约束:告诉工具“哪些是时钟、哪些是异步”
CDC 检查的核心输入之一是 SGDC(SpyGlass Design Constraints)。它至少需要声明时钟、复位以及跨时钟域关系。一个最小可用的 clocks.sgdc 示例如下:
clock -name clk_a -period 10 -waveform {0 5}
clock -name clk_b -period 6.667 -waveform {0 3.333}
reset -name rst_n -value 0
# 声明两个时钟为异步关系
cdc_setup -async_clock clk_a clk_b
其中 clock 定义时钟周期与波形,reset 定义复位有效电平,cdc_setup -async_clock 明确告诉工具这两个时钟之间需要做 CDC 检查。若缺少异步声明,工具可能按同步路径处理,从而漏掉真实的跨时钟域风险。SGDC 文件通过 read_file -type sgdc 读入,顺序上建议放在 RTL 读入之后、规则运行之前。
四、命令行与 GUI 启动:两种入口,同一套工程
SpyGlass 提供命令行与图形界面两种启动方式。命令行适合批量回归与 CI 集成,GUI 适合交互式调试与结果浏览。两者可以共用同一个工程文件,保证结果一致。
命令行启动的典型形式为:
spyglass -project ./scripts/run_cdc.prj -batch -goal cdc/cdc_setup_check
其中 -project 指定工程文件,-batch 表示批处理模式,-goal 指定要运行的检查目标。GUI 启动则去掉 -batch:
spyglass -project ./scripts/run_cdc.prj
启动后,GUI 会加载工程中的设计、库与约束,并在 Goal 列表中呈现可运行的检查项。无论哪种方式,真正决定“检查什么”的是工程文件与 SGDC,而不是启动命令本身。
五、基本运行脚本编写:把参数固化下来
为了让每次运行可复现,建议把命令行参数写入 shell 脚本,而不是手工敲。一个最小可用的 run_cdc.sh 如下:
#!/bin/bash
set -e
PROJ=./scripts/run_cdc.prj
GOAL=cdc/cdc_setup_check
LOG=./reports/logs/cdc_run.log
mkdir -p ./reports/cdc ./reports/logs ./work
spyglass -project $PROJ -batch -goal $GOAL 2>&1 | tee $LOG
echo "CDC run finished. Check reports/cdc/ for violations."
脚本中 set -e 保证任一命令失败即退出,tee 同时输出到终端与日志文件,便于事后追溯。运行结束后,重点查看 reports/cdc/ 下的违例报告:若 cdc_setup_check 报出“未声明时钟”或“时钟未约束”,说明 SGDC 不完整;若报出大量跨时钟域路径,则需要结合同步器结构判断是真实风险还是约束缺失。
set_option enableSV yes(若设计使用 SystemVerilog),并确认工具版本与库格式兼容。库文件版本与 RTL 不匹配时,CDC 结果可能完全不可信。work/ 与 reports/ 提交到版本库,也不要在同一目录下混用不同项目的工程文件。每次运行前清理 work/ 可避免旧缓存干扰结果。完成以上四步后,一个可复现的 SpyGlass CDC 环境就建立起来了:目录职责清晰、库与设计正确读入、SGDC 明确声明时钟与异步关系、命令行与 GUI 共用同一工程、运行脚本固化参数并保留日志。后续所有 CDC 规则调试与结果分析,都应在这个稳定环境上进行。