/*
 * Copyright (c) 2006 The Regents of The University of Michigan
 * All rights reserved.
 *
 * 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: Ali Saidi
 */

/**
 * @file
 * Definition of a bus object.
 */

#include <algorithm>
#include <limits>

#include "base/misc.hh"
#include "base/trace.hh"
#include "mem/bus.hh"

Port *
Bus::getPort(const std::string &if_name, int idx)
{
    if (if_name == "default") {
        if (defaultPort == NULL) {
            defaultPort = new BusPort(csprintf("%s-default",name()), this,
                                      defaultId);
            cachedBlockSizeValid = false;
            return defaultPort;
        } else
            fatal("Default port already set\n");
    }
    int id;
    if (if_name == "functional") {
        if (!funcPort) {
            id = maxId++;
            funcPort = new BusPort(csprintf("%s-p%d-func", name(), id), this, id);
            funcPortId = id;
            interfaces[id] = funcPort;
        }
        return funcPort;
    }

    // if_name ignored?  forced to be empty?
    id = maxId++;
    assert(maxId < std::numeric_limits<typeof(maxId)>::max());
    BusPort *bp = new BusPort(csprintf("%s-p%d", name(), id), this, id);
    interfaces[id] = bp;
    cachedBlockSizeValid = false;
    return bp;
}

void
Bus::deletePortRefs(Port *p)
{

    BusPort *bp =  dynamic_cast<BusPort*>(p);
    if (bp == NULL)
        panic("Couldn't convert Port* to BusPort*\n");
    // If this is our one functional port
    if (funcPort == bp)
        return;
    interfaces.erase(bp->getId());
    clearBusCache();
    delete bp;
}

/** Get the ranges of anyone other buses that we are connected to. */
void
Bus::init()
{
    m5::hash_map<short,BusPort*>::iterator intIter;

    for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++)
        intIter->second->sendStatusChange(Port::RangeChange);
}

Bus::BusFreeEvent::BusFreeEvent(Bus *_bus) : Event(&mainEventQueue), bus(_bus)
{}

void Bus::BusFreeEvent::process()
{
    bus->recvRetry(-1);
}

const char * Bus::BusFreeEvent::description() const
{
    return "bus became available";
}

Tick Bus::calcPacketTiming(PacketPtr pkt)
{
    // Bring tickNextIdle up to the present tick.
    // There is some potential ambiguity where a cycle starts, which
    // might make a difference when devices are acting right around a
    // cycle boundary. Using a < allows things which happen exactly on
    // a cycle boundary to take up only the following cycle. Anything
    // that happens later will have to "wait" for the end of that
    // cycle, and then start using the bus after that.
    if (tickNextIdle < curTick) {
        tickNextIdle = curTick;
        if (tickNextIdle % clock != 0)
            tickNextIdle = curTick - (curTick % clock) + clock;
    }

    Tick headerTime = tickNextIdle + headerCycles * clock;

    // The packet will be sent. Figure out how long it occupies the bus, and
    // how much of that time is for the first "word", aka bus width.
    int numCycles = 0;
    if (pkt->hasData()) {
        // If a packet has data, it needs ceil(size/width) cycles to send it
        int dataSize = pkt->getSize();
        numCycles += dataSize/width;
        if (dataSize % width)
            numCycles++;
    }

    // The first word will be delivered after the current tick, the delivery
    // of the address if any, and one bus cycle to deliver the data
    pkt->firstWordTime = headerTime + clock;

    pkt->finishTime = headerTime + numCycles * clock;

    return headerTime;
}

void Bus::occupyBus(Tick until)
{
    if (until == 0) {
        // shortcut for express snoop packets
        return;
    }

    tickNextIdle = until;

    if (!busIdle.scheduled()) {
        busIdle.schedule(tickNextIdle);
    } else {
        busIdle.reschedule(tickNextIdle);
    }
    DPRINTF(Bus, "The bus is now occupied from tick %d to %d\n",
            curTick, tickNextIdle);
}

/** Function called by the port when the bus is receiving a Timing
 * transaction.*/
bool
Bus::recvTiming(PacketPtr pkt)
{
    short src = pkt->getSrc();

    BusPort *src_port;
    if (src == defaultId)
        src_port = defaultPort;
    else {
        src_port = checkBusCache(src);
        if (src_port == NULL) {
            src_port = interfaces[src];
            updateBusCache(src, src_port);
        }
    }

    // If the bus is busy, or other devices are in line ahead of the current
    // one, put this device on the retry list.
    if (!pkt->isExpressSnoop() &&
        (tickNextIdle > curTick ||
         (retryList.size() && (!inRetry || src_port != retryList.front()))))
    {
        addToRetryList(src_port);
        DPRINTF(Bus, "recvTiming: src %d dst %d %s 0x%x BUSY\n",
                src, pkt->getDest(), pkt->cmdString(), pkt->getAddr());
        return false;
    }

    DPRINTF(Bus, "recvTiming: src %d dst %d %s 0x%x\n",
            src, pkt->getDest(), pkt->cmdString(), pkt->getAddr());

    Tick headerFinishTime = pkt->isExpressSnoop() ? 0 : calcPacketTiming(pkt);
    Tick packetFinishTime = pkt->isExpressSnoop() ? 0 : pkt->finishTime;

    short dest = pkt->getDest();
    int dest_port_id;
    Port *dest_port;

    if (dest == Packet::Broadcast) {
        dest_port_id = findPort(pkt->getAddr());
        dest_port = (dest_port_id == defaultId) ?
            defaultPort : interfaces[dest_port_id];
        SnoopIter s_end = snoopPorts.end();
        for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) {
            BusPort *p = *s_iter;
            if (p != dest_port && p != src_port) {
                // cache is not allowed to refuse snoop
                bool success M5_VAR_USED = p->sendTiming(pkt);
                assert(success);
            }
        }
    } else {
        assert(dest >= 0 && dest < maxId);
        assert(dest != src); // catch infinite loops
        dest_port_id = dest;
        if (dest_port_id == defaultId)
            dest_port = defaultPort;
        else {
            dest_port = checkBusCache(dest);
            if (dest_port == NULL) {
                dest_port = interfaces[dest_port_id];
            // updateBusCache(dest_port_id, dest_port);
            }
        }
        dest_port = (dest_port_id == defaultId) ?
            defaultPort : interfaces[dest_port_id];
    }

    if (dest_port_id == src) {
        // Must be forwarded snoop up from below...
        assert(dest == Packet::Broadcast);
        assert(src != defaultId); // catch infinite loops
    } else {
        // send to actual target
        if (!dest_port->sendTiming(pkt))  {
            // Packet not successfully sent. Leave or put it on the retry list.
            // illegal to block responses... can lead to deadlock
            assert(!pkt->isResponse());
            DPRINTF(Bus, "recvTiming: src %d dst %d %s 0x%x TGT RETRY\n",
                    src, pkt->getDest(), pkt->cmdString(), pkt->getAddr());
            addToRetryList(src_port);
            occupyBus(headerFinishTime);
            return false;
        }
        // send OK, fall through... pkt may have been deleted by
        // target at this point, so it should *not* be referenced
        // again.  We'll set it to NULL here just to be safe.
        pkt = NULL;
    }

    occupyBus(packetFinishTime);

    // Packet was successfully sent.
    // Also take care of retries
    if (inRetry) {
        DPRINTF(Bus, "Remove retry from list %d\n", src);
        retryList.front()->onRetryList(false);
        retryList.pop_front();
        inRetry = false;
    }
    return true;
}

