aboutsummaryrefslogtreecommitdiff
path: root/src/memory.rs
diff options
context:
space:
mode:
authorDavid Li <li.davidm96@gmail.com>2015-12-25 10:57:04 -0700
committerDavid Li <li.davidm96@gmail.com>2015-12-25 10:57:04 -0700
commitf235d8e500e9fd9945d07ed347ccab5214d26eba (patch)
tree24d6d9748edd2a61e38d9089450f8cbe096c751b /src/memory.rs
parent39ce6b062b6d36495098e39dfd813212757ac4f3 (diff)
Add trait for memory interface
Diffstat (limited to 'src/memory.rs')
-rw-r--r--src/memory.rs68
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)
}
+
}