Search code examples
system-veriloguvm

UVM virtual sequencer: choose the right child sequencer


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.


Solution

  • 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.