TLM-2.0  2.0.3
Accellera TLM-2.0 proof-of-concept library
multi_socket_bases.h
Go to the documentation of this file.
1 /*****************************************************************************
2 
3  The following code is derived, directly or indirectly, from the SystemC
4  source code Copyright (c) 1996-2014 by all Contributors.
5  All Rights reserved.
6 
7  The contents of this file are subject to the restrictions and limitations
8  set forth in the SystemC Open Source License (the "License");
9  You may not use this file except in compliance with such restrictions and
10  limitations. You may obtain instructions on how to receive a copy of the
11  License at http://www.accellera.org/. Software distributed by Contributors
12  under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
13  ANY KIND, either express or implied. See the License for the specific
14  language governing rights and limitations under the License.
15 
16  *****************************************************************************/
17 
18 #ifndef __MULTI_SOCKET_BASES_H__
19 #define __MULTI_SOCKET_BASES_H__
20 
21 #include <systemc>
22 #include <tlm>
23 
24 #include <map>
25 #include <sstream>
26 
27 namespace tlm_utils {
28 
29 template <typename signature>
30 struct fn_container{
31  signature function;
32 };
33 
34 #define TLM_DEFINE_FUNCTOR(name) \
35 template <typename MODULE, typename TRAITS> \
36 inline TLM_RET_VAL static_##name( void* mod \
37  , void* fn \
38  , int index \
39  , TLM_FULL_ARG_LIST) \
40 { \
41  typedef fn_container<TLM_RET_VAL (MODULE::*)(int, TLM_FULL_ARG_LIST)> fn_container_type; \
42  MODULE* tmp_mod=static_cast<MODULE*>(mod); \
43  fn_container_type* tmp_cb =static_cast<fn_container_type*> (fn); \
44  return (tmp_mod->*(tmp_cb->function))(index, TLM_ARG_LIST_WITHOUT_TYPES); \
45 }\
46 \
47 template <typename MODULE, typename TRAITS> \
48 inline void delete_fn_container_of_##name(void* fn) \
49 { \
50  typedef fn_container<TLM_RET_VAL (MODULE::*)(int, TLM_FULL_ARG_LIST)> fn_container_type; \
51  fn_container_type* tmp_cb =static_cast<fn_container_type*> (fn); \
52  if (tmp_cb) delete tmp_cb;\
53 } \
54 \
55 template <typename TRAITS> \
56 class name##_functor{ \
57 public: \
58  typedef typename TRAITS::tlm_payload_type payload_type; \
59  typedef typename TRAITS::tlm_phase_type phase_type; \
60  typedef TLM_RET_VAL (*call_fn)(void*,void*, int, TLM_FULL_ARG_LIST); \
61  typedef void (*del_fn)(void*); \
62 \
63  name##_functor(): m_fn(0), m_del_fn(0), m_mod(0), m_mem_fn(0){} \
64  ~name##_functor(){if (m_del_fn) (*m_del_fn)(m_mem_fn);} \
65 \
66  template <typename MODULE> \
67  void set_function(MODULE* mod, TLM_RET_VAL (MODULE::*cb)(int, TLM_FULL_ARG_LIST)){ \
68  typedef fn_container<TLM_RET_VAL (MODULE::*)(int, TLM_FULL_ARG_LIST)> fn_container_type; \
69  m_fn=&static_##name<MODULE,TRAITS>;\
70  m_del_fn=&delete_fn_container_of_##name<MODULE,TRAITS>;\
71  m_del_fn(m_mem_fn); \
72  fn_container_type* tmp= new fn_container_type(); \
73  tmp->function=cb; \
74  m_mod=static_cast<void*>(mod); \
75  m_mem_fn=static_cast<void*>(tmp); \
76  } \
77  \
78  TLM_RET_VAL operator()(int index, TLM_FULL_ARG_LIST){ \
79  return m_fn(m_mod,m_mem_fn, index, TLM_ARG_LIST_WITHOUT_TYPES); \
80  } \
81 \
82  bool empty(){return (m_mod==0 || m_mem_fn==0 || m_fn==0);}\
83 \
84 protected: \
85  call_fn m_fn;\
86  del_fn m_del_fn; \
87  void* m_mod; \
88  void* m_mem_fn; \
89 private: \
90  name##_functor& operator=(const name##_functor&); \
91 }
92 
93 
94 #define TLM_RET_VAL tlm::tlm_sync_enum
95 #define TLM_FULL_ARG_LIST typename TRAITS::tlm_payload_type& txn, typename TRAITS::tlm_phase_type& ph, sc_core::sc_time& t
96 #define TLM_ARG_LIST_WITHOUT_TYPES txn,ph,t
97 TLM_DEFINE_FUNCTOR(nb_transport);
98 #undef TLM_RET_VAL
99 #undef TLM_FULL_ARG_LIST
100 #undef TLM_ARG_LIST_WITHOUT_TYPES
101 
102 #define TLM_RET_VAL void
103 #define TLM_FULL_ARG_LIST typename TRAITS::tlm_payload_type& txn, sc_core::sc_time& t
104 #define TLM_ARG_LIST_WITHOUT_TYPES txn,t
105 TLM_DEFINE_FUNCTOR(b_transport);
106 #undef TLM_RET_VAL
107 #undef TLM_FULL_ARG_LIST
108 #undef TLM_ARG_LIST_WITHOUT_TYPES
109 
110 #define TLM_RET_VAL unsigned int
111 #define TLM_FULL_ARG_LIST typename TRAITS::tlm_payload_type& txn
112 #define TLM_ARG_LIST_WITHOUT_TYPES txn
113 TLM_DEFINE_FUNCTOR(debug_transport);
114 #undef TLM_RET_VAL
115 #undef TLM_FULL_ARG_LIST
116 #undef TLM_ARG_LIST_WITHOUT_TYPES
117 
118 #define TLM_RET_VAL bool
119 #define TLM_FULL_ARG_LIST typename TRAITS::tlm_payload_type& txn, tlm::tlm_dmi& dmi
120 #define TLM_ARG_LIST_WITHOUT_TYPES txn,dmi
121 TLM_DEFINE_FUNCTOR(get_dmi_ptr);
122 #undef TLM_RET_VAL
123 #undef TLM_FULL_ARG_LIST
124 #undef TLM_ARG_LIST_WITHOUT_TYPES
125 
126 #define TLM_RET_VAL void
127 #define TLM_FULL_ARG_LIST sc_dt::uint64 l, sc_dt::uint64 u
128 #define TLM_ARG_LIST_WITHOUT_TYPES l,u
129 TLM_DEFINE_FUNCTOR(invalidate_dmi);
130 #undef TLM_RET_VAL
131 #undef TLM_FULL_ARG_LIST
132 #undef TLM_ARG_LIST_WITHOUT_TYPES
133 
134 #undef TLM_DEFINE_FUNCTOR
135 
136 /*
137 This class implements the fw interface.
138 It allows to register a callback for each of the fw interface methods.
139 The callbacks simply forward the fw interface call, but add the id (an int)
140 of the callback binder to the signature of the call.
141 */
142 template <typename TYPES>
144  public:
145  //typedefs according to the used TYPES class
146  typedef typename TYPES::tlm_payload_type transaction_type;
147  typedef typename TYPES::tlm_phase_type phase_type;
149 
150  //typedefs for the callbacks
151  typedef nb_transport_functor<TYPES> nb_func_type;
152  typedef b_transport_functor<TYPES> b_func_type;
153  typedef debug_transport_functor<TYPES> debug_func_type;
154  typedef get_dmi_ptr_functor<TYPES> dmi_func_type;
155 
156  //ctor: an ID is needed to create a callback binder
157  callback_binder_fw(int id): m_id(id), m_nb_f(0), m_b_f(0), m_dbg_f(0), m_dmi_f(0), m_caller_port(0) {
158  }
159 
160  //the nb_transport method of the fw interface
162  phase_type& p,
163  sc_core::sc_time& t){
164  //check if a callback is registered
165  if ((m_nb_f == 0) || (m_nb_f && m_nb_f->empty())) {
166  //std::cerr<<"No function registered"<<std::endl;
167  SC_REPORT_ERROR("/OSCI_TLM-2/multi_socket","Call to nb_transport_fw without a registered callback for nb_transport_fw.");
168  }
169  else
170  return (*m_nb_f)(m_id, txn, p, t); //do the callback
171  return tlm::TLM_ACCEPTED; //unreachable
172  }
173 
174  //the b_transport method of the fw interface
176  //check if a callback is registered
177  if ((m_b_f == 0) || (m_b_f && m_b_f->empty())) {
178  SC_REPORT_ERROR("/OSCI_TLM-2/multi_socket","Call to b_transport without a registered callback for b_transport.");
179  }
180  else
181  (*m_b_f)(m_id, trans,t); //do the callback
182  }
183 
184  //the DMI method of the fw interface
186  //check if a callback is registered
187  if ((m_dmi_f == 0) && (m_dmi_f && m_dmi_f->empty())) {
188  dmi_data.allow_none();
189  dmi_data.set_start_address(0x0);
190  dmi_data.set_end_address((sc_dt::uint64)-1);
191  return false;
192  }
193  else
194  return (*m_dmi_f)(m_id, trans,dmi_data); //do the callback
195  }
196 
197  //the debug method of the fw interface
198  unsigned int transport_dbg(transaction_type& trans){
199  //check if a callback is registered
200  if ((m_dbg_f == 0) || (m_dbg_f && m_dbg_f->empty())) {
201  return 0;
202  }
203  else
204  return (*m_dbg_f)(m_id, trans); //do the callback
205  }
206 
207  //the SystemC standard callback register_port:
208  // - called when a port if bound to the interface
209  // - allowd to find out who is bound to that callback binder
210  void register_port(sc_core::sc_port_base& b, const char* name){
211  m_caller_port=&b;
212  }
213 
214  //register callbacks for all fw interface methods at once
216  m_nb_f=&cb1;
217  m_b_f=&cb2;
218  m_dmi_f=&cb3;
219  m_dbg_f=&cb4;
220  }
221 
222  //getter method to get the port that is bound to that callback binder
223  // NOTE: this will only return a valid value at end of elaboration
224  // (but not before end of elaboration!)
225  sc_core::sc_port_base* get_other_side(){return m_caller_port;}
226 
227  private:
228  //the ID of the callback binder
229  int m_id;
230 
231  //the callbacks
232  nb_func_type* m_nb_f;
233  b_func_type* m_b_f;
234  debug_func_type* m_dbg_f;
235  dmi_func_type* m_dmi_f;
236 
237  //the port bound to that callback binder
238  sc_core::sc_port_base* m_caller_port;
239 };
240 
241 /*
242 This class implements the bw interface.
243 It allows to register a callback for each of the bw interface methods.
244 The callbacks simply forward the bw interface call, but add the id (an int)
245 of the callback binder to the signature of the call.
246 */
247 template <typename TYPES>
249  public:
250  //typedefs according to the used TYPES class
251  typedef typename TYPES::tlm_payload_type transaction_type;
252  typedef typename TYPES::tlm_phase_type phase_type;
254 
255  //typedefs for the callbacks
256  typedef nb_transport_functor<TYPES> nb_func_type;
257  typedef invalidate_dmi_functor<TYPES> dmi_func_type;
258 
259  //ctor: an ID is needed to create a callback binder
260  callback_binder_bw(int id): m_id(id), m_nb_f(0), m_dmi_f(0) {
261  }
262 
263  //the nb_transport method of the bw interface
265  phase_type& p,
266  sc_core::sc_time& t){
267  //check if a callback is registered
268  if ((m_nb_f == 0) || (m_nb_f && m_nb_f->empty())) {
269  SC_REPORT_ERROR("/OSCI_TLM-2/multi_socket","Call to nb_transport_bw without a registered callback for nb_transport_bw");
270  }
271  else
272  return (*m_nb_f)(m_id, txn, p, t); //do the callback
273  return tlm::TLM_ACCEPTED; //unreachable
274  }
275 
276  //the DMI method of the bw interface
278  //check if a callback is registered
279  if ((m_dmi_f == 0) || (m_dmi_f && m_dmi_f->empty())) {
280  return;
281  }
282  else
283  (*m_dmi_f)(m_id,l,u); //do the callback
284  }
285 
286  //register callbacks for all bw interface methods at once
288  m_nb_f=&cb1;
289  m_dmi_f=&cb2;
290  }
291 
292  private:
293  //the ID of the callback binder
294  int m_id;
295  //the callbacks
296  nb_func_type* m_nb_f;
297  dmi_func_type* m_dmi_f;
298 };
299 
300 
301 /*
302 This class forms the base for multi initiator sockets.
303 It enforces a multi initiator socket to implement all functions
304 needed to do hierarchical bindings.
305 */
306 template <unsigned int BUSWIDTH = 32,
307  typename TYPES = tlm::tlm_base_protocol_types,
308  unsigned int N=0
309 #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
311 #endif
312  >
314  TYPES,
315  N
316 #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
317  ,POL
318 #endif
319  >{
320 public:
321  //typedef for the base type: the standard tlm initiator socket
322  typedef tlm::tlm_initiator_socket<BUSWIDTH,
323  TYPES,
324  N
325 #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
326  ,POL
327 #endif
328  > base_type;
329 
330  //this method shall disable the code that does the callback binding
331  // that registers callbacks to binders
332  virtual void disable_cb_bind()=0;
333 
334  //this method shall return the multi_init_base to which the
335  // multi_init_base is bound hierarchically
336  // If the base is not bound hierarchically it shall return a pointer to itself
337  virtual multi_init_base* get_hierarch_bind()=0;
338 
339  //this method shall return a vector of the callback binders of multi initiator socket
340  virtual std::vector<callback_binder_bw<TYPES>* >& get_binders()=0;
341 
342  //this method shall return a vector of all target interfaces bound to this multi init socket
343  virtual std::vector<tlm::tlm_fw_transport_if<TYPES>*>& get_sockets()=0;
344 
345  //ctor and dtor
346  virtual ~multi_init_base(){}
347  multi_init_base():base_type(sc_core::sc_gen_unique_name("multi_init_base")){}
348  multi_init_base(const char* name):base_type(name){}
349 };
350 
351 /*
352 This class forms the base for multi target sockets.
353 It enforces a multi target socket to implement all functions
354 needed to do hierarchical bindings.
355 */
356 template <unsigned int BUSWIDTH = 32,
357  typename TYPES = tlm::tlm_base_protocol_types,
358  unsigned int N=0
359 #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
360  ,sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND
361 #endif
362  >
363 class multi_target_base: public tlm::tlm_target_socket<BUSWIDTH,
364  TYPES,
365  N
366 #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
367  ,POL
368 #endif
369  >{
370 public:
371  //typedef for the base type: the standard tlm target socket
372  typedef tlm::tlm_target_socket<BUSWIDTH,
373  TYPES,
374  N
375 #if !(defined SYSTEMC_VERSION & SYSTEMC_VERSION <= 20050714)
376  ,POL
377 #endif
378  > base_type;
379 
380  //this method shall return the multi_init_base to which the
381  // multi_init_base is bound hierarchically
382  // If the base is not bound hierarchically it shall return a pointer to itself
383  virtual multi_target_base* get_hierarch_bind()=0;
384 
385  //this method shall inform the multi target socket that it is bound
386  // hierarchically and to which other multi target socket it is bound hierarchically
387  virtual void set_hierarch_bind(multi_target_base*)=0;
388 
389  //this method shall return a vector of the callback binders of multi initiator socket
390  virtual std::vector<callback_binder_fw<TYPES>* >& get_binders()=0;
391 
392  //this method shall return a map of all multi initiator sockets that are bound to this multi target
393  // the key of the map is the index at which the multi initiator i bound, while the value
394  // is the interface of the multi initiator socket that is bound at that index
395  virtual std::map<unsigned int, tlm::tlm_bw_transport_if<TYPES>*>& get_multi_binds()=0;
396 
397  //ctor and dtor
398  virtual ~multi_target_base(){}
399  multi_target_base():base_type(sc_core::sc_gen_unique_name("multi_target_base")){}
400  multi_target_base(const char* name):base_type(name){}
401 };
402 
403 /*
404 All multi sockets must additionally derive from this class.
405 It enforces a multi socket to implement a function
406 needed to do multi init to multi target bindings.
407 */
408 template <typename TYPES>
409 class multi_to_multi_bind_base{
410 public:
411  virtual ~multi_to_multi_bind_base(){}
412  virtual tlm::tlm_fw_transport_if<TYPES>* get_last_binder(tlm::tlm_bw_transport_if<TYPES>*)=0;
413 };
414 
415 }
416 #endif
sc_core::sc_port_base * get_other_side()
void allow_none(void)
Definition: tlm_dmi.h:73
get_dmi_ptr_functor< TYPES > dmi_func_type
b_transport_functor< TYPES > b_func_type
unsigned int transport_dbg(transaction_type &trans)
uint64_t uint64
void set_end_address(sc_dt::uint64 addr)
Definition: tlm_dmi.h:69
void set_callbacks(nb_func_type &cb1, dmi_func_type &cb2)
sync_enum_type nb_transport_fw(transaction_type &txn, phase_type &p, sc_core::sc_time &t)
void set_start_address(sc_dt::uint64 addr)
Definition: tlm_dmi.h:68
debug_transport_functor< TYPES > debug_func_type
TYPES::tlm_phase_type phase_type
nb_transport_functor< TYPES > nb_func_type
void register_port(sc_core::sc_port_base &b, const char *name)
void b_transport(transaction_type &trans, sc_core::sc_time &t)
void invalidate_direct_mem_ptr(sc_dt::uint64 l, sc_dt::uint64 u)
tlm_sync_enum
Definition: tlm_fw_bw_ifs.h:27
TYPES::tlm_payload_type transaction_type
TYPES::tlm_payload_type transaction_type
sync_enum_type nb_transport_bw(transaction_type &txn, phase_type &p, sc_core::sc_time &t)
TLM_DEFINE_FUNCTOR(nb_transport)
void set_callbacks(nb_func_type &cb1, b_func_type &cb2, dmi_func_type &cb3, debug_func_type &cb4)
bool get_direct_mem_ptr(transaction_type &trans, tlm::tlm_dmi &dmi_data)
#define SC_REPORT_ERROR(msg_type, msg)
TYPES::tlm_phase_type phase_type
invalidate_dmi_functor< TYPES > dmi_func_type
nb_transport_functor< TYPES > nb_func_type