[UVM源代码研究] 我们每天都在用的uvm_tlm_analysis_fifo内部是如何工作的

本文详细探讨了UVM环境中uvm_tlm_analysis_fifo的工作原理,涉及发送端的uvm_analysis_port与uvm_analysis_imp的通信方式,以及接收端uvm_blocking_get_port的选择及其内部实现。文章揭示了fifo的灵活性和组件间通信的细节。
摘要由CSDN通过智能技术生成

[UVM源代码研究] 我们每天都在用的uvm_tlm_analysis_fifo内部是如何工作的

通常我们环境中的两个uvm_component之间进行通信时,都会用一个uvm_tlm_analysis_fifo作为媒介,发送数据的组件(如monitor)内部定义一个uvm_analysis_port连接fifo的analysis_export,对应的通信方法是write;接受数据的组件内定义一个uvm_blocking_get_port连接到fifo的blocking_get_export,通信方法用的是get。

那么在这个uvm_tlm_analysis_fifo内部究竟是如何实现以上通信方法,以及这里的analysis_export和blocking_get_export在fifo内部又对应着什么样的imp实现呢,今天让我们一睹为快!

首先我们先来看看monitor端选择的port类型。通过之前对TLM机制的研究,我们知道之所以在monitor里选用uvm_analysis_port是因为monitor里抓到的transaction需要发送到不止一个组件里,所以必须用广播包的形式。一旦我们选定了在monitor内使用uvm_analysis_port,那就决定了与之配对的imp类型必须是uvm_analysis_imp类型,且实现的通信方法必须是write函数。查看tlm相关源代码如下来印证我们的猜想。
在这里插入图片描述

我们再看看源代码里关于uvm_analysis_port以及uvm_analysis_imp的定义
在这里插入图片描述
在这里插入图片描述

可见当我们调用uvm_analysis_port.write()时会遍历调用与其连接的所有imp所在组件里的write函数。

理解完发送端(monitor)与uvm_tlm_analysis_fifo的连接,我们再来看看接收端(scoreboard)的连接情况。

接收端我们需要等待fifo中有数据了之后才把数据取出,所以需要阻塞(blocking)的等待并获取(get/peek)数据,由于我们需要将fifo中的数据取走并且不希望后面取到相同的数据,所以我们选择get而不是peek,于是接收端选用的通信port就是uvm_blocking_get_port,通过之前的学习知识我们知道与之相连的imp类型必须是uvm_blocking_get_imp类型,那我们来看看uvm源代码印证下我们的猜想。
在这里插入图片描述

这里我们注意到blocking_get_export是定义在uvm_tlm_fifo_base里的,而我们之前查看的analysis_export是定义在uvm_tlm_fifos文件里的。

我们发现结果并不如我们所预期的,实际定义的blocking_get_export的类型是uvm_get_peek_imp,再次查看uvm_get_peek_imp的源代码
在这里插入图片描述

进一步顺藤摸瓜看看这些宏的定义。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

于是我们不难发现blocking_get_export为什么会使用uvm_get_peek_imp类型来定义了,这样做的好处是预留4种imp对应的通信方法,分别是:

uvm_blocking_get_imp(实现task get())

uvm_bloking_peek_imp(实现task peek())

uvm_nonblocking_get_imp(实现function try_get())

uvm_nonblocking_peek_imp(实现function try_peek())

于是我们在接收组件里选用port时就可以根据我们实际需要(nonblocking/blocking还是get/peek)灵活选择对应的port类型,并调用对应的通信方法,fifo把对应的4中通信方法都已经实现了,等于说预留了一个非常灵活的hook,而我们上面scoreboard里使用uvm_blcoking_get_port只是其中的一种实现而已。

而发送端的组件由于使用的是广播包,则不存在阻塞/非阻塞以及是否从fifo中取走数据这种,所以不需要在imp端预留多种实现。

通过以上对源代码的分析我们便可以清晰地认识到,当我们在不同组件间使用uvm_tlm_analysis_fifo作为中介通信时,fifo内部的analysis_export/blocking_get_export是如何实现的。

那我们不禁要问,uvm_tlm_(analysis)_fifo里除了我们用的这两个imp类型外,其他一些imp类型什么时候会用到呢?进一步对源代码里关于uvm_tlm_fifo_base里的各种imp进行分析
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

通过以上对类uvm_tlm_fifo_base的代码分析,我们得出以下结论:

  1. 定义了两个uvm_analysis_port,分别为put_ap和get_ap,这两个port是可以连到fifo之外的uvm_analysis_imp的,这两个port在uvm_tlm_fifo内部实现的相关通信算法(put/try_put/get/try_get)里被调用,而且实现又是在与该port相连的imp所在的组件内实现的如下图所示。
    在这里插入图片描述

