本节主要介绍了SystemVerilog中类的封装与继承的基本内容、虚方法以及包的使用。
类的概述
- 类的三要素:封装、继承、多态(虚方法)
- 类是一种可以包含数据和方法的类型
- OOP(Object-Oriented Programming)术语:
- 类(class):包括成员变量和成员方法
- 对象(object):类在例化后的实例
- 句柄(handle):指向对象的指针,通过句柄可以索引对象的变量和方法
- 原型(prototype):程序的声明部分,包含程序名、返回类型和参数列表
类的封装
1.句柄的使用
当句柄指向一个对象时, SystemVerilog不会释放该对象的内存空间(对象的创建)
如果没有句柄指向个对象, Systemverilog将释放该对象的内存空间(对象的销毁)
1
2
3
4
5
6Transaction t1, t2; //声明两个句柄
t1 = new();//创建一个对象,并将t1指向该对象
t2 = new();//创建一个对象,并将t2指向该对象
t1 = t2; //将t2的值赋予t1,这时t1和t2指向同一对象,t1之前指向的对象被释放
t1.display();//调用对象的成员方法
t1.addr = 32'h42;//给对象成员赋值
2.静态变量和静态方法
- 静态变量:
- class内部声明的变量默认为动态变量,其生命周期始于对象创建,终于对象销毁
- 使用static声明class内部的变量时,其为静态变量。其生命周期始于编译阶段,贯穿于整个仿真阶段
- 静态变量的引用:使用类名直接引用(
Transaction::count
)或者通过例化对象引用(tr.count
)
- 静态方法:静态方法内可以声明并使用动态变量,但不能使用类的动态成员变量
3.类的成员
类中的成员默认是
public
,子类和外部均可访问但如果指明了类型为
protected
,那么只有该类或者子类可以访问如果访问类型为
local
,那么只有该类可以访问成员,子类和外部均不可访问1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class clock;
local bit is_summer = 0;
local bit nclock = 6;
function int get_clock();
...
endfunction
endclass
clock ck;
initial begin
ck = new();
$display("now time is %0d",ck.get_clock);//成功访问
ck.set_summer(1);
$display("now time is %0d",ck.nclock); //报错,外部句柄不能访问local变量
end
4.this
this是用来明确索引当前所在对象的成员
this只可以用来在类的非静态成员、约束和覆盖组中使用
this可以明确所指向变量的作用域
1
2
3
4
5
6class Demo;
integer x;
function new (integer x);
this.x = x; //说明这时this.x代表成员变量integer x
endfunction
endclass
5.浅拷贝与深拷贝
浅拷贝:new复制创建了一个新的对象,原对象的值被盲目的抄写到目的对象中,但如果类中包含了一个指向另一个类的句柄,那么只有最高一级的对象被new操作符复制,下层的对象不会被复制
1
b2 = new b1
深拷贝:当使用深复制时,所有的变量都会被复制,包括下层的对象
1
b2.copy(b1); //深复制,其中一个改变,不会影响另外一个
类的继承
子类继承父类的所有数据成员和方法
子类可以添加新的数据成员或者方法
子类可以通过
super
操作符引用父类中的方法和成员1
2
3
4
5
6class LinkedPacket extends Packet;
LinkedPacket next;
function LinkedPacked get_next();
get_next = next;
endfunction
endclass通过
extends
,LinkedPacket继承于其父类Packet当子类成员与父类成员同名,必须使用
super
来指定访问其父类成员当父类的new没有参数时,子类也会自动先调用父类的new,当父类的new有参数时,需加上
super.new(参数列表)
使得子类先调用父类的new子类句柄赋值给父类之后,被赋值的父类句柄只能指向整个子类中属于父类的部分
虚方法
通过在父类里定义虚方法(virtual task or function),可以在当父类句柄调用一个方法时候,前提是若是这个句柄指向了子类对象,则调用的方法为子类的方法而不是父类的方法
使用系统函数
$cast
将父类句柄转化为子类句柄,,使其可以访问子类的变量
包的使用
- 为了使得可以在多个模块(硬件)或者类(软件)之间共享用户定义的数据类型,SV添加了包
- 通过
package endpackage
关键字来定义包 - 可以通过
package_name::var
来索引包中的变量 - 也可以通过
import package_name::var
在module中导入包中的变量 - 或者通过
import package_name::*
,这代表当在module中找不到对应的变量时,就会在包中找