diff options
Diffstat (limited to 'src/cpu/o3/alpha_cpu_impl.hh')
-rw-r--r-- | src/cpu/o3/alpha_cpu_impl.hh | 742 |
1 files changed, 573 insertions, 169 deletions
diff --git a/src/cpu/o3/alpha_cpu_impl.hh b/src/cpu/o3/alpha_cpu_impl.hh index 7c4c2b969..f7f0a3842 100644 --- a/src/cpu/o3/alpha_cpu_impl.hh +++ b/src/cpu/o3/alpha_cpu_impl.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2005 The Regents of The University of Michigan + * Copyright (c) 2004-2006 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,27 +30,96 @@ #include "base/cprintf.hh" #include "base/statistics.hh" #include "base/timebuf.hh" -#include "mem/cache/cache.hh" // for dynamic cast +#include "cpu/checker/exec_context.hh" #include "mem/mem_interface.hh" -#include "sim/builder.hh" #include "sim/sim_events.hh" #include "sim/stats.hh" #include "cpu/o3/alpha_cpu.hh" #include "cpu/o3/alpha_params.hh" #include "cpu/o3/comm.hh" +#include "cpu/o3/thread_state.hh" #if FULL_SYSTEM #include "arch/alpha/osfpal.hh" -#include "arch/alpha/isa_traits.hh" +#include "arch/isa_traits.hh" +#include "cpu/quiesce_event.hh" +#include "kern/kernel_stats.hh" #endif +using namespace TheISA; + template <class Impl> -AlphaFullCPU<Impl>::AlphaFullCPU(Params ¶ms) +AlphaFullCPU<Impl>::AlphaFullCPU(Params *params) +#if FULL_SYSTEM + : FullO3CPU<Impl>(params), itb(params->itb), dtb(params->dtb) +#else : FullO3CPU<Impl>(params) +#endif { DPRINTF(FullCPU, "AlphaFullCPU: Creating AlphaFullCPU object.\n"); + this->thread.resize(this->numThreads); + + for (int i = 0; i < this->numThreads; ++i) { +#if FULL_SYSTEM + assert(this->numThreads == 1); + this->thread[i] = new Thread(this, 0, params->mem); + this->thread[i]->setStatus(ExecContext::Suspended); +#else + if (i < params->workload.size()) { + DPRINTF(FullCPU, "FullCPU: Workload[%i]'s starting PC is %#x, " + "process is %#x", + i, params->workload[i]->prog_entry, this->thread[i]); + this->thread[i] = new Thread(this, i, params->workload[i], i); + assert(params->workload[i]->getMemory() != NULL); + + this->thread[i]->setStatus(ExecContext::Suspended); + //usedTids[i] = true; + //threadMap[i] = i; + } else { + //Allocate Empty execution context so M5 can use later + //when scheduling threads to CPU + Process* dummy_proc = NULL; + + this->thread[i] = new Thread(this, i, dummy_proc, i); + //usedTids[i] = false; + } +#endif // !FULL_SYSTEM + + this->thread[i]->numInst = 0; + + ExecContext *xc_proxy; + + AlphaXC *alpha_xc_proxy = new AlphaXC; + + if (params->checker) { + xc_proxy = new CheckerExecContext<AlphaXC>(alpha_xc_proxy, this->checker); + } else { + xc_proxy = alpha_xc_proxy; + } + + alpha_xc_proxy->cpu = this; + alpha_xc_proxy->thread = this->thread[i]; + +#if FULL_SYSTEM + this->thread[i]->quiesceEvent = + new EndQuiesceEvent(xc_proxy); + this->thread[i]->lastActivate = 0; + this->thread[i]->lastSuspend = 0; +#endif + this->thread[i]->xcProxy = xc_proxy; + + this->execContexts.push_back(xc_proxy); + } + + + for (int i=0; i < this->numThreads; i++) { + this->thread[i]->funcExeInst = 0; + } + + // Sets CPU pointers. These must be set at this level because the CPU + // pointers are defined to be the highest level of CPU class. this->fetch.setCPU(this); this->decode.setCPU(this); this->rename.setCPU(this); @@ -58,6 +127,10 @@ AlphaFullCPU<Impl>::AlphaFullCPU(Params ¶ms) this->commit.setCPU(this); this->rob.setCPU(this); + this->regFile.setCPU(this); + + lockAddr = 0; + lockFlag = false; } template <class Impl> @@ -73,179 +146,460 @@ AlphaFullCPU<Impl>::regStats() this->commit.regStats(); } -#if !FULL_SYSTEM +#if FULL_SYSTEM +template <class Impl> +void +AlphaFullCPU<Impl>::AlphaXC::dumpFuncProfile() +{ + // Currently not supported +} +#endif -// Will probably need to know which thread is calling syscall -// Will need to pass that information in to the DynInst when it is constructed, -// so that this call can be made with the proper thread number. template <class Impl> void -AlphaFullCPU<Impl>::syscall(short thread_num) +AlphaFullCPU<Impl>::AlphaXC::takeOverFrom(ExecContext *old_context) { - DPRINTF(FullCPU, "AlphaFullCPU: Syscall() called.\n\n"); + // some things should already be set up + assert(getMemPtr() == old_context->getMemPtr()); +#if FULL_SYSTEM + assert(getSystemPtr() == old_context->getSystemPtr()); +#else + assert(getProcessPtr() == old_context->getProcessPtr()); +#endif - // Commit stage needs to run as well. - this->commit.tick(); + // copy over functional state + setStatus(old_context->status()); + copyArchRegs(old_context); + setCpuId(old_context->readCpuId()); +#if !FULL_SYSTEM + thread->funcExeInst = old_context->readFuncExeInst(); +#else + EndQuiesceEvent *other_quiesce = old_context->getQuiesceEvent(); + if (other_quiesce) { + // Point the quiesce event's XC at this XC so that it wakes up + // the proper CPU. + other_quiesce->xc = this; + } + if (thread->quiesceEvent) { + thread->quiesceEvent->xc = this; + } - squashStages(); + // Transfer kernel stats from one CPU to the other. + thread->kernelStats = old_context->getKernelStats(); +// storeCondFailures = 0; + cpu->lockFlag = false; +#endif - // Temporarily increase this by one to account for the syscall - // instruction. - ++(this->funcExeInst); + old_context->setStatus(ExecContext::Unallocated); + + thread->inSyscall = false; + thread->trapPending = false; +} + +template <class Impl> +void +AlphaFullCPU<Impl>::AlphaXC::activate(int delay) +{ + DPRINTF(FullCPU, "Calling activate on AlphaXC\n"); - // Copy over all important state to xc once all the unrolling is done. - copyToXC(); + if (thread->status() == ExecContext::Active) + return; - // This is hardcoded to thread 0 while the CPU is only single threaded. - this->thread[0]->syscall(); +#if FULL_SYSTEM + thread->lastActivate = curTick; +#endif - // Copy over all important state back to CPU. - copyFromXC(); + if (thread->status() == ExecContext::Unallocated) { + cpu->activateWhenReady(thread->tid); + return; + } - // Decrease funcExeInst by one as the normal commit will handle - // incrememnting it. - --(this->funcExeInst); + thread->setStatus(ExecContext::Active); + + // status() == Suspended + cpu->activateContext(thread->tid, delay); } -// This is not a pretty function, and should only be used if it is necessary -// to fake having everything squash all at once (ie for non-full system -// syscalls). Maybe put this at the FullCPU level? template <class Impl> void -AlphaFullCPU<Impl>::squashStages() +AlphaFullCPU<Impl>::AlphaXC::suspend() { - InstSeqNum rob_head = this->rob.readHeadSeqNum(); + DPRINTF(FullCPU, "Calling suspend on AlphaXC\n"); - // Now hack the time buffer to put this sequence number in the places - // where the stages might read it. - for (int i = 0; i < 5; ++i) - { - this->timeBuffer.access(-i)->commitInfo.doneSeqNum = rob_head; + if (thread->status() == ExecContext::Suspended) + return; + +#if FULL_SYSTEM + thread->lastActivate = curTick; + thread->lastSuspend = curTick; +#endif +/* +#if FULL_SYSTEM + // Don't change the status from active if there are pending interrupts + if (cpu->check_interrupts()) { + assert(status() == ExecContext::Active); + return; } +#endif +*/ + thread->setStatus(ExecContext::Suspended); + cpu->suspendContext(thread->tid); +} - this->fetch.squash(this->rob.readHeadNextPC()); - this->fetchQueue.advance(); +template <class Impl> +void +AlphaFullCPU<Impl>::AlphaXC::deallocate() +{ + DPRINTF(FullCPU, "Calling deallocate on AlphaXC\n"); - this->decode.squash(); - this->decodeQueue.advance(); + if (thread->status() == ExecContext::Unallocated) + return; - this->rename.squash(); - this->renameQueue.advance(); - this->renameQueue.advance(); + thread->setStatus(ExecContext::Unallocated); + cpu->deallocateContext(thread->tid); +} - // Be sure to advance the IEW queues so that the commit stage doesn't - // try to set an instruction as completed at the same time that it - // might be deleting it. - this->iew.squash(); - this->iewQueue.advance(); - this->iewQueue.advance(); - // Needs to tell the LSQ to write back all of its data - this->iew.lsqWriteback(); +template <class Impl> +void +AlphaFullCPU<Impl>::AlphaXC::halt() +{ + DPRINTF(FullCPU, "Calling halt on AlphaXC\n"); - this->rob.squash(rob_head); - this->commit.setSquashing(); + if (thread->status() == ExecContext::Halted) + return; - // Now hack the time buffer to clear the sequence numbers in the places - // where the stages might read it.? - for (int i = 0; i < 5; ++i) - { - this->timeBuffer.access(-i)->commitInfo.doneSeqNum = 0; - } + thread->setStatus(ExecContext::Halted); + cpu->haltContext(thread->tid); +} +template <class Impl> +void +AlphaFullCPU<Impl>::AlphaXC::regStats(const std::string &name) +{ +#if FULL_SYSTEM + thread->kernelStats = new Kernel::Statistics(cpu->system); + thread->kernelStats->regStats(name + ".kern"); +#endif } -#endif // FULL_SYSTEM +template <class Impl> +void +AlphaFullCPU<Impl>::AlphaXC::serialize(std::ostream &os) +{ +#if FULL_SYSTEM + if (thread->kernelStats) + thread->kernelStats->serialize(os); +#endif + +} template <class Impl> void -AlphaFullCPU<Impl>::copyToXC() +AlphaFullCPU<Impl>::AlphaXC::unserialize(Checkpoint *cp, const std::string §ion) { - PhysRegIndex renamed_reg; +#if FULL_SYSTEM + if (thread->kernelStats) + thread->kernelStats->unserialize(cp, section); +#endif - // First loop through the integer registers. - for (int i = 0; i < AlphaISA::NumIntRegs; ++i) - { - renamed_reg = this->renameMap.lookup(i); - this->cpuXC->setIntReg(i, this->regFile.readIntReg(renamed_reg)); - DPRINTF(FullCPU, "FullCPU: Copying register %i, has data %lli.\n", - renamed_reg, this->regFile.intRegFile[renamed_reg]); - } +} - // Then loop through the floating point registers. - for (int i = 0; i < AlphaISA::NumFloatRegs; ++i) - { - renamed_reg = this->renameMap.lookup(i + AlphaISA::FP_Base_DepTag); - this->cpuXC->setFloatRegBits(i, - this->regFile.readFloatRegBits(renamed_reg)); - } +#if FULL_SYSTEM +template <class Impl> +EndQuiesceEvent * +AlphaFullCPU<Impl>::AlphaXC::getQuiesceEvent() +{ + return thread->quiesceEvent; +} - this->cpuXC->setMiscReg(AlphaISA::Fpcr_DepTag, - this->regFile.readMiscReg(AlphaISA::Fpcr_DepTag)); - this->cpuXC->setMiscReg(AlphaISA::Uniq_DepTag, - this->regFile.readMiscReg(AlphaISA::Uniq_DepTag)); - this->cpuXC->setMiscReg(AlphaISA::Lock_Flag_DepTag, - this->regFile.readMiscReg(AlphaISA::Lock_Flag_DepTag)); - this->cpuXC->setMiscReg(AlphaISA::Lock_Addr_DepTag, - this->regFile.readMiscReg(AlphaISA::Lock_Addr_DepTag)); +template <class Impl> +Tick +AlphaFullCPU<Impl>::AlphaXC::readLastActivate() +{ + return thread->lastActivate; +} - this->cpuXC->setPC(this->rob.readHeadPC()); - this->cpuXC->setNextPC(this->cpuXC->readPC()+4); +template <class Impl> +Tick +AlphaFullCPU<Impl>::AlphaXC::readLastSuspend() +{ + return thread->lastSuspend; +} -#if !FULL_SYSTEM - this->cpuXC->setFuncExeInst(this->funcExeInst); +template <class Impl> +void +AlphaFullCPU<Impl>::AlphaXC::profileClear() +{} + +template <class Impl> +void +AlphaFullCPU<Impl>::AlphaXC::profileSample() +{} #endif + +template <class Impl> +TheISA::MachInst +AlphaFullCPU<Impl>::AlphaXC:: getInst() +{ + return thread->inst; } -// This function will probably mess things up unless the ROB is empty and -// there are no instructions in the pipeline. template <class Impl> void -AlphaFullCPU<Impl>::copyFromXC() +AlphaFullCPU<Impl>::AlphaXC::copyArchRegs(ExecContext *xc) { + // This function will mess things up unless the ROB is empty and + // there are no instructions in the pipeline. + unsigned tid = thread->tid; PhysRegIndex renamed_reg; // First loop through the integer registers. - for (int i = 0; i < AlphaISA::NumIntRegs; ++i) - { - renamed_reg = this->renameMap.lookup(i); + for (int i = 0; i < AlphaISA::NumIntRegs; ++i) { + renamed_reg = cpu->renameMap[tid].lookup(i); DPRINTF(FullCPU, "FullCPU: Copying over register %i, had data %lli, " "now has data %lli.\n", - renamed_reg, this->regFile.intRegFile[renamed_reg], - this->cpuXC->readIntReg(i)); + renamed_reg, cpu->readIntReg(renamed_reg), + xc->readIntReg(i)); - this->regFile.setIntReg(renamed_reg, this->cpuXC->readIntReg(i)); + cpu->setIntReg(renamed_reg, xc->readIntReg(i)); } // Then loop through the floating point registers. for (int i = 0; i < AlphaISA::NumFloatRegs; ++i) { renamed_reg = this->renameMap.lookup(i + AlphaISA::FP_Base_DepTag); - this->regFile.setFloatRegBits(renamed_reg, - this->cpuXC->readFloatRegBits(i)); + this->cpuXC->setFloatRegBits(i, + this->regFile.readFloatRegBits(renamed_reg)); } - // Then loop through the misc registers. - this->regFile.setMiscReg(AlphaISA::Fpcr_DepTag, - this->cpuXC->readMiscReg(AlphaISA::Fpcr_DepTag)); - this->regFile.setMiscReg(AlphaISA::Uniq_DepTag, - this->cpuXC->readMiscReg(AlphaISA::Uniq_DepTag)); - this->regFile.setMiscReg(AlphaISA::Lock_Flag_DepTag, - this->cpuXC->readMiscReg(AlphaISA::Lock_Flag_DepTag)); - this->regFile.setMiscReg(AlphaISA::Lock_Addr_DepTag, - this->cpuXC->readMiscReg(AlphaISA::Lock_Addr_DepTag)); + // Copy the misc regs. + cpu->regFile.miscRegs[tid].copyMiscRegs(xc); // Then finally set the PC and the next PC. -// regFile.pc = cpuXC->regs.pc; -// regFile.npc = cpuXC->regs.npc; + cpu->setPC(xc->readPC(), tid); + cpu->setNextPC(xc->readNextPC(), tid); #if !FULL_SYSTEM - this->funcExeInst = this->cpuXC->readFuncExeInst(); + this->thread->funcExeInst = xc->readFuncExeInst(); #endif } +template <class Impl> +void +AlphaFullCPU<Impl>::AlphaXC::clearArchRegs() +{} + +template <class Impl> +uint64_t +AlphaFullCPU<Impl>::AlphaXC::readIntReg(int reg_idx) +{ + DPRINTF(Fault, "Reading int register through the XC!\n"); + return cpu->readArchIntReg(reg_idx, thread->tid); +} + +template <class Impl> +float +AlphaFullCPU<Impl>::AlphaXC::readFloatRegSingle(int reg_idx) +{ + DPRINTF(Fault, "Reading float register through the XC!\n"); + return cpu->readArchFloatRegSingle(reg_idx, thread->tid); +} + +template <class Impl> +double +AlphaFullCPU<Impl>::AlphaXC::readFloatRegDouble(int reg_idx) +{ + DPRINTF(Fault, "Reading float register through the XC!\n"); + return cpu->readArchFloatRegDouble(reg_idx, thread->tid); +} + +template <class Impl> +uint64_t +AlphaFullCPU<Impl>::AlphaXC::readFloatRegInt(int reg_idx) +{ + DPRINTF(Fault, "Reading floatint register through the XC!\n"); + return cpu->readArchFloatRegInt(reg_idx, thread->tid); +} + +template <class Impl> +void +AlphaFullCPU<Impl>::AlphaXC::setIntReg(int reg_idx, uint64_t val) +{ + DPRINTF(Fault, "Setting int register through the XC!\n"); + cpu->setArchIntReg(reg_idx, val, thread->tid); + + if (!thread->trapPending && !thread->inSyscall) { + cpu->squashFromXC(thread->tid); + } +} + +template <class Impl> +void +AlphaFullCPU<Impl>::AlphaXC::setFloatRegSingle(int reg_idx, float val) +{ + DPRINTF(Fault, "Setting float register through the XC!\n"); + cpu->setArchFloatRegSingle(reg_idx, val, thread->tid); + + if (!thread->trapPending && !thread->inSyscall) { + cpu->squashFromXC(thread->tid); + } +} + +template <class Impl> +void +AlphaFullCPU<Impl>::AlphaXC::setFloatRegDouble(int reg_idx, double val) +{ + DPRINTF(Fault, "Setting float register through the XC!\n"); + cpu->setArchFloatRegDouble(reg_idx, val, thread->tid); + + if (!thread->trapPending && !thread->inSyscall) { + cpu->squashFromXC(thread->tid); + } +} + +template <class Impl> +void +AlphaFullCPU<Impl>::AlphaXC::setFloatRegInt(int reg_idx, uint64_t val) +{ + DPRINTF(Fault, "Setting floatint register through the XC!\n"); + cpu->setArchFloatRegInt(reg_idx, val, thread->tid); + + if (!thread->trapPending && !thread->inSyscall) { + cpu->squashFromXC(thread->tid); + } +} + +template <class Impl> +void +AlphaFullCPU<Impl>::AlphaXC::setPC(uint64_t val) +{ + cpu->setPC(val, thread->tid); + + if (!thread->trapPending && !thread->inSyscall) { + cpu->squashFromXC(thread->tid); + } +} + +template <class Impl> +void +AlphaFullCPU<Impl>::AlphaXC::setNextPC(uint64_t val) +{ + cpu->setNextPC(val, thread->tid); + + if (!thread->trapPending && !thread->inSyscall) { + cpu->squashFromXC(thread->tid); + } +} + +template <class Impl> +Fault +AlphaFullCPU<Impl>::AlphaXC::setMiscReg(int misc_reg, const MiscReg &val) +{ + DPRINTF(Fault, "Setting misc register through the XC!\n"); + + Fault ret_fault = cpu->setMiscReg(misc_reg, val, thread->tid); + + if (!thread->trapPending && !thread->inSyscall) { + cpu->squashFromXC(thread->tid); + } + + return ret_fault; +} + +template <class Impl> +Fault +AlphaFullCPU<Impl>::AlphaXC::setMiscRegWithEffect(int misc_reg, const MiscReg &val) +{ + DPRINTF(Fault, "Setting misc register through the XC!\n"); + + Fault ret_fault = cpu->setMiscRegWithEffect(misc_reg, val, thread->tid); + + if (!thread->trapPending && !thread->inSyscall) { + cpu->squashFromXC(thread->tid); + } + + return ret_fault; +} + +#if !FULL_SYSTEM + +template <class Impl> +TheISA::IntReg +AlphaFullCPU<Impl>::AlphaXC::getSyscallArg(int i) +{ + return cpu->getSyscallArg(i, thread->tid); +} + +template <class Impl> +void +AlphaFullCPU<Impl>::AlphaXC::setSyscallArg(int i, IntReg val) +{ + cpu->setSyscallArg(i, val, thread->tid); +} + +template <class Impl> +void +AlphaFullCPU<Impl>::AlphaXC::setSyscallReturn(SyscallReturn return_value) +{ + cpu->setSyscallReturn(return_value, thread->tid); +} + +#endif // FULL_SYSTEM + +template <class Impl> +MiscReg +AlphaFullCPU<Impl>::readMiscReg(int misc_reg, unsigned tid) +{ + return this->regFile.readMiscReg(misc_reg, tid); +} + +template <class Impl> +MiscReg +AlphaFullCPU<Impl>::readMiscRegWithEffect(int misc_reg, Fault &fault, + unsigned tid) +{ + return this->regFile.readMiscRegWithEffect(misc_reg, fault, tid); +} + +template <class Impl> +Fault +AlphaFullCPU<Impl>::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid) +{ + return this->regFile.setMiscReg(misc_reg, val, tid); +} + +template <class Impl> +Fault +AlphaFullCPU<Impl>::setMiscRegWithEffect(int misc_reg, const MiscReg &val, + unsigned tid) +{ + return this->regFile.setMiscRegWithEffect(misc_reg, val, tid); +} + +template <class Impl> +void +AlphaFullCPU<Impl>::squashFromXC(unsigned tid) +{ + this->thread[tid]->inSyscall = true; + this->commit.generateXCEvent(tid); +} + #if FULL_SYSTEM template <class Impl> +void +AlphaFullCPU<Impl>::post_interrupt(int int_num, int index) +{ + BaseCPU::post_interrupt(int_num, index); + + if (this->thread[0]->status() == ExecContext::Suspended) { + DPRINTF(IPI,"Suspended Processor awoke\n"); +// xcProxies[0]->activate(); + this->execContexts[0]->activate(); + } +} + +template <class Impl> int AlphaFullCPU<Impl>::readIntrFlag() { @@ -259,20 +613,14 @@ AlphaFullCPU<Impl>::setIntrFlag(int val) this->regFile.setIntrFlag(val); } -// Can force commit stage to squash and stuff. template <class Impl> Fault -AlphaFullCPU<Impl>::hwrei() +AlphaFullCPU<Impl>::hwrei(unsigned tid) { - if (!inPalMode()) - return new AlphaISA::UnimplementedOpcodeFault; - - this->setNextPC(this->regFile.miscRegs.readReg(AlphaISA::IPR_EXC_ADDR)); + // Need to clear the lock flag upon returning from an interrupt. + this->lockFlag = false; -// kernelStats.hwrei(); - - if ((this->regFile.miscRegs.readReg(AlphaISA::IPR_EXC_ADDR) & 1) == 0) -// AlphaISA::swap_palshadow(®s, false); + this->thread[tid]->kernelStats->hwrei(); this->checkInterrupts = true; @@ -282,9 +630,11 @@ AlphaFullCPU<Impl>::hwrei() template <class Impl> bool -AlphaFullCPU<Impl>::simPalCheck(int palFunc) +AlphaFullCPU<Impl>::simPalCheck(int palFunc, unsigned tid) { -// kernelStats.callpal(palFunc); + if (this->thread[tid]->kernelStats) + this->thread[tid]->kernelStats->callpal(palFunc, + this->execContexts[tid]); switch (palFunc) { case PAL::halt: @@ -303,69 +653,123 @@ AlphaFullCPU<Impl>::simPalCheck(int palFunc) return true; } -// Probably shouldn't be able to switch to the trap handler as quickly as -// this. Also needs to get the exception restart address from the commit -// stage. template <class Impl> void -AlphaFullCPU<Impl>::trap(Fault fault) +AlphaFullCPU<Impl>::trap(Fault fault, unsigned tid) { -/* // Keep in mind that a trap may be initiated by fetch if there's a TLB - // miss - uint64_t PC = this->commit.readCommitPC(); + fault->invoke(this->execContexts[tid]); +} - DPRINTF(Fault, "Fault %s\n", fault->name()); - this->recordEvent(csprintf("Fault %s", fault->name())); +template <class Impl> +void +AlphaFullCPU<Impl>::processInterrupts() +{ + // Check for interrupts here. For now can copy the code that + // exists within isa_fullsys_traits.hh. Also assume that thread 0 + // is the one that handles the interrupts. + // @todo: Possibly consolidate the interrupt checking code. + // @todo: Allow other threads to handle interrupts. + + // Check if there are any outstanding interrupts + //Handle the interrupts + int ipl = 0; + int summary = 0; + + this->checkInterrupts = false; + + if (this->readMiscReg(IPR_ASTRR, 0)) + panic("asynchronous traps not implemented\n"); + + if (this->readMiscReg(IPR_SIRR, 0)) { + for (int i = INTLEVEL_SOFTWARE_MIN; + i < INTLEVEL_SOFTWARE_MAX; i++) { + if (this->readMiscReg(IPR_SIRR, 0) & (ULL(1) << i)) { + // See table 4-19 of the 21164 hardware reference + ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1; + summary |= (ULL(1) << i); + } + } + } - //kernelStats.fault(fault); + uint64_t interrupts = this->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 (fault->isA<ArithmeticFault>()) - panic("Arithmetic traps are unimplemented!"); + if (ipl && ipl > this->readMiscReg(IPR_IPLR, 0)) { + this->setMiscReg(IPR_ISR, summary, 0); + this->setMiscReg(IPR_INTID, ipl, 0); + if (this->checker) { + this->checker->cpuXCBase()->setMiscReg(IPR_ISR, summary); + this->checker->cpuXCBase()->setMiscReg(IPR_INTID, ipl); + } + this->trap(Fault(new InterruptFault), 0); + DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", + this->readMiscReg(IPR_IPLR, 0), ipl, summary); + } +} - // exception restart address - Get the commit PC - if (!fault->isA<InterruptFault>() || !inPalMode(PC)) - this->regFile.miscRegs.setReg(AlphaISA::IPR_EXC_ADDR, PC); +#endif // FULL_SYSTEM - if (fault->isA<PalFault>() || fault->isA<ArithmeticFault>()) - // || fault == InterruptFault && !PC_PAL(regs.pc) - { - // traps... skip faulting instruction - AlphaISA::MiscReg ipr_exc_addr = - this->regFile.miscRegs.readReg(AlphaISA::IPR_EXC_ADDR); - this->regFile.miscRegs.setReg(AlphaISA::IPR_EXC_ADDR, - ipr_exc_addr + 4); - } +#if !FULL_SYSTEM + +template <class Impl> +void +AlphaFullCPU<Impl>::syscall(int tid) +{ + DPRINTF(FullCPU, "AlphaFullCPU: [tid:%i] Executing syscall().\n\n", tid); - if (!inPalMode(PC)) - swapPALShadow(true); + DPRINTF(Activity,"Activity: syscall() called.\n"); - this->regFile.setPC(this->regFile.miscRegs.readReg(AlphaISA::IPR_PAL_BASE) + - (dynamic_cast<AlphaFault *>(fault.get()))->vect()); - this->regFile.setNextPC(PC + sizeof(MachInst));*/ + // Temporarily increase this by one to account for the syscall + // instruction. + ++(this->thread[tid]->funcExeInst); + + // Execute the actual syscall. + this->thread[tid]->syscall(); + + // Decrease funcExeInst by one as the normal commit will handle + // incrementing it. + --(this->thread[tid]->funcExeInst); } template <class Impl> -void -AlphaFullCPU<Impl>::processInterrupts() +TheISA::IntReg +AlphaFullCPU<Impl>::getSyscallArg(int i, int tid) { - // Check for interrupts here. For now can copy the code that exists - // within isa_fullsys_traits.hh. + return this->readArchIntReg(AlphaISA::ArgumentReg0 + i, tid); } -// swap_palshadow swaps in the values of the shadow registers and -// swaps them with the values of the physical registers that map to the -// same logical index. template <class Impl> void -AlphaFullCPU<Impl>::swapPALShadow(bool use_shadow) +AlphaFullCPU<Impl>::setSyscallArg(int i, IntReg val, int tid) { - if (palShadowEnabled == use_shadow) - panic("swap_palshadow: wrong PAL shadow state"); - - palShadowEnabled = use_shadow; - - // Will have to lookup in rename map to get physical registers, then - // swap. + this->setArchIntReg(AlphaISA::ArgumentReg0 + i, val, tid); } -#endif // FULL_SYSTEM +template <class Impl> +void +AlphaFullCPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid) +{ + // check for error condition. Alpha syscall convention is to + // indicate success/failure in reg a3 (r19) and put the + // return value itself in the standard return value reg (v0). + if (return_value.successful()) { + // no error + this->setArchIntReg(SyscallSuccessReg, 0, tid); + this->setArchIntReg(ReturnValueReg, return_value.value(), tid); + } else { + // got an error, return details + this->setArchIntReg(SyscallSuccessReg, (IntReg) -1, tid); + this->setArchIntReg(ReturnValueReg, -return_value.value(), tid); + } +} +#endif |