UVM Tutorial for Candy Lovers – 12. Analysis Port

This post will explain how analysis port and analysis export work.

In Agent, we connected the analysis port (jb_ap) of the jelly-bean monitor (jb_mon) to the analysis port (jb_ap) of the jelly-bean agent (jb_agent) as follows:

jb_mon.jb_ap.connect( jb_ap ); // in the jelly_bean_agent

Then, in Environment, we connected the analysis port (jb_ap) of the jelly-bean agent to the analysis export (analysis_export) of the jelly-bean-functional-coverage subscriber (jb_fc_sub):

jb_agent.jb_ap.connect( jb_fc_sub.analysis_export ); // in the jelly_bean_env

You might want to look at the verification component diagram in Overview to check these connections.
Finally, in the run_phase() of the jelly-bean monitor, the monitor called the write() function of its analysis port, every time it created a jelly-bean transaction (jb_tx):

jb_ap.write( jb_tx ); // in the jelly_bean_monitor

We will look at how the above code works in detail in this post. The class diagram related to the analysis port is shown below. UVM standard library classes are shown in pink, while the UVM classes specialized with the jelly_bean_transaction type are shown in yellow.

Analysis Port

The jb_ap of the jelly-bean monitor is an object of the uvm_analysis_port class specialized with the jelly_bean_transaction type. The following pseudo code shows how the class is specialized.

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

As you have seen above, the write() function of the uvm_analysis_port delegates its job to tif, which is an object of uvm_tlm_if_base class. The uvm_tlm_if_base class is the base class of uvm_port_base class, which in turn is the base class of uvm_analysis_imp class (line 22).

Analysis Export

The analysis_export of the jelly-bean-functional-coverage subscriber (jb_fc_sub) is an object of the uvm_analysis_imp class specialized with the jelly_bean_transaction type. The following pseudo code shows how the class is specialized.

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

The write() function of the uvm_analysis_imp class delegates its job to m_imp. The m_imp is the jelly-bean-functional-coverage subscriber (jb_fc_sub) we passed as a parameter to the uvm_analysis_imp class. This means the write() function of the uvm_analysis_imp simply calls the write() function of the jb_fc_sub.

Connection

Now let’s put the things together. The following sequence diagram shows the steps involved in the connection.

jb_mon.jb_ap.connect( jb_ap ); // in the jelly_bean_agent

When the connect() function is called in the jelly_bean_agent, the jb_ap of the jb_mon stores the jb_ap of the jb_agent in an array called m_provided_by (step 1).

jb_agent.jb_ap.connect( jb_fc_sub.analysis_export ); // in the jelly_bean_env

Similarly, when the connect() function is called in the jelly_bean_env, the jb_ap of the jb_agent stores the analysis_export of the jb_fc in its m_provided_by array (step 2).

Just before entering the end_of_elaboration_phase() of the jb_monresolve_bindings() function is called. This function traverses the port connection. If the port type is UVM_IMPLEMENTATION, the port is supposed to provide “implementation”. The function stores the “implementation” to an array called m_imp_list (steps 3 to 7).

jb_ap.write( jb_tx ); // in the jelly_bean_monitor

The write() function iterates over the implementations stored in the m_imp_list array and calls the write() function of each implementation (step 8).

That’s about the analysis port. I hope this post helped you to understand how the analysis port works.

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章