2. 类的定义
在SystemVerilog中,class也是一种类型(type),可以把类定义在program、module、package中,或者在这些块之外的任何地方定义。类可以在程序或者模块中使用。
类可以被声明成一个参数(方向可以是input、output、inout或者ref),此时被拷贝的是这个对象的句柄,而不是这个对象的内容。
class Packet;
//data or class properties
bit [3:0] command;
bit [40:0] address;
bit [4:0] master_id;
integer time_requested;
integer time_issued;
integer status;
typedef enum { ERR_OVERFLOW= 10, ERR_UNDERFLOW = 1123} PCKT_TYPE;
const integer buffer_size = 100;
const integer header_size;
// initialization
function new();
command = 4'd0;
address = 41'b0;
master_id = 5'bx;
header_size = 10;
endfunction
// methods
// public access entry points
task clean();
command = 0;
address = 0;
master_id = 5'bx;
endtask
task issue_request( int delay );
// send request to bus
endtask
function integer current_status();
current_status = status;
endfunction
endclass
注:未初始化对象句柄的默认值为null,可以通过比较对象句柄是否等于null来判断对象是否被初始化。
3.类作用域操作符::
可以通过类作用域操作符**::**用类名去访问类中定义的属性,它的语法为:
class_type::{class_type:: } identifier
其中class_type可以是以下几种类型
class类型名字;
package类型名字;
typedef名字;
covergroup类型名字;
coverpoint名字;
cross名字;
类型参数。
注:在SystemVerilog中,类作用域操作符::可以应用到类所有的静态(static)成员(属性和方法)、typedef、枚举、参数、local参数、约束、结构体、unions以及嵌套类上。
class Base;
typedef enum {bin,oct,dec,hex} radix;
static task print( radix r, integer n );
$display("r == %0d,n == %0d",r,n);
endtask
endclass
Base b = new();
int bin = 123;
b.print(Base::bin, bin); // Base::bin and bin are different
Base::print(Base::hex, 66);
// 类作用域操作符::应用到嵌套类上
class StringList;
class Node; // Nested class for a node in a linked list.
string name;
Node link;
endclass
endclass
class StringTree;
class Node; // Nested class for a node in a binary tree.
string name;
Node left, right;
endclass
endclass
// StringList::Node is different from StringTree::Node
注:StringList::Node不同于StringTree::Node。
类作用域操作符支持以下操作
从类层次结构之外访问类的静态公共成员(methods和类属性);
从派生类里面访问父类的public或protected成员;
从次结构之外或者派类外层生类里面访问在类中声明的约束块、type声明以及枚举常量;
从类外层次结构之外或者派生类里面访问在类中声明参数或者local参数。
嵌套类可以访问包含类中的local和protected成员 。嵌套类不能隐式访问包含类 中的non-static方法和属性。包含类的静态成员,嵌套类可以直接访问,也可以通过**::**访问。
class Outer;
int outerProp;
local int outerLocalProp;
static int outerStaticProp;
static local int outerLocalStaticProp;
class Inner;
function void innerMethod(Outer h);
outerStaticProp = 0;//Legal, same as Outer::outerStaticProp
outerLocalStaticProp = 0;//Legal, nested classes may access local's in outer class
outerProp = 0;//Illegal, Nested class can't implicit access to non-static outer
h.outerProp = 0;//Legal, qualified access.
h.outerLocalProp = 0;//Legal, qualified access and locals to outer class allowed.
endfunction
endclass
endclass
4. 参数化类
参数化类声明例化对象时可以设置不同的数组大小 或者数据类型(type) 。参数化类的参数可以是一个变量、也可以是type关键词定义的数据类型。
class vector #(int size = 1);//参数是一个变量
bit [size-1:0] a;
endclass
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
class stack #(type T = int);//参数是一个数据类型
local T items[];
task push( T a ); ... endtask
task pop( ref T a ); ... endtask
endclass
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
注:任何类型(type)都可以作为一个参数,包括user定义的class或者struct等类型(type)。
-
一个参数化类可以被扩展成其他参数化累,例如:
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
4.1 参数化类中类作用域操作符的使用
-
当缺省参数化类作为类解析操作符前缀时,应该显式的使用#()。例如
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
参数化类使用extern关键在在类外声明方法。
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"
5. Typedef class
有时候我们需要在class自身被定义之前去声明一个这个class的变量,例如两个类彼此需要对方的对象句柄。
typedef class C2; // C2 is declared to be of type class class C1; C2 c; endclass class C2; C1 c; endclass
注:typedef class C2中class关键词可以省略,即typedef C2。
//forward class的声明和实际class的定义应该在同一个scope中,而且forward class的声明不用看实际class是否为参数化类。