packet_queue.cc revision 10423:cc7f3988c5a9
15148SN/A/* 25148SN/A * Copyright (c) 2012 ARM Limited 35148SN/A * All rights reserved. 410036SN/A * 58835SN/A * The license below extends only to copyright in the software and shall 610036SN/A * not be construed as granting a license to any other intellectual 77873SN/A * property including but not limited to intellectual property relating 87873SN/A * to a hardware implementation of the functionality of the software 97873SN/A * licensed hereunder. You may use the software subject to the license 105148SN/A * terms below provided that you ensure that this notice is replicated 115148SN/A * unmodified and in its entirety in all distributions of the software, 125148SN/A * modified or unmodified, in source code or in binary form. 1310315SN/A * 148835SN/A * Copyright (c) 2006 The Regents of The University of Michigan 159885SN/A * All rights reserved. 169885SN/A * 1711570SCurtis.Dunham@arm.com * Redistribution and use in source and binary forms, with or without 1810036SN/A * modification, are permitted provided that the following conditions are 1911312Santhony.gutierrez@amd.com * met: redistributions of source code must retain the above copyright 208835SN/A * notice, this list of conditions and the following disclaimer; 218835SN/A * redistributions in binary form must reproduce the above copyright 2210315SN/A * notice, this list of conditions and the following disclaimer in the 2311960Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 248835SN/A * neither the name of the copyright holders nor the names of its 2510315SN/A * contributors may be used to endorse or promote products derived from 265148SN/A * this software without specific prior written permission. 279481SN/A * 288673SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2910901Snilay@cs.wisc.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3011219Snilay@cs.wisc.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 318721SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3211570SCurtis.Dunham@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3311570SCurtis.Dunham@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3411570SCurtis.Dunham@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3511570SCurtis.Dunham@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 368835SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 378835SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3811440SCurtis.Dunham@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3911440SCurtis.Dunham@arm.com * 407935SN/A * Authors: Ali Saidi 417935SN/A * Andreas Hansson 427935SN/A */ 437935SN/A 447935SN/A#include "base/trace.hh" 457935SN/A#include "debug/Drain.hh" 467935SN/A#include "debug/PacketQueue.hh" 478983SN/A#include "mem/packet_queue.hh" 485148SN/A 499885SN/Ausing namespace std; 509885SN/A 519885SN/APacketQueue::PacketQueue(EventManager& _em, const std::string& _label) 5210315SN/A : em(_em), sendEvent(this), drainManager(NULL), label(_label), 5310036SN/A waitingOnRetry(false) 5410315SN/A{ 559885SN/A} 569885SN/A 575148SN/APacketQueue::~PacketQueue() 585148SN/A{ 599885SN/A} 6010315SN/A 615876SN/Avoid 629885SN/APacketQueue::retry() 635148SN/A{ 6411570SCurtis.Dunham@arm.com DPRINTF(PacketQueue, "Queue %s received retry\n", name()); 655876SN/A assert(waitingOnRetry); 668835SN/A sendDeferredPacket(); 675876SN/A} 685148SN/A 6910036SN/Abool 708983SN/APacketQueue::checkFunctional(PacketPtr pkt) 715148SN/A{ 725148SN/A pkt->pushLabel(label); 738835SN/A 749481SN/A auto i = transmitList.begin(); 755148SN/A bool found = false; 765148SN/A 775148SN/A while (!found && i != transmitList.end()) { 785148SN/A // If the buffered packet contains data, and it overlaps the 795148SN/A // current packet, then update data 805540SN/A found = pkt->checkFunctional(i->pkt); 8111570SCurtis.Dunham@arm.com ++i; 8211570SCurtis.Dunham@arm.com } 8311570SCurtis.Dunham@arm.com 8411570SCurtis.Dunham@arm.com pkt->popLabel(); 858835SN/A 865148SN/A return found; 879885SN/A} 885509SN/A 895509SN/Avoid 9010315SN/APacketQueue::schedSendEvent(Tick when) 919481SN/A{ 9211960Sgabeblack@google.com // if we are waiting on a retry, do not schedule a send event, and 935148SN/A // instead rely on retry being called 945148SN/A if (waitingOnRetry) { 955148SN/A assert(!sendEvent.scheduled()); 965148SN/A return; 978983SN/A } 988983SN/A 995148SN/A if (!sendEvent.scheduled()) { 1009885SN/A em.schedule(&sendEvent, when); 1019885SN/A } else if (sendEvent.when() > when) { 1029885SN/A em.reschedule(&sendEvent, when); 1039885SN/A } 10410036SN/A} 1059885SN/A 1065148SN/Avoid 1076024SN/APacketQueue::schedSendTiming(PacketPtr pkt, Tick when, bool send_as_snoop) 1088835SN/A{ 10910036SN/A DPRINTF(PacketQueue, "%s for %s address %x size %d\n", __func__, 1105148SN/A pkt->cmdString(), pkt->getAddr(), pkt->getSize()); 1118835SN/A // we can still send a packet before the end of this tick 1128835SN/A assert(when >= curTick()); 1138835SN/A 1148835SN/A // express snoops should never be queued 1159885SN/A assert(!pkt->isExpressSnoop()); 11611570SCurtis.Dunham@arm.com 11710036SN/A // add a very basic sanity check on the port to ensure the 1189885SN/A // invisible buffer is not growing beyond reasonable limits 11911570SCurtis.Dunham@arm.com if (transmitList.size() > 100) { 12011570SCurtis.Dunham@arm.com panic("Packet queue %s has grown beyond 100 packets\n", 12111570SCurtis.Dunham@arm.com name()); 12211570SCurtis.Dunham@arm.com } 1238835SN/A 1248983SN/A // nothing on the list, or earlier than current front element, 1258835SN/A // schedule an event 1268835SN/A if (transmitList.empty() || when < transmitList.front().tick) { 1278835SN/A // note that currently we ignore a potentially outstanding retry 1289885SN/A // and could in theory put a new packet at the head of the 12911570SCurtis.Dunham@arm.com // transmit list before retrying the existing packet 13010036SN/A transmitList.push_front(DeferredPacket(when, pkt, send_as_snoop)); 1318835SN/A schedSendEvent(when); 13211570SCurtis.Dunham@arm.com return; 13311570SCurtis.Dunham@arm.com } 13411570SCurtis.Dunham@arm.com 1358835SN/A // list is non-empty and this belongs at the end 1369213SN/A if (when >= transmitList.back().tick) { 13711570SCurtis.Dunham@arm.com transmitList.push_back(DeferredPacket(when, pkt, send_as_snoop)); 1388835SN/A return; 1398983SN/A } 1408983SN/A 1418983SN/A // this belongs in the middle somewhere, insertion sort 1425148SN/A auto i = transmitList.begin(); 1439481SN/A ++i; // already checked for insertion at front 1449481SN/A while (i != transmitList.end() && when >= i->tick) 14510036SN/A ++i; 1469481SN/A transmitList.insert(i, DeferredPacket(when, pkt, send_as_snoop)); 1475148SN/A} 1486024SN/A 1498835SN/Avoid PacketQueue::trySendTiming() 15010036SN/A{ 1515148SN/A assert(deferredPacketReady()); 1528835SN/A 1538835SN/A DeferredPacket dp = transmitList.front(); 1548835SN/A 1558835SN/A // use the appropriate implementation of sendTiming based on the 1569885SN/A // type of port associated with the queue, and whether the packet 15711570SCurtis.Dunham@arm.com // is to be sent as a snoop or not 15810036SN/A waitingOnRetry = !sendTiming(dp.pkt, dp.sendAsSnoop); 1599885SN/A 16011570SCurtis.Dunham@arm.com if (!waitingOnRetry) { 16111570SCurtis.Dunham@arm.com // take the packet off the list 16211570SCurtis.Dunham@arm.com transmitList.pop_front(); 16311570SCurtis.Dunham@arm.com } 1648835SN/A} 1658983SN/A 1665148SN/Avoid 1675148SN/APacketQueue::scheduleSend(Tick time) 1685148SN/A{ 16910036SN/A // the next ready time is either determined by the next deferred packet, 1705148SN/A // or in the cache through the MSHR ready time 1715148SN/A Tick nextReady = std::max(std::min(deferredPacketReadyTime(), time), 17211960Sgabeblack@google.com curTick() + 1); 1735148SN/A 17410901Snilay@cs.wisc.edu if (nextReady != MaxTick) { 17510645SN/A // if the sendTiming caused someone else to call our 1765148SN/A // recvTiming we could already have an event scheduled, check 1775148SN/A if (!sendEvent.scheduled()) { 1785516SN/A em.schedule(&sendEvent, nextReady); 1795148SN/A } else if (nextReady < sendEvent.when()) { 18010036SN/A // if the new time is earlier than when the event 18111960Sgabeblack@google.com // currently is scheduled, move it forward 1825148SN/A em.reschedule(&sendEvent, nextReady); 1835148SN/A } 18410645SN/A } else { 18511960Sgabeblack@google.com // no more to send, so if we're draining, we may be done 1865148SN/A if (drainManager && transmitList.empty() && !sendEvent.scheduled()) { 18711960Sgabeblack@google.com DPRINTF(Drain, "PacketQueue done draining," 1885148SN/A "processing drain event\n"); 18911960Sgabeblack@google.com drainManager->signalDrainDone(); 1905410SN/A drainManager = NULL; 1915148SN/A } 1925148SN/A } 19310451SN/A} 1945148SN/A 1959885SN/Avoid 1969885SN/APacketQueue::sendDeferredPacket() 1979885SN/A{ 19810315SN/A // try to send what is on the list, this will set waitingOnRetry 19910036SN/A // accordingly 20010315SN/A trySendTiming(); 2019885SN/A 2029885SN/A // if we succeeded and are not waiting for a retry, schedule the 20310315SN/A // next send 20410315SN/A if (!waitingOnRetry) { 20510315SN/A scheduleSend(); 20610315SN/A } 20710315SN/A} 20810315SN/A 20910315SN/Avoid 21010315SN/APacketQueue::processSendEvent() 2115148SN/A{ 21210451SN/A assert(!waitingOnRetry); 21311960Sgabeblack@google.com sendDeferredPacket(); 2149885SN/A} 21511570SCurtis.Dunham@arm.com 21610036SN/Aunsigned int 21710901Snilay@cs.wisc.eduPacketQueue::drain(DrainManager *dm) 21810901Snilay@cs.wisc.edu{ 21911570SCurtis.Dunham@arm.com if (transmitList.empty()) 22011570SCurtis.Dunham@arm.com return 0; 22111570SCurtis.Dunham@arm.com DPRINTF(Drain, "PacketQueue not drained\n"); 22211440SCurtis.Dunham@arm.com drainManager = dm; 22311570SCurtis.Dunham@arm.com return 1; 22410901Snilay@cs.wisc.edu} 22511960Sgabeblack@google.com 22610901Snilay@cs.wisc.eduMasterPacketQueue::MasterPacketQueue(EventManager& _em, MasterPort& _masterPort, 2279583SN/A const std::string _label) 2287524SN/A : PacketQueue(_em, _label), masterPort(_masterPort) 22910901Snilay@cs.wisc.edu{ 2309150SN/A} 2318983SN/A 2325148SN/Abool 23311960Sgabeblack@google.comMasterPacketQueue::sendTiming(PacketPtr pkt, bool send_as_snoop) 23411960Sgabeblack@google.com{ 23511960Sgabeblack@google.com // attempt to send the packet and return according to the outcome 23611960Sgabeblack@google.com if (!send_as_snoop) 23711960Sgabeblack@google.com return masterPort.sendTimingReq(pkt); 23811960Sgabeblack@google.com else 23911960Sgabeblack@google.com return masterPort.sendTimingSnoopResp(pkt); 2405148SN/A} 2418983SN/A 2429373SN/ASlavePacketQueue::SlavePacketQueue(EventManager& _em, SlavePort& _slavePort, 2439885SN/A const std::string _label) 2449885SN/A : PacketQueue(_em, _label), slavePort(_slavePort) 24511570SCurtis.Dunham@arm.com{ 24610036SN/A} 2478983SN/A 24811960Sgabeblack@google.combool 2495540SN/ASlavePacketQueue::sendTiming(PacketPtr pkt, bool send_as_snoop) 2505410SN/A{ 2515509SN/A // we should never have queued snoop requests 25211570SCurtis.Dunham@arm.com assert(!send_as_snoop); 25311570SCurtis.Dunham@arm.com return slavePort.sendTimingResp(pkt); 25411570SCurtis.Dunham@arm.com} 25511570SCurtis.Dunham@arm.com