📄 simple_target_socket.h
字号:
assert(!m_mod || m_mod == mod); m_mod = mod; m_nb_transport_ptr = p; } } void set_b_transport_ptr(MODULE* mod, BTransportPtr p) { if (m_b_transport_ptr) { std::cerr << m_name << ": non-blocking callback allready registered" << std::endl; } else { assert(!m_mod || m_mod == mod); m_mod = mod; m_b_transport_ptr = p; } } void set_transport_dbg_ptr(MODULE* mod, TransportDbgPtr p) { if (m_transport_dbg_ptr) { std::cerr << m_name << ": debug callback allready registered" << std::endl; } else { assert(!m_mod || m_mod == mod); m_mod = mod; m_transport_dbg_ptr = p; } } void set_get_direct_mem_ptr(MODULE* mod, GetDirectMemPtr p) { if (m_get_direct_mem_ptr) { std::cerr << m_name << ": get DMI pointer callback allready registered" << std::endl; } else { assert(!m_mod || m_mod == mod); m_mod = mod; m_get_direct_mem_ptr = p; } }// Interface implementation sync_enum_type nb_transport_fw(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) { if (m_nb_transport_ptr) { // forward call assert(m_mod); return (m_mod->*m_nb_transport_ptr)(m_nb_transport_user_id, trans, phase, t); } else if (m_b_transport_ptr) { if (phase == tlm::BEGIN_REQ) { // create thread to do blocking call sc_core::sc_spawn_options opts; opts.dont_initialize(); sc_core::sc_event *e = new sc_core::sc_event; opts.set_sensitivity(e); // sc_core::sc_spawn(sc_bind(&fw_process::nb2b_thread, this, sc_ref(trans), e), // sc_core::sc_gen_unique_name("nb2b_thread"), &opts); process_handle_class * ph = m_process_handle.get_handle(&trans,e); if (!ph) { // create new dynamic process ph = new process_handle_class(&trans,e); m_process_handle.put_handle(ph); sc_core::sc_spawn(sc_bind(&fw_process::nb2b_thread, this, ph, sc_ref(trans), e), sc_core::sc_gen_unique_name("nb2b_thread"), &opts); } else { // reuse existing dynamic process and resume it ph->m_wakeup.notify(); // immidiate notification } e->notify(t); return tlm::TLM_ACCEPTED; } else if (phase == tlm::END_RESP) { m_response_in_progress = false; m_end_response.notify(t); return tlm::TLM_COMPLETED; } else { assert(0); exit(1);// return tlm::TLM_COMPLETED; ///< unreachable code } } else { std::cerr << m_name << ": no transport callback registered" << std::endl; assert(0); exit(1);// return tlm::TLM_COMPLETED; ///< unreachable code } } void b_transport(transaction_type& trans, sc_core::sc_time& t) { if (m_b_transport_ptr) { // forward call assert(m_mod); (m_mod->*m_b_transport_ptr)(m_b_transport_user_id, trans, t); return; } else if (m_nb_transport_ptr) { m_peq.notify(trans, t); t = sc_core::SC_ZERO_TIME; mm_end_event_ext mm_ext; const bool mm_added = !trans.has_mm(); if (mm_added){ trans.set_mm(this); trans.set_auto_extension(&mm_ext); trans.acquire(); } // wait until transaction is finished sc_core::sc_event end_event; m_owner->m_pending_trans[&trans] = &end_event; sc_core::wait(end_event); if (mm_added) { // release will not delete the transaction, it will notify mm_ext.done trans.release(); if (trans.get_ref_count()) { sc_core::wait(mm_ext.done); } trans.set_mm(0); } } else { std::cerr << m_name << ": no transport callback registered" << std::endl; assert(0); exit(1);// return tlm::TLM_COMPLETED; ///< unreachable code } } unsigned int transport_dbg(transaction_type& trans) { if (m_transport_dbg_ptr) { // forward call assert(m_mod); return (m_mod->*m_transport_dbg_ptr)(m_transport_dbg_user_id, trans); } else { // No debug support return 0; } } bool get_direct_mem_ptr(transaction_type& trans, tlm::tlm_dmi& dmi_data) { if (m_get_direct_mem_ptr) { // forward call assert(m_mod); return (m_mod->*m_get_direct_mem_ptr)(m_get_dmi_user_id, trans, dmi_data); } else { // No DMI support dmi_data.allow_read_write(); dmi_data.set_start_address(0x0); dmi_data.set_end_address((sc_dt::uint64)-1); return false; } } private:// dynamic process handler for nb2b conversion class process_handle_class { public: process_handle_class(transaction_type * trans, sc_core::sc_event* e): m_trans(trans),m_e(e),m_suspend(false){} transaction_type* m_trans; sc_core::sc_event* m_e; sc_core::sc_event m_wakeup; bool m_suspend; }; class process_handle_list { public: process_handle_list() {} process_handle_class* get_handle(transaction_type *trans,sc_core::sc_event* e) { typename std::vector<process_handle_class*>::iterator it; for(it = v.begin(); it != v.end(); it++) { if ((*it)->m_suspend) { // found suspended dynamic process, re-use it (*it)->m_trans = trans; // replace to new one (*it)->m_e = e; return *it; } } return NULL; // no suspended process } void put_handle(process_handle_class* ph) { v.push_back(ph); } private: std::vector<process_handle_class*> v; }; process_handle_list m_process_handle; void nb2b_thread(process_handle_class* h,transaction_type &trans1, sc_core::sc_event *e1) { transaction_type *trans = &trans1; sc_core::sc_event* e = e1; while(1) { sc_core::sc_time t = sc_core::SC_ZERO_TIME; // forward call assert(m_mod); (m_mod->*m_b_transport_ptr)(m_b_transport_user_id, *trans, t); sc_core::wait(t); // return path while (m_response_in_progress) { sc_core::wait(m_end_response); } t = sc_core::SC_ZERO_TIME; phase_type phase = tlm::BEGIN_RESP; if (m_owner->bw_nb_transport(*trans, phase, t) != tlm::TLM_COMPLETED) { m_response_in_progress = true; } // cleanup delete e; // suspend until next transaction h->m_suspend = true; sc_core::wait(h->m_wakeup); // start next transaction h->m_suspend = false; trans = h->m_trans; e = h->m_e; } } void b2nb_thread() { while (true) { sc_core::wait(m_peq.get_event()); transaction_type* trans; while ((trans = m_peq.get_next_transaction())!=0) { assert(m_mod); assert(m_nb_transport_ptr); phase_type phase = tlm::BEGIN_REQ; sc_core::sc_time t = sc_core::SC_ZERO_TIME; switch ((m_mod->*m_nb_transport_ptr)(m_nb_transport_user_id, *trans, phase, t)) { case tlm::TLM_COMPLETED: { // notify transaction is finished typename std::map<transaction_type*, sc_core::sc_event *>::iterator it = m_owner->m_pending_trans.find(trans); assert(it != m_owner->m_pending_trans.end()); it->second->notify(t); m_owner->m_pending_trans.erase(it); break; } case tlm::TLM_ACCEPTED: case tlm::TLM_UPDATED: switch (phase) { case tlm::BEGIN_REQ: m_owner->m_current_transaction = trans; sc_core::wait(m_owner->m_end_request); m_owner->m_current_transaction = 0; break; case tlm::END_REQ: sc_core::wait(t); break; case tlm::BEGIN_RESP: { phase = tlm::END_RESP; t = sc_core::SC_ZERO_TIME; (m_mod->*m_nb_transport_ptr)(m_nb_transport_user_id, *trans, phase, t); // notify transaction is finished typename std::map<transaction_type*, sc_core::sc_event *>::iterator it = m_owner->m_pending_trans.find(trans); assert(it != m_owner->m_pending_trans.end()); it->second->notify(t); m_owner->m_pending_trans.erase(it); break; } default: assert(0); exit(1); }; break; default: assert(0); exit(1); }; } } } void free(tlm::tlm_generic_payload* trans) { mm_end_event_ext* ext = trans->template get_extension<mm_end_event_ext>(); assert(ext); // notif event first before freeing extensions (reset) ext->done.notify(); trans->reset(); } private: struct mm_end_event_ext : public tlm::tlm_extension<mm_end_event_ext> { tlm::tlm_extension_base* clone() const { return NULL; } void free() {} void copy_from(tlm::tlm_extension_base const &) {} sc_core::sc_event done; }; private: const std::string m_name; simple_target_socket_tagged *m_owner; MODULE* m_mod; NBTransportPtr m_nb_transport_ptr; BTransportPtr m_b_transport_ptr; TransportDbgPtr m_transport_dbg_ptr; GetDirectMemPtr m_get_direct_mem_ptr; int m_nb_transport_user_id; int m_b_transport_user_id; int m_transport_dbg_user_id; int m_get_dmi_user_id; peq_with_get<transaction_type> m_peq; bool m_response_in_progress; sc_core::sc_event m_end_response; };private: fw_process m_fw_process; bw_process m_bw_process; std::map<transaction_type*, sc_core::sc_event *> m_pending_trans; sc_core::sc_event m_end_request; transaction_type* m_current_transaction;};}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -