|
8 | 8 | #include "binary_encoder.h"
|
9 | 9 |
|
10 | 10 | #include "elf/writer.h"
|
| 11 | +#include "runtime/helpers/aligned_memory.h" |
11 | 12 | #include "runtime/helpers/file_io.h"
|
| 13 | +#include "runtime/helpers/hash.h" |
12 | 14 |
|
13 | 15 | #include "CL/cl.h"
|
14 | 16 | #include "helper.h"
|
15 | 17 |
|
16 | 18 | #include <algorithm>
|
17 | 19 | #include <cstring>
|
18 | 20 | #include <fstream>
|
| 21 | +#include <sstream> |
19 | 22 |
|
20 | 23 | void BinaryEncoder::setMessagePrinter(const MessagePrinter &messagePrinter) {
|
21 | 24 | this->messagePrinter = messagePrinter;
|
@@ -49,19 +52,24 @@ void BinaryEncoder::calculatePatchListSizes(std::vector<std::string> &ptmFile) {
|
49 | 52 | }
|
50 | 53 | }
|
51 | 54 |
|
52 |
| -int BinaryEncoder::copyBinaryToBinary(const std::string &srcFileName, std::ostream &outBinary) { |
| 55 | +bool BinaryEncoder::copyBinaryToBinary(const std::string &srcFileName, std::ostream &outBinary, uint32_t *binaryLength) { |
53 | 56 | std::ifstream ifs(srcFileName, std::ios::binary);
|
54 | 57 | if (!ifs.good()) {
|
55 | 58 | messagePrinter.printf("Cannot open %s.\n", srcFileName.c_str());
|
56 |
| - return -1; |
| 59 | + return false; |
57 | 60 | }
|
58 | 61 | ifs.seekg(0, ifs.end);
|
59 | 62 | auto length = static_cast<size_t>(ifs.tellg());
|
60 | 63 | ifs.seekg(0, ifs.beg);
|
61 | 64 | std::vector<char> binary(length);
|
62 | 65 | ifs.read(binary.data(), length);
|
63 | 66 | outBinary.write(binary.data(), length);
|
64 |
| - return 0; |
| 67 | + |
| 68 | + if (binaryLength) { |
| 69 | + *binaryLength = static_cast<uint32_t>(length); |
| 70 | + } |
| 71 | + |
| 72 | + return true; |
65 | 73 | }
|
66 | 74 |
|
67 | 75 | int BinaryEncoder::createElf() {
|
@@ -169,56 +177,103 @@ int BinaryEncoder::processBinary(const std::vector<std::string> &ptmFile, std::o
|
169 | 177 | return 0;
|
170 | 178 | }
|
171 | 179 |
|
172 |
| -int BinaryEncoder::processKernel(size_t &i, const std::vector<std::string> &ptmFile, std::ostream &deviceBinary) { |
173 |
| - uint32_t kernelNameSize = 0; |
174 |
| - while (i < ptmFile.size()) { |
175 |
| - if (ptmFile[i].find("KernelName ") != std::string::npos) { |
176 |
| - break; |
177 |
| - } else if (ptmFile[i].find("KernelNameSize") != std::string::npos) { |
178 |
| - std::stringstream ss(ptmFile[i]); |
| 180 | +void BinaryEncoder::addPadding(std::ostream &out, size_t numBytes) { |
| 181 | + for (size_t i = 0; i < numBytes; ++i) { |
| 182 | + const char nullByte = 0; |
| 183 | + out.write(&nullByte, 1U); |
| 184 | + } |
| 185 | +} |
| 186 | + |
| 187 | +int BinaryEncoder::processKernel(size_t &line, const std::vector<std::string> &ptmFileLines, std::ostream &deviceBinary) { |
| 188 | + auto kernelInfoBeginMarker = line; |
| 189 | + auto kernelInfoEndMarker = ptmFileLines.size(); |
| 190 | + auto kernelNameMarker = ptmFileLines.size(); |
| 191 | + auto kernelPatchtokensMarker = ptmFileLines.size(); |
| 192 | + std::stringstream kernelBlob; |
| 193 | + |
| 194 | + // Normally these are added by the compiler, need to take or of them when reassembling |
| 195 | + constexpr size_t isaPaddingSizeInBytes = 128; |
| 196 | + constexpr uint32_t kernelHeapAlignmentInBytes = 64; |
| 197 | + |
| 198 | + uint32_t kernelNameSizeInBinary = 0; |
| 199 | + std::string kernelName; |
| 200 | + |
| 201 | + // Scan PTM lines for kernel info |
| 202 | + while (line < ptmFileLines.size()) { |
| 203 | + if (ptmFileLines[line].find("KernelName ") != std::string::npos) { |
| 204 | + kernelName = std::string(ptmFileLines[line], ptmFileLines[line].find(' ') + 1); |
| 205 | + kernelNameMarker = line; |
| 206 | + kernelPatchtokensMarker = kernelNameMarker + 1; // patchtokens come after name |
| 207 | + } else if (ptmFileLines[line].find("KernelNameSize") != std::string::npos) { |
| 208 | + std::stringstream ss(ptmFileLines[line]); |
179 | 209 | ss.ignore(32, ' ');
|
180 | 210 | ss.ignore(32, ' ');
|
181 |
| - ss >> kernelNameSize; |
182 |
| - } |
183 |
| - if (writeDeviceBinary(ptmFile[i++], deviceBinary)) { |
184 |
| - messagePrinter.printf("Error while writing to binary.\n"); |
185 |
| - return -1; |
| 211 | + ss >> kernelNameSizeInBinary; |
| 212 | + } else if (ptmFileLines[line].find("Kernel #") != std::string::npos) { |
| 213 | + kernelInfoEndMarker = line; |
| 214 | + break; |
186 | 215 | }
|
| 216 | + ++line; |
187 | 217 | }
|
188 |
| - //KernelName |
189 |
| - if (i == ptmFile.size()) { |
190 |
| - messagePrinter.printf("Couldn't find KernelName line.\n"); |
191 |
| - return -1; |
192 |
| - } |
193 |
| - std::string kernelName(ptmFile[i], ptmFile[i].find(' ') + 1); |
194 |
| - i++; |
195 | 218 |
|
196 |
| - deviceBinary.write(kernelName.c_str(), kernelName.size()); |
197 |
| - for (auto j = kernelName.size(); j < kernelNameSize; ++j) { |
198 |
| - uint8_t nullByte = 0; |
199 |
| - deviceBinary.write(reinterpret_cast<const char *>(&nullByte), sizeof(uint8_t)); |
200 |
| - } |
| 219 | + // Write KernelName and padding |
| 220 | + kernelBlob.write(kernelName.c_str(), kernelName.size()); |
| 221 | + addPadding(kernelBlob, kernelNameSizeInBinary - kernelName.size()); |
| 222 | + |
| 223 | + // Write KernelHeap and padding |
| 224 | + uint32_t kernelSizeUnpadded = 0U; |
| 225 | + bool heapsCopiedSuccesfully = copyBinaryToBinary(pathToDump + kernelName + "_KernelHeap.bin", kernelBlob, &kernelSizeUnpadded); |
| 226 | + |
| 227 | + // Adding padding and alignment |
| 228 | + addPadding(kernelBlob, isaPaddingSizeInBytes); |
| 229 | + const uint32_t kernelHeapPaddedSize = kernelSizeUnpadded + isaPaddingSizeInBytes; |
| 230 | + const uint32_t kernelHeapAlignedSize = alignUp(kernelHeapPaddedSize, kernelHeapAlignmentInBytes); |
| 231 | + addPadding(kernelBlob, kernelHeapAlignedSize - kernelHeapPaddedSize); |
201 | 232 |
|
202 |
| - // Writing KernelHeap, DynamicStateHeap, SurfaceStateHeap |
| 233 | + // Write GeneralStateHeap, DynamicStateHeap, SurfaceStateHeap |
203 | 234 | if (fileExists(pathToDump + kernelName + "_GeneralStateHeap.bin")) {
|
204 |
| - messagePrinter.printf("Warning! Adding GeneralStateHeap.\n"); |
205 |
| - if (copyBinaryToBinary(pathToDump + kernelName + "_GeneralStateHeap.bin", deviceBinary)) { |
206 |
| - messagePrinter.printf("Couldn't copy %s_GeneralStateHeap.bin\n", kernelName.c_str()); |
207 |
| - return -1; |
208 |
| - } |
| 235 | + heapsCopiedSuccesfully = heapsCopiedSuccesfully && copyBinaryToBinary(pathToDump + kernelName + "_GeneralStateHeap.bin", kernelBlob); |
209 | 236 | }
|
210 |
| - if (copyBinaryToBinary(pathToDump + kernelName + "_KernelHeap.bin", deviceBinary)) { |
211 |
| - messagePrinter.printf("Couldn't copy %s_KernelHeap.bin\n", kernelName.c_str()); |
| 237 | + heapsCopiedSuccesfully = heapsCopiedSuccesfully && copyBinaryToBinary(pathToDump + kernelName + "_DynamicStateHeap.bin", kernelBlob); |
| 238 | + heapsCopiedSuccesfully = heapsCopiedSuccesfully && copyBinaryToBinary(pathToDump + kernelName + "_SurfaceStateHeap.bin", kernelBlob); |
| 239 | + if (false == heapsCopiedSuccesfully) { |
212 | 240 | return -1;
|
213 | 241 | }
|
214 |
| - if (copyBinaryToBinary(pathToDump + kernelName + "_DynamicStateHeap.bin", deviceBinary)) { |
215 |
| - messagePrinter.printf("Couldn't copy %s_DynamicStateHeap.bin\n", kernelName.c_str()); |
216 |
| - return -1; |
| 242 | + |
| 243 | + // Write kernel patchtokens |
| 244 | + for (size_t i = kernelPatchtokensMarker; i < kernelInfoEndMarker; ++i) { |
| 245 | + if (writeDeviceBinary(ptmFileLines[i], kernelBlob)) { |
| 246 | + messagePrinter.printf("Error while writing to binary.\n"); |
| 247 | + return -1; |
| 248 | + } |
217 | 249 | }
|
218 |
| - if (copyBinaryToBinary(pathToDump + kernelName + "_SurfaceStateHeap.bin", deviceBinary)) { |
219 |
| - messagePrinter.printf("Couldn't copy %s_SurfaceStateHeap.bin\n", kernelName.c_str()); |
220 |
| - return -1; |
| 250 | + |
| 251 | + auto kernelBlobData = kernelBlob.str(); |
| 252 | + uint64_t hashValue = NEO::Hash::hash(reinterpret_cast<const char *>(kernelBlobData.data()), kernelBlobData.size()); |
| 253 | + uint32_t calcCheckSum = hashValue & 0xFFFFFFFF; |
| 254 | + |
| 255 | + // Add kernel header |
| 256 | + for (size_t i = kernelInfoBeginMarker; i < kernelNameMarker; ++i) { |
| 257 | + if (ptmFileLines[i].find("CheckSum") != std::string::npos) { |
| 258 | + static_assert(std::is_same<decltype(calcCheckSum), uint32_t>::value, ""); |
| 259 | + deviceBinary.write(reinterpret_cast<char *>(&calcCheckSum), sizeof(uint32_t)); |
| 260 | + } else if (ptmFileLines[i].find("KernelHeapSize") != std::string::npos) { |
| 261 | + static_assert(sizeof(kernelHeapAlignedSize) == sizeof(uint32_t), ""); |
| 262 | + deviceBinary.write(reinterpret_cast<const char *>(&kernelHeapAlignedSize), sizeof(uint32_t)); |
| 263 | + } else if (ptmFileLines[i].find("KernelUnpaddedSize") != std::string::npos) { |
| 264 | + static_assert(sizeof(kernelSizeUnpadded) == sizeof(uint32_t), ""); |
| 265 | + deviceBinary.write(reinterpret_cast<char *>(&kernelSizeUnpadded), sizeof(uint32_t)); |
| 266 | + } else { |
| 267 | + if (writeDeviceBinary(ptmFileLines[i], deviceBinary)) { |
| 268 | + messagePrinter.printf("Error while writing to binary.\n"); |
| 269 | + return -1; |
| 270 | + } |
| 271 | + } |
221 | 272 | }
|
| 273 | + |
| 274 | + // Add kernel blob after the header |
| 275 | + deviceBinary.write(kernelBlobData.c_str(), kernelBlobData.size()); |
| 276 | + |
222 | 277 | return 0;
|
223 | 278 | }
|
224 | 279 |
|
|
0 commit comments