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