Commit Graph

243 Commits

Author SHA1 Message Date
Damien George
b3b9b11596 tools/pyboard.py: Support executing .mpy files directly.
This patch allows executing .mpy files (including native ones) directly on
a target, eg a board over a serial connection.  So there's no need to copy
the file to its filesystem to test it.

For example:

    $ mpy-cross foo.py
    $ pyboard.py foo.mpy
2019-12-19 17:00:52 +11:00
Damien George
0bd7d1f7f0 py/persistentcode: Move loading of rodata/bss to before obj/raw-code.
This makes the loading of viper-code-with-relocations a bit neater and
easier to understand, by treating the rodata/bss like a special object to
be loaded into the constant table (which is how it behaves).
2019-12-17 13:22:11 +11:00
Damien George
fc97d6d1b5 tools/mpy-tool.py: Raise exception if trying to freeze relocatable mpy. 2019-12-12 20:15:28 +11:00
Damien George
abc642973d py/dynruntime: Add support for float API to make/get floats.
We don't want to add a feature flag to .mpy files that indicate float
support because it will get complex and difficult to use.  Instead the .mpy
is built using whatever precision it chooses (float or double) and the
native glue API will convert between this choice and what the host runtime
actually uses.
2019-12-12 20:15:28 +11:00
Damien George
aad79adab7 tools/mpy_ld.py: Add new mpy_ld.py tool and associated build files.
This commit adds a new tool called mpy_ld.py which is essentially a linker
that builds .mpy files directly from .o files.  A new header file
(dynruntime.h) and makefile fragment (dynruntime.mk) are also included
which allow building .mpy files from C source code.  Such .mpy files can
then be dynamically imported as though they were a normal Python module,
even though they are implemented in C.

Converting .o files directly (rather than pre-linked .elf files) allows the
resulting .mpy to be more efficient because it has more control over the
relocations; for example it can skip PLT indirection.  Doing it this way
also allows supporting more architectures, such as Xtensa which has
specific needs for position-independent code and the GOT.

The tool supports targets of x86, x86-64, ARM Thumb and Xtensa (windowed
and non-windowed).  BSS, text and rodata sections are supported, with
relocations to all internal sections and symbols, as well as relocations to
some external symbols (defined by dynruntime.h), and linking of qstrs.
2019-12-12 20:15:28 +11:00
Damien George
27879844d2 tools/mpy-tool.py: Add ability to merge multiple .mpy files into one.
Usage:

    mpy-tool.py -o merged.mpy --merge mod1.mpy mod2.mpy

