Verilator --timing 取舍:什么时候必须开,开了到底慢多少
零、一句话精髓
> **#/@ 放在 C++ 测试文件里 → 无须 --timing,不影响仿真速度;
> 放在 SV 测试文件里 → 必须 --timing,进而影响仿真速度。**
选择摆在面前时,答案就一条:能用 C++ 写的时序行为,就别留在 SV 里。
一、唯一主轴
> **开不开 --timing,跟着「#/@ 写在不在被 Verilator 编译的 SV 里」走;
> 慢不慢,跟着「这些构造跑起来产生多少事件」走。**
#/@ 在哪 |
--timing |
代价 |
|---|---|---|
| SV(进编译列表的部分) | 必须开,不开直接编译报错 | 有调度开销 |
| 等价功能改写在 C++ 里 | 不需要开 | 零调度开销 |
二、把边界钉死(三个精确化)
- 「SV 测试文件」= 所有进编译列表的 SV,不只是狭义 TB。
sim_main.cpp(C++ 主控)+ sim_top.sv(观测 wrapper)+ DUT:只要 wrapper 和 DUT 里没有 #/@,就不用开。
机械判断法:--no-timing 编一下,报错的就是残留构造所在的文件。
- 开销大小 ≠ 开没开,= SV 里 timing 构造的事件频率。
--timing 只是门票,真正花时间的是时间轮里排队的事件。
| 情形 | 速度影响 |
|---|---|
开了 --timing 但 SV 里已无 #/@(忘了关) |
队列空转,个位数 %,基本无感 |
SV 里留一个慢速 always #(如 1s 级看门狗时钟) |
事件稀疏,影响小 |
SV 里放 always #1360 clk=~clk 主时钟 |
每半拍一事件,提速从 5~20× 缩到 2~5× |
- 迁移期「全清零才能关」:SV 里只要还剩一个
#,就必须开着--timing。
--no-timing(tb_full 就是已到终态的样子)。
三、一句校正
说「C++ 不影响速度」更准确的说法是:
> C++ 驱动也要一拍调一次 eval(),这是周期仿真的本职工作,不是额外开销;
> 省掉的是事件队列、进程挂起/恢复、以及没人需要的负沿求值。
四、一句话行动项
搬完最后一块再关--timing;关之前用 --no-timing 编一次,报错的文件就是还没搬干净的。