qemu-riscv: Add new 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. The top-level README and the run-tests.py files are updated for this new port. Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
This commit is contained in:
parent
d7d77d91be
commit
2d69aab7b3
16 changed files with 1052 additions and 1 deletions
|
|
@ -114,7 +114,8 @@ In addition, the following ports are provided in this repository:
|
|||
- [nrf](ports/nrf) -- Nordic Semiconductor nRF51 and nRF52.
|
||||
- [pic16bit](ports/pic16bit) -- Microchip PIC 16-bit.
|
||||
- [powerpc](ports/powerpc) -- IBM PowerPC (including Microwatt)
|
||||
- [qemu-arm](ports/qemu-arm) -- QEMU-based emulated target, for testing)
|
||||
- [qemu-arm](ports/qemu-arm) -- QEMU-based Arm emulated target (for testing)
|
||||
- [qemu-riscv](ports/qemu-riscv) -- QEMU-based RISC-V emulated target (for testing)
|
||||
- [renesas-ra](ports/renesas-ra) -- Renesas RA family.
|
||||
- [rp2](ports/rp2) -- Raspberry Pi RP2040 (including Pico and Pico W).
|
||||
- [samd](ports/samd) -- Microchip (formerly Atmel) SAMD21 and SAMD51.
|
||||
|
|
|
|||
128
ports/qemu-riscv/Makefile
Normal file
128
ports/qemu-riscv/Makefile
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
include ../../py/mkenv.mk
|
||||
-include mpconfigport.mk
|
||||
|
||||
# qstr definitions (must come before including py.mk)
|
||||
QSTR_DEFS = qstrdefsport.h
|
||||
|
||||
# MicroPython feature configurations
|
||||
MICROPY_ROM_TEXT_COMPRESSION ?= 1
|
||||
|
||||
# include py core make definitions
|
||||
include $(TOP)/py/py.mk
|
||||
include $(TOP)/extmod/extmod.mk
|
||||
|
||||
BOARD ?= virt
|
||||
|
||||
CROSS_COMPILE ?= riscv64-unknown-elf-
|
||||
|
||||
GCC_VERSION = $(word 1, $(subst ., , $(shell $(CC) -dumpversion)))
|
||||
|
||||
# If Picolibc is available then select it explicitly. Ubuntu 22.04 ships its
|
||||
# bare metal RISC-V toolchain with Picolibc rather than Newlib, and the default
|
||||
# is "nosys" so a value must be provided. To avoid having per-distro
|
||||
# workarounds, always select Picolibc if available.
|
||||
PICOLIBC_SPECS = $(shell $(CC) --print-file-name=picolibc.specs)
|
||||
ifeq ($(PICOLIBC_SPECS),picolibc.specs)
|
||||
# Picolibc was not found.
|
||||
SPECS_FRAGMENT =
|
||||
else
|
||||
SPECS_FRAGMENT = --specs=$(PICOLIBC_SPECS)
|
||||
CFLAGS += $(SPECS_FRAGMENT)
|
||||
endif
|
||||
|
||||
ifeq ($(BOARD),virt)
|
||||
ABI = ilp32
|
||||
# GCC 10 and lower do not recognise the Zicsr extension in the
|
||||
# architecture name. "Make" unfortunately does not provide any simple way
|
||||
# to perform numeric comparisons, so to keep things simple we assume that
|
||||
# GCC is at least version 10 for the time being.
|
||||
ifeq ($(GCC_VERSION),10)
|
||||
ARCH ?= rv32imac
|
||||
else
|
||||
# Recent GCC versions explicitly require to declare extensions.
|
||||
ARCH ?= rv32imac_zicsr
|
||||
ARCH_LD ?= rv32imac_zicsr
|
||||
endif
|
||||
AFLAGS = -mabi=$(ABI) -march=$(ARCH)
|
||||
CFLAGS += $(AFLAGS)
|
||||
CFLAGS += -DQEMU_SOC_VIRT
|
||||
ARCH_LD ?= $(ARCH)
|
||||
LDSCRIPT = virt.ld
|
||||
LDFLAGS += -mabi=$(ABI) -march=$(ARCH_LD) -T $(LDSCRIPT) -Wl,-EL
|
||||
SRC_BOARD_O = shared/runtime/gchelper_native.o shared/runtime/gchelper_rv32i.o
|
||||
SRC_BOARD_O += entrypoint.o
|
||||
endif
|
||||
|
||||
INC += -I.
|
||||
INC += -I$(TOP)
|
||||
INC += -I$(BUILD)
|
||||
|
||||
CFLAGS += $(INC) -Wall -Wpointer-arith -Wdouble-promotion -Wfloat-conversion -Werror -std=gnu99 $(COPT) \
|
||||
-ffunction-sections -fdata-sections
|
||||
CFLAGS += $(CFLAGS_EXTRA)
|
||||
|
||||
LD = $(CC)
|
||||
|
||||
# Debugging/Optimization
|
||||
ifeq ($(DEBUG), 1)
|
||||
CFLAGS += -g
|
||||
COPT = -O0
|
||||
else
|
||||
COPT += -Os -DNDEBUG
|
||||
endif
|
||||
|
||||
LDFLAGS += $(SPECS_FRAGMENT) -Wl,--gc-sections -Wl,-Map=$(@:.elf=.map)
|
||||
|
||||
SRC_COMMON_C = \
|
||||
interrupts.c \
|
||||
startup.c \
|
||||
uart.c \
|
||||
shared/libc/string0.c \
|
||||
shared/runtime/sys_stdio_mphal.c \
|
||||
|
||||
SRC_RUN_C = \
|
||||
ports/qemu-arm/main.c \
|
||||
|
||||
SRC_TEST_C = \
|
||||
test_main.c \
|
||||
lib/tinytest/tinytest.c \
|
||||
|
||||
LIB_SRC_C += $(SRC_LIB_LIBM_C)
|
||||
LIB_SRC_C += $(SRC_LIB_LIBM_SQRT_SW_C)
|
||||
|
||||
OBJ_COMMON =
|
||||
OBJ_COMMON += $(PY_O)
|
||||
OBJ_COMMON += $(addprefix $(BUILD)/, $(SRC_COMMON_C:.c=.o))
|
||||
OBJ_COMMON += $(addprefix $(BUILD)/, $(SRC_BOARD_O))
|
||||
OBJ_COMMON += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o))
|
||||
|
||||
OBJ_RUN =
|
||||
OBJ_RUN += $(addprefix $(BUILD)/, $(SRC_RUN_C:.c=.o))
|
||||
|
||||
ALL_OBJ_RUN = $(OBJ_COMMON) $(OBJ_RUN)
|
||||
|
||||
OBJ_TEST =
|
||||
OBJ_TEST += $(addprefix $(BUILD)/, $(SRC_TEST_C:.c=.o))
|
||||
|
||||
ALL_OBJ_TEST = $(OBJ_COMMON) $(OBJ_TEST)
|
||||
|
||||
# All object files, needed to get dependencies correct
|
||||
OBJ = $(OBJ_COMMON) $(OBJ_RUN) $(OBJ_TEST)
|
||||
|
||||
# List of sources for qstr extraction
|
||||
SRC_QSTR += $(SRC_COMMON_C) $(SRC_RUN_C) $(LIB_SRC_C)
|
||||
|
||||
all: run
|
||||
|
||||
# `make debug` will block QEMU until a debugger is connected to port 1234.
|
||||
debug: $(BUILD)/firmware.elf
|
||||
qemu-system-riscv32 -machine $(BOARD) -bios none $(QEMU_EXTRA) -nographic -monitor null -semihosting -serial mon:stdio -S -s -kernel $<
|
||||
|
||||
run: $(BUILD)/firmware.elf
|
||||
qemu-system-riscv32 -machine $(BOARD) -bios none $(QEMU_EXTRA) -nographic -monitor null -semihosting -kernel $<
|
||||
|
||||
$(BUILD)/firmware.elf: $(LDSCRIPT) $(ALL_OBJ_RUN)
|
||||
$(Q)$(LD) $(LDFLAGS) -o $@ $(ALL_OBJ_RUN) $(LIBS)
|
||||
$(Q)$(SIZE) $@
|
||||
|
||||
include $(TOP)/py/mkrules.mk
|
||||
31
ports/qemu-riscv/Makefile.test
Normal file
31
ports/qemu-riscv/Makefile.test
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
LIB_SRC_C = shared/upytesthelper/upytesthelper.c
|
||||
|
||||
include Makefile
|
||||
|
||||
CFLAGS += -DTEST
|
||||
|
||||
.PHONY: $(BUILD)/genhdr/tests.h
|
||||
|
||||
TESTS_PROFILE = $(dir $(abspath $(firstword $(MAKEFILE_LIST))))/tests_profile.txt
|
||||
|
||||
$(BUILD)/test_main.o: $(BUILD)/genhdr/tests.h
|
||||
$(BUILD)/genhdr/tests.h:
|
||||
(cd $(TOP)/tests; ./run-tests.py --target=qemu-riscv --write-exp)
|
||||
$(Q)echo "Generating $@";(cd $(TOP)/tests; ../tools/tinytest-codegen.py --profile $(TESTS_PROFILE) $(addprefix --exclude ,$(TESTS_EXCLUDE))) > $@
|
||||
|
||||
$(BUILD)/lib/tinytest/tinytest.o: CFLAGS += -DNO_FORKING
|
||||
|
||||
$(BUILD)/firmware-test.elf: $(LDSCRIPT) $(ALL_OBJ_TEST)
|
||||
$(Q)$(LD) $(LDFLAGS) -o $@ $(ALL_OBJ_TEST) $(LIBS)
|
||||
$(Q)$(SIZE) $@
|
||||
|
||||
# Note: Using timeout(1) to handle cases where qemu hangs (e.g. this can happen with alignment errors).
|
||||
test: $(BUILD)/firmware-test.elf
|
||||
timeout --foreground -k 5s 60s qemu-system-riscv32 -machine $(BOARD) -bios none $(QEMU_EXTRA) -nographic -monitor null -semihosting -kernel $< > $(BUILD)/console.out
|
||||
$(Q)tail -n2 $(BUILD)/console.out
|
||||
$(Q)tail -n1 $(BUILD)/console.out | grep -q "status: 0"
|
||||
|
||||
# `make debugtest` will block QEMU until a debugger is connected to port 1234.
|
||||
|
||||
debugtest: $(BUILD)/firmware-test.elf
|
||||
qemu-system-riscv32 -machine $(BOARD) -bios none $(QEMU_EXTRA) -nographic -monitor null -semihosting -serial mon:stdio -S -s -kernel $<
|
||||
29
ports/qemu-riscv/README.md
Normal file
29
ports/qemu-riscv/README.md
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
This is an experimental, community-supported port for RISC-V RV32IMC emulation
|
||||
as provided by QEMU (http://qemu.org).
|
||||
|
||||
The purposes of this port are to enable:
|
||||
|
||||
1. Continuous integration
|
||||
- run tests against architecture-specific parts of code base
|
||||
2. Experimentation
|
||||
- simulation & prototyping of anything that has architecture-specific
|
||||
code
|
||||
- exploring instruction set in terms of optimising some part of
|
||||
MicroPython or a module
|
||||
3. Streamlined debugging
|
||||
- no need for JTAG or even an MCU chip itself
|
||||
- no need to use OpenOCD or anything else that might slow down the
|
||||
process in terms of plugging things together, pressing buttons, etc.
|
||||
|
||||
This port requires a bare metal RISC-V toolchain with GCC 10 or later, either
|
||||
with multilib support or 32 bits specific (M, C, and Zicsr extensions must be
|
||||
supported, along with ilp32 ABI). Both newlib and picolibc are supported,
|
||||
with the latter having precedence if found.
|
||||
|
||||
Most pre-built toolchains should work out of the box, either coming from your
|
||||
Linux distribution's package manager, or independently packaged ones like
|
||||
[xPack](https://xpack.github.io/dev-tools/riscv-none-elf-gcc/).
|
||||
|
||||
To build and run the image with builtin testsuite:
|
||||
|
||||
make -f Makefile.test test
|
||||
70
ports/qemu-riscv/entrypoint.s
Normal file
70
ports/qemu-riscv/entrypoint.s
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2023 Alessandro Gatti
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
.section .start
|
||||
.option norvc /* Do not emit compressed instructions. */
|
||||
.type start, @function
|
||||
.global start
|
||||
|
||||
start:
|
||||
.cfi_startproc
|
||||
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, _global_pointer /* Load global pointer register. */
|
||||
.option pop
|
||||
|
||||
csrw satp, zero /* Disable supervisor mode. */
|
||||
|
||||
/* Fill stack with a canary value. */
|
||||
|
||||
li t0, 0xBBBBBBBB /* Load canary value. */
|
||||
la t1, _sstack /* Load stack area start address. */
|
||||
la t2, _estack /* Load stack area end address. */
|
||||
1:
|
||||
sw t0, (t1) /* Write canary. */
|
||||
addi t1, t1, 4 /* Next word. */
|
||||
bltu t1, t2, 1b /* Loop until stack is filled. */
|
||||
|
||||
la sp, _estack /* Load stack pointer. */
|
||||
|
||||
/* Clear BSS area. */
|
||||
|
||||
la t1, _sbss /* Load BSS area start address. */
|
||||
la t2, _ebss /* Load BSS area end address. */
|
||||
1:
|
||||
sw zero, (t1) /* Clear word. */
|
||||
addi t1, t1, 4 /* Next word. */
|
||||
bltu t1, t2, 1b /* Loop until BSS is cleared. */
|
||||
|
||||
/* Set program counter. */
|
||||
|
||||
la t0, _entry_point /* Load program counter address. */
|
||||
csrw mepc, t0 /* Store it into machine exception PC. */
|
||||
tail _entry_point /* Jump to entry point. */
|
||||
|
||||
.cfi_endproc
|
||||
.end
|
||||
292
ports/qemu-riscv/interrupts.c
Normal file
292
ports/qemu-riscv/interrupts.c
Normal file
|
|
@ -0,0 +1,292 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2023 Alessandro Gatti
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Vector table
|
||||
|
||||
void mtvec_table(void) __attribute__((naked, section(".text.mtvec"), aligned(256)));
|
||||
|
||||
// Default interrupts
|
||||
|
||||
#define ASSIGN_EMPTY_MACHINE_INTERRUPT(interrupt_name) \
|
||||
void interrupt_name(void) __attribute__((alias("mtvec_nop")))
|
||||
|
||||
ASSIGN_EMPTY_MACHINE_INTERRUPT(mtvec_ssi);
|
||||
ASSIGN_EMPTY_MACHINE_INTERRUPT(mtvec_msi);
|
||||
ASSIGN_EMPTY_MACHINE_INTERRUPT(mtvec_sti);
|
||||
ASSIGN_EMPTY_MACHINE_INTERRUPT(mtvec_mti);
|
||||
ASSIGN_EMPTY_MACHINE_INTERRUPT(mtvec_sei);
|
||||
ASSIGN_EMPTY_MACHINE_INTERRUPT(mtvec_mei);
|
||||
ASSIGN_EMPTY_MACHINE_INTERRUPT(mtvec_plat_irq0);
|
||||
ASSIGN_EMPTY_MACHINE_INTERRUPT(mtvec_plat_irq1);
|
||||
ASSIGN_EMPTY_MACHINE_INTERRUPT(mtvec_plat_irq2);
|
||||
ASSIGN_EMPTY_MACHINE_INTERRUPT(mtvec_plat_irq3);
|
||||
ASSIGN_EMPTY_MACHINE_INTERRUPT(mtvec_plat_irq4);
|
||||
ASSIGN_EMPTY_MACHINE_INTERRUPT(mtvec_plat_irq5);
|
||||
ASSIGN_EMPTY_MACHINE_INTERRUPT(mtvec_plat_irq6);
|
||||
ASSIGN_EMPTY_MACHINE_INTERRUPT(mtvec_plat_irq7);
|
||||
ASSIGN_EMPTY_MACHINE_INTERRUPT(mtvec_plat_irq8);
|
||||
ASSIGN_EMPTY_MACHINE_INTERRUPT(mtvec_plat_irq9);
|
||||
ASSIGN_EMPTY_MACHINE_INTERRUPT(mtvec_plat_irq10);
|
||||
ASSIGN_EMPTY_MACHINE_INTERRUPT(mtvec_plat_irq11);
|
||||
ASSIGN_EMPTY_MACHINE_INTERRUPT(mtvec_plat_irq12);
|
||||
ASSIGN_EMPTY_MACHINE_INTERRUPT(mtvec_plat_irq13);
|
||||
ASSIGN_EMPTY_MACHINE_INTERRUPT(mtvec_plat_irq14);
|
||||
ASSIGN_EMPTY_MACHINE_INTERRUPT(mtvec_plat_irq15);
|
||||
|
||||
void mtvec_table(void) {
|
||||
__asm volatile (
|
||||
".org mtvec_table + 0 \n"
|
||||
"jal zero, mtvec_exception \n" // Exception Handler
|
||||
".org mtvec_table + 4 \n"
|
||||
"jal zero, mtvec_ssi \n" // Supervisor Software Interrupt
|
||||
".org mtvec_table + 12 \n"
|
||||
"jal zero, mtvec_msi \n" // Machine Software Interrupt
|
||||
".org mtvec_table + 20 \n"
|
||||
"jal zero, mtvec_sti \n" // Supervisor Timer Interrupt
|
||||
".org mtvec_table + 28 \n"
|
||||
"jal zero, mtvec_mti \n" // Machine Timer Interrupt
|
||||
".org mtvec_table + 36 \n"
|
||||
"jal zero, mtvec_sei \n" // Supervisor External Interrupt
|
||||
".org mtvec_table + 44 \n"
|
||||
"jal zero, mtvec_mei \n" // Machine External Interrupt
|
||||
// Not sure how many platform interrupts QEMU handles...
|
||||
".org mtvec_table + 48 \n"
|
||||
"jal mtvec_plat_irq0 \n" // Platform Interrupt #0
|
||||
"jal mtvec_plat_irq1 \n" // Platform Interrupt #1
|
||||
"jal mtvec_plat_irq2 \n" // Platform Interrupt #2
|
||||
"jal mtvec_plat_irq3 \n" // Platform Interrupt #3
|
||||
"jal mtvec_plat_irq4 \n" // Platform Interrupt #4
|
||||
"jal mtvec_plat_irq5 \n" // Platform Interrupt #5
|
||||
"jal mtvec_plat_irq6 \n" // Platform Interrupt #6
|
||||
"jal mtvec_plat_irq7 \n" // Platform Interrupt #7
|
||||
"jal mtvec_plat_irq8 \n" // Platform Interrupt #8
|
||||
"jal mtvec_plat_irq9 \n" // Platform Interrupt #9
|
||||
"jal mtvec_plat_irq10 \n" // Platform Interrupt #10
|
||||
"jal mtvec_plat_irq11 \n" // Platform Interrupt #11
|
||||
"jal mtvec_plat_irq12 \n" // Platform Interrupt #12
|
||||
"jal mtvec_plat_irq13 \n" // Platform Interrupt #13
|
||||
"jal mtvec_plat_irq14 \n" // Platform Interrupt #14
|
||||
"jal mtvec_plat_irq15 \n" // Platform Interrupt #15
|
||||
:
|
||||
:
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
|
||||
volatile uint32_t registers_copy[35] = { 0 };
|
||||
|
||||
const char *exception_causes[] = {
|
||||
"Reserved", // 0
|
||||
"Supervisor software interrupt", // 1
|
||||
"Machine software interrupt", // 2
|
||||
"Supervisor timer interrupt", // 3
|
||||
"Machine timer interrupt", // 4
|
||||
"Supervisor external interrupt", // 5
|
||||
"Machine external interrupt", // 6
|
||||
"Designated for platform use", // 7
|
||||
"Instruction address misaligned", // 8
|
||||
"Instruction address fault", // 9
|
||||
"Illegal instruction", // 10
|
||||
"Breakpoint", // 11
|
||||
"Load address misaligned", // 12
|
||||
"Load address fault", // 13
|
||||
"Store/AMO address misaligned", // 14
|
||||
"Store/AMO access fault", // 15
|
||||
"Environment call from U-mode", // 16
|
||||
"Environment call from S-mode", // 17
|
||||
"Environment call from M-mode", // 18
|
||||
"Instruction page fault", // 19
|
||||
"Load page fault", // 20
|
||||
"Store/AMO page fault", // 21
|
||||
"Designated for custom use" // 22
|
||||
};
|
||||
|
||||
const char *lookup_cause(uint32_t mcause) {
|
||||
if (mcause & 0x80000000) {
|
||||
switch (mcause & 0x7FFFFFFF) {
|
||||
case 1:
|
||||
return exception_causes[1];
|
||||
case 3:
|
||||
return exception_causes[2];
|
||||
case 5:
|
||||
return exception_causes[3];
|
||||
case 7:
|
||||
return exception_causes[4];
|
||||
case 9:
|
||||
return exception_causes[5];
|
||||
case 11:
|
||||
return exception_causes[6];
|
||||
default:
|
||||
return (mcause >= 16) ?
|
||||
exception_causes[7] :
|
||||
exception_causes[0];
|
||||
}
|
||||
}
|
||||
|
||||
switch (mcause) {
|
||||
case 0:
|
||||
return exception_causes[8];
|
||||
case 1:
|
||||
return exception_causes[9];
|
||||
case 2:
|
||||
return exception_causes[10];
|
||||
case 3:
|
||||
return exception_causes[11];
|
||||
case 4:
|
||||
return exception_causes[12];
|
||||
case 5:
|
||||
return exception_causes[13];
|
||||
case 6:
|
||||
return exception_causes[14];
|
||||
case 7:
|
||||
return exception_causes[15];
|
||||
case 8:
|
||||
return exception_causes[16];
|
||||
case 9:
|
||||
return exception_causes[17];
|
||||
case 11:
|
||||
return exception_causes[18];
|
||||
case 12:
|
||||
return exception_causes[19];
|
||||
case 13:
|
||||
return exception_causes[20];
|
||||
case 15:
|
||||
return exception_causes[21];
|
||||
default: {
|
||||
if ((mcause >= 24 && mcause <= 31) ||
|
||||
(mcause >= 48 && mcause <= 63)) {
|
||||
return exception_causes[22];
|
||||
}
|
||||
|
||||
return exception_causes[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("align-functions=4")
|
||||
|
||||
__attribute__((interrupt("machine"), weak)) void mtvec_nop(void) {
|
||||
}
|
||||
|
||||
__attribute__((interrupt("machine"), weak)) void mtvec_exception(void) {
|
||||
__asm volatile (
|
||||
"csrrw x31, mscratch, x31 \n" // Save X31
|
||||
"la x31, registers_copy \n" // Load target address
|
||||
"sw x1, 0(x31) \n" // Save X1
|
||||
"sw x2, 4(x31) \n" // Save X2
|
||||
"sw x3, 8(x31) \n" // Save X3
|
||||
"sw x4, 12(x31) \n" // Save X4
|
||||
"sw x5, 16(x31) \n" // Save X5
|
||||
"sw x6, 20(x31) \n" // Save X6
|
||||
"sw x7, 24(x31) \n" // Save X7
|
||||
"sw x8, 28(x31) \n" // Save X8
|
||||
"sw x9, 32(x31) \n" // Save X9
|
||||
"sw x10, 36(x31) \n" // Save X10
|
||||
"sw x11, 40(x31) \n" // Save X11
|
||||
"sw x12, 44(x31) \n" // Save X12
|
||||
"sw x13, 48(x31) \n" // Save X13
|
||||
"sw x14, 52(x31) \n" // Save X14
|
||||
"sw x15, 56(x31) \n" // Save X15
|
||||
"sw x16, 60(x31) \n" // Save X16
|
||||
"sw x17, 64(x31) \n" // Save X17
|
||||
"sw x18, 68(x31) \n" // Save X18
|
||||
"sw x19, 72(x31) \n" // Save X19
|
||||
"sw x20, 76(x31) \n" // Save X20
|
||||
"sw x21, 80(x31) \n" // Save X21
|
||||
"sw x22, 84(x31) \n" // Save X22
|
||||
"sw x23, 88(x31) \n" // Save X23
|
||||
"sw x24, 92(x31) \n" // Save X24
|
||||
"sw x25, 98(x31) \n" // Save X25
|
||||
"sw x26, 100(x31) \n" // Save X26
|
||||
"sw x27, 104(x31) \n" // Save X27
|
||||
"sw x28, 108(x31) \n" // Save X28
|
||||
"sw x29, 112(x31) \n" // Save X29
|
||||
"sw x30, 116(x31) \n" // Save X30
|
||||
"csrr x30, mscratch \n" // Restore X31
|
||||
"sw x30, 120(x31) \n" // Save X31
|
||||
"csrr x30, mepc \n" // Load MEPC
|
||||
"sw x30, 124(x31) \n" // Save MEPC
|
||||
"csrr x30, mcause \n" // Load MCAUSE
|
||||
"sw x30, 128(x31) \n" // Save MCAUSE
|
||||
"csrr x30, mtval \n" // Load MTVAL
|
||||
"sw x30, 132(x31) \n" // Save MTVAL
|
||||
"csrr x30, mstatus \n" // Load MSTATUS
|
||||
"sw x30, 138(x31) \n" // Save MSTATUS
|
||||
"lw x30, 116(x31) \n" // Restore X30
|
||||
"lw x31, 120(x31) \n" // Restore X31
|
||||
:
|
||||
:
|
||||
: "memory"
|
||||
);
|
||||
|
||||
printf("\nMACHINE EXCEPTION CAUGHT:\n\n");
|
||||
|
||||
printf(" RA=%08lX SP=%08lX GP=%08lX TP=%08lX T0=%08lX T1=%08lX\n",
|
||||
registers_copy[0], registers_copy[1], registers_copy[2],
|
||||
registers_copy[3], registers_copy[4], registers_copy[5]);
|
||||
printf(" T2=%08lX S0=%08lX S1=%08lX A0=%08lX A1=%08lX A2=%08lX\n",
|
||||
registers_copy[6], registers_copy[7], registers_copy[8],
|
||||
registers_copy[9], registers_copy[10], registers_copy[11]);
|
||||
printf(" A3=%08lX A4=%08lX A5=%08lX A6=%08lX A7=%08lX S2=%08lX\n",
|
||||
registers_copy[12], registers_copy[13], registers_copy[14],
|
||||
registers_copy[15], registers_copy[16], registers_copy[17]);
|
||||
printf(" S3=%08lX S4=%08lX S5=%08lX S6=%08lX S7=%08lX S8=%08lX\n",
|
||||
registers_copy[18], registers_copy[19], registers_copy[20],
|
||||
registers_copy[21], registers_copy[22], registers_copy[23]);
|
||||
printf(" S9=%08lX S10=%08lX S11=%08lX T3=%08lX T4=%08lX T5=%08lX\n",
|
||||
registers_copy[24], registers_copy[25], registers_copy[26],
|
||||
registers_copy[27], registers_copy[28], registers_copy[29]);
|
||||
printf(" T6=%08lX\n\n", registers_copy[30]);
|
||||
|
||||
printf(" MEPC=%08lX MTVAL=%08lX MSTATUS=%08lx MCAUSE=%08lx (%s)\n",
|
||||
registers_copy[31], registers_copy[33], registers_copy[34],
|
||||
registers_copy[32], lookup_cause(registers_copy[32]));
|
||||
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
||||
|
||||
void set_interrupt_table(void) {
|
||||
__asm volatile (
|
||||
"csrrci s0, mstatus, 8 \n" // S0 = MSTATUS & ~MIE
|
||||
"csrw mstatus, s0 \n" // Global machine interrupts are disabled
|
||||
"csrw mie, zero \n" // Disable machine interrupts
|
||||
"csrw mip, zero \n" // Clear pending machine interrupts
|
||||
"addi s0, %0, 1 \n" // Vectored machine interrupts enabled
|
||||
"csrw mtvec, s0 \n" // Set new machine vector table
|
||||
"csrrsi s0, mstatus, 8 \n" // S0 = MSTATUS | MIE
|
||||
"csrw mstatus, s0 \n" // Global machine interrupts are enabled
|
||||
:
|
||||
: "r" (mtvec_table)
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
76
ports/qemu-riscv/mpconfigport.h
Normal file
76
ports/qemu-riscv/mpconfigport.h
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2024 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// options to control how MicroPython is built
|
||||
|
||||
#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES)
|
||||
|
||||
#define MICROPY_MALLOC_USES_ALLOCATED_SIZE (1)
|
||||
#define MICROPY_MEM_STATS (1)
|
||||
#define MICROPY_ENABLE_GC (1)
|
||||
#define MICROPY_KBD_EXCEPTION (0)
|
||||
#define MICROPY_HELPER_REPL (0)
|
||||
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
|
||||
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
|
||||
#define MICROPY_WARNINGS (1)
|
||||
#define MICROPY_PY_BUILTINS_INPUT (0)
|
||||
#define MICROPY_PY_BUILTINS_HELP (0)
|
||||
#define MICROPY_PY_IO_IOBASE (0)
|
||||
#define MICROPY_PY_SYS_PLATFORM "qemu-riscv32"
|
||||
#define MICROPY_PY_SYS_STDFILES (0)
|
||||
#define MICROPY_PY_SYS_STDIO_BUFFER (0)
|
||||
#define MICROPY_PY_SELECT (0)
|
||||
#define MICROPY_PY_TIME (0)
|
||||
#define MICROPY_PY_ASYNCIO (0)
|
||||
#define MICROPY_PY_MACHINE (1)
|
||||
#define MICROPY_PY_MACHINE_INCLUDEFILE "ports/qemu-arm/modmachine.c"
|
||||
#define MICROPY_PY_MACHINE_PIN_BASE (1)
|
||||
#define MICROPY_VFS (1)
|
||||
|
||||
// type definitions for the specific machine
|
||||
|
||||
#define MP_SSIZE_MAX (0x7fffffff)
|
||||
|
||||
#define UINT_FMT "%lu"
|
||||
#define INT_FMT "%ld"
|
||||
|
||||
typedef int32_t mp_int_t; // must be pointer size
|
||||
typedef uint32_t mp_uint_t; // must be pointer size
|
||||
typedef long mp_off_t;
|
||||
|
||||
// We need an implementation of the log2 function which is not a macro.
|
||||
#define MP_NEED_LOG2 (1)
|
||||
|
||||
// We need to provide a declaration/definition of alloca()
|
||||
#include <alloca.h>
|
||||
|
||||
#ifdef TEST
|
||||
#include "shared/upytesthelper/upytesthelper.h"
|
||||
#undef MP_PLAT_PRINT_STRN
|
||||
#define MP_PLAT_PRINT_STRN(str, len) upytest_output(str, len)
|
||||
#endif
|
||||
32
ports/qemu-riscv/mphalport.h
Normal file
32
ports/qemu-riscv/mphalport.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016-2018 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "uart.h"
|
||||
|
||||
#define mp_hal_stdin_rx_chr() (0)
|
||||
#define mp_hal_stdout_tx_strn_cooked(s, l) uart_tx_strn((s), (l))
|
||||
2
ports/qemu-riscv/qstrdefsport.h
Normal file
2
ports/qemu-riscv/qstrdefsport.h
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
// qstrs specific to this port
|
||||
// *FORMAT-OFF*
|
||||
86
ports/qemu-riscv/startup.c
Normal file
86
ports/qemu-riscv/startup.c
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2023 Alessandro Gatti
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "uart.h"
|
||||
|
||||
extern void set_interrupt_table(void);
|
||||
extern int main(int argc, char **argv);
|
||||
|
||||
void _entry_point(void) {
|
||||
// Set interrupt table
|
||||
set_interrupt_table();
|
||||
// Enable UART
|
||||
uart_init();
|
||||
// Now that we have a basic system up and running we can call main
|
||||
main(0, 0);
|
||||
// Finished
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void exit(int status) {
|
||||
uint32_t semihosting_arguments[2] = { 0 };
|
||||
|
||||
// Exit via QEMU's RISC-V semihosting support.
|
||||
__asm volatile (
|
||||
".option push \n" // Transient options
|
||||
".option norvc \n" // Do not emit compressed instructions
|
||||
".align 4 \n" // 16 bytes alignment
|
||||
"mv a1, %0 \n" // Load buffer
|
||||
"li t0, 0x20026 \n" // ADP_Stopped_ApplicationExit
|
||||
"sw t0, 0(a1) \n" // ADP_Stopped_ApplicationExit
|
||||
"sw %1, 4(a1) \n" // Exit code
|
||||
"addi a0, zero, 0x20 \n" // TARGET_SYS_EXIT_EXTENDED
|
||||
"slli zero, zero, 0x1F \n" // Entry NOP
|
||||
"ebreak \n" // Give control to the debugger
|
||||
"srai zero, zero, 7 \n" // Semihosting call
|
||||
".option pop \n" // Restore previous options set
|
||||
:
|
||||
: "r" (semihosting_arguments), "r" (status)
|
||||
: "memory"
|
||||
);
|
||||
|
||||
// Should never reach here.
|
||||
for (;;) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void __assert_func(const char *file, int line, const char *func, const char *expr) {
|
||||
(void)func;
|
||||
printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Picolibc requires `stdout` to be explicitly defined.
|
||||
|
||||
#ifdef _PICOLIBC__
|
||||
FILE *const stdout;
|
||||
#endif
|
||||
66
ports/qemu-riscv/test_main.c
Normal file
66
ports/qemu-riscv/test_main.c
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014 Ilya Dmitrichenko
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "py/compile.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/stackctrl.h"
|
||||
#include "py/gc.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "shared/runtime/gchelper.h"
|
||||
#include "lib/tinytest/tinytest.h"
|
||||
#include "lib/tinytest/tinytest_macros.h"
|
||||
|
||||
#define HEAP_SIZE (200 * 1024)
|
||||
|
||||
#include "genhdr/tests.h"
|
||||
|
||||
int main() {
|
||||
mp_stack_ctrl_init();
|
||||
mp_stack_set_limit(10240);
|
||||
static uint32_t heap[HEAP_SIZE / sizeof(uint32_t)];
|
||||
upytest_set_heap(heap, (char *)heap + HEAP_SIZE);
|
||||
int r = tinytest_main(0, NULL, groups);
|
||||
printf("status: %d\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
void gc_collect(void) {
|
||||
gc_collect_start();
|
||||
gc_helper_collect_regs_and_stack();
|
||||
gc_collect_end();
|
||||
}
|
||||
|
||||
mp_lexer_t *mp_lexer_new_from_file(qstr filename) {
|
||||
mp_raise_OSError(MP_ENOENT);
|
||||
}
|
||||
|
||||
void nlr_jump_fail(void *val) {
|
||||
printf("uncaught NLR\n");
|
||||
exit(1);
|
||||
}
|
||||
53
ports/qemu-riscv/tests_profile.txt
Normal file
53
ports/qemu-riscv/tests_profile.txt
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# Port-specific tests exclusion list.
|
||||
|
||||
exclude_tests = exclude_tests.union(
|
||||
(
|
||||
# Native code generation is not yet supported.
|
||||
"micropython/native_closure.py",
|
||||
"micropython/native_const.py",
|
||||
"micropython/native_const_intbig.py",
|
||||
"micropython/native_for.py",
|
||||
"micropython/native_fun_attrs.py",
|
||||
"micropython/native_gen.py",
|
||||
"micropython/native_misc.py",
|
||||
"micropython/native_try.py",
|
||||
"micropython/native_try_deep.py",
|
||||
"micropython/native_while.py",
|
||||
"micropython/native_with.py",
|
||||
|
||||
# Viper code generator is not yet supported.
|
||||
"micropython/viper_addr.py",
|
||||
"micropython/viper_args.py",
|
||||
"micropython/viper_binop_arith.py",
|
||||
"micropython/viper_binop_arith_uint.py",
|
||||
"micropython/viper_binop_bitwise_uint.py",
|
||||
"micropython/viper_binop_comp.py",
|
||||
"micropython/viper_binop_comp_imm.py",
|
||||
"micropython/viper_binop_comp_uint.py",
|
||||
"micropython/viper_binop_divmod.py",
|
||||
"micropython/viper_binop_multi_comp.py",
|
||||
"micropython/viper_cond.py",
|
||||
"micropython/viper_const.py",
|
||||
"micropython/viper_const_intbig.py",
|
||||
"micropython/viper_error.py",
|
||||
"micropython/viper_globals.py",
|
||||
"micropython/viper_import.py",
|
||||
"micropython/viper_misc.py",
|
||||
"micropython/viper_misc2.py",
|
||||
"micropython/viper_misc3.py",
|
||||
"micropython/viper_misc_intbig.py",
|
||||
"micropython/viper_ptr16_load.py",
|
||||
"micropython/viper_ptr16_store.py",
|
||||
"micropython/viper_ptr32_load.py",
|
||||
"micropython/viper_ptr32_store.py",
|
||||
"micropython/viper_ptr8_load.py",
|
||||
"micropython/viper_ptr8_store.py",
|
||||
"micropython/viper_storeattr.py",
|
||||
"micropython/viper_subscr.py",
|
||||
"micropython/viper_subscr_multi.py",
|
||||
"micropython/viper_try.py",
|
||||
"micropython/viper_types.py",
|
||||
"micropython/viper_unop.py",
|
||||
"micropython/viper_with.py",
|
||||
)
|
||||
)
|
||||
45
ports/qemu-riscv/uart.c
Normal file
45
ports/qemu-riscv/uart.c
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2023 Alessandro Gatti
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "uart.h"
|
||||
|
||||
#if defined(QEMU_SOC_VIRT)
|
||||
|
||||
volatile unsigned char *uart_buffer = (volatile unsigned char *)0x10000000;
|
||||
|
||||
void uart_init(void) {
|
||||
}
|
||||
|
||||
void uart_tx_strn(const char *buffer, size_t length) {
|
||||
for (size_t index = 0; index < length; index++) {
|
||||
*uart_buffer = buffer[index];
|
||||
}
|
||||
}
|
||||
|
||||
#endif // QEMU_SOC_VIRT
|
||||
33
ports/qemu-riscv/uart.h
Normal file
33
ports/qemu-riscv/uart.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MICROPY_INCLUDED_QEMU_RISCV_UART_H
|
||||
#define MICROPY_INCLUDED_QEMU_RISCV_UART_H
|
||||
|
||||
void uart_init(void);
|
||||
void uart_tx_strn(const char *buf, size_t len);
|
||||
|
||||
#endif // MICROPY_INCLUDED_QEMU_RISCV_UART_H
|
||||
98
ports/qemu-riscv/virt.ld
Normal file
98
ports/qemu-riscv/virt.ld
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2023 Alessandro Gatti
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Output format is 32 bits little endian. */
|
||||
OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv", "elf32-littleriscv");
|
||||
|
||||
/*
|
||||
* Memory layout:
|
||||
*
|
||||
* 0x8000_0000: .text
|
||||
* .........: .rodata
|
||||
* 0x8040_0000: .data
|
||||
* .........: _global_pointer
|
||||
* .........: .bss
|
||||
* 0x8060_0000: .stack
|
||||
* 0x8060_0000: _sstack
|
||||
* 0x8060_FFFF: _estack
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
ROM (xr) : ORIGIN = 0x80000000, LENGTH = 4M
|
||||
RAM (xrw) : ORIGIN = ORIGIN(ROM) + LENGTH(ROM), LENGTH = 2M
|
||||
STACK (rw) : ORIGIN = ORIGIN(RAM) + LENGTH(RAM), LENGTH = 64K
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* Code + Read-Only data segment */
|
||||
|
||||
.text : ALIGN (4K)
|
||||
{
|
||||
*(.start)
|
||||
*(.text)
|
||||
. = ALIGN (4K);
|
||||
*(.rodata)
|
||||
_sirodata = .;
|
||||
} > ROM
|
||||
|
||||
.rodata : AT (_sirodata) ALIGN (4K)
|
||||
{
|
||||
*(.rodata)
|
||||
} > ROM
|
||||
|
||||
/* Data + BSS segment */
|
||||
|
||||
.data : ALIGN (4K)
|
||||
{
|
||||
*(.data)
|
||||
_sibss = .;
|
||||
} > RAM
|
||||
|
||||
.bss : AT (_sibss) ALIGN (4K)
|
||||
{
|
||||
/* Mark global pointer address. */
|
||||
_global_pointer = .;
|
||||
|
||||
/* Mark BSS start. */
|
||||
. = . + 4;
|
||||
_sbss = .;
|
||||
*(.bss)
|
||||
/* Mark BSS end. */
|
||||
_ebss = .;
|
||||
} > RAM
|
||||
|
||||
/* Isolated stack segment. */
|
||||
|
||||
.stack : ALIGN(4K)
|
||||
{
|
||||
/* Mark stack start. */
|
||||
_sstack = .;
|
||||
. = LENGTH(STACK);
|
||||
/* Mark stack end. */
|
||||
_estack = .;
|
||||
} > STACK
|
||||
}
|
||||
|
|
@ -678,6 +678,8 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1):
|
|||
) # RA fsp rtc function doesn't support nano sec info
|
||||
elif args.target == "qemu-arm":
|
||||
skip_tests.add("misc/print_exception.py") # requires sys stdfiles
|
||||
elif args.target == "qemu-riscv":
|
||||
skip_tests.add("misc/print_exception.py") # requires sys stdfiles
|
||||
elif args.target == "webassembly":
|
||||
skip_tests.add("basics/string_format_modulo.py") # can't print nulls to stdout
|
||||
skip_tests.add("basics/string_strip.py") # can't print nulls to stdout
|
||||
|
|
@ -1048,6 +1050,7 @@ the last matching regex is used:
|
|||
LOCAL_TARGETS = (
|
||||
"unix",
|
||||
"qemu-arm",
|
||||
"qemu-riscv",
|
||||
"webassembly",
|
||||
)
|
||||
EXTERNAL_TARGETS = (
|
||||
|
|
@ -1151,6 +1154,12 @@ the last matching regex is used:
|
|||
"inlineasm",
|
||||
"ports/qemu-arm",
|
||||
)
|
||||
elif args.target == "qemu-riscv":
|
||||
if not args.write_exp:
|
||||
raise ValueError("--target=qemu-riscv must be used with --write-exp")
|
||||
# Generate expected output files for qemu run.
|
||||
# This list should match the test_dirs tuple in tinytest-codegen.py.
|
||||
test_dirs += ("float",)
|
||||
elif args.target == "webassembly":
|
||||
test_dirs += ("float", "ports/webassembly")
|
||||
else:
|
||||
|
|
|
|||
Loading…
Reference in a new issue