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)
 

Reply via email to