路科验证的个人空间 https://blog.eetop.cn/1561828 [收藏] [复制] [分享] [RSS]

空间首页 动态 记录 日志 相册 主题 分享 留言板 个人资料

日志

UVM通信篇之四:通信管道应用

已有 6186 次阅读| 2018-1-28 13:37 |个人分类:验证系统思想|系统分类:芯片设计

在上一节《单向、双向及多向通信》中,读者们了解TLM通信的具体实现方式,而这些通信有一个共同的地方即都是端对端的方式,同时在target一端需要实现传输方法,例如put()或者get()。这种方式在实际使用过程中也不免会给用户带来一些烦恼:

  • 如何可以不自己实现这些传输方法,同时可以享受到TLM的好处

  • 对于monitor、coverage collector等组件在传输数据时,会存在一端到多端的传输,如何解决这一问题


本节课中我们将继续深入通信的方式,下面介绍的几个组件和TLM端口能够帮助用户免除上述的烦恼。首先来看看TLM FIFO的功能和用法。


TLM FIFO

在日常的传输过程中,无论是initiator给target发起一个transaction,还是initiator从target获取一个transaction,transaction最终会流向到consumer中(initiator和target都可以为consumer)。这个时候在还没有分析transaction时,我们希望先将该对象存储到本地的一个FIFO中,供日后使用。如果按照上节课的方式,那么用户需要分别在两个组件出例化端口,同时在target处实现相应的传输方法。而多数情况下,需要实现的方法都是极其相似的,主要的内容即是为了实现一个数据缓存功能。


TLM FIFO uvm_tlm_fifo是一个新的组件,它继承于uvm_component,而且已经预先内置了多个端口及实现了多个对应的方法,供用户使用。


从该组件的内部实现来看,它内置了一个mailbox #(T)。该mailbox没有尺寸现在,用来存储类型T的数据。同时,uvm_tlm_fifo的多个端口对应的方法均是利用该mailbox实现了数据的读写。一个uvm_tlm_fifo内主要包含下面几个TLM端口,实际上还有例化其它的TLM端口名,但为了简化起见,我们只提供下面几个端口供用户选择使用:

  • put_export:用户可以通过该端口调用put()、try_put()、can_put()。

  • put_ap:调用了put方法写入的数据同时也会通过该端口的write()函数送出。

  • get_peek_export:用户可以通过该端口调用get()、try_get()、can_get()、peek()、try_peek()、can_peek()。

  • get_ap:调用了get和peek方法读出的数据也会通过该端口的write()函数送出。


在使用过程中,我们将以用户将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

除了端对端的传输,还有一些情况下有多个组件会对同一个数据进行运算和处理。如果这个数据是从同一源出发,而到达不同的组件,这就要求有一些端口可以满足从一端到多端的需求。当一端发生变化,需要通知跟它关联的多个组件时,我们就可以利用软件的设计模式之一观察者模式(observer pattern)来实现这一要求。observer pattern的核心在于用户需要记住,第一,这是从一个initiator端到多个target端的方式;第二,analysis port采取的是"push"模式,即从initiator端调用多个target端的write()函数来实现循环式的更新。


下面的这张图给了一个典型的analysis port类型端口的连接方式,可以看到,类似于其它TLM类型端口的是,按照传输方法和端口方向组合可以将analysis port分为uvm_analysis_port、uvm_analysis_export以及uvm_analysis_imp。对于target一侧例化了uvm_analysis_imp后还应该实现write()函数。最后,在顶层可以将initiator同多个target端进行连接。那么在initiator端调用write()函数时,实际上它是通过循环的方式将所有连接的target端内置的write()函数进行了调用。由于函数的立即返回特点,无论连接多少个target端,initiator端调用write()函数总是可以立即返回的。而这里稍微不同于之前单一端口函数调用的是,及时暂时没有target与之相连,调用write()函数时也不会发生错误。

    initiator.ap.connect(target1.aimp);

    initiator.ap.connect(target2.aimp);

    initiator.ap.connect(target3.aimp);


Analysis TLM FIFO

由于analysis端口的提出实现了一端到多端的传输,而一个新的数据缓存组件类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的get_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,而用户需要实现transport()方法。那么按照同样的思路,UVM也提供了两种简便的用来接收request和response,同时供另外一方获取request和response的端口。它们分别是:

  • 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:

protected uvm_tlm_fifo #(REQ) m_request_fifo;

protected 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.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);


通过这些方式,可以实现initiator与target之间的自由的request和response的传输,而这两种连接方式仍然需要通过分别调用两次方法才可以完成request和response的传输。

在uvm_tlm_req_rsp_channel的基础上,又实现了transport端口的tlm fifo组件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之间的连接方式则可以仍然保留之前的单向传输连接方式。


本节课读者们进一步了解了一端到多端的TLM传输方式,以及为了节省用户时间而UVM内建的一些用于TLM传输的FIFO组件,希望用户今后可以灵活加以使用。


下一节课我们将看一看TLM2的端口类型,已经将它们与TLM1的端口类型进行比较。


谢谢你对路科验证的关注,也欢迎你分享和转发真正的技术价值,你的支持是我们保持前行的动力。



点赞

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 注册

  • 关注TA
  • 加好友
  • 联系TA
  • 0

    周排名
  • 0

    月排名
  • 0

    总排名
  • 0

    关注
  • 253

    粉丝
  • 25

    好友
  • 33

    获赞
  • 45

    评论
  • 访问数
关闭

站长推荐 上一条 /1 下一条

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-5-6 19:24 , Processed in 0.017700 second(s), 12 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
返回顶部