summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cpu/o3/commit.hh11
-rw-r--r--src/cpu/o3/commit_impl.hh15
2 files changed, 22 insertions, 4 deletions
diff --git a/src/cpu/o3/commit.hh b/src/cpu/o3/commit.hh
index 4c9ccf1eb..93c145d5b 100644
--- a/src/cpu/o3/commit.hh
+++ b/src/cpu/o3/commit.hh
@@ -438,9 +438,18 @@ class DefaultCommit
/** 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 --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh
index 347b23359..f0566233c 100644
--- a/src/cpu/o3/commit_impl.hh
+++ b/src/cpu/o3/commit_impl.hh
@@ -104,6 +104,7 @@ DefaultCommit<Impl>::DefaultCommit(O3CPU *_cpu, DerivO3CPUParams *params)
commitWidth(params->commitWidth),
numThreads(params->numThreads),
drainPending(false),
+ drainImminent(false),
trapLatency(params->trapLatency),
canHandleInterrupts(true),
avoidQuiesceLiveLock(false)
@@ -406,6 +407,7 @@ void
DefaultCommit<Impl>::drainResume()
{
drainPending = false;
+ drainImminent = false;
}
template <class Impl>
@@ -816,8 +818,10 @@ template <class Impl>
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 @@ DefaultCommit<Impl>::commitInsts()
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;
}
}