riscv / sail-riscv

Sail RISC-V model
https://lists.riscv.org/g/tech-golden-model
Other
465 stars 168 forks source link

Move platform specific MMIO from Sail to C #512

Open defermelowie opened 4 months ago

defermelowie commented 4 months ago

Since (most) MMIO devices are not part of the RISC-V specification and are only implemented to support the emulator, it might make sense to implement them in the C emulator directly instead of Sail. (For example HTIF, but also UART devices like discussed in #504)

I thought about this a little bit and came up with the following "API":

// model/riscv_platform.sail

val plat_mmio_within_readable  = { c: "plat_mmio_within_readable", ...  } : (xlenbits, int) -> bool
val plat_mmio_within_writeable = { c: "plat_mmio_within_writeable", ... } : (xlenbits, int) -> bool
val plat_mmio_read             = { c: "plat_mmio_read", ...             } : (xlenbits, int) -> xlenbits
val plat_mmio_write            = { c: "plat_mmio_write", ...            } : (xlenbits, int, xlenbits) -> xlenbits
// c_emulator/riscv_platform.h

bool plat_mmio_within_readable(mach_bits addr, sail_int width);
bool plat_mmio_within_writeable(mach_bits addr, sail_int width);
mach_bits plat_mmio_read(mach_bits addr, sail_int width);
mach_bits plat_mmio_write(mach_bits addr, sail_int width, mach_bits data);

plat_within_mmio_readable and plat_mmio_within_writeable are used to check if an address falls within the platform specific MMIO for a given access. Backends that do not provide MMIO can simply return false for these.

plat_mmio_read and plat_mmio_write perform the actual access. They should only be called whenever their corresponding plat_mmio_within_... passes. Therefore, backends that don't have MMIO can provide a simple stub.

Perhaps it is useful for plat_mmio_write to return whatever was actually written such that this can be logged easily.

Just a thought, please reply with your remarks/suggestions