UVM-TLM通信

本文深入解析了TLM(Transaction Level Modeling)通信的基本概念、工作原理及其应用。覆盖了单向、双向及多向通信的特点,并介绍了TLM_FIFO、AnalysisPort、AnalysisTLMFIFO和request&response通信管道等关键组件。
摘要由CSDN通过智能技术生成

1.TLM通信概述

TLM是一种基于事务(transaction)的通信方式,通常在高抽象级语言例如SystemC或SV/UVM作为模块之间的通讯方式。
TLM通信保证了相邻组件之间的通信不再通过显示句柄引用,而是独立于组件的通信方式,为验证组件的复用提供了很好的封闭性

  • TLM通信需要两个通信对象,这两个对象分别称为initiator和target。 initiator发起通信请求,target作为发起通信的响应方

  • 通信发起方并不代表了transaction的流向起点,即不一定数据是从initiator流向target,也可能是从target流向了initiator

  • 按照transaction的流向,将对象分为producer和consumer。producer数据产生方,consumer数据流向地
    在这里插入图片描述

  • 有了两个参与通信的对象之后,用户需要将TLM通信方法在target一端中实现,以便于initiator作为发起方可以调用target的通信方法,实现数据传输

  • 在target实现了必要的通信方法之后,最后一步我们需要将两个对象进行连接,这需要在两个对象中创建TLM端口,继而在更高层次将这两个对象进行连接
    TLM通信步骤:

  • 分辨出initiator和target, producer和consumer

  • 在target中实现TLM通信方法

  • 在两个对象中创建TLM端口,initiator中创建port端口,target端创建imp端口

  • 在更高层次对两个对象的端口进行连接
    分类:
    从数据流向来看,传输方向分为单向和双向

  • 单向传输:由initiator发起request transaction

  • 双向传输:由initiator发起request transaction,传送至target,继而在target在消化了request transaction后,会发起responde transaction返回给initiator
    三种端口类型:

  • port:经常作为initiator的发起端,initiator凭借port才可以访问target的TLM通信方法

  • export:作为initiator和target中间层次的端口

  • imp:只能作为target接受request的末端,它无法作为中间层次的端口,所以imp到的连接无法再次延伸

2.端口的使用

  • 声明port和export作为request发送方,参数只需要指定transaction类型参数

  • 声明imp作为request接收方,参数有2个,第一个指定transaction类型,第二个指定它所在的component类型
    关于TLM端口的类型、层次和对应的连接,可以从对应的连接关系中初步得出TLM端口连接的一般做法:

  • 在initiator端例化port,在中间层例化export,在target端例化imp,在build_phase中创建

  • 多个port可以连接到同一个export或者imp,但单个port或者export无法连接到多个imp上

  • port可以连接port、export和imp;export可以连接export和imp上;imp是数据传输的终点,无法扩展连接
    在这里插入图片描述

3.单向通信

单向通信指的是从initiator到target之间的数据流向是单一方向的,或者说initiator和target只能扮演producer和consumer中的一个角色。
在这里插入图片描述

  • uvm_blocking_put_PORT
  • uvm_nonblocking_put_PORT
  • uvm_put_PORT
  • uvm_blocking_get_PORT
  • uvm_nonblocking_get_PORT
  • uvm_get_PORT
  • uvm_blocking_peek_PORT
  • uvm_nonblocking_peek_PORT
  • uvm_peek_PORT
  • uvm_blocking_get_peek_PORT
  • uvm_nonblocking_get_peek_PORT
  • uvm_get_peek_PORT
    这里的PORT代表了三种端口名:port、export、imp
    实际上记忆这么多的端口名是有技巧的。按照每一个端口名的命名规则,它们指出通信的两个要素:
  • 是否阻塞的方式
  • 何种通信方法,包括put、get、peek、get_peek,这些都需要在target中实现
    在这里插入图片描述

数据blocking阻塞传输的方法分别包含:

  • put:initiator通过该方法可以自己生成数据Tt,同时将该数据传送至target
  • get:initiator通过该方法可以从target获取数据Tt,而target中的该数据则应消耗
  • peek:initiator通过该方法可以从target获取数据Tt,而target中该数据应该保留
    与上述三种task对应的nonblocking非阻塞的方法分别是:
  • try_put() :返回值默认为1或0
  • can_put() :回调方法,在调用try_xx()方法时自动调用
  • try_get()
  • can_get()
  • try_peek()
  • can_peek()
    这六个函数与其对应的task的区别在于,它们必须立即返回,函数try_xx()可以发送和获取数据,如果成功,返回1,失败返回0,可以通过can_xx()先试探target是否可以接受数据,再通过try_xx()发送,提高数据发送的成功率。

4.双向通信

