summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKorey Sewell <ksewell@umich.edu>2011-02-04 00:08:16 -0500
committerKorey Sewell <ksewell@umich.edu>2011-02-04 00:08:16 -0500
commitbe17617990ea2b95e0f08324570b2bbf93dee1f0 (patch)
treecdfe04692ce59363c46a7aec13827f85a0366e0d
parent050944dd7388231a334b81adf65e535058cf13fb (diff)
downloadgem5-be17617990ea2b95e0f08324570b2bbf93dee1f0.tar.xz
inorder: pipe. stage inst. buffering
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
-rw-r--r--src/cpu/inorder/first_stage.cc39
-rw-r--r--src/cpu/inorder/first_stage.hh5
-rw-r--r--src/cpu/inorder/pipeline_stage.cc92
-rw-r--r--src/cpu/inorder/pipeline_stage.hh5
4 files changed, 57 insertions, 84 deletions
diff --git a/src/cpu/inorder/first_stage.cc b/src/cpu/inorder/first_stage.cc
index 424d6b6a4..71c6ec3e0 100644
--- a/src/cpu/inorder/first_stage.cc
+++ b/src/cpu/inorder/first_stage.cc
@@ -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);
diff --git a/src/cpu/inorder/first_stage.hh b/src/cpu/inorder/first_stage.hh
index 3a3d550a0..26151075c 100644
--- a/src/cpu/inorder/first_stage.hh
+++ b/src/cpu/inorder/first_stage.hh
@@ -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;
diff --git a/src/cpu/inorder/pipeline_stage.cc b/src/cpu/inorder/pipeline_stage.cc
index d77059717..b4b9e497f 100644
--- a/src/cpu/inorder/pipeline_stage.cc
+++ b/src/cpu/inorder/pipeline_stage.cc
@@ -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());
diff --git a/src/cpu/inorder/pipeline_stage.hh b/src/cpu/inorder/pipeline_stage.hh
index fb8ec593e..dfa88de87 100644
--- a/src/cpu/inorder/pipeline_stage.hh
+++ b/src/cpu/inorder/pipeline_stage.hh
@@ -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();