Force value of random field in seq_item from test

Dear all,

Here’s the context: I am setting up a UVM database containing reusable components, such that different projects can reuse the same components over and over. For the sake of reusability I am planning to have a repo of reusable components, so that any project can make use of those components by simply referencing the repo.

For instance, in the UVM repo I would put components for AXI4 Stream: sequence item (axi4s_master_seq_item and axi4s_slave_seq_item), sequences (axi4s_master_seq and axi4s_slave_seq), sequencer (axi4s_seqr), and agents (axi4s_master_agent and axi4s_slave_agent). The axi4s_seq_item contain constraint to properly randomize the transactions, and the axi4s_seq classes simply create one single transaction.

In my project for instance, I have an AXI4 Stream Slave component that accepts transactions generated and managed by the axi4s_master_agent. The project repo contains the environment and the test classes. However, in this “default” scenario, the transactions generated by the axi4s_master_seq will meet the “default” constraints specified in axi4s_master_seq_item. As a reference for the discussion, the axi4s_master_seq_item contains a random integer specifying the length of the burst (number of data chunks to send):


class axi4s_master_seq_item extends uvm_sequence_item;
    rand int stream_len;
    //...
    constraint len_c {
        stream_len inside { [1:512] };
    };
endclass

There might be cases, though, where I need to override the “default” constraints. For instance, in my test I want the stream_len field to be exactly 256. Being UVM newbie, my current thought is to create in my project a prj_master_seq class that inherits from axi4s_master_seq whose body contains the following:


class prj_master_seq extends axi4s_master_seq;
    //...
    virtual task body();
        //..
        assert(req.randomize() with {
            stream_len == 256;
        });
        //...
    endtask
    //...
endclass

The test then instantiates such prj_master_seq instead of the axi4s_master_seq base. However, doing so would require having a different *_seq class for each scenario I want to test, bloating the repository.

So, which is the proper way to manage this? Is there a way to keep the reusable UVM repo as bare and generic as possible, so that each project should only write the really strictly necessary classes, ideally only the test and environment classes?

Many thanks
Best regards

S

In reply to scorbetta:

There are two approaches I’m aware of, both of which involve separating the hard coded constraints values from your sequence_item into another class

You can use the uvm_config_db to set “knobs” which are values used by your constraints. Each test can override the values used by the constraints. For example, you can have a stream_len_start and stream_len_end variable to define the range


class constraint_knobs;
      int stream_len_start = 1, stream_len_end = 512;
      int stream_len_list[];
endclass
class axi4s_master_seq_item extends uvm_sequence_item;
    constraint_knobs knob=new;
    rand int stream_len;
    //...
    
    constraint len_c {
        stream_len inside { [knob.stream_len_start:knob.stream_len_end] };
        knob.stream_len_list.size>0 -> stream_len inside { knob.stream_len_list };
    };
endclass

Another approach is packaging up a constraint into what’s called a “policy class”. There are a number of papers describing this, including this: SystemVerilog Constraint Layering via Reusable Randomization Policy Classes