feat(ocloc concat): allow device binary

Allow for use of device binary in ocloc concat. Previously only
AR files could be concatenated.
This feature only works for zebin with AOT Product Config note.

Signed-off-by: Krystian Chmielewski <krystian.chmielewski@intel.com>
This commit is contained in:
Krystian Chmielewski
2023-01-31 12:18:49 +00:00
committed by Compute-Runtime-Automation
parent d1b2311207
commit 7982e26ae7
8 changed files with 253 additions and 80 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022 Intel Corporation
* Copyright (C) 2022-2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -11,6 +11,7 @@
#include "shared/offline_compiler/source/ocloc_error_code.h"
#include "shared/source/device_binary_format/ar/ar_decoder.h"
#include "shared/source/device_binary_format/ar/ar_encoder.h"
#include "shared/source/device_binary_format/zebin_decoder.h"
namespace NEO {
OclocConcat::ErrorCode OclocConcat::initialize(const std::vector<std::string> &args) {
@@ -22,8 +23,8 @@ OclocConcat::ErrorCode OclocConcat::initialize(const std::vector<std::string> &a
return error;
}
Ar::Ar OclocConcat::decodeAr(const std::vector<char> &arFile, std::string &outErrors, std::string &outWarnings) {
return NEO::Ar::decodeAr({reinterpret_cast<const uint8_t *>(arFile.data()), arFile.size()}, outErrors, outWarnings);
Ar::Ar OclocConcat::decodeAr(ArrayRef<const uint8_t> arFile, std::string &outErrors, std::string &outWarnings) {
return NEO::Ar::decodeAr(arFile, outErrors, outWarnings);
}
OclocConcat::ErrorCode OclocConcat::parseArguments(const std::vector<std::string> &args) {
@@ -59,26 +60,76 @@ OclocConcat::ErrorCode OclocConcat::checkIfFatBinariesExist() {
return filesExist ? OclocErrorCode::SUCCESS : OclocErrorCode::INVALID_COMMAND_LINE;
}
void OclocConcat::printMsg(ConstStringRef fileName, const std::string &message) {
if (false == message.empty()) {
argHelper->printf(fileName.data());
argHelper->printf(" : ");
argHelper->printf(message.c_str());
}
}
AOT::PRODUCT_CONFIG OclocConcat::getAOTProductConfigFromBinary(ArrayRef<const uint8_t> binary, std::string &outErrors) {
std::vector<Elf::IntelGTNote> intelGTNotes;
if (NEO::isZebin<Elf::EI_CLASS_64>(binary)) {
std::string warnings;
auto elf = Elf::decodeElf(binary, outErrors, warnings);
getIntelGTNotes<Elf::EI_CLASS_64>(elf, intelGTNotes, outErrors, warnings);
} else if (NEO::isZebin<Elf::EI_CLASS_32>(binary)) {
std::string warnings;
auto elf = Elf::decodeElf<Elf::EI_CLASS_32>(binary, outErrors, warnings);
getIntelGTNotes<Elf::EI_CLASS_32>(elf, intelGTNotes, outErrors, warnings);
} else {
outErrors.append("Not a zebin file\n");
return {};
}
AOT::PRODUCT_CONFIG productConfig{};
bool productConfigFound = false;
for (auto &note : intelGTNotes) {
if (note.type == Elf::ProductConfig) {
productConfig = *reinterpret_cast<const AOT::PRODUCT_CONFIG *>(note.data.begin());
productConfigFound = true;
break;
}
}
if (false == productConfigFound) {
outErrors.append("Couldn't find AOT product configuration in intelGTNotes section.\n");
}
return productConfig;
}
OclocConcat::ErrorCode OclocConcat::concatenate() {
NEO::Ar::ArEncoder arEncoder(true);
for (auto &fileName : fileNamesToConcat) {
auto arFile = argHelper->readBinaryFile(fileName);
auto file = argHelper->readBinaryFile(fileName);
auto fileRef = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(file.data()), file.size());
std::string warnings;
std::string errors;
auto ar = decodeAr(arFile, errors, warnings);
if (false == errors.empty()) {
argHelper->printf(errors.c_str());
return OclocErrorCode::INVALID_FILE;
}
argHelper->printf(warnings.c_str());
if (NEO::Ar::isAr(fileRef)) {
std::string warnings;
std::string errors;
auto ar = decodeAr(fileRef, errors, warnings);
for (auto &fileEntry : ar.files) {
if (NEO::ConstStringRef(fileEntry.fileName).startsWith("pad_")) {
continue;
if (false == errors.empty()) {
printMsg(fileName, errors);
return OclocErrorCode::INVALID_FILE;
}
printMsg(fileName, warnings);
arEncoder.appendFileEntry(fileEntry.fileName, fileEntry.fileData);
for (auto &fileEntry : ar.files) {
if (NEO::ConstStringRef(fileEntry.fileName).startsWith("pad_")) {
continue;
}
arEncoder.appendFileEntry(fileEntry.fileName, fileEntry.fileData);
}
} else {
std::string errors;
auto productConfig = getAOTProductConfigFromBinary(fileRef, errors);
if (false == errors.empty()) {
printMsg(fileName, errors);
return OclocErrorCode::INVALID_FILE;
}
auto entryName = ProductConfigHelper::parseMajorMinorRevisionValue(productConfig);
arEncoder.appendFileEntry(entryName, fileRef);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022 Intel Corporation
* Copyright (C) 2022-2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -7,11 +7,15 @@
#pragma once
#include "shared/source/utilities/arrayref.h"
#include "shared/source/utilities/const_stringref.h"
#include <string>
#include <vector>
namespace AOT {
enum PRODUCT_CONFIG : uint32_t;
}
class OclocArgHelper;
namespace NEO {
namespace Ar {
@@ -38,9 +42,11 @@ Usage: ocloc concat <fat binary> <fat binary> ... [-out <concatenated fat binary
)===";
protected:
MOCKABLE_VIRTUAL Ar::Ar decodeAr(const std::vector<char> &arFile, std::string &outErrors, std::string &outWarnings);
ErrorCode parseArguments(const std::vector<std::string> &args);
ErrorCode checkIfFatBinariesExist();
MOCKABLE_VIRTUAL Ar::Ar decodeAr(ArrayRef<const uint8_t> arFile, std::string &outErrors, std::string &outWarnings);
AOT::PRODUCT_CONFIG getAOTProductConfigFromBinary(ArrayRef<const uint8_t> binary, std::string &outErrors);
ErrorCode parseArguments(const std::vector<std::string> &args);
void printMsg(ConstStringRef fileName, const std::string &message);
OclocArgHelper *argHelper;
std::vector<std::string> fileNamesToConcat;