diff options
author | Gabe Black <gblack@eecs.umich.edu> | 2007-08-04 20:27:23 -0700 |
---|---|---|
committer | Gabe Black <gblack@eecs.umich.edu> | 2007-08-04 20:27:23 -0700 |
commit | cae8d20633c0f43fdae23576adfb894284a7ee86 (patch) | |
tree | e9e232684d7fc024900d8a07d6b8a3add1f52e92 /src/mem/tport.cc | |
parent | 30e777a5d3829975266ecccac965d2297a5f4985 (diff) | |
parent | df015f17a45b18302565c43d3790d787e1b54c42 (diff) | |
download | gem5-cae8d20633c0f43fdae23576adfb894284a7ee86.tar.xz |
Merge with head.
--HG--
extra : convert_revision : 3edb9f03353b18b4c9f062bccf11e79cfb3c15f2
Diffstat (limited to 'src/mem/tport.cc')
-rw-r--r-- | src/mem/tport.cc | 78 |
1 files changed, 49 insertions, 29 deletions
diff --git a/src/mem/tport.cc b/src/mem/tport.cc index ed4c0c172..b1a6a4813 100644 --- a/src/mem/tport.cc +++ b/src/mem/tport.cc @@ -30,7 +30,7 @@ #include "mem/tport.hh" -void +bool SimpleTimingPort::checkFunctional(PacketPtr pkt) { DeferredPacketIterator i = transmitList.begin(); @@ -40,23 +40,21 @@ SimpleTimingPort::checkFunctional(PacketPtr pkt) PacketPtr target = i->pkt; // If the target contains data, and it overlaps the // probed request, need to update data - if (target->intersect(pkt)) { - if (!fixPacket(pkt, target)) { - // fixPacket returns true for continue, false for done - return; - } + if (pkt->checkFunctional(target)) { + return true; } } + + return false; } void SimpleTimingPort::recvFunctional(PacketPtr pkt) { - checkFunctional(pkt); - - // Just do an atomic access and throw away the returned latency - if (pkt->result != Packet::Success) + if (!checkFunctional(pkt)) { + // Just do an atomic access and throw away the returned latency recvAtomic(pkt); + } } bool @@ -67,17 +65,28 @@ SimpleTimingPort::recvTiming(PacketPtr pkt) // code to hanldle nacks here, but I'm pretty sure it didn't work // correctly with the drain code, so that would need to be fixed // if we ever added it back. - assert(pkt->result != Packet::Nacked); + assert(pkt->isRequest()); + + if (pkt->memInhibitAsserted()) { + // snooper will supply based on copy of packet + // still target's responsibility to delete packet + delete pkt; + return true; + } + + bool needsResponse = pkt->needsResponse(); Tick latency = recvAtomic(pkt); // turn packet around to go back to requester if response expected - if (pkt->needsResponse()) { - pkt->makeTimingResponse(); + if (needsResponse) { + // recvAtomic() should already have turned packet into + // atomic response + assert(pkt->isResponse()); schedSendTiming(pkt, curTick + latency); - } - else if (pkt->cmd != MemCmd::UpgradeReq) { + } else { delete pkt->req; delete pkt; } + return true; } @@ -88,28 +97,30 @@ SimpleTimingPort::schedSendTiming(PacketPtr pkt, Tick when) assert(when > curTick); // Nothing is on the list: add it and schedule an event - if (transmitList.empty()) { - assert(!sendEvent->scheduled()); - sendEvent->schedule(when); - transmitList.push_back(DeferredPacket(when, pkt)); + if (transmitList.empty() || when < transmitList.front().tick) { + transmitList.push_front(DeferredPacket(when, pkt)); + schedSendEvent(when); return; } - // something is on the list and this belongs at the end + // list is non-empty and this is not the head, so event should + // already be scheduled + assert(waitingOnRetry || + (sendEvent->scheduled() && sendEvent->when() <= when)); + + // list is non-empty & this belongs at the end if (when >= transmitList.back().tick) { transmitList.push_back(DeferredPacket(when, pkt)); return; } - // Something is on the list and this belongs somewhere else + + // this belongs in the middle somewhere DeferredPacketIterator i = transmitList.begin(); + i++; // already checked for insertion at front DeferredPacketIterator end = transmitList.end(); for (; i != end; ++i) { if (when < i->tick) { - if (i == transmitList.begin()) { - //Inserting at begining, reschedule - sendEvent->reschedule(when); - } transmitList.insert(i, DeferredPacket(when, pkt)); return; } @@ -122,12 +133,15 @@ void SimpleTimingPort::sendDeferredPacket() { assert(deferredPacketReady()); - bool success = sendTiming(transmitList.front().pkt); + // take packet off list here; if recvTiming() on the other side + // calls sendTiming() back on us (like SimpleTimingCpu does), then + // we get confused by having a non-active packet on transmitList + DeferredPacket dp = transmitList.front(); + transmitList.pop_front(); + bool success = sendTiming(dp.pkt); if (success) { - //send successful, remove packet - transmitList.pop_front(); - if (!transmitList.empty()) { + if (!transmitList.empty() && !sendEvent->scheduled()) { Tick time = transmitList.front().tick; sendEvent->schedule(time <= curTick ? curTick+1 : time); } @@ -136,6 +150,12 @@ SimpleTimingPort::sendDeferredPacket() drainEvent->process(); drainEvent = NULL; } + } else { + // Unsuccessful, need to put back on transmitList. Callee + // should not have messed with it (since it didn't accept that + // packet), so we can just push it back on the front. + assert(!sendEvent->scheduled()); + transmitList.push_front(dp); } waitingOnRetry = !success; |