Skip to content

Commit baf1374

Browse files
committed
Refactor chip reset
This simplifies, clarifies and fixes the reset functionality. Until now the model conflates reset and initialisation, and does way more than it should on reset. The RISC-V spec only requires a very small number of things to be reset. This change: 1. Renames the `init` functions to `reset`, to clarify that they correspond to resetting the chip. 2. Removes the `ext_init` and `ext_rvfi_init` functions. The latter is not used and the former is only used by the old CHERI code. 2. Removes the reset of the X and F registers. These are non-reset. 3. Removes the reset of various CSRs that are non-reset (`mip`, `mie`, `mideleg`, `mtvec`, `mepc`, etc). 4. Adds reset of `mstatus[MIE]` and `mstatus[MPRV]`. As far as I can see they were missing. 5. Add one-time init of `mhartid` etc to 0. I didn't remove the vector register resets yet. That needs a bigger refactor. Also note that currently there is no way to actually do a chip reset mid-simulation, but that will be needed eventually.
1 parent 601f3d8 commit baf1374

14 files changed

+84
-182
lines changed

c_emulator/riscv_sail.h

-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ unit ztick_clock(unit);
2020
unit ztick_platform(unit);
2121

2222
#ifdef RVFI_DII
23-
unit zext_rvfi_init(unit);
2423
unit zrvfi_set_instr_packet(mach_bits);
2524
mach_bits zrvfi_get_cmd(unit);
2625
mach_bits zrvfi_get_insn(unit);

c_emulator/riscv_sim.c

+1-8
Original file line numberDiff line numberDiff line change
@@ -658,17 +658,11 @@ void init_sail_reset_vector(uint64_t entry)
658658
zPC = rv_rom_base;
659659
}
660660

