一、概述
TLM通信的实现方式有一个共同的地方即都是端对端的,同时target一段需要实现传输方法,例如put()
或者get()
。对于monitor
、coverage collector
等组件在传输数据时,会存在一端到多端的传输。
二、TLM_FIFO
- 在一般TLM传输过程中,无论是initiator给target发起一个transaction,还是initiator从target获取一个transaction,transaction最终都会流向consumer中。consumer在没有分析transaction时,先将该对象存储到本地FIFO中。
- 需要分别在两个组件中例化端口,同时在target中实现相应的传输方法。多数情况下,需要实现的传输方法都是相似的,方法的主要内容即是为了实现一个数据缓存功能。
-
TLM_FIFO uvm_tlm_fifo
类是一个新组件,它继承于uvm_component
类,而且已经预先内置了多个端口以及实现了多个对应方法。
uvm_tlm_fifo
的功能类似于mailbox
,不同的地方在于uvm_tlm_fifo
提供了各种端口可以使用,在initiator端例化put_port
或者get_peek_port
,来匹配uvm_tlm_fifo
的端口类型。如果例化了其它类型的端口,uvm_tlm_fifo
还提供put
、get
以及peek
对应的端口:
uvm_put_imp #(T,this_type) blocking_put_export
uvm_put_imp #(T,this_type) nonblocking_put_export
uvm_get_peek_imp #(T,this_type) blocking_get_export
uvm_get_peek_imp #(T,this_type) nonblocking_get_export
uvm_get_peek_imp #(T,this_type) get_export
uvm_get_peek_imp #(T,this_type) blocking_peek_export
uvm_get_peek_imp #(T,this_type) nonblocking_peek_export
uvm_get_peek_imp #(T,this_type) peek_export
uvm_get_peek_imp #(T,this_type) blocking_get_peek_export
uvm_get_peek_imp #(T,this_type) nonblocking_get_peek_export
三、Analysis Port
除了端对端的传输,在一些情况下还有多个组件会对同一个数据进行运算处理。如果这个数据从同一个源的TLM端口发出到达不同的组件,这就要求该种端口可以满足从一端到多端的需求。如果数据源端发生变化需要通知跟它关联的多个组件时,可以利用软件设计模式的观察者模式来实现。
观察者模式的核心在于:
- 这是从一个initiator端到多个target端的方式。
- analysis port采取的是“push”模式,即从initiator端调用多个target端的
write()
函数来实现数据传输。
四、Analysis TLM FIFO
- 由于analysis端口提出实现了一端到多端的TLM数据传输,而一个新的数据存储组件类
uvm_tlm_analysis_fifo
提供了可以搭配uvm_analysis_port
端口、uvm_analysis_imp
端口和write()
函数。 -
uvm_tlm_analysis_fifo
类继承于uvm_tlm_fifo
,这表明它本身具有面向单一TLM端口的数据缓存特性,而同时该类又有一个uvm_analysis_imp
端口analysis_export
并且实现了write()
函数:uvm_analysis_imp #(T, uvm_tlm_analysis_fifo #(T)) analysis_export;
基于initiator到多个target的连接方式,如果实现一端到多端的数据传输,可以插入多个uvm_tlm_analysis_fifo
,连接方式如下:
- 将initiator的
analysis port
连接到tlm_analysis_fifo
的analysis_export
端口,这样数据可以从initiator发起,写入到各个tlm_analysis_fifo
的缓存中。 - 将多个target的
get_port
连接到tlm_analysis_fifo
的get_export
端口,注意保持端口类型的匹配,这样从target一侧只需要调用get()
方法就可以得到先前存储在tlm_analysis_fifo
中的数据。
initiator.ap.connect(tlm_analysis_fifo1.analysis_export);
target1.get_port.connect(tlm_analysis_fifo1.get_export);
initiator.ap.connect(tlm_analysis_fifo2.analysis_export);
target2.get_port.connect(tlm_analysis_fifo2.get_export);
initiator.ap.connect(tlm_analysis_fifo3.analysis_export);
target3.get_port.connect(tlm_analysis_fifo3.get_export);
五、Request & Response通信管道
双向通信端口transport,即通过在target端实现transport()方法可以在一次传输中既发送request又可以接收response。UVM提供了两种简便的通信管道,它们作为数据缓存区域,既有TLM端口从外侧接收request和response,同时也有TLM端口供外侧获取request和response。这两种TLM通信管道分别是uvm_tlm_req_rsp_channel
和uvm_tlm_transport_channel
uvm_tlm_req_rsp_channel
它提供的端口首先是单一方向的
uvm_put_export #(REQ) put_request_export;
uvm_put_export #(RSP) put_response_export;
uvm_get_peek_export #(RSP) get_peek_response_export;
uvm_get_peek_export #(REQ) get_peek_request_export;
uvm_analysis_port #(REQ) request_ap;
uvm_analysis_port #(RSP) response_ap;
uvm_master_imp #(REQ, RSP, this_type, uvm_tlm_fifo #(REQ), uvm_tlm_fifo #(RSP)) master_export;
uvm_slave_imp #(REQ, RSP, this_type, uvm_tlm_fifo #(REQ), uvm_tlm_fifo #(RSP)) slave_export;
可以在使用成对的端口进行数据的存储和访问。需要注意的是,uvm_tlm_req_rsp_channel
内部例化了两个mailbox分别用来存储request和response
protect uvm_tlm_fifo #(REQ) m_request_fifo;
protect uvm_tlm_fifo #(RSP) m_response_fifo;
例如initiator端可以连接channel的put_request_export
,target连接channel的get_peek_request_export
,同时target连接channel的put_response_export
,initiator连接channel的get_peek_response_export
端口。
通过这种对应的方式,使得initiator与target可以利用uvm_tlm_req_rsp_channel
进行request与response的数据交换
initiator.put_port.connect(req_rsp_channel.put_request_export);
target.get_peek_port.connect(req_rsp_channel.get_peek_request_export);
target.put_port.connect(req_rsp_channel.put_response_export);
initiator.get_peek_port.connect(req_rsp_channel.get_peek_response_export);
也可以利用另一种连接方式
initiator.master_port.connect(req_rsp_channel.master_export);
target.slave_port.connect(req_rsp_channel.slave_export);
uvm_tlm_transport_channel
在uvm_tlm_req_rsp_channel
的基础上,UVM又添加了具备transport端口的管道组件uvm_tlm_transport_channel
类,它继承于uvm_tlm_req_rsp_channel
,并且例化了transport端口uvm_transport_imp #(REQ, RSP, this_type) transport_export
新添加的这个TLM FIFO组件类型是针对于一些无法流水化处理的request和response传输,例如initiator一端要求每次发送完request,必须等到response接收到以后才可以发送下一个request,这时transport()
方法就可以满足这一需求。
将initiator端到req_rsp_channel
的连接修改为
initiator.transport_port.connect(transport_channel.transport_export)
transport_channel
和target之间的连接,可以保留之前的单向传输连接方式。