aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Li <li.davidm96@gmail.com>2016-01-15 17:20:32 -0700
committerDavid Li <li.davidm96@gmail.com>2016-01-15 17:20:32 -0700
commitd04190f91559938007c6f8a9c6acfdc50a967d31 (patch)
tree784e81f0dd1a78d9f16bdd139893e0f594538c99
parentdf305142809e543f27f2990c63184381c394e9d3 (diff)
Stall on setting trap
-rw-r--r--src/globals.rs3
-rw-r--r--src/shareable_cache.rs39
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) => {