diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index edd5d18af..4f5b2372d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -231,7 +231,8 @@ jobs: iree-install \ $PWD/llvm-aie \ /opt/xilinx/xrt \ - /opt/Xilinx/Vitis/2024.2 + /opt/Xilinx/Vitis/2024.2 \ + --reset-npu-between-runs - name: Printing IR from aie2xclbin run: | diff --git a/build_tools/ci/cpu_comparison/run_test.py b/build_tools/ci/cpu_comparison/run_test.py index b0cf365ab..035a3ee00 100755 --- a/build_tools/ci/cpu_comparison/run_test.py +++ b/build_tools/ci/cpu_comparison/run_test.py @@ -261,10 +261,16 @@ def __init__( self.xrt_hash = "undetermined" self.xrt_release = "undetermined" self.peano_commit_hash = "undetermined" - xrt_bin_dir = xrt_dir / "bin" - xrt_smi_exe = xrt_bin_dir / "xrt-smi" + xrt_bin_dir = xrt_dir + if platform.system() != "Windows": + xrt_bin_dir /= "bin" + xrt_smi_exe = xrt_bin_dir / ( + "xrt-smi" + ".exe" if platform.system() == "Windows" else "" + ) if not xrt_smi_exe.exists(): - xrt_smi_exe = xrt_bin_dir / "xbutil" + xrt_smi_exe = xrt_bin_dir / ( + "xbutil" + ".exe" if platform.system() == "Windows" else "" + ) if not xrt_smi_exe.exists(): raise RuntimeError(f"Neither xrt-smi nor xbutil found in {xrt_bin_dir}") @@ -665,7 +671,7 @@ def run(self, config): ) -def getTestPartition(): +def get_test_partition(): return [ConvolutionSet(), MatmulSet(), SmokeSet()] @@ -730,9 +736,10 @@ def all_tests( verify_determinism() # Verify a very basic script runs before running the more complex tests - shell_out(["pwd"], verbose=config.verbose) + if platform.system() != "Windows": + shell_out(["pwd"], verbose=config.verbose) - partition = getTestPartition() + partition = get_test_partition() partition_names = [p.name for p in partition] map_to_partition = {p.name: p for p in partition} if "All" in test_set: @@ -773,54 +780,48 @@ def all_tests( parser.add_argument("iree_install_dir", type=abs_path) parser.add_argument("peano_install_dir", type=abs_path) parser.add_argument("xrt_dir", type=abs_path) - parser.add_argument("vitis_dir", type=abs_path) + parser.add_argument("--vitis-dir", type=abs_path) # TODO(newling) make bool options boolean, not integer (tried but had issues) parser.add_argument( - "--return_on_fail", + "--return-on-fail", nargs="?", default=1, type=int, - help=( - "If 0, then the script will continue running even if a test fails, " - "enumerating all failures. Otherwise the script will exit on the first failure." + help=dedent( + """ + If 0, then the script will continue running even if a test fails, + enumerating all failures. Otherwise the script will exit on the first failure. + """ ), ) - parser.add_argument( - "--verbose", - nargs="?", - default=1, - type=int, - help="If 0, then print statements are suppressed, otherwise they are printed.", - ) + parser.add_argument("--verbose", action="store_true") parser.add_argument( - "--reset_npu_between_runs", - nargs="?", - default=1, - type=int, + "--reset-npu-between-runs", + action="store_true", help=( - "If 0 then the NPU is not reset between runs, otherwise it is reset. " + "If passed then the NPU is not reset between runs, otherwise it is reset. " "Resetting between runs can in theory help avoid certain types of " "errors in parts of the stack which these tests are not designed to catch." ), ) parser.add_argument( - "--do_not_run_aie", - nargs="?", - default=0, - type=int, - help=( - "If 1, then the AIE backend will not be run. This is useful for " - "ensuring that everything up to the AIE run and numerical comparison " - "is working correctly, for example if you are not on a device with " - "working AIE HW and runtime." + "--do-not-run-aie", + action="store_true", + help=dedent( + """ + If passed, then the AIE backend will not be run. This is useful for + ensuring that everything up to the AIE run and numerical comparison + is working correctly, for example if you are not on a device with + working AIE HW and runtime." + """ ), ) - partition = getTestPartition() + partition = get_test_partition() partition_names = [p.name for p in partition] partition_names_and_all = partition_names + ["All"] help_string = ( @@ -829,19 +830,22 @@ def all_tests( ) parser.add_argument( - "--test_set", + "--test-set", type=str, help=help_string, default="All", ) parser.add_argument( - "--additional_aie_compilation_flags", + "--additional-aie-compilation-flags", type=str, - help=( - "Additional flags to pass to the AIE compiler, for all tests. " - "Example, do print the IR between passes during compilation you might have: " - ' --additional_aie_compilation_flags="--mlir-print-ir-before-all --mlir-print-ir-module-scope --aie2xclbin-print-ir-before-all --aie2xclbin-print-ir-module-scope"' + help=dedent( + """ + Additional flags to pass to the AIE compiler, for all tests. + Example, do print the IR between passes during compilation you might have: + --additional_aie_compilation_flags="--mlir-print-ir-before-all --mlir-print-ir-module-scope + --aie2xclbin-print-ir-before-all --aie2xclbin-print-ir-module-scope"' + """ ), default="", ) diff --git a/build_tools/download_peano.sh b/build_tools/download_peano.sh index a8c41957b..8c20a7560 100644 --- a/build_tools/download_peano.sh +++ b/build_tools/download_peano.sh @@ -1,5 +1,5 @@ #!/bin/bash RELEASE=19.0.0.2024081918+69415c19 -pip download -q llvm_aie==$RELEASE -f https://github.com/Xilinx/llvm-aie/releases/expanded_assets/nightly -unzip -q llvm_aie*whl +pip download llvm_aie==$RELEASE -f https://github.com/Xilinx/llvm-aie/releases/expanded_assets/nightly +unzip llvm_aie*whl diff --git a/cmake/iree_aie_xrt.cmake b/cmake/iree_aie_xrt.cmake index 0811fbda4..5879e21cd 100644 --- a/cmake/iree_aie_xrt.cmake +++ b/cmake/iree_aie_xrt.cmake @@ -4,7 +4,7 @@ # See https://llvm.org/LICENSE.txt for license information. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -if(TARGET iree-aie-xclbinutil) +if(TARGET iree_aie_xrt_iree-aie-xclbinutil) return() endif() @@ -134,32 +134,38 @@ list(REMOVE_ITEM _xclbinutil_srcs "${_xclbinutil_source_dir}/SectionSmartNic.cxx # and then --add-replace-section:MEM_TOPOLOGY won't work... # XRT/src/runtime_src/tools/xclbinutil/SectionMemTopology.cxx#L26-L41 # TODO(max): and for whatever reason -WL,--whole-archive doesn't work -add_executable(iree-aie-xclbinutil ${_xclbinutil_srcs}) +set(IREE_PACKAGE_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}") +set(IREE_PACKAGE_ROOT_PREFIX "iree::aie::xrt") +iree_cc_binary( + NAME + # if you rename this be sure to update the if(...) return up top + # otherwise this script will be entered twice and you'll get a confusing error like + # "can't do add_executable; target already exists" + iree-aie-xclbinutil + SRCS + ${_xclbinutil_srcs} + COPTS + $<$:-fexceptions -frtti> + $<$:/EHsc /GR> + DEFINES + BOOST_BIND_GLOBAL_PLACEHOLDERS + INSTALL_COMPONENT + IREETools-Runtime + PUBLIC +) -target_compile_definitions(iree-aie-xclbinutil - PRIVATE - -DBOOST_BIND_GLOBAL_PLACEHOLDERS) set(THREADS_PREFER_PTHREAD_FLAG ON) -target_link_libraries(iree-aie-xclbinutil +target_link_libraries(iree_aie_xrt_iree-aie-xclbinutil PRIVATE Threads::Threads $ $<$:$>) -target_include_directories(iree-aie-xclbinutil +target_include_directories(iree_aie_xrt_iree-aie-xclbinutil PRIVATE ${XRT_BINARY_DIR}/gen ${IREE_XRT_SOURCE_DIR}/runtime_src/core/include ${_xclbinutil_source_dir}) -target_compile_options(iree-aie-xclbinutil - PRIVATE - $<$:-fexceptions -frtti> - $<$:/EHsc /GR>) -set_target_properties(iree-aie-xclbinutil +set_target_properties(iree_aie_xrt_iree-aie-xclbinutil PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/tools") -iree_install_targets( - TARGETS iree-aie-xclbinutil - COMPONENT IREETools-Runtime - EXPORT_SET Runtime -) # ############################################################################## # xrt_coreutil diff --git a/compiler/plugins/target/AMD-AIE/iree-amd-aie/Target/CMakeLists.txt b/compiler/plugins/target/AMD-AIE/iree-amd-aie/Target/CMakeLists.txt index 3c7cd4d64..1d9e94123 100644 --- a/compiler/plugins/target/AMD-AIE/iree-amd-aie/Target/CMakeLists.txt +++ b/compiler/plugins/target/AMD-AIE/iree-amd-aie/Target/CMakeLists.txt @@ -21,7 +21,7 @@ iree_cc_library( ) if(IREE_AMD_AIE_ENABLE_XRT_DRIVER) - add_dependencies(iree_target_amd-aie_Target_AIETargets iree-aie-xclbinutil) + add_dependencies(iree_target_amd-aie_Target_AIETargets iree_aie_xrt_iree-aie-xclbinutil) endif() iree_cc_library( diff --git a/compiler/plugins/target/AMD-AIE/iree-amd-aie/Target/XCLBinGen.cpp b/compiler/plugins/target/AMD-AIE/iree-amd-aie/Target/XCLBinGen.cpp index f2bdc6a33..87271a888 100644 --- a/compiler/plugins/target/AMD-AIE/iree-amd-aie/Target/XCLBinGen.cpp +++ b/compiler/plugins/target/AMD-AIE/iree-amd-aie/Target/XCLBinGen.cpp @@ -7,7 +7,6 @@ #include "XCLBinGen.h" #include -#include #include #include #include @@ -193,7 +192,10 @@ FailureOr findVitis(std::optional &vitisDir) { static FailureOr findAMDAIETool(std::string toolName, const Path &amdAIEInstallDir) { - Path toolBinExe = ""; +#if defined(_WIN32) + toolName += ".exe"; +#endif // _WIN32 + Path toolBinExe; if (!amdAIEInstallDir.empty()) { toolBinExe = amdAIEInstallDir / toolName; if (std::filesystem::exists(toolBinExe)) return toolBinExe; @@ -209,7 +211,7 @@ static FailureOr findAMDAIETool(std::string toolName, if (std::filesystem::exists(toolBinExe)) return toolBinExe; llvm::errs() << "Could not find " << toolName - << ". Check your --iree-amd-aie-install-dir flag"; + << ". Check your --iree-amd-aie-install-dir flag\n"; return failure(); } @@ -290,12 +292,30 @@ std::optional dumpStrToDisk(const std::string &payload, return {}; } +bool hasEnding(std::string const &fullString, std::string const &ending) { + if (fullString.length() >= ending.length()) { + return fullString.compare(fullString.length() - ending.length(), + ending.length(), ending) == 0; + } + return false; +} + // Returns either: // -- the output of running the tool, if run without failure, or // -- an empty optional, if the tool fails to run. -static std::optional runTool( - const std::string &program, const std::vector &args, +LogicalResult runTool( + const std::string &program_, const std::vector &args, bool verbose, std::optional> env = std::nullopt) { + std::string program; +#if defined(_WIN32) + if (hasEnding(program_, ".exe")) { + program = program_; + } else { + program = program_ + ".exe"; + } +#else + program = programs_; +#endif // _WIN32 if (verbose) { llvm::outs() << "\nRun: "; if (env) @@ -308,14 +328,11 @@ static std::optional runTool( // Check that 'program' is a valid path, if not, fail immediately. if (!std::filesystem::exists(program)) { llvm::errs() << "Program " << program << " does not exist\n"; - return {}; + return failure(); } // Run the program, piping any output to a temporary file (we only want to // print to terminal if verbose is true). - std::string errMsg; - sys::ProcessStatistics stats; - std::optional optStats(stats); SmallVector pArgs = {program}; pArgs.append(args.begin(), args.end()); SmallVector temporaryPath; @@ -327,20 +344,34 @@ static std::optional runTool( if (errorCode) { llvm::errs() << "Failed to create temporary file: " << errorCode.message() << "\n"; - return {}; + return failure(); } } std::string temporaryPathStr = std::string(temporaryPath.begin(), temporaryPath.size()); StringRef temporaryPathRef(temporaryPathStr); - auto tp = std::optional(temporaryPathRef); llvm::SmallVector envSmallVec; if (env) envSmallVec.append(env->begin(), env->end()); - int result = sys::ExecuteAndWait(program, pArgs, envSmallVec, - /* redirects */ {tp, tp, tp}, 0, 0, &errMsg, - nullptr, &optStats); + SmallVector> redirects; +#ifdef _WIN32 + redirects = {{}, {}, {}}; +#else + auto tp = std::optional(temporaryPathRef); + redirects = {tp, tp, tp}; +#endif + + bool executionFailed; + std::string errMsg; + sys::ProcessStatistics stats; + std::optional optStats(stats); + int result = sys::ExecuteAndWait(program, pArgs, std::nullopt, + /* redirects */ redirects, + /*SecondsToWait*/ 10, /*MemoryLimit*/ 0, + &errMsg, &executionFailed, &optStats); + +#ifndef _WIN32 auto maybeOutputFromFile = [&]() -> std::optional { std::ifstream t(temporaryPathRef.str()); std::stringstream buffer; @@ -354,9 +385,9 @@ static std::optional runTool( if (!maybeOutputFromFile) { llvm::errs() << "Failed to open temporary file " << temporaryPathRef.str() << "\n"; - return {}; } auto outputFromFile = maybeOutputFromFile.value(); +#endif if (verbose) { auto totalTime = std::chrono::duration_cast>( @@ -366,17 +397,21 @@ static std::optional runTool( llvm::outs() << "\n" << exitStatusStr << " in totalTime " << totalTime << " [s]. Exit code=" << result << "\n"; +#ifndef _WIN32 llvm::outs() << outputFromFile << "\n"; +#endif } - if (result != 0) { + if (result) { llvm::errs() << "Failed to run tool: " << program << ". Error: '" << errMsg - << "'\n" - << outputFromFile; - return {}; + << "'\n"; +#ifndef _WIN32 + llvm::errs() << outputFromFile; +#endif + return failure(); } - return outputFromFile; + return success(); } static LogicalResult assembleFileUsingChess( @@ -391,7 +426,7 @@ static LogicalResult assembleFileUsingChess( args.emplace_back("-o"); args.emplace_back(outputFile); std::vector env = makeChessEnv(vitisDir); - if (!runTool(xChessCCExe, args, verbose, env)) { + if (failed(runTool(xChessCCExe, args, verbose, env))) { llvm::errs() << "Failed to assemble " << inputFile << " with chess"; return failure(); } @@ -448,11 +483,7 @@ static LogicalResult assembleFileUsingPeano( args.emplace_back("-o"); args.emplace_back(outputFile); if (verbose) args.emplace_back("-v"); - if (!runTool((peanoDir / "bin" / "clang").string(), args, verbose)) { - llvm::errs() << "Failed to assemble " << outputFile << ".o with peano"; - return failure(); - } - return success(); + return runTool((peanoDir / "bin" / "clang").string(), args, verbose); } static_assert(std::is_same_v env = makeChessEnv(*vitisDir); - if (!runTool(xChessCCExe, chessArgs, verbose, env)) { - llvm::errs() << "Failed to link with xbridge"; - return failure(); - } - } else { - Path ldscriptPath = tempDir / (elfFileName + ".ld"); - { - auto ldscriptOutput = - openOutputFile(ldscriptPath.string(), &errorMessage); - if (!ldscriptOutput) { - llvm::errs() << "Failed to open ldscript file because: " - << errorMessage; - return failure(); - } - if (failed(mlir::iree_compiler::AMDAIE::AIETranslateToLdScript( - moduleOp, ldscriptOutput->os(), col, row))) { - llvm::errs() << "failed to generate ld script for core (" << col - << "," << row << ")"; - return failure(); - } - ldscriptOutput->keep(); - } + return runTool(xChessCCExe, chessArgs, verbose, env); + } - std::string targetLower = StringRef(targetArch).lower(); - std::vector flags; - flags.emplace_back(objFile); - if (ukernel && (ukernel == "mm" || ukernel == "all")) { - flags.emplace_back(mmObjectFilePath->string()); + Path ldscriptPath = tempDir / (elfFileName + ".ld"); + { + auto ldscriptOutput = + openOutputFile(ldscriptPath.string(), &errorMessage); + if (!ldscriptOutput) { + llvm::errs() << "Failed to open ldscript file because: " + << errorMessage; + return failure(); } - flags.emplace_back("--target=" + targetLower + "-none-unknown-elf"); - flags.emplace_back("-Wl,--gc-sections"); - flags.emplace_back("-Wl,-T," + ldscriptPath.string()); - flags.emplace_back("-o"); - flags.emplace_back(elfFile.string()); - if (verbose) flags.emplace_back("-v"); - // we run clang (ie cc) so that libc, libm, crt0/1 paths are injected - // automatically into the ld.lld invocation - if (!runTool((peanoDir / "bin" / "clang").string(), flags, verbose)) { - llvm::errs() << "failed to link elf file for core(" << col << "," << row - << ")"; + if (failed(mlir::iree_compiler::AMDAIE::AIETranslateToLdScript( + moduleOp, ldscriptOutput->os(), col, row))) { + llvm::errs() << "failed to generate ld script for core (" << col << "," + << row << ")\n"; return failure(); } + ldscriptOutput->keep(); } + + std::string targetLower = StringRef(targetArch).lower(); + std::vector flags; + flags.emplace_back(objFile); + if (ukernel && (ukernel == "mm" || ukernel == "all")) { + flags.emplace_back(mmObjectFilePath->string()); + } + flags.emplace_back("--target=" + targetLower + "-none-unknown-elf"); + flags.emplace_back("-Wl,--gc-sections"); + flags.emplace_back("-Wl,-T," + ldscriptPath.string()); + +#ifdef _WIN32 + // disable crt + flags.emplace_back("-nostartfiles"); + flags.emplace_back((peanoDir / "lib" / "crt0.o").string()); + flags.emplace_back((peanoDir / "lib" / "crt1.o").string()); + flags.emplace_back("-Wl,-L" + (peanoDir / "lib").string()); +#endif + + flags.emplace_back("-o"); + flags.emplace_back(elfFile.string()); + if (verbose) flags.emplace_back("-v"); + // we run clang (ie cc) so that libc, libm, crt0/1 paths are injected + // automatically into the ld.lld invocation + return runTool((peanoDir / "bin" / "clang").string(), flags, verbose); } - return success(); } static LogicalResult generateCDO(MLIRContext *context, ModuleOp moduleOp, @@ -890,75 +922,68 @@ static LogicalResult generateXCLBin( FailureOr xclbinutilBin = findAMDAIETool("iree-aie-xclbinutil", amdAIEInstallDir); - { - if (inputXclbin) { - // Create aie_partition.json. - Path aieInputPartitionJsonFile = tempDir / "aie_input_partition.json"; - std::string inputPartArg = - "AIE_PARTITION:JSON:" + aieInputPartitionJsonFile.string(); - std::vector inputFlags{"--dump-section", inputPartArg, - "--force", "--input", *inputXclbin}; - - if (!succeeded(xclbinutilBin) || - !runTool(xclbinutilBin.value().string(), inputFlags, verbose)) { - llvm::errs() << "failed to execute xclbinutil"; - return failure(); - } - auto aieInputPartitionOut = - openInputFile(aieInputPartitionJsonFile.string(), &errorMessage); - if (!aieInputPartitionOut) { - llvm::errs() << "failed to open aie_input_partition.json because: " - << errorMessage; - return failure(); - } - Expected aieInputPartitionOutValue = - llvm::json::parse(aieInputPartitionOut->getBuffer()); - json::Array *aieInputPartionPDIs; - aieInputPartionPDIs = aieInputPartitionOutValue->getAsObject() - ->getObject("aie_partition") - ->getArray("PDIs"); - auto aiePartitionOut = - openInputFile(aiePartitionJsonFile.string(), &errorMessage); - if (!aiePartitionOut) { - llvm::errs() << "failed to open aie aie_input_partition.json for " - "output because: " - << errorMessage; - return failure(); - } - llvm::Expected aiePartitionOutValue = - llvm::json::parse(aiePartitionOut->getBuffer()); - json::Array *aiePartionPDIs; - aiePartionPDIs = aiePartitionOutValue->getAsObject() - ->getObject("aie_partition") - ->getArray("PDIs"); - aieInputPartionPDIs->insert(aieInputPartionPDIs->end(), - aiePartionPDIs->begin(), - aiePartionPDIs->end()); - // rewrite aie partion json file - if (auto maybeErr = - dumpStrToDisk(formatv("{0:2}", *aieInputPartitionOutValue), - aiePartitionJsonFile.string()); - maybeErr.has_value()) { - llvm::errs() - << "failed to dump to disk aie_input_partition.json because: " - << errorMessage; - return failure(); - } - flags.insert(flags.end(), {"--input", *inputXclbin}); - } else { - flags.insert(flags.end(), {"--add-replace-section", memArg}); - } - flags.insert(flags.end(), {"--add-kernel", kernelsJsonFile.string(), - "--add-replace-section", partArg, "--force", - "--output", std::string(Output)}); + if (failed(xclbinutilBin)) return xclbinutilBin; + + if (inputXclbin) { + // Create aie_partition.json. + Path aieInputPartitionJsonFile = tempDir / "aie_input_partition.json"; + std::string inputPartArg = + "AIE_PARTITION:JSON:" + aieInputPartitionJsonFile.string(); + std::vector inputFlags{"--dump-section", inputPartArg, + "--force", "--input", *inputXclbin}; - if (!succeeded(xclbinutilBin) || - !runTool(xclbinutilBin.value().string(), flags, verbose)) { + if (failed(runTool(xclbinutilBin.value().string(), inputFlags, verbose))) { llvm::errs() << "failed to execute xclbinutil"; return failure(); } + auto aieInputPartitionOut = + openInputFile(aieInputPartitionJsonFile.string(), &errorMessage); + if (!aieInputPartitionOut) { + llvm::errs() << "failed to open aie_input_partition.json because: " + << errorMessage; + return failure(); + } + Expected aieInputPartitionOutValue = + llvm::json::parse(aieInputPartitionOut->getBuffer()); + json::Array *aieInputPartionPDIs; + aieInputPartionPDIs = aieInputPartitionOutValue->getAsObject() + ->getObject("aie_partition") + ->getArray("PDIs"); + auto aiePartitionOut = + openInputFile(aiePartitionJsonFile.string(), &errorMessage); + if (!aiePartitionOut) { + llvm::errs() << "failed to open aie aie_input_partition.json for " + "output because: " + << errorMessage; + return failure(); + } + llvm::Expected aiePartitionOutValue = + llvm::json::parse(aiePartitionOut->getBuffer()); + json::Array *aiePartionPDIs; + aiePartionPDIs = aiePartitionOutValue->getAsObject() + ->getObject("aie_partition") + ->getArray("PDIs"); + aieInputPartionPDIs->insert(aieInputPartionPDIs->end(), + aiePartionPDIs->begin(), aiePartionPDIs->end()); + // rewrite aie partion json file + if (auto maybeErr = + dumpStrToDisk(formatv("{0:2}", *aieInputPartitionOutValue), + aiePartitionJsonFile.string()); + maybeErr.has_value()) { + llvm::errs() + << "failed to dump to disk aie_input_partition.json because: " + << errorMessage; + return failure(); + } + flags.insert(flags.end(), {"--input", *inputXclbin}); + } else { + flags.insert(flags.end(), {"--add-replace-section", memArg}); } - return success(); + flags.insert(flags.end(), {"--add-kernel", kernelsJsonFile.string(), + "--add-replace-section", partArg, "--force", + "--output", std::string(Output)}); + + return runTool(xclbinutilBin.value().string(), flags, verbose); } static std::string chesshack(const std::string &input) { @@ -1053,13 +1078,17 @@ static LogicalResult generateUnifiedObject( } ModuleOp copy = moduleOp.clone(); - if (failed(pm.run(copy))) - return moduleOp.emitOpError("Failed to lower to LLVM"); + if (failed(pm.run(copy))) { + llvm::errs() << "Failed to lower to LLVM"; + return failure(); + } llvm::LLVMContext llvmContext; auto llvmModule = translateModuleToLLVMIR(copy, llvmContext); - if (!llvmModule) - return moduleOp.emitOpError("Failed to translate module to LLVMIR"); + if (!llvmModule) { + llvm::errs() << "Failed to translate module to LLVMIR"; + return failure(); + } std::string inputLLStr; { llvm::raw_string_ostream rso(inputLLStr); @@ -1101,18 +1130,18 @@ static LogicalResult generateUnifiedObject( std::vector peanoArgs = makePeanoOptArgs(); args.reserve(args.size() + peanoArgs.size()); args.insert(args.end(), peanoArgs.begin(), peanoArgs.end()); - if (!runTool(peanoOptBin.string(), args, verbose)) { + if (failed(runTool(peanoOptBin.string(), args, verbose))) { llvm::errs() << "Failed to optimize ll with peano"; return failure(); } - if (!runTool( + if (failed(runTool( peanoLLCBin.string(), {OptLLVMIRFile.string(), "-O2", "--march=" + StringRef(targetArch).lower(), "--function-sections", "--filetype=obj", "-o", std::string(outputFile)}, - verbose)) { - llvm::errs() << "Failed to assemble ll with peano"; + verbose))) { + llvm::errs() << "Failed to assemble ll with peano\n"; return failure(); } } @@ -1137,22 +1166,26 @@ LogicalResult aie2xclbin( // generateNPUInstructions pm.addNestedPass( mlir::iree_compiler::AMDAIE::createAMDAIEDmaToNpuPass()); - if (failed(pm.run(moduleOp))) - return moduleOp.emitOpError(": NPU Instruction pipeline failed"); + if (failed(pm.run(moduleOp))) { + llvm::errs() << ": NPU Instruction pipeline failed"; + return failure(); + } std::optional> npuInstructions = cast( (*moduleOp.getOps().begin()) ->getAttr("npu_instructions")) .tryGetAsArrayRef(); - if (!npuInstructions) - return moduleOp.emitOpError(": No NPU instructions in device op"); + if (!npuInstructions) { + llvm::errs() << ": No NPU instructions in device op\n"; + return failure(); + } std::string errorMessage; auto output = openOutputFile(outputNPU, &errorMessage); if (!output) { llvm::errs() << "Failed to open npu_instructions.txt for writing because: " - << errorMessage; + << errorMessage << "\n"; return failure(); } for (auto w : *npuInstructions) output->os() << llvm::format("%08X\n", w); @@ -1162,22 +1195,30 @@ LogicalResult aie2xclbin( if (failed(generateUnifiedObject( ctx, moduleOp, unifiedObj.string(), printIRBeforeAll, printIRAfterAll, printIRModuleScope, timing, useChess, verbose, tempDir, vitisDir, - targetArch, peanoDir))) - return moduleOp.emitOpError("Failed to generate unified object"); + targetArch, peanoDir))) { + llvm::errs() << "Failed to generate unified object\n"; + return failure(); + } if (failed(generateCoreElfFiles(moduleOp, unifiedObj.string(), tempDir, useChess, vitisDir, targetArch, verbose, - peanoDir, ukernel))) - return moduleOp.emitOpError("Failed to generate core ELF file(s)"); + peanoDir, ukernel))) { + llvm::errs() << "Failed to generate core ELF file(s)\n"; + return failure(); + } if (failed(generateCDO(ctx, moduleOp, printIRBeforeAll, printIRAfterAll, - printIRModuleScope, timing, tempDir))) - return moduleOp.emitOpError("Failed to generate CDO"); + printIRModuleScope, timing, tempDir))) { + llvm::errs() << "Failed to generate CDO\n"; + return failure(); + } if (failed(generateXCLBin(outputXCLBin, tempDir, xclBinKernelID, xclBinKernelName, xclBinInstanceName, - amdAIEInstallDir, verbose, InputXCLBin))) - return moduleOp.emitOpError("Failed to generate XCLBin"); + amdAIEInstallDir, verbose, InputXCLBin))) { + llvm::errs() << "Failed to generate XCLBin\n"; + return failure(); + } return success(); } diff --git a/runtime/src/iree-amd-aie/aie_runtime/iree_aie_configure.cc b/runtime/src/iree-amd-aie/aie_runtime/iree_aie_configure.cc index 4aba9c188..7feebe07d 100644 --- a/runtime/src/iree-amd-aie/aie_runtime/iree_aie_configure.cc +++ b/runtime/src/iree-amd-aie/aie_runtime/iree_aie_configure.cc @@ -213,6 +213,16 @@ LogicalResult addElfToTile(const AMDAIEDeviceModel &deviceModel, const TileLoc &tileLoc, const Path &elfPath, bool aieSim) { auto devInst = const_cast(&deviceModel.devInst); + // this isn't the case elsewhere but for whatever reason + // fopen (what XAie_LoadElf ultimately calls) braeks for >=256 +#ifdef _WIN32 + if (elfPath.string().size() >= 256) { + llvm::errs() << "Windows paths must be less than 256 chars for elf loading " + "to work (seriously):" + << elfPath.string() << "\n"; + return failure(); + } +#endif TRY_XAIE_API_LOGICAL_RESULT(XAie_LoadElf, devInst, tileLoc, elfPath.string().c_str(), /*loadSym*/ aieSim); diff --git a/runtime/src/iree-amd-aie/aie_runtime/iree_aie_runtime.h b/runtime/src/iree-amd-aie/aie_runtime/iree_aie_runtime.h index c485bb497..774549862 100644 --- a/runtime/src/iree-amd-aie/aie_runtime/iree_aie_runtime.h +++ b/runtime/src/iree-amd-aie/aie_runtime/iree_aie_runtime.h @@ -414,7 +414,7 @@ static_assert(XAIE_OK == 0); LLVM_DEBUG(llvm::dbgs().flush()); \ if (auto r = API(__VA_ARGS__)) \ llvm::report_fatal_error(llvm::Twine(#API " failed with ") + \ - to_string(r)); \ + to_string(r) + "\n"); \ } while (0) #define TRY_XAIE_API_LOGICAL_RESULT(API, ...) \ @@ -424,7 +424,7 @@ static_assert(XAIE_OK == 0); LLVM_DEBUG(llvm::dbgs() << "\n"); \ LLVM_DEBUG(llvm::dbgs().flush()); \ if (auto r = API(__VA_ARGS__)) { \ - llvm::errs() << #API " failed with " << r; \ + llvm::errs() << #API " failed with " << r << "\n"; \ return failure(); \ } \ } while (0)