TLM-2.0: include/tlm/tlm_utils/multi_passthrough_initiator_socket.h Source File

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# 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()
    00079       : base_type(sc_core::sc_gen_unique_name("multi_passthrough_initiator_socket"))
    00080       , m_hierarch_bind(0)
    00081       , m_beoe_disabled(false)
    00082       , m_dummy(42)
    00083   {
    00084   }
    00085
    00086   //CTOR
    00087   multi_passthrough_initiator_socket(const char* name)
    00088       : base_type(name)
    00089       , m_hierarch_bind(0)
    00090       , m_beoe_disabled(false)
    00091       , m_dummy(42)
    00092   {
    00093   }
    00094
    00095   ~multi_passthrough_initiator_socket(){
    00096     //clean up everything allocated by 'new'
    00097     for (unsigned int i=0; i<m_binders.size(); i++) delete m_binders[i];
    00098   }
    00099
    00100   //simple helpers for warnings an errors to shorten in code notation
    00101   void display_warning(const std::string& text){
    00102     std::stringstream s;
    00103     s<<"WARNING in instance "<<base_type::name()<<": "<<text;
    00104     SC_REPORT_WARNING("/OSCI_TLM-2/multi_socket", s.str().c_str());
    00105   }
    00106
    00107   void display_error(const std::string& text){
    00108     std::stringstream s;
    00109     s<<"ERROR in instance "<<base_type::name()<<": "<<text;
    00110     SC_REPORT_ERROR("/OSCI_TLM-2/multi_socket", s.str().c_str());
    00111   }
    00112
    00113
    00114   //register callback for nb transport of bw interface
    00115   void register_nb_transport_bw(MODULE* mod,
    00116                               sync_enum_type (MODULE::*cb)(int,
    00117                                                            transaction_type&,
    00118                                                            phase_type&,
    00119                                                            sc_core::sc_time&))
    00120   {
    00121     //warn if there already is a callback
    00122     if (!m_nb_f.empty()){
    00123       display_warning("NBTransport_bw callback already registered.");
    00124       return;
    00125     }
    00126
    00127     //set the functor
    00128     m_nb_f.set_function(mod, cb);
    00129   }
    00130
    00131   //register callback for dmi function of bw interface
    00132   void register_invalidate_direct_mem_ptr(MODULE* mod,
    00133                              void (MODULE::*cb)(int, sc_dt::uint64, sc_dt::uint64))
    00134   {
    00135     //warn if there already is a callback
    00136     if (!m_dmi_f.empty()){
    00137       display_warning("InvalidateDMI callback already registered.");
    00138       return;
    00139     }
    00140
    00141     //set the functor
    00142     m_dmi_f.set_function(mod, cb);
    00143   }
    00144
    00145   //Override virtual functions of the tlm_initiator_socket:
    00146   // this function is called whenever an sc_port (as part of a target socket)
    00147   //  wants to bind to the export of the underlying tlm_initiator_socket
    00148   //At this time a callback binder is created an returned to the sc_port
    00149   // of the target socket, so that it binds to the callback binder
    00150   virtual tlm::tlm_bw_transport_if<TYPES>& get_base_interface()
    00151   {
    00152     m_binders.push_back(new callback_binder_bw<TYPES>(m_binders.size()));
    00153     return *m_binders[m_binders.size()-1];
    00154   }
    00155
    00156   //Override virtual functions of the tlm_initiator_socket:
    00157   // this function is called whenever an sc_export (as part of a initiator socket)
    00158   //  wants to bind to the export of the underlying tlm_initiator_socket
    00159   //   i.e. a hierarchical bind takes place
    00160   virtual sc_core::sc_export<tlm::tlm_bw_transport_if<TYPES> >& get_base_export()
    00161   {
    00162     if (!m_beoe_disabled) //we are not bound hierarchically
    00163       base_type::m_export.bind(m_dummy);  //so we bind the dummy to avoid a SystemC error
    00164     return base_type::m_export; //and then return our own export so that the hierarchical binding is set up properly
    00165   }
    00166
    00167   //bind against a target socket
    00168   void bind(base_target_socket_type& s)
    00169   {
    00170     //error if this socket is already bound hierarchically
    00171     if (m_hierarch_bind)
    00172       display_error("Already hierarchically bound.");
    00173
    00174     base_type::bind(s); //satisfy systemC, leads to a call to get_base_interface()
    00175
    00176     //try to cast the target socket into a fw interface
    00177     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);
    00178     if (!p_ex_s) display_error("Multi socket not bound to tlm_socket.");
    00179
    00180     //try a cast into a multi sockets
    00181     multi_to_multi_bind_base<TYPES>* test=dynamic_cast<multi_to_multi_bind_base<TYPES>*> (p_ex_s);
    00182     if (test) //did we just do a multi-multi bind??
    00183       //if that is the case the multi target socket must have just created a callback binder
    00184       // which we want to get from it.
    00185       //Moreover, we also just created one, which we will pass to it.
    00186       m_sockets.push_back(test->get_last_binder(m_binders[m_binders.size()-1]));
    00187     else{  // if not just bind normally
    00188       sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >& ex_s=*p_ex_s;
    00189       m_sockets.push_back(&((tlm::tlm_fw_transport_if<TYPES>&)ex_s)); //store the interface we are bound against
    00190     }
    00191   }
    00192
    00193   //operator notation for direct bind
    00194   void operator() (base_target_socket_type& s)
    00195   {
    00196     bind(s);
    00197   }
    00198
    00199   //SystemC standard callback before end of elaboration
    00200   void before_end_of_elaboration(){
    00201     //if our export hasn't been bound yet (due to a hierarch binding)
    00202     // we bind it now to avoid a SystemC error.
    00203     //We must do that, because it is legal not to register a callback on this socket
    00204     // as the user might only use b_transport
    00205     if (!base_type::m_export.get_interface()){
    00206       base_type::m_export.bind(m_dummy);
    00207     }
    00208
    00209     //'break' here if the socket was told not to do callback binding
    00210     if (m_beoe_disabled) return;
    00211
    00212     //get the callback binders of the top of the hierachical bind chain
    00213     // NOTE: this could be the same socket if there is no hierachical bind
    00214     std::vector<callback_binder_bw<TYPES>* >& binders=get_hierarch_bind()->get_binders();
    00215
    00216     //get the interfaces bound to the top of the hierachical bind chain
    00217     // NOTE: this could be the same socket if there is no hierachical bind
    00218     m_used_sockets=get_hierarch_bind()->get_sockets();
    00219
    00220     //register the callbacks of this socket with the callback binders
    00221     // we just got from the top of the hierachical bind chain
    00222     for (unsigned int i=0; i<binders.size(); i++) {
    00223       binders[i]->set_callbacks(m_nb_f, m_dmi_f);
    00224     }
    00225   }
    00226
    00227   //
    00228   // Bind multi initiator socket to multi initiator socket (hierarchical bind)
    00229   //
    00230   void bind(base_type& s)
    00231   {
    00232     if (m_binders.size()) //a multi socket is either bound hierarchically or directly
    00233       display_error("Socket already directly bound.");
    00234     if (m_hierarch_bind){
    00235       display_warning("Socket already bound hierarchically. Bind attempt ignored.");
    00236       return;
    00237     }
    00238
    00239     //remember to which socket we are hierarchically bound and disable it,
    00240     // so that it won't try to register callbacks itself
    00241     s.disable_cb_bind();
    00242     m_hierarch_bind=&s;
    00243     base_type::bind(s); //satisfy SystemC
    00244   }
    00245
    00246   //operator notation for hierarchical bind
    00247   void operator() (base_type& s)
    00248   {
    00249     bind(s);
    00250   }
    00251
    00252   //get access to sub port
    00253   tlm::tlm_fw_transport_if<TYPES>* operator[](int i){return m_used_sockets[i];}
    00254
    00255   //get the number of bound targets
    00256   // NOTE: this is only valid at end of elaboration!
    00257   unsigned int size() {return get_hierarch_bind()->get_sockets().size();}
    00258
    00259 protected:
    00260   //implementation of base class interface
    00261   base_type* get_hierarch_bind(){if (m_hierarch_bind) return m_hierarch_bind->get_hierarch_bind(); else return this;}
    00262   void disable_cb_bind(){ m_beoe_disabled=true;}
    00263   std::vector<callback_binder_bw<TYPES>* >& get_binders(){return m_binders;}
    00264   std::vector<tlm::tlm_fw_transport_if<TYPES>*>& get_sockets(){return m_sockets;}
    00265   //vector of connected sockets
    00266   std::vector<tlm::tlm_fw_transport_if<TYPES>*> m_sockets;
    00267   std::vector<tlm::tlm_fw_transport_if<TYPES>*> m_used_sockets;
    00268   //vector of binders that convert untagged interface into tagged interface
    00269   std::vector<callback_binder_bw<TYPES>*> m_binders;
    00270
    00271   base_type*  m_hierarch_bind; //pointer to hierarchical bound multi port
    00272   bool m_beoe_disabled;  // bool that remembers whether this socket shall bind callbacks or not
    00273   callback_binder_bw<TYPES> m_dummy; //a callback binder that is bound to the underlying export
    00274                                      // in case there was no real bind
    00275
    00276   //callbacks as functors
    00277   // (allows to pass the callback to another socket that does not know the type of the module that owns
    00278   //  the callbacks)
    00279   typename callback_binder_bw<TYPES>::nb_func_type  m_nb_f;
    00280   typename callback_binder_bw<TYPES>::dmi_func_type m_dmi_f;
    00281 };
    00282
    00283 }
    00284
    00285 #endif