SV中的shallow copy 和 deep copy
今天我們結合幾個例子講一講SV中句柄和對象的概念,以及對象的複製都有哪些玄機。
對於verilog來說,不存在對象的概念,那麼下面的代碼很好理解:
integer a,b;a = 5;b = a;a = 4;
第一行聲明了兩個變數,此時他們的初始值為X;第二行將a賦值為5;第三行將a的值賦值給b,b也等於5;最後a的值變為4,但b的值依舊為5。
如果這時候我們把a和b由整數換成對象會出現什麼情況呢?請看如下代碼
Packet p1;
這裡聲明了一個Packet類型的變數(可以把 Packet 看成類似於前例中 integer a 中的 integer),p1專業點的稱呼就叫句柄,可以理解為一個指針,指向一塊內存區域,這塊區域只能存放Packet類的數據類型。此時還未使用構造函數new,所以p1並沒有指向任何實際的對象。也就是說變數p1的值還是初始值 null。如下圖所示:
p1 = new;
new的調用會創建Packet類的實例,這時內存里生成了一塊Packet類的數據類型,此時p1的值就是這個Packet對象所佔據的內存的起始地址。
如果聲明另一個變數並且將舊的句柄p1賦值給該變數:
Packet p2;p2 = p1;
此時內存中還是只有一個Packet類型的對象,但是可以用p1 或 p2的名字指代。
接下來為了方便解釋shallow copy和deep copy的區別,我們假定Packet內部包含另一個class A的句柄a:
class A;integer j=5;endclassclass Packet;integer i = 1;A a;function new();a = new();endfunction...endclassPacket p1 = new;
結果如下圖所示, p1.a這個句柄指向了一片內存空間(假設起始地址是0xffff_abcd),這裡存放了一個class A類型的對象。
假如,接下來又有一段代碼如下:
Packet p2;p2 = new p1;p1.i = 9; p1.a.j = 8;
p2再一次使用了new,因此創建了一個新的對象p2. 它的屬性是從p1複製過去的。這種操作稱之為shallow copy,也就是簡易複製。所有的變數,包括integers,strings, instance handles等等都被複制過去。
p2.a 的值和 p1.a也是相等的。也就是說 p2.a 仍然是指向了存放在內存地址0xffff_abcd中的 class A類型的對象。
結合下圖,就不難理解此時 p2.i == 1,p2.a.j == 8 了。
具體來說,一個shallow copy將執行以下的操作:
1)生成一個被複制的類的對象。該操作不會調用對象的構造函數,也不會對任何變數進行初始化操作。
2)所有的類的屬性,包括內部用於進行隨機操作的狀態(用於隨機操作的內部狀態包括:隨機數生成器狀態,約束的constraint_mode狀態,隨機變數的rand_mode狀態和randc隨機變數的循環狀態)和coverage都被複制到了新的對象中。類中包含的對象的句柄也被複制了,包括covergroup對象的句柄。嵌入的covergroup是個例外(在class內部定義的covergroup)。在新的對象中嵌入的covergroup的句柄會被賦值為null。
3)句柄指向這個新生成的對象的句柄將被賦值給等號左邊的變數(這裡為p2)。
注意:shallow copy並不會創建新的coverage對象(covergroup實例)。因此新對象的屬性並未被任何covergroup覆蓋。
假如我們希望複製不要藕斷絲連的話那麼就要使用deep copy,或者說full copy。這在SV中通常需要用戶自己編寫copy函數。
以剛才的packet為例,對於非簡單的類,應該創建copy函數,通過調用類所包含的所有對象的copy函數完成deep copy操作。
class A;integer j= 5;function A copy(); copy = new; copy.j = j;endfunctionendclass
假如調用a.copy,函數就會返回一個A的句柄, 這個句柄指向了新new出來的A類型的對象.
class Packet;integer i = 1;A a;function new();a = new();endfunctionfunction Packet copy(); copy = new; copy.i = i; copy.a = a.copy();endfunctionendclass...p1 = new;p2 = p1.copy;
結果如下圖所示,p2.a 此時所指向的對象就和p1.a不同了。
deep copy完成之後p1和p2就不會互相干擾了,對p1的更改就不再會影響p2了。
如果在SV中要deep copy的話,就得為所有包含的類都準備好copy函數,既容易出錯,工作量又大。好消息是UVM已經內建了copy以及clone操作,可以將你從手寫copy中解放出來,我們會在後續的文章中講解其中的細節,敬請期待。
推薦閱讀: