Skip to content

Commit

Permalink
[microTVM] Project API Arduino support (apache#8708)
Browse files Browse the repository at this point in the history
* ProjectAPI Arduino support

* Compile and run integration tests

* Add support for other Arduino boards

* Unit tests for project generation

* AOT support

* Arduino RPC server

* Incorporate ProjectAPI changes

Add Arduino tests to CI

* Copyright notices

* Fix Andrew's PR comments

* Additional PR comments

PR comments and Python 3.6 support

Linting fix

Re-add test onnx file

Test Arduino cli bug workaround

Support new hardware targets

Temporary fix for tests

Formatting issue

Spelling fix

Add test case for exact FQBN matching

* Add unit tests from apps directory to task_python_microtvm.sh
  • Loading branch information
guberti authored and ylc committed Jan 13, 2022
1 parent 566811c commit 281d686
Show file tree
Hide file tree
Showing 30 changed files with 2,383 additions and 14 deletions.
30 changes: 30 additions & 0 deletions apps/microtvm/arduino/example_project/project.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

#include "src/model.h"

void setup() {
TVMInitialize();
// If desired, initialize the RNG with random noise
// randomSeed(analogRead(0));
}

void loop() {
//TVMExecute(input_data, output_data);
}
94 changes: 94 additions & 0 deletions apps/microtvm/arduino/example_project/src/model.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

#include "model.h"

#include "Arduino.h"
#include "standalone_crt/include/tvm/runtime/crt/internal/aot_executor/aot_executor.h"
#include "standalone_crt/include/tvm/runtime/crt/stack_allocator.h"

// AOT memory array
static uint8_t g_aot_memory[WORKSPACE_SIZE];
extern tvm_model_t tvmgen_default_network;
tvm_workspace_t app_workspace;

// Blink code for debugging purposes
void TVMPlatformAbort(tvm_crt_error_t error) {
TVMLogf("TVMPlatformAbort: 0x%08x\n", error);
for (;;) {
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, HIGH);
delay(250);
digitalWrite(LED_BUILTIN, LOW);
delay(250);
digitalWrite(LED_BUILTIN, HIGH);
delay(250);
digitalWrite(LED_BUILTIN, LOW);
delay(750);
#endif
}
}

void TVMLogf(const char* msg, ...) {}

tvm_crt_error_t TVMPlatformMemoryAllocate(size_t num_bytes, DLDevice dev, void** out_ptr) {
return StackMemoryManager_Allocate(&app_workspace, num_bytes, out_ptr);
}

tvm_crt_error_t TVMPlatformMemoryFree(void* ptr, DLDevice dev) {
return StackMemoryManager_Free(&app_workspace, ptr);
}

unsigned long g_utvm_start_time_micros;
int g_utvm_timer_running = 0;

tvm_crt_error_t TVMPlatformTimerStart() {
if (g_utvm_timer_running) {
return kTvmErrorPlatformTimerBadState;
}
g_utvm_timer_running = 1;
g_utvm_start_time_micros = micros();
return kTvmErrorNoError;
}

tvm_crt_error_t TVMPlatformTimerStop(double* elapsed_time_seconds) {
if (!g_utvm_timer_running) {
return kTvmErrorPlatformTimerBadState;
}
g_utvm_timer_running = 0;
unsigned long g_utvm_stop_time = micros() - g_utvm_start_time_micros;
*elapsed_time_seconds = ((double)g_utvm_stop_time) / 1e6;
return kTvmErrorNoError;
}

tvm_crt_error_t TVMPlatformGenerateRandom(uint8_t* buffer, size_t num_bytes) {
for (size_t i = 0; i < num_bytes; i++) {
buffer[i] = rand();
}
return kTvmErrorNoError;
}

void TVMInitialize() { StackMemoryManager_Init(&app_workspace, g_aot_memory, WORKSPACE_SIZE); }

void TVMExecute(void* input_data, void* output_data) {
int ret_val = tvmgen_default_run_model(input_data, output_data);
if (ret_val != 0) {
TVMPlatformAbort(kTvmErrorPlatformCheckFailure);
}
}
40 changes: 40 additions & 0 deletions apps/microtvm/arduino/example_project/src/model.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

#define WORKSPACE_SIZE $workspace_size_bytes

#ifdef __cplusplus
extern "C" {
#endif

void TVMInitialize();

/* TODO template this function signature with the input and output
* data types and sizes. For example:
*
* void TVMExecute(uint8_t input_data[9216], uint8_t output_data[3]);
*
* Note this can only be done once MLF has JSON metadata describing
* inputs and outputs.
*/
void TVMExecute(void* input_data, void* output_data);

#ifdef __cplusplus
} // extern "C"
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/*!
* \brief CRT configuration for the host-linked CRT.
*/
#ifndef TVM_RUNTIME_MICRO_CRT_CONFIG_H_
#define TVM_RUNTIME_MICRO_CRT_CONFIG_H_

