From d916938c7cd8954fa7f6d21815dc11f8aca211f9 Mon Sep 17 00:00:00 2001 From: David Li Date: Fri, 1 Jan 2016 11:01:38 -0700 Subject: Test use of cache in simulation --- src/lib.rs | 5 +++-- src/memory.rs | 16 ++++++++-------- src/simulator.rs | 25 +++++++++++++++++++++++-- 3 files changed, 34 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 4c3db9e..f5bf110 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,7 +30,8 @@ fn it_works() { Ok(b) => { let memory = memory::Memory::new_from_binary(0x2000, b); let memory_ref = Rc::new(RefCell::new(Box::new(memory) as Box)); - let core = simulator::Core::new(memory_ref.clone()); + let cache = Rc::new( RefCell::new( Box::new( memory::DirectMappedCache::new(4, 4, memory_ref.clone())) as Box) ); + let core = simulator::Core::new(cache.clone()); let mut simulator = simulator::Simulator::new(vec![core], memory_ref.clone()); simulator.run(); }, @@ -47,7 +48,7 @@ mod tests { use std::cell::RefCell; let memory = Memory::new(16); - let memory_ref = Rc::new(RefCell::new(memory)); + let memory_ref = Rc::new(RefCell::new(Box::new(memory) as Box)); let dm_cache_word = DirectMappedCache::new(4, 1, memory_ref.clone()); let dm_cache_doubleword = DirectMappedCache::new(4, 2, memory_ref.clone()); diff --git a/src/memory.rs b/src/memory.rs index 5a30e17..8fdf43d 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -52,7 +52,7 @@ pub trait MemoryInterface { // fn write_byte(&self, address: isa::Address) -> Result<()>; } -pub type SharedMemory = Rc>; +pub type SharedMemory<'a> = Rc>>; // TODO: should be a trait pub struct Mmu { @@ -86,11 +86,11 @@ struct CacheBlock { // investigate how LRU is implemented // TODO: use hashtable for a way? // TODO: hashtable-based FA cache? -pub struct DirectMappedCache { +pub struct DirectMappedCache<'a> { num_sets: u32, block_words: u32, cache: Vec, - next_level: SharedMemory, + next_level: SharedMemory<'a>, } impl Memory { @@ -146,9 +146,9 @@ impl MemoryInterface for Memory { } } -impl DirectMappedCache { - pub fn new(sets: u32, block_words: u32, next_level: SharedMemory) - -> DirectMappedCache { +impl<'a> DirectMappedCache<'a> { + pub fn new(sets: u32, block_words: u32, next_level: SharedMemory<'a>) + -> DirectMappedCache<'a> { let set = CacheBlock { valid: false, tag: 0, @@ -190,7 +190,7 @@ impl DirectMappedCache { } } -impl MemoryInterface for DirectMappedCache { +impl<'a> MemoryInterface for DirectMappedCache<'a> { fn latency(&self) -> u32 { 100 } @@ -254,7 +254,7 @@ impl MemoryInterface for DirectMappedCache { prefetch: false, cycles_left: stall, tag: new_tag, - data: vec![0, self.block_words], + data: vec![0; self.block_words as usize], error: None, waiting_on: 0, }); diff --git a/src/simulator.rs b/src/simulator.rs index 2238421..e882c9a 100644 --- a/src/simulator.rs +++ b/src/simulator.rs @@ -27,6 +27,7 @@ struct RegisterFile { pub struct Core<'a> { pc: isa::Address, registers: RegisterFile, + stall: u32, running: bool, // TODO: change to memory::SharedMemory cache: Rc>>, @@ -81,6 +82,7 @@ impl<'a> Core<'a> { Core { pc: 0x1002c, // TODO: hardcoded: fix later registers: RegisterFile::new(), + stall: 0, running: true, cache: cache, } @@ -88,6 +90,12 @@ impl<'a> Core<'a> { fn step(&mut self, inst: isa::Instruction) { let pc = self.pc; + + if self.stall > 0 { + self.stall -= 1; + return; + } + match inst.opcode() { isa::opcodes::JALR => { // TODO: assert funct3 is 0 @@ -273,7 +281,10 @@ impl<'a> Core<'a> { match result { Ok(value) => self.registers.write_word(inst.rd(), value), - Err(MemoryError::CacheMiss {..}) => return, + Err(MemoryError::CacheMiss { stall_cycles }) => { + self.stall = stall_cycles; + return; + }, Err(MemoryError::InvalidAddress) => { self.trap(Trap::IllegalRead { address: pc, @@ -296,7 +307,10 @@ impl<'a> Core<'a> { let result = self.cache.borrow_mut().write_word(address, val); match result { Ok(()) => (), - Err(MemoryError::CacheMiss {..}) => return, + Err(MemoryError::CacheMiss { stall_cycles }) => { + self.stall = stall_cycles; + return; + }, Err(MemoryError::InvalidAddress) => { self.trap(Trap::IllegalWrite { address: pc, @@ -350,12 +364,16 @@ impl<'a> Simulator<'a> { self.cores[0].registers.write_word(isa::Register::X3, 0x108D0); // hardcode SP self.cores[0].registers.write_word(isa::Register::X2, 0x7FFC); + let mut total_cycles = 0; + let mut stall_cycles = 0; loop { let mut ran = false; + total_cycles += 1; for core in self.cores.iter_mut() { if !core.running { continue; } + if core.stall > 0 { stall_cycles += 1; } let inst = self.memory.borrow_mut().read_instruction(core.pc); if let Some(inst) = inst { core.step(inst); @@ -363,10 +381,13 @@ impl<'a> Simulator<'a> { else { // TODO: trap } + + core.cache.borrow_mut().step(); ran = true; } if !ran { println!("All cores are not running, stopping..."); + println!("Stalled cycles: {} of {}", stall_cycles, total_cycles); break; } } -- cgit v1.2.3