constraint_block is a list of
expression statements that restrict the range of a variable or define relations
between variables. A constraint_expression is
any SystemVerilog expression, or one of the constraint-specific operators: =>, inside and dist (see Sections 12.4.4 12.4.3 and 12.4.5
12.4.4).
12.4.3 Set membership
Constraints support integer value sets and set
membership operators (as defined in Section 7.17).
The syntax to define a set
expression is:
inside_expression ::= expression inside range_list_or_array
// from Annex A.8.3
range_list_or_array ::=
variable_identifier
| { value_range { , value_range } }
value_range ::=
expression
| [ expression
: expression ]
Syntax
12-3—inside expression syntax (excerpt from Annex A)
expression is any
integral SystemVerilog expression.
range_list_or_array is a
comma-separated list of integral expressions and ranges. Value ranges are
specified in ascending order with a low and high bound, enclosed by square
braces [ ], and separated by a colon ( : ), as in
[low_bound:high_bound]. Ranges
include all of the integer elements between the bounds. If the bound to the left
of the colon is greater than the bound to the right the range is empty and
contains no values.
The inside operator evaluates to true if
the expression is contained in the set; otherwise it evaluates to false.
Absent any other constraints, all values (either
single values or value ranges), have an equal probability of being chosen by
the inside operator.
The negated form denotes that expression lies outside the set: !(expression inside { set }).
For example:
rand integer x, y, z;
constraint c1 {x inside {3, 5, [
rand integer a, b, c;
constraint c2 {a inside {b, c};}
integer fives[0:3] = { 5, 10, 15, 20 };
rand integer v;
constraint c3 { v inside fives; }
Set values and ranges can be any integral expression. Values
can be repeated, so values and value ranges can overlap.
It is important to note
that the inside operator is
bidirectional, thus, the second example above is equivalent to a == b || a == c.
Just like implication, if...else style constraints are bidirectional. In the
declaration above, the value of mode constraints constrains the value of len, and the value of len constrains the value of mode.
12.13 Random weighted case – randcase
statement_item ::=
... // from Annex ???
{ attribute_instance } randcase randcase_item { randcase_item } endcase
randcase_item ::= expression : statement_or_null
The keyword randcase introduces a case statement that randomly
selects one of its branches. The randcase item
expressions are non-negative integral values that constitute the branch
weights. An item’s weight divided by the sum of all weights gives the
probability of taking that branch. For example:
randcase
3 :
x = 1;
1 :
x = 2;
4 :
x = 3;
endcase
The sum of all weights is 8, so the probability of taking the first
branch is 0.375, the probability of taking the second is 0.125, and the
probability of taking the third is 0.5.
If a branch specifies a zero weight then that branch is not taken.
If all randcase items specify zero weights then
no branch is taken and a warning may be issued.
The randcase weights can be arbitrary
expressions, not just constants. For example:
byte a, b;
randcase
a
+ b : x = 1;
a
- b : x = 2;
a
^ ~b : x = 3;
12’b800 : x = 4;
endcase
The precision of each weight expression is self-determined. The sum
of the weights is computed using standard addition semantics (maximum precision
of all weights), where each summand is unsigned. Each weight expression is
evaluated at most once (implementations may cache identical expressions) in an
unspecified order. In the example above, the first three weight expressions are
computed using 8-bit precision, the fourth expression is computed using 12-bit
precision; the resulting weights are added as unsigned values using 12-bit precision.
The weight selection then uses unsigned 12-bit comparison.
Each call to randcase retrieves one random number in
the range zero to the sum of the weights. The weights are then selected in
declaration order: smaller random numbers correspond to the first (top) weight
statements.
Randcase statements exhibit thread
stability. The random numbers are obtained from $urandom_range,
thus, random values drawn are independent of thread execution order.