From: Kevin Lim Date: Fri, 9 Jun 2006 16:29:31 +0000 (-0400) Subject: Allow for fetch to retry access if the sendTiming call fails. X-Git-Tag: m5_2.0_beta1~36^2~91 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a7f5f54ff8d7097c60fdf09bf4bbba121aaff5c6;p=gem5.git Allow for fetch to retry access if the sendTiming call fails. --HG-- extra : convert_revision : ddbcf82e0a3160c93c4e51f5d60b0a7b5983d3ba --- diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index 9e8aeb8fb..960d42178 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -115,7 +115,7 @@ class DefaultFetch QuiescePending, SwitchOut, IcacheWaitResponse, - IcacheRetry, + IcacheWaitRetry, IcacheAccessComplete }; @@ -268,6 +268,8 @@ class DefaultFetch } private: + void recvRetry(); + /** Returns the appropriate thread to fetch, given the fetch policy. */ int getFetchingThread(FetchPriority &fetch_priority); @@ -360,6 +362,15 @@ class DefaultFetch /** The width of fetch in instructions. */ unsigned fetchWidth; + /** Is the cache blocked? If so no threads can access it. */ + bool cacheBlocked; + + /** The packet that is waiting to be retried. */ + PacketPtr retryPkt; + + /** The thread that is waiting on the cache to tell fetch to retry. */ + int retryTid; + /** Cache block size. */ int cacheBlkSize; diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 152b69788..e75bc264b 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -88,18 +88,7 @@ template void DefaultFetch::IcachePort::recvRetry() { - panic("DefaultFetch doesn't support retry yet."); - // we shouldn't get a retry unless we have a packet that we're - // waiting to transmit -/* - assert(cpu->dcache_pkt != NULL); - assert(cpu->_status == DcacheRetry); - Packet *tmp = cpu->dcache_pkt; - if (sendTiming(tmp)) { - cpu->_status = DcacheWaitResponse; - cpu->dcache_pkt = NULL; - } -*/ + fetch->recvRetry(); } template @@ -111,6 +100,9 @@ DefaultFetch::DefaultFetch(Params *params) iewToFetchDelay(params->iewToFetchDelay), commitToFetchDelay(params->commitToFetchDelay), fetchWidth(params->fetchWidth), + cacheBlocked(false), + retryPkt(NULL), + retryTid(-1), numThreads(params->numberOfThreads), numFetchingThreads(params->smtNumFetchingThreads), interruptPending(false), @@ -510,9 +502,11 @@ DefaultFetch::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid unsigned flags = 0; #endif // FULL_SYSTEM - if (interruptPending && flags == 0 || switchedOut) { - // Hold off fetch from getting new instructions while an interrupt - // is pending. + if (cacheBlocked || (interruptPending && flags == 0) || switchedOut) { + // Hold off fetch from getting new instructions when: + // Cache is blocked, or + // while an interrupt is pending and we're not in PAL mode, or + // fetch is switched out. return false; } @@ -528,11 +522,7 @@ DefaultFetch::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid memReq[tid] = mem_req; // Translate the instruction request. -//#if FULL_SYSTEM fault = cpu->translateInstReq(mem_req, cpu->thread[tid]); -//#else -// fault = pTable->translate(memReq[tid]); -//#endif // In the case of faults, the fetch stage may need to stall and wait // for the ITB miss to be handled. @@ -563,8 +553,13 @@ DefaultFetch::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid // Now do the timing access to see whether or not the instruction // exists within the cache. if (!icachePort->sendTiming(data_pkt)) { + assert(retryPkt == NULL); + assert(retryTid == -1); DPRINTF(Fetch, "[tid:%i] Out of MSHRs!\n", tid); - ret_fault = NoFault; + fetchStatus[tid] = IcacheWaitRetry; + retryPkt = data_pkt; + retryTid = tid; + cacheBlocked = true; return false; } @@ -604,6 +599,16 @@ DefaultFetch::doSquash(const Addr &new_PC, unsigned tid) memReq[tid] = NULL; } + // Get rid of the retrying packet if it was from this thread. + if (retryTid == tid) { + assert(cacheBlocked); + cacheBlocked = false; + retryTid = -1; + retryPkt = NULL; + delete retryPkt->req; + delete retryPkt; + } + fetchStatus[tid] = Squashing; ++fetchSquashCycles; @@ -1103,6 +1108,28 @@ DefaultFetch::fetch(bool &status_change) } } +template +void +DefaultFetch::recvRetry() +{ + assert(cacheBlocked); + if (retryPkt != NULL) { + assert(retryTid != -1); + assert(fetchStatus[retryTid] == IcacheWaitRetry); + + if (icachePort->sendTiming(retryPkt)) { + fetchStatus[retryTid] = IcacheWaitResponse; + retryPkt = NULL; + retryTid = -1; + cacheBlocked = false; + } + } else { + assert(retryTid == -1); + // Access has been squashed since it was sent out. Just clear + // the cache being blocked. + cacheBlocked = false; + } +} /////////////////////////////////////// // //