/* * 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 AlphaFullCPU : public FullO3CPU { 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 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 Fault read(MemReqPtr &req, T &data, int load_idx) { return this->iew.ldstQueue.read(req, data, load_idx); } template 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 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__