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);
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);

View file

@ -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;

View file

@ -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;
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 PC:%08p NPC:%08p NNPC:%08p.\n",
tid, PC[tid], nextPC[tid], nextNPC[tid]);
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]);
}

View file

@ -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__