/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __EXEC_CONTEXT_HH__
-#define __EXEC_CONTEXT_HH__
+#ifndef __CPU_EXEC_CONTEXT_HH__
+#define __CPU_EXEC_CONTEXT_HH__
-#include "sim/host.hh"
+#include "config/full_system.hh"
+#include "mem/functional/functional.hh"
#include "mem/mem_req.hh"
+#include "sim/host.hh"
+#include "sim/serialize.hh"
+#include "targetarch/byte_swap.hh"
// forward declaration: see functional_memory.hh
class FunctionalMemory;
class PhysicalMemory;
class BaseCPU;
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
+#include "sim/system.hh"
#include "targetarch/alpha_memory.hh"
-class MemoryController;
-#include "kern/tru64/kernel_stats.hh"
-#include "sim/system.hh"
+class MemoryController;
+class StaticInstBase;
+namespace Kernel { class Binning; class Statistics; }
#else // !FULL_SYSTEM
-#include "sim/prog.hh"
+#include "sim/process.hh"
#endif // FULL_SYSTEM
class ExecContext
{
public:
- enum Status { Unallocated, Active, Suspended, Halted };
+ enum Status
+ {
+ /// Initialized but not running yet. All CPUs start in
+ /// this state, but most transition to Active on cycle 1.
+ /// In MP or SMT systems, non-primary contexts will stay
+ /// in this state until a thread is assigned to them.
+ Unallocated,
+
+ /// Running. Instructions should be executed only when
+ /// the context is in this state.
+ Active,
+
+ /// Temporarily inactive. Entered while waiting for
+ /// synchronization, etc.
+ Suspended,
+
+ /// Permanently shut down. Entered when target executes
+ /// m5exit pseudo-instruction. When all contexts enter
+ /// this state, the simulation will terminate.
+ Halted
+ };
private:
Status _status;
public:
Status status() const { return _status; }
- void setStatus(Status new_status);
-#ifdef FULL_SYSTEM
- public:
- KernelStats kernelStats;
-#endif
+ /// 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();
public:
RegFile regs; // correct-path register context
// pointer to CPU associated with this context
BaseCPU *cpu;
+ // Current instruction
+ MachInst inst;
+
// Index of hardware thread context on the CPU that this represents.
int thread_num;
-#ifdef FULL_SYSTEM
+ // 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;
+#if FULL_SYSTEM
FunctionalMemory *mem;
- AlphaItb *itb;
- AlphaDtb *dtb;
- int cpu_id;
+ AlphaITB *itb;
+ AlphaDTB *dtb;
System *system;
// the following two fields are redundant, since we can always
// look them up through the system pointer, but we'll leave them
// here for now for convenience
- MemoryController *memCtrl;
+ MemoryController *memctrl;
PhysicalMemory *physmem;
+ Kernel::Binning *kernelBinning;
+ Kernel::Statistics *kernelStats;
+ bool bin;
+ bool fnbin;
+ void execute(const StaticInstBase *inst);
+
#else
Process *process;
#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_insn;
+ Counter func_exe_inst;
//
// Count failed store conditionals so we can warn of apparent
unsigned storeCondFailures;
// constructor: initialize context from given process structure
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
ExecContext(BaseCPU *_cpu, int _thread_num, System *_system,
- AlphaItb *_itb, AlphaDtb *_dtb, FunctionalMemory *_dem,
- int _cpu_id);
+ AlphaITB *_itb, AlphaDTB *_dtb, FunctionalMemory *_dem);
#else
ExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid);
ExecContext(BaseCPU *_cpu, int _thread_num, FunctionalMemory *_mem,
int _asid);
#endif
- virtual ~ExecContext() {}
+ virtual ~ExecContext();
+
+ virtual void takeOverFrom(ExecContext *oldContext);
void regStats(const std::string &name);
-#ifdef FULL_SYSTEM
+ void serialize(std::ostream &os);
+ void unserialize(Checkpoint *cp, const std::string §ion);
+
+#if FULL_SYSTEM
bool validInstAddr(Addr addr) { return true; }
bool validDataAddr(Addr addr) { return true; }
- int getInstAsid() { return ITB_ASN_ASN(regs.ipr[TheISA::IPR_ITB_ASN]); }
- int getDataAsid() { return DTB_ASN_ASN(regs.ipr[TheISA::IPR_DTB_ASN]); }
+ int getInstAsid() { return regs.instAsid(); }
+ int getDataAsid() { return regs.dataAsid(); }
- Fault translateInstReq(MemReqPtr req)
+ Fault translateInstReq(MemReqPtr &req)
{
return itb->translate(req);
}
- Fault translateDataReadReq(MemReqPtr req)
+ Fault translateDataReadReq(MemReqPtr &req)
{
return dtb->translate(req, false);
}
- Fault translateDataWriteReq(MemReqPtr req)
+ Fault translateDataWriteReq(MemReqPtr &req)
{
return dtb->translate(req, true);
}
-
#else
bool validInstAddr(Addr addr)
{ return process->validInstAddr(addr); }
int getInstAsid() { return asid; }
int getDataAsid() { return asid; }
- Fault dummyTranslation(MemReqPtr req)
+ Fault dummyTranslation(MemReqPtr &req)
{
#if 0
assert((req->vaddr >> 48 & 0xffff) == 0);
req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16;
return No_Fault;
}
- Fault translateInstReq(MemReqPtr req)
+ Fault translateInstReq(MemReqPtr &req)
{
return dummyTranslation(req);
}
- Fault translateDataReadReq(MemReqPtr req)
+ Fault translateDataReadReq(MemReqPtr &req)
{
return dummyTranslation(req);
}
- Fault translateDataWriteReq(MemReqPtr req)
+ Fault translateDataWriteReq(MemReqPtr &req)
{
return dummyTranslation(req);
}
#endif
template <class T>
- Fault read(MemReqPtr req, T& data)
+ Fault read(MemReqPtr &req, T &data)
{
-#if defined(TARGET_ALPHA) && defined(FULL_SYSTEM)
+#if FULL_SYSTEM && defined(TARGET_ALPHA)
if (req->flags & LOCKED) {
MiscRegFile *cregs = &req->xc->regs.miscRegs;
cregs->lock_addr = req->paddr;
cregs->lock_flag = true;
}
#endif
- return mem->read(req, data);
+
+ Fault error;
+ error = mem->read(req, data);
+ data = gtoh(data);
+ return error;
}
template <class T>
- Fault write(MemReqPtr req, T& data)
+ Fault write(MemReqPtr &req, T &data)
{
-#if defined(TARGET_ALPHA) && defined(FULL_SYSTEM)
+#if FULL_SYSTEM && defined(TARGET_ALPHA)
MiscRegFile *cregs;
// and all other stores (WH64?). Unsuccessful Store
// Conditionals would have returned above, and wouldn't fall
// through.
- for (int i = 0; i < system->xcvec.size(); i++){
- cregs = &system->xcvec[i]->regs.miscRegs;
+ for (int i = 0; i < system->execContexts.size(); i++){
+ cregs = &system->execContexts[i]->regs.miscRegs;
if ((cregs->lock_addr & ~0xf) == (req->paddr & ~0xf)) {
cregs->lock_flag = false;
}
}
#endif
- return mem->write(req, data);
+ return mem->write(req, (T)htog(data));
}
virtual bool misspeculating();
+ MachInst getInst() { return inst; }
+
+ void setInst(MachInst new_inst)
+ {
+ inst = new_inst;
+ }
+
+ Fault instRead(MemReqPtr &req)
+ {
+ return mem->read(req, inst);
+ }
+
//
// New accessors for new decoder.
//
regs.miscRegs.fpcr = val;
}
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
uint64_t readIpr(int idx, Fault &fault);
Fault setIpr(int idx, uint64_t val);
+ int readIntrFlag() { return regs.intrflag; }
+ void setIntrFlag(int val) { regs.intrflag = val; }
Fault hwrei();
+ bool inPalMode() { return AlphaISA::PcPAL(regs.pc); }
void ev5_trap(Fault fault);
bool simPalCheck(int palFunc);
#endif
-#ifndef FULL_SYSTEM
+ /** Meant to be more generic trap function to be
+ * called when an instruction faults.
+ * @param fault The fault generated by executing the instruction.
+ * @todo How to do this properly so it's dependent upon ISA only?
+ */
+
+ void trap(Fault fault);
+
+#if !FULL_SYSTEM
+ IntReg getSyscallArg(int i)
+ {
+ return regs.intRegFile[ArgumentReg0 + i];
+ }
+
+ // used to shift args for indirect syscall
+ void setSyscallArg(int i, IntReg val)
+ {
+ regs.intRegFile[ArgumentReg0 + i] = val;
+ }
+
+ void setSyscallReturn(SyscallReturn return_value)
+ {
+ // check for error condition. Alpha syscall convention is to
+ // indicate success/failure in reg a3 (r19) and put the
+ // return value itself in the standard return value reg (v0).
+ const int RegA3 = 19; // only place this is used
+ if (return_value.successful()) {
+ // no error
+ regs.intRegFile[RegA3] = 0;
+ regs.intRegFile[ReturnValueReg] = return_value.value();
+ } else {
+ // got an error, return details
+ regs.intRegFile[RegA3] = (IntReg) -1;
+ regs.intRegFile[ReturnValueReg] = -return_value.value();
+ }
+ }
+
void syscall()
{
process->syscall(this);
return false;
}
-#endif // __EXEC_CONTEXT_HH__
+#endif // __CPU_EXEC_CONTEXT_HH__