cpu: Enable fast-forwarding for MIPS InOrderCPU and O3CPU
A copyRegs() function is added to MIPS utilities to copy architectural state from the old CPU to the new CPU during fast-forwarding. This addition alone enables fast-forwarding for the o3 cpu model running MIPS. The patch also adds takeOverFrom() and drainResume() functions to the InOrderCPU to enable it to take over from another CPU. This change enables fast-forwarding for the inorder cpu model running MIPS, but not for Alpha. Committed by: Nilay Vaish <nilay@cs.wisc.edu>
This commit is contained in:
parent
a533f3f983
commit
919baa603d
7 changed files with 106 additions and 2 deletions
|
@ -241,7 +241,23 @@ initCPU(ThreadContext *tc, int cpuId)
|
||||||
void
|
void
|
||||||
copyRegs(ThreadContext *src, ThreadContext *dest)
|
copyRegs(ThreadContext *src, ThreadContext *dest)
|
||||||
{
|
{
|
||||||
panic("Copy Regs Not Implemented Yet\n");
|
// First loop through the integer registers.
|
||||||
|
for (int i = 0; i < NumIntRegs; i++)
|
||||||
|
dest->setIntRegFlat(i, src->readIntRegFlat(i));
|
||||||
|
|
||||||
|
// Then loop through the floating point registers.
|
||||||
|
for (int i = 0; i < NumFloatRegs; i++)
|
||||||
|
dest->setFloatRegFlat(i, src->readFloatRegFlat(i));
|
||||||
|
|
||||||
|
// Would need to add condition-code regs if implemented
|
||||||
|
assert(NumCCRegs == 0);
|
||||||
|
|
||||||
|
// Copy misc. registers
|
||||||
|
for (int i = 0; i < NumMiscRegs; i++)
|
||||||
|
dest->setMiscRegNoEffect(i, src->readMiscRegNoEffect(i));
|
||||||
|
|
||||||
|
// Copy over the PC State
|
||||||
|
dest->pcState(src->pcState());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -47,6 +47,10 @@ class InOrderCPU(BaseCPU):
|
||||||
def require_caches(cls):
|
def require_caches(cls):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def support_take_over(cls):
|
||||||
|
return True
|
||||||
|
|
||||||
threadModel = Param.ThreadModel('SMT', "Multithreading model (SE-MODE only)")
|
threadModel = Param.ThreadModel('SMT', "Multithreading model (SE-MODE only)")
|
||||||
|
|
||||||
cachePorts = Param.Unsigned(2, "Cache Ports")
|
cachePorts = Param.Unsigned(2, "Cache Ports")
|
||||||
|
|
|
@ -64,6 +64,7 @@
|
||||||
#include "cpu/simple_thread.hh"
|
#include "cpu/simple_thread.hh"
|
||||||
#include "cpu/thread_context.hh"
|
#include "cpu/thread_context.hh"
|
||||||
#include "debug/Activity.hh"
|
#include "debug/Activity.hh"
|
||||||
|
#include "debug/Drain.hh"
|
||||||
#include "debug/InOrderCPU.hh"
|
#include "debug/InOrderCPU.hh"
|
||||||
#include "debug/InOrderCachePort.hh"
|
#include "debug/InOrderCachePort.hh"
|
||||||
#include "debug/Interrupt.hh"
|
#include "debug/Interrupt.hh"
|
||||||
|
@ -1491,6 +1492,67 @@ InOrderCPU::updateContextSwitchStats()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
InOrderCPU::drainResume()
|
||||||
|
{
|
||||||
|
setDrainState(Drainable::Running);
|
||||||
|
if (switchedOut())
|
||||||
|
return;
|
||||||
|
|
||||||
|
DPRINTF(Drain, "Resuming...\n");
|
||||||
|
verifyMemoryMode();
|
||||||
|
|
||||||
|
assert(!tickEvent.scheduled());
|
||||||
|
|
||||||
|
// Activate threads and also signal the resource pool to activate
|
||||||
|
// the thread on all resources.
|
||||||
|
_status = Idle;
|
||||||
|
for (ThreadID i = 0; i < thread.size(); i++) {
|
||||||
|
if (thread[i]->status() == ThreadContext::Active) {
|
||||||
|
DPRINTF(Drain, "Activating thread: %i\n", i);
|
||||||
|
activateThread(i);
|
||||||
|
resPool->activateThread(i);
|
||||||
|
_status = Running;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
InOrderCPU::switchOut()
|
||||||
|
{
|
||||||
|
DPRINTF(InOrderCPU, "Switching out\n");
|
||||||
|
BaseCPU::switchOut();
|
||||||
|
|
||||||
|
activityRec.reset();
|
||||||
|
|
||||||
|
_status = SwitchedOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
InOrderCPU::takeOverFrom(BaseCPU *oldCPU)
|
||||||
|
{
|
||||||
|
BaseCPU::takeOverFrom(oldCPU);
|
||||||
|
|
||||||
|
// Call takeOverFrom() on each pipeline stage
|
||||||
|
for (int stNum=0; stNum < NumStages; stNum++) {
|
||||||
|
pipelineStage[stNum]->takeOverFrom();
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(!tickEvent.scheduled());
|
||||||
|
|
||||||
|
// Copy over the current instruction sequence numbers if we are
|
||||||
|
// taking over from another InOrderCPU.
|
||||||
|
InOrderCPU *oldIOCPU = dynamic_cast<InOrderCPU*>(oldCPU);
|
||||||
|
if (oldIOCPU) {
|
||||||
|
for (ThreadID tid = 0; tid < numThreads; tid++)
|
||||||
|
globalSeqNum[tid] = oldIOCPU->globalSeqNum[tid];
|
||||||
|
}
|
||||||
|
|
||||||
|
lastRunningCycle = curCycle();
|
||||||
|
_status = Idle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
InOrderCPU::instDone(DynInstPtr inst, ThreadID tid)
|
InOrderCPU::instDone(DynInstPtr inst, ThreadID tid)
|
||||||
{
|
{
|
||||||
|
|
|
@ -866,6 +866,15 @@ class InOrderCPU : public BaseCPU
|
||||||
Stats::Average instsPerCtxtSwitch;
|
Stats::Average instsPerCtxtSwitch;
|
||||||
Stats::Scalar numCtxtSwitches;
|
Stats::Scalar numCtxtSwitches;
|
||||||
|
|
||||||
|
/** Resumes execution after a drain. */
|
||||||
|
void drainResume();
|
||||||
|
|
||||||
|
/** Switches out this CPU. */
|
||||||
|
virtual void switchOut();
|
||||||
|
|
||||||
|
/** Takes over from another CPU. */
|
||||||
|
virtual void takeOverFrom(BaseCPU *oldCPU);
|
||||||
|
|
||||||
/** Update Thread , used for statistic purposes*/
|
/** Update Thread , used for statistic purposes*/
|
||||||
inline void tickThreadStats();
|
inline void tickThreadStats();
|
||||||
|
|
||||||
|
|
|
@ -277,3 +277,13 @@ FirstStage::roundRobin()
|
||||||
|
|
||||||
return InvalidThreadID;
|
return InvalidThreadID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FirstStage::takeOverFrom()
|
||||||
|
{
|
||||||
|
PipelineStage::takeOverFrom();
|
||||||
|
|
||||||
|
for(ThreadID tid = 0; tid < this->numThreads; tid++) {
|
||||||
|
stageStatus[tid] = Running;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -88,6 +88,9 @@ class FirstStage : public PipelineStage {
|
||||||
|
|
||||||
/** Return next thread given Round Robin Policy for Thread Fetching */
|
/** Return next thread given Round Robin Policy for Thread Fetching */
|
||||||
ThreadID roundRobin();
|
ThreadID roundRobin();
|
||||||
|
|
||||||
|
/** Takes over from another CPU's thread. */
|
||||||
|
void takeOverFrom();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __CPU_INORDER_FIRST_STAGE_HH__
|
#endif // __CPU_INORDER_FIRST_STAGE_HH__
|
||||||
|
|
|
@ -135,7 +135,7 @@ class PipelineStage
|
||||||
void switchOut();
|
void switchOut();
|
||||||
|
|
||||||
/** Takes over from another CPU's thread. */
|
/** Takes over from another CPU's thread. */
|
||||||
void takeOverFrom();
|
virtual void takeOverFrom();
|
||||||
|
|
||||||
/** Ticks stage, processing all input signals and executing as many
|
/** Ticks stage, processing all input signals and executing as many
|
||||||
* instructions as possible.
|
* instructions as possible.
|
||||||
|
|
Loading…
Reference in a new issue