《UVM实战》学习笔记——第四章 UVM中的TLM1.0通信


前言

2023.2.28 天气晴朗 阳光明媚


不同component之间进行通信:全局变量、通过第三方base test去实例化config_object(get、set)这两种方法等,都比较麻烦

希望两个组件之间可以进行密闭的通信,且通道具有阻塞和非阻塞等性质

一、TLM1.0

1、TLM的定义

TLMTransaction Level Modeling 事务级建模
transaction:把具有某一特定功能的一组信息封装在一起而成为的一个类

(1)几种操作(均有阻塞和非阻塞之分)

  • put:A发送给B一个数据
  • get:A从B拿到一个数据
  • transport:相当于put+get,A发出一个请求,B返回一个应答
  • peek:复制一个数据走,原来的数据还在

2、数据流:数据流动的方向

producer和consumer(transaction的流向)

3、控制流:动作发起者initiator、动作接收者target

  • 优先级依次降低,port使用connect函数去发起连接

  • 三种端口均是uvm_component的子类,但应该使用new()函数在build_phase中创建。

  • 在有Port,Export,IMP连接的data path中,有且必须以IMP(implement port)作为终点,否则的话,程序会报错。Port,Export相当于一道门,没用存储作用。

  • IMP 在声明时相较于Port/Export多了一个类型参数IMP,第一个参数是IMP传输的数据类型,第二个参数是实现这个接口的component

class B extends uvm_component;
   ...
     uvm_blocking_put_export#(my_transaction) B_export;
     uvm_blocking_put_imp#(my_transaction, B) B_imp;
   ...
endclass
  • 通信的实现:发起者的动作实现,最终会落到终点IMP所在的component中,因此必须在IMP所在的component中定义名字为put/get/transport的函数或任务,完成最终的数据传输操作。

当A.port调用put()时,这个任务会调用B.export的put(),B.export的put()又会调用B.imp的put(),而B.imp的put()最终会调用B.put(). 因此用户必须在B中定义put() 函数/任务,否则的话程序会报错。

在这里插入图片描述
在这里插入图片描述

4、各种端口的连接

(1)port和imp连接

当A通过A_port写入一个transaction时,就会去调用B组件的put函数/任务。

A_inst.A_port.connect(B_inst.A_imp);

(2)export和imp连接

(3)port和export连接

(4)port和port连接(同种类型端口连接)
在这里插入图片描述
在class A里面去例化一个class C的对象,然后在class A里面连接C_port和A_port,最后在env环境去连接A_port和B_imp。(跨层次连接)

class A extends uvm_component;
	C C_inst;
	uvm_blocking_put_port#(my_transaction) A_port;
	
	function void build_phase(uvm_phase phase);
		super.build_phase(phase);
		C_inst = C::type_id::create("C_inst",this);
		A_port = new("A_port",this);
	endfunction
	
	function void connect_phase(uvm_phase phase);
		super.connect_phase(phase);
		C_inst.C_port.connect(this.A_port);
	endfunction

(5)export和export连接

总结: 上述端口连接最后都需要以imp作为结尾,可以进行跨层次连接

port不能连接两个imp,多个port可以连接到同一个export或imp,但单个port或export无法连接多个imp。(多对一)

port可以连接port、export或imp,export可以连接export或imp,imp只能作为数据传送的终点,无法扩展连接。(5种)
在这里插入图片描述

5、transport

9种类型的端口:
uvm_blocking_transport_port/export #(REQ, RSP)
uvm_nonblocking_transport_port/export #(REQ, RSP)
uvm_transport_port/export #(REQ, RSP)

uvm_blocking_transport_imp #(REQ, RSP, IMP)
uvm_nonblocking_transport_imp #(REQ, RSP, IMP)
uvm_transport_imp #(REQ, RSP, IMP)

6、nonblocking端口的使用

(1) blocking的端口:可以将put/get/transport定义为function或task;保证了可以实现事件等待和延时
(2)noblocking的端口:则只允许定义成function,保证了方法调用可以立即返回。

没有特意指明阻塞还是非阻塞的话,就都要定义这些函数。

(3)先用can_put函数去看能不能put,再用try_put,提高数据发送的成功率;也可以直接使用try_put,而不用can_put,但是在component B还是要定义这个空函数。

