一、验证的困境:为什么需要随机激励?
做芯片验证的朋友,应该都遇到过这种场景:
写了几百条定向测试用例,功能覆盖率也到了90%。结果芯片一回来,某个从来没测到的组合直接翻车。嗯,这种痛,我经历过不止一次。
为什么会这样?说白了,定向测试就像你拿着手电筒在黑屋子里找东西——你只能看到光照到的地方。而芯片里那些bug,偏偏喜欢躲在阴影里。
从定向测试到随机测试的演进
早期验证,大家都是写定向用例。比如测一个加法器:
- 测1+1=2
- 测0+0=0
- 测最大值+1=溢出
看起来挺全的,对吧?但问题来了——你写的用例,都是你想到的场景。而芯片出bug的地方,往往是你没想到的。
我记得有一次做总线验证,定向用例跑了上千条,覆盖率报告漂漂亮亮。结果随机测试跑了10万轮,直接抓到一个地址对齐的bug。那个bug的条件组合,我写定向用例时根本不会想到。
核心观点:定向测试验证的是"设计应该做什么",随机测试验证的是"设计不应该做什么"。
随机测试的演进,其实是被逼出来的。芯片越来越复杂,定向用例的编写成本指数级上升。你想想看,一个现代SoC有几十亿个晶体管,靠人脑穷举所有场景?不现实。
所以业界开始用随机激励。让工具自动产生各种输入组合,覆盖那些"你想不到"的边界情况。我个人习惯的做法是:
- 70%的随机用例——用来扫边界
- 20%的定向用例——用来测核心功能
- 10%的异常用例——用来测错误处理
覆盖率的定义与重要性
覆盖率这东西,说白了就是一把尺子。量一量你的验证到底做了多少。
常见的覆盖率类型:
| 类型 | 定义 | 我踩过的坑 |
|---|---|---|
| 代码覆盖率 | 代码被执行的比例 | 代码覆盖率100%,功能照样出bug。因为代码跑了不代表功能对了 |
| 功能覆盖率 | 功能点被覆盖的比例 | 这个才是关键。我曾经只盯着代码覆盖率,结果漏了一个状态机跳转 |
| 翻转覆盖率 | 信号0/1跳变的覆盖 | 适合检查复位、时钟这类信号 |
| 断言覆盖率 | 断言被触发的比例 | 断言写得好,bug跑不了 |
警告:覆盖率100% ≠ 验证完备。它只能告诉你"哪些测过了",不能告诉你"哪些没测到"。我曾经见过一个项目,功能覆盖率98%,结果漏掉的那个2%恰恰是致命bug。
这里有个关键点——覆盖率是验证的指南针,不是终点线。我习惯的做法是:
- 先定功能点,写覆盖组
- 跑随机,看覆盖率增长
- 覆盖率停滞了?说明有"盲区"
- 针对盲区加定向用例或约束
- 重复2-4,直到收敛
随机激励与覆盖率的协同关系
随机激励和覆盖率,就像锁和钥匙的关系。没有覆盖率,随机测试就是瞎跑。没有随机激励,覆盖率就是摆设。
我画了一张图,帮你理解这个协同逻辑:
这张图的核心逻辑很简单:
- 随机激励负责"广撒网"
- 覆盖率负责"看哪里没撒到"
- 反馈回路负责"调整撒网方向"
我的经验:刚开始做随机验证时,我总想着一次把约束写完美。后来发现,更好的做法是"先粗后细"——先放开约束跑,看覆盖率哪些地方增长快、哪些地方停滞。停滞的地方,就是你需要加约束或者加覆盖点的地方。
一个简单的代码示例
用SystemVerilog举个随机激励的例子:
class Packet;
rand bit [7:0] addr;
rand bit [7:0] data;
rand bit wr; // 0:读, 1:写
// 约束:地址范围限制
constraint addr_range {
addr inside {[0:100], [200:255]};
}
// 约束:写操作时数据不能为0
constraint data_valid {
if (wr) data != 0;
}
endclass
// 测试代码
Packet pkt = new();
repeat (1000) begin
assert(pkt.randomize());
// 驱动到DUT
drive_to_dut(pkt);
end
这段代码里,rand关键字告诉工具:这些变量要随机生成。constraint则限制了随机范围。我个人习惯把约束写得尽量宽松,让随机有足够的"探索空间"。
避坑指南:我曾经犯过一个错误——约束写得太死,导致随机空间只有几十种组合。跑了一百万轮,覆盖率纹丝不动。后来才发现,约束把大部分有效输入都过滤掉了。记住:约束是用来引导随机的,不是用来限制随机的。
覆盖率驱动的验证方法论
现在主流的验证方法论,比如UVM,核心就是"覆盖率驱动"。说白了就是:
- 定目标(覆盖率指标)
- 生成激励(随机为主)
- 收集反馈(覆盖率数据)
- 调整策略(加约束/加用例)
- 重复直到收敛
这个过程,我称之为"验证的PDCA循环"。你想想看,如果没有覆盖率这个"仪表盘",你根本不知道验证做到什么程度了。就像开车没有速度表——你只知道在跑,但不知道跑多快、方向对不对。
嗯,这一章的内容就到这里。记住一句话:随机激励让你发现未知的bug,覆盖率让你知道还有多少未知。两者缺一不可。