From d04190f91559938007c6f8a9c6acfdc50a967d31 Mon Sep 17 00:00:00 2001
From: David Li 
Date: Fri, 15 Jan 2016 17:20:32 -0700
Subject: Stall on setting trap
---
 src/globals.rs         |  3 ++-
 src/shareable_cache.rs | 39 ++++++++++++++++++++++++++++++++++++---
 2 files changed, 38 insertions(+), 4 deletions(-)
(limited to 'src')
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) => {
-- 
cgit v1.2.3