void
Bus::recvRetry(int id)
{
    // If there's anything waiting, and the bus isn't busy...
    if (retryList.size() && curTick >= tickNextIdle) {
        //retryingPort = retryList.front();
        inRetry = true;
        DPRINTF(Bus, "Sending a retry to %s\n", retryList.front()->getPeer()->name());
        retryList.front()->sendRetry();
        // If inRetry is still true, sendTiming wasn't called
        if (inRetry)
        {
            retryList.front()->onRetryList(false);
            retryList.pop_front();
            inRetry = false;

            //Bring tickNextIdle up to the present
            while (tickNextIdle < curTick)
                tickNextIdle += clock;

            //Burn a cycle for the missed grant.
            tickNextIdle += clock;

            busIdle.reschedule(tickNextIdle, true);
        }
    }
    //If we weren't able to drain before, we might be able to now.
    if (drainEvent && retryList.size() == 0 && curTick >= tickNextIdle) {
        drainEvent->process();
        // Clear the drain event once we're done with it.
        drainEvent = NULL;
    }
}

int
Bus::findPort(Addr addr)
{
    /* An interval tree would be a better way to do this. --ali. */
    int dest_id = -1;

    dest_id = checkPortCache(addr);
    if (dest_id == -1) {
        PortIter i = portMap.find(RangeSize(addr,1));
        if (i != portMap.end()) {
            dest_id = i->second;
            updatePortCache(dest_id, i->first.start, i->first.end);
        }
    }

    // Check if this matches the default range
    if (dest_id == -1) {
        AddrRangeIter a_end = defaultRange.end();
        for (AddrRangeIter i = defaultRange.begin(); i != a_end; i++) {
            if (*i == addr) {
                DPRINTF(Bus, "  found addr %#llx on default\n", addr);
                return defaultId;
            }
        }

        if (responderSet) {
            panic("Unable to find destination for addr (user set default "
                  "responder): %#llx\n", addr);
        } else {
            DPRINTF(Bus, "Unable to find destination for addr: %#llx, will use "
                    "default port\n", addr);

            return defaultId;
        }
    }

    return dest_id;
}


/** Function called by the port when the bus is receiving a Atomic
 * transaction.*/
Tick
Bus::recvAtomic(PacketPtr pkt)
{
    DPRINTF(Bus, "recvAtomic: packet src %d dest %d addr 0x%x cmd %s\n",
            pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
    assert(pkt->getDest() == Packet::Broadcast);
    assert(pkt->isRequest());

    // Variables for recording original command and snoop response (if
    // any)... if a snooper respondes, we will need to restore
    // original command so that additional snoops can take place
    // properly
    MemCmd orig_cmd = pkt->cmd;
    MemCmd snoop_response_cmd = MemCmd::InvalidCmd;
    Tick snoop_response_latency = 0;
    int orig_src = pkt->getSrc();

    int target_port_id = findPort(pkt->getAddr());
    BusPort *target_port;
    if (target_port_id == defaultId)
        target_port = defaultPort;
    else {
      target_port = checkBusCache(target_port_id);
      if (target_port == NULL) {
          target_port = interfaces[target_port_id];
          updateBusCache(target_port_id, target_port);
      }
    }

    SnoopIter s_end = snoopPorts.end();
    for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) {
        BusPort *p = *s_iter;
        // same port should not have both target addresses and snooping
        assert(p != target_port);
        if (p->getId() != pkt->getSrc()) {
            Tick latency = p->sendAtomic(pkt);
            if (pkt->isResponse()) {
                // response from snoop agent
                assert(pkt->cmd != orig_cmd);
                assert(pkt->memInhibitAsserted());
                // should only happen once
                assert(snoop_response_cmd == MemCmd::InvalidCmd);
                // save response state
                snoop_response_cmd = pkt->cmd;
                snoop_response_latency = latency;
                // restore original packet state for remaining snoopers
                pkt->cmd = orig_cmd;
                pkt->setSrc(orig_src);
                pkt->setDest(Packet::Broadcast);
            }
        }
    }

    Tick response_latency = 0;

    // we can get requests sent up from the memory side of the bus for
    // snooping... don't send them back down!
    if (target_port_id != pkt->getSrc()) {
        response_latency = target_port->sendAtomic(pkt);
    }

    // if we got a response from a snooper, restore it here
    if (snoop_response_cmd != MemCmd::InvalidCmd) {
        // no one else should have responded
        assert(!pkt->isResponse());
        assert(pkt->cmd == orig_cmd);
        pkt->cmd = snoop_response_cmd;
        response_latency = snoop_response_latency;
    }

    // why do we have this packet field and the return value both???
    pkt->finishTime = curTick + response_latency;
    return response_latency;
}

