Zebin improvements

* cleaning-up per-thread buffer size calculations
* fixing default slm alignment to 16
* adding scratch space slots
* renaming slm addressing mode
* adding support for zeinfo version

Change-Id: I0450353788b8488a685976d7f1dd26a44360383c
This commit is contained in:
Jaroslaw Chodor
2020-10-04 19:18:49 +02:00
committed by sys_ocldev
parent 20f4786423
commit 345e56a151
19 changed files with 553 additions and 84 deletions

View File

@@ -156,9 +156,8 @@ void KernelImmutableData::initialize(NEO::KernelInfo *kernelInfo, NEO::MemoryMan
ArrayRef<uint8_t> surfaceStateHeapArrayRef = ArrayRef<uint8_t>(surfaceStateHeapTemplate.get(), getSurfaceStateHeapSize()); ArrayRef<uint8_t> surfaceStateHeapArrayRef = ArrayRef<uint8_t>(surfaceStateHeapTemplate.get(), getSurfaceStateHeapSize());
auto &kernelAttributes = kernelDescriptor->kernelAttributes; auto &kernelAttributes = kernelDescriptor->kernelAttributes;
if (kernelAttributes.perThreadPrivateMemorySize != 0) { if (kernelAttributes.perHwThreadPrivateMemorySize != 0) {
auto privateSurfaceSize = NEO::KernelHelper::getPrivateSurfaceSize(kernelAttributes.perThreadPrivateMemorySize, computeUnitsUsedForSratch, auto privateSurfaceSize = NEO::KernelHelper::getPrivateSurfaceSize(kernelAttributes.perHwThreadPrivateMemorySize, computeUnitsUsedForSratch);
kernelAttributes.simdSize, kernelAttributes.flags.isSimtThread);
UNRECOVERABLE_IF(privateSurfaceSize == 0); UNRECOVERABLE_IF(privateSurfaceSize == 0);
this->privateMemoryGraphicsAllocation.reset(memoryManager.allocateGraphicsMemoryWithProperties( this->privateMemoryGraphicsAllocation.reset(memoryManager.allocateGraphicsMemoryWithProperties(

View File

@@ -260,38 +260,19 @@ HWTEST_F(KernelPropertiesTests, givenInvalidKernelThenUnitializedIsReturned) {
EXPECT_NE(0u, moduleImp->getTranslationUnit()->programInfo.kernelInfos.size()); EXPECT_NE(0u, moduleImp->getTranslationUnit()->programInfo.kernelInfos.size());
} }
HWTEST_F(KernelPropertiesTests, givenSimtThreadFlagSetWhenInitializingThenComputeWithoutSimdSize) { HWTEST_F(KernelPropertiesTests, whenInitializingThenCalculatesProperPrivateSurfaceSize) {
uint32_t computeUnitsUsedForSratch = 0x300; uint32_t computeUnitsUsedForSratch = 0x300;
KernelInfo kernelInfo; KernelInfo kernelInfo;
auto &kernelAttributes = kernelInfo.kernelDescriptor.kernelAttributes; auto &kernelAttributes = kernelInfo.kernelDescriptor.kernelAttributes;
kernelAttributes.perThreadPrivateMemorySize = 0x100; kernelAttributes.perHwThreadPrivateMemorySize = 0x100;
kernelAttributes.flags.isSimtThread = false;
kernelAttributes.simdSize = 8; kernelAttributes.simdSize = 8;
{ KernelImmutableData kernelImmutableData(device);
kernelAttributes.flags.isSimtThread = true; kernelImmutableData.initialize(&kernelInfo, *device->getNEODevice()->getMemoryManager(), device->getNEODevice(), computeUnitsUsedForSratch, nullptr, nullptr);
KernelImmutableData kernelImmutableData(device); size_t expectedSize = static_cast<size_t>(kernelAttributes.perHwThreadPrivateMemorySize) * computeUnitsUsedForSratch;
EXPECT_GE(expectedSize, kernelImmutableData.getPrivateMemoryGraphicsAllocation()->getUnderlyingBufferSize());
kernelImmutableData.initialize(&kernelInfo, *device->getNEODevice()->getMemoryManager(), device->getNEODevice(), computeUnitsUsedForSratch, nullptr, nullptr);
size_t expectedSize = kernelAttributes.perThreadPrivateMemorySize * computeUnitsUsedForSratch * kernelAttributes.simdSize;
EXPECT_GE(expectedSize, kernelImmutableData.getPrivateMemoryGraphicsAllocation()->getUnderlyingBufferSize());
}
{
kernelAttributes.flags.isSimtThread = false;
KernelImmutableData kernelImmutableData(device);
kernelImmutableData.initialize(&kernelInfo, *device->getNEODevice()->getMemoryManager(), device->getNEODevice(), computeUnitsUsedForSratch, nullptr, nullptr);
size_t expectedSize = kernelAttributes.perThreadPrivateMemorySize * computeUnitsUsedForSratch;
EXPECT_GE(expectedSize, kernelImmutableData.getPrivateMemoryGraphicsAllocation()->getUnderlyingBufferSize());
}
} }
HWTEST_F(KernelPropertiesTests, givenValidKernelThenPropertiesAreRetrieved) { HWTEST_F(KernelPropertiesTests, givenValidKernelThenPropertiesAreRetrieved) {

View File

@@ -10,6 +10,7 @@
#include "shared/source/built_ins/built_ins.h" #include "shared/source/built_ins/built_ins.h"
#include "shared/source/command_stream/command_stream_receiver.h" #include "shared/source/command_stream/command_stream_receiver.h"
#include "shared/source/debug_settings/debug_settings_manager.h" #include "shared/source/debug_settings/debug_settings_manager.h"
#include "shared/source/device_binary_format/patchtokens_decoder.h"
#include "shared/source/gmm_helper/gmm_helper.h" #include "shared/source/gmm_helper/gmm_helper.h"
#include "shared/source/helpers/aligned_memory.h" #include "shared/source/helpers/aligned_memory.h"
#include "shared/source/helpers/api_specific_config.h" #include "shared/source/helpers/api_specific_config.h"
@@ -271,13 +272,10 @@ cl_int Kernel::initialize() {
localBindingTableOffset = (patchInfo.bindingTableState != nullptr) ? patchInfo.bindingTableState->Offset : 0; localBindingTableOffset = (patchInfo.bindingTableState != nullptr) ? patchInfo.bindingTableState->Offset : 0;
// patch crossthread data and ssh with inline surfaces, if necessary // patch crossthread data and ssh with inline surfaces, if necessary
auto perThreadPrivateMemorySize = patchInfo.pAllocateStatelessPrivateSurface auto perHwThreadPrivateMemorySize = PatchTokenBinary::getPerHwThreadPrivateSurfaceSize(patchInfo.pAllocateStatelessPrivateSurface, getKernelInfo().getMaxSimdSize());
? patchInfo.pAllocateStatelessPrivateSurface->PerThreadPrivateMemorySize
: 0;
if (perThreadPrivateMemorySize) { if (perHwThreadPrivateMemorySize) {
privateSurfaceSize = KernelHelper::getPrivateSurfaceSize(perThreadPrivateMemorySize, device.getSharedDeviceInfo().computeUnitsUsedForScratch, privateSurfaceSize = KernelHelper::getPrivateSurfaceSize(perHwThreadPrivateMemorySize, device.getSharedDeviceInfo().computeUnitsUsedForScratch);
getKernelInfo().getMaxSimdSize(), patchInfo.pAllocateStatelessPrivateSurface->IsSimtThread);
DEBUG_BREAK_IF(privateSurfaceSize == 0); DEBUG_BREAK_IF(privateSurfaceSize == 0);
if (privateSurfaceSize > std::numeric_limits<uint32_t>::max()) { if (privateSurfaceSize > std::numeric_limits<uint32_t>::max()) {

View File

@@ -458,9 +458,9 @@ void KernelInfo::apply(const DeviceInfoKernelPayloadConstants &constants) {
uint32_t privateMemorySize = 0U; uint32_t privateMemorySize = 0U;
if (patchInfo.pAllocateStatelessPrivateSurface) { if (patchInfo.pAllocateStatelessPrivateSurface) {
privateMemorySize = static_cast<uint32_t>(KernelHelper::getPrivateSurfaceSize(patchInfo.pAllocateStatelessPrivateSurface->PerThreadPrivateMemorySize, auto perHwThreadSize = PatchTokenBinary::getPerHwThreadPrivateSurfaceSize(patchInfo.pAllocateStatelessPrivateSurface, this->getMaxSimdSize());
constants.computeUnitsUsedForScratch, getMaxSimdSize(), privateMemorySize = static_cast<uint32_t>(KernelHelper::getPrivateSurfaceSize(perHwThreadSize,
patchInfo.pAllocateStatelessPrivateSurface->IsSimtThread)); constants.computeUnitsUsedForScratch));
} }
if (privateMemoryStatelessSizeOffset != WorkloadInfo::undefinedOffset) { if (privateMemoryStatelessSizeOffset != WorkloadInfo::undefinedOffset) {

View File

@@ -13,6 +13,7 @@
#include "shared/source/device_binary_format/device_binary_formats.h" #include "shared/source/device_binary_format/device_binary_formats.h"
#include "shared/source/device_binary_format/elf/elf_encoder.h" #include "shared/source/device_binary_format/elf/elf_encoder.h"
#include "shared/source/device_binary_format/elf/ocl_elf.h" #include "shared/source/device_binary_format/elf/ocl_elf.h"
#include "shared/source/device_binary_format/patchtokens_decoder.h"
#include "shared/source/helpers/api_specific_config.h" #include "shared/source/helpers/api_specific_config.h"
#include "shared/source/helpers/compiler_options_parser.h" #include "shared/source/helpers/compiler_options_parser.h"
#include "shared/source/helpers/debug_helpers.h" #include "shared/source/helpers/debug_helpers.h"
@@ -341,11 +342,10 @@ void Program::allocateBlockPrivateSurfaces(uint32_t rootDeviceIndex) {
const KernelInfo *info = blockKernelManager->getBlockKernelInfo(i); const KernelInfo *info = blockKernelManager->getBlockKernelInfo(i);
if (info->patchInfo.pAllocateStatelessPrivateSurface) { if (info->patchInfo.pAllocateStatelessPrivateSurface) {
auto perThreadPrivateMemorySize = info->patchInfo.pAllocateStatelessPrivateSurface->PerThreadPrivateMemorySize; auto perHwThreadPrivateMemorySize = PatchTokenBinary::getPerHwThreadPrivateSurfaceSize(info->patchInfo.pAllocateStatelessPrivateSurface, info->getMaxSimdSize());
if (perThreadPrivateMemorySize > 0 && blockKernelManager->getPrivateSurface(i) == nullptr) { if (perHwThreadPrivateMemorySize > 0 && blockKernelManager->getPrivateSurface(i) == nullptr) {
auto privateSize = static_cast<size_t>(KernelHelper::getPrivateSurfaceSize(perThreadPrivateMemorySize, getDevice().getDeviceInfo().computeUnitsUsedForScratch, auto privateSize = static_cast<size_t>(KernelHelper::getPrivateSurfaceSize(perHwThreadPrivateMemorySize, getDevice().getDeviceInfo().computeUnitsUsedForScratch));
info->getMaxSimdSize(), info->patchInfo.pAllocateStatelessPrivateSurface->IsSimtThread));
auto *privateSurface = this->executionEnvironment.memoryManager->allocateGraphicsMemoryWithProperties({rootDeviceIndex, privateSize, GraphicsAllocation::AllocationType::PRIVATE_SURFACE, getDevice().getDeviceBitfield()}); auto *privateSurface = this->executionEnvironment.memoryManager->allocateGraphicsMemoryWithProperties({rootDeviceIndex, privateSize, GraphicsAllocation::AllocationType::PRIVATE_SURFACE, getDevice().getDeviceBitfield()});
blockKernelManager->pushPrivateSurface(privateSurface, i); blockKernelManager->pushPrivateSurface(privateSurface, i);

View File

@@ -82,7 +82,8 @@ TEST(OclocValidate, WhenWarningsEmitedThenRedirectsThemToStdout) {
TEST(OclocValidate, WhenErrorsEmitedThenRedirectsThemToStdout) { TEST(OclocValidate, WhenErrorsEmitedThenRedirectsThemToStdout) {
ZebinTestData::ValidEmptyProgram zebin; ZebinTestData::ValidEmptyProgram zebin;
zebin.removeSection(NEO::Elf::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo); zebin.removeSection(NEO::Elf::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo);
zebin.appendSection(NEO::Elf::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, ArrayRef<const char>("kernels : \nkernels :\n").toArrayRef<const uint8_t>()); std::string zeInfo = "version:" + toString(NEO::zeInfoDecoderVersion) + "\nkernels : \nkernels :\n";
zebin.appendSection(NEO::Elf::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, ArrayRef<const char>(zeInfo).toArrayRef<const uint8_t>());
MockOclocArgHelper::FilesMap files{{"src.gen", MockOclocArgHelper::FileData(reinterpret_cast<const char *>(zebin.storage.data()), MockOclocArgHelper::FilesMap files{{"src.gen", MockOclocArgHelper::FileData(reinterpret_cast<const char *>(zebin.storage.data()),
reinterpret_cast<const char *>(zebin.storage.data()) + zebin.storage.size())}}; reinterpret_cast<const char *>(zebin.storage.data()) + zebin.storage.size())}};
MockOclocArgHelper argHelper{files}; MockOclocArgHelper argHelper{files};

View File

@@ -5,7 +5,6 @@
* *
*/ */
// Abstract: Defines the types used for ELF headers/sections.
#pragma once #pragma once
#include "shared/source/device_binary_format/elf/elf.h" #include "shared/source/device_binary_format/elf/elf.h"
@@ -85,6 +84,7 @@ static_assert(sizeof(ZebinTargetFlags) == sizeof(uint32_t), "");
namespace ZebinKernelMetadata { namespace ZebinKernelMetadata {
namespace Tags { namespace Tags {
static constexpr ConstStringRef kernels("kernels"); static constexpr ConstStringRef kernels("kernels");
static constexpr ConstStringRef version("version");
namespace Kernel { namespace Kernel {
static constexpr ConstStringRef name("name"); static constexpr ConstStringRef name("name");
static constexpr ConstStringRef executionEnv("execution_env"); static constexpr ConstStringRef executionEnv("execution_env");
@@ -137,7 +137,7 @@ namespace MemoryAddressingMode {
static constexpr ConstStringRef stateless("stateless"); static constexpr ConstStringRef stateless("stateless");
static constexpr ConstStringRef stateful("stateful"); static constexpr ConstStringRef stateful("stateful");
static constexpr ConstStringRef bindless("bindless"); static constexpr ConstStringRef bindless("bindless");
static constexpr ConstStringRef sharedLocalMemory("shared_local_memory"); static constexpr ConstStringRef sharedLocalMemory("slm");
} // namespace MemoryAddressingMode } // namespace MemoryAddressingMode
namespace AddrSpace { namespace AddrSpace {
static constexpr ConstStringRef global("global"); static constexpr ConstStringRef global("global");
@@ -173,6 +173,7 @@ static constexpr ConstStringRef allocationType("type");
static constexpr ConstStringRef memoryUsage("usage"); static constexpr ConstStringRef memoryUsage("usage");
static constexpr ConstStringRef size("size"); static constexpr ConstStringRef size("size");
static constexpr ConstStringRef isSimtThread("is_simt_thread"); static constexpr ConstStringRef isSimtThread("is_simt_thread");
static constexpr ConstStringRef slot("slot");
namespace AllocationType { namespace AllocationType {
static constexpr ConstStringRef global("global"); static constexpr ConstStringRef global("global");
static constexpr ConstStringRef scratch("scratch"); static constexpr ConstStringRef scratch("scratch");
@@ -189,6 +190,11 @@ static constexpr ConstStringRef singleSpace("single_space");
namespace Types { namespace Types {
struct Version {
uint32_t major = 0U;
uint32_t minor = 0U;
};
namespace Kernel { namespace Kernel {
namespace ExecutionEnv { namespace ExecutionEnv {
using ActualKernelStartOffsetT = int32_t; using ActualKernelStartOffsetT = int32_t;
@@ -323,10 +329,12 @@ using ArgIndexT = int32_t;
using AddrmodeT = MemoryAddressingMode; using AddrmodeT = MemoryAddressingMode;
using AddrspaceT = AddressSpace; using AddrspaceT = AddressSpace;
using AccessTypeT = AccessType; using AccessTypeT = AccessType;
using SlmAlignment = uint8_t;
namespace Defaults { namespace Defaults {
static constexpr ArgIndexT argIndex = -1; static constexpr ArgIndexT argIndex = -1;
} static constexpr SlmAlignment slmArgAlignment = 16U;
} // namespace Defaults
struct PayloadArgumentBaseT { struct PayloadArgumentBaseT {
ArgTypeT argType = ArgTypeUnknown; ArgTypeT argType = ArgTypeUnknown;
@@ -367,12 +375,20 @@ enum MemoryUsage : uint8_t {
using SizeT = int32_t; using SizeT = int32_t;
using AllocationTypeT = AllocationType; using AllocationTypeT = AllocationType;
using MemoryUsageT = MemoryUsage; using MemoryUsageT = MemoryUsage;
using IsSimtThreadT = bool;
using Slot = int32_t;
namespace Defaults {
static constexpr IsSimtThreadT isSimtThread = false;
static constexpr Slot slot = 0U;
} // namespace Defaults
struct PerThreadMemoryBufferBaseT { struct PerThreadMemoryBufferBaseT {
AllocationType allocationType = AllocationTypeUnknown; AllocationType allocationType = AllocationTypeUnknown;
MemoryUsageT memoryUsage = MemoryUsageUnknown; MemoryUsageT memoryUsage = MemoryUsageUnknown;
SizeT size = 0U; SizeT size = 0U;
bool isSimtThread = false; IsSimtThreadT isSimtThread = Defaults::isSimtThread;
Slot slot = Defaults::slot;
}; };
} // namespace PerThreadMemoryBuffer } // namespace PerThreadMemoryBuffer

View File

@@ -209,6 +209,14 @@ inline const uint8_t *getInlineData(const SPatchString *ptr) {
return ptrOffset(reinterpret_cast<const uint8_t *>(ptr), sizeof(SPatchString)); return ptrOffset(reinterpret_cast<const uint8_t *>(ptr), sizeof(SPatchString));
} }
inline uint64_t getPerHwThreadPrivateSurfaceSize(const SPatchAllocateStatelessPrivateSurface *ptr, uint32_t simdSize) {
if (nullptr == ptr) {
return 0;
}
uint32_t multiplier = ptr->IsSimtThread ? simdSize : 1U;
return static_cast<uint64_t>(ptr->PerThreadPrivateMemorySize) * multiplier;
}
const KernelArgAttributesFromPatchtokens getInlineData(const SPatchKernelArgumentInfo *ptr); const KernelArgAttributesFromPatchtokens getInlineData(const SPatchKernelArgumentInfo *ptr);
const iOpenCL::SProgramBinaryHeader *decodeProgramHeader(const ArrayRef<const uint8_t> programBlob); const iOpenCL::SProgramBinaryHeader *decodeProgramHeader(const ArrayRef<const uint8_t> programBlob);

View File

@@ -158,7 +158,7 @@ bool tokenize(ConstStringRef text, LinesCache &outLines, TokensCache &outTokens,
context.isParsingIdent = false; context.isParsingIdent = false;
auto parseTokEnd = consumeStringLiteral(text, context.pos); auto parseTokEnd = consumeStringLiteral(text, context.pos);
if (parseTokEnd == context.pos) { if (parseTokEnd == context.pos) {
outErrReason = constructYamlError(outLines.size(), context.lineBeginPos, context.pos, "Underminated string"); outErrReason = constructYamlError(outLines.size(), context.lineBeginPos, context.pos, "Unterminated string");
return false; return false;
} }
outTokens.push_back(Token(ConstStringRef(context.pos, parseTokEnd - context.pos), Token::LiteralString)); outTokens.push_back(Token(ConstStringRef(context.pos, parseTokEnd - context.pos), Token::LiteralString));

View File

@@ -475,6 +475,8 @@ DecodeError readZeInfoPerThreadMemoryBuffers(const NEO::Yaml::YamlParser &parser
validBuffer &= readZeInfoValueChecked(parser, perThreadMemoryBufferMemberNd, perThreadMemoryBufferMetadata.size, context, outErrReason); validBuffer &= readZeInfoValueChecked(parser, perThreadMemoryBufferMemberNd, perThreadMemoryBufferMetadata.size, context, outErrReason);
} else if (NEO::Elf::ZebinKernelMetadata::Tags::Kernel::PerThreadMemoryBuffer::isSimtThread == key) { } else if (NEO::Elf::ZebinKernelMetadata::Tags::Kernel::PerThreadMemoryBuffer::isSimtThread == key) {
validBuffer &= readZeInfoValueChecked(parser, perThreadMemoryBufferMemberNd, perThreadMemoryBufferMetadata.isSimtThread, context, outErrReason); validBuffer &= readZeInfoValueChecked(parser, perThreadMemoryBufferMemberNd, perThreadMemoryBufferMetadata.isSimtThread, context, outErrReason);
} else if (NEO::Elf::ZebinKernelMetadata::Tags::Kernel::PerThreadMemoryBuffer::slot == key) {
validBuffer &= readZeInfoValueChecked(parser, perThreadMemoryBufferMemberNd, perThreadMemoryBufferMetadata.slot, context, outErrReason);
} else { } else {
outWarning.append("DeviceBinaryFormat::Zebin::" + NEO::Elf::SectionsNamesZebin::zeInfo.str() + " : Unknown entry \"" + key.str() + "\" for per-thread memory buffer in context of " + context.str() + "\n"); outWarning.append("DeviceBinaryFormat::Zebin::" + NEO::Elf::SectionsNamesZebin::zeInfo.str() + " : Unknown entry \"" + key.str() + "\" for per-thread memory buffer in context of " + context.str() + "\n");
} }
@@ -629,7 +631,8 @@ NEO::DecodeError populateArgDescriptor(const NEO::Elf::ZebinKernelMetadata::Type
argAsPointer.bindless = src.offset; argAsPointer.bindless = src.offset;
break; break;
case NEO::Elf::ZebinKernelMetadata::Types::Kernel::PayloadArgument::MemoryAddressingModeSharedLocalMemory: case NEO::Elf::ZebinKernelMetadata::Types::Kernel::PayloadArgument::MemoryAddressingModeSharedLocalMemory:
argAsPointer.slmOffset = src.offset; // what about SLM alignment ? argAsPointer.slmOffset = src.offset;
argAsPointer.requiredSlmAlignment = NEO::Elf::ZebinKernelMetadata::Types::Kernel::PayloadArgument::Defaults::slmArgAlignment;
break; break;
} }
break; break;
@@ -697,6 +700,10 @@ NEO::DecodeError populateKernelDescriptor(const NEO::Elf::ZebinKernelMetadata::T
using namespace NEO::Elf::ZebinKernelMetadata::Types::Kernel::PerThreadMemoryBuffer; using namespace NEO::Elf::ZebinKernelMetadata::Types::Kernel::PerThreadMemoryBuffer;
using namespace NEO::Elf::ZebinKernelMetadata::Tags::Kernel::PerThreadMemoryBuffer::AllocationType; using namespace NEO::Elf::ZebinKernelMetadata::Tags::Kernel::PerThreadMemoryBuffer::AllocationType;
using namespace NEO::Elf::ZebinKernelMetadata::Tags::Kernel::PerThreadMemoryBuffer::MemoryUsage; using namespace NEO::Elf::ZebinKernelMetadata::Tags::Kernel::PerThreadMemoryBuffer::MemoryUsage;
auto size = src.size;
if (src.isSimtThread) {
size *= dst.kernelAttributes.simdSize;
}
switch (src.allocationType) { switch (src.allocationType) {
default: default:
outErrReason.append("DeviceBinaryFormat::Zebin : Invalid per-thread memory buffer allocation type in context of : " + dst.kernelMetadata.kernelName + ".\n"); outErrReason.append("DeviceBinaryFormat::Zebin : Invalid per-thread memory buffer allocation type in context of : " + dst.kernelMetadata.kernelName + ".\n");
@@ -707,15 +714,18 @@ NEO::DecodeError populateKernelDescriptor(const NEO::Elf::ZebinKernelMetadata::T
return DecodeError::InvalidBinary; return DecodeError::InvalidBinary;
} }
dst.kernelAttributes.perThreadPrivateMemorySize = src.size; dst.kernelAttributes.perHwThreadPrivateMemorySize = size;
dst.kernelAttributes.flags.isSimtThread = src.isSimtThread;
break; break;
case AllocationTypeScratch: case AllocationTypeScratch:
if (0 != dst.kernelAttributes.perThreadScratchSize[0]) { if (src.slot > 1) {
outErrReason.append("DeviceBinaryFormat::Zebin : Invalid duplicated scratch buffer entry in context of : " + dst.kernelMetadata.kernelName + ".\n"); outErrReason.append("DeviceBinaryFormat::Zebin : Invalid scratch buffer slot " + std::to_string(src.slot) + " in context of : " + dst.kernelMetadata.kernelName + ". Expected 0 or 1.\n");
return DecodeError::InvalidBinary; return DecodeError::InvalidBinary;
} }
dst.kernelAttributes.perThreadScratchSize[0] = src.size; if (0 != dst.kernelAttributes.perThreadScratchSize[src.slot]) {
outErrReason.append("DeviceBinaryFormat::Zebin : Invalid duplicated scratch buffer entry " + std::to_string(src.slot) + " in context of : " + dst.kernelMetadata.kernelName + ".\n");
return DecodeError::InvalidBinary;
}
dst.kernelAttributes.perThreadScratchSize[src.slot] = size;
break; break;
} }
return DecodeError::Success; return DecodeError::Success;
@@ -884,7 +894,7 @@ NEO::DecodeError populateKernelDescriptor(NEO::ProgramInfo &dst, NEO::Elf::Elf<N
} }
if (nullptr == correspondingTextSegment) { if (nullptr == correspondingTextSegment) {
outErrReason.append("Could not find text section for kernel " + kernelDescriptor.kernelMetadata.kernelName + "\n"); outErrReason.append("DeviceBinaryFormat::Zebin : Could not find text section for kernel " + kernelDescriptor.kernelMetadata.kernelName + "\n");
return DecodeError::InvalidBinary; return DecodeError::InvalidBinary;
} }
@@ -897,6 +907,26 @@ NEO::DecodeError populateKernelDescriptor(NEO::ProgramInfo &dst, NEO::Elf::Elf<N
return DecodeError::Success; return DecodeError::Success;
} }
NEO::DecodeError populateZeInfoVersion(NEO::Elf::ZebinKernelMetadata::Types::Version &dst,
NEO::Yaml::YamlParser &yamlParser, const NEO::Yaml::Node &versionNd, std::string &outErrReason, std::string &outWarning) {
if (nullptr == yamlParser.getValueToken(versionNd)) {
outErrReason.append("DeviceBinaryFormat::Zebin::" + NEO::Elf::SectionsNamesZebin::zeInfo.str() + " : Invalid version format - expected \'MAJOR.MINOR\' string\n");
return NEO::DecodeError::InvalidBinary;
}
auto versionStr = yamlParser.readValueNoQuotes(versionNd);
StackVec<char, 32> nullTerminated{versionStr.begin(), versionStr.end()};
nullTerminated.push_back('\0');
auto separator = std::find(nullTerminated.begin(), nullTerminated.end(), '.');
if ((nullTerminated.end() == separator) || (nullTerminated.begin() == separator) || (&*nullTerminated.rbegin() == separator + 1)) {
outErrReason.append("DeviceBinaryFormat::Zebin::" + NEO::Elf::SectionsNamesZebin::zeInfo.str() + " : Invalid version format - expected 'MAJOR.MINOR' string, got : " + yamlParser.readValue(versionNd).str() + "\n");
return NEO::DecodeError::InvalidBinary;
}
*separator = 0;
dst.major = atoi(nullTerminated.begin());
dst.minor = atoi(separator + 1);
return NEO::DecodeError::Success;
}
template <> template <>
DecodeError decodeSingleDeviceBinary<NEO::DeviceBinaryFormat::Zebin>(ProgramInfo &dst, const SingleDeviceBinary &src, std::string &outErrReason, std::string &outWarning) { DecodeError decodeSingleDeviceBinary<NEO::DeviceBinaryFormat::Zebin>(ProgramInfo &dst, const SingleDeviceBinary &src, std::string &outErrReason, std::string &outWarning) {
auto elf = Elf::decodeElf<Elf::EI_CLASS_64>(src.deviceBinary, outErrReason, outWarning); auto elf = Elf::decodeElf<Elf::EI_CLASS_64>(src.deviceBinary, outErrReason, outWarning);
@@ -954,15 +984,44 @@ DecodeError decodeSingleDeviceBinary<NEO::DeviceBinaryFormat::Zebin>(ProgramInfo
} }
UniqueNode kernelsSectionNodes; UniqueNode kernelsSectionNodes;
UniqueNode versionSectionNodes;
for (const auto &globalScopeNd : yamlParser.createChildrenRange(*yamlParser.getRoot())) { for (const auto &globalScopeNd : yamlParser.createChildrenRange(*yamlParser.getRoot())) {
auto key = yamlParser.readKey(globalScopeNd); auto key = yamlParser.readKey(globalScopeNd);
if (NEO::Elf::ZebinKernelMetadata::Tags::kernels == key) { if (NEO::Elf::ZebinKernelMetadata::Tags::kernels == key) {
kernelsSectionNodes.push_back(&globalScopeNd); kernelsSectionNodes.push_back(&globalScopeNd);
continue; continue;
} else if (NEO::Elf::ZebinKernelMetadata::Tags::version == key) {
versionSectionNodes.push_back(&globalScopeNd);
continue;
} }
outWarning.append("DeviceBinaryFormat::Zebin::" + NEO::Elf::SectionsNamesZebin::zeInfo.str() + " : Unknown entry \"" + yamlParser.readKey(globalScopeNd).str() + "\" in global scope of " + NEO::Elf::SectionsNamesZebin::zeInfo.str() + "\n"); outWarning.append("DeviceBinaryFormat::Zebin::" + NEO::Elf::SectionsNamesZebin::zeInfo.str() + " : Unknown entry \"" + yamlParser.readKey(globalScopeNd).str() + "\" in global scope of " + NEO::Elf::SectionsNamesZebin::zeInfo.str() + "\n");
} }
if (versionSectionNodes.size() > 1U) {
outErrReason.append("DeviceBinaryFormat::Zebin::" + NEO::Elf::SectionsNamesZebin::zeInfo.str() + " : Expected at most one " + NEO::Elf::ZebinKernelMetadata::Tags::version.str() + " entry in global scope of " + NEO::Elf::SectionsNamesZebin::zeInfo.str() + ", got : " + std::to_string(versionSectionNodes.size()) + "\n");
return DecodeError::InvalidBinary;
}
NEO::Elf::ZebinKernelMetadata::Types::Version zeInfoVersion = zeInfoDecoderVersion;
if (versionSectionNodes.empty()) {
outWarning.append("DeviceBinaryFormat::Zebin::" + NEO::Elf::SectionsNamesZebin::zeInfo.str() + " : No version info provided (i.e. no " + NEO::Elf::ZebinKernelMetadata::Tags::version.str() + " entry in global scope of DeviceBinaryFormat::Zebin::" + NEO::Elf::SectionsNamesZebin::zeInfo.str() + ") - will use decoder's default : \'" + std::to_string(zeInfoDecoderVersion.major) + "." + std::to_string(zeInfoDecoderVersion.minor) + "\'\n");
zeInfoVersion = NEO::zeInfoDecoderVersion;
} else {
auto zeInfoErr = populateZeInfoVersion(zeInfoVersion, yamlParser, *versionSectionNodes[0], outErrReason, outWarning);
if (DecodeError::Success != zeInfoErr) {
return zeInfoErr;
}
}
if (zeInfoVersion.major != zeInfoDecoderVersion.major) {
outErrReason.append("DeviceBinaryFormat::Zebin::" + NEO::Elf::SectionsNamesZebin::zeInfo.str() + " : Unhandled major version : " + std::to_string(zeInfoVersion.major) + ", decoder is at : " + std::to_string(zeInfoDecoderVersion.major) + "\n");
return DecodeError::UnhandledBinary;
}
if (zeInfoVersion.minor > zeInfoDecoderVersion.minor) {
outWarning.append("DeviceBinaryFormat::Zebin::" + NEO::Elf::SectionsNamesZebin::zeInfo.str() + " : Minor version : " + std::to_string(zeInfoVersion.minor) + " is newer than available in decoder : " + std::to_string(zeInfoDecoderVersion.minor) + " - some features may be skipped\n");
}
if (kernelsSectionNodes.size() > 1U) { if (kernelsSectionNodes.size() > 1U) {
outErrReason.append("DeviceBinaryFormat::Zebin::" + NEO::Elf::SectionsNamesZebin::zeInfo.str() + " : Expected at most one " + NEO::Elf::ZebinKernelMetadata::Tags::kernels.str() + " entry in global scope of " + NEO::Elf::SectionsNamesZebin::zeInfo.str() + ", got : " + std::to_string(kernelsSectionNodes.size()) + "\n"); outErrReason.append("DeviceBinaryFormat::Zebin::" + NEO::Elf::SectionsNamesZebin::zeInfo.str() + " : Expected at most one " + NEO::Elf::ZebinKernelMetadata::Tags::kernels.str() + " entry in global scope of " + NEO::Elf::SectionsNamesZebin::zeInfo.str() + ", got : " + std::to_string(kernelsSectionNodes.size()) + "\n");
return DecodeError::InvalidBinary; return DecodeError::InvalidBinary;

View File

@@ -5,6 +5,8 @@
* *
*/ */
#pragma once
#include "shared/source/device_binary_format/device_binary_formats.h" #include "shared/source/device_binary_format/device_binary_formats.h"
#include "shared/source/device_binary_format/elf/elf_decoder.h" #include "shared/source/device_binary_format/elf/elf_decoder.h"
#include "shared/source/device_binary_format/elf/zebin_elf.h" #include "shared/source/device_binary_format/elf/zebin_elf.h"
@@ -16,6 +18,8 @@
namespace NEO { namespace NEO {
static constexpr NEO::Elf::ZebinKernelMetadata::Types::Version zeInfoDecoderVersion{1, 0};
struct ZebinSections { struct ZebinSections {
using SectionHeaderData = NEO::Elf::Elf<Elf::EI_CLASS_64>::SectionHeaderAndData; using SectionHeaderData = NEO::Elf::Elf<Elf::EI_CLASS_64>::SectionHeaderAndData;
StackVec<SectionHeaderData *, 32> textKernelSections; StackVec<SectionHeaderData *, 32> textKernelSections;
@@ -89,4 +93,7 @@ NEO::DecodeError populateArgDescriptor(const NEO::Elf::ZebinKernelMetadata::Type
NEO::DecodeError populateKernelDescriptor(NEO::ProgramInfo &dst, NEO::Elf::Elf<NEO::Elf::EI_CLASS_64> &elf, NEO::ZebinSections &zebinSections, NEO::DecodeError populateKernelDescriptor(NEO::ProgramInfo &dst, NEO::Elf::Elf<NEO::Elf::EI_CLASS_64> &elf, NEO::ZebinSections &zebinSections,
NEO::Yaml::YamlParser &yamlParser, const NEO::Yaml::Node &kernelNd, std::string &outErrReason, std::string &outWarning); NEO::Yaml::YamlParser &yamlParser, const NEO::Yaml::Node &kernelNd, std::string &outErrReason, std::string &outWarning);
NEO::DecodeError populateZeInfoVersion(NEO::Elf::ZebinKernelMetadata::Types::Version &dst,
NEO::Yaml::YamlParser &yamlParser, const NEO::Yaml::Node &versionNd, std::string &outErrReason, std::string &outWarning);
} // namespace NEO } // namespace NEO

View File

@@ -15,13 +15,8 @@ struct KernelHelper {
uint32_t usedSlmSize, uint32_t maxBarrierCount, uint32_t numberOfBarriers, uint32_t workDim, uint32_t usedSlmSize, uint32_t maxBarrierCount, uint32_t numberOfBarriers, uint32_t workDim,
const size_t *localWorkSize); const size_t *localWorkSize);
static uint64_t getPrivateSurfaceSize(uint64_t perThreadPrivateMemorySize, uint32_t computeUnitsUsedForScratch, uint32_t simdSize, bool isSimtThread) { static uint64_t getPrivateSurfaceSize(uint64_t perHwThreadPrivateMemorySize, uint32_t computeUnitsUsedForScratch) {
uint64_t size = perThreadPrivateMemorySize * computeUnitsUsedForScratch; return perHwThreadPrivateMemorySize * computeUnitsUsedForScratch;
if (isSimtThread) {
size *= simdSize;
}
return size;
} }
}; };

View File

@@ -44,7 +44,7 @@ struct KernelDescriptor final {
uint32_t slmInlineSize = 0U; uint32_t slmInlineSize = 0U;
uint32_t perThreadScratchSize[2] = {0U, 0U}; uint32_t perThreadScratchSize[2] = {0U, 0U};
uint32_t perThreadPrivateMemorySize = 0U; uint32_t perHwThreadPrivateMemorySize = 0U;
uint32_t perThreadSystemThreadSurfaceSize = 0U; uint32_t perThreadSystemThreadSurfaceSize = 0U;
uint32_t hasBarriers = 0u; uint32_t hasBarriers = 0u;
uint16_t requiredWorkgroupSize[3] = {0U, 0U, 0U}; uint16_t requiredWorkgroupSize[3] = {0U, 0U, 0U};
@@ -87,7 +87,6 @@ struct KernelDescriptor final {
bool requiresDisabledMidThreadPreemption : 1; bool requiresDisabledMidThreadPreemption : 1;
bool requiresSubgroupIndependentForwardProgress : 1; bool requiresSubgroupIndependentForwardProgress : 1;
bool requiresWorkgroupWalkOrder : 1; bool requiresWorkgroupWalkOrder : 1;
bool isSimtThread : 1;
}; };
uint32_t packed; uint32_t packed;
} flags; } flags;

View File

@@ -140,8 +140,8 @@ void populatePointerKernelArg(ArgDescPointer &dst, const TokenT &src, KernelDesc
void populateKernelDescriptor(KernelDescriptor &dst, const SPatchAllocateStatelessPrivateSurface &token) { void populateKernelDescriptor(KernelDescriptor &dst, const SPatchAllocateStatelessPrivateSurface &token) {
dst.kernelAttributes.flags.usesPrivateMemory = true; dst.kernelAttributes.flags.usesPrivateMemory = true;
dst.kernelAttributes.perThreadPrivateMemorySize = token.PerThreadPrivateMemorySize; dst.kernelAttributes.perHwThreadPrivateMemorySize = token.PerThreadPrivateMemorySize;
dst.kernelAttributes.flags.isSimtThread = (token.IsSimtThread == 1); dst.kernelAttributes.perHwThreadPrivateMemorySize = static_cast<uint32_t>(PatchTokenBinary::getPerHwThreadPrivateSurfaceSize(&token, dst.kernelAttributes.simdSize));
populatePointerKernelArg(dst.payloadMappings.implicitArgs.privateMemoryAddress, token, dst.kernelAttributes.bufferAddressingMode); populatePointerKernelArg(dst.payloadMappings.implicitArgs.privateMemoryAddress, token, dst.kernelAttributes.bufferAddressingMode);
} }

View File

@@ -885,7 +885,7 @@ TEST(YamlTokenize, GivenUnterminatedStringLiteralsThenReturnsError) {
std::string errors; std::string errors;
bool success = NEO::Yaml::tokenize(yaml, lines, tokens, errors, warnings); bool success = NEO::Yaml::tokenize(yaml, lines, tokens, errors, warnings);
EXPECT_FALSE(success); EXPECT_FALSE(success);
EXPECT_STREQ("NEO::Yaml : Could not parse line : [0] : [\"] <-- parser position on error. Reason : Underminated string\n", errors.c_str()); EXPECT_STREQ("NEO::Yaml : Could not parse line : [0] : [\"] <-- parser position on error. Reason : Unterminated string\n", errors.c_str());
EXPECT_TRUE(warnings.empty()) << warnings; EXPECT_TRUE(warnings.empty()) << warnings;
} }

View File

@@ -224,6 +224,189 @@ TEST(ValidateZebinSectionsCount, GivenTwoSpirvSectionsThenFail) {
EXPECT_TRUE(warnings.empty()) << warnings; EXPECT_TRUE(warnings.empty()) << warnings;
} }
TEST(PopulateZeInfoVersion, GivenValidVersionFormatThenParsesItProperly) {
{
NEO::ConstStringRef yaml = R"===(---
version: '1.0'
...
)===";
NEO::ZeInfoKernelSections kernelSections;
std::string parserErrors;
std::string parserWarnings;
NEO::Yaml::YamlParser parser;
bool success = parser.parse(yaml, parserErrors, parserWarnings);
EXPECT_TRUE(parserErrors.empty()) << parserErrors;
EXPECT_TRUE(parserWarnings.empty()) << parserWarnings;
ASSERT_TRUE(success);
auto &versionNode = *parser.findNodeWithKeyDfs("version");
std::string errors;
std::string warnings;
NEO::Elf::ZebinKernelMetadata::Types::Version version;
auto err = NEO::populateZeInfoVersion(version, parser, versionNode, errors, warnings);
EXPECT_EQ(NEO::DecodeError::Success, err);
EXPECT_TRUE(errors.empty()) << errors;
EXPECT_TRUE(warnings.empty()) << warnings;
EXPECT_EQ(1U, version.major);
EXPECT_EQ(0U, version.minor);
}
{
NEO::ConstStringRef yaml = R"===(---
version: '12.91'
...
)===";
NEO::ZeInfoKernelSections kernelSections;
std::string parserErrors;
std::string parserWarnings;
NEO::Yaml::YamlParser parser;
bool success = parser.parse(yaml, parserErrors, parserWarnings);
EXPECT_TRUE(parserErrors.empty()) << parserErrors;
EXPECT_TRUE(parserWarnings.empty()) << parserWarnings;
ASSERT_TRUE(success);
auto &versionNode = *parser.findNodeWithKeyDfs("version");
std::string errors;
std::string warnings;
NEO::Elf::ZebinKernelMetadata::Types::Version version;
auto err = NEO::populateZeInfoVersion(version, parser, versionNode, errors, warnings);
EXPECT_EQ(NEO::DecodeError::Success, err);
EXPECT_TRUE(errors.empty()) << errors;
EXPECT_TRUE(warnings.empty()) << warnings;
EXPECT_EQ(12U, version.major);
EXPECT_EQ(91U, version.minor);
}
}
TEST(PopulateZeInfoVersion, GivenInvalidVersionFormatThenParsesItProperly) {
{
NEO::ConstStringRef yaml = R"===(---
version: '100'
...
)===";
NEO::ZeInfoKernelSections kernelSections;
std::string parserErrors;
std::string parserWarnings;
NEO::Yaml::YamlParser parser;
bool success = parser.parse(yaml, parserErrors, parserWarnings);
EXPECT_TRUE(parserErrors.empty()) << parserErrors;
EXPECT_TRUE(parserWarnings.empty()) << parserWarnings;
ASSERT_TRUE(success);
auto &versionNode = *parser.findNodeWithKeyDfs("version");
std::string errors;
std::string warnings;
NEO::Elf::ZebinKernelMetadata::Types::Version version;
auto err = NEO::populateZeInfoVersion(version, parser, versionNode, errors, warnings);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, err);
EXPECT_STREQ("DeviceBinaryFormat::Zebin::.ze_info : Invalid version format - expected \'MAJOR.MINOR\' string, got : \'100\'\n", errors.c_str()) << errors;
EXPECT_TRUE(warnings.empty()) << warnings;
}
{
NEO::ConstStringRef yaml = R"===(---
version: '12.'
...
)===";
NEO::ZeInfoKernelSections kernelSections;
std::string parserErrors;
std::string parserWarnings;
NEO::Yaml::YamlParser parser;
bool success = parser.parse(yaml, parserErrors, parserWarnings);
EXPECT_TRUE(parserErrors.empty()) << parserErrors;
EXPECT_TRUE(parserWarnings.empty()) << parserWarnings;
ASSERT_TRUE(success);
auto &versionNode = *parser.findNodeWithKeyDfs("version");
std::string errors;
std::string warnings;
NEO::Elf::ZebinKernelMetadata::Types::Version version;
auto err = NEO::populateZeInfoVersion(version, parser, versionNode, errors, warnings);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, err);
EXPECT_STREQ("DeviceBinaryFormat::Zebin::.ze_info : Invalid version format - expected 'MAJOR.MINOR' string, got : '12.'\n", errors.c_str()) << errors;
EXPECT_TRUE(warnings.empty()) << warnings;
}
{
NEO::ConstStringRef yaml = R"===(---
version: '.12'
...
)===";
NEO::ZeInfoKernelSections kernelSections;
std::string parserErrors;
std::string parserWarnings;
NEO::Yaml::YamlParser parser;
bool success = parser.parse(yaml, parserErrors, parserWarnings);
EXPECT_TRUE(parserErrors.empty()) << parserErrors;
EXPECT_TRUE(parserWarnings.empty()) << parserWarnings;
ASSERT_TRUE(success);
auto &versionNode = *parser.findNodeWithKeyDfs("version");
std::string errors;
std::string warnings;
NEO::Elf::ZebinKernelMetadata::Types::Version version;
auto err = NEO::populateZeInfoVersion(version, parser, versionNode, errors, warnings);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, err);
EXPECT_STREQ("DeviceBinaryFormat::Zebin::.ze_info : Invalid version format - expected 'MAJOR.MINOR' string, got : '.12'\n", errors.c_str()) << errors;
EXPECT_TRUE(warnings.empty()) << warnings;
}
{
NEO::ConstStringRef yaml = R"===(---
version: '.'
...
)===";
NEO::ZeInfoKernelSections kernelSections;
std::string parserErrors;
std::string parserWarnings;
NEO::Yaml::YamlParser parser;
bool success = parser.parse(yaml, parserErrors, parserWarnings);
EXPECT_TRUE(parserErrors.empty()) << parserErrors;
EXPECT_TRUE(parserWarnings.empty()) << parserWarnings;
ASSERT_TRUE(success);
auto &versionNode = *parser.findNodeWithKeyDfs("version");
std::string errors;
std::string warnings;
NEO::Elf::ZebinKernelMetadata::Types::Version version;
auto err = NEO::populateZeInfoVersion(version, parser, versionNode, errors, warnings);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, err);
EXPECT_STREQ("DeviceBinaryFormat::Zebin::.ze_info : Invalid version format - expected 'MAJOR.MINOR' string, got : '.'\n", errors.c_str()) << errors;
EXPECT_TRUE(warnings.empty()) << warnings;
}
{
NEO::ConstStringRef yaml = R"===(---
version:
...
)===";
NEO::ZeInfoKernelSections kernelSections;
std::string parserErrors;
std::string parserWarnings;
NEO::Yaml::YamlParser parser;
bool success = parser.parse(yaml, parserErrors, parserWarnings);
EXPECT_TRUE(parserErrors.empty()) << parserErrors;
EXPECT_TRUE(parserWarnings.empty()) << parserWarnings;
ASSERT_TRUE(success);
auto &versionNode = *parser.findNodeWithKeyDfs("version");
std::string errors;
std::string warnings;
NEO::Elf::ZebinKernelMetadata::Types::Version version;
auto err = NEO::populateZeInfoVersion(version, parser, versionNode, errors, warnings);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, err);
EXPECT_STREQ("DeviceBinaryFormat::Zebin::.ze_info : Invalid version format - expected 'MAJOR.MINOR' string\n", errors.c_str()) << errors;
EXPECT_TRUE(warnings.empty()) << warnings;
}
}
TEST(ExtractZeInfoKernelSections, GivenKnownSectionsThenCapturesThemProperly) { TEST(ExtractZeInfoKernelSections, GivenKnownSectionsThenCapturesThemProperly) {
NEO::ConstStringRef yaml = R"===(--- NEO::ConstStringRef yaml = R"===(---
kernels: kernels:
@@ -1253,11 +1436,48 @@ kernels:
EXPECT_EQ(NEO::Elf::ZebinKernelMetadata::Types::Kernel::PerThreadMemoryBuffer::AllocationTypeScratch, buffers[0].allocationType); EXPECT_EQ(NEO::Elf::ZebinKernelMetadata::Types::Kernel::PerThreadMemoryBuffer::AllocationTypeScratch, buffers[0].allocationType);
EXPECT_EQ(NEO::Elf::ZebinKernelMetadata::Types::Kernel::PerThreadMemoryBuffer::MemoryUsageSingleSpace, buffers[0].memoryUsage); EXPECT_EQ(NEO::Elf::ZebinKernelMetadata::Types::Kernel::PerThreadMemoryBuffer::MemoryUsageSingleSpace, buffers[0].memoryUsage);
EXPECT_FALSE(buffers[0].isSimtThread);
EXPECT_EQ(64, buffers[0].size); EXPECT_EQ(64, buffers[0].size);
EXPECT_EQ(NEO::Elf::ZebinKernelMetadata::Types::Kernel::PerThreadMemoryBuffer::AllocationTypeGlobal, buffers[1].allocationType); EXPECT_EQ(NEO::Elf::ZebinKernelMetadata::Types::Kernel::PerThreadMemoryBuffer::AllocationTypeGlobal, buffers[1].allocationType);
EXPECT_EQ(NEO::Elf::ZebinKernelMetadata::Types::Kernel::PerThreadMemoryBuffer::MemoryUsagePrivateSpace, buffers[1].memoryUsage); EXPECT_EQ(NEO::Elf::ZebinKernelMetadata::Types::Kernel::PerThreadMemoryBuffer::MemoryUsagePrivateSpace, buffers[1].memoryUsage);
EXPECT_EQ(128, buffers[1].size); EXPECT_EQ(128, buffers[1].size);
EXPECT_FALSE(buffers[1].isSimtThread);
}
TEST(ReadZeInfoPerThreadMemoryBuffers, GivenPerSimtThreadPrivateMemoryThenSetsProperFlag) {
NEO::ConstStringRef yaml = R"===(---
kernels:
- name: some_kernel
execution_env:
simd_size: 16
per_thread_memory_buffers:
- type: global
usage: private_space
size: 128
is_simt_thread: True
...
)===";
std::string parserErrors;
std::string parserWarnings;
NEO::Yaml::YamlParser parser;
bool success = parser.parse(yaml, parserErrors, parserWarnings);
ASSERT_TRUE(success);
auto &buffersNode = *parser.findNodeWithKeyDfs("per_thread_memory_buffers");
std::string errors;
std::string warnings;
NEO::ZeInfoPerThreadMemoryBuffers buffers;
auto err = NEO::readZeInfoPerThreadMemoryBuffers(parser, buffersNode, buffers, "some_kernel", errors, warnings);
EXPECT_EQ(NEO::DecodeError::Success, err);
EXPECT_TRUE(errors.empty()) << errors;
EXPECT_TRUE(warnings.empty()) << warnings;
ASSERT_EQ(1U, buffers.size());
EXPECT_EQ(NEO::Elf::ZebinKernelMetadata::Types::Kernel::PerThreadMemoryBuffer::AllocationTypeGlobal, buffers[0].allocationType);
EXPECT_EQ(NEO::Elf::ZebinKernelMetadata::Types::Kernel::PerThreadMemoryBuffer::MemoryUsagePrivateSpace, buffers[0].memoryUsage);
EXPECT_EQ(128, buffers[0].size);
EXPECT_TRUE(buffers[0].isSimtThread);
} }
TEST(ReadZeInfoPerThreadMemoryBuffers, GivenUnknownEntryThenEmmitsWarning) { TEST(ReadZeInfoPerThreadMemoryBuffers, GivenUnknownEntryThenEmmitsWarning) {
@@ -1523,7 +1743,7 @@ TEST(DecodeSingleDeviceBinaryZebin, GivenEmptyInZeInfoThenEmitsWarning) {
TEST(DecodeSingleDeviceBinaryZebin, GivenUnknownEntryInZeInfoGlobalScopeThenEmitsWarning) { TEST(DecodeSingleDeviceBinaryZebin, GivenUnknownEntryInZeInfoGlobalScopeThenEmitsWarning) {
ZebinTestData::ValidEmptyProgram zebin; ZebinTestData::ValidEmptyProgram zebin;
zebin.removeSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo); zebin.removeSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo);
auto brokenZeInfo = NEO::ConstStringRef("some_entry : a\nkernels : \n"); auto brokenZeInfo = std::string("some_entry : a\nkernels : \nversion:\'") + toString(zeInfoDecoderVersion) + "\'\n";
zebin.appendSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, ArrayRef<const uint8_t>::fromAny(brokenZeInfo.data(), brokenZeInfo.size())); zebin.appendSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, ArrayRef<const uint8_t>::fromAny(brokenZeInfo.data(), brokenZeInfo.size()));
NEO::ProgramInfo programInfo; NEO::ProgramInfo programInfo;
@@ -1540,7 +1760,7 @@ TEST(DecodeSingleDeviceBinaryZebin, GivenUnknownEntryInZeInfoGlobalScopeThenEmit
TEST(DecodeSingleDeviceBinaryZebin, WhenZeInfoDoesNotContainKernelsSectionThenEmitsWarning) { TEST(DecodeSingleDeviceBinaryZebin, WhenZeInfoDoesNotContainKernelsSectionThenEmitsWarning) {
ZebinTestData::ValidEmptyProgram zebin; ZebinTestData::ValidEmptyProgram zebin;
zebin.removeSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo); zebin.removeSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo);
auto brokenZeInfo = NEO::ConstStringRef("a:b\n"); auto brokenZeInfo = std::string("version:\'") + toString(zeInfoDecoderVersion) + "\'\na:b\n";
zebin.appendSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, ArrayRef<const uint8_t>::fromAny(brokenZeInfo.data(), brokenZeInfo.size())); zebin.appendSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, ArrayRef<const uint8_t>::fromAny(brokenZeInfo.data(), brokenZeInfo.size()));
NEO::ProgramInfo programInfo; NEO::ProgramInfo programInfo;
@@ -1557,7 +1777,7 @@ TEST(DecodeSingleDeviceBinaryZebin, WhenZeInfoDoesNotContainKernelsSectionThenEm
TEST(DecodeSingleDeviceBinaryZebin, WhenZeInfoContainsMultipleKernelSectionsThenFails) { TEST(DecodeSingleDeviceBinaryZebin, WhenZeInfoContainsMultipleKernelSectionsThenFails) {
ZebinTestData::ValidEmptyProgram zebin; ZebinTestData::ValidEmptyProgram zebin;
zebin.removeSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo); zebin.removeSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo);
auto brokenZeInfo = NEO::ConstStringRef("kernels:\nkernels:\n"); auto brokenZeInfo = std::string("version:\'") + toString(zeInfoDecoderVersion) + "\'\nkernels:\nkernels:\n";
zebin.appendSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, ArrayRef<const uint8_t>::fromAny(brokenZeInfo.data(), brokenZeInfo.size())); zebin.appendSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, ArrayRef<const uint8_t>::fromAny(brokenZeInfo.data(), brokenZeInfo.size()));
NEO::ProgramInfo programInfo; NEO::ProgramInfo programInfo;
@@ -1571,8 +1791,118 @@ TEST(DecodeSingleDeviceBinaryZebin, WhenZeInfoContainsMultipleKernelSectionsThen
EXPECT_TRUE(decodeWarnings.empty()) << decodeWarnings; EXPECT_TRUE(decodeWarnings.empty()) << decodeWarnings;
} }
TEST(DecodeSingleDeviceBinaryZebin, WhenZeInfoContainsMultipleVersionSectionsThenFails) {
ZebinTestData::ValidEmptyProgram zebin;
zebin.removeSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo);
auto brokenZeInfo = std::string("version:\'") + toString(zeInfoDecoderVersion) + "\'\nversion:\'5.4\'\nkernels:\n";
zebin.appendSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, ArrayRef<const uint8_t>::fromAny(brokenZeInfo.data(), brokenZeInfo.size()));
NEO::ProgramInfo programInfo;
NEO::SingleDeviceBinary singleBinary;
singleBinary.deviceBinary = zebin.storage;
std::string decodeErrors;
std::string decodeWarnings;
auto error = NEO::decodeSingleDeviceBinary<NEO::DeviceBinaryFormat::Zebin>(programInfo, singleBinary, decodeErrors, decodeWarnings);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, error);
EXPECT_STREQ("DeviceBinaryFormat::Zebin::.ze_info : Expected at most one version entry in global scope of .ze_info, got : 2\n", decodeErrors.c_str());
EXPECT_TRUE(decodeWarnings.empty()) << decodeWarnings;
}
TEST(DecodeSingleDeviceBinaryZebin, WhenZeInfoDoesNotContainVersionSectionsThenEmitsWarnings) {
ZebinTestData::ValidEmptyProgram zebin;
zebin.removeSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo);
auto zeInfo = ConstStringRef("kernels:\n");
zebin.appendSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, ArrayRef<const uint8_t>::fromAny(zeInfo.data(), zeInfo.size()));
NEO::ProgramInfo programInfo;
NEO::SingleDeviceBinary singleBinary;
singleBinary.deviceBinary = zebin.storage;
std::string decodeErrors;
std::string decodeWarnings;
auto error = NEO::decodeSingleDeviceBinary<NEO::DeviceBinaryFormat::Zebin>(programInfo, singleBinary, decodeErrors, decodeWarnings);
EXPECT_EQ(NEO::DecodeError::Success, error);
EXPECT_STREQ("DeviceBinaryFormat::Zebin::.ze_info : No version info provided (i.e. no version entry in global scope of DeviceBinaryFormat::Zebin::.ze_info) - will use decoder's default : '1.0'\n", decodeWarnings.c_str());
EXPECT_TRUE(decodeErrors.empty()) << decodeErrors;
}
TEST(DecodeSingleDeviceBinaryZebin, WhenZeInfoVersionIsInvalidThenFails) {
ZebinTestData::ValidEmptyProgram zebin;
zebin.removeSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo);
auto zeInfo = ConstStringRef("version:\'1a\'\nkernels:\n");
zebin.appendSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, ArrayRef<const uint8_t>::fromAny(zeInfo.data(), zeInfo.size()));
NEO::ProgramInfo programInfo;
NEO::SingleDeviceBinary singleBinary;
singleBinary.deviceBinary = zebin.storage;
std::string decodeErrors;
std::string decodeWarnings;
auto error = NEO::decodeSingleDeviceBinary<NEO::DeviceBinaryFormat::Zebin>(programInfo, singleBinary, decodeErrors, decodeWarnings);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, error);
EXPECT_STREQ("DeviceBinaryFormat::Zebin::.ze_info : Invalid version format - expected 'MAJOR.MINOR' string, got : '1a'\n", decodeErrors.c_str());
EXPECT_TRUE(decodeWarnings.empty()) << decodeWarnings;
}
TEST(DecodeSingleDeviceBinaryZebin, WhenZeInfoMinorVersionIsNewerThenEmitsWarning) {
ZebinTestData::ValidEmptyProgram zebin;
zebin.removeSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo);
auto version = NEO::zeInfoDecoderVersion;
version.minor += 1;
auto zeInfo = std::string("version:\'") + toString(version) + "\'\nkernels:\n";
zebin.appendSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, ArrayRef<const uint8_t>::fromAny(zeInfo.data(), zeInfo.size()));
NEO::ProgramInfo programInfo;
NEO::SingleDeviceBinary singleBinary;
singleBinary.deviceBinary = zebin.storage;
std::string decodeErrors;
std::string decodeWarnings;
auto error = NEO::decodeSingleDeviceBinary<NEO::DeviceBinaryFormat::Zebin>(programInfo, singleBinary, decodeErrors, decodeWarnings);
EXPECT_EQ(NEO::DecodeError::Success, error);
EXPECT_STREQ("DeviceBinaryFormat::Zebin::.ze_info : Minor version : 1 is newer than available in decoder : 0 - some features may be skipped\n", decodeWarnings.c_str());
EXPECT_TRUE(decodeErrors.empty()) << decodeErrors;
}
TEST(DecodeSingleDeviceBinaryZebin, WhenZeInfoMajorVersionIsMismatchedThenFails) {
{
ZebinTestData::ValidEmptyProgram zebin;
zebin.removeSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo);
auto version = NEO::zeInfoDecoderVersion;
version.major += 1;
auto zeInfo = std::string("version:\'") + toString(version) + "\'\nkernels:\n";
zebin.appendSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, ArrayRef<const uint8_t>::fromAny(zeInfo.data(), zeInfo.size()));
NEO::ProgramInfo programInfo;
NEO::SingleDeviceBinary singleBinary;
singleBinary.deviceBinary = zebin.storage;
std::string decodeErrors;
std::string decodeWarnings;
auto error = NEO::decodeSingleDeviceBinary<NEO::DeviceBinaryFormat::Zebin>(programInfo, singleBinary, decodeErrors, decodeWarnings);
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, error);
EXPECT_STREQ("DeviceBinaryFormat::Zebin::.ze_info : Unhandled major version : 2, decoder is at : 1\n", decodeErrors.c_str());
EXPECT_TRUE(decodeWarnings.empty()) << decodeWarnings;
}
{
ZebinTestData::ValidEmptyProgram zebin;
zebin.removeSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo);
auto version = NEO::zeInfoDecoderVersion;
version.major -= 1;
auto zeInfo = std::string("version:\'") + toString(version) + "\'\nkernels:\n";
zebin.appendSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, ArrayRef<const uint8_t>::fromAny(zeInfo.data(), zeInfo.size()));
NEO::ProgramInfo programInfo;
NEO::SingleDeviceBinary singleBinary;
singleBinary.deviceBinary = zebin.storage;
std::string decodeErrors;
std::string decodeWarnings;
auto error = NEO::decodeSingleDeviceBinary<NEO::DeviceBinaryFormat::Zebin>(programInfo, singleBinary, decodeErrors, decodeWarnings);
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, error);
EXPECT_STREQ("DeviceBinaryFormat::Zebin::.ze_info : Unhandled major version : 0, decoder is at : 1\n", decodeErrors.c_str());
EXPECT_TRUE(decodeWarnings.empty()) << decodeWarnings;
}
}
TEST(DecodeSingleDeviceBinaryZebin, WhenDecodeZeInfoFailsThenDecodingFails) { TEST(DecodeSingleDeviceBinaryZebin, WhenDecodeZeInfoFailsThenDecodingFails) {
NEO::ConstStringRef brokenZeInfo = R"===( std::string brokenZeInfo = "version : \'" + toString(zeInfoDecoderVersion) + R"===('
kernels: kernels:
- -
)==="; )===";
@@ -1593,7 +1923,7 @@ kernels:
} }
TEST(DecodeSingleDeviceBinaryZebin, GivenValidZeInfoThenPopulatesKernelDescriptorProperly) { TEST(DecodeSingleDeviceBinaryZebin, GivenValidZeInfoThenPopulatesKernelDescriptorProperly) {
NEO::ConstStringRef validZeInfo = R"===( std::string validZeInfo = std::string("version :\'") + toString(zeInfoDecoderVersion) + R"===('
kernels: kernels:
- name : some_kernel - name : some_kernel
execution_env : execution_env :
@@ -2188,11 +2518,10 @@ kernels:
EXPECT_TRUE(errors.empty()) << errors; EXPECT_TRUE(errors.empty()) << errors;
EXPECT_TRUE(warnings.empty()) << warnings; EXPECT_TRUE(warnings.empty()) << warnings;
ASSERT_EQ(1U, programInfo.kernelInfos.size()); ASSERT_EQ(1U, programInfo.kernelInfos.size());
EXPECT_EQ(256U, programInfo.kernelInfos[0]->kernelDescriptor.kernelAttributes.perThreadPrivateMemorySize); EXPECT_EQ(256U, programInfo.kernelInfos[0]->kernelDescriptor.kernelAttributes.perHwThreadPrivateMemorySize);
EXPECT_FALSE(programInfo.kernelInfos[0]->kernelDescriptor.kernelAttributes.flags.isSimtThread);
} }
TEST(PopulateKernelDescriptor, givenSimtThreadSetWhenPopulatingThenUpdateKernelAttributes) { TEST(PopulateKernelDescriptor, givenPerSimtThreadBufferWhenPopulatingThenCalculatesCorrectSize) {
NEO::ConstStringRef zeinfo = R"===( NEO::ConstStringRef zeinfo = R"===(
kernels: kernels:
- name : some_kernel - name : some_kernel
@@ -2224,7 +2553,8 @@ kernels:
EXPECT_EQ(NEO::DecodeError::Success, err); EXPECT_EQ(NEO::DecodeError::Success, err);
EXPECT_TRUE(errors.empty()) << errors; EXPECT_TRUE(errors.empty()) << errors;
EXPECT_TRUE(warnings.empty()) << warnings; EXPECT_TRUE(warnings.empty()) << warnings;
EXPECT_TRUE(programInfo.kernelInfos[0]->kernelDescriptor.kernelAttributes.flags.isSimtThread); ASSERT_EQ(1U, programInfo.kernelInfos.size());
EXPECT_EQ(256U * 8, programInfo.kernelInfos[0]->kernelDescriptor.kernelAttributes.perHwThreadPrivateMemorySize);
} }
TEST(PopulateKernelDescriptor, GivenPerThreadMemoryBufferWhenTypeIsScratchThenSetsProperFieldsInDescriptor) { TEST(PopulateKernelDescriptor, GivenPerThreadMemoryBufferWhenTypeIsScratchThenSetsProperFieldsInDescriptor) {
@@ -2263,7 +2593,78 @@ kernels:
EXPECT_EQ(0U, programInfo.kernelInfos[0]->kernelDescriptor.kernelAttributes.perThreadScratchSize[1]); EXPECT_EQ(0U, programInfo.kernelInfos[0]->kernelDescriptor.kernelAttributes.perThreadScratchSize[1]);
} }
TEST(PopulateKernelDescriptor, GivenPerThreadMemoryBufferWithMultipleScratchEntriesThenFails) { TEST(PopulateKernelDescriptor, GivenPerThreadMemoryBufferWhenSlotIsProvidedThenSetsProperFieldsInDescriptorInCorrectSlot) {
NEO::ConstStringRef zeinfo = R"===(
kernels:
- name : some_kernel
execution_env:
simd_size: 8
per_thread_memory_buffers:
- type: scratch
usage: private_space
size: 512
slot : 1
)===";
NEO::ProgramInfo programInfo;
ZebinTestData::ValidEmptyProgram zebin;
zebin.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::textPrefix.str() + "some_kernel", {});
std::string errors, warnings;
auto elf = NEO::Elf::decodeElf(zebin.storage, errors, warnings);
ASSERT_NE(nullptr, elf.elfFileHeader) << errors << " " << warnings;
NEO::Yaml::YamlParser parser;
bool parseSuccess = parser.parse(zeinfo, errors, warnings);
ASSERT_TRUE(parseSuccess) << errors << " " << warnings;
NEO::ZebinSections zebinSections;
auto extractErr = NEO::extractZebinSections(elf, zebinSections, errors, warnings);
ASSERT_EQ(NEO::DecodeError::Success, extractErr) << errors << " " << warnings;
auto &kernelNode = *parser.createChildrenRange(*parser.findNodeWithKeyDfs("kernels")).begin();
auto err = NEO::populateKernelDescriptor(programInfo, elf, zebinSections, parser, kernelNode, errors, warnings);
EXPECT_EQ(NEO::DecodeError::Success, err);
EXPECT_TRUE(errors.empty()) << errors;
EXPECT_TRUE(warnings.empty()) << warnings;
ASSERT_EQ(1U, programInfo.kernelInfos.size());
EXPECT_EQ(0U, programInfo.kernelInfos[0]->kernelDescriptor.kernelAttributes.perThreadScratchSize[0]);
EXPECT_EQ(512U, programInfo.kernelInfos[0]->kernelDescriptor.kernelAttributes.perThreadScratchSize[1]);
}
TEST(PopulateKernelDescriptor, GivenPerThreadMemoryBufferWhenSlotIsInvalidThenFails) {
NEO::ConstStringRef zeinfo = R"===(
kernels:
- name : some_kernel
execution_env:
simd_size: 8
per_thread_memory_buffers:
- type: scratch
usage: private_space
size: 512
slot : 2
)===";
NEO::ProgramInfo programInfo;
ZebinTestData::ValidEmptyProgram zebin;
zebin.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::textPrefix.str() + "some_kernel", {});
std::string errors, warnings;
auto elf = NEO::Elf::decodeElf(zebin.storage, errors, warnings);
ASSERT_NE(nullptr, elf.elfFileHeader) << errors << " " << warnings;
NEO::Yaml::YamlParser parser;
bool parseSuccess = parser.parse(zeinfo, errors, warnings);
ASSERT_TRUE(parseSuccess) << errors << " " << warnings;
NEO::ZebinSections zebinSections;
auto extractErr = NEO::extractZebinSections(elf, zebinSections, errors, warnings);
ASSERT_EQ(NEO::DecodeError::Success, extractErr) << errors << " " << warnings;
auto &kernelNode = *parser.createChildrenRange(*parser.findNodeWithKeyDfs("kernels")).begin();
auto err = NEO::populateKernelDescriptor(programInfo, elf, zebinSections, parser, kernelNode, errors, warnings);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, err);
EXPECT_STREQ("DeviceBinaryFormat::Zebin : Invalid scratch buffer slot 2 in context of : some_kernel. Expected 0 or 1.\n", errors.c_str());
EXPECT_TRUE(warnings.empty()) << warnings;
}
TEST(PopulateKernelDescriptor, GivenPerThreadMemoryBufferWithMultipleScratchEntriesForTheSameSlotThenFails) {
NEO::ConstStringRef zeinfo = R"===( NEO::ConstStringRef zeinfo = R"===(
kernels: kernels:
- name : some_kernel - name : some_kernel
@@ -2298,7 +2699,7 @@ kernels:
auto err = NEO::populateKernelDescriptor(programInfo, elf, zebinSections, parser, kernelNode, decodeErrors, decodeWarnings); auto err = NEO::populateKernelDescriptor(programInfo, elf, zebinSections, parser, kernelNode, decodeErrors, decodeWarnings);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, err); EXPECT_EQ(NEO::DecodeError::InvalidBinary, err);
EXPECT_TRUE(decodeWarnings.empty()) << decodeWarnings; EXPECT_TRUE(decodeWarnings.empty()) << decodeWarnings;
EXPECT_STREQ("DeviceBinaryFormat::Zebin : Invalid duplicated scratch buffer entry in context of : some_kernel.\n", decodeErrors.c_str()); EXPECT_STREQ("DeviceBinaryFormat::Zebin : Invalid duplicated scratch buffer entry 0 in context of : some_kernel.\n", decodeErrors.c_str());
} }
TEST(PopulateKernelDescriptor, GivenKernelWithoutCorrespondingTextSectionThenFail) { TEST(PopulateKernelDescriptor, GivenKernelWithoutCorrespondingTextSectionThenFail) {
@@ -2325,7 +2726,7 @@ kernels:
auto &kernelNode = *parser.createChildrenRange(*parser.findNodeWithKeyDfs("kernels")).begin(); auto &kernelNode = *parser.createChildrenRange(*parser.findNodeWithKeyDfs("kernels")).begin();
auto err = NEO::populateKernelDescriptor(programInfo, elf, zebinSections, parser, kernelNode, errors, warnings); auto err = NEO::populateKernelDescriptor(programInfo, elf, zebinSections, parser, kernelNode, errors, warnings);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, err); EXPECT_EQ(NEO::DecodeError::InvalidBinary, err);
EXPECT_STREQ("Could not find text section for kernel some_kernel\n", errors.c_str()); EXPECT_STREQ("DeviceBinaryFormat::Zebin : Could not find text section for kernel some_kernel\n", errors.c_str());
EXPECT_TRUE(warnings.empty()) << warnings; EXPECT_TRUE(warnings.empty()) << warnings;
} }
@@ -2809,6 +3210,7 @@ TEST(PopulateArgDescriptorCrossthreadPalyoad, GivenPointerArgWhenMemoryAcessMode
break; break;
case AddressingMode::MemoryAddressingModeSharedLocalMemory: case AddressingMode::MemoryAddressingModeSharedLocalMemory:
EXPECT_EQ(16, argAsPointer.slmOffset); EXPECT_EQ(16, argAsPointer.slmOffset);
EXPECT_EQ(16, argAsPointer.requiredSlmAlignment);
break; break;
} }
} }

