1. 程式人生 > 實用技巧 >文章UVM and C – Perfect Together的解讀與思考

文章UVM and C – Perfect Together的解讀與思考

解讀UVM and C – Perfect Together

文章獲取方式:路科驗證--->資源--->DVCon2018-USA.zip--->08_3

http://rockeric.com/resource/paper/

文章主要內容:使用DPI-C整合UVM bench和C code時,遇到的最大問題在於:域。DPI-C的域可以是module例項,interface例項或全域性根域(the global root scope)。UVM bench沒有這種域,它是基於動態類的,而不是基於靜態例項的,但C是基於靜態的。

文章詳細介紹瞭如何實現從圖1=>圖2=>圖3

The SystemVerilog Interface

Interface是兼有“軟硬體”的特性,即interface可以例項化,使用virtual interface可以在UVM bench中使用interface。因此選擇interface作為DPI-C的域最為合適。

Interface中定義了SV一側export到C一側的方法,sv_hello和sv_start_sequenceC。其中,聲明瞭 sequencer控制代碼,再使用動態轉換,然後呼叫sequencer內的同名方法。

The UVM Agent

其中,這2行程式碼很重要。

這樣,interface和sequencer之間就建立了聯絡。第一句,interface中的uvm_sequencer_base型別的sqr被初始化,才能在interface中呼叫sequencer內的方法。第二句,sequencer中的interface被初始化,可以在sequencer中通過DPI-C呼叫C一側的方法。

The UVM Sequencer

任務c_start_thread()是通過DPI-C呼叫C一側的方法,使用fork-join並行4個執行緒。任務sv_start_sequenceC是由C code呼叫,啟動sequence後把結果輸出到C一側。

The UVM Sequence

上圖,sequenceA中,通過interface呼叫C一側的方法,c_hello和c_datatype_array_of_10_int。

Threaded Code

在sequencer的任務c_start_threads()中,4個執行緒並行執行,但是每次只執行1個執行緒。當1個執行緒啟動時,它就得到了控制權,而另一個執行緒得到控制權的方法是:當前執行緒將控制權放棄或者“讓步”。“讓步”的形式表現為執行#delay, wait() , a @(posedge clk)等時間語句。正是因為有這種“讓步”行為,才能讓4個執行緒看似並行執行。

C code中的“jj”是一個全域性變數,但不是一個安全的變數。4個執行緒並行執行過程中,“jj”的值會被不同的執行緒改變,這不是我們所期望的。

左邊是“讓步”控制權,右邊是放棄控制權。

圖中,紫紅色表示C code一側啟動的sequenceC,紫色和藍色分別是SV一側啟動的sequenceA,sequenceB。

在同一個sequencer上,掛載了sequenceA,sequenceB,sequenceC,使用並行語句,出現“讓步”行為,如波形圖所示。

C code在其他場景下使用:

Stimulus Generator:資料由C一側產生,通過DPI-C送到SV一側。

Data checker:在C一側產生預測資料,將監測到的DUT輸出送到C一側進行對比。

Bus transfer generator:C一側傳送匯流排讀寫請求。

總結

這篇文章詳細描述了將interface作為域,通過DPI-C整合UVM和C的例子。將interface作為域可以 消除整合和連線問題,最重要的是它兼有“軟硬體”的特性。

思考:

A. interface前加virtual和不加的區別?

Interface是“硬體”特性,類似於module可以例化;virtual interface是“軟體”特性,在UVM bench中是指向例化interface的指標。因此,interface才有“軟硬體”的特性。

B. 除了interface外,還有哪些地方可以作為域?

1.Module

Import:將DPI-C的實現放在C的class裡,宣告並例化C class,封裝C指標的呼叫,在SV一側的元件(run_phase/main_phase)中直接呼叫封裝後的task/function。

Export:在module中似乎沒法呼叫。

2.Package

將DPI-C的實現(import和export)放在UVM的class裡,再把這個class放在package中,在UVM bench裡建立這個class,使用控制代碼呼叫DPI-C的task/function。

C. 並行執行緒的本質?

使用fork-join(join_none)執行並行執行緒,其本質是當前執行緒在執行#delay, wait() , a @(posedge clk)等時間語句時,將控制權交給其他執行緒,使得所有執行緒看似並行執行。

D. 全域性變數和區域性變數的使用區別?

文中的例子表明,在執行並行執行緒時,並行執行緒涉及到的全域性變數是不安全的,需要使用區域性變數。

E. Sequencer的仲裁

文中的例子表明,多個sequence(有繼承關係)掛載到同一個sequencer上,sequencer需要仲裁。仲裁mode預設是SEQ_ARB_FIFO,可以在test層用函式set_arbitration改變仲裁mode。

注:以上思考完全是個人理解,如有錯,歡迎留言!