From efaf4844e51bd47f9385cedfc3f1392f04af2f42 Mon Sep 17 00:00:00 2001
From: David Li
Date: Mon, 25 Jan 2016 14:46:40 -0500
Subject: feat(memory): write cache tag info to global status structs
---
src/globals.rs | 87 +++++++++++++++++++++++++++++++++++++++++++-------
src/main.rs | 22 ++++++++++---
src/shareable_cache.rs | 5 +--
3 files changed, 97 insertions(+), 17 deletions(-)
(limited to 'src')
diff --git a/src/globals.rs b/src/globals.rs
index dc96403..3a661e4 100644
--- a/src/globals.rs
+++ b/src/globals.rs
@@ -1,6 +1,8 @@
use std::cell::RefCell;
+use std::fmt;
use std::rc::Rc;
+use rustv::cache;
use rustv::isa::{self, IsaType};
use rustv::memory::{MemoryInterface, Mmu};
@@ -10,18 +12,33 @@ pub const HOME_STATUS: isa::Address = isa::Word(0xFFF00);
/// Update the various global data structures as requested by other
/// subsystems.
-// Intended to be passed around as &'a GlobalsUpdater
-pub struct GlobalsUpdater<'a> {
+// Intended to be passed around as &'a Updater
+pub struct Updater<'a> {
// TODO: weak reference?
memory: Rc>,
mmu1: Box,
mmu2: Box,
}
-impl<'a> GlobalsUpdater<'a> {
+#[derive(Clone,Copy)]
+pub enum Player {
+ One,
+ Two,
+}
+
+impl fmt::Display for Player {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ Player::One => write!(f, "Player 1"),
+ Player::Two => write!(f, "Player 2"),
+ }
+ }
+}
+
+impl<'a> Updater<'a> {
pub fn new(memory: Rc>,
- mmu1: Box, mmu2: Box) -> GlobalsUpdater<'a> {
- GlobalsUpdater {
+ mmu1: Box, mmu2: Box) -> Updater<'a> {
+ Updater {
memory: memory,
mmu1: mmu1,
mmu2: mmu2,
@@ -42,18 +59,66 @@ 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;
+ /// Update the player's status struct with the physical address of
+ /// a tag that has been fetched.
+ pub fn finish_tag(&self, player: Player, tag: u32, index: u32) {
+ debug_assert!(index == 0 || index == 1);
+ let address = HOME_STATUS + isa::Word(index * 4);
+ let address = match player {
+ Player::One => self.mmu1.translate(address),
+ Player::Two => self.mmu2.translate(address),
+ };
+
+ match self.memory.borrow_mut().write_word(address, isa::Word(tag)) {
+ Ok(()) => {},
+ Err(e) => panic!("Could not update memory with cache tag: {:?}", e),
+ }
}
- pub fn finish_tag(&self, tag: isa::Address, index: u32) {
+ /// Update the player's status struct with the physical address of
+ /// a tag that has been requested.
+ pub fn fetch_tag(&self, player: Player, tag: u32, index: u32) {
+ debug_assert!(index == 0 || index == 1);
+ let address = HOME_STATUS + isa::Word(8 + index * 4);
+ let address = match player {
+ Player::One => self.mmu1.translate(address),
+ Player::Two => self.mmu2.translate(address),
+ };
+ match self.memory.borrow_mut().write_word(address, isa::Word(tag)) {
+ Ok(()) => {},
+ Err(e) => panic!("Could not update memory with cache tag: {:?}", e),
+ }
}
pub fn update_score(&self, player1: i64, player2: i64) {
}
}
+
+pub struct CacheEventHandler<'a> {
+ player: Player,
+ updater: &'a Updater<'a>,
+}
+
+impl<'a> CacheEventHandler<'a> {
+ pub fn new(updater: &'a Updater<'a>, player: Player)
+ -> CacheEventHandler<'a> {
+ CacheEventHandler {
+ player: player,
+ updater: updater,
+ }
+ }
+}
+
+impl<'a> cache::EventHandler for CacheEventHandler<'a> {
+ fn block_fetched(&self, location: cache::CacheLocation) {
+ // TODO: need to snoop cache
+ info!("[memory] [cache] {}: tag {:x} fetched", self.player, location.tag);
+ self.updater.finish_tag(self.player, location.tag, location.index);
+ }
+
+ fn block_requested(&self, location: cache::CacheLocation) {
+ self.updater.fetch_tag(self.player, location.tag, location.index);
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index f4ef2cc..c4cb1e1 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -20,10 +20,10 @@ use std::cell::RefCell;
use docopt::Docopt;
+use rustv::cache;
use rustv::elfloader;
use rustv::isa::{self, IsaType};
use rustv::memory;
-use rustv::memory::Mmu;
use rustv::simulator;
use memory_tracker::MemoryTracker;
@@ -98,9 +98,23 @@ fn main() {
// TODO: initialize global data
let memory_ref = Rc::new(RefCell::new(memory));
- let cache = memory::DirectMappedCache::new(2, 64, memory_ref.clone());
+
+ let updater = globals::Updater::new(
+ memory_ref.clone(),
+ Box::new(memory::IdentityMmu::new()),
+ Box::new(memory::IdentityMmu::new()));
+ updater.init_memory();
+
+ let player1_event = globals::CacheEventHandler::new(
+ &updater, globals::Player::One);
+ let player2_event = globals::CacheEventHandler::new(
+ &updater, globals::Player::Two);
+
+ let cache = cache::DirectMappedCache::new(
+ 2, 64, memory_ref.clone(), player1_event);
let cache_ref = Rc::new(RefCell::new(cache));
- let cache2 = memory::DirectMappedCache::new(2, 64, memory_ref.clone());
+ let cache2 = cache::DirectMappedCache::new(
+ 2, 64, memory_ref.clone(), player2_event);
let cache2_ref = Rc::new(RefCell::new(cache2));
let mut cores = vec![];
@@ -155,7 +169,7 @@ fn main() {
let end = time::precise_time_s();
for (core_id, cycles_stalled, total_cycles) in simulator.report().iter().cloned() {
- println!("Core {}: stalled {:08} of {:08} cycles ({:.2}%)",
+ println!("Core {}: stalled {:8} of {:8} cycles ({:.2}%)",
core_id,
cycles_stalled,
total_cycles,
diff --git a/src/shareable_cache.rs b/src/shareable_cache.rs
index 503c7d5..6cc22df 100644
--- a/src/shareable_cache.rs
+++ b/src/shareable_cache.rs
@@ -1,8 +1,8 @@
use std::collections::HashSet;
+use rustv::cache::{CacheInterface, CacheMetadata, SharedCache};
use rustv::isa::{self, IsaType};
-use rustv::memory::{CacheInterface, CacheMetadata, MemoryError, MemoryInterface,
- Result, SharedCache, SharedMemory};
+use rustv::memory::{MemoryError, MemoryInterface, Result};
pub const WRITE_TRAP_VALUE: isa::Byte = isa::Byte(0xE0);
pub const AREA_TRAP_VALUE: isa::Byte = isa::Byte(0xE4);
@@ -24,6 +24,7 @@ pub struct ShareableCache<'a> {
/// Cache snooping: update the secondary cache when the primary cache
/// is written to. This is a macro in order to be generic with regard
/// to the size of the write.
+// TODO: snoop needs to take care of in-flight fetch requests?
macro_rules! snoop {
($cache: expr, $write_value: ident, $address: ident, $value: ident) => {
if $cache.borrow().is_address_accessible($address) {
--
cgit v1.2.3