140 lines
3.9 KiB
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] );
|
|
// }
|