每一个sequence都应该派生自uvm_sequence,并且在定义时指定要产生的transaction。
每一个sequence都有一个body任务,当一个sequence启动之后,会自动执行body中的代码。
第一种:使用宏uvm_do:
class case0_sequence extends uvm_sequence #(my_transaction);
`uvm_object_utils(case0_sequence)
my_transaction m_trans;
function new(string name= "case0_sequence");
super.new(name);
endfunction
virtual task body();
if(starting_phase != null)
starting_phase.raise_objection(this);
repeat (10) begin
`uvm_do(m_trans) //`uvm_do_pri `uvm_do_with `uvm_do_pri_with
//`uvm_do_on `uvm_do_on_pri `uvm_do_on_with `uvm_do_on_pri_with
end
if(starting_phase != null)
starting_phase.drop_objection(this);
endtask
endclass
在上面中,用到了一个uvm_do宏。它的主要作用是:
1.创建一个my_transaction的实例m_trans;
2.将其随机化;
3.最终将其送给sequencer.
第二种:使用宏uvm_create和宏uvm_send
virtual task body();
my_transaction m_tr;
byte unsigned data_q[];
int data_size;
repeat (10) begin
data_size = ip_tr.pack_bytes(data_q) / 8;
m_tr = new("m_tr"); //或者`uvm_create(m_tr)
assert(m_tr.randomize with{m_tr.pload.size() == data_size;}); //随机化
for(int i = 0; i < data_size; i++) begin
m_tr.pload[i] = data_q[i]; //添加约束
end
`uvm_send(m_tr) //发送给sequencer //`uvm_send_pri(m_tr, 100)
end
endtask
1)宏uvm_creat的作用是实例化transaction;
2)利用randomize进行随机化;当一个transaction被实例化后,可以对其做更多的处理,这种使用方式比uvm_do宏更加灵活。
3)利用uvm_send或uvm_send_pri发送出去。
第三种:利用uvm_rand_send系列宏
m_trans = new("m_trans"); //实例化
`uvm_rand_send(m_trans) //随机化+发送
//`uvm_rand_send_pri `uvm_rand_send_with `uvm_rand_send_pri_with
uvm_rand_send与uvm_send宏类似,唯一的区别是它会对transaction进行随机化。
这个宏使用的前提是transaction已经被分配了空间,换言之,即已经实例化。
第四种:使用start_item和finish_item,不使用宏
virtual task body();
repeat(10) begin
tr = new("tr"); //实例化
assert(m_tr.randomize with{m_tr.pload.size() == data_size;}); //随机化
start_item(tr); //此任务可以和上一句更换顺序
finish_item(tr); //
end
endtask
1)不适用宏产生transaction的方式要依赖于两个任务:start_item和finish_item;
2)在使用这两个任务前,必须要先实例化transaction后才能调用这两个任务;
3)可以在transactin实例化后,finish_item调用前对其进行随机化;
4)uvm_do系列宏其实是将上面四个步骤封装在这个宏中。
5)start_item(tr, 100)和finish_item(tr, 100)可以指定transaction的优先级,默认的优先级是-1。
第五种:使用pre_do/mid_do/post_do
uvm_do宏封装了从transaction实例化到发送的一系列操作。封装的越多,则其灵活性就越差。为了增加uvm_do系列宏的功能,UVM提供了三个接口:pre_do、mid_do、post_do。
因为这个操作用的比较少,不再做详细介绍。具体内容可以参考张强编著的<<UVM实战>>卷I,位于Page 180。