From 9f9e725bc621ce056f657c889107eee02ab0a621 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 5 Apr 2020 00:32:25 -0700 Subject: [PATCH] util: Further consolidate the Args interface in the m5 utility. Create static methods to convert any string to an integer or to pack it into an array of integers. Create non-static methdos named pop() to pop() the first element and simultaneously convert it. If the conversion fails, the argument is not popped. Change-Id: I55d98b3971e7abb7b6206d06ec7fcf046e828d29 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/27553 Reviewed-by: Jason Lowe-Power Reviewed-by: Daniel Carvalho Maintainer: Jason Lowe-Power Tested-by: kokoro --- util/m5/src/args.cc | 25 +------- util/m5/src/args.hh | 106 ++++++++++++++++++++++++++++++++-- util/m5/src/call_type/addr.cc | 5 +- util/m5/src/commands.cc | 67 +++++++++++++-------- 4 files changed, 150 insertions(+), 53 deletions(-) diff --git a/util/m5/src/args.cc b/util/m5/src/args.cc index b6bd1c8f7..1caad4394 100644 --- a/util/m5/src/args.cc +++ b/util/m5/src/args.cc @@ -38,39 +38,20 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include -#include #include #include "args.hh" bool -parse_int_args(Args &args, uint64_t ints[], int len) -{ -// On 32 bit platforms we need to use strtoull to do the conversion -#ifdef __LP64__ -#define strto64 strtoul -#else -#define strto64 strtoull -#endif - for (int i = 0; i < len; ++i) - ints[i] = strto64(args.pop("0").c_str(), NULL, 0); - -#undef strto64 - return true; -} - -bool -pack_arg_into_regs(Args &args, uint64_t regs[], int num_regs) +Args::pack(const std::string &str, uint64_t regs[], int num_regs) { const size_t RegSize = sizeof(regs[0]); const size_t MaxLen = num_regs * RegSize; - const std::string &sarg = args.pop(); - const char *arg = sarg.c_str(); + const char *arg = str.c_str(); memset(regs, 0, MaxLen); - size_t len = sarg.size(); + size_t len = str.size(); if (len > MaxLen) return false; diff --git a/util/m5/src/args.hh b/util/m5/src/args.hh index 1afd2f28a..b541533c5 100644 --- a/util/m5/src/args.hh +++ b/util/m5/src/args.hh @@ -41,9 +41,9 @@ #ifndef __ARGS_HH__ #define __ARGS_HH__ -#include #include #include +#include #include #include @@ -61,19 +61,115 @@ class Args } Args(std::initializer_list strings) : args(strings) {} + /* + * Attempt to convert str into an integer. + * + * Return whether that succeeded. + */ + static bool + stoi(const std::string &str, uint64_t &val) + { + try { + val = std::stoi(str, nullptr, 0); + return true; + } catch (const std::invalid_argument &e) { + return false; + } catch (const std::out_of_range &e) { + return false; + } + } + + /* + * Attempt to convert str into an integer. + * + * Return whether that suceeded. If not, val will be set to def. + */ + static bool + stoi(const std::string &str, uint64_t &val, uint64_t def) + { + val = def; + return stoi(str, val); + } + + /* + * Attempt to pack str as a sequence of bytes in to regs in little endian + * byte order. + * + * Return whether that succeeded. + */ + static bool pack(const std::string &str, uint64_t regs[], int num_regs); + + /* + * If there are any arguments in the list, remove and return the first + * one. If not, return def instead. + */ const std::string & - pop(const std::string &def = "") { + pop(const std::string &def = "") + { if (!size()) return def; return args[offset++]; } + /* + * If there are any arguments in the list, attempt to convert the first + * one to an integer. If successful, remove it and store its value in val. + * + * Return whether that succeeded. + */ + bool + pop(uint64_t &val) + { + if (!size() || !stoi(args[offset], val)) { + return false; + } else { + offset++; + return true; + } + } + + /* + * If there are any arguments in the list, attempt to convert the first + * one to an integer. If successful, remove it and store its value in val. + * If there are no arguments or the conversion failed, set val to def. + * + * Return true if there were no arguments, or there were and the conversion + * succeeded. + */ + bool + pop(uint64_t &val, uint64_t def) + { + val = def; + if (!size()) + return true; + if (stoi(args[offset], val)) { + offset++; + return true; + } + return false; + } + + /* + * If there are any arguments in the list, attempt to pack the first one + * as a sequence of bytes into the integers in regs in little endian byte + * order. + * + * Return whether that succeeded. + */ + bool + pop(uint64_t regs[], int num_regs) + { + if (!size() || !pack(args[offset], regs, num_regs)) { + return false; + } else { + offset++; + return true; + } + } + size_t size() { return args.size() - offset; } const std::string &operator [] (size_t idx) { return args[offset + idx]; } }; -bool parse_int_args(Args &args, uint64_t ints[], int len); -bool pack_arg_into_regs(Args &args, uint64_t regs[], int num_regs); - #endif // __ARGS_HH__ diff --git a/util/m5/src/call_type/addr.cc b/util/m5/src/call_type/addr.cc index 752d83125..f8e39c9f5 100644 --- a/util/m5/src/call_type/addr.cc +++ b/util/m5/src/call_type/addr.cc @@ -97,8 +97,7 @@ class AddrCallType : public CallType if (arg[0] != '=') usage(); // Attempt to extract an address after the '='. - Args temp_args({ arg.substr(1) }); - if (!parse_int_args(temp_args, &addr_override, 1)) + if (!args.stoi(arg.substr(1), addr_override)) usage(); // If we found an address, use it to override m5op_addr. m5op_addr = addr_override; @@ -106,7 +105,7 @@ class AddrCallType : public CallType } // If an address override wasn't part of the first argument, check if // it's the second argument. If not, then there's no override. - if (args.size() && parse_int_args(args, &addr_override, 1)) { + if (args.pop(addr_override)) { m5op_addr = addr_override; return true; } diff --git a/util/m5/src/commands.cc b/util/m5/src/commands.cc index d721899d2..b59633b23 100644 --- a/util/m5/src/commands.cc +++ b/util/m5/src/commands.cc @@ -108,49 +108,63 @@ do_exit(const DispatchTable &dt, Args &args) if (args.size() > 1) usage(); - uint64_t ints[1]; - if (!parse_int_args(args, ints, 1)) + uint64_t ns_delay; + if (!args.pop(ns_delay, 0)) usage(); - (*dt.m5_exit)(ints[0]); + + (*dt.m5_exit)(ns_delay); } static void do_fail(const DispatchTable &dt, Args &args) { - if (args.size() < 1 || args.size() > 2) + if (args.size() > 2) usage(); - uint64_t ints[2] = { 0, 0 }; - if (!parse_int_args(args, ints, args.size())) + uint64_t ns_delay, code; + if (!args.pop(code) || !args.pop(ns_delay, 0)) usage(); - (*dt.m5_fail)(ints[1], ints[0]); + + (*dt.m5_fail)(ns_delay, code); } static void do_reset_stats(const DispatchTable &dt, Args &args) { - uint64_t ints[2]; - if (!parse_int_args(args, ints, 2)) + if (args.size() > 2) + usage(); + + uint64_t ns_delay, ns_period; + if (!args.pop(ns_delay, 0) || !args.pop(ns_period, 0)) usage(); - (*dt.m5_reset_stats)(ints[0], ints[1]); + + (*dt.m5_reset_stats)(ns_delay, ns_period); } static void do_dump_stats(const DispatchTable &dt, Args &args) { - uint64_t ints[2]; - if (!parse_int_args(args, ints, 2)) + if (args.size() > 2) + usage(); + + uint64_t ns_delay, ns_period; + if (!args.pop(ns_delay, 0) || !args.pop(ns_period, 0)) usage(); - (*dt.m5_dump_stats)(ints[0], ints[1]); + + (*dt.m5_dump_stats)(ns_delay, ns_period); } static void do_dump_reset_stats(const DispatchTable &dt, Args &args) { - uint64_t ints[2]; - if (!parse_int_args(args, ints, 2)) + if (args.size() > 2) usage(); - (*dt.m5_dump_reset_stats)(ints[0], ints[1]); + + uint64_t ns_delay, ns_period; + if (!args.pop(ns_delay, 0) || !args.pop(ns_period, 0)) + usage(); + + (*dt.m5_dump_reset_stats)(ns_delay, ns_period); } static void @@ -165,7 +179,7 @@ do_read_file(const DispatchTable &dt, Args &args) static void do_write_file(const DispatchTable &dt, Args &args) { - if (args.size() != 1 && args.size() != 2) + if (args.size() < 1 || args.size() > 2) usage(); const std::string &filename = args.pop(); @@ -177,10 +191,14 @@ do_write_file(const DispatchTable &dt, Args &args) static void do_checkpoint(const DispatchTable &dt, Args &args) { - uint64_t ints[2]; - if (!parse_int_args(args, ints, 2)) + if (args.size() > 2) + usage(); + + uint64_t ns_delay, ns_period; + if (!args.pop(ns_delay, 0) || !args.pop(ns_period, 0)) usage(); - (*dt.m5_checkpoint)(ints[0], ints[1]); + + (*dt.m5_checkpoint)(ns_delay, ns_period); } static void @@ -189,8 +207,11 @@ do_addsymbol(const DispatchTable &dt, Args &args) if (args.size() != 2) usage(); - uint64_t addr = strtoul(args.pop().c_str(), NULL, 0); + uint64_t addr; + if (!args.pop(addr)) + usage(); const std::string &symbol = args.pop(); + (*dt.m5_add_symbol)(addr, symbol.c_str()); } @@ -207,11 +228,11 @@ do_loadsymbol(const DispatchTable &dt, Args &args) static void do_initparam(const DispatchTable &dt, Args &args) { - if (args.size() > 1) + if (args.size() != 1) usage(); uint64_t key_str[2]; - if (!pack_arg_into_regs(args, key_str, 2)) + if (!args.pop(key_str, 2)) usage(); uint64_t val = (*dt.m5_init_param)(key_str[0], key_str[1]); std::cout << val; -- 2.30.2