summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/mips/utility.cc18
-rw-r--r--src/cpu/inorder/InOrderCPU.py4
-rw-r--r--src/cpu/inorder/cpu.cc62
-rw-r--r--src/cpu/inorder/cpu.hh9
-rw-r--r--src/cpu/inorder/first_stage.cc10
-rw-r--r--src/cpu/inorder/first_stage.hh3
-rw-r--r--src/cpu/inorder/pipeline_stage.hh2
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.