UVM之TLM通信基础概念

UVM之TLM通信基础概念

TLM是啥,为什么要用TLM?

TLM 就是 UVM 各个组件之间,传递 transaction(数据包)的 "专用通道"。

Driver、Monitor、Sequencer、Scoreboard、RM、Coverage 这些组件互相之间不能直接调用函数、不能直接访问变量,必须通过 TLM 端口 发数据、收数据。

为什么不用赋值?

耦合太强

一个组件改了,另一个直接报错

线程不安全

多线程同时读写会乱掉

无法阻塞、同步

数据来了你不知道,只能轮询

无法层次化、复用

换个环境就废了

无法一对多广播

一个 monitor 数据要同时给 sb + coverage,直接赋值做不到

基于以上问题,UVM 强制:组件之间必须用 TLM 通信,禁止直接访问。

简单说,TLM 让 UVM 各个组件变成模块化、可插拔、可复用。

一. TLM使用规则

TLM 是事务级建模,只传 transaction,不传信号

端口永远是主动的(port)

实现永远是被动的(imp / export)

必须成对使用:发送 ↔ 接收

阻塞(blocking):会等待,要等对方接受完才返回;

非阻塞(nonblocking):不等待,发完立刻返回

二.TLM接口类型

Put 类:主动发送数据,单向收发,分阻塞/非阻塞

发送端调用:put(tr)

接口列表

uvm_blocking_put_port #(T)

uvm_nonblocking_put_port #(T)

uvm_put_port #(T)(阻塞 + 非阻塞)

必须成对连接

port → export / imp

接收端实现

task put(T tr)(阻塞)

function bit try_put(T tr)(非阻塞)

Get / Peek 类:主动获取数据,单向收发,分阻塞/非阻塞

get(tr):取出并删除

peek(tr):只看不取

接口列表

uvm_blocking_get_port

uvm_blocking_peek_port

uvm_blocking_get_peek_port(最常用)

uvm_get_port、uvm_peek_port、uvm_get_peek_port

必须成对连接

port → export / imp

接收端实现

task get(output T tr)

task peek(output T tr)

Analysis 类:广播发送,一对多广播,非阻塞,环境数据分发

只能调用 write(tr)

接口列表

uvm_analysis_port #(T)

uvm_analysis_export #(T)

uvm_analysis_imp #(T, IMP)

接收端实现

function void write(T tr)

三.TLM FIFO

uvm_tlm_fifo #(T)

支持:put_port/get_port

不支持 analysis_port

uvm_tlm_analysis_fifo #(T) (常用,analysis_fifo = 万能 FIFO)

支持:analysis_port/put_port/get_peek_port

四.TLM 成对使用

发送端:主动发起请求,数据产生者;比如主动get数据,uvm_put_port;

接收端:被动响应,数据消费者;比如uvm_put_imp;

Export:中间传递端口,用于层次化连接;

Put 成对

发送端 port

连接

接收端(imp/export)

调用方法

uvm_blocking_put_port

uvm_blocking_put_imp / tlm_fifo.put_export

put()

uvm_nonblocking_put_port

uvm_nonblocking_put_imp

try_put()

put_port

put_imp

put() / try_put()

连接规则:initiator.put_port.connect(target.put_imp);

比如drv发给rm

Get / Peek 成对

获取端 port

连接

接收端(imp/export)

调用方法

uvm_blocking_get_port

uvm_blocking_get_imp / fifo.get_export

get()

uvm_blocking_peek_port

uvm_blocking_peek_imp

peek()

uvm_blocking_get_peek_port

uvm_blocking_get_peek_imp / analysis_fifo

get() / peek()

比如scoreboard从rm区数据做比对

Analysis 成对

发送端

连接

接收端

调用

analysis_port

analysis_imp / analysis_fifo

write()

monitor发数据给rm和scoreboard

五.端口连接规则

port.connect(export);

export.connetc(imp);

必须在connect_phase连接;

analysis port 不能直接连 get/peek port,必须加 uvm_tlm_analysis_fifo 中转。

所有端口泛型参数必须一致(都用 my_transaction)。

put_port和put_imp:发送推数据

get_port和get_imp:接收拉数据

analysis_port和analysis_imp+write:广播专用,比如monitor

六.TLM优缺点

优点:

高抽象层级,脱离底层信号;不用时序,不用操作wire信号,直接传送事物,代码简洁,开发速度快,验证效率高;

组件解耦,标准化接口;比如drv,mon,rm等只靠TLM端口通信,互相不依赖内部实现,更换、复用、移植组件非常方便,符合面向对象+接口隔离思想;

天然支持层次化连接;port->export->imp层级转发,顶层env的connect_phase只做连接即可,内部组件不用改动;

阻塞/非阻塞通信灵活;阻塞适合同步交互、控制流水、天然同步时序;非阻塞适合异步收发、高吞吐;

便于后续收集覆盖率和调试打印;事物可以自带打印函数、时间戳、自动化比对等;

跨平台、可复用、易于升级;TLM是UVM标准,不同项目、不同IP之间通信协议统一,组件复用极强;

缺点:

抽象层级高,和真实硬件有差距;不是真实信号时序,无法反映精细时序、毛刺、跨时钟域和信号竞争等硬件细节;

仿真精度不足,低层缺陷难发现;只做事物级交互,时序违规、握手错误、协议细微违规容易遗漏,必须搭配monitor抓信号;

占用仿真内存高;比如频繁创建、拷贝、传送事物,大批量传输数据内存开销信号通信大;

初学者上手门槛高;端口种类多;连接关系和实现规则容易混淆,调试链路不通比较费时间;

阻塞TLM容易造成死锁:比如组件A等待B,B等待A,任务挂起死锁,需要仔细设计同步逻辑;

analysis_port是广播型,可控性弱;比如一对多广播,无法单独控制某一个接口,流量大时容易冗余、影响性能仿真;

不适合物理层等底层验证;引脚级、时序、电平、串并转换等场景,TLM力不从心,还需要依赖信号级驱动和采样;

七.使用场景

组件内部环境之间用TLM,可高效传输数据,解耦复用;

验证环境与DUT交互用信号级,可保证硬件时序精度;

monitor发包给scoreboard和rm,进行数据比对;

mon.put_port.connect(sb.put_imp);

使用uvm_tlm_fifo

// Monitor put_port → FIFO put_export

mon.put_port.connect(tlm_fifo.put_export);

// FIFO get_export → Scoreboard get_port

sb.get_port.connect(tlm_fifo.get_export);

或者uvm_tlm_analysis_fifo

// ========================

// blocking_put_port → ana_fifo.put_export

// ========================

mon.put_port.connect(ana_fifo.put_export);

// ========================

// get_peek_port ← ana_fifo.blocking_get_peek_imp

// ========================

sb.bgp_port.connect(ana_fifo.blocking_get_peek_imp);

A环境drv和B环境的rm通信;

// RM 的 analysis port → FIFO 的 analysis_export

eA.rm.ap.connect(ana_fifo.analysis_export);

// Driver 的 get_peek_port → FIFO 的 blocking_get_peek_imp

eB.drv.bgp_port.connect(ana_fifo.blocking_get_peek_imp);

相关推荐