• 沒有找到結果。

tag is 0 for Invalid, 1 for Valid

8.25 Parameterized classes

It is often useful to define a generic class whose objects can be instantiated to have different array sizes or data types. This avoids writing similar code for each size or type and allows a single specification to be used for objects that are fundamentally different and (like a templated class in C++) not interchangeable.

The SystemVerilog parameter mechanism is used to parameterize a class:

class vector #(int size = 1);

bit [size-1:0] a;

endclass

Instances of this class can then be instantiated like modules or interfaces:

vector #(10) vten; // object with vector of size 10 vector #(.size(2)) vtwo; // object with vector of size 2 typedef vector#(4) Vfour; // Class with vector of size 4 This feature is particularly useful when using types as parameters:

class stack #(type T = int);

local T items[];

task push( T a ); ... endtask task pop( ref T a ); ... endtask endclass

The preceding class defines a generic stack class, which can be instantiated with any arbitrary type:

stack is; // default: a stack of ints

stack#(bit[1:10]) bs; // a stack of 10-bit vector stack#(real) rs; // a stack of real numbers

Any type can be supplied as a parameter, including a user-defined type such as a class or struct. The combination of a generic class and the actual parameter values is called a specialization. Each specialization of a class has a separate set of static member variables (this is consistent with C++

templated classes). To share static member variables among several class specializations, they shall be placed in a nonparameterized base class.

class vector #(int size = 1);

bit [size-1:0] a;

static int count = 0;

function void disp_count();

$display( "count: %d of size %d", count, size );

endfunction endclass

The variable count in the preceding example can only be accessed by the corresponding disp_count method. Each specialization of the class vector has its own unique copy of count.

A specialization is the combination of a specific generic class with a unique set of parameters. Two sets of parameters shall be unique unless all parameters are the same, as defined by the following rules:

a) A parameter is a type parameter and the two types are matching types.

b) A parameter is a value parameter and both their type and their value are the same.

All matching specializations of a particular generic class shall represent the same type. The set of matching specializations of a generic class is defined by the context of the class declaration. Because generic classes in a package are visible throughout the system, all matching specializations of a package generic class are the same type. In other contexts, such as modules or programs, each instance of the scope containing the generic class declaration creates a unique generic class, thus defining a new set of matching specializations.

A generic class is not a type; only a concrete specialization represents a type. In the preceding example, the class vector becomes a concrete type only when it has had parameters applied to it, for example:

VERIFICATION LANGUAGE

typedef vector my_vector; // use default size of 1

vector#(6) vx; // use size 6

To avoid having to repeat the specialization either in the declaration or to create parameters of that type, a typedef should be used:

typedef vector#(4) Vfour;

typedef stack#(Vfour) Stack4;

Stack4 s1, s2; // declare objects of type Stack4 A parameterized class can extend another parameterized class. For example:

class C #(type T = bit); ... endclass // base class

class D1 #(type P = real) extends C; // T is bit (the default) class D2 #(type P = real) extends C #(integer); // T is integer

class D3 #(type P = real) extends C #(P); // T is P

class D4 #(type P = C#(real)) extends P; // for default T is real Class D1 extends the base class C using the base class’s default type (bit) parameter. Class D2 extends the base class C using an integer parameter. Class D3 extends the base class C using the parameterized type (P) with which the extended class is parameterized. Class D4 extends the base class specified by the type parameter P.

When a type parameter or typedef name is used as a base class, as in class D4 above, the name shall resolve to a class type after elaboration.

The default specialization of a parameterized class is the specialization of the parameterized class with an empty parameter override list. For a parameterized class C, the default specialization is C#(). Other than as the prefix of the scope resolution operator, use of the unadorned name of a parameterized class shall denote the default specialization of the class. Not all parameterized classes have a default specialization since it is legal for a class to not provide parameter defaults. In that case all specializations shall override at least those parameters with no defaults.

Example:

class C #(int p = 1);

...

endclass

class D #(int p);

...

endclass

C obj; // legal; equivalent to "C#() obj";

D obj; // illegal; D has no default specialization 8.25.1 Class resolution operator for parameterized classes

Use of the class resolution operator with a prefix that is the unadorned name of a parameterized class (see 8.25) shall be restricted to use within the scope of the named parameterized class and within its out-of-block declarations (see 8.24). In such cases, the unadorned name of the parameterized class does not denote the default specialization but is used to unambiguously refer to members of the parameterized class. When referring to the default specialization as the prefix to the class resolution operator, the explicit default specialization form of #() shall be used.

Outside the context of a parameterized class or its out-of-block declarations, the class resolution operator may be used to access any of the class parameters. In such a context, the explicit specialization form shall be used; the unadorned name of the parameterized class shall be illegal. The explicit specialization form may denote a specific parameter or the default specialization form. The class resolution operator may access value as well as type parameters that are either local or parameters to the class.

Example:

class C #(int p = 1);

parameter int q = 5; // local parameter static task t;

int p;

int x = C::p; // C::p disambiguates p

// C::p is not p in the default specialization endtask

endclass

int x = C::p; // illegal; C:: is not permitted in this context int y = C#()::p; // legal; refers to parameter p in the default

// specialization of C

typedef C T; // T is a default specialization, not an alias to // the name "C"

int z = T::p; // legal; T::p refers to p in the default specialization int v = C#(3)::p; // legal; parameter p in the specialization of C#(3) int w = C#()::q; // legal; refers to the local parameter

T obj = new();

int u = obj.q; // legal; refers to the local parameter

bit arr[obj.q]; // illegal: local parameter is not a constant expression In the context of a parameterized class method out-of-block declaration, use of the class scope resolution operator shall be a reference to the name as though it was made inside the parameterized class; no specialization is implied.

Example:

class C #(int p = 1, type T = int);

extern static function T f();

endclass

function C::T C::f();

return p + C::p;

endfunction

initial $display(“%0d %0d”, C#()::f(),C#(5)::f()); // output is "2 10"