Fix simple timing port keep a list of all packets, have only one event, and scan...
authorAli Saidi <saidi@eecs.umich.edu>
Wed, 25 Oct 2006 22:34:21 +0000 (18:34 -0400)
committerAli Saidi <saidi@eecs.umich.edu>
Wed, 25 Oct 2006 22:34:21 +0000 (18:34 -0400)
--HG--
extra : convert_revision : c735a6408443b5cc90d1c1841c7aeb61e02ec6ae

src/mem/tport.cc
src/mem/tport.hh

index 55a461a8b5182f6e4b5d6aeab37e5be197be477d..b9d5cbe4ae243f300ee73cedd22a28517fbd36d3 100644 (file)
 void
 SimpleTimingPort::recvFunctional(PacketPtr pkt)
 {
-    std::list<PacketPtr>::iterator i = transmitList.begin();
-    std::list<PacketPtr>::iterator end = transmitList.end();
+    std::list<std::pair<Tick,PacketPtr> >::iterator i = transmitList.begin();
+    std::list<std::pair<Tick,PacketPtr> >::iterator end = transmitList.end();
+    bool done = false;
 
-    while (i != end) {
-        PacketPtr target = *i;
+    while (i != end && !done) {
+        PacketPtr target = i->second;
         // If the target contains data, and it overlaps the
         // probed request, need to update data
         if (target->intersect(pkt))
-            fixPacket(pkt, target);
+            done = fixPacket(pkt, target);
 
     }
 
@@ -63,7 +64,7 @@ SimpleTimingPort::recvTiming(PacketPtr pkt)
     // turn packet around to go back to requester if response expected
     if (pkt->needsResponse()) {
         pkt->makeTimingResponse();
-        sendTimingLater(pkt, latency);
+        sendTiming(pkt, latency);
     }
     else {
         if (pkt->cmd != Packet::UpgradeReq)
@@ -78,14 +79,14 @@ SimpleTimingPort::recvTiming(PacketPtr pkt)
 void
 SimpleTimingPort::recvRetry()
 {
-    assert(outTiming > 0);
     assert(!transmitList.empty());
-    if (sendTiming(transmitList.front())) {
+    if (Port::sendTiming(transmitList.front().second)) {
         transmitList.pop_front();
-        outTiming--;
         DPRINTF(Bus, "No Longer waiting on retry\n");
-        if (!transmitList.empty())
-            sendTimingLater(transmitList.front(), 1);
+        if (!transmitList.empty()) {
+            Tick time = transmitList.front().first;
+            sendEvent.schedule(time <= curTick ? curTick+1 : time);
+        }
     }
 
     if (transmitList.empty() && drainEvent) {
@@ -94,39 +95,44 @@ SimpleTimingPort::recvRetry()
     }
 }
 
+void
+SimpleTimingPort::sendTiming(PacketPtr pkt, Tick time)
+{
+    if (transmitList.empty()) {
+        assert(!sendEvent.scheduled());
+        sendEvent.schedule(curTick+time);
+    }
+    transmitList.push_back(std::pair<Tick,PacketPtr>(time+curTick,pkt));
+}
+
 void
 SimpleTimingPort::SendEvent::process()
 {
-    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(port->transmitList.size());
+    assert(port->transmitList.front().first <= curTick);
+    if (port->Port::sendTiming(port->transmitList.front().second)) {
+        //send successful, remove packet
+        port->transmitList.pop_front();
+        if (!port->transmitList.empty()) {
+            Tick time = port->transmitList.front().first;
+            schedule(time <= curTick ? curTick+1 : time);
         }
         if (port->transmitList.empty() && port->drainEvent) {
             port->drainEvent->process();
             port->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);
+        return;
     }
+    // send unsuccessful (due to flow control).  Will get retry
+    // callback later; save for then if not already
+    DPRINTF(Bus, "Waiting on retry\n");
 }
 
 
 unsigned int
 SimpleTimingPort::drain(Event *de)
 {
-    if (outTiming == 0 && transmitList.size() == 0)
+    if (transmitList.size() == 0)
         return 0;
     drainEvent = de;
     return 1;
index fbe81c44350bdd1ad088b44452434f5cbd168b5e..438ec56dcfcc14ce11a32ccfb819bc8f62add262 100644 (file)
@@ -60,23 +60,22 @@ class SimpleTimingPort : public Port
   protected:
     /** A list of outgoing timing response packets that haven't been
      * serviced yet. */
-    std::list<PacketPtr> transmitList;
+    std::list<std::pair<Tick,PacketPtr> > transmitList;
 
     /**
      * This class is used to implemented sendTiming() with a delay. When
-     * a delay is requested a new event is created. When the event time
-     * expires it attempts to send the packet. If it cannot, the packet
-     * is pushed onto the transmit list to be sent when recvRetry() is
-     * called. */
+     * a delay is requested a the event is scheduled if it isn't already.
+     * 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;
-        PacketPtr packet;
 
       public:
-        SendEvent(SimpleTimingPort *p, PacketPtr pkt, Tick t)
-            : Event(&mainEventQueue), port(p), packet(pkt)
-        { setFlags(AutoDelete); schedule(curTick + t); }
+        SendEvent(SimpleTimingPort *p)
+            : Event(&mainEventQueue), port(p)
+        { }
 
         virtual void process();
 
@@ -84,19 +83,17 @@ class SimpleTimingPort : public Port
         { return "Future scheduled sendTiming event"; }
     };
 
-
-    /** Number of timing requests that are emulating the device timing before
-     * attempting to end up on the bus.
-     */
-    int outTiming;
+    SendEvent sendEvent;
 
     /** If we need to drain, keep the drain event around until we're done
      * here.*/
     Event *drainEvent;
 
-    /** Schedule a sendTiming() event to be called in the future. */
-    void sendTimingLater(PacketPtr pkt, Tick time)
-    { outTiming++; new SendEvent(this, pkt, time); }
+    /** 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
+     */
+    void sendTiming(PacketPtr pkt, Tick time);
 
     /** This function is notification that the device should attempt to send a
      * packet again. */
@@ -118,7 +115,7 @@ class SimpleTimingPort : public Port
   public:
 
     SimpleTimingPort(std::string pname)
-        : Port(pname), outTiming(0), drainEvent(NULL)
+        : Port(pname), sendEvent(this), drainEvent(NULL)
     {}
 
     /** Hook for draining timing accesses from the system.  The