inorder: squash on memory stall
authorKorey Sewell <ksewell@umich.edu>
Sun, 31 Jan 2010 23:26:13 +0000 (18:26 -0500)
committerKorey Sewell <ksewell@umich.edu>
Sun, 31 Jan 2010 23:26:13 +0000 (18:26 -0500)
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

12 files changed:
src/cpu/inorder/cpu.cc
src/cpu/inorder/cpu.hh
src/cpu/inorder/first_stage.cc
src/cpu/inorder/first_stage.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.cc
src/cpu/inorder/resource_pool.hh
src/cpu/inorder/resources/cache_unit.cc
src/cpu/inorder/resources/cache_unit.hh

index 69aea0c57775e7d6247373b55cda6ac88687de52..035aa05710b6910db1f274cdb8493d8bf7548d51 100644 (file)
@@ -140,6 +140,10 @@ InOrderCPU::CPUEvent::process()
         cpu->disableThreads(tid, vpe);
         break;
 
+      case SquashFromMemStall:
+        cpu->squashDueToMemStall(inst->squashingStage, inst->seqNum, tid);
+        break;
+
       case Trap:
         cpu->trapCPU(fault, tid);
         break;
@@ -579,6 +583,31 @@ InOrderCPU::trapCPU(Fault fault, ThreadID tid)
     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, 
index 4c7b2710d5b230316c26da7ab899563adca27702..5d34de67a9590bf1552a3bd48b130938c4f434c3 100644 (file)
@@ -183,7 +183,7 @@ class InOrderCPU : public BaseCPU
         EnableVPEs,
         Trap,
         InstGraduated,
-        SquashAll,
+        SquashFromMemStall,
         UpdatePCs,
         NumCPUEvents
     };
@@ -344,6 +344,12 @@ class InOrderCPU : public BaseCPU
     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);
 
index 8bd703c56f03381ac402deedcc8da71ce6cd66e1..1427ca46acf061016ed9a6015c3167de849f796d 100644 (file)
@@ -67,11 +67,12 @@ FirstStage::squash(InstSeqNum squash_seq_num, ThreadID tid)
 
     // Clear the instruction list and skid buffer in case they have any
     // insts in them.
-    DPRINTF(InOrderStage, "Removing instructions from stage instruction list.\n");
+    DPRINTF(InOrderStage, "Removing instructions from stage instruction "
+            "list.\n");
     while (!insts[tid].empty()) {
         if (insts[tid].front()->seqNum <= squash_seq_num) {
-            DPRINTF(InOrderStage,"[tid:%i]: Cannot remove [sn:%i] because it's <= "
-                    "squashing seqNum %i.\n",
+            DPRINTF(InOrderStage,"[tid:%i]: Cannot remove [sn:%i] because "
+                    "it's <= squashing seqNum %i.\n",
                     tid,
                     insts[tid].front()->seqNum,
                     squash_seq_num);
@@ -82,8 +83,9 @@ FirstStage::squash(InstSeqNum squash_seq_num, ThreadID tid)
                     insts[tid].size());
             break;
         }
-        DPRINTF(InOrderStage, "[tid:%i]: Removing instruction, [sn:%i] PC %08p.\n",
-                tid, insts[tid].front()->seqNum, insts[tid].front()->PC);
+        DPRINTF(InOrderStage, "[tid:%i]: Removing instruction, [sn:%i] "
+                "PC %08p.\n", tid, insts[tid].front()->seqNum, 
+                insts[tid].front()->PC);
         insts[tid].pop();
     }
 
@@ -93,6 +95,18 @@ FirstStage::squash(InstSeqNum squash_seq_num, ThreadID tid)
     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 +120,7 @@ FirstStage::processStage(bool &status_change)
 
     for (int threadFetched = 0; threadFetched < numFetchingThreads;
          threadFetched++) {
+
         ThreadID tid = getFetchingThread(fetchPolicy);
 
         if (tid >= 0) {
@@ -117,14 +132,17 @@ FirstStage::processStage(bool &status_change)
     }
 }
 
