日常记录(78)翻译3
功能覆盖率应基于观察
试验平台的激励侧应该用于驱动DUT,激励侧不应该用于覆盖率,因为DUT或激励可能无法正常工作,从而导致错误的覆盖率。相反,功能覆盖率应基于在测试平台上DUT输出处观察到的情况。在UVM测试平台中,功能覆盖率将基于分析的事务内容。这对测试平台的设计和分析的事务有影响。
功能覆盖有效性
功能覆盖率数据仅在通过检查时有效。如果您没有使用自动工具来合并来自不同仿真的覆盖率,那么您应该确保仅在测试通过时对覆盖率模型进行采样。
但是,如果您使用验证管理工具从多个仿真中收集覆盖率,则无需这样做,因为失败测试的覆盖率结果不会与其他功能覆盖率数据合并。
将负面检测和正面检查分开收集
如果验证计划要求对某个功能进行正面和负面测试,则分别设计并收集这两种测试的功能覆盖率。
设计用于分析的覆盖模型
一个常见的错误是开发一个全面的功能覆盖模型,但后来才意识到很难理解结果。使用可用的语言结构可以更容易地理解缺失的覆盖范围。换句话说,在创建功能覆盖模型时,值得投入一些时间,以便在以后需要了解结果时节省时间。有关此主题的更多讨论,请参见用于分析的覆盖率设计页面。
确定适当的忠于原设计的级别
需要与设计实现的细节有多接近?可以应用多少抽象?
在简单的情况下,需要检查的值相对较少,创建与设计细节密切相关的覆盖率模型是一个可管理的问题。然而,当存在广泛的值时,需要就在细节级别上做出谨慎的决定。例如,一个设备具有大约20个可能值的配置可以很容易地直接建模,而像32位地址范围这样的东西需要拆分成一组有趣的值或值范围,这需要一些抽象。
使用一致的编码风格
使用一致的编码风格来实现覆盖组和断言代码非常重要,因为这使它们更容易理解和解释。它还使与验证计划和跟踪工具的集成变得更容易。
有关覆盖组编码风格的示例,请参阅SystemVerilog编码指南。请注意,实际使用的样式并不重要,但使用一致的样式很重要。
基于覆盖组的覆盖率注意事项
在设计基于覆盖组的覆盖率时,需要考虑许多基于设计的功能和特性的关键点。
哪个值是重要的?
通过简单地指定由一个覆盖点对一个变量进行采样,可以很容易地以无知的方式收集信息,这将导致自动生成2**n个bins,其中n是变量中的位数。对于窄宽度字段,这可能是可以的,但对于更宽的字段,这不太可能非常有用。在大多数情况下,将有许多重要的值或值范围需要覆盖,这些值或值范围应从规范书中衍生出来,并作为一组bins编码到coverpoint中。
数据变量之间的依赖关系是什么?
在分析一个设计或数据包应该被配置为哪种方式时,不同变量之间是否存在关系?如果确实存在这种关系,则应在covergroup中指定变量之间的cross。
是否有需要检查的边界条件?
是否有特定值或值的组合需要检查,因为它们处于操作极限或设计中的已知拐点?这必然需要一些规范书的“字里行间的阅读”,以及一些设计或实现知识。确定的任何边界条件都应添加到覆盖率模型中,以确保对其进行测试。
是否存在非法条件?
如果存在不应出现的情况,则covergroup可以使用一个术语来捕捉这些情况。该术语对功能覆盖率没有贡献,但它可以帮助检测设计或测试平台错误。
是否有不重要的条件?
即使是最简单的设计也可能有比实际使用更多的配置方式。如果有一种方法可以确定哪些模式最有可能被使用,那么也有可能会有一些已知无用或不太可能被使用的模式,这些模式可以从收集的覆盖率值排列中忽略。这里也可能有一定程度的优先级,某些配置必须进行测试,然后,如果有时间,可以检查优先级较低的配置。
什么时候是采样覆盖率的合适时间?
数据覆盖率收集代码需要对其引用的数据值进行采样。采样点需要:
- 仅在相关检查通过时发生
- 数据值有效时发生
- 数据值稳定时
如果采样基于接收UVM分析事务,那么如果它直接来自监视器,则可能需要有一种方法来区分有效的和无效的分析流量。如果功能覆盖率收集器从记分板接收分析事务,则记分板应在发送分析事务之前确认检查已通过。
是否存在数据覆盖率采样无效的情况?
如果有,则必须将编写的守卫放入功能覆盖实施代码中。
分析事务中需要哪些信息?
对于基于TLM方法学(如OVM或UVM)的测试平台,功能覆盖所需的信息需要来自分析事务。这意味着分析事务必须具有将被采样的所有信息,这很可能会影响事务以及生成事务的监视器或记分板的设计。
总结
在考虑如何测试设计功能以及该功能应该基于covergroup的功能覆盖模型的什么部分时,请记住回答以下问题:
覆盖率评判 |
要收集数据覆盖范围的特征 |
哪个值如此重要? |
确定要命中的重要值。 |
这些值之间的依赖关系是什么? |
确定数据值之间的重要叉积(cross) |
是否存在违法条件? |
确定不应该出现的值或值的组合 |
什么时候取样合适? |
指定一个有效的采样点 |
什么时候数据无效? |
确定数据不应采样的条件 |
时序覆盖率考虑
控制路径和协议依赖于信号之间的时序关系来实现握手和传输。使用时态sequences和properties最容易验证这些类型的关系。功能覆盖率信息可以通过以下几种方式从这些检查中获得:
- 如果一个property被断言且从未失败,但可以显示为已完成,则可以假定该属性中描述的功能已被涵盖
- 如果一个sequence完成,然后该序列中编码的功能行为已被观察到,且可假设功能覆盖率
- 如果一个sequence完成,则可以对覆盖组进行采样,以检查其在什么条件下完成(混合覆盖率)
- 如果一个property断言通过,则可以使用通过声明触发covergroup的采样,以检查在什么情况下通过(混合覆盖)
检查应该是具体的
一个property或sequence应该只检查一个条件,在一个属性或序列中检查多个条件会导致功能覆盖范围中的错误识别。
如果使用一个sequence和/或融合操作符来定义property,然后,为了收集通过属性的每个潜在路径上的特定功能覆盖率,必须将属性展开并实现为特定于每个路径的序列。
混合覆盖
有时可能需要混合使用数据覆盖率和时序覆盖率技术来收集特定类型的功能覆盖。例如,检查协议传输的所有模式是否都已发生,最好的方法是写入一个property或sequence,标识传输何时成功完成,然后根据协议的感兴趣信号字段对覆盖组进行采样,以检查是否出现了所有相关条件。
APB总线协议监视器包含使用混合功能覆盖的示例实现。
功能覆盖示例Functional Coverage Examples
不同的设计风格需要不同的方法来构建功能覆盖模型。以下是一些成熟的示例,说明了一些常见的设计类:
设计类型 |
覆盖组 |
断言 |
功能覆盖率建模策略 |
链接到例子 |
例子压缩包 |
基于设计的控制 |
可能 |
在这种风格的设计中,不同的信号之间有定时关系,需要检查和观察它们是否工作 |
APB总线协议 举例 |
( download source code examples online at [1] ). |
|
外设风格设计,通过寄存器编程 |
可能 |
大多数功能覆盖可以从寄存器的内容派生出来,这些寄存器用于控制和监视设备的行为。寄存器接口也可以服务于数据路径。可以在信号接口上使用断言。 |
UART覆盖率的例子 |
( download source code examples online at [1] ). |
|
DSP数据路径风格设计 |
在这类设计中,激励通过设计数据路径泵送数据,并将输出与参考模型进行比较。功能覆盖主要是关于确保算法的“旋钮”已经被充分测试。 |
Biquad 滤波器的例子 |
( download source code examples online at [1] ). |
||
聚合器/控制器风格,例如 内存控制器 |
多个端口上抽象激励组合的覆盖,Config寄存器的覆盖,目标DDR规范的特征覆盖率 |
敬请期待 |
|||
具有垂直重用VM分析组件的SoC |
可能 |
在SoC级别,功能覆盖不是用例驱动的,只有一些接口或块级别的覆盖可以重用 |
SoC覆盖率例子 |
不可提供 |
编程分析
关注covergroups的实现是一项时间上的投资,当您或其他人需要了解缺失的功能覆盖率在哪里时,这种投资会得到回报。
覆盖组标记
在对covergroup编程时使用标签的方式对理解覆盖率结果有很大影响。可以为covergroup分配一个选项。名称字符串,有助于识别覆盖范围与测试平台的哪个特定部分相关。在covergroup中,coverpoints可以被标记,bins可以被命名。使用所有这些技术,在分析过程中更容易理解覆盖率结果。
覆盖组命名
如果一个测试平台中使用了相同covergroup的多个实例,则option.name参数可用于为每个实例分配标识字符串。构造covergroup时,可以将名称字符串作为参数传入。在UVM环境中,可以使用get_full_name()方法传入名称。请参见下面的代码示例。
covergroup还可以使用covergroup以编程方式命名的set_inst_name()内置方法。
Coverpoint和bins标签
作为一个例子,考虑下面来自于UART例子的功能覆盖问题。在本例中,UART字格式由线路控制寄存器(Line Control Register, LCR)的内容决定:
LCR Bit |
值 |
描述 |
[1:0] |
2'b00 |
5数据位 |
2'b01 |
6数据位 |
|
2'b10 |
7数据位 |
|
2'b11 |
8数据位 |
|
2 |
1'b0 |
1停止位 |
1'b1 |
2 停止位 |
|
[5:3] |
3'b??0 |
无校验 |
3'b001 |
奇校验 |
|
3'b011 |
偶校验 |
|
3'b101 |
坚持0校验 |
|
3'b111 |
坚持1校验 |
更低的分析潜力
更高的分析潜力
为了检查所有可能的文字格式是否都已传输,我们可以通过为LCR[5:0]创建覆盖点来实现覆盖组,而不指定任何bins。这将创建一组默认bins,每个bins对应于寄存器的每个可能值,如左侧代码示例所示。如果功能覆盖率收集的这些位至少采样一次,则没有问题,但如果没有,则很难确定哪个箱子对应于哪个条件——请参阅Questa 覆盖组浏览器中的“之前”屏幕截图。在这里,不使用标签导致仿真器使用自动bins,这意味着需要将缺少的箱子值转换为二进制,然后映射到寄存器字段以识别缺少的配置。
实现covergroup的更好方法是为每个寄存器字段使用带标签的coverpoint,然后为寄存器真值表中的每个值使用bins语法。当进行仿真时,创建的向量积反映了不同的bins标签,这使得确定哪些功能覆盖条件没有被采样变得更加容易。它还可以更容易地查看是否存在遗漏的总覆盖条件。请参阅Questa 覆盖组GUI中重构的“之后”屏幕截图。
Covergroup选项如何影响覆盖率的报告和计算
实现选项
功能覆盖率信息的分析受覆盖结果报告方式的影响。covergroup有三个选项会影响覆盖率报告,并可能造成相当大的混乱,它们是:
- option.per_instance
- option.get_inst_coverage
- type_option.merge_instances
如果在实现covergroup的代码中未指定这些选项,则默认情况下不会启用这些选项。换句话说,它们被设置为0。
这三个选项应在covergroup中明确声明,以确保覆盖率计算和报告一致且符合要求。
Covergroup类型和实例
当一个covergroup被声明时,它就变成了一种可以在测试平台中多次实例化的类型——例如,在一个设计中,同一类型的接口用于多个端口,因此同一covergroup用于测量协议覆盖率。默认的覆盖率报告方法是将covergroup类型的覆盖率报告为该类型所有covergroup覆盖率的加权平均值。这意味着,如果其中一个端口已经实现了100%的覆盖率,而其他端口没有,那么报告的覆盖率将不低于100%,并且无法分析哪些接口尚未实现。
per_instance选项
如果covergroup中option.per_instance设置为1,则covergroup报告将按每个实例进行细分,但报告的总体覆盖率仍然是加权平均值。在引用的示例中,这将使每个端口的覆盖范围都能被检查,可能会导致检测到设计缺陷或激励生成中的缺陷。
merge_instances 选项
如果covergroup中的type_option.merge_instances设置为1,则covergroup的所有实例报告的总体覆盖率是所有覆盖率的合并或逻辑or,而不是加权平均值。如果您有相同设计IP的多个实例,并且测试平台的不同部分以不同的方式使用它,那么这可能很有用。使用merge_instances选项的一个结果是,一个covergroup实例达到100%覆盖率,而另一个实例达到0%覆盖率,此后总体覆盖率将报告为100%。
get_inst_coverage选项
要做到使能merge_instances选项的情况,option.get_inst_coverage的值设置为1,以启用SystemVerilog的$get_inst_coverage()系统调用返回covergroup实例的覆盖率,从而允许检查所有单个实例的覆盖率。如果merge_instances选项设置为0,则get_inst_coverage变量无效。
总结Summary
per_instance和merge_instances设置之间的交互:
option.per_instance |
type_option.merge_instances |
覆盖率报告行为 |
0 |
0 |
总体覆盖率报告为覆盖组所有实例的覆盖率的加权平均值 |
1 |
0 |
总体覆盖率报告为覆盖组所有实例的覆盖率的加权平均值,并为覆盖组的每个实例进行分解 |
0 |
1 |
覆盖率报告为覆盖组的单个实例的覆盖率的合并 |
1 |
1 |
整体覆盖率报告为单个覆盖率结果的合并,使能get_inst_coverage(),覆盖率报告对覆盖组的每个实例进行了分解 |
merge_instances 和 get_inst_coverage之间的交互
type_option.merge_instances |
option.get_inst_coverage |
由 $get_inst_coverage()获取的数据返回值 |
1 |
0 |
基于类型的覆盖——即合并所有实例的覆盖率 |
1 |
1 |
特定于实例的覆盖率 |
0 |
1|0 |
特定于实例的覆盖率 |
特定于仿真器的运行时选项
所描述的选项是SystemVerilog LRM中定义的covergroup选项,因此可以添加到covergroup代码中。仿真器还添加了命令行选项,允许用户更改报告覆盖率的方式,尽管这些选项往往是全局性的,会影响被仿真测试平台中的所有覆盖组。
覆盖率例子 (实践)
总线协议覆盖率
总线协议定义了总线上主设备和从设备之间的数据传输方式。协议规定了当主设备发出请求时,以及当从设备准备好响应该请求时,使用哪些信号来确认。验证总线协议的一种方法是将协议监视器实现为SystemVerilog接口,该接口使用SVA并发断言和CoverGroup的混合,以检查它观察到的总线通信量是否符合协议,并收集关于总线上发生的传输类型的功能覆盖信息。协议监控器是一种被动验证组件,用于监控协议信号,它可以连接到测试台顶层的外部信号,也可以绑定到设计内部的内部总线信号。总线协议监视器是可重用验证组件的一个很好的例子。
APB3 协议概述
ARM AMBA APB3协议是一个简单的外围总线协议的示例,可用于说明与实现协议监视器相关的要点,并说明如何使用它来收集功能覆盖信息。
使用APB3协议,一个主设备可以与多个从设备进行接口。主设备为所有从设备通用的地址、写入和写入数据生成一组控制字段。每个从机由一个单独的外围选择线(PSEL)选择,然后由一个通用的PENABLE信号启用。每个从机生成响应信号、就绪、读取数据和状态,这些信号被多路复用地传输回主机。方框图显示了典型的APB3外围模块。
APB3信号之间的时序关系如下图所示。
Deriving The Protocol Properties
开始定义属性的最简单方法是用英语为每个协议规则编写简单明确的描述。一旦定义并达成一致,那么实现断言代码通常是相对简单的。
以下概述的属性也总结为测试计划。
对于APB协议,我们可以定义以下内容:
未知的(X, Z) 信号
如果协议信号处于未定义状态,则在某些情况下会导致问题。检查未知信号状态的属性在调试设计的早期阶段很有用,但在验证的后期阶段不太有用。然而,它们确实说明了功能覆盖率集合的第一种类型——成功且永不失败的属性证明了该属性的功能覆盖率。
对于APB3协议,以下未知信号规则为真:
- PSEL应始终处于已知状态
- 如果至少有一条PSEL线处于逻辑1,则以下控制场信号也应处于已知状态
- PADDR
- PENABLE
- PWRITE
- 如果至少有一条PSEL线位于逻辑1,且PWRITE位于逻辑1,则PWDATA应处于已知状态
- 如果PSEL和PENABLE均为逻辑1,则PREADY应处于已知状态
- 如果PREADY处于逻辑1,则PSLVERR应处于已知状态
- 如果PWRITE处于逻辑0,且PREADY处于逻辑1,则PRDATA应处于已知状态
另一种方法是要求所有总线信号必须始终处于已知状态,但这可能并不总是可行的,而定义的属性是协议在所有条件下正常工作的最低要求。
有关示例实现,请参见示例的未知信号属性部分。
时间关系
协议中的信号之间的定时关系可以使用sequences和properties来描述。如果一个被覆盖的sequence完成,或者一个断言和被覆盖的覆盖属性通过,那么可以为相关函数假定功能覆盖率。对于APB3协议,可以定义以下时序关系:
- 一旦在逻辑1处对PREADY进行采样,PENABLE将在下一个时钟边缘处变低
- 当PSEL线进入逻辑1时,以下信号应保持稳定,直到在逻辑1处对PREADY进行采样时循环结束
- PSEL
- PWRITE
- PADDR
- PWDATA (iff PWRITE处于逻辑1)
- 总线传输之间至少应有一个时钟周期,其中PENABLE为逻辑0
- 当PSEL线路连接到逻辑1时,PENABLE应连接到以下时钟边缘上的逻辑1。有关这些属性的实现,请参见示例页面上的时序关系部分