这篇文章将解释analysis port 和 analysis export是如何工作的.
在Agent中将jelly-bean monitor (jb_mon
)中的analysis port (jb_ap
)和 jelly-bean agent (jb_agent
) 中的analysis port (jb_ap
)连接。
jb_mon.jb_ap.connect( jb_ap ); // in the jelly_bean_agent
然后,在Env中将jelly-bean agent (jb_agent
) 中的analysis port (jb_ap
)连接到 jelly-bean-functional-coverage收集器(jb_fc_sub
)的 analysis export (analysis_export
) 。
jb_agent.jb_ap.connect( jb_fc_sub.analysis_export ); // in the jelly_bean_env
您可能需要查看第一章“概述”中的验证组件图以检查这些连接。
最后在jelly-bean monitor的run_phase()中,monitor每次创建jelly_bean事务(jb_tx)时都会调用其analysis port的write()函数:
jb_ap.write( jb_tx ); // in the jelly_bean_monitor
我们将在这篇文章中看看上面的代码是如何工作的。 下面显示了与analysis port相关的类图。 UVM标准库类以粉色显示,而专用于jelly_bean_transaction类型的UVM类以黄色显示。
Analysis port相关类图
Analysis Port
jelly-bean monitor的jb_ap是专用于jelly_bean_transaction类型的uvm_analysis_port类的对象。 以下伪代码显示了该类是如何专门化的。
class uvm_analysis_port #( type T = jelly_bean_transaction )
extends uvm_port_base #( uvm_tlm_if_base #(T,T) );
function new( string name, uvm_component parent );
super.new( name, parent, UVM_PORT, 0, UVM_UNBOUNDED_CONNECTIONS );
m_if_mask = `UVM_TLM_ANALYSIS_MASK; // = 1 < < 8
endfunction // new
virtual function string get_type_name();
return "uvm_analysis_port";
endfunction // get_type_name
function void write( input jelly_bean_transaction t );
uvm_tlm_if_base #( jelly_bean_transaction, jelly_bean_transaction ) tif;
for ( int i = 0; i < this.size(); i++ ) begin
tif = this.get_if( i );
if ( tif == null )
uvm_report_fatal( "NTCONN",
{ "No uvm_tlm interface is connected to ",
get_full_name(), " for executing write()" },
UVM_NONE );
tif.write( t );
end
endfunction // write
endclass // uvm_analysis_port
正如您在上面看到的,uvm_analysis_port的write()函数将其作业委派给tif,该tif是uvm_tlm_if_base类的一个对象。 uvm_tlm_if_base类是uvm_port_base类的基类,后者又是uvm_analysis_imp类的基类(第22行)。
Analysis Export
jelly-bean-functional-coverage收集器(jb_fc_sub)的analysis_export是专用于jelly_bean_transaction类型的uvm_analysis_imp类的对象。以下伪代码显示了该类是如何专门化的。
class uvm_analysis_imp #( type T = jelly_bean_transaction,
type IMP = uvm_subscriber #( jelly_bean_transaction ) )
extends uvm_port_base #( uvm_tlm_if_base #( jelly_bean_transaction,
jelly_bean_transaction ) );
// `UVM_IMP_COMMON( `UVM_TLM_ANALYSIS_MASK, "uvm_analysis_imp",
// | uvm_subscriber #( jelly_bean_transaction,
// | jelly_bean_transaction ) )
// V
local uvm_subscriber #( jelly_bean_transaction, jelly_bean_transaction ) m_imp;
function new( string name, uvm_subscriber #( jelly_bean_transaction,
jelly_bean_transaction ) imp );
super.new( name, imp, UVM_IMPLEMENTATION, 1, 1 );
m_imp = imp;
m_if_mask = `UVM_TLM_ANALYSIS_MASK; // = 1 < < 8
endfunction // new
// +--> `UVM_TLM_GET_TYPE_NAME( "uvm_analysis_imp" )
virtual function string get_type_name();
return "uvm_analysis_imp";
endfunction // get_type_name
// end of macro expansion
function void write( input jelly_bean_transaction t );
m_imp.write( t );
endfunction // write
endclass // uvm_analysis_imp
uvm_analysis_imp类的write()函数将其作业委托给m_imp。 m_imp是我们作为参数传递给uvm_analysis_imp类的 jelly-bean-functional-coverage subscriber(jb_fc_sub)。这意味着uvm_analysis_imp的write()函数只是简单地调用jb_fc_sub的write()函数。
Connection
以下序列图显示了port和export连接中涉及的步骤。
序列图
jb_mon.jb_ap.connect( jb_ap ); // in the jelly_bean_agent
当在jelly_bean_agent中调用connect()函数时,jb_mon的jb_ap将jb_agent的jb_ap存储在名为m_provided_by的数组中(步骤1)。
jb_agent.jb_ap.connect( jb_fc_sub.analysis_export ); // in the jelly_bean_env
类似地,当在jelly_bean_env中调用connect()函数时,jb_agent的jb_ap将jb_fc的analysis_export存储在其m_provided_by数组中(步骤2)。
在进入jb_mon的end_of_elaboration_phase()之前,调用resolve_bindings()函数。该功能遍历端口连接。如果端口类型为UVM_IMPLEMENTATION,则端口应该提供“实现”。该函数将“实现”存储到名为m_imp_list的数组(步骤3到7)。
jb_ap.write( jb_tx ); // in the jelly_bean_monitor
write()函数迭代存储在m_imp_list数组中的实现,并调用每个实现的write()函数(步骤8)。这是一种广播操作。