From 08ba0154f75460f50fbe49d658ef28c9b3dfc75a Mon Sep 17 00:00:00 2001 From: Quentin Legot Date: Mon, 27 Mar 2023 18:10:11 +0200 Subject: [PATCH] Add a bin loader --- src/kernel/mod.rs | 2 +- src/main.rs | 24 +++++++++++++++++++++--- src/simulator/loader.rs | 31 +++++++++++++++++++++++++++++++ src/simulator/machine.rs | 30 +++++++++++++++--------------- src/simulator/print.rs | 2 +- 5 files changed, 69 insertions(+), 20 deletions(-) diff --git a/src/kernel/mod.rs b/src/kernel/mod.rs index 67a43cb..1fe4f0f 100644 --- a/src/kernel/mod.rs +++ b/src/kernel/mod.rs @@ -1,4 +1,4 @@ -mod process; +pub mod process; pub mod thread; pub mod mgerror; pub mod system; diff --git a/src/main.rs b/src/main.rs index cc181fe..2774e7b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,10 +13,28 @@ mod kernel; /// module containing useful tools which can be use in most part of the OS to ease the development of the OS pub mod utility; +use std::{rc::Rc, cell::RefCell}; + use kernel::system::System; -use simulator::machine::Machine; +use simulator::{machine::Machine, loader}; + +use crate::kernel::{thread::Thread, process::Process}; fn main() { - let machine = Machine::init_machine(); - let system = System::default(); + let mut machine = Machine::init_machine(); + loader::load("test.o", &mut machine, 0).expect("IO Error"); + let system = &mut System::default(); + let thread1 = Thread::new("th1"); + let thread1 = Rc::new(RefCell::new(thread1)); + system.get_thread_manager().get_g_alive().push(Rc::clone(&thread1)); + let owner = Process { num_thread: 0 }; + system.get_thread_manager().start_thread(Rc::clone(&thread1), owner, 0 as i64, 0); + debug_assert_eq!(thread1.borrow_mut().thread_context.pc, 0 as i64); + let to_run = system.get_thread_manager().find_next_to_run().unwrap(); + debug_assert_eq!(to_run, Rc::clone(&thread1)); + debug_assert!(system.get_thread_manager().get_g_alive().contains(&Rc::clone(&thread1))); + system.get_thread_manager().switch_to(&mut machine, Rc::clone(&to_run)); + + machine.run(); + } diff --git a/src/simulator/loader.rs b/src/simulator/loader.rs index 4b84b83..3404128 100644 --- a/src/simulator/loader.rs +++ b/src/simulator/loader.rs @@ -3,6 +3,7 @@ use crate::Machine; use std::fs; use std::io; use std::io::BufRead; +use std::io::Read; @@ -15,6 +16,7 @@ use std::io::BufRead; /// /// - **path** the path of the file to load /// - **size** the number of bytes to write (1, 2, 4 or 8) +#[deprecated] pub fn _load(path : &str, instruction_size: i32) -> Machine { let file = fs::File::open(path).expect("Wrong filename"); let reader = io::BufReader::new(file); @@ -31,4 +33,33 @@ pub fn _load(path : &str, instruction_size: i32) -> Machine { } println!("{:x}", Machine::read_memory(& mut machine, 4, 0)); machine +} + +/// load a 32-bits binary file into the machine +/// +/// ### Parameters +/// +/// - **path** path of the file to load +/// - **machine** the machine where the bin file will be loaded +/// - **start_index** at which index of machine memory you want to start to load the program +/// +/// Returns in a Result any io error +pub fn load(path: &str, machine: &mut Machine, start_index: usize) -> Result<(), std::io::Error> { + let mut file = fs::File::open(path)?; + let mut instructions: Vec = Default::default(); + loop { + let mut buf: [u8; 4] = [0; 4]; + let res = file.read(&mut buf)?; + if res == 0 { + break; // eof + } else { + instructions.push(u32::from_le_bytes(buf)); + } + } + for i in 0..instructions.len() { + machine.write_memory(4, 4 * i + start_index, instructions[i] as u64); + } + #[cfg(debug_assertions)] + println!("{:04x?}", instructions); // only print loaded program in debug build + Ok(()) } \ No newline at end of file diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index e54bd87..7d62e78 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -146,7 +146,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(&mut 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)"); } @@ -154,7 +154,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 } @@ -169,13 +169,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; } } @@ -185,11 +185,11 @@ impl Machine { /// ### Parameters /// /// - **machine** contains the memory - pub fn _extract_memory(machine: &mut Machine){ + pub fn _extract_memory(&mut 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) { @@ -198,20 +198,20 @@ impl Machine { }; } - pub fn print_machine_status(machine: &mut Machine) { + pub fn print_machine_status(&mut self) { 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)); + print!(">{0: <4} : {1:<16x} ", print::REG_X[i], self.int_reg.get_reg(i)); + print!(">{0: <4} : {1:<16x} ", print::REG_X[i+1], self.int_reg.get_reg(i+1)); 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], self.int_reg.get_reg(i+2)); } 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, Self::read_memory(machine, 8, (sp_index + i*8) as usize)); + println!("SP+{:<2} : {:16x}", i*8, Self::read_memory(self, 8, (sp_index + i*8) as usize)); } println!("##################################"); } @@ -229,9 +229,9 @@ impl Machine { /// ### Parameters /// /// - **machine** which contains a table of instructions - pub fn run(machine : &mut Machine){ - while Machine::one_instruction(machine) == 0 {} - println!("trace : \n{}", machine.registers_trace); + pub fn run(&mut self){ + while Machine::one_instruction(self) == 0 {} + println!("trace : \n{}", self.registers_trace); } /// execute the current instruction diff --git a/src/simulator/print.rs b/src/simulator/print.rs index 54bcddf..c9b62b1 100644 --- a/src/simulator/print.rs +++ b/src/simulator/print.rs @@ -216,7 +216,7 @@ pub fn print(ins: Instruction, pc: i32) -> String { //TODO pc should be u64 RISCV_SYSTEM => { "ecall".to_string() }, - _ => todo!("{:x} opcode non géré pc : {:x}, value : {:x}", ins.opcode, pc, ins.value) // Change todo! to panic! in the future, I put todo! because there's a lot of opcode currently not implemented + _ => unreachable!("{:x} opcode non géré pc : {:x}, value : {:x}", ins.opcode, pc, ins.value) } }