aboutsummaryrefslogtreecommitdiff
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
parent39ce6b062b6d36495098e39dfd813212757ac4f3 (diff)
Add trait for memory interface
-rw-r--r--src/isa/mod.rs4
-rw-r--r--src/lib.rs1
-rw-r--r--src/memory.rs68
-rw-r--r--src/simulator.rs48
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;
diff --git a/src/lib.rs b/src/lib.rs
index fd60531..7701aa3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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));
}
_ => {
-
+
}
},
_ => {