mem: Add a simple snoop counter per bus
This patch adds a simple counter for both total messages and a histogram for the fan-out of snoop messages. The fan-out describes to how many ports snoops had to be sent per incoming request / snoop-from-below. Without any cleverness, this usually means to either all, or all but the requesting port.
This commit is contained in:
parent
fe98cb6be4
commit
7d488cc66f
2 changed files with 33 additions and 1 deletions
|
@ -197,6 +197,7 @@ CoherentBus::recvTimingReq(PacketPtr pkt, PortID slave_port_id)
|
||||||
if (is_express_snoop) {
|
if (is_express_snoop) {
|
||||||
assert(success);
|
assert(success);
|
||||||
snoopDataThroughBus += pkt_size;
|
snoopDataThroughBus += pkt_size;
|
||||||
|
snoopsThroughBus++;
|
||||||
} else {
|
} else {
|
||||||
// for normal requests, check if successful
|
// for normal requests, check if successful
|
||||||
if (!success) {
|
if (!success) {
|
||||||
|
@ -297,6 +298,7 @@ CoherentBus::recvTimingSnoopReq(PacketPtr pkt, PortID master_port_id)
|
||||||
// update stats here as we know the forwarding will succeed
|
// update stats here as we know the forwarding will succeed
|
||||||
transDist[pkt->cmdToIndex()]++;
|
transDist[pkt->cmdToIndex()]++;
|
||||||
snoopDataThroughBus += pkt->hasData() ? pkt->getSize() : 0;
|
snoopDataThroughBus += pkt->hasData() ? pkt->getSize() : 0;
|
||||||
|
snoopsThroughBus++;
|
||||||
|
|
||||||
// we should only see express snoops from caches
|
// we should only see express snoops from caches
|
||||||
assert(pkt->isExpressSnoop());
|
assert(pkt->isExpressSnoop());
|
||||||
|
@ -411,6 +413,7 @@ CoherentBus::recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id)
|
||||||
// stats updates
|
// stats updates
|
||||||
transDist[pkt_cmd]++;
|
transDist[pkt_cmd]++;
|
||||||
snoopDataThroughBus += pkt_size;
|
snoopDataThroughBus += pkt_size;
|
||||||
|
snoopsThroughBus++;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -425,6 +428,8 @@ CoherentBus::forwardTiming(PacketPtr pkt, PortID exclude_slave_port_id)
|
||||||
// snoops should only happen if the system isn't bypassing caches
|
// snoops should only happen if the system isn't bypassing caches
|
||||||
assert(!system->bypassCaches());
|
assert(!system->bypassCaches());
|
||||||
|
|
||||||
|
unsigned fanout = 0;
|
||||||
|
|
||||||
for (SlavePortIter s = snoopPorts.begin(); s != snoopPorts.end(); ++s) {
|
for (SlavePortIter s = snoopPorts.begin(); s != snoopPorts.end(); ++s) {
|
||||||
SlavePort *p = *s;
|
SlavePort *p = *s;
|
||||||
// we could have gotten this request from a snooping master
|
// we could have gotten this request from a snooping master
|
||||||
|
@ -435,8 +440,12 @@ CoherentBus::forwardTiming(PacketPtr pkt, PortID exclude_slave_port_id)
|
||||||
p->getId() != exclude_slave_port_id) {
|
p->getId() != exclude_slave_port_id) {
|
||||||
// cache is not allowed to refuse snoop
|
// cache is not allowed to refuse snoop
|
||||||
p->sendTimingSnoopReq(pkt);
|
p->sendTimingSnoopReq(pkt);
|
||||||
|
fanout++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stats for fanout of this forward operation
|
||||||
|
snoopFanout.sample(fanout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -503,6 +512,7 @@ CoherentBus::recvAtomicSnoop(PacketPtr pkt, PortID master_port_id)
|
||||||
|
|
||||||
// add the request snoop data
|
// add the request snoop data
|
||||||
snoopDataThroughBus += pkt->hasData() ? pkt->getSize() : 0;
|
snoopDataThroughBus += pkt->hasData() ? pkt->getSize() : 0;
|
||||||
|
snoopsThroughBus++;
|
||||||
|
|
||||||
// forward to all snoopers
|
// forward to all snoopers
|
||||||
std::pair<MemCmd, Tick> snoop_result =
|
std::pair<MemCmd, Tick> snoop_result =
|
||||||
|
@ -514,8 +524,10 @@ CoherentBus::recvAtomicSnoop(PacketPtr pkt, PortID master_port_id)
|
||||||
pkt->cmd = snoop_response_cmd;
|
pkt->cmd = snoop_response_cmd;
|
||||||
|
|
||||||
// add the response snoop data
|
// add the response snoop data
|
||||||
if (pkt->isResponse())
|
if (pkt->isResponse()) {
|
||||||
snoopDataThroughBus += pkt->hasData() ? pkt->getSize() : 0;
|
snoopDataThroughBus += pkt->hasData() ? pkt->getSize() : 0;
|
||||||
|
snoopsThroughBus++;
|
||||||
|
}
|
||||||
|
|
||||||
// @todo: Not setting first-word time
|
// @todo: Not setting first-word time
|
||||||
pkt->busLastWordDelay = snoop_response_latency;
|
pkt->busLastWordDelay = snoop_response_latency;
|
||||||
|
@ -535,6 +547,8 @@ CoherentBus::forwardAtomic(PacketPtr pkt, PortID exclude_slave_port_id)
|
||||||
// snoops should only happen if the system isn't bypassing caches
|
// snoops should only happen if the system isn't bypassing caches
|
||||||
assert(!system->bypassCaches());
|
assert(!system->bypassCaches());
|
||||||
|
|
||||||
|
unsigned fanout = 0;
|
||||||
|
|
||||||
for (SlavePortIter s = snoopPorts.begin(); s != snoopPorts.end(); ++s) {
|
for (SlavePortIter s = snoopPorts.begin(); s != snoopPorts.end(); ++s) {
|
||||||
SlavePort *p = *s;
|
SlavePort *p = *s;
|
||||||
// we could have gotten this request from a snooping master
|
// we could have gotten this request from a snooping master
|
||||||
|
@ -544,6 +558,8 @@ CoherentBus::forwardAtomic(PacketPtr pkt, PortID exclude_slave_port_id)
|
||||||
if (exclude_slave_port_id == InvalidPortID ||
|
if (exclude_slave_port_id == InvalidPortID ||
|
||||||
p->getId() != exclude_slave_port_id) {
|
p->getId() != exclude_slave_port_id) {
|
||||||
Tick latency = p->sendAtomicSnoop(pkt);
|
Tick latency = p->sendAtomicSnoop(pkt);
|
||||||
|
fanout++;
|
||||||
|
|
||||||
// in contrast to a functional access, we have to keep on
|
// in contrast to a functional access, we have to keep on
|
||||||
// going as all snoopers must be updated even if we get a
|
// going as all snoopers must be updated even if we get a
|
||||||
// response
|
// response
|
||||||
|
@ -562,6 +578,9 @@ CoherentBus::forwardAtomic(PacketPtr pkt, PortID exclude_slave_port_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stats for fanout
|
||||||
|
snoopFanout.sample(fanout);
|
||||||
|
|
||||||
// the packet is restored as part of the loop and any potential
|
// the packet is restored as part of the loop and any potential
|
||||||
// snoop response is part of the returned pair
|
// snoop response is part of the returned pair
|
||||||
return std::make_pair(snoop_response_cmd, snoop_response_latency);
|
return std::make_pair(snoop_response_cmd, snoop_response_latency);
|
||||||
|
@ -667,6 +686,17 @@ CoherentBus::regStats()
|
||||||
.desc("Total snoop data (bytes)")
|
.desc("Total snoop data (bytes)")
|
||||||
;
|
;
|
||||||
|
|
||||||
|
snoopsThroughBus
|
||||||
|
.name(name() + ".snoops_through_bus")
|
||||||
|
.desc("Total snoops (count)")
|
||||||
|
;
|
||||||
|
|
||||||
|
snoopFanout
|
||||||
|
.init(0, snoopPorts.size(), 1)
|
||||||
|
.name(name() + ".snoop_fanout")
|
||||||
|
.desc("Request fanout histogram")
|
||||||
|
;
|
||||||
|
|
||||||
throughput
|
throughput
|
||||||
.name(name() + ".throughput")
|
.name(name() + ".throughput")
|
||||||
.desc("Throughput (bytes/s)")
|
.desc("Throughput (bytes/s)")
|
||||||
|
|
|
@ -341,6 +341,8 @@ class CoherentBus : public BaseBus
|
||||||
|
|
||||||
Stats::Scalar dataThroughBus;
|
Stats::Scalar dataThroughBus;
|
||||||
Stats::Scalar snoopDataThroughBus;
|
Stats::Scalar snoopDataThroughBus;
|
||||||
|
Stats::Scalar snoopsThroughBus;
|
||||||
|
Stats::Distribution snoopFanout;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue