TLM-2.0  2.0.4
Accellera TLM-2.0 proof-of-concept library
multi_passthrough_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 #ifndef TLM_UTILS_MULTI_PASSTHROUGH_TARGET_SOCKET_H_INCLUDED_
20 #define TLM_UTILS_MULTI_PASSTHROUGH_TARGET_SOCKET_H_INCLUDED_
21 
23 
24 namespace tlm_utils {
25 
26 /*
27 This class implements a trivial multi target socket.
28 The triviality refers to the fact that the socket does not
29 do blocking to non-blocking or non-blocking to blocking conversions.
30 
31 It allows to connect multiple initiators to this socket.
32 The user has to register callbacks for the fw interface methods
33 he likes to use. The callbacks are basically equal to the fw interface
34 methods but carry an additional integer that indicates to which
35 index of this socket the calling initiator is connected.
36 */
37 template <typename MODULE,
38  unsigned int BUSWIDTH = 32,
39  typename TYPES = tlm::tlm_base_protocol_types,
40  unsigned int N=0,
43  : public multi_target_base< BUSWIDTH, TYPES, N, POL>
44  , public multi_to_multi_bind_base<TYPES>
45 {
46 
47 public:
48 
49  //typedefs
50  // tlm 2.0 types for nb_transport
51  typedef typename TYPES::tlm_payload_type transaction_type;
52  typedef typename TYPES::tlm_phase_type phase_type;
54 
55  // typedefs to keep the fn ptr notations short
56  typedef sync_enum_type (MODULE::*nb_cb)(int, transaction_type&, phase_type&, sc_core::sc_time&);
57  typedef void (MODULE::*b_cb)(int, transaction_type&, sc_core::sc_time&);
58  typedef unsigned int (MODULE::*dbg_cb)(int, transaction_type& txn);
59  typedef bool (MODULE::*dmi_cb)(int, transaction_type& txn, tlm::tlm_dmi& dmi);
60 
62 
64 
65  static const char* default_name()
66  { return sc_core::sc_gen_unique_name("multi_passthrough_target_socket"); }
67 
68  //CTOR
70  : base_type(name)
71  , m_hierarch_bind(0)
72  , m_eoe_disabled(false)
74  {
75  }
76 
78  //clean up everything allocated by 'new'
79  for (unsigned int i=0; i<m_binders.size(); i++) delete m_binders[i];
80  }
81 
83  {
84  //if our export hasn't been bound yet (due to a hierarch binding)
85  // we bind it now.
86  //We do that here as the user of the target port HAS to bind at least on callback,
87  //otherwise the socket was useless. Nevertheless, the target socket may still
88  // stay unbound afterwards.
90  {
91  // We bind to a callback_binder that will be used as the first interface
92  // i.e. calls to the sc_export will have the same ID as calls from the first initator
93  // socket bound
95 
96  if (m_binders.size() == 0)
97  {
98  binder = new callback_binder_fw<TYPES>(this, m_binders.size());
99  m_binders.push_back(binder);
101  }
102  else
103  {
104  binder = m_binders[0];
105  }
106 
108  }
109  }
110 
111  //register callback for nb transport of fw interface
112  void register_nb_transport_fw(MODULE* mod,
113  nb_cb cb)
114  {
116 
117  //warn if there already is a callback
118  if (m_nb_f.is_valid()){
119  display_warning("NBTransport_bw callback already registered.");
120  return;
121  }
122 
123  //set the functor
124  m_nb_f.set_function(mod, cb);
125  }
126 
127  //register callback for b transport of fw interface
128  void register_b_transport(MODULE* mod,
129  b_cb cb)
130  {
132 
133  //warn if there already is a callback
134  if (m_b_f.is_valid()){
135  display_warning("BTransport callback already registered.");
136  return;
137  }
138 
139  //set the functor
140  m_b_f.set_function(mod, cb);
141  }
142 
143  //register callback for debug transport of fw interface
144  void register_transport_dbg(MODULE* mod,
145  dbg_cb cb)
146  {
148 
149  //warn if there already is a callback
150  if (m_dbg_f.is_valid()){
151  display_warning("DebugTransport callback already registered.");
152  return;
153  }
154 
155  //set the functor
156  m_dbg_f.set_function(mod, cb);
157  }
158 
159  //register callback for DMI of fw interface
160  void register_get_direct_mem_ptr(MODULE* mod,
161  dmi_cb cb)
162  {
164 
165  //warn if there already is a callback
166  if (m_dmi_f.is_valid()){
167  display_warning("DMI callback already registered.");
168  return;
169  }
170 
171  //set the functor
172  m_dmi_f.set_function(mod, cb);
173  }
174 
175 
176  //Override virtual functions of the tlm_target_socket:
177  // this function is called whenever an sc_port (as part of a init socket)
178  // wants to bind to the export of the underlying tlm_target_socket
179  //At this time a callback binder is created an returned to the sc_port
180  // of the init socket, so that it binds to the callback binder
182  {
183  //error if this socket is already bound hierarchically
184  if (m_hierarch_bind) display_error("Socket already bound hierarchically.");
185 
187  // consume binder created from the callback registration
189  } else {
190  m_binders.push_back(new callback_binder_fw<TYPES>(this, m_binders.size()));
191  }
192 
193  return *m_binders[m_binders.size()-1];
194  }
195 
196  // const overload not allowed for multi-sockets
198  {
199  display_error("'get_base_interface() const' not allowed for multi-sockets.");
201  }
202 
203  //just return the export of the underlying tlm_target_socket in case of a hierarchical bind
205  {
206  return *this;
207  }
208 
209  //just return the export of the underlying tlm_target_socket in case of a hierarchical bind
211  {
213  }
214 
215  //the standard end of elaboration callback
217  //'break' here if the socket was told not to do callback binding
218  if (m_eoe_disabled) return;
219 
220  //get the callback binders and the multi binds of the top of the hierachical bind chain
221  // NOTE: this could be the same socket if there is no hierachical bind
222  std::vector<callback_binder_fw<TYPES>* >& binders=get_hierarch_bind()->get_binders();
223  std::map<unsigned int, tlm::tlm_bw_transport_if<TYPES>*>& multi_binds=get_hierarch_bind()->get_multi_binds();
224 
225  // complete binding only if there has been a real bind
226  bool unbound = (binders.size() == 1 && m_export_callback_created);
227  // no call to get_base_interface has consumed the export - ignore
228  if (unbound) return;
229 
230  // iterate over all binders
231  for (unsigned int i=0; i<binders.size(); i++) {
232  binders[i]->set_callbacks(m_nb_f, m_b_f, m_dmi_f, m_dbg_f); //set the callbacks for the binder
233  if (multi_binds.find(i)!=multi_binds.end()) //check if this connection is multi-multi
234  //if so remember the interface
235  m_sockets.push_back(multi_binds[i]);
236  else{ //if we are bound to a normal socket
237  //get the calling port and try to cast it into a tlm socket base
238  base_initiator_socket_type* test=dynamic_cast<base_initiator_socket_type*>(binders[i]->get_other_side());
239  if (!test){display_error("Not bound to tlm_socket.");}
240  m_sockets.push_back(&test->get_base_interface()); //remember the interface
241  }
242  }
243  }
244 
245  //
246  // Bind multi target socket to multi target socket (hierarchical bind)
247  //
248  virtual void bind(base_type& s)
249  {
250  //warn if already bound hierarchically
251  if (m_eoe_disabled){
252  display_warning("Socket already bound hierarchically. Bind attempt ignored.");
253  return;
254  }
255 
256  //disable our own end of elaboration call
257  disable_cb_bind();
258 
259  //inform the bound target socket that it is bound hierarchically now
260  s.set_hierarch_bind((base_type*)this);
261  base_type::bind(s); //satisfy SystemC
262  }
263 
264  //operator notation for hierarchical bind
265  void operator() (base_type& s)
266  {
267  bind(s);
268  }
269 
270  //get access to sub port
272 
273  //get number of bound initiators
274  // NOTE: this is only valid at end of elaboration!
275  unsigned int size(){return get_hierarch_bind()->get_binders().size();}
276 
277 protected:
280 
281  //implementation of base class interface
282  base_type* get_hierarch_bind(){if (m_hierarch_bind) return m_hierarch_bind->get_hierarch_bind(); else return this;}
283  std::map<unsigned int, tlm::tlm_bw_transport_if<TYPES>*>& get_multi_binds(){return m_multi_binds;}
284  void set_hierarch_bind(base_type* h){m_hierarch_bind=h;}
286  m_multi_binds[m_binders.size()-1]=other;
287  return m_binders[m_binders.size()-1];
288  }
289 
290  //map that stores to which index a multi init socket is connected
291  // and the interface of the multi init socket
292  std::map<unsigned int, tlm::tlm_bw_transport_if<TYPES>*> m_multi_binds;
293 
295  std::vector<callback_binder_fw<TYPES>* >& get_binders(){return m_binders;}
296  //vector of connected sockets
297  std::vector<tlm::tlm_bw_transport_if<TYPES>*> m_sockets;
298  //vector of binders that convert untagged interface into tagged interface
299  std::vector<callback_binder_fw<TYPES>*> m_binders;
300 
301  base_type* m_hierarch_bind; //pointer to hierarchical bound multi port
302  bool m_eoe_disabled; //bool that disables callback bindings at end of elaboration
303  bool m_export_callback_created; //bool that indicates that a binder has been created from a callback registration
304 
305  //callbacks as functors
306  // (allows to pass the callback to another socket that does not know the type of the module that owns
307  // the callbacks)
312 };
313 
314 template <typename MODULE,
315  unsigned int BUSWIDTH = 32,
316  typename TYPES = tlm::tlm_base_protocol_types,
317  unsigned int N=0>
319  : public multi_passthrough_target_socket<MODULE,BUSWIDTH,TYPES,N,sc_core::SC_ZERO_OR_MORE_BOUND>
320 {
322 public:
324  explicit multi_passthrough_target_socket_optional(const char* name) : socket_b(name) {}
325 };
326 
327 } // namespace tlm_utils
328 #endif // TLM_UTILS_MULTI_PASSTHROUGH_TARGET_SOCKET_H_INCLUDED_
b_transport_functor< TYPES > b_func_type
callback_binder_fw< TYPES >::dmi_func_type m_dmi_f
nb_transport_functor< TYPES > nb_func_type
void display_warning(const char *msg) const
sync_enum_type(MODULE::* nb_cb)(int, transaction_type &, phase_type &, sc_core::sc_time &)
std::map< unsigned int, tlm::tlm_bw_transport_if< TYPES > * > & get_multi_binds()
multi_passthrough_target_socket(const char *name=default_name())
get_dmi_ptr_functor< TYPES > dmi_func_type
SC_ONE_OR_MORE_BOUND
callback_binder_fw< TYPES >::nb_func_type m_nb_f
virtual const tlm::tlm_fw_transport_if< TYPES > & get_base_interface() const
base_type::base_initiator_socket_type base_initiator_socket_type
virtual std::map< unsigned int, tlm::tlm_bw_transport_if< TYPES > * > & get_multi_binds()=0
virtual std::vector< callback_binder_fw< TYPES > *> & get_binders()=0
std::vector< callback_binder_fw< TYPES > * > m_binders
virtual BW_IF & get_base_interface()=0
multi_target_base< BUSWIDTH, TYPES, N, POL > base_type
virtual tlm::tlm_fw_transport_if< TYPES > & get_base_interface()
virtual const sc_core::sc_export< tlm::tlm_fw_transport_if< TYPES > > & get_base_export() const
std::vector< tlm::tlm_bw_transport_if< TYPES > * > m_sockets
void display_error(const char *msg) const
unsigned int(MODULE::* dbg_cb)(int, transaction_type &txn)
callback_binder_fw< TYPES >::debug_func_type m_dbg_f
std::map< unsigned int, tlm::tlm_bw_transport_if< TYPES > * > m_multi_binds
virtual multi_target_base * get_hierarch_bind()=0
bool(MODULE::* dmi_cb)(int, transaction_type &txn, tlm::tlm_dmi &dmi)
SC_API const char * sc_gen_unique_name(const char *, bool preserve_first)
tlm_sync_enum
Definition: tlm_fw_bw_ifs.h:29
std::vector< callback_binder_fw< TYPES > *> & get_binders()
virtual sc_core::sc_export< tlm::tlm_fw_transport_if< TYPES > > & get_base_export()
void(MODULE::* b_cb)(int, transaction_type &, sc_core::sc_time &)
debug_transport_functor< TYPES > debug_func_type
tlm::tlm_fw_transport_if< TYPES > * get_last_binder(tlm::tlm_bw_transport_if< TYPES > *other)
callback_binder_fw< TYPES >::b_func_type m_b_f
tlm::tlm_bw_transport_if< TYPES > * operator[](int i)