aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/memory.rs37
1 files changed, 27 insertions, 10 deletions
diff --git a/src/memory.rs b/src/memory.rs
index ceec504..a8b15e2 100644
--- a/src/memory.rs
+++ b/src/memory.rs
@@ -28,7 +28,7 @@ pub enum MemoryError {
pub type Result<T> = ::std::result::Result<T, MemoryError>;
pub trait MemoryInterface {
- const LATENCY: u32;
+ fn latency() -> u32;
fn read_word(&self, address: isa::Address) -> Result<isa::Word>;
fn write_word(&mut self, address: isa::Address, value: isa::Word) -> Result<()>;
@@ -50,6 +50,8 @@ pub struct Memory {
#[derive(Clone)]
struct FetchRequest {
+ address: isa::Address,
+ prefetch: bool,
cycles_left: u32,
}
@@ -67,11 +69,12 @@ type CacheSet = Vec<CacheBlock>;
// investigate how LRU is implemented
// TODO: use hashtable for a way?
// TODO: hashtable-based FA cache?
-pub struct Cache {
+pub struct Cache<T: MemoryInterface> {
num_sets: u32,
num_ways: u32,
block_words: u32,
cache: Vec<CacheSet>,
+ next_level: T,
}
impl Memory {
@@ -95,7 +98,9 @@ impl Memory {
}
impl MemoryInterface for Memory {
- const LATENCY: u32 = 100;
+ fn latency() -> u32 {
+ 100
+ }
fn read_word(&self, address: isa::Address) -> Result<isa::Word> {
// memory is word-addressed but addresses are byte-addressed
@@ -117,8 +122,8 @@ impl MemoryInterface for Memory {
}
}
-impl Cache {
- pub fn new(sets: u32, ways: u32, block_words: u32) -> Cache {
+impl<T: MemoryInterface> Cache<T> {
+ pub fn new(sets: u32, ways: u32, block_words: u32, next_level: T) -> Cache<T> {
let set = vec![CacheBlock {
valid: false,
tag: 0,
@@ -130,6 +135,7 @@ impl Cache {
num_ways: ways,
block_words: block_words,
cache: vec![set; sets as usize],
+ next_level: next_level,
}
}
@@ -155,16 +161,27 @@ impl Cache {
}
}
-impl MemoryInterface for Cache {
- const LATENCY: u32 = 1;
+impl<T: MemoryInterface> MemoryInterface for Cache<T> {
+ fn latency() -> u32 {
+ 100
+ }
fn read_word(&self, address: isa::Address) -> Result<isa::Word> {
- Err(MemoryError::InvalidAddress)
+ let (tag, index, offset) = self.parse_address(address);
+ let ref set = self.cache[index as usize];
+ for way in set {
+ if way.tag == tag {
+ return Ok(way.contents[(offset / 4) as usize]);
+ }
+ }
+ Err(MemoryError::CacheMiss {
+ stall_cycles: Cache::<T>::latency() + T::latency()
+ })
}
fn write_word(&mut self, address: isa::Address, value: isa::Word)
-> Result<()> {
- Err(MemoryError::InvalidAddress)
+ // XXX: temporary
+ self.next_level.write_word(address, value)
}
-
}