/*
 * Copyright 2018 Google, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#ifndef __SYSTEMC_TLM_PORT_WRAPPER_HH__
#define __SYSTEMC_TLM_PORT_WRAPPER_HH__

#include "base/logging.hh"
#include "sim/port.hh"
#include "systemc/ext/tlm_core/2/sockets/sockets.hh"

namespace sc_gem5
{

template <unsigned int BUSWIDTH, typename FW_IF, typename BW_IF, int N,
          sc_core::sc_port_policy POL>
class TlmInitiatorBaseWrapper;

template <unsigned int BUSWIDTH, typename FW_IF, typename BW_IF, int N,
          sc_core::sc_port_policy POL>
class TlmTargetBaseWrapper;

template <unsigned int BUSWIDTH, typename FW_IF, typename BW_IF, int N,
          sc_core::sc_port_policy POL>
class TlmInitiatorBaseWrapper : public ::Port
{
  public:
    typedef tlm::tlm_base_initiator_socket<BUSWIDTH, FW_IF, BW_IF, N, POL>
        InitiatorSocket;
    typedef typename InitiatorSocket::base_target_socket_type TargetSocket;
    typedef TlmTargetBaseWrapper<BUSWIDTH, FW_IF, BW_IF, N, POL> TargetWrapper;

    InitiatorSocket &initiator() { return _initiator; }

    TlmInitiatorBaseWrapper(
            InitiatorSocket &i, const std::string &_name, PortID _id) :
        Port(_name, _id), _initiator(i)
    {}

    void
    bind(::Port &peer) override
    {
        auto *target = dynamic_cast<TargetWrapper *>(&peer);
        fatal_if(!target, "Attempt to bind TLM initiator socket %s to "
                "incompatible port %s.", name(), peer.name());

        initiator().bind(target->target());
        Port::bind(peer);
    }

    void
    unbind() override
    {
        panic("TLM sockets can't be unbound.");
    }

  private:
    InitiatorSocket &_initiator;
};

template <unsigned int BUSWIDTH, typename FW_IF, typename BW_IF, int N,
          sc_core::sc_port_policy POL>
class TlmTargetBaseWrapper : public ::Port
{
  public:
    typedef tlm::tlm_base_target_socket<BUSWIDTH, FW_IF, BW_IF, N, POL>
        TargetSocket;

    TargetSocket &target() { return _target; }

    TlmTargetBaseWrapper(TargetSocket &t, const std::string &_name,
                         PortID _id) :
        Port(_name, _id), _target(t)
    {}

    void
    bind(::Port &peer) override
    {
        // Ignore attempts to bind a target socket. The initiator will
        // handle it.
        Port::bind(peer);
    }

    void
    unbind() override
    {
        panic("TLM sockets can't be unbound.");
    }

  private:
    TargetSocket &_target;
};

template <unsigned int BUSWIDTH=32,
          typename TYPES=tlm::tlm_base_protocol_types, int N=1,
          sc_core::sc_port_policy POL=sc_core::SC_ONE_OR_MORE_BOUND>
using TlmInitiatorWrapper =
    TlmInitiatorBaseWrapper<BUSWIDTH, tlm::tlm_fw_transport_if<TYPES>,
                            tlm::tlm_bw_transport_if<TYPES>, N, POL>;

template <unsigned int BUSWIDTH=32,
          typename TYPES=tlm::tlm_base_protocol_types, int N=1,
          sc_core::sc_port_policy POL=sc_core::SC_ONE_OR_MORE_BOUND>
using TlmTargetWrapper =
    TlmTargetBaseWrapper<BUSWIDTH, tlm::tlm_fw_transport_if<TYPES>,
                         tlm::tlm_bw_transport_if<TYPES>, N, POL>;

} // namespace sc_gem5

#endif  //__SYSTEMC_TLM_PORT_WRAPPER_HH__
