覆盖率
覆盖率有三种:验证计划目标覆盖率、代码覆盖率、功能覆盖率
基于覆盖率驱动的验证方法学主要包括:代码覆盖率和功能覆盖率
1.验证计划目标覆盖率
验证列出的项目要一一的测试:哪些功能点需要检查?这个功能点的哪些数据需要检查?如何对这个数据进行采样?
2.代码覆盖率
通过在仿真器运行过程中自动统计数据生成报告,就是代码覆盖率,该报告只表明哪些部分被测试过,而不能指出设计行为是否正确。
3.功能覆盖率
功能覆盖率在随即激励测试中十分重要,一个测试用例可能会测试到不同的功能点。Systemverilog提供专门的语法实现功能覆盖率验证:
- 面向控制的功能覆盖率:通过cover对断言中的sequence或者property做统计。
- 面向数据的功能覆盖率:在特定的时间点对某些数据使用covergroup做采样统计分析。
Systemverilog的功能覆盖率
通过提供简洁的语法定义功能覆盖率模型:主要包括覆盖组(covergroup).覆盖组的功能类似于类,也包括构造和例化过程。
覆盖组的内容中包括:覆盖点(coverpoint)以及交叉覆盖点(cross)。
其中覆盖点包括分组柜,交叉覆盖点也包括分组柜。
①覆盖组
Covergroup是一个用户自定义类型,可以在module / program / interface / class /package内定义覆盖组:其结构如下代码所示:
moudle cover_group;
bit clk;
bit [1:0] a,b,c;
covergroup cov ()@(posedge clk); //在module中定义名为cov的覆盖组类型()中用于传递参@(posedge)为采样事件
A: coverpoint a; //覆盖组中名为A,B的两个覆盖点。使用coverpoint关
B: coverpoint 键字定义。
C: cross a,b; //覆盖组中名为C的一个交叉覆盖点,使用cross关键字。
endgroup
cov cov1=new();
cov cov2=new(); //例化了cov类型的覆盖组,并调用构造函数为其分配空间。
endmodule
从上述代码可以看出:覆盖组可以定义参数,在例化时传递实参,实参在new的过程中采样;时钟事件定义了采样条件,若不定义时钟采样条件,则需要通过内置采样方法sample().
②覆盖点
1.覆盖点
通过关键字coverpoint来定义一个或多个覆盖点,覆盖点可以是整型变量或者表达式。每个覆盖点内对应一组分组柜,计数器可以用户定义也可以自动创建。
声明:
lable : coverpoint cov_expr iff(expr) //注意显式定义分组柜时此处没有分号
{
bins name[]={}iff(expr);
bins name[]={}iff(expr);
ignore_bins name={};
illegal_bins name={};
} //显式定义分组柜
lable是可选的覆盖点名称,用于层次化引用。若不指定,则仿真器自动分配。
Cov_expr为覆盖点,该点可以是整型变量,也可以是表达式。
Iff结构可以指定采样条件,若条件不成立,则该覆盖点不做覆盖率统计。
{}中的内容为显式定义分组柜,若用户没有定义,则系统自动分配分组柜。自动创建分组柜的最大数目(auto_bin_max)默认为64。
显式定义分组柜的主要目的是:针对某一个覆盖点,我们可能并不关心这个覆盖点的所有范围,而只是关心该点的某个区域或者跳转点,因此可以显示定义分组柜,列出我们关心的范围。
2.分组柜
分组柜使用关键字bins定义:bins name[]={}iff(expr);
一旦显式定义分组柜,系统将不再对覆盖点对象取值范围自动分配分组柜,而只生成用户定义的分组柜。
可以使用defualt关键字将其他数值放到特定的分组柜中。
取值总数/分组柜个数的商是每个分组柜中的成员平均数,多出来的取值放入最后一个分组柜中。
除了可以通过 bins定义普通的分组柜外,systemverilog也提供了非法分组柜(illegal_bins)和可忽略分组柜(ignored_bins),其中归入非法分组柜的数值或者跳转, 若在统计采样的时候出现,仿真器会报告错误,归入可忽略分组柜的数值或者跳转,若在统计采样的时候出现,可以忽略而不做统计,也就是计数器不会递增。
bit [2:0] v
covergroup cov @(posedge clk);
coverpoint v //没有lable和采样条件的覆盖点
{ //数值范围的分组柜
bins a = { [0:63] , 65 } ;
bins b[] = {[127:150], [148:191]};
bins c[] ={200,300,400};
bins d = {[1000:$]};
bins other[] = default;
//注意:不同数字范围的形式的分组柜名称有数组形式b,c,other。和变量形式a,d。
//d定义了数字从1000到1023($代表v的最大值)
//数值跳转的分组柜,使用=>操作符指定数值之间的跳转
bins e = (3=>4=>5); //指定了3=>4=>5这种数值序列变化
bins f = (1,5=>6,7); //1=>6,1=>7,5=>6,5=>7
bins g = (5[*3]); //5的三次连续重复,也就是5=>5=>5=>5
bins anthoers = default_sequence; //其他没有定义的序列放入anothers这个分组柜中
}
endgroup
③交叉覆盖点
若cross指定的交叉覆盖点中的成员是一个变量(未通过coverpoint指定的覆盖点) ,则系统会自动为该变量创建对应的默认的覆盖点;但是成员中不能是未通过coverpoint指定为覆盖点的表达式, 这种情况必须事先为其定义覆盖点。
其语法结构与覆盖点类似,分组柜的个数为成员分组柜个数的乘积。例如:
axb: cross a,b;
变量a具有16个分组柜,变量b有8个分组柜,那么交叉覆盖点axb具有16X8个交叉分组柜。
为此,我们在定义的时候要小心使用交叉覆盖点,以免系统自动创建大量冗余的分组柜,因为每个交叉分组柜都是一个计数器,频繁采样统计,会对仿真速度带来影响。
关键字binsof可以指定表达式生成对应期望的交叉分组柜:
binsof (x) intersect{y}:表示覆盖点和给定表达式y的交集;
!binsof (x) intersect{y}:表示覆盖点x和给点表达式y的交集以外的范围。