2015-06-22 70 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