/*
 * Copyright (c) 2012-2014 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * 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.
 */

#include "mem/external_slave.hh"

#include <cctype>
#include <iomanip>

#include "base/trace.hh"
#include "debug/ExternalPort.hh"

/** Implement a `stub' port which just responds to requests by printing
 *  a message.  The stub port can be used to configure and test a system
 *  where the external port is used for a peripheral before connecting
 *  the external port */
class StubSlavePort : public ExternalSlave::ExternalPort
{
  public:
    void processResponseEvent();

    EventFunctionWrapper responseEvent;

    /** Stub can handle a single request at a time.  This will be
     *  NULL when no packet is in flight */
    PacketPtr responsePacket;

    /** Received a new request while processing a first.  Need to ask for
     *  a retry after completing this packet */
    bool mustRetry;

    StubSlavePort(const std::string &name_,
        ExternalSlave &owner_) :
        ExternalSlave::ExternalPort(name_, owner_),
        responseEvent([this]{ processResponseEvent(); }, name()),
        responsePacket(NULL), mustRetry(false)
    { }

    Tick recvAtomic(PacketPtr packet);
    void recvFunctional(PacketPtr packet);
    bool recvTimingReq(PacketPtr packet);
    bool recvTimingSnoopResp(PacketPtr packet);
    void recvRespRetry();
    void recvFunctionalSnoop(PacketPtr packet);
};

class StubSlavePortHandler : public
    ExternalSlave::Handler
{
  public:
    ExternalSlave::ExternalPort *getExternalPort(
        const std::string &name_,
        ExternalSlave &owner,
        const std::string &port_data)
    {
        StringWrap name(name_);

        DPRINTF(ExternalPort, "finding stub port '%s'\n", port_data);
        return new StubSlavePort(name_, owner);
    }
};

Tick
StubSlavePort::recvAtomic(PacketPtr packet)
{
    if (DTRACE(ExternalPort)) {
        M5_VAR_USED unsigned int size = packet->getSize();

        DPRINTF(ExternalPort, "StubSlavePort: recvAtomic a: 0x%x size: %d"
            " data: ...\n", packet->getAddr(), size);
        DDUMP(ExternalPort, packet->getConstPtr<uint8_t>(), size);
    }

    return 0;
}

void
StubSlavePort::recvFunctional(PacketPtr packet)
{
    recvAtomic(packet);
}

void
StubSlavePort::processResponseEvent()
{
    responsePacket->makeResponse();
    responsePacket->headerDelay = 0;
    responsePacket->payloadDelay = 0;

    if (sendTimingResp(responsePacket)) {
        responsePacket = NULL;

        if (mustRetry)
            sendRetryReq();
        mustRetry = false;
    }
}

bool
StubSlavePort::recvTimingReq(PacketPtr packet)
{
    if (responsePacket) {
        mustRetry = true;

        return false;
    } else {
        recvAtomic(packet);

        responsePacket = packet;
        owner.schedule(responseEvent, curTick());

        return true;
    }
}

bool
StubSlavePort::recvTimingSnoopResp(PacketPtr packet)
{
    fatal("StubSlavePort: function: %s\n", __func__);
    return false;
}

void
StubSlavePort::recvRespRetry()
{
    assert(responsePacket);
    /* Stub handles only one response at a time so responseEvent should never
     *  be scheduled at this point.  Retrys shouldn't need to schedule, we
     *  can safely send the response here */
    responseEvent.process();
}

void
StubSlavePort::recvFunctionalSnoop(PacketPtr packet)
{
    fatal("StubSlavePort: unimplemented function: %s\n", __func__);
}

std::map<std::string, ExternalSlave::Handler *>
    ExternalSlave::portHandlers;

AddrRangeList
ExternalSlave::ExternalPort::getAddrRanges() const
{
    return owner.addrRanges;
}

ExternalSlave::ExternalSlave(const ExternalSlaveParams &params) :
    SimObject(params),
    externalPort(NULL),
    portName(params.name + ".port"),
    portType(params.port_type),
    portData(params.port_data),
    addrRanges(params.addr_ranges.begin(), params.addr_ranges.end())
{
    /* Register the stub handler if it hasn't already been registered */
    if (portHandlers.find("stub") == portHandlers.end())
        registerHandler("stub", new StubSlavePortHandler);
}

Port &
ExternalSlave::getPort(const std::string &if_name, PortID idx)
{
    if (if_name == "port") {
        DPRINTF(ExternalPort, "Trying to bind external port: %s %s\n",
            portType, portName);

        if (!externalPort) {
            auto handlerIter = portHandlers.find(portType);

            if (handlerIter == portHandlers.end())
                fatal("Can't find port handler type '%s'\n", portType);

            externalPort = portHandlers[portType]->getExternalPort(portName,
                *this, portData);

            if (!externalPort) {
                fatal("%s: Can't find external port type: %s"
                    " port_data: '%s'\n", portName, portType, portData);
            }
        }
        return *externalPort;
    } else {
        return SimObject::getPort(if_name, idx);
    }
}

void
ExternalSlave::init()
{
    if (!externalPort) {
        fatal("ExternalSlave %s: externalPort not set!\n", name());
    } else if (!externalPort->isConnected()) {
        fatal("ExternalSlave %s is unconnected!\n", name());
    } else {
        externalPort->sendRangeChange();
    }
}

void
ExternalSlave::registerHandler(const std::string &handler_name,
    Handler *handler)
{
    portHandlers[handler_name] = handler;
}
