systemverilog中的参数传递——ref,input,output 本⽂介绍了 system verilog 中静态数组、动态数组、队列作为函数参数传递的规则,以及 input、output、ref关键字的规则。system verilog中的参数传递——ref,input,output
先说明,sv 中的静态数组、动态数组、队列都是⽤⼀块内存存放,⽽他们的名字作为该内存的地址,这点应该和 c ⼀致,但 sv ⾥⾯没有指针的概念。
传递这种⼤⽚内存的值⼀般只有两种规则
地址传递,函数内部修改可以改变函数调⽤的值。
值传递,将整⽚空间复制⼀份,函数内部修改不会改变函数调⽤的值。
但是 system verilog ⾥⾯关键字有三个,input、output、ref。具体哪个对应哪个,我们来试⼀下。以静态数组作为模板来试。
function void run();
int r[2];
r[0]=1;
r[1]=2;
f(r);
$display("%0x %0x",r[0],r[1]);
endfunction
加 input 的情况
function void f(input int a[2]);
a[0]=3;
endfunction
输出结果是:1 2
具体过程如下:
1. 函数调⽤之前,内存⾥只有 r 数组的空间
2. 函数调⽤之后,会将 r 拷贝⼀份到 a,函数⾥⾯⽤的都是 a 这份空间
3. 函数调⽤之后,赋值后,修改的是 a 这份空间的值
4. 函数返回之后,a 空间会被释放掉,所以 r 的值并没有修改
因此,input 是标准的值传递。
加 output 的情况
function void f(output int a[2]);
a[0]=3;
endfunction
输出结果是:3 0
1. 函数调⽤之前,内存⾥只有 r 数组的空间
2. 函数调⽤之后,会新建⼀份 a 数组,注意这⾥并不会把 r 的值传进来,函数⾥⾯⽤的都是 a 这份空间
3. 函数调⽤之后,赋值后,修改的是 a 这份空间的值
4. 函数返回之后,会将 r 指向 a 空间,⽽原来 r 指向的空间会被释放掉,所以 r 的值都被修改了
因此,加 output,采⽤的是地址传递,确切的说是反向的地址传递,数组共有两份,函数内部看到的是新建的⼀份,并传递给函数调⽤处,因此,函数调⽤前看到的是第⼀份,函数调⽤后看到的是新建的那份。
加 ref 的情况
function void f(ref int a[2]);
a[0]=3;
endfunction
输出结果是:3 2
具体过程如下:
1. 函数调⽤之前,内存⾥只有 r 数组的空间
2. 函数调⽤之后,会将 a 指向 r 所在的空间,函数⾥⾯⽤的都是这份空间
3. 函数调⽤之后,赋值后,修改的是这份空间的值,所以 r 和 a 都修改了
4. 函数返回之后,所以 r 的值只有部分修改
因此,加 ref,采⽤的是标准的地址传递,只有⼀份数组,函数内部和调⽤处都是访问该空间。
对⽐来看,input 是将函数外⾯的值传递到函数⾥⾯,调⽤结束之后,函数⾥⾯的值就被丢弃了;out 是将函数⾥⾯的值传递到函数外⾯来,调⽤结束之后,函数外⾯的值就丢了;ref 是函数内部和外部看
到的是同⼀份值,哪⾥改都会改。
另外,可以看出,采⽤ ref 关键字是占⽤内存最⼩的,因为只有⼀份数组,这样能提⾼效率。
动态数组或队列作为参数
如果传递的是动态数组或者队列,其结果是⼀模⼀样的,不另外作说明。
类作为参数
但是!!如果传递的是类,则会有点不⼀样。
class c;
output的反义词
int v0;
int v1;
endclass
function void run();
c c0;
c0 =new();
c0.v0 =1;
c0.v1 =2;
f(c0);
$display("%0x %0x",c0.v0,c0.v1);
endfunction
function void f(input/output/ref c c0);
c0.v0 =3;
endfunction
结果是:
1. input:3 2
2. output:报 null point 错误
3. ref:3 2
可以看出,如果是传递类的话,使⽤ input 和 ref 是⼀样的,都是地址传递,⽽ output 和数组的结果是⼀样的。其他

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。