SV学习小记(3) class


一、类和对象的概述

在IC验证中,为什么要用OOP(面向对象编程)呢?
我们知道,验证结构分为以下四个部分:

  • 激励生成器(stimulate)
  • 驱动器(driver)
  • 监测器(monitor)
  • 比较器(checker)
    验证环境不同组件其功能和所需要的处理的数据内容是不相同的,因为在不同的环境可能会使用到同一种类型的组件,所以使用OOP的话,会使得验证工作更加方便。

创建第一个transaction类

class Transaction;
  bit [31:0] addr, crc, data[8];
  
  function void display;
    $display("Transaction: %h", addr);
  endfunction:display

  function void calc_crc;
    crc = addr^data.xor;
  endfunction:calc_crc

endclass:Transaction

在class中,不能定义硬件类型的变量,例如wire 与 reg 都是不可以的,c软件世界中只能定义软件变量。(动态的)在class中所有的变量都默认是动态的,与module不同,在module中所有的变量默认是静态的。那么,接口作为软硬件之间的唯一 媒介,其指针是可以传递到class中的,class可以通过接口来获得硬件世界的信号!

二、一些概念

  • Class类:基本模块包含成员变量和方法。在Verilog的module中也可以这样,但是module是硬件,而class是软件的。
  • Object对象:类的实例。
  • Handle句柄:其实就是用来指向对象的指针。
  • Property属性:就是类的变量
  • Method方法:在类中的function与task。但是在类中不能存在initial与always

三、创建对象

注意,Verilog的例化与SV中class的例化的区别!!!!!!

  • Verilog的例化是静态的,在编译链接的时候完成,SV class是动态的,在仿真开始后,才能创建。
  • Verilog中是没有句柄的概念的,只能通过层次化的索引方式。而SV class是通过句柄空压机将对象的指针赋予其他句柄。
Transaction tr;//声明变量
tr = new();//创建对象
  • 创建对象是开辟了新的内存空间,用来存放新的成员变量和方法的
  • 与C++一样,SV也可以定义自己的构造函数,其格式如下
  function new(); // new()在定义的时候不需要有返回值
    addr = 3;
    foreach (data[i])
      data[i] = 5;
  endfunction
  • 在写构造函数的时候,也可以自己添加多个参数,作为初始化的值。如下:
class Transaction;
  bit [31:0] addr, crc, data[8];

  function new(logic [31:0] a = 3, d = 5);
    addr = a;
    foreach (data[i])
      data[i] = d;
  endfunction

  function void display;
    $display("Transaction: %h", addr);
  endfunction:display

  function void calc_crc;
    crc = addr^data.xor;
  endfunction:calc_crc

endclass:Transaction

initial begin
  Transaction tr;
  tr = new(10);
end

在这种情况下,addr的值就会成为传递的参数10,而不是默认的3,但是data里面的值,则都是默认参数的值5。

四、句柄的使用

  • 看如下代码,来理解句柄的使用
  Transaction t1, t2; //声明句柄t1,t2
  t1 = new();         //例化对象,将其句柄赋予t1
  t2 = t1;            //将t1的值赋给t2,即就是t1与t2指向同一个对象
  t1 = new();         //例化第二个对象,并将其句柄赋予t1

如下列图:
当
当执行到t2 = t1; 这条语句的时候,其存储情况如上图所示
在这里插入图片描述
当执行完的时候,其结果如上图所示

四、销毁对象

  • 在SV中,不会像C和C++一样需要自己时刻关注内存空间,并且防止内存泄漏的情况。在SV中,不需要自己去写析构函数,SV与Java和Python一样,是自动回收空间。
  • 在SV中,当一个对象,在整个程序中没有任何一个句柄(及就是该对象类型的指针)指向这个对象的时候,那么,这个对象所在的空间就被free掉了。
Transaction t1, t2; //声明句柄t1,t2
t1 = new();
t2 = new();
t1 = t2;  // 将t2赋值予t1,t1和t2指向同一对象,t1之前指向的对象被释放 
t2 = null;// 将t2的值赋为空
t1.addr = 32'h42; //可以使用句柄来使用对象中的成员变量或者方法
t1.display();

五、静态变量以及静态方法

静态变量

  • 使用关键字static
  • 静态变量是在编译阶段就存在了,贯穿于整个仿真阶段
  • 如果在类中声明的静态变量,则可以使用类名直接去引用该变量,甚至不需要创建对象。class::var。当然通过例化的对象来引用也是可以的。
  • 类中的静态变量,是所有该类型的对象所共享的。不管例化多少对象,都共享这一个静态变量。
class Transaction;
  static int count =  0;
  int id;
  bit [31:0] addr, crc, data[8];

  function new(logic [31:0] a = 3, d = 5);
    id = count++;
    addr = a;
    foreach (data[i])
      data[i] = d;
  endfunction

  function void display;
    $display("Transaction: %h", addr);
  endfunction:display

  function void calc_crc;
    crc = addr^data.xor;
  endfunction:calc_crc

endclass:Transaction

Tramsaction tr1, tr2;
initial begin
  tr1 = new(); // 1st instance, id = 0, count = 1
  tr2 = new(); // 2nd instance, id = 1, count = 2
  $display("Second id=%d, count=%d", tr2.id, tr2.count);
end

静态方法

  • 在class中,其方法默认也是动态的,但是加上static就成了静态方法
  • 静态方法内部也可以声明并使用动态变量,但是不能使用在该方法外部声明的动态变量。因为在调用静态方法的时候,可能并没有创建具体的对象,也因此没有为动态成员变量开辟空间,所以在静态方法中,使用类的动态成员变量是禁止的。
  • 静态方法也可以使用静态变量。
  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值