验证方法论

第 11 章 · 共 15 章

作为活文档的验证计划:可追溯性

这个模块的收尾:一条把 spec 要求、计划条目、覆盖率条目、真正的测试串起来的链条,套在 axil_regfile 真实的开放缺口上核实——以及一份会不断吸收新信息的验证计划,信息来源既有测量,也有它自己的规划过程,而不是写一次就冻结。

第 1 到 4 章一步一步建起了一份验证计划:它是什么、一份功能清单、一套场景分类法、一个风险排名。这些每一个都是一次快照,定格在写下它的那一刻。这一章是收尾的那一块:一套机制,能把每一个条目从 spec 一路追溯到真正的测试;以及一份会不断吸收新信息、而不是原样停留在写下的那一刻的计划。

可追溯性:四条链,不是一条

每个场景一条链:spec 要求 → 计划条目 → 覆盖率条目 → 测试。每一环都各自有意义,跟别的环存不存在没关系:

  • spec → 计划条目:第 2、3 章的工作——把 spec 做出的一条承诺,拆解成一个具体的场景。
  • 计划条目 → 覆盖率条目:真正会去测量这个场景有没有跑过的那个 SystemVerilog 构造——一个 covergroupcoverpoint、一个 cross、一个 line/branch 报告会追踪的分支。dv-methodology 第 2 章讲过的一个点,正是跟这一环直接相关的:覆盖率是被人写出来的,不是自动就有的。一件事之所以会被测量,是因为一个计划条目告诉了某个人该为它声明一个 coverpoint——一个背后没有计划条目撑着的覆盖率条目,测的只是写这个 covergroup 的人恰好想到了什么,不是 spec 真正要求的东西。
  • 覆盖率条目 → 测试:真正去跑这个场景的那个测试,正是这个测试才会让覆盖率条目的数字真的动起来。

一个计划条目如果缺了对应的覆盖率条目,就算真的有一个测试碰巧跑过了它,也没有人会注意到它其实没被真正测过。一个覆盖率条目如果缺了背后的计划条目,测的是没有人决定过重要的东西。这两种缺口,只从链条的一端看,都是看不见的——这正是为什么要追溯整条链、而不是只问一句"有没有测试"的意义所在。

两个真实的条目,从头追到尾

STATUS/COUNT/未映射地址B2/B3,非法类别,第 2-3 章):spec 要求是 uvm-advanced 第 1 章立足于真实 AXI4-Lite 文本的响应码那一节。计划条目是第 3 章的非法类别场景。覆盖率条目已经存在,而且是两处:addr_x_resp 这个 cross 里合法、目前还没被采样到的 bin(dv-methodology 第 2 章),以及写 case 语句的 SLVERR/DECERR 分支(第 3 章)。测试是唯一缺的那一环,而 Coverage 第 6 章的 waiver log 已经把它标记成随时能补上:四行定向代码,不需要任何新基础设施。

AW 和 W 在不同周期到达A5/A6,并发类别,第 2-3 章):前三环一样——spec 要求(协议的独立性规则)、计划条目(第 3 章)、覆盖率条目,这次分布在两个地方(aw_have/w_have 的 toggle 检查,Coverage 第 4 章;AW_ONLY/W_ONLY 这两个 FSM 状态,Coverage 第 5 章)。这里测试同样是缺的那一环,但原因不一样:Coverage 第 6 章的 waiver log 已经标出补上它需要新的 driver 或者 sequence 能力,不是随手加几行就能搞定的。同样的链条,同样缺的那一环,背后的工作量却真的不一样——这正是这个模块第 4 章主张要把它跟风险本身分开看的那个区别。

两条链都已经建好了四环里的三环。两条都还没完成。用这种方式追溯它们,才让"还没完成"变成一个具体的、可以核实的说法,而不是一种"多测点大概会更好"的模糊感觉。

验证计划会吸收三种新信息

一份写完就撂在一边的计划,只要它下游的任何东西一变,就立刻不再值得信任了。三个变化的来源,都是这个项目真实产生过的:

  • 覆盖率测量找到一个计划里没有的缺口。 dv-methodology 第 3-5 章靠跑真实的报告找到了 STATUS/COUNT/未映射地址的缺口和 aw_have/w_have 的缺口——在这个模块出现之前,从来没有任何地方把它们正式当成计划条目写下来过。一份活的计划会把这个发现吸收成新的一行,而不是让它作为一个事实,停留在一份没人再回头看的覆盖率报告里。
  • 计划自己的系统性流程找到一个测量从来没有单独抓到过的缺口。 这个模块的第 2、3 章自己就找到了四个:受 ENABLE 门控的 DATA 写、把 CTRL 读回来、单笔未完成事务的限制(A7)、事务中途复位(D2)——这四个里没有一个是被 Coverage 第 1-6 章里建的任何 covergroup、分支检查、toggle 检查,或者 FSM 检查抓到过的,因为那些章节里没有任何一个恰好把这四个当成自己独立的条目隔离出来过。计划和测量各自抓到对方抓不到的缺口;一份活的计划,正是两种缺口最终都会落脚的地方。
  • 优先级会变。 这个项目目前还没有真正发生过这种情况——没有相关的 bug 报告或者设计变更进来重新排过第 4 章的排名——但这是计划会变的第三个合理理由,哪怕现在还没有具体例子也值得说明白:关于似然度或者影响力的新信息(别的地方发现了一个相关的 bug、spec 改版了),可以把一个条目的优先级往上或者往下挪,哪怕这个场景本身一点都没变。

