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