#include "cpu/cpuevent.hh"
#include "cpu/thread_context.hh"
#include "cpu/profile.hh"
-#include "cpu/sampler/sampler.hh"
+#include "sim/sim_exit.hh"
#include "sim/param.hh"
#include "sim/process.hh"
#include "sim/sim_events.hh"
#include "base/trace.hh"
+// Hack
+#include "sim/stat_control.hh"
+
using namespace std;
vector<BaseCPU *> BaseCPU::cpuList;
// been initialized
int maxThreadsPerCPU = 1;
+CPUProgressEvent::CPUProgressEvent(EventQueue *q, Tick ival,
+ BaseCPU *_cpu)
+ : Event(q, Event::Progress_Event_Pri), interval(ival),
+ lastNumInst(0), cpu(_cpu)
+{
+ if (interval)
+ schedule(curTick + interval);
+}
+
+void
+CPUProgressEvent::process()
+{
+ Counter temp = cpu->totalInstructions();
+#ifndef NDEBUG
+ 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;
+#else
+ cprintf("%lli: %s progress event, instructions committed: %lli\n",
+ curTick, cpu->name(), temp - lastNumInst);
+#endif
+ lastNumInst = temp;
+ schedule(curTick + interval);
+}
+
+const char *
+CPUProgressEvent::description()
+{
+ return "CPU Progress";
+}
+
#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)
+ : MemObject(p->name), clock(p->clock), instCnt(0),
+ params(p), number_of_threads(p->numberOfThreads), system(p->system),
+ phase(p->phase)
#else
BaseCPU::BaseCPU(Params *p)
- : SimObject(p->name), clock(p->clock), params(p),
- number_of_threads(p->numberOfThreads), system(p->system)
+ : MemObject(p->name), clock(p->clock), params(p),
+ number_of_threads(p->numberOfThreads), system(p->system),
+ phase(p->phase)
#endif
{
+// currentTick = curTick;
DPRINTF(FullCPU, "BaseCPU: Creating object, mem address %#x.\n", this);
// add self to global list of CPUs
//
if (p->max_insts_any_thread != 0)
for (int i = 0; i < number_of_threads; ++i)
- new SimLoopExitEvent(comInstEventQueue[i], p->max_insts_any_thread,
- "a thread reached the max instruction count");
+ schedExitSimLoop("a thread reached the max instruction count",
+ p->max_insts_any_thread, 0,
+ comInstEventQueue[i]);
if (p->max_insts_all_threads != 0) {
// allocate & initialize shared downcounter: each event will
//
if (p->max_loads_any_thread != 0)
for (int i = 0; i < number_of_threads; ++i)
- new SimLoopExitEvent(comLoadEventQueue[i], p->max_loads_any_thread,
- "a thread reached the max load count");
+ schedExitSimLoop("a thread reached the max load count",
+ p->max_loads_any_thread, 0,
+ comLoadEventQueue[i]);
if (p->max_loads_all_threads != 0) {
// allocate & initialize shared downcounter: each event will
p->max_loads_all_threads, *counter);
}
-#if FULL_SYSTEM
- memset(interrupts, 0, sizeof(interrupts));
- intstatus = 0;
-#endif
-
functionTracingEnabled = false;
if (p->functionTrace) {
functionTraceStream = simout.find(csprintf("ftrace.%s", name()));
if (p->functionTraceStart == 0) {
functionTracingEnabled = true;
} else {
- Event *e =
- new EventWrapper<BaseCPU, &BaseCPU::enableFunctionTrace>(this,
- true);
- e->schedule(p->functionTraceStart);
+ new EventWrapper<BaseCPU, &BaseCPU::enableFunctionTrace>(this,
+ p->functionTraceStart,
+ true);
}
}
#if FULL_SYSTEM
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,
+ cycles(params->progress_interval),
+ this);
+ }
}
#endif
}
+Tick
+BaseCPU::nextCycle()
+{
+ Tick next_tick = curTick - phase + clock - 1;
+ next_tick -= (next_tick % clock);
+ next_tick += phase;
+ return next_tick;
+}
+
+Tick
+BaseCPU::nextCycle(Tick begin_tick)
+{
+ Tick next_tick = begin_tick;
+ if (next_tick % clock != 0)
+ next_tick = next_tick - (next_tick % clock) + clock;
+ next_tick += phase;
+
+ assert(next_tick >= curTick);
+ return next_tick;
+}
void
BaseCPU::registerThreadContexts()
}
+int
+BaseCPU::findContext(ThreadContext *tc)
+{
+ for (int i = 0; i < threadContexts.size(); ++i) {
+ if (tc == threadContexts[i])
+ return i;
+ }
+ return 0;
+}
+
void
BaseCPU::switchOut()
{
- panic("This CPU doesn't support sampling!");
+// panic("This CPU doesn't support sampling!");
+#if FULL_SYSTEM
+ if (profileEvent && profileEvent->scheduled())
+ profileEvent->deschedule();
+#endif
}
void
-BaseCPU::takeOverFrom(BaseCPU *oldCPU)
+BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc)
{
assert(threadContexts.size() == oldCPU->threadContexts.size());
assert(newTC->getProcessPtr() == oldTC->getProcessPtr());
newTC->getProcessPtr()->replaceThreadContext(newTC, newTC->readCpuId());
#endif
+
+// TheISA::compareXCs(oldXC, newXC);
}
#if FULL_SYSTEM
- for (int i = 0; i < TheISA::NumInterruptLevels; ++i)
- interrupts[i] = oldCPU->interrupts[i];
- intstatus = oldCPU->intstatus;
+ interrupts = oldCPU->interrupts;
for (int i = 0; i < threadContexts.size(); ++i)
threadContexts[i]->profileClear();
- if (profileEvent)
- profileEvent->schedule(curTick);
+ // The Sampler must take care of this!
+// if (profileEvent)
+// profileEvent->schedule(curTick);
#endif
+
+ // Connect new CPU to old CPU's memory only if new CPU isn't
+ // connected to anything. Also connect old CPU's memory to new
+ // CPU.
+ Port *peer;
+ if (ic->getPeer() == NULL) {
+ peer = oldCPU->getPort("icache_port")->getPeer();
+ ic->setPeer(peer);
+ } else {
+ peer = ic->getPeer();
+ }
+ peer->setPeer(ic);
+
+ if (dc->getPeer() == NULL) {
+ peer = oldCPU->getPort("dcache_port")->getPeer();
+ dc->setPeer(peer);
+ } else {
+ peer = dc->getPeer();
+ }
+ peer->setPeer(dc);
}
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 >= TheISA::NumInterruptLevels)
- panic("int_num out of bounds\n");
-
- if (index < 0 || index >= sizeof(uint64_t) * 8)
- panic("int_num out of bounds\n");
-
- checkInterrupts = true;
- interrupts[int_num] |= 1 << index;
- intstatus |= (ULL(1) << int_num);
+ interrupts.post(int_num, index);
}
void
BaseCPU::clear_interrupt(int int_num, int index)
{
- DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index);
-
- if (int_num < 0 || int_num >= TheISA::NumInterruptLevels)
- panic("int_num out of bounds\n");
-
- if (index < 0 || index >= sizeof(uint64_t) * 8)
- panic("int_num out of bounds\n");
-
- interrupts[int_num] &= ~(1 << index);
- if (interrupts[int_num] == 0)
- intstatus &= ~(ULL(1) << int_num);
+ interrupts.clear(int_num, index);
}
void
BaseCPU::clear_interrupts()
{
- DPRINTF(Interrupt, "Interrupts all cleared\n");
-
- memset(interrupts, 0, sizeof(interrupts));
- intstatus = 0;
+ interrupts.clear_all();
}
+uint64_t
+BaseCPU::get_interrupts(int int_num)
+{
+ return interrupts.get_vec(int_num);
+}
void
BaseCPU::serialize(std::ostream &os)
{
- SERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels);
- SERIALIZE_SCALAR(intstatus);
+ SERIALIZE_SCALAR(instCnt);
+ interrupts.serialize(os);
}
void
BaseCPU::unserialize(Checkpoint *cp, const std::string §ion)
{
- UNSERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels);
- UNSERIALIZE_SCALAR(intstatus);
+ UNSERIALIZE_SCALAR(instCnt);
+ interrupts.unserialize(cp, section);
}
#endif // FULL_SYSTEM