diff options
Diffstat (limited to 'src/cpu/o3/alpha_cpu.hh')
-rw-r--r-- | src/cpu/o3/alpha_cpu.hh | 291 |
1 files changed, 291 insertions, 0 deletions
diff --git a/src/cpu/o3/alpha_cpu.hh b/src/cpu/o3/alpha_cpu.hh new file mode 100644 index 000000000..8e1e0f42a --- /dev/null +++ b/src/cpu/o3/alpha_cpu.hh @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2004-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Todo: Find all the stuff in ExecContext and ev5 that needs to be +// specifically designed for this CPU. + +#ifndef __CPU_O3_CPU_ALPHA_FULL_CPU_HH__ +#define __CPU_O3_CPU_ALPHA_FULL_CPU_HH__ + +#include "cpu/o3/cpu.hh" +#include "arch/isa_traits.hh" +#include "sim/byteswap.hh" + +template <class Impl> +class AlphaFullCPU : public FullO3CPU<Impl> +{ + protected: + typedef TheISA::IntReg IntReg; + typedef TheISA::MiscReg MiscReg; + typedef TheISA::RegFile RegFile; + typedef TheISA::MiscRegFile MiscRegFile; + + public: + typedef typename Impl::Params Params; + + public: + AlphaFullCPU(Params ¶ms); + +#if FULL_SYSTEM + AlphaITB *itb; + AlphaDTB *dtb; +#endif + + public: + void regStats(); + +#if FULL_SYSTEM + //Note that the interrupt stuff from the base CPU might be somewhat + //ISA specific (ie NumInterruptLevels). These functions might not + //be needed in FullCPU though. +// void post_interrupt(int int_num, int index); +// void clear_interrupt(int int_num, int index); +// void clear_interrupts(); + + Fault translateInstReq(MemReqPtr &req) + { + return itb->translate(req); + } + + Fault translateDataReadReq(MemReqPtr &req) + { + return dtb->translate(req, false); + } + + Fault translateDataWriteReq(MemReqPtr &req) + { + return dtb->translate(req, true); + } + +#else + Fault dummyTranslation(MemReqPtr &req) + { +#if 0 + assert((req->vaddr >> 48 & 0xffff) == 0); +#endif + + // put the asid in the upper 16 bits of the paddr + req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16); + req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16; + return NoFault; + } + + Fault translateInstReq(MemReqPtr &req) + { + return dummyTranslation(req); + } + + Fault translateDataReadReq(MemReqPtr &req) + { + return dummyTranslation(req); + } + + Fault translateDataWriteReq(MemReqPtr &req) + { + return dummyTranslation(req); + } + +#endif + + // Later on may want to remove this misc stuff from the regfile and + // have it handled at this level. Might prove to be an issue when + // trying to rename source/destination registers... + MiscReg readMiscReg(int misc_reg) + { + // Dummy function for now. + // @todo: Fix this once reg file gets fixed. + return 0; + } + + Fault setMiscReg(int misc_reg, const MiscReg &val) + { + // Dummy function for now. + // @todo: Fix this once reg file gets fixed. + return NoFault; + } + + // Most of the full system code and syscall emulation is not yet + // implemented. These functions do show what the final interface will + // look like. +#if FULL_SYSTEM + int readIntrFlag(); + void setIntrFlag(int val); + Fault hwrei(); + bool inPalMode() { return AlphaISA::PcPAL(this->regFile.readPC()); } + bool inPalMode(uint64_t PC) + { return AlphaISA::PcPAL(PC); } + + void trap(Fault fault); + bool simPalCheck(int palFunc); + + void processInterrupts(); +#endif + + +#if !FULL_SYSTEM + // Need to change these into regfile calls that directly set a certain + // register. Actually, these functions should handle most of this + // functionality by themselves; should look up the rename and then + // set the register. + IntReg getSyscallArg(int i) + { + return this->cpuXC->readIntReg(AlphaISA::ArgumentReg0 + i); + } + + // used to shift args for indirect syscall + void setSyscallArg(int i, IntReg val) + { + this->cpuXC->setIntReg(AlphaISA::ArgumentReg0 + i, val); + } + + void setSyscallReturn(int64_t return_value) + { + // 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). + const int RegA3 = 19; // only place this is used + if (return_value >= 0) { + // no error + this->cpuXC->setIntReg(RegA3, 0); + this->cpuXC->setIntReg(AlphaISA::ReturnValueReg, return_value); + } else { + // got an error, return details + this->cpuXC->setIntReg(RegA3, (IntReg) -1); + this->cpuXC->setIntReg(AlphaISA::ReturnValueReg, -return_value); + } + } + + void syscall(short thread_num); + void squashStages(); + +#endif + + void copyToXC(); + void copyFromXC(); + + public: +#if FULL_SYSTEM + bool palShadowEnabled; + + // Not sure this is used anywhere. + void intr_post(RegFile *regs, Fault fault, Addr pc); + // Actually used within exec files. Implement properly. + void swapPALShadow(bool use_shadow); + // Called by CPU constructor. Can implement as I please. + void initCPU(RegFile *regs); + // Called by initCPU. Implement as I please. + void initIPRs(RegFile *regs); + + void halt() { panic("Halt not implemented!\n"); } +#endif + + + template <class T> + Fault read(MemReqPtr &req, T &data) + { +#if FULL_SYSTEM && THE_ISA == ALPHA_ISA + if (req->flags & LOCKED) { + req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr); + req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true); + } +#endif + + Fault error; + error = this->mem->read(req, data); + data = gtoh(data); + return error; + } + + template <class T> + Fault read(MemReqPtr &req, T &data, int load_idx) + { + return this->iew.ldstQueue.read(req, data, load_idx); + } + + template <class T> + Fault write(MemReqPtr &req, T &data) + { +#if FULL_SYSTEM && THE_ISA == ALPHA_ISA + ExecContext *xc; + + // If this is a store conditional, act appropriately + if (req->flags & LOCKED) { + xc = req->xc; + + if (req->flags & UNCACHEABLE) { + // Don't update result register (see stq_c in isa_desc) + req->result = 2; + xc->setStCondFailures(0);//Needed? [RGD] + } else { + bool lock_flag = xc->readMiscReg(TheISA::Lock_Flag_DepTag); + Addr lock_addr = xc->readMiscReg(TheISA::Lock_Addr_DepTag); + req->result = lock_flag; + if (!lock_flag || + ((lock_addr & ~0xf) != (req->paddr & ~0xf))) { + xc->setMiscReg(TheISA::Lock_Flag_DepTag, false); + xc->setStCondFailures(xc->readStCondFailures() + 1); + if (((xc->readStCondFailures()) % 100000) == 0) { + std::cerr << "Warning: " + << xc->readStCondFailures() + << " consecutive store conditional failures " + << "on cpu " << req->xc->readCpuId() + << std::endl; + } + return NoFault; + } + else xc->setStCondFailures(0); + } + } + + // Need to clear any locked flags on other proccessors for + // this address. Only do this for succsful Store Conditionals + // and all other stores (WH64?). Unsuccessful Store + // Conditionals would have returned above, and wouldn't fall + // through. + for (int i = 0; i < this->system->execContexts.size(); i++){ + xc = this->system->execContexts[i]; + if ((xc->readMiscReg(TheISA::Lock_Addr_DepTag) & ~0xf) == + (req->paddr & ~0xf)) { + xc->setMiscReg(TheISA::Lock_Flag_DepTag, false); + } + } + +#endif + + return this->mem->write(req, (T)htog(data)); + } + + template <class T> + Fault write(MemReqPtr &req, T &data, int store_idx) + { + return this->iew.ldstQueue.write(req, data, store_idx); + } + +}; + +#endif // __CPU_O3_CPU_ALPHA_FULL_CPU_HH__ |