文章目录

  • 一、两对象与三端口
    • 1.1.两个通信对象:initiator、target
    • 1.2.三个通信端口:port、export、imp——控制流的体现
  • 二、TLM通信方式——一对一传输
    • 2.1.单向传输——put( )和get( )操作传输
    • 2.2.双向传输——transport( )操作传输
    • 2.3.跨层次传输——uvm_analysis_port
  • 三、TLM通信方式——一对多传输
    • 3.1.通信管道——TLM FIFO
    • 3.2.分析端口——Analysis port(一对多传输、最常用)

  TLM(transaction level modeling)是一个基于事务(transaction)的通信方式,通常在高抽象级的语言中被引用作为模块之间的通讯方式,例如SystemC或者UVM。TLM通信需要两个通信的对象,这两个对象分别称之为initiator和target。

一、两对象与三端口

1.1.两个通信对象:initiator、target

  • initiator:通信请求的发起方,属于initiator;
  • target : 通信请求的响应方,谁就属于target;

  注意:通信发起方并不代表了transaction的流向起点,即不一定数据是从initiator流向target,也可能是从target流向了initiator。因此,按照transaction的流向,我们又可以将两个对象分为producerconsumer。区分它们的方法:

  • producer:生产数据方,即为producer;
  • consumer:接收数据方,即为consumer;

1.2.三个通信端口:port、export、imp——控制流的体现

通信端口按照类型可以划分为三种:

  1. port:通信请求方initiator的发起端,initiator凭借port端口才可以访问target。
  2. export:作为initiator和target中间层次的端口
  3. imp:只能作为target接收请求的响应端,它无法作为中间层次的端口,所以imp的连接无法再次延伸。

  端口优先级:port > export > imp, 使用connect()建立连接关系时,只有优先级高的才能调用connect()做连接,即port可以连接port、export或者imp;export可以连接export或者imp;imp只能作为数据传送的重点,无法扩展连接。三种端口非是uvm_component的子类,应该使用new()函数在build_phase中创建。(注意:不能用create创建,端口不属于UVM树的一部分)。

二、TLM通信方式——一对一传输

  按通信传输的方向可以分为单向(unidirection)和双向(bidirection)。
需要说明的是,不论是单向传输还是双向传输都有阻塞和非阻塞之分。下面以阻塞传输为中心。

  • 单向传输:由initiator发起request transaction,数据有生产方producer发送到数据接收方consumer。
  • 双向传输:由initiator发起request transaction,传送至target;而target在消化了request transaction后,也会发起response transaction,继而返回给initiator。数据的流向是双向的。

2.1.单向传输——put( )和get( )操作传输

2.1.1. Put( )型操作传输

  • 单向通信中,port和export端口的参数只有一个;imp端口,参数有两个,第一个是传递的item类,第二个是实现该端口的component
  • 端口的实例化 使用new()函数在build_phase中创建
  • 阻塞的方法类型为task,这保证了可以实现等待事件和延时;非阻塞的方法类型为function,这确保了方法调用可以立刻返回。
  • 发起者的动作实现,最终会落到终点IMP所在的component中,因此必须 在imp所在的component中定义名字为put/get/transport的函数或任务,完成最终的数据传输操作。
class transaction extends uvm_transaction;      //传输数据包int id;int data;...
endclassclass producer extends uvm_component;            //数据生产方producer...uvm_blocking_put_port#(transaction)     put_port;     //定义端口function void build_phase(uvm_phase phase);put_port = new("put_port",this);               //创建实例化端口endfunctiontask run_phase(uvm_phase phase);        put_port.put(tr);        //1. 通过数据接收方consumer提供的任务put()处理数据,然后通过TLM传输数据过去endtask
endclassclass consumer extends uvm_component;            //数据接收方consumer...uvm_blocking_put_imp#(transaction, consumer)     put_imp;     //定义端口function void build_phase(uvm_phase phase);put_imp = new("put_imp",this);               //创建实例化端口endfunctionvirtual task put(transaction tr);        //数据生产方producer会调用接收方consumer定义的put()任务process(tr);        //2. 通过数据接收方consumer提供的任务put()处理数据endtask
endclassclass environment extends uvm_env;       //环境层...producer    p;    //数据生产方consumer    c;    //数据接收方...virtual function void connect_phase(uvm_phase phase);p.put_port.connect(c.put_imp);       //建立连接endfunction
endclass

