summaryrefslogtreecommitdiff
path: root/src/cpu/o3/fetch_impl.hh
diff options
context:
space:
mode:
authorAli Saidi <Ali.Saidi@ARM.com>2011-02-23 15:10:49 -0600
committerAli Saidi <Ali.Saidi@ARM.com>2011-02-23 15:10:49 -0600
commit68bd80794c8c72de9c1b447ab21e8c4c0a315ee3 (patch)
tree92acb1e184bfa8d2965d468ca053eaff0d413c65 /src/cpu/o3/fetch_impl.hh
parente572cf93ee411ef40acdb64eb3073231619862ed (diff)
downloadgem5-68bd80794c8c72de9c1b447ab21e8c4c0a315ee3.tar.xz
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.
Diffstat (limited to 'src/cpu/o3/fetch_impl.hh')
-rw-r--r--src/cpu/o3/fetch_impl.hh29
1 files changed, 29 insertions, 0 deletions
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<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;