SystemVerilog学习笔记(十)


# 1. 覆盖率 ## 1.1 概述 覆盖率是衡量验证完备性的一个通用词语,用来衡量设计中已经被测部分和未测部分的比例,通常被定义为已达到所需验证部分的百分比。 ## 1.2 分类 ### 按照覆盖率生成方法 * 隐性生成 * 显性生成 ### 按照覆盖率溯源 * 从功能描述而来 * 从设计实现而来 功能覆盖率是显性的需要人为定义的覆盖率,而代码覆盖率则是隐性覆盖率这是因为仿真工具可以自动从RTL代码来生成。 将上述两个分类的方式进行组合,那么可以将代码覆盖率、断言覆盖率以及功能覆盖率分别置入到不同的象限。
但是需要注意,目前有一个象限仍然处于研究阶段,没有隐性的可以从功能描述生成某种覆盖率的方法,这也是为什么功能覆盖率依然需要人为定义的原因。 # 2. 两种主要覆盖率 ## 2.1 代码覆盖率 * 跳转覆盖率:用来衡量寄存器跳转的次数(0→1,1→0) * 行覆盖率:用来衡量源代码哪些代码行被执行过,以此来指出哪些代码行没有被执行过 * 分支覆盖率:分支覆盖率是用来对条件语句( if/else,case,?:),指出其执行的分支轨迹。 * 条件覆盖率:条件覆盖率是用来衡量一些布尔表达式中各个条件真伪判断的执行轨迹。 * 状态机覆盖率:每个状态的进入次数,状态之间的跳转次数,以及多个状态的跳转顺序都可以由仿真工具记录下来。

2.2 功能覆盖率

概述

我们无法通过代码覆盖率得知要求的功能是否被实现,需要显性地通过功能覆盖率与设计功能描述做映射,继而量化功能验证的进程。
创建功能覆盖率模型需要完成以下两个步骤:

  • 从功能描述文档提取拆分需要测试的功能点
  • 将功能点量化为与设计实现对应的SV功能覆盖代码

覆盖组(covergroup)

  • 覆盖组与类相似,在一次定义以后便可以多次进行例化。
  • 覆盖组含有覆盖点(coverpoint)、选项(option)、形式参数(argument)和可选触发(trigger event)
  • 一个覆盖组包含了一个或者多个数据点,全都在同一时间采集。
  • 覆盖组可以定义在类里,也可以定义在模块或者程序(program)中。
class xyz;
    bit [3:0] m_;int m y;
    bit m_z;
    covergroup cov1 @m_z; ll embedded covergroup
        coverpoint m_x;
        coverpoint m_y;
    endgroup
    function new() ; cov1 = new ; endfunction
endclass
  • 覆盖组可以采集任何可见的变量,比如程序或模块变量、接口信号或者设计中的任何信号
  • 在类中的覆盖组也可以采集类的成员变量·覆盖组应该定义在适当的抽象层次上
  • 对任何事务的采样都必须等到数据被待测设计接收到以后。
  • 一个类也可以包含多个覆盖组,每个覆盖组可以根据需要将它们使能或者禁止
class MC;
    logic [3:0] m_x;local logic m_z;bit m_e;
    covergroup cv1 @(posedge clk); coverpoint m_x; endgroup 
    covergroup cv2 @m_e coverpoint m_z; endgroup
endclass

覆盖点(coverpoint)

仓(bin)

使用coverpoint 指定采样一个变量和表达式时,sv会创建很多的bin(仓)来记录每个数值被捕捉的次数。这些bin是衡量功能覆盖率的基本单位。

数值覆盖

Covergroup的参数也可以被传递到bin的定义中

covergroup cg (ref int ra,input int low, int high )
@ (posedge clk) ;
    coverpoint r {
        bins good = { [low : high] };
        bins bad[] = default;
        }
endgroup
...
int va, vb;
cg c1 = new ( va, 0,50 ) ;cg c2 = new( vb,120,600 ) ;

值变化覆盖

除了可以覆盖数值,还可以覆盖数值的变化

value1 =>value2
value1 =>value3 =>value4 =>value5

