Add system for memory mapping a block of memory from the host.

This commit is contained in:
Toby Jaffey 2025-12-11 02:36:46 +00:00
parent 8802b4c268
commit b55c2bc88a
9 changed files with 253 additions and 1 deletions

33
test/extram/Makefile Normal file
View file

@ -0,0 +1,33 @@
C_COMPILER=gcc
UNITY_ROOT=../unity
CFLAGS=-std=c99
CFLAGS += -Wall
CFLAGS += -Werror
CFLAGS += -DUVM32_MEMORY_SIZE=16384
SUITE_NAME=tests
TARGET_BASE1=test1
TARGET1 = $(TARGET_BASE1)
SRC_FILES1=$(UNITY_ROOT)/src/unity.c test/${SUITE_NAME}.c test/test_runners/${SUITE_NAME}_Runner.c ../../uvm32/uvm32.c
INC_DIRS=-I$(UNITY_ROOT)/src -I../../uvm32/ -I../../common -Irom
.PHONY: rom
default: $(SRC_FILES1) rom
@$(C_COMPILER) $(CFLAGS) $(INC_DIRS) $(SYMBOLS) $(SRC_FILES1) rom/rom-header.c -o $(TARGET1)
@ ./$(TARGET1)
rom:
@(cd rom && make)
test/test_runners/${SUITE_NAME}_Runner.c: test/${SUITE_NAME}.c
@mkdir -p test/test_runners
@ruby $(UNITY_ROOT)/auto/generate_test_runner.rb test/${SUITE_NAME}.c test/test_runners/${SUITE_NAME}_Runner.c
clean:
rm -rf $(TARGET1) test/test_runners
(cd rom && make clean)

13
test/extram/rom/Makefile Normal file
View file

@ -0,0 +1,13 @@
TOPDIR=../../../
PROJECT:=$(shell basename ${PWD})
SRCS=${PROJECT}.c ${TOPDIR}/apps/crt0.S
all: all_common
@# Convert ROM to C file and header
@xxd -i ${PROJECT}.bin > ${PROJECT}-header.c
@echo "extern unsigned char ${PROJECT}_bin[]; extern int ${PROJECT}_bin_len;" > ${PROJECT}-header.h
test: test_common
clean: clean_common
rm -f ${PROJECT}-header.h ${PROJECT}-header.c
include ${TOPDIR}/apps/makefile.common

31
test/extram/rom/rom.c Normal file
View file

@ -0,0 +1,31 @@
#include "uvm32_target.h"
#include "../shared.h"
void main(void) {
switch(syscall(SYSCALL_PICKTEST, 0, 0)) {
case TEST1: {
uint32_t *p = (uint32_t *)UVM32_EXTRAM_BASE;
// read memory and print via syscall
printdec(*p);
// modify memory
*p = *p * 2;
} break;
case TEST2: {
uint32_t *p = (uint32_t *)UVM32_EXTRAM_BASE;
printdec(p[32]); // past the end
} break;
case TEST3: {
uint32_t *p = (uint32_t *)UVM32_EXTRAM_BASE;
p[32] = 1234; // past the end
} break;
case TEST4: {
uint32_t *p = (uint32_t *)UVM32_EXTRAM_BASE;
p[0] = 1234; // good write
yield(0);
} break;
}
}

99
test/extram/test/tests.c Normal file
View file

@ -0,0 +1,99 @@
#include <string.h>
#include "unity.h"
#include "uvm32.h"
#include "../common/uvm32_common_custom.h"
#include "rom-header.h"
#include "../shared.h"
static uvm32_state_t vmst;
static uvm32_evt_t evt;
uint32_t extram[32];
void setUp(void) {
// runs before each test
uvm32_init(&vmst);
uvm32_load(&vmst, rom_bin, rom_bin_len);
memset(extram, 0x00, sizeof(extram));
uvm32_extram(&vmst, extram, sizeof(extram));
}
void tearDown(void) {
}
void test_extram_access(void) {
extram[0] = 1234;
// run the vm
uvm32_run(&vmst, &evt, 100);
TEST_ASSERT_EQUAL(false, uvm32_extramDirty(&vmst));
// check for picktest syscall
TEST_ASSERT_EQUAL(evt.typ, UVM32_EVT_SYSCALL);
TEST_ASSERT_EQUAL(evt.data.syscall.code, SYSCALL_PICKTEST);
uvm32_setval(&vmst, &evt, RET, TEST1);
uvm32_run(&vmst, &evt, 100);
// check for printdec of val
TEST_ASSERT_EQUAL(evt.typ, UVM32_EVT_SYSCALL);
TEST_ASSERT_EQUAL(evt.data.syscall.code, UVM32_SYSCALL_PRINTDEC);
TEST_ASSERT_EQUAL(1234, uvm32_getval(&vmst, &evt, ARG0));
// run vm to completion
uvm32_run(&vmst, &evt, 100);
TEST_ASSERT_EQUAL(evt.typ, UVM32_EVT_END);
TEST_ASSERT_EQUAL(true, uvm32_extramDirty(&vmst));
TEST_ASSERT_EQUAL(1234*2, extram[0]);
}
void test_extram_out_of_bounds_rd(void) {
// run the vm
uvm32_run(&vmst, &evt, 100);
TEST_ASSERT_EQUAL(false, uvm32_extramDirty(&vmst));
// check for picktest syscall
TEST_ASSERT_EQUAL(evt.typ, UVM32_EVT_SYSCALL);
TEST_ASSERT_EQUAL(evt.data.syscall.code, SYSCALL_PICKTEST);
uvm32_setval(&vmst, &evt, RET, TEST2);
uvm32_run(&vmst, &evt, 100);
TEST_ASSERT_EQUAL(evt.typ, UVM32_EVT_ERR);
TEST_ASSERT_EQUAL(evt.data.err.errcode, UVM32_ERR_MEM_RD);
TEST_ASSERT_EQUAL(false, uvm32_extramDirty(&vmst));
}
void test_extram_out_of_bounds_wr(void) {
// run the vm
uvm32_run(&vmst, &evt, 100);
TEST_ASSERT_EQUAL(false, uvm32_extramDirty(&vmst));
// check for picktest syscall
TEST_ASSERT_EQUAL(evt.typ, UVM32_EVT_SYSCALL);
TEST_ASSERT_EQUAL(evt.data.syscall.code, SYSCALL_PICKTEST);
uvm32_setval(&vmst, &evt, RET, TEST3);
uvm32_run(&vmst, &evt, 100);
TEST_ASSERT_EQUAL(evt.typ, UVM32_EVT_ERR);
TEST_ASSERT_EQUAL(evt.data.err.errcode, UVM32_ERR_MEM_WR);
TEST_ASSERT_EQUAL(false, uvm32_extramDirty(&vmst));
}
void test_extram_out_of_bounds_dirty_flag(void) {
// run the vm
uvm32_run(&vmst, &evt, 100);
TEST_ASSERT_EQUAL(false, uvm32_extramDirty(&vmst));
// check for picktest syscall
TEST_ASSERT_EQUAL(evt.typ, UVM32_EVT_SYSCALL);
TEST_ASSERT_EQUAL(evt.data.syscall.code, SYSCALL_PICKTEST);
uvm32_setval(&vmst, &evt, RET, TEST4);
uvm32_run(&vmst, &evt, 100);
TEST_ASSERT_EQUAL(true, uvm32_extramDirty(&vmst));
uvm32_run(&vmst, &evt, 100);
TEST_ASSERT_EQUAL(false, uvm32_extramDirty(&vmst));
}