uvm do on
在 UVM 中,uvm_do
宏的第一个参数是 “要执行的事务(sequence_item
)或子序列(sequence
)的句柄”。
- 若参数是事务(
sequence_item
类型),uvm_do
会自动调用start_item()
、randomize()
、finish_item()
,完成事务的随机化与发送; - 若参数是子序列(
sequence
类型),uvm_do
会自动调用该子序列的start(m_sequencer)
方法,在当前序列的m_sequencer
上启动子序列。
`uvm_do(req) // req 是 transaction 句柄,自动发送事务
`uvm_do(sub_seq) // sub_seq 是子序列句柄,自动启动子序列
在 uvm_do
宏中,若第一个参数是子序列(sequence
类型) 而非事务(sequence_item
),则事务的随机化逻辑应在该子序列内部实现。
子序列作为独立的 uvm_sequence
派生类,其核心职责之一就是定义 “如何生成、随机化和发送事务”。具体来说,事务的随机化通常在子序列的 body()
任务中完成,通过以下两种方式:
1. 直接在子序列中手动随机化事务
子序列内部会声明并创建事务(sequence_item
),然后显式调用 randomize()
进行随机化,再通过 start_item()
/finish_item()
发送。
// 子序列定义(包含事务的随机化逻辑)
class sub_seq extends uvm_sequence #(my_trans);`uvm_object_utils(sub_seq)task body();my_trans req; // 声明事务req = my_trans::type_id::create("req");// 在子序列内部随机化事务start_item(req);if (!req.randomize() with {addr inside {[0:100]}; data % 2 == 0;}) begin`uvm_fatal("RAND_ERR", "事务随机化失败")endfinish_item(req); // 发送事务endtask
endclass// 调用方(父序列或测试用例)使用 uvm_do 启动子序列
class parent_seq extends uvm_sequence;`uvm_object_utils(parent_seq)task body();sub_seq s;s = sub_seq::type_id::create("s");// uvm_do 的第一个参数是子序列,事务的随机化在 sub_seq 内部完成`uvm_do(s) endtask
endclass
2. 在子序列中嵌套使用 uvm_do
宏随机化事务
子序列内部也可以直接使用 uvm_do
宏处理事务,此时事务的随机化由子序列中的 uvm_do
自动完成(本质是对 randomize()
的封装)。
示例:
class sub_seq extends uvm_sequence #(my_trans);`uvm_object_utils(sub_seq)task body();my_trans req;// 子序列内部用 uvm_do 随机化并发送事务`uvm_do_with(req, {addr == 32'h1000; data > 10;}) endtask
endclass// 父序列调用子序列
class parent_seq extends uvm_sequence;task body();sub_seq s;`uvm_do(s) // 子序列内部已通过 uvm_do_with 完成事务随机化endtask
endclass