Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

README.md

Tomato software

This directory contains Tomato's two-pass assembler, assembly test programs, and TOMATO OS v3.0. Machine instructions come from docs/isa/tomato.v1.csv; assembler-only vocabulary comes from docs/isa/tomato.v1.pseudo.csv.

Project map: root README · ISA · Tomato OS · FPGA core

Tomato OS main menu on HDMI Tetris on Tomato OS

Tomato OS · menu and Tetris · software sheet

Path What
assembler.py Two-pass assembler; the ISA CSVs are its only opcode source
os/ Tomato OS v3.0, its 14 entries, Envelop client, and bounded executor
asm/ Small programs, each with a value a testbench asserts on

Table of Contents


Assemble

python3 software/assembler.py software/asm/counter.s -o hardware/fpga/core/tb/mem/counter.mem --list

From hardware/fpga/core: make asm builds every image, make burn packs them into the FPGA burn headers, make os runs the OS in simulation.


Two authorities

The assembler holds no opcode table of its own. It reads both CSVs at startup, so growing the machine's vocabulary is a data change, not a code change.

File Holds
tomato.v1.csv The 512-row control ROM: 91 instructions plus NOP, 92 burned rows
tomato.v1.pseudo.csv Pseudo-instructions that expand into already-burned instructions

Check the second one against the first at any time:

python3 software/assembler.py --selftest

That assembles every pseudo twice — once as the pseudo, once as the instructions it claims to expand into — and fails if the two word images differ. make -C hardware/fpga/core test runs it as asm-check.


Syntax

Form Example
RRR ADD r4, r1, r2
MOV MOV r1, r2 (rd ← rB)
unary ZERO r5
ADDI/LW ADDI r1, r0, 10 / LW r6, r5, 0
SW SW r1, r5, 0 (data, base, imm8)
branch BNE loop / BEQ done (PC-relative)
jump JMP loop (absolute word address)
system NOP / HALT / RET

Comments: ; or #. Labels: name:.

Vocabulary

The CPU has only BEQ / BNE / BLT / BGE, and the compare that feeds them is a separate instruction, so plain intent used to read as two unrelated lines. These say it in one:

Write Get
CALL puts JAL r16, puts — the link register
BEQZ r22, done CMP r22, r0 + BEQ done
BNEZ, BLTZ, BGEZ the same shape, other conditions
BLE done BEQ done + BLT done
BGT done skip the BGE when the compare was equal
LI r5, 100 ADDI r5, r0, 100 — value, not address
TST r6 CMP r6, r0
INC / DEC / NEG / CLR in-place arithmetic, spelled out
BZ / BNZ / BMI / BPL the conditionals, read after a TST
BRA / ASL JMP / LSL under their usual names

LA rd, label loads an address, and is the one thing limited to the low 4 KB — it assembles to ADDI rd, r0, addr, so the label must fit an unsigned 12-bit immediate. Pointer tables have no such limit: a .word label holds the full 32-bit address, which is how Tomato OS keeps its prose above 0x1000.


Directives

Directive Effect
.org addr Set the next word address (sparse image; holes are 0)
.word n, n Emit raw 32-bit words — glyphs, tables, pointers
.space n Reserve n zeroed words for something written at runtime
.ascii "text" One word per character (memory is word-addressed)
.asciz "text" The same, NUL-terminated

Tomato OS

The OS sources identify TOMATO OS v3.0 and declare 14 menu entries. Desktop v1.2 is the workspace UI revision, not the OS version. The image links tomato_os.s, the Tomato-side Envelop client and setup records, and the bounded remote executor.

See os/README.md for the menu, source boundaries, and focused checks. Envelop's user clients, backend, and nearby bridge live in the separate Envelop project; their source or deployment status cannot be inferred from the machine-side assembly here.


Samples

Program Check
asm/counter.s r1 = disp = 10
asm/fib.s fib(8) → r1 = r6 = 21
asm/collatz.s n=27 → 111 steps in r1/disp
asm/call.s JAL/RET → r1=99 r2=42
asm/bytes.s SB/LB signed byte
asm/ecall.s trap + RET → r1=42
asm/softops.s ROR/LBU → r1=r6=129
asm/io.s IN/OUT keyboard echo
asm/kb_mmio.s LW MMIO kb data/status