当前位置:网站首页>【数字IC验证快速入门】20、SystemVerilog学习之基本语法7(覆盖率驱动...内含实践练习)

【数字IC验证快速入门】20、SystemVerilog学习之基本语法7(覆盖率驱动...内含实践练习)

2022-07-07 13:22:00 luoganttcc

导读:作者有幸在中国电子信息领域的排头兵院校“电子科技大学”攻读研究生期间,接触到前沿的数字IC验证知识,旁听到诸如华为海思清华紫光联发科技等业界顶尖集成电路相关企业面授课程,对数字IC验证有了一些知识积累和学习心得。为帮助想入门前端IC验证的朋友,思忱一二后,特开此专栏,以期花最短的时间,走最少的弯路,学最多的IC验证技术知识。

一、内容概述

  • 基于覆盖率驱动的验证技术
  • 覆盖率类型:代码覆盖率(工具自动生成,客观)和功能覆盖率(人为定义覆盖点,主观)
  • SV中的功能覆盖率建模
  • 定义覆盖率模型:covergroup
  • 定义覆盖点:coverpoint
  • 覆盖点的bins
  • 覆盖率函数

覆盖率驱动 可以用来衡量我们的验证进度,简而言之就是,看我们验了半天验到了什么程度。当然最核心的还是保证我们验证完备性,我们能识别到的点都要验证到。需要澄清的是,覆盖率达到要求,并不能说验证就真正的OK了,其实验证的空间还是非常大的,只是说我们的风险变小了,不能说一点风险都没有!故,验证有时候还是我们尽力而为的一个东西。

二、基于覆盖率驱动的验证技术

  • 覆盖率是对RTL设计功能进行验证后达到的覆盖百分比(量化数据)
    • 检查过程必须满足完整性正确性,没有冗余的劳动
    • 为了最小化验证工作量,使用覆盖率来衡量一个设计哪些功能测试过,哪些功能还没有被测试过
    • 功能覆盖率是由验证工程师自己定义的,用于衡量设计规格是否被正确实现,具体内容体现在验证计划
    • 功能覆盖率用于检查设计的应用场景边界条件特殊变量或者设计条件是否被完整的正确的测试或者确认过

三、功能覆盖率模型

  • 定义覆盖率模型

    • 编写覆盖率模型用于衡量验证计划的目标是否被实现
    • 功能覆盖率模型不能自动的从设计中获取
    • 功能覆盖率模型是由验证工程师自己定义,在验证环境中检查设计意图和设计功能是否被正确实现
    • 根据设计规格书和验证计划,验证工程师需要定义哪些内容必须被覆盖到(被测试到或者被验证到)
  • 步骤

    • 定义采样的信号(coverage group)
    • 定义采样的时间

四、功能覆盖率收敛

  • 覆盖率收敛
    • 采用什么样的策略和行为,使得覆盖率达到100%
      • 功能覆盖率适用于衡量测试案例覆盖了哪些设计属性(design feathures)
      • 覆盖率收敛是一个反馈环路,用于分析覆盖率的结果并为下一步达到100%的覆盖率确定测试方案
        • 使用不同的种子(seed)运行现有的测试哪里
        • 新增约束(new constraints)

在这里插入图片描述

五、功能覆盖率数据

  • 收集覆盖率数据
    • 使用多个种子运行同一个测试案例
    • 检查测试用例(case)是否正确运行(pass/fail)
      • 只有当测试用例(case)的仿真结果正确时,功能覆盖率数据才有效
      • 因RTL设计中的bug导致仿真结果不正确时,功能覆盖率数据无效,必须丢弃
    • 分析覆盖率

在这里插入图片描述

  • 在设计中收集代码覆盖率,在验证中收集功能覆盖率
  • 收集覆盖率是一个回归的过程!

六、功能覆盖率数据的归一化和分析

  • 收集覆盖率数据库,并归一化处理
    • 使用不同的种子,多次重复运行随机化验证平台和测试用例
    • 将所有测试用例运行的功能覆盖率结果归一化处理,用于衡量验证进度
    • 分析覆盖率数据,确认如何修改测试用例
    • 如果获取的覆盖率数据保持稳定,需要使用不同的种子测试用例并且测试用例运行时间要延长
    • 如果覆盖率增长缓慢,需要增加约束条件获得更多有效激励
    • 如果遇到瓶颈,需要创建更多的直接测试用例,满足边界条件
    • 当功能覆盖率接近100%时,需要检查bug出现的几率,如果bug经常被发现,说明有一部分设计的覆盖不完整。如果不出现bug,说明设计验证工作结束。

七、覆盖率的类型:RTL代码覆盖率

