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