cpu: Unify SimpleCPU and O3 CPU serialization code

The O3 CPU used to copy its thread context to a SimpleThread in order
to do serialization. This was a bit of a hack involving two static
SimpleThread instances and a magic constructor that was only used by
the O3 CPU.

This patch moves the ThreadContext serialization code into two global
procedures that, in addition to the normal serialization parameters,
take a ThreadContext reference as a parameter. This allows us to reuse
the serialization code in all ThreadContext implementations.
This commit is contained in:
Andreas Sandberg 2013-01-07 13:05:44 -05:00
parent 6daada2701
commit 4ae02295d5
10 changed files with 116 additions and 85 deletions

View file

@ -160,21 +160,6 @@ InOrderThreadContext::regStats(const std::string &name)
}
}
void
InOrderThreadContext::serialize(std::ostream &os)
{
panic("serialize unimplemented");
}
void
InOrderThreadContext::unserialize(Checkpoint *cp, const std::string &section)
{
panic("unserialize unimplemented");
}
void
InOrderThreadContext::copyArchRegs(ThreadContext *src_tc)
{

View file

@ -191,12 +191,6 @@ class InOrderThreadContext : public ThreadContext
/** Registers statistics associated with this TC. */
void regStats(const std::string &name);
/** Serializes state. */
void serialize(std::ostream &os);
/** Unserializes state. */
void unserialize(Checkpoint *cp, const std::string &section);
/** Returns this thread's ID number. */
int getThreadNum() { return thread->threadId(); }

View file

@ -1097,16 +1097,9 @@ FullO3CPU<Impl>::serialize(std::ostream &os)
nameOut(os, csprintf("%s.tickEvent", name()));
tickEvent.serialize(os);
// Use SimpleThread's ability to checkpoint to make it easier to
// write out the registers. Also make this static so it doesn't
// get instantiated multiple times (causes a panic in statistics).
static SimpleThread temp;
ThreadID size = thread.size();
for (ThreadID i = 0; i < size; i++) {
for (ThreadID i = 0; i < thread.size(); i++) {
nameOut(os, csprintf("%s.xc.%i", name(), i));
temp.copyTC(thread[i]->getTC());
temp.serialize(os);
thread[i]->serialize(os);
}
}
@ -1119,16 +1112,11 @@ FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string &section)
BaseCPU::unserialize(cp, section);
tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
// Use SimpleThread's ability to checkpoint to make it easier to
// read in the registers. Also make this static so it doesn't
// get instantiated multiple times (causes a panic in statistics).
static SimpleThread temp;
ThreadID size = thread.size();
for (ThreadID i = 0; i < size; i++) {
temp.copyTC(thread[i]->getTC());
temp.unserialize(cp, csprintf("%s.xc.%i", section, i));
thread[i]->getTC()->copyArchRegs(temp.getTC());
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);
}
}

View file

@ -153,11 +153,6 @@ class O3ThreadContext : public ThreadContext
/** Registers statistics associated with this TC. */
virtual void regStats(const std::string &name);
/** Serializes state. */
virtual void serialize(std::ostream &os);
/** Unserializes state. */
virtual void unserialize(Checkpoint *cp, const std::string &section);
/** Reads the last tick that this thread was activated on. */
virtual Tick readLastActivate();
/** Reads the last tick that this thread was suspended on. */

View file

@ -158,22 +158,6 @@ O3ThreadContext<Impl>::regStats(const std::string &name)
}
}
template <class Impl>
void
O3ThreadContext<Impl>::serialize(std::ostream &os)
{
if (FullSystem && thread->kernelStats)
thread->kernelStats->serialize(os);
}
template <class Impl>
void
O3ThreadContext<Impl>::unserialize(Checkpoint *cp, const std::string &section)
{
if (FullSystem && thread->kernelStats)
thread->kernelStats->unserialize(cp, section);
}
template <class Impl>
Tick
O3ThreadContext<Impl>::readLastActivate()

View file

@ -1,4 +1,16 @@
/*
* Copyright (c) 2012 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
@ -99,6 +111,27 @@ struct O3ThreadState : public ThreadState {
profilePC = 3;
}
void serialize(std::ostream &os)
{
ThreadState::serialize(os);
// Use the ThreadContext serialization helper to serialize the
// TC.
::serialize(*tc, os);
}
void unserialize(Checkpoint *cp, const std::string &section)
{
// Prevent squashing - we don't have any instructions in
// flight that we need to squash since we just instantiated a
// clean system.
noSquashFromTC = true;
ThreadState::unserialize(cp, section);
// Use the ThreadContext serialization helper to unserialize
// the TC.
::unserialize(*tc, cp, section);
noSquashFromTC = false;
}
/** Pointer to the ThreadContext of this thread. */
ThreadContext *tc;

View file

