Support serializing and unserializing in the O3 CPU. Also a few small fixes for draining/switching CPUs.
src/cpu/o3/commit_impl.hh:
Fix to clear drainPending variable on call to resume.
src/cpu/o3/cpu.cc:
src/cpu/o3/cpu.hh:
Support serializing and unserializing in the O3 CPU.
src/cpu/o3/lsq_impl.hh:
Be sure to say we have no stores to write back if the active thread list is empty.
src/cpu/simple_thread.cc:
src/cpu/simple_thread.hh:
Slightly change how SimpleThread is used to copy from other ThreadContexts.
--HG--
extra : convert_revision : 92a5109b3783a989d5b451036061ef82c56d3121
This commit is contained in:
@@ -377,6 +377,7 @@ template <class Impl>
|
||||
void
|
||||
DefaultCommit<Impl>::resume()
|
||||
{
|
||||
drainPending = false;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
|
||||
@@ -707,6 +707,47 @@ FullO3CPU<Impl>::haltContext(int tid)
|
||||
*/
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
FullO3CPU<Impl>::serialize(std::ostream &os)
|
||||
{
|
||||
SERIALIZE_ENUM(_status);
|
||||
BaseCPU::serialize(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;
|
||||
|
||||
for (int i = 0; i < thread.size(); i++) {
|
||||
nameOut(os, csprintf("%s.xc.%i", name(), i));
|
||||
temp.copyTC(thread[i]->getTC());
|
||||
temp.serialize(os);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
UNSERIALIZE_ENUM(_status);
|
||||
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;
|
||||
|
||||
for (int i = 0; i < thread.size(); i++) {
|
||||
temp.copyTC(thread[i]->getTC());
|
||||
temp.unserialize(cp, csprintf("%s.xc.%i", section, i));
|
||||
thread[i]->getTC()->copyArchRegs(temp.getTC());
|
||||
}
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
bool
|
||||
FullO3CPU<Impl>::drain(Event *drain_event)
|
||||
@@ -717,15 +758,16 @@ FullO3CPU<Impl>::drain(Event *drain_event)
|
||||
rename.drain();
|
||||
iew.drain();
|
||||
commit.drain();
|
||||
// A bit of a hack...set the drainEvent after all the drain()
|
||||
// calls have been made, that way if all of the stages drain
|
||||
// immediately, the signalDrained() function knows not to call
|
||||
// process on the drain event.
|
||||
drainEvent = drain_event;
|
||||
|
||||
// Wake the CPU and record activity so everything can drain out if
|
||||
// the CPU was not able to immediately drain.
|
||||
if (_status != Drained) {
|
||||
if (getState() != SimObject::DrainedTiming) {
|
||||
// A bit of a hack...set the drainEvent after all the drain()
|
||||
// calls have been made, that way if all of the stages drain
|
||||
// immediately, the signalDrained() function knows not to call
|
||||
// process on the drain event.
|
||||
drainEvent = drain_event;
|
||||
|
||||
wakeCPU();
|
||||
activityRec.activity();
|
||||
|
||||
@@ -739,14 +781,15 @@ template <class Impl>
|
||||
void
|
||||
FullO3CPU<Impl>::resume()
|
||||
{
|
||||
if (_status == SwitchedOut)
|
||||
return;
|
||||
fetch.resume();
|
||||
decode.resume();
|
||||
rename.resume();
|
||||
iew.resume();
|
||||
commit.resume();
|
||||
|
||||
if (_status == SwitchedOut || _status == Idle)
|
||||
return;
|
||||
|
||||
if (!tickEvent.scheduled())
|
||||
tickEvent.schedule(curTick);
|
||||
_status = Running;
|
||||
@@ -760,7 +803,7 @@ FullO3CPU<Impl>::signalDrained()
|
||||
if (tickEvent.scheduled())
|
||||
tickEvent.squash();
|
||||
|
||||
_status = Drained;
|
||||
changeState(SimObject::DrainedTiming);
|
||||
|
||||
if (drainEvent) {
|
||||
drainEvent->process();
|
||||
|
||||
@@ -111,7 +111,6 @@ class FullO3CPU : public BaseO3CPU
|
||||
Idle,
|
||||
Halted,
|
||||
Blocked,
|
||||
Drained,
|
||||
SwitchedOut
|
||||
};
|
||||
|
||||
@@ -266,6 +265,13 @@ class FullO3CPU : public BaseO3CPU
|
||||
/** Update The Order In Which We Process Threads. */
|
||||
void updateThreadPriority();
|
||||
|
||||
/** Serialize state. */
|
||||
virtual void serialize(std::ostream &os);
|
||||
|
||||
/** Unserialize from a checkpoint. */
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
public:
|
||||
/** Executes a syscall on this cycle.
|
||||
* ---------------------------------------
|
||||
* Note: this is a virtual function. CPU-Specific
|
||||
|
||||
@@ -502,6 +502,9 @@ LSQ<Impl>::hasStoresToWB()
|
||||
{
|
||||
list<unsigned>::iterator active_threads = (*activeThreads).begin();
|
||||
|
||||
if ((*activeThreads).empty())
|
||||
return false;
|
||||
|
||||
while (active_threads != (*activeThreads).end()) {
|
||||
unsigned tid = *active_threads++;
|
||||
if (!hasStoresToWB(tid))
|
||||
|
||||
@@ -125,7 +125,7 @@ SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num,
|
||||
|
||||
#endif
|
||||
|
||||
SimpleThread::SimpleThread(ThreadContext *oldContext)
|
||||
SimpleThread::SimpleThread()
|
||||
#if FULL_SYSTEM
|
||||
: ThreadState(-1, -1)
|
||||
#else
|
||||
@@ -134,19 +134,6 @@ SimpleThread::SimpleThread(ThreadContext *oldContext)
|
||||
{
|
||||
tc = new ProxyThreadContext<SimpleThread>(this);
|
||||
regs.clear();
|
||||
|
||||
copyState(oldContext);
|
||||
|
||||
#if FULL_SYSTEM
|
||||
EndQuiesceEvent *quiesce = oldContext->getQuiesceEvent();
|
||||
if (quiesce) {
|
||||
quiesceEvent = quiesce;
|
||||
}
|
||||
Kernel::Statistics *stats = oldContext->getKernelStats();
|
||||
if (stats) {
|
||||
kernelStats = stats;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SimpleThread::~SimpleThread()
|
||||
@@ -182,6 +169,23 @@ SimpleThread::takeOverFrom(ThreadContext *oldContext)
|
||||
oldContext->setStatus(ThreadContext::Unallocated);
|
||||
}
|
||||
|
||||
void
|
||||
SimpleThread::copyTC(ThreadContext *context)
|
||||
{
|
||||
copyState(context);
|
||||
|
||||
#if FULL_SYSTEM
|
||||
EndQuiesceEvent *quiesce = context->getQuiesceEvent();
|
||||
if (quiesce) {
|
||||
quiesceEvent = quiesce;
|
||||
}
|
||||
Kernel::Statistics *stats = context->getKernelStats();
|
||||
if (stats) {
|
||||
kernelStats = stats;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
SimpleThread::copyState(ThreadContext *oldContext)
|
||||
{
|
||||
|
||||
@@ -121,7 +121,7 @@ class SimpleThread : public ThreadState
|
||||
MemObject *memobj);
|
||||
#endif
|
||||
|
||||
SimpleThread(ThreadContext *oldContext);
|
||||
SimpleThread();
|
||||
|
||||
virtual ~SimpleThread();
|
||||
|
||||
@@ -129,6 +129,8 @@ class SimpleThread : public ThreadState
|
||||
|
||||
void regStats(const std::string &name);
|
||||
|
||||
void copyTC(ThreadContext *context);
|
||||
|
||||
void copyState(ThreadContext *oldContext);
|
||||
|
||||
void serialize(std::ostream &os);
|
||||
|
||||
Reference in New Issue
Block a user