作为一个验证工程师我经常被问到这样的问题:"处理器的验证什么时候完成?"或者换句话说,"我该如何衡量测试平台的效率,我如何对验证的质量建立信心?"。当然这一问题没有简单的答案。业界有几个常用的指标可以参考,如覆盖率和错误曲线。虽然这些指标是绝对必要的,但它们并不足以达到尽可能高的处理器品质。事实上,这些指标并不能真正揭示验证方法找到最后一个bug的能力。随着经验的积累,我了解到检测处理器漏洞的复杂性是一个很好的指标,并可以在项目的整个开发过程中使用。
是什么定义了处理器漏洞的复杂性以及如何检测它?
经验告诉我,我们可以通过计算击中漏洞所需的独立事件或条件的数量来定义一个漏洞的复杂性。
那么“事件”又如何定义呢?
让我们举一个简单的例子。当缺少所需的警告时,一个典型的bug会在缓存中发现一个典型的漏洞。此时数据损坏可能发生在以下情况:
A cache line at address @A is Valid and Dirty in the cache.
A load at address @B causes an eviction of line @A.
Another load at address @A starts.
The external write bus is slower than the read, so the load @A completes before the end of the eviction.
External memory returns the previous data because the most recent data from the eviction got lost, causing data corruption.
在这个例子中,我们需要4个事件或条件来击中这个漏洞。这4个事件给这个bug打了4分,也就是说漏洞的复杂性为4。
对处理器漏洞进行分类?
为了衡量一个漏洞的复杂性,我们可以对漏洞进行分类,供整个处理器验证团队来使用。在之前的一篇博文中,我们讨论了4种类型的bug,并解释了我们如何使用这些分类来提高测试平台和验证的质量。此时我们可以再进一步,即将这种方法与漏洞的复杂性结合起来处理问题。
一个简单的漏洞可能需要触发1到3个事件。那么第一个简单的测试就会失败,而一个极端案例可能会需要4个或更多的事件。
回到我们上面的例子,我们有一个复杂性为4的bug,如果四个条件中的任何一个不存在,那么这个bug就不会被击中。
一个受限的随机测试平台需要几个功能,以便能够击中上文例子中的漏洞。地址序列应该足够聪明,可以重用之前请求的地址,外部总线上的延迟也应该足够非典型,以便有足够快/慢的读写。
而一个隐藏比较深的案例可能需要更多的事件来触发。假定一个更微妙的bug与我们的例子有相同的条件,但是它只发生在缓存上发现ECC错误的时候,与中断发生的时间完全一致,并且只发生在内核完成FPU操作导致除以0错误出现的时候。在典型的随机测试平台上,所有这些条件同时出现的概率是非常低的,这使得它成为一个 "隐藏 "的终极漏洞。
为了使得这些隐藏的bug在测试平台上更容易被发现,提高验证的质量是重点。它包括使隐藏的个例成为极端的个例此种情况。
如图所示,4只红色昆虫分别代表4种类型的CPU漏洞
这种分类没有任何限制。经验告诉我们,一个能够找到8分或9分漏洞的测试平台本身就是一个强大的模拟测试平台,是提供高质量RTL的关键。根据我们的观察,今天最先进的仿真测试平台可以找到复杂度高达10的漏洞。幸运的是,形式化验证的使用使我们更容易找到复杂度更高的bug,为更好的设计铺平道路,并为仿真中需要改进的地方提供线索。
使用漏洞的复杂性分类来提高验证测试平台的质量
这种分类和方法只有在验证开始时和整个项目开发过程中使用才有效,原因有二:
漏洞必须在被发现时即时修复。留下一个2级或3级的bug而不即时修复,则意味着在启动大型浸泡测试(soak test)时会出现大量的失误。据统计,一个需要更多事件的类似bug(来自同一漏洞集群)可能会被忽略。
漏洞的复杂性被用来改善和衡量测试平台的质量。复杂性水平与触发漏洞所需的事件数量越匹配,复杂性得分越高,测试平台的压力越大。追踪和分析触发漏洞的事件对于了解如何调整随机约束或创建新的功能覆盖点来说非常有用。
最后,通过将这种方法与Codasip的验证方法结合起来,包括猎杀以集群为单位的bug,确保了高水平的验证质量,帮助我们确信并超越验证验收标准。
审核编辑 :李倩
全部0条评论
快来发表一下你的评论吧 !