aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
blob: 2f607a6bfb8eb0fcc4b3d7fcc9163375fc963739 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
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 <program1> <program2>

Options:
  -h --help    Show this screen.
  --version    Show version.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_program1: String,
    arg_program2: String,
}

fn load_program<T: memory::Mmu>(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 (cache1, cache2) = ShareableCache::new(cache_ref.clone(), cache2_ref.clone());
    let mut core_caches = vec![];

    let mut cores = vec![];
    for i in 0..4 {
        let c1 = Rc::new(RefCell::new(cache1.clone()));
        core_caches.push(c1.clone());
        let mut core = simulator::Core::new(
            i, start1, (0x100000 * (i + 1)) as u32, c1,
            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 c2 = Rc::new(RefCell::new(cache2.clone()));
        core_caches.push(c2.clone());
        let mut core = simulator::Core::new(
            i, start2, (0x100000 * (i + 1)) as u32, c2,
            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);
}