smcc/test_rv_vm/ripes-vm.c

140 lines
3.9 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
struct MiniRV32IMAState;
void ecall_handler(struct MiniRV32IMAState *state);
#define ECALL_HANDLER(state) ecall_handler(state)
#define MINIRV32WARN( x... ) printf( x );
#define MINIRV32_DECORATE static
#define MINI_RV32_RAM_SIZE (32 * 1024 * 1024)
#define MINIRV32_IMPLEMENTATION
#define MINIRV32_RAM_IMAGE_OFFSET 0x0
#include "mini-rv32ima.h"
#define SYSCALL(num) (1025 + num)
void ecall_handler(struct MiniRV32IMAState *state) {
uint32_t a0 = REG(10);
uint32_t a1 = REG(11);
switch (state->regs[17]) // x17 | a7
{
case 1:
// PrintInt
printf("%d", a0);
break;
case 4:
// PrintString
printf("%s", a0);
break;
case 10:
fprintf(stderr, "\nexit: %d\n", a0);
exit(a0);
case 93:
fprintf(stderr, "\nmain return code: %d\n", a0);
exit(a0);
case SYSCALL(0):
// getchar();
REGSET(10, getchar());
case SYSCALL(1):
// putchar
putchar(a0);
case SYSCALL(4):
// input int
scanf("%d", &a0);
REGSET(10, a0);
break;
case SYSCALL(5):
// input string
scanf("%s", a0);
REGSET(10, a0);
break;
default:
MINIRV32WARN("Unhandled ECALL: %d\n", state->regs[17]);
exit(1);
break;
}
}
int main(int argc, char *argv[]) {
// gcc -DDEFAULT_FILE='\"flat.bin\"' .\ripes-vm.c -o rv32-vm.exe
struct MiniRV32IMAState state;
uint8_t *image = (uint8_t *)malloc(MINI_RV32_RAM_SIZE);
// 初始化状态
memset(&state, 0, sizeof(state));
state.pc = 0; // 程序计数器从0开始
state.mstatus = 0x80000000; // 设置机器模式
state.mtvec = 0x1000;
state.mie = 0x7; // 启用所有中断
// 初始化内存
memset(image, 0, MINI_RV32_RAM_SIZE);
#ifndef DEFAULT_FILE
#define DEFAULT_FILE "../ccompiler/backend/test_rv.bin"
#endif
const char* filename = DEFAULT_FILE;
// 加载 flatbin 文件
if (argc == 2) {
filename = argv[1];
}
FILE *file = fopen(filename, "rb");
if (!file) {
fprintf(stderr, "Usage: %s <flatbin_file>\n", argv[0]);
printf("Failed to open file %s\n", filename);
return 1;
}
fseek(file, 0, SEEK_END);
long flen = ftell(file);
fseek(file, 0, SEEK_SET);
if (flen > MINI_RV32_RAM_SIZE) {
fprintf(stderr, "Flatbin file is too large\n");
fclose(file);
return 1;
}
fread(image, flen, 1, file);
fclose(file);
// 运行模拟器
while (1) {
int32_t ret = MiniRV32IMAStep(&state, image, MINIRV32_RAM_IMAGE_OFFSET, 0, 1);
if (ret != 0) {
printf("Exception or interrupt occurred at PC: %d\n", state.pc);
return ret;
}
}
free(image);
return 0;
}
// static void DumpState( struct MiniRV32IMAState * core, uint8_t * ram_image )
// {
// uint32_t pc = core->pc;
// uint32_t pc_offset = pc - MINIRV32_RAM_IMAGE_OFFSET;
// uint32_t ir = 0;
// printf( "PC: %08x ", pc );
// if( pc_offset >= 0 && pc_offset < ram_amt - 3 )
// {
// ir = *((uint32_t*)(&((uint8_t*)ram_image)[pc_offset]));
// printf( "[0x%08x] ", ir );
// }
// else
// printf( "[xxxxxxxxxx] " );
// uint32_t * regs = core->regs;
// printf( "Z:%08x ra:%08x sp:%08x gp:%08x tp:%08x t0:%08x t1:%08x t2:%08x s0:%08x s1:%08x a0:%08x a1:%08x a2:%08x a3:%08x a4:%08x a5:%08x ",
// regs[0], regs[1], regs[2], regs[3], regs[4], regs[5], regs[6], regs[7],
// regs[8], regs[9], regs[10], regs[11], regs[12], regs[13], regs[14], regs[15] );
// printf( "a6:%08x a7:%08x s2:%08x s3:%08x s4:%08x s5:%08x s6:%08x s7:%08x s8:%08x s9:%08x s10:%08x s11:%08x t3:%08x t4:%08x t5:%08x t6:%08x\n",
// regs[16], regs[17], regs[18], regs[19], regs[20], regs[21], regs[22], regs[23],
// regs[24], regs[25], regs[26], regs[27], regs[28], regs[29], regs[30], regs[31] );
// }