From 7ef0bba057d634f7596f94000233cd36ebdd2fff Mon Sep 17 00:00:00 2001 From: Alasdair Armstrong Date: Thu, 21 Jun 2018 19:02:06 +0100 Subject: 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. --- lib/rts.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- lib/rts.h | 8 ++++++ 2 files changed, 102 insertions(+), 3 deletions(-) (limited to 'lib') 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 +#include +#include #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 @@ -99,6 +99,12 @@ void trace_retend(void); 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. -- cgit v1.2.3