1.使用virtual sequencer
1.1首先定义一个Virtual Sequencer
class virtual_jelly_bean_sequencer extends uvm_sequencer ;
//virtual sequencer中声明真实的sequencer的两个句柄
jelly_bean_sequencer jb_seqr1;
jelly_bean_sequencer jb_seqr2;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
`uvm_component_utils(virtual_jelly_bean_sequencer)
endclass
1.2然后定义一个Virtual Sequence
class jelly_bean_recipe_virtual_sequence extends uvm_sequence;
`uvm_declare_p_sequencer(virtual_jelly_bean_sequencer)//使用p_sequencer
`uvm_object_utils( jelly_bean_recipe_virtual_sequence)
function new( string name = "" );
super.new( name );
endfunction
task body();
//实例化两个sequence
same_flavored_jelly_beans_sequence jb_seq1;
same_flavored_jelly_beans_sequence jb_seq2;
jb_seq1 = same_flavored_jelly_beans_sequence::type_id::create( "jb_seq1" );
jb_seq2 = same_flavored_jelly_beans_sequence::type_id::create( "jb_seq2" );
//将如下的两个真实的seq连接到seqr并顺序执行
fork
jb_seq1.start(p_sequencer.jb_seqr1);
jb_seq2.start(p_sequencer.jb_seqr2);
join
endtask
endclass
1.3在一个component中实例化virtual sequencer,下面的例子是在base_test中实例化,并且在connect中连接virtual sequencer与真实的sequencer。
class jelly_bean_base_test extends uvm_test;
`uvm_component_utils(jelly_bean_base_test)
virtual_jelly_bean_sequencer v_sqr;//声明vir_ser的句柄
........
function new (string name,uvm_component parent);
super.new(name,parent);
endfunction
function void build_phase (uvm_phase phase);
super.build_phase(phase);
.......
//实例化vir_sqr
v_sqr = virtual_jelly_bean_sequencer::type_id::create("v_sqr", this);
endfunction
//在connect中将真实的sqr连接到vir_sqr
function void connect_phase (uvm_phase phase);
v_sqr.jb_seqr1 = jb_env.jb_agent1.jb_seqr;
v_sqr.jb_seqr2 = jb_env.jb_agent2.jb_seqr;
endfunction
endclass
1.4在test_case中启动virtual sequence,此test_case为base_test的扩展类,一般的raise与drop phase都在virtual seque中进行。
class jelly_bean_recipe_test extends jelly_bean_base_test;
`uvm_component_utils( jelly_bean_recipe_test )
function new( string name, uvm_component parent );
super.new( name, parent );
endfunction
task main_phase( uvm_phase phase );
jelly_bean_recipe_virtual_sequence jb_vseq;
phase.raise_objection( this );
jb_vseq = jelly_bean_recipe_virtual_sequence::type_id::create("jb_vseq")
assert( jb_vseq.randomize() );//随机化virtual sequence,是因为vir_seq定义了rand变量
jb_vseq.start( this.v_sqr);
#100ns ;
phase.drop_objection( this );
endtask
endclass
1.4.1上面需要随机化virtual sequence中的rand变量所以采取了手动启动,也可以自启动virtual sequence。首先在virtual sequence类中控制 raise,drop phase。
class jelly_bean_recipe_virtual_sequence extends uvm_sequence;
`uvm_declare_p_sequencer(virtual_jelly_bean_sequencer)//使用p_sequencer
`uvm_object_utils( jelly_bean_recipe_virtual_sequence)
function new( string name = "" );
super.new( name );
endfunction
task body();
if(starting_phase != null)
starting_phase.raise_objection(this);
//实例化两个sequence
same_flavored_jelly_beans_sequence jb_seq1;
same_flavored_jelly_beans_sequence jb_seq2;
jb_seq1 = same_flavored_jelly_beans_sequence::type_id::create( "jb_seq1" );
jb_seq2 = same_flavored_jelly_beans_sequence::type_id::create( "jb_seq2" );
//将如下的两个真实的seq连接到seqr并顺序执行
fork
jb_seq1.start(p_sequencer.jb_seqr1);
jb_seq2.start(p_sequencer.jb_seqr2);
join
#100;
if(starting_phase != null)
starting_phase.drop_objection(this);
endtask
endclass
1.4.2然后在test_case中设置自启动virtual sequence
class jelly_bean_recipe_test extends jelly_bean_base_test;
`uvm_component_utils( jelly_bean_recipe_test )
function new( string name, uvm_component parent );
super.new( name, parent );
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
//使用如下语句自启动vir_seq
uvm_config_db#(uvm_object_wrapper)::set(this,
"v_sqr.main_phase",//vir_seqr的句柄
"default_sequence",
jelly_bean_recipe_virtual_sequence::type_id::get());
endfunction
endclass
2.不使用virtual sequencer
2.1直接定义一个Virtual Sequence,并在其中声明sequencer的句柄,并连接
class jelly_bean_recipe_virtual_sequence extends uvm_sequence;
`uvm_object_utils( jelly_bean_recipe_virtual_sequence)
function new( string name = "" );
super.new( name );
endfunction
//直接在vir_seq中创建两个真实的sequencer 句柄
jelly_bean_sequencer jb_seqr1;
jelly_bean_sequencer jb_seqr2;
task body();
//实例化两个sequence
same_flavored_jelly_beans_sequence jb_seq1;
same_flavored_jelly_beans_sequence jb_seq2;
jb_seq1 = same_flavored_jelly_beans_sequence::type_id::create( "jb_seq1" );
jb_seq2 = same_flavored_jelly_beans_sequence::type_id::create( "jb_seq2" );
//将如下的两个真实的seq连接到seqr并顺序执行
fork
jb_seq1.start( jb_seqr1 );
jb_seq2.start( jb_seqr2 );
join
endtask
endclass
2.2不需要在component中实例化virtual sequencer。直接在test_case中设置启动virtual sequence。
class jelly_bean_recipe_test extends jelly_bean_base_test;
`uvm_component_utils( jelly_bean_recipe_test )
function new( string name, uvm_component parent );
super.new( name, parent );
endfunction
task main_phase( uvm_phase phase );
jelly_bean_recipe_virtual_sequence jb_vseq;
phase.raise_objection( this );
jb_vseq = jelly_bean_recipe_virtual_sequence::type_id::create("jb_vseq")
//将vir_seq中的seqr与实际的seqr连接
jb_vseq.jb_seqr1 = jb_env.jb_agent1.jb_seqr;
jb_vseq.jb_seqr2 = jb_env.jb_agent2.jb_seqr;
assert( jb_vseq.randomize() );//随机化virtual sequence,是因为vir_seq定义了rand变量
//启动时jb_vseq指向的sequencer的指针为null
jb_vseq.start(null);
#100ns ;
phase.drop_objection( this );
endtask
endclass