# HG changeset patch
# User Korey Sewell <[email protected]>
# Date 1254427253 14400
# Node ID bfed5a5a12278f9dff5feee73ae28052b11f52af
# Parent  15a99db60a81fdd86c7ff5611c1031c92839ee56
inorder: track last branch committed
when threads are switching in/out the CPU, we need to keep
track of special cases like branches. Add appropriate
variables in ThreadState t track this and then use
these variables when updating pc after context switch

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
@@ -690,7 +690,9 @@
         activeThreads.push_back(tid);
         
         activateThreadInPipeline(tid);
-        
+
+        thread[tid]->lastActivate = curTick;            
+
         wakeCPU();
     }
 }
@@ -869,6 +871,7 @@
     DPRINTF(InOrderCPU, "[tid: %i]: Placing on Suspended Threads List...\n", 
tid);
     deactivateThread(tid);
     suspendedThreads.push_back(tid);    
+    thread[tid]->lastSuspend = curTick;    
 }
 
 void
@@ -1041,13 +1044,24 @@
 void
 InOrderCPU::instDone(DynInstPtr inst, ThreadID tid)
 {
-    // Set the CPU's PCs - This contributes to the precise state of the CPU 
which can be used
-    // when restoring a thread to the CPU after a fork or after an exception
-    // @TODO: Set-Up Grad-Info/Committed-Info to let ThreadState know if it's 
a branch or not
+    // Set the CPU's PCs - This contributes to the precise state of the CPU 
+    // which can be used when restoring a thread to the CPU after any
+    // type of context switching activity (fork, exception, etc.)
     setPC(inst->readPC(), tid);
     setNextPC(inst->readNextPC(), tid);
     setNextNPC(inst->readNextNPC(), tid);
 
+    if (inst->isControl()) {
+        thread[tid]->lastGradIsBranch = true;
+        thread[tid]->lastBranchPC = inst->readPC();
+        thread[tid]->lastBranchNextPC = inst->readNextPC();
+        thread[tid]->lastBranchNextNPC = inst->readNextNPC();        
+    } else {
+         thread[tid]->lastGradIsBranch = false;
+    }
+    
+    
+
     // Finalize Trace Data For Instruction
     if (inst->traceData) {
         //inst->traceData->setCycle(curTick);
@@ -1058,9 +1072,6 @@
         inst->traceData = NULL;
     }
 
-    // Set Last Graduated Instruction In Thread State
-    //thread[tid]->lastGradInst = inst;
-
     // Increment thread-state's instruction count
     thread[tid]->numInst++;
 
@@ -1083,7 +1094,8 @@
 
     // Broadcast to other resources an instruction
     // has been completed
-    resPool->scheduleEvent((CPUEventType)ResourcePool::InstGraduated, inst, 
tid);
+    resPool->scheduleEvent((CPUEventType)ResourcePool::InstGraduated, inst, 
+                           0, 0 , tid);
 
     // Finally, remove instruction from CPU
     removeInst(inst);
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
@@ -551,15 +551,18 @@
         } else {
             DynInstPtr inst = switchedOutBuffer[tid];
 
-            DPRINTF(InOrderStage,"[tid:%i]: Re-Inserting [sn:%lli] PC:%#x into 
stage skidBuffer %i\n",
-                    tid, inst->seqNum, inst->readPC(), inst->threadNumber);
+            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);
+            cpu->resPool->scheduleEvent((InOrderCPU::CPUEventType)
+                                        
ResourcePool::UpdateAfterContextSwitch, 
+                                        inst, 0, 0, tid);
 
             // Clear switchout buffer
             switchedOutBuffer[tid] = NULL;
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
@@ -347,11 +347,23 @@
 {
     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]);
+    if (cpu->thread[tid]->lastGradIsBranch) {
+        /** This function assumes that the instruction causing the context
+         *  switch was right after the branch. Thus, if it's not, then
+         *  we are updating incorrectly here
+         */
+        assert(cpu->thread[tid]->lastBranchNextPC == inst->readPC());
+        
+        PC[tid] = cpu->thread[tid]->lastBranchNextNPC;
+        nextPC[tid] = PC[tid] + instSize;
+        nextNPC[tid] = nextPC[tid] + instSize;
+    } else {
+        PC[tid] = inst->readNextPC();
+        nextPC[tid] = inst->readNextNPC();
+        nextNPC[tid] = inst->readNextNPC() + instSize;        
+    }
+    
+    DPRINTF(InOrderFetchSeq, "[tid:%i]: Updating PCs due to Context Switch."
+            "Assigning  PC:%08p NPC:%08p NNPC:%08p.\n", tid, PC[tid], 
+            nextPC[tid], nextNPC[tid]);
 }
diff --git a/src/cpu/inorder/thread_state.hh b/src/cpu/inorder/thread_state.hh
--- a/src/cpu/inorder/thread_state.hh
+++ b/src/cpu/inorder/thread_state.hh
@@ -79,14 +79,14 @@
 #if FULL_SYSTEM
     InOrderThreadState(InOrderCPU *_cpu, ThreadID _thread_num)
         : ThreadState(reinterpret_cast<BaseCPU*>(_cpu), _thread_num),
-          cpu(_cpu), inSyscall(0), trapPending(0)
+          cpu(_cpu), inSyscall(0), trapPending(0), lastGradIsBranch(false)
     { }
 #else
     InOrderThreadState(InOrderCPU *_cpu, ThreadID _thread_num,
                        Process *_process)
         : ThreadState(reinterpret_cast<BaseCPU*>(_cpu), _thread_num,
                       _process),
-          cpu(_cpu), inSyscall(0), trapPending(0)
+          cpu(_cpu), inSyscall(0), trapPending(0), lastGradIsBranch(false)
     { }
 #endif
 
@@ -105,10 +105,15 @@
     /** Returns a pointer to the TC of this thread. */
     ThreadContext *getTC() { return tc; }
 
+    /** Return the thread id */
     int readTid() { return threadId(); }
 
-    /** Pointer to the last graduated instruction in the thread */
-    //DynInstPtr lastGradInst;
+    
+    /** Is last instruction graduated a branch? */
+    bool lastGradIsBranch;
+    Addr lastBranchPC;    
+    Addr lastBranchNextPC;    
+    Addr lastBranchNextNPC;    
 };
 
 #endif // __CPU_INORDER_THREAD_STATE_HH__
_______________________________________________
m5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/m5-dev

Reply via email to