/*
 * 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 <sstream>

#include "master_transactor.hh"
#include "params/ExternalMaster.hh"
#include "sc_ext.hh"
#include "sc_master_port.hh"
#include "sim/system.hh"

namespace Gem5SystemC
{

PacketPtr
SCMasterPort::generatePacket(tlm::tlm_generic_payload& trans)
{
    Request::Flags flags;
    auto req = std::make_shared<Request>(
        trans.get_address(), trans.get_data_length(), flags,
        owner.masterId);

    MemCmd cmd;

    switch (trans.get_command()) {
        case tlm::TLM_READ_COMMAND:
            cmd = MemCmd::ReadReq;
            break;
        case tlm::TLM_WRITE_COMMAND:
            cmd = MemCmd::WriteReq;
            break;
        default:
            SC_REPORT_FATAL("SCMasterPort",
                            "received transaction with unsupported command");
    }

    /*
     * 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());

    return pkt;
}

void
SCMasterPort::destroyPacket(PacketPtr pkt)
{
    delete pkt;
}

SCMasterPort::SCMasterPort(const std::string& name_,
                           const std::string& systemc_name,
                           ExternalMaster& owner_,
                           Gem5SimControl& simControl)
  : ExternalMaster::ExternalPort(name_, owner_),
    peq(this, &SCMasterPort::peq_cb),
    waitForRetry(false),
    pendingRequest(nullptr),
    pendingPacket(nullptr),
    needToSendRetry(false),
    responseInProgress(false),
    transactor(nullptr),
    simControl(simControl)
{
    system =
        dynamic_cast<const ExternalMasterParams*>(owner_.params())->system;
}

void
SCMasterPort::bindToTransactor(Gem5MasterTransactor* transactor)
{
    sc_assert(this->transactor == nullptr);

    this->transactor = transactor;

    /*
     * 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("SCMasterPort", "register non-blocking interface");
        transactor->socket.register_nb_transport_fw(this,
                                &SCMasterPort::nb_transport_fw);
    } else if (system->isAtomicMode()) {
        SC_REPORT_INFO("SCMasterPort", "register blocking interface");
        transactor->socket.register_b_transport(this,
                                &SCMasterPort::b_transport);
    } else {
        panic("gem5 operates neither in Timing nor in Atomic mode");
    }

    transactor->socket.register_transport_dbg(this,
                                              &SCMasterPort::transport_dbg);
}

void
SCMasterPort::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());
    }
}

tlm::tlm_sync_enum
SCMasterPort::nb_transport_fw(tlm::tlm_generic_payload& trans,
                              tlm::tlm_phase& phase, sc_core::sc_time& delay)
{
    uint64_t adr = trans.get_address();
    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;
}

void
SCMasterPort::peq_cb(tlm::tlm_generic_payload& trans,
                       const tlm::tlm_phase& phase)
{
    // catch up with SystemC time
    simControl.catchup();
    assert(curTick() == sc_core::sc_time_stamp().value());

    switch (phase) {
        case tlm::BEGIN_REQ:
            handleBeginReq(trans);
            break;
        case tlm::END_RESP:
            handleEndResp(trans);
            break;
        default:
            panic("unimplemented phase in callback");
    }

    // the functions called above may have scheduled gem5 events
    // -> notify the event loop handler
    simControl.notify();
}

void
SCMasterPort::handleBeginReq(tlm::tlm_generic_payload& trans)
{
    sc_assert(!waitForRetry);
    sc_assert(pendingRequest == nullptr);
    sc_assert(pendingPacket == nullptr);

    trans.acquire();

    PacketPtr pkt = nullptr;

    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) {
        extension->setPipeThrough();
        pkt = extension->getPacket();
    } else {
        pkt = generatePacket(trans);
    }

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

    if (sendTimingReq(pkt)) { // port is free -> send END_REQ immediately
        sendEndReq(trans);
        trans.release();
    } else { // port is blocked -> wait for retry before sending END_REQ
        waitForRetry = true;
        pendingRequest = &trans;
        pendingPacket = pkt;
    }
}

void
SCMasterPort::handleEndResp(tlm::tlm_generic_payload& trans)
{
    sc_assert(responseInProgress);

    responseInProgress = false;

    checkTransaction(trans);

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

void
SCMasterPort::sendEndReq(tlm::tlm_generic_payload& trans)
{
    tlm::tlm_phase phase = tlm::END_REQ;
    auto delay = sc_core::SC_ZERO_TIME;

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

void
SCMasterPort::b_transport(tlm::tlm_generic_payload& trans,
                        sc_core::sc_time& t)
{
    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) {
        extension->setPipeThrough();
        pkt = extension->getPacket();
    } else {
        pkt = generatePacket(trans);
    }

    Tick ticks = sendAtomic(pkt);

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

    // one tick is a pico second
    auto delay =
      sc_core::sc_time((double)(ticks / SimClock::Int::ps), sc_core::SC_PS);

    // update time
    t += delay;

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

    trans.set_response_status(tlm::TLM_OK_RESPONSE);
}

unsigned int
SCMasterPort::transport_dbg(tlm::tlm_generic_payload& trans)
{
    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) {
        extension->setPipeThrough();
        sendFunctional(extension->getPacket());
    } else {
        auto pkt = generatePacket(trans);
        sendFunctional(pkt);
        destroyPacket(pkt);
    }

    return trans.get_data_length();
}

bool
SCMasterPort::get_direct_mem_ptr(tlm::tlm_generic_payload& trans,
                               tlm::tlm_dmi& dmi_data)
{
    return false;
}

bool
SCMasterPort::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;

    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);
    else
        sc_assert(extension->isPipeThrough());

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

    return true;
}

void
SCMasterPort::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 = transactor->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");
    }
}

void
SCMasterPort::recvReqRetry()
{
    sc_assert(waitForRetry);
    sc_assert(pendingRequest != nullptr);
    sc_assert(pendingPacket != nullptr);

    if (sendTimingReq(pendingPacket)) {
        waitForRetry = false;
        pendingPacket = nullptr;

        auto& trans = *pendingRequest;
        sendEndReq(trans);
        trans.release();

        pendingRequest = nullptr;
    }
}

void
SCMasterPort::recvRangeChange()
{
    SC_REPORT_WARNING("SCMasterPort",
                      "received address range change but ignored it");
}

ExternalMaster::ExternalPort*
SCMasterPortHandler::getExternalPort(const std::string &name,
                                     ExternalMaster &owner,
                                     const std::string &port_data)
{
    // Create and register a new SystemC master port
    auto* port = new SCMasterPort(name, port_data, owner, control);

    control.registerMasterPort(port_data, port);

    return port;
}

} // namespace Gem5SystemC
