在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来判断对象是否被初始化。
可以通过类作用域操作符::用类名去访问类中定义的属性,它的语法为:
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
参数化类声明例化对象时可以设置不同的数组大小或者数据类型(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
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"
有时候我们需要在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是否为参数化类。