当前位置: 首页 > 工具软件 > Classp > 使用案例 >

SystemVerilog——class类

楚知
2023-12-01

目录

1. 介绍

2. 类的定义

3.类作用域操作符::

4. 参数化类

4.1 参数化类中类作用域操作符的使用

5. Typedef class


1. 介绍

本文章主要介绍关于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
  • 可以通过声明一个class类型的变量来定义一个对象(object)。

eg:

Packet     p;//Declare a variable of class Packet

p = new();      //Initialize variable to a new allocated object of the class Packet

 注:未初始化对象句柄的默认值为null,可以通过比较对象句柄是否等于null来判断对象是否被初始化。

3.类作用域操作符::

可以通过类作用域操作符::用类名去访问类中定义的属性,它的语法为:

class_type::{class_type:: }  identifier

其中class_type可以是以下几种类型

  • class类型名字;
  • package类型名字;
  • typedef名字;
  • covergroup类型名字;
  • coverpoint名字;
  • cross名字;
  • 类型参数。

注:在SystemVerilog中,类作用域操作符::可以应用到类所有的静态(static)成员(属性和方法)、typedef、枚举、参数、local参数、约束、结构体、unions以及嵌套类上。

eg:

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方法和属性。包含类的静态成员,嵌套类可以直接访问,也可以通过::访问。

eg:

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关键词定义的数据类型。

eg:

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的变量,例如两个类彼此需要对方的对象句柄

eg:

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

 类似资料: