这讲写一下有关sv覆盖率的基础知识。
目录
一、覆盖率类型
1、概述
- 覆盖率是衡量设计验证完备性的一个通用词语
- 随着测试逐步覆盖各种合理的组合,仿真过程会慢慢勾画出你的设计情况。
- 覆盖率工具会在仿真过程中收集信息,然后进行后续处理并且得覆盖率报告
- 通过这个报告找出覆盖之外的盲区,然后修改现有测试或者创建新的测试来填补这些盲区。
- 这个过程可以一直迭代进行,直到你对覆盖率满意为止
2、覆盖率反馈回路
- 可以使用一个反馈回路来分析覆盖率的结果决定采取哪种行动来达到100%的覆盖率
- 首要的选择是使用更多的种子来运行现有的测试程序
- 当大量种子依然对于覆盖率增长没有帮助时,需要建立新的约束
- 只有在确实需要的时候才会求助子创建定向测试。
3、代码覆盖率
- 不添加任何额外的HDL代码,工具会通过分析源代码和增加隐藏码来自动完成代码覆盖率的统计
- 当运行完所有测试,代码覆盖率工具便会创建相应的数据库
- 仿真器都带有代码覆盖率的工具,覆盖率数据也可被转换为可读格式。
- 行覆盖率:多少行代码已经被执行过
- 路径覆盖率:在穿过代码和表达式的路径中有哪些已经被执行过
- 翻转覆盖率:哪些单位比特变量的值为0或1.
- 状态机覆盖率: 状态机哪些状态和状态转换已经被访问过
代码覆盖率最终的结果用子衡量你执行了设计中的多少代码,关注点应该放在设计代码的分析上,而不是测试平台;
未经测试的设计代码里可能隐藏硬件漏洞也可能仅仅就是冗余的代码。
代码覆盖率衡量的是测试对于硬件设计描述的“实现”究竟测试得有多彻底,而非针对验证计划。
代码覆盖率达到了100%,并不意味着验证的工作已经完成,但代码覆盖率100%是验证工作完备性的必要条件
4、断言覆盖率
- 断言是用于一次性地或在一段时间对一个或者多个设计信号在逻辑或者时序上的声明性代码
- 断言可以跟随设计和测试平台一起仿真,也可以被形式验证工具所证实
- 你可以使用SV的程序性代码编写等效性检查,但使用SVA (SV断言)来表达会更容易
- 断言最常用于查找错误,例如两个信号是否应该互斥,或者请求与许可信号之间的时序等
- 一旦检测到问题,仿真就可以立即停止
- 有些断言可以用于查找感兴趣的信号值或者设计状态
- 可以使用cover property来测量这些关心的信号值或者状态是否发生
- 在仿真结束时,仿真工具可以自动生成断言覆盖率数据
- 断言覆盖率数据以及其它覆盖率数据都会被集成在同一个覆盖率数据库中verifier可以对其展开分析。
5、漏洞率曲线
- 在一个项目实施期间,你应该保持追踪每周有多少个漏洞被发现。
- 一开始,当你创建测试程序时,通过观察可能就会发现很多漏洞
- 当设计逐渐稳定时,你需要利用自动化的检查方式来协助发现可能的漏洞。
- 在设计临近流片时,漏洞率会下降,甚至有望为零。即便如此验证工作仍然不能结束。
- 每次漏洞率下降时,就应该寻找各种不同的办法去测试可能的边界情况 (corner case)【漏洞率下降意味着设计越来越稳定,但不意味这个设计漏洞越来越少了】
- 漏洞率可能每周都有变化,这跟很多因素都有关。不过漏洞率如果出现意外的变化,可能预示潜在的问题【有可能是一些功能点没有定义到】
说明:漏洞率下降,功能性覆盖率这个指标公会告诉我们哪需要做出调整
6、功能覆盖率(重点)
- 验证的目的就是确保设计在实际环境中的行为正确
- 功能描述文档详细说明了设计应该如何运行,而验证计划则列出了相应的功能应该如何激励、验证和测量
- 当你收集测量数据希望找出那些功能已经被覆盖时,你其实就是在计算”设计”的覆盖率。
- 功能覆盖率是和功能设计意图紧密相连的,有时也被称为"描述覆盖率”,而代码覆盖率则是衡量设计的实现情况。
- 某个功能在设计中可以被遗漏,代码覆盖率不能发现这个错误,但是功能覆盖率可以。
- 每一次仿真都会产生一个带有覆盖率信息的数据库,记录随机游走的轨迹。
- 把这些信息全部合并(合并的前提是测试全部通过)在一起就可以得到功能覆盖率,从而衡量整体的进展程度。
- 通过分析覆盖率数据可以决定如何修改回归测试集
- 如果覆盖率在稳步增长,那么添加新种子或者加长测试实际即可
- 如果覆盖率增速放缓,那么需要添加额外的约束来产生更多"有意思”的激励。
- 如果覆盖率停止增长,然而设计某些测试点没有被覆盖到,那么就需要创建新的测试了。
- 如果覆盖率为100%但依然有新的设计漏洞,那么覆盖率可能没有覆盖到设计中的某些设计功能区域。
二、功能覆盖策略
1、收集信息而非数据
- 对于MCDF,你需要关心的是合法的寄存器地址和非法的寄存器地址,可写的寄存器域和非法的寄存器域,而不是具体的寄存器地址数值。
- 一旦关注的地方着眼于感兴趣的状态,而不是具体数值,那么这对于你如何定义功能覆盖率,以及如何收集信息会减轻很大的负担。
- 设计信号如果数量范围太大,应该拆分为多个小范围再加上边界情况。
2、只测量需要的内容
- Verifier需要懂得,在使能覆盖率收集时,这一特性会降低很大的仿真性能。
- 由于收集功能覆盖率数据的开销很大,所以应该只测量你会用来分析并且改进测试的那部分数据
- 同时也需要设定合理的覆盖率采样的事件,一方面提升采样效率,一方面也可以降优收集覆盖率的开销
3、验证的完备性
三、覆盖组
1、概述
- 覆盖组 (covergroup)与类相似,一次定义后便可以多次实例化。
- covergroup可以包含一个或者多个coverpoint,且全都在同一时间采集
- covergroup可以定义在类中,也可以定义在interface或者module中。
- covergroup可以采样任何可见的变量,例如程序变量、接口信号或者设计端口。
- 一个类里可以包含多个covergroup。
- 当你拥有多个独立的covergroup时,每个covergroup可以根据需要自行使能或者禁止。
- 每个covergroup可以定义单独的触发采样事件,允许从多个源头收集数据。
- covergroup必须被例化才可以用来收集数据
2、在类里定义covergroup
3、covergroup的采样触发
4、使用事件触发
四、数据采样
1、概述
- 当你在coverpoint指定采样一个变量或表达式时,SV会创建很多的"仓 (bin)”来记录每个数值被捕捉到的次数。
- bin是衡量功能覆盖率的基本单位
- covergroup中可以定义多个coverpoint,coverpoint中可以自定义多个cover bin或者SV帮助自动定义多个cover bin。【建议自已定义bin,SV定义的bin一般不满足要求】
- 每次covergroup采样,SV都会在一个或者多个cover bin中留下标记,用来记录采样时变量的数值和匹配的cover bin。
- 在仿真之后,可以使用分析工具读取这些数据库来生成覆盖率报告,包含了各部分和总体的覆盖率
2、coverpoint和bin
- 为了计算一个coverpoint上的覆盖率,首先需要确定可能数值的个数,这也被称为域。
- 覆盖率就是采样值的数目除以bin的数目,例如一个3比特变量的域是0:7,正常情况下会自动分配8个bin。如果仿真过程中有7个值被采样到,那么最终该coverpoint的覆盖率是7/8。
- 所有的coverpoint的覆盖率最终构成一个covergroup的覆盖率
- 所有的covergroup的覆盖率构成了整体的功能覆盖率
3、bin的创建和应用
4、命名coverpoint和bin
5、条件覆盖率
6、翻转覆盖率
说明:相邻的OR连续的跳转的情况!!!
7、wildcard覆盖率
8、忽略的bin
- 在某些coverpoint可能始终无法得到全部的域值
- 对于那些不计算功能的域值可以使用ignore_bins来排除,最终它们并不会计入coverpoint的覆盖率。
9、非法的bin
- 有些采样值不仅应该被忽略,而且如果出现还应该报错
- 这种情况可以在测试平台中监测,也可以使用illegal_bins对特定的bin进行标示。
10、交叉覆盖率(难点)
11、排除部分cross bin
12、精细的交叉覆盖率指定(重点)
- 随着cross覆盖率越来越精细,可能需要花费不少的时间来指定哪些bin应该被使用或者被忽略
- 更适合的方式是不使用自动分配的cross bin,而自己声明感兴趣的cross bin。
- 假如有两个随机变量a和b,它们带着三种感兴趣的状态{a==0,b==0}、{a==1、 b==01和(b==1}。
下面两种解决方案:
方案一:
方案二:
五、覆盖选项
1、单个实例的覆盖率
如果对一个covergroup例化多次,那么默认情况下SV会将所有实例的覆盖率合并到一起。
如果需要单独列出每个covergroup实例的覆盖率,需要设置覆盖选项。