SoC Devices¶
rvsim models a complete system-on-chip based on the QEMU virt machine layout. This is the same memory map that Linux and OpenSBI expect, allowing unmodified firmware and kernels to boot.
Memory Map¶
| Device | Base Address | Size | Description |
|---|---|---|---|
| SYSCON | 0x0010_0000 |
4KB | System controller (power-off, reset, failure) |
| Goldfish RTC | 0x0010_1000 |
4KB | Real-time clock |
| Sim control | 0x0010_2000 |
4KB | Guest control of statistics and the run |
| CLINT | 0x0200_0000 |
64KB | Core Local Interruptor |
| PLIC | 0x0C00_0000 |
64MB | Platform-Level Interrupt Controller |
| UART | 0x1000_0000 |
4KB | 16550A serial port |
| RAM | 0x8000_0000 |
configurable | Main memory (default: 256MB) |
| VirtIO Disk | 0x9000_0000 |
4KB | Block device |
| HTIF | the ELF's tohost symbol |
16B | Test pass/fail for riscv-tests |
The bases of RAM, the UART, the disk, the CLINT, SYSCON and sim control
are configurable (see Configuration); the
RTC and PLIC are fixed. presets.linux() moves the disk to 0x1000_1000,
beside the UART, where the bundled image's device tree expects it.
Device access timing¶
Devices sit on the system bus, so an uncached access pays bus_latency
each way, and every device takes device_latency_ns (100 ns by default)
to answer a register access, converted to cycles at cpu_clock_mhz.
device_latency_ns_overrides sets the time per device, by the names
UART0, CLINT, PLIC, VirtIO-Blk, SysCon, GoldfishRTC and
HTIF. Device accesses bypass the caches, and a load from a device waits
until it is the oldest instruction, so it is never performed on a wrong
path.
Devices¶
CLINT (Core Local Interruptor)¶
Timer and software-interrupt registers for every hart, at the standard
layout (msip at 0x0 + 4·hart, mtimecmp at 0x4000 + 8·hart, one
mtime at 0xBFF8):
mtimeincrements everyclint_dividerCPU cycles (default: 10)- The device tree advertises a 10 MHz timebase.
presets.linux()setsclint_dividertocpu_clock_mhz / 10somtimeruns at that rate and the guest's clock keeps simulated time; with another divider the guest's time runs fast or slow by the ratio - When
mtime >= mtimecmp[hart], that hart's timer interrupt is raised (MIP.MTIP) - Writing
msip[hart]raises that hart's software interrupt (MIP.MSIP); this is how firmware sends inter-processor interrupts - Timer interrupts can be delegated to S-mode via
mideleg
PLIC (Platform-Level Interrupt Controller)¶
Priority-based interrupt controller with:
- 53 interrupt sources advertised in the device tree (the UART is source 10 and the disk source 1)
- 2 contexts per hart: context
2·hartis the hart's M-mode target and2·hart + 1its S-mode target (enables at0x2000 + 0x80·context, threshold and claim at0x200000 + 0x1000·context) - Per-source priority registers
- Per-context enable bits and priority threshold
- Claim/complete protocol: reading the claim register returns the highest-priority pending interrupt and clears it
Every cycle the bus ticks each device once, feeds the active sources into
the PLIC, and samples one set of lines per hart (mtip, msip, meip,
seip) that the hart folds into its mip before its pipeline ticks. A
change in the PLIC's pending, enable or threshold state reaches the lines
and the claim registers three cycles later, as in gem5's PLIC.
UART (16550A)¶
Serial port compatible with the NS16550A register interface:
- Transmit and receive holding registers
- Interrupt enable register (IER) with receive data available and transmit holding register empty interrupts
- Line status register (LSR) with data ready and transmitter empty bits
- FIFO control register (FCR)
- Output leaves as it is written; the transmit-empty and receive-data
interrupts rise 225 ns after their cause, as in gem5's
Uart8250
console connects the UART to stdout (the default), stderr, nothing
("quiet"), or an in-memory buffer ("captured") that the host reads with
read_console() and writes input to with write_console(); Linux sessions
use the captured console to type commands at the shell.
VirtIO MMIO Block Device¶
VirtIO specification-compliant block device:
- MMIO transport (VirtIO version 2)
- Single virtqueue for block I/O requests
- Read and write operations via DMA from/to guest memory: a request's DMA moves over the system bus and memory controller phase by phase (the ring and descriptor reads, the data in line-sized transfers, then the status and used-ring writes), and the request completes when its last transfer returns
- Backed by a host file (e.g., a rootfs image)
- Interrupt notification via PLIC, raised when the request completes
Used to mount the root filesystem when booting Linux.
Goldfish RTC¶
Real-time clock providing wall-clock time:
- Read-only
TIME_LOWandTIME_HIGHregisters, in nanoseconds - Reports
rtc_epoch_seconds(2026-01-01 by default) plus the simulated time elapsed atcpu_clock_mhz, never the host's clock, so every run reads the same time - Used by Linux to set the system time at boot
SYSCON (System Controller)¶
A 32-bit command register at offset 0, as QEMU's virt machine has:
| Value | Meaning | Exit code |
|---|---|---|
0x5555 |
Power off | 0 |
0x7777 |
Reset, taken as an exit | 0 |
0x3333 |
Failure | 1 |
Linux's poweroff and reboot reach it through OpenSBI's system-reset
call.
Sim control¶
Lets software in the guest mark what the host should measure, as gem5's
m5 operations do. Write the argument to ARG (offset 0x08), then the
command to COMMAND (offset 0x00):
| Command | Effect |
|---|---|
1 |
Reset the statistics |
2 |
Keep a snapshot of the statistics labelled ARG; the host subtracts two snapshots to get the region between them |
3 |
End the simulation with exit code ARG |
4 |
Stop the host's run here, labelled ARG, so it can save, switch configuration or measure from this point |
Bare-metal programs use the inline functions in software/libc/rvsim.h.
In a Linux guest, the rvsim tool (software/guest/rvsim.c, installed in
the bundled root filesystem) maps the device through /dev/mem;
rvsim run START END CMD snapshots the statistics around one command,
which is how Session.measure() and rvsim bench delimit a benchmark.
HTIF (Host-Target Interface)¶
Berkeley Host-Target Interface for riscv-tests compatibility:
- A 16-byte slot at the address of the ELF's
tohostsymbol, found when the program is loaded - Writing
tohost = 1ends the run with exit code 0; an odd value above 1 is a failure, with the failing test number invalue >> 1 - Writing 0 is ignored, as the tests clear
tohostbefore reporting
There is no system-call proxying. Bare-metal programs without a trap
handler end with ecall: with a7 = 93 (exit) the run ends with a0 as
its exit code.
Device Tree¶
rvsim generates a Flattened Device Tree Blob (DTB) from the active
configuration, unless a DTB file is supplied. It is placed at
ram_base + 0x0220_0000 and contains:
- One
cpu@Nnode per hart, with themisaletters plus_sstc(and_svaduwhen enabled) as itsriscv,isa,riscv,sv39as its MMU type, and acpu-map - A memory node sized to
ram_size - The CLINT, with timer and software interrupts for every hart, and the PLIC, with an M- and an S-mode context for every hart
- The UART, the VirtIO disk, SYSCON with
syscon-poweroffandsyscon-rebootnodes, and the RTC timebase-frequencyand achosennode with the boot arguments (root=/dev/vda rw console=ttyS0, with an early console on the UART)
The DTB's address is passed to the firmware in a1, following the
standard RISC-V boot protocol.
Boot Flow¶
- OpenSBI is loaded at
ram_base, the kernel image atram_base + 0x20_0000and the DTB atram_base + 0x0220_0000. - Every hart starts in OpenSBI in M-mode with its hart id in
a0and the DTB ina1. For thefw_dynamicfirmware,a2points to thefw_dynamic_inforecord naming the kernel's address and S-mode. - OpenSBI's boot lottery picks one hart to initialise the platform and parks the rest, delegates traps to S-mode, and enters the kernel.
- Linux brings the other harts up through the SBI hart-state calls, mounts the VirtIO root filesystem and starts BusyBox's init.
- A shell prompt appears on the UART.
Without firmware the loader instead places an MRET at ram_base whose
mepc is a kernel loaded at ram_base + kernel_offset; kernel_offset
has no effect when OpenSBI is used.