use crate::sim::stats::{Meta, StatId, StatSource, Stats};
#[derive(Clone, Copy, Debug)]
pub struct HomeStatPaths {
pub read_shared: StatId,
pub read_unique: StatId,
pub clean_unique: StatId,
pub writebacks: StatId,
pub evicts: StatId,
pub maintenance: StatId,
pub stale_writebacks: StatId,
pub non_coherent: StatId,
pub snoops_sent: StatId,
pub c2c_transfers: StatId,
pub recalls: StatId,
pub serialised: StatId,
pub txn_full_stalls: StatId,
pub txn_latency: StatId,
pub filter_hits: StatId,
pub filter_misses: StatId,
}
impl HomeStatPaths {
#[must_use]
pub fn new(subject: &str) -> Self {
let path = |tail: &str| StatId::of(&format!("{subject}.{tail}"));
Self {
read_shared: path("requests.read_shared"),
read_unique: path("requests.read_unique"),
clean_unique: path("requests.clean_unique"),
writebacks: path("requests.writebacks"),
evicts: path("requests.evicts"),
maintenance: path("requests.maintenance"),
stale_writebacks: path("requests.stale_writebacks"),
non_coherent: path("requests.non_coherent"),
snoops_sent: path("snoops_sent"),
c2c_transfers: path("c2c_transfers"),
recalls: path("recalls"),
serialised: path("serialised"),
txn_full_stalls: path("txn_full_stalls"),
txn_latency: path("txn_latency"),
filter_hits: path("filter.hits"),
filter_misses: path("filter.misses"),
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct InterconnectStatPaths {
pub messages: StatId,
pub bytes: StatId,
pub blocked_cycles: StatId,
pub busy_cycles: StatId,
}
impl InterconnectStatPaths {
#[must_use]
pub fn new(subject: &str) -> Self {
let path = |tail: &str| StatId::of(&format!("{subject}.{tail}"));
Self {
messages: path("messages"),
bytes: path("bytes"),
blocked_cycles: path("blocked_cycles"),
busy_cycles: path("busy_cycles"),
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct CoherenceStatPaths {
pub home: HomeStatPaths,
pub interconnect: InterconnectStatPaths,
}
impl CoherenceStatPaths {
#[must_use]
pub fn new() -> Self {
Self {
home: HomeStatPaths::new("coherence.ha"),
interconnect: InterconnectStatPaths::new("coherence.interconnect"),
}
}
}
impl Default for CoherenceStatPaths {
fn default() -> Self {
Self::new()
}
}
impl StatSource for CoherenceStatPaths {
fn register(&self, s: &mut Stats) {
let h = &self.home;
s.register(h.read_shared, Meta::events("ReadShared requests"));
s.register(h.read_unique, Meta::events("ReadUnique requests"));
s.register(h.clean_unique, Meta::events("CleanUnique (upgrade) requests"));
s.register(h.writebacks, Meta::events("writebacks from private caches"));
s.register(h.evicts, Meta::events("silent evictions reported by private caches"));
s.register(h.maintenance, Meta::events("cache-maintenance requests from private caches"));
s.register(
h.stale_writebacks,
Meta::events("writebacks whose line a snoop had already collected"),
);
s.register(h.non_coherent, Meta::events("accesses carried to memory without snooping"));
s.register(h.snoops_sent, Meta::events("snoops sent"));
s.register(
h.c2c_transfers,
Meta::events("requests served from another core's modified copy"),
);
s.register(h.recalls, Meta::events("lines recalled to free tracking room"));
s.register(
h.serialised,
Meta::events("requests that waited for an earlier transaction on their line"),
);
s.register(h.txn_full_stalls, Meta::events("requests that waited for a transaction entry"));
s.register(h.filter_hits, Meta::events("tracking lookups that found the line"));
s.register(h.filter_misses, Meta::events("tracking lookups that found nothing"));
s.register_histogram(
h.txn_latency,
Meta::cycles("cycles from a request's arrival at the home to its completion"),
);
let i = &self.interconnect;
s.register(i.messages, Meta::events("messages transferred"));
s.register(i.bytes, Meta::events("bytes transferred"));
s.register(
i.blocked_cycles,
Meta::cycles("message-cycles spent waiting for a busy link or port"),
);
s.register(i.busy_cycles, Meta::cycles("port-class-cycles spent transferring"));
}
}