问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

UVM事务级建模(TLM)通信机制详解

创作时间:
作者:
@小白创作中心

UVM事务级建模(TLM)通信机制详解

引用
CSDN
1.
https://blog.csdn.net/weixin_42167433/article/details/144078186

TLM(事务级建模)是UVM中一种基于事务的通信方式,通过封装具有特定功能的信息组来实现模块间的高效通信。本文将详细介绍TLM的基本概念、通信对象、传输方式以及各种通信机制的实现细节,帮助读者深入理解UVM中的事务级通信原理。

基本概念

TLM(transaction level modeling)是一个基于事务(transaction)的通信方式,每次传输一个transaction,一个transaction就是把具有某一特定功能的一组信息封装在一起而成为的一个类。

通信对象

  • 发起者:数据的请求方,也就是initiator
  • 响应者:数据的响应方,也就是target
  • 注:发起者和响应者不代表数据的流向性。initiator:永远有主动权,不论时请求数据还是主动发送数据,永远是发起的那一方;target:永远时被动的,只能被动的接收数据,或者被通知需要发送数据;

传输方式

put操作

单向传输,通信动作发起者A把一个transaction发送给B,数据流从A流向B

get操作

单向传输,通信动作发起者A向B索取一个transaction,数据流从B流向A

transport操作

双向传输,又称做request-response操。相当于一次put操作加一次get操作,这两次操作的“发起者”都是A,目标都是B,数据从A流到B,再从B流向A。

通信端口

端口定义

  • port端口:initiator的端口,有阻塞赋值和非阻塞赋值的区分
  • export端口:initiator和target的中转端口,有阻塞赋值和非阻塞赋值的区分
  • imp端口:target端口,有阻塞赋值和非阻塞赋值的区分
  • 注意:
  • 端口优先级:port > export > imp
  • 在connect_phase中使用connect()建立连接关系时,只有优先级高的才能调用connect()做连接(即port可以连接port、export或者imp;export可以连接export或者imp;imp只能作为数据传送的重点,无法扩展连接)
  • 在UVM中,只有IMP才能作为连接关系的终点

UVM常见端口

PORT端口

//blocking阻塞;nonblocking非阻塞;不含这两者表示既可以阻塞也可以非阻塞
uvm_blocking_put_port#(T);
uvm_nonblocking_put_port#(T);
uvm_put_port#(T);
uvm_blocking_get_port#(T);
uvm_nonblocking_get_port#(T);
uvm_get_port#(T);
uvm_blocking_peek_port#(T);
uvm_nonblocking_peek_port#(T);
uvm_peek_port#(T);
uvm_blocking_get_peek_port#(T);
uvm_nonblocking_get_peek_port#(T);
uvm_get_peek_port#(T);
uvm_blocking_transport_port#(REQ, RSP);
uvm_nonblocking_transport_port#(REQ, RSP);
uvm_transport_port#(REQ, RSP);  

EXPORT端口

uvm_blocking_put_export#(T);
uvm_nonblocking_put_export#(T);
uvm_put_export#(T);
uvm_blocking_get_export#(T);
uvm_nonblocking_get_export#(T);
uvm_get_export#(T);
uvm_blocking_peek_export#(T);
uvm_nonblocking_peek_export#(T);
uvm_peek_export#(T);
uvm_blocking_get_peek_export#(T);
uvm_nonblocking_get_peek_export#(T);
uvm_get_peek_export#(T);
uvm_blocking_transport_export#(REQ, RSP);
uvm_nonblocking_transport_export#(REQ, RSP);
uvm_transport_export#(REQ, RSP);  

IMP端口

//IMP定义中的blocking、nonblocking、put、get、peek、get_peek、transport等关键字的意思并不是它们发起做相应类型的操作,而只意味着它们可以和相应类型的PORT或者EXPORT进行通信
//每一个IMP需要和一个component相对应
uvm_blocking_put_imp#(T, IMP);
uvm_nonblocking_put_imp#(T, IMP);
uvm_put_imp#(T, IMP);
uvm_blocking_get_imp#(T, IMP);
uvm_nonblocking_get_imp#(T, IMP);
uvm_get_imp#(T, IMP);
uvm_blocking_peek_imp#(T, IMP);
uvm_nonblocking_peek_imp#(T, IMP);
uvm_peek_imp#(T, IMP);
uvm_blocking_get_peek_imp#(T, IMP);
uvm_nonblocking_get_peek_imp#(T, IMP);
uvm_get_peek_imp#(T, IMP);
uvm_blocking_transport_imp#(REQ, RSP, IMP);
uvm_nonblocking_transport_imp#(REQ, RSP, IMP);
uvm_transport_imp#(REQ, RSP, IMP);  

通信方式

一对一通信(port-export-imp)

基本概念

