代码覆盖率:
- 路径覆盖率:在穿过代码和表达式的路径中有哪些已经被执行过
- 行覆盖率: 源代码中每一行代码是否被执行至少一次
- 翻转覆盖率:哪些单比特变量的值为0或1
- 有限状态机覆盖率:状态机中哪些状态和状态转换已经被访问过
语句覆盖率不仅包括行覆盖率,还可能包括条件语句中的多个分支
断言覆盖率:测试中被触发的断言数量与总断言数量的比例
功能覆盖率:
验证计划中应该弄清楚相关设计的关键特性、边界情形和可能的故障模式;计划应该把有影响的设计状态描述清楚;
覆盖组的触发:
一般情况下,覆盖组都要进行明确的实例化才可以开始采样;如果覆盖组定义在类里,实例化时使用最初的名字即可,不用另外起名字;
使用sample()函数触发覆盖组;
使用事件触发的覆盖组:
使用断言进行触发
例9.9 带SystemVerilog断言的模块
module mem(simple_bus sb):
bit [7:0] data, addr;
event write_event;
cover property
(@(posedge sb.clock) sb.write_ena == 1)
-> write_event;
endmodule
例9.10 使用SVA触发覆盖组
program automatic test(simple_bus sb);
covergroup Write_cg @(sroot.top.ml.write_event);
coverpoint sroot.top.ml.data;
coverpoint sroot.top.ml.addr;
endgroup: Write_cg
initial begin
Write_cg = new();
end
endprogram
默认自动建仓64
{option.auto_bin_max= ;}在覆盖点内使用则是规定这个覆盖点
option.auto_bin_max= ;在覆盖组内使用则是规定这个覆盖组内的所有覆盖点
option.auto_bin_max对枚举类型没用
自定义覆盖点的仓
covergroup CovKind;
coverpoint tr.kind(
bins zero = {0}; // 1个仓代表kind=0
bins 10_3_5 = {[1:3], 5}; // 1个仓代表1到3和5的值
bins hi[] = {[8:$]}; // 8个独立的仓:8到15
bins misc = default; // 1个仓代表剩余的所有值
) // 没有分号
endgroup // CovKind
运用iff和start()和stop()控制覆盖组
例9.20 条件覆盖 - 复位期间禁止
covergroup CoverPort;
// 当reset_a=1时不要收集覆盖率数据
coverpoint port iff(!bus_if.reset);
endgroup
同样地,你也可以使用start和stop函数来控制覆盖组里各个独立的实例。
例9.21 使用start和stop函数
initial begin
CovPort ck = new();
// 实例化覆盖组
// 复位期间停止收集覆盖率数据
#1ns ck.stop();
bus_if.reset = 1;
#100ns bus_if.reset = 0; // 复位结束
ck.start();
...
end
对于枚举类型,SV会为每一个可能得值创建一个仓;如果想多个数值放到单个仓里,那就必须自己定义仓;
翻转覆盖率:
例9.24 确定覆盖点的翻转次数
covergroup CoverPort;
coverpoint porti
bins t1 = (0 => 1), (0 => 2), (0 => 3);
endgroup
使用范围表达式可以快速地确定多个转换过程。表达式[1, 2 => 3, 4]创建了四个转换过程,分别是(1 => 3)、(1 => 4)、(2 => 3)和(2 => 4)。
还可以确定任何长度的翻转次数。注意必须对转换过程中的每个状态都进行一次采样。所以(0 => 1 => 2)不同于(0 => 1 => 1 => 2)和(0 => 1 => 1 => 1 => 2)。如果你需要像最后一个式子那样重复数值,可以使用缩略形式:from:(0=>1[*3]=>2)。如果需要对数值1进行3次、4次或5次重复,那么使用1[*3:5]。
使用关键字wildcard定义bins 在表达式中任何X、Z或?都会被当成0或1的通配符
可以使用igonre_bins来排除掉那些不用来计算功能覆盖率的值;
使用illegal_bins可以捕捉到错误检查程序遗漏掉的状态;同时如果出现不合法的数值,程序会出现报错;
交叉覆盖率:
covergroup CovPortKind;
port: coverpoint tr.port
{
bins port[] = {[0:$]};
}
kind: coverpoint tr.kind
{
bins zero = (0); // 1个仓代表kind=0
bins ten = ([1:3]); // 一个仓代表1到3的值
bins hi[] = {[8:$]}; // 8个独立的仓
bins misc = default; // 1个仓代表剩余的所有值
}
cross kind, port;
endgroup: CovPortKind
在交叉覆盖中排除掉部分bin
cross kind, port {
ignore_bins hi = binsof(kind) intersect {[7]};
ignore_bins md = binsof(port) intersect { 0 } &&
binsof(kind) intersect {[9:11]};
ignore_bins lo = binsof(kind.lo);
}
endgroup
使用option.weight指明覆盖率的权重
例9.34指明交叉覆盖率的权重
covergroup CovPort :
kind: coverpoint tr.kind
{
bins zero = {0};
bins lo = {[1:3]};
bins hi[] = {[8:$]};
bins misc = default;
option.weight = 5; // 在总体中所占的分量
}
port: coverpoint tr.port
{
bins port[] = {[0:$]};
option.weight = 0; // 在总体中不占任何分量
}
cross kind, port
{option.weight = 10;} // 给予交叉更高的权重
endgroup: CovPort
ab: cross a, b {
bins a0b0 = binsof(a.a0) && binsof(b.b0);
bins a1b0 = binsof(a.al) && binsof(b.b0);
bins bl = binsof(b.bl);
}
ab: cross a, b {
bins a0b0 = binsof(a) intersect (0) &&
binsof(b) intersect (0);
bins a1b0 = binsof(a) intersect (1) &&
binsof(b) intersect (0);
bins bl = binsof(b) intersect (1);
}
覆盖组选项:
单个实例覆盖率:
如果一个覆盖组被实例化多次,那么缺省情况下,sv会把所有实例的覆盖率整合到一起;
想要查看单个实例的覆盖率,可以在覆盖组中使用option.pre_instancen = 1 ;
pre.instance只能用于覆盖组,不能用于覆盖点或交叉点;
注释:
option.comment = “”;为覆盖组增加注释字符串;(在使用pre_instance的前提下使用);
type_option.comment(当覆盖组只例化了一次时使用,若要为多个实例进行单独注释,要使用pre_instance)
覆盖阈值:
option.at_least
如果定义在覆盖组,那么作用于所有覆盖点;若定义于点内,只对该点有效;
打印空仓:
Option.cross_num_print_missing= ;
constraint块变量处理顺序:
solve ...before
获得覆盖率:
get_coverage()和get_inst_coverage()