CFS Vision

SystemVerilog Gotcha: In-line Constraints Scope

The in-line constraints in SystemVerilog are implemented by the class.randomize() with {…} syntax which basically allows you do add additional constraints over the generation of some field from some class.

I’ll show you a very common mistake which engineers are doing with this feature.

Let’s say that we have a sequence item with some integer field called size:
class my_item extends uvm_sequence_item;
rand int unsigned size;

constraint default_size {
size < 1000;
}

endclass

In a sequence body, when we randomize this item we want to constrain the size to a particular value. For this we use a local field in our sequence:
class my_sequence extends uvm_sequence;
task body();
int unsigned size = 5;
my_item local_item = my_item::type_id::create("local_item");

void'(local_item.randomize() with {
local_item.size == size;
});

`uvm_info("cfs", $sformatf("local_item.size: %0d", local_item.size), UVM_LOW)
endtask

endclass

If you think that local_item.size will be 5 after randomization you will be very wrong. I simulated this code on EDA Playground and this is the strange output:
UVM_INFO testbench.sv(33) @ 0: reporter@@local_sequence [cfs] local_item.size: 169

Did you spot the problem?
Is not that easy!

Inside the scope of randomize() with {…} local_item.size and size are the same field, the size member of local_item object. So the constraint above is the same as writing:

void'(local_item.randomize() with {
local_item.size == local_item.size;
});

In order to access the local variable size from the body() task you need to use local::size
void'(local_item.randomize() with {
local_item.size == local::size;
});

Hope this helps!


If you want to gain an in-depth knowledge on how to do module level verification using SystemVerilog and UVM language then checkout my Udemy course called “Design Verification with SystemVerilog/UVM


Cristian Slav

10 comments

  • I have encountered this and spent an entire day debugging it. Great to see your article resonates with what we encounter in our day-to-day life. Keep up the good work and expecting more articles from you.

  • How is this.variable different from local::variable in this constraint? Will the code

    void'(local_item.randomize() with {
    local_item.size == this.size;
    });
    wouldn’t have worked?

    • Hi Lakshmi,

      I don’t think it will work because this is actually that local_item so for the simulator is like doing “local_item.size == local_item.size;”. That local:: points to the “local” context of local_item – so it refers to the local variable from the body() task.

      Hope this helps,
      Cristi

  • Great article, Cristian!
    Spent quite some time to solve this. It was a pain to find it, especially as a begginer!

    Best regards,
    Iulian