那份活的验证计划

把 Coverage 第 6 章的 waiver log 扩展成这个模块追溯过的每一个场景,不只是它原来跟踪的那两个:

Verification Plan Status -- axil_regfile.sv
=====================================================================================================
Scenario                            Priority (ch4)   Coverage item                        Test
-----------------------------------  ---------------  ------------------------------------  --------
AW/W arrive on different cycles      Highest          aw_have/w_have toggle (Cov ch4);      Open --
                                                       AW_ONLY/W_ONLY FSM states (Cov ch5)   backlog
A7: new AW/W while B outstanding     High             none built in Coverage module         Open --
                                                       -- new row, added by this module      new
D2: reset mid-transaction            Notable (impact) none built in Coverage module         Open --
                                                       -- new row, added by this module      new
DATA write while ENABLE=0            Medium           none built in Coverage module         Open --
                                                       -- new row, added by this module      new
STATUS/COUNT/unmapped write          Medium           addr_x_resp cross legal bins,          Open --
                                                       write-case branches (Cov ch2-3)       ready
Reading CTRL back                    Lowest           none built in Coverage module         Open --
                                                       -- new row, added by this module      new

六行里有四行,在这个模块自己的系统性排查找到它们之前,在这个项目里根本没有作为被跟踪的计划条目存在过。这就是"计划会吸收新信息"具体的样子——不是一个假设,而是一张表,里面有几行在这个模块的第 2、3 章跑起来之前根本不存在。

Waiver 不是终点

Coverage 第 6 章把 AW/W 独立性这个缺口标成了"Backlog——需要新的 driver/sequence 能力,不是随手能改完的",然后就翻篇了,因为对一章关于怎么读一份覆盖率报告的内容来说,那样做是对的。放到这个模块的框架里看,那条 waiver 记录跟上面那张表最上面一行,是同一个事实,只是被两份不同的文档各自看到了一遍。"Backlog"从来都不是一个终点——它是一个计划条目,有一个已知的优先级(第 4 章排的最高名次)、一个已知的、它还没做完的原因(缺的是测试基础设施,不是缺理解),还有一个会被重新核对的位置,不是一行只要没人盯着那份具体报告看就悄悄不再重要的记录。

一份计划什么时候算做完?

永远不算,跟 Coverage 第 6 章主张 100% 覆盖率从来都不是真正的目标是同一个道理。一份计划天生的状态是当下有效——可追溯、排好了优先级、对每条链里哪些环存在、哪些环不存在都说得明明白白——而不是终稿。这个模块开篇提的是一个面试问题:只给你一份 spec,你会怎么验证这个模块。五章下来,诚实的答案不是一份语法清单,也不是一个百分比:是这个——一份从 spec 出发、系统地生成了自己的场景、按真正重要的东西排好了优先级、并且每次有新信息进来(不管是靠测量,还是靠它自己再跑一遍规划流程)都会继续变化的计划。这个,而不是一份冻结的文档,才是"覆盖率驱动的判断力"和"验证计划思维"归根结底原来是同一种能力的地方。

小结

  • 可追溯性是一条四环的链——spec 要求、计划条目、覆盖率条目、测试——每一环都能独立核实;链条上任何一处断了,只从一端看的话是看不见的。
  • 从头到尾追溯 STATUS/COUNT/未映射地址的写操作和 AW/W 独立性,能看到两者都已经建好了四环里的三环,缺的都是同一环(测试),但原因真的不一样。
  • 一份活的计划会吸收三种新信息:覆盖率测量找到、但计划里原来没有的缺口;计划自己的系统性流程找到、但覆盖率测量从来没有单独抓到过的缺口;由新信息驱动的优先级变化。
  • 这个模块收尾那张计划表里六个场景中的四个(A7D2、受 ENABLE 门控的 DATA 写、CTRL 读回),是这个模块自己的规划过程找到的新行——证明了这份计划吸收的是单靠测量从来没有产出过的信息。
  • 一条标着"backlog"的覆盖率 waiver 不是一个终点;它是一个计划条目,有已知的优先级和已知的、还没做完的原因,活在一份会被重新核对的文档里,不是一个悄悄不再重要的事实。

代码库里有一个 covergroup 在测量某个 DUT 行为,但没有任何计划条目记录过为什么选中了这个具体行为来测量。按照这一章描述的可追溯性链条,这有什么问题?

这一章收尾那张计划表里六个场景中的四个(A7、D2、受 ENABLE 门控的 DATA 写、CTRL 读回),在 Coverage 模块的任何地方都没有建过对应的覆盖率条目。这说明了什么?

Coverage 第 6 章把 AW/W 独立性这个缺口标成了“Backlog”。按照这一章的框架,这条 waiver 记录实际代表的是什么?

这一章的结尾主张一份验证计划从来都不算真正“做完”。如果不是完成度,真正的目标是什么?