use std::cell::RefCell; use std::rc::Rc; use rustv::isa; use rustv::memory::{MemoryInterface, Result, SharedMemory}; /// A cache that can be used as two separate caches or one /// set-associative cache. #[derive(Clone)] pub struct ShareableCache<'a> { // The idea is to create two separate ShareableCaches, one for // each player. primary: SharedMemory<'a>, secondary: SharedMemory<'a>, secondary_enabled: bool, use_secondary: bool, } impl<'a> ShareableCache<'a> { pub fn new(cache1: SharedMemory<'a>, cache2: SharedMemory<'a>) -> (Rc>>, Rc>>) { (Rc::new(RefCell::new(ShareableCache { primary: cache1.clone(), secondary: cache2.clone(), secondary_enabled: false, use_secondary: false, })), Rc::new(RefCell::new(ShareableCache { primary: cache2.clone(), secondary: cache1.clone(), secondary_enabled: false, use_secondary: false, }))) } pub fn enable_secondary(&mut self) { self.secondary_enabled = true; self.use_secondary = true; } pub fn disable_secondary(&mut self) { self.secondary_enabled = false; } } impl<'a> MemoryInterface for ShareableCache<'a> { fn latency(&self) -> u32 { self.primary.borrow().latency() } fn step(&mut self) { // We only step the primary cache. The idea is that the // secondary cache should be the primary cache of another // ShareableCache. self.primary.borrow_mut().step(); } fn is_address_accessible(&self, address: isa::Address) -> bool { self.primary.borrow().is_address_accessible(address) || (self.secondary_enabled && self.secondary.borrow().is_address_accessible(address)) } fn read_word(&mut self, address: isa::Address) -> Result { if self.secondary_enabled { if self.primary.borrow().is_address_accessible(address) { self.primary.borrow_mut().read_word(address) } else if self.secondary.borrow().is_address_accessible(address) { self.secondary.borrow_mut().read_word(address) } else { self.use_secondary = !self.use_secondary; if self.use_secondary { self.secondary.borrow_mut().read_word(address) } else { self.primary.borrow_mut().read_word(address) } } } else { self.primary.borrow_mut().read_word(address) } } fn write_word(&mut self, address: isa::Address, value: isa::Word) -> Result<()> { if self.secondary_enabled { if self.primary.borrow().is_address_accessible(address) { self.primary.borrow_mut().write_word(address, value) } else if self.secondary.borrow().is_address_accessible(address) { self.secondary.borrow_mut().write_word(address, value) } else { self.use_secondary = !self.use_secondary; if self.use_secondary { self.secondary.borrow_mut().write_word(address, value) } else { self.primary.borrow_mut().write_word(address, value) } } } else { self.primary.borrow_mut().write_word(address, value) } } }