rv32CSS is a working CSS-only RV32IM CPU/emulator/computer. Yes, CSS. JavaScript is optional.
This project is a direct tribute to rebane2001/x86CSS, and keeps the same generator/template spirit where practical.
Nope.
The CPU state machine is CSS-driven. There is an optional JS accelerator loop in the page to tick faster and more smoothly, but the CSS clock path still exists and runs without JS.
Yes. Put raw RV32 machine code bytes into program.bin, run compile_css.py, and open index.html.
Current standalone build implements RV32IM (48 instructions total):
- RV32I control flow:
LUI AUIPC JAL JALR BEQ BNE BLT BGE BLTU BGEU - RV32I memory:
LB LH LW LBU LHU SB SH SW - RV32I ALU/imm:
ADDI SLTI SLTIU XORI ORI ANDI SLLI SRLI SRAI ADD SUB SLL SLT SLTU XOR SRL SRA OR AND - RV32I misc/system:
FENCE ECALL EBREAK - RV32M:
MUL MULH MULHSU MULHU DIV DIVU REM REMU - CPU state shown on page: 32 GPRs (
x0-x31) +pc/halted/exit-code/ cycle counter
Not implemented in this build: privileged ISA, CSR instructions (Zicsr), atomics (A), compressed (C), floating-point (F/D), and FENCE.I (Zifencei).
Not really. It is gloriously impractical and very fun.
- The decode/dispatch map is generated from
riscv-instructions-rebane.json. x0is hard-wired to zero.- Memory size is
0x600bytes in this build. - The standalone display TX MMIO address is
0x5F0. - Unsupported/illegal instructions halt execution.
You can either provide raw machine code directly, or compile C to RV32IM first.
- Put your machine code bytes in
program.bin. - (Optional) add
initial_state.jsonto preload CPU state:
{
"pc": 0,
"registers": {"x1": 305419896},
"memory": {"320": 170}
}initial_state.json supports:
pcregisters(x0-x31, withx0forced to zero)- byte
memoryoverrides (0-1535)
- Generate HTML:
python3 compile_css.py- Open
index.htmlin a modern Chromium-based browser.
If program.bin does not exist, compile_css.py injects a tiny fallback demo ('A' then ebreak).
Included files:
- Source example:
fib.c - Linker script:
rv32.ld
Build commands:
clang \
--target=riscv32-unknown-elf \
-fuse-ld=lld \
-march=rv32im \
-mabi=ilp32 \
-ffreestanding \
-fno-builtin \
-fno-stack-protector \
-nostdlib \
-Oz \
-Wl,-T,rv32.ld \
-Wl,--gc-sections \
-Wl,--no-relax \
fib.c \
-o fib.elf
llvm-objcopy -O binary fib.elf program.bin
python3 compile_css.pyThe included sample continuously prints the decimal Fibonacci stream as 32-bit unsigned values (single line, wraps on uint32_t overflow).
The test harness compares CSS execution against an independent Python RV32IM reference model by running the generated page in headless Chromium.
- Test matrix:
tests/test_rv32css_css.py - Case builder:
tests/rv32css_cases.py - CSS runner:
tests/rv32css_css_runner.py - Reference model:
tests/rv32css_reference.py
Run all tests:
python3 -m pytest tests/test_rv32css_css.py -qRun one subset (substring filter):
RV32CSS_CASE_FILTER=DIV python3 -m pytest tests/test_rv32css_css.py -qOverride browser binary if needed:
CHROMIUM_BIN=/usr/bin/chromium-browser python3 -m pytest tests/test_rv32css_css.py -q- rebane2001/x86CSS for the original CSS CPU art/engineering direction this project salutes.