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
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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]);
|
||||
|
||||
skidBuffer[tid].push_back(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]);
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user