# HG changeset patch
# User Korey Sewell <[email protected]>
# Date 1254427253 14400
# Node ID 15a99db60a81fdd86c7ff5611c1031c92839ee56
# Parent  49442d9f1ae850af8d1b1ceb304344cd68b43ca1
inorder: add updatePC event to resPool
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

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
@@ -554,10 +554,15 @@
             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);            
 
+            // 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;            
         }        
     }
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
@@ -94,6 +94,10 @@
     /** 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
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
@@ -182,6 +182,9 @@
     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)
@@ -280,6 +283,20 @@
         }
         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:
         // If Resource Pool doesnt recognize event, we ignore it.
         DPRINTF(Resource, "Ignoring Unrecognized CPU Event (%s).\n", 
InOrderCPU::eventNames[e_type]);
@@ -386,6 +403,19 @@
     }
 }
 
+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)
@@ -433,6 +463,10 @@
         resPool->squashDueToMemStall(inst, stageNum, seqNum, tid);
         break;
 
+      case ResourcePool::UpdateAfterContextSwitch:
+        resPool->updateAfterContextSwitch(inst, 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
@@ -63,6 +63,7 @@
     enum ResPoolEventType {
         InstGraduated = InOrderCPU::NumCPUEvents,
         SquashAll,
+        UpdateAfterContextSwitch,
         Default
     };
 
@@ -175,6 +176,9 @@
     /** 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);
 
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
@@ -47,14 +47,14 @@
 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
@@ -63,7 +63,7 @@
     if (status == RangeChange)
         return;
 
-    panic("DefaultFetch doesn't expect recvStatusChange callback!");
+    panic("CacheUnit::CachePort doesn't expect recvStatusChange callback!");
 }
 
 bool
diff --git a/src/cpu/inorder/resources/fetch_seq_unit.cc 
b/src/cpu/inorder/resources/fetch_seq_unit.cc
--- a/src/cpu/inorder/resources/fetch_seq_unit.cc
+++ b/src/cpu/inorder/resources/fetch_seq_unit.cc
@@ -341,3 +341,17 @@
 {
     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]);
+}
diff --git a/src/cpu/inorder/resources/fetch_seq_unit.hh 
b/src/cpu/inorder/resources/fetch_seq_unit.hh
--- a/src/cpu/inorder/resources/fetch_seq_unit.hh
+++ b/src/cpu/inorder/resources/fetch_seq_unit.hh
@@ -60,6 +60,8 @@
     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
_______________________________________________
m5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/m5-dev

Reply via email to