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 m5-dev@m5sim.org http://m5sim.org/mailman/listinfo/m5-dev