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