inorder: implement trap handling
authorKorey Sewell <ksewell@umich.edu>
Mon, 20 Jun 2011 01:43:36 +0000 (21:43 -0400)
committerKorey Sewell <ksewell@umich.edu>
Mon, 20 Jun 2011 01:43:36 +0000 (21:43 -0400)
19 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/pipeline_stage.hh
src/cpu/inorder/resource.cc
src/cpu/inorder/resource.hh
src/cpu/inorder/resource_pool.9stage.cc
src/cpu/inorder/resource_pool.cc
src/cpu/inorder/resource_pool.hh
src/cpu/inorder/resources/agen_unit.cc
src/cpu/inorder/resources/cache_unit.cc
src/cpu/inorder/resources/execution_unit.cc
src/cpu/inorder/resources/fetch_seq_unit.cc
src/cpu/inorder/resources/fetch_seq_unit.hh
src/cpu/inorder/resources/fetch_unit.cc
src/cpu/inorder/resources/fetch_unit.hh
src/cpu/inorder/resources/graduation_unit.cc

index 2e3b0188b04f5b3e4c91c8c2b637086291e38853..e0e4d9a158c486b9463371e6adf22b8f61b08493 100644 (file)
@@ -142,7 +142,8 @@ InOrderCPU::CPUEvent::process()
 
       case Trap:
         DPRINTF(InOrderCPU, "Trapping CPU\n");
-        cpu->trapCPU(fault, tid, inst);
+        cpu->trap(fault, tid, inst);
+        cpu->resPool->trap(fault, tid, inst);
         break;
 
       default:
