Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 37 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ Key points:
- For higher-fidelity animations (GIFs) and interactive matplotlib views, use the `Visualizer` class which requires `matplotlib`.

Interactive controls:
```

```text
Space - toggle play/pause
l or > - next step
h or < - previous step
Expand All @@ -101,7 +102,7 @@ You can invoke the terminal visualizer directly from Python after running the CP

```python
from tiny8 import CPU, assemble_file
from tiny8.cli_visualizer import run_cli
from tiny8 import run_cli

prog, labels = assemble_file("examples/bubblesort.asm")
cpu = CPU()
Expand All @@ -116,10 +117,10 @@ Tiny8 provides a `tiny8` console script (see `pyproject.toml`). You can run the

```bash
# Run the curses-based CLI visualizer for an assembly file
tiny8 examples/bubblesort.asm # --mode cli --mem-start 100 --mem-end 131
uv run tiny8 examples/bubblesort.asm # --mode cli --mem-start 100 --mem-end 131

# Produce an animated GIF using matplotlib (requires matplotlib)
tiny8 examples/bubblesort.asm --mode ani -o bubblesort.gif --mem-start 100 --mem-end 131 --plot-every 100 --fps 60
uv run tiny8 examples/bubblesort.asm --mode ani -o bubblesort.gif --mem-start 100 --mem-end 131 --plot-every 100 --fps 60
```

> [!IMPORTANT]
Expand Down Expand Up @@ -238,48 +239,48 @@ Example Output:
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
- 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 — 8x8 -> 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
- 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 — 8x8 -> 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
- 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
- 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
- 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 / BRGE / BRLT — conditional branches based on flags
- CP Rd, Rr / CPI Rd, K — compare (sets flags)
- CPSE Rd, Rr — compare and skip if equal
- 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 / BRGE / BRLT — 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.

Expand Down
63 changes: 63 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ Designed for rapid experimentation, Tiny8 embraces minimalism with zero unnecess
.. image:: _static/examples/bubblesort.gif
:alt: Bubble sort

⭐️ NEW FEATURE!

.. image:: https://github.com/user-attachments/assets/cd5a0ae0-8aff-41af-81e0-4ff9c426f617
:alt: CLI visualizer
:width: 600px

Installation
------------

Expand Down Expand Up @@ -61,6 +67,63 @@ From PyPI (stable)

uv add tiny8

CLI Visualizer
--------------

Tiny8 includes a lightweight terminal-based visualizer that lets you step through a program's execution trace in your terminal. It shows the status register (SREG), the 32 general-purpose registers, and a compact view of a configurable memory range for each step.

Key points
~~~~~~~~~~

- The CLI visualizer expects the CPU to have a populated ``step_trace`` (run the CPU first with ``cpu.run(...)``).
- Controls are keyboard-driven (play/pause, step forward/back, jump, quit) and work in most POSIX terminals that support curses.
- For higher-fidelity animations (GIFs) and interactive matplotlib views, use the ``Visualizer`` class which requires ``matplotlib``.

Interactive controls
~~~~~~~~~~~~~~~~~~~~

.. code-block:: text

Space - toggle play/pause
l or > - next step
h or < - previous step
w - jump forward 10 steps
b - jump back 10 steps
0 - jump to first step
$ - jump to last step
q or ESC - quit

Programmatic usage
------------------

You can invoke the terminal visualizer directly from Python after running the CPU:

.. code-block:: python

from tiny8 import CPU, assemble_file
from tiny8 import run_cli

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

# Run the curses-based CLI visualizer
run_cli(cpu, mem_addr_start=100, mem_addr_end=131)

Tiny8 provides a ``tiny8`` console script (see ``pyproject.toml``). You can run the CLI or the animation mode directly:

.. code-block:: bash

# Run the curses-based CLI visualizer for an assembly file
uv run tiny8 examples/bubblesort.asm # --mode cli --mem-start 100 --mem-end 131

# Produce an animated GIF using matplotlib (requires matplotlib)
uv run tiny8 examples/bubblesort.asm --mode ani -o bubblesort.gif --mem-start 100 --mem-end 131 --plot-every 100 --fps 60

.. important::

Tiny8 uses Python's built-in curses module (Unix-like systems). On Windows, use an appropriate terminal that supports curses or run via WSL.

Examples
--------
Expand Down