diff --git a/src/main/c/emulator/src/config.h b/src/main/c/emulator/src/config.h index 3c1f1aa..ac6fd01 100644 --- a/src/main/c/emulator/src/config.h +++ b/src/main/c/emulator/src/config.h @@ -1,6 +1,8 @@ #ifndef CONFIG_H #define CONFIG_H +//#define QEMU +#define SIM #define OS_CALL 0xC0000000 #define DTB 0x81000000 diff --git a/src/main/c/emulator/src/hal.c b/src/main/c/emulator/src/hal.c index cdb052d..b2db19e 100644 --- a/src/main/c/emulator/src/hal.c +++ b/src/main/c/emulator/src/hal.c @@ -1,5 +1,7 @@ #include "hal.h" +#include "config.h" +#ifdef SIM void stopSim(){ *((volatile uint32_t*) 0xFFFFFFFC) = 0; } @@ -16,10 +18,112 @@ uint32_t rdtimeh(){ return *((volatile uint32_t*) 0xFFFFFFE4); } - void setMachineTimerCmp(uint32_t low, uint32_t high){ volatile uint32_t* base = (volatile uint32_t*) 0xFFFFFFE8; base[1] = 0xffffffff; base[0] = low; base[1] = high; } + + +void halInit(){ + +} +#endif + +#ifdef QEMU +#define VIRT_CLINT 0x2000000 +#define SIFIVE_TIMECMP_BASE VIRT_CLINT + 0x4000 +#define SIFIVE_TIME_BASE VIRT_CLINT + 0xBFF8 +#define NS16550A_UART0_CTRL_ADDR 0x10000000 +#define UART0_CLOCK_FREQ 32000000 +#define UART0_BAUD_RATE 115200 +enum { + UART_RBR = 0x00, /* Receive Buffer Register */ + UART_THR = 0x00, /* Transmit Hold Register */ + UART_IER = 0x01, /* Interrupt Enable Register */ + UART_DLL = 0x00, /* Divisor LSB (LCR_DLAB) */ + UART_DLM = 0x01, /* Divisor MSB (LCR_DLAB) */ + UART_FCR = 0x02, /* FIFO Control Register */ + UART_LCR = 0x03, /* Line Control Register */ + UART_MCR = 0x04, /* Modem Control Register */ + UART_LSR = 0x05, /* Line Status Register */ + UART_MSR = 0x06, /* Modem Status Register */ + UART_SCR = 0x07, /* Scratch Register */ + + UART_LCR_DLAB = 0x80, /* Divisor Latch Bit */ + UART_LCR_8BIT = 0x03, /* 8-bit */ + UART_LCR_PODD = 0x08, /* Parity Odd */ + + UART_LSR_DA = 0x01, /* Data Available */ + UART_LSR_OE = 0x02, /* Overrun Error */ + UART_LSR_PE = 0x04, /* Parity Error */ + UART_LSR_FE = 0x08, /* Framing Error */ + UART_LSR_BI = 0x10, /* Break indicator */ + UART_LSR_RE = 0x20, /* THR is empty */ + UART_LSR_RI = 0x40, /* THR is empty and line is idle */ + UART_LSR_EF = 0x80, /* Erroneous data in FIFO */ +}; + +static volatile uint8_t *uart; + +static void ns16550a_init() +{ + uart = (uint8_t *)(void *)(NS16550A_UART0_CTRL_ADDR); + uint32_t uart_freq = (UART0_CLOCK_FREQ); + uint32_t baud_rate = (UART0_BAUD_RATE); + uint32_t divisor = uart_freq / (16 * baud_rate); + uart[UART_LCR] = UART_LCR_DLAB; + uart[UART_DLL] = divisor & 0xff; + uart[UART_DLM] = (divisor >> 8) & 0xff; + uart[UART_LCR] = UART_LCR_PODD | UART_LCR_8BIT; +} + +//static int ns16550a_getchar() +//{ +// if (uart[UART_LSR] & UART_LSR_DA) { +// return uart[UART_RBR]; +// } else { +// return -1; +// } +//} +// +//static int ns16550a_putchar(int ch) +//{ +// while ((uart[UART_LSR] & UART_LSR_RI) == 0); +// return uart[UART_THR] = ch & 0xff; +//} + +void stopSim(){ + *((volatile uint32_t*) 0xFFFFFFFC) = 0; +} + +void putC(char ch){ + while ((uart[UART_LSR] & UART_LSR_RI) == 0); + uart[UART_THR] = ch & 0xff; +} + + +uint32_t rdtime(){ + return *((volatile uint32_t*) SIFIVE_TIME_BASE); +} + +uint32_t rdtimeh(){ + return *((volatile uint32_t*) (SIFIVE_TIME_BASE + 4)); +} + +void setMachineTimerCmp(uint32_t low, uint32_t high){ + volatile uint32_t* base = (volatile uint32_t*) SIFIVE_TIMECMP_BASE; + base[1] = 0xffffffff; + base[0] = low; + base[1] = high; +} + +void halInit(){ + ns16550a_init(); +} +#endif + + + + diff --git a/src/main/c/emulator/src/hal.h b/src/main/c/emulator/src/hal.h index c5cb70a..90e3df9 100644 --- a/src/main/c/emulator/src/hal.h +++ b/src/main/c/emulator/src/hal.h @@ -14,6 +14,7 @@ #define SBI_REMOTE_SFENCE_VMA_ASID 7 #define SBI_SHUTDOWN 8 +void halInit(); void stopSim(); void putC(char c); uint32_t rdtime(); diff --git a/src/main/c/emulator/src/main.c b/src/main/c/emulator/src/main.c index bcaf82f..c637fba 100755 --- a/src/main/c/emulator/src/main.c +++ b/src/main/c/emulator/src/main.c @@ -7,16 +7,28 @@ extern const uint32_t _sp; extern void trapEntry(); extern void emulationTrap(); +void putString(char* s){ + while(*s){ + putC(*s); + s++; + } +} + void init() { + halInit(); + putString("*** VexRiscv BIOS ***\n"); uint32_t sp = (uint32_t) (&_sp); csr_write(mtvec, trapEntry); csr_write(mscratch, sp -32*4); csr_write(mstatus, 0x0800 | MSTATUS_MPIE); csr_write(mie, 0); csr_write(mepc, OS_CALL); + //In future it would probably need to manage missaligned stuff, now it will stop the simulation csr_write(medeleg, MEDELEG_INSTRUCTION_PAGE_FAULT | MEDELEG_LOAD_PAGE_FAULT | MEDELEG_STORE_PAGE_FAULT | MEDELEG_USER_ENVIRONNEMENT_CALL); csr_write(mideleg, MIDELEG_SUPERVISOR_TIMER | MIDELEG_SUPERVISOR_EXTERNAL | MIDELEG_SUPERVISOR_SOFTWARE); csr_write(sbadaddr, 0); //Used to avoid simulation missmatch + + putString("*** Supervisor ***\n"); } int readRegister(uint32_t id){ @@ -29,7 +41,7 @@ void writeRegister(uint32_t id, int value){ } - +//Currently, this should not happen, unless kernel things are going wrong void redirectTrap(){ stopSim(); csr_write(sbadaddr, csr_read(mbadaddr));