1 静态数组作为参数
sv中的静态数组、动态数组、队列都是用一块内存存放,而他们的名字作为该内存的地址,这点和c一致,但sv中没有指针的概念。
传递这种大片内存的值一般只有两种规则:
1.地址传递,函数内部修改可以改变函数调用的值。
2.值传递,将整片空间复制一份,函数内部修改不会改变函数调用的值。
但是,sv中里面关键字有三个: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
1234567
1.1 input
当函数类型为input时。
function void f(input int a[2]);
a[0]=3;
endfunction
123
输出结果:1 2
具体过程如下:
1.函数调用之前,内存里只有r数组的空间
2.函数调用之后,会将r拷贝一份到a, 函数里面用的都是a这份空间
3.函数调用之后,复制后,修改的是a这份空间
4.函数返回之后,a空间会被释放掉,所以r的值并没有被修改
因此,input是标准的值传递。
1.2 output
当函数类型为output时。
function void f(output int a[2]);
a[0]=3;
endfunction
123
输出结果是:3 0
具体过程如下:
1.函数调用之前,内存里只有r数组的空间
2.函数调用 之后,会新建一份a数组,注意这里并不会把r的值传进来,函数里面用的是a这份空间
3.函数调用之后,赋值后,修改的是a这份空间
4.函数返回之后,会将r指向a空间,而原来的r指向的空间会被释放掉,所以r的值都被修改了
因此,output 采用的是地址传递,确切的说是反向地址传递,数组共有两份,函数内部看到的是新建的一份,并传递给函数调用的处。所以函数调用前是第一份,函数调用后看到的是新建的那份。
1.3 ref
当函数是ref时。
function void f(ref int a[2]);
a[0]=3;
endfunction
123
输出结果是: 3 2
具体过程如下:
1.函数调用前,内存里只有r数组的空间
2.函数调用之后,会将a指向r所在的空间,函数里面用的都是这份空间
3.函数调用之后,赋值后,修改的是这份空间的值,所以a和r的值都被修改啦
4.函数返回后,所以r的值只有部分被修改
因此,ref采用的是标准的地址传递,只有一份数组,函数内部和调用出都是访问该空间。
对比来看,input是将函数外面的值传递到函数里面,调用之后,函数里面的值就被丢弃了;output是将函数里面的值传递到函数外面来,调用之后,函数外面的值就被丢弃了;ref是函数内部和外部看到的是同一份值,哪里都会被修改。另外,可以看出,采用ref关键字,占用 的空间内存是最小的,因为只有一份数组,这样能提高效率。
2 动态数组或队列作为参数
如果传递的是动态数组或队列,其结果是一模一样的,不另外作说明。
3 类作为参数
下面展示一些 内联代码片。
class c;
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 voidf(input /output ref c c0);
c0.v0 =3;
endfunction
12345678910111213141516
输出结果是:
1.input : 3 2
2.output :报null point 错误
3.ref: 3 2
可以看出,如果是传递类的话,使用input 和ref 的结果是一样 的,而output和数组 的结果是一样 的。文章来源:https://www.toymoban.com/news/detail-608928.html
4,解释:
以下均为个人理解,如若有所差错,实属难免。文章来源地址https://www.toymoban.com/news/detail-608928.html
把SV与C语言做对比:
SV中的句柄就是C中的指针,其本质上是一串数字,表示地址。
C中分为传址调用和传值调用,
传值调用:在SV中就对应input,是额外开辟一块内存复制该变量传入,并不会更改原来的变量。
传址调用:在SV中对应ref,表示引用原始变量,会导致该变量的改变,如果不想改变该变量,可以再加const前缀。
在调用类的时候:
调用类(句柄),句柄指向一个地址,当使用input时,不会复制一个相同的类(句柄),因为内存中的地址是唯一的,不存在相同的两个地址。
传递的是一个句柄,我们分为两种情况,
一是当该句柄已经分配一个对象(表现为句柄 指向了一个地址),这时已经有一个确定的对象了,当使用input传递该句柄时,指向一个确定的地址。 当使用input的时候,就直接调用该句柄所指向的对象, 对该变量(类)更改与ref没有区别; 退出函数时,仍然指向该地址
二是该句柄没有分配对象, 也就是一个空指针,句柄传入函数时,必须要先new,例化后分配了一个地址,这个句柄这时候指向该地址,但是函数是动态的,有生命的,当退出函数时,该句柄指向的空间自动解除分配,这时候的 指针仍然是一个空指针。
当使用ref的时候,给该句柄分配了什么地址,最后就指向什么地址。
到了这里,关于systemverilog中的参数传递——ref、input、output的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!