SystemVerilog 第5章 面向对象编程基础


在这里插入图片描述


5.1 概述

5.2 考虑名词而非动词

5.3 Class(类)

类的定义

class Transaction;

//属性声明
bit [31:0] addr;

//方法创建
function void display;
	$display();
endfunction
endclass: Transaction
  • 变量命名参考
    类:大写字母开头,不含下划线(Transaction)
    常数:全大写(SIZE)
    变量:全小写

5.4 类定义的位置

  • program、module、package中或这些块之外
  • 类可以再program和module中使用

5.5 OOP术语

  • class:对象+方法
  • object:对象
  • handle:句柄
  • property:属性
  • method:方法(function&task)
  • prototype:原型(块头:名字,返回类型,参数列表)

5.6 创建对象

  • class和module联系和区别
    – 相同点:
    ①属性和方法的载体
    ②可以逐层例化得到复杂层次结构
    – 不同点:
    ①module静态,再编译时就分配好空间;class动态,仿真随用随分配
    ②封装性:module公开;class可以设定保护(protected/local)
    ③继承性:module不继承,class可以
    ④module的例化名和空间是绑定的(即便是automatic变量名也是和空间绑定的);对象的句柄和空间不绑定;不用了可以回收

5.6.1 没有消息就是好消息

  • 声明&例化
Transaction tr; //声明句柄
tr = new(); //例化对象
  • 刚声明完时候句柄为null,直到调用new()

5.6.2 new函数(构造函数)

  • new()例化对象的步骤
    ①new()根据句柄类型分配对应的空间
    ②为变量初始化默认值
    ③返回对象的句柄
  • new()也是class的方法,可以在new()函数中行使方法的功能(修改属性值,从外部传入参数等)

5.6.3 将声明和创建分开

  • 避免声明句柄的时候就调用new()

5.6.4 new()和new[]

  • new() 为对象(属性+方法)开辟空间
  • new[n] 为数组开辟大小为n的空间

5.6.5 为对象创建句柄

  • 句柄传递:仅仅是指向了相同的对象(可以把" : "看作“”)
Transaction t1,t2;
t1 = new();
t2 = t1; //t1和t2都指向了相同对象

5.7 对象回收(deallocation)

  • 当句柄指向一对象时,对象不可回收;当没有句柄引用时,对象自动回收
  • t = null; //回收t指向的对象
  • SV的句柄只能指向一种类型

5.8 使用对象

  • . 来引用属性和方法
    t.addr;
    t.display();

5.9 静态变量

  • 对象中的变量默认是动态的局部变量
  • 声明静态变量
    static int count=0;

5.9.1 class的静态变量

  • class中定义的静态变量,其初始化语句只执行一次;而动态变量每次执行都会重新创建并初始化

5.9.2 静态变量的访问

  • . 引用:与属性/方法相同
  • 静态独有作用域符号 ::(Transaction::count)

5.9.3 静态变量的初始化

  • 静态变量通常应在声明的时候初始化

5.9.4 静态方法

  • 定义和调用
//定义
static function void display();
	...
endfunction

//调用
object.display();
Transaction::display();
  • 静态方法不可以调用动态变量(编译时候动态变量不存在)

5.10 类的方法

  • class的属性和方法默认都是动态的(automatic)

5.11 类外部定义方法

  • class定义尽量在一页内写完
  • 定义格式: prototype在内,代码在外
class Transaction;
	bit [31:0] addr;
	extern function void display();
endclass

function void Transaction::display();
	...
endfunction

5.12 作用域

  • 作用域即一个代码块的范围:module,program,function,task,class或begin-end
  • 变量可以使用相对作用域(相对于当前块)和绝对作用域$root
  • SV调用一个变量名时,先在当前作用域中寻找,接着在上一级作用域中寻找,直到找到为止
  • class应该定义在program和module之外的package中
  • this 是当前类的指针

5.13 类的嵌套

  • 格式:一定要在new()中例化嵌套的类
class Transaction;
	bit [31:0] addr;
	Statistics stats; //声明嵌套类的句柄

	function new(); //Transaction类构造函数
		stats = new(); //stats实例化
	endfunction
endclass

5.13.1 类做多大

5.13.2 编译顺序

  • 一定要先定义类,然后再调用。解决编译顺序方法有二:
    ①将class的定义放在调用前,或定义在package中先编译
    ②在块首使用typedef创建临时class名:typedef class Statistics;

5.14 SV动态对象

5.14.1 将对象传递给方法

  • 如果直接传递句柄名到方法中,则传递的是句柄的副本,而非原始句柄,更不是对象本身
  • 下面代码中执行完后句柄 t 仍然为null,而方法中创建了一个和 t 同类型的局部句柄 tr 及对象
//操作对象的方法
function void create(Transaction tr);
	tr=new()
endfunction

//句柄传递
Transaction t;
intial begin
	create(t);
end

在这里插入图片描述

5.14.2 在任务中修改句柄

  • 在方法中修改句柄本身,不会对方法外的对象句柄产生任何影响,因为方法中的句柄是一个句柄的副本
  • 若要想直接对句柄本身操作且不影响所指对象,需要使用ref参数将句柄以指针方式传递
function void create(ref Transaction tr);
	...
endfunction

5.14.3 在程序中修改对象

  • 发送对象时需要为每个对象进行实例化

5.14.4 句柄数组

  • 存放句柄的数组,每一个元素都指向一个对象

5.15 对象的复制

5.15.1 new的浅复制

  • new操作可以复制现有对象的所有变量和方法
    handle2=new handle1;
  • 浅复制只能复制当前对象,对象中的嵌套对象不能复制(只传递句柄,没有调用new()函数)

5.15.2 copy函数的简复制

5.15.3 copy函数的深复制

  • 实现深复制则需要为层次结构中每一个类增加一个copy函数
  • copy函数返回值为所在类的句柄。步骤:函数体调用new()实例一个对象;将当前类中所有属性值复制给新建的copy对象
  • copy函数的定义和使用
//嵌套class定义
class Statistics;
	time startT,stopT;
	...
	function Statistics copy();
		copy = new();
		copy.startT = startT;
		copy.stopT = stopT;
	endfunction
endclass

//copy function
class Transaction;
	bit [31:0] addr,crc,data[8];
	Statistics stats;
	static int count = 0;
	int id;
	
	function new();
		stats = new();
		id = count++;
	endfunction
	
	function Transaction copy;
		copy = new();
		copy.addr = addr;
		copy.crc = crc;
		copy.data = data;
		copy.stats = stats.copy;
		id = count++;
	endfunction
endclass

//深复制
program top;
	Transaction src,dst;
	initial begin
		src = new();
		src.stats.startT = 42;
		dst = src.copy();
		dst.stats.startT = 96;
		$display(src.stats.startT);
	end
endprogram

5.15.4 流操作符打包对象

  • 编写pack和unpack函数
function void pack(ref byte bytes[40]);
	bytes = {>>{addr,crc,data}};
endfunction

function void unpack(ref byte bytes[40]);
	{>>{addr,crc,data}} = bytes;
endfunction

5.16 公有和私有

5.17 题外话

5.18 搭建测试平台

  • 分层测试平台的各个部分都是类,test处在最高层的program中,从而例化layered environment。功能覆盖(function coverage)定义可以放在layered environment类的内部或外部

在这里插入图片描述

  • 1
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值