注:代码覆盖率是一个客观条件,即代码风格维度看覆盖率,代码覆盖率很容易也必须(或虽然达不到但可解释)要求达到100%。

  • 代码覆盖率
    • 衡量测试用例验证覆盖了哪些设计规格在RTL中实现了,而不能衡量验证计划
      • 行(Line Coverage):RTL中的代码行
      • 有限状态机(FSM Coverage):RTL代码中的有限状态机的状态和状态之间的转化
      • 路径(Path Coverage):RTL代码中的路径分支(if-else语句)
      • 信号反转(Toggle Coverage):RTL代码中的一个信号从0跳变到1,以及从1跳变到0
      • 比导师(Expression Coverage):RTL代码中的条件表达式,例如 if(a & b & c)

八、覆盖率的类型:断言覆盖率

注:功能覆盖率更多的去检查逻辑功能,看不到时序信息是否正确,所以就有了断言覆盖率!

  • Assertion Coverage 断言覆盖率
    • 断言是一种声明性的代码,用于检查RTL代码中的信号之间的(时序)关系
    • 断言可以使用过程性的代码或者使用SystemVerilog Assertions
    • 断言可以检查信号的值或者设计的状态
      • cover property 语句

九、覆盖率的类型:功能覆盖率

  • 与设计意图有关系
    • 功能覆盖率取决于验证计划!

在这里插入图片描述

九、覆盖率的类型:功能覆盖率 VS 代码覆盖率

  • 100% 代码覆盖率并不意味着100%的功能覆盖率!

在这里插入图片描述

十、基于覆盖率驱动的验证策略

  • 收集信息而不是数据
  • 只能衡量使用了哪些内容
  • 衡量完整性

在这里插入图片描述

十一、覆盖率与缺陷率(Bug rate)的关系

  • Bug 出现的几率
    • Bug rate是指新的RTL功能缺陷被发现的几率,可以间接的衡量覆盖率
    • Bug rate随着项目和验证的进度不断变化

在这里插入图片描述

十二、定义功能覆盖率模型

  • covergroup
    • 封装覆盖率模型的规格
    • 每个covergroup包含以下内容
      • 一个时钟事件,用于同步采样覆盖点
      • 一组覆盖点
      • 覆盖点之间的交叉覆盖
      • 可选的形式参数
      • 覆盖率选项
    • Coverfroup是用户定义的一种结构类型
    • 定义好类型之后,可以在不同的程序中多次例化
    • 跟class类似,定义完成后,可以通过构造函数new()生成covergroup的实例【OOP】
    • covergroup 可以额定义在moduleprograminterfaceclass
    • 一个covergroup可以包含一个或多个覆盖点
      • 一个覆盖点可以是一个变量或者一个表达式
      • 每个覆盖点有一组bins值,这个值跟采样的变量或者变量的转换有关
      • Bins的值可以由用户自己定义,或者由EDA工具自动生成
      • covergroup 的命名要清晰明了,通过名称就可以确认覆盖的功能是什么,最好跟验证计划统一
// 声明一个covergroup

covergroup cg;
.
endgroup

cg cg_inst = new;

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在这里插入图片描述

