mem: Store snoop filter lookup result to avoid second lookup

This patch introduces a private member storing the iterator from the
lookupRequest call, such that it can be re-used when the request
eventually finishes. The method previously called updateRequest is
renamed finishRequest to make it more clear that the two functions
must be called together.
This commit is contained in:
Andreas Hansson 2015-09-25 07:26:57 -04:00
parent ceec2bb02c
commit 0c5a98f9d1
3 changed files with 42 additions and 40 deletions

View file

@ -235,7 +235,7 @@ CoherentXBar::recvTimingReq(PacketPtr pkt, PortID slave_port_id)
if (snoopFilter && !system->bypassCaches()) { if (snoopFilter && !system->bypassCaches()) {
// Let the snoop filter know about the success of the send operation // Let the snoop filter know about the success of the send operation
snoopFilter->updateRequest(pkt, *src_port, !success); snoopFilter->finishRequest(!success, pkt);
} }
// check if we were successful in sending the packet onwards // check if we were successful in sending the packet onwards
@ -610,7 +610,7 @@ CoherentXBar::recvAtomic(PacketPtr pkt, PortID slave_port_id)
// operation, and do it even before sending it onwards to // operation, and do it even before sending it onwards to
// avoid situations where atomic upward snoops sneak in // avoid situations where atomic upward snoops sneak in
// between and change the filter state // between and change the filter state
snoopFilter->updateRequest(pkt, *slavePorts[slave_port_id], false); snoopFilter->finishRequest(false, pkt);
snoop_result = forwardAtomic(pkt, slave_port_id, InvalidPortID, snoop_result = forwardAtomic(pkt, slave_port_id, InvalidPortID,
sf_res.first); sf_res.first);

View file

@ -70,8 +70,8 @@ SnoopFilter::lookupRequest(const Packet* cpkt, const SlavePort& slave_port)
bool allocate = !cpkt->req->isUncacheable() && slave_port.isSnooping(); bool allocate = !cpkt->req->isUncacheable() && slave_port.isSnooping();
Addr line_addr = cpkt->getBlockAddr(linesize); Addr line_addr = cpkt->getBlockAddr(linesize);
SnoopMask req_port = portToMask(slave_port); SnoopMask req_port = portToMask(slave_port);
auto sf_it = cachedLocations.find(line_addr); reqLookupResult = cachedLocations.find(line_addr);
bool is_hit = (sf_it != cachedLocations.end()); bool is_hit = (reqLookupResult != cachedLocations.end());
// If the snoop filter has no entry, and we should not allocate, // If the snoop filter has no entry, and we should not allocate,
// do not create a new snoop filter entry, simply return a NULL // do not create a new snoop filter entry, simply return a NULL
@ -79,8 +79,10 @@ SnoopFilter::lookupRequest(const Packet* cpkt, const SlavePort& slave_port)
if (!is_hit && !allocate) if (!is_hit && !allocate)
return snoopDown(lookupLatency); return snoopDown(lookupLatency);
// Create a new element through operator[] and modify in-place // If no hit in snoop filter create a new element and update iterator
SnoopItem& sf_item = is_hit ? sf_it->second : cachedLocations[line_addr]; if (!is_hit)
reqLookupResult = cachedLocations.emplace(line_addr, SnoopItem()).first;
SnoopItem& sf_item = reqLookupResult->second;
SnoopMask interested = sf_item.holder | sf_item.requested; SnoopMask interested = sf_item.holder | sf_item.requested;
// Store unmodified value of snoop filter item in temp storage in // Store unmodified value of snoop filter item in temp storage in
@ -144,32 +146,24 @@ SnoopFilter::lookupRequest(const Packet* cpkt, const SlavePort& slave_port)
} }
void void
SnoopFilter::updateRequest(const Packet* cpkt, const SlavePort& slave_port, SnoopFilter::finishRequest(bool will_retry, const Packet* cpkt)
bool will_retry)
{ {
DPRINTF(SnoopFilter, "%s: packet src %s addr 0x%x cmd %s\n", if (reqLookupResult != cachedLocations.end()) {
__func__, slave_port.name(), cpkt->getAddr(), cpkt->cmdString()); // since we rely on the caller, do a basic check to ensure
// that finishRequest is being called following lookupRequest
assert(reqLookupResult->first == cpkt->getBlockAddr(linesize));
if (will_retry) {
// Undo any changes made in lookupRequest to the snoop filter
// entry if the request will come again. retryItem holds
// the previous value of the snoopfilter entry.
reqLookupResult->second = retryItem;
// Ultimately we should check if the packet came from an DPRINTF(SnoopFilter, "%s: restored SF value %x.%x\n",
// allocating source, not just if the port is snooping __func__, retryItem.requested, retryItem.holder);
bool allocate = !cpkt->req->isUncacheable() && slave_port.isSnooping(); }
if (!allocate)
return;
Addr line_addr = cpkt->getBlockAddr(linesize); eraseIfNullEntry(reqLookupResult);
auto sf_it = cachedLocations.find(line_addr);
assert(sf_it != cachedLocations.end());
if (will_retry) {
// Undo any changes made in lookupRequest to the snoop filter
// entry if the request will come again. retryItem holds
// the previous value of the snoopfilter entry.
sf_it->second = retryItem;
DPRINTF(SnoopFilter, "%s: restored SF value %x.%x\n",
__func__, retryItem.requested, retryItem.holder);
} }
eraseIfNullEntry(sf_it);
} }
std::pair<SnoopFilter::SnoopList, Cycles> std::pair<SnoopFilter::SnoopList, Cycles>

