How do I make a Virtual sequencer vs sequencer?

Dear all,

I’m trying to understand sequencer and virtual sequencer.
and I come across some example code about vitual sequencer and sequencer when I googling.

the below is virtual sequencer code

class my_virtual_sequencer extends uvm_sequencer;
    `uvm_component_utils (my_virtual_sequencer)
 
    function new (string name = "my_virtual_sequencer", uvm_component parent);
      super.new (name, parent);
    endfunction
 
    // Declare handles to other sequencers here
    apb_sequencer       m_apb_seqr;
    reg_sequencer       m_reg_seqr;
    wb_sequencer        m_wb_seqr;
    pcie_sequencer      m_pcie_seqr;
  endclass

and sequencer example code


  class my_sequencer extends uvm_sequencer;
    `uvm_component_utils (my_sequencer)
    function new (string name="m_sequencer", uvm_component parent);
      super.new (name, parent);
    endfunction
 
  endclass

As you can see the above codes, they are quite similar. Even I think they looks like most the same.
So I’m confused that how do I distinguish and implement between virtual sequencer and sequencer?

In reply to UVM_LOVE:

You should never implement your own sequencer or virtual sequencer.

For an agent, you should use ‘uvm_sequencer#(agent_sequence_item)’ as the agent’s sequencer.

For virtual sequences, they should always be started on the ‘null’ sequencer.