Merge vm1.(none):/home/stever/bk/newmem-head

into  vm1.(none):/home/stever/bk/newmem-cache2

--HG--
extra : convert_revision : 72c6f2ce7e9e2b46e59711a2c3cfe770c243018e
This commit is contained in:
Steve Reinhardt 2007-05-29 22:25:57 -07:00
commit 94c19ad37d
2 changed files with 63 additions and 46 deletions

View file

@ -36,7 +36,7 @@ SimpleTimingPort::checkFunctional(PacketPtr pkt)
DeferredPacketIterator i = transmitList.begin(); DeferredPacketIterator i = transmitList.begin();
DeferredPacketIterator end = transmitList.end(); DeferredPacketIterator end = transmitList.end();
while (i != end) { for (; i != end; ++i) {
PacketPtr target = i->pkt; PacketPtr target = i->pkt;
// If the target contains data, and it overlaps the // If the target contains data, and it overlaps the
// probed request, need to update data // probed request, need to update data
@ -46,8 +46,6 @@ SimpleTimingPort::checkFunctional(PacketPtr pkt)
return; return;
} }
} }
i++;
} }
} }
@ -74,7 +72,7 @@ SimpleTimingPort::recvTiming(PacketPtr pkt)
// turn packet around to go back to requester if response expected // turn packet around to go back to requester if response expected
if (pkt->needsResponse()) { if (pkt->needsResponse()) {
pkt->makeTimingResponse(); pkt->makeTimingResponse();
sendTiming(pkt, latency); schedSendTiming(pkt, latency);
} }
else if (pkt->cmd != MemCmd::UpgradeReq) { else if (pkt->cmd != MemCmd::UpgradeReq) {
delete pkt->req; delete pkt->req;
@ -83,81 +81,85 @@ SimpleTimingPort::recvTiming(PacketPtr pkt)
return true; return true;
} }
void
SimpleTimingPort::recvRetry()
{
assert(!transmitList.empty());
if (Port::sendTiming(transmitList.front().pkt)) {
transmitList.pop_front();
DPRINTF(Bus, "No Longer waiting on retry\n");
if (!transmitList.empty()) {
Tick time = transmitList.front().tick;
sendEvent->schedule(time <= curTick ? curTick+1 : time);
}
}
if (transmitList.empty() && drainEvent) {
drainEvent->process();
drainEvent = NULL;
}
}
void void
SimpleTimingPort::sendTiming(PacketPtr pkt, Tick time) SimpleTimingPort::schedSendTiming(PacketPtr pkt, Tick when)
{ {
assert(when > curTick);
// Nothing is on the list: add it and schedule an event // Nothing is on the list: add it and schedule an event
if (transmitList.empty()) { if (transmitList.empty()) {
assert(!sendEvent->scheduled()); assert(!sendEvent->scheduled());
sendEvent->schedule(curTick+time); sendEvent->schedule(when);
transmitList.push_back(DeferredPacket(time+curTick, pkt)); transmitList.push_back(DeferredPacket(when, pkt));
return; return;
} }
// something is on the list and this belongs at the end // something is on the list and this belongs at the end
if (time+curTick >= transmitList.back().tick) { if (when >= transmitList.back().tick) {
transmitList.push_back(DeferredPacket(time+curTick, pkt)); transmitList.push_back(DeferredPacket(when, pkt));
return; return;
} }
// Something is on the list and this belongs somewhere else // Something is on the list and this belongs somewhere else
DeferredPacketIterator i = transmitList.begin(); DeferredPacketIterator i = transmitList.begin();
DeferredPacketIterator end = transmitList.end(); DeferredPacketIterator end = transmitList.end();
bool done = false;
while (i != end && !done) { for (; i != end; ++i) {
if (time+curTick < i->tick) { if (when < i->tick) {
if (i == transmitList.begin()) { if (i == transmitList.begin()) {
//Inserting at begining, reschedule //Inserting at begining, reschedule
sendEvent->reschedule(time+curTick); sendEvent->reschedule(when);
} }
transmitList.insert(i, DeferredPacket(time+curTick, pkt)); transmitList.insert(i, DeferredPacket(when, pkt));
done = true; return;
} }
i++;
} }
assert(done); assert(false); // should never get here
} }
void void
SimpleTimingPort::processSendEvent() SimpleTimingPort::sendDeferredPacket()
{ {
assert(transmitList.size()); assert(deferredPacketReady());
assert(transmitList.front().tick <= curTick); bool success = sendTiming(transmitList.front().pkt);
if (Port::sendTiming(transmitList.front().pkt)) {
if (success) {
//send successful, remove packet //send successful, remove packet
transmitList.pop_front(); transmitList.pop_front();
if (!transmitList.empty()) { if (!transmitList.empty()) {
Tick time = transmitList.front().tick; Tick time = transmitList.front().tick;
sendEvent->schedule(time <= curTick ? curTick+1 : time); sendEvent->schedule(time <= curTick ? curTick+1 : time);
} }
if (transmitList.empty() && drainEvent) { if (transmitList.empty() && drainEvent) {
drainEvent->process(); drainEvent->process();
drainEvent = NULL; drainEvent = NULL;
} }
return;
} }
// send unsuccessful (due to flow control). Will get retry
// callback later; save for then if not already waitingOnRetry = !success;
DPRINTF(Bus, "Waiting on retry\n");
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();
} }

View file

@ -94,15 +94,29 @@ class SimpleTimingPort : public Port
* here.*/ * here.*/
Event *drainEvent; Event *drainEvent;
/** Remember whether we're awaiting a retry from the bus. */
bool waitingOnRetry;
/** Check the list of buffered packets against the supplied /** Check the list of buffered packets against the supplied
* functional request. */ * functional request. */
void checkFunctional(PacketPtr funcPkt); void checkFunctional(PacketPtr funcPkt);
/** Check whether we have a packet ready to go on the transmit list. */
bool deferredPacketReady()
{ return !transmitList.empty() && transmitList.front().tick <= curTick; }
/** Schedule a sendTiming() event to be called in the future. /** Schedule a sendTiming() event to be called in the future.
* @param pkt packet to send * @param pkt packet to send
* @param time increment from now (in ticks) to send packet * @param absolute time (in ticks) to send packet
*/ */
void sendTiming(PacketPtr pkt, Tick time); void schedSendTiming(PacketPtr pkt, Tick when);
/** Attempt to send the packet at the head of the deferred packet
* list. Caller must guarantee that the deferred packet list is
* non-empty and that the head packet is scheduled for curTick (or
* earlier).
*/
void sendDeferredPacket();
/** This function is notification that the device should attempt to send a /** This function is notification that the device should attempt to send a
* packet again. */ * packet again. */
@ -126,7 +140,8 @@ class SimpleTimingPort : public Port
SimpleTimingPort(std::string pname, MemObject *_owner = NULL) SimpleTimingPort(std::string pname, MemObject *_owner = NULL)
: Port(pname, _owner), : Port(pname, _owner),
sendEvent(new SendEvent(this)), sendEvent(new SendEvent(this)),
drainEvent(NULL) drainEvent(NULL),
waitingOnRetry(false)
{} {}
~SimpleTimingPort() { delete sendEvent; } ~SimpleTimingPort() { delete sendEvent; }