System verilog 自动变量的好处是什么?

System verilog 自动变量的好处是什么?,system-verilog,System Verilog,我正在寻找Systemverilog中“自动”的好处。 我一直在看“自动”阶乘示例。但是我不能通过他们。有人知道我们为什么使用“自动”吗?传统上,Verilog用于RTL和门级抽象的硬件建模。由于RTL和门级抽象都是静态/固定的(非动态),Verilog只支持静态变量。因此,例如,Verilog中的任何reg或wire都将在模拟开始时实例化/映射,并在模拟内存中保持映射,直到模拟结束。因此,您可以将任何导线/reg的转储作为波形,reg/wire从开始到结束都有一个值,因为它始终被映射。从程序员

我正在寻找Systemverilog中“自动”的好处。
我一直在看“自动”阶乘示例。但是我不能通过他们。有人知道我们为什么使用“自动”吗?

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

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

automatic(在软件世界中称为auto)存储类变量映射到堆栈上。调用函数时,函数中声明的所有局部(非静态)变量都映射到堆栈中的各个位置。由于这些变量只存在于堆栈上,因此一旦函数执行完成,堆栈就会相应收缩,它们就不再存在

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

谈到
阶乘
算法,将阶乘概念化为递归算法相对容易。在数学中,我们写阶乘(n)=n(事实(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
如果没有automatic存储类,因为函数中的所有变量都将映射到固定位置,当我们从factorial(n)内部调用factorial(n-1)时,递归调用将覆盖调用方上下文中的任何变量。在上述代码片段中定义的阶乘函数中,如果我们不将存储类指定为automatic,则n和结果factorial都将被对阶乘(n-1)的递归调用覆盖。因此,变量n将连续被覆盖为n-1n-2n-3,依此类推,直到我们达到终止条件n=1。终止对factorial的递归调用将为n分配一个值1,当递归展开时,factorial(n-1)*n将在每个阶段计算为1

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


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

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

如果不使用automatic,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

对于(int i=0;i我提出如下一个示例(使用fork…join_none):

Ex.1(非使用自动):值输出将为“3”。因为我在退出for循环后获取最新值,所以我存储在静态内存位置。这可能是代码中的错误

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

对于(int i=0;我通常会问更具体的问题。自动变量类似于C/C++中任何局部声明的变量。Verilog中的非自动变量通常类似于C/C++中的静态变量。
initial begin   
     for( int i =0; i<=3 ; i++)
        fork
          automatic int k = i;
          $write ("%d ", k);
        join_none 
    end