覆盖率数据库管理:URG/IMC工具使用,合并、比较、报告生成
覆盖率收集完了,然后呢?
很多同学跑完仿真,看到一堆 .ucdb 文件就懵了。说实话,我早年也犯过这个错——每个用例单独看覆盖率,结果发现A用例覆盖了模块1,B用例覆盖了模块2,但合起来看,中间那块逻辑谁都没跑到。嗯,这就是典型的「只见树木不见森林」。
所以今天咱们聊聊覆盖率数据库管理。说白了,就是怎么把零散的覆盖率数据管起来,让它真正为验证闭环服务。
3.1 URG与IMC:两把刷子,各有千秋
先说说工具。Synopsys 家的 URG(Unified Report Generator)和 Cadence 家的 IMC(Incisive Metrics Center),是业界最常用的两个覆盖率管理工具。我个人习惯两个都备着,因为不同项目、不同阶段,它们各有优势。
| 对比项 | URG | IMC |
|---|---|---|
| 命令行友好度 | ★★★★★ | ★★★☆☆ |
| GUI交互体验 | ★★★☆☆ | ★★★★★ |
| 合并速度(大数据量) | 快 | 中等 |
| 交叉覆盖率分析 | 需额外脚本 | 原生支持 |
举个例子。我在一个AI芯片项目中,每天要合并200+个用例的覆盖率。用URG写个脚本,几分钟搞定。但到了分析阶段,IMC的GUI能让我直观地看到哪些covergroup没命中,甚至能直接点进去看波形。所以我的建议是:批量处理用URG,深度分析用IMC。
3.2 合并覆盖率:1+1>2 的艺术
为什么要合并?你想想看,一个模块可能有几十个测试用例。每个用例跑出来的覆盖率,就像拼图的一块。只有把它们拼起来,你才能看到全貌。
URG合并的基本命令长这样:
urg -dir test1.ucdb test2.ucdb test3.ucdb \
-dbname merged.ucdb \
-report_dir urgReport
这里有个坑,我踩过。如果不同用例用了不同的seed,或者仿真选项不一样,直接合并可能会丢数据。我曾经因为一个用例用了+define+FAST_MODE,另一个没用,合并后覆盖率反而下降了。为什么?因为FAST_MODE跳过了某些分支,合并时URG默认取「最严格」的覆盖结果。
IMC的合并更直观一些:
imc -merge -out merged.ucdb \
test1.ucdb test2.ucdb test3.ucdb
我个人更喜欢IMC的合并方式,因为它会保留每个用例的原始数据,方便回溯。但代价是文件体积会大不少。
3.3 比较覆盖率:找到「谁没跑到」
合并是为了看全貌,比较则是为了找差异。什么时候需要比较?
- 回归测试前后对比:新加的用例有没有覆盖到之前漏掉的地方?
- 不同验证工程师的用例对比:A写的用例和B写的用例,覆盖区域有没有重叠?
- RTL修改前后对比:改了代码,原来覆盖到的点还在不在?
URG比较的命令:
urg -dir baseline.ucdb new.ucdb \
-compare baseline.ucdb \
-report_dir compareReport
输出结果里,你会看到三类数据:
- 新增覆盖:新用例覆盖到,但基线没覆盖的
- 丢失覆盖:基线有,但新用例没覆盖的
- 共同覆盖:两边都覆盖到的
我记得有一次,一个同事改了一行代码,结果导致某个状态机的跳转条件永远无法满足。回归测试全绿,但覆盖率比较一跑,发现那个状态少了30%的覆盖。这就是比较的价值——它告诉你「看起来没问题」和「真的没问题」之间的差距。
3.4 报告生成:让数据说话
报告不是给机器看的,是给人看的。所以,怎么把枯燥的覆盖率数据变成可执行的决策依据,是门学问。
URG生成的HTML报告,我一般会关注这几个指标:
| 指标 | 含义 | 我的经验阈值 |
|---|---|---|
| Line Coverage | 代码行执行率 | ≥95% |
| Toggle Coverage | 信号翻转率 | ≥90% |
| Fsm Coverage | 状态机覆盖率 | 100%(必须) |
| Assertion Coverage | 断言命中率 | ≥98% |
生成报告的常用命令:
urg -dir merged.ucdb \
-report_dir finalReport \
-format both \
-show all
这里 -format both 会同时生成HTML和文本格式。我个人习惯用HTML,因为可以点进去看具体哪些行没覆盖到,甚至能直接跳转到源码。
3.5 实战:一次完整的覆盖率数据库管理流程
说了这么多,咱们走一遍完整的流程。假设你手头有5个用例的覆盖率数据:
- 收集:确保每个用例都生成了 .ucdb 文件
- 合并:用URG或IMC合并成一个总库
- 比较:和上一轮的基线对比,找出差异
- 分析:打开报告,逐项检查未覆盖点
- 决策:哪些需要加用例?哪些是冗余代码?
- 归档:把合并后的 .ucdb 和报告一起存档,作为本轮验证的交付物
这一步,我建议用脚本自动化。我在项目中写过一个Makefile,每天凌晨自动跑回归、合并、生成报告,然后发邮件给团队。省下来的时间,都用来分析那些「顽固」的未覆盖点了。
最后说一句。覆盖率数据库管理,听起来像是「体力活」,但真正的高手,能从这些数据里读出设计的问题。比如,某个模块的toggle覆盖率一直上不去,可能意味着信号设计有问题;某个状态机的覆盖率突然下降,可能意味着代码修改引入了bug。这些,都是数据告诉你的。
所以,别把工具当工具,把它当你的「第二双眼睛」。