Split Bigger Problem into Smaller Ones
Instead of mixing everything together, splitting bigger problems into smaller steps offers better performance. One may consider using “Solve-Before” for user defined solving order.
In addition, it is also recommended to sequence constraint solving in “pre_randomize()” and “post_randomize()” whenever possible.
Use “Solve-Before” with Caution
Although user-defined “solve-before” constructs are a powerful tool to control solver order, improper usage can lead to multiple retries and simulation performance degradation.
In the example below, “x” and “y” may be resolved early to certain illegal values that cannot satisfy the constraint. Constraining “x” and “y” properly avoids constraint solver retries.
class myClass {
rand bit [7:0] x, y, z;
constraint legal_range {
(x * y) + z == 10;
solve x, y before z;
// constraining x & y properly to avoid retries
(x * y) < 10;
}
}
endclass
Use SystemVerilog Build-in Functions
Using SystemVerilog built-in functions improves readability and avoids errors. For example, to randomize and uniquify an array “arr”, use “arr.unique()”; to sort an array “arr”, use “arr.sort()”.
Prefer Integer Randomization Functions Whenever Possible
There are multiple ways to randomize variables, for example:
- Standard randomization function “std::randomize()”
- Object built-in randomization function “obj.randomize()”
- Unsigned integer randomization functions “$urandom()” and “$urandom_range()”
- Signed integer randomization function “$random()”
Use integer randomization functions whenever possible, since they offer tens or even hundreds of times performance gains over standard and object built-in randomization functions. For example:
// Randomize a 64-bit unsigned variable “var”
// Instead of using
std::randomize(var);
// Using two concatenated $urandom()
var = {$urandom(), $urandom()};
// Randomize an unsigned integer “var”
// Instead of using
std::randomize (var) with {
var >= MIN;
var <= MAX;
};
// Use $urandom_range() instead
var = $urandom_range(MIN, MAX);
// Randomize a bit with unified distribution
rand bit rand_bit;
// Instead of using
std::randomize (rand_bit) with {
rand_bit dist {0:=50, 1:=50};
};
// Use $urandom_range() instead
rand_bit = $urandom_range(1);
Avoid Using Real Datatypes
SystemVerilog LRM defines that constraint solvers only need to handle integer types. Real datatypes in constraints may result in poor randomization performance. For example:
class myClass {
rand int unsigned x, y;
constraint xy_range {
x inside {[100 : 1000]};
// Do not write this way
// y inside {[0.5*x : x]};
// Use integer based workaround
y inside {[x/2 : x]};
}
}
endclass

Leave a comment