By pulling the code out, this code can be tested by unit tests.
Change-Id: I2d0510995d3e97d721f1de3024120f0c90b7a5ba
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/27547
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Gabe Black <gabeblack@google.com>
Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br>
Maintainer: Gabe Black <gabeblack@google.com>
Import('*')
# Raw source files.
-m5_mmap = 'm5_mmap.c'
args = 'args.c'
+call_type = 'call_type.c'
+commands = 'commands.c'
m5 = 'm5.c'
+m5_mmap = 'm5_mmap.c'
+usage = 'usage.c'
+
jni = 'jni_gem5Op.c'
lua = 'lua_gem5Op.c'
#
ct_support = list([ File('%s_call_type.c' % ct.name) for ct in call_types ])
m5_bin = static_env.Program('out/m5',
- ct_support + [ args, m5, m5_mmap, libm5 ])
+ ct_support + [ args, call_type, commands, m5, m5_mmap, libm5, usage ])
# The shared version of the m5 op call sights, used by mutliple targets below.
};
int
-addr_call_type_detect(int *argc, char **argv[])
+addr_call_type_detect(Args *args)
{
static const char *prefix = "--addr";
const size_t prefix_len = strlen(prefix);
uint64_t addr_override;
// If the first argument starts with --addr...
- if (*argc > 0 && memcmp((*argv)[0], prefix, prefix_len) == 0) {
- char *argv0 = (*argv)[0];
- (*argc)--;
- (*argv)++;
+ if (args->argc && memcmp(args->argv[0], prefix, prefix_len) == 0) {
+ const char *argv0 = pop_arg(args);
// If there's more text in this argument...
if (strlen(argv0) != prefix_len) {
if (argv0[prefix_len] != '=')
return -1;
// Attempt to extract an address after the '='.
- char *temp_argv[] = { &argv0[prefix_len + 1] };
- if (!parse_int_args(1, temp_argv, &addr_override, 1))
+ 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;
// If we found an address, use it to override m5op_addr.
m5op_addr = addr_override;
}
// 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 (*argc > 0 && parse_int_args(1, *argv, &addr_override, 1)) {
+ if (args->argc && parse_int_args(args, &addr_override, 1)) {
m5op_addr = addr_override;
- (*argc)--;
- (*argv)++;
return 1;
}
// If the default address was zero, an override is required.
#ifndef __ADDR_CALL_TYPE_H__
#define __ADDR_CALL_TYPE_H__
+#include "args.h"
#include "dispatch_table.h"
// Returns 0 if not detected, 1 if detected successfully, and -1 on error.
-int addr_call_type_detect(int *argc, char **argv[]);
+int addr_call_type_detect(Args *args);
DispatchTable *addr_call_type_init();
#endif // __ADDR_CALL_TYPE_H__
#include <stdlib.h>
#include <string.h>
+#include "args.h"
+
int
-parse_int_args(int argc, char *argv[], uint64_t ints[], int len)
+parse_int_args(Args *args, uint64_t ints[], int len)
{
- if (argc > len)
+ if (args->argc > len)
return 0;
// On 32 bit platforms we need to use strtoull to do the conversion
#else
#define strto64 strtoull
#endif
- int i;
- for (i = 0; i < len; ++i)
- ints[i] = (i < argc) ? strto64(argv[i], NULL, 0) : 0;
+ for (int i = 0; i < len; ++i) {
+ const char *arg = pop_arg(args);
+ ints[i] = arg ? strto64(arg, NULL, 0) : 0;
+ }
#undef strto64
return 1;
}
int
-pack_str_into_regs(const char *str, uint64_t regs[], int num_regs)
+pack_arg_into_regs(Args *args, uint64_t regs[], int num_regs)
{
const size_t RegSize = sizeof(regs[0]);
const size_t MaxLen = num_regs * RegSize;
+ const char *arg = pop_arg(args);
+
+ memset(regs, 0, MaxLen);
- size_t len = strlen(str);
+ size_t len = arg ? strlen(arg) : 0;
if (len > MaxLen)
return 0;
- memset(regs, 0, MaxLen);
-
while (len) {
for (int offset = 0; offset < RegSize && len; offset++, len--) {
int shift = offset * 8;
- *regs |= (uint64_t)(uint8_t)*str++ << shift;
+ *regs |= (uint64_t)(uint8_t)*arg++ << shift;
}
regs++;
}
#ifndef __ARGS_H__
#define __ARGS_H__
+#include <stddef.h>
#include <stdint.h>
-int parse_int_args(int argc, char *argv[], uint64_t ints[], int len);
-int pack_str_into_regs(const char *str, uint64_t regs[], int num_regs);
+typedef struct Args
+{
+ int argc;
+ const char **argv;
+} Args;
+
+static inline const char *
+pop_arg(Args *args)
+{
+ if (!args->argc)
+ return NULL;
+ args->argc--;
+ return (args->argv++)[0];
+}
+
+int parse_int_args(Args *args, uint64_t ints[], int len);
+int pack_arg_into_regs(Args *args, uint64_t regs[], int num_regs);
#endif // __ARGS_H__
--- /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.
+ */
+
+#include "args.h"
+#include "call_type.h"
+#include "usage.h"
+
+#if ENABLE_CT_addr
+#include "addr_call_type.h"
+#endif
+#if ENABLE_CT_inst
+#include "inst_call_type.h"
+#endif
+#if ENABLE_CT_semi
+#include "semi_call_type.h"
+#endif
+
+#define default_call_type_init() \
+ M5OP_MERGE_TOKENS(DEFAULT_CALL_TYPE, _call_type_init())
+
+DispatchTable *
+init_call_type(Args *args)
+{
+# 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();
+}
#ifndef __CALL_TYPE_H__
#define __CALL_TYPE_H__
+#include "args.h"
#include "dispatch_table.h"
-#if ENABLE_CT_addr
-#include "addr_call_type.h"
-#endif
-#if ENABLE_CT_inst
-#include "inst_call_type.h"
-#endif
-#if ENABLE_CT_semi
-#include "semi_call_type.h"
-#endif
-
-#define default_call_type_init() \
- M5OP_MERGE_TOKENS(DEFAULT_CALL_TYPE, _call_type_init())
+DispatchTable *init_call_type(Args *args);
#endif // __CALL_TYPE_H__
--- /dev/null
+/*
+ * 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 <err.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "args.h"
+#include "commands.h"
+#include "usage.h"
+
+static int
+read_file(DispatchTable *dt, int dest_fid)
+{
+ uint8_t buf[256*1024];
+ int offset = 0;
+ int len, ret;
+
+ // Touch all buffer pages to ensure they are mapped in the
+ // page table. This is required in the case of X86_FS, where
+ // Linux does demand paging.
+ memset(buf, 0, sizeof(buf));
+
+ while ((len = (*dt->m5_read_file)(buf, sizeof(buf), offset)) > 0) {
+ uint8_t *base = buf;
+ offset += len;
+ do {
+ ret = write(dest_fid, base, len);
+ if (ret < 0) {
+ perror("Failed to write file");
+ exit(2);
+ } else if (ret == 0) {
+ fprintf(stderr, "Failed to write file: "
+ "Unhandled short write\n");
+ exit(2);
+ }
+
+ base += ret;
+ len -= ret;
+ } while (len);
+ }
+
+ return offset;
+}
+
+static void
+write_file(DispatchTable *dt, const char *filename, const char *host_filename)
+{
+ fprintf(stderr, "opening %s\n", filename);
+ int src_fid = open(filename, O_RDONLY);
+
+ if (src_fid < 0) {
+ fprintf(stderr, "error opening %s\n", filename);
+ return;
+ }
+
+ char buf[256*1024];
+ int offset = 0;
+ int len;
+ int bytes = 0;
+
+ memset(buf, 0, sizeof(buf));
+
+ while ((len = read(src_fid, buf, sizeof(buf))) > 0) {
+ bytes += (*dt->m5_write_file)(buf, len, offset, host_filename);
+ offset += len;
+ }
+ fprintf(stderr, "written %d bytes\n", bytes);
+
+ close(src_fid);
+}
+
+static void
+do_exit(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]);
+}
+
+static void
+do_fail(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]);
+}
+
+static void
+do_reset_stats(DispatchTable *dt, Args *args)
+{
+ uint64_t ints[2];
+ if (!parse_int_args(args, ints, 2))
+ usage();
+ (*dt->m5_reset_stats)(ints[0], ints[1]);
+}
+
+static void
+do_dump_stats(DispatchTable *dt, Args *args)
+{
+ uint64_t ints[2];
+ if (!parse_int_args(args, ints, 2))
+ usage();
+ (*dt->m5_dump_stats)(ints[0], ints[1]);
+}
+
+static void
+do_dump_reset_stats(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]);
+}
+
+static void
+do_read_file(DispatchTable *dt, Args *args)
+{
+ if (args->argc > 0)
+ usage();
+
+ read_file(dt, STDOUT_FILENO);
+}
+
+static void
+do_write_file(DispatchTable *dt, Args *args)
+{
+ if (args->argc != 1 && args->argc != 2)
+ usage();
+
+ const char *filename = pop_arg(args);
+ const char *host_filename = pop_arg(args);
+ if (!host_filename)
+ host_filename = filename;
+
+ write_file(dt, filename, host_filename);
+}
+
+static void
+do_checkpoint(DispatchTable *dt, Args *args)
+{
+ uint64_t ints[2];
+ if (!parse_int_args(args, ints, 2))
+ usage();
+ (*dt->m5_checkpoint)(ints[0], ints[1]);
+}
+
+static void
+do_addsymbol(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);
+}
+
+
+static void
+do_loadsymbol(DispatchTable *dt, Args *args)
+{
+ if (args->argc > 0)
+ usage();
+
+ (*dt->m5_load_symbol)();
+}
+
+static void
+do_initparam(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]);
+ printf("%"PRIu64, val);
+}
+
+struct CommandInfo command_table[] = {
+ { "addsymbol", do_addsymbol, "<address> <symbol> // Adds a "
+ "symbol with address \"address\" "
+ "to gem5's symbol table" },
+ { "checkpoint", do_checkpoint, "[delay [period]] // After "
+ "delay (default 0) take a "
+ "checkpoint, and then optionally "
+ "every period after" },
+ { "dumpresetstats", do_dump_reset_stats, "[delay [period]] // After "
+ "delay (default 0) dump and "
+ "reset the stats, and then "
+ "optionally every period after" },
+ { "dumpstats", do_dump_stats, "[delay [period]] // After "
+ "delay (default 0) dump the "
+ "stats, and then optionally "
+ "every period after" },
+ { "exit", do_exit, "[delay] // Exit after delay, "
+ "or immediately" },
+ { "fail", do_fail, "<code> [delay] // Exit with "
+ "failure code code after delay, "
+ "or immediately" },
+ { "initparam", do_initparam, "[key] // optional key may be at "
+ "most 16 characters long" },
+ { "loadsymbol", do_loadsymbol, "load a preselected symbol file "
+ "into gem5's symbol table" },
+ { "readfile", do_read_file, "read a preselected file from "
+ "the host and write it to "
+ "stdout" },
+ { "resetstats", do_reset_stats, "[delay [period]] // After "
+ "delay (default 0) reset the "
+ "stats, and then optionally "
+ "every period after" },
+ { "writefile", do_write_file, "<filename> [host filename] // "
+ "Write a file to the host, "
+ "optionally with a different "
+ "name" },
+};
+
+int num_commands = sizeof(command_table) / sizeof(CommandInfo);
--- /dev/null
+/*
+ * 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.
+ */
+
+#ifndef __COMMANDS_H__
+#define __COMMANDS_H__
+
+#include "args.h"
+#include "dispatch_table.h"
+
+typedef struct CommandInfo
+{
+ // The name of the command.
+ 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);
+ // Help text for this command.
+ char *usage;
+} CommandInfo;
+
+// The commands themselves.
+extern CommandInfo command_table[];
+
+// The number of commands.
+extern int num_commands;
+
+#endif // __COMMANDS_H__
};
int
-inst_call_type_detect(int *argc, char **argv[])
+inst_call_type_detect(Args *args)
{
- if (*argc > 0 && strcmp((*argv)[0], "--inst") == 0) {
- (*argc)--;
- (*argv)++;
+ if (args->argc && strcmp(args->argv[0], "--inst") == 0) {
+ pop_arg(args);
return 1;
}
return 0;
#ifndef __INST_CALL_TYPE_H__
#define __INST_CALL_TYPE_H__
+#include "args.h"
#include "dispatch_table.h"
-int inst_call_type_detect(int *argc, char **argv[]);
+int inst_call_type_detect(Args *args);
DispatchTable *inst_call_type_init();
#endif // __INST_CALL_TYPE_H__
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <err.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <gem5/asm/generic/m5ops.h>
-#include <gem5/m5ops.h>
#include "args.h"
#include "call_type.h"
-#include "dispatch_table.h"
-#include "m5_mmap.h"
-
-char *progname;
-char *command = "unspecified";
-void usage();
+#include "commands.h"
+#include "usage.h"
int
-read_file(DispatchTable *dt, int dest_fid)
-{
- uint8_t buf[256*1024];
- int offset = 0;
- int len, ret;
-
- // Touch all buffer pages to ensure they are mapped in the
- // page table. This is required in the case of X86_FS, where
- // Linux does demand paging.
- memset(buf, 0, sizeof(buf));
-
- while ((len = (*dt->m5_read_file)(buf, sizeof(buf), offset)) > 0) {
- uint8_t *base = buf;
- offset += len;
- do {
- ret = write(dest_fid, base, len);
- if (ret < 0) {
- perror("Failed to write file");
- exit(2);
- } else if (ret == 0) {
- fprintf(stderr, "Failed to write file: "
- "Unhandled short write\n");
- exit(2);
- }
-
- base += ret;
- len -= ret;
- } while (len);
- }
-
- return offset;
-}
-
-void
-write_file(DispatchTable *dt, const char *filename, const char *host_filename)
-{
- fprintf(stderr, "opening %s\n", filename);
- int src_fid = open(filename, O_RDONLY);
-
- if (src_fid < 0) {
- fprintf(stderr, "error opening %s\n", filename);
- return;
- }
-
- char buf[256*1024];
- int offset = 0;
- int len;
- int bytes = 0;
-
- memset(buf, 0, sizeof(buf));
-
- while ((len = read(src_fid, buf, sizeof(buf))) > 0) {
- bytes += (*dt->m5_write_file)(buf, len, offset, host_filename);
- offset += len;
- }
- fprintf(stderr, "written %d bytes\n", bytes);
-
- close(src_fid);
-}
-
-void
-do_exit(DispatchTable *dt, int argc, char *argv[])
-{
- if (argc > 1)
- usage();
-
- uint64_t ints[1];
- if (!parse_int_args(argc, argv, ints, 1))
- usage();
- (*dt->m5_exit)(ints[0]);
-}
-
-void
-do_fail(DispatchTable *dt, int argc, char *argv[])
-{
- if (argc < 1 || argc > 2)
- usage();
-
- uint64_t ints[2] = {0,0};
- if (!parse_int_args(argc, argv, ints, argc))
- usage();
- (*dt->m5_fail)(ints[1], ints[0]);
-}
-
-void
-do_reset_stats(DispatchTable *dt, int argc, char *argv[])
-{
- uint64_t ints[2];
- if (!parse_int_args(argc, argv, ints, 2))
- usage();
- (*dt->m5_reset_stats)(ints[0], ints[1]);
-}
-
-void
-do_dump_stats(DispatchTable *dt, int argc, char *argv[])
-{
- uint64_t ints[2];
- if (!parse_int_args(argc, argv, ints, 2))
- usage();
- (*dt->m5_dump_stats)(ints[0], ints[1]);
-}
-
-void
-do_dump_reset_stats(DispatchTable *dt, int argc, char *argv[])
-{
- uint64_t ints[2];
- if (!parse_int_args(argc, argv, ints, 2))
- usage();
- (*dt->m5_dump_reset_stats)(ints[0], ints[1]);
-}
-
-void
-do_read_file(DispatchTable *dt, int argc, char *argv[])
-{
- if (argc > 0)
- usage();
-
- read_file(dt, STDOUT_FILENO);
-}
-
-void
-do_write_file(DispatchTable *dt, int argc, char *argv[])
-{
- if (argc != 1 && argc != 2)
- usage();
-
- const char *filename = argv[0];
- const char *host_filename = (argc == 2) ? argv[1] : argv[0];
-
- write_file(dt, filename, host_filename);
-}
-
-void
-do_checkpoint(DispatchTable *dt, int argc, char *argv[])
+main(int argc, const char *argv[])
{
- uint64_t ints[2];
- if (!parse_int_args(argc, argv, ints, 2))
- usage();
- (*dt->m5_checkpoint)(ints[0], ints[1]);
-}
+ Args args = { argc, argv };
-void
-do_addsymbol(DispatchTable *dt, int argc, char *argv[])
-{
- if (argc != 2)
+ if (!args.argc)
usage();
- uint64_t addr = strtoul(argv[0], NULL, 0);
- char *symbol = argv[1];
- (*dt->m5_add_symbol)(addr, symbol);
-}
+ progname = pop_arg(&args);
+ DispatchTable *dt = init_call_type(&args);
-void
-do_loadsymbol(DispatchTable *dt, int argc, char *argv[])
-{
- if (argc > 0)
- usage();
-
- (*dt->m5_load_symbol)();
-}
+ const char *command = pop_arg(&args);
-void
-do_initparam(DispatchTable *dt, int argc, char *argv[])
-{
- if (argc > 1)
+ if (!command)
usage();
- uint64_t key_str[2];
- if (!pack_str_into_regs(argc == 0 ? "" : argv[0], key_str, 2))
- usage();
- uint64_t val = (*dt->m5_init_param)(key_str[0], key_str[1]);
- printf("%"PRIu64, val);
-}
-
-struct MainFunc
-{
- char *name;
- void (*func)(DispatchTable *dt, int argc, char *argv[]);
- char *usage;
-};
-
-struct MainFunc mainfuncs[] = {
- { "addsymbol", do_addsymbol, "<address> <symbol> // Adds a "
- "symbol with address \"address\" "
- "to gem5's symbol table" },
- { "checkpoint", do_checkpoint, "[delay [period]] // After "
- "delay (default 0) take a "
- "checkpoint, and then optionally "
- "every period after" },
- { "dumpresetstats", do_dump_reset_stats, "[delay [period]] // After "
- "delay (default 0) dump and "
- "reset the stats, and then "
- "optionally every period after" },
- { "dumpstats", do_dump_stats, "[delay [period]] // After "
- "delay (default 0) dump the "
- "stats, and then optionally "
- "every period after" },
- { "exit", do_exit, "[delay] // Exit after delay, "
- "or immediately" },
- { "fail", do_fail, "<code> [delay] // Exit with "
- "failure code code after delay, "
- "or immediately" },
- { "initparam", do_initparam, "[key] // optional key may be at "
- "most 16 characters long" },
- { "loadsymbol", do_loadsymbol, "load a preselected symbol file "
- "into gem5's symbol table" },
- { "readfile", do_read_file, "read a preselected file from "
- "the host and write it to "
- "stdout" },
- { "resetstats", do_reset_stats, "[delay [period]] // After "
- "delay (default 0) reset the "
- "stats, and then optionally "
- "every period after" },
- { "writefile", do_write_file, "<filename> [host filename] // "
- "Write a file to the host, "
- "optionally with a different "
- "name" },
-};
-int numfuncs = sizeof(mainfuncs) / sizeof(mainfuncs[0]);
-
-void
-usage()
-{
- 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, "\n");
- fprintf(stderr, "Commands:\n");
- for (int i = 0; i < numfuncs; ++i)
- fprintf(stderr, " %s %s\n", mainfuncs[i].name, mainfuncs[i].usage);
- fprintf(stderr, "\n");
- fprintf(stderr, "All times in nanoseconds!\n");
-
- exit(1);
-}
-
-int
-main(int argc, char *argv[])
-{
- progname = argv[0];
-
- argv++;
- argc--;
-
- DispatchTable *dt = NULL;
-
-# if ENABLE_CT_inst
- if (!dt && inst_call_type_detect(&argc, &argv)) {
- dt = inst_call_type_init();
- }
-# endif
-# if ENABLE_CT_addr
- if (!dt) {
- int detect = addr_call_type_detect(&argc, &argv);
- if (detect < 0)
- usage();
- if (detect > 0)
- dt = addr_call_type_init();
- }
-# endif
-# if ENABLE_CT_semi
- if (!dt && semi_call_type_detect(&argc, &argv)) {
- dt = semi_call_type_init();
- }
-# endif
- if (!dt)
- dt = default_call_type_init();
-
- if (!argc)
- usage(1);
-
- command = argv[0];
-
- argv++;
- argc--;
-
- int i;
- for (i = 0; i < numfuncs; ++i) {
- if (strcmp(command, mainfuncs[i].name) != 0)
+ for (int i = 0; i < num_commands; ++i) {
+ if (strcmp(command, command_table[i].name) != 0)
continue;
- mainfuncs[i].func(dt, argc, argv);
+ command_table[i].func(dt, &args);
exit(0);
}
- usage(1);
+ usage();
}
};
int
-semi_call_type_detect(int *argc, char **argv[])
+semi_call_type_detect(Args *args)
{
- if (*argc > 0 && strcmp((*argv)[0], "--semi") == 0) {
- (*argc)--;
- (*argv)++;
+ if (args->argc && strcmp(args->argv[0], "--semi") == 0) {
+ pop_arg(args);
return 1;
}
return 0;
#ifndef __SEMI_CALL_TYPE_H__
#define __SEMI_CALL_TYPE_H__
+#include "args.h"
#include "dispatch_table.h"
-int semi_call_type_detect(int *argc, char **argv[]);
+int semi_call_type_detect(Args *args);
DispatchTable *semi_call_type_init();
#endif // __SEMI_CALL_TYPE_H__
--- /dev/null
+/*
+ * Copyright (c) 2011, 2017 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * 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 <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "commands.h"
+#include "usage.h"
+
+const char *progname = "{progname}";
+
+void
+usage()
+{
+ 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, "\n");
+ fprintf(stderr, "Commands:\n");
+ for (int i = 0; i < num_commands; ++i) {
+ fprintf(stderr, " %s %s\n",
+ command_table[i].name, command_table[i].usage);
+ }
+ fprintf(stderr, "\n");
+ fprintf(stderr, "All times in nanoseconds!\n");
+
+ exit(1);
+}
--- /dev/null
+/*
+ * Copyright (c) 2011, 2017 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * 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.
+ */
+
+#ifndef __USAGE_H__
+#define __USAGE_H__
+
+extern const char *progname;
+
+void usage();
+
+#endif // __USAGE_H__