第二章:验证计划制定——如何编写验证计划、功能覆盖率与代码覆盖率的定义、验证指标(KPI)的设定
各位同学,大家好。上一章我们聊了验证策略的顶层设计,今天咱们来点实际的——怎么把一张白纸变成一份能打仗的验证计划。
说实话,我见过太多团队,一上来就写代码、跑仿真,结果跑到一半发现“哎?这个功能测了吗?”“那个场景漏了”。嗯,这就是典型的“没有计划就开干”。我个人习惯,拿到一个模块需求后,第一件事不是开仿真环境,而是坐下来写验证计划。你想想看,盖房子还得先画图纸呢,验证这么复杂的事,怎么能凭感觉来?
2.1 验证计划(Verification Plan)到底写什么?
验证计划,说白了就是一份“测试说明书”。它告诉整个团队:我们要测什么、怎么测、用什么工具测、测到什么程度算完。
一份合格的验证计划,至少包含以下内容:
- 模块功能描述:这个模块是干什么的?输入输出是什么?
- 功能点分解:把大功能拆成小功能点,每个点都要可验证。
- 测试场景设计:正常场景、异常场景、边界场景、压力场景。
- 验证方法:定向测试?随机测试?形式化验证?
- 覆盖率目标:功能覆盖率、代码覆盖率分别要达到多少。
- 时间节点:什么时候出第一版?什么时候冻结?
重要提醒:验证计划不是写一次就完事的。我在项目中遇到过,计划写得太死,结果RTL改了三次,计划也跟着改了三版。所以,计划要有弹性,建议每两周review一次。
2.2 功能覆盖率 vs 代码覆盖率——别再傻傻分不清
这两个概念,我每次面试新人都会问。很多人答不上来,或者混为一谈。今天咱们一次讲清楚。
2.2.1 代码覆盖率
代码覆盖率,衡量的是“你的仿真代码跑了多少RTL代码”。它是个定量指标,工具自动统计,不需要你写任何额外代码。
常见的代码覆盖率类型:
| 类型 | 含义 | 我踩过的坑 |
|---|---|---|
| 行覆盖率 | 每行代码是否被执行过 | 曾经有个模块行覆盖率100%,但功能全错——因为所有行都跑了,但数据路径错了 |
| 翻转覆盖率 | 每个信号是否从0变1、从1变0 | 翻转覆盖率低,说明你的测试向量太“温柔”了 |
| 条件覆盖率 | if-else、case等分支是否都走到 | 这个最容易漏,尤其是else分支 |
| 状态机覆盖率 | 状态机的每个状态、每条跳转是否都覆盖 | 我见过一个状态机,跳转条件写错了,覆盖率还100%——因为跳转条件永远为真 |
警告:代码覆盖率100% ≠ 验证充分。它只能告诉你“代码跑了”,不能告诉你“功能对了”。我曾经有一个项目,代码覆盖率98%,但功能覆盖率只有60%,结果流片回来发现一个边界情况没测到……嗯,那次的教训很深刻。
2.2.2 功能覆盖率
功能覆盖率,衡量的是“你关心的功能场景是否都测到了”。它需要你手动定义,用covergroup、coverpoint、cross等结构来描述。
举个例子,假设你有一个FIFO模块,你关心的功能点可能是:
- 写操作:写满、写空、写半满
- 读操作:读空、读满、读半满
- 同时读写:写的同时读、读的同时写
- 复位行为:复位后状态是否正确
这些功能点,代码覆盖率是测不到的。你必须自己写covergroup来“告诉”仿真器:嘿,帮我盯着这些场景。
我的小技巧:写功能覆盖率时,别贪多。我建议先列出10-15个核心功能点,覆盖率达到90%以上后,再补充细节。否则你可能会陷入“为了覆盖率而写覆盖率”的陷阱。
2.3 验证指标(KPI)的设定——定多少才算够?
这个问题,几乎每个项目经理都会问。我的回答是:没有标准答案,但有经验法则。
2.3.1 常见的验证KPI
| KPI名称 | 定义 | 我建议的目标值 |
|---|---|---|
| 代码行覆盖率 | 被执行的代码行数 / 总行数 | ≥ 95% |
| 翻转覆盖率 | 信号翻转次数 / 总可能翻转次数 | ≥ 90% |
| 条件覆盖率 | 分支条件覆盖比例 | ≥ 95% |
| 功能覆盖率 | 已覆盖功能点 / 总功能点 | ≥ 95% |
| 断言通过率 | 通过的断言数 / 总断言数 | 100% |
| 回归测试通过率 | 通过的回归用例 / 总回归用例 | 100% |
注意:这些目标值不是死的。比如,对于安全关键模块(如汽车电子、医疗设备),功能覆盖率我建议定到99%以上。而对于一些简单的控制逻辑,90%可能就够了。我在做AI加速器项目时,功能覆盖率只定了85%——因为那模块太复杂了,100%覆盖不现实,而且边际收益很低。
2.3.2 如何设定合理的KPI?
我个人习惯分三步走:
- 先定底线:哪些指标是必须达标的?比如断言通过率必须100%,回归测试必须全绿。
- 再定目标:根据模块复杂度、项目周期、团队经验,定一个“跳一跳够得着”的目标。
- 最后留余量:别把目标定得太满。我一般会留5%的余量,防止RTL改动导致覆盖率下降。
举个例子,我之前负责一个DMA控制器模块:
- 底线:断言通过率100%,回归测试100%
- 目标:代码覆盖率95%,功能覆盖率90%
- 余量:允许5%的波动
结果呢?项目结束时,代码覆盖率96.3%,功能覆盖率92.1%。嗯,刚刚好。
2.4 验证计划模板——拿来就能用
说了这么多,给大家一个我常用的模板框架。你直接复制过去,填内容就行。
# 验证计划模板
## 1. 模块概述
- 模块名称:
- 功能描述:
- 输入输出接口:
## 2. 功能点分解
- 功能点1:描述 + 验证方法
- 功能点2:描述 + 验证方法
- ...
## 3. 测试场景
- 正常场景:
- 异常场景:
- 边界场景:
- 压力场景:
## 4. 覆盖率计划
- 代码覆盖率目标:95%
- 功能覆盖率目标:90%
- 关键功能点列表:
## 5. 验证环境
- 仿真工具:
- 验证语言:
- 断言库:
## 6. 时间节点
- 第一版验证环境:第X周
- 第一轮回归:第Y周
- 覆盖率收敛:第Z周
- 验证冻结:第W周
## 7. 风险与缓解措施
- 风险1:... 缓解措施:...
- 风险2:... 缓解措施:...
提示:这个模板我用了好几年,每次项目开始前,花半天时间填完。别小看这半天,它能帮你省下后面几周的返工时间。你想想看,是不是这个道理?
2.5 避坑指南——我踩过的那些坑
最后,分享几个我亲身经历过的教训:
- 坑1:计划写得太细——我曾经把每个测试用例的输入都写死了,结果RTL一改,计划全废。后来我学乖了,只写“测什么”,不写“怎么测”。
- 坑2:忽略覆盖率之间的关联——代码覆盖率和功能覆盖率是互补的,不是替代关系。我见过有人只盯着代码覆盖率,功能覆盖率一塌糊涂,结果漏了一个关键场景。
- 坑3:KPI定得太高——有个项目,老板要求功能覆盖率100%。结果团队花了两个月从98%追到100%,最后发现那2%是根本不可达的dead code。嗯,白白浪费了两周。
- 坑4:计划不更新——验证计划不是写一次就完事的。RTL改了,spec改了,计划也得跟着改。我建议每两周review一次,确保计划跟得上变化。
好了,这一章的内容就到这里。下一章我们聊聊验证环境的搭建——怎么搭一个高效、可复用的验证平台。到时候见!
公众号:蓝海资料掘金营,微信deep3321