GCC: Get everything working with gcc 4.6.1.
[gem5.git] / src / cpu / inorder / first_stage.cc
index 5e389b256b5a59c5cc78cb2cb5bc7e9ed6e8e90d..20fd9169fe204571cf4292ed1a225190c85f685a 100644 (file)
  */
 
 #include "base/str.hh"
-#include "cpu/inorder/first_stage.hh"
 #include "cpu/inorder/resources/resource_list.hh"
-#include "cpu/inorder/resource_pool.hh"
 #include "cpu/inorder/cpu.hh"
+#include "cpu/inorder/first_stage.hh"
+#include "cpu/inorder/resource_pool.hh"
+#include "debug/InOrderStage.hh"
 #include "params/InOrderTrace.hh"
 
 using namespace std;
@@ -43,7 +44,7 @@ FirstStage::FirstStage(Params *params, unsigned stage_num)
     : PipelineStage(params, stage_num), numFetchingThreads(1),
       fetchPolicy(FirstStage::RoundRobin)
 {
-    for(int tid=0; tid < this->numThreads; tid++) {
+    for(ThreadID tid = 0; tid < this->numThreads; tid++) {
         stageStatus[tid] = Running;
     }
 }
@@ -60,31 +61,33 @@ FirstStage::setCPU(InOrderCPU *cpu_ptr)
 
 
 void
-FirstStage::squash(InstSeqNum squash_seq_num, unsigned tid)
+FirstStage::squash(InstSeqNum squash_seq_num, ThreadID tid)
 {
     // Set status to squashing.
     //stageStatus[tid] = Squashing;
 
     // Clear the instruction list and skid buffer in case they have any
     // insts in them.
-    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, "Removing instructions from stage instruction "
+            "list.\n");
+    while (!skidBuffer[tid].empty()) {
+        if (skidBuffer[tid].front()->seqNum <= squash_seq_num) {
+            DPRINTF(InOrderStage,"[tid:%i]: Cannot remove [sn:%i] because "
+                    "it's <= squashing seqNum %i.\n",
                     tid,
-                    insts[tid].front()->seqNum,
+                    skidBuffer[tid].front()->seqNum,
                     squash_seq_num);
 
             DPRINTF(InOrderStage, "[tid:%i]: Cannot remove incoming "
                     "instructions before delay slot [sn:%i]. %i insts"
                     "left.\n", tid, squash_seq_num,
-                    insts[tid].size());
+                    skidBuffer[tid].size());
             break;
         }
-        DPRINTF(InOrderStage, "[tid:%i]: Removing instruction, [sn:%i] PC %08p.\n",
-                tid, insts[tid].front()->seqNum, insts[tid].front()->PC);
-        insts[tid].pop();
+        DPRINTF(InOrderStage, "[tid:%i]: Removing instruction, [sn:%i] "
+                "PC %s.\n", tid, skidBuffer[tid].front()->seqNum,
+                skidBuffer[tid].front()->pc);
+        skidBuffer[tid].pop_front();
     }
 
     // Now that squash has propagated to the first stage,
@@ -93,51 +96,77 @@ FirstStage::squash(InstSeqNum squash_seq_num, unsigned 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)
 {
-    list<unsigned>::iterator threads = (*activeThreads).begin();
+    list<ThreadID>::iterator threads = activeThreads->begin();
 
     //Check stall and squash signals.
-    while (threads != (*activeThreads).end()) {
-        unsigned tid = *threads++;
+    while (threads != activeThreads->end()) {
+        ThreadID tid = *threads++;
         status_change =  checkSignalsAndUpdate(tid) || status_change;
     }
 
-    for (int threadFetched = 0; threadFetched < numFetchingThreads;
-         threadFetched++) {
-        int tid = getFetchingThread(fetchPolicy);
+    while (instsProcessed < stageWidth)  {
+        ThreadID tid = getFetchingThread(fetchPolicy);
 
         if (tid >= 0) {
             DPRINTF(InOrderStage, "Processing [tid:%i]\n",tid);
             processThread(status_change, tid);
+            DPRINTF(InOrderStage, "Done Processing [tid:%i]\n",tid);
         } else {
             DPRINTF(InOrderStage, "No more threads to fetch from.\n");
+            break;
         }
     }
+
+    if (instsProcessed > 0) {
+        ++runCycles;
+        idle = false;        
+    } else {
+        ++idleCycles;
+        idle = true;        
+    }
+
 }
 
-//@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(unsigned tid)
+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 = instsProcessed;
+         insts_fetched < stageWidth;
+         insts_fetched++) {
+
         DynInstPtr inst;
         bool new_inst = false;
 
-        if (!insts[tid].empty()) {
-            inst = insts[tid].front();
+        if (!skidBuffer[tid].empty()) {
+            inst = skidBuffer[tid].front();
         } else {
             // Get new instruction.
             new_inst = true;
 
             inst = new InOrderDynInst(cpu,
-                                    cpu->thread[tid],
-                                    cpu->nextInstSeqNum(tid),
-                                    tid);
+                                      cpu->thread[tid],
+                                      cpu->nextInstSeqNum(tid),
+                                      tid,
+                                      tid);
 
 #if TRACING_ON
             inst->traceData =
@@ -145,87 +174,88 @@ FirstStage::processInsts(unsigned tid)
                                       cpu->stageTracing,
                                       cpu->thread[tid]->getTC());
 
+#else
+            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);
+            inst->setFrontSked(cpu->frontEndSked);
         }
 
-        // Don't let instruction pass to next stage if it hasnt completed
-        // all of it's requests for this stage.
-        all_reqs_completed = processInstSchedule(inst);
+        int reqs_processed = 0;            
+        all_reqs_completed = processInstSchedule(inst, reqs_processed);
+
+        // If the instruction isnt squashed & we've completed one request
+        // Then we can officially count this instruction toward the stage's 
+        // bandwidth count
+        if (reqs_processed > 0)
+            instsProcessed++;
 
-        if (!all_reqs_completed) {
+        if (!all_reqs_completed || !sendInstToNextStage(inst)) {
             if (new_inst) {
                 DPRINTF(InOrderStage, "[tid:%u]: [sn:%u] Did not finish all "
                         "requests for this stage. Keep in stage inst. "
                         "list.\n", tid, inst->seqNum);
-                insts[tid].push(inst);
+                skidBuffer[tid].push_back(inst);
             }
+            block(tid);
             break;
-        } else if (!insts[tid].empty()){
-            insts[tid].pop();
+        } else if (!skidBuffer[tid].empty()){
+            DPRINTF(InOrderStage, "[tid:%u]: [sn:%u] Finished all "
+                    "requests for this stage.\n", tid, inst->seqNum);
+            skidBuffer[tid].pop_front();
         }
 
-        sendInstToNextStage(inst);
-        //++stageProcessedInsts;
     }
 
     // Record that stage has written to the time buffer for activity
     // tracking.
-    if (toNextStageIndex) {
+    if (instsProcessed) {
         wroteToTimeBuffer = true;
     }
 }
 
-int
+ThreadID
 FirstStage::getFetchingThread(FetchPriority &fetch_priority)
 {
-    if (numThreads > 1) {
-        switch (fetch_priority) {
+    ThreadID num_active_threads = cpu->numActiveThreads();
 
+    if (num_active_threads > 1) {
+        switch (fetch_priority) {
           case SingleThread:
-            return 0;
+            return cpu->activeThreadId();
 
           case RoundRobin:
             return roundRobin();
 
           default:
-            return -1;
+            return InvalidThreadID;
         }
-    } else {
-        int tid = *((*activeThreads).begin());
+    } else if (num_active_threads == 1) {
+        ThreadID tid = *activeThreads->begin();
 
         if (stageStatus[tid] == Running ||
-            stageStatus[tid] == Idle) {
+            stageStatus[tid] == Idle ||
+            stageStatus[tid] == Unblocking) {
             return tid;
         } else {
-            return -1;
+            return InvalidThreadID;
         }
-    }
-
+    } else {
+        return InvalidThreadID;
+    }    
 }
 
-int
+ThreadID
 FirstStage::roundRobin()
 {
-    list<unsigned>::iterator pri_iter = (*fetchPriorityList).begin();
-    list<unsigned>::iterator end      = (*fetchPriorityList).end();
+    list<ThreadID>::iterator pri_iter = fetchPriorityList->begin();
+    list<ThreadID>::iterator end      = fetchPriorityList->end();
 
-    int high_pri;
+    ThreadID high_pri;
 
     while (pri_iter != end) {
         high_pri = *pri_iter;
@@ -233,10 +263,11 @@ FirstStage::roundRobin()
         assert(high_pri <= numThreads);
 
         if (stageStatus[high_pri] == Running ||
-            stageStatus[high_pri] == Idle) {
+            stageStatus[high_pri] == Idle ||
+            stageStatus[high_pri] == Unblocking){
 
-            (*fetchPriorityList).erase(pri_iter);
-            (*fetchPriorityList).push_back(high_pri);
+            fetchPriorityList->erase(pri_iter);
+            fetchPriorityList->push_back(high_pri);
 
             return high_pri;
         }
@@ -244,5 +275,5 @@ FirstStage::roundRobin()
         pri_iter++;
     }
 
-    return -1;
+    return InvalidThreadID;
 }