diff --git a/cpu/base_cpu.cc b/cpu/base_cpu.cc index 7605ff3c3..58f38d5d5 100644 --- a/cpu/base_cpu.cc +++ b/cpu/base_cpu.cc @@ -35,6 +35,7 @@ #include "base/misc.hh" #include "cpu/base_cpu.hh" #include "cpu/exec_context.hh" +#include "cpu/sampling_cpu/sampling_cpu.hh" #include "sim/param.hh" #include "sim/sim_events.hh" @@ -210,9 +211,10 @@ BaseCPU::registerExecContexts() void -BaseCPU::switchOut() +BaseCPU::switchOut(SamplingCPU *sampler) { - // default: do nothing + // default: do nothing, signal done + sampler->signalSwitched(); } void diff --git a/cpu/base_cpu.hh b/cpu/base_cpu.hh index baa956aa8..802da340b 100644 --- a/cpu/base_cpu.hh +++ b/cpu/base_cpu.hh @@ -32,6 +32,7 @@ #include #include "base/statistics.hh" +#include "cpu/sampling_cpu/sampling_cpu.hh" #include "sim/eventq.hh" #include "sim/sim_object.hh" #include "targetarch/isa_traits.hh" @@ -114,9 +115,9 @@ class BaseCPU : public SimObject bool deferRegistration; void registerExecContexts(); - /// Prepare for another CPU to take over execution. Called by - /// takeOverFrom() on its argument. - virtual void switchOut(); + /// Prepare for another CPU to take over execution. When it is + /// is ready (drained pipe) it signals the sampler. + virtual void switchOut(SamplingCPU *); /// Take over execution from the given CPU. Used for warm-up and /// sampling. diff --git a/cpu/pc_event.cc b/cpu/pc_event.cc index 8f046a7a4..21eef677a 100644 --- a/cpu/pc_event.cc +++ b/cpu/pc_event.cc @@ -31,10 +31,11 @@ #include #include -#include "sim/debug.hh" +#include "base/trace.hh" +#include "cpu/base_cpu.hh" #include "cpu/exec_context.hh" #include "cpu/pc_event.hh" -#include "base/trace.hh" +#include "sim/debug.hh" #include "sim/universe.hh" using namespace std; @@ -123,6 +124,8 @@ BreakPCEvent::BreakPCEvent(PCEventQueue *q, const std::string &desc, bool del) void BreakPCEvent::process(ExecContext *xc) { + StringWrap name(xc->cpu->name() + ".break_event"); + DPRINTFN("break event %s triggered", descr()); debug_break(); if (remove) delete this; diff --git a/cpu/simple_cpu/simple_cpu.cc b/cpu/simple_cpu/simple_cpu.cc index 9f4f821d4..2f1e8e1f1 100644 --- a/cpu/simple_cpu/simple_cpu.cc +++ b/cpu/simple_cpu/simple_cpu.cc @@ -47,6 +47,7 @@ #include "cpu/exec_context.hh" #include "cpu/exetrace.hh" #include "cpu/full_cpu/smt.hh" +#include "cpu/sampling_cpu/sampling_cpu.hh" #include "cpu/simple_cpu/simple_cpu.hh" #include "cpu/static_inst.hh" #include "mem/base_mem.hh" @@ -179,11 +180,21 @@ SimpleCPU::~SimpleCPU() } void -SimpleCPU::switchOut() +SimpleCPU::switchOut(SamplingCPU *s) { - _status = SwitchedOut; - if (tickEvent.scheduled()) - tickEvent.squash(); + sampler = s; + if (status() == DcacheMissStall) { + DPRINTF(Sampler,"Outstanding dcache access, waiting for completion\n"); + _status = DcacheMissSwitch; + } + else { + _status = SwitchedOut; + + if (tickEvent.scheduled()) + tickEvent.squash(); + + sampler->signalSwitched(); + } } @@ -203,8 +214,6 @@ SimpleCPU::takeOverFrom(BaseCPU *oldCPU) tickEvent.schedule(curTick); } } - - oldCPU->switchOut(); } @@ -631,6 +640,12 @@ SimpleCPU::processCacheCompletion() _status = Running; scheduleTickEvent(1); break; + case DcacheMissSwitch: + if (memReq->cmd.isRead()) { + curStaticInst->execute(this,traceData); + } + _status = SwitchedOut; + sampler->signalSwitched(); case SwitchedOut: // If this CPU has been switched out due to sampling/warm-up, // ignore any further status changes (e.g., due to cache diff --git a/cpu/simple_cpu/simple_cpu.hh b/cpu/simple_cpu/simple_cpu.hh index 8104d73a4..85bd1a74f 100644 --- a/cpu/simple_cpu/simple_cpu.hh +++ b/cpu/simple_cpu/simple_cpu.hh @@ -29,12 +29,13 @@ #ifndef __SIMPLE_CPU_HH__ #define __SIMPLE_CPU_HH__ -#include "cpu/base_cpu.hh" -#include "sim/eventq.hh" -#include "cpu/pc_event.hh" #include "base/statistics.hh" +#include "cpu/base_cpu.hh" #include "cpu/exec_context.hh" +#include "cpu/pc_event.hh" +#include "cpu/sampling_cpu/sampling_cpu.hh" #include "cpu/static_inst.hh" +#include "sim/eventq.hh" // forward declarations #ifdef FULL_SYSTEM @@ -117,6 +118,7 @@ class SimpleCPU : public BaseCPU IcacheMissStall, IcacheMissComplete, DcacheMissStall, + DcacheMissSwitch, SwitchedOut }; @@ -163,7 +165,7 @@ class SimpleCPU : public BaseCPU // execution context ExecContext *xc; - void switchOut(); + void switchOut(SamplingCPU *s); void takeOverFrom(BaseCPU *oldCPU); #ifdef FULL_SYSTEM @@ -184,6 +186,11 @@ class SimpleCPU : public BaseCPU // Refcounted pointer to the one memory request. MemReqPtr memReq; + // Pointer to the sampler that is telling us to switchover. + // Used to signal the completion of the pipe drain and schedule + // the next switchover + SamplingCPU *sampler; + StaticInstPtr curStaticInst; class CacheCompletionEvent : public Event diff --git a/kern/linux/linux_system.cc b/kern/linux/linux_system.cc index 401b4ef44..4ac03143e 100644 --- a/kern/linux/linux_system.cc +++ b/kern/linux/linux_system.cc @@ -102,12 +102,19 @@ LinuxSystem::LinuxSystem(Params *p) } else panic("could not find dp264_mv\n"); -#ifdef DEBUG +#ifndef NDEBUG kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic"); if (kernelSymtab->findAddress("panic", addr)) kernelPanicEvent->schedule(addr); else panic("could not find kernel symbol \'panic\'"); + + kernelDieEvent = new BreakPCEvent(&pcEventQueue, "die if kernel"); + if (kernelSymtab->findAddress("die_if_kernel", addr)) + kernelDieEvent->schedule(addr); + else + panic("could not find kernel symbol \'die_if_kernel\'"); + #endif /** @@ -174,7 +181,7 @@ LinuxSystem::LinuxSystem(Params *p) LinuxSystem::~LinuxSystem() { -#ifdef DEBUG +#ifndef NDEBUG delete kernelPanicEvent; #endif delete skipIdeDelay50msEvent; diff --git a/kern/linux/linux_system.hh b/kern/linux/linux_system.hh index 5e3cba9b3..905b0ee70 100644 --- a/kern/linux/linux_system.hh +++ b/kern/linux/linux_system.hh @@ -57,9 +57,12 @@ class PrintThreadInfo; class LinuxSystem : public System { private: -#ifdef DEBUG +#ifndef NDEBUG /** Event to halt the simulator if the kernel calls panic() */ BreakPCEvent *kernelPanicEvent; + + /** Event to halt the simulator if the kernel calls die_if_kernel */ + BreakPCEvent *kernelDieEvent; #endif /**