diff options
Diffstat (limited to 'src/cpu')
-rw-r--r-- | src/cpu/o3/alpha/cpu.hh | 7 | ||||
-rw-r--r-- | src/cpu/o3/alpha/cpu_impl.hh | 22 | ||||
-rw-r--r-- | src/cpu/o3/commit.hh | 3 | ||||
-rw-r--r-- | src/cpu/o3/commit_impl.hh | 57 | ||||
-rw-r--r-- | src/cpu/o3/cpu.cc | 6 | ||||
-rw-r--r-- | src/cpu/o3/fetch_impl.hh | 29 | ||||
-rw-r--r-- | src/cpu/o3/lsq_impl.hh | 2 | ||||
-rw-r--r-- | src/cpu/ozone/cpu_builder.cc | 2 | ||||
-rw-r--r-- | src/cpu/ozone/cpu_impl.hh | 50 | ||||
-rw-r--r-- | src/cpu/ozone/front_end_impl.hh | 4 | ||||
-rw-r--r-- | src/cpu/simple/atomic.cc | 3 | ||||
-rw-r--r-- | src/cpu/simple/base.cc | 1 |
12 files changed, 97 insertions, 89 deletions
diff --git a/src/cpu/o3/alpha/cpu.hh b/src/cpu/o3/alpha/cpu.hh index b62550062..0078db69f 100644 --- a/src/cpu/o3/alpha/cpu.hh +++ b/src/cpu/o3/alpha/cpu.hh @@ -156,8 +156,11 @@ class AlphaO3CPU : public FullO3CPU<Impl> bool simPalCheck(int palFunc, unsigned tid); - /** Processes any interrupts. */ - void processInterrupts(); + /** Returns the Fault for any valid interrupt. */ + Fault getInterrupts(); + + /** Processes any an interrupt fault. */ + void processInterrupts(Fault interrupt); /** Halts the CPU. */ void halt() { panic("Halt not implemented!\n"); } diff --git a/src/cpu/o3/alpha/cpu_impl.hh b/src/cpu/o3/alpha/cpu_impl.hh index 15b50cb15..b2ef78360 100644 --- a/src/cpu/o3/alpha/cpu_impl.hh +++ b/src/cpu/o3/alpha/cpu_impl.hh @@ -267,8 +267,16 @@ AlphaO3CPU<Impl>::simPalCheck(int palFunc, unsigned tid) } template <class Impl> +Fault +AlphaO3CPU<Impl>::getInterrupts() +{ + // Check if there are any outstanding interrupts + return this->interrupts.getInterrupt(this->threadContexts[0]); +} + +template <class Impl> void -AlphaO3CPU<Impl>::processInterrupts() +AlphaO3CPU<Impl>::processInterrupts(Fault interrupt) { // Check for interrupts here. For now can copy the code that // exists within isa_fullsys_traits.hh. Also assume that thread 0 @@ -276,14 +284,12 @@ AlphaO3CPU<Impl>::processInterrupts() // @todo: Possibly consolidate the interrupt checking code. // @todo: Allow other threads to handle interrupts. - // Check if there are any outstanding interrupts - //Handle the interrupts - Fault interrupt = this->interrupts.getInterrupt(this->tcBase(0)); + assert(interrupt != NoFault); + this->interrupts.updateIntrInfo(this->threadContexts[0]); - if (interrupt != NoFault) { - this->checkInterrupts = false; - this->trap(interrupt, 0); - } + DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name()); + this->checkInterrupts = false; + this->trap(interrupt, 0); } #endif // FULL_SYSTEM 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 30052a148..e72679710 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -122,6 +122,9 @@ DefaultCommit<Impl>::DefaultCommit(Params *params) tcSquash[i] = false; PC[i] = nextPC[i] = nextNPC[i] = 0; } +#if FULL_SYSTEM + interrupt = NoFault; +#endif } template <class Impl> @@ -635,51 +638,59 @@ DefaultCommit<Impl>::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)) && - !trapSquash[0] && - !tcSquash[0]) { - // 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()) { - // Not sure which thread should be the one to interrupt. For now - // always do thread 0. + // Squash or record that I need to squash this cycle if + // an interrupt needed to be handled. + DPRINTF(Commit, "Interrupt detected.\n"); + assert(!thread[0]->inSyscall); thread[0]->inSyscall = true; - // CPU will handle implementation of the interrupt. - cpu->processInterrupts(); - - // Now squash or record that I need to squash this cycle. - commitStatus[0] = TrapPending; + // CPU will handle interrupt. + cpu->processInterrupts(interrupt); - // Exit state update mode to avoid accidental updating. thread[0]->inSyscall = false; + commitStatus[0] = TrapPending; + // Generate trap squash event. generateTrapEvent(0); + // Clear the interrupt now that it's been handled toIEW->commitInfo[0].clearInterrupt = true; - - DPRINTF(Commit, "Interrupt detected.\n"); + 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; + } } + #endif // FULL_SYSTEM //////////////////////////////////// // Check for any possible squashes, handle them first //////////////////////////////////// - std::list<unsigned>::iterator threads = (*activeThreads).begin(); while (threads != (*activeThreads).end()) { diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index dfe42d882..580816372 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -819,6 +819,12 @@ unsigned int FullO3CPU<Impl>::drain(Event *drain_event) { DPRINTF(O3CPU, "Switching out\n"); + + // If the CPU isn't doing anything, then return immediately. + if (_status == Idle || _status == SwitchedOut) { + return 0; + } + drainCount = 0; fetch.drain(); decode.drain(); diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 350ecd52d..25faa407e 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -561,27 +561,36 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid Fault fault = NoFault; //AlphaDep - if (cacheBlocked || isSwitchedOut() || - (interruptPending && (fetch_PC & 0x3))) { + if (cacheBlocked) { + DPRINTF(Fetch, "[tid:%i] Can't fetch cache line, cache blocked\n", + tid); + return false; + } else if (isSwitchedOut()) { + DPRINTF(Fetch, "[tid:%i] Can't fetch cache line, switched out\n", + tid); + return false; + } else if (interruptPending && !(fetch_PC & 0x3)) { // Hold off fetch from getting new instructions when: // Cache is blocked, or // while an interrupt is pending and we're not in PAL mode, or // fetch is switched out. + DPRINTF(Fetch, "[tid:%i] Can't fetch cache line, interrupt pending\n", + tid); return false; } // Align the fetch PC so it's at the start of a cache block. - fetch_PC = icacheBlockAlignPC(fetch_PC); + Addr block_PC = icacheBlockAlignPC(fetch_PC); // If we've already got the block, no need to try to fetch it again. - if (cacheDataValid[tid] && fetch_PC == cacheDataPC[tid]) { + if (cacheDataValid[tid] && block_PC == cacheDataPC[tid]) { return true; } // Setup the memReq to do a read of the first instruction's address. // Set the appropriate read size and flags as well. // Build request here. - RequestPtr mem_req = new Request(tid, fetch_PC, cacheBlkSize, 0, + RequestPtr mem_req = new Request(tid, block_PC, cacheBlkSize, 0, fetch_PC, cpu->readCpuId(), tid); memReq[tid] = mem_req; @@ -611,7 +620,7 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid Packet::ReadReq, Packet::Broadcast); data_pkt->dataDynamicArray(new uint8_t[cacheBlkSize]); - cacheDataPC[tid] = fetch_PC; + cacheDataPC[tid] = block_PC; cacheDataValid[tid] = false; DPRINTF(Fetch, "Fetch: Doing instruction read.\n"); @@ -976,7 +985,9 @@ DefaultFetch<Impl>::checkSignalsAndUpdate(unsigned tid) } } - if (checkStall(tid) && fetchStatus[tid] != IcacheWaitResponse) { + if (checkStall(tid) && + fetchStatus[tid] != IcacheWaitResponse && + fetchStatus[tid] != IcacheWaitRetry) { DPRINTF(Fetch, "[tid:%i]: Setting to blocked\n",tid); fetchStatus[tid] = Blocked; @@ -1052,12 +1063,16 @@ DefaultFetch<Impl>::fetch(bool &status_change) } else { if (fetchStatus[tid] == Idle) { ++fetchIdleCycles; + DPRINTF(Fetch, "[tid:%i]: Fetch is idle!\n", tid); } else if (fetchStatus[tid] == Blocked) { ++fetchBlockedCycles; + DPRINTF(Fetch, "[tid:%i]: Fetch is blocked!\n", tid); } else if (fetchStatus[tid] == Squashing) { ++fetchSquashCycles; + DPRINTF(Fetch, "[tid:%i]: Fetch is squashing!\n", tid); } else if (fetchStatus[tid] == IcacheWaitResponse) { ++icacheStallCycles; + DPRINTF(Fetch, "[tid:%i]: Fetch is waiting cache response!\n", tid); } // Status is Idle, Squashing, Blocked, or IcacheWaitResponse, so diff --git a/src/cpu/o3/lsq_impl.hh b/src/cpu/o3/lsq_impl.hh index 317e23b14..5e7945c1c 100644 --- a/src/cpu/o3/lsq_impl.hh +++ b/src/cpu/o3/lsq_impl.hh @@ -46,7 +46,7 @@ template <class Impl> void LSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt) { - warn("O3CPU doesn't update things on a recvFunctional."); + DPRINTF(LSQ, "LSQ doesn't update things on a recvFunctional."); } template <class Impl> diff --git a/src/cpu/ozone/cpu_builder.cc b/src/cpu/ozone/cpu_builder.cc index 155f0ce09..e7ecfc496 100644 --- a/src/cpu/ozone/cpu_builder.cc +++ b/src/cpu/ozone/cpu_builder.cc @@ -67,7 +67,7 @@ Param<Tick> profile; Param<bool> do_quiesce; Param<bool> do_checkpoint_insts; -Param<bool> do_statistics_insts +Param<bool> do_statistics_insts; #else SimObjectVectorParam<Process *> workload; //SimObjectParam<PageTable *> page_table; diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index 86c973a0f..accc8d294 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -700,52 +700,12 @@ OzoneCPU<Impl>::processInterrupts() // Check if there are any outstanding interrupts //Handle the interrupts - int ipl = 0; - int summary = 0; + Fault interrupt = this->interrupts.getInterrupt(thread.getTC()); - checkInterrupts = false; - - if (thread.readMiscReg(IPR_ASTRR)) - panic("asynchronous traps not implemented\n"); - - if (thread.readMiscReg(IPR_SIRR)) { - for (int i = INTLEVEL_SOFTWARE_MIN; - i < INTLEVEL_SOFTWARE_MAX; i++) { - if (thread.readMiscReg(IPR_SIRR) & (ULL(1) << i)) { - // See table 4-19 of the 21164 hardware reference - ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1; - summary |= (ULL(1) << i); - } - } - } - - uint64_t interrupts = intr_status(); - - if (interrupts) { - for (int i = INTLEVEL_EXTERNAL_MIN; - i < INTLEVEL_EXTERNAL_MAX; i++) { - if (interrupts & (ULL(1) << i)) { - // See table 4-19 of the 21164 hardware reference - ipl = i; - summary |= (ULL(1) << i); - } - } - } - - if (ipl && ipl > thread.readMiscReg(IPR_IPLR)) { - thread.setMiscReg(IPR_ISR, summary); - thread.setMiscReg(IPR_INTID, ipl); -#if USE_CHECKER - // @todo: Make this more transparent - if (checker) { - checker->threadBase()->setMiscReg(IPR_ISR, summary); - checker->threadBase()->setMiscReg(IPR_INTID, ipl); - } -#endif - Fault fault = new InterruptFault; - fault->invoke(thread.getTC()); - DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", - thread.readMiscReg(IPR_IPLR), ipl, summary); + if (interrupt != NoFault) { + this->interrupts.updateIntrInfo(thread.getTC()); + this->checkInterrupts = false; + interrupt->invoke(thread.getTC()); } } diff --git a/src/cpu/ozone/front_end_impl.hh b/src/cpu/ozone/front_end_impl.hh index 73ca6afbe..198ce0308 100644 --- a/src/cpu/ozone/front_end_impl.hh +++ b/src/cpu/ozone/front_end_impl.hh @@ -476,8 +476,8 @@ FrontEnd<Impl>::fetchCacheLine() // Setup the memReq to do a read of the first isntruction's address. // Set the appropriate read size and flags as well. - memReq = new Request(0, fetch_PC, cacheBlkSize, flags, - fetch_PC, cpu->readCpuId(), 0); + memReq = new Request(0, fetch_PC, cacheBlkSize, 0, + PC, cpu->readCpuId(), 0); // Translate the instruction request. fault = cpu->translateInstReq(memReq, thread); diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index e9679cc7c..58dc1fe5f 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -213,6 +213,9 @@ AtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU) break; } } + if (_status != Running) { + _status = Idle; + } } diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index ab438aa77..4e5754bbb 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -315,6 +315,7 @@ BaseSimpleCPU::checkForInterrupts() Fault interrupt = interrupts.getInterrupt(tc); if (interrupt != NoFault) { + interrupts.updateIntrInfo(tc); checkInterrupts = false; interrupt->invoke(tc); } |