#![feature(augmented_assignments)] extern crate docopt; #[macro_use] extern crate log; extern crate env_logger; extern crate rand; extern crate rustc_serialize; extern crate rustv; extern crate time; mod globals; 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::{self, IsaType}; 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 = isa::Word(elf.file_header().entry); for p in elf.section_headers() { if p.flags.0 & elfloader::elf::SHF_ALLOC.0 != 0 { memory.write_segment(mmu, elf.section_data(p), p.addr as usize); } } start } fn generate_payload() -> isa::Byte { let mut payload = rand::random::(); while payload == shareable_cache::WRITE_TRAP_VALUE.0 || payload == shareable_cache::AREA_TRAP_VALUE.0 { payload = rand::random::(); } isa::Byte(payload) } 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(isa::Word(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 payload1 = generate_payload(); let payload2 = generate_payload(); let memory = MemoryTracker::new(memory, payload1, payload2); // TODO: initialize global data 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, isa::Word(0x100000 * (i + 1) as u32), core_cache, Box::new(memory::IdentityMmu::new()) ); core.registers().write_word(isa::Register::X10, isa::Word(i as u32)); core.registers().write_word(isa::Register::X11, payload1.as_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, isa::Word(0x100000 * (i + 1) as u32), core_cache, Box::new(memory::ReverseMmu::new(isa::Word(0x4000000))) ); core.registers().write_word(isa::Register::X10, isa::Word((i - 4) as u32)); core.registers().write_word(isa::Register::X11, payload2.as_word()); cores.push(core); } let steppable_caches: Vec = vec![cache_ref, 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(); match simulator.run_max(cycles) { simulator::HaltReason::OutOfCycles => { println!("Out of cycles, halting..."); }, simulator::HaltReason::SystemHalt => { println!("Team has reached payload goal, halting..."); }, simulator::HaltReason::CoresHalted => { println!("All cores have stopped, halting..."); }, } let end = time::precise_time_s(); for (core_id, cycles_stalled, total_cycles) in simulator.report().iter().cloned() { println!("Core {}: stalled {:08} of {:08} cycles ({:.2}%)", core_id, cycles_stalled, total_cycles, 100.0 * (cycles_stalled as f32) / (total_cycles as f32)); } 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); }