8000 qemu-arm: Merge RISC-V 32-bit support into qemu-arm port. · cuatrobits/micropython@0426934 · GitHub
[go: up one dir, main page]

Skip to content

Commit 0426934

Browse files
committed
qemu-arm: Merge RISC-V 32-bit support into qemu-arm port.
Currently both the qemu-arm and qemu-riscv ports share a lot of code and functionality. This commit merges the qemu-riscv port into the qemu-arm port. The only real differences between the two are the toolchains used to build the code, and the initialisation/startup framework. Everything else is pretty much the same, so this brings the following benefits: - less code duplication - less burden on maintenance - generalised qemu port, could in the future support other architectures A new board `VIRT_RV32` has been added to the qemu-arm port which is the existing RISC-V board from the qemu-riscv port. To build it: $ make BOARD=VIRT_RV32 repl To cleanly separate the code for the different architectures, startup code has been moved to ports/qemu-arm/mcu/<arch>/. Signed-off-by: Damien George <damien@micropython.org>
1 parent f769b43 commit 0426934

33 files changed

+212
-602
lines changed

.github/workflows/ports_qemu-arm.yml

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,26 @@ concurrency:
1919
cancel-in-progress: true
2020

2121
jobs:
22-
build_and_test:
22+
build_and_test_arm:
2323
runs-on: ubuntu-latest
2424
steps:
2525
- uses: actions/checkout@v4
2626
- name: Install packages
27-
run: source tools/ci.sh && ci_qemu_arm_setup
27+
run: source tools/ci.sh && ci_qemu_setup_arm
2828
- name: Build and run test suite
29-
run: source tools/ci.sh && ci_qemu_arm_build
29+
run: source tools/ci.sh && ci_qemu_build_arm
30+
- name: Print failures
31+
if: failure()
32+
run: tests/run-tests.py --print-failures
33+
34+
build_and_test_rv32:
35+
runs-on: ubuntu-latest
36+
steps:
37+
- uses: actions/checkout@v4
38+
- name: Install packages
39+
run: source tools/ci.sh && ci_qemu_setup_rv32
40+
- name: Build and run test suite
41+
run: source tools/ci.sh && ci_qemu_build_rv32
3042
- name: Print failures
3143
if: failure()
3244
run: tests/run-tests.py --print-failures

.github/workflows/ports_qemu-riscv.yml

Lines changed: 0 additions & 33 deletions
This file was deleted.

ports/qemu-arm/Makefile

Lines changed: 92 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
################################################################################
2+
# Initial setup of Makefile environment
3+
14
BOARD ?= MPS2_AN385
25

36
# Make the build directory reflect the board.
@@ -14,16 +17,79 @@ QSTR_DEFS = qstrdefsport.h
1417

1518
# MicroPython feature configurations
1619
MICROPY_ROM_TEXT_COMPR 10000 ESSION ?= 1
20+
21+
ifeq ($(QEMU_ARCH),arm)
1722
FROZEN_MANIFEST ?= "freeze('test-frzmpy')"
23+
endif
24+
ifeq ($(QEMU_ARCH),riscv32)
25+
FROZEN_MANIFEST ?= "freeze('test-frzmpy', ('frozen_const.py', 'frozen_viper.py', 'native_frozen_align.py'))"
26+
endif
1827

1928
# include py core make definitions
2029
include $(TOP)/py/py.mk
2130
include $(TOP)/extmod/extmod.mk
2231

32+
################################################################################
33+
# ARM specific settings
34+
35+
ifeq ($(QEMU_ARCH),arm)
36+
2337
CROSS_COMPILE ?= arm-none-eabi-
2438

