Make emulator.cc understand HTIF arguments
This, with riscv-fesvr modifications, enables the rocket-chip emulator to understand (and error out) if a command line argument that will eventually be consumed by HTIF looks bad and can error out quickly. This relies on modifications to risc-fesvr to support getopt and the exposure of what HTIF arguments exist via the `htif.h` header.
This commit is contained in:
parent
3ead9a5d2d
commit
1aa87f6578
109
csrc/emulator.cc
109
csrc/emulator.cc
@ -37,33 +37,39 @@ extern "C" int vpi_get_vlog_info(void* arg)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usage(const char * program_name) {
|
static void usage(const char * program_name)
|
||||||
printf("Usage: %s [OPTION]... BINARY [BINARY ARGS]\n", program_name);
|
{
|
||||||
|
printf("Usage: %s [EMULATOR OPTION]... [HOST OPTION]... BINARY [TARGET OPTION]...\n",
|
||||||
|
program_name);
|
||||||
fputs("\
|
fputs("\
|
||||||
Run a BINARY on the Rocket Chip emulator.\n\
|
Run a BINARY on the Rocket Chip emulator.\n\
|
||||||
\n\
|
\n\
|
||||||
Mandatory arguments to long options are mandatory for short options too.\n\
|
Mandatory arguments to long options are mandatory for short options too.\n\
|
||||||
-c, --cycle-count print the cycle count before exiting\n\
|
\n\
|
||||||
|
EMULATOR OPTIONS\n\
|
||||||
|
-c, --cycle-count Print the cycle count before exiting\n\
|
||||||
+cycle-count\n\
|
+cycle-count\n\
|
||||||
-h, --help display this help and exit\n\
|
-h, --help Display this help and exit\n\
|
||||||
-m, --max-cycles=CYCLES kill the emulation after CYCLES\n\
|
-m, --max-cycles=[CYCLES] Kill the emulation after CYCLES\n\
|
||||||
+max-cycles=CYCLES\n\
|
+max-cycles=[CYCLES]\n\
|
||||||
-s, --seed=SEED use random number seed SEED\n\
|
-s, --seed=[SEED] Use random number seed SEED\n\
|
||||||
-V, --verbose enable all Chisel printfs\n\
|
-V, --verbose Enable all Chisel printfs\n\
|
||||||
+verbose\n\
|
+verbose\n\
|
||||||
", stdout);
|
", stdout);
|
||||||
#if VM_TRACE
|
#if VM_TRACE
|
||||||
fputs("\
|
fputs("\
|
||||||
-v, --vcd=FILE, write vcd trace to FILE (or '-' for stdout)\n\
|
-v, --vcd=[FILE], write vcd trace to FILE (or '-' for stdout)\n\
|
||||||
-x, --dump-start=CYCLE start VCD tracing at CYCLE\n\
|
-x, --dump-start=[CYCLE] start VCD tracing at CYCLE\n\
|
||||||
+dump-start\n\
|
+dump-start\n\
|
||||||
|
\n\
|
||||||
|
EMULATOR OPTIONS (unsupported in non-debug build -- try `make debug`)\n\
|
||||||
", stdout);
|
", stdout);
|
||||||
#else
|
#endif
|
||||||
fputs("\
|
fputs("\
|
||||||
VCD options (e.g., -v, +dump-start) require a debug-enabled emulator.\n\
|
VCD options (e.g., -v, +dump-start) require a debug-enabled emulator.\n\
|
||||||
Try `make debug`.\n\
|
Try `make debug`.\n\
|
||||||
", stdout);
|
", stdout);
|
||||||
#endif
|
fputs(HTIF_USAGE_OPTIONS, stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
@ -76,8 +82,8 @@ int main(int argc, char** argv)
|
|||||||
FILE * vcdfile = NULL;
|
FILE * vcdfile = NULL;
|
||||||
uint64_t start = 0;
|
uint64_t start = 0;
|
||||||
#endif
|
#endif
|
||||||
|
char ** htif_argv = NULL;
|
||||||
|
|
||||||
std::vector<std::string> to_dtm;
|
|
||||||
while (1) {
|
while (1) {
|
||||||
static struct option long_options[] = {
|
static struct option long_options[] = {
|
||||||
{"cycle-count", no_argument, 0, 'c' },
|
{"cycle-count", no_argument, 0, 'c' },
|
||||||
@ -89,7 +95,7 @@ int main(int argc, char** argv)
|
|||||||
{"vcd", required_argument, 0, 'v' },
|
{"vcd", required_argument, 0, 'v' },
|
||||||
{"dump-start", required_argument, 0, 'x' },
|
{"dump-start", required_argument, 0, 'x' },
|
||||||
#endif
|
#endif
|
||||||
{0, 0, 0, 0}
|
HTIF_LONG_OPTIONS
|
||||||
};
|
};
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
#if VM_TRACE
|
#if VM_TRACE
|
||||||
@ -98,8 +104,9 @@ int main(int argc, char** argv)
|
|||||||
int c = getopt_long(argc, argv, "-chm:s:V", long_options, &option_index);
|
int c = getopt_long(argc, argv, "-chm:s:V", long_options, &option_index);
|
||||||
#endif
|
#endif
|
||||||
if (c == -1) break;
|
if (c == -1) break;
|
||||||
|
retry:
|
||||||
switch (c) {
|
switch (c) {
|
||||||
// Process "normal" options with '--' long options or '-' short options
|
// Process long and short EMULATOR options
|
||||||
case '?': usage(argv[0]); return 1;
|
case '?': usage(argv[0]); return 1;
|
||||||
case 'c': print_cycles = true; break;
|
case 'c': print_cycles = true; break;
|
||||||
case 'h': usage(argv[0]); return 0;
|
case 'h': usage(argv[0]); return 0;
|
||||||
@ -117,39 +124,67 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
case 'x': start = atoll(optarg); break;
|
case 'x': start = atoll(optarg); break;
|
||||||
#endif
|
#endif
|
||||||
// Processing of legacy '+' options and recognition of when
|
// Process legacy '+' EMULATOR arguments by replacing them with
|
||||||
// we've hit the binary. The binary is expected to be a
|
// their getopt equivalents
|
||||||
// non-option and not start with '-' or '+'.
|
|
||||||
case 1: {
|
case 1: {
|
||||||
std::string arg = optarg;
|
std::string arg = optarg;
|
||||||
if (arg == "+verbose")
|
if (arg.substr(0, 1) != "+") {
|
||||||
verbose = true;
|
optind--;
|
||||||
else if (arg.substr(0, 12) == "+max-cycles=")
|
|
||||||
max_cycles = atoll(optarg+12);
|
|
||||||
#if VM_TRACE
|
|
||||||
else if (arg.substr(0, 12) == "+dump-start=")
|
|
||||||
start = atoll(optarg+12);
|
|
||||||
#endif
|
|
||||||
else if (arg.substr(0, 12) == "+cycle-count")
|
|
||||||
print_cycles = true;
|
|
||||||
else {
|
|
||||||
to_dtm.push_back(optarg);
|
|
||||||
goto done_processing;
|
goto done_processing;
|
||||||
}
|
}
|
||||||
break;
|
if (arg == "+verbose")
|
||||||
|
c = 'V';
|
||||||
|
else if (arg.substr(0, 12) == "+max-cycles=") {
|
||||||
|
c = 'm';
|
||||||
|
optarg = optarg+12;
|
||||||
|
}
|
||||||
|
#if VM_TRACE
|
||||||
|
else if (arg.substr(0, 12) == "+dump-start=")
|
||||||
|
c = 'x';
|
||||||
|
optarg = optarg+12;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else if (arg.substr(0, 12) == "+cycle-count")
|
||||||
|
c = 'c';
|
||||||
|
// If we don't find a legacy '+' argument, it still could be
|
||||||
|
// an HTIF (HOST) argument and not an error. If this is the
|
||||||
|
// case, then we're doing processing EMULATOR arguments.
|
||||||
|
else {
|
||||||
|
static struct option htif_long_options [] = { HTIF_LONG_OPTIONS };
|
||||||
|
struct option * htif_option = &htif_long_options[0];
|
||||||
|
while (htif_option->name) {
|
||||||
|
if (arg.substr(1, strlen(htif_option->name)) == htif_option->name) {
|
||||||
|
optind--;
|
||||||
|
goto done_processing;
|
||||||
|
}
|
||||||
|
htif_option++;
|
||||||
|
}
|
||||||
|
std::cerr << argv[0] << ": invalid HTIF legacy plus-arg \"" << arg << "\"\n";
|
||||||
|
c = '?';
|
||||||
|
}
|
||||||
|
goto retry;
|
||||||
}
|
}
|
||||||
|
// Realize that we've hit HTIF (HOST) arguments or error out
|
||||||
|
default:
|
||||||
|
if (c >= HTIF_LONG_OPTIONS_OPTIND) {
|
||||||
|
optind--;
|
||||||
|
goto done_processing;
|
||||||
|
}
|
||||||
|
c = '?';
|
||||||
|
goto retry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
done_processing:
|
done_processing:
|
||||||
if (optind < argc)
|
if (optind == argc) {
|
||||||
while (optind < argc)
|
|
||||||
to_dtm.push_back(argv[optind++]);
|
|
||||||
if (!to_dtm.size()) {
|
|
||||||
std::cerr << "No binary specified for emulator\n";
|
std::cerr << "No binary specified for emulator\n";
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
int htif_argc = 1 + argc - optind;
|
||||||
|
htif_argv = (char **) malloc((htif_argc) * sizeof (char *));
|
||||||
|
htif_argv[0] = argv[0];
|
||||||
|
for (int i = 1; optind < argc;) htif_argv[i++] = argv[optind++];
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
fprintf(stderr, "using random seed %u\n", random_seed);
|
fprintf(stderr, "using random seed %u\n", random_seed);
|
||||||
@ -171,9 +206,8 @@ done_processing:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dtm = new dtm_t(to_dtm);
|
|
||||||
//TODO: Specify port.
|
|
||||||
jtag = new remote_bitbang_t(0);
|
jtag = new remote_bitbang_t(0);
|
||||||
|
dtm = new dtm_t(htif_argc, htif_argv);
|
||||||
|
|
||||||
signal(SIGTERM, handle_sigterm);
|
signal(SIGTERM, handle_sigterm);
|
||||||
|
|
||||||
@ -248,5 +282,6 @@ done_processing:
|
|||||||
if (dtm) delete dtm;
|
if (dtm) delete dtm;
|
||||||
if (jtag) delete jtag;
|
if (jtag) delete jtag;
|
||||||
if (tile) delete tile;
|
if (tile) delete tile;
|
||||||
|
if (htif_argv) free(htif_argv);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user