Metadata-Version: 2.4
Name: setnex-sim
Version: 0.3.2
Summary: Setnex ISA balanced-ternary processor simulator
Project-URL: Homepage, https://codeberg.org/setnex-org/setnex-sim
Project-URL: Repository, https://codeberg.org/setnex-org/setnex-sim
Project-URL: Issues, https://codeberg.org/setnex-org/setnex-sim/issues
Author-email: Eric Tellier <eric@setnex.org>
License-Expression: MIT
Keywords: balanced-ternary,ternary
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering :: Mathematics
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: tritlib>=1.2.1
Provides-Extra: dev
Requires-Dist: pytest; extra == 'dev'
Requires-Dist: pytest-cov; extra == 'dev'
Description-Content-Type: text/markdown

# setnex-sim
Python simulator for the [Setnex ISA](https://setnex.org) — an open balanced ternary instruction set architecture.
Implements the full fetch/decode/execute cycle for a 27-trit processor:
27 general-purpose registers, 5 configurable ternary logic modes (LMODE), and fixed-length R/I/J/U/B instructions.
Built on [tritlib](https://codeberg.org/setnex/tritlib).

## Status
v0.3 — fully functional simulator with assembler and CLI toolchain. 46 opcodes implemented, 98% test coverage.

Implemented:
- Decoder (R, I, J, U, B formats)
- ALU (ADD, SUB, MUL, DIV, MOD, NEG, TAND, TOR, TNOT, TIMPL, CONS, ACONS, TSHIFT, TCMP, TGET, TSET, TSIGN, TABS, TMIN, TMAX)
- Configurable ternary logic via LMODE (Kleene, Łukasiewicz, Heyting, RM3, Bochvar)
- Registers (27 GPR + CSR: PC, LMODE, FLAGS, EPC, ECAUSE, EVEC, STATUS, ESAVE)
- Sparse word-addressed memory
- CPU fetch/decode/execute loop with ternary FLAGS (sign, carry)
- Branches and jumps (BEQ, BNE, BLT, BGT, BLE, BGE, BF, BRT3, JMP, JMPA, CALL)
- System instructions (CSRR, CSRW, CSRX, ECALL, IRET, TSEL)
- Text assembler (`setnex-asm`): `.sasm` → `.tern`, label resolution, pseudo-instructions
- Runner (`setnex-run`): execute `.tern` files with register initialisation and ternary exit status

## Install
```bash
pip install setnex-sim
```
Or from source:
```bash
git clone https://codeberg.org/setnex/setnex-sim
cd setnex-sim
pip install -e ".[dev]"
```

## CLI usage

### Assembler
```bash
setnex-asm program.sasm -o program.tern
```

### Runner
```bash
setnex-run program.tern --set a0=5 --print a0
```

Options:
- `--set REG=VAL` — initialise a register before execution (repeatable)
- `--print REG` — print a register after HALT (default: `a0`)
- `--verbose` — print all registers and cycle count

Exit status follows the ternary convention via `a1` at HALT:
- `a1 < 0` (N) → shell exit 1 (error)
- `a1 = 0` (Z) → shell exit 0 (indeterminate)
- `a1 > 0` (P) → shell exit 0 (success)

### Example programs

Three example programs are provided in `fixtures/`:

**`sum.sasm`** : sum of integers 1..N (validates the full pipeline: LI, CMP, BF, ADD, ADDI, JMP):
```bash
setnex-asm fixtures/sum.sasm -o sum.tern
setnex-run sum.tern --set a0=5 --print a0
# a0 = 15
```

**`count_p.sasm`** : count P trits in `a0` using TGET and BRT3:
```bash
setnex-asm fixtures/count_p.sasm -o count_p.tern
setnex-run count_p.tern --set a0=13 --print a0
# a0 = 3  (13 = +++ in balanced ternary — three P trits)
```

**`modsum.sasm`** : sum with sign driven by symmetric Euclidean `i mod 3 ∈ {−1, 0, +1}`,
dispatched natively by BRT3 — a computation that has no natural binary equivalent:
```bash
setnex-asm fixtures/modsum.sasm -o modsum.tern
setnex-run modsum.tern --set a0=6 --print a0
# a0 = -2
```

**`check_sign.sasm`** : looks for a zero between a0 and a1, returns a1 = P if found, Z if absent, and  a0 the results if a1 == P
```bash
setnex-asm fixtures/check_sign.sasm -o check_sign.tern
setnex-run check_sign.tern --set a0=3 a1=7 --print a0 --print a1
# a0 = 3
# a1 = 0
setnex-run check_sign.tern --set a0=-3 a1=7 --print a0 --print a1
# a0 = 0
# a1 = 1
```

## Python API
```python
from setnex_sim.cpu import CPU
from setnex_sim.assembler import encode_R, encode_I

cpu = CPU()
program = [
    encode_I(-24, rd=1, rs1=0, imm=5),   # LI r1, 5
    encode_I(-24, rd=2, rs1=0, imm=3),   # LI r2, 3
    encode_R(-40, rd=3, rs1=1, rs2=2),   # ADD r3, r1, r2
    encode_R(0,   rd=0, rs1=0, rs2=0),   # HALT
]
cpu.load(program)
cpu.run()
print(int(cpu.regs[3]))  # 8
```

## Setnex ISA
The full ISA specification is available at [setnex.org](https://setnex.org) and on
[Codeberg](https://codeberg.org/setnex/setnex-isa) — Apache 2.0, patent-free.

## Licence
MIT — Copyright 2026 Eric Tellier
