覆盖率是一个量化指标,用于判定验证的进度。
覆盖率指的是满足条件的验证对象所占的比例,有两种覆盖率的尺度,分别为:
代码覆盖率指的是设计代码有多少被验证了。包括设计模块designblock的执行、代码行数,条件分支,有限状态机、翻转和路径,仿真器可以自动的从设计代码中提取代码覆盖率。
功能覆盖率是用户自定义的尺度,用来测量design sepcification多少被测试了。功能实质上由信号的值来表示,如实际问题我们会通过状态机编码来解决,因此功能覆盖率我们可以通过采样信号的值,看它是否出现了所有可能的值。
功能覆盖率的模型是通过Covergroup结构来定义的。这个结构只需要定义一次,可以在不同的语境下创建多个实例。和类是类似的,一旦被定义,我们需要使用new()操作符来创建实例,covergroup可以在module,program,interface或者类中。每个covergroup可以包括:
covergroup cov_grp @(posedge clk);
cov_p1: coverpoint a;
endgroup
cov_grp cov_inst = new();
上面例子中,覆盖组cov_grp的时钟事件为clk上升沿,覆盖点为a。
covergroup cov_grp;
cov_p1: coverpoint a;
endgroup
cov_grp cov_inst = new();
@(abc) cov_inst.sample();
上面例子表明可以在覆盖组外面定义时钟事件,通过方法sample进行采样。
class myTrns;
rand bit [3:0] mode;
rand bit [1:0] key ;
function display();
$display("[%0tns] mode = 0x%0h, key = 0x%0h", $time, mode, key);
endfunction
covergroup display();
coverpoint mode{
bins featureA = {0};
bins featureB = {[1:3]};
bins common[] = {4:$};
bins reserve = default;
}
coverpoint key;
endgroup
endclass
再看一个类内实例,类myTrns中有两个随机变量mode和key,在覆盖组中定义了覆盖点mode,理论上随机变量mode 4bit,共有16中取值,即0-15,通过bins关键词将取值规划为不同的feature特征。
一个覆盖组里面可以包含一个或者多个覆盖点,一个采样点可以是一个整数变量也可以是一个整型表达式。每个采样点都和一个“bin”联系在一起,在每个采样时钟,仿真器都会增加这个bin的值。bins可以自动创建,也可以显示定义。
module cov;
logic clk ;
logic [7:0] addr ;
logic wr_rd ;
covergroup cg @(posedge clk);
c1: coverpoint addr;
c2: coverpoint wr_rd;
endgroup:cg
cg cover_inst = new();
...
endmodule
上面的例子中,addr共有256种取值,工具会自动创建bins。c1.auto[0] c1.auto[1] c1.auto[2] … c1.auto[255]
for wr_rd: c2.auto[0]。
除了默认指定之外,我们也可以通过bins关键字来显示的指定一个变量的bins。
如上面的例子所示,当addr = 0,2,7时,b1会自增。b2[3]创建了三个bins,即b2[0],b2[1],b2[2]。他们对应的取值分别为(11,12,13),(14,15,16),(17,18,19,20),平分取值。当b3为30-40,50-60,77这些值的时,b3会自增。b4也创建了三个bins,其中逗号隔开,其中b4[0]为79:99会自增,b4[1]为110:130会自增,140时b4[3]会递增。
bins除了指定数值之外,还可以使用序列作为一个bins。用序列表示时使用=>表示先后关系。比如value1=>value2,它表示覆盖点的值从数值1到数值2的转换。在上面的例子种,b1当addr的值从10变到20,再到30的时候递增。b2则是创建了两个bins,通过逗号来区分不同的元素。b3递增的条件有四种,即b3 = 1=>6 or 1=>7 or 5=>6 or 5=>7。
我们还可以排除一些不可能的bins,通过ignore_bins指定。还可以指定不合理的bins,通过illegal_bins指定。