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