pub mod bpred;
pub mod ctx;
pub mod mdp;
pub mod mmu;
pub mod pipeline;
pub mod prefetch;
pub mod vector;
use crate::common::CoreId;
use crate::config::{Config, InclusionPolicy, LoadPrefetcherConfig, StorePrefetcherConfig};
use crate::sim::components::{CacheId, ComponentId};
use crate::sim::packet::CacheLevel;
use crate::sim::stats::paths::CorePaths;
use crate::soc::cache::Cache;
use crate::soc::cache::prefetch::StoreStreamPrefetcher;
use crate::uarch::bpred::BranchPredictor;
use crate::uarch::mmu::Mmu;
use crate::uarch::mmu::tlb::TlbGeometry;
use crate::uarch::pipeline::engine::PipelineDispatch;
use crate::uarch::pipeline::lsq::write_buffer::WriteCombiningBuffer;
use crate::uarch::prefetch::LoadPrefetcher;
#[derive(Debug)]
pub struct Core {
pub units: CoreUnits,
pub pipeline: PipelineDispatch,
}
#[derive(Debug)]
pub struct CoreUnits {
pub core_id: CoreId,
pub l1_i_cache: Cache,
pub l1_d_cache: Cache,
pub l2_cache: Cache,
pub mmu: Mmu,
pub wcb: WriteCombiningBuffer,
pub load_prefetcher: Option<LoadPrefetcher>,
pub branch_predictor: BranchPredictor,
pub stat_paths: CorePaths,
}
impl CoreUnits {
pub fn new(core_id: CoreId, config: &Config, cache_id_base: u32, l3_id: CacheId) -> Self {
let l1i_id = CacheId::new(cache_id_base);
let l1d_id = CacheId::new(cache_id_base + 1);
let l2_id = CacheId::new(cache_id_base + 2);
let subject = format!("core{}.cache", core_id.val());
let inclusion = config.cache.inclusion_policy;
let mut l1_i_cache =
Cache::new(l1i_id, CacheLevel::L1I, &config.cache.l1_i, &format!("{subject}.l1i"));
l1_i_cache.set_downstream(ComponentId::Cache(l2_id));
l1_i_cache.set_clean_victims_to_downstream(inclusion == InclusionPolicy::Exclusive);
let mut l1_d_cache =
Cache::new(l1d_id, CacheLevel::L1D, &config.cache.l1_d, &format!("{subject}.l1d"));
l1_d_cache.set_downstream(ComponentId::Cache(l2_id));
l1_d_cache.set_clean_victims_to_downstream(inclusion == InclusionPolicy::Exclusive);
if let StorePrefetcherConfig::Stream { streams, l2_lines } = config.cache.store_prefetcher {
let line_bytes = config.cache.l1_d.line_bytes;
l1_d_cache
.set_store_prefetcher(StoreStreamPrefetcher::new(line_bytes, streams, l2_lines));
}
let mut l2_cache =
Cache::new(l2_id, CacheLevel::L2, &config.cache.l2, &format!("{subject}.l2"));
l2_cache.set_downstream(ComponentId::Cache(l3_id));
l2_cache.add_upstream(ComponentId::Cache(l1i_id));
l2_cache.add_upstream(ComponentId::Cache(l1d_id));
l2_cache.set_upstream_inclusion(inclusion);
Self {
core_id,
l1_i_cache,
l1_d_cache,
l2_cache,
mmu: Mmu::new(
TlbGeometry { entries: config.memory.tlb_size, ways: config.memory.tlb_ways },
TlbGeometry { entries: config.memory.l2_tlb_size, ways: config.memory.l2_tlb_ways },
config.memory.l2_tlb_latency,
config.memory.paging_mode_max,
),
wcb: WriteCombiningBuffer::new(config.cache.wcb_entries, config.cache.l1_d.line_bytes),
load_prefetcher: load_prefetcher(config),
branch_predictor: BranchPredictor::new(config),
stat_paths: CorePaths::new(core_id),
}
}
}
fn load_prefetcher(config: &Config) -> Option<LoadPrefetcher> {
match config.cache.load_prefetcher {
LoadPrefetcherConfig::None => None,
LoadPrefetcherConfig::Stride { table_size, l1_lines, l2_lines, page_boundary } => {
Some(LoadPrefetcher::new(
config.cache.l1_d.line_bytes,
table_size,
l1_lines,
l2_lines,
page_boundary,
))
}
}
}