Simplify the argument parsing and debug code

Change-Id: Ia681aa0eb1d42fa31a4658badb376f7b32b2e338
Signed-off-by: Eric Kunze <eric.kunze@arm.com>
diff --git a/README.md b/README.md
index bbc8ad3..88aeaf2 100644
--- a/README.md
+++ b/README.md
@@ -121,22 +121,22 @@
 
 Note by default, all the files specified by "tosa_file", "ifm_file",
 "ofm_file" are relative to desc.json. This could be overwritten by
--Cflatbuffer_dir=, if desired.
+--flatbuffer_dir=, if desired.
 
 An example command is shown below:
 
 ``` bash
 ./build/reference_model/tosa_reference_model \
-  -Ctest_desc=examples/test_add_1x4x4x4_f32/flatbuffer-tflite/desc.json
+  --test_desc=examples/test_add_1x4x4x4_f32/flatbuffer-tflite/desc.json
 ```
 
 Instead of drive model by JSON test descriptor, user can also drive model
-with -Ctosa_file=, -Cifm_name=, -Cifm_file=, -Cofm_name=, -Cofm_file=
+with --tosa_file=, --ifm_name=, --ifm_file=, --ofm_name=, --ofm_file=
 options directly.
 
-In case where -Ctest_desc= and other options are specified at the same time,
+In case where --test_desc= and other options are specified at the same time,
 JSON test descriptor will be initialized first. All other options
-(-Ctosa_file=, -Cifm_name=, -Cifm_file=, -Cofm_name=, -Cofm_file=) will
+(--tosa_file=, --ifm_name=, --ifm_file=, --ofm_name=, --ofm_file=) will
 overwrite whatever specified by JSON descriptor.
 
 On a successful execution, the output tensors will be written in NumPy
@@ -145,16 +145,16 @@
 For example, you can generate new output .npy by:
 ``` bash
 ./build/reference_model/tosa_reference_model \
-  -Ctest_desc=examples/test_add_1x4x4x4_f32/flatbuffer-tflite/desc.json
-  -Cofm_file=out.npy
+  --test_desc=examples/test_add_1x4x4x4_f32/flatbuffer-tflite/desc.json
+  --ofm_file=out.npy
 ```
 
 In this case, the "ofm_file" field in desc.json will be ignored, and the
-one specified by -Cofm_file= will be picked.
+one specified by --ofm_file= will be picked.
 
 When using JSON-formatted FlatBuffers input (.json extension), the
 FlatBuffers schema file from the TOSA Serialization library must be
-specified using -Coperator_fbs=.  When using the binary FlatBuffers
+specified using --operator_fbs=.  When using the binary FlatBuffers
 format (.tosa), the schema is not necessary.
 
 ### Examples
diff --git a/examples/run_ref_model_examples.sh b/examples/run_ref_model_examples.sh
new file mode 100755
index 0000000..5762021
--- /dev/null
+++ b/examples/run_ref_model_examples.sh
@@ -0,0 +1,25 @@
+#!/bin/bash -x
+set -e
+
+run_test()
+{
+   TEST=$1; shift
+   FRAMEWORK=$1; shift
+
+   echo "####  RUNNING EXAMPLE ${FRAMEWORK} ${TEST}"
+
+   # Assumes the reference model is already built in ../build
+
+   ../build/reference_model/tosa_reference_model \
+      --test_desc=examples/${TEST}/flatbuffer-${FRAMEWORK}/desc.json \
+      --ofm_file=out.npy
+    python3 -c "import sys; import numpy as np; a = np.load(sys.argv[1]); b = np.load(sys.argv[2]); sys.exit(int((a != b).all()));" \
+        examples/${TEST}/${FRAMEWORK}_result.npy \
+        examples/${TEST}/flatbuffer-${FRAMEWORK}/out.npy
+}
+
+run_test test_add_1x4x4x4_f32 tf
+run_test test_add_1x4x4x4_f32 tflite
+run_test test_conv2d_1x1_1x32x32x8_f32_st11_padSAME_dilat11 tf
+run_test test_conv2d_1x1_1x32x32x8_f32_st11_padSAME_dilat11 tflite
+run_test test_conv2d_1x1_1x32x32x8_qi8_st11_padSAME_dilat11 tflite
diff --git a/reference_model/CMakeLists.txt b/reference_model/CMakeLists.txt
index 40d83f2..6fdaa1c 100644
--- a/reference_model/CMakeLists.txt
+++ b/reference_model/CMakeLists.txt
@@ -71,6 +71,7 @@
   PRIVATE
     tosa_serialization_lib
     nlohmann_json::nlohmann_json
+    cxxopts
 )
 
 install (TARGETS tosa_reference_model DESTINATION bin)
diff --git a/reference_model/src/func_config.cc b/reference_model/src/func_config.cc
index a17fdef..6bd809e 100644
--- a/reference_model/src/func_config.cc
+++ b/reference_model/src/func_config.cc
@@ -13,6 +13,7 @@
 //    See the License for the specific language governing permissions and
 //    limitations under the License.
 
+#include <cxxopts.hpp>
 #include <ctype.h>
 #include <signal.h>
 #include <stdarg.h>
@@ -25,615 +26,83 @@
 #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] [-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-v - Print refererence model version\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, const char* version)
+    func_config_t& func_config, func_debug_t& func_debug, int argc, char** argv, const char* version)
 {
-    int i;
-    programname = argv[0];
-    for (i = 1; i < argc; i++)
+    try
     {
-        // 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]);
+        cxxopts::Options options("tosa_reference_model", "The TOSA reference model");
+
+        // clang-format off
+        options.add_options()
+        ("operator_fbs", "Flat buffer schema file", cxxopts::value<std::string>(func_config.operator_fbs), "<schema>")
+        ("test_desc", "Json test descriptor", cxxopts::value<std::string>(func_config.test_desc), "<descriptor>")
+        ("flatbuffer_dir", "Flatbuffer directory to load. If not specified, it will be overwritten by dirname(test_desc)",
+            cxxopts::value<std::string>(func_config.flatbuffer_dir))
+        ("output_dir", "Output directory to write. If not specified, it will be overwritten by dirname(test_desc)",
+            cxxopts::value<std::string>(func_config.output_dir))
+        ("tosa_file", "Flatbuffer file. Support .json or .tosa. Specifying this will overwrite the one initialized by --test_desc.",
+            cxxopts::value<std::string>(func_config.tosa_file))
+        ("ifm_name", "Input tensor name. Comma(,) separated. Specifying this will overwrite the one initialized by --test_desc.",
+            cxxopts::value<std::string>(func_config.ifm_name))
+        ("ifm_file", "Input tensor numpy Comma(,) separated. file to initialize with placeholder. Specifying this will overwrite the one initialized by --test_desc.",
+            cxxopts::value<std::string>(func_config.ifm_file))
+        ("ofm_name", "Output tensor name. Comma(,) seperated. Specifying this will overwrite the one initialized by --test_desc.",
+            cxxopts::value<std::string>(func_config.ofm_name))
+        ("ofm_file", "Output tensor numpy file to be generated. Comma(,) seperated. Specifying this will overwrite the one initialized by --test_desc.",
+            cxxopts::value<std::string>(func_config.ofm_file))
+        ("eval", "Evaluate the network (0/1)", cxxopts::value<uint32_t>(func_config.eval))
+        ("fp_format", "Floating-point number dump format string (printf-style format, e.g. 0.5)",
+            cxxopts::value<std::string>(func_config.fp_format))
+        ("validate_only", "Validate the network, but do not read inputs or evaluate (0/1)",
+            cxxopts::value<uint32_t>(func_config.validate_only))
+        ("output_tensors", "Output tensors to a file (0/1)", cxxopts::value<uint32_t>(func_config.output_tensors))
+        ("tosa_profile", "Set TOSA profile (0 = Base Inference, 1 = Main Inference, 2 = Main Training)",
+            cxxopts::value<uint32_t>(func_config.tosa_profile))
+        ("dump_intermediates", "Dump intermediate tensors (0/1)", cxxopts::value<uint32_t>(func_config.dump_intermediates))
+        ("v,version", "print model version")
+        ("i,input_tensor_file", "specify input tensor files", cxxopts::value<std::vector<std::string>>())
+        ("l,loglevel", func_debug.get_debug_verbosity_help_string(), cxxopts::value<std::string>())
+        ("o,logfile", "output log file", cxxopts::value<std::string>())
+        ("d,debugmask", func_debug.get_debug_mask_help_string(), cxxopts::value<std::vector<std::string>>())
+        ("h,help", "print help");
+        // clang-format on
+
+        auto result = options.parse(argc, argv);
+        if (result.count("help")) {
+            std::cout << options.help() << std::endl;
+            return 1;
         }
-
-        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;
-            }
-            case 'v':
-            {
-                fprintf(stdout, "Model Version %s\n", version);
-                return 1;
-            }
-            default:
-                func_model_print_help(stderr);
-                ARG_ERROR("Unrecognized argument at position %d: %s", i, argv[i]);
+        if (result.count("debugmask")) {
+            auto& v = result["debugmask"].as<std::vector<std::string>>();
+            for (const std::string& s : v)
+                func_debug.set_mask(s);
         }
+        if (result.count("loglevel")) {
+            const std::string& levelstr = result["loglevel"].as<std::string>();
+            func_debug.set_verbosity(levelstr);
+        }
+        if (result.count("logfile")) {
+            func_debug.set_file(result["logfile"].as<std::string>());
+        }
+        if (result.count("input_tensor_file")) {
+            func_config.ifm_name = result["input_tensor_file"].as<std::string>();
+        }
+        if (result.count("version")) {
+            std::cout << "Model version " << version << std::endl;
+        }
+    }
+    catch(const std::exception& e)
+    {
+        std::cerr << e.what() << '\n';
+        return 1;
     }
 
     return 0;
 }
 
