simple_initiator_socket.h revision 13743:62e81e25d8d5
110152Satgutier@umich.edu/*****************************************************************************
210152Satgutier@umich.edu
310152Satgutier@umich.edu  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
410152Satgutier@umich.edu  more contributor license agreements.  See the NOTICE file distributed
510234Syasuko.eckert@amd.com  with this work for additional information regarding copyright ownership.
610152Satgutier@umich.edu  Accellera licenses this file to you under the Apache License, Version 2.0
710152Satgutier@umich.edu  (the "License"); you may not use this file except in compliance with the
810152Satgutier@umich.edu  License.  You may obtain a copy of the License at
910152Satgutier@umich.edu
1010152Satgutier@umich.edu    http://www.apache.org/licenses/LICENSE-2.0
1110152Satgutier@umich.edu
1210152Satgutier@umich.edu  Unless required by applicable law or agreed to in writing, software
1310152Satgutier@umich.edu  distributed under the License is distributed on an "AS IS" BASIS,
1410152Satgutier@umich.edu  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
1510152Satgutier@umich.edu  implied.  See the License for the specific language governing
1610152Satgutier@umich.edu  permissions and limitations under the License.
1710152Satgutier@umich.edu
1810152Satgutier@umich.edu *****************************************************************************/
1910152Satgutier@umich.edu
2010152Satgutier@umich.edu#ifndef __SYSTEMC_EXT_TLM_UTILS_SIMPLE_INITIATOR_SOCKET_H__
2110152Satgutier@umich.edu#define __SYSTEMC_EXT_TLM_UTILS_SIMPLE_INITIATOR_SOCKET_H__
2210152Satgutier@umich.edu
2310152Satgutier@umich.edu#include "../core/sc_module.hh"
2410152Satgutier@umich.edu#include "../core/sc_port.hh"
2510152Satgutier@umich.edu#include "../tlm_core/2/generic_payload/gp.hh"
2610152Satgutier@umich.edu#include "../tlm_core/2/interfaces/fw_bw_ifs.hh"
2710152Satgutier@umich.edu#include "../tlm_core/2/sockets/initiator_socket.hh"
2810152Satgutier@umich.edu#include "../tlm_core/2/sockets/target_socket.hh"
2910234Syasuko.eckert@amd.com#include "../utils/sc_report_handler.hh"
3010152Satgutier@umich.edu#include "convenience_socket_bases.h"
3110152Satgutier@umich.edu
3210152Satgutier@umich.edunamespace tlm_utils
3310152Satgutier@umich.edu{
3410152Satgutier@umich.edu
3510152Satgutier@umich.edutemplate <typename MODULE, unsigned int BUSWIDTH, typename TYPES,
3610152Satgutier@umich.edu          sc_core::sc_port_policy POL=sc_core::SC_ONE_OR_MORE_BOUND>
3710152Satgutier@umich.educlass simple_initiator_socket_b :
3810152Satgutier@umich.edu    public tlm::tlm_initiator_socket<BUSWIDTH, TYPES, 1, POL>,
3910152Satgutier@umich.edu    protected simple_socket_base
4010234Syasuko.eckert@amd.com{
4110234Syasuko.eckert@amd.com  public:
4210234Syasuko.eckert@amd.com    typedef typename TYPES::tlm_payload_type transaction_type;
4310234Syasuko.eckert@amd.com    typedef typename TYPES::tlm_phase_type phase_type;
4410234Syasuko.eckert@amd.com    typedef tlm::tlm_sync_enum sync_enum_type;
4510234Syasuko.eckert@amd.com    typedef tlm::tlm_fw_transport_if<TYPES> fw_interface_type;
4610234Syasuko.eckert@amd.com    typedef tlm::tlm_bw_transport_if<TYPES> bw_interface_type;
4710234Syasuko.eckert@amd.com    typedef tlm::tlm_initiator_socket<BUSWIDTH, TYPES, 1, POL> base_type;
4810234Syasuko.eckert@amd.com
4910234Syasuko.eckert@amd.com  public:
5010234Syasuko.eckert@amd.com    static const char *
5110234Syasuko.eckert@amd.com    default_name()
5210234Syasuko.eckert@amd.com    {
5310152Satgutier@umich.edu        return sc_core::sc_gen_unique_name("simple_initiator_socket");
5410152Satgutier@umich.edu    }
5510234Syasuko.eckert@amd.com
5610152Satgutier@umich.edu    explicit simple_initiator_socket_b(const char *n=default_name()) :
5710152Satgutier@umich.edu        base_type(n), m_process(this)
5810152Satgutier@umich.edu    {
5910234Syasuko.eckert@amd.com        this->m_export.bind(m_process);
6010234Syasuko.eckert@amd.com    }
6110234Syasuko.eckert@amd.com
6210234Syasuko.eckert@amd.com    void
6310234Syasuko.eckert@amd.com    register_nb_transport_bw(MODULE *mod,
6410234Syasuko.eckert@amd.com            sync_enum_type (MODULE::*cb)(transaction_type &, phase_type &,
6510152Satgutier@umich.edu                sc_core::sc_time &))
6610152Satgutier@umich.edu    {
6710152Satgutier@umich.edu        m_process.set_transport_ptr(mod, cb);
6810152Satgutier@umich.edu    }
6910234Syasuko.eckert@amd.com
7010234Syasuko.eckert@amd.com    void
7110234Syasuko.eckert@amd.com    register_invalidate_direct_mem_ptr(MODULE *mod,
7210152Satgutier@umich.edu            void (MODULE::*cb)(sc_dt::uint64, sc_dt::uint64))
7310152Satgutier@umich.edu    {
7410152Satgutier@umich.edu        m_process.set_invalidate_direct_mem_ptr(mod, cb);
7510152Satgutier@umich.edu    }
7610152Satgutier@umich.edu
7710234Syasuko.eckert@amd.com  private:
7810234Syasuko.eckert@amd.com    class process : public tlm::tlm_bw_transport_if<TYPES>,
7910234Syasuko.eckert@amd.com                    protected convenience_socket_cb_holder
8010152Satgutier@umich.edu    {
8110152Satgutier@umich.edu      public:
8210152Satgutier@umich.edu        typedef sync_enum_type (MODULE::*TransportPtr)(
8310152Satgutier@umich.edu                transaction_type &, phase_type &, sc_core::sc_time &);
8410234Syasuko.eckert@amd.com        typedef void (MODULE::*InvalidateDirectMemPtr)(
8510234Syasuko.eckert@amd.com                sc_dt::uint64, sc_dt::uint64);
8610234Syasuko.eckert@amd.com
8710234Syasuko.eckert@amd.com        explicit process(simple_socket_base *owner) :
8810152Satgutier@umich.edu            convenience_socket_cb_holder(owner), m_mod(0),
8910152Satgutier@umich.edu            m_transport_ptr(0), m_invalidate_direct_mem_ptr(0)
9010152Satgutier@umich.edu        {}
9110152Satgutier@umich.edu
9210234Syasuko.eckert@amd.com        void
9310234Syasuko.eckert@amd.com        set_transport_ptr(MODULE *mod, TransportPtr p)
9410234Syasuko.eckert@amd.com        {
9510234Syasuko.eckert@amd.com            if (m_transport_ptr) {
9610234Syasuko.eckert@amd.com                display_warning("non-blocking callback already registered");
9710234Syasuko.eckert@amd.com                return;
9810234Syasuko.eckert@amd.com            }
9910234Syasuko.eckert@amd.com            sc_assert(!m_mod || m_mod == mod);
10010234Syasuko.eckert@amd.com            m_mod = mod;
10110234Syasuko.eckert@amd.com            m_transport_ptr = p;
10210234Syasuko.eckert@amd.com        }
10310234Syasuko.eckert@amd.com
10410234Syasuko.eckert@amd.com        void
10510234Syasuko.eckert@amd.com        set_invalidate_direct_mem_ptr(MODULE *mod, InvalidateDirectMemPtr p)
10610234Syasuko.eckert@amd.com        {
10710234Syasuko.eckert@amd.com            if (m_invalidate_direct_mem_ptr) {
10810234Syasuko.eckert@amd.com                display_warning("invalidate DMI callback already registered");
10910234Syasuko.eckert@amd.com                return;
11010234Syasuko.eckert@amd.com            }
11110234Syasuko.eckert@amd.com            sc_assert(!m_mod || m_mod == mod);
11210152Satgutier@umich.edu            m_mod = mod;
11310152Satgutier@umich.edu            m_invalidate_direct_mem_ptr = p;
11410152Satgutier@umich.edu        }
11510152Satgutier@umich.edu
11610234Syasuko.eckert@amd.com        sync_enum_type
11710234Syasuko.eckert@amd.com        nb_transport_bw(transaction_type &trans, phase_type &phase,
11810234Syasuko.eckert@amd.com                        sc_core::sc_time &t)
11910152Satgutier@umich.edu        {
12010152Satgutier@umich.edu            if (m_transport_ptr) {
12110152Satgutier@umich.edu                // Forward call.
12210152Satgutier@umich.edu                sc_assert(m_mod);
12310234Syasuko.eckert@amd.com                return (m_mod->*m_transport_ptr)(trans, phase, t);
12410234Syasuko.eckert@amd.com            }
12510234Syasuko.eckert@amd.com            display_error("no transport callback registered");
12610234Syasuko.eckert@amd.com            return tlm::TLM_COMPLETED;
12710152Satgutier@umich.edu        }
12810152Satgutier@umich.edu
12910152Satgutier@umich.edu        void
13010152Satgutier@umich.edu        invalidate_direct_mem_ptr(sc_dt::uint64 start_range,
13110234Syasuko.eckert@amd.com                                  sc_dt::uint64 end_range)
13210234Syasuko.eckert@amd.com        {
13310152Satgutier@umich.edu            if (m_invalidate_direct_mem_ptr) {
13410152Satgutier@umich.edu                // Forward call.
13510152Satgutier@umich.edu                sc_assert(m_mod);
13610234Syasuko.eckert@amd.com                (m_mod->*m_invalidate_direct_mem_ptr)(
13710234Syasuko.eckert@amd.com                        start_range, end_range);
13810234Syasuko.eckert@amd.com            }
13910234Syasuko.eckert@amd.com        }
14010234Syasuko.eckert@amd.com
14110152Satgutier@umich.edu      private:
14210152Satgutier@umich.edu        MODULE *m_mod;
14310152Satgutier@umich.edu        TransportPtr m_transport_ptr;
144        InvalidateDirectMemPtr m_invalidate_direct_mem_ptr;
145    };
146
147  private:
148    const sc_core::sc_object *get_socket() const { return this; }
149
150  private:
151    process m_process;
152};
153
154template <typename MODULE, unsigned int BUSWIDTH=32,
155          typename TYPES=tlm::tlm_base_protocol_types>
156class simple_initiator_socket :
157    public simple_initiator_socket_b<MODULE, BUSWIDTH, TYPES>
158{
159    typedef simple_initiator_socket_b<MODULE, BUSWIDTH, TYPES> socket_b;
160  public:
161    simple_initiator_socket() : socket_b() {}
162    explicit simple_initiator_socket(const char *name) : socket_b(name) {}
163};
164
165template <typename MODULE, unsigned int BUSWIDTH=32,
166          typename TYPES=tlm::tlm_base_protocol_types>
167class simple_initiator_socket_optional :
168    public simple_initiator_socket_b<MODULE, BUSWIDTH, TYPES,
169                                     sc_core::SC_ZERO_OR_MORE_BOUND>
170{
171    typedef simple_initiator_socket_b<
172        MODULE, BUSWIDTH, TYPES, sc_core::SC_ZERO_OR_MORE_BOUND> socket_b;
173  public:
174    simple_initiator_socket_optional() : socket_b() {}
175    explicit simple_initiator_socket_optional(const char *name) :
176        socket_b(name)
177    {}
178};
179
180
181// Tagged version
182
183template <typename MODULE, unsigned int BUSWIDTH, typename TYPES,
184          sc_core::sc_port_policy POL=sc_core::SC_ONE_OR_MORE_BOUND>
185class simple_initiator_socket_tagged_b :
186    public tlm::tlm_initiator_socket<BUSWIDTH, TYPES, 1, POL>,
187    protected simple_socket_base
188{
189  public:
190    typedef typename TYPES::tlm_payload_type transaction_type;
191    typedef typename TYPES::tlm_phase_type phase_type;
192    typedef tlm::tlm_sync_enum sync_enum_type;
193    typedef tlm::tlm_fw_transport_if<TYPES> fw_interface_type;
194    typedef tlm::tlm_bw_transport_if<TYPES> bw_interface_type;
195    typedef tlm::tlm_initiator_socket<BUSWIDTH, TYPES, 1, POL> base_type;
196
197  public:
198    static const char *
199    default_name()
200    {
201        return sc_core::sc_gen_unique_name("simple_initiator_socket_tagged");
202    }
203
204    explicit simple_initiator_socket_tagged_b(const char *n=default_name()) :
205        base_type(n), m_process(this)
206    {
207        this->m_export.bind(m_process);
208    }
209
210    void
211    register_nb_transport_bw(MODULE *mod,
212            sync_enum_type (MODULE::*cb)(
213                int, transaction_type &, phase_type &, sc_core::sc_time &),
214            int id)
215    {
216        m_process.set_transport_ptr(mod, cb);
217        m_process.set_transport_user_id(id);
218    }
219
220    void
221    register_invalidate_direct_mem_ptr(MODULE *mod,
222            void (MODULE::*cb)(int, sc_dt::uint64, sc_dt::uint64), int id)
223    {
224        m_process.set_invalidate_direct_mem_ptr(mod, cb);
225        m_process.set_invalidate_dmi_user_id(id);
226    }
227
228  private:
229    class process : public tlm::tlm_bw_transport_if<TYPES>,
230                    protected convenience_socket_cb_holder
231    {
232      public:
233        typedef sync_enum_type (MODULE::*TransportPtr)(
234                int, transaction_type &, phase_type &, sc_core::sc_time &);
235        typedef void (MODULE::*InvalidateDirectMemPtr)(
236                int, sc_dt::uint64, sc_dt::uint64);
237
238        explicit process(simple_socket_base *owner) :
239            convenience_socket_cb_holder(owner), m_mod(0),
240            m_transport_ptr(0), m_invalidate_direct_mem_ptr(0),
241            m_transport_user_id(0), m_invalidate_direct_mem_user_id(0)
242        {}
243
244        void set_transport_user_id(int id) { m_transport_user_id = id; }
245        void
246        set_invalidate_dmi_user_id(int id)
247        {
248            m_invalidate_direct_mem_user_id = id;
249        }
250
251        void
252        set_transport_ptr(MODULE *mod, TransportPtr p)
253        {
254            if (m_transport_ptr) {
255                display_warning("non-blocking callback already registered");
256                return;
257            }
258            sc_assert(!m_mod || m_mod == mod);
259            m_mod = mod;
260            m_transport_ptr = p;
261        }
262
263        void
264        set_invalidate_direct_mem_ptr(MODULE *mod, InvalidateDirectMemPtr p)
265        {
266            if (m_invalidate_direct_mem_ptr) {
267                display_warning("invalidate DMI callback already registered");
268                return;
269            }
270            sc_assert(!m_mod || m_mod == mod);
271            m_mod = mod;
272            m_invalidate_direct_mem_ptr = p;
273        }
274
275        sync_enum_type
276        nb_transport_bw(transaction_type &trans, phase_type &phase,
277                        sc_core::sc_time &t)
278        {
279            if (m_transport_ptr) {
280                // Forward call.
281                sc_assert(m_mod);
282                return (m_mod->*m_transport_ptr)(
283                        m_transport_user_id, trans, phase, t);
284            }
285            display_error("no transport callback registered");
286            return tlm::TLM_COMPLETED;
287        }
288
289        void
290        invalidate_direct_mem_ptr(
291                sc_dt::uint64 start_range, sc_dt::uint64 end_range)
292        {
293            if (m_invalidate_direct_mem_ptr) {
294                // Forward call.
295                sc_assert(m_mod);
296                (m_mod->*m_invalidate_direct_mem_ptr)(
297                        m_invalidate_direct_mem_user_id,
298                        start_range, end_range);
299            }
300        }
301
302      private:
303        MODULE *m_mod;
304        TransportPtr m_transport_ptr;
305        InvalidateDirectMemPtr m_invalidate_direct_mem_ptr;
306        int m_transport_user_id;
307        int m_invalidate_direct_mem_user_id;
308    };
309
310  private:
311    const sc_core::sc_object *get_socket() const { return this; }
312
313  private:
314    process m_process;
315};
316
317template <typename MODULE, unsigned int BUSWIDTH=32,
318          typename TYPES=tlm::tlm_base_protocol_types>
319class simple_initiator_socket_tagged :
320    public simple_initiator_socket_tagged_b<MODULE, BUSWIDTH, TYPES>
321{
322    typedef simple_initiator_socket_tagged_b<
323        MODULE, BUSWIDTH, TYPES> socket_b;
324  public:
325    simple_initiator_socket_tagged() : socket_b() {}
326    explicit simple_initiator_socket_tagged(const char *name) :
327        socket_b(name)
328    {}
329};
330
331template <typename MODULE, unsigned int BUSWIDTH=32,
332          typename TYPES=tlm::tlm_base_protocol_types>
333class simple_initiator_socket_tagged_optional :
334    public simple_initiator_socket_tagged_b<MODULE, BUSWIDTH, TYPES,
335                                            sc_core::SC_ZERO_OR_MORE_BOUND>
336{
337    typedef simple_initiator_socket_tagged_b<
338        MODULE, BUSWIDTH, TYPES, sc_core::SC_ZERO_OR_MORE_BOUND> socket_b;
339  public:
340    simple_initiator_socket_tagged_optional() : socket_b() {}
341    explicit simple_initiator_socket_tagged_optional(const char *name) :
342        socket_b(name)
343    {}
344};
345
346} // namespace tlm_utils
347
348#endif /* __SYSTEMC_EXT_TLM_UTILS_SIMPLE_INITIATOR_SOCKET_H__ */
349