diff -r fe572800e910 -r 0abbadf96778 src/cpu/o3/fetch.hh --- a/src/cpu/o3/fetch.hh Fri May 13 09:55:16 2011 -0700 +++ b/src/cpu/o3/fetch.hh Fri May 13 14:26:31 2011 -0700 @@ -362,6 +362,12 @@ * policy. */ ThreadID branchCount(); + /** Pipeline the next I-cache access to the current one. */ + void pipelineIcacheAccesses(ThreadID tid); + + /** Profile the reasons of fetch stall. */ + void profileStall(ThreadID tid); + private: /** Pointer to the O3CPU. */ O3CPU *cpu; @@ -493,6 +499,9 @@ /** Records if fetch is switched out. */ bool switchedOut; + /** Set to true if a pipelined I-cache request should be issued. */ + bool issuePipelinedIfetch[Impl::MaxThreads]; + // @todo: Consider making these vectors and tracking on a per thread basis. /** Stat for total number of cycles stalled due to an icache miss. */ Stats::Scalar icacheStallCycles; @@ -516,6 +525,16 @@ Stats::Scalar fetchBlockedCycles; /** Total number of cycles spent in any other state. */ Stats::Scalar fetchMiscStallCycles; + /** Total number of cycles spent in waiting for drains. */ + Stats::Scalar fetchPendingDrainCycles; + /** Total number of stall cycles caused by no active threads to run. */ + Stats::Scalar fetchNoActiveThreadStallCycles; + /** Total number of stall cycles caused by pending traps. */ + Stats::Scalar fetchPendingTrapStallCycles; + /** Total number of stall cycles caused by pending quiesce instructions. */ + Stats::Scalar fetchPendingQuiesceStallCycles; + /** Total number of stall cycles caused by I-cache wait retrys. */ + Stats::Scalar fetchIcacheWaitRetryStallCycles; /** Stat for total number of fetched cache lines. */ Stats::Scalar fetchedCacheLines; /** Total number of outstanding icache accesses that were dropped diff -r fe572800e910 -r 0abbadf96778 src/cpu/o3/fetch_impl.hh --- a/src/cpu/o3/fetch_impl.hh Fri May 13 09:55:16 2011 -0700 +++ b/src/cpu/o3/fetch_impl.hh Fri May 13 14:26:31 2011 -0700 @@ -266,6 +266,31 @@ "bad addresses, or out of MSHRs") .prereq(fetchMiscStallCycles); + fetchPendingDrainCycles + .name(name() + ".PendingDrainCycles") + .desc("Number of cycles fetch has spent waiting on pipes to drain") + .prereq(fetchPendingDrainCycles); + + fetchNoActiveThreadStallCycles + .name(name() + ".NoActiveThreadStallCycles") + .desc("Number of stall cycles due to no active thread to fetch from") + .prereq(fetchNoActiveThreadStallCycles); + + fetchPendingTrapStallCycles + .name(name() + ".PendingTrapStallCycles") + .desc("Number of stall cycles due to pending traps") + .prereq(fetchPendingTrapStallCycles); + + fetchPendingQuiesceStallCycles + .name(name() + ".PendingQuiesceStallCycles") + .desc("Number of stall cycles due to pending quiesce instructions") + .prereq(fetchPendingQuiesceStallCycles); + + fetchIcacheWaitRetryStallCycles + .name(name() + ".IcacheWaitRetryStallCycles") + .desc("Number of stall cycles due to full MSHR") + .prereq(fetchIcacheWaitRetryStallCycles); + fetchIcacheSquashes .name(name() + ".IcacheSquashes") .desc("Number of outstanding Icache misses that were squashed") @@ -661,7 +686,7 @@ } } else { DPRINTF(Fetch, "[tid:%i] Got back req with addr %#x but expected %#x\n", - mem_req->getVaddr(), memReq[tid]->getVaddr()); + tid, mem_req->getVaddr(), memReq[tid]->getVaddr()); // Translation faulted, icache request won't be sent. delete mem_req; memReq[tid] = NULL; @@ -836,6 +861,10 @@ wroteToTimeBuffer = false; + for (ThreadID i = 0; i < Impl::MaxThreads; ++i) { + issuePipelinedIfetch[i] = false; + } + while (threads != end) { ThreadID tid = *threads++; @@ -880,6 +909,13 @@ cpu->activityThisCycle(); } + + // Issue the next I-cache request if possible. + for (ThreadID i = 0; i < Impl::MaxThreads; ++i) { + if (issuePipelinedIfetch[i]) { + pipelineIcacheAccesses(i); + } + } } template @@ -1081,10 +1117,13 @@ ThreadID tid = getFetchingThread(fetchPolicy); if (tid == InvalidThreadID || drainPending) { - DPRINTF(Fetch,"There are no more threads available to fetch from.\n"); - // Breaks looping condition in tick() threadFetched = numFetchingThreads; + + if (numThreads == 1) { // @todo Per-thread stats + profileStall(0); + } + return; } @@ -1132,28 +1171,9 @@ if (fetchStatus[tid] == Idle) { ++fetchIdleCycles; DPRINTF(Fetch, "[tid:%i]: Fetch is idle!\n", tid); - } else if (fetchStatus[tid] == Blocked) { - ++fetchBlockedCycles; - DPRINTF(Fetch, "[tid:%i]: Fetch is blocked!\n", tid); - } else if (fetchStatus[tid] == Squashing) { - ++fetchSquashCycles; - DPRINTF(Fetch, "[tid:%i]: Fetch is squashing!\n", tid); - } else if (fetchStatus[tid] == IcacheWaitResponse) { - ++icacheStallCycles; - DPRINTF(Fetch, "[tid:%i]: Fetch is waiting cache response!\n", - tid); - } else if (fetchStatus[tid] == ItlbWait) { - DPRINTF(Fetch, "[tid:%i]: Fetch is waiting ITLB walk to " - "finish! \n", tid); - ++fetchTlbCycles; - } else if (fetchStatus[tid] == TrapPending) { - DPRINTF(Fetch, "[tid:%i]: Fetch is waiting for a pending trap\n", - tid); } - - // Status is Idle, Squashing, Blocked, ItlbWait or IcacheWaitResponse - // so fetch should do nothing. + // Status is Idle, so fetch should do nothing. return; } @@ -1297,6 +1317,11 @@ } pc[tid] = thisPC; + + issuePipelinedIfetch[tid] = numInst < fetchWidth && + fetchStatus[tid] != IcacheWaitResponse && + fetchStatus[tid] != ItlbWait && + fetchStatus[tid] != IcacheWaitRetry; } template @@ -1479,3 +1504,78 @@ panic("Branch Count Fetch policy unimplemented\n"); return InvalidThreadID; } + +template +void +DefaultFetch::pipelineIcacheAccesses(ThreadID tid) +{ + if (!issuePipelinedIfetch[tid]) { + return; + } + + // The next PC to access. + TheISA::PCState thisPC = pc[tid]; + + if (isRomMicroPC(thisPC.microPC())) { + return; + } + + Addr pcOffset = fetchOffset[tid]; + Addr fetchAddr = (thisPC.instAddr() + pcOffset) & BaseCPU::PCMask; + + // Align the fetch PC so its at the start of a cache block. + Addr block_PC = icacheBlockAlignPC(fetchAddr); + + // Unless buffer already got the block, fetch it from icache. + if (!(cacheDataValid[tid] && block_PC == cacheDataPC[tid])) { + DPRINTF(Fetch, "[tid:%i]: Issuing a pipelined I-cache access, " + "starting at PC %s.\n", tid, thisPC); + + fetchCacheLine(fetchAddr, tid, thisPC.instAddr()); + } +} + +template +void +DefaultFetch::profileStall(ThreadID tid) { + DPRINTF(Fetch,"There are no more threads available to fetch from.\n"); + + // @todo Per-thread stats + + if (drainPending) { + ++fetchPendingDrainCycles; + DPRINTF(Fetch, "Fetch is waiting for a drain!\n"); + } else if (activeThreads->empty()) { + ++fetchNoActiveThreadStallCycles; + DPRINTF(Fetch, "Fetch has no active thread!\n"); + } else if (fetchStatus[tid] == Blocked) { + ++fetchBlockedCycles; + DPRINTF(Fetch, "[tid:%i]: Fetch is blocked!\n", tid); + } else if (fetchStatus[tid] == Squashing) { + ++fetchSquashCycles; + DPRINTF(Fetch, "[tid:%i]: Fetch is squashing!\n", tid); + } else if (fetchStatus[tid] == IcacheWaitResponse) { + ++icacheStallCycles; + DPRINTF(Fetch, "[tid:%i]: Fetch is waiting cache response!\n", + tid); + } else if (fetchStatus[tid] == ItlbWait) { + ++fetchTlbCycles; + DPRINTF(Fetch, "[tid:%i]: Fetch is waiting ITLB walk to " + "finish!\n", tid); + } else if (fetchStatus[tid] == TrapPending) { + ++fetchPendingTrapStallCycles; + DPRINTF(Fetch, "[tid:%i]: Fetch is waiting for a pending trap!\n", + tid); + } else if (fetchStatus[tid] == QuiescePending) { + ++fetchPendingQuiesceStallCycles; + DPRINTF(Fetch, "[tid:%i]: Fetch is waiting for a pending quiesce " + "instruction!\n", tid); + } else if (fetchStatus[tid] == IcacheWaitRetry) { + ++fetchIcacheWaitRetryStallCycles; + DPRINTF(Fetch, "[tid:%i]: Fetch is waiting for an I-cache retry!\n", + tid); + } else { + DPRINTF(Fetch, "[tid:%i]: Unexpected fetch stall reason (Status: %i).\n", + tid, fetchStatus[tid]); + } +}