From f69b018571a6396d0e679d4d0eceb47ef4496530 Mon Sep 17 00:00:00 2001 From: Korey Sewell Date: Wed, 4 Mar 2009 13:17:07 -0500 Subject: [PATCH] make handling of interstage buffers (i.e. StageQueues) more consistent: (1)number from 0-n, not 1-n+1, (2) always check nextStageValid before a stageNum+1 and prevStageValid for a stageNum-1 reference (3) add skidSize() to get StageQueue size for all threads --- src/cpu/inorder/cpu.cc | 4 +- src/cpu/inorder/first_stage.cc | 2 +- src/cpu/inorder/pipeline_stage.cc | 85 ++++++++++++++++++++----------- src/cpu/inorder/pipeline_stage.hh | 5 +- 4 files changed, 62 insertions(+), 34 deletions(-) diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc index 1836989af..9c957487d 100644 --- a/src/cpu/inorder/cpu.cc +++ b/src/cpu/inorder/cpu.cc @@ -250,8 +250,8 @@ InOrderCPU::InOrderCPU(Params *params) // Take Care of 1st/Nth stages if (stNum > 0) pipelineStage[stNum]->setPrevStageQueue(stageQueue[stNum - 1]); - if (stNum < NumStages - 2) - pipelineStage[stNum]->setNextStageQueue(stageQueue[stNum + 1]); + if (stNum < NumStages - 1) + pipelineStage[stNum]->setNextStageQueue(stageQueue[stNum]); } // Initialize thread specific variables diff --git a/src/cpu/inorder/first_stage.cc b/src/cpu/inorder/first_stage.cc index ce30f8466..be4431a03 100644 --- a/src/cpu/inorder/first_stage.cc +++ b/src/cpu/inorder/first_stage.cc @@ -127,7 +127,7 @@ FirstStage::processInsts(unsigned tid) { bool all_reqs_completed = true; - for (int insts_fetched = 0; insts_fetched < stageWidth && canSendInstToNextStage(); insts_fetched++) { + for (int insts_fetched = 0; insts_fetched < stageWidth && canSendInstToStage(1); insts_fetched++) { DynInstPtr inst; bool new_inst = false; diff --git a/src/cpu/inorder/pipeline_stage.cc b/src/cpu/inorder/pipeline_stage.cc index 4ded50bf0..1c8da2b13 100644 --- a/src/cpu/inorder/pipeline_stage.cc +++ b/src/cpu/inorder/pipeline_stage.cc @@ -229,7 +229,7 @@ PipelineStage::checkStall(unsigned tid) const bool ret_val = false; // Only check pipeline stall from stage directly following this stage - if (stalls[tid].stage[stageNum + 1]) { + if (nextStageValid && stalls[tid].stage[stageNum + 1]) { DPRINTF(InOrderStage,"[tid:%i]: Stall fom Stage %i detected.\n", tid, stageNum + 1); ret_val = true; @@ -422,26 +422,28 @@ PipelineStage::stageBufferAvail() } int incoming_insts = (prevStageValid) ? - cpu->pipelineStage[stageNum-1]->nextStage->size : + cpu->pipelineStage[stageNum]->prevStage->size : 0; - int avail = stageBufferMax - total - incoming_insts; + int avail = stageBufferMax - total -0;// incoming_insts; - assert(avail >= 0); + if (avail < 0) + fatal("stageNum %i:stageBufferAvail() < 0...stBMax=%i,total=%i,incoming=%i=>%i", + stageNum, stageBufferMax, total, incoming_insts, avail); return avail; } bool -PipelineStage::canSendInstToNextStage() +PipelineStage::canSendInstToStage(unsigned stage_num) { bool buffer_avail = false; - if (nextStageValid) { - buffer_avail = (cpu->pipelineStage[stageNum+1]->stageBufferAvail() >= 1); + if (cpu->pipelineStage[stage_num]->prevStageValid) { + buffer_avail = cpu->pipelineStage[stage_num]->stageBufferAvail() >= 1; } - if (!buffer_avail && nextStageValid) { + if (!buffer_avail && nextStageQueueValid(stage_num)) { DPRINTF(InOrderStall, "STALL: No room in stage %i buffer.\n", stageNum + 1); } @@ -468,6 +470,17 @@ PipelineStage::skidInsert(unsigned tid) } +int +PipelineStage::skidSize() +{ + int total = 0; + + for (int i=0; i < ThePipeline::MaxThreads; i++) { + total += skidBuffer[i].size(); + } + + return total; +} bool PipelineStage::skidsEmpty() @@ -743,8 +756,11 @@ PipelineStage::processStage(bool &status_change) nextStage->size, stageNum + 1); } - DPRINTF(InOrderStage, "%i insts left in stage buffer.\n", stageBufferMax - stageBufferAvail()); + DPRINTF(InOrderStage, "%i left in stage %i incoming buffer.\n", skidSize(), + stageNum); + DPRINTF(InOrderStage, "%i available in stage %i incoming buffer.\n", stageBufferAvail(), + stageNum); } void @@ -814,14 +830,10 @@ PipelineStage::processInsts(unsigned tid) int insts_processed = 0; - DPRINTF(InOrderStage, "[tid:%u]: Sending instructions to stage %u.\n", tid, - stageNum+1); - - //Keep processing instructions while ... these ?s are true: - while (insts_available > 0 && //1. are there instructions to process - insts_processed < stageWidth && //2. can the stage still process this - (canSendInstToNextStage() || !nextStageValid) && //3. is there room in next stage - last_req_completed) { //4. was the last instruction completed + while (insts_available > 0 && + insts_processed < stageWidth && + (!nextStageValid || canSendInstToStage(stageNum+1)) && + last_req_completed) { assert(!insts_to_stage.empty()); inst = insts_to_stage.front(); @@ -847,23 +859,21 @@ PipelineStage::processInsts(unsigned tid) last_req_completed = processInstSchedule(inst); - - insts_processed++; - // Don't let instruction pass to next stage if it hasnt completed // all of it's requests for this stage. if (!last_req_completed && !outOfOrderValid()) continue; - insts_to_stage.pop(); - - DPRINTF(InOrderStage, "Marking [tid:%i] [sn:%i] for insertion into next stage buffer.\n", - tid, inst->seqNum); - // Send to Next Stage or Break Loop - if (!sendInstToNextStage(inst)) - break;; + if (nextStageValid && !sendInstToNextStage(inst)) { + DPRINTF(InOrderStage, "[tid:%i] [sn:%i] unable to proceed to stage %i.\n", + tid, inst->seqNum,inst->nextStage); + break; + } + insts_processed++; + + insts_to_stage.pop(); //++stageProcessedInsts; --insts_available; @@ -871,8 +881,6 @@ PipelineStage::processInsts(unsigned tid) // If we didn't process all instructions, then we will need to block // and put all those instructions into the skid buffer. - // @TODO:-IN-PROGRESS-:Evaluating when stages should block/unblock - // for stage stalls... if (!insts_to_stage.empty()) { blockDueToBuffer(tid); } @@ -945,6 +953,8 @@ bool PipelineStage::sendInstToNextStage(DynInstPtr inst) { // Update Next Stage Variable in Instruction + // NOTE: Some Resources will update this nextStage var. to + // for bypassing, so can't always assume nextStage=stageNum+1 if (inst->nextStage == stageNum) inst->nextStage++; @@ -953,14 +963,29 @@ PipelineStage::sendInstToNextStage(DynInstPtr inst) int next_stage = inst->nextStage; int prev_stage = next_stage - 1; + assert(next_stage >= 1); + assert(prev_stage >= 0); + + DPRINTF(InOrderStage, "[tid:%u]: Attempting to send instructions to stage %u.\n", tid, + stageNum+1); + + if (!canSendInstToStage(inst->nextStage)) { + DPRINTF(InOrderStage, "[tid:%u]: Could not send instruction to stage %u.\n", tid, + stageNum+1); + return false; + } + + if (nextStageQueueValid(inst->nextStage - 1)) { if (inst->seqNum > cpu->squashSeqNum[tid] && curTick == cpu->lastSquashCycle[tid]) { DPRINTF(InOrderStage, "[tid:%u]: [sn:%i]: squashed, skipping insertion " "into stage %i queue.\n", tid, inst->seqNum, inst->nextStage); } else { - DPRINTF(InOrderStage, "[tid:%u] %i slots available in next stage buffer.\n", + if (nextStageValid) { + DPRINTF(InOrderStage, "[tid:%u] %i slots available in next stage buffer.\n", tid, cpu->pipelineStage[next_stage]->stageBufferAvail()); + } DPRINTF(InOrderStage, "[tid:%u]: [sn:%i]: being placed into " "index %i of stage buffer %i queue.\n", diff --git a/src/cpu/inorder/pipeline_stage.hh b/src/cpu/inorder/pipeline_stage.hh index 833547704..17ca32595 100644 --- a/src/cpu/inorder/pipeline_stage.hh +++ b/src/cpu/inorder/pipeline_stage.hh @@ -184,7 +184,7 @@ class PipelineStage virtual bool processInstSchedule(DynInstPtr inst); /** Is there room in the next stage buffer for this instruction? */ - virtual bool canSendInstToNextStage(); + virtual bool canSendInstToStage(unsigned stage_num); /** Send an instruction to the next stage buffer */ virtual bool sendInstToNextStage(DynInstPtr inst); @@ -194,6 +194,9 @@ class PipelineStage */ virtual void skidInsert(unsigned tid); + /** Total size of all skid buffers */ + int skidSize(); + /** Returns if all of the skid buffers are empty. */ bool skidsEmpty(); -- 2.30.2