SystemVerilog有着和其他oop語言一樣的數據/方法的開放性控制特性,在以下做詳細闡述:
對於公有性和私有性:
- public: 默認為public,子類和類外皆可訪問。
- local:表示的成員或方法只對該類的對象可見,子類以及類外不可見。
- protected: 表示的成員或方法對該類以及子類可見,對類外不可見。
對於靜態與動態:
由於SystemVerilog刻畫的是軟件的世界,所以默認所有的變量為dynamic。而在Verilog中,所有變量默認的上static屬性,因為Verilog描繪的是硬件的世界,是實實在在的電路,電路不能動態構成。
- static: 靜態變量,此變量被這個類的所有實例所共享。
- dynamic: 動態變量,無需聲明,變量默認為動態變量。
靜態變量和動態變量的區別
class Transaction; static int count = 0; int id; function new(); id = count ++; endfunction endclass Transation t1,t2; initial begin t1 = new(); //Frist instantiation,id=0,count=1 t2 = new(); //Second instantiation,id=1,count=2 $display("Second id=%d, cound = %d, t2.id, t2.count”); end
在上述代碼中,無論創建了多少個Transcation對象,靜態變量count只有一個,可以認為count是保存在硬件域中的。而變量id是動態的,所以每個Transcation都有自己的id變量。
在實際設計中,使用ID域來跟蹤對象是一個非常好的辦法,SystemVerilog不能輸出對象的地址,但可以創建ID域來區分對象。
通過類名訪問靜態變量
除了上述使用句柄來引用靜態變量,還可以直接使用類名引用靜態變量,只需在類名后加入:: ,即域的類作用域操作符。
class Transaction; static int count = 0; ... endclass initial class run_test(); $display("%d transation were created", Transcation::count); end
節約內存為導向
靜態變量通常在聲明時初始化,不能簡單地在類的構造函數中初始化靜態變量,因為每創建一個新的對象都會調用構造函數。總之在實際操作中,我們要保證在創建第一個對象之前就已經初始化了靜態變量。
靜態變量的設置是以優化內存為導向的,如下面的代碼,如果不設置靜態句柄,那么每次例化Transaction都會分配一次cfg的空間,沒有必要。
class Transaction; static Config cfg; MODE_E mode; function new(); mode = cfg.mode; endfunction endclass Config cfg; initial begin cfg = new(MODE_ON); Transcation::cfg = cfg; .... end
SystemVerilog不允許靜態方法讀取非靜態變量,下面代碼示例了靜態方法的調用。
class Transationl static Config cfg; static int count = 0; int id; //顯示靜態變量的靜態方法 static function void display_statics(); $dislplay("Transaction cfg.mode = %s, count = %0d",cfg.mode.name(),count); endfunction endclass Config cfg; initial begin cfg = new(MODE_ON); Transaction::cfg = cfg; Transaction::display_statics(); //調用靜態方法 end