Renumber Sections 20.5 through 20.12 to be subsections of 20.4 (20.4.1 through 20.4.8. Move Section 20.17 to 20.4.9.
Move Section 20 to be after Section 11 and renamed to Section 12 and renumber existing Sections 12 and on to be 13 and on.
Change as shown in red:
Constraint-driven test
generation allows users to automatically generate tests for functional
verification. Random testing can be more effective than a traditional, directed
testing approach. By specifying constraints, one can easily create tests that
can find hard-to-reach corner cases. SystemVerilog
allows users to specify constraints in a compact, declarative way. The
constraints are then processed by a solver that generates random values that
meet the constraints.
Change as shown in red:
This section introduces the
basic concepts and uses for generating random stimulus within objects. SystemVerilog uses an object-oriented method for
assigning random values to the member variables of an object subject to
user-defined constraints.
and
The MyBus class
inherits all of the random variables and constraints of the Bus class, and adds
a random variable called type that is used to control the address range using
another constraint. The addr_range constraint
uses implication to select one of three range constraints depending on the
random value of type. When a MyBus object is
randomized, values for addr, data, and type
are computed such that all of the constraints are satisfied. Using
inheritance to build layered constraint systems enables
the development of general-purpose models that can be constrained to
perform application-specific functions.
and
This example illustrates
several important properties of constraints:
— Constraints can be any
SystemVerilog expression with variables and constants of integral type (bit, reg, logic, integer, enum, packed struct, etc…).
— Constraint expressions follow SystemVerilog syntax and semantics,
including precedence, associativity, sign extension,
truncation, and wrap-around.
and
— Constraints interact bidirectionally.
In this example, the value chosen for addr depends on
type and how it is constrained, and the value chosen for type depends on addr and how it is constrained. All expression operators
are treated bidirectionally,
including the implication operator (=>).
and
The ability to enable or
disable constraints allows users to design a constraint hierarchies.
and
Similarly, the $rand_mode()
method can be used to enable or disable any random variable. When a random
variable is disabled, it behaves in exactly the same way as other nonrandom variables.
and (make sure font for pre_randomize and post_randomize is the same):
Occasionally, it is desirable
to perform operations immediately before or after randomization. That is
accomplished via two built-in methods, pre_randomize() and
post_randomize(), which are
automatically called before and after randomization. These methods can be
overloaded with the desired functionality:
and for the 2nd to last paragraph make the change shown in red:
By default, pre_randomize() and post_randomize()
call their overloaded parent class methods. When pre_randomize() or
post_randomize() are overloaded, care must
be taken to invoke the parent class’ methods, unless the class is a base class
(has no parent class), otherwise
the base class methods will not be called.
Change as shown in red:
— The solver can randomize singular
variables of any integral type such as integer, enumerated types, and packed
array variables of any size.
— Arrays can be declared rand or randc, in which case all of their member elements
are treated as rand or randc.
— Dynamic and associative arrays can be declared rand
or randc. All of the elements in the array
are randomized, overwriting any previous data. If the array elements are of type object, all of the
array elements must be non-null. Individual array elements may be
constrained, in which case the index expression must be a literal constant.
— The size of a dynamic array declared as rand or
randc may also be constrained. In
that case, the array will be resized according to the size constraint, and then
all the array elements will be randomized. The array size constraint is declared
using the size method. For example,
rand
bit[7:0] len;
rand
integer data[*];
constraint
db { data.size == len
; );
The variable len is declared to be 8 bits wide. The
randomizer computes a random value for the len
variable in the 8-bit range of 0 to 255, and then randomizes the first len elements of the data array.
If a dynamic array’s size
is not constrained then randomize() randomizes
all the elements in the array.
— An object handle can be
declared rand in which case all of that object’s variables and
constraints are solved concurrently with the other class variables and constraints of the object that contains the handle. Objects
cannot be declared randc.
Change as shown in red:
The semantics of random-cyclical variables requires that they be solved before other random variables.
Change as shown in red:
The values of random
variables are determined using constraint expressions that are declared using
constraint blocks. Constraint blocks are class members, like tasks, functions,
and variables. They must be defined after the variable
declarations in the class, and before the task and function declarations in the
class. Constraint block names must be
unique within a class.
and
— randc
variables cannot be specified in
ordering constraints (see solve..before
in Section 20.12).
Change as shown in red:
— A constraint in a derived class that uses the same
name as a constraint in its parent classes effectively overrides the base class constraints. For example:
Remove the last bullet as shown in red:
— The randomize() task
is virtual, accordingly, it treats the class constraints in a virtual manner.
When anamed constraint is overloaded, the previous
definition is overridden.
— The built-in methods pre_randomize() and post_randomize()
are functions and cannot block.
Change as shown in red:
The syntax to define a set
expression is:
expression
inside { value_range_list
};
or
expression
inside array_identifier; // fixed-size, dynamic, or
associative array
and
value_range_list is a
comma-separated list of integral expressions and ranges. Ranges are specified
with a low and high bound, enclosed by square braces [ ], and separated by a
colon: [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 or equal to the bound to
the right, otherwise the
range is empty and contains no values.
change the example as shown in red:
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; }
Change the last paragraph adding as shown in red:
Limitations:
— A dist operation may not be applied to randc variables.
— A dist expression requires that expression
contain at least one rand variable.
— A dist expression can only be a top-level constraint (not a
predicated constraint).
Clean-up font usage in this section (sizes are inconsistent).
and change as shown in red:
The constraint is
any valid constraint, and constraint_block represents
an unnamed constraint block. If the expression
is true, all of the constraints in the constraint block must also be satisfied.
and in the last example:
bit[3:0]
a, b;
constraint
c {(a == 0) => (b == 1) ; };
and remove the last paragraph:
It is important to that the constraint
solver be designed to cover the whole random value space with uniform
probability. This allows randomization to better explore the whole design space
than in cases where certain value combinations are preferred over others.
Change as shown in red:
If-else style constraints are also supported.
and
constraint_block represents
an unnamed constraint block. If the expression
is true, all of the constraints in the first constraint block must be satisfied,
otherwise all of the constraints in the optional else-constraint-block must
be satisfied. Constraint blocks may be used to group multiple constraints.
and
Just like implication,
if-else style constraints are bidirectional. In
the declaration above, the value of mode constraints the value of len,
and the value of len constrains the
value of mode.
Change as shown in red:
This example uses global
constraints to define the legal values of an ordered binary tree. Class A
represents a leaf node with an 8-bit value x. Class B extends class A and
represents a heap-node with value v, a left sub-tree,
and a right sub-tree. Both sub-trees are declared as rand in order to
randomize them at the same time as other class variables. The constraint block
named heapcond has two global
constraints relating the left and right sub-tree values to the heap-node value.
When an instance of class B is randomized, the solver simultaneously solves for
B and its left and right children, which in turn may be leaf nodes or more
heap-nodes.
Change as shown in red:
The solver must assure that the random values are selected to
give a uniform value distribution over legal value combinations (that is, all
combinations of values have the same probability of being the solution). This important property guarantees that
all value combinations are equally probable, which allows randomization to better explore the whole design space.
and
variable_list is a
comma-separated list of integral singular
variables or array elements.
and
— The variables must be integral singular values.
and
— Variables that are not
explicitly ordered will be solved with the last set of ordered variables. These
values are deferred until as late as possible to assure a good distribution of values.
Change as shown in red:
Checking the return status may be necessary because
the actual value of state variables or addition of constraints in derived
classes may render seemingly simple constraints unsatisfiable.
Change as shown in red:
When obj.randomize()
is invoked, it first invokes pre_randomize()
on obj and also all of its random
object members that are enabled. pre_randomize() then recursively calls super.pre_randomize().
After the new random values are computed and assigned, randomize() invokes
post_randomize() on obj
and also all of its random object members that are enabled. post_randomize() then recursively calls super.post_randomize().
and
If these methods are
overloaded, they must call their associated parent class methods, otherwise
their pre- and post-randomization processing steps will be skipped.
The pre-randomize() and post-randomize() methods are not virtual. However, because they are
automatically called by the randomize() method,
which is virtual, they appear to behave as virtual methods.
Notes: 20.13.3 Randomization methods notes
and
— If randomize() fails, post_randomize()
is not be
called.
— The randomize() method
may not be overloaded.
— The randomize() method
implements object random stability. An object can be seeded by the $srandom()
system call, specifying the object in the second argument.
— The built-in methods pre_randomize()
and post_randomize() are functions
and cannot block.
Change as shown in red:
The unnamed constraint block contains additional in-line
constraints to be applied along with the object constraints declared in the
class.
Change as shown in red:
The function form of $rand_mode()
only accepts singular variables, thus, if
the specified variable is an array, a single element must be selected via its
index.
Change as shown in red:
A constraint
block can be defined as static by
including the static keyword in its
definition.
Change as shown in red:
The system function $urandom provides a mechanism for generating pseudorandom numbers. The function returns a new
32-bit random number each time it is called. The number is unsigned.
and
The random number generator
is deterministic. Each time the program executes, it cycles through the same
random sequence. This sequence can be made nondeterministic
by seeding the $urandom function with an
extrinsic random variable, such as the time of day.
and
The $urandom
function is similar to the $random system function, with two
exceptions. $urandom returns unsigned numbers
and is automatically thread stable (see Section
20.20.2).
Change as shown in red:
The system
function $srandom() allows manually seeding the Random Number Generator (RNG) of objects or threads.
Change as shown in red:
Object stability is
guaranteed as long as object and thread creation, as well as random number
generation, are done in the same order as before.
In order to maintain random number stability, new objects, threads and random
numbers can be created after existing objects are created.
Change as shown in red:
Calling $srandom()
in an object’s new() function, assures the object’s RNG is set with
the new seed before any class member values are
randomized.
Change as shown in red:
— $dimensions
shall return the number of dimensions
in the array, or 0 for a singular object
Add the following BNF as appropriate:
Constraints BNF
<expression> ::= <verilog_expression> //
Add <inside> to <expression>
| <inside>
<inside> ::= <expression> 'inside' <range_list_or_array>
// Note: outside is specified as '!'
'(' <inside>
')'
<range_list_or_array> ::= <array_identifier> //
fixed, dynamic, associative
| '{'
<value_range> { ',' <value_range>
} '}'
<value_range> ::= <expression>
| '['
<expression> ':'
<expression> ']'
<constraint_declaration> ::= ['static'] 'constraint' <identifier>
'{' { <constraint_block>
} '}'
<constraint_block> ::= 'solve' <identifiers> 'before' <identifiers> ';'
| <expression> 'dist' '{' <dist_list>} '}'
';'
| <constraint>
<constraint> ::= <expression> ';'
| <expression> '=>' <constraints>
| 'if'
'(' <expression> ')' <constraints> [ 'else'
<constraints> ]
<constraints> ::= <constraint>
| '{'
{ <constraint> } '}'
<dist_list> ::= <dist_item> { ',' <dist_item>
}
<dist_item> ::= <value_range>
':=' <expression>
| <value_range>
':/' <expression>