diff --git a/Makefile b/Makefile index 3e309af..250d706 100644 --- a/Makefile +++ b/Makefile @@ -70,6 +70,7 @@ $(MEM_DIR): @mkdir -p $@/programs @mkdir -p $@/programs_rust +.PRECIOUS: $(MEM_DIR)/programs_rust/%.elf $(MEM_DIR)/programs_rust/%.elf: bench/programs_rust/% force $(MEM_DIR)/crt.o |$(MEM_DIR) cd bench/programs_rust && cargo build --release --bin=$(basename $(notdir $@)) cp -f bench/programs_rust/target/riscv64i/release/$(basename $(notdir $@)) $@ @@ -100,6 +101,7 @@ PATH_SRC := src/main/scala/$(TOP_REP) TOP_TEST := $(addsuffix Spec, $(TOP)) CYCLES=500 +INSTRUCTIONS=1000 # Pour filtrer les tests dans une simulation ifdef PROG FILTRE_TEST:= -- -z "$(PROG)" @@ -120,11 +122,16 @@ testall: mill compile ##! Lance la simulation automatique pour tous les tests en $(PROG): $(MEM_DIR)/$(PROG).mem -simulation: mill $(PROG) ##! Lance gtkwave sur le test fourni dans PROG +simulation: mill $(PROG) ##! Lance gtkwave sur le test fourni dans PROG et produit le log du pc @$(call check_vars,PROG) @PROOT=$(PWD) PROG=$(PROG) CYCLES=$(CYCLES) ./mill TPchisel.test.testOnly $(TOP_REP).$(TOP_TEST) -- -DemitVcd=1 -z "gtkwave" + @cp -f ./build/chiselsim/ZzTopSpec/Simulation-pour-gtkwave/workdir-verilator/core_pc.log . @gtkwave -a common/config.gtkw ./build/chiselsim/ZzTopSpec/Simulation-pour-gtkwave/workdir-verilator/trace.vcd +spike-simulation: mill $(PROG) ##! Simule INSTRUCTIONS instructions de PROG avec spike et produit un log du PC dans spike_pc.log + spike --log spike.log --instructions=$$(($(INSTRUCTIONS) + 5)) -m0x10000:0x20000,0x80000000:0x00020000 -l $(MEM_DIR)/$(PROG).elf + cat spike.log | sed "/>>>>/d" | awk '{print $$3}' | tail -n $(INSTRUCTIONS) > spike_pc.log + ############################################################################### diff --git a/bench/crt.S b/bench/crt.S index 567517d..19d6221 100644 --- a/bench/crt.S +++ b/bench/crt.S @@ -4,13 +4,8 @@ _start: # réservation d'une (petite) zone de mémoire pour la pile - la sp, stack + STACK_SIZE + la sp, _stack_start # appel de main, sans espoir de retour ! jal main -1: j 1b - - .bss - .align 4 - .global stack -stack: - .skip STACK_SIZE +.data +.bss diff --git a/bench/link.ld b/bench/link.ld index 3bbc33b..bbedd8f 100644 --- a/bench/link.ld +++ b/bench/link.ld @@ -1,50 +1,19 @@ OUTPUT_ARCH( "riscv" ) ENTRY (_start) -MEMORY -{ - insnmem (rx) : ORIGIN = 0x0000, LENGTH = 8K - datamem (wai!x) : ORIGIN = 0x2000, LENGTH = 8K -} - -PHDRS -{ - text PT_LOAD; - data PT_LOAD; - bss PT_LOAD; -} - SECTIONS { - PROVIDE(_start = ORIGIN(insnmem)); - .text : { - PROVIDE(_text_start = .); - *(.text._start) *(.text .text.*) - PROVIDE(_text_end = .); - } >insnmem AT>insnmem :text + . = 0x10000; + .text : { *(.text) } + . = ALIGN(8); + .data : { *(.data) } + .bss : { *(.bss) } + . = ALIGN(8); + PROVIDE(_memory_start = . ); + PROVIDE(_memory_end = 0x20000); + PROVIDE(_stack_size = 1024); /* 1 KiB */ + PROVIDE(_stack_start = _memory_end); + PROVIDE(_stack_end = _stack_start - _stack_size); - . = ORIGIN(datamem); - .rodata ALIGN(4) : { - PROVIDE(_rodata_start = .); - *(.rodata .rodata.*) - PROVIDE(_rodata_end = .); - } >datamem AT>datamem :data - .data ALIGN(4) : { - PROVIDE(_data_start = .); - *(.sdata .sdata.*) *(.data .data.*) - PROVIDE(_data_end = .); - } >datamem AT>datamem :data - - .bss ALIGN(4) : { - PROVIDE(_bss_start = .); - *(.sbss .sbss.*) *(.bss .bss.*) - PROVIDE(_bss_end = .); - } >datamem AT>datamem :bss - - PROVIDE(_memory_start = ORIGIN(datamem)); - PROVIDE(_memory_end = ORIGIN(datamem) + LENGTH(datamem)); - PROVIDE(_stack_size = 1024); /* 1 KiB */ - PROVIDE(_stack_start = ORIGIN(datamem) + LENGTH(datamem)); - PROVIDE(_stack_end = _stack_start - _stack_size); } diff --git a/bench/programs_rust/.cargo/config.toml b/bench/programs_rust/.cargo/config.toml index 6f20977..faccd54 100644 --- a/bench/programs_rust/.cargo/config.toml +++ b/bench/programs_rust/.cargo/config.toml @@ -8,6 +8,7 @@ linker = "riscv64-unknown-elf-ld" rustflags = [ # "-C", "link-arg=-nostartfiles", "-C", "link-arg=-T../link.ld", + "-C", "link-arg=../mem/crt.o", ] [unstable] diff --git a/bench/programs_rust/fpga-lib/src/vga.rs b/bench/programs_rust/fpga-lib/src/vga.rs index 121c3cc..baa0617 100644 --- a/bench/programs_rust/fpga-lib/src/vga.rs +++ b/bench/programs_rust/fpga-lib/src/vga.rs @@ -46,7 +46,7 @@ impl VGA { let c = if (c as u8 > b'~') || ((c as u8) < b' ') { - b'?' - b' ' + b'/' - b' ' } else { @@ -79,21 +79,9 @@ impl VGA /// The text must have a length that can fit within a `u16` pub unsafe fn draw_string(x: u16, y: u16, str: &str, color: Color) { - //str.chars().enumerate().for_each(|(i, c)| unsafe { - //Self::draw_char(x + i as u16 * (FONT_WIDTH as u16), y, c, color) - //Self::draw_char(x + (i as u16) << 1, y, c, color) - //Self::draw_char(x, y, c, color) - //}); - - for i in 0..2 - { - Self::draw_char( - x + (2 - i) as u16 * (FONT_WIDTH as u16), - y, - str.as_bytes()[i] as char, - color, - ); - } + str.bytes().enumerate().for_each(|(i, c)| unsafe { + Self::draw_char(x + i as u16 * (FONT_WIDTH as u16), y, c as char, color) + }); } unsafe fn font_plate_index(x: u16, y: u16) -> bool diff --git a/bench/programs_rust/hello-rust/src/main.rs b/bench/programs_rust/hello-rust/src/main.rs index 139f3c1..043ab6a 100644 --- a/bench/programs_rust/hello-rust/src/main.rs +++ b/bench/programs_rust/hello-rust/src/main.rs @@ -6,15 +6,14 @@ use core::arch::asm; use fpga_lib::{ panic_handler, register::X31, - vga::{BLUE, GREEN, RED, VGA, WHITE}, + vga::{BLUE, FONT_WIDTH, GREEN, RED, VGA, WHITE}, }; panic_handler! {} #[unsafe(no_mangle)] -pub extern "C" fn _start() -> ! +pub extern "C" fn main() -> ! { - unsafe { asm!("la sp, _stack_start") } // X31::write_const::<0xdead1ffffffff>(); // let test = X31::read() + 10; //unsafe { @@ -27,10 +26,45 @@ pub extern "C" fn _start() -> ! // { // VGA::write_pixel_unsafe(i, i, WHITE); // } - //unsafe { VGA::draw_char(9, 3, 'S', RED) }; - unsafe { VGA::draw_string(3, 3, "{Skibidi toilet !!}", GREEN) }; + //let c = core::hint::black_box('S'); + let c = core::hint::black_box('S'); + //unsafe { VGA::draw_char(10, 10, c, RED) }; + //unsafe { VGA::draw_string(3, 3, "{Skibidi toilet !!}", GREEN) }; //} + // for i in 0..2 + // { + // unsafe { VGA::draw_char(0 + i as u16 * FONT_WIDTH as u16, 0, c, RED) }; + // } + + // unsafe { VGA::draw_char(0, 0, c, RED) }; + // unsafe { VGA::draw_char(1, 0, c, RED) }; + + unsafe { VGA::draw_char(1, 0, c, RED) }; + unsafe { VGA::draw_char(1, 0, c, GREEN) }; + // if (c as u8 > b'~') || ((c as u8) < b' ') + // { + // X31::write_const::<0x01>(); + // } + // else + // { + // X31::write_const::<0xFFFFFFFFFFFFFFFF>(); + // }; + // + // if (c as u8 > b'~') || ((c as u8) < b' ') + // { + // X31::write_const::<0x01>(); + // } + // else + // { + // X31::write_const::<0xFFFFFFFFFFFFFFFF>(); + // }; + + // for i in 0..100 + // { + // unsafe { VGA::write_pixel_unsafe(i, i, WHITE) }; + // } + // // let mut a = core::hint::black_box(true); // let mut x = core::hint::black_box(121); // let mut y = core::hint::black_box(221); diff --git a/src/main/scala/projet/BusInterconnect.scala b/src/main/scala/projet/BusInterconnect.scala index df353d6..eaa6849 100644 --- a/src/main/scala/projet/BusInterconnect.scala +++ b/src/main/scala/projet/BusInterconnect.scala @@ -41,8 +41,8 @@ class BusInterconnect extends Module { // BASE => ( X"0000_1000", X"3000_0000", X"3000_0008", X"0C00_0000", X"0200_0000", X"8000_0000"), // HIGH => ( X"0000_8FFF", X"3000_0004", X"3000_0008", X"1000_0000", X"0200_C000", X"8FFF_FFFF") - val DMEM_BASE = 0x00000000L.U // Une mémoire unifiée code + données - val DMEM_SIZE = 0x00010000L.U + val DMEM_BASE = 0x00010000L.U // Une mémoire unifiée code + données + val DMEM_SIZE = 0x00020000L.U val LDIP_BASE = 0x30000000L.U val LDIP_SIZE = 0x00000004L.U diff --git a/src/main/scala/projet/Rv64i.scala b/src/main/scala/projet/Rv64i.scala index b7f549b..8f48553 100644 --- a/src/main/scala/projet/Rv64i.scala +++ b/src/main/scala/projet/Rv64i.scala @@ -10,7 +10,7 @@ class Rv64i(sim: Boolean = true) extends Module { val valid_x31 = if (sim) Some(Output(Bool())) else None }) - val reg_pc = RegInit(0.U(64.W)); + val reg_pc = RegInit("x10000".U(64.W)); val reg_file = Module(new RegFile(sim)); reg_file.io.rd_data := 0.U; @@ -33,10 +33,17 @@ class Rv64i(sim: Boolean = true) extends Module { alu.io.word_mode := control_unit.io.alu_word_mode // PC delayed to execute stage for auipc op - val execute_pc = Delay.Delay(reg_pc, 1, 0.U); + val execute_pc = Delay.Delay(reg_pc, 1, "x10000".U(64.W)); // True if the instruction in the execute stage is a jump val is_jump = Delay.Delay(control_unit.io.is_jump, 1, false.B); + if (sim) { + val log = SimLog.file("core_pc.log"); + when(!is_jump) { + log.printf(cf"0x${execute_pc}%x\n") + } + } + // Pipelining registers for mem stage val reg_rd_index = RegInit(0.U); val reg_execute_out = RegInit(0.U);