system verilog (九) 功能覆盖率

功能覆盖率:用来衡量哪些设计特征已经被测试程序测试过的一个指标
首要的选择是使用更多的种子来运行现有的测试程序;其次是建立新的约束,只有在确实需要的时候才会求助于定向测试
在这里插入图片描述
在这里插入图片描述
(1)通过改变随机种子,就可以反复运行同一个随机测试平台来产生新的激励;每次仿真都会产生一个带有覆盖率信息的数据库,将这些信息合并在一起可以得到功能覆盖率。
(2)如果覆盖率增速减缓,需要添加额外的约束来产生更多的激励;当覆盖率稳定下来,而设计的某些设计尚未被测试过,这时需要创建更多的新的测试,
(3)最后在功能覆盖率接近100%时检查错误率

1、代码覆盖率:测试对于设计规范的实现究竟测试得多彻底,而非针对验证计划;(多少行代码已经被执行过(行覆盖率),在穿过代码和表达式中的路径中有哪些已经被执行过(路径覆盖率),单比特变量的值是0或1(翻转覆盖率),状态机中有哪些状态和状态转换被访问过(有限状态机覆盖率)

2、功能覆盖率:和设计意图紧密相连,而代码覆盖率是衡量设计的实现情况。如果某个代码块在设计中被漏掉的情况,代码覆盖率不能发现这个错误,但功能覆盖率可以。

3、漏洞率
在这里插入图片描述
4、断言覆盖率:断言是用于一次性或在一段时间内核对两个设计信号之间关系的声明性代码;可以跟随设计和测试平台一起仿真,也可以被形式检查工具所证实。(断言最常见于查找错误,例如两个信号是否互斥或者请求是否被许可;一旦检测到问题,仿真就会立刻停止。断言也可以用于检查仲裁算法、各种FIFO以及其他硬件,这些情况使用assert property语句)

在这里插入图片描述
一个简单对象的功能覆盖率

program automatic test(busifc.TB ifc);
class Transaction;
rand bit[31:0]data;
rand bit[2:0]port;
endclass

covergroup Covport;
coverpoint tr.port;
endgroup

initial
begin
Transaction tr;
CovPort ck;
ck=new();
tr=new();
repeat(32)begin
assert(tr.randomize);//创建一个事务
ifc.cb.port<=tr.port;
inc.cb.data<=tr.data;
ck.sample();
@ifc.cb;
end
endprogram

改进功能覆盖率最简单的方法是仅仅增加仿真时间或者尝试新的随机种子
在这里插入图片描述
覆盖组(与类相似,一次定义后便可进行多次实例化)含有覆盖点、选项、形式参数和可选触发,一个覆盖组包含一个或多个数据点,在同一时间采集;可以定义在类中,也可以定义在程序或模块层次上,可以采样任何可见的变量;一个类中可以包含多个覆盖组,每个组根据需要自行使能或禁止。此外每个组可以有单独的触发,允许从多个源头收集数据。

在类中定义覆盖组:
在这里插入图片描述
在这里插入图片描述
覆盖组的触发:功能覆盖率的两个主要部分是采样的数据和数据被采样的时刻,当这些数据都准备好之后,测试平台就会触发覆盖组(通过使用sample函数来完成,或者在covergroup的定义中使用阻塞表达式,阻塞表达式可以使用wait或@来实现在信号或事件上的阻塞。

event trans_ready;
covergroup CovPort@(trans_ready);
coverpoint ifc.cb.port;
endgroup

与直接调用sample方法相比,使用事件触发的好处在于能够借助已有的事件

使用sv断言进行触发:

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

在这里插入图片描述
当你在覆盖点上指定一个变量或表达式时,sv便会创建很多“仓bin”来记录每个数值被捕获到的次数(这些仓是衡量功能覆盖率的基本单位),在每次仿真的末尾,所有带标记的仓会被汇集到一个新创建的数据库中。
为了计算一个点上的覆盖率,首先必须确定所有可能数值的个数,即域;覆盖率就是采样值的数目除以域中仓的数目。(sv会自动为覆盖点创建仓;其中覆盖组选项auto_bin_max指明了自动创建仓的最大数目,缺省值为64)
例如:使用auto_bin_max并将仓数设置成2

covergroup CovPort;
coverpoint tr.port
{options.auto_bin_max=2;}
endgroup

此时,八个port值被映射到两个bin里面。而且每个bin都有采样值
在这里插入图片描述
对表达式进行采样(需要核对报告以确保能够得到预期的值)
例如:对一个3bit加4bit的加法表达式进行采样,只能得到16个仓,但是数据实际上可以达到0:23个字节,仓数可能不够;可以使用额外常量的表达式可以计算达到5bit精度
在这里插入图片描述
自动生成的仓适用于匿名数值,如计数值、地址值或2的幂值,而对于其他数值,应该明确对仓命名,以增加准确度
例如:上例可改写成

covergroup CovLen;
len:coverpoint(tr.hdr_len+tr.payload_len+5'b0)
{bins len[]={[0:23]};
endgroup

只当覆盖点的仓名
在这里插入图片描述
条件覆盖率:使用关键字iff给覆盖点添加条件(常用于在复位期间关闭覆盖以忽略掉一些杂散的触发)
在这里插入图片描述
同样地,可以使用start和stop函数来控制覆盖组中独立的实例
在这里插入图片描述
对于枚举类型,sv会为每个可能值创建一个仓

typedef enum {INIT,DECODE,IDLE}fsmstate_e;
fsmstate_e pstate,nstate;
covergroup cg_fsm;
coverpoint pstate;
endgroup

在这里插入图片描述
翻转覆盖率:先确定覆盖点状态转移的次数(不但知道那些值出现过,而且知道这些值的变化过程)

covergroup CoverPort;
coverpoint port{
bins t1=(0=>1),(0=>2),(0=>3);
}
endgroup

使用范围表达式可以确定多个转换过程;表达式(1,2=>3,4)创建四个翻转过程
还可以确定任何长度的翻转次数,例如:(0=>1=>1=>1=>2);可以使用缩略形式
(0=>1[*3]=>2)

在状态和翻转中使用通配符:可以使用关键字wildcard创建多个状态或翻转,在表达式中,任何X、Z或?都会当成0或1的通配符
在这里插入图片描述
除了使用明确定义仓来涵盖所有的期望值,也可以让sv自动创建仓,然后使用ignore_bins排除掉那些不用来计算功能覆盖率的值
在这里插入图片描述

不合法的仓:有些采样值不仅不应该出现,而且如果出现还应该报错,可以使用illegal_bins对仓进行标识。
在这里插入图片描述
交叉覆盖率:可以同时测量两个或两个以上的覆盖点的之,如果一种由N种取值,另一个有M种取值,需要N X M交叉仓来存储所有的组合。

class Transaction;
rand bit [3:0]kind;
rand bit[2:0] port;
endclass

Transaction tr;

covergroup CovPort;
kind:coverpoint tr.kind;
port:coverpoint tr.port;
cross kind,port;
endgroup

如果需要让交叉覆盖仓的名称更具有可读性,还可以对各个覆盖点的仓进行单独标号。
在这里插入图片描述
使用ignore_bins可以减少仓的数目,在交叉覆盖中,可以使用binsof和intersect分别指定覆盖点和数值集
在这里插入图片描述
设置权重,或者不需要某些变量可以将权重设置成0
在这里插入图片描述
sv允许创建一个通用的覆盖组,这样在对它进行实例化时就可以指定一些独特的细节,可以把覆盖组放到一个类,然后把触发参数传递给构造函数。
在这里插入图片描述
覆盖率数据的分析
事务长度分布不均匀
在这里插入图片描述
在这里插入图片描述
可以使用solve…before约束
在这里插入图片描述
在这里插入图片描述
可以get_coverage() (带覆盖组名和实例,用于给出一个覆盖组所有实例的覆盖率)和get_inst_coverage()(返回一个特定覆盖组的实例的覆盖率)

发布了64 篇原创文章 · 获赞 5 · 访问量 3188

猜你喜欢

转载自blog.csdn.net/buzhiquxiang/article/details/104338548