passthrough_target_socket.h revision 13511:dc5864c73df3
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 TLM_UTILS_PASSTHROUGH_TARGET_SOCKET_H_INCLUDED_
21#define TLM_UTILS_PASSTHROUGH_TARGET_SOCKET_H_INCLUDED_
22
23#include <tlm>
24#include "tlm_utils/convenience_socket_bases.h"
25
26namespace tlm_utils {
27
28template< typename MODULE, unsigned int BUSWIDTH, typename TYPES
29        , sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND >
30class passthrough_target_socket_b
31  : public tlm::tlm_target_socket<BUSWIDTH, TYPES, 1, POL>
32  , protected passthrough_socket_base
33{
34public:
35  typedef typename TYPES::tlm_payload_type              transaction_type;
36  typedef typename TYPES::tlm_phase_type                phase_type;
37  typedef tlm::tlm_sync_enum                            sync_enum_type;
38  typedef tlm::tlm_fw_transport_if<TYPES>               fw_interface_type;
39  typedef tlm::tlm_bw_transport_if<TYPES>               bw_interface_type;
40  typedef tlm::tlm_target_socket<BUSWIDTH,TYPES,1,POL>  base_type;
41
42public:
43  static const char* default_name()
44    { return sc_core::sc_gen_unique_name("passthrough_target_socket"); }
45
46  explicit passthrough_target_socket_b(const char* n = default_name())
47    : base_type(n)
48    , m_process(this)
49  {
50    bind(m_process);
51  }
52
53  using base_type::bind;
54
55  // REGISTER_XXX
56  void register_nb_transport_fw(MODULE* mod,
57                                sync_enum_type (MODULE::*cb)(transaction_type&,
58                                                             phase_type&,
59                                                             sc_core::sc_time&))
60  {
61    m_process.set_nb_transport_ptr(mod, cb);
62  }
63
64  void register_b_transport(MODULE* mod,
65                            void (MODULE::*cb)(transaction_type&,
66                                               sc_core::sc_time&))
67  {
68    m_process.set_b_transport_ptr(mod, cb);
69  }
70
71  void register_transport_dbg(MODULE* mod,
72                              unsigned int (MODULE::*cb)(transaction_type&))
73  {
74    m_process.set_transport_dbg_ptr(mod, cb);
75  }
76
77  void register_get_direct_mem_ptr(MODULE* mod,
78                                   bool (MODULE::*cb)(transaction_type&,
79                                                      tlm::tlm_dmi&))
80  {
81    m_process.set_get_direct_mem_ptr(mod, cb);
82  }
83
84private:
85  class process
86    : public tlm::tlm_fw_transport_if<TYPES>
87    , protected convenience_socket_cb_holder
88  {
89  public:
90    typedef sync_enum_type (MODULE::*NBTransportPtr)(transaction_type&,
91                                                     phase_type&,
92                                                     sc_core::sc_time&);
93    typedef void (MODULE::*BTransportPtr)(transaction_type&,
94                                            sc_core::sc_time&);
95    typedef unsigned int (MODULE::*TransportDbgPtr)(transaction_type&);
96    typedef bool (MODULE::*GetDirectMem_ptr)(transaction_type&,
97                                               tlm::tlm_dmi&);
98
99    explicit process(passthrough_socket_base* owner)
100      : convenience_socket_cb_holder(owner), m_mod(0)
101      , m_nb_transport_ptr(0)
102      , m_b_transport_ptr(0)
103      , m_transport_dbg_ptr(0)
104      , m_get_direct_mem_ptr(0)
105    {
106    }
107
108    void set_nb_transport_ptr(MODULE* mod, NBTransportPtr p)
109    {
110      if (m_nb_transport_ptr) {
111        display_warning("non-blocking callback already registered");
112        return;
113      }
114      sc_assert(!m_mod || m_mod == mod);
115      m_mod = mod;
116      m_nb_transport_ptr = p;
117    }
118
119    void set_b_transport_ptr(MODULE* mod, BTransportPtr p)
120    {
121      if (m_b_transport_ptr) {
122        display_warning("blocking callback already registered");
123        return;
124      }
125      sc_assert(!m_mod || m_mod == mod);
126      m_mod = mod;
127      m_b_transport_ptr = p;
128    }
129
130    void set_transport_dbg_ptr(MODULE* mod, TransportDbgPtr p)
131    {
132      if (m_transport_dbg_ptr) {
133        display_warning("debug callback already registered");
134        return;
135      }
136      sc_assert(!m_mod || m_mod == mod);
137      m_mod = mod;
138      m_transport_dbg_ptr = p;
139    }
140
141    void set_get_direct_mem_ptr(MODULE* mod, GetDirectMem_ptr p)
142    {
143      if (m_get_direct_mem_ptr) {
144        display_warning("get DMI pointer callback already registered");
145        return;
146      }
147      sc_assert(!m_mod || m_mod == mod);
148      m_mod = mod;
149      m_get_direct_mem_ptr = p;
150    }
151
152    sync_enum_type nb_transport_fw(transaction_type& trans,
153                                   phase_type& phase,
154                                   sc_core::sc_time& t)
155    {
156      if (m_nb_transport_ptr) {
157        // forward call
158        sc_assert(m_mod);
159        return (m_mod->*m_nb_transport_ptr)(trans, phase, t);
160      }
161      display_error("no non-blocking callback registered");
162      return tlm::TLM_COMPLETED;
163    }
164
165    void b_transport(transaction_type& trans, sc_core::sc_time& t)
166    {
167      if (m_b_transport_ptr) {
168        // forward call
169        sc_assert(m_mod);
170        return (m_mod->*m_b_transport_ptr)(trans, t);
171      }
172      display_error("no blocking callback registered");
173    }
174
175    unsigned int transport_dbg(transaction_type& trans)
176    {
177      if (m_transport_dbg_ptr) {
178        // forward call
179        sc_assert(m_mod);
180        return (m_mod->*m_transport_dbg_ptr)(trans);
181      }
182      // No debug support
183      return 0;
184    }
185
186    bool get_direct_mem_ptr(transaction_type& trans,
187                            tlm::tlm_dmi&  dmi_data)
188    {
189      if (m_get_direct_mem_ptr) {
190        // forward call
191        sc_assert(m_mod);
192        return (m_mod->*m_get_direct_mem_ptr)(trans, dmi_data);
193      }
194      // No DMI support
195      dmi_data.allow_read_write();
196      dmi_data.set_start_address(0x0);
197      dmi_data.set_end_address((sc_dt::uint64)-1);
198      return false;
199    }
200
201  private:
202    MODULE* m_mod;
203    NBTransportPtr m_nb_transport_ptr;
204    BTransportPtr m_b_transport_ptr;
205    TransportDbgPtr m_transport_dbg_ptr;
206    GetDirectMem_ptr m_get_direct_mem_ptr;
207  };
208
209private:
210  const sc_core::sc_object* get_socket() const { return this; }
211private:
212  process m_process;
213};
214
215template< typename MODULE, unsigned int BUSWIDTH = 32
216        , typename TYPES = tlm::tlm_base_protocol_types >
217class passthrough_target_socket
218  : public passthrough_target_socket_b<MODULE,BUSWIDTH,TYPES>
219{
220  typedef passthrough_target_socket_b<MODULE,BUSWIDTH,TYPES> socket_b;
221public:
222  passthrough_target_socket() : socket_b() {}
223  explicit passthrough_target_socket(const char* name) : socket_b(name) {}
224};
225
226template< typename MODULE, unsigned int BUSWIDTH = 32
227        , typename TYPES = tlm::tlm_base_protocol_types >
228class passthrough_target_socket_optional
229  : public passthrough_target_socket_b<MODULE,BUSWIDTH,TYPES,sc_core::SC_ZERO_OR_MORE_BOUND>
230{
231  typedef passthrough_target_socket_b<MODULE,BUSWIDTH,TYPES,sc_core::SC_ZERO_OR_MORE_BOUND> socket_b;
232public:
233  passthrough_target_socket_optional() : socket_b() {}
234  explicit passthrough_target_socket_optional(const char* name) : socket_b(name) {}
235};
236
237//ID Tagged version
238template< typename MODULE, unsigned int BUSWIDTH, typename TYPES
239        , sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND >
240class passthrough_target_socket_tagged_b
241  : public tlm::tlm_target_socket<BUSWIDTH, TYPES, 1, POL>
242  , protected passthrough_socket_base
243{
244public:
245  typedef typename TYPES::tlm_payload_type              transaction_type;
246  typedef typename TYPES::tlm_phase_type                phase_type;
247  typedef tlm::tlm_sync_enum                            sync_enum_type;
248  typedef tlm::tlm_fw_transport_if<TYPES>               fw_interface_type;
249  typedef tlm::tlm_bw_transport_if<TYPES>               bw_interface_type;
250  typedef tlm::tlm_target_socket<BUSWIDTH,TYPES,1,POL>  base_type;
251
252  static const char* default_name()
253    { return sc_core::sc_gen_unique_name("passthrough_target_socket_tagged"); }
254
255public:
256  explicit passthrough_target_socket_tagged_b(const char* n = default_name())
257    : base_type(n)
258    , m_process(this)
259  {
260    bind(m_process);
261  }
262
263  using base_type::bind;
264
265  // REGISTER_XXX
266  void register_nb_transport_fw(MODULE* mod,
267                                sync_enum_type (MODULE::*cb)(int id,
268                                                             transaction_type&,
269                                                             phase_type&,
270                                                             sc_core::sc_time&),
271                                int id)
272  {
273    m_process.set_nb_transport_ptr(mod, cb);
274    m_process.set_nb_transport_user_id(id);
275  }
276
277  void register_b_transport(MODULE* mod,
278                            void (MODULE::*cb)(int id,
279                                               transaction_type&,
280                                               sc_core::sc_time&),
281                            int id)
282  {
283    m_process.set_b_transport_ptr(mod, cb);
284    m_process.set_b_transport_user_id(id);
285  }
286
287  void register_transport_dbg(MODULE* mod,
288                              unsigned int (MODULE::*cb)(int id,
289                                                         transaction_type&),
290                              int id)
291  {
292    m_process.set_transport_dbg_ptr(mod, cb);
293    m_process.set_transport_dbg_user_id(id);
294  }
295
296  void register_get_direct_mem_ptr(MODULE* mod,
297                                   bool (MODULE::*cb)(int id,
298                                                      transaction_type&,
299                                                      tlm::tlm_dmi&),
300                                   int id)
301  {
302    m_process.set_get_direct_mem_ptr(mod, cb);
303    m_process.set_get_dmi_user_id(id);
304  }
305
306private:
307  class process
308    : public tlm::tlm_fw_transport_if<TYPES>
309    , protected convenience_socket_cb_holder
310  {
311  public:
312    typedef sync_enum_type (MODULE::*NBTransportPtr)(int id,
313                                                     transaction_type&,
314                                                     phase_type&,
315                                                     sc_core::sc_time&);
316    typedef void (MODULE::*BTransportPtr)(int id,
317                                          transaction_type&,
318                                          sc_core::sc_time&);
319    typedef unsigned int (MODULE::*TransportDbgPtr)(int id,
320                                                    transaction_type&);
321    typedef bool (MODULE::*GetDirectMem_ptr)(int id,
322                                             transaction_type&,
323                                             tlm::tlm_dmi&);
324
325    process(passthrough_socket_base* owner)
326      : convenience_socket_cb_holder(owner), m_mod(0)
327      , m_nb_transport_ptr(0)
328      , m_b_transport_ptr(0)
329      , m_transport_dbg_ptr(0)
330      , m_get_direct_mem_ptr(0)
331      , m_nb_transport_user_id(0)
332      , m_b_transport_user_id(0)
333      , m_transport_dbg_user_id(0)
334      , m_get_dmi_user_id(0)
335    {
336    }
337
338    void set_nb_transport_user_id(int id) { m_nb_transport_user_id = id; }
339    void set_b_transport_user_id(int id) { m_b_transport_user_id = id; }
340    void set_transport_dbg_user_id(int id) { m_transport_dbg_user_id = id; }
341    void set_get_dmi_user_id(int id) { m_get_dmi_user_id = id; }
342
343    void set_nb_transport_ptr(MODULE* mod, NBTransportPtr p)
344    {
345      if (m_nb_transport_ptr) {
346        display_warning("non-blocking callback already registered");
347        return;
348      }
349      sc_assert(!m_mod || m_mod == mod);
350      m_mod = mod;
351      m_nb_transport_ptr = p;
352    }
353
354    void set_b_transport_ptr(MODULE* mod, BTransportPtr p)
355    {
356      if (m_b_transport_ptr) {
357        display_warning("blocking callback already registered");
358        return;
359      }
360      sc_assert(!m_mod || m_mod == mod);
361      m_mod = mod;
362      m_b_transport_ptr = p;
363    }
364
365    void set_transport_dbg_ptr(MODULE* mod, TransportDbgPtr p)
366    {
367      if (m_transport_dbg_ptr) {
368        display_warning("debug callback already registered");
369        return;
370      }
371      sc_assert(!m_mod || m_mod == mod);
372      m_mod = mod;
373      m_transport_dbg_ptr = p;
374    }
375
376    void set_get_direct_mem_ptr(MODULE* mod, GetDirectMem_ptr p)
377    {
378      if (m_get_direct_mem_ptr) {
379        display_warning("get DMI pointer callback already registered");
380        return;
381      }
382      sc_assert(!m_mod || m_mod == mod);
383      m_mod = mod;
384      m_get_direct_mem_ptr = p;
385    }
386
387    sync_enum_type nb_transport_fw(transaction_type& trans,
388                                   phase_type& phase,
389                                   sc_core::sc_time& t)
390    {
391      if (m_nb_transport_ptr) {
392        // forward call
393        sc_assert(m_mod);
394        return (m_mod->*m_nb_transport_ptr)(m_nb_transport_user_id, trans, phase, t);
395      }
396      display_error("no non-blocking callback registered");
397      return tlm::TLM_COMPLETED;
398    }
399
400    void b_transport(transaction_type& trans, sc_core::sc_time& t)
401    {
402      if (m_b_transport_ptr) {
403        // forward call
404        sc_assert(m_mod);
405        return (m_mod->*m_b_transport_ptr)(m_b_transport_user_id, trans, t);
406      }
407      display_error("no blocking callback registered");
408    }
409
410    unsigned int transport_dbg(transaction_type& trans)
411    {
412      if (m_transport_dbg_ptr) {
413        // forward call
414        sc_assert(m_mod);
415        return (m_mod->*m_transport_dbg_ptr)(m_transport_dbg_user_id, trans);
416      }
417      // No debug support
418      return 0;
419    }
420
421    bool get_direct_mem_ptr(transaction_type& trans,
422                            tlm::tlm_dmi&  dmi_data)
423    {
424      if (m_get_direct_mem_ptr) {
425        // forward call
426        sc_assert(m_mod);
427        return (m_mod->*m_get_direct_mem_ptr)(m_get_dmi_user_id, trans, dmi_data);
428      }
429      // No DMI support
430      dmi_data.allow_read_write();
431      dmi_data.set_start_address(0x0);
432      dmi_data.set_end_address((sc_dt::uint64)-1);
433      return false;
434    }
435
436  private:
437    MODULE* m_mod;
438    NBTransportPtr m_nb_transport_ptr;
439    BTransportPtr m_b_transport_ptr;
440    TransportDbgPtr m_transport_dbg_ptr;
441    GetDirectMem_ptr m_get_direct_mem_ptr;
442    int m_nb_transport_user_id;
443    int m_b_transport_user_id;
444    int m_transport_dbg_user_id;
445    int m_get_dmi_user_id;
446  };
447
448private:
449  const sc_core::sc_object* get_socket() const { return this; }
450private:
451  process m_process;
452};
453
454template< typename MODULE, unsigned int BUSWIDTH = 32
455        , typename TYPES = tlm::tlm_base_protocol_types >
456class passthrough_target_socket_tagged
457  : public passthrough_target_socket_tagged_b<MODULE,BUSWIDTH,TYPES>
458{
459  typedef passthrough_target_socket_tagged_b<MODULE,BUSWIDTH,TYPES> socket_b;
460public:
461  passthrough_target_socket_tagged() : socket_b() {}
462  explicit passthrough_target_socket_tagged(const char* name) : socket_b(name) {}
463};
464
465template< typename MODULE, unsigned int BUSWIDTH = 32
466        , typename TYPES = tlm::tlm_base_protocol_types >
467class passthrough_target_socket_tagged_optional
468  : public passthrough_target_socket_tagged_b<MODULE,BUSWIDTH,TYPES,sc_core::SC_ZERO_OR_MORE_BOUND>
469{
470  typedef passthrough_target_socket_tagged_b<MODULE,BUSWIDTH,TYPES,sc_core::SC_ZERO_OR_MORE_BOUND> socket_b;
471public:
472  passthrough_target_socket_tagged_optional() : socket_b() {}
473  explicit passthrough_target_socket_tagged_optional(const char* name) : socket_b(name) {}
474};
475
476} // namespace tlm_utils
477#endif // TLM_UTILS_PASSTHROUGH_TARGET_SOCKET_H_INCLUDED_
478