From 55a9ca94d64249280438da9b90186e0a4973f90d Mon Sep 17 00:00:00 2001 From: David Li Date: Wed, 16 Dec 2015 16:15:29 -0500 Subject: Load and recognize a minimal set of instructions --- src/binary.rs | 2 +- src/isa/funct3.rs | 8 ++++++++ src/isa/mod.rs | 13 ++++++++++++- src/isa/opcodes.rs | 6 ++++-- src/lib.rs | 5 ++++- src/memory.rs | 15 +++++++++++---- src/simulator.rs | 49 ++++++++++++++++++++++++++++++++++++++----------- 7 files changed, 78 insertions(+), 20 deletions(-) create mode 100644 src/isa/funct3.rs 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, + pub words: Vec, } #[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; diff --git a/src/lib.rs b/src/lib.rs index 8e26888..cf0b4be 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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, } 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 { - 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 { - 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>(&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; } } -- cgit v1.2.3