1.面向对象的三个基本特征
对象:万物皆对象
类:类就是具有相同属性和行为的对象的抽象的集合
实例:对象就是类的实例
封装可以隐藏实现细节,使得代码模块化;继承可以扩展已经存在的代码模块,两者的目的都是为了代码重用,多态为了实现另一个目的——接口重用。
1.1 类与结构体的差异
结构体(struct)可以自定义一个类型,类也是一种类型,那类与结构体的异同在于:
- 二者本身都可以定义数据成员
- 类在变量声明后,需要构建才会创建对象实体;而struct在变量声明时就已经开辟内存
- 类可以声明方法和任务,而结构体不能
- 从根本上看,struct是一种数据结构,而class则包含了数据成员以及针对成员的操作方法
2.封装
封装进行信息隐藏,利用抽象数据类型将数据和基于数据的操作封装在一起,尽可能隐藏内部一些细节,只保留一些对外接口使之与外部发生联系。数据封装、方法封装。
构造new()时,不需要返回值,函数会隐式地返回例化后的对象指针。
//声明类
class Transaction;
bit[31:0] addr,crc;
function new();
...
endfunction
endclass:Transaction
//声明一个句柄
Transaction tr,tr1,tr2;//指针悬空,为null值,没有指向任何对象
Transaction tr = new();//声明句柄+创建对象,为对象分配一个地址
//创建对象
tr1 = new(); //将句柄赋予给tr1
tr2 = tr1;//将tr1的值赋给tr2,即tr1、tr2指向同一个对象
tr2 = new();//将句柄赋予给tr2
注意:类中定义的变量不能是wire和reg,也不能出现initial和always,即硬件世界的部分不能在软件世界中定义。
调用new()时,系统的步骤:
1.系统开辟空间;
2.将开辟的空间分配给变量,进入new()函数对变量初始化
3.退出new()时,将当前对象的句柄返回
注意:new()函数创建对象时,会为对象分配地址,将类中变量初始化(二值变量为0,四值变量为x)。
systemverilog采取自动回收空间的处理方式,当一个对象,在整个程序中没有任何一个地方再需要它时,便会被“销毁”,即回收其空间。
在类中声明的变量时动态的(这和module恰恰相反),但可以用static来声明静态变量。
在类中声明接口的指针,必须要加virtual.
class TB;
static int count = 0;//声明一个静态变量
local virtual interface_test it;//声明一个指针
endclass
3.继承
子类继承了父类所有的成员方法和属性,并且可以拥有自己特性。通过关键字extends实现继承解决代码的重用性。
- 子类拥有父类非private的属性和方法。
- 子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
- 子类可以用自己的方式实现父类的方法。
3.1 成员访问权限
- 默认情况是子类和外部都可以访问
- protected只有该类和子类可以访问,外部不可访问
- local只有该类可以访问,子类和外部都不可访问
3.2 this 和 super的区别
- this 会先在当前作用域中查找,如果当前作用域中没有,则会去上一级作用域中查找,知道找到该变量为止
- super首先会先在该类的父类中查找
class Father
string name = "father";
function new(string name);
this.name = name;
endfunction
endclass
class Son extends Father;
int son_age = 5;
function new(string name);
super.new(name);
name = "son";
son_age = 15;
endfunction
endclass
3.3 类的方法
类的方法——也就是类的作用域定义的内部task或者function
class Transaction;
bit [31:0] addr,crc,data[8];
function void display();
$diaplay("@%0t:TR addr = %h,crc = %h",$time,addr,crc);
$write("\tdata[0-7]=");
foreach(data[i]) $write(data[i]);
$display();
endfunction
endclass
class PCI_tran;
bit [31:0] addr,data;
function void display();
$display("@a%0t:PCI:addr = %h",$time,addr,data);
endfunction
endclass
Transaction t;//声明句柄
PCI_Tran pc;
initial begin
t=new();//创建一个Transaction对象
t.display();//调用Transcation的方法
pc=new();//创建一个PCI事务
pc.display();//调用PCI事务的方法
end
4.多态
“一个接口,多种方法”,同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。
多态的三个条件:
- 继承的存在
- 子类重写父类的方法
- 父类引用变量指向子类对象
重载(overload)和重写(override)是实现多态的两种主要方式。