-//@TODO: Note in documentation, that when you make a pipeline stage change, then
-//make sure you change the first stage too
+//@TODO: Note in documentation, that when you make a pipeline stage change, 
+//then make sure you change the first stage too
 void
 FirstStage::processInsts(ThreadID tid)
 {
     bool all_reqs_completed = true;
 
-    for (int insts_fetched = 0; insts_fetched < stageWidth && canSendInstToStage(1); insts_fetched++) {
+    for (int insts_fetched = 0; 
+         insts_fetched < stageWidth && canSendInstToStage(1); 
+         insts_fetched++) {
+
         DynInstPtr inst;
         bool new_inst = false;
 
@@ -150,19 +168,9 @@ FirstStage::processInsts(ThreadID tid)
             inst->traceData = NULL;
 #endif      // TRACING_ON
 
-            DPRINTF(RefCount, "creation: [tid:%i]: [sn:%i]: Refcount = %i.\n",
-                    inst->readTid(),
-                    inst->seqNum,
-                    0/*inst->curCount()*/);
-
             // Add instruction to the CPU's list of instructions.
             inst->setInstListIt(cpu->addInst(inst));
 
-            DPRINTF(RefCount, "after add to CPU List: [tid:%i]: [sn:%i]: Refcount = %i.\n",
-                    inst->readTid(),
-                    inst->seqNum,
-                    0/*inst->curCount()*/);
-
             // Create Front-End Resource Schedule For Instruction
             ThePipeline::createFrontEndSchedule(inst);
         }
index 2a69678e4750bc39720eec29e63d5dbe305d3869..383b799f3a186fc55dd27b93619bafdadc6d27c8 100644 (file)
@@ -61,6 +61,8 @@ class FirstStage : public PipelineStage {
     /** 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
      */
index 8d14aae2720780a49b4cc319721a9bda0ba147ad..1fd7150da4df4eed9c38d88d27d483f9c4afb429 100644 (file)
@@ -339,9 +339,9 @@ PipelineStage::squashDueToBranch(DynInstPtr &inst, ThreadID tid)
 {
     if (cpu->squashSeqNum[tid] < inst->seqNum &&
         cpu->lastSquashCycle[tid] == curTick){
-        DPRINTF(Resource, "Ignoring [sn:%i] squash signal due to another "
-                "stage's squash signal for after [sn:%i].\n", inst->seqNum
-                cpu->squashSeqNum[tid]);
+        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;
@@ -381,6 +381,12 @@ PipelineStage::squashDueToBranch(DynInstPtr &inst, ThreadID tid)
     }
 }
 
+void
+PipelineStage::squashDueToMemStall(InstSeqNum seq_num, ThreadID tid)
+{
+    squash(seq_num, tid);    
+}
+
 void
 PipelineStage::squashPrevStageInsts(InstSeqNum squash_seq_num, ThreadID tid)
 {
@@ -413,8 +419,9 @@ PipelineStage::squash(InstSeqNum squash_seq_num, ThreadID tid)
     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;
         }
@@ -775,7 +782,7 @@ void
 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
@@ -787,7 +794,7 @@ PipelineStage::processThread(bool &status_change, ThreadID tid)
         ;//++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) {
@@ -904,9 +911,7 @@ bool
 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();
@@ -937,6 +942,18 @@ PipelineStage::processInstSchedule(DynInstPtr inst)
 
                 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;
             }
 
index 42a632560b6619e04539ff06b5880703321d69f8..f10906e4c6e2864a2bd2babea69f25d383c9f82e 100644 (file)
@@ -240,7 +240,7 @@ class PipelineStage
      */
     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);
index 286332e0899df001bccc767c2746158a5fe10678..47a9a4b9af297036fa8ffcea408e6066326f9f72 100644 (file)
@@ -340,6 +340,12 @@ Resource::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num,
     }
 }
 
+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)
@@ -407,7 +413,7 @@ ResourceRequest::ResourceRequest(Resource *_res, DynInstPtr _inst,
                                  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)
 {
 #ifdef DEBUG
         reqID = resReqID++;
index 2cf8e61eb3de9058614c8057e90013e75001f212..f7c4b8fcd728b9ff96da3170fca0bf2e62f94e31 100644 (file)
@@ -156,6 +156,9 @@ class Resource {
     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
      */
@@ -376,8 +379,8 @@ class ResourceRequest
     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 */
@@ -386,11 +389,12 @@ class ResourceRequest
     int resIdx;
     int slotNum;
 
-    /** Resource Status */
+    /** Resource Request Status */
     bool completed;
     bool squashed;
     bool processing;
-    bool waiting;
+
+    bool memStall;
 };
 
 #endif //__CPU_INORDER_RESOURCE_HH__
index 0d78c232bbd2f26cd7599baf7c9f6e46d32ac563..8822715c73ddd21d3efa1ce3562fd8ea336235b5 100644 (file)
@@ -41,45 +41,62 @@ using namespace ThePipeline;
 ResourcePool::ResourcePool(InOrderCPU *_cpu, ThePipeline::Params *params)
     : cpu(_cpu)
 {
-    //@todo: use this function to instantiate the resources in resource pool. This will help in the
-    //auto-generation of this pipeline model.
+    //@todo: use this function to instantiate the resources in resource pool. 
+    //This will help in the auto-generation of this pipeline model.
     //ThePipeline::addResources(resources, memObjects);
 
     // Declare Resource Objects
     // name - id - bandwidth - latency - CPU - Parameters
     // --------------------------------------------------
-    resources.push_back(new FetchSeqUnit("Fetch-Seq-Unit", FetchSeq, StageWidth * 2, 0, _cpu, params));
+    resources.push_back(new FetchSeqUnit("Fetch-Seq-Unit", FetchSeq, 
+                                         StageWidth * 2, 0, _cpu, params));
 
     memObjects.push_back(ICache);
-    resources.push_back(new CacheUnit("icache_port", ICache, StageWidth * MaxThreads, 0, _cpu, params));
+    resources.push_back(new CacheUnit("icache_port", ICache, 
+                                      StageWidth * MaxThreads, 0, _cpu, 
+                                      params));
 
-    resources.push_back(new DecodeUnit("Decode-Unit", Decode, StageWidth, 0, _cpu, params));
+    resources.push_back(new DecodeUnit("Decode-Unit", Decode, 
+                                       StageWidth, 0, _cpu, params));
 
-    resources.push_back(new BranchPredictor("Branch-Predictor", BPred, StageWidth, 0, _cpu, params));
+    resources.push_back(new BranchPredictor("Branch-Predictor", BPred, 
+                                            StageWidth, 0, _cpu, params));
 
-    resources.push_back(new InstBuffer("Fetch-Buffer-T0", FetchBuff, 4, 0, _cpu, params));
+    resources.push_back(new InstBuffer("Fetch-Buffer-T0", FetchBuff, 4, 
+                                       0, _cpu, params));
 
-    resources.push_back(new UseDefUnit("RegFile-Manager", RegManager, StageWidth * MaxThreads, 0, _cpu, params));
+    resources.push_back(new UseDefUnit("RegFile-Manager", RegManager, 
+                                       StageWidth * MaxThreads, 0, _cpu, 
+                                       params));
 
-    resources.push_back(new AGENUnit("AGEN-Unit", AGEN, StageWidth, 0, _cpu, params));
+    resources.push_back(new AGENUnit("AGEN-Unit", AGEN, 
+                                     StageWidth, 0, _cpu, params));
 
-    resources.push_back(new ExecutionUnit("Execution-Unit", ExecUnit, StageWidth, 0, _cpu, params));
+    resources.push_back(new ExecutionUnit("Execution-Unit", ExecUnit, 
+                                          StageWidth, 0, _cpu, params));
 
-    resources.push_back(new MultDivUnit("Mult-Div-Unit", MDU, 5, 0, _cpu, params));
+    resources.push_back(new MultDivUnit("Mult-Div-Unit", MDU, 5, 0, _cpu, 
+                                        params));
 
     memObjects.push_back(DCache);
-    resources.push_back(new CacheUnit("dcache_port", DCache, StageWidth * MaxThreads, 0, _cpu, params));
+    resources.push_back(new CacheUnit("dcache_port", DCache, 
+                                      StageWidth * MaxThreads, 0, _cpu, 
+                                      params));
 
-    resources.push_back(new GraduationUnit("Graduation-Unit", Grad, StageWidth * MaxThreads, 0, _cpu, params));
+    resources.push_back(new GraduationUnit("Graduation-Unit", Grad, 
+                                           StageWidth * MaxThreads, 0, _cpu, 
+                                           params));
 
-    resources.push_back(new InstBuffer("Fetch-Buffer-T1", FetchBuff2, 4, 0, _cpu, params));
+    resources.push_back(new InstBuffer("Fetch-Buffer-T1", FetchBuff2, 4, 
+                                       0, _cpu, params));
 }
 
 void
 ResourcePool::init()
 {
     for (int i=0; i < resources.size(); i++) {
-        DPRINTF(Resource, "Initializing resource: %s.\n", resources[i]->name());
+        DPRINTF(Resource, "Initializing resource: %s.\n", 
+                resources[i]->name());
         
         resources[i]->init();
     }
@@ -113,8 +130,8 @@ ResourcePool::getPort(const std::string &if_name, int idx)
         int obj_idx = memObjects[i];
         Port *port = resources[obj_idx]->getPort(if_name, idx);
         if (port != NULL) {
-            DPRINTF(Resource, "%s set to resource %s(#%i) in Resource Pool.\n", if_name,
-                    resources[obj_idx]->name(), obj_idx);
+            DPRINTF(Resource, "%s set to resource %s(#%i) in Resource Pool.\n", 
+                    if_name, resources[obj_idx]->name(), obj_idx);
             return port;
         }
     }
@@ -131,7 +148,8 @@ ResourcePool::getPortIdx(const std::string &port_name)
         unsigned obj_idx = memObjects[i];
         Port *port = resources[obj_idx]->getPort(port_name, obj_idx);
         if (port != NULL) {
-            DPRINTF(Resource, "Returning Port Idx %i for %s.\n", obj_idx, port_name);
+            DPRINTF(Resource, "Returning Port Idx %i for %s.\n", obj_idx, 
+                    port_name);
             return obj_idx;
         }
     }
