cpu: Fix Minor SMT WFI/drain interaction issues
authorMitch Hayenga <mitch.hayenga@arm.com>
Thu, 21 Jul 2016 16:19:16 +0000 (17:19 +0100)
committerMitch Hayenga <mitch.hayenga@arm.com>
Thu, 21 Jul 2016 16:19:16 +0000 (17:19 +0100)
The behavior of WFI is to cause minor to cease evaluating
pipeline logic until an interrupt is observed, however
a user may wish to drain the system while a core is sleeping
due to a WFI.  This patch makes WFI drain.  If an actual
drain occurs during a WFI, the CPU is already drained and will
immediately be ready for swapping, checkpointing, etc.  This
should not negatively impact performance as WFI instructions
are 'stream-changing' (treated like unpredicted branches), so
all remaining instructions are wrong-path and will be squashed
rapidly.

Change-Id: I63833d5acb53d8dde78f9f0c9611de0ece385e45

src/cpu/minor/decode.cc
src/cpu/minor/execute.cc
src/cpu/minor/fetch1.cc
src/cpu/minor/fetch2.cc

index 6243bca0119a9410ecf0df587cb09521a800f520..a8a33d989db0fbe7f03e3631e4a17bd25f661641 100644 (file)
@@ -313,8 +313,7 @@ Decode::getScheduledThread()
     }
 
     for (auto tid : priority_list) {
-        if (cpu.getContext(tid)->status() == ThreadContext::Active &&
-            getInput(tid) && !decodeInfo[tid].blocked) {
+        if (getInput(tid) && !decodeInfo[tid].blocked) {
             threadPriority = tid;
             return tid;
         }
index b13e0c0203c983e41685b4615090f22470a56a1c..f5f00673303463de183722ac666519e2164b0db6 100644 (file)
@@ -559,10 +559,11 @@ Execute::issue(ThreadID thread_id)
         } else if (cpu.getContext(thread_id)->status() ==
             ThreadContext::Suspended)
         {
-            DPRINTF(MinorExecute, "Not issuing inst: %s from suspended"
+            DPRINTF(MinorExecute, "Discarding inst: %s from suspended"
                 " thread\n", *inst);
 
-            issued = false;
+            issued = true;
+            discarded = true;
         } else if (inst->id.streamSeqNum != thread.streamSeqNum) {
             DPRINTF(MinorExecute, "Discarding inst: %s as its stream"
                 " state was unexpected, expected: %d\n",
@@ -880,9 +881,8 @@ Execute::commitInst(MinorDynInstPtr inst, bool early_memory_issue,
     if (thread->status() == ThreadContext::Suspended &&
         !isInterrupted(thread_id))
     {
-        DPRINTF(MinorExecute, "Not committing inst from suspended thread"
-            " inst: %s\n", *inst);
-        completed_inst = false;
+        panic("We should never hit the case where we try to commit from a "
+              "suspended thread as the streamSeqNum should not match");
     } else if (inst->isFault()) {
         ExecContext context(cpu, *cpu.threads[thread_id], *this, inst);
 
@@ -1485,9 +1485,7 @@ Execute::evaluate()
             if (inst->isFault()) {
                 can_issue_next = true;
             } else if (!inst->isBubble()) {
-                if (cpu.getContext(tid)->status() != ThreadContext::Suspended) {
-                    next_issuable_insts.push_back(inst);
-                }
+                next_issuable_insts.push_back(inst);
             }
         }
     }
@@ -1741,8 +1739,7 @@ Execute::getIssuingThread()
     }
 
     for (auto tid : priority_list) {
-        if (cpu.getContext(tid)->status() == ThreadContext::Active &&
-            getInput(tid)) {
+        if (getInput(tid)) {
             issuePriority = tid;
             return tid;
         }
@@ -1823,8 +1820,7 @@ Execute::isDrained()
         return false;
 
     for (ThreadID tid = 0; tid < cpu.numThreads; tid++) {
-        if (executeInfo[tid].drainState != DrainAllInsts ||
-            !inputBuffer[tid].empty() ||
+        if (!inputBuffer[tid].empty() ||
             !executeInfo[tid].inFlightInsts->empty()) {
 
             return false;
index f4f1205349c8eb9d20e2c003077021fe43c72365..f47f54962ca69a03a6fe46a67d8c3070008278a2 100644 (file)
@@ -734,7 +734,7 @@ Fetch1::isDrained()
                 (numInFlightFetches() == 0 ? "" : "inFlightFetches "),
                 ((*out.inputWire).isBubble() ? "" : "outputtingLine"));
 
-        drained = drained && thread.state == FetchHalted;
+        drained = drained && (thread.state != FetchRunning);
     }
 
     return drained;
index ae02b1c229e094fcae82353ad6aecafaf24664b7..394fe8549a68e680f7ef8e8824d0ab521edb5f35 100644 (file)
@@ -563,8 +563,7 @@ Fetch2::getScheduledThread()
     }
 
     for (auto tid : priority_list) {
-        if (cpu.getContext(tid)->status() == ThreadContext::Active &&
-            getInput(tid) && !fetchInfo[tid].blocked) {
+        if (getInput(tid) && !fetchInfo[tid].blocked) {
             threadPriority = tid;
             return tid;
         }