0.OOP概述
OOP即object-oriented programming,能够使用户创建复杂的数据类型,并且将它们跟使用这些数据类型的程序紧密结合。在更抽象的层次建立测试平台和系统级模型,通过调用函数来执行动作(而不是改变信号的电平)。如此一来,测试平台跟设计细节分开,更加易于维护和复用。
1.OOP术语
- 类(class):包含变量和子程序的基本构建块。
- 对象(object):类的一个实例。
- 句柄(handle):指向对象的指针。一个OOP句柄好像一个对象的地址,但是保存在一个只能指向单一数据类型的指针中。
- 属性(property):存储数据的变量。
- 方法(method):任务或者函数中操作变量的程序性代码。
- 原型(prototype):程序头,包括程序名、返回类型、参数列表。程序体包含执行代码。
- 几点理解:
- 一个类相当于房子蓝图;对象相当于房子实体;句柄相当于房子的地址,唯一地标志了该房子;类中的属性好比房子中的电器;可以通过调用方法来对属性变量进行修改,控制电器的开关。
- SV的类只有在实际用到的时候才会被例化并用于驱动DUT,最后这些对象占用的内存可以被释放以供新的对象使用,是一个动态过程。Verilog的模块例化时静态的,在编译时完成例化,仿真时候不论该例化的模块信号是否变化,这个模块都是实实在在存在的。
- 可能有很多对象,但是只有少数句柄。这些对象先后出现被句柄先后表示。
2.创建、使用、析构对象
- 创建也就是将一个抽象的类用实例表示,为该对象申请一个新的内存来保存其属性与方法。
- 通常声明一个类的句柄,并通过调用构造函数(new())来创建对象。new()除了开辟内存外慧慧初始化属性。默认情况下,对于4值逻辑的属性初始化为x、2值逻辑的为0。也可以通过一个带参数的new()函数对属性赋值。
class Transaction;
bit[31:0] addr,.....;
function void display(); //类中方法
$display('' @%0t : TR addr = '',$time,addr);
.......
endfunction
endclass
Transaction t1; //t1为句柄
t1 = new();//创建一个对象,地址为t1
t1.addr = 32'h1;//设置属性
t1.display();//调用对象的方法
t1 = new();//创建第2个对象,地址为t1,此时第一个对象的内存被释放
t1 = null;//第2个对象内存被释放
- 不同于C++,在sv中,对象析构是自动的。
3.注意事项
- 类应该在program中或者module外的package中定义。
- 若在一个类中使用了一个未声明的变量,比如循环变量i,碰巧在程序块中声明了同名变量,但是你本打算将其用于别处。然而在使用该类的该方法时,sv将会自动地使用程序级别的i,而不会给出警告!!
- 从上面一点也可看出,sv在寻找变量时候会先在当前作用域找,接着在上一级作用域找,直至找到为止。
- this明确地告诉sv,我正在向类一级的变量赋值。
- 若一个类包含着一个尚未定义的类,那么直接编译会报错,因为编译器不认识这个子类,需要用typedef class name 带提前声明告诉编译器这是一个类。