/*
 * 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.
 *
 * Authors: Andrew Bardsley
 */

#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::Port
{
  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::Port(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::Port *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)) {
        unsigned int M5_VAR_USED 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::Port::getAddrRanges() const
{
    return owner.addrRanges;
}

ExternalSlave::ExternalSlave(ExternalSlaveParams *params) :
    MemObject(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);
}

BaseSlavePort &
ExternalSlave::getSlavePort(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 MemObject::getSlavePort(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();
    }
}

ExternalSlave *
ExternalSlaveParams::create()
{
    return new ExternalSlave(this);
}

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