00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef __MULTI_SOCKET_BASES_H__
00019 #define __MULTI_SOCKET_BASES_H__
00020
00021 #include <systemc>
00022
00023 #include "tlm.h"
00024
00025 #include <map>
00026 #include <sstream>
00027
00028 namespace tlm_utils {
00029
00030 template <typename signature>
00031 struct fn_container{
00032 signature function;
00033 };
00034
00035 #define TLM_DEFINE_FUNCTOR(name) \
00036 template <typename MODULE, typename TRAITS> \
00037 inline TLM_RET_VAL static_##name( void* mod \
00038 , void* fn \
00039 , int index \
00040 , TLM_FULL_ARG_LIST) \
00041 { \
00042 typedef fn_container<TLM_RET_VAL (MODULE::*)(int, TLM_FULL_ARG_LIST)> fn_container_type; \
00043 MODULE* tmp_mod=static_cast<MODULE*>(mod); \
00044 fn_container_type* tmp_cb =static_cast<fn_container_type*> (fn); \
00045 return (tmp_mod->*(tmp_cb->function))(index, TLM_ARG_LIST_WITHOUT_TYPES); \
00046 }\
00047 \
00048 template <typename MODULE, typename TRAITS> \
00049 inline void delete_fn_container_of_##name(void* fn) \
00050 { \
00051 typedef fn_container<TLM_RET_VAL (MODULE::*)(int, TLM_FULL_ARG_LIST)> fn_container_type; \
00052 fn_container_type* tmp_cb =static_cast<fn_container_type*> (fn); \
00053 if (tmp_cb) delete tmp_cb;\
00054 } \
00055 \
00056 template <typename TRAITS> \
00057 class name##_functor{ \
00058 public: \
00059 typedef typename TRAITS::tlm_payload_type payload_type; \
00060 typedef typename TRAITS::tlm_phase_type phase_type; \
00061 typedef TLM_RET_VAL (*call_fn)(void*,void*, int, TLM_FULL_ARG_LIST); \
00062 typedef void (*del_fn)(void*); \
00063 \
00064 name##_functor(): m_fn(0), m_del_fn(0), m_mod(0), m_mem_fn(0){} \
00065 ~name##_functor(){if (m_del_fn) (*m_del_fn)(m_mem_fn);} \
00066 \
00067 template <typename MODULE> \
00068 void set_function(MODULE* mod, TLM_RET_VAL (MODULE::*cb)(int, TLM_FULL_ARG_LIST)){ \
00069 typedef fn_container<TLM_RET_VAL (MODULE::*)(int, TLM_FULL_ARG_LIST)> fn_container_type; \
00070 m_fn=&static_##name<MODULE,TRAITS>;\
00071 m_del_fn=&delete_fn_container_of_##name<MODULE,TRAITS>;\
00072 m_del_fn(m_mem_fn); \
00073 fn_container_type* tmp= new fn_container_type(); \
00074 tmp->function=cb; \
00075 m_mod=static_cast<void*>(mod); \
00076 m_mem_fn=static_cast<void*>(tmp); \
00077 } \
00078 \
00079 TLM_RET_VAL operator()(int index, TLM_FULL_ARG_LIST){ \
00080 return m_fn(m_mod,m_mem_fn, index, TLM_ARG_LIST_WITHOUT_TYPES); \
00081 } \
00082 \
00083 bool empty(){return (m_mod==0 || m_mem_fn==0 || m_fn==0);}\
00084 \
00085 protected: \
00086 call_fn m_fn;\
00087 del_fn m_del_fn; \
00088 void* m_mod; \
00089 void* m_mem_fn; \
00090 private: \
00091 name##_functor& operator=(const name##_functor&); \
00092 }
00093
00094
00095 #define TLM_RET_VAL tlm::tlm_sync_enum
00096 #define TLM_FULL_ARG_LIST typename TRAITS::tlm_payload_type& txn, typename TRAITS::tlm_phase_type& ph, sc_core::sc_time& t
00097 #define TLM_ARG_LIST_WITHOUT_TYPES txn,ph,t
00098 TLM_DEFINE_FUNCTOR(nb_transport);
00099 #undef TLM_RET_VAL
00100 #undef TLM_FULL_ARG_LIST
00101 #undef TLM_ARG_LIST_WITHOUT_TYPES
00102
00103 #define TLM_RET_VAL void
00104 #define TLM_FULL_ARG_LIST typename TRAITS::tlm_payload_type& txn, sc_core::sc_time& t
00105 #define TLM_ARG_LIST_WITHOUT_TYPES txn,t
00106 TLM_DEFINE_FUNCTOR(b_transport);
00107 #undef TLM_RET_VAL
00108 #undef TLM_FULL_ARG_LIST
00109 #undef TLM_ARG_LIST_WITHOUT_TYPES
00110
00111 #define TLM_RET_VAL unsigned int
00112 #define TLM_FULL_ARG_LIST typename TRAITS::tlm_payload_type& txn
00113 #define TLM_ARG_LIST_WITHOUT_TYPES txn
00114 TLM_DEFINE_FUNCTOR(debug_transport);
00115 #undef TLM_RET_VAL
00116 #undef TLM_FULL_ARG_LIST
00117 #undef TLM_ARG_LIST_WITHOUT_TYPES
00118
00119 #define TLM_RET_VAL bool
00120 #define TLM_FULL_ARG_LIST typename TRAITS::tlm_payload_type& txn, tlm::tlm_dmi& dmi
00121 #define TLM_ARG_LIST_WITHOUT_TYPES txn,dmi
00122 TLM_DEFINE_FUNCTOR(get_dmi_ptr);
00123 #undef TLM_RET_VAL
00124 #undef TLM_FULL_ARG_LIST
00125 #undef TLM_ARG_LIST_WITHOUT_TYPES
00126
00127 #define TLM_RET_VAL void
00128 #define TLM_FULL_ARG_LIST sc_dt::uint64 l, sc_dt::uint64 u
00129 #define TLM_ARG_LIST_WITHOUT_TYPES l,u
00130 TLM_DEFINE_FUNCTOR(invalidate_dmi);
00131 #undef TLM_RET_VAL
00132 #undef TLM_FULL_ARG_LIST
00133 #undef TLM_ARG_LIST_WITHOUT_TYPES
00134
00135 #undef TLM_DEFINE_FUNCTOR
00136
00137
00138
00139
00140
00141
00142
00143 template <typename TYPES>
00144 class callback_binder_fw: public tlm::tlm_fw_transport_if<TYPES>{
00145 public:
00146
00147 typedef typename TYPES::tlm_payload_type transaction_type;
00148 typedef typename TYPES::tlm_phase_type phase_type;
00149 typedef tlm::tlm_sync_enum sync_enum_type;
00150
00151
00152 typedef nb_transport_functor<TYPES> nb_func_type;
00153 typedef b_transport_functor<TYPES> b_func_type;
00154 typedef debug_transport_functor<TYPES> debug_func_type;
00155 typedef get_dmi_ptr_functor<TYPES> dmi_func_type;
00156
00157
00158 callback_binder_fw(int id): m_id(id){
00159 }
00160
00161
00162 sync_enum_type nb_transport_fw(transaction_type& txn,
00163 phase_type& p,
00164 sc_core::sc_time& t){
00165
00166 if (m_nb_f->empty()){
00167
00168 SC_REPORT_ERROR("/OSCI_TLM-2/multi_socket","Call to nb_transport_fw without a registered callback for nb_transport_fw.");
00169 }
00170 else
00171 return (*m_nb_f)(m_id, txn, p, t);
00172 return tlm::TLM_ACCEPTED;
00173 }
00174
00175
00176 void b_transport(transaction_type& trans,sc_core::sc_time& t){
00177
00178 if (m_b_f->empty()){
00179 SC_REPORT_ERROR("/OSCI_TLM-2/multi_socket","Call to b_transport without a registered callback for b_transport.");
00180 }
00181 else
00182 (*m_b_f)(m_id, trans,t);
00183 }
00184
00185
00186 bool get_direct_mem_ptr(transaction_type& trans, tlm::tlm_dmi& dmi_data){
00187
00188 if (m_dmi_f->empty()){
00189 dmi_data.allow_none();
00190 dmi_data.set_start_address(0x0);
00191 dmi_data.set_end_address((sc_dt::uint64)-1);
00192 return false;
00193 }
00194 else
00195 return (*m_dmi_f)(m_id, trans,dmi_data);
00196 }
00197
00198
00199 unsigned int transport_dbg(transaction_type& trans){
00200
00201 if (m_dbg_f->empty()){
00202 return 0;
00203 }
00204 else
00205 return (*m_dbg_f)(m_id, trans);
00206 }
00207
00208
00209
00210
00211 void register_port(sc_core::sc_port_base& b, const char* name){
00212 m_caller_port=&b;
00213 }
00214
00215
00216 void set_callbacks(nb_func_type& cb1, b_func_type& cb2, dmi_func_type& cb3, debug_func_type& cb4){
00217 m_nb_f=&cb1;
00218 m_b_f=&cb2;
00219 m_dmi_f=&cb3;
00220 m_dbg_f=&cb4;
00221 }
00222
00223
00224
00225
00226 sc_core::sc_port_base* get_other_side(){return m_caller_port;}
00227
00228 private:
00229
00230 int m_id;
00231
00232
00233 nb_func_type* m_nb_f;
00234 b_func_type* m_b_f;
00235 debug_func_type* m_dbg_f;
00236 dmi_func_type* m_dmi_f;
00237
00238
00239 sc_core::sc_port_base* m_caller_port;
00240 };
00241
00242
00243
00244
00245
00246
00247
00248 template <typename TYPES>
00249 class callback_binder_bw: public tlm::tlm_bw_transport_if<TYPES>{
00250 public:
00251
00252 typedef typename TYPES::tlm_payload_type transaction_type;
00253 typedef typename TYPES::tlm_phase_type phase_type;
00254 typedef tlm::tlm_sync_enum sync_enum_type;
00255
00256
00257 typedef nb_transport_functor<TYPES> nb_func_type;
00258 typedef invalidate_dmi_functor<TYPES> dmi_func_type;
00259
00260
00261 callback_binder_bw(int id): m_id(id){
00262 }
00263
00264
00265 sync_enum_type nb_transport_bw(transaction_type& txn,
00266 phase_type& p,
00267 sc_core::sc_time& t){
00268
00269 if (m_nb_f->empty()){
00270 SC_REPORT_ERROR("/OSCI_TLM-2/multi_socket","Call to nb_transport_bw without a registered callback for nb_transport_bw");
00271 }
00272 else
00273 return (*m_nb_f)(m_id, txn, p, t);
00274 return tlm::TLM_ACCEPTED;
00275 }
00276
00277
00278 void invalidate_direct_mem_ptr(sc_dt::uint64 l, sc_dt::uint64 u){
00279
00280 if (m_dmi_f->empty()){
00281 return;
00282 }
00283 else
00284 (*m_dmi_f)(m_id,l,u);
00285 }
00286
00287
00288 void set_callbacks(nb_func_type& cb1, dmi_func_type& cb2){
00289 m_nb_f=&cb1;
00290 m_dmi_f=&cb2;
00291 }
00292
00293 private:
00294
00295 int m_id;
00296
00297 nb_func_type* m_nb_f;
00298 dmi_func_type* m_dmi_f;
00299 };
00300
00301
00302
00303
00304
00305
00306
00307 template <unsigned int BUSWIDTH = 32,
00308 typename TYPES = tlm::tlm_base_protocol_types,
00309 unsigned int N=0
00310 #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
00311 ,sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND
00312 #endif
00313 >
00314 class multi_init_base: public tlm::tlm_initiator_socket<BUSWIDTH,
00315 TYPES,
00316 N
00317 #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
00318 ,POL
00319 #endif
00320 >{
00321 public:
00322
00323 typedef tlm::tlm_initiator_socket<BUSWIDTH,
00324 TYPES,
00325 N
00326 #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
00327 ,POL
00328 #endif
00329 > base_type;
00330
00331
00332
00333 virtual void disable_cb_bind()=0;
00334
00335
00336
00337
00338 virtual multi_init_base* get_hierarch_bind()=0;
00339
00340
00341 virtual std::vector<callback_binder_bw<TYPES>* >& get_binders()=0;
00342
00343
00344 virtual std::vector<tlm::tlm_fw_transport_if<TYPES>*>& get_sockets()=0;
00345
00346
00347 virtual ~multi_init_base(){}
00348 multi_init_base():base_type(sc_core::sc_gen_unique_name("multi_init_base")){}
00349 multi_init_base(const char* name):base_type(name){}
00350 };
00351
00352
00353
00354
00355
00356
00357 template <unsigned int BUSWIDTH = 32,
00358 typename TYPES = tlm::tlm_base_protocol_types,
00359 unsigned int N=0
00360 #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
00361 ,sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND
00362 #endif
00363 >
00364 class multi_target_base: public tlm::tlm_target_socket<BUSWIDTH,
00365 TYPES,
00366 N
00367 #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
00368 ,POL
00369 #endif
00370 >{
00371 public:
00372
00373 typedef tlm::tlm_target_socket<BUSWIDTH,
00374 TYPES,
00375 N
00376 #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
00377 ,POL
00378 #endif
00379 > base_type;
00380
00381
00382
00383
00384 virtual multi_target_base* get_hierarch_bind()=0;
00385
00386
00387
00388 virtual void set_hierarch_bind(multi_target_base*)=0;
00389
00390
00391 virtual std::vector<callback_binder_fw<TYPES>* >& get_binders()=0;
00392
00393
00394
00395
00396 virtual std::map<unsigned int, tlm::tlm_bw_transport_if<TYPES>*>& get_multi_binds()=0;
00397
00398
00399 virtual ~multi_target_base(){}
00400 multi_target_base():base_type(sc_core::sc_gen_unique_name("multi_target_base")){}
00401 multi_target_base(const char* name):base_type(name){}
00402 };
00403
00404
00405
00406
00407
00408
00409 template <typename TYPES>
00410 class multi_to_multi_bind_base{
00411 public:
00412 virtual ~multi_to_multi_bind_base(){}
00413 virtual tlm::tlm_fw_transport_if<TYPES>* get_last_binder(tlm::tlm_bw_transport_if<TYPES>*)=0;
00414 };
00415
00416 }
00417 #endif