1. 覆盖率类型
覆盖率的作用是什么?
衡量设计验证完备性
提高覆盖率的测试方法有哪些?
改变种子,改变约束,创建定向测试
代码覆盖率
- 行覆盖率
- 路径覆盖率
- 翻转覆盖率:比特变量0或1
- 状态机覆盖率:状态机及其状态
衡量执行了设计中的多少代码
代码覆盖率100%是验证工作完备性的必要条件
断言assert覆盖率
什么是断言?
一次性或一段时间对设计信号在逻辑或时序上的声明性代码
用在哪里,用来干嘛?
等效性检查,查找错误,查找感兴趣的信号值或者设计状态
漏洞率曲线
- 追踪每周漏洞
功能覆盖率
- 如名
- 分析覆盖率数据可以决定如何修改回归测试集
- 覆盖率稳步增长,添加新seed或加长测试时间;增速放缓,添加额外约束;停止增长,且设计某些测试点没有被覆盖到,创建新的测试
- 如果覆盖率100%但依然有新的设计漏洞,可能没有覆盖到设计中的某些设计功能区域
2. 功能覆盖策略
收集信息而非数据
- 对MCDF需要关心的是:合法/非法的寄存器地址,可写/不可写的寄存器域
- 设计信号范围过大要拆分成小范围,加上边界情况
只测量需要的内容
- en覆盖率收集会降低很大的仿真性能
- 只测量要用来分析且改进测试的那部分数据,设定合理的覆盖率采样事件
验证完备性
- 完备的覆盖率测量结果和漏洞增长曲线
- 若功能覆盖率高但代码覆盖率低,说明验证计划不完善
- 反之,说明执行了所有代码,但是测试还没有把设计定位到感兴趣的状态
- 目标:两个都高
3. 覆盖组covergroup
什么是覆盖组?
和类相似,一次定义后可以多次例化
有什么特点?
- 可以包含多个coverpoint,且在同一时间采集
- 可以定义在class,intf,module中
- 可以采用任何可见的变量,程序变量,接口信号,设计端口
- 一个class可以包含多个覆盖组
- 可以单独自行en或禁止
- 可以独立定义单独的触发采样事件,允许从多个源头收集数据
- 必须被例化才能收集数据
class transactor;
transaction tr;
mailbox mb_in;
covergroup covport;
coverpoint tr.port;//要采样的变量,也可以定义要采样的数值。用@或者wait实现采样——方式b(借助已有的事件或者信号)
//coverpoint也可以定义名字,见下面的
endgroup
function new(mailbox mb_in);
covport=new();//例化,也可以covport cg1=new();推荐这种命名例化,covport变成类型,可以例化多次
this.mb_in=mb_in;
endfunction
task main;
forever begin
tr=mb_in.get;
ifc.cb.port<=tr.port;
ifc.cb.data<=tr.data;
covport.sample();//完成采样——方式a(显示触发采样,不存在采样时刻的信号或事件,需要单独触发一个例化对象)
end
endtask
endclass
- 如何触发?
- 采样的数据
- 采样数据的事件
4. 数据采样
- coverpoint指定采样一个变量或者表达式时,SV会创建很多仓bin来记录每个数值被捕捉到的次数,这些bin是衡量功能覆盖率1.5的基本单位
- 推荐自己去定义bin,虽然SV会帮我们创建
- covergroup可以定义多个coverpoint,point可以定义多个bin
- 每次group采样都会在bin中留下标记
- 仿真后可以用分析工具读取这些数据库,生成覆盖率报告
- 为了计算一个point上的覆盖率,首先需要确定可能数值的个数,成为域
- 覆盖率=采样值的数目/bin数目
- 覆盖点的覆盖率<覆盖组的覆盖率<整体的功能覆盖率
- 用auto_bin_max指定自动创建bin的最大数目
covergroup covport;
options.auto_bin_max=8;
coverpoint tr.port
{options.auto_bin_max=2;}
endgroup
-
命名coverpoint和bin
covergroup covking; coverpoint tr.king{bins zero={0};//一个仓代表king==0 bins lo={[1:3],5};//一个代表1:3和5 bins hi[]={[8:$]};//8个独立仓表示8到15 bins misc=default;}//1个bin代表剩余的所有值 endgroup
iff给coverpoint添加条件
常用于在复位期间关闭覆盖以忽略不合理的条件触发
也可以用start和stop函数控制覆盖组各个独立实现
翻转覆盖率
- coverpoint可以用来记录变量从A到B的跳转情况
- 可以确定任何长度的翻转次数
covergroup coverport;
coverpoint port{ bins t1=(0=>1), (0=>2), (0=>3);}
//记录变量port从0跳转到1,,2,,3的次数
endgroup
wildcard覆盖率
- 用来创建多个状态或者翻转
- 表达式中任何x,z,?都会被当成0或1的通配符
bit [2:0] port;
covergroup coverport;
coverpoint port{wildcard bins even={3'b??0};//减伤wildcard,变成0和1的通用符号,即任意0或1都可以
wildcard bins odd={3'b??1};}
endgroup
- 某些coverpoint可能始终无法得到全部的域值
- 不计算功能的域值可以用ignore_bins排除,最终不会计入coverpoint的覆盖率
bit [2:0] low_ports_0_5;
covergroup coverport;
coverpoint low_ports_0_5 { ignore_bins hi={[6:7]};}
//忽略数值6-7
endgroup
- 有些采样值不仅要被忽略,出现时应该要报错
- 可以在测试平台中检测,可以用illegal_bins对特定bins标示
bit [2:0] low_ports_0_5;
covergroup coverport;
coverpoint low_ports_0_5 { illegal_bins hi={[6:7]};}
//忽略数值6-7
endgroup
交叉覆盖率cross
- coverpoint是记录单个变量或表达式的观测值
- 作用:记录在某一时刻多个变量之间值的组合情况
- cross只允许+coverpoint或者简单的变量名
class transaction;
rand bit[3:0] kind;
rand bit[3:0] port;
endclass
transaction tr;
covergroup covport;
kind: coverpoint tr.kind;
port: coverpoint tr.port;
cross kind, port;
endgroup
排除部分cross bin
- 使用ignore_bins\binsof\intersect分别制定coverpoint和值域,清楚不关心的cross bin
covergroup covport;
port: coverpoint tr.port { bins port[]={[0:$]};}
kind: coverpoint tr.kind { bins zero={0};//一个仓代表king==0
bins lo={[1:3]};//一个bin代表1:3
bins hi[]={[8:$]};//8个独立仓表示8到15
bins misc=default;}//1个bin代表剩余的所有值
cross kind, port { ignore_bins hi=binsof(port) intersect{7};//排除port为7的所有bin,7对应kind的11个bin
ignore_bins md=binsof(port) intersect{0} && vubsif(kind) intersect{[9:11]}//排除port为0kind为9-11的3个bin
ignore_bins lo=binsof(kind.lo) }//排除kind为1-3,port为0-7的3*7=21个bin
endgroup
精细的交叉覆盖率制定
- 自己声明感兴趣的cross bin
//假设随机变量a和b的三种感兴趣的状态{0,0},{1,0},{?,1}
class transaction;
rand bit a,b;
endclass
covergroup crossbinnames;
a: coverpoint tr.a { bins a0={0};
bins a1={1};
option.weight=0;}//不计算覆盖率
b: coverpoint tr.b { bins b0={0};
bins b1={1};
option.weight=0;}//不计算覆盖率
ab:cross a,b; { bins a0b0=binsof (a.a0) && binsof (b.b0);
bins a1b0=binsof (a.a1) && binsof (b.b0);
bins b1=binsof (b.b1); }
endgroup
//**********************************或者
covergroup crossbinofintersect;
a: coverpoint tr.a { option.weight=0;}
this coverpoint
b: coverpoint tr.b { option.weight=0;}
this coverpoint
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 b1=binsof (b) intersect {1}; }
endgroup
5. 覆盖选项
- 作用:对于多次例化的覆盖组,单独列出每个group实例的覆盖率,需要设置覆盖选项
covergroup coverlength;
coverpoint tr.length;
option.per_instance=1;//单独计算实例的覆盖率
endgroup
- 通过参数对每一个实例传入单独的注释,最终显示在覆盖率报告
covergroup coverport (int lo, hi, string comment);
option.comment=comment;
option.per_instance=1;
coverpotin port {bins range ={[lo:hi]};}
endgroup
................
coverport cp_lo=new(0,3,"low port numbers");
coverport cp_hi=new(4,7,"high port numbers");
at_least修改1个bin的最低采样次数
可以在组中声明影响所有point,也可以在point中声明
option.at_least
goal设置覆盖率目标
covergroup coverport;
coverpoint port;
option.goal=90;
endgroup
一些覆盖组的方法
- sample() 采样
- get_coverage()/get_inst_coverage() 获取覆盖率,返回0-100的real数值
- set_inst_name(string) 设置覆盖组名称
- start()/stop() en或者关闭覆盖率的收集
数据分析
- $get_coverage() 得到总体覆盖率
- covergroup_inst.get_inst_coverage() 获取单个group实例的覆盖率
- 用在一个测试众检测覆盖率的变化
- 如果一段时间后覆盖率水平没有提高,就要停止这个测试,改变seed,改变随机约束
去拍了证件照,第一次对自己的脸产生了怀疑。
晚上总是熬夜打游戏。