From 009970f59b86eac6c9a35eeb175dd9e3a3079d13 Mon Sep 17 00:00:00 2001 From: Andreas Sandberg Date: Mon, 7 Jan 2013 13:05:52 -0500 Subject: cpu: Unify the serialization code for all of the CPU models Cleanup the serialization code for the simple CPUs and the O3 CPU. The CPU-specific code has been replaced with a (un)serializeThread that serializes the thread state / context of a specific thread. Assuming that the thread state class uses the CPU-specific thread state uses the base thread state serialization code, this allows us to restore a checkpoint with any of the CPU models. --- src/cpu/simple/atomic.cc | 28 ++++++++++++---------------- src/cpu/simple/base.cc | 21 ++++++++++----------- src/cpu/simple/base.hh | 8 ++++---- src/cpu/simple/timing.cc | 47 +++++++++++++++++++++-------------------------- 4 files changed, 47 insertions(+), 57 deletions(-) (limited to 'src/cpu/simple') diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 036abdcdb..7255469a0 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -132,7 +132,7 @@ unsigned int AtomicSimpleCPU::drain(DrainManager *dm) { assert(!drain_manager); - if (_status == SwitchedOut) + if (switchedOut()) return 0; if (!isDrained()) { @@ -151,8 +151,9 @@ AtomicSimpleCPU::drain(DrainManager *dm) void AtomicSimpleCPU::drainResume() { + assert(!tickEvent.scheduled()); assert(!drain_manager); - if (_status == Idle || _status == SwitchedOut) + if (switchedOut()) return; DPRINTF(SimpleCPU, "Resume\n"); @@ -161,9 +162,16 @@ AtomicSimpleCPU::drainResume() "'atomic' mode.\n"); } - assert(!tickEvent.scheduled()); - if (thread->status() == ThreadContext::Active) + assert(!threadContexts.empty()); + if (threadContexts.size() > 1) + fatal("The atomic CPU only supports one thread.\n"); + + if (thread->status() == ThreadContext::Active) { schedule(tickEvent, nextCycle()); + _status = BaseSimpleCPU::Running; + } else { + _status = BaseSimpleCPU::Idle; + } system->totalNumInsts = 0; } @@ -194,8 +202,6 @@ AtomicSimpleCPU::switchOut() assert(!tickEvent.scheduled()); assert(_status == BaseSimpleCPU::Running || _status == Idle); assert(isDrained()); - - _status = SwitchedOut; } @@ -207,16 +213,6 @@ AtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU) // The tick event should have been descheduled by drain() assert(!tickEvent.scheduled()); - assert(!threadContexts.empty()); - if (threadContexts.size() > 1) - fatal("The atomic CPU only supports one thread.\n"); - - // If the ThreadContext is active, mark the CPU as running. - if (thread->status() == ThreadContext::Active) - _status = BaseSimpleCPU::Running; - else - _status = Idle; - ifetch_req.setThreadContext(_cpuId, 0); // Add thread ID if we add MT data_read_req.setThreadContext(_cpuId, 0); // Add thread ID here too data_write_req.setThreadContext(_cpuId, 0); // Add thread ID here too diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index da965450a..13e08a6cb 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011 ARM Limited + * Copyright (c) 2010-2012 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -283,22 +283,21 @@ BaseSimpleCPU::resetStats() } void -BaseSimpleCPU::serialize(ostream &os) +BaseSimpleCPU::serializeThread(ostream &os, ThreadID tid) { - SERIALIZE_ENUM(_status); - BaseCPU::serialize(os); -// SERIALIZE_SCALAR(inst); - nameOut(os, csprintf("%s.xc.0", name())); + assert(_status == Idle || _status == Running); + assert(tid == 0); + thread->serialize(os); } void -BaseSimpleCPU::unserialize(Checkpoint *cp, const string §ion) +BaseSimpleCPU::unserializeThread(Checkpoint *cp, const string §ion, + ThreadID tid) { - UNSERIALIZE_ENUM(_status); - BaseCPU::unserialize(cp, section); -// UNSERIALIZE_SCALAR(inst); - thread->unserialize(cp, csprintf("%s.xc.0", section)); + if (tid != 0) + fatal("Trying to load more than one thread into a SimpleCPU\n"); + thread->unserialize(cp, section); } void diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index 9bf144326..18b97c42f 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 ARM Limited + * Copyright (c) 2011-2012 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -137,7 +137,6 @@ class BaseSimpleCPU : public BaseCPU DcacheRetry, DcacheWaitResponse, DcacheWaitSwitch, - SwitchedOut }; Status _status; @@ -265,8 +264,9 @@ class BaseSimpleCPU : public BaseCPU Stats::Scalar dcacheRetryCycles; Counter lastDcacheRetry; - virtual void serialize(std::ostream &os); - virtual void unserialize(Checkpoint *cp, const std::string §ion); + void serializeThread(std::ostream &os, ThreadID tid); + void unserializeThread(Checkpoint *cp, const std::string §ion, + ThreadID tid); // These functions are only used in CPU models that split // effective address computation from the actual memory access. diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 78603be4f..f6dc1fbf6 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -109,9 +109,12 @@ TimingSimpleCPU::~TimingSimpleCPU() unsigned int TimingSimpleCPU::drain(DrainManager *drain_manager) { + assert(!drainManager); + if (switchedOut()) + return 0; + if (_status == Idle || - (_status == BaseSimpleCPU::Running && isDrained()) || - _status == SwitchedOut) { + (_status == BaseSimpleCPU::Running && isDrained())) { assert(!fetchEvent.scheduled()); DPRINTF(Drain, "No need to drain.\n"); return 0; @@ -122,10 +125,8 @@ TimingSimpleCPU::drain(DrainManager *drain_manager) // The fetch event can become descheduled if a drain didn't // succeed on the first attempt. We need to reschedule it if // the CPU is waiting for a microcode routine to complete. - if (_status == BaseSimpleCPU::Running && !isDrained() && - !fetchEvent.scheduled()) { + if (_status == BaseSimpleCPU::Running && !fetchEvent.scheduled()) schedule(fetchEvent, nextCycle()); - } return 1; } @@ -135,15 +136,25 @@ void TimingSimpleCPU::drainResume() { assert(!fetchEvent.scheduled()); + assert(!drainManager); + if (switchedOut()) + return; DPRINTF(SimpleCPU, "Resume\n"); - if (_status != SwitchedOut && _status != Idle) { - if (system->getMemoryMode() != Enums::timing) { - fatal("The timing CPU requires the memory system to be in " - "'timing' mode.\n"); - } + if (system->getMemoryMode() != Enums::timing) { + fatal("The timing CPU requires the memory system to be in " + "'timing' mode.\n"); + } + assert(!threadContexts.empty()); + if (threadContexts.size() > 1) + fatal("The timing CPU only supports one thread.\n"); + + if (thread->status() == ThreadContext::Active) { schedule(fetchEvent, nextCycle()); + _status = BaseSimpleCPU::Running; + } else { + _status = BaseSimpleCPU::Idle; } } @@ -174,7 +185,6 @@ TimingSimpleCPU::switchOut() assert(!stayAtPC); assert(microPC() == 0); - _status = SwitchedOut; numCycles += curCycle() - previousCycle; } @@ -184,21 +194,6 @@ TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU) { BaseSimpleCPU::takeOverFrom(oldCPU); - // if any of this CPU's ThreadContexts are active, mark the CPU as - // running and schedule its tick event. - for (int i = 0; i < threadContexts.size(); ++i) { - ThreadContext *tc = threadContexts[i]; - if (tc->status() == ThreadContext::Active && - _status != BaseSimpleCPU::Running) { - _status = BaseSimpleCPU::Running; - break; - } - } - - if (_status != BaseSimpleCPU::Running) { - _status = Idle; - } - assert(threadContexts.size() == 1); previousCycle = curCycle(); } -- cgit v1.2.3