inorder: track last branch committed

when threads are switching in/out the CPU, we need to keep
track of special cases like branches. Add appropriate
variables in ThreadState t track this and then use
these variables when updating pc after context switch
This commit is contained in:
Korey Sewell 2010-01-31 18:27:58 -05:00
parent aacc5cb205
commit 069b38c0d5
4 changed files with 51 additions and 24 deletions

View file

@ -710,6 +710,8 @@ InOrderCPU::activateThread(ThreadID tid)
activateThreadInPipeline(tid); activateThreadInPipeline(tid);
thread[tid]->lastActivate = curTick;
wakeCPU(); wakeCPU();
} }
} }
@ -888,6 +890,7 @@ InOrderCPU::suspendThread(ThreadID tid)
DPRINTF(InOrderCPU, "[tid: %i]: Placing on Suspended Threads List...\n", tid); DPRINTF(InOrderCPU, "[tid: %i]: Placing on Suspended Threads List...\n", tid);
deactivateThread(tid); deactivateThread(tid);
suspendedThreads.push_back(tid); suspendedThreads.push_back(tid);
thread[tid]->lastSuspend = curTick;
} }
void void
@ -1063,15 +1066,22 @@ void
InOrderCPU::instDone(DynInstPtr inst, ThreadID tid) InOrderCPU::instDone(DynInstPtr inst, ThreadID tid)
{ {
// Set the CPU's PCs - This contributes to the precise state of the CPU // 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 // which can be used when restoring a thread to the CPU after after any
// after an exception // type of context switching activity (fork, exception, etc.)
// =================
// @TODO: Set-Up Grad-Info/Committed-Info to let ThreadState know if
// it's a branch or not
setPC(inst->readPC(), tid); setPC(inst->readPC(), tid);
setNextPC(inst->readNextPC(), tid); setNextPC(inst->readNextPC(), tid);
setNextNPC(inst->readNextNPC(), 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 // Finalize Trace Data For Instruction
if (inst->traceData) { if (inst->traceData) {
//inst->traceData->setCycle(curTick); //inst->traceData->setCycle(curTick);
@ -1082,9 +1092,6 @@ InOrderCPU::instDone(DynInstPtr inst, ThreadID tid)
inst->traceData = NULL; inst->traceData = NULL;
} }
// Set Last Graduated Instruction In Thread State
//thread[tid]->lastGradInst = inst;
// Increment thread-state's instruction count // Increment thread-state's instruction count
thread[tid]->numInst++; thread[tid]->numInst++;
@ -1108,7 +1115,7 @@ InOrderCPU::instDone(DynInstPtr inst, ThreadID tid)
// Broadcast to other resources an instruction // Broadcast to other resources an instruction
// has been completed // has been completed
resPool->scheduleEvent((CPUEventType)ResourcePool::InstGraduated, inst, resPool->scheduleEvent((CPUEventType)ResourcePool::InstGraduated, inst,
tid); 0, 0, tid);
// Finally, remove instruction from CPU // Finally, remove instruction from CPU
removeInst(inst); removeInst(inst);

View file

@ -568,15 +568,18 @@ PipelineStage::activateThread(ThreadID tid)
} else { } else {
DynInstPtr inst = switchedOutBuffer[tid]; DynInstPtr inst = switchedOutBuffer[tid];
DPRINTF(InOrderStage,"[tid:%i]: Re-Inserting [sn:%lli] PC:%#x into stage skidBuffer %i\n", DPRINTF(InOrderStage,"[tid:%i]: Re-Inserting [sn:%lli] PC:%#x into "
tid, inst->seqNum, inst->readPC(), inst->threadNumber); "stage skidBuffer %i\n", tid, inst->seqNum,
inst->readPC(), inst->threadNumber);
// Make instruction available for pipeline processing // Make instruction available for pipeline processing
skidBuffer[tid].push(inst); skidBuffer[tid].push(inst);
// Update PC so that we start fetching after this instruction to prevent // Update PC so that we start fetching after this instruction to prevent
// "double"-execution of instructions // "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 // Clear switchout buffer
switchedOutBuffer[tid] = NULL; switchedOutBuffer[tid] = NULL;

View file

@ -348,11 +348,23 @@ FetchSeqUnit::updateAfterContextSwitch(DynInstPtr inst, ThreadID tid)
{ {
pcValid[tid] = true; pcValid[tid] = true;
PC[tid] = inst->readNextPC(); if (cpu->thread[tid]->lastGradIsBranch) {
nextPC[tid] = inst->readNextNPC(); /** This function assumes that the instruction causing the context
nextNPC[tid] = inst->readNextNPC() + instSize; * 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 PC:%08p NPC:%08p NNPC:%08p.\n", DPRINTF(InOrderFetchSeq, "[tid:%i]: Updating PCs due to Context Switch."
tid, PC[tid], nextPC[tid], nextNPC[tid]); "Assigning PC:%08p NPC:%08p NNPC:%08p.\n", tid, PC[tid],
nextPC[tid], nextNPC[tid]);
} }

View file

@ -79,14 +79,14 @@ class InOrderThreadState : public ThreadState {
#if FULL_SYSTEM #if FULL_SYSTEM
InOrderThreadState(InOrderCPU *_cpu, ThreadID _thread_num) InOrderThreadState(InOrderCPU *_cpu, ThreadID _thread_num)
: ThreadState(reinterpret_cast<BaseCPU*>(_cpu), _thread_num), : ThreadState(reinterpret_cast<BaseCPU*>(_cpu), _thread_num),
cpu(_cpu), inSyscall(0), trapPending(0) cpu(_cpu), inSyscall(0), trapPending(0), lastGradIsBranch(false)
{ } { }
#else #else
InOrderThreadState(InOrderCPU *_cpu, ThreadID _thread_num, InOrderThreadState(InOrderCPU *_cpu, ThreadID _thread_num,
Process *_process) Process *_process)
: ThreadState(reinterpret_cast<BaseCPU*>(_cpu), _thread_num, : ThreadState(reinterpret_cast<BaseCPU*>(_cpu), _thread_num,
_process), _process),
cpu(_cpu), inSyscall(0), trapPending(0) cpu(_cpu), inSyscall(0), trapPending(0), lastGradIsBranch(false)
{ } { }
#endif #endif
@ -105,10 +105,15 @@ class InOrderThreadState : public ThreadState {
/** Returns a pointer to the TC of this thread. */ /** Returns a pointer to the TC of this thread. */
ThreadContext *getTC() { return tc; } ThreadContext *getTC() { return tc; }
/** Return the thread id */
int readTid() { return threadId(); } 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__ #endif // __CPU_INORDER_THREAD_STATE_HH__