tlm模塊,用來在不同模塊之間實現實時通信,主要基於兩個定義在通信雙方的port類來實現。
兩個port之間,通過connect函數,來拿到雙方的class指針,進而調用對方的function。
但是uvm規定,控制流(調用function與被調用方)只能按一定的方向來執行,所以只有某一類port類可以調對應port的function。
由於imp所在的class中,每次通信可能實現的function不同,而且做virtual function的重載也會引入新的class,
所以imp中的port類,在定義時,就調用parent中對應的function,這樣在parent的class中就必須實現相應的function。
tlm模塊的類圖:
interface class,實現put,get,write,transparent等方法定義,
有兩種,tlm_if_base,用在general的object或component class中,
sqr_if_base,用在driver和sequencer class中,
port_component,是基於uvm_component的extend,主要為了方便調用report機制,
port_base,定義connect,binding等function,實現內部provider,provided對象queue的初始化,
port_base與port_component class中互有對方的指針變量,可以實現對方的function,
但是在應用過程中,port_component只是提供了report的訪問。
port/export/imp class,是實際應用中的class,都是通過macros來進行實現的。
其中只定義了該port對應的function和一個new函數。
從實現中的連接方式來看,port,export只是命令的傳遞者,imp是命令的執行者,其中實現了具體的function---調用parent相應的function。
所以,port,export可以被定義很多層級,來方便傳遞,都不影響最終的執行。
代碼中表現為,port調用自己provider的put等函數,即export的provider的put等函數,即imp中調用的parent的put函數。
uvm還規定了自己的連接規則,定義在port_base connect和check_relation function中。每次進行connect函數調用的時候,都會檢查。
error類型,1) mask_if不同,用來區分不同的port組;
2) 發起connect的是imp;
3) export連接port;
warning類型,1)port可以連接port,必須是child port連接parent的port;
2)port連接export,imp,必須是同一hierarchy;
3)export連接export,imp,必須是parent export,連接child export,imp;
analysis port並沒有這些warning的要求。
從通信方式看,analysis類表示廣播,可以connect多個,實現過程中,遍歷各個port、export queue中的imp;
實現的是無延時的function write;
其他包括sqr_if都是一對一的,只能connect一個,
實現中,在每個port class的new函數中,都規定了該port能夠連接的最小和最大的export,imp,
analysis [0:$],其他的port,只能是1。在resolve_binding的時候,會進行該size的檢查。
從操作行為看,定義的port的function:try_put,can_put,try_get,can_get,try_peek,can_peek,nb_transport,write,
定義的port的task:put, get, peek,transport, (imp中固定function 實現bridge,具體實現與parent class)
sqr_if port中定義的function:item_done,has_do_available,put_response,
定義的task:get_next_item,try_next_item,wait_for_sequences,get,put,peek,
(實現於sequencer,調用於driver)
port_base中的三個重要函數:
1)connect函數,需要顯式調用,必須在end_of_elaboration phase結束之前完成,之后調用會報錯。
2)resolve_binding函數,由uvm_root 在 end_of_elaboration phase開始隱式遞歸調用,所有component中的child都會做檢查。
3)get_if函數,在put,write等函數中被調用,拿到imp_list中的provider的指針,
port_base中的三個重要變量:
1)this_type m_provided_by[string]
this_type m_provided_to[string],存放provider和provided的port_base對象類型,在connect函數被賦值;
2)this_type m_imp_list[string],在resolve_binding函數中,被更新,存放對應provided的對象的類型;
如果provider的size很多,或遍歷之后,都放在imp_list中。
3)this_type m_if,指向第一個m_imp_list中的port類型的對象,
各個port class中的size, min,max,mask_if等配置在new的時候,直接初始化。
analysis min為0,max無限制,
其他port,min為1,max為1,
多個export調用同一個imp時的function重名問題,uvm的解決方法是重新define多個不同的class對象的imp,分別調用各自的不同名稱的function;
使用時,需要先define,也就是定義一個新的class,之后進行正常的connect,在imp調用的時候,會調用write_suffix這樣的function;
從而區分不同的export對應的imp實現。
這樣的imp定義,需要根據mask_if來定義各自的class,因為new的時候,MASK define仍然是和正常的imp相對應的。
export並不需要擔心重名的問題,因為它的function並沒有具體的時候,只是進行imp_list中的遍歷調用,所以function內容都一樣。
fifo部分,只是將多個port類型和一個mailbox封裝在一起,中間保存,傳遞trans。
tlm_fifo_base中,定義了兩個analysis_port,負責將trans,廣播出去;
兩個imp,分別實現,get,put,等等全部的interface function接口;
tlm_fifo中,定義了mailbox,可以在fifo new的時候,顯式指定fifo的深度;默認1
具體實現put,get等函數;(實現並不像parent中的那樣具體);單純寫入mailbox,再用analysis port寫出去;
tlm_analysis_fifo中,只是增加了一個analysis_imp,然后實現try_put;
tlm_fifo中的function,put操作,mailbox,put操作,然后通過put_ap的analysis再發出去;
get操作,mailbox,get操作,然后通過get_ap的analysis再發出去;
tlm_analysis_fifo中的function,只增加write函數;
tlm_fifo中的mailbox function:size,is_empty,is_full,used,flush,單純的mailbox function;
tlm1中的絕大多數port,只支持一個參數,只有req或者rsp,不會同時有這兩個。
但是transport或者master/slave類型的port,支持req和rsp的同時存在。
tlm_fifo,也只是支持一種req的mailbox的存在,
req_rsp_channel,支持req和rsp的同時存在,因為其中定義了兩個mailbox,
在實際使用中,聲明,port,export的聲明,需要指定一種req,作為參數;
imp的聲明,需要指定一種req參數,還必須將parent的type 也傳進來;
new函數,port、export需要指定parent,需要solve_binding;
imp需要指定parent,因為需要調用parent的function;
connect函數,需要在各個port都例化之后,在進行連接,因為port中的imp_list需要的是一個object;
所以,目前connect函數,都被放在connect phase;