gem5  v19.0.0.0
simple_target_socket.h
Go to the documentation of this file.
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 __SYSTEMC_EXT_TLM_UTILS_SIMPLE_TARGET_SOCKET_H__
21 #define __SYSTEMC_EXT_TLM_UTILS_SIMPLE_TARGET_SOCKET_H__
22 
23 #include "../core/sc_event.hh"
24 #include "../core/sc_module.hh"
25 #include "../core/sc_port.hh"
26 #include "../core/sc_spawn.hh"
27 #include "../tlm_core/2/generic_payload/gp.hh"
28 #include "../tlm_core/2/interfaces/fw_bw_ifs.hh"
29 #include "../tlm_core/2/sockets/initiator_socket.hh"
30 #include "../tlm_core/2/sockets/target_socket.hh"
31 #include "../utils/sc_report_handler.hh"
33 #include "peq_with_get.h"
34 
35 namespace tlm_utils
36 {
37 
38 template <typename MODULE, unsigned int BUSWIDTH, typename TYPES,
41  public tlm::tlm_target_socket<BUSWIDTH, TYPES, 1, POL>,
42  protected simple_socket_base
43 {
44  friend class fw_process;
45  friend class bw_process;
46  public:
47  typedef typename TYPES::tlm_payload_type transaction_type;
48  typedef typename TYPES::tlm_phase_type phase_type;
53 
54  public:
55  static const char *
57  {
58  return sc_core::sc_gen_unique_name("simple_target_socket");
59  }
60 
61  explicit simple_target_socket_b(const char *n=default_name()) :
62  base_type(n), m_fw_process(this), m_bw_process(this)
63  {
65  }
66 
67  using base_type::bind;
68 
69  // bw transport must come through us.
71 
72  // REGISTER_XXX
73  void
75  sync_enum_type (MODULE::*cb)(
76  transaction_type &, phase_type &, sc_core::sc_time &))
77  {
78  elaboration_check("register_nb_transport_fw");
80  }
81 
82  void
83  register_b_transport(MODULE *mod,
84  void (MODULE::*cb)(transaction_type &, sc_core::sc_time &))
85  {
86  elaboration_check("register_b_transport");
88  }
89 
90  void
92  unsigned int (MODULE::*cb)(transaction_type &))
93  {
94  elaboration_check("register_transport_dbg");
96  }
97 
98  void
100  bool (MODULE::*cb)(transaction_type &, tlm::tlm_dmi &))
101  {
102  elaboration_check("register_get_direct_mem_ptr");
104  }
105 
106  protected:
107  void
109  {
112  }
113 
114  private:
115  // Make call on bw path.
116  sync_enum_type
117  bw_nb_transport(transaction_type &trans, phase_type &phase,
119  {
120  return base_type::operator -> ()->nb_transport_bw(trans, phase, t);
121  }
122 
123  void
125  {
127  }
128 
129  // Helper class to handle bw path calls Needed to detect transaction end
130  // when called from b_transport.
131  class bw_process : public tlm::tlm_bw_transport_if<TYPES>
132  {
133  public:
135 
136  sync_enum_type
137  nb_transport_bw(transaction_type &trans, phase_type &phase,
139  {
140  typename std::map<transaction_type *,
141  sc_core::sc_event *>::iterator it =
142  m_owner->m_pending_trans.find(&trans);
143 
144  if (it == m_owner->m_pending_trans.end()) {
145  // Not a blocking call, forward.
146  return m_owner->bw_nb_transport(trans, phase, t);
147 
148  }
149 
150  if (phase == tlm::END_REQ) {
152  return tlm::TLM_ACCEPTED;
153  }
154  if (phase == tlm::BEGIN_RESP) {
155  if (m_owner->m_current_transaction == &trans) {
157  }
158  it->second->notify(t);
159  m_owner->m_pending_trans.erase(it);
160  return tlm::TLM_COMPLETED;
161  }
162  m_owner->display_error("invalid phase received");
163  return tlm::TLM_COMPLETED;
164  }
165 
166  void
168  {
170  }
171 
172  private:
174  };
175 
176  class fw_process : public tlm::tlm_fw_transport_if<TYPES>,
177  public tlm::tlm_mm_interface
178  {
179  public:
180  typedef sync_enum_type (MODULE::*NBTransportPtr)(
181  transaction_type &, phase_type &, sc_core::sc_time &);
182  typedef void (MODULE::*BTransportPtr)(
183  transaction_type &, sc_core::sc_time &);
184  typedef unsigned int (MODULE::*TransportDbgPtr)(transaction_type &);
185  typedef bool (MODULE::*GetDirectMemPtr)(
186  transaction_type &, tlm::tlm_dmi &);
187 
189  m_owner(p_own), m_mod(0), m_nb_transport_ptr(0),
190  m_b_transport_ptr(0), m_transport_dbg_ptr(0),
191  m_get_direct_mem_ptr(0),
192  m_peq(sc_core::sc_gen_unique_name("m_peq")),
193  m_response_in_progress(false)
194  {}
195 
196  void
198  {
199  // Only spawn b2nb_thread, if needed.
200  if (!m_b_transport_ptr && m_nb_transport_ptr) {
202  opts.set_sensitivity(&m_peq.get_event());
203  opts.dont_initialize();
205  sc_core::sc_gen_unique_name("b2nb_thread"), &opts);
206  }
207  }
208 
209  void
210  set_nb_transport_ptr(MODULE *mod, NBTransportPtr p)
211  {
212  if (m_nb_transport_ptr) {
214  "non-blocking callback already registered");
215  return;
216  }
217  sc_assert(!m_mod || m_mod == mod);
218  m_mod = mod;
219  m_nb_transport_ptr = p;
220  }
221 
222  void
223  set_b_transport_ptr(MODULE *mod, BTransportPtr p)
224  {
225  if (m_b_transport_ptr) {
227  "blocking callback already registered");
228  return;
229  }
230  sc_assert(!m_mod || m_mod == mod);
231  m_mod = mod;
232  m_b_transport_ptr = p;
233  }
234 
235  void
236  set_transport_dbg_ptr(MODULE *mod, TransportDbgPtr p)
237  {
238  if (m_transport_dbg_ptr) {
239  m_owner->display_warning("debug callback already registered");
240  return;
241  }
242  sc_assert(!m_mod || m_mod == mod);
243  m_mod = mod;
244  m_transport_dbg_ptr = p;
245  }
246 
247  void
248  set_get_direct_mem_ptr(MODULE *mod, GetDirectMemPtr p)
249  {
250  if (m_get_direct_mem_ptr) {
252  "get DMI pointer callback already registered");
253  return;
254  }
255  sc_assert(!m_mod || m_mod == mod);
256  m_mod = mod;
257  m_get_direct_mem_ptr = p;
258  }
259 
260  // Interface implementation.
261  sync_enum_type
262  nb_transport_fw(transaction_type &trans, phase_type &phase,
264  {
265  if (m_nb_transport_ptr) {
266  // Forward call.
267  sc_assert(m_mod);
268  return (m_mod->*m_nb_transport_ptr)(trans, phase, t);
269  }
270 
271  // nb->b conversion
272  if (m_b_transport_ptr) {
273  if (phase == tlm::BEGIN_REQ) {
274  // Prepare thread to do blocking call.
276  m_process_handle.get_handle(&trans);
277 
278  if (!ph) { // Create new dynamic process.
279  ph = new process_handle_class(&trans);
280  m_process_handle.put_handle(ph);
281 
283  opts.dont_initialize();
284  opts.set_sensitivity(&ph->m_e);
285 
287  sc_bind(&fw_process::nb2b_thread, this, ph),
288  sc_core::sc_gen_unique_name("nb2b_thread"),
289  &opts);
290  }
291 
292  ph->m_e.notify(t);
293  return tlm::TLM_ACCEPTED;
294  }
295  if (phase == tlm::END_RESP) {
296  m_response_in_progress = false;
297  m_end_response.notify(t);
298  return tlm::TLM_COMPLETED;
299  }
300  m_owner->display_error("invalid phase received");
301  return tlm::TLM_COMPLETED;
302  }
304  "no non-blocking transport callback registered");
305  return tlm::TLM_COMPLETED;
306  }
307 
308  void
309  b_transport(transaction_type &trans, sc_core::sc_time &t)
310  {
311  if (m_b_transport_ptr) {
312  // Forward call.
313  sc_assert(m_mod);
314  (m_mod->*m_b_transport_ptr)(trans, t);
315  return;
316  }
317 
318  // b->nb conversion
319  if (m_nb_transport_ptr) {
320  m_peq.notify(trans, t);
322 
323  mm_end_event_ext mm_ext;
324  const bool mm_added = !trans.has_mm();
325 
326  if (mm_added) {
327  trans.set_mm(this);
328  trans.set_auto_extension(&mm_ext);
329  trans.acquire();
330  }
331 
332  // Wait until transaction is finished.
333  sc_core::sc_event end_event;
334  m_owner->m_pending_trans[&trans] = &end_event;
335  sc_core::wait(end_event);
336 
337  if (mm_added) {
338  // Release will not delete the transaction, it will
339  // notify mm_ext.done.
340  trans.release();
341  if (trans.get_ref_count()) {
342  sc_core::wait(mm_ext.done);
343  }
344  trans.set_mm(0);
345  }
346  return;
347  }
348 
349  // Should not be reached.
351  "no blocking transport callback registered");
352  }
353 
354  unsigned int
355  transport_dbg(transaction_type &trans)
356  {
357  if (m_transport_dbg_ptr) {
358  // Forward call.
359  sc_assert(m_mod);
360  return (m_mod->*m_transport_dbg_ptr)(trans);
361  }
362  // No debug support.
363  return 0;
364  }
365 
366  bool
367  get_direct_mem_ptr(transaction_type &trans, tlm::tlm_dmi &dmi_data)
368  {
369  if (m_get_direct_mem_ptr) {
370  // Forward call.
371  sc_assert(m_mod);
372  return (m_mod->*m_get_direct_mem_ptr)(trans, dmi_data);
373  }
374  // No DMI support.
375  dmi_data.allow_read_write();
376  dmi_data.set_start_address(0x0);
377  dmi_data.set_end_address((sc_dt::uint64)-1);
378  return false;
379  }
380 
381  private:
382 
383  // Dynamic process handler for nb2b conversion.
384 
386  {
387  public:
388  explicit process_handle_class(transaction_type *trans) :
389  m_trans(trans), m_suspend(false)
390  {}
391 
392  transaction_type *m_trans;
394  bool m_suspend;
395  };
396 
398  {
399  public:
401 
403  {
404  for (typename std::vector<
405  process_handle_class *>::iterator it = v.begin(),
406  end = v.end(); it != end; ++it) {
407  delete *it;
408  }
409  }
410 
412  get_handle(transaction_type *trans)
413  {
415 
416  for (it = v.begin(); it != v.end(); it++) {
417  if ((*it)->m_suspend) {
418  // Found suspended dynamic process, re-use it.
419  (*it)->m_trans = trans; // Replace to new one.
420  (*it)->m_suspend = false;
421  return *it;
422  }
423  }
424  return NULL; // No suspended process.
425  }
426 
427  void
429  {
430  v.push_back(ph);
431  }
432 
433  private:
435  };
436 
438 
439  void
441  {
442  while (1) {
443  transaction_type *trans = h->m_trans;
445 
446  // Forward call.
447  sc_assert(m_mod);
448  (m_mod->*m_b_transport_ptr)(*trans, t);
449 
450  sc_core::wait(t);
451 
452  // Return path.
453  while (m_response_in_progress) {
454  sc_core::wait(m_end_response);
455  }
457  phase_type phase = tlm::BEGIN_RESP;
458  sync_enum_type sync =
459  m_owner->bw_nb_transport(*trans, phase, t);
460  if (!(sync == tlm::TLM_COMPLETED ||
461  (sync == tlm::TLM_UPDATED &&
462  phase == tlm::END_RESP))) {
463  m_response_in_progress = true;
464  }
465 
466  // Suspend until next transaction.
467  h->m_suspend = true;
468  sc_core::wait();
469  }
470  }
471 
472  void
474  {
475  while (true) {
476  transaction_type *trans;
477  while ((trans = m_peq.get_next_transaction()) != 0) {
478  sc_assert(m_mod);
479  sc_assert(m_nb_transport_ptr);
480  phase_type phase = tlm::BEGIN_REQ;
482 
483  switch ((m_mod->*m_nb_transport_ptr)(*trans, phase, t)) {
484  case tlm::TLM_COMPLETED:
485  {
486  // Notify transaction is finished.
487  typename std::map<transaction_type *,
488  sc_core::sc_event *>::iterator it =
489  m_owner->m_pending_trans.find(trans);
490  sc_assert(it != m_owner->m_pending_trans.end());
491  it->second->notify(t);
492  m_owner->m_pending_trans.erase(it);
493  break;
494  }
495 
496  case tlm::TLM_ACCEPTED:
497  case tlm::TLM_UPDATED:
498  switch (phase) {
499  case tlm::BEGIN_REQ:
503  break;
504 
505  case tlm::END_REQ:
506  sc_core::wait(t);
507  break;
508 
509  case tlm::BEGIN_RESP:
510  {
511  phase = tlm::END_RESP;
512  // This line is a bug fix added in TLM-2.0.2
513  sc_core::wait(t);
515  (m_mod->*m_nb_transport_ptr)(
516  *trans, phase, t);
517 
518  // Notify transaction is finished.
519  typename std::map<transaction_type *,
520  sc_core::sc_event *>::iterator it =
521  m_owner->m_pending_trans.find(
522  trans);
523  sc_assert(it !=
524  m_owner->m_pending_trans.end());
525  it->second->notify(t);
526  m_owner->m_pending_trans.erase(it);
527  break;
528  }
529 
530  default:
531  m_owner->display_error("invalid phase received");
532  }
533  break;
534 
535  default:
536  m_owner->display_error("invalid sync value received");
537  }
538  }
539  sc_core::wait();
540  }
541  }
542 
543  void
545  {
547  trans->template get_extension<mm_end_event_ext>();
548  sc_assert(ext);
549  // Notify event first before freeing extensions (reset).
550  ext->done.notify();
551  trans->reset();
552  }
553 
554  private:
555  struct mm_end_event_ext : public tlm::tlm_extension<mm_end_event_ext>
556  {
557  tlm::tlm_extension_base *clone() const { return NULL; }
558  void free() {}
561  };
562 
563  private:
565  MODULE *m_mod;
566  NBTransportPtr m_nb_transport_ptr;
567  BTransportPtr m_b_transport_ptr;
568  TransportDbgPtr m_transport_dbg_ptr;
569  GetDirectMemPtr m_get_direct_mem_ptr;
573  };
574 
575  private:
576  const sc_core::sc_object *get_socket() const { return this; }
577 
578  private:
581  std::map<transaction_type *, sc_core::sc_event *> m_pending_trans;
583  transaction_type* m_current_transaction;
584 };
585 
586 template <typename MODULE, unsigned int BUSWIDTH=32,
587  typename TYPES=tlm::tlm_base_protocol_types>
589  public simple_target_socket_b<MODULE, BUSWIDTH, TYPES>
590 {
592  public:
593  simple_target_socket() : socket_b() {}
594  explicit simple_target_socket(const char *name) : socket_b(name) {}
595 };
596 
597 template <typename MODULE, unsigned int BUSWIDTH=32,
598  typename TYPES=tlm::tlm_base_protocol_types>
600  public simple_target_socket_b<MODULE, BUSWIDTH, TYPES,
601  sc_core::SC_ZERO_OR_MORE_BOUND>
602 {
603  typedef simple_target_socket_b<MODULE, BUSWIDTH, TYPES,
605  public:
607  explicit simple_target_socket_optional(const char *name) :
608  socket_b(name)
609  {}
610 };
611 
612 // ID Tagged version.
613 template <typename MODULE, unsigned int BUSWIDTH, typename TYPES,
616  public tlm::tlm_target_socket<BUSWIDTH, TYPES, 1, POL>,
617  protected simple_socket_base
618 {
619  friend class fw_process;
620  friend class bw_process;
621  public:
622  typedef typename TYPES::tlm_payload_type transaction_type;
623  typedef typename TYPES::tlm_phase_type phase_type;
628 
629  public:
630  static const char *
632  {
633  return sc_core::sc_gen_unique_name("simple_target_socket_tagged");
634  }
635 
636  explicit simple_target_socket_tagged_b(const char *n=default_name()) :
637  base_type(n), m_fw_process(this), m_bw_process(this)
638  {
640  }
641 
642  using base_type::bind;
643 
644  // bw transport must come through us.
646 
647  // REGISTER_XXX
648  void
650  sync_enum_type (MODULE::*cb)(int id, transaction_type &,
651  phase_type &, sc_core::sc_time &),
652  int id)
653  {
654  elaboration_check("register_nb_transport_fw");
656  m_fw_process.set_nb_transport_user_id(id);
657  }
658 
659  void
660  register_b_transport(MODULE *mod,
661  void (MODULE::*cb)(int id, transaction_type &,
662  sc_core::sc_time &),
663  int id)
664  {
665  elaboration_check("register_b_transport");
667  m_fw_process.set_b_transport_user_id(id);
668  }
669 
670  void
672  unsigned int (MODULE::*cb)(int id, transaction_type &), int id)
673  {
674  elaboration_check("register_transport_dbg");
676  m_fw_process.set_transport_dbg_user_id(id);
677  }
678 
679  void
681  bool (MODULE::*cb)(int id, transaction_type &, tlm::tlm_dmi &),
682  int id)
683  {
684  elaboration_check("register_get_direct_mem_ptr");
686  m_fw_process.set_get_dmi_user_id(id);
687  }
688 
689  protected:
690  void
692  {
695  }
696 
697  private:
698  // Make call on bw path.
699  sync_enum_type
700  bw_nb_transport(transaction_type &trans, phase_type &phase,
702  {
703  return base_type::operator -> ()->nb_transport_bw(trans, phase, t);
704  }
705 
706  void
708  {
710  }
711 
712  // Helper class to handle bw path calls Needed to detect transaction
713  // end when called from b_transport.
714  class bw_process : public tlm::tlm_bw_transport_if<TYPES>
715  {
716  public:
718 
719  sync_enum_type
720  nb_transport_bw(transaction_type &trans, phase_type &phase,
722  {
723  typename std::map<transaction_type *,
724  sc_core::sc_event *>::iterator it =
725  m_owner->m_pending_trans.find(&trans);
726 
727  if (it == m_owner->m_pending_trans.end()) {
728  // Not a blocking call, forward.
729  return m_owner->bw_nb_transport(trans, phase, t);
730  }
731  if (phase == tlm::END_REQ) {
733  return tlm::TLM_ACCEPTED;
734  }
735  if (phase == tlm::BEGIN_RESP) {
736  if (m_owner->m_current_transaction == &trans) {
738  }
739  it->second->notify(t);
740  m_owner->m_pending_trans.erase(it);
741  return tlm::TLM_COMPLETED;
742  }
743  m_owner->display_error("invalid phase received");
744  return tlm::TLM_COMPLETED;
745  }
746 
747  void
749  {
751  }
752 
753  private:
755  };
756 
757  class fw_process : public tlm::tlm_fw_transport_if<TYPES>,
758  public tlm::tlm_mm_interface
759  {
760  public:
761  typedef sync_enum_type (MODULE::*NBTransportPtr)(
762  int id, transaction_type &, phase_type &,
763  sc_core::sc_time &);
764  typedef void (MODULE::*BTransportPtr)(
765  int id, transaction_type &, sc_core::sc_time &);
766  typedef unsigned int (MODULE::*TransportDbgPtr)(
767  int id, transaction_type &);
768  typedef bool (MODULE::*GetDirectMemPtr)(
769  int id, transaction_type &, tlm::tlm_dmi &);
770 
772  m_owner(p_own), m_mod(0), m_nb_transport_ptr(0),
773  m_b_transport_ptr(0), m_transport_dbg_ptr(0),
774  m_get_direct_mem_ptr(0), m_nb_transport_user_id(0),
775  m_b_transport_user_id(0), m_transport_dbg_user_id(0),
776  m_get_dmi_user_id(0),
777  m_peq(sc_core::sc_gen_unique_name("m_peq")),
778  m_response_in_progress(false)
779  {}
780 
781  void
783  {
784  if (!m_b_transport_ptr && m_nb_transport_ptr) {
785  // Only spawn b2nb_thread if needed.
787  opts.set_sensitivity(&m_peq.get_event());
788  opts.dont_initialize();
790  sc_core::sc_gen_unique_name("b2nb_thread"), &opts);
791  }
792  }
793 
794  void set_nb_transport_user_id(int id) { m_nb_transport_user_id = id; }
795  void set_b_transport_user_id(int id) { m_b_transport_user_id = id; }
796  void
798  {
799  m_transport_dbg_user_id = id;
800  }
801  void set_get_dmi_user_id(int id) { m_get_dmi_user_id = id; }
802 
803  void
804  set_nb_transport_ptr(MODULE *mod, NBTransportPtr p)
805  {
806  if (m_nb_transport_ptr) {
808  "non-blocking callback already registered");
809  return;
810  }
811  sc_assert(!m_mod || m_mod == mod);
812  m_mod = mod;
813  m_nb_transport_ptr = p;
814  }
815 
816  void
817  set_b_transport_ptr(MODULE* mod, BTransportPtr p)
818  {
819  if (m_b_transport_ptr) {
821  "blocking callback already registered");
822  return;
823  }
824  sc_assert(!m_mod || m_mod == mod);
825  m_mod = mod;
826  m_b_transport_ptr = p;
827  }
828 
829  void
830  set_transport_dbg_ptr(MODULE *mod, TransportDbgPtr p)
831  {
832  if (m_transport_dbg_ptr) {
834  "debug callback already registered");
835  return;
836  }
837  sc_assert(!m_mod || m_mod == mod);
838  m_mod = mod;
839  m_transport_dbg_ptr = p;
840  }
841 
842  void
843  set_get_direct_mem_ptr(MODULE *mod, GetDirectMemPtr p)
844  {
845  if (m_get_direct_mem_ptr) {
847  "get DMI pointer callback already registered");
848  }
849  sc_assert(!m_mod || m_mod == mod);
850  m_mod = mod;
851  m_get_direct_mem_ptr = p;
852  }
853 
854  // Interface implementation.
855  sync_enum_type
856  nb_transport_fw(transaction_type &trans, phase_type &phase,
858  {
859  if (m_nb_transport_ptr) {
860  // Forward call.
861  sc_assert(m_mod);
862  return (m_mod->*m_nb_transport_ptr)(
863  m_nb_transport_user_id, trans, phase, t);
864  }
865 
866  // nb->b conversion
867  if (m_b_transport_ptr) {
868  if (phase == tlm::BEGIN_REQ) {
869 
870  // Prepare thread to do blocking call.
872  m_process_handle.get_handle(&trans);
873 
874  if (!ph) { // Create new dynamic process.
875  ph = new process_handle_class(&trans);
876  m_process_handle.put_handle(ph);
877 
879  opts.dont_initialize();
880  opts.set_sensitivity(&ph->m_e);
881 
883  sc_bind(&fw_process::nb2b_thread, this, ph),
884  sc_core::sc_gen_unique_name("nb2b_thread"),
885  &opts);
886  }
887 
888  ph->m_e.notify(t);
889  return tlm::TLM_ACCEPTED;
890  }
891  if (phase == tlm::END_RESP) {
892  m_response_in_progress = false;
893  m_end_response.notify(t);
894  return tlm::TLM_COMPLETED;
895  }
896  m_owner->display_error("invalid phase");
897  return tlm::TLM_COMPLETED;
898  }
899 
901  "no non-blocking transport callback registered");
902  return tlm::TLM_COMPLETED;
903  }
904 
905  void
906  b_transport(transaction_type &trans, sc_core::sc_time &t)
907  {
908  if (m_b_transport_ptr) {
909  // Forward call.
910  sc_assert(m_mod);
911  (m_mod->*m_b_transport_ptr)(m_b_transport_user_id, trans, t);
912  return;
913  }
914 
915  // b->nb conversion
916  if (m_nb_transport_ptr) {
917  m_peq.notify(trans, t);
919 
920  mm_end_event_ext mm_ext;
921  const bool mm_added = !trans.has_mm();
922 
923  if (mm_added) {
924  trans.set_mm(this);
925  trans.set_auto_extension(&mm_ext);
926  trans.acquire();
927  }
928 
929  // Wait until transaction is finished.
930  sc_core::sc_event end_event;
931  m_owner->m_pending_trans[&trans] = &end_event;
932  sc_core::wait(end_event);
933 
934  if (mm_added) {
935  // Release will not delete the transaction, it will
936  // notify mm_ext.done.
937  trans.release();
938  if (trans.get_ref_count()) {
939  sc_core::wait(mm_ext.done);
940  }
941  trans.set_mm(0);
942  }
943  return;
944  }
945 
946  m_owner->display_error("no transport callback registered");
947  }
948 
949  unsigned int
950  transport_dbg(transaction_type &trans)
951  {
952  if (m_transport_dbg_ptr) {
953  // Forward call.
954  sc_assert(m_mod);
955  return (m_mod->*m_transport_dbg_ptr)(
956  m_transport_dbg_user_id, trans);
957  }
958  // No debug support.
959  return 0;
960  }
961 
962  bool
963  get_direct_mem_ptr(transaction_type &trans, tlm::tlm_dmi &dmi_data)
964  {
965  if (m_get_direct_mem_ptr) {
966  // Forward call.
967  sc_assert(m_mod);
968  return (m_mod->*m_get_direct_mem_ptr)(
969  m_get_dmi_user_id, trans, dmi_data);
970  }
971  // No DMI support.
972  dmi_data.allow_read_write();
973  dmi_data.set_start_address(0x0);
974  dmi_data.set_end_address((sc_dt::uint64)-1);
975  return false;
976  }
977 
978  private:
979 
980  // Dynamic process handler for nb2b conversion.
982  {
983  public:
984  explicit process_handle_class(transaction_type *trans) :
985  m_trans(trans), m_suspend(false)
986  {}
987 
988  transaction_type *m_trans;
990  bool m_suspend;
991  };
992 
994  {
995  public:
997 
999  {
1000  for (typename std::vector<
1001  process_handle_class *>::iterator it = v.begin(),
1002  end = v.end(); it != end; ++it) {
1003  delete *it;
1004  }
1005  }
1006 
1008  get_handle(transaction_type *trans)
1009  {
1011 
1012  for (it = v.begin(); it != v.end(); it++) {
1013  if ((*it)->m_suspend) {
1014  // Found suspended dynamic process, re-use it.
1015  (*it)->m_trans = trans; // Replace to new one.
1016  (*it)->m_suspend = false;
1017  return *it;
1018  }
1019  }
1020  return NULL; // No suspended process.
1021  }
1022 
1023  void put_handle(process_handle_class *ph) { v.push_back(ph); }
1024 
1025  private:
1027  };
1028 
1030 
1031  void
1033  {
1034 
1035  while (1) {
1036  transaction_type *trans = h->m_trans;
1038 
1039  // Forward call.
1040  sc_assert(m_mod);
1041  (m_mod->*m_b_transport_ptr)(
1042  m_b_transport_user_id, *trans, t);
1043 
1044  sc_core::wait(t);
1045 
1046  // Return path.
1047  while (m_response_in_progress) {
1048  sc_core::wait(m_end_response);
1049  }
1051  phase_type phase = tlm::BEGIN_RESP;
1052  sync_enum_type sync =
1053  m_owner->bw_nb_transport(*trans, phase, t);
1054  if (!(sync == tlm::TLM_COMPLETED ||
1055  (sync == tlm::TLM_UPDATED &&
1056  phase == tlm::END_RESP))) {
1057  m_response_in_progress = true;
1058  }
1059 
1060  // Suspend until next transaction.
1061  h->m_suspend = true;
1062  sc_core::wait();
1063  }
1064  }
1065 
1066  void
1068  {
1069  while (true) {
1070  transaction_type *trans;
1071  while ((trans = m_peq.get_next_transaction()) != 0) {
1072  sc_assert(m_mod);
1073  sc_assert(m_nb_transport_ptr);
1074  phase_type phase = tlm::BEGIN_REQ;
1076 
1077  switch ((m_mod->*m_nb_transport_ptr)(
1078  m_nb_transport_user_id, *trans, phase, t)) {
1079  case tlm::TLM_COMPLETED:
1080  {
1081  // Notify transaction is finished.
1082  typename std::map<transaction_type *,
1083  sc_core::sc_event *>::iterator it =
1084  m_owner->m_pending_trans.find(trans);
1085  sc_assert(it != m_owner->m_pending_trans.end());
1086  it->second->notify(t);
1087  m_owner->m_pending_trans.erase(it);
1088  break;
1089  }
1090 
1091  case tlm::TLM_ACCEPTED:
1092  case tlm::TLM_UPDATED:
1093  switch (phase) {
1094  case tlm::BEGIN_REQ:
1095  m_owner->m_current_transaction = trans;
1098  break;
1099 
1100  case tlm::END_REQ:
1101  sc_core::wait(t);
1102  break;
1103 
1104  case tlm::BEGIN_RESP:
1105  {
1106  phase = tlm::END_RESP;
1107  // This line is a bug fix added in TLM-2.0.2.
1108  sc_core::wait(t);
1110  (m_mod->*m_nb_transport_ptr)(
1111  m_nb_transport_user_id,
1112  *trans, phase, t);
1113 
1114  // Notify transaction is finished.
1115  typename std::map<transaction_type *,
1116  sc_core::sc_event *>::iterator it =
1117  m_owner->m_pending_trans.find(
1118  trans);
1119  sc_assert(it !=
1120  m_owner->m_pending_trans.end());
1121  it->second->notify(t);
1122  m_owner->m_pending_trans.erase(it);
1123  break;
1124  }
1125 
1126  default:
1127  m_owner->display_error("invalid phase received");
1128  };
1129  break;
1130 
1131  default:
1132  m_owner->display_error("invalid sync value received");
1133  }
1134  }
1135  sc_core::wait();
1136  }
1137  }
1138 
1139  void
1141  {
1143  trans->template get_extension<mm_end_event_ext>();
1144  sc_assert(ext);
1145  // Notify event first before freeing extensions (reset).
1146  ext->done.notify();
1147  trans->reset();
1148  }
1149 
1150  private:
1151  struct mm_end_event_ext : public tlm::tlm_extension<mm_end_event_ext>
1152  {
1153  tlm::tlm_extension_base *clone() const { return NULL; }
1154  void free() {}
1157  };
1158 
1159  private:
1161  MODULE *m_mod;
1162  NBTransportPtr m_nb_transport_ptr;
1163  BTransportPtr m_b_transport_ptr;
1164  TransportDbgPtr m_transport_dbg_ptr;
1165  GetDirectMemPtr m_get_direct_mem_ptr;
1173  };
1174 
1175  private:
1176  const sc_core::sc_object *get_socket() const { return this; }
1177 
1178  private:
1181  std::map<transaction_type *, sc_core::sc_event *> m_pending_trans;
1183  transaction_type* m_current_transaction;
1184 };
1185 
1186 template <typename MODULE, unsigned int BUSWIDTH=32,
1187  typename TYPES=tlm::tlm_base_protocol_types>
1189  public simple_target_socket_tagged_b<MODULE, BUSWIDTH, TYPES>
1190 {
1192  public:
1194  explicit simple_target_socket_tagged(const char *name) : socket_b(name) {}
1195 };
1196 
1197 template <typename MODULE, unsigned int BUSWIDTH=32,
1198  typename TYPES=tlm::tlm_base_protocol_types>
1200  public simple_target_socket_tagged_b<MODULE, BUSWIDTH, TYPES,
1201  sc_core::SC_ZERO_OR_MORE_BOUND>
1202 {
1204  MODULE, BUSWIDTH, TYPES, sc_core::SC_ZERO_OR_MORE_BOUND> socket_b;
1205  public:
1208  socket_b(name)
1209  {}
1210 };
1211 
1212 } // namespace tlm_utils
1213 
1214 #endif /* __SYSTEMC_EXT_TLM_UTILS_SIMPLE_TARGET_SOCKET_H__ */
void register_b_transport(MODULE *mod, void(MODULE::*cb)(int id, transaction_type &, sc_core::sc_time &), int id)
void bw_invalidate_direct_mem_ptr(sc_dt::uint64 s, sc_dt::uint64 e)
bool get_direct_mem_ptr(transaction_type &trans, tlm::tlm_dmi &dmi_data)
Bitfield< 28 > v
void register_get_direct_mem_ptr(MODULE *mod, bool(MODULE::*cb)(int id, transaction_type &, tlm::tlm_dmi &), int id)
unsigned int transport_dbg(transaction_type &trans)
bw_process(simple_target_socket_tagged_b *p_own)
const sc_core::sc_object * get_socket() const
unsigned int transport_dbg(transaction_type &trans)
fw_process(simple_target_socket_tagged_b *p_own)
void set_start_address(sc_dt::uint64 addr)
Definition: dmi.hh:82
const char * sc_gen_unique_name(const char *seed)
Definition: sc_module.cc:822
TYPES::tlm_payload_type transaction_type
process_handle_class * get_handle(transaction_type *trans)
sc_process_handle sc_spawn(T object, const char *name_p=nullptr, const sc_spawn_options *opt_p=nullptr)
Definition: sc_spawn.hh:156
std::map< transaction_type *, sc_core::sc_event * > m_pending_trans
const char * name() const
Definition: sc_object.cc:46
Bitfield< 12 > ext
tlm::tlm_fw_transport_if< TYPES > fw_interface_type
tlm::tlm_bw_transport_if< TYPES > bw_interface_type
bool get_direct_mem_ptr(transaction_type &trans, tlm::tlm_dmi &dmi_data)
simple_target_socket_tagged_b< MODULE, BUSWIDTH, TYPES > socket_b
void set_get_direct_mem_ptr(MODULE *mod, GetDirectMemPtr p)
STL vector class.
Definition: stl.hh:40
Bitfield< 33 > id
sync_enum_type nb_transport_fw(transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
Bitfield< 31 > n
sync_enum_type nb_transport_fw(transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
void b_transport(transaction_type &trans, sc_core::sc_time &t)
void register_nb_transport_fw(MODULE *mod, sync_enum_type(MODULE::*cb)(int id, transaction_type &, phase_type &, sc_core::sc_time &), int id)
void set_nb_transport_ptr(MODULE *mod, NBTransportPtr p)
void set_nb_transport_ptr(MODULE *mod, NBTransportPtr p)
void b_transport(transaction_type &trans, sc_core::sc_time &t)
Bitfield< 4 > s
virtual tlm_sync_enum nb_transport_bw(TRANS &trans, PHASE &phase, sc_core::sc_time &t)=0
const sc_core::sc_object * get_socket() const
void set_transport_dbg_ptr(MODULE *mod, TransportDbgPtr p)
sync_enum_type nb_transport_bw(transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
void bw_invalidate_direct_mem_ptr(sc_dt::uint64 s, sc_dt::uint64 e)
void set_transport_dbg_ptr(MODULE *mod, TransportDbgPtr p)
simple_target_socket_b(const char *n=default_name())
void display_error(const char *msg) const
int mod(int val, int mod)
tlm::tlm_target_socket< BUSWIDTH, TYPES, 1, POL > base_type
simple_target_socket_b< MODULE, BUSWIDTH, TYPES > socket_b
std::map< transaction_type *, sc_core::sc_event * > m_pending_trans
void register_get_direct_mem_ptr(MODULE *mod, bool(MODULE::*cb)(transaction_type &, tlm::tlm_dmi &))
void set_sensitivity(const sc_event *)
Definition: sc_spawn.cc:148
void invalidate_direct_mem_ptr(sc_dt::uint64 s, sc_dt::uint64 e)
void free(tlm::tlm_generic_payload *trans)
#define sc_assert(expr)
Bitfield< 9 > e
simple_target_socket_tagged_b< MODULE, BUSWIDTH, TYPES, sc_core::SC_ZERO_OR_MORE_BOUND > socket_b
void register_transport_dbg(MODULE *mod, unsigned int(MODULE::*cb)(transaction_type &))
sc_port_policy
Definition: sc_port.hh:69
const sc_time SC_ZERO_TIME
Definition: sc_time.cc:292
sync_enum_type bw_nb_transport(transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
void allow_read_write()
Definition: dmi.hh:90
uint64_t uint64
Definition: sc_nbdefs.hh:172
void set_get_direct_mem_ptr(MODULE *mod, GetDirectMemPtr p)
simple_target_socket_b< MODULE, BUSWIDTH, TYPES, sc_core::SC_ZERO_OR_MORE_BOUND > socket_b
auto sc_bind(F &&f, Args &&...args) -> decltype(std::bind(std::forward< F >(f), std::forward< Args >(args)...))
Definition: sc_spawn.hh:200
tlm::tlm_bw_transport_if< TYPES > bw_interface_type
void register_nb_transport_fw(MODULE *mod, sync_enum_type(MODULE::*cb)(transaction_type &, phase_type &, sc_core::sc_time &))
tlm::tlm_target_socket< BUSWIDTH, TYPES, 1, POL > base_type
void display_warning(const char *msg) const
void wait()
Definition: sc_module.cc:655
tlm::tlm_fw_transport_if< TYPES > fw_interface_type
sync_enum_type bw_nb_transport(transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
void register_transport_dbg(MODULE *mod, unsigned int(MODULE::*cb)(int id, transaction_type &), int id)
simple_target_socket_tagged_b(const char *n=default_name())
tlm_sync_enum
Definition: fw_bw_ifs.hh:31
Bitfield< 5 > t
void set_b_transport_ptr(MODULE *mod, BTransportPtr p)
void register_b_transport(MODULE *mod, void(MODULE::*cb)(transaction_type &, sc_core::sc_time &))
void set_end_address(sc_dt::uint64 addr)
Definition: dmi.hh:83
virtual void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, sc_dt::uint64 end_range)=0
Bitfield< 0 > p
void elaboration_check(const char *action) const
void set_b_transport_ptr(MODULE *mod, BTransportPtr p)
sync_enum_type nb_transport_bw(transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
tlm::tlm_bw_transport_if< TYPES > * operator->()
void invalidate_direct_mem_ptr(sc_dt::uint64 s, sc_dt::uint64 e)

Generated on Fri Feb 28 2020 16:27:04 for gem5 by doxygen 1.8.13