mem: Add a flag on AbstractMemory to control statistics collection (#656)

The stats initialization in the AbstractMemory allocates the space
according to the max requestors of the System. This may cause issues in
multiple system simulation.
Given there are two system A and B. A has one requestor and a memory,
while B has two requestors. When the requestor with requestor id 2
sending requests to the meomry in A, the simulator would crash because
requestor id 2 is out of the allocated space.

Current solution is adding a SysBridge between across A and B which
would rewrite the requestor id to a valid one. This solution works but
it needs to the bridge at the correct boundary which may not easy. In
addition, the stats would record a mapped data which may not accurate.

To reduce the complexity, we add an flag to AbstractMemory to control
the stats. If users don't want the statistics and want to solve the
cross system issue simply, users can disable the statistics collection.
We also makes the flag by default True to not disturb current users.
This commit is contained in:
Bobby R. Bruce
2023-12-12 13:13:30 -08:00
committed by GitHub
3 changed files with 28 additions and 9 deletions

View File

@@ -76,3 +76,12 @@ class AbstractMemory(ClockedObject):
)
writeable = Param.Bool(True, "Allow writes to this memory")
collect_stats = Param.Bool(
True,
"Collect statistics per requestor for "
"each type of access. Set this to `False` if "
"requestors may be unknown or when running "
"with multiple `System` objects without a "
"`SysBridge`.",
)

View File

@@ -63,8 +63,8 @@ AbstractMemory::AbstractMemory(const Params &p) :
MemBackdoor::Readable | MemBackdoor::Writeable :
MemBackdoor::Readable)),
confTableReported(p.conf_table_reported), inAddrMap(p.in_addr_map),
kvmMap(p.kvm_map), writeable(p.writeable), _system(NULL),
stats(*this)
kvmMap(p.kvm_map), writeable(p.writeable), collectStats(p.collect_stats),
_system(NULL), stats(*this)
{
panic_if(!range.valid() || !range.size(),
"Memory range %s must be valid with non-zero size.",
@@ -433,7 +433,9 @@ AbstractMemory::access(PacketPtr pkt)
assert(!pkt->req->isInstFetch());
TRACE_PACKET("Read/Write");
stats.numOther[pkt->req->requestorId()]++;
if (collectStats) {
stats.numOther[pkt->req->requestorId()]++;
}
}
} else if (pkt->isRead()) {
assert(!pkt->isWrite());
@@ -447,10 +449,13 @@ AbstractMemory::access(PacketPtr pkt)
pkt->setData(host_addr);
}
TRACE_PACKET(pkt->req->isInstFetch() ? "IFetch" : "Read");
stats.numReads[pkt->req->requestorId()]++;
stats.bytesRead[pkt->req->requestorId()] += pkt->getSize();
if (pkt->req->isInstFetch())
stats.bytesInstRead[pkt->req->requestorId()] += pkt->getSize();
if (collectStats) {
stats.numReads[pkt->req->requestorId()]++;
stats.bytesRead[pkt->req->requestorId()] += pkt->getSize();
if (pkt->req->isInstFetch()) {
stats.bytesInstRead[pkt->req->requestorId()] += pkt->getSize();
}
}
} else if (pkt->isInvalidate() || pkt->isClean()) {
assert(!pkt->isWrite());
// in a fastmem system invalidating and/or cleaning packets
@@ -466,8 +471,10 @@ AbstractMemory::access(PacketPtr pkt)
}
assert(!pkt->req->isInstFetch());
TRACE_PACKET("Write");
stats.numWrites[pkt->req->requestorId()]++;
stats.bytesWritten[pkt->req->requestorId()] += pkt->getSize();
if (collectStats) {
stats.numWrites[pkt->req->requestorId()]++;
stats.bytesWritten[pkt->req->requestorId()] += pkt->getSize();
}
}
} else {
panic("Unexpected packet %s", pkt->print());

View File

@@ -132,6 +132,9 @@ class AbstractMemory : public ClockedObject
// Are writes allowed to this memory
const bool writeable;
// Should collect traffic statistics
const bool collectStats;
std::list<LockedAddr> lockedAddrList;
// helper function for checkLockedAddrs(): we really want to