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
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")
#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"
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)
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();
return InvalidThreadID;
}
+
+void
+FirstStage::takeOverFrom()
+{
+ PipelineStage::takeOverFrom();
+
+ for(ThreadID tid = 0; tid < this->numThreads; tid++) {
+ stageStatus[tid] = Running;
+ }
+}
/** 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__
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.