/** Function called by the port when the bus is receiving a Functional
 * transaction.*/
void
Bus::recvFunctional(PacketPtr pkt)
{
    if (!pkt->isPrint()) {
        // don't do DPRINTFs on PrintReq as it clutters up the output
        DPRINTF(Bus,
                "recvFunctional: packet src %d dest %d addr 0x%x cmd %s\n",
                pkt->getSrc(), pkt->getDest(), pkt->getAddr(),
                pkt->cmdString());
    }
    assert(pkt->getDest() == Packet::Broadcast);

    int port_id = findPort(pkt->getAddr());
    Port *port = (port_id == defaultId) ? defaultPort : interfaces[port_id];
    // The packet may be changed by another bus on snoops, restore the
    // id after each
    int src_id = pkt->getSrc();

    assert(pkt->isRequest()); // hasn't already been satisfied

    SnoopIter s_end = snoopPorts.end();
    for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) {
        BusPort *p = *s_iter;
        if (p != port && p->getId() != src_id) {
            p->sendFunctional(pkt);
        }
        if (pkt->isResponse()) {
            break;
        }
        pkt->setSrc(src_id);
    }

    // If the snooping hasn't found what we were looking for, keep going.
    if (!pkt->isResponse() && port_id != pkt->getSrc()) {
        port->sendFunctional(pkt);
    }
}

/** Function called by the port when the bus is receiving a status change.*/
void
Bus::recvStatusChange(Port::Status status, int id)
{
    AddrRangeList ranges;
    bool snoops;
    AddrRangeIter iter;

    if (inRecvStatusChange.count(id))
        return;
    inRecvStatusChange.insert(id);

    assert(status == Port::RangeChange &&
           "The other statuses need to be implemented.");

    DPRINTF(BusAddrRanges, "received RangeChange from device id %d\n", id);

    clearPortCache();
    if (id == defaultId) {
        defaultRange.clear();
        // Only try to update these ranges if the user set a default responder.
        if (responderSet) {
            defaultPort->getPeerAddressRanges(ranges, snoops);
            assert(snoops == false);
            for(iter = ranges.begin(); iter != ranges.end(); iter++) {
                defaultRange.push_back(*iter);
                DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for default range\n",
                        iter->start, iter->end);
            }
        }
    } else {

        assert((id < maxId && id >= 0) || id == defaultId);
        BusPort *port = interfaces[id];

        // Clean out any previously existent ids
        for (PortIter portIter = portMap.begin();
             portIter != portMap.end(); ) {
            if (portIter->second == id)
                portMap.erase(portIter++);
            else
                portIter++;
        }

        for (SnoopIter s_iter = snoopPorts.begin();
             s_iter != snoopPorts.end(); ) {
            if ((*s_iter)->getId() == id)
                s_iter = snoopPorts.erase(s_iter);
            else
                s_iter++;
        }

        port->getPeerAddressRanges(ranges, snoops);

        if (snoops) {
            DPRINTF(BusAddrRanges, "Adding id %d to snoop list\n", id);
            snoopPorts.push_back(port);
        }

        for (iter = ranges.begin(); iter != ranges.end(); iter++) {
            DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for id %d\n",
                    iter->start, iter->end, id);
            if (portMap.insert(*iter, id) == portMap.end()) {
                int conflict_id = portMap.find(*iter)->second;
                fatal("%s has two ports with same range:\n\t%s\n\t%s\n",
                      name(), interfaces[id]->getPeer()->name(),
                      interfaces[conflict_id]->getPeer()->name());
            }
        }
    }
    DPRINTF(MMU, "port list has %d entries\n", portMap.size());

    // tell all our peers that our address range has changed.
    // Don't tell the device that caused this change, it already knows
    m5::hash_map<short,BusPort*>::iterator intIter;

    for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++)
        if (intIter->first != id && intIter->first != funcPortId)
            intIter->second->sendStatusChange(Port::RangeChange);

    if (id != defaultId && defaultPort)
        defaultPort->sendStatusChange(Port::RangeChange);
    inRecvStatusChange.erase(id);
}