@@ -167,7 +185,8 @@ void
 ResourcePool::squash(DynInstPtr inst, int res_idx, InstSeqNum done_seq_num,
                      ThreadID tid)
 {
-    resources[res_idx]->squash(inst, ThePipeline::NumStages-1, done_seq_num, tid);
+    resources[res_idx]->squash(inst, ThePipeline::NumStages-1, done_seq_num, 
+                               tid);
 }
 
 int
@@ -192,15 +211,17 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
     {
       case InOrderCPU::ActivateThread:
         {
-            DPRINTF(Resource, "Scheduling Activate Thread Resource Pool Event for tick %i.\n",
-                    curTick + delay);
-            ResPoolEvent *res_pool_event = new ResPoolEvent(this,
-                                                            e_type,
-                                                            inst,
-                                                            inst->squashingStage,
-                                                            inst->bdelaySeqNum,
-                                                            inst->readTid());
-            mainEventQueue.schedule(res_pool_event, curTick + cpu->ticks(delay));
+            DPRINTF(Resource, "Scheduling Activate Thread Resource Pool Event "
+                    "for tick %i.\n", curTick + delay);
+            ResPoolEvent *res_pool_event = 
+                new ResPoolEvent(this,
+                                 e_type,
+                                 inst,
+                                 inst->squashingStage,
+                                 inst->bdelaySeqNum,
+                                 inst->readTid());
+            mainEventQueue.schedule(res_pool_event, 
+                                    curTick + cpu->ticks(delay));
         }
         break;
 
@@ -208,49 +229,72 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
       case InOrderCPU::DeallocateThread:
         {
 
-            DPRINTF(Resource, "Scheduling Deactivate Thread Resource Pool Event for tick %i.\n",
-                    curTick + delay);
-            ResPoolEvent *res_pool_event = new ResPoolEvent(this,
-                                                            e_type,
-                                                            inst,
-                                                            inst->squashingStage,
-                                                            inst->bdelaySeqNum,
-                                                            tid);
+            DPRINTF(Resource, "Scheduling Deactivate Thread Resource Pool "
+                    "Event for tick %i.\n", curTick + delay);
+            ResPoolEvent *res_pool_event = 
+                new ResPoolEvent(this,
+                                 e_type,
+                                 inst,
+                                 inst->squashingStage,
+                                 inst->bdelaySeqNum,
+                                 tid);
 
-            mainEventQueue.schedule(res_pool_event, curTick + cpu->ticks(delay));
+            mainEventQueue.schedule(res_pool_event, 
+                                    curTick + cpu->ticks(delay));
 
         }
         break;
 
       case ResourcePool::InstGraduated:
         {
-            DPRINTF(Resource, "Scheduling Inst-Graduated Resource Pool Event for tick %i.\n",
-                    curTick + delay);
-            ResPoolEvent *res_pool_event = new ResPoolEvent(this,e_type,
-                                                            inst,
-                                                            inst->squashingStage,
-                                                            inst->seqNum,
-                                                            inst->readTid());
-            mainEventQueue.schedule(res_pool_event, curTick + cpu->ticks(delay));
+            DPRINTF(Resource, "Scheduling Inst-Graduated Resource Pool "
+                    "Event for tick %i.\n", curTick + delay);
+            ResPoolEvent *res_pool_event = 
+                new ResPoolEvent(this,e_type,
+                                 inst,
+                                 inst->squashingStage,
+                                 inst->seqNum,
+                                 inst->readTid());
+            mainEventQueue.schedule(res_pool_event, 
+                                    curTick + cpu->ticks(delay));
 
         }
         break;
 
       case ResourcePool::SquashAll:
         {
-            DPRINTF(Resource, "Scheduling Squash Resource Pool Event for tick %i.\n",
+            DPRINTF(Resource, "Scheduling Squash Resource Pool Event for "
+                    "tick %i.\n", curTick + delay);
+            ResPoolEvent *res_pool_event = 
+                new ResPoolEvent(this,e_type,
+                                 inst,
+                                 inst->squashingStage,
+                                 inst->bdelaySeqNum,
+                                 inst->readTid());
+            mainEventQueue.schedule(res_pool_event, 
+                                    curTick + cpu->ticks(delay));
+        }
+        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->bdelaySeqNum,
-                                                            inst->readTid());
-            mainEventQueue.schedule(res_pool_event, curTick + cpu->ticks(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]);
+        DPRINTF(Resource, "Ignoring Unrecognized CPU Event (%s).\n", 
+                InOrderCPU::eventNames[e_type]);
         ; // If Resource Pool doesnt recognize event, we ignore it.
     }
 }
@@ -265,8 +309,8 @@ void
 ResourcePool::squashAll(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);
+    DPRINTF(Resource, "[tid:%i] Stage %i squashing all instructions above "
+            "[sn:%i].\n", stage_num, tid, done_seq_num);
 
     int num_resources = resources.size();
 
@@ -275,11 +319,26 @@ ResourcePool::squashAll(DynInstPtr inst, int stage_num,
     }
 }
 
+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",
-            tid);
+    DPRINTF(Resource, "[tid:%i] Broadcasting Thread Activation to all "
+            "resources.\n", tid);
 
     int num_resources = resources.size();
 
@@ -291,8 +350,8 @@ ResourcePool::activateAll(ThreadID tid)
 void
 ResourcePool::deactivateAll(ThreadID tid)
 {
-    DPRINTF(Resource, "[tid:%i] Broadcasting Thread Deactivation to all resources.\n",
-            tid);
+    DPRINTF(Resource, "[tid:%i] Broadcasting Thread Deactivation to all "
+            "resources.\n", tid);
 
     int num_resources = resources.size();
 
@@ -304,8 +363,8 @@ ResourcePool::deactivateAll(ThreadID tid)
 void
 ResourcePool::instGraduated(InstSeqNum seq_num, ThreadID tid)
 {
-    DPRINTF(Resource, "[tid:%i] Broadcasting [sn:%i] graduation to all resources.\n",
-            tid, seq_num);
+    DPRINTF(Resource, "[tid:%i] Broadcasting [sn:%i] graduation to all "
+            "resources.\n", tid, seq_num);
 
     int num_resources = resources.size();
 
@@ -353,6 +412,10 @@ ResourcePool::ResPoolEvent::process()
         resPool->squashAll(inst, stageNum, seqNum, tid);
         break;
 
+      case InOrderCPU::SquashFromMemStall:
+        resPool->squashDueToMemStall(inst, stageNum, seqNum, tid);
+        break;
+
       default:
         fatal("Unrecognized Event Type");
     }
index 016fae2bf83c3ad8466fb865b584d7176a30e3f4..61e691f350fd8ad094a962db17c36e19474ed674 100644 (file)
@@ -123,7 +123,7 @@ class ResourcePool {
     };
 
   public:
-  ResourcePool(InOrderCPU *_cpu, ThePipeline::Params *params);
+    ResourcePool(InOrderCPU *_cpu, ThePipeline::Params *params);
     virtual ~ResourcePool() {}
 
     std::string name();
@@ -160,6 +160,12 @@ class ResourcePool {
     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);
 
index eb66e10f82a88a1c036a64d9b0ec9f1d77c1c063..570d27fbef04f7a48bf1e535e40141d0ea7c4833 100644 (file)
@@ -241,8 +241,8 @@ CacheUnit::requestAgain(DynInstPtr inst, bool &service_request)
         // If different, then update command in the request
         cache_req->cmd = inst->resSched.top()->cmd;
         DPRINTF(InOrderCachePort,
-                "[tid:%i]: [sn:%i]: Updating the command for this instruction\n",
-                inst->readTid(), inst->seqNum);
+                "[tid:%i]: [sn:%i]: Updating the command for this "
+                "instruction\n ", inst->readTid(), inst->seqNum);
 
         service_request = true;
     } else {
@@ -416,6 +416,7 @@ CacheUnit::execute(int slot_num)
                     tid, seq_num, inst->staticInst->disassemble(inst->PC));
 
             delete cache_req->dataPkt;
+            //cache_req->setMemStall(false);            
             cache_req->done();
         } else {
             DPRINTF(InOrderCachePort,
@@ -425,6 +426,7 @@ CacheUnit::execute(int slot_num)
                     "STALL: [tid:%i]: Fetch miss from %08p\n",
                     tid, cache_req->inst->readPC());
             cache_req->setCompleted(false);
+            //cache_req->setMemStall(true);            
         }
         break;
 
@@ -437,11 +439,13 @@ CacheUnit::execute(int slot_num)
         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;
 
@@ -510,7 +514,8 @@ CacheUnit::doCacheAccess(DynInstPtr inst, uint64_t *write_res)
     if (cache_req->pktCmd == MemCmd::WriteReq) {
         cache_req->pktCmd =
             cache_req->memReq->isSwap() ? MemCmd::SwapReq :
-            (cache_req->memReq->isLLSC() ? MemCmd::StoreCondReq : MemCmd::WriteReq);
+            (cache_req->memReq->isLLSC() ? MemCmd::StoreCondReq 
+             : MemCmd::WriteReq);
     }
 
     cache_req->dataPkt = new CacheReqPacket(cache_req, cache_req->pktCmd,
@@ -641,8 +646,9 @@ CacheUnit::processCacheCompletion(PacketPtr pkt)
             ExtMachInst ext_inst;
             StaticInstPtr staticInst = NULL;
             Addr inst_pc = inst->readPC();
-            MachInst mach_inst = TheISA::gtoh(*reinterpret_cast<TheISA::MachInst *>
-                                (cache_pkt->getPtr<uint8_t>()));
+            MachInst mach_inst = 
+                TheISA::gtoh(*reinterpret_cast<TheISA::MachInst *>
+                             (cache_pkt->getPtr<uint8_t>()));
 
             predecoder.setTC(cpu->thread[tid]->getTC());
             predecoder.moreBytes(inst_pc, inst_pc, mach_inst);
@@ -755,7 +761,8 @@ CacheUnitEvent::process()
 
     tlb_res->tlbBlocked[tid] = false;
 
-    tlb_res->cpu->pipelineStage[stage_num]->unsetResStall(tlb_res->reqMap[slotIdx], tid);
+    tlb_res->cpu->pipelineStage[stage_num]->
+        unsetResStall(tlb_res->reqMap[slotIdx], tid);
 
     req_ptr->tlbStall = false;
 
@@ -764,6 +771,23 @@ CacheUnitEvent::process()
     }
 }
 
