I 单向数据通信
i A port blocking put to B imp
//TLM -portput
//组件A通过TLM,向组件B,put一个object
//方式 port ->export -> imp
//TLM也支持port连port,export连export,但不支持imp连imp
//TLM通信
//TLM通信端口用new例化,new的时候要带上:名字和所在的parent。
//TLM端口是参数类,port端要声明传递参数,
// export端要声明传递参数,
// imp端不仅要声明传递参数,还要写当前存在的类的类名
//TLM分控制流和数据流,port发起控制,决定是发数据还是收数据,是否阻塞。高优先
// export做中间传递,中优先级
// import要在它所在的component中,实现port使用的方法
// export和import的名称要与port的名称匹配
//最终在它们的上一层使用connect方法为端口做链接,较高优先的端口调用connect方法,较低优先
//级的作为connect方法的参数
package pack1; //pack1头
import uvm_pkg::*; //+UVM
`include "uvm_macros.svh"//+工厂
class Packet extends uvm_object;
string s = "hello,world~";
`uvm_object_utils(Packet)
function new(string name = "Packet");
super.new(name);
endfunction
endclass
//组件A port端口put一个packet
class A extends uvm_component;
`uvm_component_utils (A)
Packet pkt;
uvm_blocking_put_port#(Packet) A_put_port;
function new (string name = "A", uvm_component parent= null);
super.new (name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
A_put_port = new ("A_put_port", this);
endfunction
virtual task run_phase(uvm_phase phase);
phase.raise_objection(this);
pkt = Packet::type_id::create ("pkt");
A_put_port.put(pkt);
phase.drop_objection(this);
endtask
endclass
//组件B 实现export端口和import端口(实现put函数)
// 将export与import相连接
class B extends uvm_component;
`uvm_component_utils (B)
uvm_blocking_put_export#(Packet) B_put_export;
uvm_blocking_put_imp#(Packet,B) B_put_import;
function new (string name = "B", uvm_component parent= null);
super.new (name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
B_put_export = new ("B_put_export", this);
B_put_import = new ("B_put_import", this);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
B_put_export.connect(B_put_import);
endfunction
virtual task run_phase(uvm_phase phase);
phase.raise_objection(this);
#1us;
phase.drop_objection(this);
endtask
virtual function void put(Packet pkt);
`uvm_info("B",pkt.s,UVM_LOW)
endfunction
endclass
//TEST
//将port与export相连接
class test1 extends uvm_test;
A comp_A;
B comp_B;
`uvm_component_utils(test1)
function new(string name = "test1", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
`uvm_info("test1",$sformatf("build"), UVM_LOW)
comp_A = A::type_id::create("comp_A",this);
comp_B = B::type_id::create("comp_B",this);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
comp_A.A_put_port.connect(comp_B.B_put_export);
endfunction
task run_phase(uvm_phase phase);
phase.raise_objection(this);
`uvm_info("test1",$sformatf("run0"), UVM_LOW)
#1us;
`uvm_info("test1",$sformatf("run1"), UVM_LOW)
phase.drop_objection(this);
endtask
endclass
endpackage //pack1尾
//--------------------------------------module1---------------------------------
module mod1;
import pack1::*;
import uvm_pkg::*; //+UVM
initial begin
run_test("test1");//直接例化test,并执行phase机制
end
endmodule
ii A port blocking get to B imp
//TLM -portget
//组件A向组件B get一些object
//方式 port ->export -> imp
//这个例子中使用到了队列↓
//创建队列:Packet pkt_mem[$];
//将信息放入队列:pkt_mem.push_back(pkt);
//周期性检查队列是否为空:不为空则从队列拿出信息
//while (pkt_mem.size() == 0) begin #2; end
//pack = pkt_mem.pop_front();
package pack1; //pack1头
semaphore run_stop_flags = new(); //旗语(SV语法),这里使用旗语是为了结束仿真
import uvm_pkg::*; //+UVM
`include "uvm_macros.svh"//+工厂
class Packet extends uvm_object;
string s = "hello,world~";
`uvm_object_utils(Packet)
function new(string name = "Packet");
super.new(name);
endfunction
endclass
//组件A 实现port端口
//runphase中调用组件B中的get函数,从B的fifo中获取Packet对象并使用
class A extends uvm_component;
`uvm_component_utils (A)
uvm_blocking_get_port#(Packet) A_get_port;
function new (string name = "A", uvm_component parent= null);
super.new (name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
A_get_port = new ("A_get_port", this);
endfunction
virtual task run_phase(uvm_phase phase);
Packet pkt;
phase.raise_objection(this);
while(1) begin
A_get_port.get(pkt);
`uvm_info("A","Component already get a pkt!",UVM_LOW)
pkt.print();
end
phase.drop_objection(this);
endtask
endclass
//组件B 实现imp端口,实现get函数
//runphase中:顺序产生10个packet对象放入队列
//get函数:周期性扫描队列非空,若队列非空则拿出packet,向外传递。
class B extends uvm_component;
`uvm_component_utils (B)
uvm_blocking_get_imp#(Packet,B) B_get_import;
Packet pkt_mem[$];
function new (string name = "B", uvm_component parent= null);
super.new (name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
B_get_import = new ("B_get_import", this);
endfunction
virtual task run_phase(uvm_phase phase);
Packet pkt;
phase.raise_objection(this);
repeat(10) begin //每隔10s产生一个pkt对象,放入队列
#10;
pkt = Packet::type_id::create("pkt",this);
pkt_mem.push_back(pkt);
end
#200;
run_stop_flags.put(1);//10个pkt对象都产生完之后,过200ns,
//向公共区放入一把钥匙
phase.drop_objection(this);
endtask
virtual task get;//get函数,每间隔2,查看pktmem队列是否为空,若不为空
output Packet pack; //则从队列中取出Package
while (pkt_mem.size() == 0) begin #2; end
pack = pkt_mem.pop_front();
endtask
endclass
//TEST
//将port与import相连接
class test1 extends uvm_test;
A comp_A;
B comp_B;
`uvm_component_utils(test1)
function new(string name = "test1", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
`uvm_info("test1",$sformatf("build"), UVM_LOW)
comp_A = A::type_id::create("comp_A",this);
comp_B = B::type_id::create("comp_B",this);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
comp_A.A_get_port.connect(comp_B.B_get_import);
endfunction
task run_phase(uvm_phase phase);
phase.raise_objection(this);
`uvm_info("test1",$sformatf("run0"), UVM_LOW)
run_stop_flags.get(1);//等待钥匙,结束仿真。
$finish();
phase.drop_objection(this);
endtask
endclass
endpackage //pack1尾
//--------------------------------------module1---------------------------------
module mod1;
import pack1::*;
import uvm_pkg::*; //+UVM
initial begin
run_test("test1");//直接例化test,并执行phase机制
$stop();
end
endmodule
iii 一个组件内有多个IMP
我们知道TLM的通信方法需要在imp端实现,当一个组件内有多个同类型imp的时候,就会出现方法名重复,UVM提供了宏,来解决这一问题。
package pack1; //pack1头
semaphore run_stop_flags = new(); //旗语(SV语法),这里使用旗语是为了结束仿真
import uvm_pkg::*; //+UVM
`include "uvm_macros.svh"//+工厂
`uvm_blocking_get_imp_decl(_i)
`uvm_blocking_get_imp_decl(_ii) //声明多同类型imp的后缀,然后需要在对应component
//声明imp和声明tlm方法时加上此后缀 请搜(lookthere)
class Packet extends uvm_object;
string s = "hello,world~";
`uvm_object_utils(Packet)
function new(string name = "Packet");
super.new(name);
endfunction
endclass
class A extends uvm_component;
`uvm_component_utils (A)
uvm_blocking_get_port#(Packet) A_get_port0;
uvm_blocking_get_port#(Packet) A_get_port1;
function new (string name = "A", uvm_component parent= null);
super.new (name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
A_get_port0 = new ("A_get_port0", this);
A_get_port1 = new ("A_get_port1", this);
endfunction
virtual task run_phase(uvm_phase phase);
Packet pkt0;
Packet pkt1;
phase.raise_objection(this);
fork
begin
while(1)begin
A_get_port0.get(pkt0);
`uvm_info("A_PORT0","get...",UVM_LOW)
pkt0.print();
end
end
begin
while(1)begin
A_get_port1.get(pkt1);
`uvm_info("A_PORT1","get...",UVM_LOW)
pkt1.print();
end
end
join
phase.drop_objection(this);
endtask
endclass
class B extends uvm_component;
`uvm_component_utils (B)
uvm_blocking_get_imp_i#(Packet,B) B_get_imp0;
//lookthere
uvm_blocking_get_imp_ii#(Packet,B) B_get_imp1;
//lookthere
Packet pkt_mem_0[$];
Packet pkt_mem_1[$];
function new (string name = "B", uvm_component parent= null);
super.new (name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
B_get_imp0 = new ("B_get_imp0", this);
B_get_imp1 = new ("B_get_imp1", this);
endfunction
virtual task run_phase(uvm_phase phase);
Packet pkt0;
Packet pkt1;
phase.raise_objection(this);
repeat(10) begin
#10;
pkt0 = Packet::type_id::create("pkt0",this);
pkt_mem_0.push_back(pkt0);
pkt1 = Packet::type_id::create("pkt1",this);
pkt_mem_1.push_back(pkt1);
end
#200;
run_stop_flags.put(1);//10个pkt对象都产生完之后,过200ns,
//向公共区放入一把钥匙
phase.drop_objection(this);
endtask
virtual task get_i;//lookthere
output Packet pack;
while (pkt_mem_0.size() == 0) begin #2; end
pack = pkt_mem_0.pop_front();
endtask
virtual task get_ii;//lookthere
output Packet pack;
while (pkt_mem_1.size() == 0) begin #2; end
pack = pkt_mem_1.pop_front();
endtask
endclass
class test1 extends uvm_test;
A comp_A;
B comp_B;
`uvm_component_utils(test1)
function new(string name = "test1", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
`uvm_info("test1",$sformatf("build"), UVM_LOW)
comp_A = A::type_id::create("comp_A",this);
comp_B = B::type_id::create("comp_B",this);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
comp_A.A_get_port0.connect(comp_B.B_get_imp0);
comp_A.A_get_port1.connect(comp_B.B_get_imp1);
endfunction
task run_phase(uvm_phase phase);
phase.raise_objection(this);
`uvm_info("test1",$sformatf("run0"), UVM_LOW)
run_stop_flags.get(1);//等待钥匙,结束仿真。
$finish();
phase.drop_objection(this);
endtask
endclass
endpackage //pack1尾
//--------------------------------------module1---------------------------------
module mod1;
import pack1::*;
import uvm_pkg::*; //+UVM
initial begin
run_test("test1");//直接例化test,并执行phase机制
$stop();
end
endmodule
iv TLMFIFO: A port blocking put, B port blocking get
(这里以tlm_analysis_fifo做演示,它继承于tlm_fifo)
TLM FIFO默认的深度是1,如果需要更改,可以在new()是更改参数size的值,如需要无限大小,就将传入的size参数设为0(new函数原型为:function new(string name, uvm_component parent=null, int size=1)。
package pack1; //pack1头
semaphore run_stop_flags = new(); //旗语(SV语法),这里使用旗语是为了结束仿真
import uvm_pkg::*; //+UVM
`include "uvm_macros.svh"//+工厂
class trans extends uvm_transaction;
string s = "hello,world~";
rand bit [7:0] signal;
`uvm_object_utils(trans)
function new(string name = "trans");
super.new(name);
if(this.randomize()) begin//当有trans被new的时候,我就把自己给随机化了
$display("signal = %x\n",signal);
end
else begin
$display("randomize failed !\n");
$finish();
end
endfunction
endclass
class A extends uvm_component;
`uvm_component_utils (A)
uvm_blocking_get_port#(trans) A_get_port;
trans ts;
function new (string name = "A", uvm_component parent= null);
super.new (name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
A_get_port = new ("A_get_port", this);
endfunction
virtual task run_phase(uvm_phase phase);
phase.raise_objection(this);
forever begin
A_get_port.get(ts);
`uvm_info("A run_phase",
{"\n", "cmpA have been get a transaction: \n", ts.sprint()},
UVM_MEDIUM);
end
phase.drop_objection(this);
endtask
endclass
class B extends uvm_component;
`uvm_component_utils (B)
uvm_blocking_put_port#(trans) B_put_port;
function new (string name = "B", uvm_component parent= null);
super.new (name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
B_put_port = new ("B_put_port", this);
endfunction
virtual task run_phase(uvm_phase phase);
trans ts;
phase.raise_objection(this);
repeat(10) begin
#10;
ts = trans::type_id::create("trans",this);
B_put_port.put(ts);
end
#200;
run_stop_flags.put(1);//10个pkt对象都产生完之后,过200ns,
//向公共区放入一把钥匙
phase.drop_objection(this);
endtask
endclass
//TEST
//创建fifo,连接componentA,B
class test1 extends uvm_test;
A comp_A;
B comp_B;
uvm_tlm_analysis_fifo #(trans) tlmfifo;
`uvm_component_utils(test1)
function new(string name = "test1", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
`uvm_info("test1",$sformatf("build"), UVM_LOW)
comp_A = A::type_id::create("comp_A",this);
comp_B = B::type_id::create("comp_B",this);
tlmfifo = new("tlmfifo", this);//实例化
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
comp_A.A_get_port.connect(this.tlmfifo.blocking_get_export);
comp_B.B_put_port.connect(this.tlmfifo.blocking_put_export);
//虽然tlmfifo做从机,
//但是也要连他的export
//,因为他只有export
endfunction
task run_phase(uvm_phase phase);
phase.raise_objection(this);
`uvm_info("test1",$sformatf("run0"), UVM_LOW)
run_stop_flags.get(1);//等待钥匙,结束仿真。
$finish();
phase.drop_objection(this);
endtask
endclass
endpackage //pack1尾
//--------------------------------------module1---------------------------------
module mod1;
import pack1::*;
import uvm_pkg::*; //+UVM
initial begin
run_test("test1");//直接例化test,并执行phase机制
$stop();
end
endmodule
II 双向数据通信
package pack1; //pack1头
import uvm_pkg::*; //+UVM
`include "uvm_macros.svh"//+工厂
class trans extends uvm_transaction;
int i = 3;
`uvm_object_utils (trans)
function new(string name = "trans");
super.new(name);
endfunction
endclass
class A extends uvm_component;
`uvm_component_utils (A)
uvm_blocking_transport_port #(trans,trans) txrx_port;
//(port端发的类型,port端接的类型)
function new (string name = "A", uvm_component parent= null);
super.new (name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
txrx_port=new("txrx_port",this);
endfunction
virtual task run_phase(uvm_phase phase);
trans tx_trans;
trans rx_trans;
phase.raise_objection(this);
tx_trans=new("tx_trans");//把要发trans的实例化就可以了,至于接收的
//就声明个句柄就行,到时候把
//传过来的对象贴上去
tx_trans.print();
$display("i = %d",tx_trans.i);
txrx_port.transport(tx_trans,rx_trans);
rx_trans.print();
$display("i = %d",rx_trans.i);
phase.drop_objection(this);
endtask
endclass
class B extends uvm_component;
`uvm_component_utils (B)
uvm_blocking_transport_imp #(trans,trans,B) txrx_imp;
//(port端发的类型,port端接的类型
//,imp端口所在类的类名)
function new (string name = "B", uvm_component parent= null);
super.new (name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
txrx_imp=new("txrx_imp",this);
endfunction
virtual task run_phase(uvm_phase phase);
phase.raise_objection(this);
phase.drop_objection(this);
endtask
//对于imp对应组件内的transport方法而言,
//这个方法有一个input和一个output
//input是port端传递过来的transaction,output是要传递给port端的transaction
task transport;
input trans tx_trans;
output trans rx_trans;
rx_trans=new("rx_trans");
rx_trans.i = rx_trans.i * tx_trans.i;
endtask
endclass
//TEST
//将port与import相连接
class test1 extends uvm_test;
A comp_A;
B comp_B;
`uvm_component_utils(test1)
function new(string name = "test1", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
`uvm_info("test1",$sformatf("build"), UVM_LOW)
comp_A = A::type_id::create("comp_A",this);
comp_B = B::type_id::create("comp_B",this);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
comp_A.txrx_port.connect(comp_B.txrx_imp);
endfunction
task run_phase(uvm_phase phase);
phase.raise_objection(this);
phase.drop_objection(this);
endtask
endclass
endpackage //pack1尾
//--------------------------------------module1---------------------------------
module mod1;
import pack1::*;
import uvm_pkg::*; //+UVM
initial begin
run_test("test1");//直接例化test,并执行phase机制
end
endmodule
III 广播
i broadcast_port write some imp
需要注意的是:analysis port广播出去的是handle,并不是实例化对象。广播的收听端,需要copy使用。
package pack1; //pack1头
import uvm_pkg::*; //+UVM
`include "uvm_macros.svh"//+工厂
class trans extends uvm_transaction;
int addr = 6;
int data = 7;
`uvm_object_utils (trans)
function new(string name = "trans");
super.new(name);
endfunction
function void copy (trans p);
this.addr = p.addr;
this.data = p.data;
endfunction
endclass
class A extends uvm_component;
`uvm_component_utils (A)
uvm_analysis_port#(trans) broadcast;
function new (string name = "A", uvm_component parent= null);
super.new (name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
broadcast = new("broadcast",this);
endfunction
virtual task run_phase(uvm_phase phase);
trans trs;
phase.raise_objection(this);
trs = trans::type_id::create("trs");
trs.addr = 5;
trs.data = 5;
broadcast.write(trs);//发起广播
phase.drop_objection(this);
endtask
endclass
class B extends uvm_component;
uvm_analysis_imp#(trans,B) imp_B;
`uvm_component_utils(B)
function new(string name = "B", uvm_component parent = null);
super.new(name, parent);
imp_B = new("imp_B", this);
endfunction
virtual function void write(trans trs);
trans copy_tr;
copy_tr = trans::type_id::create("copy_tr",);
$display("[compB] old addr is :%d",copy_tr.addr);
$display("[compB] old data is :%d",copy_tr.data);
copy_tr.copy(trs);
$display("[compB] new addr is :%d",copy_tr.addr);
$display("[compB] new data is :%d",copy_tr.data);
endfunction
endclass
class C extends uvm_component;
uvm_analysis_imp#(trans,C) imp_C;
`uvm_component_utils(C)
function new(string name = "C", uvm_component parent = null);
super.new(name, parent);
imp_C = new("imp_C", this);
endfunction
virtual function void write(trans trs);
trans copy_tr;
copy_tr = trans::type_id::create("copy_tr",);
$display("[compC] old addr is :%d",copy_tr.addr);
$display("[compC] old data is :%d",copy_tr.data);
copy_tr.copy(trs);
$display("[compC] new addr is :%d",copy_tr.addr);
$display("[compC] new data is :%d",copy_tr.data);
endfunction
endclass
class test1 extends uvm_test;
A comp_A;
B comp_B;
C comp_C;
`uvm_component_utils(test1)
function new(string name = "test1", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
`uvm_info("test1",$sformatf("build"), UVM_LOW)
comp_A = A::type_id::create("comp_A",this);
comp_B = B::type_id::create("comp_B",this);
comp_C = C::type_id::create("comp_C",this);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
comp_A.broadcast.connect(comp_B.imp_B);
comp_A.broadcast.connect(comp_C.imp_C);
endfunction
task run_phase(uvm_phase phase);
phase.raise_objection(this);
phase.drop_objection(this);
endtask
endclass
endpackage //pack1尾
//--------------------------------------module1---------------------------------
module mod1;
import pack1::*;
import uvm_pkg::*; //+UVM
initial begin
run_test("test1");//直接例化test,并执行phase机制
end
endmodule
ii broadcast_port write some tlm_fifo
package pack1; //pack1头
import uvm_pkg::*; //+UVM
`include "uvm_macros.svh"//+工厂
class trans extends uvm_transaction;
int addr = 6;
int data = 7;
`uvm_object_utils (trans)
function new(string name = "trans");
super.new(name);
endfunction
function void copy (trans p);
this.addr = p.addr;
this.data = p.data;
endfunction
endclass
class A extends uvm_component;
`uvm_component_utils (A)
uvm_analysis_port#(trans) broadcast;
function new (string name = "A", uvm_component parent= null);
super.new (name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
broadcast = new("broadcast",this);
endfunction
virtual task run_phase(uvm_phase phase);
trans trs;
phase.raise_objection(this);
trs = trans::type_id::create("trs");
trs.addr = 5;
trs.data = 5;
broadcast.write(trs);//发起广播
phase.drop_objection(this);
endtask
endclass
class B extends uvm_component;
uvm_get_port#(trans) get_port;
`uvm_component_utils(B)
function new(string name = "B", uvm_component parent = null);
super.new(name, parent);
get_port = new("get_port", this);
endfunction
virtual task run_phase(uvm_phase phase);
trans trs;
phase.raise_objection(this);
get_port.get(trs);
$display("[B]:get addr = %d",trs.addr);
$display("[B]:get data = %d",trs.data);
phase.drop_objection(this);
endtask
endclass
class test1 extends uvm_test;
A comp_A;
B comp_B;
uvm_tlm_analysis_fifo #(trans) fifo1;
`uvm_component_utils(test1)
function new(string name = "test1", uvm_component parent = null);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
`uvm_info("test1",$sformatf("build"), UVM_LOW)
comp_A = A::type_id::create("comp_A",this);
comp_B = B::type_id::create("comp_B",this);
fifo1 = new("fifo1", this);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
comp_A.broadcast.connect(this.fifo1.analysis_export);
comp_B.get_port.connect(this.fifo1.get_export);
endfunction
task run_phase(uvm_phase phase);
phase.raise_objection(this);
phase.drop_objection(this);
endtask
endclass
endpackage //pack1尾
//--------------------------------------module1---------------------------------
module mod1;
import pack1::*;
import uvm_pkg::*; //+UVM
initial begin
run_test("test1");//直接例化test,并执行phase机制
end
endmodule