typedef union {
uint64_t q[NumFloatRegs]; // integer qword view
double d[NumFloatRegs]; // double-precision floating point view
+
+ void clear()
+ { bzero(d, sizeof(d)); }
} FloatRegFile;
extern const Addr PageShift;
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string §ion);
+
+ void clear()
+ {
+ bzero(intRegFile, sizeof(intRegFile));
+ floatRegFile.clear();
+ miscRegs.clear();
+ }
};
static inline ExtMachInst makeExtMI(MachInst inst, const uint64_t &pc);
// been initialized
int maxThreadsPerCPU = 1;
+void
+CPUProgressEvent::process()
+{
+#ifndef NDEBUG
+ Counter temp = cpu->totalInstructions();
+ double ipc = double(temp - lastNumInst) / (interval / cpu->cycles(1));
+ DPRINTFN("%s progress event, instructions committed: %lli, IPC: %0.8d\n",
+ cpu->name(), temp - lastNumInst, ipc);
+ ipc = 0.0;
+ lastNumInst = temp;
+ schedule(curTick + interval);
+#endif
+}
+
+const char *
+CPUProgressEvent::description()
+{
+ return "CPU Progress event";
+}
+
#if FULL_SYSTEM
BaseCPU::BaseCPU(Params *p)
: SimObject(p->name), clock(p->clock), checkInterrupts(true),
if (params->profile)
profileEvent = new ProfileEvent(this, params->profile);
#endif
-
}
BaseCPU::Params::Params()
if (!params->deferRegistration && profileEvent)
profileEvent->schedule(curTick);
#endif
+
+ if (params->progress_interval) {
+ new CPUProgressEvent(&mainEventQueue, params->progress_interval,
+ this);
+ }
}
class ExecContext;
class System;
+class CPUProgressEvent : public Event
+{
+ protected:
+ Tick interval;
+ Counter lastNumInst;
+ BaseCPU *cpu;
+
+ public:
+ CPUProgressEvent(EventQueue *q, Tick ival, BaseCPU *_cpu)
+ : Event(q, Event::Stat_Event_Pri), interval(ival), lastNumInst(0), cpu(_cpu)
+ { schedule(curTick + interval); }
+
+ void process();
+
+ virtual const char *description();
+};
+
class BaseCPU : public SimObject
{
protected:
int cpu_id;
Tick profile;
#endif
+ Tick progress_interval;
BaseCPU *checker;
Params();
union Result {
uint64_t integer;
- float fp;
+// float fp;
double dbl;
};
uint64_t readIntResult() { return instResult.integer; }
/** Returns the result of a floating point instruction. */
- float readFloatResult() { return instResult.fp; }
+ float readFloatResult() { return (float)instResult.dbl; }
/** Returns the result of a floating point (double) instruction. */
double readDoubleResult() { return instResult.dbl; }
void setFloatRegSingle(const StaticInst *si, int idx, float val)
{
- instResult.fp = val;
+// instResult.fp = val;
+ instResult.dbl = (double)val;
}
void setFloatRegDouble(const StaticInst *si, int idx, double val)
{
if (updateThisCycle) {
warn("%lli: Instruction PC %#x results didn't match up, copying all "
- "registers from main CPU", unverifiedInst->readPC());
+ "registers from main CPU", curTick, unverifiedInst->readPC());
// Heavy-weight copying of all registers
cpuXC->copyArchRegs(unverifiedInst->xcBase());
+ // Also advance the PC. Hopefully no PC-based events happened.
+#if THE_ISA != MIPS_ISA
+ // go to the next instruction
+ cpuXC->setPC(cpuXC->readNextPC());
+ cpuXC->setNextPC(cpuXC->readNextPC() + sizeof(MachInst));
+#else
+ // go to the next instruction
+ cpuXC->setPC(cpuXC->readNextPC());
+ cpuXC->setNextPC(cpuXC->readNextNPC());
+ cpuXC->setNextNPC(cpuXC->readNextNPC() + sizeof(MachInst));
+#endif
updateThisCycle = false;
}
}
virtual Counter totalInstructions() const
{
- return numInst - startNumInst;
+ return 0;
}
// number of simulated loads
Param<Counter> max_insts_all_threads;
Param<Counter> max_loads_any_thread;
Param<Counter> max_loads_all_threads;
+ Param<Tick> progress_interval;
#if FULL_SYSTEM
SimObjectParam<AlphaITB *> itb;
"terminate when any thread reaches this load count"),
INIT_PARAM(max_loads_all_threads,
"terminate when all threads have reached this load count"),
+ INIT_PARAM_DFLT(progress_interval, "CPU Progress Interval", 0),
#if FULL_SYSTEM
INIT_PARAM(itb, "Instruction TLB"),
temp = max_insts_all_threads;
temp = max_loads_any_thread;
temp = max_loads_all_threads;
+ Tick temp2 = progress_interval;
+ temp2++;
BaseMem *cache = icache;
cache = dcache;
Param<Counter> max_insts_all_threads;
Param<Counter> max_loads_any_thread;
Param<Counter> max_loads_all_threads;
+ Param<Tick> progress_interval;
#if FULL_SYSTEM
SimObjectParam<AlphaITB *> itb;
Param<bool> defer_registration;
Param<bool> exitOnError;
+ Param<bool> updateOnError;
Param<bool> function_trace;
Param<Tick> function_trace_start;
"terminate when any thread reaches this load count"),
INIT_PARAM(max_loads_all_threads,
"terminate when all threads have reached this load count"),
+ INIT_PARAM_DFLT(progress_interval, "CPU Progress Interval", 0),
#if FULL_SYSTEM
INIT_PARAM(itb, "Instruction TLB"),
INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
INIT_PARAM(exitOnError, "exit on error"),
+ INIT_PARAM(updateOnError, "Update the checker with the main CPU's state on error"),
INIT_PARAM(function_trace, "Enable function trace"),
INIT_PARAM(function_trace_start, "Cycle to start function trace")
params->max_loads_any_thread = 0;
params->max_loads_all_threads = 0;
params->exitOnError = exitOnError;
+ params->updateOnError = updateOnError;
params->deferRegistration = defer_registration;
params->functionTrace = function_trace;
params->functionTraceStart = function_trace_start;
temp = max_insts_all_threads;
temp = max_loads_any_thread;
temp = max_loads_all_threads;
+ Tick temp2 = progress_interval;
+ temp2++;
BaseMem *cache = icache;
cache = dcache;
#endif
+CPUExecContext::CPUExecContext()
+#if !FULL_SYSTEM
+ : cpu(NULL), thread_num(-1), process(NULL), mem(NULL), asid(-1),
+ func_exe_inst(0), storeCondFailures(0)
+#else
+ : cpu(NULL), thread_num(-1), cpu_id(-1), lastActivate(0), lastSuspend(0),
+ mem(NULL), itb(NULL), dtb(NULL), system(NULL), memctrl(NULL),
+ physmem(NULL), profile(NULL), func_exe_inst(0), storeCondFailures(0)
+#endif
+{
+ regs.clear();
+ proxy = new ProxyExecContext<CPUExecContext>(this);
+}
+
CPUExecContext::~CPUExecContext()
{
delete proxy;
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
+ copyState(oldContext);
+#if FULL_SYSTEM
EndQuiesceEvent *quiesce = oldContext->getQuiesceEvent();
if (quiesce) {
// Point the quiesce event's XC at this XC so that it wakes up
oldContext->setStatus(ExecContext::Unallocated);
}
+void
+CPUExecContext::copyXC(ExecContext *context)
+{
+ copyState(context);
+
+#if FULL_SYSTEM
+ EndQuiesceEvent *quiesce = context->getQuiesceEvent();
+ if (quiesce) {
+ quiesceEvent = quiesce;
+ }
+ Kernel::Statistics *stats = context->getKernelStats();
+ if (stats) {
+ kernelStats = stats;
+ }
+#endif
+}
+
+void
+CPUExecContext::copyState(ExecContext *oldContext)
+{
+ // copy over functional state
+ _status = oldContext->status();
+ copyArchRegs(oldContext);
+ cpu_id = oldContext->readCpuId();
+#if !FULL_SYSTEM
+ func_exe_inst = oldContext->readFuncExeInst();
+#endif
+ inst = oldContext->getInst();
+}
+
void
CPUExecContext::serialize(ostream &os)
{
void
CPUExecContext::copyArchRegs(ExecContext *xc)
{
+ TheISA::copyRegs(xc, proxy);
+/*
// First loop through the integer registers.
for (int i = 0; i < AlphaISA::NumIntRegs; ++i) {
setIntReg(i, xc->readIntReg(i));
// Lastly copy PC/NPC
setPC(xc->readPC());
setNextPC(xc->readNextPC());
+*/
}
// else.
CPUExecContext(RegFile *regFile);
#endif
+
+ CPUExecContext();
+
virtual ~CPUExecContext();
virtual void takeOverFrom(ExecContext *oldContext);
void regStats(const std::string &name);
+ void copyXC(ExecContext *context);
+
+ void copyState(ExecContext *oldContext);
+
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string §ion);
Param<Counter> max_insts_all_threads;
Param<Counter> max_loads_any_thread;
Param<Counter> max_loads_all_threads;
+Param<Tick> progress_interval;
SimObjectParam<BaseCache *> icache;
SimObjectParam<BaseCache *> dcache;
"Terminate when all threads have reached this load"
"count",
0),
+ INIT_PARAM_DFLT(progress_interval, "Progress interval", 0),
INIT_PARAM_DFLT(icache, "L1 instruction cache", NULL),
INIT_PARAM_DFLT(dcache, "L1 data cache", NULL),
params->max_insts_all_threads = max_insts_all_threads;
params->max_loads_any_thread = max_loads_any_thread;
params->max_loads_all_threads = max_loads_all_threads;
+ params->progress_interval = progress_interval;
//
// Caches
#include "config/full_system.hh"
#if FULL_SYSTEM
+#include "cpu/quiesce_event.hh"
#include "sim/system.hh"
#else
#include "sim/process.hh"
// Be sure to signal that there's some activity so the CPU doesn't
// deschedule itself.
activityRec.activity();
+ if (thread[tid]->quiesceEvent && thread[tid]->quiesceEvent->scheduled())
+ thread[tid]->quiesceEvent->deschedule();
+
fetch.wakeFromQuiesce();
_status = Running;
tickEvent.schedule(curTick);
}
-/*
template <class Impl>
void
FullO3CPU<Impl>::serialize(std::ostream &os)
// Use SimpleThread's ability to checkpoint to make it easier to
// write out the registers. Also make this static so it doesn't
// get instantiated multiple times (causes a panic in statistics).
- static SimpleThread temp;
+ static CPUExecContext temp;
for (int i = 0; i < thread.size(); i++) {
nameOut(os, csprintf("%s.xc.%i", name(), i));
- temp.copyXC(thread[i]->getXC());
+ temp.copyXC(thread[i]->getXCProxy());
temp.serialize(os);
}
}
// Use SimpleThread's ability to checkpoint to make it easier to
// read in the registers. Also make this static so it doesn't
// get instantiated multiple times (causes a panic in statistics).
- static SimpleThread temp;
+ static CPUExecContext temp;
for (int i = 0; i < thread.size(); i++) {
- temp.copyXC(thread[i]->getXC());
+ temp.copyXC(thread[i]->getXCProxy());
temp.unserialize(cp, csprintf("%s.xc.%i", section, i));
- thread[i]->getXC()->copyArchRegs(temp.getXC());
+ thread[i]->getXCProxy()->copyArchRegs(temp.getProxy());
}
}
-*/
+
template <class Impl>
uint64_t
FullO3CPU<Impl>::readIntReg(int reg_idx)
/** Update The Order In Which We Process Threads. */
void updateThreadPriority();
+ /** Serialize state. */
+ virtual void serialize(std::ostream &os);
+
+ /** Unserialize from a checkpoint. */
+ virtual void unserialize(Checkpoint *cp, const std::string §ion);
+
+ public:
/** Executes a syscall on this cycle.
* ---------------------------------------
* Note: this is a virtual function. CPU-Specific
for (int i = 0; i < localPredictorSize; ++i)
localCtrs[i].setBits(localCtrBits);
+ localPredictorMask = floorPow2(localPredictorSize) - 1;
+
if (!isPowerOf2(localHistoryTableSize)) {
fatal("Invalid local history table size!\n");
}
//Lookup in the local predictor to get its branch prediction
local_history_idx = calcLocHistIdx(branch_addr);
local_predictor_idx = localHistoryTable[local_history_idx]
- & localHistoryMask;
+ & localPredictorMask;
local_prediction = localCtrs[local_predictor_idx].read() > threshold;
//Lookup in the global predictor to get its branch prediction
bp_history = (void *)history;
assert(globalHistory < globalPredictorSize &&
- local_history_idx < localPredictorSize);
+ local_history_idx < localHistoryTableSize &&
+ local_predictor_idx < localPredictorSize);
// Commented code is for doing speculative update of counters and
// all histories.
// Get the local predictor's current prediction
local_history_idx = calcLocHistIdx(branch_addr);
local_predictor_hist = localHistoryTable[local_history_idx];
- local_predictor_idx = local_predictor_hist & localHistoryMask;
+ local_predictor_idx = local_predictor_hist & localPredictorMask;
// Update the choice predictor to tell it which one was correct if
// there was a prediction.
}
assert(globalHistory < globalPredictorSize &&
+ local_history_idx < localHistoryTableSize &&
local_predictor_idx < localPredictorSize);
// Update the counters and local history with the proper
/** Size of the local predictor. */
unsigned localPredictorSize;
+ /** Mask to get the proper index bits into the predictor. */
+ unsigned localPredictorMask;
+
/** Number of bits of the local predictor's counters. */
unsigned localCtrBits;
Status _status;
public:
- bool checkInterrupts;
-
void post_interrupt(int int_num, int index);
void zero_fill_64(Addr addr) {
Param<Counter> max_insts_all_threads;
Param<Counter> max_loads_any_thread;
Param<Counter> max_loads_all_threads;
+Param<Tick> progress_interval;
SimObjectParam<BaseCache *> icache;
SimObjectParam<BaseCache *> dcache;
"Terminate when all threads have reached this load"
"count",
0),
+ INIT_PARAM_DFLT(progress_interval, "Progress interval", 0),
INIT_PARAM_DFLT(icache, "L1 instruction cache", NULL),
INIT_PARAM_DFLT(dcache, "L1 data cache", NULL),
params->max_insts_all_threads = max_insts_all_threads;
params->max_loads_any_thread = max_loads_any_thread;
params->max_loads_all_threads = max_loads_all_threads;
+ params->progress_interval = progress_interval;
//
// Caches
{
BaseCPU::takeOverFrom(oldCPU);
+ thread.trapPending = false;
+ thread.inSyscall = false;
+
backEnd->takeOverFrom();
frontEnd->takeOverFrom();
assert(!tickEvent.scheduled());
scheduleTickEvent(delay);
_status = Running;
thread._status = ExecContext::Active;
+ if (thread.quiesceEvent && thread.quiesceEvent->scheduled())
+ thread.quiesceEvent->deschedule();
frontEnd->wakeFromQuiesce();
}
OzoneCPU<Impl>::serialize(std::ostream &os)
{
BaseCPU::serialize(os);
- SERIALIZE_ENUM(_status);
- nameOut(os, csprintf("%s.xc", name()));
- ozoneXC.serialize(os);
nameOut(os, csprintf("%s.tickEvent", name()));
tickEvent.serialize(os);
+
+ // Use SimpleThread's ability to checkpoint to make it easier to
+ // write out the registers. Also make this static so it doesn't
+ // get instantiated multiple times (causes a panic in statistics).
+ static CPUExecContext temp;
+
+ nameOut(os, csprintf("%s.xc.0", name()));
+ temp.copyXC(thread.getXCProxy());
+ temp.serialize(os);
}
template <class Impl>
OzoneCPU<Impl>::unserialize(Checkpoint *cp, const std::string §ion)
{
BaseCPU::unserialize(cp, section);
- UNSERIALIZE_ENUM(_status);
- ozoneXC.unserialize(cp, csprintf("%s.xc", section));
tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
+
+ // Use SimpleThread's ability to checkpoint to make it easier to
+ // read in the registers. Also make this static so it doesn't
+ // get instantiated multiple times (causes a panic in statistics).
+ static CPUExecContext temp;
+
+ temp.copyXC(thread.getXCProxy());
+ temp.unserialize(cp, csprintf("%s.xc.0", section));
+ thread.getXCProxy()->copyArchRegs(temp.getProxy());
}
template <class Impl>
#if FULL_SYSTEM
if (inst->isQuiesce()) {
- warn("%lli: Quiesce instruction encountered, halting fetch!", curTick);
+// warn("%lli: Quiesce instruction encountered, halting fetch!", curTick);
status = QuiescePending;
break;
}
void
LWBackEnd<Impl>::takeOverFrom(ExecContext *old_xc)
{
- switchedOut = false;
xcSquash = false;
trapSquash = false;
BaseCPU::serialize(os);
SERIALIZE_ENUM(_status);
SERIALIZE_SCALAR(inst);
- nameOut(os, csprintf("%s.xc", name()));
+ nameOut(os, csprintf("%s.xc.0", name()));
cpuXC->serialize(os);
nameOut(os, csprintf("%s.tickEvent", name()));
tickEvent.serialize(os);
BaseCPU::unserialize(cp, section);
UNSERIALIZE_ENUM(_status);
UNSERIALIZE_SCALAR(inst);
- cpuXC->unserialize(cp, csprintf("%s.xc", section));
+ cpuXC->unserialize(cp, csprintf("%s.xc.0", section));
tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
cacheCompletionEvent
.unserialize(cp, csprintf("%s.cacheCompletionEvent", section));
Param<Counter> max_insts_all_threads;
Param<Counter> max_loads_any_thread;
Param<Counter> max_loads_all_threads;
+ Param<Tick> progress_interval;
#if FULL_SYSTEM
SimObjectParam<AlphaITB *> itb;
"terminate when any thread reaches this load count"),
INIT_PARAM(max_loads_all_threads,
"terminate when all threads have reached this load count"),
+ INIT_PARAM_DFLT(progress_interval, "CPU Progress interval", 0),
#if FULL_SYSTEM
INIT_PARAM(itb, "Instruction TLB"),
params->dcache_interface = (dcache) ? dcache->getInterface() : NULL;
params->width = width;
+ params->progress_interval = progress_interval;
#if FULL_SYSTEM
params->itb = itb;
params->dtb = dtb;
"terminate when all threads have reached this load count")
max_loads_any_thread = Param.Counter(0,
"terminate when any thread reaches this load count")
+ progress_interval = Param.Tick(0, "interval to print out the progress message")
defer_registration = Param.Bool(False,
"defer registration with system (for sampling)")
from m5 import *
from HierParams import HierParams
from Serialize import Serialize
+from Serialize import Statreset
from Statistics import Statistics
from Trace import Trace
from ExeTrace import ExecutionTrace
trace = Trace()
exetrace = ExecutionTrace()
serialize = Serialize()
+ statsreset = Statreset()
#include "sim/sim_exit.hh"
#include "sim/sim_object.hh"
+// For stat reset hack
+#include "sim/stat_control.hh"
+
using namespace std;
int Serializable::ckptMaxCount = 0;
{
return db->sectionExists(section);
}
+
+/** Hacked stat reset event */
+
+class StatresetParamContext : public ParamContext
+{
+ public:
+ StatresetParamContext(const string §ion);
+ ~StatresetParamContext();
+ void startup();
+};
+
+StatresetParamContext statParams("statsreset");
+
+Param<Tick> reset_cycle(&statParams, "reset_cycle",
+ "Cycle to reset stats on", 0);
+
+StatresetParamContext::StatresetParamContext(const string §ion)
+ : ParamContext(section)
+{ }
+
+StatresetParamContext::~StatresetParamContext()
+{
+}
+
+void
+StatresetParamContext::startup()
+{
+ if (reset_cycle > 0) {
+ Stats::SetupEvent(Stats::Reset, curTick + reset_cycle, 0);
+ cprintf("Stats reset event scheduled for %lli\n",
+ curTick + reset_cycle);
+ }
+}
if (flags & Stats::Dump)
DumpNow();
- if (flags & Stats::Reset)
+ if (flags & Stats::Reset) {
+ cprintf("Resetting stats!\n");
reset();
+ }
if (repeat)
schedule(curTick + repeat);