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 __SYSTEMC_EXT_TLM_UTILS_PASSTHROUGH_TARGET_SOCKET_H__ 21#define __SYSTEMC_EXT_TLM_UTILS_PASSTHROUGH_TARGET_SOCKET_H__ 22 23#include "../core/sc_port.hh" 24#include "../core/sc_time.hh" 25#include "../tlm_core/2/sockets/target_socket.hh" 26#include "../utils/sc_report_handler.hh" 27#include "convenience_socket_bases.h" 28 29namespace tlm_utils 30{ 31 32template <typename MODULE, unsigned int BUSWIDTH, typename TYPES, 33 sc_core::sc_port_policy POL=sc_core::SC_ONE_OR_MORE_BOUND> 34class passthrough_target_socket_b : 35 public tlm::tlm_target_socket<BUSWIDTH, TYPES, 1, POL>, 36 protected passthrough_socket_base 37{ 38 public: 39 typedef typename TYPES::tlm_payload_type transaction_type; 40 typedef typename TYPES::tlm_phase_type phase_type; 41 typedef tlm::tlm_sync_enum sync_enum_type; 42 typedef tlm::tlm_fw_transport_if<TYPES> fw_interface_type; 43 typedef tlm::tlm_bw_transport_if<TYPES> bw_interface_type; 44 typedef tlm::tlm_target_socket<BUSWIDTH,TYPES,1,POL> base_type; 45 46 public: 47 static const char * 48 default_name() 49 { 50 return sc_core::sc_gen_unique_name("passthrough_target_socket"); 51 } 52 53 explicit passthrough_target_socket_b(const char *n=default_name()) : 54 base_type(n), m_process(this) 55 { 56 bind(m_process); 57 } 58 59 using base_type::bind; 60 61 // REGISTER_XXX 62 void 63 register_nb_transport_fw(MODULE *mod, 64 sync_enum_type (MODULE::*cb)(transaction_type &, phase_type &, 65 sc_core::sc_time &)) 66 { 67 m_process.set_nb_transport_ptr(mod, cb); 68 } 69 70 void 71 register_b_transport(MODULE *mod, 72 void (MODULE::*cb)(transaction_type &, sc_core::sc_time &)) 73 { 74 m_process.set_b_transport_ptr(mod, cb); 75 } 76 77 void 78 register_transport_dbg(MODULE *mod, 79 unsigned int (MODULE::*cb)(transaction_type &)) 80 { 81 m_process.set_transport_dbg_ptr(mod, cb); 82 } 83 84 void 85 register_get_direct_mem_ptr(MODULE *mod, 86 bool (MODULE::*cb)(transaction_type &, tlm::tlm_dmi &)) 87 { 88 m_process.set_get_direct_mem_ptr(mod, cb); 89 } 90 91 private: 92 class process : public tlm::tlm_fw_transport_if<TYPES>, 93 protected convenience_socket_cb_holder 94 { 95 public: 96 typedef sync_enum_type (MODULE::*NBTransportPtr)( 97 transaction_type &, phase_type &, sc_core::sc_time &); 98 typedef void (MODULE::*BTransportPtr)( 99 transaction_type &, sc_core::sc_time &); 100 typedef unsigned int (MODULE::*TransportDbgPtr)(transaction_type &); 101 typedef bool (MODULE::*GetDirectMem_ptr)( 102 transaction_type &, tlm::tlm_dmi &); 103 104 explicit process(passthrough_socket_base *owner) : 105 convenience_socket_cb_holder(owner), m_mod(0), 106 m_nb_transport_ptr(0), m_b_transport_ptr(0), 107 m_transport_dbg_ptr(0), m_get_direct_mem_ptr(0) 108 {} 109 110 void 111 set_nb_transport_ptr(MODULE *mod, NBTransportPtr p) 112 { 113 if (m_nb_transport_ptr) { 114 display_warning("non-blocking callback already registered"); 115 return; 116 } 117 sc_assert(!m_mod || m_mod == mod); 118 m_mod = mod; 119 m_nb_transport_ptr = p; 120 } 121 122 void 123 set_b_transport_ptr(MODULE *mod, BTransportPtr p) 124 { 125 if (m_b_transport_ptr) { 126 display_warning("blocking callback already registered"); 127 return; 128 } 129 sc_assert(!m_mod || m_mod == mod); 130 m_mod = mod; 131 m_b_transport_ptr = p; 132 } 133 134 void 135 set_transport_dbg_ptr(MODULE *mod, TransportDbgPtr p) 136 { 137 if (m_transport_dbg_ptr) { 138 display_warning("debug callback already registered"); 139 return; 140 } 141 sc_assert(!m_mod || m_mod == mod); 142 m_mod = mod; 143 m_transport_dbg_ptr = p; 144 } 145 146 void 147 set_get_direct_mem_ptr(MODULE *mod, GetDirectMem_ptr p) 148 { 149 if (m_get_direct_mem_ptr) { 150 display_warning( 151 "get DMI pointer callback already registered"); 152 return; 153 } 154 sc_assert(!m_mod || m_mod == mod); 155 m_mod = mod; 156 m_get_direct_mem_ptr = p; 157 } 158 159 sync_enum_type nb_transport_fw( 160 transaction_type &trans, phase_type &phase, 161 sc_core::sc_time &t) 162 { 163 if (m_nb_transport_ptr) { 164 // Forward call. 165 sc_assert(m_mod); 166 return (m_mod->*m_nb_transport_ptr)(trans, phase, t); 167 } 168 display_error("no non-blocking callback registered"); 169 return tlm::TLM_COMPLETED; 170 } 171 172 void 173 b_transport(transaction_type &trans, sc_core::sc_time &t) 174 { 175 if (m_b_transport_ptr) { 176 // Forward call. 177 sc_assert(m_mod); 178 return (m_mod->*m_b_transport_ptr)(trans, t); 179 } 180 display_error("no blocking callback registered"); 181 } 182 183 unsigned int 184 transport_dbg(transaction_type &trans) 185 { 186 if (m_transport_dbg_ptr) { 187 // Forward call. 188 sc_assert(m_mod); 189 return (m_mod->*m_transport_dbg_ptr)(trans); 190 } 191 // No debug support 192 return 0; 193 } 194 195 bool 196 get_direct_mem_ptr(transaction_type &trans, tlm::tlm_dmi &dmi_data) 197 { 198 if (m_get_direct_mem_ptr) { 199 // Forward call. 200 sc_assert(m_mod); 201 return (m_mod->*m_get_direct_mem_ptr)(trans, dmi_data); 202 } 203 // No DMI support 204 dmi_data.allow_read_write(); 205 dmi_data.set_start_address(0x0); 206 dmi_data.set_end_address((sc_dt::uint64)-1); 207 return false; 208 } 209 210 private: 211 MODULE *m_mod; 212 NBTransportPtr m_nb_transport_ptr; 213 BTransportPtr m_b_transport_ptr; 214 TransportDbgPtr m_transport_dbg_ptr; 215 GetDirectMem_ptr m_get_direct_mem_ptr; 216 }; 217 218 private: 219 const sc_core::sc_object *get_socket() const { return this; } 220 221 private: 222 process m_process; 223}; 224 225template <typename MODULE, unsigned int BUSWIDTH=32, 226 typename TYPES=tlm::tlm_base_protocol_types> 227class passthrough_target_socket : 228 public passthrough_target_socket_b<MODULE, BUSWIDTH, TYPES> 229{ 230 typedef passthrough_target_socket_b<MODULE, BUSWIDTH, TYPES> socket_b; 231 public: 232 passthrough_target_socket() : socket_b() {} 233 explicit passthrough_target_socket(const char *name) : socket_b(name) {} 234}; 235 236template <typename MODULE, unsigned int BUSWIDTH=32, 237 typename TYPES=tlm::tlm_base_protocol_types> 238class passthrough_target_socket_optional : 239 public passthrough_target_socket_b< 240 MODULE, BUSWIDTH, TYPES, sc_core::SC_ZERO_OR_MORE_BOUND> 241{ 242 typedef passthrough_target_socket_b< 243 MODULE, BUSWIDTH, TYPES, sc_core::SC_ZERO_OR_MORE_BOUND> socket_b; 244 public: 245 passthrough_target_socket_optional() : socket_b() {} 246 explicit passthrough_target_socket_optional(const char *name) : 247 socket_b(name) {} 248}; 249 250// ID Tagged version 251template <typename MODULE, unsigned int BUSWIDTH, typename TYPES, 252 sc_core::sc_port_policy POL=sc_core::SC_ONE_OR_MORE_BOUND> 253class passthrough_target_socket_tagged_b : 254 public tlm::tlm_target_socket<BUSWIDTH, TYPES, 1, POL>, 255 protected passthrough_socket_base 256{ 257 public: 258 typedef typename TYPES::tlm_payload_type transaction_type; 259 typedef typename TYPES::tlm_phase_type phase_type; 260 typedef tlm::tlm_sync_enum sync_enum_type; 261 typedef tlm::tlm_fw_transport_if<TYPES> fw_interface_type; 262 typedef tlm::tlm_bw_transport_if<TYPES> bw_interface_type; 263 typedef tlm::tlm_target_socket<BUSWIDTH, TYPES, 1, POL> base_type; 264 265 static const char * 266 default_name() 267 { 268 return sc_core::sc_gen_unique_name( 269 "passthrough_target_socket_tagged"); 270 } 271 272 public: 273 explicit passthrough_target_socket_tagged_b( 274 const char *n=default_name()) : base_type(n), m_process(this) 275 { 276 bind(m_process); 277 } 278 279 using base_type::bind; 280 281 // REGISTER_XXX 282 void 283 register_nb_transport_fw(MODULE *mod, 284 sync_enum_type (MODULE::*cb)(int id, transaction_type &, 285 phase_type &, sc_core::sc_time &), 286 int id) 287 { 288 m_process.set_nb_transport_ptr(mod, cb); 289 m_process.set_nb_transport_user_id(id); 290 } 291 292 void 293 register_b_transport(MODULE *mod, 294 void (MODULE::*cb)(int id, transaction_type &, 295 sc_core::sc_time &), 296 int id) 297 { 298 m_process.set_b_transport_ptr(mod, cb); 299 m_process.set_b_transport_user_id(id); 300 } 301 302 void 303 register_transport_dbg(MODULE *mod, 304 unsigned int (MODULE::*cb)(int id, transaction_type &), int id) 305 { 306 m_process.set_transport_dbg_ptr(mod, cb); 307 m_process.set_transport_dbg_user_id(id); 308 } 309 310 void 311 register_get_direct_mem_ptr(MODULE *mod, 312 bool (MODULE::*cb)(int id, transaction_type &, tlm::tlm_dmi &), 313 int id) 314 { 315 m_process.set_get_direct_mem_ptr(mod, cb); 316 m_process.set_get_dmi_user_id(id); 317 } 318 319 private: 320 class process : public tlm::tlm_fw_transport_if<TYPES>, 321 protected convenience_socket_cb_holder 322 { 323 public: 324 typedef sync_enum_type (MODULE::*NBTransportPtr)( 325 int id, transaction_type &, phase_type &, sc_core::sc_time &); 326 typedef void (MODULE::*BTransportPtr)( 327 int id, transaction_type &, sc_core::sc_time &); 328 typedef unsigned int (MODULE::*TransportDbgPtr)( 329 int id, transaction_type &); 330 typedef bool (MODULE::*GetDirectMem_ptr)( 331 int id, transaction_type &, tlm::tlm_dmi &); 332 333 process(passthrough_socket_base *owner) : 334 convenience_socket_cb_holder(owner), m_mod(0), 335 m_nb_transport_ptr(0), m_b_transport_ptr(0), 336 m_transport_dbg_ptr(0), m_get_direct_mem_ptr(0), 337 m_nb_transport_user_id(0), m_b_transport_user_id(0), 338 m_transport_dbg_user_id(0), m_get_dmi_user_id(0) 339 {} 340 341 void 342 set_nb_transport_user_id(int id) 343 { 344 m_nb_transport_user_id = id; 345 } 346 void 347 set_b_transport_user_id(int id) 348 { 349 m_b_transport_user_id = id; 350 } 351 void 352 set_transport_dbg_user_id(int id) 353 { 354 m_transport_dbg_user_id = id; 355 } 356 void 357 set_get_dmi_user_id(int id) 358 { 359 m_get_dmi_user_id = id; 360 } 361 362 void 363 set_nb_transport_ptr(MODULE *mod, NBTransportPtr p) 364 { 365 if (m_nb_transport_ptr) { 366 display_warning("non-blocking callback already registered"); 367 return; 368 } 369 sc_assert(!m_mod || m_mod == mod); 370 m_mod = mod; 371 m_nb_transport_ptr = p; 372 } 373 374 void 375 set_b_transport_ptr(MODULE *mod, BTransportPtr p) 376 { 377 if (m_b_transport_ptr) { 378 display_warning("blocking callback already registered"); 379 return; 380 } 381 sc_assert(!m_mod || m_mod == mod); 382 m_mod = mod; 383 m_b_transport_ptr = p; 384 } 385 386 void 387 set_transport_dbg_ptr(MODULE *mod, TransportDbgPtr p) 388 { 389 if (m_transport_dbg_ptr) { 390 display_warning("debug callback already registered"); 391 return; 392 } 393 sc_assert(!m_mod || m_mod == mod); 394 m_mod = mod; 395 m_transport_dbg_ptr = p; 396 } 397 398 void 399 set_get_direct_mem_ptr(MODULE *mod, GetDirectMem_ptr p) 400 { 401 if (m_get_direct_mem_ptr) { 402 display_warning( 403 "get DMI pointer callback already registered"); 404 return; 405 } 406 sc_assert(!m_mod || m_mod == mod); 407 m_mod = mod; 408 m_get_direct_mem_ptr = p; 409 } 410 411 sync_enum_type 412 nb_transport_fw(transaction_type &trans, phase_type &phase, 413 sc_core::sc_time &t) 414 { 415 if (m_nb_transport_ptr) { 416 // Forward call. 417 sc_assert(m_mod); 418 return (m_mod->*m_nb_transport_ptr)( 419 m_nb_transport_user_id, trans, phase, t); 420 } 421 display_error("no non-blocking callback registered"); 422 return tlm::TLM_COMPLETED; 423 } 424 425 void 426 b_transport(transaction_type &trans, sc_core::sc_time &t) 427 { 428 if (m_b_transport_ptr) { 429 // Forward call. 430 sc_assert(m_mod); 431 return (m_mod->*m_b_transport_ptr)( 432 m_b_transport_user_id, trans, t); 433 } 434 display_error("no blocking callback registered"); 435 } 436 437 unsigned int 438 transport_dbg(transaction_type &trans) 439 { 440 if (m_transport_dbg_ptr) { 441 // Forward call. 442 sc_assert(m_mod); 443 return (m_mod->*m_transport_dbg_ptr)( 444 m_transport_dbg_user_id, trans); 445 } 446 // No debug support. 447 return 0; 448 } 449 450 bool 451 get_direct_mem_ptr(transaction_type &trans, tlm::tlm_dmi &dmi_data) 452 { 453 if (m_get_direct_mem_ptr) { 454 // Forward call. 455 sc_assert(m_mod); 456 return (m_mod->*m_get_direct_mem_ptr)( 457 m_get_dmi_user_id, trans, dmi_data); 458 } 459 // No DMI support 460 dmi_data.allow_read_write(); 461 dmi_data.set_start_address(0x0); 462 dmi_data.set_end_address((sc_dt::uint64)-1); 463 return false; 464 } 465 466 private: 467 MODULE *m_mod; 468 NBTransportPtr m_nb_transport_ptr; 469 BTransportPtr m_b_transport_ptr; 470 TransportDbgPtr m_transport_dbg_ptr; 471 GetDirectMem_ptr m_get_direct_mem_ptr; 472 int m_nb_transport_user_id; 473 int m_b_transport_user_id; 474 int m_transport_dbg_user_id; 475 int m_get_dmi_user_id; 476 }; 477 478 private: 479 const sc_core::sc_object *get_socket() const { return this; } 480 481 private: 482 process m_process; 483}; 484 485template <typename MODULE, unsigned int BUSWIDTH=32, 486 typename TYPES=tlm::tlm_base_protocol_types> 487class passthrough_target_socket_tagged : 488 public passthrough_target_socket_tagged_b<MODULE, BUSWIDTH, TYPES> 489{ 490 typedef passthrough_target_socket_tagged_b<MODULE, BUSWIDTH, TYPES> 491 socket_b; 492 public: 493 passthrough_target_socket_tagged() : socket_b() {} 494 explicit passthrough_target_socket_tagged(const char *name) : 495 socket_b(name) 496 {} 497}; 498 499template <typename MODULE, unsigned int BUSWIDTH=32, 500 typename TYPES=tlm::tlm_base_protocol_types> 501class passthrough_target_socket_tagged_optional : 502 public passthrough_target_socket_tagged_b< 503 MODULE, BUSWIDTH, TYPES, sc_core::SC_ZERO_OR_MORE_BOUND> 504{ 505 typedef passthrough_target_socket_tagged_b< 506 MODULE, BUSWIDTH, TYPES, sc_core::SC_ZERO_OR_MORE_BOUND> socket_b; 507 public: 508 passthrough_target_socket_tagged_optional() : socket_b() {} 509 explicit passthrough_target_socket_tagged_optional(const char *name) : 510 socket_b(name) 511 {} 512}; 513 514} // namespace tlm_utils 515 516#endif /* __SYSTEMC_EXT_TLM_UTILS_PASSTHROUGH_TARGET_SOCKET_H__ */ 517