1 /*
2 * Copyright (C) 2020-2021 Intel Corporation
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 */
7
8 #pragma once
9
10 #include "shared/source/utilities/arrayref.h"
11 #include "shared/source/utilities/const_stringref.h"
12
13 #include <cstddef>
14 #include <cstdint>
15 #include <igfxfmid.h>
16 #include <memory>
17 #include <vector>
18
19 namespace NEO {
20 struct ProgramInfo;
21
22 enum class DeviceBinaryFormat : uint8_t {
23 Unknown,
24 OclElf,
25 OclLibrary,
26 OclCompiledObject,
27 Patchtokens,
28 Archive,
29 Zebin
30 };
31
32 enum class DecodeError : uint8_t {
33 Success,
34 Undefined,
35 InvalidBinary,
36 UnhandledBinary
37 };
38
asString(DecodeError err)39 inline const char *asString(DecodeError err) {
40 switch (err) {
41 default:
42 return "with invalid binary";
43 break;
44 case DecodeError::UnhandledBinary:
45 return "with unhandled binary";
46 break;
47 case DecodeError::Success:
48 return "decoded successfully";
49 break;
50 case DecodeError::Undefined:
51 return "in undefined status";
52 break;
53 }
54 }
55
56 struct TargetDevice {
57 GFXCORE_FAMILY coreFamily = IGFX_UNKNOWN_CORE;
58 PRODUCT_FAMILY productFamily = IGFX_UNKNOWN;
59 uint32_t stepping = 0U;
60 uint32_t maxPointerSizeInBytes = 4U;
61 uint32_t grfSize = 32U;
62 };
63
64 struct SingleDeviceBinary {
65 DeviceBinaryFormat format = DeviceBinaryFormat::Unknown;
66 ArrayRef<const uint8_t> deviceBinary;
67 ArrayRef<const uint8_t> debugData;
68 ArrayRef<const uint8_t> intermediateRepresentation;
69 ConstStringRef buildOptions;
70 TargetDevice targetDevice;
71 };
72
73 template <DeviceBinaryFormat Format>
74 bool isDeviceBinaryFormat(const ArrayRef<const uint8_t> binary);
75
76 template <>
77 bool isDeviceBinaryFormat<DeviceBinaryFormat::OclElf>(const ArrayRef<const uint8_t>);
78 template <>
79 bool isDeviceBinaryFormat<DeviceBinaryFormat::Patchtokens>(const ArrayRef<const uint8_t>);
80 template <>
81 bool isDeviceBinaryFormat<DeviceBinaryFormat::Archive>(const ArrayRef<const uint8_t>);
82 template <>
83 bool isDeviceBinaryFormat<DeviceBinaryFormat::Zebin>(const ArrayRef<const uint8_t>);
84
isAnyDeviceBinaryFormat(const ArrayRef<const uint8_t> binary)85 inline bool isAnyDeviceBinaryFormat(const ArrayRef<const uint8_t> binary) {
86 if (isDeviceBinaryFormat<DeviceBinaryFormat::OclElf>(binary)) {
87 return true;
88 }
89 if (isDeviceBinaryFormat<DeviceBinaryFormat::Patchtokens>(binary)) {
90 return true;
91 }
92 if (isDeviceBinaryFormat<DeviceBinaryFormat::Archive>(binary)) {
93 return true;
94 }
95 if (isDeviceBinaryFormat<DeviceBinaryFormat::Zebin>(binary)) {
96 return true;
97 }
98 return false;
99 }
100
101 template <DeviceBinaryFormat Format>
102 SingleDeviceBinary unpackSingleDeviceBinary(const ArrayRef<const uint8_t> archive, const ConstStringRef requestedProductAbbreviation, const TargetDevice &requestedTargetDevice,
103 std::string &outErrReason, std::string &outWarning);
104
105 template <>
106 SingleDeviceBinary unpackSingleDeviceBinary<DeviceBinaryFormat::OclElf>(const ArrayRef<const uint8_t>, const ConstStringRef, const TargetDevice &, std::string &, std::string &);
107 template <>
108 SingleDeviceBinary unpackSingleDeviceBinary<DeviceBinaryFormat::Patchtokens>(const ArrayRef<const uint8_t>, const ConstStringRef, const TargetDevice &, std::string &, std::string &);
109 template <>
110 SingleDeviceBinary unpackSingleDeviceBinary<DeviceBinaryFormat::Archive>(const ArrayRef<const uint8_t>, const ConstStringRef, const TargetDevice &, std::string &, std::string &);
111 template <>
112 SingleDeviceBinary unpackSingleDeviceBinary<DeviceBinaryFormat::Zebin>(const ArrayRef<const uint8_t>, const ConstStringRef, const TargetDevice &, std::string &, std::string &);
113
unpackSingleDeviceBinary(const ArrayRef<const uint8_t> archive,const ConstStringRef requestedProductAbbreviation,const TargetDevice & requestedTargetDevice,std::string & outErrReason,std::string & outWarning)114 inline SingleDeviceBinary unpackSingleDeviceBinary(const ArrayRef<const uint8_t> archive, const ConstStringRef requestedProductAbbreviation, const TargetDevice &requestedTargetDevice,
115 std::string &outErrReason, std::string &outWarning) {
116 SingleDeviceBinary ret = {};
117 ret.format = DeviceBinaryFormat::Unknown;
118 if (isDeviceBinaryFormat<DeviceBinaryFormat::OclElf>(archive)) {
119 return unpackSingleDeviceBinary<DeviceBinaryFormat::OclElf>(archive, requestedProductAbbreviation, requestedTargetDevice, outErrReason, outWarning);
120 } else if (isDeviceBinaryFormat<DeviceBinaryFormat::Patchtokens>(archive)) {
121 return unpackSingleDeviceBinary<DeviceBinaryFormat::Patchtokens>(archive, requestedProductAbbreviation, requestedTargetDevice, outErrReason, outWarning);
122 } else if (isDeviceBinaryFormat<DeviceBinaryFormat::Archive>(archive)) {
123 return unpackSingleDeviceBinary<DeviceBinaryFormat::Archive>(archive, requestedProductAbbreviation, requestedTargetDevice, outErrReason, outWarning);
124 } else if (isDeviceBinaryFormat<DeviceBinaryFormat::Zebin>(archive)) {
125 return unpackSingleDeviceBinary<DeviceBinaryFormat::Zebin>(archive, requestedProductAbbreviation, requestedTargetDevice, outErrReason, outWarning);
126 } else {
127 outErrReason = "Unknown format";
128 }
129 return ret;
130 }
131
132 template <DeviceBinaryFormat Format>
133 std::vector<uint8_t> packDeviceBinary(const SingleDeviceBinary binary, std::string &outErrReason, std::string &outWarning);
134
135 template <>
136 std::vector<uint8_t> packDeviceBinary<DeviceBinaryFormat::OclElf>(const SingleDeviceBinary, std::string &, std::string &);
137
138 std::vector<uint8_t> packDeviceBinary(const SingleDeviceBinary binary, std::string &outErrReason, std::string &outWarning);
139
isAnyPackedDeviceBinaryFormat(const ArrayRef<const uint8_t> binary)140 inline bool isAnyPackedDeviceBinaryFormat(const ArrayRef<const uint8_t> binary) {
141 if (isDeviceBinaryFormat<DeviceBinaryFormat::OclElf>(binary)) {
142 return true;
143 }
144 if (isDeviceBinaryFormat<DeviceBinaryFormat::Archive>(binary)) {
145 return true;
146 }
147 if (isDeviceBinaryFormat<DeviceBinaryFormat::Zebin>(binary)) {
148 return true;
149 }
150 return false;
151 }
152
isAnySingleDeviceBinaryFormat(const ArrayRef<const uint8_t> binary)153 inline bool isAnySingleDeviceBinaryFormat(const ArrayRef<const uint8_t> binary) {
154 return ((false == isAnyPackedDeviceBinaryFormat(binary)) && isAnyDeviceBinaryFormat(binary)) || isDeviceBinaryFormat<DeviceBinaryFormat::Zebin>(binary);
155 }
156
157 template <DeviceBinaryFormat Format>
158 DecodeError decodeSingleDeviceBinary(ProgramInfo &dst, const SingleDeviceBinary &src, std::string &outErrReason, std::string &outWarning);
159
160 template <>
161 DecodeError decodeSingleDeviceBinary<DeviceBinaryFormat::OclElf>(ProgramInfo &, const SingleDeviceBinary &, std::string &, std::string &);
162 template <>
163 DecodeError decodeSingleDeviceBinary<DeviceBinaryFormat::Patchtokens>(ProgramInfo &, const SingleDeviceBinary &, std::string &, std::string &);
164 template <>
165 DecodeError decodeSingleDeviceBinary<DeviceBinaryFormat::Archive>(ProgramInfo &, const SingleDeviceBinary &, std::string &, std::string &);
166 template <>
167 DecodeError decodeSingleDeviceBinary<DeviceBinaryFormat::Zebin>(ProgramInfo &, const SingleDeviceBinary &, std::string &, std::string &);
168
decodeSingleDeviceBinary(ProgramInfo & dst,const SingleDeviceBinary & src,std::string & outErrReason,std::string & outWarning)169 inline std::pair<DecodeError, DeviceBinaryFormat> decodeSingleDeviceBinary(ProgramInfo &dst, const SingleDeviceBinary &src, std::string &outErrReason, std::string &outWarning) {
170 std::pair<DecodeError, DeviceBinaryFormat> ret;
171 ret.first = DecodeError::InvalidBinary;
172 ret.second = DeviceBinaryFormat::Unknown;
173 if (isDeviceBinaryFormat<DeviceBinaryFormat::OclElf>(src.deviceBinary)) {
174 ret.second = DeviceBinaryFormat::OclElf;
175 ret.first = decodeSingleDeviceBinary<DeviceBinaryFormat::OclElf>(dst, src, outErrReason, outWarning);
176 } else if (isDeviceBinaryFormat<DeviceBinaryFormat::Patchtokens>(src.deviceBinary)) {
177 ret.second = DeviceBinaryFormat::Patchtokens;
178 ret.first = decodeSingleDeviceBinary<DeviceBinaryFormat::Patchtokens>(dst, src, outErrReason, outWarning);
179 } else if (isDeviceBinaryFormat<DeviceBinaryFormat::Archive>(src.deviceBinary)) {
180 ret.second = DeviceBinaryFormat::Archive;
181 ret.first = decodeSingleDeviceBinary<DeviceBinaryFormat::Archive>(dst, src, outErrReason, outWarning);
182 } else if (isDeviceBinaryFormat<DeviceBinaryFormat::Zebin>(src.deviceBinary)) {
183 ret.second = DeviceBinaryFormat::Zebin;
184 ret.first = decodeSingleDeviceBinary<DeviceBinaryFormat::Zebin>(dst, src, outErrReason, outWarning);
185 } else {
186 outErrReason = "Unknown format";
187 }
188 return ret;
189 }
190
191 } // namespace NEO
192