cpu/activity.cc
cpu/base.cc
- cpu/cpu_exec_context.cc
cpu/cpuevent.cc
cpu/exetrace.cc
cpu/op_class.cc
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
#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"
// 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;
* 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);
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) {
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) {
#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"
}
CheckerCPU::CheckerCPU(Params *p)
- : BaseCPU(p), cpuXC(NULL), tc(NULL)
+ : BaseCPU(p), thread(NULL), tc(NULL)
{
memReq = NULL;
{
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
}
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
BaseCPU::serialize(os);
SERIALIZE_SCALAR(inst);
nameOut(os, csprintf("%s.xc", name()));
- cpuXC->serialize(os);
+ thread->serialize(os);
cacheCompletionEvent.serialize(os);
*/
}
/*
BaseCPU::unserialize(cp, section);
UNSERIALIZE_SCALAR(inst);
- cpuXC->unserialize(cp, csprintf("%s.xc", section));
+ thread->unserialize(cp, csprintf("%s.xc", section));
*/
}
// 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);
// 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
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
}
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, "
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, "
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
// 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;
}
if (changedNextPC) {
DPRINTF(Checker, "Changed NextPC recently to %#x\n",
- cpuXC->readNextPC());
+ thread->readNextPC());
changedNextPC = false;
}
#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);
// 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 {
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();
// that the instruction is properly marked as a fault.
if (fault == NoFault) {
- cpuXC->func_exe_inst++;
+ thread->funcExeInst++;
fault = curStaticInst->execute(this, NULL);
#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
}
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
void
Checker<DynInstPtr>::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);
// 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 "
}
}
- 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();
}
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();
}
}
#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"
* 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.
Port *dcachePort;
public:
- // execution context
- CPUExecContext *cpuXC;
+ // Primary thread being run.
+ SimpleThread *thread;
ThreadContext *tc;
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;
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;
}
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; }
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.
bool checkFlags(Request *req);
ThreadContext *tcBase() { return tc; }
- CPUExecContext *cpuXCBase() { return cpuXC; }
+ SimpleThread *threadBase() { return thread; }
Result unverifiedResult;
Request *unverifiedReq;
* 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;
/**
* 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 TC>
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:
+++ /dev/null
-/*
- * 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 <string>
-
-#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<CPUExecContext>(this);
-
- quiesceEvent = new EndQuiesceEvent(tc);
-
- regs.clear();
-
- if (cpu->params->profile) {
- profile = new FunctionProfile(system->kernelSymtab);
- Callback *cb =
- new MakeCallback<CPUExecContext,
- &CPUExecContext::dumpFuncProfile>(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<CPUExecContext>(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<CPUExecContext>(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
-
+++ /dev/null
-/*
- * 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<CPUExecContext> *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 <class T>
- 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 <class T>
- 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__
#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"
vector<string> cmd;
cmd.push_back("/bin/ls");
vector<string> null_vec;
- cpuXC = new CPUExecContext(NULL, 0, mainMem, 0);
+ thread = new SimpleThread(NULL, 0, mainMem, 0);
blockSize = cacheInterface->getBlockSize();
blockAddrMask = blockSize - 1;
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
MemInterface *cacheInterface;
FunctionalMemory *mainMem;
FunctionalMemory *checkMem;
- CPUExecContext *cpuXC;
+ SimpleThread *thread;
unsigned size; // size of testing memory region
/** 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. */
{ 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(); }
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.
/** 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);
/** 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);
/** 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
/** 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; }
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
#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;
}
}
#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"
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 {
#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;
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
#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 <class Impl>
#endif
*/
thread->setStatus(ThreadContext::Suspended);
- cpu->suspendContext(thread->tid);
+ cpu->suspendContext(thread->readTid());
}
template <class Impl>
return;
thread->setStatus(ThreadContext::Unallocated);
- cpu->deallocateContext(thread->tid);
+ cpu->deallocateContext(thread->readTid());
}
template <class Impl>
return;
thread->setStatus(ThreadContext::Halted);
- cpu->haltContext(thread->tid);
+ cpu->haltContext(thread->readTid());
}
template <class Impl>
TheISA::MachInst
AlphaFullCPU<Impl>::AlphaTC:: getInst()
{
- return thread->inst;
+ return thread->getInst();
}
template <class Impl>
{
// 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.
uint64_t
AlphaFullCPU<Impl>::AlphaTC::readIntReg(int reg_idx)
{
- return cpu->readArchIntReg(reg_idx, thread->tid);
+ return cpu->readArchIntReg(reg_idx, thread->readTid());
}
template <class Impl>
{
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;
FloatReg
AlphaFullCPU<Impl>::AlphaTC::readFloatReg(int reg_idx)
{
- return cpu->readArchFloatRegSingle(reg_idx, thread->tid);
+ return cpu->readArchFloatRegSingle(reg_idx, thread->readTid());
}
template <class Impl>
AlphaFullCPU<Impl>::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 <class Impl>
FloatRegBits
AlphaFullCPU<Impl>::AlphaTC::readFloatRegBits(int reg_idx)
{
- return cpu->readArchFloatRegInt(reg_idx, thread->tid);
+ return cpu->readArchFloatRegInt(reg_idx, thread->readTid());
}
template <class Impl>
void
AlphaFullCPU<Impl>::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());
}
}
{
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());
}
}
void
AlphaFullCPU<Impl>::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());
}
}
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());
}
}
void
AlphaFullCPU<Impl>::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());
}
}
void
AlphaFullCPU<Impl>::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());
}
}
void
AlphaFullCPU<Impl>::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());
}
}
Fault
AlphaFullCPU<Impl>::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;
AlphaFullCPU<Impl>::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;
TheISA::IntReg
AlphaFullCPU<Impl>::AlphaTC::getSyscallArg(int i)
{
- return cpu->getSyscallArg(i, thread->tid);
+ return cpu->getSyscallArg(i, thread->readTid());
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::setSyscallArg(int i, IntReg val)
{
- cpu->setSyscallArg(i, val, thread->tid);
+ cpu->setSyscallArg(i, val, thread->readTid());
}
template <class Impl>
void
AlphaFullCPU<Impl>::AlphaTC::setSyscallReturn(SyscallReturn return_value)
{
- cpu->setSyscallReturn(return_value, thread->tid);
+ cpu->setSyscallReturn(return_value, thread->readTid());
}
#endif // FULL_SYSTEM
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",
#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"
}
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);
{
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
#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"
#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
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;
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
/** 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); }
#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"
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());
// 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?
}
#endif
- Status _status;
-
- Status status() const { return _status; }
-
- void setStatus(Status new_status) { _status = new_status; }
-
RenameTable<Impl> renameTable;
+
Addr PC;
- Addr nextPC;
- // Current instruction
- TheISA::MachInst inst;
+ Addr nextPC;
TheISA::RegFile regs;
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__
AtomicSimpleCPU::activateContext(int thread_num, int delay)
{
assert(thread_num == 0);
- assert(cpuXC);
+ assert(thread);
assert(_status == Idle);
assert(!tickEvent.scheduled());
AtomicSimpleCPU::suspendContext(int thread_num)
{
assert(thread_num == 0);
- assert(cpuXC);
+ assert(thread);
assert(_status == Running);
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) {
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) {
#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"
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;
BaseCPU::serialize(os);
SERIALIZE_SCALAR(inst);
nameOut(os, csprintf("%s.xc", name()));
- cpuXC->serialize(os);
+ thread->serialize(os);
}
void
{
BaseCPU::unserialize(cp, section);
UNSERIALIZE_SCALAR(inst);
- cpuXC->unserialize(cp, csprintf("%s.xc", section));
+ thread->unserialize(cp, csprintf("%s.xc", section));
}
void
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
// 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
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;
{
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
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);
}
}
- 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)) {
}
}
- 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
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;
}
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
}
{
#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
comLoadEventQueue[0]->serviceEvents(numLoad);
}
- traceFunctions(cpuXC->readPC());
+ traceFunctions(thread->readPC());
if (traceData) {
traceData->finalize();
#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
}
#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
}
#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"
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
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; }
};
TimingSimpleCPU::activateContext(int thread_num, int delay)
{
assert(thread_num == 0);
- assert(cpuXC);
+ assert(thread);
assert(_status == Idle);
TimingSimpleCPU::suspendContext(int thread_num)
{
assert(thread_num == 0);
- assert(cpuXC);
+ assert(thread);
assert(_status == Running);
// 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) {
{
// 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 =
--- /dev/null
+/*
+ * 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 <string>
+
+#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<SimpleThread>(this);
+
+ quiesceEvent = new EndQuiesceEvent(tc);
+
+ regs.clear();
+
+ if (cpu->params->profile) {
+ profile = new FunctionProfile(system->kernelSymtab);
+ Callback *cb =
+ new MakeCallback<SimpleThread,
+ &SimpleThread::dumpFuncProfile>(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<SimpleThread>(this);
+}
+
+SimpleThread::SimpleThread(RegFile *regFile)
+ : ThreadState(-1, -1, NULL, NULL, -1), cpu(NULL)
+{
+ regs = *regFile;
+ tc = new ProxyThreadContext<SimpleThread>(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
+
--- /dev/null
+/*
+ * 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<SimpleThread> *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 <class T>
+ 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 <class T>
+ 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__
--- /dev/null
+#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
#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
namespace Kernel {
class Statistics;
};
-#else
-class FunctionalMemory;
-class Process;
#endif
/**
* 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;
// 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.
*/
Addr copySrcPhysAddr;
+ public:
/*
* number of executed instructions, for matching with syscall trace
* points in EIO files.
*/
#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"
#include "base/statistics.hh"
#include "sim/sim_object.hh"
-class CPUExecContext;
class ThreadContext;
class SyscallDesc;
class PageTable;