这样我们便发现要想使用这两个uvm_analysis_port就必须将fifo里的put_ap/get_ap连到外面的某个组件的uvm_analysis_imp里,并且在其中实现相应的write(input/output T tr)函数。并且这个通信函数在fifo里被调用是通过另一个通信函数实现的,因而需要调用fifo里的put/get/try_put/try_get方法,这样就需要与fifo内部相应imp连接的外部port所在的组件里调用以上四种通信方法,于是我们得出的结论就是put_ap和get_ap并不是fifo主动调用write函数,而是通过外面port所在组件调用put/try_put/来将数据传递给put_ap连接的外部imp所在组件或调用get/try_get从get_ap连接的外部imp所在组件获取数据,这里fifo只是起到一个中介作用,所以put_ap/get_ap使用范围很有限。

  1. uvm_tlm_fifo_base除了put_ap和get_ap另外还定义了10个imp类型。可以氛围uvm_put_imp和uvm_get_peek_imp两大类,这两中imp多对应的句柄在new阶段分别指向两个同类型的imp的对象put_export和get_peek_export,换句话说,我们连接tvm_tlm_fifo里的同类型的imp对应的不同port名称时,实际他们引用的是同一个imp对象。再换句话说,我们上面scoreboard的port连接到fifo里的blocking_get_export完全可以替换成uvm_get_peek_imp类型声明的其他任意一种imp句柄,之所以用blocking_get_export是想显式的告诉使用者我们实际需要实现的是get任务,即如下修改连接也是可以正常使用的。这就决定了我们uvm_tlm_fifo里的这些同类型的imp是不能同时使用连接到不同的port端进行独立通信的。
    在这里插入图片描述

  2. uvm_tlm_fifo_base定义了各种virtual方法的原型,并且是不能直接在该base类的对象调用使用的,否则会报uvm_report_error,必须在其继承的uvm_tlm_fifo/uvm_tlm_analysis_fifo类的对象调用被override的方法,如下图所示
    在这里插入图片描述

  3. uvm_tlm_fifo中通信的数据都会放在一个mailbox中(默认大小是1,创建fifo时可以指定大小,用默认值时要保证两次write之间一定要将fifo中数据取走),并且有且只有一个,这就决定了该fifo不能连接多个不同的组件对进行同行,即一个fifo对应一组组件,可以通过调用fifo里的函数实时获取mailbox相关的信息。
    在这里插入图片描述
    在这里插入图片描述

  4. uvm_tlm_analysis_fifo在uvm_tlm_fifo的基础上只是增加了一个uvm_analysis_imp类型的analysis_export和一个write函数的实现,在源代码中这俩类被放在了同一个文件里。
    在这里插入图片描述

总结:

通过以上对TLM fifo相关的源代码的分析我们便可以清晰地认识到,当我们在不同组件间使用uvm_tlm_analysis_fifo作为中介通信时,fifo内部的imp是如何实现的,而连接段的port类型又是该如何选择。

  • 21
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: uvm_tlm_fifoUVM中的一个通用FIFO组件,用于在不同的TLM层次之间传递数据。它可以在不同的模块之间传递数据,例如在一个生产者和一个消费者之间传递数据。 analysis_fifo是SystemVerilog中的一个FIFO组件,用于在分析层次中传递数据。它可以在不同的模块之间传递数据,例如在一个测试模块和一个设计模块之间传递数据。 ### 回答2: uvm_tlm_fifoUVM中的一个事务级FIFO,它支持多种类型的事务,包括简单的数据类型、类对象、以及自定义的事务类型。uvm_tlm_fifo使用SystemVerilog中的默认队列实现,并提供了一些附加功能,如写指针写入回显、读指针读出回显、读写指针差值、可选的后退压制等。此外,uvm_tlm_fifo还支持多个消费者和生产者,并且使用事务优先级来管理写入和读取操作。 相比之下,analysis_fifo是在SystemVerilog中实现的一种FIFO,它主要是用于在SV测试环境中进行分析。分析事件和变量的读取操作可以直接使用analysis_fifo来实现,通过它,可以在测试中获取特定数据的采样,实现在事务之间的数据共享。 两种FIFO的主要区别在于它们的实现方式和使用场景。uvm_tlm_fifoUVM中的一个通用FIFO,可用于多个类别事务的传输,而analysis_fifo则更侧重于测试数据的采集和分析。在实际应用中,根据具体的使用场景,需要选择特定的FIFO类型来完成相关的数据传输和分析任务。 ### 回答3: uvm_tlm_fifoanalysis_fifo是在UVM中用于数据通信和分析的两个重要类。它们都是基于FIFO(先进先出)的数据结构,可以实现对系统中不同模块之间数据的传输和分析。 uvm_tlm_fifoUVM TLM(事务级建模)的一部分,可以实现高层次的通信协议,使得各个模块可以以事务的形式进行通信。uvm_tlm_fifo是一个通用的FIFO,可以用于传输各种类型的数据,如信号、数据、命令、状态等。该类可以用来连接两个或多个模块,使得它们可以相互通信,实现系统级别的协议。 另一方面,analysis_fifo是用于分析数据的FIFO。它可以用来存储不同模块之间的数据、状态和事件等信息,并在需要时对这些信息进行分析和处理。analysis_fifo可以通过UVM提供的数据处理接口将分析数据发送到其他模块,以实现更高级别的分析操作。它是UVM中常用的一种分析工具,可以帮助开发人员更好地理解和解决模拟中的问题。 总之,uvm_tlm_fifoanalysis_fifoUVM中重要的通信和分析工具,它们可以帮助开发人员实现系统级别的通信和分析,提高设计效率和可靠性。使用这些工具可以让开发人员更加容易地调试和验证模型,从而加快项目的开发进程,提高代码的质量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值