1
0
rocket-chip/csrc/emulator.cc

341 lines
9.6 KiB
C++
Raw Normal View History

// See LICENSE.SiFive for license details.
// See LICENSE.Berkeley for license details.
2014-09-12 19:15:04 +02:00
#include "verilated.h"
#if VM_TRACE
Header required for -DVM_TRACE=1 (#1294) With -DVM_TRACE=1 on gcc 7.2.0. Very small change. May only affect me. Is it possible -DVM_TRACE=1 is not regressed? ~~~~ http://en.cppreference.com/w/cpp/memory/unique_ptr [..]/emulator.cc: In function ‘int main(int, char**)’: [..]/emulator.cc:254:19: error: ‘VerilatedVcdFILE’ was not declared in this scope std::unique_ptr<VerilatedVcdFILE> vcdfd(new VerilatedVcdFILE(vcdfile)); ~~~~ More info : http://en.cppreference.com/w/cpp/memory/unique_ptr ~~~~ Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper OFFLOAD_TARGET_NAMES=nvptx-none OFFLOAD_TARGET_DEFAULT=1 Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu 7.2.0-8ubuntu3.2' --with-bugurl=file:///usr/share/doc/gcc-7/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-7 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 7.2.0 (Ubuntu 7.2.0-8ubuntu3.2) ~~~~
2018-03-20 02:07:28 +01:00
#include <memory>
#include "verilated_vcd_c.h"
#endif
#include <fesvr/dtm.h>
#include "remote_bitbang.h"
#include <iostream>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
2013-03-26 01:01:13 +01:00
#include <unistd.h>
#include <getopt.h>
2012-10-02 04:30:11 +02:00
// For option parsing, which is split across this file, Verilog, and
// FESVR's HTIF, a few external files must be pulled in. The list of
// files and what they provide is enumerated:
//
// $RISCV/include/fesvr/htif.h:
// defines:
// - HTIF_USAGE_OPTIONS
// - HTIF_LONG_OPTIONS_OPTIND
// - HTIF_LONG_OPTIONS
// $(ROCKETCHIP_DIR)/generated-src(-debug)?/$(CONFIG).plusArgs:
// defines:
// - PLUSARG_USAGE_OPTIONS
// variables:
// - static const char * verilog_plusargs
extern dtm_t* dtm;
extern remote_bitbang_t * jtag;
2016-06-23 21:17:26 +02:00
static uint64_t trace_count = 0;
2016-06-18 06:09:08 +02:00
bool verbose;
bool done_reset;
2016-06-18 06:09:08 +02:00
void handle_sigterm(int sig)
{
dtm->stop();
}
2016-06-23 21:17:26 +02:00
double sc_time_stamp()
{
return trace_count;
}
extern "C" int vpi_get_vlog_info(void* arg)
{
return 0;
}
static void usage(const char * program_name)
{
printf("Usage: %s [EMULATOR OPTION]... [VERILOG PLUSARG]... [HOST OPTION]... BINARY [TARGET OPTION]...\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\
\n\
EMULATOR OPTIONS\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 (cycle-by-cycle info)\n\
+verbose\n\
", stdout);
#if VM_TRACE == 0
fputs("\
\n\
EMULATOR DEBUG OPTIONS (only supported in debug build -- try `make debug`)\n",
stdout);
#endif
fputs("\
-v, --vcd=FILE, Write vcd trace to FILE (or '-' for stdout)\n\
-x, --dump-start=CYCLE Start VCD tracing at CYCLE\n\
+dump-start\n\
", stdout);
fputs("\n" PLUSARG_USAGE_OPTIONS, stdout);
fputs("\n" HTIF_USAGE_OPTIONS, stdout);
printf("\n"
"EXAMPLES\n"
" - run a bare metal test:\n"
" %s $RISCV/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-add\n"
" - run a bare metal test showing cycle-by-cycle information:\n"
" %s +verbose $RISCV/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-add 2>&1 | spike-dasm\n"
#if VM_TRACE
" - run a bare metal test to generate a VCD waveform:\n"
" %s -v rv64ui-p-add.vcd $RISCV/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-add\n"
#endif
" - run an ELF (you wrote, called 'hello') using the proxy kernel:\n"
" %s pk hello\n",
program_name, program_name, program_name
#if VM_TRACE
, program_name
#endif
);
}
2012-10-02 04:30:11 +02:00
int main(int argc, char** argv)
{
unsigned random_seed = (unsigned)time(NULL) ^ (unsigned)getpid();
uint64_t max_cycles = -1;
int ret = 0;
bool print_cycles = false;
#if VM_TRACE
FILE * vcdfile = NULL;
uint64_t start = 0;
#endif
char ** htif_argv = NULL;
int verilog_plusargs_legal = 1;
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' },
{"dump-start", required_argument, 0, 'x' },
#endif
HTIF_LONG_OPTIONS
};
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;
retry:
switch (c) {
// Process long and short EMULATOR 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
// Process legacy '+' EMULATOR arguments by replacing them with
// their getopt equivalents
case 1: {
std::string arg = optarg;
if (arg.substr(0, 1) != "+") {
optind--;
goto done_processing;
}
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 '+' EMULATOR argument, it still could be
// a VERILOG_PLUSARG and not an error.
else if (verilog_plusargs_legal) {
const char ** plusarg = &verilog_plusargs[0];
int legal_verilog_plusarg = 0;
while (*plusarg && (legal_verilog_plusarg == 0)){
if (arg.substr(1, strlen(*plusarg)) == *plusarg) {
legal_verilog_plusarg = 1;
}
plusarg ++;
}
if (!legal_verilog_plusarg) {
verilog_plusargs_legal = 0;
} else {
c = 'P';
}
goto retry;
}
// If we STILL 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 done processing EMULATOR and VERILOG 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 plus-arg (Verilog or HTIF) \""
<< arg << "\"\n";
c = '?';
}
goto retry;
}
case 'P': break; // Nothing to do here, Verilog PlusArg
// 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:
if (optind == argc) {
std::cerr << "No binary specified for emulator\n";
usage(argv[0]);
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++];
2012-10-02 04:30:11 +02:00
if (verbose)
fprintf(stderr, "using random seed %u\n", random_seed);
2016-07-09 11:37:39 +02:00
srand(random_seed);
srand48(random_seed);
2016-07-09 11:37:39 +02:00
Verilated::randReset(2);
Verilated::commandArgs(argc, argv);
TEST_HARNESS *tile = new TEST_HARNESS;
2016-07-09 11:37:39 +02:00
#if VM_TRACE
2016-07-09 11:37:39 +02:00
Verilated::traceEverOn(true); // Verilator must compute traced signals
std::unique_ptr<VerilatedVcdFILE> vcdfd(new VerilatedVcdFILE(vcdfile));
std::unique_ptr<VerilatedVcdC> tfp(new VerilatedVcdC(vcdfd.get()));
if (vcdfile) {
tile->trace(tfp.get(), 99); // Trace 99 levels of hierarchy
2016-07-09 11:37:39 +02:00
tfp->open("");
}
#endif
jtag = new remote_bitbang_t(0);
dtm = new dtm_t(htif_argc, htif_argv);
signal(SIGTERM, handle_sigterm);
bool dump;
// reset for several cycles to handle pipelined reset
for (int i = 0; i < 10; i++) {
tile->reset = 1;
tile->clock = 0;
tile->eval();
#if VM_TRACE
dump = tfp && trace_count >= start;
if (dump)
tfp->dump(static_cast<vluint64_t>(trace_count * 2));
#endif
tile->clock = 1;
tile->eval();
#if VM_TRACE
if (dump)
tfp->dump(static_cast<vluint64_t>(trace_count * 2 + 1));
#endif
trace_count ++;
}
tile->reset = 0;
done_reset = true;
while (!dtm->done() && !jtag->done() &&
!tile->io_success && trace_count < max_cycles) {
tile->clock = 0;
tile->eval();
#if VM_TRACE
dump = tfp && trace_count >= start;
if (dump)
2016-09-14 20:36:47 +02:00
tfp->dump(static_cast<vluint64_t>(trace_count * 2));
#endif
tile->clock = 1;
tile->eval();
#if VM_TRACE
if (dump)
2016-09-14 20:36:47 +02:00
tfp->dump(static_cast<vluint64_t>(trace_count * 2 + 1));
#endif
2012-10-02 04:30:11 +02:00
trace_count++;
}
#if VM_TRACE
2016-07-09 11:37:39 +02:00
if (tfp)
tfp->close();
if (vcdfile)
fclose(vcdfile);
#endif
2016-07-09 11:37:39 +02:00
if (dtm->exit_code())
2012-10-02 04:30:11 +02:00
{
fprintf(stderr, "*** FAILED *** via dtm (code = %d, seed %d) after %ld cycles\n", dtm->exit_code(), random_seed, trace_count);
ret = dtm->exit_code();
2012-10-02 04:30:11 +02:00
}
else if (jtag->exit_code())
{
fprintf(stderr, "*** FAILED *** via jtag (code = %d, seed %d) after %ld cycles\n", jtag->exit_code(), random_seed, trace_count);
ret = jtag->exit_code();
}
2016-06-23 21:17:26 +02:00
else if (trace_count == max_cycles)
{
fprintf(stderr, "*** FAILED *** via trace_count (timeout, seed %d) after %ld cycles\n", random_seed, trace_count);
ret = 2;
}
2016-06-18 06:09:08 +02:00
else if (verbose || print_cycles)
{
2016-06-23 21:17:26 +02:00
fprintf(stderr, "Completed after %ld cycles\n", trace_count);
}
if (dtm) delete dtm;
if (jtag) delete jtag;
if (tile) delete tile;
if (htif_argv) free(htif_argv);
return ret;
2012-10-02 04:30:11 +02:00
}