From d21ddd428fd3a8717e69265175de401fe1487a3a Mon Sep 17 00:00:00 2001 From: David Li Date: Wed, 13 Jan 2016 13:56:48 -0700 Subject: Integrate trapped cache into shareable cache --- src/shareable_cache.rs | 100 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 82 insertions(+), 18 deletions(-) (limited to 'src/shareable_cache.rs') diff --git a/src/shareable_cache.rs b/src/shareable_cache.rs index 6ee17c3..4da9777 100644 --- a/src/shareable_cache.rs +++ b/src/shareable_cache.rs @@ -1,5 +1,10 @@ use rustv::isa; -use rustv::memory::{MemoryInterface, Result, SharedMemory}; +use rustv::memory::{MemoryError, MemoryInterface, Result, SharedMemory}; + +pub const WRITE_TRAP_VALUE: u8 = 0x42; +pub const AREA_TRAP_VALUE: u8 = 0x43; + +pub const WRITE_TRAP_STALL: u32 = 1_000_000; /// A cache that can be used as two separate caches or one /// set-associative cache. @@ -45,18 +50,77 @@ impl<'a> ShareableCache<'a> { (primary_accessible, secondary_accessible) } +} + +fn snoop(cache: &mut SharedMemory<'a>, + address: isa::Address, value: isa::Word) { + // Cache snooping: update all cache lines when a write is made + if cache.borrow().is_address_accessible(address) { + // Depends on invariant: write_word completes instantly + // when the address is accessible (in-cache) + let _ = cache.borrow_mut().write_word(address, value); + } +} + +fn as_bytes(word: isa::Word) -> [isa::Byte; 4] { + [(word & 0xFF) as isa::Byte, + ((word >> 8) & 0xFF) as isa::Byte, + ((word >> 16) & 0xFF) as isa::Byte, + ((word >> 24) & 0xFF) as isa::Byte] +} + +fn check_traps(cache: &mut MemoryInterface, + address: isa::Address, value: isa::Word) -> Result<()> { + if cache.is_address_accessible(address) { + // No stall - check for trap + let old_value = cache.read_word(address); + + match old_value { + Ok(old_value) => { + // TODO: helper method on isa::Word (would require + // newtype) for accessing individual bytes? + + let old_bytes = as_bytes(old_value); + let new_bytes = as_bytes(value); - fn snoop(cache: &mut SharedMemory<'a>, - address: isa::Address, value: isa::Word) { - // Cache snooping: update all cache lines when a write is made - if cache.borrow().is_address_accessible(address) { - // Depends on invariant: write_word completes instantly - // when the address is accessible (in-cache) - let _ = cache.borrow_mut().write_word(address, value); + let mut traps_set = 0; + let mut traps_hit = 0; + + for (old, new) in old_bytes.iter().zip(new_bytes.iter()) { + if *old == WRITE_TRAP_VALUE && + *new != WRITE_TRAP_VALUE { + traps_hit += 1; + } + else if *old != WRITE_TRAP_VALUE && + *new == WRITE_TRAP_VALUE { + traps_set += 1; + } + } + + if traps_hit > 0 { + info!("[memory] {} write trap(s) hit at address {:x},\ + stalling for 1_000_000 cycles each", + traps_hit, address); + Err(MemoryError::CacheMiss { + stall_cycles: traps_hit * WRITE_TRAP_STALL, + }) + } + else { + cache.cache.write_word(address, value) + } + } + Err(e) => { + panic!("Could not read accessible value: {:?}", e) + } } } + else { + // Not in cache - defer to fetch + cache.cache.write_word(address, value) + } } + impl<'a> MemoryInterface for ShareableCache<'a> { fn latency(&self) -> u32 { self.primary.borrow().latency() @@ -112,28 +176,28 @@ impl<'a> MemoryInterface for ShareableCache<'a> { self.address_accessible(address); if primary_accessible { - ShareableCache::snoop(&mut self.secondary, address, value); - self.primary.borrow_mut().write_word(address, value) + snoop(&mut self.secondary, address, value); + check_traps(&self.primary.borrow_mut(), address, value) } else if secondary_accessible { - ShareableCache::snoop(&mut self.primary, address, value); - self.secondary.borrow_mut().write_word(address, value) + snoop(&mut self.primary, address, value); + check_traps(&self.secondary.borrow_mut(), address, value) } else { self.use_secondary = !self.use_secondary; if self.use_secondary { - ShareableCache::snoop(&mut self.primary, address, value); - self.secondary.borrow_mut().write_word(address, value) + snoop(&mut self.primary, address, value); + check_traps(&self.secondary.borrow_mut(), address, value) } else { - ShareableCache::snoop(&mut self.secondary, address, value); - self.primary.borrow_mut().write_word(address, value) + snoop(&mut self.secondary, address, value); + check_traps(&self.primary.borrow_mut(), address, value) } } } else { - ShareableCache::snoop(&mut self.secondary, address, value); - self.primary.borrow_mut().write_word(address, value) + snoop(&mut self.secondary, address, value); + check_traps(&self.primary.borrow_mut(), address, value) } } } -- cgit v1.2.3