rvemu

RISC-V RV32I execution engine
git clone git://mcdim.xyz/revemu.git
Log | Files | Refs

commit a7e5dc83d3e11fd14bca2d5641d415ee1faba162
parent c0766a7dce8dbe858706627a58ff370608787618
Author: Michail Konstantinos Dimopoulos <mk@mcdim.xyz>
Date:   Sat,  5 Sep 2026 06:51:55 +0300

Added memory-based testing

Diffstat:
Mrtests.c | 125+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
Mtest.h | 1+
2 files changed, 111 insertions(+), 15 deletions(-)

diff --git a/rtests.c b/rtests.c @@ -78,7 +78,7 @@ test_t tests[] = { } }, { - .name = "basic loads and stores", + .name = "branches, loads and stores", .program = { 0x00a00093, //li ra,10 0x00000113, //li sp,0 @@ -136,6 +136,58 @@ test_t tests[] = { .pc = 0x48 } }, + { + .name = "loads and stores", + .program = { + 0x10000593, //li a1,256 + 0xfff00513, //li a0,-1 + 0x00a58023, //sb a0,0(a1) + 0x0005c503, //lbu a0,0(a1) + 0x00150513, //addi a0,a0,1 + 0x00a59123, //sh a0,2(a1) + 0x00259503, //lh a0,2(a1) + 0xeff50513, //addi a0,a0,-257 + 0x00a58223, //sb a0,4(a1) + 0x00458503, //lb a0,4(a1) + 0x00a59323, //sh a0,6(a1) + 0x00659503, //lh a0,6(a1) + 0x0065d503, //lhu a0,6(a1) + 0x00150513, //addi a0,a0,1 + 0x00a5a423, //sw a0,8(a1) + 0x00000513, //li a0,0 + 0x0085a503, //lw a0,8(a1) + 0x00000593, //li a1,0 + 0x00100073 //ebreak + }, + .program_len = 19, + .exp = { + .x = { + [10] = 0x00010000, + [11] = 0x0, + }, + .x_check_mask = ((UINT32_C(1) << 10) | + (UINT32_C(1) << 11)), + .pc = 0x48, + .mem = { + { .address = 0x100, .expected = 0xff }, + { .address = 0x101, .expected = 0x00 }, + { .address = 0x102, .expected = 0x00 }, + { .address = 0x103, .expected = 0x01 }, + + { .address = 0x104, .expected = 0xff }, + { .address = 0x105, .expected = 0x00 }, + { .address = 0x106, .expected = 0xff }, + { .address = 0x107, .expected = 0xff }, + + { .address = 0x108, .expected = 0x00 }, + { .address = 0x109, .expected = 0x00 }, + { .address = 0x10a, .expected = 0x01 }, + { .address = 0x10b, .expected = 0x00 }, + }, + .mem_len = 12, + } + }, + }; static void @@ -180,6 +232,49 @@ print_trap(cpu_state_t *cpu) } } +static void +check_reg(cpu_state_t *cpu, size_t i, int pr) +{ + for (int j=0; j<32; j++) { + if ((UINT32_C(1) << j) == tests[i].exp.x_check_mask) { + if (cpu->x[j] != tests[i].exp.x[j]) { + tests[i].result = TEST_FAILURE; + if (pr) + printf( " bad register %d. Expected %x, got %x\n", + j, tests[i].exp.x[j], cpu->x[j]); + } + } + } +} + +static void +check_mem(uint8_t *mem, size_t i, int pr) +{ + for (int j=0; j<tests[i].exp.mem_len; j++) { + uint32_t address = tests[i].exp.mem[j].address; + uint32_t expected = tests[i].exp.mem[j].expected; + uint8_t real = mem[address]; + + if (real != expected) { + tests[i].result = TEST_FAILURE; + if (pr) + printf( " bad memory x%x. Expected x%x, got x%x\n", + tests[i].exp.mem[j].address, expected, real); + } + } +} + +static void +check_pc(uint32_t pc, size_t i, int pr) +{ + if (pc != tests[i].exp.pc) { + tests[i].result = TEST_FAILURE; + if (pr) + printf( " bad pc, expected x%x, got x%x\n", + tests[i].exp.pc, pc); + } +} + int main() { @@ -202,26 +297,26 @@ main() } } - for (int j=0; j<32; j++) { - if ((UINT32_C(1) << j) == tests[i].exp.x_check_mask) { - if (cpu.x[j] != tests[i].exp.x[j]) { - tests[i].result = TEST_FAILURE; - printf( "bad register %d. Expected %x, got %x\n", - j, tests[i].exp.x[j], cpu.x[j]); - } - } + /* check registers */ + check_reg(&cpu, i, 0); + + /* check mem */ + check_mem(mem, i, 0); + + /* check pc */ + check_pc(cpu.pc, i, 0); - if (cpu.pc != tests[i].exp.pc) { - tests[i].result = TEST_FAILURE; - puts("bad pc\n"); - } - } if (tests[i].result != TEST_FAILURE) { printf("ok - %s (%zu)\n", tests[i].name, i); n_p++; } else { - printf("not ok - %s (%zu)\n ", tests[i].name, i); + printf("not ok - %s (%zu)\n ", tests[i].name, i); print_trap(&cpu); + + check_reg(&cpu, i, 1); + check_mem(mem, i, 1); + check_pc(cpu.pc, i, 1); + n_f++; } diff --git a/test.h b/test.h @@ -17,6 +17,7 @@ typedef struct { uint32_t pc; exp_word_t mem[50]; + int mem_len; } exp_t; typedef struct {