From 132caedd7fb07244965771d7d69153ef07de7892 Mon Sep 17 00:00:00 2001 From: Scott Beamer Date: Tue, 11 Feb 2020 13:36:18 -0800 Subject: [PATCH] create rocket18 directory --- .gitmodules | 3 + rocket16/Makefile | 8 - rocket18/.gitignore | 4 + rocket18/Makefile | 29 ++ rocket18/emulator.cc | 268 ++++++++++++++++++ rocket18/fesvr.commit | 1 + ...echips.rocketchip.system.DefaultConfig.fir | 0 rocket18/riscv-fesvr | 1 + rocket18/rocket-chip.commit | 1 + 9 files changed, 307 insertions(+), 8 deletions(-) create mode 100644 rocket18/.gitignore create mode 100644 rocket18/Makefile create mode 100644 rocket18/emulator.cc create mode 100644 rocket18/fesvr.commit rename {rocket => rocket18}/freechips.rocketchip.system.DefaultConfig.fir (100%) create mode 160000 rocket18/riscv-fesvr create mode 100644 rocket18/rocket-chip.commit diff --git a/.gitmodules b/.gitmodules index 2dc8434..0584ce1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "rocket16/riscv-fesvr"] path = rocket16/riscv-fesvr url = https://github.com/riscv/riscv-fesvr +[submodule "rocket18/riscv-fesvr"] + path = rocket18/riscv-fesvr + url = https://github.com/riscv/riscv-fesvr.git diff --git a/rocket16/Makefile b/rocket16/Makefile index 3870aaa..885366d 100644 --- a/rocket16/Makefile +++ b/rocket16/Makefile @@ -27,11 +27,3 @@ TestHarness.h: emulator: emulator.cc TestHarness.h riscv/lib/libfesvr.so $(CXX) $(CXXFLAGS) $(INCLUDES) emulator.cc -o emulator $(LIBS) - - - - -INCLUDES_HEAD = -I../csrc -Iriscv-head/include -I../firrtl-sig -LIBS_HEAD = -Lriscv-head/lib -Wl,-rpath,riscv-head/lib -lfesvr -lpthread -emulator-head: emulator-head.cc TestHarness.h - $(CXX) $(CXXFLAGS) $(INCLUDES_HEAD) emulator-head.cc -o emulator-head $(LIBS_HEAD) diff --git a/rocket18/.gitignore b/rocket18/.gitignore new file mode 100644 index 0000000..80c770f --- /dev/null +++ b/rocket18/.gitignore @@ -0,0 +1,4 @@ +.riscv-fesvr/build +emulator +TestHarness.h +riscv/ diff --git a/rocket18/Makefile b/rocket18/Makefile new file mode 100644 index 0000000..da64afc --- /dev/null +++ b/rocket18/Makefile @@ -0,0 +1,29 @@ +CXXFLAGS = -O3 -std=c++11 +CLANG_FLAGS = -fno-slp-vectorize -fbracket-depth=1024 + +UNAME_OS := $(shell uname -s) +ifeq ($(UNAME_OS),Darwin) + CXXFLAGS += $(CLANG_FLAGS) +endif + +ifeq ($(ALL_ON),1) + CXXFLAGS += -DALL_ON +endif + +INCLUDES = -I../csrc -Iriscv/include -I../firrtl-sig + +LIBS = -Lriscv/lib -Wl,-rpath,riscv/lib -lfesvr -lpthread + +riscv_dir := $(shell pwd)/riscv + +riscv/lib/libfesvr.so: + git submodule update --init riscv-fesvr + cd riscv-fesvr; git checkout `cat ../fesvr.commit` + mkdir $(riscv_dir) + cd riscv-fesvr; mkdir build; cd build; ../configure --prefix=$(riscv_dir) --target=riscv64-unknown-elf; make install + +TestHarness.h: + cd ../essent; sbt 'run ../rocket18/freechips.rocketchip.system.DefaultConfig.fir' + +emulator: emulator.cc TestHarness.h riscv/lib/libfesvr.so + $(CXX) $(CXXFLAGS) $(INCLUDES) emulator.cc -o emulator $(LIBS) diff --git a/rocket18/emulator.cc b/rocket18/emulator.cc new file mode 100644 index 0000000..0584a7d --- /dev/null +++ b/rocket18/emulator.cc @@ -0,0 +1,268 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "TestHarness.h" + +// TODO: add in support for JTAG remote bit bang +// TODO: add in support for VM_TRACE and VCD output + +// 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 + +dtm_t* dtm; + +static uint64_t trace_count = 0; +bool verbose; +bool done_reset; + +void handle_sigterm(int sig) { + dtm->stop(); +} + +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\ + -r, --rbb-port=PORT Use PORT for remote bit bang (with OpenOCD and GDB) \n\ + If not specified, a random port will be chosen\n\ + automatically.\n\ + -V, --verbose Enable all Chisel printfs (cycle-by-cycle info)\n\ + +verbose\n\ +", stdout); + 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" +" - run an ELF (you wrote, called 'hello') using the proxy kernel:\n" +" %s pk hello\n", + program_name, program_name, program_name); +} + +void tick_dtm(TestHarness *tile, bool done_reset) { + if (done_reset) { + dtm_t::resp resp_bits; + resp_bits.resp = tile->SimDTM$$inst.debug_resp_bits_resp.as_single_word(); + resp_bits.data = tile->SimDTM$$inst.debug_resp_bits_data.as_single_word(); + + dtm->tick(tile->SimDTM$$inst.debug_req_ready.as_single_word(), + tile->SimDTM$$inst.debug_resp_valid.as_single_word(), + resp_bits); + + tile->SimDTM$$inst.debug_resp_ready = UInt<1>(dtm->resp_ready()); + tile->SimDTM$$inst.debug_req_valid = UInt<1>(dtm->req_valid()); + tile->SimDTM$$inst.debug_req_bits_addr = UInt<7>(dtm->req_bits().addr); + tile->SimDTM$$inst.debug_req_bits_op = UInt<2>(dtm->req_bits().op); + tile->SimDTM$$inst.debug_req_bits_data = UInt<32>(dtm->req_bits().data); + + tile->SimDTM$$inst.exit = UInt<32>(dtm->done() ? (dtm->exit_code() << 1 | 1) : 0); + } else { + tile->SimDTM$$inst.debug_req_valid = UInt<1>(0); + tile->SimDTM$$inst.debug_resp_ready = UInt<1>(0); + tile->SimDTM$$inst.exit = UInt<32>(0); + } +} + +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; + 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' }, + {"rbb-port", required_argument, 0, 'r' }, + {"verbose", no_argument, 0, 'V' }, + HTIF_LONG_OPTIONS + }; + int option_index = 0; + int c = getopt_long(argc, argv, "-chm:s:r:V", long_options, &option_index); + 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; + // 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; + } + 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++]; + + if (verbose) + fprintf(stderr, "using random seed %u\n", random_seed); + + srand(random_seed); + srand48(random_seed); + + TestHarness *tile = new TestHarness; + + dtm = new dtm_t(htif_argc, htif_argv); + + signal(SIGTERM, handle_sigterm); + + // reset for several cycles to handle pipelined reset + tile->reset = UInt<1>(1); + tick_dtm(tile, done_reset); + tile->eval(false, verbose, done_reset); + for (int i = 0; i < 10; i++) { + // tile->reset = 1; + // tile->clock = 0; + // tile->eval(); + // tile->clock = 1; + // tile->eval(); + tile->eval(true, verbose, done_reset); + tick_dtm(tile, done_reset); + // trace_count ++; + } + // tile->reset = 0; + // done_reset = true; + tile->reset = UInt<1>(0); + tile->eval(false, verbose, done_reset); + tick_dtm(tile, done_reset); + done_reset = true; + + while (!dtm->done() && !tile->io_success && trace_count < max_cycles) { + // tile->clock = 0; + // tile->eval(); + // tile->clock = 1; + // tile->eval(); + tile->eval(true, verbose, done_reset); + tick_dtm(tile, done_reset); + trace_count++; + } + + if (dtm->exit_code()) { + fprintf(stderr, "*** FAILED *** via dtm (code = %d, seed %d) after %" PRIu64 " cycles\n", dtm->exit_code(), random_seed, trace_count); + ret = dtm->exit_code(); + } + else if (trace_count == max_cycles) { + fprintf(stderr, "*** FAILED *** via trace_count (timeout, seed %d) after %" PRIu64 " cycles\n", random_seed, trace_count); + ret = 2; + } + else if (verbose || print_cycles) { + fprintf(stderr, "Completed after %" PRIu64 " cycles\n", trace_count); + } + + if (dtm) delete dtm; + if (tile) delete tile; + if (htif_argv) free(htif_argv); + return ret; +} diff --git a/rocket18/fesvr.commit b/rocket18/fesvr.commit new file mode 100644 index 0000000..78c7e4c --- /dev/null +++ b/rocket18/fesvr.commit @@ -0,0 +1 @@ +68c12d06ebbdfe20856b886570822fe66804fd26 diff --git a/rocket/freechips.rocketchip.system.DefaultConfig.fir b/rocket18/freechips.rocketchip.system.DefaultConfig.fir similarity index 100% rename from rocket/freechips.rocketchip.system.DefaultConfig.fir rename to rocket18/freechips.rocketchip.system.DefaultConfig.fir diff --git a/rocket18/riscv-fesvr b/rocket18/riscv-fesvr new file mode 160000 index 0000000..68c12d0 --- /dev/null +++ b/rocket18/riscv-fesvr @@ -0,0 +1 @@ +Subproject commit 68c12d06ebbdfe20856b886570822fe66804fd26 diff --git a/rocket18/rocket-chip.commit b/rocket18/rocket-chip.commit new file mode 100644 index 0000000..d38485f --- /dev/null +++ b/rocket18/rocket-chip.commit @@ -0,0 +1 @@ +846425cc0fe8956f0b8b339320847d9cd2096b65