diff options
author | David Li <li.davidm96@gmail.com> | 2015-12-16 16:15:29 -0500 |
---|---|---|
committer | David Li <li.davidm96@gmail.com> | 2015-12-16 16:15:29 -0500 |
commit | 55a9ca94d64249280438da9b90186e0a4973f90d (patch) | |
tree | 7c2f4d5abdce0b0b00e75bfaa49e154b9be52868 | |
parent | 98475b71bcf5a89c8c1c4c59a0c9f9ade74494f5 (diff) |
Load and recognize a minimal set of instructions
-rw-r--r-- | src/binary.rs | 2 | ||||
-rw-r--r-- | src/isa/funct3.rs | 8 | ||||
-rw-r--r-- | src/isa/mod.rs | 13 | ||||
-rw-r--r-- | src/isa/opcodes.rs | 6 | ||||
-rw-r--r-- | src/lib.rs | 5 | ||||
-rw-r--r-- | src/memory.rs | 15 | ||||
-rw-r--r-- | src/simulator.rs | 49 |
7 files changed, 78 insertions, 20 deletions
diff --git a/src/binary.rs b/src/binary.rs index e1e6d45..a2a9d38 100644 --- a/src/binary.rs +++ b/src/binary.rs @@ -7,7 +7,7 @@ use std::path::Path; use std::str; pub struct Binary { - words: Vec<u32>, + pub words: Vec<u32>, } #[derive(Debug)] diff --git a/src/isa/funct3.rs b/src/isa/funct3.rs new file mode 100644 index 0000000..d9a626a --- /dev/null +++ b/src/isa/funct3.rs @@ -0,0 +1,8 @@ +pub const ADDI: u32 = 0x0; +pub const SLLI: u32 = 0x1; +pub const SLTI: u32 = 0x2; +pub const SLTIU: u32 = 0x3; + +pub const LW: u32 = 0x2; + +pub const SW: u32 = 0x2; diff --git a/src/isa/mod.rs b/src/isa/mod.rs index 5e9a7dc..ac8ce45 100644 --- a/src/isa/mod.rs +++ b/src/isa/mod.rs @@ -1,6 +1,7 @@ pub mod opcodes; +pub mod funct3; -enum Register { +pub enum Register { X0 = 0, X1 = 1, X2 = 2, @@ -15,6 +16,12 @@ enum Register { X11 = 11, } +impl Register { + pub fn as_num(self) -> usize { + self as usize + } +} + pub struct Instruction { word: u32, } @@ -29,4 +36,8 @@ impl Instruction { pub fn opcode(&self) -> u32 { self.word & 0x7F } + + pub fn funct3(&self) -> u32 { + (self.word >> 12) & 0x3 + } } diff --git a/src/isa/opcodes.rs b/src/isa/opcodes.rs index 0ea7613..33af0f6 100644 --- a/src/isa/opcodes.rs +++ b/src/isa/opcodes.rs @@ -1,2 +1,4 @@ -pub const Branch: u32 = 0x12; -pub const IntegerImmediate: u32 = 0x13; +pub const BRANCH: u32 = 0x12; +pub const INTEGER_IMMEDIATE: u32 = 0x13; +pub const LOAD: u32 = 0x3; +pub const STORE: u32 = 0x23; @@ -10,7 +10,10 @@ fn it_works() { use std::path::Path; println!("Test"); match binary::Binary::new_from_hex_file(Path::new("../riscv/kernel.hex")) { - Ok(_) => println!("Ok"), + Ok(b) => { + let mut simulator = simulator::Simulator::new(1, b); + simulator.run(); + }, Err(err) => println!("Error: {:?}", err), } } diff --git a/src/memory.rs b/src/memory.rs index 854b0ea..3409ed4 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -1,21 +1,28 @@ use isa::{Instruction}; +use binary::{Binary}; pub struct Memory { memory: Vec<u32>, } impl Memory { - pub fn new(size: usize) -> Memory { + pub fn new(size: usize, binary: Binary) -> Memory { + let mut memory = binary.words.clone(); + if size > memory.len() { + let remainder = size - memory.len(); + memory.reserve(remainder); + } Memory { - memory: Vec::with_capacity(size), + memory: memory, } } pub fn read_word(&self, address: usize) -> Option<u32> { - self.memory.get(address).map(Clone::clone) + // memory is word-addressed but addresses are byte-addressed + self.memory.get(address / 4).map(Clone::clone) } pub fn read_instruction(&self, pc: usize) -> Option<Instruction> { - self.memory.get(pc).map(Clone::clone).map(Instruction::new) + self.memory.get(pc / 4).map(Clone::clone).map(Instruction::new) } } diff --git a/src/simulator.rs b/src/simulator.rs index 86ddfab..8ecf6e7 100644 --- a/src/simulator.rs +++ b/src/simulator.rs @@ -3,7 +3,6 @@ use binary::{Binary}; use memory::{Memory}; pub struct Simulator { - binary: Binary, num_cores: usize, memory: Memory, } @@ -17,19 +16,25 @@ struct RegisterFile { registers: [u32; 32], } +impl RegisterFile { + fn write_word<T: Into<isa::Register>>(&mut self, reg: T, value: u32) { + // TODO: should be safe to use unchecked index + self.registers[reg.into().as_num()] = value; + } +} + impl Simulator { pub fn new(num_cores: usize, binary: Binary) -> Simulator { + let memory = Memory::new(0x2000, binary); + // TODO: initialize GP, registers (GP is in headers) Simulator { - binary: binary, num_cores: num_cores, - memory: Memory::new(0x20000), + memory: memory, } } pub fn run(&mut self) { let mut cores = vec![Core { pc: 0x10000, }; self.num_cores]; - // TODO: set up memory, cache, devices - // TODO: map binary into RAM loop { for core in cores.iter_mut() { self.step_core(core); @@ -40,19 +45,41 @@ impl Simulator { fn step_core(&mut self, core: &mut Core) { if let Some(inst) = self.memory.read_instruction(core.pc) { match inst.opcode() { - isa::opcodes::Branch => { + isa::opcodes::BRANCH => { - } - isa::opcodes::IntegerImmediate => { - - } + }, + isa::opcodes::INTEGER_IMMEDIATE => match inst.funct3() { + isa::funct3::ADDI => { + println!("ADDI"); + } + _ => { + panic!("Invalid integer-immediate funct3code: 0x{:x}", inst.funct3()); + } + }, + isa::opcodes::LOAD => match inst.funct3() { + isa::funct3::LW => { + println!("LW"); + } + _ => { + panic!("Invalid load funct3code: 0x{:x}", inst.funct3()); + } + }, + isa::opcodes::STORE => match inst.funct3() { + isa::funct3::SW => { + println!("SW"); + } + _ => { + panic!("Invalid store funct3code: 0x{:x}", inst.funct3()); + } + }, _ => { - + panic!("Invalid opcode: 0x{:02X}", inst.opcode()); } } } else { // trap } + core.pc += 4; } } |