diff --git a/util/m5/src/SConscript b/util/m5/src/SConscript index 0082ebcb8d..1f33caa1cc 100644 --- a/util/m5/src/SConscript +++ b/util/m5/src/SConscript @@ -32,6 +32,7 @@ env.Append(CPPPATH=Dir('.')) # Raw source files. args = 'args.cc' call_type = 'call_type.cc' +command = 'command.cc' commands = 'commands.cc' m5 = 'm5.cc' m5_mmap = 'm5_mmap.c' @@ -68,8 +69,8 @@ for ct in call_types: is_default = 'true' if ct.default else 'false' ct_env.Append(CXXFLAGS=[ '-DCALL_TYPE_IS_DEFAULT=%s' % is_default ]) ct_support.extend(ct_env.StaticObject('call_type/%s.cc' % ct.name)) -m5_bin = static_env.Program('out/m5', - ct_support + [ args, call_type, commands, m5, m5_mmap, libm5, usage ]) +m5_bin = static_env.Program('out/m5', ct_support + + [ args, call_type, command, commands, m5, m5_mmap, libm5, usage ]) # The shared version of the m5 op call sights, used by mutliple targets below. diff --git a/util/m5/src/command.cc b/util/m5/src/command.cc new file mode 100644 index 0000000000..d7dc030283 --- /dev/null +++ b/util/m5/src/command.cc @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2003-2005 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "args.hh" +#include "command.hh" + +std::map & +Command::map() +{ + static std::map the_map; + return the_map; +} + +bool +Command::run(const DispatchTable &dt, Args &args) +{ + if (!args.size()) + return false; + + auto cmd_it = map().find(args.pop()); + if (cmd_it == map().end()) + return false; + + auto &cmd = cmd_it->second; + + const int num_args = args.size(); + if (num_args < cmd.minArgs || num_args > cmd.maxArgs) + return false; + + cmd.func(dt, args); + return true; +} diff --git a/util/m5/src/commands.hh b/util/m5/src/command.hh similarity index 76% rename from util/m5/src/commands.hh rename to util/m5/src/command.hh index cb361b4bb6..8348d11167 100644 --- a/util/m5/src/commands.hh +++ b/util/m5/src/command.hh @@ -26,18 +26,21 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __COMMANDS_HH__ -#define __COMMANDS_HH__ +#ifndef __COMMAND_HH__ +#define __COMMAND_HH__ #include #include +#include -#include "args.hh" -#include "dispatch_table.hh" +class Args; +class DispatchTable; class Command { private: + const std::string name; + // The minimum number of arguments the command expects. const int minArgs; // The maximum number of arguments the command can handle. @@ -51,24 +54,32 @@ class Command // Help text for this command. const std::string usageStr; + static std::map &map(); + public: - static std::map map; + Command(const std::string &_name, int _min, int _max, FuncType _func, + const std::string &_usage) : + name(_name), minArgs(_min), maxArgs(_max), func(_func), + usageStr(_usage) + { + map().emplace(std::piecewise_construct, + std::forward_as_tuple(std::string(_name)), + std::forward_as_tuple(*this)); + } - Command(int _min, int _max, FuncType _func, const std::string &_usage) : - minArgs(_min), maxArgs(_max), func(_func), usageStr(_usage) - {} + ~Command() { map().erase(name); } - void run(const DispatchTable &dt, Args &args); + static bool run(const DispatchTable &dt, Args &args); static std::string usageSummary() { std::string summary; - for (auto &p: Command::map) + for (auto &p: Command::map()) summary += " " + p.first + " " + p.second.usageStr + "\n"; return summary; } }; -#endif // __COMMANDS_HH__ +#endif // __COMMAND_HH__ diff --git a/util/m5/src/commands.cc b/util/m5/src/commands.cc index 2d71f93148..0dd971acf8 100644 --- a/util/m5/src/commands.cc +++ b/util/m5/src/commands.cc @@ -31,21 +31,14 @@ #include #include "args.hh" -#include "commands.hh" +#include "command.hh" +#include "dispatch_table.hh" #include "usage.hh" -void -Command::run(const DispatchTable &dt, Args &args) +namespace { - const int num_args = args.size(); - if (num_args < minArgs || num_args > maxArgs) - usage(); - func(dt, args); -} - - -static int +int read_file(const DispatchTable &dt, std::ostream &os) { char buf[256 * 1024]; @@ -70,7 +63,7 @@ read_file(const DispatchTable &dt, std::ostream &os) return offset; } -static void +void write_file(const DispatchTable &dt, const std::string &filename, const std::string &host_filename) { @@ -107,7 +100,72 @@ write_file(const DispatchTable &dt, const std::string &filename, std::cerr << "Wrote " << offset << " bytes." << std::endl; } -static void +void +do_add_symbol(const DispatchTable &dt, Args &args) +{ + uint64_t addr; + if (!args.pop(addr)) + usage(); + const std::string &symbol = args.pop(); + + (*dt.m5_add_symbol)(addr, symbol.c_str()); +} + +Command add_symbol = { + "addsymbol", 2, 2, do_add_symbol, "
\n" + " Adds a symbol with address \"address\" to gem5's " + "symbol table" }; + + +void +do_checkpoint(const DispatchTable &dt, Args &args) +{ + 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); +} + +Command checkpoint = { + "checkpoint", 0, 2, do_checkpoint, "[delay [period]]\n" + " After delay (default 0) take a checkpoint, and then " + "optionally every period after" }; + + +void +do_dump_reset_stats(const DispatchTable &dt, Args &args) +{ + 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); +} + +Command dump_reset_stats = { + "dumpresetstats", 0, 2, do_dump_reset_stats, "[delay [period]]\n" + " After delay (default 0) dump and reset the stats, and then " + "optionally every period after" }; + + +void +do_dump_stats(const DispatchTable &dt, Args &args) +{ + 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); +} + +Command dump_stats = { + "dumpstats", 0, 2, do_dump_stats, "[delay [period]]\n" + " After delay (default 0) dump the stats, and then optionally " + "every period after" }; + + +void do_exit(const DispatchTable &dt, Args &args) { uint64_t ns_delay; @@ -117,8 +175,28 @@ do_exit(const DispatchTable &dt, Args &args) (*dt.m5_exit)(ns_delay); } +Command exit_cmd = { + "exit", 0, 1, do_exit, "[delay]\n" + " Exit after delay, or immediately" }; + + +void +do_fail(const DispatchTable &dt, Args &args) +{ + uint64_t ns_delay, code; + if (!args.pop(code) || !args.pop(ns_delay, 0)) + usage(); + + (*dt.m5_fail)(ns_delay, code); +} + +Command fail_cmd = { + "fail", 1, 2, do_fail, " [delay]\n" + " Exit with failure code code after delay, or immediately" }; + + // For testing purposes. -static void +void do_sum(const DispatchTable &dt, Args &args) { uint64_t a, b, c, d, e, f; @@ -130,93 +208,12 @@ do_sum(const DispatchTable &dt, Args &args) std::cout << "Sum is " << sum << "." << std::endl; } -static void -do_fail(const DispatchTable &dt, Args &args) -{ - uint64_t ns_delay, code; - if (!args.pop(code) || !args.pop(ns_delay, 0)) - usage(); - - (*dt.m5_fail)(ns_delay, code); -} - -static void -do_reset_stats(const DispatchTable &dt, Args &args) -{ - 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 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 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 -do_read_file(const DispatchTable &dt, Args &args) -{ - if (args.size() > 0) - usage(); - - read_file(dt, std::cout); -} - -static void -do_write_file(const DispatchTable &dt, Args &args) -{ - const std::string &filename = args.pop(); - const std::string &host_filename = args.pop(filename); - - write_file(dt, filename, host_filename); -} - -static void -do_checkpoint(const DispatchTable &dt, Args &args) -{ - 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 -do_addsymbol(const DispatchTable &dt, Args &args) -{ - uint64_t addr; - if (!args.pop(addr)) - usage(); - const std::string &symbol = args.pop(); - - (*dt.m5_add_symbol)(addr, symbol.c_str()); -} +Command sum = { + "sum", 2, 6, do_sum, " [c [d [e [f]]]]\n" + " Sum a-f (defaults are 0), for testing purposes" }; -static void -do_loadsymbol(const DispatchTable &dt, Args &args) -{ - (*dt.m5_load_symbol)(); -} - -static void +void do_initparam(const DispatchTable &dt, Args &args) { uint64_t key_str[2]; @@ -226,36 +223,65 @@ do_initparam(const DispatchTable &dt, Args &args) std::cout << val; } -std::map Command::map = { - { "addsymbol", { 2, 2, do_addsymbol, "
\n" - " Adds a symbol with address \"address\" to gem5's " - "symbol table" }}, - { "checkpoint", { 0, 2, do_checkpoint, "[delay [period]]\n" - " After delay (default 0) take a checkpoint, and then " - "optionally every period after" }}, - { "dumpresetstats", { 0, 2, do_dump_reset_stats, "[delay [period]]\n" - " After delay (default 0) dump and reset the stats, and then " - "optionally every period after" }}, - { "dumpstats", { 0, 2, do_dump_stats, "[delay [period]]\n" - " After delay (default 0) dump the stats, and then optionally " - "every period after" }}, - { "exit", { 0, 1, do_exit, "[delay]\n" - " Exit after delay, or immediately" }}, - { "fail", { 1, 2, do_fail, " [delay]\n" - " Exit with failure code code after delay, or immediately" }}, - { "sum", { 2, 6, do_sum, " [c [d [e [f]]]]\n" - " Sum a-f (defaults are 0), for testing purposes" }}, - { "initparam", { 1, 1, do_initparam, "[key]\n" - " optional key may be at most 16 characters long" }}, - { "loadsymbol", { 0, 0, do_loadsymbol, "\n" - " load a preselected symbol file into gem5's symbol table" }}, - { "readfile", { 0, 0, do_read_file, "\n" +Command init_param = { + "initparam", 1, 1, do_initparam, "[key]\n" + " optional key may be at most 16 characters long" }; + + +void +do_loadsymbol(const DispatchTable &dt, Args &args) +{ + (*dt.m5_load_symbol)(); +} + +Command load_symbol = { + "loadsymbol", 0, 0, do_loadsymbol, "\n" + " load a preselected symbol file into gem5's symbol table" }; + + +void +do_read_file(const DispatchTable &dt, Args &args) +{ + if (args.size() > 0) + usage(); + + read_file(dt, std::cout); +} + +Command read_file_cmd = { + "readfile", 0, 0, do_read_file, "\n" " read a preselected file from the host and write it to " - "stdout" }}, - { "resetstats", { 0, 2, do_reset_stats, "[delay [period]]\n" + "stdout" }; + + +void +do_reset_stats(const DispatchTable &dt, Args &args) +{ + 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); +} + +Command reset_stats = { + "resetstats", 0, 2, do_reset_stats, "[delay [period]]\n" " After delay (default 0) reset the stats, and then " - "optionally every period after" }}, - { "writefile", { 1, 2, do_write_file, " [host filename]\n" + "optionally every period after" }; + + +void +do_write_file(const DispatchTable &dt, Args &args) +{ + const std::string &filename = args.pop(); + const std::string &host_filename = args.pop(filename); + + write_file(dt, filename, host_filename); +} + +Command write_file_cmd = { + "writefile", 1, 2, do_write_file, " [host filename]\n" " Write a file to the host, optionally with a different " - "name" }}, -}; + "name" }; + +} // anonymous namespace diff --git a/util/m5/src/m5.cc b/util/m5/src/m5.cc index eebddd25c3..f8c1101f09 100644 --- a/util/m5/src/m5.cc +++ b/util/m5/src/m5.cc @@ -40,7 +40,7 @@ #include "args.hh" #include "call_type.hh" -#include "commands.hh" +#include "command.hh" #include "usage.hh" int @@ -55,13 +55,8 @@ main(int argc, const char *argv[]) const DispatchTable &dt = CallType::detect(args).getDispatch(); - if (!args.size()) + if (!Command::run(dt, args)) usage(); - auto cmd = Command::map.find(args.pop()); - if (cmd == Command::map.end()) - usage(); - - cmd->second.run(dt, args); exit(0); } diff --git a/util/m5/src/usage.cc b/util/m5/src/usage.cc index bbcf36af36..78bfb41363 100644 --- a/util/m5/src/usage.cc +++ b/util/m5/src/usage.cc @@ -42,7 +42,7 @@ #include #include "call_type.hh" -#include "commands.hh" +#include "command.hh" #include "usage.hh" std::string progname;