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"
2613743Sgabeblack@google.com#include "../core/sc_spawn.hh"
2713586Sgabeblack@google.com#include "../tlm_core/2/generic_payload/gp.hh"
2813586Sgabeblack@google.com#include "../tlm_core/2/interfaces/fw_bw_ifs.hh"
2913743Sgabeblack@google.com#include "../tlm_core/2/sockets/initiator_socket.hh"
3013586Sgabeblack@google.com#include "../tlm_core/2/sockets/target_socket.hh"
3113586Sgabeblack@google.com#include "../utils/sc_report_handler.hh"
3213586Sgabeblack@google.com#include "convenience_socket_bases.h"
3313586Sgabeblack@google.com#include "peq_with_get.h"
3413511Sgabeblack@google.com
3513513Sgabeblack@google.comnamespace tlm_utils
3613513Sgabeblack@google.com{
3713511Sgabeblack@google.com
3813513Sgabeblack@google.comtemplate <typename MODULE, unsigned int BUSWIDTH, typename TYPES,
3913513Sgabeblack@google.com          sc_core::sc_port_policy POL=sc_core::SC_ONE_OR_MORE_BOUND>
4013513Sgabeblack@google.comclass simple_target_socket_b :
4113513Sgabeblack@google.com    public tlm::tlm_target_socket<BUSWIDTH, TYPES, 1, POL>,
4213513Sgabeblack@google.com    protected simple_socket_base
4313511Sgabeblack@google.com{
4413513Sgabeblack@google.com    friend class fw_process;
4513513Sgabeblack@google.com    friend class bw_process;
4613513Sgabeblack@google.com  public:
4713513Sgabeblack@google.com    typedef typename TYPES::tlm_payload_type transaction_type;
4813513Sgabeblack@google.com    typedef typename TYPES::tlm_phase_type phase_type;
4913513Sgabeblack@google.com    typedef tlm::tlm_sync_enum sync_enum_type;
5013513Sgabeblack@google.com    typedef tlm::tlm_fw_transport_if<TYPES> fw_interface_type;
5113513Sgabeblack@google.com    typedef tlm::tlm_bw_transport_if<TYPES> bw_interface_type;
5213513Sgabeblack@google.com    typedef tlm::tlm_target_socket<BUSWIDTH, TYPES, 1, POL>  base_type;
5313511Sgabeblack@google.com
5413511Sgabeblack@google.com  public:
5513513Sgabeblack@google.com    static const char *
5613513Sgabeblack@google.com    default_name()
5713511Sgabeblack@google.com    {
5813513Sgabeblack@google.com        return sc_core::sc_gen_unique_name("simple_target_socket");
5913511Sgabeblack@google.com    }
6013511Sgabeblack@google.com
6113513Sgabeblack@google.com    explicit simple_target_socket_b(const char *n=default_name()) :
6213513Sgabeblack@google.com        base_type(n), m_fw_process(this), m_bw_process(this)
6313511Sgabeblack@google.com    {
6413513Sgabeblack@google.com        bind(m_fw_process);
6513511Sgabeblack@google.com    }
6613511Sgabeblack@google.com
6713513Sgabeblack@google.com    using base_type::bind;
6813513Sgabeblack@google.com
6913513Sgabeblack@google.com    // bw transport must come through us.
7013513Sgabeblack@google.com    tlm::tlm_bw_transport_if<TYPES> *operator -> () { return &m_bw_process; }
7113513Sgabeblack@google.com
7213513Sgabeblack@google.com    // REGISTER_XXX
7313513Sgabeblack@google.com    void
7413513Sgabeblack@google.com    register_nb_transport_fw(MODULE *mod,
7513513Sgabeblack@google.com            sync_enum_type (MODULE::*cb)(
7613513Sgabeblack@google.com                transaction_type &, phase_type &, sc_core::sc_time &))
7713511Sgabeblack@google.com    {
7813513Sgabeblack@google.com        elaboration_check("register_nb_transport_fw");
7913513Sgabeblack@google.com        m_fw_process.set_nb_transport_ptr(mod, cb);
8013513Sgabeblack@google.com    }
8113513Sgabeblack@google.com
8213513Sgabeblack@google.com    void
8313513Sgabeblack@google.com    register_b_transport(MODULE *mod,
8413513Sgabeblack@google.com            void (MODULE::*cb)(transaction_type &, sc_core::sc_time &))
8513513Sgabeblack@google.com    {
8613513Sgabeblack@google.com        elaboration_check("register_b_transport");
8713513Sgabeblack@google.com        m_fw_process.set_b_transport_ptr(mod, cb);
8813513Sgabeblack@google.com    }
8913513Sgabeblack@google.com
9013513Sgabeblack@google.com    void
9113513Sgabeblack@google.com    register_transport_dbg(MODULE *mod,
9213513Sgabeblack@google.com            unsigned int (MODULE::*cb)(transaction_type &))
9313513Sgabeblack@google.com    {
9413513Sgabeblack@google.com        elaboration_check("register_transport_dbg");
9513513Sgabeblack@google.com        m_fw_process.set_transport_dbg_ptr(mod, cb);
9613513Sgabeblack@google.com    }
9713513Sgabeblack@google.com
9813513Sgabeblack@google.com    void
9913513Sgabeblack@google.com    register_get_direct_mem_ptr(MODULE *mod,
10013513Sgabeblack@google.com            bool (MODULE::*cb)(transaction_type &, tlm::tlm_dmi &))
10113513Sgabeblack@google.com    {
10213513Sgabeblack@google.com        elaboration_check("register_get_direct_mem_ptr");
10313513Sgabeblack@google.com        m_fw_process.set_get_direct_mem_ptr(mod, cb);
10413513Sgabeblack@google.com    }
10513513Sgabeblack@google.com
10613513Sgabeblack@google.com  protected:
10713513Sgabeblack@google.com    void
10813513Sgabeblack@google.com    start_of_simulation()
10913513Sgabeblack@google.com    {
11013513Sgabeblack@google.com        base_type::start_of_simulation();
11113513Sgabeblack@google.com        m_fw_process.start_of_simulation();
11213511Sgabeblack@google.com    }
11313511Sgabeblack@google.com
11413511Sgabeblack@google.com  private:
11513513Sgabeblack@google.com    // Make call on bw path.
11613513Sgabeblack@google.com    sync_enum_type
11713513Sgabeblack@google.com    bw_nb_transport(transaction_type &trans, phase_type &phase,
11813513Sgabeblack@google.com                    sc_core::sc_time &t)
11913511Sgabeblack@google.com    {
12013513Sgabeblack@google.com        return base_type::operator -> ()->nb_transport_bw(trans, phase, t);
12113511Sgabeblack@google.com    }
12213511Sgabeblack@google.com
12313513Sgabeblack@google.com    void
12413513Sgabeblack@google.com    bw_invalidate_direct_mem_ptr(sc_dt::uint64 s, sc_dt::uint64 e)
12513511Sgabeblack@google.com    {
12613513Sgabeblack@google.com        base_type::operator -> ()->invalidate_direct_mem_ptr(s, e);
12713511Sgabeblack@google.com    }
12813511Sgabeblack@google.com
12913513Sgabeblack@google.com    // Helper class to handle bw path calls Needed to detect transaction end
13013513Sgabeblack@google.com    // when called from b_transport.
13113513Sgabeblack@google.com    class bw_process : public tlm::tlm_bw_transport_if<TYPES>
13213511Sgabeblack@google.com    {
13313513Sgabeblack@google.com      public:
13413513Sgabeblack@google.com        bw_process(simple_target_socket_b *p_own) : m_owner(p_own) {}
13513513Sgabeblack@google.com
13613513Sgabeblack@google.com        sync_enum_type
13713513Sgabeblack@google.com        nb_transport_bw(transaction_type &trans, phase_type &phase,
13813513Sgabeblack@google.com                        sc_core::sc_time &t)
13913513Sgabeblack@google.com        {
14013513Sgabeblack@google.com            typename std::map<transaction_type *,
14113513Sgabeblack@google.com                              sc_core::sc_event *>::iterator it =
14213513Sgabeblack@google.com                                  m_owner->m_pending_trans.find(&trans);
14313513Sgabeblack@google.com
14413513Sgabeblack@google.com            if (it == m_owner->m_pending_trans.end()) {
14513513Sgabeblack@google.com                // Not a blocking call, forward.
14613513Sgabeblack@google.com                return m_owner->bw_nb_transport(trans, phase, t);
14713513Sgabeblack@google.com
14813513Sgabeblack@google.com            }
14913513Sgabeblack@google.com
15013513Sgabeblack@google.com            if (phase == tlm::END_REQ) {
15113513Sgabeblack@google.com                m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME);
15213513Sgabeblack@google.com                return tlm::TLM_ACCEPTED;
15313513Sgabeblack@google.com            }
15413513Sgabeblack@google.com            if (phase == tlm::BEGIN_RESP) {
15513513Sgabeblack@google.com                if (m_owner->m_current_transaction == &trans) {
15613513Sgabeblack@google.com                    m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME);
15713513Sgabeblack@google.com                }
15813513Sgabeblack@google.com                it->second->notify(t);
15913513Sgabeblack@google.com                m_owner->m_pending_trans.erase(it);
16013513Sgabeblack@google.com                return tlm::TLM_COMPLETED;
16113513Sgabeblack@google.com            }
16213513Sgabeblack@google.com            m_owner->display_error("invalid phase received");
16313513Sgabeblack@google.com            return tlm::TLM_COMPLETED;
16413513Sgabeblack@google.com        }
16513513Sgabeblack@google.com
16613513Sgabeblack@google.com        void
16713513Sgabeblack@google.com        invalidate_direct_mem_ptr(sc_dt::uint64 s, sc_dt::uint64 e)
16813513Sgabeblack@google.com        {
16913513Sgabeblack@google.com            return m_owner->bw_invalidate_direct_mem_ptr(s, e);
17013513Sgabeblack@google.com        }
17113513Sgabeblack@google.com
17213513Sgabeblack@google.com      private:
17313513Sgabeblack@google.com        simple_target_socket_b *m_owner;
17413513Sgabeblack@google.com    };
17513513Sgabeblack@google.com
17613513Sgabeblack@google.com    class fw_process : public tlm::tlm_fw_transport_if<TYPES>,
17713513Sgabeblack@google.com                      public tlm::tlm_mm_interface
17813513Sgabeblack@google.com    {
17913513Sgabeblack@google.com      public:
18013513Sgabeblack@google.com        typedef sync_enum_type (MODULE::*NBTransportPtr)(
18113513Sgabeblack@google.com                transaction_type &, phase_type &, sc_core::sc_time &);
18213513Sgabeblack@google.com        typedef void (MODULE::*BTransportPtr)(
18313513Sgabeblack@google.com                transaction_type &, sc_core::sc_time &);
18413513Sgabeblack@google.com        typedef unsigned int (MODULE::*TransportDbgPtr)(transaction_type &);
18513513Sgabeblack@google.com        typedef bool (MODULE::*GetDirectMemPtr)(
18613513Sgabeblack@google.com                transaction_type &, tlm::tlm_dmi &);
18713513Sgabeblack@google.com
18813513Sgabeblack@google.com        fw_process(simple_target_socket_b *p_own) :
18913513Sgabeblack@google.com            m_owner(p_own), m_mod(0), m_nb_transport_ptr(0),
19013513Sgabeblack@google.com            m_b_transport_ptr(0), m_transport_dbg_ptr(0),
19113513Sgabeblack@google.com            m_get_direct_mem_ptr(0),
19213513Sgabeblack@google.com            m_peq(sc_core::sc_gen_unique_name("m_peq")),
19313513Sgabeblack@google.com            m_response_in_progress(false)
19413513Sgabeblack@google.com        {}
19513513Sgabeblack@google.com
19613513Sgabeblack@google.com        void
19713513Sgabeblack@google.com        start_of_simulation()
19813513Sgabeblack@google.com        {
19913513Sgabeblack@google.com            // Only spawn b2nb_thread, if needed.
20013513Sgabeblack@google.com            if (!m_b_transport_ptr && m_nb_transport_ptr) {
20113513Sgabeblack@google.com                sc_core::sc_spawn_options opts;
20213513Sgabeblack@google.com                opts.set_sensitivity(&m_peq.get_event());
20313513Sgabeblack@google.com                opts.dont_initialize();
20413513Sgabeblack@google.com                sc_core::sc_spawn(sc_bind(&fw_process::b2nb_thread, this),
20513513Sgabeblack@google.com                        sc_core::sc_gen_unique_name("b2nb_thread"), &opts);
20613513Sgabeblack@google.com            }
20713513Sgabeblack@google.com        }
20813513Sgabeblack@google.com
20913513Sgabeblack@google.com        void
21013513Sgabeblack@google.com        set_nb_transport_ptr(MODULE *mod, NBTransportPtr p)
21113513Sgabeblack@google.com        {
21213513Sgabeblack@google.com            if (m_nb_transport_ptr) {
21313513Sgabeblack@google.com                m_owner->display_warning(
21413513Sgabeblack@google.com                        "non-blocking callback already registered");
21513513Sgabeblack@google.com                return;
21613513Sgabeblack@google.com            }
21713513Sgabeblack@google.com            sc_assert(!m_mod || m_mod == mod);
21813513Sgabeblack@google.com            m_mod = mod;
21913513Sgabeblack@google.com            m_nb_transport_ptr = p;
22013513Sgabeblack@google.com        }
22113513Sgabeblack@google.com
22213513Sgabeblack@google.com        void
22313513Sgabeblack@google.com        set_b_transport_ptr(MODULE *mod, BTransportPtr p)
22413513Sgabeblack@google.com        {
22513513Sgabeblack@google.com            if (m_b_transport_ptr) {
22613513Sgabeblack@google.com                m_owner->display_warning(
22713513Sgabeblack@google.com                        "blocking callback already registered");
22813513Sgabeblack@google.com                return;
22913513Sgabeblack@google.com            }
23013513Sgabeblack@google.com            sc_assert(!m_mod || m_mod == mod);
23113513Sgabeblack@google.com            m_mod = mod;
23213513Sgabeblack@google.com            m_b_transport_ptr = p;
23313513Sgabeblack@google.com        }
23413513Sgabeblack@google.com
23513513Sgabeblack@google.com        void
23613513Sgabeblack@google.com        set_transport_dbg_ptr(MODULE *mod, TransportDbgPtr p)
23713513Sgabeblack@google.com        {
23813513Sgabeblack@google.com            if (m_transport_dbg_ptr) {
23913513Sgabeblack@google.com                m_owner->display_warning("debug callback already registered");
24013513Sgabeblack@google.com                return;
24113513Sgabeblack@google.com            }
24213513Sgabeblack@google.com            sc_assert(!m_mod || m_mod == mod);
24313513Sgabeblack@google.com            m_mod = mod;
24413513Sgabeblack@google.com            m_transport_dbg_ptr = p;
24513513Sgabeblack@google.com        }
24613513Sgabeblack@google.com
24713513Sgabeblack@google.com        void
24813513Sgabeblack@google.com        set_get_direct_mem_ptr(MODULE *mod, GetDirectMemPtr p)
24913513Sgabeblack@google.com        {
25013513Sgabeblack@google.com            if (m_get_direct_mem_ptr) {
25113513Sgabeblack@google.com                m_owner->display_warning(
25213513Sgabeblack@google.com                        "get DMI pointer callback already registered");
25313513Sgabeblack@google.com                return;
25413513Sgabeblack@google.com            }
25513513Sgabeblack@google.com            sc_assert(!m_mod || m_mod == mod);
25613513Sgabeblack@google.com            m_mod = mod;
25713513Sgabeblack@google.com            m_get_direct_mem_ptr = p;
25813513Sgabeblack@google.com        }
25913513Sgabeblack@google.com
26013513Sgabeblack@google.com        // Interface implementation.
26113513Sgabeblack@google.com        sync_enum_type
26213513Sgabeblack@google.com        nb_transport_fw(transaction_type &trans, phase_type &phase,
26313513Sgabeblack@google.com                        sc_core::sc_time & t)
26413513Sgabeblack@google.com        {
26513513Sgabeblack@google.com            if (m_nb_transport_ptr) {
26613513Sgabeblack@google.com                // Forward call.
26713513Sgabeblack@google.com                sc_assert(m_mod);
26813513Sgabeblack@google.com                return (m_mod->*m_nb_transport_ptr)(trans, phase, t);
26913513Sgabeblack@google.com            }
27013513Sgabeblack@google.com
27113513Sgabeblack@google.com            // nb->b conversion
27213513Sgabeblack@google.com            if (m_b_transport_ptr) {
27313513Sgabeblack@google.com                if (phase == tlm::BEGIN_REQ) {
27413513Sgabeblack@google.com                    // Prepare thread to do blocking call.
27513513Sgabeblack@google.com                    process_handle_class *ph =
27613513Sgabeblack@google.com                        m_process_handle.get_handle(&trans);
27713513Sgabeblack@google.com
27813513Sgabeblack@google.com                    if (!ph) { // Create new dynamic process.
27913513Sgabeblack@google.com                        ph = new process_handle_class(&trans);
28013513Sgabeblack@google.com                        m_process_handle.put_handle(ph);
28113513Sgabeblack@google.com
28213513Sgabeblack@google.com                        sc_core::sc_spawn_options opts;
28313513Sgabeblack@google.com                        opts.dont_initialize();
28413513Sgabeblack@google.com                        opts.set_sensitivity(&ph->m_e);
28513513Sgabeblack@google.com
28613513Sgabeblack@google.com                        sc_core::sc_spawn(
28713513Sgabeblack@google.com                                sc_bind(&fw_process::nb2b_thread, this, ph),
28813513Sgabeblack@google.com                                sc_core::sc_gen_unique_name("nb2b_thread"),
28913513Sgabeblack@google.com                                &opts);
29013513Sgabeblack@google.com                    }
29113513Sgabeblack@google.com
29213513Sgabeblack@google.com                    ph->m_e.notify(t);
29313513Sgabeblack@google.com                    return tlm::TLM_ACCEPTED;
29413513Sgabeblack@google.com                }
29513513Sgabeblack@google.com                if (phase == tlm::END_RESP) {
29613513Sgabeblack@google.com                    m_response_in_progress = false;
29713513Sgabeblack@google.com                    m_end_response.notify(t);
29813513Sgabeblack@google.com                    return tlm::TLM_COMPLETED;
29913513Sgabeblack@google.com                }
30013513Sgabeblack@google.com                m_owner->display_error("invalid phase received");
30113513Sgabeblack@google.com                return tlm::TLM_COMPLETED;
30213513Sgabeblack@google.com            }
30313513Sgabeblack@google.com             m_owner->display_error(
30413513Sgabeblack@google.com                     "no non-blocking transport callback registered");
30513513Sgabeblack@google.com            return tlm::TLM_COMPLETED;
30613513Sgabeblack@google.com        }
30713513Sgabeblack@google.com
30813513Sgabeblack@google.com        void
30913513Sgabeblack@google.com        b_transport(transaction_type &trans, sc_core::sc_time &t)
31013513Sgabeblack@google.com        {
31113513Sgabeblack@google.com            if (m_b_transport_ptr) {
31213513Sgabeblack@google.com                // Forward call.
31313513Sgabeblack@google.com                sc_assert(m_mod);
31413513Sgabeblack@google.com                (m_mod->*m_b_transport_ptr)(trans, t);
31513513Sgabeblack@google.com                return;
31613513Sgabeblack@google.com            }
31713513Sgabeblack@google.com
31813513Sgabeblack@google.com            // b->nb conversion
31913513Sgabeblack@google.com            if (m_nb_transport_ptr) {
32013513Sgabeblack@google.com                m_peq.notify(trans, t);
32113513Sgabeblack@google.com                t = sc_core::SC_ZERO_TIME;
32213513Sgabeblack@google.com
32313513Sgabeblack@google.com                mm_end_event_ext mm_ext;
32413513Sgabeblack@google.com                const bool mm_added = !trans.has_mm();
32513513Sgabeblack@google.com
32613513Sgabeblack@google.com                if (mm_added) {
32713513Sgabeblack@google.com                    trans.set_mm(this);
32813513Sgabeblack@google.com                    trans.set_auto_extension(&mm_ext);
32913513Sgabeblack@google.com                    trans.acquire();
33013513Sgabeblack@google.com                }
33113513Sgabeblack@google.com
33213513Sgabeblack@google.com                // Wait until transaction is finished.
33313513Sgabeblack@google.com                sc_core::sc_event end_event;
33413513Sgabeblack@google.com                m_owner->m_pending_trans[&trans] = &end_event;
33513513Sgabeblack@google.com                sc_core::wait(end_event);
33613513Sgabeblack@google.com
33713513Sgabeblack@google.com                if (mm_added) {
33813513Sgabeblack@google.com                    // Release will not delete the transaction, it will
33913513Sgabeblack@google.com                    // notify mm_ext.done.
34013513Sgabeblack@google.com                    trans.release();
34113513Sgabeblack@google.com                    if (trans.get_ref_count()) {
34213513Sgabeblack@google.com                        sc_core::wait(mm_ext.done);
34313513Sgabeblack@google.com                    }
34413513Sgabeblack@google.com                    trans.set_mm(0);
34513513Sgabeblack@google.com                }
34613513Sgabeblack@google.com                return;
34713513Sgabeblack@google.com            }
34813513Sgabeblack@google.com
34913513Sgabeblack@google.com            // Should not be reached.
35013513Sgabeblack@google.com            m_owner->display_error(
35113513Sgabeblack@google.com                    "no blocking transport callback registered");
35213513Sgabeblack@google.com        }
35313513Sgabeblack@google.com
35413513Sgabeblack@google.com        unsigned int
35513513Sgabeblack@google.com        transport_dbg(transaction_type &trans)
35613513Sgabeblack@google.com        {
35713513Sgabeblack@google.com            if (m_transport_dbg_ptr) {
35813513Sgabeblack@google.com                // Forward call.
35913513Sgabeblack@google.com                sc_assert(m_mod);
36013513Sgabeblack@google.com                return (m_mod->*m_transport_dbg_ptr)(trans);
36113513Sgabeblack@google.com            }
36213513Sgabeblack@google.com            // No debug support.
36313513Sgabeblack@google.com            return 0;
36413513Sgabeblack@google.com        }
36513513Sgabeblack@google.com
36613513Sgabeblack@google.com        bool
36713513Sgabeblack@google.com        get_direct_mem_ptr(transaction_type &trans, tlm::tlm_dmi &dmi_data)
36813513Sgabeblack@google.com        {
36913513Sgabeblack@google.com            if (m_get_direct_mem_ptr) {
37013513Sgabeblack@google.com                // Forward call.
37113513Sgabeblack@google.com                sc_assert(m_mod);
37213513Sgabeblack@google.com                return (m_mod->*m_get_direct_mem_ptr)(trans, dmi_data);
37313513Sgabeblack@google.com            }
37413513Sgabeblack@google.com            // No DMI support.
37513513Sgabeblack@google.com            dmi_data.allow_read_write();
37613513Sgabeblack@google.com            dmi_data.set_start_address(0x0);
37713513Sgabeblack@google.com            dmi_data.set_end_address((sc_dt::uint64)-1);
37813513Sgabeblack@google.com            return false;
37913513Sgabeblack@google.com        }
38013513Sgabeblack@google.com
38113513Sgabeblack@google.com      private:
38213513Sgabeblack@google.com
38313513Sgabeblack@google.com        // Dynamic process handler for nb2b conversion.
38413513Sgabeblack@google.com
38513513Sgabeblack@google.com        class process_handle_class
38613513Sgabeblack@google.com        {
38713513Sgabeblack@google.com          public:
38813513Sgabeblack@google.com            explicit process_handle_class(transaction_type *trans) :
38913513Sgabeblack@google.com                m_trans(trans), m_suspend(false)
39013513Sgabeblack@google.com            {}
39113513Sgabeblack@google.com
39213513Sgabeblack@google.com            transaction_type *m_trans;
39313513Sgabeblack@google.com            sc_core::sc_event m_e;
39413513Sgabeblack@google.com            bool m_suspend;
39513513Sgabeblack@google.com        };
39613513Sgabeblack@google.com
39713513Sgabeblack@google.com        class process_handle_list
39813513Sgabeblack@google.com        {
39913513Sgabeblack@google.com          public:
40013513Sgabeblack@google.com            process_handle_list() {}
40113513Sgabeblack@google.com
40213513Sgabeblack@google.com            ~process_handle_list()
40313513Sgabeblack@google.com            {
40413513Sgabeblack@google.com                for (typename std::vector<
40513513Sgabeblack@google.com                        process_handle_class *>::iterator it = v.begin(),
40613513Sgabeblack@google.com                        end = v.end(); it != end; ++it) {
40713513Sgabeblack@google.com                    delete *it;
40813513Sgabeblack@google.com                }
40913513Sgabeblack@google.com            }
41013513Sgabeblack@google.com
41113513Sgabeblack@google.com            process_handle_class *
41213513Sgabeblack@google.com            get_handle(transaction_type *trans)
41313513Sgabeblack@google.com            {
41413513Sgabeblack@google.com                typename std::vector<process_handle_class *>::iterator it;
41513513Sgabeblack@google.com
41613513Sgabeblack@google.com                for (it = v.begin(); it != v.end(); it++) {
41713513Sgabeblack@google.com                    if ((*it)->m_suspend) {
41813513Sgabeblack@google.com                        // Found suspended dynamic process, re-use it.
41913513Sgabeblack@google.com                        (*it)->m_trans = trans; // Replace to new one.
42013513Sgabeblack@google.com                        (*it)->m_suspend = false;
42113513Sgabeblack@google.com                        return *it;
42213513Sgabeblack@google.com                    }
42313513Sgabeblack@google.com                }
42413513Sgabeblack@google.com                return NULL; // No suspended process.
42513513Sgabeblack@google.com            }
42613513Sgabeblack@google.com
42713513Sgabeblack@google.com            void
42813513Sgabeblack@google.com            put_handle(process_handle_class *ph)
42913513Sgabeblack@google.com            {
43013513Sgabeblack@google.com                v.push_back(ph);
43113513Sgabeblack@google.com            }
43213513Sgabeblack@google.com
43313513Sgabeblack@google.com          private:
43413513Sgabeblack@google.com            std::vector<process_handle_class*> v;
43513513Sgabeblack@google.com        };
43613513Sgabeblack@google.com
43713513Sgabeblack@google.com        process_handle_list m_process_handle;
43813513Sgabeblack@google.com
43913513Sgabeblack@google.com        void
44013513Sgabeblack@google.com        nb2b_thread(process_handle_class *h)
44113513Sgabeblack@google.com        {
44213513Sgabeblack@google.com            while (1) {
44313513Sgabeblack@google.com                transaction_type *trans = h->m_trans;
44413513Sgabeblack@google.com                sc_core::sc_time t = sc_core::SC_ZERO_TIME;
44513513Sgabeblack@google.com
44613513Sgabeblack@google.com                // Forward call.
44713513Sgabeblack@google.com                sc_assert(m_mod);
44813513Sgabeblack@google.com                (m_mod->*m_b_transport_ptr)(*trans, t);
44913513Sgabeblack@google.com
45013513Sgabeblack@google.com                sc_core::wait(t);
45113513Sgabeblack@google.com
45213513Sgabeblack@google.com                // Return path.
45313513Sgabeblack@google.com                while (m_response_in_progress) {
45413513Sgabeblack@google.com                    sc_core::wait(m_end_response);
45513513Sgabeblack@google.com                }
45613513Sgabeblack@google.com                t = sc_core::SC_ZERO_TIME;
45713513Sgabeblack@google.com                phase_type phase = tlm::BEGIN_RESP;
45813513Sgabeblack@google.com                sync_enum_type sync =
45913513Sgabeblack@google.com                    m_owner->bw_nb_transport(*trans, phase, t);
46013513Sgabeblack@google.com                if (!(sync == tlm::TLM_COMPLETED ||
46113513Sgabeblack@google.com                            (sync == tlm::TLM_UPDATED &&
46213513Sgabeblack@google.com                             phase == tlm::END_RESP))) {
46313513Sgabeblack@google.com                    m_response_in_progress = true;
46413513Sgabeblack@google.com                }
46513513Sgabeblack@google.com
46613513Sgabeblack@google.com                // Suspend until next transaction.
46713513Sgabeblack@google.com                h->m_suspend = true;
46813513Sgabeblack@google.com                sc_core::wait();
46913513Sgabeblack@google.com            }
47013513Sgabeblack@google.com        }
47113513Sgabeblack@google.com
47213513Sgabeblack@google.com        void
47313513Sgabeblack@google.com        b2nb_thread()
47413513Sgabeblack@google.com        {
47513513Sgabeblack@google.com            while (true) {
47613513Sgabeblack@google.com                transaction_type *trans;
47713513Sgabeblack@google.com                while ((trans = m_peq.get_next_transaction()) != 0) {
47813513Sgabeblack@google.com                    sc_assert(m_mod);
47913513Sgabeblack@google.com                    sc_assert(m_nb_transport_ptr);
48013513Sgabeblack@google.com                    phase_type phase = tlm::BEGIN_REQ;
48113513Sgabeblack@google.com                    sc_core::sc_time t = sc_core::SC_ZERO_TIME;
48213513Sgabeblack@google.com
48313513Sgabeblack@google.com                    switch ((m_mod->*m_nb_transport_ptr)(*trans, phase, t)) {
48413513Sgabeblack@google.com                      case tlm::TLM_COMPLETED:
48513513Sgabeblack@google.com                        {
48613513Sgabeblack@google.com                            // Notify transaction is finished.
48713513Sgabeblack@google.com                            typename std::map<transaction_type *,
48813513Sgabeblack@google.com                                     sc_core::sc_event *>::iterator it =
48913513Sgabeblack@google.com                                         m_owner->m_pending_trans.find(trans);
49013513Sgabeblack@google.com                            sc_assert(it != m_owner->m_pending_trans.end());
49113513Sgabeblack@google.com                            it->second->notify(t);
49213513Sgabeblack@google.com                            m_owner->m_pending_trans.erase(it);
49313513Sgabeblack@google.com                            break;
49413513Sgabeblack@google.com                        }
49513513Sgabeblack@google.com
49613513Sgabeblack@google.com                      case tlm::TLM_ACCEPTED:
49713513Sgabeblack@google.com                      case tlm::TLM_UPDATED:
49813513Sgabeblack@google.com                        switch (phase) {
49913513Sgabeblack@google.com                          case tlm::BEGIN_REQ:
50013513Sgabeblack@google.com                            m_owner->m_current_transaction = trans;
50113513Sgabeblack@google.com                            sc_core::wait(m_owner->m_end_request);
50213513Sgabeblack@google.com                            m_owner->m_current_transaction = 0;
50313513Sgabeblack@google.com                            break;
50413513Sgabeblack@google.com
50513513Sgabeblack@google.com                          case tlm::END_REQ:
50613513Sgabeblack@google.com                            sc_core::wait(t);
50713513Sgabeblack@google.com                            break;
50813513Sgabeblack@google.com
50913513Sgabeblack@google.com                          case tlm::BEGIN_RESP:
51013513Sgabeblack@google.com                            {
51113513Sgabeblack@google.com                                phase = tlm::END_RESP;
51213513Sgabeblack@google.com                                // This line is a bug fix added in TLM-2.0.2
51313513Sgabeblack@google.com                                sc_core::wait(t);
51413513Sgabeblack@google.com                                t = sc_core::SC_ZERO_TIME;
51513513Sgabeblack@google.com                                (m_mod->*m_nb_transport_ptr)(
51613513Sgabeblack@google.com                                        *trans, phase, t);
51713513Sgabeblack@google.com
51813513Sgabeblack@google.com                                // Notify transaction is finished.
51913513Sgabeblack@google.com                                typename std::map<transaction_type *,
52013513Sgabeblack@google.com                                         sc_core::sc_event *>::iterator it =
52113513Sgabeblack@google.com                                             m_owner->m_pending_trans.find(
52213513Sgabeblack@google.com                                                     trans);
52313513Sgabeblack@google.com                                sc_assert(it !=
52413513Sgabeblack@google.com                                        m_owner->m_pending_trans.end());
52513513Sgabeblack@google.com                                it->second->notify(t);
52613513Sgabeblack@google.com                                m_owner->m_pending_trans.erase(it);
52713513Sgabeblack@google.com                                break;
52813513Sgabeblack@google.com                            }
52913513Sgabeblack@google.com
53013513Sgabeblack@google.com                          default:
53113513Sgabeblack@google.com                            m_owner->display_error("invalid phase received");
53213513Sgabeblack@google.com                        }
53313513Sgabeblack@google.com                        break;
53413513Sgabeblack@google.com
53513513Sgabeblack@google.com                      default:
53613513Sgabeblack@google.com                        m_owner->display_error("invalid sync value received");
53713513Sgabeblack@google.com                    }
53813513Sgabeblack@google.com                }
53913513Sgabeblack@google.com                sc_core::wait();
54013513Sgabeblack@google.com            }
54113513Sgabeblack@google.com        }
54213513Sgabeblack@google.com
54313513Sgabeblack@google.com        void
54413513Sgabeblack@google.com        free(tlm::tlm_generic_payload *trans)
54513513Sgabeblack@google.com        {
54613513Sgabeblack@google.com            mm_end_event_ext *ext =
54713513Sgabeblack@google.com                trans->template get_extension<mm_end_event_ext>();
54813513Sgabeblack@google.com            sc_assert(ext);
54913513Sgabeblack@google.com            // Notify event first before freeing extensions (reset).
55013513Sgabeblack@google.com            ext->done.notify();
55113513Sgabeblack@google.com            trans->reset();
55213513Sgabeblack@google.com        }
55313513Sgabeblack@google.com
55413513Sgabeblack@google.com      private:
55513513Sgabeblack@google.com        struct mm_end_event_ext : public tlm::tlm_extension<mm_end_event_ext>
55613513Sgabeblack@google.com        {
55713513Sgabeblack@google.com            tlm::tlm_extension_base *clone() const { return NULL; }
55813513Sgabeblack@google.com            void free() {}
55913513Sgabeblack@google.com            void copy_from(tlm::tlm_extension_base const &) {}
56013513Sgabeblack@google.com            sc_core::sc_event done;
56113513Sgabeblack@google.com        };
56213513Sgabeblack@google.com
56313513Sgabeblack@google.com      private:
56413513Sgabeblack@google.com        simple_target_socket_b *m_owner;
56513513Sgabeblack@google.com        MODULE *m_mod;
56613513Sgabeblack@google.com        NBTransportPtr m_nb_transport_ptr;
56713513Sgabeblack@google.com        BTransportPtr m_b_transport_ptr;
56813513Sgabeblack@google.com        TransportDbgPtr m_transport_dbg_ptr;
56913513Sgabeblack@google.com        GetDirectMemPtr m_get_direct_mem_ptr;
57013513Sgabeblack@google.com        peq_with_get<transaction_type> m_peq;
57113513Sgabeblack@google.com        bool m_response_in_progress;
57213513Sgabeblack@google.com        sc_core::sc_event m_end_response;
57313513Sgabeblack@google.com    };
57413513Sgabeblack@google.com
57513513Sgabeblack@google.com  private:
57613513Sgabeblack@google.com    const sc_core::sc_object *get_socket() const { return this; }
57713513Sgabeblack@google.com
57813513Sgabeblack@google.com  private:
57913513Sgabeblack@google.com    fw_process m_fw_process;
58013513Sgabeblack@google.com    bw_process m_bw_process;
58113513Sgabeblack@google.com    std::map<transaction_type *, sc_core::sc_event *> m_pending_trans;
58213513Sgabeblack@google.com    sc_core::sc_event m_end_request;
58313513Sgabeblack@google.com    transaction_type* m_current_transaction;
58413513Sgabeblack@google.com};
58513513Sgabeblack@google.com
58613513Sgabeblack@google.comtemplate <typename MODULE, unsigned int BUSWIDTH=32,
58713513Sgabeblack@google.com          typename TYPES=tlm::tlm_base_protocol_types>
58813513Sgabeblack@google.comclass simple_target_socket :
58913513Sgabeblack@google.com    public simple_target_socket_b<MODULE, BUSWIDTH, TYPES>
59013513Sgabeblack@google.com{
59113513Sgabeblack@google.com    typedef simple_target_socket_b<MODULE, BUSWIDTH, TYPES> socket_b;
59213513Sgabeblack@google.com  public:
59313513Sgabeblack@google.com    simple_target_socket() : socket_b() {}
59413513Sgabeblack@google.com    explicit simple_target_socket(const char *name) : socket_b(name) {}
59513513Sgabeblack@google.com};
59613513Sgabeblack@google.com
59713513Sgabeblack@google.comtemplate <typename MODULE, unsigned int BUSWIDTH=32,
59813513Sgabeblack@google.com          typename TYPES=tlm::tlm_base_protocol_types>
59913513Sgabeblack@google.comclass simple_target_socket_optional :
60013513Sgabeblack@google.com    public simple_target_socket_b<MODULE, BUSWIDTH, TYPES,
60113513Sgabeblack@google.com                                  sc_core::SC_ZERO_OR_MORE_BOUND>
60213513Sgabeblack@google.com{
60313513Sgabeblack@google.com    typedef simple_target_socket_b<MODULE, BUSWIDTH, TYPES,
60413513Sgabeblack@google.com                                   sc_core::SC_ZERO_OR_MORE_BOUND> socket_b;
60513513Sgabeblack@google.com  public:
60613513Sgabeblack@google.com    simple_target_socket_optional() : socket_b() {}
60713513Sgabeblack@google.com    explicit simple_target_socket_optional(const char *name) :
60813513Sgabeblack@google.com        socket_b(name)
60913513Sgabeblack@google.com    {}
61013513Sgabeblack@google.com};
61113513Sgabeblack@google.com
61213513Sgabeblack@google.com// ID Tagged version.
61313513Sgabeblack@google.comtemplate <typename MODULE, unsigned int BUSWIDTH, typename TYPES,
61413513Sgabeblack@google.com          sc_core::sc_port_policy POL=sc_core::SC_ONE_OR_MORE_BOUND>
61513513Sgabeblack@google.comclass simple_target_socket_tagged_b :
61613513Sgabeblack@google.com    public tlm::tlm_target_socket<BUSWIDTH, TYPES, 1, POL>,
61713513Sgabeblack@google.com    protected simple_socket_base
61813513Sgabeblack@google.com{
61913513Sgabeblack@google.com    friend class fw_process;
62013513Sgabeblack@google.com    friend class bw_process;
62113513Sgabeblack@google.com  public:
62213513Sgabeblack@google.com    typedef typename TYPES::tlm_payload_type transaction_type;
62313513Sgabeblack@google.com    typedef typename TYPES::tlm_phase_type phase_type;
62413513Sgabeblack@google.com    typedef tlm::tlm_sync_enum sync_enum_type;
62513513Sgabeblack@google.com    typedef tlm::tlm_fw_transport_if<TYPES> fw_interface_type;
62613513Sgabeblack@google.com    typedef tlm::tlm_bw_transport_if<TYPES> bw_interface_type;
62713513Sgabeblack@google.com    typedef tlm::tlm_target_socket<BUSWIDTH, TYPES, 1, POL> base_type;
62813513Sgabeblack@google.com
62913513Sgabeblack@google.com  public:
63013513Sgabeblack@google.com    static const char *
63113513Sgabeblack@google.com    default_name()
63213513Sgabeblack@google.com    {
63313513Sgabeblack@google.com        return sc_core::sc_gen_unique_name("simple_target_socket_tagged");
63413511Sgabeblack@google.com    }
63513511Sgabeblack@google.com
63613513Sgabeblack@google.com    explicit simple_target_socket_tagged_b(const char *n=default_name()) :
63713513Sgabeblack@google.com        base_type(n), m_fw_process(this), m_bw_process(this)
63813511Sgabeblack@google.com    {
63913513Sgabeblack@google.com        bind(m_fw_process);
64013511Sgabeblack@google.com    }
64113511Sgabeblack@google.com
64213513Sgabeblack@google.com    using base_type::bind;
64313513Sgabeblack@google.com
64413513Sgabeblack@google.com    // bw transport must come through us.
64513513Sgabeblack@google.com    tlm::tlm_bw_transport_if<TYPES> *operator -> () { return &m_bw_process; }
64613513Sgabeblack@google.com
64713513Sgabeblack@google.com    // REGISTER_XXX
64813513Sgabeblack@google.com    void
64913513Sgabeblack@google.com    register_nb_transport_fw(MODULE *mod,
65013513Sgabeblack@google.com            sync_enum_type (MODULE::*cb)(int id, transaction_type &,
65113513Sgabeblack@google.com                                         phase_type &, sc_core::sc_time &),
65213513Sgabeblack@google.com            int id)
65313511Sgabeblack@google.com    {
65413513Sgabeblack@google.com        elaboration_check("register_nb_transport_fw");
65513513Sgabeblack@google.com        m_fw_process.set_nb_transport_ptr(mod, cb);
65613513Sgabeblack@google.com        m_fw_process.set_nb_transport_user_id(id);
65713511Sgabeblack@google.com    }
65813511Sgabeblack@google.com
65913513Sgabeblack@google.com    void
66013513Sgabeblack@google.com    register_b_transport(MODULE *mod,
66113513Sgabeblack@google.com            void (MODULE::*cb)(int id, transaction_type &,
66213513Sgabeblack@google.com                               sc_core::sc_time &),
66313513Sgabeblack@google.com            int id)
66413511Sgabeblack@google.com    {
66513513Sgabeblack@google.com        elaboration_check("register_b_transport");
66613513Sgabeblack@google.com        m_fw_process.set_b_transport_ptr(mod, cb);
66713513Sgabeblack@google.com        m_fw_process.set_b_transport_user_id(id);
66813511Sgabeblack@google.com    }
66913511Sgabeblack@google.com
67013513Sgabeblack@google.com    void
67113513Sgabeblack@google.com    register_transport_dbg(MODULE *mod,
67213513Sgabeblack@google.com            unsigned int (MODULE::*cb)(int id, transaction_type &), int id)
67313511Sgabeblack@google.com    {
67413513Sgabeblack@google.com        elaboration_check("register_transport_dbg");
67513513Sgabeblack@google.com        m_fw_process.set_transport_dbg_ptr(mod, cb);
67613513Sgabeblack@google.com        m_fw_process.set_transport_dbg_user_id(id);
67713511Sgabeblack@google.com    }
67813511Sgabeblack@google.com
67913513Sgabeblack@google.com    void
68013513Sgabeblack@google.com    register_get_direct_mem_ptr(MODULE *mod,
68113513Sgabeblack@google.com            bool (MODULE::*cb)(int id, transaction_type &, tlm::tlm_dmi &),
68213513Sgabeblack@google.com            int id)
68313511Sgabeblack@google.com    {
68413513Sgabeblack@google.com        elaboration_check("register_get_direct_mem_ptr");
68513513Sgabeblack@google.com        m_fw_process.set_get_direct_mem_ptr(mod, cb);
68613513Sgabeblack@google.com        m_fw_process.set_get_dmi_user_id(id);
68713513Sgabeblack@google.com    }
68813513Sgabeblack@google.com
68913513Sgabeblack@google.com  protected:
69013513Sgabeblack@google.com    void
69113513Sgabeblack@google.com    start_of_simulation()
69213513Sgabeblack@google.com    {
69313513Sgabeblack@google.com        base_type::start_of_simulation();
69413513Sgabeblack@google.com        m_fw_process.start_of_simulation();
69513511Sgabeblack@google.com    }
69613511Sgabeblack@google.com
69713511Sgabeblack@google.com  private:
69813513Sgabeblack@google.com    // Make call on bw path.
69913513Sgabeblack@google.com    sync_enum_type
70013513Sgabeblack@google.com    bw_nb_transport(transaction_type &trans, phase_type &phase,
70113513Sgabeblack@google.com                    sc_core::sc_time &t)
70213513Sgabeblack@google.com    {
70313513Sgabeblack@google.com        return base_type::operator -> ()->nb_transport_bw(trans, phase, t);
70413513Sgabeblack@google.com    }
70513511Sgabeblack@google.com
70613513Sgabeblack@google.com    void
70713513Sgabeblack@google.com    bw_invalidate_direct_mem_ptr(sc_dt::uint64 s, sc_dt::uint64 e)
70813513Sgabeblack@google.com    {
70913513Sgabeblack@google.com        base_type::operator -> ()->invalidate_direct_mem_ptr(s, e);
71013513Sgabeblack@google.com    }
71113511Sgabeblack@google.com
71213513Sgabeblack@google.com    // Helper class to handle bw path calls Needed to detect transaction
71313513Sgabeblack@google.com    // end when called from b_transport.
71413513Sgabeblack@google.com    class bw_process : public tlm::tlm_bw_transport_if<TYPES>
71513513Sgabeblack@google.com    {
71613513Sgabeblack@google.com      public:
71713513Sgabeblack@google.com        bw_process(simple_target_socket_tagged_b *p_own) : m_owner(p_own) {}
71813511Sgabeblack@google.com
71913513Sgabeblack@google.com        sync_enum_type
72013513Sgabeblack@google.com        nb_transport_bw(transaction_type &trans, phase_type &phase,
72113513Sgabeblack@google.com                        sc_core::sc_time &t)
72213513Sgabeblack@google.com        {
72313513Sgabeblack@google.com            typename std::map<transaction_type *,
72413513Sgabeblack@google.com                              sc_core::sc_event *>::iterator it =
72513513Sgabeblack@google.com                                  m_owner->m_pending_trans.find(&trans);
72613513Sgabeblack@google.com
72713513Sgabeblack@google.com            if (it == m_owner->m_pending_trans.end()) {
72813513Sgabeblack@google.com                // Not a blocking call, forward.
72913513Sgabeblack@google.com                return m_owner->bw_nb_transport(trans, phase, t);
73013513Sgabeblack@google.com            }
73113513Sgabeblack@google.com            if (phase == tlm::END_REQ) {
73213513Sgabeblack@google.com                m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME);
73313513Sgabeblack@google.com                return tlm::TLM_ACCEPTED;
73413513Sgabeblack@google.com            }
73513513Sgabeblack@google.com            if (phase == tlm::BEGIN_RESP) {
73613513Sgabeblack@google.com                if (m_owner->m_current_transaction == &trans) {
73713513Sgabeblack@google.com                    m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME);
73813513Sgabeblack@google.com                }
73913513Sgabeblack@google.com                it->second->notify(t);
74013513Sgabeblack@google.com                m_owner->m_pending_trans.erase(it);
74113513Sgabeblack@google.com                return tlm::TLM_COMPLETED;
74213513Sgabeblack@google.com            }
74313513Sgabeblack@google.com            m_owner->display_error("invalid phase received");
74413513Sgabeblack@google.com            return tlm::TLM_COMPLETED;
74513513Sgabeblack@google.com        }
74613513Sgabeblack@google.com
74713513Sgabeblack@google.com        void
74813513Sgabeblack@google.com        invalidate_direct_mem_ptr(sc_dt::uint64 s, sc_dt::uint64 e)
74913513Sgabeblack@google.com        {
75013513Sgabeblack@google.com            return m_owner->bw_invalidate_direct_mem_ptr(s, e);
75113513Sgabeblack@google.com        }
75213513Sgabeblack@google.com
75313513Sgabeblack@google.com      private:
75413513Sgabeblack@google.com        simple_target_socket_tagged_b *m_owner;
75513511Sgabeblack@google.com    };
75613511Sgabeblack@google.com
75713513Sgabeblack@google.com    class fw_process : public tlm::tlm_fw_transport_if<TYPES>,
75813513Sgabeblack@google.com                       public tlm::tlm_mm_interface
75913513Sgabeblack@google.com    {
76013513Sgabeblack@google.com      public:
76113513Sgabeblack@google.com        typedef sync_enum_type (MODULE::*NBTransportPtr)(
76213513Sgabeblack@google.com                int id, transaction_type &, phase_type &,
76313513Sgabeblack@google.com                sc_core::sc_time &);
76413513Sgabeblack@google.com        typedef void (MODULE::*BTransportPtr)(
76513513Sgabeblack@google.com                int id, transaction_type &, sc_core::sc_time &);
76613513Sgabeblack@google.com        typedef unsigned int (MODULE::*TransportDbgPtr)(
76713513Sgabeblack@google.com                int id, transaction_type &);
76813513Sgabeblack@google.com        typedef bool (MODULE::*GetDirectMemPtr)(
76913513Sgabeblack@google.com                int id, transaction_type &, tlm::tlm_dmi &);
77013511Sgabeblack@google.com
77113513Sgabeblack@google.com        fw_process(simple_target_socket_tagged_b *p_own) :
77213513Sgabeblack@google.com            m_owner(p_own), m_mod(0), m_nb_transport_ptr(0),
77313513Sgabeblack@google.com            m_b_transport_ptr(0), m_transport_dbg_ptr(0),
77413513Sgabeblack@google.com            m_get_direct_mem_ptr(0), m_nb_transport_user_id(0),
77513513Sgabeblack@google.com            m_b_transport_user_id(0), m_transport_dbg_user_id(0),
77613513Sgabeblack@google.com            m_get_dmi_user_id(0),
77713513Sgabeblack@google.com            m_peq(sc_core::sc_gen_unique_name("m_peq")),
77813513Sgabeblack@google.com            m_response_in_progress(false)
77913513Sgabeblack@google.com        {}
78013511Sgabeblack@google.com
78113513Sgabeblack@google.com        void
78213513Sgabeblack@google.com        start_of_simulation()
78313513Sgabeblack@google.com        {
78413513Sgabeblack@google.com            if (!m_b_transport_ptr && m_nb_transport_ptr) {
78513513Sgabeblack@google.com                // Only spawn b2nb_thread if needed.
78613513Sgabeblack@google.com                sc_core::sc_spawn_options opts;
78713513Sgabeblack@google.com                opts.set_sensitivity(&m_peq.get_event());
78813513Sgabeblack@google.com                opts.dont_initialize();
78913513Sgabeblack@google.com                sc_core::sc_spawn(sc_bind(&fw_process::b2nb_thread, this),
79013513Sgabeblack@google.com                        sc_core::sc_gen_unique_name("b2nb_thread"), &opts);
79113513Sgabeblack@google.com            }
79213511Sgabeblack@google.com        }
79313511Sgabeblack@google.com
79413513Sgabeblack@google.com        void set_nb_transport_user_id(int id) { m_nb_transport_user_id = id; }
79513513Sgabeblack@google.com        void set_b_transport_user_id(int id) { m_b_transport_user_id = id; }
79613513Sgabeblack@google.com        void
79713513Sgabeblack@google.com        set_transport_dbg_user_id(int id)
79813513Sgabeblack@google.com        {
79913513Sgabeblack@google.com            m_transport_dbg_user_id = id;
80013513Sgabeblack@google.com        }
80113513Sgabeblack@google.com        void set_get_dmi_user_id(int id) { m_get_dmi_user_id = id; }
80213511Sgabeblack@google.com
80313513Sgabeblack@google.com        void
80413513Sgabeblack@google.com        set_nb_transport_ptr(MODULE *mod, NBTransportPtr p)
80513513Sgabeblack@google.com        {
80613513Sgabeblack@google.com            if (m_nb_transport_ptr) {
80713513Sgabeblack@google.com                m_owner->display_warning(
80813513Sgabeblack@google.com                        "non-blocking callback already registered");
80913513Sgabeblack@google.com                return;
81013513Sgabeblack@google.com            }
81113513Sgabeblack@google.com            sc_assert(!m_mod || m_mod == mod);
81213513Sgabeblack@google.com            m_mod = mod;
81313513Sgabeblack@google.com            m_nb_transport_ptr = p;
81413513Sgabeblack@google.com        }
81513511Sgabeblack@google.com
81613513Sgabeblack@google.com        void
81713513Sgabeblack@google.com        set_b_transport_ptr(MODULE* mod, BTransportPtr p)
81813513Sgabeblack@google.com        {
81913513Sgabeblack@google.com            if (m_b_transport_ptr) {
82013513Sgabeblack@google.com                m_owner->display_warning(
82113513Sgabeblack@google.com                        "blocking callback already registered");
82213513Sgabeblack@google.com                return;
82313513Sgabeblack@google.com            }
82413513Sgabeblack@google.com            sc_assert(!m_mod || m_mod == mod);
82513513Sgabeblack@google.com            m_mod = mod;
82613513Sgabeblack@google.com            m_b_transport_ptr = p;
82713513Sgabeblack@google.com        }
82813511Sgabeblack@google.com
82913513Sgabeblack@google.com        void
83013513Sgabeblack@google.com        set_transport_dbg_ptr(MODULE *mod, TransportDbgPtr p)
83113513Sgabeblack@google.com        {
83213513Sgabeblack@google.com            if (m_transport_dbg_ptr) {
83313513Sgabeblack@google.com                m_owner->display_warning(
83413513Sgabeblack@google.com                        "debug callback already registered");
83513513Sgabeblack@google.com                return;
83613513Sgabeblack@google.com            }
83713513Sgabeblack@google.com            sc_assert(!m_mod || m_mod == mod);
83813513Sgabeblack@google.com            m_mod = mod;
83913513Sgabeblack@google.com            m_transport_dbg_ptr = p;
84013513Sgabeblack@google.com        }
84113511Sgabeblack@google.com
84213513Sgabeblack@google.com        void
84313513Sgabeblack@google.com        set_get_direct_mem_ptr(MODULE *mod, GetDirectMemPtr p)
84413513Sgabeblack@google.com        {
84513513Sgabeblack@google.com            if (m_get_direct_mem_ptr) {
84613513Sgabeblack@google.com                m_owner->display_warning(
84713513Sgabeblack@google.com                        "get DMI pointer callback already registered");
84813513Sgabeblack@google.com            }
84913513Sgabeblack@google.com            sc_assert(!m_mod || m_mod == mod);
85013513Sgabeblack@google.com            m_mod = mod;
85113513Sgabeblack@google.com            m_get_direct_mem_ptr = p;
85213513Sgabeblack@google.com        }
85313511Sgabeblack@google.com
85413513Sgabeblack@google.com        // Interface implementation.
85513513Sgabeblack@google.com        sync_enum_type
85613513Sgabeblack@google.com        nb_transport_fw(transaction_type &trans, phase_type &phase,
85713513Sgabeblack@google.com                        sc_core::sc_time &t)
85813513Sgabeblack@google.com        {
85913513Sgabeblack@google.com            if (m_nb_transport_ptr) {
86013513Sgabeblack@google.com                // Forward call.
86113513Sgabeblack@google.com                sc_assert(m_mod);
86213513Sgabeblack@google.com                return (m_mod->*m_nb_transport_ptr)(
86313513Sgabeblack@google.com                        m_nb_transport_user_id, trans, phase, t);
86413511Sgabeblack@google.com            }
86513511Sgabeblack@google.com
86613513Sgabeblack@google.com            // nb->b conversion
86713513Sgabeblack@google.com            if (m_b_transport_ptr) {
86813513Sgabeblack@google.com                if (phase == tlm::BEGIN_REQ) {
86913513Sgabeblack@google.com
87013513Sgabeblack@google.com                    // Prepare thread to do blocking call.
87113513Sgabeblack@google.com                    process_handle_class *ph =
87213513Sgabeblack@google.com                        m_process_handle.get_handle(&trans);
87313513Sgabeblack@google.com
87413513Sgabeblack@google.com                    if (!ph) { // Create new dynamic process.
87513513Sgabeblack@google.com                        ph = new process_handle_class(&trans);
87613513Sgabeblack@google.com                        m_process_handle.put_handle(ph);
87713513Sgabeblack@google.com
87813513Sgabeblack@google.com                        sc_core::sc_spawn_options opts;
87913513Sgabeblack@google.com                        opts.dont_initialize();
88013513Sgabeblack@google.com                        opts.set_sensitivity(&ph->m_e);
88113513Sgabeblack@google.com
88213513Sgabeblack@google.com                        sc_core::sc_spawn(
88313513Sgabeblack@google.com                                sc_bind(&fw_process::nb2b_thread, this, ph),
88413513Sgabeblack@google.com                                sc_core::sc_gen_unique_name("nb2b_thread"),
88513513Sgabeblack@google.com                                &opts);
88613513Sgabeblack@google.com                    }
88713513Sgabeblack@google.com
88813513Sgabeblack@google.com                    ph->m_e.notify(t);
88913513Sgabeblack@google.com                    return tlm::TLM_ACCEPTED;
89013513Sgabeblack@google.com                }
89113513Sgabeblack@google.com                if (phase == tlm::END_RESP) {
89213513Sgabeblack@google.com                    m_response_in_progress = false;
89313513Sgabeblack@google.com                    m_end_response.notify(t);
89413513Sgabeblack@google.com                    return tlm::TLM_COMPLETED;
89513513Sgabeblack@google.com                }
89613513Sgabeblack@google.com                m_owner->display_error("invalid phase");
89713513Sgabeblack@google.com                return tlm::TLM_COMPLETED;
89813511Sgabeblack@google.com            }
89913511Sgabeblack@google.com
90013513Sgabeblack@google.com            m_owner->display_error(
90113513Sgabeblack@google.com                    "no non-blocking transport callback registered");
90213513Sgabeblack@google.com            return tlm::TLM_COMPLETED;
90313511Sgabeblack@google.com        }
90413511Sgabeblack@google.com
90513513Sgabeblack@google.com        void
90613513Sgabeblack@google.com        b_transport(transaction_type &trans, sc_core::sc_time &t)
90713513Sgabeblack@google.com        {
90813513Sgabeblack@google.com            if (m_b_transport_ptr) {
90913513Sgabeblack@google.com                // Forward call.
91013513Sgabeblack@google.com                sc_assert(m_mod);
91113513Sgabeblack@google.com                (m_mod->*m_b_transport_ptr)(m_b_transport_user_id, trans, t);
91213513Sgabeblack@google.com                return;
91313513Sgabeblack@google.com            }
91413511Sgabeblack@google.com
91513513Sgabeblack@google.com            // b->nb conversion
91613513Sgabeblack@google.com            if (m_nb_transport_ptr) {
91713513Sgabeblack@google.com                m_peq.notify(trans, t);
91813513Sgabeblack@google.com                t = sc_core::SC_ZERO_TIME;
91913513Sgabeblack@google.com
92013513Sgabeblack@google.com                mm_end_event_ext mm_ext;
92113513Sgabeblack@google.com                const bool mm_added = !trans.has_mm();
92213513Sgabeblack@google.com
92313513Sgabeblack@google.com                if (mm_added) {
92413513Sgabeblack@google.com                    trans.set_mm(this);
92513513Sgabeblack@google.com                    trans.set_auto_extension(&mm_ext);
92613513Sgabeblack@google.com                    trans.acquire();
92713513Sgabeblack@google.com                }
92813513Sgabeblack@google.com
92913513Sgabeblack@google.com                // Wait until transaction is finished.
93013513Sgabeblack@google.com                sc_core::sc_event end_event;
93113513Sgabeblack@google.com                m_owner->m_pending_trans[&trans] = &end_event;
93213513Sgabeblack@google.com                sc_core::wait(end_event);
93313513Sgabeblack@google.com
93413513Sgabeblack@google.com                if (mm_added) {
93513513Sgabeblack@google.com                    // Release will not delete the transaction, it will
93613513Sgabeblack@google.com                    // notify mm_ext.done.
93713513Sgabeblack@google.com                    trans.release();
93813513Sgabeblack@google.com                    if (trans.get_ref_count()) {
93913513Sgabeblack@google.com                        sc_core::wait(mm_ext.done);
94013513Sgabeblack@google.com                    }
94113513Sgabeblack@google.com                    trans.set_mm(0);
94213513Sgabeblack@google.com                }
94313513Sgabeblack@google.com                return;
94413513Sgabeblack@google.com            }
94513513Sgabeblack@google.com
94613513Sgabeblack@google.com            m_owner->display_error("no transport callback registered");
94713513Sgabeblack@google.com        }
94813513Sgabeblack@google.com
94913513Sgabeblack@google.com        unsigned int
95013513Sgabeblack@google.com        transport_dbg(transaction_type &trans)
95113513Sgabeblack@google.com        {
95213513Sgabeblack@google.com            if (m_transport_dbg_ptr) {
95313513Sgabeblack@google.com                // Forward call.
95413513Sgabeblack@google.com                sc_assert(m_mod);
95513513Sgabeblack@google.com                return (m_mod->*m_transport_dbg_ptr)(
95613513Sgabeblack@google.com                        m_transport_dbg_user_id, trans);
95713513Sgabeblack@google.com            }
95813513Sgabeblack@google.com            // No debug support.
95913513Sgabeblack@google.com            return 0;
96013513Sgabeblack@google.com        }
96113513Sgabeblack@google.com
96213513Sgabeblack@google.com        bool
96313513Sgabeblack@google.com        get_direct_mem_ptr(transaction_type &trans, tlm::tlm_dmi &dmi_data)
96413513Sgabeblack@google.com        {
96513513Sgabeblack@google.com            if (m_get_direct_mem_ptr) {
96613513Sgabeblack@google.com                // Forward call.
96713513Sgabeblack@google.com                sc_assert(m_mod);
96813513Sgabeblack@google.com                return (m_mod->*m_get_direct_mem_ptr)(
96913513Sgabeblack@google.com                        m_get_dmi_user_id, trans, dmi_data);
97013513Sgabeblack@google.com            }
97113513Sgabeblack@google.com            // No DMI support.
97213513Sgabeblack@google.com            dmi_data.allow_read_write();
97313513Sgabeblack@google.com            dmi_data.set_start_address(0x0);
97413513Sgabeblack@google.com            dmi_data.set_end_address((sc_dt::uint64)-1);
97513513Sgabeblack@google.com            return false;
97613513Sgabeblack@google.com        }
97713513Sgabeblack@google.com
97813513Sgabeblack@google.com      private:
97913513Sgabeblack@google.com
98013513Sgabeblack@google.com        // Dynamic process handler for nb2b conversion.
98113513Sgabeblack@google.com        class process_handle_class
98213513Sgabeblack@google.com        {
98313513Sgabeblack@google.com          public:
98413513Sgabeblack@google.com            explicit process_handle_class(transaction_type *trans) :
98513513Sgabeblack@google.com                m_trans(trans), m_suspend(false)
98613513Sgabeblack@google.com            {}
98713513Sgabeblack@google.com
98813513Sgabeblack@google.com            transaction_type *m_trans;
98913513Sgabeblack@google.com            sc_core::sc_event  m_e;
99013513Sgabeblack@google.com            bool m_suspend;
99113513Sgabeblack@google.com        };
99213513Sgabeblack@google.com
99313513Sgabeblack@google.com        class process_handle_list
99413513Sgabeblack@google.com        {
99513513Sgabeblack@google.com          public:
99613513Sgabeblack@google.com            process_handle_list() {}
99713513Sgabeblack@google.com
99813513Sgabeblack@google.com            ~process_handle_list()
99913513Sgabeblack@google.com            {
100013513Sgabeblack@google.com                for (typename std::vector<
100113513Sgabeblack@google.com                        process_handle_class *>::iterator it = v.begin(),
100213513Sgabeblack@google.com                        end = v.end(); it != end; ++it) {
100313513Sgabeblack@google.com                    delete *it;
100413513Sgabeblack@google.com                }
100513513Sgabeblack@google.com            }
100613513Sgabeblack@google.com
100713513Sgabeblack@google.com            process_handle_class *
100813513Sgabeblack@google.com            get_handle(transaction_type *trans)
100913513Sgabeblack@google.com            {
101013513Sgabeblack@google.com                typename std::vector<process_handle_class *>::iterator it;
101113513Sgabeblack@google.com
101213513Sgabeblack@google.com                for (it = v.begin(); it != v.end(); it++) {
101313513Sgabeblack@google.com                    if ((*it)->m_suspend) {
101413513Sgabeblack@google.com                        // Found suspended dynamic process, re-use it.
101513513Sgabeblack@google.com                        (*it)->m_trans = trans; // Replace to new one.
101613513Sgabeblack@google.com                        (*it)->m_suspend = false;
101713513Sgabeblack@google.com                        return *it;
101813513Sgabeblack@google.com                    }
101913513Sgabeblack@google.com                }
102013513Sgabeblack@google.com                return NULL; // No suspended process.
102113513Sgabeblack@google.com            }
102213513Sgabeblack@google.com
102313513Sgabeblack@google.com            void put_handle(process_handle_class *ph) { v.push_back(ph); }
102413513Sgabeblack@google.com
102513513Sgabeblack@google.com          private:
102613513Sgabeblack@google.com            std::vector<process_handle_class *> v;
102713513Sgabeblack@google.com        };
102813513Sgabeblack@google.com
102913513Sgabeblack@google.com        process_handle_list m_process_handle;
103013513Sgabeblack@google.com
103113513Sgabeblack@google.com        void
103213513Sgabeblack@google.com        nb2b_thread(process_handle_class *h)
103313513Sgabeblack@google.com        {
103413513Sgabeblack@google.com
103513513Sgabeblack@google.com            while (1) {
103613513Sgabeblack@google.com                transaction_type *trans = h->m_trans;
103713513Sgabeblack@google.com                sc_core::sc_time t = sc_core::SC_ZERO_TIME;
103813513Sgabeblack@google.com
103913513Sgabeblack@google.com                // Forward call.
104013513Sgabeblack@google.com                sc_assert(m_mod);
104113513Sgabeblack@google.com                (m_mod->*m_b_transport_ptr)(
104213513Sgabeblack@google.com                        m_b_transport_user_id, *trans, t);
104313513Sgabeblack@google.com
104413513Sgabeblack@google.com                sc_core::wait(t);
104513513Sgabeblack@google.com
104613513Sgabeblack@google.com                // Return path.
104713513Sgabeblack@google.com                while (m_response_in_progress) {
104813513Sgabeblack@google.com                    sc_core::wait(m_end_response);
104913513Sgabeblack@google.com                }
105013513Sgabeblack@google.com                t = sc_core::SC_ZERO_TIME;
105113513Sgabeblack@google.com                phase_type phase = tlm::BEGIN_RESP;
105213513Sgabeblack@google.com                sync_enum_type sync =
105313513Sgabeblack@google.com                    m_owner->bw_nb_transport(*trans, phase, t);
105413513Sgabeblack@google.com                if (!(sync == tlm::TLM_COMPLETED ||
105513513Sgabeblack@google.com                            (sync == tlm::TLM_UPDATED &&
105613513Sgabeblack@google.com                             phase == tlm::END_RESP))) {
105713513Sgabeblack@google.com                    m_response_in_progress = true;
105813513Sgabeblack@google.com                }
105913513Sgabeblack@google.com
106013513Sgabeblack@google.com                // Suspend until next transaction.
106113513Sgabeblack@google.com                h->m_suspend = true;
106213513Sgabeblack@google.com                sc_core::wait();
106313513Sgabeblack@google.com            }
106413513Sgabeblack@google.com        }
106513513Sgabeblack@google.com
106613513Sgabeblack@google.com        void
106713513Sgabeblack@google.com        b2nb_thread()
106813513Sgabeblack@google.com        {
106913513Sgabeblack@google.com            while (true) {
107013513Sgabeblack@google.com                transaction_type *trans;
107113513Sgabeblack@google.com                while ((trans = m_peq.get_next_transaction()) != 0) {
107213513Sgabeblack@google.com                    sc_assert(m_mod);
107313513Sgabeblack@google.com                    sc_assert(m_nb_transport_ptr);
107413513Sgabeblack@google.com                    phase_type phase = tlm::BEGIN_REQ;
107513513Sgabeblack@google.com                    sc_core::sc_time t = sc_core::SC_ZERO_TIME;
107613513Sgabeblack@google.com
107713513Sgabeblack@google.com                    switch ((m_mod->*m_nb_transport_ptr)(
107813513Sgabeblack@google.com                                m_nb_transport_user_id, *trans, phase, t)) {
107913513Sgabeblack@google.com                      case tlm::TLM_COMPLETED:
108013513Sgabeblack@google.com                        {
108113513Sgabeblack@google.com                            // Notify transaction is finished.
108213513Sgabeblack@google.com                            typename std::map<transaction_type *,
108313513Sgabeblack@google.com                                     sc_core::sc_event *>::iterator it =
108413513Sgabeblack@google.com                                         m_owner->m_pending_trans.find(trans);
108513513Sgabeblack@google.com                            sc_assert(it != m_owner->m_pending_trans.end());
108613513Sgabeblack@google.com                            it->second->notify(t);
108713513Sgabeblack@google.com                            m_owner->m_pending_trans.erase(it);
108813513Sgabeblack@google.com                            break;
108913513Sgabeblack@google.com                        }
109013513Sgabeblack@google.com
109113513Sgabeblack@google.com                      case tlm::TLM_ACCEPTED:
109213513Sgabeblack@google.com                      case tlm::TLM_UPDATED:
109313513Sgabeblack@google.com                        switch (phase) {
109413513Sgabeblack@google.com                          case tlm::BEGIN_REQ:
109513513Sgabeblack@google.com                            m_owner->m_current_transaction = trans;
109613513Sgabeblack@google.com                            sc_core::wait(m_owner->m_end_request);
109713513Sgabeblack@google.com                            m_owner->m_current_transaction = 0;
109813513Sgabeblack@google.com                            break;
109913513Sgabeblack@google.com
110013513Sgabeblack@google.com                          case tlm::END_REQ:
110113513Sgabeblack@google.com                            sc_core::wait(t);
110213513Sgabeblack@google.com                            break;
110313513Sgabeblack@google.com
110413513Sgabeblack@google.com                          case tlm::BEGIN_RESP:
110513513Sgabeblack@google.com                            {
110613513Sgabeblack@google.com                                phase = tlm::END_RESP;
110713513Sgabeblack@google.com                                // This line is a bug fix added in TLM-2.0.2.
110813513Sgabeblack@google.com                                sc_core::wait(t);
110913513Sgabeblack@google.com                                t = sc_core::SC_ZERO_TIME;
111013513Sgabeblack@google.com                                (m_mod->*m_nb_transport_ptr)(
111113513Sgabeblack@google.com                                        m_nb_transport_user_id,
111213513Sgabeblack@google.com                                        *trans, phase, t);
111313513Sgabeblack@google.com
111413513Sgabeblack@google.com                                // Notify transaction is finished.
111513513Sgabeblack@google.com                                typename std::map<transaction_type *,
111613513Sgabeblack@google.com                                         sc_core::sc_event *>::iterator it =
111713513Sgabeblack@google.com                                             m_owner->m_pending_trans.find(
111813513Sgabeblack@google.com                                                     trans);
111913513Sgabeblack@google.com                                sc_assert(it !=
112013513Sgabeblack@google.com                                        m_owner->m_pending_trans.end());
112113513Sgabeblack@google.com                                it->second->notify(t);
112213513Sgabeblack@google.com                                m_owner->m_pending_trans.erase(it);
112313513Sgabeblack@google.com                                break;
112413513Sgabeblack@google.com                            }
112513513Sgabeblack@google.com
112613513Sgabeblack@google.com                          default:
112713513Sgabeblack@google.com                            m_owner->display_error("invalid phase received");
112813513Sgabeblack@google.com                        };
112913513Sgabeblack@google.com                        break;
113013513Sgabeblack@google.com
113113513Sgabeblack@google.com                      default:
113213513Sgabeblack@google.com                        m_owner->display_error("invalid sync value received");
113313513Sgabeblack@google.com                    }
113413513Sgabeblack@google.com                }
113513513Sgabeblack@google.com                sc_core::wait();
113613513Sgabeblack@google.com            }
113713513Sgabeblack@google.com        }
113813513Sgabeblack@google.com
113913513Sgabeblack@google.com        void
114013513Sgabeblack@google.com        free(tlm::tlm_generic_payload *trans)
114113513Sgabeblack@google.com        {
114213513Sgabeblack@google.com            mm_end_event_ext *ext =
114313513Sgabeblack@google.com                trans->template get_extension<mm_end_event_ext>();
114413513Sgabeblack@google.com            sc_assert(ext);
114513513Sgabeblack@google.com            // Notify event first before freeing extensions (reset).
114613513Sgabeblack@google.com            ext->done.notify();
114713513Sgabeblack@google.com            trans->reset();
114813513Sgabeblack@google.com        }
114913513Sgabeblack@google.com
115013513Sgabeblack@google.com      private:
115113513Sgabeblack@google.com        struct mm_end_event_ext : public tlm::tlm_extension<mm_end_event_ext>
115213513Sgabeblack@google.com        {
115313513Sgabeblack@google.com            tlm::tlm_extension_base *clone() const { return NULL; }
115413513Sgabeblack@google.com            void free() {}
115513513Sgabeblack@google.com            void copy_from(tlm::tlm_extension_base const &) {}
115613513Sgabeblack@google.com            sc_core::sc_event done;
115713513Sgabeblack@google.com        };
115813513Sgabeblack@google.com
115913513Sgabeblack@google.com      private:
116013513Sgabeblack@google.com        simple_target_socket_tagged_b *m_owner;
116113513Sgabeblack@google.com        MODULE *m_mod;
116213513Sgabeblack@google.com        NBTransportPtr m_nb_transport_ptr;
116313513Sgabeblack@google.com        BTransportPtr m_b_transport_ptr;
116413513Sgabeblack@google.com        TransportDbgPtr m_transport_dbg_ptr;
116513513Sgabeblack@google.com        GetDirectMemPtr m_get_direct_mem_ptr;
116613513Sgabeblack@google.com        int m_nb_transport_user_id;
116713513Sgabeblack@google.com        int m_b_transport_user_id;
116813513Sgabeblack@google.com        int m_transport_dbg_user_id;
116913513Sgabeblack@google.com        int m_get_dmi_user_id;
117013513Sgabeblack@google.com        peq_with_get<transaction_type> m_peq;
117113513Sgabeblack@google.com        bool m_response_in_progress;
117213513Sgabeblack@google.com        sc_core::sc_event m_end_response;
117313511Sgabeblack@google.com    };
117413511Sgabeblack@google.com
117513511Sgabeblack@google.com  private:
117613513Sgabeblack@google.com    const sc_core::sc_object *get_socket() const { return this; }
117713511Sgabeblack@google.com
117813513Sgabeblack@google.com  private:
117913513Sgabeblack@google.com    fw_process m_fw_process;
118013513Sgabeblack@google.com    bw_process m_bw_process;
118113513Sgabeblack@google.com    std::map<transaction_type *, sc_core::sc_event *> m_pending_trans;
118213513Sgabeblack@google.com    sc_core::sc_event m_end_request;
118313513Sgabeblack@google.com    transaction_type* m_current_transaction;
118413511Sgabeblack@google.com};
118513511Sgabeblack@google.com
118613513Sgabeblack@google.comtemplate <typename MODULE, unsigned int BUSWIDTH=32,
118713513Sgabeblack@google.com          typename TYPES=tlm::tlm_base_protocol_types>
118813513Sgabeblack@google.comclass simple_target_socket_tagged :
118913513Sgabeblack@google.com    public simple_target_socket_tagged_b<MODULE, BUSWIDTH, TYPES>
119013511Sgabeblack@google.com{
119113513Sgabeblack@google.com    typedef simple_target_socket_tagged_b<MODULE, BUSWIDTH, TYPES> socket_b;
119213513Sgabeblack@google.com  public:
119313513Sgabeblack@google.com    simple_target_socket_tagged() : socket_b() {}
119413513Sgabeblack@google.com    explicit simple_target_socket_tagged(const char *name) : socket_b(name) {}
119513511Sgabeblack@google.com};
119613511Sgabeblack@google.com
119713513Sgabeblack@google.comtemplate <typename MODULE, unsigned int BUSWIDTH=32,
119813513Sgabeblack@google.com          typename TYPES=tlm::tlm_base_protocol_types>
119913513Sgabeblack@google.comclass simple_target_socket_tagged_optional :
120013513Sgabeblack@google.com    public simple_target_socket_tagged_b<MODULE, BUSWIDTH, TYPES,
120113513Sgabeblack@google.com                                         sc_core::SC_ZERO_OR_MORE_BOUND>
120213511Sgabeblack@google.com{
120313513Sgabeblack@google.com    typedef simple_target_socket_tagged_b<
120413513Sgabeblack@google.com        MODULE, BUSWIDTH, TYPES, sc_core::SC_ZERO_OR_MORE_BOUND> socket_b;
120513511Sgabeblack@google.com  public:
120613513Sgabeblack@google.com    simple_target_socket_tagged_optional() : socket_b() {}
120713513Sgabeblack@google.com    explicit simple_target_socket_tagged_optional(const char *name) :
120813513Sgabeblack@google.com        socket_b(name)
120913511Sgabeblack@google.com    {}
121013511Sgabeblack@google.com};
121113511Sgabeblack@google.com
121213511Sgabeblack@google.com} // namespace tlm_utils
121313513Sgabeblack@google.com
121413513Sgabeblack@google.com#endif /* __SYSTEMC_EXT_TLM_UTILS_SIMPLE_TARGET_SOCKET_H__ */
1215