Gabe Black has submitted this change. ( https://gem5-review.googlesource.com/c/public/gem5/+/27562 )

Change subject: util: Redistribute command code in the m5 utility.
......................................................................

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 <[email protected]>
Reviewed-by: Giacomo Travaglini <[email protected]>
Maintainer: Gabe Black <[email protected]>
Tested-by: kokoro <[email protected]>
---
M util/m5/src/SConscript
A util/m5/src/command.cc
R util/m5/src/command.hh
M util/m5/src/commands.cc
M util/m5/src/m5.cc
M util/m5/src/usage.cc
6 files changed, 240 insertions(+), 150 deletions(-)

Approvals:
  Gabe Black: Looks good to me, approved; Looks good to me, approved
  Giacomo Travaglini: Looks good to me, approved
  kokoro: Regressions pass



diff --git a/util/m5/src/SConscript b/util/m5/src/SConscript
index 0082ebc..1f33caa 100644
--- a/util/m5/src/SConscript
+++ b/util/m5/src/SConscript
@@ -32,6 +32,7 @@
 # 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 @@
     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 0000000..d7dc030
--- /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<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;
+}
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 cb361b4..8348d11 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 <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 @@
     // 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__
diff --git a/util/m5/src/commands.cc b/util/m5/src/commands.cc
index 2d71f93..0dd971a 100644
--- a/util/m5/src/commands.cc
+++ b/util/m5/src/commands.cc
@@ -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 @@
     return offset;
 }

-static void
+void
 write_file(const DispatchTable &dt, const std::string &filename,
            const std::string &host_filename)
 {
@@ -107,7 +100,72 @@
     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 @@
     (*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 @@
     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 @@
     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
diff --git a/util/m5/src/m5.cc b/util/m5/src/m5.cc
index eebddd2..f8c1101 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 @@

     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 bbcf36a..78bfb41 100644
--- a/util/m5/src/usage.cc
+++ b/util/m5/src/usage.cc
@@ -42,7 +42,7 @@
 #include <iostream>

 #include "call_type.hh"
-#include "commands.hh"
+#include "command.hh"
 #include "usage.hh"

 std::string progname;

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/27562
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: Ib7be2b93e40d07e9724443ba26784e45ad9d3b17
Gerrit-Change-Number: 27562
Gerrit-PatchSet: 24
Gerrit-Owner: Gabe Black <[email protected]>
Gerrit-Reviewer: Bobby R. Bruce <[email protected]>
Gerrit-Reviewer: Earl Ou <[email protected]>
Gerrit-Reviewer: Gabe Black <[email protected]>
Gerrit-Reviewer: Giacomo Travaglini <[email protected]>
Gerrit-Reviewer: Jason Lowe-Power <[email protected]>
Gerrit-Reviewer: Pouya Fotouhi <[email protected]>
Gerrit-Reviewer: Yu-hsin Wang <[email protected]>
Gerrit-Reviewer: kokoro <[email protected]>
Gerrit-MessageType: merged
_______________________________________________
gem5-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to