UVM——单向通信

UVM——单向通信

1. 概述

  • 单向通信(unidirectional communication)指的是从initiatortarget之间的数据流向是单一方向的,或者说initiatortarget只能扮演producerconsumer中的一个角色
  • 在UVM中,单一数据流向的TLM端口有很多类型:
    • uvm_blocking_put_PORT
    • uvm_nonblocking_put_PORT
    • uvm_put_PORT
    • uvm_blocking_get_PORT
    • uvm_nonblocking_get_PORT
    • uvm_get_PORT
    • uvm_blocking_peek_PORT
    • uvm_nonblocking_peek_PORT
    • uvm_peek_PORT
    • uvm_blocking_get_peek_PORT
    • uvm_nonblocking_get_peek_PORT
    • uvm_get_peek_PORT

2. 类型

  • PORT代表了三种端口名:port、export、imp
  • 按照UVM端口命的命名规则,它们指出了通信的两个要素:
    • 是否是阻塞的当时(即可以等待延时)
    • 何种通信方法
      在这里插入图片描述

3. 方法

  • 阻塞传输方式将blocking前缀作为函数名的一部分,而非阻塞方式则名为nonblocking。阻塞端口的方法类型为task,这保证了可以实现时间等待和延迟;非阻塞端口的方法类型为function,这确保了方法调用可以立即返回;
  • 从方法名也可以发现,uvm_blocking_put_PORT提供的方法task put()会在数据传送完后返回,uvm_nonblocking_put_PORT对应的两个函数try_put()can_put()是立刻返回的;
  • uvm_put_PORT分别提供了blockinghe nonblock的方法,这为通信方式提供了更多选择。blocking阻塞传输方式包含:
    • Put():initiator先生成数据T t,同时将数据传送至target
    • Get():initiator从target获取数据T t,而target中的该数据T t则应消耗
    • Peek():initiator从target获取数据T t,而target中的数据还应保留
  • 与上面三种任务对应的nonblocking非阻塞方法分别是:
    • try_put()
    • can_put()
    • try_get()
    • can_get()
    • try_peek()
    • can_peek()
  • 这六个非阻塞函数与对应阻塞任务的区别再与,它们必须立即返回,如果try_xxx()函数可以发送或者获取数据,那么函数应该返回1,如果执行失败则应返回0;
  • 或者通过can_xxx()函数先试探target是否可以接收数据,如果可以,再通过try_xxx()函数发送,提高数据发送的成功率;

4. 示例

在这里插入图片描述

class itrans extends uvm_transaction;
	int id;
	int data;
	...
endclass

class otrans extends uvm_transaction;
	int id;
	int data;
	...
endclass

class comp1 extends uvm_component;
	uvm_blocking_put_port #(itrans) bp_port;
	uvm_nonblocking_get_port #(otrans) nbg_port;
	
	`uvm_component_utils(comp1)
	...
	
	task run_phase(uvm_phase phase);
		itrans itr;
		otrans otr;
		int trans_num = 2;
		fork
			begin
				for(int i = 0; i < trans_num; i++) begin
					itr = new("itr", this);
					itr.data = 'h10 + 1;
					this.bp_port.put(itr);
					`uvm_info("PUT", $sformatf("put itrans id: 'h%0x, data: 'h%0x", itr.id, itr.data), UVM_LOW)
				end
			end
			begin
				for(int j = 0; j < trans_num; j++) begin
					forever begin
						if(this.nbg_port.try_get(otr) == 1) break;
						else #1ns;
					end
					`uvm_info("TRYGET", $sformatf("get otrans id: 'h%0x, data: 'h%0x", otr.id, otr.data), UVM_LOW)
				end
			end
		join
	endtask
endclass

class comp2 extends uvm_component;
	uvm_blocking_put_imp #(itrans, comp2) bp_imp;
	uvm_nonblocking_get_imp #(otrans, comp2) nbg_imp;
	itrans itr_q[$];
	
	`uvm_component_utils(comp2)
	...
	
	task put(itrans t);
		itr_q.push_back(t);
	endtask
	
	function bit try_get(output otrans t);
		itrans i;
		if(itr_q.size() != 0) begin
			i = itr_q.pop_front();
			t = new("t", this);
			t.id = i.id;
			t.data = i.data << 8;
			return 1;
		end else begin
			return 0;
		end
	endfunction
	
	function bit can_get();
		if(itr_q.size() != 0) return 1;
		else return 0;
	endfunction
endclass

class env1 extends uvm_env;
	comp1 c1;
	comp2 c2;
	
	`uvm_component_utils(env1)
	...
	
	function voi build_phase(uvm_phase phase);
		super.build_phase(phase);
		c1 = comp1::type_id::create("c1", this);
		c2 = comp2::type_id::create("c2", this);
	endfunction
	
	function void connect_phase(uvm_phase phase);
		super.connect_phase(phase);
		c1.bp_port.connect(c2.bp_imp);
		c2.nbg_port.connect(c2,nbg_imp);
	endfunction
endclass

  • 首先comp1例化了两个port端口:
    • uvm_blocking_put_port #(itrans) bp_port;
    • uvm_nonblocking_get_port #(otrans) nbg_port;
  • comp2作为target则相应实例化了两个对应的imp端口:
    • uvm_blocking_put_imp #(itrans, comp2) bp_imp;
    • uvm_nonblocking_get_imp #(otrans, comp2) nbg_imp;
  • env1环境将comp1与comp2连接之前,需要在comp2中实现两个端口对应的方法:
    • task put(itrans t)
    • function bit try_get(output otrans t)
    • function bit can_get()
  • 接下来env1对两个嘴贱的端口进行连接,这使得comp1在run_phase可以通过自身端口间接调用comp2中定义的端口方法;
  • 因此在调用端口方法之前的几个步骤是必不可少的:
    • 明确传输的transfer数据类型
    • 定义端口(port和imp要对应成对)
    • 实现对应方法(target一侧实现task或function)
    • 在上层将端口进行连接(initiator.port.connect(target.imp)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值