UVM之TLM通信中的PORT、EXPORT和IMP

1、PORT、EXPORT和IMP端口简介

LTM通信有三种常用的操作:put操作、get操作和transport操作。其中发起者具有的端口是PORT,接收者具有的端口是EXPORT。这三种操作都有阻塞与非阻塞之分。
常用的PORT端口有:

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端口有:

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具有最低优先级,只有高优先级的端口才能向低优先级的端口发起上述三种操作。

2、PORT与EXPORT的连接

UVM中使用connect函数建立连接关系,如A要与B通信,这么写:A.port.connect(B.export),写成B.export.connect(A.port)是错误的,因为A是发起者,B是被动承担者,主次顺序一定要对。例子如下:
A的代码:

class A extends uvm_component;
		`uvm_component_utils(A);
		uvm_blocking_put_port#(my_transaction) A_port;//定义端口类型
endclass
function void A::build_phase(uvm_phase phase);
		super.build_phase(phase);
		A_port = new("A_port",this);//例化端口
endfunction
task A::main_phase(uvm_phase phase);
		my_transaction tr;
		tr = new("tr");
		assert(tr.randomize());
		A_port.put(tr);//发送tr数据包
endtask

B的代码:

class B extends uvm_component;
		`uvm_component_utils(B);
		uvm_blocking_put_export#(my_transaction) B_export;//定义端口类型
		uvm_blocking_put_imp#(my_transaction,B) B_imp;//定义端口类型
endclass
function void B::build_phase(uvm_phase phase);
		super.build_phase(phase);
		B_export = new("B_export",this);
		B_imp = new("B_imp",this);		
endfunction
function void B::connect_phase(uvm_phase phase);
		super.build_phase(phase);
		B_export.connect(B_imp) ;		
endfunction
function void B::put(my_transaction tr);
		tr.print();
endfunction

在env中建立起两者的连接:

class my_env extends uvm_env;
		A A_inst;
		B B_inst;
endclass
function void my_env::build_phase(uvm_phase phase);
		super.build_phase(phase);
		A_inst = A::type_id::create("A_inst",this);
		B_inst = B::type_id::create("B_inst",this);	
endfunction
function void my_env::connect_phase(uvm_phase phase);
		super.connect_phase(phase);
		A_inst.A_port.connect(B_inst.B_export);
endfunction

3、特别说明

在上述连接关系中,IMP是连接的终点,也只有IMP才能作为连接的终点,PORT或EXPORT作为终点,都会报错。

4、PORT与IMP连接

A的代码:

class A extends uvm_component;
		`uvm_component_utils(A);
		uvm_blocking_put_port#(my_transaction) A_port;//定义端口类型
endclass
function void A::build_phase(uvm_phase phase);
		super.build_phase(phase);
		A_port = new("A_port",this);//例化端口
endfunction
task A::main_phase(uvm_phase phase);
		my_transaction tr;
		tr = new("tr");
		assert(tr.randomize());
		A_port.put(tr);//发送tr数据包
endtask

B的代码:

class B extends uvm_component;
		`uvm_component_utils(B);
		uvm_blocking_put_imp#(my_transaction,B) B_imp;//定义端口类型
endclass
function void B::build_phase(uvm_phase phase);
		super.build_phase(phase);
		B_imp = new("B_imp",this);		
endfunction
function void B::put(my_transaction tr);
		tr.print();
endfunction

在env中建立起两者的连接:

```typescript
class my_env extends uvm_env;
		A A_inst;
		B B_inst;
endclass
function void my_env::build_phase(uvm_phase phase);
		super.build_phase(phase);
		A_inst = A::type_id::create("A_inst",this);
		B_inst = B::type_id::create("B_inst",this);	
endfunction
function void my_env::connect_phase(uvm_phase phase);
		super.connect_phase(phase);
		A_inst.A_port.connect(B_inst.B_imp);
endfunction

5、EXPORT与IMP连接

A的代码:

class A extends uvm_component;
		`uvm_component_utils(A);
		uvm_blocking_put_export#(my_transaction) A_export;//定义端口类型
endclass
function void A::build_phase(uvm_phase phase);
		super.build_phase(phase);
		A_export = new("A_export",this);//例化端口
endfunction
task A::main_phase(uvm_phase phase);
		my_transaction tr;
		tr = new("tr");
		assert(tr.randomize());
		A_export.put(tr);//发送tr数据包
endtask

B的代码:

class B extends uvm_component;
		`uvm_component_utils(B);
		uvm_blocking_put_imp#(my_transaction,B) B_imp;//定义端口类型
endclass
function void B::build_phase(uvm_phase phase);
		super.build_phase(phase);
		B_imp = new("B_imp",this);		
endfunction
function void B::put(my_transaction tr);
		tr.print();
endfunction

在env中建立起两者的连接:

class my_env extends uvm_env;
		A A_inst;
		B B_inst;
endclass
function void my_env::build_phase(uvm_phase phase);
		super.build_phase(phase);
		A_inst = A::type_id::create("A_inst",this);
		B_inst = B::type_id::create("B_inst",this);	
endfunction
function void my_env::connect_phase(uvm_phase phase);
		super.connect_phase(phase);
		A_inst.A_export.connect(B_inst.B_imp);
endfunction

6、PORT与PORT连接

A的代码:

class A extends uvm_component;
		`uvm_component_utils(A);
		uvm_blocking_put_port#(my_transaction) A_port;//定义端口类型
