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 ?