Skip to content

Commit fce9833

Browse files
committed
tests/run-tests, ports/qemu-riscv: Add QEMU RV32 port.
This adds a QEMU-based bare metal RISC-V 32 bits port. For the time being only QEMU's "virt" 32 bits board is supported, using the ilp32 ABI and the RV32IMC architecture. Tests run and pass, and the test generator framework was modified to remove hardcoded references to the "qemu-arm" port. Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
1 parent 958c6d9 commit fce9833

18 files changed

+1072
-0
lines changed

ports/qemu-riscv/Makefile

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
include ../../py/mkenv.mk
2+
-include mpconfigport.mk
3+
4+
# qstr definitions (must come before including py.mk)
5+
QSTR_DEFS = qstrdefsport.h
6+
7+
# MicroPython feature configurations
8+
MICROPY_ROM_TEXT_COMPRESSION ?= 1
9+
10+
# include py core make definitions
11+
include $(TOP)/py/py.mk
12+
include $(TOP)/extmod/extmod.mk
13+
14+
CROSS_COMPILE ?= riscv64-unknown-elf-
15+
16+
BOARD ?= virt
17+
LDFLAGS = --gc-sections -Map=$(@:.elf=.map)
18+
LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
19+
20+
ifeq ($(BOARD),virt)
21+
ABI=ilp32
22+
ARCH=rv32imc_zicsr
23+
AFLAGS = -mabi=$(ABI) -march=$(ARCH)
24+
CFLAGS += -mabi=$(ABI) -fPIC -mlittle-endian -march=$(ARCH) -mcmodel=medany
25+
CFLAGS += -DQEMU_SOC_VIRT
26+
LDSCRIPT = virt.ld
27+
LDFLAGS += -T $(LDSCRIPT) -m elf32lriscv
28+
SRC_BOARD_O = shared/runtime/gchelper_generic.o setjmp.o
29+
SRC_BOARD_O += entry.o
30+
endif
31+
32+
INC += -I.
33+
INC += -I$(TOP)
34+
INC += -I$(BUILD)
35+
36+
CFLAGS += $(INC) -Wall -Wpointer-arith -Wdouble-promotion -Wfloat-conversion -Werror -std=gnu99 $(COPT) \
37+
-ffunction-sections -fdata-sections
38+
CFLAGS += $(CFLAGS_EXTRA)
39+
40+
# Debugging/Optimization
41+
ifeq ($(DEBUG), 1)
42+
CFLAGS += -g
43+
COPT = -O0
44+
else
45+
COPT += -Os -DNDEBUG
46+
endif
47+
48+
SRC_COMMON_C = \
49+
interrupts.c \
50+
startup.c \
51+
uart.c \
52+
modmachine.c \
53+
shared/libc/string0.c \
54+
shared/runtime/sys_stdio_mphal.c \
55+
56+
SRC_RUN_C = \
57+
main.c \
58+
59+
SRC_TEST_C = \
60+
test_main.c \
61+
lib/tinytest/tinytest.c \
62+
63+
LIB_SRC_C += $(addprefix lib/,\
64+
libm/math.c \
65+
libm/fmodf.c \
66+
libm/nearbyintf.c \
67+
libm/ef_sqrt.c \
68+
libm/kf_rem_pio2.c \
69+
libm/kf_sin.c \
70+
libm/kf_cos.c \
71+
libm/kf_tan.c \
72+
libm/ef_rem_pio2.c \
73+
libm/sf_sin.c \
74+
libm/sf_cos.c \
75+
libm/sf_tan.c \
76+
libm/sf_frexp.c \
77+
libm/sf_modf.c \
78+
libm/sf_ldexp.c \
79+
libm/asinfacosf.c \
80+
libm/atanf.c \
81+
libm/atan2f.c \
82+
libm/roundf.c \
83+
)
84+
85+
OBJ_COMMON =
86+
OBJ_COMMON += $(PY_O)
87+
OBJ_COMMON += $(addprefix $(BUILD)/, $(SRC_COMMON_C:.c=.o))
88+
OBJ_COMMON += $(addprefix $(BUILD)/, $(SRC_BOARD_O))
89+
OBJ_COMMON += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o))
90+
91+
OBJ_RUN =
92+
OBJ_RUN += $(addprefix $(BUILD)/, $(SRC_RUN_C:.c=.o))
93+
94+
ALL_OBJ_RUN = $(OBJ_COMMON) $(OBJ_RUN)
95+
96+
OBJ_TEST =
97+
OBJ_TEST += $(addprefix $(BUILD)/, $(SRC_TEST_C:.c=.o))
98+
99+
ALL_OBJ_TEST = $(OBJ_COMMON) $(OBJ_TEST)
100+
101+
# All object files, needed to get dependencies correct
102+
OBJ = $(OBJ_COMMON) $(OBJ_RUN) $(OBJ_TEST)
103+
104+
# List of sources for qstr extraction
105+
SRC_QSTR += $(SRC_COMMON_C) $(SRC_RUN_C) $(LIB_SRC_C)
106+
107+
all: run
108+
109+
debug: $(BUILD)/firmware.elf
110+
qemu-system-riscv32 -machine $(BOARD) -bios none $(QEMU_EXTRA) -nographic -monitor null -semihosting -serial mon:stdio -S -s -kernel $<
111+
112+
run: $(BUILD)/firmware.elf
113+
qemu-system-riscv32 -machine $(BOARD) -bios none $(QEMU_EXTRA) -nographic -monitor null -semihosting -kernel $<
114+
115+
## `$(LD)` doesn't seem to like `--specs` for some reason, but we can just use `$(CC)` here.
116+
$(BUILD)/firmware.elf: $(LDSCRIPT) $(ALL_OBJ_RUN)
117+
$(Q)$(LD) $(LDFLAGS) -o $@ $(ALL_OBJ_RUN) $(LIBS)
118+
$(Q)$(SIZE) $@
119+
120+
include $(TOP)/py/mkrules.mk

