“验证如果没有量化,那么就意味着没有尽头。”
伴随着复杂SoC系统的验证难度系数成倍增加,无论是定向测试还是随机测试,我们在验证的过程中终究需要回答两个问题:
是否所有设计的功能在验证计划中都已经验证?
代码中的某些部分是否从未执行过?
因此,引入覆盖率来作为验证过程的重要参考,用于衡量验证精度和完备性。
覆盖率的种类
如上图所示,常见为两种分法:
- 按照生成方式,分为隐性(implicit)和显性(Explicit);
- 按照来自功能描述,还是设计实现,分为specification或者implementation
因此,组合后有代码覆盖率、断言覆盖率以及功能覆盖率分别处于不同象限中。
代码覆盖率
优势:由仿真工具自动收集,继而用来指出在测试程序中设计源代码哪些被激活触发,而哪些则一直处于非激活的状态。
局限:覆盖率100%并不意味着足够的功能覆盖率。
包括:
- 跳转覆盖率(toggle),衡量寄存器跳转的次数(0–>1,1–>0);
- 行覆盖率(statement/line),衡量代码行有没有被执行;
- 分支覆盖率(branch),衡量条件语句(if/else,case,?:)分支执行情况;
- 条件覆盖率(condition/expression),衡量一些布尔表达式中各个条件真伪判断的执行轨迹;
- 状态机覆盖率(FSM),仿真工具可以自动识别状态机,因此可以状态机的执行情况,包括跳转次数、顺序等。
功能覆盖率
我们无法通过代码覆盖率来得知功能是否被实现了,因此需要显性地定义,将设计功能描述映射到与功能覆盖率中,从而量化功能验证。
覆盖组(covergroup)
覆盖组与类相似,可以多次例化。包含覆盖点(coverpoint)、选项(option)、形式参数(argument)和可选触发(trigger event)。
覆盖组可以采集任何可见的变量,比如程序或模块变量、接口信号或者设计中的任何信号。
更多地covergroup定义在类中,被称为嵌入式覆盖组声明,例如以下:
1 | class xyz; |
覆盖点(coverpoint)
覆盖组中可以包含多个覆盖点(coverpoint),coverpoint可以对应多个bin(仓)。
下面的代码中 覆盖组cg包含多个覆盖点例如b、cx、e以及匿名覆盖点和交叉覆盖点。
1 | covergroup cg ( ref int x , ref int y, input int c); |
仓(bin)
该关键字用于指定或对应所有感兴趣的数值或者取值范围。
除了覆盖数值外,还可以覆盖数值的变化。
1 | bit [4:1] v_a; |
交叉覆盖率(cross)
覆盖组中多个覆盖点或者变量之间可以另外定义交叉覆盖率(cover coverage)。
1 | //两个coverpoint交叉以后将生成256个交叉的bin |
覆盖率选项
覆盖率选项可以在covergroup、coverpoint或者cross中分别设置。
例如使用weight来表示比重;per_instance设置为1,将会记录每个covergroup实例的覆盖率数据;使用comment对covergroup/coverpoint/cross做进一步的说明,方便在覆盖率数据分析时阅读理解。
覆盖率选项以及预定义覆盖率方法做如下归纳:


Reference:
1.路科验证V0系列课程,可参考《芯片验证漫游指南:从理论到UVM的验证全视界》