Transactions
在UVM中,transaction是一個類對象,它包含了建模兩個驗證組件之間的通信所需的任何信息。一個用來傳輸信息的簡單總線協議transaction建模示例如下:
class simple_trans extends uvm_sequence_item; rand data_t data; rand addr_t addr; rand enum {WRITE,READ} kind; constraint c1 { addr < 16’h2000; } ... endclass
transaction對象包含變量、約束以及生成和操作事務所需的其他字段和方法。封裝在transaction中的信息表明了建模的抽象級別。上面的simple_trans可以被擴展為包含更多的信息(例如要注入的等待狀態的數量、傳輸的大小或其他屬性),還可以對此transaction擴展以增加更多定向約束。
Transaction-Level 通信
Transaction-level接口定義了一組使用transaction作為參數的方法。TLM port定義了一組方法,與之相連的TLMexport提供了這些方法的實現(implementation)。
基本TLM通信
最基本的transaction-level操作就是一個組件將一個transactionput給另一個組件上。
producer 上的方框表示一個port,consumer上的圓圈表示export。
producer生成transactions并將其發送出去:
class producer extends uvm_component; uvm_blocking_put_port #(simple_trans) put_port; // 1 parameter function new( string name, uvm_component parent); put_port = new(“put_port”, this); ... endfunction virtual task run(); simple_trans t; for(int i = 0; i < N; i++) begin // Generate t. put_port.put(t); end endtask
uvm_*_port參數化為將要通信的transaction類型。put()調用的實際實現由consumer提供。
class consumer extends uvm_component; uvm_blocking_put_imp #(simple_trans, consumer) put_export; // 2 parameters ... task put(simple_trans t); case(t.kind) READ: // Do read. WRITE: // Do write. endcase endtask endclass
uvm_*_imp接受兩個參數:transaction的類型和聲明方法實現的對象類型。producer中的put()調用將阻塞,直到consumer的put實現完成。除此之外,producer的操作完全獨立于put的實現(uvm_put_imp)。事實上,consumer可以被另一個也實現了put方法的組件所取代,producer可以繼續以完全相同的方式工作。
所以說,TLM促進了驗證環境開發的模塊化,因為一個清晰的接口定義,所以組件很容易復用。
相反的操作是get。
在這種情況下,consumer通過其get端口向producer請求transactions:
class get_consumer extends uvm_component; uvm_blocking_get_port #(simple_trans) get_port; function new( string name, uvm_component parent); get_port = new(“get_port”, this); ... endfunction virtual task run(); simple_trans t; for(int i = 0; i < N; i++) begin // Generate t. get_port.get(t); end endtask
get()實現由producer提供。
class get_producer extends uvm_component; uvm_blocking_get_imp #(simple_trans, get_producer) get_export; ... task get(output simple_trans t); simple_trans tmp = new(); // Assign values to tmp. t = tmp; endtask endclass
與上面put()一樣,get_consumer的get()將阻塞,直到get_producer的方法完成。在TLM術語中,put()和get()是阻塞方法(blocking)。
在這兩個示例中,都有一個進程在運行,控制流都是從port傳遞到export,而數據流都是從producer到consumer。
進程間通信
在上?的put ?例中,consumer只有在其 put() ?法被調?時才會處于活動狀態。在許多情況下,組件可能需要獨?運?,其中producer在?個進程中創建transactions,?consumer需要在另?個進程中對這些transactions進?操作。
UVM 提供了 uvm_tlm_fifo來促進這種進程間通信。uvm_tlm_fifo實現了所有的TLM接??法,因此producer將transaction放?uvm_tlm_fifo,?consumer則獨?從fifo中獲取transaction,如下圖所?。
當producer向fifo中put一個transaction時,如果fifo已滿則阻塞,否則成功將transaction放入fifo并立即返回。如果fifo中存在transaction,get操作將立即返回這個transaction,并且從fifo中刪除這個transaction,否則它將阻塞直到能夠獲取一個transaction。
因此,兩次連續的get()將向consumer產生不同的transaction。而 peek()方法返回transaction的副本而不刪除它,所以兩次連續的peek()將返回同一transaction的副本。
阻塞(Blocking)和非阻塞(Nonblocking)
到目前為止我們看到的接口都是阻塞的(blocking),阻塞任務不允許失敗,阻塞執行直到它們完成。阻塞期間,仿真時間會繼續向后走。相反,非阻塞任務調用會立即(同一個delta cycle,不消耗仿真時間)返回。所以,在 UVM 中,非阻塞任務調用就是一個functions。
class consumer extends uvm_component; uvm_get_port #(simple_trans) get_port; task run; ... for(int i=0; i<10; i++) if(get_port.try_get(t)) //Do something with t. ... endtask endclass
如果存在transaction,它將在參數中返回,函數調?本?將返回TRUE。如果不存在transaction,函數將返回FALSE。類似地,還有try_peek()和try_put()?法 。
連接Transaction-Level組件
在為transaction-level組件定義了ports和exports之后,它們之間的連接是通過上一級驗證組件中的connect()方法完成的。在驗證環境中,ports和exports之間的 connect() 調用建立peer-to-peer連接或者層次化的連接,最終連接都終止于put()或者get()方法的實現。當組件調用
put_port.put(t);意味著它實際上調用
target.put_export.put(t);其中target是port連接到的組件。
Port/Export 兼容性
UVM中TLM 通信的另一個優點是在運行用例前檢查所有TLM 連接的兼容性。為了使連接有效,export必須提供對應的方法并且數據參數類型相同。
blocking_put_port可以連接到 blocking_put_export 或 put_export,blocking_put_export需要實現put()方法的實現,put_export 還提供 try_put() 和 can_put()的實現。
???
審核編輯:劉清
-
UVM
+關注
關注
0文章
182瀏覽量
19231 -
TLM
+關注
關注
1文章
32瀏覽量
24780 -
FIFO存儲
+關注
關注
0文章
103瀏覽量
6037
原文標題:UVM TLM 的基本概念
文章出處:【微信號:芯片驗證工程師,微信公眾號:芯片驗證工程師】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論