changeset c6449ed4cbe4 in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=c6449ed4cbe4
description:
        inorder: check for interrupts each tick
        use a dummy instruction to facilitate the squash after
        the interrupts trap

diffstat:

 src/cpu/inorder/cpu.cc                      |   49 ++++++++++
 src/cpu/inorder/cpu.hh                      |    3 +
 src/cpu/inorder/pipeline_stage.cc           |    7 +-
 src/cpu/inorder/resource.cc                 |    2 +
 src/cpu/inorder/resources/cache_unit.cc     |    3 +-
 src/cpu/inorder/resources/fetch_seq_unit.cc |  128 ++++++++++++++-------------
 6 files changed, 125 insertions(+), 67 deletions(-)

diffs (295 lines):

diff -r 2e9141200f78 -r c6449ed4cbe4 src/cpu/inorder/cpu.cc
--- a/src/cpu/inorder/cpu.cc    Sun Jun 19 21:43:40 2011 -0400
+++ b/src/cpu/inorder/cpu.cc    Sun Jun 19 21:43:40 2011 -0400
@@ -350,6 +350,16 @@
                                             asid[tid]);
 
         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);
@@ -687,6 +697,8 @@
         pipes_idle = pipes_idle && pipelineStage[stNum]->idle;
     }
 
+    checkForInterrupts();
+
     if (pipes_idle)
         idleCycles++;
     else
@@ -800,6 +812,43 @@
     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
 InOrderCPU::getInterrupts()
diff -r 2e9141200f78 -r c6449ed4cbe4 src/cpu/inorder/cpu.hh
--- a/src/cpu/inorder/cpu.hh    Sun Jun 19 21:43:40 2011 -0400
+++ b/src/cpu/inorder/cpu.hh    Sun Jun 19 21:43:40 2011 -0400
@@ -253,6 +253,7 @@
     DynInstPtr dummyInst[ThePipeline::MaxThreads];
     DynInstPtr dummyBufferInst;
     DynInstPtr dummyReqInst;
+    DynInstPtr dummyTrapInst[ThePipeline::MaxThreads];
 
     /** Used by resources to signify a denied access to a resource. */
     ResourceRequest *dummyReq[ThePipeline::MaxThreads];
@@ -414,6 +415,8 @@
 
     bool simPalCheck(int palFunc, ThreadID tid);
 
+    void checkForInterrupts();
+
     /** Returns the Fault for any valid interrupt. */
     Fault getInterrupts();
 
diff -r 2e9141200f78 -r c6449ed4cbe4 src/cpu/inorder/pipeline_stage.cc
--- a/src/cpu/inorder/pipeline_stage.cc Sun Jun 19 21:43:40 2011 -0400
+++ b/src/cpu/inorder/pipeline_stage.cc Sun Jun 19 21:43:40 2011 -0400
@@ -364,9 +364,10 @@
         toPrevStages->stageInfo[squash_stage][tid].doneSeqNum =
             squash_seq_num;
 
-        DPRINTF(InOrderStage, "[tid:%i]: Squashing after [sn:%i], "
-                "due to [sn:%i] %s.\n", tid, squash_seq_num,
-                inst->seqNum, inst->instName());
+        DPRINTF(InOrderStage, "[tid:%i]: Setting up squashing after "
+                "[sn:%i], due to [sn:%i] %s. Squash-Start-Stage:%i\n",
+                tid, squash_seq_num, inst->seqNum, inst->instName(),
+                squash_stage);
 
         // Save squash num for later stage use
         cpu->lastSquashCycle[tid] = curTick();
diff -r 2e9141200f78 -r c6449ed4cbe4 src/cpu/inorder/resource.cc
--- a/src/cpu/inorder/resource.cc       Sun Jun 19 21:43:40 2011 -0400
+++ b/src/cpu/inorder/resource.cc       Sun Jun 19 21:43:40 2011 -0400
@@ -302,6 +302,8 @@
 Resource::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num,
                  ThreadID tid)
 {
+    //@todo: check squash seq num before squashing. can save time going
+    //       through this function.
     for (int i = 0; i < width; i++) {
         ResReqPtr req_ptr = reqs[i];
         DynInstPtr inst = req_ptr->getInst();
diff -r 2e9141200f78 -r c6449ed4cbe4 src/cpu/inorder/resources/cache_unit.cc
--- a/src/cpu/inorder/resources/cache_unit.cc   Sun Jun 19 21:43:40 2011 -0400
+++ b/src/cpu/inorder/resources/cache_unit.cc   Sun Jun 19 21:43:40 2011 -0400
@@ -1248,7 +1248,8 @@
 CacheUnit::squash(DynInstPtr inst, int stage_num,
                   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 "
                 " squash after [sn:%i].\n", squash_seq_num);
         tlbBlocked[tid] = false;
diff -r 2e9141200f78 -r c6449ed4cbe4 src/cpu/inorder/resources/fetch_seq_unit.cc
--- a/src/cpu/inorder/resources/fetch_seq_unit.cc       Sun Jun 19 21:43:40 
2011 -0400
+++ b/src/cpu/inorder/resources/fetch_seq_unit.cc       Sun Jun 19 21:43:40 
2011 -0400
@@ -49,6 +49,8 @@
         pcValid[tid] = false;
         pcBlockStage[tid] = 0;
 
+        //@todo: Use CPU's squashSeqNum here instead of maintaining our own
+        // state
         squashSeqNum[tid] = (InstSeqNum)-1;
         lastSquashCycle[tid] = 0;
     }
@@ -164,75 +166,77 @@
         squashSeqNum[tid] = squash_seq_num;
         lastSquashCycle[tid] = curTick();
 
-        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].%s %s \n", inst->seqNum,
-                    inst->instName(), inst->pcState());
-            pcValid[tid] = false;
-        } else {
-            TheISA::PCState nextPC;
-            assert(inst->staticInst);
-            if (inst->isControl()) {
-                nextPC = inst->readPredTarg();
+        if (inst->staticInst) {
+            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].%s %s \n", inst->seqNum,
+                        inst->instName(), inst->pcState());
+                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++;
+                    // 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_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 {
-                    InstSeqNum branch_delay_num = inst->seqNum + 1;
-                    bdelay_it = cpu->findInst(branch_delay_num, tid);
+                    nextPC = inst->pcState();
+                    advancePC(nextPC, inst->staticInst);
                 }
 
-                if (bdelay_it != cpu->instList[tid].end()) {
-                    bdelay_inst = (*bdelay_it);
+
+                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;
                 }
 
-                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);
+                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);
 }
@@ -302,8 +306,6 @@
             "%s.\n", tid, pc[tid]);
     DPRINTF(InOrderFetchSeq, "[tid:%i]: Trap updating to PC: "
             "%s.\n", tid, pc[tid]);
-
-    cpu->removePipelineStalls(tid);
 }
 
 void
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to