scc  2022.4.0
SystemC components library
signal_initiator_mixin.h
1 /*******************************************************************************
2  * Copyright 2016, 2018 MINRES Technologies GmbH
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *******************************************************************************/
16 
17 #ifndef __SIGNAL_INITIATOR_MIXIN_H__
18 #define __SIGNAL_INITIATOR_MIXIN_H__
19 
20 #include "scc/utilities.h"
21 #include <functional>
22 #include <sstream>
23 #include <tlm/scc/tlm_signal.h>
24 
26 namespace tlm {
28 namespace scc {
29 
30 template <typename BASE_TYPE> class signal_initiator_mixin : public BASE_TYPE {
31 public:
32  using tlm_signal_type = typename BASE_TYPE::tlm_signal_type;
33  using transaction_type = typename BASE_TYPE::transaction_type;
34  using phase_type = typename BASE_TYPE::phase_type;
35  using sync_enum_type = tlm::tlm_sync_enum;
38 
39 public:
41  : signal_initiator_mixin(sc_core::sc_gen_unique_name("signal_initiator_mixinn_socket")) {}
42 
43  explicit signal_initiator_mixin(const char* n)
44  : BASE_TYPE(n)
45  , error_if_no_callback(false)
46  , bw_if(this) {
47  bind(bw_if);
48  }
49 
50  using BASE_TYPE::bind;
51 
52  void write_now(tlm_signal_type value) {
54  gp->set_command(tlm::TLM_WRITE_COMMAND);
55  gp->set_value(value);
56  gp->acquire();
57  tlm::tlm_phase phase{tlm::BEGIN_REQ};
58  sc_core::sc_time delay{sc_core::SC_ZERO_TIME};
59  (*this)->nb_transport_fw(*gp, phase, delay);
60  gp->release();
61  }
62 
63  template <typename EXT_TYPE> void write_now(tlm_signal_type value, EXT_TYPE* ext) {
65  gp->set_command(tlm::TLM_WRITE_COMMAND);
66  gp->set_value(value);
67  if(ext)
68  gp->set_extension(ext);
69  gp->acquire();
70  tlm::tlm_phase phase{tlm::BEGIN_REQ};
71  sc_core::sc_time delay{sc_core::SC_ZERO_TIME};
72  (*this)->nb_transport_fw(*gp, phase, delay);
73  gp->release();
74  }
75 
80  void register_nb_transport(std::function<sync_enum_type(transaction_type&, phase_type&, sc_core::sc_time&)> cb) {
81  bw_if.set_nb_transport_ptr(cb);
82  }
91  void register_nb_transport(std::function<sync_enum_type(unsigned int, transaction_type&, phase_type&, sc_core::sc_time&)> cb,
92  unsigned int tag) {
93  bw_if.set_nb_transport_ptr(cb);
94  }
95 
96  bool error_if_no_callback;
97 
98 private:
99  class bw_transport_if : public bw_interface_type {
100  public:
101  using transport_fct = std::function<sync_enum_type(transaction_type&, phase_type&, sc_core::sc_time&)>;
102  using transport_tagged_fct = std::function<sync_enum_type(unsigned int, transaction_type&, phase_type&, sc_core::sc_time&)>;
103 
104  bw_transport_if(const signal_initiator_mixin* owner)
105  : m_owner(owner) {}
106 
107  void set_nb_transport_ptr(transport_fct p) {
108  if(m_transport_ptr || m_transport_tagged_ptr) {
109  std::stringstream s;
110  s << m_owner->name() << ": non-blocking callback allready registered";
111  SC_REPORT_WARNING("/OSCI_TLM-2/signal_initiator_mixin", s.str().c_str());
112  } else {
113  m_transport_ptr = p;
114  }
115  }
116 
117  void set_nb_transport_ptr(transport_fct p, unsigned int tag) {
118  if(m_transport_ptr || m_transport_tagged_ptr) {
119  std::stringstream s;
120  s << m_owner->name() << ": non-blocking callback allready registered";
121  SC_REPORT_WARNING("/OSCI_TLM-2/signal_initiator_mixin", s.str().c_str());
122  } else {
123  m_transport_tagged_ptr = p;
124  this->tag = tag;
125  }
126  }
127 
128  sync_enum_type nb_transport_bw(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) {
129  if(m_transport_ptr)
130  return m_transport_ptr(trans, phase, t);
131  else if(m_transport_tagged_ptr)
132  return m_transport_tagged_ptr(tag, trans, phase, t);
133  else if(m_owner->error_if_no_callback) {
134  std::stringstream s;
135  s << m_owner->name() << ": no transport callback registered";
136  SC_REPORT_ERROR("/OSCI_TLM-2/signal_initiator_mixin", s.str().c_str());
137  }
138  return tlm::TLM_COMPLETED;
139  }
140 
141  private:
142  const signal_initiator_mixin* m_owner;
143  unsigned int tag = 0;
144  transport_fct m_transport_ptr = nullptr;
145  transport_tagged_fct m_transport_tagged_ptr = nullptr;
146  };
147 
148 private:
149  bw_transport_if bw_if;
150 };
151 } // namespace scc
152 } // namespace tlm
153 
154 #include <sysc/datatypes/bit/sc_logic.h>
155 namespace tlm {
156 namespace scc {
157 using tlm_signal_bool_out = signal_initiator_mixin<tlm_signal_initiator_socket<bool>>;
158 using tlm_signal_logic_out = signal_initiator_mixin<tlm_signal_initiator_socket<sc_dt::sc_logic>>;
159 using tlm_signal_bool_opt_out = signal_initiator_mixin<tlm_signal_opt_initiator_socket<bool>>;
160 using tlm_signal_logic_opt_out = signal_initiator_mixin<tlm_signal_opt_initiator_socket<sc_dt::sc_logic>>;
161 } // namespace scc
162 } // namespace tlm
163 #endif //__SIGNAL_INITIATOR_MIXIN_H__
void register_nb_transport(std::function< sync_enum_type(unsigned int, transaction_type &, phase_type &, sc_core::sc_time &)> cb, unsigned int tag)
register a functor for nb_transport_bw call
void register_nb_transport(std::function< sync_enum_type(transaction_type &, phase_type &, sc_core::sc_time &)> cb)
SCC SystemC utilities.
SystemC TLM.