summaryrefslogtreecommitdiff
path: root/src/cpu/simple
diff options
context:
space:
mode:
authorAndreas Sandberg <Andreas.Sandberg@ARM.com>2013-01-07 13:05:52 -0500
committerAndreas Sandberg <Andreas.Sandberg@ARM.com>2013-01-07 13:05:52 -0500
commit009970f59b86eac6c9a35eeb175dd9e3a3079d13 (patch)
tree03119f68fd1e03ff753954b63722b916b39f6737 /src/cpu/simple
parent5fb00e1df6b2b7d9db472d0c25765263ed1b839f (diff)
downloadgem5-009970f59b86eac6c9a35eeb175dd9e3a3079d13.tar.xz
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 (limited to 'src/cpu/simple')
-rw-r--r--src/cpu/simple/atomic.cc28
-rw-r--r--src/cpu/simple/base.cc21
-rw-r--r--src/cpu/simple/base.hh8
-rw-r--r--src/cpu/simple/timing.cc47
4 files changed, 47 insertions, 57 deletions
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 &section)
+BaseSimpleCPU::unserializeThread(Checkpoint *cp, const string &section,
+ 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 &section);
+ void serializeThread(std::ostream &os, ThreadID tid);
+ void unserializeThread(Checkpoint *cp, const std::string &section,
+ 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();
}