覆盖率

覆盖率有三种:验证计划目标覆盖率、代码覆盖率、功能覆盖率

基于覆盖率驱动的验证方法学主要包括:代码覆盖率和功能覆盖率

1.验证计划目标覆盖率

验证列出的项目要一一的测试:哪些功能点需要检查?这个功能点的哪些数据需要检查?如何对这个数据进行采样?

2.代码覆盖率

通过在仿真器运行过程中自动统计数据生成报告,就是代码覆盖率,该报告只表明哪些部分被测试过,而不能指出设计行为是否正确。

3.功能覆盖率

功能覆盖率在随即激励测试中十分重要,一个测试用例可能会测试到不同的功能点。Systemverilog提供专门的语法实现功能覆盖率验证:

  1. 面向控制的功能覆盖率:通过cover对断言中的sequence或者property做统计。
  2. 面向数据的功能覆盖率:在特定的时间点对某些数据使用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的交集以外的范围。