multi_socket_bases.h revision 13511:dc5864c73df3
1/***************************************************************************** 2 3 Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 4 more contributor license agreements. See the NOTICE file distributed 5 with this work for additional information regarding copyright ownership. 6 Accellera licenses this file to you under the Apache License, Version 2.0 7 (the "License"); you may not use this file except in compliance with the 8 License. You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12 Unless required by applicable law or agreed to in writing, software 13 distributed under the License is distributed on an "AS IS" BASIS, 14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 15 implied. See the License for the specific language governing 16 permissions and limitations under the License. 17 18 *****************************************************************************/ 19 20#ifndef TLM_UTILS_MULTI_SOCKET_BASES_H_INCLUDED_ 21#define TLM_UTILS_MULTI_SOCKET_BASES_H_INCLUDED_ 22 23#include <tlm> 24#include "tlm_utils/convenience_socket_bases.h" 25 26#include <map> 27 28namespace tlm_utils { 29 30template <typename signature> 31struct fn_container{ 32 signature function; 33}; 34 35#define TLM_DEFINE_FUNCTOR(name) \ 36template <typename MODULE, typename TRAITS> \ 37inline TLM_RET_VAL static_##name( void* mod \ 38 , void* fn \ 39 , int index \ 40 , TLM_FULL_ARG_LIST) \ 41{ \ 42 typedef fn_container<TLM_RET_VAL (MODULE::*)(int, TLM_FULL_ARG_LIST)> fn_container_type; \ 43 MODULE* tmp_mod=static_cast<MODULE*>(mod); \ 44 fn_container_type* tmp_cb =static_cast<fn_container_type*> (fn); \ 45 return (tmp_mod->*(tmp_cb->function))(index, TLM_ARG_LIST_WITHOUT_TYPES); \ 46}\ 47\ 48template <typename MODULE, typename TRAITS> \ 49inline void delete_fn_container_of_##name(void* fn) \ 50{ \ 51 typedef fn_container<TLM_RET_VAL (MODULE::*)(int, TLM_FULL_ARG_LIST)> fn_container_type; \ 52 fn_container_type* tmp_cb =static_cast<fn_container_type*> (fn); \ 53 if (tmp_cb) delete tmp_cb;\ 54} \ 55\ 56template <typename TRAITS> \ 57class name##_functor{ \ 58public: \ 59 typedef typename TRAITS::tlm_payload_type payload_type; \ 60 typedef typename TRAITS::tlm_phase_type phase_type; \ 61 typedef TLM_RET_VAL (*call_fn)(void*,void*, int, TLM_FULL_ARG_LIST); \ 62 typedef void (*del_fn)(void*); \ 63\ 64 name##_functor(): m_fn(0), m_del_fn(0), m_mod(0), m_mem_fn(0){} \ 65 ~name##_functor(){if (m_del_fn) (*m_del_fn)(m_mem_fn);} \ 66\ 67 template <typename MODULE> \ 68 void set_function(MODULE* mod, TLM_RET_VAL (MODULE::*cb)(int, TLM_FULL_ARG_LIST)){ \ 69 typedef fn_container<TLM_RET_VAL (MODULE::*)(int, TLM_FULL_ARG_LIST)> fn_container_type; \ 70 m_fn=&static_##name<MODULE,TRAITS>;\ 71 m_del_fn=&delete_fn_container_of_##name<MODULE,TRAITS>;\ 72 m_del_fn(m_mem_fn); \ 73 fn_container_type* tmp= new fn_container_type(); \ 74 tmp->function=cb; \ 75 m_mod=static_cast<void*>(mod); \ 76 m_mem_fn=static_cast<void*>(tmp); \ 77 } \ 78 \ 79 TLM_RET_VAL operator()(int index, TLM_FULL_ARG_LIST){ \ 80 return m_fn(m_mod,m_mem_fn, index, TLM_ARG_LIST_WITHOUT_TYPES); \ 81 } \ 82\ 83 bool is_valid(){return (m_mod!=0 && m_mem_fn!=0 && m_fn!=0);}\ 84\ 85protected: \ 86 call_fn m_fn;\ 87 del_fn m_del_fn; \ 88 void* m_mod; \ 89 void* m_mem_fn; \ 90private: \ 91 name##_functor& operator=(const name##_functor&); \ 92} 93 94 95#define TLM_RET_VAL tlm::tlm_sync_enum 96#define TLM_FULL_ARG_LIST typename TRAITS::tlm_payload_type& txn, typename TRAITS::tlm_phase_type& ph, sc_core::sc_time& t 97#define TLM_ARG_LIST_WITHOUT_TYPES txn,ph,t 98TLM_DEFINE_FUNCTOR(nb_transport); 99#undef TLM_RET_VAL 100#undef TLM_FULL_ARG_LIST 101#undef TLM_ARG_LIST_WITHOUT_TYPES 102 103#define TLM_RET_VAL void 104#define TLM_FULL_ARG_LIST typename TRAITS::tlm_payload_type& txn, sc_core::sc_time& t 105#define TLM_ARG_LIST_WITHOUT_TYPES txn,t 106TLM_DEFINE_FUNCTOR(b_transport); 107#undef TLM_RET_VAL 108#undef TLM_FULL_ARG_LIST 109#undef TLM_ARG_LIST_WITHOUT_TYPES 110 111#define TLM_RET_VAL unsigned int 112#define TLM_FULL_ARG_LIST typename TRAITS::tlm_payload_type& txn 113#define TLM_ARG_LIST_WITHOUT_TYPES txn 114TLM_DEFINE_FUNCTOR(debug_transport); 115#undef TLM_RET_VAL 116#undef TLM_FULL_ARG_LIST 117#undef TLM_ARG_LIST_WITHOUT_TYPES 118 119#define TLM_RET_VAL bool 120#define TLM_FULL_ARG_LIST typename TRAITS::tlm_payload_type& txn, tlm::tlm_dmi& dmi 121#define TLM_ARG_LIST_WITHOUT_TYPES txn,dmi 122TLM_DEFINE_FUNCTOR(get_dmi_ptr); 123#undef TLM_RET_VAL 124#undef TLM_FULL_ARG_LIST 125#undef TLM_ARG_LIST_WITHOUT_TYPES 126 127#define TLM_RET_VAL void 128#define TLM_FULL_ARG_LIST sc_dt::uint64 l, sc_dt::uint64 u 129#define TLM_ARG_LIST_WITHOUT_TYPES l,u 130TLM_DEFINE_FUNCTOR(invalidate_dmi); 131#undef TLM_RET_VAL 132#undef TLM_FULL_ARG_LIST 133#undef TLM_ARG_LIST_WITHOUT_TYPES 134 135#undef TLM_DEFINE_FUNCTOR 136 137/* 138This class implements the fw interface. 139It allows to register a callback for each of the fw interface methods. 140The callbacks simply forward the fw interface call, but add the id (an int) 141of the callback binder to the signature of the call. 142*/ 143template <typename TYPES> 144class callback_binder_fw 145 : public tlm::tlm_fw_transport_if<TYPES> 146 , protected convenience_socket_cb_holder 147{ 148 public: 149 //typedefs according to the used TYPES class 150 typedef typename TYPES::tlm_payload_type transaction_type; 151 typedef typename TYPES::tlm_phase_type phase_type; 152 typedef tlm::tlm_sync_enum sync_enum_type; 153 154 //typedefs for the callbacks 155 typedef nb_transport_functor<TYPES> nb_func_type; 156 typedef b_transport_functor<TYPES> b_func_type; 157 typedef debug_transport_functor<TYPES> debug_func_type; 158 typedef get_dmi_ptr_functor<TYPES> dmi_func_type; 159 160 //ctor: an ID is needed to create a callback binder 161 callback_binder_fw(multi_socket_base* owner, int id) 162 : convenience_socket_cb_holder(owner), m_id(id) 163 , m_nb_f(0), m_b_f(0), m_dbg_f(0), m_dmi_f(0) 164 , m_caller_port(0) 165 {} 166 167 //the nb_transport method of the fw interface 168 sync_enum_type nb_transport_fw(transaction_type& txn, 169 phase_type& p, 170 sc_core::sc_time& t){ 171 //check if a callback is registered 172 if (m_nb_f && m_nb_f->is_valid()) { 173 return (*m_nb_f)(m_id, txn, p, t); //do the callback 174 } 175 176 display_error("Call to nb_transport_fw without a registered callback for nb_transport_fw."); 177 return tlm::TLM_COMPLETED; 178 } 179 180 //the b_transport method of the fw interface 181 void b_transport(transaction_type& trans,sc_core::sc_time& t){ 182 //check if a callback is registered 183 if (m_b_f && m_b_f->is_valid()) { 184 (*m_b_f)(m_id, trans,t); //do the callback 185 return; 186 } 187 188 display_error("Call to b_transport without a registered callback for b_transport."); 189 } 190 191 //the DMI method of the fw interface 192 bool get_direct_mem_ptr(transaction_type& trans, tlm::tlm_dmi& dmi_data){ 193 //check if a callback is registered 194 if (m_dmi_f && m_dmi_f->is_valid()) { 195 return (*m_dmi_f)(m_id, trans,dmi_data); //do the callback 196 } 197 198 dmi_data.allow_none(); 199 dmi_data.set_start_address(0x0); 200 dmi_data.set_end_address((sc_dt::uint64)-1); 201 return false; 202 } 203 204 //the debug method of the fw interface 205 unsigned int transport_dbg(transaction_type& trans){ 206 //check if a callback is registered 207 if (m_dbg_f && m_dbg_f->is_valid()) { 208 return (*m_dbg_f)(m_id, trans); //do the callback 209 } 210 211 return 0; 212 } 213 214 //the SystemC standard callback register_port: 215 // - called when a port if bound to the interface 216 // - allowd to find out who is bound to that callback binder 217 void register_port(sc_core::sc_port_base& b, const char* /*name*/){ 218 m_caller_port=&b; 219 } 220 221 //register callbacks for all fw interface methods at once 222 void set_callbacks(nb_func_type& cb1, b_func_type& cb2, dmi_func_type& cb3, debug_func_type& cb4){ 223 m_nb_f=&cb1; 224 m_b_f=&cb2; 225 m_dmi_f=&cb3; 226 m_dbg_f=&cb4; 227 } 228 229 //getter method to get the port that is bound to that callback binder 230 // NOTE: this will only return a valid value at end of elaboration 231 // (but not before end of elaboration!) 232 sc_core::sc_port_base* get_other_side(){return m_caller_port;} 233 234 private: 235 //the ID of the callback binder 236 int m_id; 237 238 //the callbacks 239 nb_func_type* m_nb_f; 240 b_func_type* m_b_f; 241 debug_func_type* m_dbg_f; 242 dmi_func_type* m_dmi_f; 243 244 //the port bound to that callback binder 245 sc_core::sc_port_base* m_caller_port; 246}; 247 248/* 249This class implements the bw interface. 250It allows to register a callback for each of the bw interface methods. 251The callbacks simply forward the bw interface call, but add the id (an int) 252of the callback binder to the signature of the call. 253*/ 254template <typename TYPES> 255class callback_binder_bw 256 : public tlm::tlm_bw_transport_if<TYPES> 257 , protected convenience_socket_cb_holder 258{ 259 public: 260 //typedefs according to the used TYPES class 261 typedef typename TYPES::tlm_payload_type transaction_type; 262 typedef typename TYPES::tlm_phase_type phase_type; 263 typedef tlm::tlm_sync_enum sync_enum_type; 264 265 //typedefs for the callbacks 266 typedef nb_transport_functor<TYPES> nb_func_type; 267 typedef invalidate_dmi_functor<TYPES> dmi_func_type; 268 269 //ctor: an ID is needed to create a callback binder 270 callback_binder_bw(multi_socket_base* owner, int id) 271 : convenience_socket_cb_holder(owner), m_id(id) 272 , m_nb_f(0), m_dmi_f(0) {} 273 274 //the nb_transport method of the bw interface 275 sync_enum_type nb_transport_bw(transaction_type& txn, 276 phase_type& p, 277 sc_core::sc_time& t){ 278 //check if a callback is registered 279 if (m_nb_f && m_nb_f->is_valid()) { 280 return (*m_nb_f)(m_id, txn, p, t); //do the callback 281 } 282 283 display_error("Call to nb_transport_bw without a registered callback for nb_transport_bw"); 284 return tlm::TLM_COMPLETED; 285 } 286 287 //the DMI method of the bw interface 288 void invalidate_direct_mem_ptr(sc_dt::uint64 l, sc_dt::uint64 u){ 289 //check if a callback is registered 290 if (m_dmi_f && m_dmi_f->is_valid()) { 291 (*m_dmi_f)(m_id,l,u); //do the callback 292 } 293 } 294 295 //register callbacks for all bw interface methods at once 296 void set_callbacks(nb_func_type& cb1, dmi_func_type& cb2){ 297 m_nb_f=&cb1; 298 m_dmi_f=&cb2; 299 } 300 301 private: 302 //the ID of the callback binder 303 int m_id; 304 //the callbacks 305 nb_func_type* m_nb_f; 306 dmi_func_type* m_dmi_f; 307}; 308 309/* 310This class forms the base for multi initiator sockets, 311with fewer template parameters than the multi_init_base. 312This class is implementation-defined. 313*/ 314template <typename TYPES = tlm::tlm_base_protocol_types> 315class multi_init_base_if { 316public: 317 //this method shall return a vector of the callback binders of multi initiator socket 318 virtual std::vector<callback_binder_bw<TYPES>* >& get_binders()=0; 319 //this method shall return a vector of all target interfaces bound to this multi init socket 320 virtual std::vector<tlm::tlm_fw_transport_if<TYPES>*>& get_sockets()=0; 321protected: 322 virtual ~multi_init_base_if() {} 323}; 324 325/* 326This class forms the base for multi initiator sockets. 327It enforces a multi initiator socket to implement all functions 328needed to do hierarchical bindings. 329*/ 330template <unsigned int BUSWIDTH = 32, 331 typename TYPES = tlm::tlm_base_protocol_types, 332 unsigned int N=0, 333 sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND> 334class multi_init_base 335 : public tlm::tlm_initiator_socket<BUSWIDTH, TYPES, N, POL> 336 , public multi_init_base_if<TYPES> 337 , protected multi_socket_base 338{ 339public: 340 //typedef for the base type: the standard tlm initiator socket 341 typedef tlm::tlm_initiator_socket<BUSWIDTH, TYPES, N, POL> base_type; 342 343 //this method shall disable the code that does the callback binding 344 // that registers callbacks to binders 345 virtual void disable_cb_bind()=0; 346 347 //this method shall return the multi_init_base to which the 348 // multi_init_base is bound hierarchically 349 // If the base is not bound hierarchically it shall return a pointer to itself 350 virtual multi_init_base* get_hierarch_bind()=0; 351 352 virtual tlm::tlm_socket_category get_socket_category() const 353 { 354 return tlm::TLM_MULTI_INITIATOR_SOCKET; 355 } 356 357 //ctor and dtor 358 virtual ~multi_init_base(){} 359 multi_init_base():base_type(sc_core::sc_gen_unique_name("multi_init_base")){} 360 multi_init_base(const char* name):base_type(name){} 361 362private: 363 const sc_core::sc_object* get_socket() const { return this; } 364}; 365 366/* 367This class forms the base for multi target sockets, 368with fewer template parameters than the multi_target_base. 369This class is implementation-defined. 370*/ 371template <typename TYPES = tlm::tlm_base_protocol_types> 372class multi_target_base_if { 373public: 374 //this method shall return a vector of the callback binders of multi initiator socket 375 virtual std::vector<callback_binder_fw<TYPES>* >& get_binders()=0; 376 377 //this method shall return a map of all multi initiator sockets that are 378 // bound to this multi target the key of the map is the index at which the 379 // multi initiator i bound, while the value is the interface of the multi 380 // initiator socket that is bound at that index 381 virtual std::map<unsigned int, tlm::tlm_bw_transport_if<TYPES>*>& get_multi_binds()=0; 382protected: 383 virtual ~multi_target_base_if() {} 384}; 385 386/* 387This class forms the base for multi target sockets. 388It enforces a multi target socket to implement all functions 389needed to do hierarchical bindings. 390*/ 391template <unsigned int BUSWIDTH = 32, 392 typename TYPES = tlm::tlm_base_protocol_types, 393 unsigned int N=0, 394 sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND> 395class multi_target_base 396 : public tlm::tlm_target_socket<BUSWIDTH, TYPES, N, POL> 397 , public multi_target_base_if<TYPES> 398 , protected multi_socket_base 399{ 400public: 401 //typedef for the base type: the standard tlm target socket 402 typedef tlm::tlm_target_socket<BUSWIDTH, TYPES, N, POL > base_type; 403 404 //this method shall return the multi_init_base to which the 405 // multi_init_base is bound hierarchically 406 // If the base is not bound hierarchically it shall return a pointer to itself 407 virtual multi_target_base* get_hierarch_bind()=0; 408 409 //this method shall inform the multi target socket that it is bound 410 // hierarchically and to which other multi target socket it is bound hierarchically 411 virtual void set_hierarch_bind(multi_target_base*)=0; 412 413 virtual tlm::tlm_socket_category get_socket_category() const 414 { 415 return tlm::TLM_MULTI_TARGET_SOCKET; 416 } 417 418 //ctor and dtor 419 virtual ~multi_target_base(){} 420 multi_target_base():base_type(sc_core::sc_gen_unique_name("multi_target_base")){} 421 multi_target_base(const char* name):base_type(name){} 422 423private: 424 const sc_core::sc_object* get_socket() const { return this; } 425}; 426 427/* 428All multi sockets must additionally derive from this class. 429It enforces a multi socket to implement a function 430needed to do multi init to multi target bindings. 431*/ 432template <typename TYPES> 433class multi_to_multi_bind_base{ 434public: 435 virtual ~multi_to_multi_bind_base(){} 436 virtual tlm::tlm_fw_transport_if<TYPES>* get_last_binder(tlm::tlm_bw_transport_if<TYPES>*)=0; 437}; 438 439} // namespace tlm_utils 440#endif // TLM_UTILS_MULTI_SOCKET_BASES_H_INCLUDED_ 441