inorder: check for interrupts each tick
use a dummy instruction to facilitate the squash after the interrupts trap
This commit is contained in:
parent
0bfdf342da
commit
f1c3691356
|
@ -350,6 +350,16 @@ InOrderCPU::InOrderCPU(Params *params)
|
||||||
asid[tid]);
|
asid[tid]);
|
||||||
|
|
||||||
dummyReq[tid] = new ResourceRequest(resPool->getResource(0));
|
dummyReq[tid] = new ResourceRequest(resPool->getResource(0));
|
||||||
|
|
||||||
|
#if FULL_SYSTEM
|
||||||
|
// Use this dummy inst to force squashing behind every instruction
|
||||||
|
// in pipeline
|
||||||
|
dummyTrapInst[tid] = new InOrderDynInst(this, NULL, 0, 0, 0);
|
||||||
|
dummyTrapInst[tid]->seqNum = 0;
|
||||||
|
dummyTrapInst[tid]->squashSeqNum = 0;
|
||||||
|
dummyTrapInst[tid]->setTid(tid);
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dummyReqInst = new InOrderDynInst(this, NULL, 0, 0, 0);
|
dummyReqInst = new InOrderDynInst(this, NULL, 0, 0, 0);
|
||||||
|
@ -687,6 +697,8 @@ InOrderCPU::tick()
|
||||||
pipes_idle = pipes_idle && pipelineStage[stNum]->idle;
|
pipes_idle = pipes_idle && pipelineStage[stNum]->idle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkForInterrupts();
|
||||||
|
|
||||||
if (pipes_idle)
|
if (pipes_idle)
|
||||||
idleCycles++;
|
idleCycles++;
|
||||||
else
|
else
|
||||||
|
@ -800,6 +812,43 @@ InOrderCPU::simPalCheck(int palFunc, ThreadID tid)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
InOrderCPU::checkForInterrupts()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < threadContexts.size(); i++) {
|
||||||
|
ThreadContext *tc = threadContexts[i];
|
||||||
|
|
||||||
|
if (interrupts->checkInterrupts(tc)) {
|
||||||
|
Fault interrupt = interrupts->getInterrupt(tc);
|
||||||
|
|
||||||
|
if (interrupt != NoFault) {
|
||||||
|
DPRINTF(Interrupt, "Processing Intterupt for [tid:%i].\n",
|
||||||
|
tc->threadId());
|
||||||
|
|
||||||
|
ThreadID tid = tc->threadId();
|
||||||
|
interrupts->updateIntrInfo(tc);
|
||||||
|
|
||||||
|
// Squash from Last Stage in Pipeline
|
||||||
|
unsigned last_stage = NumStages - 1;
|
||||||
|
dummyTrapInst[tid]->squashingStage = last_stage;
|
||||||
|
pipelineStage[last_stage]->setupSquash(dummyTrapInst[tid],
|
||||||
|
tid);
|
||||||
|
|
||||||
|
// By default, setupSquash will always squash from stage + 1
|
||||||
|
pipelineStage[BackEndStartStage - 1]->setupSquash(dummyTrapInst[tid],
|
||||||
|
tid);
|
||||||
|
|
||||||
|
// Schedule Squash Through-out Resource Pool
|
||||||
|
resPool->scheduleEvent(
|
||||||
|
(InOrderCPU::CPUEventType)ResourcePool::SquashAll,
|
||||||
|
dummyTrapInst[tid], 0);
|
||||||
|
|
||||||
|
// Finally, Setup Trap to happen at end of cycle
|
||||||
|
trapContext(interrupt, tid, dummyTrapInst[tid]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Fault
|
Fault
|
||||||
InOrderCPU::getInterrupts()
|
InOrderCPU::getInterrupts()
|
||||||
|
|
|
@ -253,6 +253,7 @@ class InOrderCPU : public BaseCPU
|
||||||
DynInstPtr dummyInst[ThePipeline::MaxThreads];
|
DynInstPtr dummyInst[ThePipeline::MaxThreads];
|
||||||
DynInstPtr dummyBufferInst;
|
DynInstPtr dummyBufferInst;
|
||||||
DynInstPtr dummyReqInst;
|
DynInstPtr dummyReqInst;
|
||||||
|
DynInstPtr dummyTrapInst[ThePipeline::MaxThreads];
|
||||||
|
|
||||||
/** Used by resources to signify a denied access to a resource. */
|
/** Used by resources to signify a denied access to a resource. */
|
||||||
ResourceRequest *dummyReq[ThePipeline::MaxThreads];
|
ResourceRequest *dummyReq[ThePipeline::MaxThreads];
|
||||||
|
@ -414,6 +415,8 @@ class InOrderCPU : public BaseCPU
|
||||||
|
|
||||||
bool simPalCheck(int palFunc, ThreadID tid);
|
bool simPalCheck(int palFunc, ThreadID tid);
|
||||||
|
|
||||||
|
void checkForInterrupts();
|
||||||
|
|
||||||
/** Returns the Fault for any valid interrupt. */
|
/** Returns the Fault for any valid interrupt. */
|
||||||
Fault getInterrupts();
|
Fault getInterrupts();
|
||||||
|
|
||||||
|
|
|
@ -364,9 +364,10 @@ PipelineStage::setupSquash(DynInstPtr inst, ThreadID tid)
|
||||||
toPrevStages->stageInfo[squash_stage][tid].doneSeqNum =
|
toPrevStages->stageInfo[squash_stage][tid].doneSeqNum =
|
||||||
squash_seq_num;
|
squash_seq_num;
|
||||||
|
|
||||||
DPRINTF(InOrderStage, "[tid:%i]: Squashing after [sn:%i], "
|
DPRINTF(InOrderStage, "[tid:%i]: Setting up squashing after "
|
||||||
"due to [sn:%i] %s.\n", tid, squash_seq_num,
|
"[sn:%i], due to [sn:%i] %s. Squash-Start-Stage:%i\n",
|
||||||
inst->seqNum, inst->instName());
|
tid, squash_seq_num, inst->seqNum, inst->instName(),
|
||||||
|
squash_stage);
|
||||||
|
|
||||||
// Save squash num for later stage use
|
// Save squash num for later stage use
|
||||||
cpu->lastSquashCycle[tid] = curTick();
|
cpu->lastSquashCycle[tid] = curTick();
|
||||||
|
|
|
@ -302,6 +302,8 @@ void
|
||||||
Resource::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num,
|
Resource::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num,
|
||||||
ThreadID tid)
|
ThreadID tid)
|
||||||
{
|
{
|
||||||
|
//@todo: check squash seq num before squashing. can save time going
|
||||||
|
// through this function.
|
||||||
for (int i = 0; i < width; i++) {
|
for (int i = 0; i < width; i++) {
|
||||||
ResReqPtr req_ptr = reqs[i];
|
ResReqPtr req_ptr = reqs[i];
|
||||||
DynInstPtr inst = req_ptr->getInst();
|
DynInstPtr inst = req_ptr->getInst();
|
||||||
|
|
|
@ -1248,7 +1248,8 @@ void
|
||||||
CacheUnit::squash(DynInstPtr inst, int stage_num,
|
CacheUnit::squash(DynInstPtr inst, int stage_num,
|
||||||
InstSeqNum squash_seq_num, ThreadID tid)
|
InstSeqNum squash_seq_num, ThreadID tid)
|
||||||
{
|
{
|
||||||
if (tlbBlockSeqNum[tid] > squash_seq_num) {
|
if (tlbBlockSeqNum[tid] &&
|
||||||
|
tlbBlockSeqNum[tid] > squash_seq_num) {
|
||||||
DPRINTF(InOrderCachePort, "Releasing TLB Block due to "
|
DPRINTF(InOrderCachePort, "Releasing TLB Block due to "
|
||||||
" squash after [sn:%i].\n", squash_seq_num);
|
" squash after [sn:%i].\n", squash_seq_num);
|
||||||
tlbBlocked[tid] = false;
|
tlbBlocked[tid] = false;
|
||||||
|
|
|
@ -49,6 +49,8 @@ FetchSeqUnit::FetchSeqUnit(std::string res_name, int res_id, int res_width,
|
||||||
pcValid[tid] = false;
|
pcValid[tid] = false;
|
||||||
pcBlockStage[tid] = 0;
|
pcBlockStage[tid] = 0;
|
||||||
|
|
||||||
|
//@todo: Use CPU's squashSeqNum here instead of maintaining our own
|
||||||
|
// state
|
||||||
squashSeqNum[tid] = (InstSeqNum)-1;
|
squashSeqNum[tid] = (InstSeqNum)-1;
|
||||||
lastSquashCycle[tid] = 0;
|
lastSquashCycle[tid] = 0;
|
||||||
}
|
}
|
||||||
|
@ -164,75 +166,77 @@ FetchSeqUnit::squash(DynInstPtr inst, int squash_stage,
|
||||||
squashSeqNum[tid] = squash_seq_num;
|
squashSeqNum[tid] = squash_seq_num;
|
||||||
lastSquashCycle[tid] = curTick();
|
lastSquashCycle[tid] = curTick();
|
||||||
|
|
||||||
if (inst->fault != NoFault) {
|
if (inst->staticInst) {
|
||||||
// A Trap Caused This Fault and will update the pc state
|
if (inst->fault != NoFault) {
|
||||||
// when done trapping
|
// A Trap Caused This Fault and will update the pc state
|
||||||
DPRINTF(InOrderFetchSeq, "[tid:%i] Blocking due to fault @ "
|
// when done trapping
|
||||||
"[sn:%i].%s %s \n", inst->seqNum,
|
DPRINTF(InOrderFetchSeq, "[tid:%i] Blocking due to fault @ "
|
||||||
inst->instName(), inst->pcState());
|
"[sn:%i].%s %s \n", inst->seqNum,
|
||||||
pcValid[tid] = false;
|
inst->instName(), inst->pcState());
|
||||||
} else {
|
pcValid[tid] = false;
|
||||||
TheISA::PCState nextPC;
|
} else {
|
||||||
assert(inst->staticInst);
|
TheISA::PCState nextPC;
|
||||||
if (inst->isControl()) {
|
assert(inst->staticInst);
|
||||||
nextPC = inst->readPredTarg();
|
if (inst->isControl()) {
|
||||||
|
nextPC = inst->readPredTarg();
|
||||||
|
|
||||||
// If we are already fetching this PC then advance to next PC
|
// If we are already fetching this PC then advance to next PC
|
||||||
// =======
|
// =======
|
||||||
// This should handle ISAs w/delay slots and annulled delay
|
// This should handle ISAs w/delay slots and annulled delay
|
||||||
// slots to figure out which is the next PC to fetch after
|
// slots to figure out which is the next PC to fetch after
|
||||||
// a mispredict
|
// a mispredict
|
||||||
DynInstPtr bdelay_inst = NULL;
|
DynInstPtr bdelay_inst = NULL;
|
||||||
ListIt bdelay_it;
|
ListIt bdelay_it;
|
||||||
if (inst->onInstList) {
|
if (inst->onInstList) {
|
||||||
bdelay_it = inst->getInstListIt();
|
bdelay_it = inst->getInstListIt();
|
||||||
bdelay_it++;
|
bdelay_it++;
|
||||||
} else {
|
} else {
|
||||||
InstSeqNum branch_delay_num = inst->seqNum + 1;
|
InstSeqNum branch_delay_num = inst->seqNum + 1;
|
||||||
bdelay_it = cpu->findInst(branch_delay_num, tid);
|
bdelay_it = cpu->findInst(branch_delay_num, tid);
|
||||||
}
|
|
||||||
|
|
||||||
if (bdelay_it != cpu->instList[tid].end()) {
|
|
||||||
bdelay_inst = (*bdelay_it);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bdelay_inst) {
|
|
||||||
DPRINTF(Resource, "Evaluating %s v. %s\n",
|
|
||||||
bdelay_inst->pc, nextPC);
|
|
||||||
|
|
||||||
if (bdelay_inst->pc.instAddr() == nextPC.instAddr()) {
|
|
||||||
bdelay_inst->pc = nextPC;
|
|
||||||
advancePC(nextPC, inst->staticInst);
|
|
||||||
DPRINTF(Resource, "Advanced PC to %s\n", nextPC);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bdelay_it != cpu->instList[tid].end()) {
|
||||||
|
bdelay_inst = (*bdelay_it);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bdelay_inst) {
|
||||||
|
DPRINTF(Resource, "Evaluating %s v. %s\n",
|
||||||
|
bdelay_inst->pc, nextPC);
|
||||||
|
|
||||||
|
if (bdelay_inst->pc.instAddr() == nextPC.instAddr()) {
|
||||||
|
bdelay_inst->pc = nextPC;
|
||||||
|
advancePC(nextPC, inst->staticInst);
|
||||||
|
DPRINTF(Resource, "Advanced PC to %s\n", nextPC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nextPC = inst->pcState();
|
||||||
|
advancePC(nextPC, inst->staticInst);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
nextPC = inst->pcState();
|
|
||||||
advancePC(nextPC, inst->staticInst);
|
DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC to %s.\n",
|
||||||
|
tid, nextPC);
|
||||||
|
pc[tid] = nextPC;
|
||||||
|
|
||||||
|
// Unblock Any Stages Waiting for this information to be updated ...
|
||||||
|
if (!pcValid[tid]) {
|
||||||
|
DPRINTF(InOrderFetchSeq, "[tid:%d]: Setting unblock signal "
|
||||||
|
"for stage %i.\n",
|
||||||
|
tid, pcBlockStage[tid]);
|
||||||
|
|
||||||
|
// Need to use "fromNextStages" instead of "toPrevStages"
|
||||||
|
// because the timebuffer will have already have advanced
|
||||||
|
// in the tick function and this squash function will happen after
|
||||||
|
// the tick
|
||||||
|
cpu->pipelineStage[pcBlockStage[tid]]->
|
||||||
|
fromNextStages->stageUnblock[pcBlockStage[tid]][tid] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pcValid[tid] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DPRINTF(InOrderFetchSeq, "[tid:%i]: Setting PC to %s.\n",
|
|
||||||
tid, nextPC);
|
|
||||||
pc[tid] = nextPC;
|
|
||||||
|
|
||||||
// Unblock Any Stages Waiting for this information to be updated ...
|
|
||||||
if (!pcValid[tid]) {
|
|
||||||
DPRINTF(InOrderFetchSeq, "[tid:%d]: Setting unblock signal "
|
|
||||||
"for stage %i.\n",
|
|
||||||
tid, pcBlockStage[tid]);
|
|
||||||
|
|
||||||
// Need to use "fromNextStages" instead of "toPrevStages"
|
|
||||||
// because the timebuffer will have already have advanced
|
|
||||||
// in the tick function and this squash function will happen after
|
|
||||||
// the tick
|
|
||||||
cpu->pipelineStage[pcBlockStage[tid]]->
|
|
||||||
fromNextStages->stageUnblock[pcBlockStage[tid]][tid] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pcValid[tid] = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Resource::squash(inst, squash_stage, squash_seq_num, tid);
|
Resource::squash(inst, squash_stage, squash_seq_num, tid);
|
||||||
}
|
}
|
||||||
|
@ -302,8 +306,6 @@ FetchSeqUnit::trap(Fault fault, ThreadID tid, DynInstPtr inst)
|
||||||
"%s.\n", tid, pc[tid]);
|
"%s.\n", tid, pc[tid]);
|
||||||
DPRINTF(InOrderFetchSeq, "[tid:%i]: Trap updating to PC: "
|
DPRINTF(InOrderFetchSeq, "[tid:%i]: Trap updating to PC: "
|
||||||
"%s.\n", tid, pc[tid]);
|
"%s.\n", tid, pc[tid]);
|
||||||
|
|
||||||
cpu->removePipelineStalls(tid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
Loading…
Reference in a new issue