目录
1覆盖率的类型
概述
代码覆盖率
断言覆盖率
漏洞率曲线
功能覆盖率
2 功能覆盖率策略
3 覆盖组Covergroup
covergroup概述
covergroup的采样触发
4 数据采样
概述
bin的创建和应用
命名coverpoint和bin
条件覆盖率
翻转覆盖率
wildcard覆盖率
忽略的bin和非法的bin
交叉覆盖率
更精细的交叉覆盖率指定
5 覆盖选项
6 数据分析
(概述 覆盖率反馈回路 代码覆盖率 断言覆盖率 漏洞率曲线 功能覆盖率)
代码覆盖率用于衡量你执行了多少设计代码,关注点在设计代码上,而不是测试平台。
仿真工具会自动通过分析源代码和增加隐藏代码来自动完成代码覆盖率统计。代码覆盖率100%,并不意味着验证工作已经完成,它只是验证工作完成的必要条件。
主要包含
在一个项目中,应保持追踪每周的漏洞数量。每次漏洞下降时,就应寻找不同的办法取测试可能的边界情况。
在临近流片时,漏洞率会下降,甚至为0,但漏洞率如果出现意外情况,可能预示着潜在的问题
验证的目的就是确保设计在实际环境中的行为正确,功能覆盖率和功能设计示意图是紧密相连的,有时也被称为“描述覆盖率”,而代码覆盖率则是衡量设计的实现情况。
若某个功能在设计中遗漏,代码覆盖率是不能发现这个错误,但功能覆盖率可以发现。
通过分析覆盖率数据就可以决定如何修改递归测试集,
在动手写测试代码前,我们需要预先弄清楚相关设计的关键特性,边界情形和可能的故障模式。不要只考虑数据数值等内容,相反地,要考虑到设计所包含的信息。
收集信息而非数据
只测量需要的内容
验证的完备性
covergroup由采样的数据和数据被采样的事件构成,当两个条件准备好之后,采样便会被触发。
方式一:使用sample()函数,显示的触发覆盖组
//采样方式1,显示的触发
covergroup Coverport; // 类型
coverpoint tr.port; //需要采样的变量port
endgroup
Coverport = new(); //直接实例化覆盖组
Coverpoint cgl = new(); //cgl为实例名,推荐该方法例化
cgl.sample(); //采样
方式二:可借助已有事件触发采样,使用wait或@;
//采样方式2,使用事件触发
event a;//定义时间
covergroup Coverpoint @(a); //采样触发
coverpoint ifc.cb.port;
endgroup
sv会自动为某个coverpoint创建bin,但推荐自定义bin的采样区域。
如果采样变量的域范围过大而又没有指定bin,那么系统会默认分配一个64个bin,将值域范围平均分配给这64个bin。可以使用covergroup的选项auto_bin_max来指定自动创建bin的最大数目
//覆盖组选项auto_bin_max
covergroup CovPort;
options.auto_bin_max = 8; //所有coverpoint auto_bin数量为8
coverpoint tr.port;
{options.auto_bin_max = 2;} //特定的coverpoint auto_bin为2,其余还是8
endgroup
//大括号结尾没有分号
covergroup CovKind;
coverpoint tr.kind{
bins zero = {0}; //一个仓代表kind=0,其中bins关键字,zero仓的名称
bins lo = {[1:3],5}; //一个仓代表1,2,3,5
bins hi[] = {[8:$]}; //8个独立的仓分别代表8-15,$代表上限
bins misc = default; //1个仓代表所有剩余的值
} // 没有分号
endgroup
coverpoint定义使用{}而不是begin...end,是声明性代码而非程序性代码,所以结尾没有分号。
使用关键词iff给coverpoint添加条件
也可以使用start和stop函数来控制covergroup各个实例
covergroup Coverport;
coverpoint port iff
(!bus_if.reset); //只收集reset为0时的覆盖率数据
endgroup
initial begin
Coverport ck = new();
#1ns ck.stop(); //复位期间不搜集覆盖率
bus_if.reset= 1;
#100ns bus_if.reset = 0;//复位结束
ck.start(); //开始采样
ck.sample(); //调用sample
end
记录变量从A值到B值的跳转情况
covergroup CovPort;
coverpoint port{
bins t1 = (0=>1),(0=>2),(0=>3); //一个仓,满足任何一个跳转就会记录一次
}
endgroup
使用关键字wildcard可创建多个转态或跳转,在表达式中x,z或者?会作为0或1的通配符使用
bit [2:0] port;
covergroup CovPort;
coverpoint port {
wildcard bins even = {3'b??0}; // 偶数仓
wildcard bins odd = {3'b??1}; //奇数仓
}
endgroup
对于那些不需要的域值可以使用ignore_bins来排除,最终它们就不会计算在覆盖率中
进一步地,若有些采样值不仅应忽略,若出现时还应报错,则可以使用illegal_bins进行标志
coverpoint low_ports_0_5{
ignore_bins hi = {[6:7]}; //忽略6-7
}
coverpoint low_ports_0_5{
illegal_bins hi = {[6:7]}; //如果出现便报错
}
coverpoint是记录单个变量或者表达式的观测值,若需要记录多个变量之间的组合情况,需要使用交叉覆盖率(cross)
class Transaction;
rand bit [3:0] kind;
rand bit [2:0] port;
endclass
transaction tr;
covergroup Covport;
kind : coverpoint tr.kind;//kind为该coverpoint的名称
port : coverpoint tr.port;
cross kind,port;//交叉覆盖,sv共创了128个仓(8*16)
endgroup
还可使用ignore-bins 、binsof和intersect分别指定coverpoint和值域,这样可清除不关心的cross bin
cross kind, port{
ignore_bins hi = binsof(port) intersect{7};//排除port为7的取值
}
随着cross覆盖率越来越精细,使用ignore_bins来指定需要忽略的值较为繁琐;更适合的方式是自己声明感兴趣的cross bin.
假设两个随机变量a,b有三种感兴趣的状态{a==0,b==0},{a==0,b==1},{b==1},则可以有三种方式进行覆盖率收集
//方式3,使用串联值来代替交叉覆盖率
covergroup CrossManual;
ab:coverpoint {tr.a, tr.b} //
{bins a0b0 = {2b'00};
bins a1bo = {2b'10};
wildcard bins b1 = {2b'?1};
}
endgroup
(单个实例的覆盖率、注释、覆盖次数限定、覆盖率目标、covergroup方法)
实例说明
covergroup CoverLegth(int hi,lo, string comment);//传入comment
option.comment = comment;//设置注释
option.goal = 90; //覆盖率目标设为90,默认情况是100
option.per_instance = 1;//单独列出每个实例的覆盖率
coverpoint port{
{bins range {[lo:hi]};
}
endgroup
...
Coverlength cp_lo = new(0,3,"Low port numbers"); //注释内容
Coverlength cp_lo = new(2,3,"Hign port numbers");