自动变量有什么好处?

时间:2015-06-22 06:10:24

标签: system-verilog

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

3 个答案:

答案 0 :(得分:8)

传统上,Verilog已用于RTL和门级抽象的硬件建模。由于RTL和门级抽象都是静态/固定(非动态),因此Verilog仅支持静态变量。因此,例如,Verilog中的任何 reg wire 都将在模拟开始时进行实例化/映射,并将保留在模拟内存中,直到模拟结束。因此,您可以将任何wire / reg转储为波形,并且reg / wire将具有从开始到结束的值,因为它始终被映射。从程序员的角度来看,这些变量被称为 static 。在C / C ++世界中,要声明这样的变量,您必须使用存储类说明符 静态。在Verilog中,每个变量都是隐式静态的。

请注意,在SystemVerilog出现之前,Verilog仅支持静态变量。尽管Verilog还支持一些用于行为抽象建模的构造,但由于缺少自动存储类,因此支持受到限制。

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

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

使用 factorial 算法,将阶乘概念化为递归算法相对容易。在数学中我们写 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

没有自动存储类,因为函数中的所有变量都将映射到固定位置,当我们从factorial(n)内部调用factorial(n-1)时,递归调用将覆盖调用者上下文中的任何变量。在上述代码段中定义的阶乘函数中,如果我们未将存储类指定为自动,则 n 和结果 factorial 将被阶乘(n-1)的递归调用覆盖。因此,变量 n 会连续被覆盖为 n-1 n-2 n-3 等到达 n = 1 的终止条件。对factorial的终止递归调用将赋值为1 n ,当递归展开时,factorial(n-1)* n将在每个阶段中计算为1。

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

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

答案 1 :(得分:0)

另一个例子是在for循环中使用fork join -

如果不使用自动,for循环内的fork连接将无法正常工作。

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

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

答案 2 :(得分:0)

我建议如下1个示例(使用 fork ... join_none ):

Ex.1(非使用自动):值输出为&#34; 3 3 3 3&#34;。因为 i 在退出 for 循环后取最新值, i 存储在静态内存位置。这可能是您代码中的错误。

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

Ex.2(使用自动):值输出为&#34; 0 1 2 3&#34;。因为在每个循环中, i 的值被复制到 k ,而fork..join_none产生一个每个值为 k 的线程(每个循环)将为 k找到1个内存空间:k0,k1,k2,k3 ):

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