-int func_model_parse_flat_config_file(func_config_t* func_config, const char* filename)
+void func_model_print_help()
 {
-    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;
 }
diff --git a/reference_model/src/func_config.def b/reference_model/src/func_config.def
deleted file mode 100644
index cf78ab8..0000000
--- a/reference_model/src/func_config.def
+++ /dev/null
@@ -1,92 +0,0 @@
-
-// 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.
-
-/*
- *   Filename:     src/func_config.def
- *   Description:
- *    Defines the model parameters/options for the functional model.
- */
-
-// Placeholder values for the Functional model Option Formatting (FOF) fields
-//
-//   FOF_DEC is decimal
-//   FOF_HEX is hexidecimal
-//
-// Floating point values are not supported yet, but there is no fundamental reason
-// why we can't have them.
-#ifndef FOF_DEC
-#define FOF_DEC 1
-#endif
-
-#ifndef FOF_HEX
-#define FOF_HEX 1
-#endif
-
-#ifndef FOF_STR_LEN
-#define FOF_STR_LEN 1024
-#endif
-
-// Options are defined as follows:
-// DEF_OPTION() defines a top-level option
-//  Arguments:
-//  option_field_name: a C-syntax field name in the struct
-//  description: a short string that describes the purpose of the option (printed out with help)
-//  C type: the type of the option (typically a uint64_t, uint32_t, etc)
-//  Format field: the FOF_* type used to figure out how to format/print the option
-//  Default value: the default value assigned to the option, if it isn't assigned by an configuration file
-//    or command line override
-
-// For defining hierarchical options (example hierarchy is 'cle', use the following formula).
-// All options within the hierarchical space must be grouped together:
-//
-
-// #define CURRENT_UNIT cle
-// DEF_UNIT_START(CURRENT_UNIT)
-//  DEF_UNIT_OPTION(CURRENT_UNIT,...)
-//  ...
-// DEF_UNIT_END(CURRENT_UNIT)
-// #undef CURRENT_UNIT
-//
-// The CURRENT_UNIT argument is required as a parameter in these definitions because
-// macro processing rules only allow stringification of macro parameters.  Unfortunately,
-// Other tokens that are NOT passed in as macro parameters cannot be stringified.
-
-DEF_OPTION_STR(operator_fbs, "Flat buffer syntax file", FOF_STR_LEN, "tosa.fbs")
-DEF_OPTION_STR(test_desc, "Json test descriptor", FOF_STR_LEN, "desc.json")
-DEF_OPTION_STR(flatbuffer_dir, "Flatbuffer directory to load. If not specified, it will be overwritten by dirname(test_desc)", FOF_STR_LEN, "")
-DEF_OPTION_STR(output_dir, "Output directory to write. If not specified, it will be overwritten by dirname(test_desc)", FOF_STR_LEN, "")
-DEF_OPTION_STR(tosa_file, "Flatbuffer file. Support .json or .tosa. Specifying this will overwrite the one initialized by -Ctest_desc.", FOF_STR_LEN, "")
-DEF_OPTION_STR(ifm_name, "Input tensor name. Comma(,) seperated. Specifying this will overwrite the one initialized by -Ctest_desc.", FOF_STR_LEN, "")
-DEF_OPTION_STR(ifm_file, "Input tensor numpy Comma(,) seperated. file to initialize with placeholder. Specifying this will overwrite the one initialized by -Ctest_desc.", FOF_STR_LEN, "")
-DEF_OPTION_STR(ofm_name, "Output tensor name. Comma(,) seperated. Specifying this will overwrite the one initialized by -Ctest_desc.", FOF_STR_LEN, "")
-DEF_OPTION_STR(ofm_file, "Output tensor numpy file to be generated. Comma(,) seperated. Specifying this will overwrite the one initialized by -Ctest_desc.", FOF_STR_LEN, "")
-DEF_OPTION(eval, "Evaluate the network (0/1)", uint32_t, FOF_DEC, 1)
-DEF_OPTION(validate_only, "Validate the network, but do not read inputs or evaluate (0/1)", uint32_t, FOF_DEC, 0)
-DEF_OPTION(output_tensors, "Output tensors to a file (0/1)", uint32_t, FOF_DEC, 1)
-DEF_OPTION(tosa_profile, "Set TOSA profile (0 = Base Inference, 1 = Main Inference, 2 = Main Training)", uint32_t, FOF_DEC, 1)
-DEF_OPTION(dump_intermediates, "Dump intermediate tensors (0/1)", uint32_t, FOF_DEC, 0)
-DEF_OPTION_STR(fp_format, "Floating-point number dump format string (printf-style format, e.g. 0.5)", FOF_STR_LEN, "0.5")
-// Example of a hierarchical option
-//#define CURRENT_UNIT arch
-//DEF_UNIT_START(arch)
-//DEF_UNIT_OPTION(arch, ifm_width, "input feature map width(x dim)", uint32_t, FOF_DEC, 10)
-//DEF_UNIT_END(CURRENT_UNIT)
-///#undef CURRENT_UNIT
-
-// START Do not delete
-// Required for keeping the FOFs clean
-#undef FOF_DEC
-#undef FOF_HEX
-// END Do not delete^^
diff --git a/reference_model/src/func_config.h b/reference_model/src/func_config.h
index 33cc1b1..49f03e9 100644
--- a/reference_model/src/func_config.h
+++ b/reference_model/src/func_config.h
@@ -1,5 +1,5 @@
 
-// Copyright (c) 2020, ARM Limited.
+// Copyright (c) 2020-2022, ARM Limited.
 //
 //    Licensed under the Apache License, Version 2.0 (the "License");
 //    you may not use this file except in compliance with the License.
