Skip to content

Commit

Permalink
Initial implementation of new RVFI_DII socket format
Browse files Browse the repository at this point in the history
This is not a finalized trace format yet.
  • Loading branch information
arichardson committed Mar 16, 2021
1 parent 31b53ea commit f09f510
Show file tree
Hide file tree
Showing 8 changed files with 307 additions and 65 deletions.
6 changes: 5 additions & 1 deletion c_emulator/riscv_sail.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,14 @@ unit z_set_Misa_F(struct zMisa*, mach_bits);
unit zext_rvfi_init(unit);
unit zrvfi_set_instr_packet(mach_bits);
mach_bits zrvfi_get_cmd(unit);
mach_bits zrvfi_get_insn(unit);
bool zrvfi_step(sail_int);
unit zrvfi_zzero_exec_packet(unit);
unit zrvfi_halt_exec_packet(unit);
void zrvfi_get_exec_packet(sail_bits *rop, unit);
void zrvfi_get_exec_packet_v1(sail_bits *rop, unit);
void zrvfi_get_exec_packet_v2(sail_bits *rop, unit);
mach_bits zrvfi_get_v2_trace_sizze(unit);
void zrvfi_get_v2_support_packet(sail_bits *rop, unit);
#endif

extern mach_bits zxlen_val;
Expand Down
65 changes: 55 additions & 10 deletions c_emulator/riscv_sim.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ static void read_dtb(const char *path)
munmap(m, st.st_size);
close(fd);

fprintf(stdout, "Read %" PRIi64 " bytes of DTB from %s.\n", dtb_len, path);
fprintf(stdout, "Read %zd bytes of DTB from %s.\n", dtb_len, path);
}

char *process_args(int argc, char **argv)
Expand Down Expand Up @@ -671,10 +671,12 @@ void flush_logs(void)
}

