SystemVerilog——class类

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

你可能感兴趣的:(Systemverilog,Systemverilog)