diff options
Diffstat (limited to 'riscv/riscv_sim.c')
| -rw-r--r-- | riscv/riscv_sim.c | 143 |
1 files changed, 141 insertions, 2 deletions
diff --git a/riscv/riscv_sim.c b/riscv/riscv_sim.c index 276c7b1b..98f17349 100644 --- a/riscv/riscv_sim.c +++ b/riscv/riscv_sim.c @@ -6,6 +6,8 @@ #include <sys/types.h> #include <sys/stat.h> #include <sys/mman.h> +#include <sys/socket.h> +#include <netinet/ip.h> #include <fcntl.h> #include "elf.h" @@ -45,6 +47,10 @@ char *term_log = NULL; char *dtb_file = NULL; unsigned char *dtb = NULL; size_t dtb_len = 0; +#ifdef RVFI_DII +static bool rvfi_dii = false; +static int rvfi_dii_sock; +#endif unsigned char *spike_dtb = NULL; size_t spike_dtb_len = 0; @@ -56,13 +62,20 @@ static struct option options[] = { {"dump-dts", no_argument, 0, 's'}, {"device-tree-blob", required_argument, 0, 'b'}, {"terminal-log", required_argument, 0, 't'}, +#ifdef RVFI_DII + {"rvfi-dii", no_argument, 0, 'r'}, +#endif {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; static void print_usage(const char *argv0, int ec) { +#ifdef RVFI_DII + fprintf(stdout, "Usage: %s [options] [<elf_file>]\n", argv0); +#else fprintf(stdout, "Usage: %s [options] <elf_file>\n", argv0); +#endif struct option *opt = options; while (opt->name) { fprintf(stdout, "\t -%c\t %s\n", (char)opt->val, opt->name); @@ -123,7 +136,7 @@ char *process_args(int argc, char **argv) { int c, idx = 1; while(true) { - c = getopt_long(argc, argv, "dmsb:t:v:h", options, &idx); + c = getopt_long(argc, argv, "dmsb:t:v:hr", options, &idx); if (c == -1) break; switch (c) { case 'd': @@ -146,16 +159,28 @@ char *process_args(int argc, char **argv) case 'h': print_usage(argv[0], 0); break; +#ifdef RVFI_DII + case 'r': + rvfi_dii = true; + break; +#endif default: fprintf(stderr, "Unrecognized optchar %c\n", c); print_usage(argv[0], 1); } } if (do_dump_dts) dump_dts(); +#ifdef RVFI_DII + if (idx > argc || (idx == argc && !rvfi_dii)) print_usage(argv[0], 0); +#else if (idx >= argc) print_usage(argv[0], 0); +#endif if (term_log == NULL) term_log = strdup("term.log"); if (dtb_file) read_dtb(dtb_file); +#ifdef RVFI_DII + if (!rvfi_dii) +#endif fprintf(stdout, "Running file %s.\n", argv[optind]); return argv[optind]; } @@ -276,6 +301,11 @@ void init_sail_reset_vector(uint64_t entry) /* set rom size */ rv_rom_size = rom_end - rv_rom_base; +#ifdef RVFI_DII + if (rvfi_dii) + zPC = entry; + else +#endif /* boot at reset vector */ zPC = rv_rom_base; } @@ -374,6 +404,26 @@ void flush_logs(void) fflush(stdout); } +#ifdef RVFI_DII +void rvfi_send_trace(void) { + sail_bits packet; + CREATE(sail_bits)(&packet); + zrvfi_get_exec_packet(&packet, UNIT); + if (packet.len % 8 != 0) { + fprintf(stderr, "RVFI-DII trace packet not byte aligned: %d\n", (int)packet.len); + exit(1); + } + unsigned char bytes[packet.len / 8]; + /* mpz_export might not write all of the null bytes */ + memset(bytes, 0, sizeof(bytes)); + mpz_export(bytes, NULL, -1, 1, 0, 0, *(packet.bits)); + if (write(rvfi_dii_sock, bytes, packet.len / 8) == -1) { + fprintf(stderr, "Writing RVFI DII trace failed: %s", strerror(errno)); + exit(1); + } +} +#endif + void run_sail(void) { bool spike_done; @@ -383,8 +433,46 @@ void run_sail(void) /* initialize the step number */ mach_int step_no = 0; int insn_cnt = 0; +#ifdef RVFI_DII + bool need_instr = true; +#endif while (!zhtif_done) { +#ifdef RVFI_DII + if (rvfi_dii) { + if (need_instr) { + mach_bits instr_bits; + if (read(rvfi_dii_sock, &instr_bits, sizeof(instr_bits)) == -1) { + fprintf(stderr, "Reading RVFI DII command failed: %s", strerror(errno)); + exit(1); + } + zrvfi_set_instr_packet(instr_bits); + zrvfi_zzero_exec_packet(UNIT); + mach_bits cmd = zrvfi_get_cmd(UNIT); + switch (cmd) { + case 0: /* EndOfTrace */ + zrvfi_halt_exec_packet(UNIT); + rvfi_send_trace(); + return; + case 1: /* Instruction */ + break; + default: + fprintf(stderr, "Unknown RVFI-DII command: %d\n", (int)cmd); + exit(1); + } + } + sail_int sail_step; + CREATE(sail_int)(&sail_step); + CONVERT_OF(sail_int, mach_int)(&sail_step, step_no); + stepped = zrvfi_step(sail_step); + if (have_exception) goto step_exception; + flush_logs(); + if (stepped) { + need_instr = true; + rvfi_send_trace(); + } + } else +#endif { /* run a Sail step */ sail_int sail_step; CREATE(sail_int)(&sail_step); @@ -471,7 +559,46 @@ int main(int argc, char **argv) char *file = process_args(argc, argv); init_logs(); +#ifdef RVFI_DII + uint64_t entry; + if (rvfi_dii) { + entry = 0x80000000; + int listen_sock = socket(AF_INET, SOCK_STREAM, 0); + if (listen_sock == -1) { + fprintf(stderr, "Unable to create socket: %s", strerror(errno)); + return 1; + } + int opt = 1; + if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) { + fprintf(stderr, "Unable to set reuseaddr on socket: %s", strerror(errno)); + return 1; + } + struct sockaddr_in addr = { + .sin_family = AF_INET, + .sin_addr.s_addr = INADDR_ANY, + .sin_port = htons(1234) + }; + if (bind(listen_sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) { + fprintf(stderr, "Unable to set bind socket: %s", strerror(errno)); + return 1; + } + if (listen(listen_sock, 1) == -1) { + fprintf(stderr, "Unable to listen on socket: %s", strerror(errno)); + return 1; + } + printf("Waiting for connection\n"); + rvfi_dii_sock = accept(listen_sock, NULL, NULL); + if (rvfi_dii_sock == -1) { + fprintf(stderr, "Unable to accept connection on socket: %s", strerror(errno)); + return 1; + } + close(listen_sock); + printf("Connected\n"); + } else + entry = load_sail(file); +#else uint64_t entry = load_sail(file); +#endif /* initialize spike before sail so that we can access the device-tree blob, * until we roll our own. @@ -481,6 +608,18 @@ int main(int argc, char **argv) if (!init_check(s)) finish(1); - run_sail(); + do { + run_sail(); +#ifndef RVFI_DII + } while (0); +#else + if (rvfi_dii) { + /* Reset for next test; currently we only quit when the connection breaks + and we crash due to SIGPIPE. */ + model_fini(); + init_sail(entry); + } + } while (rvfi_dii); +#endif flush_logs(); } |
