summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAlasdair Armstrong2018-06-21 19:02:06 +0100
committerAlasdair Armstrong2018-06-21 19:19:28 +0100
commit7ef0bba057d634f7596f94000233cd36ebdd2fff (patch)
tree58a9a429e16096f3afedb75179bdb06b666a9572 /lib
parent2005eb7c190f8d28d6499df3dd77cf65a87e60cb (diff)
Add command line option support for Sail->C compiled models
For example, the MIPS model can boot FreeBSD as ./mips_c --binary=0x100000,/path/to/kernel --image=/path/to/simboot.sailbin Or with short options as ./mips_c -b 0x100000,/path/to/kernel -i /path/to/simboot.sailbin The current options are: -e, --elf, which loads an elf file directly -n, --entry, which sets the entry point -i, --image, which loads an image file compiled by "sail -elf" using Linksem -b, --binary, which loads a plain binary image into memory at a specific address -l, --cyclelimit, which means the (new) cycle_count() builtin exits the model after a certain number of calls Also there are the default -? --help and --usage options.
Diffstat (limited to 'lib')
-rw-r--r--lib/rts.c97
-rw-r--r--lib/rts.h8
2 files changed, 102 insertions, 3 deletions
diff --git a/lib/rts.c b/lib/rts.c
index 563d11e2..e9ecc5fd 100644
--- a/lib/rts.c
+++ b/lib/rts.c
@@ -1,4 +1,6 @@
#include<string.h>
+#include<argp.h>
+#include<inttypes.h>
#include"sail.h"
#include"rts.h"
@@ -168,6 +170,11 @@ unit load_raw(mach_bits addr, const sail_string file)
{
FILE *fp = fopen(file, "r");
+ if (!fp) {
+ fprintf(stderr, "[Sail] Raw file %s could not be loaded\n", file);
+ exit(EXIT_FAILURE);
+ }
+
uint64_t byte;
while ((byte = (uint64_t)fgetc(fp)) != EOF) {
write_mem(addr, byte);
@@ -182,7 +189,7 @@ void load_image(char *file)
FILE *fp = fopen(file, "r");
if (!fp) {
- fprintf(stderr, "Image file %s could not be loaded\n", file);
+ fprintf(stderr, "[Sail] Image file %s could not be loaded\n", file);
exit(EXIT_FAILURE);
}
@@ -198,10 +205,10 @@ void load_image(char *file)
if (!strcmp(addr, "elf_entry\n")) {
if (sscanf(data, "%" PRIu64 "\n", &g_elf_entry) != 1) {
- fprintf(stderr, "Failed to parse elf_entry\n");
+ fprintf(stderr, "[Sail] Failed to parse elf_entry\n");
exit(EXIT_FAILURE);
};
- printf("Elf entry point: %" PRIx64 "\n", g_elf_entry);
+ fprintf(stderr, "[Sail] Elf entry point: %" PRIx64 "\n", g_elf_entry);
} else {
write_mem((uint64_t) atoll(addr), (uint64_t) atoll(data));
}
@@ -314,6 +321,90 @@ void elf_tohost(mpz_t *rop, const unit u)
mpz_set_ui(*rop, 0x0ul);
}
+/* ***** Cycle limit ***** */
+
+static uint64_t g_cycle_count = 0;
+static uint64_t g_cycle_limit;
+
+unit cycle_count(const unit u)
+{
+ if (++g_cycle_count >= g_cycle_limit && g_cycle_limit != 0) {
+ printf("[Sail] cycle limit %" PRId64 " reached\n", g_cycle_limit);
+ exit(EXIT_SUCCESS);
+ }
+
+ return UNIT;
+}
+
+/* ***** Argument Parsing ***** */
+
+static char doc[] =
+ "Sail RTS -- Sail C run time system";
+
+/* A description of the arguments we accept. */
+static char args_doc[] = "ARG";
+
+static struct argp_option options[] = {
+ {"elf", 'e', "FILE", 0, "Load an ELF file"},
+ {"entry", 'n', "ADDRESS", 0, "Manually set the entry address"},
+ {"image", 'i', "FILE", 0, "Load an Linksem preprocessed ELF image"},
+ {"binary", 'b', "ADDRESS,FILE", 0, "Load a raw binary file"},
+ {"cyclelimit", 'l', "NUMBER", 0, "Set a cycle limit"},
+ { 0 }
+};
+
+static error_t parse_opt(int key, char *arg, struct argp_state *state)
+{
+ switch (key) {
+ case 'b': ;
+ uint64_t addr;
+ char *file;
+
+ if (!sscanf(arg, "0x%" PRIx64 ",%ms", &addr, &file)) {
+ fprintf(stderr, "Could not parse argument %s\n", arg);
+ return EINVAL;
+ };
+
+ load_raw(addr, file);
+ free(file);
+ break;
+
+ case 'i':
+ load_image(arg);
+ break;
+
+ case 'e':
+ load_elf(arg);
+ break;
+
+ case 'n':
+ if (!sscanf(arg, "0x%" PRIx64, &g_elf_entry)) {
+ fprintf(stderr, "Could not parse address %s\n", arg);
+ return EINVAL;
+ }
+ break;
+
+ case 'l':
+ if (!sscanf(arg, "%" PRId64, &g_cycle_limit)) {
+ fprintf(stderr, "Could not parse cycle limit %s\n", arg);
+ return EINVAL;
+ }
+ break;
+
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+
+ return 0;
+}
+
+static struct argp argp = {options, parse_opt, args_doc, doc};
+
+int process_arguments(int argc, char *argv[])
+{
+ return argp_parse (&argp, argc, argv, 0, 0, NULL);
+}
+
/* ***** Setup and cleanup functions for RTS ***** */
void setup_rts(void)
diff --git a/lib/rts.h b/lib/rts.h
index 7f26df4e..b0e59252 100644
--- a/lib/rts.h
+++ b/lib/rts.h
@@ -100,6 +100,12 @@ void trace_start(char *);
void trace_end(void);
/*
+ * Functions for counting and limiting cycles
+ */
+
+unit cycle_count(const unit);
+
+/*
* Functions to get info from ELF files.
*/
@@ -108,6 +114,8 @@ static uint64_t g_elf_entry;
void elf_entry(sail_int *rop, const unit u);
void elf_tohost(sail_int *rop, const unit u);
+int process_arguments(int, char**);
+
/*
* setup_rts and cleanup_rts are responsible for calling setup_library
* and cleanup_library in sail.h.