mirror of
https://github.com/intel/compute-runtime.git
synced 2025-09-15 13:01:45 +08:00
Adding support for kernel disasm using IGA
Change-Id: Ic75540c9b42913f5d12d66438cc4e6dcc39ceb98
This commit is contained in:

committed by
sys_ocldev

parent
79e78e18c4
commit
2f42f332d8
@ -16,6 +16,7 @@ ${IGDRCL_SOURCE_DIR}/offline_compiler/offline_compiler.cpp
|
||||
set(IGDRCL_SRCS_offline_compiler_mock
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/decoder/mock/mock_decoder.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/decoder/mock/mock_encoder.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/decoder/mock/mock_iga_wrapper.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_offline_compiler.h
|
||||
)
|
||||
|
||||
|
@ -46,8 +46,6 @@ TEST(DecoderTests, WhenMissingParametersThenValidateInputReturnsErrorCode) {
|
||||
const char *argv[] = {
|
||||
"ocloc",
|
||||
"decoder",
|
||||
"-file",
|
||||
"test_files/binary.bin",
|
||||
"-patch",
|
||||
"test_files"};
|
||||
|
||||
@ -299,5 +297,7 @@ TEST(DecoderTests, GivenValidBinaryWhenProcessingBinaryThenProgramAndKernelAndPa
|
||||
|
||||
std::string expectedOutput = "ProgramBinaryHeader:\n\t4 Magic 1229870147\n\t4 Version 0\n\t4 Device 0\n\t4 GPUPointerSizeInBytes 0\n\t4 NumberOfKernels 1\n\t4 SteppingId 0\n\t4 PatchListSize 30\nPATCH_TOKEN_ALLOCATE_CONSTANT_MEMORY_SURFACE_PROGRAM_BINARY_INFO:\n\t4 Token 42\n\t4 Size 16\n\t4 ConstantBufferIndex 0\n\t4 InlineDataSize 14\n\tHex 0 1 2 3 4 5 6 7 8 9 a b c d\nKernel #0\nKernelBinaryHeader:\n\t4 CheckSum 4294967295\n\t8 ShaderHashCode 18446744073709551615\n\t4 KernelNameSize 14\n\t4 PatchListSize 12\n\t4 KernelHeapSize 0\n\t4 GeneralStateHeapSize 0\n\t4 DynamicStateHeapSize 0\n\t4 SurfaceStateHeapSize 0\n\t4 KernelUnpaddedSize 0\n\tKernelName ExampleKernel\nPATCH_TOKEN_MEDIA_INTERFACE_DESCRIPTOR_LOAD:\n\t4 Token 19\n\t4 Size 12\n\t4 InterfaceDescriptorDataOffset 0\n";
|
||||
EXPECT_EQ(expectedOutput, ptmFile.str());
|
||||
EXPECT_TRUE(decoder.getMockIga()->disasmWasCalled);
|
||||
EXPECT_FALSE(decoder.getMockIga()->asmWasCalled);
|
||||
}
|
||||
} // namespace NEO
|
||||
|
@ -239,14 +239,14 @@ TEST(EncoderTests, WhenProcessingDeviceBinaryThenProperChecksumIsCalculated) {
|
||||
MockEncoder encoder;
|
||||
std::string kernelName = "kernel";
|
||||
encoder.filesMap["kernel_DynamicStateHeap.bin"] = std::string(16, 2);
|
||||
encoder.filesMap["kernel_KernelHeap.bin"] = std::string(16, 4);
|
||||
encoder.filesMap["kernel_KernelHeap.dat"] = std::string(16, 4);
|
||||
encoder.filesMap["kernel_SurfaceStateHeap.bin"] = std::string(16, 8);
|
||||
std::stringstream kernelBlob;
|
||||
kernelBlob << kernelName;
|
||||
kernelBlob.write(encoder.filesMap["kernel_KernelHeap.bin"].data(), encoder.filesMap["kernel_KernelHeap.bin"].size());
|
||||
kernelBlob.write(encoder.filesMap["kernel_KernelHeap.dat"].data(), encoder.filesMap["kernel_KernelHeap.dat"].size());
|
||||
encoder.addPadding(kernelBlob, 128); // isa prefetch padding
|
||||
encoder.addPadding(kernelBlob, 64 - (encoder.filesMap["kernel_KernelHeap.bin"].size() + 128) % 64); // isa alignment
|
||||
size_t kernelHeapSize = encoder.filesMap["kernel_KernelHeap.bin"].size();
|
||||
encoder.addPadding(kernelBlob, 64 - (encoder.filesMap["kernel_KernelHeap.dat"].size() + 128) % 64); // isa alignment
|
||||
size_t kernelHeapSize = encoder.filesMap["kernel_KernelHeap.dat"].size();
|
||||
kernelHeapSize = alignUp(kernelHeapSize + 128, 64);
|
||||
kernelBlob.write(encoder.filesMap["kernel_DynamicStateHeap.bin"].data(), encoder.filesMap["kernel_DynamicStateHeap.bin"].size());
|
||||
kernelBlob.write(encoder.filesMap["kernel_SurfaceStateHeap.bin"].data(), encoder.filesMap["kernel_SurfaceStateHeap.bin"].size());
|
||||
@ -295,9 +295,10 @@ TEST(EncoderTests, WhenProcessingDeviceBinaryThenProperChecksumIsCalculated) {
|
||||
expectedBinary.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
|
||||
byte4 = 16;
|
||||
expectedBinary.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
|
||||
byte4 = static_cast<uint32_t>(encoder.filesMap["kernel_KernelHeap.bin"].size());
|
||||
byte4 = static_cast<uint32_t>(encoder.filesMap["kernel_KernelHeap.dat"].size());
|
||||
expectedBinary.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
|
||||
expectedBinary.write(kernelName.c_str(), kernelName.length());
|
||||
expectedBinary.write(encoder.filesMap["kernel_KernelHeap.dat"].data(), encoder.filesMap["kernel_KernelHeap.dat"].size());
|
||||
|
||||
std::vector<std::string> ptmFile;
|
||||
ptmFile.push_back("ProgramBinaryHeader:");
|
||||
@ -316,7 +317,7 @@ TEST(EncoderTests, WhenProcessingDeviceBinaryThenProperChecksumIsCalculated) {
|
||||
ptmFile.push_back("\tHex 48 65");
|
||||
ptmFile.push_back("Kernel #0");
|
||||
ptmFile.push_back("KernelBinaryHeader:");
|
||||
ptmFile.push_back("\t4 CheckSum " + std::to_string(checksum));
|
||||
ptmFile.push_back("\t4 CheckSum 0");
|
||||
ptmFile.push_back("\t8 ShaderHashCode 4988534869940066475");
|
||||
ptmFile.push_back("\t4 KernelNameSize " + std::to_string(kernelName.size()));
|
||||
ptmFile.push_back("\t4 PatchListSize 0");
|
||||
@ -333,6 +334,119 @@ TEST(EncoderTests, WhenProcessingDeviceBinaryThenProperChecksumIsCalculated) {
|
||||
auto expectedBinaryAsString = expectedBinary.str();
|
||||
resultAsString.resize(expectedBinaryAsString.size()); // don't test beyond kernel header
|
||||
EXPECT_EQ(expectedBinaryAsString, resultAsString);
|
||||
EXPECT_FALSE(encoder.getMockIga()->disasmWasCalled);
|
||||
EXPECT_FALSE(encoder.getMockIga()->asmWasCalled);
|
||||
}
|
||||
|
||||
TEST(EncoderTests, WhenProcessingDeviceBinaryAndAsmIsAvailableThenAseembleItWithIga) {
|
||||
std::stringstream expectedBinary;
|
||||
uint8_t byte;
|
||||
uint32_t byte4;
|
||||
uint64_t byte8;
|
||||
|
||||
MockEncoder encoder;
|
||||
encoder.getMockIga()->binaryToReturn = std::string(32, 13);
|
||||
std::string kernelName = "kernel";
|
||||
encoder.filesMap["kernel_DynamicStateHeap.bin"] = std::string(16, 2);
|
||||
encoder.filesMap["kernel_KernelHeap.dat"] = std::string(16, 4);
|
||||
encoder.filesMap["kernel_KernelHeap.asm"] = std::string(16, 7);
|
||||
encoder.filesMap["kernel_SurfaceStateHeap.bin"] = std::string(16, 8);
|
||||
std::stringstream kernelBlob;
|
||||
kernelBlob << kernelName;
|
||||
kernelBlob.write(encoder.getMockIga()->binaryToReturn.c_str(), encoder.getMockIga()->binaryToReturn.size());
|
||||
encoder.addPadding(kernelBlob, 128); // isa prefetch padding
|
||||
encoder.addPadding(kernelBlob, 64 - (encoder.getMockIga()->binaryToReturn.size() + 128) % 64); // isa alignment
|
||||
size_t kernelHeapSize = encoder.getMockIga()->binaryToReturn.size();
|
||||
kernelHeapSize = alignUp(kernelHeapSize + 128, 64);
|
||||
kernelBlob.write(encoder.filesMap["kernel_DynamicStateHeap.bin"].data(), encoder.filesMap["kernel_DynamicStateHeap.bin"].size());
|
||||
kernelBlob.write(encoder.filesMap["kernel_SurfaceStateHeap.bin"].data(), encoder.filesMap["kernel_SurfaceStateHeap.bin"].size());
|
||||
|
||||
auto kernelBlobData = kernelBlob.str();
|
||||
uint64_t hashValue = NEO::Hash::hash(reinterpret_cast<const char *>(kernelBlobData.data()), kernelBlobData.size());
|
||||
uint32_t checksum = hashValue & 0xFFFFFFFF;
|
||||
|
||||
byte4 = 1229870147;
|
||||
expectedBinary.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
|
||||
byte4 = 1042;
|
||||
expectedBinary.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
|
||||
byte4 = 12;
|
||||
expectedBinary.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
|
||||
byte4 = 4;
|
||||
expectedBinary.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
|
||||
byte4 = 1;
|
||||
expectedBinary.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
|
||||
byte4 = 2;
|
||||
expectedBinary.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
|
||||
byte4 = 18;
|
||||
expectedBinary.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
|
||||
byte4 = 42;
|
||||
expectedBinary.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
|
||||
byte4 = 16;
|
||||
expectedBinary.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
|
||||
byte4 = 0;
|
||||
expectedBinary.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
|
||||
byte4 = 2;
|
||||
expectedBinary.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
|
||||
byte = 0x48;
|
||||
expectedBinary.write(reinterpret_cast<char *>(&byte), sizeof(uint8_t));
|
||||
byte = 0x65;
|
||||
expectedBinary.write(reinterpret_cast<char *>(&byte), sizeof(uint8_t));
|
||||
byte4 = checksum;
|
||||
expectedBinary.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
|
||||
byte8 = 4988534869940066475;
|
||||
expectedBinary.write(reinterpret_cast<char *>(&byte8), sizeof(uint64_t));
|
||||
byte4 = static_cast<uint32_t>(kernelName.size());
|
||||
expectedBinary.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
|
||||
byte4 = 0;
|
||||
expectedBinary.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
|
||||
byte4 = static_cast<uint32_t>(kernelHeapSize);
|
||||
expectedBinary.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
|
||||
byte4 = 0;
|
||||
expectedBinary.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
|
||||
byte4 = static_cast<uint32_t>(16);
|
||||
expectedBinary.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
|
||||
byte4 = static_cast<uint32_t>(encoder.getMockIga()->binaryToReturn.size());
|
||||
expectedBinary.write(reinterpret_cast<char *>(&byte4), sizeof(uint32_t));
|
||||
expectedBinary.write(kernelName.c_str(), kernelName.length());
|
||||
expectedBinary.write(encoder.getMockIga()->binaryToReturn.data(), encoder.getMockIga()->binaryToReturn.size());
|
||||
|
||||
std::vector<std::string> ptmFile;
|
||||
ptmFile.push_back("ProgramBinaryHeader:");
|
||||
ptmFile.push_back("\t4 Magic 1229870147");
|
||||
ptmFile.push_back("\t4 Version 1042");
|
||||
ptmFile.push_back("\t4 Device 12");
|
||||
ptmFile.push_back("\t4 GPUPointerSizeInBytes 4");
|
||||
ptmFile.push_back("\t4 NumberOfKernels 1");
|
||||
ptmFile.push_back("\t4 SteppingId 2");
|
||||
ptmFile.push_back("\t4 PatchListSize 18");
|
||||
ptmFile.push_back("PATCH_TOKEN_ALLOCATE_CONSTANT_MEMORY_SURFACE_PROGRAM_BINARY_INFO:");
|
||||
ptmFile.push_back("\t4 Token 42");
|
||||
ptmFile.push_back("\t4 Size 16");
|
||||
ptmFile.push_back("\t4 ConstantBufferIndex 0");
|
||||
ptmFile.push_back("\t4 InlineDataSize 2");
|
||||
ptmFile.push_back("\tHex 48 65");
|
||||
ptmFile.push_back("Kernel #0");
|
||||
ptmFile.push_back("KernelBinaryHeader:");
|
||||
ptmFile.push_back("\t4 CheckSum 0");
|
||||
ptmFile.push_back("\t8 ShaderHashCode 4988534869940066475");
|
||||
ptmFile.push_back("\t4 KernelNameSize " + std::to_string(kernelName.size()));
|
||||
ptmFile.push_back("\t4 PatchListSize 0");
|
||||
ptmFile.push_back("\t4 KernelHeapSize 16");
|
||||
ptmFile.push_back("\t4 GeneralStateHeapSize 0");
|
||||
ptmFile.push_back("\t4 DynamicStateHeapSize 16");
|
||||
ptmFile.push_back("\t4 KernelUnpaddedSize 16");
|
||||
ptmFile.push_back("\tKernelName " + kernelName);
|
||||
|
||||
std::stringstream result;
|
||||
auto ret = encoder.processBinary(ptmFile, result);
|
||||
auto resultAsString = result.str();
|
||||
EXPECT_EQ(0, ret);
|
||||
auto expectedBinaryAsString = expectedBinary.str();
|
||||
resultAsString.resize(expectedBinaryAsString.size()); // don't test beyond kernel header
|
||||
EXPECT_EQ(expectedBinaryAsString, resultAsString);
|
||||
EXPECT_FALSE(encoder.getMockIga()->disasmWasCalled);
|
||||
EXPECT_TRUE(encoder.getMockIga()->asmWasCalled);
|
||||
EXPECT_EQ(encoder.filesMap["kernel_KernelHeap.asm"], encoder.getMockIga()->receivedAsm);
|
||||
}
|
||||
|
||||
} // namespace NEO
|
||||
|
@ -8,15 +8,20 @@
|
||||
#pragma once
|
||||
#include "offline_compiler/decoder/binary_decoder.h"
|
||||
|
||||
#include "mock_iga_wrapper.h"
|
||||
|
||||
struct MockDecoder : public BinaryDecoder {
|
||||
MockDecoder() : MockDecoder("", "", ""){};
|
||||
MockDecoder() : MockDecoder("", "", "") {
|
||||
}
|
||||
MockDecoder(const std::string &file, const std::string &patch, const std::string &dump)
|
||||
: BinaryDecoder(file, patch, dump) {
|
||||
this->iga.reset(new MockIgaWrapper);
|
||||
setMessagePrinter(MessagePrinter{true});
|
||||
};
|
||||
using BinaryDecoder::binaryFile;
|
||||
using BinaryDecoder::decode;
|
||||
using BinaryDecoder::getSize;
|
||||
using BinaryDecoder::iga;
|
||||
using BinaryDecoder::kernelHeader;
|
||||
using BinaryDecoder::parseTokens;
|
||||
using BinaryDecoder::patchTokens;
|
||||
@ -27,4 +32,8 @@ struct MockDecoder : public BinaryDecoder {
|
||||
using BinaryDecoder::programHeader;
|
||||
using BinaryDecoder::readPatchTokens;
|
||||
using BinaryDecoder::readStructFields;
|
||||
|
||||
MockIgaWrapper *getMockIga() const {
|
||||
return static_cast<MockIgaWrapper *>(iga.get());
|
||||
}
|
||||
};
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include "offline_compiler/decoder/binary_encoder.h"
|
||||
#include "runtime/helpers/hash.h"
|
||||
|
||||
#include "mock_iga_wrapper.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
@ -16,6 +18,7 @@ struct MockEncoder : public BinaryEncoder {
|
||||
MockEncoder() : MockEncoder("", ""){};
|
||||
MockEncoder(const std::string &dump, const std::string &elf)
|
||||
: BinaryEncoder(dump, elf) {
|
||||
this->iga.reset(new MockIgaWrapper);
|
||||
setMessagePrinter(MessagePrinter{true});
|
||||
};
|
||||
|
||||
@ -31,17 +34,31 @@ struct MockEncoder : public BinaryEncoder {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fileExists(const std::string &path) const override {
|
||||
return filesMap.count(path) || BinaryEncoder::fileExists(path);
|
||||
}
|
||||
|
||||
std::vector<char> readBinaryFile(const std::string &path) const override {
|
||||
return filesMap.count(path) ? std::vector<char>(filesMap.at(path).c_str(), filesMap.at(path).c_str() + filesMap.at(path).size())
|
||||
: BinaryEncoder::readBinaryFile(path);
|
||||
}
|
||||
|
||||
using BinaryEncoder::addPadding;
|
||||
using BinaryEncoder::calculatePatchListSizes;
|
||||
using BinaryEncoder::copyBinaryToBinary;
|
||||
using BinaryEncoder::createElf;
|
||||
using BinaryEncoder::elfName;
|
||||
using BinaryEncoder::encode;
|
||||
using BinaryEncoder::iga;
|
||||
using BinaryEncoder::pathToDump;
|
||||
using BinaryEncoder::processBinary;
|
||||
using BinaryEncoder::processKernel;
|
||||
using BinaryEncoder::write;
|
||||
using BinaryEncoder::writeDeviceBinary;
|
||||
|
||||
MockIgaWrapper *getMockIga() const {
|
||||
return static_cast<MockIgaWrapper *>(iga.get());
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> filesMap;
|
||||
};
|
||||
|
50
unit_tests/offline_compiler/decoder/mock/mock_iga_wrapper.h
Normal file
50
unit_tests/offline_compiler/decoder/mock/mock_iga_wrapper.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2019 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "offline_compiler/decoder/iga_wrapper.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
struct MockIgaWrapper : public IgaWrapper {
|
||||
bool tryDisassembleGenISA(const void *kernelPtr, uint32_t kernelSize, std::string &out) override {
|
||||
out = asmToReturn;
|
||||
disasmWasCalled = true;
|
||||
receivedBinary.assign(reinterpret_cast<const char *>(kernelPtr), kernelSize);
|
||||
return asmToReturn.size() != 0;
|
||||
}
|
||||
|
||||
bool tryAssembleGenISA(const std::string &inAsm, std::string &outBinary) override {
|
||||
outBinary = binaryToReturn;
|
||||
asmWasCalled = true;
|
||||
receivedAsm = inAsm;
|
||||
return outBinary.size() != 0;
|
||||
}
|
||||
|
||||
void setGfxCore(GFXCORE_FAMILY core) override {
|
||||
}
|
||||
|
||||
void setProductFamily(PRODUCT_FAMILY product) override {
|
||||
}
|
||||
|
||||
bool isKnownPlatform() const override {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool tryLoadIga() override {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string asmToReturn;
|
||||
std::string binaryToReturn;
|
||||
std::string receivedAsm;
|
||||
std::string receivedBinary;
|
||||
|
||||
bool disasmWasCalled = false;
|
||||
bool asmWasCalled = false;
|
||||
};
|
Reference in New Issue
Block a user