blob: cf1c1f651f87088940ea26c7d825a3299d8827d1 [file] [log] [blame]
///////////////////////////////////////////////////////////////////////////////
/*
* Copyright (c) 2019, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
///////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <string>
#include <algorithm>
#include <sys/stat.h>
#include <bits/stdc++.h>
static const int32_t MAJ_VERSION = 1;
static const int32_t MIN_VERSION = 1;
static const char *HEADER_EXT = ".h";
static const char *SOURCE_EXT = ".c";
static const char *PARAM_I = "-i";
static const char *PARAM_O = "-o";
static const char *PARAM_V = "-v";
static const char *PARAM_INDEX = "-index";
static const char *PARAM_TOTAL = "-t";
#ifdef LINUX_
static const char *FILE_SEP = "/";
#else
static const char *FILE_SEP = "\\";
#endif
static const char *COPYRIGHT =
"/*\n"
" * Copyright (c) 2019, Intel Corporation\n"
" *\n"
" * Permission is hereby granted, free of charge, to any person obtaining a\n"
" * copy of this software and associated documentation files (the\n"
" * 'Software'), to deal in the Software without restriction, including\n"
" * without limitation the rights to use, copy, modify, merge, publish,\n"
" * distribute, sublicense, and/or sell copies of the Software, and to\n"
" * permit persons to whom the Software is furnished to do so, subject to\n"
" * the following conditions:\n"
" *\n"
" * The above copyright notice and this permission notice shall be included\n"
" * in all copies or substantial portions of the Software.\n"
" *\n"
" * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS\n"
" * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n"
" * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n"
" * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n"
" * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n"
" * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n"
" * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
"*/\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"// !!! WARNING - AUTO GENERATED FILE. DO NOT EDIT DIRECTLY. !!!\n"
"// Generated by KernelBinToSource.exe tool\n"
"////////////////////////////////////////////////////////////////////////////////\n"
;
//-----------------------------------------------------------------------------
// String EndsWith
//-----------------------------------------------------------------------------
bool strEndsWith(
const std::string &str,
const std::string &substr)
{
size_t i = str.rfind(substr);
return (i != std::string::npos) && (i == (str.length() - substr.length()));
}
//-----------------------------------------------------------------------------
// Append Path
//-----------------------------------------------------------------------------
std::string appendPath(
const std::string &sPath,
const std::string &sSubPath)
{
std::string strAppendPath = sPath;
if (!strEndsWith(sPath, FILE_SEP))
{
strAppendPath += FILE_SEP;
}
strAppendPath += sSubPath;
return strAppendPath;
}
//-----------------------------------------------------------------------------
// Get the filename from file path
//-----------------------------------------------------------------------------
std::string getFileName(const std::string &sFilePath)
{
#ifdef LINUX_
std::string::size_type uiLoc = sFilePath.rfind("/");
#else
std::string::size_type uiLoc = sFilePath.rfind("\\");
#endif
if (uiLoc != std::string::npos)
{
return sFilePath.substr(uiLoc+1, sFilePath.length());
}
return sFilePath;
}
//-----------------------------------------------------------------------------
// Writes the Header file
//-----------------------------------------------------------------------------
int32_t writeHeaderFile(
const uint32_t *pBuffer,
uint32_t uiSize,
const std::string &sFileName,
const std::string &sVarName)
{
int32_t iStatus = -1;
std::ofstream oOutStream;
std::stringstream oSs;
std::string sHeaderSentry;
std::string sSizeName;
oOutStream.open(sFileName.c_str(), std::ios::out | std::ios::trunc );
if (!oOutStream.is_open())
{
printf("Error: Unable to open file '%s' for writing\n", sFileName.c_str());
goto finish;
}
sHeaderSentry = "__" + sVarName + "_H__";
sSizeName = "extern const unsigned int " + sVarName + "_SIZE";
oSs << COPYRIGHT
<< "#ifndef " << sHeaderSentry << std::endl
<< "#define " << sHeaderSentry << std::endl << std::endl
<< sSizeName.c_str() << ";" << std::endl
<< "extern const unsigned int " << sVarName.c_str() << "[]" << ";"
<< std::endl << std::endl;
oSs << "#endif // " << sHeaderSentry << std::endl;
oOutStream << oSs.rdbuf();
printf("Header file '%s' generated successfully!\n", sFileName.c_str());
iStatus = 0;
finish:
if (oOutStream.is_open())
{
oOutStream.close();
}
return iStatus;
}
//-----------------------------------------------------------------------------
// Writes Partial Source file
//-----------------------------------------------------------------------------
int32_t writePartialSourceFile(
const uint32_t *pBuffer,
uint32_t uiSize,
const std::string &sFileName,
const std::string &sVarName,
const uint32_t &index,
const uint32_t &total)
{
int32_t iStatus = -1;
std::ofstream oOutStream;
std::stringstream oSs;
std::string sSizeName;
std::string sPlatformName;
const uint32_t uiHexLen = 11;
char sHex[uiHexLen];
uint32_t offset_size = 0;
uint32_t final_size = (uiSize + total) * sizeof(uint32_t);
uint32_t stub = 0;
oOutStream.open(sFileName.c_str(), std::ios::out | std::ios::trunc );
if (!oOutStream.is_open())
{
printf("Error: Unable to open file '%s' for writing\n", sFileName.c_str());
goto finish;
}
sSizeName = "extern const unsigned int " + sVarName + "_SIZE";
sPlatformName = sVarName;
sPlatformName.erase(0, sPlatformName.find_first_of('G',3) + 1);
oSs << COPYRIGHT << std::endl;
oSs << "#ifdef IGFX_GEN" << sPlatformName.c_str() << "_SUPPORTED" << std::endl;
oSs << sSizeName.c_str() << " = " << final_size << ";" << std::endl
<< "extern const unsigned int " << sVarName.c_str() << "[] ="
<< std::endl << "{";
for(stub = 0; stub < total; stub++)
{
if (stub % 8 == 0)
{
oSs << std::endl << " ";
}
if( stub == index + 1)
{
offset_size = uiSize * sizeof(uint32_t);
}
snprintf(sHex, uiHexLen, "0x%08x", offset_size);
sHex[uiHexLen - 1] = '\0';
if (stub % 8 == 7)
{
oSs << sHex << ",";
}else
{
oSs << sHex << ", ";
}
}
for (uint32_t i = 0; i < uiSize; i++)
{
if ((i + stub) % 8 == 0)
{
oSs << std::endl << " ";
}
snprintf(sHex, uiHexLen, "0x%08x", pBuffer[i]);
sHex[uiHexLen - 1] = '\0';
oSs << sHex;
if (i < (uiSize - 1))
{
if ((i + stub) % 8 == 7)
{
oSs << ",";
}
else
{
oSs << ", ";
}
}
}
oSs << std::endl << "};" << std::endl;
//Dummy kernel filled with 216 bytes
oSs << "#else" << std::endl
<< sSizeName.c_str() << " = 216;" << std::endl
<< "extern const unsigned int " << sVarName.c_str() << "[] = {" << std::endl
<< " 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000," << std::endl
<< "};" << std::endl
<< "#endif" << std::endl;
oOutStream << oSs.rdbuf();
printf("Source file '%s' generated successfully!\n", sFileName.c_str());
iStatus = 0;
finish:
if (oOutStream.is_open())
{
oOutStream.close();
}
return iStatus;
}
//-----------------------------------------------------------------------------
// Writes the Source file
//-----------------------------------------------------------------------------
int32_t writeSourceFile(
const uint32_t *pBuffer,
uint32_t uiSize,
const std::string &sFileName,
const std::string &sVarName)
{
int32_t iStatus = -1;
std::ofstream oOutStream;
std::stringstream oSs;
std::string sSizeName;
std::string sPlatformName;
const uint32_t uiHexLen = 11;
char sHex[uiHexLen];
oOutStream.open(sFileName.c_str(), std::ios::out | std::ios::trunc );
if (!oOutStream.is_open())
{
printf("Error: Unable to open file '%s' for writing\n", sFileName.c_str());
goto finish;
}
sSizeName = "extern const unsigned int " + sVarName + "_SIZE";
sPlatformName = sVarName;
sPlatformName.erase(0, sPlatformName.find_first_of('G',3) + 1);
oSs << COPYRIGHT << std::endl;
oSs << "#ifdef IGFX_GEN" << sPlatformName.c_str() << "_SUPPORTED" << std::endl;
oSs << sSizeName.c_str() << " = " << uiSize * sizeof(uint32_t) << ";" << std::endl
<< "extern const unsigned int " << sVarName.c_str() << "[] ="
<< std::endl << "{";
for (uint32_t i = 0; i < uiSize; i++)
{
if (i % 8 == 0)
{
oSs << std::endl << " ";
}
snprintf(sHex, uiHexLen, "0x%08x", pBuffer[i]);
sHex[uiHexLen - 1] = '\0';
oSs << sHex;
if (i < (uiSize - 1))
{
oSs << ", ";
}
}
oSs << std::endl << "};" << std::endl;
//Dummy kernel filled with 216 bytes
oSs << "#else" << std::endl
<< sSizeName.c_str() << " = 216;" << std::endl
<< "extern const unsigned int " << sVarName.c_str() << "[] = {" << std::endl
<< " 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000," << std::endl
<< "};" << std::endl
<< "#endif" << std::endl;
oOutStream << oSs.rdbuf();
printf("Source file '%s' generated successfully!\n", sFileName.c_str());
iStatus = 0;
finish:
if (oOutStream.is_open())
{
oOutStream.close();
}
return iStatus;
}
//-----------------------------------------------------------------------------
// Creates the Source file
//-----------------------------------------------------------------------------
int32_t createSourceFile(
const std::string &sInputFile,
const std::string &sOutputDir,
const std::string &sVar,
const uint32_t &index,
const uint32_t &total)
{
struct stat StatResult;
int32_t iStatus = -1;
std::ifstream oInStream;
std::string sInputFileName;
std::string sOutputFile;
std::string sVarName;
uint32_t *pBuffer = nullptr;
uint32_t uiSize = 0;
float fSize = (ceil)(0.0f);
uint32_t uiIntSize = 0;
// Check if input file exists
if (0 != stat(sInputFile.c_str(), &StatResult))
{
printf("Error: Unable to read file '%s'\n", sInputFile.c_str());
goto finish;
}
uiSize = StatResult.st_size;
if (sOutputDir.length() > 0)
{
// Check if out direction exists and validate it is a directory
if (0 != stat(sOutputDir.c_str(), &StatResult))
{
printf("Error: Unable to find directory '%s'\n", sOutputDir.c_str());
goto finish;
}
if (0 == (StatResult.st_mode & S_IFDIR))
{
printf("Error: Path '%s' is a valid directory\n", sOutputDir.c_str());
goto finish;
}
}
sInputFileName = getFileName(sInputFile);
{
// Set the Output path
std::string::size_type uiLoc = sInputFileName.find(".", 0 );
sOutputFile = (uiLoc != std::string::npos) ? sInputFileName.substr(0, uiLoc) : sInputFileName;
sVarName = (sVar.length() == 0) ? sOutputFile : sVar;
}
sOutputFile += SOURCE_EXT;
sOutputFile = appendPath(sOutputDir, sOutputFile);
// Read the File
oInStream.open(sInputFile.c_str(), std::ios::in | std::ios::binary);
if (! oInStream.is_open())
{
printf("Error: Unable to open file '%s' for reading\n", sInputFile.c_str());
goto finish;
}
// Read from the file
fSize = (ceil)(uiSize / 4.0f);
uiIntSize = static_cast<uint32_t>(fSize);
pBuffer = new uint32_t[uiIntSize];
pBuffer[uiIntSize - 1] = 0; // set the last entry as 0 for handling non uint32_t file sizes.
oInStream.read(reinterpret_cast<char*>(pBuffer), uiSize);
if (oInStream.bad())
{
printf("Error: Unable to read from file '%s'\n", sInputFile.c_str());
goto finish;
}
{
std::transform(sVarName.begin(), sVarName.end(), sVarName.begin(), ::toupper);
if(index == -1)
{
iStatus = writeSourceFile(pBuffer, uiIntSize, sOutputFile, sVarName);
}else{
iStatus = writePartialSourceFile(pBuffer, uiIntSize, sOutputFile, sVarName, index, total);
}
}
finish:
if (oInStream.is_open())
{
oInStream.close();
}
if (pBuffer)
{
delete [] pBuffer;
pBuffer = nullptr;
}
return iStatus;
}
//-----------------------------------------------------------------------------
// Creates the Header file
//-----------------------------------------------------------------------------
int32_t createHeaderFile(
const std::string &sInputFile,
const std::string &sOutputDir,
const std::string &sVar)
{
struct stat StatResult;
int32_t iStatus = -1;
std::ifstream oInStream;
std::string sInputFileName;
std::string sOutputFile;
std::string sVarName;
uint32_t *pBuffer = nullptr;
uint32_t uiSize = 0;
float fSize = (ceil)(0.0f);
uint32_t uiIntSize = 0;
// Check if input file exists
if (0 != stat(sInputFile.c_str(), &StatResult))
{
printf("Error: Unable to read file '%s'\n", sInputFile.c_str());
goto finish;
}
uiSize = StatResult.st_size;
if (sOutputDir.length() > 0)
{
// Check if out direction exists and validate it is a directory
if (0 != stat(sOutputDir.c_str(), &StatResult))
{
printf("Error: Unable to find directory '%s'\n", sOutputDir.c_str());
goto finish;
}
if (0 == (StatResult.st_mode & S_IFDIR))
{
printf("Error: Path '%s' is a valid directory\n", sOutputDir.c_str());
goto finish;
}
}
sInputFileName = getFileName(sInputFile);
{
// Set the Output path
std::string::size_type uiLoc = sInputFileName.find(".", 0 );
sOutputFile = (uiLoc != std::string::npos) ? sInputFileName.substr(0, uiLoc) : sInputFileName;
sVarName = (sVar.length() == 0) ? sOutputFile : sVar;
}
sOutputFile += HEADER_EXT;
sOutputFile = appendPath(sOutputDir, sOutputFile);
// Read the File
oInStream.open(sInputFile.c_str(), std::ios::in | std::ios::binary);
if (! oInStream.is_open())
{
printf("Error: Unable to open file '%s' for reading\n", sInputFile.c_str());
goto finish;
}
// Read from the file
fSize = (ceil)(uiSize / 4.0f);
uiIntSize = static_cast<uint32_t>(fSize);
pBuffer = new uint32_t[uiIntSize];
pBuffer[uiIntSize - 1] = 0; // set the last entry as 0 for handling non uint32_t file sizes.
oInStream.read(reinterpret_cast<char*>(pBuffer), uiSize);
if (oInStream.bad())
{
printf("Error: Unable to read from file '%s'\n", sInputFile.c_str());
goto finish;
}
std::transform(sVarName.begin(), sVarName.end(), sVarName.begin(), ::toupper);
iStatus = writeHeaderFile(pBuffer, uiIntSize, sOutputFile, sVarName);
finish:
if (oInStream.is_open())
{
oInStream.close();
}
if (pBuffer)
{
delete [] pBuffer;
pBuffer = nullptr;
}
return iStatus;
}
//-----------------------------------------------------------------------------
// Prints Usage
//-----------------------------------------------------------------------------
void printUsage(const std::string &sProgram)
{
std::cout << "Usage: "
<< sProgram.c_str()
<< " (" << PARAM_I << " InPath)"
<< " [" << PARAM_O << " OutPath]"
<< " [" << PARAM_V << " VarName]"
<< " [" << PARAM_INDEX << " Kernel Index]"
<< " [" << PARAM_TOTAL << " Kernel Total]"
<< std::endl
<< " " << PARAM_I << " Path to Kernel binary input file (required)" << std::endl
<< " " << PARAM_O << " Path to Kernel binary output directory (optional)" << std::endl
<< " " << PARAM_V << " Variable Name on the generated source file (optional)" << std::endl
<< " " << PARAM_INDEX << " Variable kernel Index (optional)" << std::endl
<< " " << PARAM_TOTAL << " Variable kernel total count (optional)" << std::endl;
}
//-----------------------------------------------------------------------------
// Parses input
//-----------------------------------------------------------------------------
int32_t parseInput(
int32_t argc,
char *argv[],
const std::string &sProgram,
std::string &sInput,
std::string &sOutput,
std::string &sVarName,
uint32_t &index,
uint32_t &total)
{
int32_t iStatus = -1;
// Must have even number of arguments (excluding argv[0])
if (argc % 2 == 0)
{
goto finish;
}
for (int i = 1; i < argc; i += 2)
{
if (0 == strcmp(PARAM_I, argv[i]))
{
sInput = argv[i+1];
}
else if (0 == strcmp(PARAM_O, argv[i]))
{
sOutput = argv[i+1];
}
else if (0 == strcmp(PARAM_V, argv[i]))
{
sVarName = argv[i+1];
}
else if (0 == strcmp(PARAM_INDEX, argv[i]))
{
index = atoi(argv[i+1]);
}
else if (0 == strcmp(PARAM_TOTAL, argv[i]))
{
total = atoi(argv[i+1]) + 1;
}
else
{
std::cout << "Error: Invalid option " << argv[i] << std::endl;
goto finish;
}
}
if (sInput.length() == 0)
{
goto finish;
}
iStatus = 0;
finish:
if (iStatus != 0)
{
printUsage(sProgram);
}
return iStatus;
}
//-----------------------------------------------------------------------------
// Prints time
//-----------------------------------------------------------------------------
void printTime(int64_t lFreq, int64_t lTime)
{
double dsec = ((double)lTime) / ((double)lFreq);
double dms = dsec * 1000;
std::cout << "Time Took " << std::setw(2) << dsec << "s "
<< "(" << dms << "ms)"
<< std::endl;
}
//-----------------------------------------------------------------------------
// Main Function
//-----------------------------------------------------------------------------
int32_t main(int argc, char *argv[])
{
std::string sProgram = getFileName(argv[0]);
std::cout << std::endl
<< sProgram.c_str() << " v" << MAJ_VERSION << "." << MIN_VERSION << std::endl
<< "(c) Intel Corporation 2019. All rights reserved." << std::endl << std::endl;
int32_t iStatus = -1;
std::string sInputPath;
std::string sOutputDir;
std::string sVarName;
uint32_t index=-1;
uint32_t total=-1;
iStatus = parseInput(argc, argv, sProgram, sInputPath, sOutputDir, sVarName, index, total);
if (iStatus != 0)
{
goto finish;
}
iStatus = createHeaderFile(sInputPath, sOutputDir, sVarName);
iStatus = createSourceFile(sInputPath, sOutputDir, sVarName, index, total);
finish:
return iStatus;
}