From 54d4220b004a385d04def37fa55c820366da0d4a Mon Sep 17 00:00:00 2001 From: Kevin Lim Date: Wed, 7 Jun 2006 15:29:53 -0400 Subject: Reorganization/renaming of CPUExecContext. Now it is called SimpleThread in order to clear up the confusion due to the many ExecContexts. It also derives from a common ThreadState object, which holds various state common to threads across CPU models. Following with the previous check-in, ExecContext now refers only to the interface provided to the ISA in order to access CPU state. ThreadContext refers to the interface provided to all objects outside the CPU in order to access thread state. SimpleThread provides all thread state and the interface to access it, and is suitable for simple execution models such as the SimpleCPU. src/SConscript: Include thread state file. src/arch/alpha/ev5.cc: src/cpu/checker/cpu.cc: src/cpu/checker/cpu.hh: src/cpu/checker/thread_context.hh: src/cpu/memtest/memtest.cc: src/cpu/memtest/memtest.hh: src/cpu/o3/cpu.cc: src/cpu/ozone/cpu_impl.hh: src/cpu/simple/atomic.cc: src/cpu/simple/base.cc: src/cpu/simple/base.hh: src/cpu/simple/timing.cc: Rename CPUExecContext to SimpleThread. src/cpu/base_dyn_inst.hh: Make thread member variables protected.. src/cpu/o3/alpha_cpu.hh: src/cpu/o3/cpu.hh: Make various members of ThreadState protected. src/cpu/o3/alpha_cpu_impl.hh: Push generation of TranslatingPort into the CPU itself. Make various members of ThreadState protected. src/cpu/o3/thread_state.hh: Pull a lot of common code into the base ThreadState class. src/cpu/ozone/thread_state.hh: Rename CPUExecContext to SimpleThread, move a lot of common code into base ThreadState class. src/cpu/thread_state.hh: Push a lot of common code into base ThreadState class. This goes along with renaming CPUExecContext to SimpleThread, and making it derive from ThreadState. src/cpu/simple_thread.cc: Rename CPUExecContext to SimpleThread, make it derive from ThreadState. This helps push a lot of common code/state into a single class that can be used by all CPUs. src/cpu/simple_thread.hh: Rename CPUExecContext to SimpleThread, make it derive from ThreadState. src/kern/system_events.cc: Rename cpu_exec_context to thread_context. src/sim/process.hh: Remove unused forward declaration. --HG-- rename : src/cpu/cpu_exec_context.cc => src/cpu/simple_thread.cc rename : src/cpu/cpu_exec_context.hh => src/cpu/simple_thread.hh extra : convert_revision : 2ed617aa80b64016cb9270f75352607cca032733 --- src/SConscript | 3 +- src/arch/alpha/ev5.cc | 10 +- src/cpu/base_dyn_inst.hh | 4 +- src/cpu/checker/cpu.cc | 118 ++++----- src/cpu/checker/cpu.hh | 54 ++-- src/cpu/checker/thread_context.hh | 25 +- src/cpu/cpu_exec_context.cc | 345 ------------------------ src/cpu/cpu_exec_context.hh | 543 -------------------------------------- src/cpu/memtest/memtest.cc | 6 +- src/cpu/memtest/memtest.hh | 2 +- src/cpu/o3/alpha_cpu.hh | 34 +-- src/cpu/o3/alpha_cpu_impl.hh | 117 +++++--- src/cpu/o3/cpu.cc | 12 +- src/cpu/o3/cpu.hh | 6 +- src/cpu/o3/thread_state.hh | 31 +-- src/cpu/ozone/cpu_impl.hh | 6 +- src/cpu/ozone/thread_state.hh | 21 +- src/cpu/simple/atomic.cc | 12 +- src/cpu/simple/base.cc | 116 ++++---- src/cpu/simple/base.hh | 63 ++--- src/cpu/simple/timing.cc | 12 +- src/cpu/simple_thread.cc | 324 +++++++++++++++++++++++ src/cpu/simple_thread.hh | 463 ++++++++++++++++++++++++++++++++ src/cpu/thread_state.cc | 46 ++++ src/cpu/thread_state.hh | 128 +++++++-- src/kern/system_events.cc | 2 +- src/sim/process.hh | 1 - 27 files changed, 1255 insertions(+), 1249 deletions(-) delete mode 100644 src/cpu/cpu_exec_context.cc delete mode 100644 src/cpu/cpu_exec_context.hh create mode 100644 src/cpu/simple_thread.cc create mode 100644 src/cpu/simple_thread.hh create mode 100644 src/cpu/thread_state.cc (limited to 'src') diff --git a/src/SConscript b/src/SConscript index 3fc9d4c2f..d29ecb7bb 100644 --- a/src/SConscript +++ b/src/SConscript @@ -83,7 +83,6 @@ base_sources = Split(''' cpu/activity.cc cpu/base.cc - cpu/cpu_exec_context.cc cpu/cpuevent.cc cpu/exetrace.cc cpu/op_class.cc @@ -91,6 +90,8 @@ base_sources = Split(''' cpu/quiesce_event.cc cpu/static_inst.cc cpu/sampler/sampler.cc + cpu/simple_thread.cc + cpu/thread_state.cc encumbered/cpu/full/fu_pool.cc diff --git a/src/arch/alpha/ev5.cc b/src/arch/alpha/ev5.cc index 50ce6b78a..c419762b7 100644 --- a/src/arch/alpha/ev5.cc +++ b/src/arch/alpha/ev5.cc @@ -37,7 +37,7 @@ #include "base/stats/events.hh" #include "config/full_system.hh" #include "cpu/base.hh" -#include "cpu/cpu_exec_context.hh" +#include "cpu/simple_thread.hh" #include "cpu/thread_context.hh" #include "kern/kernel_stats.hh" #include "sim/debug.hh" @@ -135,12 +135,12 @@ AlphaISA::zeroRegisters(CPU *cpu) // Insure ISA semantics // (no longer very clean due to the change in setIntReg() in the // cpu model. Consider changing later.) - cpu->cpuXC->setIntReg(ZeroReg, 0); - cpu->cpuXC->setFloatReg(ZeroReg, 0.0); + cpu->thread->setIntReg(ZeroReg, 0); + cpu->thread->setFloatReg(ZeroReg, 0.0); } Fault -CPUExecContext::hwrei() +SimpleThread::hwrei() { if (!inPalMode()) return new UnimplementedOpcodeFault; @@ -562,7 +562,7 @@ AlphaISA::copyIprs(ThreadContext *src, ThreadContext *dest) * If return value is false, actual PAL call will be suppressed. */ bool -CPUExecContext::simPalCheck(int palFunc) +SimpleThread::simPalCheck(int palFunc) { if (kernelStats) kernelStats->callpal(palFunc, tc); diff --git a/src/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh index 0657be324..e69e00d6c 100644 --- a/src/cpu/base_dyn_inst.hh +++ b/src/cpu/base_dyn_inst.hh @@ -650,7 +650,7 @@ BaseDynInst::read(Addr addr, T &data, unsigned flags) req = new Request(); req->setVirt(asid, addr, sizeof(T), flags, this->PC); - req->setThreadContext(thread->cpuId, threadNumber); + req->setThreadContext(thread->readCpuId(), threadNumber); if ((req->getVaddr() & (TheISA::VMPageSize - 1)) + req->getSize() > TheISA::VMPageSize) { @@ -705,7 +705,7 @@ BaseDynInst::write(T data, Addr addr, unsigned flags, uint64_t *res) req = new Request(); req->setVirt(asid, addr, sizeof(T), flags, this->PC); - req->setThreadContext(thread->cpuId, threadNumber); + req->setThreadContext(thread->readCpuId(), threadNumber); if ((req->getVaddr() & (TheISA::VMPageSize - 1)) + req->getSize() > TheISA::VMPageSize) { diff --git a/src/cpu/checker/cpu.cc b/src/cpu/checker/cpu.cc index 7ae7047e8..2d2f67e6b 100644 --- a/src/cpu/checker/cpu.cc +++ b/src/cpu/checker/cpu.cc @@ -33,7 +33,7 @@ #include "cpu/base.hh" #include "cpu/base_dyn_inst.hh" #include "cpu/checker/cpu.hh" -#include "cpu/cpu_exec_context.hh" +#include "cpu/simple_thread.hh" #include "cpu/thread_context.hh" #include "cpu/static_inst.hh" #include "sim/byteswap.hh" @@ -62,7 +62,7 @@ CheckerCPU::init() } CheckerCPU::CheckerCPU(Params *p) - : BaseCPU(p), cpuXC(NULL), tc(NULL) + : BaseCPU(p), thread(NULL), tc(NULL) { memReq = NULL; @@ -94,21 +94,21 @@ CheckerCPU::setMemory(MemObject *mem) { memPtr = mem; #if !FULL_SYSTEM - cpuXC = new CPUExecContext(this, /* thread_num */ 0, process, - /* asid */ 0, mem); + thread = new SimpleThread(this, /* thread_num */ 0, process, + /* asid */ 0, mem); - cpuXC->setStatus(ThreadContext::Suspended); - tc = cpuXC->getTC(); + thread->setStatus(ThreadContext::Suspended); + tc = thread->getTC(); threadContexts.push_back(tc); #else if (systemPtr) { - cpuXC = new CPUExecContext(this, 0, systemPtr, itb, dtb, memPtr, false); + thread = new SimpleThread(this, 0, systemPtr, itb, dtb, memPtr, false); - cpuXC->setStatus(ThreadContext::Suspended); - tc = cpuXC->getTC(); + thread->setStatus(ThreadContext::Suspended); + tc = thread->getTC(); threadContexts.push_back(tc); - delete cpuXC->kernelStats; - cpuXC->kernelStats = NULL; + delete thread->kernelStats; + thread->kernelStats = NULL; } #endif } @@ -120,13 +120,13 @@ CheckerCPU::setSystem(System *system) systemPtr = system; if (memPtr) { - cpuXC = new CPUExecContext(this, 0, systemPtr, itb, dtb, memPtr, false); + thread = new SimpleThread(this, 0, systemPtr, itb, dtb, memPtr, false); - cpuXC->setStatus(ThreadContext::Suspended); - tc = cpuXC->getTC(); + thread->setStatus(ThreadContext::Suspended); + tc = thread->getTC(); threadContexts.push_back(tc); - delete cpuXC->kernelStats; - cpuXC->kernelStats = NULL; + delete thread->kernelStats; + thread->kernelStats = NULL; } } #endif @@ -150,7 +150,7 @@ CheckerCPU::serialize(ostream &os) BaseCPU::serialize(os); SERIALIZE_SCALAR(inst); nameOut(os, csprintf("%s.xc", name())); - cpuXC->serialize(os); + thread->serialize(os); cacheCompletionEvent.serialize(os); */ } @@ -161,7 +161,7 @@ CheckerCPU::unserialize(Checkpoint *cp, const string §ion) /* BaseCPU::unserialize(cp, section); UNSERIALIZE_SCALAR(inst); - cpuXC->unserialize(cp, csprintf("%s.xc", section)); + thread->unserialize(cp, csprintf("%s.xc", section)); */ } @@ -184,7 +184,7 @@ CheckerCPU::read(Addr addr, T &data, unsigned flags) // need to fill in CPU & thread IDs here memReq = new Request(); - memReq->setVirt(0, addr, sizeof(T), flags, cpuXC->readPC()); + memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC()); // translate to physical address translateDataReadReq(memReq); @@ -254,10 +254,10 @@ CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) // need to fill in CPU & thread IDs here memReq = new Request(); - memReq->setVirt(0, addr, sizeof(T), flags, cpuXC->readPC()); + memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC()); // translate to physical address - cpuXC->translateDataWriteReq(memReq); + thread->translateDataWriteReq(memReq); // Can compare the write data and result only if it's cacheable, // not a store conditional, or is a store conditional that @@ -356,9 +356,9 @@ bool CheckerCPU::translateInstReq(Request *req) { #if FULL_SYSTEM - return (cpuXC->translateInstReq(req) == NoFault); + return (thread->translateInstReq(req) == NoFault); #else - cpuXC->translateInstReq(req); + thread->translateInstReq(req); return true; #endif } @@ -366,7 +366,7 @@ CheckerCPU::translateInstReq(Request *req) void CheckerCPU::translateDataReadReq(Request *req) { - cpuXC->translateDataReadReq(req); + thread->translateDataReadReq(req); if (req->getVaddr() != unverifiedReq->getVaddr()) { warn("%lli: Request virtual addresses do not match! Inst: %#x, " @@ -386,7 +386,7 @@ CheckerCPU::translateDataReadReq(Request *req) void CheckerCPU::translateDataWriteReq(Request *req) { - cpuXC->translateDataWriteReq(req); + thread->translateDataWriteReq(req); if (req->getVaddr() != unverifiedReq->getVaddr()) { warn("%lli: Request virtual addresses do not match! Inst: %#x, " @@ -475,9 +475,9 @@ Checker::tick(DynInstPtr &completed_inst) Fault fault = NoFault; // maintain $r0 semantics - cpuXC->setIntReg(ZeroReg, 0); + thread->setIntReg(ZeroReg, 0); #ifdef TARGET_ALPHA - cpuXC->setFloatRegDouble(ZeroReg, 0.0); + thread->setFloatRegDouble(ZeroReg, 0.0); #endif // TARGET_ALPHA // Check if any recent PC changes match up with anything we @@ -485,14 +485,14 @@ Checker::tick(DynInstPtr &completed_inst) // PC-based events have occurred in both the checker and CPU. if (changedPC) { DPRINTF(Checker, "Changed PC recently to %#x\n", - cpuXC->readPC()); + thread->readPC()); if (willChangePC) { - if (newPC == cpuXC->readPC()) { + if (newPC == thread->readPC()) { DPRINTF(Checker, "Changed PC matches expected PC\n"); } else { warn("%lli: Changed PC does not match expected PC, " "changed: %#x, expected: %#x", - curTick, cpuXC->readPC(), newPC); + curTick, thread->readPC(), newPC); handleError(); } willChangePC = false; @@ -501,7 +501,7 @@ Checker::tick(DynInstPtr &completed_inst) } if (changedNextPC) { DPRINTF(Checker, "Changed NextPC recently to %#x\n", - cpuXC->readNextPC()); + thread->readNextPC()); changedNextPC = false; } @@ -513,13 +513,13 @@ Checker::tick(DynInstPtr &completed_inst) #define IFETCH_FLAGS(pc) 0 #endif - uint64_t fetch_PC = cpuXC->readPC() & ~3; + uint64_t fetch_PC = thread->readPC() & ~3; // set up memory request for instruction fetch memReq = new Request(inst->threadNumber, fetch_PC, sizeof(uint32_t), - IFETCH_FLAGS(cpuXC->readPC()), - fetch_PC, cpuXC->readCpuId(), inst->threadNumber); + IFETCH_FLAGS(thread->readPC()), + fetch_PC, thread->readCpuId(), inst->threadNumber); bool succeeded = translateInstReq(memReq); @@ -531,12 +531,12 @@ Checker::tick(DynInstPtr &completed_inst) // translate this instruction; in the SMT case it's // possible that its ITB entry was kicked out. warn("%lli: Instruction PC %#x was not found in the ITB!", - curTick, cpuXC->readPC()); + curTick, thread->readPC()); handleError(); // go to the next instruction - cpuXC->setPC(cpuXC->readNextPC()); - cpuXC->setNextPC(cpuXC->readNextPC() + sizeof(MachInst)); + thread->setPC(thread->readNextPC()); + thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); return; } else { @@ -567,10 +567,10 @@ Checker::tick(DynInstPtr &completed_inst) validateInst(inst); curStaticInst = StaticInst::decode(makeExtMI(machInst, - cpuXC->readPC())); + thread->readPC())); #if FULL_SYSTEM - cpuXC->setInst(machInst); + thread->setInst(machInst); #endif // FULL_SYSTEM fault = inst->getFault(); @@ -585,7 +585,7 @@ Checker::tick(DynInstPtr &completed_inst) // that the instruction is properly marked as a fault. if (fault == NoFault) { - cpuXC->func_exe_inst++; + thread->funcExeInst++; fault = curStaticInst->execute(this, NULL); @@ -601,21 +601,21 @@ Checker::tick(DynInstPtr &completed_inst) #if FULL_SYSTEM fault->invoke(xcProxy); willChangePC = true; - newPC = cpuXC->readPC(); + newPC = thread->readPC(); DPRINTF(Checker, "Fault, PC is now %#x\n", newPC); #else // !FULL_SYSTEM - fatal("fault (%d) detected @ PC 0x%08p", fault, cpuXC->readPC()); + fatal("fault (%d) detected @ PC 0x%08p", fault, thread->readPC()); #endif // FULL_SYSTEM } else { #if THE_ISA != MIPS_ISA // go to the next instruction - cpuXC->setPC(cpuXC->readNextPC()); - cpuXC->setNextPC(cpuXC->readNextPC() + sizeof(MachInst)); + thread->setPC(thread->readNextPC()); + thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); #else // go to the next instruction - cpuXC->setPC(cpuXC->readNextPC()); - cpuXC->setNextPC(cpuXC->readNextNPC()); - cpuXC->setNextNPC(cpuXC->readNextNPC() + sizeof(MachInst)); + thread->setPC(thread->readNextPC()); + thread->setNextPC(thread->readNextNPC()); + thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); #endif } @@ -627,13 +627,13 @@ Checker::tick(DynInstPtr &completed_inst) Addr oldpc; int count = 0; do { - oldpc = cpuXC->readPC(); + oldpc = thread->readPC(); system->pcEventQueue.service(xcProxy); count++; - } while (oldpc != cpuXC->readPC()); + } while (oldpc != thread->readPC()); if (count > 1) { willChangePC = true; - newPC = cpuXC->readPC(); + newPC = thread->readPC(); DPRINTF(Checker, "PC Event, PC is now %#x\n", newPC); } #endif @@ -677,9 +677,9 @@ template void Checker::validateInst(DynInstPtr &inst) { - if (inst->readPC() != cpuXC->readPC()) { + if (inst->readPC() != thread->readPC()) { warn("%lli: PCs do not match! Inst: %#x, checker: %#x", - curTick, inst->readPC(), cpuXC->readPC()); + curTick, inst->readPC(), thread->readPC()); if (changedPC) { warn("%lli: Changed PCs recently, may not be an error", curTick); @@ -710,11 +710,11 @@ Checker::validateExecution(DynInstPtr &inst) // instruction and write it to the register. RegIndex idx = inst->destRegIdx(0); if (idx < TheISA::FP_Base_DepTag) { - cpuXC->setIntReg(idx, inst->readIntResult()); + thread->setIntReg(idx, inst->readIntResult()); } else if (idx < TheISA::Fpcr_DepTag) { - cpuXC->setFloatRegBits(idx, inst->readIntResult()); + thread->setFloatRegBits(idx, inst->readIntResult()); } else { - cpuXC->setMiscReg(idx, inst->readIntResult()); + thread->setMiscReg(idx, inst->readIntResult()); } } else if (result.integer != inst->readIntResult()) { warn("%lli: Instruction results do not match! (Values may not " @@ -724,10 +724,10 @@ Checker::validateExecution(DynInstPtr &inst) } } - if (inst->readNextPC() != cpuXC->readNextPC()) { + if (inst->readNextPC() != thread->readNextPC()) { warn("%lli: Instruction next PCs do not match! Inst: %#x, " "checker: %#x", - curTick, inst->readNextPC(), cpuXC->readNextPC()); + curTick, inst->readNextPC(), thread->readNextPC()); handleError(); } @@ -741,12 +741,12 @@ Checker::validateExecution(DynInstPtr &inst) miscRegIdxs.pop(); if (inst->tcBase()->readMiscReg(misc_reg_idx) != - cpuXC->readMiscReg(misc_reg_idx)) { + thread->readMiscReg(misc_reg_idx)) { warn("%lli: Misc reg idx %i (side effect) does not match! " "Inst: %#x, checker: %#x", curTick, misc_reg_idx, inst->tcBase()->readMiscReg(misc_reg_idx), - cpuXC->readMiscReg(misc_reg_idx)); + thread->readMiscReg(misc_reg_idx)); handleError(); } } diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh index 484f4cf04..f733becd4 100644 --- a/src/cpu/checker/cpu.hh +++ b/src/cpu/checker/cpu.hh @@ -38,7 +38,7 @@ #include "config/full_system.hh" #include "cpu/base.hh" #include "cpu/base_dyn_inst.hh" -#include "cpu/cpu_exec_context.hh" +#include "cpu/simple_thread.hh" #include "cpu/pc_event.hh" #include "cpu/static_inst.hh" #include "sim/eventq.hh" @@ -77,7 +77,7 @@ class Sampler; * instructions marked as "IsUnverifiable", the checker assumes that * the value from the main CPU's execution is correct and simply * copies that value. It provides a CheckerThreadContext (see - * checker/exec_context.hh) that provides hooks for updating the + * checker/thread_context.hh) that provides hooks for updating the * Checker's state through any ThreadContext accesses. This allows the * checker to be able to correctly verify instructions, even with * external accesses to the ThreadContext that change state. @@ -129,8 +129,8 @@ class CheckerCPU : public BaseCPU Port *dcachePort; public: - // execution context - CPUExecContext *cpuXC; + // Primary thread being run. + SimpleThread *thread; ThreadContext *tc; @@ -213,43 +213,43 @@ class CheckerCPU : public BaseCPU uint64_t readIntReg(const StaticInst *si, int idx) { - return cpuXC->readIntReg(si->srcRegIdx(idx)); + return thread->readIntReg(si->srcRegIdx(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); + return thread->readFloatReg(reg_idx, width); } FloatReg readFloatReg(const StaticInst *si, int idx) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; - return cpuXC->readFloatReg(reg_idx); + return thread->readFloatReg(reg_idx); } FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; - return cpuXC->readFloatRegBits(reg_idx, width); + return thread->readFloatRegBits(reg_idx, width); } FloatRegBits readFloatRegBits(const StaticInst *si, int idx) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; - return cpuXC->readFloatRegBits(reg_idx); + return thread->readFloatRegBits(reg_idx); } void setIntReg(const StaticInst *si, int idx, uint64_t val) { - cpuXC->setIntReg(si->destRegIdx(idx), val); + thread->setIntReg(si->destRegIdx(idx), val); result.integer = val; } void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; - cpuXC->setFloatReg(reg_idx, val, width); + thread->setFloatReg(reg_idx, val, width); switch(width) { case 32: result.fp = val; @@ -263,7 +263,7 @@ class CheckerCPU : public BaseCPU void setFloatReg(const StaticInst *si, int idx, FloatReg val) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; - cpuXC->setFloatReg(reg_idx, val); + thread->setFloatReg(reg_idx, val); result.fp = val; } @@ -271,46 +271,46 @@ class CheckerCPU : public BaseCPU int width) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; - cpuXC->setFloatRegBits(reg_idx, val, width); + thread->setFloatRegBits(reg_idx, val, width); result.integer = val; } void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; - cpuXC->setFloatRegBits(reg_idx, val); + thread->setFloatRegBits(reg_idx, val); result.integer = val; } - uint64_t readPC() { return cpuXC->readPC(); } + uint64_t readPC() { return thread->readPC(); } - uint64_t readNextPC() { return cpuXC->readNextPC(); } + uint64_t readNextPC() { return thread->readNextPC(); } void setNextPC(uint64_t val) { - cpuXC->setNextPC(val); + thread->setNextPC(val); } MiscReg readMiscReg(int misc_reg) { - return cpuXC->readMiscReg(misc_reg); + return thread->readMiscReg(misc_reg); } MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) { - return cpuXC->readMiscRegWithEffect(misc_reg, fault); + return thread->readMiscRegWithEffect(misc_reg, fault); } Fault setMiscReg(int misc_reg, const MiscReg &val) { result.integer = val; miscRegIdxs.push(misc_reg); - return cpuXC->setMiscReg(misc_reg, val); + return thread->setMiscReg(misc_reg, val); } Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val) { miscRegIdxs.push(misc_reg); - return cpuXC->setMiscRegWithEffect(misc_reg, val); + return thread->setMiscRegWithEffect(misc_reg, val); } void recordPCChange(uint64_t val) { changedPC = true; } @@ -321,12 +321,12 @@ class CheckerCPU : public BaseCPU void translateDataReadReq(Request *req); #if FULL_SYSTEM - Fault hwrei() { return cpuXC->hwrei(); } - int readIntrFlag() { return cpuXC->readIntrFlag(); } - void setIntrFlag(int val) { cpuXC->setIntrFlag(val); } - bool inPalMode() { return cpuXC->inPalMode(); } + Fault hwrei() { return thread->hwrei(); } + int readIntrFlag() { return thread->readIntrFlag(); } + void setIntrFlag(int val) { thread->setIntrFlag(val); } + bool inPalMode() { return thread->inPalMode(); } void ev5_trap(Fault fault) { fault->invoke(xcProxy); } - bool simPalCheck(int palFunc) { return cpuXC->simPalCheck(palFunc); } + bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); } #else // Assume that the normal CPU's call to syscall was successful. // The checker's state would have already been updated by the syscall. @@ -341,7 +341,7 @@ class CheckerCPU : public BaseCPU bool checkFlags(Request *req); ThreadContext *tcBase() { return tc; } - CPUExecContext *cpuXCBase() { return cpuXC; } + SimpleThread *threadBase() { return thread; } Result unverifiedResult; Request *unverifiedReq; diff --git a/src/cpu/checker/thread_context.hh b/src/cpu/checker/thread_context.hh index 48890584d..d3eb9cf0c 100644 --- a/src/cpu/checker/thread_context.hh +++ b/src/cpu/checker/thread_context.hh @@ -26,11 +26,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __CPU_CHECKER_EXEC_CONTEXT_HH__ -#define __CPU_CHECKER_EXEC_CONTEXT_HH__ +#ifndef __CPU_CHECKER_THREAD_CONTEXT_HH__ +#define __CPU_CHECKER_THREAD_CONTEXT_HH__ #include "cpu/checker/cpu.hh" -#include "cpu/cpu_exec_context.hh" +#include "cpu/simple_thread.hh" #include "cpu/thread_context.hh" class EndQuiesceEvent; @@ -41,23 +41,30 @@ namespace Kernel { /** * Derived ThreadContext class for use with the Checker. The template * parameter is the ThreadContext class used by the specific CPU being - * verified. This CheckerThreadContext is then used by the main CPU in - * place of its usual ThreadContext class. It handles updating the - * checker's state any time state is updated through the ThreadContext. + * verified. This CheckerThreadContext is then used by the main CPU + * in place of its usual ThreadContext class. It handles updating the + * checker's state any time state is updated externally through the + * ThreadContext. */ template class CheckerThreadContext : public ThreadContext { public: CheckerThreadContext(TC *actual_tc, - CheckerCPU *checker_cpu) - : actualTC(actual_tc), checkerTC(checker_cpu->cpuXC), + CheckerCPU *checker_cpu) + : actualTC(actual_tc), checkerTC(checker_cpu->thread), checkerCPU(checker_cpu) { } private: + /** The main CPU's ThreadContext, or class that implements the + * ThreadContext interface. */ TC *actualTC; - CPUExecContext *checkerTC; + /** The checker's own SimpleThread. Will be updated any time + * anything uses this ThreadContext to externally update a + * thread's state. */ + SimpleThread *checkerTC; + /** Pointer to the checker CPU. */ CheckerCPU *checkerCPU; public: diff --git a/src/cpu/cpu_exec_context.cc b/src/cpu/cpu_exec_context.cc deleted file mode 100644 index 1e8071ca8..000000000 --- a/src/cpu/cpu_exec_context.cc +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Copyright (c) 2001-2006 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. - * - * Authors: Steve Reinhardt - * Nathan Binkert - * Lisa Hsu - * Kevin Lim - */ - -#include - -#include "arch/isa_traits.hh" -#include "cpu/base.hh" -#include "cpu/cpu_exec_context.hh" -#include "cpu/thread_context.hh" - -#if FULL_SYSTEM -#include "base/callback.hh" -#include "base/cprintf.hh" -#include "base/output.hh" -#include "base/trace.hh" -#include "cpu/profile.hh" -#include "cpu/quiesce_event.hh" -#include "kern/kernel_stats.hh" -#include "sim/serialize.hh" -#include "sim/sim_exit.hh" -#include "arch/stacktrace.hh" -#else -#include "sim/process.hh" -#include "sim/system.hh" -#include "mem/translating_port.hh" -#endif - -using namespace std; - -// constructor -#if FULL_SYSTEM -CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_sys, - AlphaITB *_itb, AlphaDTB *_dtb, - bool use_kernel_stats) - : _status(ThreadContext::Unallocated), cpu(_cpu), thread_num(_thread_num), - cpu_id(-1), lastActivate(0), lastSuspend(0), system(_sys), itb(_itb), - dtb(_dtb), profile(NULL), func_exe_inst(0), storeCondFailures(0) - -{ - tc = new ProxyThreadContext(this); - - quiesceEvent = new EndQuiesceEvent(tc); - - regs.clear(); - - if (cpu->params->profile) { - profile = new FunctionProfile(system->kernelSymtab); - Callback *cb = - new MakeCallback(this); - registerExitCallback(cb); - } - - // let's fill with a dummy node for now so we don't get a segfault - // on the first cycle when there's no node available. - static ProfileNode dummyNode; - profileNode = &dummyNode; - profilePC = 3; - - - if (use_kernel_stats) { - kernelStats = new Kernel::Statistics(system); - } else { - kernelStats = NULL; - } - Port *mem_port; - physPort = new FunctionalPort(csprintf("%s-%d-funcport", - cpu->name(), thread_num)); - mem_port = system->physmem->getPort("functional"); - mem_port->setPeer(physPort); - physPort->setPeer(mem_port); - - virtPort = new VirtualPort(csprintf("%s-%d-vport", - cpu->name(), thread_num)); - 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, MemObject* memobj) - : _status(ThreadContext::Unallocated), - cpu(_cpu), thread_num(_thread_num), cpu_id(-1), lastActivate(0), - lastSuspend(0), process(_process), asid(_asid), - func_exe_inst(0), storeCondFailures(0) -{ - /* Use this port to for syscall emulation writes to memory. */ - Port *mem_port; - port = new TranslatingPort(csprintf("%s-%d-funcport", - cpu->name(), thread_num), - process->pTable, false); - mem_port = memobj->getPort("functional"); - mem_port->setPeer(port); - port->setPeer(mem_port); - - regs.clear(); - tc = new ProxyThreadContext(this); -} - -CPUExecContext::CPUExecContext(RegFile *regFile) - : cpu(NULL), thread_num(-1), process(NULL), asid(-1), - func_exe_inst(0), storeCondFailures(0) -{ - regs = *regFile; - tc = new ProxyThreadContext(this); -} - -#endif - -CPUExecContext::~CPUExecContext() -{ - delete tc; -} - -#if FULL_SYSTEM -void -CPUExecContext::dumpFuncProfile() -{ - std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name())); - profile->dump(tc, *os); -} - -void -CPUExecContext::profileClear() -{ - if (profile) - profile->clear(); -} - -void -CPUExecContext::profileSample() -{ - if (profile) - profile->sample(profileNode, profilePC); -} - -#endif - -void -CPUExecContext::takeOverFrom(ThreadContext *oldContext) -{ - // some things should already be set up -#if FULL_SYSTEM - assert(system == oldContext->getSystemPtr()); -#else - assert(process == oldContext->getProcessPtr()); -#endif - - // copy over functional state - _status = oldContext->status(); - copyArchRegs(oldContext); - cpu_id = oldContext->readCpuId(); -#if !FULL_SYSTEM - func_exe_inst = oldContext->readFuncExeInst(); -#else - EndQuiesceEvent *quiesce = oldContext->getQuiesceEvent(); - if (quiesce) { - // Point the quiesce event's TC at this TC so that it wakes up - // the proper CPU. - quiesce->tc = tc; - } - if (quiesceEvent) { - quiesceEvent->tc = tc; - } -#endif - - storeCondFailures = 0; - - oldContext->setStatus(ThreadContext::Unallocated); -} - -void -CPUExecContext::serialize(ostream &os) -{ - SERIALIZE_ENUM(_status); - regs.serialize(os); - // thread_num and cpu_id are deterministic from the config - SERIALIZE_SCALAR(func_exe_inst); - SERIALIZE_SCALAR(inst); - -#if FULL_SYSTEM - Tick quiesceEndTick = 0; - if (quiesceEvent->scheduled()) - quiesceEndTick = quiesceEvent->when(); - SERIALIZE_SCALAR(quiesceEndTick); - if (kernelStats) - kernelStats->serialize(os); -#endif -} - - -void -CPUExecContext::unserialize(Checkpoint *cp, const std::string §ion) -{ - UNSERIALIZE_ENUM(_status); - regs.unserialize(cp, section); - // thread_num and cpu_id are deterministic from the config - UNSERIALIZE_SCALAR(func_exe_inst); - UNSERIALIZE_SCALAR(inst); - -#if FULL_SYSTEM - Tick quiesceEndTick; - UNSERIALIZE_SCALAR(quiesceEndTick); - if (quiesceEndTick) - quiesceEvent->schedule(quiesceEndTick); - if (kernelStats) - kernelStats->unserialize(cp, section); -#endif -} - - -void -CPUExecContext::activate(int delay) -{ - if (status() == ThreadContext::Active) - return; - - lastActivate = curTick; - - if (status() == ThreadContext::Unallocated) { - cpu->activateWhenReady(thread_num); - return; - } - - _status = ThreadContext::Active; - - // status() == Suspended - cpu->activateContext(thread_num, delay); -} - -void -CPUExecContext::suspend() -{ - if (status() == ThreadContext::Suspended) - return; - - lastActivate = curTick; - lastSuspend = curTick; -/* -#if FULL_SYSTEM - // Don't change the status from active if there are pending interrupts - if (cpu->check_interrupts()) { - assert(status() == ThreadContext::Active); - return; - } -#endif -*/ - _status = ThreadContext::Suspended; - cpu->suspendContext(thread_num); -} - -void -CPUExecContext::deallocate() -{ - if (status() == ThreadContext::Unallocated) - return; - - _status = ThreadContext::Unallocated; - cpu->deallocateContext(thread_num); -} - -void -CPUExecContext::halt() -{ - if (status() == ThreadContext::Halted) - return; - - _status = ThreadContext::Halted; - cpu->haltContext(thread_num); -} - - -void -CPUExecContext::regStats(const string &name) -{ -#if FULL_SYSTEM - if (kernelStats) - kernelStats->regStats(name + ".kern"); -#endif -} - -void -CPUExecContext::copyArchRegs(ThreadContext *src_tc) -{ - TheISA::copyRegs(src_tc, tc); -} - -#if FULL_SYSTEM -VirtualPort* -CPUExecContext::getVirtPort(ThreadContext *src_tc) -{ - if (!src_tc) - return virtPort; - - VirtualPort *vp; - Port *mem_port; - - vp = new VirtualPort("tc-vport", src_tc); - mem_port = system->physmem->getPort("functional"); - mem_port->setPeer(vp); - vp->setPeer(mem_port); - return vp; -} - -void -CPUExecContext::delVirtPort(VirtualPort *vp) -{ -// assert(!vp->nullThreadContext()); - delete vp->getPeer(); - delete vp; -} - - -#endif - diff --git a/src/cpu/cpu_exec_context.hh b/src/cpu/cpu_exec_context.hh deleted file mode 100644 index 01b5cbb15..000000000 --- a/src/cpu/cpu_exec_context.hh +++ /dev/null @@ -1,543 +0,0 @@ -/* - * Copyright (c) 2001-2006 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. - * - * Authors: Steve Reinhardt - * Nathan Binkert - */ - -#ifndef __CPU_CPU_EXEC_CONTEXT_HH__ -#define __CPU_CPU_EXEC_CONTEXT_HH__ - -#include "arch/isa_traits.hh" -#include "config/full_system.hh" -#include "cpu/thread_context.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" - -class BaseCPU; - -#if FULL_SYSTEM - -#include "sim/system.hh" -#include "arch/tlb.hh" - -class FunctionProfile; -class ProfileNode; -class FunctionalPort; -class PhysicalPort; - - -namespace Kernel { - class Statistics; -}; - -#else // !FULL_SYSTEM - -#include "sim/process.hh" -#include "mem/page_table.hh" -class TranslatingPort; - - -#endif // FULL_SYSTEM - -// -// The CPUExecContext object represents a functional context for -// instruction execution. It incorporates everything required for -// architecture-level functional simulation of a single thread. -// - -class CPUExecContext -{ - protected: - typedef TheISA::RegFile RegFile; - typedef TheISA::MachInst MachInst; - typedef TheISA::MiscRegFile MiscRegFile; - typedef TheISA::MiscReg MiscReg; - typedef TheISA::FloatReg FloatReg; - typedef TheISA::FloatRegBits FloatRegBits; - public: - typedef ThreadContext::Status Status; - - private: - Status _status; - - public: - Status status() const { return _status; } - - void setStatus(Status newStatus) { _status = newStatus; } - - /// Set the status to Active. Optional delay indicates number of - /// cycles to wait before beginning execution. - void activate(int delay = 1); - - /// Set the status to Suspended. - void suspend(); - - /// Set the status to Unallocated. - void deallocate(); - - /// Set the status to Halted. - void halt(); - - protected: - RegFile regs; // correct-path register context - - public: - // pointer to CPU associated with this context - BaseCPU *cpu; - - ProxyThreadContext *tc; - - // Current instruction - MachInst inst; - - // Index of hardware thread context on the CPU that this represents. - int thread_num; - - // ID of this context w.r.t. the System or Process object to which - // it belongs. For full-system mode, this is the system CPU ID. - int cpu_id; - - Tick lastActivate; - Tick lastSuspend; - - System *system; - - -#if FULL_SYSTEM - AlphaITB *itb; - AlphaDTB *dtb; - - /** 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; - Addr profilePC; - void dumpFuncProfile(); - - EndQuiesceEvent *quiesceEvent; - - EndQuiesceEvent *getQuiesceEvent() { return quiesceEvent; } - - Tick readLastActivate() { return lastActivate; } - - Tick readLastSuspend() { return lastSuspend; } - - void profileClear(); - - void profileSample(); - - Kernel::Statistics *getKernelStats() { return kernelStats; } - - Kernel::Statistics *kernelStats; -#else - /// Port that syscalls can use to access memory (provides translation step). - TranslatingPort *port; - - Process *process; - - // Address space ID. Note that this is used for TIMING cache - // simulation only; all functional memory accesses should use - // one of the FunctionalMemory pointers above. - short asid; - -#endif - - /** - * Temporary storage to pass the source address from copy_load to - * copy_store. - * @todo Remove this temporary when we have a better way to do it. - */ - Addr copySrcAddr; - /** - * Temp storage for the physical source address of a copy. - * @todo Remove this temporary when we have a better way to do it. - */ - Addr copySrcPhysAddr; - - - /* - * number of executed instructions, for matching with syscall trace - * points in EIO files. - */ - Counter func_exe_inst; - - // - // Count failed store conditionals so we can warn of apparent - // application deadlock situations. - unsigned storeCondFailures; - - // constructor: initialize context from given process structure -#if FULL_SYSTEM - CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_system, - AlphaITB *_itb, AlphaDTB *_dtb, - bool use_kernel_stats = true); -#else - 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); -#endif - virtual ~CPUExecContext(); - - virtual void takeOverFrom(ThreadContext *oldContext); - - void regStats(const std::string &name); - - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); - - BaseCPU *getCpuPtr() { return cpu; } - - ThreadContext *getTC() { return tc; } - - int getThreadNum() { return thread_num; } - -#if FULL_SYSTEM - System *getSystemPtr() { return system; } - - AlphaITB *getITBPtr() { return itb; } - - AlphaDTB *getDTBPtr() { return dtb; } - - int getInstAsid() { return regs.instAsid(); } - int getDataAsid() { return regs.dataAsid(); } - - Fault translateInstReq(RequestPtr &req) - { - return itb->translate(req, tc); - } - - Fault translateDataReadReq(RequestPtr &req) - { - return dtb->translate(req, tc, false); - } - - Fault translateDataWriteReq(RequestPtr &req) - { - return dtb->translate(req, tc, true); - } - - FunctionalPort *getPhysPort() { return physPort; } - - /** Return a virtual port. If no thread context is specified then a static - * port is returned. Otherwise a port is created and returned. It must be - * deleted by deleteVirtPort(). */ - VirtualPort *getVirtPort(ThreadContext *tc); - - void delVirtPort(VirtualPort *vp); - -#else - TranslatingPort *getMemPort() { return port; } - - Process *getProcessPtr() { return process; } - - int getInstAsid() { return asid; } - int getDataAsid() { return asid; } - - Fault translateInstReq(RequestPtr &req) - { - return process->pTable->translate(req); - } - - Fault translateDataReadReq(RequestPtr &req) - { - return process->pTable->translate(req); - } - - Fault translateDataWriteReq(RequestPtr &req) - { - return process->pTable->translate(req); - } - -#endif - -/* - template - Fault read(RequestPtr &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 = mem->prot_read(req->paddr, data, req->size); - data = LittleEndianGuest::gtoh(data); - return error; - } - - template - Fault write(RequestPtr &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 < system->execContexts.size(); i++){ - xc = system->execContexts[i]; - if ((xc->readMiscReg(TheISA::Lock_Addr_DepTag) & ~0xf) == - (req->paddr & ~0xf)) { - xc->setMiscReg(TheISA::Lock_Flag_DepTag, false); - } - } - -#endif - return mem->prot_write(req->paddr, (T)htog(data), req->size); - } -*/ - virtual bool misspeculating(); - - - MachInst getInst() { return inst; } - - void setInst(MachInst new_inst) - { - inst = new_inst; - } - - Fault instRead(RequestPtr &req) - { - panic("instRead not implemented"); - // return funcPhysMem->read(req, inst); - return NoFault; - } - - void setCpuId(int id) { cpu_id = id; } - - int readCpuId() { return cpu_id; } - - void copyArchRegs(ThreadContext *tc); - - // - // New accessors for new decoder. - // - uint64_t readIntReg(int reg_idx) - { - return regs.readIntReg(reg_idx); - } - - FloatReg readFloatReg(int reg_idx, int width) - { - return regs.readFloatReg(reg_idx, width); - } - - FloatReg readFloatReg(int reg_idx) - { - return regs.readFloatReg(reg_idx); - } - - FloatRegBits readFloatRegBits(int reg_idx, int width) - { - 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.setIntReg(reg_idx, val); - } - - void setFloatReg(int reg_idx, FloatReg val, int width) - { - regs.setFloatReg(reg_idx, val, width); - } - - void setFloatReg(int reg_idx, FloatReg val) - { - regs.setFloatReg(reg_idx, val); - } - - void setFloatRegBits(int reg_idx, FloatRegBits val, int width) - { - regs.setFloatRegBits(reg_idx, val, width); - } - - void setFloatRegBits(int reg_idx, FloatRegBits val) - { - regs.setFloatRegBits(reg_idx, val); - } - - uint64_t readPC() - { - return regs.readPC(); - } - - void setPC(uint64_t val) - { - regs.setPC(val); - } - - uint64_t readNextPC() - { - return regs.readNextPC(); - } - - void setNextPC(uint64_t val) - { - regs.setNextPC(val); - } - - uint64_t readNextNPC() - { - return regs.readNextNPC(); - } - - void setNextNPC(uint64_t val) - { - regs.setNextNPC(val); - } - - - MiscReg readMiscReg(int misc_reg) - { - return regs.readMiscReg(misc_reg); - } - - MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) - { - return regs.readMiscRegWithEffect(misc_reg, fault, tc); - } - - Fault setMiscReg(int misc_reg, const MiscReg &val) - { - return regs.setMiscReg(misc_reg, val); - } - - Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val) - { - return regs.setMiscRegWithEffect(misc_reg, val, tc); - } - - unsigned readStCondFailures() { return storeCondFailures; } - - void setStCondFailures(unsigned sc_failures) - { storeCondFailures = sc_failures; } - - 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.readPC()); } - bool simPalCheck(int palFunc); -#endif - -#if !FULL_SYSTEM - TheISA::IntReg getSyscallArg(int i) - { - return regs.readIntReg(TheISA::ArgumentReg0 + i); - } - - // used to shift args for indirect syscall - void setSyscallArg(int i, TheISA::IntReg val) - { - regs.setIntReg(TheISA::ArgumentReg0 + i, val); - } - - void setSyscallReturn(SyscallReturn return_value) - { - TheISA::setSyscallReturn(return_value, ®s); - } - - void syscall(int64_t callnum) - { - process->syscall(callnum, tc); - } - - 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); - } -}; - - -// for non-speculative execution context, spec_mode is always false -inline bool -CPUExecContext::misspeculating() -{ - return false; -} - -#endif // __CPU_CPU_EXEC_CONTEXT_HH__ diff --git a/src/cpu/memtest/memtest.cc b/src/cpu/memtest/memtest.cc index 62e539250..7ea9eaefc 100644 --- a/src/cpu/memtest/memtest.cc +++ b/src/cpu/memtest/memtest.cc @@ -38,7 +38,7 @@ #include "base/misc.hh" #include "base/statistics.hh" -#include "cpu/cpu_exec_context.hh" +#include "cpu/simple_thread.hh" #include "cpu/memtest/memtest.hh" #include "mem/cache/base_cache.hh" #include "sim/builder.hh" @@ -81,7 +81,7 @@ MemTest::MemTest(const string &name, vector cmd; cmd.push_back("/bin/ls"); vector null_vec; - cpuXC = new CPUExecContext(NULL, 0, mainMem, 0); + thread = new SimpleThread(NULL, 0, mainMem, 0); blockSize = cacheInterface->getBlockSize(); blockAddrMask = blockSize - 1; @@ -271,7 +271,7 @@ MemTest::tick() req->data = new uint8_t[req->size]; req->paddr &= ~(req->size - 1); req->time = curTick; - req->xc = cpuXC->getProxy(); + req->xc = thread->getProxy(); if (cmd < percentReads) { // read diff --git a/src/cpu/memtest/memtest.hh b/src/cpu/memtest/memtest.hh index 9976000e9..42fb235db 100644 --- a/src/cpu/memtest/memtest.hh +++ b/src/cpu/memtest/memtest.hh @@ -86,7 +86,7 @@ class MemTest : public SimObject MemInterface *cacheInterface; FunctionalMemory *mainMem; FunctionalMemory *checkMem; - CPUExecContext *cpuXC; + SimpleThread *thread; unsigned size; // size of testing memory region diff --git a/src/cpu/o3/alpha_cpu.hh b/src/cpu/o3/alpha_cpu.hh index 588b11724..3449454bd 100644 --- a/src/cpu/o3/alpha_cpu.hh +++ b/src/cpu/o3/alpha_cpu.hh @@ -96,7 +96,7 @@ class AlphaFullCPU : public FullO3CPU /** Reads this CPU's ID. */ virtual int readCpuId() { return cpu->cpu_id; } - virtual TranslatingPort *getMemPort() { return thread->port; } + virtual TranslatingPort *getMemPort() { return thread->getMemPort(); } #if FULL_SYSTEM /** Returns a pointer to the system. */ @@ -116,7 +116,7 @@ class AlphaFullCPU : public FullO3CPU { return thread->kernelStats; } #else /** Returns a pointer to this thread's process. */ - virtual Process *getProcessPtr() { return thread->process; } + virtual Process *getProcessPtr() { return thread->getProcessPtr(); } #endif /** Returns this thread's status. */ virtual Status status() const { return thread->status(); } @@ -170,7 +170,7 @@ class AlphaFullCPU : public FullO3CPU virtual void profileSample(); #endif /** Returns this thread's ID number. */ - virtual int getThreadNum() { return thread->tid; } + virtual int getThreadNum() { return thread->readTid(); } /** Returns the instruction this thread is currently committing. * Only used when an instruction faults. @@ -207,14 +207,14 @@ class AlphaFullCPU : public FullO3CPU /** Reads this thread's PC. */ virtual uint64_t readPC() - { return cpu->readPC(thread->tid); } + { return cpu->readPC(thread->readTid()); } /** Sets this thread's PC. */ virtual void setPC(uint64_t val); /** Reads this thread's next PC. */ virtual uint64_t readNextPC() - { return cpu->readNextPC(thread->tid); } + { return cpu->readNextPC(thread->readTid()); } /** Sets this thread's next PC. */ virtual void setNextPC(uint64_t val); @@ -230,12 +230,12 @@ class AlphaFullCPU : public FullO3CPU /** Reads a miscellaneous register. */ virtual MiscReg readMiscReg(int misc_reg) - { return cpu->readMiscReg(misc_reg, thread->tid); } + { return cpu->readMiscReg(misc_reg, thread->readTid()); } /** Reads a misc. register, including any side-effects the * read might have as defined by the architecture. */ virtual MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) - { return cpu->readMiscRegWithEffect(misc_reg, fault, thread->tid); } + { return cpu->readMiscRegWithEffect(misc_reg, fault, thread->readTid()); } /** Sets a misc. register. */ virtual Fault setMiscReg(int misc_reg, const MiscReg &val); @@ -257,7 +257,7 @@ class AlphaFullCPU : public FullO3CPU /** Returns if the thread is currently in PAL mode, based on * the PC's value. */ virtual bool inPalMode() - { return TheISA::PcPAL(cpu->readPC(thread->tid)); } + { return TheISA::PcPAL(cpu->readPC(thread->readTid())); } #endif // Only really makes sense for old CPU model. Lots of code // outside the CPU still checks this function, so it will @@ -279,7 +279,7 @@ class AlphaFullCPU : public FullO3CPU /** Executes a syscall in SE mode. */ virtual void syscall(int64_t callnum) - { return cpu->syscall(callnum, thread->tid); } + { return cpu->syscall(callnum, thread->readTid()); } /** Reads the funcExeInst counter. */ virtual Counter readFuncExeInst() { return thread->funcExeInst; } @@ -323,21 +323,21 @@ class AlphaFullCPU : public FullO3CPU Fault translateInstReq(RequestPtr &req) { int tid = req->getThreadNum(); - return this->thread[tid]->process->pTable->translate(req); + return this->thread[tid]->getProcessPtr()->pTable->translate(req); } /** Translates data read request in syscall emulation mode. */ Fault translateDataReadReq(RequestPtr &req) { int tid = req->getThreadNum(); - return this->thread[tid]->process->pTable->translate(req); + return this->thread[tid]->getProcessPtr()->pTable->translate(req); } /** Translates data write request in syscall emulation mode. */ Fault translateDataWriteReq(RequestPtr &req) { int tid = req->getThreadNum(); - return this->thread[tid]->process->pTable->translate(req); + return this->thread[tid]->getProcessPtr()->pTable->translate(req); } #endif @@ -492,14 +492,14 @@ class AlphaFullCPU : public FullO3CPU #if FULL_SYSTEM // @todo: Fix this LL/SC hack. - if (req->flags & LOCKED) { - if (req->flags & UNCACHEABLE) { - req->result = 2; + if (req->getFlags() & LOCKED) { + if (req->getFlags() & UNCACHEABLE) { + req->setScResult(2); } else { if (this->lockFlag) { - req->result = 1; + req->setScResult(1); } else { - req->result = 0; + req->setScResult(0); return NoFault; } } diff --git a/src/cpu/o3/alpha_cpu_impl.hh b/src/cpu/o3/alpha_cpu_impl.hh index 7f3d91640..2debe074b 100644 --- a/src/cpu/o3/alpha_cpu_impl.hh +++ b/src/cpu/o3/alpha_cpu_impl.hh @@ -32,7 +32,7 @@ #include "base/cprintf.hh" #include "base/statistics.hh" #include "base/timebuf.hh" -#include "cpu/checker/exec_context.hh" +#include "cpu/checker/thread_context.hh" #include "sim/sim_events.hh" #include "sim/stats.hh" @@ -77,6 +77,20 @@ AlphaFullCPU::AlphaFullCPU(Params *params) i, params->mem); this->thread[i]->setStatus(ThreadContext::Suspended); + +#if !FULL_SYSTEM + /* Use this port to for syscall emulation writes to memory. */ + Port *mem_port; + TranslatingPort *trans_port; + trans_port = new TranslatingPort(csprintf("%s-%d-funcport", + name(), i), + params->workload[i]->pTable, + false); + mem_port = params->mem->getPort("functional"); + mem_port->setPeer(trans_port); + trans_port->setPeer(mem_port); + this->thread[i]->setMemPort(trans_port); +#endif //usedTids[i] = true; //threadMap[i] = i; } else { @@ -108,10 +122,25 @@ AlphaFullCPU::AlphaFullCPU(Params *params) #if FULL_SYSTEM // Setup quiesce event. - this->thread[i]->quiesceEvent = - new EndQuiesceEvent(tc); - this->thread[i]->lastActivate = 0; - this->thread[i]->lastSuspend = 0; + this->thread[i]->quiesceEvent = new EndQuiesceEvent(tc); + + Port *mem_port; + FunctionalPort *phys_port; + VirtualPort *virt_port; + phys_port = new FunctionalPort(csprintf("%s-%d-funcport", + cpu->name(), tid)); + mem_port = system->physmem->getPort("functional"); + mem_port->setPeer(phys_port); + phys_port->setPeer(mem_port); + + virt_port = new VirtualPort(csprintf("%s-%d-vport", + cpu->name(), tid)); + mem_port = system->physmem->getPort("functional"); + mem_port->setPeer(virt_port); + virt_port->setPeer(mem_port); + + this->thread[i]->setPhysPort(phys_port); + this->thread[i]->setVirtPort(virt_port); #endif // Give the thread the TC. this->thread[i]->tc = tc; @@ -120,9 +149,8 @@ AlphaFullCPU::AlphaFullCPU(Params *params) this->threadContexts.push_back(tc); } - for (int i=0; i < this->numThreads; i++) { - this->thread[i]->funcExeInst = 0; + this->thread[i]->setFuncExeInst(0); } // Sets CPU pointers. These must be set at this level because the CPU @@ -218,14 +246,14 @@ AlphaFullCPU::AlphaTC::activate(int delay) #endif if (thread->status() == ThreadContext::Unallocated) { - cpu->activateWhenReady(thread->tid); + cpu->activateWhenReady(thread->readTid()); return; } thread->setStatus(ThreadContext::Active); // status() == Suspended - cpu->activateContext(thread->tid, delay); + cpu->activateContext(thread->readTid(), delay); } template @@ -251,7 +279,7 @@ AlphaFullCPU::AlphaTC::suspend() #endif */ thread->setStatus(ThreadContext::Suspended); - cpu->suspendContext(thread->tid); + cpu->suspendContext(thread->readTid()); } template @@ -264,7 +292,7 @@ AlphaFullCPU::AlphaTC::deallocate() return; thread->setStatus(ThreadContext::Unallocated); - cpu->deallocateContext(thread->tid); + cpu->deallocateContext(thread->readTid()); } template @@ -277,7 +305,7 @@ AlphaFullCPU::AlphaTC::halt() return; thread->setStatus(ThreadContext::Halted); - cpu->haltContext(thread->tid); + cpu->haltContext(thread->readTid()); } template @@ -349,7 +377,7 @@ template TheISA::MachInst AlphaFullCPU::AlphaTC:: getInst() { - return thread->inst; + return thread->getInst(); } template @@ -358,7 +386,7 @@ AlphaFullCPU::AlphaTC::copyArchRegs(ThreadContext *tc) { // This function will mess things up unless the ROB is empty and // there are no instructions in the pipeline. - unsigned tid = thread->tid; + unsigned tid = thread->readTid(); PhysRegIndex renamed_reg; // First loop through the integer registers. @@ -400,7 +428,7 @@ template uint64_t AlphaFullCPU::AlphaTC::readIntReg(int reg_idx) { - return cpu->readArchIntReg(reg_idx, thread->tid); + return cpu->readArchIntReg(reg_idx, thread->readTid()); } template @@ -409,9 +437,9 @@ AlphaFullCPU::AlphaTC::readFloatReg(int reg_idx, int width) { switch(width) { case 32: - return cpu->readArchFloatRegSingle(reg_idx, thread->tid); + return cpu->readArchFloatRegSingle(reg_idx, thread->readTid()); case 64: - return cpu->readArchFloatRegDouble(reg_idx, thread->tid); + return cpu->readArchFloatRegDouble(reg_idx, thread->readTid()); default: panic("Unsupported width!"); return 0; @@ -422,7 +450,7 @@ template FloatReg AlphaFullCPU::AlphaTC::readFloatReg(int reg_idx) { - return cpu->readArchFloatRegSingle(reg_idx, thread->tid); + return cpu->readArchFloatRegSingle(reg_idx, thread->readTid()); } template @@ -430,25 +458,25 @@ FloatRegBits AlphaFullCPU::AlphaTC::readFloatRegBits(int reg_idx, int width) { DPRINTF(Fault, "Reading floatint register through the TC!\n"); - return cpu->readArchFloatRegInt(reg_idx, thread->tid); + return cpu->readArchFloatRegInt(reg_idx, thread->readTid()); } template FloatRegBits AlphaFullCPU::AlphaTC::readFloatRegBits(int reg_idx) { - return cpu->readArchFloatRegInt(reg_idx, thread->tid); + return cpu->readArchFloatRegInt(reg_idx, thread->readTid()); } template void AlphaFullCPU::AlphaTC::setIntReg(int reg_idx, uint64_t val) { - cpu->setArchIntReg(reg_idx, val, thread->tid); + cpu->setArchIntReg(reg_idx, val, thread->readTid()); // Squash if we're not already in a state update mode. if (!thread->trapPending && !thread->inSyscall) { - cpu->squashFromTC(thread->tid); + cpu->squashFromTC(thread->readTid()); } } @@ -458,16 +486,16 @@ AlphaFullCPU::AlphaTC::setFloatReg(int reg_idx, FloatReg val, int width) { switch(width) { case 32: - cpu->setArchFloatRegSingle(reg_idx, val, thread->tid); + cpu->setArchFloatRegSingle(reg_idx, val, thread->readTid()); break; case 64: - cpu->setArchFloatRegDouble(reg_idx, val, thread->tid); + cpu->setArchFloatRegDouble(reg_idx, val, thread->readTid()); break; } // Squash if we're not already in a state update mode. if (!thread->trapPending && !thread->inSyscall) { - cpu->squashFromTC(thread->tid); + cpu->squashFromTC(thread->readTid()); } } @@ -475,10 +503,10 @@ template void AlphaFullCPU::AlphaTC::setFloatReg(int reg_idx, FloatReg val) { - cpu->setArchFloatRegSingle(reg_idx, val, thread->tid); + cpu->setArchFloatRegSingle(reg_idx, val, thread->readTid()); if (!thread->trapPending && !thread->inSyscall) { - cpu->squashFromTC(thread->tid); + cpu->squashFromTC(thread->readTid()); } } @@ -488,11 +516,11 @@ AlphaFullCPU::AlphaTC::setFloatRegBits(int reg_idx, FloatRegBits val, int width) { DPRINTF(Fault, "Setting floatint register through the TC!\n"); - cpu->setArchFloatRegInt(reg_idx, val, thread->tid); + cpu->setArchFloatRegInt(reg_idx, val, thread->readTid()); // Squash if we're not already in a state update mode. if (!thread->trapPending && !thread->inSyscall) { - cpu->squashFromTC(thread->tid); + cpu->squashFromTC(thread->readTid()); } } @@ -500,11 +528,11 @@ template void AlphaFullCPU::AlphaTC::setFloatRegBits(int reg_idx, FloatRegBits val) { - cpu->setArchFloatRegInt(reg_idx, val, thread->tid); + cpu->setArchFloatRegInt(reg_idx, val, thread->readTid()); // Squash if we're not already in a state update mode. if (!thread->trapPending && !thread->inSyscall) { - cpu->squashFromTC(thread->tid); + cpu->squashFromTC(thread->readTid()); } } @@ -512,11 +540,11 @@ template void AlphaFullCPU::AlphaTC::setPC(uint64_t val) { - cpu->setPC(val, thread->tid); + cpu->setPC(val, thread->readTid()); // Squash if we're not already in a state update mode. if (!thread->trapPending && !thread->inSyscall) { - cpu->squashFromTC(thread->tid); + cpu->squashFromTC(thread->readTid()); } } @@ -524,11 +552,11 @@ template void AlphaFullCPU::AlphaTC::setNextPC(uint64_t val) { - cpu->setNextPC(val, thread->tid); + cpu->setNextPC(val, thread->readTid()); // Squash if we're not already in a state update mode. if (!thread->trapPending && !thread->inSyscall) { - cpu->squashFromTC(thread->tid); + cpu->squashFromTC(thread->readTid()); } } @@ -536,11 +564,11 @@ template Fault AlphaFullCPU::AlphaTC::setMiscReg(int misc_reg, const MiscReg &val) { - Fault ret_fault = cpu->setMiscReg(misc_reg, val, thread->tid); + Fault ret_fault = cpu->setMiscReg(misc_reg, val, thread->readTid()); // Squash if we're not already in a state update mode. if (!thread->trapPending && !thread->inSyscall) { - cpu->squashFromTC(thread->tid); + cpu->squashFromTC(thread->readTid()); } return ret_fault; @@ -551,11 +579,12 @@ Fault AlphaFullCPU::AlphaTC::setMiscRegWithEffect(int misc_reg, const MiscReg &val) { - Fault ret_fault = cpu->setMiscRegWithEffect(misc_reg, val, thread->tid); + Fault ret_fault = cpu->setMiscRegWithEffect(misc_reg, val, + thread->readTid()); // Squash if we're not already in a state update mode. if (!thread->trapPending && !thread->inSyscall) { - cpu->squashFromTC(thread->tid); + cpu->squashFromTC(thread->readTid()); } return ret_fault; @@ -567,21 +596,21 @@ template TheISA::IntReg AlphaFullCPU::AlphaTC::getSyscallArg(int i) { - return cpu->getSyscallArg(i, thread->tid); + return cpu->getSyscallArg(i, thread->readTid()); } template void AlphaFullCPU::AlphaTC::setSyscallArg(int i, IntReg val) { - cpu->setSyscallArg(i, val, thread->tid); + cpu->setSyscallArg(i, val, thread->readTid()); } template void AlphaFullCPU::AlphaTC::setSyscallReturn(SyscallReturn return_value) { - cpu->setSyscallReturn(return_value, thread->tid); + cpu->setSyscallReturn(return_value, thread->readTid()); } #endif // FULL_SYSTEM @@ -749,8 +778,8 @@ AlphaFullCPU::processInterrupts() this->setMiscReg(IPR_INTID, ipl, 0); // Checker needs to know these two registers were updated. if (this->checker) { - this->checker->cpuXCBase()->setMiscReg(IPR_ISR, summary); - this->checker->cpuXCBase()->setMiscReg(IPR_INTID, ipl); + this->checker->threadBase()->setMiscReg(IPR_ISR, summary); + this->checker->threadBase()->setMiscReg(IPR_INTID, ipl); } this->trap(Fault(new InterruptFault), 0); DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index f523766cc..c5f78d63d 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -38,7 +38,7 @@ #include "cpu/activity.hh" #include "cpu/checker/cpu.hh" -#include "cpu/cpu_exec_context.hh" +#include "cpu/simple_thread.hh" #include "cpu/thread_context.hh" #include "cpu/o3/alpha_dyn_inst.hh" #include "cpu/o3/alpha_impl.hh" @@ -245,12 +245,6 @@ FullO3CPU::FullO3CPU(Params *params) } rename.setFreeList(&freeList); - // Setup the page table for whichever stages need it. -#if !FULL_SYSTEM -// fetch.setPageTable(pTable); -// iew.setPageTable(pTable); -#endif - // Setup the ROB for whichever stages need it. commit.setROB(&rob); @@ -427,12 +421,12 @@ FullO3CPU::insertThread(unsigned tid) { DPRINTF(FullCPU,"[tid:%i] Initializing thread data"); // Will change now that the PC and thread state is internal to the CPU - // and not in the CPUExecContext. + // and not in the ThreadContext. #if 0 #if FULL_SYSTEM ThreadContext *src_tc = system->threadContexts[tid]; #else - CPUExecContext *src_tc = thread[tid]; + ThreadContext *src_tc = thread[tid]; #endif //Bind Int Regs to Rename Map diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 69f52f147..8e482f1e5 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -43,7 +43,7 @@ #include "config/full_system.hh" #include "cpu/activity.hh" #include "cpu/base.hh" -#include "cpu/cpu_exec_context.hh" +#include "cpu/simple_thread.hh" #include "cpu/o3/comm.hh" #include "cpu/o3/cpu_policy.hh" #include "cpu/o3/scoreboard.hh" @@ -237,11 +237,11 @@ class FullO3CPU : public BaseFullCPU #else /** Get instruction asid. */ int getInstAsid(unsigned tid) - { return thread[tid]->asid; } + { return thread[tid]->getInstAsid(); } /** Get data asid. */ int getDataAsid(unsigned tid) - { return thread[tid]->asid; } + { return thread[tid]->getDataAsid(); } #endif diff --git a/src/cpu/o3/thread_state.hh b/src/cpu/o3/thread_state.hh index 7322161e6..38d37ec96 100644 --- a/src/cpu/o3/thread_state.hh +++ b/src/cpu/o3/thread_state.hh @@ -58,14 +58,6 @@ struct O3ThreadState : public ThreadState { typedef ThreadContext::Status Status; typedef typename Impl::FullCPU FullCPU; - /** Current status of the thread. */ - Status _status; - - /** Current instruction the thread is committing. Only set and - * used for DTB faults currently. - */ - TheISA::MachInst inst; - private: /** Pointer to the CPU. */ FullCPU *cpu; @@ -81,8 +73,8 @@ struct O3ThreadState : public ThreadState { bool trapPending; #if FULL_SYSTEM - O3ThreadState(FullCPU *_cpu, int _thread_num, FunctionalMemory *_mem) - : ThreadState(-1, _thread_num, _mem), + O3ThreadState(FullCPU *_cpu, int _thread_num, ) + : ThreadState(-1, _thread_num), inSyscall(0), trapPending(0) { } #else @@ -99,25 +91,6 @@ struct O3ThreadState : public ThreadState { /** Returns a pointer to the TC of this thread. */ ThreadContext *getTC() { return tc; } - /** Returns the status of this thread. */ - Status status() const { return _status; } - - /** Sets the status of this thread. */ - void setStatus(Status new_status) { _status = new_status; } - - /** Sets the current instruction being committed. */ - void setInst(TheISA::MachInst _inst) { inst = _inst; } - - /** Reads the number of instructions functionally executed and - * committed. - */ - Counter readFuncExeInst() { return funcExeInst; } - - /** Sets the total number of instructions functionally executed - * and committed. - */ - void setFuncExeInst(Counter new_val) { funcExeInst = new_val; } - #if !FULL_SYSTEM /** Handles the syscall. */ void syscall(int64_t callnum) { process->syscall(callnum, tc); } diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index 0763a30b3..76e2318aa 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -36,7 +36,7 @@ #include "base/trace.hh" #include "config/full_system.hh" #include "cpu/base.hh" -#include "cpu/checker/exec_context.hh" +#include "cpu/checker/thread_context.hh" #include "cpu/thread_context.hh" #include "cpu/exetrace.hh" #include "cpu/ozone/cpu.hh" @@ -670,8 +670,8 @@ OzoneCPU::processInterrupts() thread.setMiscReg(IPR_INTID, ipl); // @todo: Make this more transparent if (checker) { - checker->cpuXCBase()->setMiscReg(IPR_ISR, summary); - checker->cpuXCBase()->setMiscReg(IPR_INTID, ipl); + checker->threadBase()->setMiscReg(IPR_ISR, summary); + checker->threadBase()->setMiscReg(IPR_INTID, ipl); } Fault fault = new InterruptFault; fault->invoke(thread.getTC()); diff --git a/src/cpu/ozone/thread_state.hh b/src/cpu/ozone/thread_state.hh index c91297e73..e6256e4e3 100644 --- a/src/cpu/ozone/thread_state.hh +++ b/src/cpu/ozone/thread_state.hh @@ -49,7 +49,7 @@ class FunctionalMemory; // Maybe this ozone thread state should only really have committed state? // I need to think about why I'm using this and what it's useful for. Clearly -// has benefits for SMT; basically serves same use as CPUExecContext. +// has benefits for SMT; basically serves same use as SimpleThread. // Makes the ExecContext proxy easier. Gives organization/central access point // to state of a thread that can be accessed normally (i.e. not in-flight // stuff within a OoO processor). Does this need an TC proxy within it? @@ -83,18 +83,11 @@ struct OzoneThreadState : public ThreadState { } #endif - Status _status; - - Status status() const { return _status; } - - void setStatus(Status new_status) { _status = new_status; } - RenameTable renameTable; + Addr PC; - Addr nextPC; - // Current instruction - TheISA::MachInst inst; + Addr nextPC; TheISA::RegFile regs; @@ -169,14 +162,6 @@ struct OzoneThreadState : public ThreadState { void setNextPC(uint64_t val) { nextPC = val; } - - bool misspeculating() { return false; } - - void setInst(TheISA::MachInst _inst) { inst = _inst; } - - Counter readFuncExeInst() { return funcExeInst; } - - void setFuncExeInst(Counter new_val) { funcExeInst = new_val; } }; #endif // __CPU_OZONE_THREAD_STATE_HH__ diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 91ac0b6a5..071193f02 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -196,7 +196,7 @@ void AtomicSimpleCPU::activateContext(int thread_num, int delay) { assert(thread_num == 0); - assert(cpuXC); + assert(thread); assert(_status == Idle); assert(!tickEvent.scheduled()); @@ -211,7 +211,7 @@ void AtomicSimpleCPU::suspendContext(int thread_num) { assert(thread_num == 0); - assert(cpuXC); + assert(thread); assert(_status == Running); @@ -229,14 +229,14 @@ template Fault AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags) { - data_read_req->setVirt(0, addr, sizeof(T), flags, cpuXC->readPC()); + data_read_req->setVirt(0, addr, sizeof(T), flags, thread->readPC()); if (traceData) { traceData->setAddr(addr); } // translate to physical address - Fault fault = cpuXC->translateDataReadReq(data_read_req); + Fault fault = thread->translateDataReadReq(data_read_req); // Now do the access. if (fault == NoFault) { @@ -304,14 +304,14 @@ template Fault AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) { - data_write_req->setVirt(0, addr, sizeof(T), flags, cpuXC->readPC()); + data_write_req->setVirt(0, addr, sizeof(T), flags, thread->readPC()); if (traceData) { traceData->setAddr(addr); } // translate to physical address - Fault fault = cpuXC->translateDataWriteReq(data_write_req); + Fault fault = thread->translateDataWriteReq(data_write_req); // Now do the access. if (fault == NoFault) { diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index d36aa93a2..c1ecf3967 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -38,18 +38,18 @@ #include "base/stats/events.hh" #include "base/trace.hh" #include "cpu/base.hh" -#include "cpu/cpu_exec_context.hh" -#include "cpu/thread_context.hh" #include "cpu/exetrace.hh" #include "cpu/profile.hh" #include "cpu/sampler/sampler.hh" #include "cpu/simple/base.hh" +#include "cpu/simple_thread.hh" #include "cpu/smt.hh" #include "cpu/static_inst.hh" +#include "cpu/thread_context.hh" #include "kern/kernel_stats.hh" #include "mem/packet_impl.hh" -#include "sim/byteswap.hh" #include "sim/builder.hh" +#include "sim/byteswap.hh" #include "sim/debug.hh" #include "sim/host.hh" #include "sim/sim_events.hh" @@ -70,18 +70,18 @@ using namespace std; using namespace TheISA; BaseSimpleCPU::BaseSimpleCPU(Params *p) - : BaseCPU(p), mem(p->mem), cpuXC(NULL) + : BaseCPU(p), mem(p->mem), thread(NULL) { #if FULL_SYSTEM - cpuXC = new CPUExecContext(this, 0, p->system, p->itb, p->dtb); + thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb); #else - cpuXC = new CPUExecContext(this, /* thread_num */ 0, p->process, + thread = new SimpleThread(this, /* thread_num */ 0, p->process, /* asid */ 0, mem); #endif // !FULL_SYSTEM - cpuXC->setStatus(ThreadContext::Suspended); + thread->setStatus(ThreadContext::Suspended); - tc = cpuXC->getTC(); + tc = thread->getTC(); numInst = 0; startNumInst = 0; @@ -180,7 +180,7 @@ BaseSimpleCPU::serialize(ostream &os) BaseCPU::serialize(os); SERIALIZE_SCALAR(inst); nameOut(os, csprintf("%s.xc", name())); - cpuXC->serialize(os); + thread->serialize(os); } void @@ -188,7 +188,7 @@ BaseSimpleCPU::unserialize(Checkpoint *cp, const string §ion) { BaseCPU::unserialize(cp, section); UNSERIALIZE_SCALAR(inst); - cpuXC->unserialize(cp, csprintf("%s.xc", section)); + thread->unserialize(cp, csprintf("%s.xc", section)); } void @@ -217,16 +217,16 @@ BaseSimpleCPU::copySrcTranslate(Addr src) memReq->reset(src & ~(blk_size - 1), blk_size); // translate to physical address - Fault fault = cpuXC->translateDataReadReq(req); + Fault fault = thread->translateDataReadReq(req); if (fault == NoFault) { - cpuXC->copySrcAddr = src; - cpuXC->copySrcPhysAddr = memReq->paddr + offset; + thread->copySrcAddr = src; + thread->copySrcPhysAddr = memReq->paddr + offset; } else { assert(!fault->isAlignmentFault()); - cpuXC->copySrcAddr = 0; - cpuXC->copySrcPhysAddr = 0; + thread->copySrcAddr = 0; + thread->copySrcPhysAddr = 0; } return fault; #else @@ -243,7 +243,7 @@ BaseSimpleCPU::copy(Addr dest) // Only support block sizes of 64 atm. assert(blk_size == 64); uint8_t data[blk_size]; - //assert(cpuXC->copySrcAddr); + //assert(thread->copySrcAddr); int offset = dest & (blk_size - 1); // Make sure block doesn't span page @@ -256,19 +256,19 @@ BaseSimpleCPU::copy(Addr dest) memReq->reset(dest & ~(blk_size -1), blk_size); // translate to physical address - Fault fault = cpuXC->translateDataWriteReq(req); + Fault fault = thread->translateDataWriteReq(req); if (fault == NoFault) { Addr dest_addr = memReq->paddr + offset; // Need to read straight from memory since we have more than 8 bytes. - memReq->paddr = cpuXC->copySrcPhysAddr; - cpuXC->mem->read(memReq, data); + memReq->paddr = thread->copySrcPhysAddr; + thread->mem->read(memReq, data); memReq->paddr = dest_addr; - cpuXC->mem->write(memReq, data); + thread->mem->write(memReq, data); if (dcacheInterface) { memReq->cmd = Copy; memReq->completionEvent = NULL; - memReq->paddr = cpuXC->copySrcPhysAddr; + memReq->paddr = thread->copySrcPhysAddr; memReq->dest = dest_addr; memReq->size = 64; memReq->time = curTick; @@ -300,9 +300,9 @@ BaseSimpleCPU::post_interrupt(int int_num, int index) { BaseCPU::post_interrupt(int_num, index); - if (cpuXC->status() == ThreadContext::Suspended) { + if (thread->status() == ThreadContext::Suspended) { DPRINTF(IPI,"Suspended Processor awoke\n"); - cpuXC->activate(); + thread->activate(); } } #endif // FULL_SYSTEM @@ -311,15 +311,15 @@ void BaseSimpleCPU::checkForInterrupts() { #if FULL_SYSTEM - if (checkInterrupts && check_interrupts() && !cpuXC->inPalMode()) { + if (checkInterrupts && check_interrupts() && !thread->inPalMode()) { int ipl = 0; int summary = 0; checkInterrupts = false; - if (cpuXC->readMiscReg(IPR_SIRR)) { + if (thread->readMiscReg(IPR_SIRR)) { for (int i = INTLEVEL_SOFTWARE_MIN; i < INTLEVEL_SOFTWARE_MAX; i++) { - if (cpuXC->readMiscReg(IPR_SIRR) & (ULL(1) << i)) { + if (thread->readMiscReg(IPR_SIRR) & (ULL(1) << i)) { // See table 4-19 of 21164 hardware reference ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1; summary |= (ULL(1) << i); @@ -327,7 +327,7 @@ BaseSimpleCPU::checkForInterrupts() } } - uint64_t interrupts = cpuXC->cpu->intr_status(); + uint64_t interrupts = thread->cpu->intr_status(); for (int i = INTLEVEL_EXTERNAL_MIN; i < INTLEVEL_EXTERNAL_MAX; i++) { if (interrupts & (ULL(1) << i)) { @@ -337,17 +337,17 @@ BaseSimpleCPU::checkForInterrupts() } } - if (cpuXC->readMiscReg(IPR_ASTRR)) + if (thread->readMiscReg(IPR_ASTRR)) panic("asynchronous traps not implemented\n"); - if (ipl && ipl > cpuXC->readMiscReg(IPR_IPLR)) { - cpuXC->setMiscReg(IPR_ISR, summary); - cpuXC->setMiscReg(IPR_INTID, ipl); + if (ipl && ipl > thread->readMiscReg(IPR_IPLR)) { + thread->setMiscReg(IPR_ISR, summary); + thread->setMiscReg(IPR_INTID, ipl); Fault(new InterruptFault)->invoke(tc); DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", - cpuXC->readMiscReg(IPR_IPLR), ipl, summary); + thread->readMiscReg(IPR_IPLR), ipl, summary); } } #endif @@ -358,14 +358,14 @@ Fault BaseSimpleCPU::setupFetchRequest(Request *req) { // set up memory request for instruction fetch - DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",cpuXC->readPC(), - cpuXC->readNextPC(),cpuXC->readNextNPC()); + DPRINTF(Fetch,"Fetch: PC:%08p NPC:%08p NNPC:%08p\n",thread->readPC(), + thread->readNextPC(),thread->readNextNPC()); - req->setVirt(0, cpuXC->readPC() & ~3, sizeof(MachInst), - (FULL_SYSTEM && (cpuXC->readPC() & 1)) ? PHYSICAL : 0, - cpuXC->readPC()); + req->setVirt(0, thread->readPC() & ~3, sizeof(MachInst), + (FULL_SYSTEM && (thread->readPC() & 1)) ? PHYSICAL : 0, + thread->readPC()); - Fault fault = cpuXC->translateInstReq(req); + Fault fault = thread->translateInstReq(req); return fault; } @@ -375,33 +375,33 @@ void BaseSimpleCPU::preExecute() { // maintain $r0 semantics - cpuXC->setIntReg(ZeroReg, 0); + thread->setIntReg(ZeroReg, 0); #if THE_ISA == ALPHA_ISA - cpuXC->setFloatReg(ZeroReg, 0.0); + thread->setFloatReg(ZeroReg, 0.0); #endif // ALPHA_ISA // keep an instruction count numInst++; numInsts++; - cpuXC->func_exe_inst++; + thread->funcExeInst++; // check for instruction-count-based events comInstEventQueue[0]->serviceEvents(numInst); // decode the instruction inst = gtoh(inst); - curStaticInst = StaticInst::decode(makeExtMI(inst, cpuXC->readPC())); + curStaticInst = StaticInst::decode(makeExtMI(inst, thread->readPC())); traceData = Trace::getInstRecord(curTick, tc, this, curStaticInst, - cpuXC->readPC()); + thread->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); + thread->setInst(inst); #endif // FULL_SYSTEM } @@ -410,17 +410,17 @@ BaseSimpleCPU::postExecute() { #if FULL_SYSTEM if (system->kernelBinning->fnbin) { - assert(cpuXC->getKernelStats()); + assert(thread->getKernelStats()); system->kernelBinning->execute(tc, inst); } - if (cpuXC->profile) { + if (thread->profile) { bool usermode = - (cpuXC->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0; - cpuXC->profilePC = usermode ? 1 : cpuXC->readPC(); - ProfileNode *node = cpuXC->profile->consume(tc, inst); + (thread->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0; + thread->profilePC = usermode ? 1 : thread->readPC(); + ProfileNode *node = thread->profile->consume(tc, inst); if (node) - cpuXC->profileNode = node; + thread->profileNode = node; } #endif @@ -433,7 +433,7 @@ BaseSimpleCPU::postExecute() comLoadEventQueue[0]->serviceEvents(numLoad); } - traceFunctions(cpuXC->readPC()); + traceFunctions(thread->readPC()); if (traceData) { traceData->finalize(); @@ -448,17 +448,17 @@ BaseSimpleCPU::advancePC(Fault fault) #if FULL_SYSTEM fault->invoke(tc); #else // !FULL_SYSTEM - fatal("fault (%s) detected @ PC %08p", fault->name(), cpuXC->readPC()); + fatal("fault (%s) detected @ PC %08p", fault->name(), thread->readPC()); #endif // FULL_SYSTEM } else { // go to the next instruction - cpuXC->setPC(cpuXC->readNextPC()); + thread->setPC(thread->readNextPC()); #if THE_ISA == ALPHA_ISA - cpuXC->setNextPC(cpuXC->readNextPC() + sizeof(MachInst)); + thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); #else - cpuXC->setNextPC(cpuXC->readNextNPC()); - cpuXC->setNextNPC(cpuXC->readNextNPC() + sizeof(MachInst)); + thread->setNextPC(thread->readNextNPC()); + thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); #endif } @@ -466,9 +466,9 @@ BaseSimpleCPU::advancePC(Fault fault) #if FULL_SYSTEM Addr oldpc; do { - oldpc = cpuXC->readPC(); + oldpc = thread->readPC(); system->pcEventQueue.service(tc); - } while (oldpc != cpuXC->readPC()); + } while (oldpc != thread->readPC()); #endif } diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index bc17ece56..39bc86050 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -36,7 +36,7 @@ #include "base/statistics.hh" #include "config/full_system.hh" #include "cpu/base.hh" -#include "cpu/cpu_exec_context.hh" +#include "cpu/simple_thread.hh" #include "cpu/pc_event.hh" #include "cpu/sampler/sampler.hh" #include "cpu/static_inst.hh" @@ -108,9 +108,12 @@ class BaseSimpleCPU : public BaseCPU virtual ~BaseSimpleCPU(); public: - // execution context - CPUExecContext *cpuXC; + /** SimpleThread object, provides all the architectural state. */ + SimpleThread *thread; + /** ThreadContext object, provides an interface for external + * objects to modify this thread's state. + */ ThreadContext *tc; #if FULL_SYSTEM @@ -217,103 +220,103 @@ class BaseSimpleCPU : public BaseCPU uint64_t readIntReg(const StaticInst *si, int idx) { - return cpuXC->readIntReg(si->srcRegIdx(idx)); + return thread->readIntReg(si->srcRegIdx(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); + return thread->readFloatReg(reg_idx, width); } FloatReg readFloatReg(const StaticInst *si, int idx) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; - return cpuXC->readFloatReg(reg_idx); + return thread->readFloatReg(reg_idx); } FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; - return cpuXC->readFloatRegBits(reg_idx, width); + return thread->readFloatRegBits(reg_idx, width); } FloatRegBits readFloatRegBits(const StaticInst *si, int idx) { int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; - return cpuXC->readFloatRegBits(reg_idx); + return thread->readFloatRegBits(reg_idx); } void setIntReg(const StaticInst *si, int idx, uint64_t val) { - cpuXC->setIntReg(si->destRegIdx(idx), val); + thread->setIntReg(si->destRegIdx(idx), val); } void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; - cpuXC->setFloatReg(reg_idx, val, width); + thread->setFloatReg(reg_idx, val, width); } void setFloatReg(const StaticInst *si, int idx, FloatReg val) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; - cpuXC->setFloatReg(reg_idx, val); + thread->setFloatReg(reg_idx, val); } void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val, int width) { int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; - cpuXC->setFloatRegBits(reg_idx, val, width); + thread->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); + thread->setFloatRegBits(reg_idx, val); } - uint64_t readPC() { return cpuXC->readPC(); } - uint64_t readNextPC() { return cpuXC->readNextPC(); } - uint64_t readNextNPC() { return cpuXC->readNextNPC(); } + uint64_t readPC() { return thread->readPC(); } + uint64_t readNextPC() { return thread->readNextPC(); } + uint64_t readNextNPC() { return thread->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); } + void setPC(uint64_t val) { thread->setPC(val); } + void setNextPC(uint64_t val) { thread->setNextPC(val); } + void setNextNPC(uint64_t val) { thread->setNextNPC(val); } MiscReg readMiscReg(int misc_reg) { - return cpuXC->readMiscReg(misc_reg); + return thread->readMiscReg(misc_reg); } MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) { - return cpuXC->readMiscRegWithEffect(misc_reg, fault); + return thread->readMiscRegWithEffect(misc_reg, fault); } Fault setMiscReg(int misc_reg, const MiscReg &val) { - return cpuXC->setMiscReg(misc_reg, val); + return thread->setMiscReg(misc_reg, val); } Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val) { - return cpuXC->setMiscRegWithEffect(misc_reg, val); + return thread->setMiscRegWithEffect(misc_reg, val); } #if FULL_SYSTEM - Fault hwrei() { return cpuXC->hwrei(); } - int readIntrFlag() { return cpuXC->readIntrFlag(); } - void setIntrFlag(int val) { cpuXC->setIntrFlag(val); } - bool inPalMode() { return cpuXC->inPalMode(); } + Fault hwrei() { return thread->hwrei(); } + int readIntrFlag() { return thread->readIntrFlag(); } + void setIntrFlag(int val) { thread->setIntrFlag(val); } + bool inPalMode() { return thread->inPalMode(); } void ev5_trap(Fault fault) { fault->invoke(tc); } - bool simPalCheck(int palFunc) { return cpuXC->simPalCheck(palFunc); } + bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); } #else - void syscall(int64_t callnum) { cpuXC->syscall(callnum); } + void syscall(int64_t callnum) { thread->syscall(callnum); } #endif - bool misspeculating() { return cpuXC->misspeculating(); } + bool misspeculating() { return thread->misspeculating(); } ThreadContext *tcBase() { return tc; } }; diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 00c6de037..c99db8fbf 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -141,7 +141,7 @@ void TimingSimpleCPU::activateContext(int thread_num, int delay) { assert(thread_num == 0); - assert(cpuXC); + assert(thread); assert(_status == Idle); @@ -158,7 +158,7 @@ void TimingSimpleCPU::suspendContext(int thread_num) { assert(thread_num == 0); - assert(cpuXC); + assert(thread); assert(_status == Running); @@ -177,14 +177,14 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags) // need to fill in CPU & thread IDs here Request *data_read_req = new Request(); - data_read_req->setVirt(0, addr, sizeof(T), flags, cpuXC->readPC()); + data_read_req->setVirt(0, addr, sizeof(T), flags, thread->readPC()); if (traceData) { traceData->setAddr(data_read_req->getVaddr()); } // translate to physical address - Fault fault = cpuXC->translateDataReadReq(data_read_req); + Fault fault = thread->translateDataReadReq(data_read_req); // Now do the access. if (fault == NoFault) { @@ -257,10 +257,10 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) { // need to fill in CPU & thread IDs here Request *data_write_req = new Request(); - data_write_req->setVirt(0, addr, sizeof(T), flags, cpuXC->readPC()); + data_write_req->setVirt(0, addr, sizeof(T), flags, thread->readPC()); // translate to physical address - Fault fault = cpuXC->translateDataWriteReq(data_write_req); + Fault fault = thread->translateDataWriteReq(data_write_req); // Now do the access. if (fault == NoFault) { Packet *data_write_pkt = diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc new file mode 100644 index 000000000..219167e4e --- /dev/null +++ b/src/cpu/simple_thread.cc @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2001-2006 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. + * + * Authors: Steve Reinhardt + * Nathan Binkert + * Lisa Hsu + * Kevin Lim + */ + +#include + +#include "arch/isa_traits.hh" +#include "cpu/base.hh" +#include "cpu/simple_thread.hh" +#include "cpu/thread_context.hh" + +#if FULL_SYSTEM +#include "base/callback.hh" +#include "base/cprintf.hh" +#include "base/output.hh" +#include "base/trace.hh" +#include "cpu/profile.hh" +#include "cpu/quiesce_event.hh" +#include "kern/kernel_stats.hh" +#include "sim/serialize.hh" +#include "sim/sim_exit.hh" +#include "arch/stacktrace.hh" +#else +#include "sim/process.hh" +#include "sim/system.hh" +#include "mem/translating_port.hh" +#endif + +using namespace std; + +// constructor +#if FULL_SYSTEM +SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys, + AlphaITB *_itb, AlphaDTB *_dtb, + bool use_kernel_stats) + : ThreadState(-1, _thread_num), cpu(_cpu), system(_sys), itb(_itb), + dtb(_dtb) + +{ + tc = new ProxyThreadContext(this); + + quiesceEvent = new EndQuiesceEvent(tc); + + regs.clear(); + + if (cpu->params->profile) { + profile = new FunctionProfile(system->kernelSymtab); + Callback *cb = + new MakeCallback(this); + registerExitCallback(cb); + } + + // let's fill with a dummy node for now so we don't get a segfault + // on the first cycle when there's no node available. + static ProfileNode dummyNode; + profileNode = &dummyNode; + profilePC = 3; + + if (use_kernel_stats) { + kernelStats = new Kernel::Statistics(system); + } else { + kernelStats = NULL; + } + Port *mem_port; + physPort = new FunctionalPort(csprintf("%s-%d-funcport", + cpu->name(), tid)); + mem_port = system->physmem->getPort("functional"); + mem_port->setPeer(physPort); + physPort->setPeer(mem_port); + + virtPort = new VirtualPort(csprintf("%s-%d-vport", + cpu->name(), tid)); + mem_port = system->physmem->getPort("functional"); + mem_port->setPeer(virtPort); + virtPort->setPeer(mem_port); +} +#else +SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, + Process *_process, int _asid, MemObject* memobj) + : ThreadState(-1, _thread_num, memobj, _process, _asid), + cpu(_cpu) +{ + /* Use this port to for syscall emulation writes to memory. */ + Port *mem_port; + port = new TranslatingPort(csprintf("%s-%d-funcport", + cpu->name(), tid), + process->pTable, false); + mem_port = memobj->getPort("functional"); + mem_port->setPeer(port); + port->setPeer(mem_port); + + regs.clear(); + tc = new ProxyThreadContext(this); +} + +SimpleThread::SimpleThread(RegFile *regFile) + : ThreadState(-1, -1, NULL, NULL, -1), cpu(NULL) +{ + regs = *regFile; + tc = new ProxyThreadContext(this); +} + +#endif + +SimpleThread::~SimpleThread() +{ + delete tc; +} + +void +SimpleThread::takeOverFrom(ThreadContext *oldContext) +{ + // some things should already be set up +#if FULL_SYSTEM + assert(system == oldContext->getSystemPtr()); +#else + assert(process == oldContext->getProcessPtr()); +#endif + + // copy over functional state + _status = oldContext->status(); + copyArchRegs(oldContext); + cpuId = oldContext->readCpuId(); +#if !FULL_SYSTEM + funcExeInst = oldContext->readFuncExeInst(); +#else + EndQuiesceEvent *quiesce = oldContext->getQuiesceEvent(); + if (quiesce) { + // Point the quiesce event's TC at this TC so that it wakes up + // the proper CPU. + quiesce->tc = tc; + } + if (quiesceEvent) { + quiesceEvent->tc = tc; + } +#endif + + storeCondFailures = 0; + + oldContext->setStatus(ThreadContext::Unallocated); +} + +void +SimpleThread::serialize(ostream &os) +{ + SERIALIZE_ENUM(_status); + regs.serialize(os); + // thread_num and cpu_id are deterministic from the config + SERIALIZE_SCALAR(funcExeInst); + SERIALIZE_SCALAR(inst); + +#if FULL_SYSTEM + Tick quiesceEndTick = 0; + if (quiesceEvent->scheduled()) + quiesceEndTick = quiesceEvent->when(); + SERIALIZE_SCALAR(quiesceEndTick); + if (kernelStats) + kernelStats->serialize(os); +#endif +} + + +void +SimpleThread::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_ENUM(_status); + regs.unserialize(cp, section); + // thread_num and cpu_id are deterministic from the config + UNSERIALIZE_SCALAR(funcExeInst); + UNSERIALIZE_SCALAR(inst); + +#if FULL_SYSTEM + Tick quiesceEndTick; + UNSERIALIZE_SCALAR(quiesceEndTick); + if (quiesceEndTick) + quiesceEvent->schedule(quiesceEndTick); + if (kernelStats) + kernelStats->unserialize(cp, section); +#endif +} + +#if FULL_SYSTEM +void +SimpleThread::dumpFuncProfile() +{ + std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name())); + profile->dump(tc, *os); +} +#endif + +void +SimpleThread::activate(int delay) +{ + if (status() == ThreadContext::Active) + return; + + lastActivate = curTick; + + if (status() == ThreadContext::Unallocated) { + cpu->activateWhenReady(tid); + return; + } + + _status = ThreadContext::Active; + + // status() == Suspended + cpu->activateContext(tid, delay); +} + +void +SimpleThread::suspend() +{ + if (status() == ThreadContext::Suspended) + return; + + lastActivate = curTick; + lastSuspend = curTick; +/* +#if FULL_SYSTEM + // Don't change the status from active if there are pending interrupts + if (cpu->check_interrupts()) { + assert(status() == ThreadContext::Active); + return; + } +#endif +*/ + _status = ThreadContext::Suspended; + cpu->suspendContext(tid); +} + +void +SimpleThread::deallocate() +{ + if (status() == ThreadContext::Unallocated) + return; + + _status = ThreadContext::Unallocated; + cpu->deallocateContext(tid); +} + +void +SimpleThread::halt() +{ + if (status() == ThreadContext::Halted) + return; + + _status = ThreadContext::Halted; + cpu->haltContext(tid); +} + + +void +SimpleThread::regStats(const string &name) +{ +#if FULL_SYSTEM + if (kernelStats) + kernelStats->regStats(name + ".kern"); +#endif +} + +void +SimpleThread::copyArchRegs(ThreadContext *src_tc) +{ + TheISA::copyRegs(src_tc, tc); +} + +#if FULL_SYSTEM +VirtualPort* +SimpleThread::getVirtPort(ThreadContext *src_tc) +{ + if (!src_tc) + return virtPort; + + VirtualPort *vp; + Port *mem_port; + + vp = new VirtualPort("tc-vport", src_tc); + mem_port = system->physmem->getPort("functional"); + mem_port->setPeer(vp); + vp->setPeer(mem_port); + return vp; +} + +void +SimpleThread::delVirtPort(VirtualPort *vp) +{ +// assert(!vp->nullThreadContext()); + delete vp->getPeer(); + delete vp; +} + + +#endif + diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh new file mode 100644 index 000000000..de65e9891 --- /dev/null +++ b/src/cpu/simple_thread.hh @@ -0,0 +1,463 @@ +/* + * Copyright (c) 2001-2006 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. + * + * Authors: Steve Reinhardt + * Nathan Binkert + */ + +#ifndef __CPU_SIMPLE_THREAD_HH__ +#define __CPU_SIMPLE_THREAD_HH__ + +#include "arch/isa_traits.hh" +#include "config/full_system.hh" +#include "cpu/thread_context.hh" +#include "cpu/thread_state.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" + +class BaseCPU; + +#if FULL_SYSTEM + +#include "sim/system.hh" +#include "arch/tlb.hh" + +class FunctionProfile; +class ProfileNode; +class FunctionalPort; +class PhysicalPort; + +namespace Kernel { + class Statistics; +}; + +#else // !FULL_SYSTEM + +#include "sim/process.hh" +#include "mem/page_table.hh" +class TranslatingPort; + +#endif // FULL_SYSTEM + +/** + * The SimpleThread object provides a combination of the ThreadState + * object and the ThreadContext interface. It implements the + * ThreadContext interface so that a ProxyThreadContext class can be + * made using SimpleThread as the template parameter (see + * thread_context.hh). It adds to the ThreadState object by adding all + * the objects needed for simple functional execution, including a + * simple architectural register file, and pointers to the ITB and DTB + * in full system mode. For CPU models that do not need more advanced + * ways to hold state (i.e. a separate physical register file, or + * separate fetch and commit PC's), this SimpleThread class provides + * all the necessary state for full architecture-level functional + * simulation. See the AtomicSimpleCPU or TimingSimpleCPU for + * examples. + */ + +class SimpleThread : public ThreadState +{ + protected: + typedef TheISA::RegFile RegFile; + typedef TheISA::MachInst MachInst; + typedef TheISA::MiscRegFile MiscRegFile; + typedef TheISA::MiscReg MiscReg; + typedef TheISA::FloatReg FloatReg; + typedef TheISA::FloatRegBits FloatRegBits; + public: + typedef ThreadContext::Status Status; + + protected: + RegFile regs; // correct-path register context + + public: + // pointer to CPU associated with this SimpleThread + BaseCPU *cpu; + + ProxyThreadContext *tc; + + System *system; + +#if FULL_SYSTEM + AlphaITB *itb; + AlphaDTB *dtb; +#endif + + // constructor: initialize SimpleThread from given process structure +#if FULL_SYSTEM + SimpleThread(BaseCPU *_cpu, int _thread_num, System *_system, + AlphaITB *_itb, AlphaDTB *_dtb, + bool use_kernel_stats = true); +#else + SimpleThread(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid, + MemObject *memobj); + // Constructor to use SimpleThread to pass reg file around. Not + // used for anything else. + SimpleThread(RegFile *regFile); +#endif + virtual ~SimpleThread(); + + virtual void takeOverFrom(ThreadContext *oldContext); + + void regStats(const std::string &name); + + void serialize(std::ostream &os); + void unserialize(Checkpoint *cp, const std::string §ion); + + /*************************************************************** + * SimpleThread functions to provide CPU with access to various + * state, and to provide address translation methods. + **************************************************************/ + + /** Returns the pointer to this SimpleThread's ThreadContext. Used + * when a ThreadContext must be passed to objects outside of the + * CPU. + */ + ThreadContext *getTC() { return tc; } + +#if FULL_SYSTEM + int getInstAsid() { return regs.instAsid(); } + int getDataAsid() { return regs.dataAsid(); } + + Fault translateInstReq(RequestPtr &req) + { + return itb->translate(req, tc); + } + + Fault translateDataReadReq(RequestPtr &req) + { + return dtb->translate(req, tc, false); + } + + Fault translateDataWriteReq(RequestPtr &req) + { + return dtb->translate(req, tc, true); + } + + void dumpFuncProfile(); + + int readIntrFlag() { return regs.intrflag; } + void setIntrFlag(int val) { regs.intrflag = val; } + Fault hwrei(); + + bool simPalCheck(int palFunc); +#else + Fault translateInstReq(RequestPtr &req) + { + return process->pTable->translate(req); + } + + Fault translateDataReadReq(RequestPtr &req) + { + return process->pTable->translate(req); + } + + Fault translateDataWriteReq(RequestPtr &req) + { + return process->pTable->translate(req); + } +#endif + + /******************************************* + * ThreadContext interface functions. + ******************************************/ + + BaseCPU *getCpuPtr() { return cpu; } + + int getThreadNum() { return tid; } + +#if FULL_SYSTEM + System *getSystemPtr() { return system; } + + AlphaITB *getITBPtr() { return itb; } + + AlphaDTB *getDTBPtr() { return dtb; } + + FunctionalPort *getPhysPort() { return physPort; } + + /** Return a virtual port. If no thread context is specified then a static + * port is returned. Otherwise a port is created and returned. It must be + * deleted by deleteVirtPort(). */ + VirtualPort *getVirtPort(ThreadContext *tc); + + void delVirtPort(VirtualPort *vp); +#endif + + Status status() const { return _status; } + + void setStatus(Status newStatus) { _status = newStatus; } + + /// Set the status to Active. Optional delay indicates number of + /// cycles to wait before beginning execution. + void activate(int delay = 1); + + /// Set the status to Suspended. + void suspend(); + + /// Set the status to Unallocated. + void deallocate(); + + /// Set the status to Halted. + void halt(); + +/* + template + Fault read(RequestPtr &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 = mem->prot_read(req->paddr, data, req->size); + data = LittleEndianGuest::gtoh(data); + return error; + } + + template + Fault write(RequestPtr &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 < system->execContexts.size(); i++){ + xc = system->execContexts[i]; + if ((xc->readMiscReg(TheISA::Lock_Addr_DepTag) & ~0xf) == + (req->paddr & ~0xf)) { + xc->setMiscReg(TheISA::Lock_Flag_DepTag, false); + } + } + +#endif + return mem->prot_write(req->paddr, (T)htog(data), req->size); + } +*/ + virtual bool misspeculating(); + + Fault instRead(RequestPtr &req) + { + panic("instRead not implemented"); + // return funcPhysMem->read(req, inst); + return NoFault; + } + + void copyArchRegs(ThreadContext *tc); + + void clearArchRegs() { regs.clear(); } + + // + // New accessors for new decoder. + // + uint64_t readIntReg(int reg_idx) + { + return regs.readIntReg(reg_idx); + } + + FloatReg readFloatReg(int reg_idx, int width) + { + return regs.readFloatReg(reg_idx, width); + } + + FloatReg readFloatReg(int reg_idx) + { + return regs.readFloatReg(reg_idx); + } + + FloatRegBits readFloatRegBits(int reg_idx, int width) + { + 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.setIntReg(reg_idx, val); + } + + void setFloatReg(int reg_idx, FloatReg val, int width) + { + regs.setFloatReg(reg_idx, val, width); + } + + void setFloatReg(int reg_idx, FloatReg val) + { + regs.setFloatReg(reg_idx, val); + } + + void setFloatRegBits(int reg_idx, FloatRegBits val, int width) + { + regs.setFloatRegBits(reg_idx, val, width); + } + + void setFloatRegBits(int reg_idx, FloatRegBits val) + { + regs.setFloatRegBits(reg_idx, val); + } + + uint64_t readPC() + { + return regs.readPC(); + } + + void setPC(uint64_t val) + { + regs.setPC(val); + } + + uint64_t readNextPC() + { + return regs.readNextPC(); + } + + void setNextPC(uint64_t val) + { + regs.setNextPC(val); + } + + uint64_t readNextNPC() + { + return regs.readNextNPC(); + } + + void setNextNPC(uint64_t val) + { + regs.setNextNPC(val); + } + + MiscReg readMiscReg(int misc_reg) + { + return regs.readMiscReg(misc_reg); + } + + MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) + { + return regs.readMiscRegWithEffect(misc_reg, fault, tc); + } + + Fault setMiscReg(int misc_reg, const MiscReg &val) + { + return regs.setMiscReg(misc_reg, val); + } + + Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val) + { + return regs.setMiscRegWithEffect(misc_reg, val, tc); + } + + unsigned readStCondFailures() { return storeCondFailures; } + + void setStCondFailures(unsigned sc_failures) + { storeCondFailures = sc_failures; } + +#if FULL_SYSTEM + bool inPalMode() { return AlphaISA::PcPAL(regs.readPC()); } +#endif + +#if !FULL_SYSTEM + TheISA::IntReg getSyscallArg(int i) + { + return regs.readIntReg(TheISA::ArgumentReg0 + i); + } + + // used to shift args for indirect syscall + void setSyscallArg(int i, TheISA::IntReg val) + { + regs.setIntReg(TheISA::ArgumentReg0 + i, val); + } + + void setSyscallReturn(SyscallReturn return_value) + { + TheISA::setSyscallReturn(return_value, ®s); + } + + void syscall(int64_t callnum) + { + process->syscall(callnum, tc); + } +#endif + + void changeRegFileContext(RegFile::ContextParam param, + RegFile::ContextVal val) + { + regs.changeContext(param, val); + } +}; + + +// for non-speculative execution context, spec_mode is always false +inline bool +SimpleThread::misspeculating() +{ + return false; +} + +#endif // __CPU_CPU_EXEC_CONTEXT_HH__ diff --git a/src/cpu/thread_state.cc b/src/cpu/thread_state.cc new file mode 100644 index 000000000..9712ffa23 --- /dev/null +++ b/src/cpu/thread_state.cc @@ -0,0 +1,46 @@ +#include "base/output.hh" +#include "cpu/profile.hh" +#include "cpu/thread_state.hh" + +#if FULL_SYSTEM +ThreadState::ThreadState(int _cpuId, int _tid) + : cpuId(_cpuId), tid(_tid), lastActivate(0), lastSuspend(0), + profile(NULL), profileNode(NULL), profilePC(0), quiesceEvent(NULL), + funcExeInst(0), storeCondFailures(0) +#else +ThreadState::ThreadState(int _cpuId, int _tid, MemObject *mem, + Process *_process, short _asid) + : cpuId(_cpuId), tid(_tid), lastActivate(0), lastSuspend(0), + process(_process), asid(_asid), + funcExeInst(0), storeCondFailures(0) +#endif +{ +#if !FULL_SYSTEM + /* Use this port to for syscall emulation writes to memory. */ + Port *mem_port; + port = new TranslatingPort(csprintf("%d-funcport", + tid), + process->pTable, false); + mem_port = mem->getPort("functional"); + mem_port->setPeer(port); + port->setPeer(mem_port); +#endif +} + +#if FULL_SYSTEM + +void +ThreadState::profileClear() +{ + if (profile) + profile->clear(); +} + +void +ThreadState::profileSample() +{ + if (profile) + profile->sample(profileNode, profilePC); +} + +#endif diff --git a/src/cpu/thread_state.hh b/src/cpu/thread_state.hh index 6d64c94f7..d72697cb7 100644 --- a/src/cpu/thread_state.hh +++ b/src/cpu/thread_state.hh @@ -29,10 +29,13 @@ #ifndef __CPU_THREAD_STATE_HH__ #define __CPU_THREAD_STATE_HH__ +#include "arch/isa_traits.hh" #include "cpu/thread_context.hh" #if !FULL_SYSTEM +#include "mem/mem_object.hh" #include "mem/translating_port.hh" +#include "sim/process.hh" #endif #if FULL_SYSTEM @@ -42,9 +45,6 @@ class ProfileNode; namespace Kernel { class Statistics; }; -#else -class FunctionalMemory; -class Process; #endif /** @@ -54,56 +54,121 @@ class Process; * to hold more thread-specific stats within it. */ struct ThreadState { + typedef ThreadContext::Status Status; + #if FULL_SYSTEM - ThreadState(int _cpuId, int _tid) - : cpuId(_cpuId), tid(_tid), lastActivate(0), lastSuspend(0), - profile(NULL), profileNode(NULL), profilePC(0), quiesceEvent(NULL) + ThreadState(int _cpuId, int _tid); #else ThreadState(int _cpuId, int _tid, MemObject *mem, - Process *_process, short _asid) - : cpuId(_cpuId), tid(_tid), process(_process), asid(_asid) + Process *_process, short _asid); #endif - { - funcExeInst = 0; - storeCondFailures = 0; -#if !FULL_SYSTEM - /* Use this port to for syscall emulation writes to memory. */ - Port *mem_port; - port = new TranslatingPort(csprintf("%d-funcport", - tid), - process->pTable, false); - mem_port = mem->getPort("functional"); - mem_port->setPeer(port); - port->setPeer(mem_port); + + void setCpuId(int id) { cpuId = id; } + + int readCpuId() { return cpuId; } + + void setTid(int id) { tid = id; } + + int readTid() { return tid; } + + Tick readLastActivate() { return lastActivate; } + + Tick readLastSuspend() { return lastSuspend; } + +#if FULL_SYSTEM + void dumpFuncProfile(); + + EndQuiesceEvent *getQuiesceEvent() { return quiesceEvent; } + + void profileClear(); + + void profileSample(); + + Kernel::Statistics *getKernelStats() { return kernelStats; } + + void setPhysPort(FunctionalPort *port) { physPort = port; } + + void setVirtPort(VirtualPort *port) { virtPort = port; } +#else + Process *getProcessPtr() { return process; } + + TranslatingPort *getMemPort() { return port; } + + void setMemPort(TranslatingPort *_port) { port = _port; } + + int getInstAsid() { return asid; } + int getDataAsid() { return asid; } #endif - } - ThreadContext::Status status; + /** Sets the current instruction being committed. */ + void setInst(TheISA::MachInst _inst) { inst = _inst; } - int cpuId; + /** Returns the current instruction being committed. */ + TheISA::MachInst getInst() { return inst; } - // Index of hardware thread context on the CPU that this represents. - int tid; + /** Reads the number of instructions functionally executed and + * committed. + */ + Counter readFuncExeInst() { return funcExeInst; } + + /** Sets the total number of instructions functionally executed + * and committed. + */ + void setFuncExeInst(Counter new_val) { funcExeInst = new_val; } + + /** Returns the status of this thread. */ + Status status() const { return _status; } + /** Sets the status of this thread. */ + void setStatus(Status new_status) { _status = new_status; } + + /** Number of instructions committed. */ Counter numInst; + /** Stat for number instructions committed. */ Stats::Scalar<> numInsts; + /** Stat for number of memory references. */ Stats::Scalar<> numMemRefs; - // number of simulated loads + /** Number of simulated loads, used for tracking events based on + * the number of loads committed. + */ Counter numLoad; + + /** The number of simulated loads committed prior to this run. */ Counter startNumLoad; -#if FULL_SYSTEM + protected: + ThreadContext::Status _status; + + // ID of this context w.r.t. the System or Process object to which + // it belongs. For full-system mode, this is the system CPU ID. + int cpuId; + + // Index of hardware thread context on the CPU that this represents. + int tid; + + /** Last time activate was called on this thread. */ Tick lastActivate; + + /** Last time suspend was called on this thread. */ Tick lastSuspend; +#if FULL_SYSTEM + public: FunctionProfile *profile; ProfileNode *profileNode; Addr profilePC; - EndQuiesceEvent *quiesceEvent; Kernel::Statistics *kernelStats; + protected: + /** 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; #else TranslatingPort *port; @@ -113,9 +178,13 @@ struct ThreadState { // simulation only; all functional memory accesses should use // one of the FunctionalMemory pointers above. short asid; - #endif + /** Current instruction the thread is committing. Only set and + * used for DTB faults currently. + */ + TheISA::MachInst inst; + /** * Temporary storage to pass the source address from copy_load to * copy_store. @@ -128,6 +197,7 @@ struct ThreadState { */ Addr copySrcPhysAddr; + public: /* * number of executed instructions, for matching with syscall trace * points in EIO files. diff --git a/src/kern/system_events.cc b/src/kern/system_events.cc index aca75e27d..fe3805ce2 100644 --- a/src/kern/system_events.cc +++ b/src/kern/system_events.cc @@ -30,7 +30,7 @@ */ #include "cpu/base.hh" -#include "cpu/cpu_exec_context.hh" +#include "cpu/thread_context.hh" #include "kern/kernel_stats.hh" #include "kern/system_events.hh" #include "sim/system.hh" diff --git a/src/sim/process.hh b/src/sim/process.hh index 15d564455..edbc1e492 100644 --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -46,7 +46,6 @@ #include "base/statistics.hh" #include "sim/sim_object.hh" -class CPUExecContext; class ThreadContext; class SyscallDesc; class PageTable; -- cgit v1.2.3