Skip to content

Repository files navigation

mlogv32

RISC-V processor in Mindustry logic that runs Linux. Requires Mindustry build 150+.

linux

Architecture

Physical memory consists of three sections. Two are directly accessible by code: ROM (rx) and RAM (rwx). The third section is an instruction cache, which sits directly after RAM and uses the same processor layout to store partially decoded instructions.

For maximum performance, the instruction cache for ROM can be initialized at boot using the MLOGSYS instruction. It is also updated whenever an instruction writes to RAM that is covered by the icache. If executing from memory not covered by the icache, the processor manually fetches and decodes the instruction from main memory.

Instructions are cached in the following format, utilizing the full 54 bits of double precision (53 mantissa, 1 sign).

53:4746:4241:3736:3231:0
op_id (-64 to 63)rs2rs1rdimm

The CPU is implemented using a variable-size build-order-independent subframe architecture. There is one controller processor and an arbitrary number of worker processors. Schematics are generated using a custom preprocessor based on Jinja and pymsch.

Memory

AddressSizeAccess TypeName
0x00000000ConfigurableR/XProgram ROM
ConfigurableConfigurableR/XData ROM
0x80000000ConfigurableR/W/X/A*RAM
0xf00000000x8R/Wmtime
0xf00000080x8R/Wmtimecmp
0xf00000100x10R/WUART0
0xf00000200x10R/WUART1
0xf00000300x10R/WUART2
0xf00000400x10R/WUART3
0xfffffff00x4R/WSyscon

* Atomic instructions are only supported in RAM.

Code begins executing at address 0x00000000 (ie. the start of ROM).

ROM may optionally be partitioned into program ROM and data ROM. Data ROM begins immediately after program ROM and is not included in the instruction cache, allowing large amounts of data to be included in ROM while maintaining icache coverage of RAM. Despite being intended for storing data, it is still possible to execute from data ROM (eg. to allow efficiently implementing zero stage bootloaders without wasting icache space). The division between program and data ROM must be aligned to 16K, ie. the size of one memory proc. By default, data ROM has a size of 0.

Addresses 0xf0000000 - 0xffffffff are reserved for system purposes such as MMIO.

Machine Timers

The mtime and mtimecmp registers are mapped to 0xf0000000 and 0xf0000008 respectively. The frequency is configurable, defaulting to a period of 1 μs. The timer registers are not accessible to privilege modes lower than M-mode.

UART

The processor includes four instances of an emulated UART peripheral compatible with the AXI UART Lite. The UARTs support the following features:

  • Up to 32 data bits.
  • Configurable FIFO capacity (up to 253 bytes) for TX and RX, stored as a variable in the CONFIG processor.
  • Theoretical maximum transfer rate of 121440 bits/sec (253 bytes/tick).
  • Edge-triggered interrupts for RX FIFO non-empty and TX FIFO empty.
OffsetAccess TypeRegister
0x0RRX FIFO
0x4WTX FIFO
0x8RStatus
0xcWControl

Each UART is implemented as two circular buffers in a memory bank with the following layout. Note that RX refers to data sent to / read by the processor, and TX refers to data sent from / written by the processor.

IndexName
0RX buffer start
254RX buffer read pointer
255RX buffer write pointer / overflow flag
256TX buffer start
510TX buffer read pointer
511TX buffer write pointer

Read/write pointers are stored modulo capacity + 1. A buffer is empty when rptr == wptr and full when rptr == (wptr + 1) % (capacity + 1). If the RX buffer is full and more data arrives, producers should discard the new data rather than overwriting old data in the buffer.

Note that the processor itself does not prevent code from overflowing the TX buffer. Users are expected to check the Status register and avoid writing too much data at once.

If any UART interrupt is pending, mip.MEIP will become pending. To make UART interrupts visible to S-mode, M-mode software must either delegate mip.MEIP via mideleg, or manually update mip.SEIP in an M-mode interrupt handler. The interrupt for a given port is cleared when the Status register for that port is accessed.

Internally, UART interrupts are implemented using the uart_flags variable.

7:43:0
ieip

ip and ie are similar to the RISC-V mip and mie registers. UART i corresponds with bit i in both ip and ie.

Syscon

Address 0xfffffff0 contains a simple memory-mapped peripheral which can be used to control the system by writing values from the following table. Unsupported values will have no effect if written. Reads will always return 0.

ValueEffect
0x00000000Power off
0x00000001Reboot
0x00000002Power off

Additionally, the trap vector CSRs mtvec and stvec are initialized to 0xfffffff0 at reset. To help catch issues with uninitialized trap vectors, the processor will halt and output an error message if a trap jumps to this address.

ISA

RV32IMAZicntr_Zicsr_Zifencei_Zihintpause_Sstc_Svade

Supported privilege levels: M, S, U

Supported address translation schemes: Bare, Sv32

ExtensionVersion
M-mode1.13
S-mode1.13
I2.1
M2.0
A2.1
Zicntr2.0
Zicsr2.0
Zifencei*2.0
Zihintpause2.0
Sstc1.0.0
Svade1.0
XmlogsysN/A

* Zifencei is currently just a stub - the instruction cache is already updated on every write to memory.

Xmlogsys

This non-standard extension adds instructions to control the mlogv32 processor's hardware and access certain Mlog features.

funct12 (31:20)rs1 (19:15)funct3 (14:12)rd (11:7)opcode (6:0)name
funct12rs1000000000001011MLOGSYS

The MLOG instructions are encoded with an I-type instruction format using the custom-0 opcode. The zero-extended immediate is used as a minor opcode (funct12) for implementation reasons.

The MLOGSYS instruction is used for simple system controls.

The mlogsys.icache M-mode instruction uses register rs1 as the number of bytes to decode. This can be generated by using a linker script to find the end address of the .text section and load it using li. The actual number of bytes decoded will be the smallest of rs1, the size of the icache, and the size of ROM.

funct12rs1name
0lengthInitialize ROM icache

CSRs

CSR values are stored either in a RAM processor (CSRS), in a variable in the CPU, or as an implicit read-only zero value, depending on the CSR. See cpu.yaml for the full list of implemented CSRs. Attempts to access a CSR that is not in this list will raise an illegal instruction exception.

cycle

The [m]cycle[h] counter is incremented at the start of each worker's tick, just before it jumps back into code execution. The period should be something like number of workers * 1/60 seconds, but it will vary based on FPS.

riscv-arch-test

mlogv32 currently passes all compliance tests for the RV32IMASUZicsr_Zifencei ISA.

Commit: riscv-non-isa/riscv-arch-test@6731c039

TEST NAMESTATUS
riscv-arch-test/riscv-test-suite/rv32i_m/A/src/amoadd.w-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/A/src/amoand.w-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/A/src/amomax.w-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/A/src/amomaxu.w-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/A/src/amomin.w-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/A/src/amominu.w-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/A/src/amoor.w-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/A/src/amoswap.w-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/A/src/amoxor.w-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/add-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/addi-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/and-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/andi-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/auipc-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/beq-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/bge-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/bgeu-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/blt-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/bltu-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/bne-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/fence-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/jal-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/jalr-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/lb-align-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/lbu-align-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/lh-align-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/lhu-align-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/lui-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/lw-align-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/misalign1-jalr-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/or-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/ori-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/sb-align-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/sh-align-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/sll-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/slli-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/slt-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/slti-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/sltiu-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/sltu-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/sra-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/srai-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/srl-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/srli-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/sub-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/sw-align-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/xor-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/I/src/xori-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/M/src/div-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/M/src/divu-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/M/src/mul-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/M/src/mulh-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/M/src/mulhsu-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/M/src/mulhu-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/M/src/rem-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/M/src/remu-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/Zifencei/src/Fencei.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/pmp/src/pmp32-CSR-ALL-MODES.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/pmp/src/pmp32-NA4-M.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/pmp/src/pmp32-NA4-S.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/pmp/src/pmp32-NA4-U.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/pmp/src/pmp32-NAPOT-M.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/pmp/src/pmp32-NAPOT-S.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/pmp/src/pmp32-NAPOT-U.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/pmp/src/pmp32-TOR-M.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/pmp/src/pmp32-TOR-S.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/pmp/src/pmp32-TOR-U.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/ebreak.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/ecall.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-beq-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-bge-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-bgeu-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-blt-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-bltu-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-bne-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-jal-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-lh-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-lhu-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-lw-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-sh-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-sw-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign2-jalr-01.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/mstatus_tvm_test.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/pmp_check_on_pa_S_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/pmp_check_on_pa_U_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/pmp_check_on_pte_S_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/pmp_check_on_pte_U_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/satp_access_tests.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_A_and_D_S_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_A_and_D_U_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_U_Bit_set_U_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_U_Bit_unset_S_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_U_Bit_unset_U_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_VA_all_ones_S_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_global_pte_S_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_global_pte_U_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_invalid_pte_S_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_invalid_pte_U_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_misaligned_S_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_misaligned_U_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_mprv_S_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_mprv_U_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_mprv_U_set_sum_set_S_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_mprv_U_set_sum_unset_S_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_mprv_bare_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_mstatus_sbe_set_S_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_mstatus_sbe_set_sum_set_S_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_mxr_S_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_mxr_U_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_nleaf_pte_level0_S_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_nleaf_pte_level0_U_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_reserved_rsw_pte_S_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_reserved_rsw_pte_U_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_reserved_rwx_pte_S_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_reserved_rwx_pte_U_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_sum_set_S_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_sum_set_U_Bit_unset_S_mode.SPassed
riscv-arch-test/riscv-test-suite/rv32i_m/vm_sv32/src/vm_sum_unset_S_mode.SPassed

Building

Dev containers

  • Attach to the dev container.
    • Option 1: Open this repository in VSCode with the Dev Containers extension.
    • Option 2:
      • Install the Dev Container CLI.
      • Start the container if not running: devcontainer up --workspace-folder .
      • Get a shell in the container: devcontainer exec --workspace-folder . bash
  • Activate the Python environment: source .venv/bin/activate
  • Build everything: make

Assembly

Assumes Ubuntu WSL on Windows.

  • Install uv, gcc-riscv64-unknown-elf, and binutils-riscv64-unknown-elf.
  • Set up the Python environment:
    • uv venv .venv-wsl
    • source .venv-wsl/bin/activate
    • uv sync --active
  • Build all source files in asm/: make asm

Rust

Assumes Powershell on Windows.

  • Install uv, Rust, and cargo-binutils.
  • Set up the Python environment:
    • uv sync
    • .venv\Scripts\activate.ps1
  • Build all Rust projects in rust/: make rust

Attribution

About

RISC-V processor in Mindustry logic.

Resources

Stars

11 stars

Watchers

1 watching

Forks

Packages

Used by

Contributors

Languages