UVM virtual sequencer: choose the right child sequencer

4.8k views Asked by At

I have a question about virtual sequencer in UVM. Let's think that I have N equal interfaces driven by N equal drivers, each one connected to its own sequencer. What I want to do is to have a transaction like:

    class my_transaction extends uvm_sequence_item;
         logic data;
         int num_if;
    endclass

that when executed with `uvm_do() is sent to the driver number num_if. My idea is that for this kind of work I need a virtual sequencer that "forward" the transaction to the right sequencer (the number num_if). Is this right? If yes, how it could be done? Thanks.

2

There are 2 answers

1
Gordon A On BEST ANSWER

While Tudor's answer will work technically, conceptually the decision on which of the interfaces to run on (num_if) is a value that should not belong to the transaction, but to the sequence that calls it (which of course should also be randomized). Transactions should contain only a representation of the value that travels from A to B and the way in which it travels for that protocol. The specification of which A and B is normally outside of the responsibility of a transaction.

In which case, a variation on your transaction and Tudor's sequence would look like this:

class my_transaction extends uvm_sequence_item;
   rand logic data;
endclass

..and..

class some_virtual_sequence extends uvm_sequence;
  `uvm_declare_p_sequencer(virtual_seqr)
  rand int num_if; constraint.....
  task body();
    my_transaction trans = my_transaction::type_id::create("my_transaction");
    start_item(trans, , p_sequencer.seqrs[num_if]);
    trans.randomize(); // randomization should be done after start_item()
    finish_item(trans);
  endtask
endclass

..running on the virtual sequencer as Tudor says:

class virtual_seqr extends uvm_sequencer;
  my_sequencer seqrs[10];
endclass

The above approach also lets the randomization happen in the correct place: after start_item() returns and immediately prior to calling finish_item() which completes the sequence item.

0
Tudor Timi On

You're right about the virtual sequencer. I'll show you an idea on how to do it (all pseudo-code, you'll have to work on the details yourself).

Let's say we have a virtual sequencer that contains an array of all the bus sequencers:

class virtual_seqr extends uvm_sequencer;
  my_sequencer seqrs[10];
endclass

We'll assume these handles get passed properly. In our virtual sequence, we can create a transaction, randomize it and then send it to the appropriate sequencer.

class some_virtual_sequence extends uvm_sequence;
  `uvm_declare_p_sequencer(virtual_seqr)

  task body();
    my_transaction trans = my_transaction::type_id::create("my_transaction");
    my_transaction.randomize();
    start_item (my_transaction, , p_sequencer.seqrs[my_transaction.num_if]);
    finish_item(my_transaction);
  endtask
endclass

We can't use uvm_do, because that doesn't know where to dispatch. We also can't use uvm_do_on because the num_if field has to be randomized before to know where to send the item.