From 96efab3e5259d7def32923fabd74e51dce92efdf Mon Sep 17 00:00:00 2001 From: sql-hkr Date: Sun, 26 Oct 2025 22:48:49 +0900 Subject: [PATCH] Add CLI Visualizer documentation and usage examples (#17) Extend the `README` and `docs/index.rst` to document the new CLI Visualizer, including usage instructions, keyboard controls, and example commands. --- README.md | 73 +++++++++++++++++++++++++------------------------- docs/index.rst | 63 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 684707a..c946969 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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() @@ -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] @@ -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. diff --git a/docs/index.rst b/docs/index.rst index 3bdd612..f845be7 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -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 ------------ @@ -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 --------