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