@ -99,12 +99,6 @@ SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys,
kernelStats = new TheISA::Kernel::Statistics(system);
}
SimpleThread::SimpleThread()
: ThreadState(NULL, -1, NULL), isa(NULL)
{
tc = new ProxyThreadContext<SimpleThread>(this);
}
SimpleThread::~SimpleThread()
{
delete tc;
@ -175,10 +169,7 @@ void
SimpleThread::serialize(ostream &os)
{
ThreadState::serialize(os);
SERIALIZE_ARRAY(floatRegs.i, TheISA::NumFloatRegs);
SERIALIZE_ARRAY(intRegs, TheISA::NumIntRegs);
_pcState.serialize(os);
// thread_num and cpu_id are deterministic from the config
::serialize(*tc, os);
}
@ -186,10 +177,7 @@ void
SimpleThread::unserialize(Checkpoint *cp, const std::string &section)
{
ThreadState::unserialize(cp, section);
UNSERIALIZE_ARRAY(floatRegs.i, TheISA::NumFloatRegs);
UNSERIALIZE_ARRAY(intRegs, TheISA::NumIntRegs);
_pcState.unserialize(cp, section);
// thread_num and cpu_id are deterministic from the config
::unserialize(*tc, cp, section);
}
void

View file

@ -140,8 +140,6 @@ class SimpleThread : public ThreadState
Process *_process, TheISA::TLB *_itb, TheISA::TLB *_dtb,
TheISA::ISA *_isa);
SimpleThread();
virtual ~SimpleThread();
virtual void takeOverFrom(ThreadContext *oldContext);

View file

@ -1,4 +1,16 @@
/*
* Copyright (c) 2012 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
@ -78,3 +90,49 @@ ThreadContext::compare(ThreadContext *one, ThreadContext *two)
}
void
serialize(ThreadContext &tc, std::ostream &os)
{
using namespace TheISA;
FloatRegBits floatRegs[NumFloatRegs];
for (int i = 0; i < NumFloatRegs; ++i)
floatRegs[i] = tc.readFloatRegBitsFlat(i);
// This is a bit ugly, but needed to maintain backwards
// compatibility.
arrayParamOut(os, "floatRegs.i", floatRegs, NumFloatRegs);
IntReg intRegs[NumIntRegs];
for (int i = 0; i < NumIntRegs; ++i)
intRegs[i] = tc.readIntRegFlat(i);
SERIALIZE_ARRAY(intRegs, NumIntRegs);
tc.pcState().serialize(os);
// thread_num and cpu_id are deterministic from the config
}
void
unserialize(ThreadContext &tc, Checkpoint *cp, const std::string &section)
{
using namespace TheISA;
FloatRegBits floatRegs[NumFloatRegs];
// This is a bit ugly, but needed to maintain backwards
// compatibility.
arrayParamIn(cp, section, "floatRegs.i", floatRegs, NumFloatRegs);
for (int i = 0; i < NumFloatRegs; ++i)
tc.setFloatRegBitsFlat(i, floatRegs[i]);
IntReg intRegs[NumIntRegs];
UNSERIALIZE_ARRAY(intRegs, NumIntRegs);
for (int i = 0; i < NumIntRegs; ++i)
tc.setIntRegFlat(i, intRegs[i]);
PCState pcState;
pcState.unserialize(cp, section);
tc.pcState(pcState);
// thread_num and cpu_id are deterministic from the config
}

View file

@ -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
@ -177,9 +177,6 @@ class ThreadContext
virtual void regStats(const std::string &name) = 0;
virtual void serialize(std::ostream &os) = 0;
virtual void unserialize(Checkpoint *cp, const std::string &section) = 0;
virtual EndQuiesceEvent *getQuiesceEvent() = 0;
// Not necessarily the best location for these...
@ -369,10 +366,6 @@ class ProxyThreadContext : public ThreadContext
void regStats(const std::string &name) { actualTC->regStats(name); }
void serialize(std::ostream &os) { actualTC->serialize(os); }
void unserialize(Checkpoint *cp, const std::string &section)
{ actualTC->unserialize(cp, section); }
EndQuiesceEvent *getQuiesceEvent() { return actualTC->getQuiesceEvent(); }
Tick readLastActivate() { return actualTC->readLastActivate(); }
@ -473,4 +466,19 @@ class ProxyThreadContext : public ThreadContext
{ actualTC->setFloatRegBitsFlat(idx, val); }
};
/** @{ */
/**
* Thread context serialization helpers
*
* These helper functions provide a way to the data in a
* ThreadContext. They are provided as separate helper function since
* implementing them as members of the ThreadContext interface would
* be confusing when the ThreadContext is exported via a proxy.
*/
void serialize(ThreadContext &tc, std::ostream &os);
void unserialize(ThreadContext &tc, Checkpoint *cp, const std::string &section);
/** @} */
#endif