@@ -541,6 +541,7 @@ F: doc/guides/prog_guide/rawdev.rst
ML device API - EXPERIMENTAL
M: Srikanth Yalavarthi <syalavarthi@marvell.com>
F: lib/mldev/
+F: app/test-mldev/
F: doc/guides/prog_guide/mldev.rst
@@ -23,6 +23,7 @@ apps = [
'test-fib',
'test-flow-perf',
'test-gpudev',
+ 'test-mldev',
'test-pipeline',
'test-pmd',
'test-regex',
new file mode 100644
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright (c) 2022 Marvell.
+
+if is_windows
+ build = false
+ reason = 'not supported on Windows'
+ subdir_done()
+endif
+
+sources = files(
+ 'ml_main.c',
+ 'ml_options.c',
+ 'ml_test.c',
+ 'parser.c',
+)
+
+deps += ['mldev']
new file mode 100644
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2022 Marvell.
+ */
+
+#ifndef _ML_COMMON_
+#define _ML_COMMON_
+
+#include <stdio.h>
+
+#define CLNRM "\x1b[0m"
+#define CLRED "\x1b[31m"
+#define CLGRN "\x1b[32m"
+#define CLYEL "\x1b[33m"
+
+#define ML_STR_FMT 20
+
+#define ml_err(fmt, args...) fprintf(stderr, CLRED "error: %s() " fmt CLNRM "\n", __func__, ##args)
+
+#define ml_info(fmt, args...) fprintf(stdout, CLYEL "" fmt CLNRM "\n", ##args)
+
+#define ml_dump(str, fmt, val...) printf("\t%-*s : " fmt "\n", ML_STR_FMT, str, ##val)
+
+#define ml_dump_begin(str) printf("\t%-*s :\n\t{\n", ML_STR_FMT, str)
+
+#define ml_dump_list(str, id, val) printf("\t%*s[%2u] : %s\n", ML_STR_FMT - 4, str, id, val)
+
+#define ml_dump_end printf("\b\t}\n\n")
+
+#endif /* _ML_COMMON_*/
new file mode 100644
@@ -0,0 +1,118 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2022 Marvell.
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <rte_debug.h>
+#include <rte_eal.h>
+#include <rte_mldev.h>
+
+#include "ml_common.h"
+#include "ml_options.h"
+#include "ml_test.h"
+
+struct ml_options opt;
+struct ml_test *test;
+
+int
+main(int argc, char **argv)
+{
+ uint16_t mldevs;
+ int ret;
+
+ ret = rte_eal_init(argc, argv);
+ if (ret < 0)
+ rte_panic("invalid EAL arguments\n");
+ argc -= ret;
+ argv += ret;
+
+ mldevs = rte_ml_dev_count();
+ if (!mldevs)
+ rte_panic("no mldev devices found\n");
+
+ /* set default values for options */
+ ml_options_default(&opt);
+
+ /* parse the command line arguments */
+ ret = ml_options_parse(&opt, argc, argv);
+ if (ret) {
+ ml_err("parsing one or more user options failed");
+ goto error;
+ }
+
+ /* get test struct from name */
+ test = ml_test_get(opt.test_name);
+ if (test == NULL) {
+ ml_err("failed to find requested test: %s", opt.test_name);
+ goto error;
+ }
+
+ if (test->ops.test_result == NULL) {
+ ml_err("%s: ops.test_result not found", opt.test_name);
+ goto error;
+ }
+
+ /* check test options */
+ if (test->ops.opt_check) {
+ if (test->ops.opt_check(&opt)) {
+ ml_err("invalid command line argument");
+ goto error;
+ }
+ }
+
+ /* check the device capability */
+ if (test->ops.cap_check) {
+ if (test->ops.cap_check(&opt) == false) {
+ ml_info("unsupported test: %s", opt.test_name);
+ ret = ML_TEST_UNSUPPORTED;
+ goto no_cap;
+ }
+ }
+
+ /* dump options */
+ if (opt.debug) {
+ if (test->ops.opt_dump)
+ test->ops.opt_dump(&opt);
+ }
+
+ /* test specific setup */
+ if (test->ops.test_setup) {
+ if (test->ops.test_setup(test, &opt)) {
+ ml_err("failed to setup test: %s", opt.test_name);
+ goto error;
+ }
+ }
+
+ /* test driver */
+ if (test->ops.test_driver)
+ test->ops.test_driver(test, &opt);
+
+ /* get result */
+ if (test->ops.test_result)
+ ret = test->ops.test_result(test, &opt);
+
+ if (test->ops.test_destroy)
+ test->ops.test_destroy(test, &opt);
+
+no_cap:
+ if (ret == ML_TEST_SUCCESS) {
+ printf("Result: " CLGRN "%s" CLNRM "\n", "Success");
+ } else if (ret == ML_TEST_FAILED) {
+ printf("Result: " CLRED "%s" CLNRM "\n", "Failed");
+ return EXIT_FAILURE;
+ } else if (ret == ML_TEST_UNSUPPORTED) {
+ printf("Result: " CLYEL "%s" CLNRM "\n", "Unsupported");
+ }
+
+ rte_eal_cleanup();
+
+ return 0;
+
+error:
+ rte_eal_cleanup();
+
+ return EXIT_FAILURE;
+}
new file mode 100644
@@ -0,0 +1,160 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2022 Marvell.
+ */
+
+#include <errno.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rte_memory.h>
+#include <rte_mldev.h>
+#include <rte_string_fns.h>
+
+#include "ml_common.h"
+#include "ml_options.h"
+#include "ml_test.h"
+#include "parser.h"
+
+typedef int (*option_parser_t)(struct ml_options *opt, const char *arg);
+
+void
+ml_options_default(struct ml_options *opt)
+{
+ memset(opt, 0, sizeof(*opt));
+ strlcpy(opt->test_name, "ml_test", ML_TEST_NAME_MAX_LEN);
+ opt->dev_id = 0;
+ opt->socket_id = SOCKET_ID_ANY;
+ opt->debug = false;
+}
+
+struct long_opt_parser {
+ const char *lgopt_name;
+ option_parser_t parser_fn;
+};
+
+static int
+ml_parse_test_name(struct ml_options *opt, const char *arg)
+{
+ strlcpy(opt->test_name, arg, ML_TEST_NAME_MAX_LEN);
+ return 0;
+}
+
+static int
+ml_parse_dev_id(struct ml_options *opt, const char *arg)
+{
+ int ret;
+
+ ret = parser_read_int16(&opt->dev_id, arg);
+
+ if (ret < 0)
+ return -EINVAL;
+
+ return ret;
+}
+
+static int
+ml_parse_socket_id(struct ml_options *opt, const char *arg)
+{
+ opt->socket_id = atoi(arg);
+
+ return 0;
+}
+
+static void
+ml_dump_test_options(const char *testname)
+{
+ RTE_SET_USED(testname);
+}
+
+static void
+print_usage(char *program)
+{
+ printf("\nusage : %s [EAL options] -- [application options]\n", program);
+ printf("application options:\n");
+ printf("\t--test : name of the test application to run\n"
+ "\t--dev_id : device id of the ML device\n"
+ "\t--socket_id : socket_id of application resources\n"
+ "\t--debug : enable debug mode\n"
+ "\t--help : print help\n");
+ printf("\n");
+ printf("available tests and test specific application options:\n");
+ ml_test_dump_names(ml_dump_test_options);
+}
+
+static struct option lgopts[] = {{ML_TEST, 1, 0, 0}, {ML_DEVICE_ID, 1, 0, 0},
+ {ML_SOCKET_ID, 1, 0, 0}, {ML_DEBUG, 0, 0, 0},
+ {ML_HELP, 0, 0, 0}, {NULL, 0, 0, 0}};
+
+static int
+ml_opts_parse_long(int opt_idx, struct ml_options *opt)
+{
+ unsigned int i;
+
+ struct long_opt_parser parsermap[] = {
+ {ML_TEST, ml_parse_test_name},
+ {ML_DEVICE_ID, ml_parse_dev_id},
+ {ML_SOCKET_ID, ml_parse_socket_id},
+ };
+
+ for (i = 0; i < RTE_DIM(parsermap); i++) {
+ if (strncmp(lgopts[opt_idx].name, parsermap[i].lgopt_name,
+ strlen(lgopts[opt_idx].name)) == 0)
+ return parsermap[i].parser_fn(opt, optarg);
+ }
+
+ return -EINVAL;
+}
+
+int
+ml_options_parse(struct ml_options *opt, int argc, char **argv)
+{
+ int opt_idx;
+ int retval;
+ int opts;
+
+ while ((opts = getopt_long(argc, argv, "", lgopts, &opt_idx)) != EOF) {
+ switch (opts) {
+ case 0: /* parse long options */
+ if (!strcmp(lgopts[opt_idx].name, "debug")) {
+ opt->debug = true;
+ break;
+ }
+
+ if (!strcmp(lgopts[opt_idx].name, "help")) {
+ print_usage(argv[0]);
+ exit(EXIT_SUCCESS);
+ }
+
+ retval = ml_opts_parse_long(opt_idx, opt);
+ if (retval != 0)
+ return retval;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+void
+ml_options_dump(struct ml_options *opt)
+{
+ struct rte_ml_dev_info dev_info;
+
+ rte_ml_dev_info_get(opt->dev_id, &dev_info);
+
+ ml_dump("driver", "%s", dev_info.driver_name);
+ ml_dump("test", "%s", opt->test_name);
+ ml_dump("dev_id", "%d", opt->dev_id);
+
+ if (opt->socket_id == SOCKET_ID_ANY)
+ ml_dump("socket_id", "%d (SOCKET_ID_ANY)", opt->socket_id);
+ else
+ ml_dump("socket_id", "%d", opt->socket_id);
+
+ ml_dump("debug", "%s", (opt->debug ? "true" : "false"));
+}
new file mode 100644
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2022 Marvell.
+ */
+
+#ifndef _ML_OPTIONS_
+#define _ML_OPTIONS_
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#define ML_TEST_NAME_MAX_LEN 32
+
+/* Options names */
+#define ML_TEST ("test")
+#define ML_DEVICE_ID ("dev_id")
+#define ML_SOCKET_ID ("socket_id")
+#define ML_DEBUG ("debug")
+#define ML_HELP ("help")
+
+struct ml_options {
+ char test_name[ML_TEST_NAME_MAX_LEN];
+ int16_t dev_id;
+ int socket_id;
+ bool debug;
+};
+
+void ml_options_default(struct ml_options *opt);
+int ml_options_parse(struct ml_options *opt, int argc, char **argv);
+void ml_options_dump(struct ml_options *opt);
+
+#endif /* _ML_OPTIONS_ */
new file mode 100644
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2022 Marvell.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/queue.h>
+
+#include "ml_test.h"
+
+static STAILQ_HEAD(, ml_test_entry) head = STAILQ_HEAD_INITIALIZER(head);
+
+void
+ml_test_register(struct ml_test_entry *entry)
+{
+ STAILQ_INSERT_TAIL(&head, entry, next);
+}
+
+struct ml_test *
+ml_test_get(const char *name)
+{
+ struct ml_test_entry *entry;
+
+ if (!name)
+ return NULL;
+
+ STAILQ_FOREACH(entry, &head, next)
+ if (!strncmp(entry->test.name, name, strlen(name)))
+ return &entry->test;
+
+ return NULL;
+}
+
+void
+ml_test_dump_names(void (*f)(const char *name))
+{
+ struct ml_test_entry *entry;
+
+ STAILQ_FOREACH(entry, &head, next)
+ {
+ if (entry->test.name)
+ printf("\t %s\n", entry->test.name);
+ f(entry->test.name);
+ }
+}
new file mode 100644
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2022 Marvell.
+ */
+
+#ifndef _ML_TEST_
+#define _ML_TEST_
+
+#include <stdbool.h>
+#include <string.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+
+#include "ml_options.h"
+
+#define ML_TEST_MAX_POOL_SIZE 256
+
+enum ml_test_result {
+ ML_TEST_SUCCESS,
+ ML_TEST_FAILED,
+ ML_TEST_UNSUPPORTED,
+};
+
+struct ml_test;
+
+typedef bool (*ml_test_capability_check_t)(struct ml_options *opt);
+typedef int (*ml_test_options_check_t)(struct ml_options *opt);
+typedef void (*ml_test_options_dump_t)(struct ml_options *opt);
+typedef int (*ml_test_setup_t)(struct ml_test *test, struct ml_options *opt);
+typedef void (*ml_test_destroy_t)(struct ml_test *test, struct ml_options *opt);
+typedef int (*ml_test_driver_t)(struct ml_test *test, struct ml_options *opt);
+typedef int (*ml_test_result_t)(struct ml_test *test, struct ml_options *opt);
+
+struct ml_test_ops {
+ ml_test_capability_check_t cap_check;
+ ml_test_options_check_t opt_check;
+ ml_test_options_dump_t opt_dump;
+ ml_test_setup_t test_setup;
+ ml_test_destroy_t test_destroy;
+ ml_test_driver_t test_driver;
+ ml_test_result_t test_result;
+};
+
+struct ml_test {
+ const char *name;
+ void *test_priv;
+ struct ml_test_ops ops;
+};
+
+struct ml_test_entry {
+ struct ml_test test;
+
+ STAILQ_ENTRY(ml_test_entry) next;
+};
+
+static inline void *
+ml_test_priv(struct ml_test *test)
+{
+ return test->test_priv;
+}
+
+struct ml_test *ml_test_get(const char *name);
+void ml_test_register(struct ml_test_entry *test);
+void ml_test_dump_names(void (*f)(const char *));
+
+#define ML_TEST_REGISTER(nm) \
+ static struct ml_test_entry _ml_test_entry_##nm; \
+ RTE_INIT(ml_test_##nm) \
+ { \
+ _ml_test_entry_##nm.test.name = RTE_STR(nm); \
+ memcpy(&_ml_test_entry_##nm.test.ops, &nm, sizeof(struct ml_test_ops)); \
+ ml_test_register(&_ml_test_entry_##nm); \
+ }
+
+#endif /* _ML_TEST_ */
new file mode 100644
@@ -0,0 +1,380 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2016 Intel Corporation.
+ * Copyright (c) 2017 Cavium, Inc.
+ * Copyright (c) 2022 Marvell.
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rte_common.h>
+
+#include "parser.h"
+
+static uint32_t
+get_hex_val(char c)
+{
+ switch (c) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return c - '0';
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ return c - 'A' + 10;
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ return c - 'a' + 10;
+ default:
+ return 0;
+ }
+}
+
+int
+parser_read_arg_bool(const char *p)
+{
+ p = skip_white_spaces(p);
+ int result = -EINVAL;
+
+ if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) ||
+ ((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) {
+ p += 3;
+ result = 1;
+ }
+
+ if (((p[0] == 'o') && (p[1] == 'n')) || ((p[0] == 'O') && (p[1] == 'N'))) {
+ p += 2;
+ result = 1;
+ }
+
+ if (((p[0] == 'n') && (p[1] == 'o')) || ((p[0] == 'N') && (p[1] == 'O'))) {
+ p += 2;
+ result = 0;
+ }
+
+ if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) ||
+ ((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) {
+ p += 3;
+ result = 0;
+ }
+
+ p = skip_white_spaces(p);
+
+ if (p[0] != '\0')
+ return -EINVAL;
+
+ return result;
+}
+
+int
+parser_read_uint64(uint64_t *value, const char *p)
+{
+ char *next;
+ uint64_t val;
+
+ p = skip_white_spaces(p);
+ if (!isdigit(*p))
+ return -EINVAL;
+
+ val = strtoul(p, &next, 10);
+ if (p == next)
+ return -EINVAL;
+
+ p = next;
+ switch (*p) {
+ case 'T':
+ val *= 1024ULL;
+ /* fall through */
+ case 'G':
+ val *= 1024ULL;
+ /* fall through */
+ case 'M':
+ val *= 1024ULL;
+ /* fall through */
+ case 'k':
+ case 'K':
+ val *= 1024ULL;
+ p++;
+ break;
+ }
+
+ p = skip_white_spaces(p);
+ if (*p != '\0')
+ return -EINVAL;
+
+ *value = val;
+ return 0;
+}
+
+int
+parser_read_int32(int32_t *value, const char *p)
+{
+ char *next;
+ int32_t val;
+
+ p = skip_white_spaces(p);
+ if (!isdigit(*p))
+ return -EINVAL;
+
+ val = strtol(p, &next, 10);
+ if (p == next)
+ return -EINVAL;
+
+ *value = val;
+ return 0;
+}
+
+int
+parser_read_int16(int16_t *value, const char *p)
+{
+ char *next;
+ int16_t val;
+
+ p = skip_white_spaces(p);
+ if (!isdigit(*p))
+ return -EINVAL;
+
+ val = strtol(p, &next, 10);
+ if (p == next)
+ return -EINVAL;
+
+ *value = val;
+ return 0;
+}
+
+int
+parser_read_uint64_hex(uint64_t *value, const char *p)
+{
+ char *next;
+ uint64_t val;
+
+ p = skip_white_spaces(p);
+
+ val = strtoul(p, &next, 16);
+ if (p == next)
+ return -EINVAL;
+
+ p = skip_white_spaces(next);
+ if (*p != '\0')
+ return -EINVAL;
+
+ *value = val;
+ return 0;
+}
+
+int
+parser_read_uint32(uint32_t *value, const char *p)
+{
+ uint64_t val = 0;
+ int ret = parser_read_uint64(&val, p);
+
+ if (ret < 0)
+ return ret;
+
+ if (val > UINT32_MAX)
+ return -ERANGE;
+
+ *value = val;
+ return 0;
+}
+
+int
+parser_read_uint32_hex(uint32_t *value, const char *p)
+{
+ uint64_t val = 0;
+ int ret = parser_read_uint64_hex(&val, p);
+
+ if (ret < 0)
+ return ret;
+
+ if (val > UINT32_MAX)
+ return -ERANGE;
+
+ *value = val;
+ return 0;
+}
+
+int
+parser_read_uint16(uint16_t *value, const char *p)
+{
+ uint64_t val = 0;
+ int ret = parser_read_uint64(&val, p);
+
+ if (ret < 0)
+ return ret;
+
+ if (val > UINT16_MAX)
+ return -ERANGE;
+
+ *value = val;
+ return 0;
+}
+
+int
+parser_read_uint16_hex(uint16_t *value, const char *p)
+{
+ uint64_t val = 0;
+ int ret = parser_read_uint64_hex(&val, p);
+
+ if (ret < 0)
+ return ret;
+
+ if (val > UINT16_MAX)
+ return -ERANGE;
+
+ *value = val;
+ return 0;
+}
+
+int
+parser_read_uint8(uint8_t *value, const char *p)
+{
+ uint64_t val = 0;
+ int ret = parser_read_uint64(&val, p);
+
+ if (ret < 0)
+ return ret;
+
+ if (val > UINT8_MAX)
+ return -ERANGE;
+
+ *value = val;
+ return 0;
+}
+
+int
+parser_read_uint8_hex(uint8_t *value, const char *p)
+{
+ uint64_t val = 0;
+ int ret = parser_read_uint64_hex(&val, p);
+
+ if (ret < 0)
+ return ret;
+
+ if (val > UINT8_MAX)
+ return -ERANGE;
+
+ *value = val;
+ return 0;
+}
+
+int
+parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
+{
+ uint32_t i;
+
+ if ((string == NULL) || (tokens == NULL) || (*n_tokens < 1))
+ return -EINVAL;
+
+ for (i = 0; i < *n_tokens; i++) {
+ tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
+ if (tokens[i] == NULL)
+ break;
+ }
+
+ if ((i == *n_tokens) && (strtok_r(string, PARSE_DELIMITER, &string) != NULL))
+ return -E2BIG;
+
+ *n_tokens = i;
+ return 0;
+}
+
+int
+parse_hex_string(char *src, uint8_t *dst, uint32_t *size)
+{
+ char *c;
+ uint32_t len, i;
+
+ /* Check input parameters */
+ if ((src == NULL) || (dst == NULL) || (size == NULL) || (*size == 0))
+ return -1;
+
+ len = strlen(src);
+ if (((len & 3) != 0) || (len > (*size) * 2))
+ return -1;
+ *size = len / 2;
+
+ for (c = src; *c != 0; c++) {
+ if ((((*c) >= '0') && ((*c) <= '9')) || (((*c) >= 'A') && ((*c) <= 'F')) ||
+ (((*c) >= 'a') && ((*c) <= 'f')))
+ continue;
+
+ return -1;
+ }
+
+ /* Convert chars to bytes */
+ for (i = 0; i < *size; i++)
+ dst[i] = get_hex_val(src[2 * i]) * 16 + get_hex_val(src[2 * i + 1]);
+
+ return 0;
+}
+
+int
+parse_lcores_list(bool lcores[], int lcores_num, const char *corelist)
+{
+ int i, idx = 0;
+ int min, max;
+ char *end = NULL;
+
+ if (corelist == NULL)
+ return -1;
+ while (isblank(*corelist))
+ corelist++;
+ i = strlen(corelist);
+ while ((i > 0) && isblank(corelist[i - 1]))
+ i--;
+
+ /* Get list of lcores */
+ min = RTE_MAX_LCORE;
+ do {
+ while (isblank(*corelist))
+ corelist++;
+ if (*corelist == '\0')
+ return -1;
+ idx = strtoul(corelist, &end, 10);
+ if (idx < 0 || idx > lcores_num)
+ return -1;
+
+ if (end == NULL)
+ return -1;
+ while (isblank(*end))
+ end++;
+ if (*end == '-') {
+ min = idx;
+ } else if ((*end == ',') || (*end == '\0')) {
+ max = idx;
+ if (min == RTE_MAX_LCORE)
+ min = idx;
+ for (idx = min; idx <= max; idx++) {
+ if (lcores[idx] == 1)
+ return -E2BIG;
+ lcores[idx] = 1;
+ }
+
+ min = RTE_MAX_LCORE;
+ } else
+ return -1;
+ corelist = end + 1;
+ } while (*end != '\0');
+
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2010-2016 Intel Corporation.
+ * Copyright (c) 2022 Marvell.
+ */
+
+#ifndef __INCLUDE_PARSER_H__
+#define __INCLUDE_PARSER_H__
+
+#include <ctype.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#define PARSE_DELIMITER " \f\n\r\t\v"
+
+#define skip_white_spaces(pos) \
+ ({ \
+ __typeof__(pos) _p = (pos); \
+ for (; isspace(*_p); _p++) \
+ ; \
+ _p; \
+ })
+
+static inline size_t
+skip_digits(const char *src)
+{
+ size_t i;
+
+ for (i = 0; isdigit(src[i]); i++)
+ ;
+
+ return i;
+}
+
+int parser_read_arg_bool(const char *p);
+
+int parser_read_uint64(uint64_t *value, const char *p);
+int parser_read_uint32(uint32_t *value, const char *p);
+int parser_read_uint16(uint16_t *value, const char *p);
+int parser_read_uint8(uint8_t *value, const char *p);
+
+int parser_read_uint64_hex(uint64_t *value, const char *p);
+int parser_read_uint32_hex(uint32_t *value, const char *p);
+int parser_read_uint16_hex(uint16_t *value, const char *p);
+int parser_read_uint8_hex(uint8_t *value, const char *p);
+
+int parser_read_int32(int32_t *value, const char *p);
+int parser_read_int16(int16_t *value, const char *p);
+
+int parse_hex_string(char *src, uint8_t *dst, uint32_t *size);
+
+int parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens);
+
+int parse_lcores_list(bool lcores[], int lcores_num, const char *corelist);
+
+#endif /* __INCLUDE_PARSER_H__ */
@@ -87,6 +87,14 @@ New Features
* Added a machine learning inference device framework for management and provision of
hardware and software machine learning inference devices.
+* **Added test application for machine learning inference device library.**
+
+ * Added test application for mldev library with support for multiple test cases.
+ * Test case for device operations.
+ * Test case for model operations.
+ * Test case for inferences from multiple models in ordered mode.
+ * Test case for inferences from multiple models.in interleaving mode.
+
Removed Items
-------------