gem5  v22.1.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)(
77  {
78  elaboration_check("register_nb_transport_fw");
80  }
81 
82  void
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.
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 
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) {
151  m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME);
152  return tlm::TLM_ACCEPTED;
153  }
154  if (phase == tlm::BEGIN_RESP) {
155  if (m_owner->m_current_transaction == &trans) {
156  m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME);
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  {
169  return m_owner->bw_invalidate_direct_mem_ptr(s, e);
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)(
182  typedef void (MODULE::*BTransportPtr)(
184  typedef unsigned int (MODULE::*TransportDbgPtr)(transaction_type &);
185  typedef bool (MODULE::*GetDirectMemPtr)(
187 
189  m_owner(p_own), m_mod(0), m_nb_transport_ptr(0),
192  m_peq(sc_core::sc_gen_unique_name("m_peq")),
194  {}
195 
196  void
198  {
199  // Only spawn b2nb_thread, if needed.
203  opts.dont_initialize();
205  sc_core::sc_gen_unique_name("b2nb_thread"), &opts);
206  }
207  }
208 
209  void
211  {
212  if (m_nb_transport_ptr) {
213  m_owner->display_warning(
214  "non-blocking callback already registered");
215  return;
216  }
217  sc_assert(!m_mod || m_mod == mod);
218  m_mod = mod;
220  }
221 
222  void
224  {
225  if (m_b_transport_ptr) {
226  m_owner->display_warning(
227  "blocking callback already registered");
228  return;
229  }
230  sc_assert(!m_mod || m_mod == mod);
231  m_mod = mod;
233  }
234 
235  void
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;
245  }
246 
247  void
249  {
250  if (m_get_direct_mem_ptr) {
251  m_owner->display_warning(
252  "get DMI pointer callback already registered");
253  return;
254  }
255  sc_assert(!m_mod || m_mod == mod);
256  m_mod = mod;
258  }
259 
260  // Interface implementation.
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.
277 
278  if (!ph) { // Create new dynamic process.
279  ph = new process_handle_class(&trans);
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;
298  return tlm::TLM_COMPLETED;
299  }
300  m_owner->display_error("invalid phase received");
301  return tlm::TLM_COMPLETED;
302  }
303  m_owner->display_error(
304  "no non-blocking transport callback registered");
305  return tlm::TLM_COMPLETED;
306  }
307 
308  void
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.
350  m_owner->display_error(
351  "no blocking transport callback registered");
352  }
353 
354  unsigned int
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
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:
389  m_trans(trans), m_suspend(false)
390  {}
391 
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 
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) {
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);
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:
500  m_owner->m_current_transaction = trans;
501  sc_core::wait(m_owner->m_end_request);
502  m_owner->m_current_transaction = 0;
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);
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;
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;
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:
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 &,
652  int id)
653  {
654  elaboration_check("register_nb_transport_fw");
657  }
658 
659  void
661  void (MODULE::*cb)(int id, transaction_type &,
662  sc_core::sc_time &),
663  int id)
664  {
665  elaboration_check("register_b_transport");
668  }
669 
670  void
672  unsigned int (MODULE::*cb)(int id, transaction_type &), int id)
673  {
674  elaboration_check("register_transport_dbg");
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");
687  }
688 
689  protected:
690  void
692  {
695  }
696 
697  private:
698  // Make call on bw path.
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 
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) {
732  m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME);
733  return tlm::TLM_ACCEPTED;
734  }
735  if (phase == tlm::BEGIN_RESP) {
736  if (m_owner->m_current_transaction == &trans) {
737  m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME);
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  {
750  return m_owner->bw_invalidate_direct_mem_ptr(s, e);
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)(
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),
777  m_peq(sc_core::sc_gen_unique_name("m_peq")),
779  {}
780 
781  void
783  {
785  // Only spawn b2nb_thread if needed.
788  opts.dont_initialize();
790  sc_core::sc_gen_unique_name("b2nb_thread"), &opts);
791  }
792  }
793 
796  void
798  {
800  }
802 
803  void
805  {
806  if (m_nb_transport_ptr) {
807  m_owner->display_warning(
808  "non-blocking callback already registered");
809  return;
810  }
811  sc_assert(!m_mod || m_mod == mod);
812  m_mod = mod;
814  }
815 
816  void
818  {
819  if (m_b_transport_ptr) {
820  m_owner->display_warning(
821  "blocking callback already registered");
822  return;
823  }
824  sc_assert(!m_mod || m_mod == mod);
825  m_mod = mod;
827  }
828 
829  void
831  {
832  if (m_transport_dbg_ptr) {
833  m_owner->display_warning(
834  "debug callback already registered");
835  return;
836  }
837  sc_assert(!m_mod || m_mod == mod);
838  m_mod = mod;
840  }
841 
842  void
844  {
845  if (m_get_direct_mem_ptr) {
846  m_owner->display_warning(
847  "get DMI pointer callback already registered");
848  }
849  sc_assert(!m_mod || m_mod == mod);
850  m_mod = mod;
852  }
853 
854  // Interface implementation.
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.
873 
874  if (!ph) { // Create new dynamic process.
875  ph = new process_handle_class(&trans);
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;
894  return tlm::TLM_COMPLETED;
895  }
896  m_owner->display_error("invalid phase");
897  return tlm::TLM_COMPLETED;
898  }
899 
900  m_owner->display_error(
901  "no non-blocking transport callback registered");
902  return tlm::TLM_COMPLETED;
903  }
904 
905  void
907  {
908  if (m_b_transport_ptr) {
909  // Forward call.
910  sc_assert(m_mod);
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
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
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:
985  m_trans(trans), m_suspend(false)
986  {}
987 
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 
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);
1042  m_b_transport_user_id, *trans, t);
1043 
1044  sc_core::wait(t);
1045 
1046  // Return path.
1047  while (m_response_in_progress) {
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);
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;
1096  sc_core::wait(m_owner->m_end_request);
1097  m_owner->m_current_transaction = 0;
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);
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;
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;
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 start_of_simulation() override
Definition: sc_export.hh:120
const char * name() const
Definition: sc_object.cc:44
void set_sensitivity(const sc_event *)
Definition: sc_spawn.cc:146
STL vector class.
Definition: stl.hh:37
virtual void bind(base_initiator_socket_type &s)
virtual void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, sc_dt::uint64 end_range)=0
virtual tlm_sync_enum nb_transport_bw(TRANS &trans, PHASE &phase, sc_core::sc_time &t)=0
void set_start_address(sc_dt::uint64 addr)
Definition: dmi.hh:82
void set_end_address(sc_dt::uint64 addr)
Definition: dmi.hh:83
void allow_read_write()
Definition: dmi.hh:90
transaction_type * get_next_transaction()
Definition: peq_with_get.h:64
sc_core::sc_event & get_event()
Definition: peq_with_get.h:82
void notify(transaction_type &trans, const sc_core::sc_time &t)
Definition: peq_with_get.h:48
void elaboration_check(const char *action) const
void invalidate_direct_mem_ptr(sc_dt::uint64 s, sc_dt::uint64 e)
sync_enum_type nb_transport_bw(transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
process_handle_class * get_handle(transaction_type *trans)
unsigned int transport_dbg(transaction_type &trans)
void set_get_direct_mem_ptr(MODULE *mod, GetDirectMemPtr p)
void set_transport_dbg_ptr(MODULE *mod, TransportDbgPtr p)
void set_b_transport_ptr(MODULE *mod, BTransportPtr p)
unsigned int(MODULE::* TransportDbgPtr)(transaction_type &)
sync_enum_type(MODULE::* NBTransportPtr)(transaction_type &, phase_type &, sc_core::sc_time &)
sync_enum_type nb_transport_fw(transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
void free(tlm::tlm_generic_payload *trans)
bool(MODULE::* GetDirectMemPtr)(transaction_type &, tlm::tlm_dmi &)
void b_transport(transaction_type &trans, sc_core::sc_time &t)
void set_nb_transport_ptr(MODULE *mod, NBTransportPtr p)
bool get_direct_mem_ptr(transaction_type &trans, tlm::tlm_dmi &dmi_data)
void(MODULE::* BTransportPtr)(transaction_type &, sc_core::sc_time &)
tlm::tlm_bw_transport_if< TYPES > bw_interface_type
simple_target_socket_b(const char *n=default_name())
tlm::tlm_target_socket< BUSWIDTH, TYPES, 1, POL > base_type
TYPES::tlm_payload_type transaction_type
void register_b_transport(MODULE *mod, void(MODULE::*cb)(transaction_type &, sc_core::sc_time &))
void register_nb_transport_fw(MODULE *mod, sync_enum_type(MODULE::*cb)(transaction_type &, phase_type &, sc_core::sc_time &))
void register_get_direct_mem_ptr(MODULE *mod, bool(MODULE::*cb)(transaction_type &, tlm::tlm_dmi &))
tlm::tlm_bw_transport_if< TYPES > * operator->()
const sc_core::sc_object * get_socket() const
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)(transaction_type &))
tlm::tlm_fw_transport_if< TYPES > fw_interface_type
void bw_invalidate_direct_mem_ptr(sc_dt::uint64 s, sc_dt::uint64 e)
std::map< transaction_type *, sc_core::sc_event * > m_pending_trans
simple_target_socket_b< MODULE, BUSWIDTH, TYPES, sc_core::SC_ZERO_OR_MORE_BOUND > socket_b
bw_process(simple_target_socket_tagged_b *p_own)
sync_enum_type nb_transport_bw(transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
void invalidate_direct_mem_ptr(sc_dt::uint64 s, sc_dt::uint64 e)
void set_transport_dbg_ptr(MODULE *mod, TransportDbgPtr p)
void set_get_direct_mem_ptr(MODULE *mod, GetDirectMemPtr p)
void(MODULE::* BTransportPtr)(int id, transaction_type &, sc_core::sc_time &)
void b_transport(transaction_type &trans, sc_core::sc_time &t)
sync_enum_type(MODULE::* NBTransportPtr)(int id, transaction_type &, phase_type &, sc_core::sc_time &)
void set_b_transport_ptr(MODULE *mod, BTransportPtr p)
unsigned int transport_dbg(transaction_type &trans)
fw_process(simple_target_socket_tagged_b *p_own)
sync_enum_type nb_transport_fw(transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
bool get_direct_mem_ptr(transaction_type &trans, tlm::tlm_dmi &dmi_data)
bool(MODULE::* GetDirectMemPtr)(int id, transaction_type &, tlm::tlm_dmi &)
void set_nb_transport_ptr(MODULE *mod, NBTransportPtr p)
unsigned int(MODULE::* TransportDbgPtr)(int id, transaction_type &)
void register_nb_transport_fw(MODULE *mod, sync_enum_type(MODULE::*cb)(int id, transaction_type &, phase_type &, sc_core::sc_time &), int id)
const sc_core::sc_object * get_socket() const
void register_transport_dbg(MODULE *mod, unsigned int(MODULE::*cb)(int id, transaction_type &), int id)
tlm::tlm_target_socket< BUSWIDTH, TYPES, 1, POL > base_type
std::map< transaction_type *, sc_core::sc_event * > m_pending_trans
sync_enum_type bw_nb_transport(transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
tlm::tlm_bw_transport_if< TYPES > bw_interface_type
void register_get_direct_mem_ptr(MODULE *mod, bool(MODULE::*cb)(int id, transaction_type &, tlm::tlm_dmi &), int id)
tlm::tlm_bw_transport_if< TYPES > * operator->()
simple_target_socket_tagged_b(const char *n=default_name())
tlm::tlm_fw_transport_if< TYPES > fw_interface_type
void bw_invalidate_direct_mem_ptr(sc_dt::uint64 s, sc_dt::uint64 e)
void register_b_transport(MODULE *mod, void(MODULE::*cb)(int id, transaction_type &, sc_core::sc_time &), int id)
simple_target_socket_tagged_b< MODULE, BUSWIDTH, TYPES, sc_core::SC_ZERO_OR_MORE_BOUND > socket_b
simple_target_socket_tagged_b< MODULE, BUSWIDTH, TYPES > socket_b
simple_target_socket_b< MODULE, BUSWIDTH, TYPES > socket_b
Bitfield< 31 > n
Definition: misc_types.hh:462
Bitfield< 9 > e
Definition: misc_types.hh:65
Bitfield< 33 > id
Definition: misc_types.hh:257
Bitfield< 12 > ext
Definition: misc_types.hh:434
Bitfield< 1 > s
Definition: pagetable.hh:64
Bitfield< 51 > t
Definition: pagetable.hh:56
Bitfield< 54 > p
Definition: pagetable.hh:70
const sc_time SC_ZERO_TIME
Definition: sc_time.cc:290
sc_process_handle sc_spawn(T object, const char *name_p=nullptr, const sc_spawn_options *opt_p=nullptr)
Definition: sc_spawn.hh:154
auto sc_bind(F &&f, Args &&...args) -> decltype(std::bind(std::forward< F >(f), std::forward< Args >(args)...))
Definition: sc_spawn.hh:198
sc_port_policy
Definition: sc_port.hh:68
@ SC_ZERO_OR_MORE_BOUND
Definition: sc_port.hh:70
@ SC_ONE_OR_MORE_BOUND
Definition: sc_port.hh:69
const char * sc_gen_unique_name(const char *seed)
Definition: sc_module.cc:820
void wait()
Definition: sc_module.cc:653
uint64_t uint64
Definition: sc_nbdefs.hh:172
@ BEGIN_RESP
Definition: phase.hh:43
@ END_RESP
Definition: phase.hh:44
@ BEGIN_REQ
Definition: phase.hh:41
@ END_REQ
Definition: phase.hh:42
tlm_sync_enum
Definition: fw_bw_ifs.hh:31
@ TLM_COMPLETED
Definition: fw_bw_ifs.hh:31
@ TLM_ACCEPTED
Definition: fw_bw_ifs.hh:31
@ TLM_UPDATED
Definition: fw_bw_ifs.hh:31
#define sc_assert(expr)

Generated on Wed Dec 21 2022 10:22:42 for gem5 by doxygen 1.9.1