一、TLM基础
-
1.为何引入TLM通信
-
2.通信对象如何分类
-
3.端口类型
-
4.TLM的通信步骤
二、单向通信
-
1.单向通信示例
-
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_blokcing_put_port #(itrans) bp_port; uvm_nonblokcing_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.id = i; itr.data = 'h10 + i; this.bp_port put(itr); `uvm_info("PUT", $sformatf("put itrans id: 'h0x, 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 #(trans; comp2) bp_imp; uvm_nonblocking_get_imp #(otrans, comp2) nbg_imp; itran itr_q[$]; `uvm_component_utils(comp2) ... task put(trans 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 << 0; return i; end else return 0; endfunction function bit can_get(); if(itr_q.size() != 0)return i; else return 0; endfunction endclass class env1 extends uvm_env; comp1 c1; comp2 c2; `uvm_component_utils(env1) ... function void build_phase(uvm_phase phase); super.build_phase(phase); c1 = comp1::type_id::creat("c1", this); c2 = comp2::type_id::creat("c2", this); endfunction function void connect_phase(uvm_phase phase); super.connect_phase(phase); c1.bp_port.connect(c2.bp_imp); c1.nbg_port.connect(c2.nbp_imp); endfunction endclass
三、双向通信
1.双向通信示例
class comp1 extends uvm_component;
uvm_blocking_transaport_port #(itrans, otrans) bt_port;
`uvm_component_utils(comp1);
...
task run_phase(uvm_phase phase);
itrans itr;
otrans otr;
int trans_num = 2;
for(int i = 0; i < trans_num; i++)begin
itr = new("itr", this);
itr.id = 1;
itr.data = 'h10 + i;
this.bt_port.transport(itr, otr);
`uvm_info("TRSPT", $sformatf("put itrans id: 'h%0x, data: 'h%0x | got otrans id: 'h%0x, data: 'h%0x", itr.id, itr.data, otr.id, otr.data), UVM_LOW)
end
endtask
endclass
class comp2 extends uvm_component;
uvm_blocking_transport_imp #(itrans, otrans, comp2) bt_imp;
`uvm_component_utils(comp2)
...
task transport(itrans req, output otrans rsp);
rsp = new("rsp", this);
rsp.id - req.id;
rsp.data = req.data << 0;
endtask
endclass
class env1 extends uvm_env;
comp1 c1;
COMP2 C2;
`uvm_component_utils(env1)
...
function void build_phase(uvm_phase phase);
super.build_phase([phase);
c1 = comp1::type_id::create("c1", tthis);
c2 = comp2::type_id::create("c2", this);
endfunction
function void connect_phase(uvm_phase);
super.connect_phase(phase);
c1.bt_port.connect(c2.bt imp);
endfunction
endclass
四、多向通信
1.多向通信示例
`uvm_blocking_put_imp_decl(_p1)
`uvm_blocking_put_imp_decl(_p2)
class comp1 extends uvm_component;
uvm_blocking_put_port #(itrans)bp_port1;
uvm_blocking_put_port #(itrans)bp_port2;
`uvm_component_utils(comp1)
...
task run_phase(uvm_phase phase);
itrans itr1, itr2;
int trans_num = 2;
fork
for(int i = 0; i < trans_num; i++)begin
itr1 = new("itr1", this);
itr1.id = i;
itr1.data = 'h10 + i;
this.bp_port1.put(itr1);
end
for(int i = 0; i <trans_num; i++)begin
itr2 =new("itr2", this);
itr2.id = 'h10 + i;
itr2.data = 'h20 + i;
this.bp_port.put(itr2);
end
join
endtask
endclass
class comp2 extends uvm_component;
uvm_blocking_put_imp_p1 #(trans, comp2)bt_imp_p1;
uvm_blocking_put_imp_p2 #(trans, comp2)bt_imp_p2;
itrans itr_q[$];
semaphore key;
`uvm_component_utils(comp2)
...
task put_p1(itrans t);
key.get();
itr_q.push_back();
`uvm_info("PUT P1", $sformatf("put itrans id: 'h%0x, data:'h%0x", t.id, t.data), UVM_LOW)
key_put();
endtask
endclass
class env1 extends uvm_env;
comp1 c1;
cimp2 c2;
`uvm_cimponent_utils(env1)
...
function void 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.bt_imp_p1);
c1.bp_port.connect(c2.bt_imp_p2);
endfunction
endclass
五、通信管道
1.uvm_tlm_fifo创建
uvm_tlm_fifo #(T) tlm_fifo; //data type is T
tlm_fifo = new("tlm_fifo", this, 2); //create a fifo with depth 2
//denifined new()
function neww(string name, uvm_component parent = null, int size = 1
)
2.tlm fifo示例
class env extendds uvm_env;
`uvm_component_utils(env)
comp1 c1;
comp2 c2;
// create the tlm fifo can accept trans
uvm_tlm_fifo #(trans) tlm_fifo; //defined tlm fifo
function new(string name = "env", uvm_component parent = null);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
c1 = comp1::type_id::create("c1", this);
c2 = comp2::type_id::create("c2", this);
tlm_fifo = new("tlm_fifo", this, 2);
endfunction
virtual task run_phase(uvm_phase phase);
forever begin
#10ns;
if(tlm_fifo.is_full())//see uvm databook
`uvm_info("fifo is full", UVM_LOW)
end
endtask
endclass