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

@@ -5,7 +5,6 @@
*
*/
// Abstract: Defines the types used for ELF headers/sections.
#pragma once
#include "shared/source/device_binary_format/elf/elf.h"
@@ -85,6 +84,7 @@ static_assert(sizeof(ZebinTargetFlags) == sizeof(uint32_t), "");
namespace ZebinKernelMetadata {
namespace Tags {
static constexpr ConstStringRef kernels("kernels");
static constexpr ConstStringRef version("version");
namespace Kernel {
static constexpr ConstStringRef name("name");
static constexpr ConstStringRef executionEnv("execution_env");
@@ -137,7 +137,7 @@ namespace MemoryAddressingMode {
static constexpr ConstStringRef stateless("stateless");
static constexpr ConstStringRef stateful("stateful");
static constexpr ConstStringRef bindless("bindless");
static constexpr ConstStringRef sharedLocalMemory("shared_local_memory");
static constexpr ConstStringRef sharedLocalMemory("slm");
} // namespace MemoryAddressingMode
namespace AddrSpace {
static constexpr ConstStringRef global("global");
@@ -173,6 +173,7 @@ static constexpr ConstStringRef allocationType("type");
static constexpr ConstStringRef memoryUsage("usage");
static constexpr ConstStringRef size("size");
static constexpr ConstStringRef isSimtThread("is_simt_thread");
static constexpr ConstStringRef slot("slot");
namespace AllocationType {
static constexpr ConstStringRef global("global");
static constexpr ConstStringRef scratch("scratch");
@@ -189,6 +190,11 @@ static constexpr ConstStringRef singleSpace("single_space");
namespace Types {
struct Version {
uint32_t major = 0U;
uint32_t minor = 0U;
};
namespace Kernel {
namespace ExecutionEnv {
using ActualKernelStartOffsetT = int32_t;
@@ -323,10 +329,12 @@ using ArgIndexT = int32_t;
using AddrmodeT = MemoryAddressingMode;
using AddrspaceT = AddressSpace;
using AccessTypeT = AccessType;
using SlmAlignment = uint8_t;
namespace Defaults {
static constexpr ArgIndexT argIndex = -1;
}
static constexpr SlmAlignment slmArgAlignment = 16U;
} // namespace Defaults
struct PayloadArgumentBaseT {
ArgTypeT argType = ArgTypeUnknown;
@@ -367,12 +375,20 @@ enum MemoryUsage : uint8_t {
using SizeT = int32_t;
using AllocationTypeT = AllocationType;
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 {
AllocationType allocationType = AllocationTypeUnknown;
MemoryUsageT memoryUsage = MemoryUsageUnknown;
SizeT size = 0U;
bool isSimtThread = false;
IsSimtThreadT isSimtThread = Defaults::isSimtThread;
Slot slot = Defaults::slot;
};
} // 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));
}
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 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;
auto parseTokEnd = consumeStringLiteral(text, 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;
}
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);
} else if (NEO::Elf::ZebinKernelMetadata::Tags::Kernel::PerThreadMemoryBuffer::isSimtThread == key) {
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 {
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;
break;
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;
@@ -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::Tags::Kernel::PerThreadMemoryBuffer::AllocationType;
using namespace NEO::Elf::ZebinKernelMetadata::Tags::Kernel::PerThreadMemoryBuffer::MemoryUsage;
auto size = src.size;
if (src.isSimtThread) {
size *= dst.kernelAttributes.simdSize;
}
switch (src.allocationType) {
default:
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;
}
dst.kernelAttributes.perThreadPrivateMemorySize = src.size;
dst.kernelAttributes.flags.isSimtThread = src.isSimtThread;
dst.kernelAttributes.perHwThreadPrivateMemorySize = size;
break;
case AllocationTypeScratch:
if (0 != dst.kernelAttributes.perThreadScratchSize[0]) {
outErrReason.append("DeviceBinaryFormat::Zebin : Invalid duplicated scratch buffer entry in context of : " + dst.kernelMetadata.kernelName + ".\n");
if (src.slot > 1) {
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;
}
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;
}
return DecodeError::Success;
@@ -884,7 +894,7 @@ NEO::DecodeError populateKernelDescriptor(NEO::ProgramInfo &dst, NEO::Elf::Elf<N
}
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;
}
@@ -897,6 +907,26 @@ NEO::DecodeError populateKernelDescriptor(NEO::ProgramInfo &dst, NEO::Elf::Elf<N
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 <>
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);
@@ -954,15 +984,44 @@ DecodeError decodeSingleDeviceBinary<NEO::DeviceBinaryFormat::Zebin>(ProgramInfo
}
UniqueNode kernelsSectionNodes;
UniqueNode versionSectionNodes;
for (const auto &globalScopeNd : yamlParser.createChildrenRange(*yamlParser.getRoot())) {
auto key = yamlParser.readKey(globalScopeNd);
if (NEO::Elf::ZebinKernelMetadata::Tags::kernels == key) {
kernelsSectionNodes.push_back(&globalScopeNd);
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");
}
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) {
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;

View File

@@ -5,6 +5,8 @@
*
*/
#pragma once
#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/zebin_elf.h"
@@ -16,6 +18,8 @@
namespace NEO {
static constexpr NEO::Elf::ZebinKernelMetadata::Types::Version zeInfoDecoderVersion{1, 0};
struct ZebinSections {
using SectionHeaderData = NEO::Elf::Elf<Elf::EI_CLASS_64>::SectionHeaderAndData;
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::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

View File

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

View File

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

View File

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

View File

@@ -885,7 +885,7 @@ TEST(YamlTokenize, GivenUnterminatedStringLiteralsThenReturnsError) {
std::string errors;
bool success = NEO::Yaml::tokenize(yaml, lines, tokens, errors, warnings);
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;
}

View File

@@ -224,6 +224,189 @@ TEST(ValidateZebinSectionsCount, GivenTwoSpirvSectionsThenFail) {
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) {
NEO::ConstStringRef yaml = R"===(---
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::MemoryUsageSingleSpace, buffers[0].memoryUsage);
EXPECT_FALSE(buffers[0].isSimtThread);
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::MemoryUsagePrivateSpace, buffers[1].memoryUsage);
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) {
@@ -1523,7 +1743,7 @@ TEST(DecodeSingleDeviceBinaryZebin, GivenEmptyInZeInfoThenEmitsWarning) {
TEST(DecodeSingleDeviceBinaryZebin, GivenUnknownEntryInZeInfoGlobalScopeThenEmitsWarning) {
ZebinTestData::ValidEmptyProgram zebin;
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()));
NEO::ProgramInfo programInfo;
@@ -1540,7 +1760,7 @@ TEST(DecodeSingleDeviceBinaryZebin, GivenUnknownEntryInZeInfoGlobalScopeThenEmit
TEST(DecodeSingleDeviceBinaryZebin, WhenZeInfoDoesNotContainKernelsSectionThenEmitsWarning) {
ZebinTestData::ValidEmptyProgram zebin;
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()));
NEO::ProgramInfo programInfo;
@@ -1557,7 +1777,7 @@ TEST(DecodeSingleDeviceBinaryZebin, WhenZeInfoDoesNotContainKernelsSectionThenEm
TEST(DecodeSingleDeviceBinaryZebin, WhenZeInfoContainsMultipleKernelSectionsThenFails) {
ZebinTestData::ValidEmptyProgram zebin;
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()));
NEO::ProgramInfo programInfo;
@@ -1571,8 +1791,118 @@ TEST(DecodeSingleDeviceBinaryZebin, WhenZeInfoContainsMultipleKernelSectionsThen
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) {
NEO::ConstStringRef brokenZeInfo = R"===(
std::string brokenZeInfo = "version : \'" + toString(zeInfoDecoderVersion) + R"===('
kernels:
-
)===";
@@ -1593,7 +1923,7 @@ kernels:
}
TEST(DecodeSingleDeviceBinaryZebin, GivenValidZeInfoThenPopulatesKernelDescriptorProperly) {
NEO::ConstStringRef validZeInfo = R"===(
std::string validZeInfo = std::string("version :\'") + toString(zeInfoDecoderVersion) + R"===('
kernels:
- name : some_kernel
execution_env :
@@ -2188,11 +2518,10 @@ kernels:
EXPECT_TRUE(errors.empty()) << errors;
EXPECT_TRUE(warnings.empty()) << warnings;
ASSERT_EQ(1U, programInfo.kernelInfos.size());
EXPECT_EQ(256U, programInfo.kernelInfos[0]->kernelDescriptor.kernelAttributes.perThreadPrivateMemorySize);
EXPECT_FALSE(programInfo.kernelInfos[0]->kernelDescriptor.kernelAttributes.flags.isSimtThread);
EXPECT_EQ(256U, programInfo.kernelInfos[0]->kernelDescriptor.kernelAttributes.perHwThreadPrivateMemorySize);
}
TEST(PopulateKernelDescriptor, givenSimtThreadSetWhenPopulatingThenUpdateKernelAttributes) {
TEST(PopulateKernelDescriptor, givenPerSimtThreadBufferWhenPopulatingThenCalculatesCorrectSize) {
NEO::ConstStringRef zeinfo = R"===(
kernels:
- name : some_kernel
@@ -2224,7 +2553,8 @@ kernels:
EXPECT_EQ(NEO::DecodeError::Success, err);
EXPECT_TRUE(errors.empty()) << errors;
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) {
@@ -2263,7 +2593,78 @@ kernels:
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"===(
kernels:
- name : some_kernel
@@ -2298,7 +2699,7 @@ kernels:
auto err = NEO::populateKernelDescriptor(programInfo, elf, zebinSections, parser, kernelNode, decodeErrors, decodeWarnings);
EXPECT_EQ(NEO::DecodeError::InvalidBinary, err);
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) {
@@ -2325,7 +2726,7 @@ kernels:
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("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;
}
@@ -2809,6 +3210,7 @@ TEST(PopulateArgDescriptorCrossthreadPalyoad, GivenPointerArgWhenMemoryAcessMode
break;
case AddressingMode::MemoryAddressingModeSharedLocalMemory:
EXPECT_EQ(16, argAsPointer.slmOffset);
EXPECT_EQ(16, argAsPointer.requiredSlmAlignment);
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_encoder.h"
#include "shared/source/device_binary_format/elf/zebin_elf.h"
#include "shared/source/device_binary_format/zebin_decoder.h"
#include "igfxfmid.h"
@@ -17,6 +18,10 @@
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 {
struct ValidEmptyProgram {
@@ -24,7 +29,8 @@ struct ValidEmptyProgram {
NEO::Elf::ElfEncoder<> enc;
enc.getElfFileHeader().type = NEO::Elf::ET_ZEBIN_EXE;
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();
recalcPtr();
}

View File

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

View File

@@ -13,11 +13,10 @@
TEST(KernelDescriptor, WhenDefaultInitializedThenValuesAreCleared) {
NEO::KernelDescriptor desc;
EXPECT_EQ(0U, desc.kernelAttributes.flags.packed);
EXPECT_FALSE(desc.kernelAttributes.flags.isSimtThread);
EXPECT_EQ(0U, desc.kernelAttributes.slmInlineSize);
EXPECT_EQ(0U, desc.kernelAttributes.perThreadScratchSize[0]);
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.requiredWorkgroupSize[0]);
EXPECT_EQ(0U, desc.kernelAttributes.requiredWorkgroupSize[1]);