inorder: add updatePC event to resPool
authorKorey Sewell <ksewell@umich.edu>
Sun, 31 Jan 2010 23:27:49 +0000 (18:27 -0500)
committerKorey Sewell <ksewell@umich.edu>
Sun, 31 Jan 2010 23:27:49 +0000 (18:27 -0500)
this will be used for when a thread comes back from a cache miss, it needs to update the PCs
because the inst might of been a branch or delayslot in which the next PC isnt always
a straight addition

src/cpu/inorder/pipeline_stage.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/fetch_seq_unit.cc
src/cpu/inorder/resources/fetch_seq_unit.hh

index ef91f206b89f7762c3e26ec87dfcfe16c12a0b92..620951e34a8cc05e2b2984691b0935dc4dfbfbdd 100644 (file)
@@ -571,10 +571,15 @@ PipelineStage::activateThread(ThreadID tid)
             DPRINTF(InOrderStage,"[tid:%i]: Re-Inserting [sn:%lli] PC:%#x into stage skidBuffer %i\n",
                     tid, inst->seqNum, inst->readPC(), inst->threadNumber);
 
+            // Make instruction available for pipeline processing
             skidBuffer[tid].push(inst);            
 
-            switchedOutBuffer[tid] = NULL;
+            // Update PC so that we start fetching after this instruction to prevent
+            // "double"-execution of instructions
+            cpu->resPool->scheduleEvent((InOrderCPU::CPUEventType)ResourcePool::UpdateAfterContextSwitch, inst, 0, 0, tid);
 
+            // Clear switchout buffer
+            switchedOutBuffer[tid] = NULL;
             switchedOutValid[tid] = false;            
         }        
     }
