Architecture

The design is split so that each piece can be checked on its own. The RTL is the hardware. A golden model written in Python is the specification. The WebAssembly module is the same hardware, seen from the browser.

Memory map

RegionAddressSizeNotes
IMEM0x0000_00004 KiBLoaded by the harness; read-only to the core.
DMEM0x0001_00004 KiBByte-addressable: LB, LH, LW, SB, SH, SW.
CONSOLE0x0002_00001 wordWriting a byte sends it to the console panel.
TOHOST0x0002_00041 wordWriting 1 reports PASS and halts the core.
CYCLE0x0002_00081 wordReads the cycle counter.

Instruction and data memory are separate ports (a Harvard design), but they share one address space, so a program can read its own constants from DMEM.

Two cores, one instruction set

Both cores are compiled into the same WebAssembly module, and the app chooses one at run time.

The golden model

The reference is an instruction-set simulator written in Python (sim/golden/iss.py). It executes every instruction and writes a retire record for each one: the program counter, the instruction, the register and memory it changed, and the next program counter. The RTL is checked by comparing its retire records to the model's, instruction by instruction.

Assembler in the browser

The app assembles RV32I source itself. Its output is byte-for-byte what the GNU RISC-V toolchain produces for the same source, which is tested against GNU's output.

The contract between hardware and browser

The WebAssembly module exposes the state of each cycle as a plain object: the five stages, the hazard flags, the registers, the retired instruction, console output and tohost. The field-by-field definition is in docs/STATE_SCHEMA.md, and the browser checks every state it receives against it.