/* * Copyright (C) 2020 Intel Corporation * * SPDX-License-Identifier: MIT * */ #include "shared/offline_compiler/source/ocloc_fatbinary.h" #include "shared/offline_compiler/source/ocloc_arg_helper.h" #include "shared/offline_compiler/source/offline_compiler.h" #include "shared/offline_compiler/source/utilities/safety_caller.h" #include "shared/source/device_binary_format/ar/ar_encoder.h" #include "shared/source/helpers/file_io.h" #include "shared/source/helpers/hw_info.h" #include "compiler_options.h" #include "igfxfmid.h" #include #include #include #include namespace NEO { bool requestedFatBinary(int argc, const char *argv[]) { for (int argIndex = 1; argIndex < argc; argIndex++) { const auto &currArg = argv[argIndex]; const bool hasMoreArgs = (argIndex + 1 < argc); if ((ConstStringRef("-device") == currArg) && hasMoreArgs) { ConstStringRef deviceArg(argv[argIndex + 1], strlen(argv[argIndex + 1])); return deviceArg.contains("*") || deviceArg.contains("-") || deviceArg.contains(",") || deviceArg.contains("gen"); } } return false; } std::vector getAllSupportedTargetPlatforms() { return std::vector{ALL_SUPPORTED_PRODUCT_FAMILIES}; } std::vector toProductNames(const std::vector &productIds) { std::vector ret; for (auto prodId : productIds) { ret.push_back(ConstStringRef(hardwarePrefix[prodId], strlen(hardwarePrefix[prodId]))); } return ret; } PRODUCT_FAMILY asProductId(ConstStringRef product, const std::vector &allSupportedPlatforms) { for (auto family : allSupportedPlatforms) { if (product == hardwarePrefix[family]) { return family; } } return IGFX_UNKNOWN; } GFXCORE_FAMILY asGfxCoreId(ConstStringRef core) { ConstStringRef coreIgnoreG(core.begin() + 1, core.size() - 1); for (unsigned int coreId = 0; coreId < IGFX_MAX_CORE; ++coreId) { if (nullptr == familyName[coreId]) { continue; } if (ConstStringRef(familyName[coreId] + 1, strlen(familyName[coreId]) - 1) == coreIgnoreG) { return static_cast(coreId); } } return IGFX_UNKNOWN_CORE; } void appendPlatformsForGfxCore(GFXCORE_FAMILY core, const std::vector &allSupportedPlatforms, std::vector &out) { for (auto family : allSupportedPlatforms) { if (core == hardwareInfoTable[family]->platform.eRenderCoreFamily) { out.push_back(family); } } } std::vector getTargetPlatformsForFatbinary(ConstStringRef deviceArg, OclocArgHelper *argHelper) { std::vector allSupportedPlatforms = getAllSupportedTargetPlatforms(); if (deviceArg == "*") { return toProductNames(allSupportedPlatforms); } auto genArg = ConstStringRef("gen"); std::vector requestedPlatforms; auto sets = CompilerOptions::tokenize(deviceArg, ','); for (auto set : sets) { if (set.contains("-")) { auto range = CompilerOptions::tokenize(deviceArg, '-'); if (range.size() > 2) { argHelper->printf("Invalid range : %s - should be from-to or -to or from-\n", set.str().c_str()); return {}; } if (range.size() == 1) { // open range , from-max or min-to if (range[0].contains("gen")) { auto coreId = asGfxCoreId(range[0]); if (IGFX_UNKNOWN_CORE == coreId) { argHelper->printf("Unknown device : %s\n", set.str().c_str()); return {}; } if ('-' == set[0]) { // to unsigned int coreIt = IGFX_UNKNOWN_CORE; ++coreIt; while (coreIt <= static_cast(coreId)) { appendPlatformsForGfxCore(static_cast(coreIt), allSupportedPlatforms, requestedPlatforms); ++coreIt; } } else { // from unsigned int coreIt = coreId; while (coreIt < static_cast(IGFX_MAX_CORE)) { appendPlatformsForGfxCore(static_cast(coreIt), allSupportedPlatforms, requestedPlatforms); ++coreIt; } } } else { auto prodId = asProductId(range[0], allSupportedPlatforms); if (IGFX_UNKNOWN == prodId) { argHelper->printf("Unknown device : %s\n", range[0].str().c_str()); return {}; } auto prodIt = std::find(allSupportedPlatforms.begin(), allSupportedPlatforms.end(), prodId); assert(prodIt != allSupportedPlatforms.end()); if ('-' == set[0]) { // to requestedPlatforms.insert(requestedPlatforms.end(), allSupportedPlatforms.begin(), prodIt + 1); } else { // from requestedPlatforms.insert(requestedPlatforms.end(), prodIt, allSupportedPlatforms.end()); } } } else { if (range[0].contains("gen")) { if (false == range[1].contains("gen")) { argHelper->printf("Ranges mixing platforms and gfxCores is not supported : %s - should be genFrom-genTo or platformFrom-platformTo\n", set.str().c_str()); return {}; } auto coreFrom = asGfxCoreId(range[0]); auto coreTo = asGfxCoreId(range[1]); if (IGFX_UNKNOWN_CORE == coreFrom) { argHelper->printf("Unknown device : %s\n", set.str().c_str()); return {}; } if (IGFX_UNKNOWN_CORE == coreTo) { argHelper->printf("Unknown device : %s\n", set.str().c_str()); return {}; } if (coreFrom > coreTo) { std::swap(coreFrom, coreTo); } while (coreFrom <= coreTo) { appendPlatformsForGfxCore(static_cast(coreFrom), allSupportedPlatforms, requestedPlatforms); coreFrom = static_cast(static_cast(coreFrom) + 1); } } else { auto platformFrom = asProductId(range[0], allSupportedPlatforms); auto platformTo = asProductId(range[1], allSupportedPlatforms); if (IGFX_UNKNOWN == platformFrom) { argHelper->printf("Unknown device : %s\n", set.str().c_str()); return {}; } if (IGFX_UNKNOWN == platformTo) { argHelper->printf("Unknown device : %s\n", set.str().c_str()); return {}; } if (platformFrom > platformTo) { std::swap(platformFrom, platformTo); } auto from = std::find(allSupportedPlatforms.begin(), allSupportedPlatforms.end(), platformFrom); auto to = std::find(allSupportedPlatforms.begin(), allSupportedPlatforms.end(), platformTo) + 1; requestedPlatforms.insert(requestedPlatforms.end(), from, to); } } } else if (set.contains("gen")) { if (set.size() == genArg.size()) { argHelper->printf("Invalid gen-based device : %s - gen should be followed by a number\n", set.str().c_str()); } else { auto coreId = asGfxCoreId(set); if (IGFX_UNKNOWN_CORE == coreId) { argHelper->printf("Unknown device : %s\n", set.str().c_str()); return {}; } appendPlatformsForGfxCore(coreId, allSupportedPlatforms, requestedPlatforms); } } else { auto prodId = asProductId(set, allSupportedPlatforms); if (IGFX_UNKNOWN == prodId) { argHelper->printf("Unknown device : %s\n", set.str().c_str()); return {}; } requestedPlatforms.push_back(prodId); } } return toProductNames(requestedPlatforms); } int buildFatbinary(int argc, const char *argv[], OclocArgHelper *argHelper) { std::string pointerSizeInBits = (sizeof(void *) == 4) ? "32" : "64"; int deviceArgIndex = -1; std::string inputFileName = ""; std::string outputFileName = ""; std::string outputDirectory = ""; std::vector argsCopy; if (argc > 1) { argsCopy.assign(argv, argv + argc); } for (int argIndex = 1; argIndex < argc; argIndex++) { const auto &currArg = argv[argIndex]; const bool hasMoreArgs = (argIndex + 1 < argc); if ((ConstStringRef("-device") == currArg) && hasMoreArgs) { deviceArgIndex = argIndex + 1; ++argIndex; } else if ((CompilerOptions::arch32bit == currArg) || (ConstStringRef("-32") == currArg)) { pointerSizeInBits = "32"; } else if ((CompilerOptions::arch64bit == currArg) || (ConstStringRef("-64") == currArg)) { pointerSizeInBits = "64"; } else if ((ConstStringRef("-file") == currArg) && hasMoreArgs) { inputFileName = argv[argIndex + 1]; ++argIndex; } else if ((ConstStringRef("-output") == currArg) && hasMoreArgs) { outputFileName = argv[argIndex + 1]; ++argIndex; } else if ((ConstStringRef("-out_dir") == currArg) && hasMoreArgs) { outputDirectory = argv[argIndex + 1]; ++argIndex; } } std::vector targetPlatforms; targetPlatforms = getTargetPlatformsForFatbinary(ConstStringRef(argv[deviceArgIndex], strlen(argv[deviceArgIndex])), argHelper); if (targetPlatforms.empty()) { argHelper->printf("Failed to parse target devices from : %s\n", argv[deviceArgIndex]); return 1; } NEO::Ar::ArEncoder fatbinary(true); for (auto targetPlatform : targetPlatforms) { int retVal = 0; argsCopy[deviceArgIndex] = targetPlatform.str(); std::unique_ptr pCompiler{OfflineCompiler::create(argc, argsCopy, false, retVal, argHelper)}; if (ErrorCode::SUCCESS != retVal) { argHelper->printf("Error! Couldn't create OfflineCompiler. Exiting.\n"); return retVal; } auto stepping = pCompiler->getHardwareInfo().platform.usRevId; if (retVal == 0) { retVal = buildWithSafetyGuard(pCompiler.get()); std::string buildLog = pCompiler->getBuildLog(); if (buildLog.empty() == false) { argHelper->printf("%s\n", buildLog.c_str()); } if (retVal == 0) { if (!pCompiler->isQuiet()) argHelper->printf("Build succeeded for : %s.\n", (targetPlatform.str() + "." + std::to_string(stepping)).c_str()); } else { argHelper->printf("Build failed for : %s with error code: %d\n", (targetPlatform.str() + "." + std::to_string(stepping)).c_str(), retVal); argHelper->printf("Command was:"); for (auto i = 0; i < argc; ++i) argHelper->printf(" %s", argv[i]); argHelper->printf("\n"); } } if (0 != retVal) { return retVal; } fatbinary.appendFileEntry(pointerSizeInBits + "." + targetPlatform.str() + "." + std::to_string(stepping), pCompiler->getPackedDeviceBinaryOutput()); } auto fatbinaryData = fatbinary.encode(); std::string fatbinaryFileName = outputFileName; if (outputFileName.empty() && (false == inputFileName.empty())) { fatbinaryFileName = OfflineCompiler::getFileNameTrunk(inputFileName) + ".ar"; } if (false == outputDirectory.empty()) { fatbinaryFileName = outputDirectory + "/" + outputFileName; } argHelper->saveOutput(fatbinaryFileName, fatbinaryData.data(), fatbinaryData.size()); return 0; } } // namespace NEO