661-
void preinit_sail()
662-
{
663-
model_init();
664-
}
665-
666661
void init_sail(uint64_t elf_entry)
667662
{
668663
zinit_model(UNIT);
669664
#ifdef RVFI_DII
670665
if (rvfi_dii) {
671-
zext_rvfi_init(UNIT);
672666
rv_ram_base = UINT64_C(0x80000000);
673667
rv_ram_size = UINT64_C(0x800000);
674668
rv_rom_base = UINT64_C(0);
@@ -1138,8 +1132,7 @@ void init_logs()
11381132

11391133
int main(int argc, char **argv)
11401134
{
1141-
// Initialize model so that we can check or report its architecture.
1142-
preinit_sail();
1135+
model_init();
11431136

11441137
int files_start = process_args(argc, argv);
11451138
char *initial_elf_file = argv[files_start];

model/main.sail

-3
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@ function get_entry_point() = zero_extend(0x1000)
2424
$endif
2525

2626
function main() : unit -> unit = {
27-
// initialize extensions
28-
ext_init();
29-
3027
PC = get_entry_point();
3128
print_bits("PC = ", PC);
3229

model/riscv_ext_regs.sail

-14
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,6 @@
1010
* overridden by extensions.
1111
*/
1212

13-
val ext_init_regs : unit -> unit
14-
function ext_init_regs () = ()
15-
16-
/*!
17-
This function is called after above when running rvfi and allows the model
18-
to be initialised differently (e.g. CHERI cap regs are initialised
19-
to omnipotent instead of null).
20-
*/
21-
val ext_rvfi_init : unit -> unit
22-
function ext_rvfi_init () = {
23-
x1 = x1 // to avoid hook being optimized out
24-
}
25-
26-
2713
/*!
2814
THIS(csrno, priv, isWrite) allows an extension to block access to csrno,
2915
at Privilege level priv. It should return true if the access is allowed.

model/riscv_fdext_regs.sail

-36
Original file line numberDiff line numberDiff line change
@@ -353,42 +353,6 @@ mapping freg_or_reg_name = {
353353
reg if sys_enable_zfinx() <-> reg_name(reg) if sys_enable_zfinx()
354354
}
355355

356-
val init_fdext_regs : unit -> unit
357-
function init_fdext_regs () = {
358-
f0 = zero_freg;
359-
f1 = zero_freg;
360-
f2 = zero_freg;
361-
f3 = zero_freg;
362-
f4 = zero_freg;
363-
f5 = zero_freg;
364-
f6 = zero_freg;
365-
f7 = zero_freg;
366-
f8 = zero_freg;
367-
f9 = zero_freg;
368-
f10 = zero_freg;
369-
f11 = zero_freg;
370-
f12 = zero_freg;
371-
f13 = zero_freg;
372-
f14 = zero_freg;
373-
f15 = zero_freg;
374-
f16 = zero_freg;
375-
f17 = zero_freg;
376-
f18 = zero_freg;
377-
f19 = zero_freg;
378-
f20 = zero_freg;
379-
f21 = zero_freg;
380-
f22 = zero_freg;
381-
f23 = zero_freg;
382-
f24 = zero_freg;
383-
f25 = zero_freg;
384-
f26 = zero_freg;
385-
f27 = zero_freg;
386-
f28 = zero_freg;
387-
f29 = zero_freg;
388-
f30 = zero_freg;
389-
f31 = zero_freg
390-
}
391-
392356
/* **************************************************************** */
393357
/* Floating Point CSR */
394358
/* fflags address 0x001 same as fcrs [4..0] */

model/riscv_pmp_control.sail

+1-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ function pmpCheck forall 'n, 'n > 0. (addr: physaddr, width: int('n), acc: Acces
126126
if priv == Machine then None() else Some(accessToFault(acc))
127127
}
128128

129-
function init_pmp() -> unit = {
129+
function reset_pmp() -> unit = {
130130
assert(
131131
sys_pmp_count() == 0 | sys_pmp_count() == 16 | sys_pmp_count() == 64,
132132
"sys_pmp_count() must be 0, 16, or 64"

model/riscv_regs.sail

-35
Original file line numberDiff line numberDiff line change
@@ -198,38 +198,3 @@ mapping creg_name : cregidx <-> string = {
198198
0b110 <-> "a4",
199199
0b111 <-> "a5"
200200
}
201-
202-
val init_base_regs : unit -> unit
203-
function init_base_regs () = {
204-
x1 = zero_reg;
205-
x2 = zero_reg;
206-
x3 = zero_reg;
207-
x4 = zero_reg;
208-
x5 = zero_reg;
209-
x6 = zero_reg;
210-
x7 = zero_reg;
211-
x8 = zero_reg;
212-
x9 = zero_reg;
213-
x10 = zero_reg;
214-
x11 = zero_reg;
215-
x12 = zero_reg;
216-
x13 = zero_reg;
217-
x14 = zero_reg;
218-
x15 = zero_reg;
219-
x16 = zero_reg;
220-
x17 = zero_reg;
221-
x18 = zero_reg;
222-
x19 = zero_reg;
223-
x20 = zero_reg;
224-
x21 = zero_reg;
225-
x22 = zero_reg;
226-
x23 = zero_reg;
227-
x24 = zero_reg;
228-
x25 = zero_reg;
229-
x26 = zero_reg;
230-
x27 = zero_reg;
231-
x28 = zero_reg;
232-
x29 = zero_reg;
233-
x30 = zero_reg;
234-
x31 = zero_reg
235-
}

model/riscv_step.sail

+12-8
Original file line numberDiff line numberDiff line change
@@ -123,13 +123,17 @@ function loop () : unit -> unit = {
123123
}
124124
}
125125

126-
/* initialize model state */
127-
function init_model () -> unit = {
128-
init_platform (); /* devices */
129-
init_sys (); /* processor */
130-
init_vmem (); /* virtual memory */
126+
// Chip reset. This only does the minimum resets required by the RISC-V spec.
127+
function reset() -> unit = {
128+
reset_sys();
129+
reset_vmem();
131130

132-
/* initialize extensions last */
133-
ext_init ();
134-
ext_init_regs ();
131+
// To allow model extensions (code outside this repo) to perform additional reset.
132+
ext_reset();
133+
}
134+
135+
// Initialize model state. This is only called once; not for every chip reset.
136+
function init_model() -> unit = {
137+
init_platform();
138+
reset();
135139
}

model/riscv_step_ext.sail

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88

99
/* The default implementation of hooks for the step() and main() functions. */
1010

11-
function ext_init() -> unit = ()
12-
1311
function ext_fetch_hook(f : FetchResult) -> FetchResult = f
1412

1513
function ext_pre_step_hook() -> unit = ()
1614
function ext_post_step_hook() -> unit = ()
15+
16+
function ext_reset() -> unit = ()

model/riscv_step_rvfi.sail

+1-9
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,4 @@ function ext_post_step_hook() -> unit = {
1717
rvfi_pc_data[rvfi_pc_wdata] = zero_extend(get_arch_pc())
1818
}
1919

20-
val ext_init : unit -> unit
21-
function ext_init() = {
22-
init_base_regs();
23-
init_fdext_regs();
24-
/* these are here so that the C backend doesn't prune them out. */
25-
// let _ = rvfi_step(0);
26-
ext_rvfi_init();
27-
()
28-
}
20+
function ext_reset() -> unit = ()

model/riscv_sys_control.sail

+39-39
Original file line numberDiff line numberDiff line change
@@ -303,15 +303,8 @@ function handle_exception(e: ExceptionType) -> unit = {
303303
function handle_interrupt(i : InterruptType, del_priv : Privilege) -> unit =
304304
set_next_pc(trap_handler(del_priv, true, interruptType_to_bits(i), PC, None(), None()))
305305

306-
/* state state initialization */
307-
308-
function init_sys() -> unit = {
309-
cur_privilege = Machine;
310-
311-
mhartid = zeros();
312-
mconfigptr = zeros();
313-
314-
misa[MXL] = arch_to_bits(if xlen == 32 then RV32 else RV64);
306+
// Reset misa to enable the maximal set of supported extensions.
307+
function reset_misa() -> unit = {
315308
misa[A] = 0b1; /* atomics */
316309
misa[C] = bool_to_bits(sys_enable_rvc()); /* RVC */
317310
misa[B] = bool_to_bits(sys_enable_bext()); /* Bit-manipulation */
@@ -327,40 +320,50 @@ function init_sys() -> unit = {
327320
/* We currently support both F and D */
328321
misa[F] = bool_to_bits(sys_enable_fdext()); /* single-precision */
329322
misa[D] = if flen >= 64
330-
then bool_to_bits(sys_enable_fdext()) /* double-precision */
331-
else 0b0;
323+
then bool_to_bits(sys_enable_fdext()) /* double-precision */
324+
else 0b0;
325+
}
332326

333-
mstatus = set_mstatus_SXL(mstatus, misa[MXL]);
334-
mstatus = set_mstatus_UXL(mstatus, misa[MXL]);
335-
mstatus[SD] = 0b0;
336-
mstatus[MPP] = privLevel_to_bits(lowest_supported_privLevel());
327+
// This function is called on reset, so it should only perform the reset actions
328+
// described in the "Reset" section of the privileged architecture specification.
329+
function reset_sys() -> unit = {
337330

338-
/* set to little-endian mode */
339-
if xlen == 64 then {
340-
mstatus = Mk_Mstatus([mstatus.bits with 37 .. 36 = 0b00])
341-
};
342-
mstatush.bits = zeros();
331+
// "Upon reset, a hart's privilege mode is set to M."
332+
cur_privilege = Machine;
333+
334+
// "The mstatus fields MIE and MPRV are reset to 0."
335+
mstatus[MIE] = 0b0;
336+
mstatus[MPRV] = 0b0;
337+
338+
// "If little-endian memory accesses are supported, the mstatus/mstatush field
339+
// MBE is reset to 0."
340+
// TODO: The handling of mstatush is a bit awkward currently, but the model
341+
// currently only supports little endian so MBE is always 0.
342+
// See https://github.com/riscv/sail-riscv/issues/639
343+
// mstatus[MBE] = 0b0;
343344

344-
mip.bits = zeros();
345-
mie.bits = zeros();
346-
mideleg.bits = zeros();
347-
medeleg.bits = zeros();
348-
mtvec.bits = zeros();
349-
mcause.bits = zeros();
350-
mepc = zeros();
351-
mtval = zeros();
352-
mscratch = zeros();
345+
// "The misa register is reset to enable the maximal set of supported extensions"
346+
reset_misa();
353347

354-
mcycle = zeros();
355-
mtime = zeros();
348+
// "For implementations with the "A" standard extension, there is no valid load reservation."
349+
cancel_reservation();
356350

357-
mcounteren.bits = zeros();
351+
// "The pc is set to an implementation-defined reset vector."
352+
// This is outside the scope of this function.
358353

359-
minstret = zeros();
360-
minstret_increment = true;
354+
// "The mcause register is set to a value indicating the cause of the reset."
355+
// "The mcause values after reset have implementation-specific interpretation,
356+
// but the value 0 should be returned on implementations that do not
357+
// distinguish different reset conditions."
358+
mcause.bits = zeros();
359+
360+
// "Writable PMP registers’ A and L fields are set to 0, unless the platform
361+
// mandates a different reset value for some PMP registers’ A and L fields."
362+
reset_pmp();
363+
364+
// TODO: Probably need to remove these vector resets too but it needs
365+
// refactoring anyway. See https://github.com/riscv/sail-riscv/issues/566 etc.
361366

362-
menvcfg.bits = zeros();
363-
senvcfg.bits = zeros();
364367
/* initialize vector csrs */
365368
vstart = zeros();
366369
vl = zeros();
@@ -373,9 +376,6 @@ function init_sys() -> unit = {
373376
vtype[vsew] = 0b000;
374377
vtype[vlmul] = 0b000;
375378

376-
// PMP's L and A fields are set to 0 on reset.
377-
init_pmp();
378-
379379
// log compatibility with spike
380380
if get_config_print_reg()
381381
then print_reg("CSR mstatus <- " ^ BitStr(mstatus.bits) ^ " (input: " ^ BitStr(zeros() : xlenbits) ^ ")")

0 commit comments

Comments
 (0)