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