-
Notifications
You must be signed in to change notification settings - Fork 23
Constraints
Constraints allow the user to define how the randomness should be directed. In this way, we can improve the effectiveness of a test by given random values which stimulate the DUT in more interesting ways.
In chiselverify.crv
, each variable can have one or multiple constraints. Constraint relations are usually preceded by the #
symbol. For example:
len #>= 2
In the previous block of code we are specifying that the variable len
can only take values that are grater then 2.
There are two ways to define constraints:
- Single constraints: One single constraints, like the one defined above, that can be independently from all other constraints.
- Constraint Groups: Multiple constraints grouped together in a single block, these must function together and constraints within a block can't be individually disabled or enabled.
Each constraint can be assigned to a variable, thus creating a single constraint. These can be enabled or disabled at any time during the test. For example:
val lenConstraint = len #> 2
[....]
lenConstraint.disable()
[....]
lenConstraint.enable()
Being able to enable
and disable
constraints allows one to define multiple constraints on a single random variable and then have test that use subsets of those constraints rather than being limited to always using all of the constraints.
Constraints can also be grouped together in a ConstraintGroup
and the group itself can be enabled or disabled.
val legal: ConstraintGroup = new ConstraintGroup {
len #>= 2
len #<= 5
payload.size #= len
}
[...]
legal.disable()
[...]
legal.enable()
By default, constraints and constraints groups are enabled when they are declared.
Multiple different operators can be used to define constraints. The list of operator used to construct constraints is the following:
-
#<
: Guarantees that the random variable will always generate values below a certain maximum. -
#<=
: Guarantees that the random variable will always generate values below or equal to a certain maximum. -
#>
: Guarantees that the random variable will always generate values above a certain minimum. -
#>=
: Guarantees that the random variable will always generate values above or equal to a certain minimum. -
#=
: Guarantees that the random variable will always generate values equal a certain value. -
div
: Guarantees that the random variable will always generate values within ranges resulting by the division of our random variable's bounds and either a given random variable's bounds or aBigInt
. -
#*
: Guarantees that the random variable will always generate values within ranges resulting by the multiplication of our random variable's bounds and either a given random variable's boudns or aBigInt
. -
mod
: Guarantees that the random variable will always generate values within ranges resulting by the modulus of our random variable's bounds and either a given random variable's bounds or aBigInt
. -
#+
: Guarantees that the random variable will always generate values within ranges resulting by the addition of our random variable's bounds and either a given random variable's bounds or aBigInt
. -
-
: Guarantees that the random variable will always generate values within ranges resulting by the inversion of our random variable's bounds' signs. -
#\=
: Guarantees that the random variable will never generate values equal a certain value. -
#^
: Guarantees that a random variable's generated value to a given exponent will be in a given range. -
in
,inside
: Guarantees that the random variable will always generate values in a certain range.
It is also possible to declare conditional constraints with constructors like IfCon
and IfElseCon
.
val constraint1: crv.Constraint = IfCon(len #= 1) {
payload.size #= 3
} ElseC {
payload.size #= 10
}
Here the constraint will only be applied if a given condition is met. This condition must be defined using constraint operators.
Custom distributions can also be defined using the dist
operator. This associates weights to each given range of values. The weights represent how likely it is that a value within said range will be generated:
val randVal: Rand = new Rand("customDist", 0, 0xFFFF)
val distConst = randVal dist (
0 to 0xF := 1,
0xF to 0xFF := 2,
0xFF to 0xFFF := 4,
0xFFF to 0xFFFF := 8 //Here it is more likely to generate higher values
)
The distribution we created makes it exponentially more likely to generate high values.
This is the last page on CRV. Return Home