Gotcha: Function Calls in SystemVerilog Constraints

SystemVerilog allows to call functions inside constraints, although, as I found out, it is a sensitive topic.
Here is an example:

class constraint_container;
  rand int unsigned a, b, c;

  function int unsigned get_a();
    return a;

  function int unsigned value_of(int unsigned value);
    return value;

  constraint a_constraint {
    a == 5;
    // I expect "b" to be equal to "a", but, surprise, surprise...
    b == get_a();
    // I expect "c" will be equal to "a"
    c == value_of(a);

module top;
  initial begin
    automatic constraint_container cc_inst = new();
    $display($sformatf("a: %0d, b: %0d, c: %0d", cc_inst.a, cc_inst.b, cc_inst.c));

At first glance one would guess that all three fields will be 5, but one will get instead:

a: 5, b: 0, c: 5

Gotcha: regardless of the seed, b will always be equal to 0!
It looks like get_a() is evaluated before the generation, when a is 0.

The closest thing I could find as an explanation for this behavior was in SystemVerilog IEEE 1800-2012 standard, chapter “18.5.12 Functions in constraints”:

Functions shall be called before constraints are solved, and their return values shall be treated as state variables.
Function calls in active constraints are executed an unspecified number of times (at least once) in an unspecified order.

The conclusion is that functions used by constraints should compute the result based ONLY on function’s arguments and NOT on class members.


Tudor Timi March 12th, 2015 22:12:20

It’s the same for e as well. Cadence has a note saying that functions used in constraints shouldn’t use any class members/global variables.

    Cristian Slav March 13th, 2015 10:20:42

    Hi Tudor,

    I could not find such a note. Can you please point me to a specific chapter?

    I just gave it a try in ‘e’ language using this code:

    struct constraint_container {
       a : uint;
       b : uint;
       c : uint;
       get_a() : uint is {
          return a;
       value_of(value : uint) : uint is {
          return value;
       keep a == 5;
       keep b == get_a();
       keep c == value_of(a);
    extend sys {
       run() is also {
          var cc_inst : constraint_container;
          gen cc_inst;
          messagef(LOW, "a: %0d, b: %0d, c: %0d", cc_inst.a, cc_inst.b, cc_inst.c);

    The output is this:

    a: 5, b: 5, c: 5

Juhi Patel April 29th, 2021 09:48:23

It might be the case with old version of simulator. I tried this on vcs 2020 version and got error msg as below:

Error-[CSTR-UMC] Constraint: unsupported method call, 17
$unit, “this.get_a()”
Method constraint_container::get_a contains a construct not supported in
constraint functions: reference to a rand variable ‘a’ at line 7 of
Rewrite the method to avoid unsupported constructs.

1 error

Leave a Comment:

Your comment will be visible after approval.

(will not be published)

This site uses Akismet to reduce spam. Learn how your comment data is processed.