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