Systemverilog类

1 什么是类(Class)

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

2 在哪里定义类

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

3 OOP术语

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

创建新对象——构造函数

对象的创建过程:

Transaction tr;   //声明一个句柄。在声明一个句柄时,它被初始化为特殊值null

Tr=new();         //new函数为Transaction分配空间,将变量初始化为默认值
                  //(二值变量为0,四值变量为X),并返回保存对象的地址。

定制构造函数(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

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

//一个带有参数的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函数。这样构造函数在第一条声明语句前就被调用了,初始化的顺序便不能被控制了。

静态变量和全局变量

每个对象都有自己的局部变量,这些变量不和任何其他对象共享。但有时候你需要一个某种类型的变量,被所有对象所共享,此时就需要静态变量(如果没有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

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

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

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

静态变量的初始化

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

静态方法

在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

类的成员

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

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

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值