Randomization-V1.pdf

(175 KB) Pobierz
Microsoft Word - Randomization.doc
Accellera VHDL-TC Extensions-SC
Randomization
Jim Lewis, SynthWorks
jim@synthworks.com
Version 1.0 Draft , 26 Mar 2007
Abstract
This paper explores ideas for implementation of randomization in VHDL.
Revision History
Version 1.0 26-Mar-07, Jim Lewis. Initial work in progress draft.
1. Motivation
The rationale for bringing randomization and other verification constructs into VHDL is to remove the language
barrier between verification and design engineers. While verification and design techniques may be different,
familiarity with the language will help bridge the gap. While language constructs are being added to VHDL, it is
important to realize there are several existing verification languages and offering similar constructs and capability is
important so that similar and/or common methodologies can be utilized.
Many designs contain numerous configurable features. Testing features individually in an isolated manner is
typically straightforward. However, testing how these features interact can be a large verification space – one that
may not be able to be simulated completely. It is also may be difficult to predict all of the corner cases.
Randomization has been used to sequence a test in a non-deterministic way to get reasonably good coverage of this
verification space.
Each randomization covers a set of values such as the values used in a transaction or the mix of transactions to be
used on an interface. As a result, relationships need to be expressed between different items. These relationships
can be expressed either procedurally with code or declaratively. Existing verification languages use both
approaches.
Procedural based approach can use the same process structure and transaction based procedures used by a directed
test approach. Basic randomization capability is used to randomize each item separately. Items may be transaction
types (controlling the sequencing), transaction values (including error injection), delays, and other items.
In a declarative approach, typically a class is used to bundle items together such that relationships between them can
be expressed. In addition, a class offers the benefits being OO extensible and including methods with the objects.
Sequencing and transaction value generation become part of the class. Except when the class value need to be
overridden, the process generating the test sequence becomes very generic – one has to focus on what is in the class
to know what the test is doing.
Procedural approach gives a great degree of readability in a familiar environment for a verification team currently
using a directed approach. In a procedural approach, randomization order (determined by order of code) and relative
weights (frequency of one item being picked vs another) can be used to accomplish many useful test cases. A
declarative approach allows constraints on multiple items can be randomized simultaneously and, hence, gives a
1
uniform distribution across an entire transaction. Using OO in a declarative approach allows one to either build on or
remove existing constraints – hence, new tests can be generated with minimal changes.
2. Design of Randomization Language Features
In order for VHDL randomization features to be compatible with existing methodologies as much as possible will be
leveraged from other verification languages including SystemVerilog. As we do this, features can be either a direct
translation with minimal changes, or they can be adapted some to better suit VHDL. It is my intent to consider both
options.
Since there are candidates for the syntax to be considered, examples will be provided. Syntax productions will be
added once we agree on syntax.
3. Basic Randomization
The intent of basic randomization is to provide the occasional single random value. While it can be used for
randomizing transactions, using class-based randomization is more effective at expressing constraint relationships
between multiple items.
3.1. Baseline
Randomization uses a seed as the basis for generating the next value. To avoid maintaining the seed externally, the
seed and randomization functions can be encapsulated in a class (note don’t confuse this with class-based
randomization which is presented later).
Package RandomPkg is
type SeedType is record
seed1 : positive ;
seed2 : positive ;
end record SeedType ;
type RandClass is class
variable Seed : SeedType := (7, 1) ;
procedure seed_random (A : SeedType ) ;
function seed_random return SeedType ;
impure function RandReal return real ;
impure function RandReal(Max: Real) return real ; -- 0.0 to Max
impure function RandReal(Min : Real; Max: Real) return real ;
impure function RandInt (Max: Integer) return integer ; -- 0 to Max
impure function RandInt (Min : Integer; Max: Integer) return integer ;
impure function RandSlv (Len: integer) -- 0 to 2**Len - 1
return std_logic_vector ;
impure function RandSlv (Max: Natural; Len: integer) -- 0 to Max
return std_logic_vector ;
impure function RandSlv (Min : Natural; Max: Natural; Len: integer)
return std_logic_vector ;
impure function RandUnsigned (Len: integer) -- 0 to 2**Len - 1
return Unsigned ;
impure function RandUnsigned (Max: Natural; Len: integer) -- 0 to Max
return Unsigned ;
impure function RandUnsigned (Min : Natural; Max: Natural; Len: integer)
return Unsigned ;
impure function RandSigned (Len: integer) -- -2**(Len-1) to 2**(Len-1) - 1
return Signed ;
impure function RandSigned (Max: Integer; Len: integer) -- 0 to Max
return Signed ;
impure function RandSigned(Min : Integer; Max: Integer; Len: integer)
return Signed ;
end class RandClass;
end package RandPkg ;
2
Value based distributions can also be handled in a similar fashion, however, in section Procedural Randomization,
we will see that it can be more effectively handled with syntax.
All randomization functions call RandReal for basic randomization. RandReal returns a value between 0.0 and 1.0
(same as ieee.math_real.uniform) and the other functions scale this value to the appropriate range. By extending
RandClass and overloading RandReal, different distributions can be generated for all types.
type ExtRandClass extends RandClass is class body
impure function RandReal return real is
begin
return poisson(super.RandReal) ;
end function RandReal ;
end class body ExtRandClass;
3.2. Tradeoff: Randomize
Name all random functions randomize instead of RandReal, RandInt, RandSlv, RandUnsigned, and RandSigned.
3.3. Tradeoff: Types ufixed, sfixed, and float
How do we handle types ufixed, sfixed, and float? Although they are generic types, the generic values associated
with them do not impact the value itself. Instead they impact things when operators are used (such as rounding, …).
3.4. Tradeoff: Visability
SystemVerilog provides $urandom and $urandom_range to randomize integer values. These functions have access
to a seed and are thread stable, hence, they are somewhat of an implicit class. The class is associated with a thread
and its methods are accessed with function call notation rather than class notation.
In VHDL a variable of type RandClass would need to be created and then its methods would need to be accessed
using class method call notation. To be like SystemVerilog, each process would need to implicitly create a variable
of type RandClass and calls to method of RandClass would need to be permitted without referencing the variable
name. SystemVerilog uses this type of notion already for Procedural Randomization, VHDL will need to do
something similar.
4. Class Based Randomization
4.1. Specifying Random Variables to Randomize
4.1.1. Baseline
A class is used to bundle items together such that relationships between them can be expressed. SystemVerilog uses
public class variables and marks them with either randc or rand if they are to be randomized by default. Translating
this into VHDL:
Type CpuOpType is (CpuRead, CpuWrite, CpuIntAck) ;
Type CpuOpGen is class
Rand Variable CpuOp : CpuOpType ;
Rand Variable Addr : std_logic_vector(21 downto 0);
Rand Variable Data : std_logic_vector(15 downto 0) ;
End class CpuOpGen ;
4.1.2. Tradeoff: Randc and Rand
Some how class state variables (ones not part of randomization) need to be differentiated from random class
variables. Randc and rand are as good as a methodology as any. Alternately, these could be done solely with
attributes.
Type CpuOpType is (CpuRead, CpuWrite, CpuIntAck) ;
Type CpuOpGen is class
Variable CpuOp : CpuOpType ;
Attribute Rand of CpuOp is true ;
3
Variable Addr : std_logic_vector(21 downto 0) ;
Attribute Rand of Addr is true ;
Variable Data : std_logic_vector(15 downto 0) ;
Attribute Rand of Data is true ;
End class CpuOpGen ;
To meet other needs of randomization, it would help if the attribute value assigned in a class could be overridden by
a specification/assignment outside of the class. Also a shorter notation or a default specification in the variable
declaration would be helpful. Perhaps that is how the “Rand Variable CpuOp : CpuOpType;” should be viewed?
4.2. Types to Randomize
4.2.1. Baseline
SystemVerilog requires random class variables to integral types. In VHDL, minimally this should include the types
(user defined enumerated types, boolean, bit, bit_vector, std_ulogic, std_logic, std_logic_vector, std_ulogic_vector,
unsigned, signed, and integer). For bit types (std_ulogic and std_logic) and arrays of bit types, values generated
shall be limited to ‘0’ and ‘1’ and constraints based on values other than ‘0’ and ‘1 are illegal and shall be an error.
For ordering purposes, array types without a numeric representation (bit_vector, std_logic_vector, and
std_ulogic_vector) shall be treated as if they are unsigned.
4.2.2. Enhancement: Randomizing Real
The procedure ieee.math_real.uniform already supports randomization of real numbers. There does not seem to be
any reason to limit usage to integral numbers – other than perhaps loosing the notion of how many bits are in the
representation.
Given the extension to real, it seems logical to also support types ieee.<generic_fixed_pkg_instance>.sfixed,
ieee.<generic_fixed_pkg_instance>.ufixed, and ieee.<generic_float_pkg_instance>.float. As already pointed out,
the generics do not affect the value represented by the type.
4.3. Randomizing Class Objects
4.3.1. Baseline
In SystemVerilog, objects are randomized using the built-in randomize class pseudo-method. It uses method call
syntax (a function returning integer), but has arguments that are beyond what is representable in SV and is not
overloadable. This Randomize also has extended syntax that allows a single additional constraint to be specified.
The same format can be used for VHDL with the method returning false when it fails:
<class_identifier>.randomize [([<variable_list>|null])] with constraint_block ;
If the variable_list is specified, only the variables specified in it are randomized (including ones not marked randc or
rand). The constraint_block allows additional constraints to be specified. To work around randomize not being
overloadable, overloadable methods (procedures) for pre_randomize and post_randomize are provided. The
randomization is seeded with the srandom method. External to the class, each variable and constraint may be turned
off in mass or individually using methods rand_mode and constraint_mode respectively.
4.3.2. Tradeoff: Randomize Return Success/Failure
Returning a success/failure value complicates the use model. Each call to randomize must handle the return value.
Instead of having a return value, the predefined method, named error_handler, shall be called when an error in
randomization occurs. Error_handler is overloadable and has a default implementation that prints randomization
failed and the name of the class variable for which it failed.
4
4.3.3. Tradeoff: Enabling Randomization and Constraints
The implication of rand_mode and constraint_mode is that for each random variable and for each constraint there is
an implied variable that controls whether it is enabled or disabled. VHDL uses attributes to address situations like
this.
Attribute Rand of class_variable is true ;
Class_variable’rand is true ;
4.3.4. Tradeoff: Srandom is ill Named.
It is not obvious that srandom is the seed method. Based on names it is difficult to distinguish srandom from
urandom. It would be better if the seed initialization method for randomize included the word seed., for example,
seed_random or init_seed.
4.3.5. Tradeoff: Randomize Is Not Overloadable
If randomize were overloadable, methods pre_randomize and post_randomize would not be needed. To do this,
some how the current variable list and constraint block would need to be replaced by a subprogram generic or
parameter. The object could be either a constraint block or an anonymous in-line extension of the class. If the
object is a constraint block, the statements that enable/disable variable randomization would need to be expressible
in the constraint block.
Expressed in an overloadable form:
<class_identifier>.randomize (anonymous class extension) ;
<class_identifier>.randomize (constraint_block) ;
Neither of these seem quite right – it might be better to stick with the pseudo-method model.
4.3.6. Tradeoff: Randomize Does Not Return a Randomized Value
Randomize does not return a randomized value. Instead an application accesses the class variables that have been
randomized to gain access. If we view a class as a structure + methods, then this seems reasonable as then the entire
class itself can be passed as a transaction value.
Shared Variable CpuOpTrans : CpuOpGen ;
. . .
CpuOpTrans.randomize ;
Scoreboard.put(CpuOpTrans) ;
TransactionIF.put(CpuOpTrans) ;
4.3.7. Conclusions
While there are merits to doing an exact syntax sugaring of SystemVerilog, it is also important to keep consistent
with the nature of VHDL.
If we don’t do a direct VHDL’ization of SystemVerilog, I would at least address the following issues:
Make Randomize a pseudo-procedure and provide an overloadable error_handler method.
Enable randomization and constraints with attributes, but only if we also allow attributes to be specified
as a statement as well as a declaration.
Put “seed” in the name of the method that specifies the seed value (seed_random, init_seed, …)
4.4. Format of Class Based Constraints
4.4.1. Baseline
Constraints are specified in both the class and the randomize pseudo-call. The following shows constraints specified
in a class:
Type CpuOpType is (CpuRead, CpuWrite, CpuIntAck) ;
Type CpuOpGen is class
Rand Variable CpuOp : CpuOpType ;
Rand Variable Addr : std_logic_vector(21 downto 0);
5
Zgłoś jeśli naruszono regulamin