mirror of
https://github.com/ringtailsoftware/uvm32.git
synced 2026-06-05 22:43:39 +00:00
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.
This commit is contained in:
parent
be5dbbfa44
commit
5dc9acdf3d
8 changed files with 75 additions and 3 deletions
Binary file not shown.
|
|
@ -6,7 +6,8 @@ TESTS = \
|
||||||
meter \
|
meter \
|
||||||
extram \
|
extram \
|
||||||
badcode \
|
badcode \
|
||||||
invalid_opcodes
|
invalid_opcodes \
|
||||||
|
minirv32_internal
|
||||||
|
|
||||||
RUNCMD = $(foreach TEST,${TESTS},make -C ${TEST} &&)
|
RUNCMD = $(foreach TEST,${TESTS},make -C ${TEST} &&)
|
||||||
CLEANCMD = $(foreach TEST,${TESTS},make -C ${TEST} clean &&)
|
CLEANCMD = $(foreach TEST,${TESTS},make -C ${TEST} clean &&)
|
||||||
|
|
@ -14,7 +15,7 @@ CLEANCMD = $(foreach TEST,${TESTS},make -C ${TEST} clean &&)
|
||||||
ifeq (,$(shell which gcovr))
|
ifeq (,$(shell which gcovr))
|
||||||
GCOVRCMD=echo Install gcovr for code coverage reports
|
GCOVRCMD=echo Install gcovr for code coverage reports
|
||||||
else
|
else
|
||||||
GCOVRCMD=gcovr -r ../ --filter ".*uvm32.c"
|
GCOVRCMD=gcovr -r ../ --filter ".*uvm32.c" --filter ".*mini.*"
|
||||||
PERC=$(shell gcovr -r ../ --filter ".*uvm32.c" | grep uvm | awk '{print $$4}')
|
PERC=$(shell gcovr -r ../ --filter ".*uvm32.c" | grep uvm | awk '{print $$4}')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
||||||
2
test/minirv32_internal/Makefile
Normal file
2
test/minirv32_internal/Makefile
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
TOPDIR=../..
|
||||||
|
include ${TOPDIR}/test/common/makefile.common
|
||||||
2
test/minirv32_internal/rom/Makefile
Normal file
2
test/minirv32_internal/rom/Makefile
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
TOPDIR=../../..
|
||||||
|
include ${TOPDIR}/test/common/makefile-rom.common
|
||||||
6
test/minirv32_internal/rom/rom.c
Normal file
6
test/minirv32_internal/rom/rom.c
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
#include "uvm32_target.h"
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
println("Hello world");
|
||||||
|
}
|
||||||
|
|
||||||
55
test/minirv32_internal/test/tests.c
Normal file
55
test/minirv32_internal/test/tests.c
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
#include <string.h>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -501,6 +501,7 @@ MINIRV32_STEPPROTO
|
||||||
// Handle traps and interrupts.
|
// Handle traps and interrupts.
|
||||||
if( trap )
|
if( trap )
|
||||||
{
|
{
|
||||||
|
#ifndef MINIRV32_RETURN_TRAP
|
||||||
if( trap & 0x80000000 ) // If prefixed with 1 in MSB, it's an interrupt, not a trap.
|
if( trap & 0x80000000 ) // If prefixed with 1 in MSB, it's an interrupt, not a trap.
|
||||||
{
|
{
|
||||||
SETCSR( mcause, trap );
|
SETCSR( mcause, trap );
|
||||||
|
|
@ -520,9 +521,13 @@ MINIRV32_STEPPROTO
|
||||||
|
|
||||||
// If trapping, always enter machine mode.
|
// If trapping, always enter machine mode.
|
||||||
CSR( extraflags ) |= 3;
|
CSR( extraflags ) |= 3;
|
||||||
|
|
||||||
trap = 0;
|
trap = 0;
|
||||||
pc += 4;
|
pc += 4;
|
||||||
|
#else
|
||||||
|
if (trap > 0) {
|
||||||
|
return trap;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if( CSR( cyclel ) > cycle ) CSR( cycleh )++;
|
if( CSR( cyclel ) > cycle ) CSR( cycleh )++;
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ SOFTWARE.
|
||||||
|
|
||||||
// Setup and hooks for mini-rv32ima emulator core
|
// Setup and hooks for mini-rv32ima emulator core
|
||||||
#define MINIRV32_DECORATE static
|
#define MINIRV32_DECORATE static
|
||||||
|
#define MINIRV32_RETURN_TRAP
|
||||||
#define MINI_RV32_RAM_SIZE UVM32_MEMORY_SIZE
|
#define MINI_RV32_RAM_SIZE UVM32_MEMORY_SIZE
|
||||||
#define MINIRV32_POSTEXEC(pc, ir, retval) {if (retval > 0) return retval;}
|
#define MINIRV32_POSTEXEC(pc, ir, retval) {if (retval > 0) return retval;}
|
||||||
uint32_t _uvm32_extramLoad(void *userdata, uint32_t addr, uint32_t accessTyp);
|
uint32_t _uvm32_extramLoad(void *userdata, uint32_t addr, uint32_t accessTyp);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue