112027Sjungma@eit.uni-kl.de/*****************************************************************************
212027Sjungma@eit.uni-kl.de
312027Sjungma@eit.uni-kl.de  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
412027Sjungma@eit.uni-kl.de  more contributor license agreements.  See the NOTICE file distributed
512027Sjungma@eit.uni-kl.de  with this work for additional information regarding copyright ownership.
612027Sjungma@eit.uni-kl.de  Accellera licenses this file to you under the Apache License, Version 2.0
712027Sjungma@eit.uni-kl.de  (the "License"); you may not use this file except in compliance with the
812027Sjungma@eit.uni-kl.de  License.  You may obtain a copy of the License at
912027Sjungma@eit.uni-kl.de
1012027Sjungma@eit.uni-kl.de    http://www.apache.org/licenses/LICENSE-2.0
1112027Sjungma@eit.uni-kl.de
1212027Sjungma@eit.uni-kl.de  Unless required by applicable law or agreed to in writing, software
1312027Sjungma@eit.uni-kl.de  distributed under the License is distributed on an "AS IS" BASIS,
1412027Sjungma@eit.uni-kl.de  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
1512027Sjungma@eit.uni-kl.de  implied.  See the License for the specific language governing
1612027Sjungma@eit.uni-kl.de  permissions and limitations under the License.
1712027Sjungma@eit.uni-kl.de
1812027Sjungma@eit.uni-kl.de *****************************************************************************/
1912027Sjungma@eit.uni-kl.de
2012027Sjungma@eit.uni-kl.de// *****************************************************************************
2112027Sjungma@eit.uni-kl.de// Modified by John Aynsley, Doulos, Feb 2009,
2212027Sjungma@eit.uni-kl.de// Fix a bug in simple_target_socket and simple_target_socket_tagged
2312027Sjungma@eit.uni-kl.de// with the addition of one new line of code in each:  wait(*e);
2412027Sjungma@eit.uni-kl.de// *****************************************************************************
2512027Sjungma@eit.uni-kl.de
2612027Sjungma@eit.uni-kl.de// *****************************************************************************
2712027Sjungma@eit.uni-kl.de// Modified by John Aynsley on behalf of Robert Guenzel, May 2011,
2812027Sjungma@eit.uni-kl.de// Fix a bug in simple_target_socket and simple_target_socket_tagged
2912027Sjungma@eit.uni-kl.de// with the addition of one new line of code in each:  wait(t);
3012027Sjungma@eit.uni-kl.de// *****************************************************************************
3112027Sjungma@eit.uni-kl.de
3212027Sjungma@eit.uni-kl.de
3312027Sjungma@eit.uni-kl.de#ifndef __SIMPLE_TARGET_SOCKET_H__
3412027Sjungma@eit.uni-kl.de#define __SIMPLE_TARGET_SOCKET_H__
3512027Sjungma@eit.uni-kl.de
3612027Sjungma@eit.uni-kl.de#ifndef SC_INCLUDE_DYNAMIC_PROCESSES // needed for sc_spawn
3712027Sjungma@eit.uni-kl.de#  define SC_INCLUDE_DYNAMIC_PROCESSES
3812027Sjungma@eit.uni-kl.de#endif
3912027Sjungma@eit.uni-kl.de
4012027Sjungma@eit.uni-kl.de#include <systemc>
4112027Sjungma@eit.uni-kl.de#include <tlm>
4212027Sjungma@eit.uni-kl.de#include "tlm_utils/peq_with_get.h"
4312027Sjungma@eit.uni-kl.de#include <sstream>
4412027Sjungma@eit.uni-kl.de
4512027Sjungma@eit.uni-kl.denamespace tlm_utils {
4612027Sjungma@eit.uni-kl.de
4712027Sjungma@eit.uni-kl.detemplate <typename MODULE,
4812027Sjungma@eit.uni-kl.de          unsigned int BUSWIDTH = 32,
4912027Sjungma@eit.uni-kl.de          typename TYPES = tlm::tlm_base_protocol_types>
5012027Sjungma@eit.uni-kl.declass simple_target_socket :
5112027Sjungma@eit.uni-kl.de  public tlm::tlm_target_socket<BUSWIDTH, TYPES>
5212027Sjungma@eit.uni-kl.de{
5312027Sjungma@eit.uni-kl.de  friend class fw_process;
5412027Sjungma@eit.uni-kl.de  friend class bw_process;
5512027Sjungma@eit.uni-kl.depublic:
5612027Sjungma@eit.uni-kl.de  typedef typename TYPES::tlm_payload_type              transaction_type;
5712027Sjungma@eit.uni-kl.de  typedef typename TYPES::tlm_phase_type                phase_type;
5812027Sjungma@eit.uni-kl.de  typedef tlm::tlm_sync_enum                            sync_enum_type;
5912027Sjungma@eit.uni-kl.de  typedef tlm::tlm_fw_transport_if<TYPES>               fw_interface_type;
6012027Sjungma@eit.uni-kl.de  typedef tlm::tlm_bw_transport_if<TYPES>               bw_interface_type;
6112027Sjungma@eit.uni-kl.de  typedef tlm::tlm_target_socket<BUSWIDTH, TYPES>       base_type;
6212027Sjungma@eit.uni-kl.de
6312027Sjungma@eit.uni-kl.depublic:
6412027Sjungma@eit.uni-kl.de  simple_target_socket() :
6512027Sjungma@eit.uni-kl.de    base_type(sc_core::sc_gen_unique_name("simple_target_socket")),
6612027Sjungma@eit.uni-kl.de    m_fw_process(this),
6712027Sjungma@eit.uni-kl.de    m_bw_process(this)
6812027Sjungma@eit.uni-kl.de  {
6912027Sjungma@eit.uni-kl.de    bind(m_fw_process);
7012027Sjungma@eit.uni-kl.de  }
7112027Sjungma@eit.uni-kl.de
7212027Sjungma@eit.uni-kl.de  explicit simple_target_socket(const char* n) :
7312027Sjungma@eit.uni-kl.de    base_type(n),
7412027Sjungma@eit.uni-kl.de    m_fw_process(this),
7512027Sjungma@eit.uni-kl.de    m_bw_process(this)
7612027Sjungma@eit.uni-kl.de  {
7712027Sjungma@eit.uni-kl.de    bind(m_fw_process);
7812027Sjungma@eit.uni-kl.de  }
7912027Sjungma@eit.uni-kl.de
8012027Sjungma@eit.uni-kl.de  using tlm::tlm_target_socket<BUSWIDTH, TYPES>::bind;
8112027Sjungma@eit.uni-kl.de
8212027Sjungma@eit.uni-kl.de  // bw transport must come thru us.
8312027Sjungma@eit.uni-kl.de  tlm::tlm_bw_transport_if<TYPES> * operator ->() {return &m_bw_process;}
8412027Sjungma@eit.uni-kl.de
8512027Sjungma@eit.uni-kl.de  // REGISTER_XXX
8612027Sjungma@eit.uni-kl.de  void register_nb_transport_fw(MODULE* mod,
8712027Sjungma@eit.uni-kl.de                                sync_enum_type (MODULE::*cb)(transaction_type&,
8812027Sjungma@eit.uni-kl.de                                                             phase_type&,
8912027Sjungma@eit.uni-kl.de                                                             sc_core::sc_time&))
9012027Sjungma@eit.uni-kl.de  {
9112027Sjungma@eit.uni-kl.de    assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
9212027Sjungma@eit.uni-kl.de    m_fw_process.set_nb_transport_ptr(mod, cb);
9312027Sjungma@eit.uni-kl.de  }
9412027Sjungma@eit.uni-kl.de
9512027Sjungma@eit.uni-kl.de  void register_b_transport(MODULE* mod,
9612027Sjungma@eit.uni-kl.de                            void (MODULE::*cb)(transaction_type&,
9712027Sjungma@eit.uni-kl.de                                               sc_core::sc_time&))
9812027Sjungma@eit.uni-kl.de  {
9912027Sjungma@eit.uni-kl.de    assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
10012027Sjungma@eit.uni-kl.de    m_fw_process.set_b_transport_ptr(mod, cb);
10112027Sjungma@eit.uni-kl.de  }
10212027Sjungma@eit.uni-kl.de
10312027Sjungma@eit.uni-kl.de  void register_transport_dbg(MODULE* mod,
10412027Sjungma@eit.uni-kl.de                              unsigned int (MODULE::*cb)(transaction_type&))
10512027Sjungma@eit.uni-kl.de  {
10612027Sjungma@eit.uni-kl.de    assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
10712027Sjungma@eit.uni-kl.de    m_fw_process.set_transport_dbg_ptr(mod, cb);
10812027Sjungma@eit.uni-kl.de  }
10912027Sjungma@eit.uni-kl.de
11012027Sjungma@eit.uni-kl.de  void register_get_direct_mem_ptr(MODULE* mod,
11112027Sjungma@eit.uni-kl.de                                   bool (MODULE::*cb)(transaction_type&,
11212027Sjungma@eit.uni-kl.de                                                      tlm::tlm_dmi&))
11312027Sjungma@eit.uni-kl.de  {
11412027Sjungma@eit.uni-kl.de    assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
11512027Sjungma@eit.uni-kl.de    m_fw_process.set_get_direct_mem_ptr(mod, cb);
11612027Sjungma@eit.uni-kl.de  }
11712027Sjungma@eit.uni-kl.de
11812027Sjungma@eit.uni-kl.deprivate:
11912027Sjungma@eit.uni-kl.de  //make call on bw path.
12012027Sjungma@eit.uni-kl.de  sync_enum_type bw_nb_transport(transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
12112027Sjungma@eit.uni-kl.de  {
12212027Sjungma@eit.uni-kl.de    return base_type::operator ->()->nb_transport_bw(trans, phase, t);
12312027Sjungma@eit.uni-kl.de  }
12412027Sjungma@eit.uni-kl.de
12512027Sjungma@eit.uni-kl.de  void bw_invalidate_direct_mem_ptr(sc_dt::uint64 s,sc_dt::uint64 e)
12612027Sjungma@eit.uni-kl.de  {
12712027Sjungma@eit.uni-kl.de    base_type::operator ->()->invalidate_direct_mem_ptr(s, e);
12812027Sjungma@eit.uni-kl.de  }
12912027Sjungma@eit.uni-kl.de
13012027Sjungma@eit.uni-kl.de  //Helper class to handle bw path calls
13112027Sjungma@eit.uni-kl.de  // Needed to detect transaction end when called from b_transport.
13212027Sjungma@eit.uni-kl.de  class bw_process : public tlm::tlm_bw_transport_if<TYPES>
13312027Sjungma@eit.uni-kl.de  {
13412027Sjungma@eit.uni-kl.de  public:
13512027Sjungma@eit.uni-kl.de    bw_process(simple_target_socket *p_own) : m_owner(p_own)
13612027Sjungma@eit.uni-kl.de    {
13712027Sjungma@eit.uni-kl.de    }
13812027Sjungma@eit.uni-kl.de
13912027Sjungma@eit.uni-kl.de    sync_enum_type nb_transport_bw(transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
14012027Sjungma@eit.uni-kl.de    {
14112027Sjungma@eit.uni-kl.de      typename std::map<transaction_type*, sc_core::sc_event *>::iterator it;
14212027Sjungma@eit.uni-kl.de
14312027Sjungma@eit.uni-kl.de      it = m_owner->m_pending_trans.find(&trans);
14412027Sjungma@eit.uni-kl.de      if(it == m_owner->m_pending_trans.end()) {
14512027Sjungma@eit.uni-kl.de        // Not a blocking call, forward.
14612027Sjungma@eit.uni-kl.de        return m_owner->bw_nb_transport(trans, phase, t);
14712027Sjungma@eit.uni-kl.de
14812027Sjungma@eit.uni-kl.de      } else {
14912027Sjungma@eit.uni-kl.de        if (phase == tlm::END_REQ) {
15012027Sjungma@eit.uni-kl.de          m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME);
15112027Sjungma@eit.uni-kl.de          return tlm::TLM_ACCEPTED;
15212027Sjungma@eit.uni-kl.de
15312027Sjungma@eit.uni-kl.de        } else if (phase == tlm::BEGIN_RESP) {
15412027Sjungma@eit.uni-kl.de          if (m_owner->m_current_transaction == &trans) {
15512027Sjungma@eit.uni-kl.de            m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME);
15612027Sjungma@eit.uni-kl.de          }
15712027Sjungma@eit.uni-kl.de          //TODO: add response-accept delay?
15812027Sjungma@eit.uni-kl.de          it->second->notify(t);
15912027Sjungma@eit.uni-kl.de          m_owner->m_pending_trans.erase(it);
16012027Sjungma@eit.uni-kl.de          return tlm::TLM_COMPLETED;
16112027Sjungma@eit.uni-kl.de
16212027Sjungma@eit.uni-kl.de        } else {
16312027Sjungma@eit.uni-kl.de          assert(0); exit(1);
16412027Sjungma@eit.uni-kl.de        }
16512027Sjungma@eit.uni-kl.de
16612027Sjungma@eit.uni-kl.de//        return tlm::TLM_COMPLETED;  //Should not reach here
16712027Sjungma@eit.uni-kl.de      }
16812027Sjungma@eit.uni-kl.de    }
16912027Sjungma@eit.uni-kl.de
17012027Sjungma@eit.uni-kl.de    void invalidate_direct_mem_ptr(sc_dt::uint64 s,sc_dt::uint64 e)
17112027Sjungma@eit.uni-kl.de    {
17212027Sjungma@eit.uni-kl.de      return m_owner->bw_invalidate_direct_mem_ptr(s, e);
17312027Sjungma@eit.uni-kl.de    }
17412027Sjungma@eit.uni-kl.de
17512027Sjungma@eit.uni-kl.de  private:
17612027Sjungma@eit.uni-kl.de    simple_target_socket *m_owner;
17712027Sjungma@eit.uni-kl.de  };
17812027Sjungma@eit.uni-kl.de
17912027Sjungma@eit.uni-kl.de  class fw_process : public tlm::tlm_fw_transport_if<TYPES>,
18012027Sjungma@eit.uni-kl.de                    public tlm::tlm_mm_interface
18112027Sjungma@eit.uni-kl.de  {
18212027Sjungma@eit.uni-kl.de  public:
18312027Sjungma@eit.uni-kl.de    typedef sync_enum_type (MODULE::*NBTransportPtr)(transaction_type&,
18412027Sjungma@eit.uni-kl.de                                                     phase_type&,
18512027Sjungma@eit.uni-kl.de                                                     sc_core::sc_time&);
18612027Sjungma@eit.uni-kl.de    typedef void (MODULE::*BTransportPtr)(transaction_type&,
18712027Sjungma@eit.uni-kl.de                                          sc_core::sc_time&);
18812027Sjungma@eit.uni-kl.de    typedef unsigned int (MODULE::*TransportDbgPtr)(transaction_type&);
18912027Sjungma@eit.uni-kl.de    typedef bool (MODULE::*GetDirectMemPtr)(transaction_type&,
19012027Sjungma@eit.uni-kl.de                                            tlm::tlm_dmi&);
19112027Sjungma@eit.uni-kl.de
19212027Sjungma@eit.uni-kl.de    fw_process(simple_target_socket *p_own) :
19312027Sjungma@eit.uni-kl.de      m_name(p_own->name()),
19412027Sjungma@eit.uni-kl.de      m_owner(p_own),
19512027Sjungma@eit.uni-kl.de      m_mod(0),
19612027Sjungma@eit.uni-kl.de      m_nb_transport_ptr(0),
19712027Sjungma@eit.uni-kl.de      m_b_transport_ptr(0),
19812027Sjungma@eit.uni-kl.de      m_transport_dbg_ptr(0),
19912027Sjungma@eit.uni-kl.de      m_get_direct_mem_ptr(0),
20012027Sjungma@eit.uni-kl.de      m_peq(sc_core::sc_gen_unique_name("m_peq")),
20112027Sjungma@eit.uni-kl.de      m_response_in_progress(false)
20212027Sjungma@eit.uni-kl.de    {
20312027Sjungma@eit.uni-kl.de      sc_core::sc_spawn_options opts;
20412027Sjungma@eit.uni-kl.de      opts.set_sensitivity(&m_peq.get_event());
20512027Sjungma@eit.uni-kl.de      sc_core::sc_spawn(sc_bind(&fw_process::b2nb_thread, this),
20612027Sjungma@eit.uni-kl.de                        sc_core::sc_gen_unique_name("b2nb_thread"), &opts);
20712027Sjungma@eit.uni-kl.de    }
20812027Sjungma@eit.uni-kl.de
20912027Sjungma@eit.uni-kl.de    void set_nb_transport_ptr(MODULE* mod, NBTransportPtr p)
21012027Sjungma@eit.uni-kl.de    {
21112027Sjungma@eit.uni-kl.de      if (m_nb_transport_ptr) {
21212027Sjungma@eit.uni-kl.de        std::stringstream s;
21312027Sjungma@eit.uni-kl.de        s << m_name << ": non-blocking callback allready registered";
21412027Sjungma@eit.uni-kl.de        SC_REPORT_WARNING("/OSCI_TLM-2/simple_socket",s.str().c_str());
21512027Sjungma@eit.uni-kl.de      } else {
21612027Sjungma@eit.uni-kl.de        assert(!m_mod || m_mod == mod);
21712027Sjungma@eit.uni-kl.de        m_mod = mod;
21812027Sjungma@eit.uni-kl.de        m_nb_transport_ptr = p;
21912027Sjungma@eit.uni-kl.de      }
22012027Sjungma@eit.uni-kl.de    }
22112027Sjungma@eit.uni-kl.de
22212027Sjungma@eit.uni-kl.de    void set_b_transport_ptr(MODULE* mod, BTransportPtr p)
22312027Sjungma@eit.uni-kl.de    {
22412027Sjungma@eit.uni-kl.de      if (m_b_transport_ptr) {
22512027Sjungma@eit.uni-kl.de        std::stringstream s;
22612027Sjungma@eit.uni-kl.de        s << m_name << ": blocking callback allready registered";
22712027Sjungma@eit.uni-kl.de        SC_REPORT_WARNING("/OSCI_TLM-2/simple_socket",s.str().c_str());
22812027Sjungma@eit.uni-kl.de      } else {
22912027Sjungma@eit.uni-kl.de        assert(!m_mod || m_mod == mod);
23012027Sjungma@eit.uni-kl.de        m_mod = mod;
23112027Sjungma@eit.uni-kl.de        m_b_transport_ptr = p;
23212027Sjungma@eit.uni-kl.de      }
23312027Sjungma@eit.uni-kl.de    }
23412027Sjungma@eit.uni-kl.de
23512027Sjungma@eit.uni-kl.de    void set_transport_dbg_ptr(MODULE* mod, TransportDbgPtr p)
23612027Sjungma@eit.uni-kl.de    {
23712027Sjungma@eit.uni-kl.de      if (m_transport_dbg_ptr) {
23812027Sjungma@eit.uni-kl.de        std::stringstream s;
23912027Sjungma@eit.uni-kl.de        s << m_name << ": debug callback allready registered";
24012027Sjungma@eit.uni-kl.de        SC_REPORT_WARNING("/OSCI_TLM-2/simple_socket",s.str().c_str());
24112027Sjungma@eit.uni-kl.de      } else {
24212027Sjungma@eit.uni-kl.de        assert(!m_mod || m_mod == mod);
24312027Sjungma@eit.uni-kl.de        m_mod = mod;
24412027Sjungma@eit.uni-kl.de        m_transport_dbg_ptr = p;
24512027Sjungma@eit.uni-kl.de      }
24612027Sjungma@eit.uni-kl.de    }
24712027Sjungma@eit.uni-kl.de
24812027Sjungma@eit.uni-kl.de    void set_get_direct_mem_ptr(MODULE* mod, GetDirectMemPtr p)
24912027Sjungma@eit.uni-kl.de    {
25012027Sjungma@eit.uni-kl.de      if (m_get_direct_mem_ptr) {
25112027Sjungma@eit.uni-kl.de        std::stringstream s;
25212027Sjungma@eit.uni-kl.de        s << m_name << ": get DMI pointer callback allready registered";
25312027Sjungma@eit.uni-kl.de        SC_REPORT_WARNING("/OSCI_TLM-2/simple_socket",s.str().c_str());
25412027Sjungma@eit.uni-kl.de      } else {
25512027Sjungma@eit.uni-kl.de        assert(!m_mod || m_mod == mod);
25612027Sjungma@eit.uni-kl.de        m_mod = mod;
25712027Sjungma@eit.uni-kl.de        m_get_direct_mem_ptr = p;
25812027Sjungma@eit.uni-kl.de      }
25912027Sjungma@eit.uni-kl.de    }
26012027Sjungma@eit.uni-kl.de// Interface implementation
26112027Sjungma@eit.uni-kl.de    sync_enum_type nb_transport_fw(transaction_type& trans,
26212027Sjungma@eit.uni-kl.de                                   phase_type& phase,
26312027Sjungma@eit.uni-kl.de                                   sc_core::sc_time& t)
26412027Sjungma@eit.uni-kl.de    {
26512027Sjungma@eit.uni-kl.de      if (m_nb_transport_ptr) {
26612027Sjungma@eit.uni-kl.de        // forward call
26712027Sjungma@eit.uni-kl.de        assert(m_mod);
26812027Sjungma@eit.uni-kl.de        return (m_mod->*m_nb_transport_ptr)(trans, phase, t);
26912027Sjungma@eit.uni-kl.de
27012027Sjungma@eit.uni-kl.de      } else if (m_b_transport_ptr) {
27112027Sjungma@eit.uni-kl.de        if (phase == tlm::BEGIN_REQ) {
27212027Sjungma@eit.uni-kl.de          // prepare thread to do blocking call
27312027Sjungma@eit.uni-kl.de          process_handle_class * ph = m_process_handle.get_handle(&trans);
27412027Sjungma@eit.uni-kl.de
27512027Sjungma@eit.uni-kl.de          if (!ph) { // create new dynamic process
27612027Sjungma@eit.uni-kl.de            ph = new process_handle_class(&trans);
27712027Sjungma@eit.uni-kl.de            m_process_handle.put_handle(ph);
27812027Sjungma@eit.uni-kl.de
27912027Sjungma@eit.uni-kl.de            sc_core::sc_spawn_options opts;
28012027Sjungma@eit.uni-kl.de            opts.dont_initialize();
28112027Sjungma@eit.uni-kl.de            opts.set_sensitivity(&ph->m_e);
28212027Sjungma@eit.uni-kl.de
28312027Sjungma@eit.uni-kl.de            sc_core::sc_spawn(sc_bind(&fw_process::nb2b_thread,this, ph),
28412027Sjungma@eit.uni-kl.de                            sc_core::sc_gen_unique_name("nb2b_thread"), &opts);
28512027Sjungma@eit.uni-kl.de          }
28612027Sjungma@eit.uni-kl.de
28712027Sjungma@eit.uni-kl.de          ph->m_e.notify(t);
28812027Sjungma@eit.uni-kl.de          return tlm::TLM_ACCEPTED;
28912027Sjungma@eit.uni-kl.de
29012027Sjungma@eit.uni-kl.de        } else if (phase == tlm::END_RESP) {
29112027Sjungma@eit.uni-kl.de          m_response_in_progress = false;
29212027Sjungma@eit.uni-kl.de          m_end_response.notify(t);
29312027Sjungma@eit.uni-kl.de          return tlm::TLM_COMPLETED;
29412027Sjungma@eit.uni-kl.de
29512027Sjungma@eit.uni-kl.de        } else {
29612027Sjungma@eit.uni-kl.de          assert(0); exit(1);
29712027Sjungma@eit.uni-kl.de//          return tlm::TLM_COMPLETED;   ///< unreachable code
29812027Sjungma@eit.uni-kl.de        }
29912027Sjungma@eit.uni-kl.de
30012027Sjungma@eit.uni-kl.de      } else {
30112027Sjungma@eit.uni-kl.de        std::stringstream s;
30212027Sjungma@eit.uni-kl.de        s << m_name << ": no non-blocking transport callback registered";
30312027Sjungma@eit.uni-kl.de        SC_REPORT_ERROR("/OSCI_TLM-2/simple_socket",s.str().c_str());
30412027Sjungma@eit.uni-kl.de      }
30512027Sjungma@eit.uni-kl.de      return tlm::TLM_ACCEPTED;   ///< unreachable code
30612027Sjungma@eit.uni-kl.de    }
30712027Sjungma@eit.uni-kl.de
30812027Sjungma@eit.uni-kl.de    void b_transport(transaction_type& trans, sc_core::sc_time& t)
30912027Sjungma@eit.uni-kl.de    {
31012027Sjungma@eit.uni-kl.de      if (m_b_transport_ptr) {
31112027Sjungma@eit.uni-kl.de        // forward call
31212027Sjungma@eit.uni-kl.de        assert(m_mod);
31312027Sjungma@eit.uni-kl.de        (m_mod->*m_b_transport_ptr)(trans, t);
31412027Sjungma@eit.uni-kl.de        return;
31512027Sjungma@eit.uni-kl.de
31612027Sjungma@eit.uni-kl.de      } else if (m_nb_transport_ptr) {
31712027Sjungma@eit.uni-kl.de        m_peq.notify(trans, t);
31812027Sjungma@eit.uni-kl.de        t = sc_core::SC_ZERO_TIME;
31912027Sjungma@eit.uni-kl.de
32012027Sjungma@eit.uni-kl.de        mm_end_event_ext mm_ext;
32112027Sjungma@eit.uni-kl.de        const bool mm_added = !trans.has_mm();
32212027Sjungma@eit.uni-kl.de
32312027Sjungma@eit.uni-kl.de        if (mm_added) {
32412027Sjungma@eit.uni-kl.de          trans.set_mm(this);
32512027Sjungma@eit.uni-kl.de          trans.set_auto_extension(&mm_ext);
32612027Sjungma@eit.uni-kl.de          trans.acquire();
32712027Sjungma@eit.uni-kl.de        }
32812027Sjungma@eit.uni-kl.de
32912027Sjungma@eit.uni-kl.de        // wait until transaction is finished
33012027Sjungma@eit.uni-kl.de        sc_core::sc_event end_event;
33112027Sjungma@eit.uni-kl.de        m_owner->m_pending_trans[&trans] = &end_event;
33212027Sjungma@eit.uni-kl.de        sc_core::wait(end_event);
33312027Sjungma@eit.uni-kl.de
33412027Sjungma@eit.uni-kl.de        if (mm_added) {
33512027Sjungma@eit.uni-kl.de          // release will not delete the transaction, it will notify mm_ext.done
33612027Sjungma@eit.uni-kl.de          trans.release();
33712027Sjungma@eit.uni-kl.de          if (trans.get_ref_count()) {
33812027Sjungma@eit.uni-kl.de            sc_core::wait(mm_ext.done);
33912027Sjungma@eit.uni-kl.de          }
34012027Sjungma@eit.uni-kl.de          trans.set_mm(0);
34112027Sjungma@eit.uni-kl.de        }
34212027Sjungma@eit.uni-kl.de
34312027Sjungma@eit.uni-kl.de      } else {
34412027Sjungma@eit.uni-kl.de        std::stringstream s;
34512027Sjungma@eit.uni-kl.de        s << m_name << ": no blocking transport callback registered";
34612027Sjungma@eit.uni-kl.de        SC_REPORT_ERROR("/OSCI_TLM-2/simple_socket",s.str().c_str());
34712027Sjungma@eit.uni-kl.de      }
34812027Sjungma@eit.uni-kl.de    }
34912027Sjungma@eit.uni-kl.de
35012027Sjungma@eit.uni-kl.de    unsigned int transport_dbg(transaction_type& trans)
35112027Sjungma@eit.uni-kl.de    {
35212027Sjungma@eit.uni-kl.de      if (m_transport_dbg_ptr) {
35312027Sjungma@eit.uni-kl.de        // forward call
35412027Sjungma@eit.uni-kl.de        assert(m_mod);
35512027Sjungma@eit.uni-kl.de        return (m_mod->*m_transport_dbg_ptr)(trans);
35612027Sjungma@eit.uni-kl.de
35712027Sjungma@eit.uni-kl.de      } else {
35812027Sjungma@eit.uni-kl.de        // No debug support
35912027Sjungma@eit.uni-kl.de        return 0;
36012027Sjungma@eit.uni-kl.de      }
36112027Sjungma@eit.uni-kl.de    }
36212027Sjungma@eit.uni-kl.de
36312027Sjungma@eit.uni-kl.de    bool get_direct_mem_ptr(transaction_type& trans,
36412027Sjungma@eit.uni-kl.de                            tlm::tlm_dmi&  dmi_data)
36512027Sjungma@eit.uni-kl.de    {
36612027Sjungma@eit.uni-kl.de      if (m_get_direct_mem_ptr) {
36712027Sjungma@eit.uni-kl.de        // forward call
36812027Sjungma@eit.uni-kl.de        assert(m_mod);
36912027Sjungma@eit.uni-kl.de        return (m_mod->*m_get_direct_mem_ptr)(trans, dmi_data);
37012027Sjungma@eit.uni-kl.de
37112027Sjungma@eit.uni-kl.de      } else {
37212027Sjungma@eit.uni-kl.de        // No DMI support
37312027Sjungma@eit.uni-kl.de        dmi_data.allow_read_write();
37412027Sjungma@eit.uni-kl.de        dmi_data.set_start_address(0x0);
37512027Sjungma@eit.uni-kl.de        dmi_data.set_end_address((sc_dt::uint64)-1);
37612027Sjungma@eit.uni-kl.de        return false;
37712027Sjungma@eit.uni-kl.de      }
37812027Sjungma@eit.uni-kl.de    }
37912027Sjungma@eit.uni-kl.de
38012027Sjungma@eit.uni-kl.de  private:
38112027Sjungma@eit.uni-kl.de
38212027Sjungma@eit.uni-kl.de// dynamic process handler for nb2b conversion
38312027Sjungma@eit.uni-kl.de
38412027Sjungma@eit.uni-kl.de    class process_handle_class {
38512027Sjungma@eit.uni-kl.de    public:
38612027Sjungma@eit.uni-kl.de      explicit process_handle_class(transaction_type * trans)
38712027Sjungma@eit.uni-kl.de        : m_trans(trans),m_suspend(false) {}
38812027Sjungma@eit.uni-kl.de
38912027Sjungma@eit.uni-kl.de      transaction_type*  m_trans;
39012027Sjungma@eit.uni-kl.de      sc_core::sc_event  m_e;
39112027Sjungma@eit.uni-kl.de      bool m_suspend;
39212027Sjungma@eit.uni-kl.de    };
39312027Sjungma@eit.uni-kl.de
39412027Sjungma@eit.uni-kl.de    class process_handle_list {
39512027Sjungma@eit.uni-kl.de    public:
39612027Sjungma@eit.uni-kl.de      process_handle_list() {}
39712027Sjungma@eit.uni-kl.de
39812027Sjungma@eit.uni-kl.de      ~process_handle_list() {
39912027Sjungma@eit.uni-kl.de        for( typename std::vector<process_handle_class*>::iterator
40012027Sjungma@eit.uni-kl.de               it=v.begin(), end = v.end(); it != end; ++it )
40112027Sjungma@eit.uni-kl.de          delete *it;
40212027Sjungma@eit.uni-kl.de      }
40312027Sjungma@eit.uni-kl.de
40412027Sjungma@eit.uni-kl.de      process_handle_class* get_handle(transaction_type *trans)
40512027Sjungma@eit.uni-kl.de      {
40612027Sjungma@eit.uni-kl.de        typename std::vector<process_handle_class*>::iterator it;
40712027Sjungma@eit.uni-kl.de
40812027Sjungma@eit.uni-kl.de        for(it = v.begin(); it != v.end(); it++) {
40912027Sjungma@eit.uni-kl.de          if ((*it)->m_suspend) {  // found suspended dynamic process, re-use it
41012027Sjungma@eit.uni-kl.de            (*it)->m_trans   = trans; // replace to new one
41112027Sjungma@eit.uni-kl.de            (*it)->m_suspend = false;
41212027Sjungma@eit.uni-kl.de            return *it;
41312027Sjungma@eit.uni-kl.de          }
41412027Sjungma@eit.uni-kl.de        }
41512027Sjungma@eit.uni-kl.de        return NULL; // no suspended process
41612027Sjungma@eit.uni-kl.de      }
41712027Sjungma@eit.uni-kl.de
41812027Sjungma@eit.uni-kl.de      void put_handle(process_handle_class* ph)
41912027Sjungma@eit.uni-kl.de      {
42012027Sjungma@eit.uni-kl.de        v.push_back(ph);
42112027Sjungma@eit.uni-kl.de      }
42212027Sjungma@eit.uni-kl.de
42312027Sjungma@eit.uni-kl.de    private:
42412027Sjungma@eit.uni-kl.de      std::vector<process_handle_class*> v;
42512027Sjungma@eit.uni-kl.de    };
42612027Sjungma@eit.uni-kl.de
42712027Sjungma@eit.uni-kl.de    process_handle_list m_process_handle;
42812027Sjungma@eit.uni-kl.de
42912027Sjungma@eit.uni-kl.de
43012027Sjungma@eit.uni-kl.de    void nb2b_thread(process_handle_class* h)
43112027Sjungma@eit.uni-kl.de    {
43212027Sjungma@eit.uni-kl.de
43312027Sjungma@eit.uni-kl.de      while(1) {
43412027Sjungma@eit.uni-kl.de        transaction_type *trans = h->m_trans;
43512027Sjungma@eit.uni-kl.de        sc_core::sc_time t = sc_core::SC_ZERO_TIME;
43612027Sjungma@eit.uni-kl.de
43712027Sjungma@eit.uni-kl.de        // forward call
43812027Sjungma@eit.uni-kl.de        assert(m_mod);
43912027Sjungma@eit.uni-kl.de        (m_mod->*m_b_transport_ptr)(*trans, t);
44012027Sjungma@eit.uni-kl.de
44112027Sjungma@eit.uni-kl.de        sc_core::wait(t);
44212027Sjungma@eit.uni-kl.de
44312027Sjungma@eit.uni-kl.de        // return path
44412027Sjungma@eit.uni-kl.de        while (m_response_in_progress) {
44512027Sjungma@eit.uni-kl.de          sc_core::wait(m_end_response);
44612027Sjungma@eit.uni-kl.de        }
44712027Sjungma@eit.uni-kl.de        t = sc_core::SC_ZERO_TIME;
44812027Sjungma@eit.uni-kl.de        phase_type phase    = tlm::BEGIN_RESP;
44912027Sjungma@eit.uni-kl.de        sync_enum_type sync = m_owner->bw_nb_transport(*trans, phase, t);
45012027Sjungma@eit.uni-kl.de        if ( !(sync == tlm::TLM_COMPLETED ||
45112027Sjungma@eit.uni-kl.de              (sync == tlm::TLM_UPDATED && phase == tlm::END_RESP)) ) {
45212027Sjungma@eit.uni-kl.de          m_response_in_progress = true;
45312027Sjungma@eit.uni-kl.de        }
45412027Sjungma@eit.uni-kl.de
45512027Sjungma@eit.uni-kl.de        // suspend until next transaction
45612027Sjungma@eit.uni-kl.de        h->m_suspend = true;
45712027Sjungma@eit.uni-kl.de        sc_core::wait();
45812027Sjungma@eit.uni-kl.de      }
45912027Sjungma@eit.uni-kl.de    }
46012027Sjungma@eit.uni-kl.de
46112027Sjungma@eit.uni-kl.de    void b2nb_thread()
46212027Sjungma@eit.uni-kl.de    {
46312027Sjungma@eit.uni-kl.de      while (true) {
46412027Sjungma@eit.uni-kl.de        sc_core::wait(m_peq.get_event());
46512027Sjungma@eit.uni-kl.de
46612027Sjungma@eit.uni-kl.de        transaction_type* trans;
46712027Sjungma@eit.uni-kl.de        while ((trans = m_peq.get_next_transaction())!=0) {
46812027Sjungma@eit.uni-kl.de          assert(m_mod);
46912027Sjungma@eit.uni-kl.de          assert(m_nb_transport_ptr);
47012027Sjungma@eit.uni-kl.de          phase_type phase = tlm::BEGIN_REQ;
47112027Sjungma@eit.uni-kl.de          sc_core::sc_time t = sc_core::SC_ZERO_TIME;
47212027Sjungma@eit.uni-kl.de
47312027Sjungma@eit.uni-kl.de          switch ((m_mod->*m_nb_transport_ptr)(*trans, phase, t)) {
47412027Sjungma@eit.uni-kl.de          case tlm::TLM_COMPLETED:
47512027Sjungma@eit.uni-kl.de          {
47612027Sjungma@eit.uni-kl.de            // notify transaction is finished
47712027Sjungma@eit.uni-kl.de            typename std::map<transaction_type*, sc_core::sc_event *>::iterator it =
47812027Sjungma@eit.uni-kl.de              m_owner->m_pending_trans.find(trans);
47912027Sjungma@eit.uni-kl.de            assert(it != m_owner->m_pending_trans.end());
48012027Sjungma@eit.uni-kl.de            it->second->notify(t);
48112027Sjungma@eit.uni-kl.de            m_owner->m_pending_trans.erase(it);
48212027Sjungma@eit.uni-kl.de            break;
48312027Sjungma@eit.uni-kl.de          }
48412027Sjungma@eit.uni-kl.de
48512027Sjungma@eit.uni-kl.de          case tlm::TLM_ACCEPTED:
48612027Sjungma@eit.uni-kl.de          case tlm::TLM_UPDATED:
48712027Sjungma@eit.uni-kl.de            switch (phase) {
48812027Sjungma@eit.uni-kl.de            case tlm::BEGIN_REQ:
48912027Sjungma@eit.uni-kl.de              m_owner->m_current_transaction = trans;
49012027Sjungma@eit.uni-kl.de              sc_core::wait(m_owner->m_end_request);
49112027Sjungma@eit.uni-kl.de              m_owner->m_current_transaction = 0;
49212027Sjungma@eit.uni-kl.de              break;
49312027Sjungma@eit.uni-kl.de
49412027Sjungma@eit.uni-kl.de            case tlm::END_REQ:
49512027Sjungma@eit.uni-kl.de              sc_core::wait(t);
49612027Sjungma@eit.uni-kl.de              break;
49712027Sjungma@eit.uni-kl.de
49812027Sjungma@eit.uni-kl.de            case tlm::BEGIN_RESP:
49912027Sjungma@eit.uni-kl.de            {
50012027Sjungma@eit.uni-kl.de              phase = tlm::END_RESP;
50112027Sjungma@eit.uni-kl.de              sc_core::wait(t);  // This line is a bug fix added in TLM-2.0.2
50212027Sjungma@eit.uni-kl.de              t = sc_core::SC_ZERO_TIME;
50312027Sjungma@eit.uni-kl.de              (m_mod->*m_nb_transport_ptr)(*trans, phase, t);
50412027Sjungma@eit.uni-kl.de
50512027Sjungma@eit.uni-kl.de              // notify transaction is finished
50612027Sjungma@eit.uni-kl.de              typename std::map<transaction_type*, sc_core::sc_event *>::iterator it =
50712027Sjungma@eit.uni-kl.de                m_owner->m_pending_trans.find(trans);
50812027Sjungma@eit.uni-kl.de              assert(it != m_owner->m_pending_trans.end());
50912027Sjungma@eit.uni-kl.de              it->second->notify(t);
51012027Sjungma@eit.uni-kl.de              m_owner->m_pending_trans.erase(it);
51112027Sjungma@eit.uni-kl.de              break;
51212027Sjungma@eit.uni-kl.de            }
51312027Sjungma@eit.uni-kl.de
51412027Sjungma@eit.uni-kl.de            default:
51512027Sjungma@eit.uni-kl.de              assert(0); exit(1);
51612027Sjungma@eit.uni-kl.de            };
51712027Sjungma@eit.uni-kl.de            break;
51812027Sjungma@eit.uni-kl.de
51912027Sjungma@eit.uni-kl.de          default:
52012027Sjungma@eit.uni-kl.de            assert(0); exit(1);
52112027Sjungma@eit.uni-kl.de          };
52212027Sjungma@eit.uni-kl.de        }
52312027Sjungma@eit.uni-kl.de      }
52412027Sjungma@eit.uni-kl.de    }
52512027Sjungma@eit.uni-kl.de
52612027Sjungma@eit.uni-kl.de    void free(tlm::tlm_generic_payload* trans)
52712027Sjungma@eit.uni-kl.de    {
52812027Sjungma@eit.uni-kl.de      mm_end_event_ext* ext = trans->template get_extension<mm_end_event_ext>();
52912027Sjungma@eit.uni-kl.de      assert(ext);
53012027Sjungma@eit.uni-kl.de      // notif event first before freeing extensions (reset)
53112027Sjungma@eit.uni-kl.de      ext->done.notify();
53212027Sjungma@eit.uni-kl.de      trans->reset();
53312027Sjungma@eit.uni-kl.de    }
53412027Sjungma@eit.uni-kl.de
53512027Sjungma@eit.uni-kl.de  private:
53612027Sjungma@eit.uni-kl.de    struct mm_end_event_ext : public tlm::tlm_extension<mm_end_event_ext>
53712027Sjungma@eit.uni-kl.de    {
53812027Sjungma@eit.uni-kl.de      tlm::tlm_extension_base* clone() const { return NULL; }
53912027Sjungma@eit.uni-kl.de      void free() {}
54012027Sjungma@eit.uni-kl.de      void copy_from(tlm::tlm_extension_base const &) {}
54112027Sjungma@eit.uni-kl.de      sc_core::sc_event done;
54212027Sjungma@eit.uni-kl.de    };
54312027Sjungma@eit.uni-kl.de
54412027Sjungma@eit.uni-kl.de  private:
54512027Sjungma@eit.uni-kl.de    const std::string m_name;
54612027Sjungma@eit.uni-kl.de    simple_target_socket *m_owner;
54712027Sjungma@eit.uni-kl.de    MODULE* m_mod;
54812027Sjungma@eit.uni-kl.de    NBTransportPtr m_nb_transport_ptr;
54912027Sjungma@eit.uni-kl.de    BTransportPtr m_b_transport_ptr;
55012027Sjungma@eit.uni-kl.de    TransportDbgPtr m_transport_dbg_ptr;
55112027Sjungma@eit.uni-kl.de    GetDirectMemPtr m_get_direct_mem_ptr;
55212027Sjungma@eit.uni-kl.de    peq_with_get<transaction_type> m_peq;
55312027Sjungma@eit.uni-kl.de    bool m_response_in_progress;
55412027Sjungma@eit.uni-kl.de    sc_core::sc_event m_end_response;
55512027Sjungma@eit.uni-kl.de  };
55612027Sjungma@eit.uni-kl.de
55712027Sjungma@eit.uni-kl.deprivate:
55812027Sjungma@eit.uni-kl.de  fw_process m_fw_process;
55912027Sjungma@eit.uni-kl.de  bw_process m_bw_process;
56012027Sjungma@eit.uni-kl.de  std::map<transaction_type*, sc_core::sc_event *> m_pending_trans;
56112027Sjungma@eit.uni-kl.de  sc_core::sc_event m_end_request;
56212027Sjungma@eit.uni-kl.de  transaction_type* m_current_transaction;
56312027Sjungma@eit.uni-kl.de};
56412027Sjungma@eit.uni-kl.de
56512027Sjungma@eit.uni-kl.de//ID Tagged version
56612027Sjungma@eit.uni-kl.detemplate <typename MODULE,
56712027Sjungma@eit.uni-kl.de          unsigned int BUSWIDTH = 32,
56812027Sjungma@eit.uni-kl.de          typename TYPES = tlm::tlm_base_protocol_types>
56912027Sjungma@eit.uni-kl.declass simple_target_socket_tagged :
57012027Sjungma@eit.uni-kl.de  public tlm::tlm_target_socket<BUSWIDTH, TYPES>
57112027Sjungma@eit.uni-kl.de{
57212027Sjungma@eit.uni-kl.de  friend class fw_process;
57312027Sjungma@eit.uni-kl.de  friend class bw_process;
57412027Sjungma@eit.uni-kl.depublic:
57512027Sjungma@eit.uni-kl.de  typedef typename TYPES::tlm_payload_type              transaction_type;
57612027Sjungma@eit.uni-kl.de  typedef typename TYPES::tlm_phase_type                phase_type;
57712027Sjungma@eit.uni-kl.de  typedef tlm::tlm_sync_enum                            sync_enum_type;
57812027Sjungma@eit.uni-kl.de  typedef tlm::tlm_fw_transport_if<TYPES>               fw_interface_type;
57912027Sjungma@eit.uni-kl.de  typedef tlm::tlm_bw_transport_if<TYPES>               bw_interface_type;
58012027Sjungma@eit.uni-kl.de  typedef tlm::tlm_target_socket<BUSWIDTH, TYPES>       base_type;
58112027Sjungma@eit.uni-kl.de
58212027Sjungma@eit.uni-kl.depublic:
58312027Sjungma@eit.uni-kl.de  simple_target_socket_tagged() :
58412027Sjungma@eit.uni-kl.de    base_type(sc_core::sc_gen_unique_name("simple_target_socket_tagged")),
58512027Sjungma@eit.uni-kl.de    m_fw_process(this),
58612027Sjungma@eit.uni-kl.de    m_bw_process(this)
58712027Sjungma@eit.uni-kl.de  {
58812027Sjungma@eit.uni-kl.de    bind(m_fw_process);
58912027Sjungma@eit.uni-kl.de  }
59012027Sjungma@eit.uni-kl.de
59112027Sjungma@eit.uni-kl.de  explicit simple_target_socket_tagged(const char* n) :
59212027Sjungma@eit.uni-kl.de    base_type(n),
59312027Sjungma@eit.uni-kl.de    m_fw_process(this),
59412027Sjungma@eit.uni-kl.de    m_bw_process(this)
59512027Sjungma@eit.uni-kl.de  {
59612027Sjungma@eit.uni-kl.de    bind(m_fw_process);
59712027Sjungma@eit.uni-kl.de  }
59812027Sjungma@eit.uni-kl.de
59912027Sjungma@eit.uni-kl.de  using tlm::tlm_target_socket<BUSWIDTH, TYPES>::bind;
60012027Sjungma@eit.uni-kl.de
60112027Sjungma@eit.uni-kl.de  // bw transport must come thru us.
60212027Sjungma@eit.uni-kl.de  tlm::tlm_bw_transport_if<TYPES> * operator ->() {return &m_bw_process;}
60312027Sjungma@eit.uni-kl.de
60412027Sjungma@eit.uni-kl.de  // REGISTER_XXX
60512027Sjungma@eit.uni-kl.de  void register_nb_transport_fw(MODULE* mod,
60612027Sjungma@eit.uni-kl.de                                sync_enum_type (MODULE::*cb)(int id,
60712027Sjungma@eit.uni-kl.de                                                             transaction_type&,
60812027Sjungma@eit.uni-kl.de                                                             phase_type&,
60912027Sjungma@eit.uni-kl.de                                                             sc_core::sc_time&),
61012027Sjungma@eit.uni-kl.de                                int id)
61112027Sjungma@eit.uni-kl.de  {
61212027Sjungma@eit.uni-kl.de    assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
61312027Sjungma@eit.uni-kl.de    m_fw_process.set_nb_transport_ptr(mod, cb);
61412027Sjungma@eit.uni-kl.de    m_fw_process.set_nb_transport_user_id(id);
61512027Sjungma@eit.uni-kl.de  }
61612027Sjungma@eit.uni-kl.de
61712027Sjungma@eit.uni-kl.de  void register_b_transport(MODULE* mod,
61812027Sjungma@eit.uni-kl.de                            void (MODULE::*cb)(int id,
61912027Sjungma@eit.uni-kl.de                                               transaction_type&,
62012027Sjungma@eit.uni-kl.de                                               sc_core::sc_time&),
62112027Sjungma@eit.uni-kl.de                            int id)
62212027Sjungma@eit.uni-kl.de  {
62312027Sjungma@eit.uni-kl.de    assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
62412027Sjungma@eit.uni-kl.de    m_fw_process.set_b_transport_ptr(mod, cb);
62512027Sjungma@eit.uni-kl.de    m_fw_process.set_b_transport_user_id(id);
62612027Sjungma@eit.uni-kl.de  }
62712027Sjungma@eit.uni-kl.de
62812027Sjungma@eit.uni-kl.de  void register_transport_dbg(MODULE* mod,
62912027Sjungma@eit.uni-kl.de                              unsigned int (MODULE::*cb)(int id,
63012027Sjungma@eit.uni-kl.de                                                         transaction_type&),
63112027Sjungma@eit.uni-kl.de                              int id)
63212027Sjungma@eit.uni-kl.de  {
63312027Sjungma@eit.uni-kl.de    assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
63412027Sjungma@eit.uni-kl.de    m_fw_process.set_transport_dbg_ptr(mod, cb);
63512027Sjungma@eit.uni-kl.de    m_fw_process.set_transport_dbg_user_id(id);
63612027Sjungma@eit.uni-kl.de  }
63712027Sjungma@eit.uni-kl.de
63812027Sjungma@eit.uni-kl.de  void register_get_direct_mem_ptr(MODULE* mod,
63912027Sjungma@eit.uni-kl.de                                   bool (MODULE::*cb)(int id,
64012027Sjungma@eit.uni-kl.de                                                      transaction_type&,
64112027Sjungma@eit.uni-kl.de                                                      tlm::tlm_dmi&),
64212027Sjungma@eit.uni-kl.de                                   int id)
64312027Sjungma@eit.uni-kl.de  {
64412027Sjungma@eit.uni-kl.de    assert(!sc_core::sc_get_curr_simcontext()->elaboration_done());
64512027Sjungma@eit.uni-kl.de    m_fw_process.set_get_direct_mem_ptr(mod, cb);
64612027Sjungma@eit.uni-kl.de    m_fw_process.set_get_dmi_user_id(id);
64712027Sjungma@eit.uni-kl.de  }
64812027Sjungma@eit.uni-kl.de
64912027Sjungma@eit.uni-kl.deprivate:
65012027Sjungma@eit.uni-kl.de  //make call on bw path.
65112027Sjungma@eit.uni-kl.de  sync_enum_type bw_nb_transport(transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
65212027Sjungma@eit.uni-kl.de  {
65312027Sjungma@eit.uni-kl.de    return base_type::operator ->()->nb_transport_bw(trans, phase, t);
65412027Sjungma@eit.uni-kl.de  }
65512027Sjungma@eit.uni-kl.de
65612027Sjungma@eit.uni-kl.de  void bw_invalidate_direct_mem_ptr(sc_dt::uint64 s,sc_dt::uint64 e)
65712027Sjungma@eit.uni-kl.de  {
65812027Sjungma@eit.uni-kl.de    base_type::operator ->()->invalidate_direct_mem_ptr(s, e);
65912027Sjungma@eit.uni-kl.de  }
66012027Sjungma@eit.uni-kl.de
66112027Sjungma@eit.uni-kl.de  //Helper class to handle bw path calls
66212027Sjungma@eit.uni-kl.de  // Needed to detect transaction end when called from b_transport.
66312027Sjungma@eit.uni-kl.de  class bw_process : public tlm::tlm_bw_transport_if<TYPES>
66412027Sjungma@eit.uni-kl.de  {
66512027Sjungma@eit.uni-kl.de  public:
66612027Sjungma@eit.uni-kl.de    bw_process(simple_target_socket_tagged *p_own) : m_owner(p_own)
66712027Sjungma@eit.uni-kl.de    {
66812027Sjungma@eit.uni-kl.de    }
66912027Sjungma@eit.uni-kl.de
67012027Sjungma@eit.uni-kl.de    sync_enum_type nb_transport_bw(transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
67112027Sjungma@eit.uni-kl.de    {
67212027Sjungma@eit.uni-kl.de      typename std::map<transaction_type*, sc_core::sc_event *>::iterator it;
67312027Sjungma@eit.uni-kl.de
67412027Sjungma@eit.uni-kl.de      it = m_owner->m_pending_trans.find(&trans);
67512027Sjungma@eit.uni-kl.de      if(it == m_owner->m_pending_trans.end()) {
67612027Sjungma@eit.uni-kl.de        // Not a blocking call, forward.
67712027Sjungma@eit.uni-kl.de        return m_owner->bw_nb_transport(trans, phase, t);
67812027Sjungma@eit.uni-kl.de
67912027Sjungma@eit.uni-kl.de      } else {
68012027Sjungma@eit.uni-kl.de        if (phase == tlm::END_REQ) {
68112027Sjungma@eit.uni-kl.de          m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME);
68212027Sjungma@eit.uni-kl.de          return tlm::TLM_ACCEPTED;
68312027Sjungma@eit.uni-kl.de
68412027Sjungma@eit.uni-kl.de        } else if (phase == tlm::BEGIN_RESP) {
68512027Sjungma@eit.uni-kl.de          if (m_owner->m_current_transaction == &trans) {
68612027Sjungma@eit.uni-kl.de            m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME);
68712027Sjungma@eit.uni-kl.de          }
68812027Sjungma@eit.uni-kl.de          //TODO: add response-accept delay?
68912027Sjungma@eit.uni-kl.de          it->second->notify(t);
69012027Sjungma@eit.uni-kl.de          m_owner->m_pending_trans.erase(it);
69112027Sjungma@eit.uni-kl.de          return tlm::TLM_COMPLETED;
69212027Sjungma@eit.uni-kl.de
69312027Sjungma@eit.uni-kl.de        } else {
69412027Sjungma@eit.uni-kl.de          assert(0); exit(1);
69512027Sjungma@eit.uni-kl.de        }
69612027Sjungma@eit.uni-kl.de
69712027Sjungma@eit.uni-kl.de//        return tlm::TLM_COMPLETED;  //Should not reach here
69812027Sjungma@eit.uni-kl.de      }
69912027Sjungma@eit.uni-kl.de    }
70012027Sjungma@eit.uni-kl.de
70112027Sjungma@eit.uni-kl.de    void invalidate_direct_mem_ptr(sc_dt::uint64 s,sc_dt::uint64 e)
70212027Sjungma@eit.uni-kl.de    {
70312027Sjungma@eit.uni-kl.de      return m_owner->bw_invalidate_direct_mem_ptr(s, e);
70412027Sjungma@eit.uni-kl.de    }
70512027Sjungma@eit.uni-kl.de
70612027Sjungma@eit.uni-kl.de  private:
70712027Sjungma@eit.uni-kl.de    simple_target_socket_tagged *m_owner;
70812027Sjungma@eit.uni-kl.de  };
70912027Sjungma@eit.uni-kl.de
71012027Sjungma@eit.uni-kl.de  class fw_process : public tlm::tlm_fw_transport_if<TYPES>,
71112027Sjungma@eit.uni-kl.de                     public tlm::tlm_mm_interface
71212027Sjungma@eit.uni-kl.de  {
71312027Sjungma@eit.uni-kl.de  public:
71412027Sjungma@eit.uni-kl.de    typedef sync_enum_type (MODULE::*NBTransportPtr)(int id,
71512027Sjungma@eit.uni-kl.de                                                     transaction_type&,
71612027Sjungma@eit.uni-kl.de                                                     phase_type&,
71712027Sjungma@eit.uni-kl.de                                                     sc_core::sc_time&);
71812027Sjungma@eit.uni-kl.de    typedef void (MODULE::*BTransportPtr)(int id,
71912027Sjungma@eit.uni-kl.de                                          transaction_type&,
72012027Sjungma@eit.uni-kl.de                                          sc_core::sc_time&);
72112027Sjungma@eit.uni-kl.de    typedef unsigned int (MODULE::*TransportDbgPtr)(int id,
72212027Sjungma@eit.uni-kl.de                                                    transaction_type&);
72312027Sjungma@eit.uni-kl.de    typedef bool (MODULE::*GetDirectMemPtr)(int id,
72412027Sjungma@eit.uni-kl.de                                            transaction_type&,
72512027Sjungma@eit.uni-kl.de                                            tlm::tlm_dmi&);
72612027Sjungma@eit.uni-kl.de
72712027Sjungma@eit.uni-kl.de    fw_process(simple_target_socket_tagged *p_own) :
72812027Sjungma@eit.uni-kl.de      m_name(p_own->name()),
72912027Sjungma@eit.uni-kl.de      m_owner(p_own),
73012027Sjungma@eit.uni-kl.de      m_mod(0),
73112027Sjungma@eit.uni-kl.de      m_nb_transport_ptr(0),
73212027Sjungma@eit.uni-kl.de      m_b_transport_ptr(0),
73312027Sjungma@eit.uni-kl.de      m_transport_dbg_ptr(0),
73412027Sjungma@eit.uni-kl.de      m_get_direct_mem_ptr(0),
73512027Sjungma@eit.uni-kl.de      m_nb_transport_user_id(0),
73612027Sjungma@eit.uni-kl.de      m_b_transport_user_id(0),
73712027Sjungma@eit.uni-kl.de      m_transport_dbg_user_id(0),
73812027Sjungma@eit.uni-kl.de      m_get_dmi_user_id(0),
73912027Sjungma@eit.uni-kl.de      m_peq(sc_core::sc_gen_unique_name("m_peq")),
74012027Sjungma@eit.uni-kl.de      m_response_in_progress(false)
74112027Sjungma@eit.uni-kl.de    {
74212027Sjungma@eit.uni-kl.de      sc_core::sc_spawn_options opts;
74312027Sjungma@eit.uni-kl.de      opts.set_sensitivity(&m_peq.get_event());
74412027Sjungma@eit.uni-kl.de      sc_core::sc_spawn(sc_bind(&fw_process::b2nb_thread, this),
74512027Sjungma@eit.uni-kl.de                        sc_core::sc_gen_unique_name("b2nb_thread"), &opts);
74612027Sjungma@eit.uni-kl.de    }
74712027Sjungma@eit.uni-kl.de
74812027Sjungma@eit.uni-kl.de    void set_nb_transport_user_id(int id) { m_nb_transport_user_id = id; }
74912027Sjungma@eit.uni-kl.de    void set_b_transport_user_id(int id) { m_b_transport_user_id = id; }
75012027Sjungma@eit.uni-kl.de    void set_transport_dbg_user_id(int id) { m_transport_dbg_user_id = id; }
75112027Sjungma@eit.uni-kl.de    void set_get_dmi_user_id(int id) { m_get_dmi_user_id = id; }
75212027Sjungma@eit.uni-kl.de
75312027Sjungma@eit.uni-kl.de    void set_nb_transport_ptr(MODULE* mod, NBTransportPtr p)
75412027Sjungma@eit.uni-kl.de    {
75512027Sjungma@eit.uni-kl.de      if (m_nb_transport_ptr) {
75612027Sjungma@eit.uni-kl.de        std::stringstream s;
75712027Sjungma@eit.uni-kl.de        s << m_name << ": non-blocking callback allready registered";
75812027Sjungma@eit.uni-kl.de        SC_REPORT_WARNING("/OSCI_TLM-2/simple_socket",s.str().c_str());
75912027Sjungma@eit.uni-kl.de      } else {
76012027Sjungma@eit.uni-kl.de        assert(!m_mod || m_mod == mod);
76112027Sjungma@eit.uni-kl.de        m_mod = mod;
76212027Sjungma@eit.uni-kl.de        m_nb_transport_ptr = p;
76312027Sjungma@eit.uni-kl.de      }
76412027Sjungma@eit.uni-kl.de    }
76512027Sjungma@eit.uni-kl.de
76612027Sjungma@eit.uni-kl.de    void set_b_transport_ptr(MODULE* mod, BTransportPtr p)
76712027Sjungma@eit.uni-kl.de    {
76812027Sjungma@eit.uni-kl.de      if (m_b_transport_ptr) {
76912027Sjungma@eit.uni-kl.de        std::stringstream s;
77012027Sjungma@eit.uni-kl.de        s << m_name << ": blocking callback allready registered";
77112027Sjungma@eit.uni-kl.de        SC_REPORT_WARNING("/OSCI_TLM-2/simple_socket",s.str().c_str());
77212027Sjungma@eit.uni-kl.de      } else {
77312027Sjungma@eit.uni-kl.de        assert(!m_mod || m_mod == mod);
77412027Sjungma@eit.uni-kl.de        m_mod = mod;
77512027Sjungma@eit.uni-kl.de        m_b_transport_ptr = p;
77612027Sjungma@eit.uni-kl.de      }
77712027Sjungma@eit.uni-kl.de    }
77812027Sjungma@eit.uni-kl.de
77912027Sjungma@eit.uni-kl.de    void set_transport_dbg_ptr(MODULE* mod, TransportDbgPtr p)
78012027Sjungma@eit.uni-kl.de    {
78112027Sjungma@eit.uni-kl.de      if (m_transport_dbg_ptr) {
78212027Sjungma@eit.uni-kl.de        std::stringstream s;
78312027Sjungma@eit.uni-kl.de        s << m_name << ": debug callback allready registered";
78412027Sjungma@eit.uni-kl.de        SC_REPORT_WARNING("/OSCI_TLM-2/simple_socket",s.str().c_str());
78512027Sjungma@eit.uni-kl.de      } else {
78612027Sjungma@eit.uni-kl.de        assert(!m_mod || m_mod == mod);
78712027Sjungma@eit.uni-kl.de        m_mod = mod;
78812027Sjungma@eit.uni-kl.de        m_transport_dbg_ptr = p;
78912027Sjungma@eit.uni-kl.de      }
79012027Sjungma@eit.uni-kl.de    }
79112027Sjungma@eit.uni-kl.de
79212027Sjungma@eit.uni-kl.de    void set_get_direct_mem_ptr(MODULE* mod, GetDirectMemPtr p)
79312027Sjungma@eit.uni-kl.de    {
79412027Sjungma@eit.uni-kl.de      if (m_get_direct_mem_ptr) {
79512027Sjungma@eit.uni-kl.de        std::stringstream s;
79612027Sjungma@eit.uni-kl.de        s << m_name << ": get DMI pointer callback allready registered";
79712027Sjungma@eit.uni-kl.de        SC_REPORT_WARNING("/OSCI_TLM-2/simple_socket",s.str().c_str());
79812027Sjungma@eit.uni-kl.de      } else {
79912027Sjungma@eit.uni-kl.de        assert(!m_mod || m_mod == mod);
80012027Sjungma@eit.uni-kl.de        m_mod = mod;
80112027Sjungma@eit.uni-kl.de        m_get_direct_mem_ptr = p;
80212027Sjungma@eit.uni-kl.de      }
80312027Sjungma@eit.uni-kl.de    }
80412027Sjungma@eit.uni-kl.de// Interface implementation
80512027Sjungma@eit.uni-kl.de    sync_enum_type nb_transport_fw(transaction_type& trans,
80612027Sjungma@eit.uni-kl.de                                   phase_type& phase,
80712027Sjungma@eit.uni-kl.de                                   sc_core::sc_time& t)
80812027Sjungma@eit.uni-kl.de    {
80912027Sjungma@eit.uni-kl.de      if (m_nb_transport_ptr) {
81012027Sjungma@eit.uni-kl.de        // forward call
81112027Sjungma@eit.uni-kl.de        assert(m_mod);
81212027Sjungma@eit.uni-kl.de        return (m_mod->*m_nb_transport_ptr)(m_nb_transport_user_id, trans, phase, t);
81312027Sjungma@eit.uni-kl.de
81412027Sjungma@eit.uni-kl.de      } else if (m_b_transport_ptr) {
81512027Sjungma@eit.uni-kl.de        if (phase == tlm::BEGIN_REQ) {
81612027Sjungma@eit.uni-kl.de
81712027Sjungma@eit.uni-kl.de          // prepare thread to do blocking call
81812027Sjungma@eit.uni-kl.de          process_handle_class * ph = m_process_handle.get_handle(&trans);
81912027Sjungma@eit.uni-kl.de
82012027Sjungma@eit.uni-kl.de          if (!ph) { // create new dynamic process
82112027Sjungma@eit.uni-kl.de            ph = new process_handle_class(&trans);
82212027Sjungma@eit.uni-kl.de            m_process_handle.put_handle(ph);
82312027Sjungma@eit.uni-kl.de
82412027Sjungma@eit.uni-kl.de            sc_core::sc_spawn_options opts;
82512027Sjungma@eit.uni-kl.de            opts.dont_initialize();
82612027Sjungma@eit.uni-kl.de            opts.set_sensitivity(&ph->m_e);
82712027Sjungma@eit.uni-kl.de
82812027Sjungma@eit.uni-kl.de            sc_core::sc_spawn(sc_bind(&fw_process::nb2b_thread, this, ph),
82912027Sjungma@eit.uni-kl.de                            sc_core::sc_gen_unique_name("nb2b_thread"), &opts);
83012027Sjungma@eit.uni-kl.de          }
83112027Sjungma@eit.uni-kl.de
83212027Sjungma@eit.uni-kl.de          ph->m_e.notify(t);
83312027Sjungma@eit.uni-kl.de          return tlm::TLM_ACCEPTED;
83412027Sjungma@eit.uni-kl.de
83512027Sjungma@eit.uni-kl.de        } else if (phase == tlm::END_RESP) {
83612027Sjungma@eit.uni-kl.de          m_response_in_progress = false;
83712027Sjungma@eit.uni-kl.de          m_end_response.notify(t);
83812027Sjungma@eit.uni-kl.de          return tlm::TLM_COMPLETED;
83912027Sjungma@eit.uni-kl.de
84012027Sjungma@eit.uni-kl.de        } else {
84112027Sjungma@eit.uni-kl.de          assert(0); exit(1);
84212027Sjungma@eit.uni-kl.de//          return tlm::TLM_COMPLETED;   ///< unreachable code
84312027Sjungma@eit.uni-kl.de        }
84412027Sjungma@eit.uni-kl.de
84512027Sjungma@eit.uni-kl.de      } else {
84612027Sjungma@eit.uni-kl.de        std::stringstream s;
84712027Sjungma@eit.uni-kl.de        s << m_name << ": no non-blocking transport callback registered";
84812027Sjungma@eit.uni-kl.de        SC_REPORT_ERROR("/OSCI_TLM-2/simple_socket",s.str().c_str());
84912027Sjungma@eit.uni-kl.de      }
85012027Sjungma@eit.uni-kl.de      return tlm::TLM_ACCEPTED;   ///< unreachable code
85112027Sjungma@eit.uni-kl.de    }
85212027Sjungma@eit.uni-kl.de
85312027Sjungma@eit.uni-kl.de    void b_transport(transaction_type& trans, sc_core::sc_time& t)
85412027Sjungma@eit.uni-kl.de    {
85512027Sjungma@eit.uni-kl.de      if (m_b_transport_ptr) {
85612027Sjungma@eit.uni-kl.de        // forward call
85712027Sjungma@eit.uni-kl.de        assert(m_mod);
85812027Sjungma@eit.uni-kl.de        (m_mod->*m_b_transport_ptr)(m_b_transport_user_id, trans, t);
85912027Sjungma@eit.uni-kl.de        return;
86012027Sjungma@eit.uni-kl.de
86112027Sjungma@eit.uni-kl.de      } else if (m_nb_transport_ptr) {
86212027Sjungma@eit.uni-kl.de        m_peq.notify(trans, t);
86312027Sjungma@eit.uni-kl.de        t = sc_core::SC_ZERO_TIME;
86412027Sjungma@eit.uni-kl.de
86512027Sjungma@eit.uni-kl.de        mm_end_event_ext mm_ext;
86612027Sjungma@eit.uni-kl.de        const bool mm_added = !trans.has_mm();
86712027Sjungma@eit.uni-kl.de
86812027Sjungma@eit.uni-kl.de        if (mm_added){
86912027Sjungma@eit.uni-kl.de          trans.set_mm(this);
87012027Sjungma@eit.uni-kl.de          trans.set_auto_extension(&mm_ext);
87112027Sjungma@eit.uni-kl.de          trans.acquire();
87212027Sjungma@eit.uni-kl.de        }
87312027Sjungma@eit.uni-kl.de
87412027Sjungma@eit.uni-kl.de        // wait until transaction is finished
87512027Sjungma@eit.uni-kl.de        sc_core::sc_event end_event;
87612027Sjungma@eit.uni-kl.de        m_owner->m_pending_trans[&trans] = &end_event;
87712027Sjungma@eit.uni-kl.de        sc_core::wait(end_event);
87812027Sjungma@eit.uni-kl.de
87912027Sjungma@eit.uni-kl.de        if (mm_added) {
88012027Sjungma@eit.uni-kl.de          // release will not delete the transaction, it will notify mm_ext.done
88112027Sjungma@eit.uni-kl.de          trans.release();
88212027Sjungma@eit.uni-kl.de          if (trans.get_ref_count()) {
88312027Sjungma@eit.uni-kl.de            sc_core::wait(mm_ext.done);
88412027Sjungma@eit.uni-kl.de          }
88512027Sjungma@eit.uni-kl.de          trans.set_mm(0);
88612027Sjungma@eit.uni-kl.de        }
88712027Sjungma@eit.uni-kl.de
88812027Sjungma@eit.uni-kl.de      } else {
88912027Sjungma@eit.uni-kl.de        std::stringstream s;
89012027Sjungma@eit.uni-kl.de        s << m_name << ": no transport callback registered";
89112027Sjungma@eit.uni-kl.de        SC_REPORT_ERROR("/OSCI_TLM-2/simple_socket",s.str().c_str());
89212027Sjungma@eit.uni-kl.de      }
89312027Sjungma@eit.uni-kl.de    }
89412027Sjungma@eit.uni-kl.de
89512027Sjungma@eit.uni-kl.de    unsigned int transport_dbg(transaction_type& trans)
89612027Sjungma@eit.uni-kl.de    {
89712027Sjungma@eit.uni-kl.de      if (m_transport_dbg_ptr) {
89812027Sjungma@eit.uni-kl.de        // forward call
89912027Sjungma@eit.uni-kl.de        assert(m_mod);
90012027Sjungma@eit.uni-kl.de        return (m_mod->*m_transport_dbg_ptr)(m_transport_dbg_user_id, trans);
90112027Sjungma@eit.uni-kl.de
90212027Sjungma@eit.uni-kl.de      } else {
90312027Sjungma@eit.uni-kl.de        // No debug support
90412027Sjungma@eit.uni-kl.de        return 0;
90512027Sjungma@eit.uni-kl.de      }
90612027Sjungma@eit.uni-kl.de    }
90712027Sjungma@eit.uni-kl.de
90812027Sjungma@eit.uni-kl.de    bool get_direct_mem_ptr(transaction_type& trans,
90912027Sjungma@eit.uni-kl.de                            tlm::tlm_dmi&  dmi_data)
91012027Sjungma@eit.uni-kl.de    {
91112027Sjungma@eit.uni-kl.de      if (m_get_direct_mem_ptr) {
91212027Sjungma@eit.uni-kl.de        // forward call
91312027Sjungma@eit.uni-kl.de        assert(m_mod);
91412027Sjungma@eit.uni-kl.de        return (m_mod->*m_get_direct_mem_ptr)(m_get_dmi_user_id, trans, dmi_data);
91512027Sjungma@eit.uni-kl.de
91612027Sjungma@eit.uni-kl.de      } else {
91712027Sjungma@eit.uni-kl.de        // No DMI support
91812027Sjungma@eit.uni-kl.de        dmi_data.allow_read_write();
91912027Sjungma@eit.uni-kl.de        dmi_data.set_start_address(0x0);
92012027Sjungma@eit.uni-kl.de        dmi_data.set_end_address((sc_dt::uint64)-1);
92112027Sjungma@eit.uni-kl.de        return false;
92212027Sjungma@eit.uni-kl.de      }
92312027Sjungma@eit.uni-kl.de    }
92412027Sjungma@eit.uni-kl.de
92512027Sjungma@eit.uni-kl.de  private:
92612027Sjungma@eit.uni-kl.de// dynamic process handler for nb2b conversion
92712027Sjungma@eit.uni-kl.de
92812027Sjungma@eit.uni-kl.de    class process_handle_class {
92912027Sjungma@eit.uni-kl.de    public:
93012027Sjungma@eit.uni-kl.de      explicit process_handle_class(transaction_type * trans)
93112027Sjungma@eit.uni-kl.de        : m_trans(trans),m_suspend(false){}
93212027Sjungma@eit.uni-kl.de
93312027Sjungma@eit.uni-kl.de      transaction_type*  m_trans;
93412027Sjungma@eit.uni-kl.de      sc_core::sc_event  m_e;
93512027Sjungma@eit.uni-kl.de      bool m_suspend;
93612027Sjungma@eit.uni-kl.de    };
93712027Sjungma@eit.uni-kl.de
93812027Sjungma@eit.uni-kl.de    class process_handle_list {
93912027Sjungma@eit.uni-kl.de    public:
94012027Sjungma@eit.uni-kl.de      process_handle_list() {}
94112027Sjungma@eit.uni-kl.de
94212027Sjungma@eit.uni-kl.de      ~process_handle_list() {
94312027Sjungma@eit.uni-kl.de        for( typename std::vector<process_handle_class*>::iterator
94412027Sjungma@eit.uni-kl.de               it=v.begin(), end = v.end(); it != end; ++it )
94512027Sjungma@eit.uni-kl.de          delete *it;
94612027Sjungma@eit.uni-kl.de      }
94712027Sjungma@eit.uni-kl.de
94812027Sjungma@eit.uni-kl.de      process_handle_class* get_handle(transaction_type *trans)
94912027Sjungma@eit.uni-kl.de      {
95012027Sjungma@eit.uni-kl.de        typename std::vector<process_handle_class*>::iterator it;
95112027Sjungma@eit.uni-kl.de
95212027Sjungma@eit.uni-kl.de        for(it = v.begin(); it != v.end(); it++) {
95312027Sjungma@eit.uni-kl.de          if ((*it)->m_suspend) {  // found suspended dynamic process, re-use it
95412027Sjungma@eit.uni-kl.de            (*it)->m_trans   = trans; // replace to new one
95512027Sjungma@eit.uni-kl.de            (*it)->m_suspend = false;
95612027Sjungma@eit.uni-kl.de            return *it;
95712027Sjungma@eit.uni-kl.de          }
95812027Sjungma@eit.uni-kl.de        }
95912027Sjungma@eit.uni-kl.de        return NULL; // no suspended process
96012027Sjungma@eit.uni-kl.de      }
96112027Sjungma@eit.uni-kl.de
96212027Sjungma@eit.uni-kl.de      void put_handle(process_handle_class* ph)
96312027Sjungma@eit.uni-kl.de      {
96412027Sjungma@eit.uni-kl.de        v.push_back(ph);
96512027Sjungma@eit.uni-kl.de      }
96612027Sjungma@eit.uni-kl.de
96712027Sjungma@eit.uni-kl.de    private:
96812027Sjungma@eit.uni-kl.de      std::vector<process_handle_class*> v;
96912027Sjungma@eit.uni-kl.de    };
97012027Sjungma@eit.uni-kl.de
97112027Sjungma@eit.uni-kl.de    process_handle_list m_process_handle;
97212027Sjungma@eit.uni-kl.de
97312027Sjungma@eit.uni-kl.de    void nb2b_thread(process_handle_class* h)
97412027Sjungma@eit.uni-kl.de    {
97512027Sjungma@eit.uni-kl.de
97612027Sjungma@eit.uni-kl.de      while(1) {
97712027Sjungma@eit.uni-kl.de        transaction_type * trans = h->m_trans;
97812027Sjungma@eit.uni-kl.de        sc_core::sc_time t = sc_core::SC_ZERO_TIME;
97912027Sjungma@eit.uni-kl.de
98012027Sjungma@eit.uni-kl.de        // forward call
98112027Sjungma@eit.uni-kl.de        assert(m_mod);
98212027Sjungma@eit.uni-kl.de        (m_mod->*m_b_transport_ptr)(m_b_transport_user_id, *trans, t);
98312027Sjungma@eit.uni-kl.de
98412027Sjungma@eit.uni-kl.de        sc_core::wait(t);
98512027Sjungma@eit.uni-kl.de
98612027Sjungma@eit.uni-kl.de        // return path
98712027Sjungma@eit.uni-kl.de        while (m_response_in_progress) {
98812027Sjungma@eit.uni-kl.de          sc_core::wait(m_end_response);
98912027Sjungma@eit.uni-kl.de        }
99012027Sjungma@eit.uni-kl.de        t = sc_core::SC_ZERO_TIME;
99112027Sjungma@eit.uni-kl.de        phase_type phase    = tlm::BEGIN_RESP;
99212027Sjungma@eit.uni-kl.de        sync_enum_type sync = m_owner->bw_nb_transport(*trans, phase, t);
99312027Sjungma@eit.uni-kl.de        if ( !(sync == tlm::TLM_COMPLETED ||
99412027Sjungma@eit.uni-kl.de              (sync == tlm::TLM_UPDATED && phase == tlm::END_RESP)) ) {
99512027Sjungma@eit.uni-kl.de          m_response_in_progress = true;
99612027Sjungma@eit.uni-kl.de        }
99712027Sjungma@eit.uni-kl.de
99812027Sjungma@eit.uni-kl.de        // suspend until next transaction
99912027Sjungma@eit.uni-kl.de        h->m_suspend = true;
100012027Sjungma@eit.uni-kl.de        sc_core::wait();
100112027Sjungma@eit.uni-kl.de      }
100212027Sjungma@eit.uni-kl.de    }
100312027Sjungma@eit.uni-kl.de
100412027Sjungma@eit.uni-kl.de    void b2nb_thread()
100512027Sjungma@eit.uni-kl.de    {
100612027Sjungma@eit.uni-kl.de      while (true) {
100712027Sjungma@eit.uni-kl.de        sc_core::wait(m_peq.get_event());
100812027Sjungma@eit.uni-kl.de
100912027Sjungma@eit.uni-kl.de        transaction_type* trans;
101012027Sjungma@eit.uni-kl.de        while ((trans = m_peq.get_next_transaction())!=0) {
101112027Sjungma@eit.uni-kl.de          assert(m_mod);
101212027Sjungma@eit.uni-kl.de          assert(m_nb_transport_ptr);
101312027Sjungma@eit.uni-kl.de          phase_type phase = tlm::BEGIN_REQ;
101412027Sjungma@eit.uni-kl.de          sc_core::sc_time t = sc_core::SC_ZERO_TIME;
101512027Sjungma@eit.uni-kl.de
101612027Sjungma@eit.uni-kl.de          switch ((m_mod->*m_nb_transport_ptr)(m_nb_transport_user_id, *trans, phase, t)) {
101712027Sjungma@eit.uni-kl.de          case tlm::TLM_COMPLETED:
101812027Sjungma@eit.uni-kl.de          {
101912027Sjungma@eit.uni-kl.de            // notify transaction is finished
102012027Sjungma@eit.uni-kl.de            typename std::map<transaction_type*, sc_core::sc_event *>::iterator it =
102112027Sjungma@eit.uni-kl.de              m_owner->m_pending_trans.find(trans);
102212027Sjungma@eit.uni-kl.de            assert(it != m_owner->m_pending_trans.end());
102312027Sjungma@eit.uni-kl.de            it->second->notify(t);
102412027Sjungma@eit.uni-kl.de            m_owner->m_pending_trans.erase(it);
102512027Sjungma@eit.uni-kl.de            break;
102612027Sjungma@eit.uni-kl.de          }
102712027Sjungma@eit.uni-kl.de
102812027Sjungma@eit.uni-kl.de          case tlm::TLM_ACCEPTED:
102912027Sjungma@eit.uni-kl.de          case tlm::TLM_UPDATED:
103012027Sjungma@eit.uni-kl.de            switch (phase) {
103112027Sjungma@eit.uni-kl.de            case tlm::BEGIN_REQ:
103212027Sjungma@eit.uni-kl.de              m_owner->m_current_transaction = trans;
103312027Sjungma@eit.uni-kl.de              sc_core::wait(m_owner->m_end_request);
103412027Sjungma@eit.uni-kl.de              m_owner->m_current_transaction = 0;
103512027Sjungma@eit.uni-kl.de              break;
103612027Sjungma@eit.uni-kl.de
103712027Sjungma@eit.uni-kl.de            case tlm::END_REQ:
103812027Sjungma@eit.uni-kl.de              sc_core::wait(t);
103912027Sjungma@eit.uni-kl.de              break;
104012027Sjungma@eit.uni-kl.de
104112027Sjungma@eit.uni-kl.de            case tlm::BEGIN_RESP:
104212027Sjungma@eit.uni-kl.de            {
104312027Sjungma@eit.uni-kl.de              phase = tlm::END_RESP;
104412027Sjungma@eit.uni-kl.de              sc_core::wait(t);  // This line is a bug fix added in TLM-2.0.2
104512027Sjungma@eit.uni-kl.de              t = sc_core::SC_ZERO_TIME;
104612027Sjungma@eit.uni-kl.de              (m_mod->*m_nb_transport_ptr)(m_nb_transport_user_id, *trans, phase, t);
104712027Sjungma@eit.uni-kl.de
104812027Sjungma@eit.uni-kl.de              // notify transaction is finished
104912027Sjungma@eit.uni-kl.de              typename std::map<transaction_type*, sc_core::sc_event *>::iterator it =
105012027Sjungma@eit.uni-kl.de                m_owner->m_pending_trans.find(trans);
105112027Sjungma@eit.uni-kl.de              assert(it != m_owner->m_pending_trans.end());
105212027Sjungma@eit.uni-kl.de              it->second->notify(t);
105312027Sjungma@eit.uni-kl.de              m_owner->m_pending_trans.erase(it);
105412027Sjungma@eit.uni-kl.de              break;
105512027Sjungma@eit.uni-kl.de            }
105612027Sjungma@eit.uni-kl.de
105712027Sjungma@eit.uni-kl.de            default:
105812027Sjungma@eit.uni-kl.de              assert(0); exit(1);
105912027Sjungma@eit.uni-kl.de            };
106012027Sjungma@eit.uni-kl.de            break;
106112027Sjungma@eit.uni-kl.de
106212027Sjungma@eit.uni-kl.de          default:
106312027Sjungma@eit.uni-kl.de            assert(0); exit(1);
106412027Sjungma@eit.uni-kl.de          };
106512027Sjungma@eit.uni-kl.de        }
106612027Sjungma@eit.uni-kl.de      }
106712027Sjungma@eit.uni-kl.de    }
106812027Sjungma@eit.uni-kl.de
106912027Sjungma@eit.uni-kl.de    void free(tlm::tlm_generic_payload* trans)
107012027Sjungma@eit.uni-kl.de    {
107112027Sjungma@eit.uni-kl.de      mm_end_event_ext* ext = trans->template get_extension<mm_end_event_ext>();
107212027Sjungma@eit.uni-kl.de      assert(ext);
107312027Sjungma@eit.uni-kl.de      // notif event first before freeing extensions (reset)
107412027Sjungma@eit.uni-kl.de      ext->done.notify();
107512027Sjungma@eit.uni-kl.de      trans->reset();
107612027Sjungma@eit.uni-kl.de    }
107712027Sjungma@eit.uni-kl.de
107812027Sjungma@eit.uni-kl.de  private:
107912027Sjungma@eit.uni-kl.de    struct mm_end_event_ext : public tlm::tlm_extension<mm_end_event_ext>
108012027Sjungma@eit.uni-kl.de    {
108112027Sjungma@eit.uni-kl.de      tlm::tlm_extension_base* clone() const { return NULL; }
108212027Sjungma@eit.uni-kl.de      void free() {}
108312027Sjungma@eit.uni-kl.de      void copy_from(tlm::tlm_extension_base const &) {}
108412027Sjungma@eit.uni-kl.de      sc_core::sc_event done;
108512027Sjungma@eit.uni-kl.de    };
108612027Sjungma@eit.uni-kl.de
108712027Sjungma@eit.uni-kl.de  private:
108812027Sjungma@eit.uni-kl.de    const std::string m_name;
108912027Sjungma@eit.uni-kl.de    simple_target_socket_tagged *m_owner;
109012027Sjungma@eit.uni-kl.de    MODULE* m_mod;
109112027Sjungma@eit.uni-kl.de    NBTransportPtr m_nb_transport_ptr;
109212027Sjungma@eit.uni-kl.de    BTransportPtr m_b_transport_ptr;
109312027Sjungma@eit.uni-kl.de    TransportDbgPtr m_transport_dbg_ptr;
109412027Sjungma@eit.uni-kl.de    GetDirectMemPtr m_get_direct_mem_ptr;
109512027Sjungma@eit.uni-kl.de    int m_nb_transport_user_id;
109612027Sjungma@eit.uni-kl.de    int m_b_transport_user_id;
109712027Sjungma@eit.uni-kl.de    int m_transport_dbg_user_id;
109812027Sjungma@eit.uni-kl.de    int m_get_dmi_user_id;
109912027Sjungma@eit.uni-kl.de    peq_with_get<transaction_type> m_peq;
110012027Sjungma@eit.uni-kl.de    bool m_response_in_progress;
110112027Sjungma@eit.uni-kl.de    sc_core::sc_event m_end_response;
110212027Sjungma@eit.uni-kl.de  };
110312027Sjungma@eit.uni-kl.de
110412027Sjungma@eit.uni-kl.deprivate:
110512027Sjungma@eit.uni-kl.de  fw_process m_fw_process;
110612027Sjungma@eit.uni-kl.de  bw_process m_bw_process;
110712027Sjungma@eit.uni-kl.de  std::map<transaction_type*, sc_core::sc_event *> m_pending_trans;
110812027Sjungma@eit.uni-kl.de  sc_core::sc_event m_end_request;
110912027Sjungma@eit.uni-kl.de  transaction_type* m_current_transaction;
111012027Sjungma@eit.uni-kl.de};
111112027Sjungma@eit.uni-kl.de
111212027Sjungma@eit.uni-kl.de}
111312027Sjungma@eit.uni-kl.de
111412027Sjungma@eit.uni-kl.de#endif
1115