#include "mem/tport.hh"
void
-SimpleTimingPort::recvFunctional(PacketPtr pkt)
+SimpleTimingPort::checkFunctional(PacketPtr pkt)
{
- //First check queued events
- std::list<PacketPtr>::iterator i = transmitList.begin();
- std::list<PacketPtr>::iterator end = transmitList.end();
- bool cont = true;
+ DeferredPacketIterator i = transmitList.begin();
+ DeferredPacketIterator end = transmitList.end();
- while (i != end && cont) {
- PacketPtr target = *i;
+ for (; i != end; ++i) {
+ PacketPtr target = i->pkt;
// If the target contains data, and it overlaps the
// probed request, need to update data
- if (target->intersect(pkt))
- fixPacket(pkt, target);
-
+ if (target->intersect(pkt)) {
+ if (!fixPacket(pkt, target)) {
+ // fixPacket returns true for continue, false for done
+ return;
+ }
+ }
}
- //Then just do an atomic access and throw away the returned latency
- if (cont)
+}
+
+void
+SimpleTimingPort::recvFunctional(PacketPtr pkt)
+{
+ checkFunctional(pkt);
+
+ // Just do an atomic access and throw away the returned latency
+ if (pkt->result != Packet::Success)
recvAtomic(pkt);
}
// turn packet around to go back to requester if response expected
if (pkt->needsResponse()) {
pkt->makeTimingResponse();
- sendTimingLater(pkt, latency);
+ schedSendTiming(pkt, curTick + latency);
}
- else {
- if (pkt->cmd != Packet::UpgradeReq)
- {
- delete pkt->req;
- delete pkt;
- }
+ else if (pkt->cmd != MemCmd::UpgradeReq) {
+ delete pkt->req;
+ delete pkt;
}
return true;
}
+
void
-SimpleTimingPort::recvRetry()
+SimpleTimingPort::schedSendTiming(PacketPtr pkt, Tick when)
{
- assert(outTiming > 0);
- assert(!transmitList.empty());
- if (sendTiming(transmitList.front())) {
- transmitList.pop_front();
- outTiming--;
- DPRINTF(Bus, "No Longer waiting on retry\n");
- if (!transmitList.empty())
- sendTimingLater(transmitList.front(), 1);
+ 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));
+ return;
}
- if (transmitList.empty() && drainEvent) {
- drainEvent->process();
- drainEvent = NULL;
+ // something is on the list and 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
+ DeferredPacketIterator i = transmitList.begin();
+ 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;
+ }
+ }
+ assert(false); // should never get here
}
+
void
-SimpleTimingPort::SendEvent::process()
+SimpleTimingPort::sendDeferredPacket()
{
- assert(port->outTiming > 0);
- if (!port->transmitList.empty() && port->transmitList.front() != packet) {
- //We are not the head of the list
- port->transmitList.push_back(packet);
- } else if (port->sendTiming(packet)) {
- // send successful
- if (port->transmitList.size()) {
- port->transmitList.pop_front();
- port->outTiming--;
- if (!port->transmitList.empty())
- port->sendTimingLater(port->transmitList.front(), 1);
+ assert(deferredPacketReady());
+ bool success = sendTiming(transmitList.front().pkt);
+
+ if (success) {
+ //send successful, remove packet
+ transmitList.pop_front();
+ if (!transmitList.empty()) {
+ Tick time = transmitList.front().tick;
+ sendEvent->schedule(time <= curTick ? curTick+1 : time);
}
- if (port->transmitList.empty() && port->drainEvent) {
- port->drainEvent->process();
- port->drainEvent = NULL;
+
+ if (transmitList.empty() && drainEvent) {
+ drainEvent->process();
+ drainEvent = NULL;
}
- } else {
- // send unsuccessful (due to flow control). Will get retry
- // callback later; save for then if not already
- DPRINTF(Bus, "Waiting on retry\n");
- if (!(port->transmitList.front() == packet))
- port->transmitList.push_back(packet);
}
+
+ waitingOnRetry = !success;
+
+ if (waitingOnRetry) {
+ DPRINTF(Bus, "Send failed, waiting on retry\n");
+ }
+}
+
+
+void
+SimpleTimingPort::recvRetry()
+{
+ DPRINTF(Bus, "Received retry\n");
+ assert(waitingOnRetry);
+ sendDeferredPacket();
+}
+
+
+void
+SimpleTimingPort::processSendEvent()
+{
+ assert(!waitingOnRetry);
+ sendDeferredPacket();
}
unsigned int
SimpleTimingPort::drain(Event *de)
{
- if (outTiming == 0 && transmitList.size() == 0)
+ if (transmitList.size() == 0)
return 0;
drainEvent = de;
return 1;