验证方法论

第 10 章 · 共 15 章

基于风险的优先级:先写什么

第 3 章那套分类法产出的场景,并不是每一个都同样值得先写。一套似然度/影响力框架,套用在 axil_regfile 真实的开放缺口上——其中一项还有能找到的最有力证据:这块 RTL 恰好已经产生过一个真实的、上线过的 bug。

第 3 章把 axil_regfile 的功能清单套进四个类别,得出了一份看起来像是排好优先级的开放场景清单——但它其实压根还没排优先级。它只是一份清单,顺序是各个类别恰好被讲到的顺序。排期从来没有长到能同时把所有场景都写一遍,而按清单从头写到尾、按它被生成出来的顺序写,根本不是一个计划——那是一次意外,穿着计划的外衣。这一章要做的判断,正是把这份清单变成一个顺序。

两条轴,不是一条

风险是似然度乘以影响力,值得把这两者分开看,而不是靠一个"这个看起来挺重要"的直觉笼统带过:

  • 似然度 ——这一块地方真的藏着一个还没被发现的 bug 的可能性有多大。依据是相关逻辑在结构上到底有多精细易错,这个具体区域有没有已经产生过一个已知的 bug(如果有,这是能找到的最有力信号),以及这个场景属不属于一类历来就容易藏 bug 的类别——独立/并发的握手逻辑和复位/恢复路径,在真实的验证项目里都是出了名的这样,不只是这一个项目。
  • 影响力 ——如果这一块地方的 bug 真的漏过去了,后果有多严重。依据是波及范围(一个 bug 能影响到共享总线基础设施,还是只局限在一个寄存器私有的行为里)、这个场景碰的是不是 DUT 核心承诺的契约还是一个边角细节,以及这个失败一旦发生有多容易被注意到——一个响亮、明显的失败,比一个安静的、看起来还算合理的错误答案,危险程度要低。

这两条轴都跟一个场景写起来有多便宜不是一回事——这个区别值得留到这一章结尾再回过头来细说。

给真实的开放缺口打分

下面每一行都是第 3 章的一个真实发现,不是编出来的例子:

场景似然度影响力为什么
AW 和 W 在不同周期到达这块 RTL 区域恰好已经产生过一个真实的、上线过的 bug:uvm-advanced 第 1 章找到并修复的那个组合逻辑环,就活在同一段 AW/W 锁存逻辑里。而这段逻辑专门用来处理的那个具体情况——在不同周期到达——一次都没有被真正跑过,所以在一个本来就已知精细易错的区域上,实测层面的信心是零。这里的 bug 会落在共享的写路径基础设施上,不是某一个寄存器私有的行为。
A7:B 响应还挂着的时候来了新的 AW/W中高跟同一块写路径区域一样精细易错的寄存器状态逻辑,只是结构上比 AW/W 锁存本身简单一些。如果这里坏了,一个 master 的事务可能会在背压下被悄悄丢掉或者弄错——跟上一行同样的共享基础设施波及范围。
D2:事务中途触发复位中低复位那块逻辑本身是这份清单里结构上最不精细的——就一个 if (!aresetn)。但一条坏掉的恢复路径能把总线卡死,而 AXI 是共享基础设施,这能让互联上的其他一切都跟着挂住,不只是这一个外设。复位恢复类 bug 也是出了名容易被忽略的一类,原因正是这个项目自己的历史所展示的:复位出于习惯只在最开始触发一次,之后再也没被碰过。
ENABLE=0 时写 DATA中高这段 RTL 就一个普通的条件语句(if (ctrl_enable) count_reg <= count_reg + 1;),结构上大概是这个 DUT 里最简单的部分了。但 ENABLE 门控计数器,正是这个外设存在的全部意义——如果这里被悄悄破坏了,下游关于 irq 什么时候能置位、什么时候不能置位的每一个假设也都会跟着错。
STATUS/COUNT/未映射地址中低机械的 case 语句逻辑,三个不同的分支,每一个都可能各自独立出错。不过一个错误的响应码是看得见的——软件本来就该看到并且处理 SLVERR/DECERR,所以这里的 bug 不会像一个悄悄算错的计数器那样安安静静地藏起来。
CTRL 读回来大概是这个 DUT 里最简单的 RTL 行为了,而且局限在一个寄存器的读回值上——这种 bug 几乎肯定会在任何人出于任何理由第一次尝试把 CTRL 读回来的时候就冒出来,不用非得是这个场景。

