summaryrefslogtreecommitdiff
path: root/src/mem/tport.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem/tport.cc')
-rw-r--r--src/mem/tport.cc180
1 files changed, 7 insertions, 173 deletions
diff --git a/src/mem/tport.cc b/src/mem/tport.cc
index cbb7ed2ac..bf3d59a8f 100644
--- a/src/mem/tport.cc
+++ b/src/mem/tport.cc
@@ -41,49 +41,21 @@
* Andreas Hansson
*/
-#include "debug/Bus.hh"
#include "mem/mem_object.hh"
#include "mem/tport.hh"
-using namespace std;
-
-SimpleTimingPort::SimpleTimingPort(const string &_name, MemObject *_owner,
- const string _label)
- : Port(_name, _owner), label(_label), sendEvent(this), drainEvent(NULL),
- waitingOnRetry(false)
-{
-}
-
-SimpleTimingPort::~SimpleTimingPort()
-{
-}
-
-bool
-SimpleTimingPort::checkFunctional(PacketPtr pkt)
+SimpleTimingPort::SimpleTimingPort(const std::string& _name,
+ MemObject* _owner) :
+ QueuedPort(_name, _owner, queue), queue(*_owner, *this)
{
- pkt->pushLabel(label);
-
- DeferredPacketIterator i = transmitList.begin();
- DeferredPacketIterator end = transmitList.end();
- bool found = false;
-
- while (!found && i != end) {
- // If the buffered packet contains data, and it overlaps the
- // current packet, then update data
- found = pkt->checkFunctional(i->pkt);
- ++i;
- }
-
- pkt->popLabel();
-
- return found;
}
void
SimpleTimingPort::recvFunctional(PacketPtr pkt)
{
- if (!checkFunctional(pkt)) {
- // Just do an atomic access and throw away the returned latency
+ assert(pkt->isRequest());
+ if (!queue.checkFunctional(pkt)) {
+ // do an atomic access and throw away the returned latency
recvAtomic(pkt);
}
}
@@ -91,12 +63,6 @@ SimpleTimingPort::recvFunctional(PacketPtr pkt)
bool
SimpleTimingPort::recvTiming(PacketPtr pkt)
{
- // If the device is only a slave, it should only be sending
- // responses, which should never get nacked. There used to be
- // 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.
-
if (pkt->memInhibitAsserted()) {
// snooper will supply based on copy of packet
// still target's responsibility to delete packet
@@ -111,142 +77,10 @@ SimpleTimingPort::recvTiming(PacketPtr pkt)
// recvAtomic() should already have turned packet into
// atomic response
assert(pkt->isResponse());
- schedSendTiming(pkt, curTick() + latency);
+ queue.schedSendTiming(pkt, curTick() + latency);
} else {
delete pkt;
}
return true;
}
-
-void
-SimpleTimingPort::schedSendEvent(Tick when)
-{
- // if we are waiting on a retry, do not schedule a send event, and
- // instead rely on retry being called
- if (waitingOnRetry) {
- assert(!sendEvent.scheduled());
- return;
- }
-
- if (!sendEvent.scheduled()) {
- owner->schedule(&sendEvent, when);
- } else if (sendEvent.when() > when) {
- owner->reschedule(&sendEvent, when);
- }
-}
-
-void
-SimpleTimingPort::schedSendTiming(PacketPtr pkt, Tick when)
-{
- assert(when > curTick());
- assert(when < curTick() + SimClock::Int::ms);
-
- // Nothing is on the list: add it and schedule an event
- if (transmitList.empty() || when < transmitList.front().tick) {
- transmitList.push_front(DeferredPacket(when, pkt));
- schedSendEvent(when);
- return;
- }
-
- // list is non-empty & this belongs at the end
- if (when >= transmitList.back().tick) {
- transmitList.push_back(DeferredPacket(when, pkt));
- return;
- }
-
- // 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) {
- transmitList.insert(i, DeferredPacket(when, pkt));
- return;
- }
- }
- assert(false); // should never get here
-}
-
-void SimpleTimingPort::trySendTiming()
-{
- assert(deferredPacketReady());
- // take the next packet off the list here, as we might return to
- // ourselves through the sendTiming call below
- DeferredPacket dp = transmitList.front();
- transmitList.pop_front();
-
- // attempt to send the packet and remember the outcome
- waitingOnRetry = !sendTiming(dp.pkt);
-
- if (waitingOnRetry) {
- // put the packet back at the front of the list (packet should
- // not have changed since it wasn't accepted)
- assert(!sendEvent.scheduled());
- transmitList.push_front(dp);
- }
-}
-
-void
-SimpleTimingPort::scheduleSend(Tick time)
-{
- // the next ready time is either determined by the next deferred packet,
- // or in the cache through the MSHR ready time
- Tick nextReady = std::min(deferredPacketReadyTime(), time);
- if (nextReady != MaxTick) {
- // if the sendTiming caused someone else to call our
- // recvTiming we could already have an event scheduled, check
- if (!sendEvent.scheduled())
- owner->schedule(&sendEvent, std::max(nextReady, curTick() + 1));
- } else {
- // no more to send, so if we're draining, we may be done
- if (drainEvent && !sendEvent.scheduled()) {
- drainEvent->process();
- drainEvent = NULL;
- }
- }
-}
-
-void
-SimpleTimingPort::sendDeferredPacket()
-{
- // try to send what is on the list
- trySendTiming();
-
- // if we succeeded and are not waiting for a retry, schedule the
- // next send
- if (!waitingOnRetry) {
- scheduleSend();
- }
-}
-
-
-void
-SimpleTimingPort::recvRetry()
-{
- DPRINTF(Bus, "Received retry\n");
- // note that in the cache we get a retry even though we may not
- // have a packet to retry (we could potentially decide on a new
- // packet every time we retry)
- assert(waitingOnRetry);
- sendDeferredPacket();
-}
-
-
-void
-SimpleTimingPort::processSendEvent()
-{
- assert(!waitingOnRetry);
- sendDeferredPacket();
-}
-
-
-unsigned int
-SimpleTimingPort::drain(Event *de)
-{
- if (transmitList.empty() && !sendEvent.scheduled())
- return 0;
- drainEvent = de;
- return 1;
-}