View File

@@ -10,6 +10,7 @@
#include "shared/source/device_binary_format/elf/elf_decoder.h" #include "shared/source/device_binary_format/elf/elf_decoder.h"
#include "shared/source/device_binary_format/elf/elf_encoder.h" #include "shared/source/device_binary_format/elf/elf_encoder.h"
#include "shared/source/device_binary_format/elf/zebin_elf.h" #include "shared/source/device_binary_format/elf/zebin_elf.h"
#include "shared/source/device_binary_format/zebin_decoder.h"
#include "igfxfmid.h" #include "igfxfmid.h"
@@ -17,6 +18,10 @@
extern PRODUCT_FAMILY productFamily; extern PRODUCT_FAMILY productFamily;
inline std::string toString(NEO::Elf::ZebinKernelMetadata::Types::Version version) {
return std::to_string(version.major) + "." + std::to_string(version.minor);
}
namespace ZebinTestData { namespace ZebinTestData {
struct ValidEmptyProgram { struct ValidEmptyProgram {
@@ -24,7 +29,8 @@ struct ValidEmptyProgram {
NEO::Elf::ElfEncoder<> enc; NEO::Elf::ElfEncoder<> enc;
enc.getElfFileHeader().type = NEO::Elf::ET_ZEBIN_EXE; enc.getElfFileHeader().type = NEO::Elf::ET_ZEBIN_EXE;
enc.getElfFileHeader().machine = productFamily; enc.getElfFileHeader().machine = productFamily;
enc.appendSection(NEO::Elf::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, std::string{"---\nkernels : \n...\n"}); auto zeInfo = std::string{"---\nversion : \'" + toString(NEO::zeInfoDecoderVersion) + "\'" + "\nkernels : \n...\n"};
enc.appendSection(NEO::Elf::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, zeInfo);
storage = enc.encode(); storage = enc.encode();
recalcPtr(); recalcPtr();
} }

View File

@@ -257,7 +257,7 @@ TEST(KernelDescriptorFromPatchtokens, GivenImplicitArgsThenSetsProperPartsOfDesc
kernelTokens.tokens.dataParameterStream = nullptr; kernelTokens.tokens.dataParameterStream = nullptr;
EXPECT_FALSE(kernelDescriptor.kernelAttributes.flags.usesPrivateMemory); EXPECT_FALSE(kernelDescriptor.kernelAttributes.flags.usesPrivateMemory);
EXPECT_EQ(0U, kernelDescriptor.kernelAttributes.perThreadPrivateMemorySize); EXPECT_EQ(0U, kernelDescriptor.kernelAttributes.perHwThreadPrivateMemorySize);
EXPECT_TRUE(NEO::isUndefinedOffset(kernelDescriptor.payloadMappings.implicitArgs.privateMemoryAddress.stateless)); EXPECT_TRUE(NEO::isUndefinedOffset(kernelDescriptor.payloadMappings.implicitArgs.privateMemoryAddress.stateless));
EXPECT_EQ(0U, kernelDescriptor.payloadMappings.implicitArgs.privateMemoryAddress.pointerSize); EXPECT_EQ(0U, kernelDescriptor.payloadMappings.implicitArgs.privateMemoryAddress.pointerSize);
EXPECT_TRUE(NEO::isUndefinedOffset(kernelDescriptor.payloadMappings.implicitArgs.privateMemoryAddress.bindful)); EXPECT_TRUE(NEO::isUndefinedOffset(kernelDescriptor.payloadMappings.implicitArgs.privateMemoryAddress.bindful));
@@ -271,8 +271,7 @@ TEST(KernelDescriptorFromPatchtokens, GivenImplicitArgsThenSetsProperPartsOfDesc
kernelTokens.tokens.allocateStatelessPrivateSurface = &privateSurface; kernelTokens.tokens.allocateStatelessPrivateSurface = &privateSurface;
NEO::populateKernelDescriptor(kernelDescriptor, kernelTokens, 4); NEO::populateKernelDescriptor(kernelDescriptor, kernelTokens, 4);
EXPECT_TRUE(kernelDescriptor.kernelAttributes.flags.usesPrivateMemory); EXPECT_TRUE(kernelDescriptor.kernelAttributes.flags.usesPrivateMemory);
EXPECT_TRUE(kernelDescriptor.kernelAttributes.flags.isSimtThread); EXPECT_EQ(NEO::PatchTokenBinary::getPerHwThreadPrivateSurfaceSize(&privateSurface, kernelDescriptor.kernelAttributes.simdSize), kernelDescriptor.kernelAttributes.perHwThreadPrivateMemorySize);
EXPECT_EQ(privateSurface.PerThreadPrivateMemorySize, kernelDescriptor.kernelAttributes.perThreadPrivateMemorySize);
EXPECT_EQ(privateSurface.DataParamOffset, kernelDescriptor.payloadMappings.implicitArgs.privateMemoryAddress.stateless); EXPECT_EQ(privateSurface.DataParamOffset, kernelDescriptor.payloadMappings.implicitArgs.privateMemoryAddress.stateless);
EXPECT_EQ(privateSurface.DataParamSize, kernelDescriptor.payloadMappings.implicitArgs.privateMemoryAddress.pointerSize); EXPECT_EQ(privateSurface.DataParamSize, kernelDescriptor.payloadMappings.implicitArgs.privateMemoryAddress.pointerSize);
EXPECT_EQ(privateSurface.SurfaceStateHeapOffset, kernelDescriptor.payloadMappings.implicitArgs.privateMemoryAddress.bindful); EXPECT_EQ(privateSurface.SurfaceStateHeapOffset, kernelDescriptor.payloadMappings.implicitArgs.privateMemoryAddress.bindful);

View File

@@ -13,11 +13,10 @@
TEST(KernelDescriptor, WhenDefaultInitializedThenValuesAreCleared) { TEST(KernelDescriptor, WhenDefaultInitializedThenValuesAreCleared) {
NEO::KernelDescriptor desc; NEO::KernelDescriptor desc;
EXPECT_EQ(0U, desc.kernelAttributes.flags.packed); EXPECT_EQ(0U, desc.kernelAttributes.flags.packed);
EXPECT_FALSE(desc.kernelAttributes.flags.isSimtThread);
EXPECT_EQ(0U, desc.kernelAttributes.slmInlineSize); EXPECT_EQ(0U, desc.kernelAttributes.slmInlineSize);
EXPECT_EQ(0U, desc.kernelAttributes.perThreadScratchSize[0]); EXPECT_EQ(0U, desc.kernelAttributes.perThreadScratchSize[0]);
EXPECT_EQ(0U, desc.kernelAttributes.perThreadScratchSize[1]); EXPECT_EQ(0U, desc.kernelAttributes.perThreadScratchSize[1]);
EXPECT_EQ(0U, desc.kernelAttributes.perThreadPrivateMemorySize); EXPECT_EQ(0U, desc.kernelAttributes.perHwThreadPrivateMemorySize);
EXPECT_EQ(0U, desc.kernelAttributes.perThreadSystemThreadSurfaceSize); EXPECT_EQ(0U, desc.kernelAttributes.perThreadSystemThreadSurfaceSize);
EXPECT_EQ(0U, desc.kernelAttributes.requiredWorkgroupSize[0]); EXPECT_EQ(0U, desc.kernelAttributes.requiredWorkgroupSize[0]);
EXPECT_EQ(0U, desc.kernelAttributes.requiredWorkgroupSize[1]); EXPECT_EQ(0U, desc.kernelAttributes.requiredWorkgroupSize[1]);