The constituent .mpy files are executed sequentially when the merged file
is imported, and they all use the same global namespace.
2019-12-12 20:15:28 +11:00
Damien George
360d972c16 py/nativeglue: Add new header file with native function table typedef. 2019-12-12 20:15:28 +11:00
Damien George
7f24c29778 tools/mpy-tool.py: Support qstr linking when freezing Xtensa native mpy. 2019-11-28 13:11:51 +11:00
Yonatan Goldschmidt
b2dd443d92 tools/makemanifest.py: Use sys.executable when invoking Python scripts.
So the version of Python used to run makemanifest.py is also used for the
sub-scripts.
2019-11-13 13:44:19 +11:00
Andrew Leech
d2e6cfd8fd tools/makemanifest.py: Skip freezing unsupported files with warning. 2019-11-07 12:34:57 +11:00
Mirko Vogt
2f71d66ef7 tools/makemanifest.py: Follow symlinks when freezing linked directories.
While the new manifest.py style got introduced for freezing python code
into the resulting binary, the old way - where files and modules within
ports/*/modules where baked into the resulting binary - was still
supported via `freeze('$(PORT_DIR)/modules')` within manifest.py.

However behaviour changed for symlinked directories (=modules), as those
links weren't followed anymore.

This commit restores the original behaviour by explicitly following
symlinks within a modules/ directory
2019-11-06 11:41:06 +11:00
Damien George
36c9be6f60 tools/mpy-tool.py: Use "@progbits #" attribute for native xtensa code. 2019-11-04 15:31:42 +11:00
Jim Mussared
8ba963cfa3 tools/makemanifest.py: Eval relative paths w.r.t. current manifest file.
When loading a manifest file, e.g. by include(), it will chdir first to the
directory of that manifest.  This means that all file operations within a
manifest are relative to that manifest's location.

As a consequence of this, additional environment variables are needed to
find absolute paths, so the following are added: $(MPY_LIB_DIR),
$(PORT_DIR), $(BOARD_DIR).  And rename $(MPY) to $(MPY_DIR) to be
consistent.

Existing manifests are updated to match.
2019-10-21 23:01:41 +11:00
Damien George
e81f538e25 tools: Add mechanism to provide a manifest of frozen files.
This introduces a new build variable FROZEN_MANIFEST which can be set to a
manifest listing (written in Python) that describes the set of files to be
frozen in to the firmware.
2019-10-15 21:34:23 +11:00
Damien George
8e8cfa6f53 tools/make-frozen.py: Allow to run with no directory passed in.
In which case it will just emit empty frozen C definitions.
2019-10-15 21:33:49 +11:00
Damien George
23f0691fdd py/persistentcode: Make .mpy more compact with qstr directly in prelude.
Instead of encoding 4 zero bytes as placeholders for the simple_name and
source_file qstrs, and storing the qstrs after the bytecode, store the
qstrs at the location of these 4 bytes.  This saves 4 bytes per bytecode
function stored in a .mpy file (for example lcd160cr.mpy drops by 232
bytes, 4x 58 functions).  And resulting code size is slightly reduced on
ports that use this feature.
2019-10-15 16:56:27 +11:00
Damien George
9adedce42e py: Add new Xtensa-Windowed arch for native emitter.
Enabled via the configuration MICROPY_EMIT_XTENSAWIN.
2019-10-05 13:44:53 +10:00
Damien George
c8c0fd4ca3 py: Rework and compress second part of bytecode prelude.
This patch compresses the second part of the bytecode prelude which
contains the source file name, function name, source-line-number mapping
and cell closure information.  This part of the prelude now begins with a
single varible length unsigned integer which encodes 2 numbers, being the
byte-size of the following 2 sections in the header: the "source info
section" and the "closure section".  After decoding this variable unsigned
integer it's possible to skip over one or both of these sections very
easily.

This scheme saves about 2 bytes for most functions compared to the original
format: one in the case that there are no closure cells, and one because
padding was eliminated.
2019-10-01 12:26:22 +10:00
Damien George
b5ebfadbd6 py: Compress first part of bytecode prelude.
The start of the bytecode prelude contains 6 numbers telling the amount of
stack needed for the Python values and exceptions, and the signature of the
function.  Prior to this patch these numbers were all encoded one after the
other (2x variable unsigned integers, then 4x bytes), but using so many
bytes is unnecessary.

An entropy analysis of around 150,000 bytecode functions from the CPython
standard library showed that the optimal Shannon coding would need about
7.1 bits on average to encode these 6 numbers, compared to the existing 48
bits.

This patch attempts to get close to this optimal value by packing the 6
numbers into a single, varible-length unsigned integer via bit-wise
interleaving.  The interleaving scheme is chosen to minimise the average
number of bytes needed, and at the same time keep the scheme simple enough
so it can be implemented without too much overhead in code size or speed.
The scheme requires about 10.5 bits on average to store the 6 numbers.

As a result most functions which originally took 6 bytes to encode these 6
numbers now need only 1 byte (in 80% of cases).
2019-10-01 12:26:22 +10:00
Damien George
5716c5cf65 py/persistentcode: Bump .mpy version to 5.
The bytecode opcodes have changed (there are more, and they have been
reordered).
2019-09-26 16:39:37 +10:00
Josh Lloyd
7d58a197cf py: Rename MP_QSTR_NULL to MP_QSTRnull to avoid intern collisions.
Fixes #5140.
2019-09-26 16:04:56 +10:00
Damien George
1f7202d122 py/bc: Replace big opcode format table with simple macro. 2019-09-26 15:27:11 +10:00
Damien George
5889cf58db py/bc0: Order opcodes into groups based on their size and format. 2019-09-26 15:27:10 +10:00
Damien George
c69f58e6b9 tools/mpy-tool.py: Fix freezing of non-bytecode funcs with settrace.
Only bytecode functions can be profiled at this stage.  Native functions
(eg inline assembler) may not even have a valid prelude.

Fixes issue #5075.
2019-09-06 23:55:15 +10:00
Damien George
b29fae0c56 py/bc: Fix size calculation of UNWIND_JUMP opcode in mp_opcode_format.
Prior to this patch mp_opcode_format would calculate the incorrect size of
the MP_BC_UNWIND_JUMP opcode, missing the additional byte.  But, because
opcodes below 0x10 are unused and treated as bytes in the .mpy load/save
and freezing code, this bug did not show any symptoms, since nested unwind
jumps would rarely (if ever) reach a depth of 16 (so the extra byte of this
opcode would be between 0x01 and 0x0f and be correctly loaded/saved/frozen
simply as an undefined opcode).

This patch fixes this bug by correctly accounting for the additional byte.
        .
2019-09-02 13:30:16 +10:00
Damien George
4691b43c8a tools/mpy-tool.py: Add initial support for frozen with settrace. 2019-08-30 16:49:13 +10:00
Milan Rossa
498e35219e tests: Add tests for sys.settrace feature. 2019-08-30 16:48:22 +10:00
Jim Mussared
0bd1eb80ff qemu-arm: Add testing of frozen native modules.
- Split 'qemu-arm' from 'unix' for generating tests.
- Add frozen module to the qemu-arm test build.
- Add test that reproduces the requirement to half-word align native
  function data.
2019-08-20 15:14:08 +10:00
Jim Mussared
4ab5156c01 tools/mpy-tool.py: Force native func alignment to halfword/word on ARM.
This is necessary for ARMV6 and V7.  Without this change, calling a frozen
native/viper function that is misaligned will crash.
2019-08-20 15:13:17 +10:00
Damien George
4d94fae833 tools/pyboard.py: Add filesystem commands to ls/cat/cp/rm remote files.
Use "-f" to select filesystem mode, followed by the command to execute.
Optionally put ":" at the start of a filename to indicate that it's on the
remote device, if it would otherwise be ambiguous.

Examples:

    $ pyboard.py -f ls
    $ pyboard.py -f cat main.py
    $ pyboard.py -f cp :main.py .   # get from device
    $ pyboard.py -f cp main.py :    # put to device
    $ pyboard.py -f rm main.py
2019-07-25 15:56:01 +10:00
Damien George
f073f2b543 tools: Add uf2conv.py from Microsoft/uf2 repository.
Repository https://github.com/Microsoft/uf2 commit
19615407727073e36d81bf239c52108ba92e7660
2019-07-01 17:18:44 +10:00
Jun Wu
b152bbddd1 py: Define EMIT_MACHINE_CODE as EMIT_NATIVE || EMIT_INLINE_ASM.
The combination MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_ASM is used in
many places, so define a new macro for it.
2019-06-28 13:54:45 +10:00
Damien George
9d3031cc9d tools/mpy-tool.py: Fix linking of qstr objects in native ARM Thumb code.
Previously, when linking qstr objects in native code for ARM Thumb, the
index into the machine code was being incremented by 4, not 8.  It should
be 8 to account for the size of the two machine instructions movw and movt.
This patch makes sure the index into the machine code is incremented by the
correct amount for all variations of qstr linking.

See issue #4829.
2019-06-11 11:36:39 +10:00
Damien George
faf3d3e9e9 tools/mpy-tool.py: Fix linking qstrs in native code, and multiple files.
Fixes errors in the tool when 1) linking qstrs in native ARM-M code; 2)
freezing multiple files some of which use native code and some which don't.

Fixes issue #4829.
2019-06-04 22:21:01 +10:00
Damien George
993ca572ca tools/upip.py: Add support for multiple index URLs with custom default.
The user can now select their own package index by either passing the "-i"
command line option, or setting the upip.index_urls variable (before doing
an install).

The https://micropython.org/pi package index hosts packages from
micropython-lib and will be searched first when installing a package.  If a
package is not found here then it will fallback to PyPI.
2019-05-15 15:46:16 +10:00
Damien George
56f6ceba7f tools/pyboard.py: Don't accumulate output data if data_consumer used.
Prior to this patch, when a lot of data was output by a running script
pyboard.py would try to capture all of this output into the "data"
variable, which would gradually slow down pyboard.py to the point where it
would have large CPU and memory usage (on the host) and potentially lose
data.

This patch fixes this problem by not accumulating the data in the case that
the data is not needed, which is when "data_consumer" is used.
2019-04-25 13:24:32 +10:00
Damien George
74ed06828f tools/mpy-tool.py: Fix init of QStrWindow, and remove unused variable.
The qstr window size is not log-2 encoded, it's just the actual number (but
in mpy-tool.py this didn't lead to an error because the size is just used
to truncate the window so it doesn't grow arbitrarily large in memory).

Addresses issue #4635.
2019-04-08 15:24:24 +10:00
Damien George
643d2a0e86 tools/mpy-tool.py: Adjust use of super() to make it work with Python 2.
Fixes the regression introduced in ea3c80a514
2019-04-08 11:21:18 +10:00
rhubarbdog
869a8b70ce tools/pyboard.py: Add missing line from example usage comments. 2019-03-26 16:52:41 +11:00
Andrew Leech
89ff506513 py: Update and rework build system for including external C modules.
How to use this feature is documented in docs/develop/cmodules.rst.
2019-03-08 22:58:42 +11:00
Ayke van Laethem
2e516074da py: Implement a module system for external, user C modules.
This system makes it a lot easier to include external libraries as static,
native modules in MicroPython.  Simply pass USER_C_MODULES (like
FROZEN_MPY_DIR) as a make parameter.
2019-03-08 22:49:00 +11:00
Damien George
6e11d86318 tools/upip.py: Use "raise arg" instead of no-arg raise form, for native. 2019-03-08 16:51:09 +11:00
Damien George
9a5f92ea72 py/persistentcode: Bump .mpy version to 4. 2019-03-08 15:53:05 +11:00
Damien George
ea3c80a514 tools/mpy-tool.py: Add support for freezing native code.
This adds support to freeze .mpy files that contain native code blocks.
2019-03-08 15:53:05 +11:00
Damien George
636ed0ff8d py/emitglue: Remove union in mp_raw_code_t to combine bytecode & native. 2019-03-08 15:53:04 +11:00
Damien George
4f0931b21f py/persistentcode: Define static qstr set to reduce size of mpy files.
When encoded in the mpy file, if qstr <= QSTR_LAST_STATIC then store two
bytes: 0, static_qstr_id.  Otherwise encode the qstr as usual (either with
string data or a reference into the qstr window).

Reduces mpy file size by about 5%.
2019-03-05 16:32:05 +11:00
Damien George
992a6e1dea py/persistentcode: Pack qstrs directly in bytecode to reduce mpy size.
Instead of emitting two bytes in the bytecode for where the linked qstr
should be written to, it is now replaced by the actual qstr data, or a
reference into the qstr window.

Reduces mpy file size by about 10%.
2019-03-05 16:27:34 +11:00
Damien George
5996eeb48f py/persistentcode: Add a qstr window to save mpy files more efficiently.
This is an implementation of a sliding qstr window used to reduce the
number of qstrs stored in a .mpy file.  The window size is configured to 32
entries which takes a fixed 64 bytes (16-bits each) on the C stack when
loading/saving a .mpy file.  It allows to remember the most recent 32 qstrs
so they don't need to be stored again in the .mpy file.  The qstr window
uses a simple least-recently-used mechanism to discard the least recently
used qstr when the window overflows (similar to dictionary compression).
This scheme only needs a single pass to save/load the .mpy file.

Reduces mpy file size by about 25% with a window size of 32.
2019-03-05 16:25:07 +11:00
Damien George
5a2599d962 py: Replace POP_BLOCK and POP_EXCEPT opcodes with POP_EXCEPT_JUMP.
POP_BLOCK and POP_EXCEPT are now the same, and are always followed by a
JUMP.  So this optimisation reduces code size, and RAM usage of bytecode by
two bytes for each try-except handler.
2019-03-05 16:09:58 +11:00
Dave Hylands
c932639063 tools/pydfu.py: Fix regression so tool runs under Python 2 again.
Under python3 (tested with 3.6.7) bytes with a list of integers as an
argument returns a different result than under python 2.7 (tested with
2.7.15rc1) which causes pydfu.py to fail when run under 2.7.  Changing
bytes to bytearray makes pydfu work properly under both Python 2.7 and
Python 3.6.
2018-12-30 01:20:48 +11:00