在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是否为参数化类。