From 9380538d5de60b7167053a0ffcffdc0ff3882608 Mon Sep 17 00:00:00 2001 From: David Li Date: Thu, 31 Dec 2015 19:16:02 -0700 Subject: Finish DirectMappedCache.step --- src/memory.rs | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) (limited to 'src/memory.rs') diff --git a/src/memory.rs b/src/memory.rs index 8a8ac1e..7dc017c 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -52,6 +52,8 @@ pub trait MemoryInterface { // fn write_byte(&self, address: isa::Address) -> Result<()>; } +pub type SharedMemory = Rc>; + // TODO: should be a trait pub struct Mmu { memory: T, @@ -61,20 +63,15 @@ pub struct Memory { memory: Vec, } -#[derive(Clone)] -enum FetchStage { - CurrentLevel, - NextLevel, -} - #[derive(Clone)] struct FetchRequest { address: isa::Address, - prefetch: bool, + prefetch: bool, // is this a prefetch cycles_left: u32, - stage: FetchStage, + tag: u32, data: Vec, // hold data temporarily while we wait for an entire line error: Option, // in case next level returns an error + waiting_on: u32, // which word of the block are we waiting on } #[derive(Clone)] @@ -93,7 +90,7 @@ pub struct DirectMappedCache { num_sets: u32, block_words: u32, cache: Vec, - next_level: Rc>, + next_level: SharedMemory, } impl Memory { @@ -150,7 +147,7 @@ impl MemoryInterface for Memory { } impl DirectMappedCache { - pub fn new(sets: u32, block_words: u32, next_level: Rc>) + pub fn new(sets: u32, block_words: u32, next_level: SharedMemory) -> DirectMappedCache { let set = CacheBlock { valid: false, @@ -203,45 +200,51 @@ impl MemoryInterface for DirectMappedCache { if let Some(ref mut fetch_request) = set.fetch_request { if fetch_request.cycles_left > 0 { fetch_request.cycles_left -= 1; + continue; } else { // read all the words in a line from the next // level, until we get a stall - // TODO: need to keep track of what words we already got - for offset in 0..self.block_words { + for offset in fetch_request.waiting_on..self.block_words { let result = self.next_level .borrow_mut() .read_word(fetch_request.address + (4 * offset)); match result { Ok(data) => { fetch_request.data[offset as usize] = data; + fetch_request.waiting_on += 1; }, Err(MemoryError::CacheMiss { stall_cycles }) => { fetch_request.cycles_left = stall_cycles; - return; + continue; }, Err(MemoryError::InvalidAddress) => { fetch_request.error = Some(MemoryError::InvalidAddress); - return; + continue; } } } - // TODO: need to move request to next level once - // done (i.e. write to cache and remove fetch - // request) + + // All words fetched, write to cache + set.tag = fetch_request.tag; + set.contents = fetch_request.data.clone(); + set.valid = true; } } + + set.fetch_request = None; } } fn read_word(&mut self, address: isa::Address) -> Result { let normalized = self.normalize_address(address); + let (new_tag, _, _) = self.parse_address(address); let stall = self.latency(); let (tag, index, offset) = self.parse_address(address); let ref mut set = self.cache[index as usize]; - if set.tag == tag { + if set.valid && set.tag == tag { return Ok(set.contents[(offset / 4) as usize]); } else if let None = set.fetch_request { @@ -249,13 +252,17 @@ impl MemoryInterface for DirectMappedCache { address: normalized, prefetch: false, cycles_left: stall, - stage: FetchStage::CurrentLevel, + tag: new_tag, data: vec![0, self.block_words], error: None, + waiting_on: 0, }) } else if let Some(ref fetch_request) = set.fetch_request { if let Some(ref err) = fetch_request.error { + // TODO: check to make sure the fetch request is for + // this address, else just clear the request + // TODO: clear the fetch request return Err(err.clone()); } return Err(MemoryError::CacheMiss { -- cgit v1.2.3