首页 > 其他分享 >SV学习(5)——类和对象、类的成员

SV学习(5)——类和对象、类的成员

时间:2022-10-04 23:35:09浏览次数:71  
标签:Transaction 变量 对象 句柄 成员 SV new class

SV学习(5)——类和对象、类的成员

1. 类和对象概述

  • class类:包含成员变量和方法,是软件盒子
  • object对象:类在例化后的实例
  • handle句柄(指针):指向对象的指针
  • property属性(变量):在类中声明的存储数据的变量
  • method方法:类中使用task或function定义方法,处理自身或外部传入的数据
  • 原型声明(propotype):程序的声明部分,包含程序名、返回类型和参数列表

2. 声明类并创建对象

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

initial	begin
	Transaction tr;	// 声明句柄
	tr = new();		// 创建对象
end
  • 创建对象,开辟新的内存空间,用来存放新的成员变量和方法
  • 创建对象时,会调用构建函数(可自定义),不需要返回值,隐式的返回例化后的对象指针
  • 创建对象的动作时动态的,可以在仿真过程中发生
  • SV的类在定义时,只需要定义构建函数(constructor),而不需要定义析构函数(destructor)
  • 类定义时,需要定义构建函数,如果未定义,系统会自动帮助定义一个空的构建函数(没有形式参数,函数体为空)

3. 赋值和拷贝,深拷贝浅拷贝

  • 声明变量和创建对象是两个个过程,也可以一步完成

    Packet p1;
    p1 = new():
    
    Packet p1 = new();
    
  • 如果将t1赋值给另一个变量t2,实际也只有一个对象,只是指向这个对象的句柄有t1和t2,这种方式就是句柄的传递

    Transaction t1, t2;
    t1 =  new();
    t2 = t1;
    t1 = new();
    

    在这里插入图片描述

  • 下面的方式表示p1和p2代表两个不同的对象。在创建p2的同时,将从p1拷贝其成员变量例如integer、string和句柄等,这种拷贝方式称为浅拷贝(shallow copy)

    Packet p1, p2;
    p1 = new():
    p2 = new p1;
    
  • 浅拷贝VS深拷贝

    // 假设有这一样一个class
    class packet_c;
    	integer command;
    	static int data = 1;
    	packet_c pre;
    	function new(int inival = -1);
    		command = inival;
    	endfunction
    endclass
    
  1. 浅拷贝即句柄拷贝,只拷贝对象中的数据变量,比如数组、句柄,但是它不复制对象,只复制了句柄,对于对象中的数据操作(一般为任务和函数)和其中定义的其他类的句柄,采用类似“引用”的方式,浅拷贝前后共用同一内存空间;
  2. 深拷贝即对象拷贝,对对象中的所有成员变量(包括数据变量、数据操作和其他句柄)统一分配新的内存空间;
    在这里插入图片描述

4. 对象的销毁

  • 没有句柄指向的对象就会被销毁,空间被收回
  • SV不能回收一个被句柄引用的对象,即同一个对象被多个句柄指向,必须清除所有句柄才能销毁对象

5. 句柄的使用

  • 句柄可以用来创建多个对象,也可以前后指向不同对象

    Transaction t1, t2;
    t1 =  new();
    t2 = t1;
    t1 = new();
    t2 = null;	// 将t2赋值为‘空’,即不指向任何对象,此时指针‘悬空’,悬空的指针很‘危险’
    
  • 可以通过句柄来使用对象中的成员变量或者成员方法

    Transaction t;
    t = new();
    t.addr = 32'h42;
    t.display();// 调用对象的成员方法
    

6. 静态变量

  • class中声明的变量默认为动态变量,声明周期始于对象创建,终于对象销毁

  • static声明class中变量为静态,声明周期始于编译阶段,贯穿于整个仿真阶段

  • 静态变量var的引用:class::car、object.var

  • 类的所有对象共享一个静态变量

    class Transaction;
    	static itn count = 0;
    	int id;
    	
    	function new ();
    		id = count++;
    	endfunction
    	
    endclass: Transaction
    
    initial	begin
    	Transaction t1, t2;
    	t1 = new();	// id = 0, count = 1
    	t2 = new();	// id = 1, count = 2
    	$display("Second id = %d, count = %0d", t2.id, t2.count);	// 同 Transaction::count	
    end
    

7. 静态方法

  • class中声明的方法默认是动态的,可以用static修改为静态方法
  • 静态方法内可以声明并使用动态变量,但是不能使用类的动态成员变量

在调用静态方法时,可能并没有创建具体的对象,也因此没有为动态成员变量开辟空间,因此在静态方法中使用类的动态成员变量是禁止的,可能会造成内存泄漏,但是静态方法可以使用类的静态变量,因为静态方法和静态变量在编译阶段就已经分配好了空间。