39+
LDFLAGS += -nostdlib
40+
LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
41+
42+
SRC_C += \
43+
mcu/arm/startup.c \
44+
shared/runtime/semihosting_arm.c \
45+
46+
endif
47+
48+
################################################################################
49+
# RISC-V 32-bit specific settings
50+
51+
ifeq ($(QEMU_ARCH),riscv32)
52+
53+
CROSS_COMPILE ?= riscv64-unknown-elf-
54+
55+
GCC_VERSION = $(word 1, $(subst ., , $(shell $(CC) -dumpversion)))
56+
57+
RV32_ABI = ilp32
58+
59+
QEMU_ARGS += -bios none
60+
61+
# GCC 10 and lower do not recognise the Zicsr extension in the architecture name.
62+
ifeq ($(shell test $(GCC_VERSION) -le 10; echo $$?),0)
63+
RV32_ARCH ?= rv32imac
64+
else
65+
# Recent GCC versions explicitly require to declare extensions.
66+
RV32_ARCH ?= rv32imac_zicsr
67+
endif
68+
69+
AFLAGS += -mabi=$(RV32_ABI) -march=$(RV32_ARCH)
70+
CFLAGS += $(AFLAGS)
71+
LDFLAGS += -mabi=$(RV32_ABI) -march=$(RV32_ARCH) -Wl,-EL
72+
73+
SRC_C += \
74+
mcu/rv32/interrupts.c \
75+
mcu/rv32/startup.c \
76+
77+
SRC_BOARD_O += mcu/rv32/entrypoint.o
78+
79+
endif
80+
81+
################################################################################
82+
# Project specific settings and compiler/linker flags
83+
2584
QEMU_SYSTEM = qemu-system-$(QEMU_ARCH)
2685
QEMU_ARGS += -machine $(QEMU_MACHINE) -nographic -monitor null -semihosting
86+
QEMU_ARGS += $(QEMU_EXTRA)
87+
88+
# Specifying QEMU_DEBUG=1 will block qemu until a debugger is connected.
89+
ifeq ($(QEMU_DEBUG),1)
90+
QEMU_DEBUG_ARGS ?= -s
91+
QEMU_ARGS += -S $(QEMU_DEBUG_ARGS) $(QEMU_DEBUG_EXTRA)
92+
endif
2793

2894
INC += -I.
2995
INC += -I$(TOP)
@@ -34,6 +100,8 @@ CFLAGS += $(INC) -Wall -Wpointer-arith -Wdouble-promotion -Wfloat-conversion -We
34100
-ffunction-sections -fdata-sections
35101
CFLAGS += $(CFLAGS_EXTRA)
36102

103+
LDFLAGS += -T $(LDSCRIPT) -Wl,--gc-sections -Wl,-Map=$(@:.elf=.map)
104+
37105
# Debugging/Optimization
38106
ifeq ($(DEBUG), 1)
39107
CFLAGS += -g
@@ -42,25 +110,31 @@ else
42110
COPT += -Os -DNDEBUG
43111
endif
44112

45-
## With CoudeSourcery it's actually a little different, you just need `-T generic-m-hosted.ld`.
46-
## Although for some reason `$(LD)` will not find that linker script, it works with `$(CC)`.
47-
## It turns out that this is specific to CoudeSourcery, and ARM version of GCC ships something
48-
## else instead and according to the following files, this is what we need to pass to `$(CC).
49-
## - gcc-arm-none-eabi-4_8-2014q1/share/gcc-arm-none-eabi/samples/src/makefile.conf
50-
## - gcc-arm-none-eabi-4_8-2014q1/share/gcc-arm-none-eabi/samples/src/qemu/Makefile
51-
LDFLAGS= -T $(LDSCRIPT) --gc-sections -Map=$(@:.elf=.map)
52-
LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
113+
# If Picolibc is available then select it explicitly. Ubuntu 22.04 ships its
114+
# bare metal RISC-V toolchain with Picolibc rather than Newlib, and the default
115+
# is "nosys" so a value must be provided. To avoid having per-distro
116+
# workarounds, always select Picolibc if available.
117+
PICOLIBC_SPECS = $(shell $(CC) --print-file-name=picolibc.specs)
118+
ifeq ($(PICOLIBC_SPECS),picolibc.specs)
119+
# Picolibc was not found.
120+
else
121+
$(info picolibc used $(PICOLIBC_SPECS))
122+
SPECS_FRAGMENT = --specs=$(PICOLIBC_SPECS)
123+
CFLAGS += $(SPECS_FRAGMENT)
124+
LDFLAGS += $(SPECS_FRAGMENT)
125+
endif
53126

