Skip to content

Commit ae1ada4

Browse files
committed
Extended runtime/vector coverage
1 parent 92929ff commit ae1ada4

18 files changed

Lines changed: 1598 additions & 96 deletions

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ jobs:
2424
steps:
2525
- uses: actions/checkout@v4
2626

27+
- name: Check helper docs
28+
run: make check-helper-docs
29+
2730
- name: Install GCC ${{ matrix.gcc-version }}
2831
if: matrix.os == 'ubuntu-latest'
2932
run: |

MASTER_ISA.md

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# Master Ternary ISA Roadmap
2+
3+
This document sketches the instructions a balanced-ternary ISA should expose once we
4+
grow beyond the core helpers already listed in `SPECIFICATION.md`. The goal is not to
5+
duplicate binary primitives (add/mul/cmp are already covered there) but to capture the
6+
**ternary-only logic** that emerges from Setun-style three-state arithmetic, Kleene logic,
7+
and recent ternary/AI research. Each entry summarizes the semantics, why it is harder (or
8+
impossible) to reproduce in binary, and what the plugin/runtime should provide.
9+
10+
## Existing foundation
11+
12+
The current GCC plugin and runtime already describe a complete helper ABI for the
13+
standard ternary integer instructions (addition, compare, select, shifts, etc.).
14+
Refer to `SPECIFICATION.md` for those helpers. This roadmap is intentionally additive and
15+
focuses on instructions whose semantics *literally require* a three-valued perspective.
16+
17+
## Unique Ternary Operations
18+
19+
### 1. Three-valued logic primitives
20+
21+
- **TMIN / TMAX** – Combines two ternary operands per trit using Kleene-style min/max (−1
22+
< 0 < +1). These instructions directly propagate unknowns (`0`). Binary min/max
23+
instructions cannot distinguish three states without extra flags and masking, which
24+
multiplies latency. Useful as fast logical AND/OR substitutes for ternary boolean vectors.
25+
- **TNOT** – Tritwise inversion that flips the sign of non-zero trits while keeping zero
26+
intact. Balanced ternary can negate entire words without a carry or add-one step, unlike
27+
two's-complement inversion. The helper should map to `__builtin_ternary_not` variants.
28+
- **TIMPL** – Kleene implication (e.g., −1 implies anything = +1, 0 implies 0/ +1, etc.).
29+
It captures conditional reasoning with explicit “unknown” propagation, a common pattern in
30+
ternary neural nets and satisfiability solvers. Binary hardware would need a multi-instruction
31+
sequence to emulate the same partial truth table.
32+
| antecedent ↓ \ consequent → | -1 (false) | 0 (unknown) | +1 (true) |
33+
|----------------------------|-------------|--------------|------------|
34+
| -1 (false) | +1 | +1 | +1 |
35+
| 0 (unknown) | -1 | 0 | +1 |
36+
| +1 (true) | -1 | 0 | +1 |
37+
- **TMAJ** – Element-wise majority vote on three inputs (extendable to vectors). Returns
38+
the trit that appears at least twice; when `(−1, 0, +1)` all appear, it resolves to `0`
39+
(unknown). This matches REBEL-6’s majority voter and is useful for error-correcting memory
40+
and ensemble ternary inference.
41+
| inputs (a,b,c) | result |
42+
|---------------------------------|--------|
43+
| two or more `+1` values | +1 |
44+
| two or more `0` values | 0 |
45+
| two or more `−1` values | −1 |
46+
| `(-1, 0, +1)` (all distinct) | 0 |
47+
48+
### 2. Control flow that uses three-way decisions
49+
50+
- **TBRANCH** – Single instruction with three potential targets keyed by condition trit
51+
values (−1, 0, +1). Instead of chaining binary comparisons, a ternary CPU can implement
52+
decision trees or state machines with exactly one branch per comparison. This aligns with
53+
Setun’s three-way transition commands.
54+
- **TSIGNJMP** – Jump based on the sign trit of a register (positive/zero/negative), letting
55+
late-stage code skip redundant compares or flags. A binary design must inspect zero and sign
56+
flags separately, but balanced ternary exposes the sign trit directly.
57+
58+
### 3. Symmetric arithmetic helpers for AI / DSP workloads
59+
60+
- **TINV** – Multi-trit inversion operation that flips +1↔−1 while leaving zeros. In ternary
61+
inference kernels (e.g., ternary neural nets) this is often the only change between weights.
62+
It maps naturally to `__builtin_ternary_not` but it can be kept distinct for vector acceleration.
63+
- **TMULADD** – Combined multiply-and-accumulate with symmetric rounding (A×B + C). Setun
64+
used this for polynomial evaluation, and ternary addition/multiplication avoid bias that
65+
plagues binary MAC units (no implicit +0.5 shifts). A TMULADD helper can replace the current
66+
multiply + add sequence with one lower-latency call.
67+
- **TROUND** – Truncates the least-significant trits of a value using symmetric rounding (round
68+
toward zero with equal bias). Binary rounding must track sign + carry to avoid bias, but
69+
balanced ternary simply drops trits because truncation equals rounding.
70+
- **TQUANT** – Quantizes binary or floating values into {−1, 0, +1} per trit, targeting low-precision
71+
AI weights. Binary quantization typically lands at {0,1} or 8-bit ints; ternary quantization
72+
captures more information with fewer bits. This helper is critical for runtime math that
73+
prepares data for `TMIN/TMAX`-style activations.
74+
75+
### 4. Memory / conversion utilities beyond standard packing
76+
77+
- **TPACK / TUNPACK** – Encodes/decodes arbitrary ternary strings or vector lanes into the
78+
2-bit representation (00 = −1, 01 = 0, 10 = +1). They hide the packing format so higher-level
79+
code can consume ternary data from external sources without bit fiddling.
80+
- **TBIAS** – Adds/subtracts a fixed bias to reinterpret balanced vs. biased ternary forms
81+
(useful for offsets or unsigned slices). Binary systems can do biasing, but the symmetry in
82+
ternary makes bias transitions cheaper and worth exposing explicitly.
83+
- **TNORMALIZE** – Replays the trit encoding to clamp invalid bit patterns (like `11`). This
84+
keeps memory/IO sane when binary corruption bypasses helper validation.
85+
86+
## Implementation guidance
87+
88+
- Expose the above helpers through the existing plugin options (`-fplugin-arg-ternary_plugin-logic`)
89+
and helper headers (`include/ternary_helpers.h`). Prefix names with the current `<prefix>` so
90+
downstream runtimes can reuse `__ternary_tmin`/`__ternary_tbranch`, etc.
91+
- Provide reference C fallbacks (in `runtime/ternary_runtime.c`) that mirror the ternary truth tables
92+
before introducing hardware acceleration.
93+
- Add unit tests (e.g., `tests/test_logic.c`) that exercise the unknown propagations and three-way
94+
jumps. Use the runtime skeleton to demonstrate symmetric rounding and quantization.
95+
- Document how each helper avoids binary duplication and cite Setun/REBEL-6 inspiration for the
96+
three-valued control-flow primitives.
97+
98+
### Hardware encoding & async control
99+
100+
- Tryte-friendly opcodes: reserve 6 trits per slot (e.g., 2 trits for vector width, 2 trits for the instruction family, 2 trits for immediates/flags). Instructions such as `TBRANCH`, `TMAJ`, and `TMULADD` can live in a single tryte with built-in width tags so the hardware decoder can dispatch without binary prefix tables.
101+
- Async branch support: follow Setun’s clockless transitions by treating `TBRANCH`/`TSIGNJMP` as micro-instructions that grab a condition trit and target triple simultaneously, avoiding the binary flag expansion. Documenting this early helps map the runtime helpers to future hardware that may signal targets through a branch arbiter rather than the normal program counter updates.
102+
- Async control handshake: model hardware such that the condition feed (ternary condition register) produces one of three ready signals, and an arbiter selects the matching target label/offset in the same cycle. `TBRANCH` should therefore expose a triple-target field plus a flag that indicates whether the jump is speculative; software helpers can mirror that by returning the chosen target value so forward progress can be verified even before hardware support arrives.
103+
104+
## Next steps
105+
106+
1. Align this roadmap with `SPECIFICATION.md` by referencing the new helpers in the “Future Extensions”
107+
or “Needs Implementation” lists.
108+
2. Choose a canonical helper prefix (`__ternary` by default) and append the new operations to that ABI.
109+
3. Prototype the quantization/branch helpers in `runtime_skeleton/` so plugin tests can depend on them.
110+
4. Sketch hardware encodings (tryte/6-trit opcodes) once the semantics settle.

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,12 @@ assembly to match your ISA. `TERNARY_COND_T` defines the condition type used by
165165
and is fixed to `ternary_cond_t` (default: `int64_t`). The plugin lowers conditions to
166166
`ternary_cond_t` before helper calls.
167167

