写在前面:开始修炼
类是通过代码怎么体现?
实例1:定义一个类
//systemverilog绿皮书
//例5.1简单的 Transaction类
class Transaction;
bit [31: 0] addr, crc, data[8];//class properities
function void display; //class method
$display("Transaction: %h", addr) ;
endfunction: display
function void calc_crc:
crc=addr^data. xor;
endfunction: calc_crc
endclass: Transaction
- 类封装了数据和对数据的操作(定义一个类就体现了类的封装性)
- 类中的数据称为属性( properties)
- 类中对数据的操作子程序称为方法( methods)
实例2:创建新的对象
Transaction b;// 声明一个句柄b
b=new(); //调用new()函数创建一个对象
- 声明一个句柄b。
该句柄描指向一个 Transaction 类型的对象。当声明一个句柄时,它的初始值为null。
- 调用new()函数创建一个对象。new()函数就是构造函数,创建对象空间
调用new函数时,系统会分配一块内存空间,用于存储对对象中得变量。
- new函数分配内存空间,存放Transaction的实例
- 将实例中的变量值初始化,默认情况下,二值逻辑变量初始值为0,四值逻辑变量的初始值位x
- 返回存放实例的地址(指针pointer)
实例总结:
实例1和实例2组合起来就满足了类的基本特征。
因此,使用一个类就包括三步:定义一个类、声明一个句柄、创建一个对象。
而实例中包括一些基本概念,看下面描述。
面向对象的基本概念
- 类 class
◆编码元素,包含所有的属性和功能
◆将数据和对数据的操作封装在起 Encapsulates
◆提供建立对象的模板
◆可以看做一种数据结构
-
对象 Object
◆对象 object是类class的实体
-
句柄 Handle
◆类型安全的指向对象( object)的指针( pointer)
-
属性 Properties
◆类( class)的实体( object)中包含的各种变量( variables)
-
方法 Methods
◆操作变量的任务(task)和函数( function)
面向对象编程的基本术语
面向对象编程的优势
- 传统的编程:分开处理数据结构和算法
- 面向对象编程:通过封装的方式对数据进行组织和管理
◆类( class)封装了数据和对数据的处理算法
◆对象( object)是一个类的实例
◆类( class)是有成员( members)组成的
◆成员( members)可以是属性( properties)(数据或者变量)或者方法( methods)(任务task或函数 function)
- OOP具有继承的特性-允许对已经存在的类的成员进行扩展
- OOP具有多态的特性一在运行时将数据和函数进行绑定
类中的一些常识:
-
释放句柄指向的对象的内存空间
◆如果没有句柄指向个对象, Systemverilog将释放该对象的内存空间
◆当句柄指向一个对象时, SystemVerilog不会释放该对象的内存空间
◆将句柄设置为null,将手动释放所有的句柄
-
重新new()一下,就会重新开辟内存空间
-
在一个类中可以使用另外一个类(多层嵌套)
- 使用层次化语法hierarchical
句柄的使用
shallow copy浅复制(指向同一个内存空间 )
获得对象的句柄
◆类的属性和实例化对象可以在类声明时直接被初始化
◆浅复制不会复制嵌套的对象(只是复制了句柄)
◆可以通过点号“.”操作符对对象中的变量进行操作,比如b1.aj
◆可以通过手动编写代码实现对所有变量的全复制,包括嵌套的对象
Transaction b1,b2;//声明两个句柄b1,b2
b1=new; //给b1分配内存空间
b2=new; //给b2分配内存空间
b2.copy(b1); //深复制,其中一个改变,不会影响另外一个
好,我们讲这个句柄讲的挺多的了,我给大家看一个例子。(这就是E课网中的原话,就喜欢听这句话,路桑的全是蓝字,小白很0.0)
实例:class_t.sv
//class_t.sv
//E课网
program class_t;
//Class with constructor,with no parameter
class A;
integer j;
//Constructor
//Task in class(object method)
endclass
//Class with constructor,with no parameter
class B;
integer i;
A a=new;
//Constructor
//Task in class(object method)
function copy(B in);
this.i=in.i; //父类B中的i
this.a.j=in.a.j;//父类B中父类A中的j
endfunction
endclass
initial begin
B b1 = new;
B b2 = new;
b2 = b1;//shallow copy
//b2.copy(b1);//deep copy
b2.a.j=50;
$display("b2.a.j=%0d\nb1.a.j=%0d",b2.a.j,b1.a.j);
end
endprogram
运行shallow copy的仿真结果:b2.a.j=50,b1.a.j=50
运行deep copy的仿真结果: b2.a.j=50, b1.a.j=x
静态变量
Systemverilog中允许在类中声明一个静态变量
- 静态变量跟类的定义相关,跟实例对象无关
- 静态变量用于存储可变数据,如创建的实例的数量
- 静态变量被类的所有对象共享
oop:继承inheritance
- 在原有的类的基础上增加新功能
- 单一继承:修改一个类的当前功能
◆在派生类中使用关键字" super"可以引用基类中的成员
◆如果在派生类中修改了基类中的成员,这必须使用关键字" 'super'获取基类的相关成员
实例:class_extend_example. sv
//systemverilog与功能验证(钟文枫)
//Chapter7 class_extend_example. sv
class Packet;
//属性
integer status;
//方法
task rst();
status =0
endtask
endcalass
Class DerivedPacket extends Packet;
//属性
integer a,b, c;
/方法
task showstatus ();
$display(status);
endtask
endclass
数据保护:本地变量 local
派生类不能操作基类中的本地变量(local)
抽象类和虚方法
oop:多态与虚方法直接关系
多态总结:实方法看句柄 ;虚方法看对象
实例:virtual_method.sv
//virtual_method.sv
//E课网
class A;
virtual task disp();
$display("This is class A");
endtask
endclass
class EA extends A;
task disp();
$display("This is Extended class A");
endtask
endclass
program main;
EA my_ea;//声明一个EA句柄my_ea;
A my_a; //声明一个A 句柄my_a;
initial begin
my_a = new;//给my_a创建一个对象
my_a.disp();//调用my_a的task
my_ea = new;//给my_ea创建一个对象
my_a=my_ea;//浅复制,句柄改变
my_a.disp();//调用my_ea的task
end
endprogram
仿真结果如下:
This is class A
This is Extended class A
这是虚方法,因此只看对象
实例:basic_method.sv
//basic_method.sv
//E课网
class A;
task disp();
$display("This is class A");
endtask
endclass
class EA extends A;
task disp();
$display("This is Extended class A");
endtask
endclass
program main;
EA my_ea;//声明一个EA句柄my_ea;
A my_a; //声明一个A 句柄my_a;
initial begin
my_a = new;//给my_a创建一个对象
my_a.disp();//调用my_a的task
my_ea = new;//给my_ea创建一个对象
my_a=my_ea;//浅复制,句柄改变
my_a.disp();//调用my_ea的task
end
endprogram
仿真结果如下:
This is class A
This is class A
实例:class_extern_methods.sv(这些宏?)
//class_extern_methods.sv
//E课网
`ifndef CLASS_EXTERN_SV
`define CLASS_EXTERN_SV
`include "class_extern.sv"
function class_extern::new();
this.address=$random;
this.data ={$random, $random};
this.crc =$random;
endfunction
task class_extern::print();
$display("Address : %x", address);
$display("Data : %x", data);
$display("CRC : %x", crc);
endtask
`endif
//class_extern.sv
//E课网
`ifndef CLASS_EXTERN_SVI
`define CLASS_EXTERN_SVI
class class_extern;
int address;
bit [63:0] data;
shortint crc;
extern function new();
extern task print();
endclass
`endif
参数化类
通用的类是很有用的,特别是在例化的时候可以修改数组的大小和数据类型。为了避免为每个特定的类编写类似的代码, SystemVerilog也支持参数化类,就如C++中的模板。
写到最后:好好修炼