summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNilay Vaish <nilay@cs.wisc.edu>2012-02-10 08:37:30 -0600
committerNilay Vaish <nilay@cs.wisc.edu>2012-02-10 08:37:30 -0600
commitcd765c23a2030d45223952315b4e862999714890 (patch)
tree0bddf25b5ff70e31dd2fea912d65abe14e5dbfc1 /src
parent8f7e03d4cf4810fa3e09b134c2cf5b6df78a39b0 (diff)
downloadgem5-cd765c23a2030d45223952315b4e862999714890.tar.xz
O3 CPU: Strengthen condition for handling interrupts
The condition for handling interrupts is to check whether or not the cpu's instruction list is empty. As observed, this can lead to cases in which even though the instruction list is empty, interrupts are handled when they should not be. The condition is being strengthened so that interrupts get handled only when the last committed microop did not had IsDelayedCommit set.
Diffstat (limited to 'src')
-rw-r--r--src/cpu/o3/commit.hh3
-rw-r--r--src/cpu/o3/commit_impl.hh26
-rw-r--r--src/cpu/o3/fetch_impl.hh1
3 files changed, 22 insertions, 8 deletions
diff --git a/src/cpu/o3/commit.hh b/src/cpu/o3/commit.hh
index f35928b08..094518655 100644
--- a/src/cpu/o3/commit.hh
+++ b/src/cpu/o3/commit.hh
@@ -441,6 +441,9 @@ class DefaultCommit
/** Rename map interface. */
RenameMap *renameMap[Impl::MaxThreads];
+ /** True if last committed microop can be followed by an interrupt */
+ bool canHandleInterrupts;
+
/** Updates commit stats based on this instruction. */
void updateComInstStats(DynInstPtr &inst);
diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh
index a9b795933..446c8e6f3 100644
--- a/src/cpu/o3/commit_impl.hh
+++ b/src/cpu/o3/commit_impl.hh
@@ -105,7 +105,8 @@ DefaultCommit<Impl>::DefaultCommit(O3CPU *_cpu, DerivO3CPUParams *params)
numThreads(params->numThreads),
drainPending(false),
switchedOut(false),
- trapLatency(params->trapLatency)
+ trapLatency(params->trapLatency),
+ canHandleInterrupts(true)
{
_status = Active;
_nextStatus = Inactive;
@@ -714,7 +715,7 @@ DefaultCommit<Impl>::handleInterrupt()
// Wait until all in flight instructions are finished before enterring
// the interrupt.
- if (cpu->instList.empty()) {
+ if (canHandleInterrupts && cpu->instList.empty()) {
// Squash or record that I need to squash this cycle if
// an interrupt needed to be handled.
DPRINTF(Commit, "Interrupt detected.\n");
@@ -743,7 +744,10 @@ DefaultCommit<Impl>::handleInterrupt()
interrupt = NoFault;
} else {
- DPRINTF(Commit, "Interrupt pending, waiting for ROB to empty.\n");
+ DPRINTF(Commit, "Interrupt pending: instruction is %sin "
+ "flight, ROB is %sempty\n",
+ canHandleInterrupts ? "not " : "",
+ cpu->instList.empty() ? "" : "not " );
}
}
@@ -775,11 +779,6 @@ void
DefaultCommit<Impl>::commit()
{
if (FullSystem) {
- // Check for any interrupt that we've already squashed for and
- // start processing it.
- if (interrupt != NoFault)
- handleInterrupt();
-
// Check if we have a interrupt and get read to handle it
if (cpu->checkInterrupts(cpu->tcBase(0)))
propagateInterrupt();
@@ -936,6 +935,11 @@ DefaultCommit<Impl>::commitInsts()
// Commit as many instructions as possible until the commit bandwidth
// limit is reached, or it becomes impossible to commit any more.
while (num_committed < commitWidth) {
+ // Check for any interrupt that we've already squashed for
+ // and start processing it.
+ if (interrupt != NoFault)
+ handleInterrupt();
+
int commit_thread = getCommittingThread();
if (commit_thread == -1 || !rob->isHeadReady(commit_thread))
@@ -992,6 +996,12 @@ DefaultCommit<Impl>::commitInsts()
cpu->instDone(tid);
}
+ if (tid == 0) {
+ canHandleInterrupts = (!head_inst->isDelayedCommit()) &&
+ ((THE_ISA != ALPHA_ISA) ||
+ (!(pc[0].instAddr() & 0x3)));
+ }
+
// Updates misc. registers.
head_inst->updateMiscRegs();
diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh
index 48c21917a..72d9e960e 100644
--- a/src/cpu/o3/fetch_impl.hh
+++ b/src/cpu/o3/fetch_impl.hh
@@ -1144,6 +1144,7 @@ DefaultFetch<Impl>::fetch(bool &status_change)
// an delayed commit micro-op currently (delayed commit instructions
// are not interruptable by interrupts, only faults)
++fetchMiscStallCycles;
+ DPRINTF(Fetch, "[tid:%i]: Fetch is stalled!\n", tid);
return;
}
} else {