Code Monkey home page Code Monkey logo

topllab / warduino Goto Github PK

View Code? Open in Web Editor NEW
79.0 79.0 7.0 10.04 MB

📟 A dynamic WebAssembly VM for embedded systems

Home Page: https://topllab.github.io/WARDuino/

License: Mozilla Public License 2.0

CMake 1.86% C++ 77.69% Shell 0.65% Python 0.46% Makefile 0.99% JavaScript 0.71% C 3.42% TypeScript 9.16% WebAssembly 2.22% Rust 2.86%
arduino debugger debugging-tool embedded esp32 espressif interpreter iot runtime wasm webassembly webassembly-runtime zephyr

warduino's People

Contributors

a-andreyev avatar beardhatcode avatar carllocos avatar chscholl avatar dependabot[bot] avatar maartens11 avatar tolauwae avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

warduino's Issues

Add SIMD

Add WebAssembly SIMD instructions proposal: https://github.com/WebAssembly/simd/blob/main/proposals/simd/SIMD.md

Overview of new opcodes: https://github.com/WebAssembly/simd/blob/main/proposals/simd/NewOpcodes.md

Full list of current opcodes: https://webassembly.github.io/spec/core/appendix/index-instructions.html?highlight=opcode


Spectests that fail because of this missing proposal:

  • block.wast
  • simd_address.wast
  • simd_bit_shift.wast
  • simd_bitwise.wast
  • simd_boolean.wast
  • simd_conversions.wast
  • simd_f32x4_arith.wast
  • simd_f32x4.wast
  • simd_f32x4_cmp.wast
  • simd_f32x4_pmin_pmax.wast
  • simd_f32x4_rounding.wast
  • simd_f64x2_arith.wast
  • simd_f64x2.wast
  • simd_f64x2_cmp.wast
  • simd_f64x2_pmin_pmax.wast
  • simd_f64x2_rounding.wast
  • simd_i16x8_arith2.wast
  • simd_i16x8_arith.wast
  • simd_i16x8_cmp.wast
  • simd_i16x8_extadd_pairwise_i8x16.wast
  • simd_i16x8_extmul_i8x16.wast
  • simd_i16x8_q15mulr_sat_s.wast
  • simd_i16x8_sat_arith.wast
  • simd_i32x4_arith2.wast
  • simd_i32x4_arith.wast
  • simd_i32x4_cmp.wast
  • simd_i32x4_dot_i16x8.wast
  • simd_i32x4_extadd_pairwise_i16x8.wast
  • simd_i32x4_extmul_i16x8.wast
  • simd_i32x4_trunc_sat_f32x4.wast
  • simd_i32x4_trunc_sat_f64x2.wast
  • simd_i64x2_arith2.wast
  • simd_i64x2_arith.wast
  • simd_i64x2_cmp.wast
  • simd_i64x2_extmul_i32x4.wast
  • simd_i8x16_arith2.wast
  • simd_i8x16_arith.wast
  • simd_i8x16_cmp.wast
  • simd_i8x16_sat_arith.wast
  • simd_int_to_int_extend.wast
  • simd_lane.wast
  • simd_load16_lane.wast
  • simd_load32_lane.wast
  • simd_load64_lane.wast
  • simd_load8_lane.wast
  • simd_load.wast
  • simd_load_extend.wast
  • simd_load_splat.wast
  • simd_load_zero.wast
  • simd_splat.wast
  • simd_store16_lane.wast
  • simd_store32_lane.wast
  • simd_store64_lane.wast
  • simd_store8_lane.wast
  • simd_store.wast

MQTT unsubscribe should only unsubscribe if no more callbacks exist

The MQTT unsubscribe function removes the callback from the callback list, but there may be multiple callbacks for the same topic. As long as there are callbacks left, the subscription should remain.

def_prim(mqtt_unsubscribe, threeToOneU32) {
uint32_t topic_param = arg2.uint32;
uint32_t topic_length = arg1.uint32;
uint32_t fidx = arg0.uint32;
const char *topic =
parse_utf8_string(m->memory.bytes, topic_length, topic_param).c_str();
Callback c = Callback(m, topic, fidx);
CallbackHandler::remove_callback(c);
bool ret = mqttClient.unsubscribe(topic);
#if DEBUG
Serial.print("Unsubscribed to ");
Serial.println(topic);
Serial.flush();
#endif
pop_args(2);
pushInt32((int)ret);
return true;
}