ports/qemu-riscv/Makefile.test

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
LIB_SRC_C = shared/upytesthelper/upytesthelper.c
2+
3+
include Makefile
4+
5+
ifeq ($(BOARD),virt)
6+
TESTS_EXCLUDE = extmod/deflate_decompress.py
7+
endif
8+
9+
CFLAGS += -DTEST
10+
11+
.PHONY: $(BUILD)/genhdr/tests.h
12+
13+
TESTS_PROFILE = $(dir $(abspath $(firstword $(MAKEFILE_LIST))))/tests_profile.txt
14+
15+
$(BUILD)/test_main.o: $(BUILD)/genhdr/tests.h
16+
$(BUILD)/genhdr/tests.h:
17+
(cd $(TOP)/tests; ./run-tests.py --target=qemu-riscv --write-exp)
18+
$(Q)echo "Generating $@";(cd $(TOP)/tests; ../tools/tinytest-codegen.py --profile $(TESTS_PROFILE) $(addprefix --exclude ,$(TESTS_EXCLUDE))) > $@
19+
20+
$(BUILD)/lib/tinytest/tinytest.o: CFLAGS += -DNO_FORKING
21+
22+
$(BUILD)/firmware-test.elf: $(LDSCRIPT) $(ALL_OBJ_TEST)
23+
$(Q)$(LD) $(LDFLAGS) -o $@ $(ALL_OBJ_TEST) $(LIBS)
24+
$(Q)$(SIZE) $@
25+
26+
# Note: Using timeout(1) to handle cases where qemu hangs (e.g. this can happen with alignment errors).
27+
test: $(BUILD)/firmware-test.elf
28+
timeout --foreground -k 5s 60s qemu-system-riscv32 -machine $(BOARD) -bios none $(QEMU_EXTRA) -nographic -monitor null -semihosting -kernel $< > $(BUILD)/console.out
29+
$(Q)tail -n2 $(BUILD)/console.out
30+
$(Q)tail -n1 $(BUILD)/console.out | grep -q "status: 0"
31+
32+
debugtest: $(BUILD)/firmware-test.elf
33+
qemu-system-riscv32 -machine $(BOARD) -bios none $(QEMU_EXTRA) -nographic -monitor null -semihosting -serial mon:stdio -S -s -kernel $<
34+

ports/qemu-riscv/README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
This is experimental, community-supported port for RISC-V RV32IM emulation as
2+
provided by QEMU (http://qemu.org).
3+
4+
The purposes of this port are to enable:
5+
6+
1. Continuous integration
7+
- run tests against architecture-specific parts of code base
8+
2. Experimentation
9+
- simulation & prototyping of anything that has architecture-specific
10+
code
11+
- exploring instruction set in terms of optimising some part of
12+
MicroPython or a module
13+
3. Streamlined debugging
14+
- no need for JTAG or even an MCU chip itself
15+
- no need to use OpenOCD or anything else that might slow down the
16+
process in terms of plugging things together, pressing buttons, etc.
17+
18+
This port requires a newlib based bare metal/ELF RISC-V toolchain, either
19+
with multilib support or 32 bits specific (M, C, and Zicsr extensions must
20+
be supported, along with ilp32 ABI). Either musl-based or glibc-based
21+
toolchains are not tested or known to work.
22+
23+
If your toolchain does not support the above requirements, either download
24+
a pre-built toolchain (and that's a hit or miss situation in its own right)
25+
or follow the instructions on [RISC-V's reference toolchain Github repo](https://github.com/riscv-collab/riscv-gnu-toolchain)
26+
to get a newlib-based multilib toolchain (the target will be
27+
`riscv64-unknown-elf` but said toolchain will be able to generate 32 bits
28+
code as well).
29+
30+
That said, when in doubt, build your own toolchain - it's the fastest way to
31+
get things going for sure.
32+
33+
To build and run image with builtin testsuite:
34+
35+
make -f Makefile.test test

ports/qemu-riscv/entry.s

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
3+
Adapted from https://wiki.osdev.org/RISC-V_Bare_Bones#entry.S
4+
5+
According to the page history, this content was added after 20110703, and
6+
following the text found at https://wiki.osdev.org/OSDev_Wiki:License the
7+
overall licence for this code is as follows:
8+
9+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
10+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
12+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
13+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
14+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
15+
THE SOFTWARE.
16+
17+
*/
18+
19+
.section .init
20+
.option norvc
21+
.type start, @function
22+
.global start
23+
24+
start:
25+
.cfi_startproc
26+
27+
.option push
28+
.option norelax
29+
30+
la gp, global_pointer
31+
32+
.option pop
33+
34+
csrw satp, zero
35+
la sp, stack_top
36+
la t5, bss_start
37+
la t6, bss_end
38+
39+
bss_clear:
40+
sw zero, (t5)
41+
addi t5, t5, 4
42+
bltu t5, t6, bss_clear
43+
44+
la t0, _entry_point
45+
csrw mepc, t0
46+
47+
tail _entry_point
48+
49+
.cfi_endproc
50+
.end
51+

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy