From c51aab59a75201c56ac0e19ff50b0975b5d03b0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20W=C4=99grzyn?= Date: Sun, 11 Aug 2024 14:17:49 +0200 Subject: [PATCH] Support loading initialized data memory from asm tests (#725) --- test/asm/exception_mem.asm | 2 ++ test/asm/fibonacci_mem.asm | 3 +++ test/asm/init_regs.s | 8 ++++++ test/asm/interrupt.asm | 10 ++++--- test/asm/link.ld | 12 ++++++--- test/asm/wfi_int.asm | 6 ++++- test/test_core.py | 55 ++++++++++++++++++++++---------------- 7 files changed, 66 insertions(+), 30 deletions(-) diff --git a/test/asm/exception_mem.asm b/test/asm/exception_mem.asm index c3556e795..4964f135d 100644 --- a/test/asm/exception_mem.asm +++ b/test/asm/exception_mem.asm @@ -9,3 +9,5 @@ sw x2, 4(x0) sw x1, 4(x0) /* TODO: actually check the side fx */ li x2, 9 +.section .bss +.skip 0x8 diff --git a/test/asm/fibonacci_mem.asm b/test/asm/fibonacci_mem.asm index 9986aca76..0db8b2130 100644 --- a/test/asm/fibonacci_mem.asm +++ b/test/asm/fibonacci_mem.asm @@ -24,3 +24,6 @@ loop: bne x3, x4, loop infloop: j infloop + +.section .bss +.skip 0xC diff --git a/test/asm/init_regs.s b/test/asm/init_regs.s index 5c27a365b..853a40a15 100644 --- a/test/asm/init_regs.s +++ b/test/asm/init_regs.s @@ -1,3 +1,4 @@ +.macro INIT_REGS_LOAD # load the initial states of registers # the value of a register `n` is assumed to be stored under address `0x100 + n * 4`. lw x1, 0x104(x0) @@ -31,3 +32,10 @@ lw x29,0x174(x0) lw x30,0x178(x0) lw x31,0x17c(x0) +.endm + +.macro INIT_REGS_ALLOCATION +.section .init_regs, "a", @nobits +.skip 0x80 +.previous +.endm diff --git a/test/asm/interrupt.asm b/test/asm/interrupt.asm index 02388127f..a3b59b30e 100644 --- a/test/asm/interrupt.asm +++ b/test/asm/interrupt.asm @@ -1,7 +1,9 @@ - _start: - .include "init_regs.s" +.include "init_regs.s" -# fibonacci spiced with interrupt handler (also with fibonacci) +_start: + INIT_REGS_LOAD + + # fibonacci spiced with interrupt handler (also with fibonacci) li x1, 0x200 csrw mtvec, x1 li x27, 0 # handler count @@ -98,3 +100,5 @@ fail: .org 0x200 j int_handler li x31, 0xae # should never happen + +INIT_REGS_ALLOCATION diff --git a/test/asm/link.ld b/test/asm/link.ld index 9ceab42eb..c77c5fef8 100644 --- a/test/asm/link.ld +++ b/test/asm/link.ld @@ -5,7 +5,13 @@ start = 0; SECTIONS { .text : { *(.text) } - . = 0x100000000; /* start from 2**32 - trick to emulate Harvard architecture (.bss addresses will start from 0) */ - .bss : { *(.bss) } - _end = .; + . = 0x100000000; /* start from 2**32 - trick to emulate Harvard architecture (memory addresses will start from 0) */ + .data : { + *(.data) + *(.bss) + + . = _end_init_regs > . ? 0x1000 : .; /* skip .init_regs origin allocation if not used */ + *(.init_regs) + _end_init_regs = .; + } } diff --git a/test/asm/wfi_int.asm b/test/asm/wfi_int.asm index 3f50000c4..39ceda94a 100644 --- a/test/asm/wfi_int.asm +++ b/test/asm/wfi_int.asm @@ -1,5 +1,7 @@ +.include "init_regs.s" + _start: - .include "init_regs.s" + INIT_REGS_LOAD li x1, 0x100 # set handler vector csrw mtvec, x1 @@ -26,3 +28,5 @@ skip: .org 0x100 j handler + +INIT_REGS_ALLOCATION diff --git a/test/test_core.py b/test/test_core.py index d9cf4655d..e988b1437 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -12,7 +12,6 @@ from coreblocks.params.configurations import CoreConfiguration, basic_core_config, full_core_config from coreblocks.peripherals.wishbone import WishboneMemorySlave -from typing import Optional import random import subprocess import tempfile @@ -20,13 +19,10 @@ class CoreTestElaboratable(Elaboratable): - def __init__(self, gen_params: GenParams, instr_mem: list[int] = [0], data_mem: Optional[list[int]] = None): + def __init__(self, gen_params: GenParams, instr_mem: list[int] = [0], data_mem: list[int] = []): self.gen_params = gen_params self.instr_mem = instr_mem - if data_mem is None: - self.data_mem = [0] * (2**10) - else: - self.data_mem = data_mem + self.data_mem = data_mem def elaborate(self, platform): m = Module() @@ -71,12 +67,10 @@ def get_arch_reg_val(self, reg_id): class TestCoreAsmSourceBase(TestCoreBase): base_dir: str = "test/asm/" - def prepare_source(self, filename): - bin_src = [] + def prepare_source(self, filename, *, c_extension=False): with ( tempfile.NamedTemporaryFile() as asm_tmp, tempfile.NamedTemporaryFile() as ld_tmp, - tempfile.NamedTemporaryFile() as bin_tmp, ): subprocess.check_call( [ @@ -84,7 +78,7 @@ def prepare_source(self, filename): "-mabi=ilp32", # Specified manually, because toolchains from most distributions don't support new extensioins # and this test should be accessible locally. - "-march=rv32im_zicsr", + f"-march=rv32im{'c' if c_extension else ''}_zicsr", "-I", self.base_dir, "-o", @@ -104,16 +98,31 @@ def prepare_source(self, filename): ld_tmp.name, ] ) - subprocess.check_call( - ["riscv64-unknown-elf-objcopy", "-O", "binary", "-j", ".text", ld_tmp.name, bin_tmp.name] - ) - code = bin_tmp.read() - for word_idx in range(0, len(code), 4): - word = code[word_idx : word_idx + 4] - bin_instr = int.from_bytes(word, "little") - bin_src.append(bin_instr) - return bin_src + def load_section(section: str): + with tempfile.NamedTemporaryFile() as bin_tmp: + bin = [] + + subprocess.check_call( + [ + "riscv64-unknown-elf-objcopy", + "-O", + "binary", + "-j", + section, + ld_tmp.name, + bin_tmp.name, + ] + ) + + data = bin_tmp.read() + for word_idx in range(0, len(data), 4): + word = data[word_idx : word_idx + 4] + bin.append(int.from_bytes(word, "little")) + + return bin + + return {"text": load_section(".text"), "data": load_section(".data")} @parameterized_class( @@ -146,7 +155,8 @@ def test_asm_source(self): self.gen_params = GenParams(self.configuration) bin_src = self.prepare_source(self.source_file) - self.m = CoreTestElaboratable(self.gen_params, instr_mem=bin_src) + self.m = CoreTestElaboratable(self.gen_params, instr_mem=bin_src["text"], data_mem=bin_src["data"]) + with self.run_simulation(self.m) as sim: sim.add_sync_process(self.run_and_check) @@ -269,10 +279,9 @@ def do_interrupt(): def test_interrupted_prog(self): bin_src = self.prepare_source(self.source_file) - data_mem = [0] * (2**10) for reg_id, val in self.start_regvals.items(): - data_mem[self.reg_init_mem_offset // 4 + reg_id] = val - self.m = CoreTestElaboratable(self.gen_params, instr_mem=bin_src, data_mem=data_mem) + bin_src["data"][self.reg_init_mem_offset // 4 + reg_id] = val + self.m = CoreTestElaboratable(self.gen_params, instr_mem=bin_src["text"], data_mem=bin_src["data"]) with self.run_simulation(self.m) as sim: sim.add_sync_process(self.run_with_interrupt_process) sim.add_sync_process(self.clear_level_interrupt_procsess)