merge
[gem5.git] / src / cpu / inorder / first_stage.cc
index cc0af13f9d5f5d325621eca84800b448a1484f8b..658ce37d39ef11c252a98a50a1b68c672f8b90dd 100644 (file)
@@ -43,7 +43,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,18 +60,19 @@ 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");
+    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,"[tid:%i]: Cannot remove [sn:%i] because "
+                    "it's <= squashing seqNum %i.\n",
                     tid,
                     insts[tid].front()->seqNum,
                     squash_seq_num);
@@ -82,8 +83,9 @@ FirstStage::squash(InstSeqNum squash_seq_num, unsigned tid)
                     insts[tid].size());
             break;
         }
-        DPRINTF(InOrderStage, "[tid:%i]: Removing instruction, [sn:%i] PC %08p.\n",
-                tid, insts[tid].front()->seqNum, insts[tid].front()->PC);
+        DPRINTF(InOrderStage, "[tid:%i]: Removing instruction, [sn:%i] "
+                "PC %08p.\n", tid, insts[tid].front()->seqNum, 
+                insts[tid].front()->PC);
         insts[tid].pop();
     }
 
@@ -93,20 +95,33 @@ 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);
+    for (int insts_fetched = 0; 
+         insts_fetched < stageWidth && canSendInstToStage(1); 
+         insts_fetched++) {
+        ThreadID tid = getFetchingThread(fetchPolicy);
 
         if (tid >= 0) {
             DPRINTF(InOrderStage, "Processing [tid:%i]\n",tid);
@@ -115,16 +130,28 @@ FirstStage::processStage(bool &status_change)
             DPRINTF(InOrderStage, "No more threads to fetch from.\n");
         }
     }
+
+    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 = 0; 
+         insts_fetched < stageWidth && canSendInstToStage(1); 
+         insts_fetched++) {
+
         DynInstPtr inst;
         bool new_inst = false;
 
@@ -150,26 +177,21 @@ FirstStage::processInsts(unsigned tid)
             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);
         }
 
-        // 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 (new_inst) {
@@ -184,7 +206,6 @@ FirstStage::processInsts(unsigned tid)
         }
 
         sendInstToNextStage(inst);
-        //++stageProcessedInsts;
     }
 
     // Record that stage has written to the time buffer for activity
@@ -194,41 +215,43 @@ FirstStage::processInsts(unsigned tid)
     }
 }
 
-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) {
             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;
@@ -238,8 +261,8 @@ FirstStage::roundRobin()
         if (stageStatus[high_pri] == Running ||
             stageStatus[high_pri] == Idle) {
 
-            (*fetchPriorityList).erase(pri_iter);
-            (*fetchPriorityList).push_back(high_pri);
+            fetchPriorityList->erase(pri_iter);
+            fetchPriorityList->push_back(high_pri);
 
             return high_pri;
         }
@@ -247,5 +270,5 @@ FirstStage::roundRobin()
         pri_iter++;
     }
 
-    return -1;
+    return InvalidThreadID;
 }