summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cpu/inorder/cpu.cc27
-rw-r--r--src/cpu/inorder/pipeline_stage.cc9
-rw-r--r--src/cpu/inorder/resources/fetch_seq_unit.cc26
-rw-r--r--src/cpu/inorder/thread_state.hh13
4 files changed, 51 insertions, 24 deletions
diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc
index 501150386..8d41a18b4 100644
--- a/src/cpu/inorder/cpu.cc
+++ b/src/cpu/inorder/cpu.cc
@@ -709,7 +709,9 @@ InOrderCPU::activateThread(ThreadID tid)
activeThreads.push_back(tid);
activateThreadInPipeline(tid);
-
+
+ thread[tid]->lastActivate = curTick;
+
wakeCPU();
}
}
@@ -888,6 +890,7 @@ InOrderCPU::suspendThread(ThreadID tid)
DPRINTF(InOrderCPU, "[tid: %i]: Placing on Suspended Threads List...\n", tid);
deactivateThread(tid);
suspendedThreads.push_back(tid);
+ thread[tid]->lastSuspend = curTick;
}
void
@@ -1063,15 +1066,22 @@ void
InOrderCPU::instDone(DynInstPtr inst, ThreadID tid)
{
// Set the CPU's PCs - This contributes to the precise state of the CPU
- // which can be used when restoring a thread to the CPU after a fork or
- // after an exception
- // =================
- // @TODO: Set-Up Grad-Info/Committed-Info to let ThreadState know if
- // it's a branch or not
+ // which can be used when restoring a thread to the CPU after after any
+ // type of context switching activity (fork, exception, etc.)
setPC(inst->readPC(), tid);
setNextPC(inst->readNextPC(), tid);
setNextNPC(inst->readNextNPC(), tid);
+ if (inst->isControl()) {
+ thread[tid]->lastGradIsBranch = true;
+ thread[tid]->lastBranchPC = inst->readPC();
+ thread[tid]->lastBranchNextPC = inst->readNextPC();
+ thread[tid]->lastBranchNextNPC = inst->readNextNPC();
+ } else {
+ thread[tid]->lastGradIsBranch = false;
+ }
+
+
// Finalize Trace Data For Instruction
if (inst->traceData) {
//inst->traceData->setCycle(curTick);
@@ -1082,9 +1092,6 @@ InOrderCPU::instDone(DynInstPtr inst, ThreadID tid)
inst->traceData = NULL;
}
- // Set Last Graduated Instruction In Thread State
- //thread[tid]->lastGradInst = inst;
-
// Increment thread-state's instruction count
thread[tid]->numInst++;
@@ -1108,7 +1115,7 @@ InOrderCPU::instDone(DynInstPtr inst, ThreadID tid)
// Broadcast to other resources an instruction
// has been completed
resPool->scheduleEvent((CPUEventType)ResourcePool::InstGraduated, inst,
- tid);
+ 0, 0, tid);
// Finally, remove instruction from CPU
removeInst(inst);
diff --git a/src/cpu/inorder/pipeline_stage.cc b/src/cpu/inorder/pipeline_stage.cc
index 620951e34..55ee3ad12 100644
--- a/src/cpu/inorder/pipeline_stage.cc
+++ b/src/cpu/inorder/pipeline_stage.cc
@@ -568,15 +568,18 @@ PipelineStage::activateThread(ThreadID tid)
} else {
DynInstPtr inst = switchedOutBuffer[tid];
- DPRINTF(InOrderStage,"[tid:%i]: Re-Inserting [sn:%lli] PC:%#x into stage skidBuffer %i\n",
- tid, inst->seqNum, inst->readPC(), inst->threadNumber);
+ DPRINTF(InOrderStage,"[tid:%i]: Re-Inserting [sn:%lli] PC:%#x into "
+ "stage skidBuffer %i\n", tid, inst->seqNum,
+ inst->readPC(), inst->threadNumber);
// Make instruction available for pipeline processing
skidBuffer[tid].push(inst);
// Update PC so that we start fetching after this instruction to prevent
// "double"-execution of instructions
- cpu->resPool->scheduleEvent((InOrderCPU::CPUEventType)ResourcePool::UpdateAfterContextSwitch, inst, 0, 0, tid);
+ cpu->resPool->scheduleEvent((InOrderCPU::CPUEventType)
+ ResourcePool::UpdateAfterContextSwitch,
+ inst, 0, 0, tid);
// Clear switchout buffer
switchedOutBuffer[tid] = NULL;
diff --git a/src/cpu/inorder/resources/fetch_seq_unit.cc b/src/cpu/inorder/resources/fetch_seq_unit.cc
index c217f972e..ba86a91f0 100644
--- a/src/cpu/inorder/resources/fetch_seq_unit.cc
+++ b/src/cpu/inorder/resources/fetch_seq_unit.cc
@@ -348,11 +348,23 @@ FetchSeqUnit::updateAfterContextSwitch(DynInstPtr inst, ThreadID tid)
{
pcValid[tid] = true;
- PC[tid] = inst->readNextPC();
- nextPC[tid] = inst->readNextNPC();
- nextNPC[tid] = inst->readNextNPC() + instSize;
-
-
- DPRINTF(InOrderFetchSeq, "[tid:%i]: Updating PC:%08p NPC:%08p NNPC:%08p.\n",
- tid, PC[tid], nextPC[tid], nextNPC[tid]);
+ if (cpu->thread[tid]->lastGradIsBranch) {
+ /** This function assumes that the instruction causing the context
+ * switch was right after the branch. Thus, if it's not, then
+ * we are updating incorrectly here
+ */
+ assert(cpu->thread[tid]->lastBranchNextPC == inst->readPC());
+
+ PC[tid] = cpu->thread[tid]->lastBranchNextNPC;
+ nextPC[tid] = PC[tid] + instSize;
+ nextNPC[tid] = nextPC[tid] + instSize;
+ } else {
+ PC[tid] = inst->readNextPC();
+ nextPC[tid] = inst->readNextNPC();
+ nextNPC[tid] = inst->readNextNPC() + instSize;
+ }
+
+ DPRINTF(InOrderFetchSeq, "[tid:%i]: Updating PCs due to Context Switch."
+ "Assigning PC:%08p NPC:%08p NNPC:%08p.\n", tid, PC[tid],
+ nextPC[tid], nextNPC[tid]);
}
diff --git a/src/cpu/inorder/thread_state.hh b/src/cpu/inorder/thread_state.hh
index 422df30aa..0a171a99f 100644
--- a/src/cpu/inorder/thread_state.hh
+++ b/src/cpu/inorder/thread_state.hh
@@ -79,14 +79,14 @@ class InOrderThreadState : public ThreadState {
#if FULL_SYSTEM
InOrderThreadState(InOrderCPU *_cpu, ThreadID _thread_num)
: ThreadState(reinterpret_cast<BaseCPU*>(_cpu), _thread_num),
- cpu(_cpu), inSyscall(0), trapPending(0)
+ cpu(_cpu), inSyscall(0), trapPending(0), lastGradIsBranch(false)
{ }
#else
InOrderThreadState(InOrderCPU *_cpu, ThreadID _thread_num,
Process *_process)
: ThreadState(reinterpret_cast<BaseCPU*>(_cpu), _thread_num,
_process),
- cpu(_cpu), inSyscall(0), trapPending(0)
+ cpu(_cpu), inSyscall(0), trapPending(0), lastGradIsBranch(false)
{ }
#endif
@@ -105,10 +105,15 @@ class InOrderThreadState : public ThreadState {
/** Returns a pointer to the TC of this thread. */
ThreadContext *getTC() { return tc; }
+ /** Return the thread id */
int readTid() { return threadId(); }
- /** Pointer to the last graduated instruction in the thread */
- //DynInstPtr lastGradInst;
+
+ /** Is last instruction graduated a branch? */
+ bool lastGradIsBranch;
+ Addr lastBranchPC;
+ Addr lastBranchNextPC;
+ Addr lastBranchNextNPC;
};
#endif // __CPU_INORDER_THREAD_STATE_HH__