packet_queue.cc revision 4666
1955SN/A/* 2955SN/A * Copyright (c) 2006 The Regents of The University of Michigan 31762SN/A * All rights reserved. 4955SN/A * 5955SN/A * Redistribution and use in source and binary forms, with or without 6955SN/A * modification, are permitted provided that the following conditions are 7955SN/A * met: redistributions of source code must retain the above copyright 8955SN/A * notice, this list of conditions and the following disclaimer; 9955SN/A * redistributions in binary form must reproduce the above copyright 10955SN/A * notice, this list of conditions and the following disclaimer in the 11955SN/A * documentation and/or other materials provided with the distribution; 12955SN/A * neither the name of the copyright holders nor the names of its 13955SN/A * contributors may be used to endorse or promote products derived from 14955SN/A * this software without specific prior written permission. 15955SN/A * 16955SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17955SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19955SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20955SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26955SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27955SN/A * 282665Ssaidi@eecs.umich.edu * Authors: Ali Saidi 294762Snate@binkert.org */ 30955SN/A 315522Snate@binkert.org#include "mem/tport.hh" 326143Snate@binkert.org 334762Snate@binkert.orgvoid 345522Snate@binkert.orgSimpleTimingPort::checkFunctional(PacketPtr pkt) 35955SN/A{ 365522Snate@binkert.org DeferredPacketIterator i = transmitList.begin(); 37955SN/A DeferredPacketIterator end = transmitList.end(); 385522Snate@binkert.org 394202Sbinkertn@umich.edu for (; i != end; ++i) { 405742Snate@binkert.org PacketPtr target = i->pkt; 41955SN/A // If the target contains data, and it overlaps the 424381Sbinkertn@umich.edu // probed request, need to update data 434381Sbinkertn@umich.edu if (target->intersect(pkt)) { 448334Snate@binkert.org if (!fixPacket(pkt, target)) { 45955SN/A // fixPacket returns true for continue, false for done 46955SN/A return; 474202Sbinkertn@umich.edu } 48955SN/A } 494382Sbinkertn@umich.edu } 504382Sbinkertn@umich.edu} 514382Sbinkertn@umich.edu 526654Snate@binkert.orgvoid 535517Snate@binkert.orgSimpleTimingPort::recvFunctional(PacketPtr pkt) 548614Sgblack@eecs.umich.edu{ 557674Snate@binkert.org checkFunctional(pkt); 566143Snate@binkert.org 576143Snate@binkert.org // Just do an atomic access and throw away the returned latency 586143Snate@binkert.org if (pkt->result != Packet::Success) 598233Snate@binkert.org recvAtomic(pkt); 608233Snate@binkert.org} 618233Snate@binkert.org 628233Snate@binkert.orgbool 638233Snate@binkert.orgSimpleTimingPort::recvTiming(PacketPtr pkt) 648334Snate@binkert.org{ 658334Snate@binkert.org // If the device is only a slave, it should only be sending 668233Snate@binkert.org // responses, which should never get nacked. There used to be 678233Snate@binkert.org // code to hanldle nacks here, but I'm pretty sure it didn't work 688233Snate@binkert.org // correctly with the drain code, so that would need to be fixed 698233Snate@binkert.org // if we ever added it back. 708233Snate@binkert.org assert(pkt->isRequest()); 718233Snate@binkert.org assert(pkt->result == Packet::Unknown); 726143Snate@binkert.org bool needsResponse = pkt->needsResponse(); 738233Snate@binkert.org Tick latency = recvAtomic(pkt); 748233Snate@binkert.org // turn packet around to go back to requester if response expected 758233Snate@binkert.org if (needsResponse) { 766143Snate@binkert.org // recvAtomic() should already have turned packet into atomic response 776143Snate@binkert.org assert(pkt->isResponse()); 786143Snate@binkert.org pkt->convertAtomicToTimingResponse(); 796143Snate@binkert.org schedSendTiming(pkt, curTick + latency); 808233Snate@binkert.org } else { 818233Snate@binkert.org delete pkt->req; 828233Snate@binkert.org delete pkt; 836143Snate@binkert.org } 848233Snate@binkert.org return true; 858233Snate@binkert.org} 868233Snate@binkert.org 878233Snate@binkert.org 886143Snate@binkert.orgvoid 896143Snate@binkert.orgSimpleTimingPort::schedSendTiming(PacketPtr pkt, Tick when) 906143Snate@binkert.org{ 914762Snate@binkert.org assert(when > curTick); 926143Snate@binkert.org 938233Snate@binkert.org // Nothing is on the list: add it and schedule an event 948233Snate@binkert.org if (transmitList.empty() || when < transmitList.front().tick) { 958233Snate@binkert.org transmitList.push_front(DeferredPacket(when, pkt)); 968233Snate@binkert.org schedSendEvent(when); 978233Snate@binkert.org return; 986143Snate@binkert.org } 998233Snate@binkert.org 1008233Snate@binkert.org // list is non-empty and this is not the head, so event should 1018233Snate@binkert.org // already be scheduled 1028233Snate@binkert.org assert(waitingOnRetry || 1036143Snate@binkert.org (sendEvent->scheduled() && sendEvent->when() <= when)); 1046143Snate@binkert.org 1056143Snate@binkert.org // list is non-empty & this belongs at the end 1066143Snate@binkert.org if (when >= transmitList.back().tick) { 1076143Snate@binkert.org transmitList.push_back(DeferredPacket(when, pkt)); 1086143Snate@binkert.org return; 1096143Snate@binkert.org } 1106143Snate@binkert.org 1116143Snate@binkert.org // this belongs in the middle somewhere 1127065Snate@binkert.org DeferredPacketIterator i = transmitList.begin(); 1136143Snate@binkert.org i++; // already checked for insertion at front 1148233Snate@binkert.org DeferredPacketIterator end = transmitList.end(); 1158233Snate@binkert.org 1168233Snate@binkert.org for (; i != end; ++i) { 1178233Snate@binkert.org if (when < i->tick) { 1188233Snate@binkert.org transmitList.insert(i, DeferredPacket(when, pkt)); 1198233Snate@binkert.org return; 1208233Snate@binkert.org } 1218233Snate@binkert.org } 1228233Snate@binkert.org assert(false); // should never get here 1238233Snate@binkert.org} 1248233Snate@binkert.org 1258233Snate@binkert.org 1268233Snate@binkert.orgvoid 1278233Snate@binkert.orgSimpleTimingPort::sendDeferredPacket() 1288233Snate@binkert.org{ 1298233Snate@binkert.org assert(deferredPacketReady()); 1308233Snate@binkert.org bool success = sendTiming(transmitList.front().pkt); 1318233Snate@binkert.org 1328233Snate@binkert.org if (success) { 1338233Snate@binkert.org //send successful, remove packet 1348233Snate@binkert.org transmitList.pop_front(); 1358233Snate@binkert.org if (!transmitList.empty()) { 1368233Snate@binkert.org Tick time = transmitList.front().tick; 1378233Snate@binkert.org sendEvent->schedule(time <= curTick ? curTick+1 : time); 1388233Snate@binkert.org } 1398233Snate@binkert.org 1408233Snate@binkert.org if (transmitList.empty() && drainEvent) { 1418233Snate@binkert.org drainEvent->process(); 1428233Snate@binkert.org drainEvent = NULL; 1438233Snate@binkert.org } 1448233Snate@binkert.org } 1456143Snate@binkert.org 1466143Snate@binkert.org waitingOnRetry = !success; 1476143Snate@binkert.org 1486143Snate@binkert.org if (waitingOnRetry) { 1496143Snate@binkert.org DPRINTF(Bus, "Send failed, waiting on retry\n"); 1506143Snate@binkert.org } 1516143Snate@binkert.org} 1526143Snate@binkert.org 1536143Snate@binkert.org 1548945Ssteve.reinhardt@amd.comvoid 1558233Snate@binkert.orgSimpleTimingPort::recvRetry() 1568233Snate@binkert.org{ 1576143Snate@binkert.org DPRINTF(Bus, "Received retry\n"); 1588945Ssteve.reinhardt@amd.com assert(waitingOnRetry); 1596143Snate@binkert.org sendDeferredPacket(); 1606143Snate@binkert.org} 1616143Snate@binkert.org 1626143Snate@binkert.org 1635522Snate@binkert.orgvoid 1646143Snate@binkert.orgSimpleTimingPort::processSendEvent() 1656143Snate@binkert.org{ 1666143Snate@binkert.org assert(!waitingOnRetry); 1676143Snate@binkert.org sendDeferredPacket(); 1688233Snate@binkert.org} 1698233Snate@binkert.org 1708233Snate@binkert.org 1716143Snate@binkert.orgunsigned int 1726143Snate@binkert.orgSimpleTimingPort::drain(Event *de) 1736143Snate@binkert.org{ 1746143Snate@binkert.org if (transmitList.size() == 0) 1755522Snate@binkert.org return 0; 1765522Snate@binkert.org drainEvent = de; 1775522Snate@binkert.org return 1; 1785522Snate@binkert.org} 1795604Snate@binkert.org