#include "cpu/base.hh"
#include "cpu/exec_context.hh"
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
+#include "base/callback.hh"
#include "base/cprintf.hh"
+#include "base/output.hh"
+#include "cpu/profile.hh"
#include "kern/kernel_stats.hh"
#include "sim/serialize.hh"
+#include "sim/sim_exit.hh"
#include "sim/system.hh"
+#include "targetarch/stacktrace.hh"
#else
#include "sim/process.hh"
#endif
using namespace std;
// constructor
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
AlphaITB *_itb, AlphaDTB *_dtb,
FunctionalMemory *_mem)
cpu_id(-1), mem(_mem), itb(_itb), dtb(_dtb), system(_sys),
memctrl(_sys->memctrl), physmem(_sys->physmem),
kernelBinning(system->kernelBinning), bin(kernelBinning->bin),
- fnbin(kernelBinning->fnbin), func_exe_inst(0), storeCondFailures(0)
+ fnbin(kernelBinning->fnbin), profile(NULL),
+ func_exe_inst(0), storeCondFailures(0)
{
kernelStats = new Kernel::Statistics(this);
memset(®s, 0, sizeof(RegFile));
+
+ if (cpu->params->profile) {
+ profile = new FunctionProfile(system->kernelSymtab);
+ Callback *cb =
+ new MakeCallback<ExecContext, &ExecContext::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;
}
#else
ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num,
ExecContext::~ExecContext()
{
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
delete kernelStats;
#endif
}
+#if FULL_SYSTEM
+void
+ExecContext::dumpFuncProfile()
+{
+ std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name()));
+ profile->dump(this, *os);
+}
+#endif
void
ExecContext::takeOverFrom(ExecContext *oldContext)
{
// some things should already be set up
assert(mem == oldContext->mem);
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
assert(system == oldContext->system);
#else
assert(process == oldContext->process);
oldContext->_status = ExecContext::Unallocated;
}
-#ifdef FULL_SYSTEM
-void
-ExecContext::execute(const StaticInstBase *inst)
-{
- assert(kernelStats);
- system->kernelBinning->execute(this, inst);
-}
-#endif
-
void
ExecContext::serialize(ostream &os)
{
SERIALIZE_SCALAR(func_exe_inst);
SERIALIZE_SCALAR(inst);
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
kernelStats->serialize(os);
#endif
}
UNSERIALIZE_SCALAR(func_exe_inst);
UNSERIALIZE_SCALAR(inst);
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
kernelStats->unserialize(cp, section);
#endif
}
if (status() == Suspended)
return;
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
// Don't change the status from active if there are pending interrupts
if (cpu->check_interrupts()) {
assert(status() == Active);
void
ExecContext::regStats(const string &name)
{
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
kernelStats->regStats(name + ".kern");
#endif
}
//TheISA::trap(fault); //One possible way to do it...
/** @todo: Going to hack it for now. Do a true fixup later. */
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
ev5_trap(fault);
#else
fatal("fault (%d) detected @ PC 0x%08p", fault, readPC());