Add a qemu option (wip)
This commit is contained in:
parent
1a36f2689d
commit
9383445e0b
|
@ -1,6 +1,8 @@
|
|||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
//#define QEMU
|
||||
#define SIM
|
||||
#define OS_CALL 0xC0000000
|
||||
#define DTB 0x81000000
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue