4、功能仿真验证:验证计划覆盖率、功能测试用例完备性、回归测试结果
功能仿真验证,说白了就是给你的芯片设计做一次「全身体检」。
我见过太多团队,RTL写完了就急着往后跑,结果流片回来发现功能不对。嗯,那滋味可不好受。今天咱们就聊聊,怎么把功能仿真验证这关过得扎实。
4.1 验证计划覆盖率——你测了多少?
覆盖率这东西,很多人觉得就是个数字。我告诉你,数字会骗人。
我个人习惯,先看代码覆盖率。行覆盖率、条件覆盖率、状态机覆盖率,这些是基础。但光看这个不够,你想想看,代码全跑了不代表功能全对了。
关键指标:
- 行覆盖率:每行代码都被执行过吗?目标≥95%
- 条件覆盖率:每个分支条件都测到了吗?目标≥90%
- 状态机覆盖率:所有状态跳转都覆盖了吗?目标100%
- 翻转覆盖率:每个信号都从0变1、从1变0了吗?目标≥80%
我在项目中遇到过一件事。有个模块行覆盖率到了98%,但流片回来就挂了。后来一查,有个条件分支的else路径从来没走过,但行覆盖率显示那行代码被执行了——因为else里是空语句。你看,光看数字多危险。
我的小技巧:覆盖率报告一定要人工review。别只看百分比,要打开报告看看哪些行没跑到,问问自己「为什么没跑到?」
4.2 功能测试用例完备性——你测全了吗?
功能测试用例,说白了就是你的「考题集」。考题出得好不好,直接决定你能不能发现bug。
我一般把测试用例分成几类:
| 类型 | 说明 | 例子 |
|---|---|---|
| 正常功能测试 | 验证基本功能正确 | 读写操作、配置寄存器 |
| 边界测试 | 验证边界条件 | FIFO满/空、计数器溢出 |
| 异常测试 | 验证错误处理 | 非法地址、超时处理 |
| 随机测试 | 随机激励验证 | 随机数据、随机延迟 |
| 压力测试 | 高负载下验证 | 最大带宽、最大并发 |
我曾经吃过一个亏。一个DMA控制器,正常功能全过了,边界也测了。结果有个场景——连续两次中断请求间隔只有1个时钟周期——直接死机。这就是压力测试没做到位。
注意:测试用例不是越多越好。我见过有人写了2000个用例,但全是重复的。关键是要覆盖所有功能点和边界条件。我个人习惯,每个功能点至少配一个正常用例和一个异常用例。
4.3 回归测试结果——改代码后,老功能还正常吗?
回归测试,说白了就是「改完代码后,把以前的测试再跑一遍」。这步很多人嫌麻烦,但我觉得这是性价比最高的验证手段。
我建议回归测试要做到:
- 全量回归:每次提交代码前,跑一遍所有用例
- 自动化:别手动跑,用脚本一键执行
- 结果比对:自动比对预期输出和实际输出
- 失败分析:回归失败要追根溯源
我记得有一次,一个同事改了一行代码,觉得没问题就直接提交了。结果回归测试跑出来,三个模块的功能全乱了。为什么?那行代码改了一个全局信号的时序,影响了一大片。要是没做回归,这bug就流片了。
我的经验:回归测试最好每天跑一次。早上来公司,先看回归报告。如果有失败的,第一时间定位问题。别拖,越拖越难查。
4.4 功能仿真验证的核心逻辑
下面这张图,是我自己总结的功能仿真验证流程。你看一眼就明白了:
这个流程看着简单,但每一步都有坑。我见过有人覆盖率不达标就敢说「差不多了」,结果流片回来一堆bug。也见过有人回归测试只跑一半用例,说「时间不够了」。嗯,时间不够的时候,往往就是出问题的时候。
4.5 避坑指南
我曾经踩过的坑:
- 坑1:只关注行覆盖率,忽略了条件覆盖率。结果条件分支没测到,流片回来功能异常。
- 坑2:测试用例全是正常路径,没有异常路径。结果芯片在异常场景下直接死机。
- 坑3:回归测试只跑增量用例,不跑全量。结果改了A模块,B模块的功能被破坏了都不知道。
- 坑4:覆盖率报告只看数字,不人工review。结果空语句、死代码全被算进去了,数字好看但实际没测到。
我的建议:
- 覆盖率目标定高一点,别给自己留退路。我一般定95%以上。
- 测试用例要分类管理,每个类别都要有代表用例。
- 回归测试自动化,每天跑,雷打不动。
- 每次流片前,做一次完整的验证评审,拉上所有相关人一起过。
功能仿真验证这关,说白了就是「宁可多跑一万个用例,也不要漏掉一个bug」。流片一次几十万上百万,一个bug就能让你全打水漂。你想想看,值不值得花时间把验证做扎实?