概述
TLM需要两个通信的对象,分别为initiator和target;谁先发起通信请求,谁属于initiator,发起通信的响应方属于target。如果按照transaction的流向,又可分为producer和consumer。
TLM通信步骤分为:
- 分辨initiator和target,producer和consumer。
- 在target中实现TLM通信方法。
- 在两个对象中创建TLM端口。
- 在更高层次中将两个对象的端口进行连接。
单向通信
指从initiator到target之间的数据流向是单一方向的,或者说initiator和target只能扮演producer和consumer中的一个角色。
按照UVM端口名的命名规则,包括两个要素:是否阻塞的方式(blocking,nonblocking),通信方法(put(t)数据流出initiator、get(t)数据流入initiator、peek(t)数据流入initiator但target中的数据保留)
initiator端 | target端 | |
uvm_blocking_put_port #(th) h | uvm_blocking_put_imp #(th) h | task put(tr) |
uvm_nonblocking_put_port #(th) h | uvm_nonblocking_put_imp #(th) h | function bit try_put(tr) function bit can_put() |
注意:th为数据类型(trans__t),h为句柄,tr为 数据方向 数据类型 数据类型句柄(调用时为数据类型实例的句柄)
具体实例:
class itrans extends uvm_transaction;
int id;
endclass
class otrans extends uvm_transaction;
int data;
endclass
class comp1 extends uvm_compoent;
uvm_blocking_put_port #(itrans) bp_port;
uvm_nonblocking_put_port #(otrans) nbg_port;
...
task run_phase(uvm_phase phase);
itrans itr;
otrans otr;
itr=new("itr",this); #例化itr(initiator),处理数据用于发送
itr.id=1;
this.bp_port.put(itr); #调用imp端的put方法,发送itr
this.nbg_port.try_get(otr); #调用imp端的try_get()方法,拿到otr
end
endclass
class comp2 extends uvm_compoent;
uvm_blocking_put_imp #(itrans,comp2) bp_port;
uvm_nonblocking_put_imp #(otrans,comp2) nbg_port;
itrans itr_q[$];
...
task put(itrans t); #定义imp端的put方法
itr_q.push_back(t);
endtask
function bit try_get(output otrans t); #定义imp端的try_get()方法
t=new("t",this); #例化otr(initiator),处理数据用于发送
t.data =10;
endfucntion
function bit can_get(); #定义imp端的can_get()方法
if(itr_q.size()!=0)
return 1;
else
return 0;
endfucntion
endclass
class env1 extends uvm_env;
comp1 c1;
comp2 c2;
...
function build_phase(uvm_phase phase);
surper.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);
surper.connect_phase(phase);
c1.bp_port.connect(c2.bp_imp);
c1.nbg_port.connect(c2.nbg_imp);
endfunction
endclass