Restructure bus timing calcs to cope with pkt being deleted by target.
authorSteve Reinhardt <stever@gmail.com>
Mon, 17 Mar 2008 07:07:38 +0000 (03:07 -0400)
committerSteve Reinhardt <stever@gmail.com>
Mon, 17 Mar 2008 07:07:38 +0000 (03:07 -0400)
--HG--
extra : convert_revision : db8497e73a44f2a06aab121e797e88b4c0c31330

src/mem/bus.cc
src/mem/bus.hh

index ff4512aca1b79aa9a9ae7466976343aae87a3154..3bf1c6cfc5f0f9e255574b028a4499009354b427 100644 (file)
@@ -110,21 +110,22 @@ const char * Bus::BusFreeEvent::description() const
     return "bus became available";
 }
 
-void Bus::preparePacket(PacketPtr pkt, Tick & headerTime)
+Tick Bus::calcPacketTiming(PacketPtr pkt)
 {
-    //Bring tickNextIdle up to the present tick
-    //There is some potential ambiguity where a cycle starts, which might make
-    //a difference when devices are acting right around a cycle boundary. Using
-    //a < allows things which happen exactly on a cycle boundary to take up
-    //only the following cycle. Anything that happens later will have to "wait"
-    //for the end of that cycle, and then start using the bus after that.
+    // Bring tickNextIdle up to the present tick.
+    // There is some potential ambiguity where a cycle starts, which
+    // might make a difference when devices are acting right around a
+    // cycle boundary. Using a < allows things which happen exactly on
+    // a cycle boundary to take up only the following cycle. Anything
+    // that happens later will have to "wait" for the end of that
+    // cycle, and then start using the bus after that.
     if (tickNextIdle < curTick) {
         tickNextIdle = curTick;
         if (tickNextIdle % clock != 0)
             tickNextIdle = curTick - (curTick % clock) + clock;
     }
 
-    headerTime = tickNextIdle + headerCycles * clock;
+    Tick headerTime = tickNextIdle + headerCycles * clock;
 
     // The packet will be sent. Figure out how long it occupies the bus, and
     // how much of that time is for the first "word", aka bus width.
@@ -142,10 +143,17 @@ void Bus::preparePacket(PacketPtr pkt, Tick & headerTime)
     pkt->firstWordTime = headerTime + clock;
 
     pkt->finishTime = headerTime + numCycles * clock;
+
+    return headerTime;
 }
 
 void Bus::occupyBus(Tick until)
 {
+    if (until == 0) {
+        // shortcut for express snoop packets
+        return;
+    }
+
     tickNextIdle = until;
 
     if (!busIdle.scheduled()) {
@@ -190,11 +198,8 @@ Bus::recvTiming(PacketPtr pkt)
     DPRINTF(Bus, "recvTiming: src %d dst %d %s 0x%x\n",
             src, pkt->getDest(), pkt->cmdString(), pkt->getAddr());
 
-    Tick headerTime = 0;
-
-    if (!pkt->isExpressSnoop()) {
-        preparePacket(pkt, headerTime);
-    }
+    Tick headerFinishTime = pkt->isExpressSnoop() ? 0 : calcPacketTiming(pkt);
+    Tick packetFinishTime = pkt->isExpressSnoop() ? 0 : pkt->finishTime;
 
     short dest = pkt->getDest();
     int dest_port_id;
@@ -243,17 +248,16 @@ Bus::recvTiming(PacketPtr pkt)
             DPRINTF(Bus, "recvTiming: src %d dst %d %s 0x%x TGT RETRY\n",
                     src, pkt->getDest(), pkt->cmdString(), pkt->getAddr());
             addToRetryList(src_port);
-            if (!pkt->isExpressSnoop()) {
-                occupyBus(headerTime);
-            }
+            occupyBus(headerFinishTime);
             return false;
         }
-        // send OK, fall through
+        // send OK, fall through... pkt may have been deleted by
+        // target at this point, so it should *not* be referenced
+        // again.  We'll set it to NULL here just to be safe.
+        pkt = NULL;
     }
 
-    if (!pkt->isExpressSnoop()) {
-        occupyBus(pkt->finishTime);
-    }
+    occupyBus(packetFinishTime);
 
     // Packet was successfully sent.
     // Also take care of retries
index 274c02de417d39dbf7a1aa4947f57dc74c3908e3..74901d6268dac9a9c69823e15e605ec58b0e31ff 100644 (file)
@@ -245,10 +245,12 @@ class Bus : public MemObject
      */
     void addressRanges(AddrRangeList &resp, bool &snoop, int id);
 
-    /** Prepare a packet to be sent on the bus. The header finishes at tick
-     *  headerTime
+    /** Calculate the timing parameters for the packet.  Updates the
+     * firstWordTime and finishTime fields of the packet object.
+     * Returns the tick at which the packet header is completed (which
+     * will be all that is sent if the target rejects the packet).
      */
-    void preparePacket(PacketPtr pkt, Tick & headerTime);
+    Tick calcPacketTiming(PacketPtr pkt);
 
     /** Occupy the bus until until */
     void occupyBus(Tick until);