代码覆盖率
在本节中,我们将介绍各种覆盖率度量,这些度量与设计模型的隐式实现覆盖率空间相关联。通常,这些度量与设计模型的隐式实现覆盖空间相关的。通常,这些指标被称为代码覆盖率或结构覆盖率指标。
优点:
代码覆盖率的起源可以追溯到20世纪60年代,是最早为系统软件测试发明的方法之一[1]。代码覆盖率的优点之一是,它自动描述程序的源代码在测试期间被激活的程度,从而识别源代码中在测试期间未被激活的结构。与功能覆盖不同,代码覆盖的一个关键好处是,创建结构覆盖率模型是一个自动过程。因此,将代码覆盖率集成到现有的仿真流中很容易,并且不需要更改当前的设计或验证方法。
局限:
在我们题为“什么是覆盖率”的部分中,为实现成功的测试,我们讨论了在仿真过程中必须存在的三个重要条件,他们是:
- testbench必须产生合理的输入激励以激活设计错误。
- testbench必须产生合理的输入激励,将设计错误产生的所有影响传播到输出端口。
- testbench必须包含一个能够检测设计错误的监视器,该设计错误首先被激活,然后传递到一个检测点。
代码覆盖率是对源代码中在仿真过程中激活的结构的度量。代码覆盖率指标的一个限制是,你可能在回归运行期间实现100%的代码覆盖率,这意味着你的testbench提供了激活RTL源代码中所有结构的激励,但你的设计中仍然存在缺陷。例如,输入激励可能激活了一行包含错误的代码,但testbench没有生成额外所需的刺激,而这些激励将bug的影响传播到testbench中可以检测到的某个点。事实上,研究人员已经研究了这个问题,并发现如果testbench实现了90%的代码覆盖率,那么在模拟运行期间,只有54%的代码被覆盖[2]。这意味着一个bug可能存在于一行被标记为已覆盖的代码上,但由于没有足够的输入激励将bug传播到一个可观察点,该bug从未被检测到。
代码覆盖范围的另一个限制是,它没有提供关于规范书中定义的功能实际被测试的确切指示。例如,你可能会遇到这样一种情况:你实现了100%的代码覆盖率,然后假设您完成了。然而,规范书中定义的功能可能从未经过测试,甚至这些功能可能从未实现过!代码覆盖率指标不会帮助您发现这些情况。
即使有这些限制,代码覆盖的自动方面使它成为testbench上识别输入刺激缺陷的相对简单的方法。在你开始推进高级验证步骤性能时,它是覆盖率指标的最佳首选。
代码覆盖率指标的类型
翻转覆盖率
翻转覆盖率是一种代码覆盖率指标,用于测量寄存器或导线的每一位翻转其值的次数。尽管这是一个相对基本的指标,但许多项目都有一个测试要求,即所有端口和寄存器至少必须经历过0到1和1到0的转换。
总的来说,如果不仔细关注,检查一个翻转覆盖率分析报告可能会让人不知所措,也没有什么价值。例如,翻转覆盖通常用于IP块之间的基本连接检查。此外,了解许多控制结构(如独热码选择总线)已完全执行也是有用的。
行覆盖率
行覆盖率是一种代码覆盖率指标,我们用来确定在仿真期间执行了源代码的哪些行。行覆盖率度量报告将有一个与每行源代码关联的计数,指示该行已执行的总次数。行执行的计数值不仅可用于识别从未执行过的源代码行,而且在工程师认为需要最低行执行阈值以实现充分测试时也很有用。
行覆盖率分析通常表示一个罕见的情形被要求,以激活由于缺少输入刺激而导致的代码行未被覆盖。或者,行覆盖率分析可能会发现,源代码的数据和控制流阻止了它,这要么是因为代码中存在错误,要么是因为在某些IP配置下目前不需要死代码。对于未使用或死代码,你可以选择在覆盖率记录和报告步骤中排除或过滤此代码,这允许您只关注相关代码。
语句覆盖率
语句覆盖率是一种代码覆盖率指标,我们使用它来识别源代码中的哪些语句在仿真过程中被执行了。一般来说,大多数工程师发现,语句覆盖率分析比行覆盖率更有用,因为一条语句通常跨越多行源代码,或者一行源代码上可能出现多条语句。
用于语句覆盖率分析的度量报告将有一个与每行源代码关联的计数,该计数指示语句执行的总次数。该语句执行计数不仅可用于识别从未执行过的源代码行,而且在工程师认为需要达到最低语句执行阈值以实现充分测试时也很有用。
块覆盖率
块覆盖率是语句覆盖率度量的一个变体,用于标识代码块是否已被执行。块被定义为条件语句之间或过程定义内的一组语句,关键点是,如果到达该块,将执行该块内的所有行。该指标用于避免肆无忌惮的工程师通过简单地向代码中添加更多的语句来实现更高的语句覆盖率。
分支覆盖率
分支覆盖率(也称为决策覆盖率)是一种代码覆盖率度量,它报告在控制结构(例如if、case、while、repeat、forever、for和loop语句)中测试的布尔表达式的计算结果是否被同时计算为true和false。整个布尔表达式被视为一个true或false的断言,无论它是否包含逻辑and或逻辑or运算符。
表达式覆盖率
表达式覆盖率(有时称为条件覆盖率)是一种代码覆盖率度量,用于确定每个条件的计算结果是否同时为true和false。条件是不包含逻辑运算符的布尔操作数。因此,表达式覆盖率可以独立地度量布尔条件。
聚焦表达式覆盖率
聚焦表达式覆盖率(FEC),也被称为修改条件/决策覆盖(MC/DC),是DO-178B安全关键软件认证标准以及DO-254正式机载电子硬件认证标准经常使用的代码覆盖率指标。这一指标比条件和决策覆盖率更强。DO-178B对MC/DC的正式定义如下:
程序中的每个入口和出口点都至少被调用过一次,决策中的每个条件都至少产生过一次所有可能的结果,程序中的每个决策都至少产生过一次所有可能的结果,并且决策中的每个条件都被证明会独立地影响决策结果。一个条件被证明是独立地影响决策结果,是通过它只改变该条件,同时保持所有其他可能的条件不变[3]。
值得一提的是,完全封闭式的聚焦表达式覆盖率非同小可。
有限状态机覆盖率
今天的代码覆盖率工具能够识别RTL源代码中的有限状态机。因此,这使得自动提取有限状态机代码覆盖率指标来度量条件成为可能。例如,状态机的每个状态进入的次数,状态机从一个状态转换到每个相邻状态的次数,甚至是顺序arc覆盖率,以识别状态访问转换。
典型的代码覆盖率流程
收集和分析代码覆盖率指标的目的是识别当前验证环境尚未执行的部分源代码。从项目的角度来看,通常最好等到RTL的实现接近完成,然后才开始认真收集和分析代码覆盖率结果。否则,您可能会浪费大量的周期时间,试图从不断变化的RTL代码中理解移动的目标。话虽如此,我们建议您至少在项目周期的早期(即在认真收集覆盖指标之前)运行一些捕获覆盖指标的仿真,以解决覆盖流程中的任何潜在问题。
从高层次的角度来看,代码覆盖流程通常涉及三个主要步骤,包括:
- 检测RTL代码以收集覆盖率范围
- 运行仿真以捕获和记录覆盖率指标
- 报告并分析覆盖率结果
分析步骤的一部分是识别覆盖盲区,并确定覆盖盲区是否由以下三种情况之一造成:
- 缺少激活未覆盖代码所需的输入激励
- 设计(或testbench)中的一个缺陷,它阻止输入激励激活未覆盖的代码
- 某些IP配置未使用的代码或正常运行条件下预期无法访问的相关代码
第一个条件要求你要么编写额外的定向激励,要么调整随机约束,以生成针对未覆盖代码的所需输入激励。第二个条件显然要求工程师修复阻止执行未覆盖代码的错误。第三个条件可以通过设置覆盖率工具在覆盖率记录和报告步骤中排除未使用的或不可达的代码来解决。正规的工具可以用来自动识别不可到达的代码,然后自动生成排除文件。