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