Cleanup emulator.cc, use getopt, add help text (#487)
This changes the emulator to conform to POSIX-style options (e.g., short/'-' and long/'--') while preserving legacy option parsing (i.e., '+'). Options are read from the user until the first non-option (either POSIX or legacy) is encountered. This and everything following is assumed to be the binary and any arguments the user wants to run on the emulator. All non-options are passed directly to the DTM. This allows for the same option to be passed, safely, to both the emulator and the binary, e.g., "+verbose". This introduces a dependency on <getopt.h>. Closes #484.
This commit is contained in:
parent
540502f96d
commit
7e794212d9
141
csrc/emulator.cc
141
csrc/emulator.cc
@ -12,6 +12,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
|
||||
extern dtm_t* dtm;
|
||||
static uint64_t trace_count = 0;
|
||||
@ -33,33 +34,123 @@ extern "C" int vpi_get_vlog_info(void* arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void usage(const char * program_name) {
|
||||
printf("Usage: %s [OPTION]... BINARY [BINARY ARGS]\n", program_name);
|
||||
fputs("\
|
||||
Run a BINARY on the Rocket Chip emulator.\n\
|
||||
\n\
|
||||
Mandatory arguments to long options are mandatory for short options too.\n\
|
||||
-c, --cycle-count print the cycle count before exiting\n\
|
||||
+cycle-count\n\
|
||||
-h, --help display this help and exit\n\
|
||||
-m, --max-cycles=CYCLES kill the emulation after CYCLES\n\
|
||||
+max-cycles=CYCLES\n\
|
||||
-s, --seed=SEED use random number seed SEED\n\
|
||||
-V, --verbose enable all Chisel printfs\n\
|
||||
+verbose\n\
|
||||
", stdout);
|
||||
#if VM_TRACE
|
||||
fputs("\
|
||||
-v, --vcd=FILE, write vcd trace to FILE (or '-' for stdout)\n\
|
||||
-x, --start=CYCLE start VCD tracing at CYCLE\n\
|
||||
+start\n\
|
||||
", stdout);
|
||||
#else
|
||||
fputs("\
|
||||
VCD options (e.g., -v, +start) require a debug-enabled emulator.\n\
|
||||
Try `make debug`.\n\
|
||||
", stdout);
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
unsigned random_seed = (unsigned)time(NULL) ^ (unsigned)getpid();
|
||||
uint64_t max_cycles = -1;
|
||||
uint64_t start = 0;
|
||||
int ret = 0;
|
||||
FILE *vcdfile = NULL;
|
||||
bool print_cycles = false;
|
||||
#if VM_TRACE
|
||||
FILE * vcdfile = NULL;
|
||||
uint64_t start = 0;
|
||||
#endif
|
||||
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
std::string arg = argv[i];
|
||||
if (arg.substr(0, 2) == "-v") {
|
||||
const char* filename = argv[i]+2;
|
||||
vcdfile = strcmp(filename, "-") == 0 ? stdout : fopen(filename, "w");
|
||||
if (!vcdfile)
|
||||
abort();
|
||||
} else if (arg.substr(0, 2) == "-s")
|
||||
random_seed = atoi(argv[i]+2);
|
||||
else if (arg == "+verbose")
|
||||
verbose = true;
|
||||
else if (arg.substr(0, 12) == "+max-cycles=")
|
||||
max_cycles = atoll(argv[i]+12);
|
||||
else if (arg.substr(0, 7) == "+start=")
|
||||
start = atoll(argv[i]+7);
|
||||
else if (arg.substr(0, 12) == "+cycle-count")
|
||||
print_cycles = true;
|
||||
std::vector<std::string> to_dtm;
|
||||
while (1) {
|
||||
static struct option long_options[] = {
|
||||
{"cycle-count", no_argument, 0, 'c' },
|
||||
{"help", no_argument, 0, 'h' },
|
||||
{"max-cycles", required_argument, 0, 'm' },
|
||||
{"seed", required_argument, 0, 's' },
|
||||
{"verbose", no_argument, 0, 'V' },
|
||||
#if VM_TRACE
|
||||
{"vcd", required_argument, 0, 'v' },
|
||||
{"start", required_argument, 0, 'x' },
|
||||
#endif
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
int option_index = 0;
|
||||
#if VM_TRACE
|
||||
int c = getopt_long(argc, argv, "-chm:s:v:Vx:", long_options, &option_index);
|
||||
#else
|
||||
int c = getopt_long(argc, argv, "-chm:s:V", long_options, &option_index);
|
||||
#endif
|
||||
if (c == -1) break;
|
||||
switch (c) {
|
||||
// Process "normal" options with '--' long options or '-' short options
|
||||
case '?': usage(argv[0]); return 1;
|
||||
case 'c': print_cycles = true; break;
|
||||
case 'h': usage(argv[0]); return 0;
|
||||
case 'm': max_cycles = atoll(optarg); break;
|
||||
case 's': random_seed = atoi(optarg); break;
|
||||
case 'V': verbose = true; break;
|
||||
#if VM_TRACE
|
||||
case 'v': {
|
||||
vcdfile = strcmp(optarg, "-") == 0 ? stdout : fopen(optarg, "w");
|
||||
if (!vcdfile) {
|
||||
std::cerr << "Unable to open " << optarg << " for VCD write\n";
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'x': start = atoll(optarg); break;
|
||||
#endif
|
||||
// Processing of legacy '+' options and recognition of when
|
||||
// we've hit the binary. The binary is expected to be a
|
||||
// non-option and not start with '-' or '+'.
|
||||
case 1: {
|
||||
if (optarg[0] != '+') {
|
||||
to_dtm.push_back(optarg);
|
||||
goto done_processing;
|
||||
}
|
||||
std::string arg = optarg;
|
||||
if (arg == "+verbose")
|
||||
verbose = true;
|
||||
else if (arg.substr(0, 12) == "+max-cycles=")
|
||||
max_cycles = atoll(optarg+12);
|
||||
#if VM_TRACE
|
||||
else if (arg.substr(0, 7) == "+start=")
|
||||
start = atoll(optarg+7);
|
||||
#endif
|
||||
else if (arg.substr(0, 12) == "+cycle-count")
|
||||
print_cycles = true;
|
||||
else {
|
||||
fprintf(stderr, "%s: unrecognized option '%s'\n", argv[0], optarg);
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done_processing:
|
||||
if (optind < argc)
|
||||
while (optind < argc)
|
||||
to_dtm.push_back(argv[optind++]);
|
||||
if (!to_dtm.size()) {
|
||||
std::cerr << "No binary specified for emulator\n";
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
@ -81,7 +172,7 @@ int main(int argc, char** argv)
|
||||
}
|
||||
#endif
|
||||
|
||||
dtm = new dtm_t(std::vector<std::string>(argv + 1, argv + argc));
|
||||
dtm = new dtm_t(to_dtm);
|
||||
|
||||
signal(SIGTERM, handle_sigterm);
|
||||
|
||||
@ -117,10 +208,9 @@ int main(int argc, char** argv)
|
||||
#if VM_TRACE
|
||||
if (tfp)
|
||||
tfp->close();
|
||||
#endif
|
||||
|
||||
if (vcdfile)
|
||||
fclose(vcdfile);
|
||||
#endif
|
||||
|
||||
if (dtm->exit_code())
|
||||
{
|
||||
@ -137,8 +227,7 @@ int main(int argc, char** argv)
|
||||
fprintf(stderr, "Completed after %ld cycles\n", trace_count);
|
||||
}
|
||||
|
||||
delete dtm;
|
||||
delete tile;
|
||||
|
||||
if (dtm) delete dtm;
|
||||
if (tile) delete tile;
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user