simple_initiator_socket.h revision 13586:008fe87c1ad4
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_SIMPLE_INITIATOR_SOCKET_H__
21#define __SYSTEMC_EXT_TLM_UTILS_SIMPLE_INITIATOR_SOCKET_H__
22
23#include "../core/sc_module.hh"
24#include "../core/sc_port.hh"
25#include "../tlm_core/2/generic_payload/gp.hh"
26#include "../tlm_core/2/interfaces/fw_bw_ifs.hh"
27#include "../tlm_core/2/sockets/initiator_socket.hh"
28#include "../utils/sc_report_handler.hh"
29#include "convenience_socket_bases.h"
30
31namespace tlm_utils
32{
33
34template <typename MODULE, unsigned int BUSWIDTH, typename TYPES,
35          sc_core::sc_port_policy POL=sc_core::SC_ONE_OR_MORE_BOUND>
36class simple_initiator_socket_b :
37    public tlm::tlm_initiator_socket<BUSWIDTH, TYPES, 1, POL>,
38    protected simple_socket_base
39{
40  public:
41    typedef typename TYPES::tlm_payload_type transaction_type;
42    typedef typename TYPES::tlm_phase_type phase_type;
43    typedef tlm::tlm_sync_enum sync_enum_type;
44    typedef tlm::tlm_fw_transport_if<TYPES> fw_interface_type;
45    typedef tlm::tlm_bw_transport_if<TYPES> bw_interface_type;
46    typedef tlm::tlm_initiator_socket<BUSWIDTH, TYPES, 1, POL> base_type;
47
48  public:
49    static const char *
50    default_name()
51    {
52        return sc_core::sc_gen_unique_name("simple_initiator_socket");
53    }
54
55    explicit simple_initiator_socket_b(const char *n=default_name()) :
56        base_type(n), m_process(this)
57    {
58        this->m_export.bind(m_process);
59    }
60
61    void
62    register_nb_transport_bw(MODULE *mod,
63            sync_enum_type (MODULE::*cb)(transaction_type &, phase_type &,
64                sc_core::sc_time &))
65    {
66        m_process.set_transport_ptr(mod, cb);
67    }
68
69    void
70    register_invalidate_direct_mem_ptr(MODULE *mod,
71            void (MODULE::*cb)(sc_dt::uint64, sc_dt::uint64))
72    {
73        m_process.set_invalidate_direct_mem_ptr(mod, cb);
74    }
75
76  private:
77    class process : public tlm::tlm_bw_transport_if<TYPES>,
78                    protected convenience_socket_cb_holder
79    {
80      public:
81        typedef sync_enum_type (MODULE::*TransportPtr)(
82                transaction_type &, phase_type &, sc_core::sc_time &);
83        typedef void (MODULE::*InvalidateDirectMemPtr)(
84                sc_dt::uint64, sc_dt::uint64);
85
86        explicit process(simple_socket_base *owner) :
87            convenience_socket_cb_holder(owner), m_mod(0),
88            m_transport_ptr(0), m_invalidate_direct_mem_ptr(0)
89        {}
90
91        void
92        set_transport_ptr(MODULE *mod, TransportPtr p)
93        {
94            if (m_transport_ptr) {
95                display_warning("non-blocking callback already registered");
96                return;
97            }
98            sc_assert(!m_mod || m_mod == mod);
99            m_mod = mod;
100            m_transport_ptr = p;
101        }
102
103        void
104        set_invalidate_direct_mem_ptr(MODULE *mod, InvalidateDirectMemPtr p)
105        {
106            if (m_invalidate_direct_mem_ptr) {
107                display_warning("invalidate DMI callback already registered");
108                return;
109            }
110            sc_assert(!m_mod || m_mod == mod);
111            m_mod = mod;
112            m_invalidate_direct_mem_ptr = p;
113        }
114
115        sync_enum_type
116        nb_transport_bw(transaction_type &trans, phase_type &phase,
117                        sc_core::sc_time &t)
118        {
119            if (m_transport_ptr) {
120                // Forward call.
121                sc_assert(m_mod);
122                return (m_mod->*m_transport_ptr)(trans, phase, t);
123            }
124            display_error("no transport callback registered");
125            return tlm::TLM_COMPLETED;
126        }
127
128        void
129        invalidate_direct_mem_ptr(sc_dt::uint64 start_range,
130                                  sc_dt::uint64 end_range)
131        {
132            if (m_invalidate_direct_mem_ptr) {
133                // Forward call.
134                sc_assert(m_mod);
135                (m_mod->*m_invalidate_direct_mem_ptr)(
136                        start_range, end_range);
137            }
138        }
139
140      private:
141        MODULE *m_mod;
142        TransportPtr m_transport_ptr;
143        InvalidateDirectMemPtr m_invalidate_direct_mem_ptr;
144    };
145
146  private:
147    const sc_core::sc_object *get_socket() const { return this; }
148
149  private:
150    process m_process;
151};
152
153template <typename MODULE, unsigned int BUSWIDTH=32,
154          typename TYPES=tlm::tlm_base_protocol_types>
155class simple_initiator_socket :
156    public simple_initiator_socket_b<MODULE, BUSWIDTH, TYPES>
157{
158    typedef simple_initiator_socket_b<MODULE, BUSWIDTH, TYPES> socket_b;
159  public:
160    simple_initiator_socket() : socket_b() {}
161    explicit simple_initiator_socket(const char *name) : socket_b(name) {}
162};
163
164template <typename MODULE, unsigned int BUSWIDTH=32,
165          typename TYPES=tlm::tlm_base_protocol_types>
166class simple_initiator_socket_optional :
167    public simple_initiator_socket_b<MODULE, BUSWIDTH, TYPES,
168                                     sc_core::SC_ZERO_OR_MORE_BOUND>
169{
170    typedef simple_initiator_socket_b<
171        MODULE, BUSWIDTH, TYPES, sc_core::SC_ZERO_OR_MORE_BOUND> socket_b;
172  public:
173    simple_initiator_socket_optional() : socket_b() {}
174    explicit simple_initiator_socket_optional(const char *name) :
175        socket_b(name)
176    {}
177};
178
179
180// Tagged version
181
182template <typename MODULE, unsigned int BUSWIDTH, typename TYPES,
183          sc_core::sc_port_policy POL=sc_core::SC_ONE_OR_MORE_BOUND>
184class simple_initiator_socket_tagged_b :
185    public tlm::tlm_initiator_socket<BUSWIDTH, TYPES, 1, POL>,
186    protected simple_socket_base
187{
188  public:
189    typedef typename TYPES::tlm_payload_type transaction_type;
190    typedef typename TYPES::tlm_phase_type phase_type;
191    typedef tlm::tlm_sync_enum sync_enum_type;
192    typedef tlm::tlm_fw_transport_if<TYPES> fw_interface_type;
193    typedef tlm::tlm_bw_transport_if<TYPES> bw_interface_type;
194    typedef tlm::tlm_initiator_socket<BUSWIDTH, TYPES, 1, POL> base_type;
195
196  public:
197    static const char *
198    default_name()
199    {
200        return sc_core::sc_gen_unique_name("simple_initiator_socket_tagged");
201    }
202
203    explicit simple_initiator_socket_tagged_b(const char *n=default_name()) :
204        base_type(n), m_process(this)
205    {
206        this->m_export.bind(m_process);
207    }
208
209    void
210    register_nb_transport_bw(MODULE *mod,
211            sync_enum_type (MODULE::*cb)(
212                int, transaction_type &, phase_type &, sc_core::sc_time &),
213            int id)
214    {
215        m_process.set_transport_ptr(mod, cb);
216        m_process.set_transport_user_id(id);
217    }
218
219    void
220    register_invalidate_direct_mem_ptr(MODULE *mod,
221            void (MODULE::*cb)(int, sc_dt::uint64, sc_dt::uint64), int id)
222    {
223        m_process.set_invalidate_direct_mem_ptr(mod, cb);
224        m_process.set_invalidate_dmi_user_id(id);
225    }
226
227  private:
228    class process : public tlm::tlm_bw_transport_if<TYPES>,
229                    protected convenience_socket_cb_holder
230    {
231      public:
232        typedef sync_enum_type (MODULE::*TransportPtr)(
233                int, transaction_type &, phase_type &, sc_core::sc_time &);
234        typedef void (MODULE::*InvalidateDirectMemPtr)(
235                int, sc_dt::uint64, sc_dt::uint64);
236
237        explicit process(simple_socket_base *owner) :
238            convenience_socket_cb_holder(owner), m_mod(0),
239            m_transport_ptr(0), m_invalidate_direct_mem_ptr(0),
240            m_transport_user_id(0), m_invalidate_direct_mem_user_id(0)
241        {}
242
243        void set_transport_user_id(int id) { m_transport_user_id = id; }
244        void
245        set_invalidate_dmi_user_id(int id)
246        {
247            m_invalidate_direct_mem_user_id = id;
248        }
249
250        void
251        set_transport_ptr(MODULE *mod, TransportPtr p)
252        {
253            if (m_transport_ptr) {
254                display_warning("non-blocking callback already registered");
255                return;
256            }
257            sc_assert(!m_mod || m_mod == mod);
258            m_mod = mod;
259            m_transport_ptr = p;
260        }
261
262        void
263        set_invalidate_direct_mem_ptr(MODULE *mod, InvalidateDirectMemPtr p)
264        {
265            if (m_invalidate_direct_mem_ptr) {
266                display_warning("invalidate DMI callback already registered");
267                return;
268            }
269            sc_assert(!m_mod || m_mod == mod);
270            m_mod = mod;
271            m_invalidate_direct_mem_ptr = p;
272        }
273
274        sync_enum_type
275        nb_transport_bw(transaction_type &trans, phase_type &phase,
276                        sc_core::sc_time &t)
277        {
278            if (m_transport_ptr) {
279                // Forward call.
280                sc_assert(m_mod);
281                return (m_mod->*m_transport_ptr)(
282                        m_transport_user_id, trans, phase, t);
283            }
284            display_error("no transport callback registered");
285            return tlm::TLM_COMPLETED;
286        }
287
288        void
289        invalidate_direct_mem_ptr(
290                sc_dt::uint64 start_range, sc_dt::uint64 end_range)
291        {
292            if (m_invalidate_direct_mem_ptr) {
293                // Forward call.
294                sc_assert(m_mod);
295                (m_mod->*m_invalidate_direct_mem_ptr)(
296                        m_invalidate_direct_mem_user_id,
297                        start_range, end_range);
298            }
299        }
300
301      private:
302        MODULE *m_mod;
303        TransportPtr m_transport_ptr;
304        InvalidateDirectMemPtr m_invalidate_direct_mem_ptr;
305        int m_transport_user_id;
306        int m_invalidate_direct_mem_user_id;
307    };
308
309  private:
310    const sc_core::sc_object *get_socket() const { return this; }
311
312  private:
313    process m_process;
314};
315
316template <typename MODULE, unsigned int BUSWIDTH=32,
317          typename TYPES=tlm::tlm_base_protocol_types>
318class simple_initiator_socket_tagged :
319    public simple_initiator_socket_tagged_b<MODULE, BUSWIDTH, TYPES>
320{
321    typedef simple_initiator_socket_tagged_b<
322        MODULE, BUSWIDTH, TYPES> socket_b;
323  public:
324    simple_initiator_socket_tagged() : socket_b() {}
325    explicit simple_initiator_socket_tagged(const char *name) :
326        socket_b(name)
327    {}
328};
329
330template <typename MODULE, unsigned int BUSWIDTH=32,
331          typename TYPES=tlm::tlm_base_protocol_types>
332class simple_initiator_socket_tagged_optional :
333    public simple_initiator_socket_tagged_b<MODULE, BUSWIDTH, TYPES,
334                                            sc_core::SC_ZERO_OR_MORE_BOUND>
335{
336    typedef simple_initiator_socket_tagged_b<
337        MODULE, BUSWIDTH, TYPES, sc_core::SC_ZERO_OR_MORE_BOUND> socket_b;
338  public:
339    simple_initiator_socket_tagged_optional() : socket_b() {}
340    explicit simple_initiator_socket_tagged_optional(const char *name) :
341        socket_b(name)
342    {}
343};
344
345} // namespace tlm_utils
346
347#endif /* __SYSTEMC_EXT_TLM_UTILS_SIMPLE_INITIATOR_SOCKET_H__ */
348