index 4ae4db818c774876e775c06774a7c42089994f4e..383340df2e174934cc333c70c561d7e5dbb1e450 100644 (file)
@@ -96,6 +96,10 @@ class Resource {
     /** Resources that care about thread activation override this. */
     virtual void suspendThread(ThreadID tid) { }
     
+    /** Will be called the cycle before a context switch. Any bookkeeping
+     *  that needs to be kept for that, can be done here
+     */
+    virtual void updateAfterContextSwitch(DynInstPtr inst, ThreadID tid) { }    
 
     /** Resources that care when an instruction has been graduated
      *  can override this
index 45a4a9e6000211ecda14e8baae34e4bb6e80205d..20f112a660bff03099dd2e22b555ba72bfda7273 100644 (file)
@@ -201,6 +201,9 @@ ResourcePool::slotsInUse(int res_idx)
     return resources[res_idx]->slotsInUse();
 }
 
+//@todo: split this function and call this version schedulePoolEvent
+//       and use this scheduleEvent for scheduling a specific event on 
+//       a resource
 void
 ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
                             int delay,  int res_idx, ThreadID tid)
@@ -310,6 +313,20 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
         }
         break;
 
+      case ResourcePool::UpdateAfterContextSwitch:
+        {
+            DPRINTF(Resource, "Scheduling UpdatePC 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;
+
       default:
         DPRINTF(Resource, "Ignoring Unrecognized CPU Event (%s).\n", 
                 InOrderCPU::eventNames[e_type]);
@@ -415,6 +432,19 @@ ResourcePool::instGraduated(InstSeqNum seq_num, ThreadID tid)
     }
 }
 
+void
+ResourcePool::updateAfterContextSwitch(DynInstPtr inst, ThreadID tid)
+{
+    DPRINTF(Resource, "[tid:%i] Broadcasting Update PC to all resources.\n",
+            tid);
+
+    int num_resources = resources.size();
+
+    for (int idx = 0; idx < num_resources; idx++) {
+        resources[idx]->updateAfterContextSwitch(inst, tid);
+    }
+}
+
 ResourcePool::ResPoolEvent::ResPoolEvent(ResourcePool *_resPool)
     : Event((Event::Priority)((unsigned)CPU_Tick_Pri+5)), resPool(_resPool),
       eventType((InOrderCPU::CPUEventType) Default)
@@ -462,6 +492,10 @@ ResourcePool::ResPoolEvent::process()
         resPool->squashDueToMemStall(inst, stageNum, seqNum, tid);
         break;
 
+      case ResourcePool::UpdateAfterContextSwitch:
+        resPool->updateAfterContextSwitch(inst, tid);
+        break;
+
       default:
         fatal("Unrecognized Event Type");
     }
index ae63c4c593d26c64e2e6362c32d8a78f168a15fd..3f62d2caafc333b0365a45b3991e63fb6155ccbd 100644 (file)
@@ -63,6 +63,7 @@ class ResourcePool {
     enum ResPoolEventType {
         InstGraduated = InOrderCPU::NumCPUEvents,
         SquashAll,
+        UpdateAfterContextSwitch,
         Default
     };
 
@@ -175,6 +176,9 @@ class ResourcePool {
     /** De-Activate Thread in all resources */
     void suspendAll(ThreadID tid);
 
+    /** Broadcast Context Switch Update to all resources */
+    void updateAfterContextSwitch(DynInstPtr inst, ThreadID tid);
+
     /** Broadcast graduation to all resources */
     void instGraduated(InstSeqNum seq_num, ThreadID tid);
 
index 2cf6c319559002005b93014e56429f43d0bfdf08..4f9ed3ecaea3ee4d92085b8c92464c524fae11ae 100644 (file)
@@ -49,14 +49,14 @@ using namespace ThePipeline;
 Tick
 CacheUnit::CachePort::recvAtomic(PacketPtr pkt)
 {
-    panic("DefaultFetch doesn't expect recvAtomic callback!");
+    panic("CacheUnit::CachePort doesn't expect recvAtomic callback!");
     return curTick;
 }
 
 void
 CacheUnit::CachePort::recvFunctional(PacketPtr pkt)
 {
-    panic("DefaultFetch doesn't expect recvFunctional callback!");
+    panic("CacheUnit::CachePort doesn't expect recvFunctional callback!");
 }
 
 void
@@ -65,7 +65,7 @@ CacheUnit::CachePort::recvStatusChange(Status status)
     if (status == RangeChange)
         return;
 
-    panic("DefaultFetch doesn't expect recvStatusChange callback!");
+    panic("CacheUnit::CachePort doesn't expect recvStatusChange callback!");
 }
 
 bool
index e0b9ea1f96f5b5c86cd33e7d3b6e5704728f9741..c217f972e6047de8bf448b4ca61e763de764fdaa 100644 (file)
@@ -342,3 +342,17 @@ FetchSeqUnit::suspendThread(ThreadID tid)
 {
     deactivateThread(tid);    
 }
+
+void
+FetchSeqUnit::updateAfterContextSwitch(DynInstPtr inst, ThreadID tid)
+{
+    pcValid[tid] = true;
+
+    PC[tid] = inst->readNextPC();
+    nextPC[tid] = inst->readNextNPC();
+    nextNPC[tid] = inst->readNextNPC() + instSize;
+
+
+    DPRINTF(InOrderFetchSeq, "[tid:%i]: Updating  PC:%08p NPC:%08p NNPC:%08p.\n",
+            tid, PC[tid], nextPC[tid], nextNPC[tid]);
+}
index fdbc4521f989862ed6b0269f01f311fe393f7b55..3283e0330a82bb81c39611465c52dc15c362426f 100644 (file)
@@ -61,6 +61,8 @@ class FetchSeqUnit : public Resource {
     virtual void deactivateThread(ThreadID tid);
     virtual void suspendThread(ThreadID tid);
     virtual void execute(int slot_num);
+    void updateAfterContextSwitch(DynInstPtr inst, ThreadID tid);
+    
 
     /** Override default Resource squash sequence. This actually,
      *  looks in the global communication buffer to get squash