activeThreads.push_back(tid);
activateThreadInPipeline(tid);
-
+
+ thread[tid]->lastActivate = curTick;
+
wakeCPU();
}
}
DPRINTF(InOrderCPU, "[tid: %i]: Placing on Suspended Threads List...\n", tid);
deactivateThread(tid);
suspendedThreads.push_back(tid);
+ thread[tid]->lastSuspend = curTick;
}
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);
inst->traceData = NULL;
}
- // Set Last Graduated Instruction In Thread State
- //thread[tid]->lastGradInst = inst;
-
// Increment thread-state's instruction count
thread[tid]->numInst++;
// 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);
} 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;
{
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]);
}
#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
/** 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__