sql-hkr/tiny8: A tiny CPU simulator written in Python

πŸ”₯ Check out this insightful post from Hacker News πŸ“–

πŸ“‚ Category:

πŸ“Œ Key idea:

PyPI version
License
Python versions
CI

bubblesort

Tiny8 is a lightweight toolkit that allows you to explore how computers work at their core through small-scale memory models, handcrafted assembly, and lightweight in-memory data structures.
Designed for rapid experimentation, Tiny8 embraces minimalism with zero unnecessary dependencies, a clean design, and intuitive visualization tools that make learning, debugging, and tinkering enjoyable.

Why Tiny8?

  • Lightweight: tiny install footprint and no heavy runtime dependencies.
  • Educational: clear primitives and examples that demonstrate CPU concepts, memory layout, and algorithms.
  • Fast feedback loop: assemble, run, and visualize within seconds to iterate on ideas.
  • Extensible: meant for experiments, teaching, demos, and small tools that benefit from a predictable, tiny VM.

Who should use it?

  • Students learning low-level programming, assembly, or computer architecture who want hands-on examples.
  • Educators building demos and interactive lessons that visualize how registers and memory change.
  • Hobbyists and hackers experimenting with toy CPUs, compact data layouts, or custom instruction ideas.
  • Developers who want a tiny, readable simulator to prototype algorithms that manipulate memory directly.

Get started

  • Follow the Installation section below to install from PyPI or set up a development environment.
  • See the Examples section (like the bubble sort demo) to run real programs and watch the visualizer in action.
  • Dive into the API Reference for details on the CPU, assembler, and visualization helpers.

Tiny8 supports Python 3.11 and newer. It has no heavy external dependencies and is suitable for inclusion in virtual environments. Follow the steps below to prepare your environment and install from source or PyPI.

  • Python 3.11+
  • Git (for installing from the repository)
  • Recommended: create and use a virtual environment

From source (development)

git clone https://github.com/sql-hkr/tiny8.git
cd tiny8
uv venv
source .venv/bin/activate
uv sync

Tip

uv is an extremely fast Python package and project manager, written in Rust. To install it, run:

# On macOS and Linux.
curl -LsSf https://astral.sh/uv/install.sh | sh

# On Windows.
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

This flow sets up a development virtual environment, installs development requirements, and prepares the project for local editing and testing.

This example demonstrates a simple bubble sort algorithm implemented in assembly language for the Tiny8 CPU. The program first fills a section of RAM with pseudo-random bytes, then sorts those bytes using the bubble sort algorithm. Finally, a Python script runs the assembly program and visualizes the sorting process.

bubblesort.asm:

