simple_target_socket.h revision 13511
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
2013511Sgabeblack@google.com// *****************************************************************************
2113511Sgabeblack@google.com// Modified by John Aynsley, Doulos, Feb 2009,
2213511Sgabeblack@google.com// Fix a bug in simple_target_socket and simple_target_socket_tagged
2313511Sgabeblack@google.com// with the addition of one new line of code in each:  wait(*e);
2413511Sgabeblack@google.com// *****************************************************************************
2513511Sgabeblack@google.com
2613511Sgabeblack@google.com// *****************************************************************************
2713511Sgabeblack@google.com// Modified by John Aynsley on behalf of Robert Guenzel, May 2011,
2813511Sgabeblack@google.com// Fix a bug in simple_target_socket and simple_target_socket_tagged
2913511Sgabeblack@google.com// with the addition of one new line of code in each:  wait(t);
3013511Sgabeblack@google.com// *****************************************************************************
3113511Sgabeblack@google.com
3213511Sgabeblack@google.com
3313511Sgabeblack@google.com#ifndef TLM_UTILS_SIMPLE_TARGET_SOCKET_H_INCLUDED_
3413511Sgabeblack@google.com#define TLM_UTILS_SIMPLE_TARGET_SOCKET_H_INCLUDED_
3513511Sgabeblack@google.com
3613511Sgabeblack@google.com#ifndef SC_INCLUDE_DYNAMIC_PROCESSES // needed for sc_spawn
3713511Sgabeblack@google.com#  define SC_INCLUDE_DYNAMIC_PROCESSES
3813511Sgabeblack@google.com#endif
3913511Sgabeblack@google.com
4013511Sgabeblack@google.com#include <systemc>
4113511Sgabeblack@google.com#include <tlm>
4213511Sgabeblack@google.com#include "tlm_utils/convenience_socket_bases.h"
4313511Sgabeblack@google.com#include "tlm_utils/peq_with_get.h"
4413511Sgabeblack@google.com
4513511Sgabeblack@google.comnamespace tlm_utils {
4613511Sgabeblack@google.com
4713511Sgabeblack@google.comtemplate< typename MODULE, unsigned int BUSWIDTH, typename TYPES
4813511Sgabeblack@google.com        , sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND >
4913511Sgabeblack@google.comclass simple_target_socket_b
5013511Sgabeblack@google.com  : public tlm::tlm_target_socket<BUSWIDTH, TYPES, 1, POL>
5113511Sgabeblack@google.com  , protected simple_socket_base
5213511Sgabeblack@google.com{
5313511Sgabeblack@google.com  friend class fw_process;
5413511Sgabeblack@google.com  friend class bw_process;
5513511Sgabeblack@google.compublic:
5613511Sgabeblack@google.com  typedef typename TYPES::tlm_payload_type              transaction_type;
5713511Sgabeblack@google.com  typedef typename TYPES::tlm_phase_type                phase_type;
5813511Sgabeblack@google.com  typedef tlm::tlm_sync_enum                            sync_enum_type;
5913511Sgabeblack@google.com  typedef tlm::tlm_fw_transport_if<TYPES>               fw_interface_type;
6013511Sgabeblack@google.com  typedef tlm::tlm_bw_transport_if<TYPES>               bw_interface_type;
6113511Sgabeblack@google.com  typedef tlm::tlm_target_socket<BUSWIDTH,TYPES,1,POL>  base_type;
6213511Sgabeblack@google.com
6313511Sgabeblack@google.compublic:
6413511Sgabeblack@google.com  static const char* default_name()
6513511Sgabeblack@google.com    { return sc_core::sc_gen_unique_name("simple_target_socket"); }
6613511Sgabeblack@google.com
6713511Sgabeblack@google.com  explicit simple_target_socket_b(const char* n = default_name())
6813511Sgabeblack@google.com    : base_type(n)
6913511Sgabeblack@google.com    , m_fw_process(this)
7013511Sgabeblack@google.com    , m_bw_process(this)
7113511Sgabeblack@google.com  {
7213511Sgabeblack@google.com    bind(m_fw_process);
7313511Sgabeblack@google.com  }
7413511Sgabeblack@google.com
7513511Sgabeblack@google.com  using base_type::bind;
7613511Sgabeblack@google.com
7713511Sgabeblack@google.com  // bw transport must come thru us.
7813511Sgabeblack@google.com  tlm::tlm_bw_transport_if<TYPES> * operator ->() {return &m_bw_process;}
7913511Sgabeblack@google.com
8013511Sgabeblack@google.com  // REGISTER_XXX
8113511Sgabeblack@google.com  void register_nb_transport_fw(MODULE* mod,
8213511Sgabeblack@google.com                                sync_enum_type (MODULE::*cb)(transaction_type&,
8313511Sgabeblack@google.com                                                             phase_type&,
8413511Sgabeblack@google.com                                                             sc_core::sc_time&))
8513511Sgabeblack@google.com  {
8613511Sgabeblack@google.com    elaboration_check("register_nb_transport_fw");
8713511Sgabeblack@google.com    m_fw_process.set_nb_transport_ptr(mod, cb);
8813511Sgabeblack@google.com  }
8913511Sgabeblack@google.com
9013511Sgabeblack@google.com  void register_b_transport(MODULE* mod,
9113511Sgabeblack@google.com                            void (MODULE::*cb)(transaction_type&,
9213511Sgabeblack@google.com                                               sc_core::sc_time&))
9313511Sgabeblack@google.com  {
9413511Sgabeblack@google.com    elaboration_check("register_b_transport");
9513511Sgabeblack@google.com    m_fw_process.set_b_transport_ptr(mod, cb);
9613511Sgabeblack@google.com  }
9713511Sgabeblack@google.com
9813511Sgabeblack@google.com  void register_transport_dbg(MODULE* mod,
9913511Sgabeblack@google.com                              unsigned int (MODULE::*cb)(transaction_type&))
10013511Sgabeblack@google.com  {
10113511Sgabeblack@google.com    elaboration_check("register_transport_dbg");
10213511Sgabeblack@google.com    m_fw_process.set_transport_dbg_ptr(mod, cb);
10313511Sgabeblack@google.com  }
10413511Sgabeblack@google.com
10513511Sgabeblack@google.com  void register_get_direct_mem_ptr(MODULE* mod,
10613511Sgabeblack@google.com                                   bool (MODULE::*cb)(transaction_type&,
10713511Sgabeblack@google.com                                                      tlm::tlm_dmi&))
10813511Sgabeblack@google.com  {
10913511Sgabeblack@google.com    elaboration_check("register_get_direct_mem_ptr");
11013511Sgabeblack@google.com    m_fw_process.set_get_direct_mem_ptr(mod, cb);
11113511Sgabeblack@google.com  }
11213511Sgabeblack@google.com
11313511Sgabeblack@google.comprotected:
11413511Sgabeblack@google.com  void start_of_simulation()
11513511Sgabeblack@google.com  {
11613511Sgabeblack@google.com    base_type::start_of_simulation();
11713511Sgabeblack@google.com    m_fw_process.start_of_simulation();
11813511Sgabeblack@google.com  }
11913511Sgabeblack@google.com
12013511Sgabeblack@google.comprivate:
12113511Sgabeblack@google.com  //make call on bw path.
12213511Sgabeblack@google.com  sync_enum_type bw_nb_transport(transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
12313511Sgabeblack@google.com  {
12413511Sgabeblack@google.com    return base_type::operator ->()->nb_transport_bw(trans, phase, t);
12513511Sgabeblack@google.com  }
12613511Sgabeblack@google.com
12713511Sgabeblack@google.com  void bw_invalidate_direct_mem_ptr(sc_dt::uint64 s,sc_dt::uint64 e)
12813511Sgabeblack@google.com  {
12913511Sgabeblack@google.com    base_type::operator ->()->invalidate_direct_mem_ptr(s, e);
13013511Sgabeblack@google.com  }
13113511Sgabeblack@google.com
13213511Sgabeblack@google.com  //Helper class to handle bw path calls
13313511Sgabeblack@google.com  // Needed to detect transaction end when called from b_transport.
13413511Sgabeblack@google.com  class bw_process : public tlm::tlm_bw_transport_if<TYPES>
13513511Sgabeblack@google.com  {
13613511Sgabeblack@google.com  public:
13713511Sgabeblack@google.com    bw_process(simple_target_socket_b *p_own) : m_owner(p_own)
13813511Sgabeblack@google.com    {
13913511Sgabeblack@google.com    }
14013511Sgabeblack@google.com
14113511Sgabeblack@google.com    sync_enum_type nb_transport_bw(transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
14213511Sgabeblack@google.com    {
14313511Sgabeblack@google.com      typename std::map<transaction_type*, sc_core::sc_event *>::iterator it =
14413511Sgabeblack@google.com        m_owner->m_pending_trans.find(&trans);
14513511Sgabeblack@google.com
14613511Sgabeblack@google.com      if(it == m_owner->m_pending_trans.end()) {
14713511Sgabeblack@google.com        // Not a blocking call, forward.
14813511Sgabeblack@google.com        return m_owner->bw_nb_transport(trans, phase, t);
14913511Sgabeblack@google.com
15013511Sgabeblack@google.com      }
15113511Sgabeblack@google.com
15213511Sgabeblack@google.com      if (phase == tlm::END_REQ) {
15313511Sgabeblack@google.com        m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME);
15413511Sgabeblack@google.com        return tlm::TLM_ACCEPTED;
15513511Sgabeblack@google.com      }
15613511Sgabeblack@google.com      if (phase == tlm::BEGIN_RESP) {
15713511Sgabeblack@google.com        if (m_owner->m_current_transaction == &trans) {
15813511Sgabeblack@google.com          m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME);
15913511Sgabeblack@google.com        }
16013511Sgabeblack@google.com        //TODO: add response-accept delay?
16113511Sgabeblack@google.com        it->second->notify(t);
16213511Sgabeblack@google.com        m_owner->m_pending_trans.erase(it);
16313511Sgabeblack@google.com        return tlm::TLM_COMPLETED;
16413511Sgabeblack@google.com      }
16513511Sgabeblack@google.com      m_owner->display_error("invalid phase received");
16613511Sgabeblack@google.com      return tlm::TLM_COMPLETED;
16713511Sgabeblack@google.com    }
16813511Sgabeblack@google.com
16913511Sgabeblack@google.com    void invalidate_direct_mem_ptr(sc_dt::uint64 s,sc_dt::uint64 e)
17013511Sgabeblack@google.com    {
17113511Sgabeblack@google.com      return m_owner->bw_invalidate_direct_mem_ptr(s, e);
17213511Sgabeblack@google.com    }
17313511Sgabeblack@google.com
17413511Sgabeblack@google.com  private:
17513511Sgabeblack@google.com    simple_target_socket_b *m_owner;
17613511Sgabeblack@google.com  };
17713511Sgabeblack@google.com
17813511Sgabeblack@google.com  class fw_process : public tlm::tlm_fw_transport_if<TYPES>,
17913511Sgabeblack@google.com                    public tlm::tlm_mm_interface
18013511Sgabeblack@google.com  {
18113511Sgabeblack@google.com  public:
18213511Sgabeblack@google.com    typedef sync_enum_type (MODULE::*NBTransportPtr)(transaction_type&,
18313511Sgabeblack@google.com                                                     phase_type&,
18413511Sgabeblack@google.com                                                     sc_core::sc_time&);
18513511Sgabeblack@google.com    typedef void (MODULE::*BTransportPtr)(transaction_type&,
18613511Sgabeblack@google.com                                          sc_core::sc_time&);
18713511Sgabeblack@google.com    typedef unsigned int (MODULE::*TransportDbgPtr)(transaction_type&);
18813511Sgabeblack@google.com    typedef bool (MODULE::*GetDirectMemPtr)(transaction_type&,
18913511Sgabeblack@google.com                                            tlm::tlm_dmi&);
19013511Sgabeblack@google.com
19113511Sgabeblack@google.com    fw_process(simple_target_socket_b *p_own) :
19213511Sgabeblack@google.com      m_owner(p_own),
19313511Sgabeblack@google.com      m_mod(0),
19413511Sgabeblack@google.com      m_nb_transport_ptr(0),
19513511Sgabeblack@google.com      m_b_transport_ptr(0),
19613511Sgabeblack@google.com      m_transport_dbg_ptr(0),
19713511Sgabeblack@google.com      m_get_direct_mem_ptr(0),
19813511Sgabeblack@google.com      m_peq(sc_core::sc_gen_unique_name("m_peq")),
19913511Sgabeblack@google.com      m_response_in_progress(false)
20013511Sgabeblack@google.com    {}
20113511Sgabeblack@google.com
20213511Sgabeblack@google.com    void start_of_simulation()
20313511Sgabeblack@google.com    {
20413511Sgabeblack@google.com      if (!m_b_transport_ptr && m_nb_transport_ptr) { // only spawn b2nb_thread, if needed
20513511Sgabeblack@google.com        sc_core::sc_spawn_options opts;
20613511Sgabeblack@google.com        opts.set_sensitivity(&m_peq.get_event());
20713511Sgabeblack@google.com        opts.dont_initialize();
20813511Sgabeblack@google.com        sc_core::sc_spawn(sc_bind(&fw_process::b2nb_thread, this),
20913511Sgabeblack@google.com                          sc_core::sc_gen_unique_name("b2nb_thread"), &opts);
21013511Sgabeblack@google.com      }
21113511Sgabeblack@google.com    }
21213511Sgabeblack@google.com
21313511Sgabeblack@google.com    void set_nb_transport_ptr(MODULE* mod, NBTransportPtr p)
21413511Sgabeblack@google.com    {
21513511Sgabeblack@google.com      if (m_nb_transport_ptr) {
21613511Sgabeblack@google.com        m_owner->display_warning("non-blocking callback already registered");
21713511Sgabeblack@google.com        return;
21813511Sgabeblack@google.com      }
21913511Sgabeblack@google.com      sc_assert(!m_mod || m_mod == mod);
22013511Sgabeblack@google.com      m_mod = mod;
22113511Sgabeblack@google.com      m_nb_transport_ptr = p;
22213511Sgabeblack@google.com    }
22313511Sgabeblack@google.com
22413511Sgabeblack@google.com    void set_b_transport_ptr(MODULE* mod, BTransportPtr p)
22513511Sgabeblack@google.com    {
22613511Sgabeblack@google.com      if (m_b_transport_ptr) {
22713511Sgabeblack@google.com        m_owner->display_warning("blocking callback already registered");
22813511Sgabeblack@google.com        return;
22913511Sgabeblack@google.com      }
23013511Sgabeblack@google.com      sc_assert(!m_mod || m_mod == mod);
23113511Sgabeblack@google.com      m_mod = mod;
23213511Sgabeblack@google.com      m_b_transport_ptr = p;
23313511Sgabeblack@google.com    }
23413511Sgabeblack@google.com
23513511Sgabeblack@google.com    void set_transport_dbg_ptr(MODULE* mod, TransportDbgPtr p)
23613511Sgabeblack@google.com    {
23713511Sgabeblack@google.com      if (m_transport_dbg_ptr) {
23813511Sgabeblack@google.com        m_owner->display_warning("debug callback already registered");
23913511Sgabeblack@google.com        return;
24013511Sgabeblack@google.com      }
24113511Sgabeblack@google.com      sc_assert(!m_mod || m_mod == mod);
24213511Sgabeblack@google.com      m_mod = mod;
24313511Sgabeblack@google.com      m_transport_dbg_ptr = p;
24413511Sgabeblack@google.com    }
24513511Sgabeblack@google.com
24613511Sgabeblack@google.com    void set_get_direct_mem_ptr(MODULE* mod, GetDirectMemPtr p)
24713511Sgabeblack@google.com    {
24813511Sgabeblack@google.com      if (m_get_direct_mem_ptr) {
24913511Sgabeblack@google.com        m_owner->display_warning("get DMI pointer callback already registered");
25013511Sgabeblack@google.com        return;
25113511Sgabeblack@google.com      }
25213511Sgabeblack@google.com      sc_assert(!m_mod || m_mod == mod);
25313511Sgabeblack@google.com      m_mod = mod;
25413511Sgabeblack@google.com      m_get_direct_mem_ptr = p;
25513511Sgabeblack@google.com    }
25613511Sgabeblack@google.com// Interface implementation
25713511Sgabeblack@google.com    sync_enum_type nb_transport_fw(transaction_type& trans,
25813511Sgabeblack@google.com                                   phase_type& phase,
25913511Sgabeblack@google.com                                   sc_core::sc_time& t)
26013511Sgabeblack@google.com    {
26113511Sgabeblack@google.com      if (m_nb_transport_ptr) {
26213511Sgabeblack@google.com        // forward call
26313511Sgabeblack@google.com        sc_assert(m_mod);
26413511Sgabeblack@google.com        return (m_mod->*m_nb_transport_ptr)(trans, phase, t);
26513511Sgabeblack@google.com      }
26613511Sgabeblack@google.com
26713511Sgabeblack@google.com      // nb->b conversion
26813511Sgabeblack@google.com      if (m_b_transport_ptr) {
26913511Sgabeblack@google.com        if (phase == tlm::BEGIN_REQ) {
27013511Sgabeblack@google.com          // prepare thread to do blocking call
27113511Sgabeblack@google.com          process_handle_class * ph = m_process_handle.get_handle(&trans);
27213511Sgabeblack@google.com
27313511Sgabeblack@google.com          if (!ph) { // create new dynamic process
27413511Sgabeblack@google.com            ph = new process_handle_class(&trans);
27513511Sgabeblack@google.com            m_process_handle.put_handle(ph);
27613511Sgabeblack@google.com
27713511Sgabeblack@google.com            sc_core::sc_spawn_options opts;
27813511Sgabeblack@google.com            opts.dont_initialize();
27913511Sgabeblack@google.com            opts.set_sensitivity(&ph->m_e);
28013511Sgabeblack@google.com
28113511Sgabeblack@google.com            sc_core::sc_spawn(sc_bind(&fw_process::nb2b_thread,this, ph),
28213511Sgabeblack@google.com                            sc_core::sc_gen_unique_name("nb2b_thread"), &opts);
28313511Sgabeblack@google.com          }
28413511Sgabeblack@google.com
28513511Sgabeblack@google.com          ph->m_e.notify(t);
28613511Sgabeblack@google.com          return tlm::TLM_ACCEPTED;
28713511Sgabeblack@google.com        }
28813511Sgabeblack@google.com        if (phase == tlm::END_RESP) {
28913511Sgabeblack@google.com          m_response_in_progress = false;
29013511Sgabeblack@google.com          m_end_response.notify(t);
29113511Sgabeblack@google.com          return tlm::TLM_COMPLETED;
29213511Sgabeblack@google.com        }
29313511Sgabeblack@google.com        m_owner->display_error("invalid phase received");
29413511Sgabeblack@google.com        return tlm::TLM_COMPLETED;
29513511Sgabeblack@google.com      }
29613511Sgabeblack@google.com      m_owner->display_error("no non-blocking transport callback registered");
29713511Sgabeblack@google.com      return tlm::TLM_COMPLETED;
29813511Sgabeblack@google.com    }
29913511Sgabeblack@google.com
30013511Sgabeblack@google.com    void b_transport(transaction_type& trans, sc_core::sc_time& t)
30113511Sgabeblack@google.com    {
30213511Sgabeblack@google.com      if (m_b_transport_ptr) {
30313511Sgabeblack@google.com        // forward call
30413511Sgabeblack@google.com        sc_assert(m_mod);
30513511Sgabeblack@google.com        (m_mod->*m_b_transport_ptr)(trans, t);
30613511Sgabeblack@google.com        return;
30713511Sgabeblack@google.com      }
30813511Sgabeblack@google.com
30913511Sgabeblack@google.com      // b->nb conversion
31013511Sgabeblack@google.com      if (m_nb_transport_ptr) {
31113511Sgabeblack@google.com        m_peq.notify(trans, t);
31213511Sgabeblack@google.com        t = sc_core::SC_ZERO_TIME;
31313511Sgabeblack@google.com
31413511Sgabeblack@google.com        mm_end_event_ext mm_ext;
31513511Sgabeblack@google.com        const bool mm_added = !trans.has_mm();
31613511Sgabeblack@google.com
31713511Sgabeblack@google.com        if (mm_added) {
31813511Sgabeblack@google.com          trans.set_mm(this);
31913511Sgabeblack@google.com          trans.set_auto_extension(&mm_ext);
32013511Sgabeblack@google.com          trans.acquire();
32113511Sgabeblack@google.com        }
32213511Sgabeblack@google.com
32313511Sgabeblack@google.com        // wait until transaction is finished
32413511Sgabeblack@google.com        sc_core::sc_event end_event;
32513511Sgabeblack@google.com        m_owner->m_pending_trans[&trans] = &end_event;
32613511Sgabeblack@google.com        sc_core::wait(end_event);
32713511Sgabeblack@google.com
32813511Sgabeblack@google.com        if (mm_added) {
32913511Sgabeblack@google.com          // release will not delete the transaction, it will notify mm_ext.done
33013511Sgabeblack@google.com          trans.release();
33113511Sgabeblack@google.com          if (trans.get_ref_count()) {
33213511Sgabeblack@google.com            sc_core::wait(mm_ext.done);
33313511Sgabeblack@google.com          }
33413511Sgabeblack@google.com          trans.set_mm(0);
33513511Sgabeblack@google.com        }
33613511Sgabeblack@google.com        return;
33713511Sgabeblack@google.com      }
33813511Sgabeblack@google.com
33913511Sgabeblack@google.com      // should not be reached
34013511Sgabeblack@google.com      m_owner->display_error("no blocking transport callback registered");
34113511Sgabeblack@google.com    }
34213511Sgabeblack@google.com
34313511Sgabeblack@google.com    unsigned int transport_dbg(transaction_type& trans)
34413511Sgabeblack@google.com    {
34513511Sgabeblack@google.com      if (m_transport_dbg_ptr) {
34613511Sgabeblack@google.com        // forward call
34713511Sgabeblack@google.com        sc_assert(m_mod);
34813511Sgabeblack@google.com        return (m_mod->*m_transport_dbg_ptr)(trans);
34913511Sgabeblack@google.com      }
35013511Sgabeblack@google.com      // No debug support
35113511Sgabeblack@google.com      return 0;
35213511Sgabeblack@google.com    }
35313511Sgabeblack@google.com
35413511Sgabeblack@google.com    bool get_direct_mem_ptr(transaction_type& trans,
35513511Sgabeblack@google.com                            tlm::tlm_dmi&  dmi_data)
35613511Sgabeblack@google.com    {
35713511Sgabeblack@google.com      if (m_get_direct_mem_ptr) {
35813511Sgabeblack@google.com        // forward call
35913511Sgabeblack@google.com        sc_assert(m_mod);
36013511Sgabeblack@google.com        return (m_mod->*m_get_direct_mem_ptr)(trans, dmi_data);
36113511Sgabeblack@google.com      }
36213511Sgabeblack@google.com      // No DMI support
36313511Sgabeblack@google.com      dmi_data.allow_read_write();
36413511Sgabeblack@google.com      dmi_data.set_start_address(0x0);
36513511Sgabeblack@google.com      dmi_data.set_end_address((sc_dt::uint64)-1);
36613511Sgabeblack@google.com      return false;
36713511Sgabeblack@google.com    }
36813511Sgabeblack@google.com
36913511Sgabeblack@google.com  private:
37013511Sgabeblack@google.com
37113511Sgabeblack@google.com// dynamic process handler for nb2b conversion
37213511Sgabeblack@google.com
37313511Sgabeblack@google.com    class process_handle_class {
37413511Sgabeblack@google.com    public:
37513511Sgabeblack@google.com      explicit process_handle_class(transaction_type * trans)
37613511Sgabeblack@google.com        : m_trans(trans),m_suspend(false) {}
37713511Sgabeblack@google.com
37813511Sgabeblack@google.com      transaction_type*  m_trans;
37913511Sgabeblack@google.com      sc_core::sc_event  m_e;
38013511Sgabeblack@google.com      bool m_suspend;
38113511Sgabeblack@google.com    };
38213511Sgabeblack@google.com
38313511Sgabeblack@google.com    class process_handle_list {
38413511Sgabeblack@google.com    public:
38513511Sgabeblack@google.com      process_handle_list() {}
38613511Sgabeblack@google.com
38713511Sgabeblack@google.com      ~process_handle_list() {
38813511Sgabeblack@google.com        for( typename std::vector<process_handle_class*>::iterator
38913511Sgabeblack@google.com               it=v.begin(), end = v.end(); it != end; ++it )
39013511Sgabeblack@google.com          delete *it;
39113511Sgabeblack@google.com      }
39213511Sgabeblack@google.com
39313511Sgabeblack@google.com      process_handle_class* get_handle(transaction_type *trans)
39413511Sgabeblack@google.com      {
39513511Sgabeblack@google.com        typename std::vector<process_handle_class*>::iterator it;
39613511Sgabeblack@google.com
39713511Sgabeblack@google.com        for(it = v.begin(); it != v.end(); it++) {
39813511Sgabeblack@google.com          if ((*it)->m_suspend) {  // found suspended dynamic process, re-use it
39913511Sgabeblack@google.com            (*it)->m_trans   = trans; // replace to new one
40013511Sgabeblack@google.com            (*it)->m_suspend = false;
40113511Sgabeblack@google.com            return *it;
40213511Sgabeblack@google.com          }
40313511Sgabeblack@google.com        }
40413511Sgabeblack@google.com        return NULL; // no suspended process
40513511Sgabeblack@google.com      }
40613511Sgabeblack@google.com
40713511Sgabeblack@google.com      void put_handle(process_handle_class* ph)
40813511Sgabeblack@google.com      {
40913511Sgabeblack@google.com        v.push_back(ph);
41013511Sgabeblack@google.com      }
41113511Sgabeblack@google.com
41213511Sgabeblack@google.com    private:
41313511Sgabeblack@google.com      std::vector<process_handle_class*> v;
41413511Sgabeblack@google.com    };
41513511Sgabeblack@google.com
41613511Sgabeblack@google.com    process_handle_list m_process_handle;
41713511Sgabeblack@google.com
41813511Sgabeblack@google.com
41913511Sgabeblack@google.com    void nb2b_thread(process_handle_class* h)
42013511Sgabeblack@google.com    {
42113511Sgabeblack@google.com
42213511Sgabeblack@google.com      while(1) {
42313511Sgabeblack@google.com        transaction_type *trans = h->m_trans;
42413511Sgabeblack@google.com        sc_core::sc_time t = sc_core::SC_ZERO_TIME;
42513511Sgabeblack@google.com
42613511Sgabeblack@google.com        // forward call
42713511Sgabeblack@google.com        sc_assert(m_mod);
42813511Sgabeblack@google.com        (m_mod->*m_b_transport_ptr)(*trans, t);
42913511Sgabeblack@google.com
43013511Sgabeblack@google.com        sc_core::wait(t);
43113511Sgabeblack@google.com
43213511Sgabeblack@google.com        // return path
43313511Sgabeblack@google.com        while (m_response_in_progress) {
43413511Sgabeblack@google.com          sc_core::wait(m_end_response);
43513511Sgabeblack@google.com        }
43613511Sgabeblack@google.com        t = sc_core::SC_ZERO_TIME;
43713511Sgabeblack@google.com        phase_type phase    = tlm::BEGIN_RESP;
43813511Sgabeblack@google.com        sync_enum_type sync = m_owner->bw_nb_transport(*trans, phase, t);
43913511Sgabeblack@google.com        if ( !(sync == tlm::TLM_COMPLETED ||
44013511Sgabeblack@google.com              (sync == tlm::TLM_UPDATED && phase == tlm::END_RESP)) ) {
44113511Sgabeblack@google.com          m_response_in_progress = true;
44213511Sgabeblack@google.com        }
44313511Sgabeblack@google.com
44413511Sgabeblack@google.com        // suspend until next transaction
44513511Sgabeblack@google.com        h->m_suspend = true;
44613511Sgabeblack@google.com        sc_core::wait();
44713511Sgabeblack@google.com      }
44813511Sgabeblack@google.com    }
44913511Sgabeblack@google.com
45013511Sgabeblack@google.com    void b2nb_thread()
45113511Sgabeblack@google.com    {
45213511Sgabeblack@google.com      while (true) {
45313511Sgabeblack@google.com        transaction_type* trans;
45413511Sgabeblack@google.com        while ((trans = m_peq.get_next_transaction())!=0) {
45513511Sgabeblack@google.com          sc_assert(m_mod);
45613511Sgabeblack@google.com          sc_assert(m_nb_transport_ptr);
45713511Sgabeblack@google.com          phase_type phase = tlm::BEGIN_REQ;
45813511Sgabeblack@google.com          sc_core::sc_time t = sc_core::SC_ZERO_TIME;
45913511Sgabeblack@google.com
46013511Sgabeblack@google.com          switch ((m_mod->*m_nb_transport_ptr)(*trans, phase, t)) {
46113511Sgabeblack@google.com          case tlm::TLM_COMPLETED:
46213511Sgabeblack@google.com          {
46313511Sgabeblack@google.com            // notify transaction is finished
46413511Sgabeblack@google.com            typename std::map<transaction_type*, sc_core::sc_event *>::iterator it =
46513511Sgabeblack@google.com              m_owner->m_pending_trans.find(trans);
46613511Sgabeblack@google.com            sc_assert(it != m_owner->m_pending_trans.end());
46713511Sgabeblack@google.com            it->second->notify(t);
46813511Sgabeblack@google.com            m_owner->m_pending_trans.erase(it);
46913511Sgabeblack@google.com            break;
47013511Sgabeblack@google.com          }
47113511Sgabeblack@google.com
47213511Sgabeblack@google.com          case tlm::TLM_ACCEPTED:
47313511Sgabeblack@google.com          case tlm::TLM_UPDATED:
47413511Sgabeblack@google.com            switch (phase) {
47513511Sgabeblack@google.com            case tlm::BEGIN_REQ:
47613511Sgabeblack@google.com              m_owner->m_current_transaction = trans;
47713511Sgabeblack@google.com              sc_core::wait(m_owner->m_end_request);
47813511Sgabeblack@google.com              m_owner->m_current_transaction = 0;
47913511Sgabeblack@google.com              break;
48013511Sgabeblack@google.com
48113511Sgabeblack@google.com            case tlm::END_REQ:
48213511Sgabeblack@google.com              sc_core::wait(t);
48313511Sgabeblack@google.com              break;
48413511Sgabeblack@google.com
48513511Sgabeblack@google.com            case tlm::BEGIN_RESP:
48613511Sgabeblack@google.com            {
48713511Sgabeblack@google.com              phase = tlm::END_RESP;
48813511Sgabeblack@google.com              sc_core::wait(t);  // This line is a bug fix added in TLM-2.0.2
48913511Sgabeblack@google.com              t = sc_core::SC_ZERO_TIME;
49013511Sgabeblack@google.com              (m_mod->*m_nb_transport_ptr)(*trans, phase, t);
49113511Sgabeblack@google.com
49213511Sgabeblack@google.com              // notify transaction is finished
49313511Sgabeblack@google.com              typename std::map<transaction_type*, sc_core::sc_event *>::iterator it =
49413511Sgabeblack@google.com                m_owner->m_pending_trans.find(trans);
49513511Sgabeblack@google.com              sc_assert(it != m_owner->m_pending_trans.end());
49613511Sgabeblack@google.com              it->second->notify(t);
49713511Sgabeblack@google.com              m_owner->m_pending_trans.erase(it);
49813511Sgabeblack@google.com              break;
49913511Sgabeblack@google.com            }
50013511Sgabeblack@google.com
50113511Sgabeblack@google.com            default:
50213511Sgabeblack@google.com              m_owner->display_error("invalid phase received");
50313511Sgabeblack@google.com            }
50413511Sgabeblack@google.com            break;
50513511Sgabeblack@google.com
50613511Sgabeblack@google.com          default:
50713511Sgabeblack@google.com            m_owner->display_error("invalid sync value received");
50813511Sgabeblack@google.com          }
50913511Sgabeblack@google.com        }
51013511Sgabeblack@google.com        sc_core::wait();
51113511Sgabeblack@google.com      }
51213511Sgabeblack@google.com    }
51313511Sgabeblack@google.com
51413511Sgabeblack@google.com    void free(tlm::tlm_generic_payload* trans)
51513511Sgabeblack@google.com    {
51613511Sgabeblack@google.com      mm_end_event_ext* ext = trans->template get_extension<mm_end_event_ext>();
51713511Sgabeblack@google.com      sc_assert(ext);
51813511Sgabeblack@google.com      // notif event first before freeing extensions (reset)
51913511Sgabeblack@google.com      ext->done.notify();
52013511Sgabeblack@google.com      trans->reset();
52113511Sgabeblack@google.com    }
52213511Sgabeblack@google.com
52313511Sgabeblack@google.com  private:
52413511Sgabeblack@google.com    struct mm_end_event_ext : public tlm::tlm_extension<mm_end_event_ext>
52513511Sgabeblack@google.com    {
52613511Sgabeblack@google.com      tlm::tlm_extension_base* clone() const { return NULL; }
52713511Sgabeblack@google.com      void free() {}
52813511Sgabeblack@google.com      void copy_from(tlm::tlm_extension_base const &) {}
52913511Sgabeblack@google.com      sc_core::sc_event done;
53013511Sgabeblack@google.com    };
53113511Sgabeblack@google.com
53213511Sgabeblack@google.com  private:
53313511Sgabeblack@google.com    simple_target_socket_b *m_owner;
53413511Sgabeblack@google.com    MODULE* m_mod;
53513511Sgabeblack@google.com    NBTransportPtr m_nb_transport_ptr;
53613511Sgabeblack@google.com    BTransportPtr m_b_transport_ptr;
53713511Sgabeblack@google.com    TransportDbgPtr m_transport_dbg_ptr;
53813511Sgabeblack@google.com    GetDirectMemPtr m_get_direct_mem_ptr;
53913511Sgabeblack@google.com    peq_with_get<transaction_type> m_peq;
54013511Sgabeblack@google.com    bool m_response_in_progress;
54113511Sgabeblack@google.com    sc_core::sc_event m_end_response;
54213511Sgabeblack@google.com  };
54313511Sgabeblack@google.com
54413511Sgabeblack@google.comprivate:
54513511Sgabeblack@google.com  const sc_core::sc_object* get_socket() const { return this; }
54613511Sgabeblack@google.comprivate:
54713511Sgabeblack@google.com  fw_process m_fw_process;
54813511Sgabeblack@google.com  bw_process m_bw_process;
54913511Sgabeblack@google.com  std::map<transaction_type*, sc_core::sc_event *> m_pending_trans;
55013511Sgabeblack@google.com  sc_core::sc_event m_end_request;
55113511Sgabeblack@google.com  transaction_type* m_current_transaction;
55213511Sgabeblack@google.com};
55313511Sgabeblack@google.com
55413511Sgabeblack@google.comtemplate< typename MODULE, unsigned int BUSWIDTH = 32
55513511Sgabeblack@google.com        , typename TYPES = tlm::tlm_base_protocol_types >
55613511Sgabeblack@google.comclass simple_target_socket
55713511Sgabeblack@google.com  : public simple_target_socket_b<MODULE,BUSWIDTH,TYPES>
55813511Sgabeblack@google.com{
55913511Sgabeblack@google.com  typedef simple_target_socket_b<MODULE,BUSWIDTH,TYPES> socket_b;
56013511Sgabeblack@google.compublic:
56113511Sgabeblack@google.com  simple_target_socket() : socket_b() {}
56213511Sgabeblack@google.com  explicit simple_target_socket(const char* name) : socket_b(name) {}
56313511Sgabeblack@google.com};
56413511Sgabeblack@google.com
56513511Sgabeblack@google.comtemplate< typename MODULE, unsigned int BUSWIDTH = 32
56613511Sgabeblack@google.com        , typename TYPES = tlm::tlm_base_protocol_types >
56713511Sgabeblack@google.comclass simple_target_socket_optional
56813511Sgabeblack@google.com  : public simple_target_socket_b<MODULE,BUSWIDTH,TYPES,sc_core::SC_ZERO_OR_MORE_BOUND>
56913511Sgabeblack@google.com{
57013511Sgabeblack@google.com  typedef simple_target_socket_b<MODULE,BUSWIDTH,TYPES,sc_core::SC_ZERO_OR_MORE_BOUND> socket_b;
57113511Sgabeblack@google.compublic:
57213511Sgabeblack@google.com  simple_target_socket_optional() : socket_b() {}
57313511Sgabeblack@google.com  explicit simple_target_socket_optional(const char* name) : socket_b(name) {}
57413511Sgabeblack@google.com};
57513511Sgabeblack@google.com
57613511Sgabeblack@google.com//ID Tagged version
57713511Sgabeblack@google.comtemplate< typename MODULE, unsigned int BUSWIDTH, typename TYPES
57813511Sgabeblack@google.com        , sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND >
57913511Sgabeblack@google.comclass simple_target_socket_tagged_b
58013511Sgabeblack@google.com  : public tlm::tlm_target_socket<BUSWIDTH, TYPES, 1, POL>
58113511Sgabeblack@google.com  , protected simple_socket_base
58213511Sgabeblack@google.com{
58313511Sgabeblack@google.com  friend class fw_process;
58413511Sgabeblack@google.com  friend class bw_process;
58513511Sgabeblack@google.compublic:
58613511Sgabeblack@google.com  typedef typename TYPES::tlm_payload_type              transaction_type;
58713511Sgabeblack@google.com  typedef typename TYPES::tlm_phase_type                phase_type;
58813511Sgabeblack@google.com  typedef tlm::tlm_sync_enum                            sync_enum_type;
58913511Sgabeblack@google.com  typedef tlm::tlm_fw_transport_if<TYPES>               fw_interface_type;
59013511Sgabeblack@google.com  typedef tlm::tlm_bw_transport_if<TYPES>               bw_interface_type;
59113511Sgabeblack@google.com  typedef tlm::tlm_target_socket<BUSWIDTH,TYPES,1,POL>  base_type;
59213511Sgabeblack@google.com
59313511Sgabeblack@google.compublic:
59413511Sgabeblack@google.com  static const char* default_name()
59513511Sgabeblack@google.com    { return sc_core::sc_gen_unique_name("simple_target_socket_tagged"); }
59613511Sgabeblack@google.com
59713511Sgabeblack@google.com  explicit simple_target_socket_tagged_b(const char* n = default_name())
59813511Sgabeblack@google.com    : base_type(n)
59913511Sgabeblack@google.com    , m_fw_process(this)
60013511Sgabeblack@google.com    , m_bw_process(this)
60113511Sgabeblack@google.com  {
60213511Sgabeblack@google.com    bind(m_fw_process);
60313511Sgabeblack@google.com  }
60413511Sgabeblack@google.com
60513511Sgabeblack@google.com  using base_type::bind;
60613511Sgabeblack@google.com
60713511Sgabeblack@google.com  // bw transport must come thru us.
60813511Sgabeblack@google.com  tlm::tlm_bw_transport_if<TYPES> * operator ->() {return &m_bw_process;}
60913511Sgabeblack@google.com
61013511Sgabeblack@google.com  // REGISTER_XXX
61113511Sgabeblack@google.com  void register_nb_transport_fw(MODULE* mod,
61213511Sgabeblack@google.com                                sync_enum_type (MODULE::*cb)(int id,
61313511Sgabeblack@google.com                                                             transaction_type&,
61413511Sgabeblack@google.com                                                             phase_type&,
61513511Sgabeblack@google.com                                                             sc_core::sc_time&),
61613511Sgabeblack@google.com                                int id)
61713511Sgabeblack@google.com  {
61813511Sgabeblack@google.com    elaboration_check("register_nb_transport_fw");
61913511Sgabeblack@google.com    m_fw_process.set_nb_transport_ptr(mod, cb);
62013511Sgabeblack@google.com    m_fw_process.set_nb_transport_user_id(id);
62113511Sgabeblack@google.com  }
62213511Sgabeblack@google.com
62313511Sgabeblack@google.com  void register_b_transport(MODULE* mod,
62413511Sgabeblack@google.com                            void (MODULE::*cb)(int id,
62513511Sgabeblack@google.com                                               transaction_type&,
62613511Sgabeblack@google.com                                               sc_core::sc_time&),
62713511Sgabeblack@google.com                            int id)
62813511Sgabeblack@google.com  {
62913511Sgabeblack@google.com    elaboration_check("register_b_transport");
63013511Sgabeblack@google.com    m_fw_process.set_b_transport_ptr(mod, cb);
63113511Sgabeblack@google.com    m_fw_process.set_b_transport_user_id(id);
63213511Sgabeblack@google.com  }
63313511Sgabeblack@google.com
63413511Sgabeblack@google.com  void register_transport_dbg(MODULE* mod,
63513511Sgabeblack@google.com                              unsigned int (MODULE::*cb)(int id,
63613511Sgabeblack@google.com                                                         transaction_type&),
63713511Sgabeblack@google.com                              int id)
63813511Sgabeblack@google.com  {
63913511Sgabeblack@google.com    elaboration_check("register_transport_dbg");
64013511Sgabeblack@google.com    m_fw_process.set_transport_dbg_ptr(mod, cb);
64113511Sgabeblack@google.com    m_fw_process.set_transport_dbg_user_id(id);
64213511Sgabeblack@google.com  }
64313511Sgabeblack@google.com
64413511Sgabeblack@google.com  void register_get_direct_mem_ptr(MODULE* mod,
64513511Sgabeblack@google.com                                   bool (MODULE::*cb)(int id,
64613511Sgabeblack@google.com                                                      transaction_type&,
64713511Sgabeblack@google.com                                                      tlm::tlm_dmi&),
64813511Sgabeblack@google.com                                   int id)
64913511Sgabeblack@google.com  {
65013511Sgabeblack@google.com    elaboration_check("register_get_direct_mem_ptr");
65113511Sgabeblack@google.com    m_fw_process.set_get_direct_mem_ptr(mod, cb);
65213511Sgabeblack@google.com    m_fw_process.set_get_dmi_user_id(id);
65313511Sgabeblack@google.com  }
65413511Sgabeblack@google.com
65513511Sgabeblack@google.comprotected:
65613511Sgabeblack@google.com  void start_of_simulation()
65713511Sgabeblack@google.com  {
65813511Sgabeblack@google.com    base_type::start_of_simulation();
65913511Sgabeblack@google.com    m_fw_process.start_of_simulation();
66013511Sgabeblack@google.com  }
66113511Sgabeblack@google.com
66213511Sgabeblack@google.comprivate:
66313511Sgabeblack@google.com  //make call on bw path.
66413511Sgabeblack@google.com  sync_enum_type bw_nb_transport(transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
66513511Sgabeblack@google.com  {
66613511Sgabeblack@google.com    return base_type::operator ->()->nb_transport_bw(trans, phase, t);
66713511Sgabeblack@google.com  }
66813511Sgabeblack@google.com
66913511Sgabeblack@google.com  void bw_invalidate_direct_mem_ptr(sc_dt::uint64 s,sc_dt::uint64 e)
67013511Sgabeblack@google.com  {
67113511Sgabeblack@google.com    base_type::operator ->()->invalidate_direct_mem_ptr(s, e);
67213511Sgabeblack@google.com  }
67313511Sgabeblack@google.com
67413511Sgabeblack@google.com  //Helper class to handle bw path calls
67513511Sgabeblack@google.com  // Needed to detect transaction end when called from b_transport.
67613511Sgabeblack@google.com  class bw_process : public tlm::tlm_bw_transport_if<TYPES>
67713511Sgabeblack@google.com  {
67813511Sgabeblack@google.com  public:
67913511Sgabeblack@google.com    bw_process(simple_target_socket_tagged_b *p_own) : m_owner(p_own)
68013511Sgabeblack@google.com    {
68113511Sgabeblack@google.com    }
68213511Sgabeblack@google.com
68313511Sgabeblack@google.com    sync_enum_type nb_transport_bw(transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
68413511Sgabeblack@google.com    {
68513511Sgabeblack@google.com      typename std::map<transaction_type*, sc_core::sc_event *>::iterator it =
68613511Sgabeblack@google.com        m_owner->m_pending_trans.find(&trans);
68713511Sgabeblack@google.com
68813511Sgabeblack@google.com      if(it == m_owner->m_pending_trans.end()) {
68913511Sgabeblack@google.com        // Not a blocking call, forward.
69013511Sgabeblack@google.com        return m_owner->bw_nb_transport(trans, phase, t);
69113511Sgabeblack@google.com      }
69213511Sgabeblack@google.com      if (phase == tlm::END_REQ) {
69313511Sgabeblack@google.com        m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME);
69413511Sgabeblack@google.com        return tlm::TLM_ACCEPTED;
69513511Sgabeblack@google.com      }
69613511Sgabeblack@google.com      if (phase == tlm::BEGIN_RESP) {
69713511Sgabeblack@google.com        if (m_owner->m_current_transaction == &trans) {
69813511Sgabeblack@google.com          m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME);
69913511Sgabeblack@google.com        }
70013511Sgabeblack@google.com        //TODO: add response-accept delay?
70113511Sgabeblack@google.com        it->second->notify(t);
70213511Sgabeblack@google.com        m_owner->m_pending_trans.erase(it);
70313511Sgabeblack@google.com        return tlm::TLM_COMPLETED;
70413511Sgabeblack@google.com      }
70513511Sgabeblack@google.com      m_owner->display_error("invalid phase received");
70613511Sgabeblack@google.com      return tlm::TLM_COMPLETED;
70713511Sgabeblack@google.com    }
70813511Sgabeblack@google.com
70913511Sgabeblack@google.com    void invalidate_direct_mem_ptr(sc_dt::uint64 s,sc_dt::uint64 e)
71013511Sgabeblack@google.com    {
71113511Sgabeblack@google.com      return m_owner->bw_invalidate_direct_mem_ptr(s, e);
71213511Sgabeblack@google.com    }
71313511Sgabeblack@google.com
71413511Sgabeblack@google.com  private:
71513511Sgabeblack@google.com    simple_target_socket_tagged_b *m_owner;
71613511Sgabeblack@google.com  };
71713511Sgabeblack@google.com
71813511Sgabeblack@google.com  class fw_process : public tlm::tlm_fw_transport_if<TYPES>,
71913511Sgabeblack@google.com                     public tlm::tlm_mm_interface
72013511Sgabeblack@google.com  {
72113511Sgabeblack@google.com  public:
72213511Sgabeblack@google.com    typedef sync_enum_type (MODULE::*NBTransportPtr)(int id,
72313511Sgabeblack@google.com                                                     transaction_type&,
72413511Sgabeblack@google.com                                                     phase_type&,
72513511Sgabeblack@google.com                                                     sc_core::sc_time&);
72613511Sgabeblack@google.com    typedef void (MODULE::*BTransportPtr)(int id,
72713511Sgabeblack@google.com                                          transaction_type&,
72813511Sgabeblack@google.com                                          sc_core::sc_time&);
72913511Sgabeblack@google.com    typedef unsigned int (MODULE::*TransportDbgPtr)(int id,
73013511Sgabeblack@google.com                                                    transaction_type&);
73113511Sgabeblack@google.com    typedef bool (MODULE::*GetDirectMemPtr)(int id,
73213511Sgabeblack@google.com                                            transaction_type&,
73313511Sgabeblack@google.com                                            tlm::tlm_dmi&);
73413511Sgabeblack@google.com
73513511Sgabeblack@google.com    fw_process(simple_target_socket_tagged_b *p_own) :
73613511Sgabeblack@google.com      m_owner(p_own),
73713511Sgabeblack@google.com      m_mod(0),
73813511Sgabeblack@google.com      m_nb_transport_ptr(0),
73913511Sgabeblack@google.com      m_b_transport_ptr(0),
74013511Sgabeblack@google.com      m_transport_dbg_ptr(0),
74113511Sgabeblack@google.com      m_get_direct_mem_ptr(0),
74213511Sgabeblack@google.com      m_nb_transport_user_id(0),
74313511Sgabeblack@google.com      m_b_transport_user_id(0),
74413511Sgabeblack@google.com      m_transport_dbg_user_id(0),
74513511Sgabeblack@google.com      m_get_dmi_user_id(0),
74613511Sgabeblack@google.com      m_peq(sc_core::sc_gen_unique_name("m_peq")),
74713511Sgabeblack@google.com      m_response_in_progress(false)
74813511Sgabeblack@google.com    {}
74913511Sgabeblack@google.com
75013511Sgabeblack@google.com    void start_of_simulation()
75113511Sgabeblack@google.com    {
75213511Sgabeblack@google.com      if (!m_b_transport_ptr && m_nb_transport_ptr) { // only spawn b2nb_thread, if needed
75313511Sgabeblack@google.com        sc_core::sc_spawn_options opts;
75413511Sgabeblack@google.com        opts.set_sensitivity(&m_peq.get_event());
75513511Sgabeblack@google.com        opts.dont_initialize();
75613511Sgabeblack@google.com        sc_core::sc_spawn(sc_bind(&fw_process::b2nb_thread, this),
75713511Sgabeblack@google.com                          sc_core::sc_gen_unique_name("b2nb_thread"), &opts);
75813511Sgabeblack@google.com      }
75913511Sgabeblack@google.com    }
76013511Sgabeblack@google.com
76113511Sgabeblack@google.com    void set_nb_transport_user_id(int id) { m_nb_transport_user_id = id; }
76213511Sgabeblack@google.com    void set_b_transport_user_id(int id) { m_b_transport_user_id = id; }
76313511Sgabeblack@google.com    void set_transport_dbg_user_id(int id) { m_transport_dbg_user_id = id; }
76413511Sgabeblack@google.com    void set_get_dmi_user_id(int id) { m_get_dmi_user_id = id; }
76513511Sgabeblack@google.com
76613511Sgabeblack@google.com    void set_nb_transport_ptr(MODULE* mod, NBTransportPtr p)
76713511Sgabeblack@google.com    {
76813511Sgabeblack@google.com      if (m_nb_transport_ptr) {
76913511Sgabeblack@google.com        m_owner->display_warning("non-blocking callback already registered");
77013511Sgabeblack@google.com        return;
77113511Sgabeblack@google.com      }
77213511Sgabeblack@google.com      sc_assert(!m_mod || m_mod == mod);
77313511Sgabeblack@google.com      m_mod = mod;
77413511Sgabeblack@google.com      m_nb_transport_ptr = p;
77513511Sgabeblack@google.com    }
77613511Sgabeblack@google.com
77713511Sgabeblack@google.com    void set_b_transport_ptr(MODULE* mod, BTransportPtr p)
77813511Sgabeblack@google.com    {
77913511Sgabeblack@google.com      if (m_b_transport_ptr) {
78013511Sgabeblack@google.com        m_owner->display_warning("blocking callback already registered");
78113511Sgabeblack@google.com        return;
78213511Sgabeblack@google.com      }
78313511Sgabeblack@google.com      sc_assert(!m_mod || m_mod == mod);
78413511Sgabeblack@google.com      m_mod = mod;
78513511Sgabeblack@google.com      m_b_transport_ptr = p;
78613511Sgabeblack@google.com    }
78713511Sgabeblack@google.com
78813511Sgabeblack@google.com    void set_transport_dbg_ptr(MODULE* mod, TransportDbgPtr p)
78913511Sgabeblack@google.com    {
79013511Sgabeblack@google.com      if (m_transport_dbg_ptr) {
79113511Sgabeblack@google.com        m_owner->display_warning("debug callback already registered");
79213511Sgabeblack@google.com        return;
79313511Sgabeblack@google.com      }
79413511Sgabeblack@google.com      sc_assert(!m_mod || m_mod == mod);
79513511Sgabeblack@google.com      m_mod = mod;
79613511Sgabeblack@google.com      m_transport_dbg_ptr = p;
79713511Sgabeblack@google.com    }
79813511Sgabeblack@google.com
79913511Sgabeblack@google.com    void set_get_direct_mem_ptr(MODULE* mod, GetDirectMemPtr p)
80013511Sgabeblack@google.com    {
80113511Sgabeblack@google.com      if (m_get_direct_mem_ptr) {
80213511Sgabeblack@google.com        m_owner->display_warning("get DMI pointer callback already registered");
80313511Sgabeblack@google.com      }
80413511Sgabeblack@google.com      sc_assert(!m_mod || m_mod == mod);
80513511Sgabeblack@google.com      m_mod = mod;
80613511Sgabeblack@google.com      m_get_direct_mem_ptr = p;
80713511Sgabeblack@google.com    }
80813511Sgabeblack@google.com// Interface implementation
80913511Sgabeblack@google.com    sync_enum_type nb_transport_fw(transaction_type& trans,
81013511Sgabeblack@google.com                                   phase_type& phase,
81113511Sgabeblack@google.com                                   sc_core::sc_time& t)
81213511Sgabeblack@google.com    {
81313511Sgabeblack@google.com      if (m_nb_transport_ptr) {
81413511Sgabeblack@google.com        // forward call
81513511Sgabeblack@google.com        sc_assert(m_mod);
81613511Sgabeblack@google.com        return (m_mod->*m_nb_transport_ptr)(m_nb_transport_user_id, trans, phase, t);
81713511Sgabeblack@google.com      }
81813511Sgabeblack@google.com
81913511Sgabeblack@google.com      // nb->b conversion
82013511Sgabeblack@google.com      if (m_b_transport_ptr) {
82113511Sgabeblack@google.com        if (phase == tlm::BEGIN_REQ) {
82213511Sgabeblack@google.com
82313511Sgabeblack@google.com          // prepare thread to do blocking call
82413511Sgabeblack@google.com          process_handle_class * ph = m_process_handle.get_handle(&trans);
82513511Sgabeblack@google.com
82613511Sgabeblack@google.com          if (!ph) { // create new dynamic process
82713511Sgabeblack@google.com            ph = new process_handle_class(&trans);
82813511Sgabeblack@google.com            m_process_handle.put_handle(ph);
82913511Sgabeblack@google.com
83013511Sgabeblack@google.com            sc_core::sc_spawn_options opts;
83113511Sgabeblack@google.com            opts.dont_initialize();
83213511Sgabeblack@google.com            opts.set_sensitivity(&ph->m_e);
83313511Sgabeblack@google.com
83413511Sgabeblack@google.com            sc_core::sc_spawn(sc_bind(&fw_process::nb2b_thread, this, ph),
83513511Sgabeblack@google.com                            sc_core::sc_gen_unique_name("nb2b_thread"), &opts);
83613511Sgabeblack@google.com          }
83713511Sgabeblack@google.com
83813511Sgabeblack@google.com          ph->m_e.notify(t);
83913511Sgabeblack@google.com          return tlm::TLM_ACCEPTED;
84013511Sgabeblack@google.com        }
84113511Sgabeblack@google.com        if (phase == tlm::END_RESP) {
84213511Sgabeblack@google.com          m_response_in_progress = false;
84313511Sgabeblack@google.com          m_end_response.notify(t);
84413511Sgabeblack@google.com          return tlm::TLM_COMPLETED;
84513511Sgabeblack@google.com        }
84613511Sgabeblack@google.com        m_owner->display_error("invalid phase");
84713511Sgabeblack@google.com        return tlm::TLM_COMPLETED;
84813511Sgabeblack@google.com      }
84913511Sgabeblack@google.com
85013511Sgabeblack@google.com      m_owner->display_error("no non-blocking transport callback registered");
85113511Sgabeblack@google.com      return tlm::TLM_COMPLETED;
85213511Sgabeblack@google.com    }
85313511Sgabeblack@google.com
85413511Sgabeblack@google.com    void b_transport(transaction_type& trans, sc_core::sc_time& t)
85513511Sgabeblack@google.com    {
85613511Sgabeblack@google.com      if (m_b_transport_ptr) {
85713511Sgabeblack@google.com        // forward call
85813511Sgabeblack@google.com        sc_assert(m_mod);
85913511Sgabeblack@google.com        (m_mod->*m_b_transport_ptr)(m_b_transport_user_id, trans, t);
86013511Sgabeblack@google.com        return;
86113511Sgabeblack@google.com      }
86213511Sgabeblack@google.com
86313511Sgabeblack@google.com      // b->nb conversion
86413511Sgabeblack@google.com      if (m_nb_transport_ptr) {
86513511Sgabeblack@google.com        m_peq.notify(trans, t);
86613511Sgabeblack@google.com        t = sc_core::SC_ZERO_TIME;
86713511Sgabeblack@google.com
86813511Sgabeblack@google.com        mm_end_event_ext mm_ext;
86913511Sgabeblack@google.com        const bool mm_added = !trans.has_mm();
87013511Sgabeblack@google.com
87113511Sgabeblack@google.com        if (mm_added){
87213511Sgabeblack@google.com          trans.set_mm(this);
87313511Sgabeblack@google.com          trans.set_auto_extension(&mm_ext);
87413511Sgabeblack@google.com          trans.acquire();
87513511Sgabeblack@google.com        }
87613511Sgabeblack@google.com
87713511Sgabeblack@google.com        // wait until transaction is finished
87813511Sgabeblack@google.com        sc_core::sc_event end_event;
87913511Sgabeblack@google.com        m_owner->m_pending_trans[&trans] = &end_event;
88013511Sgabeblack@google.com        sc_core::wait(end_event);
88113511Sgabeblack@google.com
88213511Sgabeblack@google.com        if (mm_added) {
88313511Sgabeblack@google.com          // release will not delete the transaction, it will notify mm_ext.done
88413511Sgabeblack@google.com          trans.release();
88513511Sgabeblack@google.com          if (trans.get_ref_count()) {
88613511Sgabeblack@google.com            sc_core::wait(mm_ext.done);
88713511Sgabeblack@google.com          }
88813511Sgabeblack@google.com          trans.set_mm(0);
88913511Sgabeblack@google.com        }
89013511Sgabeblack@google.com        return;
89113511Sgabeblack@google.com      }
89213511Sgabeblack@google.com
89313511Sgabeblack@google.com      m_owner->display_error("no transport callback registered");
89413511Sgabeblack@google.com    }
89513511Sgabeblack@google.com
89613511Sgabeblack@google.com    unsigned int transport_dbg(transaction_type& trans)
89713511Sgabeblack@google.com    {
89813511Sgabeblack@google.com      if (m_transport_dbg_ptr) {
89913511Sgabeblack@google.com        // forward call
90013511Sgabeblack@google.com        sc_assert(m_mod);
90113511Sgabeblack@google.com        return (m_mod->*m_transport_dbg_ptr)(m_transport_dbg_user_id, trans);
90213511Sgabeblack@google.com      }
90313511Sgabeblack@google.com      // No debug support
90413511Sgabeblack@google.com      return 0;
90513511Sgabeblack@google.com    }
90613511Sgabeblack@google.com
90713511Sgabeblack@google.com    bool get_direct_mem_ptr(transaction_type& trans,
90813511Sgabeblack@google.com                            tlm::tlm_dmi&  dmi_data)
90913511Sgabeblack@google.com    {
91013511Sgabeblack@google.com      if (m_get_direct_mem_ptr) {
91113511Sgabeblack@google.com        // forward call
91213511Sgabeblack@google.com        sc_assert(m_mod);
91313511Sgabeblack@google.com        return (m_mod->*m_get_direct_mem_ptr)(m_get_dmi_user_id, trans, dmi_data);
91413511Sgabeblack@google.com      }
91513511Sgabeblack@google.com      // No DMI support
91613511Sgabeblack@google.com      dmi_data.allow_read_write();
91713511Sgabeblack@google.com      dmi_data.set_start_address(0x0);
91813511Sgabeblack@google.com      dmi_data.set_end_address((sc_dt::uint64)-1);
91913511Sgabeblack@google.com      return false;
92013511Sgabeblack@google.com    }
92113511Sgabeblack@google.com
92213511Sgabeblack@google.com  private:
92313511Sgabeblack@google.com// dynamic process handler for nb2b conversion
92413511Sgabeblack@google.com
92513511Sgabeblack@google.com    class process_handle_class {
92613511Sgabeblack@google.com    public:
92713511Sgabeblack@google.com      explicit process_handle_class(transaction_type * trans)
92813511Sgabeblack@google.com        : m_trans(trans),m_suspend(false){}
92913511Sgabeblack@google.com
93013511Sgabeblack@google.com      transaction_type*  m_trans;
93113511Sgabeblack@google.com      sc_core::sc_event  m_e;
93213511Sgabeblack@google.com      bool m_suspend;
93313511Sgabeblack@google.com    };
93413511Sgabeblack@google.com
93513511Sgabeblack@google.com    class process_handle_list {
93613511Sgabeblack@google.com    public:
93713511Sgabeblack@google.com      process_handle_list() {}
93813511Sgabeblack@google.com
93913511Sgabeblack@google.com      ~process_handle_list() {
94013511Sgabeblack@google.com        for( typename std::vector<process_handle_class*>::iterator
94113511Sgabeblack@google.com               it=v.begin(), end = v.end(); it != end; ++it )
94213511Sgabeblack@google.com          delete *it;
94313511Sgabeblack@google.com      }
94413511Sgabeblack@google.com
94513511Sgabeblack@google.com      process_handle_class* get_handle(transaction_type *trans)
94613511Sgabeblack@google.com      {
94713511Sgabeblack@google.com        typename std::vector<process_handle_class*>::iterator it;
94813511Sgabeblack@google.com
94913511Sgabeblack@google.com        for(it = v.begin(); it != v.end(); it++) {
95013511Sgabeblack@google.com          if ((*it)->m_suspend) {  // found suspended dynamic process, re-use it
95113511Sgabeblack@google.com            (*it)->m_trans   = trans; // replace to new one
95213511Sgabeblack@google.com            (*it)->m_suspend = false;
95313511Sgabeblack@google.com            return *it;
95413511Sgabeblack@google.com          }
95513511Sgabeblack@google.com        }
95613511Sgabeblack@google.com        return NULL; // no suspended process
95713511Sgabeblack@google.com      }
95813511Sgabeblack@google.com
95913511Sgabeblack@google.com      void put_handle(process_handle_class* ph)
96013511Sgabeblack@google.com      {
96113511Sgabeblack@google.com        v.push_back(ph);
96213511Sgabeblack@google.com      }
96313511Sgabeblack@google.com
96413511Sgabeblack@google.com    private:
96513511Sgabeblack@google.com      std::vector<process_handle_class*> v;
96613511Sgabeblack@google.com    };
96713511Sgabeblack@google.com
96813511Sgabeblack@google.com    process_handle_list m_process_handle;
96913511Sgabeblack@google.com
97013511Sgabeblack@google.com    void nb2b_thread(process_handle_class* h)
97113511Sgabeblack@google.com    {
97213511Sgabeblack@google.com
97313511Sgabeblack@google.com      while(1) {
97413511Sgabeblack@google.com        transaction_type * trans = h->m_trans;
97513511Sgabeblack@google.com        sc_core::sc_time t = sc_core::SC_ZERO_TIME;
97613511Sgabeblack@google.com
97713511Sgabeblack@google.com        // forward call
97813511Sgabeblack@google.com        sc_assert(m_mod);
97913511Sgabeblack@google.com        (m_mod->*m_b_transport_ptr)(m_b_transport_user_id, *trans, t);
98013511Sgabeblack@google.com
98113511Sgabeblack@google.com        sc_core::wait(t);
98213511Sgabeblack@google.com
98313511Sgabeblack@google.com        // return path
98413511Sgabeblack@google.com        while (m_response_in_progress) {
98513511Sgabeblack@google.com          sc_core::wait(m_end_response);
98613511Sgabeblack@google.com        }
98713511Sgabeblack@google.com        t = sc_core::SC_ZERO_TIME;
98813511Sgabeblack@google.com        phase_type phase    = tlm::BEGIN_RESP;
98913511Sgabeblack@google.com        sync_enum_type sync = m_owner->bw_nb_transport(*trans, phase, t);
99013511Sgabeblack@google.com        if ( !(sync == tlm::TLM_COMPLETED ||
99113511Sgabeblack@google.com              (sync == tlm::TLM_UPDATED && phase == tlm::END_RESP)) ) {
99213511Sgabeblack@google.com          m_response_in_progress = true;
99313511Sgabeblack@google.com        }
99413511Sgabeblack@google.com
99513511Sgabeblack@google.com        // suspend until next transaction
99613511Sgabeblack@google.com        h->m_suspend = true;
99713511Sgabeblack@google.com        sc_core::wait();
99813511Sgabeblack@google.com      }
99913511Sgabeblack@google.com    }
100013511Sgabeblack@google.com
100113511Sgabeblack@google.com    void b2nb_thread()
100213511Sgabeblack@google.com    {
100313511Sgabeblack@google.com      while (true) {
100413511Sgabeblack@google.com        transaction_type* trans;
100513511Sgabeblack@google.com        while ((trans = m_peq.get_next_transaction())!=0) {
100613511Sgabeblack@google.com          sc_assert(m_mod);
100713511Sgabeblack@google.com          sc_assert(m_nb_transport_ptr);
100813511Sgabeblack@google.com          phase_type phase = tlm::BEGIN_REQ;
100913511Sgabeblack@google.com          sc_core::sc_time t = sc_core::SC_ZERO_TIME;
101013511Sgabeblack@google.com
101113511Sgabeblack@google.com          switch ((m_mod->*m_nb_transport_ptr)(m_nb_transport_user_id, *trans, phase, t)) {
101213511Sgabeblack@google.com          case tlm::TLM_COMPLETED:
101313511Sgabeblack@google.com          {
101413511Sgabeblack@google.com            // notify transaction is finished
101513511Sgabeblack@google.com            typename std::map<transaction_type*, sc_core::sc_event *>::iterator it =
101613511Sgabeblack@google.com              m_owner->m_pending_trans.find(trans);
101713511Sgabeblack@google.com            sc_assert(it != m_owner->m_pending_trans.end());
101813511Sgabeblack@google.com            it->second->notify(t);
101913511Sgabeblack@google.com            m_owner->m_pending_trans.erase(it);
102013511Sgabeblack@google.com            break;
102113511Sgabeblack@google.com          }
102213511Sgabeblack@google.com
102313511Sgabeblack@google.com          case tlm::TLM_ACCEPTED:
102413511Sgabeblack@google.com          case tlm::TLM_UPDATED:
102513511Sgabeblack@google.com            switch (phase) {
102613511Sgabeblack@google.com            case tlm::BEGIN_REQ:
102713511Sgabeblack@google.com              m_owner->m_current_transaction = trans;
102813511Sgabeblack@google.com              sc_core::wait(m_owner->m_end_request);
102913511Sgabeblack@google.com              m_owner->m_current_transaction = 0;
103013511Sgabeblack@google.com              break;
103113511Sgabeblack@google.com
103213511Sgabeblack@google.com            case tlm::END_REQ:
103313511Sgabeblack@google.com              sc_core::wait(t);
103413511Sgabeblack@google.com              break;
103513511Sgabeblack@google.com
103613511Sgabeblack@google.com            case tlm::BEGIN_RESP:
103713511Sgabeblack@google.com            {
103813511Sgabeblack@google.com              phase = tlm::END_RESP;
103913511Sgabeblack@google.com              sc_core::wait(t);  // This line is a bug fix added in TLM-2.0.2
104013511Sgabeblack@google.com              t = sc_core::SC_ZERO_TIME;
104113511Sgabeblack@google.com              (m_mod->*m_nb_transport_ptr)(m_nb_transport_user_id, *trans, phase, t);
104213511Sgabeblack@google.com
104313511Sgabeblack@google.com              // notify transaction is finished
104413511Sgabeblack@google.com              typename std::map<transaction_type*, sc_core::sc_event *>::iterator it =
104513511Sgabeblack@google.com                m_owner->m_pending_trans.find(trans);
104613511Sgabeblack@google.com              sc_assert(it != m_owner->m_pending_trans.end());
104713511Sgabeblack@google.com              it->second->notify(t);
104813511Sgabeblack@google.com              m_owner->m_pending_trans.erase(it);
104913511Sgabeblack@google.com              break;
105013511Sgabeblack@google.com            }
105113511Sgabeblack@google.com
105213511Sgabeblack@google.com            default:
105313511Sgabeblack@google.com              m_owner->display_error("invalid phase received");
105413511Sgabeblack@google.com            };
105513511Sgabeblack@google.com            break;
105613511Sgabeblack@google.com
105713511Sgabeblack@google.com          default:
105813511Sgabeblack@google.com            m_owner->display_error("invalid sync value received");
105913511Sgabeblack@google.com          }
106013511Sgabeblack@google.com        }
106113511Sgabeblack@google.com        sc_core::wait();
106213511Sgabeblack@google.com      }
106313511Sgabeblack@google.com    }
106413511Sgabeblack@google.com
106513511Sgabeblack@google.com    void free(tlm::tlm_generic_payload* trans)
106613511Sgabeblack@google.com    {
106713511Sgabeblack@google.com      mm_end_event_ext* ext = trans->template get_extension<mm_end_event_ext>();
106813511Sgabeblack@google.com      sc_assert(ext);
106913511Sgabeblack@google.com      // notif event first before freeing extensions (reset)
107013511Sgabeblack@google.com      ext->done.notify();
107113511Sgabeblack@google.com      trans->reset();
107213511Sgabeblack@google.com    }
107313511Sgabeblack@google.com
107413511Sgabeblack@google.com  private:
107513511Sgabeblack@google.com    struct mm_end_event_ext : public tlm::tlm_extension<mm_end_event_ext>
107613511Sgabeblack@google.com    {
107713511Sgabeblack@google.com      tlm::tlm_extension_base* clone() const { return NULL; }
107813511Sgabeblack@google.com      void free() {}
107913511Sgabeblack@google.com      void copy_from(tlm::tlm_extension_base const &) {}
108013511Sgabeblack@google.com      sc_core::sc_event done;
108113511Sgabeblack@google.com    };
108213511Sgabeblack@google.com
108313511Sgabeblack@google.com  private:
108413511Sgabeblack@google.com    simple_target_socket_tagged_b *m_owner;
108513511Sgabeblack@google.com    MODULE* m_mod;
108613511Sgabeblack@google.com    NBTransportPtr m_nb_transport_ptr;
108713511Sgabeblack@google.com    BTransportPtr m_b_transport_ptr;
108813511Sgabeblack@google.com    TransportDbgPtr m_transport_dbg_ptr;
108913511Sgabeblack@google.com    GetDirectMemPtr m_get_direct_mem_ptr;
109013511Sgabeblack@google.com    int m_nb_transport_user_id;
109113511Sgabeblack@google.com    int m_b_transport_user_id;
109213511Sgabeblack@google.com    int m_transport_dbg_user_id;
109313511Sgabeblack@google.com    int m_get_dmi_user_id;
109413511Sgabeblack@google.com    peq_with_get<transaction_type> m_peq;
109513511Sgabeblack@google.com    bool m_response_in_progress;
109613511Sgabeblack@google.com    sc_core::sc_event m_end_response;
109713511Sgabeblack@google.com  };
109813511Sgabeblack@google.com
109913511Sgabeblack@google.comprivate:
110013511Sgabeblack@google.com  const sc_core::sc_object* get_socket() const { return this; }
110113511Sgabeblack@google.comprivate:
110213511Sgabeblack@google.com  fw_process m_fw_process;
110313511Sgabeblack@google.com  bw_process m_bw_process;
110413511Sgabeblack@google.com  std::map<transaction_type*, sc_core::sc_event *> m_pending_trans;
110513511Sgabeblack@google.com  sc_core::sc_event m_end_request;
110613511Sgabeblack@google.com  transaction_type* m_current_transaction;
110713511Sgabeblack@google.com};
110813511Sgabeblack@google.com
110913511Sgabeblack@google.comtemplate< typename MODULE, unsigned int BUSWIDTH = 32
111013511Sgabeblack@google.com        , typename TYPES = tlm::tlm_base_protocol_types >
111113511Sgabeblack@google.comclass simple_target_socket_tagged
111213511Sgabeblack@google.com  : public simple_target_socket_tagged_b<MODULE,BUSWIDTH,TYPES>
111313511Sgabeblack@google.com{
111413511Sgabeblack@google.com  typedef simple_target_socket_tagged_b<MODULE,BUSWIDTH,TYPES> socket_b;
111513511Sgabeblack@google.compublic:
111613511Sgabeblack@google.com  simple_target_socket_tagged() : socket_b() {}
111713511Sgabeblack@google.com  explicit simple_target_socket_tagged(const char* name) : socket_b(name) {}
111813511Sgabeblack@google.com};
111913511Sgabeblack@google.com
112013511Sgabeblack@google.comtemplate< typename MODULE, unsigned int BUSWIDTH = 32
112113511Sgabeblack@google.com        , typename TYPES = tlm::tlm_base_protocol_types >
112213511Sgabeblack@google.comclass simple_target_socket_tagged_optional
112313511Sgabeblack@google.com  : public simple_target_socket_tagged_b<MODULE,BUSWIDTH,TYPES,sc_core::SC_ZERO_OR_MORE_BOUND>
112413511Sgabeblack@google.com{
112513511Sgabeblack@google.com  typedef simple_target_socket_tagged_b<MODULE,BUSWIDTH,TYPES,sc_core::SC_ZERO_OR_MORE_BOUND> socket_b;
112613511Sgabeblack@google.compublic:
112713511Sgabeblack@google.com  simple_target_socket_tagged_optional() : socket_b() {}
112813511Sgabeblack@google.com  explicit simple_target_socket_tagged_optional(const char* name) : socket_b(name) {}
112913511Sgabeblack@google.com};
113013511Sgabeblack@google.com
113113511Sgabeblack@google.com} // namespace tlm_utils
113213511Sgabeblack@google.com#endif // TLM_UTILS_SIMPLE_TARGET_SOCKET_H_INCLUDED_
1133