A little more cleanup & refactoring of SimpleTimingPort.

Make it a better base class for cache ports.

--HG--
extra : convert_revision : 37d6de11545a68c1a7d11ce33fe5971c51434ee4
This commit is contained in:
Steve Reinhardt 2007-05-29 22:23:41 -07:00
parent cd423aa9dd
commit 365e4ac374
2 changed files with 63 additions and 46 deletions

View file

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

View file

@ -94,15 +94,29 @@ class SimpleTimingPort : public Port
* here.*/
Event *drainEvent;
/** Remember whether we're awaiting a retry from the bus. */
bool waitingOnRetry;
/** Check the list of buffered packets against the supplied
* functional request. */
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.
* @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
* packet again. */
@ -126,7 +140,8 @@ class SimpleTimingPort : public Port
SimpleTimingPort(std::string pname, MemObject *_owner = NULL)
: Port(pname, _owner),
sendEvent(new SendEvent(this)),
drainEvent(NULL)
drainEvent(NULL),
waitingOnRetry(false)
{}
~SimpleTimingPort() { delete sendEvent; }