changeset 569d1e8f74e4 in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=569d1e8f74e4
description:
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.
diffstat:
src/cpu/base.cc | 31 +++++++++++++++++++++++--------
src/cpu/base.hh | 32 +++++++++++++++++++++++++++++++-
src/cpu/o3/cpu.cc | 28 +++++-----------------------
src/cpu/o3/cpu.hh | 7 +++----
src/cpu/simple/atomic.cc | 28 ++++++++++++----------------
src/cpu/simple/base.cc | 21 ++++++++++-----------
src/cpu/simple/base.hh | 8 ++++----
src/cpu/simple/timing.cc | 47 +++++++++++++++++++++--------------------------
8 files changed, 109 insertions(+), 93 deletions(-)
diffs (truncated from 394 to 300 lines):
diff -r 156f74caf0d4 -r 569d1e8f74e4 src/cpu/base.cc
--- a/src/cpu/base.cc Mon Jan 07 13:05:52 2013 -0500
+++ b/src/cpu/base.cc Mon Jan 07 13:05:52 2013 -0500
@@ -524,21 +524,36 @@
{
SERIALIZE_SCALAR(instCnt);
- /* Unlike _pid, _taskId is not serialized, as they are dynamically
- * assigned unique ids that are only meaningful for the duration of
- * a specific run. We will need to serialize the entire taskMap in
- * system. */
- SERIALIZE_SCALAR(_pid);
+ if (!_switchedOut) {
+ /* Unlike _pid, _taskId is not serialized, as they are dynamically
+ * assigned unique ids that are only meaningful for the duration of
+ * a specific run. We will need to serialize the entire taskMap in
+ * system. */
+ SERIALIZE_SCALAR(_pid);
- interrupts->serialize(os);
+ interrupts->serialize(os);
+
+ // Serialize the threads, this is done by the CPU implementation.
+ for (ThreadID i = 0; i < numThreads; ++i) {
+ nameOut(os, csprintf("%s.xc.%i", name(), i));
+ serializeThread(os, i);
+ }
+ }
}
void
BaseCPU::unserialize(Checkpoint *cp, const std::string §ion)
{
UNSERIALIZE_SCALAR(instCnt);
- UNSERIALIZE_SCALAR(_pid);
- interrupts->unserialize(cp, section);
+
+ if (!_switchedOut) {
+ UNSERIALIZE_SCALAR(_pid);
+ interrupts->unserialize(cp, section);
+
+ // Unserialize the threads, this is done by the CPU implementation.
+ for (ThreadID i = 0; i < numThreads; ++i)
+ unserializeThread(cp, csprintf("%s.xc.%i", section, i), i);
+ }
}
void
diff -r 156f74caf0d4 -r 569d1e8f74e4 src/cpu/base.hh
--- a/src/cpu/base.hh Mon Jan 07 13:05:52 2013 -0500
+++ b/src/cpu/base.hh Mon Jan 07 13:05:52 2013 -0500
@@ -365,18 +365,48 @@
/**
* Serialize this object to the given output stream.
+ *
+ * @note CPU models should normally overload the serializeThread()
+ * method instead of the serialize() method as this provides a
+ * uniform data format for all CPU models and promotes better code
+ * reuse.
+ *
* @param os The stream to serialize to.
*/
virtual void serialize(std::ostream &os);
/**
* Reconstruct the state of this object from a checkpoint.
+ *
+ * @note CPU models should normally overload the
+ * unserializeThread() method instead of the unserialize() method
+ * as this provides a uniform data format for all CPU models and
+ * promotes better code reuse.
+
* @param cp The checkpoint use.
- * @param section The section name of this object
+ * @param section The section name of this object.
*/
virtual void unserialize(Checkpoint *cp, const std::string §ion);
/**
+ * Serialize a single thread.
+ *
+ * @param os The stream to serialize to.
+ * @param tid ID of the current thread.
+ */
+ virtual void serializeThread(std::ostream &os, ThreadID tid) {};
+
+ /**
+ * Unserialize one thread.
+ *
+ * @param cp The checkpoint use.
+ * @param section The section name of this thread.
+ * @param tid ID of the current thread.
+ */
+ virtual void unserializeThread(Checkpoint *cp, const std::string §ion,
+ ThreadID tid) {};
+
+ /**
* Return pointer to CPU's branch predictor (NULL if none).
* @return Branch predictor pointer.
*/
diff -r 156f74caf0d4 -r 569d1e8f74e4 src/cpu/o3/cpu.cc
--- a/src/cpu/o3/cpu.cc Mon Jan 07 13:05:52 2013 -0500
+++ b/src/cpu/o3/cpu.cc Mon Jan 07 13:05:52 2013 -0500
@@ -1094,35 +1094,17 @@
template <class Impl>
void
-FullO3CPU<Impl>::serialize(std::ostream &os)
+FullO3CPU<Impl>::serializeThread(std::ostream &os, ThreadID tid)
{
- Drainable::State so_state(getDrainState());
- SERIALIZE_ENUM(so_state);
- BaseCPU::serialize(os);
- nameOut(os, csprintf("%s.tickEvent", name()));
- tickEvent.serialize(os);
-
- for (ThreadID i = 0; i < thread.size(); i++) {
- nameOut(os, csprintf("%s.xc.%i", name(), i));
- thread[i]->serialize(os);
- }
+ thread[tid]->serialize(os);
}
template <class Impl>
void
-FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string §ion)
+FullO3CPU<Impl>::unserializeThread(Checkpoint *cp, const std::string §ion,
+ ThreadID tid)
{
- Drainable::State so_state;
- UNSERIALIZE_ENUM(so_state);
- BaseCPU::unserialize(cp, section);
- tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
-
- for (ThreadID i = 0; i < thread.size(); i++) {
- thread[i]->unserialize(cp,
- csprintf("%s.xc.%i", section, i));
- if (thread[i]->status() == ThreadContext::Active)
- activateThread(i);
- }
+ thread[tid]->unserialize(cp, section);
}
template <class Impl>
diff -r 156f74caf0d4 -r 569d1e8f74e4 src/cpu/o3/cpu.hh
--- a/src/cpu/o3/cpu.hh Mon Jan 07 13:05:52 2013 -0500
+++ b/src/cpu/o3/cpu.hh Mon Jan 07 13:05:52 2013 -0500
@@ -446,11 +446,10 @@
/** Is the CPU draining? */
bool isDraining() const { return getDrainState() == Drainable::Draining; }
- /** Serialize state. */
- virtual void serialize(std::ostream &os);
+ void serializeThread(std::ostream &os, ThreadID tid);
- /** Unserialize from a checkpoint. */
- virtual void unserialize(Checkpoint *cp, const std::string §ion);
+ void unserializeThread(Checkpoint *cp, const std::string §ion,
+ ThreadID tid);
public:
/** Executes a syscall.
diff -r 156f74caf0d4 -r 569d1e8f74e4 src/cpu/simple/atomic.cc
--- a/src/cpu/simple/atomic.cc Mon Jan 07 13:05:52 2013 -0500
+++ b/src/cpu/simple/atomic.cc Mon Jan 07 13:05:52 2013 -0500
@@ -132,7 +132,7 @@
AtomicSimpleCPU::drain(DrainManager *dm)
{
assert(!drain_manager);
- if (_status == SwitchedOut)
+ if (switchedOut())
return 0;
if (!isDrained()) {
@@ -151,8 +151,9 @@
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 @@
"'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 @@
assert(!tickEvent.scheduled());
assert(_status == BaseSimpleCPU::Running || _status == Idle);
assert(isDrained());
-
- _status = SwitchedOut;
}
@@ -207,16 +213,6 @@
// 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 -r 156f74caf0d4 -r 569d1e8f74e4 src/cpu/simple/base.cc
--- a/src/cpu/simple/base.cc Mon Jan 07 13:05:52 2013 -0500
+++ b/src/cpu/simple/base.cc Mon Jan 07 13:05:52 2013 -0500
@@ -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 @@
}
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 -r 156f74caf0d4 -r 569d1e8f74e4 src/cpu/simple/base.hh
--- a/src/cpu/simple/base.hh Mon Jan 07 13:05:52 2013 -0500
+++ b/src/cpu/simple/base.hh Mon Jan 07 13:05:52 2013 -0500
@@ -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 @@
DcacheRetry,
DcacheWaitResponse,
DcacheWaitSwitch,
- SwitchedOut
};
Status _status;
@@ -265,8 +264,9 @@
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);
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev