Skip to content

Commit 8e57e48

Browse files
L0: Pass debug zebin to SLD
Added passing debug zebin to SLD. Added support for .const.data.strings section in debug zebin creation. Refactored debug zebin creation code. Resolves: NEO-6246 Signed-off-by: Krystian Chmielewski <[email protected]>
1 parent a787931 commit 8e57e48

File tree

9 files changed

+294
-82
lines changed

9 files changed

+294
-82
lines changed

level_zero/core/source/module/module_imp.cpp

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "shared/source/compiler_interface/intermediate_representations.h"
1111
#include "shared/source/compiler_interface/linker.h"
1212
#include "shared/source/device/device.h"
13+
#include "shared/source/device_binary_format/debug_zebin.h"
1314
#include "shared/source/device_binary_format/device_binary_formats.h"
1415
#include "shared/source/device_binary_format/elf/elf.h"
1516
#include "shared/source/device_binary_format/elf/elf_encoder.h"
@@ -431,6 +432,34 @@ ModuleImp::~ModuleImp() {
431432
kernelImmDatas.clear();
432433
}
433434

435+
NEO::Debug::Segments ModuleImp::getZebinSegments() {
436+
NEO::Debug::Segments segments;
437+
438+
auto varBuffer = translationUnit->globalVarBuffer;
439+
if (varBuffer) {
440+
segments.varData = {varBuffer->getGpuAddressToPatch(), {reinterpret_cast<uint8_t *>(varBuffer->getUnderlyingBuffer()), varBuffer->getUnderlyingBufferSize()}};
441+
}
442+
443+
auto constBuffer = translationUnit->globalConstBuffer;
444+
if (constBuffer) {
445+
segments.constData = {constBuffer->getGpuAddressToPatch(), {reinterpret_cast<uint8_t *>(constBuffer->getUnderlyingBuffer()), constBuffer->getUnderlyingBufferSize()}};
446+
}
447+
448+
auto stringBuffer = translationUnit->programInfo.globalStrings;
449+
if (stringBuffer.initData) {
450+
segments.stringData = {reinterpret_cast<uintptr_t>(stringBuffer.initData),
451+
{reinterpret_cast<const uint8_t *>(stringBuffer.initData), stringBuffer.size}};
452+
}
453+
454+
for (auto &kernImmData : this->kernelImmDatas) {
455+
const auto &isa = kernImmData->getIsaGraphicsAllocation();
456+
NEO::Debug::Segments::Segment kernelSegment = {isa->getGpuAddressToPatch(), {reinterpret_cast<uint8_t *>(isa->getUnderlyingBuffer()), isa->getUnderlyingBufferSize()}};
457+
segments.nameToSegMap.insert(std::pair(kernImmData->getDescriptor().kernelMetadata.kernelName, kernelSegment));
458+
}
459+
460+
return segments;
461+
}
462+
434463
bool ModuleImp::initialize(const ze_module_desc_t *desc, NEO::Device *neoDevice) {
435464
bool success = true;
436465

@@ -493,9 +522,8 @@ bool ModuleImp::initialize(const ze_module_desc_t *desc, NEO::Device *neoDevice)
493522
}
494523
}
495524

496-
verifyDebugCapabilities();
497-
498525
this->updateBuildLog(neoDevice);
526+
verifyDebugCapabilities();
499527

500528
if (false == success) {
501529
return false;
@@ -513,7 +541,33 @@ bool ModuleImp::initialize(const ze_module_desc_t *desc, NEO::Device *neoDevice)
513541

514542
checkIfPrivateMemoryPerDispatchIsNeeded();
515543

544+
success = this->linkBinary();
545+
516546
if (debugEnabled) {
547+
passDebugData();
548+
}
549+
550+
return success;
551+
}
552+
553+
void ModuleImp::passDebugData() {
554+
auto refBin = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(translationUnit->unpackedDeviceBinary.get()), translationUnit->unpackedDeviceBinarySize);
555+
if (NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::Zebin>(refBin)) {
556+
auto segments = getZebinSegments();
557+
auto debugZebin = NEO::Debug::createDebugZebin(refBin, segments);
558+
559+
translationUnit->debugDataSize = debugZebin.size();
560+
translationUnit->debugData.reset(new char[translationUnit->debugDataSize]);
561+
memcpy_s(translationUnit->debugData.get(), translationUnit->debugDataSize,
562+
debugZebin.data(), debugZebin.size());
563+
564+
if (device->getSourceLevelDebugger()) {
565+
NEO::DebugData debugData; // pass debug zebin in vIsa field
566+
debugData.vIsa = reinterpret_cast<const char *>(debugZebin.data());
567+
debugData.vIsaSize = static_cast<uint32_t>(debugZebin.size());
568+
device->getSourceLevelDebugger()->notifyKernelDebugData(&debugData, "debug_zebin", nullptr, 0);
569+
}
570+
} else {
517571
if (device->getSourceLevelDebugger()) {
518572
for (auto kernelInfo : this->translationUnit->programInfo.kernelInfos) {
519573
NEO::DebugData *notifyDebugData = kernelInfo->kernelDescriptor.external.debugData.get();
@@ -534,8 +588,6 @@ bool ModuleImp::initialize(const ze_module_desc_t *desc, NEO::Device *neoDevice)
534588
}
535589
}
536590
}
537-
538-
return this->linkBinary();
539591
}
540592

