1. 什么是TLM
TLM是Transaction Level Modeling(事务级建模),为组件之间的通信建立专门的通信信道。
2. TLM原理


3. 常用TLM port/imp/export
port | export | import | |
put | uvm_blocking_put_port#(T); uvm_nonblocking_put_port#(T); uvm_put_port#(T); | uvm_blocking_put_export#(T); uvm_nonblocking_put_export#(T); uvm_put_export#(T); | uvm_blocking_put_imp#(T, IMP); uvm_nonblocking_put_imp#(T, IMP); uvm_put_imp#(T, IMP); |
get | uvm_blocking_get_port#(T); uvm_nonblocking_get_port#(T); uvm_get_port#(T); | uvm_blocking_get_export#(T); uvm_nonblocking_get_export#(T); uvm_get_export#(T); | uvm_blocking_get_imp#(T, IMP); uvm_nonblocking_get_imp#(T, IMP); uvm_get_imp#(T, IMP); |
peek | uvm_blocking_peek_port#(T); uvm_nonblocking_peek_port#(T); uvm_peek_port#(T); | uvm_blocking_peek_export#(T); uvm_nonblocking_peek_export#(T); uvm_peek_export#(T); | uvm_blocking_peek_imp#(T, IMP); uvm_nonblocking_peek_imp#(T, IMP); uvm_peek_imp#(T, IMP); |
get peek | uvm_blocking_get_peek_port#(T); uvm_nonblocking_get_peek_port#(T); uvm_get_peek_port#(T); | uvm_blocking_get_peek_export#(T); uvm_nonblocking_get_peek_export#(T); uvm_get_peek_export#(T); | uvm_blocking_get_peek_imp#(T, IMP); uvm_nonblocking_get_peek_imp#(T, IMP); uvm_get_peek_imp#(T, IMP); |
transport | uvm_blocking_transport_port#(REQ, RSP); uvm_nonblocking_transport_port#(REQ, RSP); uvm_transport_port#(REQ, RSP); | uvm_blocking_transport_export#(REQ, RSP); uvm_nonblocking_transport_export#(REQ, RSP); uvm_transport_export#(REQ, RSP); | uvm_blocking_transport_imp#(REQ, RSP, IMP); uvm_nonblocking_transport_imp#(REQ, RSP, IMP); uvm_transport_imp#(REQ, RSP, IMP); |
每一个IMP要和一个component相对应。
按照控制流的优先级排序,UVM中 三种端口顺序为:PORT > EXPORT > IMP。
4. 常用TLM端口使用方法
端口类型 | 实现方法 |
uvm_put_port #(T) | put() try_put() can_put() |
uvm_blocking_put_port #(T) | put() |
uvm_nonblocking_put_port #(T) | try_put() can_put() |
uvm_get_peek_port | get()、try_get()、can_get() peek()、try_peek()、can_peek() |
uvm_blocking_get_peek_port | get() peek() |
uvm_nonblocking_get_peek_port | try_get()、can_get() try_peek()、can_peek() |
uvm_transport_port | transport() nb_transport() |
uvm_blocking_transport_port | transport() |
uvm_nonblocking_transport_port | nb_transport() |
上表中省略了get、peek port,与get_peek_port类似。
put() 是一个task,可能会阻塞当前进程直到transaction传输成功。
try_put() 是一个function,不会阻塞当前进程,不管transaction传输是否完成都会返回。
can_put() 是一个function,不会阻塞当前进程,不发生transaction传输,只是检验对方是否准备好了接受。
get()、peek()与put()类似;try_get()、try_peek()与try_put()类似;can_get()、can_peek()与can_put()类似。
对于analysis_port和analysis_export来说,没有阻塞和非阻塞的概念。只有一种操作:write。
从功能上来看 export和port的功能是一样的,通常export作为中间端口使用。
需在import中重载实现表格中的对应方法,并通过发送方的 port名.方法 调用。
因此只有import才能作为连接关系的终点。
4. FIFO

peek端口与get相似,其数据流、控制流都相似,唯一的区别在于当get任务被调用时,FIFO内部缓存中会少一个transaction,而 peek被调用时,FIFO会把transaction复制一份发送出去,其内部缓存中的transaction数量并不会减少。
FIFO的类型有两种,一种是上图中的uvm_tlm_analysis_fifo,另外一种是uvm_tlm_fifo。这两者的唯一差别在于前者有一个 analysis_export端口,并且有一个write函数,而后者没有。

fifo的调试函数
函数名 | 用途 |
used() | 用于查询FIFO缓存中有多少transaction。 |
is_empty() | 用于判断当前FIFO缓存是否为空。 |
is_full() | 用于判断当前FIFO缓存是否已经满了。 |
flush() | 用于清空FIFO的缓存。 |
new | ![]() fifo本质上是个component,前两个参数与componet new函数中参数一致。第三个参数用于设定FIFO缓存的上限,默认为1。若要把缓存设置为无限大,则将传入的size参数设置为0。 |
size() | 返回FIFO缓存的上限。 |
一般来说,使用 uvm_analysis_port、uvm_tlm_analysis_fifo、uvm_analysis_imp 即可。