(4)systemverilog 面向对象编程(一)

面向对象编程(一)

一、前言

面向对象编程使用户能够创建复杂的数据类型,并且将它们跟使用这些数据类型的程序紧密地结合在一起。用户可以在更加抽象的层次建立测试平台和系统级模型,通过调用函数来执行一个动作而不是改变信号的电平。当使用事务来代替信号翻转的时候,你就会变得更加高效。这样做的附加好处是,测试平台跟设计细节分开了,它们变得更加可靠,更加易于维护,在将来的项目中可以重复使用。

测试平台的目标是给一个设计施加激励,然后检查其结果是否正确。如果把流入和流出设计的数据组合到一个事务里,那么围绕事务及其操作实施测试平台就是最好的办法。在OOP中,事务就是测试平台的焦点。传统的测试平台强调的是要做的操作:创建一个事务、发送、接收、检查结果、然后产生报告。而在OOP中,你需要重新考虑测试平台的结构,以及每部分的功能。发生器(generator)创建事务并且将它们传给下一级,驱动器(driver)和设计进行会话,设计返回的事务将被监视器(monitor)捕获,记分板(scoreboard)会将捕获的结构跟预期的结果进行比对。因此,测试平台应该分成若干个块(block),然后定义它们相互之间如何通信。

在SV中,你可以把类定义在program、module、package中,或者在这些块之外的任何地方。当你创建一个项目的时候,可能需要将每个类保存在独立的文件中。当文件的数目变得太大的时候,可以使用SV的包将一组相关的类和类型定义捆绑在一起。

二、OOP术语

  1. 类(class):包含变量和子程序的基本构建块。Verilog中与之对应的是模块(module);
  2. 对象(object):类的一个实例。在Verilog中,你需要实例化一个模块才能使用它;
  3. 句柄(handle):指向对象的指针。在Verilog中,你通过实例名在模块外部引用信号和方法。一个OOP句柄就像一个对象的地址,但是它保存在一个只能指向单一数据类型的指针中;
  4. 属性(property):存储数据的变量。在Verilog中,就是寄存器reg或者线网wire类型的信号。
  5. 方法(method):任务或者函数中操作变量的程序性代码。
  6. 原型(property):程序的头,包括程序名,返回类型和参数列表。程序体则包含了执行代码。

三、对象

1.创建新对象

Transaction tr;//声明一个句柄
Tr=new();

在声明句柄Tr的时候,它被初始化为特殊值null。接下来,你调用new()函数来创建Transaction对象。new函数为Transaction分配空间,将变量初始化为默认值(二值变量为0,四值变量为X),并返回保存对象的地址。
new函数也被称为"构造函数",但是new函数不能有返回值,因为构造函数总是返回一个指向类对象的句柄,其类型就是类本身。
可以使用具有默认值的函数参数来创建更加灵活的构造函数。

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

应该避免在声明一个句柄的时候调用构造函数,即new函数。虽然这样在语法上是合法的,但是这会引起顺序问题,因为在这时构造函数在第一条过程语句前就被调用了。你可能希望按照一定的顺序初始化对象,但是如果在声明的时候调用了new函数,你就不能控制这个顺序了。

2.回收对象

一旦你得知事务已经成功完成,并且也得到了统计结果,你就不需要再保留这些对象了。这时候你需要回收内存。否则,长时间的仿真将会将内存耗尽,或者运行得越来越慢。
垃圾回收是一种自动释放不再被引用得对象得过程。SV分辨对象不再被引用得办法就是记住指向它得句柄的数量,当最后一个句柄不再引用某个对象了,SV就释放该对象的空间。

Transaction t;
t=new();
t=new();
t=null;

3.使用对象

可以通过对对象使用" . "符号来引用变量和子程序,例如:

Transaction t;
t=new();
t.addr=32'h42;

四、静态变量和全局变量

每个对象都有自己的局部变量,这些变量不和任何其他对象共享。如果有两个Transaction对象,则每个对象都有自己的addr、crc和data变量。但有时候你需要一个某种类型的变量,被所有的对象所共享。例如,可能需要一个变量来保存已创建事务的数目,如果没有OOP,可能需要创建一个全局变量。然后你就有了一个只被一小段代码所使用,但是整个测试平台都可以访问的全局变量。

在SV中,可以在类中创建一个静态变量。该变量将被这个类的所有实例所共享,并且它的使用范围仅限于这个类。

class Transaction;
	static int count=0;\
	int id;
	function new();
		id=count++;
	endfunction
endclass

Transaction t1,t2;
initial begin
	t1=new();
	t2=new();
end

可以通过类名加上::来引用静态变量
静态变量通常在声明时初始化。你不能简单地在类的构造函数中初始化静态变量,因为每一个新的对象都会调用构造函数。你可能需要另一个静态变量来作为标志,以标识原始变量是否已被初始化。
SV不允许静态方法读写非静态变量。

关注作者

  • 自述
    作者是一位中科大数字设计专业的研究生,水平有限,如有错误,请大家指正,想要与大家一同进步。
  • 经历
    曾获得国家奖学金,“高教社杯”数学建模国家二等奖等
  • 陆续更新:
    1.与UVM验证相关的system verilog后续内容;
    2.与verilog数字设计相关的一些基础模块设计,例如FIFO,UART,I2C等的书写。
    3.保研与竞赛经历等
  • 微信公众号
    欢迎大家关注公众号“数字IC小白的日常修炼”,期待与大家一同仗剑遨游数字IC世界。
  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数字IC小白的日常修炼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值