@@ -16,40 +16,31 @@
 #ifndef FUNC_CONFIG_H_
 #define FUNC_CONFIG_H_
 
-// Parameter value structure
-#define DEF_UNIT_START(UNIT)                                                                                           \
-    struct UNIT##_t                                                                                                    \
-    {
-#define DEF_UNIT_END(UNIT)                                                                                             \
-    }                                                                                                                  \
-    UNIT;
-#define DEF_OPTION(NAME, DESC, TYPE, FMT, DEFAULT) TYPE NAME;
-#define DEF_OPTION_STR(NAME, DESC, LEN, DEFAULT) char NAME[LEN];
-#define DEF_UNIT_OPTION(UNIT, NAME, DESC, TYPE, FMT, DEFAULT) TYPE NAME;
-#define DEF_UNIT_OPTION_STR(UNIT, NAME, DESC, LEN, DEFAULT) char NAME[LEN];
 struct func_config_t
 {
-#include "func_config.def"
-#undef DEF_UNIT_START
-#undef DEF_UNIT_END
-#undef DEF_OPTION
-#undef DEF_OPTION_STR
-#undef DEF_UNIT_OPTION
-#undef DEF_UNIT_OPTION_STR
+    std::string operator_fbs = "tosa.fbs";
+    std::string test_desc    = "desc.json";
+    std::string flatbuffer_dir = "";
+    std::string output_dir = "";
+    std::string tosa_file = "";
+    std::string ifm_name = "";
+    std::string ifm_file = "";
+    std::string ofm_name = "";
+    std::string ofm_file = "";
+    uint32_t eval               = 1;
+    uint32_t validate_only      = 0;
+    uint32_t output_tensors     = 1;
+    uint32_t tosa_profile       = 1;
+    uint32_t dump_intermediates = 0;
+    std::string fp_format       = "0.5";
 };
 
 // Forward declaration
 struct func_debug_t;
 
-int func_model_init_config();
-int func_model_set_default_config(func_config_t*);
-int func_model_config_set_option(func_config_t*, const char* name, const char* value);
-int func_model_print_config(func_config_t*, FILE* out);
-int func_model_parse_cmd_line(func_config_t*, func_debug_t* func_debug, const int argc, const char** argv, const char* version);
+int func_model_parse_cmd_line(
+    func_config_t& func_config, func_debug_t& func_debug, int argc, char** argv, const char* version);
 int func_model_parse_flat_config_file(func_config_t*, const char* filename);
-int func_model_config_cleanup();
-int func_model_config_get_str_option_by_name(func_config_t*, const char* name, char* value, const uint32_t len);
-int func_model_config_get_option_by_name(func_config_t*, const char* name, uint64_t* val);
-int func_model_print_help(FILE* out);
+void func_model_print_help();
 
 #endif
diff --git a/reference_model/src/func_debug.cc b/reference_model/src/func_debug.cc
index f5f045e..755f79f 100644
--- a/reference_model/src/func_debug.cc
+++ b/reference_model/src/func_debug.cc
@@ -20,6 +20,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
+#include <sstream>
 
 #ifndef _MSC_VER
 #include <execinfo.h>
@@ -33,6 +34,12 @@
 
 #define MAX_FRAMES 100
 
+static bool str_case_equal(const std::string& a, const std::string& b)
+{
+    return std::equal(a.begin(), a.end(), b.begin(), b.end(),
+                      [](char ac, char bc) { return tolower(ac) == tolower(bc); });
+}
+
 #ifndef _MSC_VER
 pid_t func_print_backtrace_helper(int num_tries, int sig);
 #endif
@@ -144,113 +151,63 @@
     }
 }
 
-const char* func_debug_mode_str_table[] = {
-#define DEBUG_MODE(NAME, BIT) #NAME,
-#include "debug_modes.def"
-#undef DEBUG_MODE
+static const std::vector<std::pair<std::string, uint32_t>> func_debug_verbosity_table = {
+    { "NONE", DEBUG_VERB_NONE }, { "INFO", DEBUG_VERB_INFO }, { "IFACE", DEBUG_VERB_IFACE },
+    { "LOW", DEBUG_VERB_LOW },   { "MED", DEBUG_VERB_MED },   { "HIGH", DEBUG_VERB_HIGH }
 };
 
-#define DEBUG_MASK_COUNT (sizeof(func_debug_mode_str_table) / sizeof(const char*))
-
-const char* func_debug_verbosity_str_table[] = { "NONE", "INFO", "IFACE", "LOW", "MED", "HIGH" };
-
-const uint32_t func_debug_verbosity_mask_table[] = { DEBUG_VERB_NONE, DEBUG_VERB_INFO, DEBUG_VERB_IFACE,
-                                                     DEBUG_VERB_LOW,  DEBUG_VERB_MED,  DEBUG_VERB_HIGH };
-
-#define DEBUG_VERBOSITY_COUNT (sizeof(func_debug_verbosity_str_table) / sizeof(const char*))
-
 // Initialize the debug mode
-int func_init_debug(func_debug_t* func_debug, uint64_t inst_id)
+int func_debug_t::init_debug(uint64_t inst_id)
 {
     // Set the default debug settings
-    bzero(func_debug, sizeof(func_debug_t));
-    func_debug_set_mask(func_debug, DEBUG_NONE);
-    func_debug_set_verbosity(func_debug, DEBUG_VERB_NONE);
-    func_debug_set_inst_mask(func_debug, DEBUG_INST_ALL);
-    func_debug->func_debug_file = stderr;
-    func_debug_set_captured_warnings(func_debug, 0);
-    func_debug_set_output_unbuffered(func_debug, false);
-    func_debug->inst_id = inst_id;
+    set_mask(static_cast<uint64_t>(DEBUG_NONE));
+    set_verbosity(DEBUG_VERB_NONE);
+    set_inst_mask(DEBUG_INST_ALL);
+    func_debug_file = stderr;
+    this->inst_id = inst_id;
 
     return 0;
 }
 
-int func_fini_debug(func_debug_t* func_debug)
+int func_debug_t::fini_debug()
 {
-    if (func_debug->record_warnings)
-    {
-        func_debug_set_captured_warnings(func_debug, 0);
-    }
-
-#ifndef _FUNC_INCLUDE_WINDOWS_SUPPORT_H
-    if (func_debug->is_gzip && func_debug->func_debug_file)
-    {
-        pclose(func_debug->func_debug_file);
-        func_debug->func_debug_file = NULL;
-    }
-#endif
-
     return 0;
 }
 
-int func_debug_set_file(func_debug_t* func_debug, const char* filename)
+int func_debug_t::set_file(const std::string& filename)
 {
-    int filenameLen = strlen(filename);
-
     // Open the debug output file
-    ASSERT(filename != NULL);
-#ifndef _FUNC_INCLUDE_WINDOWS_SUPPORT_H
-    if (filenameLen > 3 && strcmp(filename + filenameLen - 3, ".gz") == 0)
-    {
-        char cmd[256];
+    func_debug_file = fopen(filename.c_str(), "w");
 
-        snprintf(cmd, sizeof(cmd), "gzip > %s", filename);
-        func_debug->func_debug_file = popen(cmd, "w");
-        func_debug->is_gzip         = 1;
-    }
-    else
-    {
-#else
-    {
-#endif
-        func_debug->func_debug_file = fopen(filename, "w");
-    }
-
-    if (!func_debug->func_debug_file)
+    if (!func_debug_file)
     {
         perror(NULL);
-        FATAL_ERROR("Cannot open debug output file: %s\n", filename);
+        FATAL_ERROR("Cannot open debug output file: %s\n", filename.c_str());
         return 1;
     }
-    if (func_debug->is_output_unbuffered)
+    if (is_output_unbuffered)
     {
-        setvbuf(func_debug->func_debug_file, nullptr, _IONBF, 0);
+        setvbuf(func_debug_file, nullptr, _IONBF, 0);
     }
 
     return 0;
 }
 
-void func_debug_set_verbosity(func_debug_t* func_debug, const char* str)
+void func_debug_t::set_verbosity(const std::string& str)
 {
-    if (!strcasecmp(str, "RESET"))
+    for (auto& verb : func_debug_verbosity_table)
     {
-        func_debug_set_verbosity(func_debug, DEBUG_VERB_NONE);
-        return;
-    }
-
-    for (size_t i = 0; i < DEBUG_VERBOSITY_COUNT; i++)
-    {
-        if (!strcasecmp(str, func_debug_verbosity_str_table[i]))
+        if (str_case_equal(str, verb.first))
         {
-            func_debug_set_verbosity(func_debug, func_debug_verbosity_mask_table[i]);
+            set_verbosity(verb.second);
             return;
         }
     }
 
-    FATAL_ERROR("Invalid debug verbosity: %s", str);
+    FATAL_ERROR("Invalid debug verbosity: %s", str.c_str());
 }
 
-void func_debug_set_verbosity(func_debug_t* func_debug, const uint32_t verb)
+void func_debug_t::set_verbosity(const uint32_t verb)
 {
     uint32_t new_mask = verb;
 
@@ -278,81 +235,76 @@
             break;
     }
 
-    func_debug->func_debug_verbosity = new_mask;
+    func_debug_verbosity = new_mask;
 }
 
-void func_debug_set_suppress_arch_error_mask(func_debug_t* func_debug, const uint32_t suppress)
-{
-    func_debug->func_suppress_arch_error_mask = suppress;
-}
-
-void func_debug_set_mask(func_debug_t* func_debug, const uint64_t mask)
+void func_debug_t::set_mask(const uint64_t mask)
 {
     if (mask == DEBUG_NONE)
-        func_debug->func_debug_mask = mask;
+        func_debug_mask = mask;
     else
-        func_debug->func_debug_mask |= mask;
+        func_debug_mask |= mask;
 
     // Set a minimum verbosity level
-    if (func_debug->func_debug_verbosity == DEBUG_VERB_NONE)
-        func_debug->func_debug_verbosity = DEBUG_VERB_INFO;
+    if (func_debug_verbosity == DEBUG_VERB_NONE)
+        func_debug_verbosity = DEBUG_VERB_INFO;
 }
 
-void func_debug_set_inst_mask(func_debug_t* func_debug, const char* mask)
+void func_debug_t::set_inst_mask(const char* mask)
 {
     uint64_t val;
 
     val = strtoul(mask, NULL, 0);
 
-    return func_debug_set_inst_mask(func_debug, val);
+    return set_inst_mask(val);
 }
 
-void func_debug_set_inst_mask(func_debug_t* func_debug, const uint64_t mask)
+void func_debug_t::set_inst_mask(const uint64_t mask)
 {
     if (mask == 0)
-        func_debug->func_debug_inst_mask = DEBUG_INST_ALL;
+        func_debug_inst_mask = DEBUG_INST_ALL;
     else
-        func_debug->func_debug_inst_mask = mask;
+        func_debug_inst_mask = mask;
 }
 
-void func_debug_set_mask(func_debug_t* func_debug, const char* str)
+std::vector<std::pair<std::string, int>> debug_str_table = {
+#define DEBUG_MODE(NAME, BIT) {#NAME, BIT},
+#include "debug_modes.def"
+#undef DEBUG_MODE
+};
+
+void func_debug_t::set_mask(const std::string& str)
 {
-    if (!strcasecmp(str, "all"))
+    if (str == "all")
     {
-        func_debug_set_mask(func_debug, UINT64_MAX - 1);
+        set_mask(UINT64_MAX - 1);
         return;
     }
-
-    size_t i;
-    for (i = 0; i < DEBUG_MASK_COUNT; i++)
+    for (auto& mode : debug_str_table)
     {
-        if (!strcasecmp(str, func_debug_mode_str_table[i]))
+        if (mode.first == str)
         {
-            func_debug_set_mask(func_debug, 1ULL << i);
+            set_mask(mode.second);
             return;
         }
     }
+    print_masks(stderr);
 
-    func_debug_print_masks(stderr);
-
-    FATAL_ERROR("Invalid debug mask: %s", str);
+    FATAL_ERROR("Invalid debug mask: %s", str.c_str());
 }
 
-void func_debug_print_masks(FILE* out)
+void func_debug_t::print_masks(FILE* out)
 {
-    uint32_t i;
-
     fprintf(out, "Available debug masks:\n");
-
-    for (i = 0; i < DEBUG_MASK_COUNT; i++)
+    for (auto& mode : debug_str_table)
     {
-        fprintf(out, "[%d] %s\n", i, func_debug_mode_str_table[i]);
+        fprintf(out, "[%d] %s\n", mode.second, mode.first.c_str());
     }
 }
 
-void func_debug_set_output_unbuffered(func_debug_t* func_debug, const bool is_unbuffered)
+void func_debug_t::set_output_unbuffered(const bool is_unbuffered)
 {
-    func_debug->is_output_unbuffered = is_unbuffered;
+    is_output_unbuffered = is_unbuffered;
 }
 
 // Print warnings to the debug file or optionally store them in a buffer instead
@@ -364,73 +316,29 @@
     va_list args;
     va_start(args, fmt);
 
-    if (func_debug->record_warnings)
-    {
-        // Record to the circular buffer
-        uint32_t len;
+    // Print to the debug file (e.g., stderr)
+    fprintf(func_debug->func_debug_file, "WARNING AT %s:%d %s():\n", file, line, func);
+    vfprintf(func_debug->func_debug_file, fmt, args);
+    fprintf(func_debug->func_debug_file, "\n");
 
-        len = snprintf(func_debug->warning_buffer[func_debug->warning_buffer_tail], WARNING_BUFFER_ENTRY_LENGTH,
-                       "WARNING AT %s:%d %s(): ", file, line, func);
-        vsnprintf(func_debug->warning_buffer[func_debug->warning_buffer_tail] + len, WARNING_BUFFER_ENTRY_LENGTH - len,
-                  fmt, args);
-        func_debug->warning_buffer_tail = (func_debug->warning_buffer_tail + 1) % WARNING_BUFFER_SIZE;
-    }
-    else
-    {
-        // Print to the debug file (e.g., stderr)
-        fprintf(func_debug->func_debug_file, "WARNING AT %s:%d %s():\n", file, line, func);
-        vfprintf(func_debug->func_debug_file, fmt, args);
-        fprintf(func_debug->func_debug_file, "\n");
-    }
     va_end(args);
 }
 
