summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKorey Sewell <ksewell@umich.edu>2009-03-04 13:17:07 -0500
committerKorey Sewell <ksewell@umich.edu>2009-03-04 13:17:07 -0500
commitf69b018571a6396d0e679d4d0eceb47ef4496530 (patch)
tree00e8e6ad7b94e17a9ca328e37fb8bdbd5225cbf9
parentf98e9161a83cd9bafbe7e5612db344a8b5cb2ae1 (diff)
downloadgem5-f69b018571a6396d0e679d4d0eceb47ef4496530.tar.xz
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
-rw-r--r--src/cpu/inorder/cpu.cc4
-rw-r--r--src/cpu/inorder/first_stage.cc2
-rw-r--r--src/cpu/inorder/pipeline_stage.cc85
-rw-r--r--src/cpu/inorder/pipeline_stage.hh5
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();