In reply to vgadupu:
There are 2 different ways to deal with virtual sequences, either you have the refences of your agent sequencers in the virtual sequence or you have it in the virtual sequencer. If you have it in the virtual sequence you do not need a virtual sequencer. This is how I work with.
My virtual bse sequence looks like this:
//-----------------------------------------------------------------------------
class example_top_base_seq extends uvm_sequence #(uvm_sequence_item);
//-----------------------------------------------------------------------------
`uvm_object_utils(example_top_base_seq)
example_top_config cfg;
apb_sequencer apb_sequencer_i;
spi_sequencer spi_sequencer_i;
extern function new(string name = “example_top_base_seq”);
extern task body();
//---------------------------------------------------------------------------
// constraints
//---------------------------------------------------------------------------
endclass : example_top_base_seq
//-----------------------------------------------------------------------------
// example_top_base_seq implementation
//-----------------------------------------------------------------------------
function example_top_base_seq::new(string name = “example_top_base_seq”);
super.new(name);
endfunction : new
task example_top_base_seq::body();
if (!uvm_config_db #(apb_sequencer)::get(null, get_full_name(), “apb_sequencer”, apb_sequencer_i))
uvm_error(get_type_name(), "Config Error uvm_config_db #(apb_sequencer)::get cannot find sequencer") if (!uvm_config_db #(spi_sequencer)::get(null, get_full_name(), "spi_sequencer", spi_sequencer_i))
uvm_error(get_type_name(), “Config Error uvm_config_db #(spi_sequencer)::get cannot find sequencer”)
endtask: body
This are the refernces to the agent sequencers.
The real sequence is here:
class example_top_default_seq extends example_top_base_seq;
`uvm_object_utils(example_top_default_seq)
// UVC sequences
apb_default_seq apb_seq;
spi_default_seq spi_seq;
extern function new(string name = “example_top_default_seq”);
extern task body();
endclass : example_top_default_seq
//-----------------------------------------------------------------------------
// example_top_default_seq implementation
//-----------------------------------------------------------------------------
function example_top_default_seq::new(string name = “example_top_default_seq”);
super.new(name);
endfunction : new
task example_top_default_seq::body();
super.body();
apb_seq = apb_default_seq::type_id::create(“apb_seq”);
spi_seq = spi_default_seq::type_id::create(“spi_seq”);
`uvm_info(get_type_name(),“default sequence starting”, UVM_MEDIUM)
repeat(10) begin
`uvm_info(get_type_name(),“apb sequence starting”, UVM_MEDIUM)
void’(apb_seq.randomize());
apb_seq.start(apb_sequencer_i);
`uvm_info(get_type_name(),“spi sequence starting”, UVM_MEDIUM)
void’(spi_seq.randomize());
spi_seq.start(spi_sequencer_i);
end
// alternatively use macros to start sequences
// fork
// uvm_do_on(apb_seq, apb_sequencer_i) //
uvm_do_on(spi_seq, spi_sequencer_i)
// join
`uvm_info(get_type_name(),“default sequence completed”,UVM_MEDIUM)
endtask : body
And the body task of the agent sequence looks like this:
task spi_default_seq::body();
uvm_info(get_type_name(),"default sequence starting", UVM_MEDIUM) super.body(); item = spi_seq_item::type_id::create("item"); begin start_item(item); item.data = data; item.no_bits = no_bits; item.RX_NEG = RX_NEG; finish_item(item); end
uvm_info(get_type_name(),“default sequence completed”, UVM_MEDIUM)
// Alternatively use macros
// `uvm_do_with(item, {
// item.data == data;
// item.no_bits == no_bits;
// item.RX_NEG == RX_NEG;
// })
endtask : body
Does this help for your understanding?