static_env = env.Clone()
static_env.Append(LINKFLAGS=[ '-no-pie', '-static' ])
-for ct in all_call_types:
- static_env.Append(CXXFLAGS='-DENABLE_CT_%s=%d' %
- (ct.name, 1 if ct.enabled else 0))
- static_env.Append(CXXFLAGS='-DDEFAULT_CT_%s=%d' %
- (ct.name, 1 if ct.default else 0))
-static_env.Append(CXXFLAGS='-DDEFAULT_CALL_TYPE=%s' % default_call_type.name)
-
#
# The m5 library for use in other C/C++ programs.
#
#
# The m5 stand alone command line utility.
#
-ct_support = list([ File('%s_call_type.cc' % ct.name) for ct in call_types ])
+ct_support = []
+for ct in call_types:
+ ct_env = static_env.Clone()
+ 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('%s_call_type.cc' % ct.name))
m5_bin = static_env.Program('out/m5',
ct_support + [ args, call_type, commands, m5, m5_mmap, libm5, usage ])
#include <cstring>
-#include "addr_call_type.hh"
-#include "args.hh"
#include "m5_mmap.h"
+#include "call_type.hh"
+#include "usage.hh"
+
extern "C"
{
#define M5OP(name, func) __typeof__(name) M5OP_MERGE_TOKENS(name, _addr);
#undef M5OP
}
-static DispatchTable addr_dispatch = {
+namespace
+{
+
+DispatchTable addr_dispatch = {
#define M5OP(name, func) .name = &::M5OP_MERGE_TOKENS(name, _addr),
M5OP_FOREACH
#undef M5OP
};
-int
-addr_call_type_detect(Args *args)
+#if defined(M5OP_ADDR)
+const bool DefaultAddrDefined = true;
+constexpr uint64_t DefaultAddress = M5OP_ADDR;
+#else
+const bool DefaultAddrDefined = false;
+constexpr uint64_t DefaultAddress = 0;
+#endif
+
+class AddrCallType : public CallType
{
- static const char *prefix = "--addr";
- const size_t prefix_len = strlen(prefix);
- uint64_t addr_override;
+ private:
+ public:
+ bool isDefault() const override { return CALL_TYPE_IS_DEFAULT; }
+ const DispatchTable &getDispatch() const override { return addr_dispatch; }
+
+ void
+ printBrief(std::ostream &os) const override
+ {
+ os << "--addr " << (DefaultAddrDefined ? "[address override]" :
+ "<address override>");
+ }
+
+ void
+ printDesc(std::ostream &os) const override
+ {
+ os << "Use the address based invocation method.";
+ if (DefaultAddrDefined) {
+ os << " The default address is 0x" <<
+ std::hex << DefaultAddress << std::dec << ".";
+ }
+ }
+
+ bool
+ checkArgs(Args &args) override
+ {
+ static const char *prefix = "--addr";
+ const size_t prefix_len = strlen(prefix);
+ uint64_t addr_override;
- // If the first argument starts with --addr...
- if (args->argc && memcmp(args->argv[0], prefix, prefix_len) == 0) {
- const char *argv0 = pop_arg(args);
+ // If the first argument doesn't start with --addr...
+ if (!args.argc || memcmp(args.argv[0], prefix, prefix_len) != 0)
+ return false;
+
+ const char *argv0 = pop_arg(&args);
// If there's more text in this argument...
if (strlen(argv0) != prefix_len) {
// If it doesn't start with '=', it's malformed.
if (argv0[prefix_len] != '=')
- return -1;
+ usage();
// Attempt to extract an address after the '='.
const char *temp_argv[] = { &argv0[prefix_len + 1] };
Args temp_args = { 1, temp_argv };
if (!parse_int_args(&temp_args, &addr_override, 1))
- return -1;
+ usage();
// If we found an address, use it to override m5op_addr.
m5op_addr = addr_override;
- return 1;
+ return true;
}
// 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->argc && parse_int_args(args, &addr_override, 1)) {
+ if (args.argc && parse_int_args(&args, &addr_override, 1)) {
m5op_addr = addr_override;
- return 1;
+ return true;
}
- // If the default address was zero, an override is required.
- if (!m5op_addr)
- return -1;
- return 1;
+ // If the default address was not defined, an override is required.
+ if (!DefaultAddrDefined)
+ usage();
+
+ return true;
}
- return 0;
-}
-DispatchTable *
-addr_call_type_init()
-{
- map_m5_mem();
- return &addr_dispatch;
-}
+ void init() override { map_m5_mem(); }
+} addr_call_type;
+
+} // anonymous namespace
+++ /dev/null
-/*
- * Copyright 2020 Google Inc.
- *
- * 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.
- */
-
-#ifndef __ADDR_CALL_TYPE_HH__
-#define __ADDR_CALL_TYPE_HH__
-
-#include "args.hh"
-#include "dispatch_table.hh"
-
-// Returns 0 if not detected, 1 if detected successfully, and -1 on error.
-int addr_call_type_detect(Args *args);
-DispatchTable *addr_call_type_init();
-
-#endif // __ADDR_CALL_TYPE_HH__
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "args.hh"
+#include <cassert>
+#include <sstream>
+
#include "call_type.hh"
-#include "usage.hh"
-#if ENABLE_CT_addr
-#include "addr_call_type.hh"
-#endif
-#if ENABLE_CT_inst
-#include "inst_call_type.hh"
-#endif
-#if ENABLE_CT_semi
-#include "semi_call_type.hh"
-#endif
+std::vector<CallType *> &
+CallType::allTypes()
+{
+ static std::vector<CallType *> all;
+ return all;
+}
+
+CallType &
+CallType::detect(Args &args)
+{
+ CallType *def = nullptr;
-#define default_call_type_init() \
- M5OP_MERGE_TOKENS(DEFAULT_CALL_TYPE, _call_type_init())
+ for (auto *ct: allTypes()) {
+ if (ct->checkArgs(args)) {
+ ct->init();
+ return *ct;
+ }
+ if (ct->isDefault())
+ def = ct;
+ }
-DispatchTable *
-init_call_type(Args *args)
+ assert(def);
+ def->init();
+ return *def;
+}
+
+std::string
+CallType::usageSummary()
{
-# if ENABLE_CT_inst
- if (inst_call_type_detect(args))
- return inst_call_type_init();
-# endif
-# if ENABLE_CT_addr
- int detect = addr_call_type_detect(args);
- if (detect < 0)
- usage();
- if (detect > 0)
- return addr_call_type_init();
-# endif
-# if ENABLE_CT_semi
- if (semi_call_type_detect(args))
- return semi_call_type_init();
-# endif
- return default_call_type_init();
+ std::string summary = "";
+ for (auto *ct: allTypes())
+ summary += ct->formattedUsage();
+ return summary;
+}
+
+std::string
+CallType::formattedUsage() const
+{
+ std::ostringstream os;
+ os << " ";
+ printBrief(os);
+ if (isDefault())
+ os << " (default)";
+ os << std::endl;
+
+ os << " ";
+ printDesc(os);
+ os << std::endl;
+ return os.str();
}
#ifndef __CALL_TYPE_HH__
#define __CALL_TYPE_HH__
+#include <iostream>
+#include <string>
+#include <vector>
+
#include "args.hh"
#include "dispatch_table.hh"
-DispatchTable *init_call_type(Args *args);
+class CallType
+{
+ protected:
+ virtual bool isDefault() const = 0;
+ virtual bool checkArgs(Args &args) = 0;
+ virtual void init() {}
+
+ static std::vector<CallType *> &allTypes();
+
+ virtual void printBrief(std::ostream &os) const = 0;
+ virtual void printDesc(std::ostream &os) const = 0;
+ std::string formattedUsage() const;
+
+ public:
+ CallType() { allTypes().push_back(this); }
+
+ static CallType &detect(Args &args);
+ static std::string usageSummary();
+
+ virtual const DispatchTable &getDispatch() const = 0;
+};
+
#endif // __CALL_TYPE_HH__
#include "usage.hh"
static int
-read_file(DispatchTable *dt, int dest_fid)
+read_file(const DispatchTable &dt, int dest_fid)
{
uint8_t buf[256*1024];
int offset = 0;
// Linux does demand paging.
memset(buf, 0, sizeof(buf));
- while ((len = (*dt->m5_read_file)(buf, sizeof(buf), offset)) > 0) {
+ while ((len = (*dt.m5_read_file)(buf, sizeof(buf), offset)) > 0) {
uint8_t *base = buf;
offset += len;
do {
}
static void
-write_file(DispatchTable *dt, const char *filename, const char *host_filename)
+write_file(const DispatchTable &dt, const char *filename,
+ const char *host_filename)
{
fprintf(stderr, "opening %s\n", filename);
int src_fid = open(filename, O_RDONLY);
memset(buf, 0, sizeof(buf));
while ((len = read(src_fid, buf, sizeof(buf))) > 0) {
- bytes += (*dt->m5_write_file)(buf, len, offset, host_filename);
+ bytes += (*dt.m5_write_file)(buf, len, offset, host_filename);
offset += len;
}
fprintf(stderr, "written %d bytes\n", bytes);
}
static void
-do_exit(DispatchTable *dt, Args *args)
+do_exit(const DispatchTable &dt, Args *args)
{
if (args->argc > 1)
usage();
uint64_t ints[1];
if (!parse_int_args(args, ints, 1))
usage();
- (*dt->m5_exit)(ints[0]);
+ (*dt.m5_exit)(ints[0]);
}
static void
-do_fail(DispatchTable *dt, Args *args)
+do_fail(const DispatchTable &dt, Args *args)
{
if (args->argc < 1 || args->argc > 2)
usage();
uint64_t ints[2] = { 0, 0 };
if (!parse_int_args(args, ints, args->argc))
usage();
- (*dt->m5_fail)(ints[1], ints[0]);
+ (*dt.m5_fail)(ints[1], ints[0]);
}
static void
-do_reset_stats(DispatchTable *dt, Args *args)
+do_reset_stats(const DispatchTable &dt, Args *args)
{
uint64_t ints[2];
if (!parse_int_args(args, ints, 2))
usage();
- (*dt->m5_reset_stats)(ints[0], ints[1]);
+ (*dt.m5_reset_stats)(ints[0], ints[1]);
}
static void
-do_dump_stats(DispatchTable *dt, Args *args)
+do_dump_stats(const DispatchTable &dt, Args *args)
{
uint64_t ints[2];
if (!parse_int_args(args, ints, 2))
usage();
- (*dt->m5_dump_stats)(ints[0], ints[1]);
+ (*dt.m5_dump_stats)(ints[0], ints[1]);
}
static void
-do_dump_reset_stats(DispatchTable *dt, Args *args)
+do_dump_reset_stats(const DispatchTable &dt, Args *args)
{
uint64_t ints[2];
if (!parse_int_args(args, ints, 2))
usage();
- (*dt->m5_dump_reset_stats)(ints[0], ints[1]);
+ (*dt.m5_dump_reset_stats)(ints[0], ints[1]);
}
static void
-do_read_file(DispatchTable *dt, Args *args)
+do_read_file(const DispatchTable &dt, Args *args)
{
if (args->argc > 0)
usage();
}
static void
-do_write_file(DispatchTable *dt, Args *args)
+do_write_file(const DispatchTable &dt, Args *args)
{
if (args->argc != 1 && args->argc != 2)
usage();
}
static void
-do_checkpoint(DispatchTable *dt, Args *args)
+do_checkpoint(const DispatchTable &dt, Args *args)
{
uint64_t ints[2];
if (!parse_int_args(args, ints, 2))
usage();
- (*dt->m5_checkpoint)(ints[0], ints[1]);
+ (*dt.m5_checkpoint)(ints[0], ints[1]);
}
static void
-do_addsymbol(DispatchTable *dt, Args *args)
+do_addsymbol(const DispatchTable &dt, Args *args)
{
if (args->argc != 2)
usage();
uint64_t addr = strtoul(pop_arg(args), NULL, 0);
const char *symbol = pop_arg(args);
- (*dt->m5_add_symbol)(addr, symbol);
+ (*dt.m5_add_symbol)(addr, symbol);
}
static void
-do_loadsymbol(DispatchTable *dt, Args *args)
+do_loadsymbol(const DispatchTable &dt, Args *args)
{
if (args->argc > 0)
usage();
- (*dt->m5_load_symbol)();
+ (*dt.m5_load_symbol)();
}
static void
-do_initparam(DispatchTable *dt, Args *args)
+do_initparam(const DispatchTable &dt, Args *args)
{
if (args->argc > 1)
usage();
uint64_t key_str[2];
if (!pack_arg_into_regs(args, key_str, 2))
usage();
- uint64_t val = (*dt->m5_init_param)(key_str[0], key_str[1]);
+ uint64_t val = (*dt.m5_init_param)(key_str[0], key_str[1]);
std::cout << val;
}
const char *name;
// A function which processes command line arguments and passes them to
// the underlying function through the dispatch table.
- void (*func)(DispatchTable *dt, Args *args);
+ void (*func)(const DispatchTable &dt, Args *args);
// Help text for this command.
const char *usage;
};
#include <cstring>
-#include "inst_call_type.hh"
+#include "call_type.hh"
-static DispatchTable inst_dispatch = {
+namespace
+{
+
+DispatchTable inst_dispatch = {
#define M5OP(name, func) .name = &::name,
M5OP_FOREACH
#undef M5OP
};
-int
-inst_call_type_detect(Args *args)
+class InstCallType : public CallType
{
- if (args->argc && strcmp(args->argv[0], "--inst") == 0) {
- pop_arg(args);
- return 1;
+ public:
+ bool isDefault() const override { return CALL_TYPE_IS_DEFAULT; }
+ const DispatchTable &getDispatch() const override { return inst_dispatch; }
+
+ bool
+ checkArgs(Args &args) override
+ {
+ if (args.argc && strcmp(args.argv[0], "--inst") == 0) {
+ pop_arg(&args);
+ return true;
+ }
+ return false;
}
- return 0;
-}
-DispatchTable *
-inst_call_type_init()
-{
- return &inst_dispatch;
-}
+ void printBrief(std::ostream &os) const override { os << "--inst"; }
+ void
+ printDesc(std::ostream &os) const override
+ {
+ os << "Use the instruction based invocation method.";
+ }
+} inst_call_type;
+
+} // anonymous namespace
+++ /dev/null
-/*
- * Copyright 2020 Google Inc.
- *
- * 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.
- */
-
-#ifndef __INST_CALL_TYPE_HH__
-#define __INST_CALL_TYPE_HH__
-
-#include "args.hh"
-#include "dispatch_table.hh"
-
-int inst_call_type_detect(Args *args);
-DispatchTable *inst_call_type_init();
-
-#endif // __INST_CALL_TYPE_HH__
progname = pop_arg(&args);
- DispatchTable *dt = init_call_type(&args);
+ const DispatchTable &dt = CallType::detect(args).getDispatch();
const char *command = pop_arg(&args);
#include <cstring>
-#include "semi_call_type.hh"
+#include "call_type.hh"
extern "C"
{
#undef M5OP
}
-static DispatchTable semi_dispatch = {
+namespace
+{
+
+DispatchTable semi_dispatch = {
#define M5OP(name, func) .name = &::M5OP_MERGE_TOKENS(name, _semi),
M5OP_FOREACH
#undef M5OP
};
-int
-semi_call_type_detect(Args *args)
+class SemiCallType : public CallType
{
- if (args->argc && strcmp(args->argv[0], "--semi") == 0) {
- pop_arg(args);
- return 1;
+ public:
+ bool isDefault() const override { return CALL_TYPE_IS_DEFAULT; }
+ const DispatchTable &getDispatch() const override { return semi_dispatch; }
+
+ bool
+ checkArgs(Args &args) override
+ {
+ if (args.argc && strcmp(args.argv[0], "--semi") == 0) {
+ pop_arg(&args);
+ return true;
+ }
+ return false;
}
- return 0;
-}
-DispatchTable *
-semi_call_type_init()
-{
- return &semi_dispatch;
-}
+ void printBrief(std::ostream &os) const override { os << "--semi"; }
+ void
+ printDesc(std::ostream &os) const override
+ {
+ os << "Use the semi-hosting based invocation method.";
+ }
+} semi_call_type;
+
+} // anonymous namespace
+++ /dev/null
-/*
- * Copyright 2020 Google Inc.
- *
- * 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.
- */
-
-#ifndef __SEMI_CALL_TYPE_HH__
-#define __SEMI_CALL_TYPE_HH__
-
-#include "args.hh"
-#include "dispatch_table.hh"
-
-int semi_call_type_detect(Args *args);
-DispatchTable *semi_call_type_init();
-
-#endif // __SEMI_CALL_TYPE_HH__
#include <cstdio>
#include <cstdlib>
+#include "call_type.hh"
#include "commands.hh"
#include "usage.hh"
fprintf(stderr, "Usage: %s [call type] <command> [arguments]\n", progname);
fprintf(stderr, "\n");
fprintf(stderr, "Call types:\n");
-# if ENABLE_CT_addr
- fprintf(stderr, " --addr %s%s\n",
-# if defined(M5OP_ADDR)
- "[address override]",
-# else
- "<address override>",
-# endif
- DEFAULT_CT_addr ? " (default)" : "");
- fprintf(stderr, " Use the address based invocation method.\n");
-# if defined(M5OP_ADDR)
- fprintf(stderr, " The default address is %#" PRIx64 ".\n",
- (uint64_t)M5OP_ADDR);
-# endif
-# endif
-# if ENABLE_CT_inst
- fprintf(stderr, " --inst%s\n", DEFAULT_CT_inst ? " (default)" : "");
- fprintf(stderr, " Use the instruction based invocation method.\n");
-# endif
-# if ENABLE_CT_semi
- fprintf(stderr, " --semi%s\n", DEFAULT_CT_semi ? " (default)" : "");
- fprintf(stderr, " Use the semi-hosting based invocation method.\n");
-# endif
+ fprintf(stderr, CallType::usageSummary().c_str());
fprintf(stderr, "\n");
fprintf(stderr, "Commands:\n");
for (int i = 0; i < num_commands; ++i) {