Note: I did not test this and could be entirely wrong, to me the code seems to not handle this case correctly

Fix watchdog timer

We should fix this properly. That way we can also remove the sdkconfig file from the repository.

Update smartlamp.ts example

I am unable to connect to Wifi when using the smartlamp.ts example.
However if I change the following function:

function until_connected(connect: () => void,
connected: () => boolean): void {
while (!connected()) {
wd.delay(1000);
connect();
}
}

into

function until_connected(connect: () => void,
connected: () => boolean): void {
while (!connected()) {
connect();
wd.delay(5000);
}
}

the program connects to Wifi.

Fix GitHub Actions

  • Update the GitHub Actions to the new project structure
  • Add ESP-IDF to GitHub Actions
  • Fix compilation on macos and windows

Quality of Life changes

Requested features:

  • README in platforms
  • Make platform files into actual templates
  • Update upload script

Document and test debugger API

We must make sure we know immediately when changes might break the VS Code plugin.

  • Add a complete reference for the debugger API
  • Add CI tests to verify the VM implements this API correctly

`subscribe_interrupt` requires the use of a memory page and table

I'm not sure whether this is an issue or not but I rather mention it just in case.

I noticed that to correctly use primitive subscribe_interrupt the executed Wasm needs to use a memory page and provide the function that needs to be used as callback as a table index.

I can understand why we need the memory page since this is the location where MQTT payloads get stored but are we 100% sure that compilers will always generate Wasm that uses at least one memory page? And also is there a reason why we need to pass the callback identifier through the table? Can the function identifier of the callback simply be passed as an argument to subscribe_interrupt?

AssemblyScript example optimized version fails

Trying to run the AssemblyScript example without the mqtt fails. (= programming demo example)

When the busy loop is empty, binaryen optimizes away callback functions. It eliminates the funcref table and passes the function's own index to the subscribe_interrupt primitive.

    while (true) {    
        wd.sleep(5); // Sleep for 5 seconds    
    }

The resulting index is obviously out of range since there is no table. This causes an unhandled exception whenever the VM wants to resolve an event.

It seems users of Asyncify have run into similar problems: WebAssembly/binaryen#4484

Source-level debugging?

Debugging wasm opcode execution doesn't seem very useful. Is source-level debugging available? If yes, are there any docs on this?

Add latest WASM proposal support

