/* * Copyright (C) 2018-2019 Intel Corporation * * SPDX-License-Identifier: MIT * */ #include "iga_wrapper.h" #include "core/helpers/hw_info.h" #include "core/os_interface/os_library.h" #include "runtime/os_interface/os_inc_base.h" #include "helper.h" #include "igfxfmid.h" #include "translate_platform_base.h" #include struct IgaLibrary { pIGAAssemble assemble = nullptr; pIGAContextCreate contextCreate = nullptr; pIGAContextGetErrors contextGetErrors = nullptr; pIGAContextGetWarnings contextGetWarnings = nullptr; pIGAContextRelease contextRelease = nullptr; pIGADisassemble disassemble = nullptr; pIGAStatusToString statusToString = nullptr; iga_context_options_t OptsContext = {}; std::unique_ptr library; bool isLoaded() { return library != nullptr; } }; struct IgaWrapper::Impl { iga_gen_t igaGen = IGA_GEN_INVALID; IgaLibrary igaLib; void loadIga() { IgaLibrary iga; iga.OptsContext.cb = sizeof(igaLib.OptsContext); iga.OptsContext.gen = igaGen; #define STR2(X) #X #define STR(X) STR2(X) iga.library.reset(NEO::OsLibrary::load(STR(IGA_LIBRARY_NAME))); if (iga.library == nullptr) { return; } #define LOAD_OR_ERROR(MEMBER, FUNC_NAME) \ if (nullptr == (iga.MEMBER = reinterpret_cast(iga.library->getProcAddress(FUNC_NAME)))) { \ printf("Warning : Couldn't find %s in %s\n", FUNC_NAME, STR(IGA_LIBRARY_NAME)); \ return; \ } LOAD_OR_ERROR(assemble, IGA_ASSEMBLE_STR); LOAD_OR_ERROR(contextCreate, IGA_CONTEXT_CREATE_STR); LOAD_OR_ERROR(contextGetErrors, IGA_CONTEXT_GET_ERRORS_STR); LOAD_OR_ERROR(contextGetWarnings, IGA_CONTEXT_GET_WARNINGS_STR); LOAD_OR_ERROR(contextRelease, IGA_CONTEXT_RELEASE_STR); LOAD_OR_ERROR(disassemble, IGA_DISASSEMBLE_STR); LOAD_OR_ERROR(statusToString, IGA_STATUS_TO_STRING_STR); #undef LOAD_OR_ERROR #undef STR #undef STR2 this->igaLib = std::move(iga); } }; IgaWrapper::IgaWrapper() : pimpl(std::make_unique()) { } IgaWrapper::~IgaWrapper() = default; bool IgaWrapper::tryDisassembleGenISA(const void *kernelPtr, uint32_t kernelSize, std::string &out) { if (false == tryLoadIga()) { messagePrinter->printf("Warning: couldn't load iga - kernel binaries won't be disassembled.\n"); return false; } iga_context_t context; iga_disassemble_options_t disassembleOptions = IGA_DISASSEMBLE_OPTIONS_INIT(); iga_status_t stat; stat = pimpl->igaLib.contextCreate(&pimpl->igaLib.OptsContext, &context); if (stat != 0) { messagePrinter->printf("Error while creating IGA Context! Error msg: %s", pimpl->igaLib.statusToString(stat)); return false; } char kernelText = '\0'; char *pKernelText = &kernelText; stat = pimpl->igaLib.disassemble(context, &disassembleOptions, kernelPtr, kernelSize, nullptr, nullptr, &pKernelText); if (stat != 0) { messagePrinter->printf("Error while disassembling with IGA!\nStatus msg: %s\n", pimpl->igaLib.statusToString(stat)); const iga_diagnostic_t *errors; uint32_t size = 100; pimpl->igaLib.contextGetErrors(context, &errors, &size); if (errors != nullptr) { messagePrinter->printf("Errors: %s\n", errors->message); } pimpl->igaLib.contextRelease(context); return false; } const iga_diagnostic_t *warnings; uint32_t warningsSize = 100; pimpl->igaLib.contextGetWarnings(context, &warnings, &warningsSize); if (warningsSize > 0 && warnings != nullptr) { messagePrinter->printf("Warnings: %s\n", warnings->message); } out = pKernelText; pimpl->igaLib.contextRelease(context); return true; } bool IgaWrapper::tryAssembleGenISA(const std::string &inAsm, std::string &outBinary) { if (false == tryLoadIga()) { messagePrinter->printf("Warning: couldn't load iga - kernel binaries won't be assembled.\n"); return false; } iga_context_t context; iga_status_t stat; iga_assemble_options_t assembleOptions = IGA_ASSEMBLE_OPTIONS_INIT(); stat = pimpl->igaLib.contextCreate(&pimpl->igaLib.OptsContext, &context); if (stat != 0) { messagePrinter->printf("Error while creating IGA Context! Error msg: %s", pimpl->igaLib.statusToString(stat)); return false; } uint32_t size = 0; void *pOutput = nullptr; stat = pimpl->igaLib.assemble(context, &assembleOptions, inAsm.c_str(), &pOutput, &size); if (stat != 0) { messagePrinter->printf("Error while assembling with IGA!\nStatus msg: %s\n", pimpl->igaLib.statusToString(stat)); const iga_diagnostic_t *errors; uint32_t size = 100; pimpl->igaLib.contextGetErrors(context, &errors, &size); if (errors != nullptr) { messagePrinter->printf("Errors: %s\n", errors->message); } pimpl->igaLib.contextRelease(context); return false; } const iga_diagnostic_t *warnings; uint32_t context_size; pimpl->igaLib.contextGetWarnings(context, &warnings, &context_size); if (context_size > 0 && warnings != nullptr) { messagePrinter->printf("Warnings: %s\n", warnings->message); } outBinary.assign(reinterpret_cast(pOutput), reinterpret_cast(pOutput) + size); pimpl->igaLib.contextRelease(context); return true; } bool IgaWrapper::tryLoadIga() { if (false == pimpl->igaLib.isLoaded()) { pimpl->loadIga(); } return pimpl->igaLib.isLoaded(); } void IgaWrapper::setGfxCore(GFXCORE_FAMILY core) { if (pimpl->igaGen == IGA_GEN_INVALID) { pimpl->igaGen = translateToIgaGen(core); } } void IgaWrapper::setProductFamily(PRODUCT_FAMILY product) { if (pimpl->igaGen == IGA_GEN_INVALID) { pimpl->igaGen = translateToIgaGen(product); } } bool IgaWrapper::isKnownPlatform() const { return pimpl->igaGen != IGA_GEN_INVALID; }