packet_queue.cc revision 12637:bfc3cb9c7e6c
110780SCurtis.Dunham@arm.com/*
27586SAli.Saidi@arm.com * Copyright (c) 2012,2015 ARM Limited
37586SAli.Saidi@arm.com * All rights reserved.
47586SAli.Saidi@arm.com *
57586SAli.Saidi@arm.com * The license below extends only to copyright in the software and shall
67586SAli.Saidi@arm.com * not be construed as granting a license to any other intellectual
77586SAli.Saidi@arm.com * property including but not limited to intellectual property relating
87586SAli.Saidi@arm.com * to a hardware implementation of the functionality of the software
97586SAli.Saidi@arm.com * licensed hereunder.  You may use the software subject to the license
107586SAli.Saidi@arm.com * terms below provided that you ensure that this notice is replicated
117586SAli.Saidi@arm.com * unmodified and in its entirety in all distributions of the software,
127586SAli.Saidi@arm.com * modified or unmodified, in source code or in binary form.
137905SBrad.Beckmann@amd.com *
145323Sgblack@eecs.umich.edu * Copyright (c) 2006 The Regents of The University of Michigan
152934Sktlim@umich.edu * All rights reserved.
162934Sktlim@umich.edu *
172934Sktlim@umich.edu * Redistribution and use in source and binary forms, with or without
182934Sktlim@umich.edu * modification, are permitted provided that the following conditions are
192934Sktlim@umich.edu * met: redistributions of source code must retain the above copyright
202934Sktlim@umich.edu * notice, this list of conditions and the following disclaimer;
212934Sktlim@umich.edu * redistributions in binary form must reproduce the above copyright
222934Sktlim@umich.edu * notice, this list of conditions and the following disclaimer in the
232934Sktlim@umich.edu * documentation and/or other materials provided with the distribution;
242934Sktlim@umich.edu * neither the name of the copyright holders nor the names of its
252934Sktlim@umich.edu * contributors may be used to endorse or promote products derived from
262934Sktlim@umich.edu * this software without specific prior written permission.
272934Sktlim@umich.edu *
282934Sktlim@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
292934Sktlim@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
302934Sktlim@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
312934Sktlim@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
322934Sktlim@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
332934Sktlim@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
342934Sktlim@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
352934Sktlim@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
362934Sktlim@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
372934Sktlim@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
382934Sktlim@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
392934Sktlim@umich.edu *
402934Sktlim@umich.edu * Authors: Ali Saidi
412934Sktlim@umich.edu *          Andreas Hansson
422934Sktlim@umich.edu */
432995Ssaidi@eecs.umich.edu
4410046Snilay@cs.wisc.edu#include "mem/packet_queue.hh"
4511238Sandreas.sandberg@arm.com
462934Sktlim@umich.edu#include "base/trace.hh"
4710747SChris.Emmons@arm.com#include "debug/Drain.hh"
4810747SChris.Emmons@arm.com#include "debug/PacketQueue.hh"
4910747SChris.Emmons@arm.com
5010747SChris.Emmons@arm.comPacketQueue::PacketQueue(EventManager& _em, const std::string& _label,
5110747SChris.Emmons@arm.com                         const std::string& _sendEventName,
5210747SChris.Emmons@arm.com                         bool disable_sanity_check)
5310747SChris.Emmons@arm.com    : em(_em), sendEvent([this]{ processSendEvent(); }, _sendEventName),
5410747SChris.Emmons@arm.com      _disableSanityCheck(disable_sanity_check),
5510747SChris.Emmons@arm.com      label(_label), waitingOnRetry(false)
5610747SChris.Emmons@arm.com{
5710747SChris.Emmons@arm.com}
5810747SChris.Emmons@arm.com
592934Sktlim@umich.eduPacketQueue::~PacketQueue()
602934Sktlim@umich.edu{
612934Sktlim@umich.edu}
622934Sktlim@umich.edu
632934Sktlim@umich.eduvoid
642934Sktlim@umich.eduPacketQueue::retry()
652934Sktlim@umich.edu{
6610720Sandreas.hansson@arm.com    DPRINTF(PacketQueue, "Queue %s received retry\n", name());
676122SSteve.Reinhardt@amd.com    assert(waitingOnRetry);
686122SSteve.Reinhardt@amd.com    waitingOnRetry = false;
696122SSteve.Reinhardt@amd.com    sendDeferredPacket();
7010594Sgabeblack@google.com}
7110594Sgabeblack@google.com
7210697SCurtis.Dunham@arm.combool
7310594Sgabeblack@google.comPacketQueue::hasAddr(Addr addr) const
7410594Sgabeblack@google.com{
7510594Sgabeblack@google.com    // caller is responsible for ensuring that all packets have the
7610594Sgabeblack@google.com    // same alignment
7710594Sgabeblack@google.com    for (const auto& p : transmitList) {
7810118Snilay@cs.wisc.edu        if (p.pkt->getAddr() == addr)
794520Ssaidi@eecs.umich.edu            return true;
804982Ssaidi@eecs.umich.edu    }
814520Ssaidi@eecs.umich.edu    return false;
824520Ssaidi@eecs.umich.edu}
832934Sktlim@umich.edu
842934Sktlim@umich.edubool
853005Sstever@eecs.umich.eduPacketQueue::checkFunctional(PacketPtr pkt)
863005Sstever@eecs.umich.edu{
873304Sstever@eecs.umich.edu    pkt->pushLabel(label);
882995Ssaidi@eecs.umich.edu
8910118Snilay@cs.wisc.edu    auto i = transmitList.begin();
9010118Snilay@cs.wisc.edu    bool found = false;
9110118Snilay@cs.wisc.edu
9210118Snilay@cs.wisc.edu    while (!found && i != transmitList.end()) {
9310720Sandreas.hansson@arm.com        // If the buffered packet contains data, and it overlaps the
9410118Snilay@cs.wisc.edu        // current packet, then update data
9510118Snilay@cs.wisc.edu        found = pkt->checkFunctional(i->pkt);
9610118Snilay@cs.wisc.edu        ++i;
9710118Snilay@cs.wisc.edu    }
9810118Snilay@cs.wisc.edu
9910118Snilay@cs.wisc.edu    pkt->popLabel();
10010118Snilay@cs.wisc.edu
10110118Snilay@cs.wisc.edu    return found;
10210118Snilay@cs.wisc.edu}
10310118Snilay@cs.wisc.edu
10410118Snilay@cs.wisc.eduvoid
10510118Snilay@cs.wisc.eduPacketQueue::schedSendTiming(PacketPtr pkt, Tick when, bool force_order)
10610118Snilay@cs.wisc.edu{
10710118Snilay@cs.wisc.edu    DPRINTF(PacketQueue, "%s for %s address %x size %d when %lu ord: %i\n",
10810118Snilay@cs.wisc.edu            __func__, pkt->cmdString(), pkt->getAddr(), pkt->getSize(), when,
10910118Snilay@cs.wisc.edu            force_order);
11010118Snilay@cs.wisc.edu
1118713Sandreas.hansson@arm.com    // we can still send a packet before the end of this tick
11210118Snilay@cs.wisc.edu    assert(when >= curTick());
11310118Snilay@cs.wisc.edu
11410118Snilay@cs.wisc.edu    // express snoops should never be queued
11510118Snilay@cs.wisc.edu    assert(!pkt->isExpressSnoop());
11610118Snilay@cs.wisc.edu
11710118Snilay@cs.wisc.edu    // add a very basic sanity check on the port to ensure the
11810118Snilay@cs.wisc.edu    // invisible buffer is not growing beyond reasonable limits
11910118Snilay@cs.wisc.edu    if (!_disableSanityCheck && transmitList.size() > 100) {
1209826Sandreas.hansson@arm.com        panic("Packet queue %s has grown beyond 100 packets\n",
1212934Sktlim@umich.edu              name());
1222934Sktlim@umich.edu    }
1232995Ssaidi@eecs.umich.edu
1242934Sktlim@umich.edu    // nothing on the list
1256765SBrad.Beckmann@amd.com    if (transmitList.empty()) {
1266765SBrad.Beckmann@amd.com        transmitList.emplace_front(when, pkt);
1276765SBrad.Beckmann@amd.com        schedSendEvent(when);
1286765SBrad.Beckmann@amd.com        return;
1296765SBrad.Beckmann@amd.com    }
1306765SBrad.Beckmann@amd.com
1316765SBrad.Beckmann@amd.com    // we should either have an outstanding retry, or a send event
1326765SBrad.Beckmann@amd.com    // scheduled, but there is an unfortunate corner case where the
13310594Sgabeblack@google.com    // x86 page-table walker and timing CPU send out a new request as
13410594Sgabeblack@google.com    // part of the receiving of a response (called by
13510594Sgabeblack@google.com    // PacketQueue::sendDeferredPacket), in which we end up calling
1366765SBrad.Beckmann@amd.com    // ourselves again before we had a chance to update waitingOnRetry
1376765SBrad.Beckmann@amd.com    // assert(waitingOnRetry || sendEvent.scheduled());
1386765SBrad.Beckmann@amd.com
13911182Spalle@lyckegaard.dk    // this belongs in the middle somewhere, so search from the end to
1408713Sandreas.hansson@arm.com    // order by tick; however, if force_order is set, also make sure
1418713Sandreas.hansson@arm.com    // not to re-order in front of some existing packet with the same
1428713Sandreas.hansson@arm.com    // address
1438713Sandreas.hansson@arm.com    auto i = transmitList.end();
1444486Sbinkertn@umich.edu    --i;
1454486Sbinkertn@umich.edu    while (i != transmitList.begin() && when < i->tick &&
1464486Sbinkertn@umich.edu           !(force_order && i->pkt->getAddr() == pkt->getAddr()))
1474486Sbinkertn@umich.edu        --i;
1484486Sbinkertn@umich.edu
1494486Sbinkertn@umich.edu    // emplace inserts the element before the position pointed to by
1504486Sbinkertn@umich.edu    // the iterator, so advance it one step
1513584Ssaidi@eecs.umich.edu    transmitList.emplace(++i, when, pkt);
1523584Ssaidi@eecs.umich.edu}
1533584Ssaidi@eecs.umich.edu
1543584Ssaidi@eecs.umich.eduvoid
1553584Ssaidi@eecs.umich.eduPacketQueue::schedSendEvent(Tick when)
15610720Sandreas.hansson@arm.com{
1579036Sandreas.hansson@arm.com    // if we are waiting on a retry just hold off
1589164Sandreas.hansson@arm.com    if (waitingOnRetry) {
1593743Sgblack@eecs.umich.edu        DPRINTF(PacketQueue, "Not scheduling send as waiting for retry\n");
1604104Ssaidi@eecs.umich.edu        assert(!sendEvent.scheduled());
1613743Sgblack@eecs.umich.edu        return;
1629826Sandreas.hansson@arm.com    }
1639826Sandreas.hansson@arm.com
1648839Sandreas.hansson@arm.com    if (when != MaxTick) {
1658839Sandreas.hansson@arm.com        // we cannot go back in time, and to be consistent we stick to
1668839Sandreas.hansson@arm.com        // one tick in the future
1678839Sandreas.hansson@arm.com        when = std::max(when, curTick() + 1);
1688839Sandreas.hansson@arm.com        // @todo Revisit the +1
1698839Sandreas.hansson@arm.com
1703584Ssaidi@eecs.umich.edu        if (!sendEvent.scheduled()) {
1713898Ssaidi@eecs.umich.edu            em.schedule(&sendEvent, when);
1723898Ssaidi@eecs.umich.edu        } else if (when < sendEvent.when()) {
1738839Sandreas.hansson@arm.com            // if the new time is earlier than when the event
1748713Sandreas.hansson@arm.com            // currently is scheduled, move it forward
1758713Sandreas.hansson@arm.com            em.reschedule(&sendEvent, when);
1768713Sandreas.hansson@arm.com        }
1778713Sandreas.hansson@arm.com    } else {
1788713Sandreas.hansson@arm.com        // we get a MaxTick when there is no more to send, so if we're
1798713Sandreas.hansson@arm.com        // draining, we may be done at this point
1808713Sandreas.hansson@arm.com        if (drainState() == DrainState::Draining &&
1818713Sandreas.hansson@arm.com            transmitList.empty() && !sendEvent.scheduled()) {
1828713Sandreas.hansson@arm.com
1838713Sandreas.hansson@arm.com            DPRINTF(Drain, "PacketQueue done draining,"
1848713Sandreas.hansson@arm.com                    "processing drain event\n");
1858713Sandreas.hansson@arm.com            signalDrainDone();
1868713Sandreas.hansson@arm.com        }
1878713Sandreas.hansson@arm.com    }
1888713Sandreas.hansson@arm.com}
1898713Sandreas.hansson@arm.com
1908713Sandreas.hansson@arm.comvoid
1918713Sandreas.hansson@arm.comPacketQueue::sendDeferredPacket()
1928713Sandreas.hansson@arm.com{
1934103Ssaidi@eecs.umich.edu    // sanity checks
1944103Ssaidi@eecs.umich.edu    assert(!waitingOnRetry);
1954103Ssaidi@eecs.umich.edu    assert(deferredPacketReady());
1963745Sgblack@eecs.umich.edu
1973745Sgblack@eecs.umich.edu    DeferredPacket dp = transmitList.front();
1983745Sgblack@eecs.umich.edu
1993584Ssaidi@eecs.umich.edu    // take the packet of the list before sending it, as sending of
2008839Sandreas.hansson@arm.com    // the packet in some cases causes a new packet to be enqueued
2018706Sandreas.hansson@arm.com    // (most notaly when responding to the timing CPU, leading to a
2023584Ssaidi@eecs.umich.edu    // new request hitting in the L1 icache, leading to a new
2033584Ssaidi@eecs.umich.edu    // response)
20410588Sgabeblack@google.com    transmitList.pop_front();
20510780SCurtis.Dunham@arm.com
20610780SCurtis.Dunham@arm.com    // use the appropriate implementation of sendTiming based on the
2078061SAli.Saidi@ARM.com    // type of queue
2088061SAli.Saidi@ARM.com    waitingOnRetry = !sendTiming(dp.pkt);
20911238Sandreas.sandberg@arm.com
21011238Sandreas.sandberg@arm.com    // if we succeeded and are not waiting for a retry, schedule the
21111238Sandreas.sandberg@arm.com    // next send
21211238Sandreas.sandberg@arm.com    if (!waitingOnRetry) {
21311238Sandreas.sandberg@arm.com        schedSendEvent(deferredPacketReadyTime());
21411238Sandreas.sandberg@arm.com    } else {
21511238Sandreas.sandberg@arm.com        // put the packet back at the front of the list
21611238Sandreas.sandberg@arm.com        transmitList.emplace_front(dp);
21711238Sandreas.sandberg@arm.com    }
21811238Sandreas.sandberg@arm.com}
21911238Sandreas.sandberg@arm.com
22011238Sandreas.sandberg@arm.comvoid
22111238Sandreas.sandberg@arm.comPacketQueue::processSendEvent()
22211238Sandreas.sandberg@arm.com{
22311297Sandreas.sandberg@arm.com    assert(!waitingOnRetry);
22411297Sandreas.sandberg@arm.com    sendDeferredPacket();
2257586SAli.Saidi@arm.com}
2267586SAli.Saidi@arm.com
2277586SAli.Saidi@arm.comDrainState
2287586SAli.Saidi@arm.comPacketQueue::drain()
2297586SAli.Saidi@arm.com{
2307586SAli.Saidi@arm.com    if (transmitList.empty()) {
2317586SAli.Saidi@arm.com        return DrainState::Drained;
2327586SAli.Saidi@arm.com    } else {
2337586SAli.Saidi@arm.com        DPRINTF(Drain, "PacketQueue not drained\n");
2347586SAli.Saidi@arm.com        return DrainState::Draining;
23510720Sandreas.hansson@arm.com    }
2369036Sandreas.hansson@arm.com}
2377586SAli.Saidi@arm.com
2389164Sandreas.hansson@arm.comReqPacketQueue::ReqPacketQueue(EventManager& _em, MasterPort& _masterPort,
2398839Sandreas.hansson@arm.com                               const std::string _label)
2408839Sandreas.hansson@arm.com    : PacketQueue(_em, _label, name(_masterPort, _label)),
2417586SAli.Saidi@arm.com      masterPort(_masterPort)
2427586SAli.Saidi@arm.com{
2437586SAli.Saidi@arm.com}
24411238Sandreas.sandberg@arm.com
24511238Sandreas.sandberg@arm.combool
24611238Sandreas.sandberg@arm.comReqPacketQueue::sendTiming(PacketPtr pkt)
24711238Sandreas.sandberg@arm.com{
24811238Sandreas.sandberg@arm.com    return masterPort.sendTimingReq(pkt);
24911238Sandreas.sandberg@arm.com}
25011238Sandreas.sandberg@arm.com
25111238Sandreas.sandberg@arm.comSnoopRespPacketQueue::SnoopRespPacketQueue(EventManager& _em,
25211238Sandreas.sandberg@arm.com                                           MasterPort& _masterPort,
25311238Sandreas.sandberg@arm.com                                           const std::string _label)
25411238Sandreas.sandberg@arm.com    : PacketQueue(_em, _label, name(_masterPort, _label)),
25511238Sandreas.sandberg@arm.com      masterPort(_masterPort)
25611238Sandreas.sandberg@arm.com{
25711238Sandreas.sandberg@arm.com}
25810512SAli.Saidi@ARM.com
25910512SAli.Saidi@ARM.combool
26010512SAli.Saidi@ARM.comSnoopRespPacketQueue::sendTiming(PacketPtr pkt)
2617586SAli.Saidi@arm.com{
26210353SGeoffrey.Blake@arm.com    return masterPort.sendTimingSnoopResp(pkt);
26310353SGeoffrey.Blake@arm.com}
26410353SGeoffrey.Blake@arm.com
26511297Sandreas.sandberg@arm.comRespPacketQueue::RespPacketQueue(EventManager& _em, SlavePort& _slavePort,
26611297Sandreas.sandberg@arm.com                                 const std::string _label)
26711297Sandreas.sandberg@arm.com    : PacketQueue(_em, _label, name(_slavePort, _label)),
26811297Sandreas.sandberg@arm.com      slavePort(_slavePort)
26911297Sandreas.sandberg@arm.com{
27011297Sandreas.sandberg@arm.com}
27111297Sandreas.sandberg@arm.com
27210357SAli.Saidi@ARM.combool
27311297Sandreas.sandberg@arm.comRespPacketQueue::sendTiming(PacketPtr pkt)
2748528SAli.Saidi@ARM.com{
27511297Sandreas.sandberg@arm.com    return slavePort.sendTimingResp(pkt);
27611297Sandreas.sandberg@arm.com}
27711297Sandreas.sandberg@arm.com