Loading repository data…
Loading repository data…
sql-hkr / repository
A tiny CPU simulator written in Python
A transparent discovery signal based on current public GitHub metadata.
This score does not audit code, security, maintainers, documentation quality, or suitability. Verify the repository and its current documentation before adoption.
An educational 8-bit CPU simulator with interactive visualization
Tiny8 is a lightweight and educational toolkit for exploring the fundamentals of computer architecture through hands-on assembly programming and real-time visualization. Designed for learning and experimentation, it features an AVR-inspired 8-bit CPU with 32 registers, a rich instruction set, and powerful debugging tools — all with zero heavy dependencies.
pip install tiny8
Create fibonacci.asm:
; Fibonacci Sequence Calculator
; Calculates the 10th Fibonacci number (F(10) = 55)
; F(0) = 0, F(1) = 1, F(n) = F(n-1) + F(n-2)
;
; Results stored in registers:
; R16 and R17 hold the two most recent Fibonacci numbers
ldi r16, 0 ; F(0) = 0
ldi r17, 1 ; F(1) = 1
ldi r18, 9 ; Counter: 9 more iterations to reach F(10)
loop:
add r16, r17 ; F(n) = F(n-1) + F(n-2)
mov r19, r16 ; Save result temporarily
mov r16, r17 ; Shift: previous = current
mov r17, r19 ; Shift: current = new result
dec r18 ; Decrement counter
brne loop ; Continue if counter != 0
done:
jmp done ; Infinite loop at end
Run it:
tiny8 fibonacci.asm # Interactive debugger
tiny8 fibonacci.asm -m ani -o fibonacci.gif # Generate animation
from tiny8 import CPU, assemble_file
asm = assemble_file("fibonacci.asm")
cpu = CPU()
cpu.load_program(asm)
cpu.run(max_steps=1000)
print(f"Result: R17 = {cpu.read_reg(17)}") # Final Fibonacci number
For Students — Write assembly, see immediate results with visual feedback. Understand how each instruction affects CPU state without abstractions.
For Educators — Interactive demonstrations, easy assignment creation, and generate animations for lectures.
For Hobbyists — Rapid algorithm prototyping at the hardware level with minimal overhead and an extensible, readable codebase.
The terminal-based debugger provides powerful navigation and inspection capabilities.
l / h or → / ← — Step forward/backwardw / b — Jump ±10 steps0 / $ — Jump to first/last stepSpace — Play/pause auto-execution[ / ] — Decrease/increase playback speedr — Toggle register display (all/changed only)M — Toggle memory display (all/non-zero only)= — Show detailed step informationj / k — Scroll memory view up/down:):123 — Jump to step 123:+50 / :-20 — Relative jumps:/ldi — Search forward for instruction "ldi":?add — Search backward for "add":@0x100 — Jump to PC address 0x100:r10 — Find next change to register R10:r10=42 — Find where R10 equals 42:m100 — Find next change to memory[100]:fZ — Find next change to flag Zma — Set mark 'a' at current step'a — Jump to mark 'a'/ — Show help screenq or ESC — QuitThe examples/ directory contains programs demonstrating key concepts:
| Example | Description |
|---|---|
fibonacci.asm | Fibonacci sequence using registers |
bubblesort.asm | Sorting algorithm with memory visualization |
factorial.asm | Recursive factorial calculation |
find_max.asm | Finding maximum value in array |
is_prime.asm | Prime number checking algorithm |
gcd.asm | Greatest common divisor (Euclidean algorithm) |
Sort 32 bytes in memory:
tiny8 examples/bubblesort.asm -ms 0x60 -me 0x80 # Watch live
tiny8 examples/bubblesort.asm -m ani -o sort.gif -ms 0x60 -me 0x80 # Create GIF
from tiny8 import CPU, assemble_file
cpu = CPU()
cpu.load_program(assemble_file("examples/bubblesort.asm"))
cpu.run()
print("Sorted:", [cpu.read_ram(i) for i in range(0x60, 0x80)])
tiny8 FILE [OPTIONS]
| Option | Description |
|---|---|
-m, --mode {cli,ani} | Visualization mode: cli for interactive debugger (default), ani for animation |
-v, --version | Show version and exit |
--max-steps N | Maximum execution steps (default: 15000) |
| Option | Description |
|---|---|
-ms, --mem-start ADDR | Starting memory address (decimal or 0xHEX, default: 0x00) |
-me, --mem-end ADDR | Ending memory address (decimal or 0xHEX, default: 0xFF) |
| Option | Description |
|---|---|
-d, --delay SEC | Initial playback delay in seconds (default: 0.15) |
| Option | Description |
|---|---|
-o, --output FILE | Output filename (.gif, .mp4, .png) |
-f, --fps FPS | Frames per second (default: 60) |
-i, --interval MS | Update interval in milliseconds (default: 1) |
-pe, --plot-every N | Update plot every N steps (default: 100, higher = faster) |
Windows: CLI debugger requires WSL or
windows-curses. Animation works natively.
Tiny8 implements an AVR-inspired instruction set with 62 instructions organized into logical categories. All mnemonics are case-insensitive. Registers are specified as R0-R31, immediates support decimal, hex ($FF or 0xFF), and binary (0b11111111) notation.
| Instruction | Description | Example |
|---|---|---|
LDI Rd, K | Load 8-bit immediate into register | ldi r16, 42 |
MOV Rd, Rr | Copy register to register | mov r17, r16 |
LD Rd, Rr | Load from RAM at address in Rr | ld r18, r16 |
ST Rr, Rs | Store Rs to RAM at address in Rr | st r16, r18 |
IN Rd, port | Read from I/O port into register | in r16, 0x3F |
OUT port, Rr | Write register to I/O port | out 0x3F, r16 |
PUSH Rr | Push register onto stack | push r16 |
POP Rd | Pop from stack into register | pop r16 |
| Instruction | Description | Example |
|---|---|---|
ADD Rd, Rr | Add registers | add r16, r17 |
ADC Rd, Rr | Add with carry | adc r16, r17 |
SUB Rd, Rr | Subtract registers | sub r16, r17 |
SUBI Rd, K | Subtract immediate | subi r16, 10 |
SBC Rd, Rr | Subtract with carry | sbc r16, r17 |
SBCI Rd, K | Subtract immediate with carry | sbci r16, 5 |
INC Rd | Increment register | inc r16 |
DEC Rd | Decrement register | dec r16 |
MUL Rd, Rr | Multiply (result in Rd:Rd+1) | mul r16, r17 |
DIV Rd, Rr | Divide (quotient→Rd, remainder→Rd+1) | div r16, r17 |
NEG Rd | Two's complement negation | neg r16 |
ADIW Rd, K | Add immediate to word (16-bit) | adiw r24, 1 |
SBIW Rd, K | Subtract immediate from word | sbiw r24, 1 |
| Instruction | Description | Example |
|---|---|---|
AND Rd, Rr | Logical AND | and r16, r17 |
ANDI Rd, K | AND with immediate | andi r16, 0x0F |
OR Rd, Rr | Logical OR | or r16, r17 |
ORI Rd, K | OR with immediate | ori r16, 0x80 |
EOR Rd, Rr | Exclusive OR | eor r16, r17 |
EORI Rd, K | XOR with immediate | eori r16, 0xFF |
COM Rd | One's complement | com r16 |
CLR Rd | Clear register (XOR with self) | clr r16 |
SER Rd | Set register to 0xFF | ser r16 |
TST Rd | Test for zero or negative | tst r16 |
SWAP Rd | Swap nibbles (high/low 4 bits) | swap r16 |
SBI port, bit | Set bit in I/O register | sbi 0x18, 3 |
CBI port, bit | Clear bit in I/O register | cbi 0x18, 3 |
| Instruction | Description | Example |
|---|---|---|
LSL Rd | Logical shift left | lsl r16 |
LSR Rd | Logical shift right | lsr r16 |
ROL Rd | Rotate left through carry | rol r16 |
ROR Rd | Rotate right through carry | ror r16 |
| Instruction | Description | Example |
|---|---|---|
JMP label | Unconditional jump | jmp loop |
RJMP offset | Relative jump | rjmp -5 |
CALL label | Call subroutine | call function |
RCALL offset | Relative call | rcall -10 |
RET | Return from subroutine | ret |
RETI | Return from interrupt | reti |
BRNE label | Branch if not equal (Z=0) | brne loop |
BREQ label | Branch if equal (Z=1) | breq done |
BRCS label | Branch if carry set (C=1) | brcs overflow |
BRCC label | Branch if carry clear (C=0) | brcc no_carry |
BRGE label | Branch if greater/equal | brge positive |
BRLT label | Branch if less than | brlt negative |
BRMI label | Branch if minus (N=1) | brmi negative |
BRPL label | Branch if plus (N=0) | brpl positive |
| Instruction | Description | Example |
|---|---|---|
CP Rd, Rr | Compare registers (Rd - Rr) | cp r16, r17 |
CPI Rd, K | Compare with immediate | cpi r16, 42 |
CPSE Rd, Rr | Compare, skip if equal | cpse r16, r17 |
| Instruction |