endclass
function void A::build_phase(uvm_phase phase);
		super.build_phase(phase);
		A_port = new("A_port",this);//例化端口
endfunction
task A::main_phase(uvm_phase phase);
		my_transaction tr;
		tr = new("tr");
		assert(tr.randomize());
		A_port.put(tr);//发送tr数据包
endtask

B的代码:

class B extends uvm_component;
		`uvm_component_utils(B);
		A A_inst;
		uvm_blocking_put_port#(my_transaction) B_port;//定义端口类型
endclass
function void B::build_phase(uvm_phase phase);
		super.build_phase(phase);
		A_inst = A::type_id::create("A_inst",this);
		B_port = new("B_port",this);		
endfunction
function void B::connect_phase(uvm_phase phase);
		super.connect_phase(phase);
		A_inst.A_port.connect(this.B_port);
endfunction

task B::main_phase(uvm_phase phase);
	
endtask

C的代码:

class C extends uvm_component;
		`uvm_component_utils(C);
		uvm_blocking_put_imp#(my_transaction,C) C_imp;//定义端口类型
endclass
function void C::build_phase(uvm_phase phase);
		super.build_phase(phase);
		C_imp = new("C_imp",this);		
endfunction
function void C::put(my_transaction tr);
		tr.print();
endfunction

在env中建立起两者的连接:

class my_env extends uvm_env;
		B B_inst;
		C C_inst;
endclass
function void my_env::build_phase(uvm_phase phase);
		super.build_phase(phase);
		B_inst = B::type_id::create("B_inst",this);
		C_inst = C::type_id::create("C_inst",this);	
endfunction
function void my_env::connect_phase(uvm_phase phase);
		super.connect_phase(phase);
		B_inst.B_port.connect(C_inst.C_imp);
endfunction

7、EXPORT与EXPORT连接

A的代码:

class A extends uvm_component;
		`uvm_component_utils(A);
		uvm_blocking_put_port#(my_transaction) A_port;//定义端口类型
endclass
function void A::build_phase(uvm_phase phase);
		super.build_phase(phase);
		A_port = new("A_port",this);//例化端口
endfunction
task A::main_phase(uvm_phase phase);
		my_transaction tr;
		tr = new("tr");
		assert(tr.randomize());
		A_port.put(tr);//发送tr数据包
endtask

B的代码:

class B extends uvm_component;
		`uvm_component_utils(B);
		uvm_blocking_put_export#(my_transaction) B_export;//定义端口类型		
		uvm_blocking_put_imp#(my_transaction,B) B_imp;//定义端口类型
endclass
function void B::build_phase(uvm_phase phase);
		super.build_phase(phase);
		B_export = new("B_export",this);	
		B_imp = new("B_imp",this);		
endfunction
function void B::connect_phase(uvm_phase phase);
		super.build_phase(phase);
		B_imp = new("B_export",this);	
		B_imp = new("B_imp",this);
		this.B_export.connect(this.B_imp);		
endfunction
function void B::put(my_transaction tr);
		tr.print();
endfunction

C的代码:

class C extends uvm_component;
		`uvm_component_utils(C);
		B B_inst;
		uvm_blocking_put_export#(my_transaction) C_export;//定义端口类型
endclass
function void C::build_phase(uvm_phase phase);
		super.build_phase(phase);
		C_export = new("C_export",this);	
		B_inst = B::type_id::create("B_inst",this);	
endfunction
function void B::connect_phase(uvm_phase phase);
		super.connect_phase(phase);
		this.C_export.connect(B_inst.B_export);
endfunction

task C::main_phase(uvm_phase phase);
	
endtask

在env中建立起两者的连接:

class my_env extends uvm_env;
		A A_inst;
		C C_inst;
endclass
function void my_env::build_phase(uvm_phase phase);
		super.build_phase(phase);
		A_inst = A::type_id::create("A_inst",this);
		C_inst = C::type_id::create("C_inst",this);	
endfunction
function void my_env::connect_phase(uvm_phase phase);
		super.connect_phase(phase);
		A_inst.A_port.connect(C_inst.C_export);
endfunction

8、blocking_get端口的使用

get系列端口与put系列端口在某些方面完全相反,如数据流方向与put端口正好相反,例子如下:
A的代码:

class A extends uvm_component;
		`uvm_component_utils(A);
		uvm_blocking_get_export#(my_transaction) A_export;//定义端口类型
	    uvm_blocking_get_imp#(my_transaction,A) A_imp;//定义端口类型
endclass
function void A::build_phase(uvm_phase phase);
		super.build_phase(phase);
		A_export = new("A_export",this);//例化端口
		A_imp = new("A_imp",this);//例化端口
