4. Cadence覆盖率采集环境搭建

覆盖率闭环的第一步不是“看报告”,而是让仿真器在运行过程中把覆盖率信息稳定地写出来。Cadence Xcelium 的覆盖率采集依赖三件事:编译期打开覆盖率插桩、运行期指定覆盖率数据库路径与类型、仿真结束后对数据库做合并与报告生成。这三件事分别落在编译脚本、运行脚本和后续处理脚本中,任何一环缺失,覆盖率都会“看起来跑了但没有数据”。本节围绕 irun/xrun 的覆盖率选项,给出一套可直接落地的环境搭建方案。

一、覆盖率采集的三个阶段与关键选项

Xcelium 的覆盖率流程可以理解为“编译插桩 → 运行采集 → 合并报告”三段。编译阶段决定哪些覆盖率类型被插入到设计中,运行阶段决定数据写到哪个 cov_work 目录,合并阶段把多次运行的数据库归并成一份可分析的结果。常用的覆盖率类型包括:

  • 代码覆盖率:block(语句块)、expression(表达式)、toggle(信号翻转)、fsm(状态机)。
  • 功能覆盖率:由 SystemVerilog covergroup 定义,通过 functional 采集。
  • 断言覆盖率:SVA 断言命中情况,通过 assert 采集。

编译期用 -coverage 指定类型,例如 -coverage block+toggle+fsm+functional+assert。注意 toggle 会显著增加数据库体积和仿真开销,在大型 SoC 上通常先只开 block+functional,等回归稳定后再补 toggle。运行期用 -covfile 指定覆盖率配置文件,或用 -covworkdir 指定数据库根目录,用 -covtest 给本次运行命名,便于后续按用例区分数据。

覆盖率类型一旦在编译期确定,运行期无法“补开”。如果发现报告里没有 toggle 数据,先检查编译命令是否包含 toggle,而不是去改运行脚本。

二、编译脚本集成

下面是一段可参考的编译脚本片段,假设顶层为 tb_top,设计文件列表放在 filelist.f 中。示例参数属于教学假设,实际项目需按自己的目录结构替换。

#!/bin/bash
# compile.sh —— 编译期打开覆盖率插桩
xrun -elaborate \
     -f filelist.f \
     -top tb_top \
     -coverage block+functional+assert \
     -covdut tb_top \
     -covoverwrite \
     -access +rwc \
     -timescale 1ns/1ps \
     -l compile.log

其中 -covdut tb_top 指定覆盖率统计的顶层范围,避免把 UVM 库、VIP 内部代码也纳入统计;-covoverwrite 表示每次编译覆盖旧的插桩信息,防止多次编译后数据库混乱。编译完成后,工作目录下会出现 cov_work 目录的雏形,但此时还没有运行数据。

三、运行脚本集成与数据库生成

运行阶段的核心是把每次仿真的覆盖率数据隔离存放,并打上用例标签。推荐用 -covtest 加用例名,用 -covworkdir 指定统一的数据库根目录:

#!/bin/bash
# run.sh —— 单用例运行并生成覆盖率数据库
TEST_NAME=$1
xrun -R \
     -covworkdir ./cov_work \
     -covtest ${TEST_NAME} \
     -covoverwrite \
     -input run.tcl \
     -l ${TEST_NAME}.log

运行结束后,./cov_work/scope/tb_top 下会生成以 ${TEST_NAME} 命名的数据库目录,里面包含 icc 等覆盖率数据文件。此时可以用 imc 打开单个用例查看,但回归场景下更常见的是把几十上百个用例的数据合并。

Xcelium 覆盖率采集与合并流程 编译期 · 插桩 xrun -elaborate -coverage block+functional -covdut tb_top -covoverwrite 运行期 · 采集 xrun -R -covworkdir ./cov_work -covtest ${TEST_NAME} -covoverwrite 合并期 · 归并 imc -load cov_work -merge test1 test2 ... -report report.txt -html -detail cov_work 目录结构(示例) cov_work/ └── scope/ └── tb_top/ ├── test_smoke/ ← 单用例数据库 ├── test_regress/ ← 单用例数据库 └── merged/ ← 合并后数据库

四、合并流程与常见问题

合并使用 imc 命令行模式,把多个用例数据库归并到一份结果中。示例命令如下:

imc -load cov_work/scope/tb_top \
    -merge test_smoke test_regress test_error \
    -report merged_cov.txt \
    -html -detail

合并时需要注意三点。第一,所有被合并的数据库必须来自同一次编译,即插桩信息一致;如果中途改了 RTL 或编译选项,旧数据库与新数据库的覆盖率模型不匹配,合并会报错或产生错误百分比。第二,-covtest 名称不能重复,否则后一次运行会覆盖前一次数据,建议用“用例名+时间戳”或“用例名+seed”命名。第三,合并后的数据库建议单独存放,不要与单用例数据库混在同一目录,便于回归脚本反复重建。

如果 imc 报 “coverage model mismatch”,优先检查是否混用了不同编译批次的数据;如果报告里功能覆盖率始终为 0,检查 covergroup 是否在 initial 或 final 阶段被正确例化并采样。

五、环境搭建检查清单

把上述内容整理成一份可执行的检查清单,便于在项目初期快速核对:

阶段检查项判断依据
编译是否包含 -coverage 及所需类型compile.log 中无 “coverage disabled” 提示
编译-covdut 是否限定到 TB 顶层报告 scope 中不出现 UVM/VIP 内部模块
运行-covworkdir 与 -covtest 是否成对出现cov_work 下生成以用例名命名的目录
运行用例名是否唯一目录不互相覆盖,数量与回归用例数一致
合并是否同一次编译产物imc 合并无 model mismatch
合并报告是否包含功能覆盖率merged_cov.txt 中 functional 百分比非 0