【数字IC前端】学习随笔(3)——类/对象/继承/句柄


复习整理下。安利下 路科验证。

类和对象的概述

类和对象

  • 对象编程语言更符合人对自然的理解(属性property和功能function)
  • 无数的类(class)和对象(object)构成代码世界。类是将相同的个体抽象出来的描述方式,对象是实体,其具备有独立行为的能力,一个对象是万千世界中的“一粒沙”。
  • 具有相同属性和功能的对象属于同一类,而不同的类之间可能有联系(继承关系)或者没有联系。
  • 在C语言中,编程基于过程方法(function);在Verilog中,提供了笨拙的类对象编程可能性,即在module中定义方法,而后调用module实例中的方法
  • Verilog的module+method的方式与SV的class定义有本质上的差别,即面向对象编程的三要素封装(Encapsulation)继承(Inheritance)和多态(Polymorphism)
  • 类的定义核心即是属性声明(property declaration)方法定义(method definition),所以类是数据和方法的自洽体(self-compatible),即可以保存数据和处理数据。这是与struct结构体在数据保存方面的重要区别,因为结构体只是单纯的数据集合,而类则可以对数据做出符合需要的处理。

为什么要OOP(面向对象编程)?

- 激励生成器(stimulus generator):生成激励内容
- 驱动器(driver):将激励以时序形式送至DUT
- 监测器(monitor):监测信号并记录数据
- 比较器(checker):比较数据
  • 验证环境的不同组件其功能和所需要处理的数据内容是不相同的

  • 同环境的同一类型的组件其所具备的功能和数据内容是相似的

  • 基于以上两点,验证世界的各个组件角色明确、功能分立,使用面向对象编程与验证世界的构建原则十分符合。

  • 示例激励数据类:一个transaction事务类

class Transaction;
	bit[310]addr,crc,data[8];
	function void display;
		$display("Transaction:8h",addr);
	endfunction:display 
	function void calc crc;
		crc = addr ^ data.xor;
	endfunction:calc_crc 
endclass:Transaction

OOP的概念要素

官方OOP三要素;封装、继承、多态

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

创建对象

  • Verilog的例化SV class例化差别:
    • 两者的共同点在于使用相同的模板来创建内存实例
    • 不同点在于Veriloa的例化是静态的,即在编译链接时完成,而SV class的例化是动态的,可以在住意时间点发生,这也使得类的例化方式更加灵活和节省空间。
    • Verilog中没有句柄的概念,即只能通过层次化的索引方式A.B.sigX,而SV class通过句柄可以将对象的指针赋予其它句柄,使得操作更加灵活。
  • 在创建对象时,需要注意什么是**“声明”,什么是“创建”(即例化)**
Transaction tr;//声明句柄
tr =new();//创建对象
- 思考题: 下面有关类的说法哪些是错误的呢?
	- A、类可以定义变量也可以定义方法
	- B、一个类只能够用来生成一个对象(可声明很多个)
	- C、指向对象的句柄有且只能有一个(错,可以有很多个,多个句柄可指向同一对象)
	- D、类中定义的变量类型可以是wire或者reg(错,SV类偏向软件编程的思想,和硬件有关的内容都不要出现)
  • 所谓创建对象即开辟新的内存间,用来存放新的成变量和方法
  • 创建对象时,可以通过自定义构建函数(constructor)来完成变量的初始化和其它初始操作。
    • 示例
class Transaction;
	logic[310]addr,crc,data[8];
	
	function new();
		addr = 3;
		foreach(data[i])
			data[i]=5;
	endfunction 
endclass
  • 构建函数new()是系统预定义函数,不需要指定返回值,函数会隐式地返回例化后的对象指针。
  • 构建函数也可以定义多个参数作为初始化时外部传入数值的手段。
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);//data uses default of 5
end

上述代码中完成初始化后,tr.addr=10。new(10),将10传给了a。赋值在初始化之后,初始化的值被改变了,所以tr.addr不再是初值的’h10,而是10。

句柄的传递

  • 在区分了类(抽象)和对象(具体)之后,还需要区分对象(存储空间)和句柄(空间指针)。也就是说,在创建了对象之后,该对象的空间位置不会更改,而指向该空间的句柄可以有多个。
Transaction t1,t2;//声明句柄t1,t2
t1 =new();//例化对象,将其句柄赋予t1
t2=t1;//将t1的值赋予t2,即t1和t2指向同一个对象
t1 = new();//例化第二个对象,并将其句柄赋予t1

在这里插入图片描述在这里插入图片描述

对象的销毁

  • 软件编程的灵活在于可以动态地开辟使用空间,在资源闲置或者不再需要时,可以回收空间,这样使得内存空间保持在一个合理的区间。
  • C++语言中的类除了有构建函数,还有析构函数。析构函数的作用即在于手动释放空间,但这对编程人员的细心和经验提出了要求;Java和Python等后续面向对象语言则不再需要手动定义析构函数并且释放空间,这意味着空间的回收利用也是自动的。
  • sv也采用了自动回收空间的处理方式,使得用户不再软件空间的开销而烦恼。那么,自动回收空间的基本原理是什么呢?即,当一个对象,在整个程序中没有任何一个地方再需要"它时,便会被销毁,即回收其空间。这里需要的意思即指的是有句柄指向该对象。
class word 
	byte nb []; //注意动态数组开辟 用中括号
	function new(int n); 
		nb = new[n]; 
	endfunction 
endclass 
initial begin : initial_1
	word wd; 
	for (int i=1; i<=4; i++) wd=new(i) ; 
end 
initial begin : 
	initial_2
	#1ps
	$display ("How many Bytes are allocated for word instances?")<
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值