From 716e447da8424386f2c3448c17891927aeb49f67 Mon Sep 17 00:00:00 2001 From: Korey Sewell Date: Sun, 19 Jun 2011 21:43:41 -0400 Subject: [PATCH] inorder: handle serializing instructions including IPR accesses and store-conditionals. These class of instructions will not execute correctly in a superscalar machine --- src/cpu/inorder/pipeline_stage.cc | 1 + src/cpu/inorder/resource.cc | 1 + src/cpu/inorder/resources/cache_unit.cc | 6 ++-- src/cpu/inorder/resources/execution_unit.cc | 20 +++---------- src/cpu/inorder/resources/execution_unit.hh | 1 - src/cpu/inorder/resources/use_def.cc | 33 ++++++++++++++++----- src/cpu/inorder/resources/use_def.hh | 4 ++- 7 files changed, 39 insertions(+), 27 deletions(-) diff --git a/src/cpu/inorder/pipeline_stage.cc b/src/cpu/inorder/pipeline_stage.cc index ac180d3c0..4dec38629 100644 --- a/src/cpu/inorder/pipeline_stage.cc +++ b/src/cpu/inorder/pipeline_stage.cc @@ -1093,6 +1093,7 @@ PipelineStage::sendInstToNextStage(DynInstPtr inst) // Take note of trace data for this inst & stage if (inst->traceData) { + //@todo: exec traces are broke. fix them inst->traceData->setStageCycle(stageNum, curTick()); } diff --git a/src/cpu/inorder/resource.cc b/src/cpu/inorder/resource.cc index b7f6a8db6..9eec63062 100644 --- a/src/cpu/inorder/resource.cc +++ b/src/cpu/inorder/resource.cc @@ -272,6 +272,7 @@ Resource::rejectRequest(DynInstPtr inst) void Resource::execute(int slot_idx) { + //@todo: have each resource print out command their executing DPRINTF(Resource, "[tid:%i]: Executing %s resource.\n", reqs[slot_idx]->getTid(), name()); reqs[slot_idx]->setCompleted(true); diff --git a/src/cpu/inorder/resources/cache_unit.cc b/src/cpu/inorder/resources/cache_unit.cc index 7c8ad6905..7a24348fc 100644 --- a/src/cpu/inorder/resources/cache_unit.cc +++ b/src/cpu/inorder/resources/cache_unit.cc @@ -105,8 +105,10 @@ CacheUnit::CachePort::recvTiming(Packet *pkt) pkt->getAddr()); else if (pkt->isResponse()) cachePortUnit->processCacheCompletion(pkt); - else - DPRINTF(Cache, "Received snoop pkt %x,Ignoring\n", pkt->getAddr()); + else { + //@note: depending on consistency model, update here + DPRINTF(InOrderCachePort, "Received snoop pkt %x,Ignoring\n", pkt->getAddr()); + } return true; } diff --git a/src/cpu/inorder/resources/execution_unit.cc b/src/cpu/inorder/resources/execution_unit.cc index c1945488c..255756956 100644 --- a/src/cpu/inorder/resources/execution_unit.cc +++ b/src/cpu/inorder/resources/execution_unit.cc @@ -45,7 +45,7 @@ ExecutionUnit::ExecutionUnit(string res_name, int res_id, int res_width, int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params) : Resource(res_name, res_id, res_width, res_latency, _cpu), - lastExecuteTick(0), lastControlTick(0), serializeTick(0) + lastExecuteTick(0), lastControlTick(0) { } void @@ -103,13 +103,6 @@ ExecutionUnit::execute(int slot_num) #if TRACING_ON InstSeqNum seq_num = inst->seqNum; #endif - if (cur_tick == serializeTick) { - DPRINTF(InOrderExecute, "Can not execute [tid:%i][sn:%i][PC:%s] %s. " - "All instructions are being serialized this cycle\n", - inst->readTid(), seq_num, inst->pcState(), inst->instName()); - exec_req->done(false); - return; - } switch (exec_req->cmd) { @@ -131,15 +124,9 @@ ExecutionUnit::execute(int slot_num) lastExecuteTick = cur_tick; } + //@todo: handle address generation here assert(!inst->isMemRef()); - if (inst->isSerializeAfter()) { - serializeTick = cur_tick; - DPRINTF(InOrderExecute, "Serializing execution after [tid:%i] " - "[sn:%i] [PC:%s] %s.\n", inst->readTid(), seq_num, - inst->pcState(), inst->instName()); - } - if (inst->isControl()) { if (lastControlTick == cur_tick) { DPRINTF(InOrderExecute, "Can not Execute More than One Control " @@ -219,11 +206,12 @@ ExecutionUnit::execute(int slot_num) #if TRACING_ON for (int didx = 0; didx < inst->numDestRegs(); didx++) if (inst->resultType(didx) == InOrderDynInst::Float || + inst->resultType(didx) == InOrderDynInst::FloatBits || inst->resultType(didx) == InOrderDynInst::Double) DPRINTF(InOrderExecute, "[tid:%i]: [sn:%i]: Dest result %i " "of FP execution is %08f (%x).\n", inst->readTid(), seq_num, didx, inst->readFloatResult(didx), - inst->readIntResult(didx)); + inst->readFloatBitsResult(didx)); else DPRINTF(InOrderExecute, "[tid:%i]: [sn:%i]: Dest result %i " "of Int execution is 0x%x.\n", inst->readTid(), diff --git a/src/cpu/inorder/resources/execution_unit.hh b/src/cpu/inorder/resources/execution_unit.hh index ed645ec3b..bebb69ca3 100644 --- a/src/cpu/inorder/resources/execution_unit.hh +++ b/src/cpu/inorder/resources/execution_unit.hh @@ -76,7 +76,6 @@ class ExecutionUnit : public Resource { Stats::Scalar executions; Tick lastExecuteTick; Tick lastControlTick; - Tick serializeTick; }; diff --git a/src/cpu/inorder/resources/use_def.cc b/src/cpu/inorder/resources/use_def.cc index 06591121e..f7376c83c 100644 --- a/src/cpu/inorder/resources/use_def.cc +++ b/src/cpu/inorder/resources/use_def.cc @@ -52,7 +52,8 @@ UseDefUnit::UseDefUnit(string res_name, int res_id, int res_width, for (ThreadID tid = 0; tid < ThePipeline::MaxThreads; tid++) { nonSpecInstActive[tid] = &cpu->nonSpecInstActive[tid]; nonSpecSeqNum[tid] = &cpu->nonSpecSeqNum[tid]; - + serializeOnNextInst[tid] = false; + serializeAfterSeqNum[tid] = 0; regDepMap[tid] = &cpu->archRegDepMap[tid]; } @@ -152,11 +153,12 @@ UseDefUnit::findRequest(DynInstPtr inst) void UseDefUnit::execute(int slot_idx) { - // After this is working, change this to a reinterpret cast - // for performance considerations UseDefRequest* ud_req = dynamic_cast(reqs[slot_idx]); - assert(ud_req); DynInstPtr inst = ud_req->inst; + ThreadID tid = inst->readTid(); + InstSeqNum seq_num = inst->seqNum; + int ud_idx = ud_req->useDefIdx; + if (inst->fault != NoFault) { DPRINTF(InOrderUseDef, "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to " @@ -166,11 +168,28 @@ UseDefUnit::execute(int slot_idx) return; } - ThreadID tid = inst->readTid(); - InstSeqNum seq_num = inst->seqNum; - int ud_idx = ud_req->useDefIdx; + if (serializeOnNextInst[tid] && + seq_num > serializeAfterSeqNum[tid]) { + inst->setSerializeBefore(); + serializeOnNextInst[tid] = false; + } + + if ((inst->isIprAccess() || inst->isSerializeBefore()) && + cpu->instList[tid].front() != inst) { + DPRINTF(InOrderUseDef, "[tid:%i]: [sn:%i] Serialize before instruction encountered." + " Blocking until pipeline is clear.\n", tid, seq_num); + ud_req->done(false); + return; + } else if (inst->isStoreConditional() || inst->isSerializeAfter()) { + DPRINTF(InOrderUseDef, "[tid:%i]: [sn:%i] Serialize after instruction encountered." + " Blocking until pipeline is clear.\n", tid, seq_num); + serializeOnNextInst[tid] = true; + serializeAfterSeqNum[tid] = seq_num; + } + // If there is a non-speculative instruction // in the pipeline then stall instructions here + // --- if (*nonSpecInstActive[tid] == true && seq_num > *nonSpecSeqNum[tid]) { DPRINTF(InOrderUseDef, "[tid:%i]: [sn:%i] cannot execute because" "there is non-speculative instruction [sn:%i] has not " diff --git a/src/cpu/inorder/resources/use_def.hh b/src/cpu/inorder/resources/use_def.hh index 7e2a77469..9581bc5f5 100644 --- a/src/cpu/inorder/resources/use_def.hh +++ b/src/cpu/inorder/resources/use_def.hh @@ -76,9 +76,11 @@ class UseDefUnit : public Resource { RegDepMap *regDepMap[ThePipeline::MaxThreads]; bool *nonSpecInstActive[ThePipeline::MaxThreads]; - InstSeqNum *nonSpecSeqNum[ThePipeline::MaxThreads]; + bool serializeOnNextInst[ThePipeline::MaxThreads]; + InstSeqNum serializeAfterSeqNum[ThePipeline::MaxThreads]; + Stats::Average uniqueRegsPerSwitch; std::map uniqueIntRegMap; std::map uniqueFloatRegMap;