inorder: pipe. stage inst. buffering
authorKorey Sewell <ksewell@umich.edu>
Fri, 4 Feb 2011 05:08:16 +0000 (00:08 -0500)
committerKorey Sewell <ksewell@umich.edu>
Fri, 4 Feb 2011 05:08:16 +0000 (00:08 -0500)
use skidbuffer as only location for instructions between stages. before,
we had the insts queue from the prior stage and the skidbuffer for the
current stage, but that gets confusing and this consolidation helps
when handling squash cases

src/cpu/inorder/first_stage.cc
src/cpu/inorder/first_stage.hh
src/cpu/inorder/pipeline_stage.cc
src/cpu/inorder/pipeline_stage.hh

index 424d6b6a4981ad47899ce6058c2a16400f442b13..71c6ec3e05cd609dba6bc92b56a27eb068b4c080 100644 (file)
@@ -69,24 +69,24 @@ FirstStage::squash(InstSeqNum squash_seq_num, ThreadID tid)
     // insts in them.
     DPRINTF(InOrderStage, "Removing instructions from stage instruction "
             "list.\n");
-    while (!insts[tid].empty()) {
-        if (insts[tid].front()->seqNum <= squash_seq_num) {
+    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 %s.\n", tid, insts[tid].front()->seqNum,
-                insts[tid].front()->pc);
-        insts[tid].pop();
+                "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,
@@ -118,9 +118,7 @@ FirstStage::processStage(bool &status_change)
         status_change =  checkSignalsAndUpdate(tid) || status_change;
     }
 
-    for (int insts_fetched = 0; 
-         insts_fetched < stageWidth && canSendInstToStage(1); 
-         insts_fetched++) {
+    while (instsProcessed < stageWidth)  {
         ThreadID tid = getFetchingThread(fetchPolicy);
 
         if (tid >= 0) {
@@ -151,14 +149,14 @@ FirstStage::processInsts(ThreadID tid)
     bool all_reqs_completed = true;
 
     for (int insts_fetched = instsProcessed;
-         insts_fetched < stageWidth && canSendInstToStage(1); 
+         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;
@@ -195,22 +193,21 @@ FirstStage::processInsts(ThreadID tid)
         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()){
+        } else if (!skidBuffer[tid].empty()){
             DPRINTF(InOrderStage, "[tid:%u]: [sn:%u] Finished all "
                     "requests for this stage.\n", tid, inst->seqNum);
-            insts[tid].pop();
+            skidBuffer[tid].pop_front();
         }
 
-        sendInstToNextStage(inst);
     }
 
     // Record that stage has written to the time buffer for activity
@@ -240,7 +237,8 @@ FirstStage::getFetchingThread(FetchPriority &fetch_priority)
         ThreadID tid = *activeThreads->begin();
 
         if (stageStatus[tid] == Running ||
-            stageStatus[tid] == Idle) {
+            stageStatus[tid] == Idle ||
+            stageStatus[tid] == Unblocking) {
             return tid;
         } else {
             return InvalidThreadID;
@@ -264,7 +262,8 @@ 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);
index 3a3d550a0fbc536c627c993e4ec598dd2a5a9e82..26151075c09fc1e8149bd9b961f37d86116ab16a 100644 (file)
@@ -68,11 +68,6 @@ class FirstStage : public PipelineStage {
      */
     void sortInsts() {}
 
-    /** There are no skidBuffers for the first stage. So
-     *  just use an empty function.
-     */
-    void skidInsert(ThreadID tid) { }
-
     /** The number of fetching threads in the CPU */
     int numFetchingThreads;
 
index d770597170503bbf9acd66e8fa81cc4136357738..b4b9e497f624f26949b80433aa17134464dc166f 100644 (file)
@@ -272,10 +272,6 @@ PipelineStage::block(ThreadID tid)
     DPRINTF(InOrderStage, "[tid:%d]: Blocking, sending block signal back to "
             "previous stages.\n", tid);
 
-    // Add the current inputs to the skid buffer so they can be
-    // reprocessed when this stage unblocks.
-    // skidInsert(tid);
-
     // If the stage status is blocked or unblocking then stage has not yet
     // signalled fetch to unblock. In that case, there is no need to tell
     // fetch to block.
@@ -412,19 +408,26 @@ PipelineStage::squash(InstSeqNum squash_seq_num, ThreadID tid)
 
     DPRINTF(InOrderStage, "[tid:%i]: Removing instructions from incoming stage"
             " skidbuffer.\n", tid);
-    while (!skidBuffer[tid].empty()) {
-        if (skidBuffer[tid].front()->seqNum <= squash_seq_num) {
+    //@TODO: Walk Through List Using iterator and remove
+    //       all instructions over the value
+    std::list<DynInstPtr>::iterator cur_it = skidBuffer[tid].begin();
+    std::list<DynInstPtr>::iterator end_it = skidBuffer[tid].end();
+
+    while (cur_it != end_it) {
+        if ((*cur_it)->seqNum <= squash_seq_num) {
             DPRINTF(InOrderStage, "[tid:%i]: Cannot remove skidBuffer "
                     "instructions (starting w/[sn:%i]) before delay slot "
                     "[sn:%i]. %i insts left.\n", tid, 
-                    skidBuffer[tid].front()->seqNum, squash_seq_num,
+                    (*cur_it)->seqNum, squash_seq_num,
                     skidBuffer[tid].size());
-            break;
+            cur_it++;
+        } else {
+            DPRINTF(InOrderStage, "[tid:%i]: Removing instruction, [sn:%i] "
+                    " PC %s.\n", tid, (*cur_it)->seqNum, (*cur_it)->pc);
+            (*cur_it)->setSquashed();
+            cur_it = skidBuffer[tid].erase(cur_it);
         }
-        DPRINTF(InOrderStage, "[tid:%i]: Removing instruction, [sn:%i] "
-                " PC %s.\n", tid, skidBuffer[tid].front()->seqNum,
-                skidBuffer[tid].front()->pc);
-        skidBuffer[tid].pop_front();
+
     }
 
 }
@@ -442,7 +445,7 @@ PipelineStage::stageBufferAvail()
         cpu->pipelineStage[stageNum]->prevStage->size :
         0;
 
-    int avail = stageBufferMax - total -0;// incoming_insts;
+    int avail = stageBufferMax - total;
 
     if (avail < 0)
         fatal("stageNum %i:stageBufferAvail() < 0..."
@@ -458,7 +461,8 @@ PipelineStage::canSendInstToStage(unsigned stage_num)
     bool buffer_avail = false;
 
     if (cpu->pipelineStage[stage_num]->prevStageValid) {
-        buffer_avail = cpu->pipelineStage[stage_num]->stageBufferAvail() >= 1;
+        buffer_avail = cpu->pipelineStage[stage_num]->stageBufferAvail() -
+            cpu->pipelineStage[stage_num-1]->nextStage->size >= 1;
     }
 
     if (!buffer_avail && nextStageQueueValid(stage_num)) {
@@ -469,27 +473,6 @@ PipelineStage::canSendInstToStage(unsigned stage_num)
     return buffer_avail;
 }
 
-void
-PipelineStage::skidInsert(ThreadID tid)
-{
-    DynInstPtr inst = NULL;
-
-    while (!insts[tid].empty()) {
-        inst = insts[tid].front();
-
-        insts[tid].pop();
-
-        assert(tid == inst->threadNumber);
-
-        DPRINTF(InOrderStage,"[tid:%i]: Inserting [sn:%lli] PC:%s into stage "
-                "skidBuffer %i\n", tid, inst->seqNum, inst->pcState(),
-                inst->threadNumber);
-
-        skidBuffer[tid].push_back(inst);
-    }
-}
-
-
 int
 PipelineStage::skidSize()
 {
@@ -601,13 +584,8 @@ PipelineStage::sortInsts()
                 insts_from_cur_stage);
 
         int inserted_insts = 0;
-        for (int i = 0; i < insts_from_prev_stage; ++i) {
-            if (inserted_insts + insts_from_cur_stage == stageWidth) {
-               DPRINTF(InOrderStage, "Stage %i has accepted all insts "
-                       "possible for this tick.\n");
-                break;
-            }
 
+        for (int i = 0; i < insts_from_prev_stage; i++) {
             if (prevStage->insts[i]->isSquashed()) {
                 DPRINTF(InOrderStage, "[tid:%i]: Ignoring squashed [sn:%i], "
                         "not inserting into stage buffer.\n",
@@ -617,15 +595,27 @@ PipelineStage::sortInsts()
                 continue;
             }
 
-            DPRINTF(InOrderStage, "[tid:%i]: Inserting [sn:%i] into stage "
-                    "buffer.\n", prevStage->insts[i]->readTid(),
-                    prevStage->insts[i]->seqNum);
-
             ThreadID tid = prevStage->insts[i]->threadNumber;
 
-            DynInstPtr inst = prevStage->insts[i];
+            if (inserted_insts + insts_from_cur_stage == stageWidth) {
+               DPRINTF(InOrderStage, "Stage %i has accepted all insts "
+                       "possible for this tick. Placing [sn:%i] in stage %i skidBuffer\n",
+                       stageNum, prevStage->insts[i]->seqNum, stageNum - 1);
+                cpu->pipelineStage[stageNum - 1]->
+                    skidBuffer[tid].push_front(prevStage->insts[i]);
+
+                int prev_stage = stageNum - 1;
+                if (cpu->pipelineStage[prev_stage]->stageStatus[tid] == Running ||
+                    cpu->pipelineStage[prev_stage]->stageStatus[tid] == Idle) {
+                    cpu->pipelineStage[prev_stage]->stageStatus[tid] = Unblocking;
+                }
+            } else {
+                DPRINTF(InOrderStage, "[tid:%i]: Inserting [sn:%i] into stage "
+                        "buffer.\n", prevStage->insts[i]->readTid(),
+                        prevStage->insts[i]->seqNum);
 
-            skidBuffer[tid].push_back(prevStage->insts[i]);
+                skidBuffer[tid].push_back(prevStage->insts[i]);
+            }
 
             prevStage->insts[i] = cpu->dummyBufferInst;
 
@@ -633,6 +623,7 @@ PipelineStage::sortInsts()
 
             inserted_insts++;
         }
+
         assert(prevStage->size == 0);
     }
 }
@@ -862,12 +853,6 @@ PipelineStage::processThread(bool &status_change, ThreadID tid)
         // the rest of unblocking.
         processInsts(tid);
 
-        if (prevStageValid && prevStageInstsValid()) {
-            // Add the current inputs to the skid buffer so they can be
-            // reprocessed when this stage unblocks.
-            skidInsert(tid);
-        }
-
         status_change = unblock(tid) || status_change;
     }
 }
@@ -893,7 +878,6 @@ PipelineStage::processInsts(ThreadID tid)
 
     while (insts_available > 0 &&
            instsProcessed < stageWidth &&
-           (!nextStageValid || canSendInstToStage(stageNum+1)) &&
            last_req_completed) {
         assert(!insts_to_stage.empty());
 
index fb8ec593e2a0a72ba78e20d6ced999e03f198d99..dfa88de87ca842055e56e4298232e434eeefebcb 100644 (file)
@@ -184,11 +184,6 @@ class PipelineStage
     /** Send an instruction to the next stage buffer */
     bool sendInstToNextStage(DynInstPtr inst);
 
-    /** Inserts a thread's instructions into the skid buffer, to be staged
-     * once stage unblocks.
-     */
-    virtual void skidInsert(ThreadID tid);
-
     /** Total size of all skid buffers */
     int skidSize();