Skip to content

U2FsdGVkX1/RV32CSS

Repository files navigation

rv32CSS

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.

Frequently Asked Questions

Is JavaScript required?

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.

Can I run my own programs?

Yes. Put raw RV32 machine code bytes into program.bin, run compile_css.py, and open index.html.

Which ISA is implemented?

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).

Is this practical?

Not really. It is gloriously impractical and very fun.

Compatibility Notes

  • The decode/dispatch map is generated from riscv-instructions-rebane.json.
  • x0 is hard-wired to zero.
  • Memory size is 0x600 bytes in this build.
  • The standalone display TX MMIO address is 0x5F0.
  • Unsupported/illegal instructions halt execution.

Compiling

You can either provide raw machine code directly, or compile C to RV32IM first.

Option A: Start from raw machine code

  1. Put your machine code bytes in program.bin.
  2. (Optional) add initial_state.json to preload CPU state:
{
  "pc": 0,
  "registers": {"x1": 305419896},
  "memory": {"320": 170}
}

initial_state.json supports:

  • pc
  • registers (x0-x31, with x0 forced to zero)
  • byte memory overrides (0-1535)
  1. Generate HTML:
python3 compile_css.py
  1. Open index.html in a modern Chromium-based browser.

If program.bin does not exist, compile_css.py injects a tiny fallback demo ('A' then ebreak).

Option B: Compile C with LLVM (manual steps)

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.py

The included sample continuously prints the decimal Fibonacci stream as 32-bit unsigned values (single line, wraps on uint32_t overflow).

Testing

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 -q

Run one subset (substring filter):

RV32CSS_CASE_FILTER=DIV python3 -m pytest tests/test_rv32css_css.py -q

Override browser binary if needed:

CHROMIUM_BIN=/usr/bin/chromium-browser python3 -m pytest tests/test_rv32css_css.py -q

Credits

  • rebane2001/x86CSS for the original CSS CPU art/engineering direction this project salutes.

Releases

No releases published

Packages

 
 
 

Contributors