inorder: track last branch committed
authorKorey Sewell <ksewell@umich.edu>
Sun, 31 Jan 2010 23:27:58 +0000 (18:27 -0500)
committerKorey Sewell <ksewell@umich.edu>
Sun, 31 Jan 2010 23:27:58 +0000 (18:27 -0500)
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

src/cpu/inorder/cpu.cc
src/cpu/inorder/pipeline_stage.cc
src/cpu/inorder/resources/fetch_seq_unit.cc
src/cpu/inorder/thread_state.hh

index 501150386f21e9c123013f36b2f25461f61f2e2d..8d41a18b4d2c6a6bf54365081657a48c7e9998ef 100644 (file)
@@ -709,7 +709,9 @@ InOrderCPU::activateThread(ThreadID tid)
         activeThreads.push_back(tid);
         
         activateThreadInPipeline(tid);
-        
+
+        thread[tid]->lastActivate = curTick;            
+
         wakeCPU();
     }
 }
@@ -888,6 +890,7 @@ InOrderCPU::suspendThread(ThreadID tid)
     DPRINTF(InOrderCPU, "[tid: %i]: Placing on Suspended Threads List...\n", tid);
     deactivateThread(tid);
     suspendedThreads.push_back(tid);    
+    thread[tid]->lastSuspend = curTick;    
 }
 
 void
@@ -1063,15 +1066,22 @@ 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
+    // which can be used when restoring a thread to the CPU after 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);
@@ -1082,9 +1092,6 @@ InOrderCPU::instDone(DynInstPtr inst, ThreadID tid)
         inst->traceData = NULL;
     }
 
-    // Set Last Graduated Instruction In Thread State
-    //thread[tid]->lastGradInst = inst;
-
     // Increment thread-state's instruction count
     thread[tid]->numInst++;
 
@@ -1108,7 +1115,7 @@ InOrderCPU::instDone(DynInstPtr inst, ThreadID tid)
     // Broadcast to other resources an instruction
     // has been completed
     resPool->scheduleEvent((CPUEventType)ResourcePool::InstGraduated, inst, 
-                           tid);
+                           0, 0, tid);
 
     // Finally, remove instruction from CPU
     removeInst(inst);
index 620951e34a8cc05e2b2984691b0935dc4dfbfbdd..55ee3ad128a55184477275978c66e537415c860b 100644 (file)
@@ -568,15 +568,18 @@ PipelineStage::activateThread(ThreadID tid)
         } 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;
index c217f972e6047de8bf448b4ca61e763de764fdaa..ba86a91f0f99a0d30868071dba659ef971984be2 100644 (file)
@@ -348,11 +348,23 @@ 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]);
+    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]);
 }
index 422df30aa13634f8d52bdb3181c1097f9d66674f..0a171a99f26a7470952143ce2f547da88ed1c924 100644 (file)
@@ -79,14 +79,14 @@ class InOrderThreadState : public ThreadState {
 #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 @@ class InOrderThreadState : public ThreadState {
     /** 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__