changeset 40d24a672351 in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=40d24a672351
description:
        cpu: Fix o3 drain bug

        For X86, the o3 CPU would get stuck with the commit stage not being
        drained if an interrupt arrived while drain was pending. isDrained()
        makes sure that pcState.microPC() == 0, thus ensuring that we are at
        an instruction boundary. However, when we take an interrupt we
        execute:

            pcState.upc(romMicroPC(entry));
            pcState.nupc(romMicroPC(entry) + 1);
            tc->pcState(pcState);

        As a result, the MicroPC is no longer zero. This patch ensures the 
drain is
        delayed until no interrupts are present.  Once draining, non-synchronous
        interrupts are deffered until after the switch.

diffstat:

 src/cpu/o3/commit.hh      |  11 ++++++++++-
 src/cpu/o3/commit_impl.hh |  15 ++++++++++++---
 2 files changed, 22 insertions(+), 4 deletions(-)

diffs (72 lines):

diff -r 53278be85b40 -r 40d24a672351 src/cpu/o3/commit.hh
--- a/src/cpu/o3/commit.hh      Wed Sep 03 07:42:44 2014 -0400
+++ b/src/cpu/o3/commit.hh      Wed Sep 03 07:42:45 2014 -0400
@@ -438,9 +438,18 @@
     /** Number of Active Threads */
     ThreadID numThreads;
 
-    /** Is a drain pending. */
+    /** Is a drain pending? Commit is looking for an instruction boundary while
+     * there are no pending interrupts
+     */
     bool drainPending;
 
+    /** Is a drain imminent? Commit has found an instruction boundary while no
+     * interrupts were present or in flight.  This was the last architecturally
+     * committed instruction.  Interrupts disabled and pipeline flushed.
+     * Waiting for structures to finish draining.
+     */
+    bool drainImminent;
+
     /** The latency to handle a trap.  Used when scheduling trap
      * squash event.
      */
diff -r 53278be85b40 -r 40d24a672351 src/cpu/o3/commit_impl.hh
--- a/src/cpu/o3/commit_impl.hh Wed Sep 03 07:42:44 2014 -0400
+++ b/src/cpu/o3/commit_impl.hh Wed Sep 03 07:42:45 2014 -0400
@@ -104,6 +104,7 @@
       commitWidth(params->commitWidth),
       numThreads(params->numThreads),
       drainPending(false),
+      drainImminent(false),
       trapLatency(params->trapLatency),
       canHandleInterrupts(true),
       avoidQuiesceLiveLock(false)
@@ -406,6 +407,7 @@
 DefaultCommit<Impl>::drainResume()
 {
     drainPending = false;
+    drainImminent = false;
 }
 
 template <class Impl>
@@ -816,8 +818,10 @@
 void
 DefaultCommit<Impl>::propagateInterrupt()
 {
+    // Don't propagate intterupts if we are currently handling a trap or
+    // in draining and the last observable instruction has been committed.
     if (commitStatus[0] == TrapPending || interrupt || trapSquash[0] ||
-            tcSquash[0])
+            tcSquash[0] || drainImminent)
         return;
 
     // Process interrupts if interrupts are enabled, not in PAL
@@ -1089,10 +1093,15 @@
                     squashAfter(tid, head_inst);
 
                 if (drainPending) {
-                    DPRINTF(Drain, "Draining: %i:%s\n", tid, pc[tid]);
-                    if (pc[tid].microPC() == 0 && interrupt == NoFault) {
+                    if (pc[tid].microPC() == 0 && interrupt == NoFault &&
+                        !thread[tid]->trapPending) {
+                        // Last architectually committed instruction.
+                        // Squash the pipeline, stall fetch, and use
+                        // drainImminent to disable interrupts
+                        DPRINTF(Drain, "Draining: %i:%s\n", tid, pc[tid]);
                         squashAfter(tid, head_inst);
                         cpu->commitDrained(tid);
+                        drainImminent = true;
                     }
                 }
 
_______________________________________________
gem5-dev mailing list
gem5-dev@gem5.org
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to