1)、上述代码分别在producer和consumer中声明并例化了两个端口实例:

     uvm_blocking_put_port #(transaction)         put_port;
     uvm_blocking_put_imp #(transaction,consumer)   put_imp;

2)、在environment环境对producer与consumer进行连接之前,需要在consumer中实现两个端口对应的方法
    virtual task put( transaction  tr );    //阻塞端口需要定义为任务task
3)、最后在environment中对两个组件之间的端口进行了连接,这使得producer的run phase中可以通过自身的两个端口间接调用consumer中的方法。需要注意的是,在调用方法之前的几个步骤是必不可少的:

     – 定义端口
     – 实现对应方法
     – 在上层将端口进行连接

2.1.2.Get( )型操作传输

class transaction extends uvm_transaction;      //传输数据包int id;int data;...
endclassclass producer extends uvm_component;            //数据生产方producer...uvm_blocking_get_imp#(transaction,producer)     get_imp;     //定义端口function void build_phase(uvm_phase phase);get_imp = new("put_imp",this);               //创建实例化端口endfunctionvirtual task get(output transaction tr);        //在imp端口所在component中定义get()任务或者方法,output方向tr = transaction::type_id::create("tr",this);     endtask
endclassclass consumer extends uvm_component;            //数据接收方consumer...uvm_blocking_get_port#(transaction, consumer)     get_port;     //定义端口function void build_phase(uvm_phase phase);put_imp = new("put_imp",this);               //创建实例化端口endfunctiontask run_phase(uvm_phase phase);        get_port.get(tr);        //通过imp所在component定义的get()处理数据,然后通过TLM传输数据endtask
endclassclass environment extends uvm_env;       //环境层...producer    p;    //数据生产方consumer    c;    //数据接收方...virtual function void connect_phase(uvm_phase phase);c.get_port.connect(p.get_imp);       //建立连接endfunction
endclass

详细流程参考put( )型操作传输。

2.2.双向传输——transport( )操作传输

  双向传输通信通过transport()任务实现。相当于一次put传输加一次get传输,可以在同一任务调用过程中完成REQ和RSP的发出和返回;