-// Initialize the warning buffer capture
-int func_debug_set_captured_warnings(func_debug_t* func_debug, uint32_t capture)
+std::string func_debug_t::get_debug_mask_help_string()
 {
-    uint32_t i;
-    func_debug->record_warnings = capture;
-    if (capture)
-    {
-        func_debug->warning_buffer_head = 0;
-        func_debug->warning_buffer_tail = 0;
-
-        for (i = 0; i < WARNING_BUFFER_SIZE; i++)
-        {
-            func_debug->warning_buffer[i] = (char*)calloc(1, WARNING_BUFFER_ENTRY_LENGTH);
-        }
+    std::string rval = "Set debug mask. Valid values are: ";
+    for (auto& mask : debug_str_table) {
+        rval += mask.first + " ";
     }
-    else
+    return rval;
+}
+
+std::string func_debug_t::get_debug_verbosity_help_string()
+{
+    std::string rval = "Set logging level. Valid values are: ";
+    for (auto& verb : func_debug_verbosity_table)
     {
-        for (i = 0; i < WARNING_BUFFER_SIZE; i++)
-        {
-            if (func_debug->warning_buffer[i])
-            {
-                free(func_debug->warning_buffer[i]);
-                func_debug->warning_buffer[i] = NULL;
-            }
-        }
+        rval += verb.first + " ";
     }
-
-    return 0;
-}
-
-int func_debug_has_captured_warning(func_debug_t* func_debug)
-{
-    if (func_debug->record_warnings && func_debug->warning_buffer_head != func_debug->warning_buffer_tail)
-        return 1;
-    else
-        return 0;
-}
-
-int func_debug_get_captured_warning(func_debug_t* func_debug, char* buf_ptr, const uint32_t buf_len)
-{
-    if (!func_debug_has_captured_warning(func_debug))
-        return 1;
-
-    strncpy(buf_ptr, func_debug->warning_buffer[func_debug->warning_buffer_head], buf_len);
-
-    func_debug->warning_buffer_head = (func_debug->warning_buffer_head + 1) % WARNING_BUFFER_SIZE;
-
-    return 0;
-}
+    return rval;
+}
\ No newline at end of file
diff --git a/reference_model/src/func_debug.h b/reference_model/src/func_debug.h
index f2790a4..ee89935 100644
--- a/reference_model/src/func_debug.h
+++ b/reference_model/src/func_debug.h
@@ -21,15 +21,12 @@
 #include <cinttypes>
 #include <signal.h>
 #include <stdio.h>
+#include <vector>
 
 void func_print_backtrace(FILE* out, int sig = SIGABRT);
 
 void func_enable_signal_handlers();
 
-// Debug content container
-#define WARNING_BUFFER_SIZE 16
-#define WARNING_BUFFER_ENTRY_LENGTH 1024
-
 // STRINGIFY2 is needed expand expression passed to STRINGIFY
 #define STRINGIFY2(s) #s
 #define STRINGIFY(s) STRINGIFY2(s)
@@ -62,18 +59,26 @@
 
 struct func_debug_t
 {
-    uint32_t func_debug_verbosity;             // What verbosity level is set? (bitmask)
-    uint64_t func_debug_mask;                  // Which units have debugging enabled? (bitmask)
-    uint64_t func_debug_inst_mask;             // Which instances have debugging enabled (bitmask)
-    uint64_t inst_id;                          // The instance id for multiple model instances
-    uint32_t func_suppress_arch_error_mask;    // Which architecture error should be suppressed? (bitmask)
-    FILE* func_debug_file;                     // Output file
-    uint32_t record_warnings;
-    char* warning_buffer[WARNING_BUFFER_SIZE];
-    uint32_t warning_buffer_head;    // next unread message
-    uint32_t warning_buffer_tail;    // next message to write
-    uint32_t is_gzip;
-    bool is_output_unbuffered;    // should log files be opened with unbuffered I/O.
+    uint32_t func_debug_verbosity = 0;             // What verbosity level is set? (bitmask)
+    uint64_t func_debug_mask = 0;                  // Which units have debugging enabled? (bitmask)
+    uint64_t func_debug_inst_mask = 0;             // Which instances have debugging enabled (bitmask)
+    uint64_t inst_id = 0;                          // The instance id for multiple model instances
+    FILE* func_debug_file = stderr;                     // Output file
+    bool is_output_unbuffered = false;    // should log files be opened with unbuffered I/O.
+
+    int init_debug(uint64_t inst_id);
+    int fini_debug();
+    int set_file(const std::string& filename);
+    void set_mask(const std::string& str);
+    void set_mask(const uint64_t mask);
+    void print_masks(FILE* out);
+    void set_verbosity(const std::string& str);
+    void set_verbosity(const uint32_t verb);
+    void set_inst_mask(const char* mask);
+    void set_inst_mask(const uint64_t mask);
+    void set_output_unbuffered(const bool is_unbuffered);
+    std::string get_debug_mask_help_string();
+    std::string get_debug_verbosity_help_string();
 };
 
 #ifndef ASSERT
@@ -157,11 +162,7 @@
     fprintf(stderr, COL_WARN(fmt) "\n", ##__VA_ARGS__);
 #endif
 
-int func_debug_set_captured_warnings(func_debug_t* func_debug, uint32_t capture);
 
-int func_debug_has_captured_warning(func_debug_t* func_debug);
-
-int func_debug_get_captured_warning(func_debug_t* func_debug, char* buf_ptr, const uint32_t buf_len);
 
 // Is this debug verbosity and unit level enabled?
 // Provide compiler hints that this is unlikely
@@ -240,17 +241,4 @@
 #define DEBUG_MED(LEVEL, FMT, ...) DEBUG(DEBUG_VERB_MED, LEVEL, COL_MED(FMT), ##__VA_ARGS__)
 #define DEBUG_HIGH(LEVEL, FMT, ...) DEBUG(DEBUG_VERB_HIGH, LEVEL, COL_HIGH(FMT), ##__VA_ARGS__)
 
-int func_init_debug(func_debug_t*, uint64_t inst_id);
-int func_fini_debug(func_debug_t*);
-int func_debug_set_file(func_debug_t*, const char* filename);
-void func_debug_set_mask(func_debug_t*, const char* str);
-void func_debug_set_mask(func_debug_t*, const uint64_t mask);
-void func_debug_print_masks(FILE* out);
-void func_debug_set_verbosity(func_debug_t*, const char* str);
-void func_debug_set_verbosity(func_debug_t*, const uint32_t verb);
-void func_debug_set_suppress_arch_error_mask(func_debug_t*, const uint32_t suppress);
-void func_debug_set_inst_mask(func_debug_t*, const char* mask);
-void func_debug_set_inst_mask(func_debug_t*, const uint64_t mask);
-void func_debug_set_output_unbuffered(func_debug_t*, const bool is_unbuffered);
-
 #endif
diff --git a/reference_model/src/main.cpp b/reference_model/src/main.cpp
index 4dc31e1..db687e0 100644
--- a/reference_model/src/main.cpp
+++ b/reference_model/src/main.cpp
@@ -43,16 +43,14 @@
 int writeFinalTensors(SubgraphTraverser& gt, json test_desc);
 int loadGraph(TosaSerializationHandler& tsh, json test_desc);
 
-int main(int argc, const char** argv)
+int main(int argc, char** argv)
 {
     TosaVersion model_version(MODEL_VERSION_MAJOR, MODEL_VERSION_MINOR, MODEL_VERSION_PATCH, MODEL_VERSION_DRAFT);
 
     // Initialize configuration and debug subsystems
-    func_model_init_config();
-    func_model_set_default_config(&g_func_config);
-    func_init_debug(&g_func_debug, 0);
+    g_func_debug.init_debug(0);
 
-    if (func_model_parse_cmd_line(&g_func_config, &g_func_debug, argc, argv, model_version.to_string().c_str()))
+    if (func_model_parse_cmd_line(g_func_config, g_func_debug, argc, argv, model_version.to_string().c_str()))
     {
         return 1;
     }
@@ -191,8 +189,7 @@
             fprintf(stderr, "Unknown graph status code=%d.\n", (int)main_gt.getGraphStatus());
     }
 
-    func_fini_debug(&g_func_debug);
-    func_model_config_cleanup();
+    g_func_debug.fini_debug();
 
     return (int)main_gt.getGraphStatus();
 }
@@ -201,12 +198,12 @@
 {
     char graph_fullname[1024];
 
-    snprintf(graph_fullname, sizeof(graph_fullname), "%s/%s", g_func_config.flatbuffer_dir,
+    snprintf(graph_fullname, sizeof(graph_fullname), "%s/%s", g_func_config.flatbuffer_dir.c_str(),
              test_desc["tosa_file"].get<std::string>().c_str());
 
     if (strlen(graph_fullname) <= 2)
     {
-        func_model_print_help(stderr);
+        func_model_print_help();
         FATAL_ERROR("Missing required argument: Check \"tosa_file\" in .json specified by -Ctosa_desc=");
     }
 
@@ -225,10 +222,10 @@
 
     if (is_json)
     {
-        if (tsh.LoadFileSchema(g_func_config.operator_fbs))
+        if (tsh.LoadFileSchema(g_func_config.operator_fbs.c_str()))
         {
             FATAL_ERROR("\nJSON file detected.  Unable to load TOSA flatbuffer schema from: %s\nCheck -Coperator_fbs=",
-                        g_func_config.operator_fbs);
+                        g_func_config.operator_fbs.c_str());
         }
 
         if (tsh.LoadFileJson(graph_fullname))
@@ -260,7 +257,7 @@
     {
         if ((tensorCount != (int)test_desc["ifm_name"].size()) || (tensorCount != (int)test_desc["ifm_file"].size()))
         {
-            WARNING("Number of input tensors(%d) doesn't match name(%ld)/file(%ld)in test descriptor.", tensorCount,
+            WARNING("Number of input tensors(%d) doesn't match name(%ld)/file(%ld) in test descriptor.", tensorCount,
                     test_desc["ifm_name"].size(), test_desc["ifm_file"].size());
             return 1;
         }
@@ -274,7 +271,7 @@
                 return 1;
             }
 
-            snprintf(filename, sizeof(filename), "%s/%s", g_func_config.flatbuffer_dir,
+            snprintf(filename, sizeof(filename), "%s/%s", g_func_config.flatbuffer_dir.c_str(),
                      test_desc["ifm_file"][i].get<std::string>().c_str());
 
             DEBUG_MED(GT, "Loading input tensor %s from filename: %s", tensor->getName().c_str(), filename);
@@ -340,7 +337,7 @@
                 return 1;
             }
 
-            snprintf(filename, sizeof(filename), "%s/%s", g_func_config.output_dir,
+            snprintf(filename, sizeof(filename), "%s/%s", g_func_config.output_dir.c_str(),
                      test_desc["ofm_file"][i].get<std::string>().c_str());
 
             DEBUG_MED(GT, "Writing output tensor[%d] %s to filename: %s", i, tensor->getName().c_str(), filename);
@@ -403,63 +400,55 @@
     }
     else
     {
-        WARNING("Cannot open input file: %s", g_func_config.test_desc);
+        WARNING("Cannot open input file: %s", g_func_config.test_desc.c_str());
         return 1;
     }
 
     // Overwrite flatbuffer_dir/output_dir with dirname(g_func_config.test_desc) if it's not specified.
-    std::string flatbuffer_dir_str(g_func_config.flatbuffer_dir);
-    std::string output_dir_str(g_func_config.output_dir);
-    if (flatbuffer_dir_str.empty() || output_dir_str.empty())
+    if (g_func_config.flatbuffer_dir.empty() || g_func_config.output_dir.empty())
     {
-        std::string test_path(g_func_config.test_desc);
-        std::string test_dir = test_path.substr(0, test_path.find_last_of("/\\"));
-        if (flatbuffer_dir_str.empty())
+        std::string test_dir = g_func_config.test_desc.substr(0, g_func_config.test_desc.find_last_of("/\\"));
+        if (g_func_config.flatbuffer_dir.empty())
         {
-            strncpy(g_func_config.flatbuffer_dir, test_dir.c_str(), FOF_STR_LEN);
+            g_func_config.flatbuffer_dir = test_dir;
         }
-        if (output_dir_str.empty())
+        if (g_func_config.output_dir.empty())
         {
-            strncpy(g_func_config.output_dir, test_dir.c_str(), FOF_STR_LEN);
+            g_func_config.output_dir = test_dir;
         }
     }
 
     // Overwrite test_desc["tosa_file"] if -Ctosa_file= specified.
-    std::string tosa_file_str(g_func_config.tosa_file);
-    if (!tosa_file_str.empty())
+    if (!g_func_config.tosa_file.empty())
     {
-        test_desc["tosa_file"] = tosa_file_str;
+        test_desc["tosa_file"] = g_func_config.tosa_file;
     }
 
     // Overwrite test_desc["ifm_name"] if -Cifm_name= specified.
-    std::string ifm_name_str(g_func_config.ifm_name);
-    if (!ifm_name_str.empty())
+    if (!g_func_config.ifm_name.empty())
     {
-        std::vector<std::string> ifm_name_vec = parseFromString(ifm_name_str);
+        std::vector<std::string> ifm_name_vec = parseFromString(g_func_config.ifm_name);
         test_desc["ifm_name"]                 = ifm_name_vec;
     }
 
     // Overwrite test_desc["ifm_file"] if -Cifm_file= specified.
-    std::string ifm_file_str(g_func_config.ifm_file);
-    if (!ifm_file_str.empty())
+    if (!g_func_config.ifm_file.empty())
     {
-        std::vector<std::string> ifm_file_vec = parseFromString(ifm_file_str);
+        std::vector<std::string> ifm_file_vec = parseFromString(g_func_config.ifm_file);
         test_desc["ifm_file"]                 = ifm_file_vec;
     }
 
     // Overwrite test_desc["ofm_name"] if -Cofm_name= specified.
-    std::string ofm_name_str(g_func_config.ofm_name);
-    if (!ofm_name_str.empty())
+    if (!g_func_config.ofm_name.empty())
     {
-        std::vector<std::string> ofm_name_vec = parseFromString(ofm_name_str);
+        std::vector<std::string> ofm_name_vec = parseFromString(g_func_config.ofm_name);
         test_desc["ofm_name"]                 = ofm_name_vec;
     }
 
     // Overwrite test_desc["ofm_file"] if -Cofm_file= specified.
-    std::string ofm_file_str(g_func_config.ofm_file);
-    if (!ofm_file_str.empty())
+    if (!g_func_config.ofm_file.empty())
     {
-        std::vector<std::string> ofm_file_vec = parseFromString(ofm_file_str);
+        std::vector<std::string> ofm_file_vec = parseFromString(g_func_config.ofm_file);
         test_desc["ofm_file"]                 = ofm_file_vec;
     }
 
diff --git a/reference_model/src/tensor.cc b/reference_model/src/tensor.cc
index 36ace48..90aee05 100644
--- a/reference_model/src/tensor.cc
+++ b/reference_model/src/tensor.cc
@@ -2054,8 +2054,8 @@
 template <>
 int TosaReference::Tensor0<float>::dumpTensor(FILE* out) const
 {
-    char fp_fmt[FOF_STR_LEN];
-    snprintf(fp_fmt, FOF_STR_LEN, "[ %%%sf ]\n", g_func_config.fp_format);
+    char fp_fmt[32];
+    snprintf(fp_fmt, sizeof(fp_fmt), "[ %%%sf ]\n", g_func_config.fp_format.c_str());
 
     if (tensor == nullptr)
     {
@@ -2071,8 +2071,8 @@
 template <>
 int TosaReference::Tensor1<float>::dumpTensor(FILE* out) const
 {
-    char fp_fmt[FOF_STR_LEN];
-    snprintf(fp_fmt, FOF_STR_LEN, " %%%sf ", g_func_config.fp_format);
+    char fp_fmt[32];
+    snprintf(fp_fmt, sizeof(fp_fmt), " %%%sf ", g_func_config.fp_format.c_str());
 
     if (tensor == nullptr)
     {
@@ -2093,8 +2093,8 @@
 template <>
 int TosaReference::Tensor2<float>::dumpTensor(FILE* out) const
 {
-    char fp_fmt[FOF_STR_LEN];
-    snprintf(fp_fmt, FOF_STR_LEN, " %%%sf ", g_func_config.fp_format);
+    char fp_fmt[32];
+    snprintf(fp_fmt, sizeof(fp_fmt), " %%%sf ", g_func_config.fp_format.c_str());
 
     if (tensor == nullptr)
     {
@@ -2120,8 +2120,8 @@
 template <>
 int TosaReference::Tensor3<float>::dumpTensor(FILE* out) const
 {
-    char fp_fmt[FOF_STR_LEN];
-    snprintf(fp_fmt, FOF_STR_LEN, " %%%sf ", g_func_config.fp_format);
+    char fp_fmt[32];
+    snprintf(fp_fmt, sizeof(fp_fmt), " %%%sf ", g_func_config.fp_format.c_str());
 
     if (tensor == nullptr)
     {
@@ -2152,8 +2152,8 @@
 template <>
 int TosaReference::Tensor4<float>::dumpTensor(FILE* out) const
 {
-    char fp_fmt[FOF_STR_LEN];
-    snprintf(fp_fmt, FOF_STR_LEN, " %%%sf ", g_func_config.fp_format);
+    char fp_fmt[32];
+    snprintf(fp_fmt, sizeof(fp_fmt), " %%%sf ", g_func_config.fp_format.c_str());
 
     if (tensor == nullptr)
     {
@@ -2189,8 +2189,8 @@
 template <>
 int TosaReference::Tensor5<float>::dumpTensor(FILE* out) const
 {
-    char fp_fmt[FOF_STR_LEN];
-    snprintf(fp_fmt, FOF_STR_LEN, " %%%sf ", g_func_config.fp_format);
+    char fp_fmt[32];
+    snprintf(fp_fmt, sizeof(fp_fmt), " %%%sf ", g_func_config.fp_format.c_str());
 
     if (tensor == nullptr)
     {
@@ -2231,8 +2231,8 @@
 template <>
 int TosaReference::Tensor6<float>::dumpTensor(FILE* out) const
 {
-    char fp_fmt[FOF_STR_LEN];
-    snprintf(fp_fmt, FOF_STR_LEN, " %%%sf ", g_func_config.fp_format);
+    char fp_fmt[32];
+    snprintf(fp_fmt, sizeof(fp_fmt), " %%%sf ", g_func_config.fp_format.c_str());
 
     if (tensor == nullptr)
     {
@@ -2278,8 +2278,8 @@
 template <>
 int TosaReference::Tensor0<int64_t>::dumpTensor(FILE* out) const
 {
-    char i64_fmt[FOF_STR_LEN];
-    snprintf(i64_fmt, FOF_STR_LEN, "[ %%ld ]\n");
+    char i64_fmt[32];
+    snprintf(i64_fmt, sizeof(i64_fmt), "[ %%ld ]\n");
 
     if (tensor == nullptr)
     {
@@ -2295,8 +2295,8 @@
 template <>
 int TosaReference::Tensor1<int64_t>::dumpTensor(FILE* out) const
 {
-    char i64_fmt[FOF_STR_LEN];
-    snprintf(i64_fmt, FOF_STR_LEN, " %%ld ");
+    char i64_fmt[32];
+    snprintf(i64_fmt, sizeof(i64_fmt), " %%ld ");
 
     if (tensor == nullptr)
     {
@@ -2317,8 +2317,8 @@
 template <>
 int TosaReference::Tensor2<int64_t>::dumpTensor(FILE* out) const
 {
-    char i64_fmt[FOF_STR_LEN];
-    snprintf(i64_fmt, FOF_STR_LEN, " %%ld ");
+    char i64_fmt[32];
+    snprintf(i64_fmt, sizeof(i64_fmt), " %%ld ");
 
     if (tensor == nullptr)
     {
@@ -2344,8 +2344,8 @@
 template <>
 int TosaReference::Tensor3<int64_t>::dumpTensor(FILE* out) const
 {
-    char i64_fmt[FOF_STR_LEN];
-    snprintf(i64_fmt, FOF_STR_LEN, " %%ld ");
+    char i64_fmt[32];
+    snprintf(i64_fmt, sizeof(i64_fmt), " %%ld ");
 
     if (tensor == nullptr)
     {
@@ -2376,8 +2376,8 @@
 template <>
 int TosaReference::Tensor4<int64_t>::dumpTensor(FILE* out) const
 {
-    char i64_fmt[FOF_STR_LEN];
-    snprintf(i64_fmt, FOF_STR_LEN, " %%ld ");
+    char i64_fmt[32];
+    snprintf(i64_fmt, sizeof(i64_fmt), " %%ld ");
 
     if (tensor == nullptr)
     {
@@ -2413,8 +2413,8 @@
 template <>
 int TosaReference::Tensor5<int64_t>::dumpTensor(FILE* out) const
 {
-    char i64_fmt[FOF_STR_LEN];
-    snprintf(i64_fmt, FOF_STR_LEN, " %%ld ");
+    char i64_fmt[32];
+    snprintf(i64_fmt, sizeof(i64_fmt), " %%ld ");
 
     if (tensor == nullptr)
     {
@@ -2455,8 +2455,8 @@
 template <>
 int TosaReference::Tensor6<int64_t>::dumpTensor(FILE* out) const
 {
-    char i64_fmt[FOF_STR_LEN];
-    snprintf(i64_fmt, FOF_STR_LEN, " %%ld ");
+    char i64_fmt[32];
+    snprintf(i64_fmt, sizeof(i64_fmt), " %%ld ");
 
     if (tensor == nullptr)
     {
@@ -2502,8 +2502,8 @@
 template <>
 int TosaReference::Tensor0<int32_t>::dumpTensor(FILE* out) const
 {
-    char i32_fmt[FOF_STR_LEN];
-    snprintf(i32_fmt, FOF_STR_LEN, "[ %%d ]\n");
+    char i32_fmt[32];
+    snprintf(i32_fmt, sizeof(i32_fmt), "[ %%d ]\n");
 
     if (tensor == nullptr)
     {
@@ -2519,8 +2519,8 @@
 template <>
 int TosaReference::Tensor1<int32_t>::dumpTensor(FILE* out) const
 {
-    char i32_fmt[FOF_STR_LEN];
-    snprintf(i32_fmt, FOF_STR_LEN, " %%d ");
+    char i32_fmt[32];
+    snprintf(i32_fmt, sizeof(i32_fmt), " %%d ");
 
     if (tensor == nullptr)
     {
@@ -2541,8 +2541,8 @@
 template <>
 int TosaReference::Tensor2<int32_t>::dumpTensor(FILE* out) const
 {
-    char i32_fmt[FOF_STR_LEN];
-    snprintf(i32_fmt, FOF_STR_LEN, " %%d ");
+    char i32_fmt[32];
+    snprintf(i32_fmt, sizeof(i32_fmt), " %%d ");
 
     if (tensor == nullptr)
     {
@@ -2574,8 +2574,8 @@
 template <>
 int TosaReference::Tensor3<int32_t>::dumpTensor(FILE* out) const
 {
-    char i32_fmt[FOF_STR_LEN];
-    snprintf(i32_fmt, FOF_STR_LEN, " %%d ");
+    char i32_fmt[32];
+    snprintf(i32_fmt, sizeof(i32_fmt), " %%d ");
 
     if (tensor == nullptr)
     {
@@ -2612,8 +2612,8 @@
 template <>
 int TosaReference::Tensor4<int32_t>::dumpTensor(FILE* out) const
 {
-    char i32_fmt[FOF_STR_LEN];
-    snprintf(i32_fmt, FOF_STR_LEN, " %%d ");
+    char i32_fmt[32];
+    snprintf(i32_fmt, sizeof(i32_fmt), " %%d ");
 
     if (tensor == nullptr)
     {
@@ -2649,8 +2649,8 @@
 template <>
 int TosaReference::Tensor5<int32_t>::dumpTensor(FILE* out) const
 {
-    char i32_fmt[FOF_STR_LEN];
-    snprintf(i32_fmt, FOF_STR_LEN, " %%d ");
+    char i32_fmt[32];
+    snprintf(i32_fmt, sizeof(i32_fmt), " %%d ");
 
     if (tensor == nullptr)
     {
@@ -2691,8 +2691,8 @@
 template <>
 int TosaReference::Tensor6<int32_t>::dumpTensor(FILE* out) const
 {
-    char i32_fmt[FOF_STR_LEN];
-    snprintf(i32_fmt, FOF_STR_LEN, " %%d ");
+    char i32_fmt[32];
+    snprintf(i32_fmt, sizeof(i32_fmt), " %%d ");
 
     if (tensor == nullptr)
     {
@@ -2738,8 +2738,8 @@
 template <>
 int TosaReference::Tensor0<bool>::dumpTensor(FILE* out) const
 {
-    char bool_fmt[FOF_STR_LEN];
-    snprintf(bool_fmt, FOF_STR_LEN, "[ %%s ]\n");
+    char bool_fmt[32];
+    snprintf(bool_fmt, sizeof(bool_fmt), "[ %%s ]\n");
 
     if (tensor == nullptr)
     {
@@ -2755,8 +2755,8 @@
 template <>
 int TosaReference::Tensor1<bool>::dumpTensor(FILE* out) const
 {
-    char bool_fmt[FOF_STR_LEN];
-    snprintf(bool_fmt, FOF_STR_LEN, " %%s ");
+    char bool_fmt[32];
+    snprintf(bool_fmt, sizeof(bool_fmt), " %%s ");
 
     if (tensor == nullptr)
     {
@@ -2777,8 +2777,8 @@
 template <>
 int TosaReference::Tensor2<bool>::dumpTensor(FILE* out) const
 {
-    char bool_fmt[FOF_STR_LEN];
-    snprintf(bool_fmt, FOF_STR_LEN, " %%s ");
+    char bool_fmt[32];
+    snprintf(bool_fmt, sizeof(bool_fmt), " %%s ");
 
     if (tensor == nullptr)
     {
@@ -2804,8 +2804,8 @@
 template <>
 int TosaReference::Tensor3<bool>::dumpTensor(FILE* out) const
 {
-    char bool_fmt[FOF_STR_LEN];
-    snprintf(bool_fmt, FOF_STR_LEN, " %%s ");
+    char bool_fmt[32];
+    snprintf(bool_fmt, sizeof(bool_fmt), " %%s ");
 
     if (tensor == nullptr)
     {
@@ -2836,8 +2836,8 @@
 template <>
 int TosaReference::Tensor4<bool>::dumpTensor(FILE* out) const
 {
-    char bool_fmt[FOF_STR_LEN];
-    snprintf(bool_fmt, FOF_STR_LEN, " %%s ");
+    char bool_fmt[32];
+    snprintf(bool_fmt, sizeof(bool_fmt), " %%s ");
 
     if (tensor == nullptr)
     {
@@ -2873,8 +2873,8 @@
 template <>
 int TosaReference::Tensor5<bool>::dumpTensor(FILE* out) const
 {
-    char bool_fmt[FOF_STR_LEN];
-    snprintf(bool_fmt, FOF_STR_LEN, " %%s ");
+    char bool_fmt[32];
+    snprintf(bool_fmt, sizeof(bool_fmt), " %%s ");
 
     if (tensor == nullptr)
     {
@@ -2915,8 +2915,8 @@
 template <>
 int TosaReference::Tensor6<bool>::dumpTensor(FILE* out) const
 {
-    char bool_fmt[FOF_STR_LEN];
-    snprintf(bool_fmt, FOF_STR_LEN, " %%s ");
+    char bool_fmt[32];
+    snprintf(bool_fmt, sizeof(bool_fmt), " %%s ");
 
     if (tensor == nullptr)
     {
diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt
index a85af3c..abcc52c 100644
--- a/thirdparty/CMakeLists.txt
+++ b/thirdparty/CMakeLists.txt
@@ -1,8 +1,17 @@
 cmake_minimum_required (VERSION 3.4)
 
+# fetch 3rd party libraries
+include(FetchContent)
+FetchContent_Declare(
+  cxxopts
+  URL               https://github.com/jarro2783/cxxopts/archive/v2.2.1.tar.gz
+  URL_MD5           6e70da4fc17a09f32612443f1866042e
+)
+
 set(CMAKE_INSTALL_PREFIX "./thirdparty" CACHE PATH "..." FORCE)
 
 project(thirdparty LANGUAGES CXX)
 
+add_subdirectory(cxxopts)
 add_subdirectory(serialization_lib EXCLUDE_FROM_ALL)
 add_subdirectory(json EXCLUDE_FROM_ALL)
diff --git a/thirdparty/cxxopts/CMakeLists.txt b/thirdparty/cxxopts/CMakeLists.txt
new file mode 100644
index 0000000..e81bf08
--- /dev/null
+++ b/thirdparty/cxxopts/CMakeLists.txt
@@ -0,0 +1,8 @@
+set(CXXOPTS_BUILD_EXAMPLES OFF CACHE INTERNAL "")
+set(CXXOPTS_BUILD_TESTS OFF CACHE INTERNAL "")
+FetchContent_GetProperties(cxxopts)
+if(NOT cxxopts_POPULATED)
+    FetchContent_Populate(cxxopts)
+    add_subdirectory(${cxxopts_SOURCE_DIR} ${cxxopts_BINARY_DIR} EXCLUDE_FROM_ALL)
+
+endif()
diff --git a/verif/frameworks/tosa_verif_framework_compiler_runner.py b/verif/frameworks/tosa_verif_framework_compiler_runner.py
index 9ea1bff..3597f2a 100755
--- a/verif/frameworks/tosa_verif_framework_compiler_runner.py
+++ b/verif/frameworks/tosa_verif_framework_compiler_runner.py
@@ -518,11 +518,11 @@
         os.path.join(
             args.tools_base_dir, "build", "reference_model", "tosa_reference_model"
         ),
-        "-Ctest_desc={}".format(os.path.join(test, flatbuffer_dir, "desc.json")),
+        "--test_desc={}".format(os.path.join(test, flatbuffer_dir, "desc.json")),
     ]
 
     if args.debug_ref_model:
-        ref_model_cmd.extend(["-DALL", "-lhigh"])
+        ref_model_cmd.extend(["-D ALL", "-l high"])
 
     if args.valgrind:
         ref_model_cmd = [
diff --git a/verif/runner/tosa_refmodel_sut_run.py b/verif/runner/tosa_refmodel_sut_run.py
index 2aeb7b1..2ae7a69 100644
--- a/verif/runner/tosa_refmodel_sut_run.py
+++ b/verif/runner/tosa_refmodel_sut_run.py
@@ -34,16 +34,16 @@
         # Call Reference model with description file to provide all file details
         cmd = [
             args.ref_model_path,
-            "-Coperator_fbs={}".format(args.operator_fbs),
-            "-Ctest_desc={}".format(self.descFile),
+            "--operator_fbs={}".format(args.operator_fbs),
+            "--test_desc={}".format(self.descFile),
         ]
 
         # Specific debug options for reference model
         if args.ref_debug:
-            cmd.extend(["-dALL", "-l{}".format(args.ref_debug)])
+            cmd.extend(["-d ALL", "-l {}".format(args.ref_debug)])
 
         if args.ref_intermediates:
-            cmd.extend(["-Ddump_intermediates=1"])
+            cmd.extend(["-D dump_intermediates=1"])
 
         # Run command and interpret tosa graph result via process return codes
         graphMessage = None