/*! Log level of the CRT runtime */
#define TVM_CRT_LOG_LEVEL TVM_CRT_LOG_LEVEL_DEBUG

/*! Support low-level debugging in MISRA-C runtime */
#define TVM_CRT_DEBUG 0

/*! Maximum supported dimension in NDArray */
#define TVM_CRT_MAX_NDIM 6
/*! Maximum supported arguments in generated functions */
#define TVM_CRT_MAX_ARGS 10
/*! Maximum supported string length in dltype, e.g. "int8", "int16", "float32" */
#define TVM_CRT_MAX_STRLEN_DLTYPE 10
/*! Maximum supported string length in function names */
#define TVM_CRT_MAX_STRLEN_FUNCTION_NAME 80

/*! Maximum number of registered modules. */
#define TVM_CRT_MAX_REGISTERED_MODULES 2

/*! Size of the global function registry, in bytes. */
#define TVM_CRT_GLOBAL_FUNC_REGISTRY_SIZE_BYTES 512

/*! Maximum packet size, in bytes, including the length header. */
#define TVM_CRT_MAX_PACKET_SIZE_BYTES 8 * 1024

/*! \brief Maximum length of a PackedFunc function name. */
#define TVM_CRT_MAX_FUNCTION_NAME_LENGTH_BYTES 30

// #define TVM_CRT_FRAMER_ENABLE_LOGS

#endif // TVM_RUNTIME_MICRO_CRT_CONFIG_H_
53 changes: 53 additions & 0 deletions apps/microtvm/arduino/host_driven/project.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

#include "src/standalone_crt/include/tvm/runtime/crt/microtvm_rpc_server.h"
#include "src/standalone_crt/include/tvm/runtime/crt/logging.h"
microtvm_rpc_server_t server;

// Called by TVM to write serial data to the UART.
ssize_t write_serial(void* unused_context, const uint8_t* data, size_t size) {
Serial.write(data, size);
return size;
}

void setup() {
server = MicroTVMRpcServerInit(write_serial, NULL);
TVMLogf("microTVM Arduino runtime - running");
Serial.begin(115200);

// If desired, initialize the RNG with random noise
// randomSeed(analogRead(0));
}

void loop() {
// Read at most 128 bytes at a time to prevent stack blowup
int to_read = min(Serial.available(), 128);

uint8_t data[to_read];
size_t bytes_remaining = Serial.readBytes((char*) data, to_read);
uint8_t* arr_ptr = data;
while (bytes_remaining > 0) {
// Pass the received bytes to the RPC server.
tvm_crt_error_t err = MicroTVMRpcServerLoop(server, &arr_ptr, &bytes_remaining);
if (err != kTvmErrorNoError && err != kTvmErrorFramingShortPacket) {
TVMPlatformAbort(err);
}
}
}
75 changes: 75 additions & 0 deletions apps/microtvm/arduino/host_driven/src/model_support.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

#include "standalone_crt/include/tvm/runtime/crt/internal/aot_executor/aot_executor.h"
#include "stdarg.h"

// Blink code for debugging purposes
void TVMPlatformAbort(tvm_crt_error_t error) {
TVMLogf("TVMPlatformAbort: 0x%08x\n", error);
for (;;)
;
}

size_t TVMPlatformFormatMessage(char* out_buf, size_t out_buf_size_bytes, const char* fmt,
va_list args) {
return vsnprintf(out_buf, out_buf_size_bytes, fmt, args);
}

tvm_crt_error_t TVMPlatformMemoryAllocate(size_t num_bytes, DLDevice dev, void** out_ptr) {
if (num_bytes == 0) {
num_bytes = sizeof(int);
}
*out_ptr = malloc(num_bytes);
return (*out_ptr == NULL) ? kTvmErrorPlatformNoMemory : kTvmErrorNoError;
}

tvm_crt_error_t TVMPlatformMemoryFree(void* ptr, DLDevice dev) {
free(ptr);
return kTvmErrorNoError;
}

unsigned long g_utvm_start_time_micros;
int g_utvm_timer_running = 0;

tvm_crt_error_t TVMPlatformTimerStart() {
if (g_utvm_timer_running) {
return kTvmErrorPlatformTimerBadState;
}
g_utvm_timer_running = 1;
g_utvm_start_time_micros = micros();
return kTvmErrorNoError;
}

tvm_crt_error_t TVMPlatformTimerStop(double* elapsed_time_seconds) {
if (!g_utvm_timer_running) {
return kTvmErrorPlatformTimerBadState;
}
g_utvm_timer_running = 0;
unsigned long g_utvm_stop_time = micros() - g_utvm_start_time_micros;
*elapsed_time_seconds = ((double)g_utvm_stop_time) / 1e6;
return kTvmErrorNoError;
}

tvm_crt_error_t TVMPlatformGenerateRandom(uint8_t* buffer, size_t num_bytes) {
for (size_t i = 0; i < num_bytes; i++) {
buffer[i] = rand();
}
return kTvmErrorNoError;
}
Loading

0 comments on commit 281d686

Please sign in to comment.