SystemVerilog Gotcha: In-line Constraints Scope

SystemVerilog Gotcha: In-line Constraints Scope

Posted by

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:

1
2
3
4
5
6
7
8
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
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:

1
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:

1
2
3
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

1
2
3
void'(local_item.randomize() with {
   local_item.size == local::size;
});

Hope this helps!

Cristian Slav

10 Comments

  • syed.taahir.active99@gmail.com' Taahir says:

    Awesome article

  • imajeeth@gmail.com' Ajeeth Kumar Venkatesan says:

    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.

  • ananthula08@gmail.com' Ananthalakshmi says:

    Great Post Cris.

  • ananthula08@gmail.com' Ananthalakshmi says:

    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

  • iulian.dirstaru1@gmail.com' Iulian Dirstaru says:

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

    Best regards,
    Iulian

Leave a Reply

Your email address will not be published.