UVM入门与进阶学习笔11——TLM通信(3)

目录


通信管道

TLM通信的实现方式的共同点在于都是端对端的,同时target一端需实现传输方法,例如put()或者get()。

  • 对于monitor、coverage collector等组件在传输数据时,会存在一端到多端的传输,如何解决这一问题?
  • 几个TLM组件和端口可帮助用户解决问题:TLM FIFO、analysis port、analysis TLM FIFO、request & response通信管道。

TLM FIFO

UVM入门与进阶学习笔11——TLM通信(3)

  • 在一般TLM传输过程中,无论是initiator给target发起一个transaction,还是initiator从target获取一个transaction,transaction最终都会流向consumer中consumer没有分析transaction时先将该对象存储到本地FIFO*稍后使用
  • 需要分别在两个组件中例化端口,同时在target中实现相应的传输方法
  • 多数情况下需要实现的传输方法都是相似的,方法的主要内容是为了实现一个数据缓存功能
  • TLM FIFO uvm_tlm_fifo类是一个新组件,它继承于uvm_component类,而且已经预先内置了多个端口以及实现了多个对应方法
  • uvm_tlm_fifo的功能类似于mailbox,不同之处在于它提供各种端口可以使用,推荐在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

UVM入门与进阶学习笔11——TLM通信(3)

  • 除了端对端的传输,在一些情况下还有多个组件会对同一个数据进行运算处理
  • 如果这个数据从同一个源的TLM端口发出到达不同的组件,这就要求该端口可以满足从一端到多端的需求
  • 如果数据源端发生变化需要通知跟它关联的多个组件时,可以利用软件设计模式的观察者模式来实现。
  • 观察者模式的核心在于:
    • 这是从一个initiator端到多个target端的方式;
    • analysis port采取的是“push”模式,即从initiator端调用多个target端的write()函数实现数据传输
initiator.ap.connect(target1.aimp);
initiator.ap.connect(target2.aimp);
initiator.ap.connect(target3.aimp);
  • 典型的analysis port类型端口的连接方式,类似其它TLM端口,按传输方法和端口方向组合可将analysis port分为uvm_analysis_port、uvm_analysis_export、uvm_analysis_imp
  • target一侧例化了uvm_analysis_imp后还需要实现write()函数
  • 顶层可以将initiator端的uvm_analysis_port同多个target端的uvm_analysis_imp进行连接
  • 在initiator端调用write()函数时,实际上它是通过循环的方式将所有连接的target端内置的write()函数进行了调用。
  • 由于函数立即返回的特点,无论连接多少个target端,initiator端调用write()函数可以立即返回。不同于之前单一端口函数调用的是,即使没有target与之相连,调用write()函数时也不会发生错误

Analysis TLM FIFO

UVM入门与进阶学习笔11——TLM通信(3)

  • 由于analysis端口提出实现了一端到多端的TLM数据传输,而新的数据存储组件类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_fifoanalysis_export端口,这样数据可以从initiator发起,写入到各个tlm_analysis_fifo的缓存中。
    • 将多个target的get_port连接到tlm_analysis_fifoget_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
  • UVM提供了两种简便的通信管道作为数据缓存区域,既有TLM端口从外侧接收request和response,同时也有TLM端口供外侧获取request和response。这两种TLM通信管道分别是uvm_tlm_req_rsp_channeluvm_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入门与进阶学习笔11——TLM通信(3)

  • 有了这么多丰富的端口,用户可以使用成对的端口进行数据的存储和访问。需要注意的是,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与target可以利用uvm_tlm_req_rsp_channel进行request与response的数据交换。
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);

UVM入门与进阶学习笔11——TLM通信(3)
也可利用另一种连接方式:

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入门与进阶学习笔11——TLM通信(3)
  • uvm_tlm_req_rsp_channel的基础上,UVM又添加了具备transport端口的管道组件uvm_tlm_transport_channel类,它继承于uvm_tlm_req_rsp_channel且例化了transport端口:uvm_transport_imp #(REQ, RSP, this_type) transport_export;
  • 这个新的组件类型是针对一些无法流水化处理的request和response传输,例如initiator一端要求每次发送完request,必须等到response接收到以后才可以发送下一个request,这时transport()方法就可以满足这一需求。
  • 如果将上面的传输方式进行修改,需要变化的是initiator端到req_rsp_channel的连接,应修改为:initiator.transport_port.connect(transport_channel.transport_export)
  • transport_channel和target之间的连接,可以保留之前的单向传输连接方式。
上一篇:数星星(树状数组的应用)


下一篇:怎么一次同时把多个服务项目进行打包