summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlessandro Gatti <a.gatti@frob.it>2025-09-23 22:52:44 +0200
committerAlessandro Gatti <a.gatti@frob.it>2025-10-24 18:30:55 +0200
commit64971f1a65aed54e6a1c041d069c2cb75f2dd64b (patch)
tree34c6b0b7db8424842b81a88681a565dc85768f67
parenta6bc1ccbe51e582d39c6bf7b484c75bfb662357b (diff)
py/persistentcode: Add architecture flags check for RV32 platforms.
This commit introduces the MPY architecture flags checking code specific for the RV32 target, currently checking for the only additional extension that is supported by the runtime: Zba. The warnings inside "mpy-cross" have also been removed since now there is a way to reject incompatible MPY files at runtime. Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
-rw-r--r--docs/reference/mpyfiles.rst15
-rw-r--r--mpy-cross/main.c12
-rw-r--r--py/asmrv32.h2
-rw-r--r--py/persistentcode.c19
4 files changed, 39 insertions, 9 deletions
diff --git a/docs/reference/mpyfiles.rst b/docs/reference/mpyfiles.rst
index b2d552d09..9687f5e46 100644
--- a/docs/reference/mpyfiles.rst
+++ b/docs/reference/mpyfiles.rst
@@ -179,8 +179,19 @@ If bit #6 of the header's feature flags byte is set, then a vuint containing
optional architecture-specific information will follow the header. The contents
of this integer depends on which native architecture the file is meant for.
-See also ``mpy-tool.py``'s ``-march-flags`` command-line option to set this
-value when creating MPY files.
+This is currently used to store which RISC-V processor extensions the MPY file
+needs to operate correctly besides I, M, C, and Zicsr. Different flavours of
+ArmV7 are identified by their native architecture number, but reusing that
+mechanism would complicate things for RV32 and RV64.
+
+MPY files targeting RV32 or RV64 that do not need any particular processor
+extensions do not need to provide a flags integer (along with setting the
+appropriate bit in the header). The lack of a flags value for RV32 and RV64
+MPY files is used to indicate that no specific extensions are needed, and saves
+one byte in the final output binary.
+
+See also the ``-march-flags`` command-line option in both ``mpy-tool.py`` and
+``mpy-cross`` to set this value when creating MPY files.
The global qstr and constant tables
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/mpy-cross/main.c b/mpy-cross/main.c
index 0415eb664..246390383 100644
--- a/mpy-cross/main.c
+++ b/mpy-cross/main.c
@@ -94,6 +94,12 @@ static int compile_and_save(const char *file, const char *output_file, const cha
mp_compiled_module_t cm;
cm.context = m_new_obj(mp_module_context_t);
cm.arch_flags = 0;
+ #if MICROPY_EMIT_NATIVE && MICROPY_EMIT_RV32
+ if (mp_dynamic_compiler.native_arch == MP_NATIVE_ARCH_RV32IMC && mp_dynamic_compiler.backend_options != NULL) {
+ cm.arch_flags = ((asm_rv32_backend_options_t *)mp_dynamic_compiler.backend_options)->allowed_extensions;
+ }
+ #endif
+
mp_compile_to_raw_code(&parse_tree, source_name, false, &cm);
if ((output_file != NULL && strcmp(output_file, "-") == 0) ||
@@ -138,7 +144,7 @@ static int usage(char **argv) {
"-march=<arch> : set architecture for native emitter;\n"
" x86, x64, armv6, armv6m, armv7m, armv7em, armv7emsp,\n"
" armv7emdp, xtensa, xtensawin, rv32imc, rv64imc, host, debug\n"
- "-march-flags=<flags> : set architecture-specific flags (OUTPUT FILE MAY NOT WORK ON ALL TARGETS!)\n"
+ "-march-flags=<flags> : set architecture-specific flags\n"
" supported flags for rv32imc: zba\n"
"\n"
"Implementation specific options:\n", argv[0]
@@ -382,10 +388,6 @@ MP_NOINLINE int main_(int argc, char **argv) {
mp_printf(&mp_stderr_print, "unrecognised arch flags\n");
exit(1);
}
- mp_printf(&mp_stderr_print,
- "WARNING: Using architecture-specific flags may create a MPY file whose code won't run on all targets!\n"
- " Currently there are no checks in the module file loader for whether the chosen flags used to\n"
- " build the MPY file are compatible with the running target.\n\n");
}
#if MICROPY_EMIT_NATIVE
diff --git a/py/asmrv32.h b/py/asmrv32.h
index 27a08cf9f..4456e6119 100644
--- a/py/asmrv32.h
+++ b/py/asmrv32.h
@@ -125,6 +125,8 @@ typedef struct _asm_rv32_t {
enum {
RV32_EXT_NONE = 0,
RV32_EXT_ZBA = 1 << 0,
+
+ RV32_EXT_ALL = RV32_EXT_ZBA
};
typedef struct _asm_rv32_backend_options_t {
diff --git a/py/persistentcode.c b/py/persistentcode.c
index 7d71cfd98..b12c10074 100644
--- a/py/persistentcode.c
+++ b/py/persistentcode.c
@@ -63,6 +63,10 @@ typedef struct _bytecode_prelude_t {
uint code_info_size;
} bytecode_prelude_t;
+#if MICROPY_EMIT_RV32
+#include "py/asmrv32.h"
+#endif
+
#endif // MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE
#if MICROPY_PERSISTENT_CODE_LOAD
@@ -485,8 +489,19 @@ void mp_raw_code_load(mp_reader_t *reader, mp_compiled_module_t *cm) {
size_t arch_flags = 0;
if (MPY_FEATURE_ARCH_FLAGS_TEST(header[2])) {
- (void)arch_flags;
- mp_raise_ValueError(MP_ERROR_TEXT("incompatible .mpy file"));
+ #if MICROPY_EMIT_RV32
+ arch_flags = read_uint(reader);
+
+ if (MPY_FEATURE_ARCH_TEST(MP_NATIVE_ARCH_RV32IMC)) {
+ if ((arch_flags & (size_t)asm_rv32_allowed_extensions()) != arch_flags) {
+ mp_raise_ValueError(MP_ERROR_TEXT("incompatible .mpy file"));
+ }
+ } else
+ #endif
+ {
+ (void)arch_flags;
+ mp_raise_ValueError(MP_ERROR_TEXT("incompatible .mpy file"));
+ }
}
size_t n_qstr = read_uint(reader);