Fixes to the bus, and added fields to the packet.
authorGabe Black <gblack@eecs.umich.edu>
Tue, 10 Oct 2006 03:24:21 +0000 (23:24 -0400)
committerGabe Black <gblack@eecs.umich.edu>
Tue, 10 Oct 2006 03:24:21 +0000 (23:24 -0400)
src/mem/bus.cc:
    Put back the check to see if the bus is busy. Also, populate the fields in the packet to indicate when the first word and the entire packet will be delivered.
src/mem/bus.hh:
    Remove the occupyBus function.
src/mem/packet.hh:
    Added fields to the packet to indicate when the first chunk of a packet arrives, and when the entire packet arrives.

--HG--
extra : convert_revision : cfc7670a33913d48a04d02c6d2448290a51f2d3c

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

index 7584ffffd948bda4b770a79ab1e7d0945609ac2e..66cd581e7fbdf0f0ccefd48995eecc0b0725d5d8 100644 (file)
@@ -82,33 +82,6 @@ const char * Bus::BusFreeEvent::description()
     return "bus became available";
 }
 
-void
-Bus::occupyBus(int numCycles)
-{
-    //Move up when the bus will next be free
-    //We avoid the use of divide by adding repeatedly
-    //This should be faster if the value is updated frequently, but should
-    //be may be slower otherwise.
-
-    //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. Anthing that happens later will have to "wait" for the
-    //end of that cycle, and then start using the bus after that.
-    while (tickNextIdle < curTick)
-        tickNextIdle += clock;
-    //Advance it numCycles bus cycles.
-    //XXX Should this use the repeating add trick as well?
-    tickNextIdle += (numCycles * clock);
-    if (!busIdle.scheduled()) {
-        busIdle.schedule(tickNextIdle);
-    } else {
-        busIdle.reschedule(tickNextIdle);
-    }
-    DPRINTF(Bus, "The bus is now occupied from tick %d to %d\n", curTick, tickNextIdle);
-}
-
 /** Function called by the port when the bus is receiving a Timing
  * transaction.*/
 bool
@@ -120,6 +93,14 @@ Bus::recvTiming(Packet *pkt)
 
     Port *pktPort = interfaces[pkt->getSrc()];
 
+    // If the bus is busy, or other devices are in line ahead of the current
+    // one, put this device on the retry list.
+    if (tickNextIdle > curTick ||
+            (retryList.size() && pktPort != retryingPort)) {
+        addToRetryList(pktPort);
+        return false;
+    }
+
     short dest = pkt->getDest();
     if (dest == Packet::Broadcast) {
         if (timingSnoop(pkt)) {
@@ -146,7 +127,17 @@ Bus::recvTiming(Packet *pkt)
         port = interfaces[dest];
     }
 
-    // The packet will be sent. Figure out how long it occupies the bus.
+    //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. Anthing that happens later will have to "wait" for
+    //the end of that cycle, and then start using the bus after that.
+    while (tickNextIdle < curTick)
+        tickNextIdle += 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.
     int numCycles = 0;
     // Requests need one cycle to send an address
     if (pkt->isRequest())
@@ -167,7 +158,26 @@ Bus::recvTiming(Packet *pkt)
         }
     }
 
-    occupyBus(numCycles);
+    // The first word will be delivered after the current tick, the delivery
+    // of the address if any, and one bus cycle to deliver the data
+    pkt->firstWordTime =
+        tickNextIdle +
+        pkt->isRequest() ? clock : 0 +
+        clock;
+
+    //Advance it numCycles bus cycles.
+    //XXX Should this use the repeated addition trick as well?
+    tickNextIdle += (numCycles * clock);
+    if (!busIdle.scheduled()) {
+        busIdle.schedule(tickNextIdle);
+    } else {
+        busIdle.reschedule(tickNextIdle);
+    }
+    DPRINTF(Bus, "The bus is now occupied from tick %d to %d\n",
+            curTick, tickNextIdle);
+
+    // The bus will become idle once the current packet is delivered.
+    pkt->finishTime = tickNextIdle;
 
     if (port->sendTiming(pkt))  {
         // Packet was successfully sent. Return true.
index a89738775cb0650292b33b12b6977193cb02cea4..ce3f4bed7f0fed34ed5e422189df48665b6f8918 100644 (file)
@@ -195,8 +195,6 @@ class Bus : public MemObject
 
     BusFreeEvent busIdle;
 
-    void occupyBus(int numCycles);
-
     Port * retryingPort;
 
     /** An array of pointers to the peer port interfaces
index 4d57aee75c4bdd91e09242cc7b53fc4991cc721a..28864522f8a8304d0e4a951567a3ab8ef14f0cad 100644 (file)
@@ -90,7 +90,6 @@ class Packet
      *   be called on it rather than simply delete.*/
     bool arrayData;
 
-
     /** The address of the request.  This address could be virtual or
      *   physical, depending on the system configuration. */
     Addr addr;
@@ -122,6 +121,12 @@ class Packet
     /** Used to calculate latencies for each packet.*/
     Tick time;
 
+    /** The time at which the packet will be fully transmitted */
+    Tick finishTime;
+
+    /** The time at which the first chunk of the packet will be transmitted */
+    Tick firstWordTime;
+
     /** The special destination address indicating that the packet
      *   should be routed based on its address. */
     static const short Broadcast = -1;