WebAssembly Micro Runtimeお試し①

はじめに

少し前に、組込みで使えるWebAssembly Micro Runtimeが公開されました。 また、いつの間にかSTMでのデモアプリが公開されています。

github.com

リファレンスが普段触っているZephyrなので、少し動かしてみます。

準備

ライブラリをインストールします。

sudo apt install lib32gcc-5-dev g++-multilib

ソースコードをビルドします。

git clone https://github.com/intel/wasm-micro-runtime.git
cd wasm-micro-runtime/core/iwasm/products/linux/
cmake
make

iwasmというバイナリができました。

$ ls
CMakeCache.txt  cmake_install.cmake  libiwasm.so  Makefile
CMakeFiles      iwasm                libvmlib.a

Zephyrで起動してみましょう。

cd core/iwasm/products/zephyr/simple
source <zephyr>/zephyr-env.sh
ln -s ../../../ iwasm
ln -s ../../../../shared-lib shared-lib
mkdir build && cd $_
cmake -GNinja -DBOARD=qemu_x86 ..

<iwasm_dir>core/iwasmディレクトリです。 <shared_lib_dir>wasm-micro-runtime/core/shared-libディレクトリです。

実行します。

$ ninja run
SeaBIOS (version rel-1.12.0-0-ga698c8995f-prebuilt.qemu.org)
Booting from ROM..***** Booting Zephyr OS zephyr-v1.14.0 *****
Hello world!
buf ptr: 0x40000180
buf: 1234

動くやん!お手軽ですねー。

次に、試しにqemu_cortex_m3にターゲットを移してみましょう。

$ cmake -GNinja -DBOARD=qemu_cortex_m3 ..
$ ninja run
Memory region         Used Size  Region Size  %age Used
           FLASH:       69112 B       256 KB     26.36%
            SRAM:      535984 B        64 KB    817.85%
        IDT_LIST:         120 B         2 KB      5.86/opt/zephyr-sdk/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/8.3.0/../../../../arm-zephyr-eabi/bin/ld: zephyr/zephyr_prebuilt.elf section `bss' will not fit in region `SRAM'
/opt/zephyr-sdk/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/8.3.0/../../../../arm-zephyr-eabi/bin/ld: section .intList VMA [0000000020010000,0000000020010077] overlaps section bss VMA [0000000020000000,0000000020080354]
/opt/zephyr-sdk/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/8.3.0/../../../../arm-zephyr-eabi/bin/ld: region `SRAM' overflowed by 470448 bytes
collect2: error: ld returned 1 exit status
%
ninja: build stopped: subcommand failed.

SRAMのサイズが足りずにリンクで死んだ!!! なんでしょうこのSRAM使用量…。500KB超えてますが…。

STMのデモ

じゃあSTMで動いているデモは一体何なのでしょうか? ということで、デモアプリのREADMEを読んでみます。

|> wasm-micro-runtime/samples/littlevgl/README.md

Since ui_app incorporated LittlevGL source code, so it needs more RAM on the device to install the application. It is recommended that RAM SIZE greater than 512KB.

512KB以上のRAMが推奨環境! かなり高性能なマイコンを要求していますね…。

デモで使用しているマイコンNUCLEO-F767ZIという512KB RAMを搭載しているものですね…。

os.mbed.com

simpleデモアプリのソースコードを見る

希望を捨てずに、デモアプリで何をしているか、少し覗いてみましょう。 アプリで使うRAMサイズが減れば、動くかもしれないですし!

|> wasm-micro-runtime/core/iwasm/products/zephyr/simple/src/main.c

static char global_heap_buf[512 * 1024] = { 0 };

ん?きみぃ?何だいこの有無を言わさず512KB確保するstatic変数の定義は!

static char global_heap_buf[16 * 1024] = { 0 };

とりあえず、16KBくらいにしたろ。

$ ninja run
[0/1] To exit from QEMU enter: 'CTRL+a, x'[QEMU] CPU: cortex-m3
qemu-system-arm: warning: nic stellaris_enet.0 has no peer
***** Booting Zephyr OS zephyr-v1.14.0 *****
Instantiate memory failed: allocate memory failed.

うん。QEMU起動まではいきましたが、ランタイムで落ちてます。

|> wasm-micro-runtime/core/iwasm/products/zephyr/simple/iwasm/runtime/vmcore-wasm/wasm_runtime.c

static WASMMemoryInstance*
memory_instantiate(uint32 init_page_count, uint32 max_page_count,
                   uint32 addr_data_size, uint32 global_data_size,
                   uint32 heap_size,
                   char *error_buf, uint32 error_buf_size)
{
    WASMMemoryInstance *memory;
    uint32 total_size = offsetof(WASMMemoryInstance, base_addr) +
                        NumBytesPerPage * init_page_count +
                        addr_data_size + global_data_size;

    /* Allocate memory space, addr data and global data */
    if (!(memory = wasm_malloc(total_size))) {
        set_error_buf(error_buf, error_buf_size,
                      "Instantiate memory failed: allocate memory failed.");
        return NULL;
    }

この辺りかな? 少しデバッガで見ていますが、サクッと解決できなさそうなので、また次回。