class comp1 extends uvm_component;`uvm_component_utils(comp1)uvm_blocking_transport_port #(itrans,otrans) t_port;...virtual function void build_phase(uvm_phase phase);super.build_phase(phase);t_port=new("t_port",this);      //transort端口实例化endfunctionvirtual task run_phase(uvm_phase phase);super.run_phase(phase);itransactions itrs;        //生产数据,输入otransactions otrs;        //响应数据,返回itrs=new("itrs");t_port.transport(itr,otrs);       //调用comp2中声明的transport()....endtask
endclassclass comp2 extends uvm_component;`uvm_component_utils(comp2)uvm_blocking_transport_imp #(itransactions,otransactions,comp2) t_imp;//注意imp端口多一个组件参数...virtual function void build_phase(uvm_phase phase);super.build_phase(phase);t_imp=new("t_imp",this);        //例化端口endfunctiontask transport(input itransactions req, output otransactions rsp);      //编写transport方法rsp=new("rsp");.....endtask
endclassclass env1 extends uvm_env;`uvm_component_utils(env1)comp1 c1;comp2 c2;...virtual function void connect_phase(uvm_phase phase);super.connect_phase(phase);c1.t_port.connect(c2.t_imp);endfunction
endclass

1)、首先在comp1和comp2中分别例化了transport端口:

  • uvm_blocking_transport_port #(itrans,otrans)     t_port;
         //双向通信,port和export端口的参数有两个,分别表示REQ和RSP
  • uvm_blocking_transport_imp#(itrans,otrans,comp2)     t_imp;
         //双向通信,imp端口的参数有三个,分别表示REQ和RSP,以及实现该端口的component

2)、然后在env1环境对comp1与comp2进行连接之前,需要在comp2中实现两个端口对应的方法 task transport();

3)、最后在env1中对两个组件之间的端口进行了连接,这使得comp1的run_phase中可以通过自身的端口间接调用comp2中的方法;

从上面的例码可以看出,类似于单向端口连接的是端口的例化和连接,不同的只是要求实现对应的双向传输任务。

  task transport(input itrans req, output otrans rsp);

2.3.跨层次传输——uvm_analysis_port

方法1:

  在复杂的UVM TB中常用到port跨多级component连接的情形,在多层次连接中,connect要按控制流逐层进行连接。在一个path中,始终只会有一个imp作为连接的结尾。

  以agent中的monitor与scoreboard通信为例:

class monitor extends uvm_monitor;...uvm_analysis_port#(transaction)    analysis_port;     //声明端口virtual function void build_phase(uvm_phase phase);this.analysis_port=new("analysis_port",this);    //端口实例化endfunction
endclassclass agent extends uvm_agent;...monitor   mon;uvm_analysis_port#(transaction)    analysis_port;    //声明端口virtual function void build_phase(uvm_phase phase);this.analysis_port=new("analysis_port",this);    //端口实例化endfunctionvirtual function void connect_phase(uvm_phase phase);mon.analysis_port.connect(this.analysis_port);     //相同端口的跨层次连接endfucntion
endclassclass environment extends uvm_env;...agent  agt;scoreboard  sb;...virtual function void connect_phase(uvm_phase phase);agt.analysis_port.connect(sb.analysis_imp);     //不同端口类型连接endfucntion
endclass

方法2:(常用方法) 在agent中声明一个ap,但是不例化它,让其指向monitor中的ap。在env中可以直接连接agent的ap到scoreboard的imp

class monitor extends uvm_monitor;...uvm_analysis_port#(transaction)    ap;     //声明端口virtual function void build_phase(uvm_phase phase);this.ap=new("ap",this);               //端口实例化endfunctiontask main_phase(uvm_phase phase);super.mian_phase(phase);transaction  tr;...ap.write(tr);...endtask
endclassclass agent extends uvm_agent;...monitor   mon;uvm_analysis_port#(transaction)    ap;    //声明端口...virtual function void connect_phase(uvm_phase phase);ap=mon.ap;                            //1. 调用实例化的mon.ap赋值给为实例化的ap,(相当于连接并实例化)...endfucntion
endclassclass scoreboard extends uvm_scoreboard;...uvm_analysis_imp #(transaction, scoreboard)    analysis_imp;...task write(transaction  tr);//do something on trendtask
endclassclass environment extends uvm_env;...agent  agt;scoreboard  sb;...virtual function void connect_phase(uvm_phase phase);agt.ap.connect(sb.analysis_imp);       //2. 不同端口类型连接endfucntion
endclass

三、TLM通信方式——一对多传输

  前面通信有一个共同的地方即都是端对端的方式,同时在target一端需要实现传输方法,例如put()或者get()。这种方式在实际使用过程中也不免会给用户带来一些烦恼:

  • 如何可以不自己实现这些传输方法,同时可以享受到TLM的好处
  • 对于monitor、coverage collector等组件在传输数据时,会存在一端到多端的传输,如何解决这一问题。

3.1.通信管道——TLM FIFO

  uvm_tlm_fifo类是一个新的组件,它继承于uvm_component,且预先内置了多个端口、实现了多个对应方法供用户使用;功能类似mailbox #(T),该邮箱没有尺寸限制,用来存储数据类型T,而uvm_tlm_fifo的多个端口对应的方法都是利用该邮箱实现了数据读写。uvm_tlm_fifo所带的端口类型都是imp!!!

  在前面的例子中,我们通过port和imp实现了将数据从A发送到B,也可以在A和B之间加入一个FIFO进行缓存,如下图:

class my_env extends uvm_env;`uvm_component_utils (my_env)componentA compA;componentB compB;uvm_tlm_fifo #(transaction)    tlm_fifo;//定义TLM FIFO... virtual function void build_phase (uvm_phase phase);super.build_phase (phase);compA = componentA::type_id::create ("compA", this);compB = componentB::type_id::create ("compB", this);tlm_fifo = new ("tlm_fifo", this, 2);    //创建一个深度为2的FIFO,2省略,FIFO无限深endfunctionvirtual function void connect_phase (uvm_phase phase);compA.put_port.connect (tlm_fifo.put_export);compB.get_port.connect (tlm_fifo.get_export);endfunctionvirtual task run_phase (uvm_phase phase);forever begin#10 if (tlm_fifo.is_full ())//uvm_tlm_fifo常用的方法见UVM手册,FIFO为满时打印信息`uvm_info ("UVM_TLM_FIFO", "Fifo is now FULL !", UVM_MEDIUM)endendtask
endclass

  FIFO类型有两种,一种为上面介绍的uvm_tlm_fifo,另一种较常用的为uvm_tlm_analysis_fifo。二者的唯一差别在于后者有一个analysis_port端口,且有一个write()函数,而前者没有。
  对于一般用户而言,只需要知道uvm_tlm_analysis_fifo的两个端口即可,即analysis_port与blocking_get_port,前者常用于fifo进数据,后者用于fifo出数据

