1. 程式人生 > 其它 >SystemVerilog中的類和物件

SystemVerilog中的類和物件

技術標籤:SystemVerilogverilogsystemverilog

類和物件的概述

1、類和物件

  • 類是將相同的個體抽象出來的描述方式,物件時實體,具備有獨立行為的能力。
  • 具有相同屬性和功能的物件屬於同一類,而不同的類之間可能有聯絡或者沒有聯絡。
  • C語言中,程式設計基於過程方法,在Verilog中提供了笨拙的類物件程式設計可能性,即在module中定義方法,而後呼叫module例項中的方法。
  • Verilog的module+method的方式與SV的class定義有本質上的差別,即面向物件程式設計的三要素:封裝、繼承、多型。
  • 類的定義核心即是屬性宣告和方法定義,所以類是資料和方法的自洽體,即可以儲存資料和處理資料。這是與struct結構體在資料儲存方面的重要區別,因為結構體只是單純的資料集合,而類可以對資料做出符合需要的處理。

2、驗證使用OOP的意義

  • 驗證環境的不同元件功能和所需要處理的資料內容是不相同的。
  • 不同環境同一型別的元件其所具備的功能和資料內容是相似的。
  • 基於以上兩點,驗證世界的各個元件角色明確、功能分立,使用面向物件程式設計與驗證世界的構建原則十分符合。

3、OOP的概念要素

  • Class類:基本模組包括成員變數和方法。在Verilog中module也可以包含變數和方法,只不過它是“硬體盒子”,class是“軟體盒子”。
  • Object物件:類的例項。Verilog中module也可以例化,這是“硬體”例化,在SV中可以使用class來例化,這是“軟體”的例化。
  • Handle控制代碼(指標):用來指向物件的指標。在Verilog中,可以通過層次化的索引來找到結構中的設計例項,而在SV的物件索引時,需要通過控制代碼來索引物件的變數和方法。
  • Property屬性(變數):在類中宣告的儲存資料的變數。在Verilog中,它可以是wire或者reg型別。
  • Method方法:類中可以使用task或者function來定義方法以便處理自身或者外部傳入的資料。Verilog中可以在module中定義task/function,也可以使用initial/always處理資料。

4、建立物件

Verilog的例化和SV的class例化的差別:

  • 二者的共同點在於使用相同的“模板”來建立記憶體例項
  • 不同點在於Verilog的例化是靜態的,即在編譯連結時完成,而SV中class例化是動態的,可以在任意時間點發生
  • Verilog中沒有控制代碼的概念,即只能通過層次化的索引方式A.B.sigx,而SV中的class通過控制代碼可以將物件的指標賦予其它控制代碼,使得操作更加靈活。

在建立物件時,需要注意什麼是宣告,什麼是建立

Transaction tr;		//宣告控制代碼
tr = new();			//建立物件

建立物件時,可以通過自定義的構建函式來完成變數的初始化和其它初始操作。構建函式new()是系統預定義函式,不需要指定返回值,函式會隱式地返回例化後的物件指標。

class Transaction;
	logic[31:0] addr, crc, data[8];
	function new();
		addr = 3;
		foreach(data[i])
			data[i] = 5;
		endfunction
enclass

構建函式也可以定義多個引數作為初始化時外部傳入數值的手段。

class Transaction;
	logic[31:0] addr = 'h10;
	logic[31:0] crc, data[8];
	function new(logic[31:0] a=3, d=5);
		addr = a;
		foreach(data[i])
			data[i] = d;
	endfunction
endclass

initial begin
	Transaction tr;
	tr = new(10);

5、控制代碼的傳遞

物件是指的儲存空間,而控制代碼指的是空間指標。也就是說在建立了物件之後,該物件的空間位置不會改變,而指向該空間的控制代碼可以有多個。

Transaction t1, t2;		//宣告控制代碼
t1 = new();				//例化物件,將其控制代碼賦予t1
t2 = t1;				//將t1的值賦予t2,即t1和t2指向同一個物件
t1 = new();				//例化第二個物件,並將其控制代碼賦予t1

在這裡插入圖片描述

6、物件的銷燬

  • 軟體程式設計的靈活在於可以動態地開闢使用空間,在資源閒置或者不再需要時,可以回收空間,這樣使得記憶體空間保持在一個合理的區間。
  • C++語言中的類除了有構建函式,還有解構函式。解構函式的作用即在於手動釋放空間,但這對程式設計人員的細心和經驗提出了要求;JAVA和Python等後續面嚮物件語言則不再需要手動定義解構函式並且釋放空間,空間的回收利用也是自動的。
  • SV中也採用了自動回收空間的處理方式,自動回收空間的基本原理是,當一個物件,在整個程式中沒有任何一個地方再“需要”它時,便會被“銷燬”。這裡的“需要”的意思指的是有控制代碼指向該物件。

7、控制代碼的使用

  • 控制代碼可以用來建立多個物件,也可以前後指向不同物件。
Transaction t1, t2;		//宣告控制代碼
t1 = new();				//建立物件並將其指標賦予t1
t2 = new();				//建立物件並將其指標賦予t2
t1 = t2;				//將t2的值賦予t1,t1和t2指向同一物件,t1之前指向的物件被釋放
t2 = null;				//將t2賦值為空,此時指標懸空,懸空的指標很危險
  • 可以通過控制代碼來使用物件中的成員變數或者成員方法。
Transaction t;
t = new();
t.addr = 32'h42;
t.display();

8、靜態變數

  • 與硬體域例如module、interface不同的是,在class中宣告的變數其預設為型別為動態變數,即其宣告週期在模擬開始後的某時間點開始到某時間點結束。
  • 使用關鍵字static來宣告class內的變數時,則其為靜態變數。靜態變數的生命週期開始於編譯階段,貫穿於整個模擬階段。
  • 如果在類中聲明瞭靜態變數,可以直接引用該變數class::var,或者通過例化物件引用object.var。類中的靜態變數宣告以後,無論例化多少個物件,只可以共享一個同名的靜態變數。

9、靜態方法

  • 在class中定義的方法預設型別是動態方法,也可以通過關鍵字static修改為靜態方法。
  • 靜態方法內可以宣告並使用動態變數,但是不能使用類的動態成員變數。原因是因為在呼叫靜態方法時,可能並沒有建立具體的物件,也因此沒有為動態成員變數開闢空間,因此在靜態方法中使用類的動態成員變數是禁止的,可能會造成記憶體洩漏,但是靜態方法可以使用類的靜態變數,因為靜態方法同靜態變數一樣在編譯階段就已經分配了記憶體空間。