The best way to start/select sequence(s) in a test class

I am considering the best way to start/select sequences in a test class. There are following ways as far as I know. I listed Pros and Cons of each way. Which one do you think the best way? Tell me your opinions, suggestions, ideas and objections, etc.


1. Manual sequence start
1-a : Direct Sequencer Assignment


      task Test::run_phase();
        seq1.start(env.agent1.seqr);

  Directly selects the target sequence.
  Pros. : Straightforward, simple and easy to understand
  Cons. : Test class needs to know the layer below env.

1-b : Virtual Sequence


      task Test::run_phase();
        v_seq.seqr1_ = env.agent1.seqr;
        v_seq.start(null);

      task Virtul_Sequence::body()
        seq1.start(seqr1_);

  Factory override or start different virtual sequences to select target sequences
  Pros : No virtual sequencer is created
  Cons : Test needs to know layer below env and connect sequencer(s)
  Cons : A lot of extra components, virtual sequences, are necessary  (Different virtual sequence selection way)
  Cons : Difficult to understand for those who doesn't know factory override well. (Factory override way)

1-c : Virtual sequence and Virtual Sequencer


        function Env::connect_phase();
          v_seqr.seqr1_ = agent1.seqr;

        task Test::run_phase();
          v_seq.start(env.v_seqr);

        task Virtul_Sequence::body()
          $cast(v_seqr, m_sequencer);
          seq1.start(v_seqr.seqr1_);

    Factory override or start different virtual sequences to select target sequences
    Pros : Test doesn't need to know the layer below env.
    Cons : Extra component, virtual sequencer, is created
    Cons : Need to create multiple virtual sequences per test (Different virtual sequence selection way)
    Cons : Difficult to understand for those who doesn't know factory override well. (Factory override way)

1-d : Sequencer handles in Env (My original way)


        function Env::connect_phase();
          seqr1_ = agent1.seqr;

        task Test::run_phase();
          seq1.start(env.seqr1_);

    Pros : Easy to understand.
    Pros : Not need to know layer below Env.
    Cons : Not suggested in UVM user guide nor Verification Academy

2. Default Sequence Assignment


  function Test::build_phase();
    uvm_config_db#(uvm_object_wrapper)::set
    (  this,
       "env.agent1.seqr.run_phase",
       "default_sequence",
       Sequence1::type_id::get()
    );

Pros : Don’t need to create virtual sequences and virtual sequencer
Pros : Well-known way
Cons : Test needs to know the layer below env?
Cons : Difficult to understand for those who doesn’t know the concept of default sequence and configuration database

I know Mentor suggests 1-b in Verification Academy while they don’t recommend 1-c. However, I don’t get the drawback of 1-c they insist on. I guess 1-c was suggested by Cadence before.
Personally, I think 1-a or 1-d is a good way because they are clear and easy to understand. I don’t like 2.
The background of my question is that I am preparing a simple UVM example for those who doesn’t know UVM now. I don’t think the current UVM is suggesting definitive test sequence start/selection ways. So, I haven’t decided in which way I should implement. I hope this matter will be clarified in the next version of UVM in the near future.
I am looking forward to anyone’s comments.

In reply to serizawa:

I usually use 1-a, 1-b, 1-c (I think 1-d is not much different from 1-a) to start a sequence. Depending on my application/scenario, I will choose one of them to implement:

  • A single sequence generates stimulus for single DUT interface (single agent/sequencer) I will choose 1-a.
  • Multiple sequences (which need a communication/handshaking) for single DUT interface, I will choose 1-b.
  • Multiple sequences for multiple DUT interfaces (they have some relations together). I will choose 1-c.

I dont like #2, difficult to manage and understand the implementation flow. You need to manage objection in your sequence as well.

In reply to chris_le:

Thank you for your comment.
Regarding 1-d, there is no structural difference from 1-a. The point of 1-d is that its env has a handle(s) to a sequencer(s). Thanks to this, the test doesn’t need to look into the structure below env. UVM has basic concept that test and test bench structure should be clearly separated to make reuse possible. So, it is not good that test needs to know layer structure below env. For example, test class has to be updated whenever there is any structural changes in env like VIP change, another env insertion in the env, agent instance name change, etc. That’s the reason why I would rather suggest 1-d than 1-a (and 1-b).
To be hones, I don’t get why Mentor is introducing direct sequencer referencing by test in Cookbook of Verification Academy.

By the way, here is another discussion regarding virtual sequence/sequencer use. [advantages of virtual sequences versus tasks](https://verificationacademy.com/forums/uvm/advantages-virtual-sequences-versus-tasks) Please refer to this as well and leave your comments.

In reply to Orimitsu:

Tests are not considered re-usable. Sequences used by tests are re-usable.

Since tests are DUT specific (and hence ENV specific), assigning sequencer handles to a sequence is the easiest method to configure them. Additionally, if you have multiple agents of the same type, it is easier to reuse a sequence by assigning the sequencer of the desired agent to the sequence.

In reply to cgales:

In addition to Chuck, there is no ‘best way’ of starting a sequence. You should use an appropriate way for your environment and you should follow your coding guidelines. Mixing all the different options is indeed not a good way.