diff options
-rw-r--r-- | src/lib.rs | 5 | ||||
-rw-r--r-- | src/memory.rs | 16 | ||||
-rw-r--r-- | src/simulator.rs | 25 |
3 files changed, 34 insertions, 12 deletions
@@ -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<memory::MemoryInterface>)); - 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<memory::MemoryInterface>) ); + 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<MemoryInterface>)); 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<RefCell<MemoryInterface>>; +pub type SharedMemory<'a> = Rc<RefCell<Box<MemoryInterface + 'a>>>; // TODO: should be a trait pub struct Mmu<T: MemoryInterface> { @@ -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<CacheBlock>, - 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<RefCell<Box<MemoryInterface + 'a>>>, @@ -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; } } |