上面没有一行用编出来的数字打分,这是故意的——一个 1 到 5 的量表乘出一个整整齐齐的优先级数字,看起来比一张朴素的高/中/低表格更严谨,但其实不然;它只是把同样的判断藏在了一层虚假的精确度后面。"为什么"这一列里的推理才是真正的论据。标签只是对它的概括,不是替代品。

这实际上改变了什么

只按风险排序,顺序是:AW/W 独立性,然后是 A7 的背压场景,然后是事务中途复位,然后是受 ENABLE 门控的 DATA 写,然后是非法地址写操作,CTRL 读回排在最后。这是一个真实的排序,但它跟 Coverage 第 6 章从完全不同的角度——补上的成本——得出的排序不是同一个。

Coverage 第 6 章已经把这同一批缺口的成本那一面给定了下来:STATUS/COUNT/未映射地址的写操作只需要四行定向测试就能补上,不需要任何新基础设施。AW/W 独立性这个缺口和 A7 的背压场景,都需要目前还不存在的新 sequence 或 driver 能力——是真正更贵,不只是排在待办清单靠后的位置而已。风险排序和成本排序在这里是故意不一致的,一份真正的排期必须同时装下两者,而不是选一个、无视另一个。

解法不是"风险说了算",也不是"成本说了算"——而是既按风险、也按提前量来排期。AW/W 独立性这项工作,既是清单上风险最高的一项,是离能产出一个通过的测试最远的一项,因为对应的 driver 能力得先造出来才行。提前动手,哪怕它不会是第一个亮绿灯的东西,才是不让它在排期用完的时候依然还开着的办法——这是一种真实、常见的失败模式:风险最高的那一项,恰恰因为它是启动成本最高的那一项,才被推到"以后再说",而"以后"往往从来没有真正到来。便宜、风险较低的那几项——STATUS/COUNT/未映射地址的写操作、受 ENABLE 门控的 DATA 写——是并行写的,不是用来替代前者的:真实、快速的风险下降,不需要等任何别的东西先做完。

小结

  • 风险是似然度乘以影响力,要分开评估——一个场景可以似然度很低,却依然是高优先级,只要漏掉它的影响力足够严重;反过来也一样。
  • 关于似然度,最有力的证据(如果存在的话)是这块区域已经真实产生过一个 bug——axil_regfile 的 AW/W 锁存逻辑就有一个,来自 uvm-advanced 第 1 章,这也是为什么同一段逻辑里那个还没测过的情况在这里排名最高。
  • 影响力随波及范围扩大:共享总线握手基础设施里的一个 bug,能影响的不只是它所在的那个外设,这也是为什么事务中途复位在影响力上排名很高,尽管对应的 RTL 相对简单、似然度也比较低。
  • 编出来的数字打分并不比一张有理有据的高/中/低表格更严谨——它只是把同样的判断藏在了一层虚假的精确度后面。
  • 风险排序和补上成本的排序可以不一致,而且两者都重要:这里风险最高的一项,也是补上成本最高的一项,这恰恰是主张让它最早启动、跟便宜的那几项并行推进,而不是选一种排序、无视另一种的理由。

一个场景写成定向测试很便宜,风险也相对较低。另一个场景造起来很贵(需要新的 driver 能力),风险也很高。在这套框架里,“写起来便宜”和“优先级高”之间是什么关系?

为什么 AW/W 独立性这个场景的似然度具体被评为“高”——引用的最有力证据是什么?

事务中途复位(D2)似然度是“中低”——复位那块 RTL 本身结构上很简单——但影响力是“高”。为什么它依然算得上一个值得排优先级的真实风险,而不是因为概率低就被当成低优先级打发掉?

AW/W 独立性这个缺口,既是风险最高的一项,又是补上成本最高的一项(需要新的 driver 能力)。这一章主张应该怎么给它排期?