/*
 * Copyright 2019 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.
 *
 * Copyright (c) 2016, Dresden University of Technology (TU Dresden)
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. Neither the name of the copyright holder 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 HOLDER
 * 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.
 */

#include "systemc/tlm_bridge/tlm_to_gem5.hh"

#include <utility>

#include "params/TlmToGem5Bridge32.hh"
#include "params/TlmToGem5Bridge64.hh"
#include "params/TlmToGem5Bridge128.hh"
#include "params/TlmToGem5Bridge256.hh"
#include "params/TlmToGem5Bridge512.hh"
#include "sim/core.hh"
#include "sim/system.hh"
#include "systemc/ext/core/sc_module_name.hh"
#include "systemc/ext/core/sc_time.hh"

using namespace gem5;

namespace sc_gem5
{

namespace
{
/**
 * Hold all the callbacks necessary to convert a tlm payload to gem5 packet.
 */
std::vector<PayloadToPacketConversionStep> extraPayloadToPacketSteps;
}  // namespace

/**
 * Notify the Tlm2Gem5 bridge that we need an extra step to properly convert a
 * tlm payload to gem5 packet. This can be useful when there exists a SystemC
 * extension that carries extra information. For example, SystemC user might
 * define an extension to store stream_id, the user may then add an extra step
 * to set the generated request's stream_id accordingly.
 */
void
addPayloadToPacketConversionStep(PayloadToPacketConversionStep step)
{
    extraPayloadToPacketSteps.push_back(std::move(step));
}

PacketPtr
payload2packet(RequestorID _id, tlm::tlm_generic_payload &trans)
{
    MemCmd cmd;
    RequestPtr req;

    Gem5SystemC::AtomicExtension *atomic_ex = nullptr;
    trans.get_extension(atomic_ex);
    if (atomic_ex) {
        cmd = MemCmd::SwapReq;
        Request::Flags flags = (atomic_ex->needReturn() ?
                                Request::ATOMIC_RETURN_OP :
                                Request::ATOMIC_NO_RETURN_OP);
        AtomicOpFunctorPtr amo_op = AtomicOpFunctorPtr(
            atomic_ex->getAtomicOpFunctor()->clone());
        // FIXME: correct the context_id and pc state.
        req = std::make_shared<Request>(
            trans.get_address(), trans.get_data_length(), flags, _id,
            0, 0, std::move(amo_op));
        req->setPaddr(trans.get_address());
    } else {
        switch (trans.get_command()) {
          case tlm::TLM_READ_COMMAND:
            cmd = MemCmd::ReadReq;
            break;
          case tlm::TLM_WRITE_COMMAND:
            cmd = MemCmd::WriteReq;
            break;
          case tlm::TLM_IGNORE_COMMAND:
            return nullptr;
          default:
            SC_REPORT_FATAL("TlmToGem5Bridge",
                            "received transaction with unsupported "
                            "command");
        }
        Request::Flags flags;
        req = std::make_shared<Request>(
            trans.get_address(), trans.get_data_length(), flags, _id);
    }


    /*
     * Allocate a new Packet. The packet will be deleted when it returns from
     * the gem5 world as a response.
     */
    auto pkt = new Packet(req, cmd);
    pkt->dataStatic(trans.get_data_ptr());

    // Apply all conversion steps necessary in this specific setup.
    for (auto &step : extraPayloadToPacketSteps) {
        step(pkt, trans);
    }

    return pkt;
}

template <unsigned int BITWIDTH>
void
TlmToGem5Bridge<BITWIDTH>::sendEndReq(tlm::tlm_generic_payload &trans)
{
    tlm::tlm_phase phase = tlm::END_REQ;
    auto delay = sc_core::SC_ZERO_TIME;

    auto status = socket->nb_transport_bw(trans, phase, delay);
    panic_if(status != tlm::TLM_ACCEPTED,
             "Unexpected status after sending END_REQ");
}

template <unsigned int BITWIDTH>
void
TlmToGem5Bridge<BITWIDTH>::sendBeginResp(tlm::tlm_generic_payload &trans,
                                         sc_core::sc_time &delay)
{
    tlm::tlm_phase phase = tlm::BEGIN_RESP;

    trans.set_response_status(tlm::TLM_OK_RESPONSE);

    auto status = socket->nb_transport_bw(trans, phase, delay);

    if (status == tlm::TLM_COMPLETED ||
        (status == tlm::TLM_UPDATED && phase == tlm::END_RESP)) {
        // transaction completed -> no need to wait for tlm::END_RESP
        responseInProgress = false;
    } else if (status == tlm::TLM_ACCEPTED) {
        // we need to wait for tlm::END_RESP
        responseInProgress = true;
    } else {
        panic("Unexpected status after sending BEGIN_RESP");
    }
}

template <unsigned int BITWIDTH>
void
TlmToGem5Bridge<BITWIDTH>::handleBeginReq(tlm::tlm_generic_payload &trans)
{
    sc_assert(!waitForRetry);
    sc_assert(pendingRequest == nullptr);
    sc_assert(pendingPacket == nullptr);

    trans.acquire();

    PacketPtr pkt = nullptr;

    Gem5SystemC::Gem5Extension *extension = nullptr;
    trans.get_extension(extension);

    // If there is an extension, this transaction was initiated by the gem5
    // world and we can pipe through the original packet. Otherwise, we
    // generate a new packet based on the transaction.
    if (extension != nullptr) {
        pkt = extension->getPacket();
    } else {
        pkt = payload2packet(_id, trans);
    }

    auto tlmSenderState = new TlmSenderState(trans);
    pkt->pushSenderState(tlmSenderState);

    // If the packet doesn't need a response, we should send BEGIN_RESP by
    // ourselves.
    bool needsResponse = pkt->needsResponse();
    if (bmp.sendTimingReq(pkt)) { // port is free -> send END_REQ immediately
        sendEndReq(trans);
        if (!needsResponse) {
            auto delay = sc_core::SC_ZERO_TIME;
            sendBeginResp(trans, delay);
        }
        trans.release();
    } else { // port is blocked -> wait for retry before sending END_REQ
        waitForRetry = true;
        pendingRequest = &trans;
        pendingPacket = pkt;
    }
}

template <unsigned int BITWIDTH>
void
TlmToGem5Bridge<BITWIDTH>::handleEndResp(tlm::tlm_generic_payload &trans)
{
    sc_assert(responseInProgress);

    responseInProgress = false;

    checkTransaction(trans);

    if (needToSendRetry) {
        bmp.sendRetryResp();
        needToSendRetry = false;
    }
}

template <unsigned int BITWIDTH>
void
TlmToGem5Bridge<BITWIDTH>::destroyPacket(PacketPtr pkt)
{
    delete pkt;
}

template <unsigned int BITWIDTH>
void
TlmToGem5Bridge<BITWIDTH>::checkTransaction(tlm::tlm_generic_payload &trans)
{
    if (trans.is_response_error()) {
        std::stringstream ss;
        ss << "Transaction returned with error, response status = "
           << trans.get_response_string();
        SC_REPORT_ERROR("TLM-2", ss.str().c_str());
    }
}

template <unsigned int BITWIDTH>
void
TlmToGem5Bridge<BITWIDTH>::invalidateDmi(const gem5::MemBackdoor &backdoor)
{
    socket->invalidate_direct_mem_ptr(
            backdoor.range().start(), backdoor.range().end());
}

template <unsigned int BITWIDTH>
void
TlmToGem5Bridge<BITWIDTH>::peq_cb(tlm::tlm_generic_payload &trans,
                                  const tlm::tlm_phase &phase)
{
    switch (phase) {
        case tlm::BEGIN_REQ:
            handleBeginReq(trans);
            break;
        case tlm::END_RESP:
            handleEndResp(trans);
            break;
        default:
            panic("unimplemented phase in callback");
    }
}

template <unsigned int BITWIDTH>
tlm::tlm_sync_enum
TlmToGem5Bridge<BITWIDTH>::nb_transport_fw(
        tlm::tlm_generic_payload &trans, tlm::tlm_phase &phase,
        sc_core::sc_time &delay)
{
    unsigned len = trans.get_data_length();
    unsigned char *byteEnable = trans.get_byte_enable_ptr();
    unsigned width = trans.get_streaming_width();

    // check the transaction attributes for unsupported features ...
    if (byteEnable != 0) {
        trans.set_response_status(tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE);
        return tlm::TLM_COMPLETED;
    }
    if (width < len) { // is this a burst request?
        trans.set_response_status(tlm::TLM_BURST_ERROR_RESPONSE);
        return tlm::TLM_COMPLETED;
    }

    // ... and queue the valid transaction
    trans.acquire();
    peq.notify(trans, phase, delay);
    return tlm::TLM_ACCEPTED;
}

template <unsigned int BITWIDTH>
void
TlmToGem5Bridge<BITWIDTH>::b_transport(tlm::tlm_generic_payload &trans,
                                       sc_core::sc_time &t)
{
    Gem5SystemC::Gem5Extension *extension = nullptr;
    trans.get_extension(extension);

    PacketPtr pkt = nullptr;

    // If there is an extension, this transaction was initiated by the gem5
    // world and we can pipe through the original packet.
    if (extension != nullptr) {
        pkt = extension->getPacket();
    } else {
        pkt = payload2packet(_id, trans);
    }

    MemBackdoorPtr backdoor = nullptr;
    Tick ticks = bmp.sendAtomicBackdoor(pkt, backdoor);
    if (backdoor)
        trans.set_dmi_allowed(true);

    // send an atomic request to gem5
    panic_if(pkt->needsResponse() && !pkt->isResponse(),
             "Packet sending failed!\n");

    auto delay =
      sc_core::sc_time((double)(ticks / sim_clock::as_int::ps),
        sc_core::SC_PS);

    // update time
    t += delay;

    if (extension == nullptr)
        destroyPacket(pkt);

    trans.set_response_status(tlm::TLM_OK_RESPONSE);
}

template <unsigned int BITWIDTH>
unsigned int
TlmToGem5Bridge<BITWIDTH>::transport_dbg(tlm::tlm_generic_payload &trans)
{
    Gem5SystemC::Gem5Extension *extension = nullptr;
    trans.get_extension(extension);

    // If there is an extension, this transaction was initiated by the gem5
    // world and we can pipe through the original packet.
    if (extension != nullptr) {
        bmp.sendFunctional(extension->getPacket());
    } else {
        auto pkt = payload2packet(_id, trans);
        if (pkt) {
            bmp.sendFunctional(pkt);
            destroyPacket(pkt);
        }
    }

    return trans.get_data_length();
}

template <unsigned int BITWIDTH>
bool
TlmToGem5Bridge<BITWIDTH>::get_direct_mem_ptr(tlm::tlm_generic_payload &trans,
                                              tlm::tlm_dmi &dmi_data)
{
    Gem5SystemC::Gem5Extension *extension = nullptr;
    trans.get_extension(extension);

    PacketPtr pkt = nullptr;

    // If there is an extension, this transaction was initiated by the gem5
    // world and we can pipe through the original packet.
    if (extension != nullptr) {
        pkt = extension->getPacket();
    } else {
        pkt = payload2packet(_id, trans);
        pkt->req->setFlags(Request::NO_ACCESS);
    }

    MemBackdoorPtr backdoor = nullptr;
    bmp.sendAtomicBackdoor(pkt, backdoor);
    if (backdoor) {
        trans.set_dmi_allowed(true);
        dmi_data.set_dmi_ptr(backdoor->ptr());
        dmi_data.set_start_address(backdoor->range().start());
        dmi_data.set_end_address(backdoor->range().end());

        typedef tlm::tlm_dmi::dmi_access_e access_t;
        access_t access = tlm::tlm_dmi::DMI_ACCESS_NONE;
        if (backdoor->readable())
            access = (access_t)(access | tlm::tlm_dmi::DMI_ACCESS_READ);
        if (backdoor->writeable())
            access = (access_t)(access | tlm::tlm_dmi::DMI_ACCESS_WRITE);
        dmi_data.set_granted_access(access);

        backdoor->addInvalidationCallback(
            [this](const MemBackdoor &backdoor)
            {
                invalidateDmi(backdoor);
            }
        );
    }

    if (extension == nullptr)
        destroyPacket(pkt);

    trans.set_response_status(tlm::TLM_OK_RESPONSE);

    return backdoor != nullptr;
}

template <unsigned int BITWIDTH>
bool
TlmToGem5Bridge<BITWIDTH>::recvTimingResp(PacketPtr pkt)
{
    // exclusion rule
    // We need to Wait for END_RESP before sending next BEGIN_RESP
    if (responseInProgress) {
        sc_assert(!needToSendRetry);
        needToSendRetry = true;
        return false;
    }

    sc_assert(pkt->isResponse());

    /*
     * Pay for annotated transport delays.
     *
     * See recvTimingReq in sc_slave_port.cc for a detailed description.
     */
    auto delay = sc_core::sc_time::from_value(pkt->payloadDelay);
    // reset the delays
    pkt->payloadDelay = 0;
    pkt->headerDelay = 0;

    auto tlmSenderState = dynamic_cast<TlmSenderState*>(pkt->popSenderState());
    sc_assert(tlmSenderState != nullptr);

    auto &trans = tlmSenderState->trans;

    Gem5SystemC::Gem5Extension *extension = nullptr;
    trans.get_extension(extension);

    // clean up
    delete tlmSenderState;

    // If there is an extension the packet was piped through and we must not
    // delete it. The packet travels back with the transaction.
    if (extension == nullptr)
        destroyPacket(pkt);

    sendBeginResp(trans, delay);
    trans.release();

    return true;
}

template <unsigned int BITWIDTH>
void
TlmToGem5Bridge<BITWIDTH>::recvReqRetry()
{
    sc_assert(waitForRetry);
    sc_assert(pendingRequest != nullptr);
    sc_assert(pendingPacket != nullptr);

    // If the packet doesn't need a response, we should send BEGIN_RESP by
    // ourselves.
    bool needsResponse = pendingPacket->needsResponse();
    if (bmp.sendTimingReq(pendingPacket)) {
        waitForRetry = false;
        pendingPacket = nullptr;

        auto &trans = *pendingRequest;
        sendEndReq(trans);
        if (!needsResponse) {
            auto delay = sc_core::SC_ZERO_TIME;
            sendBeginResp(trans, delay);
        }
        trans.release();

        pendingRequest = nullptr;
    }
}

template <unsigned int BITWIDTH>
void
TlmToGem5Bridge<BITWIDTH>::recvRangeChange()
{
    SC_REPORT_WARNING("TlmToGem5Bridge",
                      "received address range change but ignored it");
}

template <unsigned int BITWIDTH>
gem5::Port &
TlmToGem5Bridge<BITWIDTH>::gem5_getPort(const std::string &if_name, int idx)
{
    if (if_name == "gem5")
        return bmp;
    else if (if_name == "tlm")
        return wrapper;

    return sc_core::sc_module::gem5_getPort(if_name, idx);
}

template <unsigned int BITWIDTH>
TlmToGem5Bridge<BITWIDTH>::TlmToGem5Bridge(
        const Params &params, const sc_core::sc_module_name &mn) :
    TlmToGem5BridgeBase(mn), peq(this, &TlmToGem5Bridge<BITWIDTH>::peq_cb),
    waitForRetry(false), pendingRequest(nullptr), pendingPacket(nullptr),
    needToSendRetry(false), responseInProgress(false),
    bmp(std::string(name()) + "master", *this), socket("tlm_socket"),
    wrapper(socket, std::string(name()) + ".tlm", InvalidPortID),
    system(params.system),
    _id(params.system->getGlobalRequestorId(
                std::string("[systemc].") + name()))
{
}

template <unsigned int BITWIDTH>
void
TlmToGem5Bridge<BITWIDTH>::before_end_of_elaboration()
{
    /*
     * Register the TLM non-blocking interface when using gem5 Timing mode and
     * the TLM blocking interface when using the gem5 Atomic mode.
     * Then the magic (TM) in simple_target_socket automatically transforms
     * non-blocking in blocking transactions and vice versa.
     *
     * NOTE: The mode may change during execution.
     */
    if (system->isTimingMode()) {
        SC_REPORT_INFO("TlmToGem5Bridge", "register non-blocking interface");
        socket.register_nb_transport_fw(
                this, &TlmToGem5Bridge<BITWIDTH>::nb_transport_fw);
    } else if (system->isAtomicMode()) {
        SC_REPORT_INFO("TlmToGem5Bridge", "register blocking interface");
        socket.register_b_transport(
                this, &TlmToGem5Bridge<BITWIDTH>::b_transport);
        socket.register_get_direct_mem_ptr(
                this, &TlmToGem5Bridge<BITWIDTH>::get_direct_mem_ptr);
    } else {
        panic("gem5 operates neither in Timing nor in Atomic mode");
    }

    socket.register_transport_dbg(
            this, &TlmToGem5Bridge<BITWIDTH>::transport_dbg);

    sc_core::sc_module::before_end_of_elaboration();
}

} // namespace sc_gem5

sc_gem5::TlmToGem5Bridge<32> *
gem5::TlmToGem5Bridge32Params::create() const
{
    return new sc_gem5::TlmToGem5Bridge<32>(
            *this, sc_core::sc_module_name(name.c_str()));
}

sc_gem5::TlmToGem5Bridge<64> *
gem5::TlmToGem5Bridge64Params::create() const
{
    return new sc_gem5::TlmToGem5Bridge<64>(
            *this, sc_core::sc_module_name(name.c_str()));
}

sc_gem5::TlmToGem5Bridge<128> *
gem5::TlmToGem5Bridge128Params::create() const
{
    return new sc_gem5::TlmToGem5Bridge<128>(
            *this, sc_core::sc_module_name(name.c_str()));
}

sc_gem5::TlmToGem5Bridge<256> *
gem5::TlmToGem5Bridge256Params::create() const
{
    return new sc_gem5::TlmToGem5Bridge<256>(
            *this, sc_core::sc_module_name(name.c_str()));
}

sc_gem5::TlmToGem5Bridge<512> *
gem5::TlmToGem5Bridge512Params::create() const
{
    return new sc_gem5::TlmToGem5Bridge<512>(
            *this, sc_core::sc_module_name(name.c_str()));
}
