aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Li <li.davidm96@gmail.com>2016-01-01 11:01:38 -0700
committerDavid Li <li.davidm96@gmail.com>2016-01-01 11:01:38 -0700
commitd916938c7cd8954fa7f6d21815dc11f8aca211f9 (patch)
treef1c4dfae2c86096c7ea3d0e27a9b30493ea5c577 /src
parent0440fb92abc0ac72d03787aa24238deb22abbb7b (diff)
Test use of cache in simulation
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs5
-rw-r--r--src/memory.rs16
-rw-r--r--src/simulator.rs25
3 files changed, 34 insertions, 12 deletions
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<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;
}
}