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 <power.jg@gmail.com> Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br> Maintainer: Jason Lowe-Power <power.jg@gmail.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -38,39 +38,20 @@
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cinttypes>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#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;
|
||||
|
||||
@@ -41,9 +41,9 @@
|
||||
#ifndef __ARGS_HH__
|
||||
#define __ARGS_HH__
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <initializer_list>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -61,19 +61,115 @@ class Args
|
||||
}
|
||||
Args(std::initializer_list<std::string> 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__
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
(*dt.m5_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_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();
|
||||
(*dt.m5_dump_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_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();
|
||||
(*dt.m5_checkpoint)(ints[0], ints[1]);
|
||||
|
||||
uint64_t ns_delay, ns_period;
|
||||
if (!args.pop(ns_delay, 0) || !args.pop(ns_period, 0))
|
||||
usage();
|
||||
|
||||
(*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;
|
||||
|
||||
Reference in New Issue
Block a user