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:
parent
aacc5cb205
commit
069b38c0d5
4 changed files with 51 additions and 24 deletions
|
@ -709,7 +709,9 @@ InOrderCPU::activateThread(ThreadID tid)
|
||||||
activeThreads.push_back(tid);
|
activeThreads.push_back(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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
*/
|
||||||
DPRINTF(InOrderFetchSeq, "[tid:%i]: Updating PC:%08p NPC:%08p NNPC:%08p.\n",
|
assert(cpu->thread[tid]->lastBranchNextPC == inst->readPC());
|
||||||
tid, PC[tid], nextPC[tid], nextNPC[tid]);
|
|
||||||
|
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]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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__
|
||||||
|
|
Loading…
Reference in a new issue