From 68bd80794c8c72de9c1b447ab21e8c4c0a315ee3 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Wed, 23 Feb 2011 15:10:49 -0600 Subject: O3: Fix bug when a squash occurs right before TLB miss returns. In this case we need to throw away the TLB miss, not assume it was the one we were waiting for. --- src/cpu/o3/fetch.hh | 4 ++++ src/cpu/o3/fetch_impl.hh | 29 +++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) (limited to 'src/cpu/o3') diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index 647c48a76..c51658104 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -522,6 +522,10 @@ class DefaultFetch * due to a squash. */ Stats::Scalar fetchIcacheSquashes; + /** Total number of outstanding tlb accesses that were dropped + * due to a squash. + */ + Stats::Scalar fetchTlbSquashes; /** Distribution of number of instructions fetched each cycle. */ Stats::Distribution fetchNisnDist; /** Rate of how often fetch was idle. */ diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index d2cde496e..2c4906760 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -268,6 +268,11 @@ DefaultFetch::regStats() .desc("Number of outstanding Icache misses that were squashed") .prereq(fetchIcacheSquashes); + fetchTlbSquashes + .name(name() + ".ItlbSquashes") + .desc("Number of outstanding ITLB misses that were squashed") + .prereq(fetchTlbSquashes); + fetchNisnDist .init(/* base value */ 0, /* last value */ fetchWidth, @@ -580,6 +585,9 @@ DefaultFetch::fetchCacheLine(Addr vaddr, ThreadID tid, Addr pc) // Align the fetch address so it's at the start of a cache block. Addr block_PC = icacheBlockAlignPC(vaddr); + DPRINTF(Fetch, "[tid:%i] Fetching cache line %#x for addr %#x\n", + tid, block_PC, vaddr); + // Setup the memReq to do a read of the first instruction's address. // Set the appropriate read size and flags as well. // Build request here. @@ -607,6 +615,16 @@ DefaultFetch::finishTranslation(Fault fault, RequestPtr mem_req) // Wake up CPU if it was idle cpu->wakeCPU(); + if (fetchStatus[tid] != ItlbWait || mem_req != memReq[tid] || + mem_req->getVaddr() != memReq[tid]->getVaddr() || isSwitchedOut()) { + DPRINTF(Fetch, "[tid:%i] Ignoring itlb completed after squash\n", + tid); + ++fetchTlbSquashes; + delete mem_req; + return; + } + + // If translation was successful, attempt to read the icache block. if (fault == NoFault) { // Build packet here. @@ -639,6 +657,8 @@ DefaultFetch::finishTranslation(Fault fault, RequestPtr mem_req) fetchStatus[tid] = IcacheWaitResponse; } } else { + DPRINTF(Fetch, "[tid:%i] Got back req with addr %#x but expected %#x\n", + mem_req->getVaddr(), memReq[tid]->getVaddr()); // Translation faulted, icache request won't be sent. delete mem_req; memReq[tid] = NULL; @@ -648,6 +668,7 @@ DefaultFetch::finishTranslation(Fault fault, RequestPtr mem_req) // wake up is if a squash comes along and changes the PC. TheISA::PCState fetchPC = pc[tid]; + DPRINTF(Fetch, "[tid:%i]: Translation faulted, building noop.\n", tid); // We will use a nop in ordier to carry the fault. DynInstPtr instruction = buildInst(tid, StaticInstPtr(TheISA::NoopMachInst, fetchPC.instAddr()), @@ -686,6 +707,10 @@ DefaultFetch::doSquash(const TheISA::PCState &newPC, ThreadID tid) DPRINTF(Fetch, "[tid:%i]: Squashing outstanding Icache miss.\n", tid); memReq[tid] = NULL; + } else if (fetchStatus[tid] == ItlbWait) { + DPRINTF(Fetch, "[tid:%i]: Squashing outstanding ITLB miss.\n", + tid); + memReq[tid] = NULL; } // Get rid of the retrying packet if it was from this thread. @@ -1120,8 +1145,12 @@ DefaultFetch::fetch(bool &status_change) 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. return; -- cgit v1.2.3