From f0f6c4a511d08b0cc953631ae958d360c4d16b2c Mon Sep 17 00:00:00 2001 From: David Li Date: Thu, 31 Dec 2015 10:52:44 -0700 Subject: Sketch impl of cache step --- src/memory.rs | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/src/memory.rs b/src/memory.rs index 2170556..8a8ac1e 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -20,7 +20,7 @@ use std::cell::RefCell; use isa::{self, Instruction}; use binary::{Binary}; -#[derive(Debug)] +#[derive(Clone, Debug)] pub enum MemoryError { InvalidAddress, CacheMiss { @@ -33,6 +33,8 @@ pub type Result = ::std::result::Result; pub trait MemoryInterface { fn latency(&self) -> u32; + fn step(&mut self); + fn read_word(&mut self, address: isa::Address) -> Result; fn write_word(&mut self, address: isa::Address, value: isa::Word) -> Result<()>; @@ -50,6 +52,7 @@ pub trait MemoryInterface { // fn write_byte(&self, address: isa::Address) -> Result<()>; } +// TODO: should be a trait pub struct Mmu { memory: T, } @@ -58,11 +61,20 @@ pub struct Memory { memory: Vec, } +#[derive(Clone)] +enum FetchStage { + CurrentLevel, + NextLevel, +} + #[derive(Clone)] struct FetchRequest { address: isa::Address, prefetch: bool, cycles_left: u32, + stage: FetchStage, + data: Vec, // hold data temporarily while we wait for an entire line + error: Option, // in case next level returns an error } #[derive(Clone)] @@ -109,6 +121,8 @@ impl MemoryInterface for Memory { 100 } + fn step(&mut self) {} + fn read_word(&mut self, address: isa::Address) -> Result { // memory is word-addressed but addresses are byte-addressed self.memory.get((address / 4) as usize) @@ -184,9 +198,47 @@ impl MemoryInterface for DirectMappedCache { 100 } + fn step(&mut self) { + for set in self.cache.iter_mut() { + if let Some(ref mut fetch_request) = set.fetch_request { + if fetch_request.cycles_left > 0 { + fetch_request.cycles_left -= 1; + } + 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 { + 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; + }, + Err(MemoryError::CacheMiss { stall_cycles }) => { + fetch_request.cycles_left = stall_cycles; + return; + }, + Err(MemoryError::InvalidAddress) => { + fetch_request.error = + Some(MemoryError::InvalidAddress); + return; + } + } + } + // TODO: need to move request to next level once + // done (i.e. write to cache and remove fetch + // request) + } + } + } + } + fn read_word(&mut self, address: isa::Address) -> Result { let normalized = self.normalize_address(address); - let stall = self.latency() + self.next_level.borrow().latency(); + 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 { @@ -197,9 +249,15 @@ impl MemoryInterface for DirectMappedCache { address: normalized, prefetch: false, cycles_left: stall, + stage: FetchStage::CurrentLevel, + data: vec![0, self.block_words], + error: None, }) } else if let Some(ref fetch_request) = set.fetch_request { + if let Some(ref err) = fetch_request.error { + return Err(err.clone()); + } return Err(MemoryError::CacheMiss { stall_cycles: fetch_request.cycles_left }); -- cgit v1.2.3