验证计划制定:验证目标分解、功能点提取方法、覆盖率定义与优先级划分
做验证这么多年,我最大的体会就是:没有计划的验证,就像没有地图的旅行。你可能跑得很快,但最终发现方向全错了。
今天咱们聊聊验证计划怎么定。说白了,就是回答三个问题:
- 要验证什么?(目标分解)
- 怎么验证?(功能点提取)
- 验证到什么程度算完?(覆盖率与优先级)
一、验证目标分解:把大象装进冰箱分几步?
我刚开始带项目时,经常犯一个错误——拿到芯片 spec 就开始写 testcase。结果呢?写到一半发现漏了很多场景,回头补,项目延期。
后来我学乖了。验证目标分解,我习惯用三层分解法:
- 系统级目标:芯片整体行为是否正确?比如 NPU 能不能正确跑完一个推理网络?
- 模块级目标:每个子模块功能是否正常?比如卷积计算单元、激活函数单元。
- 场景级目标:特定工作模式下是否 OK?比如低功耗模式、异常中断处理。
核心原则:每个目标必须可量化、可验证。别写「性能要好」这种废话,要写「在 1GHz 时钟下,卷积计算延迟不超过 100 个 cycle」。
举个例子。我之前做的一个 NPU 项目,验证目标分解成这样的表格:
| 层级 | 验证目标 | 验收标准 |
|---|---|---|
| 系统级 | ResNet-50 推理正确 | Top-1 准确率 ≥ 76% |
| 模块级 | 卷积单元 | 所有 kernel 尺寸(1x1,3x3,5x5)正确 |
| 场景级 | 动态电压频率调整 | 频率切换时无数据丢失 |
二、功能点提取方法:别漏掉任何一个角落
功能点提取,说白了就是把 spec 翻译成验证语言。我见过太多人拿着 spec 直接写 testcase,结果漏掉边界条件。
我个人常用的方法叫「五步提取法」:
- 读 spec,划重点:把每个功能描述圈出来,包括正常模式、异常模式、边界条件。
- 画状态机:每个模块的状态转换图必须画出来。我踩过坑——有一次漏了「空闲→忙→空闲」这个状态回环,结果仿真时死锁了。
- 列接口协议:每个输入输出信号怎么交互?握手协议、超时机制、错误响应。
- 找交叉场景:多个功能同时触发会怎样?比如卷积计算时同时收到复位信号。
- 加随机因子:哪些参数可以随机化?比如数据值、地址偏移、延迟时间。
小技巧:我习惯用 Excel 管理功能点,每行一个功能点,列包括「功能描述」「验证方法」「覆盖率类型」「优先级」。这样后期写 testplan 时直接导出,省事。
这里我画了一张功能点提取的流程图,帮你理清思路:
三、覆盖率定义:你说验证完了,证据呢?
「验证完了」这句话,在我这必须有数据支撑。覆盖率就是那个证据。
我一般把覆盖率分成三类:
- 代码覆盖率:行覆盖、条件覆盖、状态机覆盖。这是基础,但别迷信——代码覆盖率高不代表功能正确。
- 功能覆盖率:这才是重点。每个功能点有没有被覆盖到?边界值有没有跑到?
- 断言覆盖率:你写的断言有没有被触发?没触发说明要么断言写错了,要么场景没跑到。
我曾经踩过的坑:有一次项目代码覆盖率 98%,但流片回来还是挂了。为什么?因为功能覆盖率只有 60%。从那以后,我强制要求功能覆盖率必须 ≥ 95% 才能 tapeout。
覆盖率定义时,我习惯用这个模板:
// 功能覆盖率示例 - NPU 卷积模式
covergroup conv_mode_cg @(posedge clk);
mode_cp: coverpoint conv_mode {
bins normal = {MODE_NORMAL};
bins bypass = {MODE_BYPASS};
bins all_modes[] = {[MODE_MIN:MODE_MAX]};
illegal_bins reserved = {MODE_RESERVED};
}
kernel_cp: coverpoint kernel_size {
bins small[] = {1, 3};
bins large = {5};
bins illegal = {7, 9}; // 不支持
}
cross_mode_kernel: cross mode_cp, kernel_cp;
endgroup
四、优先级划分:资源有限,先干重要的
做验证最怕什么?什么都想测,结果什么都没测透。优先级划分,说白了就是在有限的时间和资源下,做最关键的验证。
我自己的划分标准是这样的:
| 优先级 | 定义 | 举例 | 验证策略 |
|---|---|---|---|
| P0 | 功能正确性的基石 | 卷积计算结果正确 | 定向测试 + 形式化验证 |
| P1 | 常见使用场景 | 连续推理多个网络 | 随机测试 + 回归 |
| P2 | 边界/异常场景 | 输入数据全0或全1 | 边界测试 + 错误注入 |
| P3 | 性能/功耗相关 | 不同频率下的吞吐量 | 性能仿真 + 功耗分析 |
我的习惯:P0 的 testcase 必须全部通过才能进入下一阶段。P1 可以留少量 bug,但必须评估风险。P2/P3 看项目进度,实在来不及可以砍掉。
嗯,这里要注意一点:优先级不是一成不变的。我在项目中遇到过,某个 P2 的功能点,因为客户特别要求,临时升到了 P1。所以验证计划要留出调整空间。
五、避坑指南:那些年我交过的学费
最后分享几个实战经验:
- 别等 spec 完全冻结再开始写验证计划。我一般拿到初版 spec 就开始搭框架,后面迭代更新。等 spec 冻结再动手,黄花菜都凉了。
- 功能点提取时,让设计工程师一起参与。他们最清楚哪些 corner case 容易出问题。我一个人闭门造车,漏掉过不少场景。
- 覆盖率目标要写进验证计划里。比如「功能覆盖率 ≥ 95%,代码覆盖率 ≥ 90%」。没有目标,验证就是无底洞。
- 定期 review 验证计划。我习惯每两周和团队过一遍,看看有没有新增的功能点,或者哪些优先级需要调整。
验证计划制定,说白了就是把「不知道」变成「知道」的过程。你花在计划上的时间,会在后期十倍百倍地省回来。别急着写代码,先把计划做扎实了。
公众号:蓝海资料掘金营,微信deep3321