十三、功能覆盖率的建模

  • 以验证计划为起点,编写可以仿真的功能覆盖率模型
  • 在验证平台中采样变量和表达式的值(coverpoints
  • 在下面的例子中,验证平台随机产生端口值,验证计划中要求遍历所有值

在这里插入图片描述

十四、功能覆盖率报告

在这里插入图片描述

十五、功能覆盖率的采样事件

  • 带有event触发的covergroup
    • 当验证平台触发 trans_ready 事件时,采样CovPort

在这里插入图片描述

十六、功能覆盖率:触发SystemVerilog Assertion

在这里插入图片描述

十七、定义覆盖点:信号和表达式

  • 采样数据

    • 如何收集覆盖率信息?
      • 在覆盖点中指定了变量和表达式,SystemVerilog创建了一组bins,用于记录那些采样到的数值
      • bins是一个功能覆盖率的衡量单位
      • 在每次仿真结束后,生成的数据库中包含了采样后所有的bins
      • EDA分析工具可以读取这个数据库,生成一个覆盖率报告,报告中包含了设计中哪一部分被覆盖,以及总的覆盖率数值
  • 私有bins和总的覆盖率

    • 计算一个覆盖点的覆盖率,首先确认所有可能数值的总的数量
    • 覆盖率等于采样的bins值除以总的bins的值
  • 采样表达式

    • 表达式可以被采样,但必须检查覆盖率报告,确保采样值是正确的

在这里插入图片描述

注:lens32的覆盖率应该为:24 / 32 = 75% 。范围计算方法:hdr_len是3bit,所以一共8个组合,payload_len时4bit,所以一共16个组合。那么,加起来一共是24个组合0-23,而总的空间是0-31即32个组合,又最后加的是5'b0故32个组合中必定有某些值达不到,所以lens32的覆盖率为:24 / 32 = 75%

  • 采样数据:bins
    • 私有bins和总覆盖率
      • SystemVerilog 自动为覆盖点创建bins
      • 一个N位的表达式有
                  2
                 
                 
                  N
                 
                
               
               
                2^N
               
              
             </span><span class="katex-html"><span class="base"><span class="strut" style="height: 0.841331em; vertical-align: 0em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height: 0.841331em;"><span class="" style="top: -3.063em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right: 0.10903em;">N</span></span></span></span></span></span></span></span></span></span></span></span>个有效值</li><li>一个3bit的变量port有8有效值</li></ul> </li><li>限制自动生成的bins的数量 
        <ul><li>covergroup 选项<code>auto_bin_max</code>指定自动生成bins的最大数量,默认值为64bins</li></ul> </li></ul> </li></ul> 
        

在这里插入图片描述

注:自动生成bins这种在实际中应有的比较少!

在这里插入图片描述

  • Q:什么算是一个功能点?
    • A:UT/BT 功能点更多聚焦模块上下接口和时序上面;IT 对应的可能是数据流;ST 对应的可能是系统级的应用场景
    • 故,功能点在不同的level验证上分解对应的点是不太一样的

十八、定义覆盖点:bins

  • 用户定义bins
    • 显式命名bins可以提高精度,方便统计覆盖率

在这里插入图片描述

注:为什么23不会出现呢?hdr_len的最大值为7,而payload_len的最大值为22,故len的最大值为22不会出现23!

  • 覆盖点bins的命名
    • 定义bins时
      • 用户限制覆盖率统计时需要的数值
      • SystemVerilog 不再自动创建bins,并且忽略非用户定义的bins值
      • 只有 用户定义的bins的值才可以用于计算功能覆盖率
      • 用户默认bin值可能被遗忘

在这里插入图片描述
在这里插入图片描述

十九、定义覆盖点:条件覆盖

  • 条件覆盖(下述两种用法等效)
    • 使用关键字iff为覆盖点添加条件(更简洁)
    • 使用startstop函数

在这里插入图片描述

在这里插入图片描述

二十、定义覆盖点:状态跳转覆盖

注:上面是收集静态的覆盖点,下面来看看状态切换点的覆盖收集。

  • Transition Coverage 跳转覆盖率
    • 用户定义覆盖点的状态跳转,并收集相关的信息
    • 使用?等通配符表示状态和状态跳转

在这里插入图片描述

注意:上述t2是1到3;1到4;2到3;2到4,四种跳转情况!
在这里插入图片描述
注:当状态较多时,可以使用?通配符

二十一、定义覆盖点:交叉覆盖

  • Cross Coverage 交叉覆盖率
    • 在覆盖率组中,可以定义两个或多个覆盖点或者变量之间的交叉 覆盖率

在这里插入图片描述

注:kind 一共16种组合,port一共8种组合,交叉一共有16x8=128种组合

在这里插入图片描述

二十二、参数化的覆盖率:提供代码的重用性

  • 参数化的covergroup
    • SystemVerilog 允许创建参数化的covergroup,便于创建通用的定义

在这里插入图片描述

二十三、covergroup实战补充(2021-10-15)

在这里插入图片描述

在这里插入图片描述

二十四、小结

  • 基于覆盖率驱动的验证技术
    • 为什么是基于覆盖率驱动?整个验证需要看验证进度,需要覆盖率这个可以量化的标准可以看到进展。功能覆盖率一般是100%,代码覆盖率接近100%(条件覆盖率需要根据具体的电路类型,一般来讲很难达到100%,需要根据不同的代码来定)。总之做验证计划的时候有一个覆盖率目标,达到覆盖率目标,才算达到我们的要求!另外需要强调一点,并不是说达到覆盖率我们的验证就OK了,达到覆盖率后,需要去看比如缺陷的情况等。如果覆盖率ok,但缺陷仍持续很高,此时并不能证明验证是收敛的!另外一点,功能覆盖率是验证人员自己来写的,主观写的话,一开始可能就写的不全,故即便达到100%,也不能说所有的功能就覆盖掉了!因为本身可能写的覆盖率场景本身就没有cover到,故整个过程需要做多轮的迭代来完成。
    • 总之,记住几个点。1、覆盖率是用来衡量验证进度的标值。2、体现在验证计划中,在验证一开始需要体现一个覆盖率目标。
  • 覆盖率类型:代码覆盖率和功能覆盖率
    • 代码覆盖率是一种根据代码描写结构去客观的工具自动收集的覆盖率;功能覆盖率是验证人员根据我们要验的功能规格从规格设计书作为一个入口来分析我们要验的DUT有哪些功能,然后把这些功能点写出来!
    • 代码覆盖率达到要求并不代表功能达到要求!如果代码覆盖率都没达到要求,那么肯定验证是不完备的。
  • SV中的功能覆盖率建模
    • 定义覆盖率模型:covergroup
    • 定义覆盖点:coverpoint
    • 覆盖点的 bins(类似约束限定范围,还有条件覆盖、交叉覆盖、transition覆盖(随着时间的延续的覆盖))
    • 覆盖率函数(传递参数)

X、实践练习

X.1、编写源代码

修改Makefile,由于我们需要看覆盖率,所以需要在Makefile中添加dve工具相关的命令。

Makefile

comp_file = ;
all: comp run dve_cov
comp:
	vcs -full64 -sverilog -debug_all  -timescale=1ns/1ps $(comp_file) -l comp.log
run:
	./simv -l $(comp_file).log
dve_wave:
	dve -vpd vcdplus.vpd &
dve_cov:
	dve -full64 -covdir simv.vdb
log:
	sed '/^[^*].*/d' $(comp_file).log > rslt.log
open:
	gvim rslt.log
clean:
	rm -rf csrc simv* *.log ucli.key
  • dve_wave 在后面的SVA会用到,现在暂时用不到
  • 更改all为:comp run dve_cov
  • dve_cov 是我们收集覆盖率要用到的

cov_demo.sv

module cov_demo();
  class transaction;//激励
    rand bit [31:0] data;
    rand bit [2:0]  port;
/*    constraint data_c1{
    
      data inside{
    [0:100], [101:9999], [10000:12000]};
    }  */
  endclass
  covergroup cov_grp;
    cport : coverpoint tr.port;
    cdata : coverpoint tr.data;
/*    cdata : coverpoint tr.data {
    
      bins min = {
    [0:100]};
      bins mid = {
    [101:9999]};
      bins max = {
    [10000:$]};
    }*/
  endgroup
  transaction tr = new;
  cov_grp ck = new;
  initial begin
    repeat(32) begin//重复次数
      tr.randomize;//发送激励
      ck.sample();//采集覆盖率
    end
  end 
endmodule 
  • portdata冒号前面的仅仅是起个名字,有无都可!

在这里插入图片描述

X.2、运行源代码

执行make comp_file=cov_demo.sv会自动编译运行并弹出DVE窗口以供我们查看覆盖率!

在这里插入图片描述

点击左侧的<Function Groups>+展开该选项,而后双击cov_demo::cov_grp Covergroup definition

在这里插入图片描述

在这里插入图片描述

在右侧串口可以看到cov_demo::cov_grp对应的覆盖率只有14.84%,这是很低的!可以继续点击其下的cdatacport在右侧会看到变量的哪些覆盖了,哪些没有覆盖。如下图:

在这里插入图片描述
在这里插入图片描述

注:由于使用的是默认的bins,所以这里标识的是auto。auto bins的情形下,bins的分类特别多,覆盖率特别低!

从下图不难看出,cport覆盖率为25%,在右侧可以看到具体覆盖信息,67个命中了1次和3次,还有0-56个值没有被覆盖,所以覆盖率为2/8=0.25

在这里插入图片描述

上述实验中,我们仅仅repeat了4次,导致命中的范围变小,覆盖率只有25%也是情理之中。接下来我们修改repeat改为32,增加次数,可以扩大命中范围,也就是cportcdata变量的覆盖率也会增加!

点击右上角关闭DVE,修改源代码中的repeat参数,并重新运行Makefile脚本。

运行结果如下图,可以看到总体覆盖率为69.53%,显著提升。其中cport的8种情况全部覆盖,所以覆盖率为100%!

在这里插入图片描述

接着我们使用自定义bins,取消14-18行注释,并把第13行注释。这里是将data分为了三类,拿第一类min举例来说,只要出现0~100中的任意一个数,就算命中min,就算一个等价的测试点!比如产生一个50,那么就意味着0~100这样一个范围就已经测试过了!

如下图,可以看到cdata只覆盖了max,对于midmin并没有进行覆盖,这个时候我们只能去调整随机激励的约束,让他产生中间值和小值!

在这里插入图片描述

取消掉第6-8行注释,实现对data的范围进行约束。重新便于DVE,运行Makefile脚本,可以看到cdata的覆盖率和整体覆盖率均达到了100%

在这里插入图片描述

注:如果某一类没有覆盖到,我们就可以将约束改小,单独的去覆盖它。这里给我们一个启示,可以跑多个用例,每个用例跑多个范围,那么这样的话最终merge,data的覆盖率就可以达到100%了!

原网站

版权声明
本文为[luoganttcc]所创,转载请带上原文链接,感谢
https://luogantt.blog.csdn.net/article/details/125645282