目录
1、my_reference_model.sv文件中(紫色圆圈①)
1、my_reference_model.sv文件中(紫色圆圈①)
1、my_reference_model.sv文件中(紫色圆圈①)
本文目标
使用 TLM端口 实现 master agent 中的 monitor组件 与 env 中的 reference model组件 互连!
UVM验证总体架构图如下所示(该部分已由红色圈出):
一、put ()模式
put () 模式特点:port 类型的端口位于产生事务的 producer 组件(主动方)当中,import 类型的端口位于事务发送目标的 consumer 组件(被动方)当中。发送时,需要调用 port 的 put 方法来完成,需注意:该 put 方法是在 consumer 组件中定义的。
producer 发送事务时,并不知道 consumer 是否可以接收事务!
代码部分
1、my_reference_model.sv文件中(紫色圆圈①)
在此处,reference_model 是事务的接收方,处于被动接收。
//my_reference_model扩展于uvm_component
class my_reference_model extends uvm_component;//扩展于uvm_component
//注册
`uvm_component_utils(my_reference_model)
//添加import(第一个参数为传输事务的类型,第二个参数为该import所在的类)
uvm_blocking_put_imp #(my_transaction,my_reference_model) i_m2r_imp;
//实例化import对象
function new(string name = "",uvm_component parent);
super.new(name , parent);
this.i_m2r_imp = new("i_m2r_imp",this);
endfunction
//为import构建put方法(将monitor发送的事务打印出来)
task put(my_transaction tr);
`uvm_info("REF_REPORT",{"\n","master agent have been sent a transaction: \n",tr.sprint()},UVM_MEDIUM)
endtask
endclass
2、my_monitor.sv文件中(紫色圆圈③)
//my_monitor扩展于uvm_monitor
class my_monitor extends uvm_monitor;
//添加port(参数为传输事务的类型)
uvm_blocking_put_port #(my_transaction) m2r_port;
//实例化port对象
function new(string name = "",uvm_component parent);
super.new(name , parent);
this.m2r_port = new("m2r_imp",this);
endfunction
//将monitor发送的事务打印出来
virtual task run_phase(uvm_phase phase);
....//循环发送至reference_model
`uvm_info("Monitor","Now monitor send the transaction to the reference model!",UVM_MEDIUM)
//调用put()方法发送transaction
this.m2r_port.put(tr);
endtask
endclass
monitor 与 reference_model 的连接最终会在 env 中完成!但是在两个组件中还有一层master_agent 阻碍,因此使用 export 端口在中间当媒介使用。
3、my_agent.sv文件中(紫色圆圈④)
//my_agent扩展于uvm_agent
class my_agent extends uvm_agent;
...
//添加export(参数为传输事务的类型)
uvm_blocking_put_export #(my_transaction) m_a2r_export;
//实例化export对象
function new(string name = "",uvm_component parent);
super.new(name , parent);
this.m_a2r_export = new("m_a2r_export",this);
endfunction
//连接monitor的port和master_agent的export
virtual function void connect_phase(uvm_phase phase);
if(is_active == UVM_ACTIVE)
m_driv.seq_item_port.connect(m_seqr.seq_item_export);
m_moni.m2r_port.connect(this.m_a2r_export);
endtask
endclass
4、my_env.sv文件中(紫色圆圈③)
//my_env扩展于uvm_env
class my_env extends uvm_env;
...
//声明reference model句柄
my_reference_model ref_model;
//实例化reference model对象
virtual function void build_phase(uvm_phase phase);
...
ref_model = my_reference_model::type_id::create("ref_model",this);
endfunction
//连接agent的export与reference model的import
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
`uvm_info("ENV","Connect the agent and reference model ...",UVM_MEDIUM)
m_agent.m_a2r_export.connect(ref_model.i_m2r_imp);
endfunction
endclass
5、打印结构图示
二、get ()模式
get () 模式特点:consumer 是操作的主动方,从 producer 获取事务。当 producer 产生事务时不会主动发送事务至 consumer ,而是等待 consumer 发起 get 操作之后,才会进行发送。
consumer 想要获取事务时,并不知道 producer 是否有事务需要发送!
代码部分
1、my_reference_model.sv文件中(紫色圆圈①)
在此处,reference_model 是事务的接收方,处于主动接收。
//my_reference_model扩展于uvm_component
class my_reference_model extends uvm_component;//扩展于uvm_component
//注册
`uvm_component_utils(my_reference_model)
//添加port(参数为传输事务的类型)
uvm_blocking_get_port #(my_transaction) i_m2r_port;
//实例化port对象
function new(string name = "",uvm_component parent);
super.new(name , parent);
this.i_m2r_port = new("i_m2r_port",this);
endfunction
//重载run_phase任务,不断调用get()函数获取transaction
virtual task run_phase(uvm_phase phase);
`uvm_info("REF_MODEL_RUN","Reference model running!",UVM_MEDIUM)
forever begin
i_m2r_port.get(item);
`uvm_info("REF_REPORT",{"\n","master agent have been sent a transaction: \n",item.sprint()},UVM_MEDIUM)
end
endtask
endclass
2、my_monitor.sv文件中(紫色圆圈④)
//my_monitor扩展于uvm_monitor
class my_monitor extends uvm_monitor;
//添加import
uvm_blocking_get_imp #(my_transaction,my_monitor) m2r_imp;
//添加队列,用来存储已经监测到的事务对象,避免数据丢失,因为monitor不能主动发出事务
my_transaction tr_fifo[$];
//实例化import对象
function new(string name = "",uvm_component parent);
super.new(name , parent);
this.m2r_imp = new("m2r_imp",this);
endfunction
virtual task run_phase(uvm_phase phase);
//将收到的transaction放入fifo中
tr_fifo.push_back.(tr);
endtask
//添加get()方法
task get(output my_transaction s_tr);
while(tr_fifo.size() == 0) @(m_vif.monitor_cb);
s_tr = tr_fifo.pop_front();
`uvm_info("Monitor",{"\n","Now monitor send the transaction to the reference model: \n",s_tr.sprint()},UVM_MEDIUM)
endtask
endclass
monitor 与 reference_model 的连接最终会在 env 中完成!但是在两个组件中还有一层master_agent 阻碍,因此使用 export 端口在中间当媒介使用。
3、my_agent.sv文件中(紫色圆圈③)
//my_agent扩展于uvm_agent
class my_agent extends uvm_agent;
...
//添加export(参数为传输事务的类型)
uvm_blocking_get_export #(my_transaction) m_a2r_export;
//实例化export对象
function new(string name = "",uvm_component parent);
super.new(name , parent);
this.m_a2r_export = new("m_a2r_export",this);
endfunction
//连接monitor的port和master_agent的export
virtual function void connect_phase(uvm_phase phase);
if(is_active == UVM_ACTIVE)
m_driv.seq_item_port.connect(m_seqr.seq_item_export);
this.m_a2r_export.connect(m_moni.m2r_imp);
endtask
endclass
4、my_env.sv文件中(紫色圆圈②)
//my_env扩展于uvm_env
class my_env extends uvm_env;
...
//声明reference model句柄
my_reference_model ref_model;
//实例化reference model对象
virtual function void build_phase(uvm_phase phase);
...
ref_model = my_reference_model::type_id::create("ref_model",this);
endfunction
//连接agent的export与reference model的import
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
`uvm_info("ENV","Connect the agent and reference model ...",UVM_MEDIUM)
ref_model.i_m2r_port.connect(m_agent.m_a2r_export);
endfunction
endclass
5、打印结构图示
三、fifo ()模式
fifo () 模式特点:相对于前面两种模式,fifo()模式可以在两者之间起到缓存数据的作用。在该模式下,producer 与 consumer 均为操作的主动方,fifo 为被动方。当 producer 当中有事务产生时,既可以使用 put () 操作将该事务放入 fifo 当中进行缓存,而不必等待 consumer 获取事务,所以 consumer 不会阻塞 producer 的事务发送;另一方面,当 consumer 需要事务则可以调用 get () 操作将 fifo 中的事务取出。
代码部分
1、my_reference_model.sv文件中(紫色圆圈①)
//my_reference_model扩展于uvm_component
class my_reference_model extends uvm_component;//扩展于uvm_component
//注册
`uvm_component_utils(my_reference_model)
//添加port(参数为传输事务的类型)
uvm_blocking_get_port #(my_transaction) i_m2r_port;
//实例化port对象
function new(string name = "",uvm_component parent);
super.new(name , parent);
this.i_m2r_port = new("i_m2r_port",this);
endfunction
//重载run_phase任务,不断调用get()函数获取transaction
virtual task run_phase(uvm_phase phase);
`uvm_info("REF_MODEL_RUN","Reference model running!",UVM_MEDIUM)
forever begin
i_m2r_port.get(item);
`uvm_info("REF_REPORT",{"\n","master agent have been sent a transaction: \n",item.sprint()},UVM_MEDIUM)
end
endtask
endclass
2、my_monitor.sv文件中(紫色圆圈④)
//my_monitor扩展于uvm_monitor
class my_monitor extends uvm_monitor;
//添加port(参数为传输事务的类型)
uvm_blocking_put_port #(my_transaction) m2r_port;
//实例化port对象
function new(string name = "",uvm_component parent);
super.new(name , parent);
this.m2r_port = new("m2r_imp",this);
endfunction
//将monitor发送的事务打印出来
virtual task run_phase(uvm_phase phase);
....//循环发送至reference_model
`uvm_info("Monitor","Now monitor send the transaction to the reference model!",UVM_MEDIUM)
//调用put()方法发送transaction
this.m2r_port.put(tr);
endtask
endclass
3、my_agent.sv文件中(紫色圆圈⑤)
//my_agent扩展于uvm_agent
class my_agent extends uvm_agent;
...
//添加export(参数为传输事务的类型)
uvm_blocking_put_export #(my_transaction) m_a2r_export;
//实例化export对象
function new(string name = "",uvm_component parent);
super.new(name , parent);
this.m_a2r_export = new("m_a2r_export",this);
endfunction
//连接monitor的export和master_agent的export
virtual function void connect_phase(uvm_phase phase);
if(is_active == UVM_ACTIVE)
m_driv.seq_item_port.connect(m_seqr.seq_item_export);
m_moni.m2r_export.connect(this.m_a2r_export);
endtask
endclass
4、my_env.sv文件中(紫色圆圈②、③)
//my_env扩展于uvm_env
class my_env extends uvm_env;
...
//声明reference model句柄
my_reference_model ref_model;
//声明fifo句柄
uvm_tlm_analysis_fifo #(transaction) magt2ref_fifo;
//实例化reference model对象
virtual function void build_phase(uvm_phase phase);
...
ref_model = my_reference_model::type_id::create("ref_model",this);
endfunction
//实例化fifo
function new(string name = "" , uvm_component parent);
super.new(name , parent);
magt2ref_fifo = new("magt2ref",this);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
//连接agent与fifo
`uvm_info("ENV","Connect the agent to fifo ...",UVM_MEDIUM)
m_agent.m_a2r_export.connect(this.magt2ref_fifo.blocking_put_export);
//连接reference_model与fifo
`uvm_info("ENV","Connect the reference model to fifo ...",UVM_MEDIUM)
ref_model.i_m2r_port.connect(this.magt2ref_fifo.blocking_get_export);
endfunction
endclass