与单向通信相同的是,双向通信的两端也分为initiator和target,但是数据的流向是端对端双向的。
双向通信的两端同时扮演着producer和consumer的角色。
在这里插入图片描述
UVM双向端口分为以下类型:

  • uvm_blocking_transport_PORT

  • uvm_nonblocking_transport_PORT

  • uvm_transport_PORT

  • uvm_blocking_master_PORT

  • uvm_nonblocking_master_PORT

  • uvm_master_PORT

  • uvm_blocking_slave_PORT

  • uvm_nonblocking_slave_PORT

  • uvm_slave_PORT
    可以将上面的端口按照通信方法分为两类:

  • transport双向通信方式

  • master和slave双向通信方式
    在这里插入图片描述

  • transport端口通过transport()方法,可以在同一方法调用过程中完成REQ和RSP的发出和返回

  • master和slave的通信必须分别通过put、get和peek的调用,使用两个方法才可以完成一次握手通信

  • 而master端口的slave端口的区别在于,当initiator作为master时,它会发起REQ送至target端,而后再从target端获取RSP;当initiator使用slave端口时,它会先从target端获取REQ,而后,将RSP送至target端
    对于master端口或者slave端口的实现方式,非常类似于之前介绍的单向通信方式,只是imp端口所在的组件需要实现的方法更多了。

5.多向通信

  • 多向通信仍然是两个组件之间的通信,而不是多个组件之间的通信
  • 多向通信是指,如果initiator与target之间的相同TLM端口数目超过一个情况,在target端的解决方法
  • UVM通过端口宏声明方式来解决这一问题,它解决的核心问题在于让不同端口对应不同的任务名,这样就不会造成方法名的冲突
    在这里插入图片描述
    comp1存在两个uvm_block_put_port端口,而从comp2存在两个uvm_blocking_put_imp端口,同时还要定义两个put()方法,我们可以在端口例化时创建不同的端口名,但是问题在于comp2中要定义两个task put(),不同的端口之间要求在imp端口一侧实现专属方法,这就造成了方法命名冲突,即无法在comp2中定义两个同名put方法。
    UVM通过端口宏声明来解决这一问题,解决该问题的核心在于让不同的端口对应不同命的任务,这样不会造成方法名的冲突。简单来说就是加上声明imp端口的宏,如下:
`uvm_blocking_put_imp_dec1(SFX)
`uvm_nonblocking_put_imp_dec1(SFX)
`uvm_put_imp_dec1(SFX)
 //方法类型可以替换为其他,SFX为imp端口和方法的后缀名

多向通信总结:

  • 用户只需要例化多个imp端口的组件中实现不同名称的方法,使其与对应imp类型名保持一致
  • 而对于port端口一侧的组件,则不需要关心调用的方法名称,因为该方法名并不会发生改变

5.通信管道

TLM通信的实现方式,这些通信有一个共同的地方即都是端对端的,同时在target一端需要实现传输方法,如put()和get(),对于monitor、coverage、collection等组件在传输数据时,会存在一端到多端,如何解决?
下面介绍几个TLM组件和端口可以帮助用户免除这些烦恼:

  • TLM FIFO
  • analysis port
  • analysis TLM FIFO
  • request & reponse通信管道

5.1 TLM_FIFO

uvm_tlm_fifo类是一个新的组件,它继承与uvm_component,且预先内置了多个端口,实现了多个对应方法供用户使用,从组件内部来看,它内置了一个mailbox #(T),该信箱没有尺寸限制,用来存储数据类型T,uvm_tlm_fifo的多个端口对应的方法都是利用该信箱实现了数据读写。

5.2 Analysis Port

除了端对端的传输,在一些情况下还有多个组件会对同一个数据进行运算处理。
在这里插入图片描述

  • 可以实现一端对多端的需求,即数据是从同一个源的TLM端口出发到达不同的组件
  • 如果数据源端发生变化需要通知跟它关联的多个组件时,可以利用软件设计模式之一观察者模式来实现
    observe pattern的核心在于:
  • 第一,这是一个initiator端到多个target端的方式
  • 第二,analysis port采用的是”push"模式,即从initiator端调用多个target端的write()函数实现数据传输

5.3 Analysis TLM FIFO

  • uvm_tlm_analysis_fifo为用户提供了可以搭配uvm_analysis_port端口、uvm_analysis_imp端口和write()函数
  • uvm_tlm_analysis_fifo类继承于uvm_tlm_fifo,这表明它本身具有面向单一TLM端口的数据缓存特性,而同时该类又有一个uvm_analysis_imp端口
    在这里插入图片描述

连接方式:

  • 将initiator的analysis port连接到uvm_tlm_analysis_fifo 的 get_export 端口,这样数据可以从initiator发起,写到各个uvm_tlm_analysis_fifo的缓存中
  • 将多个target的get_port连接到tlm_analysis_fifo的get_export,注意保持端口类型的匹配,这样从target一侧需要调用get()方法就可以得到先前存储在tlm_analysis_fifo中的数据

5.4 request & response 通信管道

UVM提供了两种简单的通信管道,他们作为数据缓存区域,既有TLM端口从外侧接收request 和 response,同时也有TLM端口供外侧获取request和response。
在这里插入图片描述

  • uvm_tlm_req_rsp_channel
  • uvm_tlm_transport_channel
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值