# HG changeset patch
# User Korey Sewell <[email protected]>
# Date 1254427253 14400
# Node ID a829497e6ff5fd1962764b0c4717a32cbce5b7d9
# Parent  5e04e6117c84cd57a60e612020aa0eee462c2006
inorder: squash on memory stall
add code to recognize memory stalls in resources and the pipeline as well
as squash a thread if there is a stall and we are in the switch on cache miss
model

diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc
--- a/src/cpu/inorder/cpu.cc
+++ b/src/cpu/inorder/cpu.cc
@@ -138,6 +138,10 @@
         cpu->disableThreads(tid, vpe);
         break;
 
+      case SquashFromMemStall:
+        cpu->squashDueToMemStall(inst->squashingStage, inst->seqNum, tid);
+        break;
+
       case Trap:
         cpu->trapCPU(fault, tid);
         break;
@@ -565,6 +569,31 @@
     fault->invoke(tcBase(tid));
 }
 
+void 
+InOrderCPU::squashFromMemStall(DynInstPtr inst, ThreadID tid, int delay)
+{
+    scheduleCpuEvent(SquashFromMemStall, NoFault, tid, inst, delay);
+}
+
+
+void
+InOrderCPU::squashDueToMemStall(int stage_num, InstSeqNum seq_num, ThreadID 
tid)
+{
+    DPRINTF(InOrderCPU, "Squashing Pipeline Stages Due to Memory Stall...\n");
+        
+    // Squash all instructions in each stage including 
+    // instruction that caused the squash (seq_num - 1)
+    // NOTE: The stage bandwidth needs to be cleared so thats why
+    //       the stalling instruction is squashed as well. The stalled
+    //       instruction is previously placed in another intermediate buffer
+    //       while it's stall is being handled.
+    InstSeqNum squash_seq_num = seq_num - 1;
+    
+    for (int stNum=stage_num; stNum >= 0 ; stNum--) {
+        pipelineStage[stNum]->squashDueToMemStall(squash_seq_num, tid);
+    }
+}
+
 void
 InOrderCPU::scheduleCpuEvent(CPUEventType c_event, Fault fault,
                              ThreadID tid, DynInstPtr inst, 
diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh
--- a/src/cpu/inorder/cpu.hh
+++ b/src/cpu/inorder/cpu.hh
@@ -180,7 +180,7 @@
         EnableVPEs,
         Trap,
         InstGraduated,
-        SquashAll,
+        SquashFromMemStall,
         UpdatePCs,
         NumCPUEvents
     };
@@ -340,6 +340,12 @@
     void trap(Fault fault, ThreadID tid, int delay = 0);
     void trapCPU(Fault fault, ThreadID tid);
 
+    /** squashFromMemStall() - sets up a squash event
+     *  squashDueToMemStall() - squashes pipeline
+     */
+    void squashFromMemStall(DynInstPtr inst, ThreadID tid, int delay = 0);
+    void squashDueToMemStall(int stage_num, InstSeqNum seq_num, ThreadID tid); 
   
+
     /** Setup CPU to insert a thread's context */
     void insertThread(ThreadID tid);
 
diff --git a/src/cpu/inorder/first_stage.cc b/src/cpu/inorder/first_stage.cc
--- a/src/cpu/inorder/first_stage.cc
+++ b/src/cpu/inorder/first_stage.cc
@@ -93,6 +93,18 @@
     cpu->removeInstsUntil(squash_seq_num, tid);
 }
 