+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)
@@ -798,7 +822,8 @@ CacheUnit::squash(DynInstPtr inst, int stage_num,
 
                 int stall_stage = reqMap[req_slot_num]->getStageNum();
 
-                cpu->pipelineStage[stall_stage]->unsetResStall(reqMap[req_slot_num], tid);
+                cpu->pipelineStage[stall_stage]->
+                    unsetResStall(reqMap[req_slot_num], tid);
             }
 
             if (!cache_req->tlbStall && !cache_req->isMemAccPending()) {
@@ -927,14 +952,16 @@ CacheUnit::write(DynInstPtr inst, uint8_t data, Addr addr,
 
 template<>
 Fault
-CacheUnit::write(DynInstPtr inst, double data, Addr addr, unsigned flags, uint64_t *res)
+CacheUnit::write(DynInstPtr inst, double data, Addr addr, unsigned flags, 
+                 uint64_t *res)
 {
     return write(inst, *(uint64_t*)&data, addr, flags, res);
 }
 
 template<>
 Fault
-CacheUnit::write(DynInstPtr inst, float data, Addr addr, unsigned flags, uint64_t *res)
+CacheUnit::write(DynInstPtr inst, float data, Addr addr, unsigned flags, 
+                 uint64_t *res)
 {
     return write(inst, *(uint32_t*)&data, addr, flags, res);
 }
@@ -942,7 +969,8 @@ CacheUnit::write(DynInstPtr inst, float data, Addr addr, unsigned flags, uint64_
 
 template<>
 Fault
-CacheUnit::write(DynInstPtr inst, int32_t data, Addr addr, unsigned flags, uint64_t *res)
+CacheUnit::write(DynInstPtr inst, int32_t data, Addr addr, unsigned flags, 
+                 uint64_t *res)
 {
     return write(inst, (uint32_t)data, addr, flags, res);
 }
index c467e977188f7d69ba9a708072a7fb1b074ab57c..a6b07ebd9f40c4cf7e667dea7286f267687456c8 100644 (file)
@@ -146,6 +146,9 @@ class CacheUnit : public Resource
     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);