This is an automated email from the ASF dual-hosted git repository.
ashutoshp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm.git
The following commit(s) were added to refs/heads/main by this push:
new 77df6e8d7c [CMSIS-NN] Add a runtime error message (#13643)
77df6e8d7c is described below
commit 77df6e8d7c4e2481751931bb85d134e2c0801818
Author: Nicola Lancellotti <[email protected]>
AuthorDate: Mon Feb 27 18:05:40 2023 +0100
[CMSIS-NN] Add a runtime error message (#13643)
[CMSIS-NN] Add a runtime error message
APIs TVMAPISetLastError and TVMGetLastError are used to propagate CMSIS-NN
errors caught in the backend. AOT test runner was improved to observe the
contents
of this global variable. A test was added to check for the last set error
as part of this
commit.
---
python/tvm/testing/aot.py | 67 +++++++--
.../backend/contrib/cmsisnn/compiler_attrs.cc | 2 +
src/relay/backend/contrib/cmsisnn/compiler_attrs.h | 4 +
src/relay/backend/contrib/cmsisnn/target.cc | 1 +
.../backend/contrib/cmsisnn/tir_to_runtime.cc | 59 +++++---
.../python/contrib/test_cmsisnn/test_last_error.py | 164 +++++++++++++++++++++
tests/python/contrib/test_cmsisnn/utils.py | 6 +-
tests/python/relay/aot/corstone300.mk | 18 ++-
8 files changed, 287 insertions(+), 34 deletions(-)
diff --git a/python/tvm/testing/aot.py b/python/tvm/testing/aot.py
index d58a1af9d6..086b2a1bfd 100644
--- a/python/tvm/testing/aot.py
+++ b/python/tvm/testing/aot.py
@@ -23,7 +23,7 @@ import re
import subprocess
import tarfile
import logging
-from typing import Any, NamedTuple, Union, Tuple, Optional, List, Dict
+from typing import Any, NamedTuple, Union, Tuple, Optional, List, Dict,
Callable
import numpy as np
import tvm
@@ -200,6 +200,7 @@ def _emit_main_prologue(
compiled_models,
interface_api,
use_stack_allocator=True,
+ debug_last_error=False,
):
if use_stack_allocator:
workspace_define = f"#define WORKSPACE_SIZE ({workspace_bytes}"
@@ -243,11 +244,28 @@ void TVMLogf(const char* msg, ...) {
va_start(args, msg);
vfprintf(stdout, msg, args);
va_end(args);
-}\n
-TVM_DLL int TVMFuncRegisterGlobal(const char* name, TVMFunctionHandle f, int
override) {}
-int main(){\n
+}
"""
)
+ if debug_last_error:
+ main_file.write(
+ """\n
+tvm_crt_error_t TVMPlatformTimerStart() {
+ return kTvmErrorFunctionCallNotImplemented;
+}
+tvm_crt_error_t TVMPlatformTimerStop(double* elapsed_time_seconds) {
+ return kTvmErrorFunctionCallNotImplemented;
+}
+const TVMModule* TVMSystemLibEntryPoint(void) { return NULL; }
+"""
+ )
+ else:
+ main_file.write(
+ """\n
+TVM_DLL int TVMFuncRegisterGlobal(const char* name, TVMFunctionHandle f, int
override) {}
+"""
+ )
+ main_file.write("\nint main(){\n")
main_file.write(custom_prologue)
@@ -332,10 +350,10 @@ def _emit_main_data_setup(main_file, input_map,
output_map, mod_name):
def _emit_main_c_interface_call(
- main_file, devices, workspace_pool_names, mod_name, use_workspace_io
+ main_file, devices, workspace_pool_names, mod_name, use_workspace_io,
debug_last_error
):
sub_strings = list()
- sub_strings.append(f'{_mangle_name(mod_name,"run")}(')
+ sub_strings.append(f'if ({_mangle_name(mod_name,"run")}(')
if not use_workspace_io:
sub_strings.append(f'&{_mangle_name(mod_name,"inputs")}, ')
sub_strings.append(f'&{_mangle_name(mod_name,"outputs")}, ')
@@ -346,10 +364,14 @@ def _emit_main_c_interface_call(
# Removing the last two characters that is a comma and a space
sub_strings[-1] = sub_strings[-1][:-2]
# Adding brackets and newline instead
- sub_strings[-1] = sub_strings[-1] + ");\n"
-
+ sub_strings[-1] = sub_strings[-1] + ") == -1) {\n"
main_file_string = "".join(sub_strings)
main_file.write(main_file_string)
+ if debug_last_error:
+ main_file.write(f'\tprintf("ERROR: %s\\n", TVMGetLastError());\n')
+ main_file.write(f'\tprintf("{AOT_FAILURE_TOKEN}\\n");\n')
+ main_file.write(f"\treturn -1;\n")
+ main_file.write("}\n")
def _emit_main_fake_packed_values(main_file):
@@ -447,13 +469,15 @@ def _emit_main_epilogue(main_file, custom_epilogue):
main_file.write("}\n")
-def _emit_main_common_includes(main_file, custom_includes):
+def _emit_main_common_includes(main_file, custom_includes, debug_last_error):
main_file.write("#include <stdio.h>\n")
main_file.write("#include <stdarg.h>\n")
main_file.write("#include <stdlib.h>\n")
main_file.write("#include <math.h>\n")
main_file.write('#include "tvm/runtime/c_runtime_api.h"\n')
main_file.write('#include "tvm/runtime/crt/stack_allocator.h"\n')
+ if debug_last_error:
+ main_file.write('#include "tvm/runtime/crt/module.h"\n')
for include in custom_includes:
main_file.write(f'#include "{include}"\n')
@@ -474,12 +498,13 @@ def _create_main(
workspace_bytes,
use_stack_allocator=True,
use_workspace_io=False,
+ debug_last_error=False,
):
file_path = pathlib.Path(f"{output_path}/" + test_name).resolve()
# create header file
raw_path = file_path.with_suffix(".c").resolve()
with open(raw_path, "w") as main_file:
- _emit_main_common_includes(main_file, custom_includes)
+ _emit_main_common_includes(main_file, custom_includes,
debug_last_error)
if interface_api == "c":
for compiled_model in compiled_models:
@@ -497,6 +522,7 @@ def _create_main(
compiled_models,
interface_api,
use_stack_allocator,
+ debug_last_error,
)
if use_stack_allocator:
_emit_main_init_memory_manager(main_file)
@@ -529,6 +555,7 @@ def _create_main(
list(workspace_pool_names.keys()),
model.name,
use_workspace_io,
+ debug_last_error,
)
else:
_emit_main_fake_packed_values(main_file)
@@ -701,6 +728,8 @@ def run_and_check(
test_dir: str = None,
verbose: bool = False,
use_workspace_io: bool = False,
+ debug_last_error: bool = False,
+ checker: Optional[Callable[[str], bool]] = None,
):
"""
This method uses the original test data and compiled runtime.Modules
@@ -780,8 +809,12 @@ def run_and_check(
workspace_bytes,
use_stack_allocator,
use_workspace_io,
+ debug_last_error,
)
+ if checker and (not checker(base_path)):
+ return False
+
# Verify that compiles fine
file_dir = os.path.dirname(os.path.abspath(__file__))
makefile_dir = os.path.join(file_dir,
"../../../tests/python/relay/aot")
@@ -829,11 +862,13 @@ def run_and_check(
with open(run_log_path) as run_log:
assert AOT_SUCCESS_TOKEN in run_log.read()
+ return True
+
if test_dir is None:
tmpdir = utils.tempdir()
- run_and_check_body(os.path.join(tmpdir.path, "test"))
+ return run_and_check_body(os.path.join(tmpdir.path, "test"))
else:
- run_and_check_body(test_dir)
+ return run_and_check_body(test_dir)
def compile_and_run(
@@ -852,7 +887,9 @@ def compile_and_run(
test_dir: str = None,
verbose: bool = False,
schedule_name: str = None,
-):
+ debug_last_error: bool = False,
+ checker: Optional[Callable[[str], bool]] = None,
+) -> bool:
"""This is a wrapper API to compile and run models as test for AoT
Parameters
@@ -883,7 +920,7 @@ def compile_and_run(
schedule_name=schedule_name,
)
- run_and_check(
+ return run_and_check(
models=compiled_test_mods,
runner=runner,
interface_api=interface_api,
@@ -893,6 +930,8 @@ def compile_and_run(
data_linkage=data_linkage,
test_dir=test_dir,
verbose=verbose,
+ debug_last_error=debug_last_error,
+ checker=checker,
)
diff --git a/src/relay/backend/contrib/cmsisnn/compiler_attrs.cc
b/src/relay/backend/contrib/cmsisnn/compiler_attrs.cc
index 1df84d94d8..61b6c9ce89 100644
--- a/src/relay/backend/contrib/cmsisnn/compiler_attrs.cc
+++ b/src/relay/backend/contrib/cmsisnn/compiler_attrs.cc
@@ -40,11 +40,13 @@ Target CreateTarget(const tvm::transform::PassContext& ctx)
{
String mcpu = cfg.value()->mcpu;
Array<String> mattr = {cfg.value()->mattr};
+ Bool debug_last_error = cfg.value()->debug_last_error;
Target cmsis_nn_target(TargetJSON{
{"kind", String("cmsis-nn")},
{"mcpu", mcpu},
{"mattr", mattr},
+ {"debug_last_error", debug_last_error},
});
return cmsis_nn_target;
diff --git a/src/relay/backend/contrib/cmsisnn/compiler_attrs.h
b/src/relay/backend/contrib/cmsisnn/compiler_attrs.h
index 794dcbfa19..7bb355e0b2 100644
--- a/src/relay/backend/contrib/cmsisnn/compiler_attrs.h
+++ b/src/relay/backend/contrib/cmsisnn/compiler_attrs.h
@@ -37,6 +37,7 @@ namespace cmsisnn {
struct CMSISNNCompilerConfigNode : public
tvm::AttrsNode<CMSISNNCompilerConfigNode> {
String mcpu;
String mattr;
+ Bool debug_last_error = Bool(false);
TVM_DECLARE_ATTRS(CMSISNNCompilerConfigNode,
"ext.attrs.CMSISNNCompilerConfigNode") {
TVM_ATTR_FIELD(mcpu)
@@ -47,6 +48,9 @@ struct CMSISNNCompilerConfigNode : public
tvm::AttrsNode<CMSISNNCompilerConfigNo
TVM_ATTR_FIELD(mattr)
.describe("The attributes to configure CMSIS-NN (i.e. +nodsp, +nomve)")
.set_default("");
+ TVM_ATTR_FIELD(debug_last_error)
+ .describe("Whether to enable storing the last error")
+ .set_default(Bool(false));
}
};
diff --git a/src/relay/backend/contrib/cmsisnn/target.cc
b/src/relay/backend/contrib/cmsisnn/target.cc
index ec4fa83d34..f14c106703 100644
--- a/src/relay/backend/contrib/cmsisnn/target.cc
+++ b/src/relay/backend/contrib/cmsisnn/target.cc
@@ -36,6 +36,7 @@ runtime::Module TIRToRuntime(IRModule mod, Target target);
TVM_REGISTER_TARGET_KIND("cmsis-nn", kDLCPU)
.add_attr_option<Array<String>>("mattr")
.add_attr_option<String>("mcpu")
+ .add_attr_option<Bool>("debug_last_error")
.set_attr<FTVMRelayToTIR>(tvm::attr::kRelayToTIR, RelayToTIR())
.set_attr<FTVMTIRToRuntime>("TIRToRuntime", TIRToRuntime)
.set_target_parser(tvm::target::parsers::cpu::ParseTarget);
diff --git a/src/relay/backend/contrib/cmsisnn/tir_to_runtime.cc
b/src/relay/backend/contrib/cmsisnn/tir_to_runtime.cc
index a592eb74b4..ba2aea54bb 100644
--- a/src/relay/backend/contrib/cmsisnn/tir_to_runtime.cc
+++ b/src/relay/backend/contrib/cmsisnn/tir_to_runtime.cc
@@ -16,6 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
+#include <tvm/ir/transform.h>
+
#include <cmath>
#include <fstream>
#include <map>
@@ -26,6 +28,7 @@
#include "../../../../runtime/file_utils.h"
#include "../../../../target/source/codegen_c.h"
#include "../../../../target/source/codegen_c_host.h"
+#include "compiler_attrs.h"
namespace tvm {
using namespace tir;
@@ -35,7 +38,9 @@ namespace cmsisnn {
class CodeGenCMSISNN : public codegen::CodeGenCHost {
public:
- void Init(bool output_ssa, bool emit_asserts, bool emit_fwd_func_decl,
std::string target_str) {
+ void Init(bool output_ssa, bool emit_asserts, bool emit_fwd_func_decl,
std::string target_str,
+ bool debug_last_error) {
+ this->debug_last_error = debug_last_error;
std::unordered_set<std::string> devices;
devices.insert("cmsis-nn");
CodeGenCHost::Init(output_ssa, emit_asserts, emit_fwd_func_decl,
target_str, devices);
@@ -49,6 +54,9 @@ class CodeGenCMSISNN : public codegen::CodeGenCHost {
void AddFunction(const PrimFunc& prim_func) {
CodeGenC::AddFunction(prim_func); }
private:
+ /*! * \brief Enable storing the last error */
+ bool debug_last_error;
+
/*! * \brief CMSIS-NN context buffer info */
struct CMSISNNContextBuffer {
std::string name;
@@ -357,13 +365,7 @@ class CodeGenCMSISNN : public codegen::CodeGenCHost {
stream << "&" << filter_dim << ", " << filter_data << ", ";
stream << "&" << bias_dim << ", " << bias_data << ", ";
stream << "&" << output_dim << ", " << output_data << ");\n";
- PrintIndent();
- stream << "if (status != ARM_CMSIS_NN_SUCCESS) {\n";
- PrintIndent();
- PrintIndent();
- stream << "return -1;\n";
- PrintIndent();
- stream << "}\n";
+ EmitErrorCheck();
}
/*! * \brief Emits CMSIS-NN APIs for every call_extern comprising fully
connected */
@@ -426,13 +428,7 @@ class CodeGenCMSISNN : public codegen::CodeGenCHost {
stream << "&" << filter_dim << ", " << filter_data << ", ";
stream << "&" << bias_dim << ", " << bias_data << ", ";
stream << "&" << output_dim << ", " << output_data << ");\n";
- PrintIndent();
- stream << "if (status != ARM_CMSIS_NN_SUCCESS) {\n";
- PrintIndent();
- PrintIndent();
- stream << "return -1;\n";
- PrintIndent();
- stream << "}\n";
+ EmitErrorCheck();
}
/*! * \brief Emits CMSIS-NN APIs for every call_extern comprising pooling
ops */
@@ -480,24 +476,51 @@ class CodeGenCMSISNN : public codegen::CodeGenCHost {
stream << "&" << input_dim << ", " << input_data << ", ";
stream << "&" << filter_dim << ", ";
stream << "&" << output_dim << ", " << output_data << ");\n";
+ EmitErrorCheck();
+ }
+
+ void EmitErrorCheck() {
+ auto emit_error = [&](std::string error) {
+ if (this->debug_last_error) {
+ stream << "TVMAPISetLastError(\"" << error << "\"); ";
+ }
+ };
+
PrintIndent();
- stream << "if (status != ARM_CMSIS_NN_SUCCESS) {\n";
+ stream << "switch (!status) {\n";
PrintIndent();
+ stream << "case ARM_CMSIS_NN_SUCCESS: break;\n";
PrintIndent();
+ stream << "case ARM_CMSIS_NN_ARG_ERROR: ";
+ emit_error("ARM_CMSIS_NN_ARG_ERROR");
+ stream << "return -1;\n";
+ PrintIndent();
+ stream << "case ARM_CMSIS_NN_NO_IMPL_ERROR: ";
+ emit_error("ARM_CMSIS_NN_NO_IMPL_ERROR");
stream << "return -1;\n";
PrintIndent();
stream << "}\n";
}
};
+static CMSISNNCompilerConfig GetCompilerAttrs() {
+ auto ctx = tvm::tir::transform::PassContext::Current();
+ Optional<CMSISNNCompilerConfig> cfg =
+ ctx->GetConfig<CMSISNNCompilerConfig>("relay.ext.cmsisnn.options");
+ if (!cfg.defined()) {
+ return AttrsWithDefaultValues<CMSISNNCompilerConfig>();
+ }
+ return cfg.value();
+}
+
runtime::Module TIRToRuntime(IRModule mod, Target target) {
bool output_ssa = false;
bool emit_asserts = false;
bool emit_fwd_func_decl = false;
+ bool debug_last_error = GetCompilerAttrs()->debug_last_error;
CodeGenCMSISNN codegen;
Array<String> function_names;
- codegen.Init(output_ssa, emit_asserts, emit_fwd_func_decl, target->str());
-
+ codegen.Init(output_ssa, emit_asserts, emit_fwd_func_decl, target->str(),
debug_last_error);
std::vector<std::pair<tvm::GlobalVar, tvm::BaseFunc>> funcs;
for (auto kv : mod->functions) {
funcs.push_back(kv);
diff --git a/tests/python/contrib/test_cmsisnn/test_last_error.py
b/tests/python/contrib/test_cmsisnn/test_last_error.py
new file mode 100644
index 0000000000..f21d5d1a03
--- /dev/null
+++ b/tests/python/contrib/test_cmsisnn/test_last_error.py
@@ -0,0 +1,164 @@
+# 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.
+
+"""CMSIS-NN integration tests: debug_last_error"""
+
+import re
+import numpy as np
+import pytest
+import tvm
+from tvm import relay
+from tvm.relay.op.contrib import cmsisnn
+
+from tvm.testing.aot import (
+ get_dtype_range,
+ generate_ref_data,
+ AOTTestModel,
+ compile_and_run,
+)
+from .utils import (
+ make_module,
+ get_same_padding,
+ make_qnn_relu,
+ assert_partitioned_function,
+ create_test_runner,
+)
+
+
+def make_model(
+ pool_op,
+ shape,
+ pool_size,
+ strides,
+ padding,
+ dtype,
+ scale,
+ zero_point,
+ relu_type,
+ layout,
+ input_op,
+):
+ """Create a Relay Function / network model"""
+ if input_op:
+ op = input_op
+ else:
+ op = relay.var("input", shape=shape, dtype=dtype)
+ pad_ = (0, 0, 0, 0)
+ if padding == "SAME":
+ dilation = (1, 1)
+ pad_ = get_same_padding((shape[1], shape[2]), pool_size, dilation,
strides)
+ op = relay.nn.pad(
+ op,
+ pad_width=[(0, 0), (pad_[0], pad_[2]), (pad_[1], pad_[3]), (0, 0)],
+ pad_value=zero_point,
+ pad_mode="constant",
+ )
+ if pool_op.__name__ == relay.nn.avg_pool2d.__name__:
+ op = relay.cast(op, "int32")
+ op = pool_op(
+ op, pool_size=pool_size, strides=strides, padding=pad_,
ceil_mode=True, layout=layout
+ )
+ if pool_op.__name__ == relay.nn.avg_pool2d.__name__:
+ op = relay.cast(op, dtype)
+ op = make_qnn_relu(op, relu_type, scale, zero_point, dtype)
+ return op
+
+
[email protected]_cmsisnn
[email protected]("debug_last_error", [True, False])
+def test_last_error(debug_last_error):
+ """Tests debug_last_error"""
+ dtype = "int16"
+ in_shape = (1, 28, 28, 12)
+ pool_size = (3, 3)
+ strides = (2, 2)
+ padding = "SAME"
+ relu_type = "NONE"
+ pool_type = relay.nn.avg_pool2d
+ zero_point = -34
+ scale = 0.0256
+ compiler_cpu = "cortex-m55"
+ cpu_flags = "+nomve"
+ layout = "NHWC"
+ input_op = None
+
+ interface_api = "c"
+ use_unpacked_api = True
+
+ model = make_model(
+ pool_op=pool_type,
+ shape=in_shape,
+ pool_size=pool_size,
+ strides=strides,
+ padding=padding,
+ dtype=dtype,
+ scale=scale,
+ zero_point=zero_point,
+ relu_type=relu_type,
+ layout=layout,
+ input_op=input_op,
+ )
+ orig_mod = make_module(model)
+
+ cmsisnn_mod = cmsisnn.partition_for_cmsisnn(orig_mod)
+
+ # validate pattern matching
+ assert_partitioned_function(orig_mod, cmsisnn_mod)
+
+ # validate the output
+ in_min, in_max = get_dtype_range(dtype)
+ inputs = {
+ "input": np.random.randint(in_min, high=in_max, size=in_shape,
dtype=dtype),
+ }
+ output_list = generate_ref_data(orig_mod["main"], inputs)
+
+ def checker(base_path: str) -> bool:
+ def read_file(path):
+ with open(path) as f:
+ return f.read()
+
+ test = read_file(base_path + "/build/test.c")
+ test_check = "TVMGetLastError" in test
+
+ default_lib2 = read_file(base_path +
"/codegen/host/src/default_lib2.c")
+ regex = (
+ r"(?s)arm_avgpool_s16(.*?)"
+ r'ARM_CMSIS_NN_ARG_ERROR:
TVMAPISetLastError\("ARM_CMSIS_NN_ARG_ERROR(.*?)'
+ r'ARM_CMSIS_NN_NO_IMPL_ERROR:
TVMAPISetLastError\("ARM_CMSIS_NN_NO_IMPL_ERROR'
+ )
+ default_lib2_check = re.search(regex, default_lib2) is not None
+
+ if debug_last_error:
+ return test_check and default_lib2_check
+ else:
+ return not (test_check or default_lib2_check)
+
+ result = compile_and_run(
+ AOTTestModel(
+ module=cmsisnn_mod,
+ inputs=inputs,
+ outputs=output_list,
+ params=None,
+ output_tolerance=1,
+ ),
+ create_test_runner(compiler_cpu, cpu_flags,
debug_last_error=debug_last_error),
+ interface_api,
+ use_unpacked_api,
+ debug_last_error=debug_last_error,
+ checker=checker,
+ )
+ assert result
diff --git a/tests/python/contrib/test_cmsisnn/utils.py
b/tests/python/contrib/test_cmsisnn/utils.py
index 74d9686a78..65f7402e6b 100644
--- a/tests/python/contrib/test_cmsisnn/utils.py
+++ b/tests/python/contrib/test_cmsisnn/utils.py
@@ -252,7 +252,7 @@ class
CheckForPadsWithinCompositeFunc(tvm.relay.ExprVisitor):
assert self.num_pads_ > 0, "Composite function should have pads within
it."
-def create_test_runner(compiler_cpu="cortex-m55", cpu_flags=""):
+def create_test_runner(compiler_cpu="cortex-m55", cpu_flags="",
debug_last_error=False):
"""
Creates AOT test runner for CMSIS-NN tests.
@@ -267,6 +267,8 @@ def create_test_runner(compiler_cpu="cortex-m55",
cpu_flags=""):
Arm(R) Cortex(R)-M55: when null +mve is set by default.
+nomve disables vector extensions.
Arm(R) Cortex(R)-M7 does not support mve.
+ debug_last_error: bool
+ Whether to enable storing the last error
"""
# cmsis_cpu is used to find out start up code inside CMSIS package
cmsis_cpu = "ARMCM7" if compiler_cpu == "cortex-m7" else "ARMCM55"
@@ -280,6 +282,7 @@ def create_test_runner(compiler_cpu="cortex-m55",
cpu_flags=""):
pass_config={
"relay.ext.cmsisnn.options": {
"mcpu": compiler_cpu + cpu_flags,
+ "debug_last_error": debug_last_error,
},
"tir.usmp.enable": True,
"tir.disable_storage_rewrite": True,
@@ -289,5 +292,6 @@ def create_test_runner(compiler_cpu="cortex-m55",
cpu_flags=""):
"MCPU": compiler_cpu,
"MCPU_FLAGS": cpu_flags,
"MFLOAT_ABI": mfloat_abi,
+ "DEBUG_LAST_ERROR": 1 if debug_last_error else 0,
},
)
diff --git a/tests/python/relay/aot/corstone300.mk
b/tests/python/relay/aot/corstone300.mk
index 1ac1ebfa0c..9b3ef46223 100644
--- a/tests/python/relay/aot/corstone300.mk
+++ b/tests/python/relay/aot/corstone300.mk
@@ -99,6 +99,22 @@ $(build_dir)/crt_backend_api.o:
$(TVM_ROOT)/src/runtime/crt/common/crt_backend_a
$(QUIET)mkdir -p $(@D)
$(QUIET)$(CC) -c $(PKG_CFLAGS) -o $@ $^
+ifeq ($(DEBUG_LAST_ERROR), 1)
+$(build_dir)/crt_runtime_api.o:
$(TVM_ROOT)/src/runtime/crt/common/crt_runtime_api.c
+ $(QUIET)mkdir -p $(@D)
+ $(QUIET)$(CC) -c $(PKG_CFLAGS) -o $@ $^
+
+$(build_dir)/func_registry.o:
$(TVM_ROOT)/src/runtime/crt/common/func_registry.c
+ $(QUIET)mkdir -p $(@D)
+ $(QUIET)$(CC) -c $(PKG_CFLAGS) -o $@ $^
+
+$(build_dir)/ndarray.o: $(TVM_ROOT)/src/runtime/crt/common/ndarray.c
+ $(QUIET)mkdir -p $(@D)
+ $(QUIET)$(CC) -c $(PKG_CFLAGS) -o $@ $^
+
+DEBUG_LAST_ERROR_SOURCES = $(build_dir)/crt_runtime_api.o
$(build_dir)/func_registry.o $(build_dir)/ndarray.o
+endif
+
$(build_dir)/tvm_ethosu_runtime.o:
$(TVM_ROOT)/src/runtime/contrib/ethosu/bare_metal/tvm_ethosu_runtime.c
$(QUIET)mkdir -p $(@D)
$(QUIET)$(CC) -c $(PKG_CFLAGS) -o $@ $^
@@ -133,7 +149,7 @@
${build_dir}/ethosu_core_platform/libethosu_uart_cmsdk_apb.a:
$(QUIET)cd ${ETHOSU_PLATFORM_PATH}/drivers/uart && $(CMAKE) -B
$(abspath $(build_dir)/ethosu_core_platform) $(CMAKE_FLAGS)
$(QUIET)cd $(abspath $(build_dir)/ethosu_core_platform) && $(MAKE)
-$(build_dir)/aot_test_runner: $(build_dir)/test.c
$(build_dir)/crt_backend_api.o $(build_dir)/stack_allocator.o
$(build_dir)/libcodegen.a ${build_dir}/libcmsis_startup.a
${build_dir}/libcmsis_nn.a ${build_dir}/libcorstone.a
${build_dir}/ethosu_core_platform/libethosu_uart_cmsdk_apb.a
$(ETHOSU_DRIVER_LIBS) $(ETHOSU_RUNTIME)
+$(build_dir)/aot_test_runner: $(build_dir)/test.c
$(build_dir)/crt_backend_api.o $(build_dir)/stack_allocator.o
$(build_dir)/libcodegen.a ${build_dir}/libcmsis_startup.a
${build_dir}/libcmsis_nn.a ${build_dir}/libcorstone.a
${build_dir}/ethosu_core_platform/libethosu_uart_cmsdk_apb.a
$(ETHOSU_DRIVER_LIBS) $(ETHOSU_RUNTIME) $(DEBUG_LAST_ERROR_SOURCES)
$(QUIET)mkdir -p $(@D)
$(QUIET)$(CC) $(PKG_CFLAGS) $(ETHOSU_INCLUDE) -o $@ -Wl,--whole-archive
$^ -Wl,--no-whole-archive $(PKG_LDFLAGS)