541593
const KernelImmutableData *ModuleImp::getKernelImmutableData(const char *functionName) const {

level_zero/core/source/module/module_imp.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020
#include <memory>
2121
#include <string>
2222

23+
namespace NEO {
24+
namespace Debug {
25+
struct Segments;
26+
}
27+
} // namespace NEO
2328
namespace L0 {
2429

2530
namespace BuildOptions {
@@ -132,6 +137,8 @@ struct ModuleImp : public Module {
132137
void copyPatchedSegments(const NEO::Linker::PatchableSegments &isaSegmentsForPatching);
133138
void verifyDebugCapabilities();
134139
void checkIfPrivateMemoryPerDispatchIsNeeded() override;
140+
NEO::Debug::Segments getZebinSegments();
141+
void passDebugData();
135142

136143
Device *device = nullptr;
137144
PRODUCT_FAMILY productFamily{};

level_zero/core/test/unit_tests/fixtures/module_fixture.h

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "shared/test/common/mocks/mock_compilers.h"
1616
#include "shared/test/common/mocks/mock_graphics_allocation.h"
1717
#include "shared/test/common/mocks/mock_memory_manager.h"
18+
#include "shared/test/unit_test/device_binary_format/zebin_tests.h"
1819

1920
#include "level_zero/core/source/module/module.h"
2021
#include "level_zero/core/source/module/module_imp.h"
@@ -288,6 +289,88 @@ struct MultiDeviceModuleFixture : public MultiDeviceFixture {
288289
std::unique_ptr<WhiteBox<::L0::Kernel>> kernel;
289290
};
290291

292+
struct ModuleWithZebinFixture : public DeviceFixture {
293+
struct MockImmutableData : public KernelImmutableData {
294+
using KernelImmutableData::device;
295+
using KernelImmutableData::isaGraphicsAllocation;
296+
using KernelImmutableData::kernelDescriptor;
297+
MockImmutableData(L0::Device *device) {
298+
299+
auto mockKernelDescriptor = new NEO::KernelDescriptor;
300+
mockKernelDescriptor->kernelMetadata.kernelName = "kernel";
301+
kernelDescriptor = mockKernelDescriptor;
302+
this->device = device;
303+
isaGraphicsAllocation.reset(new NEO::MockGraphicsAllocation(0,
304+
NEO::GraphicsAllocation::AllocationType::KERNEL_ISA,
305+
reinterpret_cast<void *>(0x1234),
306+
0x1000,
307+
0,
308+
sizeof(uint32_t),
309+
MemoryPool::System4KBPages));
310+
}
311+
312+
~MockImmutableData() {
313+
delete kernelDescriptor;
314+
}
315+
};
316+
317+
struct MockModuleWithZebin : public L0::ModuleImp {
318+
using ModuleImp::getZebinSegments;
319+
using ModuleImp::kernelImmDatas;
320+
using ModuleImp::passDebugData;
321+
using ModuleImp::translationUnit;
322+
MockModuleWithZebin(L0::Device *device) : ModuleImp(device, nullptr, ModuleType::User) {}
323+
324+
void addSegments() {
325+
kernelImmDatas.push_back(std::make_unique<MockImmutableData>(device));
326+
translationUnit->globalVarBuffer = new NEO::MockGraphicsAllocation(0,
327+
NEO::GraphicsAllocation::AllocationType::GLOBAL_SURFACE,
328+
reinterpret_cast<void *>(0x1234),
329+
0x1000,
330+
0,
331+
sizeof(uint32_t),
332+
MemoryPool::System4KBPages);
333+
translationUnit->globalConstBuffer = new NEO::MockGraphicsAllocation(0,
334+
NEO::GraphicsAllocation::AllocationType::GLOBAL_SURFACE,
335+
reinterpret_cast<void *>(0x1234),
336+
0x1000,
337+
0,
338+
sizeof(uint32_t),
339+
MemoryPool::System4KBPages);
340+
341+
translationUnit->programInfo.globalStrings.initData = &strings;
342+
translationUnit->programInfo.globalStrings.size = sizeof(strings);
343+
}
344+
345+
void addKernelSegment() {
346+
}
347+
348+
void addEmptyZebin() {
349+
auto zebin = ZebinTestData::ValidEmptyProgram();
350+
351+
translationUnit->unpackedDeviceBinarySize = zebin.storage.size();
352+
translationUnit->unpackedDeviceBinary.reset(new char[zebin.storage.size()]);
353+
memcpy_s(translationUnit->unpackedDeviceBinary.get(), translationUnit->unpackedDeviceBinarySize,
354+
zebin.storage.data(), zebin.storage.size());
355+
}
356+
357+
~MockModuleWithZebin() {
358+
}
359+
360+
const char strings[12] = "Hello olleH";
361+
};
362+
void SetUp() {
363+
NEO::MockCompilerEnableGuard mock(true);
364+
DeviceFixture::SetUp();
365+
module = std::make_unique<MockModuleWithZebin>(device);
366+
}
367+
368+
void TearDown() {
369+
DeviceFixture::TearDown();
370+
}
371+
std::unique_ptr<MockModuleWithZebin> module;
372+
};
373+
291374
struct ImportHostPointerModuleFixture : public ModuleFixture {
292375
void SetUp() {
293376
DebugManager.flags.EnableHostPointerImport.set(1);

level_zero/core/test/unit_tests/sources/debugger/test_module_with_debug.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,16 @@ TEST_F(ModuleWithSLDTest, GivenDebugDataWithMultipleRelocationsWhenInitializingM
297297
EXPECT_NE(nullptr, kernelInfo->kernelDescriptor.external.relocatedDebugData);
298298
}
299299

300+
using ModuleWithZebinAndSLDTest = Test<ModuleWithZebinFixture>;
301+
TEST_F(ModuleWithZebinAndSLDTest, GivenZebinThenCreateDebugZebinAndPassToSLD) {
302+
module->addEmptyZebin();
303+
304+
auto debugger = new MockActiveSourceLevelDebugger(new MockOsLibrary);
305+
neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[0]->debugger.reset(debugger);
306+
module->passDebugData();
307+
308+
EXPECT_TRUE(module->translationUnit->debugData);
309+
}
300310
using KernelDebugSurfaceTest = Test<ModuleFixture>;
301311

302312
HWTEST_F(KernelDebugSurfaceTest, givenDebuggerAndBindfulKernelWhenAppendingKernelToCommandListThenBindfulSurfaceStateForDebugSurfaceIsProgrammed) {

level_zero/core/test/unit_tests/sources/module/test_module.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*
66
*/
77

8+
#include "shared/source/device_binary_format/debug_zebin.h"
89
#include "shared/source/gmm_helper/gmm.h"
910
#include "shared/source/gmm_helper/gmm_helper.h"
1011
#include "shared/source/kernel/implicit_args.h"
@@ -1958,5 +1959,39 @@ TEST_F(ModuleTests, givenImplicitArgsRelocationWhenLinkingModuleThenSegmentIsPat
19581959
EXPECT_TRUE(kernelInfo->kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs);
19591960
}
19601961

1962+
using ModuleWithZebinTest = Test<ModuleWithZebinFixture>;
1963+
TEST_F(ModuleWithZebinTest, givenNoZebinThenSegmentsAreEmpty) {
1964+
auto segments = module->getZebinSegments();
1965+
1966+
EXPECT_EQ(std::numeric_limits<uintptr_t>::max(), segments.constData.address);
1967+
EXPECT_TRUE(segments.constData.data.empty());
1968+
1969+
EXPECT_EQ(std::numeric_limits<uintptr_t>::max(), segments.varData.address);
1970+
EXPECT_TRUE(segments.varData.data.empty());
1971+
1972+
EXPECT_EQ(std::numeric_limits<uintptr_t>::max(), segments.stringData.address);
1973+
EXPECT_TRUE(segments.stringData.data.empty());
1974+
1975+
EXPECT_TRUE(segments.nameToSegMap.empty());
1976+
}
1977+
1978+
TEST_F(ModuleWithZebinTest, givenZebinSegmentsThenSegmentsArePopulated) {
1979+
module->addSegments();
1980+
auto segments = module->getZebinSegments();
1981+
1982+
auto checkGPUSeg = [](NEO::GraphicsAllocation *alloc, NEO::Debug::Segments::Segment segment) {
1983+
EXPECT_EQ(static_cast<uintptr_t>(alloc->getGpuAddressToPatch()), segment.address);
1984+
EXPECT_EQ(reinterpret_cast<uint8_t *>(alloc->getUnderlyingBuffer()), segment.data.begin());
1985+
EXPECT_EQ(static_cast<size_t>(alloc->getUnderlyingBufferSize()), segment.data.size());
1986+
};
1987+
checkGPUSeg(module->translationUnit->globalConstBuffer, segments.constData);
1988+
checkGPUSeg(module->translationUnit->globalConstBuffer, segments.varData);
1989+
checkGPUSeg(module->kernelImmDatas[0]->getIsaGraphicsAllocation(), segments.nameToSegMap["kernel"]);
1990+
1991+
EXPECT_EQ(reinterpret_cast<uintptr_t>(module->translationUnit->programInfo.globalStrings.initData), segments.stringData.address);
1992+
EXPECT_EQ(reinterpret_cast<const uint8_t *>(module->translationUnit->programInfo.globalStrings.initData), segments.stringData.data.begin());
1993+
EXPECT_EQ(module->translationUnit->programInfo.globalStrings.size, segments.stringData.data.size());
1994+
}
1995+
19611996
} // namespace ult
19621997
} // namespace L0

0 commit comments

Comments
 (0)