simple_target_socket.h revision 13586
113511Sgabeblack@google.com/*****************************************************************************
213511Sgabeblack@google.com
313511Sgabeblack@google.com  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
413511Sgabeblack@google.com  more contributor license agreements.  See the NOTICE file distributed
513511Sgabeblack@google.com  with this work for additional information regarding copyright ownership.
613511Sgabeblack@google.com  Accellera licenses this file to you under the Apache License, Version 2.0
713511Sgabeblack@google.com  (the "License"); you may not use this file except in compliance with the
813511Sgabeblack@google.com  License.  You may obtain a copy of the License at
913511Sgabeblack@google.com
1013511Sgabeblack@google.com    http://www.apache.org/licenses/LICENSE-2.0
1113511Sgabeblack@google.com
1213511Sgabeblack@google.com  Unless required by applicable law or agreed to in writing, software
1313511Sgabeblack@google.com  distributed under the License is distributed on an "AS IS" BASIS,
1413511Sgabeblack@google.com  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
1513511Sgabeblack@google.com  implied.  See the License for the specific language governing
1613511Sgabeblack@google.com  permissions and limitations under the License.
1713511Sgabeblack@google.com
1813511Sgabeblack@google.com *****************************************************************************/
1913511Sgabeblack@google.com
2013513Sgabeblack@google.com#ifndef __SYSTEMC_EXT_TLM_UTILS_SIMPLE_TARGET_SOCKET_H__
2113513Sgabeblack@google.com#define __SYSTEMC_EXT_TLM_UTILS_SIMPLE_TARGET_SOCKET_H__
2213511Sgabeblack@google.com
2313586Sgabeblack@google.com#include "../core/sc_event.hh"
2413586Sgabeblack@google.com#include "../core/sc_module.hh"
2513586Sgabeblack@google.com#include "../core/sc_port.hh"
2613586Sgabeblack@google.com#include "../tlm_core/2/generic_payload/gp.hh"
2713586Sgabeblack@google.com#include "../tlm_core/2/interfaces/fw_bw_ifs.hh"
2813586Sgabeblack@google.com#include "../tlm_core/2/sockets/target_socket.hh"
2913586Sgabeblack@google.com#include "../utils/sc_report_handler.hh"
3013586Sgabeblack@google.com#include "convenience_socket_bases.h"
3113586Sgabeblack@google.com#include "peq_with_get.h"
3213511Sgabeblack@google.com
3313513Sgabeblack@google.comnamespace tlm_utils
3413513Sgabeblack@google.com{
3513511Sgabeblack@google.com
3613513Sgabeblack@google.comtemplate <typename MODULE, unsigned int BUSWIDTH, typename TYPES,
3713513Sgabeblack@google.com          sc_core::sc_port_policy POL=sc_core::SC_ONE_OR_MORE_BOUND>
3813513Sgabeblack@google.comclass simple_target_socket_b :
3913513Sgabeblack@google.com    public tlm::tlm_target_socket<BUSWIDTH, TYPES, 1, POL>,
4013513Sgabeblack@google.com    protected simple_socket_base
4113511Sgabeblack@google.com{
4213513Sgabeblack@google.com    friend class fw_process;
4313513Sgabeblack@google.com    friend class bw_process;
4413513Sgabeblack@google.com  public:
4513513Sgabeblack@google.com    typedef typename TYPES::tlm_payload_type transaction_type;
4613513Sgabeblack@google.com    typedef typename TYPES::tlm_phase_type phase_type;
4713513Sgabeblack@google.com    typedef tlm::tlm_sync_enum sync_enum_type;
4813513Sgabeblack@google.com    typedef tlm::tlm_fw_transport_if<TYPES> fw_interface_type;
4913513Sgabeblack@google.com    typedef tlm::tlm_bw_transport_if<TYPES> bw_interface_type;
5013513Sgabeblack@google.com    typedef tlm::tlm_target_socket<BUSWIDTH, TYPES, 1, POL>  base_type;
5113511Sgabeblack@google.com
5213511Sgabeblack@google.com  public:
5313513Sgabeblack@google.com    static const char *
5413513Sgabeblack@google.com    default_name()
5513511Sgabeblack@google.com    {
5613513Sgabeblack@google.com        return sc_core::sc_gen_unique_name("simple_target_socket");
5713511Sgabeblack@google.com    }
5813511Sgabeblack@google.com
5913513Sgabeblack@google.com    explicit simple_target_socket_b(const char *n=default_name()) :
6013513Sgabeblack@google.com        base_type(n), m_fw_process(this), m_bw_process(this)
6113511Sgabeblack@google.com    {
6213513Sgabeblack@google.com        bind(m_fw_process);
6313511Sgabeblack@google.com    }
6413511Sgabeblack@google.com
6513513Sgabeblack@google.com    using base_type::bind;
6613513Sgabeblack@google.com
6713513Sgabeblack@google.com    // bw transport must come through us.
6813513Sgabeblack@google.com    tlm::tlm_bw_transport_if<TYPES> *operator -> () { return &m_bw_process; }
6913513Sgabeblack@google.com
7013513Sgabeblack@google.com    // REGISTER_XXX
7113513Sgabeblack@google.com    void
7213513Sgabeblack@google.com    register_nb_transport_fw(MODULE *mod,
7313513Sgabeblack@google.com            sync_enum_type (MODULE::*cb)(
7413513Sgabeblack@google.com                transaction_type &, phase_type &, sc_core::sc_time &))
7513511Sgabeblack@google.com    {
7613513Sgabeblack@google.com        elaboration_check("register_nb_transport_fw");
7713513Sgabeblack@google.com        m_fw_process.set_nb_transport_ptr(mod, cb);
7813513Sgabeblack@google.com    }
7913513Sgabeblack@google.com
8013513Sgabeblack@google.com    void
8113513Sgabeblack@google.com    register_b_transport(MODULE *mod,
8213513Sgabeblack@google.com            void (MODULE::*cb)(transaction_type &, sc_core::sc_time &))
8313513Sgabeblack@google.com    {
8413513Sgabeblack@google.com        elaboration_check("register_b_transport");
8513513Sgabeblack@google.com        m_fw_process.set_b_transport_ptr(mod, cb);
8613513Sgabeblack@google.com    }
8713513Sgabeblack@google.com
8813513Sgabeblack@google.com    void
8913513Sgabeblack@google.com    register_transport_dbg(MODULE *mod,
9013513Sgabeblack@google.com            unsigned int (MODULE::*cb)(transaction_type &))
9113513Sgabeblack@google.com    {
9213513Sgabeblack@google.com        elaboration_check("register_transport_dbg");
9313513Sgabeblack@google.com        m_fw_process.set_transport_dbg_ptr(mod, cb);
9413513Sgabeblack@google.com    }
9513513Sgabeblack@google.com
9613513Sgabeblack@google.com    void
9713513Sgabeblack@google.com    register_get_direct_mem_ptr(MODULE *mod,
9813513Sgabeblack@google.com            bool (MODULE::*cb)(transaction_type &, tlm::tlm_dmi &))
9913513Sgabeblack@google.com    {
10013513Sgabeblack@google.com        elaboration_check("register_get_direct_mem_ptr");
10113513Sgabeblack@google.com        m_fw_process.set_get_direct_mem_ptr(mod, cb);
10213513Sgabeblack@google.com    }
10313513Sgabeblack@google.com
10413513Sgabeblack@google.com  protected:
10513513Sgabeblack@google.com    void
10613513Sgabeblack@google.com    start_of_simulation()
10713513Sgabeblack@google.com    {
10813513Sgabeblack@google.com        base_type::start_of_simulation();
10913513Sgabeblack@google.com        m_fw_process.start_of_simulation();
11013511Sgabeblack@google.com    }
11113511Sgabeblack@google.com
11213511Sgabeblack@google.com  private:
11313513Sgabeblack@google.com    // Make call on bw path.
11413513Sgabeblack@google.com    sync_enum_type
11513513Sgabeblack@google.com    bw_nb_transport(transaction_type &trans, phase_type &phase,
11613513Sgabeblack@google.com                    sc_core::sc_time &t)
11713511Sgabeblack@google.com    {
11813513Sgabeblack@google.com        return base_type::operator -> ()->nb_transport_bw(trans, phase, t);
11913511Sgabeblack@google.com    }
12013511Sgabeblack@google.com
12113513Sgabeblack@google.com    void
12213513Sgabeblack@google.com    bw_invalidate_direct_mem_ptr(sc_dt::uint64 s, sc_dt::uint64 e)
12313511Sgabeblack@google.com    {
12413513Sgabeblack@google.com        base_type::operator -> ()->invalidate_direct_mem_ptr(s, e);
12513511Sgabeblack@google.com    }
12613511Sgabeblack@google.com
12713513Sgabeblack@google.com    // Helper class to handle bw path calls Needed to detect transaction end
12813513Sgabeblack@google.com    // when called from b_transport.
12913513Sgabeblack@google.com    class bw_process : public tlm::tlm_bw_transport_if<TYPES>
13013511Sgabeblack@google.com    {
13113513Sgabeblack@google.com      public:
13213513Sgabeblack@google.com        bw_process(simple_target_socket_b *p_own) : m_owner(p_own) {}
13313513Sgabeblack@google.com
13413513Sgabeblack@google.com        sync_enum_type
13513513Sgabeblack@google.com        nb_transport_bw(transaction_type &trans, phase_type &phase,
13613513Sgabeblack@google.com                        sc_core::sc_time &t)
13713513Sgabeblack@google.com        {
13813513Sgabeblack@google.com            typename std::map<transaction_type *,
13913513Sgabeblack@google.com                              sc_core::sc_event *>::iterator it =
14013513Sgabeblack@google.com                                  m_owner->m_pending_trans.find(&trans);
14113513Sgabeblack@google.com
14213513Sgabeblack@google.com            if (it == m_owner->m_pending_trans.end()) {
14313513Sgabeblack@google.com                // Not a blocking call, forward.
14413513Sgabeblack@google.com                return m_owner->bw_nb_transport(trans, phase, t);
14513513Sgabeblack@google.com
14613513Sgabeblack@google.com            }
14713513Sgabeblack@google.com
14813513Sgabeblack@google.com            if (phase == tlm::END_REQ) {
14913513Sgabeblack@google.com                m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME);
15013513Sgabeblack@google.com                return tlm::TLM_ACCEPTED;
15113513Sgabeblack@google.com            }
15213513Sgabeblack@google.com            if (phase == tlm::BEGIN_RESP) {
15313513Sgabeblack@google.com                if (m_owner->m_current_transaction == &trans) {
15413513Sgabeblack@google.com                    m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME);
15513513Sgabeblack@google.com                }
15613513Sgabeblack@google.com                it->second->notify(t);
15713513Sgabeblack@google.com                m_owner->m_pending_trans.erase(it);
15813513Sgabeblack@google.com                return tlm::TLM_COMPLETED;
15913513Sgabeblack@google.com            }
16013513Sgabeblack@google.com            m_owner->display_error("invalid phase received");
16113513Sgabeblack@google.com            return tlm::TLM_COMPLETED;
16213513Sgabeblack@google.com        }
16313513Sgabeblack@google.com
16413513Sgabeblack@google.com        void
16513513Sgabeblack@google.com        invalidate_direct_mem_ptr(sc_dt::uint64 s, sc_dt::uint64 e)
16613513Sgabeblack@google.com        {
16713513Sgabeblack@google.com            return m_owner->bw_invalidate_direct_mem_ptr(s, e);
16813513Sgabeblack@google.com        }
16913513Sgabeblack@google.com
17013513Sgabeblack@google.com      private:
17113513Sgabeblack@google.com        simple_target_socket_b *m_owner;
17213513Sgabeblack@google.com    };
17313513Sgabeblack@google.com
17413513Sgabeblack@google.com    class fw_process : public tlm::tlm_fw_transport_if<TYPES>,
17513513Sgabeblack@google.com                      public tlm::tlm_mm_interface
17613513Sgabeblack@google.com    {
17713513Sgabeblack@google.com      public:
17813513Sgabeblack@google.com        typedef sync_enum_type (MODULE::*NBTransportPtr)(
17913513Sgabeblack@google.com                transaction_type &, phase_type &, sc_core::sc_time &);
18013513Sgabeblack@google.com        typedef void (MODULE::*BTransportPtr)(
18113513Sgabeblack@google.com                transaction_type &, sc_core::sc_time &);
18213513Sgabeblack@google.com        typedef unsigned int (MODULE::*TransportDbgPtr)(transaction_type &);
18313513Sgabeblack@google.com        typedef bool (MODULE::*GetDirectMemPtr)(
18413513Sgabeblack@google.com                transaction_type &, tlm::tlm_dmi &);
18513513Sgabeblack@google.com
18613513Sgabeblack@google.com        fw_process(simple_target_socket_b *p_own) :
18713513Sgabeblack@google.com            m_owner(p_own), m_mod(0), m_nb_transport_ptr(0),
18813513Sgabeblack@google.com            m_b_transport_ptr(0), m_transport_dbg_ptr(0),
18913513Sgabeblack@google.com            m_get_direct_mem_ptr(0),
19013513Sgabeblack@google.com            m_peq(sc_core::sc_gen_unique_name("m_peq")),
19113513Sgabeblack@google.com            m_response_in_progress(false)
19213513Sgabeblack@google.com        {}
19313513Sgabeblack@google.com
19413513Sgabeblack@google.com        void
19513513Sgabeblack@google.com        start_of_simulation()
19613513Sgabeblack@google.com        {
19713513Sgabeblack@google.com            // Only spawn b2nb_thread, if needed.
19813513Sgabeblack@google.com            if (!m_b_transport_ptr && m_nb_transport_ptr) {
19913513Sgabeblack@google.com                sc_core::sc_spawn_options opts;
20013513Sgabeblack@google.com                opts.set_sensitivity(&m_peq.get_event());
20113513Sgabeblack@google.com                opts.dont_initialize();
20213513Sgabeblack@google.com                sc_core::sc_spawn(sc_bind(&fw_process::b2nb_thread, this),
20313513Sgabeblack@google.com                        sc_core::sc_gen_unique_name("b2nb_thread"), &opts);
20413513Sgabeblack@google.com            }
20513513Sgabeblack@google.com        }
20613513Sgabeblack@google.com
20713513Sgabeblack@google.com        void
20813513Sgabeblack@google.com        set_nb_transport_ptr(MODULE *mod, NBTransportPtr p)
20913513Sgabeblack@google.com        {
21013513Sgabeblack@google.com            if (m_nb_transport_ptr) {
21113513Sgabeblack@google.com                m_owner->display_warning(
21213513Sgabeblack@google.com                        "non-blocking callback already registered");
21313513Sgabeblack@google.com                return;
21413513Sgabeblack@google.com            }
21513513Sgabeblack@google.com            sc_assert(!m_mod || m_mod == mod);
21613513Sgabeblack@google.com            m_mod = mod;
21713513Sgabeblack@google.com            m_nb_transport_ptr = p;
21813513Sgabeblack@google.com        }
21913513Sgabeblack@google.com
22013513Sgabeblack@google.com        void
22113513Sgabeblack@google.com        set_b_transport_ptr(MODULE *mod, BTransportPtr p)
22213513Sgabeblack@google.com        {
22313513Sgabeblack@google.com            if (m_b_transport_ptr) {
22413513Sgabeblack@google.com                m_owner->display_warning(
22513513Sgabeblack@google.com                        "blocking callback already registered");
22613513Sgabeblack@google.com                return;
22713513Sgabeblack@google.com            }
22813513Sgabeblack@google.com            sc_assert(!m_mod || m_mod == mod);
22913513Sgabeblack@google.com            m_mod = mod;
23013513Sgabeblack@google.com            m_b_transport_ptr = p;
23113513Sgabeblack@google.com        }
23213513Sgabeblack@google.com
23313513Sgabeblack@google.com        void
23413513Sgabeblack@google.com        set_transport_dbg_ptr(MODULE *mod, TransportDbgPtr p)
23513513Sgabeblack@google.com        {
23613513Sgabeblack@google.com            if (m_transport_dbg_ptr) {
23713513Sgabeblack@google.com                m_owner->display_warning("debug callback already registered");
23813513Sgabeblack@google.com                return;
23913513Sgabeblack@google.com            }
24013513Sgabeblack@google.com            sc_assert(!m_mod || m_mod == mod);
24113513Sgabeblack@google.com            m_mod = mod;
24213513Sgabeblack@google.com            m_transport_dbg_ptr = p;
24313513Sgabeblack@google.com        }
24413513Sgabeblack@google.com
24513513Sgabeblack@google.com        void
24613513Sgabeblack@google.com        set_get_direct_mem_ptr(MODULE *mod, GetDirectMemPtr p)
24713513Sgabeblack@google.com        {
24813513Sgabeblack@google.com            if (m_get_direct_mem_ptr) {
24913513Sgabeblack@google.com                m_owner->display_warning(
25013513Sgabeblack@google.com                        "get DMI pointer callback already registered");
25113513Sgabeblack@google.com                return;
25213513Sgabeblack@google.com            }
25313513Sgabeblack@google.com            sc_assert(!m_mod || m_mod == mod);
25413513Sgabeblack@google.com            m_mod = mod;
25513513Sgabeblack@google.com            m_get_direct_mem_ptr = p;
25613513Sgabeblack@google.com        }
25713513Sgabeblack@google.com
25813513Sgabeblack@google.com        // Interface implementation.
25913513Sgabeblack@google.com        sync_enum_type
26013513Sgabeblack@google.com        nb_transport_fw(transaction_type &trans, phase_type &phase,
26113513Sgabeblack@google.com                        sc_core::sc_time & t)
26213513Sgabeblack@google.com        {
26313513Sgabeblack@google.com            if (m_nb_transport_ptr) {
26413513Sgabeblack@google.com                // Forward call.
26513513Sgabeblack@google.com                sc_assert(m_mod);
26613513Sgabeblack@google.com                return (m_mod->*m_nb_transport_ptr)(trans, phase, t);
26713513Sgabeblack@google.com            }
26813513Sgabeblack@google.com
26913513Sgabeblack@google.com            // nb->b conversion
27013513Sgabeblack@google.com            if (m_b_transport_ptr) {
27113513Sgabeblack@google.com                if (phase == tlm::BEGIN_REQ) {
27213513Sgabeblack@google.com                    // Prepare thread to do blocking call.
27313513Sgabeblack@google.com                    process_handle_class *ph =
27413513Sgabeblack@google.com                        m_process_handle.get_handle(&trans);
27513513Sgabeblack@google.com
27613513Sgabeblack@google.com                    if (!ph) { // Create new dynamic process.
27713513Sgabeblack@google.com                        ph = new process_handle_class(&trans);
27813513Sgabeblack@google.com                        m_process_handle.put_handle(ph);
27913513Sgabeblack@google.com
28013513Sgabeblack@google.com                        sc_core::sc_spawn_options opts;
28113513Sgabeblack@google.com                        opts.dont_initialize();
28213513Sgabeblack@google.com                        opts.set_sensitivity(&ph->m_e);
28313513Sgabeblack@google.com
28413513Sgabeblack@google.com                        sc_core::sc_spawn(
28513513Sgabeblack@google.com                                sc_bind(&fw_process::nb2b_thread, this, ph),
28613513Sgabeblack@google.com                                sc_core::sc_gen_unique_name("nb2b_thread"),
28713513Sgabeblack@google.com                                &opts);
28813513Sgabeblack@google.com                    }
28913513Sgabeblack@google.com
29013513Sgabeblack@google.com                    ph->m_e.notify(t);
29113513Sgabeblack@google.com                    return tlm::TLM_ACCEPTED;
29213513Sgabeblack@google.com                }
29313513Sgabeblack@google.com                if (phase == tlm::END_RESP) {
29413513Sgabeblack@google.com                    m_response_in_progress = false;
29513513Sgabeblack@google.com                    m_end_response.notify(t);
29613513Sgabeblack@google.com                    return tlm::TLM_COMPLETED;
29713513Sgabeblack@google.com                }
29813513Sgabeblack@google.com                m_owner->display_error("invalid phase received");
29913513Sgabeblack@google.com                return tlm::TLM_COMPLETED;
30013513Sgabeblack@google.com            }
30113513Sgabeblack@google.com             m_owner->display_error(
30213513Sgabeblack@google.com                     "no non-blocking transport callback registered");
30313513Sgabeblack@google.com            return tlm::TLM_COMPLETED;
30413513Sgabeblack@google.com        }
30513513Sgabeblack@google.com
30613513Sgabeblack@google.com        void
30713513Sgabeblack@google.com        b_transport(transaction_type &trans, sc_core::sc_time &t)
30813513Sgabeblack@google.com        {
30913513Sgabeblack@google.com            if (m_b_transport_ptr) {
31013513Sgabeblack@google.com                // Forward call.
31113513Sgabeblack@google.com                sc_assert(m_mod);
31213513Sgabeblack@google.com                (m_mod->*m_b_transport_ptr)(trans, t);
31313513Sgabeblack@google.com                return;
31413513Sgabeblack@google.com            }
31513513Sgabeblack@google.com
31613513Sgabeblack@google.com            // b->nb conversion
31713513Sgabeblack@google.com            if (m_nb_transport_ptr) {
31813513Sgabeblack@google.com                m_peq.notify(trans, t);
31913513Sgabeblack@google.com                t = sc_core::SC_ZERO_TIME;
32013513Sgabeblack@google.com
32113513Sgabeblack@google.com                mm_end_event_ext mm_ext;
32213513Sgabeblack@google.com                const bool mm_added = !trans.has_mm();
32313513Sgabeblack@google.com
32413513Sgabeblack@google.com                if (mm_added) {
32513513Sgabeblack@google.com                    trans.set_mm(this);
32613513Sgabeblack@google.com                    trans.set_auto_extension(&mm_ext);
32713513Sgabeblack@google.com                    trans.acquire();
32813513Sgabeblack@google.com                }
32913513Sgabeblack@google.com
33013513Sgabeblack@google.com                // Wait until transaction is finished.
33113513Sgabeblack@google.com                sc_core::sc_event end_event;
33213513Sgabeblack@google.com                m_owner->m_pending_trans[&trans] = &end_event;
33313513Sgabeblack@google.com                sc_core::wait(end_event);
33413513Sgabeblack@google.com
33513513Sgabeblack@google.com                if (mm_added) {
33613513Sgabeblack@google.com                    // Release will not delete the transaction, it will
33713513Sgabeblack@google.com                    // notify mm_ext.done.
33813513Sgabeblack@google.com                    trans.release();
33913513Sgabeblack@google.com                    if (trans.get_ref_count()) {
34013513Sgabeblack@google.com                        sc_core::wait(mm_ext.done);
34113513Sgabeblack@google.com                    }
34213513Sgabeblack@google.com                    trans.set_mm(0);
34313513Sgabeblack@google.com                }
34413513Sgabeblack@google.com                return;
34513513Sgabeblack@google.com            }
34613513Sgabeblack@google.com
34713513Sgabeblack@google.com            // Should not be reached.
34813513Sgabeblack@google.com            m_owner->display_error(
34913513Sgabeblack@google.com                    "no blocking transport callback registered");
35013513Sgabeblack@google.com        }
35113513Sgabeblack@google.com
35213513Sgabeblack@google.com        unsigned int
35313513Sgabeblack@google.com        transport_dbg(transaction_type &trans)
35413513Sgabeblack@google.com        {
35513513Sgabeblack@google.com            if (m_transport_dbg_ptr) {
35613513Sgabeblack@google.com                // Forward call.
35713513Sgabeblack@google.com                sc_assert(m_mod);
35813513Sgabeblack@google.com                return (m_mod->*m_transport_dbg_ptr)(trans);
35913513Sgabeblack@google.com            }
36013513Sgabeblack@google.com            // No debug support.
36113513Sgabeblack@google.com            return 0;
36213513Sgabeblack@google.com        }
36313513Sgabeblack@google.com
36413513Sgabeblack@google.com        bool
36513513Sgabeblack@google.com        get_direct_mem_ptr(transaction_type &trans, tlm::tlm_dmi &dmi_data)
36613513Sgabeblack@google.com        {
36713513Sgabeblack@google.com            if (m_get_direct_mem_ptr) {
36813513Sgabeblack@google.com                // Forward call.
36913513Sgabeblack@google.com                sc_assert(m_mod);
37013513Sgabeblack@google.com                return (m_mod->*m_get_direct_mem_ptr)(trans, dmi_data);
37113513Sgabeblack@google.com            }
37213513Sgabeblack@google.com            // No DMI support.
37313513Sgabeblack@google.com            dmi_data.allow_read_write();
37413513Sgabeblack@google.com            dmi_data.set_start_address(0x0);
37513513Sgabeblack@google.com            dmi_data.set_end_address((sc_dt::uint64)-1);
37613513Sgabeblack@google.com            return false;
37713513Sgabeblack@google.com        }
37813513Sgabeblack@google.com
37913513Sgabeblack@google.com      private:
38013513Sgabeblack@google.com
38113513Sgabeblack@google.com        // Dynamic process handler for nb2b conversion.
38213513Sgabeblack@google.com
38313513Sgabeblack@google.com        class process_handle_class
38413513Sgabeblack@google.com        {
38513513Sgabeblack@google.com          public:
38613513Sgabeblack@google.com            explicit process_handle_class(transaction_type *trans) :
38713513Sgabeblack@google.com                m_trans(trans), m_suspend(false)
38813513Sgabeblack@google.com            {}
38913513Sgabeblack@google.com
39013513Sgabeblack@google.com            transaction_type *m_trans;
39113513Sgabeblack@google.com            sc_core::sc_event m_e;
39213513Sgabeblack@google.com            bool m_suspend;
39313513Sgabeblack@google.com        };
39413513Sgabeblack@google.com
39513513Sgabeblack@google.com        class process_handle_list
39613513Sgabeblack@google.com        {
39713513Sgabeblack@google.com          public:
39813513Sgabeblack@google.com            process_handle_list() {}
39913513Sgabeblack@google.com
40013513Sgabeblack@google.com            ~process_handle_list()
40113513Sgabeblack@google.com            {
40213513Sgabeblack@google.com                for (typename std::vector<
40313513Sgabeblack@google.com                        process_handle_class *>::iterator it = v.begin(),
40413513Sgabeblack@google.com                        end = v.end(); it != end; ++it) {
40513513Sgabeblack@google.com                    delete *it;
40613513Sgabeblack@google.com                }
40713513Sgabeblack@google.com            }
40813513Sgabeblack@google.com
40913513Sgabeblack@google.com            process_handle_class *
41013513Sgabeblack@google.com            get_handle(transaction_type *trans)
41113513Sgabeblack@google.com            {
41213513Sgabeblack@google.com                typename std::vector<process_handle_class *>::iterator it;
41313513Sgabeblack@google.com
41413513Sgabeblack@google.com                for (it = v.begin(); it != v.end(); it++) {
41513513Sgabeblack@google.com                    if ((*it)->m_suspend) {
41613513Sgabeblack@google.com                        // Found suspended dynamic process, re-use it.
41713513Sgabeblack@google.com                        (*it)->m_trans = trans; // Replace to new one.
41813513Sgabeblack@google.com                        (*it)->m_suspend = false;
41913513Sgabeblack@google.com                        return *it;
42013513Sgabeblack@google.com                    }
42113513Sgabeblack@google.com                }
42213513Sgabeblack@google.com                return NULL; // No suspended process.
42313513Sgabeblack@google.com            }
42413513Sgabeblack@google.com
42513513Sgabeblack@google.com            void
42613513Sgabeblack@google.com            put_handle(process_handle_class *ph)
42713513Sgabeblack@google.com            {
42813513Sgabeblack@google.com                v.push_back(ph);
42913513Sgabeblack@google.com            }
43013513Sgabeblack@google.com
43113513Sgabeblack@google.com          private:
43213513Sgabeblack@google.com            std::vector<process_handle_class*> v;
43313513Sgabeblack@google.com        };
43413513Sgabeblack@google.com
43513513Sgabeblack@google.com        process_handle_list m_process_handle;
43613513Sgabeblack@google.com
43713513Sgabeblack@google.com        void
43813513Sgabeblack@google.com        nb2b_thread(process_handle_class *h)
43913513Sgabeblack@google.com        {
44013513Sgabeblack@google.com            while (1) {
44113513Sgabeblack@google.com                transaction_type *trans = h->m_trans;
44213513Sgabeblack@google.com                sc_core::sc_time t = sc_core::SC_ZERO_TIME;
44313513Sgabeblack@google.com
44413513Sgabeblack@google.com                // Forward call.
44513513Sgabeblack@google.com                sc_assert(m_mod);
44613513Sgabeblack@google.com                (m_mod->*m_b_transport_ptr)(*trans, t);
44713513Sgabeblack@google.com
44813513Sgabeblack@google.com                sc_core::wait(t);
44913513Sgabeblack@google.com
45013513Sgabeblack@google.com                // Return path.
45113513Sgabeblack@google.com                while (m_response_in_progress) {
45213513Sgabeblack@google.com                    sc_core::wait(m_end_response);
45313513Sgabeblack@google.com                }
45413513Sgabeblack@google.com                t = sc_core::SC_ZERO_TIME;
45513513Sgabeblack@google.com                phase_type phase = tlm::BEGIN_RESP;
45613513Sgabeblack@google.com                sync_enum_type sync =
45713513Sgabeblack@google.com                    m_owner->bw_nb_transport(*trans, phase, t);
45813513Sgabeblack@google.com                if (!(sync == tlm::TLM_COMPLETED ||
45913513Sgabeblack@google.com                            (sync == tlm::TLM_UPDATED &&
46013513Sgabeblack@google.com                             phase == tlm::END_RESP))) {
46113513Sgabeblack@google.com                    m_response_in_progress = true;
46213513Sgabeblack@google.com                }
46313513Sgabeblack@google.com
46413513Sgabeblack@google.com                // Suspend until next transaction.
46513513Sgabeblack@google.com                h->m_suspend = true;
46613513Sgabeblack@google.com                sc_core::wait();
46713513Sgabeblack@google.com            }
46813513Sgabeblack@google.com        }
46913513Sgabeblack@google.com
47013513Sgabeblack@google.com        void
47113513Sgabeblack@google.com        b2nb_thread()
47213513Sgabeblack@google.com        {
47313513Sgabeblack@google.com            while (true) {
47413513Sgabeblack@google.com                transaction_type *trans;
47513513Sgabeblack@google.com                while ((trans = m_peq.get_next_transaction()) != 0) {
47613513Sgabeblack@google.com                    sc_assert(m_mod);
47713513Sgabeblack@google.com                    sc_assert(m_nb_transport_ptr);
47813513Sgabeblack@google.com                    phase_type phase = tlm::BEGIN_REQ;
47913513Sgabeblack@google.com                    sc_core::sc_time t = sc_core::SC_ZERO_TIME;
48013513Sgabeblack@google.com
48113513Sgabeblack@google.com                    switch ((m_mod->*m_nb_transport_ptr)(*trans, phase, t)) {
48213513Sgabeblack@google.com                      case tlm::TLM_COMPLETED:
48313513Sgabeblack@google.com                        {
48413513Sgabeblack@google.com                            // Notify transaction is finished.
48513513Sgabeblack@google.com                            typename std::map<transaction_type *,
48613513Sgabeblack@google.com                                     sc_core::sc_event *>::iterator it =
48713513Sgabeblack@google.com                                         m_owner->m_pending_trans.find(trans);
48813513Sgabeblack@google.com                            sc_assert(it != m_owner->m_pending_trans.end());
48913513Sgabeblack@google.com                            it->second->notify(t);
49013513Sgabeblack@google.com                            m_owner->m_pending_trans.erase(it);
49113513Sgabeblack@google.com                            break;
49213513Sgabeblack@google.com                        }
49313513Sgabeblack@google.com
49413513Sgabeblack@google.com                      case tlm::TLM_ACCEPTED:
49513513Sgabeblack@google.com                      case tlm::TLM_UPDATED:
49613513Sgabeblack@google.com                        switch (phase) {
49713513Sgabeblack@google.com                          case tlm::BEGIN_REQ:
49813513Sgabeblack@google.com                            m_owner->m_current_transaction = trans;
49913513Sgabeblack@google.com                            sc_core::wait(m_owner->m_end_request);
50013513Sgabeblack@google.com                            m_owner->m_current_transaction = 0;
50113513Sgabeblack@google.com                            break;
50213513Sgabeblack@google.com
50313513Sgabeblack@google.com                          case tlm::END_REQ:
50413513Sgabeblack@google.com                            sc_core::wait(t);
50513513Sgabeblack@google.com                            break;
50613513Sgabeblack@google.com
50713513Sgabeblack@google.com                          case tlm::BEGIN_RESP:
50813513Sgabeblack@google.com                            {
50913513Sgabeblack@google.com                                phase = tlm::END_RESP;
51013513Sgabeblack@google.com                                // This line is a bug fix added in TLM-2.0.2
51113513Sgabeblack@google.com                                sc_core::wait(t);
51213513Sgabeblack@google.com                                t = sc_core::SC_ZERO_TIME;
51313513Sgabeblack@google.com                                (m_mod->*m_nb_transport_ptr)(
51413513Sgabeblack@google.com                                        *trans, phase, t);
51513513Sgabeblack@google.com
51613513Sgabeblack@google.com                                // Notify transaction is finished.
51713513Sgabeblack@google.com                                typename std::map<transaction_type *,
51813513Sgabeblack@google.com                                         sc_core::sc_event *>::iterator it =
51913513Sgabeblack@google.com                                             m_owner->m_pending_trans.find(
52013513Sgabeblack@google.com                                                     trans);
52113513Sgabeblack@google.com                                sc_assert(it !=
52213513Sgabeblack@google.com                                        m_owner->m_pending_trans.end());
52313513Sgabeblack@google.com                                it->second->notify(t);
52413513Sgabeblack@google.com                                m_owner->m_pending_trans.erase(it);
52513513Sgabeblack@google.com                                break;
52613513Sgabeblack@google.com                            }
52713513Sgabeblack@google.com
52813513Sgabeblack@google.com                          default:
52913513Sgabeblack@google.com                            m_owner->display_error("invalid phase received");
53013513Sgabeblack@google.com                        }
53113513Sgabeblack@google.com                        break;
53213513Sgabeblack@google.com
53313513Sgabeblack@google.com                      default:
53413513Sgabeblack@google.com                        m_owner->display_error("invalid sync value received");
53513513Sgabeblack@google.com                    }
53613513Sgabeblack@google.com                }
53713513Sgabeblack@google.com                sc_core::wait();
53813513Sgabeblack@google.com            }
53913513Sgabeblack@google.com        }
54013513Sgabeblack@google.com
54113513Sgabeblack@google.com        void
54213513Sgabeblack@google.com        free(tlm::tlm_generic_payload *trans)
54313513Sgabeblack@google.com        {
54413513Sgabeblack@google.com            mm_end_event_ext *ext =
54513513Sgabeblack@google.com                trans->template get_extension<mm_end_event_ext>();
54613513Sgabeblack@google.com            sc_assert(ext);
54713513Sgabeblack@google.com            // Notify event first before freeing extensions (reset).
54813513Sgabeblack@google.com            ext->done.notify();
54913513Sgabeblack@google.com            trans->reset();
55013513Sgabeblack@google.com        }
55113513Sgabeblack@google.com
55213513Sgabeblack@google.com      private:
55313513Sgabeblack@google.com        struct mm_end_event_ext : public tlm::tlm_extension<mm_end_event_ext>
55413513Sgabeblack@google.com        {
55513513Sgabeblack@google.com            tlm::tlm_extension_base *clone() const { return NULL; }
55613513Sgabeblack@google.com            void free() {}
55713513Sgabeblack@google.com            void copy_from(tlm::tlm_extension_base const &) {}
55813513Sgabeblack@google.com            sc_core::sc_event done;
55913513Sgabeblack@google.com        };
56013513Sgabeblack@google.com
56113513Sgabeblack@google.com      private:
56213513Sgabeblack@google.com        simple_target_socket_b *m_owner;
56313513Sgabeblack@google.com        MODULE *m_mod;
56413513Sgabeblack@google.com        NBTransportPtr m_nb_transport_ptr;
56513513Sgabeblack@google.com        BTransportPtr m_b_transport_ptr;
56613513Sgabeblack@google.com        TransportDbgPtr m_transport_dbg_ptr;
56713513Sgabeblack@google.com        GetDirectMemPtr m_get_direct_mem_ptr;
56813513Sgabeblack@google.com        peq_with_get<transaction_type> m_peq;
56913513Sgabeblack@google.com        bool m_response_in_progress;
57013513Sgabeblack@google.com        sc_core::sc_event m_end_response;
57113513Sgabeblack@google.com    };
57213513Sgabeblack@google.com
57313513Sgabeblack@google.com  private:
57413513Sgabeblack@google.com    const sc_core::sc_object *get_socket() const { return this; }
57513513Sgabeblack@google.com
57613513Sgabeblack@google.com  private:
57713513Sgabeblack@google.com    fw_process m_fw_process;
57813513Sgabeblack@google.com    bw_process m_bw_process;
57913513Sgabeblack@google.com    std::map<transaction_type *, sc_core::sc_event *> m_pending_trans;
58013513Sgabeblack@google.com    sc_core::sc_event m_end_request;
58113513Sgabeblack@google.com    transaction_type* m_current_transaction;
58213513Sgabeblack@google.com};
58313513Sgabeblack@google.com
58413513Sgabeblack@google.comtemplate <typename MODULE, unsigned int BUSWIDTH=32,
58513513Sgabeblack@google.com          typename TYPES=tlm::tlm_base_protocol_types>
58613513Sgabeblack@google.comclass simple_target_socket :
58713513Sgabeblack@google.com    public simple_target_socket_b<MODULE, BUSWIDTH, TYPES>
58813513Sgabeblack@google.com{
58913513Sgabeblack@google.com    typedef simple_target_socket_b<MODULE, BUSWIDTH, TYPES> socket_b;
59013513Sgabeblack@google.com  public:
59113513Sgabeblack@google.com    simple_target_socket() : socket_b() {}
59213513Sgabeblack@google.com    explicit simple_target_socket(const char *name) : socket_b(name) {}
59313513Sgabeblack@google.com};
59413513Sgabeblack@google.com
59513513Sgabeblack@google.comtemplate <typename MODULE, unsigned int BUSWIDTH=32,
59613513Sgabeblack@google.com          typename TYPES=tlm::tlm_base_protocol_types>
59713513Sgabeblack@google.comclass simple_target_socket_optional :
59813513Sgabeblack@google.com    public simple_target_socket_b<MODULE, BUSWIDTH, TYPES,
59913513Sgabeblack@google.com                                  sc_core::SC_ZERO_OR_MORE_BOUND>
60013513Sgabeblack@google.com{
60113513Sgabeblack@google.com    typedef simple_target_socket_b<MODULE, BUSWIDTH, TYPES,
60213513Sgabeblack@google.com                                   sc_core::SC_ZERO_OR_MORE_BOUND> socket_b;
60313513Sgabeblack@google.com  public:
60413513Sgabeblack@google.com    simple_target_socket_optional() : socket_b() {}
60513513Sgabeblack@google.com    explicit simple_target_socket_optional(const char *name) :
60613513Sgabeblack@google.com        socket_b(name)
60713513Sgabeblack@google.com    {}
60813513Sgabeblack@google.com};
60913513Sgabeblack@google.com
61013513Sgabeblack@google.com// ID Tagged version.
61113513Sgabeblack@google.comtemplate <typename MODULE, unsigned int BUSWIDTH, typename TYPES,
61213513Sgabeblack@google.com          sc_core::sc_port_policy POL=sc_core::SC_ONE_OR_MORE_BOUND>
61313513Sgabeblack@google.comclass simple_target_socket_tagged_b :
61413513Sgabeblack@google.com    public tlm::tlm_target_socket<BUSWIDTH, TYPES, 1, POL>,
61513513Sgabeblack@google.com    protected simple_socket_base
61613513Sgabeblack@google.com{
61713513Sgabeblack@google.com    friend class fw_process;
61813513Sgabeblack@google.com    friend class bw_process;
61913513Sgabeblack@google.com  public:
62013513Sgabeblack@google.com    typedef typename TYPES::tlm_payload_type transaction_type;
62113513Sgabeblack@google.com    typedef typename TYPES::tlm_phase_type phase_type;
62213513Sgabeblack@google.com    typedef tlm::tlm_sync_enum sync_enum_type;
62313513Sgabeblack@google.com    typedef tlm::tlm_fw_transport_if<TYPES> fw_interface_type;
62413513Sgabeblack@google.com    typedef tlm::tlm_bw_transport_if<TYPES> bw_interface_type;
62513513Sgabeblack@google.com    typedef tlm::tlm_target_socket<BUSWIDTH, TYPES, 1, POL> base_type;
62613513Sgabeblack@google.com
62713513Sgabeblack@google.com  public:
62813513Sgabeblack@google.com    static const char *
62913513Sgabeblack@google.com    default_name()
63013513Sgabeblack@google.com    {
63113513Sgabeblack@google.com        return sc_core::sc_gen_unique_name("simple_target_socket_tagged");
63213511Sgabeblack@google.com    }
63313511Sgabeblack@google.com
63413513Sgabeblack@google.com    explicit simple_target_socket_tagged_b(const char *n=default_name()) :
63513513Sgabeblack@google.com        base_type(n), m_fw_process(this), m_bw_process(this)
63613511Sgabeblack@google.com    {
63713513Sgabeblack@google.com        bind(m_fw_process);
63813511Sgabeblack@google.com    }
63913511Sgabeblack@google.com
64013513Sgabeblack@google.com    using base_type::bind;
64113513Sgabeblack@google.com
64213513Sgabeblack@google.com    // bw transport must come through us.
64313513Sgabeblack@google.com    tlm::tlm_bw_transport_if<TYPES> *operator -> () { return &m_bw_process; }
64413513Sgabeblack@google.com
64513513Sgabeblack@google.com    // REGISTER_XXX
64613513Sgabeblack@google.com    void
64713513Sgabeblack@google.com    register_nb_transport_fw(MODULE *mod,
64813513Sgabeblack@google.com            sync_enum_type (MODULE::*cb)(int id, transaction_type &,
64913513Sgabeblack@google.com                                         phase_type &, sc_core::sc_time &),
65013513Sgabeblack@google.com            int id)
65113511Sgabeblack@google.com    {
65213513Sgabeblack@google.com        elaboration_check("register_nb_transport_fw");
65313513Sgabeblack@google.com        m_fw_process.set_nb_transport_ptr(mod, cb);
65413513Sgabeblack@google.com        m_fw_process.set_nb_transport_user_id(id);
65513511Sgabeblack@google.com    }
65613511Sgabeblack@google.com
65713513Sgabeblack@google.com    void
65813513Sgabeblack@google.com    register_b_transport(MODULE *mod,
65913513Sgabeblack@google.com            void (MODULE::*cb)(int id, transaction_type &,
66013513Sgabeblack@google.com                               sc_core::sc_time &),
66113513Sgabeblack@google.com            int id)
66213511Sgabeblack@google.com    {
66313513Sgabeblack@google.com        elaboration_check("register_b_transport");
66413513Sgabeblack@google.com        m_fw_process.set_b_transport_ptr(mod, cb);
66513513Sgabeblack@google.com        m_fw_process.set_b_transport_user_id(id);
66613511Sgabeblack@google.com    }
66713511Sgabeblack@google.com
66813513Sgabeblack@google.com    void
66913513Sgabeblack@google.com    register_transport_dbg(MODULE *mod,
67013513Sgabeblack@google.com            unsigned int (MODULE::*cb)(int id, transaction_type &), int id)
67113511Sgabeblack@google.com    {
67213513Sgabeblack@google.com        elaboration_check("register_transport_dbg");
67313513Sgabeblack@google.com        m_fw_process.set_transport_dbg_ptr(mod, cb);
67413513Sgabeblack@google.com        m_fw_process.set_transport_dbg_user_id(id);
67513511Sgabeblack@google.com    }
67613511Sgabeblack@google.com
67713513Sgabeblack@google.com    void
67813513Sgabeblack@google.com    register_get_direct_mem_ptr(MODULE *mod,
67913513Sgabeblack@google.com            bool (MODULE::*cb)(int id, transaction_type &, tlm::tlm_dmi &),
68013513Sgabeblack@google.com            int id)
68113511Sgabeblack@google.com    {
68213513Sgabeblack@google.com        elaboration_check("register_get_direct_mem_ptr");
68313513Sgabeblack@google.com        m_fw_process.set_get_direct_mem_ptr(mod, cb);
68413513Sgabeblack@google.com        m_fw_process.set_get_dmi_user_id(id);
68513513Sgabeblack@google.com    }
68613513Sgabeblack@google.com
68713513Sgabeblack@google.com  protected:
68813513Sgabeblack@google.com    void
68913513Sgabeblack@google.com    start_of_simulation()
69013513Sgabeblack@google.com    {
69113513Sgabeblack@google.com        base_type::start_of_simulation();
69213513Sgabeblack@google.com        m_fw_process.start_of_simulation();
69313511Sgabeblack@google.com    }
69413511Sgabeblack@google.com
69513511Sgabeblack@google.com  private:
69613513Sgabeblack@google.com    // Make call on bw path.
69713513Sgabeblack@google.com    sync_enum_type
69813513Sgabeblack@google.com    bw_nb_transport(transaction_type &trans, phase_type &phase,
69913513Sgabeblack@google.com                    sc_core::sc_time &t)
70013513Sgabeblack@google.com    {
70113513Sgabeblack@google.com        return base_type::operator -> ()->nb_transport_bw(trans, phase, t);
70213513Sgabeblack@google.com    }
70313511Sgabeblack@google.com
70413513Sgabeblack@google.com    void
70513513Sgabeblack@google.com    bw_invalidate_direct_mem_ptr(sc_dt::uint64 s, sc_dt::uint64 e)
70613513Sgabeblack@google.com    {
70713513Sgabeblack@google.com        base_type::operator -> ()->invalidate_direct_mem_ptr(s, e);
70813513Sgabeblack@google.com    }
70913511Sgabeblack@google.com
71013513Sgabeblack@google.com    // Helper class to handle bw path calls Needed to detect transaction
71113513Sgabeblack@google.com    // end when called from b_transport.
71213513Sgabeblack@google.com    class bw_process : public tlm::tlm_bw_transport_if<TYPES>
71313513Sgabeblack@google.com    {
71413513Sgabeblack@google.com      public:
71513513Sgabeblack@google.com        bw_process(simple_target_socket_tagged_b *p_own) : m_owner(p_own) {}
71613511Sgabeblack@google.com
71713513Sgabeblack@google.com        sync_enum_type
71813513Sgabeblack@google.com        nb_transport_bw(transaction_type &trans, phase_type &phase,
71913513Sgabeblack@google.com                        sc_core::sc_time &t)
72013513Sgabeblack@google.com        {
72113513Sgabeblack@google.com            typename std::map<transaction_type *,
72213513Sgabeblack@google.com                              sc_core::sc_event *>::iterator it =
72313513Sgabeblack@google.com                                  m_owner->m_pending_trans.find(&trans);
72413513Sgabeblack@google.com
72513513Sgabeblack@google.com            if (it == m_owner->m_pending_trans.end()) {
72613513Sgabeblack@google.com                // Not a blocking call, forward.
72713513Sgabeblack@google.com                return m_owner->bw_nb_transport(trans, phase, t);
72813513Sgabeblack@google.com            }
72913513Sgabeblack@google.com            if (phase == tlm::END_REQ) {
73013513Sgabeblack@google.com                m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME);
73113513Sgabeblack@google.com                return tlm::TLM_ACCEPTED;
73213513Sgabeblack@google.com            }
73313513Sgabeblack@google.com            if (phase == tlm::BEGIN_RESP) {
73413513Sgabeblack@google.com                if (m_owner->m_current_transaction == &trans) {
73513513Sgabeblack@google.com                    m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME);
73613513Sgabeblack@google.com                }
73713513Sgabeblack@google.com                it->second->notify(t);
73813513Sgabeblack@google.com                m_owner->m_pending_trans.erase(it);
73913513Sgabeblack@google.com                return tlm::TLM_COMPLETED;
74013513Sgabeblack@google.com            }
74113513Sgabeblack@google.com            m_owner->display_error("invalid phase received");
74213513Sgabeblack@google.com            return tlm::TLM_COMPLETED;
74313513Sgabeblack@google.com        }
74413513Sgabeblack@google.com
74513513Sgabeblack@google.com        void
74613513Sgabeblack@google.com        invalidate_direct_mem_ptr(sc_dt::uint64 s, sc_dt::uint64 e)
74713513Sgabeblack@google.com        {
74813513Sgabeblack@google.com            return m_owner->bw_invalidate_direct_mem_ptr(s, e);
74913513Sgabeblack@google.com        }
75013513Sgabeblack@google.com
75113513Sgabeblack@google.com      private:
75213513Sgabeblack@google.com        simple_target_socket_tagged_b *m_owner;
75313511Sgabeblack@google.com    };
75413511Sgabeblack@google.com
75513513Sgabeblack@google.com    class fw_process : public tlm::tlm_fw_transport_if<TYPES>,
75613513Sgabeblack@google.com                       public tlm::tlm_mm_interface
75713513Sgabeblack@google.com    {
75813513Sgabeblack@google.com      public:
75913513Sgabeblack@google.com        typedef sync_enum_type (MODULE::*NBTransportPtr)(
76013513Sgabeblack@google.com                int id, transaction_type &, phase_type &,
76113513Sgabeblack@google.com                sc_core::sc_time &);
76213513Sgabeblack@google.com        typedef void (MODULE::*BTransportPtr)(
76313513Sgabeblack@google.com                int id, transaction_type &, sc_core::sc_time &);
76413513Sgabeblack@google.com        typedef unsigned int (MODULE::*TransportDbgPtr)(
76513513Sgabeblack@google.com                int id, transaction_type &);
76613513Sgabeblack@google.com        typedef bool (MODULE::*GetDirectMemPtr)(
76713513Sgabeblack@google.com                int id, transaction_type &, tlm::tlm_dmi &);
76813511Sgabeblack@google.com
76913513Sgabeblack@google.com        fw_process(simple_target_socket_tagged_b *p_own) :
77013513Sgabeblack@google.com            m_owner(p_own), m_mod(0), m_nb_transport_ptr(0),
77113513Sgabeblack@google.com            m_b_transport_ptr(0), m_transport_dbg_ptr(0),
77213513Sgabeblack@google.com            m_get_direct_mem_ptr(0), m_nb_transport_user_id(0),
77313513Sgabeblack@google.com            m_b_transport_user_id(0), m_transport_dbg_user_id(0),
77413513Sgabeblack@google.com            m_get_dmi_user_id(0),
77513513Sgabeblack@google.com            m_peq(sc_core::sc_gen_unique_name("m_peq")),
77613513Sgabeblack@google.com            m_response_in_progress(false)
77713513Sgabeblack@google.com        {}
77813511Sgabeblack@google.com
77913513Sgabeblack@google.com        void
78013513Sgabeblack@google.com        start_of_simulation()
78113513Sgabeblack@google.com        {
78213513Sgabeblack@google.com            if (!m_b_transport_ptr && m_nb_transport_ptr) {
78313513Sgabeblack@google.com                // Only spawn b2nb_thread if needed.
78413513Sgabeblack@google.com                sc_core::sc_spawn_options opts;
78513513Sgabeblack@google.com                opts.set_sensitivity(&m_peq.get_event());
78613513Sgabeblack@google.com                opts.dont_initialize();
78713513Sgabeblack@google.com                sc_core::sc_spawn(sc_bind(&fw_process::b2nb_thread, this),
78813513Sgabeblack@google.com                        sc_core::sc_gen_unique_name("b2nb_thread"), &opts);
78913513Sgabeblack@google.com            }
79013511Sgabeblack@google.com        }
79113511Sgabeblack@google.com
79213513Sgabeblack@google.com        void set_nb_transport_user_id(int id) { m_nb_transport_user_id = id; }
79313513Sgabeblack@google.com        void set_b_transport_user_id(int id) { m_b_transport_user_id = id; }
79413513Sgabeblack@google.com        void
79513513Sgabeblack@google.com        set_transport_dbg_user_id(int id)
79613513Sgabeblack@google.com        {
79713513Sgabeblack@google.com            m_transport_dbg_user_id = id;
79813513Sgabeblack@google.com        }
79913513Sgabeblack@google.com        void set_get_dmi_user_id(int id) { m_get_dmi_user_id = id; }
80013511Sgabeblack@google.com
80113513Sgabeblack@google.com        void
80213513Sgabeblack@google.com        set_nb_transport_ptr(MODULE *mod, NBTransportPtr p)
80313513Sgabeblack@google.com        {
80413513Sgabeblack@google.com            if (m_nb_transport_ptr) {
80513513Sgabeblack@google.com                m_owner->display_warning(
80613513Sgabeblack@google.com                        "non-blocking callback already registered");
80713513Sgabeblack@google.com                return;
80813513Sgabeblack@google.com            }
80913513Sgabeblack@google.com            sc_assert(!m_mod || m_mod == mod);
81013513Sgabeblack@google.com            m_mod = mod;
81113513Sgabeblack@google.com            m_nb_transport_ptr = p;
81213513Sgabeblack@google.com        }
81313511Sgabeblack@google.com
81413513Sgabeblack@google.com        void
81513513Sgabeblack@google.com        set_b_transport_ptr(MODULE* mod, BTransportPtr p)
81613513Sgabeblack@google.com        {
81713513Sgabeblack@google.com            if (m_b_transport_ptr) {
81813513Sgabeblack@google.com                m_owner->display_warning(
81913513Sgabeblack@google.com                        "blocking callback already registered");
82013513Sgabeblack@google.com                return;
82113513Sgabeblack@google.com            }
82213513Sgabeblack@google.com            sc_assert(!m_mod || m_mod == mod);
82313513Sgabeblack@google.com            m_mod = mod;
82413513Sgabeblack@google.com            m_b_transport_ptr = p;
82513513Sgabeblack@google.com        }
82613511Sgabeblack@google.com
82713513Sgabeblack@google.com        void
82813513Sgabeblack@google.com        set_transport_dbg_ptr(MODULE *mod, TransportDbgPtr p)
82913513Sgabeblack@google.com        {
83013513Sgabeblack@google.com            if (m_transport_dbg_ptr) {
83113513Sgabeblack@google.com                m_owner->display_warning(
83213513Sgabeblack@google.com                        "debug callback already registered");
83313513Sgabeblack@google.com                return;
83413513Sgabeblack@google.com            }
83513513Sgabeblack@google.com            sc_assert(!m_mod || m_mod == mod);
83613513Sgabeblack@google.com            m_mod = mod;
83713513Sgabeblack@google.com            m_transport_dbg_ptr = p;
83813513Sgabeblack@google.com        }
83913511Sgabeblack@google.com
84013513Sgabeblack@google.com        void
84113513Sgabeblack@google.com        set_get_direct_mem_ptr(MODULE *mod, GetDirectMemPtr p)
84213513Sgabeblack@google.com        {
84313513Sgabeblack@google.com            if (m_get_direct_mem_ptr) {
84413513Sgabeblack@google.com                m_owner->display_warning(
84513513Sgabeblack@google.com                        "get DMI pointer callback already registered");
84613513Sgabeblack@google.com            }
84713513Sgabeblack@google.com            sc_assert(!m_mod || m_mod == mod);
84813513Sgabeblack@google.com            m_mod = mod;
84913513Sgabeblack@google.com            m_get_direct_mem_ptr = p;
85013513Sgabeblack@google.com        }
85113511Sgabeblack@google.com
85213513Sgabeblack@google.com        // Interface implementation.
85313513Sgabeblack@google.com        sync_enum_type
85413513Sgabeblack@google.com        nb_transport_fw(transaction_type &trans, phase_type &phase,
85513513Sgabeblack@google.com                        sc_core::sc_time &t)
85613513Sgabeblack@google.com        {
85713513Sgabeblack@google.com            if (m_nb_transport_ptr) {
85813513Sgabeblack@google.com                // Forward call.
85913513Sgabeblack@google.com                sc_assert(m_mod);
86013513Sgabeblack@google.com                return (m_mod->*m_nb_transport_ptr)(
86113513Sgabeblack@google.com                        m_nb_transport_user_id, trans, phase, t);
86213511Sgabeblack@google.com            }
86313511Sgabeblack@google.com
86413513Sgabeblack@google.com            // nb->b conversion
86513513Sgabeblack@google.com            if (m_b_transport_ptr) {
86613513Sgabeblack@google.com                if (phase == tlm::BEGIN_REQ) {
86713513Sgabeblack@google.com
86813513Sgabeblack@google.com                    // Prepare thread to do blocking call.
86913513Sgabeblack@google.com                    process_handle_class *ph =
87013513Sgabeblack@google.com                        m_process_handle.get_handle(&trans);
87113513Sgabeblack@google.com
87213513Sgabeblack@google.com                    if (!ph) { // Create new dynamic process.
87313513Sgabeblack@google.com                        ph = new process_handle_class(&trans);
87413513Sgabeblack@google.com                        m_process_handle.put_handle(ph);
87513513Sgabeblack@google.com
87613513Sgabeblack@google.com                        sc_core::sc_spawn_options opts;
87713513Sgabeblack@google.com                        opts.dont_initialize();
87813513Sgabeblack@google.com                        opts.set_sensitivity(&ph->m_e);
87913513Sgabeblack@google.com
88013513Sgabeblack@google.com                        sc_core::sc_spawn(
88113513Sgabeblack@google.com                                sc_bind(&fw_process::nb2b_thread, this, ph),
88213513Sgabeblack@google.com                                sc_core::sc_gen_unique_name("nb2b_thread"),
88313513Sgabeblack@google.com                                &opts);
88413513Sgabeblack@google.com                    }
88513513Sgabeblack@google.com
88613513Sgabeblack@google.com                    ph->m_e.notify(t);
88713513Sgabeblack@google.com                    return tlm::TLM_ACCEPTED;
88813513Sgabeblack@google.com                }
88913513Sgabeblack@google.com                if (phase == tlm::END_RESP) {
89013513Sgabeblack@google.com                    m_response_in_progress = false;
89113513Sgabeblack@google.com                    m_end_response.notify(t);
89213513Sgabeblack@google.com                    return tlm::TLM_COMPLETED;
89313513Sgabeblack@google.com                }
89413513Sgabeblack@google.com                m_owner->display_error("invalid phase");
89513513Sgabeblack@google.com                return tlm::TLM_COMPLETED;
89613511Sgabeblack@google.com            }
89713511Sgabeblack@google.com
89813513Sgabeblack@google.com            m_owner->display_error(
89913513Sgabeblack@google.com                    "no non-blocking transport callback registered");
90013513Sgabeblack@google.com            return tlm::TLM_COMPLETED;
90113511Sgabeblack@google.com        }
90213511Sgabeblack@google.com
90313513Sgabeblack@google.com        void
90413513Sgabeblack@google.com        b_transport(transaction_type &trans, sc_core::sc_time &t)
90513513Sgabeblack@google.com        {
90613513Sgabeblack@google.com            if (m_b_transport_ptr) {
90713513Sgabeblack@google.com                // Forward call.
90813513Sgabeblack@google.com                sc_assert(m_mod);
90913513Sgabeblack@google.com                (m_mod->*m_b_transport_ptr)(m_b_transport_user_id, trans, t);
91013513Sgabeblack@google.com                return;
91113513Sgabeblack@google.com            }
91213511Sgabeblack@google.com
91313513Sgabeblack@google.com            // b->nb conversion
91413513Sgabeblack@google.com            if (m_nb_transport_ptr) {
91513513Sgabeblack@google.com                m_peq.notify(trans, t);
91613513Sgabeblack@google.com                t = sc_core::SC_ZERO_TIME;
91713513Sgabeblack@google.com
91813513Sgabeblack@google.com                mm_end_event_ext mm_ext;
91913513Sgabeblack@google.com                const bool mm_added = !trans.has_mm();
92013513Sgabeblack@google.com
92113513Sgabeblack@google.com                if (mm_added) {
92213513Sgabeblack@google.com                    trans.set_mm(this);
92313513Sgabeblack@google.com                    trans.set_auto_extension(&mm_ext);
92413513Sgabeblack@google.com                    trans.acquire();
92513513Sgabeblack@google.com                }
92613513Sgabeblack@google.com
92713513Sgabeblack@google.com                // Wait until transaction is finished.
92813513Sgabeblack@google.com                sc_core::sc_event end_event;
92913513Sgabeblack@google.com                m_owner->m_pending_trans[&trans] = &end_event;
93013513Sgabeblack@google.com                sc_core::wait(end_event);
93113513Sgabeblack@google.com
93213513Sgabeblack@google.com                if (mm_added) {
93313513Sgabeblack@google.com                    // Release will not delete the transaction, it will
93413513Sgabeblack@google.com                    // notify mm_ext.done.
93513513Sgabeblack@google.com                    trans.release();
93613513Sgabeblack@google.com                    if (trans.get_ref_count()) {
93713513Sgabeblack@google.com                        sc_core::wait(mm_ext.done);
93813513Sgabeblack@google.com                    }
93913513Sgabeblack@google.com                    trans.set_mm(0);
94013513Sgabeblack@google.com                }
94113513Sgabeblack@google.com                return;
94213513Sgabeblack@google.com            }
94313513Sgabeblack@google.com
94413513Sgabeblack@google.com            m_owner->display_error("no transport callback registered");
94513513Sgabeblack@google.com        }
94613513Sgabeblack@google.com
94713513Sgabeblack@google.com        unsigned int
94813513Sgabeblack@google.com        transport_dbg(transaction_type &trans)
94913513Sgabeblack@google.com        {
95013513Sgabeblack@google.com            if (m_transport_dbg_ptr) {
95113513Sgabeblack@google.com                // Forward call.
95213513Sgabeblack@google.com                sc_assert(m_mod);
95313513Sgabeblack@google.com                return (m_mod->*m_transport_dbg_ptr)(
95413513Sgabeblack@google.com                        m_transport_dbg_user_id, trans);
95513513Sgabeblack@google.com            }
95613513Sgabeblack@google.com            // No debug support.
95713513Sgabeblack@google.com            return 0;
95813513Sgabeblack@google.com        }
95913513Sgabeblack@google.com
96013513Sgabeblack@google.com        bool
96113513Sgabeblack@google.com        get_direct_mem_ptr(transaction_type &trans, tlm::tlm_dmi &dmi_data)
96213513Sgabeblack@google.com        {
96313513Sgabeblack@google.com            if (m_get_direct_mem_ptr) {
96413513Sgabeblack@google.com                // Forward call.
96513513Sgabeblack@google.com                sc_assert(m_mod);
96613513Sgabeblack@google.com                return (m_mod->*m_get_direct_mem_ptr)(
96713513Sgabeblack@google.com                        m_get_dmi_user_id, trans, dmi_data);
96813513Sgabeblack@google.com            }
96913513Sgabeblack@google.com            // No DMI support.
97013513Sgabeblack@google.com            dmi_data.allow_read_write();
97113513Sgabeblack@google.com            dmi_data.set_start_address(0x0);
97213513Sgabeblack@google.com            dmi_data.set_end_address((sc_dt::uint64)-1);
97313513Sgabeblack@google.com            return false;
97413513Sgabeblack@google.com        }
97513513Sgabeblack@google.com
97613513Sgabeblack@google.com      private:
97713513Sgabeblack@google.com
97813513Sgabeblack@google.com        // Dynamic process handler for nb2b conversion.
97913513Sgabeblack@google.com        class process_handle_class
98013513Sgabeblack@google.com        {
98113513Sgabeblack@google.com          public:
98213513Sgabeblack@google.com            explicit process_handle_class(transaction_type *trans) :
98313513Sgabeblack@google.com                m_trans(trans), m_suspend(false)
98413513Sgabeblack@google.com            {}
98513513Sgabeblack@google.com
98613513Sgabeblack@google.com            transaction_type *m_trans;
98713513Sgabeblack@google.com            sc_core::sc_event  m_e;
98813513Sgabeblack@google.com            bool m_suspend;
98913513Sgabeblack@google.com        };
99013513Sgabeblack@google.com
99113513Sgabeblack@google.com        class process_handle_list
99213513Sgabeblack@google.com        {
99313513Sgabeblack@google.com          public:
99413513Sgabeblack@google.com            process_handle_list() {}
99513513Sgabeblack@google.com
99613513Sgabeblack@google.com            ~process_handle_list()
99713513Sgabeblack@google.com            {
99813513Sgabeblack@google.com                for (typename std::vector<
99913513Sgabeblack@google.com                        process_handle_class *>::iterator it = v.begin(),
100013513Sgabeblack@google.com                        end = v.end(); it != end; ++it) {
100113513Sgabeblack@google.com                    delete *it;
100213513Sgabeblack@google.com                }
100313513Sgabeblack@google.com            }
100413513Sgabeblack@google.com
100513513Sgabeblack@google.com            process_handle_class *
100613513Sgabeblack@google.com            get_handle(transaction_type *trans)
100713513Sgabeblack@google.com            {
100813513Sgabeblack@google.com                typename std::vector<process_handle_class *>::iterator it;
100913513Sgabeblack@google.com
101013513Sgabeblack@google.com                for (it = v.begin(); it != v.end(); it++) {
101113513Sgabeblack@google.com                    if ((*it)->m_suspend) {
101213513Sgabeblack@google.com                        // Found suspended dynamic process, re-use it.
101313513Sgabeblack@google.com                        (*it)->m_trans = trans; // Replace to new one.
101413513Sgabeblack@google.com                        (*it)->m_suspend = false;
101513513Sgabeblack@google.com                        return *it;
101613513Sgabeblack@google.com                    }
101713513Sgabeblack@google.com                }
101813513Sgabeblack@google.com                return NULL; // No suspended process.
101913513Sgabeblack@google.com            }
102013513Sgabeblack@google.com
102113513Sgabeblack@google.com            void put_handle(process_handle_class *ph) { v.push_back(ph); }
102213513Sgabeblack@google.com
102313513Sgabeblack@google.com          private:
102413513Sgabeblack@google.com            std::vector<process_handle_class *> v;
102513513Sgabeblack@google.com        };
102613513Sgabeblack@google.com
102713513Sgabeblack@google.com        process_handle_list m_process_handle;
102813513Sgabeblack@google.com
102913513Sgabeblack@google.com        void
103013513Sgabeblack@google.com        nb2b_thread(process_handle_class *h)
103113513Sgabeblack@google.com        {
103213513Sgabeblack@google.com
103313513Sgabeblack@google.com            while (1) {
103413513Sgabeblack@google.com                transaction_type *trans = h->m_trans;
103513513Sgabeblack@google.com                sc_core::sc_time t = sc_core::SC_ZERO_TIME;
103613513Sgabeblack@google.com
103713513Sgabeblack@google.com                // Forward call.
103813513Sgabeblack@google.com                sc_assert(m_mod);
103913513Sgabeblack@google.com                (m_mod->*m_b_transport_ptr)(
104013513Sgabeblack@google.com                        m_b_transport_user_id, *trans, t);
104113513Sgabeblack@google.com
104213513Sgabeblack@google.com                sc_core::wait(t);
104313513Sgabeblack@google.com
104413513Sgabeblack@google.com                // Return path.
104513513Sgabeblack@google.com                while (m_response_in_progress) {
104613513Sgabeblack@google.com                    sc_core::wait(m_end_response);
104713513Sgabeblack@google.com                }
104813513Sgabeblack@google.com                t = sc_core::SC_ZERO_TIME;
104913513Sgabeblack@google.com                phase_type phase = tlm::BEGIN_RESP;
105013513Sgabeblack@google.com                sync_enum_type sync =
105113513Sgabeblack@google.com                    m_owner->bw_nb_transport(*trans, phase, t);
105213513Sgabeblack@google.com                if (!(sync == tlm::TLM_COMPLETED ||
105313513Sgabeblack@google.com                            (sync == tlm::TLM_UPDATED &&
105413513Sgabeblack@google.com                             phase == tlm::END_RESP))) {
105513513Sgabeblack@google.com                    m_response_in_progress = true;
105613513Sgabeblack@google.com                }
105713513Sgabeblack@google.com
105813513Sgabeblack@google.com                // Suspend until next transaction.
105913513Sgabeblack@google.com                h->m_suspend = true;
106013513Sgabeblack@google.com                sc_core::wait();
106113513Sgabeblack@google.com            }
106213513Sgabeblack@google.com        }
106313513Sgabeblack@google.com
106413513Sgabeblack@google.com        void
106513513Sgabeblack@google.com        b2nb_thread()
106613513Sgabeblack@google.com        {
106713513Sgabeblack@google.com            while (true) {
106813513Sgabeblack@google.com                transaction_type *trans;
106913513Sgabeblack@google.com                while ((trans = m_peq.get_next_transaction()) != 0) {
107013513Sgabeblack@google.com                    sc_assert(m_mod);
107113513Sgabeblack@google.com                    sc_assert(m_nb_transport_ptr);
107213513Sgabeblack@google.com                    phase_type phase = tlm::BEGIN_REQ;
107313513Sgabeblack@google.com                    sc_core::sc_time t = sc_core::SC_ZERO_TIME;
107413513Sgabeblack@google.com
107513513Sgabeblack@google.com                    switch ((m_mod->*m_nb_transport_ptr)(
107613513Sgabeblack@google.com                                m_nb_transport_user_id, *trans, phase, t)) {
107713513Sgabeblack@google.com                      case tlm::TLM_COMPLETED:
107813513Sgabeblack@google.com                        {
107913513Sgabeblack@google.com                            // Notify transaction is finished.
108013513Sgabeblack@google.com                            typename std::map<transaction_type *,
108113513Sgabeblack@google.com                                     sc_core::sc_event *>::iterator it =
108213513Sgabeblack@google.com                                         m_owner->m_pending_trans.find(trans);
108313513Sgabeblack@google.com                            sc_assert(it != m_owner->m_pending_trans.end());
108413513Sgabeblack@google.com                            it->second->notify(t);
108513513Sgabeblack@google.com                            m_owner->m_pending_trans.erase(it);
108613513Sgabeblack@google.com                            break;
108713513Sgabeblack@google.com                        }
108813513Sgabeblack@google.com
108913513Sgabeblack@google.com                      case tlm::TLM_ACCEPTED:
109013513Sgabeblack@google.com                      case tlm::TLM_UPDATED:
109113513Sgabeblack@google.com                        switch (phase) {
109213513Sgabeblack@google.com                          case tlm::BEGIN_REQ:
109313513Sgabeblack@google.com                            m_owner->m_current_transaction = trans;
109413513Sgabeblack@google.com                            sc_core::wait(m_owner->m_end_request);
109513513Sgabeblack@google.com                            m_owner->m_current_transaction = 0;
109613513Sgabeblack@google.com                            break;
109713513Sgabeblack@google.com
109813513Sgabeblack@google.com                          case tlm::END_REQ:
109913513Sgabeblack@google.com                            sc_core::wait(t);
110013513Sgabeblack@google.com                            break;
110113513Sgabeblack@google.com
110213513Sgabeblack@google.com                          case tlm::BEGIN_RESP:
110313513Sgabeblack@google.com                            {
110413513Sgabeblack@google.com                                phase = tlm::END_RESP;
110513513Sgabeblack@google.com                                // This line is a bug fix added in TLM-2.0.2.
110613513Sgabeblack@google.com                                sc_core::wait(t);
110713513Sgabeblack@google.com                                t = sc_core::SC_ZERO_TIME;
110813513Sgabeblack@google.com                                (m_mod->*m_nb_transport_ptr)(
110913513Sgabeblack@google.com                                        m_nb_transport_user_id,
111013513Sgabeblack@google.com                                        *trans, phase, t);
111113513Sgabeblack@google.com
111213513Sgabeblack@google.com                                // Notify transaction is finished.
111313513Sgabeblack@google.com                                typename std::map<transaction_type *,
111413513Sgabeblack@google.com                                         sc_core::sc_event *>::iterator it =
111513513Sgabeblack@google.com                                             m_owner->m_pending_trans.find(
111613513Sgabeblack@google.com                                                     trans);
111713513Sgabeblack@google.com                                sc_assert(it !=
111813513Sgabeblack@google.com                                        m_owner->m_pending_trans.end());
111913513Sgabeblack@google.com                                it->second->notify(t);
112013513Sgabeblack@google.com                                m_owner->m_pending_trans.erase(it);
112113513Sgabeblack@google.com                                break;
112213513Sgabeblack@google.com                            }
112313513Sgabeblack@google.com
112413513Sgabeblack@google.com                          default:
112513513Sgabeblack@google.com                            m_owner->display_error("invalid phase received");
112613513Sgabeblack@google.com                        };
112713513Sgabeblack@google.com                        break;
112813513Sgabeblack@google.com
112913513Sgabeblack@google.com                      default:
113013513Sgabeblack@google.com                        m_owner->display_error("invalid sync value received");
113113513Sgabeblack@google.com                    }
113213513Sgabeblack@google.com                }
113313513Sgabeblack@google.com                sc_core::wait();
113413513Sgabeblack@google.com            }
113513513Sgabeblack@google.com        }
113613513Sgabeblack@google.com
113713513Sgabeblack@google.com        void
113813513Sgabeblack@google.com        free(tlm::tlm_generic_payload *trans)
113913513Sgabeblack@google.com        {
114013513Sgabeblack@google.com            mm_end_event_ext *ext =
114113513Sgabeblack@google.com                trans->template get_extension<mm_end_event_ext>();
114213513Sgabeblack@google.com            sc_assert(ext);
114313513Sgabeblack@google.com            // Notify event first before freeing extensions (reset).
114413513Sgabeblack@google.com            ext->done.notify();
114513513Sgabeblack@google.com            trans->reset();
114613513Sgabeblack@google.com        }
114713513Sgabeblack@google.com
114813513Sgabeblack@google.com      private:
114913513Sgabeblack@google.com        struct mm_end_event_ext : public tlm::tlm_extension<mm_end_event_ext>
115013513Sgabeblack@google.com        {
115113513Sgabeblack@google.com            tlm::tlm_extension_base *clone() const { return NULL; }
115213513Sgabeblack@google.com            void free() {}
115313513Sgabeblack@google.com            void copy_from(tlm::tlm_extension_base const &) {}
115413513Sgabeblack@google.com            sc_core::sc_event done;
115513513Sgabeblack@google.com        };
115613513Sgabeblack@google.com
115713513Sgabeblack@google.com      private:
115813513Sgabeblack@google.com        simple_target_socket_tagged_b *m_owner;
115913513Sgabeblack@google.com        MODULE *m_mod;
116013513Sgabeblack@google.com        NBTransportPtr m_nb_transport_ptr;
116113513Sgabeblack@google.com        BTransportPtr m_b_transport_ptr;
116213513Sgabeblack@google.com        TransportDbgPtr m_transport_dbg_ptr;
116313513Sgabeblack@google.com        GetDirectMemPtr m_get_direct_mem_ptr;
116413513Sgabeblack@google.com        int m_nb_transport_user_id;
116513513Sgabeblack@google.com        int m_b_transport_user_id;
116613513Sgabeblack@google.com        int m_transport_dbg_user_id;
116713513Sgabeblack@google.com        int m_get_dmi_user_id;
116813513Sgabeblack@google.com        peq_with_get<transaction_type> m_peq;
116913513Sgabeblack@google.com        bool m_response_in_progress;
117013513Sgabeblack@google.com        sc_core::sc_event m_end_response;
117113511Sgabeblack@google.com    };
117213511Sgabeblack@google.com
117313511Sgabeblack@google.com  private:
117413513Sgabeblack@google.com    const sc_core::sc_object *get_socket() const { return this; }
117513511Sgabeblack@google.com
117613513Sgabeblack@google.com  private:
117713513Sgabeblack@google.com    fw_process m_fw_process;
117813513Sgabeblack@google.com    bw_process m_bw_process;
117913513Sgabeblack@google.com    std::map<transaction_type *, sc_core::sc_event *> m_pending_trans;
118013513Sgabeblack@google.com    sc_core::sc_event m_end_request;
118113513Sgabeblack@google.com    transaction_type* m_current_transaction;
118213511Sgabeblack@google.com};
118313511Sgabeblack@google.com
118413513Sgabeblack@google.comtemplate <typename MODULE, unsigned int BUSWIDTH=32,
118513513Sgabeblack@google.com          typename TYPES=tlm::tlm_base_protocol_types>
118613513Sgabeblack@google.comclass simple_target_socket_tagged :
118713513Sgabeblack@google.com    public simple_target_socket_tagged_b<MODULE, BUSWIDTH, TYPES>
118813511Sgabeblack@google.com{
118913513Sgabeblack@google.com    typedef simple_target_socket_tagged_b<MODULE, BUSWIDTH, TYPES> socket_b;
119013513Sgabeblack@google.com  public:
119113513Sgabeblack@google.com    simple_target_socket_tagged() : socket_b() {}
119213513Sgabeblack@google.com    explicit simple_target_socket_tagged(const char *name) : socket_b(name) {}
119313511Sgabeblack@google.com};
119413511Sgabeblack@google.com
119513513Sgabeblack@google.comtemplate <typename MODULE, unsigned int BUSWIDTH=32,
119613513Sgabeblack@google.com          typename TYPES=tlm::tlm_base_protocol_types>
119713513Sgabeblack@google.comclass simple_target_socket_tagged_optional :
119813513Sgabeblack@google.com    public simple_target_socket_tagged_b<MODULE, BUSWIDTH, TYPES,
119913513Sgabeblack@google.com                                         sc_core::SC_ZERO_OR_MORE_BOUND>
120013511Sgabeblack@google.com{
120113513Sgabeblack@google.com    typedef simple_target_socket_tagged_b<
120213513Sgabeblack@google.com        MODULE, BUSWIDTH, TYPES, sc_core::SC_ZERO_OR_MORE_BOUND> socket_b;
120313511Sgabeblack@google.com  public:
120413513Sgabeblack@google.com    simple_target_socket_tagged_optional() : socket_b() {}
120513513Sgabeblack@google.com    explicit simple_target_socket_tagged_optional(const char *name) :
120613513Sgabeblack@google.com        socket_b(name)
120713511Sgabeblack@google.com    {}
120813511Sgabeblack@google.com};
120913511Sgabeblack@google.com
121013511Sgabeblack@google.com} // namespace tlm_utils
121113513Sgabeblack@google.com
121213513Sgabeblack@google.com#endif /* __SYSTEMC_EXT_TLM_UTILS_SIMPLE_TARGET_SOCKET_H__ */
1213