How to execute specific sequence in virtual sequence?

Hi,

I’m tryingto understand the usage of virtual sequence with virtual sequencer.
As I know basically virtual sequence is implemend as like the below with virtual sequencer.


class my_virtual_seq extends uvm_sequence;
`uvm_object_utils (my_virtual_seq)
`uvm_declare_p_sequencer (my_virtual_sequence

function new (string name = "my_virtual_seq")
super.new (name);
endfunction

apb_rd_wr_seq m_apb_rd_wr_seq;
wb_reset_seq m_wb_reset_seq;
pcie_gen_seq m_pcie_gen_seq;

task pre_body();
m_apb_rd_wr_seq = apb_rd_wr_seq::type_id:
m_wb_reset_seq = wb_reset_seq:::type_id::create();
m_pcie_gen_seq = pcie_gen_seq:::type_id::create();
endtask

task body();
...
m_apb_rd_wr_seq.start (p_sequencer.m_apb_rd_wr_seq );
fork
m_wb_reset_seq.start (p_sequencer.m_wb_reset_seq);
m_pcie_gen_seq.start (p_sequencer.m_pcie_gen_seq);
join
...
endtask
endclass

Basically, we execute to virtual sequence as below.


class my_test extends uvm_test;
`uvm_component_utils (my_test)
my_env m_env;
...
task run_phase (uvm_phase phase);
my_virtual_seq m_vseq = my_virtual_seq::t
phase.raise_objection (this);
m_vseq.start (m_env.m_virtual_seqr);
phase.drop_objection (this);
endtask
endclass

But I’m confused that If we do execute

m_vseq.start(m_env.m_virtual_seqr);

then all vsequences will be excuted as implemented in “my_virtual_seq”.

So I can’t use this way to execute specific sequence from my_virtual_seq.
Is there any way to execute specific sequence in virtual sequence with virtual sequencer?

In reply to UVM_LOVE:

Of course you can do that. But a few things in your code are not correct.
(1) Using a virtual sequence you do not need p_sequencer.
(2) To start your local sequences you need the handles of the local sequencers in your virtual sequence.
Your code should look like this:

class my_virtual_seq extends uvm_sequence;
`uvm_object_utils (my_virtual_seq)
 
function new (string name = "my_virtual_seq")
super.new (name);
endfunction
apb_sequencer apb_sqr;
wb_sequencer  wb_sqr;
pcie_sequencer pcie_sqr;

apb_rd_wr_seq m_apb_rd_wr_seq;
wb_reset_seq m_wb_reset_seq;
pcie_gen_seq m_pcie_gen_seq;
 
task pre_body();
  m_apb_rd_wr_seq = apb_rd_wr_seq::type_id:create("m_apb_rd_wr_seq")
  m_wb_reset_seq = wb_reset_seq:::type_id::create("m_wb_reset_seq");
  m_pcie_gen_seq = pcie_gen_seq:::type_id::create("m_pcie_gen_seq");
endtask
 
task body();
...
m_apb_rd_wr_seq.start (apb_sqr );
fork
  m_wb_reset_seq.start (wb_sqr);
  m_pcie_gen_seq.start (pcie_sqr);
join
...
endtask
endclass

Now you have to take care to get the handles of your local sequencers into the virtual sequence. You have different options to do that:
(1) use the config_db
(2) assign the local sequencers in your test

In reply to chr_sue:

I think the below example will be working also the same as waht I wrote a question.
Even if I will implement as below but eventually, the following the all sequences will be excuted.

So, If I didn’t undersatnd as well, Please guide me a little bit more. How do I execute the specific sequence in test?

task body();
...
m_apb_rd_wr_seq.start (apb_sqr );
fork
  m_wb_reset_seq.start (wb_sqr);
  m_pcie_gen_seq.start (pcie_sqr);
join
...
endtask
class my_virtual_seq extends uvm_sequence;
`uvm_object_utils (my_virtual_seq)
 
function new (string name = "my_virtual_seq")
super.new (name);
endfunction
apb_sequencer apb_sqr;
wb_sequencer  wb_sqr;
pcie_sequencer pcie_sqr;
 
apb_rd_wr_seq m_apb_rd_wr_seq;
wb_reset_seq m_wb_reset_seq;
pcie_gen_seq m_pcie_gen_seq;
 
task pre_body();
  m_apb_rd_wr_seq = apb_rd_wr_seq::type_id:create("m_apb_rd_wr_seq")
  m_wb_reset_seq = wb_reset_seq:::type_id::create("m_wb_reset_seq");
  m_pcie_gen_seq = pcie_gen_seq:::type_id::create("m_pcie_gen_seq");
endtask
 
task body();
...
m_apb_rd_wr_seq.start (apb_sqr );
fork
  m_wb_reset_seq.start (wb_sqr);
  m_pcie_gen_seq.start (pcie_sqr);
join
...
endtask
endclass

In reply to UVM_LOVE:

In general you have any number of virtual sequences to test the behavior. These sequences will be started in different tests. It is recommended not to use a virtual sequencer like this

class my_test extends uvm_test;
`uvm_component_utils (my_test)
my_env m_env;
...
task run_phase (uvm_phase phase);
my_virtual_seq m_vseq = my_virtual_seq::type_id::create("m_vseq");
m_vseq.apb_sqr = m_env.abp_agnt.seqr;
m_vseq.wb_sqr = m_env.wb_agnt.seqr;
m_vseq.pcie_sqr = m_env.pcie_agnt.seqr;
phase.raise_objection (this);
  m_vseq.start (null);
phase.drop_objection (this);
endtask
endclass

In reply to chr_sue:

Thanks for reply from my question.
But even if I implement as the below

class my_test extends uvm_test;
`uvm_component_utils (my_test)
my_env m_env;
...
task run_phase (uvm_phase phase);
my_virtual_seq m_vseq = my_virtual_seq::type_id::create("m_vseq");
m_vseq.apb_sqr = m_env.abp_agnt.seqr;
m_vseq.wb_sqr = m_env.wb_agnt.seqr;
m_vseq.pcie_sqr = m_env.pcie_agnt.seqr;
phase.raise_objection (this);
  m_vseq.start (null);
phase.drop_objection (this);
endtask
endclass

Eventually, m_vseq is no information specific sequence which is will be exxcuted.
m_vseq have multiple sequences in task body.
So I can’t find what is the difference except removed virtual sequencer.

When " m_vseq.start (null);" execued , the below multiple sequences will be excuted not specific sequence.

task body();
...
m_apb_rd_wr_seq.start (apb_sqr );
fork
  m_wb_reset_seq.start (wb_sqr);
  m_pcie_gen_seq.start (pcie_sqr);
join

Could you guide me please ?