; Bubble sort using RAM (addresses 100..131) - 32 elements
; Purpose: fill RAM[100..131] with pseudo-random bytes and sort them
; Registers (use R16..R31 for LDI immediates):
;   R16 - base address (start = 100)
;   R17 - index / loop counter for initialization
;   R18 - PRNG state (seed)
;   R19..R24 - temporary registers used in loops and swaps
;   R25 - PRNG multiplier (kept aside to avoid clobber in MUL)
;
; The code below is split into two phases:
; 1) init_loop: generate and store 32 pseudo-random bytes at RAM[100..131]
; 2) outer/inner loops: perform a simple bubble sort over those 32 bytes

    ; initialize pointers and PRNG
    ldi r16, 100    ; base address
    ldi r17, 0      ; index = 0
    ldi r18, 123    ; PRNG seed
    ldi r25, 75     ; PRNG multiplier (kept in r25 so mul doesn't clobber it)

init_loop:
    ; PRNG step: r2 := lowbyte(r2 * 75), then tweak
    mul r18, r25     ; r18 = low byte of (r18 * 75)
    inc r18           ; small increment to avoid repeating patterns
    ; store generated byte into memory at base + index
    st r16, r18       ; RAM[base] = r18
    inc r16           ; advance base pointer
    inc r17           ; increment index
    ldi r23, 32
    cp r17, r23
    brne init_loop

; Bubble sort for 32 elements (perform passes until i == 31)
    ldi r18, 0      ; i = 0 (outer loop counter)
outer_loop:
    ldi r19, 0      ; j = 0 (inner loop counter)
inner_loop:
    ; compute address of element A = base + j
    ldi r20, 100
    add r20, r19
    ld r21, r20      ; r21 = A
    ; compute address of element B = base + j + 1
    ldi r22, 100
    add r22, r19
    ldi r23, 1
    add r22, r23
    ld r24, r22      ; r24 = B
    ; compare A and B (we'll swap if A < B)
    cp r21, r24      ; sets carry if r21 < r24
    brcs no_swap
    ; swap A and B: store B into A's address, A into B's address
    st r20, r24
    st r22, r21
no_swap:
    inc r19
    ldi r23, 31
    cp r19, r23
    breq end_inner
    jmp inner_loop
end_inner:
    inc r18
    ldi r23, 31
    cp r18, r23
    breq done
    jmp outer_loop

done:
    jmp done

Python Code:

from tiny8 import CPU, Visualizer, assemble_file

prog, labels = assemble_file("examples/bubblesort.asm")
cpu = CPU()
cpu.load_program(prog, labels)
cpu.run(max_cycles=15000)

print([cpu.read_ram(i) for i in range(100, 132)])

viz = Visualizer(cpu)
base = 100
viz.animate_combined(
    interval=1,
    mem_addr_start=base,
    mem_addr_end=base + 31,
    plot_every=100,
    # filename="bubblesort.gif",
    # fps=60,
)

Example Output:

[247, 243, 239, 238, 227, 211, 210, 195, 190, 187, 186, 171, 167, 159, 155, 150, 142, 139, 135, 130, 127, 106, 102, 94, 54, 50, 34, 26, 23, 15, 10, 6]

Below is a concise, categorized summary of the Tiny8 instruction set (mnemonics are case-insensitive). This is a quick reference β€” for implementation details see src/tiny8/cpu.py.

  • Data transfer

    • LDI Rd, K β€” load immediate into register
    • MOV Rd, Rr β€” copy register
    • LD Rd, Rr_addr β€” load from RAM at address in register
    • ST Rr_addr, Rr β€” store register into RAM at address in register
    • IN Rd, port β€” read byte from RAM/IO into register
    • OUT port, Rr β€” write register to RAM/IO
    • PUSH Rr / POP Rd β€” stack push/pop
  • Arithmetic

    • ADD Rd, Rr β€” add registers
    • ADC Rd, Rr β€” add with carry
    • SUB Rd, Rr / SUBI Rd, K β€” subtraction
    • SBC Rd, Rr / SBCI Rd, K β€” subtract with carry/borrow
    • INC Rd / DEC Rd β€” increment / decrement
    • MUL Rd, Rr β€” 8×8 -> 16 multiply (low/high in Rd/Rd+1)
    • DIV Rd, Rr β€” unsigned divide (quotient->Rd, remainder->Rd+1)
    • NEG Rd β€” two’s complement negate
    • CLR Rd / SER Rd β€” clear or set register to all ones
  • Logical and bit ops

    • AND Rd, Rr / ANDI Rd, K β€” bitwise AND
    • OR Rd, Rr / ORI Rd, K β€” bitwise OR
    • EOR Rd, Rr / EORI Rd, K β€” exclusive OR
    • COM Rd β€” one’s complement
    • SWAP Rd β€” swap nibbles
    • TST Rd β€” test for zero or minus
    • SBI/CBI / SBIS/SBIC / SBRS/SBRC β€” set/clear/test single bits and conditional skips
  • Shifts & rotates

    • LSL Rd / LSR Rd β€” logical shift left/right
    • ROL Rd / ROR Rd β€” rotate through carry
  • Word (16-bit) ops

    • SBIW / ADIW β€” simplified word add/subtract helpers for register pairs
  • Control flow

    • JMP label / RJMP offset β€” unconditional jump
    • CALL label / RCALL offset β€” call subroutine (push return address)
    • RET / RETI β€” return from subroutine / return from interrupt (sets I)
    • BRNE / BREQ / BRCS / BRCC β€” conditional branches based on flags
    • CP Rd, Rr / CPI Rd, K β€” compare (sets flags)
    • CPSE Rd, Rr β€” compare and skip if equal

Use the assembler in src/tiny8/assembler.py (or parse_asm) to write programs β€” register operands are specified as R0..R31 and immediates accept decimal, $hex, 0x, or 0b binary notation.

The API section documents the public modules, classes, functions, and configuration options. See:

Tiny8 is licensed under the MIT License. See LICENSE for details.

Contributions, bug reports, and pull requests are welcome; please follow the repository’s CONTRIBUTING guidelines.

πŸ”₯ What do you think?

#️⃣ #sqlhkrtiny8 #tiny #CPU #simulator #written #Python

πŸ•’ Posted on 1761315885

By

Leave a Reply

Your email address will not be published. Required fields are marked *