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:
parent
ff4009ac00
commit
752f1c1fe9
4 changed files with 11 additions and 17 deletions
|
@ -313,8 +313,7 @@ Decode::getScheduledThread()
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto tid : priority_list) {
|
for (auto tid : priority_list) {
|
||||||
if (cpu.getContext(tid)->status() == ThreadContext::Active &&
|
if (getInput(tid) && !decodeInfo[tid].blocked) {
|
||||||
getInput(tid) && !decodeInfo[tid].blocked) {
|
|
||||||
threadPriority = tid;
|
threadPriority = tid;
|
||||||
return tid;
|
return tid;
|
||||||
}
|
}
|
||||||
|
|
|
@ -559,10 +559,11 @@ Execute::issue(ThreadID thread_id)
|
||||||
} else if (cpu.getContext(thread_id)->status() ==
|
} else if (cpu.getContext(thread_id)->status() ==
|
||||||
ThreadContext::Suspended)
|
ThreadContext::Suspended)
|
||||||
{
|
{
|
||||||
DPRINTF(MinorExecute, "Not issuing inst: %s from suspended"
|
DPRINTF(MinorExecute, "Discarding inst: %s from suspended"
|
||||||
" thread\n", *inst);
|
" thread\n", *inst);
|
||||||
|
|
||||||
issued = false;
|
issued = true;
|
||||||
|
discarded = true;
|
||||||
} else if (inst->id.streamSeqNum != thread.streamSeqNum) {
|
} else if (inst->id.streamSeqNum != thread.streamSeqNum) {
|
||||||
DPRINTF(MinorExecute, "Discarding inst: %s as its stream"
|
DPRINTF(MinorExecute, "Discarding inst: %s as its stream"
|
||||||
" state was unexpected, expected: %d\n",
|
" state was unexpected, expected: %d\n",
|
||||||
|
@ -880,9 +881,8 @@ Execute::commitInst(MinorDynInstPtr inst, bool early_memory_issue,
|
||||||
if (thread->status() == ThreadContext::Suspended &&
|
if (thread->status() == ThreadContext::Suspended &&
|
||||||
!isInterrupted(thread_id))
|
!isInterrupted(thread_id))
|
||||||
{
|
{
|
||||||
DPRINTF(MinorExecute, "Not committing inst from suspended thread"
|
panic("We should never hit the case where we try to commit from a "
|
||||||
" inst: %s\n", *inst);
|
"suspended thread as the streamSeqNum should not match");
|
||||||
completed_inst = false;
|
|
||||||
} else if (inst->isFault()) {
|
} else if (inst->isFault()) {
|
||||||
ExecContext context(cpu, *cpu.threads[thread_id], *this, inst);
|
ExecContext context(cpu, *cpu.threads[thread_id], *this, inst);
|
||||||
|
|
||||||
|
@ -1485,9 +1485,7 @@ Execute::evaluate()
|
||||||
if (inst->isFault()) {
|
if (inst->isFault()) {
|
||||||
can_issue_next = true;
|
can_issue_next = true;
|
||||||
} else if (!inst->isBubble()) {
|
} 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) {
|
for (auto tid : priority_list) {
|
||||||
if (cpu.getContext(tid)->status() == ThreadContext::Active &&
|
if (getInput(tid)) {
|
||||||
getInput(tid)) {
|
|
||||||
issuePriority = tid;
|
issuePriority = tid;
|
||||||
return tid;
|
return tid;
|
||||||
}
|
}
|
||||||
|
@ -1823,8 +1820,7 @@ Execute::isDrained()
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (ThreadID tid = 0; tid < cpu.numThreads; tid++) {
|
for (ThreadID tid = 0; tid < cpu.numThreads; tid++) {
|
||||||
if (executeInfo[tid].drainState != DrainAllInsts ||
|
if (!inputBuffer[tid].empty() ||
|
||||||
!inputBuffer[tid].empty() ||
|
|
||||||
!executeInfo[tid].inFlightInsts->empty()) {
|
!executeInfo[tid].inFlightInsts->empty()) {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -734,7 +734,7 @@ Fetch1::isDrained()
|
||||||
(numInFlightFetches() == 0 ? "" : "inFlightFetches "),
|
(numInFlightFetches() == 0 ? "" : "inFlightFetches "),
|
||||||
((*out.inputWire).isBubble() ? "" : "outputtingLine"));
|
((*out.inputWire).isBubble() ? "" : "outputtingLine"));
|
||||||
|
|
||||||
drained = drained && thread.state == FetchHalted;
|
drained = drained && (thread.state != FetchRunning);
|
||||||
}
|
}
|
||||||
|
|
||||||
return drained;
|
return drained;
|
||||||
|
|
|
@ -563,8 +563,7 @@ Fetch2::getScheduledThread()
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto tid : priority_list) {
|
for (auto tid : priority_list) {
|
||||||
if (cpu.getContext(tid)->status() == ThreadContext::Active &&
|
if (getInput(tid) && !fetchInfo[tid].blocked) {
|
||||||
getInput(tid) && !fetchInfo[tid].blocked) {
|
|
||||||
threadPriority = tid;
|
threadPriority = tid;
|
||||||
return tid;
|
return tid;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue