summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cpu/inorder/pipeline_stage.cc137
-rw-r--r--src/cpu/inorder/pipeline_stage.hh19
2 files changed, 95 insertions, 61 deletions
diff --git a/src/cpu/inorder/pipeline_stage.cc b/src/cpu/inorder/pipeline_stage.cc
index dc0378bf3..8d14aae27 100644
--- a/src/cpu/inorder/pipeline_stage.cc
+++ b/src/cpu/inorder/pipeline_stage.cc
@@ -44,6 +44,9 @@ PipelineStage::PipelineStage(Params *params, unsigned stage_num)
stageBufferMax(ThePipeline::interStageBuffSize[stage_num]),
prevStageValid(false), nextStageValid(false)
{
+ switchedOutBuffer.resize(ThePipeline::MaxThreads);
+ switchedOutValid.resize(ThePipeline::MaxThreads);
+
init(params);
}
@@ -267,7 +270,8 @@ PipelineStage::isBlocked(ThreadID tid)
bool
PipelineStage::block(ThreadID tid)
{
- DPRINTF(InOrderStage, "[tid:%d]: Blocking, sending block signal back to previous stages.\n", 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.
@@ -296,7 +300,8 @@ PipelineStage::block(ThreadID tid)
void
PipelineStage::blockDueToBuffer(ThreadID tid)
{
- DPRINTF(InOrderStage, "[tid:%d]: Blocking instructions from passing to next stage.\n", tid);
+ DPRINTF(InOrderStage, "[tid:%d]: Blocking instructions from passing to "
+ "next stage.\n", tid);
if (stageStatus[tid] != Blocked) {
// Set the status to Blocked.
@@ -334,8 +339,9 @@ PipelineStage::squashDueToBranch(DynInstPtr &inst, ThreadID tid)
{
if (cpu->squashSeqNum[tid] < inst->seqNum &&
cpu->lastSquashCycle[tid] == curTick){
- DPRINTF(Resource, "Ignoring [sn:%i] squash signal due to another stage's squash "
- "signal for after [sn:%i].\n", inst->seqNum, cpu->squashSeqNum[tid]);
+ DPRINTF(Resource, "Ignoring [sn:%i] squash signal due to another "
+ "stage's squash signal for after [sn:%i].\n", inst->seqNum,
+ cpu->squashSeqNum[tid]);
} else {
// Send back mispredict information.
toPrevStages->stageInfo[stageNum][tid].branchMispredict = true;
@@ -346,20 +352,28 @@ PipelineStage::squashDueToBranch(DynInstPtr &inst, ThreadID tid)
#if ISA_HAS_DELAY_SLOT
- toPrevStages->stageInfo[stageNum][tid].branchTaken = inst->readNextNPC() !=
+ toPrevStages->stageInfo[stageNum][tid].branchTaken =
+ inst->readNextNPC() !=
(inst->readNextPC() + sizeof(TheISA::MachInst));
- toPrevStages->stageInfo[stageNum][tid].bdelayDoneSeqNum = inst->bdelaySeqNum;
+
+ toPrevStages->stageInfo[stageNum][tid].bdelayDoneSeqNum =
+ inst->bdelaySeqNum;
+
InstSeqNum squash_seq_num = inst->bdelaySeqNum;
#else
- toPrevStages->stageInfo[stageNum][tid].branchTaken = inst->readNextPC() !=
+ toPrevStages->stageInfo[stageNum][tid].branchTaken =
+ inst->readNextPC() !=
(inst->readPC() + sizeof(TheISA::MachInst));
+
toPrevStages->stageInfo[stageNum][tid].bdelayDoneSeqNum = inst->seqNum;
InstSeqNum squash_seq_num = inst->seqNum;
#endif
- DPRINTF(InOrderStage, "Target being re-set to %08p\n", inst->readPredTarg());
- DPRINTF(InOrderStage, "[tid:%i]: Squashing after [sn:%i], due to [sn:%i] "
- "branch.\n", tid, squash_seq_num, inst->seqNum);
+ DPRINTF(InOrderStage, "Target being re-set to %08p\n",
+ inst->readPredTarg());
+ DPRINTF(InOrderStage, "[tid:%i]: Squashing after [sn:%i], "
+ "due to [sn:%i] branch.\n", tid, squash_seq_num,
+ inst->seqNum);
// Save squash num for later stage use
cpu->squashSeqNum[tid] = squash_seq_num;
@@ -394,8 +408,8 @@ PipelineStage::squash(InstSeqNum squash_seq_num, ThreadID tid)
squashPrevStageInsts(squash_seq_num, tid);
- DPRINTF(InOrderStage, "[tid:%i]: Removing instructions from incoming stage skidbuffer.\n",
- 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) {
DPRINTF(InOrderStage, "[tid:%i]: Cannot remove skidBuffer "
@@ -404,8 +418,9 @@ PipelineStage::squash(InstSeqNum squash_seq_num, ThreadID tid)
skidBuffer[tid].size());
break;
}
- DPRINTF(InOrderStage, "[tid:%i]: Removing instruction, [sn:%i] PC %08p.\n",
- tid, skidBuffer[tid].front()->seqNum, skidBuffer[tid].front()->PC);
+ DPRINTF(InOrderStage, "[tid:%i]: Removing instruction, [sn:%i] "
+ " PC %08p.\n", tid, skidBuffer[tid].front()->seqNum,
+ skidBuffer[tid].front()->PC);
skidBuffer[tid].pop();
}
@@ -427,7 +442,8 @@ PipelineStage::stageBufferAvail()
int avail = stageBufferMax - total -0;// incoming_insts;
if (avail < 0)
- fatal("stageNum %i:stageBufferAvail() < 0...stBMax=%i,total=%i,incoming=%i=>%i",
+ fatal("stageNum %i:stageBufferAvail() < 0..."
+ "stBMax=%i,total=%i,incoming=%i=>%i",
stageNum, stageBufferMax, total, incoming_insts, avail);
return avail;
@@ -443,7 +459,8 @@ PipelineStage::canSendInstToStage(unsigned stage_num)
}
if (!buffer_avail && nextStageQueueValid(stage_num)) {
- DPRINTF(InOrderStall, "STALL: No room in stage %i buffer.\n", stageNum + 1);
+ DPRINTF(InOrderStall, "STALL: No room in stage %i buffer.\n",
+ stageNum + 1);
}
return buffer_avail;
@@ -461,8 +478,9 @@ PipelineStage::skidInsert(ThreadID tid)
assert(tid == inst->threadNumber);
- DPRINTF(InOrderStage,"[tid:%i]: Inserting [sn:%lli] PC:%#x into stage skidBuffer %i\n",
- tid, inst->seqNum, inst->readPC(), inst->threadNumber);
+ DPRINTF(InOrderStage,"[tid:%i]: Inserting [sn:%lli] PC:%#x into stage "
+ "skidBuffer %i\n", tid, inst->seqNum, inst->readPC(),
+ inst->threadNumber);
skidBuffer[tid].push(inst);
}
@@ -547,16 +565,16 @@ PipelineStage::sortInsts()
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",
+ DPRINTF(InOrderStage, "[tid:%i]: Ignoring squashed [sn:%i], "
+ "not inserting into stage buffer.\n",
prevStage->insts[i]->readTid(),
prevStage->insts[i]->seqNum);
continue;
}
- DPRINTF(InOrderStage, "[tid:%i]: Inserting [sn:%i] into stage buffer.\n",
- prevStage->insts[i]->readTid(),
+ 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;
@@ -611,8 +629,8 @@ PipelineStage::checkSignalsAndUpdate(ThreadID tid)
// Check for squash from later pipeline stages
for (int stage_idx=stageNum; stage_idx < NumStages; stage_idx++) {
if (fromNextStages->stageInfo[stage_idx][tid].squash) {
- DPRINTF(InOrderStage, "[tid:%u]: Squashing instructions due to squash "
- "from stage %u.\n", tid, stage_idx);
+ DPRINTF(InOrderStage, "[tid:%u]: Squashing instructions due to "
+ "squash from stage %u.\n", tid, stage_idx);
InstSeqNum squash_seq_num = fromNextStages->
stageInfo[stage_idx][tid].bdelayDoneSeqNum;
squash(squash_seq_num, tid);
@@ -625,8 +643,8 @@ PipelineStage::checkSignalsAndUpdate(ThreadID tid)
}
if (stageStatus[tid] == Blocked) {
- DPRINTF(InOrderStage, "[tid:%u]: Done blocking, switching to unblocking.\n",
- tid);
+ DPRINTF(InOrderStage, "[tid:%u]: Done blocking, switching to "
+ "unblocking.\n", tid);
stageStatus[tid] = Unblocking;
@@ -637,15 +655,15 @@ PipelineStage::checkSignalsAndUpdate(ThreadID tid)
if (stageStatus[tid] == Squashing) {
if (!skidBuffer[tid].empty()) {
- DPRINTF(InOrderStage, "[tid:%u]: Done squashing, switching to unblocking.\n",
- tid);
+ DPRINTF(InOrderStage, "[tid:%u]: Done squashing, switching to "
+ "unblocking.\n", tid);
stageStatus[tid] = Unblocking;
} else {
// Switch status to running if stage isn't being told to block or
// squash this cycle.
- DPRINTF(InOrderStage, "[tid:%u]: Done squashing, switching to running.\n",
- tid);
+ DPRINTF(InOrderStage, "[tid:%u]: Done squashing, switching to "
+ "running.\n", tid);
stageStatus[tid] = Running;
}
@@ -717,13 +735,13 @@ PipelineStage::unsetResStall(ResReqPtr res_req, ThreadID tid)
}
if (stalls[tid].resources.size() == 0) {
- DPRINTF(InOrderStage, "[tid:%u]: There are no remaining resource stalls.\n",
- tid);
+ DPRINTF(InOrderStage, "[tid:%u]: There are no remaining resource"
+ "stalls.\n", tid);
}
}
-// @TODO: Update How we handled threads in CPU. Maybe threads shouldnt be handled
-// one at a time, but instead first come first serve by instruction?
+// @TODO: Update How we handled threads in CPU. Maybe threads shouldnt be
+// handled one at a time, but instead first come first serve by instruction?
// Questions are how should a pipeline stage handle thread-specific stalls &
// pipeline squashes
void
@@ -749,8 +767,8 @@ PipelineStage::processStage(bool &status_change)
DPRINTF(InOrderStage, "%i left in stage %i incoming buffer.\n", skidSize(),
stageNum);
- DPRINTF(InOrderStage, "%i available in stage %i incoming buffer.\n", stageBufferAvail(),
- stageNum);
+ DPRINTF(InOrderStage, "%i available in stage %i incoming buffer.\n",
+ stageBufferAvail(), stageNum);
}
void
@@ -828,8 +846,8 @@ PipelineStage::processInsts(ThreadID tid)
inst = insts_to_stage.front();
- DPRINTF(InOrderStage, "[tid:%u]: Processing instruction [sn:%lli] with "
- "PC %#x\n",
+ DPRINTF(InOrderStage, "[tid:%u]: Processing instruction [sn:%lli] "
+ "with PC %#x\n",
tid, inst->seqNum, inst->readPC());
if (inst->isSquashed()) {
@@ -856,8 +874,8 @@ PipelineStage::processInsts(ThreadID tid)
// Send to Next Stage or Break Loop
if (nextStageValid && !sendInstToNextStage(inst)) {
- DPRINTF(InOrderStage, "[tid:%i] [sn:%i] unable to proceed to stage %i.\n",
- tid, inst->seqNum,inst->nextStage);
+ DPRINTF(InOrderStage, "[tid:%i] [sn:%i] unable to proceed to stage"
+ " %i.\n", tid, inst->seqNum,inst->nextStage);
break;
}
@@ -897,14 +915,15 @@ PipelineStage::processInstSchedule(DynInstPtr inst)
int res_num = inst->nextResource();
- DPRINTF(InOrderStage, "[tid:%i]: [sn:%i]: sending request to %s.\n",
- tid, inst->seqNum, cpu->resPool->name(res_num));
+ DPRINTF(InOrderStage, "[tid:%i]: [sn:%i]: sending request to %s."
+ "\n", tid, inst->seqNum, cpu->resPool->name(res_num));
ResReqPtr req = cpu->resPool->request(res_num, inst);
if (req->isCompleted()) {
- DPRINTF(InOrderStage, "[tid:%i]: [sn:%i] request to %s completed.\n",
- tid, inst->seqNum, cpu->resPool->name(res_num));
+ DPRINTF(InOrderStage, "[tid:%i]: [sn:%i] request to %s "
+ "completed.\n", tid, inst->seqNum,
+ cpu->resPool->name(res_num));
if (req->fault == NoFault) {
inst->popSchedEntry();
@@ -913,8 +932,8 @@ PipelineStage::processInstSchedule(DynInstPtr inst)
curTick, req->fault->name());
}
} else {
- DPRINTF(InOrderStage, "[tid:%i]: [sn:%i] request to %s failed.\n",
- tid, inst->seqNum, cpu->resPool->name(res_num));
+ DPRINTF(InOrderStage, "[tid:%i]: [sn:%i] request to %s failed."
+ "\n", tid, inst->seqNum, cpu->resPool->name(res_num));
last_req_completed = false;
@@ -956,12 +975,12 @@ PipelineStage::sendInstToNextStage(DynInstPtr inst)
assert(next_stage >= 1);
assert(prev_stage >= 0);
- DPRINTF(InOrderStage, "[tid:%u]: Attempting to send instructions to stage %u.\n", tid,
- stageNum+1);
+ 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);
+ DPRINTF(InOrderStage, "[tid:%u]: Could not send instruction to "
+ "stage %u.\n", tid, stageNum+1);
return false;
}
@@ -969,12 +988,14 @@ PipelineStage::sendInstToNextStage(DynInstPtr inst)
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);
+ DPRINTF(InOrderStage, "[tid:%u]: [sn:%i]: squashed, skipping "
+ "insertion into stage %i queue.\n", tid, inst->seqNum,
+ inst->nextStage);
} else {
if (nextStageValid) {
- DPRINTF(InOrderStage, "[tid:%u] %i slots available in next stage buffer.\n",
- tid, cpu->pipelineStage[next_stage]->stageBufferAvail());
+ 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 "
@@ -982,11 +1003,13 @@ PipelineStage::sendInstToNextStage(DynInstPtr inst)
tid, inst->seqNum, toNextStageIndex,
cpu->pipelineStage[prev_stage]->nextStageQueue->id());
- int next_stage_idx = cpu->pipelineStage[prev_stage]->nextStage->size;
+ int next_stage_idx =
+ cpu->pipelineStage[prev_stage]->nextStage->size;
- // Place instructions in inter-stage communication struct for the next
+ // Place instructions in inter-stage communication struct for next
// pipeline stage to read next cycle
- cpu->pipelineStage[prev_stage]->nextStage->insts[next_stage_idx] = inst;
+ cpu->pipelineStage[prev_stage]->nextStage->insts[next_stage_idx]
+ = inst;
++(cpu->pipelineStage[prev_stage]->nextStage->size);
diff --git a/src/cpu/inorder/pipeline_stage.hh b/src/cpu/inorder/pipeline_stage.hh
index 86ee98132..42a632560 100644
--- a/src/cpu/inorder/pipeline_stage.hh
+++ b/src/cpu/inorder/pipeline_stage.hh
@@ -240,6 +240,8 @@ class PipelineStage
*/
virtual void squashDueToBranch(DynInstPtr &inst, ThreadID tid);
+ virtual void squashDueToMemStall(DynInstPtr &inst, ThreadID tid);
+
/** Squash instructions from stage buffer */
virtual void squashPrevStageInsts(InstSeqNum squash_seq_num, ThreadID tid);
@@ -259,19 +261,28 @@ class PipelineStage
/** List of active thread ids */
std::list<ThreadID> *activeThreads;
+ /** Buffer of instructions switched out to mem-stall.
+ * Only used when using SwitchOnCacheMiss threading model
+ * Used as 1-to-1 mapping between ThreadID and Entry.
+ */
+ std::vector<DynInstPtr> switchedOutBuffer;
+ std::vector<bool> switchedOutValid;
+
/** Queue of all instructions coming from previous stage on this cycle. */
std::queue<DynInstPtr> insts[ThePipeline::MaxThreads];
- /** Queue of instructions that are finished processing and ready to go next stage.
- * This is used to prevent from processing an instrution more than once on any
- * stage. NOTE: It is up to the PROGRAMMER must manage this as a queue
+ /** Queue of instructions that are finished processing and ready to go
+ * next stage. This is used to prevent from processing an instrution more
+ * than once on any stage. NOTE: It is up to the PROGRAMMER must manage
+ * this as a queue
*/
std::list<DynInstPtr> instsToNextStage;
/** Skid buffer between previous stage and this one. */
std::queue<DynInstPtr> skidBuffer[ThePipeline::MaxThreads];
- /** Instruction used to signify that there is no *real* instruction in buffer slot */
+ /** Instruction used to signify that there is no *real* instruction in
+ * buffer slot */
DynInstPtr dummyBufferInst;
/** SeqNum of Squashing Branch Delay Instruction (used for MIPS) */