endfunction
function void A::connect_phase(uvm_phase phase);
		super.build_phase(phase);
        A_export.connect(A_imp);
endfunction
task A::get(output my_transaction tr);
		while(tr_q.size() == 0);
		tr = tr_q.pop_front();
endtask
task A::main_phase(uvm_phase phase);
		my_transaction tr;
		tr = new("tr");
		assert(tr.randomize());
		tr_q.push_back(tr);//tr数据包存入队列中
endtask

B的代码:

class B extends uvm_component;
		`uvm_component_utils(B);
		uvm_blocking_put_port#(my_transaction) B_port;//定义端口类型		
endclass
function void B::build_phase(uvm_phase phase);
		super.build_phase(phase);
		B_port = new("B_port",this);		
endfunction
task B::main_phase(uvm_phase phase);
        my_transaction tr;
        while(1)begin
        	B_port.get(tr);
			tr.print();
		end
endtask

在env中建立起两者的连接:

class my_env extends uvm_env;
		A A_inst;
		B B_inst;
endclass
function void my_env::build_phase(uvm_phase phase);
		super.build_phase(phase);
		A_inst = A::type_id::create("A_inst",this);
		B_inst = B::type_id::create("B_inst",this);	
endfunction
function void my_env::connect_phase(uvm_phase phase);
		super.connect_phase(phase);
		B_inst.B_port.connect(A_inst.A_export);
endfunction

9、blocking_transport端口的使用

与put和get系列端口的单向通信不同,transport系列端口通信是双向的,例子如下:
A的代码:

class A extends uvm_component;
		`uvm_component_utils(A);
		uvm_blocking_transport_port#(my_transaction,my_transaction) A_transport;//定义端口类型
endclass
function void A::build_phase(uvm_phase phase);
		super.build_phase(phase);
		A_transport = new("A_transport",this);//例化端口
endfunction
task A::main_phase(uvm_phase phase);
		my_transaction tr;
		my_transaction rsp;		
		tr = new("tr");
		assert(tr.randomize());
		A_transport.transport(tr,rsp); 
		rsp.print();
endtask

B的代码:

class B extends uvm_component;
		`uvm_component_utils(B);
		uvm_blocking_transport_imp#(my_transaction,my_transaction,B) B_imp;//定义端口类型		
endclass
function void B::build_phase(uvm_phase phase);
		super.build_phase(phase);
		B_imp = new("B_imp",this);		
endfunction
task B::transport(my_transaction req,my_transaction rsp);
		req.print();
		rsp = new("rsp");
endtask

在env中建立起两者的连接:

class my_env extends uvm_env;
		A A_inst;
		B B_inst;
endclass
function void my_env::build_phase(uvm_phase phase);
		super.build_phase(phase);
		A_inst = A::type_id::create("A_inst",this);
		B_inst = B::type_id::create("B_inst",this);	
endfunction
function void my_env::connect_phase(uvm_phase phase);
		super.connect_phase(phase);
		A_inst.A_transport.connect(B_inst.B_imp);
endfunction

10、nonblocking端口的使用

nonblocking系列端口的所有操作都是非阻塞的,例子如下:
A的代码:

class A extends uvm_component;
		`uvm_component_utils(A);
		uvm_nonblocking_put_port#(my_transaction) A_port;//定义端口类型
endclass
function void A::build_phase(uvm_phase phase);
		super.build_phase(phase);
		A_port = new("A_port",this);//例化端口
endfunction
task A::main_phase(uvm_phase phase);
		my_transaction tr;	
		tr = new("tr");
		assert(tr.randomize());
		while(!A_port.can_put()) ;//等待并判断是否可以执行put操作
		A_port.try_put(tr); 
endtask

B的代码:

class B extends uvm_component;
		`uvm_component_utils(B);
		uvm_nonblocking_put_imp#(my_transaction,B) B_imp;//定义端口类型		
		my_transaction tr_q[$];
endclass
function void B::build_phase(uvm_phase phase);
		super.build_phase(phase);
		B_imp = new("B_imp",this);		
endfunction
function bit B::can_put();
		if(tr_q.size() > 0)
			return 0;
		else
			return 1;
endfunction
function bit B::try_put(my_transaction tr);
		if(tr_q.size() > 0)
			return 0;
		else
			tr_q.push_back(tr);
			return 1;
endfunction
task B::main_phase(uvm_phase phase);
		my_transaction tr;	
		while(1)begin
			if(tr_q.size() > 0)
				tr = tr_q.pop_front();
		end
		tr.print();
endtask

在env中建立起两者的连接:

class my_env extends uvm_env;
		A A_inst;
		B B_inst;
endclass
function void my_env::build_phase(uvm_phase phase);
		super.build_phase(phase);
		A_inst = A::type_id::create("A_inst",this);
		B_inst = B::type_id::create("B_inst",this);	
endfunction
function void my_env::connect_phase(uvm_phase phase);
		super.connect_phase(phase);
		A_inst.A_port.connect(B_inst.B_imp);
endfunction
  • 3
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值