Question

I ran across the following constraint in a testbench. It's behavior seems to vary depending on the simulator used.

constraint wr_c {
    if (!one_beat) { addr[5:0] == 0, len == 15 };
}

What is it actually supposed to do, as written?

An example:

import uvm_pkg::*;

class pkt extends uvm_object;

  rand bit one_beat;
  rand int len;
  rand bit [31:0] addr;

  `uvm_object_utils_begin(pkt)
    `uvm_field_int(one_beat, UVM_DEFAULT)
    `uvm_field_int(len, UVM_DEFAULT)
    `uvm_field_int(addr, UVM_DEFAULT)
  `uvm_object_utils_end

  constraint wr_c {
    if (!one_beat) { addr[5:0] == 0, len == 15 };
  } 

endclass

module test;

  initial begin
    for (int i = 0; i < 10; i++) begin
      automatic pkt p = new();
      p.randomize();
      p.print();
    end
  end

endmodule
Was it helpful?

Solution

The reason the different simulator give different results likely has to do with what it constitutes as true for the solver. Using the following example:

rand bit [1:0] example;
rand bit one_beat;
constraint example_c { if(!one_beat) example; }

In this case example has the same randomization width as { addr[5:0] == 0, len == 15 }. Depending on the simulator the above constraint may infer example==2'b1 or example!=2'b0 or example>2'b0 (different results with signed and unsigned) . If one_beat wasn't an one-bit value, the same issue would be true for want counts as true for the if() statement.

If the OR option is intended, a better way to write the constraint would be:

if (!one_beat) ( addr[5:0] == 0  ||  len == 15 );

or

if (!one_beat) { addr[5:0] == 0, len == 15 } != 0; // or '>0', '>=1', etc

There is a good change the creator of the constraint intended both constraints to be true when if(!one_beat). In this case the follow would be better constraint options:

if (!one_beat) { addr[5:0] == 0; len == 15; } // note the semicolon positions

or

if (!one_beat) ( addr[5:0] == 0 && len == 15 );

Also note that with the given SSCCE, one_beat has a very low probability of being 1'b0 because the solver is trying to find a legal condition for one_beat, addr and len in parallel with equal priority.

  • When addr[5:0]==0 || len==15 its probability is 1/(1+2**6) + 1/(1+2**32)
  • When addr[5:0]==0 && len==15 its probability is 1/(1+2**(6+32))

If this is not intend, then add another constraint such as one_beat dist { ... }; or sovle one_beat before addr,len;

OTHER TIPS

This is how the constraint behaves on different simulators. The constraint behaves differently because the simulators treat the concatenation constraint {a, b}; in different ways.

The code below is pseudo code for purposes of demonstrating how the constraint from the question works.

On VCS 2013.06:

if (!one_beat) { 
  { addr[5:0] == 0, len == 15 } == 2'b01 || { addr[5:0] == 0, len == 15 } == 2'b10;
  // distribution highly favors 2'b01
}

On Questa SIM 10.1d:

if (!one_beat) { 
  { addr[5:0] == 0, len == 15 } == 2'b10;
}

On INCISIV 13.10.001:

if (!one_beat) { 
  { addr[5:0] == 0, len == 15 } == 2'b01 || { addr[5:0] == 0, len == 15 } == 2'b10;
  // distribution favors 2'b10
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top