range_list1 =>range_list2
1,5 =>6,7

trans__item [*repeat_range]

除了使用=>来表示相邻采样点的变化,也可以使用->来表示非相邻采样点的数值变化,在=>序列后的下一个时序必须紧跟=>序列的最后一个事件
3 [->3]
表示…=>3…=>3…=>3
1=>3 [->3]=>5
表示1…=>3…=>3…=>3 =>5

与[-> repeat range]类似的有[= repeatrange]也表示非连续的循环,只是与->有区别的在于,跟随->序列的下一次值变化可以发生在->结束后的任何时刻。
3 [= 2]
表示…=>3…=>3
1=>3 [=2]=>6
表示1…=>3…=>3…=>6

自动生成

如果coverpoint没有指定任何bin,那么SV将会为其自动生成bin,遵循的原则是:

  • 如果变量是枚举类型,那么bin的数量是枚举类型的基数(所有枚举数值的合)
  • 如果变量是整形(M位宽),那么bin的类型将是2^M和auto_bin_max选项的较小值

通配应用

  • 默认情况下,数值的变化可以针对四值类型变量进行覆盖,例如bin如果包含x或者z,则表示只有该变量对应位也为x或者z的时候,bin也才可以被采样到。
  • wildcard修饰符可以使得bin中包含x,z和?的数值都将用来表示0或者1,也就是通配符的意思
wildcard bins g12_15 = { 4 'b11??} ;
g12_15可以用来表示12到15之间的值,即1100,1101,1110,1111

忽略类型和非法类型

ignore_bins用来将其排除在有效统计的bin集合之外

covergroup cg23;
    coverpoint a {
        ignore_bins ignore_vals = { 7,8} ;
        ignore_bins ignore_trans = (1=>3=>5);
        }
endgroup

illegal_bins用来指出采样到的数值为非法制,如果illegal_bins被采样到,那么仿真将报错

covergroup cg3 ;
    coverpoint b {
    i1legal_bins bad_vals = { 1,2,3};
    illegal_bins bad_trans = (4=>5=>6);
    }
endgroup

交叉覆盖率(cross)

  • covergroup可以在两个或者更多的coverpoint或者变量之间定义交叉覆盖率(cross coverage)
  • 在对a和b产生交叉覆盖率之前,系统会先为它们隐性产生对应的coverpoint和bin,每个coverpoint都有16个自动产生的bin
  • 两个coverpoint交叉以后将生成256个交叉的bin
bit [3:0] a, b;
covergroup cov @(posedge clk) ;
    axb : cross a, b;
endgroup
  • 除了系统会自动为交叉覆盖率生成bin以外,用户还可以自己定义交叉覆盖率的bin
  • binsof()的参数可以是coverpoint或者变量,表示对应的bin总和,可以利用binsof()对其结果做进—步的过滤
int i,j;
    covergroup ct;
        coverpoint i { bins i[]= { [O:1] } ; }
        coverpoint j { bins j[] = { [0:1] } ; }
        x1 : cross i,j;
        x2 : cross i,j{
        bins i_zero = binsof(i)intersect { o };
        }
endgroup

3. 问答题

请考虑对于目前的DUT (router),要完成对它的功能测试,从接口时序、路由功能来看,需要考虑哪些功能和对应的测试场景?考虑路桑给出的接口插件文件(包含功能覆盖率定义和采样),是否没有全部映射你给出的待测功能点?如果需要补全,你是否可以在给出的接口插件文件中,补全这部分功能覆盖率定义代码呢?请将补全的部分代码,粘贴到这里,并且在你的实验四的代码中,试运行去收集你关心的这部分功能覆盖率,在验收实验四的时候,给予必要的说明。

答:需要考虑是否各个输入端口都能输入数据,各个输出端口是否都能接收到数据;以及不同输入端口并行发送数据、同一端口发送多个数据到不同输出端,同一输出端口接收来自不同输入端口发送的数据……

可参考

SV基础知识6—覆盖率收集_持续学习_ing的博客-CSDN博客_覆盖率收集


文章作者: DPH
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 DPH !
  目录