43 using transaction_type =
typename TYPES::tlm_payload_type;
44 using phase_type =
typename TYPES::tlm_phase_type;
45 using sync_enum_type = tlm::tlm_sync_enum;
54 :
target_mixin(sc_core::sc_gen_unique_name(
"target_mixin_socket")) {}
64 , m_current_transaction(nullptr) {
68 using BASE_TYPE::bind;
81 assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
82 m_fw_process.set_nb_transport_ptr(cb);
90 assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
91 m_fw_process.set_b_transport_ptr(cb);
98 assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
99 m_fw_process.set_transport_dbg_ptr(cb);
107 assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
108 m_fw_process.set_get_direct_mem_ptr(cb);
113 sync_enum_type bw_nb_transport(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) {
114 return BASE_TYPE::operator->()->nb_transport_bw(trans, phase, t);
124 sync_enum_type nb_transport_bw(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) {
125 typename std::map<transaction_type*, sc_core::sc_event*>::iterator it;
127 it = m_owner->m_pending_trans.find(&trans);
128 if(it == m_owner->m_pending_trans.end()) {
130 return m_owner->bw_nb_transport(trans, phase, t);
133 if(phase == tlm::nw::CONFIRM || phase == tlm::nw::RESPONSE) {
134 m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME);
135 return tlm::TLM_ACCEPTED;
147 class fw_process :
public tlm::nw::tlm_network_fw_transport_if<TYPES>,
public tlm::nw::tlm_base_mm_interface {
149 using NBTransportPtr = std::function<sync_enum_type(transaction_type&, phase_type&, sc_core::sc_time&)>;
150 using BTransportPtr = std::function<void(transaction_type&, sc_core::sc_time&)>;
151 using TransportDbgPtr = std::function<
unsigned int(transaction_type&)>;
152 using GetDirectMemPtr = std::function<bool(transaction_type&, tlm::tlm_dmi&)>;
155 : m_name(p_own->name())
157 , m_nb_transport_ptr(0)
158 , m_b_transport_ptr(0)
159 , m_transport_dbg_ptr(0)
160 , m_get_direct_mem_ptr(0)
161 , m_peq(sc_core::sc_gen_unique_name(
"m_peq")) {
162 sc_core::sc_spawn_options opts;
163 opts.set_sensitivity(&m_peq.get_event());
164 sc_core::sc_spawn(sc_bind(&fw_process::b2nb_thread,
this), sc_core::sc_gen_unique_name(
"b2nb_thread"), &opts);
167 void set_nb_transport_ptr(NBTransportPtr p) {
168 if(m_nb_transport_ptr) {
170 s << m_name <<
": non-blocking callback allready registered";
171 SC_REPORT_WARNING(
"/OSCI_TLM-2/simple_socket", s.str().c_str());
173 m_nb_transport_ptr = p;
177 void set_b_transport_ptr(BTransportPtr p) {
178 if(m_b_transport_ptr) {
180 s << m_name <<
": blocking callback allready registered";
181 SC_REPORT_WARNING(
"/OSCI_TLM-2/simple_socket", s.str().c_str());
183 m_b_transport_ptr = p;
187 void set_transport_dbg_ptr(TransportDbgPtr p) {
188 if(m_transport_dbg_ptr) {
190 s << m_name <<
": debug callback allready registered";
191 SC_REPORT_WARNING(
"/OSCI_TLM-2/simple_socket", s.str().c_str());
193 m_transport_dbg_ptr = p;
197 void set_get_direct_mem_ptr(GetDirectMemPtr p) {
198 if(m_get_direct_mem_ptr) {
200 s << m_name <<
": get DMI pointer callback allready registered";
201 SC_REPORT_WARNING(
"/OSCI_TLM-2/simple_socket", s.str().c_str());
203 m_get_direct_mem_ptr = p;
207 sync_enum_type nb_transport_fw(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) {
208 if(m_nb_transport_ptr) {
210 return m_nb_transport_ptr(trans, phase, t);
211 }
else if(m_b_transport_ptr) {
212 if(phase == tlm::nw::REQUEST || phase == tlm::nw::INDICATION) {
214 process_handle_class* ph = m_process_handle.get_handle(&trans, phase);
217 ph =
new process_handle_class(&trans, phase);
218 m_process_handle.put_handle(ph);
220 sc_core::sc_spawn_options opts;
221 opts.dont_initialize();
222 opts.set_sensitivity(&ph->m_e);
223 sc_core::sc_spawn(sc_bind(&fw_process::nb2b_thread,
this, ph), sc_core::sc_gen_unique_name(
"nb2b_thread"), &opts);
226 return tlm::TLM_ACCEPTED;
233 s << m_name <<
": no non-blocking transport callback registered";
234 SC_REPORT_ERROR(
"/OSCI_TLM-2/simple_socket", s.str().c_str());
236 return tlm::TLM_ACCEPTED;
239 void b_transport(transaction_type& trans, sc_core::sc_time& t) {
240 if(m_b_transport_ptr) {
242 m_b_transport_ptr(trans, t);
245 }
else if(m_nb_transport_ptr) {
246 m_peq.notify(trans, t);
247 t = sc_core::SC_ZERO_TIME;
249 mm_end_event_ext mm_ext;
250 const bool mm_added = !trans.has_mm();
254 trans.set_auto_extension(&mm_ext);
259 sc_core::sc_event end_event;
260 m_owner->m_pending_trans[&trans] = &end_event;
261 sc_core::wait(end_event);
266 if(trans.get_ref_count()) {
267 sc_core::wait(mm_ext.done);
274 s << m_name <<
": no blocking transport callback registered";
275 SC_REPORT_ERROR(
"/OSCI_TLM-2/simple_socket", s.str().c_str());
279 unsigned int transport_dbg(transaction_type& trans) {
280 if(m_transport_dbg_ptr) {
282 return m_transport_dbg_ptr(trans);
289 bool get_direct_mem_ptr(transaction_type& trans, tlm::tlm_dmi& dmi_data) {
290 if(m_get_direct_mem_ptr) {
292 return m_get_direct_mem_ptr(trans, dmi_data);
296 dmi_data.allow_read_write();
297 dmi_data.set_start_address(0x0);
298 dmi_data.set_end_address((sc_dt::uint64)-1);
306 class process_handle_class {
308 explicit process_handle_class(transaction_type* trans, phase_type phase)
311 , m_suspend(false) {}
313 transaction_type* m_trans;
315 sc_core::sc_event m_e;
319 class process_handle_list {
321 process_handle_list() =
default;
323 ~process_handle_list() {
324 for(
typename std::vector<process_handle_class*>::iterator it = v.begin(), end = v.end(); it != end; ++it)
328 process_handle_class* get_handle(transaction_type* trans, phase_type phase) {
329 typename std::vector<process_handle_class*>::iterator it;
331 for(it = v.begin(); it != v.end(); it++) {
332 if((*it)->m_suspend) {
333 (*it)->m_trans = trans;
334 (*it)->m_phase = phase;
335 (*it)->m_suspend =
false;
342 void put_handle(process_handle_class* ph) { v.push_back(ph); }
345 std::vector<process_handle_class*> v;
348 process_handle_list m_process_handle;
350 void nb2b_thread(process_handle_class* h) {
352 transaction_type* trans = h->m_trans;
353 sc_core::sc_time t = sc_core::SC_ZERO_TIME;
355 m_b_transport_ptr(*trans, t);
357 t = sc_core::SC_ZERO_TIME;
358 phase_type phase = tlm::nw::RESPONSE;
359 if(h->m_phase == tlm::nw::REQUEST)
360 phase = tlm::nw::CONFIRM;
361 sync_enum_type sync = m_owner->bw_nb_transport(*trans, phase, t);
370 sc_core::wait(m_peq.get_event());
371 transaction_type* trans;
372 while((trans = m_peq.get_next_transaction()) != 0) {
373 assert(m_nb_transport_ptr);
374 phase_type phase = tlm::nw::REQUEST;
376 phase = tlm::nw::INDICATION;
377 sc_core::sc_time t = sc_core::SC_ZERO_TIME;
379 switch(m_nb_transport_ptr(*trans, phase, t)) {
380 case tlm::TLM_COMPLETED: {
381 assert(phase == tlm::nw::CONFIRM || phase == tlm::nw::RESPONSE);
383 typename std::map<transaction_type*, sc_core::sc_event*>::iterator it = m_owner->m_pending_trans.find(trans);
384 assert(it != m_owner->m_pending_trans.end());
385 it->second->notify(t);
386 m_owner->m_pending_trans.erase(it);
389 case tlm::TLM_ACCEPTED:
390 case tlm::TLM_UPDATED:
391 if(phase == tlm::nw::REQUEST || phase == tlm::nw::INDICATION) {
392 m_owner->m_current_transaction = trans;
393 sc_core::wait(m_owner->m_end_request);
394 m_owner->m_current_transaction = 0;
395 }
else if(phase == tlm::nw::CONFIRM || phase == tlm::nw::RESPONSE) {
398 assert(
false &&
"Illegal phase received");
401 assert(
false &&
"Illegate sync enum received");
408 void free(tlm::nw::tlm_network_payload_base* trans) {
409 mm_end_event_ext* ext = trans->template get_extension<mm_end_event_ext>();
417 class mm_end_event_ext :
public tlm::tlm_extension<mm_end_event_ext> {
419 tlm::tlm_extension_base* clone()
const {
return NULL; }
421 void copy_from(tlm::tlm_extension_base
const&) {}
422 sc_core::sc_event done;
425 const std::string m_name;
427 NBTransportPtr m_nb_transport_ptr;
428 BTransportPtr m_b_transport_ptr;
429 TransportDbgPtr m_transport_dbg_ptr;
430 GetDirectMemPtr m_get_direct_mem_ptr;
431 tlm_utils::peq_with_get<transaction_type> m_peq;
435 fw_process m_fw_process;
436 bw_process m_bw_process;
437 std::map<transaction_type*, sc_core::sc_event*> m_pending_trans;
438 sc_core::sc_event m_end_request;
439 transaction_type* m_current_transaction;