Skip to content

Commit cd62eef

Browse files
jordancarlinTim Hutt
andcommitted
Implementing callbacks in sail-riscv for state-changing events
1. Added callback functions for XRegs, FRegs, VRegs, PC, CSR and memory writes, and CSR and memory reads. 2. Added RVFI and standard trace logging implementation of callbacks. Co-authored-by: Tim Hutt <timothy.hutt@codasip.com>
1 parent 8ff2a70 commit cd62eef

21 files changed

+317
-156
lines changed

c_emulator/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
set(EMULATOR_COMMON_SRCS
2+
riscv_callbacks.cpp
3+
riscv_callbacks.h
24
riscv_config.h
35
riscv_platform.cpp
46
riscv_platform.h

c_emulator/riscv_callbacks.cpp

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
#include "riscv_callbacks.h"
2+
#include "riscv_config.h"
3+
#include "riscv_platform_impl.h"
4+
#include <stdlib.h>
5+
#include <vector>
6+
#include <inttypes.h>
7+
8+
void print_lbits_hex(lbits val, int length = 0)
9+
{
10+
if (length == 0) {
11+
length = val.len;
12+
}
13+
std::vector<uint8_t> data(length);
14+
mpz_export(data.data(), nullptr, -1, 1, 0, 0, *val.bits);
15+
for (int i = length - 1; i >= 0; --i) {
16+
fprintf(trace_log, "%02" PRIX8, data[i]);
17+
}
18+
fprintf(trace_log, "\n");
19+
}
20+
21+
// Implementations of default callbacks for trace printing and RVFI.
22+
// The model assumes that these functions do not change the state of the model.
23+
unit mem_write_callback(uint64_t addr, uint64_t width, lbits value)
24+
{
25+
if (config_print_mem_access) {
26+
fprintf(trace_log, "mem[0x%016" PRIX64 "] <- 0x", addr);
27+
print_lbits_hex(value, width);
28+
}
29+
#ifdef RVFI_DII
30+
if (config_enable_rvfi) {
31+
zrvfi_write(addr, width, value);
32+
}
33+
#endif
34+
return UNIT;
35+
}
36+
37+
unit mem_read_callback(const char *type, uint64_t addr, uint64_t width,
38+
lbits value)
39+
{
40+
if (config_print_mem_access) {
41+
fprintf(trace_log, "mem[%s,0x%016" PRIX64 "] -> 0x", type, addr);
42+
print_lbits_hex(value, width);
43+
}
44+
#ifdef RVFI_DII
45+
if (config_enable_rvfi) {
46+
sail_int len;
47+
CREATE(sail_int)(&len);
48+
CONVERT_OF(sail_int, mach_int)(&len, width);
49+
zrvfi_read(addr, len, value);
50+
KILL(sail_int)(&len);
51+
}
52+
#endif
53+
return UNIT;
54+
}
55+
56+
unit mem_exception_callback(uint64_t addr, uint64_t num_of_exception)
57+
{
58+
(void)num_of_exception;
59+
#ifdef RVFI_DII
60+
if (config_enable_rvfi) {
61+
zrvfi_mem_exception(addr);
62+
}
63+
#else
64+
(void)addr;
65+
#endif
66+
return UNIT;
67+
}
68+
69+
unit xreg_write_callback(unsigned reg, uint64_t value)
70+
{
71+
if (config_print_reg) {
72+
fprintf(trace_log, "x%d <- 0x%016" PRIX64 "\n", reg, value);
73+
}
74+
#ifdef RVFI_DII
75+
if (config_enable_rvfi) {
76+
zrvfi_wX(reg, value);
77+
}
78+
#endif
79+
return UNIT;
80+
}
81+
82+
unit freg_write_callback(unsigned reg, uint64_t value)
83+
{
84+
// TODO: will only print bits; should we print in floating point format?
85+
if (config_print_reg) {
86+
fprintf(trace_log, "f%d <- 0x%016" PRIX64 "\n", reg, value);
87+
}
88+
return UNIT;
89+
}
90+
91+
unit csr_write_callback(sail_string csr_name, unsigned reg, uint64_t value)
92+
{
93+
if (config_print_reg) {
94+
fprintf(trace_log, "CSR %s (0x%03X) <- 0x%016" PRIX64 "\n", csr_name, reg,
95+
value);
96+
}
97+
return UNIT;
98+
}
99+
100+
unit csr_read_callback(sail_string csr_name, unsigned reg, uint64_t value)
101+
{
102+
if (config_print_reg) {
103+
fprintf(trace_log, "CSR %s (0x%03X) -> 0x%016" PRIX64 "\n", csr_name, reg,
104+
value);
105+
}
106+
return UNIT;
107+
}
108+
109+
unit vreg_write_callback(unsigned reg, lbits value)
110+
{
111+
if (config_print_reg) {
112+
fprintf(trace_log, "v%d <- ", reg);
113+
print_lbits_hex(value);
114+
}
115+
return UNIT;
116+
}
117+
118+
unit pc_write_callback(uint64_t value)
119+
{
120+
(void)value;
121+
return UNIT;
122+
}
123+
124+
unit trap_callback(unit)
125+
{
126+
#ifdef RVFI_DII
127+
if (config_enable_rvfi) {
128+
zrvfi_trap();
129+
}
130+
#endif
131+
return UNIT;
132+
}

c_emulator/riscv_callbacks.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#pragma once
2+
#include "sail.h"
3+
4+
#ifdef __cplusplus
5+
extern "C" {
6+
#endif
7+
8+
unit mem_write_callback(uint64_t addr, uint64_t width, lbits value);
9+
unit mem_read_callback(const char *type, uint64_t addr, uint64_t width,
10+
lbits value);
11+
unit mem_exception_callback(uint64_t addr, uint64_t num_of_exception);
12+
unit xreg_write_callback(unsigned reg, uint64_t value);
13+
unit freg_write_callback(unsigned reg, uint64_t value);
14+
unit csr_write_callback(sail_string csr_name, unsigned reg, uint64_t value);
15+
unit csr_read_callback(sail_string csr_name, unsigned reg, uint64_t value);
16+
unit vreg_write_callback(unsigned reg, lbits value);
17+
unit pc_write_callback(uint64_t value);
18+
unit trap_callback(unit);
19+
20+
#ifdef RVFI_DII
21+
// TODO: Move these implementations to C.
22+
unit zrvfi_write(uint64_t addr, int64_t width, lbits value);
23+
unit zrvfi_read(uint64_t addr, sail_int width, lbits value);
24+
unit zrvfi_mem_exception(uint64_t addr);
25+
unit zrvfi_wX(int64_t reg, uint64_t value);
26+
unit zrvfi_trap();
27+
#endif
28+
29+
#ifdef __cplusplus
30+
}
31+
#endif

c_emulator/riscv_config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ extern bool config_print_step;
66
extern bool config_print_reg;
77
extern bool config_print_mem_access;
88
extern bool config_print_platform;
9+
extern bool config_enable_rvfi;

c_emulator/riscv_prelude.cpp

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,6 @@ unit print_step(unit)
2222
return UNIT;
2323
}
2424