类型

  • port-imp互联
  • export-imp互联
  • port-port互联,PORT与PORT之间的连接可以有无限多层。
  • export-export互联,EXPORT与EXPORT之间的连接可以有无限多层

端口互联对应关系

发起者(port/export/transport)类型 imp中对应的任务/函数

| blocking_put | put |
| nonblocking_put | try_put和can_put |
| put | put、try_put和can_put |
| blocking_get | get |
| nonblocking_get | try_get和can_get |
| get | get、try_get和can_get |
| blocking_peek | peek |
| nonblocking_peek | try_peek和can_peek |
| peek | peek、try_peek和can_peek |
| blocking_get_peek | get和peek |
| nonblocking_get_peek | try_get和can_get、try_peek和can_peek |
| get_peek | get和peek、try_get和can_get、try_peek和can_peek |
| blocking_transport | transport |
| nonblocking_transport | nb_transport |
| transport | transport和nb_transport |

注:对于blocking的端口,可以定义相应的任务或函数;对于nonblocking端口,只能定义函数

一对多通信(analysis_port/analysis_export-analysis_imp)

基本概念

  • 一个analysis_port(analysis_export)可以连接多个analysis_imp
  • 对于analysis_port和analysis_export来说,没有阻塞和非阻塞的概念
  • analysis_port如果和analysis_export直接相连也会出错,只有在analysis_export后面再连接一级uvm_analysis_imp,才不会出错

端口互联对应关系

analysis_port和analysis_export类型 analysis_imp对应函数

| * | write |

注:对于同一个component下需要用到多个uvm_analysis_imp的场景,解决方式可通过定义宏`uvm_analysis_imp_decl(_xxx),声明多个后缀不一样的imp,UVM会根据后缀内建不同的imp。

//my_scoreboard.sv

`uvm_analysis_imp_decl(_monitor)
`uvm_analysis_imp_decl(_model)
class my_scoreboard extends uvm_scoreboard;
    my_transaction expect_queue[$];
    uvm_analysis_imp_monitor#(my_transaction, my_scoreboard) monitor_imp;
    uvm_analysis_imp_model#(my_transaction, my_scoreboard) model_imp;
    ...

    extern function void write_monitor(my_transaction tr);
    extern function void write_model(my_transaction tr);
    extern virtual task main_phase(uvm_phase phase);

endclass
function void my_scoreboard::write_model(my_transaction tr);
    expect_queue.push_back(tr);
endfunction
function void my_scoreboard::write_monitor(my_transaction tr);
    my_transaction tmp_tran;
    bit result;
    if(expect_queue.size() > 0) begin
        ...
    end
endfunction  

FIFO通信

基本概念

  • uvm_analysis_fifo,本质是一块缓存加两个imp

类型

端口类型 区别

| uvm_tlm_fifo | 无以下 |
| uvm_tlm_analysis_fifo | 有一个analysis_export端口,及其配套的write函数 |

FIFO端口

  • FIFO中端口有关键字export,但是其类型却是IMP。如analysis_export的原型如下:
uvm_analysis_imp #(T, uvm_tlm_analysis_fifo #(T)) analysis_export;  
  • FIFO中的get端口,get任务被调用时,FIFO内部缓存中会少一个transaction
  • FIFO中的peek端口,peek任务被调用时,FIFO会把transaction复制一份发送出去,其内部缓存中的transaction数量并不会减少
  • 当FIFO中的put端口被连接时,FIFO内部被定义的put任务被调用,它把传递过来的transaction放在FIFO内部的缓存里,同时,把这个transaction通过put_ap使用write函数发送出去
virtual task put( input T t );
    m.put( t );
    put_ap.write( t );
endtask  
  • 与put_ap相似,当FIFO的get任务被调用时,同样会有一个transaction从get_ap上发出
virtual task get( output T t );
    m_pending_blocked_gets++;
    m.get( t );
    m_pending_blocked_gets--;
    get_ap.write( t );
endtask  

FIFO调试函数

函数 作用

| used | 查询FIFO缓存中有多少transaction |
| is_empty | 判断当前FIFO缓存是否为空 |
| is_full | 判断当前FIFO缓存是否为满 |
| flush | 清空FIFO缓存中的所有数据,它一般用于复位等操作 |

//FIFO的new函数原型
function new(string name, uvm_component parent = null, int size = 1);
//第三个参数size,用于设定FIFO缓存的上限,默认的情况下为1。若要把缓存设置为无限大小,将传入的size参数设置为0即可。通过size函数可以返回这个上限值。  

FIFO与IMP对比

  • FIFO对于初学者,使用方式比IMP简洁易上手
  • FIFO连接的方式增加了env中代码的复杂度
  • 对于使用端口数组的情况,FIFO要优于IMP
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号