summaryrefslogtreecommitdiff
path: root/riscv/riscv_sim.c
diff options
context:
space:
mode:
Diffstat (limited to 'riscv/riscv_sim.c')
-rw-r--r--riscv/riscv_sim.c157
1 files changed, 155 insertions, 2 deletions
diff --git a/riscv/riscv_sim.c b/riscv/riscv_sim.c
index f518f20e..0a5fec70 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"
@@ -40,11 +42,17 @@ struct tv_spike_t;
#define CSR_MIP 0x344
static bool do_dump_dts = false;
+static bool disable_compressed = false;
struct tv_spike_t *s = NULL;
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_port;
+static int rvfi_dii_sock;
+#endif
unsigned char *spike_dtb = NULL;
size_t spike_dtb_len = 0;
@@ -53,17 +61,25 @@ static struct option options[] = {
{"enable-dirty", no_argument, 0, 'd'},
{"enable-misaligned", no_argument, 0, 'm'},
{"ram-size", required_argument, 0, 'z'},
+ {"disable-compressed", no_argument, 0, 'C'},
{"mtval-has-illegal-inst-bits", no_argument, 0, 'i'},
{"dump-dts", no_argument, 0, 's'},
{"device-tree-blob", required_argument, 0, 'b'},
{"terminal-log", required_argument, 0, 't'},
+#ifdef RVFI_DII
+ {"rvfi-dii", required_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 %s [options] -r <port>\n", argv0, 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);
@@ -125,7 +141,7 @@ char *process_args(int argc, char **argv)
int c, idx = 1;
uint64_t ram_size = 0;
while(true) {
- c = getopt_long(argc, argv, "dmsz:b:t:v:h", options, &idx);
+ c = getopt_long(argc, argv, "dmCsz:b:t:v:hr:", options, &idx);
if (c == -1) break;
switch (c) {
case 'd':
@@ -136,6 +152,9 @@ char *process_args(int argc, char **argv)
fprintf(stderr, "enabling misaligned access.\n");
rv_enable_misaligned = true;
break;
+ case 'C':
+ disable_compressed = true;
+ break;
case 'i':
rv_mtval_has_illegal_inst_bits = true;
case 's':
@@ -157,16 +176,29 @@ char *process_args(int argc, char **argv)
case 'h':
print_usage(argv[0], 0);
break;
+#ifdef RVFI_DII
+ case 'r':
+ rvfi_dii = true;
+ rvfi_dii_port = atoi(optarg);
+ 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];
}
@@ -316,7 +348,18 @@ void init_sail(uint64_t elf_entry)
model_init();
zinit_platform(UNIT);
zinit_sys(UNIT);
+#ifdef RVFI_DII
+ if (rvfi_dii) {
+ rv_ram_base = UINT64_C(0x80000000);
+ rv_ram_size = UINT64_C(0x10000);
+ rv_rom_base = UINT64_C(0);
+ rv_rom_size = UINT64_C(0);
+ zPC = elf_entry;
+ } else
+#endif
init_sail_reset_vector(elf_entry);
+ if (disable_compressed)
+ z_set_Misa_C(&zmisa, 0);
}
int init_check(struct tv_spike_t *s)
@@ -405,6 +448,26 @@ void flush_logs(void)
fflush(stdout);
}
+#ifdef RVFI_DII
+void rvfi_send_trace(void) {
+ sail_bits packet;
+ CREATE(lbits)(&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;
@@ -414,8 +477,47 @@ 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
+ need_instr = false;
+ } else
+#endif
{ /* run a Sail step */
sail_int sail_step;
CREATE(sail_int)(&sail_step);
@@ -503,7 +605,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(rvfi_dii_port)
+ };
+ 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.
@@ -513,6 +654,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();
}