Allow for fetch to retry access if the sendTiming call fails.

--HG--
extra : convert_revision : ddbcf82e0a3160c93c4e51f5d60b0a7b5983d3ba
This commit is contained in:
Kevin Lim 2006-06-09 12:29:31 -04:00
parent 02606ebb26
commit a7f5f54ff8
2 changed files with 59 additions and 21 deletions

View file

@ -115,7 +115,7 @@ class DefaultFetch
QuiescePending, QuiescePending,
SwitchOut, SwitchOut,
IcacheWaitResponse, IcacheWaitResponse,
IcacheRetry, IcacheWaitRetry,
IcacheAccessComplete IcacheAccessComplete
}; };
@ -268,6 +268,8 @@ class DefaultFetch
} }
private: private:
void recvRetry();
/** Returns the appropriate thread to fetch, given the fetch policy. */ /** Returns the appropriate thread to fetch, given the fetch policy. */
int getFetchingThread(FetchPriority &fetch_priority); int getFetchingThread(FetchPriority &fetch_priority);
@ -360,6 +362,15 @@ class DefaultFetch
/** The width of fetch in instructions. */ /** The width of fetch in instructions. */
unsigned fetchWidth; 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. */ /** Cache block size. */
int cacheBlkSize; int cacheBlkSize;

View file

@ -88,18 +88,7 @@ template<class Impl>
void void
DefaultFetch<Impl>::IcachePort::recvRetry() DefaultFetch<Impl>::IcachePort::recvRetry()
{ {
panic("DefaultFetch doesn't support retry yet."); fetch->recvRetry();
// 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;
}
*/
} }
template<class Impl> template<class Impl>
@ -111,6 +100,9 @@ DefaultFetch<Impl>::DefaultFetch(Params *params)
iewToFetchDelay(params->iewToFetchDelay), iewToFetchDelay(params->iewToFetchDelay),
commitToFetchDelay(params->commitToFetchDelay), commitToFetchDelay(params->commitToFetchDelay),
fetchWidth(params->fetchWidth), fetchWidth(params->fetchWidth),
cacheBlocked(false),
retryPkt(NULL),
retryTid(-1),
numThreads(params->numberOfThreads), numThreads(params->numberOfThreads),
numFetchingThreads(params->smtNumFetchingThreads), numFetchingThreads(params->smtNumFetchingThreads),
interruptPending(false), interruptPending(false),
@ -510,9 +502,11 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
unsigned flags = 0; unsigned flags = 0;
#endif // FULL_SYSTEM #endif // FULL_SYSTEM
if (interruptPending && flags == 0 || switchedOut) { if (cacheBlocked || (interruptPending && flags == 0) || switchedOut) {
// Hold off fetch from getting new instructions while an interrupt // Hold off fetch from getting new instructions when:
// is pending. // Cache is blocked, or
// while an interrupt is pending and we're not in PAL mode, or
// fetch is switched out.
return false; return false;
} }
@ -528,11 +522,7 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
memReq[tid] = mem_req; memReq[tid] = mem_req;
// Translate the instruction request. // Translate the instruction request.
//#if FULL_SYSTEM
fault = cpu->translateInstReq(mem_req, cpu->thread[tid]); 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 // In the case of faults, the fetch stage may need to stall and wait
// for the ITB miss to be handled. // for the ITB miss to be handled.
@ -563,8 +553,13 @@ DefaultFetch<Impl>::fetchCacheLine(Addr fetch_PC, Fault &ret_fault, unsigned tid
// Now do the timing access to see whether or not the instruction // Now do the timing access to see whether or not the instruction
// exists within the cache. // exists within the cache.
if (!icachePort->sendTiming(data_pkt)) { if (!icachePort->sendTiming(data_pkt)) {
assert(retryPkt == NULL);
assert(retryTid == -1);
DPRINTF(Fetch, "[tid:%i] Out of MSHRs!\n", tid); DPRINTF(Fetch, "[tid:%i] Out of MSHRs!\n", tid);
ret_fault = NoFault; fetchStatus[tid] = IcacheWaitRetry;
retryPkt = data_pkt;
retryTid = tid;
cacheBlocked = true;
return false; return false;
} }
@ -604,6 +599,16 @@ DefaultFetch<Impl>::doSquash(const Addr &new_PC, unsigned tid)
memReq[tid] = NULL; 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; fetchStatus[tid] = Squashing;
++fetchSquashCycles; ++fetchSquashCycles;
@ -1103,6 +1108,28 @@ DefaultFetch<Impl>::fetch(bool &status_change)
} }
} }
template<class Impl>
void
DefaultFetch<Impl>::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;
}
}
/////////////////////////////////////// ///////////////////////////////////////
// // // //