SystemVerilog中的类和对象

1、类和对象

  • 类是将相同的个体抽象出来的描述方式,对象时实体,具备有独立行为的能力。
  • 具有相同属性和功能的对象属于同一类,而不同的类之间可能有联系或者没有联系。
  • C语言中,编程基于过程方法,在Verilog中提供了笨拙的类对象编程可能性,即在module中定义方法,而后调用module实例中的方法。
  • Verilog的module+method的方式与SV的class定义有本质上的差别,即面向对象编程的三要素:封装、继承、多态。
  • 类的定义核心即是属性声明和方法定义,所以类是数据和方法的自洽体,即可以保存数据和处理数据。这是与struct结构体在数据保存方面的重要区别,因为结构体只是单纯的数据集合,而类可以对数据做出符合需要的处理。

2、验证使用OOP的意义

  • 验证环境的不同组件功能和所需要处理的数据内容是不相同的。
  • 不同环境同一类型的组件其所具备的功能和数据内容是相似的。
  • 基于以上两点,验证世界的各个组件角色明确、功能分立,使用面向对象编程与验证世界的构建原则十分符合。

3、OOP的概念要素

  • Class类:基本模块包括成员变量和方法。在Verilog中module也可以包含变量和方法,只不过它是“硬件盒子”,class是“软件盒子”。
  • Object对象:类的实例。Verilog中module也可以例化,这是“硬件”例化,在SV中可以使用class来例化,这是“软件”的例化。
  • Handle句柄(指针):用来指向对象的指针。在Verilog中,可以通过层次化的索引来找到结构中的设计实例,而在SV的对象索引时,需要通过句柄来索引对象的变量和方法。
  • Property属性(变量):在类中声明的存储数据的变量。在Verilog中,它可以是wire或者reg类型。
  • Method方法:类中可以使用task或者function来定义方法以便处理自身或者外部传入的数据。Verilog中可以在module中定义task/function,也可以使用initial/always处理数据。

4、创建对象

Verilog的例化和SV的class例化的差别:

  • 二者的共同点在于使用相同的“模板”来创建内存实例
  • 不同点在于Verilog的例化是静态的,即在编译链接时完成,而SV中class例化是动态的,可以在任意时间点发生
  • Verilog中没有句柄的概念,即只能通过层次化的索引方式A.B.sigx,而SV中的class通过句柄可以将对象的指针赋予其它句柄,使得操作更加灵活。

在创建对象时,需要注意什么是声明,什么是创建

Transaction tr;		//声明句柄
tr = new();			//创建对象

创建对象时,可以通过自定义的构建函数来完成变量的初始化和其它初始操作。构建函数new()是系统预定义函数,不需要指定返回值,函数会隐式地返回例化后的对象指针。

class Transaction;
	logic[31:0] addr, crc, data[8];
	function new();
		addr = 3;
		foreach(data[i])
			data[i] = 5;
		endfunction
enclass

构建函数也可以定义多个参数作为初始化时外部传入数值的手段。

class Transaction;
	logic[31:0] addr = 'h10;
	logic[31:0] 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);

5、句柄的传递

对象是指的存储空间,而句柄指的是空间指针。也就是说在创建了对象之后,该对象的空间位置不会改变,而指向该空间的句柄可以有多个。

Transaction t1, t2;		//声明句柄
t1 = new();				//例化对象,将其句柄赋予t1
t2 = t1;				//将t1的值赋予t2,即t1和t2指向同一个对象
t1 = new();				//例化第二个对象,并将其句柄赋予t1

在这里插入图片描述

6、对象的销毁

  • 软件编程的灵活在于可以动态地开辟使用空间,在资源闲置或者不再需要时,可以回收空间,这样使得内存空间保持在一个合理的区间。
  • C++语言中的类除了有构建函数,还有析构函数。析构函数的作用即在于手动释放空间,但这对编程人员的细心和经验提出了要求;JAVA和Python等后续面向对象语言则不再需要手动定义析构函数并且释放空间,空间的回收利用也是自动的。
  • SV中也采用了自动回收空间的处理方式,自动回收空间的基本原理是,当一个对象,在整个程序中没有任何一个地方再“需要”它时,便会被“销毁”。这里的“需要”的意思指的是有句柄指向该对象。

7、句柄的使用

  • 句柄可以用来创建多个对象,也可以前后指向不同对象。
Transaction t1, t2;		//声明句柄
t1 = new();				//创建对象并将其指针赋予t1
t2 = new();				//创建对象并将其指针赋予t2
t1 = t2;				//将t2的值赋予t1,t1和t2指向同一对象,t1之前指向的对象被释放
t2 = null;				//将t2赋值为空,此时指针悬空,悬空的指针很危险
  • 可以通过句柄来使用对象中的成员变量或者成员方法。
Transaction t;
t = new();
t.addr = 32'h42;
t.display();

8、静态变量

  • 与硬件域例如module、interface不同的是,在class中声明的变量其默认为类型为动态变量,即其声明周期在仿真开始后的某时间点开始到某时间点结束。
  • 使用关键字static来声明class内的变量时,则其为静态变量。静态变量的生命周期开始于编译阶段,贯穿于整个仿真阶段。
  • 如果在类中声明了静态变量,可以直接引用该变量class::var,或者通过例化对象引用object.var。类中的静态变量声明以后,无论例化多少个对象,只可以共享一个同名的静态变量。

9、静态方法

  • 在class中定义的方法默认类型是动态方法,也可以通过关键字static修改为静态方法。
  • 静态方法内可以声明并使用动态变量,但是不能使用类的动态成员变量。原因是因为在调用静态方法时,可能并没有创建具体的对象,也因此没有为动态成员变量开辟空间,因此在静态方法中使用类的动态成员变量是禁止的,可能会造成内存泄漏,但是静态方法可以使用类的静态变量,因为静态方法同静态变量一样在编译阶段就已经分配了内存空间。
  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值