aboutsummaryrefslogtreecommitdiff
path: root/src/shareable_cache.rs
diff options
context:
space:
mode:
authorDavid Li <li.davidm96@gmail.com>2016-01-08 10:04:27 -0700
committerDavid Li <li.davidm96@gmail.com>2016-01-08 10:04:27 -0700
commitad805c698cd1c4d68d090f842fb14621c32ee8d6 (patch)
treefd357647c13c461370d34a067b84cc7aac94c7d3 /src/shareable_cache.rs
parent940a5ae77a1efc8f89fe5b56fe4a4ae34a0e480d (diff)
Refactor into multiple files
Diffstat (limited to 'src/shareable_cache.rs')
-rw-r--r--src/shareable_cache.rs104
1 files changed, 104 insertions, 0 deletions
diff --git a/src/shareable_cache.rs b/src/shareable_cache.rs
new file mode 100644
index 0000000..b6c6654
--- /dev/null
+++ b/src/shareable_cache.rs
@@ -0,0 +1,104 @@
+use rustv::isa;
+use rustv::memory::{MemoryInterface, Result, SharedMemory};
+
+/// A cache that can be used as two separate caches or one
+/// set-associative cache.
+struct ShareableCache<'a> {
+ // The idea is to create two separate ShareableCaches, one for
+ // each player.
+ primary: SharedMemory<'a>,
+ secondary: SharedMemory<'a>,
+ secondary_enabled: bool,
+ use_secondary: bool,
+}
+
+impl<'a> ShareableCache<'a> {
+ pub fn new(cache1: SharedMemory<'a>, cache2: SharedMemory<'a>)
+ -> (ShareableCache<'a>, ShareableCache<'a>) {
+ (ShareableCache {
+ primary: cache1.clone(),
+ secondary: cache2.clone(),
+ secondary_enabled: false,
+ use_secondary: false,
+ }, ShareableCache {
+ primary: cache2.clone(),
+ secondary: cache1.clone(),
+ secondary_enabled: false,
+ use_secondary: false,
+ })
+ }
+
+ pub fn enable_secondary(&mut self) {
+ self.secondary_enabled = true;
+ self.use_secondary = true;
+ }
+
+ pub fn disable_secondary(&mut self) {
+ self.secondary_enabled = false;
+ }
+}
+
+impl<'a> MemoryInterface for ShareableCache<'a> {
+ fn latency(&self) -> u32 {
+ self.primary.borrow().latency()
+ }
+
+ fn step(&mut self) {
+ // We only step the primary cache. The idea is that the
+ // secondary cache should be the primary cache of another
+ // ShareableCache.
+ self.primary.borrow_mut().step();
+ }
+
+ fn is_address_accessible(&self, address: isa::Address) -> bool {
+ self.primary.borrow().is_address_accessible(address) ||
+ (self.secondary_enabled &&
+ self.secondary.borrow().is_address_accessible(address))
+ }
+
+ fn read_word(&mut self, address: isa::Address) -> Result<isa::Word> {
+ if self.secondary_enabled {
+ if self.primary.borrow().is_address_accessible(address) {
+ self.primary.borrow_mut().read_word(address)
+ }
+ else if self.secondary.borrow().is_address_accessible(address) {
+ self.secondary.borrow_mut().read_word(address)
+ }
+ else {
+ self.use_secondary = !self.use_secondary;
+ if self.use_secondary {
+ self.secondary.borrow_mut().read_word(address)
+ }
+ else {
+ self.primary.borrow_mut().read_word(address)
+ }
+ }
+ }
+ else {
+ self.primary.borrow_mut().read_word(address)
+ }
+ }
+
+ fn write_word(&mut self, address: isa::Address, value: isa::Word) -> Result<()> {
+ if self.secondary_enabled {
+ if self.primary.borrow().is_address_accessible(address) {
+ self.primary.borrow_mut().write_word(address, value)
+ }
+ else if self.secondary.borrow().is_address_accessible(address) {
+ self.secondary.borrow_mut().write_word(address, value)
+ }
+ else {
+ self.use_secondary = !self.use_secondary;
+ if self.use_secondary {
+ self.secondary.borrow_mut().write_word(address, value)
+ }
+ else {
+ self.primary.borrow_mut().write_word(address, value)
+ }
+ }
+ }
+ else {
+ self.primary.borrow_mut().write_word(address, value)
+ }
+ }
+}