system verilog学习2
三、过程语句与子程序
函数与任务
task | fuction |
---|---|
任务可以调用函数 | 函数不能调用任务 |
任务可以有延时 | 函数一般没有延时 |
任务没有返回值 | ·函数有返回值,没有返回值需要指定function void |
待补充
第五章 面向对象编程基础
类
类是相关功能和特征元素的综合。
- 定义
class Transaction;
bit [31:0] addr;//属性声明
function void display;//方法(函数)创建
$display();
endfunction
task print();//方法(任务)创建
$display();
ebdtask
endclass: Transaction
-
OPP术语
class:类,对象+方法
object:对象是类的实例
handle:句柄,指向对象的指针,指向对象的地址。
property:属性
method:方法(function&task)
prototype:原型(块头:名字,返回类型,参数列表) -
类的初始化与回收
class Transaction;
Transaction tr;//声明一个句柄,初始化是null
tr=new();//分配空间,返回对象的句柄tr
注意:
1、new() 为对象(属性+方法)开辟空间;new[] 为动态数组开辟的空间
2、一个对象可能有多个句柄
3、t = null; 回收t指向的对象。没有任何句柄指向对象的时候就自动回收垃圾
- 对象的使用
t.addr;
t.display();
- 静态变量和全局变量
1、静态变量count用来报讯创建对象的数目。
class Transaction;
static int count = 0;
int id;
function new();
id=count++
endfunction
endclass
2、静态变量的访问
① . 引用:与属性/方法相同
② 静态独有作用域符号 ::(Transaction::count)
3、静态方法
static function void display();//定义
...
endfunction
//调用
object.display();
Transaction::display();
- 类的方法
1、class的属性和方法默认都是动态的(automatic)
2、类外部定义方法,将方法定义在类后面,class定义在一页内写完。
class Transaction;
bit [31:0] addr;
extern function void display();//extern
endclass
function void Transaction::display();//::
...
endfunction
-
类的作用域
1、作用域即一个代码块的范围:module,program,function,task,class或begin-end
2、变量可以使用相对作用域(相对于当前块)和绝对作用域$root
3、SV调用一个变量名时,先在当前作用域中寻找,接着在上一级作用域中寻找,直到找到为止
4、class应该定义在program和module之外的package中
5、this指针指向当前类的变量 -
类的嵌套
一定要在new()中例化嵌套的类,stats句柄是null的时候,调用start会失败。
class Transaction;
bit [31:0] addr;
Statistics stats; //声明嵌套类的句柄
function new();
stats = new(); //stats实例化
endfunction
task create_pockect();
stats.start();//调用Statistics类中的成员
endtask
endclass
-
类的编译顺序
编译一个类的时候包含尚未定义的类,需要用typedef语句声明一个低级别的类。 -
理解动态对象
1、将对象传递给方法
注意传递的是句柄的副本,不是句柄本身,所以句柄不会被改变。可以认为,只在函数里有一个句柄指向t,但是函数结束就被释放了。将对象传递给函数、任务等,注意方法中传递的是句柄的副本,不是句柄本身,所以句柄不会被改变,此时有两个句柄正指向对象t(存疑)。
function void create(Transaction tr); //定义操作对象的方法
tr=new();
tr.addr=42;
...
endfunction
Transaction t;//声明类Transaction的对象t
intial begin
create(t);//create修改了参数tr,但是句柄t仍未null
display(t.sddr);//失败,因为t=null
end
2、在任务中修改句柄ref
tr没有申明ref的时候,在方法内部对于tr的修改不会被调用该方法的代码看到,tr仍没有变化。
function void create(ref Transaction tr);
...
endfunction
3、在程序中修改对象
待补充
4、句柄数组
待补充
- 对象的复制
1、new的浅复制
new操作可以复制现有对象的所有变量和方法,对象中嵌套的对象不能复制
handle2=new handle1;
2、copy函数的深层复制
需要为类中嵌套的每一个类增加一个copy函数。
//嵌套class的定义,由于后面要copy,增加copy函数
class Statistics;
time startT,stopT;
...
function Statistics copy();
copy = new();//copy函数返回值为所在类的句柄
copy.startT = startT;
copy.stopT = stopT;
endfunction
endclass
//copy function
class Transaction;
bit [31:0] addr,crc,data[8];
Statistics stats;//嵌套Statistics
static int count = 0;
int id;
function new();
stats = new();
id = count++;//计数
endfunction
function Transaction copy;
copy = new();
copy.addr = addr;
copy.crc = crc;
copy.data = data;
copy.stats = stats.copy;//调用嵌套类Statistics的函数copy在Transaction类中对于Statistics进行复制
id = count++;
endfunction
endclass
//深复制
program top;
Transaction src,dst;
initial begin
src = new();
src.stats.startT = 42;
dst = src.copy();
dst.stats.startT = 96;
$display(src.stats.startT);//42
end
endprogram
类的继承
子类可以继承父类的属性和方法
见SV初级培训PPT
通过父类对象调用被重载的方法,这个方法需要使用virtual声明
见SV初级培训PPT