Skip to content

Commit

Permalink
feat(16550): add configureble 16550 for riscv64-xs (#43)
Browse files Browse the repository at this point in the history
- Migrating 16550 serial port functionality from gos(https://github.com/OpenXiangShan/gos/blob/master/mysbi/sbi/uart_ns16550a.c) to am
- Using the same 16550 address with FPGA
- configurable with macro, and docs are in README

Co-authored-by: jiaxiaoyu <[email protected]>
  • Loading branch information
shinezyy and xyyy1420 authored Dec 3, 2024
1 parent ef5492d commit 6fc8d88
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 2 deletions.
5 changes: 3 additions & 2 deletions Makefile.compile
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,18 @@ CFLAGS += $(CC_OPT) -MMD -Wall -Werror -ggdb $(INCLUDES) \
-fno-asynchronous-unwind-tables -fno-builtin -fno-stack-protector \
-Wno-main
CXXFLAGS += $(CFLAGS) -ffreestanding -fno-rtti -fno-exceptions
CPPFLAGS ?=
ASFLAGS += -MMD $(INCLUDES)

## Compliation rule for .c -> .o (using gcc)
$(DST_DIR)/%.o: %.c
@mkdir -p $(dir $@) && echo + CC $<
@$(CC) -std=gnu11 $(CFLAGS) -c -o $@ $(realpath $<)
@$(CC) $(CPPFLAGS) -std=gnu11 $(CFLAGS) -c -o $@ $(realpath $<)

## Compliation rule for .cpp -> .o (using g++)
$(DST_DIR)/%.o: %.cpp
@mkdir -p $(dir $@) && echo + CXX $<
@$(CXX) -std=c++11 $(CXXFLAGS) -c -o $@ $(realpath $<)
@$(CXX) $(CPPFLAGS) -std=c++11 $(CXXFLAGS) -c -o $@ $(realpath $<)

## Compliation rule for .S -> .o (using as)
$(DST_DIR)/%.o: %.S
Expand Down
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,32 @@ Finalize CPU ID: 0
```

Note that both `sum` and `atomic_sum` are incremented 100 times per CPU parallelly. However, `atomic_sum` utilizes atomic primitive. Thus, we have `sum` <= 200 && `atomic_sum` == 200.


## How to build AM image for 16550

The major difference between RTL simulation with Verilator and FPGA of Xiangshan is that FPGA is using 16550 at 0x310b0000,
while RTL simulation is using UARTLITE at 0x40600000.
So we should change the serial devices when compiling for FPGA by
``` shell
# Hello as an example
cd apps/hello
rm -rf $AM_HOME/am/build build # Macro definition is not yet added into dependency of Makefile, clean am.a manually
make ARCH=riscv64-xs CPPFLAGS=-DUART16550=1 # define UART16550
```
Then run `build/hello-riscv64-xs.bin` on FPGA

Remember to `rm -rf $AM_HOME/am/build build` if you want to switch back to uartlite.


## How to generate compile_commands.json

`compile_commands.json` can be used in many language servers to help completion.

``` shell
# Hello as an example
rm -rf $AM_HOME/am/build apps/hello/build # A full rebuild to obtain full compile commands
bear -- make -C apps/hello ARCH=riscv64-xs
```

If you don't have bear on your machine, please search.
1 change: 1 addition & 0 deletions am/arch/riscv64-noop.mk
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ AM_SRCS := noop/isa/riscv/trm.c \
nemu/common/mainargs.S \
noop/isa/riscv/perf.c \
noop/common/uartlite.c \
noop/common/serial-16550.c \
nemu/isa/riscv/cte.c \
nemu/isa/riscv/trap.S \
nemu/isa/riscv/cte64.c \
Expand Down
1 change: 1 addition & 0 deletions am/arch/riscv64-xs.mk
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ AM_SRCS := noop/isa/riscv/trm.c \
nemu/common/mainargs.S \
noop/isa/riscv/perf.c \
noop/common/uartlite.c \
noop/common/serial-16550.c \
nemu/isa/riscv/cte.c \
nemu/isa/riscv/trap.S \
nemu/isa/riscv/cte64.c \
Expand Down
78 changes: 78 additions & 0 deletions am/src/noop/common/serial-16550.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#include <riscv.h>


/*
* Copyright (c) 2024 Beijing Institute of Open Source Chip (BOSC)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2 or later, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/


//#define SERIAL_MMIO 0x10000000
#define SERIAL_MMIO 0x310b0000

#define RBR 0x00
#define THR 0x00
#define DLL 0x00
#define DLH 0x04
#define IER 0x04
#define FCR 0x08
#define LCR 0x0c
#define MCR 0x10
#define LSR 0x14
#define USR 0x7c

#define DTR 0X01
#define RTS 0X02

// note: ns16550a_delay __am_16550_putchar __am_init_16550 is migrated directly from https://github.com/OpenXiangShan/gos/blob/master/mysbi/sbi/uart_ns16550a.c

static void ns16550a_delay(unsigned int loops)
{
while (loops--) {
__asm__ volatile ("nop");
}
}

void __am_16550_putchar(char ch) {
if (ch == '\n') __am_16550_putchar('\r');

unsigned int value;

value = inl(SERIAL_MMIO + LSR);
while (!(value & 0x60)) {
ns16550a_delay(100);
value = inl(SERIAL_MMIO + LSR);
}

outl(SERIAL_MMIO + THR, ch);

}

void __am_init_16550(){
unsigned int divisor;
divisor = 50000000 / (16 * 115200);

outl(SERIAL_MMIO + IER, 0x00);

outl(SERIAL_MMIO + LCR, 0x83); // enable DLAB
while (inl(SERIAL_MMIO + USR) & 0x1) ;

outl(SERIAL_MMIO + DLH, 0x00); // 115200
outl(SERIAL_MMIO + DLL, divisor); // 115200

outl(SERIAL_MMIO + LCR, 0x03); // disable DLAB

outl(SERIAL_MMIO + FCR, 0x01);
outl(SERIAL_MMIO + MCR, RTS | DTR);
}
10 changes: 10 additions & 0 deletions am/src/noop/isa/riscv/trm.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,20 @@ extern char _pmem_end;
int main(const char *args);
void __am_init_uartlite(void);
void __am_uartlite_putchar(char ch);
void __am_init_16550(void);
void __am_16550_putchar(char ch);

_Area _heap = {
.start = &_heap_start,
.end = &_pmem_end,
};

void _putc(char ch) {
#ifdef UART16550
__am_16550_putchar(ch);
#else
__am_uartlite_putchar(ch);
#endif
}

void _halt(int code) {
Expand All @@ -28,7 +34,11 @@ void _halt(int code) {
}

void _trm_init() {
#ifdef UART16550
__am_init_16550();
#else
__am_init_uartlite();
#endif
extern const char __am_mainargs;
int ret = main(&__am_mainargs);
_halt(ret);
Expand Down

0 comments on commit 6fc8d88

Please sign in to comment.