diff --git a/src/arch/alpha/interrupts.hh b/src/arch/alpha/interrupts.hh index 75031ae47c..a86fb2d7b3 100644 --- a/src/arch/alpha/interrupts.hh +++ b/src/arch/alpha/interrupts.hh @@ -49,6 +49,7 @@ namespace AlphaISA { memset(interrupts, 0, sizeof(interrupts)); intstatus = 0; + newInfoSet = false; } void post(int int_num, int index) @@ -137,18 +138,10 @@ namespace AlphaISA } if (ipl && ipl > tc->readMiscReg(IPR_IPLR)) { - tc->setMiscReg(IPR_ISR, summary); - tc->setMiscReg(IPR_INTID, ipl); - - /* The following needs to be added back in somehow */ - // Checker needs to know these two registers were updated. -/*#if USE_CHECKER - if (this->checker) { - this->checker->threadBase()->setMiscReg(IPR_ISR, summary); - this->checker->threadBase()->setMiscReg(IPR_INTID, ipl); - } -#endif*/ - +// assert(!newInfoSet); + newIpl = ipl; + newSummary = newSummary; + newInfoSet = true; DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", tc->readMiscReg(IPR_IPLR), ipl, summary); @@ -158,7 +151,18 @@ namespace AlphaISA } } + void updateIntrInfo(ThreadContext *tc) + { + assert(newInfoSet); + tc->setMiscReg(IPR_ISR, newSummary); + tc->setMiscReg(IPR_INTID, newIpl); + newInfoSet = false; + } + private: + bool newInfoSet; + int newIpl; + int newSummary; }; } diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc index ae302e6867..af69e45c07 100644 --- a/src/arch/alpha/tlb.cc +++ b/src/arch/alpha/tlb.cc @@ -292,7 +292,7 @@ namespace AlphaISA Fault ITB::translate(RequestPtr &req, ThreadContext *tc) const { - if (PcPAL(req->getVaddr())) { + if (PcPAL(req->getPC())) { // strip off PAL PC marker (lsb is 1) req->setPaddr((req->getVaddr() & ~3) & PAddrImplMask); hits++; diff --git a/src/cpu/o3/alpha/cpu.hh b/src/cpu/o3/alpha/cpu.hh index b62550062c..0078db69fc 100644 --- a/src/cpu/o3/alpha/cpu.hh +++ b/src/cpu/o3/alpha/cpu.hh @@ -156,8 +156,11 @@ class AlphaO3CPU : public FullO3CPU 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 04eadfa5ad..f5c3948267 100644 --- a/src/cpu/o3/alpha/cpu_impl.hh +++ b/src/cpu/o3/alpha/cpu_impl.hh @@ -266,9 +266,17 @@ AlphaO3CPU::simPalCheck(int palFunc, unsigned tid) return true; } +template +Fault +AlphaO3CPU::getInterrupts() +{ + // Check if there are any outstanding interrupts + return this->interrupts.getInterrupt(this->threadContexts[0]); +} + template void -AlphaO3CPU::processInterrupts() +AlphaO3CPU::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::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_impl.hh b/src/cpu/o3/commit_impl.hh index 30052a1483..d8e079a7e6 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -640,8 +640,18 @@ DefaultCommit::commit() // @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. @@ -650,26 +660,24 @@ DefaultCommit::commit() // 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(); + // CPU will handle interrupt. + cpu->processInterrupts(intr); - // Now squash or record that I need to squash this cycle. - commitStatus[0] = TrapPending; - - // Exit state update mode to avoid accidental updating. thread[0]->inSyscall = false; + commitStatus[0] = TrapPending; + // Generate trap squash event. generateTrapEvent(0); toIEW->commitInfo[0].clearInterrupt = true; - - DPRINTF(Commit, "Interrupt detected.\n"); } else { DPRINTF(Commit, "Interrupt pending, waiting for ROB to empty.\n"); } @@ -679,7 +687,7 @@ DefaultCommit::commit() //////////////////////////////////// // Check for any possible squashes, handle them first //////////////////////////////////// - + commit_insts: std::list::iterator threads = (*activeThreads).begin(); while (threads != (*activeThreads).end()) { diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 5ef6e27ea3..b1fae8cf05 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -559,27 +559,36 @@ DefaultFetch::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; @@ -609,7 +618,7 @@ DefaultFetch::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"); @@ -1050,12 +1059,16 @@ DefaultFetch::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/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index 86c973a0f0..accc8d2941 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -700,52 +700,12 @@ OzoneCPU::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 73ca6afbe4..198ce0308e 100644 --- a/src/cpu/ozone/front_end_impl.hh +++ b/src/cpu/ozone/front_end_impl.hh @@ -476,8 +476,8 @@ FrontEnd::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/base.cc b/src/cpu/simple/base.cc index ab438aa770..4e5754bbb9 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); }