changeset 2290428b5f04 in /z/repo/m5
details: http://repo.m5sim.org/m5?cmd=changeset;node=2290428b5f04
description:
O3: Support timing translations for O3 CPU fetch.
diffstat:
src/cpu/o3/fetch.hh | 38 ++++-
src/cpu/o3/fetch_impl.hh | 371 ++++++++++++++++++++++------------------------
2 files changed, 212 insertions(+), 197 deletions(-)
diffs (truncated from 577 to 300 lines):
diff -r cc5e64f8423f -r 2290428b5f04 src/cpu/o3/fetch.hh
--- a/src/cpu/o3/fetch.hh Tue Jan 18 16:30:02 2011 -0600
+++ b/src/cpu/o3/fetch.hh Tue Jan 18 16:30:02 2011 -0600
@@ -1,4 +1,16 @@
/*
+ * Copyright (c) 2010 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2004-2006 The Regents of The University of Michigan
* All rights reserved.
*
@@ -38,6 +50,7 @@
#include "cpu/timebuf.hh"
#include "config/the_isa.hh"
#include "cpu/pc_event.hh"
+#include "cpu/translation.hh"
#include "mem/packet.hh"
#include "mem/port.hh"
#include "sim/eventq.hh"
@@ -113,6 +126,25 @@
virtual void recvRetry();
};
+ class FetchTranslation : public BaseTLB::Translation
+ {
+ protected:
+ DefaultFetch<Impl> *fetch;
+
+ public:
+ FetchTranslation(DefaultFetch<Impl> *_fetch)
+ : fetch(_fetch)
+ {}
+
+ void
+ finish(Fault fault, RequestPtr req, ThreadContext *tc,
+ BaseTLB::Mode mode)
+ {
+ assert(mode == BaseTLB::Execute);
+ fetch->finishTranslation(fault, req);
+ delete this;
+ }
+ };
public:
/** Overall fetch status. Used to determine if the CPU can
@@ -133,6 +165,7 @@
TrapPending,
QuiescePending,
SwitchOut,
+ ItlbWait,
IcacheWaitResponse,
IcacheWaitRetry,
IcacheAccessComplete
@@ -242,7 +275,8 @@
* @param pc The actual PC of the current instruction.
* @return Any fault that occured.
*/
- bool fetchCacheLine(Addr vaddr, Fault &ret_fault, ThreadID tid, Addr pc);
+ bool fetchCacheLine(Addr vaddr, ThreadID tid, Addr pc);
+ void finishTranslation(Fault fault, RequestPtr mem_req);
/** Check if an interrupt is pending and that we need to handle
@@ -468,6 +502,8 @@
Stats::Scalar fetchCycles;
/** Stat for total number of cycles spent squashing. */
Stats::Scalar fetchSquashCycles;
+ /** Stat for total number of cycles spent waiting for translation */
+ Stats::Scalar fetchTlbCycles;
/** Stat for total number of cycles spent blocked due to other stages in
* the pipeline.
*/
diff -r cc5e64f8423f -r 2290428b5f04 src/cpu/o3/fetch_impl.hh
--- a/src/cpu/o3/fetch_impl.hh Tue Jan 18 16:30:02 2011 -0600
+++ b/src/cpu/o3/fetch_impl.hh Tue Jan 18 16:30:02 2011 -0600
@@ -237,6 +237,11 @@
.desc("Number of cycles fetch has spent squashing")
.prereq(fetchSquashCycles);
+ fetchTlbCycles
+ .name(name() + ".TlbCycles")
+ .desc("Number of cycles fetch has spent waiting for tlb")
+ .prereq(fetchTlbCycles);
+
fetchIdleCycles
.name(name() + ".IdleCycles")
.desc("Number of cycles fetch was idle")
@@ -548,11 +553,11 @@
template <class Impl>
bool
-DefaultFetch<Impl>::fetchCacheLine(Addr vaddr, Fault &ret_fault, ThreadID tid,
- Addr pc)
+DefaultFetch<Impl>::fetchCacheLine(Addr vaddr, ThreadID tid, Addr pc)
{
Fault fault = NoFault;
+ // @todo: not sure if these should block translation.
//AlphaDep
if (cacheBlocked) {
DPRINTF(Fetch, "[tid:%i] Can't fetch cache line, cache blocked\n",
@@ -575,11 +580,6 @@
// Align the fetch address so it's at the start of a cache block.
Addr block_PC = icacheBlockAlignPC(vaddr);
- // If we've already got the block, no need to try to fetch it again.
- if (cacheDataValid[tid] && block_PC == cacheDataPC[tid]) {
- return true;
- }
-
// 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.
@@ -589,27 +589,23 @@
memReq[tid] = mem_req;
- // Translate the instruction request.
- fault = cpu->itb->translateAtomic(mem_req, cpu->thread[tid]->getTC(),
- BaseTLB::Execute);
+ // Initiate translation of the icache block
+ fetchStatus[tid] = ItlbWait;
+ FetchTranslation *trans = new FetchTranslation(this);
+ cpu->itb->translateTiming(mem_req, cpu->thread[tid]->getTC(),
+ trans, BaseTLB::Execute);
+ return true;
+}
- // In the case of faults, the fetch stage may need to stall and wait
- // for the ITB miss to be handled.
+template <class Impl>
+void
+DefaultFetch<Impl>::finishTranslation(Fault fault, RequestPtr mem_req)
+{
+ ThreadID tid = mem_req->threadId();
+ Addr block_PC = mem_req->getVaddr();
- // If translation was successful, attempt to read the first
- // instruction.
+ // If translation was successful, attempt to read the icache block.
if (fault == NoFault) {
-#if 0
- if (cpu->system->memctrl->badaddr(memReq[tid]->paddr) ||
- memReq[tid]->isUncacheable()) {
- DPRINTF(Fetch, "Fetch: Bad address %#x (hopefully on a "
- "misspeculating path)!",
- memReq[tid]->paddr);
- ret_fault = TheISA::genMachineCheckFault();
- return false;
- }
-#endif
-
// Build packet here.
PacketPtr data_pkt = new Packet(mem_req,
MemCmd::ReadReq, Packet::Broadcast);
@@ -617,39 +613,54 @@
cacheDataPC[tid] = block_PC;
cacheDataValid[tid] = false;
-
DPRINTF(Fetch, "Fetch: Doing instruction read.\n");
fetchedCacheLines++;
- // Now do the timing access to see whether or not the instruction
- // exists within the cache.
+ // Access the cache.
if (!icachePort->sendTiming(data_pkt)) {
assert(retryPkt == NULL);
assert(retryTid == InvalidThreadID);
DPRINTF(Fetch, "[tid:%i] Out of MSHRs!\n", tid);
+
fetchStatus[tid] = IcacheWaitRetry;
retryPkt = data_pkt;
retryTid = tid;
cacheBlocked = true;
- return false;
+ } else {
+ DPRINTF(Fetch, "[tid:%i]: Doing Icache access.\n", tid);
+ DPRINTF(Activity, "[tid:%i]: Activity: Waiting on I-cache "
+ "response.\n", tid);
+
+ lastIcacheStall[tid] = curTick();
+ fetchStatus[tid] = IcacheWaitResponse;
}
-
- DPRINTF(Fetch, "[tid:%i]: Doing cache access.\n", tid);
-
- lastIcacheStall[tid] = curTick();
-
- DPRINTF(Activity, "[tid:%i]: Activity: Waiting on I-cache "
- "response.\n", tid);
-
- fetchStatus[tid] = IcacheWaitResponse;
} else {
+ // Translation faulted, icache request won't be sent.
delete mem_req;
memReq[tid] = NULL;
+
+ // Send the fault to commit. This thread will not do anything
+ // until commit handles the fault. The only other way it can
+ // wake up is if a squash comes along and changes the PC.
+ TheISA::PCState fetchPC = pc[tid];
+
+ // We will use a nop in ordier to carry the fault.
+ DynInstPtr instruction = buildInst(tid,
+ StaticInstPtr(TheISA::NoopMachInst, fetchPC.instAddr()),
+ NULL, fetchPC, fetchPC, false);
+
+ instruction->setPredTarg(fetchPC);
+ instruction->fault = fault;
+ wroteToTimeBuffer = true;
+
+ fetchStatus[tid] = TrapPending;
+
+ DPRINTF(Fetch, "[tid:%i]: Blocked, need to handle the trap.\n", tid);
+ DPRINTF(Fetch, "[tid:%i]: fault (%s) detected @ PC %s.\n",
+ tid, fault->name(), pc[tid]);
}
-
- ret_fault = fault;
- return true;
+ _status = updateFetchStatus();
}
template <class Impl>
@@ -1044,9 +1055,6 @@
// The current PC.
TheISA::PCState thisPC = pc[tid];
- // Fault code for memory access.
- Fault fault = NoFault;
-
Addr pcOffset = fetchOffset[tid];
Addr fetchAddr = (thisPC.instAddr() + pcOffset) & BaseCPU::PCMask;
@@ -1054,22 +1062,30 @@
// to running, otherwise do the cache access. Possibly move this up
// to tick() function.
if (fetchStatus[tid] == IcacheAccessComplete) {
- DPRINTF(Fetch, "[tid:%i]: Icache miss is complete.\n",tid);
+ DPRINTF(Fetch, "[tid:%i]: Icache miss is complete.\n", tid);
fetchStatus[tid] = Running;
status_change = true;
} else if (fetchStatus[tid] == Running) {
- DPRINTF(Fetch, "[tid:%i]: Attempting to translate and read "
- "instruction, starting at PC %#x.\n", tid, fetchAddr);
+ // Align the fetch PC so its at the start of a cache block.
+ Addr block_PC = icacheBlockAlignPC(fetchAddr);
- bool fetch_success = fetchCacheLine(fetchAddr, fault, tid,
- thisPC.instAddr());
- if (!fetch_success) {
- if (cacheBlocked) {
+ // Unless buffer already got the block, fetch it from icache.
+ if (!cacheDataValid[tid] || block_PC != cacheDataPC[tid]) {
+ DPRINTF(Fetch, "[tid:%i]: Attempting to translate and read "
+ "instruction, starting at PC %s.\n", tid, thisPC);
+
+ fetchCacheLine(fetchAddr, tid, thisPC.instAddr());
+
+ if (fetchStatus[tid] == IcacheWaitResponse)
++icacheStallCycles;
- } else {
+ else if (fetchStatus[tid] == ItlbWait)
+ ++fetchTlbCycles;
+ else
++fetchMiscStallCycles;
- }
+ return;
+ } else if (checkInterrupt(thisPC.instAddr()) || isSwitchedOut()) {
+ ++fetchMiscStallCycles;
return;
}
} else {
@@ -1084,145 +1100,140 @@
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);
+ 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;
}
- // Status is Idle, Squashing, Blocked, or IcacheWaitResponse, so
- // fetch should do nothing.
_______________________________________________
m5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/m5-dev