168+
See `SPECIFICATION.md` for the current ABI and helper list grouped by category; keep it in sync
169+
with `include/ternary_runtime.h` (and the helper header) so documentation, tests, and the plugin
170+
Lowering stay aligned.
171+
Run `make check-helper-docs` (or `python3 tools/check_helper_docs.py`) whenever the helper ABI list
172+
or headers change to keep the helper documentation in lockstep.
173+
168174
For testing without the plugin, the header provides C implementations of all ternary operations.
169175
Packed ternary types use a 2-bit encoding per trit (00 = -1, 01 = 0, 10 = +1).
170176
Define `TERNARY_USE_BUILTIN_TYPES` before including the header when compiling with
@@ -253,6 +259,8 @@ On macOS, run:
253259
make test CXX=g++-15 CC=gcc-15
254260
```
255261

262+
`make test` now also compiles `tests/test_literals.c` (ensuring literal helpers + promotions compile) and `test_ternary.c` with `-fplugin-arg-ternary_plugin-dump-gimple` so Phase 3 coverage exercises the dump/trace flags.
263+
256264
## Description
257265

258266
This plugin analyzes ternary conditional expressions in the code and can optionally
@@ -292,6 +300,12 @@ The ternary vector operations provide a foundation for SIMD acceleration:
292300
- Potential for higher computational density in AI/ML workloads
293301
- Reduced carry propagation compared to binary arithmetic
294302

303+
For helpers that literally need three-valued semantics (TMIN/TMAX, TIMPL/TLIMP,
304+
TMAJ, TQUANT, and the TNOT/TINV aliases), see `MASTER_ISA.md`. It documents how
305+
these instructions propagate “unknown” trits, when to use TINV as an inference
306+
alias, and the extended control-flow helpers (TBRANCH/TSIGNJMP) you can expose
307+
through `__ternary_*` before hardware encodings are sketched.
308+
295309
### Control Flow Operations (brt/brf) - PLANNED
296310
- `brt Rc, label`: branch if Rc != 0 (ternary true)
297311
- `brf Rc, label`: branch if Rc == 0 (ternary false)

ROADMAP.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,13 @@ Deliverables:
8181

8282
- Document supported platform/compiler versions and current status.
8383
- Add ABI validation checks in CI (symbol presence or hash).
84+
- Ensure the documented helper ABI (`SPECIFICATION.md`/README) stays aligned with the headers
85+
(`include/ternary_runtime.h`, `include/ternary_helpers.h`), ideally via a CI regression.
8486

8587
Deliverables:
8688
- Compatibility matrix in `README.md`.
8789
- ABI validation step in CI.
90+
- Regression/check that the helper ABI list matches the headers/docs.
8891

8992
## Phase 8: Optional Hardware Backend
9093

0 commit comments

Comments
 (0)