A virtual sequence is a container to start multiple sequences on different sequencers in the environment. This virtual sequence is usually executed by a virtual sequencer which has handles to real sequencers. The need for a virtual sequence arises when you require different sequences to be run on different environments. For example, an SoC design might have multiple different interfaces that might need to be driven by a different set of sequences on individual sequencers. Hence the best way to start and control these different sequences would be from a virtual sequence. It becomes virtual because it is not associated with any particular data type.

Use of a virtual sequencer
  class my_virtual_seq extends uvm_sequence;
    `uvm_object_utils (my_virtual_seq)
    `uvm_declare_p_sequencer (my_virtual_sequencer)
    function new (string name = "my_virtual_seq");
      super.new (name);
    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");
    task body();
      m_apb_rd_wr_seq.start (p_sequencer.m_apb_seqr);
        m_wb_reset_seq.start (p_sequencer.m_wb_seqr);
        m_pcie_gen_seq.start (p_sequencer.m_pcie_seqr);

Note the following from the example above.

  • my_virtual_seq is derived from uvm_sequence just like any other sequence
  • A handle called p_sequencer is created within the sequence via macro `uvm_declare_p_sequencer and assigned to be run with my_virtual_sequencer
  • Each sequence is started on its corresponding sequencer using the start() method
  • Each sequencer is referenced by p_sequencer handle which points to the virtual sequencer

Login to your free account to read more ...

Was this article helpful ?