In reply to cgales:
In reply to cliffc:
I consider creating an agent sequencer as a waste of time which can be better spent developing other parts of your environment. For an agent sequencer, you need to create the file, add the template code, add theinclude to your package file, and then debug any issues, for no additional benefit. In the space of your
include line, you can have a simple typedef which meets all the requirements for your agent.
One of the main advantages to have a dedicated sequencer is clearly in the event of reactive agents, where the sequencer will need to add separate TLM ports to get responses from the Monitor (see: https://www.verilab.com/files/mastering_reactive_slaves.pdf)
I consider creating a virtual sequencer to be a similar waste of time and recommend running a virtual sequence on a null sequencer. In a virtual sequence, you only have handles to the required sequencers based upon the types of sequence items you are generating. Since a test is always environment specific, it knows all the paths of the sequencers, so you can reuse test sequences from sub-environments very easily.
While I agree that a virtual sequencer doesn’t “add” much, I still consider it a useful component to have since it can provide some facility to check for agent sequencers or sub virtual sequencers. Imagine the following:
class vsequencer extends uvm_sequencer;
`uvm_component_utils(vsequencer)
tb_ahb_sequencer ahb_sqr;
tb_eth_sequencer eth_sqr;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void end_of_elaboration_phase(uvm_phase phase);
super.end_of_elaboration_phase(phase);
if (!uvm_config_db#(tb_ahb_sequencer)::get(this, "", "ahb_sqr", ahb_sqr))
`uvm_fatal("VSQR/CFG/NOAHB", "No ahb_sqr specified for this instance");
if (!uvm_config_db#(tb_eth_sequencer)::get(this, "", "eth_sqr", eth_sqr))
`uvm_fatal("VSQR/CFG/NOETH", "No eth_sqr specified for this instance");
if (ahb_sqr == null)
`uvm_fatal(get_full_name(), "ahb_sqr sub-sequencer null pointer: this test case will fail, check config or virtual sequence")
if (eth_sqr == null)
`uvm_fatal(get_full_name(), "eth_sqr sub-sequencer null pointer: this test case will fail, check config or virtual sequence")
endfunction
endclass
EDIT: courtesy of Clifford E. Cummings and Janick Bergeron (DVCON16)
As you can see I’m encapsulating knowledge in the virtual sequencer and have it work for me. The tester needs to make sure the virtual sequence is run on the appropriate virtual_sequencer (you could actually leverage the p_sequencer with the `uvm_declare_p_sequencer macro that performs this check for you).
An example of flexibility is a using a test sequence which requires a single Ethernet port sequencer in an environment that has multiple Ethernet agents. The test can now randomly select one of the Ethernet agents to be utilized and assign the sequencer handle to the sequence. If you use a p_sequencer which contains multiple Ethernet sequencer handles, you would have to somehow account for which sequencer handle to use from the p_sequencer.
I could achieve that by doing the following:
class ethernet_vseq extends ethernet_base_vseq;
// random sequencer to chose from
ethernet_sequencer eth_sqr;
function void post_randomize ();
for (int i=0, i < NUM_ETH_AGENTS; i++)
randcase
0 : eth_sqr = p_sequencer.eth_sqr0;
1 : eth_sqr = p_sequencer.eth_sqr1;
2 : eth_sqr = p_sequencer.eth_sqr2;
endcase
end
tast body();
eth_seq.start(eth_sqr);
endtask
endfunction : post_randomize
endclass: ethernet_vseq
I know can be sure that using the above virtual sequence on the correct virtual sequencer I am guaranteed to have it running.
Assigning sequencer handles to a sequence has the same amount of complexity as adding sequencer handles to a p_sequencer, and can be accomplished with helper functions in your base test and base test sequences. When you are writing tests and test sequences, the overall hierarchy is generally static with minimal changes at that point.
[/quote]
You’ve consistently claimed that using virtual sequencers will hamper reusability, but I failed to find an example for that. Can you please provide clarity on why you think using a virtual sequencer will hamper reusability?