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 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 76 insertions(+), 11 deletions(-) (limited to 'src/globals.rs') 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); + } +} -- cgit v1.2.3