while(!A_port.can_put()) #10;
void'(A_port.try_put(tr));

(4)总结
(路科的这张表上阻塞的话只写了定义为任务,下面白皮书上则写了阻塞可以定义为函数或任务)
在这里插入图片描述

在这里插入图片描述
master端口和slave端口的区别:当initiator作为master时,它会发送REQ至target,而后再从target端获取RSP;当initiator使用slave端口时,它会先从target端获取REQ,而后将RSP送至target端。

slave端口要显示声明参数类型为output,否则默认的是input。

在这里插入图片描述

二、UVM中的通信方式

1、analysis端口

除了port、export、imp端口外,还有两种analysis_portanalysis_export

(1)两者对比
相同点:都用于传递transaction
不同点
一个analysis端口可以连接多个imp(一对多),而一个port/export只可以连接一个imp(一对一)。
前者没有阻塞和非阻塞区分,因为同时连接了多个端口,后者有阻塞和非阻塞之分。
前者只有write操作,后者有put try_put can_put这三种操作。

(2)analysis_portanalysis_port直接相连会报错,必须再和analysis_imp相连。

(3)monitor和scoreboard有三种通信方式
a. 跨层次连接,写绝对路径
b. 在agent例化一个analysis_port,作为中介和monitor、scb的ap相接
c. 在agent声明一个ap,不例化,让其指向monitor的ap,再与scb相连(推荐该方式
在这里插入图片描述

(4)宏uvm_analysis_imp_decl:解决scb里面有两个imp,因此要写两个write函数如何区分的问题。使用这个宏会定义两个新的IMP类

2、FIFO通信

(1)uvm_tlm_analysis_fifo:本质上是一块缓存+2个IMP

(2)monitor、scb、model之间的通信
首先monitor收集数据可能给到很多地方,会用到广播模式,所以monitor的端口用的是analysis_port,同理reference model也用到了analysis_port。
在这里插入图片描述
在这里插入图片描述

而scb两个端口都是去从monitor、model获得数据,所以使用的是uvm_blocking_get_port
在这里插入图片描述

在env中创建组件和fifo
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

(3)为什么fifo里面的端口叫analysis_export和blocking_get_export?
只是叫做这个名字,本质上类型都是imp

3、两种TLM FIFO

(1)uvm_tlm_fifo: 包含analysis 端口以外的多有端口,不支持write操作。

左边是端口类型,右边是定义的名字。可以看到上述端口为imp类型。
在这里插入图片描述

(2)uvm_tlm_analysis_fifo: 含有下图中的所有端口,支持write操作。(一般用这种)有analysis_export,write函数。
uvm_tlm_analysis_fifo继承于uvm_tlm_fifo,添加了uvm_analysis_imp端口和write函数。

12个IMP + 两个analysis_port
在这里插入图片描述

在这里插入图片描述
put_ap:当往fifo的buffer写入一笔transaction,这个transaction同时会通过put_ap的write函数写到第三方component中。(例如monitor里面的ap.write(tr)

get_ap:从fifo的buffer读出一笔transaction,这个transaction自然会发给fifo get export连接的component,但同时会通过put_ap写到第三方component中。(例如scb中的exp_port.get(exp_expect)

在这里插入图片描述

在这里插入图片描述

4、FIFO的内置函数

used:查询fifo里存了多少transaction
is_empty: 判断当前fifo是否为空
is_full: 判断当前fifo是否满了
flush:清空fifo中缓存的数据,复位时可以用
TLM FIFO默认的深度是1,如果需要更改,可以在new()是更改参数size的值,如需要无限大小,就将传入的size参数设为0。

5、TLM FIFO的好处

不用在scb中写write函数;target中不需要再定义方法,而且从imp变成了port。

三、Request and Response通信管道

适合双向通信的管道、数据缓存

1、uvm_tlm_req_rsp_channel

内部例化了两个mailbox来分别存储request和response
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

也可以用master和slave来传输,master里面定义了put/get/peek
在这里插入图片描述

2、uvm_tlm_transport_channel

继承于uvm_tlm_req_rsp_channel,新添加了transport端口
在这里插入图片描述

在这里插入图片描述

四、TLM2.0

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值