Compare commits
No commits in common. "main" and "documentation" have entirely different histories.
main
...
documentat
26
Makefile
26
Makefile
@ -1,13 +1,6 @@
|
||||
TOPDIR=.
|
||||
include $(TOPDIR)/Makefile.config
|
||||
|
||||
#
|
||||
# Demo vars
|
||||
#
|
||||
FLAGS=--offline -r --
|
||||
CARGO=RUSTFLAGS=-Awarnings cargo run ${FLAGS}
|
||||
|
||||
|
||||
|
||||
all: dumps user_lib instruction_tests syscall
|
||||
#
|
||||
@ -29,27 +22,10 @@ syscall: user_lib
|
||||
$(MAKE) build -C test/syscall_tests/
|
||||
$(RM) test/syscall_tests/*.o
|
||||
mkdir -p ${TOPDIR}/target/guac/
|
||||
find . -name '*.guac' -exec mv {} ${TOPDIR}/target/guac/ 2> /dev/null \;
|
||||
find . -name '*.guac' -exec mv {} ${TOPDIR}/target/guac/ \;
|
||||
|
||||
clean:
|
||||
$(MAKE) clean -C userlib/
|
||||
$(MAKE) clean -C test/
|
||||
$(RM) -rf $(TOPDIR)/target
|
||||
|
||||
#
|
||||
# Demo targets
|
||||
#
|
||||
halt: syscall
|
||||
${CARGO} -x ./target/guac/halt.guac -d3
|
||||
|
||||
pc: syscall
|
||||
${CARGO} -x ./target/guac/producteur_consommateur.guac -d2
|
||||
|
||||
matmult: syscall
|
||||
${CARGO} -x ./target/guac/matmult.guac -d2
|
||||
|
||||
lock: syscall
|
||||
${CARGO} -x ./target/guac/lock.guac -d2
|
||||
|
||||
prints: syscall
|
||||
${CARGO} -x ./target/guac/prints.guac -d2
|
||||
|
70
README.md
70
README.md
@ -6,76 +6,6 @@ BurritOS (BurritOS Using Rust Really Improves The Operating System) is an educat
|
||||
|
||||
Based on [NachOS](https://homes.cs.washington.edu/~tom/nachos/) (Copyright (c) 1992-1993 The Regents of the University of California. All rights reserved.)
|
||||
|
||||
## Progress overview
|
||||
|
||||
![Progress overview](./assets/progress_overview.png)
|
||||
|
||||
Currently, the BurritOS project simulator contains a RISC-V processing unit supporting all 47 base instructions plus multiplication and 32bit floating point operations. RAM and the interrupt controller are also integrated. Both the memory management unit and the Disk are written but not tested nor integrated yet.
|
||||
|
||||
On the kernel side, synchronization primitives and scheduling logic are all implemented except for Conditions.
|
||||
|
||||
## Build instructions
|
||||
|
||||
To build in release mode:
|
||||
|
||||
```
|
||||
$ cargo build -r
|
||||
```
|
||||
|
||||
To build in development mode:
|
||||
|
||||
```
|
||||
$ cargo build
|
||||
```
|
||||
|
||||
The generated executable can then be found in the `./target` directory.
|
||||
|
||||
## Running BurritOS
|
||||
|
||||
*In the following examples, BurritOS is started by directly invoking its executable. However, replacing this direct invocation by `cargo run -- <PARAMETERS>` would garner the same result.*
|
||||
|
||||
As it stands, BurritOS does not include a virtual console nor a shell for dynamic user interaction. Thus, programs need to be manually loaded into the system memory. To perform this operation:
|
||||
|
||||
```
|
||||
$ ./burritos --executable <PATH>
|
||||
```
|
||||
|
||||
## Help
|
||||
|
||||
BurritOS provides a succinct manual. To display this manual:
|
||||
|
||||
```
|
||||
$ ./burritos --help
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
Documentation for all components of the BurritOS project can be generated using the following command:
|
||||
|
||||
```
|
||||
$ cargo doc
|
||||
```
|
||||
|
||||
The generated web documentation can be found in the `./target/doc` directory.
|
||||
|
||||
## Tests
|
||||
|
||||
BurritOS is unit tested using the cargo provided testing framework. However, some tests, most notably the Machine tests, require access to a few files **which need to be generated first**.
|
||||
|
||||
To generate test files:
|
||||
|
||||
```
|
||||
$ make all
|
||||
```
|
||||
|
||||
Afterwards, tests can be run with:
|
||||
|
||||
```
|
||||
$ cargo test
|
||||
```
|
||||
|
||||
All make artifacts can be found in the `./target` directory.
|
||||
|
||||
## Authors
|
||||
|
||||
Amaury Brodu, Abdelmajid El Bahri, François Autin, Quentin Legot, Baptiste Meauze, Gabriel Moysan, Rémi Rativel, Samy Solhi
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 100 KiB |
@ -2,7 +2,7 @@
|
||||
# BurritOS configuration file
|
||||
##################################################
|
||||
|
||||
NumPhysPages = 40000000
|
||||
NumPhysPages = 400
|
||||
UserStackSize = 4096
|
||||
MaxFileNameSize = 256
|
||||
NumDirEntries = 30
|
||||
|
@ -8,7 +8,7 @@ use std::{cell::RefCell, rc::Rc};
|
||||
use crate::{simulator::{machine::{ExceptionType, Machine}, error::{MachineOk, MachineError}}};
|
||||
use crate::kernel::synch::{Lock, Semaphore};
|
||||
|
||||
use super::{system::System, thread::Thread};
|
||||
use super::{system::{System, self}, thread::Thread};
|
||||
|
||||
/// The halt system call. Stops Burritos.
|
||||
pub const SC_SHUTDOWN: u8 = 0;
|
||||
@ -143,8 +143,7 @@ fn syscall(machine: &mut Machine, system: &mut System) -> Result<MachineOk, Mach
|
||||
Some(th) => th.clone(),
|
||||
None => Err("Current thread is None")?
|
||||
};
|
||||
let code = machine.read_int_register(10);
|
||||
system.get_thread_manager().thread_finish(machine, th, code);
|
||||
system.get_thread_manager().thread_finish(machine, th);
|
||||
Ok(MachineOk::Ok)
|
||||
},
|
||||
SC_EXEC => todo!(),
|
||||
@ -160,17 +159,13 @@ fn syscall(machine: &mut Machine, system: &mut System) -> Result<MachineOk, Mach
|
||||
let f = machine.read_int_register(12);
|
||||
|
||||
// load buffer
|
||||
let mut buffer = String::new();
|
||||
let mut val: [u8; 4] = [0; 4];
|
||||
for (j, elem) in val.iter_mut().enumerate() {
|
||||
*elem = machine.read_memory(1, address as usize + j) as u8;
|
||||
}
|
||||
let mut buffer = "".to_string();
|
||||
for i in 0..size {
|
||||
buffer.push((machine.read_memory(1, (address + i) as usize)) as u8 as char);
|
||||
}
|
||||
|
||||
if f as u8 == CONSOLE_OUTPUT {
|
||||
print!("{}", buffer); // todo replace with console driver in the future
|
||||
println!("{}", buffer); // todo replace with console driver in the future
|
||||
Ok(MachineOk::Ok)
|
||||
} else {
|
||||
Err("SC_WRITE to file is not yet implemented")?
|
||||
@ -188,7 +183,7 @@ fn syscall(machine: &mut Machine, system: &mut System) -> Result<MachineOk, Mach
|
||||
SC_LOCK_CREATE => sc_lock_create(machine, system),
|
||||
SC_LOCK_DESTROY => sc_lock_destroy(machine, system),
|
||||
SC_LOCK_ACQUIRE => sc_lock_acquire(machine, system),
|
||||
SC_LOCK_RELEASE => sc_lock_release(machine, system),
|
||||
SC_LOCK_RELEASE => todo!(),
|
||||
SC_COND_CREATE => todo!(),
|
||||
SC_COND_DESTROY => todo!(),
|
||||
SC_COND_WAIT => todo!(),
|
||||
@ -288,16 +283,13 @@ fn sc_new_thread(machine: &mut Machine, system: &mut System) -> Result<MachineOk
|
||||
};
|
||||
let current_thread = current_thread.borrow_mut();
|
||||
if let Some(process) = current_thread.get_process_owner() {
|
||||
let sp_max = system.get_thread_manager().get_sp_max() + machine.user_stack_size;
|
||||
system.get_thread_manager().set_sp_max(sp_max);
|
||||
system.get_thread_manager().start_thread(n_thread, Rc::clone(&process), func as u64, sp_max, args);
|
||||
system.get_thread_manager().start_thread(n_thread, Rc::clone(&process), func as u64, current_thread.thread_context.int_registers[2] as u64 + machine.page_size, args);
|
||||
// TODO changé la valeur de sp quand on supportera les addresses virtuels
|
||||
machine.write_int_register(10, tid as i64);
|
||||
Ok(MachineOk::Ok)
|
||||
} else {
|
||||
return Err("Process owner of current thread is none")?;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn sc_join(machine: &mut Machine, system: &mut System) -> Result<MachineOk, MachineError> {
|
||||
@ -362,18 +354,9 @@ mod test {
|
||||
let mut machine = Machine::new(true, get_debug_configuration());
|
||||
machine.write_int_register(17, SC_SHUTDOWN as i64); // Set type to shutdown
|
||||
// let ecall = Instruction::new(0b000000000000_00000_000_00000_1110011);
|
||||
let insts: [u8; 4] = 0b000000000000_00000_000_00000_1110011_u32.to_le_bytes();
|
||||
machine.write_memory(1, 0, insts[0] as u64);
|
||||
machine.write_memory(1, 1, insts[1] as u64);
|
||||
machine.write_memory(1, 2, insts[2] as u64);
|
||||
machine.write_memory(1, 3, insts[3] as u64); // ecall
|
||||
// machine.write_memory(4, 0, 0b000000000000_00000_000_00000_1110011_u64.to_be()); // ecall
|
||||
let insts: [u8; 4] = 0b000000001010_00000_000_00001_0010011_u32.to_le_bytes();
|
||||
machine.write_memory(1, 4, insts[0] as u64);
|
||||
machine.write_memory(1, 5, insts[1] as u64);
|
||||
machine.write_memory(1, 6, insts[2] as u64);
|
||||
machine.write_memory(1, 7, insts[3] as u64); // r1 <- 10
|
||||
// machine.write_memory(4, 4, 0b000000001010_00000_000_00001_0010011_u64.to_be()); // r1 <- 10
|
||||
|
||||
machine.write_memory(4, 0, 0b000000000000_00000_000_00000_1110011); // ecall
|
||||
machine.write_memory(4, 4, 0b000000001010_00000_000_00001_0010011); // r1 <- 10
|
||||
let mut system = System::new(true);
|
||||
machine.run(&mut system);
|
||||
// If the machine was stopped with no error, the shutdown worked
|
||||
|
@ -118,11 +118,7 @@ pub struct ThreadManager {
|
||||
/// List of objects created by the thread manager (such as Locks and Semaphores)
|
||||
obj_addrs: ObjAddr,
|
||||
/// If true, enables debug mode
|
||||
debug: bool,
|
||||
/// Temporary field, to be removed when virtual memory will be available to use.
|
||||
///
|
||||
/// A value to know where the next starting thread should have its stack pointer
|
||||
sp_max: u64,
|
||||
debug: bool
|
||||
}
|
||||
|
||||
impl ThreadManager {
|
||||
@ -134,24 +130,23 @@ impl ThreadManager {
|
||||
g_alive: List::default(),
|
||||
ready_list: List::default(),
|
||||
obj_addrs: ObjAddr::init(),
|
||||
debug,
|
||||
sp_max: 0
|
||||
debug
|
||||
}
|
||||
}
|
||||
|
||||
/// Mark `thread` as ready, but not necessarily running yet.
|
||||
/// Mark a thread as aready, but not necessarily running yet.
|
||||
///
|
||||
/// Put it in the ready list, for later scheduling onto the CPU.
|
||||
///
|
||||
/// ## Pamameter
|
||||
///
|
||||
/// **thread** is the thread to be put on the ready list
|
||||
/// **thread** is the thread to be put on the read list
|
||||
pub fn ready_to_run(&mut self, thread: ThreadRef) {
|
||||
self.ready_list.push(thread);
|
||||
}
|
||||
|
||||
/// Return the next thread to be scheduled onto the CPU.
|
||||
/// If there are no ready threads, return `Option::None`
|
||||
/// If there are no ready threads, return Option::None
|
||||
///
|
||||
/// Thread is removed from the ready list.
|
||||
///
|
||||
@ -160,12 +155,12 @@ impl ThreadManager {
|
||||
self.ready_list.pop()
|
||||
}
|
||||
|
||||
/// Dispatch the CPU to `next_thread`. Save the state of the old thread
|
||||
/// Dispatch the CPU to next_thread. Save the state of the old thread
|
||||
/// and load the state of the new thread.
|
||||
///
|
||||
/// We assume the state of the previously running thread has already been changed from running to blocked or ready.
|
||||
///
|
||||
/// Variable `g_current_thread` become next_thread
|
||||
/// Global variable g_current_thread become next_thread
|
||||
///
|
||||
/// ## Parameter
|
||||
///
|
||||
@ -190,14 +185,6 @@ impl ThreadManager {
|
||||
}
|
||||
|
||||
/// Start a thread, attaching it to a process
|
||||
///
|
||||
/// ## Parameter
|
||||
///
|
||||
/// **thread** thread to start
|
||||
/// **owner** process owner of thread (after the execution of this method)
|
||||
/// **func_pc** pc the thread
|
||||
/// **sp_loc** stack pointer of the thread, to remove (or move) when mmu will be completed
|
||||
/// **argument** value to be place on register[10]
|
||||
pub fn start_thread(&mut self, thread: ThreadRef, owner: Rc<RefCell<Process>>, func_pc: u64, sp_loc: u64, argument: i64) {
|
||||
self.debug(format!("starting thread \"{}\"", thread.borrow().get_name()));
|
||||
|
||||
@ -212,11 +199,6 @@ impl ThreadManager {
|
||||
}
|
||||
|
||||
/// Wait for another thread to finish its execution
|
||||
///
|
||||
/// If the thread you want to wait doesn't exist (isn't alive), execution will resume.
|
||||
/// Otherwise, CPU is dispatch to next alive thread if any.
|
||||
///
|
||||
/// When the thread you want to join finish, it place the waiting thread (self) in ready list
|
||||
pub fn thread_join(&mut self, machine: &mut Machine, waiter: ThreadRef, waiting_for: ThreadRef) {
|
||||
let waiting_for = Rc::clone(&waiting_for);
|
||||
if self.get_g_alive().contains(&waiting_for) {
|
||||
@ -227,19 +209,10 @@ impl ThreadManager {
|
||||
|
||||
/// Relinquish the CPU if any other thread is runnable.
|
||||
///
|
||||
/// If so, put the current thread at the end of the ready list, so it'll be re-scheduled in the future.
|
||||
///
|
||||
/// **Returns** immediately if there's no other thread ready or return when the current thread has been switched.
|
||||
///
|
||||
/// Interruptions are disabled during the process, so all the process of looking for a next thread and switching to it is atomic,
|
||||
/// and is place at its old status at the end of the method.
|
||||
///
|
||||
/// Cannot use `yield` as a function name -> reserved name in rust
|
||||
/// Cannot use yield as a function name -> reserved name in rust
|
||||
///
|
||||
/// ## Parameters
|
||||
///
|
||||
/// **machine** RISC-V simulator
|
||||
/// **thread** current thread to be relinquish
|
||||
/// **is_ready** true if **thread** should be readded to ready_to_run list, false otherwise. Typically false when joining per example
|
||||
pub fn thread_yield(&mut self, machine: &mut Machine, thread: ThreadRef, is_ready: bool) {
|
||||
let old_status = machine.interrupt.set_status(crate::simulator::interrupt::InterruptStatus::InterruptOff);
|
||||
@ -256,16 +229,7 @@ impl ThreadManager {
|
||||
machine.interrupt.set_status(old_status);
|
||||
}
|
||||
|
||||
/// Put the thread to sleep and relinquish the processor because the current thread is blocked (Semaphore, Lock, Condition) or because it finished its execution
|
||||
///
|
||||
/// Another thread will eventually wake it up and put it back to ready list after it has been unblocked.
|
||||
///
|
||||
/// Behavior now: At the moment, disk isn't fully develop and not integrated to burritos, so if there's no ready thread, then we stop the OS.
|
||||
///
|
||||
/// Behaviour in the future: If there are no threads on the ready list, that means there is no thread to run,
|
||||
/// we assume this is because at least one thread is waiting for I/O [`interrupt`](crate::simulator::interrupt::Interrupt) (the only reason a new thread can become ready at this point).
|
||||
///
|
||||
/// We also assume interruption are already disabled, becuase it's called from a synchronization routine for interrupt should be disabled.
|
||||
/// Put the thread to sleep and relinquish the processor
|
||||
pub fn thread_sleep(&mut self, machine: &mut Machine, thread: ThreadRef) {
|
||||
debug_assert_eq!(Option::Some(Rc::clone(&thread)), self.g_current_thread);
|
||||
debug_assert_eq!(machine.interrupt.get_status(), InterruptStatus::InterruptOff);
|
||||
@ -275,27 +239,17 @@ impl ThreadManager {
|
||||
while next_thread.is_none() {
|
||||
eprintln!("Nobody to run => idle");
|
||||
machine.interrupt.idle();
|
||||
if let Some(t) = self.find_next_to_run() {
|
||||
next_thread = Some(t);
|
||||
} else {
|
||||
panic!("Couldn't find next thread to run.\nShutting down...");
|
||||
}
|
||||
next_thread = self.find_next_to_run();
|
||||
}
|
||||
self.switch_to(machine, Rc::clone(&next_thread.unwrap()));
|
||||
|
||||
}
|
||||
|
||||
/// Finish the execution of the thread and prepare its deallocation
|
||||
///
|
||||
/// Called by the thread itself when it finish its execution ([`Exit`](super::exception::SC_EXIT) exception).
|
||||
///
|
||||
/// We remove the thread from the alive list, and rustc deallocate the thread itself(behaviour different than Nachos)
|
||||
///
|
||||
/// Interruption are disabled to assume atomicity.
|
||||
pub fn thread_finish(&mut self, machine: &mut Machine, thread: ThreadRef, exit_code: i64) {
|
||||
pub fn thread_finish(&mut self, machine: &mut Machine, thread: ThreadRef) {
|
||||
let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff);
|
||||
assert!(self.g_alive.remove(Rc::clone(&thread)));
|
||||
self.debug(format!("Finishing thread {} with code {}", thread.borrow().get_name(), exit_code));
|
||||
self.debug(format!("Finishing thread {}", thread.borrow().get_name()));
|
||||
// g_objets_addrs->removeObject(self.thread) // a ajouté plus tard
|
||||
for (_, el) in thread.borrow().join_thread.iter().enumerate() {
|
||||
self.ready_to_run(Rc::clone(&el));
|
||||
@ -305,8 +259,6 @@ impl ThreadManager {
|
||||
}
|
||||
|
||||
/// Save the CPU state of a user program on a context switch.
|
||||
///
|
||||
/// Save PC and registers
|
||||
pub fn thread_save_processor_state(&mut self, machine: &mut Machine, thread: ThreadRef) {
|
||||
let mut t = thread.borrow_mut();
|
||||
for i in 0..NUM_INT_REGS {
|
||||
@ -319,8 +271,6 @@ impl ThreadManager {
|
||||
}
|
||||
|
||||
/// Restore the CPU state of a user program on a context switch.
|
||||
///
|
||||
/// Restore PC and registers
|
||||
pub fn thread_restore_processor_state(&self, machine: &mut Machine, thread: ThreadRef) {
|
||||
let t: Ref<_> = thread.borrow();
|
||||
for i in 0..NUM_INT_REGS {
|
||||
@ -415,9 +365,7 @@ impl ThreadManager {
|
||||
Ok(MachineOk::Ok)
|
||||
}
|
||||
|
||||
/// Release lock hold by current thread and wake up a waiter if necessary, placing it on ready list, this thread now hold the lock.
|
||||
///
|
||||
/// If no thread is waiting for the lock, the lock is released
|
||||
/// Wake up a waiter if necessary, or release it if no thread is waiting.
|
||||
pub fn lock_release(&mut self, id: i32, machine: &mut Machine) -> Result<MachineOk, MachineError> {
|
||||
let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff);
|
||||
let current_thread = match self.get_g_current_thread() {
|
||||
@ -448,12 +396,12 @@ impl ThreadManager {
|
||||
Ok(MachineOk::Ok)
|
||||
}
|
||||
|
||||
/// Return currently running thread
|
||||
/// Currently running thread
|
||||
pub fn get_g_current_thread(&mut self) -> &Option<ThreadRef> {
|
||||
&self.g_current_thread
|
||||
}
|
||||
|
||||
/// Return list of alive threads
|
||||
/// List of alive threads
|
||||
pub fn get_g_alive(&mut self) -> &mut List<ThreadRef> {
|
||||
&mut self.g_alive
|
||||
}
|
||||
@ -475,14 +423,6 @@ impl ThreadManager {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_sp_max(&self) -> u64 {
|
||||
self.sp_max
|
||||
}
|
||||
|
||||
pub fn set_sp_max(&mut self, sp_max: u64) {
|
||||
self.sp_max = sp_max;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -56,9 +56,7 @@ fn main() {
|
||||
|
||||
let owner1 = Process { num_thread: 0 };
|
||||
let owner1 = Rc::new(RefCell::new(owner1));
|
||||
let sp_max = ptr + machine.user_stack_size;
|
||||
system.get_thread_manager().set_sp_max(sp_max);
|
||||
system.get_thread_manager().start_thread(Rc::clone(&thread_exec), owner1, loader.elf_header.entrypoint, sp_max, -1);
|
||||
system.get_thread_manager().start_thread(Rc::clone(&thread_exec), owner1, loader.elf_header.entrypoint, ptr + machine.page_size, -1);
|
||||
|
||||
let to_run = system.get_thread_manager().find_next_to_run().unwrap();
|
||||
system.get_thread_manager().switch_to(&mut machine, Rc::clone(&to_run));
|
||||
|
@ -349,11 +349,11 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_op() {
|
||||
let sub = Instruction::new(0b0100000_10000_10001_000_11100_0110011_u64.to_le());
|
||||
let add = Instruction::new(0b0000000_10000_10001_000_11100_0110011_u64.to_le());
|
||||
let xor = Instruction::new(0b0000000_10000_10001_100_11100_0110011_u64.to_le());
|
||||
let slr = Instruction::new(0b0000000_10000_10001_101_11100_0110011_u64.to_le());
|
||||
let sra = Instruction::new(0b0100000_10000_10001_101_11100_0110011_u64.to_le());
|
||||
let sub = Instruction::new(0b0100000_10000_10001_000_11100_0110011);
|
||||
let add = Instruction::new(0b0000000_10000_10001_000_11100_0110011);
|
||||
let xor = Instruction::new(0b0000000_10000_10001_100_11100_0110011);
|
||||
let slr = Instruction::new(0b0000000_10000_10001_101_11100_0110011);
|
||||
let sra = Instruction::new(0b0100000_10000_10001_101_11100_0110011);
|
||||
|
||||
assert_eq!("sub\tt3,a7,a6", instruction_debug(&sub, 0));
|
||||
assert_eq!("xor\tt3,a7,a6", instruction_debug(&xor, 0));
|
||||
@ -365,13 +365,13 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_opi() {
|
||||
let addi = Instruction::new(0b0000000000_10001_000_11100_0010011_u64.to_le());
|
||||
let slli = Instruction::new(0b0000000000_10001_001_11100_0010011_u64.to_le());
|
||||
let slti = Instruction::new(0b0000000000_10001_010_11100_0010011_u64.to_le());
|
||||
let sltiu = Instruction::new(0b0000000000_10001_011_11100_0010011_u64.to_le());
|
||||
let xori = Instruction::new(0b_0000000000010001_100_11100_0010011_u64.to_le());
|
||||
let ori = Instruction::new(0b00000000000_10001_110_11100_0010011_u64.to_le());
|
||||
let andi = Instruction::new(0b000000000000_10001_111_11100_0010011_u64.to_le());
|
||||
let addi = Instruction::new(0b0000000000_10001_000_11100_0010011);
|
||||
let slli = Instruction::new(0b0000000000_10001_001_11100_0010011);
|
||||
let slti = Instruction::new(0b0000000000_10001_010_11100_0010011);
|
||||
let sltiu = Instruction::new(0b0000000000_10001_011_11100_0010011);
|
||||
let xori = Instruction::new(0b_0000000000010001_100_11100_0010011);
|
||||
let ori = Instruction::new(0b00000000000_10001_110_11100_0010011);
|
||||
let andi = Instruction::new(0b000000000000_10001_111_11100_0010011);
|
||||
assert_eq!("andi\tt3,a7,0", instruction_debug(&andi, 0));
|
||||
assert_eq!("addi\tt3,a7,0", instruction_debug(&addi, 0));
|
||||
assert_eq!("slli\tt3,a7,0", instruction_debug(&slli, 0));
|
||||
@ -383,8 +383,8 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_lui() {
|
||||
let lui = Instruction::new(0b01110001000011111000_11100_0110111_u64.to_le());
|
||||
let lui_negatif = Instruction::new(0b11110001000011111000_11100_0110111_u64.to_le());
|
||||
let lui = Instruction::new(0b01110001000011111000_11100_0110111);
|
||||
let lui_negatif = Instruction::new(0b11110001000011111000_11100_0110111);
|
||||
assert_eq!("lui\tt3,710f8000", instruction_debug(&lui, 0));
|
||||
assert_eq!("lui\tt3,f10f8000", instruction_debug(&lui_negatif, 0));
|
||||
}
|
||||
@ -392,13 +392,13 @@ mod test {
|
||||
#[test]
|
||||
fn test_ld() {
|
||||
// imm rs1 f3 rd opcode
|
||||
let lb = Instruction::new(0b010111110000_10001_000_11100_0000011_u64.to_le());
|
||||
let lh = Instruction::new(0b010111110000_10001_001_11100_0000011_u64.to_le());
|
||||
let lw = Instruction::new(0b010111110000_10001_010_11100_0000011_u64.to_le());
|
||||
let lbu = Instruction::new(0b010111110000_10001_100_11100_0000011_u64.to_le());
|
||||
let lhu = Instruction::new(0b010111110000_10001_101_11100_0000011_u64.to_le());
|
||||
let ld = Instruction::new(0b010111110000_10001_011_11100_0000011_u64.to_le());
|
||||
let lwu = Instruction::new(0b010111110000_10001_110_11100_0000011_u64.to_le());
|
||||
let lb = Instruction::new(0b010111110000_10001_000_11100_0000011);
|
||||
let lh = Instruction::new(0b010111110000_10001_001_11100_0000011);
|
||||
let lw = Instruction::new(0b010111110000_10001_010_11100_0000011);
|
||||
let lbu = Instruction::new(0b010111110000_10001_100_11100_0000011);
|
||||
let lhu = Instruction::new(0b010111110000_10001_101_11100_0000011);
|
||||
let ld = Instruction::new(0b010111110000_10001_011_11100_0000011);
|
||||
let lwu = Instruction::new(0b010111110000_10001_110_11100_0000011);
|
||||
|
||||
assert_eq!("lb\tt3,1520(a7)", instruction_debug(&lb, 0));
|
||||
assert_eq!("lh\tt3,1520(a7)", instruction_debug(&lh, 0));
|
||||
@ -411,10 +411,10 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_opw() {
|
||||
let addw: Instruction = Instruction::new(0b0000000_10000_10001_000_11100_0111011_u64.to_le());
|
||||
let sllw: Instruction = Instruction::new(0b0000000_10000_10001_001_11100_0111011_u64.to_le());
|
||||
let srlw: Instruction = Instruction::new(0b0000000_10000_10001_101_11100_0111011_u64.to_le());
|
||||
let sraw: Instruction = Instruction::new(0b0100000_10000_10001_101_11100_0111011_u64.to_le());
|
||||
let addw: Instruction = Instruction::new(0b0000000_10000_10001_000_11100_0111011);
|
||||
let sllw: Instruction = Instruction::new(0b0000000_10000_10001_001_11100_0111011);
|
||||
let srlw: Instruction = Instruction::new(0b0000000_10000_10001_101_11100_0111011);
|
||||
let sraw: Instruction = Instruction::new(0b0100000_10000_10001_101_11100_0111011);
|
||||
|
||||
assert_eq!("addw\tt3,a7,a6", instruction_debug(&addw, 0));
|
||||
assert_eq!("sllw\tt3,a7,a6", instruction_debug(&sllw, 0));
|
||||
@ -424,9 +424,9 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_opwi() {
|
||||
let addiw: Instruction =Instruction::new(0b000000000000_10001_000_11100_0011011_u64.to_le());
|
||||
let slliw: Instruction = Instruction::new(0b0000000_10000_10001_001_11100_0011011_u64.to_le());
|
||||
let srai: Instruction = Instruction::new(0b010000010001_10001_101_11100_0010011_u64.to_le());
|
||||
let addiw: Instruction =Instruction::new(0b000000000000_10001_000_11100_0011011);
|
||||
let slliw: Instruction = Instruction::new(0b0000000_10000_10001_001_11100_0011011);
|
||||
let srai: Instruction = Instruction::new(0b010000010001_10001_101_11100_0010011);
|
||||
assert_eq!("addiw\tt3,a7,0x0", instruction_debug(&addiw, 0));
|
||||
assert_eq!("slliw\tt3,a7,0x10", instruction_debug(&slliw, 0));
|
||||
assert_eq!("srai\tt3,a7,17", instruction_debug(&srai, 0));
|
||||
@ -435,13 +435,13 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_br() {
|
||||
let beq: Instruction = Instruction::new(0b0000000_10000_10001_000_00000_1100011_u64.to_le());
|
||||
let bne: Instruction = Instruction::new(0b0000000_10000_10001_001_00000_1100011_u64.to_le());
|
||||
let blt: Instruction = Instruction::new(0b0000000_10000_10001_100_00000_1100011_u64.to_le());
|
||||
let bge: Instruction = Instruction::new(0b0000000_10000_10001_101_00000_1100011_u64.to_le());
|
||||
let bge2: Instruction = Instruction::new(0x00f75863_u64.to_le());
|
||||
let bltu: Instruction = Instruction::new(0b0000000_10000_10001_110_00000_1100011_u64.to_le());
|
||||
let bgeu: Instruction = Instruction::new(0b0000000_10000_10001_111_00000_1100011_u64.to_le());
|
||||
let beq: Instruction = Instruction::new(0b0000000_10000_10001_000_00000_1100011);
|
||||
let bne: Instruction = Instruction::new(0b0000000_10000_10001_001_00000_1100011);
|
||||
let blt: Instruction = Instruction::new(0b0000000_10000_10001_100_00000_1100011);
|
||||
let bge: Instruction = Instruction::new(0b0000000_10000_10001_101_00000_1100011);
|
||||
let bge2: Instruction = Instruction::new(0x00f75863);
|
||||
let bltu: Instruction = Instruction::new(0b0000000_10000_10001_110_00000_1100011);
|
||||
let bgeu: Instruction = Instruction::new(0b0000000_10000_10001_111_00000_1100011);
|
||||
assert_eq!("blt\ta7,a6,0", instruction_debug(&blt, 0));
|
||||
assert_eq!("bge\ta7,a6,0", instruction_debug(&bge, 0));
|
||||
assert_eq!("bge\ta4,a5,104d4", instruction_debug(&bge2, 0x104c4));
|
||||
@ -461,72 +461,72 @@ mod test {
|
||||
a = a + b;
|
||||
b = a - b;
|
||||
*/
|
||||
assert_eq!("addi sp,sp,-32", instruction_debug(&Instruction::new(0xfe010113_u64.to_le()), 0));
|
||||
assert_eq!("sd s0,24(sp)", instruction_debug(&Instruction::new(0x00813c23_u64.to_le()), 0));
|
||||
assert_eq!("addi s0,sp,32", instruction_debug(&Instruction::new(0x02010413_u64.to_le()), 0));
|
||||
assert_eq!("sw zero,-20(s0)", instruction_debug(&Instruction::new(0xfe042623_u64.to_le()), 0));
|
||||
assert_eq!("addi a5,zero,5", instruction_debug(&Instruction::new(0x00500793_u64.to_le()), 0));
|
||||
assert_eq!("sw a5,-24(s0)", instruction_debug(&Instruction::new(0xfef42423_u64.to_le()), 0));
|
||||
assert_eq!("lw a5,-24(s0)", instruction_debug(&Instruction::new(0xfe842783_u64.to_le()), 0));
|
||||
assert_eq!("sw a5,-20(s0)", instruction_debug(&Instruction::new(0xfef42623_u64.to_le()), 0));
|
||||
assert_eq!("lw a5,-20(s0)", instruction_debug(&Instruction::new(0xfec42783_u64.to_le()), 0));
|
||||
assert_eq!("addi a4,a5,0", instruction_debug(&Instruction::new(0x00078713_u64.to_le()), 0));
|
||||
assert_eq!("lw a5,-24(s0)", instruction_debug(&Instruction::new(0xfe842783_u64.to_le()), 0));
|
||||
assert_eq!("mulw a5,a4,a5", instruction_debug(&Instruction::new(0x02f707bb_u64.to_le()), 0));
|
||||
assert_eq!("sw a5,-20(s0)", instruction_debug(&Instruction::new(0xfef42623_u64.to_le()), 0));
|
||||
assert_eq!("lw a5,-20(s0)", instruction_debug(&Instruction::new(0xfec42783_u64.to_le()), 0));
|
||||
assert_eq!("addi a4,a5,0", instruction_debug(&Instruction::new(0x00078713_u64.to_le()), 0));
|
||||
assert_eq!("lw a5,-24(s0)", instruction_debug(&Instruction::new(0xfe842783_u64.to_le()), 0));
|
||||
assert_eq!("addw a5,a4,a5", instruction_debug(&Instruction::new(0x00f707bb_u64.to_le()), 0));
|
||||
assert_eq!("sw a5,-20(s0)", instruction_debug(&Instruction::new(0xfef42623_u64.to_le()), 0));
|
||||
assert_eq!("lw a5,-20(s0)", instruction_debug(&Instruction::new(0xfec42783_u64.to_le()), 0));
|
||||
assert_eq!("addi a4,a5,0", instruction_debug(&Instruction::new(0x00078713_u64.to_le()), 0));
|
||||
assert_eq!("lw a5,-24(s0)", instruction_debug(&Instruction::new(0xfe842783_u64.to_le()), 0));
|
||||
assert_eq!("subw a5,a4,a5", instruction_debug(&Instruction::new(0x40f707bb_u64.to_le()), 0));
|
||||
assert_eq!("sw a5,-24(s0)", instruction_debug(&Instruction::new(0xfef42423_u64.to_le()), 0));
|
||||
assert_eq!("addi a5,zero,0", instruction_debug(&Instruction::new(0x00000793_u64.to_le()), 0));
|
||||
assert_eq!("addi a0,a5,0", instruction_debug(&Instruction::new(0x00078513_u64.to_le()), 0));
|
||||
assert_eq!("ld s0,24(sp)", instruction_debug(&Instruction::new(0x01813403_u64.to_le()), 0));
|
||||
assert_eq!("addi sp,sp,32", instruction_debug(&Instruction::new(0x02010113_u64.to_le()), 0));
|
||||
assert_eq!("jalr zero,0(ra)", instruction_debug(&Instruction::new(0x00008067_u64.to_le()), 0));
|
||||
assert_eq!("addi sp,sp,-32", instruction_debug(&Instruction::new(0xfe010113), 0));
|
||||
assert_eq!("sd s0,24(sp)", instruction_debug(&Instruction::new(0x00813c23), 0));
|
||||
assert_eq!("addi s0,sp,32", instruction_debug(&Instruction::new(0x02010413), 0));
|
||||
assert_eq!("sw zero,-20(s0)", instruction_debug(&Instruction::new(0xfe042623), 0));
|
||||
assert_eq!("addi a5,zero,5", instruction_debug(&Instruction::new(0x00500793), 0));
|
||||
assert_eq!("sw a5,-24(s0)", instruction_debug(&Instruction::new(0xfef42423), 0));
|
||||
assert_eq!("lw a5,-24(s0)", instruction_debug(&Instruction::new(0xfe842783), 0));
|
||||
assert_eq!("sw a5,-20(s0)", instruction_debug(&Instruction::new(0xfef42623), 0));
|
||||
assert_eq!("lw a5,-20(s0)", instruction_debug(&Instruction::new(0xfec42783), 0));
|
||||
assert_eq!("addi a4,a5,0", instruction_debug(&Instruction::new(0x00078713), 0));
|
||||
assert_eq!("lw a5,-24(s0)", instruction_debug(&Instruction::new(0xfe842783), 0));
|
||||
assert_eq!("mulw a5,a4,a5", instruction_debug(&Instruction::new(0x02f707bb), 0));
|
||||
assert_eq!("sw a5,-20(s0)", instruction_debug(&Instruction::new(0xfef42623), 0));
|
||||
assert_eq!("lw a5,-20(s0)", instruction_debug(&Instruction::new(0xfec42783), 0));
|
||||
assert_eq!("addi a4,a5,0", instruction_debug(&Instruction::new(0x00078713), 0));
|
||||
assert_eq!("lw a5,-24(s0)", instruction_debug(&Instruction::new(0xfe842783), 0));
|
||||
assert_eq!("addw a5,a4,a5", instruction_debug(&Instruction::new(0x00f707bb), 0));
|
||||
assert_eq!("sw a5,-20(s0)", instruction_debug(&Instruction::new(0xfef42623), 0));
|
||||
assert_eq!("lw a5,-20(s0)", instruction_debug(&Instruction::new(0xfec42783), 0));
|
||||
assert_eq!("addi a4,a5,0", instruction_debug(&Instruction::new(0x00078713), 0));
|
||||
assert_eq!("lw a5,-24(s0)", instruction_debug(&Instruction::new(0xfe842783), 0));
|
||||
assert_eq!("subw a5,a4,a5", instruction_debug(&Instruction::new(0x40f707bb), 0));
|
||||
assert_eq!("sw a5,-24(s0)", instruction_debug(&Instruction::new(0xfef42423), 0));
|
||||
assert_eq!("addi a5,zero,0", instruction_debug(&Instruction::new(0x00000793), 0));
|
||||
assert_eq!("addi a0,a5,0", instruction_debug(&Instruction::new(0x00078513), 0));
|
||||
assert_eq!("ld s0,24(sp)", instruction_debug(&Instruction::new(0x01813403), 0));
|
||||
assert_eq!("addi sp,sp,32", instruction_debug(&Instruction::new(0x02010113), 0));
|
||||
assert_eq!("jalr zero,0(ra)", instruction_debug(&Instruction::new(0x00008067), 0));
|
||||
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_fibo() {
|
||||
assert_eq!("jal zero,10504", instruction_debug(&Instruction::new(0x0500006f_u64.to_le()), 0x104b4));
|
||||
assert_eq!("blt a4,a5,104b8", instruction_debug(&Instruction::new(0xfaf740e3_u64.to_le()), 0x10518));
|
||||
assert_eq!("jal zero,10504", instruction_debug(&Instruction::new(0x0500006f), 0x104b4));
|
||||
assert_eq!("blt a4,a5,104b8", instruction_debug(&Instruction::new(0xfaf740e3), 0x10518));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mul_prog() {
|
||||
assert_eq!("addi sp,sp,-32", instruction_debug(&Instruction::new(0xfe010113_u64.to_le()), 0));
|
||||
assert_eq!("sd s0,24(sp)", instruction_debug(&Instruction::new(0x00813c23_u64.to_le()), 0));
|
||||
assert_eq!("addi s0,sp,32", instruction_debug(&Instruction::new(0x02010413_u64.to_le()), 0));
|
||||
assert_eq!("addi a5,zero,5", instruction_debug(&Instruction::new(0x00500793_u64.to_le()), 0));
|
||||
assert_eq!("sw a5,-20(s0)", instruction_debug(&Instruction::new(0xfef42623_u64.to_le()), 0));
|
||||
assert_eq!("lw a5,-20(s0)", instruction_debug(&Instruction::new(0xfec42783_u64.to_le()), 0));
|
||||
assert_eq!("addi a4,a5,0", instruction_debug(&Instruction::new(0x00078713_u64.to_le()), 0));
|
||||
assert_eq!("addi a5,a4,0", instruction_debug(&Instruction::new(0x00070793_u64.to_le()), 0));
|
||||
assert_eq!("slliw a5,a5,0x2", instruction_debug(&Instruction::new(0x0027979b_u64.to_le()), 0));
|
||||
assert_eq!("addw a5,a5,a4", instruction_debug(&Instruction::new(0x00e787bb_u64.to_le()), 0));
|
||||
assert_eq!("sw a5,-24(s0)", instruction_debug(&Instruction::new(0xfef42423_u64.to_le()), 0));
|
||||
assert_eq!("lw a5,-20(s0)", instruction_debug(&Instruction::new(0xfec42783_u64.to_le()), 0));
|
||||
assert_eq!("addi a4,a5,0", instruction_debug(&Instruction::new(0x00078713_u64.to_le()), 0));
|
||||
assert_eq!("lw a5,-24(s0)", instruction_debug(&Instruction::new(0xfe842783_u64.to_le()), 0));
|
||||
assert_eq!("mulw a5,a4,a5", instruction_debug(&Instruction::new(0x02f707bb_u64.to_le()), 0));
|
||||
assert_eq!("sw a5,-28(s0)", instruction_debug(&Instruction::new(0xfef42223_u64.to_le()), 0));
|
||||
assert_eq!("lw a5,-28(s0)", instruction_debug(&Instruction::new(0xfe442783_u64.to_le()), 0));
|
||||
assert_eq!("addi a4,a5,0", instruction_debug(&Instruction::new(0x00078713_u64.to_le()), 0));
|
||||
assert_eq!("lw a5,-24(s0)", instruction_debug(&Instruction::new(0xfe842783_u64.to_le()), 0));
|
||||
assert_eq!("divw a5,a4,a5", instruction_debug(&Instruction::new(0x02f747bb_u64.to_le()), 0));
|
||||
assert_eq!("sw a5,-20(s0)", instruction_debug(&Instruction::new(0xfef42623_u64.to_le()), 0));
|
||||
assert_eq!("addi a5,zero,0", instruction_debug(&Instruction::new(0x00000793_u64.to_le()), 0));
|
||||
assert_eq!("addi a0,a5,0", instruction_debug(&Instruction::new(0x00078513_u64.to_le()), 0));
|
||||
assert_eq!("ld s0,24(sp)", instruction_debug(&Instruction::new(0x01813403_u64.to_le()), 0));
|
||||
assert_eq!("addi sp,sp,32", instruction_debug(&Instruction::new(0x02010113_u64.to_le()), 0));
|
||||
assert_eq!("jalr zero,0(ra)", instruction_debug(&Instruction::new(0x00008067_u64.to_le()), 0));
|
||||
assert_eq!("addi sp,sp,-32", instruction_debug(&Instruction::new(0xfe010113), 0));
|
||||
assert_eq!("sd s0,24(sp)", instruction_debug(&Instruction::new(0x00813c23), 0));
|
||||
assert_eq!("addi s0,sp,32", instruction_debug(&Instruction::new(0x02010413), 0));
|
||||
assert_eq!("addi a5,zero,5", instruction_debug(&Instruction::new(0x00500793), 0));
|
||||
assert_eq!("sw a5,-20(s0)", instruction_debug(&Instruction::new(0xfef42623), 0));
|
||||
assert_eq!("lw a5,-20(s0)", instruction_debug(&Instruction::new(0xfec42783), 0));
|
||||
assert_eq!("addi a4,a5,0", instruction_debug(&Instruction::new(0x00078713), 0));
|
||||
assert_eq!("addi a5,a4,0", instruction_debug(&Instruction::new(0x00070793), 0));
|
||||
assert_eq!("slliw a5,a5,0x2", instruction_debug(&Instruction::new(0x0027979b), 0));
|
||||
assert_eq!("addw a5,a5,a4", instruction_debug(&Instruction::new(0x00e787bb), 0));
|
||||
assert_eq!("sw a5,-24(s0)", instruction_debug(&Instruction::new(0xfef42423), 0));
|
||||
assert_eq!("lw a5,-20(s0)", instruction_debug(&Instruction::new(0xfec42783), 0));
|
||||
assert_eq!("addi a4,a5,0", instruction_debug(&Instruction::new(0x00078713), 0));
|
||||
assert_eq!("lw a5,-24(s0)", instruction_debug(&Instruction::new(0xfe842783), 0));
|
||||
assert_eq!("mulw a5,a4,a5", instruction_debug(&Instruction::new(0x02f707bb), 0));
|
||||
assert_eq!("sw a5,-28(s0)", instruction_debug(&Instruction::new(0xfef42223), 0));
|
||||
assert_eq!("lw a5,-28(s0)", instruction_debug(&Instruction::new(0xfe442783), 0));
|
||||
assert_eq!("addi a4,a5,0", instruction_debug(&Instruction::new(0x00078713), 0));
|
||||
assert_eq!("lw a5,-24(s0)", instruction_debug(&Instruction::new(0xfe842783), 0));
|
||||
assert_eq!("divw a5,a4,a5", instruction_debug(&Instruction::new(0x02f747bb), 0));
|
||||
assert_eq!("sw a5,-20(s0)", instruction_debug(&Instruction::new(0xfef42623), 0));
|
||||
assert_eq!("addi a5,zero,0", instruction_debug(&Instruction::new(0x00000793), 0));
|
||||
assert_eq!("addi a0,a5,0", instruction_debug(&Instruction::new(0x00078513), 0));
|
||||
assert_eq!("ld s0,24(sp)", instruction_debug(&Instruction::new(0x01813403), 0));
|
||||
assert_eq!("addi sp,sp,32", instruction_debug(&Instruction::new(0x02010113), 0));
|
||||
assert_eq!("jalr zero,0(ra)", instruction_debug(&Instruction::new(0x00008067), 0));
|
||||
}
|
||||
|
||||
}
|
@ -479,12 +479,7 @@ impl Loader {
|
||||
buf[k] = self.bytes.get(section.image_offset as usize + j + k).copied().ok_or(LoaderError::ParsingError(format!("index 0x{:x} is out of bound because list have a size of 0x{:x} (image offset 0x{:x}, j 0x{:x}, k 0x{:x})", section.image_offset as usize + j + k, self.bytes.len(), section.image_offset, j, k)))?;
|
||||
}
|
||||
}
|
||||
|
||||
machine.write_memory(1, start_index + section.virt_addr as usize + j, buf[0] as u64);
|
||||
machine.write_memory(1, start_index + section.virt_addr as usize + j + 1, buf[1] as u64);
|
||||
machine.write_memory(1, start_index + section.virt_addr as usize + j + 2, buf[2] as u64);
|
||||
machine.write_memory(1, start_index + section.virt_addr as usize + j + 3, buf[3] as u64);
|
||||
|
||||
machine.write_memory(4, start_index + section.virt_addr as usize + j, u32::from_le_bytes(buf) as u64);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -96,7 +96,6 @@ pub struct Machine {
|
||||
//creer une struct cfg(configuration) qui s'initialise avec valeur dans un fichier cfg
|
||||
num_phy_page: u64,
|
||||
pub page_size: u64,
|
||||
pub user_stack_size: u64,
|
||||
/// Current machine status
|
||||
pub status: MachineStatus
|
||||
}
|
||||
@ -116,8 +115,7 @@ impl Machine {
|
||||
|
||||
let num_phy_page = *settings.get(&MachineSettingKey::NumPhysPages).unwrap();
|
||||
let page_size = *settings.get(&MachineSettingKey::PageSize).unwrap();
|
||||
let user_stack_size = *settings.get(&MachineSettingKey::UserStackSize).unwrap();
|
||||
let mem_size = (page_size*num_phy_page) as usize;
|
||||
let mem_size = (page_size*num_phy_page*100_000) as usize;
|
||||
|
||||
Machine {
|
||||
debug,
|
||||
@ -131,8 +129,7 @@ impl Machine {
|
||||
registers_trace : String::from(""),
|
||||
status: MachineStatus::SystemMode,
|
||||
num_phy_page,
|
||||
page_size,
|
||||
user_stack_size
|
||||
page_size
|
||||
}
|
||||
}
|
||||
|
||||
@ -287,7 +284,7 @@ impl Machine {
|
||||
*elem = self.main_memory[self.pc as usize + i];
|
||||
}
|
||||
|
||||
let val = u32::from_le_bytes(val) as u64;
|
||||
let val = u32::from_be_bytes(val) as u64;
|
||||
let inst : Instruction = Instruction::new(val);
|
||||
if self.debug {
|
||||
self.print_status();
|
||||
@ -428,10 +425,10 @@ impl Machine {
|
||||
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, shamt),
|
||||
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 { // SRAI
|
||||
} else {
|
||||
compute(&core::ops::Shr::shr, rs1, shamt)
|
||||
}
|
||||
_ => Err(format!("Unreachable in opi_instruction match! Instruction was {:?}", inst))?
|
||||
@ -504,8 +501,8 @@ impl Machine {
|
||||
let local_data = self.int_reg.get_reg(inst.rs1);
|
||||
let result = match inst.funct3 {
|
||||
RISCV_OPIW_ADDIW => local_data + inst.imm12_I_signed as i64,
|
||||
RISCV_OPIW_SLLIW => local_data << inst.rs2,
|
||||
RISCV_OPIW_SRW => (local_data >> inst.rs2) & if inst.funct7 == RISCV_OPIW_SRW_SRLIW { self.shiftmask[32 + inst.rs2 as usize] as i64 } else { 1 },
|
||||
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(format!("Unreachable in op_instruction match! Instruction was {:?}", inst))?
|
||||
};
|
||||
self.int_reg.set_reg(inst.rd, result);
|
||||
@ -522,7 +519,7 @@ impl Machine {
|
||||
|
||||
// Match case for multiplication operations (in standard extension RV32M)
|
||||
match inst.funct3 {
|
||||
RISCV_OPW_M_MULW => self.int_reg.set_reg(inst.rd, (local_data_a * local_data_b) & 0xffffffff),
|
||||
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),
|
||||
@ -541,9 +538,9 @@ impl Machine {
|
||||
},
|
||||
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 {
|
||||
self.int_reg.set_reg(inst.rd, local_dataa >> (local_datab /* & 0x1f */) & self.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
|
||||
self.int_reg.set_reg(inst.rd, local_dataa >> (local_datab /* & 0x1f */))
|
||||
self.int_reg.set_reg(inst.rd, local_dataa >> (local_datab & 0x1f))
|
||||
},
|
||||
_ => Err(format!("Unreachable in opw_instruction match! Instruction was {:?}", inst))?
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ use std::{fs, io::{BufRead, BufReader, Lines, Error}};
|
||||
use crate::Machine;
|
||||
|
||||
/// File section
|
||||
pub struct SectionFormat {
|
||||
pub struct SectionFormat{
|
||||
/// Memory address of the section
|
||||
addr: String,
|
||||
/// The size of data in bytes
|
||||
@ -43,7 +43,7 @@ pub struct SectionFormat {
|
||||
/// # Memory section
|
||||
///
|
||||
/// Representation of a section of memory from BurritOS or NachOS
|
||||
pub struct Section {
|
||||
pub struct Section{
|
||||
/// Memory address of the section
|
||||
addr: usize,
|
||||
/// The size of data in bytes
|
||||
@ -53,23 +53,15 @@ pub struct Section {
|
||||
}
|
||||
|
||||
impl Section {
|
||||
|
||||
/// Creates a memory section from a SectionFormat
|
||||
fn from(section: &mut SectionFormat) -> Section {
|
||||
fn from(section: &SectionFormat) -> Section {
|
||||
let addr = usize::from_str_radix(§ion.addr, 16).unwrap_or_default();
|
||||
let len = usize::from_str_radix(§ion.len, 16).unwrap_or_default();
|
||||
let content: Vec<u8>;
|
||||
unsafe {
|
||||
content = section.content.as_bytes_mut()
|
||||
.chunks_mut(4).map(
|
||||
|x| {
|
||||
x.reverse();
|
||||
u8::from_str_radix(
|
||||
std::str::from_utf8(x).unwrap_or_default(), 16
|
||||
).unwrap_or_default()
|
||||
}
|
||||
).collect();
|
||||
}
|
||||
Section { addr, len, content }
|
||||
let content: Vec<u8> = section.content.as_bytes().chunks(2).map(|x| {
|
||||
u8::from_str_radix(std::str::from_utf8(x).unwrap_or_default(), 16).unwrap_or_default()
|
||||
}).collect();
|
||||
Section{addr, len, content}
|
||||
}
|
||||
|
||||
/// Pretty prints a memory section
|
||||
@ -93,7 +85,7 @@ pub struct MemChecker {
|
||||
}
|
||||
|
||||
|
||||
impl MemChecker {
|
||||
impl MemChecker{
|
||||
|
||||
///Translate lines of a file in e Vector of String
|
||||
///We need this method to parse the memory we received
|
||||
@ -151,12 +143,12 @@ impl MemChecker {
|
||||
}
|
||||
else {
|
||||
//lecture ligne CONTENT
|
||||
let mut section_f = SectionFormat {
|
||||
let section_f = SectionFormat{
|
||||
addr: tmp_addr_str.clone(),
|
||||
len: tmp_len_str.clone(),
|
||||
content: current_line.clone().replace(' ', ""),
|
||||
};
|
||||
sections.push(Section::from(&mut section_f));
|
||||
sections.push(Section::from(§ion_f));
|
||||
}
|
||||
|
||||
}
|
||||
@ -194,7 +186,7 @@ impl MemChecker {
|
||||
machine.pc = m_c.pc as u64;
|
||||
|
||||
for section in m_c.sections.iter() {
|
||||
for (i, b) in section.content.iter().enumerate() {
|
||||
for (i,b) in section.content.iter().enumerate() {
|
||||
machine.main_memory[section.addr + i] = *b;
|
||||
}
|
||||
}
|
||||
@ -260,12 +252,12 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_create_section_content(){
|
||||
let mut section_format = SectionFormat{
|
||||
let section_format = SectionFormat{
|
||||
addr: "0".to_string(),
|
||||
len: "0".to_string(),
|
||||
content: "00FF0AA0A5".to_string(),
|
||||
};
|
||||
let section = Section::from(&mut section_format);
|
||||
let section = Section::from(§ion_format);
|
||||
let expected_vec: Vec<u8> = vec![0u8, 255u8, 10u8, 160u8, 165u8];
|
||||
assert_eq!(section.content, expected_vec);
|
||||
}
|
||||
|
@ -223,7 +223,7 @@ pub mod global {
|
||||
///
|
||||
/// Shift left logical immediate
|
||||
///
|
||||
/// `SLLI rd, rs1, shamt` => `rd <- rs1 << shamt`
|
||||
/// `SLLI rd, rs1, shamt` => `rd <- rs1 >> shamt`
|
||||
pub const RISCV_OPI_SLLI: u8 = 0x1;
|
||||
/// Shift right immediate, may be SRAI or SRLI
|
||||
pub const RISCV_OPI_SRI: u8 = 0x5;
|
||||
|
@ -93,17 +93,13 @@ pub fn read_settings() -> Result<Settings, Error> {
|
||||
}
|
||||
|
||||
/// Returns a mock configuration for Machine unit testing
|
||||
///
|
||||
/// FIXME: Does not cover the whole configuration yet
|
||||
pub fn get_debug_configuration() -> Settings {
|
||||
let mut settings_map = Settings::new();
|
||||
settings_map.insert(MachineSettingKey::PageSize, 2048);
|
||||
settings_map.insert(MachineSettingKey::NumPhysPages, 8192);
|
||||
settings_map.insert(MachineSettingKey::UserStackSize, 4096);
|
||||
settings_map.insert(MachineSettingKey::PageSize, 128);
|
||||
settings_map.insert(MachineSettingKey::NumPhysPages, 400);
|
||||
settings_map
|
||||
}
|
||||
|
||||
/// Removes comments and empty lines
|
||||
/// Filters out empty lines and comments from the reader `BufReader`.
|
||||
///
|
||||
/// Returns a [`Vec<String>`], each entry containing a valid
|
||||
@ -115,7 +111,6 @@ fn filter_garbage<R: std::io::Read>(reader: BufReader<R>) -> Vec<String> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Inserts user settings into setting map
|
||||
/// Adds a <K, V> pair to a [`Settings`] map.
|
||||
///
|
||||
/// Returns the updated [`Settings`].
|
||||
|
@ -1,13 +1,15 @@
|
||||
int main() {
|
||||
int x = 0;
|
||||
int y = 1;
|
||||
while (x <= y) {
|
||||
if (x > y) {
|
||||
x += 1;
|
||||
}
|
||||
if (x == y) {
|
||||
} else if (x == y) {
|
||||
x += y;
|
||||
}
|
||||
if (x < y) {
|
||||
} else if (x < y) {
|
||||
y += 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
PROGRAMS = halt.guac prints.guac producteur_consommateur.guac lock.guac join.guac matmult.guac
|
||||
PROGRAMS = halt.guac prints.guac producteur_consommateur.guac join.guac
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Makefile.rules
|
||||
|
||||
|
@ -1,29 +0,0 @@
|
||||
#include "userlib/syscall.h"
|
||||
#include "userlib/libnachos.h"
|
||||
|
||||
LockId mutex;
|
||||
int glob_int = 0;
|
||||
|
||||
void increment(void){
|
||||
LockAcquire(mutex);
|
||||
glob_int++;
|
||||
LockRelease(mutex);
|
||||
}
|
||||
|
||||
void counter(int n){
|
||||
for (int i = 0; i < 50; i++){
|
||||
increment();
|
||||
}
|
||||
}
|
||||
|
||||
int main(void){
|
||||
mutex = LockCreate("Lock_debug");
|
||||
|
||||
ThreadId th1 = threadCreate("Thread1", (VoidNoArgFunctionPtr) counter);
|
||||
ThreadId th2 = threadCreate("Thread2",(VoidNoArgFunctionPtr) counter);
|
||||
|
||||
Join(th1);
|
||||
Join(th2);
|
||||
Exit(glob_int);
|
||||
return 0;
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
/* matmult.c
|
||||
* Test program to do matrix multiplication on large arrays.
|
||||
*
|
||||
* Intended to stress virtual memory system.
|
||||
*
|
||||
* Ideally, we could read the matrices off of the file system,
|
||||
* and store the result back to the file system!
|
||||
*
|
||||
* -----------------------------------------------------
|
||||
* This file is part of the Nachos-RiscV distribution
|
||||
* Copyright (c) 2022 University of Rennes 1.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details
|
||||
* (see see <http://www.gnu.org/licenses/>).
|
||||
* -----------------------------------------------------
|
||||
|
||||
*/
|
||||
|
||||
#include "userlib/syscall.h"
|
||||
|
||||
#define Dim 10 /* sum total of the arrays doesn't fit in
|
||||
* physical memory
|
||||
*/
|
||||
|
||||
/* The matrices to be filled-in and multiplied */
|
||||
int A[Dim][Dim];
|
||||
int B[Dim][Dim];
|
||||
int C[Dim][Dim];
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
int i, j, k;
|
||||
|
||||
Write("Start matmult\n",14,CONSOLE_OUTPUT);
|
||||
|
||||
for (i = 0; i < Dim; i++) /* first initialize the matrices */
|
||||
for (j = 0; j < Dim; j++) {
|
||||
A[i][j] = i;
|
||||
B[i][j] = j;
|
||||
C[i][j] = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < Dim; i++) /* then multiply them together */
|
||||
for (j = 0; j < Dim; j++)
|
||||
for (k = 0; k < Dim; k++)
|
||||
C[i][j] += A[i][k] * B[k][j];
|
||||
|
||||
|
||||
Exit(C[Dim-1][Dim-1]); /* and then we're done */
|
||||
|
||||
return 0;
|
||||
}
|
@ -2,53 +2,9 @@
|
||||
#include "userlib/libnachos.h"
|
||||
|
||||
int main() {
|
||||
n_printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
|
||||
n_printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&##BBGGGPPGGGBB##&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
|
||||
n_printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&#G5J?!~^::............::^~!?J5G#&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
|
||||
n_printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@&B5?!^:....:^^~!!7777??7777!!~~^::...:^!JPB&@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
|
||||
n_printf("@@@@@@@@@@@@@@@@@@@@@@@@@B57^....^~!?JJYYY5555555555555555Y5PGP57~::..:^75B@@@@@@@@@@@@@@@@@@@@@@@@@\n");
|
||||
n_printf("@@@@@@@@@@@@@@@@@@@@@&G?~. .:~7?JY55555YYYYYYYYYYYYYYYYY5PB##BPY???7!~^:..:~JG&@@@@@@@@@@@@@@@@@@@@@\n");
|
||||
n_printf("@@@@@@@@@@@@@@@@@@@BJ~. .^!?Y5555YYYYYYYYYYYYYYYYYYYY5PB##B5J?77???????7!~^:.:~JB@@@@@@@@@@@@@@@@@@@\n");
|
||||
n_printf("@@@@@@@@@@@@@@@@&P!. .^!JY55YYYYYYYYYYYYYYYYYYYYYY5PB##B5J?77??????????????7~^:.:!P&@@@@@@@@@@@@@@@@\n");
|
||||
n_printf("@@@@@@@@@@@@@@&Y^..:~?Y55YYYYYYYYYYYYYYYYYYYYYY5PB##B5J?77????????????????????7~:.:~5&@@@@@@@@@@@@@@\n");
|
||||
n_printf("@@@@@@@@@@@@&5^..:!J55YYYYYYYYYYYYYYYYYYYYYY5PB##B5J?77?????????????????????????7~^::~5@@@@@@@@@@@@@\n");
|
||||
n_printf("@@@@@@@@@@@G~..:!Y55YYYYYYYYYYYYYYYYYYYYY5PB##B5J?77??????????????????????????????7~:::!B@@@@@@@@@@@\n");
|
||||
n_printf("@@@@@@@@@&J...~J55YYYYYYYYYYYYYYYYYYYY5PB##B5J?77??????????????????????????????777?Y57:::J&@@@@@@@@@\n");
|
||||
n_printf("@@@@@@@@#!..:7Y5YYYYYYYYYYYYYYYYYYY5PB##B5J?77??????????????????????????????777?YPB##G?^::7#@@@@@@@@\n");
|
||||
n_printf("@@@@@@@G^..^J5YYYYYYYYYYYYYYYYYY5PB##B5J?77??????????????????????????????777?YPB##GP5Y5J~::~B@@@@@@@\n");
|
||||
n_printf("@@@@@@G^..^Y5YYYYYYYYYYYYYYYY5PB##B5J?77??????????????????????????????777?YPB##GP55Y5555Y~::^B@@@@@@\n");
|
||||
n_printf("@@@@@B^..^Y5YYYYYYYYYYYYYY5PB##B5J?77??????????????????????????????777?YPB##GP5YYYY555555Y~::~B@@@@@\n");
|
||||
n_printf("@@@@&!..^J5YYYYYYYYYYYY5PB##B5J?77??????????????????????????????777?YPB#BGPYYYYYY555555555Y~::7&@@@@\n");
|
||||
n_printf("@@@@J..:?5YYYYYYYYYY5PB##B5J?77??????????????????????????????777?YPB#BG5YYYYYYY55YY55555555J^::Y@@@@\n");
|
||||
n_printf("@@@B:..~5YYYYYYYY5PB##G5J?77??????????????????????????????777?YPB#BG5YYYYYYYY5YYY55555555555!::^#@@@\n");
|
||||
n_printf("@@@?..:JYYYYYY5PB##G5J?77??????????????????????????????777?YPB#BG5YYYYYYYYYYYYY55YY555555555Y^::J@@@\n");
|
||||
n_printf("@@&^..~YYYY5PB##G5J?77??????????????????????????????777?YPB#BG5YYYYYYYYYYYYYYYYYY5555Y5555555!::~&@@\n");
|
||||
n_printf("@@G:..7Y5PB##G5J?77??????????????????????????????777?YPB#BG5YJYYYYYYYYYYYYYYYYY55YYY555555555?::^B@@\n");
|
||||
n_printf("@@5:..YB##G5J?77??????????????????????????????777?YPB#BG5JJJYYYJYYYYYYYYYYYYYY5YY5555Y5555555J:^^P@@\n");
|
||||
n_printf("@@5:..PB5J?77??????????????????????????????777?YGB#BG5JJJYYJYYYYYYYYYYYYYYYYYYY55Y55555555555J:^^5@@\n");
|
||||
n_printf("@@5:..7?77??????????????????????????????777?YPB#BG5JJJJJJJJYYYYYYYYYYYYYYYYYYY5YY5Y5555555555J:^^P@@\n");
|
||||
n_printf("@@G:..~??????????????????????????????777?YGB#BPYJJJJJJJJJJJYYYYYYYYYYYYYYYYYYYY5YY55555555555?:^^B@@\n");
|
||||
n_printf("@@&^..^???????????????????????????777?YGB#BPYJ?JJJJJJJJJJJYYJYYYYYYYYYYYYYYYYY5YY5Y5555555555!^:~@@@\n");
|
||||
n_printf("@@@?.::7???????????????????????777?YGB#BPYJ???JJJJJJJJJJJJJYYYYYYYYYYYYYYYYYYYYYYY5555555555Y^^:J@@@\n");
|
||||
n_printf("@@@#:..^????????????????????777?YG##BPYJ????JJJJJJJJJJJJJJYJJYYYYYYYYYYYYYYYYY5YYYY555555555!^^^#@@@\n");
|
||||
n_printf("@@@@J.::!????????????????777?YG##BPY???????JJJJJJJJJJJJJJJJYYYYYYYYYYYYYYYYYY5YYY5555555555J^^:Y@@@@\n");
|
||||
n_printf("@@@@&!..:7????????????777?YGB#BPJ????????????JJJJJJJJJJJJYYJJYYYYYYYYYYYYYYYYYY55YY5555555Y~::7&@@@@\n");
|
||||
n_printf("@@@@@B^.:^7????????777?YGB#BPJ?7???????????JJJ?JJJJJJJJJJJJYYYYJYYYYYYYYYYYYYYYYY5555Y555Y~^:~B@@@@@\n");
|
||||
n_printf("@@@@@@G^.:^7????777?YGB#BPJ?7????????????????JJJJJJJJJJJJYYJJYYYYYYYYYYYYYYYYYY55YYY5555Y~::~B@@@@@@\n");
|
||||
n_printf("@@@@@@@B^.:^7?77?YGB#BPJ?77??7?????????????JJJ?JJJJJJJJJJJJYYYYJYYYYYYYYYYYYYYYYY5555Y5J~::~B@@@@@@@\n");
|
||||
n_printf("@@@@@@@@#!..:!YG##BPJ?77?????????????????????JJJJJJJJJJJJYYJYYYYYYYYYYYYYYYYYYY55YYY55?^::7#@@@@@@@@\n");
|
||||
n_printf("@@@@@@@@@&J:.:7PPY?77???7????7??????????????JJ?JJJJJJJJJJJJYYYYJYYYYYYYYYYYYYY5YY555J!^:^Y&@@@@@@@@@\n");
|
||||
n_printf("@@@@@@@@@@@G!..:~7?????????????????????????JJJJJJJJJJJJJJYYJYYYYYYYYYYYYYYYYYYY555Y7^::7G@@@@@@@@@@@\n");
|
||||
n_printf("@@@@@@@@@@@@@5~..:~7????????????????????????JJJJJJJJJJJJJJJYJYYYYYYYYYYYYYYYYY5YY7^::~5@@@@@@@@@@@@@\n");
|
||||
n_printf("@@@@@@@@@@@@@@&Y~..:~7?????????????????????JJJJJJJJJJJJJJJJYYYYYYYYYYYYYYYYY5YJ!^::!5&@@@@@@@@@@@@@@\n");
|
||||
n_printf("@@@@@@@@@@@@@@@@&P!:.:^~7???????????????????JJJJJJJJJJJJJJJJJYYYYYYYYYYYYYYJ7~::^7P&@@@@@@@@@@@@@@@@\n");
|
||||
n_printf("@@@@@@@@@@@@@@@@@@@BJ~:.:^~77??????????????JJ?JJJJJJJJJJJJJYYYYYYYYYYYYYJ7~^::!YB@@@@@@@@@@@@@@@@@@@\n");
|
||||
n_printf("@@@@@@@@@@@@@@@@@@@@@&GJ~:.::~!!7????????????JJJJJJJJJJJJJYJJYYYYYYJ?7!^::^!JG&@@@@@@@@@@@@@@@@@@@@@\n");
|
||||
n_printf("@@@@@@@@@@@@@@@@@@@@@@@@@B5?~::::^~~!7????JJJJJJJJJJJJYYJJJJJJ?77!~^::^~?5B@@@@@@@@@@@@@@@@@@@@@@@@@\n");
|
||||
n_printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@&BPJ7~^:::::^~~~!!77777777!!!~~^^::::^~7JPB&@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
|
||||
n_printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&#G5Y?7!~^^::::::::::::^~~!7JYPG#&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
|
||||
n_printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&&##BGGGGGGGBB##&&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
|
||||
n_printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
|
||||
Shutdown();
|
||||
n_printf("Hello World 1");
|
||||
n_printf("Hello World 2");
|
||||
n_printf("Hello World 3");
|
||||
n_printf("Hello World 4");
|
||||
return 0;
|
||||
}
|
@ -9,32 +9,9 @@ int tab[3];
|
||||
SemId svide;
|
||||
SemId splein;
|
||||
|
||||
void producteur() {
|
||||
for(int i = 0; i < 10; i++)
|
||||
{
|
||||
n_printf("batir une information\n");
|
||||
P(svide);
|
||||
iplein = (iplein + 1) % N;
|
||||
// n_printf("communique une information : %d\n", i);
|
||||
tab[iplein] = i;
|
||||
V(splein);
|
||||
}
|
||||
}
|
||||
void producteur();
|
||||
|
||||
void consommateur() {
|
||||
int sum = 0;
|
||||
for(int i = 0; i < 10; i++)
|
||||
{
|
||||
P(splein);
|
||||
ivide = (ivide +1) % N;
|
||||
n_printf("recevoir une information\n");
|
||||
int info = tab[ivide];
|
||||
V(svide);
|
||||
sum += info;
|
||||
// n_printf("exploiter l'information : %d\n", info);
|
||||
}
|
||||
Exit(sum);
|
||||
}
|
||||
void consommateur();
|
||||
|
||||
int main() {
|
||||
svide = SemCreate("producteur", N);
|
||||
@ -43,6 +20,29 @@ int main() {
|
||||
ThreadId consommateurTh = threadCreate("consommateur", consommateur);
|
||||
Join(producteurTh);
|
||||
Join(consommateurTh);
|
||||
Shutdown();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void producteur() {
|
||||
for(int i = 0; i < 10; i++)
|
||||
{
|
||||
n_printf("batir une information\n");
|
||||
P(svide);
|
||||
iplein = (iplein + 1) % N;
|
||||
n_printf("communique une information : %d\n", i);
|
||||
tab[iplein] = i;
|
||||
V(splein);
|
||||
}
|
||||
}
|
||||
|
||||
void consommateur() {
|
||||
for(int i = 0; i < 10; i++)
|
||||
{
|
||||
P(splein);
|
||||
ivide = (ivide +1) % N;
|
||||
n_printf("recevoir une information\n");
|
||||
int info = tab[ivide];
|
||||
V(svide);
|
||||
n_printf("exploiter l'information : %d\n", info);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user