#ifdef RVFI_DII
void rvfi_send_trace(void) {

typedef void (packet_reader_fn)(sail_bits *rop, unit);
static void get_and_send_rvfi_packet_maxlen(packet_reader_fn *reader, size_t maxbytes) {
sail_bits packet;
CREATE(lbits)(&packet);
zrvfi_get_exec_packet(&packet, UNIT);
reader(&packet, UNIT);
if (packet.len % 8 != 0) {
fprintf(stderr, "RVFI-DII trace packet not byte aligned: %d\n", (int)packet.len);
exit(1);
Expand All @@ -683,12 +685,29 @@ void rvfi_send_trace(void) {
/* 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));
size_t send_size = maxbytes < packet.len / 8 ? maxbytes : packet.len / 8;
if (write(rvfi_dii_sock, bytes, send_size) == -1) {
fprintf(stderr, "Writing RVFI DII trace failed: %s\n", strerror(errno));
exit(1);
}
KILL(lbits)(&packet);
}

static void get_and_send_rvfi_packet(packet_reader_fn *reader) {
get_and_send_rvfi_packet_maxlen(reader, SIZE_MAX);
}

void rvfi_send_trace(unsigned version) {
if (version == 1) {
get_and_send_rvfi_packet(zrvfi_get_exec_packet_v1);
} else if (version == 2) {
mach_bits trace_size = zrvfi_get_v2_trace_sizze(UNIT);
get_and_send_rvfi_packet_maxlen(zrvfi_get_exec_packet_v2, trace_size);
} else {
fprintf(stderr, "Sending v%d packets not implemented yet!\n", version);
abort();
}
}
#endif

void run_sail(void)
Expand All @@ -712,6 +731,7 @@ void run_sail(void)

while (!zhtif_done && (insn_limit == 0 || total_insns < insn_limit)) {
#ifdef RVFI_DII
unsigned trace_version = 1;
if (rvfi_dii) {
mach_bits instr_bits;
int res = read(rvfi_dii_sock, &instr_bits, sizeof(instr_bits));
Expand All @@ -731,12 +751,37 @@ void run_sail(void)
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 0: { /* EndOfTrace */
mach_bits insn = zrvfi_get_insn(UNIT);
if (insn == (('V' << 24) | ('E' << 16) | ('R' << 8) | 'S')) {
/*
* Reset with insn set to 'VERS' is a version negotiation request
* and not a actual reset request. Respond with a message say that
* we support version 2.
*/
get_and_send_rvfi_packet(&zrvfi_get_v2_support_packet);
continue;
} else {
zrvfi_halt_exec_packet(UNIT);
rvfi_send_trace(trace_version);
return;
}
}
case 1: /* Instruction */
break;
case 'v': { /* Set wire format version */
mach_bits insn = zrvfi_get_insn(UNIT);
if (insn == 1) {
fprintf(stderr, "Requested trace in legacy format!\n");
} else if (insn == 2) {
fprintf(stderr, "Requested trace in legacy format!\n");
} else {
fprintf(stderr, "Requested trace in unsupported format %d!\n", (int)insn);
exit(1);
}
trace_version = insn; // From now on send traces in the requested format
continue;
}
default:
fprintf(stderr, "Unknown RVFI-DII command: %d\n", (int)cmd);
exit(1);
Expand All @@ -748,7 +793,7 @@ void run_sail(void)
if (have_exception) goto step_exception;
flush_logs();
KILL(sail_int)(&sail_step);
rvfi_send_trace();
rvfi_send_trace(trace_version);
} else /* if (!rvfi_dii) */
#endif
{ /* run a Sail step */
Expand Down
11 changes: 3 additions & 8 deletions model/riscv_fetch_rvfi.sail
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
function fetch() -> FetchResult = {
rvfi_exec->rvfi_order() = minstret;
rvfi_exec->rvfi_pc_rdata() = EXTZ(get_arch_pc());
rvfi_inst_data->rvfi_order() = minstret;
rvfi_pc_data->rvfi_pc_rdata() = EXTZ(get_arch_pc());

/* First allow extensions to check pc */
match ext_fetch_check_pc(PC, PC) {
Expand All @@ -13,12 +13,7 @@ function fetch() -> FetchResult = {
TR_Failure(e, _) => F_Error(e, PC),
TR_Address(_, _) => {
let i = rvfi_instruction.rvfi_insn();
rvfi_exec->rvfi_insn() = EXTZ(i);
/* TODO: should we write these even if they're not really registers? */
rvfi_exec->rvfi_rs1_data() = EXTZ(X(i[19 .. 15]));
rvfi_exec->rvfi_rs2_data() = EXTZ(X(i[24 .. 20]));
rvfi_exec->rvfi_rs1_addr() = sail_zero_extend(i[19 .. 15],8);
rvfi_exec->rvfi_rs2_addr() = sail_zero_extend(i[24 .. 20],8);
rvfi_inst_data->rvfi_insn() = EXTZ(i);
if (i[1 .. 0] != 0b11)
then F_RVC(i[15 .. 0])
else {
Expand Down
26 changes: 16 additions & 10 deletions model/riscv_mem.sail
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,16 @@ function pmp_mem_read forall 'n, 0 < 'n <= max_mem_access . (t : AccessType(ext_
$ifdef RVFI_DII
val rvfi_read : forall 'n, 'n > 0. (xlenbits, atom('n), MemoryOpResult(bits(8 * 'n))) -> unit effect {wreg}
function rvfi_read (addr, width, result) = {
rvfi_exec->rvfi_mem_addr() = EXTZ(addr);
rvfi_mem_data->rvfi_mem_addr() = EXTZ(addr);
rvfi_mem_data_present = true;
match result {
/* TODO: report tag bit for capability writes and extend mask by one bit. */
MemValue(v) => if width <= 8
then { rvfi_exec->rvfi_mem_rdata() = sail_zero_extend(v,64);
rvfi_exec->rvfi_mem_rmask() = rvfi_encode_width_mask(width) }
else { rvfi_exec->rvfi_mem_rdata() = v[63..0];
rvfi_exec->rvfi_mem_rmask() = 0xFF},
then { rvfi_mem_data->rvfi_mem_rdata() = sail_zero_extend(v,64);
rvfi_mem_data->rvfi_mem_rmask() = rvfi_encode_width_mask(width) }
else { rvfi_mem_data->rvfi_mem_rdata() = v[63..0]; /* report low bits only */
assert(width == 16, "Should only be used for capabilities");
rvfi_mem_data->rvfi_mem_rmask() = rvfi_encode_width_mask(16)},
MemException(_) => ()
};
}
Expand Down Expand Up @@ -135,13 +138,16 @@ function mem_write_ea (addr, width, aq, rl, con) = {
$ifdef RVFI_DII
val rvfi_write : forall 'n, 0 < 'n <= max_mem_access . (xlenbits, atom('n), bits(8 * 'n)) -> unit effect {wreg}
function rvfi_write (addr, width, value) = {
rvfi_exec->rvfi_mem_addr() = EXTZ(addr);
rvfi_mem_data->rvfi_mem_addr() = EXTZ(addr);
rvfi_mem_data_present = true;
if width <= 8 then {
rvfi_exec->rvfi_mem_wdata() = sail_zero_extend(value,64);
rvfi_exec->rvfi_mem_wmask() = rvfi_encode_width_mask(width);
rvfi_mem_data->rvfi_mem_wdata() = sail_zero_extend(value,64);
rvfi_mem_data->rvfi_mem_wmask() = rvfi_encode_width_mask(width);
} else {
rvfi_exec->rvfi_mem_wdata() = value[63..0];
rvfi_exec->rvfi_mem_wmask() = 0xFF;
/* TODO: report tag bit for capability writes and extend mask by one bit. */
rvfi_mem_data->rvfi_mem_wdata() = value[63..0];
assert(width == 16, "Should only be used for capabilities");
rvfi_mem_data->rvfi_mem_wmask() = rvfi_encode_width_mask(width);
}
}
$else
Expand Down
5 changes: 3 additions & 2 deletions model/riscv_regs.sail
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,9 @@ function rX r = {
$ifdef RVFI_DII
val rvfi_wX : forall 'n, 0 <= 'n < 32. (regno('n), xlenbits) -> unit effect {wreg}
function rvfi_wX (r,v) = {
rvfi_exec->rvfi_rd_wdata() = EXTZ(v);
rvfi_exec->rvfi_rd_addr() = to_bits(8,r);
rvfi_int_data->rvfi_rd_wdata() = EXTZ(v);
rvfi_int_data->rvfi_rd_addr() = to_bits(8,r);
rvfi_int_data_present = true;
}
$else
val rvfi_wX : forall 'n, 0 <= 'n < 32. (regno('n), xlenbits) -> unit
Expand Down
7 changes: 1 addition & 6 deletions model/riscv_step_rvfi.sail
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,15 @@ function ext_pre_step_hook() -> unit = ()

function ext_post_step_hook() -> unit = {
/* record the next pc */
rvfi_exec->rvfi_pc_wdata() = EXTZ(get_arch_pc())
rvfi_pc_data->rvfi_pc_wdata() = EXTZ(get_arch_pc())
}

val ext_init : unit -> unit effect {wreg}
function ext_init() = {
init_base_regs();
init_fdext_regs();
/* these are here so that the C backend doesn't prune them out. */
rvfi_set_instr_packet(0x0000000000000000);
print_bits("", rvfi_get_cmd());
// let _ = rvfi_step(0);
rvfi_zero_exec_packet();
rvfi_halt_exec_packet();
let _ = rvfi_get_exec_packet();
ext_rvfi_init();
()
}
3 changes: 2 additions & 1 deletion model/riscv_sys_control.sail
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,9 @@ function tval(excinfo : option(xlenbits)) -> xlenbits = {

$ifdef RVFI_DII
val rvfi_trap : unit -> unit effect {wreg}
// TODO: record rvfi_trap_data
function rvfi_trap () =
rvfi_exec->rvfi_trap() = 0x01
rvfi_inst_data->rvfi_trap() = 0x01
$else
val rvfi_trap : unit -> unit
function rvfi_trap () = ()
Expand Down
Loading

0 comments on commit f09f510

Please sign in to comment.