3.2.分析端口——Analysis port(一对多传输、最常用)

  UVM提供了一种分析端口(analysis port),它在组件中是以广播(broadcast)的形式向外发送数据的,而不管存在几个imp或者没有imp。分析端口的根据端口类型的不同分为:

  • uvm_analysis_port、 uvm_analysis_export、 uvm_analysis_imp
  • 只有一个操作:write()
class componentB extends uvm_component;...uvm_analysis_port #(transaction) ap;        //1.定义分析port端口...virtual function void build_phase (uvm_phase phase);super.build_phase (phase);ap = new ("analysis_port", this);        //2.创建端口对象endfunctionvirtual task run_phase (uvm_phase phase);super.run_phase (phase); for (int i = 0; i < 5; i++) beginsimple_packet pkt = simple_packet::type_id::create ("pkt");pkt.randomize();ap.write (tr);                     //3.调用订阅端(subscriber)的write()方法,将数据发送出去endendtask
endclassclass subscriber extends uvm_component;... uvm_analysis_imp #(transaction, subscriber) analysis_export;//定义分析imp端口...virtual function void write (transaction  tr);     //4. 定义write()方法`uvm_info (get_full_name(), "Sub got transaction", UVM_MEDIUM)endfunction
endclass


在environment中通过分析端口将B与sub1、sub2、sub3连接,如下:

