类的概述
类是一种可以包含数据和方法(function,task)的类型。
例如一个数据包,可能被定义为一个类,类中可以包含指令、地址、队列ID、时间戳和数据等成员。
class Packet ;//class定义类 类名 packet
//类 packet的成员
//数据或类属性
bit [3:0] command; bit [40:0] address; bit [4:0] master_id;
integer time_requested ;
integer time_ issued;
integer status;
typedef enum { ERR_OVERFLOW= 10,ERR_UNDERFLOW = 1123} PCKT_TYPE;
const integer buffer_size = 100;
const integer header_size;
//类 packet的成员方法new ();clean() ;issue_request; current_status
//初始化
function new ();
command = 4' d0; address = 41'b0; master_id = 5'bx; header_size = 10;
endfunction
//方法
//公共通道入口
task clean() ;
command = 0; address = 0; master_id = 5'bx ;
endtask
task issue_request( int delay ) ;
//向总线发送请求
endtask
function integer current_status ( ;
current_status = status;
endfunction
endclass
如果将class换成module,就变成硬件模块的定义。从一个软件的容器变成了硬件的容器。(class这个软件容器,对于构建验证环境更加灵活)
类的特点:
每一个packet类具体例化的数据成员可能都不相同,但是packet作为描述这些类的抽象类型,将其对应的数据成员和操作这些数据成员的方法都定义在其中。
面向对象编程(OOP)
面向对象编程(OOP,Object-Oriented Programming)使用户能够创建复杂的数据类型,并且将它们跟使用这些数据类型的程序紧密地结合在一起。
用户可以在更加抽象的层次建立测试平台和系统级模型,通过调用函数来执行一个动作而不是简单地改变信号的电平。即验证组件可以将软件抽象的激励转换为硬件的电平
在验证环境中,包括stimulator、monitor、checker以及其它验证组件接下来都将按照00P的方式来构建。
OOP术语
类(class) :包含成员变量和成员方法。
类与结构体的差别:
结构体可以定义成员变量,但是不能定义成员方法,也无法进行对象例化
对象(object) :类在例化后的实例。是具象的,类是抽象的。
类可以例化多个对象,每个对象的存储空间是各自独立的。每个对象都具有指针
句柄(handle):指向对象的指针。
原型(prototype):程序的声明部分,包含程序名、返回类型和参数列表。
类packet的特殊成员方法——构建函数
SV并不像C++语言一样要求复杂的存储空间开辟和销毁的手段,而是采用了像Java—样空间自动开辟和回收的手段。
因此SV的类在定义时,只需要定义构建函数(constructor) new,而不需要定义析构函数(destructor ) 。
类在定义时,需要定义构建函数,如果未定义,则系统会自动帮助定义一个空的构建函数(没有形式参数,函数体亦为空)。
对象在创建时,需要先声明再例化,同时进行亦可。
new()函数一般完成三件任务:
1、在例化对象实体的时候,为其开辟内存空间
2、内部会对对象的成员变量做初始化
3、在执行完之后,返回对象实例的句柄。
class Packet;//定义了类 packet 实例化的类:packet
integer command;
function new () ;
command = IDLE;
endfunction
endclass
Packet p;//声明句柄p,该句柄默认值是none,即表示它是悬空状态,没有指向任何对象。
p =new() ;//通过调用new(),new()完成自身的三个任务,并将句柄指向p
//句柄p最终指向新创建的对象
实际上,指向对象的句柄有多个,如果没有任何句柄指向该对象时,系统会认为该对象没有价值,系统会销毁此对象,收回内存空间。
静态成员(变量/方法)
类的成员(变量/方法)默认都是动态(automatic)生命周期,即每一个对象的变量和方法都会为其开辟新的空间。
静态成员变量
- 如果多个对象为了共享一个成员(变量/方法),那么可以为其添加关键字static。
- 多个对象因此可以共享同一个成员变量或者方法。
- 在访问静态变量时,也无需对它进行例化
//访问packet 类的静态成员变量filelD
//即使还未做例化,但是可以通过句柄或者域的索引符号来访问这个静态成员变量
class Packet ;
static integer filelD = $fopen( "data","r”);
...
endclass
Packet p;
c= $fgetc( p.filelD );//或者Packet::filelD
静态成员方法
- 成员方法也可以声明为静态。
- 静态方法无法访问动态成员(变量/方法),否则会发生编译错误。
class id;
static int current = 0;
static function int next_id();
next_id = ++current; // oK to access static variable
endfunction
endclass
静态方法无法访问动态成员(变量/方法)的原因:
在调用静态方法时,也不需要进行例化,静态成员变量/方法的空间是独立于实例对象的存储空间静态方法和动态成员之间是不应该存在访问关系的。
类的方法定义——this关键词
- this是用来明确索引当前所在对象的成员(变量/参数/方法)。
- this只可以用来在类的非静态成员方法、约束和覆盖组中使用。
- this的使用可以明确所指向变量的作用域。
class Demo ;
integer x;
function new (integer x);
this.x = x;//this.x指成员变量,x指参数
endfunction
endclass
//在这里有两个成员变量x
//Demo类的成员变量x和它的构建函数new()的参数x
//为了区分这个变量x,通过this.x来索引对象中的成员变量