zebin: add support for kernels source attributes

This commit adds parsing of "user_attributes" section of zeInfo
containing kernel's language attributes.

Signed-off-by: Krystian Chmielewski <krystian.chmielewski@intel.com>
This commit is contained in:
Krystian Chmielewski 2022-09-07 13:21:53 +00:00 committed by Compute-Runtime-Automation
parent 9c82238c1e
commit 5af2bc8a60
4 changed files with 268 additions and 3 deletions

View File

@ -11,8 +11,10 @@
#include "shared/source/device_binary_format/elf/elf_decoder.h" #include "shared/source/device_binary_format/elf/elf_decoder.h"
#include "shared/source/utilities/const_stringref.h" #include "shared/source/utilities/const_stringref.h"
#include <inttypes.h> #include <array>
#include <stddef.h> #include <cinttypes>
#include <cstddef>
#include <optional>
namespace NEO { namespace NEO {
@ -120,6 +122,7 @@ constexpr ConstStringRef globalHostAccessTable("global_host_access_table");
constexpr ConstStringRef functions("functions"); constexpr ConstStringRef functions("functions");
namespace Kernel { namespace Kernel {
constexpr ConstStringRef attributes("user_attributes");
constexpr ConstStringRef name("name"); constexpr ConstStringRef name("name");
constexpr ConstStringRef executionEnv("execution_env"); constexpr ConstStringRef executionEnv("execution_env");
constexpr ConstStringRef debugEnv("debug_env"); constexpr ConstStringRef debugEnv("debug_env");
@ -159,6 +162,16 @@ constexpr ConstStringRef roundRobinStall("round_robin_stall");
} // namespace ThreadSchedulingMode } // namespace ThreadSchedulingMode
} // namespace ExecutionEnv } // namespace ExecutionEnv
namespace Attributes {
constexpr ConstStringRef intelReqdSubgroupSize("intel_reqd_sub_group_size");
constexpr ConstStringRef intelReqdWorkgroupWalkOrder("intel_reqd_workgroup_walk_order");
constexpr ConstStringRef reqdWorkgroupSize("reqd_work_group_size");
constexpr ConstStringRef invalidKernel("invalid_kernel");
constexpr ConstStringRef vecTypeHint("vec_type_hint");
constexpr ConstStringRef workgroupSizeHint("work_group_size_hint");
constexpr ConstStringRef hintSuffix("_hint");
} // namespace Attributes
namespace DebugEnv { namespace DebugEnv {
constexpr ConstStringRef debugSurfaceBTI("sip_surface_bti"); constexpr ConstStringRef debugSurfaceBTI("sip_surface_bti");
} // namespace DebugEnv } // namespace DebugEnv
@ -429,6 +442,32 @@ struct ExperimentalPropertiesBaseT {
} // namespace ExecutionEnv } // namespace ExecutionEnv
namespace Attributes {
using IntelReqdSubgroupSizeT = int32_t;
using IntelReqdWorkgroupWalkOrder = std::array<int32_t, 3>;
using ReqdWorkgroupSizeT = std::array<int32_t, 3>;
using InvalidKernelT = ConstStringRef;
using WorkgroupSizeHint = std::array<int32_t, 3>;
using VecTypeHintT = ConstStringRef;
namespace Defaults {
constexpr IntelReqdSubgroupSizeT intelReqdSubgroupSize = 0;
constexpr IntelReqdWorkgroupWalkOrder intelReqdWorkgroupWalkOrder = {0, 0, 0};
constexpr ReqdWorkgroupSizeT reqdWorkgroupSize = {0, 0, 0};
constexpr WorkgroupSizeHint workgroupSizeHint = {0, 0, 0};
} // namespace Defaults
struct AttributesBaseT {
std::optional<IntelReqdSubgroupSizeT> intelReqdSubgroupSize;
std::optional<IntelReqdWorkgroupWalkOrder> intelReqdWorkgroupWalkOrder;
std::optional<ReqdWorkgroupSizeT> reqdWorkgroupSize;
std::optional<InvalidKernelT> invalidKernel;
std::optional<WorkgroupSizeHint> workgroupSizeHint;
std::optional<VecTypeHintT> vecTypeHint;
std::vector<std::pair<ConstStringRef, ConstStringRef>> otherHints;
};
} // namespace Attributes
namespace DebugEnv { namespace DebugEnv {
using DebugSurfaceBTIT = int32_t; using DebugSurfaceBTIT = int32_t;

View File

@ -251,6 +251,8 @@ void extractZeInfoKernelSections(const NEO::Yaml::YamlParser &parser, const NEO:
auto key = parser.readKey(kernelMetadataNd); auto key = parser.readKey(kernelMetadataNd);
if (NEO::Elf::ZebinKernelMetadata::Tags::Kernel::name == key) { if (NEO::Elf::ZebinKernelMetadata::Tags::Kernel::name == key) {
outZeInfoKernelSections.nameNd.push_back(&kernelMetadataNd); outZeInfoKernelSections.nameNd.push_back(&kernelMetadataNd);
} else if (NEO::Elf::ZebinKernelMetadata::Tags::Kernel::attributes == key) {
outZeInfoKernelSections.attributesNd.push_back(&kernelMetadataNd);
} else if (NEO::Elf::ZebinKernelMetadata::Tags::Kernel::executionEnv == key) { } else if (NEO::Elf::ZebinKernelMetadata::Tags::Kernel::executionEnv == key) {
outZeInfoKernelSections.executionEnvNd.push_back(&kernelMetadataNd); outZeInfoKernelSections.executionEnvNd.push_back(&kernelMetadataNd);
} else if (NEO::Elf::ZebinKernelMetadata::Tags::Kernel::debugEnv == key) { } else if (NEO::Elf::ZebinKernelMetadata::Tags::Kernel::debugEnv == key) {
@ -274,6 +276,7 @@ void extractZeInfoKernelSections(const NEO::Yaml::YamlParser &parser, const NEO:
DecodeError validateZeInfoKernelSectionsCount(const ZeInfoKernelSections &outZeInfoKernelSections, std::string &outErrReason, std::string &outWarning) { DecodeError validateZeInfoKernelSectionsCount(const ZeInfoKernelSections &outZeInfoKernelSections, std::string &outErrReason, std::string &outWarning) {
bool valid = validateZebinSectionsCountExactly(outZeInfoKernelSections.nameNd, NEO::Elf::ZebinKernelMetadata::Tags::Kernel::name, 1U, outErrReason, outWarning); bool valid = validateZebinSectionsCountExactly(outZeInfoKernelSections.nameNd, NEO::Elf::ZebinKernelMetadata::Tags::Kernel::name, 1U, outErrReason, outWarning);
valid &= validateZebinSectionsCountExactly(outZeInfoKernelSections.executionEnvNd, NEO::Elf::ZebinKernelMetadata::Tags::Kernel::executionEnv, 1U, outErrReason, outWarning); valid &= validateZebinSectionsCountExactly(outZeInfoKernelSections.executionEnvNd, NEO::Elf::ZebinKernelMetadata::Tags::Kernel::executionEnv, 1U, outErrReason, outWarning);
valid &= validateZebinSectionsCountAtMost(outZeInfoKernelSections.attributesNd, NEO::Elf::ZebinKernelMetadata::Tags::Kernel::attributes, 1U, outErrReason, outWarning);
valid &= validateZebinSectionsCountAtMost(outZeInfoKernelSections.debugEnvNd, NEO::Elf::ZebinKernelMetadata::Tags::Kernel::debugEnv, 1U, outErrReason, outWarning); valid &= validateZebinSectionsCountAtMost(outZeInfoKernelSections.debugEnvNd, NEO::Elf::ZebinKernelMetadata::Tags::Kernel::debugEnv, 1U, outErrReason, outWarning);
valid &= validateZebinSectionsCountAtMost(outZeInfoKernelSections.payloadArgumentsNd, NEO::Elf::ZebinKernelMetadata::Tags::Kernel::payloadArguments, 1U, outErrReason, outWarning); valid &= validateZebinSectionsCountAtMost(outZeInfoKernelSections.payloadArgumentsNd, NEO::Elf::ZebinKernelMetadata::Tags::Kernel::payloadArguments, 1U, outErrReason, outWarning);
valid &= validateZebinSectionsCountAtMost(outZeInfoKernelSections.perThreadPayloadArgumentsNd, NEO::Elf::ZebinKernelMetadata::Tags::Kernel::perThreadPayloadArguments, 1U, outErrReason, outWarning); valid &= validateZebinSectionsCountAtMost(outZeInfoKernelSections.perThreadPayloadArgumentsNd, NEO::Elf::ZebinKernelMetadata::Tags::Kernel::perThreadPayloadArguments, 1U, outErrReason, outWarning);
@ -294,7 +297,7 @@ bool readZeInfoValueChecked(const NEO::Yaml::YamlParser &parser, const NEO::Yaml
} }
template <typename DestinationT, size_t Len> template <typename DestinationT, size_t Len>
bool readZeInfoValueCollectionChecked(DestinationT (&vec)[Len], const NEO::Yaml::YamlParser &parser, const NEO::Yaml::Node &node, ConstStringRef context, std::string &outErrReason) { bool readZeInfoValueCollectionCheckedArr(std::array<DestinationT, Len> &vec, const NEO::Yaml::YamlParser &parser, const NEO::Yaml::Node &node, ConstStringRef context, std::string &outErrReason) {
auto collectionNodes = parser.createChildrenRange(node); auto collectionNodes = parser.createChildrenRange(node);
size_t index = 0U; size_t index = 0U;
bool isValid = true; bool isValid = true;
@ -310,6 +313,12 @@ bool readZeInfoValueCollectionChecked(DestinationT (&vec)[Len], const NEO::Yaml:
return isValid; return isValid;
} }
template <typename DestinationT, size_t Len>
bool readZeInfoValueCollectionChecked(DestinationT (&vec)[Len], const NEO::Yaml::YamlParser &parser, const NEO::Yaml::Node &node, ConstStringRef context, std::string &outErrReason) {
auto &array = reinterpret_cast<std::array<DestinationT, Len> &>(vec);
return readZeInfoValueCollectionCheckedArr(array, parser, node, context, outErrReason);
}
DecodeError readZeInfoExecutionEnvironment(const NEO::Yaml::YamlParser &parser, const NEO::Yaml::Node &node, DecodeError readZeInfoExecutionEnvironment(const NEO::Yaml::YamlParser &parser, const NEO::Yaml::Node &node,
NEO::Elf::ZebinKernelMetadata::Types::Kernel::ExecutionEnv::ExecutionEnvBaseT &outExecEnv, NEO::Elf::ZebinKernelMetadata::Types::Kernel::ExecutionEnv::ExecutionEnvBaseT &outExecEnv,
ConstStringRef context, ConstStringRef context,
@ -368,6 +377,37 @@ DecodeError readZeInfoExecutionEnvironment(const NEO::Yaml::YamlParser &parser,
return validExecEnv ? DecodeError::Success : DecodeError::InvalidBinary; return validExecEnv ? DecodeError::Success : DecodeError::InvalidBinary;
} }
DecodeError readZeInfoAttributes(const NEO::Yaml::YamlParser &parser, const NEO::Yaml::Node &node, NEO::Elf::ZebinKernelMetadata::Types::Kernel::Attributes::AttributesBaseT &outAttributes, ConstStringRef context, std::string &outErrReason, std::string &outWarning) {
namespace AttributeTypes = NEO::Elf::ZebinKernelMetadata::Types::Kernel::Attributes;
bool validAttributes = true;
for (const auto &attributesMetadataNd : parser.createChildrenRange(node)) {
auto key = parser.readKey(attributesMetadataNd);
if (key == NEO::Elf::ZebinKernelMetadata::Tags::Kernel::Attributes::intelReqdSubgroupSize) {
outAttributes.intelReqdSubgroupSize = AttributeTypes::Defaults::intelReqdSubgroupSize;
validAttributes &= readZeInfoValueChecked(parser, attributesMetadataNd, *outAttributes.intelReqdSubgroupSize, context, outErrReason);
} else if (key == NEO::Elf::ZebinKernelMetadata::Tags::Kernel::Attributes::intelReqdWorkgroupWalkOrder) {
outAttributes.intelReqdWorkgroupWalkOrder = AttributeTypes::Defaults::intelReqdWorkgroupWalkOrder;
validAttributes &= readZeInfoValueCollectionCheckedArr(*outAttributes.intelReqdWorkgroupWalkOrder, parser, attributesMetadataNd, context, outErrReason);
} else if (key == NEO::Elf::ZebinKernelMetadata::Tags::Kernel::Attributes::reqdWorkgroupSize) {
outAttributes.reqdWorkgroupSize = AttributeTypes::Defaults::reqdWorkgroupSize;
validAttributes &= readZeInfoValueCollectionCheckedArr(*outAttributes.reqdWorkgroupSize, parser, attributesMetadataNd, context, outErrReason);
} else if (key == NEO::Elf::ZebinKernelMetadata::Tags::Kernel::Attributes::workgroupSizeHint) {
outAttributes.workgroupSizeHint = AttributeTypes::Defaults::workgroupSizeHint;
validAttributes &= readZeInfoValueCollectionCheckedArr(*outAttributes.workgroupSizeHint, parser, attributesMetadataNd, context, outErrReason);
} else if (key == NEO::Elf::ZebinKernelMetadata::Tags::Kernel::Attributes::invalidKernel) {
outAttributes.invalidKernel = parser.readValue(attributesMetadataNd);
} else if (key == NEO::Elf::ZebinKernelMetadata::Tags::Kernel::Attributes::vecTypeHint) {
outAttributes.vecTypeHint = parser.readValue(attributesMetadataNd);
} else if (key.contains(NEO::Elf::ZebinKernelMetadata::Tags::Kernel::Attributes::hintSuffix.data())) {
outAttributes.otherHints.push_back({key, parser.readValue(attributesMetadataNd)});
} else {
outErrReason.append("DeviceBinaryFormat::Zebin::" + NEO::Elf::SectionsNamesZebin::zeInfo.str() + " : Unknown attribute entry \"" + key.str() + "\" in context of " + context.str() + "\n");
validAttributes = false;
}
}
return validAttributes ? DecodeError::Success : DecodeError::InvalidBinary;
}
DecodeError readZeInfoDebugEnvironment(const NEO::Yaml::YamlParser &parser, const NEO::Yaml::Node &node, DecodeError readZeInfoDebugEnvironment(const NEO::Yaml::YamlParser &parser, const NEO::Yaml::Node &node,
NEO::Elf::ZebinKernelMetadata::Types::Kernel::DebugEnv::DebugEnvBaseT &outDebugEnv, NEO::Elf::ZebinKernelMetadata::Types::Kernel::DebugEnv::DebugEnvBaseT &outDebugEnv,
ConstStringRef context, ConstStringRef context,
@ -1034,6 +1074,15 @@ NEO::DecodeError populateKernelDescriptor(NEO::ProgramInfo &dst, NEO::Elf::Elf<N
return execEnvErr; return execEnvErr;
} }
NEO::Elf::ZebinKernelMetadata::Types::Kernel::Attributes::AttributesBaseT attributes;
if (false == zeInfokernelSections.attributesNd.empty()) {
auto attributeErr = readZeInfoAttributes(yamlParser, *zeInfokernelSections.attributesNd[0], attributes, kernelInfo->kernelDescriptor.kernelMetadata.kernelName, outErrReason, outWarning);
if (DecodeError::Success != attributeErr) {
return attributeErr;
}
populateKernelSourceAttributes(kernelDescriptor, attributes);
}
NEO::Elf::ZebinKernelMetadata::Types::Kernel::DebugEnv::DebugEnvBaseT debugEnv; NEO::Elf::ZebinKernelMetadata::Types::Kernel::DebugEnv::DebugEnvBaseT debugEnv;
if (false == zeInfokernelSections.debugEnvNd.empty()) { if (false == zeInfokernelSections.debugEnvNd.empty()) {
auto debugEnvErr = readZeInfoDebugEnvironment(yamlParser, *zeInfokernelSections.debugEnvNd[0], debugEnv, kernelInfo->kernelDescriptor.kernelMetadata.kernelName, outErrReason, outWarning); auto debugEnvErr = readZeInfoDebugEnvironment(yamlParser, *zeInfokernelSections.debugEnvNd[0], debugEnv, kernelInfo->kernelDescriptor.kernelMetadata.kernelName, outErrReason, outWarning);
@ -1328,6 +1377,48 @@ NEO::DecodeError populateExternalFunctionsMetadata(NEO::ProgramInfo &dst, NEO::Y
} }
} }
std::string attributeToString(const int32_t &attribute) {
return std::to_string(attribute);
}
std::string attributeToString(const std::array<int32_t, 3> &attribute) {
return std::to_string(attribute[0]) + ", " + std::to_string(attribute[1]) + ", " + std::to_string(attribute[2]);
}
std::string attributeToString(ConstStringRef attribute) {
return attribute.str();
}
void appendAttribute(std::string &dst, const std::string &attributeName, const std::string &attributeValue) {
if (dst.empty() == false) {
dst.append(" ");
}
dst.append(attributeName + "(" + attributeValue + ")");
}
template <typename T>
void appendAttributeIfSet(std::string &dst, ConstStringRef attributeName, std::optional<T> &attributeValue) {
if (attributeValue) {
appendAttribute(dst, attributeName.str(), attributeToString(*attributeValue));
}
}
NEO::DecodeError populateKernelSourceAttributes(NEO::KernelDescriptor &dst, NEO::Elf::ZebinKernelMetadata::Types::Kernel::Attributes::AttributesBaseT &attributes) {
namespace AttributeTags = NEO::Elf::ZebinKernelMetadata::Tags::Kernel::Attributes;
namespace AttributeTypes = NEO::Elf::ZebinKernelMetadata::Types::Kernel::Attributes;
auto &languageAttributes = dst.kernelMetadata.kernelLanguageAttributes;
for (auto &hint : attributes.otherHints) {
appendAttribute(languageAttributes, hint.first.str(), hint.second.str());
}
appendAttributeIfSet(languageAttributes, AttributeTags::intelReqdSubgroupSize, attributes.intelReqdSubgroupSize);
appendAttributeIfSet(languageAttributes, AttributeTags::intelReqdWorkgroupWalkOrder, attributes.intelReqdWorkgroupWalkOrder);
appendAttributeIfSet(languageAttributes, AttributeTags::reqdWorkgroupSize, attributes.reqdWorkgroupSize);
appendAttributeIfSet(languageAttributes, AttributeTags::workgroupSizeHint, attributes.workgroupSizeHint);
appendAttributeIfSet(languageAttributes, AttributeTags::vecTypeHint, attributes.vecTypeHint);
appendAttributeIfSet(languageAttributes, AttributeTags::invalidKernel, attributes.invalidKernel);
dst.kernelAttributes.flags.isInvalid = attributes.invalidKernel.has_value();
return 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);

View File

@ -35,6 +35,7 @@ struct ZebinSections {
using UniqueNode = StackVec<const NEO::Yaml::Node *, 1>; using UniqueNode = StackVec<const NEO::Yaml::Node *, 1>;
struct ZeInfoKernelSections { struct ZeInfoKernelSections {
UniqueNode attributesNd;
UniqueNode nameNd; UniqueNode nameNd;
UniqueNode executionEnvNd; UniqueNode executionEnvNd;
UniqueNode debugEnvNd; UniqueNode debugEnvNd;
@ -56,6 +57,9 @@ DecodeError validateZeInfoKernelSectionsCount(const ZeInfoKernelSections &outZeI
DecodeError readZeInfoExecutionEnvironment(const NEO::Yaml::YamlParser &parser, const NEO::Yaml::Node &node, DecodeError readZeInfoExecutionEnvironment(const NEO::Yaml::YamlParser &parser, const NEO::Yaml::Node &node,
NEO::Elf::ZebinKernelMetadata::Types::Kernel::ExecutionEnv::ExecutionEnvBaseT &outExecEnv, NEO::Elf::ZebinKernelMetadata::Types::Kernel::ExecutionEnv::ExecutionEnvBaseT &outExecEnv,
ConstStringRef context, std::string &outErrReason, std::string &outWarning); ConstStringRef context, std::string &outErrReason, std::string &outWarning);
DecodeError readZeInfoAttributes(const NEO::Yaml::YamlParser &parser, const NEO::Yaml::Node &node,
NEO::Elf::ZebinKernelMetadata::Types::Kernel::Attributes::AttributesBaseT &outAttributes,
ConstStringRef context, std::string &outErrReason, std::string &outWarning);
DecodeError readZeInfoDebugEnvironment(const NEO::Yaml::YamlParser &parser, const NEO::Yaml::Node &node, DecodeError readZeInfoDebugEnvironment(const NEO::Yaml::YamlParser &parser, const NEO::Yaml::Node &node,
NEO::Elf::ZebinKernelMetadata::Types::Kernel::DebugEnv::DebugEnvBaseT &outDebugEnv, NEO::Elf::ZebinKernelMetadata::Types::Kernel::DebugEnv::DebugEnvBaseT &outDebugEnv,
ConstStringRef context, ConstStringRef context,
@ -115,4 +119,6 @@ NEO::DecodeError readZeInfoVersionFromZeInfo(NEO::Elf::ZebinKernelMetadata::Type
NEO::DecodeError populateZeInfoVersion(NEO::Elf::ZebinKernelMetadata::Types::Version &dst, ConstStringRef &versionStr, std::string &outErrReason); NEO::DecodeError populateZeInfoVersion(NEO::Elf::ZebinKernelMetadata::Types::Version &dst, ConstStringRef &versionStr, std::string &outErrReason);
NEO::DecodeError populateExternalFunctionsMetadata(NEO::ProgramInfo &dst, NEO::Yaml::YamlParser &yamlParser, const NEO::Yaml::Node &functionNd, std::string &outErrReason, std::string &outWarning); NEO::DecodeError populateExternalFunctionsMetadata(NEO::ProgramInfo &dst, NEO::Yaml::YamlParser &yamlParser, const NEO::Yaml::Node &functionNd, std::string &outErrReason, std::string &outWarning);
NEO::DecodeError populateKernelSourceAttributes(NEO::KernelDescriptor &dst, NEO::Elf::ZebinKernelMetadata::Types::Kernel::Attributes::AttributesBaseT &attributes);
} // namespace NEO } // namespace NEO

View File

@ -1124,6 +1124,51 @@ kernels:
EXPECT_STREQ("DeviceBinaryFormat::Zebin::.ze_info : wrong size of collection required_work_group_size in context of : some_kernel. Got : 2 expected : 3\n", errors.c_str()); EXPECT_STREQ("DeviceBinaryFormat::Zebin::.ze_info : wrong size of collection required_work_group_size in context of : some_kernel. Got : 2 expected : 3\n", errors.c_str());
} }
TEST(ReadZeInfoAttributes, GivenValidYamlEntriesThenSetProperMembers) {
NEO::ConstStringRef yaml = R"===(---
kernels:
- name: some_kernel
user_attributes:
intel_reqd_sub_group_size: 16
intel_reqd_workgroup_walk_order: [0, 1, 2]
reqd_work_group_size: [256, 2, 1]
vec_type_hint: uint
work_group_size_hint: [256, 2, 1]
new_user_hint: new_user_hint_value
invalid_kernel: invalid_kernel_reason
...
)===";
std::string parserErrors;
std::string parserWarnings;
NEO::Yaml::YamlParser parser;
bool success = parser.parse(yaml, parserErrors, parserWarnings);
ASSERT_TRUE(success);
auto &attributeNd = *parser.findNodeWithKeyDfs(NEO::Elf::ZebinKernelMetadata::Tags::Kernel::attributes);
std::string errors;
std::string warnings;
NEO::Elf::ZebinKernelMetadata::Types::Kernel::Attributes::AttributesBaseT attributes;
auto err = NEO::readZeInfoAttributes(parser, attributeNd, attributes, "some_kernel", errors, warnings);
EXPECT_EQ(NEO::DecodeError::Success, err);
EXPECT_TRUE(warnings.empty()) << warnings;
EXPECT_TRUE(errors.empty()) << errors;
EXPECT_EQ(16, attributes.intelReqdSubgroupSize.value());
EXPECT_EQ(0, attributes.intelReqdWorkgroupWalkOrder.value()[0]);
EXPECT_EQ(1, attributes.intelReqdWorkgroupWalkOrder.value()[1]);
EXPECT_EQ(2, attributes.intelReqdWorkgroupWalkOrder.value()[2]);
EXPECT_EQ(256, attributes.reqdWorkgroupSize.value()[0]);
EXPECT_EQ(2, attributes.reqdWorkgroupSize.value()[1]);
EXPECT_EQ(1, attributes.reqdWorkgroupSize.value()[2]);
EXPECT_TRUE(equals(attributes.vecTypeHint.value(), "uint"));
EXPECT_EQ(256, attributes.workgroupSizeHint.value()[0]);
EXPECT_EQ(2, attributes.workgroupSizeHint.value()[1]);
EXPECT_EQ(1, attributes.workgroupSizeHint.value()[2]);
ASSERT_EQ(1U, attributes.otherHints.size());
EXPECT_TRUE(equals(attributes.otherHints[0].first, "new_user_hint"));
EXPECT_TRUE(equals(attributes.otherHints[0].second, "new_user_hint_value"));
EXPECT_TRUE(equals(attributes.invalidKernel.value(), "invalid_kernel_reason"));
}
TEST(ReadZeInfoDebugEnvironment, givenValidYamlEntryThenSetProperMembers) { TEST(ReadZeInfoDebugEnvironment, givenValidYamlEntryThenSetProperMembers) {
NEO::ConstStringRef yaml = R"===(--- NEO::ConstStringRef yaml = R"===(---
kernels: kernels:
@ -1452,6 +1497,90 @@ kernels:
EXPECT_STREQ("Missing source offset value for element in argByValue\n", errors.c_str()); EXPECT_STREQ("Missing source offset value for element in argByValue\n", errors.c_str());
} }
TEST(PopulateKernelDescriptor, GivenKernelAttributesWhenPopulatingKernelDescriptorThenKernelLanguageSourcesAreSetAccordingly) {
NEO::ConstStringRef yaml = R"===(---
kernels:
- name: some_kernel
execution_env:
simd_size: 8
user_attributes:
intel_reqd_sub_group_size: 16
intel_reqd_workgroup_walk_order: [0, 1, 2]
reqd_work_group_size: [256, 2, 1]
vec_type_hint: uint
work_group_size_hint: [256, 2, 1]
new_user_hint: new_user_hint_value
...
)===";
NEO::ProgramInfo programInfo;
ZebinTestData::ValidEmptyProgram zebin;
NEO::ZebinSections zebinSections;
std::string errors, warnings;
zebin.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::textPrefix.str() + "some_kernel", {});
auto elf = NEO::Elf::decodeElf(zebin.storage, errors, warnings);
ASSERT_NE(nullptr, elf.elfFileHeader) << errors << " " << warnings;
NEO::Yaml::YamlParser parser;
bool parseSuccess = parser.parse(yaml, errors, warnings);
ASSERT_TRUE(parseSuccess) << errors << " " << warnings;
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(warnings.empty()) << warnings;
EXPECT_TRUE(errors.empty()) << errors;
EXPECT_STREQ("new_user_hint(new_user_hint_value) intel_reqd_sub_group_size(16) intel_reqd_workgroup_walk_order(0, 1, 2) reqd_work_group_size(256, 2, 1) work_group_size_hint(256, 2, 1) vec_type_hint(uint)", programInfo.kernelInfos[0]->kernelDescriptor.kernelMetadata.kernelLanguageAttributes.c_str());
EXPECT_FALSE(programInfo.kernelInfos[0]->kernelDescriptor.kernelAttributes.flags.isInvalid);
}
TEST(PopulateKernelSourceAttributes, GivenInvalidKernelAttributeWhenPopulatingKernelSourceAttributesThenKernelIsInvalidFlagIsSet) {
NEO::KernelDescriptor kd;
NEO::Elf::ZebinKernelMetadata::Types::Kernel::Attributes::AttributesBaseT attributes;
attributes.invalidKernel = "reason";
auto err = populateKernelSourceAttributes(kd, attributes);
EXPECT_EQ(NEO::DecodeError::Success, err);
EXPECT_TRUE(kd.kernelAttributes.flags.isInvalid);
EXPECT_STREQ("invalid_kernel(reason)", kd.kernelMetadata.kernelLanguageAttributes.c_str());
}
TEST(PopulateKernelDescriptor, GivenUnknownAttributeWhenPopulatingKernelDescriptorThenErrorIsReturned) {
NEO::ConstStringRef yaml = R"===(---
kernels:
- name: some_kernel
execution_env:
simd_size: 8
user_attributes:
unknown_attribute: unkown_attribute_value
...
)===";
NEO::ProgramInfo programInfo;
ZebinTestData::ValidEmptyProgram zebin;
NEO::ZebinSections zebinSections;
std::string errors, warnings;
zebin.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::textPrefix.str() + "some_kernel", {});
auto elf = NEO::Elf::decodeElf(zebin.storage, errors, warnings);
ASSERT_NE(nullptr, elf.elfFileHeader) << errors << " " << warnings;
NEO::Yaml::YamlParser parser;
bool parseSuccess = parser.parse(yaml, errors, warnings);
ASSERT_TRUE(parseSuccess) << errors << " " << warnings;
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_TRUE(warnings.empty()) << warnings;
EXPECT_STREQ("DeviceBinaryFormat::Zebin::.ze_info : Unknown attribute entry \"unknown_attribute\" in context of some_kernel\n", errors.c_str());
}
TEST(ReadZeInfoEnumChecked, GivenInvalidNodeThenFail) { TEST(ReadZeInfoEnumChecked, GivenInvalidNodeThenFail) {
using ArgType = NEO::Zebin::ZeInfo::EnumLookup::ArgType::ArgType; using ArgType = NEO::Zebin::ZeInfo::EnumLookup::ArgType::ArgType;
NEO::Yaml::YamlParser parser; NEO::Yaml::YamlParser parser;