54-
SRC_C = \
127+
################################################################################
128+
# Source files and libraries
129+
130+
SRC_C += \
55131
main.c \
56-
startup.c \
57132
uart.c \
58133
mphalport.c \
59134
shared/libc/string0.c \
60135
shared/readline/readline.c \
61136
shared/runtime/interrupt_char.c \
62137
shared/runtime/pyexec.c \
63-
shared/runtime/semihosting_arm.c \
64138
shared/runtime/stdout_helpers.c \
65139
shared/runtime/sys_stdio_mphal.c \
66140

@@ -75,6 +149,9 @@ OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o))
75149
# List of sources for qstr extraction
76150
SRC_QSTR += $(SRC_C) $(LIB_SRC_C)
77151

152+
################################################################################
153+
# Main targets
154+
78155
all: $(BUILD)/firmware.elf
79156

80157
.PHONY: repl
@@ -91,9 +168,11 @@ test: $(BUILD)/firmware.elf
91168
$(eval DIRNAME=ports/$(notdir $(CURDIR)))
92169
cd $(TOP)/tests && ./run-tests.py --target qemu-arm --device execpty:"$(QEMU_SYSTEM) $(QEMU_ARGS) -serial pty -kernel ../$(DIRNAME)/$<" $(RUN_TESTS_ARGS) $(RUN_TESTS_EXTRA)
93170

94-
## `$(LD)` doesn't seem to like `--specs` for some reason, but we can just use `$(CC)` here.
95171
$(BUILD)/firmware.elf: $(LDSCRIPT) $(OBJ)
96-
$(Q)$(LD) $(LDFLAGS) -o $@ $(OBJ) $(LIBS)
172+
$(Q)$(CC) $(LDFLAGS) -o $@ $(OBJ) $(LIBS)
97173
$(Q)$(SIZE) $@
98174

175+
################################################################################
176+
# Remaining make rules
177+
99178
include $(TOP)/py/mkrules.mk

ports/qemu-arm/README.md

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
MicroPython port to qemu-arm
22
============================
33

