1 /* 2 * Copyright (C) 2018-2021 Intel Corporation 3 * 4 * SPDX-License-Identifier: MIT 5 * 6 */ 7 8 #pragma once 9 #include "shared/source/built_ins/sip.h" 10 #include "shared/source/compiler_interface/compiler_cache.h" 11 #include "shared/source/helpers/string.h" 12 #include "shared/source/os_interface/os_library.h" 13 #include "shared/source/utilities/arrayref.h" 14 #include "shared/source/utilities/spinlock.h" 15 16 #include "cif/common/cif_main.h" 17 #include "ocl_igc_interface/code_type.h" 18 #include "ocl_igc_interface/fcl_ocl_device_ctx.h" 19 #include "ocl_igc_interface/igc_ocl_device_ctx.h" 20 21 #include <map> 22 #include <unordered_map> 23 24 namespace NEO { 25 class Device; 26 27 using specConstValuesMap = std::unordered_map<uint32_t, uint64_t>; 28 29 struct TranslationInput { 30 TranslationInput(IGC::CodeType::CodeType_t srcType, IGC::CodeType::CodeType_t outType, IGC::CodeType::CodeType_t preferredIntermediateType = IGC::CodeType::undefined) srcTypeTranslationInput31 : srcType(srcType), preferredIntermediateType(preferredIntermediateType), outType(outType) { 32 } 33 34 bool allowCaching = false; 35 36 ArrayRef<const char> src; 37 ArrayRef<const char> apiOptions; 38 ArrayRef<const char> internalOptions; 39 const char *tracingOptions = nullptr; 40 uint32_t tracingOptionsCount = 0; 41 IGC::CodeType::CodeType_t srcType = IGC::CodeType::invalid; 42 IGC::CodeType::CodeType_t preferredIntermediateType = IGC::CodeType::invalid; 43 IGC::CodeType::CodeType_t outType = IGC::CodeType::invalid; 44 void *GTPinInput = nullptr; 45 46 specConstValuesMap specializedValues; 47 }; 48 49 struct TranslationOutput { 50 enum class ErrorCode { 51 Success = 0, 52 CompilerNotAvailable, 53 CompilationFailure, 54 BuildFailure, 55 LinkFailure, 56 AlreadyCompiled, 57 UnknownError, 58 }; 59 60 struct MemAndSize { 61 std::unique_ptr<char[]> mem; 62 size_t size = 0; 63 }; 64 65 IGC::CodeType::CodeType_t intermediateCodeType = IGC::CodeType::invalid; 66 MemAndSize intermediateRepresentation; 67 MemAndSize deviceBinary; 68 MemAndSize debugData; 69 std::string frontendCompilerLog; 70 std::string backendCompilerLog; 71 72 template <typename ContainerT> makeCopyTranslationOutput73 static void makeCopy(ContainerT &dst, CIF::Builtins::BufferSimple *src) { 74 if ((nullptr == src) || (src->GetSizeRaw() == 0)) { 75 dst.clear(); 76 return; 77 } 78 dst.assign(src->GetMemory<char>(), src->GetSize<char>()); 79 } 80 makeCopyTranslationOutput81 static void makeCopy(MemAndSize &dst, CIF::Builtins::BufferSimple *src) { 82 if ((nullptr == src) || (src->GetSizeRaw() == 0)) { 83 dst.mem.reset(); 84 dst.size = 0U; 85 return; 86 } 87 88 dst.size = src->GetSize<char>(); 89 dst.mem = ::makeCopy(src->GetMemory<void>(), src->GetSize<char>()); 90 } 91 }; 92 93 struct SpecConstantInfo { 94 CIF::RAII::UPtr_t<CIF::Builtins::BufferLatest> idsBuffer; 95 CIF::RAII::UPtr_t<CIF::Builtins::BufferLatest> sizesBuffer; 96 }; 97 98 class CompilerInterface { 99 public: 100 CompilerInterface(); 101 CompilerInterface(const CompilerInterface &) = delete; 102 CompilerInterface &operator=(const CompilerInterface &) = delete; 103 CompilerInterface(CompilerInterface &&) = delete; 104 CompilerInterface &operator=(CompilerInterface &&) = delete; 105 virtual ~CompilerInterface(); 106 107 template <typename CompilerInterfaceT = CompilerInterface> createInstance(std::unique_ptr<CompilerCache> && cache,bool requireFcl)108 static CompilerInterfaceT *createInstance(std::unique_ptr<CompilerCache> &&cache, bool requireFcl) { 109 auto instance = new CompilerInterfaceT(); 110 if (!instance->initialize(std::move(cache), requireFcl)) { 111 delete instance; 112 instance = nullptr; 113 } 114 return instance; 115 } 116 117 MOCKABLE_VIRTUAL TranslationOutput::ErrorCode build(const NEO::Device &device, 118 const TranslationInput &input, 119 TranslationOutput &output); 120 121 MOCKABLE_VIRTUAL TranslationOutput::ErrorCode compile(const NEO::Device &device, 122 const TranslationInput &input, 123 TranslationOutput &output); 124 125 MOCKABLE_VIRTUAL TranslationOutput::ErrorCode link(const NEO::Device &device, 126 const TranslationInput &input, 127 TranslationOutput &output); 128 129 MOCKABLE_VIRTUAL TranslationOutput::ErrorCode getSpecConstantsInfo(const NEO::Device &device, 130 ArrayRef<const char> srcSpirV, SpecConstantInfo &output); 131 132 TranslationOutput::ErrorCode createLibrary(NEO::Device &device, 133 const TranslationInput &input, 134 TranslationOutput &output); 135 136 MOCKABLE_VIRTUAL TranslationOutput::ErrorCode getSipKernelBinary(NEO::Device &device, SipKernelType type, std::vector<char> &retBinary, 137 std::vector<char> &stateSaveAreaHeader); 138 139 protected: 140 MOCKABLE_VIRTUAL bool initialize(std::unique_ptr<CompilerCache> &&cache, bool requireFcl); 141 MOCKABLE_VIRTUAL bool loadFcl(); 142 MOCKABLE_VIRTUAL bool loadIgc(); 143 144 static SpinLock spinlock; lock()145 MOCKABLE_VIRTUAL std::unique_lock<SpinLock> lock() { 146 return std::unique_lock<SpinLock>{spinlock}; 147 } 148 std::unique_ptr<CompilerCache> cache = nullptr; 149 150 using igcDevCtxUptr = CIF::RAII::UPtr_t<IGC::IgcOclDeviceCtxTagOCL>; 151 using fclDevCtxUptr = CIF::RAII::UPtr_t<IGC::FclOclDeviceCtxTagOCL>; 152 153 std::unique_ptr<OsLibrary> igcLib; 154 CIF::RAII::UPtr_t<CIF::CIFMain> igcMain = nullptr; 155 std::map<const Device *, igcDevCtxUptr> igcDeviceContexts; 156 157 std::unique_ptr<OsLibrary> fclLib; 158 CIF::RAII::UPtr_t<CIF::CIFMain> fclMain = nullptr; 159 std::map<const Device *, fclDevCtxUptr> fclDeviceContexts; 160 CIF::RAII::UPtr_t<IGC::FclOclTranslationCtxTagOCL> fclBaseTranslationCtx = nullptr; 161 162 MOCKABLE_VIRTUAL IGC::FclOclDeviceCtxTagOCL *getFclDeviceCtx(const Device &device); 163 MOCKABLE_VIRTUAL IGC::IgcOclDeviceCtxTagOCL *getIgcDeviceCtx(const Device &device); 164 MOCKABLE_VIRTUAL IGC::CodeType::CodeType_t getPreferredIntermediateRepresentation(const Device &device); 165 166 MOCKABLE_VIRTUAL CIF::RAII::UPtr_t<IGC::FclOclTranslationCtxTagOCL> createFclTranslationCtx(const Device &device, 167 IGC::CodeType::CodeType_t inType, 168 IGC::CodeType::CodeType_t outType); 169 MOCKABLE_VIRTUAL CIF::RAII::UPtr_t<IGC::IgcOclTranslationCtxTagOCL> createIgcTranslationCtx(const Device &device, 170 IGC::CodeType::CodeType_t inType, 171 IGC::CodeType::CodeType_t outType); 172 isFclAvailable()173 bool isFclAvailable() const { 174 return (fclMain != nullptr); 175 } 176 isIgcAvailable()177 bool isIgcAvailable() const { 178 return (igcMain != nullptr); 179 } 180 isCompilerAvailable(IGC::CodeType::CodeType_t translationSrc,IGC::CodeType::CodeType_t translationDst)181 bool isCompilerAvailable(IGC::CodeType::CodeType_t translationSrc, IGC::CodeType::CodeType_t translationDst) const { 182 bool requiresFcl = (IGC::CodeType::oclC == translationSrc); 183 bool requiresIgc = (IGC::CodeType::oclC != translationSrc) || ((IGC::CodeType::spirV != translationDst) && (IGC::CodeType::llvmBc != translationDst) && (IGC::CodeType::llvmLl != translationDst)); 184 return (isFclAvailable() || (false == requiresFcl)) && (isIgcAvailable() || (false == requiresIgc)); 185 } 186 }; 187 } // namespace NEO 188