summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorStephan Diestelhorst <stephan.diestelhorst@arm.com>2014-04-24 13:28:47 +0100
committerStephan Diestelhorst <stephan.diestelhorst@arm.com>2014-04-24 13:28:47 +0100
commit7d488cc66f77d8c6138f0117732ebc38758e814b (patch)
tree2a0ae00833e55eab273693a4d2d17ce16224c989 /src
parentfe98cb6be471e8187658fea950bee0ecd5bf959c (diff)
downloadgem5-7d488cc66f77d8c6138f0117732ebc38758e814b.tar.xz
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.
Diffstat (limited to 'src')
-rw-r--r--src/mem/coherent_bus.cc32
-rw-r--r--src/mem/coherent_bus.hh2
2 files changed, 33 insertions, 1 deletions
diff --git a/src/mem/coherent_bus.cc b/src/mem/coherent_bus.cc
index 756d4c05c..f9d0a4968 100644
--- a/src/mem/coherent_bus.cc
+++ b/src/mem/coherent_bus.cc
@@ -197,6 +197,7 @@ CoherentBus::recvTimingReq(PacketPtr pkt, PortID slave_port_id)
if (is_express_snoop) {
assert(success);
snoopDataThroughBus += pkt_size;
+ snoopsThroughBus++;
} else {
// for normal requests, check if successful
if (!success) {
@@ -297,6 +298,7 @@ CoherentBus::recvTimingSnoopReq(PacketPtr pkt, PortID master_port_id)
// update stats here as we know the forwarding will succeed
transDist[pkt->cmdToIndex()]++;
snoopDataThroughBus += pkt->hasData() ? pkt->getSize() : 0;
+ snoopsThroughBus++;
// we should only see express snoops from caches
assert(pkt->isExpressSnoop());
@@ -411,6 +413,7 @@ CoherentBus::recvTimingSnoopResp(PacketPtr pkt, PortID slave_port_id)
// stats updates
transDist[pkt_cmd]++;
snoopDataThroughBus += pkt_size;
+ snoopsThroughBus++;
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
assert(!system->bypassCaches());
+ unsigned fanout = 0;
+
for (SlavePortIter s = snoopPorts.begin(); s != snoopPorts.end(); ++s) {
SlavePort *p = *s;
// 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) {
// cache is not allowed to refuse snoop
p->sendTimingSnoopReq(pkt);
+ fanout++;
}
}
+
+ // Stats for fanout of this forward operation
+ snoopFanout.sample(fanout);
}
void
@@ -503,6 +512,7 @@ CoherentBus::recvAtomicSnoop(PacketPtr pkt, PortID master_port_id)
// add the request snoop data
snoopDataThroughBus += pkt->hasData() ? pkt->getSize() : 0;
+ snoopsThroughBus++;
// forward to all snoopers
std::pair<MemCmd, Tick> snoop_result =
@@ -514,8 +524,10 @@ CoherentBus::recvAtomicSnoop(PacketPtr pkt, PortID master_port_id)
pkt->cmd = snoop_response_cmd;
// add the response snoop data
- if (pkt->isResponse())
+ if (pkt->isResponse()) {
snoopDataThroughBus += pkt->hasData() ? pkt->getSize() : 0;
+ snoopsThroughBus++;
+ }
// @todo: Not setting first-word time
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
assert(!system->bypassCaches());
+ unsigned fanout = 0;
+
for (SlavePortIter s = snoopPorts.begin(); s != snoopPorts.end(); ++s) {
SlavePort *p = *s;
// 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 ||
p->getId() != exclude_slave_port_id) {
Tick latency = p->sendAtomicSnoop(pkt);
+ fanout++;
+
// in contrast to a functional access, we have to keep on
// going as all snoopers must be updated even if we get a
// 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
// snoop response is part of the returned pair
return std::make_pair(snoop_response_cmd, snoop_response_latency);
@@ -667,6 +686,17 @@ CoherentBus::regStats()
.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
.name(name() + ".throughput")
.desc("Throughput (bytes/s)")
diff --git a/src/mem/coherent_bus.hh b/src/mem/coherent_bus.hh
index 8dde66d37..16ba92d26 100644
--- a/src/mem/coherent_bus.hh
+++ b/src/mem/coherent_bus.hh
@@ -341,6 +341,8 @@ class CoherentBus : public BaseBus
Stats::Scalar dataThroughBus;
Stats::Scalar snoopDataThroughBus;
+ Stats::Scalar snoopsThroughBus;
+ Stats::Distribution snoopFanout;
public: