aboutsummaryrefslogtreecommitdiff
path: root/reference_model/src/func_config.cc
diff options
context:
space:
mode:
Diffstat (limited to 'reference_model/src/func_config.cc')
-rw-r--r--reference_model/src/func_config.cc632
1 files changed, 632 insertions, 0 deletions
diff --git a/reference_model/src/func_config.cc b/reference_model/src/func_config.cc
new file mode 100644
index 0000000..bd1ce32
--- /dev/null
+++ b/reference_model/src/func_config.cc
@@ -0,0 +1,632 @@
+
+// Copyright (c) 2020, ARM Limited.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <ctype.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "func_config.h"
+#include "func_debug.h"
+
+#define MAX_NAME_LEN 128
+#define MAX_DESC_LEN 128
+
+#ifndef ARG_ERROR
+#define ARG_ERROR(...) \
+ fprintf(stderr, "ERROR: "); \
+ fprintf(stderr, __VA_ARGS__); \
+ fprintf(stderr, "\n"); \
+ return 1;
+#endif
+
+// Parameter base name string table
+const char* config_base_name_table[] = {
+#define DEF_UNIT_START(UNIT)
+#define DEF_UNIT_END(UNIT)
+#define DEF_OPTION(NAME, DESC, TYPE, FMT, DEFAULT) #NAME,
+#define DEF_OPTION_STR(NAME, DESC, LEN, DEFAULT) #NAME,
+#define DEF_UNIT_OPTION(UNIT, NAME, DESC, TYPE, FMT, DEFAULT) #NAME,
+#define DEF_UNIT_OPTION_STR(UNIT, NAME, DESC, LEN, DEFAULT) #NAME,
+#include "func_config.def"
+#undef DEF_UNIT_START
+#undef DEF_UNIT_END
+#undef DEF_OPTION
+#undef DEF_OPTION_STR
+#undef DEF_UNIT_OPTION_STR
+#undef DEF_UNIT_OPTION
+};
+
+// Parameter description table
+const char* config_param_desc_table[] = {
+#define DEF_UNIT_START(UNIT)
+#define DEF_UNIT_END(UNIT)
+#define DEF_OPTION(NAME, DESC, TYPE, FMT, DEFAULT) #DESC,
+#define DEF_OPTION_STR(NAME, DESC, LEN, DEFAULT) #DESC,
+#define DEF_UNIT_OPTION(UNIT, NAME, DESC, TYPE, FMT, DEFAULT) #DESC,
+#define DEF_UNIT_OPTION_STR(UNIT, NAME, DESC, LEN, DEFAULT) #DESC,
+#include "func_config.def"
+#undef DEF_UNIT_START
+#undef DEF_UNIT_END
+#undef DEF_OPTION
+#undef DEF_UNIT_OPTION
+#undef DEF_OPTION_STR
+#undef DEF_UNIT_OPTION_STR
+};
+
+// String table and enum for the option hierarchy level/sub-levels
+// (no leaf options). Attribute at the top level have "BASE" as their
+// enum value and an empty string for the value.
+const char* config_hier_str_table[] = {
+ "",
+#define DEF_UNIT_START(UNIT) #UNIT,
+#define DEF_UNIT_END(UNIT) /**/
+#define DEF_OPTION(NAME, DESC, TYPE, FMT, DEFAULT) /**/
+#define DEF_OPTION_STR(NAME, DESC, LEN, DEFAULT) /**/
+#define DEF_UNIT_OPTION(UNIT, NAME, DESC, TYPE, FMT, DEFAULT) /**/
+#define DEF_UNIT_OPTION_STR(UNIT, NAME, DESC, LEN, DEFAULT) /**/
+#include "func_config.def"
+#undef DEF_UNIT_START
+#undef DEF_UNIT_END
+#undef DEF_OPTION
+#undef DEF_UNIT_OPTION
+#undef DEF_OPTION_STR
+#undef DEF_UNIT_OPTION_STR
+};
+
+typedef enum config_hier_enum_t
+{
+ BASE,
+#define DEF_UNIT_START(UNIT) CURRENT_UNIT,
+#define DEF_UNIT_END(UNIT) /**/
+#define DEF_OPTION(NAME, DESC, TYPE, FMT, DEFAULT) /**/
+#define DEF_OPTION_STR(NAME, DESC, LEN, DEFAULT) /**/
+#define DEF_UNIT_OPTION(UNIT, NAME, DESC, TYPE, FMT, DEFAULT) /**/
+#define DEF_UNIT_OPTION_STR(UNIT, NAME, DESC, LEN, DEFAULT) /**/
+#include "func_config.def"
+#undef DEF_UNIT_START
+#undef DEF_UNIT_END
+#undef DEF_OPTION
+#undef DEF_UNIT_OPTION
+#undef DEF_OPTION_STR
+#undef DEF_UNIT_OPTION_STR
+
+ MAX_CONFIG_HIER
+} config_hier_enum_t;
+
+// Mapping from a leaf parameter index to the
+// position in the hierarchy.
+config_hier_enum_t config_hierarchy_map[] = {
+#define DEF_UNIT_START(UNIT)
+#define DEF_UNIT_END(UNIT)
+#define DEF_OPTION(NAME, DESC, TYPE, FMT, DEFAULT) BASE,
+#define DEF_OPTION_STR(NAME, DESC, LEN, DEFAULT) BASE,
+#define DEF_UNIT_OPTION(UNIT, NAME, DESC, TYPE, FMT, DEFAULT) CURRENT_UNIT,
+#define DEF_UNIT_OPTION_STR(UNIT, NAME, DESC, LEN, DEFAULT) CURRENT_UNIT,
+#include "func_config.def"
+#undef DEF_UNIT_START
+#undef DEF_UNIT_END
+#undef DEF_OPTION
+#undef DEF_UNIT_OPTION
+#undef DEF_OPTION_STR
+#undef DEF_UNIT_OPTION_STR
+};
+
+#define CONFIG_PARAMETER_COUNT (sizeof(config_hierarchy_map) / sizeof(config_hier_enum_t))
+
+// Dynamically generated at initialization
+char** config_param_str_table = nullptr;
+
+// Initialize the configuration data structures
+int func_model_init_config()
+{
+ // Initialize string table (builds the hierarchical names)
+ config_param_str_table = (char**)calloc(CONFIG_PARAMETER_COUNT, sizeof(char*));
+ ASSERT_MEM(config_param_str_table);
+
+ for (uint32_t i = 0; i < CONFIG_PARAMETER_COUNT; i++)
+ {
+ size_t len = strlen(config_base_name_table[i]) + 1;
+ if (config_hierarchy_map[i] != BASE)
+ {
+ ASSERT_MSG(config_hierarchy_map[i] <= MAX_CONFIG_HIER,
+ "Configuration parameter\'s hierarchy is out of bounds");
+ len += strlen(config_hier_str_table[config_hierarchy_map[i]]) + 1;
+ }
+ config_param_str_table[i] = (char*)calloc(len, 1);
+ ASSERT_MEM(config_param_str_table[i]);
+ ASSERT_MSG(len < MAX_NAME_LEN, "option expanded name is too long: %s", config_base_name_table[i]);
+
+ if (config_hierarchy_map[i] != BASE)
+ {
+ snprintf(config_param_str_table[i], len, "%s.%s", config_hier_str_table[config_hierarchy_map[i]],
+ config_base_name_table[i]);
+ }
+ else
+ {
+ snprintf(config_param_str_table[i], len, "%s", config_base_name_table[i]);
+ }
+ }
+
+ return 0;
+}
+
+int func_model_set_default_config(func_config_t* func_config)
+{
+ // Set default values in the global configuration data structure
+ bzero(func_config, sizeof(*func_config));
+
+#define DEF_UNIT_START(UNIT)
+#define DEF_UNIT_END(UNIT)
+#define DEF_OPTION(NAME, DESC, TYPE, FMT, DEFAULT) func_config->NAME = (DEFAULT);
+#define DEF_OPTION_STR(NAME, DESC, LEN, DEFAULT) strncpy(func_config->NAME, (DEFAULT), (LEN)-1);
+#define DEF_UNIT_OPTION(UNIT, NAME, DESC, TYPE, FMT, DEFAULT) func_config->UNIT.NAME = (DEFAULT);
+#define DEF_UNIT_OPTION_STR(UNIT, NAME, DESC, LEN, DEFAULT) strncpy(func_config->UNIT.NAME, (DEFAULT), (LEN)-1);
+#include "func_config.def"
+#undef DEF_UNIT_START
+#undef DEF_UNIT_END
+#undef DEF_OPTION
+#undef DEF_UNIT_OPTION
+#undef DEF_OPTION_STR
+#undef DEF_UNIT_OPTION_STR
+
+ return 0;
+}
+
+int func_model_config_cleanup()
+{
+ uint32_t i;
+
+ if (!config_param_str_table)
+ return 1;
+
+ for (i = 0; i < CONFIG_PARAMETER_COUNT; i++)
+ {
+ free(config_param_str_table[i]);
+ }
+
+ free(config_param_str_table);
+ config_param_str_table = nullptr;
+
+ return 0;
+}
+
+int func_model_config_set_option(func_config_t* func_config, const char* name, const char* value)
+{
+ // Increment an index variable on each parameter position
+ // so that we can index both the position struct through the macro and the
+ // array of parameter names through a simple array of strings.
+ int param_idx = 0;
+ char* endptr;
+
+ // TODO: does not handle strings yet. Can set magic values on FMT to
+ // choose a string copy vs strtoull
+#define DEF_UNIT_START(UNIT)
+#define DEF_UNIT_END(UNIT)
+#define DEF_OPTION(NAME, DESC, TYPE, FMT, DEFAULT) \
+ if (!strcmp(config_param_str_table[param_idx], name)) \
+ { \
+ func_config->NAME = (uint64_t)strtoll(value, &endptr, 0); \
+ if (endptr == value) \
+ { \
+ ARG_ERROR("Cannot parse option: %s = %s", name, value); \
+ } \
+ return 0; \
+ } \
+ param_idx++;
+
+#define DEF_OPTION_STR(NAME, DESC, LEN, DEFAULT) \
+ if (!strcmp(config_param_str_table[param_idx], name)) \
+ { \
+ if (strlen(value) >= LEN) \
+ { \
+ ARG_ERROR("Option value is too long: %s = %s", name, value); \
+ } \
+ strncpy(func_config->NAME, value, (LEN)-1); \
+ return 0; \
+ } \
+ param_idx++;
+
+#define DEF_UNIT_OPTION(UNIT, NAME, DESC, TYPE, FMT, DEFAULT) \
+ if (!strcmp(config_param_str_table[param_idx], name)) \
+ { \
+ func_config->UNIT.NAME = (uint64_t)strtoll(value, &endptr, 0); \
+ if (endptr == value) \
+ { \
+ ARG_ERROR("Cannot parse option: %s = %s", name, value); \
+ } \
+ return 0; \
+ } \
+ param_idx++;
+
+#define DEF_UNIT_OPTION_STR(UNIT, NAME, DESC, LEN, DEFAULT) \
+ if (!strcmp(config_param_str_table[param_idx], name)) \
+ { \
+ if (strlen(value) >= LEN) \
+ { \
+ ARG_ERROR("Option value is too long: %s = %s", name, value); \
+ } \
+ strncpy(func_config->UNIT.NAME, value, (LEN)-1); \
+ return 0; \
+ } \
+ param_idx++;
+
+#include "func_config.def"
+#undef DEF_UNIT_START
+#undef DEF_UNIT_END
+#undef DEF_OPTION
+#undef DEF_UNIT_OPTION
+#undef DEF_OPTION_STR
+#undef DEF_UNIT_OPTION_STR
+
+ // No match!
+ ARG_ERROR("Cannot find option: %s", name);
+
+ return 1;
+}
+
+int func_model_config_get_option_by_name(func_config_t* func_config, const char* name, uint64_t* val)
+{
+ // Increment an index variable on each parameter position
+ // so that we can index both the position struct through the macro and the
+ // array of parameter names through a simple array of strings.
+ int param_idx = 0;
+
+#define DEF_UNIT_START(UNIT)
+#define DEF_UNIT_END(UNIT)
+
+#define DEF_OPTION_STR(NAME, DESC, LEN, DEFAULT) param_idx++;
+
+#define DEF_UNIT_OPTION_STR(UNIT, NAME, DESC, FMT, DEFAULT) param_idx++;
+
+#define DEF_OPTION(NAME, DESC, TYPE, FMT, DEFAULT) \
+ if (!strcmp(config_param_str_table[param_idx], name)) \
+ { \
+ *val = func_config->NAME; \
+ return 0; \
+ } \
+ param_idx++;
+
+#define DEF_UNIT_OPTION(UNIT, NAME, DESC, TYPE, FMT, DEFAULT) \
+ if (!strcmp(config_param_str_table[param_idx], name)) \
+ { \
+ *val = func_config->UNIT.NAME; \
+ return 0; \
+ } \
+ param_idx++;
+
+#include "func_config.def"
+#undef DEF_UNIT_START
+#undef DEF_UNIT_END
+#undef DEF_OPTION
+#undef DEF_UNIT_OPTION
+#undef DEF_OPTION_STR
+#undef DEF_UNIT_OPTION_STR
+ // No match!
+ return 1;
+}
+int func_model_config_get_str_option_by_name(func_config_t* func_config,
+ const char* name,
+ char* value,
+ const uint32_t len)
+{
+ // Increment an index variable on each parameter position
+ // so that we can index both the position struct through the macro and the
+ // array of parameter names through a simple array of strings.
+ int param_idx = 0;
+
+#define DEF_UNIT_START(UNIT)
+#define DEF_UNIT_END(UNIT)
+#define DEF_OPTION_STR(NAME, DESC, LEN, DEFAULT) \
+ if (!strcmp(config_param_str_table[param_idx], name)) \
+ { \
+ strncpy(value, func_config->NAME, len - 1); \
+ return 0; \
+ } \
+ param_idx++;
+
+#define DEF_UNIT_OPTION_STR(UNIT, NAME, DESC, LEN, DEFAULT) \
+ if (!strcmp(config_param_str_table[param_idx], name)) \
+ { \
+ strncpy(value, func_config->UNIT.NAME, len - 1); \
+ return 0; \
+ } \
+ param_idx++;
+
+#define DEF_OPTION(NAME, DESC, TYPE, FMT, DEFAULT) param_idx++;
+
+#define DEF_UNIT_OPTION(UNIT, NAME, DESC, TYPE, FMT, DEFAULT) param_idx++;
+
+#include "func_config.def"
+#undef DEF_UNIT_START
+#undef DEF_UNIT_END
+#undef DEF_OPTION
+#undef DEF_UNIT_OPTION
+#undef DEF_OPTION_STR
+#undef DEF_UNIT_OPTION_STR
+ // No match!
+ return 1;
+}
+
+int func_config_print_config_help(FILE* out)
+{
+ fprintf(out, "%-40s %s\n", "Option", "Description");
+ fprintf(out, "%-40s %s\n", "------", "-----------");
+
+ for (uint32_t i = 0; i < CONFIG_PARAMETER_COUNT; i++)
+ {
+ fprintf(out, "-C%-40s %s\n", config_param_str_table[i], config_param_desc_table[i]);
+ }
+
+ fprintf(out, "\n");
+
+ return 0;
+}
+
+int func_model_print_config(func_config_t* func_config, FILE* out)
+{
+#define DEF_UNIT_START(UNIT)
+#define DEF_UNIT_END(UNIT)
+#define DEF_OPTION(NAME, DESC, TYPE, FMT, DEFAULT) fprintf(out, "%-40s = " FMT "\n", #NAME, func_config->NAME);
+#define DEF_UNIT_OPTION(UNIT, NAME, DESC, TYPE, FMT, DEFAULT) \
+ fprintf(out, "%-40s = " FMT "\n", #UNIT "." #NAME, func_config->UNIT.NAME);
+#define DEF_OPTION_STR(NAME, DESC, LEN, DEFAULT) fprintf(out, "%-40s = %s\n", #NAME, func_config->NAME);
+#define DEF_UNIT_OPTION_STR(UNIT, NAME, DESC, LEN, DEFAULT) \
+ fprintf(out, "%-40s = %s\n", #UNIT "." #NAME, func_config->UNIT.NAME);
+
+#define FOF_HEX "0x%llx"
+#define FOF_DEC "%" PRIu32
+#define FOF_DECU64 "%" PRIu64
+
+#include "func_config.def"
+#undef DEF_UNIT_START
+#undef DEF_UNIT_END
+#undef DEF_OPTION
+#undef DEF_UNIT_OPTION
+#undef DEF_OPTION_STR
+#undef DEF_UNIT_OPTION_STR
+
+ return 0;
+}
+
+static const char* programname;
+
+void func_model_print_debug_masks(FILE* out)
+{
+ fprintf(out, "\t List of components:\n");
+#define DEBUG_MODE(string, value) fprintf(out, "\t\t" #string "\n");
+#include "debug_modes.def"
+#undef DEBUG_MODE
+}
+
+int func_model_print_help(FILE* out)
+{
+ fprintf(out, "TOSA Reference Model help\n\n");
+
+ fprintf(out,
+ "Usage: %s [-c] [-C <name=value>] [-d <Debug Mask>] [-h] [-i <uscriptfile>] [-l <verbosity>] [-F "
+ "<flatconfig>]\n",
+ programname);
+ fprintf(out, "\t-c - Print list of config options\n");
+ fprintf(out, "\t-C <name=value> - modify config option <name> to <value>\n");
+ fprintf(out, "\t-d <Debug Mask - set component debug mask\n");
+ func_model_print_debug_masks(out);
+ fprintf(out, "\t-F <flatconfig> - parse <flatconfig> as file of config options\n");
+ fprintf(out, "\t-h - show this help message and exit\n");
+ fprintf(
+ out,
+ "\t-i <input_tensor_name>,<filename> - set input tensor <input_tensor_name> to the values from <filename>\n");
+ fprintf(out, "\t-l <verbosity> - set log verbosity\n");
+ fprintf(out, "\t-o <debuglog> - set debug log file\n");
+ fprintf(out, "\n");
+
+ func_config_print_config_help(stdout);
+
+ return 0;
+}
+
+static const char* get_arg_text(int& index, const int argc, const char** argv)
+{
+ if (strlen(argv[index]) > 2)
+ {
+ return argv[index] + 2;
+ }
+
+ if ((index + 1 == argc) || (argv[index + 1][0] == '-'))
+ {
+ fprintf(stderr, "No option value found for option %s\n", argv[index]);
+ return "";
+ }
+
+ index++;
+ return argv[index];
+}
+
+// Read the command line arguments
+int func_model_parse_cmd_line(func_config_t* func_config, func_debug_t* func_debug, const int argc, const char** argv)
+{
+ int i;
+ programname = argv[0];
+ for (i = 1; i < argc; i++)
+ {
+ // All command line arguments must begin with -X where X is a recognized character
+ if (strlen(argv[i]) < 2 || argv[i][0] != '-')
+ {
+ func_model_print_help(stderr);
+ ARG_ERROR("Command line argument at position %d not valid: %s", i, argv[i]);
+ }
+
+ switch (argv[i][1])
+ {
+ // Model parameters may be overridden with the -Cname=value switch
+ case 'c':
+ func_config_print_config_help(stderr);
+ return 1;
+
+ case 'C':
+ {
+ const char *name = nullptr, *value = nullptr;
+
+ // Break the string into name and value parts
+ name = get_arg_text(i, argc, argv);
+ value = strchr(name, '=');
+
+ if (value == nullptr)
+ {
+ func_model_print_help(stderr);
+ ARG_ERROR("Cannot parse -C argument at position %d: %s", i, argv[i]);
+ }
+
+ *const_cast<char*>(value) = 0;
+
+ if (func_model_config_set_option(func_config, name, value + 1))
+ {
+ func_model_print_help(stderr);
+ ARG_ERROR("Cannot parse -C argument at position %d: %s", i, argv[i]);
+ }
+ break;
+ }
+
+ case 'd':
+ case 'D':
+ {
+ func_debug_set_mask(func_debug, get_arg_text(i, argc, argv));
+ break;
+ }
+ case 'F':
+ {
+ // Read a flat configuration file
+ if (func_model_parse_flat_config_file(func_config, get_arg_text(i, argc, argv)))
+ return 1;
+
+ break;
+ }
+ case 'h':
+ func_model_print_help(stderr);
+ return 1;
+
+ case 'i':
+ {
+ // shortcut for '-Cinput_tensor='
+ if (func_model_config_set_option(func_config, "input_tensor", get_arg_text(i, argc, argv)))
+ {
+ func_model_print_help(stderr);
+ ARG_ERROR("Cannot set input tensor config value");
+ }
+ break;
+ }
+ case 'l':
+ {
+ // Debug verbosity/logging level
+ func_debug_set_verbosity(func_debug, get_arg_text(i, argc, argv));
+ break;
+ }
+ case 'o':
+ {
+ func_debug_set_file(func_debug, get_arg_text(i, argc, argv));
+ break;
+ }
+ default:
+ func_model_print_help(stderr);
+ ARG_ERROR("Unrecognized argument at position %d: %s", i, argv[i]);
+ }
+ }
+
+ return 0;
+}
+
+int func_model_parse_flat_config_file(func_config_t* func_config, const char* filename)
+{
+ const int MAX_LINE_LEN = 1024;
+
+ FILE* infile = nullptr;
+ char line_buf[MAX_LINE_LEN];
+ int line = 1;
+
+ infile = fopen(filename, "r");
+
+ if (infile == nullptr)
+ {
+ ARG_ERROR("Cannot open config file: %s\n", filename);
+ }
+
+ while (fgets(line_buf, MAX_LINE_LEN - 1, infile) != nullptr)
+ {
+ char *name = line_buf, *value = nullptr, *comment = nullptr, *ptr = nullptr;
+
+ // Remove comments
+ comment = strchr(line_buf, '#');
+
+ if (comment)
+ *comment = 0;
+
+ // Break the string into name and value parts
+ name = line_buf;
+
+ // Remove leading whitespace
+ while (*name && isspace(*name))
+ name++;
+
+ // Empty line?
+ if (*name == 0)
+ {
+ line++;
+ continue;
+ }
+
+ value = strchr(name, '=');
+
+ // Missing value
+ if (value == nullptr)
+ {
+ ARG_ERROR("Cannot parse parameter in %s at line %d: %s", filename, line, line_buf);
+ }
+
+ // Remove the =
+ *value = 0;
+ value++;
+
+ // Trim off any whitespace at the end of the value
+ ptr = value;
+ while (*ptr != 0 && !isspace(*ptr))
+ ptr++;
+ *ptr = 0;
+
+ // Include a nested file
+ if (!strcmp(name, "include"))
+ {
+ if (func_model_parse_flat_config_file(func_config, value))
+ return 1;
+ line++;
+ continue;
+ }
+
+ if (func_model_config_set_option(func_config, name, value))
+ {
+ func_model_print_help(stderr);
+ ARG_ERROR("Cannot set parameter in %s at line %d: %s", filename, line, line_buf)
+ }
+
+ line++;
+ }
+
+ fclose(infile);
+
+ return 0;
+}