SystemVerilog 第9章 功能覆盖率
9.1 覆盖率的类型
- 覆盖率:验证完成程度的衡量指标
- 覆盖率收敛flow
9.1.1 代码覆盖率
- 代码覆盖率:衡量TB对RTL执行的彻底程度
- 代码覆盖率种类:
line(行覆盖率)
branch(分支覆盖率):条件语句的每一个分支
tgl(翻转覆盖率)
fsm(状态机):①所有状态遍历②所有状态的转移情况
cond(条件覆盖率):进入条件语句分支的可能条件
9.1.2 功能覆盖率
- 功能覆盖率:衡量哪些设计特征通过了测试的指标
- 设计规范说明设备如何运行;验证计划列出响应功能应该如何激励、验证和测量
- 设计功能的遗漏可以通过功能覆盖率发现
9.1.3 漏洞率
- 漏洞率:衡量覆盖率的间接方式
9.1.4 断言覆盖率
- cover property语句用于观测信号序列;cover group用于对仿真过程中的事务和数值进行采样
9.2 功能覆盖策略
9.2.1 收集信息而非数据
9.2.2 只测有用信息
9.2.3 测量的完备性
- 同时取得很高的代码和功能覆盖率
9.3 功能覆盖率的简单例子
9.4 覆盖组
- covergroup和class类似,使用时需要进行声明和实例化(class中定义的只实例化即可使用)
- covergroup含有coverpoint, 选项(option), 形参, 可选触发(trigger)
- covergroup中的coverpoint在采集时候同时触发
- covergroup可以定义在module, program和class中
9.4.1 类中定义covergroup
- class中的covergroup使用时,可以不用声明直接实例化
- covergroup创建&声明&实例
class Transactor;
Transaction tr;
mailbox mbx;
virtul bus_ifc ifc;
covergroup covport;
coverpoint tr.port;
endgroup
function new(mailbox mbx,virtual bus_ifc ifc);
covport = new();
this.ifc = ifc;
this.mbx = mbx;
endfunction
task main();
mbx.get(tr);
ifc.cb.data <= tr.data;
ifc.cb.port <= tr.port;
covport.sample();
endtask
endclass
9.4.1 program中定义covergroup
- covergroup创建&声明&实例
program test(bus_ifc.TB ifc);
...
Transaction tr;
covergroup covport
coverpoint tr.port;
endgroup
covport cp;
initial begin
cp = new();
assert(tr.randomize());
cp.sample();
end
endprogram
9.5 覆盖组的触发
- 功能覆盖率的两个主要部分:
①采样的数据
②采样的时刻 - 触发coverport方式有二(只能二选一):
①sample()函数直接采样
②covergroup定义是采用阻塞表达式(wait/@ 等待event或信号)
9.5.1 使用回调函数进行采样
need update
9.5.2 使用事件触发
event trans_ready;
covergroup covport @(trans_ready);
coverpoint tr.port;
endgroup
9.5.3 使用SV断言进行触发
- cover property 检查断言是否成立(成立一次即可)
- 格式
cover property(property块) action_block;
module mem(...);
...
event write_event;
cover property(@(posedge ifc.clk) ifc.write_en == 1)
-> write_event;
...
endmodule
program test(...);
covergroup write_cg @($root.top.m1.write_event);
coverpoint ifc.data;
coverpoint ifc.port;
endgroup
endprogram
9.6 数据采样
- 仓是衡量功能覆盖率的基本单位
9.6.1 总体覆盖率
- 总体覆盖率=covergroup覆盖率之和(covergroup覆盖率=其对应的coverpoint覆盖率之和)
- coverpoint覆盖率=采样到的数目/域中仓的数目(所有可能的取值称为域)
9.6.2 自动创建仓
- SV会自动创建仓,当可能取值过大时只会建64个仓,并将变量取值平均分配到这些仓中
9.6.3 限制自动建仓上限
- 可用于covergroup或者coverpoint
covergroup covport;
options.auto_bin_max = 8;
coverpoint tr.port {
options.auto_bin_max = 2;
}
endgroup
9.6.4 对表达式采样
- 为每个coverpoint增加标识可以提高覆盖率报告的可读性
- 注意表达式最终的位宽溢出以及域的取值过大问题
9.6.5 自定义的仓
- 命名仓最简单的方式是使用[]
9.6.6 命名覆盖点的仓
coverpoint tr.kind{
bins neg = {[$:-1]}; //负的最小值到-1
bins zero = {0};
bins lo = {[1:3],5}; //1~3,5共4个取值
bins hi[] = {[8:$]}; //8到最大取值
bins misc = default; //捕捉剩下的取值
}
9.6.7 条件覆盖率
- iff:当条件满足时使能coverpoint
covergroup covport;
coverpoint port iff(!bus_if.reset);
endgroup
- 使用 inst.stop()/inst.start() 是能covergroup
9.6.8 为枚举类型建仓
- SV默认为枚举类型每一个取值建一个仓
- auto_bin_max的值对枚举类型不起作用
9.6.9 翻转覆盖率
coverpoint port {
bins t1 = (0=>1),(0=>2),(0=>3); //三个跳转
bins t2 = (1,2=>3,4); //共四个跳转
bins t3 = (0=>1[*3]=>2); //有三个1
bins t4 = (0=>1[*3:5]=>2); //有3~5个1
}
9.6.10 使用通配符
- wildcard可以用来创建使用通配符的状态或者翻转
- x,z,?都被看作时0或1的通配符
coverpoint port {
wildcard bins even = {3'b??0};
wildcard bins odd = {3'b??1};
}
9.6.11 忽略仓
- ignore_bins用于排除不用的取值
coverpoint low_ports {
ignore_bins hi = {6,7};
}
9.6.12 不合法仓
coverpoint low_ports {
illegal_bins hi = {6,7};
}
9.6.13 状态机覆盖率
- 使用代码覆盖率工具来提取状态寄存器、状态以及翻转轨迹
9.7 交叉覆盖率
- 交叉覆盖率用于统计不同变量之间的组合情况
- 交叉覆盖率的建仓不受auto_bin_max影响(没有上限)
9.7.1 基本的cross
covergroup covport;
kind: coverpoint tr.kind;
port: coverpoint tr.port;
cross kind, port;
endgroup
9.7.2 对交叉覆盖仓标号
- 可以对cross中交叉覆盖点成员的仓进行命名,一遍覆盖率报告的可读性
- 可以对cross覆盖点命名,格式同coverpoint
9.7.3 排除掉部分交叉覆盖仓
cross kind,port {
igonre_bins hi = binsof(port)intersect{7}; //参数为coverpoint名&变量取值
igonre_bins lo = binsof(kind.lo); //参数为仓
}
9.7.4 排除覆盖点
- 可以使用权重忽略覆盖点的采样
port: coverpoint tr.port {
bins port[] = {[0:$]};
option.weight = 0;
}
9.7.5 从多个值域中合并数据
- 将信号拷贝到变量中,然后新建覆盖组对其进行采样
9.7.6 交叉覆盖率的自定义仓
- 使用 binsof()
ab: cross a,b {
bins a0b0 = binsof(a.a0) && binsof(b.b0);
}
- 使用 binsof() intersect{}
ab: cross a,b {
bins a0b0 = binsof(a) intersect{0} && binsof(b) intersect{0};
}
- 使用变量串联值(变量拼接)
ab: coverpoint{tr.a,tr.b} {
bins a0b0 = {2'b00};
bins a1b0 = {2'b10};
wildcard bins b1 = {2'b?1};
}
9.8 覆盖组端口
9.8.1 数值参数
covergroup covport(int mid)
coverpoint port {
bins lo = {[0:mid-1]};
bins hi = {[mid:$]};
}
endgroup
9.8.2 ref参数
- 引用方式传入的不能时常数,只能是变量
covergroup covport(ref bit[2:0] port, int mid);
coverpoint port{
bins lo = {[0:mid]};
bins hi = {[mid:$]};
}
endgroup
9.9 覆盖选项
- 选项可以放在覆盖组中对所有coverpoint有效,也可以放在coverpoint中对单个coverpoint有效
- options.auto_bin_max = 8;
- option.weitht = 0;
9.9.1 单个实例覆盖率
- per_instance 只能用在覆盖组里,不可用于覆盖点和交叉点
- option.per_instance = 1;
9.9.2 覆盖组注释
- 为一个覆盖组指定注释
covergroup covport;
type_option.comment = "xxx";
coverpoint port;
endgroup
- 为每一个实例指定注释(同时使用per_instance=1)
covergroup covport(string comment);
option.comment = comment;
option.per_instance = 1;
coverpoint port;
endgroup
9.9.3 覆盖阈值
- option.at_least = 2; //类似auto_bin_max
9.9.4 打印空仓
- option.cross_num_print_missing = 1000; //报告工具打印出没有被命中的仓
9.9.5 覆盖率目标
- option.goal = 90; //默认为100%
9.10 覆盖率数据分析
- 采用更多的种子,更少的约束
- 希望表达式取值为平均分布,可以采用solve…before…进行干预
9.11 仿真中统计覆盖率
- $get_coverage() //打印所有覆盖组的总覆盖率
- covport::get_coverage() //返回一个覆盖组的覆盖率
- inst.get_inst_coverage() //返回一个实例的覆盖率,同时需要指定per_instance=1