sequence用来产生激励,一般设置为某个component phase的default sequence(一般为sequencer),从而使用sequence来控制平台的关闭。
class my_sequence extends uvm_sequence #(my_transaction);
my_transaction tr;
virtual task body();
repeat(10) begin
'uvm_do(tr)
end
#100;
endtask
virtual task body();
starting_phase.raise_objection(this);
repeat(10) begin
'uvm_do_with(tr, {tr.crc_err = 1;})
end
#100;
starting_phase.drop_objection(this);
endtask
'uvm_object_utils(my_sequence)
endclass
第一种实现采用uvm_do随机产生数据,第二种uvm_do_with加上了约束,并且增加了控制结束语句。
如果需要交替产生包数据,可以将sequence作为参数传入uvm_do中:
class crc_seq extends uvm_sequence#(my_transaction);
......
endclass
class long_seq extends uvm_sequence#(my_transaction);
.......
endclass
class new_seq extends uvm_sequence#(my_transaction)
task body();
crc_seq cq;
long_seq lq;
'uvm_do(cq);
'uvm_do(lq);
endtask;
'uvm_object_utils(new_seq)
endclass
如果需要控制包产生的顺序,可以使用全局变量,这种发送次数有限制,而且添加复用性差,第二种方式是是哦那个virtual sequence。
class vsequencer extends uvm_sequencer;
cpu_sequencer cpu_sqr;
mac_sequencer mac_sqr;
'uvm_component_utils(vsequencer);
endclass
class base_test extends uvm_test
env env_inst;
vsequencer vsqr;
function build_phase(uvm_phase phase);
...
vsqr = vsequencer::type_id::create("vsqr", this);
...
endfunction
function connect_phase(uvm_phase phase);
...
vsqr.cpu_sqr = env_lnst.agent.cpu_sqr;
vsqr.mac_sqr = env_inst.agent.mac_sqr;
...
endfunction
endclass
class vsequence extends uvm_sequence;
task body();
cpu_seq cq;
mac_seq mq;
'uvm_do_on(cq, p_sequencer.cpu_sqr)
'uvm_do_on(mq, p_sequencer.mac_sqr)
endtask
’uvm_declare_p_sequencer(vsequencer)
endclass
uvm_config_db#(uvm_object_wrapper)::set(this, "env.vsqr.main_phase", "default_sequence", vsequence::type_id::get());
最后一句在base_test中加,这里创建了一个vsequencer和对应的vsequence,在vsequencer里将cpu_sqr和mac_sqr绑定到env实例化过的对象上,再从vsequence中调用uvm_do_on将需要使用的sequence与对应的sequencer结合起来,再由具体的sequencer端口发送。正常流程是sequencer绑定在sequencer的phase中产生激励,在agent中将sequencer实例化并且将端口连接通信。
使用virtual sequencer后,由于具体的sequence没有设置为default sequence了,所以无法使用starting_phase(设置default时会给这个指针赋值),所以在最顶层的vsequence中控制平台的关闭。