Adds a way to simulate the programs with spike, to compare PCs and debug
This commit is contained in:
9
Makefile
9
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
|
||||
|
||||
|
||||
###############################################################################
|
||||
|
||||
|
||||
11
bench/crt.S
11
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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user