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
@ -292,6 +292,46 @@ else()
|
||||
message(STATUS "IGC targets: ${IGDRCL__IGC_TARGETS}")
|
||||
endif()
|
||||
|
||||
# VISA headers - always relative to IGC
|
||||
if(IS_DIRECTORY "${IGC_DIR}/../visa")
|
||||
get_filename_component(VISA_DIR "${IGC_DIR}/../visa" ABSOLUTE)
|
||||
elseif(IS_DIRECTORY "${IGC_DIR}/visa")
|
||||
set(VISA_DIR "${IGC_DIR}/visa")
|
||||
elseif(IS_DIRECTORY "${IGC_DIR}/include/visa")
|
||||
set(VISA_DIR "${IGC_DIR}/include/visa")
|
||||
elseif(IS_DIRECTORY "${IGDRCL__IGC_INCLUDEDIR}/../visa")
|
||||
get_filename_component(VISA_DIR "${IGDRCL__IGC_INCLUDEDIR}/../visa" ABSOLUTE)
|
||||
endif()
|
||||
message("VISA_DIR : ${VISA_DIR}")
|
||||
|
||||
if(IS_DIRECTORY "${VISA_DIR}/include")
|
||||
set(VISA_INCLUDE_DIR "${VISA_DIR}/include")
|
||||
else()
|
||||
set(VISA_INCLUDE_DIR "${VISA_DIR}")
|
||||
endif()
|
||||
|
||||
# IGA headers - always relative to VISA
|
||||
if(IS_DIRECTORY "${VISA_DIR}/../iga")
|
||||
get_filename_component(IGA_DIR "${VISA_DIR}/../iga" ABSOLUTE)
|
||||
elseif(IS_DIRECTORY "${VISA_DIR}/iga")
|
||||
set(IGA_DIR "${VISA_DIR}/iga")
|
||||
endif()
|
||||
|
||||
if(IS_DIRECTORY "${IGA_DIR}/IGALibrary/api")
|
||||
set(IGA_INCLUDE_DIR "${IGA_DIR}/IGALibrary/api")
|
||||
else()
|
||||
set(IGA_INCLUDE_DIR "${IGA_DIR}")
|
||||
endif()
|
||||
|
||||
if(IS_DIRECTORY ${IGA_INCLUDE_DIR})
|
||||
set(IGA_HEADERS_AVAILABLE TRUE)
|
||||
set(IGA_LIBRARY_NAME "iga${NEO_BITS}")
|
||||
else()
|
||||
set(IGA_HEADERS_AVAILABLE FALSE)
|
||||
endif()
|
||||
|
||||
message("IGA_INCLUDE_DIR : ${IGA_INCLUDE_DIR}")
|
||||
|
||||
if(WIN32)
|
||||
set(IGC_LIBRARY_NAME "igc${NEO_BITS}")
|
||||
set(FCL_LIBRARY_NAME "igdfcl${NEO_BITS}")
|
||||
|
@ -7,27 +7,40 @@
|
||||
project(ocloc)
|
||||
|
||||
set(CLOC_SRCS_LIB
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/decoder/binary_decoder.cpp
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/decoder/binary_decoder.h
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/decoder/binary_encoder.cpp
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/decoder/binary_encoder.h
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/decoder/helper.cpp
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/decoder/helper.h
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/helper.cpp
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/offline_compiler.cpp
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/offline_compiler.h
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/multi_command.cpp
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/multi_command.h
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/options.cpp
|
||||
${IGDRCL_SOURCE_DIR}/runtime/compiler_interface/create_main.cpp
|
||||
${IGDRCL_SOURCE_DIR}/runtime/helpers/abort.cpp
|
||||
${IGDRCL_SOURCE_DIR}/runtime/helpers/debug_helpers.cpp
|
||||
${IGDRCL_SOURCE_DIR}/runtime/helpers/file_io.cpp
|
||||
${IGDRCL_SOURCE_DIR}/runtime/helpers/hw_info.cpp
|
||||
${IGDRCL_SOURCE_DIR}/runtime/platform/extensions.cpp
|
||||
${IGDRCL_SOURCE_DIR}/runtime/platform/extensions.h
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/decoder/binary_decoder.cpp
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/decoder/binary_decoder.h
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/decoder/binary_encoder.cpp
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/decoder/binary_encoder.h
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/decoder/helper.cpp
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/decoder/helper.h
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/decoder/iga_wrapper.h
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/decoder/translate_platform_base.h
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/helper.cpp
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/offline_compiler.cpp
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/offline_compiler.h
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/multi_command.cpp
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/multi_command.h
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/options.cpp
|
||||
${IGDRCL_SOURCE_DIR}/runtime/compiler_interface/create_main.cpp
|
||||
${IGDRCL_SOURCE_DIR}/runtime/helpers/abort.cpp
|
||||
${IGDRCL_SOURCE_DIR}/runtime/helpers/debug_helpers.cpp
|
||||
${IGDRCL_SOURCE_DIR}/runtime/helpers/file_io.cpp
|
||||
${IGDRCL_SOURCE_DIR}/runtime/helpers/hw_info.cpp
|
||||
${IGDRCL_SOURCE_DIR}/runtime/platform/extensions.cpp
|
||||
${IGDRCL_SOURCE_DIR}/runtime/platform/extensions.h
|
||||
)
|
||||
|
||||
if(${IGA_HEADERS_AVAILABLE})
|
||||
set(CLOC_SRCS_LIB ${CLOC_SRCS_LIB}
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/decoder/iga_wrapper.cpp
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/decoder${BRANCH_DIR_SUFFIX}/translate_platform.cpp
|
||||
)
|
||||
else()
|
||||
set(CLOC_SRCS_LIB ${CLOC_SRCS_LIB}
|
||||
${IGDRCL_SOURCE_DIR}/offline_compiler/decoder/iga_stubs.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND CLOC_SRCS_LIB
|
||||
${IGDRCL_SOURCE_DIR}/runtime/os_interface/windows/os_library.cpp
|
||||
@ -96,8 +109,10 @@ set(CLOC_INCLUDES
|
||||
)
|
||||
|
||||
target_include_directories(ocloc BEFORE PRIVATE ${CLOC_INCLUDES})
|
||||
target_include_directories(ocloc BEFORE PRIVATE ${IGA_INCLUDE_DIR})
|
||||
|
||||
target_compile_definitions(ocloc PUBLIC ${CLOC_LIB_FLAGS_DEFINITIONS} ${SUPPORTED_GEN_FLAGS_DEFINITONS} DEFAULT_PLATFORM=${DEFAULT_SUPPORTED_PLATFORM})
|
||||
target_compile_definitions(ocloc PUBLIC ${CLOC_LIB_FLAGS_DEFINITIONS} ${SUPPORTED_GEN_FLAGS_DEFINITONS} DEFAULT_PLATFORM=${DEFAULT_SUPPORTED_PLATFORM}
|
||||
IGA_LIBRARY_NAME=${CMAKE_SHARED_LIBRARY_PREFIX}${IGA_LIBRARY_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX})
|
||||
|
||||
if(MSVC)
|
||||
target_link_libraries(ocloc dbghelp)
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "core/helpers/ptr_math.h"
|
||||
#include "elf/reader.h"
|
||||
#include "offline_compiler/offline_compiler.h"
|
||||
#include "runtime/helpers/file_io.h"
|
||||
|
||||
#include "helper.h"
|
||||
@ -242,18 +243,22 @@ void BinaryDecoder::parseTokens() {
|
||||
}
|
||||
|
||||
void BinaryDecoder::printHelp() {
|
||||
messagePrinter.printf("Usage:\n-file <Opencl elf binary file> -patch <path to folder containing patchlist> -dump <path to dumping folder>\n");
|
||||
messagePrinter.printf("Usage:\n-file <Opencl elf binary file> -patch <path to folder containing patchlist> -dump <path to dumping folder> -device <device_type>\n");
|
||||
messagePrinter.printf("e.g. -file C:/my_folder/my_binary.bin -patch C:/igc/inc -dump C:/my_folder/dump\n");
|
||||
messagePrinter.printf(" -device <device_type> Indicates which device for which we will compile.\n");
|
||||
messagePrinter.printf(" <device_type> can be: %s\n", NEO::getDevicesTypes().c_str());
|
||||
}
|
||||
|
||||
int BinaryDecoder::processBinary(void *&ptr, std::ostream &ptmFile) {
|
||||
ptmFile << "ProgramBinaryHeader:\n";
|
||||
uint32_t numberOfKernels = 0, patchListSize = 0;
|
||||
uint32_t numberOfKernels = 0, patchListSize = 0, device = 0;
|
||||
for (const auto &v : programHeader.fields) {
|
||||
if (v.name == "NumberOfKernels") {
|
||||
numberOfKernels = readUnaligned<uint32_t>(ptr);
|
||||
} else if (v.name == "PatchListSize") {
|
||||
patchListSize = readUnaligned<uint32_t>(ptr);
|
||||
} else if (v.name == "Device") {
|
||||
device = readUnaligned<uint32_t>(ptr);
|
||||
}
|
||||
dumpField(ptr, v, ptmFile);
|
||||
}
|
||||
@ -262,6 +267,7 @@ int BinaryDecoder::processBinary(void *&ptr, std::ostream &ptmFile) {
|
||||
}
|
||||
|
||||
readPatchTokens(ptr, patchListSize, ptmFile);
|
||||
iga->setGfxCore(static_cast<GFXCORE_FAMILY>(device));
|
||||
|
||||
//Reading Kernels
|
||||
for (uint32_t i = 0; i < numberOfKernels; ++i) {
|
||||
@ -272,7 +278,7 @@ int BinaryDecoder::processBinary(void *&ptr, std::ostream &ptmFile) {
|
||||
}
|
||||
|
||||
void BinaryDecoder::processKernel(void *&ptr, std::ostream &ptmFile) {
|
||||
uint32_t KernelNameSize = 0, KernelPatchListSize = 0, KernelHeapSize = 0,
|
||||
uint32_t KernelNameSize = 0, KernelPatchListSize = 0, KernelHeapSize = 0, KernelUnpaddedSize = 0,
|
||||
GeneralStateHeapSize = 0, DynamicStateHeapSize = 0, SurfaceStateHeapSize = 0;
|
||||
ptmFile << "KernelBinaryHeader:\n";
|
||||
for (const auto &v : kernelHeader.fields) {
|
||||
@ -282,6 +288,8 @@ void BinaryDecoder::processKernel(void *&ptr, std::ostream &ptmFile) {
|
||||
KernelNameSize = readUnaligned<uint32_t>(ptr);
|
||||
else if (v.name == "KernelHeapSize")
|
||||
KernelHeapSize = readUnaligned<uint32_t>(ptr);
|
||||
else if (v.name == "KernelUnpaddedSize")
|
||||
KernelUnpaddedSize = readUnaligned<uint32_t>(ptr);
|
||||
else if (v.name == "GeneralStateHeapSize")
|
||||
GeneralStateHeapSize = readUnaligned<uint32_t>(ptr);
|
||||
else if (v.name == "DynamicStateHeapSize")
|
||||
@ -302,8 +310,14 @@ void BinaryDecoder::processKernel(void *&ptr, std::ostream &ptmFile) {
|
||||
ptmFile << kernelName << '\n';
|
||||
ptr = ptrOffset(ptr, KernelNameSize);
|
||||
|
||||
std::string fileName = pathToDump + kernelName + "_KernelHeap.bin";
|
||||
writeDataToFile(fileName.c_str(), ptr, KernelHeapSize);
|
||||
std::string fileName = pathToDump + kernelName + "_KernelHeap";
|
||||
messagePrinter.printf("Trying to disassemble %s.krn\n", kernelName.c_str());
|
||||
std::string disassembledKernel;
|
||||
if (iga->tryDisassembleGenISA(ptr, KernelUnpaddedSize, disassembledKernel)) {
|
||||
writeDataToFile((fileName + ".asm").c_str(), disassembledKernel.data(), disassembledKernel.size());
|
||||
} else {
|
||||
writeDataToFile((fileName + ".dat").c_str(), ptr, KernelHeapSize);
|
||||
}
|
||||
ptr = ptrOffset(ptr, KernelHeapSize);
|
||||
|
||||
if (GeneralStateHeapSize != 0) {
|
||||
@ -411,6 +425,8 @@ int BinaryDecoder::validateInput(uint32_t argc, const char **argv) {
|
||||
for (uint32_t i = 2; i < argc - 1; ++i) {
|
||||
if (!strcmp(argv[i], "-file")) {
|
||||
binaryFile = std::string(argv[++i]);
|
||||
} else if (!strcmp(argv[i], "-device")) {
|
||||
iga->setProductFamily(getProductFamilyFromDeviceName(argv[++i]));
|
||||
} else if (!strcmp(argv[i], "-patch")) {
|
||||
pathToPatch = std::string(argv[++i]);
|
||||
addSlash(pathToPatch);
|
||||
@ -427,10 +443,15 @@ int BinaryDecoder::validateInput(uint32_t argc, const char **argv) {
|
||||
messagePrinter.printf(".bin extension is expected for binary file.\n");
|
||||
printHelp();
|
||||
return -1;
|
||||
} else if (pathToDump.empty()) {
|
||||
messagePrinter.printf("Path to dump folder can't be empty.\n");
|
||||
printHelp();
|
||||
return -1;
|
||||
}
|
||||
if (pathToDump.empty()) {
|
||||
messagePrinter.printf("Warning : Path to dump folder not specificed - using ./dump as default.\n");
|
||||
pathToDump = "dump";
|
||||
addSlash(pathToDump);
|
||||
}
|
||||
|
||||
if (false == iga->isKnownPlatform()) {
|
||||
messagePrinter.printf("Warning : missing or invalid -device parameter - results may be inacurate\n");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "elf/types.h"
|
||||
|
||||
#include "helper.h"
|
||||
#include "iga_wrapper.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@ -21,7 +22,7 @@ struct PTField {
|
||||
};
|
||||
|
||||
struct BinaryHeader {
|
||||
std::vector<PTField> fields; // (size, name)
|
||||
std::vector<PTField> fields;
|
||||
uint32_t size;
|
||||
};
|
||||
struct PatchToken : BinaryHeader {
|
||||
@ -32,7 +33,9 @@ using PTMap = std::unordered_map<uint8_t, std::unique_ptr<PatchToken>>;
|
||||
|
||||
class BinaryDecoder {
|
||||
public:
|
||||
BinaryDecoder() = default;
|
||||
BinaryDecoder() : iga(new IgaWrapper) {
|
||||
iga->setMessagePrinter(messagePrinter);
|
||||
}
|
||||
BinaryDecoder(const std::string &file, const std::string &patch, const std::string &dump)
|
||||
: binaryFile(file), pathToPatch(patch), pathToDump(dump){};
|
||||
int decode();
|
||||
@ -43,6 +46,7 @@ class BinaryDecoder {
|
||||
protected:
|
||||
BinaryHeader programHeader, kernelHeader;
|
||||
CLElfLib::ElfBinaryStorage binary;
|
||||
std::unique_ptr<IgaWrapper> iga;
|
||||
PTMap patchTokens;
|
||||
std::string binaryFile, pathToPatch, pathToDump;
|
||||
MessagePrinter messagePrinter;
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "binary_encoder.h"
|
||||
|
||||
#include "elf/writer.h"
|
||||
#include "offline_compiler/offline_compiler.h"
|
||||
#include "runtime/helpers/aligned_memory.h"
|
||||
#include "runtime/helpers/file_io.h"
|
||||
#include "runtime/helpers/hash.h"
|
||||
@ -138,8 +139,10 @@ int BinaryEncoder::createElf() {
|
||||
}
|
||||
|
||||
void BinaryEncoder::printHelp() {
|
||||
messagePrinter.printf("Usage:\n-dump <path to dumping folder> -out <new elf file>\n");
|
||||
messagePrinter.printf("Usage:\n-dump <path to dumping folder> -out <new elf file> -device <device_type>\n");
|
||||
messagePrinter.printf("e.g. -dump C:/my_folder/dump -out C:/my_folder/new_binary.bin\n");
|
||||
messagePrinter.printf(" -device <device_type> Indicates which device for which we will compile.\n");
|
||||
messagePrinter.printf(" <device_type> can be: %s\n", NEO::getDevicesTypes().c_str());
|
||||
}
|
||||
|
||||
int BinaryEncoder::encode() {
|
||||
@ -161,15 +164,26 @@ int BinaryEncoder::encode() {
|
||||
return createElf();
|
||||
}
|
||||
|
||||
int BinaryEncoder::processBinary(const std::vector<std::string> &ptmFile, std::ostream &deviceBinary) {
|
||||
int BinaryEncoder::processBinary(const std::vector<std::string> &ptmFileLines, std::ostream &deviceBinary) {
|
||||
if (false == iga->isKnownPlatform()) {
|
||||
auto deviceMarker = findPos(ptmFileLines, "Device");
|
||||
if (deviceMarker != ptmFileLines.size()) {
|
||||
std::stringstream ss(ptmFileLines[deviceMarker]);
|
||||
ss.ignore(32, ' ');
|
||||
ss.ignore(32, ' ');
|
||||
uint32_t gfxCore = 0;
|
||||
ss >> gfxCore;
|
||||
iga->setGfxCore(static_cast<GFXCORE_FAMILY>(gfxCore));
|
||||
}
|
||||
}
|
||||
size_t i = 0;
|
||||
while (i < ptmFile.size()) {
|
||||
if (ptmFile[i].find("Kernel #") != std::string::npos) {
|
||||
if (processKernel(++i, ptmFile, deviceBinary)) {
|
||||
while (i < ptmFileLines.size()) {
|
||||
if (ptmFileLines[i].find("Kernel #") != std::string::npos) {
|
||||
if (processKernel(++i, ptmFileLines, deviceBinary)) {
|
||||
messagePrinter.printf("Warning while processing kernel!\n");
|
||||
return -1;
|
||||
}
|
||||
} else if (writeDeviceBinary(ptmFile[i++], deviceBinary)) {
|
||||
} else if (writeDeviceBinary(ptmFileLines[i++], deviceBinary)) {
|
||||
messagePrinter.printf("Error while writing to binary!\n");
|
||||
return -1;
|
||||
}
|
||||
@ -222,7 +236,22 @@ int BinaryEncoder::processKernel(size_t &line, const std::vector<std::string> &p
|
||||
|
||||
// Write KernelHeap and padding
|
||||
uint32_t kernelSizeUnpadded = 0U;
|
||||
bool heapsCopiedSuccesfully = copyBinaryToBinary(pathToDump + kernelName + "_KernelHeap.bin", kernelBlob, &kernelSizeUnpadded);
|
||||
bool heapsCopiedSuccesfully = true;
|
||||
|
||||
// Use .asm if available, fallback to .dat
|
||||
if (fileExists(pathToDump + kernelName + "_KernelHeap.asm")) {
|
||||
auto kernelAsAsm = readBinaryFile(pathToDump + kernelName + "_KernelHeap.asm");
|
||||
std::string kernelAsBinary;
|
||||
messagePrinter.printf("Trying to assemble %s.asm\n", kernelName.c_str());
|
||||
if (false == iga->tryAssembleGenISA(std::string(kernelAsAsm.begin(), kernelAsAsm.end()), kernelAsBinary)) {
|
||||
messagePrinter.printf("Error : Could not assemble : %s\n", kernelName.c_str());
|
||||
return -1;
|
||||
}
|
||||
kernelSizeUnpadded = static_cast<uint32_t>(kernelAsBinary.size());
|
||||
kernelBlob.write(kernelAsBinary.data(), kernelAsBinary.size());
|
||||
} else {
|
||||
heapsCopiedSuccesfully = copyBinaryToBinary(pathToDump + kernelName + "_KernelHeap.dat", kernelBlob, &kernelSizeUnpadded);
|
||||
}
|
||||
|
||||
// Adding padding and alignment
|
||||
addPadding(kernelBlob, isaPaddingSizeInBytes);
|
||||
@ -286,6 +315,8 @@ int BinaryEncoder::validateInput(uint32_t argc, const char **argv) {
|
||||
if (!strcmp(argv[i], "-dump")) {
|
||||
pathToDump = std::string(argv[++i]);
|
||||
addSlash(pathToDump);
|
||||
} else if (!strcmp(argv[i], "-device")) {
|
||||
iga->setProductFamily(getProductFamilyFromDeviceName(argv[++i]));
|
||||
} else if (!strcmp(argv[i], "-out")) {
|
||||
elfName = std::string(argv[++i]);
|
||||
} else {
|
||||
@ -295,14 +326,19 @@ int BinaryEncoder::validateInput(uint32_t argc, const char **argv) {
|
||||
}
|
||||
}
|
||||
if (pathToDump.empty()) {
|
||||
messagePrinter.printf("Path to dump folder can't be empty.\n");
|
||||
printHelp();
|
||||
return -1;
|
||||
} else if (elfName.find(".bin") == std::string::npos) {
|
||||
messagePrinter.printf("Warning : Path to dump folder not specificed - using ./dump as default.\n");
|
||||
pathToDump = "dump";
|
||||
addSlash(pathToDump);
|
||||
}
|
||||
if (elfName.find(".bin") == std::string::npos) {
|
||||
messagePrinter.printf(".bin extension is expected for binary file.\n");
|
||||
printHelp();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (false == iga->isKnownPlatform()) {
|
||||
messagePrinter.printf("Warning : missing or invalid -device parameter - results may be inacurate\n");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -364,3 +400,11 @@ int BinaryEncoder::writeDeviceBinary(const std::string &line, std::ostream &devi
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool BinaryEncoder::fileExists(const std::string &path) const {
|
||||
return ::fileExists(path);
|
||||
}
|
||||
|
||||
std::vector<char> BinaryEncoder::readBinaryFile(const std::string &path) const {
|
||||
return ::readBinaryFile(path);
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#pragma once
|
||||
#include "helper.h"
|
||||
#include "iga_wrapper.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
@ -14,7 +15,9 @@
|
||||
|
||||
class BinaryEncoder {
|
||||
public:
|
||||
BinaryEncoder() = default;
|
||||
BinaryEncoder() : iga(new IgaWrapper) {
|
||||
iga->setMessagePrinter(messagePrinter);
|
||||
}
|
||||
BinaryEncoder(const std::string &dump, const std::string &elf)
|
||||
: pathToDump(dump), elfName(elf){};
|
||||
int encode();
|
||||
@ -25,7 +28,7 @@ class BinaryEncoder {
|
||||
protected:
|
||||
std::string pathToDump, elfName;
|
||||
MessagePrinter messagePrinter;
|
||||
|
||||
std::unique_ptr<IgaWrapper> iga;
|
||||
void calculatePatchListSizes(std::vector<std::string> &ptmFile);
|
||||
MOCKABLE_VIRTUAL bool copyBinaryToBinary(const std::string &srcFileName, std::ostream &outBinary, uint32_t *binaryLength);
|
||||
bool copyBinaryToBinary(const std::string &srcFileName, std::ostream &outBinary) {
|
||||
@ -39,4 +42,6 @@ class BinaryEncoder {
|
||||
void write(std::stringstream &in, std::ostream &deviceBinary);
|
||||
int writeDeviceBinary(const std::string &line, std::ostream &deviceBinary);
|
||||
void addPadding(std::ostream &out, size_t numBytes);
|
||||
MOCKABLE_VIRTUAL bool fileExists(const std::string &path) const;
|
||||
MOCKABLE_VIRTUAL std::vector<char> readBinaryFile(const std::string &path) const;
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
* Copyright (C) 2018-2019 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
@ -7,6 +7,12 @@
|
||||
|
||||
#include "helper.h"
|
||||
|
||||
#include "runtime/helpers/hw_info.h"
|
||||
#include "runtime/os_interface/os_inc_base.h"
|
||||
#include "runtime/os_interface/os_library.h"
|
||||
|
||||
#include "igfxfmid.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
|
||||
@ -66,3 +72,12 @@ size_t findPos(const std::vector<std::string> &lines, const std::string &whatToF
|
||||
}
|
||||
return lines.size();
|
||||
}
|
||||
|
||||
PRODUCT_FAMILY getProductFamilyFromDeviceName(const std::string &deviceName) {
|
||||
for (unsigned int productId = 0; productId < IGFX_MAX_PRODUCT; ++productId) {
|
||||
if (deviceName == NEO::hardwarePrefix[productId]) {
|
||||
return static_cast<PRODUCT_FAMILY>(productId);
|
||||
}
|
||||
}
|
||||
return IGFX_UNKNOWN;
|
||||
}
|
||||
|
@ -6,7 +6,12 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "runtime/os_interface/os_library.h"
|
||||
|
||||
#include "igfxfmid.h"
|
||||
|
||||
#include <exception>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@ -18,6 +23,8 @@ void readFileToVectorOfStrings(std::vector<std::string> &lines, const std::strin
|
||||
|
||||
size_t findPos(const std::vector<std::string> &lines, const std::string &whatToFind);
|
||||
|
||||
PRODUCT_FAMILY getProductFamilyFromDeviceName(const std::string &deviceName);
|
||||
|
||||
class MessagePrinter {
|
||||
public:
|
||||
MessagePrinter() = default;
|
||||
|
39
offline_compiler/decoder/iga_stubs.cpp
Normal file
39
offline_compiler/decoder/iga_stubs.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2019 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "helper.h"
|
||||
#include "iga_wrapper.h"
|
||||
|
||||
struct IgaWrapper::Impl {
|
||||
};
|
||||
|
||||
IgaWrapper::IgaWrapper() = default;
|
||||
IgaWrapper::~IgaWrapper() = default;
|
||||
|
||||
bool IgaWrapper::tryDisassembleGenISA(const void *kernelPtr, uint32_t kernelSize, std::string &out) {
|
||||
messagePrinter->printf("Warning: ocloc built without support for IGA - kernel binaries won't be disassembled.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IgaWrapper::tryAssembleGenISA(const std::string &inAsm, std::string &outBinary) {
|
||||
messagePrinter->printf("Warning: ocloc built without support for IGA - kernel binaries won't be assembled.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IgaWrapper::tryLoadIga() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void IgaWrapper::setGfxCore(GFXCORE_FAMILY core) {
|
||||
}
|
||||
|
||||
void IgaWrapper::setProductFamily(PRODUCT_FAMILY product) {
|
||||
}
|
||||
|
||||
bool IgaWrapper::isKnownPlatform() const {
|
||||
return false;
|
||||
}
|
192
offline_compiler/decoder/iga_wrapper.cpp
Normal file
192
offline_compiler/decoder/iga_wrapper.cpp
Normal file
@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2019 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "iga_wrapper.h"
|
||||
|
||||
#include "runtime/helpers/hw_info.h"
|
||||
#include "runtime/os_interface/os_inc_base.h"
|
||||
#include "runtime/os_interface/os_library.h"
|
||||
|
||||
#include "helper.h"
|
||||
#include "igfxfmid.h"
|
||||
#include "translate_platform_base.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
struct IgaLibrary {
|
||||
pIGAAssemble assemble = nullptr;
|
||||
pIGAContextCreate contextCreate = nullptr;
|
||||
pIGAContextGetErrors contextGetErrors = nullptr;
|
||||
pIGAContextGetWarnings contextGetWarnings = nullptr;
|
||||
pIGAContextRelease contextRelease = nullptr;
|
||||
pIGADisassemble disassemble = nullptr;
|
||||
pIGAStatusToString statusToString = nullptr;
|
||||
iga_context_options_t OptsContext = {};
|
||||
|
||||
std::unique_ptr<NEO::OsLibrary> library;
|
||||
|
||||
bool isLoaded() {
|
||||
return library != nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
struct IgaWrapper::Impl {
|
||||
iga_gen_t igaGen = IGA_GEN_INVALID;
|
||||
IgaLibrary igaLib;
|
||||
|
||||
void loadIga() {
|
||||
IgaLibrary iga;
|
||||
iga.OptsContext.cb = sizeof(igaLib.OptsContext);
|
||||
iga.OptsContext.gen = igaGen;
|
||||
|
||||
#define STR2(X) #X
|
||||
#define STR(X) STR2(X)
|
||||
iga.library.reset(NEO::OsLibrary::load(STR(IGA_LIBRARY_NAME)));
|
||||
if (iga.library == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
#define LOAD_OR_ERROR(MEMBER, FUNC_NAME) \
|
||||
if (nullptr == (iga.MEMBER = reinterpret_cast<decltype(iga.MEMBER)>(iga.library->getProcAddress(FUNC_NAME)))) { \
|
||||
printf("Warning : Couldn't find %s in %s\n", FUNC_NAME, STR(IGA_LIBRARY_NAME)); \
|
||||
return; \
|
||||
}
|
||||
|
||||
LOAD_OR_ERROR(assemble, IGA_ASSEMBLE_STR);
|
||||
LOAD_OR_ERROR(contextCreate, IGA_CONTEXT_CREATE_STR);
|
||||
LOAD_OR_ERROR(contextGetErrors, IGA_CONTEXT_GET_ERRORS_STR);
|
||||
LOAD_OR_ERROR(contextGetWarnings, IGA_CONTEXT_GET_WARNINGS_STR);
|
||||
LOAD_OR_ERROR(contextRelease, IGA_CONTEXT_RELEASE_STR);
|
||||
LOAD_OR_ERROR(disassemble, IGA_DISASSEMBLE_STR);
|
||||
LOAD_OR_ERROR(statusToString, IGA_STATUS_TO_STRING_STR);
|
||||
|
||||
#undef LOAD_OR_ERROR
|
||||
#undef STR
|
||||
#undef STR2
|
||||
|
||||
this->igaLib = std::move(iga);
|
||||
}
|
||||
};
|
||||
|
||||
IgaWrapper::IgaWrapper()
|
||||
: pimpl(new Impl()) {
|
||||
}
|
||||
|
||||
IgaWrapper::~IgaWrapper() = default;
|
||||
|
||||
bool IgaWrapper::tryDisassembleGenISA(const void *kernelPtr, uint32_t kernelSize, std::string &out) {
|
||||
if (false == tryLoadIga()) {
|
||||
messagePrinter->printf("Warning: couldn't load iga - kernel binaries won't be disassembled.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
iga_context_t context;
|
||||
iga_disassemble_options_t disassembleOptions = IGA_DISASSEMBLE_OPTIONS_INIT();
|
||||
iga_status_t stat;
|
||||
|
||||
stat = pimpl->igaLib.contextCreate(&pimpl->igaLib.OptsContext, &context);
|
||||
if (stat != 0) {
|
||||
messagePrinter->printf("Error while creating IGA Context! Error msg: %s", pimpl->igaLib.statusToString(stat));
|
||||
return false;
|
||||
}
|
||||
|
||||
char kernelText = '\0';
|
||||
char *pKernelText = &kernelText;
|
||||
|
||||
stat = pimpl->igaLib.disassemble(context, &disassembleOptions, kernelPtr, kernelSize, nullptr, nullptr, &pKernelText);
|
||||
if (stat != 0) {
|
||||
messagePrinter->printf("Error while disassembling with IGA!\nStatus msg: %s\n", pimpl->igaLib.statusToString(stat));
|
||||
const iga_diagnostic_t *errors;
|
||||
uint32_t size = 100;
|
||||
pimpl->igaLib.contextGetErrors(context, &errors, &size);
|
||||
if (errors != nullptr) {
|
||||
messagePrinter->printf("Errors: %s\n", errors->message);
|
||||
}
|
||||
pimpl->igaLib.contextRelease(context);
|
||||
return false;
|
||||
}
|
||||
|
||||
const iga_diagnostic_t *warnings;
|
||||
uint32_t warningsSize = 100;
|
||||
pimpl->igaLib.contextGetWarnings(context, &warnings, &warningsSize);
|
||||
if (warningsSize > 0 && warnings != nullptr) {
|
||||
messagePrinter->printf("Warnings: %s\n", warnings->message);
|
||||
}
|
||||
|
||||
out = pKernelText;
|
||||
pimpl->igaLib.contextRelease(context);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IgaWrapper::tryAssembleGenISA(const std::string &inAsm, std::string &outBinary) {
|
||||
if (false == tryLoadIga()) {
|
||||
messagePrinter->printf("Warning: couldn't load iga - kernel binaries won't be assembled.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
iga_context_t context;
|
||||
iga_status_t stat;
|
||||
iga_assemble_options_t assembleOptions = IGA_ASSEMBLE_OPTIONS_INIT();
|
||||
|
||||
stat = pimpl->igaLib.contextCreate(&pimpl->igaLib.OptsContext, &context);
|
||||
if (stat != 0) {
|
||||
messagePrinter->printf("Error while creating IGA Context! Error msg: %s", pimpl->igaLib.statusToString(stat));
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t size = 0;
|
||||
void *pOutput = nullptr;
|
||||
stat = pimpl->igaLib.assemble(context, &assembleOptions, inAsm.c_str(), &pOutput, &size);
|
||||
if (stat != 0) {
|
||||
messagePrinter->printf("Error while assembling with IGA!\nStatus msg: %s\n", pimpl->igaLib.statusToString(stat));
|
||||
|
||||
const iga_diagnostic_t *errors;
|
||||
uint32_t size = 100;
|
||||
pimpl->igaLib.contextGetErrors(context, &errors, &size);
|
||||
if (errors != nullptr) {
|
||||
messagePrinter->printf("Errors: %s\n", errors->message);
|
||||
}
|
||||
|
||||
pimpl->igaLib.contextRelease(context);
|
||||
return false;
|
||||
}
|
||||
|
||||
const iga_diagnostic_t *warnings;
|
||||
uint32_t context_size;
|
||||
pimpl->igaLib.contextGetWarnings(context, &warnings, &context_size);
|
||||
if (context_size > 0 && warnings != nullptr) {
|
||||
messagePrinter->printf("Warnings: %s\n", warnings->message);
|
||||
}
|
||||
|
||||
outBinary.assign(reinterpret_cast<char *>(pOutput), reinterpret_cast<char *>(pOutput) + size);
|
||||
|
||||
pimpl->igaLib.contextRelease(context);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IgaWrapper::tryLoadIga() {
|
||||
if (false == pimpl->igaLib.isLoaded()) {
|
||||
pimpl->loadIga();
|
||||
}
|
||||
return pimpl->igaLib.isLoaded();
|
||||
}
|
||||
|
||||
void IgaWrapper::setGfxCore(GFXCORE_FAMILY core) {
|
||||
if (pimpl->igaGen == IGA_GEN_INVALID) {
|
||||
pimpl->igaGen = translateToIgaGen(core);
|
||||
}
|
||||
}
|
||||
|
||||
void IgaWrapper::setProductFamily(PRODUCT_FAMILY product) {
|
||||
if (pimpl->igaGen == IGA_GEN_INVALID) {
|
||||
pimpl->igaGen = translateToIgaGen(product);
|
||||
}
|
||||
}
|
||||
|
||||
bool IgaWrapper::isKnownPlatform() const {
|
||||
return pimpl->igaGen != IGA_GEN_INVALID;
|
||||
}
|
43
offline_compiler/decoder/iga_wrapper.h
Normal file
43
offline_compiler/decoder/iga_wrapper.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2019 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "igfxfmid.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
class MessagePrinter;
|
||||
|
||||
struct IgaWrapper {
|
||||
IgaWrapper();
|
||||
MOCKABLE_VIRTUAL ~IgaWrapper();
|
||||
|
||||
IgaWrapper(IgaWrapper &) = delete;
|
||||
IgaWrapper(const IgaWrapper &&) = delete;
|
||||
IgaWrapper &operator=(IgaWrapper &) = delete;
|
||||
IgaWrapper &operator=(const IgaWrapper &&) = delete;
|
||||
|
||||
MOCKABLE_VIRTUAL bool tryDisassembleGenISA(const void *kernelPtr, uint32_t kernelSize, std::string &out);
|
||||
MOCKABLE_VIRTUAL bool tryAssembleGenISA(const std::string &inAsm, std::string &outBinary);
|
||||
|
||||
MOCKABLE_VIRTUAL void setGfxCore(GFXCORE_FAMILY core);
|
||||
MOCKABLE_VIRTUAL void setProductFamily(PRODUCT_FAMILY product);
|
||||
MOCKABLE_VIRTUAL bool isKnownPlatform() const;
|
||||
void setMessagePrinter(MessagePrinter &messagePrinter) {
|
||||
this->messagePrinter = &messagePrinter;
|
||||
}
|
||||
|
||||
protected:
|
||||
MOCKABLE_VIRTUAL bool tryLoadIga();
|
||||
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> pimpl;
|
||||
|
||||
MessagePrinter *messagePrinter;
|
||||
};
|
16
offline_compiler/decoder/translate_platform.cpp
Normal file
16
offline_compiler/decoder/translate_platform.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "offline_compiler/decoder/translate_platform_base.h"
|
||||
|
||||
iga_gen_t translateToIgaGen(PRODUCT_FAMILY productFamily) {
|
||||
return translateToIgaGenBase(productFamily);
|
||||
}
|
||||
|
||||
iga_gen_t translateToIgaGen(GFXCORE_FAMILY coreFamily) {
|
||||
return translateToIgaGenBase(coreFamily);
|
||||
}
|
52
offline_compiler/decoder/translate_platform_base.h
Normal file
52
offline_compiler/decoder/translate_platform_base.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "igad.h"
|
||||
#include "igfxfmid.h"
|
||||
|
||||
inline iga_gen_t translateToIgaGenBase(PRODUCT_FAMILY productFamily) {
|
||||
switch (productFamily) {
|
||||
default:
|
||||
return IGA_GEN_INVALID;
|
||||
case IGFX_BROADWELL:
|
||||
return IGA_GEN8;
|
||||
case IGFX_CHERRYVIEW:
|
||||
return IGA_GEN8lp;
|
||||
case IGFX_SKYLAKE:
|
||||
return IGA_GEN9;
|
||||
case IGFX_BROXTON:
|
||||
return IGA_GEN9lp;
|
||||
case IGFX_KABYLAKE:
|
||||
return IGA_GEN9p5;
|
||||
case IGFX_COFFEELAKE:
|
||||
return IGA_GEN9p5;
|
||||
case IGFX_ICELAKE:
|
||||
return IGA_GEN11;
|
||||
case IGFX_ICELAKE_LP:
|
||||
return IGA_GEN11;
|
||||
}
|
||||
}
|
||||
|
||||
inline iga_gen_t translateToIgaGenBase(GFXCORE_FAMILY coreFamily) {
|
||||
switch (coreFamily) {
|
||||
default:
|
||||
return IGA_GEN_INVALID;
|
||||
case IGFX_GEN8_CORE:
|
||||
return IGA_GEN8;
|
||||
case IGFX_GEN9_CORE:
|
||||
return IGA_GEN9;
|
||||
case IGFX_GEN11_CORE:
|
||||
return IGA_GEN11;
|
||||
case IGFX_GEN11LP_CORE:
|
||||
return IGA_GEN11;
|
||||
}
|
||||
}
|
||||
|
||||
iga_gen_t translateToIgaGen(PRODUCT_FAMILY productFamily);
|
||||
iga_gen_t translateToIgaGen(GFXCORE_FAMILY coreFamily);
|
@ -20,7 +20,7 @@ using namespace NEO;
|
||||
|
||||
int main(int numArgs, const char *argv[]) {
|
||||
try {
|
||||
if (numArgs > 1 && !strcmp(argv[1], "disasm")) { // -file binary.bin -patch workspace/igc/inc -dump dump/folder
|
||||
if (numArgs > 1 && !strcmp(argv[1], "disasm")) {
|
||||
BinaryDecoder disasm;
|
||||
int retVal = disasm.validateInput(numArgs, argv);
|
||||
if (retVal == 0) {
|
||||
@ -28,7 +28,7 @@ int main(int numArgs, const char *argv[]) {
|
||||
} else {
|
||||
return retVal;
|
||||
}
|
||||
} else if (numArgs > 1 && !strcmp(argv[1], "asm")) { // -dump dump/folder -out new_elf.bin
|
||||
} else if (numArgs > 1 && !strcmp(argv[1], "asm")) {
|
||||
BinaryEncoder assembler;
|
||||
int retVal = assembler.validateInput(numArgs, argv);
|
||||
if (retVal == 0) {
|
||||
|
@ -30,6 +30,7 @@ enum ErrorCode {
|
||||
};
|
||||
|
||||
std::string generateFilePath(const std::string &directory, const std::string &fileNameBase, const char *extension);
|
||||
std::string getDevicesTypes();
|
||||
|
||||
class OfflineCompiler {
|
||||
public:
|
||||
|
@ -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