Add a qemu option (wip)

This commit is contained in:
Dolu1990 2019-03-30 18:26:29 +01:00
parent 1a36f2689d
commit 9383445e0b
4 changed files with 121 additions and 2 deletions

View File

@ -1,6 +1,8 @@
#ifndef CONFIG_H #ifndef CONFIG_H
#define CONFIG_H #define CONFIG_H
//#define QEMU
#define SIM
#define OS_CALL 0xC0000000 #define OS_CALL 0xC0000000
#define DTB 0x81000000 #define DTB 0x81000000

View File

@ -1,5 +1,7 @@
#include "hal.h" #include "hal.h"
#include "config.h"
#ifdef SIM
void stopSim(){ void stopSim(){
*((volatile uint32_t*) 0xFFFFFFFC) = 0; *((volatile uint32_t*) 0xFFFFFFFC) = 0;
} }
@ -16,10 +18,112 @@ uint32_t rdtimeh(){
return *((volatile uint32_t*) 0xFFFFFFE4); return *((volatile uint32_t*) 0xFFFFFFE4);
} }
void setMachineTimerCmp(uint32_t low, uint32_t high){ void setMachineTimerCmp(uint32_t low, uint32_t high){
volatile uint32_t* base = (volatile uint32_t*) 0xFFFFFFE8; volatile uint32_t* base = (volatile uint32_t*) 0xFFFFFFE8;
base[1] = 0xffffffff; base[1] = 0xffffffff;
base[0] = low; base[0] = low;
base[1] = high; 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

View File

@ -14,6 +14,7 @@
#define SBI_REMOTE_SFENCE_VMA_ASID 7 #define SBI_REMOTE_SFENCE_VMA_ASID 7
#define SBI_SHUTDOWN 8 #define SBI_SHUTDOWN 8
void halInit();
void stopSim(); void stopSim();
void putC(char c); void putC(char c);
uint32_t rdtime(); uint32_t rdtime();

View File

@ -7,16 +7,28 @@ extern const uint32_t _sp;
extern void trapEntry(); extern void trapEntry();
extern void emulationTrap(); extern void emulationTrap();
void putString(char* s){
while(*s){
putC(*s);
s++;
}
}
void init() { void init() {
halInit();
putString("*** VexRiscv BIOS ***\n");
uint32_t sp = (uint32_t) (&_sp); uint32_t sp = (uint32_t) (&_sp);
csr_write(mtvec, trapEntry); csr_write(mtvec, trapEntry);
csr_write(mscratch, sp -32*4); csr_write(mscratch, sp -32*4);
csr_write(mstatus, 0x0800 | MSTATUS_MPIE); csr_write(mstatus, 0x0800 | MSTATUS_MPIE);
csr_write(mie, 0); csr_write(mie, 0);
csr_write(mepc, OS_CALL); 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(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(mideleg, MIDELEG_SUPERVISOR_TIMER | MIDELEG_SUPERVISOR_EXTERNAL | MIDELEG_SUPERVISOR_SOFTWARE);
csr_write(sbadaddr, 0); //Used to avoid simulation missmatch csr_write(sbadaddr, 0); //Used to avoid simulation missmatch
putString("*** Supervisor ***\n");
} }
int readRegister(uint32_t id){ 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(){ void redirectTrap(){
stopSim(); stopSim();
csr_write(sbadaddr, csr_read(mbadaddr)); csr_write(sbadaddr, csr_read(mbadaddr));