diff options
author | Korey Sewell <ksewell@umich.edu> | 2011-06-19 21:43:40 -0400 |
---|---|---|
committer | Korey Sewell <ksewell@umich.edu> | 2011-06-19 21:43:40 -0400 |
commit | 561c33f0824a705cb360ecb4ae3bf8cfd490f007 (patch) | |
tree | 7fb92ebc9a8f09ceacb8ad8e60e60990a9939621 /src/cpu/inorder/resources | |
parent | c4deabfb97928f81acb0d66338426cb5f2687c37 (diff) | |
download | gem5-561c33f0824a705cb360ecb4ae3bf8cfd490f007.tar.xz |
inorder: dont handle multiple faults on same cycle
if a faulting instruction reaches an execution unit,
then ignore it and pass it through the pipeline.
Once we recognize the fault in the graduation unit,
dont allow a second fault to creep in on the same cycle.
Diffstat (limited to 'src/cpu/inorder/resources')
-rw-r--r-- | src/cpu/inorder/resources/agen_unit.cc | 9 | ||||
-rw-r--r-- | src/cpu/inorder/resources/branch_predictor.cc | 15 | ||||
-rw-r--r-- | src/cpu/inorder/resources/cache_unit.cc | 33 | ||||
-rw-r--r-- | src/cpu/inorder/resources/decode_unit.cc | 17 | ||||
-rw-r--r-- | src/cpu/inorder/resources/execution_unit.cc | 9 | ||||
-rw-r--r-- | src/cpu/inorder/resources/fetch_seq_unit.cc | 11 | ||||
-rw-r--r-- | src/cpu/inorder/resources/fetch_unit.cc | 20 | ||||
-rw-r--r-- | src/cpu/inorder/resources/graduation_unit.cc | 39 | ||||
-rw-r--r-- | src/cpu/inorder/resources/graduation_unit.hh | 4 | ||||
-rw-r--r-- | src/cpu/inorder/resources/mult_div_unit.cc | 10 | ||||
-rw-r--r-- | src/cpu/inorder/resources/use_def.cc | 14 |
11 files changed, 132 insertions, 49 deletions
diff --git a/src/cpu/inorder/resources/agen_unit.cc b/src/cpu/inorder/resources/agen_unit.cc index 64f6d7544..7be8a23f2 100644 --- a/src/cpu/inorder/resources/agen_unit.cc +++ b/src/cpu/inorder/resources/agen_unit.cc @@ -58,6 +58,15 @@ AGENUnit::execute(int slot_num) #endif InstSeqNum seq_num = inst->seqNum; + if (inst->fault != NoFault) { + DPRINTF(InOrderAGEN, + "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to " + "next stage.\n", tid, inst->seqNum, inst->fault->name(), + inst->pcState()); + agen_req->done(); + return; + } + switch (agen_req->cmd) { case GenerateAddr: diff --git a/src/cpu/inorder/resources/branch_predictor.cc b/src/cpu/inorder/resources/branch_predictor.cc index 3dea92cfb..0dab5a70f 100644 --- a/src/cpu/inorder/resources/branch_predictor.cc +++ b/src/cpu/inorder/resources/branch_predictor.cc @@ -68,8 +68,14 @@ BranchPredictor::execute(int slot_num) { ResourceRequest* bpred_req = reqs[slot_num]; DynInstPtr inst = bpred_req->inst; - ThreadID tid = inst->readTid(); - InstSeqNum seq_num = inst->seqNum; + if (inst->fault != NoFault) { + DPRINTF(InOrderBPred, + "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to " + "next stage.\n", inst->readTid(), inst->seqNum, inst->fault->name(), + inst->pcState()); + bpred_req->done(); + return; + } if (!inst->isControl()) { DPRINTF(Resource, "Ignoring %s, not a control inst.\n", @@ -78,7 +84,8 @@ BranchPredictor::execute(int slot_num) return; } - + ThreadID tid = inst->readTid(); + InstSeqNum seq_num = inst->seqNum; switch (bpred_req->cmd) { case PredictBranch: @@ -110,6 +117,8 @@ BranchPredictor::execute(int slot_num) inst->setBranchPred(predict_taken); } + //@todo: Check to see how hw_rei is handled here...how does PC,NPC get + // updated to compare mispredict against??? inst->setPredTarg(pred_PC); DPRINTF(InOrderBPred, "[tid:%i]: [sn:%i]: %s Predicted PC is " "%s.\n", tid, seq_num, inst->instName(), pred_PC); diff --git a/src/cpu/inorder/resources/cache_unit.cc b/src/cpu/inorder/resources/cache_unit.cc index 41429510d..7c8ad6905 100644 --- a/src/cpu/inorder/resources/cache_unit.cc +++ b/src/cpu/inorder/resources/cache_unit.cc @@ -395,7 +395,7 @@ CacheUnit::setupMemRequest(DynInstPtr inst, CacheReqPtr cache_req, if (cache_req->memReq == NULL) { cache_req->memReq = new Request(cpu->asid[tid], aligned_addr, acc_size, flags, - inst->instAddr(), cpu->readCpuId(), + inst->instAddr(), cpu->readCpuId(), //@todo: use context id tid); DPRINTF(InOrderCachePort, "[sn:%i] Created memReq @%x, ->%x\n", inst->seqNum, &cache_req->memReq, cache_req->memReq); @@ -685,6 +685,15 @@ CacheUnit::execute(int slot_num) } DynInstPtr inst = cache_req->inst; + if (inst->fault != NoFault) { + DPRINTF(InOrderCachePort, + "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to " + "next stage.\n", inst->readTid(), inst->seqNum, inst->fault->name(), + inst->getMemAddr()); + finishCacheUnitReq(inst, cache_req); + return; + } + #if TRACING_ON ThreadID tid = inst->readTid(); std::string acc_type = "write"; @@ -747,14 +756,6 @@ CacheUnit::execute(int slot_num) "[tid:%i]: [sn:%i]: Trying to Complete Data Read Access\n", tid, inst->seqNum); - if (inst->fault != NoFault) { - DPRINTF(InOrderCachePort, - "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to " - "next stage.\n", tid, inst->seqNum, inst->fault->name(), - inst->getMemAddr()); - finishCacheUnitReq(inst, cache_req); - return; - } //@todo: timing translations need to check here... assert(!inst->isInstPrefetch() && "Can't Handle Inst. Prefecthes"); @@ -774,14 +775,6 @@ CacheUnit::execute(int slot_num) "[tid:%i]: [sn:%i]: Trying to Complete Data Write Access\n", tid, inst->seqNum); - if (inst->fault != NoFault) { - DPRINTF(InOrderCachePort, - "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to ", - "next stage.\n", tid, inst->seqNum, inst->fault->name(), - inst->getMemAddr()); - finishCacheUnitReq(inst, cache_req); - return; - } //@todo: check that timing translation is finished here RequestPtr mem_req = cache_req->memReq; @@ -937,7 +930,7 @@ CacheUnit::doCacheAccess(DynInstPtr inst, uint64_t *write_res, if (mem_req->isLLSC()) { assert(cache_req->inst->isStoreConditional()); DPRINTF(InOrderCachePort, "Evaluating Store Conditional access\n"); - do_access = TheISA::handleLockedWrite(cpu, mem_req); + do_access = TheISA::handleLockedWrite(inst.get(), mem_req); } } @@ -1129,7 +1122,7 @@ CacheUnit::processCacheCompletion(PacketPtr pkt) DPRINTF(InOrderCachePort, "[tid:%u]: Handling Load-Linked for [sn:%u]\n", tid, inst->seqNum); - TheISA::handleLockedRead(cpu, cache_pkt->req); + TheISA::handleLockedRead(inst.get(), cache_pkt->req); } DPRINTF(InOrderCachePort, @@ -1280,7 +1273,7 @@ void CacheUnit::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num, ThreadID tid) { - if (tlbBlockSeqNum[tid] && + if (tlbBlocked[tid] && tlbBlockSeqNum[tid] > squash_seq_num) { DPRINTF(InOrderCachePort, "Releasing TLB Block due to " " squash after [sn:%i].\n", squash_seq_num); diff --git a/src/cpu/inorder/resources/decode_unit.cc b/src/cpu/inorder/resources/decode_unit.cc index d15428436..a3548edfc 100644 --- a/src/cpu/inorder/resources/decode_unit.cc +++ b/src/cpu/inorder/resources/decode_unit.cc @@ -59,13 +59,18 @@ DecodeUnit::execute(int slot_num) { case DecodeInst: { - assert(!inst->staticInst->isMacroop()); - DPRINTF(Decode,"Decoded instruction [sn:%i]: %s : 0x%x\n", - inst->seqNum, inst->instName(), - inst->staticInst->machInst); - - inst->setBackSked(cpu->createBackEndSked(inst)); + if (inst->fault != NoFault) { + inst->setBackSked(cpu->faultSked); + DPRINTF(Decode,"[tid:%i]: Fault found for instruction [sn:%i]\n", + inst->readTid(), inst->seqNum); + } else { + assert(!inst->staticInst->isMacroop()); + inst->setBackSked(cpu->createBackEndSked(inst)); + DPRINTF(Decode,"Decoded instruction [sn:%i]: %s : 0x%x\n", + inst->seqNum, inst->instName(), + inst->staticInst->machInst); + } if (inst->backSked != NULL) { DPRINTF(InOrderDecode, diff --git a/src/cpu/inorder/resources/execution_unit.cc b/src/cpu/inorder/resources/execution_unit.cc index 460ec32fe..c1945488c 100644 --- a/src/cpu/inorder/resources/execution_unit.cc +++ b/src/cpu/inorder/resources/execution_unit.cc @@ -87,6 +87,15 @@ ExecutionUnit::execute(int slot_num) { ResourceRequest* exec_req = reqs[slot_num]; DynInstPtr inst = reqs[slot_num]->inst; + if (inst->fault != NoFault) { + DPRINTF(InOrderExecute, + "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to " + "next stage.\n", inst->readTid(), inst->seqNum, inst->fault->name(), + inst->pcState()); + exec_req->done(); + return; + } + Fault fault = NoFault; Tick cur_tick = curTick(); unsigned stage_num = exec_req->getStageNum(); diff --git a/src/cpu/inorder/resources/fetch_seq_unit.cc b/src/cpu/inorder/resources/fetch_seq_unit.cc index 58e466e13..71507e2d8 100644 --- a/src/cpu/inorder/resources/fetch_seq_unit.cc +++ b/src/cpu/inorder/resources/fetch_seq_unit.cc @@ -81,6 +81,15 @@ FetchSeqUnit::execute(int slot_num) ThreadID tid = inst->readTid(); int stage_num = fs_req->getStageNum(); + if (inst->fault != NoFault) { + DPRINTF(InOrderFetchSeq, + "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to " + "next stage.\n", tid, inst->seqNum, inst->fault->name(), + inst->pcState()); + fs_req->done(); + return; + } + switch (fs_req->cmd) { case AssignNextPC: @@ -302,8 +311,6 @@ 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]); } diff --git a/src/cpu/inorder/resources/fetch_unit.cc b/src/cpu/inorder/resources/fetch_unit.cc index 958d69b34..85411ae28 100644 --- a/src/cpu/inorder/resources/fetch_unit.cc +++ b/src/cpu/inorder/resources/fetch_unit.cc @@ -247,7 +247,14 @@ FetchUnit::execute(int slot_num) Addr block_addr = cacheBlockAlign(inst->getMemAddr()); int asid = cpu->asid[tid]; - inst->fault = NoFault; + if (inst->fault != NoFault) { + DPRINTF(InOrderCachePort, + "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to " + "next stage.\n", tid, inst->seqNum, inst->fault->name(), + cacheBlockAlign(inst->getMemAddr())); + finishCacheUnitReq(inst, cache_req); + return; + } switch (cache_req->cmd) { @@ -295,7 +302,7 @@ FetchUnit::execute(int slot_num) return; } - doTLBAccess(inst, cache_req, cacheBlkSize, 0, TheISA::TLB::Execute); + doTLBAccess(inst, cache_req, cacheBlkSize, Request::INST_FETCH, TheISA::TLB::Execute); if (inst->fault == NoFault) { DPRINTF(InOrderCachePort, @@ -320,6 +327,15 @@ FetchUnit::execute(int slot_num) } case CompleteFetch: + if (inst->fault != NoFault) { + DPRINTF(InOrderCachePort, + "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to " + "next stage.\n", tid, inst->seqNum, inst->fault->name(), + inst->getMemAddr()); + finishCacheUnitReq(inst, cache_req); + return; + } + if (cache_req->fetchBufferFill) { // Block request if it's depending on a previous fetch, but it hasnt made it yet std::list<FetchBlock*>::iterator fetch_it = findBlock(fetchBuffer, asid, block_addr); diff --git a/src/cpu/inorder/resources/graduation_unit.cc b/src/cpu/inorder/resources/graduation_unit.cc index 617ef14f6..ebcf40c6a 100644 --- a/src/cpu/inorder/resources/graduation_unit.cc +++ b/src/cpu/inorder/resources/graduation_unit.cc @@ -37,12 +37,13 @@ using namespace ThePipeline; GraduationUnit::GraduationUnit(std::string res_name, int res_id, int res_width, int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params) - : Resource(res_name, res_id, res_width, res_latency, _cpu), - lastNonSpecTick(0) + : Resource(res_name, res_id, res_width, res_latency, _cpu) { for (ThreadID tid = 0; tid < ThePipeline::MaxThreads; tid++) { nonSpecInstActive[tid] = &cpu->nonSpecInstActive[tid]; nonSpecSeqNum[tid] = &cpu->nonSpecSeqNum[tid]; + lastNonSpecTick[tid] = 0; + lastFaultTick[tid] = 0; } } @@ -53,6 +54,25 @@ GraduationUnit::execute(int slot_num) DynInstPtr inst = reqs[slot_num]->inst; ThreadID tid = inst->readTid(); int stage_num = inst->curSkedEntry->stageNum; + Tick cur_tick = curTick(); + + //@todo: not the common case, anyway we can move this + // check to the stage and just ignore instructions + // after? + if (lastNonSpecTick[tid] == cur_tick) { + DPRINTF(InOrderGraduation, "Unable to graduate [sn:%i]. " + "Only 1 nonspec inst. per cycle can graduate.\n"); + grad_req->done(false); + return; + } + + if (lastFaultTick[tid] == cur_tick) { + DPRINTF(InOrderGraduation, "Unable to graduate [sn:%i]. " + "Only 1 fault can be handled per tick.\n"); + grad_req->done(false); + return; + } + switch (grad_req->cmd) { @@ -64,6 +84,7 @@ GraduationUnit::execute(int slot_num) tid, inst->seqNum, inst->fault->name(), inst->instName()); squashThenTrap(stage_num, inst); + lastFaultTick[tid] = cur_tick; grad_req->done(false); return; } @@ -76,13 +97,6 @@ GraduationUnit::execute(int slot_num) case GraduateInst: { - if (lastNonSpecTick == curTick()) { - DPRINTF(InOrderGraduation, "Unable to graduate [sn:%i]. " - "Only 1 nonspec inst. per cycle can graduate.\n"); - grad_req->done(false); - return; - } - DPRINTF(InOrderGraduation, "[tid:%i]:[sn:%i]: Graduating instruction %s.\n", tid, inst->seqNum, inst->staticInst->disassemble(inst->instAddr())); @@ -90,16 +104,19 @@ GraduationUnit::execute(int slot_num) // Release Non-Speculative "Block" on instructions that could not // execute because there was a non-speculative inst. active. // @TODO: Fix this functionality. Probably too conservative. + // Maybe it should be, non-spec. insts should block other + // non-spec insts because they can potentially be reading + // system state that will be changed by the 1st non-spec inst. if (inst->isNonSpeculative()) { *nonSpecInstActive[tid] = false; DPRINTF(InOrderGraduation, "[tid:%i] Non-speculative inst [sn:%i] graduated\n", tid, inst->seqNum); - lastNonSpecTick = curTick(); + lastNonSpecTick[tid] = cur_tick; } if (inst->traceData) { - inst->traceData->setStageCycle(stage_num, curTick()); + inst->traceData->setStageCycle(stage_num, cur_tick); } // Tell CPU that instruction is finished processing diff --git a/src/cpu/inorder/resources/graduation_unit.hh b/src/cpu/inorder/resources/graduation_unit.hh index 01abae85b..836b568a6 100644 --- a/src/cpu/inorder/resources/graduation_unit.hh +++ b/src/cpu/inorder/resources/graduation_unit.hh @@ -58,9 +58,9 @@ class GraduationUnit : public Resource { void execute(int slot_num); protected: - Tick lastNonSpecTick; + Tick lastNonSpecTick[ThePipeline::MaxThreads]; + Tick lastFaultTick[ThePipeline::MaxThreads]; bool *nonSpecInstActive[ThePipeline::MaxThreads]; - InstSeqNum *nonSpecSeqNum[ThePipeline::MaxThreads]; }; diff --git a/src/cpu/inorder/resources/mult_div_unit.cc b/src/cpu/inorder/resources/mult_div_unit.cc index fc27276d5..0ff05252c 100644 --- a/src/cpu/inorder/resources/mult_div_unit.cc +++ b/src/cpu/inorder/resources/mult_div_unit.cc @@ -192,7 +192,15 @@ MultDivUnit::execute(int slot_num) { ResourceRequest* mult_div_req = reqs[slot_num]; DynInstPtr inst = reqs[slot_num]->inst; - + if (inst->fault != NoFault) { + DPRINTF(InOrderMDU, + "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to " + "next stage.\n", inst->readTid(), inst->seqNum, inst->fault->name(), + inst->pcState()); + mult_div_req->done(); + return; + } + DPRINTF(InOrderMDU, "Executing [sn:%i] ...\n", slot_num); switch (mult_div_req->cmd) diff --git a/src/cpu/inorder/resources/use_def.cc b/src/cpu/inorder/resources/use_def.cc index 78497f6e5..06591121e 100644 --- a/src/cpu/inorder/resources/use_def.cc +++ b/src/cpu/inorder/resources/use_def.cc @@ -92,6 +92,9 @@ UseDefUnit::regStats() .desc("Total Accesses (Read+Write) to the FP Register File"); floatRegFileAccs = floatRegFileReads + floatRegFileWrites; + //@todo: add miscreg reads/writes + // add forwarding by type??? + regForwards .name(name() + ".regForwards") .desc("Number of Registers Read Through Forwarding Logic"); @@ -153,12 +156,19 @@ UseDefUnit::execute(int slot_idx) // for performance considerations UseDefRequest* ud_req = dynamic_cast<UseDefRequest*>(reqs[slot_idx]); assert(ud_req); - DynInstPtr inst = ud_req->inst; + if (inst->fault != NoFault) { + DPRINTF(InOrderUseDef, + "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to " + "next stage.\n", inst->readTid(), inst->seqNum, inst->fault->name(), + inst->pcState()); + ud_req->done(); + return; + } + ThreadID tid = inst->readTid(); InstSeqNum seq_num = inst->seqNum; int ud_idx = ud_req->useDefIdx; - // If there is a non-speculative instruction // in the pipeline then stall instructions here if (*nonSpecInstActive[tid] == true && seq_num > *nonSpecSeqNum[tid]) { |