25-
unit print_reg(sail_string s)
26-
{
27-
if (config_print_reg)
28-
fprintf(trace_log, "%s\n", s);
29-
return UNIT;
30-
}
31-
32-
unit print_mem_access(sail_string s)
33-
{
34-
if (config_print_mem_access)
35-
fprintf(trace_log, "%s\n", s);
36-
return UNIT;
37-
}
38-
3925
unit print_platform(sail_string s)
4026
{
4127
if (config_print_platform)
@@ -45,20 +31,10 @@ unit print_platform(sail_string s)
4531

4632
bool get_config_print_instr(unit)
4733
{
48-
return (config_print_instr) ? true : false;
49-
}
50-
51-
bool get_config_print_reg(unit)
52-
{
53-
return (config_print_reg) ? true : false;
54-
}
55-
56-
bool get_config_print_mem(unit)
57-
{
58-
return (config_print_mem_access) ? true : false;
34+
return config_print_instr;
5935
}
6036

6137
bool get_config_print_platform(unit)
6238
{
63-
return (config_print_platform) ? true : false;
39+
return config_print_platform;
6440
}

c_emulator/riscv_prelude.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,9 @@ unit print_string(sail_string prefix, sail_string msg);
1111

1212
unit print_instr(sail_string s);
1313
unit print_step(unit);
14-
unit print_reg(sail_string s);
15-
unit print_mem_access(sail_string s);
1614
unit print_platform(sail_string s);
1715

1816
bool get_config_print_instr(unit);
19-
bool get_config_print_reg(unit);
20-
bool get_config_print_mem(unit);
2117
bool get_config_print_platform(unit);
2218

2319
#ifdef __cplusplus

c_emulator/riscv_sim.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ bool config_print_mem_access = true;
5757
bool config_print_platform = true;
5858
bool config_print_rvfi = false;
5959
bool config_print_step = false;
60+
bool config_enable_rvfi = true;
6061

6162
void set_config_print(char *var, bool val)
6263
{
@@ -66,6 +67,7 @@ void set_config_print(char *var, bool val)
6667
config_print_reg = val;
6768
config_print_platform = val;
6869
config_print_rvfi = val;
70+
config_enable_rvfi = val;
6971
} else if (strcmp("instr", var) == 0) {
7072
config_print_instr = val;
7173
} else if (strcmp("reg", var) == 0) {

model/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ foreach (xlen IN ITEMS 32 64)
261261
# Extra #include's.
262262
--c-include riscv_prelude.h
263263
--c-include riscv_platform.h
264+
--c-include riscv_callbacks.h
264265
# Don't dead-code eliminate these functions. These should match the
265266
# ones used from riscv_sail.h
266267
--c-preserve init_model
@@ -281,6 +282,12 @@ foreach (xlen IN ITEMS 32 64)
281282
--c-preserve rvfi_halt_exec_packet
282283
--c-preserve print_instr_packet
283284
--c-preserve print_rvfi_exec
285+
--c-preserve rvfi_write
286+
--c-preserve rvfi_read
287+
--c-preserve rvfi_mem_exception
288+
--c-preserve rvfi_wX
289+
--c-preserve rvfi_trap
290+
--c-preserve csr_name_map_forwards
284291
# Input files.
285292
${sail_srcs}
286293
)

model/prelude.sail

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,23 +62,16 @@ overload max = {max_int}
6262
val print_string = pure "print_string" : (string, string) -> unit
6363

6464
val print_instr = pure {interpreter: "print_endline", c: "print_instr", lem: "print_dbg", _: "print_endline"} : string -> unit
65-
val print_reg = pure {interpreter: "print_endline", c: "print_reg", lem: "print_dbg", _: "print_endline"} : string -> unit
66-
val print_mem = pure {interpreter: "print_endline", c: "print_mem_access", lem: "print_dbg", _: "print_endline"} : string -> unit
6765
val print_platform = pure {interpreter: "print_endline", c: "print_platform", lem: "print_dbg", _: "print_endline"} : string -> unit
6866

6967
val print_step = pure {c: "print_step"} : unit -> unit
7068

7169
function print_step() = ()
7270

7371
val get_config_print_instr = pure {c:"get_config_print_instr"} : unit -> bool
74-
val get_config_print_reg = pure {c:"get_config_print_reg"} : unit -> bool
75-
val get_config_print_mem = pure {c:"get_config_print_mem"} : unit -> bool
76-
7772
val get_config_print_platform = pure {c:"get_config_print_platform"} : unit -> bool
7873
// defaults for other backends
7974
function get_config_print_instr () = false
80-
function get_config_print_reg () = false
81-
function get_config_print_mem () = false
8275
function get_config_print_platform () = false
8376

8477
val sign_extend : forall 'n 'm, 'm >= 'n. (implicit('m), bits('n)) -> bits('m)

model/riscv_fdext_regs.sail

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ function nan_unbox(m, x) = if 'n == 'm then x else (
5555
newtype fregidx = Fregidx : bits(5)
5656
newtype fregno = Fregno : range(0, 31)
5757
function fregidx_to_fregno (Fregidx(b) : fregidx) -> fregno = Fregno(unsigned(b))
58+
function fregno_to_fregidx (Fregno(b) : fregno) -> fregidx = Fregidx(to_bits(5, b))
5859
function fregidx_offset(Fregidx(r) : fregidx, o : bits(5)) -> fregidx = Fregidx(r + o)
5960
function fregidx_bits(Fregidx(r) : fregidx) -> bits(5) = r
6061

@@ -69,6 +70,8 @@ function fregidx_to_regidx (Fregidx(b) : fregidx) -> regidx =
6970

7071
mapping encdec_freg : fregidx <-> bits(5) = { Fregidx(r) <-> r }
7172

73+
val freg_write_callback = pure {c: "freg_write_callback"} : (fregidx, flenbits) -> unit
74+
7275
register f0 : fregtype
7376
register f1 : fregtype
7477
register f2 : fregtype
@@ -106,6 +109,9 @@ function dirty_fd_context() -> unit = {
106109
assert(hartSupports(Ext_F));
107110
mstatus[FS] = extStatus_to_bits(Dirty);
108111
mstatus[SD] = 0b1;
112+
csr_write_callback("mstatus", csr_name_map("mstatus"), mstatus.bits[xlen - 1 .. 0]);
113+
if xlen == 32
114+
then csr_write_callback("mstatush", csr_name_map("mstatush"), mstatus.bits[63 .. 32]);
109115
}
110116

111117
function dirty_fd_context_if_present() -> unit = {
@@ -193,12 +199,8 @@ function wF (Fregno(r) : fregno, in_v : flenbits) -> unit = {
193199
_ => assert(false, "invalid floating point register number")
194200
};
195201

202+
freg_write_callback(fregno_to_fregidx(Fregno(r)), in_v);
196203
dirty_fd_context();
197-
198-
if get_config_print_reg()
199-
then
200-
/* TODO: will only print bits; should we print in floating point format? */
201-
print_reg("f" ^ dec_str(r) ^ " <- " ^ FRegStr(v));
202204
}
203205

204206
function rF_bits(i: fregidx) -> flenbits = rF(fregidx_to_fregno(i))

0 commit comments

Comments
 (0)