View file

@ -88,7 +88,8 @@ class SnoopFilter : public SimObject {
public: public:
typedef std::vector<QueuedSlavePort*> SnoopList; typedef std::vector<QueuedSlavePort*> SnoopList;
SnoopFilter (const SnoopFilterParams *p) : SimObject(p), SnoopFilter (const SnoopFilterParams *p) :
SimObject(p), reqLookupResult(cachedLocations.end()), retryItem{0, 0},
linesize(p->system->cacheLineSize()), lookupLatency(p->lookup_latency) linesize(p->system->cacheLineSize()), lookupLatency(p->lookup_latency)
{ {
} }
@ -104,10 +105,12 @@ class SnoopFilter : public SimObject {
} }
/** /**
* Lookup a request (from a slave port) in the snoop filter and return a * Lookup a request (from a slave port) in the snoop filter and
* list of other slave ports that need forwarding of the resulting snoops. * return a list of other slave ports that need forwarding of the
* Additionally, update the tracking structures with new request * resulting snoops. Additionally, update the tracking structures
* information. * with new request information. Note that the caller must also
* call finishRequest once it is known if the request needs to
* retry or not.
* *
* @param cpkt Pointer to the request packet. Not changed. * @param cpkt Pointer to the request packet. Not changed.
* @param slave_port Slave port where the request came from. * @param slave_port Slave port where the request came from.
@ -117,15 +120,15 @@ class SnoopFilter : public SimObject {
const SlavePort& slave_port); const SlavePort& slave_port);
/** /**
* For a successful request, update all data structures in the snoop filter * For an un-successful request, revert the change to the snoop
* reflecting the changes caused by that request * filter. Also take care of erasing any null entries. This method
* relies on the result from lookupRequest being stored in
* reqLookupResult.
* *
* @param cpkt Pointer to the request packet. Not changed.
* @param slave_port Slave port where the request came from.
* @param will_retry This request will retry on this bus / snoop filter * @param will_retry This request will retry on this bus / snoop filter
* @param cpkt Request packet, merely for sanity checking
*/ */
void updateRequest(const Packet* cpkt, const SlavePort& slave_port, void finishRequest(bool will_retry, const Packet* cpkt);
bool will_retry);
/** /**
* Handle an incoming snoop from below (the master port). These can upgrade the * Handle an incoming snoop from below (the master port). These can upgrade the
@ -234,9 +237,14 @@ class SnoopFilter : public SimObject {
void eraseIfNullEntry(SnoopFilterCache::iterator& sf_it); void eraseIfNullEntry(SnoopFilterCache::iterator& sf_it);
/** Simple hash set of cached addresses. */ /** Simple hash set of cached addresses. */
SnoopFilterCache cachedLocations; SnoopFilterCache cachedLocations;
/**
* Iterator used to store the result from lookupRequest until we
* call finishRequest.
*/
SnoopFilterCache::iterator reqLookupResult;
/** /**
* Variable to temporarily store value of snoopfilter entry * Variable to temporarily store value of snoopfilter entry
* incase updateRequest needs to undo changes made in lookupRequest * incase finishRequest needs to undo changes made in lookupRequest
* (because of crossbar retry) * (because of crossbar retry)
*/ */
SnoopItem retryItem; SnoopItem retryItem;