@@ -451,8 +452,8 @@ InOrderCPU::createBackEndSked(DynInstPtr inst)
             if (inst->splitInst)
                 M.needs(DCache, CacheUnit::InitSecondSplitRead);
         } else if ( inst->isStore() ) {
-            if ( inst->numSrcRegs() >= 2 ) {
-                M.needs(RegManager, UseDefUnit::ReadSrcReg, 1);
+            for (int i = 1; i < inst->numSrcRegs(); i++ ) {
+                M.needs(RegManager, UseDefUnit::ReadSrcReg, i);
             }
             M.needs(AGEN, AGENUnit::GenerateAddr);
             M.needs(DCache, CacheUnit::InitiateWriteData);
@@ -795,14 +796,13 @@ InOrderCPU::updateMemPorts()
 #endif
 
 void
-InOrderCPU::trap(Fault fault, ThreadID tid, DynInstPtr inst, int delay)
+InOrderCPU::trapContext(Fault fault, ThreadID tid, DynInstPtr inst, int delay)
 {
-    //@ Squash Pipeline during TRAP
     scheduleCpuEvent(Trap, fault, tid, inst, delay);
 }
 
 void
-InOrderCPU::trapCPU(Fault fault, ThreadID tid, DynInstPtr inst)
+InOrderCPU::trap(Fault fault, ThreadID tid, DynInstPtr inst)
 {
     fault->invoke(tcBase(tid), inst->staticInst);
 }
@@ -1302,11 +1302,18 @@ InOrderCPU::updateContextSwitchStats()
 void
 InOrderCPU::instDone(DynInstPtr inst, ThreadID tid)
 {
-    // Set the CPU's PCs - This contributes to the precise state of the CPU 
+    // Set the nextPC to be fetched if this is the last instruction
+    // committed
+    // ========
+    // This contributes to the precise state of the CPU
     // which can be used when restoring a thread to the CPU after after any
     // type of context switching activity (fork, exception, etc.)
-    pcState(inst->pcState(), tid);
+    TheISA::PCState comm_pc = inst->pcState();
+    lastCommittedPC[tid] = comm_pc;
+    TheISA::advancePC(comm_pc, inst->staticInst);
+    pcState(comm_pc, tid);
 
+    //@todo: may be unnecessary with new-ISA-specific branch handling code
     if (inst->isControl()) {
         thread[tid]->lastGradIsBranch = true;
         thread[tid]->lastBranchPC = inst->pcState();
index aad701ff4d8b94e4f0fac89f1d7343541208384f..f60258c963c216950634a98830cd153fc6fc9820 100644 (file)
@@ -275,6 +275,9 @@ class InOrderCPU : public BaseCPU
     /** Program Counters */
     TheISA::PCState pc[ThePipeline::MaxThreads];
 
+    /** Last Committed PC */
+    TheISA::PCState lastCommittedPC[ThePipeline::MaxThreads];
+
     /** The Register File for the CPU */
     union {
         FloatReg f[ThePipeline::MaxThreads][TheISA::NumFloatRegs];
@@ -430,33 +433,45 @@ class InOrderCPU : public BaseCPU
     bool validDataAddr(Addr addr) { return true; }
 #endif
 
-    /** trap() - sets up a trap event on the cpuTraps to handle given fault.
-     *  trapCPU() - Traps to handle given fault
-     */
-    void trap(Fault fault, ThreadID tid, DynInstPtr inst, int delay = 0);
-    void trapCPU(Fault fault, ThreadID tid, DynInstPtr inst);
+    /** Schedule a trap on the CPU */
+    void trapContext(Fault fault, ThreadID tid, DynInstPtr inst, int delay = 0);
 
-    /** Add Thread to Active Threads List. */
+    /** Perform trap to Handle Given Fault */
+    void trap(Fault fault, ThreadID tid, DynInstPtr inst);
+
+    /** Schedule thread activation on the CPU */
     void activateContext(ThreadID tid, int delay = 0);
+
+    /** Add Thread to Active Threads List. */
     void activateThread(ThreadID tid);
+
+    /** Activate Thread In Each Pipeline Stage */
     void activateThreadInPipeline(ThreadID tid);
     
-    /** Add Thread to Active Threads List. */
+    /** Schedule Thread Activation from Ready List */
     void activateNextReadyContext(int delay = 0);
+
+    /** Add Thread From Ready List to Active Threads List. */
     void activateNextReadyThread();
 
-    /** Remove from Active Thread List */
+    /** Schedule a thread deactivation on the CPU */
     void deactivateContext(ThreadID tid, int delay = 0);
+
+    /** Remove from Active Thread List */
     void deactivateThread(ThreadID tid);
 
-    /** Suspend Thread, Remove from Active Threads List, Add to Suspend List */
+    /** Schedule a thread suspension on the CPU */
     void suspendContext(ThreadID tid, int delay = 0);
+
+    /** Suspend Thread, Remove from Active Threads List, Add to Suspend List */
     void suspendThread(ThreadID tid);
 
+    /** Schedule a thread halt on the CPU */
+    void haltContext(ThreadID tid, int delay = 0);
+
     /** Halt Thread, Remove from Active Thread List, Place Thread on Halted 
      *  Threads List 
      */
-    void haltContext(ThreadID tid, int delay = 0);
     void haltThread(ThreadID tid);
 
     /** squashFromMemStall() - sets up a squash event
index d8bfbacc7a333e82d9d3e75e0ebad47441ef1c6d..d42e840162eaf867ace780a2d27899bd9f5a1b27 100644 (file)
@@ -54,7 +54,7 @@ InOrderDynInst::InOrderDynInst(InOrderCPU *cpu,
                                InstSeqNum seq_num,
                                ThreadID tid,
                                unsigned _asid)
-  : seqNum(seq_num), bdelaySeqNum(0), threadNumber(tid), asid(_asid),
+  : seqNum(seq_num), squashSeqNum(0), threadNumber(tid), asid(_asid),
     virtProcNumber(0), staticInst(NULL), traceData(NULL), cpu(cpu),
     thread(state), fault(NoFault), memData(NULL), loadData(0),
     storeData(0), effAddr(0), physEffAddr(0), memReqFlags(0),
@@ -319,7 +319,15 @@ void
 InOrderDynInst::setSquashInfo(unsigned stage_num)
 {
     squashingStage = stage_num;
-    bdelaySeqNum = seqNum;
+
+    // If it's a fault, then we need to squash
+    // the faulting instruction too. Squash
+    // functions squash above a seqNum, so we
+    // decrement here for that case
+    if (fault != NoFault)
+        squashSeqNum = seqNum - 1;
+    else
+        squashSeqNum = seqNum;
 
 #if ISA_HAS_DELAY_SLOT
     if (isControl()) {
@@ -329,10 +337,9 @@ InOrderDynInst::setSquashInfo(unsigned stage_num)
         // Check to see if we should squash after the
         // branch or after a branch delay slot.
         if (pc.nextInstAddr() == pc.instAddr() + sizeof(MachInst))
-            bdelaySeqNum = seqNum + 1;
+            squashSeqNum = seqNum + 1;
         else
-            bdelaySeqNum = seqNum;
-
+            squashSeqNum = seqNum;
     }
 #endif
 }
index 73e723312b295e3ad4d5341d0a209d710106aa09..0776dc5aa76a27ab1905f9664736b6f6f833b789 100644 (file)
@@ -122,8 +122,8 @@ class InOrderDynInst : public FastAlloc, public RefCounted
     /** The sequence number of the instruction. */
     InstSeqNum seqNum;
 
-    /** The sequence number of the instruction. */
-    InstSeqNum bdelaySeqNum;
+    /** If this instruction is squashing, the number should we squash behind. */
+    InstSeqNum squashSeqNum;
 
     enum Status {
         RegDepMapEntry,          /// Instruction is entered onto the RegDepMap
index 51e16b6c47404de53c0e4aa3e7311ee2a86d4ac3..d37779ce8eb5ed5237c5c850210ac6103cff2b2e 100644 (file)
@@ -342,43 +342,27 @@ PipelineStage::unblock(ThreadID tid)
 }
 
 void
-PipelineStage::squashDueToBranch(DynInstPtr &inst, ThreadID tid)
+PipelineStage::setupSquash(DynInstPtr inst, ThreadID tid)
 {
-    if (cpu->squashSeqNum[tid] < inst->seqNum &&
-        cpu->lastSquashCycle[tid] == curTick()){
+    if (cpu->lastSquashCycle[tid] == curTick() &&
+        cpu->squashSeqNum[tid] < inst->seqNum){
         DPRINTF(Resource, "Ignoring [sn:%i] branch squash signal due to "
                 "another stage's squash signal for after [sn:%i].\n", 
                 inst->seqNum, cpu->squashSeqNum[tid]);
     } else {
-        // Send back mispredict information.
-        toPrevStages->stageInfo[stageNum][tid].branchMispredict = true;
-        toPrevStages->stageInfo[stageNum][tid].predIncorrect = true;
-        toPrevStages->stageInfo[stageNum][tid].doneSeqNum = inst->seqNum;
-        toPrevStages->stageInfo[stageNum][tid].squash = true;
-        toPrevStages->stageInfo[stageNum][tid].nextPC = inst->readPredTarg();
-
-        toPrevStages->stageInfo[stageNum][tid].branchTaken =
-            inst->pcState().branching();
-
-#if ISA_HAS_DELAY_SLOT
-        toPrevStages->stageInfo[stageNum][tid].bdelayDoneSeqNum =
-            inst->bdelaySeqNum;
+        InstSeqNum squash_seq_num = inst->squashSeqNum;
 
-        InstSeqNum squash_seq_num = inst->bdelaySeqNum;
-#else
-        toPrevStages->stageInfo[stageNum][tid].bdelayDoneSeqNum = inst->seqNum;
-        InstSeqNum squash_seq_num = inst->seqNum;
-#endif
+        toPrevStages->stageInfo[stageNum][tid].squash = true;
+        toPrevStages->stageInfo[stageNum][tid].doneSeqNum =
+            squash_seq_num;
 
-        DPRINTF(InOrderStage, "Target being re-set to %08p\n", 
-                inst->predInstAddr());
         DPRINTF(InOrderStage, "[tid:%i]: Squashing after [sn:%i], "
-                "due to [sn:%i] branch.\n", tid, squash_seq_num, 
-                inst->seqNum);
+                "due to [sn:%i] %s.\n", tid, squash_seq_num,
+                inst->seqNum, inst->instName());
 
         // Save squash num for later stage use
-        cpu->squashSeqNum[tid] = squash_seq_num;
         cpu->lastSquashCycle[tid] = curTick();
+        cpu->squashSeqNum[tid] = squash_seq_num;
     }
 }
 
@@ -398,7 +382,6 @@ PipelineStage::squashPrevStageInsts(InstSeqNum squash_seq_num, ThreadID tid)
     for (int i=0; i < insts_from_prev_stage; i++) {
         if (prevStage->insts[i]->threadNumber == tid &&
             prevStage->insts[i]->seqNum > squash_seq_num) {
-            // Change Comment to Annulling previous instruction
             DPRINTF(InOrderStage, "[tid:%i]: Squashing instruction, "
                     "[sn:%i] PC %s.\n",
                     tid,
@@ -676,7 +659,7 @@ PipelineStage::checkSignalsAndUpdate(ThreadID tid)
             DPRINTF(InOrderStage, "[tid:%u]: Squashing instructions due to "
                     "squash from stage %u.\n", tid, stage_idx);
             InstSeqNum squash_seq_num = fromNextStages->
-                stageInfo[stage_idx][tid].bdelayDoneSeqNum;
+                stageInfo[stage_idx][tid].doneSeqNum;
             squash(squash_seq_num, tid);
             break; //return true;
         }
@@ -989,7 +972,7 @@ PipelineStage::processInstSchedule(DynInstPtr inst,int &reqs_processed)
                     
                     // Remove Thread From Pipeline & Resource Pool
                     inst->squashingStage = stageNum;
-                    inst->bdelaySeqNum = inst->seqNum;
+                    inst->squashSeqNum = inst->seqNum;
                     cpu->squashFromMemStall(inst, tid);  
 
                     // Switch On Cache Miss
index d0d9112c0deb3fdda21194c4e3056a1a73224dad..963d96afb539b7f30bce6850a39c31b5914ac740 100644 (file)
@@ -227,21 +227,17 @@ class PipelineStage
   public:
     void activateThread(ThreadID tid);
     
-    /** Squashes if there is a PC-relative branch that was predicted
-     * incorrectly. Sends squash information back to fetch.
-     */
-    void squashDueToBranch(DynInstPtr &inst, ThreadID tid);
+    /** Setup Squashing Information to be passed back thru the pipeline */
+    void setupSquash(DynInstPtr inst, ThreadID tid);
 
     virtual void squashDueToMemStall(InstSeqNum seq_num, ThreadID tid);
 
+    /** Perform squash of instructions above seq_num */
+    virtual void squash(InstSeqNum squash_num, ThreadID tid);
+
     /** Squash instructions from stage buffer  */
     void squashPrevStageInsts(InstSeqNum squash_seq_num, ThreadID tid);
 
-    /** Squashes due to commit signalling a squash. Changes status to
-     *  squashing and clears block/unblock signals as needed.
-     */
-    virtual void squash(InstSeqNum squash_num, ThreadID tid);
-
     void dumpInsts();
 
   protected:
index 23d33afbede6b6aa0e92ad8713c99e6dd6bdaaf5..836335510dbd0e98798841982ddfdca493a63754 100644 (file)
@@ -290,10 +290,8 @@ Resource::deactivateThread(ThreadID tid)
 void
 Resource::setupSquash(DynInstPtr inst, int stage_num, ThreadID tid)
 {
-    assert(inst->isControl() && "Function Assumes Squash From A Branch");
-
     // Squash In Pipeline Stage
-    cpu->pipelineStage[stage_num]->squashDueToBranch(inst, tid);
+    cpu->pipelineStage[stage_num]->setupSquash(inst, tid);
 
     // Schedule Squash Through-out Resource Pool
     cpu->resPool->scheduleEvent(
index 09749736242c1dd1ec3bf47ac235e1ff14c742f9..fcf01065a8ba849dc030036dafadfc4e977837a5 100644 (file)
@@ -106,6 +106,9 @@ class Resource {
      */
     virtual void instGraduated(InstSeqNum seq_num, ThreadID tid) { }
 
+    /** Post-processsing for Trap Generated from this instruction */
+    virtual void trap(Fault fault, ThreadID tid, DynInstPtr inst) { }
+
     /** Request usage of this resource. Returns a ResourceRequest object
      *  with all the necessary resource information
      */
index 78a7d4b888841338932b9802e7ad766a59b066f7..e0a00ee0f767c4c996490c1354e9f1ff06e1a01b 100644 (file)
@@ -192,7 +192,7 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
             res_pool_event->setEvent(e_type,
                                      inst,
                                      inst->squashingStage,
-                                     inst->bdelaySeqNum,
+                                     inst->squashSeqNum,
                                      inst->readTid());
             res_pool_event->schedule(curTick() + cpu->cycles(delay));
 
@@ -208,7 +208,7 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
             res_pool_event->setEvent(e_type,
                                      inst,
                                      inst->squashingStage,
-                                     inst->bdelaySeqNum,
+                                     inst->squashSeqNum,
                                      tid);
 
             res_pool_event->schedule(curTick() + cpu->cycles(delay));
@@ -238,7 +238,7 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
             res_pool_event->setEvent(e_type,
                                      inst,
                                      inst->squashingStage,
-                                     inst->bdelaySeqNum,
+                                     inst->squashSeqNum,
                                      inst->readTid());
             res_pool_event->schedule(curTick() + cpu->cycles(delay));
 
index 1800aac37adf03d7b7ee9532edc382d9e38791f4..d5b3a5115021d99fca2da638a1d09d5b7e0475d5 100644 (file)
@@ -234,6 +234,18 @@ ResourcePool::squash(DynInstPtr inst, int res_idx, InstSeqNum done_seq_num,
                                tid);
 }
 
+void
+ResourcePool::trap(Fault fault, ThreadID tid, DynInstPtr inst)
+{
+    DPRINTF(Resource, "[tid:%i] Broadcasting Trap to all "
+            "resources.\n", tid);
+
+    int num_resources = resources.size();
+
+    for (int idx = 0; idx < num_resources; idx++)
+        resources[idx]->trap(fault, tid, inst);
+}
+
 int
 ResourcePool::slotsAvail(int res_idx)
 {
@@ -272,7 +284,7 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
                                  e_type,
                                  inst,
                                  inst->squashingStage,
-                                 inst->bdelaySeqNum,
+                                 inst->squashSeqNum,
                                  inst->readTid());
             cpu->schedule(res_pool_event, when);
         }
@@ -289,7 +301,7 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
                                  e_type,
                                  inst,
                                  inst->squashingStage,
-                                 inst->bdelaySeqNum,
+                                 inst->squashSeqNum,
                                  tid);
 
             cpu->schedule(res_pool_event, when);
@@ -308,7 +320,7 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
                                                             e_type,
                                                             inst,
                                                             inst->squashingStage,
-                                                            inst->bdelaySeqNum,
+                                                            inst->squashSeqNum,
                                                             tid);
 
             cpu->schedule(res_pool_event, sked_tick);
@@ -337,7 +349,7 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
                 new ResPoolEvent(this,e_type,
                                  inst,
                                  inst->squashingStage,
-                                 inst->bdelaySeqNum,
+                                 inst->squashSeqNum,
                                  inst->readTid());
             cpu->schedule(res_pool_event, when);
         }
index b420110912af3bc987b6921a22a79df25c884339..85c0f70f6dd6e4ad439889f7a54d66f18cd2e53c 100644 (file)
@@ -182,6 +182,9 @@ class ResourcePool {
     /** Broadcast graduation to all resources */
     void instGraduated(InstSeqNum seq_num, ThreadID tid);
 
+    /** Broadcast trap to all resources */
+    void trap(Fault fault, ThreadID tid, DynInstPtr inst);
+
     /** The number of instructions available that a resource can
      *  can still process.
      */
index d87ca364dcf770e7857445be31ecc8240b0e297d..64f6d7544b55f83df178b62a93e535cd297ebf48 100644 (file)
@@ -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++;
index c1a3590be6a8ae7a787462ee6c9c635c677bc048..760fdb13494e13d666dd03e64e1ef1e8ab7cd55c 100644 (file)
@@ -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<CacheUnit*>(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]->
index 4363f125d8240c7f9476b16ae14ea623c8b02e60..d7151add194fd2ece687994095c3283c51f129dc 100644 (file)
@@ -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;
                 }
 
index 62dbb452ada028780ed80e6639edf97238748f2c..024f38fdda91041ca387a6fd99b2594dbab80f86 100644 (file)
@@ -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)
 {
index 7c57fa17b413c5d7be455e847722a4b15d4f9bb7..1cd0047e2e5affbec5bc20788d2b21e783b5ea7b 100644 (file)
@@ -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;
index 692f78c7b1549fe1ebf91155a8ef6fd205a8a1e7..60452bacd79b2aeab8892b41758db51baddd9ee5 100644 (file)
@@ -111,6 +111,7 @@ FetchUnit::createMachInst(std::list<FetchBlock*>::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();
+}
index 3075e726dfcd999fa591d21e6f0d101e66e83356..d6e36419a2c43ad1a8793024502478faf7b4d770 100644 (file)
@@ -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);
 
index 826ed8e03505e2dc8dd2cf41457b0c9b65ae2e87..9c17db945ae46f1b7491cf0eb4b71dd2cc1d9bc2 100644 (file)
@@ -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,