/*
- * Copyright (c) 2013-2017 ARM Limited
+ * Copyright (c) 2013-2017,2019 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
#include "debug/SnoopFilter.hh"
#include "sim/system.hh"
+const int SnoopFilter::SNOOP_MASK_SIZE;
+
void
SnoopFilter::eraseIfNullEntry(SnoopFilterCache::iterator& sf_it)
{
SnoopItem& sf_item = sf_it->second;
- if (!(sf_item.requested | sf_item.holder)) {
+ if ((sf_item.requested | sf_item.holder).none()) {
cachedLocations.erase(sf_it);
DPRINTF(SnoopFilter, "%s: Removed SF entry.\n",
__func__);
totRequests++;
if (is_hit) {
- // Single bit set -> value is a power of two
- if (isPow2(interested))
+ if (interested.count() == 1)
hitSingleRequests++;
else
hitMultiRequests++;
if (cpkt->needsResponse()) {
if (!cpkt->cacheResponding()) {
// Max one request per address per port
- panic_if(sf_item.requested & req_port, "double request :( " \
- "SF value %x.%x\n", sf_item.requested, sf_item.holder);
+ panic_if((sf_item.requested & req_port).any(),
+ "double request :( SF value %x.%x\n",
+ sf_item.requested, sf_item.holder);
// Mark in-flight requests to distinguish later on
sf_item.requested |= req_port;
// to the CPU, already -> the response will not be seen by this
// filter -> we do not need to keep the in-flight request, but make
// sure that we know that that cluster has a copy
- panic_if(!(sf_item.holder & req_port), "Need to hold the value!");
+ panic_if((sf_item.holder & req_port).none(),
+ "Need to hold the value!");
DPRINTF(SnoopFilter,
"%s: not marking request. SF value %x.%x\n",
__func__, sf_item.requested, sf_item.holder);
} else { // if (!cpkt->needsResponse())
assert(cpkt->isEviction());
// make sure that the sender actually had the line
- panic_if(!(sf_item.holder & req_port), "requester %x is not a " \
+ panic_if((sf_item.holder & req_port).none(), "requester %x is not a " \
"holder :( SF value %x.%x\n", req_port,
sf_item.requested, sf_item.holder);
// CleanEvicts and Writebacks -> the sender and all caches above
SnoopMask interested = (sf_item.holder | sf_item.requested);
totSnoops++;
- // Single bit set -> value is a power of two
- if (isPow2(interested))
+
+ if (interested.count() == 1)
hitSingleSnoops++;
else
hitMultiSnoops++;
assert(cpkt->isWriteback() || cpkt->req->isUncacheable() ||
(cpkt->isInvalidate() == cpkt->needsWritable()) ||
cpkt->req->isCacheMaintenance());
- if (cpkt->isInvalidate() && !sf_item.requested) {
+ if (cpkt->isInvalidate() && sf_item.requested.none()) {
// Early clear of the holder, if no other request is currently going on
// @todo: This should possibly be updated even though we do not filter
// upward snoops
__func__, sf_item.requested, sf_item.holder);
// The source should have the line
- panic_if(!(sf_item.holder & rsp_mask), "SF value %x.%x does not have "\
- "the line\n", sf_item.requested, sf_item.holder);
+ panic_if((sf_item.holder & rsp_mask).none(),
+ "SF value %x.%x does not have the line\n",
+ sf_item.requested, sf_item.holder);
// The destination should have had a request in
- panic_if(!(sf_item.requested & req_mask), "SF value %x.%x missing "\
+ panic_if((sf_item.requested & req_mask).none(), "SF value %x.%x missing "\
"the original request\n", sf_item.requested, sf_item.holder);
// If the snoop response has no sharers the line is passed in
// @todo Deal with invalidating responses
sf_item.holder |= req_mask;
sf_item.requested &= ~req_mask;
- assert(sf_item.requested | sf_item.holder);
+ assert((sf_item.requested | sf_item.holder).any());
DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
__func__, sf_item.requested, sf_item.holder);
}
__func__, sf_item.requested, sf_item.holder);
// Make sure we have seen the actual request, too
- panic_if(!(sf_item.requested & slave_mask), "SF value %x.%x missing "\
- "request bit\n", sf_item.requested, sf_item.holder);
+ panic_if((sf_item.requested & slave_mask).none(),
+ "SF value %x.%x missing request bit\n",
+ sf_item.requested, sf_item.holder);
sf_item.requested &= ~slave_mask;
// Update the residency of the cache line.
// Any other response implies that a cache above will have the
// block.
sf_item.holder |= slave_mask;
- assert(sf_item.holder | sf_item.requested);
+ assert((sf_item.holder | sf_item.requested).any());
}
DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
__func__, sf_item.requested, sf_item.holder);
/*
- * Copyright (c) 2013-2016 ARM Limited
+ * Copyright (c) 2013-2016,2019 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
#ifndef __MEM_SNOOP_FILTER_HH__
#define __MEM_SNOOP_FILTER_HH__
+#include <bitset>
#include <unordered_map>
#include <utility>
*/
class SnoopFilter : public SimObject {
public:
+
+ // Change for systems with more than 256 ports tracked by this object
+ static const int SNOOP_MASK_SIZE = 256;
+
typedef std::vector<QueuedSlavePort*> SnoopList;
SnoopFilter (const SnoopFilterParams *p) :
}
// make sure we can deal with this many ports
- fatal_if(id > 8 * sizeof(SnoopMask),
+ fatal_if(id > SNOOP_MASK_SIZE,
"Snoop filter only supports %d snooping ports, got %d\n",
- 8 * sizeof(SnoopMask), id);
+ SNOOP_MASK_SIZE, id);
}
/**
/**
* The underlying type for the bitmask we use for tracking. This
- * limits the number of snooping ports supported per crossbar. For
- * the moment it is an uint64_t to offer maximum
- * scalability. However, it is possible to use e.g. a uint16_t or
- * uint32_to slim down the footprint of the hash map (and
- * ultimately improve the simulation performance).
+ * limits the number of snooping ports supported per crossbar.
*/
- typedef uint64_t SnoopMask;
+ typedef std::bitset<SNOOP_MASK_SIZE> SnoopMask;
/**
* Per cache line item tracking a bitmask of SlavePorts who have an
{
SnoopList res;
for (const auto& p : slavePorts)
- if (port_mask & portToMask(*p))
+ if ((port_mask & portToMask(*p)).any())
res.push_back(p);
return res;
}