UVM实现component之间transaction级别的通信


        my_model是从i_agt中得到my_transaction,并把 my_transaction传递给my_scoreboard。在UVM中,通常使用TLM(Transaction Level Modeling)实现component之间transaction级别 的通信

        在UVM的transaction级别的通信 中,数据的发送有多种方式,其中一种是使用uvm_analysis_port。

(1)使用uvm_analysis_port发送数据

        在my_monitor中定义如下变量:

my_monitor.sv

uvm_analysis_port #(my_transaction) ap;/// 声明了ap

        uvm_analysis_port是一个参数化的类,其参数就是这个analysis_port需要传递的数据的类型,在例中是my_transaction。
         声明了ap后,需要在monitor的build_phase中将其实例化:

my_monitor.sv

   virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      if(!uvm_config_db#(virtual my_if)::get(this, "", "vif", vif))
         `uvm_fatal("my_monitor", "virtual interface must be set for vif!!!")
      ap = new("ap", this);///在monitor的build_phase中将其实例化
   endfunction

        在main_phase中,当收集完一个transaction后,需要将其写入ap中:

task my_monitor::main_phase(uvm_phase phase);
    my_transaction tr;
        while(1) begin
            tr = new("tr");
            collect_one_pkt(tr);
            ap.write(tr);当收集完一个transaction后,需要将其写入ap中
    end
endtask

        write是uvm_analysis_port的一个内建函数。到此,在my_monitor中需要为transaction通信准备的工作已经全部完成。

(2)使用uvm_blocking_get_port接收数据

        UVM的transaction级别通信的数据接收方式也有多种,其中一种就是使用uvm_blocking_get_port。这也是一个参数化的类,其 参数是要在其中传递的transaction的类型

        在my_model的第6行中,定义了一个端口,并在build_phase中对其进行实例化。

my_model.sv

   uvm_blocking_get_port #(my_transaction)  port;//定义端口


function void my_model::build_phase(uvm_phase phase);
   super.build_phase(phase);
   port = new("port", this);  //在build_phase中对其进行实例化
   ap = new("ap", this);
endfunction

        在 main_phase中,通过port.get任务来得到从i_agt的monitor中发出的transaction

task my_model::main_phase(uvm_phase phase);
   my_transaction tr;
   my_transaction new_tr;
   super.main_phase(phase);
   while(1) begin

      port.get(tr);//在 main_phase中,
                    //通过port.get任务来得到从i_agt的monitor中发出的transaction

      new_tr = new("new_tr");
      new_tr.my_copy(tr);
      `uvm_info("my_model", "get one transaction, copy and print it:", UVM_LOW)
      new_tr.my_print();
      ap.write(new_tr);
   end
endtask

        在my_monitor和my_model中定义并实现了各自的端口之后,通信的功能并没有实现,还需要在my_env中使用fifo将两个端口 联系在一起。在my_env中定义一个fifo,并在build_phase中将其实例化

my_env.sv

uvm_tlm_analysis_fifo #(my_transaction) agt_mdl_fifo;

   virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      i_agt = my_agent::type_id::create("i_agt", this);
      o_agt = my_agent::type_id::create("o_agt", this);
      i_agt.is_active = UVM_ACTIVE;
      o_agt.is_active = UVM_PASSIVE;
      mdl = my_model::type_id::create("mdl", this);

        //实例化agt_mdl_fifo
      agt_mdl_fifo = new("agt_mdl_fifo", this);


   endfunction

        fifo的类型是uvm_tlm_analysis_fifo,它本身也是一个参数化的类,其参数是存储在其中的transaction的类型,这里是 my_transaction
        之后,在connect_phase中将fifo分别与my_monitor中的analysis_port和my_model中的blocking_get_port相连

function void my_env::connect_phase(uvm_phase phase);
   super.connect_phase(phase);
   i_agt.ap.connect(agt_mdl_fifo.analysis_export);
   mdl.port.connect(agt_mdl_fifo.blocking_get_export);
endfunction

        这里引入了connect_phase。与build_phase及main_phase类似,connect_phase也是UVM内建的一个phase,它在build_phase执行 完成之后马上执行。但是与build_phase不同的是,它的执行顺序并不是从树根到树叶,而是从树叶到树根——先执行driver和 monitor的connect_phase,再执行agent的connect_phase,最后执行env的connect_phase
         为什么这里需要一个fifo呢?不能直接把my_monitor中的analysis_port和my_model中的blocking_get_port相连吗?由于 analysis_port是非阻塞性质的,ap.write函数调用完成后马上返回,不会等待数据被接收。假如当write函数调用时, blocking_get_port正在忙于其他事情,而没有准备好接收新的数据时,此时被write函数写入的my_transaction就需要一个暂存的位 置,这就是fifo。
        在如上的连接中,用到了i_agt的一个成员变量ap,它的定义与my_monitor中ap的定义完全一样:

my_agent.sv

class my_agent extends uvm_agent ;
   my_driver     drv;
   my_monitor    mon;
   
   uvm_analysis_port #(my_transaction)  ap;
   
   function new(string name, uvm_component parent);
      super.new(name, parent);
   endfunction 

        与my_monitor中的ap不同的是,不需要对my_agent中的ap进行实例化,而只需要在my_agent的connect_phase中将monitor的值 赋给它,换句话说,这相当于是一个指向my_monitor的ap的指针

my_agent.sv

function void my_agent::connect_phase(uvm_phase phase);
   super.connect_phase(phase);
   ap = mon.ap;
endfunction

        根据前面介绍的connect_phase的执行顺序,my_agent的connect_phase的执行顺序早于my_env的connect_phase的执行顺序,从 而可以保证执行到i_agt.ap.connect语句时,i_agt.ap不是一个空指针。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/219827.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【已验证】SqlBulkCopy 执行批量插入的时候报超时问题-解决办法

把datatable里面的数据插入到数据库,但是数据量大的情况下批量插入会提示超时,所以把datatable的数据分批写入数据库的 using (SqlConnection connection new SqlConnection(ConnectionString)){connection.Open();int pageSize 100000;//SqlBulkCopy大…

Linux各目录结构说明

文章目录 目录说明源码放哪里?拓展:Linux里面安装软件是装在home目录还是opt目录还是/usr/local好? bin boot dev etc home lib lib64 lostfound media mnt opt proc root run sbin srv sys tmp usr var 目录说明 bin 存放二进制可执行文件&…

C语言每日一题(46)整数转罗马数字

力扣网12 整数转罗马数字 题目描述 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。 字符 数值 I 1 V 5 X 10 L 50 C 100 D …

手机如何设置防骚扰电话?

很多人都曾接到过烦人的推销电话,这些电话不仅让人感到烦恼,而且有时候还会接二连三地打来,让人不胜其烦。我们的手机号码似乎已经被泄露,很难避免这些骚扰。 有时,我们因无法忍受骚扰电话而选择立即将其拉黑&#xff…

ROW_NUMBER()函数——(分组后取每组最新的两条数据)

ROW_NUMBER() 功能:简单的说row_number()从1开始,为每一条分组记录返回一个数字。 用法一: ROW_NUMBER() OVER (ORDER BY col DESC) 说明:先把col列降序,再为降序后的每条col记录返回一个序号 用法二&#xf…

Linux系统---图书管理中的同步问题

顾得泉:个人主页 个人专栏:《Linux操作系统》 《C/C》 《LeedCode刷题》 键盘敲烂,年薪百万! 一、问题描述 (1)图书馆阅览室最多能够容纳N(N5)名学生,若有更多学生想…

玩转大数据7:数据湖与数据仓库的比较与选择

1. 引言 在当今数字化的世界中,数据被视为一种宝贵的资源,而数据湖和数据仓库则是两种重要的数据处理工具。本文将详细介绍这两种工具的概念、作用以及它们之间的区别和联系。 1.1. 数据湖的概念和作用 数据湖是一个集中式存储和处理大量数据的平台&a…

【FreeRTOS】消息队列——简介、常用API函数、注意事项、项目实现

在嵌入式系统开发中,任务间的通信是非常常见的需求。FreeRTOS提供了多种任务间通信的机制,其中之一就是消息队列。消息队列是一种非常灵活和高效的方式,用于在不同的任务之间传递数据。通过消息队列,任务可以异步地发送和接收消息…

优化您的Mac体验——System Dashboard Pro for Mac(系统仪表板)

作为Mac用户,我们都希望能够拥有一个高效、流畅的电脑体验。然而,在长时间使用后,我们的Mac可能会变得越来越慢,导致我们的工作效率下降。这时候,System Dashboard Pro for Mac(系统仪表板)就可以派上用场了。它是一款…

vivado时序方法检查2

TIMING-4 &#xff1a; 时钟树上的基准时钟重新定义无效 时钟树上的时钟重新定义无效。基准时钟 <clock_name> 是在时钟 <clock_name> 下游定义的 &#xff0c; 并覆盖其插入延迟和/ 或波形定义。 描述 基准时钟必须在时钟树的源时钟上定义。例如 &#xff0…

mongdb配置ssl

mongodb5.0.9 centos7.6 x86 1、正常启动mongod -f mongodb.conf 【前言】 ssl配置流程步骤&#xff0c;按照以下顺序处理即可。 1.生成证书&#xff0c;根证书&#xff0c;服务端证书&#xff0c;客户端证书 2.配置服务端ssl配置&#xff0c;测试she…

Arrays类 - Java

Arrays类 Arrays类1、常用方法案例 Arrays类 1、常用方法 Arrays 里面包含了一系列静态方法&#xff0c;用于管理或操作数组(比如排序和搜索)。 toString 返回数组的字符串形式 Arrays.toString(arr)【案例1】 sort 排序(自然排序和定制排序) Integer arr[]{1, -1, 7, 0, 8…

云服务器部署过程(从零开始)

首先介绍如何在 Linux 上复制粘贴 CtrlInsert&#xff0c;或者CtrlshiftC复制文本&#xff0c;使用ShiftInsert或CtrlshiftV 在终端中粘贴文本。 搭建java部署环境 要搭建java部署环境&#xff0c;那么首先就需要在Linux上安装jdk&#xff0c;MySQL等必需工具&#xff0c;接…

01_阿里云_Xshell连接服务器

PC使用Xshell连接阿里云服务器 问题引出 之前使用Xshell连接阿里云服务器连接的好好的&#xff0c;今天准备上去服务器学习Linux发现连不上了&#xff0c;后来发现是防火墙的问题&#xff0c;还有阿里云的安全组也需要设置 解决方案 方法一&#xff1a;&#xff08;简单粗暴…

CGAL的周期三角剖分(相关信息较少)

CGAL的周期二维三角剖分类旨在表示二维平面上的一组点的三角剖分。该三角剖分形成其计算空间的分区。它是一个单纯复体&#xff0c;即它包含任何k-单纯形的所有关联j-单纯形&#xff08;j<k&#xff09;&#xff0c;并且两个k-单纯形要么不重叠&#xff0c;要么共享一个公共…

博客访问量到达2万了!

博客访问量到达2万了&#xff01;这也发生的太快了吧&#xff0c;前两天才1万7千访问量&#xff0c;用了平台送的1500的流量券&#xff0c;粉丝从1个&#xff08;N年前的&#xff09;&#xff0c;蹭蹭的往上涨&#xff0c;这也太“假”了吧。关键我也是个菜鸟自学者&#xff0c…

杂散表的阅读

杂散表得阅读 —— 以Marki公司得手册为例 混频杂散&#xff08;Mixing Spurs&#xff09;是指信号经过混频器时&#xff0c;不仅会与本振混频&#xff0c;还会与本振的高次谐波混频&#xff08;对于第二章说的方波本振&#xff0c;信号只与本振的奇次谐波混频因为方波只含有奇…

写论文焦虑?No,免费AI写作大师来帮你

先来看1分钟的视频&#xff0c;对于要写论文的你来说&#xff0c;绝对有所值&#xff01; 还在为写论文焦虑&#xff1f;免费AI写作大师来帮你三步搞定 第一步&#xff1a;输入关键信息 第二步&#xff1a;生成大纲 稍等片刻后&#xff0c;专业大纲生成&#xff08;由于举例&am…

minio配置监听(对象操作日志)

minio配置监听对象操作 本文档适用于minio2021.3.17版本 有时我们需要查看minio中对象操作的日志&#xff0c;比如像监听minio某一个桶中的删除事件&#xff0c;就需要配置监听。minio支持将监听的结果输出到es、pg、amq等等&#xff0c;下面介绍一下将minio对象操作监听结果输…

《C++ Primer》第11章 关联容器

参考资料&#xff1a; 《C Primer》第5版《C Primer 习题集》第5版 关联容器支持高效关键字查找和访问&#xff0c;两个主要的关联容器是 map 和 set 。map 中的元素是键-值&#xff08; key value &#xff09;对&#xff0c;set 中的元素只包含一个关键字。 标准库提供 8 …