class my_env extends uvm_env;`uvm_component_utils (my_env)componentA  compA;componentB  compB;sub         sub1; sub         sub2; sub         sub3; function new (string name = "my_env", uvm_component parent = null);super.new (name, parent);endfunctionvirtual function void build_phase (uvm_phase phase);super.build_phase (phase);// Create an object of both componentscompA = componentA::type_id::create ("compA", this);compB = componentB::type_id::create ("compB", this);sub1 = sub::type_id::create ("sub1", this);sub2 = sub::type_id::create ("sub2", this);sub3 = sub::type_id::create ("sub3", this);endfunctionvirtual function void connect_phase (uvm_phase phase);compA.put_port.connect (compB.put_export);  compB.ap.connect (sub1.analysis_export);       //5.端口连接compB.ap.connect (sub2.analysis_export);compB.ap.connect (sub3.analysis_export);endfunction
endclass

1). 首先在componentB中定义分析port端口,并在run_phase阶段调用write()函数

  • uvm_analysis_port #(transaction)   ap;
  • ap.write (tr);

2)、 在分析端口的订阅端(subscriber) ,我们需要定义write()方法

3)、在environment中通过分析端口将B与sub1、sub2、sub3连接 ,如下:

  • compB.ap.connect (sub1.analysis_export);
  • compB.ap.connect (sub2.analysis_export);
  • compB.ap.connect (sub3.analysis_export);

参考:https://blog.csdn.net/bleauchat/article/details/90757417

UVM——TLM通信机制(port、export、imp + analysis_port)相关推荐

  1. UVM基础-TLM通信机制(一)

    目录 基本概念 TLM通信分类 单向通信 单向通信举例 单向通信代码 双向通信 多向通信 多向通信总结 通信管道 TLM FIFO Analysis Port Analysis TLM FIFO 芯片 ...

  2. UVM——TLM通信

    UVM--TLM通信 1. 概述 2. 基本概念 3. 分类 4. 端口的使用 1. 概述 在芯片开发流程中,系统原型和芯片验证对项目的助推起到了关键作用 系统原型,一般是通过硬件功能描述文档来模拟硬 ...

  3. 【UVM基础】TLM1.0 通信机制(port/export/imp/analysis_xxx)快速上手指南

    知识点: 通过端口分辨initiator和traget.如:有两个端口port和imp,那initiator一定是port端,而target是imp端:连接的时候也是port.connect(imp) ...

  4. UVM——TLM通信(1)

    目录 TLM的定义 通信的端口定义和所在的组件 单向通信 定义 通信流程 多向通信 定义 通信流程 通信管道 定义 通信流程 前言:基于<UVM实战>和路科讲解的TLM通信,总结一下 TL ...

  5. 【从零开始学习 UVM】10.5、UVM TLM —— UVM TLM Blocking Get Port

    文章目录 UVM TLM Get Port Example 1. 创建一个发送方类,其端口类型为 uvm_blocking_get_imp 3. 创建接收器类,等待 get 方法. 4. 在更高层次上 ...

  6. UVM基础-TLM通信机制(二)

    目录 TLM 2.0 通信 端口定义 传送数据 时间标记 同步通信元件 uvm_event uvm_event 总结 uvm_barrier uvm_callback TLM 2.0 通信 TLM 2 ...

  7. UVM TLM通信简介

    1.UVM put/get通信 在UVM中一对一的TLM有很多种类型,以sequencer和driver为例. driver是请求端,在driver列化了两种端口(在uvm_driver中列化,可直接 ...

  8. TLM通信 — UVM

    文章目录 简介 1.端口的使用 2.单向通信 3.双向通信 4.多向通信 5.通信管道 1. TLM_FIFO 2. Analysis Port 3. Analysis TLM FIFO 4. req ...

  9. UVM学习笔记--TLM通信

    Table of Contents 1.TLM简介 2.UVM TLM基本概念 2.1 TLM 通信常用的的三种传输:Put/Get/Transport 2.2 TLM 通信中的三种端口:Port,E ...

  10. UVM中的TLM通信

    UVM中的TLM通信 1.TLM简介 TLM:Transaction Level Modeling(事务级建模),它是一个独立于语言的一个标准,常用于系统建模,加速软硬件协同开发.在芯片开发中,常配合 ...

最新文章

  1. SQL語句大全4(常用函數)
  2. 《UNIX环境高级编程(第3版)》——1.7 出错处理
  3. 探索从 MVC 到 MVVM + Flux 架构模式的转变
  4. java文本输入输出小结
  5. 【职场】还真的遇到了个失业开滴滴的程序员
  6. CodeForces 11D(状压DP 求图中环的个数)
  7. Docker 架构原理及简单使用
  8. Java学习记录 课程来自黑马刘意(风清扬)19年版
  9. 锐捷 重启计算机,提示“重启计算机后才能使用锐捷客户端”常用解决方法
  10. linux绕过内存写保护,TF卡写保护解决案例教程
  11. audio realtek 耳机没声_解决Realtek High Definition Audio 声卡前面板耳机无声音方法
  12. Android的界面1080,安卓1080P界面设计规范解读
  13. [DEMO] 互联网广告RTB机制简介
  14. BZOJ 2002 HNOI2010 弹飞绵羊 分块
  15. 未睹棺椁先哭君——谷歌墓志铭
  16. noip2015day1
  17. 基于LINUX下ESP_IDF开发环境搭建安装问题总结
  18. oracle 手机、身份证 打码 函数
  19. linux中合并多个文件内容到一个文件的例子
  20. RACSignal 冷信号和热信号底层实现分析

热门文章

  1. 2021SC@SDUSC Zxing开源代码(八)Data Matrix二维码(一)
  2. boost斩波电路控制系统C语言,Boost升压斩波电路[精华]
  3. 实战中,利用10日均线捕捉主升浪,必须满足这四个条件!
  4. 《评人工智能如何走向新阶段》后记(再续11)
  5. Java 编程实例 - 查找数组中的重复元素
  6. dw相对路径怎么改_了解 Dreamweaver 模板中的路径
  7. 华东师范大学夏令营复习计划总结
  8. 计算机重新启动后打印机脱机,重新启动计算机后打印机脱机怎么办
  9. 【Python】爬虫-----下载B站视频
  10. EMQ优特云-贵阳娃哈哈生产基地物联网能耗监控项目回顾与展望