diff options
author | David Li <li.davidm96@gmail.com> | 2016-01-15 17:20:32 -0700 |
---|---|---|
committer | David Li <li.davidm96@gmail.com> | 2016-01-15 17:20:32 -0700 |
commit | d04190f91559938007c6f8a9c6acfdc50a967d31 (patch) | |
tree | 784e81f0dd1a78d9f16bdd139893e0f594538c99 | |
parent | df305142809e543f27f2990c63184381c394e9d3 (diff) |
Stall on setting trap
-rw-r--r-- | src/globals.rs | 3 | ||||
-rw-r--r-- | src/shareable_cache.rs | 39 |
2 files changed, 38 insertions, 4 deletions
diff --git a/src/globals.rs b/src/globals.rs index 2d2a067..dc96403 100644 --- a/src/globals.rs +++ b/src/globals.rs @@ -2,7 +2,7 @@ use std::cell::RefCell; use std::rc::Rc; use rustv::isa::{self, IsaType}; -use rustv::memory::{Memory, MemoryInterface, Mmu}; +use rustv::memory::{MemoryInterface, Mmu}; use memory_tracker::MemoryTracker; @@ -43,6 +43,7 @@ impl<'a> GlobalsUpdater<'a> { } // TODO: how to distinguish which player? + // TODO: we want virtual addresses? or physical ones? pub fn fetch_tag(&self, tag: isa::Address, index: u32) { // TODO: assert index is 0 or 1 let address = HOME_STATUS; diff --git a/src/shareable_cache.rs b/src/shareable_cache.rs index f6c76f6..e61e907 100644 --- a/src/shareable_cache.rs +++ b/src/shareable_cache.rs @@ -7,6 +7,7 @@ pub const WRITE_TRAP_VALUE: isa::Byte = isa::Byte(0xE0); pub const AREA_TRAP_VALUE: isa::Byte = isa::Byte(0xE4); pub const WRITE_TRAP_STALL: u32 = 1_000_000; +pub const WRITE_TRAP_SET_STALL: u32 = 100; /// A cache that can be used as two separate caches or one /// set-associative cache. @@ -52,13 +53,15 @@ macro_rules! check_traps { let new_bytes = $value.as_bytes(); let mut num_traps_hit = 0; + let mut num_traps_set = 0; let iter = old_bytes.iter() // Skip {offset} bytes .skip(($address.0 & 0x3) as usize) .take(new_bytes.len()) + .zip(new_bytes.iter()) .enumerate(); - for (offset, old) in iter { + for (offset, (old, new)) in iter { // Make sure offset bits are cleared before // adding offset let trap_address = ($address & 0xFFFFFFFC) + @@ -71,19 +74,49 @@ macro_rules! check_traps { else if *old != WRITE_TRAP_VALUE { $traps_hit.remove(&trap_address); } + + if *new == WRITE_TRAP_VALUE && + (*old != WRITE_TRAP_VALUE || + $traps_hit.contains(&trap_address)) { + $traps_hit.remove(&trap_address); + num_traps_set += 1; + } } if num_traps_hit > 0 { - println!("Checking for traps: {:?} vs {:?}", old_bytes, new_bytes); info!("[memory] core {}: {} write trap(s) hit at address {:x},\ stalling for 1_000_000 cycles each", $core_id, num_traps_hit, $address); Err(MemoryError::CacheMiss { stall_cycles: num_traps_hit * WRITE_TRAP_STALL, + retry: true, }) } else { - $cache.borrow_mut().$write_value($address, $value) + // Use retry: false to induce a stall iff the + // write succeeded + let result = + $cache.borrow_mut().$write_value($address, $value); + + if num_traps_set > 0 { + println!("Traps set: {}", num_traps_set); + match result { + Ok(()) => { + info!("[memory] core {}: {} write trap(s) set at address {:x},\ + stalling for 100 cycles each", + $core_id, num_traps_set, $address); + Err(MemoryError::CacheMiss { + stall_cycles: num_traps_set * + WRITE_TRAP_SET_STALL, + retry: false, + }) + }, + _ => result + } + } + else { + result + } } } Err(e) => { |