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
This commit is contained in:
Mitch Hayenga 2016-07-21 17:19:16 +01:00
parent ff4009ac00
commit 752f1c1fe9
4 changed files with 11 additions and 17 deletions

View 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;
}

View 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,12 +1485,10 @@ 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);
}
}
}
}
bool becoming_stalled = true;
@ -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;

View 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;

View 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;
}