1*89c4ff92SAndroid Build Coastguard Worker //
2*89c4ff92SAndroid Build Coastguard Worker // Copyright © 2017 Arm Ltd. All rights reserved.
3*89c4ff92SAndroid Build Coastguard Worker // SPDX-License-Identifier: MIT
4*89c4ff92SAndroid Build Coastguard Worker //
5*89c4ff92SAndroid Build Coastguard Worker
6*89c4ff92SAndroid Build Coastguard Worker #include <armnnUtils/Filesystem.hpp>
7*89c4ff92SAndroid Build Coastguard Worker #include <cxxopts/cxxopts.hpp>
8*89c4ff92SAndroid Build Coastguard Worker
9*89c4ff92SAndroid Build Coastguard Worker #include <algorithm>
10*89c4ff92SAndroid Build Coastguard Worker #include <fstream>
11*89c4ff92SAndroid Build Coastguard Worker #include <iostream>
12*89c4ff92SAndroid Build Coastguard Worker #include <string>
13*89c4ff92SAndroid Build Coastguard Worker
14*89c4ff92SAndroid Build Coastguard Worker namespace
15*89c4ff92SAndroid Build Coastguard Worker {
16*89c4ff92SAndroid Build Coastguard Worker
17*89c4ff92SAndroid Build Coastguard Worker // parses the command line to extract
18*89c4ff92SAndroid Build Coastguard Worker // * the directory -i to look through .raw files from (must exist)
19*89c4ff92SAndroid Build Coastguard Worker // * the name of the file -o the output CSV file path (must not already exist)
20*89c4ff92SAndroid Build Coastguard Worker class CommandLineProcessor
21*89c4ff92SAndroid Build Coastguard Worker {
22*89c4ff92SAndroid Build Coastguard Worker public:
ParseOptions(cxxopts::ParseResult & result)23*89c4ff92SAndroid Build Coastguard Worker bool ParseOptions(cxxopts::ParseResult& result)
24*89c4ff92SAndroid Build Coastguard Worker {
25*89c4ff92SAndroid Build Coastguard Worker // indir is mandatory, dir could possibly be changed.
26*89c4ff92SAndroid Build Coastguard Worker if (result.count("indir"))
27*89c4ff92SAndroid Build Coastguard Worker {
28*89c4ff92SAndroid Build Coastguard Worker std::string dir = result["indir"].as<std::string>();
29*89c4ff92SAndroid Build Coastguard Worker
30*89c4ff92SAndroid Build Coastguard Worker if (!ValidateDirectory(dir))
31*89c4ff92SAndroid Build Coastguard Worker {
32*89c4ff92SAndroid Build Coastguard Worker return false;
33*89c4ff92SAndroid Build Coastguard Worker }
34*89c4ff92SAndroid Build Coastguard Worker
35*89c4ff92SAndroid Build Coastguard Worker m_InputDirectory = dir;
36*89c4ff92SAndroid Build Coastguard Worker }
37*89c4ff92SAndroid Build Coastguard Worker else
38*89c4ff92SAndroid Build Coastguard Worker {
39*89c4ff92SAndroid Build Coastguard Worker std::cerr << "-i/--indir parameter is mandatory." << std::endl;
40*89c4ff92SAndroid Build Coastguard Worker return false;
41*89c4ff92SAndroid Build Coastguard Worker }
42*89c4ff92SAndroid Build Coastguard Worker
43*89c4ff92SAndroid Build Coastguard Worker // outfile is mandatory
44*89c4ff92SAndroid Build Coastguard Worker if (result.count("outfile"))
45*89c4ff92SAndroid Build Coastguard Worker {
46*89c4ff92SAndroid Build Coastguard Worker if (!ValidateOutputFile(result["outfile"].as<std::string>()))
47*89c4ff92SAndroid Build Coastguard Worker {
48*89c4ff92SAndroid Build Coastguard Worker return false;
49*89c4ff92SAndroid Build Coastguard Worker }
50*89c4ff92SAndroid Build Coastguard Worker }
51*89c4ff92SAndroid Build Coastguard Worker else
52*89c4ff92SAndroid Build Coastguard Worker {
53*89c4ff92SAndroid Build Coastguard Worker std::cerr << "-o/--outfile parameter is mandatory." << std::endl;
54*89c4ff92SAndroid Build Coastguard Worker return false;
55*89c4ff92SAndroid Build Coastguard Worker }
56*89c4ff92SAndroid Build Coastguard Worker
57*89c4ff92SAndroid Build Coastguard Worker if (result.count("layer-binding-id"))
58*89c4ff92SAndroid Build Coastguard Worker {
59*89c4ff92SAndroid Build Coastguard Worker if(!ValidateBindingId(result["layer-binding-id"].as<std::string>()))
60*89c4ff92SAndroid Build Coastguard Worker {
61*89c4ff92SAndroid Build Coastguard Worker return false;
62*89c4ff92SAndroid Build Coastguard Worker }
63*89c4ff92SAndroid Build Coastguard Worker }
64*89c4ff92SAndroid Build Coastguard Worker return true;
65*89c4ff92SAndroid Build Coastguard Worker }
66*89c4ff92SAndroid Build Coastguard Worker
ValidateDirectory(std::string & dir)67*89c4ff92SAndroid Build Coastguard Worker bool ValidateDirectory(std::string& dir)
68*89c4ff92SAndroid Build Coastguard Worker {
69*89c4ff92SAndroid Build Coastguard Worker if (dir.empty())
70*89c4ff92SAndroid Build Coastguard Worker {
71*89c4ff92SAndroid Build Coastguard Worker std::cerr << "No directory specified" << std::endl;
72*89c4ff92SAndroid Build Coastguard Worker return false;
73*89c4ff92SAndroid Build Coastguard Worker }
74*89c4ff92SAndroid Build Coastguard Worker
75*89c4ff92SAndroid Build Coastguard Worker if (dir[dir.length() - 1] != '/')
76*89c4ff92SAndroid Build Coastguard Worker {
77*89c4ff92SAndroid Build Coastguard Worker dir += "/";
78*89c4ff92SAndroid Build Coastguard Worker }
79*89c4ff92SAndroid Build Coastguard Worker
80*89c4ff92SAndroid Build Coastguard Worker if (!fs::exists(dir))
81*89c4ff92SAndroid Build Coastguard Worker {
82*89c4ff92SAndroid Build Coastguard Worker std::cerr << "Directory [" << dir << "] does not exist" << std::endl;
83*89c4ff92SAndroid Build Coastguard Worker return false;
84*89c4ff92SAndroid Build Coastguard Worker }
85*89c4ff92SAndroid Build Coastguard Worker
86*89c4ff92SAndroid Build Coastguard Worker if (!fs::is_directory(dir))
87*89c4ff92SAndroid Build Coastguard Worker {
88*89c4ff92SAndroid Build Coastguard Worker std::cerr << "Given directory [" << dir << "] is not a directory" << std::endl;
89*89c4ff92SAndroid Build Coastguard Worker return false;
90*89c4ff92SAndroid Build Coastguard Worker }
91*89c4ff92SAndroid Build Coastguard Worker
92*89c4ff92SAndroid Build Coastguard Worker return true;
93*89c4ff92SAndroid Build Coastguard Worker }
94*89c4ff92SAndroid Build Coastguard Worker
ValidateOutputFile(const std::string & outputFileName)95*89c4ff92SAndroid Build Coastguard Worker bool ValidateOutputFile(const std::string& outputFileName)
96*89c4ff92SAndroid Build Coastguard Worker {
97*89c4ff92SAndroid Build Coastguard Worker if (outputFileName.empty())
98*89c4ff92SAndroid Build Coastguard Worker {
99*89c4ff92SAndroid Build Coastguard Worker std::cerr << "No output file name specified" << std::endl;
100*89c4ff92SAndroid Build Coastguard Worker return false;
101*89c4ff92SAndroid Build Coastguard Worker }
102*89c4ff92SAndroid Build Coastguard Worker
103*89c4ff92SAndroid Build Coastguard Worker if (fs::exists(outputFileName))
104*89c4ff92SAndroid Build Coastguard Worker {
105*89c4ff92SAndroid Build Coastguard Worker std::cerr << "Output file [" << outputFileName << "] already exists" << std::endl;
106*89c4ff92SAndroid Build Coastguard Worker return false;
107*89c4ff92SAndroid Build Coastguard Worker }
108*89c4ff92SAndroid Build Coastguard Worker
109*89c4ff92SAndroid Build Coastguard Worker if (fs::is_directory(outputFileName))
110*89c4ff92SAndroid Build Coastguard Worker {
111*89c4ff92SAndroid Build Coastguard Worker std::cerr << "Output file [" << outputFileName << "] is a directory" << std::endl;
112*89c4ff92SAndroid Build Coastguard Worker return false;
113*89c4ff92SAndroid Build Coastguard Worker }
114*89c4ff92SAndroid Build Coastguard Worker
115*89c4ff92SAndroid Build Coastguard Worker fs::path outputPath(outputFileName);
116*89c4ff92SAndroid Build Coastguard Worker if (!fs::exists(outputPath.parent_path()))
117*89c4ff92SAndroid Build Coastguard Worker {
118*89c4ff92SAndroid Build Coastguard Worker std::cerr << "Directory [" << outputPath.parent_path().c_str() << "] does not exist" << std::endl;
119*89c4ff92SAndroid Build Coastguard Worker return false;
120*89c4ff92SAndroid Build Coastguard Worker }
121*89c4ff92SAndroid Build Coastguard Worker
122*89c4ff92SAndroid Build Coastguard Worker return true;
123*89c4ff92SAndroid Build Coastguard Worker }
124*89c4ff92SAndroid Build Coastguard Worker
ValidateBindingId(const std::string & id)125*89c4ff92SAndroid Build Coastguard Worker bool ValidateBindingId(const std::string& id)
126*89c4ff92SAndroid Build Coastguard Worker {
127*89c4ff92SAndroid Build Coastguard Worker if (!std::all_of(id.begin(), id.end(), ::isdigit))
128*89c4ff92SAndroid Build Coastguard Worker {
129*89c4ff92SAndroid Build Coastguard Worker std::cerr << "Invalid input binding Id" << std::endl;
130*89c4ff92SAndroid Build Coastguard Worker return false;
131*89c4ff92SAndroid Build Coastguard Worker }
132*89c4ff92SAndroid Build Coastguard Worker
133*89c4ff92SAndroid Build Coastguard Worker return true;
134*89c4ff92SAndroid Build Coastguard Worker }
135*89c4ff92SAndroid Build Coastguard Worker
ProcessCommandLine(int argc,char * argv[])136*89c4ff92SAndroid Build Coastguard Worker bool ProcessCommandLine(int argc, char* argv[])
137*89c4ff92SAndroid Build Coastguard Worker {
138*89c4ff92SAndroid Build Coastguard Worker try
139*89c4ff92SAndroid Build Coastguard Worker {
140*89c4ff92SAndroid Build Coastguard Worker cxxopts::Options options("ImageCSVFileGenerator",
141*89c4ff92SAndroid Build Coastguard Worker "Program for creating a CSV file that "
142*89c4ff92SAndroid Build Coastguard Worker "contains a list of .raw tensor files. "
143*89c4ff92SAndroid Build Coastguard Worker "These .raw tensor files can be generated using the ImageTensorGenerator");
144*89c4ff92SAndroid Build Coastguard Worker
145*89c4ff92SAndroid Build Coastguard Worker options.add_options()
146*89c4ff92SAndroid Build Coastguard Worker ("h,help", "Display help messages")
147*89c4ff92SAndroid Build Coastguard Worker ("i,indir",
148*89c4ff92SAndroid Build Coastguard Worker "Directory that .raw files are stored in",
149*89c4ff92SAndroid Build Coastguard Worker cxxopts::value<std::string>(m_InputDirectory))
150*89c4ff92SAndroid Build Coastguard Worker ("o,outfile",
151*89c4ff92SAndroid Build Coastguard Worker "Output CSV file path",
152*89c4ff92SAndroid Build Coastguard Worker cxxopts::value<std::string>(m_OutputFileName))
153*89c4ff92SAndroid Build Coastguard Worker ("l, layer-binding-id",
154*89c4ff92SAndroid Build Coastguard Worker "Input layer binding Id, Defaults to 0",
155*89c4ff92SAndroid Build Coastguard Worker cxxopts::value<std::string>(m_InputBindingId)->default_value("0"));
156*89c4ff92SAndroid Build Coastguard Worker
157*89c4ff92SAndroid Build Coastguard Worker auto result = options.parse(argc, argv);
158*89c4ff92SAndroid Build Coastguard Worker
159*89c4ff92SAndroid Build Coastguard Worker if (result.count("help"))
160*89c4ff92SAndroid Build Coastguard Worker {
161*89c4ff92SAndroid Build Coastguard Worker std::cout << options.help() << std::endl;
162*89c4ff92SAndroid Build Coastguard Worker return false;
163*89c4ff92SAndroid Build Coastguard Worker }
164*89c4ff92SAndroid Build Coastguard Worker
165*89c4ff92SAndroid Build Coastguard Worker // Check for mandatory parameters and validate inputs
166*89c4ff92SAndroid Build Coastguard Worker if(!ParseOptions(result)){
167*89c4ff92SAndroid Build Coastguard Worker return false;
168*89c4ff92SAndroid Build Coastguard Worker }
169*89c4ff92SAndroid Build Coastguard Worker }
170*89c4ff92SAndroid Build Coastguard Worker catch (const cxxopts::OptionException& e)
171*89c4ff92SAndroid Build Coastguard Worker {
172*89c4ff92SAndroid Build Coastguard Worker std::cerr << e.what() << std::endl << std::endl;
173*89c4ff92SAndroid Build Coastguard Worker return false;
174*89c4ff92SAndroid Build Coastguard Worker }
175*89c4ff92SAndroid Build Coastguard Worker catch (const std::exception& e)
176*89c4ff92SAndroid Build Coastguard Worker {
177*89c4ff92SAndroid Build Coastguard Worker std::cerr << "Fatal internal error: [" << e.what() << "]" << std::endl;
178*89c4ff92SAndroid Build Coastguard Worker return false;
179*89c4ff92SAndroid Build Coastguard Worker }
180*89c4ff92SAndroid Build Coastguard Worker
181*89c4ff92SAndroid Build Coastguard Worker return true;
182*89c4ff92SAndroid Build Coastguard Worker }
183*89c4ff92SAndroid Build Coastguard Worker
GetInputDirectory()184*89c4ff92SAndroid Build Coastguard Worker std::string GetInputDirectory() {return m_InputDirectory;}
GetOutputFileName()185*89c4ff92SAndroid Build Coastguard Worker std::string GetOutputFileName() {return m_OutputFileName;}
GetInputBindingId()186*89c4ff92SAndroid Build Coastguard Worker std::string GetInputBindingId() {return m_InputBindingId;}
187*89c4ff92SAndroid Build Coastguard Worker
188*89c4ff92SAndroid Build Coastguard Worker private:
189*89c4ff92SAndroid Build Coastguard Worker std::string m_InputDirectory;
190*89c4ff92SAndroid Build Coastguard Worker std::string m_OutputFileName;
191*89c4ff92SAndroid Build Coastguard Worker std::string m_InputBindingId;
192*89c4ff92SAndroid Build Coastguard Worker };
193*89c4ff92SAndroid Build Coastguard Worker
194*89c4ff92SAndroid Build Coastguard Worker } // namespace anonymous
195*89c4ff92SAndroid Build Coastguard Worker
main(int argc,char * argv[])196*89c4ff92SAndroid Build Coastguard Worker int main(int argc, char* argv[])
197*89c4ff92SAndroid Build Coastguard Worker {
198*89c4ff92SAndroid Build Coastguard Worker CommandLineProcessor cmdline;
199*89c4ff92SAndroid Build Coastguard Worker if (!cmdline.ProcessCommandLine(argc, argv))
200*89c4ff92SAndroid Build Coastguard Worker {
201*89c4ff92SAndroid Build Coastguard Worker return -1;
202*89c4ff92SAndroid Build Coastguard Worker }
203*89c4ff92SAndroid Build Coastguard Worker
204*89c4ff92SAndroid Build Coastguard Worker const std::string fileFormat(".raw");
205*89c4ff92SAndroid Build Coastguard Worker
206*89c4ff92SAndroid Build Coastguard Worker const std::string rawDirectory(cmdline.GetInputDirectory());
207*89c4ff92SAndroid Build Coastguard Worker const std::string outputPath(cmdline.GetOutputFileName());
208*89c4ff92SAndroid Build Coastguard Worker const std::string bindingId(cmdline.GetInputBindingId());
209*89c4ff92SAndroid Build Coastguard Worker
210*89c4ff92SAndroid Build Coastguard Worker std::vector<fs::path> rawFiles;
211*89c4ff92SAndroid Build Coastguard Worker for (auto& entry : fs::directory_iterator(rawDirectory))
212*89c4ff92SAndroid Build Coastguard Worker {
213*89c4ff92SAndroid Build Coastguard Worker if (entry.path().extension().c_str() == fileFormat)
214*89c4ff92SAndroid Build Coastguard Worker {
215*89c4ff92SAndroid Build Coastguard Worker rawFiles.push_back(entry.path());
216*89c4ff92SAndroid Build Coastguard Worker }
217*89c4ff92SAndroid Build Coastguard Worker }
218*89c4ff92SAndroid Build Coastguard Worker
219*89c4ff92SAndroid Build Coastguard Worker if (!rawFiles.empty())
220*89c4ff92SAndroid Build Coastguard Worker {
221*89c4ff92SAndroid Build Coastguard Worker unsigned int pass = 0;
222*89c4ff92SAndroid Build Coastguard Worker std::ofstream refinementData;
223*89c4ff92SAndroid Build Coastguard Worker refinementData.open(outputPath, std::ofstream::out);
224*89c4ff92SAndroid Build Coastguard Worker if (refinementData.is_open())
225*89c4ff92SAndroid Build Coastguard Worker {
226*89c4ff92SAndroid Build Coastguard Worker for (auto const& raw : rawFiles)
227*89c4ff92SAndroid Build Coastguard Worker {
228*89c4ff92SAndroid Build Coastguard Worker refinementData << pass << ", " << bindingId << ", " << raw.c_str() << "\n";
229*89c4ff92SAndroid Build Coastguard Worker if (!refinementData)
230*89c4ff92SAndroid Build Coastguard Worker {
231*89c4ff92SAndroid Build Coastguard Worker std::cerr << "Failed to write to output file: " << outputPath << std::endl;
232*89c4ff92SAndroid Build Coastguard Worker continue;
233*89c4ff92SAndroid Build Coastguard Worker }
234*89c4ff92SAndroid Build Coastguard Worker ++pass;
235*89c4ff92SAndroid Build Coastguard Worker }
236*89c4ff92SAndroid Build Coastguard Worker refinementData.close();
237*89c4ff92SAndroid Build Coastguard Worker }
238*89c4ff92SAndroid Build Coastguard Worker else
239*89c4ff92SAndroid Build Coastguard Worker {
240*89c4ff92SAndroid Build Coastguard Worker std::cerr << "Failed to open output file: " << outputPath << std::endl;
241*89c4ff92SAndroid Build Coastguard Worker return -1;
242*89c4ff92SAndroid Build Coastguard Worker }
243*89c4ff92SAndroid Build Coastguard Worker }
244*89c4ff92SAndroid Build Coastguard Worker else
245*89c4ff92SAndroid Build Coastguard Worker {
246*89c4ff92SAndroid Build Coastguard Worker std::cerr << "No matching files with the \".raw\" extension found in the directory: "
247*89c4ff92SAndroid Build Coastguard Worker << rawDirectory << std::endl;
248*89c4ff92SAndroid Build Coastguard Worker return -1;
249*89c4ff92SAndroid Build Coastguard Worker }
250*89c4ff92SAndroid Build Coastguard Worker
251*89c4ff92SAndroid Build Coastguard Worker return 0;
252*89c4ff92SAndroid Build Coastguard Worker }