+void 
+FirstStage::squashDueToMemStall(InstSeqNum seq_num, ThreadID tid)
+{
+    // Need to preserve the stalling instruction in first-stage
+    // since the squash() from first stage also removes
+    // the instruction from the CPU (removeInstsUntil). If that
+    // functionality gets changed then you can move this offset.
+    // (stalling instruction = seq_num + 1)
+    squash(seq_num+1, tid);
+}
+
+
 void
 FirstStage::processStage(bool &status_change)
 {
@@ -106,6 +118,7 @@
 
     for (int threadFetched = 0; threadFetched < numFetchingThreads;
          threadFetched++) {
+
         ThreadID tid = getFetchingThread(fetchPolicy);
 
         if (tid >= 0) {
diff --git a/src/cpu/inorder/first_stage.hh b/src/cpu/inorder/first_stage.hh
--- a/src/cpu/inorder/first_stage.hh
+++ b/src/cpu/inorder/first_stage.hh
@@ -61,6 +61,8 @@
     /** Squash Instructions Above a Seq. Num */
     void squash(InstSeqNum squash_seq_num, ThreadID tid);
 
+    void squashDueToMemStall(InstSeqNum seq_num, ThreadID tid);
+
     /** There are no insts. coming from previous stages, so there is
      * no need to sort insts here
      */
diff --git a/src/cpu/inorder/pipeline_stage.cc 
b/src/cpu/inorder/pipeline_stage.cc
--- a/src/cpu/inorder/pipeline_stage.cc
+++ b/src/cpu/inorder/pipeline_stage.cc
@@ -336,7 +336,7 @@
 {
     if (cpu->squashSeqNum[tid] < inst->seqNum &&
         cpu->lastSquashCycle[tid] == curTick){
-        DPRINTF(Resource, "Ignoring [sn:%i] squash signal due to another 
stage's squash "
+        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.
@@ -370,6 +370,12 @@
 }
 
 void
+PipelineStage::squashDueToMemStall(InstSeqNum seq_num, ThreadID tid)
+{
+    squash(seq_num, tid);    
+}
+
+void
 PipelineStage::squashPrevStageInsts(InstSeqNum squash_seq_num, ThreadID tid)
 {
     DPRINTF(InOrderStage, "[tid:%i]: Removing instructions from "
@@ -401,8 +407,8 @@
     while (!skidBuffer[tid].empty()) {
         if (skidBuffer[tid].front()->seqNum <= squash_seq_num) {
             DPRINTF(InOrderStage, "[tid:%i]: Cannot remove skidBuffer "
-                    "instructions before delay slot [sn:%i]. %i insts"
-                    "left.\n", tid, squash_seq_num,
+                    "instructions (starting w/[sn:%i]) before delay slot 
[sn:%i]. %i insts"
+                    "left.\n", tid, skidBuffer[tid].front()->seqNum, 
squash_seq_num,
                     skidBuffer[tid].size());
             break;
         }
@@ -759,7 +765,7 @@
 PipelineStage::processThread(bool &status_change, ThreadID tid)
 {
     // If status is Running or idle,
-    //     call stageInsts()
+    //     call processInsts()
     // If status is Unblocking,
     //     buffer any instructions coming from fetch
     //     continue trying to empty skid buffer
@@ -771,7 +777,7 @@
         ;//++stageSquashCycles;
     }
 
-    // Stage should try to stage as many instructions as its bandwidth
+    // Stage should try to process as many instructions as its bandwidth
     // will allow, as long as it is not currently blocked.
     if (stageStatus[tid] == Running ||
         stageStatus[tid] == Idle) {
@@ -888,9 +894,7 @@
 PipelineStage::processInstSchedule(DynInstPtr inst)
 {
     bool last_req_completed = true;
-#if TRACING_ON
     ThreadID tid = inst->readTid();
-#endif
 
     if (inst->nextResStage() == stageNum) {
         int res_stage_num = inst->nextResStage();
@@ -920,6 +924,17 @@
 
                 last_req_completed = false;
 
+                if (req->isMemStall() && cpu->threadModel == 
InOrderCPU::SwitchOnCacheMiss) {
+                    // Save Stalling Instruction
+                    switchedOutBuffer[tid] = inst;
+                    switchedOutValid[tid] = true;
+                    
+                    // Remove Thread From Pipeline & Resource Pool
+                    inst->squashingStage = stageNum;         
+                    inst->bdelaySeqNum = inst->seqNum;                         
      
+                    cpu->squashFromMemStall(inst, tid);                    
+                }
+                
                 break;
             }
 
diff --git a/src/cpu/inorder/pipeline_stage.hh 
b/src/cpu/inorder/pipeline_stage.hh
--- a/src/cpu/inorder/pipeline_stage.hh
+++ b/src/cpu/inorder/pipeline_stage.hh
@@ -240,7 +240,7 @@
      */
     virtual void squashDueToBranch(DynInstPtr &inst, ThreadID tid);
 
-    virtual void squashDueToMemStall(DynInstPtr &inst, ThreadID tid);
+    virtual void squashDueToMemStall(InstSeqNum seq_num, ThreadID tid);
 
     /** Squash instructions from stage buffer  */
     virtual void squashPrevStageInsts(InstSeqNum squash_seq_num, ThreadID tid);
diff --git a/src/cpu/inorder/resource.cc b/src/cpu/inorder/resource.cc
--- a/src/cpu/inorder/resource.cc
+++ b/src/cpu/inorder/resource.cc
@@ -334,6 +334,12 @@
     }
 }
 
+void
+Resource::squashDueToMemStall(DynInstPtr inst, int stage_num, InstSeqNum 
squash_seq_num,
+                              ThreadID tid)
+{
+    squash(inst, stage_num, squash_seq_num, tid);    
+}
 
 Tick
 Resource::ticks(int num_cycles)
diff --git a/src/cpu/inorder/resource.hh b/src/cpu/inorder/resource.hh
--- a/src/cpu/inorder/resource.hh
+++ b/src/cpu/inorder/resource.hh
@@ -154,6 +154,9 @@
     virtual void squash(DynInstPtr inst, int stage_num,
                         InstSeqNum squash_seq_num, ThreadID tid);
 
+    virtual void squashDueToMemStall(DynInstPtr inst, int stage_num,
+                                     InstSeqNum squash_seq_num, ThreadID tid);
+
     /** The number of instructions available that this resource can
      *  can still process
      */
@@ -309,7 +312,7 @@
                     int res_idx, int slot_num, unsigned _cmd)
         : res(_res), inst(_inst), cmd(_cmd),  stageNum(stage_num),
           resIdx(res_idx), slotNum(slot_num), completed(false),
-          squashed(false), processing(false), waiting(false)
+          squashed(false), processing(false), memStall(false)
     {
         reqID = resReqID++;
         resReqCount++;
@@ -389,8 +392,8 @@
     void setProcessing() { processing = true; }
 
     /** Get/Set IsWaiting variables */
-    bool isWaiting() { return waiting; }
-    void setWaiting() { waiting = true; }
+    bool isMemStall() { return memStall; }
+    void setMemStall(bool stall = true) { memStall = stall; }
 
   protected:
     /** Resource Identification */
@@ -399,11 +402,12 @@
     int resIdx;
     int slotNum;
 
-    /** Resource Status */
+    /** Resource Request Status */
     bool completed;
     bool squashed;
     bool processing;
-    bool waiting;
+
+    bool memStall;
 };
 
 #endif //__CPU_INORDER_RESOURCE_HH__
diff --git a/src/cpu/inorder/resource_pool.cc b/src/cpu/inorder/resource_pool.cc
--- a/src/cpu/inorder/resource_pool.cc
+++ b/src/cpu/inorder/resource_pool.cc
@@ -249,6 +249,20 @@
         }
         break;
 
+      case InOrderCPU::SquashFromMemStall:
+        {
+            DPRINTF(Resource, "Scheduling Squash Due to Memory Stall Resource "
+                    "Pool Event for tick %i.\n",
+                    curTick + delay);
+            ResPoolEvent *res_pool_event = new ResPoolEvent(this,e_type,
+                                                            inst,
+                                                            
inst->squashingStage,
+                                                            inst->seqNum - 1,
+                                                            inst->readTid());
+            mainEventQueue.schedule(res_pool_event, curTick + 
cpu->ticks(delay));
+        }
+        break;
+
       default:
         DPRINTF(Resource, "Ignoring Unrecognized CPU Event (%s).\n", 
InOrderCPU::eventNames[e_type]);
         ; // If Resource Pool doesnt recognize event, we ignore it.
@@ -276,6 +290,20 @@
 }
 
 void
+ResourcePool::squashDueToMemStall(DynInstPtr inst, int stage_num,
+                             InstSeqNum done_seq_num, ThreadID tid)
+{
+    DPRINTF(Resource, "[tid:%i] Stage %i squashing all instructions above 
[sn:%i].\n",
+            stage_num, tid, done_seq_num);
+
+    int num_resources = resources.size();
+
+    for (int idx = 0; idx < num_resources; idx++) {
+        resources[idx]->squashDueToMemStall(inst, stage_num, done_seq_num, 
tid);
+    }
+}
+
+void
 ResourcePool::activateAll(ThreadID tid)
 {
     DPRINTF(Resource, "[tid:%i] Broadcasting Thread Activation to all 
resources.\n",
@@ -353,6 +381,10 @@
         resPool->squashAll(inst, stageNum, seqNum, tid);
         break;
 
+      case InOrderCPU::SquashFromMemStall:
+        resPool->squashDueToMemStall(inst, stageNum, seqNum, tid);
+        break;
+
       default:
         fatal("Unrecognized Event Type");
     }
diff --git a/src/cpu/inorder/resource_pool.hh b/src/cpu/inorder/resource_pool.hh
--- a/src/cpu/inorder/resource_pool.hh
+++ b/src/cpu/inorder/resource_pool.hh
@@ -123,7 +123,7 @@
     };
 
   public:
-  ResourcePool(InOrderCPU *_cpu, ThePipeline::Params *params);
+    ResourcePool(InOrderCPU *_cpu, ThePipeline::Params *params);
     virtual ~ResourcePool() {}
 
     std::string name();
@@ -160,6 +160,12 @@
     void squashAll(DynInstPtr inst, int stage_num,
                    InstSeqNum done_seq_num, ThreadID tid);
 
+    /** Squash Resources in Pool after a memory stall 
+     *  NOTE: Only use during Switch-On-Miss Thread model
+     */    
+    void squashDueToMemStall(DynInstPtr inst, int stage_num,
+                             InstSeqNum done_seq_num, ThreadID tid);
+
     /** Activate Thread in all resources */
     void activateAll(ThreadID tid);
 
diff --git a/src/cpu/inorder/resources/cache_unit.cc 
b/src/cpu/inorder/resources/cache_unit.cc
--- a/src/cpu/inorder/resources/cache_unit.cc
+++ b/src/cpu/inorder/resources/cache_unit.cc
@@ -414,6 +414,7 @@
                     tid, seq_num, inst->staticInst->disassemble(inst->PC));
 
             delete cache_req->dataPkt;
+            //cache_req->setMemStall(false);            
             cache_req->done();
         } else {
             DPRINTF(InOrderCachePort,
@@ -423,6 +424,7 @@
                     "STALL: [tid:%i]: Fetch miss from %08p\n",
                     tid, cache_req->inst->readPC());
             cache_req->setCompleted(false);
+            //cache_req->setMemStall(true);            
         }
         break;
 
@@ -435,11 +437,13 @@
         if (cache_req->isMemAccComplete() ||
             inst->isDataPrefetch() ||
             inst->isInstPrefetch()) {
+            cache_req->setMemStall(false);            
             cache_req->done();
         } else {
             DPRINTF(InOrderStall, "STALL: [tid:%i]: Data miss from %08p\n",
                     tid, cache_req->inst->getMemAddr());
             cache_req->setCompleted(false);
+            cache_req->setMemStall(true);            
         }
         break;
 
@@ -763,6 +767,23 @@
 }
 
 void
+CacheUnit::squashDueToMemStall(DynInstPtr inst, int stage_num,
+                               InstSeqNum squash_seq_num, ThreadID tid)
+{
+    // If squashing due to memory stall, then we do NOT want to 
+    // squash the instruction that caused the stall so we
+    // increment the sequence number here to prevent that.
+    //
+    // NOTE: This is only for the SwitchOnCacheMiss Model
+    // NOTE: If you have multiple outstanding misses from the same
+    //       thread then you need to reevaluate this code
+    // NOTE: squash should originate from 
+    //       pipeline_stage.cc:processInstSchedule
+    squash(inst, stage_num, squash_seq_num + 1, tid);    
+}
+
+
+void
 CacheUnit::squash(DynInstPtr inst, int stage_num,
                   InstSeqNum squash_seq_num, ThreadID tid)
 {
diff --git a/src/cpu/inorder/resources/cache_unit.hh 
b/src/cpu/inorder/resources/cache_unit.hh
--- a/src/cpu/inorder/resources/cache_unit.hh
+++ b/src/cpu/inorder/resources/cache_unit.hh
@@ -146,6 +146,9 @@
     void squash(DynInstPtr inst, int stage_num,
                 InstSeqNum squash_seq_num, ThreadID tid);
 
+    void squashDueToMemStall(DynInstPtr inst, int stage_num,
+                             InstSeqNum squash_seq_num, ThreadID tid);
+
     /** Processes cache completion event. */
     void processCacheCompletion(PacketPtr pkt);
 
_______________________________________________
m5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/m5-dev

Reply via email to