ovm_connector_base.svh

Go to the documentation of this file.
00001 // $Id: ovm__connector__base_8svh-source.html,v 1.1 2008/10/07 21:54:44 alex.marin Exp $
00002 //------------------------------------------------------------------------------
00003 //   Copyright 2007-2008 Mentor Graphics Corporation
00004 //   Copyright 2007-2008 Cadence Design Systems, Inc.
00005 //   All Rights Reserved Worldwide
00006 //
00007 //   Licensed under the Apache License, Version 2.0 (the
00008 //   "License"); you may not use this file except in
00009 //   compliance with the License.  You may obtain a copy of
00010 //   the License at
00011 //
00012 //       http://www.apache.org/licenses/LICENSE-2.0
00013 //
00014 //   Unless required by applicable law or agreed to in
00015 //   writing, software distributed under the License is
00016 //   distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
00017 //   CONDITIONS OF ANY KIND, either express or implied.  See
00018 //   the License for the specific language governing
00019 //   permissions and limitations under the License.
00020 //------------------------------------------------------------------------------
00021 
00022 typedef enum {
00023   OVM_PORT ,
00024   OVM_EXPORT ,
00025   OVM_IMPLEMENTATION
00026 } ovm_port_type_e;
00027 
00028 `const string s_connection_error_id = "Connection Error";
00029 `const string s_connection_debug_id = "Connections Debug";
00030 
00031 
00032 //------------------------------------------------------------------------------
00033 //
00034 // CLASS: ovm_connector_base
00035 //
00036 //------------------------------------------------------------------------------
00037 // ovm_connector_base stores the detailed connectivity mechanics for
00038 // ovm_*_port and ovm_*_export.
00039 //------------------------------------------------------------------------------
00040 
00041 virtual class ovm_connector_base extends ovm_component;
00042 
00043   protected ovm_port_type_e m_port_type; // ie, PORT, EXPORT or IMP
00044 
00045   function new( string name, ovm_component parent,
00046                 ovm_port_type_e port_type );
00047     super.new(name, parent );
00048     m_port_type = port_type;
00049   endfunction
00050 
00051   function bit is_port();
00052     return m_port_type == OVM_PORT;
00053   endfunction
00054 
00055   function bit is_export();
00056     return m_port_type == OVM_EXPORT;
00057   endfunction
00058 
00059   function bit is_imp();
00060     return m_port_type == OVM_IMPLEMENTATION;
00061   endfunction
00062 
00063   function string get_type_name();
00064     //return "ovm_connector_base";
00065     case( m_port_type )
00066       OVM_PORT : return "port";
00067       OVM_EXPORT : return "export";
00068       OVM_IMPLEMENTATION : return "implementation";
00069     endcase
00070   endfunction
00071 
00072 endclass
00073 
00074 
00075 
00076 //------------------------------------------------------------------------------
00077 //
00078 // CLASS: ovm_connector #(IF)
00079 //
00080 //------------------------------------------------------------------------------
00081 
00082 class ovm_connector #(type IF=int) extends ovm_connector_base;
00083  
00084   typedef ovm_connector #(IF) connector_type;
00085   
00086   local int unsigned if_mask;
00087 
00088   local ovm_if_container #(IF) m_if_container;
00089 
00090   ovm_port_base_base #(IF) port_h;
00091 
00092   // Consider port->port->export->export->imp.
00093   // provided_by list points to RHS of "->"
00094 
00095   // the provided_by list is list of connectors that "this" uses to
00096   // satisfy its conenctivity requirements
00097 
00098   // all the interfaces of all the m_provided_by[i] are copied into
00099   // this.m_if_list
00100 
00101   local connector_type m_provided_by[string];
00102   
00103   // Consider port->port->export->export->imp.
00104   // provided_to_list point to LHS of "->"
00105   
00106   // the provided_to list is the list of connectors that use "this" to
00107   // satisfy their connectivity requirements
00108 
00109   local connector_type m_provided_to[string];
00110 
00111   function new( string name , ovm_component parent ,
00112                 ovm_port_type_e port_type,
00113                 int min_size = 0, int max_size = 1 );
00114     
00115     super.new( name, parent, port_type );
00116     m_if_container = new(min_size, max_size);
00117   endfunction
00118 
00119   //----------------------------------------------------------------------------
00120   // accessor and convenience functions
00121   //----------------------------------------------------------------------------
00122 
00123   function ovm_if_container #(IF) get_if_container();
00124     return m_if_container;
00125   endfunction
00126 
00127   function int size();
00128     return m_if_container.size();
00129   endfunction
00130 
00131   function int min_size();
00132     return m_if_container.min_size();
00133   endfunction
00134 
00135   function int max_size();
00136     return m_if_container.max_size();
00137   endfunction
00138 
00139   //----------------------------------------------------------------------------
00140   // connect_to
00141   //
00142   // For new style binding ovm_*_port -> ovm_*_port -> ovm_*_export ->
00143   // to ovm_*_imp
00144   //
00145   //----------------------------------------------------------------------------
00146   function bit connect_to( input connector_type c );
00147     string s;
00148 
00149     if(!c.m_if_container.add_list(m_if_container)) begin
00150       s = {"Cannot connect to " , c.get_full_name()};
00151       ovm_report_error( s_connection_error_id , s );
00152       return 0;
00153     end
00154 
00155     // set the value if m_if to the first entry
00156     // in the interface list 
00157     c.port_h.set_if();
00158 
00159     //debug_connected_to();
00160 
00161     return 1;
00162   endfunction  
00163 
00164   //--------------------------------------------------------------------
00165   // end_of_elaboration
00166   //--------------------------------------------------------------------
00167   function void end_of_elaboration();
00168     check_min_connection_size();
00169   endfunction
00170 
00171   //----------------------------------------------------------------------------
00172   // update_connection_lists
00173   //----------------------------------------------------------------------------
00174   function void update_connection_lists( input connector_type c );
00175     m_provided_by[c.get_full_name()] = c;
00176     c.m_provided_to[get_full_name()] = this;
00177   endfunction
00178 
00179 
00180   //----------------------------------------------------------------------------
00181   // resolve_bindings
00182   //----------------------------------------------------------------------------
00183   virtual function void resolve_bindings();
00184 
00185     if(!is_imp() || is_imp() && m_provided_to.num() == 0)
00186       return;
00187    resolve_bindings_all();
00188 
00189   endfunction
00190 
00191 
00192   //----------------------------------------------------------------------------
00193   // resolve_bindings_all
00194   //----------------------------------------------------------------------------
00195   function void resolve_bindings_all();
00196     connector_type c;
00197 
00198     foreach (m_provided_to[s]) begin
00199       c = m_provided_to[s];
00200       if(connect_to(c))
00201         c.resolve_bindings_all();
00202     end
00203 
00204    check_min_connection_size();
00205  
00206   endfunction
00207 
00208 
00209   //--------------------------------------------------------------------
00210   // check_min_connection_size
00211   //--------------------------------------------------------------------
00212 
00213   function void check_min_connection_size();
00214     string s;
00215   
00216     if( size() < min_size() ) begin
00217       $sformat( s,
00218                 "connection count of %0d does not meet required minimum of %0d" ,
00219                 size(), min_size() );
00220       ovm_report_error( s_connection_error_id , s );
00221     end
00222   endfunction
00223 
00224   
00225   //----------------------------------------------------------------------------
00226   // add_if
00227   //
00228   // For old style binding eg ovm_*_port -> tlm_*_if or ovm_*_export to
00229   // to tlm_*_if
00230   //
00231   //----------------------------------------------------------------------------
00232   function bit add_if( IF _if );
00233     string s;
00234     
00235     if(!m_if_container.add_if(_if)) begin
00236       s.itoa(max_size());
00237       s = {"Maximum number of interfaces (",s,") exceeded"};
00238       ovm_report_error( s_connection_error_id , s );
00239       return 0;
00240     end
00241 
00242     return 1;
00243   endfunction
00244 
00245   //----------------------------------------------------------------------------
00246   // lookup_indexed_if
00247   //
00248   // For multiport access
00249   //
00250   //----------------------------------------------------------------------------
00251   function IF lookup_indexed_if( int i = 0 );
00252     string s;
00253     IF ifc;
00254     ifc = m_if_container.lookup_indexed_if(i);
00255   
00256     if(ifc == null) begin
00257       $sformat( s , "Index %0d out of range [0,%0d]" , i , size() );
00258       ovm_report_warning( s_connection_error_id , s );
00259     end
00260     return ifc;
00261   endfunction
00262 
00263   //----------------------------------------------------------------------------
00264   // check_types
00265   //
00266   // checks that the connection types are legal
00267   //----------------------------------------------------------------------------
00268   function bit check_types( connector_type provider );
00269 
00270     string s;
00271   
00272     if( is_imp() || ( is_export() && provider.is_port())) begin
00273 
00274       s = {"Cannot connect ", get_type_name(),
00275            "s to ", provider.get_type_name(),"s"};
00276 
00277       ovm_report_error( s_connection_error_id , s );
00278       return 0;
00279       
00280     end
00281 
00282     return 1; 
00283   endfunction
00284 
00285 
00286   //----------------------------------------------------------------------------
00287   // check_phase
00288   //
00289   // checks that this connection is being made in the correct phase
00290   //----------------------------------------------------------------------------
00291   function bit check_phase( connector_type provider );
00292 
00293     string s;
00294     ovm_phase required_phase, actual_phase;
00295   
00296     required_phase = get_required_phase(provider);
00297     actual_phase = ovm_top.get_current_phase();
00298  
00299     if( required_phase != actual_phase ) begin
00300 
00301       s = {"You have attempted to connect ", get_full_name(),
00302            " to ",provider.get_full_name(), " in phase '",
00303            actual_phase.get_name(),"'" };
00304 
00305       ovm_report_warning( s_connection_error_id , s );
00306 
00307       s = {"You can only connect ", get_type_name(), "s to ", 
00308            provider.get_type_name(), "s in phase '",
00309            required_phase.get_name(), "'" };
00310 
00311       ovm_report_error(s_connection_error_id , s );
00312       return 0;
00313     end
00314   
00315     return 1;
00316   endfunction
00317 
00318 
00319   //----------------------------------------------------------------------------
00320   // check_relationship
00321   //
00322   // checks that the parent child relationships are correct
00323   //----------------------------------------------------------------------------
00324   function bit check_relationship( connector_type provider );  
00325     string s;
00326     ovm_component grandparent;
00327     ovm_component provider_grandparent;
00328   
00329     if( m_parent == null || provider == null || provider.m_parent == null ) begin
00330       // don't check if we have a parentless analysis port
00331       return 1;
00332     end
00333 
00334     grandparent = m_parent.m_parent;
00335     provider_grandparent = provider.m_parent.m_parent;
00336 
00337     // don't check if one or both ends are at top-level
00338     if( grandparent == ovm_top || provider_grandparent == ovm_top)
00339       return 1;
00340   
00341     // REVIEW: temporarily disabling the check in preparation for
00342     // import/export_connections deprecation
00343     return 1;
00344 
00345     // IUS doesn't support a class handle as a case item so use if/else
00346     if ( get_required_phase(provider) == import_connections_ph)
00347       if( grandparent != provider.m_parent ) begin
00348         s = {"connect ( child port -> port ) : ", m_parent.get_full_name(),
00349              " should be a child of %s", provider.m_parent.get_full_name()};
00350         ovm_report_error( s_connection_error_id , s );
00351         return 0;
00352       end    
00353       
00354     else if ( get_required_phase(provider) == connect_ph)
00355       if( grandparent != provider_grandparent ) begin
00356         s = {"connect ( port -> export ) : ", m_parent.get_full_name(),
00357              " should be a sibling of %s", provider.m_parent.get_full_name()};
00358         ovm_report_error( s_connection_error_id , s );
00359         return 0;
00360       end
00361       
00362     else if ( get_required_phase(provider) == export_connections_ph)
00363       if( m_parent != provider_grandparent ) begin
00364         s = {"connect ( export -> child export ) : ", m_parent.get_full_name(),
00365              " should be a parent of %s", provider.m_parent.get_full_name()};
00366         ovm_report_error(s_connection_error_id , s );
00367         return 0;
00368       end
00369 
00370     return 1;
00371   endfunction
00372 
00373  
00374   //----------------------------------------------------------------------------
00375   // get_required_phase
00376   //----------------------------------------------------------------------------
00377   local function ovm_phase get_required_phase(ovm_connector_base provider);
00378   
00379     if( is_export() && ( provider.is_export() || provider.is_imp()))
00380       return export_connections_ph;
00381  
00382     if( is_port() && ( provider.is_export() || provider.is_imp()))
00383       return connect_ph;
00384   
00385     if( is_port() && provider.is_port())
00386       return import_connections_ph;
00387 
00388     ovm_report_error(s_connection_error_id, "no valid required phase");
00389     return null;
00390      
00391   endfunction
00392 
00393 
00394 
00395 
00396 
00397 
00398 
00399   // Deprecated ...
00400 
00401 
00402   //----------------------------------------------------------------------------
00403   // do_display
00404   // 
00405   // do_display is virtual in ovm_component. We only print
00406   // anything if display_connectors is true
00407   //----------------------------------------------------------------------------
00408   function void do_display( int max_level = -1 ,
00409                             int level = 0 ,
00410                             bit display_connectors = 0 );
00411   
00412     if( display_connectors ) begin
00413       ovm_report_info("hierarchy debug" , "" , 1000 );
00414     end
00415   
00416   endfunction  
00417 
00418 
00419   //----------------------------------------------------------------------------
00420   // debug_connected_to
00421   //     
00422   // recurses rightwards through the port->port->export->export->imp
00423   // connections, printing out where it has got to and how many
00424   // interfaces are held at each point
00425   //----------------------------------------------------------------------------
00426   function void debug_connected_to( int level = 0 ,
00427                                     int max_level = -1 );
00428     string s, nm;
00429     int sz;
00430     connector_type connector;
00431 
00432     if( size() > 1 ) begin
00433   
00434       if( m_provided_by.num() > 0 ) begin
00435           $sformat( s , "has %0d interfaces from %0d places" ,
00436           size() , m_provided_by.num() );
00437       end
00438       else begin
00439         $sformat( s , "has %0d interfaces" , size() );
00440       end
00441       
00442       ovm_report_info( s_connection_debug_id , s );
00443     end
00444   
00445     foreach( m_provided_by[i] ) begin
00446       connector = m_provided_by[i];
00447       sz =  connector.size();
00448       nm = connector.get_full_name();
00449       $sformat( s , " has %0d interface%s provided by %s" , sz,
00450                 ( connector.size() == 1 ? "" : "s" ) , nm );
00451       ovm_report_info("Connections Debug" , s );
00452     end
00453 
00454 /*
00455     if( is_imp() ) begin
00456       $sformat( s , " implemented by %s" , m_parent.get_full_name() );
00457       ovm_report_info( s_connection_debug_id , s ); 
00458     end
00459     */
00460 
00461     if( level == max_level ) begin
00462       return;
00463     end
00464  
00465     foreach( m_provided_by[i] ) begin
00466       connector = m_provided_by[i];
00467       connector.debug_connected_to( level + 1 , max_level );
00468     end
00469   
00470   endfunction
00471 
00472 
00473   //----------------------------------------------------------------------------
00474   // debug_provided_to
00475   //
00476   // recurses leftwards through the port->port->export->export->imp
00477   // connections, printing out where it has got to and how many
00478   // interfaces are held at each point
00479   //----------------------------------------------------------------------------
00480   function void debug_provided_to( int level = 0 , int max_level = -1 );
00481     string s, nm;
00482     connector_type connector;
00483 
00484     if( m_provided_to.num() == 0 ) begin
00485       return;
00486     end
00487 
00488     if( size() > 1 ) begin
00489 
00490       if( m_provided_to.num() > 1 ) begin
00491   
00492         $sformat( s , "provides %0d interfaces to %0d ports/exports" ,
00493                   size() , m_provided_to.num() );
00494 
00495       end
00496       else begin
00497         $sformat( s , "provides %0d interfaces" , size() );
00498       end
00499 
00500       ovm_report_info( s_connection_debug_id , s );
00501     end
00502       
00503     foreach( m_provided_to[i] ) begin
00504       connector = m_provided_to[i];
00505       nm = connector.get_full_name();
00506       $sformat( s , "provides %0d interface%s to %s" ,
00507                 size() , ( size() == 1 ? "" : "s") , nm );
00508       
00509       ovm_report_info( s_connection_debug_id , s );
00510     end
00511 
00512     if( level == max_level ) begin
00513       return;
00514     end
00515  
00516     foreach( m_provided_to[i] ) begin
00517       connector = m_provided_to[i];
00518       connector.debug_provided_to( level + 1 , max_level );
00519     end
00520   
00521   endfunction
00522 
00523 
00524   //----------------------------------------------------------------------------
00525   // add_to_debug_list
00526   //
00527   // This method is purely for GUI debugging purposes.
00528   //
00529   // puts this into correct debug list
00530   //
00531   //----------------------------------------------------------------------------
00532   local virtual function void add_to_debug_list();
00533   
00534     case( m_port_type )
00535       OVM_PORT : m_parent.m_ports[get_full_name()] = this;
00536       OVM_EXPORT : m_parent.m_exports[get_full_name()] = this; 
00537       OVM_IMPLEMENTATION : m_parent.m_implementations[get_full_name()] = this;
00538     endcase
00539   endfunction
00540 
00541 endclass
00542 

Intelligent Design Verification
Intelligent Design Verification
Project: OVM, Revision: 1.1.0
Copyright (c) 2008 Intelligent Design Verification.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included here:
http://www.intelligentdv.com/licenses/fdl.txt
doxygen
Doxygen Version: 1.4.6
Mon Sep 29 14:20:12 2008
Find a documentation bug? Report bugs to: bugs.intelligentdv.com Project: DoxygenFilterSV