1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #include "CommandLineProcessor.hpp"
7 #include <Filesystem.hpp>
8
9 #include <cxxopts/cxxopts.hpp>
10
11 namespace armnnQuantizer
12 {
13
ValidateOutputDirectory(std::string & dir)14 bool ValidateOutputDirectory(std::string& dir)
15 {
16 if (dir.empty())
17 {
18 std::cerr << "No output directory specified" << std::endl;
19 return false;
20 }
21
22 if (dir[dir.length() - 1] != '/')
23 {
24 dir += "/";
25 }
26
27 if (!fs::exists(dir))
28 {
29 std::cerr << "Output directory [" << dir << "] does not exist" << std::endl;
30 return false;
31 }
32
33 if (!fs::is_directory(dir))
34 {
35 std::cerr << "Given output directory [" << dir << "] is not a directory" << std::endl;
36 return false;
37 }
38
39 return true;
40 }
41
ValidateProvidedFile(const std::string & inputFileName)42 bool ValidateProvidedFile(const std::string& inputFileName)
43 {
44 if (!fs::exists(inputFileName))
45 {
46 std::cerr << "Provided file [" << inputFileName << "] does not exist" << std::endl;
47 return false;
48 }
49
50 if (fs::is_directory(inputFileName))
51 {
52 std::cerr << "Given file [" << inputFileName << "] is a directory" << std::endl;
53 return false;
54 }
55
56 return true;
57 }
58
ValidateQuantizationScheme(const std::string & scheme)59 bool ValidateQuantizationScheme(const std::string& scheme)
60 {
61 if (scheme.empty())
62 {
63 std::cerr << "No Quantization Scheme specified" << std::endl;
64 return false;
65 }
66
67 std::vector<std::string> supportedSchemes =
68 {
69 "QAsymmS8",
70 "QAsymmU8",
71 "QSymm16"
72 };
73
74 auto iterator = std::find(supportedSchemes.begin(), supportedSchemes.end(), scheme);
75 if (iterator == supportedSchemes.end())
76 {
77 std::cerr << "Quantization Scheme [" << scheme << "] is not supported" << std::endl;
78 return false;
79 }
80
81 return true;
82 }
83
ProcessCommandLine(int argc,char * argv[])84 bool CommandLineProcessor::ProcessCommandLine(int argc, char* argv[])
85 {
86 try
87 {
88 cxxopts::Options options("ArmnnQuantizer","Convert a Fp32 ArmNN model to a quantized ArmNN model.");
89
90 options.add_options()
91 ("h,help", "Display help messages")
92 ("f,infile",
93 "Input file containing float 32 ArmNN Input Graph",
94 cxxopts::value<std::string>(m_InputFileName))
95 ("s,scheme",
96 "Quantization scheme,"
97 " \"QAsymmU8\" or \"QAsymmS8\" or \"QSymm16\","
98 " default value QAsymmU8",
99 cxxopts::value<std::string>(m_QuantizationScheme)->default_value("QAsymmU8"))
100 ("c,csvfile",
101 "CSV file containing paths for RAW input tensors",
102 cxxopts::value<std::string>(m_CsvFileName)->default_value(""))
103 ("p,preserve-data-type",
104 "Preserve the input and output data types",
105 cxxopts::value<bool>(m_PreserveDataType)->default_value("false"))
106 ("d,outdir",
107 "Directory that output file will be written to",
108 cxxopts::value<std::string>(m_OutputDirectory))
109 ("o,outfile",
110 "ArmNN output file name",
111 cxxopts::value<std::string>(m_OutputFileName));
112
113 auto result = options.parse(argc, argv);
114
115 if (result.count("help") > 0 || argc <= 1)
116 {
117 std::cout << options.help() << std::endl;
118 return false;
119 }
120
121 // Check for mandatory single options.
122 std::string mandatorySingleParameters[] = { "infile", "outdir", "outfile" };
123 for (auto param : mandatorySingleParameters)
124 {
125 if (result.count(param) != 1)
126 {
127 std::cerr << "Parameter \'--" << param << "\' is required but missing." << std::endl;
128 return false;
129 }
130 }
131 }
132 catch (const cxxopts::OptionException& e)
133 {
134 std::cerr << e.what() << std::endl << std::endl;
135 return false;
136 }
137 catch (const std::exception& e)
138 {
139 std::cerr << "Fatal internal error: [" << e.what() << "]" << std::endl;
140 return false;
141 }
142
143 if (!armnnQuantizer::ValidateProvidedFile(m_InputFileName))
144 {
145 return false;
146 }
147
148 if (!ValidateQuantizationScheme(m_QuantizationScheme))
149 {
150 return false;
151 }
152
153 if (m_CsvFileName != "")
154 {
155 if (!armnnQuantizer::ValidateProvidedFile(m_CsvFileName))
156 {
157 return false;
158 }
159 else
160 {
161 fs::path csvFilePath(m_CsvFileName);
162 m_CsvFileDirectory = csvFilePath.parent_path().c_str();
163 }
164
165 // If CSV file is defined, create a QuantizationDataSet for specified CSV file.
166 m_QuantizationDataSet = QuantizationDataSet(m_CsvFileName);
167 }
168
169 if (!armnnQuantizer::ValidateOutputDirectory(m_OutputDirectory))
170 {
171 return false;
172 }
173
174 std::string output(m_OutputDirectory);
175 output.append(m_OutputFileName);
176
177 if (fs::exists(output))
178 {
179 std::cerr << "Output file [" << output << "] already exists" << std::endl;
180 return false;
181 }
182
183 return true;
184 }
185
186 } // namespace armnnQuantizer