Systemverilog类

 1、什么是类(Class)

        类封装了数据和操作这些数据的子程序。

2 、在哪里定义类

        在SystemVerilog中,可以把类定义在program、module、package中,或者在这些块之外的任何地方。类可以在程序和模块中使用。

3 、OOP术语

        类(Class):包含变量和子程序的基本构件块。
        对象(Object):类的一个实例。
        句柄(Handle):指向对象的指针。
        属性(Property)
        方法(Method)
        原型(Prototype):程序的头,包括程序名、返回类型和参数列表。程序体包含了执行代码。

4、创建新对象——构造函数

4.1、对象的创建过程:

Transaction tr;   //声明一个句柄。在声明一个句柄时,它被初始化为特殊值null
Tr=new();         //new函数为Transaction分配空间,将变量初始化为默认值
                  //(二值变量为0,四值变量为X),并返回保存对象的地址。

4.2、定制构造函数(Constructor)

        new函数也成为构造函数,因为它创建对象构造函数除了分配内存外,它还初始化变量。可以通过自定义new函数修改变量的默认数值。但是new函数不能有返回值,因为构造函数总是返回一个指向对象的句柄,其类型就是类本身

//简单用户定义的new()函数
class Transaction;
    logic[31:0] addr,crc,data[8];
 
    function new;
        addr=3;
        foreach(data[i]) 
            data[i]=5;
    endfunction
endclass
//addr和crc被设为固定数值,但crc仍然被初始化为默认值X

4.3、可以使用具有默认值的函数参数来创建更加灵活的构造函数:

//一个带有参数的new()函数
class Transaction;
    logic[31:0]addr,crc,data[8];
 
    function new(logic[31:0] a=3,d=5);
        addr = a;
        foreach(data[i])
            data[i]=d;
    endfunction
endclass
 
initial begin
    Transaction tr;
    tr=new(10);     //data使用默认值5
end

        每一个类都有自己的new函数,在调用new函数时,SystemVerilog通过赋值操作符左边的句柄类型来决定使用哪个new函数

class Transaction;
    ...
endclass:Transaction
 
class Driver;
    Transaction tr;
    function new();   //Driver的new函数
        tr=new();     //调用Transaction的new函数
    endfunction;
endclass:Driver

注意:应该避免在声明一个句柄的时候调用构造函数,即new函数。这样构造函数在第一条声明语句前就被调用了,初始化的顺序便不能被控制了

5、静态变量和全局变量

        每个对象都有自己的局部变量,这些变量不和任何其他对象共享。但有时候你需要一个某种类型的变量,被所有对象所共享,此时就需要静态变量(如果没有OOP,可能需要创建一个全局变量)。

        当你打算创建一个全局变量的时候,首先应该考虑创建一个类的静态变量。一个类应该是自给自足的,对外部的引用越少越好。

        静态变量:在SystemVerilog中,可以在类中创建一个静态变量。该变量将被这个类的所有实例所共享,并且它的使用范围仅限于这个类

//以下是一个含有静态变量的类
class Transcation;
    static int count=0; // 使用static关键字声明一个int类型的静态变量
    int id;
    funtion new();
        id=count++;
    endfunction
endclass
 
Transaction t1,t2;
initial begin
    t1=new();
    t2=new();
    $display("Second id=%d,count=%d",t2.id,t2.count);
end

静态变量可以累积,动态变量离开函数后自动清空

5.2、访问静态变量有以下两种方法

// 方法1:使用句柄访问静态变量
tr.StaticVariable
// 方法2:使用 类名+作用域符“:”
Transcation::StaticVariable 

5.3、静态变量的初始化

        静态变量通常在声明时初始化。不能简单地在类的构造函数中初始化静态变量,因为每一个新的对象都会调用构造函数

5.4、静态方法

        在SystemVerilog中,可以在类中创建一个静态方法用于读写静态变量,甚至可以在第一个实例产生之前读写静态变量。SystemVerilog不允许静态方法读写非静态变量,例如id。     

class Transaction;
    static Config cfg;
    static int count=0;
    int id;
 
    //显示静态变量的静态方法
    static function void display_statics();
        $display("Transcation cfg.mode=%s,count=%0d",cfg.mode.name(),count);
    endfunction
endclass
 
Config cfg;
 
initial begin
    cfg=new(MODE_ON);
    Transaction::cfg=cfg;
    Transaction::display_statics(); //调用静态方法
end

6、类的成员

        一个类的功能应该尽可能简单,不应该承担过多的责任,也不应该承担不符合它的职责。类作为载体,不会将成员变量直接暴露给外部,通过public,protected,local关键词来设置成员变量方法的外部权限访问。

        在SystemVerilog中,所有成员都是公有的,除非标记为local或者protected。你应该尽量使用默认值,以保证对DUT行为的最大程度控制,这比软件的长期稳定性更加重要。
        Public:(SystemVerilog默认类型)子类和外部类型均可以访问成员。
        Protected:只有子类可以访问成员,外部访问是非法的。
        Local:只有该类可以访问,子类和外部都不能。

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