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