diff --git a/src/cpu/o3/commit.hh b/src/cpu/o3/commit.hh index 7575783f7..0d7d82529 100644 --- a/src/cpu/o3/commit.hh +++ b/src/cpu/o3/commit.hh @@ -392,6 +392,9 @@ class DefaultCommit */ Tick trapLatency; + /** The interrupt fault. */ + Fault interrupt; + /** The commit PC of each thread. Refers to the instruction that * is currently being processed/committed. */ diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh index b394759b9..e72679710 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -122,6 +122,9 @@ DefaultCommit::DefaultCommit(Params *params) tcSquash[i] = false; PC[i] = nextPC[i] = nextNPC[i] = 0; } +#if FULL_SYSTEM + interrupt = NoFault; +#endif } template @@ -635,28 +638,7 @@ DefaultCommit::commit() ////////////////////////////////////// #if FULL_SYSTEM - // Process interrupts if interrupts are enabled, not in PAL mode, - // and no other traps or external squashes are currently pending. - // @todo: Allow other threads to handle interrupts. - if (cpu->checkInterrupts && - cpu->check_interrupts(cpu->tcBase(0)) && - commitStatus[0] != TrapPending && - !trapSquash[0] && - !tcSquash[0]) { - - // Get any interrupt that happened - Fault intr = cpu->getInterrupts(); - - // Exit this if block if there's no fault. - if (intr == NoFault) { - goto commit_insts; - } - - // Tell fetch that there is an interrupt pending. This will - // make fetch wait until it sees a non PAL-mode PC, at which - // point it stops fetching instructions. - toIEW->commitInfo[0].interruptPending = true; - + if (interrupt != NoFault) { // Wait until the ROB is empty and all stores have drained in // order to enter the interrupt. if (rob->isEmpty() && !iewStage->hasStoresToWB()) { @@ -668,7 +650,7 @@ DefaultCommit::commit() thread[0]->inSyscall = true; // CPU will handle interrupt. - cpu->processInterrupts(intr); + cpu->processInterrupts(interrupt); thread[0]->inSyscall = false; @@ -677,15 +659,33 @@ DefaultCommit::commit() // Generate trap squash event. generateTrapEvent(0); + // Clear the interrupt now that it's been handled toIEW->commitInfo[0].clearInterrupt = true; + interrupt = NoFault; } else { DPRINTF(Commit, "Interrupt pending, waiting for ROB to empty.\n"); } + } else if (cpu->checkInterrupts && + cpu->check_interrupts(cpu->tcBase(0)) && + commitStatus[0] != TrapPending && + !trapSquash[0] && + !tcSquash[0]) { + // Process interrupts if interrupts are enabled, not in PAL + // mode, and no other traps or external squashes are currently + // pending. + // @todo: Allow other threads to handle interrupts. + + // Get any interrupt that happened + interrupt = cpu->getInterrupts(); + + if (interrupt != NoFault) { + // Tell fetch that there is an interrupt pending. This + // will make fetch wait until it sees a non PAL-mode PC, + // at which point it stops fetching instructions. + toIEW->commitInfo[0].interruptPending = true; + } } - // Label for goto. Not pretty but more readable than really big - // if statement above. - commit_insts: #endif // FULL_SYSTEM ////////////////////////////////////