inorder: dont handle multiple faults on same cycle
authorKorey Sewell <ksewell@umich.edu>
Mon, 20 Jun 2011 01:43:40 +0000 (21:43 -0400)
committerKorey Sewell <ksewell@umich.edu>
Mon, 20 Jun 2011 01:43:40 +0000 (21:43 -0400)
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.

16 files changed:
src/cpu/inorder/cpu.cc
src/cpu/inorder/cpu.hh
src/cpu/inorder/inorder_dyn_inst.cc
src/cpu/inorder/inorder_dyn_inst.hh
src/cpu/inorder/pipeline_stage.cc
src/cpu/inorder/resources/agen_unit.cc
src/cpu/inorder/resources/branch_predictor.cc
src/cpu/inorder/resources/cache_unit.cc
src/cpu/inorder/resources/decode_unit.cc
src/cpu/inorder/resources/execution_unit.cc
src/cpu/inorder/resources/fetch_seq_unit.cc
src/cpu/inorder/resources/fetch_unit.cc
src/cpu/inorder/resources/graduation_unit.cc
src/cpu/inorder/resources/graduation_unit.hh
src/cpu/inorder/resources/mult_div_unit.cc
src/cpu/inorder/resources/use_def.cc

index 2623c6c1db9f674e97cf484af6e96b6f8fe1f6c6..365b2f18a190f983149412c349f2d597bcc87898 100644 (file)
@@ -196,7 +196,6 @@ InOrderCPU::InOrderCPU(Params *params)
       timeBuffer(2 , 2),
       removeInstsThisCycle(false),
       activityRec(params->name, NumStages, 10, params->activity),
-      stCondFails(0),
 #if FULL_SYSTEM
       system(params->system),
 #endif // FULL_SYSTEM
@@ -372,7 +371,8 @@ InOrderCPU::InOrderCPU(Params *params)
 
     endOfSkedIt = skedCache.end();
     frontEndSked = createFrontEndSked();
-    
+    faultSked = createFaultSked();
+
     lastRunningCycle = curTick();
 
     lockAddr = 0;
@@ -417,8 +417,18 @@ InOrderCPU::createFrontEndSked()
     D.needs(FetchSeq, FetchSeqUnit::UpdateTargetPC);
 
 
-    DPRINTF(SkedCache, "Resource Sked created for instruction \"front_end\"\n");
+    DPRINTF(SkedCache, "Resource Sked created for instruction Front End\n");
+
+    return res_sked;
+}
 
+RSkedPtr
+InOrderCPU::createFaultSked()
+{
+    RSkedPtr res_sked = new ResourceSked();
+    StageScheduler W(res_sked, NumStages - 1);
+    W.needs(Grad, GraduationUnit::CheckFault);
+    DPRINTF(SkedCache, "Resource Sked created for instruction Faults\n");
     return res_sked;
 }
 
index 8a0f2167ba92aa303805cd03cb34481d8b56bba2..a1e92f302fe565efe45dec33594af9b4fe755342 100644 (file)
@@ -319,6 +319,7 @@ class InOrderCPU : public BaseCPU
     SkedCacheIt endOfSkedIt;
 
     ThePipeline::RSkedPtr frontEndSked;
+    ThePipeline::RSkedPtr faultSked;
 
     /** Add a new instruction schedule to the schedule cache */
     void addToSkedCache(DynInstPtr inst, ThePipeline::RSkedPtr inst_sked)
@@ -366,6 +367,7 @@ class InOrderCPU : public BaseCPU
     }
 
     ThePipeline::RSkedPtr createFrontEndSked();
