From 41f6cbce9aa24f9cd8a6eb4a340dcc2e9671cdcb Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Mon, 28 May 2007 08:11:43 -0700 Subject: Restructure SimpleTimingPort a bit: - factor out checkFunctional() code so it can be called from derived classes - use EventWrapper for sendEvent, move event handling code from event to port where it belongs - make sendEvent a pointer so derived classes can override it - replace std::pair with new class for readability --HG-- extra : convert_revision : 5709de2daacfb751a440144ecaab5f9fc02e6b7a --- src/mem/physical.cc | 15 +--------- src/mem/tport.cc | 84 ++++++++++++++++++++++++++++------------------------- src/mem/tport.hh | 47 +++++++++++++++++++----------- 3 files changed, 76 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/src/mem/physical.cc b/src/mem/physical.cc index 6621c36cf..9d840fe69 100644 --- a/src/mem/physical.cc +++ b/src/mem/physical.cc @@ -414,20 +414,7 @@ PhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt) void PhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt) { - //Since we are overriding the function, make sure to have the impl of the - //check or functional accesses here. - std::list >::iterator i = transmitList.begin(); - std::list >::iterator end = transmitList.end(); - bool notDone = true; - - while (i != end && notDone) { - PacketPtr target = i->second; - // If the target contains data, and it overlaps the - // probed request, need to update data - if (target->intersect(pkt)) - notDone = fixPacket(pkt, target); - i++; - } + checkFunctional(pkt); // Default implementation of SimpleTimingPort::recvFunctional() // calls recvAtomic() and throws away the latency; we can save a diff --git a/src/mem/tport.cc b/src/mem/tport.cc index 9a4bd7967..8797cf6e6 100644 --- a/src/mem/tport.cc +++ b/src/mem/tport.cc @@ -31,23 +31,32 @@ #include "mem/tport.hh" void -SimpleTimingPort::recvFunctional(PacketPtr pkt) +SimpleTimingPort::checkFunctional(PacketPtr pkt) { - std::list >::iterator i = transmitList.begin(); - std::list >::iterator end = transmitList.end(); - bool notDone = true; + DeferredPacketIterator i = transmitList.begin(); + DeferredPacketIterator end = transmitList.end(); - while (i != end && notDone) { - PacketPtr target = i->second; + while (i != end) { + PacketPtr target = i->pkt; // If the target contains data, and it overlaps the // probed request, need to update data - if (target->intersect(pkt)) - notDone = fixPacket(pkt, target); + if (target->intersect(pkt)) { + if (!fixPacket(pkt, target)) { + // fixPacket returns true for continue, false for done + return; + } + } i++; } +} - //Then just do an atomic access and throw away the returned latency +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); } @@ -67,12 +76,9 @@ SimpleTimingPort::recvTiming(PacketPtr pkt) pkt->makeTimingResponse(); sendTiming(pkt, latency); } - else { - if (pkt->cmd != MemCmd::UpgradeReq) - { - delete pkt->req; - delete pkt; - } + else if (pkt->cmd != MemCmd::UpgradeReq) { + delete pkt->req; + delete pkt; } return true; } @@ -81,12 +87,12 @@ void SimpleTimingPort::recvRetry() { assert(!transmitList.empty()); - if (Port::sendTiming(transmitList.front().second)) { + if (Port::sendTiming(transmitList.front().pkt)) { transmitList.pop_front(); DPRINTF(Bus, "No Longer waiting on retry\n"); if (!transmitList.empty()) { - Tick time = transmitList.front().first; - sendEvent.schedule(time <= curTick ? curTick+1 : time); + Tick time = transmitList.front().tick; + sendEvent->schedule(time <= curTick ? curTick+1 : time); } } @@ -101,29 +107,29 @@ SimpleTimingPort::sendTiming(PacketPtr pkt, Tick time) { // Nothing is on the list: add it and schedule an event if (transmitList.empty()) { - assert(!sendEvent.scheduled()); - sendEvent.schedule(curTick+time); - transmitList.push_back(std::pair(time+curTick,pkt)); + assert(!sendEvent->scheduled()); + sendEvent->schedule(curTick+time); + transmitList.push_back(DeferredPacket(time+curTick, pkt)); return; } // something is on the list and this belongs at the end - if (time+curTick >= transmitList.back().first) { - transmitList.push_back(std::pair(time+curTick,pkt)); + if (time+curTick >= transmitList.back().tick) { + transmitList.push_back(DeferredPacket(time+curTick, pkt)); return; } // Something is on the list and this belongs somewhere else - std::list >::iterator i = transmitList.begin(); - std::list >::iterator end = transmitList.end(); + DeferredPacketIterator i = transmitList.begin(); + DeferredPacketIterator end = transmitList.end(); bool done = false; while (i != end && !done) { - if (time+curTick < i->first) { + if (time+curTick < i->tick) { if (i == transmitList.begin()) { //Inserting at begining, reschedule - sendEvent.reschedule(time+curTick); + sendEvent->reschedule(time+curTick); } - transmitList.insert(i,std::pair(time+curTick,pkt)); + transmitList.insert(i, DeferredPacket(time+curTick, pkt)); done = true; } i++; @@ -132,20 +138,20 @@ SimpleTimingPort::sendTiming(PacketPtr pkt, Tick time) } void -SimpleTimingPort::SendEvent::process() +SimpleTimingPort::processSendEvent() { - assert(port->transmitList.size()); - assert(port->transmitList.front().first <= curTick); - if (port->Port::sendTiming(port->transmitList.front().second)) { + assert(transmitList.size()); + assert(transmitList.front().tick <= curTick); + if (Port::sendTiming(transmitList.front().pkt)) { //send successful, remove packet - port->transmitList.pop_front(); - if (!port->transmitList.empty()) { - Tick time = port->transmitList.front().first; - schedule(time <= curTick ? curTick+1 : time); + 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; } return; } diff --git a/src/mem/tport.hh b/src/mem/tport.hh index 3d28ea3e5..9e8a01786 100644 --- a/src/mem/tport.hh +++ b/src/mem/tport.hh @@ -58,9 +58,26 @@ class SimpleTimingPort : public Port { protected: + /** A deferred packet, buffered to transmit later. */ + class DeferredPacket { + public: + Tick tick; ///< The tick when the packet is ready to transmit + PacketPtr pkt; ///< Pointer to the packet to transmit + DeferredPacket(Tick t, PacketPtr p) + : tick(t), pkt(p) + {} + }; + + typedef std::list DeferredPacketList; + typedef std::list::iterator DeferredPacketIterator; + /** A list of outgoing timing response packets that haven't been * serviced yet. */ - std::list > transmitList; + DeferredPacketList transmitList; + + /** This function attempts to send deferred packets. Scheduled to + * be called in the future via SendEvent. */ + void processSendEvent(); /** * This class is used to implemented sendTiming() with a delay. When @@ -68,27 +85,19 @@ class SimpleTimingPort : public Port * When the event time expires it attempts to send the packet. * If it cannot, the packet sent when recvRetry() is called. **/ - class SendEvent : public Event - { - SimpleTimingPort *port; - - public: - SendEvent(SimpleTimingPort *p) - : Event(&mainEventQueue), port(p) - { } - - virtual void process(); - - virtual const char *description() - { return "Future scheduled sendTiming event"; } - }; + typedef EventWrapper + SendEvent; - SendEvent sendEvent; + Event *sendEvent; /** If we need to drain, keep the drain event around until we're done * here.*/ Event *drainEvent; + /** Check the list of buffered packets against the supplied + * functional request. */ + void checkFunctional(PacketPtr funcPkt); + /** 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 @@ -115,9 +124,13 @@ class SimpleTimingPort : public Port public: SimpleTimingPort(std::string pname, MemObject *_owner = NULL) - : Port(pname, _owner), sendEvent(this), drainEvent(NULL) + : Port(pname, _owner), + sendEvent(new SendEvent(this)), + drainEvent(NULL) {} + ~SimpleTimingPort() { delete sendEvent; } + /** Hook for draining timing accesses from the system. The * associated SimObject's drain() functions should be implemented * something like this when this class is used: -- cgit v1.2.3