O3 CPU: Strengthen condition for handling interrupts
authorNilay Vaish <nilay@cs.wisc.edu>
Fri, 10 Feb 2012 14:37:30 +0000 (08:37 -0600)
committerNilay Vaish <nilay@cs.wisc.edu>
Fri, 10 Feb 2012 14:37:30 +0000 (08:37 -0600)
The condition for handling interrupts is to check whether or not the cpu's
instruction list is empty. As observed, this can lead to cases in which even
though the instruction list is empty, interrupts are handled when they should
not be. The condition is being strengthened so that interrupts get handled only
when the last committed microop did not had IsDelayedCommit set.

src/cpu/o3/commit.hh
src/cpu/o3/commit_impl.hh
src/cpu/o3/fetch_impl.hh

index f35928b08b367be74d91864854d8e3b5bae7408a..0945186555f1cb1ec2d8e5da724bc4c327ad2060 100644 (file)
@@ -441,6 +441,9 @@ class DefaultCommit
     /** Rename map interface. */
     RenameMap *renameMap[Impl::MaxThreads];
 
+    /** True if last committed microop can be followed by an interrupt */
+    bool canHandleInterrupts;
+
     /** Updates commit stats based on this instruction. */
     void updateComInstStats(DynInstPtr &inst);
 
index a9b7959331e8aa68e6f1f2bec52061fc1ee3dd9a..446c8e6f3d0762435bd3cf20d8a994248dade67d 100644 (file)
@@ -105,7 +105,8 @@ DefaultCommit<Impl>::DefaultCommit(O3CPU *_cpu, DerivO3CPUParams *params)
       numThreads(params->numThreads),
       drainPending(false),
       switchedOut(false),
-      trapLatency(params->trapLatency)
+      trapLatency(params->trapLatency),
+      canHandleInterrupts(true)
 {
     _status = Active;
     _nextStatus = Inactive;
@@ -714,7 +715,7 @@ DefaultCommit<Impl>::handleInterrupt()
 
     // Wait until all in flight instructions are finished before enterring
     // the interrupt.
-    if (cpu->instList.empty()) {
+    if (canHandleInterrupts && cpu->instList.empty()) {
         // Squash or record that I need to squash this cycle if
         // an interrupt needed to be handled.
         DPRINTF(Commit, "Interrupt detected.\n");
@@ -743,7 +744,10 @@ DefaultCommit<Impl>::handleInterrupt()
 
         interrupt = NoFault;
     } else {
-        DPRINTF(Commit, "Interrupt pending, waiting for ROB to empty.\n");
+        DPRINTF(Commit, "Interrupt pending: instruction is %sin "
+                "flight, ROB is %sempty\n",
+                canHandleInterrupts ? "not " : "",
+                cpu->instList.empty() ? "" : "not " );
     }
 }
 
@@ -775,11 +779,6 @@ void
 DefaultCommit<Impl>::commit()
 {
     if (FullSystem) {
-        // Check for any interrupt that we've already squashed for and
-        // start processing it.
-        if (interrupt != NoFault)
-            handleInterrupt();
-
         // Check if we have a interrupt and get read to handle it
         if (cpu->checkInterrupts(cpu->tcBase(0)))
             propagateInterrupt();
@@ -936,6 +935,11 @@ DefaultCommit<Impl>::commitInsts()
     // Commit as many instructions as possible until the commit bandwidth
     // limit is reached, or it becomes impossible to commit any more.
     while (num_committed < commitWidth) {
+        // Check for any interrupt that we've already squashed for
+        // and start processing it.
+        if (interrupt != NoFault)
+            handleInterrupt();
+
         int commit_thread = getCommittingThread();
 
         if (commit_thread == -1 || !rob->isHeadReady(commit_thread))
@@ -992,6 +996,12 @@ DefaultCommit<Impl>::commitInsts()
                     cpu->instDone(tid);
                 }
 
+                if (tid == 0) {
+                    canHandleInterrupts =  (!head_inst->isDelayedCommit()) &&
+                                           ((THE_ISA != ALPHA_ISA) ||
+                                             (!(pc[0].instAddr() & 0x3)));
+                }
+
                 // Updates misc. registers.
                 head_inst->updateMiscRegs();
 
index 48c21917a7844ab3ac986f474522cf8ab8467e71..72d9e960e6386d58b417010b583fad457b95863d 100644 (file)
@@ -1144,6 +1144,7 @@ DefaultFetch<Impl>::fetch(bool &status_change)
             // an delayed commit micro-op currently (delayed commit instructions
             // are not interruptable by interrupts, only faults)
             ++fetchMiscStallCycles;
+            DPRINTF(Fetch, "[tid:%i]: Fetch is stalled!\n", tid);
             return;
         }
     } else {