From 7dea79535c87b68b5fc6143190d09b8fc364f2aa Mon Sep 17 00:00:00 2001 From: Korey Sewell Date: Sun, 19 Jun 2011 21:43:36 -0400 Subject: inorder: implement trap handling --- src/cpu/inorder/resources/agen_unit.cc | 4 +- src/cpu/inorder/resources/cache_unit.cc | 10 ++- src/cpu/inorder/resources/execution_unit.cc | 8 +- src/cpu/inorder/resources/fetch_seq_unit.cc | 109 ++++++++++++++++----------- src/cpu/inorder/resources/fetch_seq_unit.hh | 11 +-- src/cpu/inorder/resources/fetch_unit.cc | 7 ++ src/cpu/inorder/resources/fetch_unit.hh | 2 + src/cpu/inorder/resources/graduation_unit.cc | 9 ++- 8 files changed, 101 insertions(+), 59 deletions(-) (limited to 'src/cpu/inorder/resources') diff --git a/src/cpu/inorder/resources/agen_unit.cc b/src/cpu/inorder/resources/agen_unit.cc index d87ca364d..64f6d7544 100644 --- a/src/cpu/inorder/resources/agen_unit.cc +++ b/src/cpu/inorder/resources/agen_unit.cc @@ -78,8 +78,8 @@ AGENUnit::execute(int slot_num) if (inst->fault == NoFault) { agen_req->done(); } else { - fatal("%s encountered while calculating address [sn:%i]", - inst->fault->name(), seq_num); + fatal("%s encountered while calculating address [sn:%i] %s", + inst->fault->name(), seq_num, inst->instName()); } agens++; diff --git a/src/cpu/inorder/resources/cache_unit.cc b/src/cpu/inorder/resources/cache_unit.cc index c1a3590be..760fdb134 100644 --- a/src/cpu/inorder/resources/cache_unit.cc +++ b/src/cpu/inorder/resources/cache_unit.cc @@ -441,9 +441,10 @@ CacheUnit::doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size, cache_req->tlbStall = true; + // schedule a time to process the tlb miss. + // latency hardcoded to 1 (for now), but will be updated + // when timing translation gets added in scheduleEvent(slot_idx, 1); - - cpu->trap(inst->fault, tid, inst); } else { DPRINTF(InOrderTLB, "[tid:%i]: [sn:%i] virt. addr %08p translated " "to phys. addr:%08p.\n", tid, inst->seqNum, @@ -1072,6 +1073,11 @@ CacheUnitEvent::process() CacheUnit* tlb_res = dynamic_cast(resource); assert(tlb_res); + //@todo: eventually, we should do a timing translation w/ + // hw page table walk on tlb miss + DPRINTF(Fault, "Handling Fault %s\n", inst->fault->name()); + inst->fault->invoke(tlb_res->cpu->tcBase(tid), inst->staticInst); + tlb_res->tlbBlocked[tid] = false; tlb_res->cpu->pipelineStage[stage_num]-> diff --git a/src/cpu/inorder/resources/execution_unit.cc b/src/cpu/inorder/resources/execution_unit.cc index 4363f125d..d7151add1 100644 --- a/src/cpu/inorder/resources/execution_unit.cc +++ b/src/cpu/inorder/resources/execution_unit.cc @@ -140,9 +140,10 @@ ExecutionUnit::execute(int slot_num) // Evaluate Branch fault = inst->execute(); executions++; - inst->setExecuted(); if (fault == NoFault) { + inst->setExecuted(); + if (inst->mispredicted()) { assert(inst->isControl()); @@ -190,7 +191,8 @@ ExecutionUnit::execute(int slot_num) exec_req->done(); } else { - warn("inst [sn:%i] had a %s fault", seq_num, fault->name()); + DPRINTF(Fault, "[tid:%i]:[sn:%i]: Fault %s found\n", + inst->readTid(), inst->seqNum, fault->name()); inst->fault = fault; exec_req->done(); } @@ -210,6 +212,8 @@ ExecutionUnit::execute(int slot_num) } else { DPRINTF(InOrderExecute, "[tid:%i]: [sn:%i]: had a %s " "fault.\n", inst->readTid(), seq_num, fault->name()); + DPRINTF(Fault, "[tid:%i]:[sn:%i]: Fault %s found\n", + inst->readTid(), inst->seqNum, fault->name()); inst->fault = fault; } diff --git a/src/cpu/inorder/resources/fetch_seq_unit.cc b/src/cpu/inorder/resources/fetch_seq_unit.cc index 62dbb452a..024f38fdd 100644 --- a/src/cpu/inorder/resources/fetch_seq_unit.cc +++ b/src/cpu/inorder/resources/fetch_seq_unit.cc @@ -127,7 +127,7 @@ FetchSeqUnit::execute(int slot_num) DPRINTF(InOrderFetchSeq, "[tid:%i] Setting up squash to " "start from stage %i, after [sn:%i].\n", - tid, stage_num, inst->bdelaySeqNum); + tid, stage_num, inst->squashSeqNum); } } else { DPRINTF(InOrderFetchSeq, "[tid:%i]: [sn:%i]: Ignoring branch " @@ -152,8 +152,8 @@ FetchSeqUnit::squash(DynInstPtr inst, int squash_stage, "stage %i.\n", tid, inst->instName(), inst->pcState(), squash_stage); - if (squashSeqNum[tid] <= squash_seq_num && - lastSquashCycle[tid] == curTick()) { + if (lastSquashCycle[tid] == curTick() && + squashSeqNum[tid] <= squash_seq_num) { DPRINTF(InOrderFetchSeq, "[tid:%i]: Ignoring squash from stage %i, " "since there is an outstanding squash that is older.\n", tid, squash_stage); @@ -161,57 +161,65 @@ FetchSeqUnit::squash(DynInstPtr inst, int squash_stage, squashSeqNum[tid] = squash_seq_num; lastSquashCycle[tid] = curTick(); - TheISA::PCState nextPC; - assert(inst->staticInst); - if (inst->isControl()) { - nextPC = inst->readPredTarg(); - - // If we are already fetching this PC then advance to next PC - // ======= - // This should handle ISAs w/delay slots and annulled delay - // slots to figure out which is the next PC to fetch after - // a mispredict - DynInstPtr bdelay_inst = NULL; - ListIt bdelay_it; - if (inst->onInstList) { - bdelay_it = inst->getInstListIt(); - bdelay_it++; - } else { - InstSeqNum branch_delay_num = inst->seqNum + 1; - bdelay_it = cpu->findInst(branch_delay_num, tid); - } + if (inst->fault != NoFault) { + // A Trap Caused This Fault and will update the pc state + // when done trapping + DPRINTF(InOrderFetchSeq, "[tid:%i] Blocking due to fault @ " + "[sn:%i].\n", inst->seqNum); + pcValid[tid] = false; + } else { + TheISA::PCState nextPC; + assert(inst->staticInst); + if (inst->isControl()) { + nextPC = inst->readPredTarg(); + + // If we are already fetching this PC then advance to next PC + // ======= + // This should handle ISAs w/delay slots and annulled delay + // slots to figure out which is the next PC to fetch after + // a mispredict + DynInstPtr bdelay_inst = NULL; + ListIt bdelay_it; + if (inst->onInstList) { + bdelay_it = inst->getInstListIt(); + bdelay_it++; + } else { + InstSeqNum branch_delay_num = inst->seqNum + 1; + bdelay_it = cpu->findInst(branch_delay_num, tid); + } - if (bdelay_it != cpu->instList[tid].end()) { - bdelay_inst = (*bdelay_it); - } + 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) { + DPRINTF(Resource, "Evaluating %s v. %s\n", + bdelay_inst->pc, nextPC); - if (bdelay_inst->pc.instAddr() == nextPC.instAddr()) { - advancePC(nextPC, inst->staticInst); - DPRINTF(Resource, "Advanced PC to %s\n", nextPC); + if (bdelay_inst->pc.instAddr() == nextPC.instAddr()) { + 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; + 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]) { - cpu->pipelineStage[pcBlockStage[tid]]-> - toPrevStages->stageUnblock[pcBlockStage[tid]][tid] = true; - } + // Unblock Any Stages Waiting for this information to be updated ... + if (!pcValid[tid]) { + cpu->pipelineStage[pcBlockStage[tid]]-> + toPrevStages->stageUnblock[pcBlockStage[tid]][tid] = true; + } - pcValid[tid] = true; - } + pcValid[tid] = true; + } + } Resource::squash(inst, squash_stage, squash_seq_num, tid); } @@ -272,6 +280,17 @@ FetchSeqUnit::suspendThread(ThreadID tid) deactivateThread(tid); } +void +FetchSeqUnit::trap(Fault fault, ThreadID tid, DynInstPtr inst) +{ + pcValid[tid] = true; + pc[tid] = cpu->pcState(tid); + DPRINTF(Fault, "[tid:%i]: Trap updating to PC: " + "%s.\n", tid, pc[tid]); + DPRINTF(InOrderFetchSeq, "[tid:%i]: Trap updating to PC: " + "%s.\n", tid, pc[tid]); +} + void FetchSeqUnit::updateAfterContextSwitch(DynInstPtr inst, ThreadID tid) { diff --git a/src/cpu/inorder/resources/fetch_seq_unit.hh b/src/cpu/inorder/resources/fetch_seq_unit.hh index 7c57fa17b..1cd0047e2 100644 --- a/src/cpu/inorder/resources/fetch_seq_unit.hh +++ b/src/cpu/inorder/resources/fetch_seq_unit.hh @@ -65,15 +65,12 @@ class FetchSeqUnit : public Resource { void updateAfterContextSwitch(DynInstPtr inst, ThreadID tid); - /** Override default Resource squash sequence. This actually, - * looks in the global communication buffer to get squash - * info - */ + /** Update to correct PC from a squash */ void squash(DynInstPtr inst, int squash_stage, - InstSeqNum squash_seq_num, ThreadID tid); + InstSeqNum squash_seq_num, ThreadID tid); - - inline void squashAfterInst(DynInstPtr inst, int stage_num, ThreadID tid); + /** Update to correct PC from a trap */ + void trap(Fault fault, ThreadID tid, DynInstPtr inst); protected: unsigned instSize; diff --git a/src/cpu/inorder/resources/fetch_unit.cc b/src/cpu/inorder/resources/fetch_unit.cc index 692f78c7b..60452bacd 100644 --- a/src/cpu/inorder/resources/fetch_unit.cc +++ b/src/cpu/inorder/resources/fetch_unit.cc @@ -111,6 +111,7 @@ FetchUnit::createMachInst(std::list::iterator fetch_it, predecoder.setTC(cpu->thread[tid]->getTC()); predecoder.moreBytes(instPC, inst->instAddr(), mach_inst); + assert(predecoder.extMachInstReady()); ext_inst = predecoder.getExtMachInst(instPC); inst->pcState(instPC); @@ -552,3 +553,9 @@ FetchUnit::squashCacheRequest(CacheReqPtr req_ptr) CacheUnit::squashCacheRequest(req_ptr); } +void +FetchUnit::trap(Fault fault, ThreadID tid, DynInstPtr inst) +{ + //@todo: per thread? + predecoder.reset(); +} diff --git a/src/cpu/inorder/resources/fetch_unit.hh b/src/cpu/inorder/resources/fetch_unit.hh index 3075e726d..d6e36419a 100644 --- a/src/cpu/inorder/resources/fetch_unit.hh +++ b/src/cpu/inorder/resources/fetch_unit.hh @@ -88,6 +88,8 @@ class FetchUnit : public CacheUnit /** Executes one of the commands from the "Command" enum */ void execute(int slot_num); + void trap(Fault fault, ThreadID tid, DynInstPtr inst); + private: void squashCacheRequest(CacheReqPtr req_ptr); diff --git a/src/cpu/inorder/resources/graduation_unit.cc b/src/cpu/inorder/resources/graduation_unit.cc index 826ed8e03..9c17db945 100644 --- a/src/cpu/inorder/resources/graduation_unit.cc +++ b/src/cpu/inorder/resources/graduation_unit.cc @@ -67,7 +67,14 @@ GraduationUnit::execute(int slot_num) // Handle Any Faults Before Graduating Instruction if (inst->fault != NoFault) { - cpu->trap(inst->fault, tid, inst); + DPRINTF(Fault, "[sn:%i]: fault %s found for %s\n", + inst->seqNum, inst->fault->name(), + inst->instName()); + inst->setSquashInfo(stage_num); + setupSquash(inst, stage_num, tid); + cpu->trapContext(inst->fault, tid, inst); + grad_req->done(false); + return; } DPRINTF(InOrderGraduation, -- cgit v1.2.3