extern crate docopt; #[macro_use] extern crate log; extern crate env_logger; extern crate rustc_serialize; extern crate rustv; extern crate time; mod memory_tracker; mod shareable_cache; mod system; use std::fs::File; use std::io::Read; use std::rc::Rc; use std::cell::RefCell; use docopt::Docopt; use rustv::elfloader; use rustv::isa; use rustv::memory; use rustv::memory::Mmu; use rustv::simulator; use memory_tracker::MemoryTracker; use shareable_cache::ShareableCache; use system::SyscallHandler; const USAGE: &'static str = " cacheracer - A F/OSS implementation of the CS 3410 CacheRacer Usage: cacheracer Options: -h --help Show this screen. --version Show version. "; #[derive(Debug, RustcDecodable)] struct Args { arg_program1: String, arg_program2: String, } fn load_program(memory: &mut memory::Memory, mmu: &T, path: &str) -> isa::Address { let mut f = File::open(path).unwrap(); let mut buffer = Vec::new(); f.read_to_end(&mut buffer).unwrap(); let elf = elfloader::ElfBinary::new("test", &buffer).unwrap(); let start = elf.file_header().entry as isa::Address; for p in elf.section_headers() { let name = elf.section_name(p); if name == ".text" || name == ".sdata" || name == ".rodata" { memory.write_segment(mmu, elf.section_data(p), p.addr as usize); } } start } fn main() { env_logger::init().unwrap(); let args: Args = Docopt::new(USAGE) .and_then(|d| d.decode()) .unwrap_or_else(|e| e.exit()); let mmu = memory::IdentityMmu::new(); // TODO: account for word-vs-byte addressed. Use newtype pattern? let mmu2 = memory::ReverseMmu::new(0x4000000); let mut memory = memory::Memory::new(0x1000000); let start1 = load_program(&mut memory, &mmu, &args.arg_program1); let start2 = load_program(&mut memory, &mmu2, &args.arg_program2); let memory = MemoryTracker::new(memory, 0x43, 0x42); let memory_ref = Rc::new(RefCell::new(memory)); let cache = memory::DirectMappedCache::new(2, 64, memory_ref.clone()); let cache_ref = Rc::new(RefCell::new(cache)); let cache2 = memory::DirectMappedCache::new(2, 64, memory_ref.clone()); let cache2_ref = Rc::new(RefCell::new(cache2)); let mut cores = vec![]; let mut core_caches = vec![]; for i in 0..4 { let core_cache = Rc::new(RefCell::new( ShareableCache::new(i, cache_ref.clone(), cache2_ref.clone()))); core_caches.push(core_cache.clone()); let mut core = simulator::Core::new( i, start1, (0x100000 * (i + 1)) as u32, core_cache, Box::new(memory::IdentityMmu::new()) ); core.registers().write_word(isa::Register::X10, i as isa::Word); cores.push(core); } for i in 4..8 { let core_cache = Rc::new(RefCell::new( ShareableCache::new(i, cache2_ref.clone(), cache_ref.clone()))); core_caches.push(core_cache.clone()); let mut core = simulator::Core::new( i, start2, (0x100000 * (i + 1)) as u32, core_cache, Box::new(memory::ReverseMmu::new(0x4000000)) ); core.registers().write_word(isa::Register::X10, i as isa::Word); cores.push(core); } let steppable_caches = vec![cache_ref.clone() as memory::SharedMemory, cache2_ref]; let system = SyscallHandler::new(memory_ref.clone(), core_caches); let mut simulator = simulator::Simulator::new( cores, memory_ref.clone(), steppable_caches, system); // let cycles = 0x1000000; let cycles = 0x50000; let start = time::precise_time_s(); simulator.run_max(cycles); let end = time::precise_time_s(); println!("{} cycles in {:04} seconds ({} cycles/sec)", cycles, end - start, (cycles as f64) / (end - start)); let (p1, p2) = memory_ref.borrow().score(); println!("Program 1 bytes written: {}", p1); println!("Program 2 bytes written: {}", p2); }