/*
- * Copyright (c) 2002-2004 The Regents of The University of Michigan
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#include "base/output.hh"
#include "cpu/base.hh"
#include "cpu/exec_context.hh"
+#include "cpu/profile.hh"
#include "cpu/sampler/sampler.hh"
#include "sim/param.hh"
#include "sim/sim_events.hh"
// been initialized
int maxThreadsPerCPU = 1;
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
BaseCPU::BaseCPU(Params *p)
: SimObject(p->name), clock(p->clock), checkInterrupts(true),
params(p), number_of_threads(p->numberOfThreads), system(p->system)
p->max_loads_all_threads, *counter);
}
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
memset(interrupts, 0, sizeof(interrupts));
intstatus = 0;
#endif
e->schedule(p->functionTraceStart);
}
}
+#if FULL_SYSTEM
+ profileEvent = NULL;
+ if (params->profile)
+ profileEvent = new ProfileEvent(this, params->profile);
+#endif
}
+BaseCPU::Params::Params()
+{
+#if FULL_SYSTEM
+ profile = false;
+#endif
+}
void
BaseCPU::enableFunctionTrace()
registerExecContexts();
}
+void
+BaseCPU::startup()
+{
+#if FULL_SYSTEM
+ if (!params->deferRegistration && profileEvent)
+ profileEvent->schedule(curTick);
+#endif
+}
+
+
void
BaseCPU::regStats()
{
{
for (int i = 0; i < execContexts.size(); ++i) {
ExecContext *xc = execContexts[i];
- int cpu_id;
+#if FULL_SYSTEM
+ int id = params->cpu_id;
+ if (id != -1)
+ id += i;
-#ifdef FULL_SYSTEM
- cpu_id = system->registerExecContext(xc);
+ xc->cpu_id = system->registerExecContext(xc, id);
#else
- cpu_id = xc->process->registerExecContext(xc);
+ xc->cpu_id = xc->process->registerExecContext(xc);
#endif
-
- xc->cpu_id = cpu_id;
}
}
void
-BaseCPU::switchOut(SamplingCPU *sampler)
+BaseCPU::switchOut(Sampler *sampler)
{
panic("This CPU doesn't support sampling!");
}
newXC->takeOverFrom(oldXC);
assert(newXC->cpu_id == oldXC->cpu_id);
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
system->replaceExecContext(newXC, newXC->cpu_id);
#else
assert(newXC->process == oldXC->process);
#endif
}
-#ifdef FULL_SYSTEM
- for (int i = 0; i < NumInterruptLevels; ++i)
+#if FULL_SYSTEM
+ for (int i = 0; i < TheISA::NumInterruptLevels; ++i)
interrupts[i] = oldCPU->interrupts[i];
intstatus = oldCPU->intstatus;
+
+ for (int i = 0; i < execContexts.size(); ++i)
+ if (execContexts[i]->profile)
+ execContexts[i]->profile->clear();
+
+ if (profileEvent)
+ profileEvent->schedule(curTick);
#endif
}
-#ifdef FULL_SYSTEM
+#if FULL_SYSTEM
+BaseCPU::ProfileEvent::ProfileEvent(BaseCPU *_cpu, int _interval)
+ : Event(&mainEventQueue), cpu(_cpu), interval(_interval)
+{ }
+
+void
+BaseCPU::ProfileEvent::process()
+{
+ for (int i = 0, size = cpu->execContexts.size(); i < size; ++i) {
+ ExecContext *xc = cpu->execContexts[i];
+ xc->profile->sample(xc->profileNode, xc->profilePC);
+ }
+
+ schedule(curTick + interval);
+}
+
void
BaseCPU::post_interrupt(int int_num, int index)
{
DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
- if (int_num < 0 || int_num >= NumInterruptLevels)
+ if (int_num < 0 || int_num >= TheISA::NumInterruptLevels)
panic("int_num out of bounds\n");
if (index < 0 || index >= sizeof(uint64_t) * 8)
{
DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index);
- if (int_num < 0 || int_num >= NumInterruptLevels)
+ if (int_num < 0 || int_num >= TheISA::NumInterruptLevels)
panic("int_num out of bounds\n");
if (index < 0 || index >= sizeof(uint64_t) * 8)
void
BaseCPU::serialize(std::ostream &os)
{
- SERIALIZE_ARRAY(interrupts, NumInterruptLevels);
+ SERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels);
SERIALIZE_SCALAR(intstatus);
}
void
BaseCPU::unserialize(Checkpoint *cp, const std::string §ion)
{
- UNSERIALIZE_ARRAY(interrupts, NumInterruptLevels);
+ UNSERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels);
UNSERIALIZE_SCALAR(intstatus);
}