4. UVM波形调试:使用Verdi/DVE与UVM结合,Transaction级波形显示
波形调试,说白了就是芯片验证的「照妖镜」。
我们平时跑仿真,打印一堆log,看到「PASS」就以为万事大吉了。但说实话,很多隐蔽的bug,log根本看不出来。比如某个信号刚好在时钟沿跳变时被采样,或者transaction的时序刚好差了那么一个cycle——这种问题,只有盯着波形才能找到。
我个人习惯,不管log报不报错,每个testcase跑完都会拉一下波形看看。尤其是UVM环境,光看信号级波形太原始了,咱们得看transaction级的波形,那才叫高效。
4.1 为什么需要Transaction级波形?
传统的信号级波形,你看到的是一个个bit在跳。比如一个AXI总线,你看到awaddr、awvalid、awready这些信号在变。但你想过没有,一个完整的写transaction,包含了地址、数据、响应,这些信息是分散在几十个信号里的。
你想想看,如果波形里直接显示「WRITE: addr=0x1000, data=0xDEAD_BEEF, resp=OKAY」,那定位问题得多快?
Transaction级波形的核心价值:
- 把分散的信号聚合为完整的协议事务
- 显示transaction的属性字段(地址、数据、状态等)
- 支持按transaction类型过滤和搜索
- 一眼看出时序关系,比如两个transaction之间隔了多少cycle
我在项目中遇到过一件事:一个DMA模块,数据一直传错。看信号级波形看了两天,眼睛都快瞎了。后来把transaction级波形打开,发现是地址对齐出了问题——transaction里显示的地址是0x1003,但硬件要求4字节对齐。这种问题,信号级波形根本看不出来,因为地址总线上的值就是0x1003,你没法一眼判断它是不是对齐的。
4.2 UVM与Verdi的Transaction级波形集成
Verdi和DVE都支持UVM的transaction级波形显示。但说实话,不是你把波形dump出来就能自动看到的。你需要做一些配置。
嗯,这里要注意:Verdi支持的是UVM的objection和transaction recording机制。说白了,就是UVM在仿真时把transaction的信息记录下来,Verdi再去读取并显示。
4.2.1 使能Transaction Recording
在UVM环境中,要让transaction出现在波形里,你需要在driver或monitor里调用begin_tr和end_tr。我见过很多新手,写了UVM环境但忘了加这个,结果波形里啥也没有。
class my_driver extends uvm_driver#(my_transaction);
virtual task run_phase(uvm_phase phase);
my_transaction tr;
forever begin
seq_item_port.get_next_item(tr);
// 开始记录transaction
void'(begin_tr(tr, "my_driver"));
// 驱动信号...
drive_transaction(tr);
// 结束记录
end_tr(tr);
seq_item_port.item_done();
end
endtask
endclass
这里有个坑:begin_tr返回的是一个整数句柄,你可以忽略它,但一定要调用end_tr。我曾经有一次忘了调end_tr,结果波形里transaction一直处于「进行中」状态,根本看不到结束时间。
4.2.2 添加Transaction字段到波形
光有transaction的起止时间还不够,你还需要把transaction里的关键字段显示出来。比如地址、数据、命令类型等。
UVM提供了uvm_record_attribute和uvm_record_field宏,用来把字段添加到波形数据库中。
class my_transaction extends uvm_sequence_item;
rand bit [31:0] addr;
rand bit [31:0] data;
rand cmd_enum cmd; // READ, WRITE
function void do_record(uvm_recorder recorder);
super.do_record(recorder);
// 记录字段到波形
`uvm_record_field("addr", addr)
`uvm_record_field("data", data)
`uvm_record_field("cmd", cmd)
endfunction
endclass
我个人习惯,把关键字段都记录下来。但别什么都记,比如一些中间变量、临时状态,记多了波形会变得很乱。你想想看,一个transaction里显示20个字段,谁看得过来?
我的经验:只记录对调试有帮助的字段。比如地址、数据、状态、错误码。像一些内部计数器、临时标志位,就别记了。保持波形清爽,定位问题才快。
4.3 在Verdi中查看Transaction级波形
好了,仿真跑完,波形dump出来了。怎么在Verdi里看transaction级波形?
首先,打开Verdi,加载波形文件(.fsdb)。然后,在波形窗口里,你会看到信号列表。找到你的UVM组件层次结构,比如uvm_test_top.env.agent.driver。
右键点击driver,选择「Add to Wave」->「Transaction」。Verdi会自动识别出这个driver里记录的transaction。
嗯,这里要注意:如果你在driver里调用了begin_tr和end_tr,Verdi才能看到transaction。否则,你只能看到信号级波形。
4.3.1 使用Transaction过滤和搜索
Verdi的transaction级波形支持按字段值过滤。比如,你只想看地址为0x1000的写transaction,可以这样操作:
- 在波形窗口里,点击「Transaction Filter」按钮
- 选择字段「addr」,设置值为「0x1000」
- 选择字段「cmd」,设置值为「WRITE」
- 点击「Apply」
波形里就只显示符合条件的transaction了。这个功能在定位特定场景时特别有用。我记得有一次,一个bug只在地址为0x2000~0x2FFF范围内出现,我就是用这个过滤功能,一秒就锁定了问题transaction。
4.3.2 查看Transaction的详细信息
在波形里,双击某个transaction的条块,Verdi会弹出一个窗口,显示这个transaction的所有字段值。包括你在do_record里记录的那些字段。
这个功能我经常用。比如看到波形里有一个transaction的响应是SLVERR,双击一看,发现地址超出了地址范围。这种问题,如果只看信号级波形,你得一个一个信号去对,累死。
4.4 DVE中的Transaction级波形显示
DVE是Synopsys的波形工具,用法和Verdi类似。但DVE对UVM的支持稍微弱一些,需要额外配置。
在DVE中查看transaction级波形,你需要确保仿真时生成了VCD+或FSDB格式的波形文件。DVE支持读取FSDB,但更推荐使用VCD+。
我个人觉得,DVE的transaction显示不如Verdi直观。Verdi的transaction条块是彩色的,不同颜色代表不同transaction类型。DVE默认是单色的,需要手动设置颜色映射。
避坑指南:我曾经在DVE里折腾了半天,transaction就是显示不出来。后来发现是仿真时忘了加+UVM_TR_RECORD=1这个选项。UVM默认是不记录transaction的,需要显式开启。
仿真命令里加上:+UVM_TR_RECORD=1,或者在testbench里调用uvm_config_int::set(this, "*", "recording_detail", UVM_FULL);
4.5 实战技巧:如何高效使用Transaction级波形
说了这么多,总结几个我实际项目中的经验:
- 分层记录:在driver、monitor、scoreboard里都加上transaction recording。这样你可以看到从驱动到监测再到比对的完整链路。
- 命名规范:transaction的name字段要起有意义的名字。比如
tr.set_name($sformatf("WR_%0h", addr));,这样波形里一眼就能看出是哪个transaction。 - 结合信号级波形:别只看transaction级。有时候需要同时看信号级波形,比如检查时序是否满足建立保持时间。Verdi支持同时显示两种视图。
- 使用书签:找到关键transaction后,加个书签。方便后续回归验证时快速定位。
说实话,transaction级波形是我调试UVM环境时最常用的工具。没有它,很多问题根本无从下手。你想想看,一个复杂的协议,比如AXI、AHB、PCIe,信号成百上千,靠肉眼去对,那不是人干的事。
好了,这一章的内容就到这里。记住:波形调试不是可有可无的步骤,它是验证工程师的必备技能。尤其是transaction级波形,能让你从「看信号」升级到「看事务」,效率提升不止一个量级。
本章核心要点:
- Transaction级波形把信号聚合为协议事务,大幅提升调试效率
- 使用
begin_tr/end_tr和do_record记录transaction信息 - Verdi支持按字段过滤和搜索transaction
- 别忘了加
+UVM_TR_RECORD=1选项 - 只记录关键字段,保持波形清爽
可可精品资料库