00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef __SIMPLE_TARGET_SOCKET_H__
00019 #define __SIMPLE_TARGET_SOCKET_H__
00020
00021 #include "tlm.h"
00022 #include "peq_with_get.h"
00023
00024 namespace tlm_utils {
00025
00026 template <typename MODULE,
00027 unsigned int BUSWIDTH = 32,
00028 typename TYPES = tlm::tlm_base_protocol_types>
00029 class simple_target_socket :
00030 public tlm::tlm_target_socket<BUSWIDTH, TYPES>
00031 {
00032 friend class fw_process;
00033 friend class bw_process;
00034 public:
00035 typedef typename TYPES::tlm_payload_type transaction_type;
00036 typedef typename TYPES::tlm_phase_type phase_type;
00037 typedef tlm::tlm_sync_enum sync_enum_type;
00038 typedef tlm::tlm_fw_transport_if<TYPES> fw_interface_type;
00039 typedef tlm::tlm_bw_transport_if<TYPES> bw_interface_type;
00040 typedef tlm::tlm_target_socket<BUSWIDTH, TYPES> base_type;
00041
00042 public:
00043 explicit simple_target_socket(const char* n = "simple_target_socket") :
00044 base_type(sc_core::sc_gen_unique_name(n)),
00045 m_fw_process(this),
00046 m_bw_process(this)
00047 {
00048 bind(m_fw_process);
00049 }
00050
00051
00052 tlm::tlm_bw_transport_if<TYPES> * operator ->() {return &m_bw_process;}
00053
00054
00055 void register_nb_transport_fw(MODULE* mod,
00056 sync_enum_type (MODULE::*cb)(transaction_type&,
00057 phase_type&,
00058 sc_core::sc_time&))
00059 {
00060 assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
00061 m_fw_process.set_nb_transport_ptr(mod, cb);
00062 }
00063
00064 void register_b_transport(MODULE* mod,
00065 void (MODULE::*cb)(transaction_type&,
00066 sc_core::sc_time&))
00067 {
00068 assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
00069 m_fw_process.set_b_transport_ptr(mod, cb);
00070 }
00071
00072 void register_transport_dbg(MODULE* mod,
00073 unsigned int (MODULE::*cb)(transaction_type&))
00074 {
00075 assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
00076 m_fw_process.set_transport_dbg_ptr(mod, cb);
00077 }
00078
00079 void register_get_direct_mem_ptr(MODULE* mod,
00080 bool (MODULE::*cb)(transaction_type&,
00081 tlm::tlm_dmi&))
00082 {
00083 assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
00084 m_fw_process.set_get_direct_mem_ptr(mod, cb);
00085 }
00086
00087 private:
00088
00089 sync_enum_type bw_nb_transport(transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
00090 {
00091 return base_type::operator ->()->nb_transport_bw(trans, phase, t);
00092 }
00093
00094 void bw_invalidate_direct_mem_ptr(sc_dt::uint64 s,sc_dt::uint64 e)
00095 {
00096 base_type::operator ->()->invalidate_direct_mem_ptr(s, e);
00097 }
00098
00099
00100
00101 class bw_process : public tlm::tlm_bw_transport_if<TYPES>
00102 {
00103 public:
00104 bw_process(simple_target_socket *p_own) : m_owner(p_own)
00105 {
00106 }
00107
00108 sync_enum_type nb_transport_bw(transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
00109 {
00110 typename std::map<transaction_type*, sc_core::sc_event *>::iterator it;
00111
00112 it = m_owner->m_pending_trans.find(&trans);
00113 if(it == m_owner->m_pending_trans.end()) {
00114
00115 return m_owner->bw_nb_transport(trans, phase, t);
00116
00117 } else {
00118 if (phase == tlm::END_REQ) {
00119 m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME);
00120 return tlm::TLM_ACCEPTED;
00121
00122 } else if (phase == tlm::BEGIN_RESP) {
00123 if (m_owner->m_current_transaction == &trans) {
00124 m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME);
00125 }
00126
00127 it->second->notify(t);
00128 m_owner->m_pending_trans.erase(it);
00129 return tlm::TLM_COMPLETED;
00130
00131 } else {
00132 assert(0); exit(1);
00133 }
00134
00135
00136 }
00137 }
00138
00139 void invalidate_direct_mem_ptr(sc_dt::uint64 s,sc_dt::uint64 e)
00140 {
00141 return m_owner->bw_invalidate_direct_mem_ptr(s, e);
00142 }
00143
00144 private:
00145 simple_target_socket *m_owner;
00146 };
00147
00148 class fw_process : public tlm::tlm_fw_transport_if<TYPES>,
00149 public tlm::tlm_mm_interface
00150 {
00151 public:
00152 typedef sync_enum_type (MODULE::*NBTransportPtr)(transaction_type&,
00153 tlm::tlm_phase&,
00154 sc_core::sc_time&);
00155 typedef void (MODULE::*BTransportPtr)(transaction_type&,
00156 sc_core::sc_time&);
00157 typedef unsigned int (MODULE::*TransportDbgPtr)(transaction_type&);
00158 typedef bool (MODULE::*GetDirectMemPtr)(transaction_type&,
00159 tlm::tlm_dmi&);
00160
00161 fw_process(simple_target_socket *p_own) :
00162 m_name(p_own->name()),
00163 m_owner(p_own),
00164 m_mod(0),
00165 m_nb_transport_ptr(0),
00166 m_b_transport_ptr(0),
00167 m_transport_dbg_ptr(0),
00168 m_get_direct_mem_ptr(0),
00169 m_peq(sc_core::sc_gen_unique_name("m_peq")),
00170 m_response_in_progress(false)
00171 {
00172 sc_core::sc_spawn_options opts;
00173 opts.set_sensitivity(&m_peq.get_event());
00174 sc_core::sc_spawn(sc_bind(&fw_process::b2nb_thread, this),
00175 sc_core::sc_gen_unique_name("b2nb_thread"), &opts);
00176 }
00177
00178 void set_nb_transport_ptr(MODULE* mod, NBTransportPtr p)
00179 {
00180 if (m_nb_transport_ptr) {
00181 std::cerr << m_name << ": non-blocking callback allready registered" << std::endl;
00182
00183 } else {
00184 assert(!m_mod || m_mod == mod);
00185 m_mod = mod;
00186 m_nb_transport_ptr = p;
00187 }
00188 }
00189
00190 void set_b_transport_ptr(MODULE* mod, BTransportPtr p)
00191 {
00192 if (m_b_transport_ptr) {
00193 std::cerr << m_name << ": non-blocking callback allready registered" << std::endl;
00194
00195 } else {
00196 assert(!m_mod || m_mod == mod);
00197 m_mod = mod;
00198 m_b_transport_ptr = p;
00199 }
00200 }
00201
00202 void set_transport_dbg_ptr(MODULE* mod, TransportDbgPtr p)
00203 {
00204 if (m_transport_dbg_ptr) {
00205 std::cerr << m_name << ": debug callback allready registered" << std::endl;
00206
00207 } else {
00208 assert(!m_mod || m_mod == mod);
00209 m_mod = mod;
00210 m_transport_dbg_ptr = p;
00211 }
00212 }
00213
00214 void set_get_direct_mem_ptr(MODULE* mod, GetDirectMemPtr p)
00215 {
00216 if (m_get_direct_mem_ptr) {
00217 std::cerr << m_name << ": get DMI pointer callback allready registered" << std::endl;
00218
00219 } else {
00220 assert(!m_mod || m_mod == mod);
00221 m_mod = mod;
00222 m_get_direct_mem_ptr = p;
00223 }
00224 }
00225
00226 sync_enum_type nb_transport_fw(transaction_type& trans,
00227 phase_type& phase,
00228 sc_core::sc_time& t)
00229 {
00230 if (m_nb_transport_ptr) {
00231
00232 assert(m_mod);
00233 return (m_mod->*m_nb_transport_ptr)(trans, phase, t);
00234
00235 } else if (m_b_transport_ptr) {
00236 if (phase == tlm::BEGIN_REQ) {
00237
00238 sc_core::sc_spawn_options opts;
00239 opts.dont_initialize();
00240 sc_core::sc_event *e = new sc_core::sc_event;
00241 opts.set_sensitivity(e);
00242
00243
00244
00245
00246 process_handle_class * ph = m_process_handle.get_handle(&trans,e);
00247
00248 if (!ph) {
00249 ph = new process_handle_class(&trans,e);
00250 m_process_handle.put_handle(ph);
00251
00252 sc_core::sc_spawn(sc_bind(&fw_process::nb2b_thread,this, ph, sc_ref(trans), e),
00253 sc_core::sc_gen_unique_name("nb2b_thread"), &opts);
00254 } else {
00255 ph->m_wakeup.notify();
00256 }
00257
00258
00259 e->notify(t);
00260 return tlm::TLM_ACCEPTED;
00261
00262 } else if (phase == tlm::END_RESP) {
00263 m_response_in_progress = false;
00264 m_end_response.notify(t);
00265 return tlm::TLM_COMPLETED;
00266
00267 } else {
00268 assert(0); exit(1);
00269
00270 }
00271
00272 } else {
00273 std::cerr << m_name << ": no transport callback registered" << std::endl;
00274 assert(0); exit(1);
00275
00276 }
00277 }
00278
00279 void b_transport(transaction_type& trans, sc_core::sc_time& t)
00280 {
00281 if (m_b_transport_ptr) {
00282
00283 assert(m_mod);
00284 (m_mod->*m_b_transport_ptr)(trans, t);
00285 return;
00286
00287 } else if (m_nb_transport_ptr) {
00288 m_peq.notify(trans, t);
00289 t = sc_core::SC_ZERO_TIME;
00290
00291 mm_end_event_ext mm_ext;
00292 const bool mm_added = !trans.has_mm();
00293
00294 if (mm_added) {
00295 trans.set_mm(this);
00296 trans.set_auto_extension(&mm_ext);
00297 trans.acquire();
00298 }
00299
00300
00301 sc_core::sc_event end_event;
00302 m_owner->m_pending_trans[&trans] = &end_event;
00303 sc_core::wait(end_event);
00304
00305 if (mm_added) {
00306
00307 trans.release();
00308 if (trans.get_ref_count()) {
00309 sc_core::wait(mm_ext.done);
00310 }
00311 trans.set_mm(0);
00312 }
00313
00314 } else {
00315 std::cerr << m_name << ": no transport callback registered" << std::endl;
00316 assert(0); exit(1);
00317
00318 }
00319 }
00320
00321 unsigned int transport_dbg(transaction_type& trans)
00322 {
00323 if (m_transport_dbg_ptr) {
00324
00325 assert(m_mod);
00326 return (m_mod->*m_transport_dbg_ptr)(trans);
00327
00328 } else {
00329
00330 return 0;
00331 }
00332 }
00333
00334 bool get_direct_mem_ptr(transaction_type& trans,
00335 tlm::tlm_dmi& dmi_data)
00336 {
00337 if (m_get_direct_mem_ptr) {
00338
00339 assert(m_mod);
00340 return (m_mod->*m_get_direct_mem_ptr)(trans, dmi_data);
00341
00342 } else {
00343
00344 dmi_data.allow_read_write();
00345 dmi_data.set_start_address(0x0);
00346 dmi_data.set_end_address((sc_dt::uint64)-1);
00347 return false;
00348 }
00349 }
00350
00351 private:
00352
00353
00354
00355 class process_handle_class {
00356 public:
00357 process_handle_class(transaction_type * trans,
00358 sc_core::sc_event* e):
00359 m_trans(trans),m_e(e),m_suspend(false){}
00360
00361 transaction_type* m_trans;
00362 sc_core::sc_event* m_e;
00363 sc_core::sc_event m_wakeup;
00364 bool m_suspend;
00365 };
00366
00367 class process_handle_list {
00368 public:
00369 process_handle_list() {}
00370
00371 process_handle_class* get_handle(transaction_type *trans,sc_core::sc_event* e)
00372 {
00373 typename std::vector<process_handle_class*>::iterator it;
00374
00375 for(it = v.begin(); it != v.end(); it++) {
00376 if ((*it)->m_suspend) {
00377 (*it)->m_trans = trans;
00378 (*it)->m_e = e;
00379 return *it;
00380 }
00381 }
00382 return NULL;
00383 }
00384
00385 void put_handle(process_handle_class* ph)
00386 {
00387 v.push_back(ph);
00388 }
00389
00390 private:
00391 std::vector<process_handle_class*> v;
00392 };
00393
00394 process_handle_list m_process_handle;
00395
00396
00397 void nb2b_thread(process_handle_class* h,transaction_type &trans1, sc_core::sc_event *e1)
00398 {
00399 transaction_type *trans = &trans1;
00400 sc_core::sc_event* e = e1;
00401
00402 while(1) {
00403
00404 sc_core::sc_time t = sc_core::SC_ZERO_TIME;
00405
00406
00407 assert(m_mod);
00408 (m_mod->*m_b_transport_ptr)(*trans, t);
00409
00410 sc_core::wait(t);
00411
00412
00413 while (m_response_in_progress) {
00414 sc_core::wait(m_end_response);
00415 }
00416 t = sc_core::SC_ZERO_TIME;
00417 phase_type phase = tlm::BEGIN_RESP;
00418 if (m_owner->bw_nb_transport(*trans, phase, t) != tlm::TLM_COMPLETED) {
00419 m_response_in_progress = true;
00420 }
00421
00422
00423 delete e;
00424
00425
00426 h->m_suspend = true;
00427 sc_core::wait(h->m_wakeup);
00428
00429
00430 h->m_suspend = false;
00431 trans = h->m_trans;
00432 e = h->m_e;
00433 }
00434 }
00435
00436 void b2nb_thread()
00437 {
00438 while (true) {
00439 sc_core::wait(m_peq.get_event());
00440
00441 transaction_type* trans;
00442 while ((trans = m_peq.get_next_transaction())!=0) {
00443 assert(m_mod);
00444 assert(m_nb_transport_ptr);
00445 phase_type phase = tlm::BEGIN_REQ;
00446 sc_core::sc_time t = sc_core::SC_ZERO_TIME;
00447
00448 switch ((m_mod->*m_nb_transport_ptr)(*trans, phase, t)) {
00449 case tlm::TLM_COMPLETED:
00450 {
00451
00452 typename std::map<transaction_type*, sc_core::sc_event *>::iterator it =
00453 m_owner->m_pending_trans.find(trans);
00454 assert(it != m_owner->m_pending_trans.end());
00455 it->second->notify(t);
00456 m_owner->m_pending_trans.erase(it);
00457 break;
00458 }
00459
00460 case tlm::TLM_ACCEPTED:
00461 case tlm::TLM_UPDATED:
00462 switch (phase) {
00463 case tlm::BEGIN_REQ:
00464 m_owner->m_current_transaction = trans;
00465 sc_core::wait(m_owner->m_end_request);
00466 m_owner->m_current_transaction = 0;
00467 break;
00468
00469 case tlm::END_REQ:
00470 sc_core::wait(t);
00471 break;
00472
00473 case tlm::BEGIN_RESP:
00474 {
00475 phase = tlm::END_RESP;
00476 t = sc_core::SC_ZERO_TIME;
00477 (m_mod->*m_nb_transport_ptr)(*trans, phase, t);
00478
00479
00480 typename std::map<transaction_type*, sc_core::sc_event *>::iterator it =
00481 m_owner->m_pending_trans.find(trans);
00482 assert(it != m_owner->m_pending_trans.end());
00483 it->second->notify(t);
00484 m_owner->m_pending_trans.erase(it);
00485 break;
00486 }
00487
00488 default:
00489 assert(0); exit(1);
00490 };
00491 break;
00492
00493 default:
00494 assert(0); exit(1);
00495 };
00496 }
00497 }
00498 }
00499
00500 void free(tlm::tlm_generic_payload* trans)
00501 {
00502 mm_end_event_ext* ext = trans->template get_extension<mm_end_event_ext>();
00503 assert(ext);
00504
00505 ext->done.notify();
00506 trans->reset();
00507 }
00508
00509 private:
00510 struct mm_end_event_ext : public tlm::tlm_extension<mm_end_event_ext>
00511 {
00512 tlm::tlm_extension_base* clone() const { return NULL; }
00513 void free() {}
00514 void copy_from(tlm::tlm_extension_base const &) {}
00515 sc_core::sc_event done;
00516 };
00517
00518 private:
00519 const std::string m_name;
00520 simple_target_socket *m_owner;
00521 MODULE* m_mod;
00522 NBTransportPtr m_nb_transport_ptr;
00523 BTransportPtr m_b_transport_ptr;
00524 TransportDbgPtr m_transport_dbg_ptr;
00525 GetDirectMemPtr m_get_direct_mem_ptr;
00526 peq_with_get<transaction_type> m_peq;
00527 bool m_response_in_progress;
00528 sc_core::sc_event m_end_response;
00529 };
00530
00531 private:
00532 fw_process m_fw_process;
00533 bw_process m_bw_process;
00534 std::map<transaction_type*, sc_core::sc_event *> m_pending_trans;
00535 sc_core::sc_event m_end_request;
00536 transaction_type* m_current_transaction;
00537 };
00538
00539
00540 template <typename MODULE,
00541 unsigned int BUSWIDTH = 32,
00542 typename TYPES = tlm::tlm_base_protocol_types>
00543 class simple_target_socket_tagged :
00544 public tlm::tlm_target_socket<BUSWIDTH, TYPES>
00545 {
00546 friend class fw_process;
00547 friend class bw_process;
00548 public:
00549 typedef typename TYPES::tlm_payload_type transaction_type;
00550 typedef typename TYPES::tlm_phase_type phase_type;
00551 typedef tlm::tlm_sync_enum sync_enum_type;
00552 typedef tlm::tlm_fw_transport_if<TYPES> fw_interface_type;
00553 typedef tlm::tlm_bw_transport_if<TYPES> bw_interface_type;
00554 typedef tlm::tlm_target_socket<BUSWIDTH, TYPES> base_type;
00555
00556 public:
00557 explicit simple_target_socket_tagged(const char* n = "simple_target_socket_tagged") :
00558 base_type(sc_core::sc_gen_unique_name(n)),
00559 m_fw_process(this),
00560 m_bw_process(this)
00561 {
00562 bind(m_fw_process);
00563 }
00564
00565
00566 tlm::tlm_bw_transport_if<TYPES> * operator ->() {return &m_bw_process;}
00567
00568
00569 void register_nb_transport_fw(MODULE* mod,
00570 sync_enum_type (MODULE::*cb)(int id,
00571 transaction_type&,
00572 phase_type&,
00573 sc_core::sc_time&),
00574 int id)
00575 {
00576 assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
00577 m_fw_process.set_nb_transport_ptr(mod, cb);
00578 m_fw_process.set_nb_transport_user_id(id);
00579 }
00580
00581 void register_b_transport(MODULE* mod,
00582 void (MODULE::*cb)(int id,
00583 transaction_type&,
00584 sc_core::sc_time&),
00585 int id)
00586 {
00587 assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
00588 m_fw_process.set_b_transport_ptr(mod, cb);
00589 m_fw_process.set_b_transport_user_id(id);
00590 }
00591
00592 void register_transport_dbg(MODULE* mod,
00593 unsigned int (MODULE::*cb)(int id,
00594 transaction_type&),
00595 int id)
00596 {
00597 assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
00598 m_fw_process.set_transport_dbg_ptr(mod, cb);
00599 m_fw_process.set_transport_dbg_user_id(id);
00600 }
00601
00602 void register_get_direct_mem_ptr(MODULE* mod,
00603 bool (MODULE::*cb)(int id,
00604 transaction_type&,
00605 tlm::tlm_dmi&),
00606 int id)
00607 {
00608 assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
00609 m_fw_process.set_get_direct_mem_ptr(mod, cb);
00610 m_fw_process.set_get_dmi_user_id(id);
00611 }
00612
00613 private:
00614
00615 sync_enum_type bw_nb_transport(transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
00616 {
00617 return base_type::operator ->()->nb_transport_bw(trans, phase, t);
00618 }
00619
00620 void bw_invalidate_direct_mem_ptr(sc_dt::uint64 s,sc_dt::uint64 e)
00621 {
00622 base_type::operator ->()->invalidate_direct_mem_ptr(s, e);
00623 }
00624
00625
00626
00627 class bw_process : public tlm::tlm_bw_transport_if<TYPES>
00628 {
00629 public:
00630 bw_process(simple_target_socket_tagged *p_own) : m_owner(p_own)
00631 {
00632 }
00633
00634 sync_enum_type nb_transport_bw(transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
00635 {
00636 typename std::map<transaction_type*, sc_core::sc_event *>::iterator it;
00637
00638 it = m_owner->m_pending_trans.find(&trans);
00639 if(it == m_owner->m_pending_trans.end()) {
00640
00641 return m_owner->bw_nb_transport(trans, phase, t);
00642
00643 } else {
00644 if (phase == tlm::END_REQ) {
00645 m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME);
00646 return tlm::TLM_ACCEPTED;
00647
00648 } else if (phase == tlm::BEGIN_RESP) {
00649 if (m_owner->m_current_transaction == &trans) {
00650 m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME);
00651 }
00652
00653 it->second->notify(t);
00654 m_owner->m_pending_trans.erase(it);
00655 return tlm::TLM_COMPLETED;
00656
00657 } else {
00658 assert(0); exit(1);
00659 }
00660
00661
00662 }
00663 }
00664
00665 void invalidate_direct_mem_ptr(sc_dt::uint64 s,sc_dt::uint64 e)
00666 {
00667 return m_owner->bw_invalidate_direct_mem_ptr(s, e);
00668 }
00669
00670 private:
00671 simple_target_socket_tagged *m_owner;
00672 };
00673
00674 class fw_process : public tlm::tlm_fw_transport_if<TYPES>,
00675 public tlm::tlm_mm_interface
00676 {
00677 public:
00678 typedef sync_enum_type (MODULE::*NBTransportPtr)(int id,
00679 transaction_type&,
00680 tlm::tlm_phase&,
00681 sc_core::sc_time&);
00682 typedef void (MODULE::*BTransportPtr)(int id,
00683 transaction_type&,
00684 sc_core::sc_time&);
00685 typedef unsigned int (MODULE::*TransportDbgPtr)(int id,
00686 transaction_type&);
00687 typedef bool (MODULE::*GetDirectMemPtr)(int id,
00688 transaction_type&,
00689 tlm::tlm_dmi&);
00690
00691 fw_process(simple_target_socket_tagged *p_own) :
00692 m_name(p_own->name()),
00693 m_owner(p_own),
00694 m_mod(0),
00695 m_nb_transport_ptr(0),
00696 m_b_transport_ptr(0),
00697 m_transport_dbg_ptr(0),
00698 m_get_direct_mem_ptr(0),
00699 m_nb_transport_user_id(0),
00700 m_b_transport_user_id(0),
00701 m_transport_dbg_user_id(0),
00702 m_get_dmi_user_id(0),
00703 m_peq(sc_core::sc_gen_unique_name("m_peq")),
00704 m_response_in_progress(false)
00705 {
00706 sc_core::sc_spawn_options opts;
00707 opts.set_sensitivity(&m_peq.get_event());
00708 sc_core::sc_spawn(sc_bind(&fw_process::b2nb_thread, this),
00709 sc_core::sc_gen_unique_name("b2nb_thread"), &opts);
00710 }
00711
00712 void set_nb_transport_user_id(int id) { m_nb_transport_user_id = id; }
00713 void set_b_transport_user_id(int id) { m_b_transport_user_id = id; }
00714 void set_transport_dbg_user_id(int id) { m_transport_dbg_user_id = id; }
00715 void set_get_dmi_user_id(int id) { m_get_dmi_user_id = id; }
00716
00717 void set_nb_transport_ptr(MODULE* mod, NBTransportPtr p)
00718 {
00719 if (m_nb_transport_ptr) {
00720 std::cerr << m_name << ": non-blocking callback allready registered" << std::endl;
00721
00722 } else {
00723 assert(!m_mod || m_mod == mod);
00724 m_mod = mod;
00725 m_nb_transport_ptr = p;
00726 }
00727 }
00728
00729 void set_b_transport_ptr(MODULE* mod, BTransportPtr p)
00730 {
00731 if (m_b_transport_ptr) {
00732 std::cerr << m_name << ": non-blocking callback allready registered" << std::endl;
00733
00734 } else {
00735 assert(!m_mod || m_mod == mod);
00736 m_mod = mod;
00737 m_b_transport_ptr = p;
00738 }
00739 }
00740
00741 void set_transport_dbg_ptr(MODULE* mod, TransportDbgPtr p)
00742 {
00743 if (m_transport_dbg_ptr) {
00744 std::cerr << m_name << ": debug callback allready registered" << std::endl;
00745
00746 } else {
00747 assert(!m_mod || m_mod == mod);
00748 m_mod = mod;
00749 m_transport_dbg_ptr = p;
00750 }
00751 }
00752
00753 void set_get_direct_mem_ptr(MODULE* mod, GetDirectMemPtr p)
00754 {
00755 if (m_get_direct_mem_ptr) {
00756 std::cerr << m_name << ": get DMI pointer callback allready registered" << std::endl;
00757
00758 } else {
00759 assert(!m_mod || m_mod == mod);
00760 m_mod = mod;
00761 m_get_direct_mem_ptr = p;
00762 }
00763 }
00764
00765 sync_enum_type nb_transport_fw(transaction_type& trans,
00766 phase_type& phase,
00767 sc_core::sc_time& t)
00768 {
00769 if (m_nb_transport_ptr) {
00770
00771 assert(m_mod);
00772 return (m_mod->*m_nb_transport_ptr)(m_nb_transport_user_id, trans, phase, t);
00773
00774 } else if (m_b_transport_ptr) {
00775 if (phase == tlm::BEGIN_REQ) {
00776
00777 sc_core::sc_spawn_options opts;
00778 opts.dont_initialize();
00779 sc_core::sc_event *e = new sc_core::sc_event;
00780 opts.set_sensitivity(e);
00781
00782
00783
00784
00785 process_handle_class * ph = m_process_handle.get_handle(&trans,e);
00786
00787 if (!ph) {
00788 ph = new process_handle_class(&trans,e);
00789 m_process_handle.put_handle(ph);
00790
00791 sc_core::sc_spawn(sc_bind(&fw_process::nb2b_thread, this, ph, sc_ref(trans), e),
00792 sc_core::sc_gen_unique_name("nb2b_thread"), &opts);
00793 } else {
00794 ph->m_wakeup.notify();
00795 }
00796
00797 e->notify(t);
00798 return tlm::TLM_ACCEPTED;
00799
00800 } else if (phase == tlm::END_RESP) {
00801 m_response_in_progress = false;
00802 m_end_response.notify(t);
00803 return tlm::TLM_COMPLETED;
00804
00805 } else {
00806 assert(0); exit(1);
00807
00808 }
00809
00810 } else {
00811 std::cerr << m_name << ": no transport callback registered" << std::endl;
00812 assert(0); exit(1);
00813
00814 }
00815 }
00816
00817 void b_transport(transaction_type& trans, sc_core::sc_time& t)
00818 {
00819 if (m_b_transport_ptr) {
00820
00821 assert(m_mod);
00822 (m_mod->*m_b_transport_ptr)(m_b_transport_user_id, trans, t);
00823 return;
00824
00825 } else if (m_nb_transport_ptr) {
00826 m_peq.notify(trans, t);
00827 t = sc_core::SC_ZERO_TIME;
00828
00829 mm_end_event_ext mm_ext;
00830 const bool mm_added = !trans.has_mm();
00831
00832 if (mm_added){
00833 trans.set_mm(this);
00834 trans.set_auto_extension(&mm_ext);
00835 trans.acquire();
00836 }
00837
00838
00839 sc_core::sc_event end_event;
00840 m_owner->m_pending_trans[&trans] = &end_event;
00841 sc_core::wait(end_event);
00842
00843 if (mm_added) {
00844
00845 trans.release();
00846 if (trans.get_ref_count()) {
00847 sc_core::wait(mm_ext.done);
00848 }
00849 trans.set_mm(0);
00850 }
00851
00852 } else {
00853 std::cerr << m_name << ": no transport callback registered" << std::endl;
00854 assert(0); exit(1);
00855
00856 }
00857 }
00858
00859 unsigned int transport_dbg(transaction_type& trans)
00860 {
00861 if (m_transport_dbg_ptr) {
00862
00863 assert(m_mod);
00864 return (m_mod->*m_transport_dbg_ptr)(m_transport_dbg_user_id, trans);
00865
00866 } else {
00867
00868 return 0;
00869 }
00870 }
00871
00872 bool get_direct_mem_ptr(transaction_type& trans,
00873 tlm::tlm_dmi& dmi_data)
00874 {
00875 if (m_get_direct_mem_ptr) {
00876
00877 assert(m_mod);
00878 return (m_mod->*m_get_direct_mem_ptr)(m_get_dmi_user_id, trans, dmi_data);
00879
00880 } else {
00881
00882 dmi_data.allow_read_write();
00883 dmi_data.set_start_address(0x0);
00884 dmi_data.set_end_address((sc_dt::uint64)-1);
00885 return false;
00886 }
00887 }
00888
00889 private:
00890
00891
00892 class process_handle_class {
00893 public:
00894 process_handle_class(transaction_type * trans,
00895 sc_core::sc_event* e):
00896 m_trans(trans),m_e(e),m_suspend(false){}
00897
00898 transaction_type* m_trans;
00899 sc_core::sc_event* m_e;
00900 sc_core::sc_event m_wakeup;
00901 bool m_suspend;
00902 };
00903
00904 class process_handle_list {
00905 public:
00906 process_handle_list() {}
00907
00908 process_handle_class* get_handle(transaction_type *trans,sc_core::sc_event* e)
00909 {
00910 typename std::vector<process_handle_class*>::iterator it;
00911
00912 for(it = v.begin(); it != v.end(); it++) {
00913 if ((*it)->m_suspend) {
00914 (*it)->m_trans = trans;
00915 (*it)->m_e = e;
00916 return *it;
00917 }
00918 }
00919 return NULL;
00920 }
00921
00922 void put_handle(process_handle_class* ph)
00923 {
00924 v.push_back(ph);
00925 }
00926
00927 private:
00928 std::vector<process_handle_class*> v;
00929 };
00930
00931 process_handle_list m_process_handle;
00932
00933 void nb2b_thread(process_handle_class* h,transaction_type &trans1, sc_core::sc_event *e1)
00934 {
00935 transaction_type *trans = &trans1;
00936 sc_core::sc_event* e = e1;
00937
00938 while(1) {
00939 sc_core::sc_time t = sc_core::SC_ZERO_TIME;
00940
00941
00942 assert(m_mod);
00943 (m_mod->*m_b_transport_ptr)(m_b_transport_user_id, *trans, t);
00944
00945 sc_core::wait(t);
00946
00947
00948 while (m_response_in_progress) {
00949 sc_core::wait(m_end_response);
00950 }
00951 t = sc_core::SC_ZERO_TIME;
00952 phase_type phase = tlm::BEGIN_RESP;
00953 if (m_owner->bw_nb_transport(*trans, phase, t) != tlm::TLM_COMPLETED) {
00954 m_response_in_progress = true;
00955 }
00956
00957
00958 delete e;
00959
00960
00961 h->m_suspend = true;
00962 sc_core::wait(h->m_wakeup);
00963
00964
00965 h->m_suspend = false;
00966 trans = h->m_trans;
00967 e = h->m_e;
00968 }
00969 }
00970
00971 void b2nb_thread()
00972 {
00973 while (true) {
00974 sc_core::wait(m_peq.get_event());
00975
00976 transaction_type* trans;
00977 while ((trans = m_peq.get_next_transaction())!=0) {
00978 assert(m_mod);
00979 assert(m_nb_transport_ptr);
00980 phase_type phase = tlm::BEGIN_REQ;
00981 sc_core::sc_time t = sc_core::SC_ZERO_TIME;
00982
00983 switch ((m_mod->*m_nb_transport_ptr)(m_nb_transport_user_id, *trans, phase, t)) {
00984 case tlm::TLM_COMPLETED:
00985 {
00986
00987 typename std::map<transaction_type*, sc_core::sc_event *>::iterator it =
00988 m_owner->m_pending_trans.find(trans);
00989 assert(it != m_owner->m_pending_trans.end());
00990 it->second->notify(t);
00991 m_owner->m_pending_trans.erase(it);
00992 break;
00993 }
00994
00995 case tlm::TLM_ACCEPTED:
00996 case tlm::TLM_UPDATED:
00997 switch (phase) {
00998 case tlm::BEGIN_REQ:
00999 m_owner->m_current_transaction = trans;
01000 sc_core::wait(m_owner->m_end_request);
01001 m_owner->m_current_transaction = 0;
01002 break;
01003
01004 case tlm::END_REQ:
01005 sc_core::wait(t);
01006 break;
01007
01008 case tlm::BEGIN_RESP:
01009 {
01010 phase = tlm::END_RESP;
01011 t = sc_core::SC_ZERO_TIME;
01012 (m_mod->*m_nb_transport_ptr)(m_nb_transport_user_id, *trans, phase, t);
01013
01014
01015 typename std::map<transaction_type*, sc_core::sc_event *>::iterator it =
01016 m_owner->m_pending_trans.find(trans);
01017 assert(it != m_owner->m_pending_trans.end());
01018 it->second->notify(t);
01019 m_owner->m_pending_trans.erase(it);
01020 break;
01021 }
01022
01023 default:
01024 assert(0); exit(1);
01025 };
01026 break;
01027
01028 default:
01029 assert(0); exit(1);
01030 };
01031 }
01032 }
01033 }
01034
01035 void free(tlm::tlm_generic_payload* trans)
01036 {
01037 mm_end_event_ext* ext = trans->template get_extension<mm_end_event_ext>();
01038 assert(ext);
01039
01040 ext->done.notify();
01041 trans->reset();
01042 }
01043
01044 private:
01045 struct mm_end_event_ext : public tlm::tlm_extension<mm_end_event_ext>
01046 {
01047 tlm::tlm_extension_base* clone() const { return NULL; }
01048 void free() {}
01049 void copy_from(tlm::tlm_extension_base const &) {}
01050 sc_core::sc_event done;
01051 };
01052
01053 private:
01054 const std::string m_name;
01055 simple_target_socket_tagged *m_owner;
01056 MODULE* m_mod;
01057 NBTransportPtr m_nb_transport_ptr;
01058 BTransportPtr m_b_transport_ptr;
01059 TransportDbgPtr m_transport_dbg_ptr;
01060 GetDirectMemPtr m_get_direct_mem_ptr;
01061 int m_nb_transport_user_id;
01062 int m_b_transport_user_id;
01063 int m_transport_dbg_user_id;
01064 int m_get_dmi_user_id;
01065 peq_with_get<transaction_type> m_peq;
01066 bool m_response_in_progress;
01067 sc_core::sc_event m_end_response;
01068 };
01069
01070 private:
01071 fw_process m_fw_process;
01072 bw_process m_bw_process;
01073 std::map<transaction_type*, sc_core::sc_event *> m_pending_trans;
01074 sc_core::sc_event m_end_request;
01075 transaction_type* m_current_transaction;
01076 };
01077
01078 }
01079
01080 #endif