+    ThePipeline::RSkedPtr createFaultSked();
     ThePipeline::RSkedPtr createBackEndSked(DynInstPtr inst);
 
     class StageScheduler {
@@ -751,7 +753,7 @@ class InOrderCPU : public BaseCPU
     virtual void wakeup();
 #endif
 
-    // LL/SC debug functionality
+    /* LL/SC debug functionality
     unsigned stCondFails;
 
     unsigned readStCondFailures() 
@@ -759,6 +761,7 @@ class InOrderCPU : public BaseCPU
 
     unsigned setStCondFailures(unsigned st_fails) 
     { return stCondFails = st_fails; }
+    */
 
     /** Returns a pointer to a thread context. */
     ThreadContext *tcBase(ThreadID tid = 0)
index 58280bf622ecf5604d532bfe92071727d5f11e13..7fbab4c7de211d5cc0c9f0c75fb1c01462c2046b 100644 (file)
@@ -87,6 +87,12 @@ InOrderDynInst::InOrderDynInst(InOrderCPU *cpu,
 
 int InOrderDynInst::instcount = 0;
 
+int
+InOrderDynInst::cpuId()
+{
+    return cpu->cpuId();
+}
+
 void
 InOrderDynInst::setMachInst(ExtMachInst machInst)
 {
@@ -330,7 +336,7 @@ InOrderDynInst::setSquashInfo(unsigned stage_num)
         squashSeqNum = seqNum;
 
 #if ISA_HAS_DELAY_SLOT
-    if (isControl()) {
+    if (staticInst && isControl()) {
         TheISA::PCState nextPC = pc;
         TheISA::advancePC(nextPC, staticInst);
 
index c896812d7aa1745de931e0cb501c7fbedd88085a..54c2e16c5be428d30d98c348e59273f77af38c0e 100644 (file)
@@ -355,6 +355,12 @@ class InOrderDynInst : public FastAlloc, public RefCounted
     /** Returns the fault type. */
     Fault getFault() { return fault; }
 
+    /** Read this CPU's ID. */
+    int cpuId();
+
+    /** Read this context's system-wide ID **/
+    int contextId() { return thread->contextId(); }
+
     ////////////////////////////////////////////////////////////
     //
     //  INSTRUCTION TYPES -  Forward checks to StaticInst object.
@@ -473,12 +479,12 @@ class InOrderDynInst : public FastAlloc, public RefCounted
         curSkedEntry++;
 
         if (inFrontEnd && curSkedEntry == frontSked_end) {
-          DPRINTF(InOrderDynInst, "[sn:%i] Switching to "
+            DPRINTF(InOrderDynInst, "[sn:%i] Switching to "
                   "back end schedule.\n", seqNum);
           assert(backSked != NULL);
-            curSkedEntry.init(backSked);
-            curSkedEntry = backSked->begin();
-            inFrontEnd = false;
+          curSkedEntry.init(backSked);
+          curSkedEntry = backSked->begin();
+          inFrontEnd = false;
         } else if (!inFrontEnd && curSkedEntry == backSked_end) {
             return true;
         }
@@ -915,6 +921,10 @@ class InOrderDynInst : public FastAlloc, public RefCounted
     virtual void setRegOtherThread(unsigned idx, const uint64_t &val,
                                    ThreadID tid = InvalidThreadID);
 
+    /** Returns the number of consecutive store conditional failures. */
+    unsigned readStCondFailures()
+    { return thread->storeCondFailures; }
+
     /** Sets the number of consecutive store conditional failures. */
     void setStCondFailures(unsigned sc_failures)
     { thread->storeCondFailures = sc_failures; }
index 3c945d31c871fc8f937f9bf5f6152d4e2d08fb00..ac180d3c0b4f02b09b98a58211408d7dc3d24b87 100644 (file)
@@ -130,6 +130,7 @@ PipelineStage::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
     timeBuffer = tb_ptr;
 
     // Setup wire to write information back to fetch.
+    // @todo: should this be writing to the next stage => -1 and reading from is (0)???
     toPrevStages = timeBuffer->getWire(0);
 
     // Create wires to get information from proper places in time buffer.
index 64f6d7544b55f83df178b62a93e535cd297ebf48..7be8a23f2c1bb070b1abc05e8bd865b5093408bc 100644 (file)
@@ -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:
index 3dea92cfbc1ea37cc44fa1fb31c73b282a277404..0dab5a70fce607c67bf3a0d7df3a44e674ffd73f 100644 (file)
@@ -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);
index 41429510d2ca91df2db2efe695cb4d413497e8db..7c8ad6905164e46aa9450534b31bb25c574e4b1d 100644 (file)
@@ -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);
index d15428436374f67cf1cf9a70b27ccb59bbb74fc5..a3548edfc6af89c039dfd6679a3fa3e9f3721c9d 100644 (file)
@@ -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,
index 460ec32fe54f711b2b3048fe36185ba6714d32c1..c1945488c623df428742ae3d507e9eae2358da9a 100644 (file)
@@ -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();
index 58e466e13e52c69537e345f003bcfd88c128f548..71507e2d813fbbf95f17512dceb486d91a4af516 100644 (file)
@@ -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]);
 }
index 958d69b34c09df8eb1f02dd44912184a85cff956..85411ae28a599d9b2a582f12f7eb2c7a6976d2e4 100644 (file)
@@ -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);
index 617ef14f67d2a17f89ece41b2a98ebc1996ed911..ebcf40c6a0bd914d18dae8a82cf76c254db078d7 100644 (file)
@@ -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
index 01abae85bc37c482bf0b0854fbd968afa2dbf01c..836b568a66175e2740a4f78a436c60cad06f50a0 100644 (file)
@@ -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];
 };
 
index fc27276d50c241a6c14b4082035b66b19884c46d..0ff05252c04fc8bf468b3e0efdfaa48defeed9ad 100644 (file)
@@ -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)
index 78497f6e58020813756cf3bae69d4b9798976770..06591121e8ee1c956006c008a1f60c18aa19b05b 100644 (file)
@@ -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]) {