在簡單的測試平臺里,component之間通過變量或者config_db機制通信是可行的,但是如果在復雜測試平臺中依然使用這種耦合性很強的方式通信的話,就不太行了。
因此,UVM提供了TLM這樣的概念。接下來將會從需求出發,逐步引入port、export、imp、analysis端口、uvm_analysis_imp_decl宏以及FIFO等。
1 典型UVM驗證平臺
2 一對一如何通信(一般方法)
說明:這里以monitor和scoreboard之間的通信為例
- 方法一 使用全局變量 :在monitor里對此全局變量進行賦值, 在scoreboard里監測此全局變量值的改變
- 問題:所有模塊都可以修改全局變量,合作中他人誤修改可能導致致命bug
- 方法二 A中pulic變量+B對模塊A的引用 :scoreboard中使用public類型的變量,然后monitor中使用指向scoreboard的指針對該變量進行賦值
- 問題:monitor可以修改scoreboard中所有public類型變量
- 方法三 config機制(類似于在指定模塊作用域構建了全局變量) :在base_test中實例化一個config_object,并將其指針通過config_db傳遞給scoreboard和monitor,然后兩個模塊就可以對該config_object中變量進行操作
- 問題1:需要引入一個專門的config_object類
- 問題2:一定要有base_test(父模塊)這個第三方的參與,這樣就不能保證某一個從base_test派生而來的類會不會改變這個config_object類中某些變量的值
現有機制更多通信問題
- 通信需要考慮阻塞和非阻塞的處理方式
- 如果scoreboard主動要求向monitor請求數據, 這樣的行為方式使用systemverilog搭建會非常復雜
3 一對一如何通信(引入TLM)
3.1 新概念
- TLM:是Transaction Level Modeling( 事務級建模) 的縮寫,是將某一特定功能的一組信息封裝在一起成為一個類,通過這個類(即事務)進行通信。
- 三個端口:PORT(發起者)、EXPORT(接收者)、IMP(執行者)
- 端口方法:put/get/transport/peek/get_peek
3.2 使用舉例
說明:以blocking_put系列端口,PORT>EXPORT>IMP的連接舉例說明
- A|PORT發起端口操作put :task A::main_phase中A_port.put(tr);
- 建立A|PORT和B|EXPORT的連接 :AB的頂層模塊my_env::connect_phase中:A_inst.A_port.connect(B_inst.B_export);
- 建立B|EXPORT和B|IMP的連接 :B::connect_phase中:B_export.connect(B_imp);
- 建立B|IMP和B中操作put的連接 :B模塊定義中:uvm_blocking_put_imp#(my_transaction, B) B_imp;
- B中操作put的實現 :function void B::put(my_transaction tr);
注意:EXPORT可以省略,即 PORT直接連接到IMP
4 一對多如何通信(引入analysis端口)
4.1 使用舉例
-
A|analysis_port發起端口操作write :task A::main_phase中A_ap.write(tr);
-
建立A|analysis_port和(B或C)|analysis_imp,的連接 :A(B或C)的頂層模塊my_env::connect_phase中
A_inst.A_ap.connect(B_inst.B_imp);
A_inst.A_ap.connect(C_inst.C_imp);
-
建立(B或C)|analysis_imp和(B或C)中操作write的連接 :(B或C)模塊定義中:
uvm_analysis_imp#(my_transaction, B) B_imp;或
uvm_analysis_imp#(my_transaction, C) C_imp;
-
(B或C)中操作write的實現 :
function void B::write
function void C::write
5 多IMP的模塊的通信問題
5.1 問題描述
一個component(my_scoreboard)內有多個IMP時,依據前面知識,component(my_scoreboard)中只能有一個write方法,這如何處理兩個imp(來自輸出監視monitor 和 來自參考模型model)
5.2 解決方法
方法一:使用宏uvm_analysis_imp_decl
通過宏uvm_analysis_imp_decl,在component(my_scoreboard)中添加不同的后綴以區分兩個imp的處理邏輯。具體實現如下:
-
通過宏uvm_analysis_imp_decl聲明兩個后綴_monitor和_model
uvm_analysis_imp_decl(**_monitor**)
uvm_analysis_imp_decl( _model ) -
使用帶后綴的analysis_imp端口類聲明兩個analysis_imp端口
uvm_analysis_imp**_monitor**#(my_transaction, my_scoreboard) monitor_imp;
uvm_analysis_imp**_model**#(my_transaction, my_scoreboard) model_imp;
-
使用帶后綴的write方法實現analysis_imp對信號的處理邏輯
extern function void write**_monitor**(my_transaction tr);
extern function void write**_model**(my_transaction tr);
-
宏uvm_analysis_imp_decl的特性會讓 相同后綴的 analysis_imp端口 和 write函數 對應上
function void my_scoreboard ::write_model(my_transaction tr);
function void my_scoreboard ::write_monitor(my_transaction tr);
方法二:使用FIFO通信
將imp的實現邏輯放在FIFO中,而component(my_scoreboard)作為PORT端,主動請求get到FIFO中的數據,關鍵代碼如下:
// my_scoreboard類中
uvm_blocking_get_port #(my_transaction) exp_port;
uvm_blocking_get_port #(my_transaction) act_port;
// task my_scoreboard::main_phase中
exp_port.get(get_expect); // 獲取的數據存到get_expect中
act_port.get(get_actual); // 獲取的數據存到get_actual中
// my_env類中
uvm_tlm_analysis_fifo #(my_transaction) agt_scb_fifo;
uvm_tlm_analysis_fifo #(my_transaction) agt_mdl_fifo;
uvm_tlm_analysis_fifo #(my_transaction) mdl_scb_fifo;
// function void my_env::connect_phase中
i_agt.ap.connect(agt_mdl_fifo.analysis_export);
mdl.port.connect(agt_mdl_fifo.blocking_get_export);
mdl.ap.connect(mdl_scb_fifo.analysis_export);
scb.exp_port.connect(mdl_scb_fifo.blocking_get_export);
o_agt.ap.connect(agt_scb_fifo.analysis_export);
scb.act_port.connect(agt_scb_fifo.blocking_get_export);
注意:FIFO中的analysis_export和blocking_get_export雖然名字中有關鍵字export, 但是其類型卻是IMP
5.3 用FIFO還是用IMP
個人推薦使用FIFO,尤其是對于使用端口數組的情況。因為ap與imp直接相連不能使用for循環(write函數需要一個一個寫,沒法用數組),會導致代碼量增加,理解困難。
-
UVM
+關注
關注
0文章
182瀏覽量
19174 -
TLM
+關注
關注
1文章
32瀏覽量
24753 -
IMP
+關注
關注
0文章
11瀏覽量
8412 -
FIFO存儲
+關注
關注
0文章
103瀏覽量
5986
發布評論請先 登錄
相關推薦
評論