void
Bus::addressRanges(AddrRangeList &resp, bool &snoop, int id)
{
    resp.clear();
    snoop = false;

    DPRINTF(BusAddrRanges, "received address range request, returning:\n");

    for (AddrRangeIter dflt_iter = defaultRange.begin();
         dflt_iter != defaultRange.end(); dflt_iter++) {
        resp.push_back(*dflt_iter);
        DPRINTF(BusAddrRanges, "  -- Dflt: %#llx : %#llx\n",dflt_iter->start,
                dflt_iter->end);
    }
    for (PortIter portIter = portMap.begin();
         portIter != portMap.end(); portIter++) {
        bool subset = false;
        for (AddrRangeIter dflt_iter = defaultRange.begin();
             dflt_iter != defaultRange.end(); dflt_iter++) {
            if ((portIter->first.start < dflt_iter->start &&
                portIter->first.end >= dflt_iter->start) ||
               (portIter->first.start < dflt_iter->end &&
                portIter->first.end >= dflt_iter->end))
                fatal("Devices can not set ranges that itersect the default set\
                        but are not a subset of the default set.\n");
            if (portIter->first.start >= dflt_iter->start &&
                portIter->first.end <= dflt_iter->end) {
                subset = true;
                DPRINTF(BusAddrRanges, "  -- %#llx : %#llx is a SUBSET\n",
                    portIter->first.start, portIter->first.end);
            }
        }
        if (portIter->second != id && !subset) {
            resp.push_back(portIter->first);
            DPRINTF(BusAddrRanges, "  -- %#llx : %#llx\n",
                    portIter->first.start, portIter->first.end);
        }
    }

    for (SnoopIter s_iter = snoopPorts.begin(); s_iter != snoopPorts.end();
         s_iter++) {
        if ((*s_iter)->getId() != id) {
            snoop = true;
            break;
        }
    }
}

int
Bus::findBlockSize(int id)
{
    if (cachedBlockSizeValid)
        return cachedBlockSize;

    int max_bs = -1;

    PortIter p_end = portMap.end();
    for (PortIter p_iter = portMap.begin(); p_iter != p_end; p_iter++) {
        int tmp_bs = interfaces[p_iter->second]->peerBlockSize();
        if (tmp_bs > max_bs)
            max_bs = tmp_bs;
    }
    SnoopIter s_end = snoopPorts.end();
    for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) {
        int tmp_bs = (*s_iter)->peerBlockSize();
        if (tmp_bs > max_bs)
            max_bs = tmp_bs;
    }
    if (max_bs <= 0)
        max_bs = defaultBlockSize;

    if (max_bs != 64)
        warn_once("Blocksize found to not be 64... hmm... probably not.\n");
    cachedBlockSize = max_bs;
    cachedBlockSizeValid = true;
    return max_bs;
}


unsigned int
Bus::drain(Event * de)
{
    //We should check that we're not "doing" anything, and that noone is
    //waiting. We might be idle but have someone waiting if the device we
    //contacted for a retry didn't actually retry.
    if (retryList.size() || (curTick < tickNextIdle && busIdle.scheduled())) {
        drainEvent = de;
        return 1;
    }
    return 0;
}

void
Bus::startup()
{
    if (tickNextIdle < curTick)
        tickNextIdle = (curTick / clock) * clock + clock;
}

Bus *
BusParams::create()
{
    return new Bus(this);
}
