Add a qemu option (wip)
This commit is contained in:
parent
1a36f2689d
commit
9383445e0b
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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));
|
||||||
|
|
Loading…
Reference in New Issue