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 功能仿真验证的核心逻辑

下面这张图,是我自己总结的功能仿真验证流程。你看一眼就明白了:

功能仿真验证核心流程 制定验证计划 确定覆盖率目标 编写测试用例 正常/边界/异常/随机 执行仿真 运行所有测试用例 分析覆盖率 代码+功能覆盖率 回归测试 全量自动化回归 结果审查 人工review报告 覆盖率达标? 否:补充用例 是:验证通过 验证完成 ✓

这个流程看着简单,但每一步都有坑。我见过有人覆盖率不达标就敢说「差不多了」,结果流片回来一堆bug。也见过有人回归测试只跑一半用例,说「时间不够了」。嗯,时间不够的时候,往往就是出问题的时候。

4.5 避坑指南

我曾经踩过的坑:

  • 坑1:只关注行覆盖率,忽略了条件覆盖率。结果条件分支没测到,流片回来功能异常。
  • 坑2:测试用例全是正常路径,没有异常路径。结果芯片在异常场景下直接死机。
  • 坑3:回归测试只跑增量用例,不跑全量。结果改了A模块,B模块的功能被破坏了都不知道。
  • 坑4:覆盖率报告只看数字,不人工review。结果空语句、死代码全被算进去了,数字好看但实际没测到。

我的建议:

  • 覆盖率目标定高一点,别给自己留退路。我一般定95%以上。
  • 测试用例要分类管理,每个类别都要有代表用例。
  • 回归测试自动化,每天跑,雷打不动。
  • 每次流片前,做一次完整的验证评审,拉上所有相关人一起过。

功能仿真验证这关,说白了就是「宁可多跑一万个用例,也不要漏掉一个bug」。流片一次几十万上百万,一个bug就能让你全打水漂。你想想看,值不值得花时间把验证做扎实?


专注资料整理