1 /*
2  * Copyright (C) 2020-2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  */
7 
8 #pragma once
9 
10 #include "shared/source/helpers/file_io.h"
11 #include "shared/source/memory_manager/allocation_properties.h"
12 #include "shared/source/program/kernel_info.h"
13 #include "shared/test/common/helpers/debug_manager_state_restore.h"
14 #include "shared/test/common/helpers/test_files.h"
15 #include "shared/test/common/mocks/mock_compilers.h"
16 #include "shared/test/common/mocks/mock_graphics_allocation.h"
17 #include "shared/test/common/mocks/mock_memory_manager.h"
18 #include "shared/test/unit_test/device_binary_format/zebin_tests.h"
19 
20 #include "level_zero/core/source/module/module.h"
21 #include "level_zero/core/source/module/module_imp.h"
22 #include "level_zero/core/test/unit_tests/fixtures/device_fixture.h"
23 #include "level_zero/core/test/unit_tests/mocks/mock_built_ins.h"
24 #include "level_zero/core/test/unit_tests/mocks/mock_context.h"
25 #include "level_zero/core/test/unit_tests/mocks/mock_device.h"
26 #include "level_zero/core/test/unit_tests/mocks/mock_kernel.h"
27 
28 namespace L0 {
29 namespace ult {
30 
31 struct ModuleImmutableDataFixture : public DeviceFixture {
32     struct MockImmutableMemoryManager : public NEO::MockMemoryManager {
MockImmutableMemoryManagerModuleImmutableDataFixture::MockImmutableMemoryManager33         MockImmutableMemoryManager(NEO::ExecutionEnvironment &executionEnvironment) : NEO::MockMemoryManager(const_cast<NEO::ExecutionEnvironment &>(executionEnvironment)) {}
copyMemoryToAllocationModuleImmutableDataFixture::MockImmutableMemoryManager34         bool copyMemoryToAllocation(NEO::GraphicsAllocation *graphicsAllocation,
35                                     size_t destinationOffset,
36                                     const void *memoryToCopy,
37                                     size_t sizeToCopy) override {
38             copyMemoryToAllocationCalledTimes++;
39             return true;
40         }
41         uint32_t copyMemoryToAllocationCalledTimes = 0;
42     };
43 
44     struct MockImmutableData : KernelImmutableData {
45         using KernelImmutableData::crossThreadDataSize;
46         using KernelImmutableData::crossThreadDataTemplate;
47         using KernelImmutableData::kernelDescriptor;
48         using KernelImmutableData::kernelInfo;
MockImmutableDataModuleImmutableDataFixture::MockImmutableData49         MockImmutableData(uint32_t perHwThreadPrivateMemorySize) {
50             mockKernelDescriptor = new NEO::KernelDescriptor;
51             mockKernelDescriptor->kernelAttributes.perHwThreadPrivateMemorySize = perHwThreadPrivateMemorySize;
52             kernelDescriptor = mockKernelDescriptor;
53 
54             mockKernelInfo = new NEO::KernelInfo;
55             mockKernelInfo->heapInfo.pKernelHeap = kernelHeap;
56             mockKernelInfo->heapInfo.KernelHeapSize = MemoryConstants::pageSize;
57             kernelInfo = mockKernelInfo;
58 
59             if (getIsaGraphicsAllocation() != nullptr) {
60                 device->getNEODevice()->getMemoryManager()->freeGraphicsMemory(&*isaGraphicsAllocation);
61                 isaGraphicsAllocation.release();
62             }
63             isaGraphicsAllocation.reset(new NEO::MockGraphicsAllocation(0,
64                                                                         NEO::GraphicsAllocation::AllocationType::KERNEL_ISA,
65                                                                         reinterpret_cast<void *>(0x1234),
66                                                                         0x1000,
67                                                                         0,
68                                                                         sizeof(uint32_t),
69                                                                         MemoryPool::System4KBPages));
70         }
71 
setDeviceModuleImmutableDataFixture::MockImmutableData72         void setDevice(L0::Device *inDevice) {
73             device = inDevice;
74         }
75 
~MockImmutableDataModuleImmutableDataFixture::MockImmutableData76         ~MockImmutableData() override {
77             delete mockKernelInfo;
78             delete mockKernelDescriptor;
79         }
resizeExplicitArgsModuleImmutableDataFixture::MockImmutableData80         void resizeExplicitArgs(size_t size) {
81             kernelDescriptor->payloadMappings.explicitArgs.resize(size);
82         }
83         NEO::KernelDescriptor *mockKernelDescriptor = nullptr;
84         char kernelHeap[MemoryConstants::pageSize] = {};
85         NEO::KernelInfo *mockKernelInfo = nullptr;
86     };
87 
88     struct MockModule : public L0::ModuleImp {
89         using ModuleImp::getKernelImmutableDataVector;
90         using ModuleImp::kernelImmDatas;
91         using ModuleImp::maxGroupSize;
92         using ModuleImp::translationUnit;
93         using ModuleImp::type;
94 
MockModuleModuleImmutableDataFixture::MockModule95         MockModule(L0::Device *device,
96                    L0::ModuleBuildLog *moduleBuildLog,
97                    L0::ModuleType type,
98                    uint32_t perHwThreadPrivateMemorySize,
99                    MockImmutableData *inMockKernelImmData) : ModuleImp(device, moduleBuildLog, type), mockKernelImmData(inMockKernelImmData) {
100             mockKernelImmData->setDevice(device);
101         }
102 
~MockModuleModuleImmutableDataFixture::MockModule103         ~MockModule() {
104         }
105 
getKernelImmutableDataModuleImmutableDataFixture::MockModule106         const KernelImmutableData *getKernelImmutableData(const char *functionName) const override {
107             return mockKernelImmData;
108         }
109 
checkIfPrivateMemoryPerDispatchIsNeededModuleImmutableDataFixture::MockModule110         void checkIfPrivateMemoryPerDispatchIsNeeded() override {
111             const_cast<KernelDescriptor &>(kernelImmDatas[0]->getDescriptor()).kernelAttributes.perHwThreadPrivateMemorySize = mockKernelImmData->getDescriptor().kernelAttributes.perHwThreadPrivateMemorySize;
112             ModuleImp::checkIfPrivateMemoryPerDispatchIsNeeded();
113         }
114 
115         MockImmutableData *mockKernelImmData = nullptr;
116     };
117 
118     class MockKernel : public WhiteBox<L0::KernelImp> {
119       public:
120         using KernelImp::crossThreadData;
121         using KernelImp::crossThreadDataSize;
122         using KernelImp::kernelArgHandlers;
123         using KernelImp::kernelHasIndirectAccess;
124         using KernelImp::privateMemoryGraphicsAllocation;
125 
MockKernelModuleImmutableDataFixture126         MockKernel(MockModule *mockModule) : WhiteBox<L0::KernelImp>(mockModule) {
127         }
setBufferSurfaceStateModuleImmutableDataFixture128         void setBufferSurfaceState(uint32_t argIndex, void *address, NEO::GraphicsAllocation *alloc) override {
129             return;
130         }
evaluateIfRequiresGenerationOfLocalIdsByRuntimeModuleImmutableDataFixture131         void evaluateIfRequiresGenerationOfLocalIdsByRuntime(const NEO::KernelDescriptor &kernelDescriptor) override {
132             return;
133         }
setCrossThreadDataModuleImmutableDataFixture134         void setCrossThreadData(uint32_t dataSize) {
135             crossThreadData.reset(new uint8_t[dataSize]);
136             crossThreadDataSize = dataSize;
137             memset(crossThreadData.get(), 0x00, crossThreadDataSize);
138         }
~MockKernelModuleImmutableDataFixture139         ~MockKernel() override {
140         }
141     };
142 
SetUpModuleImmutableDataFixture143     void SetUp() {
144         auto executionEnvironment = MockDevice::prepareExecutionEnvironment(NEO::defaultHwInfo.get(), 0u);
145         memoryManager = new MockImmutableMemoryManager(*executionEnvironment);
146         executionEnvironment->memoryManager.reset(memoryManager);
147         DeviceFixture::setupWithExecutionEnvironment(*executionEnvironment);
148     }
149 
createModuleFromBinaryModuleImmutableDataFixture150     void createModuleFromBinary(uint32_t perHwThreadPrivateMemorySize, bool isInternal, MockImmutableData *mockKernelImmData) {
151         std::string testFile;
152         retrieveBinaryKernelFilenameNoRevision(testFile, binaryFilename + "_", ".bin");
153 
154         size_t size = 0;
155         auto src = loadDataFromFile(
156             testFile.c_str(),
157             size);
158 
159         ASSERT_NE(0u, size);
160         ASSERT_NE(nullptr, src);
161 
162         ze_module_desc_t moduleDesc = {};
163         moduleDesc.format = ZE_MODULE_FORMAT_NATIVE;
164         moduleDesc.pInputModule = reinterpret_cast<const uint8_t *>(src.get());
165         moduleDesc.inputSize = size;
166 
167         ModuleBuildLog *moduleBuildLog = nullptr;
168 
169         module = std::make_unique<MockModule>(device,
170                                               moduleBuildLog,
171                                               ModuleType::User,
172                                               perHwThreadPrivateMemorySize,
173                                               mockKernelImmData);
174 
175         module->type = isInternal ? ModuleType::Builtin : ModuleType::User;
176         bool result = module->initialize(&moduleDesc, device->getNEODevice());
177         EXPECT_TRUE(result);
178     }
179 
createKernelModuleImmutableDataFixture180     void createKernel(MockKernel *kernel) {
181         ze_kernel_desc_t desc = {};
182         desc.pKernelName = kernelName.c_str();
183         kernel->initialize(&desc);
184     }
185 
TearDownModuleImmutableDataFixture186     void TearDown() {
187         DeviceFixture::TearDown();
188     }
189 
190     const std::string binaryFilename = "test_kernel";
191     const std::string kernelName = "test";
192     const uint32_t numKernelArguments = 6;
193     std::unique_ptr<MockModule> module;
194     MockImmutableMemoryManager *memoryManager;
195 };
196 
197 struct ModuleFixture : public DeviceFixture {
SetUpModuleFixture198     void SetUp() {
199         NEO::MockCompilerEnableGuard mock(true);
200         DeviceFixture::SetUp();
201         createModuleFromBinary();
202     }
203 
204     void createModuleFromBinary(ModuleType type = ModuleType::User) {
205         std::string testFile;
206         retrieveBinaryKernelFilenameNoRevision(testFile, binaryFilename + "_", ".bin");
207 
208         size_t size = 0;
209         auto src = loadDataFromFile(
210             testFile.c_str(),
211             size);
212 
213         ASSERT_NE(0u, size);
214         ASSERT_NE(nullptr, src);
215 
216         ze_module_desc_t moduleDesc = {};
217         moduleDesc.format = ZE_MODULE_FORMAT_NATIVE;
218         moduleDesc.pInputModule = reinterpret_cast<const uint8_t *>(src.get());
219         moduleDesc.inputSize = size;
220 
221         ModuleBuildLog *moduleBuildLog = nullptr;
222 
223         module.reset(Module::create(device, &moduleDesc, moduleBuildLog, type));
224     }
225 
createKernelModuleFixture226     void createKernel() {
227         ze_kernel_desc_t desc = {};
228         desc.pKernelName = kernelName.c_str();
229 
230         kernel = std::make_unique<WhiteBox<::L0::Kernel>>();
231         kernel->module = module.get();
232         kernel->initialize(&desc);
233     }
234 
TearDownModuleFixture235     void TearDown() {
236         DeviceFixture::TearDown();
237     }
238 
239     const std::string binaryFilename = "test_kernel";
240     const std::string kernelName = "test";
241     const uint32_t numKernelArguments = 6;
242     std::unique_ptr<L0::Module> module;
243     std::unique_ptr<WhiteBox<::L0::Kernel>> kernel;
244 };
245 
246 struct MultiDeviceModuleFixture : public MultiDeviceFixture {
SetUpMultiDeviceModuleFixture247     void SetUp() {
248         MultiDeviceFixture::SetUp();
249         modules.resize(numRootDevices);
250     }
251 
createModuleFromBinaryMultiDeviceModuleFixture252     void createModuleFromBinary(uint32_t rootDeviceIndex) {
253         std::string testFile;
254         retrieveBinaryKernelFilenameNoRevision(testFile, binaryFilename + "_", ".bin");
255 
256         size_t size = 0;
257         auto src = loadDataFromFile(testFile.c_str(), size);
258 
259         ASSERT_NE(0u, size);
260         ASSERT_NE(nullptr, src);
261 
262         ze_module_desc_t moduleDesc = {};
263         moduleDesc.format = ZE_MODULE_FORMAT_NATIVE;
264         moduleDesc.pInputModule = reinterpret_cast<const uint8_t *>(src.get());
265         moduleDesc.inputSize = size;
266 
267         ModuleBuildLog *moduleBuildLog = nullptr;
268 
269         auto device = driverHandle->devices[rootDeviceIndex];
270         modules[rootDeviceIndex].reset(Module::create(device,
271                                                       &moduleDesc,
272                                                       moduleBuildLog, ModuleType::User));
273     }
274 
createKernelMultiDeviceModuleFixture275     void createKernel(uint32_t rootDeviceIndex) {
276         ze_kernel_desc_t desc = {};
277         desc.pKernelName = kernelName.c_str();
278 
279         kernel = std::make_unique<WhiteBox<::L0::Kernel>>();
280         kernel->module = modules[rootDeviceIndex].get();
281         kernel->initialize(&desc);
282     }
283 
TearDownMultiDeviceModuleFixture284     void TearDown() {
285         MultiDeviceFixture::TearDown();
286     }
287 
288     const std::string binaryFilename = "test_kernel";
289     const std::string kernelName = "test";
290     const uint32_t numKernelArguments = 6;
291     std::vector<std::unique_ptr<L0::Module>> modules;
292     std::unique_ptr<WhiteBox<::L0::Kernel>> kernel;
293 };
294 
295 struct ModuleWithZebinFixture : public DeviceFixture {
296     struct MockImmutableData : public KernelImmutableData {
297         using KernelImmutableData::device;
298         using KernelImmutableData::isaGraphicsAllocation;
299         using KernelImmutableData::kernelDescriptor;
MockImmutableDataModuleWithZebinFixture::MockImmutableData300         MockImmutableData(L0::Device *device) {
301 
302             auto mockKernelDescriptor = new NEO::KernelDescriptor;
303             mockKernelDescriptor->kernelMetadata.kernelName = "kernel";
304             kernelDescriptor = mockKernelDescriptor;
305             this->device = device;
306             isaGraphicsAllocation.reset(new NEO::MockGraphicsAllocation(0,
307                                                                         NEO::GraphicsAllocation::AllocationType::KERNEL_ISA,
308                                                                         reinterpret_cast<void *>(0x1234),
309                                                                         0x1000,
310                                                                         0,
311                                                                         sizeof(uint32_t),
312                                                                         MemoryPool::System4KBPages));
313         }
314 
~MockImmutableDataModuleWithZebinFixture::MockImmutableData315         ~MockImmutableData() {
316             delete kernelDescriptor;
317         }
318     };
319 
320     struct MockModuleWithZebin : public L0::ModuleImp {
321         using ModuleImp::getDebugInfo;
322         using ModuleImp::getZebinSegments;
323         using ModuleImp::kernelImmDatas;
324         using ModuleImp::passDebugData;
325         using ModuleImp::translationUnit;
MockModuleWithZebinModuleWithZebinFixture::MockModuleWithZebin326         MockModuleWithZebin(L0::Device *device) : ModuleImp(device, nullptr, ModuleType::User) {}
327 
addSegmentsModuleWithZebinFixture::MockModuleWithZebin328         void addSegments() {
329             kernelImmDatas.push_back(std::make_unique<MockImmutableData>(device));
330             translationUnit->globalVarBuffer = new NEO::MockGraphicsAllocation(0,
331                                                                                NEO::GraphicsAllocation::AllocationType::GLOBAL_SURFACE,
332                                                                                reinterpret_cast<void *>(0x1234),
333                                                                                0x1000,
334                                                                                0,
335                                                                                sizeof(uint32_t),
336                                                                                MemoryPool::System4KBPages);
337             translationUnit->globalConstBuffer = new NEO::MockGraphicsAllocation(0,
338                                                                                  NEO::GraphicsAllocation::AllocationType::GLOBAL_SURFACE,
339                                                                                  reinterpret_cast<void *>(0x1234),
340                                                                                  0x1000,
341                                                                                  0,
342                                                                                  sizeof(uint32_t),
343                                                                                  MemoryPool::System4KBPages);
344 
345             translationUnit->programInfo.globalStrings.initData = &strings;
346             translationUnit->programInfo.globalStrings.size = sizeof(strings);
347         }
348 
addKernelSegmentModuleWithZebinFixture::MockModuleWithZebin349         void addKernelSegment() {
350         }
351 
addEmptyZebinModuleWithZebinFixture::MockModuleWithZebin352         void addEmptyZebin() {
353             auto zebin = ZebinTestData::ValidEmptyProgram();
354 
355             translationUnit->unpackedDeviceBinarySize = zebin.storage.size();
356             translationUnit->unpackedDeviceBinary.reset(new char[zebin.storage.size()]);
357             memcpy_s(translationUnit->unpackedDeviceBinary.get(), translationUnit->unpackedDeviceBinarySize,
358                      zebin.storage.data(), zebin.storage.size());
359         }
360 
~MockModuleWithZebinModuleWithZebinFixture::MockModuleWithZebin361         ~MockModuleWithZebin() {
362         }
363 
364         const char strings[12] = "Hello olleH";
365     };
SetUpModuleWithZebinFixture366     void SetUp() {
367         NEO::MockCompilerEnableGuard mock(true);
368         DeviceFixture::SetUp();
369         module = std::make_unique<MockModuleWithZebin>(device);
370     }
371 
TearDownModuleWithZebinFixture372     void TearDown() {
373         DeviceFixture::TearDown();
374     }
375     std::unique_ptr<MockModuleWithZebin> module;
376 };
377 
378 struct ImportHostPointerModuleFixture : public ModuleFixture {
SetUpImportHostPointerModuleFixture379     void SetUp() {
380         DebugManager.flags.EnableHostPointerImport.set(1);
381         ModuleFixture::SetUp();
382 
383         hostPointer = driverHandle->getMemoryManager()->allocateSystemMemory(MemoryConstants::pageSize, MemoryConstants::pageSize);
384     }
385 
TearDownImportHostPointerModuleFixture386     void TearDown() {
387         driverHandle->getMemoryManager()->freeSystemMemory(hostPointer);
388         ModuleFixture::TearDown();
389     }
390 
391     DebugManagerStateRestore debugRestore;
392     void *hostPointer = nullptr;
393 };
394 
395 } // namespace ult
396 } // namespace L0
397