mem: Only track snooping ports in the snoop filter
This patch changes the tracking of ports in the snoop filter to use local dense port IDs so that we can have 64 snooping ports (rather than crossbar slave ports). This is achieved by adding a simple remapping vector that translates the actal port IDs into the local slave IDs used in the SnoopMask. Ultimately this patch allows us to scale to much larger systems without introducing a hierarchy of crossbars.
This commit is contained in:
parent
3aa87251d7
commit
ca163a80e2
|
@ -96,9 +96,6 @@ CoherentXBar::CoherentXBar(const CoherentXBarParams *p)
|
||||||
snoopRespPorts.push_back(new SnoopRespPort(*bp, *this));
|
snoopRespPorts.push_back(new SnoopRespPort(*bp, *this));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (snoopFilter)
|
|
||||||
snoopFilter->setSlavePorts(slavePorts);
|
|
||||||
|
|
||||||
clearPortCache();
|
clearPortCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,6 +130,11 @@ CoherentXBar::init()
|
||||||
|
|
||||||
if (snoopPorts.empty())
|
if (snoopPorts.empty())
|
||||||
warn("CoherentXBar %s has no snooping ports attached!\n", name());
|
warn("CoherentXBar %s has no snooping ports attached!\n", name());
|
||||||
|
|
||||||
|
// inform the snoop filter about the slave ports so it can create
|
||||||
|
// its own internal representation
|
||||||
|
if (snoopFilter)
|
||||||
|
snoopFilter->setSlavePorts(slavePorts);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -96,13 +96,27 @@ class SnoopFilter : public SimObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Init a new snoop filter and tell it about all the slave ports of the
|
* Init a new snoop filter and tell it about all the
|
||||||
* enclosing bus.
|
* slave ports of the enclosing bus.
|
||||||
*
|
*
|
||||||
* @param bus_slave_ports Vector of slave ports that the bus is attached to.
|
* @param slave_ports Slave ports that the bus is attached to.
|
||||||
*/
|
*/
|
||||||
void setSlavePorts(const SnoopList& bus_slave_ports) {
|
void setSlavePorts(const SnoopList& slave_ports) {
|
||||||
slavePorts = bus_slave_ports;
|
localSlavePortIds.resize(slave_ports.size(), InvalidPortID);
|
||||||
|
|
||||||
|
PortID id = 0;
|
||||||
|
for (const auto& p : slave_ports) {
|
||||||
|
// no need to track this port if it is not snooping
|
||||||
|
if (p->isSnooping()) {
|
||||||
|
slavePorts.push_back(p);
|
||||||
|
localSlavePortIds[p->getId()] = id++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure we can deal with this many ports
|
||||||
|
fatal_if(id > 8 * sizeof(SnoopMask),
|
||||||
|
"Snoop filter only supports %d snooping ports, got %d\n",
|
||||||
|
8 * sizeof(SnoopMask), id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -217,12 +231,6 @@ class SnoopFilter : public SimObject {
|
||||||
* @return One-hot bitmask corresponding to the port.
|
* @return One-hot bitmask corresponding to the port.
|
||||||
*/
|
*/
|
||||||
SnoopMask portToMask(const SlavePort& port) const;
|
SnoopMask portToMask(const SlavePort& port) const;
|
||||||
/**
|
|
||||||
* Convert multiple ports to a corresponding bitmask
|
|
||||||
* @param ports SnoopList that should be converted.
|
|
||||||
* @return Bitmask corresponding to the ports in the list.
|
|
||||||
*/
|
|
||||||
SnoopMask portListToMask(const SnoopList& ports) const;
|
|
||||||
/**
|
/**
|
||||||
* Converts a bitmask of ports into the corresponing list of ports
|
* Converts a bitmask of ports into the corresponing list of ports
|
||||||
* @param ports SnoopMask of the requested ports
|
* @param ports SnoopMask of the requested ports
|
||||||
|
@ -249,8 +257,10 @@ class SnoopFilter : public SimObject {
|
||||||
* (because of crossbar retry)
|
* (because of crossbar retry)
|
||||||
*/
|
*/
|
||||||
SnoopItem retryItem;
|
SnoopItem retryItem;
|
||||||
/** List of all attached slave ports. */
|
/** List of all attached snooping slave ports. */
|
||||||
SnoopList slavePorts;
|
SnoopList slavePorts;
|
||||||
|
/** Track the mapping from port ids to the local mask ids. */
|
||||||
|
std::vector<PortID> localSlavePortIds;
|
||||||
/** Cache line size. */
|
/** Cache line size. */
|
||||||
const unsigned linesize;
|
const unsigned linesize;
|
||||||
/** Latency for doing a lookup in the filter */
|
/** Latency for doing a lookup in the filter */
|
||||||
|
@ -271,29 +281,19 @@ class SnoopFilter : public SimObject {
|
||||||
inline SnoopFilter::SnoopMask
|
inline SnoopFilter::SnoopMask
|
||||||
SnoopFilter::portToMask(const SlavePort& port) const
|
SnoopFilter::portToMask(const SlavePort& port) const
|
||||||
{
|
{
|
||||||
unsigned id = (unsigned)port.getId();
|
assert(port.getId() != InvalidPortID);
|
||||||
assert(id != (unsigned)InvalidPortID);
|
// if this is not a snooping port, return a zero mask
|
||||||
assert((int)id < 8 * sizeof(SnoopMask));
|
return !port.isSnooping() ? 0 :
|
||||||
|
((SnoopMask)1) << localSlavePortIds[port.getId()];
|
||||||
return ((SnoopMask)1) << id;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline SnoopFilter::SnoopMask
|
|
||||||
SnoopFilter::portListToMask(const SnoopList& ports) const
|
|
||||||
{
|
|
||||||
SnoopMask m = 0;
|
|
||||||
for (auto port = ports.begin(); port != ports.end(); ++port)
|
|
||||||
m |= portToMask(**port);
|
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline SnoopFilter::SnoopList
|
inline SnoopFilter::SnoopList
|
||||||
SnoopFilter::maskToPortList(SnoopMask port_mask) const
|
SnoopFilter::maskToPortList(SnoopMask port_mask) const
|
||||||
{
|
{
|
||||||
SnoopList res;
|
SnoopList res;
|
||||||
for (auto port = slavePorts.begin(); port != slavePorts.end(); ++port)
|
for (const auto& p : slavePorts)
|
||||||
if (port_mask & portToMask(**port))
|
if (port_mask & portToMask(*p))
|
||||||
res.push_back(*port);
|
res.push_back(p);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
#endif // __MEM_SNOOP_FILTER_HH__
|
#endif // __MEM_SNOOP_FILTER_HH__
|
||||||
|
|
Loading…
Reference in a new issue