Skip to content

Commit c071693

Browse files
committed
Add new examples
1 parent 0d62a57 commit c071693

14 files changed

+3530
-1
lines changed

examples/Wasm_CoreMark/README.md

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
## CoreMark 1.0
2+
3+
### RAM requirements
4+
5+
- Wasm binary: `7.6 Kb`
6+
- Wasm3 dynamic structures: `~34Kb`
7+
- Linear Memory: `3 Kb`
8+
- Wasm Stack: `2 Kb`
9+
- Native stack: `~2 Kb`
10+
- **Total: `~44Kb`**
11+
12+
Note: if no TCO is available, native stack can get much larger.
13+
I.e. it grows to `48 Kb` for ESP32. And this causes ESP8266 to hang.
14+
This will be improved in future. 🦄
15+
16+
### Results for some boards
17+
```log
18+
Board | MCU | Freq | CoreMark
19+
-----------------------------------------------------------------
20+
Teensy 4.0 iMXRT1062 1 GHz 109.842
21+
Teensy 4.0 iMXRT1062 816 MHz 88.925
22+
Teensy 4.0 iMXRT1062 600 MHz 65.383
23+
Sipeed MAIX BiT Kendryte K210 400 MHz 60.730
24+
Adafruit pyBadge ATSAMD51J19 200 MHz 15.315
25+
Adafruit pyBadge ATSAMD51J19 120 MHz 9.193
26+
ESP32 ESP32 240 MHz 8.778
27+
ESP8266 ESP8266 80 MHz (hangs)
28+
Teensy 3.2 fastest+lto MK20DX256 120 MHz 6.800
29+
BLE Nano 2 nRF52832 64 MHz 3.938
30+
BBC micro:bit v2 nRF52833 64 MHz 3.908
31+
```
32+
+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/*
2+
* Wasm3 - high performance WebAssembly interpreter written in C.
3+
* Copyright © 2020 Volodymyr Shymanskyy, Steven Massey.
4+
* All rights reserved.
5+
*/
6+
7+
#include <wasm3.h>
8+
#include <m3_api_defs.h>
9+
#include <m3_env.h>
10+
11+
#include "coremark_minimal.wasm.h"
12+
13+
m3ApiRawFunction(env_clock_ms)
14+
{
15+
m3ApiReturnType (uint32_t)
16+
m3ApiReturn(millis());
17+
}
18+
19+
IM3Environment env;
20+
IM3Runtime runtime;
21+
IM3Module module;
22+
IM3Function func_run;
23+
24+
#define FATAL(func, msg) { Serial.print("Fatal: " func " "); Serial.println(msg); while(1) { delay(100); } }
25+
26+
void wasm_task(void*)
27+
{
28+
M3Result result = m3Err_none;
29+
30+
result = m3_FindFunction (&func_run, runtime, "run");
31+
if (result) FATAL("FindFunction", result);
32+
33+
Serial.println("Running CoreMark 1.0...");
34+
35+
result = m3_CallV (func_run);
36+
if (result) FATAL("Call", result);
37+
38+
float value = 0;
39+
result = m3_GetResultsV (func_run, &value);
40+
if (result) FATAL("GetResults: %s", result);
41+
42+
Serial.print("Result: ");
43+
Serial.println(value, 3);
44+
45+
if (result != m3Err_none) {
46+
M3ErrorInfo info;
47+
m3_GetErrorInfo (runtime, &info);
48+
Serial.print("Error: ");
49+
Serial.print(result);
50+
Serial.print(" (");
51+
Serial.print(info.message);
52+
Serial.println(")");
53+
if (info.file && strlen(info.file) && info.line) {
54+
Serial.print("At ");
55+
Serial.print(info.file);
56+
Serial.print(":");
57+
Serial.println(info.line);
58+
}
59+
}
60+
61+
#ifdef ESP32
62+
vTaskDelete(NULL);
63+
#endif
64+
}
65+
66+
void setup()
67+
{
68+
Serial.begin(115200);
69+
delay(500);
70+
71+
// Wait for serial port to connect
72+
// Needed for native USB port only
73+
//while(!Serial) {}
74+
75+
Serial.println();
76+
Serial.println("Wasm3 v" M3_VERSION " build " __DATE__ " " __TIME__);
77+
Serial.println("CPU: " M3_ARCH " @ " + String(F_CPU/1000000) + " MHz");
78+
79+
M3Result result = m3Err_none;
80+
81+
env = m3_NewEnvironment ();
82+
if (!env) FATAL("NewEnvironment", "failed");
83+
84+
runtime = m3_NewRuntime (env, 2048, NULL);
85+
if (!runtime) FATAL("NewRuntime", "failed");
86+
87+
runtime->memoryLimit = 3*1024;
88+
89+
result = m3_ParseModule (env, &module, coremark_minimal_wasm, coremark_minimal_wasm_len);
90+
if (result) FATAL("ParseModule", result);
91+
92+
result = m3_LoadModule (runtime, module);
93+
if (result) FATAL("LoadModule", result);
94+
95+
m3_LinkRawFunction (module, "env", "clock_ms", "i()", &env_clock_ms);
96+
97+
#if defined(ESP8266)
98+
ESP.wdtDisable();
99+
*((volatile uint32_t*) 0x60000900) &= ~(1); // Hardware WDT OFF
100+
wasm_task(NULL);
101+
#elif defined(ESP32)
102+
Serial.println("Launching a separate task");
103+
disableCore0WDT();
104+
xTaskCreate(&wasm_task, "wasm3", 64*1024, NULL, 5, NULL);
105+
#else
106+
wasm_task(NULL);
107+
#endif
108+
}
109+
110+
void loop()
111+
{
112+
delay(100);
113+
}

examples/Wasm_CoreMark/coremark_minimal.wasm.h

+651
Large diffs are not rendered by default.

examples/Wasm_Dino_ESP32_TDisplay/NotoSansBold15.h

+696
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
/*
2+
* Wasm3 - high performance WebAssembly interpreter written in C.
3+
* Copyright © 2021 Volodymyr Shymanskyy, Steven Massey.
4+
* All rights reserved.
5+
*/
6+
7+
#include <TFT_eSPI.h>
8+
#include <SPI.h>
9+
#include "NotoSansBold15.h"
10+
11+
#include <wasm3.h>
12+
#include <m3_api_defs.h>
13+
14+
#define NATIVE_STACK_SIZE (32*1024)
15+
16+
#define BUTTON_UP 35
17+
#define BUTTON_DOWN 0
18+
19+
#define DISPLAY_BRIGHTESS 1 // 0..255
20+
21+
TFT_eSPI tft = TFT_eSPI(135, 240); // Invoke custom library
22+
23+
/*
24+
* Dino game by by Ben Smith (binji)
25+
* https://github.com/binji/raw-wasm/tree/master/dino
26+
* To build:
27+
* export PATH=/opt/wasp/build/src/tools:$PATH
28+
* wasp wat2wasm --enable-numeric-values -o dino.wasm dino.wat
29+
* xxd -iC dino.wasm > dino.wasm.h
30+
*
31+
* Note: In Arduino IDE, select Tools->Optimize->Faster (-O3)
32+
*/
33+
#include "dino.wasm.h"
34+
35+
/*
36+
* Engine start, liftoff!
37+
*/
38+
39+
#define FATAL(func, msg) { Serial.print("Fatal: " func " "); Serial.println(msg); while(1) { delay(100); } }
40+
#define TSTART() { tstart = micros(); }
41+
#define TFINISH(s) { tend = micros(); Serial.print(s " in "); Serial.print(tend-tstart); Serial.println(" us"); }
42+
43+
// The Math.random() function returns a floating-point,
44+
// pseudo-random number in the range 0 to less than 1
45+
m3ApiRawFunction(Math_random)
46+
{
47+
m3ApiReturnType (float)
48+
49+
float r = (float)random(INT_MAX)/INT_MAX;
50+
//Serial.print("Random: "); Serial.println(r);
51+
52+
m3ApiReturn(r);
53+
}
54+
55+
// Memcpy is generic, and much faster in native code
56+
m3ApiRawFunction(Dino_memcpy)
57+
{
58+
m3ApiGetArgMem (uint8_t *, dst)
59+
m3ApiGetArgMem (uint8_t *, src)
60+
m3ApiGetArgMem (uint8_t *, dstend)
61+
62+
do {
63+
*dst++ = *src++;
64+
} while (dst < dstend);
65+
66+
m3ApiSuccess();
67+
}
68+
69+
IM3Environment env;
70+
IM3Runtime runtime;
71+
IM3Module module;
72+
IM3Function func_run;
73+
uint8_t* mem;
74+
75+
void load_wasm()
76+
{
77+
M3Result result = m3Err_none;
78+
79+
if (!env) {
80+
env = m3_NewEnvironment ();
81+
if (!env) FATAL("NewEnvironment", "failed");
82+
}
83+
84+
m3_FreeRuntime(runtime);
85+
86+
runtime = m3_NewRuntime (env, 1024, NULL);
87+
if (!runtime) FATAL("NewRuntime", "failed");
88+
89+
result = m3_ParseModule (env, &module, dino_wasm, sizeof(dino_wasm));
90+
if (result) FATAL("ParseModule", result);
91+
92+
result = m3_LoadModule (runtime, module);
93+
if (result) FATAL("LoadModule", result);
94+
95+
m3_LinkRawFunction (module, "Math", "random", "f()", &Math_random);
96+
m3_LinkRawFunction (module, "Dino", "memcpy", "v(iii)", &Dino_memcpy);
97+
98+
mem = m3_GetMemory (runtime, NULL, 0);
99+
if (!mem) FATAL("GetMemory", "failed");
100+
101+
result = m3_FindFunction (&func_run, runtime, "run");
102+
if (result) FATAL("FindFunction", result);
103+
}
104+
105+
void init_device()
106+
{
107+
pinMode(BUTTON_UP, INPUT);
108+
pinMode(BUTTON_DOWN, INPUT);
109+
110+
// Try to randomize seed
111+
randomSeed((analogRead(A5) << 16) + analogRead(A4));
112+
Serial.print("Random: 0x"); Serial.println(random(INT_MAX), HEX);
113+
114+
tft.init();
115+
tft.setRotation(1);
116+
tft.setSwapBytes(true);
117+
tft.loadFont(NotoSansBold15);
118+
119+
// Set backlight brightness
120+
ledcSetup(0, 5000, 8);
121+
ledcAttachPin(TFT_BL, 0);
122+
ledcWrite(0, DISPLAY_BRIGHTESS);
123+
}
124+
125+
void display_info()
126+
{
127+
tft.fillScreen(TFT_WHITE);
128+
tft.setTextColor(TFT_BLACK, TFT_WHITE);
129+
tft.setCursor(0, 5);
130+
tft.println(" Wasm3 v" M3_VERSION " (ESP32)");
131+
tft.println(" Dino game");
132+
tft.println(" by Ben Smith (binji)");
133+
}
134+
135+
void setup()
136+
{
137+
Serial.begin(115200);
138+
139+
Serial.println("\nWasm3 v" M3_VERSION " (" M3_ARCH "), build " __DATE__ " " __TIME__);
140+
141+
uint32_t tend, tstart;
142+
TSTART();
143+
init_device();
144+
display_info();
145+
TFINISH("Device init");
146+
147+
TSTART();
148+
load_wasm();
149+
TFINISH("Wasm3 init");
150+
151+
Serial.println("Running WebAssembly...");
152+
153+
xTaskCreate(&wasm_task, "wasm3", NATIVE_STACK_SIZE, NULL, 5, NULL);
154+
}
155+
156+
void wasm_task(void*)
157+
{
158+
M3Result result;
159+
uint64_t last_fps_print = 0;
160+
161+
while (true) {
162+
const uint64_t framestart = micros();
163+
164+
// Process inputs
165+
uint32_t* input = (uint32_t*)(mem + 0x0000);
166+
*input = 0;
167+
if (LOW == digitalRead(BUTTON_UP)) {
168+
*input |= 0x1;
169+
}
170+
if (LOW == digitalRead(BUTTON_DOWN)) {
171+
*input |= 0x2;
172+
}
173+
174+
// Render frame
175+
result = m3_CallV (func_run);
176+
if (result) break;
177+
178+
// Output to display
179+
tft.pushImage(0, 135-10-75, 240, 75, (uint16_t*)(mem+0x5000));
180+
181+
const uint64_t frametime = micros() - framestart;
182+
const uint32_t target_frametime = 1000000/50;
183+
if (target_frametime > frametime) {
184+
delay((target_frametime - frametime)/1000);
185+
}
186+
if (framestart - last_fps_print > 1000000) {
187+
Serial.print("FPS: "); Serial.println((uint32_t)(1000000/frametime));
188+
last_fps_print = framestart;
189+
}
190+
}
191+
192+
if (result != m3Err_none) {
193+
M3ErrorInfo info;
194+
m3_GetErrorInfo (runtime, &info);
195+
Serial.print("Error: ");
196+
Serial.print(result);
197+
Serial.print(" (");
198+
Serial.print(info.message);
199+
Serial.println(")");
200+
if (info.file && strlen(info.file) && info.line) {
201+
Serial.print("At ");
202+
Serial.print(info.file);
203+
Serial.print(":");
204+
Serial.println(info.line);
205+
}
206+
}
207+
}
208+
209+
void loop()
210+
{
211+
delay(100);
212+
}
2.01 KB
Binary file not shown.

0 commit comments

Comments
 (0)