Allow for fetch to retry access if the sendTiming call fails.
--HG-- extra : convert_revision : ddbcf82e0a3160c93c4e51f5d60b0a7b5983d3ba
This commit is contained in:
parent
02606ebb26
commit
a7f5f54ff8
2 changed files with 59 additions and 21 deletions
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
// //
|
// //
|
||||||
|
|
Loading…
Reference in a new issue