Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2022 Marvell.
3 : : */
4 : :
5 : : #include <errno.h>
6 : : #include <getopt.h>
7 : : #include <math.h>
8 : :
9 : : #include <rte_memory.h>
10 : : #include <rte_mldev.h>
11 : : #include <rte_string_fns.h>
12 : :
13 : : #include "ml_common.h"
14 : : #include "ml_test.h"
15 : : #include "parser.h"
16 : :
17 : : typedef int (*option_parser_t)(struct ml_options *opt, const char *arg);
18 : :
19 : : void
20 : 0 : ml_options_default(struct ml_options *opt)
21 : : {
22 : : memset(opt, 0, sizeof(*opt));
23 : 0 : strlcpy(opt->test_name, "device_ops", ML_TEST_NAME_MAX_LEN);
24 : 0 : opt->dev_id = 0;
25 : 0 : opt->socket_id = SOCKET_ID_ANY;
26 : 0 : opt->nb_filelist = 0;
27 : 0 : opt->quantized_io = false;
28 : 0 : opt->repetitions = 1;
29 : 0 : opt->burst_size = 1;
30 : 0 : opt->queue_pairs = 1;
31 : 0 : opt->queue_size = 1;
32 : 0 : opt->tolerance = 0.0;
33 : 0 : opt->stats = false;
34 : 0 : opt->debug = false;
35 : 0 : }
36 : :
37 : : struct long_opt_parser {
38 : : const char *lgopt_name;
39 : : option_parser_t parser_fn;
40 : : };
41 : :
42 : : static int
43 : 0 : ml_parse_test_name(struct ml_options *opt, const char *arg)
44 : : {
45 : 0 : strlcpy(opt->test_name, arg, ML_TEST_NAME_MAX_LEN);
46 : :
47 : 0 : return 0;
48 : : }
49 : :
50 : : static int
51 : 0 : ml_parse_dev_id(struct ml_options *opt, const char *arg)
52 : : {
53 : : int ret;
54 : :
55 : 0 : ret = parser_read_int16(&opt->dev_id, arg);
56 : 0 : if (ret < 0)
57 : 0 : ml_err("Invalid option: dev_id = %s\n", arg);
58 : :
59 : 0 : return ret;
60 : : }
61 : :
62 : : static int
63 : 0 : ml_parse_socket_id(struct ml_options *opt, const char *arg)
64 : : {
65 : : int ret;
66 : :
67 : 0 : ret = parser_read_int32(&opt->socket_id, arg);
68 : 0 : if (ret < 0)
69 : 0 : ml_err("Invalid option: socket_id = %s\n", arg);
70 : :
71 : 0 : return ret;
72 : : }
73 : :
74 : : static int
75 : 0 : ml_parse_models(struct ml_options *opt, const char *arg)
76 : : {
77 : : const char *delim = ",";
78 : : char models[PATH_MAX];
79 : : char *token;
80 : : int ret = 0;
81 : :
82 : : strlcpy(models, arg, PATH_MAX);
83 : :
84 : 0 : token = strtok(models, delim);
85 : 0 : while (token != NULL) {
86 : 0 : if (opt->nb_filelist >= ML_TEST_MAX_MODELS) {
87 : 0 : ml_err("Exceeded model count, max = %d\n", ML_TEST_MAX_MODELS);
88 : : ret = -EINVAL;
89 : 0 : break;
90 : : }
91 : :
92 : 0 : strlcpy(opt->filelist[opt->nb_filelist].model, token, PATH_MAX);
93 : 0 : opt->nb_filelist++;
94 : :
95 : 0 : token = strtok(NULL, delim);
96 : : }
97 : :
98 : 0 : if (opt->nb_filelist == 0) {
99 : 0 : ml_err("Models list is empty. Need at least one model for the test");
100 : : ret = -EINVAL;
101 : : }
102 : :
103 : 0 : return ret;
104 : : }
105 : :
106 : : static int
107 : 0 : ml_parse_filelist(struct ml_options *opt, const char *arg)
108 : : {
109 : : const char *delim = ",";
110 : : char filelist[PATH_MAX];
111 : : char *token;
112 : :
113 : 0 : if (opt->nb_filelist >= ML_TEST_MAX_MODELS) {
114 : 0 : ml_err("Exceeded filelist count, max = %d\n", ML_TEST_MAX_MODELS);
115 : 0 : return -1;
116 : : }
117 : :
118 : : strlcpy(filelist, arg, PATH_MAX);
119 : :
120 : : /* model */
121 : 0 : token = strtok(filelist, delim);
122 : 0 : if (token == NULL) {
123 : 0 : ml_err("Invalid filelist, model not specified = %s\n", arg);
124 : 0 : return -EINVAL;
125 : : }
126 : 0 : strlcpy(opt->filelist[opt->nb_filelist].model, token, PATH_MAX);
127 : :
128 : : /* input */
129 : 0 : token = strtok(NULL, delim);
130 : 0 : if (token == NULL) {
131 : 0 : ml_err("Invalid filelist, input not specified = %s\n", arg);
132 : 0 : return -EINVAL;
133 : : }
134 : 0 : strlcpy(opt->filelist[opt->nb_filelist].input, token, PATH_MAX);
135 : :
136 : : /* output */
137 : 0 : token = strtok(NULL, delim);
138 : 0 : if (token == NULL) {
139 : 0 : ml_err("Invalid filelist, output not specified = %s\n", arg);
140 : 0 : return -EINVAL;
141 : : }
142 : 0 : strlcpy(opt->filelist[opt->nb_filelist].output, token, PATH_MAX);
143 : :
144 : : /* reference - optional */
145 : 0 : token = strtok(NULL, delim);
146 : 0 : if (token != NULL)
147 : 0 : strlcpy(opt->filelist[opt->nb_filelist].reference, token, PATH_MAX);
148 : : else
149 : 0 : memset(opt->filelist[opt->nb_filelist].reference, 0, PATH_MAX);
150 : :
151 : : /* check for extra tokens */
152 : 0 : token = strtok(NULL, delim);
153 : 0 : if (token != NULL) {
154 : 0 : ml_err("Invalid filelist. Entries > 4\n.");
155 : 0 : return -EINVAL;
156 : : }
157 : :
158 : 0 : opt->nb_filelist++;
159 : :
160 : 0 : if (opt->nb_filelist == 0) {
161 : 0 : ml_err("Empty filelist. Need at least one filelist entry for the test.\n");
162 : 0 : return -EINVAL;
163 : : }
164 : :
165 : : return 0;
166 : : }
167 : :
168 : : static int
169 : 0 : ml_parse_repetitions(struct ml_options *opt, const char *arg)
170 : : {
171 : : int ret;
172 : :
173 : 0 : ret = parser_read_uint64(&opt->repetitions, arg);
174 : 0 : if (ret != 0)
175 : 0 : ml_err("Invalid option, repetitions = %s\n", arg);
176 : :
177 : 0 : return ret;
178 : : }
179 : :
180 : : static int
181 : 0 : ml_parse_burst_size(struct ml_options *opt, const char *arg)
182 : : {
183 : : int ret;
184 : :
185 : 0 : ret = parser_read_uint16(&opt->burst_size, arg);
186 : 0 : if (ret != 0)
187 : 0 : ml_err("Invalid option, burst_size = %s\n", arg);
188 : :
189 : 0 : return ret;
190 : : }
191 : :
192 : : static int
193 : 0 : ml_parse_queue_pairs(struct ml_options *opt, const char *arg)
194 : : {
195 : : int ret;
196 : :
197 : 0 : ret = parser_read_uint16(&opt->queue_pairs, arg);
198 : 0 : if (ret != 0)
199 : 0 : ml_err("Invalid option, queue_pairs = %s\n", arg);
200 : :
201 : 0 : return ret;
202 : : }
203 : :
204 : : static int
205 : 0 : ml_parse_queue_size(struct ml_options *opt, const char *arg)
206 : : {
207 : : int ret;
208 : :
209 : 0 : ret = parser_read_uint16(&opt->queue_size, arg);
210 : 0 : if (ret != 0)
211 : 0 : ml_err("Invalid option, queue_size = %s\n", arg);
212 : :
213 : 0 : return ret;
214 : : }
215 : :
216 : : static int
217 : 0 : ml_parse_tolerance(struct ml_options *opt, const char *arg)
218 : : {
219 : 0 : opt->tolerance = fabs(atof(arg));
220 : :
221 : 0 : return 0;
222 : : }
223 : :
224 : : static void
225 : 0 : ml_dump_test_options(const char *testname)
226 : : {
227 : 0 : if (strcmp(testname, "device_ops") == 0) {
228 : : printf("\t\t--queue_pairs : number of queue pairs to create\n"
229 : : "\t\t--queue_size : size of queue-pair\n");
230 : : printf("\n");
231 : : }
232 : :
233 : 0 : if (strcmp(testname, "model_ops") == 0) {
234 : : printf("\t\t--models : comma separated list of models\n"
235 : : "\t\t--stats : enable reporting device statistics\n");
236 : : printf("\n");
237 : : }
238 : :
239 : 0 : if ((strcmp(testname, "inference_ordered") == 0) ||
240 : 0 : (strcmp(testname, "inference_interleave") == 0)) {
241 : : printf("\t\t--filelist : comma separated list of model, input, output and reference\n"
242 : : "\t\t--repetitions : number of inference repetitions\n"
243 : : "\t\t--burst_size : inference burst size\n"
244 : : "\t\t--queue_pairs : number of queue pairs to create\n"
245 : : "\t\t--queue_size : size of queue-pair\n"
246 : : "\t\t--tolerance : maximum tolerance (%%) for output validation\n"
247 : : "\t\t--stats : enable reporting device and model statistics\n"
248 : : "\t\t--quantized_io : skip input/output quantization\n");
249 : : printf("\n");
250 : : }
251 : 0 : }
252 : :
253 : : static void
254 : 0 : print_usage(char *program)
255 : : {
256 : : printf("\nusage : %s [EAL options] -- [application options]\n", program);
257 : : printf("application options:\n");
258 : : printf("\t--test : name of the test application to run\n"
259 : : "\t--dev_id : device id of the ML device\n"
260 : : "\t--socket_id : socket_id of application resources\n"
261 : : "\t--debug : enable debug mode\n"
262 : : "\t--help : print help\n");
263 : : printf("\n");
264 : : printf("available tests and test specific application options:\n");
265 : 0 : ml_test_dump_names(ml_dump_test_options);
266 : 0 : }
267 : :
268 : : static struct option lgopts[] = {
269 : : {ML_TEST, 1, 0, 0},
270 : : {ML_DEVICE_ID, 1, 0, 0},
271 : : {ML_SOCKET_ID, 1, 0, 0},
272 : : {ML_MODELS, 1, 0, 0},
273 : : {ML_FILELIST, 1, 0, 0},
274 : : {ML_QUANTIZED_IO, 0, 0, 0},
275 : : {ML_REPETITIONS, 1, 0, 0},
276 : : {ML_BURST_SIZE, 1, 0, 0},
277 : : {ML_QUEUE_PAIRS, 1, 0, 0},
278 : : {ML_QUEUE_SIZE, 1, 0, 0},
279 : : {ML_TOLERANCE, 1, 0, 0},
280 : : {ML_STATS, 0, 0, 0},
281 : : {ML_DEBUG, 0, 0, 0},
282 : : {ML_HELP, 0, 0, 0},
283 : : {NULL, 0, 0, 0}};
284 : :
285 : : static int
286 : 0 : ml_opts_parse_long(int opt_idx, struct ml_options *opt)
287 : : {
288 : : unsigned int i;
289 : :
290 : 0 : struct long_opt_parser parsermap[] = {
291 : : {ML_TEST, ml_parse_test_name},
292 : : {ML_DEVICE_ID, ml_parse_dev_id},
293 : : {ML_SOCKET_ID, ml_parse_socket_id},
294 : : {ML_MODELS, ml_parse_models},
295 : : {ML_FILELIST, ml_parse_filelist},
296 : : {ML_REPETITIONS, ml_parse_repetitions},
297 : : {ML_BURST_SIZE, ml_parse_burst_size},
298 : : {ML_QUEUE_PAIRS, ml_parse_queue_pairs},
299 : : {ML_QUEUE_SIZE, ml_parse_queue_size},
300 : : {ML_TOLERANCE, ml_parse_tolerance},
301 : : };
302 : :
303 : 0 : for (i = 0; i < RTE_DIM(parsermap); i++) {
304 : 0 : if (strncmp(lgopts[opt_idx].name, parsermap[i].lgopt_name,
305 : : strlen(lgopts[opt_idx].name)) == 0)
306 : 0 : return parsermap[i].parser_fn(opt, optarg);
307 : : }
308 : :
309 : : return -EINVAL;
310 : : }
311 : :
312 : : int
313 : 0 : ml_options_parse(struct ml_options *opt, int argc, char **argv)
314 : : {
315 : : int opt_idx;
316 : : int retval;
317 : : int opts;
318 : :
319 : 0 : while ((opts = getopt_long(argc, argv, "", lgopts, &opt_idx)) != EOF) {
320 : 0 : switch (opts) {
321 : 0 : case 0: /* parse long options */
322 : 0 : if (!strcmp(lgopts[opt_idx].name, "quantized_io")) {
323 : 0 : opt->quantized_io = true;
324 : 0 : break;
325 : : }
326 : :
327 : 0 : if (!strcmp(lgopts[opt_idx].name, "stats")) {
328 : 0 : opt->stats = true;
329 : 0 : break;
330 : : }
331 : :
332 : 0 : if (!strcmp(lgopts[opt_idx].name, "debug")) {
333 : 0 : opt->debug = true;
334 : 0 : break;
335 : : }
336 : :
337 : 0 : if (!strcmp(lgopts[opt_idx].name, "help")) {
338 : 0 : print_usage(argv[0]);
339 : 0 : exit(EXIT_SUCCESS);
340 : : }
341 : :
342 : 0 : retval = ml_opts_parse_long(opt_idx, opt);
343 : 0 : if (retval != 0)
344 : 0 : return retval;
345 : : break;
346 : : default:
347 : : return -EINVAL;
348 : : }
349 : : }
350 : :
351 : : return 0;
352 : : }
353 : :
354 : : void
355 : 0 : ml_options_dump(struct ml_options *opt)
356 : : {
357 : : struct rte_ml_dev_info dev_info;
358 : :
359 : 0 : rte_ml_dev_info_get(opt->dev_id, &dev_info);
360 : :
361 : 0 : ml_dump("driver", "%s", dev_info.driver_name);
362 : 0 : ml_dump("test", "%s", opt->test_name);
363 : 0 : ml_dump("dev_id", "%d", opt->dev_id);
364 : :
365 : 0 : if (opt->socket_id == SOCKET_ID_ANY)
366 : : ml_dump("socket_id", "%d (SOCKET_ID_ANY)", opt->socket_id);
367 : : else
368 : : ml_dump("socket_id", "%d", opt->socket_id);
369 : :
370 : 0 : ml_dump("debug", "%s", (opt->debug ? "true" : "false"));
371 : 0 : ml_dump("quantized_io", "%s", (opt->quantized_io ? "true" : "false"));
372 : 0 : }
|