diff options
Diffstat (limited to 'src/memory.rs')
-rw-r--r-- | src/memory.rs | 68 |
1 files changed, 50 insertions, 18 deletions
diff --git a/src/memory.rs b/src/memory.rs index ffe37c4..51d8199 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -1,6 +1,31 @@ use isa::{self, Instruction}; use binary::{Binary}; +#[derive(Debug)] +pub enum MemoryError { + InvalidAddress, + CacheMiss, +} + +pub type Result<T> = ::std::result::Result<T, MemoryError>; + +pub trait MemoryInterface { + const LATENCY: u32; + + fn read_word(&self, address: isa::Address) -> Result<isa::Word>; + fn write_word(&mut self, address: isa::Address, value: isa::Word) -> Result<()>; + + // fn read_halfword(&self, address: isa::Address) -> Result<isa::HalfWord>; + // fn write_halfword(&self, address: isa::Address) -> Result<()>; + + // fn read_byte(&self, address: isa::Address) -> Result<isa::Byte>; + // fn write_byte(&self, address: isa::Address) -> Result<()>; +} + +pub struct Mmu<T: MemoryInterface> { + memory: T, +} + pub struct Memory { memory: Vec<u32>, } @@ -23,8 +48,6 @@ pub struct Cache { cache: Vec<Vec<CacheBlock>>, } -// TODO: refactor impls into a MemoryController(?) trait - impl Memory { pub fn new(size: isa::Address, binary: Binary) -> Memory { let mut memory = binary.words.clone(); @@ -37,25 +60,29 @@ impl Memory { } } - pub fn read_word(&self, address: isa::Address) -> Option<isa::Word> { + pub fn read_instruction(&self, pc: isa::Address) -> Option<Instruction> { + self.memory.get(pc / 4).map(Clone::clone).map(Instruction::new) + } +} + +impl MemoryInterface for Memory { + const LATENCY: u32 = 100; + + fn read_word(&self, address: isa::Address) -> Result<isa::Word> { // memory is word-addressed but addresses are byte-addressed - self.memory.get(address / 4).map(Clone::clone) + self.memory.get(address / 4).map(Clone::clone).ok_or(MemoryError::InvalidAddress) } - pub fn write_word(&mut self, address: isa::Address, value: isa::Word) -> Option<()> { + fn write_word(&mut self, address: isa::Address, value: isa::Word) -> Result<()> { let address = address / 4; - if address >= self.memory.len() { - None + if address >= self.memory.len() || address <= 0 { + Err(MemoryError::InvalidAddress) } else { self.memory[address] = value; - Some(()) + Ok(()) } } - - pub fn read_instruction(&self, pc: isa::Address) -> Option<Instruction> { - self.memory.get(pc / 4).map(Clone::clone).map(Instruction::new) - } } impl Cache { @@ -72,15 +99,20 @@ impl Cache { } } - fn read_word(&self, address: isa::Address) -> Option<isa::Word> { - None + fn invalidate(&mut self, address: isa::Address) { + } +} - fn write_word(&mut self, address: isa::Address, value: isa::Word) -> Option<()> { - None +impl MemoryInterface for Cache { + const LATENCY: u32 = 1; + + fn read_word(&self, address: isa::Address) -> Result<isa::Word> { + Err(MemoryError::InvalidAddress) } - fn invalidate(&mut self, address: isa::Address) { - + fn write_word(&mut self, address: isa::Address, value: isa::Word) -> Result<()> { + Err(MemoryError::InvalidAddress) } + } |