From 5dc9acdf3db383c9385bee695d75134d2a252c68 Mon Sep 17 00:00:00 2001 From: Toby Jaffey Date: Sun, 14 Dec 2025 11:00:45 +0000 Subject: [PATCH] When a trap occurs in mini-rv32ima, always pass to the host rather than allowing running code to handle it. This would be important for a real OS, but the aim of uvm32 is embeddable logic - not full emulation. As all traps are caught by host, begin testing mini-rv32ima internals by checking PC oob and PC alignment. --- precompiled/self.bin | Bin 5260 -> 5180 bytes test/Makefile | 5 ++- test/minirv32_internal/Makefile | 2 + test/minirv32_internal/rom/Makefile | 2 + test/minirv32_internal/rom/rom.c | 6 +++ test/minirv32_internal/test/tests.c | 55 ++++++++++++++++++++++++++++ uvm32/mini-rv32ima.h | 7 +++- uvm32/uvm32.h | 1 + 8 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 test/minirv32_internal/Makefile create mode 100644 test/minirv32_internal/rom/Makefile create mode 100644 test/minirv32_internal/rom/rom.c create mode 100644 test/minirv32_internal/test/tests.c diff --git a/precompiled/self.bin b/precompiled/self.bin index 344ae738c8769cb83ec9ec5c0de6493cda77a406..d80139bc226e8fb4e5987bf43c4872319ef26a9c 100755 GIT binary patch delta 636 zcmYLHUr19?82`@h&OP_;Pu_LP847C4{tU~}Dlv+t(+nEfLp}t(#0e6Tq$i`7R%_mw zD>gsDFu|9=Fdu>&EvScHLQu&CiBLkpDt(AtkW)xn$Mw*8_`cuw{W!n#{mwbbeXsVW z!gb-yc8Fq}ZsqhAS%GL}#tTv2Z+c4EP7LgC_oTa?5X0I=nrv)>wV>G^#&gPf=BF*3 zwuP-{3b)Y!-gPwKEWPOLZ3ppyY1m6O45<|%S*Xh7fR@o9n%NCtu__||EZDKo2x3IF z^TdG5V(SnaXAqlo>RbsZINuAru*NW11(;GTvJ+d`F!AFeyXLh&SCO6t@on`&Y5L(k zARW}>CGABZHty81?<9!z4Jmk9N7DAP`Et|ws#(|sFgPa*4hL&t%Q2!uC znJrT%&y2@iTn!N`{t`H~!%Ds*-IMQl$5{ZZJBONcqe~meYQR_X3wrW%b6jFEvh-GZ zyN|R+_R79;3Y%P!(|l3xm3gxso9Aj_2Bl7Jd1^7kfjkx&ptoWP)H~-tO+*6FgPr z4VNH4+~e&ke+U0S{<5$g`PFXSRgh^2hoRu2<^Pcg#uzn$Rg1`f;uKG7RVBjcI9zIgshH|56HH# zi2MdA$KhQFL2o%q{)(4E#)XnWp$Oc(q`2?w)gM;~Yq-L@Nf`Wmop`Hxm8u(0Z z+0m2?d=sKymoF9w4Ob&ZYCl{R-#DPtogXgIl~ra>OQ744_ADoAPajFz_=3n{h>l3D zs-9h=rKA-ar2(!jeiIT>4L)Ef=KI*$Bb)`@hUg$cNs*5_8|F>E^k|g!2~E!CJYI|> zdxaTl<53~6lQcohGKpPqTXt3*GW2+XLyMmvCM?S#@2H${uVed9YRDh=%9LTs^TbCS3t>#~#RsLpG zXJ%A}>EqM~U;1)4@RiKhzo_!*H5U7;@`&AM|E$}Jm?~r +#include "unity.h" +#include "uvm32.h" +#include "../common/uvm32_common_custom.h" + +#include "rom-header.h" + +static uvm32_state_t vmst; +static uvm32_evt_t evt; + +void setUp(void) { + // runs before each test + uvm32_init(&vmst); + uvm32_load(&vmst, rom_bin, rom_bin_len); +} + +void tearDown(void) { +} + +void test_pc_too_big(void) { + // No code should be doing this, but... + TEST_ASSERT_EQUAL(0x80000000, uvm32_getProgramCounter(&vmst)); + vmst._core.pc = 0x80000000 + 1024 * 16 * 4; // off end + uvm32_run(&vmst, &evt, 1); + TEST_ASSERT_EQUAL(evt.typ, UVM32_EVT_ERR); + TEST_ASSERT_EQUAL(evt.data.err.errcode, UVM32_ERR_INTERNAL_CORE); +} + +void test_pc_unaligned_1(void) { + // No code should be doing this, but... + TEST_ASSERT_EQUAL(0x80000000, uvm32_getProgramCounter(&vmst)); + vmst._core.pc = 0x80000000 + 1; + uvm32_run(&vmst, &evt, 1); + TEST_ASSERT_EQUAL(evt.typ, UVM32_EVT_ERR); + TEST_ASSERT_EQUAL(evt.data.err.errcode, UVM32_ERR_INTERNAL_CORE); +} + +void test_pc_unaligned_2(void) { + // No code should be doing this, but... + TEST_ASSERT_EQUAL(0x80000000, uvm32_getProgramCounter(&vmst)); + vmst._core.pc = 0x80000000 + 2; + uvm32_run(&vmst, &evt, 1); + TEST_ASSERT_EQUAL(evt.typ, UVM32_EVT_ERR); + TEST_ASSERT_EQUAL(evt.data.err.errcode, UVM32_ERR_INTERNAL_CORE); +} + +void test_pc_unaligned_3(void) { + // No code should be doing this, but... + TEST_ASSERT_EQUAL(0x80000000, uvm32_getProgramCounter(&vmst)); + vmst._core.pc = 0x80000000 + 3; + uvm32_run(&vmst, &evt, 1); + TEST_ASSERT_EQUAL(evt.typ, UVM32_EVT_ERR); + TEST_ASSERT_EQUAL(evt.data.err.errcode, UVM32_ERR_INTERNAL_CORE); +} + diff --git a/uvm32/mini-rv32ima.h b/uvm32/mini-rv32ima.h index 531648e..e33c52c 100644 --- a/uvm32/mini-rv32ima.h +++ b/uvm32/mini-rv32ima.h @@ -501,6 +501,7 @@ MINIRV32_STEPPROTO // Handle traps and interrupts. if( trap ) { +#ifndef MINIRV32_RETURN_TRAP if( trap & 0x80000000 ) // If prefixed with 1 in MSB, it's an interrupt, not a trap. { SETCSR( mcause, trap ); @@ -520,9 +521,13 @@ MINIRV32_STEPPROTO // If trapping, always enter machine mode. CSR( extraflags ) |= 3; - trap = 0; pc += 4; +#else + if (trap > 0) { + return trap; + } +#endif } if( CSR( cyclel ) > cycle ) CSR( cycleh )++; diff --git a/uvm32/uvm32.h b/uvm32/uvm32.h index ceb92d2..d397ba5 100644 --- a/uvm32/uvm32.h +++ b/uvm32/uvm32.h @@ -40,6 +40,7 @@ SOFTWARE. // Setup and hooks for mini-rv32ima emulator core #define MINIRV32_DECORATE static +#define MINIRV32_RETURN_TRAP #define MINI_RV32_RAM_SIZE UVM32_MEMORY_SIZE #define MINIRV32_POSTEXEC(pc, ir, retval) {if (retval > 0) return retval;} uint32_t _uvm32_extramLoad(void *userdata, uint32_t addr, uint32_t accessTyp);