2015-06-22 115 views
4

我正在寻找Systemverilog中“自动”的好处。 我一直在看“自动”因子的例子。但我无法理解他们。有谁知道我们为什么使用“自动”?自动变量的好处是什么?

+0

请问更具体的问题。自动变量就像C/C++中的任何本地声明的变量。通常Verilog中的非自动变量就像C/C++中的静态变量。 –

+0

http://stackoverflow.com/questions/28021666/what-is-the-difference-between-automatic-and-static-task-why-we-cant-pass-by-ref/28025207#28025207 – Meir

回答

7

传统的Verilog已被用于在RTL模型硬件,并在门抽象。由于RTL和门级抽象都是静态/固定(非动态),因此Verilog仅支持静态变量。因此,例如,用Verilog任何REG线将被实例化/映射在模拟开始时和在模拟存储器,直到模拟结束将保持映射。因此,您可以将任何导线/脉冲转储为波形,并且reg/wire从开始到结束都会有一个值,因为它总是被映射的。在程序员的角度来看,这些变量被称为静态。在C/C++的世界,声明这样的变量,你将不得不使用存储类说明静态。在Verilog中,每个变量都是隐式静态的。

注意,直到SystemVerilog的来临,Verilog的只支持静态变量。尽管Verilog的也支持一些结构在行为的抽象造型,支持由缺乏自动存储类的限制。

自动(在软件世界中称为auto)存储类变量映射到堆栈上。当函数被调用时,函数中声明的所有本地(非静态)变量都映射到堆栈中的各个位置。由于这些变量只存在于堆栈上,因此只要函数执行完成并且堆栈相应缩小,它们就不再存在。

除了其他优点,此存储类启用的一种可能性是递归函数。在Verilog世界中,函数不能重入。递归(或重入)函数在自动存储类不可用的世界中不起任何有用的作用。为了理解这一点,你可以想象一个可重入函数作为一个函数,它动态地为它自己创建多个递归实例。每个实例都将自动自动变量映射到堆栈上。随着我们进入递归过程,堆栈不断增长,每个函数都可以使用自己的一组变量进行计算。当函数调用返回时,计算出的值将被整理并且最终结果可用。仅使用静态变量,每个函数调用都会将变量值存储在相同的公共位置,从而消除具有多个调用(实例化)的好处。

即将到达因子算法,将阶乘概念化为递归算法相对容易。在数学中,我们写了factorial(n)= n(factial(n-1))*。所以你需要计算阶乘(n-1)以便知道阶乘(n)。请注意,递归不能在没有终止情况下完成,在阶乘情况下n = 1。

function automatic int factorial; 
    input int n; 
    if (n > 1) 
    factorial = factorial (n - 1) * n; 
    else 
    factorial = 1; 
endfunction 

没有自动存储类,因为在函数中的所有变量将被映射到一个固定的位置,当我们调用阶乘(N-1)从内侧阶乘(n)时,递归调用将覆盖任何调用者上下文中的变量。在上述代码片段中定义的阶乘函数中,如果我们没有指定存储类别为自动,那么n和结果阶乘将被递归调用阶乘(n-1)所覆盖。作为结果,变量Ñ将连续被重写为n-1个N-2的n-3等等,直到我们达到的n = 1的终止条件。阶乘的终止递归调用的值为1,分配给n,当递归展开时,阶乘(n-1)* n在每个阶段中评估为1。

使用自动存储类,每个递归函数调用将在内存中(实际上在堆栈中)有自己的位置来存储变量n。因此连续调用阶乘不会覆盖调用者的变量n。因此,当递归展开时,我们将具有阶乘(n)的正确值为n *(n-1)(n-2) .. * 1。

请注意,也可以使用迭代定义阶乘。并且可以在不使用自动存储类的情况下完成。但在很多情况下,递归使用户能够以更直观的方式编码算法。

0

另一个例子是使用fork里面加入for循环 -

不使用的自动,叉加入里面的for循环将无法正常工作。

for (int i=0; i<`SOME_VALUE ; i++) begin 
    automatic int id=i; 
    fork 

     task/function using the id above ; 
     ... 
    join_none 
end 
0

我建议1例如如下(使用叉... join_none):(非使用自动

实施例1,:值输出将是 “3 3 3 3” 。因为i在退出后取最新值为循环,i存储在静态存储位置。这可能是您的代码中的一个错误。

initial begin 
    for(int i =0; i<=3 ; i++) 
    fork 
     $write ("%d ", i); 
    join_none 
end 

例2(使用自动):值输出将是 “0 1 2 3”。因为在每个循环中,值被复制到ķ,和fork..join_none产生一个线程与ķ每个值(每个循环将定位用于K 1个存储器空间:K0,K1,K2, k3):

initial begin 
    for(int i =0; i<=3 ; i++) 
     fork 
      automatic int k = i; 
      $write ("%d ", i); 
     join_none 
    end