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

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# 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
    00078   //CTOR
    00079   multi_passthrough_target_socket()
    00080       : base_type(sc_core::sc_gen_unique_name("multi_passthrough_target_socket"))
    00081       , m_hierarch_bind(0)
    00082       , m_eoe_disabled(false)
    00083       , m_dummy(42)
    00084   {
    00085   }
    00086
    00087   //CTOR
    00088   multi_passthrough_target_socket(const char* name)
    00089       : base_type(name)
    00090       , m_hierarch_bind(0)
    00091       , m_eoe_disabled(false)
    00092       , m_dummy(42)
    00093   {
    00094   }
    00095
    00096   ~multi_passthrough_target_socket(){
    00097     //clean up everything allocated by 'new'
    00098     for (unsigned int i=0; i<m_binders.size(); i++) delete m_binders[i];
    00099   }
    00100
    00101   //simple helpers for warnings an errors to shorten in code notation
    00102   void display_warning(const std::string& text){
    00103     std::stringstream s;
    00104     s<<"WARNING in instance "<<base_type::name()<<": "<<text;
    00105     SC_REPORT_WARNING("/OSCI_TLM-2/multi_socket", s.str().c_str());
    00106   }
    00107
    00108   void display_error(const std::string& text){
    00109     std::stringstream s;
    00110     s<<"ERROR in instance "<<base_type::name()<<": "<<text;
    00111     SC_REPORT_ERROR("/OSCI_TLM-2/multi_socket", s.str().c_str());
    00112   }
    00113
    00114   //register callback for nb transport of fw interface
    00115   void register_nb_transport_fw(MODULE* mod,
    00116                               nb_cb cb)
    00117   {
    00118     //if our export hasn't been bound yet (due to a hierarch binding)
    00119     //  we bind it now.
    00120     //We do that here as the user of the target port HAS to bind at least on callback,
    00121     //otherwise the socket was useless. Nevertheless, the target socket may still
    00122     // stay unbound afterwards.
    00123     if (!sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >::get_interface())
    00124       sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >::bind(m_dummy);
    00125
    00126     //warn if there already is a callback
    00127     if (!m_nb_f.empty()){
    00128       display_warning("NBTransport_bw callback already registered.");
    00129       return;
    00130     }
    00131
    00132     //set the functor
    00133     m_nb_f.set_function(mod, cb);
    00134   }
    00135
    00136   //register callback for b transport of fw interface
    00137   void register_b_transport(MODULE* mod,
    00138                               b_cb cb)
    00139   {
    00140     //if our export hasn't been bound yet (due to a hierarch binding)
    00141     //  we bind it now.
    00142     //We do that here as the user of the target port HAS to bind at least on callback,
    00143     //otherwise the socket was useless. Nevertheless, the target socket may still
    00144     // stay unbound afterwards.
    00145     if (!sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >::get_interface())
    00146       sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >::bind(m_dummy);
    00147
    00148     //warn if there already is a callback
    00149     if (!m_b_f.empty()){
    00150       display_warning("BTransport callback already registered.");
    00151       return;
    00152     }
    00153
    00154     //set the functor
    00155     m_b_f.set_function(mod, cb);
    00156   }
    00157
    00158   //register callback for debug transport of fw interface
    00159   void register_transport_dbg(MODULE* mod,
    00160                               dbg_cb cb)
    00161   {
    00162     //if our export hasn't been bound yet (due to a hierarch binding)
    00163     //  we bind it now.
    00164     //We do that here as the user of the target port HAS to bind at least on callback,
    00165     //otherwise the socket was useless. Nevertheless, the target socket may still
    00166     // stay unbound afterwards.
    00167     if (!sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >::get_interface())
    00168       sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >::bind(m_dummy);
    00169
    00170     //warn if there already is a callback
    00171     if (!m_dbg_f.empty()){
    00172       display_warning("DebugTransport callback already registered.");
    00173       return;
    00174     }
    00175
    00176     //set the functor
    00177     m_dbg_f.set_function(mod, cb);
    00178   }
    00179
    00180   //register callback for DMI of fw interface
    00181   void register_get_direct_mem_ptr(MODULE* mod,
    00182                                    dmi_cb cb)
    00183   {
    00184     //if our export hasn't been bound yet (due to a hierarch binding)
    00185     //  we bind it now.
    00186     //We do that here as the user of the target port HAS to bind at least on callback,
    00187     //otherwise the socket was useless. Nevertheless, the target socket may still
    00188     // stay unbound afterwards.
    00189     if (!sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >::get_interface())
    00190       sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >::bind(m_dummy);
    00191
    00192     //warn if there already is a callback
    00193     if (!m_dmi_f.empty()){
    00194       display_warning("DMI callback already registered.");
    00195       return;
    00196     }
    00197
    00198     //set the functor
    00199     m_dmi_f.set_function(mod, cb);
    00200   }
    00201
    00202
    00203   //Override virtual functions of the tlm_target_socket:
    00204   // this function is called whenever an sc_port (as part of a init socket)
    00205   //  wants to bind to the export of the underlying tlm_target_socket
    00206   //At this time a callback binder is created an returned to the sc_port
    00207   // of the init socket, so that it binds to the callback binder
    00208   virtual tlm::tlm_fw_transport_if<TYPES>& get_base_interface()
    00209   {
    00210     //error if this socket is already bound hierarchically
    00211     if (m_hierarch_bind) display_error("Socket already bound hierarchically.");
    00212
    00213     m_binders.push_back(new callback_binder_fw<TYPES>(m_binders.size()));
    00214     return *m_binders[m_binders.size()-1];
    00215   }
    00216
    00217   //just return the export of the underlying tlm_target_socket in case of a hierarchical bind
    00218   virtual sc_core::sc_export<tlm::tlm_fw_transport_if<TYPES> >& get_base_export()
    00219   {
    00220     return *this;
    00221   }
    00222
    00223   //the standard end of elaboration callback
    00224   void end_of_elaboration(){
    00225     //'break' here if the socket was told not to do callback binding
    00226     if (m_eoe_disabled) return;
    00227
    00228     //get the callback binders and the multi binds of the top of the hierachical bind chain
    00229     // NOTE: this could be the same socket if there is no hierachical bind
    00230     std::vector<callback_binder_fw<TYPES>* >& binders=get_hierarch_bind()->get_binders();
    00231     std::map<unsigned int, tlm::tlm_bw_transport_if<TYPES>*>&  multi_binds=get_hierarch_bind()->get_multi_binds();
    00232
    00233     //iterate over all binders
    00234     for (unsigned int i=0; i<binders.size(); i++) {
    00235       binders[i]->set_callbacks(m_nb_f, m_b_f, m_dmi_f, m_dbg_f); //set the callbacks for the binder
    00236       if (multi_binds.find(i)!=multi_binds.end()) //check if this connection is multi-multi
    00237         //if so remember the interface
    00238         m_sockets.push_back(multi_binds[i]);
    00239       else{ //if we are bound to a normal socket
    00240         //get the calling port and try to cast it into a tlm socket base
    00241         base_initiator_socket_type* test=dynamic_cast<base_initiator_socket_type*>(binders[i]->get_other_side());
    00242         if (!test){display_error("Not bound to tlm_socket.");}
    00243         m_sockets.push_back(&test->get_base_interface()); //remember the interface
    00244       }
    00245     }
    00246   }
    00247
    00248   //
    00249   // Bind multi target socket to multi target socket (hierarchical bind)
    00250   //
    00251   void bind(base_type& s)
    00252   {
    00253     //warn if already bound hierarchically
    00254     if (m_eoe_disabled){
    00255       display_warning("Socket already bound hierarchically. Bind attempt ignored.");
    00256       return;
    00257     }
    00258
    00259     //disable our own end of elaboration call
    00260     disable_cb_bind();
    00261
    00262     //inform the bound target socket that it is bound hierarchically now
    00263     s.set_hierarch_bind((base_type*)this);
    00264     base_type::bind(s); //satisfy SystemC
    00265   }
    00266
    00267   //operator notation for hierarchical bind
    00268   void operator() (base_type& s)
    00269   {
    00270     bind(s);
    00271   }
    00272
    00273   //get access to sub port
    00274   tlm::tlm_bw_transport_if<TYPES>* operator[](int i){return m_sockets[i];}
    00275
    00276   //get number of bound initiators
    00277   // NOTE: this is only valid at end of elaboration!
    00278   unsigned int size(){return get_hierarch_bind()->get_binders().size();}
    00279
    00280 protected:
    00281   //implementation of base class interface
    00282   base_type* get_hierarch_bind(){if (m_hierarch_bind) return m_hierarch_bind->get_hierarch_bind(); else return this;}
    00283   std::map<unsigned int, tlm::tlm_bw_transport_if<TYPES>*>&  get_multi_binds(){return m_multi_binds;}
    00284   void set_hierarch_bind(base_type* h){m_hierarch_bind=h;}
    00285   tlm::tlm_fw_transport_if<TYPES>* get_last_binder(tlm::tlm_bw_transport_if<TYPES>* other){
    00286     m_multi_binds[m_binders.size()-1]=other;
    00287     return m_binders[m_binders.size()-1];
    00288   }
    00289
    00290   //map that stores to which index a multi init socket is connected
    00291   // and the interface of the multi init socket
    00292   std::map<unsigned int, tlm::tlm_bw_transport_if<TYPES>*> m_multi_binds;
    00293
    00294   void disable_cb_bind(){ m_eoe_disabled=true;}
    00295   std::vector<callback_binder_fw<TYPES>* >& get_binders(){return m_binders;}
    00296   //vector of connected sockets
    00297   std::vector<tlm::tlm_bw_transport_if<TYPES>*> m_sockets;
    00298   //vector of binders that convert untagged interface into tagged interface
    00299   std::vector<callback_binder_fw<TYPES>*> m_binders;
    00300
    00301   base_type*  m_hierarch_bind; //pointer to hierarchical bound multi port
    00302   bool m_eoe_disabled; //bool that diables callback bindings at end of elaboration
    00303   callback_binder_fw<TYPES> m_dummy; //a dummy to bind to the export
    00304
    00305   //callbacks as functors
    00306   // (allows to pass the callback to another socket that does not know the type of the module that owns
    00307   //  the callbacks)
    00308   typename callback_binder_fw<TYPES>::nb_func_type    m_nb_f;
    00309   typename callback_binder_fw<TYPES>::b_func_type     m_b_f;
    00310   typename callback_binder_fw<TYPES>::debug_func_type m_dbg_f;
    00311   typename callback_binder_fw<TYPES>::dmi_func_type   m_dmi_f;
    00312 };
    00313
    00314 }
    00315
    00316 #endif