diff options
Diffstat (limited to 'src/cpu')
-rw-r--r-- | src/cpu/o3/commit.hh | 11 | ||||
-rw-r--r-- | src/cpu/o3/commit_impl.hh | 15 |
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; } } |