From 5000c28b970bfa8bde974146d4aac5a48e2f4647 Mon Sep 17 00:00:00 2001 From: Quentin Legot Date: Sun, 7 May 2023 14:50:41 +0200 Subject: [PATCH 01/10] Fix endianness issues particulary with strings --- src/kernel/exception.rs | 8 ++++++-- src/simulator/loader.rs | 7 ++++++- src/simulator/machine.rs | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/kernel/exception.rs b/src/kernel/exception.rs index 45fb0c1..c982264 100644 --- a/src/kernel/exception.rs +++ b/src/kernel/exception.rs @@ -154,13 +154,17 @@ fn syscall(machine: &mut Machine, system: &mut System) -> Result Date: Sun, 7 May 2023 16:02:48 +0200 Subject: [PATCH 02/10] Fix instructions tests --- src/simulator/instruction.rs | 182 +++++++++---------- test/syscall_tests/prints.c | 9 +- test/syscall_tests/producteur_consommateur.c | 24 +-- 3 files changed, 106 insertions(+), 109 deletions(-) diff --git a/src/simulator/instruction.rs b/src/simulator/instruction.rs index f85f5ac..409955f 100644 --- a/src/simulator/instruction.rs +++ b/src/simulator/instruction.rs @@ -349,11 +349,11 @@ mod test { #[test] fn test_op() { - 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); + 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()); 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); - 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); + 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()); 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); - let lui_negatif = Instruction::new(0b11110001000011111000_11100_0110111); + let lui = Instruction::new(0b01110001000011111000_11100_0110111_u64.to_le()); + let lui_negatif = Instruction::new(0b11110001000011111000_11100_0110111_u64.to_le()); 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); - 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); + 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()); 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); - 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); + 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()); 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); - let slliw: Instruction = Instruction::new(0b0000000_10000_10001_001_11100_0011011); - let srai: Instruction = Instruction::new(0b010000010001_10001_101_11100_0010011); + 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()); 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); - 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); + 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()); 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), 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)); + 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)); } #[test] fn test_fibo() { - assert_eq!("jal zero,10504", instruction_debug(&Instruction::new(0x0500006f), 0x104b4)); - assert_eq!("blt a4,a5,104b8", instruction_debug(&Instruction::new(0xfaf740e3), 0x10518)); + 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)); } #[test] fn test_mul_prog() { - 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)); + 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)); } } \ No newline at end of file diff --git a/test/syscall_tests/prints.c b/test/syscall_tests/prints.c index c2f296a..7380d30 100644 --- a/test/syscall_tests/prints.c +++ b/test/syscall_tests/prints.c @@ -2,9 +2,10 @@ #include "userlib/libnachos.h" int main() { - n_printf("Hello World 1"); - n_printf("Hello World 2"); - n_printf("Hello World 3"); - n_printf("Hello World 4"); + n_printf("Hello World 1\n"); + n_printf("Hello World 2\n"); + n_printf("Hello World 3\n"); + n_printf("Hello World 4\n"); + Shutdown(); return 0; } \ No newline at end of file diff --git a/test/syscall_tests/producteur_consommateur.c b/test/syscall_tests/producteur_consommateur.c index f0126cb..07cf8c8 100644 --- a/test/syscall_tests/producteur_consommateur.c +++ b/test/syscall_tests/producteur_consommateur.c @@ -9,20 +9,6 @@ int tab[3]; SemId svide; SemId splein; -void producteur(); - -void consommateur(); - -int main() { - svide = SemCreate("producteur", N); - splein = SemCreate("consommateur", 0); - ThreadId producteurTh = threadCreate("producteur", producteur); - ThreadId consommateurTh = threadCreate("consommateur", consommateur); - Join(producteurTh); - Join(consommateurTh); - return 0; -} - void producteur() { for(int i = 0; i < 10; i++) { @@ -46,3 +32,13 @@ void consommateur() { n_printf("exploiter l'information : %d\n", info); } } + +int main() { + svide = SemCreate("producteur", N); + splein = SemCreate("consommateur", 0); + ThreadId producteurTh = threadCreate("producteur", producteur); + ThreadId consommateurTh = threadCreate("consommateur", consommateur); + Join(producteurTh); + Join(consommateurTh); + return 0; +} From 2884d5d479ce33df3c993bc01b9675f5fa19f290 Mon Sep 17 00:00:00 2001 From: Quentin Legot Date: Sun, 7 May 2023 16:09:45 +0200 Subject: [PATCH 03/10] Fix shutdown test exception --- src/kernel/exception.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/kernel/exception.rs b/src/kernel/exception.rs index c982264..223827a 100644 --- a/src/kernel/exception.rs +++ b/src/kernel/exception.rs @@ -353,9 +353,18 @@ 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); - - machine.write_memory(4, 0, 0b000000000000_00000_000_00000_1110011); // ecall - machine.write_memory(4, 4, 0b000000001010_00000_000_00001_0010011); // r1 <- 10 + 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 let mut system = System::new(true); machine.run(&mut system); // If the machine was stopped with no error, the shutdown worked From 7d29b92eba88479846ce086debbb9cf8413280aa Mon Sep 17 00:00:00 2001 From: Quentin Legot Date: Sun, 7 May 2023 16:56:38 +0200 Subject: [PATCH 04/10] temporary workaround for producteur_consommateur --- test/syscall_tests/producteur_consommateur.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/syscall_tests/producteur_consommateur.c b/test/syscall_tests/producteur_consommateur.c index 07cf8c8..95d43b8 100644 --- a/test/syscall_tests/producteur_consommateur.c +++ b/test/syscall_tests/producteur_consommateur.c @@ -15,7 +15,7 @@ void producteur() { n_printf("batir une information\n"); P(svide); iplein = (iplein + 1) % N; - n_printf("communique une information : %d\n", i); + // n_printf("communique une information : %d\n", i); tab[iplein] = i; V(splein); } @@ -29,7 +29,7 @@ void consommateur() { n_printf("recevoir une information\n"); int info = tab[ivide]; V(svide); - n_printf("exploiter l'information : %d\n", info); + // n_printf("exploiter l'information : %d\n", info); } } @@ -40,5 +40,6 @@ int main() { ThreadId consommateurTh = threadCreate("consommateur", consommateur); Join(producteurTh); Join(consommateurTh); + Shutdown(); return 0; } From 7be0c0accc367025908d5ab2747a5e7a8969f1c4 Mon Sep 17 00:00:00 2001 From: Quentin Legot Date: Tue, 9 May 2023 17:01:52 +0200 Subject: [PATCH 05/10] Add user_stack_size to Machine and use it for threads sp --- burritos.cfg | 2 +- src/kernel/exception.rs | 6 ++++-- src/kernel/thread_manager.rs | 14 ++++++++++++-- src/main.rs | 5 ++++- src/simulator/machine.rs | 21 ++++++++++++--------- src/simulator/mod.rs | 2 +- 6 files changed, 34 insertions(+), 16 deletions(-) diff --git a/burritos.cfg b/burritos.cfg index 6dedd7a..abf55f8 100755 --- a/burritos.cfg +++ b/burritos.cfg @@ -2,7 +2,7 @@ # BurritOS configuration file ################################################## -NumPhysPages = 400 +NumPhysPages = 40000000 UserStackSize = 4096 MaxFileNameSize = 256 NumDirEntries = 30 diff --git a/src/kernel/exception.rs b/src/kernel/exception.rs index 223827a..93f66ce 100644 --- a/src/kernel/exception.rs +++ b/src/kernel/exception.rs @@ -3,7 +3,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, self}, thread::Thread}; +use super::{system::System, thread::Thread}; /// The halt system call. Stops Burritos. pub const SC_SHUTDOWN: u8 = 0; @@ -282,7 +282,9 @@ fn sc_new_thread(machine: &mut Machine, system: &mut System) -> Result u64 { + self.sp_max + } + + pub fn set_sp_max(&mut self, sp_max: u64) { + self.sp_max = sp_max; + } + } #[cfg(test)] diff --git a/src/main.rs b/src/main.rs index a481d44..370d1f2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -55,7 +55,10 @@ fn main() { let owner1 = Process { num_thread: 0 }; let owner1 = Rc::new(RefCell::new(owner1)); - system.get_thread_manager().start_thread(Rc::clone(&thread_exec), owner1, loader.elf_header.entrypoint, ptr + machine.page_size, -1); + 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); + let to_run = system.get_thread_manager().find_next_to_run().unwrap(); system.get_thread_manager().switch_to(&mut machine, Rc::clone(&to_run)); diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index 5c87dea..67ac20c 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -96,6 +96,7 @@ 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 } @@ -115,7 +116,8 @@ impl Machine { let num_phy_page = *settings.get(&MachineSettingKey::NumPhysPages).unwrap(); let page_size = *settings.get(&MachineSettingKey::PageSize).unwrap(); - let mem_size = (page_size*num_phy_page*100_000) as usize; + let user_stack_size = *settings.get(&MachineSettingKey::UserStackSize).unwrap(); + let mem_size = (page_size*num_phy_page) as usize; Machine { debug, @@ -129,7 +131,8 @@ impl Machine { registers_trace : String::from(""), status: MachineStatus::SystemMode, num_phy_page, - page_size + page_size, + user_stack_size } } @@ -425,10 +428,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, imm12), + RISCV_OPI_SLLI => compute(&core::ops::Shl::shl, rs1, shamt), 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 { + } else { // SRAI compute(&core::ops::Shr::shr, rs1, shamt) } _ => Err(format!("Unreachable in opi_instruction match! Instruction was {:?}", inst))? @@ -501,8 +504,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.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 }, + 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 }, _ => Err(format!("Unreachable in op_instruction match! Instruction was {:?}", inst))? }; self.int_reg.set_reg(inst.rd, result); @@ -519,7 +522,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), + RISCV_OPW_M_MULW => self.int_reg.set_reg(inst.rd, (local_data_a * local_data_b) & 0xffffffff), 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), @@ -538,9 +541,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))? } diff --git a/src/simulator/mod.rs b/src/simulator/mod.rs index f764fbd..a0e55ba 100644 --- a/src/simulator/mod.rs +++ b/src/simulator/mod.rs @@ -214,7 +214,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; From 86113da9d3a0a76ac552c1565835faaffc244ae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Tue, 9 May 2023 19:32:33 +0200 Subject: [PATCH 06/10] Fixed missing UserStackSize from default configuration --- src/utility/cfg.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/utility/cfg.rs b/src/utility/cfg.rs index f12e51f..b2c671d 100644 --- a/src/utility/cfg.rs +++ b/src/utility/cfg.rs @@ -98,6 +98,7 @@ pub fn get_debug_configuration() -> Settings { let mut settings_map = Settings::new(); settings_map.insert(MachineSettingKey::PageSize, 128); settings_map.insert(MachineSettingKey::NumPhysPages, 400); + settings_map.insert(MachineSettingKey::UserStackSize, 4096); settings_map } From 15a04fb9dad8d2c37501ac3b31b5423b1cfbcdcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Tue, 9 May 2023 20:52:00 +0200 Subject: [PATCH 07/10] Fixed tests failing because of a too small memory --- src/simulator/mem_cmp.rs | 36 ++++++++++++++++++++++-------------- src/utility/cfg.rs | 12 ++++++++---- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/src/simulator/mem_cmp.rs b/src/simulator/mem_cmp.rs index 07f48b6..099d96f 100644 --- a/src/simulator/mem_cmp.rs +++ b/src/simulator/mem_cmp.rs @@ -14,7 +14,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 @@ -26,7 +26,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 @@ -36,15 +36,23 @@ pub struct Section{ } impl Section { - /// Creates a memory section from a SectionFormat - fn from(section: &SectionFormat) -> Section { + fn from(section: &mut 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 = 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} + let content: Vec; + 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 } } /// Pretty prints a memory section @@ -68,7 +76,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 @@ -126,12 +134,12 @@ impl MemChecker{ } else { //lecture ligne CONTENT - let section_f = SectionFormat{ + let mut section_f = SectionFormat { addr: tmp_addr_str.clone(), len: tmp_len_str.clone(), content: current_line.clone().replace(' ', ""), }; - sections.push(Section::from(§ion_f)); + sections.push(Section::from(&mut section_f)); } } @@ -169,7 +177,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; } } @@ -235,12 +243,12 @@ mod tests { #[test] fn test_create_section_content(){ - let section_format = SectionFormat{ + let mut section_format = SectionFormat{ addr: "0".to_string(), len: "0".to_string(), content: "00FF0AA0A5".to_string(), }; - let section = Section::from(§ion_format); + let section = Section::from(&mut section_format); let expected_vec: Vec = vec![0u8, 255u8, 10u8, 160u8, 165u8]; assert_eq!(section.content, expected_vec); } diff --git a/src/utility/cfg.rs b/src/utility/cfg.rs index b2c671d..87acfc4 100644 --- a/src/utility/cfg.rs +++ b/src/utility/cfg.rs @@ -93,25 +93,29 @@ pub fn read_settings() -> Result { } /// 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, 128); - settings_map.insert(MachineSettingKey::NumPhysPages, 400); + settings_map.insert(MachineSettingKey::PageSize, 2048); + settings_map.insert(MachineSettingKey::NumPhysPages, 8192); settings_map.insert(MachineSettingKey::UserStackSize, 4096); settings_map } +/// Removes comments and empty lines fn filter_garbage(reader: BufReader) -> Vec { reader.lines() .map(|l| l.unwrap()) - .filter(|l| !l.is_empty() && !l.starts_with("#")) + .filter(|l| !l.is_empty() && !l.starts_with('#')) .collect() } + +/// Inserts user settings into setting map fn update_settings_map(mut settings_map: Settings, key: &str, setting: &str) -> Settings { let key = MachineSettingKey::from(key); - let setting = u64::from_str_radix(setting, 10).unwrap_or(0); + let setting = setting.parse::().unwrap_or(0); settings_map.insert(key, setting); settings_map } \ No newline at end of file From 98fe63f487e926e819a71f7d15ac0c5609295ea0 Mon Sep 17 00:00:00 2001 From: Quentin Legot Date: Tue, 9 May 2023 23:16:16 +0200 Subject: [PATCH 08/10] print exit code when using debug machine, add matmult --- src/kernel/exception.rs | 3 +- src/kernel/thread_manager.rs | 4 +-- test/syscall_tests/Makefile | 2 +- test/syscall_tests/matmult.c | 60 ++++++++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 test/syscall_tests/matmult.c diff --git a/src/kernel/exception.rs b/src/kernel/exception.rs index 93f66ce..3252b85 100644 --- a/src/kernel/exception.rs +++ b/src/kernel/exception.rs @@ -138,7 +138,8 @@ fn syscall(machine: &mut Machine, system: &mut System) -> Result th.clone(), None => Err("Current thread is None")? }; - system.get_thread_manager().thread_finish(machine, th); + let code = machine.read_int_register(10); + system.get_thread_manager().thread_finish(machine, th, code); Ok(MachineOk::Ok) }, SC_EXEC => todo!(), diff --git a/src/kernel/thread_manager.rs b/src/kernel/thread_manager.rs index fa41a79..ec88c47 100644 --- a/src/kernel/thread_manager.rs +++ b/src/kernel/thread_manager.rs @@ -248,10 +248,10 @@ impl ThreadManager { } /// Finish the execution of the thread and prepare its deallocation - pub fn thread_finish(&mut self, machine: &mut Machine, thread: ThreadRef) { + pub fn thread_finish(&mut self, machine: &mut Machine, thread: ThreadRef, exit_code: i64) { let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff); assert!(self.g_alive.remove(Rc::clone(&thread))); - self.debug(format!("Finishing thread {}", thread.borrow().get_name())); + self.debug(format!("Finishing thread {} with code {}", thread.borrow().get_name(), exit_code)); // 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)); diff --git a/test/syscall_tests/Makefile b/test/syscall_tests/Makefile index 79041ed..4c8f4ca 100644 --- a/test/syscall_tests/Makefile +++ b/test/syscall_tests/Makefile @@ -1,4 +1,4 @@ -PROGRAMS = halt.guac prints.guac producteur_consommateur.guac join.guac +PROGRAMS = halt.guac prints.guac producteur_consommateur.guac join.guac matmult.guac TOPDIR = ../.. include $(TOPDIR)/Makefile.rules diff --git a/test/syscall_tests/matmult.c b/test/syscall_tests/matmult.c new file mode 100644 index 0000000..cd62424 --- /dev/null +++ b/test/syscall_tests/matmult.c @@ -0,0 +1,60 @@ +/* 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 ). + * ----------------------------------------------------- + + */ + +#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; +} From e3654de2983fdf4fda54e076fcf1d66f82cbe443 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Tue, 9 May 2023 18:08:44 +0200 Subject: [PATCH 09/10] Fixed nobody to run --- src/kernel/thread_manager.rs | 6 +++++- .../boolean_logic/comparisons.c | 18 ++++++++---------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/kernel/thread_manager.rs b/src/kernel/thread_manager.rs index ec88c47..65da837 100644 --- a/src/kernel/thread_manager.rs +++ b/src/kernel/thread_manager.rs @@ -241,7 +241,11 @@ impl ThreadManager { while next_thread.is_none() { eprintln!("Nobody to run => idle"); machine.interrupt.idle(); - next_thread = self.find_next_to_run(); + if let Some(t) = self.find_next_to_run() { + next_thread = Some(t); + } else { + panic!("Couldn't find next thread to run.\nShutting down..."); + } } self.switch_to(machine, Rc::clone(&next_thread.unwrap())); diff --git a/test/riscv_instructions/boolean_logic/comparisons.c b/test/riscv_instructions/boolean_logic/comparisons.c index ec42461..ad5debf 100644 --- a/test/riscv_instructions/boolean_logic/comparisons.c +++ b/test/riscv_instructions/boolean_logic/comparisons.c @@ -1,15 +1,13 @@ int main() { int x = 0; int y = 1; - while (x <= y) { - if (x > y) { - x += 1; - } else if (x == y) { - x += y; - } else if (x < y) { - y += 1; - } else { - return 0; - } + if (x > y) { + x += 1; + } + if (x == y) { + x += y; + } + if (x < y) { + y += 1; } } \ No newline at end of file From 3f51413038a520a89ea20e6323cf9a4a1c5dd5df Mon Sep 17 00:00:00 2001 From: Quentin Legot Date: Tue, 9 May 2023 23:24:43 +0200 Subject: [PATCH 10/10] Add sum to producteur_consommateur --- test/syscall_tests/producteur_consommateur.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/syscall_tests/producteur_consommateur.c b/test/syscall_tests/producteur_consommateur.c index 95d43b8..85f55b3 100644 --- a/test/syscall_tests/producteur_consommateur.c +++ b/test/syscall_tests/producteur_consommateur.c @@ -22,6 +22,7 @@ void producteur() { } void consommateur() { + int sum = 0; for(int i = 0; i < 10; i++) { P(splein); @@ -29,8 +30,10 @@ void consommateur() { n_printf("recevoir une information\n"); int info = tab[ivide]; V(svide); + sum += info; // n_printf("exploiter l'information : %d\n", info); } + Exit(sum); } int main() {