diff options
-rw-r--r-- | src/arch/mips/utility.cc | 18 | ||||
-rw-r--r-- | src/cpu/inorder/InOrderCPU.py | 4 | ||||
-rw-r--r-- | src/cpu/inorder/cpu.cc | 62 | ||||
-rw-r--r-- | src/cpu/inorder/cpu.hh | 9 | ||||
-rw-r--r-- | src/cpu/inorder/first_stage.cc | 10 | ||||
-rw-r--r-- | src/cpu/inorder/first_stage.hh | 3 | ||||
-rw-r--r-- | src/cpu/inorder/pipeline_stage.hh | 2 |
7 files changed, 106 insertions, 2 deletions
diff --git a/src/arch/mips/utility.cc b/src/arch/mips/utility.cc index f84819756..ff410bad1 100644 --- a/src/arch/mips/utility.cc +++ b/src/arch/mips/utility.cc @@ -241,7 +241,23 @@ initCPU(ThreadContext *tc, int cpuId) void 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 diff --git a/src/cpu/inorder/InOrderCPU.py b/src/cpu/inorder/InOrderCPU.py index 4caf254c4..920b9cdc1 100644 --- a/src/cpu/inorder/InOrderCPU.py +++ b/src/cpu/inorder/InOrderCPU.py @@ -47,6 +47,10 @@ class InOrderCPU(BaseCPU): def require_caches(cls): return True + @classmethod + def support_take_over(cls): + return True + threadModel = Param.ThreadModel('SMT', "Multithreading model (SE-MODE only)") cachePorts = Param.Unsigned(2, "Cache Ports") diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc index 5a02f94d9..eecbd033e 100644 --- a/src/cpu/inorder/cpu.cc +++ b/src/cpu/inorder/cpu.cc @@ -64,6 +64,7 @@ #include "cpu/simple_thread.hh" #include "cpu/thread_context.hh" #include "debug/Activity.hh" +#include "debug/Drain.hh" #include "debug/InOrderCPU.hh" #include "debug/InOrderCachePort.hh" #include "debug/Interrupt.hh" @@ -1490,6 +1491,67 @@ InOrderCPU::updateContextSwitchStats() instsPerSwitch = 0; } + +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 InOrderCPU::instDone(DynInstPtr inst, ThreadID tid) diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh index 1183f6fc9..0104cb95f 100644 --- a/src/cpu/inorder/cpu.hh +++ b/src/cpu/inorder/cpu.hh @@ -866,6 +866,15 @@ class InOrderCPU : public BaseCPU Stats::Average instsPerCtxtSwitch; 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*/ inline void tickThreadStats(); diff --git a/src/cpu/inorder/first_stage.cc b/src/cpu/inorder/first_stage.cc index 20fd9169f..f59e89410 100644 --- a/src/cpu/inorder/first_stage.cc +++ b/src/cpu/inorder/first_stage.cc @@ -277,3 +277,13 @@ FirstStage::roundRobin() return InvalidThreadID; } + +void +FirstStage::takeOverFrom() +{ + PipelineStage::takeOverFrom(); + + for(ThreadID tid = 0; tid < this->numThreads; tid++) { + stageStatus[tid] = Running; + } +} diff --git a/src/cpu/inorder/first_stage.hh b/src/cpu/inorder/first_stage.hh index 44ffb9599..ae8b12102 100644 --- a/src/cpu/inorder/first_stage.hh +++ b/src/cpu/inorder/first_stage.hh @@ -88,6 +88,9 @@ class FirstStage : public PipelineStage { /** Return next thread given Round Robin Policy for Thread Fetching */ ThreadID roundRobin(); + + /** Takes over from another CPU's thread. */ + void takeOverFrom(); }; #endif // __CPU_INORDER_FIRST_STAGE_HH__ diff --git a/src/cpu/inorder/pipeline_stage.hh b/src/cpu/inorder/pipeline_stage.hh index 963d96afb..478561a8e 100644 --- a/src/cpu/inorder/pipeline_stage.hh +++ b/src/cpu/inorder/pipeline_stage.hh @@ -135,7 +135,7 @@ class PipelineStage void switchOut(); /** Takes over from another CPU's thread. */ - void takeOverFrom(); + virtual void takeOverFrom(); /** Ticks stage, processing all input signals and executing as many * instructions as possible. |