aboutsummaryrefslogtreecommitdiff
path: root/src/memory.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/memory.rs')
-rw-r--r--src/memory.rs239
1 files changed, 0 insertions, 239 deletions
diff --git a/src/memory.rs b/src/memory.rs
index 958ef21..33a9503 100644
--- a/src/memory.rs
+++ b/src/memory.rs
@@ -123,23 +123,8 @@ pub trait MemoryInterface {
}
}
-pub struct CacheMetadata {
- /// How many sets are in the cache
- pub num_sets: usize,
- /// How many ways are in a set
- pub num_ways: usize,
- /// How many words are in a block/line
- pub num_block_words: usize,
- /// The tags currently in the cache, in order of set, then way
- pub tags: Vec<Option<isa::Address>>,
-}
-
-pub trait CacheInterface : MemoryInterface {
- fn cache_metadata(&self) -> CacheMetadata;
-}
pub type SharedMemory<'a> = Rc<RefCell<MemoryInterface + 'a>>;
-pub type SharedCache<'a> = Rc<RefCell<CacheInterface + 'a>>;
pub trait Mmu {
fn translate(&self, address: isa::Address) -> isa::Address;
@@ -181,36 +166,6 @@ pub struct Memory {
memory: Vec<u32>,
}
-#[derive(Clone)]
-struct FetchRequest {
- address: isa::Address,
- prefetch: bool, // is this a prefetch
- cycles_left: u32,
- tag: u32,
- data: Vec<isa::Word>, // hold data temporarily while we wait for an entire line
- error: Option<MemoryError>, // in case next level returns an error
- waiting_on: u32, // which word of the block are we waiting on
-}
-
-#[derive(Clone)]
-struct CacheBlock {
- valid: bool,
- tag: u32,
- contents: Vec<isa::Word>,
- fetch_request: Option<FetchRequest>,
-}
-
-// TODO: probably want different caches for different strategies, and
-// investigate how LRU is implemented
-// TODO: use hashtable for a way?
-// TODO: hashtable-based FA cache?
-pub struct DirectMappedCache<'a> {
- num_sets: u32,
- block_words: u32,
- cache: Vec<CacheBlock>,
- next_level: SharedMemory<'a>,
-}
-
fn copy_u8_into_u32<T: Mmu>(mmu: &T, base: usize, src: &[u8], dst: &mut [u32]) {
for (offset, word) in src.chunks(4).enumerate() {
let word = if word.len() == 4 {
@@ -289,197 +244,3 @@ impl MemoryInterface for Memory {
.map(Instruction::new)
}
}
-
-impl<'a> DirectMappedCache<'a> {
- pub fn new(sets: u32, block_words: u32, next_level: SharedMemory<'a>)
- -> DirectMappedCache<'a> {
- let set = CacheBlock {
- valid: false,
- tag: 0,
- contents: vec![isa::Word(0); block_words as usize],
- fetch_request: None,
- };
- DirectMappedCache {
- num_sets: sets,
- block_words: block_words,
- cache: vec![set; sets as usize],
- next_level: next_level,
- }
- }
-
- pub fn parse_address(&self, address: isa::Address) -> (u32, u32, u32) {
- // TODO: use constant in ISA module for word->byte conversion
- let offset_mask = (self.block_words * 4 - 1) as u32;
- let offset = address & offset_mask;
- let index_mask = (self.num_sets - 1) as u32;
- let index_shift = 32 - (self.block_words * 4).leading_zeros() - 1;
- let index = (address >> index_shift) & index_mask;
- let tag_shift = index_shift + (32 - self.num_sets.leading_zeros()) - 1;
- let tag = address >> tag_shift;
-
- (tag.0, index.0, offset.0)
- }
-
- fn normalize_address(&self, address: isa::Address) -> isa::Address {
- let offset_mask = !(self.block_words * 4 - 1);
- address & offset_mask
- }
-}
-
-impl<'a> MemoryInterface for DirectMappedCache<'a> {
- fn latency(&self) -> u32 {
- 0
- }
-
- fn step(&mut self) {
- for set in self.cache.iter_mut() {
- if let Some(ref mut fetch_request) = set.fetch_request {
- // Start filling the cache once the cycles_left would
- // have hit 0, so that the consumer never gets
- // stall_cycles = 0
- if fetch_request.cycles_left > 1 {
- fetch_request.cycles_left -= 1;
- return;
- }
- // read all the words in a line from the next
- // level, until we get a stall
-
- for offset in fetch_request.waiting_on..self.block_words {
- let result = self.next_level
- .borrow_mut()
- .read_word(fetch_request.address + (4 * offset));
- match result {
- Ok(data) => {
- fetch_request.data[offset as usize] = data;
- fetch_request.waiting_on += 1;
- },
- Err(MemoryError::CacheMiss { stall_cycles, .. }) => {
- fetch_request.cycles_left = stall_cycles;
- continue;
- },
- Err(MemoryError::InvalidAddress) => {
- fetch_request.error =
- Some(MemoryError::InvalidAddress);
- continue;
- }
- }
- }
-
- // All words fetched, write to cache
- set.tag = fetch_request.tag;
- set.contents = fetch_request.data.clone();
- set.valid = true;
- }
-
- set.fetch_request = None;
- }
- }
-
- fn is_address_accessible(&self, address: isa::Address) -> bool {
- let (tag, index, _) = self.parse_address(address);
- let ref set = self.cache[index as usize];
-
- set.valid && set.tag == tag
- }
-
- fn read_word(&mut self, address: isa::Address) -> Result<isa::Word> {
- let normalized = self.normalize_address(address);
- let (new_tag, _, _) = self.parse_address(address);
- let stall = self.next_level.borrow().latency();
- let (tag, index, offset) = self.parse_address(address);
- let ref mut set = self.cache[index as usize];
-
- if set.valid && set.tag == tag {
- return Ok(set.contents[(offset / 4) as usize]);
- }
- else if let None = set.fetch_request {
- set.fetch_request = Some(FetchRequest {
- address: normalized,
- prefetch: false,
- cycles_left: stall,
- tag: new_tag,
- data: vec![isa::Word(0); self.block_words as usize],
- error: None,
- waiting_on: 0,
- });
- }
- else if let Some(ref mut fetch_request) = set.fetch_request {
- if let Some(ref err) = fetch_request.error {
- if fetch_request.address == normalized {
- return Err(err.clone());
- }
- else {
- fetch_request.address = normalized;
- fetch_request.prefetch = false;
- fetch_request.cycles_left = stall;
- fetch_request.tag = new_tag;
- fetch_request.waiting_on = 0;
- }
- }
- // Do the assignment outside the borrow of the error
- fetch_request.error = None;
-
- return Err(MemoryError::CacheMiss {
- stall_cycles: fetch_request.cycles_left,
- retry: true,
- });
- }
-
- Err(MemoryError::CacheMiss {
- stall_cycles: stall,
- retry: true,
- })
- }
-
- fn write_word(&mut self, address: isa::Address, value: isa::Word)
- -> Result<()> {
- // Write-allocate policy
- match self.read_word(address) {
- Ok(_) => {
- let (tag, index, offset) = self.parse_address(address);
- let ref mut set = self.cache[index as usize];
-
- if set.valid && set.tag == tag {
- set.contents[(offset / 4) as usize] = value;
- // Write-through policy
- let result = self.next_level.borrow_mut()
- .write_word(address, value);
- match result {
- Ok(()) => Ok(()),
- Err(e) => Err(e),
- }
- }
- else {
- panic!("Could not find supposedly read word");
- }
- },
- Err(e) => Err(e),
- }
- }
-}
-
-impl<'a> CacheInterface for DirectMappedCache<'a> {
- fn cache_metadata(&self) -> CacheMetadata {
- let tags = {
- let mut tags = Vec::new();
-
- for set in self.cache.iter() {
- if set.valid {
- tags.push(Some(isa::Word(set.tag)));
- }
- else {
- tags.push(None);
- }
- }
-
- tags
- };
-
- CacheMetadata {
- num_sets: self.num_sets as usize,
- num_ways: 1,
- num_block_words: self.block_words as usize,
- tags: tags,
- }
- }
-}