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.
This commit is contained in:
Ali Saidi 2011-02-23 15:10:49 -06:00
parent e572cf93ee
commit 68bd80794c
2 changed files with 33 additions and 0 deletions

View file

@ -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. */

View file

@ -268,6 +268,11 @@ DefaultFetch<Impl>::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<Impl>::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<Impl>::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<Impl>::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<Impl>::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<Impl>::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<Impl>::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;