packet_queue.cc revision 11207
15409Sgblack@eecs.umich.edu/*
24519Sgblack@eecs.umich.edu * Copyright (c) 2012,2015 ARM Limited
34519Sgblack@eecs.umich.edu * All rights reserved.
47087Snate@binkert.org *
57087Snate@binkert.org * The license below extends only to copyright in the software and shall
67087Snate@binkert.org * not be construed as granting a license to any other intellectual
77087Snate@binkert.org * property including but not limited to intellectual property relating
87087Snate@binkert.org * to a hardware implementation of the functionality of the software
97087Snate@binkert.org * licensed hereunder.  You may use the software subject to the license
107087Snate@binkert.org * terms below provided that you ensure that this notice is replicated
117087Snate@binkert.org * unmodified and in its entirety in all distributions of the software,
124519Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form.
137087Snate@binkert.org *
147087Snate@binkert.org * Copyright (c) 2006 The Regents of The University of Michigan
157087Snate@binkert.org * All rights reserved.
167087Snate@binkert.org *
177087Snate@binkert.org * Redistribution and use in source and binary forms, with or without
187087Snate@binkert.org * modification, are permitted provided that the following conditions are
197087Snate@binkert.org * met: redistributions of source code must retain the above copyright
207087Snate@binkert.org * notice, this list of conditions and the following disclaimer;
214519Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
227087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the
234519Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
244519Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
254519Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
264519Sgblack@eecs.umich.edu * this software without specific prior written permission.
274519Sgblack@eecs.umich.edu *
284519Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
294519Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
304519Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
314519Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
324519Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
334519Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
344519Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
354519Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
364519Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
374519Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
384519Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
394519Sgblack@eecs.umich.edu *
404519Sgblack@eecs.umich.edu * Authors: Ali Saidi
414519Sgblack@eecs.umich.edu *          Andreas Hansson
424519Sgblack@eecs.umich.edu */
434519Sgblack@eecs.umich.edu
444519Sgblack@eecs.umich.edu#include "base/trace.hh"
454519Sgblack@eecs.umich.edu#include "debug/Drain.hh"
464519Sgblack@eecs.umich.edu#include "debug/PacketQueue.hh"
474519Sgblack@eecs.umich.edu#include "mem/packet_queue.hh"
484519Sgblack@eecs.umich.edu
494519Sgblack@eecs.umich.eduusing namespace std;
504809Sgblack@eecs.umich.edu
514519Sgblack@eecs.umich.eduPacketQueue::PacketQueue(EventManager& _em, const std::string& _label,
524519Sgblack@eecs.umich.edu                         bool disable_sanity_check)
534688Sgblack@eecs.umich.edu    : em(_em), sendEvent(this), _disableSanityCheck(disable_sanity_check),
544688Sgblack@eecs.umich.edu      label(_label), waitingOnRetry(false)
554688Sgblack@eecs.umich.edu{
564688Sgblack@eecs.umich.edu}
574688Sgblack@eecs.umich.edu
584688Sgblack@eecs.umich.eduPacketQueue::~PacketQueue()
594708Sgblack@eecs.umich.edu{
604708Sgblack@eecs.umich.edu}
614708Sgblack@eecs.umich.edu
624708Sgblack@eecs.umich.eduvoid
634519Sgblack@eecs.umich.eduPacketQueue::retry()
644519Sgblack@eecs.umich.edu{
654519Sgblack@eecs.umich.edu    DPRINTF(PacketQueue, "Queue %s received retry\n", name());
664519Sgblack@eecs.umich.edu    assert(waitingOnRetry);
674519Sgblack@eecs.umich.edu    waitingOnRetry = false;
684519Sgblack@eecs.umich.edu    sendDeferredPacket();
694519Sgblack@eecs.umich.edu}
704519Sgblack@eecs.umich.edu
714519Sgblack@eecs.umich.edubool
724519Sgblack@eecs.umich.eduPacketQueue::hasAddr(Addr addr) const
734519Sgblack@eecs.umich.edu{
744951Sgblack@eecs.umich.edu    // caller is responsible for ensuring that all packets have the
754519Sgblack@eecs.umich.edu    // same alignment
764519Sgblack@eecs.umich.edu    for (const auto& p : transmitList) {
774519Sgblack@eecs.umich.edu        if (p.pkt->getAddr() == addr)
784519Sgblack@eecs.umich.edu            return true;
794519Sgblack@eecs.umich.edu    }
804519Sgblack@eecs.umich.edu    return false;
814688Sgblack@eecs.umich.edu}
824688Sgblack@eecs.umich.edu
834688Sgblack@eecs.umich.edubool
844688Sgblack@eecs.umich.eduPacketQueue::checkFunctional(PacketPtr pkt)
854688Sgblack@eecs.umich.edu{
864688Sgblack@eecs.umich.edu    pkt->pushLabel(label);
874708Sgblack@eecs.umich.edu
884708Sgblack@eecs.umich.edu    auto i = transmitList.begin();
894708Sgblack@eecs.umich.edu    bool found = false;
904708Sgblack@eecs.umich.edu
914519Sgblack@eecs.umich.edu    while (!found && i != transmitList.end()) {
924519Sgblack@eecs.umich.edu        // If the buffered packet contains data, and it overlaps the
934519Sgblack@eecs.umich.edu        // current packet, then update data
944519Sgblack@eecs.umich.edu        found = pkt->checkFunctional(i->pkt);
954519Sgblack@eecs.umich.edu        ++i;
964519Sgblack@eecs.umich.edu    }
974519Sgblack@eecs.umich.edu
984519Sgblack@eecs.umich.edu    pkt->popLabel();
994519Sgblack@eecs.umich.edu
1004519Sgblack@eecs.umich.edu    return found;
1014519Sgblack@eecs.umich.edu}
1024519Sgblack@eecs.umich.edu
1034519Sgblack@eecs.umich.eduvoid
1044519Sgblack@eecs.umich.eduPacketQueue::schedSendTiming(PacketPtr pkt, Tick when, bool force_order)
1054519Sgblack@eecs.umich.edu{
1067620Sgblack@eecs.umich.edu    DPRINTF(PacketQueue, "%s for %s address %x size %d when %lu ord: %i\n",
1076345Sgblack@eecs.umich.edu            __func__, pkt->cmdString(), pkt->getAddr(), pkt->getSize(), when,
1084712Sgblack@eecs.umich.edu            force_order);
1094519Sgblack@eecs.umich.edu
1104519Sgblack@eecs.umich.edu    // we can still send a packet before the end of this tick
1114519Sgblack@eecs.umich.edu    assert(when >= curTick());
1124519Sgblack@eecs.umich.edu
1134519Sgblack@eecs.umich.edu    // express snoops should never be queued
1144519Sgblack@eecs.umich.edu    assert(!pkt->isExpressSnoop());
1154519Sgblack@eecs.umich.edu
1164951Sgblack@eecs.umich.edu    // add a very basic sanity check on the port to ensure the
1174519Sgblack@eecs.umich.edu    // invisible buffer is not growing beyond reasonable limits
1184519Sgblack@eecs.umich.edu    if (!_disableSanityCheck && transmitList.size() > 100) {
1194951Sgblack@eecs.umich.edu        panic("Packet queue %s has grown beyond 100 packets\n",
1207620Sgblack@eecs.umich.edu              name());
1216646Sgblack@eecs.umich.edu    }
1224712Sgblack@eecs.umich.edu
1234519Sgblack@eecs.umich.edu    // nothing on the list
1244519Sgblack@eecs.umich.edu    if (transmitList.empty()) {
1254519Sgblack@eecs.umich.edu        transmitList.emplace_front(when, pkt);
1264519Sgblack@eecs.umich.edu        schedSendEvent(when);
1274519Sgblack@eecs.umich.edu        return;
1284519Sgblack@eecs.umich.edu    }
1294519Sgblack@eecs.umich.edu
1307620Sgblack@eecs.umich.edu    // we should either have an outstanding retry, or a send event
1316345Sgblack@eecs.umich.edu    // scheduled, but there is an unfortunate corner case where the
1324712Sgblack@eecs.umich.edu    // x86 page-table walker and timing CPU send out a new request as
1337620Sgblack@eecs.umich.edu    // part of the receiving of a response (called by
1344688Sgblack@eecs.umich.edu    // PacketQueue::sendDeferredPacket), in which we end up calling
1354581Sgblack@eecs.umich.edu    // ourselves again before we had a chance to update waitingOnRetry
1364519Sgblack@eecs.umich.edu    // assert(waitingOnRetry || sendEvent.scheduled());
1377626Sgblack@eecs.umich.edu
1387894SBrad.Beckmann@amd.com    // this belongs in the middle somewhere, so search from the end to
1394519Sgblack@eecs.umich.edu    // order by tick; however, if force_order is set, also make sure
1404519Sgblack@eecs.umich.edu    // not to re-order in front of some existing packet with the same
1414519Sgblack@eecs.umich.edu    // address
1424519Sgblack@eecs.umich.edu    auto i = transmitList.end();
1434951Sgblack@eecs.umich.edu    --i;
1447620Sgblack@eecs.umich.edu    while (i != transmitList.begin() && when < i->tick &&
1456646Sgblack@eecs.umich.edu           !(force_order && i->pkt->getAddr() == pkt->getAddr()))
1464712Sgblack@eecs.umich.edu        --i;
1477620Sgblack@eecs.umich.edu
1484688Sgblack@eecs.umich.edu    // emplace inserts the element before the position pointed to by
1494581Sgblack@eecs.umich.edu    // the iterator, so advance it one step
1504519Sgblack@eecs.umich.edu    transmitList.emplace(++i, when, pkt);
1517626Sgblack@eecs.umich.edu}
1527894SBrad.Beckmann@amd.com
1534519Sgblack@eecs.umich.eduvoid
1544519Sgblack@eecs.umich.eduPacketQueue::schedSendEvent(Tick when)
1554519Sgblack@eecs.umich.edu{
1565075Sgblack@eecs.umich.edu    // if we are waiting on a retry just hold off
1575075Sgblack@eecs.umich.edu    if (waitingOnRetry) {
1585075Sgblack@eecs.umich.edu        DPRINTF(PacketQueue, "Not scheduling send as waiting for retry\n");
1595075Sgblack@eecs.umich.edu        assert(!sendEvent.scheduled());
1605428Sgblack@eecs.umich.edu        return;
1615428Sgblack@eecs.umich.edu    }
1625674Sgblack@eecs.umich.edu
1635899Sgblack@eecs.umich.edu    if (when != MaxTick) {
1645936Sgblack@eecs.umich.edu        // we cannot go back in time, and to be consistent we stick to
1655428Sgblack@eecs.umich.edu        // one tick in the future
1665678Sgblack@eecs.umich.edu        when = std::max(when, curTick() + 1);
1675678Sgblack@eecs.umich.edu        // @todo Revisit the +1
1685678Sgblack@eecs.umich.edu
1695678Sgblack@eecs.umich.edu        if (!sendEvent.scheduled()) {
1705678Sgblack@eecs.umich.edu            em.schedule(&sendEvent, when);
1715678Sgblack@eecs.umich.edu        } else if (when < sendEvent.when()) {
1725678Sgblack@eecs.umich.edu            // if the new time is earlier than when the event
1735678Sgblack@eecs.umich.edu            // currently is scheduled, move it forward
1745678Sgblack@eecs.umich.edu            em.reschedule(&sendEvent, when);
1755075Sgblack@eecs.umich.edu        }
1765075Sgblack@eecs.umich.edu    } else {
1775075Sgblack@eecs.umich.edu        // we get a MaxTick when there is no more to send, so if we're
1785075Sgblack@eecs.umich.edu        // draining, we may be done at this point
1795075Sgblack@eecs.umich.edu        if (drainState() == DrainState::Draining &&
1805075Sgblack@eecs.umich.edu            transmitList.empty() && !sendEvent.scheduled()) {
1815075Sgblack@eecs.umich.edu
1825075Sgblack@eecs.umich.edu            DPRINTF(Drain, "PacketQueue done draining,"
1837719Sgblack@eecs.umich.edu                    "processing drain event\n");
1845075Sgblack@eecs.umich.edu            signalDrainDone();
1855075Sgblack@eecs.umich.edu        }
1865075Sgblack@eecs.umich.edu    }
1875075Sgblack@eecs.umich.edu}
1885075Sgblack@eecs.umich.edu
1895075Sgblack@eecs.umich.eduvoid
1905075Sgblack@eecs.umich.eduPacketQueue::sendDeferredPacket()
1915075Sgblack@eecs.umich.edu{
1925075Sgblack@eecs.umich.edu    // sanity checks
1935075Sgblack@eecs.umich.edu    assert(!waitingOnRetry);
1945075Sgblack@eecs.umich.edu    assert(deferredPacketReady());
1955075Sgblack@eecs.umich.edu
1965075Sgblack@eecs.umich.edu    DeferredPacket dp = transmitList.front();
1975075Sgblack@eecs.umich.edu
1985075Sgblack@eecs.umich.edu    // take the packet of the list before sending it, as sending of
1995075Sgblack@eecs.umich.edu    // the packet in some cases causes a new packet to be enqueued
2005075Sgblack@eecs.umich.edu    // (most notaly when responding to the timing CPU, leading to a
2015075Sgblack@eecs.umich.edu    // new request hitting in the L1 icache, leading to a new
2025075Sgblack@eecs.umich.edu    // response)
2035075Sgblack@eecs.umich.edu    transmitList.pop_front();
2045075Sgblack@eecs.umich.edu
2055075Sgblack@eecs.umich.edu    // use the appropriate implementation of sendTiming based on the
2065075Sgblack@eecs.umich.edu    // type of queue
2075075Sgblack@eecs.umich.edu    waitingOnRetry = !sendTiming(dp.pkt);
2085075Sgblack@eecs.umich.edu
2094519Sgblack@eecs.umich.edu    // if we succeeded and are not waiting for a retry, schedule the
2105040Sgblack@eecs.umich.edu    // next send
2115040Sgblack@eecs.umich.edu    if (!waitingOnRetry) {
2125040Sgblack@eecs.umich.edu        schedSendEvent(deferredPacketReadyTime());
2135040Sgblack@eecs.umich.edu    } else {
2145040Sgblack@eecs.umich.edu        // put the packet back at the front of the list
2155040Sgblack@eecs.umich.edu        transmitList.emplace_front(dp);
2165040Sgblack@eecs.umich.edu    }
2175040Sgblack@eecs.umich.edu}
2185040Sgblack@eecs.umich.edu
2195040Sgblack@eecs.umich.eduvoid
2205040Sgblack@eecs.umich.eduPacketQueue::processSendEvent()
2215040Sgblack@eecs.umich.edu{
2225040Sgblack@eecs.umich.edu    assert(!waitingOnRetry);
2235040Sgblack@eecs.umich.edu    sendDeferredPacket();
2245040Sgblack@eecs.umich.edu}
2255040Sgblack@eecs.umich.edu
2265040Sgblack@eecs.umich.eduDrainState
2277967Sgblack@eecs.umich.eduPacketQueue::drain()
2287967Sgblack@eecs.umich.edu{
2295040Sgblack@eecs.umich.edu    if (transmitList.empty()) {
2305040Sgblack@eecs.umich.edu        return DrainState::Drained;
2315040Sgblack@eecs.umich.edu    } else {
2325040Sgblack@eecs.umich.edu        DPRINTF(Drain, "PacketQueue not drained\n");
2335040Sgblack@eecs.umich.edu        return DrainState::Draining;
2345040Sgblack@eecs.umich.edu    }
2355040Sgblack@eecs.umich.edu}
2367894SBrad.Beckmann@amd.com
2377894SBrad.Beckmann@amd.comReqPacketQueue::ReqPacketQueue(EventManager& _em, MasterPort& _masterPort,
2387967Sgblack@eecs.umich.edu                               const std::string _label)
2397967Sgblack@eecs.umich.edu    : PacketQueue(_em, _label), masterPort(_masterPort)
2405040Sgblack@eecs.umich.edu{
2415040Sgblack@eecs.umich.edu}
2425040Sgblack@eecs.umich.edu
2435062Sgblack@eecs.umich.edubool
2447967Sgblack@eecs.umich.eduReqPacketQueue::sendTiming(PacketPtr pkt)
2455062Sgblack@eecs.umich.edu{
2465062Sgblack@eecs.umich.edu    return masterPort.sendTimingReq(pkt);
2475062Sgblack@eecs.umich.edu}
2485062Sgblack@eecs.umich.edu
2495062Sgblack@eecs.umich.eduSnoopRespPacketQueue::SnoopRespPacketQueue(EventManager& _em,
2505040Sgblack@eecs.umich.edu                                           MasterPort& _masterPort,
2515062Sgblack@eecs.umich.edu                                           const std::string _label)
2527967Sgblack@eecs.umich.edu    : PacketQueue(_em, _label), masterPort(_masterPort)
2535062Sgblack@eecs.umich.edu{
2545062Sgblack@eecs.umich.edu}
2557894SBrad.Beckmann@amd.com
2567894SBrad.Beckmann@amd.combool
2576647Sgblack@eecs.umich.eduSnoopRespPacketQueue::sendTiming(PacketPtr pkt)
2585040Sgblack@eecs.umich.edu{
2596647Sgblack@eecs.umich.edu    return masterPort.sendTimingSnoopResp(pkt);
2607967Sgblack@eecs.umich.edu}
2616647Sgblack@eecs.umich.edu
2626647Sgblack@eecs.umich.eduRespPacketQueue::RespPacketQueue(EventManager& _em, SlavePort& _slavePort,
2637894SBrad.Beckmann@amd.com                                 const std::string _label)
2647894SBrad.Beckmann@amd.com    : PacketQueue(_em, _label), slavePort(_slavePort)
2655040Sgblack@eecs.umich.edu{
2665040Sgblack@eecs.umich.edu}
2675040Sgblack@eecs.umich.edu
2685040Sgblack@eecs.umich.edubool
2695239Sgblack@eecs.umich.eduRespPacketQueue::sendTiming(PacketPtr pkt)
2705040Sgblack@eecs.umich.edu{
2717967Sgblack@eecs.umich.edu    return slavePort.sendTimingResp(pkt);
2725040Sgblack@eecs.umich.edu}
2735040Sgblack@eecs.umich.edu