Allow for fetch to retry access if the sendTiming call fails.
authorKevin Lim <ktlim@umich.edu>
Fri, 9 Jun 2006 16:29:31 +0000 (12:29 -0400)
committerKevin Lim <ktlim@umich.edu>
Fri, 9 Jun 2006 16:29:31 +0000 (12:29 -0400)
--HG--
extra : convert_revision : ddbcf82e0a3160c93c4e51f5d60b0a7b5983d3ba

src/cpu/o3/fetch.hh
src/cpu/o3/fetch_impl.hh

index 9e8aeb8fb2903179365cca671d1895dd805a7e59..960d42178fe50fecf26abb7e84d2f37dff8c283d 100644 (file)
@@ -115,7 +115,7 @@ class DefaultFetch
         QuiescePending,
         SwitchOut,
         IcacheWaitResponse,
-        IcacheRetry,
+        IcacheWaitRetry,
         IcacheAccessComplete
     };
 
@@ -268,6 +268,8 @@ class DefaultFetch
     }
 
   private:
+    void recvRetry();
+
     /** Returns the appropriate thread to fetch, given the fetch policy. */
     int getFetchingThread(FetchPriority &fetch_priority);
 
@@ -360,6 +362,15 @@ class DefaultFetch
     /** The width of fetch in instructions. */
     unsigned fetchWidth;
 
+    /** Is the cache blocked?  If so no threads can access it. */
+    bool cacheBlocked;
+
+    /** The packet that is waiting to be retried. */
+    PacketPtr retryPkt;
+
+    /** The thread that is waiting on the cache to tell fetch to retry. */
+    int retryTid;
+
     /** Cache block size. */
     int cacheBlkSize;
 
index 152b69788a02f8088df2e9d1a2854156452a0be9..e75bc264bae20dcbb9c6ac249c40ff36617daa26 100644 (file)
@@ -88,18 +88,7 @@ template<class Impl>
 void
 DefaultFetch<Impl>::IcachePort::recvRetry()
 {
-    panic("DefaultFetch doesn't support retry yet.");
-    // we shouldn't get a retry unless we have a packet that we're
-    // waiting to transmit
-/*
-    assert(cpu->dcache_pkt != NULL);
-    assert(cpu->_status == DcacheRetry);
-    Packet *tmp = cpu->dcache_pkt;
-    if (sendTiming(tmp)) {
-        cpu->_status = DcacheWaitResponse;
-        cpu->dcache_pkt = NULL;
-    }
-*/
+    fetch->recvRetry();
 }
 
 template<class Impl>
@@ -111,6 +100,9 @@ DefaultFetch<Impl>::DefaultFetch(Params *params)
       iewToFetchDelay(params->iewToFetchDelay),
       commitToFetchDelay(params->commitToFetchDelay),
       fetchWidth(params->fetchWidth),
+      cacheBlocked(false),
+      retryPkt(NULL),
+      retryTid(-1),
       numThreads(params->numberOfThreads),
       numFetchingThreads(params->smtNumFetchingThreads),
       interruptPending(false),
@@ -510,9 +502,11 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
     unsigned flags = 0;
 #endif // FULL_SYSTEM
 
-    if (interruptPending && flags == 0 || switchedOut) {
-        // Hold off fetch from getting new instructions while an interrupt
-        // is pending.
+    if (cacheBlocked || (interruptPending && flags == 0) || switchedOut) {
+        // Hold off fetch from getting new instructions when:
+        // Cache is blocked, or
+        // while an interrupt is pending and we're not in PAL mode, or
+        // fetch is switched out.
         return false;
     }
 
@@ -528,11 +522,7 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
     memReq[tid] = mem_req;
 
     // Translate the instruction request.
-//#if FULL_SYSTEM
     fault = cpu->translateInstReq(mem_req, cpu->thread[tid]);
-//#else
-//    fault = pTable->translate(memReq[tid]);
-//#endif
 
     // In the case of faults, the fetch stage may need to stall and wait
     // for the ITB miss to be handled.
@@ -563,8 +553,13 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
         // Now do the timing access to see whether or not the instruction
         // exists within the cache.
         if (!icachePort->sendTiming(data_pkt)) {
+            assert(retryPkt == NULL);
+            assert(retryTid == -1);
             DPRINTF(Fetch, "[tid:%i] Out of MSHRs!\n", tid);
-            ret_fault = NoFault;
+            fetchStatus[tid] = IcacheWaitRetry;
+            retryPkt = data_pkt;
+            retryTid = tid;
+            cacheBlocked = true;
             return false;
         }
 
@@ -604,6 +599,16 @@ DefaultFetch<Impl>::doSquash(const Addr &new_PC, unsigned tid)
         memReq[tid] = NULL;
     }
 
+    // Get rid of the retrying packet if it was from this thread.
+    if (retryTid == tid) {
+        assert(cacheBlocked);
+        cacheBlocked = false;
+        retryTid = -1;
+        retryPkt = NULL;
+        delete retryPkt->req;
+        delete retryPkt;
+    }
+
     fetchStatus[tid] = Squashing;
 
     ++fetchSquashCycles;
@@ -1103,6 +1108,28 @@ DefaultFetch<Impl>::fetch(bool &status_change)
     }
 }
 
+template<class Impl>
+void
+DefaultFetch<Impl>::recvRetry()
+{
+    assert(cacheBlocked);
+    if (retryPkt != NULL) {
+        assert(retryTid != -1);
+        assert(fetchStatus[retryTid] == IcacheWaitRetry);
+
+        if (icachePort->sendTiming(retryPkt)) {
+            fetchStatus[retryTid] = IcacheWaitResponse;
+            retryPkt = NULL;
+            retryTid = -1;
+            cacheBlocked = false;
+        }
+    } else {
+        assert(retryTid == -1);
+        // Access has been squashed since it was sent out.  Just clear
+        // the cache being blocked.
+        cacheBlocked = false;
+    }
+}
 
 ///////////////////////////////////////
 //                                   //