1 /*
2  * Copyright (C) 2020-2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  */
7 
8 #include <fstream>
9 #include <iomanip>
10 #include <iostream>
11 #include <sstream>
12 
13 constexpr int MIN_ARG_COUNT = 7;
14 
show_usage(std::string name)15 static void show_usage(std::string name) {
16     std::cerr << "Usage " << name << "<option(s)> - ALL BUT -p, --platform MUST BE SPECIFIED\n"
17               << "Options :\n"
18               << "\t -f, --file\t\tA file which content will be parsed into a uint32_t array in a .cpp file\n"
19               << "\t -o, --out\t\t.Cpp output file name\n"
20               << "\t -p, --platform\t\tOPTIONAL - Family name with type\n"
21               << "\t -a, --array\t\tName of an uin32_t type array containing parsed input file" << std::endl;
22 }
parseToCharArray(std::unique_ptr<uint8_t[]> & binary,size_t size,std::string & builtinName,std::string & platform,std::string revisionId,bool isSpirV)23 std::string parseToCharArray(std::unique_ptr<uint8_t[]> &binary, size_t size, std::string &builtinName, std::string &platform, std::string revisionId, bool isSpirV) {
24     std::ostringstream out;
25 
26     out << "#include <cstddef>\n";
27     out << "#include <cstdint>\n\n";
28     out << "size_t " << builtinName << "BinarySize_" << platform << "_" << revisionId << " = " << size << ";\n";
29     out << "uint32_t " << builtinName << "Binary_" << platform << "_" << revisionId << "[" << (size + 3) / 4 << "] = {"
30         << std::endl
31         << "    ";
32     uint32_t *binaryUint = reinterpret_cast<uint32_t *>(binary.get());
33     for (size_t i = 0; i < (size + 3) / 4; i++) {
34         if (i != 0) {
35             out << ", ";
36             if (i % 8 == 0) {
37                 out << std::endl
38                     << "    ";
39             }
40         }
41         if (i < size / 4) {
42             out << "0x" << std::hex << std::setw(8) << std::setfill('0') << binaryUint[i];
43         } else {
44             uint32_t lastBytes = size & 0x3;
45             uint32_t lastUint = 0;
46             uint8_t *pLastUint = (uint8_t *)&lastUint;
47             for (uint32_t j = 0; j < lastBytes; j++) {
48                 pLastUint[sizeof(uint32_t) - 1 - j] = binary.get()[i * 4 + j];
49             }
50             out << "0x" << std::hex << std::setw(8) << std::setfill('0') << lastUint;
51         }
52     }
53     out << "};" << std::endl;
54 
55     out << std::endl
56         << "#include \"shared/source/built_ins/registry/built_ins_registry.h\"\n"
57         << std::endl;
58     out << "namespace NEO {" << std::endl;
59     out << "static RegisterEmbeddedResource register" << builtinName;
60     isSpirV ? out << "Ir(" : out << "Bin(";
61     out << std::endl;
62     out << "    \"";
63     platform != "" ? out << platform << "_" << revisionId << "_" << builtinName : out << builtinName;
64     isSpirV ? out << ".builtin_kernel.bc\"," : out << ".builtin_kernel.bin\",";
65     out << std::endl;
66     out << "    (const char *)" << builtinName << "Binary_" << platform << "_" << revisionId << "," << std::endl;
67     out << "    " << builtinName << "BinarySize_" << platform << "_" << revisionId << ");" << std::endl;
68     out << "}" << std::endl;
69 
70     return out.str();
71 }
72 
main(int argc,char * argv[])73 int main(int argc, char *argv[]) {
74     if (argc < MIN_ARG_COUNT) {
75         show_usage(argv[0]);
76         return 1;
77     }
78     std::string fileName;
79     std::string cppOutputName;
80     std::string arrayName;
81     std::string platform = "";
82     std::string revisionId = "0";
83     size_t size = 0;
84     std::fstream inputFile;
85     bool isSpirV;
86     for (int i = 1; i < argc; i++) {
87         std::string arg = argv[i];
88         if ((arg == "-f") || (arg == "--file")) {
89             fileName = argv[++i];
90         } else if ((arg == "-o") || (arg == "--output")) {
91             cppOutputName = argv[++i];
92         } else if ((arg == "-a") || (arg == "--array")) {
93             arrayName = argv[++i];
94         } else if ((arg == "-p") || (arg == "--platform")) {
95             platform = argv[++i];
96         } else if ((arg == "-r") || (arg == "--revision_id")) {
97             revisionId = argv[++i];
98         } else {
99             return 1;
100         }
101     }
102     if (fileName.empty() || cppOutputName.empty() || arrayName.empty()) {
103         std::cerr << "All three: fileName, cppOutputName and arrayName must be specified!" << std::endl;
104         return 1;
105     }
106     inputFile.open(fileName.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
107 
108     if (inputFile.is_open()) {
109         size = static_cast<size_t>(inputFile.tellg());
110         std::unique_ptr<uint8_t[]> memblock = std::make_unique<uint8_t[]>(size);
111         inputFile.clear();
112         inputFile.seekg(0, std::ios::beg);
113         inputFile.read(reinterpret_cast<char *>(memblock.get()), size);
114         inputFile.close();
115         isSpirV = fileName.find(".spv") != std::string::npos;
116         std::string cpp = parseToCharArray(memblock, size, arrayName, platform, revisionId, isSpirV);
117         std::fstream(cppOutputName.c_str(), std::ios::out | std::ios::binary).write(cpp.c_str(), cpp.size());
118     } else {
119         std::cerr << "File cannot be opened!" << std::endl;
120         return 1;
121     }
122     return 0;
123 }
124