Jump to content
cliffc

Starting sequences on null sequencer?

Recommended Posts

@Uwe But what does this mean exactly? If it's a virtual sequence running on a 'null' sequencer, it can only start other sequences if it gets pointers to the respective sequencers from some other source (config DB, etc.) and not from its parent sequencer, right? Also, we probably can't do any funky grabbing or prioritization, either.

 

In what scenario would this be useful?

Share this post


Link to post
Share on other sites

I've used it just because for a simple virtual sequence there's no need to create a virtual sequencer whose only purpose is to hold references to the sub-sequencers. You can put those references in the virtual sequence instead.

 

So I suppose it just saves a bit of typing!

 

regards

Alan

 

P.S. I wish UVM had used different words that "sequence" and "sequencer"... it's a recipe for confusion.

Share this post


Link to post
Share on other sites

@Alan -

 

I have always used the almost-empty virtual sequencer with references to the sub-sequencers and used the env to copy the subsequencer handles to the handles declared in the virtual sequencer, then my vseq_base class would $cast the m_sequencer handle to the vseqr handle and use that handle to set the sub-sequencer handles declared in the vseq_base class. Then I could extend the vseq_base to create virtual sequences that started on the two sub-sequencer handles. Relevant code from the vseq_base and vseq classes below.

 

Could you give an equivalent example of how you copy the handles into the virtual sequence and then execute the virtual sequence on null? Perhaps @uwes could explain how it tis done.

 

Thanks - Cliff

 

class vseq_base extends uvm_sequence;

  `uvm_object_utils(vseq_base)

 

  function new(string name="vseq_base");

    super.new(name);

  endfunction

 

  vsequencer         v_sqr;

  tb_ahb_sequencer ahb_sqr;

  tb_eth_sequencer eth_sqr;

 

  virtual task pre_body();

    if(!$cast( v_sqr, get_sequencer() ))

      `uvm_fatal("vseq_base","BAD v_sqr type");;

    ahb_sqr = v_sqr.ahb_sqr;

    eth_sqr = v_sqr.eth_sqr;

  endtask

endclass

 

class v_seq1 extends vseq_base;

  `uvm_object_utils(v_seq1)

 

  function new(string name="v_seq1");

      super.new(name);

    endfunction

 

  task body();

    ahb_pkt ahb_pkt;

    eth_pkt eth_pkt;

    //---------------------------------------------------

    `uvm_info("v_seq1", "Executing virtual sequence on DUT.", UVM_HIGH)

    `uvm_do_on(ahb_pkt, ahb_sqr)

    `uvm_do_on(eth_pkt, eth_sqr)

    `uvm_do_on(eth_pkt, eth_sqr)

    `uvm_do_on(ahb_pkt, ahb_sqr)

    `uvm_info("v_seq1", "Sequence complete.", UVM_MEDIUM)  

  endtask

endclass

Share this post


Link to post
Share on other sites

@Uwe But what does this mean exactly? If it's a virtual sequence running on a 'null' sequencer, it can only start other sequences if it gets pointers to the respective sequencers from some other source (config DB, etc.) and not from its parent sequencer, right? Also, we probably can't do any funky grabbing or prioritization, either.

 

In what scenario would this be useful?

 

thats correct. a virtual sequence running on a null sequencer can start other virtual sequences(on this or other sequencers) or other BFM sequences/items (when a real sequencer handle is supplied). The 'funky' stuff like grab/lock does probably require a sequencer instance. priorities should only be in the picture for items.

 

/uwe

Share this post


Link to post
Share on other sites

hi,

 

some pseudo code (lacking checks,ctor and other things)

class vseq1 extends uvm_sequence...;
  seqr1 s1;
  seqr2 s2;

  task body(); ... endtask
endclass

// with this simply instantiate the sequence assign the sequencers and start it

vseq1 = new();
vseq1.s1 = path.to.my.sqr1;
vseq1.s2 = path.to.other.sqr1;
vseq.start(null);

you may also do it via the config-db

class vseq1 extends uvm_sequence...;

  task body();
     seqr1 s1;
     seqr2 s2;

     uvm_config_db#(seq1type)::get(ctxt,"sqr1",s1);
     uvm_config_db#(seq1type)::get(ctxt,"sqr2",s2);

     `uvm_do_on(....)

  endtask
endclass

the challenge here is to invent a 'context'. 'null' or get_sequencer() isnt a good context alone here since it would map to uvm_root::get() and doesnt scale. but you could use ctxt=null and {get_full_name(),".sqr1"} as the full path for your virtual sequence plus the "sqr1" postfix

 

/uwe. 

 

Share this post


Link to post
Share on other sites

the challenge here is to invent a 'context'. 'null' or get_sequencer() isnt a good context alone here since it would map to uvm_root::get() and doesnt scale. but you could use ctxt=null and {get_full_name(),".sqr1"} as the full path for your virtual sequence plus the "sqr1" postfix

 

/uwe. 

 

An alternative approach is to add a sequence to sequencer mapper to the top level environment, and use it to run sequences without reference to sequencers by calling (common) services in base classes for tests and sequences. Cliff's vsequence would go like this:

 

task body();

  `uvm_info("v_seq1", "Executing virtual sequence on DUT.", UVM_HIGH)

  RunSequence(ahb_pkt::Create());

  RunSequence(eth_pkt::Create());

  RunSequence(eth_pkt::Create());

  RunSequence(ahb_pkt::Create());

  `uvm_info("v_seq1", "Sequence complete.", UVM_MEDIUM) 

endtask

 

In other words, just create the sequence and run, and it will be randomized in context of, and start on, the right sequencer automatically, provided the calling context is a test, sequence, or vsequence.

 

Advantages:

 

- no dot-pointing into the env

- no need to single step through macros to debug

- no need to distribute sequencers

- easier for non-experts to modify/add tests

- randomization, error checking etc in one place

- inline constraints are discouraged

 

BTW, null-sequencers aren't a wonderful idea in my opinion. An actual sequencer provides a context for sequences from the very beginning, which makes it easier to deal with resources etc, where the caller context is significant.

 

 

Erling

Share this post


Link to post
Share on other sites

Hi experts,

I have the following question about vertical reusability and null sequencers.

I have a sequence that stimulates a sub block inside a TOP block. I have verified first the separated sub block. Therefore, i had a testbench for the sub block that has of course VC interfaces and registers.

I would like to have a clear way of coding to allow vertical reusability of the sequence that test the sub block. In other words, i would like how to code the sub sequence so that i can start that sequence from a TOP module afterwards.

I see the following problems

1)The TOP test bench will not have the interfaces (VCs) for the sub block.

2)The registers will be accessed through the TOP interface but not the sub interface.

I can solve the 2 point by creating a new register model and connecting the predictor/adapter of the top. At the same time, i can overwrite the register model used in the sub block sequence so that it uses the new register TOP block handler correctly.---:OK

However for the point one, it is more difficult. Theoretically, the sequence should ignore all the VCs of the sub block that are not used anymore. Now the sub block is driven by the TOP DUT and not by a test bench VC. How should a write the sequence so that these VC accesses are ignored in case a TOP sequence calling the old subsequence?.

I though that any uvm_do macro that is performed to a VC that is not declared would be ignored but that is not the case...

The only idea it comes to me is to code the sub-sequence with an if asking if the VC exists (not null). If it exists, then go ahead, but if it doesn´t assume that this access will be done by a TOP DUT and ignore it!

Is this the right way to do this? How can you reuse your old sub sequence from the top sequence? Is there any methodology? Any link?

Thanks in advance

Jonathan

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×