引言
本文简单介绍 SystemVerilog 的功能覆盖率。
前文链接:
介绍
啥是功能覆盖率?
功能覆盖率是对测试执行了哪些设计功能/特性的度量。这在约束随机验证(CRV)中很有用,以了解回归中的一组测试覆盖了哪些功能。
它的局限性在哪?
假设您在设计文档中提到了10个功能,而您不知何故忽略了/遗漏了3个功能,或者没有意识到其中的3个,那么您将只为其中的7个编写功能覆盖代码。如果所有7个功能都在测试中被击中,您可能会得出结论,所有的功能都被覆盖了。因此,您需要确保设计规范中的所有必需信息都包含在功能覆盖块中。
SV中的功能覆盖率如何做?
我们的想法是在测试平台中对感兴趣的变量进行采样,并分析它们是否达到了特定的值。
mode可以接受16个值,而key可以接受4个值。因此,如果在仿真中有东西可以监视这两个变量,并报告执行了模式和关键字的值,您就会知道测试是否覆盖了特定的功能。好的方面是,仿真器中有一些选项可以将这些覆盖细节转储到文件中,以便在模拟完成后可以对其进行审查。此外,您可以将来自不同测试的所有此类覆盖文件合并到单个数据库中,并作为一个整体进行审查。如果测试A覆盖功能X,测试B覆盖功能Y,合并后的数据库将显示您已经涵盖了X和Y。
怎么写覆盖组?
// 覆盖组
class CLASS_EXP1;
rand bit [3:0] mode;
rand bit [1:0] key;
function void display();
$display("[%0t ns] mode = 0x%0h , key = 0x%0h",$time,mode,key);
endfunction
covergroup COVERGROUP;
coverpoint mode{
bins featureA = {0};
bins featureB = {[1:3]};
bins common[] = {4:$};
bins reserve = default;
}
coverpoint key;
endgroup
endclass
注意:
- 变量均以覆盖点(coverpoint)的形式出现;
- 覆盖点均放置在 covergroup 内;
- 可以创建多个覆盖组用不用的 bins 集合采样相同的变量;
- 当变量达到预期值后,bins 可以说是被覆盖或者击中,所以当 mode 取到1,2或3时,featureB被覆盖;
- reserve bin 是用于不属于其他bin的所有值的单个bin。
- common将有12个独立的bin,从0x4到0xF的每个值对应一个bin。
为什么仿真中缺少覆盖率指标?
您必须启用工具供应商特定的命令行开关来转储覆盖率详细信息。然后,打开Cadence ICCR/IMC等覆盖率查看器工具,并打开覆盖率转储文件。
如何声明采样时刻?
有两种方式在覆盖组中触发覆盖率采集。
- 使用 sample() 方法:
- 设置触发事件
条件覆盖率的方式?
- 使用 iff 结构;
- 使用 start 和 stop 函数;
覆盖组和覆盖点
SystemVerilog 的 covergroup是一个用户定义的类型,它封装了覆盖率模型的规范。它们可以定义一次,通过new函数在不同的地方实例化多次。CoverGroup可以在包、模块、程序、接口或类中定义,通常封装以下信息:
- 一组覆盖点
- 覆盖点之间的交叉覆盖
- 定义覆盖组采样时刻的事件
- 配置覆盖对象的其他选项
覆盖组
module COVER1_TEST ;
// 变量定义
bit [1:0] mode;
bit [2:0] cfg;
// 时钟
bit clk;
always #20 clk = ~clk;
// 覆盖组
covergroup cg @(posedge clk);
coverpoint mode;
endgroup
// 实例
cg cg_inst;
initial
begin
cg_inst = new();
for(int i=0;i<5;i++)
begin
@(negedge clk);
mode = $random();
cfg = $random();
$display("[%0t] mode = 0x%0h cfg = 0x%0h",$time,mode,cfg);
end
end
initial
begin
#500 $display("Coverage = %0.2f %%",cg_inst.get_inst_coverage());
$finish;
end
endmodule
仿真结果:
# [40] mode = 0x0 cfg = 0x1
# [80] mode = 0x1 cfg = 0x3
# [120] mode = 0x1 cfg = 0x5
# [160] mode = 0x1 cfg = 0x2
# [200] mode = 0x1 cfg = 0x5
# Coverage = 50.00 %
覆盖点
CoverGroup可以包含一个或多个覆盖点。CoverPoint指定需要覆盖的整数表达式。CoverPoint表达式的求值发生在CoverGroup采样时。SystemVerilog覆盖点可以选择性地用冒号(:)标记。
下面显示的示例多次随机化两个变量MODE和CFG,并在时钟的每个负边沿分配一个值。CoverGroup被指定为在时钟的每一个正沿出现时进行采样。因此,这两个变量在时钟的负边沿被随机化5次,并在时钟的正边沿采样。
mode的值可以从0到3,cfg的值可以从0到7。覆盖率的问题是:每个变量实际取到的数值占总的可取值数量的比例。
module COVER1_TEST ;
// 变量定义
bit [1:0] mode;
bit [2:0] cfg;
// 时钟
bit clk;
always #20 clk = ~clk;
// 覆盖组
covergroup cg @(posedge clk);
cp_mpde : coverpoint mode;
cp_cfg_10 : coverpoint cfg[1:0];
cp_cfg_lsb : coverpoint cfg[0];
cp_sum : coverpoint (mode+cfg);
endgroup
// 实例
cg cg_inst;
initial
begin
cg_inst = new();
for(int i=0;i<10;i++)
begin
@(negedge clk);
mode = $random();
cfg = $random();
$display("[%0t] mode = 0x%0h cfg = 0x%0h",$time,mode,cfg);
end
end
initial
begin
#500 $display("Coverage = %0.2f %%",cg_inst.get_inst_coverage());
$finish;
end
endmodule
仿真结果:
# [40] mode = 0x0 cfg = 0x1
# [80] mode = 0x1 cfg = 0x3
# [120] mode = 0x1 cfg = 0x5
# [160] mode = 0x1 cfg = 0x2
# [200] mode = 0x1 cfg = 0x5
# [240] mode = 0x2 cfg = 0x5
# [280] mode = 0x1 cfg = 0x4
# [320] mode = 0x1 cfg = 0x6
# [360] mode = 0x1 cfg = 0x2
# [400] mode = 0x1 cfg = 0x7
# Coverage = 90.63 %
覆盖点 bins
bins 结构允许为覆盖点变量的可能值的给定范围内的每个值创建单独的bin。