TLM通信
TLM是一种基于事务的通信方式,通常在高抽象级语言作为模块之间的通信方式。
系统原型验证的芯片验证阶段都会使用TLM通信方式,前者是为了更快的实现硬件原型之间的数据通信,后者是为了更快的实现验证组件之间的数据通信。TLM通信对项目的最大贡献是仿真速度,还可以保证足够大的信息量和准确性。
通信对象
TLM通信需要两个通信对象,分别为initiator和target。区别在于initiator是属于通信的发起方,target属于通信的响应方。但是通信的发起方并不代表着数据流向起点。
按照transaction的流向,又可以将两个对象分为producer和consumer。区分方法是数据从哪里产生,那里就是producer,流向哪里,那里就是consumer。 所以initiator和target的关系 与 producer和consumer 的关系不是固定的。
TLM通信步骤
分辨出initiator和target,producer和consumer 。
在target中实现TLM通信方法。
在两个对象中创建TLM端口。
在更高层次中将两个对象的端口进行连接。
传输方向
传输方向的区分来自于数据的流向。
单向传输:由initiator发起request transaction
双向传输:由initiator发起request transaction,传送至target之后,target进行消化,然后发起response transaction,返回给initiator。
端口的划分
根据端口类型可以划分为三种,优先级为PORT、EXPORT、IMP(IMP优先级最低)
port:经常作为initiator的发起端,initiator凭借port才可以访问target的TLM通信方式。
export:作为initiator和target的中间层次端口。
imp:只能作为target接收request的末端,无法作为中间层次的端口,imp的俩呢及无法再延伸。
传输方向和端口的组合,可以加以区分TLM端口的继承树。
端口的使用
单向端口:声明port和export作为request发起方,需要指定tranaction类型参数,而声明月imp作为request接收方,不但需要指定transaction类型,也需要指定它所在的component类型。
双向端口:指定参数需要考虑双向传输的因素,将传输类型transaction拆分为request transaction类型和response transaction类型。
TLM端口连接的一般做法:
在initiator端例化port,在中间层次例化export,在target端例化imp。
多个port可以连接到同一个export或者imp;但是单个port或者export无法连接多个imp。 这可以抽象为多个initiator可以对同一个target发起request,但是尾一个initiator无法连接多个target
port应为request起点,imp应为request终点,而中间可以穿越多个层次。基单元组件的自闭性考虑建议在穿越的中间层次声明export,继而通过层层连接实现数据通。
port可以连接port、expor或者imp;export可以连接export或者imp;imp只能作为数据产送的重点,无法扩展连接。
单项通信
单项通信的TLM端口类型,这里的PORT代表了三种端口名称(port、export、imp)
阻塞传输方式将blocking前缀作为函数名的一部分,而非阻塞方式则名为nonblocking。阻塞端口的方法类型为task,这保证了可以实现事件等待和延时; 非阻塞端口的方式类型为function,这确保了方法调用可以立即返回。
blocking的阻塞传输方法也被扩展了:
put(): initiator先生成数据T,同时将该数据传送至target。
get():initiator从target获取数据T,而target中的该数据T则应消耗。
peek():initiator从target获取数据T,而target中的该数据T 还应保留。
nonblocking非阻塞的方法:
try_put() can_put() try_get() can_get() try_peek() can_peek() 。这六个非阻塞函数与对应阻塞任务的区别在于,它们必须立即返回,如果try XX函数可以发送或者获取数据,那么函数应该返 回1如果执行失败则应返回0o 。或者通过can_XXX函数先试探target是否可以接收数据,如果可以再通过try_xxx函数发送,提高数据发送的成功率
双向通信
与单向通信相同的是,双向通信(bidirectional Communication) 的两端也分为initiator和target,但是数据流向在端对端之间是双向的。 双向通信中的两端同时扮演着producer和onsumer的角色,而initiator 作为request发起方,在发起request之后,还会等待response返回。
双向端口类型:
双向通信按照通信握手方式可以分为:transport双向通信方式、master和slave双向通信方式。
transpor端口通过transport()方法,可以在同一方法调用过程中完成 REO和RSP的发出和返回。
master和slave的通信方式必须分别通过put、 get和peek的调用,使用两个方法才可以完成一次握手通信。
master端口的slave端口的区别在于,当initiator作为master时,它会发起REQ送至target端,而后再从target端获取RSP;当initiator使用slave端 口时,它会先从target端获取REQ,而后将RSP送至target端。
多向通信
多向通信任然是两个组件之间的通信,并不是多个组件之间,但是多个组件之间的通信任然可以由基础的两个组件之间的通信组成。多向通信指的是:initiator和target之间相同的TLM端口数目(超过一个时)的通信处理方法。例如:Comp1有两个uvm_blocking_put_port。而comp2有两个 uvm_blocking_put_imp端口,对于端口例化可以给不同名字, 连接也可以通过不同名字来索引,但问题在于Comp2中需要实现两个task put({itrans t),又因为不同端口之间要求在imp端口—侧实现专属方法,这就造成了方法命名冲突,即无法在Comp2中定义两个同名的put任务
解决方法:UVM通过端口宏声明方式来解决。这个方法解决的方法的核心在于让不同端口对应不同名的任务。
示例
双向通信的实现步骤
选择正确的imp宏来定义不同的imp端口类型,而宏的参数SF(后缀名) 转化为相应的imp端口类型名。
在imp所例化的组件中,分别实现不同的put_SFX方法。
在por所例化的组件中,不需要对目标imp端口类型做区分,例如compl bp_portl和bp_port2为相同的端□类型。
对于comp1调用put(方法,它只需要选择bp_port1或者bp_port2。而不需更替put()方法名,即仍然按照put()来调用而不是put_pl(或者put_p2)。
在上层环境应该连接COompl和Comp2的TLM端口。
通信管道
TLM FIFO
TLM FIFO uvm_tlm_fifo类是一个新组件,它继承于uvm_component类,内置了多个端口可以实现多个对应的方法。uvm_tlm_fifo的功能类似于mailboX,不同的地方在于uvm_tlm_fifo提供了各种端口供用户使用。
Analysis Port
唯一 一个满足一端到多端的通信方式。target端需要实现write()函数,initiator端调用write()函数,在顶层环境中将port和imp连接起来。无论有多少个target,initiator端调用的write()函数都是立即返回的。
Analysis TLM FIFO
就是前两个的结合,中间插入多个uvm_tlm_analysis_fifo。initiator的port连接到uvm_tlm_analysis_fifo的export端口,写入数据;target的port端口连接到uvm_tlm_analysis_fifo的export端口,读取之前存入的数据。
Request & Response 通信管道
双向通信端口transport,通过在target端实现transport()方法可以在一次传输中既发送request又可以接收responsec
UVM提是供了两种简便的通信管道,它们作为数据缓存区域,既有 TLM端口从外侧接收request和response,同时也有TLM端口供外侧获取request和response。 ·uVm_tlm_reg_s_channe uvm_tm_treq_rsp_channel 和 uvm_tm_transaction_channel
uvm_tm_treq_rsp_channel 提供的端口是单一方向的,有如下该类例化的端口: