# HG changeset patch
# User Korey Sewell <[email protected]>
# Date 1254427253 14400
# Node ID a829497e6ff5fd1962764b0c4717a32cbce5b7d9
# Parent 5e04e6117c84cd57a60e612020aa0eee462c2006
inorder: squash on memory stall
add code to recognize memory stalls in resources and the pipeline as well
as squash a thread if there is a stall and we are in the switch on cache miss
model
diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc
--- a/src/cpu/inorder/cpu.cc
+++ b/src/cpu/inorder/cpu.cc
@@ -138,6 +138,10 @@
cpu->disableThreads(tid, vpe);
break;
+ case SquashFromMemStall:
+ cpu->squashDueToMemStall(inst->squashingStage, inst->seqNum, tid);
+ break;
+
case Trap:
cpu->trapCPU(fault, tid);
break;
@@ -565,6 +569,31 @@
fault->invoke(tcBase(tid));
}
+void
+InOrderCPU::squashFromMemStall(DynInstPtr inst, ThreadID tid, int delay)
+{
+ scheduleCpuEvent(SquashFromMemStall, NoFault, tid, inst, delay);
+}
+
+
+void
+InOrderCPU::squashDueToMemStall(int stage_num, InstSeqNum seq_num, ThreadID
tid)
+{
+ DPRINTF(InOrderCPU, "Squashing Pipeline Stages Due to Memory Stall...\n");
+
+ // Squash all instructions in each stage including
+ // instruction that caused the squash (seq_num - 1)
+ // NOTE: The stage bandwidth needs to be cleared so thats why
+ // the stalling instruction is squashed as well. The stalled
+ // instruction is previously placed in another intermediate buffer
+ // while it's stall is being handled.
+ InstSeqNum squash_seq_num = seq_num - 1;
+
+ for (int stNum=stage_num; stNum >= 0 ; stNum--) {
+ pipelineStage[stNum]->squashDueToMemStall(squash_seq_num, tid);
+ }
+}
+
void
InOrderCPU::scheduleCpuEvent(CPUEventType c_event, Fault fault,
ThreadID tid, DynInstPtr inst,
diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh
--- a/src/cpu/inorder/cpu.hh
+++ b/src/cpu/inorder/cpu.hh
@@ -180,7 +180,7 @@
EnableVPEs,
Trap,
InstGraduated,
- SquashAll,
+ SquashFromMemStall,
UpdatePCs,
NumCPUEvents
};
@@ -340,6 +340,12 @@
void trap(Fault fault, ThreadID tid, int delay = 0);
void trapCPU(Fault fault, ThreadID tid);
+ /** squashFromMemStall() - sets up a squash event
+ * squashDueToMemStall() - squashes pipeline
+ */
+ void squashFromMemStall(DynInstPtr inst, ThreadID tid, int delay = 0);
+ void squashDueToMemStall(int stage_num, InstSeqNum seq_num, ThreadID tid);
+
/** Setup CPU to insert a thread's context */
void insertThread(ThreadID tid);
diff --git a/src/cpu/inorder/first_stage.cc b/src/cpu/inorder/first_stage.cc
--- a/src/cpu/inorder/first_stage.cc
+++ b/src/cpu/inorder/first_stage.cc
@@ -93,6 +93,18 @@
cpu->removeInstsUntil(squash_seq_num, tid);
}
+void
+FirstStage::squashDueToMemStall(InstSeqNum seq_num, ThreadID tid)
+{
+ // Need to preserve the stalling instruction in first-stage
+ // since the squash() from first stage also removes
+ // the instruction from the CPU (removeInstsUntil). If that
+ // functionality gets changed then you can move this offset.
+ // (stalling instruction = seq_num + 1)
+ squash(seq_num+1, tid);
+}
+
+
void
FirstStage::processStage(bool &status_change)
{
@@ -106,6 +118,7 @@
for (int threadFetched = 0; threadFetched < numFetchingThreads;
threadFetched++) {
+
ThreadID tid = getFetchingThread(fetchPolicy);
if (tid >= 0) {
diff --git a/src/cpu/inorder/first_stage.hh b/src/cpu/inorder/first_stage.hh
--- a/src/cpu/inorder/first_stage.hh
+++ b/src/cpu/inorder/first_stage.hh
@@ -61,6 +61,8 @@
/** Squash Instructions Above a Seq. Num */
void squash(InstSeqNum squash_seq_num, ThreadID tid);
+ void squashDueToMemStall(InstSeqNum seq_num, ThreadID tid);
+
/** There are no insts. coming from previous stages, so there is
* no need to sort insts here
*/
diff --git a/src/cpu/inorder/pipeline_stage.cc
b/src/cpu/inorder/pipeline_stage.cc
--- a/src/cpu/inorder/pipeline_stage.cc
+++ b/src/cpu/inorder/pipeline_stage.cc
@@ -336,7 +336,7 @@
{
if (cpu->squashSeqNum[tid] < inst->seqNum &&
cpu->lastSquashCycle[tid] == curTick){
- DPRINTF(Resource, "Ignoring [sn:%i] squash signal due to another
stage's squash "
+ DPRINTF(Resource, "Ignoring [sn:%i] branch squash signal due to
another stage's squash "
"signal for after [sn:%i].\n", inst->seqNum,
cpu->squashSeqNum[tid]);
} else {
// Send back mispredict information.
@@ -370,6 +370,12 @@
}
void
+PipelineStage::squashDueToMemStall(InstSeqNum seq_num, ThreadID tid)
+{
+ squash(seq_num, tid);
+}
+
+void
PipelineStage::squashPrevStageInsts(InstSeqNum squash_seq_num, ThreadID tid)
{
DPRINTF(InOrderStage, "[tid:%i]: Removing instructions from "
@@ -401,8 +407,8 @@
while (!skidBuffer[tid].empty()) {
if (skidBuffer[tid].front()->seqNum <= squash_seq_num) {
DPRINTF(InOrderStage, "[tid:%i]: Cannot remove skidBuffer "
- "instructions before delay slot [sn:%i]. %i insts"
- "left.\n", tid, squash_seq_num,
+ "instructions (starting w/[sn:%i]) before delay slot
[sn:%i]. %i insts"
+ "left.\n", tid, skidBuffer[tid].front()->seqNum,
squash_seq_num,
skidBuffer[tid].size());
break;
}
@@ -759,7 +765,7 @@
PipelineStage::processThread(bool &status_change, ThreadID tid)
{
// If status is Running or idle,
- // call stageInsts()
+ // call processInsts()
// If status is Unblocking,
// buffer any instructions coming from fetch
// continue trying to empty skid buffer
@@ -771,7 +777,7 @@
;//++stageSquashCycles;
}
- // Stage should try to stage as many instructions as its bandwidth
+ // Stage should try to process as many instructions as its bandwidth
// will allow, as long as it is not currently blocked.
if (stageStatus[tid] == Running ||
stageStatus[tid] == Idle) {
@@ -888,9 +894,7 @@
PipelineStage::processInstSchedule(DynInstPtr inst)
{
bool last_req_completed = true;
-#if TRACING_ON
ThreadID tid = inst->readTid();
-#endif
if (inst->nextResStage() == stageNum) {
int res_stage_num = inst->nextResStage();
@@ -920,6 +924,17 @@
last_req_completed = false;
+ if (req->isMemStall() && cpu->threadModel ==
InOrderCPU::SwitchOnCacheMiss) {
+ // Save Stalling Instruction
+ switchedOutBuffer[tid] = inst;
+ switchedOutValid[tid] = true;
+
+ // Remove Thread From Pipeline & Resource Pool
+ inst->squashingStage = stageNum;
+ inst->bdelaySeqNum = inst->seqNum;
+ cpu->squashFromMemStall(inst, tid);
+ }
+
break;
}
diff --git a/src/cpu/inorder/pipeline_stage.hh
b/src/cpu/inorder/pipeline_stage.hh
--- a/src/cpu/inorder/pipeline_stage.hh
+++ b/src/cpu/inorder/pipeline_stage.hh
@@ -240,7 +240,7 @@
*/
virtual void squashDueToBranch(DynInstPtr &inst, ThreadID tid);
- virtual void squashDueToMemStall(DynInstPtr &inst, ThreadID tid);
+ virtual void squashDueToMemStall(InstSeqNum seq_num, ThreadID tid);
/** Squash instructions from stage buffer */
virtual void squashPrevStageInsts(InstSeqNum squash_seq_num, ThreadID tid);
diff --git a/src/cpu/inorder/resource.cc b/src/cpu/inorder/resource.cc
--- a/src/cpu/inorder/resource.cc
+++ b/src/cpu/inorder/resource.cc
@@ -334,6 +334,12 @@
}
}
+void
+Resource::squashDueToMemStall(DynInstPtr inst, int stage_num, InstSeqNum
squash_seq_num,
+ ThreadID tid)
+{
+ squash(inst, stage_num, squash_seq_num, tid);
+}
Tick
Resource::ticks(int num_cycles)
diff --git a/src/cpu/inorder/resource.hh b/src/cpu/inorder/resource.hh
--- a/src/cpu/inorder/resource.hh
+++ b/src/cpu/inorder/resource.hh
@@ -154,6 +154,9 @@
virtual void squash(DynInstPtr inst, int stage_num,
InstSeqNum squash_seq_num, ThreadID tid);
+ virtual void squashDueToMemStall(DynInstPtr inst, int stage_num,
+ InstSeqNum squash_seq_num, ThreadID tid);
+
/** The number of instructions available that this resource can
* can still process
*/
@@ -309,7 +312,7 @@
int res_idx, int slot_num, unsigned _cmd)
: res(_res), inst(_inst), cmd(_cmd), stageNum(stage_num),
resIdx(res_idx), slotNum(slot_num), completed(false),
- squashed(false), processing(false), waiting(false)
+ squashed(false), processing(false), memStall(false)
{
reqID = resReqID++;
resReqCount++;
@@ -389,8 +392,8 @@
void setProcessing() { processing = true; }
/** Get/Set IsWaiting variables */
- bool isWaiting() { return waiting; }
- void setWaiting() { waiting = true; }
+ bool isMemStall() { return memStall; }
+ void setMemStall(bool stall = true) { memStall = stall; }
protected:
/** Resource Identification */
@@ -399,11 +402,12 @@
int resIdx;
int slotNum;
- /** Resource Status */
+ /** Resource Request Status */
bool completed;
bool squashed;
bool processing;
- bool waiting;
+
+ bool memStall;
};
#endif //__CPU_INORDER_RESOURCE_HH__
diff --git a/src/cpu/inorder/resource_pool.cc b/src/cpu/inorder/resource_pool.cc
--- a/src/cpu/inorder/resource_pool.cc
+++ b/src/cpu/inorder/resource_pool.cc
@@ -249,6 +249,20 @@
}
break;
+ case InOrderCPU::SquashFromMemStall:
+ {
+ DPRINTF(Resource, "Scheduling Squash Due to Memory Stall Resource "
+ "Pool Event for tick %i.\n",
+ curTick + delay);
+ ResPoolEvent *res_pool_event = new ResPoolEvent(this,e_type,
+ inst,
+
inst->squashingStage,
+ inst->seqNum - 1,
+ inst->readTid());
+ mainEventQueue.schedule(res_pool_event, curTick +
cpu->ticks(delay));
+ }
+ break;
+
default:
DPRINTF(Resource, "Ignoring Unrecognized CPU Event (%s).\n",
InOrderCPU::eventNames[e_type]);
; // If Resource Pool doesnt recognize event, we ignore it.
@@ -276,6 +290,20 @@
}
void
+ResourcePool::squashDueToMemStall(DynInstPtr inst, int stage_num,
+ InstSeqNum done_seq_num, ThreadID tid)
+{
+ DPRINTF(Resource, "[tid:%i] Stage %i squashing all instructions above
[sn:%i].\n",
+ stage_num, tid, done_seq_num);
+
+ int num_resources = resources.size();
+
+ for (int idx = 0; idx < num_resources; idx++) {
+ resources[idx]->squashDueToMemStall(inst, stage_num, done_seq_num,
tid);
+ }
+}
+
+void
ResourcePool::activateAll(ThreadID tid)
{
DPRINTF(Resource, "[tid:%i] Broadcasting Thread Activation to all
resources.\n",
@@ -353,6 +381,10 @@
resPool->squashAll(inst, stageNum, seqNum, tid);
break;
+ case InOrderCPU::SquashFromMemStall:
+ resPool->squashDueToMemStall(inst, stageNum, seqNum, tid);
+ break;
+
default:
fatal("Unrecognized Event Type");
}
diff --git a/src/cpu/inorder/resource_pool.hh b/src/cpu/inorder/resource_pool.hh
--- a/src/cpu/inorder/resource_pool.hh
+++ b/src/cpu/inorder/resource_pool.hh
@@ -123,7 +123,7 @@
};
public:
- ResourcePool(InOrderCPU *_cpu, ThePipeline::Params *params);
+ ResourcePool(InOrderCPU *_cpu, ThePipeline::Params *params);
virtual ~ResourcePool() {}
std::string name();
@@ -160,6 +160,12 @@
void squashAll(DynInstPtr inst, int stage_num,
InstSeqNum done_seq_num, ThreadID tid);
+ /** Squash Resources in Pool after a memory stall
+ * NOTE: Only use during Switch-On-Miss Thread model
+ */
+ void squashDueToMemStall(DynInstPtr inst, int stage_num,
+ InstSeqNum done_seq_num, ThreadID tid);
+
/** Activate Thread in all resources */
void activateAll(ThreadID tid);
diff --git a/src/cpu/inorder/resources/cache_unit.cc
b/src/cpu/inorder/resources/cache_unit.cc
--- a/src/cpu/inorder/resources/cache_unit.cc
+++ b/src/cpu/inorder/resources/cache_unit.cc
@@ -414,6 +414,7 @@
tid, seq_num, inst->staticInst->disassemble(inst->PC));
delete cache_req->dataPkt;
+ //cache_req->setMemStall(false);
cache_req->done();
} else {
DPRINTF(InOrderCachePort,
@@ -423,6 +424,7 @@
"STALL: [tid:%i]: Fetch miss from %08p\n",
tid, cache_req->inst->readPC());
cache_req->setCompleted(false);
+ //cache_req->setMemStall(true);
}
break;
@@ -435,11 +437,13 @@
if (cache_req->isMemAccComplete() ||
inst->isDataPrefetch() ||
inst->isInstPrefetch()) {
+ cache_req->setMemStall(false);
cache_req->done();
} else {
DPRINTF(InOrderStall, "STALL: [tid:%i]: Data miss from %08p\n",
tid, cache_req->inst->getMemAddr());
cache_req->setCompleted(false);
+ cache_req->setMemStall(true);
}
break;
@@ -763,6 +767,23 @@
}
void
+CacheUnit::squashDueToMemStall(DynInstPtr inst, int stage_num,
+ InstSeqNum squash_seq_num, ThreadID tid)
+{
+ // If squashing due to memory stall, then we do NOT want to
+ // squash the instruction that caused the stall so we
+ // increment the sequence number here to prevent that.
+ //
+ // NOTE: This is only for the SwitchOnCacheMiss Model
+ // NOTE: If you have multiple outstanding misses from the same
+ // thread then you need to reevaluate this code
+ // NOTE: squash should originate from
+ // pipeline_stage.cc:processInstSchedule
+ squash(inst, stage_num, squash_seq_num + 1, tid);
+}
+
+
+void
CacheUnit::squash(DynInstPtr inst, int stage_num,
InstSeqNum squash_seq_num, ThreadID tid)
{
diff --git a/src/cpu/inorder/resources/cache_unit.hh
b/src/cpu/inorder/resources/cache_unit.hh
--- a/src/cpu/inorder/resources/cache_unit.hh
+++ b/src/cpu/inorder/resources/cache_unit.hh
@@ -146,6 +146,9 @@
void squash(DynInstPtr inst, int stage_num,
InstSeqNum squash_seq_num, ThreadID tid);
+ void squashDueToMemStall(DynInstPtr inst, int stage_num,
+ InstSeqNum squash_seq_num, ThreadID tid);
+
/** Processes cache completion event. */
void processCacheCompletion(PacketPtr pkt);
_______________________________________________
m5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/m5-dev