Surprisingly easy to hook up: micropython stdin connected to system getchar() in my testbench harness, boom, interactive Python prompt running on CXXRTL/Verilator Hazard3.
MicroPython is set up to run all of its tests and benchmarks on real embedded targets via UART, so I figure it should be possible to hook that up to stdin/stdout on my tb harness and use that as a source of regressions and benchmarks for hardware (and compiler) changes.
Worst case I end up using a TCP socket instead to avoid platform-specific stdio weirdness
I honestly think building the Pico 2 W MicroPython firmware is a much better embedded firmware size benchmark than Embench.
You've got the MP interpreter itself, the C parts of the standard Python libraries, multiple mbed-tls algorithms, tinyusb, lwip, btstack, pico-sdk hardware support, so on. It's a much larger and more diverse corpus, all in one binary.
That's the basics proven out -- test failures are a problem for future Luke
This test takes... a long time 😅
Also some of the tests do `import unittest` inside micropython to run subtests. So the test framework is running *inside* Verilator. Neat!
Went to test my GCC patches against the (now clean) MicroPython test suite. Findings:
* Two failures introduced by GCC 15.2 -> clean GCC 16.1
* No failures introduced by my patches on top of GCC 16.1
Both failures are related to some interaction between kwargs and exceptions. These yaks don't shave themselves
uhhh this is a straight up codegen bug? Maybe an IPA thing?
if (dest[0] != MP_OBJ_NULL) {
// __next__ exists, call it and return its result
return mp_call_method_n_kw(0, 0, dest);
@mei Yeah that's what I thought but it actually seems to survive all the way through the GIMPLE passes and get dropped in the backend. I think there's something funky going on with cm.popretz in the callee
Bisected to the RISC-V-specific popretz pass: the `li a0, 0` is absorbed into the cm.popretz at the **end of the function** even though it's a live value consumed by the earlier call.
Ok how do I file bugs on GCC 🤔
@palmer aha, already filed a couple of days ago: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126454
Fixed locally:
if (going_to_miscompile()) dont();
Good, that yak is thoroughly smooth and hairless now
Quick before/after: hashlib.sha256 (aka mbedtls) is ~3% faster with my Xh3bextm and Zbkb patches.
In this case it's almost entirely down to the Zbkb unaligned loads. Looks like Xh3bextm is used quite a bit in the AES, for extracting the second or third byte from a word.
AES is ~2.1% faster. Firmware is 800 bytes smaller (out of 320k). This is just my testbench MicroPython build, not the real RP2 one.
Anyway, nice to know it helps a bit, and doesn't seem to break anything.
@wren6991 hmm is this something we're likely to hit on our other RISC-V MicroPython boards if we update to 16.1, or is it specific to the extensions you're testing?
@projectgus I didn't check the RP2 port but in general, 16.1.0 + MicroPython + Zcmp = bad
Edit: thinking about it for more than 5 seconds: in SDK 2.3.0 there is an SDK bug that cancels this out (Zcmp feature detect is broken and it will fail to set Zcmp in `-march`).
That is fixed in https://github.com/raspberrypi/pico-sdk/commit/dcaf9c45fbd2cd9b1581d36ff93f0936381a646e so an SDK release that includes that (2.3.1) will be break MicroPython on GCC 16.1.0
Whether it affects other ports depends on whether they use Zcmp. A quick workaround is to set -fdisable-rtl-popretz to disable the offending pass without losing out on the rest of the Zcmp compression.