diff --git a/CMakeLists.txt b/CMakeLists.txt index 36f7d379620f..7082c8e9de89 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -481,6 +481,7 @@ include(cmake/utils/CCache.cmake) # Module rules include(cmake/modules/VTA.cmake) include(cmake/modules/StandaloneCrt.cmake) +include(cmake/modules/CRT.cmake) include(cmake/modules/Zephyr.cmake) include(cmake/modules/Arduino.cmake) include(cmake/modules/CUDA.cmake) @@ -576,6 +577,7 @@ include(cmake/modules/contrib/PAPI.cmake) if(USE_MICRO) # NOTE: cmake doesn't track dependencies at the file level across subdirectories. For the # Unix Makefiles generator, need to add these explicit target-level dependency) + add_dependencies(tvm_runtime crt) add_dependencies(tvm_runtime zephyr) add_dependencies(tvm_runtime arduino) if(MSVC) diff --git a/ci/jenkins/generated/arm_jenkinsfile.groovy b/ci/jenkins/generated/arm_jenkinsfile.groovy index 0fc71b430ca0..2c64e9ab2499 100644 --- a/ci/jenkins/generated/arm_jenkinsfile.groovy +++ b/ci/jenkins/generated/arm_jenkinsfile.groovy @@ -60,7 +60,7 @@ // 'python3 jenkins/generate.py' // Note: This timestamp is here to ensure that updates to the Jenkinsfile are // always rebased on main before merging: -// Generated at 2022-12-09T15:39:24.387114 +// Generated at 2023-01-20T20:00:09.294689 import org.jenkinsci.plugins.pipeline.modeldefinition.Utils // These are set at runtime from data in ci/jenkins/docker-images.yml, update @@ -556,7 +556,7 @@ def build() { make_standalone_crt(ci_arm, 'build') make_cpp_tests(ci_arm, 'build') sh( - script: "./${jenkins_scripts_root}/s3.py --action upload --bucket ${s3_bucket} --prefix ${s3_prefix}/arm --items build/libtvm.so build/libvta_fsim.so build/libtvm_runtime.so build/config.cmake build/cpptest build/build.ninja build/CMakeFiles/rules.ninja build/crttest build/standalone_crt build/build.ninja", + script: "./${jenkins_scripts_root}/s3.py --action upload --bucket ${s3_bucket} --prefix ${s3_prefix}/arm --items build/libtvm.so build/libvta_fsim.so build/libtvm_runtime.so build/config.cmake build/cpptest build/build.ninja build/CMakeFiles/rules.ninja build/crttest build/standalone_crt build/build.ninja build/microtvm_template_projects", label: 'Upload artifacts to S3', ) } diff --git a/ci/jenkins/generated/cpu_jenkinsfile.groovy b/ci/jenkins/generated/cpu_jenkinsfile.groovy index f9ede00399a2..c9e02ba28761 100644 --- a/ci/jenkins/generated/cpu_jenkinsfile.groovy +++ b/ci/jenkins/generated/cpu_jenkinsfile.groovy @@ -60,7 +60,7 @@ // 'python3 jenkins/generate.py' // Note: This timestamp is here to ensure that updates to the Jenkinsfile are // always rebased on main before merging: -// Generated at 2022-12-09T15:39:24.540570 +// Generated at 2023-01-20T22:52:37.278903 import org.jenkinsci.plugins.pipeline.modeldefinition.Utils // These are set at runtime from data in ci/jenkins/docker-images.yml, update @@ -556,7 +556,7 @@ def build() { make_standalone_crt(ci_cpu, 'build') make_cpp_tests(ci_cpu, 'build') sh( - script: "./${jenkins_scripts_root}/s3.py --action upload --bucket ${s3_bucket} --prefix ${s3_prefix}/cpu --items build/libvta_tsim.so build/libtvm.so build/libvta_fsim.so build/libtvm_runtime.so build/config.cmake build/libtvm_allvisible.so build/crttest build/cpptest build/build.ninja build/CMakeFiles/rules.ninja build/standalone_crt build/build.ninja", + script: "./${jenkins_scripts_root}/s3.py --action upload --bucket ${s3_bucket} --prefix ${s3_prefix}/cpu --items build/libvta_tsim.so build/libtvm.so build/libvta_fsim.so build/libtvm_runtime.so build/config.cmake build/libtvm_allvisible.so build/crttest build/cpptest build/build.ninja build/CMakeFiles/rules.ninja build/standalone_crt build/build.ninja build/microtvm_template_projects", label: 'Upload artifacts to S3', ) diff --git a/ci/jenkins/generated/i386_jenkinsfile.groovy b/ci/jenkins/generated/i386_jenkinsfile.groovy index ae66fbe3e48c..0cadeac33dac 100644 --- a/ci/jenkins/generated/i386_jenkinsfile.groovy +++ b/ci/jenkins/generated/i386_jenkinsfile.groovy @@ -60,7 +60,7 @@ // 'python3 jenkins/generate.py' // Note: This timestamp is here to ensure that updates to the Jenkinsfile are // always rebased on main before merging: -// Generated at 2022-12-09T15:39:24.421467 +// Generated at 2023-01-20T20:00:09.177735 import org.jenkinsci.plugins.pipeline.modeldefinition.Utils // These are set at runtime from data in ci/jenkins/docker-images.yml, update @@ -556,7 +556,7 @@ def build() { make_standalone_crt(ci_i386, 'build') make_cpp_tests(ci_i386, 'build') sh( - script: "./${jenkins_scripts_root}/s3.py --action upload --bucket ${s3_bucket} --prefix ${s3_prefix}/i386 --items build/libvta_tsim.so build/libtvm.so build/libvta_fsim.so build/libtvm_runtime.so build/config.cmake build/standalone_crt build/build.ninja build/crttest build/cpptest build/build.ninja build/CMakeFiles/rules.ninja", + script: "./${jenkins_scripts_root}/s3.py --action upload --bucket ${s3_bucket} --prefix ${s3_prefix}/i386 --items build/libvta_tsim.so build/libtvm.so build/libvta_fsim.so build/libtvm_runtime.so build/config.cmake build/standalone_crt build/build.ninja build/crttest build/cpptest build/build.ninja build/CMakeFiles/rules.ninja build/microtvm_template_projects", label: 'Upload artifacts to S3', ) } diff --git a/ci/jenkins/generated/minimal_jenkinsfile.groovy b/ci/jenkins/generated/minimal_jenkinsfile.groovy index 6c4abb0bd5af..f054f60a3aa2 100644 --- a/ci/jenkins/generated/minimal_jenkinsfile.groovy +++ b/ci/jenkins/generated/minimal_jenkinsfile.groovy @@ -60,7 +60,7 @@ // 'python3 jenkins/generate.py' // Note: This timestamp is here to ensure that updates to the Jenkinsfile are // always rebased on main before merging: -// Generated at 2022-12-09T15:39:24.492813 +// Generated at 2023-01-20T22:52:37.006864 import org.jenkinsci.plugins.pipeline.modeldefinition.Utils // These are set at runtime from data in ci/jenkins/docker-images.yml, update @@ -556,7 +556,7 @@ def build() { make_standalone_crt(ci_minimal, 'build') make_cpp_tests(ci_minimal, 'build') sh( - script: "./${jenkins_scripts_root}/s3.py --action upload --bucket ${s3_bucket} --prefix ${s3_prefix}/cpu-minimal --items build/libtvm.so build/libtvm_runtime.so build/config.cmake build/libtvm_allvisible.so build/crttest build/cpptest build/build.ninja build/CMakeFiles/rules.ninja build/standalone_crt build/build.ninja", + script: "./${jenkins_scripts_root}/s3.py --action upload --bucket ${s3_bucket} --prefix ${s3_prefix}/cpu-minimal --items build/libtvm.so build/libtvm_runtime.so build/config.cmake build/libtvm_allvisible.so build/crttest build/cpptest build/build.ninja build/CMakeFiles/rules.ninja build/standalone_crt build/build.ninja build/microtvm_template_projects", label: 'Upload artifacts to S3', ) } diff --git a/ci/jenkins/templates/arm_jenkinsfile.groovy.j2 b/ci/jenkins/templates/arm_jenkinsfile.groovy.j2 index 6cffd5cbbe66..b455fa04125d 100644 --- a/ci/jenkins/templates/arm_jenkinsfile.groovy.j2 +++ b/ci/jenkins/templates/arm_jenkinsfile.groovy.j2 @@ -31,7 +31,7 @@ cmake_build(ci_arm, 'build', '-j4') make_standalone_crt(ci_arm, 'build') make_cpp_tests(ci_arm, 'build') - {{ m.upload_artifacts(tag='arm', filenames=tvm_multilib + cpptest + crttest + standalone_crt) }} + {{ m.upload_artifacts(tag='arm', filenames=tvm_multilib + cpptest + crttest + standalone_crt + microtvm_template_projects) }} {% endcall %} {% set test_method_names = [] %} diff --git a/ci/jenkins/templates/cpu_jenkinsfile.groovy.j2 b/ci/jenkins/templates/cpu_jenkinsfile.groovy.j2 index fa2be6584ff0..a833a89d64da 100644 --- a/ci/jenkins/templates/cpu_jenkinsfile.groovy.j2 +++ b/ci/jenkins/templates/cpu_jenkinsfile.groovy.j2 @@ -31,7 +31,7 @@ cmake_build(ci_cpu, 'build', '-j2') make_standalone_crt(ci_cpu, 'build') make_cpp_tests(ci_cpu, 'build') - {{ m.upload_artifacts(tag='cpu', filenames=tvm_multilib_tsim + tvm_allvisible + crttest + cpptest + standalone_crt) }} + {{ m.upload_artifacts(tag='cpu', filenames=tvm_multilib_tsim + tvm_allvisible + crttest + cpptest + standalone_crt + microtvm_template_projects) }} ci_setup(ci_cpu) // sh "${docker_run} ${ci_cpu} ./tests/scripts/task_golang.sh" // TODO(@jroesch): need to resolve CI issue will turn back on in follow up patch diff --git a/ci/jenkins/templates/i386_jenkinsfile.groovy.j2 b/ci/jenkins/templates/i386_jenkinsfile.groovy.j2 index 1825e0cbd6bd..da1cdeaefeee 100644 --- a/ci/jenkins/templates/i386_jenkinsfile.groovy.j2 +++ b/ci/jenkins/templates/i386_jenkinsfile.groovy.j2 @@ -31,7 +31,7 @@ cmake_build(ci_i386, 'build', '-j2') make_standalone_crt(ci_i386, 'build') make_cpp_tests(ci_i386, 'build') - {{ m.upload_artifacts(tag='i386', filenames=tvm_multilib_tsim + standalone_crt + crttest + cpptest) }} + {{ m.upload_artifacts(tag='i386', filenames=tvm_multilib_tsim + standalone_crt + crttest + cpptest + microtvm_template_projects) }} {% endcall %} diff --git a/ci/jenkins/templates/minimal_jenkinsfile.groovy.j2 b/ci/jenkins/templates/minimal_jenkinsfile.groovy.j2 index 87db883745cc..6420599061de 100644 --- a/ci/jenkins/templates/minimal_jenkinsfile.groovy.j2 +++ b/ci/jenkins/templates/minimal_jenkinsfile.groovy.j2 @@ -31,7 +31,7 @@ cmake_build(ci_minimal, 'build', '-j2') make_standalone_crt(ci_minimal, 'build') make_cpp_tests(ci_minimal, 'build') - {{ m.upload_artifacts(tag='cpu-minimal', filenames=tvm_lib + tvm_allvisible + crttest + cpptest + standalone_crt) }} + {{ m.upload_artifacts(tag='cpu-minimal', filenames=tvm_lib + tvm_allvisible + crttest + cpptest + standalone_crt + microtvm_template_projects) }} {% endcall %} diff --git a/ci/scripts/jenkins/s3.py b/ci/scripts/jenkins/s3.py index 63fbaac5fafc..8886adef7236 100755 --- a/ci/scripts/jenkins/s3.py +++ b/ci/scripts/jenkins/s3.py @@ -142,4 +142,7 @@ def s3(source: str, destination: str, recursive: bool) -> List[str]: show_md5(file) elif action == Action.UPLOAD: show_md5(item) + if Path(item).is_dir(): + if len(list(Path(item).glob("**/*"))) == 0: + raise RuntimeError(f"Cannot upload empty folder with name: {item}") s3(item, s3_path + "/" + item, recursive=Path(item).is_dir()) diff --git a/cmake/modules/CRT.cmake b/cmake/modules/CRT.cmake new file mode 100644 index 000000000000..518a613dc102 --- /dev/null +++ b/cmake/modules/CRT.cmake @@ -0,0 +1,74 @@ +# 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. + +if(USE_MICRO) + message(STATUS "Add CRT template project for microTVM") + + function(microtvm_add_crt) + list( + APPEND + CRT_TEMPLATE_FILE_COPY_JOBS + "src/runtime/crt/host microtvm_api_server.py -> crt" + "src/runtime/crt/host Makefile.template -> crt" + "src/runtime/crt crt_config-template.h -> crt" + "src/runtime/crt/host main.cc -> crt/src" + ) + + foreach(job_spec IN LISTS CRT_TEMPLATE_FILE_COPY_JOBS) + string(REPLACE " " ";" job_spec "${job_spec}") + list(LENGTH job_spec job_spec_length) + math(EXPR job_spec_length_mod "${job_spec_length} % 3") + if(NOT "${job_spec_length_mod}" EQUAL 1) + message( + FATAL_ERROR + "CRT copy job spec list length is ${job_spec_length}; parsed job spec is ${job_spec}" + ) + endif() + math(EXPR job_spec_stop "${job_spec_length} - 3") + + list(GET job_spec 0 job_src_base) + set(job_src_base "${CMAKE_CURRENT_SOURCE_DIR}/${job_src_base}") + foreach(copy_pattern_index RANGE 1 "${job_spec_stop}" 3) + list(GET job_spec ${copy_pattern_index} copy_pattern) + math(EXPR copy_dest_index "${copy_pattern_index} + 2") + list(GET job_spec ${copy_dest_index} copy_dest) + + file( + GLOB_RECURSE copy_files + RELATIVE "${job_src_base}" + "${job_src_base}/${copy_pattern}") + list(LENGTH copy_files copy_files_length) + if("${copy_files_length}" EQUAL 0) + message( + FATAL_ERROR + "CRT copy job matched 0 files: ${job_src_base}/${copy_pattern} -> ${copy_dest}" + ) + endif() + foreach(copy_src IN LISTS copy_files) + get_filename_component( + dest_path "${MICROTVM_TEMPLATE_PROJECTS}/${copy_dest}/${copy_src}" + ABSOLUTE) + tvm_micro_add_copy_file(crt_template_deps + ${job_src_base}/${copy_src} ${dest_path}) + endforeach() + endforeach() + endforeach() + + add_custom_target(crt DEPENDS ${crt_template_deps}) + endfunction() + + microtvm_add_crt() + +endif(USE_MICRO) diff --git a/cmake/modules/StandaloneCrt.cmake b/cmake/modules/StandaloneCrt.cmake index 2ca37f53d9f5..1d4e213ec71a 100644 --- a/cmake/modules/StandaloneCrt.cmake +++ b/cmake/modules/StandaloneCrt.cmake @@ -94,16 +94,12 @@ else() "src/runtime/crt/common *.c -> src/runtime/crt/common" "src/runtime/crt/graph_executor *.c -> src/runtime/crt/graph_executor" "src/runtime/crt/graph_executor_module *.c -> src/runtime/crt/graph_executor_module" - "src/runtime/crt/host *.cc -> template/host" - "src/runtime/crt/host *.py -> template/host" - "src/runtime/crt/host Makefile.template -> template/host" "src/runtime/crt/memory *.c -> src/runtime/crt/memory" "src/runtime/crt/microtvm_rpc_common *.cc -> src/runtime/crt/microtvm_rpc_common" "src/runtime/crt/microtvm_rpc_server *.cc -> src/runtime/crt/microtvm_rpc_server" "src/runtime/minrpc *.h -> src/runtime/minrpc" "src/support generic_arena.h -> src/support" "src/support ssize.h -> src/support" - "src/runtime/crt crt_config-template.h -> template" ) set(STANDALONE_CRT_BASE ${CMAKE_CURRENT_BINARY_DIR}/standalone_crt) diff --git a/python/tvm/micro/build.py b/python/tvm/micro/build.py index 92574ce2f8c2..e45054be98ca 100644 --- a/python/tvm/micro/build.py +++ b/python/tvm/micro/build.py @@ -94,9 +94,6 @@ def get_microtvm_template_projects(platform: str) -> str: if platform not in MicroTVMTemplateProject.list(): raise ValueError(f"platform {platform} is not supported.") - if platform == MicroTVMTemplateProject.CRT.value: - return os.path.join(get_standalone_crt_dir(), "template", "host") - microtvm_template_projects = None for path in libinfo.find_lib_path(): template_path = os.path.join(os.path.dirname(path), "microtvm_template_projects") diff --git a/python/tvm/testing/aot.py b/python/tvm/testing/aot.py index 30d3c78ae43b..5ddbdcabacc9 100644 --- a/python/tvm/testing/aot.py +++ b/python/tvm/testing/aot.py @@ -723,9 +723,9 @@ def run_and_check_body(base_path): include_path = os.path.join(base_path, "include") os.mkdir(include_path) - crt_root = tvm.micro.get_standalone_crt_dir() + crt_root = tvm.micro.get_microtvm_template_projects("crt") shutil.copy2( - os.path.join(crt_root, "template", "crt_config-template.h"), + os.path.join(crt_root, "crt_config-template.h"), os.path.join(include_path, "crt_config.h"), ) diff --git a/src/runtime/crt/host/microtvm_api_server.py b/src/runtime/crt/host/microtvm_api_server.py index b84abdf45985..e5b82f96b0ff 100644 --- a/src/runtime/crt/host/microtvm_api_server.py +++ b/src/runtime/crt/host/microtvm_api_server.py @@ -144,7 +144,7 @@ def generate_project(self, model_library_format_path, standalone_crt_dir, projec crt_config_dir = project_dir / "crt_config" crt_config_dir.mkdir() shutil.copy2( - os.path.join(os.path.dirname(__file__), "..", "crt_config-template.h"), + os.path.join(os.path.dirname(__file__), "crt_config-template.h"), os.path.join(crt_config_dir, "crt_config.h"), ) @@ -152,7 +152,8 @@ def generate_project(self, model_library_format_path, standalone_crt_dir, projec src_dir = os.path.join(project_dir, "src") os.mkdir(src_dir) shutil.copy2( - os.path.join(os.path.dirname(__file__), "main.cc"), os.path.join(src_dir, "main.cc") + os.path.join(os.path.dirname(__file__), "src", "main.cc"), + os.path.join(src_dir, "main.cc"), ) def build(self, options): diff --git a/tests/python/unittest/test_crt.py b/tests/python/unittest/test_crt.py index b11f7a5fac5e..83fa91af06c9 100644 --- a/tests/python/unittest/test_crt.py +++ b/tests/python/unittest/test_crt.py @@ -47,7 +47,7 @@ def _make_sess_from_op(temp_dir, op_name, sched, arg_bufs): def _make_session(temp_dir, mod): - template_project_dir = os.path.join(tvm.micro.get_standalone_crt_dir(), "template", "host") + template_project_dir = pathlib.Path(tvm.micro.get_microtvm_template_projects("crt")) project = tvm.micro.generate_project( template_project_dir, mod, temp_dir / "project", {"verbose": 1} ) diff --git a/tests/python/unittest/test_link_params.py b/tests/python/unittest/test_link_params.py index e5b8cd77445f..70caa99c9bca 100644 --- a/tests/python/unittest/test_link_params.py +++ b/tests/python/unittest/test_link_params.py @@ -345,7 +345,7 @@ def test_crt_link_params(linkable_dtype): assert len(factory.get_params().keys()) == 0 # NOTE: params became tir.constants temp_dir = tvm.contrib.utils.tempdir() - template_project_dir = os.path.join(tvm.micro.get_standalone_crt_dir(), "template", "host") + template_project_dir = tvm.micro.get_microtvm_template_projects("crt") project = tvm.micro.generate_project( template_project_dir, factory, temp_dir / "project", {"verbose": 1} )