C:/ESLX/projects/TLMWG/tlm2/include/tlm/tlm_utils/multi_passthrough_initiator_socket.h

Go to the documentation of this file.
00001 /*****************************************************************************
00002 
00003   The following code is derived, directly or indirectly, from the SystemC
00004   source code Copyright (c) 1996-2008 by all Contributors.
00005   All Rights reserved.
00006 
00007   The contents of this file are subject to the restrictions and limitations
00008   set forth in the SystemC Open Source License Version 3.0 (the "License");
00009   You may not use this file except in compliance with such restrictions and
00010   limitations. You may obtain instructions on how to receive a copy of the
00011   License at http://www.systemc.org/. Software distributed by Contributors
00012   under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
00013   ANY KIND, either express or implied. See the License for the specific
00014   language governing rights and limitations under the License.
00015 
00016  *****************************************************************************/
00017 #ifndef __MULTI_PASSTHROUGH_INITIATOR_SOCKET_H__
00018 #define __MULTI_PASSTHROUGH_INITIATOR_SOCKET_H__
00019 
00020 #include "multi_socket_bases.h"
00021 
00022 namespace tlm_utils {
00023 
00024 /*
00025 This class implements a trivial multi initiator socket.
00026 The triviality refers to the fact that the socket does not
00027 do blocking to non-blocking or non-blocking to blocking conversions.
00028 
00029 It allows to connect multiple targets to this socket.
00030 The user has to register callbacks for the bw interface methods
00031 he likes to use. The callbacks are basically equal to the bw interface
00032 methods but carry an additional integer that indicates to which
00033 index of this socket the calling target is connected.
00034 */
00035 template <typename MODULE,
00036           unsigned int BUSWIDTH = 32,
00037           typename TYPES = tlm::tlm_base_protocol_types,
00038           unsigned int N=0
00039 #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
00040           ,sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND
00041 #endif
00042           >
00043 class multi_passthrough_initiator_socket: public multi_init_base< BUSWIDTH, 
00044                                                         TYPES,
00045                                                         N
00046 #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
00047                                                         ,POL
00048 #endif
00049                                                         >
00050 {
00051 
00052 public:
00053 
00054   //typedefs
00055   //  tlm 2.0 types for nb_transport
00056   typedef typename TYPES::tlm_payload_type              transaction_type;
00057   typedef typename TYPES::tlm_phase_type                phase_type;  
00058   typedef tlm::tlm_sync_enum                            sync_enum_type;
00059   
00060   //  typedefs to keep the fn ptr notations short
00061   typedef sync_enum_type (MODULE::*nb_cb)(int,
00062                                          transaction_type&,
00063                                          phase_type&,
00064                                          sc_core::sc_time&);
00065   typedef void (MODULE::*dmi_cb)(int, sc_dt::uint64, sc_dt::uint64);
00066 
00067   typedef multi_init_base<BUSWIDTH, 
00068                         TYPES,
00069                         N
00070 #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
00071                         ,POL
00072 #endif
00073                         > base_type;
00074 
00075   typedef typename base_type::base_target_socket_type base_target_socket_type;
00076 
00077   //CTOR
00078   multi_passthrough_initiator_socket(const char* name)
00079       : base_type((std::string(name)+std::string("_base")).c_str())
00080       , m_mod(0)
00081       , m_nb_cb(0)
00082       , m_dmi_cb(0)
00083       , m_hierarch_bind(0)
00084       , m_beoe_disabled(false)
00085       , m_dummy(42)
00086   {
00087   }
00088 
00089   ~multi_passthrough_initiator_socket(){
00090     //clean up everything allocated by 'new'
00091     for (unsigned int i=0; i<m_binders.size(); i++) delete m_binders[i];
00092   }
00093   
00094   //simple helpers for warnings an errors to shorten in code notation
00095   void display_warning(const std::string& text){
00096     std::stringstream s;
00097     s<<"WARNING in instance "<<base_type::name()<<": "<<text;
00098     SC_REPORT_WARNING("multi_socket", s.str().c_str());
00099   }
00100 
00101   void display_error(const std::string& text){
00102     std::stringstream s;
00103     s<<"ERROR in instance "<<base_type::name()<<": "<<text;
00104     SC_REPORT_ERROR("multi_socket", s.str().c_str());
00105   }
00106 
00107 
00108   //register callback for nb transport of bw interface
00109   void register_nb_transport_bw(MODULE* mod,
00110                               sync_enum_type (MODULE::*cb)(int,
00111                                                            transaction_type&,
00112                                                            phase_type&,
00113                                                            sc_core::sc_time&))
00114   {
00115     //make sure that only one module is registering callbacks with this socket
00116     if (m_mod) assert(m_mod==mod);
00117     else m_mod=mod;
00118     
00119     //warn if there already is a callback
00120     if (m_nb_cb){
00121       display_warning("NBTransport_bw callback already registered.");
00122       return;
00123     }
00124     
00125     //store the callback and create the appropriate boost function
00126     m_nb_cb=cb;
00127     m_nb_f=boost::bind<sync_enum_type>(boost::mem_fn(m_nb_cb) , m_mod, _1, _2, _3, _4);
00128   }
00129 
00130   //register callback for dmi function of bw interface
00131   void register_invalidate_direct_mem_ptr(MODULE* mod,
00132                              void (MODULE::*cb)(int, sc_dt::uint64, sc_dt::uint64))
00133   {
00134     //make sure that only one module is registering callbacks with this socket
00135     if (m_mod) assert(m_mod==mod);
00136     else m_mod=mod;
00137 
00138     //warn if there already is a callback
00139     if (m_dmi_cb){
00140       display_warning("InvalidateDMI callback already registered.");
00141       return;
00142     }
00143     
00144     //store the callback and create the appropriate boost function
00145     m_dmi_cb=cb;
00146     m_dmi_f=boost::bind<void>(boost::mem_fn(m_dmi_cb), m_mod, _1, _2, _3);
00147   }
00148 
00149   //Override virtual functions of the tlm_initiator_socket:
00150   // this function is called whenever an sc_port (as part of a target socket)
00151   //  wants to bind to the export of the underlying tlm_initiator_socket
00152   //At this time a callback binder is created an returned to the sc_port
00153   // of the target socket, so that it binds to the callback binder
00154   virtual tlm::tlm_bw_transport_if<TYPES>& get_base_interface()
00155   {
00156     m_binders.push_back(new callback_binder_bw<TYPES>(m_binders.size()));
00157     return *m_binders[m_binders.size()-1];
00158   }
00159 
00160   //Override virtual functions of the tlm_initiator_socket:
00161   // this function is called whenever an sc_export (as part of a initiator socket)
00162   //  wants to bind to the export of the underlying tlm_initiator_socket
00163   //   i.e. a hierarchical bind takes place
00164   virtual sc_core::sc_export<tlm::tlm_bw_transport_if<TYPES> >& get_base_export()
00165   {
00166     if (!m_beoe_disabled) //we are not bound hierarchically
00167       base_type::m_export.bind(m_dummy);  //so we bind the dummy to avoid a SystemC error
00168     return base_type::m_export; //and then return our own export so that the hierarchical binding is set up properly
00169   }
00170 
00171   //bind against a target socket
00172   void bind(base_target_socket_type& s)
00173   {
00174     //error if this socket is already bound hierarchically
00175     if (m_hierarch_bind)
00176       display_error("Already hierarchically bound.");     
00177        
00178     base_type::bind(s); //satisfy systemC, leads to a call to get_base_interface()
00179     
00180     //try to cast the target socket into a fw interface
00181     sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >* p_ex_s=dynamic_cast<sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >*>(&s);
00182     if (!p_ex_s) display_error("Multi socket not bound to tlm_socket.");
00183     
00184     //try a cast into a multi sockets
00185     multi_to_multi_bind_base<TYPES>* test=dynamic_cast<multi_to_multi_bind_base<TYPES>*> (p_ex_s);
00186     if (test) //did we just do a multi-multi bind??
00187       //if that is the case the multi target socket must have just created a callback binder
00188       // which we want to get from it.
00189       //Moreover, we also just created one, which we will pass to it.
00190       m_sockets.push_back(test->get_last_binder(m_binders[m_binders.size()-1])); 
00191     else{  // if not just bind normally
00192       sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >& ex_s=*p_ex_s;
00193       m_sockets.push_back(&((tlm::tlm_fw_transport_if<TYPES>&)ex_s)); //store the interface we are bound against
00194     }
00195   }
00196 
00197   //operator notation for direct bind
00198   void operator() (base_target_socket_type& s)
00199   {
00200     bind(s);
00201   }
00202   
00203   //SystemC standard callback before end of elaboration
00204   void before_end_of_elaboration(){
00205     //if our export hasn't been bound yet (due to a hierarch binding)
00206     // we bind it now to avoid a SystemC error.
00207     //We must do that, because it is legal not to register a callback on this socket
00208     // as the user might only use b_transport
00209     if (!base_type::m_export.get_interface()){ 
00210       base_type::m_export.bind(m_dummy);      
00211     }
00212     
00213     //'break' here if the socket was told not to do callback binding
00214     if (m_beoe_disabled) return;
00215     
00216     //get the callback binders of the top of the hierachical bind chain
00217     // NOTE: this could be the same socket if there is no hierachical bind
00218     std::vector<callback_binder_bw<TYPES>* >& binders=get_hierarch_bind()->get_binders();
00219 
00220     //get the interfaces bound to the top of the hierachical bind chain
00221     // NOTE: this could be the same socket if there is no hierachical bind
00222     m_used_sockets=get_hierarch_bind()->get_sockets();
00223     
00224     //register the callbacks of this socket with the callback binders
00225     // we just got from the top of the hierachical bind chain
00226     for (unsigned int i=0; i<binders.size(); i++) {
00227       binders[i]->set_callbacks(m_nb_f, m_dmi_f);
00228     }
00229   }
00230 
00231   //
00232   // Bind multi initiator socket to multi initiator socket (hierarchical bind)
00233   //
00234   void bind(base_type& s)
00235   {
00236     if (m_binders.size()) //a multi socket is either bound hierarchically or directly
00237       display_error("Socket already directly bound.");
00238     if (m_hierarch_bind){
00239       display_warning("Socket already bound hierarchically. Bind attempt ignored.");
00240       return;
00241     }
00242     
00243     //remember to which socket we are hierarchically bound and disable it, 
00244     // so that it won't try to register callbacks itself
00245     s.disable_cb_bind();
00246     m_hierarch_bind=&s;    
00247     base_type::bind(s); //satisfy SystemC
00248   }
00249 
00250   //operator notation for hierarchical bind
00251   void operator() (base_type& s)
00252   {
00253     bind(s);
00254   }
00255 
00256   //get access to sub port
00257   tlm::tlm_fw_transport_if<TYPES>* operator[](int i){return m_used_sockets[i];}
00258   
00259   //get the number of bound targets
00260   // NOTE: this is only valid at end of elaboration!
00261   unsigned int size() {return get_hierarch_bind()->get_sockets().size();}
00262 
00263 protected:
00264   //implementation of base class interface
00265   base_type* get_hierarch_bind(){if (m_hierarch_bind) return m_hierarch_bind->get_hierarch_bind(); else return this;}
00266   void disable_cb_bind(){ m_beoe_disabled=true;}
00267   std::vector<callback_binder_bw<TYPES>* >& get_binders(){return m_binders;}
00268   std::vector<tlm::tlm_fw_transport_if<TYPES>*>& get_sockets(){return m_sockets;}
00269   //vector of connected sockets
00270   std::vector<tlm::tlm_fw_transport_if<TYPES>*> m_sockets;
00271   std::vector<tlm::tlm_fw_transport_if<TYPES>*> m_used_sockets;
00272   //vector of binders that convert untagged interface into tagged interface
00273   std::vector<callback_binder_bw<TYPES>*> m_binders;
00274   
00275   MODULE* m_mod; //the owning module
00276   nb_cb   m_nb_cb; //the nb callback of the owning module
00277   dmi_cb  m_dmi_cb; //the dmi callback of the owning module
00278   base_type*  m_hierarch_bind; //pointer to hierarchical bound multi port
00279   bool m_beoe_disabled;  // bool that remembers whether this socket shall bind callbacks or not
00280   callback_binder_bw<TYPES> m_dummy; //a callback binder that is bound to the underlying export
00281                                      // in case there was no real bind
00282 
00283   //callbacks as boost functions
00284   // (allows to pass the callback to another socket that does not know the type of the module that owns
00285   //  the callbacks)
00286   boost::function<sync_enum_type (int i, transaction_type& txn, phase_type& p, sc_core::sc_time& t)> m_nb_f;
00287   boost::function<void (int i, sc_dt::uint64 l, sc_dt::uint64 u)> m_dmi_f;
00288 };
00289 
00290 }
00291 
00292 #endif

Generated on Thu Jun 5 17:43:03 2008 for TLM 2 by  doxygen 1.5.3