From c6ea3a0cb322b888b0b8e6fd14e6d9942eeab576 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Thu, 23 Mar 2023 17:42:36 +0100 Subject: [PATCH 01/29] :recycle: Refacted machine tests with macros --- src/simulator/machine.rs | 104 ++++++++++++--------------------------- 1 file changed, 32 insertions(+), 72 deletions(-) diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index e54bd87..1a1057f 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -728,6 +728,29 @@ mod test { use crate::simulator::{machine::Machine, mem_cmp}; + macro_rules! get_full_path { + ($prefix: expr, $test_name:expr) => {{ + let mut s = String::from("test/machine/"); + s.push_str($prefix); + s.push_str($test_name); + s.push_str(".txt"); + &s.to_owned() + }} + } + + macro_rules! init_test { + ($a:expr) => {{ + let mut m = Machine::init_machine(); + let end_file_name = { let mut s = String::from($a); s.push_str("End"); s }; + let memory_before = mem_cmp::MemChecker::from(get_full_path!("memory", $a)).unwrap(); + let memory_after = mem_cmp::MemChecker::from(get_full_path!("memory", &end_file_name)).unwrap(); + mem_cmp::MemChecker::fill_memory_from_mem_checker(&memory_before, &mut m); + Machine::run(&mut m); + let expected_trace = fs::read_to_string(get_full_path!("reg_trace", $a)).unwrap(); + (m, memory_after, expected_trace) + }}; + } + #[test] fn test_init_machine() { let _ = Machine::init_machine(); @@ -756,126 +779,63 @@ mod test { #[test] fn test_comp() { - let mut m = Machine::init_machine(); - let memory_before = mem_cmp::MemChecker::from("test/machine/memoryComp.txt").unwrap(); - let memory_after = mem_cmp::MemChecker::from("test/machine/memoryCompEnd.txt").unwrap(); - mem_cmp::MemChecker::fill_memory_from_mem_checker(&memory_before, &mut m); - Machine::run(&mut m); - - let expected_trace = fs::read_to_string("test/machine/reg_traceComp.txt").unwrap(); - + let (m, memory_after, expected_trace) = init_test!("Comp"); assert!(mem_cmp::MemChecker::compare_machine_memory(&memory_after, &m)); assert!(expected_trace.contains(m.registers_trace.as_str())); } #[test] fn test_add() { - let mut m = Machine::init_machine(); - let memory_before = mem_cmp::MemChecker::from("test/machine/memoryAdd.txt").unwrap(); - let memory_after = mem_cmp::MemChecker::from("test/machine/memoryAddEnd.txt").unwrap(); - mem_cmp::MemChecker::fill_memory_from_mem_checker(&memory_before, &mut m); - Machine::run(&mut m); - - let expected_trace = fs::read_to_string("test/machine/reg_traceAdd.txt").unwrap(); - + let (m, memory_after, expected_trace) = init_test!("Add"); assert!(mem_cmp::MemChecker::compare_machine_memory(&memory_after, &m)); assert!(expected_trace.contains(m.registers_trace.as_str())); } #[test] fn test_div() { - let mut m = Machine::init_machine(); - let memory_before = mem_cmp::MemChecker::from("test/machine/memoryDiv.txt").unwrap(); - let memory_after = mem_cmp::MemChecker::from("test/machine/memoryDivEnd.txt").unwrap(); - mem_cmp::MemChecker::fill_memory_from_mem_checker(&memory_before, &mut m); - Machine::run(&mut m); - - let expected_trace = fs::read_to_string("test/machine/reg_traceDiv.txt").unwrap(); - + let (m, memory_after, expected_trace) = init_test!("Div"); assert!(mem_cmp::MemChecker::compare_machine_memory(&memory_after, &m)); assert!(expected_trace.contains(m.registers_trace.as_str())); } #[test] fn test_if() { - let mut m = Machine::init_machine(); - let memory_before = mem_cmp::MemChecker::from("test/machine/memoryIf.txt").unwrap(); - let memory_after = mem_cmp::MemChecker::from("test/machine/memoryIfEnd.txt").unwrap(); - mem_cmp::MemChecker::fill_memory_from_mem_checker(&memory_before, &mut m); - Machine::run(&mut m); - - let expected_trace = fs::read_to_string("test/machine/reg_traceIf.txt").unwrap(); - + let (m, memory_after, expected_trace) = init_test!("If"); assert!(mem_cmp::MemChecker::compare_machine_memory(&memory_after, &m)); assert!(expected_trace.contains(m.registers_trace.as_str())); } #[test] fn test_jump() { - let mut m = Machine::init_machine(); - let memory_before = mem_cmp::MemChecker::from("test/machine/memoryJump.txt").unwrap(); - let memory_after = mem_cmp::MemChecker::from("test/machine/memoryJumpEnd.txt").unwrap(); - mem_cmp::MemChecker::fill_memory_from_mem_checker(&memory_before, &mut m); - Machine::run(&mut m); - - let expected_trace = fs::read_to_string("test/machine/reg_traceJump.txt").unwrap(); - + let (m, memory_after, expected_trace) = init_test!("Jump"); assert!(mem_cmp::MemChecker::compare_machine_memory(&memory_after, &m)); assert!(expected_trace.contains(m.registers_trace.as_str())); } #[test] fn test_mul() { - let mut m = Machine::init_machine(); - let memory_before = mem_cmp::MemChecker::from("test/machine/memoryMult.txt").unwrap(); - let memory_after = mem_cmp::MemChecker::from("test/machine/memoryMultEnd.txt").unwrap(); - mem_cmp::MemChecker::fill_memory_from_mem_checker(&memory_before, &mut m); - Machine::run(&mut m); - - let expected_trace = fs::read_to_string("test/machine/reg_traceMult.txt").unwrap(); - + let (m, memory_after, expected_trace) = init_test!("Mult"); assert!(mem_cmp::MemChecker::compare_machine_memory(&memory_after, &m)); assert!(expected_trace.contains(m.registers_trace.as_str())); } #[test] fn test_ret() { - let mut m = Machine::init_machine(); - let memory_before = mem_cmp::MemChecker::from("test/machine/memoryRet.txt").unwrap(); - let memory_after = mem_cmp::MemChecker::from("test/machine/memoryRetEnd.txt").unwrap(); - mem_cmp::MemChecker::fill_memory_from_mem_checker(&memory_before, &mut m); - Machine::run(&mut m); - - let expected_trace = fs::read_to_string("test/machine/reg_traceRet.txt").unwrap(); - + let (m, memory_after, expected_trace) = init_test!("Ret"); assert!(mem_cmp::MemChecker::compare_machine_memory(&memory_after, &m)); assert!(expected_trace.contains(m.registers_trace.as_str())); } #[test] fn test_sub() { - let mut m = Machine::init_machine(); - let memory_before = mem_cmp::MemChecker::from("test/machine/memorySub.txt").unwrap(); - let memory_after = mem_cmp::MemChecker::from("test/machine/memorySubEnd.txt").unwrap(); - mem_cmp::MemChecker::fill_memory_from_mem_checker(&memory_before, &mut m); - Machine::run(&mut m); - - let expected_trace = fs::read_to_string("test/machine/reg_traceSub.txt").unwrap(); - + let (m, memory_after, expected_trace) = init_test!("Sub"); assert!(mem_cmp::MemChecker::compare_machine_memory(&memory_after, &m)); assert!(expected_trace.contains(m.registers_trace.as_str())); } #[test] fn test_switch() { - let mut m = Machine::init_machine(); - let memory_before = mem_cmp::MemChecker::from("test/machine/memorySwitch.txt").unwrap(); - let memory_after = mem_cmp::MemChecker::from("test/machine/memorySwitchEnd.txt").unwrap(); - mem_cmp::MemChecker::fill_memory_from_mem_checker(&memory_before, &mut m); - Machine::run(&mut m); - - let expected_trace = fs::read_to_string("test/machine/reg_traceSwitch.txt").unwrap(); - + let (m, memory_after, expected_trace) = init_test!("Switch"); assert!(mem_cmp::MemChecker::compare_machine_memory(&memory_after, &m)); assert!(expected_trace.contains(m.registers_trace.as_str())); } From 87d90c394fb661fd0bb38e652e1d7fdb5c261325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Thu, 23 Mar 2023 20:04:21 +0100 Subject: [PATCH 02/29] :sparkles: Added MachineError struct --- src/simulator/error.rs | 27 +++++++++++++++++++++++++++ src/simulator/mod.rs | 1 + 2 files changed, 28 insertions(+) create mode 100644 src/simulator/error.rs diff --git a/src/simulator/error.rs b/src/simulator/error.rs new file mode 100644 index 0000000..42db367 --- /dev/null +++ b/src/simulator/error.rs @@ -0,0 +1,27 @@ +use std::fmt; + +/// Machine Error +/// This error serves as a specific exception handler for the Machine struct +#[derive(Debug, Clone)] +pub struct MachineError { + /// The error message + message: String +} + +impl MachineError { + + pub fn new(message: &str) -> MachineError { + MachineError { + message: message.to_string() + } + } + +} + +impl fmt::Display for MachineError { + + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Machine error: {}", &self.message) + } + +} \ No newline at end of file diff --git a/src/simulator/mod.rs b/src/simulator/mod.rs index 8626048..e13df71 100644 --- a/src/simulator/mod.rs +++ b/src/simulator/mod.rs @@ -1,4 +1,5 @@ pub mod machine; +pub mod error; pub mod decode; pub mod print; pub mod mem_cmp; From 43de76bd72da76fc975caf0e96bfc40f8dae0e06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Thu, 23 Mar 2023 20:05:46 +0100 Subject: [PATCH 03/29] :recycle: Started work on machine.rs refactoring # Current changes - Crude error management - Readability improvements - Broke down one_instruction into smaller, more manageable methods - Added crude documentation --- src/simulator/machine.rs | 709 +++++++++++++++++---------------------- 1 file changed, 313 insertions(+), 396 deletions(-) diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index 1a1057f..b785d6b 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -1,6 +1,6 @@ use std::{ops::{Add, Sub}, io::Write}; -use crate::simulator::print; +use crate::simulator::{print, error::MachineError}; use super::{decode::{Instruction, decode}, interrupt::Interrupt}; use super::global::*; @@ -230,28 +230,16 @@ impl Machine { /// /// - **machine** which contains a table of instructions pub fn run(machine : &mut Machine){ - while Machine::one_instruction(machine) == 0 {} + while let Ok(()) = Machine::one_instruction(machine) {} println!("trace : \n{}", machine.registers_trace); } - /// execute the current instruction + /// Execute the current instruction /// /// ### Parameters /// /// - **machine** which contains a table of instructions and a pc to the actual instruction - pub fn one_instruction(machine :&mut Machine) -> i32 { - - let unsigned_reg1 : u64; - let unsigned_reg2 : u64; - let long_result : i128; - - /*__int128 longResult; - int32_t local_data_a, local_data_b; - int64_t localLongResult; - uint32_t local_data_aUnsigned, local_data_bUnsigned; - int32_t localResult; - float localFloat; - uint64_t value;*/ + pub fn one_instruction(machine :&mut Machine) -> Result<(), MachineError> { if machine.main_memory.len() <= machine.pc as usize { panic!("ERROR : number max of instructions rushed"); @@ -274,422 +262,351 @@ impl Machine { match inst.opcode { RISCV_LUI => { machine.int_reg.set_reg(inst.rd as usize, inst.imm31_12 as i64); + Ok(()) }, RISCV_AUIPC => { machine.int_reg.set_reg(inst.rd as usize,machine.pc as i64 - 4 + inst.imm31_12 as i64); + Ok(()) }, RISCV_JAL => { machine.int_reg.set_reg(inst.rd as usize, machine.pc as i64); machine.pc = (machine.pc as i64 + inst.imm21_1_signed as i64 - 4) as u64; + Ok(()) }, RISCV_JALR => { let tmp = machine.pc; machine.pc = (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_I_signed as i64) as u64 & 0xfffffffe; machine.int_reg.set_reg(inst.rd as usize, tmp as i64); + Ok(()) }, - - //****************************************************************************************** // Treatment for: BRANCH INSTRUCTIONS RISCV_BR => { - match inst.funct3 { - RISCV_BR_BEQ => { - if machine.int_reg.get_reg(inst.rs1 as usize) == machine.int_reg.get_reg(inst.rs2 as usize) { - machine.pc = (machine.pc as i64 + inst.imm13_signed as i64 - 4) as u64; - } - }, - RISCV_BR_BNE => { - if machine.int_reg.get_reg(inst.rs1 as usize) != machine.int_reg.get_reg(inst.rs2 as usize) { - machine.pc = (machine.pc as i64 + inst.imm13_signed as i64 - 4) as u64; - } - }, - RISCV_BR_BLT => { - if machine.int_reg.get_reg(inst.rs1 as usize) < machine.int_reg.get_reg(inst.rs2 as usize) { - machine.pc = (machine.pc as i64 + inst.imm13_signed as i64 - 4) as u64; - } - }, - RISCV_BR_BGE => { - if machine.int_reg.get_reg(inst.rs1 as usize) >= machine.int_reg.get_reg(inst.rs2 as usize) { - machine.pc = (machine.pc as i64 + inst.imm13_signed as i64 - 4) as u64; - } - }, - RISCV_BR_BLTU => { - if machine.int_reg.get_reg(inst.rs1 as usize) < machine.int_reg.get_reg(inst.rs2 as usize) { - machine.pc = (machine.pc as i64 + inst.imm13_signed as i64 - 4) as u64; - } - }, - RISCV_BR_BGEU => { - if machine.int_reg.get_reg(inst.rs1 as usize) >= machine.int_reg.get_reg(inst.rs2 as usize) { - machine.pc = (machine.pc as i64 + inst.imm13_signed as i64 - 4) as u64; - } - }, - _ => { - panic!("In BR switch case, this should never happen... Instr was {}", inst.value); - } - } + Self::branch_instruction(machine, inst) }, - - //****************************************************************************************** // Treatment for: LOAD INSTRUCTIONS RISCV_LD => { - match inst.funct3 { - RISCV_LD_LB | RISCV_LD_LBU => { - let tmp = Self::read_memory(machine, 1, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_I_signed as i64) as usize) as i64; - machine.int_reg.set_reg(inst.rd as usize, tmp); - }, - RISCV_LD_LH | RISCV_LD_LHU => { - let tmp = Self::read_memory(machine, 2, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_I_signed as i64) as usize) as i64; - machine.int_reg.set_reg(inst.rd as usize, tmp); - }, - RISCV_LD_LW | RISCV_LD_LWU => { - let tmp = Self::read_memory(machine, 4, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_I_signed as i64) as usize) as i64; - machine.int_reg.set_reg(inst.rd as usize, tmp); - }, - RISCV_LD_LD => { - let tmp = Self::read_memory(machine, 8, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_I_signed as i64) as usize) as i64; - machine.int_reg.set_reg(inst.rd as usize, tmp); - }, - _ => { - panic!("In LD switch case, this should never happen... Instr was {}", inst.value); - } - } + Self::load_instruction(machine, inst) }, // store instructions RISCV_ST => { - match inst.funct3 { - RISCV_ST_STB => { - Self::write_memory(machine, 1, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2 as usize) as u64); - }, - RISCV_ST_STH => { - Self::write_memory(machine, 2, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2 as usize) as u64); - }, - RISCV_ST_STW => { - Self::write_memory(machine, 4, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2 as usize) as u64); - }, - RISCV_ST_STD => { - Self::write_memory(machine, 8, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2 as usize) as u64); - }, - _ => { - panic!("In ST switch case, this should never happen... Instr was {}", inst.value); - } - } - } - //****************************************************************************************** + Self::store_instruction(machine, inst) + }, // Treatment for: OPI INSTRUCTIONS RISCV_OPI => { - match inst.funct3 { - RISCV_OPI_ADDI => { - machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_I_signed as i64); - }, - RISCV_OPI_SLTI => { - machine.int_reg.set_reg(inst.rd as usize, (machine.int_reg.get_reg(inst.rs1 as usize) < inst.imm12_I_signed as i64) as i64); - }, - RISCV_OPI_XORI => { - machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) ^ inst.imm12_I_signed as i64); - }, - RISCV_OPI_ORI => { - machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) | inst.imm12_I_signed as i64); - }, - RISCV_OPI_ANDI => { - machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) & inst.imm12_I_signed as i64); - }, - RISCV_OPI_SLLI => { - machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) << inst.shamt); - }, - RISCV_OPI_SRI => { - if inst.funct7_smaller == RISCV_OPI_SRI_SRLI { - machine.int_reg.set_reg(inst.rd as usize, (machine.int_reg.get_reg(inst.rs1 as usize) >> inst.shamt) & machine.shiftmask[inst.shamt as usize] as i64); - } else { // SRAI - machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) >> inst.shamt); - } - } - _ => { panic!("In OPI switch case, this should never happen... Instr was %x\n {}", inst.value); } - } + Self::opi_instruction(machine, inst) }, - RISCV_OP => { - if inst.funct7 == 1 { - match inst.funct3 { - RISCV_OP_M_MUL => { - long_result = (machine.int_reg.get_reg(inst.rs1 as usize) * machine.int_reg.get_reg(inst.rs2 as usize)) as i128; - machine.int_reg.set_reg(inst.rd as usize, (long_result & 0xffffffffffffffff) as i64); - }, - RISCV_OP_M_MULH => { - long_result = (machine.int_reg.get_reg(inst.rs1 as usize) * machine.int_reg.get_reg(inst.rs2 as usize)) as i128; - machine.int_reg.set_reg(inst.rd as usize, ((long_result >> 64) & 0xffffffffffffffff) as i64); - }, - RISCV_OP_M_MULHSU => { - unsigned_reg2 = machine.int_reg.get_reg(inst.rs2 as usize) as u64; - long_result = (machine.int_reg.get_reg(inst.rs1 as usize) as u64 * unsigned_reg2) as i128; - machine.int_reg.set_reg(inst.rd as usize, ((long_result >> 64) & 0xffffffffffffffff) as i64); - }, - // VOIR CE QUE FAIT EXACTEMENT CE TRUC , PK on converve - /* - * VOIR SI LES CAST machine.int_reg[....] = i128*u64 as u32 FAUSSE RESULTAT (suit pas la logique du code c++) - * WHAT DA HECK - */ - RISCV_OP_M_MULHU => { - unsigned_reg1 = machine.int_reg.get_reg(inst.rs1 as usize) as u64; - unsigned_reg2 = machine.int_reg.get_reg(inst.rs2 as usize) as u64; - long_result = (unsigned_reg1 * unsigned_reg2) as i128; - machine.int_reg.set_reg(inst.rd as usize, ((long_result >> 64) & 0xffffffffffffffff) as i64); - }, - RISCV_OP_M_DIV => { - machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) / machine.int_reg.get_reg(inst.rs2 as usize)); - } - _ => { - panic!("RISCV_OP : funct7 = 1 (Multiplication) :: Error\n"); - } - } - } else { - match inst.funct3 { - RISCV_OP_ADD => { - if inst.funct7 == RISCV_OP_ADD_ADD { - machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) + machine.int_reg.get_reg(inst.rs2 as usize)); - } else { - machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) - machine.int_reg.get_reg(inst.rs2 as usize)); - } - }, - RISCV_OP_SLL => { - machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) << (machine.int_reg.get_reg(inst.rs2 as usize) & 0x3f)); - }, - RISCV_OP_SLT => { - if machine.int_reg.get_reg(inst.rs1 as usize) < machine.int_reg.get_reg(inst.rs2 as usize) { - machine.int_reg.set_reg(inst.rd as usize, 1); - } else { - machine.int_reg.set_reg(inst.rd as usize, 0); - } - }, - RISCV_OP_SLTU => { - unsigned_reg1 = machine.int_reg.get_reg(inst.rs1 as usize) as u64; - unsigned_reg2 = machine.int_reg.get_reg(inst.rs2 as usize) as u64; - if unsigned_reg1 < unsigned_reg2 { - machine.int_reg.set_reg(inst.rd as usize, 1); - } else { - machine.int_reg.set_reg(inst.rd as usize, 0); - } - }, - RISCV_OP_XOR => { - machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) ^ machine.int_reg.get_reg(inst.rs2 as usize)); - }, - RISCV_OP_SR => { - // RISCV_OP_SR_SRL inaccessible - machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) >> machine.int_reg.get_reg(inst.rs2 as usize)); - }, - RISCV_OP_OR => { - machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) | machine.int_reg.get_reg(inst.rs2 as usize)); - }, - RISCV_OP_AND => { - machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) & machine.int_reg.get_reg(inst.rs2 as usize)); - }, - _ => { - panic!("RISCV_OP undefined case\n"); - } - }//LA - } + Self::op_instruction(machine, inst) }, - //****************************************************************************************** // Treatment for OPIW INSTRUCTIONS RISCV_OPIW => { - let local_data = machine.int_reg.get_reg(inst.rs1 as usize); - match inst.funct3 { - RISCV_OPIW_ADDIW => { - let result = local_data + inst.imm12_I_signed as i64; - machine.int_reg.set_reg(inst.rd as usize, result); - }, - RISCV_OPIW_SLLIW => { - let result = local_data << inst.shamt; - machine.int_reg.set_reg(inst.rd as usize, result); - }, - RISCV_OPIW_SRW => { - let result = if inst.funct7 == RISCV_OPIW_SRW_SRLIW { - (local_data >> inst.shamt) & machine.shiftmask[32 + inst.shamt as usize] as i64 - } else { // SRAIW - local_data >> inst.shamt - }; - machine.int_reg.set_reg(inst.rd as usize, result); - }, - _ => { - panic!("In OPI switch case, this should never happen... Instr was {}\n", inst.value); - } - } + Self::opiw_instruction(machine, inst) }, - //****************************************************************************************** // Treatment for: OPW INSTRUCTIONS - RISCV_OPW => { - if inst.funct7 == 1 { // rv64m - let local_data_a = machine.int_reg.get_reg(inst.rs1 as usize) & 0xffffffff; - let local_data_b = machine.int_reg.get_reg(inst.rs2 as usize) & 0xffffffff; - let local_data_a_unsigned = machine.int_reg.get_reg(inst.rs1 as usize) & 0xffffffff; - let local_data_b_unsigned = machine.int_reg.get_reg(inst.rs2 as usize) & 0xffffffff; - - // Match case for multiplication operations (in standard extension RV32M) - match inst.funct3 { - RISCV_OPW_M_MULW => { - machine.int_reg.set_reg(inst.rd as usize, local_data_a * local_data_b); - }, - RISCV_OPW_M_DIVW => { - machine.int_reg.set_reg(inst.rd as usize, local_data_a / local_data_b); - }, - RISCV_OPW_M_DIVUW => { - machine.int_reg.set_reg(inst.rd as usize, local_data_a_unsigned / local_data_b_unsigned); - }, - RISCV_OPW_M_REMW => { - machine.int_reg.set_reg(inst.rd as usize, local_data_a % local_data_b); - }, - RISCV_OPW_M_REMUW => { - machine.int_reg.set_reg(inst.rd as usize, local_data_a_unsigned % local_data_b_unsigned); - }, - _ => { - panic!("this instruction ({}) doesn't exists", inst.value); - } - } - } else { // others rv64 OPW operations - let local_dataa = machine.int_reg.get_reg(inst.rs1 as usize) & 0xffffffff; - let local_datab = machine.int_reg.get_reg(inst.rs2 as usize) & 0xffffffff; - - // Match case for base OP operation - match inst.funct3 { - RISCV_OPW_ADDSUBW => { - if inst.funct7 == RISCV_OPW_ADDSUBW_ADDW { - machine.int_reg.set_reg(inst.rd as usize, local_dataa + local_datab); - } else { // SUBW - machine.int_reg.set_reg(inst.rd as usize, local_dataa - local_datab); - } - }, - RISCV_OPW_SLLW => { - machine.int_reg.set_reg(inst.rd as usize, local_dataa << (local_datab & 0x1f)); - }, - RISCV_OPW_SRW => { - if inst.funct7 == RISCV_OPW_SRW_SRLW { - machine.int_reg.set_reg(inst.rd as usize, local_dataa >> (local_datab & 0x1f) & machine.shiftmask[32 + local_datab as usize] as i64); - } else { // SRAW - machine.int_reg.set_reg(inst.rd as usize, local_dataa >> (local_datab & 0x1f)); - } - }, - _ => { - panic!("this instruction ({}) doesn't exists", inst.value); - } - } - } - }, - //****************************************************************************************** + RISCV_OPW => Self::opw_instruction(machine, inst), // Treatment for: Simple floating point extension - RISCV_FP => { - match inst.funct7 { - RISCV_FP_ADD => { - machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) + machine.fp_reg.get_reg(inst.rs2 as usize)); - }, - RISCV_FP_SUB => { - machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) - machine.fp_reg.get_reg(inst.rs2 as usize)); - }, - RISCV_FP_MUL => { - machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) * machine.fp_reg.get_reg(inst.rs2 as usize)); - }, - RISCV_FP_DIV => { - machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) / machine.fp_reg.get_reg(inst.rs2 as usize)); - }, - RISCV_FP_SQRT => { - machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize).sqrt()); - }, - RISCV_FP_FSGN => { - let local_float = machine.fp_reg.get_reg(inst.rs1 as usize); - match inst.funct3 { - RISCV_FP_FSGN_J => { - if machine.fp_reg.get_reg(inst.rs2 as usize) < 0f32 { - machine.fp_reg.set_reg(inst.rd as usize, -local_float); - } else { - machine.fp_reg.set_reg(inst.rd as usize, local_float); - } - } - RISCV_FP_FSGN_JN => { - if machine.fp_reg.get_reg(inst.rs2 as usize) < 0f32 { - machine.fp_reg.set_reg(inst.rd as usize, local_float); - } else { - machine.fp_reg.set_reg(inst.rd as usize, -local_float); - } - } - RISCV_FP_FSGN_JX => { - if (machine.fp_reg.get_reg(inst.rs2 as usize) < 0.0 && machine.fp_reg.get_reg(inst.rs1 as usize) >= 0.0) || (machine.fp_reg.get_reg(inst.rs2 as usize) >= 0.0 && machine.fp_reg.get_reg(inst.rs1 as usize) < 0.0) { - machine.fp_reg.set_reg(inst.rd as usize, -local_float); - } else { - machine.fp_reg.set_reg(inst.rd as usize, local_float); - } - } - _ => { - panic!("this instruction ({}) doesn't exists", inst.value); - } - } - }, - RISCV_FP_MINMAX => { - let r1 = machine.fp_reg.get_reg(inst.rs1 as usize); - let r2 = machine.fp_reg.get_reg(inst.rs2 as usize); - match inst.funct3 { - RISCV_FP_MINMAX_MIN => { - machine.fp_reg.set_reg(inst.rd as usize, if r1 < r2 {r1} else {r2}); - }, - RISCV_FP_MINMAX_MAX => { - machine.fp_reg.set_reg(inst.rd as usize, if r1 > r2 {r1} else {r2}); - }, - _ => { - panic!("this instruction ({}) doesn't exists", inst.value); - } - } - }, - RISCV_FP_FCVTW => { - if inst.rs2 == RISCV_FP_FCVTW_W { - machine.int_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) as i64); - } else { - machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1 as usize) as u64) as i64); - } - }, - RISCV_FP_FCVTS => { - if inst.rs2 == RISCV_FP_FCVTS_W { - machine.fp_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) as f32); - } else { - machine.fp_reg.set_reg(inst.rd as usize, (machine.int_reg.get_reg(inst.rs1 as usize) as u32) as f32); - } - }, - RISCV_FP_FMVW => { - machine.fp_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) as f32); - }, - RISCV_FP_FMVXFCLASS => { - if inst.funct3 == RISCV_FP_FMVXFCLASS_FMVX { - machine.int_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) as i64); - } else { - panic!("Fclass instruction is not handled in riscv simulator"); - } - }, - RISCV_FP_FCMP => { - match inst.funct3 { - RISCV_FP_FCMP_FEQ => { - machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1 as usize) == machine.fp_reg.get_reg(inst.rs2 as usize)) as i64); - }, - RISCV_FP_FCMP_FLT => { - machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1 as usize) < machine.fp_reg.get_reg(inst.rs2 as usize)) as i64); - }, - RISCV_FP_FCMP_FLE => { - machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1 as usize) <= machine.fp_reg.get_reg(inst.rs2 as usize)) as i64); - }, - _ => { - panic!("this instruction ({}) doesn't exists", inst.value); - } - } - }, - _ => { - panic!("this instruction ({}) doesn't exists", inst.value); - } - } - } + RISCV_FP => Self::fp_instruction(machine, inst), + // Treatment for: System instructions RISCV_SYSTEM => { // temporary return value to stop the loop of run - // before we can use system call - return 1; - } - _ => { panic!("{:x} opcode non géré pc : {:x}", inst.opcode, machine.pc)}, + // before we can use system call + Err(MachineError::new(format!("{:x}: System opcode\npc: {:x}", inst.opcode, machine.pc).as_str())) + }, + _ => Err(MachineError::new(format!("{:x}: Unknown opcode\npc: {:x}", inst.opcode, machine.pc).as_str())) } + } - 0 + /// Treatement for Branch instructions + fn branch_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { + match inst.funct3 { + RISCV_BR_BEQ => { + if machine.int_reg.get_reg(inst.rs1 as usize) == machine.int_reg.get_reg(inst.rs2 as usize) { + machine.pc = (machine.pc as i64 + inst.imm13_signed as i64 - 4) as u64; + } + }, + RISCV_BR_BNE => { + if machine.int_reg.get_reg(inst.rs1 as usize) != machine.int_reg.get_reg(inst.rs2 as usize) { + machine.pc = (machine.pc as i64 + inst.imm13_signed as i64 - 4) as u64; + } + }, + RISCV_BR_BLT => { + if machine.int_reg.get_reg(inst.rs1 as usize) < machine.int_reg.get_reg(inst.rs2 as usize) { + machine.pc = (machine.pc as i64 + inst.imm13_signed as i64 - 4) as u64; + } + }, + RISCV_BR_BGE => { + if machine.int_reg.get_reg(inst.rs1 as usize) >= machine.int_reg.get_reg(inst.rs2 as usize) { + machine.pc = (machine.pc as i64 + inst.imm13_signed as i64 - 4) as u64; + } + }, + RISCV_BR_BLTU => { + if machine.int_reg.get_reg(inst.rs1 as usize) < machine.int_reg.get_reg(inst.rs2 as usize) { + machine.pc = (machine.pc as i64 + inst.imm13_signed as i64 - 4) as u64; + } + }, + RISCV_BR_BGEU => { + if machine.int_reg.get_reg(inst.rs1 as usize) >= machine.int_reg.get_reg(inst.rs2 as usize) { + machine.pc = (machine.pc as i64 + inst.imm13_signed as i64 - 4) as u64; + } + }, + _ => { + panic!("In BR switch case, this should never happen... Instr was {}", inst.value); + } + } + Ok(()) + } + /// Executes RISC-V Load Instructions on the machine + fn load_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { + match inst.funct3 { + RISCV_LD_LB | RISCV_LD_LBU => { + let tmp = Self::read_memory(machine, 1, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_I_signed as i64) as usize) as i64; + machine.int_reg.set_reg(inst.rd as usize, tmp); + }, + RISCV_LD_LH | RISCV_LD_LHU => { + let tmp = Self::read_memory(machine, 2, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_I_signed as i64) as usize) as i64; + machine.int_reg.set_reg(inst.rd as usize, tmp); + }, + RISCV_LD_LW | RISCV_LD_LWU => { + let tmp = Self::read_memory(machine, 4, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_I_signed as i64) as usize) as i64; + machine.int_reg.set_reg(inst.rd as usize, tmp); + }, + RISCV_LD_LD => { + let tmp = Self::read_memory(machine, 8, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_I_signed as i64) as usize) as i64; + machine.int_reg.set_reg(inst.rd as usize, tmp); + }, + _ => panic!("In LD switch case, this should never happen... Instr was {}", inst.value) + } + Ok(()) + } + + /// Executes RISC-V Store Instructions on the machine + fn store_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { + match inst.funct3 { + RISCV_ST_STB => Self::write_memory(machine, 1, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2 as usize) as u64), + RISCV_ST_STH => Self::write_memory(machine, 2, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2 as usize) as u64), + RISCV_ST_STW => Self::write_memory(machine, 4, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2 as usize) as u64), + RISCV_ST_STD => Self::write_memory(machine, 8, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2 as usize) as u64), + _ => panic!("In ST switch case, this should never happen... Instr was {}", inst.value) + } + Ok(()) + } + + /// Executes RISC-V Integer Register-Immediate Instructions on the machine + fn opi_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { + match inst.funct3 { + RISCV_OPI_ADDI => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_I_signed as i64), + RISCV_OPI_SLTI => machine.int_reg.set_reg(inst.rd as usize, (machine.int_reg.get_reg(inst.rs1 as usize) < inst.imm12_I_signed as i64) as i64), + RISCV_OPI_XORI => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) ^ inst.imm12_I_signed as i64), + RISCV_OPI_ORI => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) | inst.imm12_I_signed as i64), + RISCV_OPI_ANDI => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) & inst.imm12_I_signed as i64), + RISCV_OPI_SLLI => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) << inst.shamt), + RISCV_OPI_SRI => if inst.funct7_smaller == RISCV_OPI_SRI_SRLI { + machine.int_reg.set_reg(inst.rd as usize, (machine.int_reg.get_reg(inst.rs1 as usize) >> inst.shamt) & machine.shiftmask[inst.shamt as usize] as i64); + } else { // SRAI + machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) >> inst.shamt); + }, + _ => panic!("In OPI switch case, this should never happen... Instr was %x\n {}", inst.value) + } + Ok(()) + } + + /// Executes simple RISC-V mathematical operations on the machine + fn op_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { + let long_result: i128; + let unsigned_reg1: u64; + let unsigned_reg2: u64; + if inst.funct7 == 1 { + match inst.funct3 { + RISCV_OP_M_MUL => { + long_result = (machine.int_reg.get_reg(inst.rs1 as usize) * machine.int_reg.get_reg(inst.rs2 as usize)) as i128; + machine.int_reg.set_reg(inst.rd as usize, (long_result & 0xffffffffffffffff) as i64) + }, + RISCV_OP_M_MULH => { + long_result = (machine.int_reg.get_reg(inst.rs1 as usize) * machine.int_reg.get_reg(inst.rs2 as usize)) as i128; + machine.int_reg.set_reg(inst.rd as usize, ((long_result >> 64) & 0xffffffffffffffff) as i64) + }, + RISCV_OP_M_MULHSU => { + unsigned_reg2 = machine.int_reg.get_reg(inst.rs2 as usize) as u64; + long_result = (machine.int_reg.get_reg(inst.rs1 as usize) as u64 * unsigned_reg2) as i128; + machine.int_reg.set_reg(inst.rd as usize, ((long_result >> 64) & 0xffffffffffffffff) as i64) + }, + RISCV_OP_M_MULHU => { + unsigned_reg1 = machine.int_reg.get_reg(inst.rs1 as usize) as u64; + unsigned_reg2 = machine.int_reg.get_reg(inst.rs2 as usize) as u64; + long_result = (unsigned_reg1 * unsigned_reg2) as i128; + machine.int_reg.set_reg(inst.rd as usize, ((long_result >> 64) & 0xffffffffffffffff) as i64); + }, + RISCV_OP_M_DIV => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) / machine.int_reg.get_reg(inst.rs2 as usize)), + _ => panic!("RISCV_OP : funct7 = 1 (Multiplication) :: Error\n") + } + } else { + match inst.funct3 { + RISCV_OP_ADD => if inst.funct7 == RISCV_OP_ADD_ADD { + machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) + machine.int_reg.get_reg(inst.rs2 as usize)) + } else { + machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) - machine.int_reg.get_reg(inst.rs2 as usize)) + }, + RISCV_OP_SLL => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) << (machine.int_reg.get_reg(inst.rs2 as usize) & 0x3f)), + RISCV_OP_SLT => if machine.int_reg.get_reg(inst.rs1 as usize) < machine.int_reg.get_reg(inst.rs2 as usize) { + machine.int_reg.set_reg(inst.rd as usize, 1) + } else { + machine.int_reg.set_reg(inst.rd as usize, 0) + }, + RISCV_OP_SLTU => { + unsigned_reg1 = machine.int_reg.get_reg(inst.rs1 as usize) as u64; + unsigned_reg2 = machine.int_reg.get_reg(inst.rs2 as usize) as u64; + if unsigned_reg1 < unsigned_reg2 { + machine.int_reg.set_reg(inst.rd as usize, 1) + } else { + machine.int_reg.set_reg(inst.rd as usize, 0) + } + }, + RISCV_OP_XOR => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) ^ machine.int_reg.get_reg(inst.rs2 as usize)), + RISCV_OP_SR => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) >> machine.int_reg.get_reg(inst.rs2 as usize)), // RISCV_OP_SR_SRL inaccessible + RISCV_OP_OR => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) | machine.int_reg.get_reg(inst.rs2 as usize)), + RISCV_OP_AND => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) & machine.int_reg.get_reg(inst.rs2 as usize)), + _ => panic!("RISCV_OP undefined case\n") + } + } + Ok(()) + } + + /// Exectutes simple RISC-V *iw instructions on the machine + fn opiw_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { + let local_data = machine.int_reg.get_reg(inst.rs1 as usize); + match inst.funct3 { + RISCV_OPIW_ADDIW => { + let result = local_data + inst.imm12_I_signed as i64; + machine.int_reg.set_reg(inst.rd as usize, result) + }, + RISCV_OPIW_SLLIW => { + let result = local_data << inst.shamt; + machine.int_reg.set_reg(inst.rd as usize, result) + }, + RISCV_OPIW_SRW => { + let result = if inst.funct7 == RISCV_OPIW_SRW_SRLIW { + (local_data >> inst.shamt) & machine.shiftmask[32 + inst.shamt as usize] as i64 + } else { // SRAIW + local_data >> inst.shamt + }; + machine.int_reg.set_reg(inst.rd as usize, result) + }, + _ => panic!("In OPI switch case, this should never happen... Instr was {}\n", inst.value), + } + Ok(()) + } + + /// Executes simple RISC-V *w instructions on the machine + fn opw_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { + if inst.funct7 == 1 { // rv64m + let local_data_a = machine.int_reg.get_reg(inst.rs1 as usize) & 0xffffffff; + let local_data_b = machine.int_reg.get_reg(inst.rs2 as usize) & 0xffffffff; + let local_data_a_unsigned = machine.int_reg.get_reg(inst.rs1 as usize) & 0xffffffff; + let local_data_b_unsigned = machine.int_reg.get_reg(inst.rs2 as usize) & 0xffffffff; + + // Match case for multiplication operations (in standard extension RV32M) + match inst.funct3 { + RISCV_OPW_M_MULW => machine.int_reg.set_reg(inst.rd as usize, local_data_a * local_data_b), + RISCV_OPW_M_DIVW => machine.int_reg.set_reg(inst.rd as usize, local_data_a / local_data_b), + RISCV_OPW_M_DIVUW => machine.int_reg.set_reg(inst.rd as usize, local_data_a_unsigned / local_data_b_unsigned), + RISCV_OPW_M_REMW => machine.int_reg.set_reg(inst.rd as usize, local_data_a % local_data_b), + RISCV_OPW_M_REMUW => machine.int_reg.set_reg(inst.rd as usize, local_data_a_unsigned % local_data_b_unsigned), + _ => panic!("this instruction ({}) doesn't exists", inst.value) + } + } else { // others rv64 OPW operations + let local_dataa = machine.int_reg.get_reg(inst.rs1 as usize) & 0xffffffff; + let local_datab = machine.int_reg.get_reg(inst.rs2 as usize) & 0xffffffff; + // Match case for base OP operation + match inst.funct3 { + RISCV_OPW_ADDSUBW => if inst.funct7 == RISCV_OPW_ADDSUBW_ADDW { + machine.int_reg.set_reg(inst.rd as usize, local_dataa + local_datab); + } else { // SUBW + machine.int_reg.set_reg(inst.rd as usize, local_dataa - local_datab); + }, + RISCV_OPW_SLLW => machine.int_reg.set_reg(inst.rd as usize, local_dataa << (local_datab & 0x1f)), + RISCV_OPW_SRW => if inst.funct7 == RISCV_OPW_SRW_SRLW { + machine.int_reg.set_reg(inst.rd as usize, local_dataa >> (local_datab & 0x1f) & machine.shiftmask[32 + local_datab as usize] as i64) + } else { // SRAW + machine.int_reg.set_reg(inst.rd as usize, local_dataa >> (local_datab & 0x1f)) + }, + _ => panic!("this instruction ({}) doesn't exists", inst.value) + } + } + Ok(()) + } + + /// Executes simple RISC-V floating point instructions on the machine + fn fp_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { + match inst.funct7 { + RISCV_FP_ADD => machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) + machine.fp_reg.get_reg(inst.rs2 as usize)), + RISCV_FP_SUB => machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) - machine.fp_reg.get_reg(inst.rs2 as usize)), + RISCV_FP_MUL => machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) * machine.fp_reg.get_reg(inst.rs2 as usize)), + RISCV_FP_DIV => machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) / machine.fp_reg.get_reg(inst.rs2 as usize)), + RISCV_FP_SQRT => machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize).sqrt()), + RISCV_FP_FSGN => { + let local_float = machine.fp_reg.get_reg(inst.rs1 as usize); + match inst.funct3 { + RISCV_FP_FSGN_J => if machine.fp_reg.get_reg(inst.rs2 as usize) < 0f32 { + machine.fp_reg.set_reg(inst.rd as usize, -local_float) + } else { + machine.fp_reg.set_reg(inst.rd as usize, local_float) + }, + RISCV_FP_FSGN_JN => if machine.fp_reg.get_reg(inst.rs2 as usize) < 0f32 { + machine.fp_reg.set_reg(inst.rd as usize, local_float) + } else { + machine.fp_reg.set_reg(inst.rd as usize, -local_float) + }, + RISCV_FP_FSGN_JX => if (machine.fp_reg.get_reg(inst.rs2 as usize) < 0.0 && machine.fp_reg.get_reg(inst.rs1 as usize) >= 0.0) || (machine.fp_reg.get_reg(inst.rs2 as usize) >= 0.0 && machine.fp_reg.get_reg(inst.rs1 as usize) < 0.0) { + machine.fp_reg.set_reg(inst.rd as usize, -local_float) + } else { + machine.fp_reg.set_reg(inst.rd as usize, local_float) + }, + _ => panic!("this instruction ({}) doesn't exists", inst.value) + } + }, + RISCV_FP_MINMAX => { + let r1 = machine.fp_reg.get_reg(inst.rs1 as usize); + let r2 = machine.fp_reg.get_reg(inst.rs2 as usize); + match inst.funct3 { + RISCV_FP_MINMAX_MIN => machine.fp_reg.set_reg(inst.rd as usize, if r1 < r2 {r1} else {r2}), + RISCV_FP_MINMAX_MAX => machine.fp_reg.set_reg(inst.rd as usize, if r1 > r2 {r1} else {r2}), + _ => panic!("this instruction ({}) doesn't exists", inst.value) + } + }, + RISCV_FP_FCVTW => { + if inst.rs2 == RISCV_FP_FCVTW_W { + machine.int_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) as i64) + } else { + machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1 as usize) as u64) as i64) + } + }, + RISCV_FP_FCVTS => { + if inst.rs2 == RISCV_FP_FCVTS_W { + machine.fp_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) as f32); + } else { + machine.fp_reg.set_reg(inst.rd as usize, (machine.int_reg.get_reg(inst.rs1 as usize) as u32) as f32); + } + }, + RISCV_FP_FMVW => machine.fp_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) as f32), + RISCV_FP_FMVXFCLASS => { + if inst.funct3 == RISCV_FP_FMVXFCLASS_FMVX { + machine.int_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) as i64); + } else { + panic!("Fclass instruction is not handled in riscv simulator"); + } + }, + RISCV_FP_FCMP => { + match inst.funct3 { + RISCV_FP_FCMP_FEQ => machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1 as usize) == machine.fp_reg.get_reg(inst.rs2 as usize)) as i64), + RISCV_FP_FCMP_FLT => machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1 as usize) < machine.fp_reg.get_reg(inst.rs2 as usize)) as i64), + RISCV_FP_FCMP_FLE => machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1 as usize) <= machine.fp_reg.get_reg(inst.rs2 as usize)) as i64), + _ => panic!("this instruction ({}) doesn't exists", inst.value) + } + }, + _ => panic!("this instruction ({}) doesn't exists", inst.value) + } + Ok(()) } /// print memory FOR DEBUG From 21159d3d98f58dcaaea54c9252508aaaa09d0934 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Thu, 23 Mar 2023 20:54:05 +0100 Subject: [PATCH 04/29] Renamed exceptions to follow CamlCase convention --- src/simulator/machine.rs | 20 +++++++++----------- src/simulator/mmu.rs | 22 +++++++++++----------- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index b785d6b..d90c950 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -11,16 +11,17 @@ use std::fs::File; * Decommenter la variant si il est utilisé quelque part */ pub enum ExceptionType { - NO_EXCEPTION,//Everything ok! + //Everything ok! + NoException, //SYSCALL_EXCEPTION,//A program executed a system call. - PAGEFAULT_EXCEPTION,//Page fault exception - READONLY_EXCEPTION,//Write attempted to a page marked "read-only" */ - BUSERROR_EXCEPTION, + PagefaultException,//Page fault exception + ReadOnlyException,//Write attempted to a page marked "read-only" */ + BusErrorException, /* translation resulted in an invalid physical address (mis-aligned or out-of-bounds) */ - ADDRESSERROR_EXCEPTION, /* Reference that was + AddressErrorException, /* Reference that was not mapped in the address space */ //OVERFLOW_EXCEPTION, //Integer overflow in add or sub. @@ -30,18 +31,15 @@ pub enum ExceptionType { pub const STACK_REG: usize = 2; - pub const NUM_INT_REGS: usize = 32; pub const NUM_FP_REGS: usize = 32; - -//max number of physical page +/// max number of physical pages pub const NUM_PHY_PAGE : u64 = 400; -//doit etre une puissance de deux +/// Must be 2^x pub const PAGE_SIZE : u64 = 128; -//doit etre un multiple de PAGE_SIZE +/// Must be a multiple of PAGE_SIZE pub const MEM_SIZE : usize = (PAGE_SIZE*NUM_PHY_PAGE*100) as usize; - pub trait RegisterNum: Add + Sub + PartialEq + Copy {} impl RegisterNum for i64 {} diff --git a/src/simulator/mmu.rs b/src/simulator/mmu.rs index 780e49f..f91dcb0 100644 --- a/src/simulator/mmu.rs +++ b/src/simulator/mmu.rs @@ -29,7 +29,7 @@ impl <'a>MMU <'_>{ MMU::translate(mmu, virt_addr, &mut phy_addr_double_check, false); match exc { - ExceptionType::NO_EXCEPTION => { + ExceptionType::NoException => { if phy_addr != phy_addr_double_check { //Besoin ici d'une impl pour gestion d'exeption //dans nachos : g-machine->RaiseException(exc, virt_addr); @@ -44,7 +44,7 @@ impl <'a>MMU <'_>{ _ => { //Besoin ici d'une impl pour gestion d'exeption //dans nachos : g-machine->RaiseException(exc, virt_addr); - println!("Error from mmu_read_mem :: Exception different from NO_EXCEPTION"); + println!("Error from mmu_read_mem :: Exception different from NoException"); return false; } } @@ -63,7 +63,7 @@ impl <'a>MMU <'_>{ MMU::translate(mmu, virt_addr, &mut phy_addr_double_check, true); match exc { - ExceptionType::NO_EXCEPTION => { + ExceptionType::NoException => { if phy_addr != phy_addr_double_check { //Besoin ici d'une impl pour gestion d'exeption //dans nachos : g-machine->RaiseException(exc, virt_addr); @@ -78,7 +78,7 @@ impl <'a>MMU <'_>{ _ => { //Besoin ici d'une impl pour gestion d'exeption //dans nachos : g-machine->RaiseException(exc, virt_addr); - println!("Error from mmu_write_mem :: Exception different from NO_EXCEPTION"); + println!("Error from mmu_write_mem :: Exception different from NoException"); return false; } } @@ -96,7 +96,7 @@ impl <'a>MMU <'_>{ match &mut mmu.translationTable { None => { println!("Error from translate : MMU refers to None (No page Table)"); - return ExceptionType::ADDRESSERROR_EXCEPTION; + return ExceptionType::AddressErrorException; } Some(table_ref) => { @@ -104,7 +104,7 @@ impl <'a>MMU <'_>{ //On verifie que notre index est valide if vpn >= table_ref.get_max_num_pages(){ println!("Error from translate :: index is out of bound"); - return ExceptionType::ADDRESSERROR_EXCEPTION; + return ExceptionType::AddressErrorException; } /*Doc nachos dit que ce test sert a savoir si la page est mappée @@ -113,13 +113,13 @@ impl <'a>MMU <'_>{ */ if !table_ref.get_bit_read(vpn) && !table_ref.get_bit_write(vpn) { println!("Error from translate :: virtual page # {} not mapped",vpn); - return ExceptionType::ADDRESSERROR_EXCEPTION; + return ExceptionType::AddressErrorException; } //si on souhaite effectuer un acces lecture, on verifie que l'on dispose du droit d'acces sur cette page if writing && !table_ref.get_bit_write(vpn) { println!("Error from translate :: write access on a read only virtual page # {}",vpn); - return ExceptionType::READONLY_EXCEPTION; + return ExceptionType::AddressErrorException; } //if the page is not yet in main memory, run the page fault manager @@ -129,13 +129,13 @@ impl <'a>MMU <'_>{ println!("We need to update the page table by raising an exception -> not implemented"); //Ici il faudra reverifier le bit valid apres intervention du page fault manager - return ExceptionType::ADDRESSERROR_EXCEPTION; + return ExceptionType::AddressErrorException; } //Make sure that the physical adress is correct if table_ref.get_physical_page(vpn) < 0 || table_ref.get_physical_page(vpn) >= (NUM_PHY_PAGE as i32) { println!("Error from translate :: no valid correspondance"); - return ExceptionType::BUSERROR_EXCEPTION; + return ExceptionType::BusErrorException; } //Set U/M bits to 1 @@ -151,6 +151,6 @@ impl <'a>MMU <'_>{ } } - ExceptionType::NO_EXCEPTION + ExceptionType::NoException } } \ No newline at end of file From cc6aab7c3f96a07846d5c541a8c1826fb322b4e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Thu, 23 Mar 2023 20:58:10 +0100 Subject: [PATCH 05/29] Documented ExceptionType --- src/simulator/machine.rs | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index d90c950..ff4c0e0 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -6,27 +6,26 @@ use super::{decode::{Instruction, decode}, interrupt::Interrupt}; use super::global::*; use std::fs::File; - -/* -* Decommenter la variant si il est utilisé quelque part - */ +/// Exceptions +/// todo: is this really supposed to stand in machine.rs? pub enum ExceptionType { - //Everything ok! + /// Everything ok NoException, - //SYSCALL_EXCEPTION,//A program executed a system call. - PagefaultException,//Page fault exception - ReadOnlyException,//Write attempted to a page marked "read-only" */ - BusErrorException, - /* translation resulted - in an invalid physical - address (mis-aligned or - out-of-bounds) */ - AddressErrorException, /* Reference that was - not mapped in the address - space */ - //OVERFLOW_EXCEPTION, //Integer overflow in add or sub. - //ILLEGALINSTR_EXCEPTION, //Unimplemented or reserved instr. - //NUM_EXCEPTION_TYPES + /// A program executed a system call + SyscallException, + /// Page fault exception + PagefaultException, + /// Write attempted to a page marked "read-only" + ReadOnlyException, + /// Translation resulted in an invalid physical address (mis-aligned or out-of-bounds) + BusErrorException, + /// Reference which was not mapped in the address space + AddressErrorException, + /// Integer overflow in add or sub + OverflowException, + /// Unimplemented or reserved instruction + IllegalInstrException, + NumExceptionTypes } From bee0e8ce715253f2413be06dc62348d548ba2737 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Thu, 23 Mar 2023 21:55:46 +0100 Subject: [PATCH 06/29] :memo: Documentation updates for machine.rs --- src/simulator/machine.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index ff4c0e0..a2c8046 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -109,6 +109,7 @@ pub struct Machine { impl Machine { + /// Machine constructor pub fn init_machine() -> Machine { let mut shiftmask : [u64 ; 64] = [0 ; 64]; let mut value : u64 = 0xffffffff; @@ -195,6 +196,11 @@ impl Machine { }; } + /// Print the status of the machine to the standard output + /// + /// ### Parameters + /// + /// - **machine** the machine to get the status from pub fn print_machine_status(machine: &mut Machine) { println!("######### Machine status #########"); for i in (0..32).step_by(3) { @@ -213,6 +219,11 @@ impl Machine { println!("##################################"); } + /// Get the state of the registers as a string + /// + /// ### Parameters + /// + /// - **machine** the machine to read the registers from pub fn string_registers(machine: &mut Machine) -> String { let mut s = String::from(""); for i in 0..32 { @@ -554,7 +565,8 @@ impl Machine { } else { machine.fp_reg.set_reg(inst.rd as usize, -local_float) }, - RISCV_FP_FSGN_JX => if (machine.fp_reg.get_reg(inst.rs2 as usize) < 0.0 && machine.fp_reg.get_reg(inst.rs1 as usize) >= 0.0) || (machine.fp_reg.get_reg(inst.rs2 as usize) >= 0.0 && machine.fp_reg.get_reg(inst.rs1 as usize) < 0.0) { + RISCV_FP_FSGN_JX => if (machine.fp_reg.get_reg(inst.rs2 as usize) < 0.0 && machine.fp_reg.get_reg(inst.rs1 as usize) >= 0.0) || + (machine.fp_reg.get_reg(inst.rs2 as usize) >= 0.0 && machine.fp_reg.get_reg(inst.rs1 as usize) < 0.0) { machine.fp_reg.set_reg(inst.rd as usize, -local_float) } else { machine.fp_reg.set_reg(inst.rd as usize, local_float) @@ -608,7 +620,7 @@ impl Machine { /// print memory FOR DEBUG /// - /// "@"adresse [16 bytes] + /// "@"adress [16 bytes] pub fn _print_memory(machine : &mut Machine, from: usize, to: usize) { for i in from..to { if i%16 == 0 { @@ -619,18 +631,22 @@ impl Machine { println!(); } + /// Get value from int register pub fn read_int_register(&self, index: usize) -> i64 { self.int_reg.get_reg(index) } + /// Get value from float register pub fn read_fp_register(&self, index: usize) -> f32 { self.fp_reg.get_reg(index) } + /// Write into int register pub fn write_int_register(&mut self, index: usize, value: i64) { self.int_reg.set_reg(index, value); } + /// Write info float register pub fn write_fp_register(&mut self, index: usize, value: f32) { self.fp_reg.set_reg(index, value); } From c74c99499eaf3b17b83efd6148bebdb6548e0bb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Fri, 24 Mar 2023 17:32:04 +0100 Subject: [PATCH 07/29] :recycle: Removed loads of casts to usize --- src/simulator/machine.rs | 152 +++++++++++++++++++-------------------- 1 file changed, 76 insertions(+), 76 deletions(-) diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index a2c8046..2cc98ad 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -53,8 +53,8 @@ pub struct Register { impl Register { - pub fn get_reg(&self, position: usize) -> U { - self.register[position] + pub fn get_reg(&self, position: u8) -> U { + self.register[position as usize] } } @@ -203,11 +203,11 @@ impl Machine { /// - **machine** the machine to get the status from pub fn print_machine_status(machine: &mut Machine) { println!("######### Machine status #########"); - for i in (0..32).step_by(3) { - print!(">{0: <4} : {1:<16x} ", print::REG_X[i], machine.int_reg.get_reg(i)); - print!(">{0: <4} : {1:<16x} ", print::REG_X[i+1], machine.int_reg.get_reg(i+1)); + for i in (0..32 as usize).step_by(3) { + print!(">{0: <4} : {1:<16x} ", print::REG_X[i], machine.int_reg.get_reg(i as u8)); + print!(">{0: <4} : {1:<16x} ", print::REG_X[i+1], machine.int_reg.get_reg((i+1) as u8)); if i+2 < 32 { - print!(">{0: <4} : {1:<16x} ", print::REG_X[i+2], machine.int_reg.get_reg(i+2)); + print!(">{0: <4} : {1:<16x} ", print::REG_X[i+2], machine.int_reg.get_reg((i+2) as u8)); } println!(); } @@ -283,7 +283,7 @@ impl Machine { }, RISCV_JALR => { let tmp = machine.pc; - machine.pc = (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_I_signed as i64) as u64 & 0xfffffffe; + machine.pc = (machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as u64 & 0xfffffffe; machine.int_reg.set_reg(inst.rd as usize, tmp as i64); Ok(()) }, @@ -328,32 +328,32 @@ impl Machine { fn branch_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { match inst.funct3 { RISCV_BR_BEQ => { - if machine.int_reg.get_reg(inst.rs1 as usize) == machine.int_reg.get_reg(inst.rs2 as usize) { + if machine.int_reg.get_reg(inst.rs1) == machine.int_reg.get_reg(inst.rs2) { machine.pc = (machine.pc as i64 + inst.imm13_signed as i64 - 4) as u64; } }, RISCV_BR_BNE => { - if machine.int_reg.get_reg(inst.rs1 as usize) != machine.int_reg.get_reg(inst.rs2 as usize) { + if machine.int_reg.get_reg(inst.rs1) != machine.int_reg.get_reg(inst.rs2) { machine.pc = (machine.pc as i64 + inst.imm13_signed as i64 - 4) as u64; } }, RISCV_BR_BLT => { - if machine.int_reg.get_reg(inst.rs1 as usize) < machine.int_reg.get_reg(inst.rs2 as usize) { + if machine.int_reg.get_reg(inst.rs1) < machine.int_reg.get_reg(inst.rs2) { machine.pc = (machine.pc as i64 + inst.imm13_signed as i64 - 4) as u64; } }, RISCV_BR_BGE => { - if machine.int_reg.get_reg(inst.rs1 as usize) >= machine.int_reg.get_reg(inst.rs2 as usize) { + if machine.int_reg.get_reg(inst.rs1) >= machine.int_reg.get_reg(inst.rs2) { machine.pc = (machine.pc as i64 + inst.imm13_signed as i64 - 4) as u64; } }, RISCV_BR_BLTU => { - if machine.int_reg.get_reg(inst.rs1 as usize) < machine.int_reg.get_reg(inst.rs2 as usize) { + if machine.int_reg.get_reg(inst.rs1) < machine.int_reg.get_reg(inst.rs2) { machine.pc = (machine.pc as i64 + inst.imm13_signed as i64 - 4) as u64; } }, RISCV_BR_BGEU => { - if machine.int_reg.get_reg(inst.rs1 as usize) >= machine.int_reg.get_reg(inst.rs2 as usize) { + if machine.int_reg.get_reg(inst.rs1) >= machine.int_reg.get_reg(inst.rs2) { machine.pc = (machine.pc as i64 + inst.imm13_signed as i64 - 4) as u64; } }, @@ -368,19 +368,19 @@ impl Machine { fn load_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { match inst.funct3 { RISCV_LD_LB | RISCV_LD_LBU => { - let tmp = Self::read_memory(machine, 1, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_I_signed as i64) as usize) as i64; + let tmp = Self::read_memory(machine, 1, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; machine.int_reg.set_reg(inst.rd as usize, tmp); }, RISCV_LD_LH | RISCV_LD_LHU => { - let tmp = Self::read_memory(machine, 2, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_I_signed as i64) as usize) as i64; + let tmp = Self::read_memory(machine, 2, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; machine.int_reg.set_reg(inst.rd as usize, tmp); }, RISCV_LD_LW | RISCV_LD_LWU => { - let tmp = Self::read_memory(machine, 4, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_I_signed as i64) as usize) as i64; + let tmp = Self::read_memory(machine, 4, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; machine.int_reg.set_reg(inst.rd as usize, tmp); }, RISCV_LD_LD => { - let tmp = Self::read_memory(machine, 8, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_I_signed as i64) as usize) as i64; + let tmp = Self::read_memory(machine, 8, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; machine.int_reg.set_reg(inst.rd as usize, tmp); }, _ => panic!("In LD switch case, this should never happen... Instr was {}", inst.value) @@ -391,10 +391,10 @@ impl Machine { /// Executes RISC-V Store Instructions on the machine fn store_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { match inst.funct3 { - RISCV_ST_STB => Self::write_memory(machine, 1, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2 as usize) as u64), - RISCV_ST_STH => Self::write_memory(machine, 2, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2 as usize) as u64), - RISCV_ST_STW => Self::write_memory(machine, 4, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2 as usize) as u64), - RISCV_ST_STD => Self::write_memory(machine, 8, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2 as usize) as u64), + RISCV_ST_STB => Self::write_memory(machine, 1, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2) as u64), + RISCV_ST_STH => Self::write_memory(machine, 2, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2) as u64), + RISCV_ST_STW => Self::write_memory(machine, 4, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2) as u64), + RISCV_ST_STD => Self::write_memory(machine, 8, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2) as u64), _ => panic!("In ST switch case, this should never happen... Instr was {}", inst.value) } Ok(()) @@ -403,16 +403,16 @@ impl Machine { /// Executes RISC-V Integer Register-Immediate Instructions on the machine fn opi_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { match inst.funct3 { - RISCV_OPI_ADDI => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_I_signed as i64), - RISCV_OPI_SLTI => machine.int_reg.set_reg(inst.rd as usize, (machine.int_reg.get_reg(inst.rs1 as usize) < inst.imm12_I_signed as i64) as i64), - RISCV_OPI_XORI => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) ^ inst.imm12_I_signed as i64), - RISCV_OPI_ORI => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) | inst.imm12_I_signed as i64), - RISCV_OPI_ANDI => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) & inst.imm12_I_signed as i64), - RISCV_OPI_SLLI => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) << inst.shamt), + RISCV_OPI_ADDI => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64), + RISCV_OPI_SLTI => machine.int_reg.set_reg(inst.rd as usize, (machine.int_reg.get_reg(inst.rs1) < inst.imm12_I_signed as i64) as i64), + RISCV_OPI_XORI => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) ^ inst.imm12_I_signed as i64), + RISCV_OPI_ORI => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) | inst.imm12_I_signed as i64), + RISCV_OPI_ANDI => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) & inst.imm12_I_signed as i64), + RISCV_OPI_SLLI => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) << inst.shamt), RISCV_OPI_SRI => if inst.funct7_smaller == RISCV_OPI_SRI_SRLI { - machine.int_reg.set_reg(inst.rd as usize, (machine.int_reg.get_reg(inst.rs1 as usize) >> inst.shamt) & machine.shiftmask[inst.shamt as usize] as i64); + machine.int_reg.set_reg(inst.rd as usize, (machine.int_reg.get_reg(inst.rs1) >> inst.shamt) & machine.shiftmask[inst.shamt as usize] as i64); } else { // SRAI - machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) >> inst.shamt); + machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) >> inst.shamt); }, _ => panic!("In OPI switch case, this should never happen... Instr was %x\n {}", inst.value) } @@ -427,53 +427,53 @@ impl Machine { if inst.funct7 == 1 { match inst.funct3 { RISCV_OP_M_MUL => { - long_result = (machine.int_reg.get_reg(inst.rs1 as usize) * machine.int_reg.get_reg(inst.rs2 as usize)) as i128; + long_result = (machine.int_reg.get_reg(inst.rs1) * machine.int_reg.get_reg(inst.rs2)) as i128; machine.int_reg.set_reg(inst.rd as usize, (long_result & 0xffffffffffffffff) as i64) }, RISCV_OP_M_MULH => { - long_result = (machine.int_reg.get_reg(inst.rs1 as usize) * machine.int_reg.get_reg(inst.rs2 as usize)) as i128; + long_result = (machine.int_reg.get_reg(inst.rs1) * machine.int_reg.get_reg(inst.rs2)) as i128; machine.int_reg.set_reg(inst.rd as usize, ((long_result >> 64) & 0xffffffffffffffff) as i64) }, RISCV_OP_M_MULHSU => { - unsigned_reg2 = machine.int_reg.get_reg(inst.rs2 as usize) as u64; - long_result = (machine.int_reg.get_reg(inst.rs1 as usize) as u64 * unsigned_reg2) as i128; + unsigned_reg2 = machine.int_reg.get_reg(inst.rs2) as u64; + long_result = (machine.int_reg.get_reg(inst.rs1) as u64 * unsigned_reg2) as i128; machine.int_reg.set_reg(inst.rd as usize, ((long_result >> 64) & 0xffffffffffffffff) as i64) }, RISCV_OP_M_MULHU => { - unsigned_reg1 = machine.int_reg.get_reg(inst.rs1 as usize) as u64; - unsigned_reg2 = machine.int_reg.get_reg(inst.rs2 as usize) as u64; + unsigned_reg1 = machine.int_reg.get_reg(inst.rs1) as u64; + unsigned_reg2 = machine.int_reg.get_reg(inst.rs2) as u64; long_result = (unsigned_reg1 * unsigned_reg2) as i128; machine.int_reg.set_reg(inst.rd as usize, ((long_result >> 64) & 0xffffffffffffffff) as i64); }, - RISCV_OP_M_DIV => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) / machine.int_reg.get_reg(inst.rs2 as usize)), + RISCV_OP_M_DIV => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) / machine.int_reg.get_reg(inst.rs2)), _ => panic!("RISCV_OP : funct7 = 1 (Multiplication) :: Error\n") } } else { match inst.funct3 { RISCV_OP_ADD => if inst.funct7 == RISCV_OP_ADD_ADD { - machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) + machine.int_reg.get_reg(inst.rs2 as usize)) + machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) + machine.int_reg.get_reg(inst.rs2)) } else { - machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) - machine.int_reg.get_reg(inst.rs2 as usize)) + machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) - machine.int_reg.get_reg(inst.rs2)) }, - RISCV_OP_SLL => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) << (machine.int_reg.get_reg(inst.rs2 as usize) & 0x3f)), - RISCV_OP_SLT => if machine.int_reg.get_reg(inst.rs1 as usize) < machine.int_reg.get_reg(inst.rs2 as usize) { + RISCV_OP_SLL => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) << (machine.int_reg.get_reg(inst.rs2) & 0x3f)), + RISCV_OP_SLT => if machine.int_reg.get_reg(inst.rs1) < machine.int_reg.get_reg(inst.rs2) { machine.int_reg.set_reg(inst.rd as usize, 1) } else { machine.int_reg.set_reg(inst.rd as usize, 0) }, RISCV_OP_SLTU => { - unsigned_reg1 = machine.int_reg.get_reg(inst.rs1 as usize) as u64; - unsigned_reg2 = machine.int_reg.get_reg(inst.rs2 as usize) as u64; + unsigned_reg1 = machine.int_reg.get_reg(inst.rs1) as u64; + unsigned_reg2 = machine.int_reg.get_reg(inst.rs2) as u64; if unsigned_reg1 < unsigned_reg2 { machine.int_reg.set_reg(inst.rd as usize, 1) } else { machine.int_reg.set_reg(inst.rd as usize, 0) } }, - RISCV_OP_XOR => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) ^ machine.int_reg.get_reg(inst.rs2 as usize)), - RISCV_OP_SR => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) >> machine.int_reg.get_reg(inst.rs2 as usize)), // RISCV_OP_SR_SRL inaccessible - RISCV_OP_OR => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) | machine.int_reg.get_reg(inst.rs2 as usize)), - RISCV_OP_AND => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) & machine.int_reg.get_reg(inst.rs2 as usize)), + RISCV_OP_XOR => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) ^ machine.int_reg.get_reg(inst.rs2)), + RISCV_OP_SR => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) >> machine.int_reg.get_reg(inst.rs2)), // RISCV_OP_SR_SRL inaccessible + RISCV_OP_OR => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) | machine.int_reg.get_reg(inst.rs2)), + RISCV_OP_AND => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) & machine.int_reg.get_reg(inst.rs2)), _ => panic!("RISCV_OP undefined case\n") } } @@ -482,7 +482,7 @@ impl Machine { /// Exectutes simple RISC-V *iw instructions on the machine fn opiw_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { - let local_data = machine.int_reg.get_reg(inst.rs1 as usize); + let local_data = machine.int_reg.get_reg(inst.rs1); match inst.funct3 { RISCV_OPIW_ADDIW => { let result = local_data + inst.imm12_I_signed as i64; @@ -508,10 +508,10 @@ impl Machine { /// Executes simple RISC-V *w instructions on the machine fn opw_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { if inst.funct7 == 1 { // rv64m - let local_data_a = machine.int_reg.get_reg(inst.rs1 as usize) & 0xffffffff; - let local_data_b = machine.int_reg.get_reg(inst.rs2 as usize) & 0xffffffff; - let local_data_a_unsigned = machine.int_reg.get_reg(inst.rs1 as usize) & 0xffffffff; - let local_data_b_unsigned = machine.int_reg.get_reg(inst.rs2 as usize) & 0xffffffff; + let local_data_a = machine.int_reg.get_reg(inst.rs1) & 0xffffffff; + let local_data_b = machine.int_reg.get_reg(inst.rs2) & 0xffffffff; + let local_data_a_unsigned = machine.int_reg.get_reg(inst.rs1) & 0xffffffff; + let local_data_b_unsigned = machine.int_reg.get_reg(inst.rs2) & 0xffffffff; // Match case for multiplication operations (in standard extension RV32M) match inst.funct3 { @@ -523,8 +523,8 @@ impl Machine { _ => panic!("this instruction ({}) doesn't exists", inst.value) } } else { // others rv64 OPW operations - let local_dataa = machine.int_reg.get_reg(inst.rs1 as usize) & 0xffffffff; - let local_datab = machine.int_reg.get_reg(inst.rs2 as usize) & 0xffffffff; + let local_dataa = machine.int_reg.get_reg(inst.rs1) & 0xffffffff; + let local_datab = machine.int_reg.get_reg(inst.rs2) & 0xffffffff; // Match case for base OP operation match inst.funct3 { RISCV_OPW_ADDSUBW => if inst.funct7 == RISCV_OPW_ADDSUBW_ADDW { @@ -547,26 +547,26 @@ impl Machine { /// Executes simple RISC-V floating point instructions on the machine fn fp_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { match inst.funct7 { - RISCV_FP_ADD => machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) + machine.fp_reg.get_reg(inst.rs2 as usize)), - RISCV_FP_SUB => machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) - machine.fp_reg.get_reg(inst.rs2 as usize)), - RISCV_FP_MUL => machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) * machine.fp_reg.get_reg(inst.rs2 as usize)), - RISCV_FP_DIV => machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) / machine.fp_reg.get_reg(inst.rs2 as usize)), - RISCV_FP_SQRT => machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize).sqrt()), + RISCV_FP_ADD => machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1) + machine.fp_reg.get_reg(inst.rs2)), + RISCV_FP_SUB => machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1) - machine.fp_reg.get_reg(inst.rs2)), + RISCV_FP_MUL => machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1) * machine.fp_reg.get_reg(inst.rs2)), + RISCV_FP_DIV => machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1) / machine.fp_reg.get_reg(inst.rs2)), + RISCV_FP_SQRT => machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1).sqrt()), RISCV_FP_FSGN => { - let local_float = machine.fp_reg.get_reg(inst.rs1 as usize); + let local_float = machine.fp_reg.get_reg(inst.rs1); match inst.funct3 { - RISCV_FP_FSGN_J => if machine.fp_reg.get_reg(inst.rs2 as usize) < 0f32 { + RISCV_FP_FSGN_J => if machine.fp_reg.get_reg(inst.rs2) < 0f32 { machine.fp_reg.set_reg(inst.rd as usize, -local_float) } else { machine.fp_reg.set_reg(inst.rd as usize, local_float) }, - RISCV_FP_FSGN_JN => if machine.fp_reg.get_reg(inst.rs2 as usize) < 0f32 { + RISCV_FP_FSGN_JN => if machine.fp_reg.get_reg(inst.rs2) < 0f32 { machine.fp_reg.set_reg(inst.rd as usize, local_float) } else { machine.fp_reg.set_reg(inst.rd as usize, -local_float) }, - RISCV_FP_FSGN_JX => if (machine.fp_reg.get_reg(inst.rs2 as usize) < 0.0 && machine.fp_reg.get_reg(inst.rs1 as usize) >= 0.0) || - (machine.fp_reg.get_reg(inst.rs2 as usize) >= 0.0 && machine.fp_reg.get_reg(inst.rs1 as usize) < 0.0) { + RISCV_FP_FSGN_JX => if (machine.fp_reg.get_reg(inst.rs2) < 0.0 && machine.fp_reg.get_reg(inst.rs1) >= 0.0) || + (machine.fp_reg.get_reg(inst.rs2) >= 0.0 && machine.fp_reg.get_reg(inst.rs1) < 0.0) { machine.fp_reg.set_reg(inst.rd as usize, -local_float) } else { machine.fp_reg.set_reg(inst.rd as usize, local_float) @@ -575,8 +575,8 @@ impl Machine { } }, RISCV_FP_MINMAX => { - let r1 = machine.fp_reg.get_reg(inst.rs1 as usize); - let r2 = machine.fp_reg.get_reg(inst.rs2 as usize); + let r1 = machine.fp_reg.get_reg(inst.rs1); + let r2 = machine.fp_reg.get_reg(inst.rs2); match inst.funct3 { RISCV_FP_MINMAX_MIN => machine.fp_reg.set_reg(inst.rd as usize, if r1 < r2 {r1} else {r2}), RISCV_FP_MINMAX_MAX => machine.fp_reg.set_reg(inst.rd as usize, if r1 > r2 {r1} else {r2}), @@ -585,31 +585,31 @@ impl Machine { }, RISCV_FP_FCVTW => { if inst.rs2 == RISCV_FP_FCVTW_W { - machine.int_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) as i64) + machine.int_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1) as i64) } else { - machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1 as usize) as u64) as i64) + machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1) as u64) as i64) } }, RISCV_FP_FCVTS => { if inst.rs2 == RISCV_FP_FCVTS_W { - machine.fp_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) as f32); + machine.fp_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) as f32); } else { - machine.fp_reg.set_reg(inst.rd as usize, (machine.int_reg.get_reg(inst.rs1 as usize) as u32) as f32); + machine.fp_reg.set_reg(inst.rd as usize, (machine.int_reg.get_reg(inst.rs1) as u32) as f32); } }, - RISCV_FP_FMVW => machine.fp_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) as f32), + RISCV_FP_FMVW => machine.fp_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) as f32), RISCV_FP_FMVXFCLASS => { if inst.funct3 == RISCV_FP_FMVXFCLASS_FMVX { - machine.int_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) as i64); + machine.int_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1) as i64); } else { panic!("Fclass instruction is not handled in riscv simulator"); } }, RISCV_FP_FCMP => { match inst.funct3 { - RISCV_FP_FCMP_FEQ => machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1 as usize) == machine.fp_reg.get_reg(inst.rs2 as usize)) as i64), - RISCV_FP_FCMP_FLT => machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1 as usize) < machine.fp_reg.get_reg(inst.rs2 as usize)) as i64), - RISCV_FP_FCMP_FLE => machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1 as usize) <= machine.fp_reg.get_reg(inst.rs2 as usize)) as i64), + RISCV_FP_FCMP_FEQ => machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1) == machine.fp_reg.get_reg(inst.rs2)) as i64), + RISCV_FP_FCMP_FLT => machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1) < machine.fp_reg.get_reg(inst.rs2)) as i64), + RISCV_FP_FCMP_FLE => machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1) <= machine.fp_reg.get_reg(inst.rs2)) as i64), _ => panic!("this instruction ({}) doesn't exists", inst.value) } }, @@ -633,12 +633,12 @@ impl Machine { /// Get value from int register pub fn read_int_register(&self, index: usize) -> i64 { - self.int_reg.get_reg(index) + self.int_reg.get_reg(index as u8) } /// Get value from float register pub fn read_fp_register(&self, index: usize) -> f32 { - self.fp_reg.get_reg(index) + self.fp_reg.get_reg(index as u8) } /// Write into int register From 03cc8e17c6f8c837154ca0ea60d04ea300b9b989 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Fri, 24 Mar 2023 17:44:24 +0100 Subject: [PATCH 08/29] :recycle: Simplified imports and moved Register struct to own file --- src/simulator/machine.rs | 72 +++++++-------------------------------- src/simulator/mod.rs | 1 + src/simulator/register.rs | 51 +++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 60 deletions(-) create mode 100644 src/simulator/register.rs diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index 2cc98ad..116a942 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -1,10 +1,15 @@ -use std::{ops::{Add, Sub}, io::Write}; - -use crate::simulator::{print, error::MachineError}; - -use super::{decode::{Instruction, decode}, interrupt::Interrupt}; -use super::global::*; -use std::fs::File; +use std::{ + io::Write, + fs::File +}; +use crate::simulator::{ + print, + error::MachineError, + decode::*, + interrupt::Interrupt, + global::*, + register::* +}; /// Exceptions /// todo: is this really supposed to stand in machine.rs? @@ -39,59 +44,6 @@ pub const PAGE_SIZE : u64 = 128; /// Must be a multiple of PAGE_SIZE pub const MEM_SIZE : usize = (PAGE_SIZE*NUM_PHY_PAGE*100) as usize; -pub trait RegisterNum: Add + Sub + PartialEq + Copy {} - -impl RegisterNum for i64 {} - -impl RegisterNum for f32 {} - - -#[derive(PartialEq)] -pub struct Register { - register: [U; 32] -} - -impl Register { - - pub fn get_reg(&self, position: u8) -> U { - self.register[position as usize] - } - -} - -impl Register { - - pub fn init() -> Register { - Register { - register: [0i64; 32] - } - } - - pub fn set_reg(&mut self, position: usize, value: i64) { - if position != 0 { - self.register[position] = value; - } else { - // Panic ou rien ? (dans le doute pour le moment panic) - // unreachable!("You can't write to zero register") - } - } - -} - -impl Register { - - pub fn init() -> Register { - Register { - register: [0f32; 32] - } - } - - pub fn set_reg(&mut self, position: usize, value: f32) { - self.register[position] = value; - } - -} - #[derive(PartialEq)] pub struct Machine { pub pc : u64, diff --git a/src/simulator/mod.rs b/src/simulator/mod.rs index e13df71..956ee64 100644 --- a/src/simulator/mod.rs +++ b/src/simulator/mod.rs @@ -7,6 +7,7 @@ pub mod loader; pub mod interrupt; pub mod translationtable; pub mod mmu; +pub mod register; pub mod global { diff --git a/src/simulator/register.rs b/src/simulator/register.rs new file mode 100644 index 0000000..d352d74 --- /dev/null +++ b/src/simulator/register.rs @@ -0,0 +1,51 @@ +use std::ops::{Add, Sub}; + +pub trait RegisterNum: Add + Sub + PartialEq + Copy {} + +impl RegisterNum for i64 {} + +impl RegisterNum for f32 {} + +/// Machine register array +#[derive(PartialEq)] +pub struct Register { + /// 32 available registers of type U + register: [U; 32] +} + +impl Register { + + /// Returns the current value held in register *position* + pub fn get_reg(&self, position: u8) -> U { + self.register[position as usize] + } + + /// Set value of register *position* to *value* + pub fn set_reg(&mut self, position: usize, value: U) { + self.register[position] = value; + } + + +} + +impl Register { + + /// i64 register constructor + pub fn init() -> Register { + Register { + register: [0i64; 32] + } + } + +} + +impl Register { + + /// f32 register constructor + pub fn init() -> Register { + Register { + register: [0f32; 32] + } + } + +} \ No newline at end of file From 228d58655a7771ee9b47e68b4c94b0402df19958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Fri, 24 Mar 2023 17:56:37 +0100 Subject: [PATCH 09/29] :bug: Fixed missing check for position 0 --- src/simulator/register.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/simulator/register.rs b/src/simulator/register.rs index d352d74..4cbe50d 100644 --- a/src/simulator/register.rs +++ b/src/simulator/register.rs @@ -22,7 +22,7 @@ impl Register { /// Set value of register *position* to *value* pub fn set_reg(&mut self, position: usize, value: U) { - self.register[position] = value; + if position != 0 { self.register[position] = value; } } From 928628c305082cd64eb5eaaf2945301ea2d5bf89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Fri, 24 Mar 2023 18:11:37 +0100 Subject: [PATCH 10/29] :memo: Documentation updates --- src/simulator/error.rs | 1 + src/simulator/machine.rs | 13 +++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/simulator/error.rs b/src/simulator/error.rs index 42db367..4794315 100644 --- a/src/simulator/error.rs +++ b/src/simulator/error.rs @@ -10,6 +10,7 @@ pub struct MachineError { impl MachineError { + /// MachineError constructor pub fn new(message: &str) -> MachineError { MachineError { message: message.to_string() diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index 116a942..6b5e64b 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -33,9 +33,10 @@ pub enum ExceptionType { NumExceptionTypes } - pub const STACK_REG: usize = 2; +/// Number of available Integer registers pub const NUM_INT_REGS: usize = 32; +/// Number of available Floating Point registers pub const NUM_FP_REGS: usize = 32; /// max number of physical pages pub const NUM_PHY_PAGE : u64 = 400; @@ -44,15 +45,23 @@ pub const PAGE_SIZE : u64 = 128; /// Must be a multiple of PAGE_SIZE pub const MEM_SIZE : usize = (PAGE_SIZE*NUM_PHY_PAGE*100) as usize; -#[derive(PartialEq)] +/// RISC-V Simulator pub struct Machine { + /// Program counter pub pc : u64, + /// Stack pointer pub sp: usize, + /// Integer register pub int_reg : Register, + /// Floating point register pub fp_reg : Register, + /// Heap memory pub main_memory : Vec, + /// Shiftmask pub shiftmask : [u64 ; 64], + /// Debug data pub registers_trace : String, // for tests + /// todo: document Interrupts pub interrupt: Interrupt // futur taille à calculer int memSize = g_cfg->NumPhysPages * g_cfg->PageSize; //creer une struct cfg(configuration) qui s'initialise avec valeur dans un fichier cfg From 35fdb1e0b0bf7107860100809c507c9fe0fb7e19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Fri, 24 Mar 2023 18:13:18 +0100 Subject: [PATCH 11/29] :memo: :recycle: Doc updates & Registers are now sized from consts --- src/simulator/register.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/simulator/register.rs b/src/simulator/register.rs index 4cbe50d..2f78d30 100644 --- a/src/simulator/register.rs +++ b/src/simulator/register.rs @@ -1,3 +1,5 @@ +use crate::simulator::machine::{NUM_FP_REGS, NUM_INT_REGS}; + use std::ops::{Add, Sub}; pub trait RegisterNum: Add + Sub + PartialEq + Copy {} @@ -20,7 +22,10 @@ impl Register { self.register[position as usize] } - /// Set value of register *position* to *value* + /// Set value of register *position* to *value* + /// + /// Checking against trying to set a new value to the 0th register + /// as its value is NOT supposed to change pub fn set_reg(&mut self, position: usize, value: U) { if position != 0 { self.register[position] = value; } } @@ -33,7 +38,7 @@ impl Register { /// i64 register constructor pub fn init() -> Register { Register { - register: [0i64; 32] + register: [0i64; NUM_INT_REGS] } } @@ -44,7 +49,7 @@ impl Register { /// f32 register constructor pub fn init() -> Register { Register { - register: [0f32; 32] + register: [0f32; NUM_FP_REGS] } } From 7bdde709895cec79e0d19a3fb4b3c3d34de4aa29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Fri, 24 Mar 2023 18:20:59 +0100 Subject: [PATCH 12/29] :recycle: Removed tons of casts to usize --- src/simulator/machine.rs | 138 +++++++++++++++++++------------------- src/simulator/register.rs | 4 +- 2 files changed, 71 insertions(+), 71 deletions(-) diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index 6b5e64b..c9c1877 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -230,22 +230,22 @@ impl Machine { match inst.opcode { RISCV_LUI => { - machine.int_reg.set_reg(inst.rd as usize, inst.imm31_12 as i64); + machine.int_reg.set_reg(inst.rd, inst.imm31_12 as i64); Ok(()) }, RISCV_AUIPC => { - machine.int_reg.set_reg(inst.rd as usize,machine.pc as i64 - 4 + inst.imm31_12 as i64); + machine.int_reg.set_reg(inst.rd,machine.pc as i64 - 4 + inst.imm31_12 as i64); Ok(()) }, RISCV_JAL => { - machine.int_reg.set_reg(inst.rd as usize, machine.pc as i64); + machine.int_reg.set_reg(inst.rd, machine.pc as i64); machine.pc = (machine.pc as i64 + inst.imm21_1_signed as i64 - 4) as u64; Ok(()) }, RISCV_JALR => { let tmp = machine.pc; machine.pc = (machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as u64 & 0xfffffffe; - machine.int_reg.set_reg(inst.rd as usize, tmp as i64); + machine.int_reg.set_reg(inst.rd, tmp as i64); Ok(()) }, // Treatment for: BRANCH INSTRUCTIONS @@ -330,19 +330,19 @@ impl Machine { match inst.funct3 { RISCV_LD_LB | RISCV_LD_LBU => { let tmp = Self::read_memory(machine, 1, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; - machine.int_reg.set_reg(inst.rd as usize, tmp); + machine.int_reg.set_reg(inst.rd, tmp); }, RISCV_LD_LH | RISCV_LD_LHU => { let tmp = Self::read_memory(machine, 2, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; - machine.int_reg.set_reg(inst.rd as usize, tmp); + machine.int_reg.set_reg(inst.rd, tmp); }, RISCV_LD_LW | RISCV_LD_LWU => { let tmp = Self::read_memory(machine, 4, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; - machine.int_reg.set_reg(inst.rd as usize, tmp); + machine.int_reg.set_reg(inst.rd, tmp); }, RISCV_LD_LD => { let tmp = Self::read_memory(machine, 8, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; - machine.int_reg.set_reg(inst.rd as usize, tmp); + machine.int_reg.set_reg(inst.rd, tmp); }, _ => panic!("In LD switch case, this should never happen... Instr was {}", inst.value) } @@ -364,16 +364,16 @@ impl Machine { /// Executes RISC-V Integer Register-Immediate Instructions on the machine fn opi_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { match inst.funct3 { - RISCV_OPI_ADDI => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64), - RISCV_OPI_SLTI => machine.int_reg.set_reg(inst.rd as usize, (machine.int_reg.get_reg(inst.rs1) < inst.imm12_I_signed as i64) as i64), - RISCV_OPI_XORI => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) ^ inst.imm12_I_signed as i64), - RISCV_OPI_ORI => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) | inst.imm12_I_signed as i64), - RISCV_OPI_ANDI => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) & inst.imm12_I_signed as i64), - RISCV_OPI_SLLI => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) << inst.shamt), + RISCV_OPI_ADDI => machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64), + RISCV_OPI_SLTI => machine.int_reg.set_reg(inst.rd, (machine.int_reg.get_reg(inst.rs1) < inst.imm12_I_signed as i64) as i64), + RISCV_OPI_XORI => machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) ^ inst.imm12_I_signed as i64), + RISCV_OPI_ORI => machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) | inst.imm12_I_signed as i64), + RISCV_OPI_ANDI => machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) & inst.imm12_I_signed as i64), + RISCV_OPI_SLLI => machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) << inst.shamt), RISCV_OPI_SRI => if inst.funct7_smaller == RISCV_OPI_SRI_SRLI { - machine.int_reg.set_reg(inst.rd as usize, (machine.int_reg.get_reg(inst.rs1) >> inst.shamt) & machine.shiftmask[inst.shamt as usize] as i64); + machine.int_reg.set_reg(inst.rd, (machine.int_reg.get_reg(inst.rs1) >> inst.shamt) & machine.shiftmask[inst.shamt as usize] as i64); } else { // SRAI - machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) >> inst.shamt); + machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) >> inst.shamt); }, _ => panic!("In OPI switch case, this should never happen... Instr was %x\n {}", inst.value) } @@ -389,52 +389,52 @@ impl Machine { match inst.funct3 { RISCV_OP_M_MUL => { long_result = (machine.int_reg.get_reg(inst.rs1) * machine.int_reg.get_reg(inst.rs2)) as i128; - machine.int_reg.set_reg(inst.rd as usize, (long_result & 0xffffffffffffffff) as i64) + machine.int_reg.set_reg(inst.rd, (long_result & 0xffffffffffffffff) as i64) }, RISCV_OP_M_MULH => { long_result = (machine.int_reg.get_reg(inst.rs1) * machine.int_reg.get_reg(inst.rs2)) as i128; - machine.int_reg.set_reg(inst.rd as usize, ((long_result >> 64) & 0xffffffffffffffff) as i64) + machine.int_reg.set_reg(inst.rd, ((long_result >> 64) & 0xffffffffffffffff) as i64) }, RISCV_OP_M_MULHSU => { unsigned_reg2 = machine.int_reg.get_reg(inst.rs2) as u64; long_result = (machine.int_reg.get_reg(inst.rs1) as u64 * unsigned_reg2) as i128; - machine.int_reg.set_reg(inst.rd as usize, ((long_result >> 64) & 0xffffffffffffffff) as i64) + machine.int_reg.set_reg(inst.rd, ((long_result >> 64) & 0xffffffffffffffff) as i64) }, RISCV_OP_M_MULHU => { unsigned_reg1 = machine.int_reg.get_reg(inst.rs1) as u64; unsigned_reg2 = machine.int_reg.get_reg(inst.rs2) as u64; long_result = (unsigned_reg1 * unsigned_reg2) as i128; - machine.int_reg.set_reg(inst.rd as usize, ((long_result >> 64) & 0xffffffffffffffff) as i64); + machine.int_reg.set_reg(inst.rd, ((long_result >> 64) & 0xffffffffffffffff) as i64); }, - RISCV_OP_M_DIV => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) / machine.int_reg.get_reg(inst.rs2)), + RISCV_OP_M_DIV => machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) / machine.int_reg.get_reg(inst.rs2)), _ => panic!("RISCV_OP : funct7 = 1 (Multiplication) :: Error\n") } } else { match inst.funct3 { RISCV_OP_ADD => if inst.funct7 == RISCV_OP_ADD_ADD { - machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) + machine.int_reg.get_reg(inst.rs2)) + machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) + machine.int_reg.get_reg(inst.rs2)) } else { - machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) - machine.int_reg.get_reg(inst.rs2)) + machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) - machine.int_reg.get_reg(inst.rs2)) }, - RISCV_OP_SLL => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) << (machine.int_reg.get_reg(inst.rs2) & 0x3f)), + RISCV_OP_SLL => machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) << (machine.int_reg.get_reg(inst.rs2) & 0x3f)), RISCV_OP_SLT => if machine.int_reg.get_reg(inst.rs1) < machine.int_reg.get_reg(inst.rs2) { - machine.int_reg.set_reg(inst.rd as usize, 1) + machine.int_reg.set_reg(inst.rd, 1) } else { - machine.int_reg.set_reg(inst.rd as usize, 0) + machine.int_reg.set_reg(inst.rd, 0) }, RISCV_OP_SLTU => { unsigned_reg1 = machine.int_reg.get_reg(inst.rs1) as u64; unsigned_reg2 = machine.int_reg.get_reg(inst.rs2) as u64; if unsigned_reg1 < unsigned_reg2 { - machine.int_reg.set_reg(inst.rd as usize, 1) + machine.int_reg.set_reg(inst.rd, 1) } else { - machine.int_reg.set_reg(inst.rd as usize, 0) + machine.int_reg.set_reg(inst.rd, 0) } }, - RISCV_OP_XOR => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) ^ machine.int_reg.get_reg(inst.rs2)), - RISCV_OP_SR => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) >> machine.int_reg.get_reg(inst.rs2)), // RISCV_OP_SR_SRL inaccessible - RISCV_OP_OR => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) | machine.int_reg.get_reg(inst.rs2)), - RISCV_OP_AND => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) & machine.int_reg.get_reg(inst.rs2)), + RISCV_OP_XOR => machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) ^ machine.int_reg.get_reg(inst.rs2)), + RISCV_OP_SR => machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) >> machine.int_reg.get_reg(inst.rs2)), // RISCV_OP_SR_SRL inaccessible + RISCV_OP_OR => machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) | machine.int_reg.get_reg(inst.rs2)), + RISCV_OP_AND => machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) & machine.int_reg.get_reg(inst.rs2)), _ => panic!("RISCV_OP undefined case\n") } } @@ -447,11 +447,11 @@ impl Machine { match inst.funct3 { RISCV_OPIW_ADDIW => { let result = local_data + inst.imm12_I_signed as i64; - machine.int_reg.set_reg(inst.rd as usize, result) + machine.int_reg.set_reg(inst.rd, result) }, RISCV_OPIW_SLLIW => { let result = local_data << inst.shamt; - machine.int_reg.set_reg(inst.rd as usize, result) + machine.int_reg.set_reg(inst.rd, result) }, RISCV_OPIW_SRW => { let result = if inst.funct7 == RISCV_OPIW_SRW_SRLIW { @@ -459,7 +459,7 @@ impl Machine { } else { // SRAIW local_data >> inst.shamt }; - machine.int_reg.set_reg(inst.rd as usize, result) + machine.int_reg.set_reg(inst.rd, result) }, _ => panic!("In OPI switch case, this should never happen... Instr was {}\n", inst.value), } @@ -476,11 +476,11 @@ impl Machine { // Match case for multiplication operations (in standard extension RV32M) match inst.funct3 { - RISCV_OPW_M_MULW => machine.int_reg.set_reg(inst.rd as usize, local_data_a * local_data_b), - RISCV_OPW_M_DIVW => machine.int_reg.set_reg(inst.rd as usize, local_data_a / local_data_b), - RISCV_OPW_M_DIVUW => machine.int_reg.set_reg(inst.rd as usize, local_data_a_unsigned / local_data_b_unsigned), - RISCV_OPW_M_REMW => machine.int_reg.set_reg(inst.rd as usize, local_data_a % local_data_b), - RISCV_OPW_M_REMUW => machine.int_reg.set_reg(inst.rd as usize, local_data_a_unsigned % local_data_b_unsigned), + RISCV_OPW_M_MULW => machine.int_reg.set_reg(inst.rd, local_data_a * local_data_b), + RISCV_OPW_M_DIVW => machine.int_reg.set_reg(inst.rd, local_data_a / local_data_b), + RISCV_OPW_M_DIVUW => machine.int_reg.set_reg(inst.rd, local_data_a_unsigned / local_data_b_unsigned), + RISCV_OPW_M_REMW => machine.int_reg.set_reg(inst.rd, local_data_a % local_data_b), + RISCV_OPW_M_REMUW => machine.int_reg.set_reg(inst.rd, local_data_a_unsigned % local_data_b_unsigned), _ => panic!("this instruction ({}) doesn't exists", inst.value) } } else { // others rv64 OPW operations @@ -489,15 +489,15 @@ impl Machine { // Match case for base OP operation match inst.funct3 { RISCV_OPW_ADDSUBW => if inst.funct7 == RISCV_OPW_ADDSUBW_ADDW { - machine.int_reg.set_reg(inst.rd as usize, local_dataa + local_datab); + machine.int_reg.set_reg(inst.rd, local_dataa + local_datab); } else { // SUBW - machine.int_reg.set_reg(inst.rd as usize, local_dataa - local_datab); + machine.int_reg.set_reg(inst.rd, local_dataa - local_datab); }, - RISCV_OPW_SLLW => machine.int_reg.set_reg(inst.rd as usize, local_dataa << (local_datab & 0x1f)), + RISCV_OPW_SLLW => machine.int_reg.set_reg(inst.rd, local_dataa << (local_datab & 0x1f)), RISCV_OPW_SRW => if inst.funct7 == RISCV_OPW_SRW_SRLW { - machine.int_reg.set_reg(inst.rd as usize, local_dataa >> (local_datab & 0x1f) & machine.shiftmask[32 + local_datab as usize] as i64) + machine.int_reg.set_reg(inst.rd, local_dataa >> (local_datab & 0x1f) & machine.shiftmask[32 + local_datab as usize] as i64) } else { // SRAW - machine.int_reg.set_reg(inst.rd as usize, local_dataa >> (local_datab & 0x1f)) + machine.int_reg.set_reg(inst.rd, local_dataa >> (local_datab & 0x1f)) }, _ => panic!("this instruction ({}) doesn't exists", inst.value) } @@ -508,29 +508,29 @@ impl Machine { /// Executes simple RISC-V floating point instructions on the machine fn fp_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { match inst.funct7 { - RISCV_FP_ADD => machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1) + machine.fp_reg.get_reg(inst.rs2)), - RISCV_FP_SUB => machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1) - machine.fp_reg.get_reg(inst.rs2)), - RISCV_FP_MUL => machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1) * machine.fp_reg.get_reg(inst.rs2)), - RISCV_FP_DIV => machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1) / machine.fp_reg.get_reg(inst.rs2)), - RISCV_FP_SQRT => machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1).sqrt()), + RISCV_FP_ADD => machine.fp_reg.set_reg(inst.rd, machine.fp_reg.get_reg(inst.rs1) + machine.fp_reg.get_reg(inst.rs2)), + RISCV_FP_SUB => machine.fp_reg.set_reg(inst.rd, machine.fp_reg.get_reg(inst.rs1) - machine.fp_reg.get_reg(inst.rs2)), + RISCV_FP_MUL => machine.fp_reg.set_reg(inst.rd, machine.fp_reg.get_reg(inst.rs1) * machine.fp_reg.get_reg(inst.rs2)), + RISCV_FP_DIV => machine.fp_reg.set_reg(inst.rd, machine.fp_reg.get_reg(inst.rs1) / machine.fp_reg.get_reg(inst.rs2)), + RISCV_FP_SQRT => machine.fp_reg.set_reg(inst.rd, machine.fp_reg.get_reg(inst.rs1).sqrt()), RISCV_FP_FSGN => { let local_float = machine.fp_reg.get_reg(inst.rs1); match inst.funct3 { RISCV_FP_FSGN_J => if machine.fp_reg.get_reg(inst.rs2) < 0f32 { - machine.fp_reg.set_reg(inst.rd as usize, -local_float) + machine.fp_reg.set_reg(inst.rd, -local_float) } else { - machine.fp_reg.set_reg(inst.rd as usize, local_float) + machine.fp_reg.set_reg(inst.rd, local_float) }, RISCV_FP_FSGN_JN => if machine.fp_reg.get_reg(inst.rs2) < 0f32 { - machine.fp_reg.set_reg(inst.rd as usize, local_float) + machine.fp_reg.set_reg(inst.rd, local_float) } else { - machine.fp_reg.set_reg(inst.rd as usize, -local_float) + machine.fp_reg.set_reg(inst.rd, -local_float) }, RISCV_FP_FSGN_JX => if (machine.fp_reg.get_reg(inst.rs2) < 0.0 && machine.fp_reg.get_reg(inst.rs1) >= 0.0) || (machine.fp_reg.get_reg(inst.rs2) >= 0.0 && machine.fp_reg.get_reg(inst.rs1) < 0.0) { - machine.fp_reg.set_reg(inst.rd as usize, -local_float) + machine.fp_reg.set_reg(inst.rd, -local_float) } else { - machine.fp_reg.set_reg(inst.rd as usize, local_float) + machine.fp_reg.set_reg(inst.rd, local_float) }, _ => panic!("this instruction ({}) doesn't exists", inst.value) } @@ -539,38 +539,38 @@ impl Machine { let r1 = machine.fp_reg.get_reg(inst.rs1); let r2 = machine.fp_reg.get_reg(inst.rs2); match inst.funct3 { - RISCV_FP_MINMAX_MIN => machine.fp_reg.set_reg(inst.rd as usize, if r1 < r2 {r1} else {r2}), - RISCV_FP_MINMAX_MAX => machine.fp_reg.set_reg(inst.rd as usize, if r1 > r2 {r1} else {r2}), + RISCV_FP_MINMAX_MIN => machine.fp_reg.set_reg(inst.rd, if r1 < r2 {r1} else {r2}), + RISCV_FP_MINMAX_MAX => machine.fp_reg.set_reg(inst.rd, if r1 > r2 {r1} else {r2}), _ => panic!("this instruction ({}) doesn't exists", inst.value) } }, RISCV_FP_FCVTW => { if inst.rs2 == RISCV_FP_FCVTW_W { - machine.int_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1) as i64) + machine.int_reg.set_reg(inst.rd, machine.fp_reg.get_reg(inst.rs1) as i64) } else { - machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1) as u64) as i64) + machine.int_reg.set_reg(inst.rd, (machine.fp_reg.get_reg(inst.rs1) as u64) as i64) } }, RISCV_FP_FCVTS => { if inst.rs2 == RISCV_FP_FCVTS_W { - machine.fp_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) as f32); + machine.fp_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) as f32); } else { - machine.fp_reg.set_reg(inst.rd as usize, (machine.int_reg.get_reg(inst.rs1) as u32) as f32); + machine.fp_reg.set_reg(inst.rd, (machine.int_reg.get_reg(inst.rs1) as u32) as f32); } }, - RISCV_FP_FMVW => machine.fp_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1) as f32), + RISCV_FP_FMVW => machine.fp_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) as f32), RISCV_FP_FMVXFCLASS => { if inst.funct3 == RISCV_FP_FMVXFCLASS_FMVX { - machine.int_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1) as i64); + machine.int_reg.set_reg(inst.rd, machine.fp_reg.get_reg(inst.rs1) as i64); } else { panic!("Fclass instruction is not handled in riscv simulator"); } }, RISCV_FP_FCMP => { match inst.funct3 { - RISCV_FP_FCMP_FEQ => machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1) == machine.fp_reg.get_reg(inst.rs2)) as i64), - RISCV_FP_FCMP_FLT => machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1) < machine.fp_reg.get_reg(inst.rs2)) as i64), - RISCV_FP_FCMP_FLE => machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1) <= machine.fp_reg.get_reg(inst.rs2)) as i64), + RISCV_FP_FCMP_FEQ => machine.int_reg.set_reg(inst.rd, (machine.fp_reg.get_reg(inst.rs1) == machine.fp_reg.get_reg(inst.rs2)) as i64), + RISCV_FP_FCMP_FLT => machine.int_reg.set_reg(inst.rd, (machine.fp_reg.get_reg(inst.rs1) < machine.fp_reg.get_reg(inst.rs2)) as i64), + RISCV_FP_FCMP_FLE => machine.int_reg.set_reg(inst.rd, (machine.fp_reg.get_reg(inst.rs1) <= machine.fp_reg.get_reg(inst.rs2)) as i64), _ => panic!("this instruction ({}) doesn't exists", inst.value) } }, @@ -604,12 +604,12 @@ impl Machine { /// Write into int register pub fn write_int_register(&mut self, index: usize, value: i64) { - self.int_reg.set_reg(index, value); + self.int_reg.set_reg(index as u8, value); } /// Write info float register pub fn write_fp_register(&mut self, index: usize, value: f32) { - self.fp_reg.set_reg(index, value); + self.fp_reg.set_reg(index as u8, value); } } diff --git a/src/simulator/register.rs b/src/simulator/register.rs index 2f78d30..a0ef372 100644 --- a/src/simulator/register.rs +++ b/src/simulator/register.rs @@ -26,8 +26,8 @@ impl Register { /// /// Checking against trying to set a new value to the 0th register /// as its value is NOT supposed to change - pub fn set_reg(&mut self, position: usize, value: U) { - if position != 0 { self.register[position] = value; } + pub fn set_reg(&mut self, position: u8, value: U) { + if position != 0 { self.register[position as usize] = value; } } From 88e1921b3cf1584ffe58206fcac84ae72933f819 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Fri, 24 Mar 2023 18:27:28 +0100 Subject: [PATCH 13/29] :recycle: Further simplified tests --- src/simulator/machine.rs | 39 +++++++++++---------------------------- 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index c9c1877..cf6c659 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -638,7 +638,8 @@ mod test { mem_cmp::MemChecker::fill_memory_from_mem_checker(&memory_before, &mut m); Machine::run(&mut m); let expected_trace = fs::read_to_string(get_full_path!("reg_trace", $a)).unwrap(); - (m, memory_after, expected_trace) + assert!(mem_cmp::MemChecker::compare_machine_memory(&memory_after, &m)); + assert!(expected_trace.contains(m.registers_trace.as_str())); }}; } @@ -670,64 +671,46 @@ mod test { #[test] fn test_comp() { - let (m, memory_after, expected_trace) = init_test!("Comp"); - assert!(mem_cmp::MemChecker::compare_machine_memory(&memory_after, &m)); - assert!(expected_trace.contains(m.registers_trace.as_str())); + init_test!("Comp") } #[test] fn test_add() { - let (m, memory_after, expected_trace) = init_test!("Add"); - assert!(mem_cmp::MemChecker::compare_machine_memory(&memory_after, &m)); - assert!(expected_trace.contains(m.registers_trace.as_str())); + init_test!("Add") } #[test] fn test_div() { - let (m, memory_after, expected_trace) = init_test!("Div"); - assert!(mem_cmp::MemChecker::compare_machine_memory(&memory_after, &m)); - assert!(expected_trace.contains(m.registers_trace.as_str())); + init_test!("Div") } #[test] fn test_if() { - let (m, memory_after, expected_trace) = init_test!("If"); - assert!(mem_cmp::MemChecker::compare_machine_memory(&memory_after, &m)); - assert!(expected_trace.contains(m.registers_trace.as_str())); + init_test!("If") } #[test] fn test_jump() { - let (m, memory_after, expected_trace) = init_test!("Jump"); - assert!(mem_cmp::MemChecker::compare_machine_memory(&memory_after, &m)); - assert!(expected_trace.contains(m.registers_trace.as_str())); + init_test!("Jump") } #[test] fn test_mul() { - let (m, memory_after, expected_trace) = init_test!("Mult"); - assert!(mem_cmp::MemChecker::compare_machine_memory(&memory_after, &m)); - assert!(expected_trace.contains(m.registers_trace.as_str())); + init_test!("Mult") } #[test] fn test_ret() { - let (m, memory_after, expected_trace) = init_test!("Ret"); - assert!(mem_cmp::MemChecker::compare_machine_memory(&memory_after, &m)); - assert!(expected_trace.contains(m.registers_trace.as_str())); + init_test!("Ret") } #[test] fn test_sub() { - let (m, memory_after, expected_trace) = init_test!("Sub"); - assert!(mem_cmp::MemChecker::compare_machine_memory(&memory_after, &m)); - assert!(expected_trace.contains(m.registers_trace.as_str())); + init_test!("Sub") } #[test] fn test_switch() { - let (m, memory_after, expected_trace) = init_test!("Switch"); - assert!(mem_cmp::MemChecker::compare_machine_memory(&memory_after, &m)); - assert!(expected_trace.contains(m.registers_trace.as_str())); + init_test!("Switch") } } From b33c31ef3845cff59ba57f0183f40965c185a22e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Fri, 24 Mar 2023 18:34:06 +0100 Subject: [PATCH 14/29] :recycle: Machine::read_memory is now indeed a self method --- src/simulator/machine.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index cf6c659..7f2ccd6 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -105,7 +105,7 @@ impl Machine { /// - **machine** which contains the main memory /// - **size** the number of bytes to read (1, 2, 4, 8) /// - **address** in the memory to read - pub fn read_memory(machine : &mut Machine, size : i32, address : usize) -> u64 { + pub fn read_memory(&self, size : i32, address : usize) -> u64 { if ![1, 2, 4, 8].contains(&size) { panic!("ERROR read_memory : wrong size parameter {size}, must be (1, 2, 4 or 8)"); } @@ -113,7 +113,7 @@ impl Machine { let mut ret: u64 = 0; for i in 0..size { ret <<= 8; - ret += machine.main_memory[address + i as usize] as u64; + ret += self.main_memory[address + i as usize] as u64; } ret } @@ -175,7 +175,7 @@ impl Machine { println!("________________SP________________"); let sp_index = machine.int_reg.get_reg(2); for i in 0..5 { - println!("SP+{:<2} : {:16x}", i*8, Self::read_memory(machine, 8, (sp_index + i*8) as usize)); + println!("SP+{:<2} : {:16x}", i*8, machine.read_memory(8, (sp_index + i*8) as usize)); } println!("##################################"); } @@ -329,19 +329,19 @@ impl Machine { fn load_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { match inst.funct3 { RISCV_LD_LB | RISCV_LD_LBU => { - let tmp = Self::read_memory(machine, 1, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; + let tmp = machine.read_memory(1, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; machine.int_reg.set_reg(inst.rd, tmp); }, RISCV_LD_LH | RISCV_LD_LHU => { - let tmp = Self::read_memory(machine, 2, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; + let tmp = machine.read_memory(2, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; machine.int_reg.set_reg(inst.rd, tmp); }, RISCV_LD_LW | RISCV_LD_LWU => { - let tmp = Self::read_memory(machine, 4, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; + let tmp = machine.read_memory(4, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; machine.int_reg.set_reg(inst.rd, tmp); }, RISCV_LD_LD => { - let tmp = Self::read_memory(machine, 8, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; + let tmp = machine.read_memory(8, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; machine.int_reg.set_reg(inst.rd, tmp); }, _ => panic!("In LD switch case, this should never happen... Instr was {}", inst.value) @@ -653,7 +653,7 @@ mod test { let mut m = Machine::init_machine(); m.main_memory[4] = 43; m.main_memory[5] = 150; - assert_eq!((43 << 8) + 150, Machine::read_memory(&mut m, 2, 4)); + assert_eq!((43 << 8) + 150, m.read_memory(2, 4)); } #[test] From a2d5b22774d50d1d22512dc2f4c2db132cd83ff3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Fri, 24 Mar 2023 18:36:02 +0100 Subject: [PATCH 15/29] :recycle: Machine::write_memory is now indeed a self method --- src/simulator/machine.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index 7f2ccd6..aa434b8 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -128,13 +128,13 @@ impl Machine { /// - **size** the number of bytes to write (1, 2, 4 or 8) /// - **address** the address to write to /// - **value** data to be written - pub fn write_memory(machine: &mut Machine, size: i32, address: usize, value: u64) { + pub fn write_memory(&mut self, size: i32, address: usize, value: u64) { if ![1, 2, 4, 8].contains(&size) { panic!("ERROR write_memory: WRONG `size` PARAMETER ({size}), must be 1, 2, 4 or 8") } for i in 0..size as usize { let inv_i = size as usize - i - 1; - machine.main_memory[address + i] = ((value & 0xff << (8 * inv_i)) >> (inv_i * 8)) as u8; + self.main_memory[address + i] = ((value & 0xff << (8 * inv_i)) >> (inv_i * 8)) as u8; } } @@ -352,10 +352,10 @@ impl Machine { /// Executes RISC-V Store Instructions on the machine fn store_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { match inst.funct3 { - RISCV_ST_STB => Self::write_memory(machine, 1, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2) as u64), - RISCV_ST_STH => Self::write_memory(machine, 2, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2) as u64), - RISCV_ST_STW => Self::write_memory(machine, 4, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2) as u64), - RISCV_ST_STD => Self::write_memory(machine, 8, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2) as u64), + RISCV_ST_STB => machine.write_memory(1, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2) as u64), + RISCV_ST_STH => machine.write_memory(2, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2) as u64), + RISCV_ST_STW => machine.write_memory(4, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2) as u64), + RISCV_ST_STD => machine.write_memory(8, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2) as u64), _ => panic!("In ST switch case, this should never happen... Instr was {}", inst.value) } Ok(()) @@ -659,10 +659,10 @@ mod test { #[test] fn test_write_memory() { let mut m = Machine::init_machine(); - Machine::write_memory(&mut m, 2, 6, (43 << 8) + 150); + m.write_memory(2, 6, (43 << 8) + 150); assert_eq!(43, m.main_memory[6]); assert_eq!(150, m.main_memory[7]); - Machine::write_memory(&mut m, 4, 8, (52 << 24) + (20 << 16) + (43 << 8) + 150); + m.write_memory(4, 8, (52 << 24) + (20 << 16) + (43 << 8) + 150); assert_eq!(52, m.main_memory[8]); assert_eq!(20, m.main_memory[9]); assert_eq!(43, m.main_memory[10]); From 4e90d9fef747b046763b20dd73e69c8ceb3a7e13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Fri, 24 Mar 2023 18:48:07 +0100 Subject: [PATCH 16/29] :recycle: Now all machine methods are called through self --- src/simulator/machine.rs | 314 +++++++++++++++++++-------------------- 1 file changed, 157 insertions(+), 157 deletions(-) diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index aa434b8..740ae94 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -144,11 +144,11 @@ impl Machine { /// ### Parameters /// /// - **machine** contains the memory - pub fn _extract_memory(machine: &mut Machine){ + pub fn extract_memory(&self){ let file_path = "burritos_memory.txt"; let write_to_file = |path| -> std::io::Result { let mut file = File::create(path)?; - file.write_all(&machine.main_memory)?; + file.write_all(&self.main_memory)?; Ok(file) }; match write_to_file(file_path) { @@ -162,20 +162,20 @@ impl Machine { /// ### Parameters /// /// - **machine** the machine to get the status from - pub fn print_machine_status(machine: &mut Machine) { + pub fn print_status(&self) { println!("######### Machine status #########"); - for i in (0..32 as usize).step_by(3) { - print!(">{0: <4} : {1:<16x} ", print::REG_X[i], machine.int_reg.get_reg(i as u8)); - print!(">{0: <4} : {1:<16x} ", print::REG_X[i+1], machine.int_reg.get_reg((i+1) as u8)); + for i in (0..32).step_by(3) { + print!(">{0: <4} : {1:<16x} ", print::REG_X[i], self.int_reg.get_reg(i as u8)); + print!(">{0: <4} : {1:<16x} ", print::REG_X[i+1], self.int_reg.get_reg((i+1) as u8)); if i+2 < 32 { - print!(">{0: <4} : {1:<16x} ", print::REG_X[i+2], machine.int_reg.get_reg((i+2) as u8)); + print!(">{0: <4} : {1:<16x} ", print::REG_X[i+2], self.int_reg.get_reg((i+2) as u8)); } println!(); } println!("________________SP________________"); - let sp_index = machine.int_reg.get_reg(2); + let sp_index = self.int_reg.get_reg(2); for i in 0..5 { - println!("SP+{:<2} : {:16x}", i*8, machine.read_memory(8, (sp_index + i*8) as usize)); + println!("SP+{:<2} : {:16x}", i*8, self.read_memory(8, (sp_index + i*8) as usize)); } println!("##################################"); } @@ -185,10 +185,10 @@ impl Machine { /// ### Parameters /// /// - **machine** the machine to read the registers from - pub fn string_registers(machine: &mut Machine) -> String { + pub fn string_registers(&self) -> String { let mut s = String::from(""); for i in 0..32 { - s.push_str(format!("{} ", machine.int_reg.get_reg(i)).as_str()); + s.push_str(format!("{} ", self.int_reg.get_reg(i)).as_str()); } s } @@ -198,9 +198,9 @@ impl Machine { /// ### Parameters /// /// - **machine** which contains a table of instructions - pub fn run(machine : &mut Machine){ - while let Ok(()) = Machine::one_instruction(machine) {} - println!("trace : \n{}", machine.registers_trace); + pub fn run(&mut self){ + while let Ok(()) = Machine::one_instruction(self) {} + println!("trace : \n{}", self.registers_trace); } /// Execute the current instruction @@ -208,114 +208,114 @@ impl Machine { /// ### Parameters /// /// - **machine** which contains a table of instructions and a pc to the actual instruction - pub fn one_instruction(machine :&mut Machine) -> Result<(), MachineError> { + pub fn one_instruction(&mut self) -> Result<(), MachineError> { - if machine.main_memory.len() <= machine.pc as usize { + if self.main_memory.len() <= self.pc as usize { panic!("ERROR : number max of instructions rushed"); } let mut val: [u8; 4] = [0; 4]; for i in 0..4 { - val[i] = machine.main_memory[machine.pc as usize + i]; + val[i] = self.main_memory[self.pc as usize + i]; } let val = u32::from_be_bytes(val) as u64; let inst : Instruction = decode(val); - Self::print_machine_status(machine); - println!("executing instruction : {:016x} at pc {:x}", val, machine.pc); - println!("{}", print::print(decode(val), machine.pc as i32)); - let trace = Self::string_registers(machine); - machine.registers_trace.push_str(format!("{}\n", trace).as_str()); + self.print_status(); + println!("executing instruction : {:016x} at pc {:x}", val, self.pc); + println!("{}", print::print(decode(val), self.pc as i32)); + let trace = Self::string_registers(self); + self.registers_trace.push_str(format!("{}\n", trace).as_str()); - machine.pc += 4; + self.pc += 4; match inst.opcode { RISCV_LUI => { - machine.int_reg.set_reg(inst.rd, inst.imm31_12 as i64); + self.int_reg.set_reg(inst.rd, inst.imm31_12 as i64); Ok(()) }, RISCV_AUIPC => { - machine.int_reg.set_reg(inst.rd,machine.pc as i64 - 4 + inst.imm31_12 as i64); + self.int_reg.set_reg(inst.rd, self.pc as i64 - 4 + inst.imm31_12 as i64); Ok(()) }, RISCV_JAL => { - machine.int_reg.set_reg(inst.rd, machine.pc as i64); - machine.pc = (machine.pc as i64 + inst.imm21_1_signed as i64 - 4) as u64; + self.int_reg.set_reg(inst.rd, self.pc as i64); + self.pc = (self.pc as i64 + inst.imm21_1_signed as i64 - 4) as u64; Ok(()) }, RISCV_JALR => { - let tmp = machine.pc; - machine.pc = (machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as u64 & 0xfffffffe; - machine.int_reg.set_reg(inst.rd, tmp as i64); + let tmp = self.pc; + self.pc = (self.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as u64 & 0xfffffffe; + self.int_reg.set_reg(inst.rd, tmp as i64); Ok(()) }, // Treatment for: BRANCH INSTRUCTIONS RISCV_BR => { - Self::branch_instruction(machine, inst) + self.branch_instruction(inst) }, // Treatment for: LOAD INSTRUCTIONS RISCV_LD => { - Self::load_instruction(machine, inst) + self.load_instruction(inst) }, // store instructions RISCV_ST => { - Self::store_instruction(machine, inst) + self.store_instruction(inst) }, // Treatment for: OPI INSTRUCTIONS RISCV_OPI => { - Self::opi_instruction(machine, inst) + self.opi_instruction(inst) }, RISCV_OP => { - Self::op_instruction(machine, inst) + self.op_instruction(inst) }, // Treatment for OPIW INSTRUCTIONS RISCV_OPIW => { - Self::opiw_instruction(machine, inst) + self.opiw_instruction(inst) }, // Treatment for: OPW INSTRUCTIONS - RISCV_OPW => Self::opw_instruction(machine, inst), + RISCV_OPW => self.opw_instruction(inst), // Treatment for: Simple floating point extension - RISCV_FP => Self::fp_instruction(machine, inst), + RISCV_FP => self.fp_instruction(inst), // Treatment for: System instructions RISCV_SYSTEM => { // temporary return value to stop the loop of run // before we can use system call - Err(MachineError::new(format!("{:x}: System opcode\npc: {:x}", inst.opcode, machine.pc).as_str())) + Err(MachineError::new(format!("{:x}: System opcode\npc: {:x}", inst.opcode, self.pc).as_str())) }, - _ => Err(MachineError::new(format!("{:x}: Unknown opcode\npc: {:x}", inst.opcode, machine.pc).as_str())) + _ => Err(MachineError::new(format!("{:x}: Unknown opcode\npc: {:x}", inst.opcode, self.pc).as_str())) } } /// Treatement for Branch instructions - fn branch_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { + fn branch_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { match inst.funct3 { RISCV_BR_BEQ => { - if machine.int_reg.get_reg(inst.rs1) == machine.int_reg.get_reg(inst.rs2) { - machine.pc = (machine.pc as i64 + inst.imm13_signed as i64 - 4) as u64; + if self.int_reg.get_reg(inst.rs1) == self.int_reg.get_reg(inst.rs2) { + self.pc = (self.pc as i64 + inst.imm13_signed as i64 - 4) as u64; } }, RISCV_BR_BNE => { - if machine.int_reg.get_reg(inst.rs1) != machine.int_reg.get_reg(inst.rs2) { - machine.pc = (machine.pc as i64 + inst.imm13_signed as i64 - 4) as u64; + if self.int_reg.get_reg(inst.rs1) != self.int_reg.get_reg(inst.rs2) { + self.pc = (self.pc as i64 + inst.imm13_signed as i64 - 4) as u64; } }, RISCV_BR_BLT => { - if machine.int_reg.get_reg(inst.rs1) < machine.int_reg.get_reg(inst.rs2) { - machine.pc = (machine.pc as i64 + inst.imm13_signed as i64 - 4) as u64; + if self.int_reg.get_reg(inst.rs1) < self.int_reg.get_reg(inst.rs2) { + self.pc = (self.pc as i64 + inst.imm13_signed as i64 - 4) as u64; } }, RISCV_BR_BGE => { - if machine.int_reg.get_reg(inst.rs1) >= machine.int_reg.get_reg(inst.rs2) { - machine.pc = (machine.pc as i64 + inst.imm13_signed as i64 - 4) as u64; + if self.int_reg.get_reg(inst.rs1) >= self.int_reg.get_reg(inst.rs2) { + self.pc = (self.pc as i64 + inst.imm13_signed as i64 - 4) as u64; } }, RISCV_BR_BLTU => { - if machine.int_reg.get_reg(inst.rs1) < machine.int_reg.get_reg(inst.rs2) { - machine.pc = (machine.pc as i64 + inst.imm13_signed as i64 - 4) as u64; + if self.int_reg.get_reg(inst.rs1) < self.int_reg.get_reg(inst.rs2) { + self.pc = (self.pc as i64 + inst.imm13_signed as i64 - 4) as u64; } }, RISCV_BR_BGEU => { - if machine.int_reg.get_reg(inst.rs1) >= machine.int_reg.get_reg(inst.rs2) { - machine.pc = (machine.pc as i64 + inst.imm13_signed as i64 - 4) as u64; + if self.int_reg.get_reg(inst.rs1) >= self.int_reg.get_reg(inst.rs2) { + self.pc = (self.pc as i64 + inst.imm13_signed as i64 - 4) as u64; } }, _ => { @@ -326,23 +326,23 @@ impl Machine { } /// Executes RISC-V Load Instructions on the machine - fn load_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { + fn load_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { match inst.funct3 { RISCV_LD_LB | RISCV_LD_LBU => { - let tmp = machine.read_memory(1, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; - machine.int_reg.set_reg(inst.rd, tmp); + let tmp = self.read_memory(1, (self.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; + self.int_reg.set_reg(inst.rd, tmp); }, RISCV_LD_LH | RISCV_LD_LHU => { - let tmp = machine.read_memory(2, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; - machine.int_reg.set_reg(inst.rd, tmp); + let tmp = self.read_memory(2, (self.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; + self.int_reg.set_reg(inst.rd, tmp); }, RISCV_LD_LW | RISCV_LD_LWU => { - let tmp = machine.read_memory(4, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; - machine.int_reg.set_reg(inst.rd, tmp); + let tmp = self.read_memory(4, (self.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; + self.int_reg.set_reg(inst.rd, tmp); }, RISCV_LD_LD => { - let tmp = machine.read_memory(8, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; - machine.int_reg.set_reg(inst.rd, tmp); + let tmp = self.read_memory(8, (self.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; + self.int_reg.set_reg(inst.rd, tmp); }, _ => panic!("In LD switch case, this should never happen... Instr was {}", inst.value) } @@ -350,30 +350,30 @@ impl Machine { } /// Executes RISC-V Store Instructions on the machine - fn store_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { + fn store_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { match inst.funct3 { - RISCV_ST_STB => machine.write_memory(1, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2) as u64), - RISCV_ST_STH => machine.write_memory(2, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2) as u64), - RISCV_ST_STW => machine.write_memory(4, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2) as u64), - RISCV_ST_STD => machine.write_memory(8, (machine.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2) as u64), + RISCV_ST_STB => self.write_memory(1, (self.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, self.int_reg.get_reg(inst.rs2) as u64), + RISCV_ST_STH => self.write_memory(2, (self.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, self.int_reg.get_reg(inst.rs2) as u64), + RISCV_ST_STW => self.write_memory(4, (self.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, self.int_reg.get_reg(inst.rs2) as u64), + RISCV_ST_STD => self.write_memory(8, (self.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, self.int_reg.get_reg(inst.rs2) as u64), _ => panic!("In ST switch case, this should never happen... Instr was {}", inst.value) } Ok(()) } /// Executes RISC-V Integer Register-Immediate Instructions on the machine - fn opi_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { + fn opi_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { match inst.funct3 { - RISCV_OPI_ADDI => machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64), - RISCV_OPI_SLTI => machine.int_reg.set_reg(inst.rd, (machine.int_reg.get_reg(inst.rs1) < inst.imm12_I_signed as i64) as i64), - RISCV_OPI_XORI => machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) ^ inst.imm12_I_signed as i64), - RISCV_OPI_ORI => machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) | inst.imm12_I_signed as i64), - RISCV_OPI_ANDI => machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) & inst.imm12_I_signed as i64), - RISCV_OPI_SLLI => machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) << inst.shamt), + RISCV_OPI_ADDI => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64), + RISCV_OPI_SLTI => self.int_reg.set_reg(inst.rd, (self.int_reg.get_reg(inst.rs1) < inst.imm12_I_signed as i64) as i64), + RISCV_OPI_XORI => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) ^ inst.imm12_I_signed as i64), + RISCV_OPI_ORI => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) | inst.imm12_I_signed as i64), + RISCV_OPI_ANDI => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) & inst.imm12_I_signed as i64), + RISCV_OPI_SLLI => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) << inst.shamt), RISCV_OPI_SRI => if inst.funct7_smaller == RISCV_OPI_SRI_SRLI { - machine.int_reg.set_reg(inst.rd, (machine.int_reg.get_reg(inst.rs1) >> inst.shamt) & machine.shiftmask[inst.shamt as usize] as i64); + self.int_reg.set_reg(inst.rd, (self.int_reg.get_reg(inst.rs1) >> inst.shamt) & self.shiftmask[inst.shamt as usize] as i64); } else { // SRAI - machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) >> inst.shamt); + self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) >> inst.shamt); }, _ => panic!("In OPI switch case, this should never happen... Instr was %x\n {}", inst.value) } @@ -381,60 +381,60 @@ impl Machine { } /// Executes simple RISC-V mathematical operations on the machine - fn op_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { + fn op_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { let long_result: i128; let unsigned_reg1: u64; let unsigned_reg2: u64; if inst.funct7 == 1 { match inst.funct3 { RISCV_OP_M_MUL => { - long_result = (machine.int_reg.get_reg(inst.rs1) * machine.int_reg.get_reg(inst.rs2)) as i128; - machine.int_reg.set_reg(inst.rd, (long_result & 0xffffffffffffffff) as i64) + long_result = (self.int_reg.get_reg(inst.rs1) * self.int_reg.get_reg(inst.rs2)) as i128; + self.int_reg.set_reg(inst.rd, (long_result & 0xffffffffffffffff) as i64) }, RISCV_OP_M_MULH => { - long_result = (machine.int_reg.get_reg(inst.rs1) * machine.int_reg.get_reg(inst.rs2)) as i128; - machine.int_reg.set_reg(inst.rd, ((long_result >> 64) & 0xffffffffffffffff) as i64) + long_result = (self.int_reg.get_reg(inst.rs1) * self.int_reg.get_reg(inst.rs2)) as i128; + self.int_reg.set_reg(inst.rd, ((long_result >> 64) & 0xffffffffffffffff) as i64) }, RISCV_OP_M_MULHSU => { - unsigned_reg2 = machine.int_reg.get_reg(inst.rs2) as u64; - long_result = (machine.int_reg.get_reg(inst.rs1) as u64 * unsigned_reg2) as i128; - machine.int_reg.set_reg(inst.rd, ((long_result >> 64) & 0xffffffffffffffff) as i64) + unsigned_reg2 = self.int_reg.get_reg(inst.rs2) as u64; + long_result = (self.int_reg.get_reg(inst.rs1) as u64 * unsigned_reg2) as i128; + self.int_reg.set_reg(inst.rd, ((long_result >> 64) & 0xffffffffffffffff) as i64) }, RISCV_OP_M_MULHU => { - unsigned_reg1 = machine.int_reg.get_reg(inst.rs1) as u64; - unsigned_reg2 = machine.int_reg.get_reg(inst.rs2) as u64; + unsigned_reg1 = self.int_reg.get_reg(inst.rs1) as u64; + unsigned_reg2 = self.int_reg.get_reg(inst.rs2) as u64; long_result = (unsigned_reg1 * unsigned_reg2) as i128; - machine.int_reg.set_reg(inst.rd, ((long_result >> 64) & 0xffffffffffffffff) as i64); + self.int_reg.set_reg(inst.rd, ((long_result >> 64) & 0xffffffffffffffff) as i64); }, - RISCV_OP_M_DIV => machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) / machine.int_reg.get_reg(inst.rs2)), + RISCV_OP_M_DIV => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) / self.int_reg.get_reg(inst.rs2)), _ => panic!("RISCV_OP : funct7 = 1 (Multiplication) :: Error\n") } } else { match inst.funct3 { RISCV_OP_ADD => if inst.funct7 == RISCV_OP_ADD_ADD { - machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) + machine.int_reg.get_reg(inst.rs2)) + self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) + self.int_reg.get_reg(inst.rs2)) } else { - machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) - machine.int_reg.get_reg(inst.rs2)) + self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) - self.int_reg.get_reg(inst.rs2)) }, - RISCV_OP_SLL => machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) << (machine.int_reg.get_reg(inst.rs2) & 0x3f)), - RISCV_OP_SLT => if machine.int_reg.get_reg(inst.rs1) < machine.int_reg.get_reg(inst.rs2) { - machine.int_reg.set_reg(inst.rd, 1) + RISCV_OP_SLL => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) << (self.int_reg.get_reg(inst.rs2) & 0x3f)), + RISCV_OP_SLT => if self.int_reg.get_reg(inst.rs1) < self.int_reg.get_reg(inst.rs2) { + self.int_reg.set_reg(inst.rd, 1) } else { - machine.int_reg.set_reg(inst.rd, 0) + self.int_reg.set_reg(inst.rd, 0) }, RISCV_OP_SLTU => { - unsigned_reg1 = machine.int_reg.get_reg(inst.rs1) as u64; - unsigned_reg2 = machine.int_reg.get_reg(inst.rs2) as u64; + unsigned_reg1 = self.int_reg.get_reg(inst.rs1) as u64; + unsigned_reg2 = self.int_reg.get_reg(inst.rs2) as u64; if unsigned_reg1 < unsigned_reg2 { - machine.int_reg.set_reg(inst.rd, 1) + self.int_reg.set_reg(inst.rd, 1) } else { - machine.int_reg.set_reg(inst.rd, 0) + self.int_reg.set_reg(inst.rd, 0) } }, - RISCV_OP_XOR => machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) ^ machine.int_reg.get_reg(inst.rs2)), - RISCV_OP_SR => machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) >> machine.int_reg.get_reg(inst.rs2)), // RISCV_OP_SR_SRL inaccessible - RISCV_OP_OR => machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) | machine.int_reg.get_reg(inst.rs2)), - RISCV_OP_AND => machine.int_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) & machine.int_reg.get_reg(inst.rs2)), + RISCV_OP_XOR => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) ^ self.int_reg.get_reg(inst.rs2)), + RISCV_OP_SR => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) >> self.int_reg.get_reg(inst.rs2)), // RISCV_OP_SR_SRL inaccessible + RISCV_OP_OR => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) | self.int_reg.get_reg(inst.rs2)), + RISCV_OP_AND => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) & self.int_reg.get_reg(inst.rs2)), _ => panic!("RISCV_OP undefined case\n") } } @@ -442,24 +442,24 @@ impl Machine { } /// Exectutes simple RISC-V *iw instructions on the machine - fn opiw_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { - let local_data = machine.int_reg.get_reg(inst.rs1); + fn opiw_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { + let local_data = self.int_reg.get_reg(inst.rs1); match inst.funct3 { RISCV_OPIW_ADDIW => { let result = local_data + inst.imm12_I_signed as i64; - machine.int_reg.set_reg(inst.rd, result) + self.int_reg.set_reg(inst.rd, result) }, RISCV_OPIW_SLLIW => { let result = local_data << inst.shamt; - machine.int_reg.set_reg(inst.rd, result) + self.int_reg.set_reg(inst.rd, result) }, RISCV_OPIW_SRW => { let result = if inst.funct7 == RISCV_OPIW_SRW_SRLIW { - (local_data >> inst.shamt) & machine.shiftmask[32 + inst.shamt as usize] as i64 + (local_data >> inst.shamt) & self.shiftmask[32 + inst.shamt as usize] as i64 } else { // SRAIW local_data >> inst.shamt }; - machine.int_reg.set_reg(inst.rd, result) + self.int_reg.set_reg(inst.rd, result) }, _ => panic!("In OPI switch case, this should never happen... Instr was {}\n", inst.value), } @@ -467,37 +467,37 @@ impl Machine { } /// Executes simple RISC-V *w instructions on the machine - fn opw_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { + fn opw_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { if inst.funct7 == 1 { // rv64m - let local_data_a = machine.int_reg.get_reg(inst.rs1) & 0xffffffff; - let local_data_b = machine.int_reg.get_reg(inst.rs2) & 0xffffffff; - let local_data_a_unsigned = machine.int_reg.get_reg(inst.rs1) & 0xffffffff; - let local_data_b_unsigned = machine.int_reg.get_reg(inst.rs2) & 0xffffffff; + let local_data_a = self.int_reg.get_reg(inst.rs1) & 0xffffffff; + let local_data_b = self.int_reg.get_reg(inst.rs2) & 0xffffffff; + let local_data_a_unsigned = self.int_reg.get_reg(inst.rs1) & 0xffffffff; + let local_data_b_unsigned = self.int_reg.get_reg(inst.rs2) & 0xffffffff; // Match case for multiplication operations (in standard extension RV32M) match inst.funct3 { - RISCV_OPW_M_MULW => machine.int_reg.set_reg(inst.rd, local_data_a * local_data_b), - RISCV_OPW_M_DIVW => machine.int_reg.set_reg(inst.rd, local_data_a / local_data_b), - RISCV_OPW_M_DIVUW => machine.int_reg.set_reg(inst.rd, local_data_a_unsigned / local_data_b_unsigned), - RISCV_OPW_M_REMW => machine.int_reg.set_reg(inst.rd, local_data_a % local_data_b), - RISCV_OPW_M_REMUW => machine.int_reg.set_reg(inst.rd, local_data_a_unsigned % local_data_b_unsigned), + RISCV_OPW_M_MULW => self.int_reg.set_reg(inst.rd, local_data_a * local_data_b), + RISCV_OPW_M_DIVW => self.int_reg.set_reg(inst.rd, local_data_a / local_data_b), + RISCV_OPW_M_DIVUW => self.int_reg.set_reg(inst.rd, local_data_a_unsigned / local_data_b_unsigned), + RISCV_OPW_M_REMW => self.int_reg.set_reg(inst.rd, local_data_a % local_data_b), + RISCV_OPW_M_REMUW => self.int_reg.set_reg(inst.rd, local_data_a_unsigned % local_data_b_unsigned), _ => panic!("this instruction ({}) doesn't exists", inst.value) } } else { // others rv64 OPW operations - let local_dataa = machine.int_reg.get_reg(inst.rs1) & 0xffffffff; - let local_datab = machine.int_reg.get_reg(inst.rs2) & 0xffffffff; + let local_dataa = self.int_reg.get_reg(inst.rs1) & 0xffffffff; + let local_datab = self.int_reg.get_reg(inst.rs2) & 0xffffffff; // Match case for base OP operation match inst.funct3 { RISCV_OPW_ADDSUBW => if inst.funct7 == RISCV_OPW_ADDSUBW_ADDW { - machine.int_reg.set_reg(inst.rd, local_dataa + local_datab); + self.int_reg.set_reg(inst.rd, local_dataa + local_datab); } else { // SUBW - machine.int_reg.set_reg(inst.rd, local_dataa - local_datab); + self.int_reg.set_reg(inst.rd, local_dataa - local_datab); }, - RISCV_OPW_SLLW => machine.int_reg.set_reg(inst.rd, local_dataa << (local_datab & 0x1f)), + RISCV_OPW_SLLW => self.int_reg.set_reg(inst.rd, local_dataa << (local_datab & 0x1f)), RISCV_OPW_SRW => if inst.funct7 == RISCV_OPW_SRW_SRLW { - machine.int_reg.set_reg(inst.rd, local_dataa >> (local_datab & 0x1f) & machine.shiftmask[32 + local_datab as usize] as i64) + self.int_reg.set_reg(inst.rd, local_dataa >> (local_datab & 0x1f) & self.shiftmask[32 + local_datab as usize] as i64) } else { // SRAW - machine.int_reg.set_reg(inst.rd, local_dataa >> (local_datab & 0x1f)) + self.int_reg.set_reg(inst.rd, local_dataa >> (local_datab & 0x1f)) }, _ => panic!("this instruction ({}) doesn't exists", inst.value) } @@ -506,71 +506,71 @@ impl Machine { } /// Executes simple RISC-V floating point instructions on the machine - fn fp_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> { + fn fp_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { match inst.funct7 { - RISCV_FP_ADD => machine.fp_reg.set_reg(inst.rd, machine.fp_reg.get_reg(inst.rs1) + machine.fp_reg.get_reg(inst.rs2)), - RISCV_FP_SUB => machine.fp_reg.set_reg(inst.rd, machine.fp_reg.get_reg(inst.rs1) - machine.fp_reg.get_reg(inst.rs2)), - RISCV_FP_MUL => machine.fp_reg.set_reg(inst.rd, machine.fp_reg.get_reg(inst.rs1) * machine.fp_reg.get_reg(inst.rs2)), - RISCV_FP_DIV => machine.fp_reg.set_reg(inst.rd, machine.fp_reg.get_reg(inst.rs1) / machine.fp_reg.get_reg(inst.rs2)), - RISCV_FP_SQRT => machine.fp_reg.set_reg(inst.rd, machine.fp_reg.get_reg(inst.rs1).sqrt()), + RISCV_FP_ADD => self.fp_reg.set_reg(inst.rd, self.fp_reg.get_reg(inst.rs1) + self.fp_reg.get_reg(inst.rs2)), + RISCV_FP_SUB => self.fp_reg.set_reg(inst.rd, self.fp_reg.get_reg(inst.rs1) - self.fp_reg.get_reg(inst.rs2)), + RISCV_FP_MUL => self.fp_reg.set_reg(inst.rd, self.fp_reg.get_reg(inst.rs1) * self.fp_reg.get_reg(inst.rs2)), + RISCV_FP_DIV => self.fp_reg.set_reg(inst.rd, self.fp_reg.get_reg(inst.rs1) / self.fp_reg.get_reg(inst.rs2)), + RISCV_FP_SQRT => self.fp_reg.set_reg(inst.rd, self.fp_reg.get_reg(inst.rs1).sqrt()), RISCV_FP_FSGN => { - let local_float = machine.fp_reg.get_reg(inst.rs1); + let local_float = self.fp_reg.get_reg(inst.rs1); match inst.funct3 { - RISCV_FP_FSGN_J => if machine.fp_reg.get_reg(inst.rs2) < 0f32 { - machine.fp_reg.set_reg(inst.rd, -local_float) + RISCV_FP_FSGN_J => if self.fp_reg.get_reg(inst.rs2) < 0f32 { + self.fp_reg.set_reg(inst.rd, -local_float) } else { - machine.fp_reg.set_reg(inst.rd, local_float) + self.fp_reg.set_reg(inst.rd, local_float) }, - RISCV_FP_FSGN_JN => if machine.fp_reg.get_reg(inst.rs2) < 0f32 { - machine.fp_reg.set_reg(inst.rd, local_float) + RISCV_FP_FSGN_JN => if self.fp_reg.get_reg(inst.rs2) < 0f32 { + self.fp_reg.set_reg(inst.rd, local_float) } else { - machine.fp_reg.set_reg(inst.rd, -local_float) + self.fp_reg.set_reg(inst.rd, -local_float) }, - RISCV_FP_FSGN_JX => if (machine.fp_reg.get_reg(inst.rs2) < 0.0 && machine.fp_reg.get_reg(inst.rs1) >= 0.0) || - (machine.fp_reg.get_reg(inst.rs2) >= 0.0 && machine.fp_reg.get_reg(inst.rs1) < 0.0) { - machine.fp_reg.set_reg(inst.rd, -local_float) + RISCV_FP_FSGN_JX => if (self.fp_reg.get_reg(inst.rs2) < 0.0 && self.fp_reg.get_reg(inst.rs1) >= 0.0) || + (self.fp_reg.get_reg(inst.rs2) >= 0.0 && self.fp_reg.get_reg(inst.rs1) < 0.0) { + self.fp_reg.set_reg(inst.rd, -local_float) } else { - machine.fp_reg.set_reg(inst.rd, local_float) + self.fp_reg.set_reg(inst.rd, local_float) }, _ => panic!("this instruction ({}) doesn't exists", inst.value) } }, RISCV_FP_MINMAX => { - let r1 = machine.fp_reg.get_reg(inst.rs1); - let r2 = machine.fp_reg.get_reg(inst.rs2); + let r1 = self.fp_reg.get_reg(inst.rs1); + let r2 = self.fp_reg.get_reg(inst.rs2); match inst.funct3 { - RISCV_FP_MINMAX_MIN => machine.fp_reg.set_reg(inst.rd, if r1 < r2 {r1} else {r2}), - RISCV_FP_MINMAX_MAX => machine.fp_reg.set_reg(inst.rd, if r1 > r2 {r1} else {r2}), + RISCV_FP_MINMAX_MIN => self.fp_reg.set_reg(inst.rd, if r1 < r2 {r1} else {r2}), + RISCV_FP_MINMAX_MAX => self.fp_reg.set_reg(inst.rd, if r1 > r2 {r1} else {r2}), _ => panic!("this instruction ({}) doesn't exists", inst.value) } }, RISCV_FP_FCVTW => { if inst.rs2 == RISCV_FP_FCVTW_W { - machine.int_reg.set_reg(inst.rd, machine.fp_reg.get_reg(inst.rs1) as i64) + self.int_reg.set_reg(inst.rd, self.fp_reg.get_reg(inst.rs1) as i64) } else { - machine.int_reg.set_reg(inst.rd, (machine.fp_reg.get_reg(inst.rs1) as u64) as i64) + self.int_reg.set_reg(inst.rd, (self.fp_reg.get_reg(inst.rs1) as u64) as i64) } }, RISCV_FP_FCVTS => { if inst.rs2 == RISCV_FP_FCVTS_W { - machine.fp_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) as f32); + self.fp_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) as f32); } else { - machine.fp_reg.set_reg(inst.rd, (machine.int_reg.get_reg(inst.rs1) as u32) as f32); + self.fp_reg.set_reg(inst.rd, (self.int_reg.get_reg(inst.rs1) as u32) as f32); } }, - RISCV_FP_FMVW => machine.fp_reg.set_reg(inst.rd, machine.int_reg.get_reg(inst.rs1) as f32), + RISCV_FP_FMVW => self.fp_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) as f32), RISCV_FP_FMVXFCLASS => { if inst.funct3 == RISCV_FP_FMVXFCLASS_FMVX { - machine.int_reg.set_reg(inst.rd, machine.fp_reg.get_reg(inst.rs1) as i64); + self.int_reg.set_reg(inst.rd, self.fp_reg.get_reg(inst.rs1) as i64); } else { panic!("Fclass instruction is not handled in riscv simulator"); } }, RISCV_FP_FCMP => { match inst.funct3 { - RISCV_FP_FCMP_FEQ => machine.int_reg.set_reg(inst.rd, (machine.fp_reg.get_reg(inst.rs1) == machine.fp_reg.get_reg(inst.rs2)) as i64), - RISCV_FP_FCMP_FLT => machine.int_reg.set_reg(inst.rd, (machine.fp_reg.get_reg(inst.rs1) < machine.fp_reg.get_reg(inst.rs2)) as i64), - RISCV_FP_FCMP_FLE => machine.int_reg.set_reg(inst.rd, (machine.fp_reg.get_reg(inst.rs1) <= machine.fp_reg.get_reg(inst.rs2)) as i64), + RISCV_FP_FCMP_FEQ => self.int_reg.set_reg(inst.rd, (self.fp_reg.get_reg(inst.rs1) == self.fp_reg.get_reg(inst.rs2)) as i64), + RISCV_FP_FCMP_FLT => self.int_reg.set_reg(inst.rd, (self.fp_reg.get_reg(inst.rs1) < self.fp_reg.get_reg(inst.rs2)) as i64), + RISCV_FP_FCMP_FLE => self.int_reg.set_reg(inst.rd, (self.fp_reg.get_reg(inst.rs1) <= self.fp_reg.get_reg(inst.rs2)) as i64), _ => panic!("this instruction ({}) doesn't exists", inst.value) } }, @@ -582,12 +582,12 @@ impl Machine { /// print memory FOR DEBUG /// /// "@"adress [16 bytes] - pub fn _print_memory(machine : &mut Machine, from: usize, to: usize) { + pub fn print_memory(&self, from: usize, to: usize) { for i in from..to { if i%16 == 0 { print!("\n@{:04x} ", i); } - print!("{:02x}", machine.main_memory[i]); + print!("{:02x}", self.main_memory[i]); } println!(); } From 7ed53261a0c073ce9e5af3e61c25ffd0ea905eed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Fri, 24 Mar 2023 19:02:50 +0100 Subject: [PATCH 17/29] :memo: Documentation updates --- src/simulator/error.rs | 16 ++++++++++++++++ src/simulator/machine.rs | 13 +++++++++++++ src/simulator/mod.rs | 9 +++++---- src/simulator/register.rs | 13 +++++-------- 4 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/simulator/error.rs b/src/simulator/error.rs index 4794315..3d922a9 100644 --- a/src/simulator/error.rs +++ b/src/simulator/error.rs @@ -1,3 +1,19 @@ +//! # Error +//! +//! This module contains the definition of the MachineError struct, +//! for error management in the Machine module. +//! +//! Basic usage: +//! +//! ``` +//! fn example(x: bool) -> Result<(), MachineError> { +//! match x { +//! true => Ok(()), +//! _ => Err(MachineError::new("Machine failed because of ...")); +//! } +//! } +//! ``` + use std::fmt; /// Machine Error diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index 740ae94..8cb3b8c 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -1,3 +1,16 @@ +//! # Machine +//! +//! This module contains a RISC-V simulator. +//! It supports the base instruction set along +//! with 32bit floating point operations. +//! +//! Basic usage: +//! +//! ``` +//! let mut machine = Machine::init_machine(); +//! machine.run(); +//! ``` + use std::{ io::Write, fs::File diff --git a/src/simulator/mod.rs b/src/simulator/mod.rs index 956ee64..037d545 100644 --- a/src/simulator/mod.rs +++ b/src/simulator/mod.rs @@ -9,6 +9,7 @@ pub mod translationtable; pub mod mmu; pub mod register; +/// Definition of global constants pub mod global { #![allow(dead_code)] @@ -54,15 +55,15 @@ pub mod global { /// /// See func3 to know the type of instruction (LD, LW, LH, LB, LWU, LHU, LBU) pub const RISCV_LD: u8 = 0x3; - // Store instructions + /// Store instructions pub const RISCV_ST: u8 = 0x23; - // immediate Arithmetic operations + /// immediate Arithmetic operations pub const RISCV_OPI: u8 = 0x13; - // Arithmetic operations + /// Arithmetic operations pub const RISCV_OP: u8 = 0x33; /// Immediate arithmetic operations for rv64i pub const RISCV_OPIW: u8 = 0x1b; - // Arithmetic operations for rv64i + /// Arithmetic operations for rv64i pub const RISCV_OPW: u8 = 0x3b; /// Type: B diff --git a/src/simulator/register.rs b/src/simulator/register.rs index a0ef372..339c0e5 100644 --- a/src/simulator/register.rs +++ b/src/simulator/register.rs @@ -1,5 +1,9 @@ -use crate::simulator::machine::{NUM_FP_REGS, NUM_INT_REGS}; +//! # Register +//! +//! This mod contains the definition of the Register structs +//! for use within the Machine module. +use crate::simulator::machine::{NUM_FP_REGS, NUM_INT_REGS}; use std::ops::{Add, Sub}; pub trait RegisterNum: Add + Sub + PartialEq + Copy {} @@ -16,7 +20,6 @@ pub struct Register { } impl Register { - /// Returns the current value held in register *position* pub fn get_reg(&self, position: u8) -> U { self.register[position as usize] @@ -29,28 +32,22 @@ impl Register { pub fn set_reg(&mut self, position: u8, value: U) { if position != 0 { self.register[position as usize] = value; } } - - } impl Register { - /// i64 register constructor pub fn init() -> Register { Register { register: [0i64; NUM_INT_REGS] } } - } impl Register { - /// f32 register constructor pub fn init() -> Register { Register { register: [0f32; NUM_FP_REGS] } } - } \ No newline at end of file From 651e03a446cabefcdd6b366de3a0560a613748bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Sat, 25 Mar 2023 15:37:14 +0100 Subject: [PATCH 18/29] :memo: :refactor: Form and documentation updates --- src/simulator/machine.rs | 68 ++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index 8cb3b8c..c721876 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -94,19 +94,16 @@ impl Machine { value >>= 1; } - let mut ret = Machine { + Machine { pc : 0, sp: 0, - int_reg : Register::::init(), + int_reg : { let mut r = Register::::init(); r.set_reg(10, -1); r }, fp_reg : Register::::init(), main_memory : vec![0_u8; MEM_SIZE], shiftmask, interrupt: Interrupt::new(), registers_trace : String::from("") - }; - - ret.int_reg.set_reg(10, -1); - ret + } } /// Read from main memory of the machine @@ -242,58 +239,61 @@ impl Machine { self.pc += 4; match inst.opcode { + // Treatment for: LOAD UPPER IMMEDIATE INSTRUCTION RISCV_LUI => { self.int_reg.set_reg(inst.rd, inst.imm31_12 as i64); Ok(()) }, + + // Treatment for: ADD UPPER IMMEDIATE TO PC INSTRUCTION RISCV_AUIPC => { self.int_reg.set_reg(inst.rd, self.pc as i64 - 4 + inst.imm31_12 as i64); Ok(()) }, + + // Treatement for: JUMP AND LINK INSTRUCTIONS (direct jump) RISCV_JAL => { self.int_reg.set_reg(inst.rd, self.pc as i64); self.pc = (self.pc as i64 + inst.imm21_1_signed as i64 - 4) as u64; Ok(()) }, + + // Treatment for: JUMP AND LINK REGISTER INSTRUCTIONS (indirect jump) RISCV_JALR => { let tmp = self.pc; self.pc = (self.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as u64 & 0xfffffffe; self.int_reg.set_reg(inst.rd, tmp as i64); Ok(()) }, + // Treatment for: BRANCH INSTRUCTIONS - RISCV_BR => { - self.branch_instruction(inst) - }, + RISCV_BR => self.branch_instruction(inst), + // Treatment for: LOAD INSTRUCTIONS - RISCV_LD => { - self.load_instruction(inst) - }, - // store instructions - RISCV_ST => { - self.store_instruction(inst) - }, + RISCV_LD => self.load_instruction(inst), + + // Treatment for: STORE INSTRUCTIONS + RISCV_ST => self.store_instruction(inst), + // Treatment for: OPI INSTRUCTIONS - RISCV_OPI => { - self.opi_instruction(inst) - }, - RISCV_OP => { - self.op_instruction(inst) - }, + RISCV_OPI => self.opi_instruction(inst), + + // Treatment for: OP INSTRUCTIONS + RISCV_OP => self.op_instruction(inst), + // Treatment for OPIW INSTRUCTIONS - RISCV_OPIW => { - self.opiw_instruction(inst) - }, + RISCV_OPIW => self.opiw_instruction(inst), + // Treatment for: OPW INSTRUCTIONS - RISCV_OPW => self.opw_instruction(inst), - // Treatment for: Simple floating point extension - RISCV_FP => self.fp_instruction(inst), - // Treatment for: System instructions - RISCV_SYSTEM => { - // temporary return value to stop the loop of run - // before we can use system call - Err(MachineError::new(format!("{:x}: System opcode\npc: {:x}", inst.opcode, self.pc).as_str())) - }, + RISCV_OPW => self.opw_instruction(inst), + + // Treatment for: FLOATING POINT INSTRUCTIONS + RISCV_FP => self.fp_instruction(inst), + + // Treatment for: SYSTEM CALLS + RISCV_SYSTEM => Err(MachineError::new(format!("{:x}: System opcode\npc: {:x}", inst.opcode, self.pc).as_str())), + + // Default case _ => Err(MachineError::new(format!("{:x}: Unknown opcode\npc: {:x}", inst.opcode, self.pc).as_str())) } } From 3dfeca4c42eb4f38a445fb801908c0efcf7db2f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Sat, 25 Mar 2023 15:43:33 +0100 Subject: [PATCH 19/29] :recycle: simplified store_instruction using closure --- src/simulator/machine.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index c721876..a43b06c 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -364,13 +364,22 @@ impl Machine { /// Executes RISC-V Store Instructions on the machine fn store_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { + + let mut store = |size| + self.write_memory( + size, + (self.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, + self.int_reg.get_reg(inst.rs2) as u64 + ); + match inst.funct3 { - RISCV_ST_STB => self.write_memory(1, (self.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, self.int_reg.get_reg(inst.rs2) as u64), - RISCV_ST_STH => self.write_memory(2, (self.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, self.int_reg.get_reg(inst.rs2) as u64), - RISCV_ST_STW => self.write_memory(4, (self.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, self.int_reg.get_reg(inst.rs2) as u64), - RISCV_ST_STD => self.write_memory(8, (self.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, self.int_reg.get_reg(inst.rs2) as u64), + RISCV_ST_STB => store(1), + RISCV_ST_STH => store(2), + RISCV_ST_STW => store(4), + RISCV_ST_STD => store(8), _ => panic!("In ST switch case, this should never happen... Instr was {}", inst.value) } + Ok(()) } From e77e125f967f5847f7420fae8899bfefa9d3d86e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Sat, 25 Mar 2023 15:57:28 +0100 Subject: [PATCH 20/29] :recycle: Error management and simplification Modified methods - load_instruction - store_instruction --- src/simulator/machine.rs | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index a43b06c..5ba058b 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -340,47 +340,39 @@ impl Machine { /// Executes RISC-V Load Instructions on the machine fn load_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { + let mut set_reg = |rd, size| { + let val = self.read_memory(size, (self.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; + self.int_reg.set_reg(rd, val); + Ok(()) + }; + match inst.funct3 { - RISCV_LD_LB | RISCV_LD_LBU => { - let tmp = self.read_memory(1, (self.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; - self.int_reg.set_reg(inst.rd, tmp); - }, - RISCV_LD_LH | RISCV_LD_LHU => { - let tmp = self.read_memory(2, (self.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; - self.int_reg.set_reg(inst.rd, tmp); - }, - RISCV_LD_LW | RISCV_LD_LWU => { - let tmp = self.read_memory(4, (self.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; - self.int_reg.set_reg(inst.rd, tmp); - }, - RISCV_LD_LD => { - let tmp = self.read_memory(8, (self.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; - self.int_reg.set_reg(inst.rd, tmp); - }, - _ => panic!("In LD switch case, this should never happen... Instr was {}", inst.value) + RISCV_LD_LB | RISCV_LD_LBU => set_reg(inst.rd, 1), + RISCV_LD_LH | RISCV_LD_LHU => set_reg(inst.rd, 2), + RISCV_LD_LW | RISCV_LD_LWU => set_reg(inst.rd, 4), + RISCV_LD_LD => set_reg(inst.rd, 8), + _ => Err(MachineError::new(format!("In LD switch case, this should never happen... Instr was {}", inst.value).as_str())) } - Ok(()) } /// Executes RISC-V Store Instructions on the machine fn store_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { - - let mut store = |size| + let mut store = |size| { self.write_memory( size, (self.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, self.int_reg.get_reg(inst.rs2) as u64 ); + Ok(()) + }; match inst.funct3 { RISCV_ST_STB => store(1), RISCV_ST_STH => store(2), RISCV_ST_STW => store(4), RISCV_ST_STD => store(8), - _ => panic!("In ST switch case, this should never happen... Instr was {}", inst.value) + _ => Err(MachineError::new(format!("In ST switch case, this should never happen... Instr was {}", inst.value).as_str())) } - - Ok(()) } /// Executes RISC-V Integer Register-Immediate Instructions on the machine From 8ba63d38a37e143464cf7f1e0f8793fc81d2c8e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Mon, 27 Mar 2023 10:21:18 +0200 Subject: [PATCH 21/29] :recycle: Main loop now panics on error --- src/simulator/machine.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index 5ba058b..4c7ea58 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -208,9 +208,13 @@ impl Machine { /// ### Parameters /// /// - **machine** which contains a table of instructions - pub fn run(&mut self){ - while let Ok(()) = Machine::one_instruction(self) {} - println!("trace : \n{}", self.registers_trace); + pub fn run(&mut self) { + loop { + match Machine::one_instruction(self) { + Ok(()) => (), + Err(e) => panic!("FATAL at pc {} -> {}", self.pc, e) + } + } } /// Execute the current instruction From a8bbc131428fc5e30a52242620fc1197f2afa4bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Mon, 27 Mar 2023 10:34:10 +0200 Subject: [PATCH 22/29] :bug: Readded check for system instructions in order to pass tests --- src/simulator/machine.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index 4c7ea58..56224ea 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -210,9 +210,9 @@ impl Machine { /// - **machine** which contains a table of instructions pub fn run(&mut self) { loop { - match Machine::one_instruction(self) { - Ok(()) => (), - Err(e) => panic!("FATAL at pc {} -> {}", self.pc, e) + match self.one_instruction() { + Ok(_) => println!("hello"), + Err(e) => { if e.to_string().contains("System") { break; } panic!("FATAL at pc {} -> {}", self.pc, e) } } } } @@ -654,7 +654,7 @@ mod test { let memory_before = mem_cmp::MemChecker::from(get_full_path!("memory", $a)).unwrap(); let memory_after = mem_cmp::MemChecker::from(get_full_path!("memory", &end_file_name)).unwrap(); mem_cmp::MemChecker::fill_memory_from_mem_checker(&memory_before, &mut m); - Machine::run(&mut m); + m.run(); let expected_trace = fs::read_to_string(get_full_path!("reg_trace", $a)).unwrap(); assert!(mem_cmp::MemChecker::compare_machine_memory(&memory_after, &m)); assert!(expected_trace.contains(m.registers_trace.as_str())); From 939e23883eea11c08b61375b7c70b8c70ba67451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Mon, 27 Mar 2023 11:22:53 +0200 Subject: [PATCH 23/29] :recycle: Simplified OPI --- src/simulator/machine.rs | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index 56224ea..2048455 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -13,7 +13,7 @@ use std::{ io::Write, - fs::File + fs::File, ops::Add }; use crate::simulator::{ print, @@ -381,21 +381,27 @@ impl Machine { /// Executes RISC-V Integer Register-Immediate Instructions on the machine fn opi_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { + let mut compute = |operation: &dyn Fn (i64, i64) -> i64| { + self.int_reg.set_reg(inst.rd, operation(self.int_reg.get_reg(inst.rs1), inst.imm12_I_signed as i64)); + Ok(()) + }; match inst.funct3 { - RISCV_OPI_ADDI => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64), - RISCV_OPI_SLTI => self.int_reg.set_reg(inst.rd, (self.int_reg.get_reg(inst.rs1) < inst.imm12_I_signed as i64) as i64), - RISCV_OPI_XORI => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) ^ inst.imm12_I_signed as i64), - RISCV_OPI_ORI => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) | inst.imm12_I_signed as i64), - RISCV_OPI_ANDI => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) & inst.imm12_I_signed as i64), - RISCV_OPI_SLLI => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) << inst.shamt), - RISCV_OPI_SRI => if inst.funct7_smaller == RISCV_OPI_SRI_SRLI { - self.int_reg.set_reg(inst.rd, (self.int_reg.get_reg(inst.rs1) >> inst.shamt) & self.shiftmask[inst.shamt as usize] as i64); - } else { // SRAI - self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) >> inst.shamt); - }, - _ => panic!("In OPI switch case, this should never happen... Instr was %x\n {}", inst.value) + RISCV_OPI_ADDI => compute(&std::ops::Add::add), + RISCV_OPI_SLTI => compute(&|a, b| { (a < b) as i64 }), + RISCV_OPI_XORI => compute(&|a, b| { a ^ b }), + RISCV_OPI_ORI => compute(&|a, b| { a | b }), + RISCV_OPI_ANDI => compute(&|a, b| { a & b }), + RISCV_OPI_SLLI => compute(&|a, b| { a << b }), + RISCV_OPI_SRI => { + if inst.funct7_smaller == RISCV_OPI_SRI_SRLI { + self.int_reg.set_reg(inst.rd, (self.int_reg.get_reg(inst.rs1) >> inst.shamt) & self.shiftmask[inst.shamt as usize] as i64) + } else { // SRAI + self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) >> inst.shamt) + } + Ok(()) + } + _ => Err(MachineError::new(format!("In OPI switch case, this should never happen... Instr was %x\n {}", inst.value).as_str())) } - Ok(()) } /// Executes simple RISC-V mathematical operations on the machine @@ -517,7 +523,7 @@ impl Machine { } else { // SRAW self.int_reg.set_reg(inst.rd, local_dataa >> (local_datab & 0x1f)) }, - _ => panic!("this instruction ({}) doesn't exists", inst.value) + _ => panic!("this instruction ({}) doesn't exist", inst.value) } } Ok(()) From ba8e36ea90cc5f7a3fc7ee1f63a652f3974f9c74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Mon, 27 Mar 2023 11:35:04 +0200 Subject: [PATCH 24/29] :rotating_lights: Small lint fixes --- src/main.rs | 3 ++- src/simulator/machine.rs | 14 +++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/main.rs b/src/main.rs index cc181fe..9fe5976 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,6 +17,7 @@ use kernel::system::System; use simulator::machine::Machine; fn main() { - let machine = Machine::init_machine(); + let mut machine = Machine::init_machine(); let system = System::default(); + machine.run() } diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index 2048455..fdb9b0f 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -13,7 +13,7 @@ use std::{ io::Write, - fs::File, ops::Add + fs::File }; use crate::simulator::{ print, @@ -24,7 +24,10 @@ use crate::simulator::{ register::* }; -/// Exceptions +/// # Exceptions +/// +/// Textual names of the exceptions that can be generated by user program +/// execution, for debugging purpose. /// todo: is this really supposed to stand in machine.rs? pub enum ExceptionType { /// Everything ok @@ -46,6 +49,7 @@ pub enum ExceptionType { NumExceptionTypes } +/// ID of the stack register pub const STACK_REG: usize = 2; /// Number of available Integer registers pub const NUM_INT_REGS: usize = 32; @@ -154,7 +158,7 @@ impl Machine { /// ### Parameters /// /// - **machine** contains the memory - pub fn extract_memory(&self){ + pub fn _extract_memory(&self){ let file_path = "burritos_memory.txt"; let write_to_file = |path| -> std::io::Result { let mut file = File::create(path)?; @@ -228,8 +232,8 @@ impl Machine { panic!("ERROR : number max of instructions rushed"); } let mut val: [u8; 4] = [0; 4]; - for i in 0..4 { - val[i] = self.main_memory[self.pc as usize + i]; + for (i, elem) in val.iter_mut().enumerate() { + *elem = self.main_memory[self.pc as usize + i]; } let val = u32::from_be_bytes(val) as u64; From 288703321ea7a7b8ac4d57fea707d54f75effd8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Mon, 27 Mar 2023 14:59:22 +0200 Subject: [PATCH 25/29] :recycle: OPI instruction done --- src/simulator/machine.rs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index fdb9b0f..d1fcd3a 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -385,24 +385,24 @@ impl Machine { /// Executes RISC-V Integer Register-Immediate Instructions on the machine fn opi_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { - let mut compute = |operation: &dyn Fn (i64, i64) -> i64| { - self.int_reg.set_reg(inst.rd, operation(self.int_reg.get_reg(inst.rs1), inst.imm12_I_signed as i64)); + let rs1 = self.int_reg.get_reg(inst.rs1); + let imm12 = inst.imm12_I_signed as i64; + let shamt = inst.shamt as i64; + let mut compute = |operation: &dyn Fn (i64, i64) -> i64, a, b| { + self.int_reg.set_reg(inst.rd, operation(a, b)); Ok(()) }; match inst.funct3 { - RISCV_OPI_ADDI => compute(&std::ops::Add::add), - RISCV_OPI_SLTI => compute(&|a, b| { (a < b) as i64 }), - RISCV_OPI_XORI => compute(&|a, b| { a ^ b }), - RISCV_OPI_ORI => compute(&|a, b| { a | b }), - RISCV_OPI_ANDI => compute(&|a, b| { a & b }), - RISCV_OPI_SLLI => compute(&|a, b| { a << b }), - RISCV_OPI_SRI => { - if inst.funct7_smaller == RISCV_OPI_SRI_SRLI { - self.int_reg.set_reg(inst.rd, (self.int_reg.get_reg(inst.rs1) >> inst.shamt) & self.shiftmask[inst.shamt as usize] as i64) - } else { // SRAI - self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) >> inst.shamt) - } - Ok(()) + RISCV_OPI_ADDI => compute(&std::ops::Add::add, rs1, imm12), + RISCV_OPI_SLTI => compute(&|a, b| (a < b) as i64, rs1, imm12), + RISCV_OPI_XORI => compute(&core::ops::BitXor::bitxor, rs1, imm12), + RISCV_OPI_ORI => compute(&core::ops::BitOr::bitor, rs1, imm12), + RISCV_OPI_ANDI => compute(&core::ops::BitAnd::bitand, rs1, imm12), + RISCV_OPI_SLLI => compute(&core::ops::Shl::shl, rs1, imm12), + RISCV_OPI_SRI => if inst.funct7_smaller == RISCV_OPI_SRI_SRLI { + compute(&|a, b| { (a >> b) & self.shiftmask[inst.shamt as usize] as i64 }, rs1, shamt) + } else { + compute(&|a, b| { a >> b }, rs1, shamt) } _ => Err(MachineError::new(format!("In OPI switch case, this should never happen... Instr was %x\n {}", inst.value).as_str())) } From ff93fab8326fce12cb7a1b301c8184b7ea4deee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Mon, 27 Mar 2023 15:01:34 +0200 Subject: [PATCH 26/29] :recycle: Amend of previous commit --- src/simulator/machine.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index d1fcd3a..99c70ba 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -353,7 +353,6 @@ impl Machine { self.int_reg.set_reg(rd, val); Ok(()) }; - match inst.funct3 { RISCV_LD_LB | RISCV_LD_LBU => set_reg(inst.rd, 1), RISCV_LD_LH | RISCV_LD_LHU => set_reg(inst.rd, 2), @@ -373,7 +372,6 @@ impl Machine { ); Ok(()) }; - match inst.funct3 { RISCV_ST_STB => store(1), RISCV_ST_STH => store(2), @@ -402,7 +400,7 @@ impl Machine { RISCV_OPI_SRI => if inst.funct7_smaller == RISCV_OPI_SRI_SRLI { compute(&|a, b| { (a >> b) & self.shiftmask[inst.shamt as usize] as i64 }, rs1, shamt) } else { - compute(&|a, b| { a >> b }, rs1, shamt) + compute(&core::ops::Shr::shr, rs1, shamt) } _ => Err(MachineError::new(format!("In OPI switch case, this should never happen... Instr was %x\n {}", inst.value).as_str())) } From 21622321994b96dac81ca19936cd8213b117aa12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Mon, 27 Mar 2023 15:37:30 +0200 Subject: [PATCH 27/29] :recycle: Simplified branch_instruction --- src/simulator/machine.rs | 47 +++++++++++----------------------------- 1 file changed, 13 insertions(+), 34 deletions(-) diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index 99c70ba..b9aa48e 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -308,40 +308,19 @@ impl Machine { /// Treatement for Branch instructions fn branch_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { - match inst.funct3 { - RISCV_BR_BEQ => { - if self.int_reg.get_reg(inst.rs1) == self.int_reg.get_reg(inst.rs2) { - self.pc = (self.pc as i64 + inst.imm13_signed as i64 - 4) as u64; - } - }, - RISCV_BR_BNE => { - if self.int_reg.get_reg(inst.rs1) != self.int_reg.get_reg(inst.rs2) { - self.pc = (self.pc as i64 + inst.imm13_signed as i64 - 4) as u64; - } - }, - RISCV_BR_BLT => { - if self.int_reg.get_reg(inst.rs1) < self.int_reg.get_reg(inst.rs2) { - self.pc = (self.pc as i64 + inst.imm13_signed as i64 - 4) as u64; - } - }, - RISCV_BR_BGE => { - if self.int_reg.get_reg(inst.rs1) >= self.int_reg.get_reg(inst.rs2) { - self.pc = (self.pc as i64 + inst.imm13_signed as i64 - 4) as u64; - } - }, - RISCV_BR_BLTU => { - if self.int_reg.get_reg(inst.rs1) < self.int_reg.get_reg(inst.rs2) { - self.pc = (self.pc as i64 + inst.imm13_signed as i64 - 4) as u64; - } - }, - RISCV_BR_BGEU => { - if self.int_reg.get_reg(inst.rs1) >= self.int_reg.get_reg(inst.rs2) { - self.pc = (self.pc as i64 + inst.imm13_signed as i64 - 4) as u64; - } - }, - _ => { - panic!("In BR switch case, this should never happen... Instr was {}", inst.value); - } + let op = match inst.funct3 { + RISCV_BR_BEQ => |a, b| a == b, + RISCV_BR_BNE => |a, b| a != b, + RISCV_BR_BLT => |a, b| a < b, + RISCV_BR_BGE => |a, b| a >= b, + RISCV_BR_BLTU => |a, b| a < b, + RISCV_BR_BGEU => |a, b| a >= b, + _ => unreachable!() + }; + let rs1 = self.int_reg.get_reg(inst.rs1); + let rs2 = self.int_reg.get_reg(inst.rs2); + if op(rs1, rs2) { + self.pc = (self.pc as i64 + inst.imm13_signed as i64 - 4) as u64; } Ok(()) } From 7f37965ed47f89df118a413353149d5303984af2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Mon, 27 Mar 2023 15:56:23 +0200 Subject: [PATCH 28/29] :recycle: Implement From<&str> and From traits to MachineError, and simplified opiw_instruction --- src/simulator/error.rs | 14 +++++++++++++- src/simulator/machine.rs | 36 ++++++++++++------------------------ 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/simulator/error.rs b/src/simulator/error.rs index 3d922a9..6b7c515 100644 --- a/src/simulator/error.rs +++ b/src/simulator/error.rs @@ -14,7 +14,7 @@ //! } //! ``` -use std::fmt; +use std::fmt::{self, Error}; /// Machine Error /// This error serves as a specific exception handler for the Machine struct @@ -41,4 +41,16 @@ impl fmt::Display for MachineError { write!(f, "Machine error: {}", &self.message) } +} + +impl From<&str> for MachineError { + fn from(value: &str) -> Self { + MachineError { message: value.to_string() } + } +} + +impl From for MachineError { + fn from(value: String) -> Self { + MachineError { message: value } + } } \ No newline at end of file diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index b9aa48e..55a31e5 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -299,10 +299,10 @@ impl Machine { RISCV_FP => self.fp_instruction(inst), // Treatment for: SYSTEM CALLS - RISCV_SYSTEM => Err(MachineError::new(format!("{:x}: System opcode\npc: {:x}", inst.opcode, self.pc).as_str())), + RISCV_SYSTEM => Err(format!("{:x}: System opcode\npc: {:x}", inst.opcode, self.pc))?, // Default case - _ => Err(MachineError::new(format!("{:x}: Unknown opcode\npc: {:x}", inst.opcode, self.pc).as_str())) + _ => Err(format!("{:x}: Unknown opcode\npc: {:x}", inst.opcode, self.pc))? } } @@ -337,7 +337,7 @@ impl Machine { RISCV_LD_LH | RISCV_LD_LHU => set_reg(inst.rd, 2), RISCV_LD_LW | RISCV_LD_LWU => set_reg(inst.rd, 4), RISCV_LD_LD => set_reg(inst.rd, 8), - _ => Err(MachineError::new(format!("In LD switch case, this should never happen... Instr was {}", inst.value).as_str())) + _ => Err(format!("In LD switch case, this should never happen... Instr was {}", inst.value).as_str())? } } @@ -356,7 +356,7 @@ impl Machine { RISCV_ST_STH => store(2), RISCV_ST_STW => store(4), RISCV_ST_STD => store(8), - _ => Err(MachineError::new(format!("In ST switch case, this should never happen... Instr was {}", inst.value).as_str())) + _ => Err(format!("In ST switch case, this should never happen... Instr was {}", inst.value).as_str())? } } @@ -381,7 +381,7 @@ impl Machine { } else { compute(&core::ops::Shr::shr, rs1, shamt) } - _ => Err(MachineError::new(format!("In OPI switch case, this should never happen... Instr was %x\n {}", inst.value).as_str())) + _ => Err(format!("In OPI switch case, this should never happen... Instr was %x\n {}", inst.value))? } } @@ -449,25 +449,13 @@ impl Machine { /// Exectutes simple RISC-V *iw instructions on the machine fn opiw_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { let local_data = self.int_reg.get_reg(inst.rs1); - match inst.funct3 { - RISCV_OPIW_ADDIW => { - let result = local_data + inst.imm12_I_signed as i64; - self.int_reg.set_reg(inst.rd, result) - }, - RISCV_OPIW_SLLIW => { - let result = local_data << inst.shamt; - self.int_reg.set_reg(inst.rd, result) - }, - RISCV_OPIW_SRW => { - let result = if inst.funct7 == RISCV_OPIW_SRW_SRLIW { - (local_data >> inst.shamt) & self.shiftmask[32 + inst.shamt as usize] as i64 - } else { // SRAIW - local_data >> inst.shamt - }; - self.int_reg.set_reg(inst.rd, result) - }, - _ => panic!("In OPI switch case, this should never happen... Instr was {}\n", inst.value), - } + let result = match inst.funct3 { + RISCV_OPIW_ADDIW => local_data + inst.imm12_I_signed as i64, + RISCV_OPIW_SLLIW => local_data << inst.shamt, + RISCV_OPIW_SRW => (local_data >> inst.shamt) & if inst.funct7 == RISCV_OPIW_SRW_SRLIW { self.shiftmask[32 + inst.shamt as usize] as i64 } else { 1 }, + _ => Err("In OPI switch case, this should never happen... Instr was {}\n")?, + }; + self.int_reg.set_reg(inst.rd, result); Ok(()) } From 40039eca173132fb6a9da80d48ae54d81dfd9d8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Tue, 28 Mar 2023 19:37:31 +0200 Subject: [PATCH 29/29] :recycle: Error cleanup --- src/simulator/error.rs | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/simulator/error.rs b/src/simulator/error.rs index 6b7c515..d6ea783 100644 --- a/src/simulator/error.rs +++ b/src/simulator/error.rs @@ -14,7 +14,7 @@ //! } //! ``` -use std::fmt::{self, Error}; +use std::fmt; /// Machine Error /// This error serves as a specific exception handler for the Machine struct @@ -24,23 +24,22 @@ pub struct MachineError { message: String } -impl MachineError { - - /// MachineError constructor - pub fn new(message: &str) -> MachineError { - MachineError { - message: message.to_string() - } - } - -} - +/// This impl allows this MachineError to be formatted into an empty format. +/// +/// ``` +/// // Result of printing a MachineError +/// let m = MachineError::new("Lorem Ipsum"); +/// println!("Example: {}", m); +/// ``` +/// +/// Console output:Error} +/// ``` +/// example Lorem Ipsum +/// ``` impl fmt::Display for MachineError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Machine error: {}", &self.message) } - } impl From<&str> for MachineError {