tport.cc revision 5606
11689SN/A/* 22329SN/A * Copyright (c) 2006 The Regents of The University of Michigan 31689SN/A * All rights reserved. 41689SN/A * 51689SN/A * Redistribution and use in source and binary forms, with or without 61689SN/A * modification, are permitted provided that the following conditions are 71689SN/A * met: redistributions of source code must retain the above copyright 81689SN/A * notice, this list of conditions and the following disclaimer; 91689SN/A * redistributions in binary form must reproduce the above copyright 101689SN/A * notice, this list of conditions and the following disclaimer in the 111689SN/A * documentation and/or other materials provided with the distribution; 121689SN/A * neither the name of the copyright holders nor the names of its 131689SN/A * contributors may be used to endorse or promote products derived from 141689SN/A * this software without specific prior written permission. 151689SN/A * 161689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 181689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 191689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 201689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 211689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 221689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 251689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 261689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Ali Saidi 291689SN/A */ 301689SN/A 312292SN/A#include "mem/tport.hh" 322292SN/A 331060SN/Abool 341061SN/ASimpleTimingPort::checkFunctional(PacketPtr pkt) 351684SN/A{ 367720Sgblack@eecs.umich.edu DeferredPacketIterator i = transmitList.begin(); 376216Snate@binkert.org DeferredPacketIterator end = transmitList.end(); 386216Snate@binkert.org 392980Sgblack@eecs.umich.edu for (; i != end; ++i) { 401060SN/A PacketPtr target = i->pkt; 412292SN/A // If the target contains data, and it overlaps the 422292SN/A // probed request, need to update data 432292SN/A if (pkt->checkFunctional(target)) { 441060SN/A return true; 451060SN/A } 462348SN/A } 471060SN/A 482292SN/A return false; 492292SN/A} 502292SN/A 512292SN/Avoid 522292SN/ASimpleTimingPort::recvFunctional(PacketPtr pkt) 532292SN/A{ 542292SN/A if (!checkFunctional(pkt)) { 552292SN/A // Just do an atomic access and throw away the returned latency 562292SN/A recvAtomic(pkt); 572292SN/A } 582292SN/A} 592348SN/A 602292SN/Abool 612292SN/ASimpleTimingPort::recvTiming(PacketPtr pkt) 621061SN/A{ 631061SN/A // If the device is only a slave, it should only be sending 641061SN/A // responses, which should never get nacked. There used to be 651061SN/A // code to hanldle nacks here, but I'm pretty sure it didn't work 661461SN/A // correctly with the drain code, so that would need to be fixed 671060SN/A // if we ever added it back. 681060SN/A assert(pkt->isRequest()); 692348SN/A 701060SN/A if (pkt->memInhibitAsserted()) { 712292SN/A // snooper will supply based on copy of packet 721061SN/A // still target's responsibility to delete packet 731061SN/A delete pkt; 741061SN/A return true; 751061SN/A } 761461SN/A 771060SN/A bool needsResponse = pkt->needsResponse(); 781060SN/A Tick latency = recvAtomic(pkt); 792348SN/A // turn packet around to go back to requester if response expected 801060SN/A if (needsResponse) { 812292SN/A // recvAtomic() should already have turned packet into 821061SN/A // atomic response 831061SN/A assert(pkt->isResponse()); 841061SN/A schedSendTiming(pkt, curTick + latency); 851061SN/A } else { 861461SN/A delete pkt; 871062SN/A } 882292SN/A 892292SN/A return true; 902292SN/A} 914636Sgblack@eecs.umich.edu 927720Sgblack@eecs.umich.edu 932292SN/Avoid 942292SN/ASimpleTimingPort::schedSendTiming(PacketPtr pkt, Tick when) 952292SN/A{ 961060SN/A assert(when > curTick); 971060SN/A assert(when < curTick + Clock::Int::ms); 981060SN/A 991060SN/A // Nothing is on the list: add it and schedule an event 1001061SN/A if (transmitList.empty() || when < transmitList.front().tick) { 1011061SN/A transmitList.push_front(DeferredPacket(when, pkt)); 1021061SN/A schedSendEvent(when); 1031061SN/A return; 1041461SN/A } 1051060SN/A 1061060SN/A // list is non-empty & this belongs at the end 1072348SN/A if (when >= transmitList.back().tick) { 1082292SN/A transmitList.push_back(DeferredPacket(when, pkt)); 1091060SN/A return; 1101060SN/A } 1111060SN/A 1121060SN/A // this belongs in the middle somewhere 1131060SN/A DeferredPacketIterator i = transmitList.begin(); 1141060SN/A i++; // already checked for insertion at front 1151062SN/A DeferredPacketIterator end = transmitList.end(); 1161062SN/A 1172292SN/A for (; i != end; ++i) { 1181062SN/A if (when < i->tick) { 1191061SN/A transmitList.insert(i, DeferredPacket(when, pkt)); 1201061SN/A return; 1214636Sgblack@eecs.umich.edu } 1227720Sgblack@eecs.umich.edu } 1232292SN/A assert(false); // should never get here 1242292SN/A} 1251060SN/A 1261060SN/A 1272292SN/Avoid 1281060SN/ASimpleTimingPort::sendDeferredPacket() 1291060SN/A{ 1301060SN/A assert(deferredPacketReady()); 1311060SN/A // take packet off list here; if recvTiming() on the other side 1322292SN/A // calls sendTiming() back on us (like SimpleTimingCpu does), then 1331060SN/A // we get confused by having a non-active packet on transmitList 1341060SN/A DeferredPacket dp = transmitList.front(); 1352292SN/A transmitList.pop_front(); 1362292SN/A bool success = sendTiming(dp.pkt); 1372292SN/A 1382292SN/A if (success) { 1392292SN/A if (!transmitList.empty() && !sendEvent->scheduled()) { 1401060SN/A Tick time = transmitList.front().tick; 1412292SN/A schedule(sendEvent, time <= curTick ? curTick+1 : time); 1422292SN/A } 1432292SN/A 1442292SN/A if (transmitList.empty() && drainEvent) { 1452292SN/A drainEvent->process(); 1461060SN/A drainEvent = NULL; 1471060SN/A } 1482292SN/A } else { 1491060SN/A // Unsuccessful, need to put back on transmitList. Callee 1501060SN/A // should not have messed with it (since it didn't accept that 1512292SN/A // packet), so we can just push it back on the front. 1522292SN/A assert(!sendEvent->scheduled()); 1532292SN/A transmitList.push_front(dp); 1542292SN/A } 1551060SN/A 1562292SN/A waitingOnRetry = !success; 1571060SN/A 1581061SN/A if (waitingOnRetry) { 1591061SN/A DPRINTF(Bus, "Send failed, waiting on retry\n"); 1604636Sgblack@eecs.umich.edu } 1617720Sgblack@eecs.umich.edu} 1621060SN/A 1631060SN/A 1641060SN/Avoid 1651060SN/ASimpleTimingPort::recvRetry() 1661060SN/A{ 1671061SN/A DPRINTF(Bus, "Received retry\n"); 1682292SN/A assert(waitingOnRetry); 1692292SN/A sendDeferredPacket(); 1702292SN/A} 1712292SN/A 1721061SN/A 1731061SN/Avoid 1741061SN/ASimpleTimingPort::processSendEvent() 1751061SN/A{ 1762292SN/A assert(!waitingOnRetry); 1772292SN/A sendDeferredPacket(); 1782292SN/A} 1792292SN/A 1802292SN/A 1812292SN/Aunsigned int 1822292SN/ASimpleTimingPort::drain(Event *de) 1832292SN/A{ 1841060SN/A if (transmitList.size() == 0) 1851060SN/A return 0; 1862292SN/A drainEvent = de; 1872292SN/A return 1; 1882292SN/A} 1892292SN/A