sv 变量赋值,参数传递
systemverilog变量赋值,参数传递
1、变量类型
systemverilog中的变量可以分为两种,一种普通变量类型,一种是句柄变量类型。
- 普遍变量跟C/C++中的普通变量一样,而句柄变量则与C/C++中的指针变量或者引用变量类似。
- 内置类型,比如int,bit,这些类型定义的变量都是普通变量。
- 自定义的class通过new的方式定义的变量都是句柄变量。
2、变量赋值
- 普通变量赋值,直接是拷贝值。
- 句柄变量赋值,只是拷贝了句柄,使得两个句柄指向同一个空间。
- systemverilog没有拷贝构造函数,所以句柄变量拷贝的时候只是进行了句柄的拷贝,没有进行指向空间的拷贝。为了完成指向空间的拷贝,一般实现的方式是先new一块空间,让后调用copy函数,copy函数实现了拷贝构造函数的功能。
class_A ca1 = new(10);
class_A ca2 = new(12); // ca2要先new好,分配空间。
ca2.copy(ca1); // ca2拷贝ca1的数据
3、参数传递
参数传递默认跟变量赋值一样,普通变量拷贝值,句柄变量拷贝句柄。
(1)、ref修饰
如果普通变量想传递句柄到function或task中,可以添加ref修饰,这样传递给function或task的是原变量的句柄(这个时候要求参数必须是变量而不能是字面值)
这种方式跟C/C++中传递引用有点类似,如果传递的数据量比较大的时候,通过这种方式可以避免数据的拷贝,同时通过这种方式还可以将funciton和task的对这个变量的修改传出来。
(2)、input、output、inout
这几种修饰不能和ref修饰同时一起使用,因为这些修饰都是进行值拷贝的方式传递数据的,其中inout是进行了两次值的拷贝,输入的时候一次,输出的时候一次。
class class_A;
int a;
function new(int a);
this.a = a;
endfunction
function void getA_ref(ref int a);
a = this.a;
endfunction
function void getA_value(int a);
a = this.a;
endfunction
function void setA(int a);
this.a = a;
endfunction
function int getA();
return a;
endfunction
function void copy(class_A ca);
this.a = ca.a;
endfunction
endclass
class class_B;
class_A ca;
function new(class_A ca);
this.ca = ca;
endfunction
function int setA(int a);
ca.setA(a);
endfunction
endclass
program automatic test;
initial begin
class_A ca1;
class_A ca2;
class_B cb1;
int a = 1;
int b;
b = a; // 值拷贝
b = 2;
$display(a); // 因为b是值拷贝,修改b不影响a,所以输出1
ca1 = new(10);
ca1.getA_value(a); // 通过值传递方式获取函数内部值(且没有加output和inout)
$display(a); // 输出1,应为函数内部的a是a的一个值拷贝,函数修改不影响函数外的值。
ca1.getA_ref(a); // 同ref方式获取返回值。
$display(a); // a传递给函数内部的是引用,所以函数内部的修改,等效于修改了函数外的值。所以输出10
ca2 = ca1; // ca1为句柄变量,句柄拷贝
ca2.setA(20); // 通过句柄ca2修改内部的域。
$display(ca1.getA());// 因为ca2是ca1的句柄拷贝,所以ca2修改内部与,相当于修改了ca1的内部域,ca1和ca2指向相同空间。
cb1 = new(ca1);
cb1.setA(30);
$display(ca1.getA());// 输出30,通过非ref的参数传递ca1其实也是传递的是ca1的句柄,所以在函数内修改ca1能够体现到函数外。
ca2 = new(40); // 分配一块新的空间,让ca2指向,这个时候ca1和ca2指向了不同的空间。
$display(ca1.getA());// 输出30
$display(ca2.getA()); // 输出40
end
endprogram
队列、关联数组、动态数组
队列、关联数组、动态数组作为参数可以直接作为函数参数,但是要作为函数返回值则需要进行typedef
typedef int int_q[$];
function int_q func(int a[$], int b[], int c[int]);
endfunction