vvp 日志与跟踪选项:-l、VCD 与 LXT2 的支持边界
更新时间:2026-10-31。本篇只讨论 Icarus Verilog 运行器
vvp的输出通道:终端文本、-l日志与波形文件分别由什么产生。编译期数组诊断是另一类问题,可对照 iverilog 数组下标越界。
本文要回答的问题
vvp -l simulation.log demo.vvp会代替终端输出,还是同时保留两份文本?-l放在输入文件后面,为什么可能没有任何日志文件?- 没有
$dumpfile和$dumpvars时,添加波形相关参数能否自动生成波形? - Icarus Verilog 13.0 的
vvp接受-lxt2后,实际生成的是 LXT2 还是 VCD?
先说答案:本次实测中,正确放置的 -l 会在保留控制台输出的同时写一份日志;放在输入文件后则没有创建目标日志。带 dump 系统任务的测试平台默认生成 ASCII VCD;-lxt2 实际表现为 -l 后紧跟日志名 xt2,文本日志写进 xt2,波形仍是 VCD。没有 dump 系统任务时,它也不会凭空产生波形。
一、vvp 日志与跟踪选项对应三条独立通道
vvp 的文本日志和信号波形不是同一种东西。$display 等输出进入仿真文本流,-l 为文本流增加日志文件;VCD(Value Change Dump,值变化转储)则由测试平台中的 dump 系统任务打开,并记录所选信号随时间的变化。
读这张图要抓住分叉点:-l 不连接波形文件,dump 系统任务也不负责把终端文本保存成日志。蓝色是终端文本,紫色是文本副本,绿色是独立的波形通道。因此,「有 simulation.log」不能证明记录了信号,「有 waves.vcd」也不能证明保存了所有 $display 输出。
二、最小测试平台必须显式打开波形
实验让计数器变化两次,同时打印四条文本。这样一次运行就能区分「人能读到的消息」与「供波形工具读取的值变化」。
initial begin
$dumpfile("waves.vcd");
$dumpvars(0, tb);
clk = 1'b0;
count = 4'd0;
$display("DISPLAY: simulation start");
#5 clk = 1'b1;
count = 4'd1;
$display("DISPLAY: count=%0d", count);
#5 clk = 1'b0;
count = 4'd2;
$display("DISPLAY: count=%0d", count);
$display("DISPLAY: simulation finish");
$finish;
end$dumpfile 指定文件名,$dumpvars(0, tb) 从 tb 层次开始记录信号。少了这两个系统任务,vvp 仍然可以正常执行 $display 和 $finish,但没有创建波形的请求。另一个 no_dump.v 用例专门保留打印、移除 dump,用来排除「运行器默认总会生成波形」的假设。
$dumpvars 的第一个参数控制向下展开的层次数,0 表示包含指定作用域及其下层。它决定记录哪些信号,与 -l 记录哪些文本没有对应关系。若只想缩小波形,可以收窄作用域或减少层次;若只想减少日志,则应调整打印语句或日志保存方式。不要用关闭波形的方法治理终端输出,也不要靠增加 $display 来替代信号值变化记录。
本例还声明了 timescale 1ns/1ps,所以结束信息显示为 10000 ps。时间信息会进入波形,帮助把某条文本与信号变化对齐;但文本里的仿真时刻仍不是波形本身。调试时可以先用 $display 找到可疑时刻,再在 VCD 中检查该时刻前后的时钟、计数器和控制信号,二者是互补证据。
三、-l 是增加日志副本,不是重定向终端
下面的运行记录同时包含控制台与 simulation.log 的内容。两段都有 VCD info、四条 DISPLAY 和 $finish 信息,说明本次 -l 行为更接近复制一份文本日志,而不是把输出从终端搬走。
选项顺序同样重要。帮助给出的形式是 vvp [options] input-file [+plusargs...],所以应写:
vvp -l simulation.log demo.vvp实测的 vvp demo.vvp -l misplaced.log 返回 0,仿真也完整结束,但 misplaced.log 不存在。也就是说,退出成功不能反推出选项已经生效。排查脚本时,除了检查退出码,还应检查文件是否创建、内容是否更新,并把运行器选项统一放在输入文件之前。
还要注意日志范围:这里观察到的是本次运行产生的文本内容,不是任意应用程序日志的通用收集器。若命令外层还使用 shell 重定向,应分别说明 stdout、stderr 和 -l 文件的去向,避免三层配置互相覆盖后误判。
例如,脚本若再执行 vvp -l run.log demo.vvp > console.log 2>&1,就会同时留下运行器维护的 run.log 与 shell 捕获的 console.log。两份文件可能看似重复,但职责不同:前者来自 vvp 的日志选项,后者来自进程外层重定向。复现文档应把完整命令写全,否则读者只看到其中一份文件,很难判断另一份为何存在。
对自动化任务,建议在运行前删除本轮同名旧产物,或使用独立的输出目录。否则,命令这次没有创建日志,目录里却残留上一轮文件,很容易被误认为执行成功。同理,检查时间戳只能提供线索,最稳妥的方式仍是让每次运行在干净目录中生成并核对预期产物。
四、-lxt2 实际创建了 xt2 日志,并未切换格式
vvp -h 明确列出了 -l file,但本次 13.0 帮助没有列出 LXT2 选项。实跑 -lxt2 没有报「未知选项」,退出码也是 0,却额外出现了名为 xt2 的文本日志。这与 -l 的紧贴参数写法一致: -lxt2 被用于指定日志名 xt2,不是波形格式开关。启动信息仍为 VCD info,file 判定结果是 ASCII text,文件开头仍是 $date。
--- -lxt2 probe: actual log and dump format ---
$ vvp -lxt2 demo.vvp
VCD info: dumpfile waves.vcd opened for output.
DISPLAY: simulation start
DISPLAY: count=1
DISPLAY: count=2
DISPLAY: simulation finish
tb.v:19: $finish called at 10000 (1ps)
exit=0
$ cat xt2
VCD info: dumpfile waves.vcd opened for output.
DISPLAY: simulation start
DISPLAY: count=1
DISPLAY: count=2
DISPLAY: simulation finish
tb.v:19: $finish called at 10000 (1ps)
$ file waves.vcd
waves.vcd: ASCII text
$ od -An -c -N8 waves.vcd
$ d a t e \n \t S
--- -lxt2 without dump tasks ---
$ vvp -lxt2 no_dump.vvp
NO_DUMP: no dumpfile or dumpvars tasks
no_dump.v:6: $finish called at 1000 (1ps)
exit=0
waves.vcd exists: no这组结果给出了完整解释:在本文版本与命令组合中,-lxt2 没有报错的代价是产生一个容易忽略的 xt2 日志,默认 VCD 则原样保留。它没有替代 $dumpfile 与 $dumpvars:无 dump 用例结束后没有 waves.vcd。若目录中莫名多出 xt2,应检查是否把网上的 LXT2 命令原样套到了这个运行器上。
判断波形格式不要只看扩展名。这里的文件名一直是 waves.vcd,关键证据是工具报告的 VCD info、ASCII 文件类型和文件头。换用其他 Icarus 构建或其他模拟器时,应重新核对帮助和实际文件格式,不能把某篇教程里的参数直接当成跨版本承诺。
反过来,也不能由这次结果推导出「所有 vvp 都永不支持 LXT2」。不同版本、构建选项和前端流程可能提供不同能力。本文划定的是可复现的支持边界:在这套 13.0 环境里,这条命令没有完成格式切换。若项目确实需要 LXT2,应查阅当前安装版本对应的文档并做独立格式验收,而不是继续堆叠未经验证的参数。
五、写复现脚本时按产物逐项验收
| 需要的产物 | 必要配置 | 本次实测的验收方法 | 容易误判之处 |
|---|---|---|---|
| 终端文本 | 正常运行测试平台 | 查看 DISPLAY 与结束信息 | 看到文本不等于有波形 |
| 文本日志文件 | 输入文件前写 -l 文件名 | 检查文件存在并读取内容 | 返回 0 不代表选项位置正确 |
| VCD 波形 | $dumpfile 与 $dumpvars | 查看 VCD info 和文件头 | 加波形参数不能替代 dump 任务 |
| LXT2 波形 | 必须以当前工具真实支持为准 | 检查实际格式,不只看扩展名 | 参数被接受不等于格式切换 |
推荐把这些检查写进运行脚本,而不是只在终端扫一眼。尤其是静默忽略参数的情况,仿真功能结果可能完全正常,只有预期的日志或波形缺失。持续集成中若要把波形作为失败附件,还应显式检查文件非空,并记录工具版本和完整命令。
实验环境
- 机器/系统:Mac / macOS,Darwin 25.5.0
- 工具版本:Icarus Verilog 13.0 stable(v13_0)
- 日期:2026-10-31
- 完整命令:
bash run.sh;脚本编译两个测试平台,依次运行默认 VCD、-l、错位-l、-lxt2与无 dump 对照,并用file、od检查实际产物
代码获取
测试平台与一键复跑脚本位于公开仓 https://github.com/derekzhuo/geek-doc.cn/tree/main/experiments/ts-iverilog-vvp-log-and-trace。安装 Icarus Verilog 后进入该目录执行 bash run.sh,即可对照终端文本、日志副本、选项位置和波形文件格式。
这一篇在知识体系里的位置
本篇属于 EDA 工具运行与证据收集节点,处理 vvp 日志与跟踪选项的产物边界。若问题已经定位到编译或运行期的数组访问,可继续看 iverilog 数组下标越界;其他 Icarus 与仿真问题可从 EDA 排错目录按现象继续查找。
总结
vvp 日志与跟踪选项不能混用概念:-l 保存文本日志副本,VCD 由 $dumpfile 和 $dumpvars 显式开启,二者互不代表。Icarus Verilog 13.0 本次实测中,-l 必须放在输入文件前才会创建目标日志;-lxt2 实际创建名为 xt2 的文本日志,波形仍是 ASCII VCD,无 dump 任务时则不生成波形。验收应检查真实文件与格式,而不是只看退出码或参数是否出现在命令里。