diff options
Diffstat (limited to 'cpu')
-rw-r--r-- | cpu/base.cc | 3 | ||||
-rw-r--r-- | cpu/base.hh | 7 | ||||
-rw-r--r-- | cpu/cpu_exec_context.cc | 92 | ||||
-rw-r--r-- | cpu/cpu_exec_context.hh | 202 | ||||
-rw-r--r-- | cpu/exec_context.hh | 117 | ||||
-rw-r--r-- | cpu/exetrace.cc | 15 | ||||
-rw-r--r-- | cpu/exetrace.hh | 2 | ||||
-rw-r--r-- | cpu/o3/alpha_cpu.hh | 4 | ||||
-rw-r--r-- | cpu/o3/alpha_cpu_impl.hh | 12 | ||||
-rw-r--r-- | cpu/o3/alpha_dyn_inst.hh | 36 | ||||
-rw-r--r-- | cpu/o3/cpu.cc | 47 | ||||
-rw-r--r-- | cpu/o3/cpu.hh | 16 | ||||
-rw-r--r-- | cpu/o3/regfile.hh | 80 | ||||
-rw-r--r-- | cpu/op_class.cc | 50 | ||||
-rw-r--r-- | cpu/op_class.hh | 64 | ||||
-rw-r--r-- | cpu/ozone/cpu.hh | 36 | ||||
-rw-r--r-- | cpu/pc_event.hh | 5 | ||||
-rw-r--r-- | cpu/simple/cpu.cc | 449 | ||||
-rw-r--r-- | cpu/simple/cpu.hh | 162 | ||||
-rw-r--r-- | cpu/static_inst.hh | 15 |
20 files changed, 1009 insertions, 405 deletions
diff --git a/cpu/base.cc b/cpu/base.cc index 2eb5f7fd3..9ce458c64 100644 --- a/cpu/base.cc +++ b/cpu/base.cc @@ -65,7 +65,7 @@ BaseCPU::BaseCPU(Params *p) #else BaseCPU::BaseCPU(Params *p) : SimObject(p->name), clock(p->clock), params(p), - number_of_threads(p->numberOfThreads) + number_of_threads(p->numberOfThreads), system(p->system) #endif { DPRINTF(FullCPU, "BaseCPU: Creating object, mem address %#x.\n", this); @@ -229,6 +229,7 @@ BaseCPU::registerExecContexts() { for (int i = 0; i < execContexts.size(); ++i) { ExecContext *xc = execContexts[i]; + #if FULL_SYSTEM int id = params->cpu_id; if (id != -1) diff --git a/cpu/base.hh b/cpu/base.hh index d9d5d2b88..79700c117 100644 --- a/cpu/base.hh +++ b/cpu/base.hh @@ -38,11 +38,8 @@ #include "sim/sim_object.hh" #include "arch/isa_traits.hh" -#if FULL_SYSTEM class System; namespace Kernel { class Statistics; } -#endif - class BranchPred; class ExecContext; @@ -123,8 +120,8 @@ class BaseCPU : public SimObject Tick clock; bool functionTrace; Tick functionTraceStart; -#if FULL_SYSTEM System *system; +#if FULL_SYSTEM int cpu_id; Tick profile; #endif @@ -173,9 +170,9 @@ class BaseCPU : public SimObject */ EventQueue **comLoadEventQueue; -#if FULL_SYSTEM System *system; +#if FULL_SYSTEM /** * Serialize this object to the given output stream. * @param os The stream to serialize to. diff --git a/cpu/cpu_exec_context.cc b/cpu/cpu_exec_context.cc index b7238e73a..ec1e94561 100644 --- a/cpu/cpu_exec_context.cc +++ b/cpu/cpu_exec_context.cc @@ -28,6 +28,7 @@ #include <string> +#include "arch/isa_traits.hh" #include "cpu/base.hh" #include "cpu/cpu_exec_context.hh" #include "cpu/exec_context.hh" @@ -41,10 +42,11 @@ #include "kern/kernel_stats.hh" #include "sim/serialize.hh" #include "sim/sim_exit.hh" -#include "sim/system.hh" #include "arch/stacktrace.hh" #else #include "sim/process.hh" +#include "sim/system.hh" +#include "mem/translating_port.hh" #endif using namespace std; @@ -52,16 +54,16 @@ using namespace std; // constructor #if FULL_SYSTEM CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_sys, - AlphaITB *_itb, AlphaDTB *_dtb, - FunctionalMemory *_mem) + AlphaITB *_itb, AlphaDTB *_dtb) : _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num), - cpu_id(-1), lastActivate(0), lastSuspend(0), mem(_mem), itb(_itb), - dtb(_dtb), system(_sys), memctrl(_sys->memctrl), physmem(_sys->physmem), - profile(NULL), quiesceEvent(this), func_exe_inst(0), storeCondFailures(0) + cpu_id(-1), lastActivate(0), lastSuspend(0), system(_sys), itb(_itb), + dtb(_dtb), profile(NULL), quiesceEvent(this), func_exe_inst(0), + storeCondFailures(0) + { proxy = new ProxyExecContext<CPUExecContext>(this); - memset(®s, 0, sizeof(RegFile)); + regs.clear(); if (cpu->params->profile) { profile = new FunctionProfile(system->kernelSymtab); @@ -76,30 +78,39 @@ CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_sys, static ProfileNode dummyNode; profileNode = &dummyNode; profilePC = 3; + + Port *mem_port; + physPort = new FunctionalPort(); + mem_port = system->physmem->getPort("functional"); + mem_port->setPeer(physPort); + physPort->setPeer(mem_port); + + virtPort = new VirtualPort(); + mem_port = system->physmem->getPort("functional"); + mem_port->setPeer(virtPort); + virtPort->setPeer(mem_port); } #else CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, - Process *_process, int _asid) + Process *_process, int _asid, MemObject* memobj) : _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num), cpu_id(-1), lastActivate(0), - lastSuspend(0), process(_process), mem(process->getMemory()), asid(_asid), - func_exe_inst(0), storeCondFailures(0) -{ - memset(®s, 0, sizeof(RegFile)); - proxy = new ProxyExecContext<CPUExecContext>(this); -} - -CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, - FunctionalMemory *_mem, int _asid) - : cpu(_cpu), thread_num(_thread_num), process(0), mem(_mem), asid(_asid), + lastSuspend(0), process(_process), asid(_asid), func_exe_inst(0), storeCondFailures(0) { - memset(®s, 0, sizeof(RegFile)); + /* Use this port to for syscall emulation writes to memory. */ + Port *mem_port; + port = new TranslatingPort(process->pTable, false); + mem_port = memobj->getPort("functional"); + mem_port->setPeer(port); + port->setPeer(mem_port); + + regs.clear(); proxy = new ProxyExecContext<CPUExecContext>(this); } CPUExecContext::CPUExecContext(RegFile *regFile) - : cpu(NULL), thread_num(-1), process(NULL), mem(NULL), asid(-1), + : cpu(NULL), thread_num(-1), process(NULL), asid(-1), func_exe_inst(0), storeCondFailures(0) { regs = *regFile; @@ -158,7 +169,6 @@ void CPUExecContext::takeOverFrom(ExecContext *oldContext) { // some things should already be set up - assert(mem == oldContext->getMemPtr()); #if FULL_SYSTEM assert(system == oldContext->getSystemPtr()); #else @@ -277,22 +287,34 @@ CPUExecContext::regStats(const string &name) void CPUExecContext::copyArchRegs(ExecContext *xc) { - // First loop through the integer registers. - for (int i = 0; i < AlphaISA::NumIntRegs; ++i) { - setIntReg(i, xc->readIntReg(i)); - } + TheISA::copyRegs(xc, proxy); +} - // Then loop through the floating point registers. - for (int i = 0; i < AlphaISA::NumFloatRegs; ++i) { - setFloatRegDouble(i, xc->readFloatRegDouble(i)); - setFloatRegInt(i, xc->readFloatRegInt(i)); - } +#if FULL_SYSTEM +VirtualPort* +CPUExecContext::getVirtPort(ExecContext *xc) +{ + if (!xc) + return virtPort; - // Copy misc. registers - regs.miscRegs.copyMiscRegs(xc); + VirtualPort *vp; + Port *mem_port; - // Lastly copy PC/NPC - setPC(xc->readPC()); - setNextPC(xc->readNextPC()); + vp = new VirtualPort(xc); + mem_port = system->physmem->getPort("functional"); + mem_port->setPeer(vp); + vp->setPeer(mem_port); + return vp; } +void +CPUExecContext::delVirtPort(VirtualPort *vp) +{ +// assert(!vp->nullExecContext()); + delete vp->getPeer(); + delete vp; +} + + +#endif + diff --git a/cpu/cpu_exec_context.hh b/cpu/cpu_exec_context.hh index beaf67352..2c06a7b3b 100644 --- a/cpu/cpu_exec_context.hh +++ b/cpu/cpu_exec_context.hh @@ -32,16 +32,13 @@ #include "arch/isa_traits.hh" #include "config/full_system.hh" #include "cpu/exec_context.hh" -#include "mem/functional/functional.hh" -#include "mem/mem_req.hh" +#include "mem/physical.hh" +#include "mem/request.hh" #include "sim/byteswap.hh" #include "sim/eventq.hh" #include "sim/host.hh" #include "sim/serialize.hh" -// forward declaration: see functional_memory.hh -class FunctionalMemory; -class PhysicalMemory; class BaseCPU; #if FULL_SYSTEM @@ -51,11 +48,16 @@ class BaseCPU; class FunctionProfile; class ProfileNode; -class MemoryController; +class FunctionalPort; +class PhysicalPort; + #else // !FULL_SYSTEM #include "sim/process.hh" +#include "mem/page_table.hh" +class TranslatingPort; + #endif // FULL_SYSTEM @@ -72,6 +74,8 @@ class CPUExecContext typedef TheISA::MachInst MachInst; typedef TheISA::MiscRegFile MiscRegFile; typedef TheISA::MiscReg MiscReg; + typedef TheISA::FloatReg FloatReg; + typedef TheISA::FloatRegBits FloatRegBits; public: typedef ExecContext::Status Status; @@ -118,17 +122,20 @@ class CPUExecContext Tick lastActivate; Tick lastSuspend; + System *system; + + #if FULL_SYSTEM - FunctionalMemory *mem; AlphaITB *itb; AlphaDTB *dtb; - System *system; - // the following two fields are redundant, since we can always - // look them up through the system pointer, but we'll leave them - // here for now for convenience - MemoryController *memctrl; - PhysicalMemory *physmem; + /** A functional port outgoing only for functional accesses to physical + * addresses.*/ + FunctionalPort *physPort; + + /** A functional port, outgoing only, for functional accesse to virtual + * addresses. That doen't require execution context information */ + VirtualPort *virtPort; FunctionProfile *profile; ProfileNode *profileNode; @@ -162,9 +169,10 @@ class CPUExecContext void profileSample(); #else - Process *process; + /// Port that syscalls can use to access memory (provides translation step). + TranslatingPort *port; - FunctionalMemory *mem; // functional storage for process address space + Process *process; // Address space ID. Note that this is used for TIMING cache // simulation only; all functional memory accesses should use @@ -200,11 +208,10 @@ class CPUExecContext // constructor: initialize context from given process structure #if FULL_SYSTEM CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_system, - AlphaITB *_itb, AlphaDTB *_dtb, FunctionalMemory *_dem); + AlphaITB *_itb, AlphaDTB *_dtb); #else - CPUExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid); - CPUExecContext(BaseCPU *_cpu, int _thread_num, FunctionalMemory *_mem, - int _asid); + CPUExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid, + MemObject *memobj); // Constructor to use XC to pass reg file around. Not used for anything // else. CPUExecContext(RegFile *regFile); @@ -227,74 +234,67 @@ class CPUExecContext #if FULL_SYSTEM System *getSystemPtr() { return system; } - PhysicalMemory *getPhysMemPtr() { return physmem; } - AlphaITB *getITBPtr() { return itb; } AlphaDTB *getDTBPtr() { return dtb; } - bool validInstAddr(Addr addr) { return true; } - bool validDataAddr(Addr addr) { return true; } int getInstAsid() { return regs.instAsid(); } int getDataAsid() { return regs.dataAsid(); } - Fault translateInstReq(MemReqPtr &req) + Fault translateInstReq(RequestPtr &req) { - return itb->translate(req); + return itb->translate(req, proxy); } - Fault translateDataReadReq(MemReqPtr &req) + Fault translateDataReadReq(RequestPtr &req) { - return dtb->translate(req, false); + return dtb->translate(req, proxy, false); } - Fault translateDataWriteReq(MemReqPtr &req) + Fault translateDataWriteReq(RequestPtr &req) { - return dtb->translate(req, true); + return dtb->translate(req, proxy, true); } -#else - Process *getProcessPtr() { return process; } + FunctionalPort *getPhysPort() { return physPort; } - bool validInstAddr(Addr addr) - { return process->validInstAddr(addr); } + /** Return a virtual port. If no exec context is specified then a static + * port is returned. Otherwise a port is created and returned. It must be + * deleted by deleteVirtPort(). */ + VirtualPort *getVirtPort(ExecContext *xc); - bool validDataAddr(Addr addr) - { return process->validDataAddr(addr); } + void delVirtPort(VirtualPort *vp); + +#else + TranslatingPort *getMemPort() { return port; } + + Process *getProcessPtr() { return process; } int getInstAsid() { return asid; } int getDataAsid() { return asid; } - 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) + Fault translateInstReq(RequestPtr &req) { - return dummyTranslation(req); + return process->pTable->translate(req); } - Fault translateDataReadReq(MemReqPtr &req) + + Fault translateDataReadReq(RequestPtr &req) { - return dummyTranslation(req); + return process->pTable->translate(req); } - Fault translateDataWriteReq(MemReqPtr &req) + + Fault translateDataWriteReq(RequestPtr &req) { - return dummyTranslation(req); + return process->pTable->translate(req); } #endif +/* template <class T> - Fault read(MemReqPtr &req, T &data) + Fault read(RequestPtr &req, T &data) { -#if FULL_SYSTEM && defined(TARGET_ALPHA) +#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); @@ -302,15 +302,15 @@ class CPUExecContext #endif Fault error; - error = mem->read(req, data); + error = mem->prot_read(req->paddr, data, req->size); data = LittleEndianGuest::gtoh(data); return error; } template <class T> - Fault write(MemReqPtr &req, T &data) + Fault write(RequestPtr &req, T &data) { -#if FULL_SYSTEM && defined(TARGET_ALPHA) +#if FULL_SYSTEM && THE_ISA == ALPHA_ISA ExecContext *xc; // If this is a store conditional, act appropriately @@ -356,9 +356,9 @@ class CPUExecContext } #endif - return mem->write(req, (T)LittleEndianGuest::htog(data)); + return mem->prot_write(req->paddr, (T)htog(data), req->size); } - +*/ virtual bool misspeculating(); @@ -369,17 +369,17 @@ class CPUExecContext inst = new_inst; } - Fault instRead(MemReqPtr &req) + Fault instRead(RequestPtr &req) { - return mem->read(req, inst); + panic("instRead not implemented"); + // return funcPhysMem->read(req, inst); + return NoFault; } void setCpuId(int id) { cpu_id = id; } int readCpuId() { return cpu_id; } - FunctionalMemory *getMemPtr() { return mem; } - void copyArchRegs(ExecContext *xc); // @@ -387,93 +387,103 @@ class CPUExecContext // uint64_t readIntReg(int reg_idx) { - return regs.intRegFile[reg_idx]; + return regs.readIntReg(reg_idx); } - float readFloatRegSingle(int reg_idx) + FloatReg readFloatReg(int reg_idx, int width) { - return (float)regs.floatRegFile.d[reg_idx]; + return regs.readFloatReg(reg_idx, width); } - double readFloatRegDouble(int reg_idx) + FloatReg readFloatReg(int reg_idx) { - return regs.floatRegFile.d[reg_idx]; + return regs.readFloatReg(reg_idx); } - uint64_t readFloatRegInt(int reg_idx) + FloatRegBits readFloatRegBits(int reg_idx, int width) { - return regs.floatRegFile.q[reg_idx]; + return regs.readFloatRegBits(reg_idx, width); + } + + FloatRegBits readFloatRegBits(int reg_idx) + { + return regs.readFloatRegBits(reg_idx); } void setIntReg(int reg_idx, uint64_t val) { - regs.intRegFile[reg_idx] = val; + regs.setIntReg(reg_idx, val); } - void setFloatRegSingle(int reg_idx, float val) + void setFloatReg(int reg_idx, FloatReg val, int width) { - regs.floatRegFile.d[reg_idx] = (double)val; + regs.setFloatReg(reg_idx, val, width); } - void setFloatRegDouble(int reg_idx, double val) + void setFloatReg(int reg_idx, FloatReg val) { - regs.floatRegFile.d[reg_idx] = val; + regs.setFloatReg(reg_idx, val); } - void setFloatRegInt(int reg_idx, uint64_t val) + void setFloatRegBits(int reg_idx, FloatRegBits val, int width) { - regs.floatRegFile.q[reg_idx] = val; + regs.setFloatRegBits(reg_idx, val, width); + } + + void setFloatRegBits(int reg_idx, FloatRegBits val) + { + regs.setFloatRegBits(reg_idx, val); } uint64_t readPC() { - return regs.pc; + return regs.readPC(); } void setPC(uint64_t val) { - regs.pc = val; + regs.setPC(val); } uint64_t readNextPC() { - return regs.npc; + return regs.readNextPC(); } void setNextPC(uint64_t val) { - regs.npc = val; + regs.setNextPC(val); } uint64_t readNextNPC() { - return regs.nnpc; + return regs.readNextNPC(); } void setNextNPC(uint64_t val) { - regs.nnpc = val; + regs.setNextNPC(val); } MiscReg readMiscReg(int misc_reg) { - return regs.miscRegs.readReg(misc_reg); + return regs.readMiscReg(misc_reg); } MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) { - return regs.miscRegs.readRegWithEffect(misc_reg, fault, proxy); + return regs.readMiscRegWithEffect(misc_reg, fault, proxy); } Fault setMiscReg(int misc_reg, const MiscReg &val) { - return regs.miscRegs.setReg(misc_reg, val); + return regs.setMiscReg(misc_reg, val); } Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val) { - return regs.miscRegs.setRegWithEffect(misc_reg, val, proxy); + return regs.setMiscRegWithEffect(misc_reg, val, proxy); } unsigned readStCondFailures() { return storeCondFailures; } @@ -481,26 +491,26 @@ class CPUExecContext void setStCondFailures(unsigned sc_failures) { storeCondFailures = sc_failures; } - void clearArchRegs() { memset(®s, 0, sizeof(regs)); } + void clearArchRegs() { regs.clear(); } #if FULL_SYSTEM int readIntrFlag() { return regs.intrflag; } void setIntrFlag(int val) { regs.intrflag = val; } Fault hwrei(); - bool inPalMode() { return AlphaISA::PcPAL(regs.pc); } + bool inPalMode() { return AlphaISA::PcPAL(regs.readPC()); } bool simPalCheck(int palFunc); #endif #if !FULL_SYSTEM TheISA::IntReg getSyscallArg(int i) { - return regs.intRegFile[TheISA::ArgumentReg0 + i]; + return regs.readIntReg(TheISA::ArgumentReg0 + i); } // used to shift args for indirect syscall void setSyscallArg(int i, TheISA::IntReg val) { - regs.intRegFile[TheISA::ArgumentReg0 + i] = val; + regs.setIntReg(TheISA::ArgumentReg0 + i, val); } void setSyscallReturn(SyscallReturn return_value) @@ -508,15 +518,21 @@ class CPUExecContext TheISA::setSyscallReturn(return_value, ®s); } - void syscall() + void syscall(int64_t callnum) { - process->syscall(proxy); + process->syscall(callnum, proxy); } Counter readFuncExeInst() { return func_exe_inst; } void setFuncExeInst(Counter new_val) { func_exe_inst = new_val; } #endif + + void changeRegFileContext(RegFile::ContextParam param, + RegFile::ContextVal val) + { + regs.changeContext(param, val); + } }; diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh index 2b6c41bd7..1f26183ab 100644 --- a/cpu/exec_context.hh +++ b/cpu/exec_context.hh @@ -30,21 +30,21 @@ #define __CPU_EXEC_CONTEXT_HH__ #include "config/full_system.hh" -#include "mem/mem_req.hh" +#include "mem/request.hh" #include "sim/faults.hh" #include "sim/host.hh" #include "sim/serialize.hh" #include "sim/byteswap.hh" -// forward declaration: see functional_memory.hh // @todo: Figure out a more architecture independent way to obtain the ITB and // DTB pointers. class AlphaDTB; class AlphaITB; class BaseCPU; class Event; -class FunctionalMemory; -class PhysicalMemory; +class TranslatingPort; +class FunctionalPort; +class VirtualPort; class Process; class System; @@ -54,6 +54,8 @@ class ExecContext typedef TheISA::RegFile RegFile; typedef TheISA::MachInst MachInst; typedef TheISA::IntReg IntReg; + typedef TheISA::FloatReg FloatReg; + typedef TheISA::FloatRegBits FloatRegBits; typedef TheISA::MiscRegFile MiscRegFile; typedef TheISA::MiscReg MiscReg; public: @@ -87,17 +89,21 @@ class ExecContext virtual int readCpuId() = 0; - virtual FunctionalMemory *getMemPtr() = 0; - #if FULL_SYSTEM virtual System *getSystemPtr() = 0; - virtual PhysicalMemory *getPhysMemPtr() = 0; - virtual AlphaITB *getITBPtr() = 0; virtual AlphaDTB * getDTBPtr() = 0; + + virtual FunctionalPort *getPhysPort() = 0; + + virtual VirtualPort *getVirtPort(ExecContext *xc = NULL) = 0; + + virtual void delVirtPort(VirtualPort *vp) = 0; #else + virtual TranslatingPort *getMemPort() = 0; + virtual Process *getProcessPtr() = 0; #endif @@ -143,16 +149,14 @@ class ExecContext virtual int getThreadNum() = 0; - virtual bool validInstAddr(Addr addr) = 0; - virtual bool validDataAddr(Addr addr) = 0; virtual int getInstAsid() = 0; virtual int getDataAsid() = 0; - virtual Fault translateInstReq(MemReqPtr &req) = 0; + virtual Fault translateInstReq(RequestPtr &req) = 0; - virtual Fault translateDataReadReq(MemReqPtr &req) = 0; + virtual Fault translateDataReadReq(RequestPtr &req) = 0; - virtual Fault translateDataWriteReq(MemReqPtr &req) = 0; + virtual Fault translateDataWriteReq(RequestPtr &req) = 0; // Also somewhat obnoxious. Really only used for the TLB fault. // However, may be quite useful in SPARC. @@ -167,19 +171,23 @@ class ExecContext // virtual uint64_t readIntReg(int reg_idx) = 0; - virtual float readFloatRegSingle(int reg_idx) = 0; + virtual FloatReg readFloatReg(int reg_idx, int width) = 0; - virtual double readFloatRegDouble(int reg_idx) = 0; + virtual FloatReg readFloatReg(int reg_idx) = 0; - virtual uint64_t readFloatRegInt(int reg_idx) = 0; + virtual FloatRegBits readFloatRegBits(int reg_idx, int width) = 0; + + virtual FloatRegBits readFloatRegBits(int reg_idx) = 0; virtual void setIntReg(int reg_idx, uint64_t val) = 0; - virtual void setFloatRegSingle(int reg_idx, float val) = 0; + virtual void setFloatReg(int reg_idx, FloatReg val, int width) = 0; + + virtual void setFloatReg(int reg_idx, FloatReg val) = 0; - virtual void setFloatRegDouble(int reg_idx, double val) = 0; + virtual void setFloatRegBits(int reg_idx, FloatRegBits val) = 0; - virtual void setFloatRegInt(int reg_idx, uint64_t val) = 0; + virtual void setFloatRegBits(int reg_idx, FloatRegBits val, int width) = 0; virtual uint64_t readPC() = 0; @@ -189,6 +197,10 @@ class ExecContext virtual void setNextPC(uint64_t val) = 0; + virtual uint64_t readNextNPC() = 0; + + virtual void setNextNPC(uint64_t val) = 0; + virtual MiscReg readMiscReg(int misc_reg) = 0; virtual MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) = 0; @@ -222,13 +234,16 @@ class ExecContext virtual void setSyscallReturn(SyscallReturn return_value) = 0; - virtual void syscall() = 0; + virtual void syscall(int64_t callnum) = 0; // Same with st cond failures. virtual Counter readFuncExeInst() = 0; virtual void setFuncExeInst(Counter new_val) = 0; #endif + + virtual void changeRegFileContext(RegFile::ContextParam param, + RegFile::ContextVal val) = 0; }; template <class XC> @@ -249,17 +264,21 @@ class ProxyExecContext : public ExecContext int readCpuId() { return actualXC->readCpuId(); } - FunctionalMemory *getMemPtr() { return actualXC->getMemPtr(); } - #if FULL_SYSTEM System *getSystemPtr() { return actualXC->getSystemPtr(); } - PhysicalMemory *getPhysMemPtr() { return actualXC->getPhysMemPtr(); } - AlphaITB *getITBPtr() { return actualXC->getITBPtr(); } AlphaDTB *getDTBPtr() { return actualXC->getDTBPtr(); } + + FunctionalPort *getPhysPort() { return actualXC->getPhysPort(); } + + VirtualPort *getVirtPort(ExecContext *xc = NULL) { return actualXC->getVirtPort(xc); } + + void delVirtPort(VirtualPort *vp) { return actualXC->delVirtPort(vp); } #else + TranslatingPort *getMemPort() { return actualXC->getMemPort(); } + Process *getProcessPtr() { return actualXC->getProcessPtr(); } #endif @@ -305,18 +324,16 @@ class ProxyExecContext : public ExecContext int getThreadNum() { return actualXC->getThreadNum(); } - bool validInstAddr(Addr addr) { return actualXC->validInstAddr(addr); } - bool validDataAddr(Addr addr) { return actualXC->validDataAddr(addr); } int getInstAsid() { return actualXC->getInstAsid(); } int getDataAsid() { return actualXC->getDataAsid(); } - Fault translateInstReq(MemReqPtr &req) + Fault translateInstReq(RequestPtr &req) { return actualXC->translateInstReq(req); } - Fault translateDataReadReq(MemReqPtr &req) + Fault translateDataReadReq(RequestPtr &req) { return actualXC->translateDataReadReq(req); } - Fault translateDataWriteReq(MemReqPtr &req) + Fault translateDataWriteReq(RequestPtr &req) { return actualXC->translateDataWriteReq(req); } // @todo: Do I need this? @@ -333,26 +350,32 @@ class ProxyExecContext : public ExecContext uint64_t readIntReg(int reg_idx) { return actualXC->readIntReg(reg_idx); } - float readFloatRegSingle(int reg_idx) - { return actualXC->readFloatRegSingle(reg_idx); } + FloatReg readFloatReg(int reg_idx, int width) + { return actualXC->readFloatReg(reg_idx, width); } + + FloatReg readFloatReg(int reg_idx) + { return actualXC->readFloatReg(reg_idx); } - double readFloatRegDouble(int reg_idx) - { return actualXC->readFloatRegDouble(reg_idx); } + FloatRegBits readFloatRegBits(int reg_idx, int width) + { return actualXC->readFloatRegBits(reg_idx, width); } - uint64_t readFloatRegInt(int reg_idx) - { return actualXC->readFloatRegInt(reg_idx); } + FloatRegBits readFloatRegBits(int reg_idx) + { return actualXC->readFloatRegBits(reg_idx); } void setIntReg(int reg_idx, uint64_t val) { actualXC->setIntReg(reg_idx, val); } - void setFloatRegSingle(int reg_idx, float val) - { actualXC->setFloatRegSingle(reg_idx, val); } + void setFloatReg(int reg_idx, FloatReg val, int width) + { actualXC->setFloatReg(reg_idx, val, width); } - void setFloatRegDouble(int reg_idx, double val) - { actualXC->setFloatRegDouble(reg_idx, val); } + void setFloatReg(int reg_idx, FloatReg val) + { actualXC->setFloatReg(reg_idx, val); } - void setFloatRegInt(int reg_idx, uint64_t val) - { actualXC->setFloatRegInt(reg_idx, val); } + void setFloatRegBits(int reg_idx, FloatRegBits val, int width) + { actualXC->setFloatRegBits(reg_idx, val, width); } + + void setFloatRegBits(int reg_idx, FloatRegBits val) + { actualXC->setFloatRegBits(reg_idx, val); } uint64_t readPC() { return actualXC->readPC(); } @@ -362,6 +385,10 @@ class ProxyExecContext : public ExecContext void setNextPC(uint64_t val) { actualXC->setNextPC(val); } + uint64_t readNextNPC() { return actualXC->readNextNPC(); } + + void setNextNPC(uint64_t val) { actualXC->setNextNPC(val); } + MiscReg readMiscReg(int misc_reg) { return actualXC->readMiscReg(misc_reg); } @@ -405,13 +432,19 @@ class ProxyExecContext : public ExecContext void setSyscallReturn(SyscallReturn return_value) { actualXC->setSyscallReturn(return_value); } - void syscall() { actualXC->syscall(); } + void syscall(int64_t callnum) { actualXC->syscall(callnum); } Counter readFuncExeInst() { return actualXC->readFuncExeInst(); } void setFuncExeInst(Counter new_val) { return actualXC->setFuncExeInst(new_val); } #endif + + void changeRegFileContext(RegFile::ContextParam param, + RegFile::ContextVal val) + { + actualXC->changeRegFileContext(param, val); + } }; #endif diff --git a/cpu/exetrace.cc b/cpu/exetrace.cc index 84b5eacf7..0ed3b43c4 100644 --- a/cpu/exetrace.cc +++ b/cpu/exetrace.cc @@ -29,14 +29,12 @@ #include <fstream> #include <iomanip> -#include "sim/param.hh" -#include "encumbered/cpu/full/dyn_inst.hh" -#include "encumbered/cpu/full/spec_state.hh" -#include "encumbered/cpu/full/issue.hh" -#include "cpu/exetrace.hh" #include "base/loader/symtab.hh" #include "cpu/base.hh" +#include "cpu/exetrace.hh" #include "cpu/static_inst.hh" +#include "sim/param.hh" +#include "sim/system.hh" using namespace std; @@ -130,10 +128,11 @@ Trace::InstRecord::dump(ostream &outs) outs << " A=0x" << hex << addr; if (flags[PRINT_INT_REGS] && regs_valid) { - for (int i = 0; i < 32;) + for (int i = 0; i < TheISA::NumIntRegs;) for (int j = i + 1; i <= j; i++) - ccprintf(outs, "r%02d = %#018x%s", i, iregs->regs[i], - ((i == j) ? "\n" : " ")); + ccprintf(outs, "r%02d = %#018x%s", i, + iregs->regs.readReg(i), + ((i == j) ? "\n" : " ")); outs << "\n"; } diff --git a/cpu/exetrace.hh b/cpu/exetrace.hh index 67d042ec8..a26cdc517 100644 --- a/cpu/exetrace.hh +++ b/cpu/exetrace.hh @@ -163,7 +163,7 @@ InstRecord::setRegs(const IntRegFile ®s) if (!iregs) iregs = new iRegFile; - memcpy(&iregs->regs, regs, sizeof(IntRegFile)); + memcpy(&iregs->regs, ®s, sizeof(IntRegFile)); regs_valid = true; } diff --git a/cpu/o3/alpha_cpu.hh b/cpu/o3/alpha_cpu.hh index 0352e9972..8e1e0f42a 100644 --- a/cpu/o3/alpha_cpu.hh +++ b/cpu/o3/alpha_cpu.hh @@ -208,7 +208,7 @@ class AlphaFullCPU : public FullO3CPU<Impl> template <class T> Fault read(MemReqPtr &req, T &data) { -#if FULL_SYSTEM && defined(TARGET_ALPHA) +#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); @@ -230,7 +230,7 @@ class AlphaFullCPU : public FullO3CPU<Impl> template <class T> Fault write(MemReqPtr &req, T &data) { -#if FULL_SYSTEM && defined(TARGET_ALPHA) +#if FULL_SYSTEM && THE_ISA == ALPHA_ISA ExecContext *xc; // If this is a store conditional, act appropriately diff --git a/cpu/o3/alpha_cpu_impl.hh b/cpu/o3/alpha_cpu_impl.hh index 9f1fa24f6..7c4c2b969 100644 --- a/cpu/o3/alpha_cpu_impl.hh +++ b/cpu/o3/alpha_cpu_impl.hh @@ -175,10 +175,8 @@ AlphaFullCPU<Impl>::copyToXC() for (int i = 0; i < AlphaISA::NumFloatRegs; ++i) { renamed_reg = this->renameMap.lookup(i + AlphaISA::FP_Base_DepTag); - this->cpuXC->setFloatRegDouble(i, - this->regFile.readFloatRegDouble(renamed_reg)); - this->cpuXC->setFloatRegInt(i, - this->regFile.readFloatRegInt(renamed_reg)); + this->cpuXC->setFloatRegBits(i, + this->regFile.readFloatRegBits(renamed_reg)); } this->cpuXC->setMiscReg(AlphaISA::Fpcr_DepTag, @@ -223,10 +221,8 @@ AlphaFullCPU<Impl>::copyFromXC() for (int i = 0; i < AlphaISA::NumFloatRegs; ++i) { renamed_reg = this->renameMap.lookup(i + AlphaISA::FP_Base_DepTag); - this->regFile.setFloatRegDouble(renamed_reg, - this->cpuXC->readFloatRegDouble(i)); - this->regFile.setFloatRegInt(renamed_reg, - this->cpuXC->readFloatRegInt(i)); + this->regFile.setFloatRegBits(renamed_reg, + this->cpuXC->readFloatRegBits(i)); } // Then loop through the misc registers. diff --git a/cpu/o3/alpha_dyn_inst.hh b/cpu/o3/alpha_dyn_inst.hh index e7f7d3a57..5b8a05e5c 100644 --- a/cpu/o3/alpha_dyn_inst.hh +++ b/cpu/o3/alpha_dyn_inst.hh @@ -152,19 +152,24 @@ class AlphaDynInst : public BaseDynInst<Impl> return this->cpu->readIntReg(_srcRegIdx[idx]); } - float readFloatRegSingle(const StaticInst *si, int idx) + FloatReg readFloatReg(const StaticInst *si, int idx, int width) { - return this->cpu->readFloatRegSingle(_srcRegIdx[idx]); + return this->cpu->readFloatReg(_srcRegIdx[idx], width); } - double readFloatRegDouble(const StaticInst *si, int idx) + FloatReg readFloatReg(const StaticInst *si, int idx) { - return this->cpu->readFloatRegDouble(_srcRegIdx[idx]); + return this->cpu->readFloatReg(_srcRegIdx[idx]); } - uint64_t readFloatRegInt(const StaticInst *si, int idx) + FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width) { - return this->cpu->readFloatRegInt(_srcRegIdx[idx]); + return this->cpu->readFloatRegBits(_srcRegIdx[idx], width); + } + + FloatRegBits readFloatRegBits(const StaticInst *si, int idx) + { + return this->cpu->readFloatRegBits(_srcRegIdx[idx]); } /** @todo: Make results into arrays so they can handle multiple dest @@ -176,21 +181,28 @@ class AlphaDynInst : public BaseDynInst<Impl> this->instResult.integer = val; } - void setFloatRegSingle(const StaticInst *si, int idx, float val) + void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width) { - this->cpu->setFloatRegSingle(_destRegIdx[idx], val); + this->cpu->setFloatReg(_destRegIdx[idx], val, width); this->instResult.fp = val; } - void setFloatRegDouble(const StaticInst *si, int idx, double val) + void setFloatReg(const StaticInst *si, int idx, FloatReg val) { - this->cpu->setFloatRegDouble(_destRegIdx[idx], val); + this->cpu->setFloatReg(_destRegIdx[idx], val); this->instResult.dbl = val; } - void setFloatRegInt(const StaticInst *si, int idx, uint64_t val) + void setFloatRegBits(const StaticInst *si, int idx, + FloatRegBits val, int width) + { + this->cpu->setFloatRegBits(_destRegIdx[idx], val, width); + this->instResult.integer = val; + } + + void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val) { - this->cpu->setFloatRegInt(_destRegIdx[idx], val); + this->cpu->setFloatRegBits(_destRegIdx[idx], val); this->instResult.integer = val; } diff --git a/cpu/o3/cpu.cc b/cpu/o3/cpu.cc index 62d68bb33..a268dbc23 100644 --- a/cpu/o3/cpu.cc +++ b/cpu/o3/cpu.cc @@ -258,8 +258,7 @@ FullO3CPU<Impl>::init() // Then loop through the floating point registers. for (int i = 0; i < TheISA::NumFloatRegs; ++i) { - regFile.floatRegFile[i].d = src_xc->readFloatRegDouble(i); - regFile.floatRegFile[i].q = src_xc->readFloatRegInt(i); + regFile.floatRegFile.setRegBits(i, src_xc->readRegBits(i)) } /* // Then loop through the misc registers. @@ -348,24 +347,31 @@ FullO3CPU<Impl>::readIntReg(int reg_idx) } template <class Impl> -float -FullO3CPU<Impl>::readFloatRegSingle(int reg_idx) +FloatReg +FullO3CPU<Impl>::readFloatReg(int reg_idx, int width) { - return regFile.readFloatRegSingle(reg_idx); + return regFile.readFloatReg(reg_idx, width); } template <class Impl> -double -FullO3CPU<Impl>::readFloatRegDouble(int reg_idx) +FloatReg +FullO3CPU<Impl>::readFloatReg(int reg_idx) { - return regFile.readFloatRegDouble(reg_idx); + return regFile.readFloatReg(reg_idx); } template <class Impl> -uint64_t -FullO3CPU<Impl>::readFloatRegInt(int reg_idx) +FloatRegBits +FullO3CPU<Impl>::readFloatRegBits(int reg_idx, int width) +{ + return regFile.readFloatRegBits(reg_idx, width); +} + +template <class Impl> +FloatRegBits +FullO3CPU<Impl>::readFloatRegBits(int reg_idx) { - return regFile.readFloatRegInt(reg_idx); + return regFile.readFloatRegBits(reg_idx); } template <class Impl> @@ -377,23 +383,30 @@ FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val) template <class Impl> void -FullO3CPU<Impl>::setFloatRegSingle(int reg_idx, float val) +FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val, int width) +{ + regFile.setFloatReg(reg_idx, val, width); +} + +template <class Impl> +void +FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val) { - regFile.setFloatRegSingle(reg_idx, val); + regFile.setFloatReg(reg_idx, val); } template <class Impl> void -FullO3CPU<Impl>::setFloatRegDouble(int reg_idx, double val) +FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val, int width) { - regFile.setFloatRegDouble(reg_idx, val); + regFile.setFloatRegBits(reg_idx, val, width); } template <class Impl> void -FullO3CPU<Impl>::setFloatRegInt(int reg_idx, uint64_t val) +FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) { - regFile.setFloatRegInt(reg_idx, val); + regFile.setFloatRegBits(reg_idx, val); } template <class Impl> diff --git a/cpu/o3/cpu.hh b/cpu/o3/cpu.hh index 6577e46e4..f7c80e8a1 100644 --- a/cpu/o3/cpu.hh +++ b/cpu/o3/cpu.hh @@ -170,19 +170,23 @@ class FullO3CPU : public BaseFullCPU // uint64_t readIntReg(int reg_idx); - float readFloatRegSingle(int reg_idx); + FloatReg readFloatReg(int reg_idx); - double readFloatRegDouble(int reg_idx); + FloatReg readFloatReg(int reg_idx, int width); - uint64_t readFloatRegInt(int reg_idx); + FloatRegBits readFloatRegBits(int reg_idx); + + FloatRegBits readFloatRegBits(int reg_idx, int width); void setIntReg(int reg_idx, uint64_t val); - void setFloatRegSingle(int reg_idx, float val); + void setFloatReg(int reg_idx, FloatReg val, int width); + + void setFloatReg(int reg_idx, FloatReg val, int width); - void setFloatRegDouble(int reg_idx, double val); + void setFloatRegBits(int reg_idx, FloatRegBits val); - void setFloatRegInt(int reg_idx, uint64_t val); + void setFloatRegBits(int reg_idx, FloatRegBits val); uint64_t readPC(); diff --git a/cpu/o3/regfile.hh b/cpu/o3/regfile.hh index 1e6e10f29..a5cfa8f3c 100644 --- a/cpu/o3/regfile.hh +++ b/cpu/o3/regfile.hh @@ -89,43 +89,64 @@ class PhysRegFile return intRegFile[reg_idx]; } - float readFloatRegSingle(PhysRegIndex reg_idx) + FloatReg readFloatReg(PhysRegIndex reg_idx, int width) { // Remove the base Float reg dependency. reg_idx = reg_idx - numPhysicalIntRegs; assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs); - DPRINTF(IEW, "RegFile: Access to float register %i as single, has " - "data %8.8f\n", int(reg_idx), (float)floatRegFile[reg_idx].d); + FloatReg floatReg = floatRegFile.readReg(reg_idx, width); - return (float)floatRegFile[reg_idx].d; + DPRINTF(IEW, "RegFile: Access to %d byte float register %i, has " + "data %8.8d\n", int(reg_idx), (double)floatReg); + + return floatReg; } - double readFloatRegDouble(PhysRegIndex reg_idx) + FloatReg readFloatReg(PhysRegIndex reg_idx) { // Remove the base Float reg dependency. reg_idx = reg_idx - numPhysicalIntRegs; assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs); - DPRINTF(IEW, "RegFile: Access to float register %i as double, has " - " data %8.8f\n", int(reg_idx), floatRegFile[reg_idx].d); + FloatReg floatReg = floatRegFile.readReg(reg_idx); + + DPRINTF(IEW, "RegFile: Access to float register %i, has " + "data %8.8d\n", int(reg_idx), (double)floatReg); - return floatRegFile[reg_idx].d; + return floatReg; } - uint64_t readFloatRegInt(PhysRegIndex reg_idx) + FloatRegBits readFloatRegBits(PhysRegIndex reg_idx, int width) { // Remove the base Float reg dependency. reg_idx = reg_idx - numPhysicalIntRegs; assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs); - DPRINTF(IEW, "RegFile: Access to float register %i as int, has data " - "%lli\n", int(reg_idx), floatRegFile[reg_idx].q); + FloatRegBits floatRegBits = floatRegFile.readRegBits(reg_idx, width); + + DPRINTF(IEW, "RegFile: Access to %d byte float register %i as int, " + "has data %lli\n", int(reg_idx), (uint64_t)floatRegBits); + + return floatRegBits; + } + + FloatRegBits readFloatRegBits(PhysRegIndex reg_idx) + { + // Remove the base Float reg dependency. + reg_idx = reg_idx - numPhysicalIntRegs; + + assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs); + + FloatRegBits floatRegBits = floatRegFile.readRegBits(reg_idx); + + DPRINTF(IEW, "RegFile: Access to float register %i as int, " + "has data %lli\n", int(reg_idx), (uint64_t)floatRegBits); - return floatRegFile[reg_idx].q; + return floatRegBits; } void setIntReg(PhysRegIndex reg_idx, uint64_t val) @@ -138,33 +159,33 @@ class PhysRegFile intRegFile[reg_idx] = val; } - void setFloatRegSingle(PhysRegIndex reg_idx, float val) + void setFloatReg(PhysRegIndex reg_idx, FloatReg val, int width) { // Remove the base Float reg dependency. reg_idx = reg_idx - numPhysicalIntRegs; assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs); - DPRINTF(IEW, "RegFile: Setting float register %i to %8.8f\n", - int(reg_idx), val); + DPRINTF(IEW, "RegFile: Setting float register %i to %8.8d\n", + int(reg_idx), (double)val); - floatRegFile[reg_idx].d = (double)val; + floatRegFile.setReg(reg_idx, val, width); } - void setFloatRegDouble(PhysRegIndex reg_idx, double val) + void setFloatReg(PhysRegIndex reg_idx, FloatReg val) { // Remove the base Float reg dependency. reg_idx = reg_idx - numPhysicalIntRegs; assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs); - DPRINTF(IEW, "RegFile: Setting float register %i to %8.8f\n", - int(reg_idx), val); + DPRINTF(IEW, "RegFile: Setting float register %i to %8.8d\n", + int(reg_idx), (double)val); - floatRegFile[reg_idx].d = val; + floatRegFile.setReg(reg_idx, val); } - void setFloatRegInt(PhysRegIndex reg_idx, uint64_t val) + void setFloatRegBits(PhysRegIndex reg_idx, FloatRegBits val, int width) { // Remove the base Float reg dependency. reg_idx = reg_idx - numPhysicalIntRegs; @@ -172,9 +193,22 @@ class PhysRegFile assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs); DPRINTF(IEW, "RegFile: Setting float register %i to %lli\n", - int(reg_idx), val); + int(reg_idx), (uint64_t)val); + + floatRegFile.setRegBits(reg_idx, val, width); + } + + void setFloatRegBits(PhysRegIndex reg_idx, FloatRegBits val) + { + // Remove the base Float reg dependency. + reg_idx = reg_idx - numPhysicalIntRegs; + + assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs); + + DPRINTF(IEW, "RegFile: Setting float register %i to %lli\n", + int(reg_idx), (uint64_t)val); - floatRegFile[reg_idx].q = val; + floatRegFile.setRegBits(reg_idx, val); } uint64_t readPC() diff --git a/cpu/op_class.cc b/cpu/op_class.cc new file mode 100644 index 000000000..00136ded5 --- /dev/null +++ b/cpu/op_class.cc @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2003-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. + */ + +#include "cpu/op_class.hh" + +/** OpClass enum -> description string */ +const char * +opClassStrings[Num_OpClasses] = +{ + "(null)", + "IntAlu", + "IntMult", + "IntDiv", + "FloatAdd", + "FloatCmp", + "FloatCvt", + "FloatMult", + "FloatDiv", + "FloatSqrt", + "MemRead", + "MemWrite", + "IprAccess", + "InstPrefetch" +}; + diff --git a/cpu/op_class.hh b/cpu/op_class.hh new file mode 100644 index 000000000..cdb40a0fb --- /dev/null +++ b/cpu/op_class.hh @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2003-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. + */ + +#ifndef __CPU__OP_CLASS_HH__ +#define __CPU__OP_CLASS_HH__ + +/** + * @file + * Definition of operation classes. + */ + +/** + * Instruction operation classes. These classes are used for + * assigning instructions to functional units. + */ +enum OpClass { + No_OpClass = 0, ///< Instruction does not use a functional unit + IntAluOp, ///< Integer ALU operaton (add/sub/logical) + IntMultOp, ///< Integer multiply + IntDivOp, ///< Integer divide + FloatAddOp, ///< Floating point add/subtract + FloatCmpOp, ///< Floating point comparison + FloatCvtOp, ///< Floating point<->integer conversion + FloatMultOp, ///< Floating point multiply + FloatDivOp, ///< Floating point divide + FloatSqrtOp, ///< Floating point square root + MemReadOp, ///< Memory read port + MemWriteOp, ///< Memory write port + IprAccessOp, ///< Internal Processor Register read/write port + InstPrefetchOp, ///< Instruction prefetch port (on I-cache) + Num_OpClasses ///< Total number of operation classes +}; + +/** + * Array mapping OpClass enum values to strings. Defined in op_class.cc. + */ +extern const char *opClassStrings[]; + +#endif // __CPU__OP_CLASS_HH__ diff --git a/cpu/ozone/cpu.hh b/cpu/ozone/cpu.hh index f5d84d656..fa849bb09 100644 --- a/cpu/ozone/cpu.hh +++ b/cpu/ozone/cpu.hh @@ -406,22 +406,28 @@ class OoOCPU : public BaseCPU return xc->readIntReg(si->srcRegIdx(idx)); } - float readFloatRegSingle(StaticInst *si, int idx) + FloatReg readFloatReg(StaticInst *si, int idx, width) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; - return xc->readFloatRegSingle(reg_idx); + return xc->readFloatReg(reg_idx, width); } - double readFloatRegDouble(StaticInst *si, int idx) + FloatReg readFloatReg(StaticInst *si, int idx) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; - return xc->readFloatRegDouble(reg_idx); + return xc->readFloatReg(reg_idx); } - uint64_t readFloatRegInt(StaticInst *si, int idx) + FloatRegBits readFloatRegBits(StaticInst *si, int idx, int width) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; - return xc->readFloatRegInt(reg_idx); + return xc->readFloatRegBits(reg_idx, width); + } + + FloatRegBits readFloatRegBits(StaticInst *si, int idx) + { + int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; + return xc->readFloatRegBits(reg_idx); } void setIntReg(StaticInst *si, int idx, uint64_t val) @@ -429,22 +435,28 @@ class OoOCPU : public BaseCPU xc->setIntReg(si->destRegIdx(idx), val); } - void setFloatRegSingle(StaticInst *si, int idx, float val) + void setFloatReg(StaticInst *si, int idx, FloatReg val, int width) + { + int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; + xc->setFloatReg(reg_idx, val, width); + } + + void setFloatReg(StaticInst *si, int idx, FloatReg val) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; - xc->setFloatRegSingle(reg_idx, val); + xc->setFloatReg(reg_idx, val); } - void setFloatRegDouble(StaticInst *si, int idx, double val) + void setFloatRegBits(StaticInst *si, int idx, FloatRegBits val, int width) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; - xc->setFloatRegDouble(reg_idx, val); + xc->setFloatRegBits(reg_idx, val, width); } - void setFloatRegInt(StaticInst *si, int idx, uint64_t val) + void setFloatRegBits(StaticInst *si, int idx, FloatRegBits val) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; - xc->setFloatRegInt(reg_idx, val); + xc->setFloatRegBits(reg_idx, val); } uint64_t readPC() { return PC; } diff --git a/cpu/pc_event.hh b/cpu/pc_event.hh index 7fa3902cc..32b7f3ef5 100644 --- a/cpu/pc_event.hh +++ b/cpu/pc_event.hh @@ -31,7 +31,7 @@ #include <vector> -#include "mem/mem_req.hh" +#include "base/misc.hh" class ExecContext; class PCEventQueue; @@ -39,9 +39,6 @@ class PCEventQueue; class PCEvent { protected: - static const Addr badpc = MemReq::inval_addr; - - protected: std::string description; PCEventQueue *queue; Addr evpc; diff --git a/cpu/simple/cpu.cc b/cpu/simple/cpu.cc index 8db72b77e..33fe63c26 100644 --- a/cpu/simple/cpu.cc +++ b/cpu/simple/cpu.cc @@ -35,6 +35,7 @@ #include <sstream> #include <string> +#include "arch/utility.hh" #include "base/cprintf.hh" #include "base/inifile.hh" #include "base/loader/symtab.hh" @@ -53,8 +54,7 @@ #include "cpu/smt.hh" #include "cpu/static_inst.hh" #include "kern/kernel_stats.hh" -#include "mem/base_mem.hh" -#include "mem/mem_interface.hh" +#include "mem/packet_impl.hh" #include "sim/byteswap.hh" #include "sim/builder.hh" #include "sim/debug.hh" @@ -65,20 +65,18 @@ #if FULL_SYSTEM #include "base/remote_gdb.hh" -#include "mem/functional/memory_control.hh" -#include "mem/functional/physical.hh" +//#include "mem/functional/memory_control.hh" +//#include "mem/functional/physical.hh" #include "sim/system.hh" #include "arch/tlb.hh" #include "arch/stacktrace.hh" #include "arch/vtophys.hh" #else // !FULL_SYSTEM -#include "mem/functional/functional.hh" +#include "mem/mem_object.hh" #endif // FULL_SYSTEM using namespace std; -//The SimpleCPU does alpha only -using namespace AlphaISA; - +using namespace TheISA; SimpleCPU::TickEvent::TickEvent(SimpleCPU *c, int w) : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c), width(w) @@ -89,6 +87,15 @@ SimpleCPU::TickEvent::TickEvent(SimpleCPU *c, int w) void SimpleCPU::init() { + //Create Memory Ports (conect them up) + Port *mem_dport = mem->getPort(""); + dcachePort.setPeer(mem_dport); + mem_dport->setPeer(&dcachePort); + + Port *mem_iport = mem->getPort(""); + icachePort.setPeer(mem_iport); + mem_iport->setPeer(&icachePort); + BaseCPU::init(); #if FULL_SYSTEM for (int i = 0; i < execContexts.size(); ++i) { @@ -116,43 +123,82 @@ SimpleCPU::TickEvent::description() } -SimpleCPU::CacheCompletionEvent::CacheCompletionEvent(SimpleCPU *_cpu) - : Event(&mainEventQueue), cpu(_cpu) +bool +SimpleCPU::CpuPort::recvTiming(Packet &pkt) { + cpu->processResponse(pkt); + return true; } -void SimpleCPU::CacheCompletionEvent::process() +Tick +SimpleCPU::CpuPort::recvAtomic(Packet &pkt) { - cpu->processCacheCompletion(); + panic("CPU doesn't expect callback!"); + return curTick; } -const char * -SimpleCPU::CacheCompletionEvent::description() +void +SimpleCPU::CpuPort::recvFunctional(Packet &pkt) +{ + panic("CPU doesn't expect callback!"); +} + +void +SimpleCPU::CpuPort::recvStatusChange(Status status) { - return "SimpleCPU cache completion event"; + cpu->recvStatusChange(status); +} + +Packet * +SimpleCPU::CpuPort::recvRetry() +{ + return cpu->processRetry(); } SimpleCPU::SimpleCPU(Params *p) - : BaseCPU(p), tickEvent(this, p->width), cpuXC(NULL), - cacheCompletionEvent(this) + : BaseCPU(p), mem(p->mem), icachePort(this), + dcachePort(this), tickEvent(this, p->width), cpuXC(NULL) { _status = Idle; -#if FULL_SYSTEM - cpuXC = new CPUExecContext(this, 0, p->system, p->itb, p->dtb, p->mem); +#if FULL_SYSTEM + cpuXC = new CPUExecContext(this, 0, p->system, p->itb, p->dtb); #else cpuXC = new CPUExecContext(this, /* thread_num */ 0, p->process, - /* asid */ 0); + /* asid */ 0, mem); #endif // !FULL_SYSTEM - xcProxy = cpuXC->getProxy(); - icacheInterface = p->icache_interface; - dcacheInterface = p->dcache_interface; + xcProxy = cpuXC->getProxy(); - memReq = new MemReq(); - memReq->xc = xcProxy; - memReq->asid = 0; - memReq->data = new uint8_t[64]; +#if SIMPLE_CPU_MEM_ATOMIC || SIMPLE_CPU_MEM_IMMEDIATE + ifetch_req = new Request(true); + ifetch_req->setAsid(0); + // @todo fix me and get the real cpu iD!!! + ifetch_req->setCpuNum(0); + ifetch_req->setSize(sizeof(MachInst)); + ifetch_pkt = new Packet; + ifetch_pkt->cmd = Read; + ifetch_pkt->dataStatic(&inst); + ifetch_pkt->req = ifetch_req; + ifetch_pkt->size = sizeof(MachInst); + + data_read_req = new Request(true); + // @todo fix me and get the real cpu iD!!! + data_read_req->setCpuNum(0); + data_read_req->setAsid(0); + data_read_pkt = new Packet; + data_read_pkt->cmd = Read; + data_read_pkt->dataStatic(&dataReg); + data_read_pkt->req = data_read_req; + + data_write_req = new Request(true); + // @todo fix me and get the real cpu iD!!! + data_write_req->setCpuNum(0); + data_write_req->setAsid(0); + data_write_pkt = new Packet; + data_write_pkt->cmd = Write; + data_write_pkt->req = data_write_req; +#endif numInst = 0; startNumInst = 0; @@ -172,9 +218,9 @@ void SimpleCPU::switchOut(Sampler *s) { sampler = s; - if (status() == DcacheMissStall) { + if (status() == DcacheWaitResponse) { DPRINTF(Sampler,"Outstanding dcache access, waiting for completion\n"); - _status = DcacheMissSwitch; + _status = DcacheWaitSwitch; } else { _status = SwitchedOut; @@ -287,6 +333,18 @@ SimpleCPU::regStats() .prereq(dcacheStallCycles) ; + icacheRetryCycles + .name(name() + ".icache_retry_cycles") + .desc("ICache total retry cycles") + .prereq(icacheRetryCycles) + ; + + dcacheRetryCycles + .name(name() + ".dcache_retry_cycles") + .desc("DCache total retry cycles") + .prereq(dcacheRetryCycles) + ; + idleFraction = constant(1.0) - notIdleFraction; } @@ -308,7 +366,6 @@ SimpleCPU::serialize(ostream &os) nameOut(os, csprintf("%s.tickEvent", name())); tickEvent.serialize(os); nameOut(os, csprintf("%s.cacheCompletionEvent", name())); - cacheCompletionEvent.serialize(os); } void @@ -319,8 +376,6 @@ SimpleCPU::unserialize(Checkpoint *cp, const string §ion) UNSERIALIZE_SCALAR(inst); cpuXC->unserialize(cp, csprintf("%s.xc", section)); tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); - cacheCompletionEvent - .unserialize(cp, csprintf("%s.cacheCompletionEvent", section)); } void @@ -331,6 +386,7 @@ change_thread_state(int thread_number, int activate, int priority) Fault SimpleCPU::copySrcTranslate(Addr src) { +#if 0 static bool no_warn = true; int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64; // Only support block sizes of 64 atm. @@ -347,8 +403,7 @@ SimpleCPU::copySrcTranslate(Addr src) memReq->reset(src & ~(blk_size - 1), blk_size); - // translate to physical address - Fault fault = cpuXC->translateDataReadReq(memReq); + // translate to physical address Fault fault = cpuXC->translateDataReadReq(req); if (fault == NoFault) { cpuXC->copySrcAddr = src; @@ -360,11 +415,15 @@ SimpleCPU::copySrcTranslate(Addr src) cpuXC->copySrcPhysAddr = 0; } return fault; +#else + return NoFault; +#endif } Fault SimpleCPU::copy(Addr dest) { +#if 0 static bool no_warn = true; int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64; // Only support block sizes of 64 atm. @@ -383,7 +442,7 @@ SimpleCPU::copy(Addr dest) memReq->reset(dest & ~(blk_size -1), blk_size); // translate to physical address - Fault fault = cpuXC->translateDataWriteReq(memReq); + Fault fault = cpuXC->translateDataWriteReq(req); if (fault == NoFault) { Addr dest_addr = memReq->paddr + offset; @@ -407,6 +466,10 @@ SimpleCPU::copy(Addr dest) assert(!fault->isAlignmentFault()); return fault; +#else + panic("copy not implemented"); + return NoFault; +#endif } // precise architected memory state accessor macros @@ -414,22 +477,65 @@ template <class T> Fault SimpleCPU::read(Addr addr, T &data, unsigned flags) { - if (status() == DcacheMissStall || status() == DcacheMissSwitch) { - Fault fault = cpuXC->read(memReq,data); + if (status() == DcacheWaitResponse || status() == DcacheWaitSwitch) { +// Fault fault = xc->read(memReq,data); + // Not sure what to check for no fault... + if (data_read_pkt->result == Success) { + data = data_read_pkt->get<T>(); + } if (traceData) { - traceData->setAddr(addr); + traceData->setAddr(data_read_req->getVaddr()); } - return fault; + + // @todo: Figure out a way to create a Fault from the packet result. + return NoFault; } - memReq->reset(addr, sizeof(T), flags); +// memReq->reset(addr, sizeof(T), flags); + +#if SIMPLE_CPU_MEM_TIMING + CpuRequest *data_read_req = new Request(true); +#endif + + data_read_req->setVaddr(addr); + data_read_req->setSize(sizeof(T)); + data_read_req->setFlags(flags); + data_read_req->setTime(curTick); // translate to physical address - Fault fault = cpuXC->translateDataReadReq(memReq); + Fault fault = cpuXC->translateDataReadReq(data_read_req); - // if we have a cache, do cache access too - if (fault == NoFault && dcacheInterface) { + // Now do the access. + if (fault == NoFault) { +#if SIMPLE_CPU_MEM_TIMING + data_read_pkt = new Packet; + data_read_pkt->cmd = Read; + data_read_pkt->req = data_read_req; + data_read_pkt->data = new uint8_t[8]; +#endif + data_read_pkt->reset(); + data_read_pkt->addr = data_read_req->getPaddr(); + data_read_pkt->size = sizeof(T); + + sendDcacheRequest(data_read_pkt); + +#if SIMPLE_CPU_MEM_IMMEDIATE + // Need to find a way to not duplicate code above. + + if (data_read_pkt->result == Success) { + data = data_read_pkt->get<T>(); + } + + if (traceData) { + traceData->setAddr(addr); + } + + // @todo: Figure out a way to create a Fault from the packet result. + return NoFault; +#endif + } +/* memReq->cmd = Read; memReq->completionEvent = NULL; memReq->time = curTick; @@ -454,8 +560,9 @@ SimpleCPU::read(Addr addr, T &data, unsigned flags) fault = cpuXC->read(memReq, data); } - - if (!dcacheInterface && (memReq->flags & UNCACHEABLE)) +*/ + // This will need a new way to tell if it has a dcache attached. + if (data_read_req->getFlags() & UNCACHEABLE) recordEvent("Uncached Read"); return fault; @@ -508,11 +615,33 @@ template <class T> Fault SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) { - memReq->reset(addr, sizeof(T), flags); + data_write_req->setVaddr(addr); + data_write_req->setTime(curTick); + data_write_req->setSize(sizeof(T)); + data_write_req->setFlags(flags); // translate to physical address - Fault fault = cpuXC->translateDataWriteReq(memReq); + Fault fault = cpuXC->translateDataWriteReq(data_write_req); + // Now do the access. + if (fault == NoFault) { +#if SIMPLE_CPU_MEM_TIMING + data_write_pkt = new Packet; + data_write_pkt->cmd = Write; + data_write_pkt->req = data_write_req; + data_write_pkt->allocate(); + data_write_pkt->set(data); +#else + data_write_pkt->reset(); + data = htog(data); + data_write_pkt->dataStatic(&data); +#endif + data_write_pkt->addr = data_write_req->getPaddr(); + data_write_pkt->size = sizeof(T); + + sendDcacheRequest(data_write_pkt); + } +/* // do functional access if (fault == NoFault) fault = cpuXC->write(memReq, data); @@ -535,13 +664,21 @@ SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) _status = DcacheMissStall; } } - +*/ if (res && (fault == NoFault)) - *res = memReq->result; + *res = data_write_pkt->result; - if (!dcacheInterface && (memReq->flags & UNCACHEABLE)) + // This will need a new way to tell if it's hooked up to a cache or not. + if (data_write_req->getFlags() & UNCACHEABLE) recordEvent("Uncached Write"); + // @todo this is a hack and only works on uniprocessor systems some one else + // can implement LL/SC. + if (data_write_req->getFlags() & LOCKED) + *res = 1; + + // If the write needs to have a fault on the access, consider calling + // changeStatus() and changing it to "bad addr write" or something. return fault; } @@ -597,36 +734,130 @@ SimpleCPU::dbg_vtophys(Addr addr) #endif // FULL_SYSTEM void -SimpleCPU::processCacheCompletion() +SimpleCPU::sendIcacheRequest(Packet *pkt) { + assert(!tickEvent.scheduled()); +#if SIMPLE_CPU_MEM_TIMING + retry_pkt = pkt; + bool success = icachePort.sendTiming(*pkt); + + unscheduleTickEvent(); + + lastIcacheStall = curTick; + + if (!success) { + // Need to wait for retry + _status = IcacheRetry; + } else { + // Need to wait for cache to respond + _status = IcacheWaitResponse; + } +#elif SIMPLE_CPU_MEM_ATOMIC + Tick latency = icachePort.sendAtomic(*pkt); + + unscheduleTickEvent(); + scheduleTickEvent(latency); + + // Note that Icache miss cycles will be incorrect. Unless + // we check the status of the packet sent (is this valid?), + // we won't know if the latency is a hit or a miss. + icacheStallCycles += latency; + + _status = IcacheAccessComplete; +#elif SIMPLE_CPU_MEM_IMMEDIATE + icachePort.sendAtomic(*pkt); +#else +#error "SimpleCPU has no mem model set" +#endif +} + +void +SimpleCPU::sendDcacheRequest(Packet *pkt) +{ + assert(!tickEvent.scheduled()); +#if SIMPLE_CPU_MEM_TIMING + unscheduleTickEvent(); + + retry_pkt = pkt; + bool success = dcachePort.sendTiming(*pkt); + + lastDcacheStall = curTick; + + if (!success) { + _status = DcacheRetry; + } else { + _status = DcacheWaitResponse; + } +#elif SIMPLE_CPU_MEM_ATOMIC + unscheduleTickEvent(); + + Tick latency = dcachePort.sendAtomic(*pkt); + + scheduleTickEvent(latency); + + // Note that Dcache miss cycles will be incorrect. Unless + // we check the status of the packet sent (is this valid?), + // we won't know if the latency is a hit or a miss. + dcacheStallCycles += latency; +#elif SIMPLE_CPU_MEM_IMMEDIATE + dcachePort.sendAtomic(*pkt); +#else +#error "SimpleCPU has no mem model set" +#endif +} + +void +SimpleCPU::processResponse(Packet &response) +{ + assert(SIMPLE_CPU_MEM_TIMING); + + // For what things is the CPU the consumer of the packet it sent + // out? This may create a memory leak if that's the case and it's + // expected of the SimpleCPU to delete its own packet. + Packet *pkt = &response; + switch (status()) { - case IcacheMissStall: + case IcacheWaitResponse: icacheStallCycles += curTick - lastIcacheStall; - _status = IcacheMissComplete; + + _status = IcacheAccessComplete; scheduleTickEvent(1); + + // Copy the icache data into the instruction itself. + inst = pkt->get<MachInst>(); + + delete pkt; break; - case DcacheMissStall: - if (memReq->cmd.isRead()) { + case DcacheWaitResponse: + if (pkt->cmd == Read) { curStaticInst->execute(this,traceData); if (traceData) traceData->finalize(); } + + delete pkt; + dcacheStallCycles += curTick - lastDcacheStall; _status = Running; scheduleTickEvent(1); break; - case DcacheMissSwitch: - if (memReq->cmd.isRead()) { + case DcacheWaitSwitch: + if (pkt->cmd == Read) { curStaticInst->execute(this,traceData); if (traceData) traceData->finalize(); } + + delete pkt; + _status = SwitchedOut; sampler->signalSwitched(); case SwitchedOut: // If this CPU has been switched out due to sampling/warm-up, // ignore any further status changes (e.g., due to cache // misses outstanding at the time of the switch). + delete pkt; + return; default: panic("SimpleCPU::processCacheCompletion: bad state"); @@ -634,6 +865,28 @@ SimpleCPU::processCacheCompletion() } } +Packet * +SimpleCPU::processRetry() +{ +#if SIMPLE_CPU_MEM_TIMING + switch(status()) { + case IcacheRetry: + icacheRetryCycles += curTick - lastIcacheStall; + return retry_pkt; + break; + case DcacheRetry: + dcacheRetryCycles += curTick - lastDcacheStall; + return retry_pkt; + break; + default: + panic("SimpleCPU::processRetry: bad state"); + break; + } +#else + panic("shouldn't be here"); +#endif +} + #if FULL_SYSTEM void SimpleCPU::post_interrupt(int int_num, int index) @@ -651,6 +904,8 @@ SimpleCPU::post_interrupt(int int_num, int index) void SimpleCPU::tick() { + DPRINTF(SimpleCPU,"\n\n"); + numCycles++; traceData = NULL; @@ -659,7 +914,7 @@ SimpleCPU::tick() #if FULL_SYSTEM if (checkInterrupts && check_interrupts() && !cpuXC->inPalMode() && - status() != IcacheMissComplete) { + status() != IcacheAccessComplete) { int ipl = 0; int summary = 0; checkInterrupts = false; @@ -702,37 +957,57 @@ SimpleCPU::tick() // maintain $r0 semantics cpuXC->setIntReg(ZeroReg, 0); -#ifdef TARGET_ALPHA - cpuXC->setFloatRegDouble(ZeroReg, 0.0); -#endif // TARGET_ALPHA +#if THE_ISA == ALPHA_ISA + cpuXC->setFloatReg(ZeroReg, 0.0); +#endif // ALPHA_ISA - if (status() == IcacheMissComplete) { + if (status() == IcacheAccessComplete) { // We've already fetched an instruction and were stalled on an // I-cache miss. No need to fetch it again. // Set status to running; tick event will get rescheduled if // necessary at end of tick() function. _status = Running; - } - else { + } else { // Try to fetch an instruction // set up memory request for instruction fetch + + DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",cpuXC->readPC(), + cpuXC->readNextPC(),cpuXC->readNextNPC()); + +#if SIMPLE_CPU_MEM_TIMING + CpuRequest *ifetch_req = new CpuRequest(); + ifetch_req->setSize(sizeof(MachInst)); +#endif + + ifetch_req->resetMin(); + ifetch_req->setVaddr(cpuXC->readPC() & ~3); + ifetch_req->setTime(curTick); #if FULL_SYSTEM -#define IFETCH_FLAGS(pc) ((pc) & 1) ? PHYSICAL : 0 + ifetch_req->setFlags((cpuXC->readPC() & 1) ? PHYSICAL : 0); #else -#define IFETCH_FLAGS(pc) 0 + ifetch_req->setFlags(0); #endif - memReq->cmd = Read; - memReq->reset(cpuXC->readPC() & ~3, sizeof(uint32_t), - IFETCH_FLAGS(cpuXC->readPC())); - - fault = cpuXC->translateInstReq(memReq); + fault = cpuXC->translateInstReq(ifetch_req); - if (fault == NoFault) - fault = cpuXC->mem->read(memReq, inst); + if (fault == NoFault) { +#if SIMPLE_CPU_MEM_TIMING + Packet *ifetch_pkt = new Packet; + ifetch_pkt->cmd = Read; + ifetch_pkt->data = (uint8_t *)&inst; + ifetch_pkt->req = ifetch_req; + ifetch_pkt->size = sizeof(MachInst); +#endif + ifetch_pkt->reset(); + ifetch_pkt->addr = ifetch_req->getPaddr(); + sendIcacheRequest(ifetch_pkt); +#if SIMPLE_CPU_MEM_TIMING || SIMPLE_CPU_MEM_ATOMIC + return; +#endif +/* if (icacheInterface && fault == NoFault) { memReq->completionEvent = NULL; @@ -743,7 +1018,7 @@ SimpleCPU::tick() // Ugly hack to get an event scheduled *only* if the access is // a miss. We really should add first-class support for this // at some point. - if (result != MA_HIT && icacheInterface->doEvents()) { + if (result != MA_HIT && icacheInterface->doEvents()) { memReq->completionEvent = &cacheCompletionEvent; lastIcacheStall = curTick; unscheduleTickEvent(); @@ -751,6 +1026,8 @@ SimpleCPU::tick() return; } } +*/ + } } // If we've got a valid instruction (i.e., no fault on instruction @@ -771,6 +1048,9 @@ SimpleCPU::tick() traceData = Trace::getInstRecord(curTick, xcProxy, this, curStaticInst, cpuXC->readPC()); + DPRINTF(Decode,"Decode: Decoded %s instruction (opcode: 0x%x): 0x%x\n", + curStaticInst->getName(),curStaticInst->getOpcode(), curStaticInst->machInst); + #if FULL_SYSTEM cpuXC->setInst(inst); #endif // FULL_SYSTEM @@ -806,8 +1086,7 @@ SimpleCPU::tick() // If we have a dcache miss, then we can't finialize the instruction // trace yet because we want to populate it with the data later - if (traceData && - !(status() == DcacheMissStall && memReq->cmd.isRead())) { + if (traceData && (status() != DcacheWaitResponse)) { traceData->finalize(); } @@ -819,11 +1098,11 @@ SimpleCPU::tick() #if FULL_SYSTEM fault->invoke(xcProxy); #else // !FULL_SYSTEM - fatal("fault (%d) detected @ PC 0x%08p", fault, cpuXC->readPC()); + fatal("fault (%s) detected @ PC %08p", fault->name(), cpuXC->readPC()); #endif // FULL_SYSTEM } else { -#if THE_ISA != MIPS_ISA +#if THE_ISA == ALPHA_ISA // go to the next instruction cpuXC->setPC(cpuXC->readNextPC()); cpuXC->setNextPC(cpuXC->readNextPC() + sizeof(MachInst)); @@ -846,7 +1125,7 @@ SimpleCPU::tick() assert(status() == Running || status() == Idle || - status() == DcacheMissStall); + status() == DcacheWaitResponse); if (status() == Running && !tickEvent.scheduled()) tickEvent.schedule(curTick + cycles(1)); @@ -862,11 +1141,11 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU) Param<Counter> max_insts_all_threads; Param<Counter> max_loads_any_thread; Param<Counter> max_loads_all_threads; + SimObjectParam<MemObject *> mem; #if FULL_SYSTEM SimObjectParam<AlphaITB *> itb; SimObjectParam<AlphaDTB *> dtb; - SimObjectParam<FunctionalMemory *> mem; SimObjectParam<System *> system; Param<int> cpu_id; Param<Tick> profile; @@ -875,8 +1154,6 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU) #endif // FULL_SYSTEM Param<int> clock; - SimObjectParam<BaseMem *> icache; - SimObjectParam<BaseMem *> dcache; Param<bool> defer_registration; Param<int> width; @@ -895,11 +1172,11 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleCPU) "terminate when any thread reaches this load count"), INIT_PARAM(max_loads_all_threads, "terminate when all threads have reached this load count"), + INIT_PARAM(mem, "memory"), #if FULL_SYSTEM INIT_PARAM(itb, "Instruction TLB"), INIT_PARAM(dtb, "Data TLB"), - INIT_PARAM(mem, "memory"), INIT_PARAM(system, "system object"), INIT_PARAM(cpu_id, "processor ID"), INIT_PARAM(profile, ""), @@ -908,8 +1185,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleCPU) #endif // FULL_SYSTEM INIT_PARAM(clock, "clock speed"), - INIT_PARAM(icache, "L1 instruction cache object"), - INIT_PARAM(dcache, "L1 data cache object"), INIT_PARAM(defer_registration, "defer system registration (for sampling)"), INIT_PARAM(width, "cpu width"), INIT_PARAM(function_trace, "Enable function trace"), @@ -931,14 +1206,12 @@ CREATE_SIM_OBJECT(SimpleCPU) params->clock = clock; params->functionTrace = function_trace; params->functionTraceStart = function_trace_start; - params->icache_interface = (icache) ? icache->getInterface() : NULL; - params->dcache_interface = (dcache) ? dcache->getInterface() : NULL; params->width = width; + params->mem = mem; #if FULL_SYSTEM params->itb = itb; params->dtb = dtb; - params->mem = mem; params->system = system; params->cpu_id = cpu_id; params->profile = profile; diff --git a/cpu/simple/cpu.hh b/cpu/simple/cpu.hh index 4ab9a1c3e..945de20af 100644 --- a/cpu/simple/cpu.hh +++ b/cpu/simple/cpu.hh @@ -36,6 +36,9 @@ #include "cpu/pc_event.hh" #include "cpu/sampler/sampler.hh" #include "cpu/static_inst.hh" +#include "mem/packet.hh" +#include "mem/port.hh" +#include "mem/request.hh" #include "sim/eventq.hh" // forward declarations @@ -43,7 +46,7 @@ class Processor; class AlphaITB; class AlphaDTB; -class PhysicalMemory; +class MemObject; class RemoteGDB; class GDBListener; @@ -55,18 +58,61 @@ class Process; #endif // FULL_SYSTEM class ExecContext; -class MemInterface; class Checkpoint; namespace Trace { class InstRecord; } + +// Set exactly one of these symbols to 1 to set the memory access +// model. Probably should make these template parameters, or even +// just fork the CPU models. +// +#define SIMPLE_CPU_MEM_TIMING 0 +#define SIMPLE_CPU_MEM_ATOMIC 0 +#define SIMPLE_CPU_MEM_IMMEDIATE 1 + + class SimpleCPU : public BaseCPU { protected: typedef TheISA::MachInst MachInst; typedef TheISA::MiscReg MiscReg; + typedef TheISA::FloatReg FloatReg; + typedef TheISA::FloatRegBits FloatRegBits; + class CpuPort : public Port + { + + SimpleCPU *cpu; + + public: + + CpuPort(SimpleCPU *_cpu) + : cpu(_cpu) + { } + + protected: + + virtual bool recvTiming(Packet &pkt); + + virtual Tick recvAtomic(Packet &pkt); + + virtual void recvFunctional(Packet &pkt); + + virtual void recvStatusChange(Status status); + + virtual Packet *recvRetry(); + + virtual void getDeviceAddressRanges(AddrRangeList &resp, + AddrRangeList &snoop) + { resp.clear(); snoop.clear(); } + }; + + MemObject *mem; + CpuPort icachePort; + CpuPort dcachePort; + public: // main simulation loop (one cycle) void tick(); @@ -109,10 +155,12 @@ class SimpleCPU : public BaseCPU enum Status { Running, Idle, - IcacheMissStall, - IcacheMissComplete, - DcacheMissStall, - DcacheMissSwitch, + IcacheRetry, + IcacheWaitResponse, + IcacheAccessComplete, + DcacheRetry, + DcacheWaitResponse, + DcacheWaitSwitch, SwitchedOut }; @@ -133,13 +181,11 @@ class SimpleCPU : public BaseCPU public: struct Params : public BaseCPU::Params { - MemInterface *icache_interface; - MemInterface *dcache_interface; int width; + MemObject *mem; #if FULL_SYSTEM AlphaITB *itb; AlphaDTB *dtb; - FunctionalMemory *mem; #else Process *process; #endif @@ -162,17 +208,22 @@ class SimpleCPU : public BaseCPU bool interval_stats; #endif - // L1 instruction cache - MemInterface *icacheInterface; - - // L1 data cache - MemInterface *dcacheInterface; - // current instruction MachInst inst; - // Refcounted pointer to the one memory request. - MemReqPtr memReq; + // Static data storage + TheISA::IntReg dataReg; + +#if SIMPLE_CPU_MEM_TIMING + Packet *retry_pkt; +#elif SIMPLE_CPU_MEM_ATOMIC || SIMPLE_CPU_MEM_IMMEDIATE + Request *ifetch_req; + Packet *ifetch_pkt; + Request *data_read_req; + Packet *data_read_pkt; + Request *data_write_req; + Packet *data_write_pkt; +#endif // Pointer to the sampler that is telling us to switchover. // Used to signal the completion of the pipe drain and schedule @@ -181,20 +232,6 @@ class SimpleCPU : public BaseCPU StaticInstPtr curStaticInst; - class CacheCompletionEvent : public Event - { - private: - SimpleCPU *cpu; - - public: - CacheCompletionEvent(SimpleCPU *_cpu); - - virtual void process(); - virtual const char *description(); - }; - - CacheCompletionEvent cacheCompletionEvent; - Status status() const { return _status; } virtual void activateContext(int thread_num, int delay); @@ -227,15 +264,28 @@ class SimpleCPU : public BaseCPU Stats::Average<> notIdleFraction; Stats::Formula idleFraction; - // number of cycles stalled for I-cache misses + // number of cycles stalled for I-cache responses Stats::Scalar<> icacheStallCycles; Counter lastIcacheStall; - // number of cycles stalled for D-cache misses + // number of cycles stalled for I-cache retries + Stats::Scalar<> icacheRetryCycles; + Counter lastIcacheRetry; + + // number of cycles stalled for D-cache responses Stats::Scalar<> dcacheStallCycles; Counter lastDcacheStall; - void processCacheCompletion(); + // number of cycles stalled for D-cache retries + Stats::Scalar<> dcacheRetryCycles; + Counter lastDcacheRetry; + + void sendIcacheRequest(Packet *pkt); + void sendDcacheRequest(Packet *pkt); + void processResponse(Packet &response); + + Packet * processRetry(); + void recvStatusChange(Port::Status status) {} virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); @@ -281,22 +331,28 @@ class SimpleCPU : public BaseCPU return cpuXC->readIntReg(si->srcRegIdx(idx)); } - float readFloatRegSingle(const StaticInst *si, int idx) + FloatReg readFloatReg(const StaticInst *si, int idx, int width) + { + int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; + return cpuXC->readFloatReg(reg_idx, width); + } + + FloatReg readFloatReg(const StaticInst *si, int idx) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; - return cpuXC->readFloatRegSingle(reg_idx); + return cpuXC->readFloatReg(reg_idx); } - double readFloatRegDouble(const StaticInst *si, int idx) + FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; - return cpuXC->readFloatRegDouble(reg_idx); + return cpuXC->readFloatRegBits(reg_idx, width); } - uint64_t readFloatRegInt(const StaticInst *si, int idx) + FloatRegBits readFloatRegBits(const StaticInst *si, int idx) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; - return cpuXC->readFloatRegInt(reg_idx); + return cpuXC->readFloatRegBits(reg_idx); } void setIntReg(const StaticInst *si, int idx, uint64_t val) @@ -304,26 +360,38 @@ class SimpleCPU : public BaseCPU cpuXC->setIntReg(si->destRegIdx(idx), val); } - void setFloatRegSingle(const StaticInst *si, int idx, float val) + void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; - cpuXC->setFloatRegSingle(reg_idx, val); + cpuXC->setFloatReg(reg_idx, val, width); } - void setFloatRegDouble(const StaticInst *si, int idx, double val) + void setFloatReg(const StaticInst *si, int idx, FloatReg val) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; - cpuXC->setFloatRegDouble(reg_idx, val); + cpuXC->setFloatReg(reg_idx, val); } - void setFloatRegInt(const StaticInst *si, int idx, uint64_t val) + void setFloatRegBits(const StaticInst *si, int idx, + FloatRegBits val, int width) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; - cpuXC->setFloatRegInt(reg_idx, val); + cpuXC->setFloatRegBits(reg_idx, val, width); + } + + void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val) + { + int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; + cpuXC->setFloatRegBits(reg_idx, val); } uint64_t readPC() { return cpuXC->readPC(); } + uint64_t readNextPC() { return cpuXC->readNextPC(); } + uint64_t readNextNPC() { return cpuXC->readNextNPC(); } + + void setPC(uint64_t val) { cpuXC->setPC(val); } void setNextPC(uint64_t val) { cpuXC->setNextPC(val); } + void setNextNPC(uint64_t val) { cpuXC->setNextNPC(val); } MiscReg readMiscReg(int misc_reg) { @@ -353,7 +421,7 @@ class SimpleCPU : public BaseCPU void ev5_trap(Fault fault) { fault->invoke(xcProxy); } bool simPalCheck(int palFunc) { return cpuXC->simPalCheck(palFunc); } #else - void syscall() { cpuXC->syscall(); } + void syscall(int64_t callnum) { cpuXC->syscall(callnum); } #endif bool misspeculating() { return cpuXC->misspeculating(); } diff --git a/cpu/static_inst.hh b/cpu/static_inst.hh index 20116554e..f0b75c10e 100644 --- a/cpu/static_inst.hh +++ b/cpu/static_inst.hh @@ -33,8 +33,9 @@ #include <string> #include "base/hashmap.hh" +#include "base/misc.hh" #include "base/refcnt.hh" -#include "encumbered/cpu/full/op_class.hh" +#include "cpu/op_class.hh" #include "sim/host.hh" #include "arch/isa_traits.hh" @@ -390,6 +391,18 @@ class StaticInst : public StaticInstBase /// @retval A pointer to the corresponding StaticInst object. //This is defined as inline below. static StaticInstPtr decode(ExtMachInst mach_inst); + + //MIPS Decoder Debug Functions + int getOpcode() { return (machInst & 0xFC000000) >> 26 ; }//31..26 + int getRs() { return (machInst & 0x03E00000) >> 21; } //25...21 + int getRt() { return (machInst & 0x001F0000) >> 16; } //20...16 + int getRd() { return (machInst & 0x0000F800) >> 11; } //15...11 + int getImm() { return (machInst & 0x0000FFFF); } //15...0 + int getFunction(){ return (machInst & 0x0000003F); }//5...0 + int getBranch(){ return (machInst & 0x0000FFFF); }//15...0 + int getJump(){ return (machInst & 0x03FFFFFF); }//5...0 + int getHint(){ return (machInst & 0x000007C0) >> 6; } //10...6 + std::string getName() { return mnemonic; } }; typedef RefCountingPtr<StaticInstBase> StaticInstBasePtr; |