/*
 * 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.
 *
 * Authors: Christian Menard
 */

#include "systemc/tlm_bridge/sc_master_port.hh"

#include <sstream>

#include "params/ExternalMaster.hh"
#include "sim/system.hh"
#include "systemc/tlm_bridge/master_transactor.hh"
#include "systemc/tlm_bridge/sc_ext.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::Port(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)
{
    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::Port *
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
