tport.cc revision 8856
12650Ssaidi@eecs.umich.edu/* 22650Ssaidi@eecs.umich.edu * Copyright (c) 2012 ARM Limited 32650Ssaidi@eecs.umich.edu * All rights reserved. 42650Ssaidi@eecs.umich.edu * 52650Ssaidi@eecs.umich.edu * The license below extends only to copyright in the software and shall 62650Ssaidi@eecs.umich.edu * not be construed as granting a license to any other intellectual 72650Ssaidi@eecs.umich.edu * property including but not limited to intellectual property relating 82650Ssaidi@eecs.umich.edu * to a hardware implementation of the functionality of the software 92650Ssaidi@eecs.umich.edu * licensed hereunder. You may use the software subject to the license 102650Ssaidi@eecs.umich.edu * terms below provided that you ensure that this notice is replicated 112650Ssaidi@eecs.umich.edu * unmodified and in its entirety in all distributions of the software, 122650Ssaidi@eecs.umich.edu * modified or unmodified, in source code or in binary form. 132650Ssaidi@eecs.umich.edu * 142650Ssaidi@eecs.umich.edu * Copyright (c) 2006 The Regents of The University of Michigan 152650Ssaidi@eecs.umich.edu * All rights reserved. 162650Ssaidi@eecs.umich.edu * 172650Ssaidi@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 182650Ssaidi@eecs.umich.edu * modification, are permitted provided that the following conditions are 192650Ssaidi@eecs.umich.edu * met: redistributions of source code must retain the above copyright 202650Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 212650Ssaidi@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 222650Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 232650Ssaidi@eecs.umich.edu * documentation and/or other materials provided with the distribution; 242650Ssaidi@eecs.umich.edu * neither the name of the copyright holders nor the names of its 252650Ssaidi@eecs.umich.edu * contributors may be used to endorse or promote products derived from 262650Ssaidi@eecs.umich.edu * this software without specific prior written permission. 272650Ssaidi@eecs.umich.edu * 282650Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 294194Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 303817Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 313817Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 323817Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 333817Ssaidi@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 343817Ssaidi@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 354194Ssaidi@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 362650Ssaidi@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 373817Ssaidi@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 385946Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 393817Ssaidi@eecs.umich.edu * 404103Ssaidi@eecs.umich.edu * Authors: Ali Saidi 414103Ssaidi@eecs.umich.edu * Andreas Hansson 424103Ssaidi@eecs.umich.edu */ 434103Ssaidi@eecs.umich.edu 445531Snate@binkert.org#include "debug/Bus.hh" 455531Snate@binkert.org#include "mem/mem_object.hh" 464103Ssaidi@eecs.umich.edu#include "mem/tport.hh" 474103Ssaidi@eecs.umich.edu 485704Snate@binkert.orgusing namespace std; 494103Ssaidi@eecs.umich.edu 505704Snate@binkert.orgSimpleTimingPort::SimpleTimingPort(const string &_name, MemObject *_owner, 514103Ssaidi@eecs.umich.edu const string _label) 525704Snate@binkert.org : Port(_name, _owner), label(_label), sendEvent(this), drainEvent(NULL), 534103Ssaidi@eecs.umich.edu waitingOnRetry(false) 545704Snate@binkert.org{ 554103Ssaidi@eecs.umich.edu} 564103Ssaidi@eecs.umich.edu 574103Ssaidi@eecs.umich.eduSimpleTimingPort::~SimpleTimingPort() 584103Ssaidi@eecs.umich.edu{ 595704Snate@binkert.org} 604103Ssaidi@eecs.umich.edu 615704Snate@binkert.orgbool 624103Ssaidi@eecs.umich.eduSimpleTimingPort::checkFunctional(PacketPtr pkt) 634103Ssaidi@eecs.umich.edu{ 644103Ssaidi@eecs.umich.edu pkt->pushLabel(label); 655946Sgblack@eecs.umich.edu 665946Sgblack@eecs.umich.edu DeferredPacketIterator i = transmitList.begin(); 675946Sgblack@eecs.umich.edu DeferredPacketIterator end = transmitList.end(); 685946Sgblack@eecs.umich.edu bool found = false; 695946Sgblack@eecs.umich.edu 705946Sgblack@eecs.umich.edu while (!found && i != end) { 715946Sgblack@eecs.umich.edu // If the buffered packet contains data, and it overlaps the 725946Sgblack@eecs.umich.edu // current packet, then update data 735946Sgblack@eecs.umich.edu found = pkt->checkFunctional(i->pkt); 745946Sgblack@eecs.umich.edu ++i; 755946Sgblack@eecs.umich.edu } 765946Sgblack@eecs.umich.edu 775946Sgblack@eecs.umich.edu pkt->popLabel(); 785946Sgblack@eecs.umich.edu 795946Sgblack@eecs.umich.edu return found; 805946Sgblack@eecs.umich.edu} 815946Sgblack@eecs.umich.edu 825946Sgblack@eecs.umich.eduvoid 835946Sgblack@eecs.umich.eduSimpleTimingPort::recvFunctional(PacketPtr pkt) 845946Sgblack@eecs.umich.edu{ 854103Ssaidi@eecs.umich.edu if (!checkFunctional(pkt)) { 863817Ssaidi@eecs.umich.edu // Just do an atomic access and throw away the returned latency 874185Ssaidi@eecs.umich.edu recvAtomic(pkt); 882650Ssaidi@eecs.umich.edu } 895531Snate@binkert.org} 905531Snate@binkert.org 912650Ssaidi@eecs.umich.edubool 922650Ssaidi@eecs.umich.eduSimpleTimingPort::recvTiming(PacketPtr pkt) 932982Sstever@eecs.umich.edu{ 943919Shsul@eecs.umich.edu // If the device is only a slave, it should only be sending 954172Ssaidi@eecs.umich.edu // responses, which should never get nacked. There used to be 964103Ssaidi@eecs.umich.edu // code to hanldle nacks here, but I'm pretty sure it didn't work 973919Shsul@eecs.umich.edu // correctly with the drain code, so that would need to be fixed 983919Shsul@eecs.umich.edu // if we ever added it back. 994172Ssaidi@eecs.umich.edu 1003919Shsul@eecs.umich.edu if (pkt->memInhibitAsserted()) { 1014172Ssaidi@eecs.umich.edu // snooper will supply based on copy of packet 1022650Ssaidi@eecs.umich.edu // still target's responsibility to delete packet 1033919Shsul@eecs.umich.edu delete pkt; 1043919Shsul@eecs.umich.edu return true; 1053919Shsul@eecs.umich.edu } 1064172Ssaidi@eecs.umich.edu 1074103Ssaidi@eecs.umich.edu bool needsResponse = pkt->needsResponse(); 1085606Snate@binkert.org Tick latency = recvAtomic(pkt); 1093919Shsul@eecs.umich.edu // turn packet around to go back to requester if response expected 1104103Ssaidi@eecs.umich.edu if (needsResponse) { 1114103Ssaidi@eecs.umich.edu // recvAtomic() should already have turned packet into 1125606Snate@binkert.org // atomic response 1135606Snate@binkert.org assert(pkt->isResponse()); 1144103Ssaidi@eecs.umich.edu schedSendTiming(pkt, curTick() + latency); 1153919Shsul@eecs.umich.edu } else { 1163919Shsul@eecs.umich.edu delete pkt; 1172650Ssaidi@eecs.umich.edu } 1183919Shsul@eecs.umich.edu 1193919Shsul@eecs.umich.edu return true; 1203919Shsul@eecs.umich.edu} 1214172Ssaidi@eecs.umich.edu 1223919Shsul@eecs.umich.eduvoid 1235606Snate@binkert.orgSimpleTimingPort::schedSendEvent(Tick when) 1243919Shsul@eecs.umich.edu{ 1255531Snate@binkert.org // if we are waiting on a retry, do not schedule a send event, and 1264103Ssaidi@eecs.umich.edu // instead rely on retry being called 1274103Ssaidi@eecs.umich.edu if (waitingOnRetry) { 1285606Snate@binkert.org assert(!sendEvent.scheduled()); 1295606Snate@binkert.org return; 1304103Ssaidi@eecs.umich.edu } 1313919Shsul@eecs.umich.edu 1323919Shsul@eecs.umich.edu if (!sendEvent.scheduled()) { 1332650Ssaidi@eecs.umich.edu owner->schedule(&sendEvent, when); 1343919Shsul@eecs.umich.edu } else if (sendEvent.when() > when) { 1354172Ssaidi@eecs.umich.edu owner->reschedule(&sendEvent, when); 1363827Shsul@eecs.umich.edu } 1373919Shsul@eecs.umich.edu} 1384172Ssaidi@eecs.umich.edu 1394103Ssaidi@eecs.umich.eduvoid 1403919Shsul@eecs.umich.eduSimpleTimingPort::schedSendTiming(PacketPtr pkt, Tick when) 1412650Ssaidi@eecs.umich.edu{ 1423919Shsul@eecs.umich.edu assert(when > curTick()); 1433919Shsul@eecs.umich.edu assert(when < curTick() + SimClock::Int::ms); 1442650Ssaidi@eecs.umich.edu 1453921Shsul@eecs.umich.edu // Nothing is on the list: add it and schedule an event 1464172Ssaidi@eecs.umich.edu if (transmitList.empty() || when < transmitList.front().tick) { 1474103Ssaidi@eecs.umich.edu transmitList.push_front(DeferredPacket(when, pkt)); 1485704Snate@binkert.org schedSendEvent(when); 1494103Ssaidi@eecs.umich.edu return; 1505704Snate@binkert.org } 1514103Ssaidi@eecs.umich.edu 1523921Shsul@eecs.umich.edu // list is non-empty & this belongs at the end 1533919Shsul@eecs.umich.edu if (when >= transmitList.back().tick) { 1543919Shsul@eecs.umich.edu transmitList.push_back(DeferredPacket(when, pkt)); 1554172Ssaidi@eecs.umich.edu return; 1563919Shsul@eecs.umich.edu } 1572650Ssaidi@eecs.umich.edu 1583919Shsul@eecs.umich.edu // this belongs in the middle somewhere 1593919Shsul@eecs.umich.edu DeferredPacketIterator i = transmitList.begin(); 1604172Ssaidi@eecs.umich.edu i++; // already checked for insertion at front 1614103Ssaidi@eecs.umich.edu DeferredPacketIterator end = transmitList.end(); 1625704Snate@binkert.org 1634103Ssaidi@eecs.umich.edu for (; i != end; ++i) { 1645704Snate@binkert.org if (when < i->tick) { 1654103Ssaidi@eecs.umich.edu transmitList.insert(i, DeferredPacket(when, pkt)); 1663919Shsul@eecs.umich.edu return; 1673919Shsul@eecs.umich.edu } 1684172Ssaidi@eecs.umich.edu } 1694103Ssaidi@eecs.umich.edu assert(false); // should never get here 1705704Snate@binkert.org} 1714103Ssaidi@eecs.umich.edu 1725704Snate@binkert.orgvoid SimpleTimingPort::trySendTiming() 1734103Ssaidi@eecs.umich.edu{ 1743919Shsul@eecs.umich.edu assert(deferredPacketReady()); 1753919Shsul@eecs.umich.edu // take the next packet off the list here, as we might return to 1764172Ssaidi@eecs.umich.edu // ourselves through the sendTiming call below 1774103Ssaidi@eecs.umich.edu DeferredPacket dp = transmitList.front(); 1785704Snate@binkert.org transmitList.pop_front(); 1794103Ssaidi@eecs.umich.edu 1805704Snate@binkert.org // attempt to send the packet and remember the outcome 1814103Ssaidi@eecs.umich.edu waitingOnRetry = !sendTiming(dp.pkt); 1823919Shsul@eecs.umich.edu 1833919Shsul@eecs.umich.edu if (waitingOnRetry) { 1844172Ssaidi@eecs.umich.edu // put the packet back at the front of the list (packet should 1854103Ssaidi@eecs.umich.edu // not have changed since it wasn't accepted) 1863919Shsul@eecs.umich.edu assert(!sendEvent.scheduled()); 1873828Shsul@eecs.umich.edu transmitList.push_front(dp); 1883919Shsul@eecs.umich.edu } 1893919Shsul@eecs.umich.edu} 1903919Shsul@eecs.umich.edu 1914172Ssaidi@eecs.umich.eduvoid 1923919Shsul@eecs.umich.eduSimpleTimingPort::scheduleSend(Tick time) 1935606Snate@binkert.org{ 1943919Shsul@eecs.umich.edu // the next ready time is either determined by the next deferred packet, 1955531Snate@binkert.org // or in the cache through the MSHR ready time 1964103Ssaidi@eecs.umich.edu Tick nextReady = std::min(deferredPacketReadyTime(), time); 1974103Ssaidi@eecs.umich.edu if (nextReady != MaxTick) { 1985606Snate@binkert.org // if the sendTiming caused someone else to call our 1995606Snate@binkert.org // recvTiming we could already have an event scheduled, check 2004103Ssaidi@eecs.umich.edu if (!sendEvent.scheduled()) 2013919Shsul@eecs.umich.edu owner->schedule(&sendEvent, std::max(nextReady, curTick() + 1)); 2023919Shsul@eecs.umich.edu } else { 2033817Ssaidi@eecs.umich.edu // no more to send, so if we're draining, we may be done 2043919Shsul@eecs.umich.edu if (drainEvent && !sendEvent.scheduled()) { 2053919Shsul@eecs.umich.edu drainEvent->process(); 2064172Ssaidi@eecs.umich.edu drainEvent = NULL; 2074103Ssaidi@eecs.umich.edu } 2084103Ssaidi@eecs.umich.edu } 2095704Snate@binkert.org} 2104103Ssaidi@eecs.umich.edu 2115704Snate@binkert.orgvoid 2124103Ssaidi@eecs.umich.eduSimpleTimingPort::sendDeferredPacket() 2133919Shsul@eecs.umich.edu{ 2143919Shsul@eecs.umich.edu // try to send what is on the list 2154194Ssaidi@eecs.umich.edu trySendTiming(); 2164194Ssaidi@eecs.umich.edu 2174194Ssaidi@eecs.umich.edu // if we succeeded and are not waiting for a retry, schedule the 2183919Shsul@eecs.umich.edu // next send 2194194Ssaidi@eecs.umich.edu if (!waitingOnRetry) { 2204194Ssaidi@eecs.umich.edu scheduleSend(); 2214194Ssaidi@eecs.umich.edu } 2224194Ssaidi@eecs.umich.edu} 2234216Ssaidi@eecs.umich.edu 2244194Ssaidi@eecs.umich.edu 2254194Ssaidi@eecs.umich.eduvoid 2264194Ssaidi@eecs.umich.eduSimpleTimingPort::recvRetry() 2274194Ssaidi@eecs.umich.edu{ 2285531Snate@binkert.org DPRINTF(Bus, "Received retry\n"); 2293919Shsul@eecs.umich.edu // note that in the cache we get a retry even though we may not 2303817Ssaidi@eecs.umich.edu // have a packet to retry (we could potentially decide on a new 2313919Shsul@eecs.umich.edu // packet every time we retry) 2325531Snate@binkert.org assert(waitingOnRetry); 2335531Snate@binkert.org sendDeferredPacket(); 2342650Ssaidi@eecs.umich.edu} 2352650Ssaidi@eecs.umich.edu 2362650Ssaidi@eecs.umich.edu 2372650Ssaidi@eecs.umich.eduvoid 2384185Ssaidi@eecs.umich.eduSimpleTimingPort::processSendEvent() 2392650Ssaidi@eecs.umich.edu{ 2404194Ssaidi@eecs.umich.edu assert(!waitingOnRetry); 2414194Ssaidi@eecs.umich.edu sendDeferredPacket(); 2422650Ssaidi@eecs.umich.edu} 2433919Shsul@eecs.umich.edu 2443825Ssaidi@eecs.umich.edu 2453825Ssaidi@eecs.umich.eduunsigned int 2463825Ssaidi@eecs.umich.eduSimpleTimingPort::drain(Event *de) 2473825Ssaidi@eecs.umich.edu{ 2483825Ssaidi@eecs.umich.edu if (transmitList.empty() && !sendEvent.scheduled()) 2493825Ssaidi@eecs.umich.edu return 0; 2503825Ssaidi@eecs.umich.edu drainEvent = de; 2513825Ssaidi@eecs.umich.edu return 1; 2523825Ssaidi@eecs.umich.edu} 2533825Ssaidi@eecs.umich.edu