100 files from the official spectests fail due to changes from newly standardized WASM proposals:

  • block.wast
  • br_if.wast
  • br_table.wast
  • br.wast
  • call_indirect.wast
  • call.wast
  • conversions.wast
  • endianness.wast
  • fac.wast
  • float_literals.wast
  • float_memory.wast
  • func_ptrs.wast
  • func.wast
  • global.wast
  • i32.wast
  • i64.wast
  • if.wast
  • int_exprs.wast
  • load.wast
  • local_get.wast
  • local_set.wast
  • local_tee.wast
  • loop.wast
  • memory_init.wast
  • memory_fill.wast
  • memory_grow.wast
  • memory_redundancy.wast
  • memory_size.wast
  • memory_trap.wast
  • nop.wast
  • ref_is_null.wast
  • ref_null.wast
  • return.wast
  • select.wast
  • simd_address.wast
  • simd_bit_shift.wast
  • simd_bitwise.wast
  • simd_boolean.wast
  • simd_conversions.wast
  • simd_f32x4_arith.wast
  • simd_f32x4.wast
  • simd_f32x4_cmp.wast
  • simd_f32x4_pmin_pmax.wast
  • simd_f32x4_rounding.wast
  • simd_f64x2_arith.wast
  • simd_f64x2.wast
  • simd_f64x2_cmp.wast
  • simd_f64x2_pmin_pmax.wast
  • simd_f64x2_rounding.wast
  • simd_i16x8_arith2.wast
  • simd_i16x8_arith.wast
  • simd_i16x8_cmp.wast
  • simd_i16x8_extadd_pairwise_i8x16.wast
  • simd_i16x8_extmul_i8x16.wast
  • simd_i16x8_q15mulr_sat_s.wast
  • simd_i16x8_sat_arith.wast
  • simd_i32x4_arith2.wast
  • simd_i32x4_arith.wast
  • simd_i32x4_cmp.wast
  • simd_i32x4_dot_i16x8.wast
  • simd_i32x4_extadd_pairwise_i16x8.wast
  • simd_i32x4_extmul_i16x8.wast
  • simd_i32x4_trunc_sat_f32x4.wast
  • simd_i32x4_trunc_sat_f64x2.wast
  • simd_i64x2_arith2.wast
  • simd_i64x2_arith.wast
  • simd_i64x2_cmp.wast
  • simd_i64x2_extmul_i32x4.wast
  • simd_i8x16_arith2.wast
  • simd_i8x16_arith.wast
  • simd_i8x16_cmp.wast
  • simd_i8x16_sat_arith.wast
  • simd_int_to_int_extend.wast
  • simd_lane.wast
  • simd_load16_lane.wast
  • simd_load32_lane.wast
  • simd_load64_lane.wast
  • simd_load8_lane.wast
  • simd_load.wast
  • simd_load_extend.wast
  • simd_load_splat.wast
  • simd_load_zero.wast
  • simd_splat.wast
  • simd_store16_lane.wast
  • simd_store32_lane.wast
  • simd_store64_lane.wast
  • simd_store8_lane.wast
  • simd_store.wast
  • skip-stack-guard-page.wast
  • start.wast
  • store.wast
  • table_fill.wast
  • table_get.wast
  • table_grow.wast
  • table_set.wast
  • table_size.wast
  • traps.wast
  • unreachable.wast
  • unreached-valid.wast
  • unwind.wast

Fix Schrödinbug: reflashing + incomplete callback synchronisation

OOP doesn't seem to work anymore:

  1. Reflashing undoes init code: set_pinmode, subscribe_interrupt, ... So no events are generated from the device.
  2. Callbackmapping only synced when fetching the snapshot. So either (A) the drone can receive events but the emulator has an empty callbackmapping or (B) the drone cannot receive events (see 1) while the emulator has a correct callbackmapping.

Support multiple modules

Tasks:

  • Move stack pointers from Module to WARDuino class

Spectests that fail because of this missing proposal:

  • block.wast

Once WARDuino reaches a breakpoint, it is not possible to resume the execution with a RUN interrupt

Once WARDuino reaches a breakpoint, sending a RUN interrupt to WARDuino does not resume the computation, but instead WARDuino gets stuck at the currently reached bp.

The reason is the if-statement responsible to determine whether the current pc_ptr contains a breakpoint (see interpret function file instructions.cpp line nr. 1490). When you resume computation after reaching a bp, the if statement re-evaluates the pc_ptr to be a bp and thus pauses the execution once again. I guess this is not desired behavior?

If needed I can make a pull request for this.

Push debugging

  • second socket connection on drone
  • drone version of CallbackHandler::push_event: sends event to emulator (as json)
  • emulator: receive data from second socket connection (while loop in new thread)
  • emulator: parse json data from socket and create Event
  • emulator: push events to event queue (CallbackHandler::push_event)
  • emulator: resolve event on message (plugin can choose when to resolve the event)
  • plugin: add command to perform next event
  • plugin: view current event queue
  • emulator: change event queue size
  • drone: add interrupt to toggle eventPushingMode
  • emulator: change proxy list at runtime
  • emulator: change the pushClient's buffer size
  • plugin: test push event receive
  • plugin: resolve next event
  • #62

json interface:

{
   "topic":"topic string",
   "payload":"payload as a string"
}

Add pull push debugging unit tests

  • Refactor code so an emulated version can also be a drone
  • Test connection
  • Test proxy calls (check return value)
  • Test push debugging with fake events in drone

Version 0.2.2-dev

0.2.2-dev: Stable EDWARD

The #47 pull request works, but there are a lot of outstanding issues before it can be merged into master.

Code smells

  • remove strict wifi socket requirement
  • Remove #ifndef ARDUINO as much as possible
  • Separate proxy and proxysupervisor code. Use clearer names.
  • #70

Bugs

Major features

Minor features

Plugin

Related issues in the plugin:

  • fix breakpoints
  • implement step back until start

Add dronify message

Instead of reflashing a drone version of the Arduino.ino file to the board after we pull the debugsession, we should add a dronify or zombify message which simply tells the device to turn into a drone.

  • Remove Arduino-socket.ino

Full emulated testing of out-of-place

Our goal is to allow the full VM to be tested with the emulated version.
The most challenging part is testing OOP with the emulator because a lot of inherited code is microcontroller specific.

Things to fix in order:

  • Replace SocketServer.h with abstract and uniform socket interface, the same used for remote debugging. (deprecates SocketServer.h)
  • Implement functionality of deprecated SocketServer for emulated VM
  • Enable OOP code in emulated VM (can become a drone with the dronify message)
  • Add code to CLI to control drone: answer proxy calls and send events

This will allow for manual testing of OOP with 2 emulated VMs. As part of #53 we can add automated API tests in a next step.

Off by one error with breakpoints

When debugging larger files, the offset reported by warduino is sometimes wrong (off by one)

The cause is probably somewhere here:

WARDuino/WARDuino.cpp

Lines 314 to 327 in 07cf2b6

uint8_t *pos = bytes;
word = read_uint32(&pos);
debug("Magic number is 0x%x\n", word);
ASSERT(word == WA_MAGIC, "Wrong module magic 0x%x\n", word);
word = read_uint32(&pos);
ASSERT(word == WA_VERSION, "Wrong module version 0x%x\n", word);
// Read the sections
uint8_t *bytes_end = bytes + byte_count;
while (pos < bytes_end) {
uint32_t id = read_LEB(&pos, 7);
uint32_t section_len = read_LEB_32(&pos);
uint8_t *start_pos = pos;
debug("Reading section %d at 0x%p, length %d\n", id, pos, section_len);
switch (id) {

WARDuino/WARDuino.cpp

Lines 335 to 339 in 07cf2b6

// TODO: make use of these
uint32_t memorysize = read_LEB_32(&pos);
uint32_t tablesize = read_LEB_32(&pos);
(void) memorysize;
(void) tablesize;

@carllocos could you supply 2 files: one with correct offset, one with a wrong offset

Remove unnecessary files

On branch feat/wood there are a lot of temporary and unnecessary files.
We should clean the repo before merging #47.

Remove the following files:

  • do_build.sh
  • platforms/Arduino/upload
  • platforms/Arduino-socket/*
  • scripts/*
  • examples/blinkm5stickc
  • examples/factorial

Interrupt payload needs to end with a space and a new line

I'm writing a python client to WARDuino and noticed that when sending an interrupt through the socket, the interrupt payload has to end with a space and a new line in order to be processed by WARDuino: '60 \n' works fine but '60\n' or '60 ' does not work.

However, when sending interrupts through Telnet the space is not needed i.e., it suffices to type '60' and press enter.

Block type collision

Block types may be expressed in one of two forms; (1) as a type index of an existing function type or (2) as a value type.¹

Currently the VM only supports the latter. (see WARDuino.cpp#L57)
However, to avoid collision with the type indices, the value types are encoded as negative numbers.
In WARDuino we only use unsigned integers.
This means that simply adding type indices to the switch statement in the get_block_types function, like we did in commit fc5c1df, means collisions are technically possible.

How would we best resolve this?


¹ https://webassembly.github.io/spec/core/valid/types.html?highlight=block#block-types

Memory synchronisation during OOP

Changes to the memory are not forwarded to the drone.
This means that calling primitives with pointers (start + length of string for example) may fail, as the memory is not kept in sync.

Reproduce

  1. Start OOP
  2. Change memory
  3. Call a primitive that uses the altered memory

How to build WARDuino for other mcu's

Hi! I would like to know if there is a list of supported mcu's other than esp32/esp8266. If not, it is possible to get some instructions on how to build WARDuino for other Arduino compatible mcu's??

Thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.