4-
This is experimental, community-supported port for Cortex-M emulation as
5-
provided by QEMU (http://qemu.org).
4+
This is experimental, community-supported port for Cortex-M and RISC-V RV32IMC
5+
emulation as provided by QEMU (http://qemu.org).
66

77
The purposes of this port are to enable:
88

@@ -18,6 +18,25 @@ The purposes of this port are to enable:
1818
- no need to use OpenOCD or anything else that might slow down the
1919
process in terms of plugging things together, pressing buttons, etc.
2020

21+
Dependencies
22+
------------
23+
24+
### ARM
25+
26+
For ARM-based boards the build requires a bare-metal ARM toolchain, such as
27+
`arm-none-eabi-gcc`.
28+
29+
### RISC-V
30+
31+
For RISC-V-based boards the build requires a bare metal RISC-V toolchain with GCC 10
32+
or later, either with multilib support or 32 bits specific (M, C, and Zicsr
33+
extensions must be supported, along with ilp32 ABI). Both newlib and picolibc are
34+
supported, with the latter having precedence if found.
35+
36+
Most pre-built toolchains should work out of the box, either coming from your
37+
Linux distribution's package manager, or independently packaged ones like
38+
[xPack](https://xpack.github.io/dev-tools/riscv-none-elf-gcc/).
39+
2140
Build instructions
2241
------------------
2342

@@ -36,12 +55,13 @@ different board pass the `BOARD` argument to `make`, for example:
3655

3756
Available boards are:
3857

39-
| Name for `BOARD=` | Corresponding qemu board |
40-
| ----------------- | ------------------------ |
41-
| `MICROBIT` | `microbit` |
42-
| `MPS2_AN385` | `mps2-an385` |
43-
| `NETDUINO2` | `netduino2` |
44-
| `SABRELITE` | `sabrelite` |
58+
| Name for `BOARD=` | Architecture | Corresponding qemu board |
59+
| ----------------- | ------------ | ------------------------ |
60+
| `MICROBIT` | `arm` | `microbit` |
61+
| `MPS2_AN385` | `arm` | `mps2-an385` |
62+
| `NETDUINO2` | `arm` | `netduino2` |
63+
| `SABRELITE` | `arm` | `sabrelite` |
64+
| `VIRT_RV32` | `riscv32` | `virt` |
4565

4666
Running
4767
-------
@@ -84,3 +104,9 @@ The following options can be specified on the `make` command line:
84104
- `CFLAGS_EXTRA`: pass in extra flags for the compiler.
85105
- `RUN_TESTS_EXTRA`: pass in extra flags for `run-tests.py` when invoked via
86106
`make test`.
107+
- `QEMU_DEBUG=1`: when running qemu (via `repl`, `run` or `test` target), qemu
108+
will block until a debugger is connected. By default it waits for a gdb connection
109+
on TCP port 1234.
110+
- `QEMU_DEBUG_ARGS`: defaults to `-s` (gdb on TCP port 1234), but can be overridden
111+
with different qemu gdb arguments.
112+
- `QEMU_DEBUG_EXTRA`: extra options to pass to qemu when `QEMU_DEBUG=1` is used.

ports/qemu-arm/boards/MICROBIT.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ CFLAGS += -mthumb -mcpu=cortex-m0 -mfloat-abi=soft
66
CFLAGS += -DQEMU_SOC_NRF51
77
CFLAGS += -DMICROPY_HW_MCU_NAME='"nRF51"'
88

9-
LDSCRIPT = nrf51.ld
9+
LDSCRIPT = mcu/arm/nrf51.ld
1010

1111
SRC_BOARD_O = shared/runtime/gchelper_native.o shared/runtime/gchelper_thumb1.o
1212

ports/qemu-arm/boards/MPS2_AN385.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ CFLAGS += -mthumb -mcpu=cortex-m3 -mfloat-abi=soft
55
CFLAGS += -DQEMU_SOC_MPS2
66
CFLAGS += -DMICROPY_HW_MCU_NAME='"Cortex-M3"'
77

8-
LDSCRIPT = mps2.ld
8+
LDSCRIPT = mcu/arm/mps2.ld
99

1010
SRC_BOARD_O = shared/runtime/gchelper_native.o shared/runtime/gchelper_thumb2.o
1111

ports/qemu-arm/boards/NETDUINO2.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ CFLAGS += -mthumb -mcpu=cortex-m3 -mfloat-abi=soft
55
CFLAGS += -DQEMU_SOC_STM32
66
CFLAGS += -DMICROPY_HW_MCU_NAME='"STM32"'
77

8-
LDSCRIPT = stm32.ld
8+
LDSCRIPT = mcu/arm/stm32.ld
99

1010
SRC_BOARD_O = shared/runtime/gchelper_native.o shared/runtime/gchelper_thumb2.o
1111

ports/qemu-arm/boards/SABRELITE.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ CFLAGS += -DMICROPY_HW_MCU_NAME='"Cortex-A9"'
88
# Cortex-A9 should support unaligned-access, but qemu doesn't seem to.
99
CFLAGS += -mno-unaligned-access
1010

11-
LDSCRIPT = imx6.ld
11+
LDSCRIPT = mcu/arm/imx6.ld
1212

1313
SRC_BOARD_O = shared/runtime/gchelper_generic.o
1414

ports/qemu-arm/boards/VIRT_RV32.mk

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
QEMU_ARCH = riscv32
2+
QEMU_MACHINE = virt
3+
4+
CFLAGS += -DQEMU_SOC_VIRT
5+
CFLAGS += -DMICROPY_HW_MCU_NAME='"$(RV32_ARCH)"'
6+
7+
LDSCRIPT = mcu/rv32/virt.ld
8+
9+
SRC_BOARD_O += shared/runtime/gchelper_native.o shared/runtime/gchelper_rv32i.o
10+
11+
MPY_CROSS_FLAGS += -march=rv32imc
12+
13+
# These Thumb tests don't run on RV32, so exclude them.
14+
RUN_TESTS_ARGS = --exclude 'inlineasm|qemu-arm/asm_test'
File renamed without changes.

0 commit comments

Comments
 (0)
0