util: Redistribute command code in the m5 utility.
This division will make it easier to test both the common command code, and the individual commands. Change-Id: Ib7be2b93e40d07e9724443ba26784e45ad9d3b17 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/27562 Reviewed-by: Gabe Black <gabeblack@google.com> Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com> Maintainer: Gabe Black <gabeblack@google.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -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.
|
||||
|
||||
57
util/m5/src/command.cc
Normal file
57
util/m5/src/command.cc
Normal file
@@ -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<std::string, Command &> &
|
||||
Command::map()
|
||||
{
|
||||
static std::map<std::string, Command &> 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;
|
||||
}
|
||||
@@ -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 <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#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<std::string, Command &> &map();
|
||||
|
||||
public:
|
||||
|
||||
static std::map<std::string, Command> 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__
|
||||
@@ -31,21 +31,14 @@
|
||||
#include <iostream>
|
||||
|
||||
#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, "<address> <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, "<code> [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, "<a> <b> [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<std::string, Command> Command::map = {
|
||||
{ "addsymbol", { 2, 2, do_addsymbol, "<address> <symbol>\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, "<code> [delay]\n"
|
||||
" Exit with failure code code after delay, or immediately" }},
|
||||
{ "sum", { 2, 6, do_sum, "<a> <b> [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, "<filename> [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, "<filename> [host filename]\n"
|
||||
" Write a file to the host, optionally with a different "
|
||||
"name" }},
|
||||
};
|
||||
"name" };
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "call_type.hh"
|
||||
#include "commands.hh"
|
||||
#include "command.hh"
|
||||
#include "usage.hh"
|
||||
|
||||
std::string progname;
|
||||
|
||||
Reference in New Issue
Block a user