C:/ESLX/projects/TLMWG/tlm2/include/tlm/tlm_utils/multi_passthrough_target_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_TARGET_SOCKET_H__
00018 #define __MULTI_PASSTHROUGH_TARGET_SOCKET_H__
00019 
00020 #include "multi_socket_bases.h"
00021 #include <sstream>
00022 
00023 namespace tlm_utils {
00024 
00025 /*
00026 This class implements a trivial multi target socket.
00027 The triviality refers to the fact that the socket does not
00028 do blocking to non-blocking or non-blocking to blocking conversions.
00029 
00030 It allows to connect multiple initiators to this socket.
00031 The user has to register callbacks for the fw interface methods
00032 he likes to use. The callbacks are basically equal to the fw interface
00033 methods but carry an additional integer that indicates to which
00034 index of this socket the calling initiator is connected.
00035 */
00036 template <typename MODULE,
00037           unsigned int BUSWIDTH = 32,
00038           typename TYPES = tlm::tlm_base_protocol_types,
00039           unsigned int N=0
00040 #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
00041           ,sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND
00042 #endif
00043           >
00044 class multi_passthrough_target_socket: public multi_target_base< BUSWIDTH,
00045                                                         TYPES,
00046                                                         N
00047 #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
00048                                                         ,POL
00049 #endif
00050                                                         >
00051                               , public multi_to_multi_bind_base<TYPES>
00052 {
00053 
00054 public:
00055 
00056   //typedefs
00057   //  tlm 2.0 types for nb_transport
00058   typedef typename TYPES::tlm_payload_type              transaction_type;
00059   typedef typename TYPES::tlm_phase_type                phase_type;
00060   typedef tlm::tlm_sync_enum                            sync_enum_type;
00061 
00062   //  typedefs to keep the fn ptr notations short
00063   typedef sync_enum_type (MODULE::*nb_cb)(int, transaction_type&, phase_type&, sc_core::sc_time&);
00064   typedef void (MODULE::*b_cb)(int, transaction_type&, sc_core::sc_time&);
00065   typedef unsigned int (MODULE::*dbg_cb)(int, transaction_type& txn);
00066   typedef bool (MODULE::*dmi_cb)(int, transaction_type& txn, tlm::tlm_dmi& dmi);
00067 
00068   typedef multi_target_base<BUSWIDTH,
00069                         TYPES,
00070                         N
00071 #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
00072                         ,POL
00073 #endif
00074                         > base_type;
00075 
00076   typedef typename base_type::base_initiator_socket_type base_initiator_socket_type;
00077   typedef typename base_type::initiator_socket_type initiator_socket_type;
00078 
00079   //CTOR
00080   multi_passthrough_target_socket(const char* name)
00081       : base_type((std::string(name)+std::string("_base")).c_str())
00082       , m_mod(0)
00083       , m_nb_cb(0)
00084       , m_b_cb(0)
00085       , m_dbg_cb(0)
00086       , m_dmi_cb(0)
00087       , m_hierarch_bind(0)
00088       , m_eoe_disabled(false)
00089       , m_dummy(42)
00090   {
00091   }
00092 
00093   ~multi_passthrough_target_socket(){
00094     //clean up everything allocated by 'new'
00095     for (unsigned int i=0; i<m_binders.size(); i++) delete m_binders[i];
00096   }
00097 
00098   //simple helpers for warnings an errors to shorten in code notation
00099   void display_warning(const std::string& text){
00100     std::stringstream s;
00101     s<<"WARNING in instance "<<base_type::name()<<": "<<text;
00102     SC_REPORT_WARNING("multi_socket", s.str().c_str());
00103   }
00104 
00105   void display_error(const std::string& text){
00106     std::stringstream s;
00107     s<<"ERROR in instance "<<base_type::name()<<": "<<text;
00108     SC_REPORT_ERROR("multi_socket", s.str().c_str());
00109   }
00110 
00111   //register callback for nb transport of fw interface
00112   void register_nb_transport_fw(MODULE* mod,
00113                               nb_cb cb)
00114   {
00115     //if our export hasn't been bound yet (due to a hierarch binding)
00116     //  we bind it now.
00117     //We do that here as the user of the target port HAS to bind at least on callback,
00118     //otherwise the socket was useless. Nevertheless, the target socket may still
00119     // stay unbound afterwards.
00120     if (!sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >::get_interface())
00121       sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >::bind(m_dummy);
00122 
00123     //make sure that only one module is registering callbacks with this socket
00124     if (m_mod) assert(m_mod==mod);
00125     else m_mod=mod;
00126 
00127     //warn if there already is a callback
00128     if (m_nb_cb){
00129       display_warning("NBTransport_bw callback already registered.");
00130       return;
00131     }
00132 
00133     //store the callback and create the appropriate boost function
00134     m_nb_cb=cb;
00135     m_nb_f=boost::bind<sync_enum_type>(boost::mem_fn(m_nb_cb), m_mod, _1, _2, _3, _4);
00136   }
00137 
00138   //register callback for b transport of fw interface
00139   void register_b_transport(MODULE* mod,
00140                               b_cb cb)
00141   {
00142     //if our export hasn't been bound yet (due to a hierarch binding)
00143     //  we bind it now.
00144     //We do that here as the user of the target port HAS to bind at least on callback,
00145     //otherwise the socket was useless. Nevertheless, the target socket may still
00146     // stay unbound afterwards.
00147     if (!sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >::get_interface())
00148       sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >::bind(m_dummy);
00149 
00150     //make sure that only one module is registering callbacks with this socket
00151     if (m_mod) assert(m_mod==mod);
00152     else m_mod=mod;
00153 
00154     //warn if there already is a callback
00155     if (m_b_cb){
00156       display_warning("BTransport callback already registered.");
00157       return;
00158     }
00159 
00160     //store the callback and create the appropriate boost function
00161     m_b_cb=cb;
00162     m_b_f=boost::bind<void>(boost::mem_fn(m_b_cb), m_mod, _1, _2, _3);
00163   }
00164 
00165   //register callback for debug transport of fw interface
00166   void register_transport_dbg(MODULE* mod,
00167                               dbg_cb cb)
00168   {
00169     //if our export hasn't been bound yet (due to a hierarch binding)
00170     //  we bind it now.
00171     //We do that here as the user of the target port HAS to bind at least on callback,
00172     //otherwise the socket was useless. Nevertheless, the target socket may still
00173     // stay unbound afterwards.
00174     if (!sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >::get_interface())
00175       sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >::bind(m_dummy);
00176 
00177     //make sure that only one module is registering callbacks with this socket
00178     if (m_mod) assert(m_mod==mod);
00179     else m_mod=mod;
00180 
00181     //warn if there already is a callback
00182     if (m_dbg_cb){
00183       display_warning("DebugTransport callback already registered.");
00184       return;
00185     }
00186 
00187     //store the callback and create the appropriate boost function
00188     m_dbg_cb=cb;
00189     m_dbg_f=boost::bind<unsigned int>(boost::mem_fn(m_dbg_cb), m_mod, _1, _2);
00190   }
00191 
00192   //register callback for DMI of fw interface
00193   void register_get_direct_mem_ptr(MODULE* mod,
00194                                    dmi_cb cb)
00195   {
00196     //if our export hasn't been bound yet (due to a hierarch binding)
00197     //  we bind it now.
00198     //We do that here as the user of the target port HAS to bind at least on callback,
00199     //otherwise the socket was useless. Nevertheless, the target socket may still
00200     // stay unbound afterwards.
00201     if (!sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >::get_interface())
00202       sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >::bind(m_dummy);
00203 
00204     //make sure that only one module is registering callbacks with this socket
00205     if (m_mod) assert(m_mod==mod);
00206     else m_mod=mod;
00207 
00208     //warn if there already is a callback
00209     if (m_dmi_cb){
00210       display_warning("DMI callback already registered.");
00211       return;
00212     }
00213 
00214     //store the callback and create the appropriate boost function
00215     m_dmi_cb=cb;
00216     m_dmi_f=boost::bind<bool>(boost::mem_fn(m_dmi_cb), m_mod, _1, _2, _3);
00217   }
00218 
00219 
00220   //Override virtual functions of the tlm_target_socket:
00221   // this function is called whenever an sc_port (as part of a init socket)
00222   //  wants to bind to the export of the underlying tlm_target_socket
00223   //At this time a callback binder is created an returned to the sc_port
00224   // of the init socket, so that it binds to the callback binder
00225   virtual tlm::tlm_fw_transport_if<TYPES>& get_base_interface()
00226   {
00227     //error if this socket is already bound hierarchically
00228     if (m_hierarch_bind) display_error("Socket already bound hierarchically.");
00229 
00230     m_binders.push_back(new callback_binder_fw<TYPES>(m_binders.size()));
00231     return *m_binders[m_binders.size()-1];
00232   }
00233 
00234   //just return the export of the underlying tlm_target_socket in case of a hierarchical bind
00235   virtual sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >& get_base_export()
00236   {
00237     return *this;
00238   }
00239 
00240   //the standard end of elaboration callback
00241   void end_of_elaboration(){
00242     //'break' here if the socket was told not to do callback binding
00243     if (m_eoe_disabled) return;
00244 
00245     //get the callback binders and the multi binds of the top of the hierachical bind chain
00246     // NOTE: this could be the same socket if there is no hierachical bind
00247     std::vector<callback_binder_fw<TYPES>* >& binders=get_hierarch_bind()->get_binders();
00248     std::map<unsigned int, tlm::tlm_bw_transport_if<TYPES>*>&  multi_binds=get_hierarch_bind()->get_multi_binds();
00249 
00250     //iterate over all binders
00251     for (unsigned int i=0; i<binders.size(); i++) {
00252       binders[i]->set_callbacks(m_nb_f, m_b_f, m_dmi_f, m_dbg_f); //set the callbacks for the binder
00253       if (multi_binds.find(i)!=multi_binds.end()) //check if this connection is multi-multi
00254         //if so remember the interface
00255         m_sockets.push_back(multi_binds[i]);
00256       else{ //if we are bound to a normal socket
00257         //get the calling port and try to cast it into a tlm socket base
00258         base_initiator_socket_type* test=dynamic_cast<base_initiator_socket_type*>(binders[i]->get_other_side());
00259         if (!test){display_error("Not bound to tlm_socket.");}
00260         m_sockets.push_back(&test->get_base_interface()); //remember the interface
00261       }
00262     }
00263   }
00264 
00265   //
00266   // Bind multi target socket to multi target socket (hierarchical bind)
00267   //
00268   void bind(base_type& s)
00269   {
00270     //warn if already bound hierarchically
00271     if (m_eoe_disabled){
00272       display_warning("Socket already bound hierarchically. Bind attempt ignored.");
00273       return;
00274     }
00275 
00276     //disable our own end of elaboration call
00277     disable_cb_bind();
00278 
00279     //inform the bound target socket that it is bound hierarchically now
00280     s.set_hierarch_bind((base_type*)this);
00281     base_type::bind(s); //satisfy SystemC
00282   }
00283 
00284   //operator notation for hierarchical bind
00285   void operator() (base_type& s)
00286   {
00287     bind(s);
00288   }
00289 
00290   //get access to sub port
00291   tlm::tlm_bw_transport_if<TYPES>* operator[](int i){return m_sockets[i];}
00292 
00293   //get number of bound initiators
00294   // NOTE: this is only valid at end of elaboration!
00295   unsigned int size(){return get_hierarch_bind()->get_binders().size();}
00296 
00297 protected:
00298   //implementation of base class interface
00299   base_type* get_hierarch_bind(){if (m_hierarch_bind) return m_hierarch_bind->get_hierarch_bind(); else return this;}
00300   std::map<unsigned int, tlm::tlm_bw_transport_if<TYPES>*>&  get_multi_binds(){return m_multi_binds;}
00301   void set_hierarch_bind(base_type* h){m_hierarch_bind=h;}
00302   tlm::tlm_fw_transport_if<TYPES>* get_last_binder(tlm::tlm_bw_transport_if<TYPES>* other){
00303     m_multi_binds[m_binders.size()-1]=other;
00304     return m_binders[m_binders.size()-1];
00305   }
00306 
00307   //map that stores to which index a multi init socket is connected
00308   // and the interface of the multi init socket
00309   std::map<unsigned int, tlm::tlm_bw_transport_if<TYPES>*> m_multi_binds;
00310 
00311   void disable_cb_bind(){ m_eoe_disabled=true;}
00312   std::vector<callback_binder_fw<TYPES>* >& get_binders(){return m_binders;}
00313   //vector of connected sockets
00314   std::vector<tlm::tlm_bw_transport_if<TYPES>*> m_sockets;
00315   //vector of binders that convert untagged interface into tagged interface
00316   std::vector<callback_binder_fw<TYPES>*> m_binders;
00317 
00318   MODULE* m_mod; //the owning module
00319   nb_cb   m_nb_cb; //the nb callback of the owning module
00320   b_cb    m_b_cb;  //the b callback of the owning module
00321   dbg_cb  m_dbg_cb; //the debug callback of the owning module
00322   dmi_cb  m_dmi_cb; //the dmi callback of the owning module
00323   base_type*  m_hierarch_bind; //pointer to hierarchical bound multi port
00324   bool m_eoe_disabled; //bool that diables callback bindings at end of elaboration
00325   callback_binder_fw<TYPES> m_dummy; //a dummy to bind to the export
00326 
00327   //callbacks as boost functions
00328   // (allows to pass the callback to another socket that does not know the type of the module that owns
00329   //  the callbacks)
00330   boost::function<sync_enum_type (int i, transaction_type& txn, phase_type& p, sc_core::sc_time& t)> m_nb_f;
00331   boost::function<void (int i, transaction_type& txn, sc_core::sc_time& t)> m_b_f;
00332   boost::function<unsigned int (int i, transaction_type& txn)> m_dbg_f;
00333   boost::function<bool (int i, transaction_type& txn, tlm::tlm_dmi& dmi)> m_dmi_f;
00334 
00335 };
00336 
00337 }
00338 
00339 #endif

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