From 752f1c1fe9e74ebb0d373276b332b3242e589208 Mon Sep 17 00:00:00 2001 From: Mitch Hayenga Date: Thu, 21 Jul 2016 17:19:16 +0100 Subject: [PATCH] cpu: Fix Minor SMT WFI/drain interaction issues 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 | 3 +-- src/cpu/minor/execute.cc | 20 ++++++++------------ src/cpu/minor/fetch1.cc | 2 +- src/cpu/minor/fetch2.cc | 3 +-- 4 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/cpu/minor/decode.cc b/src/cpu/minor/decode.cc index 6243bca01..a8a33d989 100644 --- a/src/cpu/minor/decode.cc +++ b/src/cpu/minor/decode.cc @@ -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; } diff --git a/src/cpu/minor/execute.cc b/src/cpu/minor/execute.cc index b13e0c020..f5f006733 100644 --- a/src/cpu/minor/execute.cc +++ b/src/cpu/minor/execute.cc @@ -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; diff --git a/src/cpu/minor/fetch1.cc b/src/cpu/minor/fetch1.cc index f4f120534..f47f54962 100644 --- a/src/cpu/minor/fetch1.cc +++ b/src/cpu/minor/fetch1.cc @@ -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; diff --git a/src/cpu/minor/fetch2.cc b/src/cpu/minor/fetch2.cc index ae02b1c22..394fe8549 100644 --- a/src/cpu/minor/fetch2.cc +++ b/src/cpu/minor/fetch2.cc @@ -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; }