use crate::common::LineAddr;
use crate::config::InclusionPolicy;
use crate::sim::components::ComponentId;
use crate::sim::handle::HandleCtx;
use crate::sim::packet::Packet;
use super::Cache;
use super::writeback_buffer::WritebackCause;
impl Cache {
pub(super) fn back_invalidate(
&self,
line: LineAddr,
holders: &[ComponentId],
ctx: &mut HandleCtx<'_>,
) {
if self.upstream_inclusion != InclusionPolicy::Inclusive {
return;
}
for &upstream in holders {
ctx.scheduler.schedule(
ctx.cycle,
upstream,
ctx.self_id,
Packet::CacheInval { line_addr: line },
);
}
}
pub(super) fn on_back_invalidate(&mut self, line: LineAddr, ctx: &mut HandleCtx<'_>) {
if !self.enabled {
return;
}
let holders = self.upper_holders(line);
let held = self.contains(line.val()) || !holders.is_empty();
if self.invalidate_line(line.val(), ctx.stats) {
self.write_back(line, true, WritebackCause::Demanded, ctx);
}
if held {
ctx.stats.counter(self.stat_paths.back_invalidations).inc();
}
self.back_invalidate(line, &holders, ctx);
}
pub(super) fn upstream_bit(&self, source: ComponentId) -> u8 {
self.upstream.iter().position(|&up| up == source).map_or(0, |i| 1 << i)
}
pub(super) fn note_upper_copy(&mut self, index: usize, source: ComponentId) {
self.lines[index].upper |= self.upstream_bit(source);
}
pub(super) fn forget_upper_copy(&mut self, addr: u64, source: ComponentId) {
if let Some(way) = self.find_way(addr) {
let index = self.set_index(addr) * self.ways + way;
self.lines[index].upper &= !self.upstream_bit(source);
}
}
pub(super) fn upper_holders(&self, line: LineAddr) -> Vec<ComponentId> {
if !self.enabled {
return self.upstream.clone();
}
match self.find_way(line.val()) {
Some(way) => {
let bits = self.lines[self.set_index(line.val()) * self.ways + way].upper;
self.upstream
.iter()
.enumerate()
.filter(|(i, _)| bits & (1 << i) != 0)
.map(|(_, &up)| up)
.collect()
}
None if self.upstream_inclusion == InclusionPolicy::Inclusive => Vec::new(),
None => self.upstream.clone(),
}
}
}