From 71746a2fff1fb1cf3dfb906eaa2aa12d75ee1912 Mon Sep 17 00:00:00 2001 From: Igor Venevtsev Date: Tue, 28 Dec 2021 16:44:13 +0000 Subject: [PATCH] Register zebin binary in L0 debugger Related-To: NEO-5571 Signed-off-by: Igor Venevtsev --- level_zero/core/source/kernel/kernel.h | 4 +- level_zero/core/source/kernel/kernel_imp.cpp | 9 +- level_zero/core/source/module/module_imp.cpp | 31 ++++- level_zero/core/source/module/module_imp.h | 5 +- .../test/unit_tests/mocks/mock_l0_debugger.h | 10 +- .../core/test/unit_tests/mocks/mock_module.h | 10 +- .../debugger/test_module_with_debug.cpp | 130 +++++++++++++++++- .../unit_tests/sources/kernel/test_kernel.cpp | 53 +------ .../compiler_options/compiler_options_base.h | 4 +- 9 files changed, 185 insertions(+), 71 deletions(-) diff --git a/level_zero/core/source/kernel/kernel.h b/level_zero/core/source/kernel/kernel.h index 6987066b50..a1d079a42b 100644 --- a/level_zero/core/source/kernel/kernel.h +++ b/level_zero/core/source/kernel/kernel.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2021 Intel Corporation + * Copyright (C) 2020-2022 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -71,10 +71,10 @@ struct KernelImmutableData { return isaCopiedToAllocation; } - protected: MOCKABLE_VIRTUAL void createRelocatedDebugData(NEO::GraphicsAllocation *globalConstBuffer, NEO::GraphicsAllocation *globalVarBuffer); + protected: Device *device = nullptr; NEO::KernelInfo *kernelInfo = nullptr; NEO::KernelDescriptor *kernelDescriptor = nullptr; diff --git a/level_zero/core/source/kernel/kernel_imp.cpp b/level_zero/core/source/kernel/kernel_imp.cpp index 85d7b5ae0f..2e9c38c826 100644 --- a/level_zero/core/source/kernel/kernel_imp.cpp +++ b/level_zero/core/source/kernel/kernel_imp.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2021 Intel Corporation + * Copyright (C) 2020-2022 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -136,13 +136,6 @@ void KernelImmutableData::initialize(NEO::KernelInfo *kernelInfo, Device *device isaGraphicsAllocation.reset(allocation); - if (neoDevice->getDebugger() && kernelInfo->kernelDescriptor.external.debugData.get()) { - createRelocatedDebugData(globalConstBuffer, globalVarBuffer); - if (device->getL0Debugger()) { - device->getL0Debugger()->registerElf(kernelInfo->kernelDescriptor.external.debugData.get(), allocation); - } - } - this->crossThreadDataSize = this->kernelDescriptor->kernelAttributes.crossThreadDataSize; ArrayRef crossThredDataArrayRef; diff --git a/level_zero/core/source/module/module_imp.cpp b/level_zero/core/source/module/module_imp.cpp index 5e5c8f2800..fda2822772 100644 --- a/level_zero/core/source/module/module_imp.cpp +++ b/level_zero/core/source/module/module_imp.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2021 Intel Corporation + * Copyright (C) 2020-2022 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -550,6 +550,8 @@ bool ModuleImp::initialize(const ze_module_desc_t *desc, NEO::Device *neoDevice) this->type == ModuleType::Builtin); kernelImmDatas.push_back(std::move(kernelImmData)); } + + registerElfInDebuggerL0(neoDevice); this->maxGroupSize = static_cast(this->translationUnit->device->getNEODevice()->getDeviceInfo().maxWorkGroupSize); checkIfPrivateMemoryPerDispatchIsNeeded(); @@ -999,6 +1001,33 @@ ze_result_t ModuleImp::performDynamicLink(uint32_t numModules, return ZE_RESULT_SUCCESS; } +void ModuleImp::registerElfInDebuggerL0(NEO::Device *neoDevice) { + if (neoDevice->getDebugger() == nullptr) { + return; + } + + auto refBin = ArrayRef(reinterpret_cast(translationUnit->unpackedDeviceBinary.get()), translationUnit->unpackedDeviceBinarySize); + if (NEO::isDeviceBinaryFormat(refBin)) { + size_t debugDataSize = 0; + getDebugInfo(&debugDataSize, nullptr); + if (device->getL0Debugger()) { + NEO::DebugData debugData; // pass debug zebin in vIsa field + debugData.vIsa = reinterpret_cast(translationUnit->debugData.get()); + debugData.vIsaSize = static_cast(translationUnit->debugDataSize); + device->getL0Debugger()->registerElf(&debugData, kernelImmDatas[0]->getIsaGraphicsAllocation()); + } + } else { + for (auto &kernImmData : kernelImmDatas) { + if (kernImmData->getKernelInfo()->kernelDescriptor.external.debugData.get()) { + kernImmData->createRelocatedDebugData(translationUnit->globalConstBuffer, translationUnit->globalVarBuffer); + if (device->getL0Debugger()) { + device->getL0Debugger()->registerElf(kernImmData->getKernelInfo()->kernelDescriptor.external.debugData.get(), kernImmData->getIsaGraphicsAllocation()); + } + } + } + } +} + bool moveBuildOption(std::string &dstOptionsSet, std::string &srcOptionSet, NEO::ConstStringRef dstOptionName, NEO::ConstStringRef srcOptionName) { const char optDelim = ' '; const char valDelim = '='; diff --git a/level_zero/core/source/module/module_imp.h b/level_zero/core/source/module/module_imp.h index 5e6b7dd2e9..ac982dad79 100644 --- a/level_zero/core/source/module/module_imp.h +++ b/level_zero/core/source/module/module_imp.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2021 Intel Corporation + * Copyright (C) 2020-2022 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -47,7 +47,7 @@ struct ModuleTranslationUnit { std::vector generateElfFromSpirV(std::vector inputSpirVs, std::vector inputModuleSizes); bool processSpecConstantInfo(NEO::CompilerInterface *compilerInterface, const ze_module_constants_t *pConstants, const char *input, uint32_t inputSize); std::string generateCompilerOptions(const char *buildOptions, const char *internalBuildOptions); - bool compileGenBinary(NEO::TranslationInput inputArgs, bool staticLink); + MOCKABLE_VIRTUAL bool compileGenBinary(NEO::TranslationInput inputArgs, bool staticLink); void updateBuildLog(const std::string &newLogEntry); void processDebugData(); L0::Device *device = nullptr; @@ -141,6 +141,7 @@ struct ModuleImp : public Module { NEO::Debug::Segments getZebinSegments(); void passDebugData(); void createDebugZebin(); + void registerElfInDebuggerL0(NEO::Device *neoDevice); Device *device = nullptr; PRODUCT_FAMILY productFamily{}; diff --git a/level_zero/core/test/unit_tests/mocks/mock_l0_debugger.h b/level_zero/core/test/unit_tests/mocks/mock_l0_debugger.h index da7eb8e0cf..05a9d7491f 100644 --- a/level_zero/core/test/unit_tests/mocks/mock_l0_debugger.h +++ b/level_zero/core/test/unit_tests/mocks/mock_l0_debugger.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2022 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -41,9 +41,15 @@ class MockDebuggerL0Hw : public L0::DebuggerL0Hw { L0::DebuggerL0Hw::programSbaTrackingCommands(cmdStream, sba); } + void registerElf(NEO::DebugData *debugData, NEO::GraphicsAllocation *isaAllocation) override { + registerElfCount++; + L0::DebuggerL0Hw::registerElf(debugData, isaAllocation); + } + uint32_t captureStateBaseAddressCount = 0; uint32_t programSbaTrackingCommandsCount = 0; uint32_t getSbaTrackingCommandsSizeCount = 0; + uint32_t registerElfCount = 0; }; template @@ -60,4 +66,4 @@ struct WhiteBox<::L0::DebuggerL0> : public ::L0::DebuggerL0 { }; } // namespace ult -} // namespace L0 \ No newline at end of file +} // namespace L0 diff --git a/level_zero/core/test/unit_tests/mocks/mock_module.h b/level_zero/core/test/unit_tests/mocks/mock_module.h index bb8c9bb409..dd465ee705 100644 --- a/level_zero/core/test/unit_tests/mocks/mock_module.h +++ b/level_zero/core/test/unit_tests/mocks/mock_module.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2021 Intel Corporation + * Copyright (C) 2020-2022 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -62,6 +62,14 @@ struct MockModuleTranslationUnit : public L0::ModuleTranslationUnit { bool processUnpackedBinary() override { return true; } + + bool compileGenBinary(NEO::TranslationInput inputArgs, bool staticLink) override { + if (unpackedDeviceBinarySize && unpackedDeviceBinary) { + return true; + } else { + return ModuleTranslationUnit::compileGenBinary(inputArgs, staticLink); + } + } }; struct MockModule : public L0::ModuleImp { diff --git a/level_zero/core/test/unit_tests/sources/debugger/test_module_with_debug.cpp b/level_zero/core/test/unit_tests/sources/debugger/test_module_with_debug.cpp index 1252fce42e..f9c2052aee 100644 --- a/level_zero/core/test/unit_tests/sources/debugger/test_module_with_debug.cpp +++ b/level_zero/core/test/unit_tests/sources/debugger/test_module_with_debug.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2021 Intel Corporation + * Copyright (C) 2020-2022 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -308,6 +308,7 @@ TEST_F(ModuleWithZebinAndSLDTest, GivenZebinThenCreateDebugZebinAndPassToSLD) { EXPECT_TRUE(module->translationUnit->debugData); } + using KernelDebugSurfaceTest = Test; HWTEST_F(KernelDebugSurfaceTest, givenDebuggerAndBindfulKernelWhenAppendingKernelToCommandListThenBindfulSurfaceStateForDebugSurfaceIsProgrammed) { @@ -413,6 +414,133 @@ TEST_F(ModuleWithDebuggerL0Test, givenDebuggingEnabledWhenKernelsAreInitializedT EXPECT_THAT(isa, testing::Not(MemCompare(&kernelHeap, sizeof(kernelHeap)))); }; +HWTEST_F(ModuleWithDebuggerL0Test, GivenDebugDataWhenInitializingModuleThenRegisterElf) { + NEO::MockCompilerEnableGuard mock(true); + auto cip = new NEO::MockCompilerInterfaceCaptureBuildOptions(); + neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[device->getRootDeviceIndex()]->compilerInterface.reset(cip); + + uint8_t binary[10]; + ze_module_desc_t moduleDesc = {}; + moduleDesc.format = ZE_MODULE_FORMAT_IL_SPIRV; + moduleDesc.pInputModule = binary; + moduleDesc.inputSize = 10; + ModuleBuildLog *moduleBuildLog = nullptr; + + std::unique_ptr moduleMock = std::make_unique(device, moduleBuildLog, ModuleType::User); + moduleMock->translationUnit = std::make_unique(device); + + uint32_t kernelHeap = 0; + auto kernelInfo = new KernelInfo(); + kernelInfo->heapInfo.KernelHeapSize = 1; + kernelInfo->heapInfo.pKernelHeap = &kernelHeap; + + Mock<::L0::Kernel> kernelMock; + kernelMock.module = moduleMock.get(); + kernelMock.immutableData.kernelInfo = kernelInfo; + kernelInfo->kernelDescriptor.payloadMappings.implicitArgs.systemThreadSurfaceAddress.bindful = 0; + + moduleMock->kernelImmData = &kernelMock.immutableData; + moduleMock->translationUnit->programInfo.kernelInfos.push_back(kernelInfo); + + kernelInfo->kernelDescriptor.external.debugData = std::make_unique(); + + auto debugData = MockElfEncoder<>::createRelocateableDebugDataElf(); + kernelInfo->kernelDescriptor.external.debugData->vIsaSize = static_cast(debugData.size()); + kernelInfo->kernelDescriptor.external.debugData->vIsa = reinterpret_cast(debugData.data()); + kernelInfo->kernelDescriptor.external.debugData->genIsa = nullptr; + kernelInfo->kernelDescriptor.external.debugData->genIsaSize = 0; + + EXPECT_EQ(0u, getMockDebuggerL0Hw()->registerElfCount); + EXPECT_TRUE(moduleMock->initialize(&moduleDesc, neoDevice)); + EXPECT_EQ(1u, getMockDebuggerL0Hw()->registerElfCount); +} + +HWTEST_F(ModuleWithDebuggerL0Test, GivenNoDebugDataWhenInitializingModuleThenDoNotRegisterElf) { + NEO::MockCompilerEnableGuard mock(true); + auto cip = new NEO::MockCompilerInterfaceCaptureBuildOptions(); + neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[device->getRootDeviceIndex()]->compilerInterface.reset(cip); + + uint8_t binary[10]; + ze_module_desc_t moduleDesc = {}; + moduleDesc.format = ZE_MODULE_FORMAT_IL_SPIRV; + moduleDesc.pInputModule = binary; + moduleDesc.inputSize = 10; + ModuleBuildLog *moduleBuildLog = nullptr; + + std::unique_ptr moduleMock = std::make_unique(device, moduleBuildLog, ModuleType::User); + moduleMock->translationUnit = std::make_unique(device); + + uint32_t kernelHeap = 0; + auto kernelInfo = new KernelInfo(); + kernelInfo->heapInfo.KernelHeapSize = 1; + kernelInfo->heapInfo.pKernelHeap = &kernelHeap; + + Mock<::L0::Kernel> kernelMock; + kernelMock.module = moduleMock.get(); + kernelMock.immutableData.kernelInfo = kernelInfo; + kernelInfo->kernelDescriptor.payloadMappings.implicitArgs.systemThreadSurfaceAddress.bindful = 0; + + moduleMock->kernelImmData = &kernelMock.immutableData; + moduleMock->translationUnit->programInfo.kernelInfos.push_back(kernelInfo); + + EXPECT_EQ(0u, getMockDebuggerL0Hw()->registerElfCount); + EXPECT_TRUE(moduleMock->initialize(&moduleDesc, neoDevice)); + EXPECT_EQ(0u, getMockDebuggerL0Hw()->registerElfCount); +} + +using ModuleWithZebinAndL0DebuggerTest = Test; + +HWTEST_F(ModuleWithZebinAndL0DebuggerTest, GivenZebinDebugDataWhenInitializingModuleThenRegisterElf) { + NEO::MockCompilerEnableGuard mock(true); + auto cip = new NEO::MockCompilerInterfaceCaptureBuildOptions(); + neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[neoDevice->getRootDeviceIndex()]->compilerInterface.reset(cip); + uint8_t binary[10]; + ze_module_desc_t moduleDesc = {}; + moduleDesc.format = ZE_MODULE_FORMAT_IL_SPIRV; + moduleDesc.pInputModule = binary; + moduleDesc.inputSize = 10; + + uint32_t kernelHeap = 0; + auto kernelInfo = std::make_unique(); + kernelInfo->heapInfo.KernelHeapSize = 1; + kernelInfo->heapInfo.pKernelHeap = &kernelHeap; + + auto kernelImmutableData = ::std::make_unique(device); + kernelImmutableData->initialize(kernelInfo.get(), device, 0, nullptr, nullptr, false); + std::unique_ptr moduleMock = std::make_unique(device, nullptr, ModuleType::User); + moduleMock->translationUnit = std::make_unique(device); + moduleMock->kernelImmDatas.push_back(std::move(kernelImmutableData)); + + auto zebin = ZebinTestData::ValidEmptyProgram(); + moduleMock->translationUnit = std::make_unique(device); + moduleMock->translationUnit->unpackedDeviceBinarySize = zebin.storage.size(); + moduleMock->translationUnit->unpackedDeviceBinary.reset(new char[zebin.storage.size()]); + memcpy_s(moduleMock->translationUnit->unpackedDeviceBinary.get(), moduleMock->translationUnit->unpackedDeviceBinarySize, + zebin.storage.data(), zebin.storage.size()); + EXPECT_EQ(0u, getMockDebuggerL0Hw()->registerElfCount); + EXPECT_TRUE(moduleMock->initialize(&moduleDesc, neoDevice)); + EXPECT_EQ(1u, getMockDebuggerL0Hw()->registerElfCount); +} + +HWTEST_F(ModuleWithZebinAndL0DebuggerTest, GivenZebinNoDebugDataWhenInitializingModuleThenDoNotRegisterElf) { + NEO::MockCompilerEnableGuard mock(true); + auto cip = new NEO::MockCompilerInterfaceCaptureBuildOptions(); + neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[neoDevice->getRootDeviceIndex()]->compilerInterface.reset(cip); + + uint8_t binary[10]; + ze_module_desc_t moduleDesc = {}; + moduleDesc.format = ZE_MODULE_FORMAT_IL_SPIRV; + moduleDesc.pInputModule = binary; + moduleDesc.inputSize = 10; + + std::unique_ptr moduleMock = std::make_unique(device, nullptr, ModuleType::User); + moduleMock->translationUnit = std::make_unique(device); + + EXPECT_EQ(0u, getMockDebuggerL0Hw()->registerElfCount); + EXPECT_TRUE(moduleMock->initialize(&moduleDesc, neoDevice)); + EXPECT_EQ(0u, getMockDebuggerL0Hw()->registerElfCount); +} + using ModuleTest = Test; HWTEST_F(ModuleTest, givenDebuggingEnabledWhenModuleIsCreatedAndFullyLinkedThenIsaAllocationsAreCopiedAndResident) { diff --git a/level_zero/core/test/unit_tests/sources/kernel/test_kernel.cpp b/level_zero/core/test/unit_tests/sources/kernel/test_kernel.cpp index 2f9f860094..436162fc98 100644 --- a/level_zero/core/test/unit_tests/sources/kernel/test_kernel.cpp +++ b/level_zero/core/test/unit_tests/sources/kernel/test_kernel.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2021 Intel Corporation + * Copyright (C) 2020-2022 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -1459,57 +1459,6 @@ TEST_F(KernelIsaTests, givenGlobalBuffersWhenCreatingKernelImmutableDataThenBuff EXPECT_EQ(1, std::count(resCont.begin(), resCont.end(), &globalConstBuffer)); } -TEST_F(KernelIsaTests, givenDebugONAndKernelDegugInfoWhenInitializingImmutableDataThenRegisterElf) { - uint32_t kernelHeap = 0; - KernelInfo kernelInfo; - kernelInfo.heapInfo.KernelHeapSize = 1; - kernelInfo.heapInfo.pKernelHeap = &kernelHeap; - auto debugData = new DebugData; - kernelInfo.kernelDescriptor.external.debugData.reset(debugData); - class MockDebugger : public DebuggerL0 { - public: - MockDebugger(NEO::Device *neodev) : DebuggerL0(neodev) { - } - void registerElf(NEO::DebugData *debugData, NEO::GraphicsAllocation *isaAllocation) override { - debugData->vIsaSize = 123; - }; - size_t getSbaTrackingCommandsSize(size_t trackedAddressCount) override { return static_cast(0); }; - void programSbaTrackingCommands(NEO::LinearStream &cmdStream, const SbaAddresses &sba) override{}; - }; - MockDebugger *debugger = new MockDebugger(neoDevice); - - neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[0]->debugger.reset(static_cast(debugger)); - KernelImmutableData kernelImmutableData(device); - - kernelImmutableData.initialize(&kernelInfo, device, 0, nullptr, nullptr, false); - EXPECT_EQ(kernelInfo.kernelDescriptor.external.debugData->vIsaSize, static_cast(123)); -} - -TEST_F(KernelIsaTests, givenDebugONAndNoKernelDegugInfoWhenInitializingImmutableDataThenDoNotRegisterElf) { - uint32_t kernelHeap = 0; - KernelInfo kernelInfo; - kernelInfo.heapInfo.KernelHeapSize = 1; - kernelInfo.heapInfo.pKernelHeap = &kernelHeap; - kernelInfo.kernelDescriptor.external.debugData.reset(nullptr); - class MockDebugger : public DebuggerL0 { - public: - MockDebugger(NEO::Device *neodev) : DebuggerL0(neodev) { - } - void registerElf(NEO::DebugData *debugData, NEO::GraphicsAllocation *isaAllocation) override { - debugData->vIsaSize = 123; - }; - size_t getSbaTrackingCommandsSize(size_t trackedAddressCount) override { return static_cast(0); }; - void programSbaTrackingCommands(NEO::LinearStream &cmdStream, const SbaAddresses &sba) override{}; - }; - MockDebugger *debugger = new MockDebugger(neoDevice); - - neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[0]->debugger.reset(static_cast(debugger)); - KernelImmutableData kernelImmutableData(device); - - kernelImmutableData.initialize(&kernelInfo, device, 0, nullptr, nullptr, false); - EXPECT_EQ(kernelInfo.kernelDescriptor.external.debugData, nullptr); -} - using KernelImpPatchBindlessTest = Test; TEST_F(KernelImpPatchBindlessTest, GivenKernelImpWhenPatchBindlessOffsetCalledThenOffsetPatchedCorrectly) { diff --git a/shared/source/compiler_interface/compiler_options/compiler_options_base.h b/shared/source/compiler_interface/compiler_options/compiler_options_base.h index c46c666618..fb9da30965 100644 --- a/shared/source/compiler_interface/compiler_options/compiler_options_base.h +++ b/shared/source/compiler_interface/compiler_options/compiler_options_base.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2021 Intel Corporation + * Copyright (C) 2019-2022 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -33,7 +33,7 @@ static constexpr ConstStringRef bindlessMode = "-cl-intel-use-bindless-mode -cl- static constexpr ConstStringRef uniformWorkgroupSize = "-cl-uniform-work-group-size"; static constexpr ConstStringRef forceEmuInt32DivRem = "-cl-intel-force-emu-int32divrem"; static constexpr ConstStringRef forceEmuInt32DivRemSP = "-cl-intel-force-emu-sp-int32divrem"; -static constexpr ConstStringRef allowZebin = "-allow-zebin"; +static constexpr ConstStringRef allowZebin = "-cl-intel-allow-zebin"; static constexpr ConstStringRef enableImageSupport = "-D__IMAGE_SUPPORT__=1"; static constexpr ConstStringRef optLevel = "-ze-opt-level=O"; static constexpr ConstStringRef excludeIrFromZebin = "-exclude-ir-from-zebin";