4. Synopsys VCS编译与仿真流程
VCS 的签核效率,很大程度上不取决于仿真跑得多快,而取决于“编译一次、仿真多次”这条链路上每个环节是否被正确配置。VCS 采用两阶段模型:编译阶段把 Verilog/SystemVerilog/VHDL 源码、UVM 库、断言与覆盖率模型一起分析、细化并生成可执行的仿真二进制(simv);仿真阶段运行 simv,通过运行时选项控制激励、随机种子、波形、覆盖率与调试行为。理解这两个阶段各自接受哪些选项、哪些选项会触发重新编译,是提升签核吞吐量的第一步。
编译阶段:把设计、验证平台与覆盖率一次性固化
典型编译命令由三部分组成:源文件列表、库与语言选项、编译期优化与覆盖率选项。一个可参考的示例(参数为教学示例,非实测结果):
vcs -full64 -sverilog -ntb_opts uvm-1.2 \
-timescale=1ns/1ps \
-f filelist.f \
-top tb_top \
-debug_access+all -kdb \
-cm line+cond+fsm+tgl+branch \
-cm_dir ./cov.vdb \
-cm_hier cm_hier.cfg \
-l compile.log \
-o simv
其中 -sverilog 启用 SystemVerilog,-ntb_opts uvm-1.2 引入 UVM 库,-f filelist.f 用文件列表管理上千个源文件,-top 指定顶层模块。-debug_access+all 与 -kdb 是调试接口的关键:前者开放信号、类、断点等调试能力,后者生成 Verdi 可读的知识数据库(KDB),使后续可以用 Verdi 直接加载 simv 做后处理调试,而不必重新编译。覆盖率方面,-cm 指定采集类型,-cm_dir 指定覆盖率数据库目录,-cm_hier 用配置文件限定采集范围,避免对无关 IP 采集覆盖率而拖慢仿真。
-cm 类型、修改 -debug_access 级别、更换 UVM 版本),必须重新编译。因此签核前应尽早冻结编译配置,把“需要调试”和“需要覆盖率”的能力一次性编入 simv,避免反复重编。仿真阶段:用运行时选项控制行为而不重编
仿真阶段通过 simv 加运行时参数控制。常用控制项包括:+ntb_random_seed=auto 让每次运行使用不同随机种子以扩大激励空间;+UVM_TESTNAME=xxx 选择要跑的 UVM 测试用例;+UVM_VERBOSITY=UVM_LOW 控制日志详细程度;-cm_name 与 -cm_dir 指定本次覆盖率写入位置;+fsdb+... 或 -ucli 控制波形与交互调试。例如:
./simv +UVM_TESTNAME=smoke_test \
+ntb_random_seed=12345 \
+UVM_VERBOSITY=UVM_LOW \
-cm line+cond+fsm+tgl+branch \
-cm_dir ./cov.vdb \
-l sim_smoke.log
这里的关键判断是:哪些选项属于编译期、哪些属于运行期。测试用例名、随机种子、日志级别、覆盖率写入目录都属于运行期,可以在不重编的前提下反复切换;而覆盖率采集类型、调试能力、UVM 版本属于编译期,改动即触发重编。把这两类选项分清,才能设计出高效的回归策略。
调试接口:让一次编译支撑多轮定位
调试接口的价值在于“编译一次、反复定位”。-debug_access+all 打开全部调试访问能力,配合 -kdb 生成 KDB,Verdi 可以直接加载 simv 与 KDB,查看信号波形、类层次、事务流和断言失败点,无需重新编译。若只需有限调试,可用 -debug_access+class 或 -debug_access+pp 降低编译开销。运行时用 -ucli 进入交互命令行,可在仿真中途设置断点、强制信号、dump 指定层次波形;用 +fsdb+... 或 $fsdbDumpfile 控制 FSDB 波形输出范围。实践中常见做法是:日常回归只开 -debug_access+class 并关闭全波形,仅在失败用例复现时用全调试 simv 加 -ucli 定位。
签核效率优化:把重编次数降到最低
签核效率的核心指标是“单位时间内完成的验证用例数”和“覆盖率收敛速度”。可操作的优化手段包括:
- 冻结编译配置:在回归启动前确定
-cm类型、-debug_access级别与 UVM 版本,避免回归中途重编。 - 用
-cm_hier裁剪覆盖率采集范围:只对 DUT 和关键验证组件采集,排除参考模型、第三方 VIP 内部,可显著降低仿真与合并开销。 - 并行回归与种子管理:用
+ntb_random_seed=auto或指定种子列表并行跑多个 simv 实例,失败种子单独记录以便复现。 - 覆盖率合并:用
urg把多个-cm_dir的 vdb 合并,统一查看 line/cond/fsm/tgl/branch 收敛情况,避免逐目录人工比对。 - 增量与分区:按模块或测试类型拆分回归批次,优先跑高价值用例,缩短反馈周期。
-debug_access+all 并 dump 全波形,导致编译时间与磁盘 I/O 大幅上升。正确做法是区分“调试编译”和“回归编译”两套配置,回归用轻量配置,失败后再用调试配置复现。一个可复用的签核检查清单
| 检查项 | 关键选项/命令 | 判断依据 |
|---|---|---|
| 编译配置是否冻结 | -cm、-debug_access、-ntb_opts | 回归期间无重编记录 |
| 覆盖率采集范围是否裁剪 | -cm_hier cm_hier.cfg | 排除非 DUT 层次,仿真时间下降 |
| 调试能力是否可用 | -kdb、-debug_access+all | Verdi 能加载 simv 与 KDB |
| 种子是否可复现 | +ntb_random_seed=12345 | 失败用例可用同种子复现 |
| 覆盖率是否合并 | urg -dir cov1.vdb cov2.vdb | 生成统一覆盖率报告 |
把上述配置固化为回归脚本的一部分,VCS 的编译与仿真就不再是“每次从头再来”,而是一条可预测、可复现、可并行的签核流水线。编译期决定能力边界,运行期决定激励与观测,调试接口决定定位速度,三者配合才能把签核效率真正提上去。