class Transaction;
	static Congif cfg;
	static int count = 0;
	int id;
	
	// 通过静态方法来操作静态变量
	static function void display_statics();
		$display("Transaction cfg.mode = %s, count = %0d", cdf.mode.name(), count);
	endfunction
	
endclass: Transaction

initial	begin
	Congif cfg;
	Transaction::cfg = cfg;			// 静态变量赋值
	Transaction::display_statics();	// 调用静态方法
end

8. 验证为什么需要OOP面向对象

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

9. 一些差别对比

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

  • 两者共同点在于使用想用的模板来创建内存实例
  • 不同点在于Verilog的例化是静态的,即在编译链接时玩车个,而SV class例化是动态的,可以在任意时间点发生,使得类的例化方式更加灵活和节省空间
  • Verilog中没有句柄的概念,即只能通过层次化的索引方式A.B.sigX,而SV class通过句柄可以将对象的指针赋予其他句柄,使得操作更加灵活

9.2. 类与结构体的异同

  • 二者本身都可以定义数据成员
  • 类变量在声明之后,需要构造函数才会创建对象实体,而struct在变量声明时就开辟内存
  • 类除了可以声明数据变量,还可以声明方法,而struct不行
  • 根本上看,struct是一种数据结构,而class包含了数据成员以及针对这些成员们操作的方法

9.3. 类与模块的异同

  • 从数据和方法定义而言,二者都可以作为封闭的容器来定义和存储
  • 从例化来看,模块必须在仿真一开始就确定是否应该被例化,类的变量在仿真的任何时段都可以被构造(开辟内存)创建新对象。硬件部分必须在仿真一开始就确定下来,即module和其内部过程块、变量都应该是静态的;而软甲部分,即类的部分可以在仿真任何阶段声明并创建出新的对象
  • 从封装性来看,模块内的变量和方法是对外部公共(public)开放的,而类可以根据需要确定外部访问的权限是否是默认的公共类型、或者受保护类型(protected)还是私有类型(local)
  • 从继承性来看,模块没有任何的继承性,即无法在原有module基础上进行新module功能的扩展,而继承性是类的一大特点

10. this

  • this是用来明确索引当前所在对象的成员(变量、参数、方法)
  • this只可以用来在类的非静态成员、约束和覆盖组中使用
  • this的使用可以明确所指变量的作用域
class Demo;
	integer x;
	function new (integer x);
		this.x = x;
	endfunction
endclass

标签:Transaction,变量,对象,句柄,成员,SV,new,class
From: https://www.cnblogs.com/amxiang/p/16754821.html

相关文章

  • SV学习(6)——类的继承、句柄的使
    SV学习(6)——类的继承、句柄的使用1.类的成员访问类型2.类的继承extends3.子类索引父类的同名函数super4.成员覆盖补充一个有趣的代码5.句柄的传递6.......
  • SV学习(7)——包的使用
    1.包的定义SV提供了一种在多个module、interface和program中共享parameter、data、type、task、function、class等的方法,即利用package(包)的方法来实现。完整的验证环境......
  • 12.设计模式-适配器模式-对象适配器
    //1.定义目标被适配类//2.定义适配器接口,期望输出//3.实现适配器接口,被适配对象,通过set/构造方法注入进行组合//4.测试/**被适配类,输出的是220V*/publicclassVo......
  • 第五章.内置对象
    一、Date日期对象//获取时间方法一://获取日期对象lettimeS=newDate();console.log(timeS);//打印出来的时间是SatSep03202208:53:48GMT+0800(中国标准时间) ......
  • 关于静态方法中访问类的实例成员的两种方法
    之前的动手动脑我理解错了老师的意思,,写的程序并不能完全符合老师的要求,今天再写一遍复习一下。(1)把静态方法的参数变成类的实例化对象,简单代码和运行程序如下:  (2)在静......
  • python中类与对象的命名空间(静态属性的陷阱)、__dict__ 和 dir() 在继承中使用说明
    1.面向对象的概念1)类是一类抽象的事物,对象是一个具体的事物;用类创建对象的过程,称为实例化。2)类就是一个模子,只知道在这个模子里有什么属性、什么方法,但是不知道......
  • 面向对象
    一、理解面向对象(一)理解面向对象的举例为了方便了解,拿面向过程做一个对比面向过程:去超市--买菜--买肉--买米--回家--洗菜--切肉--炒菜--煮米饭--盛饭--开吃面向对......
  • 匿名对象
    匿名对象在java中可以充当return的值如publicclassPerson{publicStringname;//姓名publicintage;//年龄//定义构造方法,为属性初始化publicPerson(String......
  • 实验1 类和对象
    实验任务1task1_1.cpp#include<iostream>#include<string>#include<vector>intmain(){usingnamespacestd;strings1;strings2{"cplusplu......
  • 15.4 文件对象的常用方法
     #读,输出 read(),  read([size]) ,readline(), readlines()file=open('a.txt','r')print('输出文本所有内容',file.read())#输出文本所有内容fil......