O3: Fix bug when a squash occurs right before TLB miss returns.
authorAli Saidi <Ali.Saidi@ARM.com>
Wed, 23 Feb 2011 21:10:49 +0000 (15:10 -0600)
committerAli Saidi <Ali.Saidi@ARM.com>
Wed, 23 Feb 2011 21:10:49 +0000 (15:10 -0600)
In this case we need to throw away the TLB miss, not assume it was the
one we were waiting for.

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

index 647c48a763668c701de6c42f24a4dbb0fd564728..c5165810449a40057fff476381347c3d507c6fa9 100644 (file)
@@ -522,6 +522,10 @@ class DefaultFetch
      * due to a squash.
      */
     Stats::Scalar fetchIcacheSquashes;
+    /** Total number of outstanding tlb accesses that were dropped
+     * due to a squash.
+     */
+    Stats::Scalar fetchTlbSquashes;
     /** Distribution of number of instructions fetched each cycle. */
     Stats::Distribution fetchNisnDist;
     /** Rate of how often fetch was idle. */
index d2cde496e5cc1c9c1ab5e616d6e4eb7a0f154289..2c490676071228e17efb8d32029a9945b7cce7f7 100644 (file)
@@ -268,6 +268,11 @@ DefaultFetch<Impl>::regStats()
         .desc("Number of outstanding Icache misses that were squashed")
         .prereq(fetchIcacheSquashes);
 
+    fetchTlbSquashes
+        .name(name() + ".ItlbSquashes")
+        .desc("Number of outstanding ITLB misses that were squashed")
+        .prereq(fetchTlbSquashes);
+
     fetchNisnDist
         .init(/* base value */ 0,
               /* last value */ fetchWidth,
@@ -580,6 +585,9 @@ DefaultFetch<Impl>::fetchCacheLine(Addr vaddr, ThreadID tid, Addr pc)
     // Align the fetch address so it's at the start of a cache block.
     Addr block_PC = icacheBlockAlignPC(vaddr);
 
+    DPRINTF(Fetch, "[tid:%i] Fetching cache line %#x for addr %#x\n",
+            tid, block_PC, vaddr);
+
     // Setup the memReq to do a read of the first instruction's address.
     // Set the appropriate read size and flags as well.
     // Build request here.
@@ -607,6 +615,16 @@ DefaultFetch<Impl>::finishTranslation(Fault fault, RequestPtr mem_req)
     // Wake up CPU if it was idle
     cpu->wakeCPU();
 
+    if (fetchStatus[tid] != ItlbWait || mem_req != memReq[tid] ||
+        mem_req->getVaddr() != memReq[tid]->getVaddr() || isSwitchedOut()) {
+        DPRINTF(Fetch, "[tid:%i] Ignoring itlb completed after squash\n",
+                tid);
+        ++fetchTlbSquashes;
+        delete mem_req;
+        return;
+    }
+
+
     // If translation was successful, attempt to read the icache block.
     if (fault == NoFault) {
         // Build packet here.
@@ -639,6 +657,8 @@ DefaultFetch<Impl>::finishTranslation(Fault fault, RequestPtr mem_req)
             fetchStatus[tid] = IcacheWaitResponse;
         }
     } else {
+        DPRINTF(Fetch, "[tid:%i] Got back req with addr %#x but expected %#x\n",
+                mem_req->getVaddr(), memReq[tid]->getVaddr());
         // Translation faulted, icache request won't be sent.
         delete mem_req;
         memReq[tid] = NULL;
@@ -648,6 +668,7 @@ DefaultFetch<Impl>::finishTranslation(Fault fault, RequestPtr mem_req)
         // wake up is if a squash comes along and changes the PC.
         TheISA::PCState fetchPC = pc[tid];
 
+        DPRINTF(Fetch, "[tid:%i]: Translation faulted, building noop.\n", tid);
         // We will use a nop in ordier to carry the fault.
         DynInstPtr instruction = buildInst(tid,
                 StaticInstPtr(TheISA::NoopMachInst, fetchPC.instAddr()),
@@ -686,6 +707,10 @@ DefaultFetch<Impl>::doSquash(const TheISA::PCState &newPC, ThreadID tid)
         DPRINTF(Fetch, "[tid:%i]: Squashing outstanding Icache miss.\n",
                 tid);
         memReq[tid] = NULL;
+    } else if (fetchStatus[tid] == ItlbWait) {
+        DPRINTF(Fetch, "[tid:%i]: Squashing outstanding ITLB miss.\n",
+                tid);
+        memReq[tid] = NULL;
     }
 
     // Get rid of the retrying packet if it was from this thread.
@@ -1120,8 +1145,12 @@ DefaultFetch<Impl>::fetch(bool &status_change)
             DPRINTF(Fetch, "[tid:%i]: Fetch is waiting ITLB walk to "
                     "finish! \n", tid);
             ++fetchTlbCycles;
+        } else if (fetchStatus[tid] == TrapPending) {
+            DPRINTF(Fetch, "[tid:%i]: Fetch is waiting for a pending trap\n",
+                    tid);
         }
 
+
         // Status is Idle, Squashing, Blocked, ItlbWait or IcacheWaitResponse
         // so fetch should do nothing.
         return;