1. 程式人生 > 其它 >UVM中主要的三種virtual

UVM中主要的三種virtual

技術標籤:IC驗證

目錄

1、virtual class

2、virtual function/task

3、virtual interface

微信公眾號


​ virtual在uvm是一個經常看到的關鍵字,這個關鍵字與OOP三大特性(封裝,繼承,多型)中的多型特性息息相關,下面主要介紹一些virtual的三種常見用法。

通過virtual宣告的類,介面,任務與函式,其本身自帶一些方法或者函式。後續的例化或者擴充套件可以對原有的內容進行增加或者修改,從而實現同一函式不同方法的多種形態。

1、virtual class

不能被直接例化的類被定義為虛類,也就是說這都是概念類,沒有能直接對應的實體,只能被擴充套件(過載)後例項化。

比如動物就是虛類,而人類可以被理解為可以直接例化的實類。SV中一般用這個定義最基層的類,防止這些類被錯誤使用。

虛類中的方法通常使用關鍵字 " pure virtual " 純虛方法。同時OOP規定,只要class中存在一個沒有被實現的pure function,就不允許例化這個class。

UVM中一個顯著虛類是uvm_void:裡面不包含任何成員變數以及函式,是所有其他UVM類的基類。

virtual class uvm_void;endclass

2、virtual function/task

這種使用對應著面向物件中多型的概念。以下SV語法說明自帶的例子很好的解釋了這種用法

class BasePacket;   intA = 1;         intB = 2;                                                            function void printA;                                                 $display("BasePacket::A is %d", A);                                endfunction: printA                                               
virtual function void printB; $display("BasePacket::B is %d", B); endfunction: printB endclass: BasePacket class My_Packet extendsBasePacket; intA = 3; intB = 4; function voidprintA; $display("My_Packet::A is %d", A); endfunction: printA virtual function voidprintB; $display("My_Packet::B is %d", B); endfunction: printB endclass: My_Packet BasePacket P1 = new; My_Packet P2 = new; initial begin P1.printA; // displays 'BasePacket::A is 1' P1.printB; // displays 'BasePacket::B is 2' //以上都是普通的函式呼叫,沒有特別 P1 = P2; // P1 has a handle to a My_packet object //這裡把子類的指標賦值給基類指標 P1.printA; // displays 'BasePacket::A is 1' //printA非虛擬函式,沒有過載,仍然執行基類操作 P1.printB; // displays 'My_Packet::B is 4' – latest derived method//printB虛擬函式,發生動態過載,執行子類操作 P2.printA; // displays 'My_Packet::A is 3' P2.printB; // displays 'My_Packet::B is 4' end

結論:對一個virtual函式,通過指標被呼叫時,是由這個指標指向的物件的決定呼叫哪個具體的函式,而不是指標的型別決定。反之,如果基類函式宣告時沒有加virtual關鍵字,那麼該函式被呼叫時是由指標型別決定應該呼叫哪個具體函式。

當父類定義了virtual時,在子類中呼叫某task/function時,會先查詢在子類中是否定義了該 task/function,如果子類沒有定義,則在父類中查詢。父類未定義virtual時,只在被呼叫的指標型別中查詢,沒有定義就是編譯器報錯。

從以上可以看出,如果子類與基類的同一個函式不使用virtual,則基類與子類定義不會動態過載,p2的函式對p1指標是不可見的。如果子類與基類的同一個函式使用virtual(只需要在父類中定義virtual即可),則子類定義會動態過載基類定義,p2的函式對p1指標是可見的。

這種動態的過載是很有用的。例如可以用一個基類的指標陣列來儲存所有子類物件的指標,然後呼叫基類的某個虛擬函式,實現所有子類物件的某個函式的依次執行。

pure virtual function/task

純虛方法一般對應放在虛類中,只提供函式的介面,不提供具體實現,也就是說必須有一個子類定義這個實現,否則會編譯報錯,當然非虛類也可以定義這個,比如上列中p1的printB若定義為虛擬函式,則必須有p2的printB來實現他。

3、virtual interface

SV中定義了interface,但是一般這種interface都是在實體的module中進行例化,用以方便連線各個埠。class的例化一般在模擬啟動後進行,所以SV不支援在class中直接例化interface,而是要使用一個interface指標。這就是virtual interface。這樣方便這個虛介面在模擬啟動後,根據需要連線到TB中某個地方。這種虛介面一般在類中定義,然後通過某種機制由TB把DUT中一組具體的訊號傳遞到類中使用。在UVM這是標準用法。

interface SBus; // A Simple bus interfacelogic req, grant;logic [7:0] addr, data;endinterfaceclass SBusTransctor; // SBus transactor class  virtual SBus bus; // 這裡只能定義虛介面  function new( virtual SBus s );    bus = s; // initialize the virtual interface  endfunction  task request(); // request the bus    bus.req <= 1'b1;  endtask  task wait_for_bus(); // wait for the bus to be granted    @(posedge bus.grant);  endtaskendclassmodule devA( Sbus s ) ... endmodule // devices that use SBusmodule devB( Sbus s ) ... endmodulemodule top;SBus s[1:4] (); // instantiate 4 interfacesdevA a1( s[1] ); // 將實際介面與被測物件連線devB b1( s[2] );devA a2( s[3] );devB b2( s[4] );initial beginSbusTransactor t[1:4]; // create 4 bus-transactors and bindt[1] = new( s[1] ); //將實際介面作為引數傳給物件的粒化t[2] = new( s[2] );t[3] = new( s[3] );t[4] = new( s[4] );endendmodule

微信公眾號

建立了一個微信公眾號“Andy的ICer之路”,此公眾號主要分享數字IC相關的學習經驗,文章主要在公眾號上發,csdn會盡量同步更新,有興趣的朋友可以關注一下!