SV芯片验证之类的封装和继承
类class
声明:本内容来自于学习路科验证发布在B站上的免费视频课程后的笔记
0、概念
类class:包含成员变量和成员方法;
对象object:类在例化后的实例;
句柄handle:指向对象的指针;
原型prototype:程序的声明部分,包含程序名、返回类型和参数列表。
对象的创建是在仿真以后才做的。对象和软件编程中的对象相似。
类的三要素:封装、继承、多态(虚方法)
类是一种可以包含数据和方法(function、task)的类型。
一、类的封装
1、构建函数constructor:
SV的空间开辟和回收都是自动的。因此在SV里面定义类的时候,只需要定义构建函数(constructor)就行,而不需要定义析构函数(destructor)。
而类在定义的时候,如果用户未自己定义,那么系统则会自动帮助定义一个空的构建函数(没有形式参数,函数体也为空)。
对象在创建时,需要先声明再例化,或者同时进行。
class Packet;
integer new();
function new();
command = IDLE;
endfunction
endclass
Packet p = new;
2、静态成员(变量、参数、方法):
类的成员(变量和方法)默认都是动态的automatic生命周期的,即每一个对象的变量和方法都会为其开辟新的空间。
如果有多个对象为了共享一个成员,那么这时可以给它添加静态关键字static,这样多个对象就可以共享同一个成员变量或者方法,访问该成员时,无需进行对象的例化。
当整个运行程序中,没有任何一个句柄指向一个对象时,那么它原先开辟的空间就会自动被释放掉(回收)。
静态的意思是在仿真开始前就已为它分配好了空间;而动态的意思则是在跑仿真的时候才会分配空间。默认情况下,都是动态。
1)由类创建的对象是动态的,例化的模块是静态的。
2)类的成员变量和方法在默认情况下是动态的,但可以声明为静态的。
3)静态成员无法访问非静态成员,否则会发生编译报错。
3、this
用来索引它当前所在对象的成员,比如变量、参数、方法。
它只可以用来在类的非静态成员、约束和覆盖组中使用。
使用this,可以明确所指向变量的作用域。
class Demo;
integer x;
function new (integer x);
this.x = x;
endfunction
endclass
当没有this时,在查找变量时遵循就近原则。
当有this时就会指向当前所在类的成员变量x。
4、赋值与拷贝
1)声明变量(句柄)和创建对象是两个不同的过程。
Packet p1; //声明变量(句柄)
p1 = new(); //创建对象
p2 = p1; //句柄的赋值,没有创建新的对象。即是句柄p1和p2都指向了同一个对象。
2)也可以一步完成。
Packet p1 = new();//声明变量的同时创建对象。
3)浅拷贝shallow copy
在创建p2的对象的同时,将p1的成员变量拷贝给p2。
Packet p1;
Packet p2;
p1 = new;
p2 = new p1;
深拷贝deep copy:需要自己写自定义函数。深拷贝后新的句柄指向与被拷贝的句柄指向完全一样,且两者空间互相独立。
5、数据的隐藏和封装
1)类的成员(变量或者方法)在默认情况下,它们是公共的,即是类本身和外部均可访问它们。
有时候,类的提供方会限制一些类成员的外部访问权限,从而隐藏类成员的一些细节。
2)有以下两种方式可以限定类的成员:
使用local,它表示只有该类可以访问该成员,而子类以及外部都无法访问;
使用protected,它表示该类及其子类都可以访问该成员,而外部无法访问。
二、类的继承
1、通过关键字extends可以在类的基础上再扩展出一个子类,子类继承父类所有的成员(变量和方法)。
class Packet1 extends Packet;
Packet1 next;
function Packet1 get_next();
get_next = next;
endfunction
endclass
2、为了便于理解,最好是在写代码时在子类里面调用super.new()。
关键字super是用来访问当前对象其父类的成员。
3、子类的方法名(task和function)经常与父类的方法名相同;
4、子类的成员变量名尽量不要与父类的成员变量名相同(但可以相同)。
如果子类变量名和父类变量名相同且值不一样的话,那么子类句柄就无法获取父类的变量,因为此时子类的变量就覆盖掉了父类的变量。但又可以通过将子类句柄赋值给父类句柄,然后通过父类句柄来获取(这句话有点废话)或者直接通过父类句柄来获取。
5、子类的句柄可以直接赋值给父类,但赋值后父类访问的成员变量也仅限于父类里的成员变量(子类域包含父类域,子类域的范围比父类域大)。
6、父类句柄不能直接赋值给子类句柄,编译的时候可能会出错(此处不确定),但如果在运行或者仿真时父类句柄指向了子类成员变量,那么就可以父类句柄可以赋值给子类句柄,但不能用=,需要用$cast(子类句柄,父类句柄)。
4-6总结:
- 子类句柄可以获取到子类自加的变量和继承于父类的变量。但如果子类自加变量名与继承于父类的变量名相同,那么此时子类句柄就获取不到同名的父类变量;
- 父类句柄只能获取到父类的变量。
关键字super、this只适合出现在类里面,表示的查找域范围仅限于类,而不能出现在模块等地方。

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)