diff options
author | David Li <li.davidm96@gmail.com> | 2015-12-25 10:57:04 -0700 |
---|---|---|
committer | David Li <li.davidm96@gmail.com> | 2015-12-25 10:57:04 -0700 |
commit | f235d8e500e9fd9945d07ed347ccab5214d26eba (patch) | |
tree | 24d6d9748edd2a61e38d9089450f8cbe096c751b /src | |
parent | 39ce6b062b6d36495098e39dfd813212757ac4f3 (diff) |
Add trait for memory interface
Diffstat (limited to 'src')
-rw-r--r-- | src/isa/mod.rs | 4 | ||||
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/memory.rs | 68 | ||||
-rw-r--r-- | src/simulator.rs | 48 |
4 files changed, 85 insertions, 36 deletions
diff --git a/src/isa/mod.rs b/src/isa/mod.rs index 49fad10..5458255 100644 --- a/src/isa/mod.rs +++ b/src/isa/mod.rs @@ -4,6 +4,10 @@ pub mod funct7; pub type Word = u32; pub type SignedWord = i32; +pub type HalfWord = u16; +pub type SignedHalfWord = i16; +pub type Byte = u8; +pub type SignedByte = i8; // TODO: directly encode PC as u32, as architecturally specified pub type Address = usize; @@ -1,3 +1,4 @@ +#![feature(associated_consts)] pub mod isa; pub mod binary; pub mod memory; 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) } + } diff --git a/src/simulator.rs b/src/simulator.rs index bc4443c..5eb68e2 100644 --- a/src/simulator.rs +++ b/src/simulator.rs @@ -1,6 +1,6 @@ use isa; use binary::{Binary}; -use memory::{Memory}; +use memory::{MemoryInterface, Memory, MemoryError}; pub struct Simulator { num_cores: usize, @@ -272,21 +272,22 @@ impl Simulator { } }, isa::opcodes::LOAD => match inst.funct3() { - isa::funct3::LW => { - let imm = inst.i_imm(); - let base = core.registers.read_word(inst.rs1()); - let address = ((base as isa::SignedWord) + imm) as isa::Address; - if let Some(value) = self.memory.read_word(address) { - core.registers.write_word(inst.rd(), value); - } - else { - self.trap(core, Trap::IllegalRead { - address: pc, - instruction: inst, - memory_address: address, - }); - } - } + isa::funct3::LW => { + let imm = inst.i_imm(); + let base = core.registers.read_word(inst.rs1()); + let address = ((base as isa::SignedWord) + imm) as isa::Address; + match self.memory.read_word(address) { + Ok(value) => core.registers.write_word(inst.rd(), value), + Err(MemoryError::CacheMiss) => return, + Err(MemoryError::InvalidAddress) => { + self.trap(core, Trap::IllegalRead { + address: pc, + instruction: inst, + memory_address: address, + }); + } + } + }, _ => { panic!("Invalid load funct3code: 0x{:x}", inst.funct3()); } @@ -297,7 +298,18 @@ impl Simulator { let base = core.registers.read_word(inst.rs1()); let val = core.registers.read_word(inst.rs2()); let address = ((base as isa::SignedWord) + imm) as isa::Address; - self.memory.write_word(address, val); + match self.memory.write_word(address, val) { + Ok(()) => (), + Err(MemoryError::CacheMiss) => return, + Err(MemoryError::InvalidAddress) => { + self.trap(core, Trap::IllegalWrite { + address: pc, + instruction: inst, + memory_address: address, + memory_value: val, + }) + } + } } _ => { panic!("Invalid store funct3code: 0x{:x}", inst.funct3()); @@ -311,7 +323,7 @@ impl Simulator { println!("Argument {:X}: {:?}", address, self.memory.read_word(address)); } _ => { - + } }, _ => { |