CharlesCNorton commited on
Commit ·
b3106d8
1
Parent(s): 28868a6
Move source library into src/; repoint module, tool, and README paths
Browse files- README.md +39 -38
- build.py → src/build.py +3 -3
- constructor8.py → src/constructor8.py +1 -1
- eval.py → src/eval.py +2 -2
- eval_all.py → src/eval_all.py +0 -0
- machines.py → src/machines.py +2 -2
- matrix8.py → src/matrix8.py +1 -1
- quantize.py → src/quantize.py +0 -0
- tools/build_all.py +3 -3
- tools/play.py +1 -1
- tools/prune_weights.py +1 -1
- tools/test_cpu.py +1 -1
README.md
CHANGED
|
@@ -78,14 +78,14 @@ for a, c in [(0, 0), (0, 1), (1, 0), (1, 1)]:
|
|
| 78 |
Run the full circuit verification suite against any variant:
|
| 79 |
|
| 80 |
```bash
|
| 81 |
-
python eval_all.py variants/ # 18 fitness variants (machines skipped)
|
| 82 |
-
python eval_all.py neural_computer.safetensors # the canonical file
|
| 83 |
-
python eval_all.py --cpu-program variants/ # also run an assembled
|
| 84 |
# program through the
|
| 85 |
# threshold-gated CPU
|
| 86 |
```
|
| 87 |
|
| 88 |
-
`eval_all.py` reads each variant's manifest, runs a gate-level fitness suite (13,900–15,900 tests per variant covering Boolean, arithmetic, ALU, control, modular, error-detection, threshold, and float circuits, including end-to-end evaluation of the composed float pipelines from the shipped wiring metadata — see the Verification table), and optionally executes a small assembled program through a manifest-sized threshold CPU plus a chained 16- or 32-bit ALU sequence on wider variants.
|
| 89 |
|
| 90 |
For an interactive walkthrough that exercises Boolean gates, the 8-bit ALU, mod-5 divisibility, and a CPU loop end-to-end:
|
| 91 |
|
|
@@ -294,10 +294,10 @@ The build tool emits one of 51 functionally distinct configurations: three data-
|
|
| 294 |
Auto-generated filename: `neural_{alu|computer}{BITS}[_{MEMORY}].safetensors`. Custom address widths via `-a N` produce `_addrN`.
|
| 295 |
|
| 296 |
```bash
|
| 297 |
-
python build.py --bits 32 --apply all # neural_computer32.safetensors
|
| 298 |
-
python build.py --bits 8 -m none --apply all # neural_alu8.safetensors
|
| 299 |
-
python build.py --bits 16 -m small --apply all # neural_computer16_small.safetensors
|
| 300 |
-
python build.py --bits 32 -a 6 --apply all # neural_computer32_addr6.safetensors
|
| 301 |
```
|
| 302 |
|
| 303 |
To regenerate every named variant in one pass:
|
|
@@ -306,21 +306,21 @@ To regenerate every named variant in one pass:
|
|
| 306 |
python tools/build_all.py
|
| 307 |
```
|
| 308 |
|
| 309 |
-
This populates `variants/` with all 18 builds, quantizes each one to the smallest signed integer dtype that exactly represents its weights (~4× reduction in tensor data, with file size dominated by the safetensors header on the smaller profiles), verifies the strictly ternary weight invariant (`--ternary --strict`, so a build with any non-ternary weight fails loudly), stamps the `weight_quantization` metadata field, and runs `eval.py` on each as a sanity check.
|
| 310 |
|
| 311 |
The quantizer is also available standalone:
|
| 312 |
|
| 313 |
```bash
|
| 314 |
-
python quantize.py path/to/file.safetensors # in-place
|
| 315 |
-
python quantize.py variants/ # whole directory
|
| 316 |
-
python quantize.py model.safetensors -o quantized.safetensors
|
| 317 |
-
python quantize.py file.safetensors --ternary # push toward {-1, 0, 1} weights
|
| 318 |
-
python quantize.py file.safetensors --ternary --strict # error if any weight is non-ternary
|
| 319 |
```
|
| 320 |
|
| 321 |
Every weight and bias tensor in the canonical model fits in `int8`. The eval pipeline promotes weights to `float32` on load, so integer storage is exact and transparent.
|
| 322 |
|
| 323 |
-
**Ternary mode.** `build.py` emits only ternary weights: identity buffers are `weight=1, bias=-1` (`H(x - 1)`), and the comparators, modular detectors, and division stages that previously required positional weights up to ±2³¹ are bit-cascaded multi-layer equivalents. With `--ternary`, the quantizer verifies this and repairs legacy files: it rewrites historical single-input `weight=±2` buffers as `weight=±1` with the bias adjusted to preserve the heaviside output for binary inputs (`H(2x - 1) ≡ H(x - 1)`), and rebuilds pre-bit-cascade modular detectors (moduli already in bit-cascade form are left untouched, routing metadata included). `--strict` fails if any weight tensor remains non-ternary. Every shipped file carries the metadata field `weight_quantization: ternary`; a repaired file with remaining violations would be stamped `ternary_partial`.
|
| 324 |
|
| 325 |
---
|
| 326 |
|
|
@@ -347,7 +347,7 @@ Every weight and bias tensor in the canonical model fits in `int8`. The eval pip
|
|
| 347 |
|
| 348 |
The 8-bit arithmetic and ALU tests use strategic sampling rather than the full 65,536-case sweep because exhaustive coverage at 8-bit is feasible but not necessary given that the circuits are constructed gate-by-gate. The 16-bit and 32-bit arithmetic tests sample edge cases only; full exhaustive coverage at those widths is infeasible without specialized hardware.
|
| 349 |
|
| 350 |
-
`eval_all.py` runs the unified suite. Exit code is the number of failing variants (0 means all pass). **Testing is evaluation, not rebuilding**: `python eval_all.py variants/` scores all 18 fitness variants against the shipped weights in about two minutes (~6 s each, the composed float netlists evaluated in `NetlistEvaluator`'s leveled mode) and cleanly skips the four standalone machines. Rebuilding the models (`tools/build_all.py`, ~50 min for all 18) is a separate step, needed only when the circuit constructions in `build.py` change; routine verification never rebuilds. The batched evaluator is population-safe: every chained intermediate (carry, borrow, mux select) is computed per population slot, so `tools/prune_weights.py`'s parallel fitness screens are exact rather than slot-0 approximations.
|
| 351 |
|
| 352 |
---
|
| 353 |
|
|
@@ -360,11 +360,11 @@ The minimal member of the family: a Turing-complete computer with **no instructi
|
|
| 360 |
- Circuits (all wiring shipped as `.inputs` metadata): an 8-bit two's-complement subtractor, the branch neuron, a `PC + 3` incrementer, a branch mux, and the packed 256-row memory.
|
| 361 |
|
| 362 |
```bash
|
| 363 |
-
python build.py --apply subleq # -> variants/neural_subleq8.safetensors
|
| 364 |
-
python machines.py subleq # exhaustive datapath + lockstep programs
|
| 365 |
```
|
| 366 |
|
| 367 |
-
`machines.py subleq` evaluates the datapath **from the shipped wiring metadata** over all 65,536 operand pairs (result and branch decision both exhaustive), checks the PC mux, and runs a program suite (clear, negate-copy, add-by-double-negation, countdown loop) in full-state lockstep against a reference emulator. Third-party SUBLEQ toolchains target this machine directly once the `0xFF` halt convention is mapped.
|
| 368 |
|
| 369 |
---
|
| 370 |
|
|
@@ -382,10 +382,10 @@ The most capable member: a RISC-V CPU whose entire datapath is ternary threshold
|
|
| 382 |
Signed comparisons ride the unsigned bit-cascade with sign bits complemented through NOT gates; SLL uses the barrel shifter, SRL is bit-reversal wiring over it, SRA a gate mux over the complement form. Instruction decode, immediate extraction, register-file indexing, and PC sequencing are fixed wiring, per the family convention.
|
| 383 |
|
| 384 |
```bash
|
| 385 |
-
python build.py --apply rv32 # build the file
|
| 386 |
-
python quantize.py variants/neural_rv32.safetensors --ternary --strict
|
| 387 |
-
python machines.py rv32 # eight-program lockstep suite
|
| 388 |
-
python machines.py rv32-c # stock-compiler C, end to end
|
| 389 |
```
|
| 390 |
|
| 391 |
**Running compiled C.** `machines.py rv32-c` compiles a freestanding C program (gcd, Fibonacci, insertion sort; `rv32im`, so real `mul`/`rem`) with an unmodified clang rv32im toolchain, loads the relocatable object with an in-repo loader (no external linker — it resolves the R_RISCV relocations of one translation unit and lays the sections out flat), executes it on the threshold CPU, and checks the return value against the value computed natively. The program retires in ~300 instructions and matches exactly. Stock `rv32im` toolchains (gcc, clang, rustc) emit this ISA. Unfinished float work — subnormals, FMA, and the FCVT rounding-mode field — is tracked in `todo.md`.
|
|
@@ -439,9 +439,9 @@ write is gated by NOT halt), so iterating past HALT is harmless.
|
|
| 439 |
conductance mismatch (bit-exact through σ_G = 0.10).
|
| 440 |
|
| 441 |
```bash
|
| 442 |
-
python matrix8.py build # compile + save variants/neural_matrix8.safetensors
|
| 443 |
-
python matrix8.py verify # exhaustive equality vs the gate graph and integer reference
|
| 444 |
-
python matrix8.py analog # margin measurement + read-noise + conductance-mismatch sweeps
|
| 445 |
```
|
| 446 |
|
| 447 |
Because the transition is a fixed matrix stack proven equal to the gate-graph
|
|
@@ -486,9 +486,9 @@ The equality is machine-checked rather than observed on one run:
|
|
| 486 |
closing the loop across two generations.
|
| 487 |
|
| 488 |
```bash
|
| 489 |
-
python constructor8.py build # emit variants/neural_subleq8io.safetensors
|
| 490 |
-
python constructor8.py verify # host soundness + codec round-trip + constructor on all 3 backends
|
| 491 |
-
python constructor8.py self # full self-reproduction on the threshold matrices, then gen-2 boot
|
| 492 |
```
|
| 493 |
|
| 494 |
A program running on the processor emits the exact tensor file that defines
|
|
@@ -672,15 +672,16 @@ Loss components: BCE on output bits, BCE on extracted A and B bits (2× weight),
|
|
| 672 |
neural_computer.safetensors canonical model (32-bit, 64 KB, ~8.61M params)
|
| 673 |
variants/ 18 fitness variants + 4 standalone machines
|
| 674 |
(neural_subleq8, neural_rv32, neural_matrix8, neural_subleq8io)
|
| 675 |
-
|
| 676 |
-
|
| 677 |
-
|
| 678 |
-
|
| 679 |
-
|
| 680 |
-
|
| 681 |
-
|
| 682 |
-
|
| 683 |
-
|
|
|
|
| 684 |
constructor / self-reproduction suite
|
| 685 |
tools/ build_all.py (build + quantize + verify every profile),
|
| 686 |
cpu_programs.py (assembler + CPU program suite), test_cpu.py
|
|
|
|
| 78 |
Run the full circuit verification suite against any variant:
|
| 79 |
|
| 80 |
```bash
|
| 81 |
+
python src/eval_all.py variants/ # 18 fitness variants (machines skipped)
|
| 82 |
+
python src/eval_all.py neural_computer.safetensors # the canonical file
|
| 83 |
+
python src/eval_all.py --cpu-program variants/ # also run an assembled
|
| 84 |
# program through the
|
| 85 |
# threshold-gated CPU
|
| 86 |
```
|
| 87 |
|
| 88 |
+
`src/eval_all.py` reads each variant's manifest, runs a gate-level fitness suite (13,900–15,900 tests per variant covering Boolean, arithmetic, ALU, control, modular, error-detection, threshold, and float circuits, including end-to-end evaluation of the composed float pipelines from the shipped wiring metadata — see the Verification table), and optionally executes a small assembled program through a manifest-sized threshold CPU plus a chained 16- or 32-bit ALU sequence on wider variants.
|
| 89 |
|
| 90 |
For an interactive walkthrough that exercises Boolean gates, the 8-bit ALU, mod-5 divisibility, and a CPU loop end-to-end:
|
| 91 |
|
|
|
|
| 294 |
Auto-generated filename: `neural_{alu|computer}{BITS}[_{MEMORY}].safetensors`. Custom address widths via `-a N` produce `_addrN`.
|
| 295 |
|
| 296 |
```bash
|
| 297 |
+
python src/build.py --bits 32 --apply all # neural_computer32.safetensors
|
| 298 |
+
python src/build.py --bits 8 -m none --apply all # neural_alu8.safetensors
|
| 299 |
+
python src/build.py --bits 16 -m small --apply all # neural_computer16_small.safetensors
|
| 300 |
+
python src/build.py --bits 32 -a 6 --apply all # neural_computer32_addr6.safetensors
|
| 301 |
```
|
| 302 |
|
| 303 |
To regenerate every named variant in one pass:
|
|
|
|
| 306 |
python tools/build_all.py
|
| 307 |
```
|
| 308 |
|
| 309 |
+
This populates `variants/` with all 18 builds, quantizes each one to the smallest signed integer dtype that exactly represents its weights (~4× reduction in tensor data, with file size dominated by the safetensors header on the smaller profiles), verifies the strictly ternary weight invariant (`--ternary --strict`, so a build with any non-ternary weight fails loudly), stamps the `weight_quantization` metadata field, and runs `src/eval.py` on each as a sanity check.
|
| 310 |
|
| 311 |
The quantizer is also available standalone:
|
| 312 |
|
| 313 |
```bash
|
| 314 |
+
python src/quantize.py path/to/file.safetensors # in-place
|
| 315 |
+
python src/quantize.py variants/ # whole directory
|
| 316 |
+
python src/quantize.py model.safetensors -o quantized.safetensors
|
| 317 |
+
python src/quantize.py file.safetensors --ternary # push toward {-1, 0, 1} weights
|
| 318 |
+
python src/quantize.py file.safetensors --ternary --strict # error if any weight is non-ternary
|
| 319 |
```
|
| 320 |
|
| 321 |
Every weight and bias tensor in the canonical model fits in `int8`. The eval pipeline promotes weights to `float32` on load, so integer storage is exact and transparent.
|
| 322 |
|
| 323 |
+
**Ternary mode.** `src/build.py` emits only ternary weights: identity buffers are `weight=1, bias=-1` (`H(x - 1)`), and the comparators, modular detectors, and division stages that previously required positional weights up to ±2³¹ are bit-cascaded multi-layer equivalents. With `--ternary`, the quantizer verifies this and repairs legacy files: it rewrites historical single-input `weight=±2` buffers as `weight=±1` with the bias adjusted to preserve the heaviside output for binary inputs (`H(2x - 1) ≡ H(x - 1)`), and rebuilds pre-bit-cascade modular detectors (moduli already in bit-cascade form are left untouched, routing metadata included). `--strict` fails if any weight tensor remains non-ternary. Every shipped file carries the metadata field `weight_quantization: ternary`; a repaired file with remaining violations would be stamped `ternary_partial`.
|
| 324 |
|
| 325 |
---
|
| 326 |
|
|
|
|
| 347 |
|
| 348 |
The 8-bit arithmetic and ALU tests use strategic sampling rather than the full 65,536-case sweep because exhaustive coverage at 8-bit is feasible but not necessary given that the circuits are constructed gate-by-gate. The 16-bit and 32-bit arithmetic tests sample edge cases only; full exhaustive coverage at those widths is infeasible without specialized hardware.
|
| 349 |
|
| 350 |
+
`src/eval_all.py` runs the unified suite. Exit code is the number of failing variants (0 means all pass). **Testing is evaluation, not rebuilding**: `python src/eval_all.py variants/` scores all 18 fitness variants against the shipped weights in about two minutes (~6 s each, the composed float netlists evaluated in `NetlistEvaluator`'s leveled mode) and cleanly skips the four standalone machines. Rebuilding the models (`tools/build_all.py`, ~50 min for all 18) is a separate step, needed only when the circuit constructions in `src/build.py` change; routine verification never rebuilds. The batched evaluator is population-safe: every chained intermediate (carry, borrow, mux select) is computed per population slot, so `tools/prune_weights.py`'s parallel fitness screens are exact rather than slot-0 approximations.
|
| 351 |
|
| 352 |
---
|
| 353 |
|
|
|
|
| 360 |
- Circuits (all wiring shipped as `.inputs` metadata): an 8-bit two's-complement subtractor, the branch neuron, a `PC + 3` incrementer, a branch mux, and the packed 256-row memory.
|
| 361 |
|
| 362 |
```bash
|
| 363 |
+
python src/build.py --apply subleq # -> variants/neural_subleq8.safetensors
|
| 364 |
+
python src/machines.py subleq # exhaustive datapath + lockstep programs
|
| 365 |
```
|
| 366 |
|
| 367 |
+
`src/machines.py subleq` evaluates the datapath **from the shipped wiring metadata** over all 65,536 operand pairs (result and branch decision both exhaustive), checks the PC mux, and runs a program suite (clear, negate-copy, add-by-double-negation, countdown loop) in full-state lockstep against a reference emulator. Third-party SUBLEQ toolchains target this machine directly once the `0xFF` halt convention is mapped.
|
| 368 |
|
| 369 |
---
|
| 370 |
|
|
|
|
| 382 |
Signed comparisons ride the unsigned bit-cascade with sign bits complemented through NOT gates; SLL uses the barrel shifter, SRL is bit-reversal wiring over it, SRA a gate mux over the complement form. Instruction decode, immediate extraction, register-file indexing, and PC sequencing are fixed wiring, per the family convention.
|
| 383 |
|
| 384 |
```bash
|
| 385 |
+
python src/build.py --apply rv32 # build the file
|
| 386 |
+
python src/quantize.py variants/neural_rv32.safetensors --ternary --strict
|
| 387 |
+
python src/machines.py rv32 # eight-program lockstep suite
|
| 388 |
+
python src/machines.py rv32-c # stock-compiler C, end to end
|
| 389 |
```
|
| 390 |
|
| 391 |
**Running compiled C.** `machines.py rv32-c` compiles a freestanding C program (gcd, Fibonacci, insertion sort; `rv32im`, so real `mul`/`rem`) with an unmodified clang rv32im toolchain, loads the relocatable object with an in-repo loader (no external linker — it resolves the R_RISCV relocations of one translation unit and lays the sections out flat), executes it on the threshold CPU, and checks the return value against the value computed natively. The program retires in ~300 instructions and matches exactly. Stock `rv32im` toolchains (gcc, clang, rustc) emit this ISA. Unfinished float work — subnormals, FMA, and the FCVT rounding-mode field — is tracked in `todo.md`.
|
|
|
|
| 439 |
conductance mismatch (bit-exact through σ_G = 0.10).
|
| 440 |
|
| 441 |
```bash
|
| 442 |
+
python src/matrix8.py build # compile + save variants/neural_matrix8.safetensors
|
| 443 |
+
python src/matrix8.py verify # exhaustive equality vs the gate graph and integer reference
|
| 444 |
+
python src/matrix8.py analog # margin measurement + read-noise + conductance-mismatch sweeps
|
| 445 |
```
|
| 446 |
|
| 447 |
Because the transition is a fixed matrix stack proven equal to the gate-graph
|
|
|
|
| 486 |
closing the loop across two generations.
|
| 487 |
|
| 488 |
```bash
|
| 489 |
+
python src/constructor8.py build # emit variants/neural_subleq8io.safetensors
|
| 490 |
+
python src/constructor8.py verify # host soundness + codec round-trip + constructor on all 3 backends
|
| 491 |
+
python src/constructor8.py self # full self-reproduction on the threshold matrices, then gen-2 boot
|
| 492 |
```
|
| 493 |
|
| 494 |
A program running on the processor emits the exact tensor file that defines
|
|
|
|
| 672 |
neural_computer.safetensors canonical model (32-bit, 64 KB, ~8.61M params)
|
| 673 |
variants/ 18 fitness variants + 4 standalone machines
|
| 674 |
(neural_subleq8, neural_rv32, neural_matrix8, neural_subleq8io)
|
| 675 |
+
src/ the library (run scripts as `python src/<name>.py`)
|
| 676 |
+
├── build.py generator (one safetensors per invocation; also `subleq`, `rv32`)
|
| 677 |
+
├── quantize.py min integer dtypes + ternary verification/repair
|
| 678 |
+
├── eval.py gate-level fitness suite, NetlistEvaluator, float oracles, reference CPU
|
| 679 |
+
├── eval_all.py variant-agnostic harness + manifest-sized threshold CPU
|
| 680 |
+
├── machines.py neural_subleq8 + neural_rv32 runtimes, references, assemblers,
|
| 681 |
+
│ RV32 object loader, and the test suites (subleq / rv32 / rv32-c)
|
| 682 |
+
├── matrix8.py compiles the CPU to a recurrent ternary matrix stack; the
|
| 683 |
+
│ exhaustive equality suite and the analog crossbar simulation
|
| 684 |
+
└── constructor8.py the neural_subleq8io host, the recipe codec, and the universal
|
| 685 |
constructor / self-reproduction suite
|
| 686 |
tools/ build_all.py (build + quantize + verify every profile),
|
| 687 |
cpu_programs.py (assembler + CPU program suite), test_cpu.py
|
build.py → src/build.py
RENAMED
|
@@ -112,7 +112,7 @@ from safetensors import safe_open
|
|
| 112 |
from safetensors.torch import save_file
|
| 113 |
|
| 114 |
|
| 115 |
-
MODEL_DIR = Path(__file__).resolve().parent
|
| 116 |
|
| 117 |
|
| 118 |
def get_model_path(bits: int = 8, memory_profile: str = None, addr_bits: int = None) -> Path:
|
|
@@ -140,7 +140,7 @@ def get_model_path(bits: int = 8, memory_profile: str = None, addr_bits: int = N
|
|
| 140 |
|
| 141 |
|
| 142 |
MODEL_PATH = MODEL_DIR / "neural_computer8.safetensors"
|
| 143 |
-
MANIFEST_PATH = Path(__file__).resolve().parent / "tensors.txt"
|
| 144 |
|
| 145 |
DEFAULT_ADDR_BITS = 16
|
| 146 |
DEFAULT_MEM_BYTES = 1 << DEFAULT_ADDR_BITS
|
|
@@ -4074,7 +4074,7 @@ def _load_routing_table() -> Dict[str, Any]:
|
|
| 4074 |
global _ROUTING_TABLE_CACHE
|
| 4075 |
if _ROUTING_TABLE_CACHE is not None:
|
| 4076 |
return _ROUTING_TABLE_CACHE
|
| 4077 |
-
path = Path(__file__).parent / "routing" / "routing.json"
|
| 4078 |
if not path.exists():
|
| 4079 |
_ROUTING_TABLE_CACHE = {}
|
| 4080 |
return _ROUTING_TABLE_CACHE
|
|
|
|
| 112 |
from safetensors.torch import save_file
|
| 113 |
|
| 114 |
|
| 115 |
+
MODEL_DIR = Path(__file__).resolve().parent.parent # repo root; this module lives in src/
|
| 116 |
|
| 117 |
|
| 118 |
def get_model_path(bits: int = 8, memory_profile: str = None, addr_bits: int = None) -> Path:
|
|
|
|
| 140 |
|
| 141 |
|
| 142 |
MODEL_PATH = MODEL_DIR / "neural_computer8.safetensors"
|
| 143 |
+
MANIFEST_PATH = Path(__file__).resolve().parent.parent / "tensors.txt"
|
| 144 |
|
| 145 |
DEFAULT_ADDR_BITS = 16
|
| 146 |
DEFAULT_MEM_BYTES = 1 << DEFAULT_ADDR_BITS
|
|
|
|
| 4074 |
global _ROUTING_TABLE_CACHE
|
| 4075 |
if _ROUTING_TABLE_CACHE is not None:
|
| 4076 |
return _ROUTING_TABLE_CACHE
|
| 4077 |
+
path = Path(__file__).parent.parent / "routing" / "routing.json"
|
| 4078 |
if not path.exists():
|
| 4079 |
_ROUTING_TABLE_CACHE = {}
|
| 4080 |
return _ROUTING_TABLE_CACHE
|
constructor8.py → src/constructor8.py
RENAMED
|
@@ -58,7 +58,7 @@ from safetensors.torch import save_file
|
|
| 58 |
|
| 59 |
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
| 60 |
|
| 61 |
-
REPO = os.path.dirname(os.path.abspath(__file__))
|
| 62 |
MODEL_PATH = os.path.join(REPO, "variants", "neural_subleq8io.safetensors")
|
| 63 |
|
| 64 |
from matrix8 import Net, compile_net # machine-1 compiler, reused verbatim
|
|
|
|
| 58 |
|
| 59 |
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
| 60 |
|
| 61 |
+
REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # repo root; this module lives in src/
|
| 62 |
MODEL_PATH = os.path.join(REPO, "variants", "neural_subleq8io.safetensors")
|
| 63 |
|
| 64 |
from matrix8 import Net, compile_net # machine-1 compiler, reused verbatim
|
eval.py → src/eval.py
RENAMED
|
@@ -30,7 +30,7 @@ import torch
|
|
| 30 |
from safetensors import safe_open
|
| 31 |
|
| 32 |
|
| 33 |
-
MODEL_PATH = os.path.join(os.path.dirname(__file__), "neural_computer.safetensors")
|
| 34 |
|
| 35 |
|
| 36 |
@dataclass
|
|
@@ -433,7 +433,7 @@ def run_smoke_test() -> int:
|
|
| 433 |
f"LOOP={final.mem[0x0109]}, cycles={cycles}")
|
| 434 |
|
| 435 |
print("Running threshold-weight implementation (GenericThresholdCPU, 1 KB)...")
|
| 436 |
-
path = os.path.join(os.path.dirname(__file__), "variants",
|
| 437 |
"neural_computer8_small.safetensors")
|
| 438 |
tensors = {}
|
| 439 |
with safe_open(path, framework="pt") as f:
|
|
|
|
| 30 |
from safetensors import safe_open
|
| 31 |
|
| 32 |
|
| 33 |
+
MODEL_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)), "neural_computer.safetensors") # repo root; this module lives in src/
|
| 34 |
|
| 35 |
|
| 36 |
@dataclass
|
|
|
|
| 433 |
f"LOOP={final.mem[0x0109]}, cycles={cycles}")
|
| 434 |
|
| 435 |
print("Running threshold-weight implementation (GenericThresholdCPU, 1 KB)...")
|
| 436 |
+
path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "variants",
|
| 437 |
"neural_computer8_small.safetensors")
|
| 438 |
tensors = {}
|
| 439 |
with safe_open(path, framework="pt") as f:
|
eval_all.py → src/eval_all.py
RENAMED
|
File without changes
|
machines.py → src/machines.py
RENAMED
|
@@ -209,7 +209,7 @@ def load(obj: bytes, base: int = 0, mem_size: int = 65536,
|
|
| 209 |
# ============================================================================
|
| 210 |
# neural_rv32: assembler, reference emulator, threshold runtime
|
| 211 |
# ============================================================================
|
| 212 |
-
RV32_MODEL = os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
| 213 |
"variants", "neural_rv32.safetensors")
|
| 214 |
MASK32 = 0xFFFFFFFF
|
| 215 |
MMIO_CONSOLE = 0xFF00
|
|
@@ -1092,7 +1092,7 @@ class Rv32ThresholdCPU:
|
|
| 1092 |
# ============================================================================
|
| 1093 |
# neural_subleq8: threshold runtime, reference, assembler
|
| 1094 |
# ============================================================================
|
| 1095 |
-
SUBLEQ_MODEL = os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
| 1096 |
"variants", "neural_subleq8.safetensors")
|
| 1097 |
HALT_PC = 0xFF
|
| 1098 |
|
|
|
|
| 209 |
# ============================================================================
|
| 210 |
# neural_rv32: assembler, reference emulator, threshold runtime
|
| 211 |
# ============================================================================
|
| 212 |
+
RV32_MODEL = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
|
| 213 |
"variants", "neural_rv32.safetensors")
|
| 214 |
MASK32 = 0xFFFFFFFF
|
| 215 |
MMIO_CONSOLE = 0xFF00
|
|
|
|
| 1092 |
# ============================================================================
|
| 1093 |
# neural_subleq8: threshold runtime, reference, assembler
|
| 1094 |
# ============================================================================
|
| 1095 |
+
SUBLEQ_MODEL = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
|
| 1096 |
"variants", "neural_subleq8.safetensors")
|
| 1097 |
HALT_PC = 0xFF
|
| 1098 |
|
matrix8.py → src/matrix8.py
RENAMED
|
@@ -62,7 +62,7 @@ from safetensors.torch import save_file
|
|
| 62 |
|
| 63 |
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
| 64 |
|
| 65 |
-
REPO = os.path.dirname(os.path.abspath(__file__))
|
| 66 |
MODEL_PATH = os.path.join(REPO, "variants", "neural_matrix8.safetensors")
|
| 67 |
GATE_MODEL_PATH = os.path.join(REPO, "variants", "neural_computer8_registers.safetensors")
|
| 68 |
|
|
|
|
| 62 |
|
| 63 |
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
| 64 |
|
| 65 |
+
REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # repo root; this module lives in src/
|
| 66 |
MODEL_PATH = os.path.join(REPO, "variants", "neural_matrix8.safetensors")
|
| 67 |
GATE_MODEL_PATH = os.path.join(REPO, "variants", "neural_computer8_registers.safetensors")
|
| 68 |
|
quantize.py → src/quantize.py
RENAMED
|
File without changes
|
tools/build_all.py
CHANGED
|
@@ -52,7 +52,7 @@ def build_variant(bits: int, profile: str) -> Path:
|
|
| 52 |
out = OUT_DIR / variant_filename(bits, profile)
|
| 53 |
shutil.copy2(SEED, out)
|
| 54 |
cmd = [
|
| 55 |
-
sys.executable, str(ROOT / "build.py"),
|
| 56 |
"--bits", str(bits),
|
| 57 |
"-m", profile,
|
| 58 |
"--apply",
|
|
@@ -71,7 +71,7 @@ def quantize_variant(path: Path) -> tuple[int, int]:
|
|
| 71 |
dtype, verifies the strictly ternary weight invariant, and stamps the
|
| 72 |
weight_quantization metadata field. Returns (bytes_before, bytes_after).
|
| 73 |
"""
|
| 74 |
-
rc, log = run([sys.executable, str(ROOT / "quantize.py"), str(path),
|
| 75 |
"--ternary", "--strict"], timeout=300)
|
| 76 |
if rc != 0:
|
| 77 |
raise RuntimeError(f"quantize failed for {path.name}:\n{log[-800:]}")
|
|
@@ -108,7 +108,7 @@ def measure_variant(path: Path) -> dict:
|
|
| 108 |
def eval_variant(path: Path, device: str = "cpu", timeout: int = 600) -> dict:
|
| 109 |
"""Run eval.py against a variant and parse fitness."""
|
| 110 |
cmd = [
|
| 111 |
-
sys.executable, str(ROOT / "eval.py"),
|
| 112 |
"--model", str(path),
|
| 113 |
"--device", device,
|
| 114 |
"--quiet",
|
|
|
|
| 52 |
out = OUT_DIR / variant_filename(bits, profile)
|
| 53 |
shutil.copy2(SEED, out)
|
| 54 |
cmd = [
|
| 55 |
+
sys.executable, str(ROOT / "src" / "build.py"),
|
| 56 |
"--bits", str(bits),
|
| 57 |
"-m", profile,
|
| 58 |
"--apply",
|
|
|
|
| 71 |
dtype, verifies the strictly ternary weight invariant, and stamps the
|
| 72 |
weight_quantization metadata field. Returns (bytes_before, bytes_after).
|
| 73 |
"""
|
| 74 |
+
rc, log = run([sys.executable, str(ROOT / "src" / "quantize.py"), str(path),
|
| 75 |
"--ternary", "--strict"], timeout=300)
|
| 76 |
if rc != 0:
|
| 77 |
raise RuntimeError(f"quantize failed for {path.name}:\n{log[-800:]}")
|
|
|
|
| 108 |
def eval_variant(path: Path, device: str = "cpu", timeout: int = 600) -> dict:
|
| 109 |
"""Run eval.py against a variant and parse fitness."""
|
| 110 |
cmd = [
|
| 111 |
+
sys.executable, str(ROOT / "src" / "eval.py"),
|
| 112 |
"--model", str(path),
|
| 113 |
"--device", device,
|
| 114 |
"--quiet",
|
tools/play.py
CHANGED
|
@@ -26,7 +26,7 @@ import torch
|
|
| 26 |
from safetensors import safe_open
|
| 27 |
|
| 28 |
REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # this file lives in tools/
|
| 29 |
-
sys.path.insert(0, REPO)
|
| 30 |
|
| 31 |
# Reuse the variant-aware CPU runtime from eval_all.py
|
| 32 |
from eval_all import GenericThresholdCPU, builtin_program
|
|
|
|
| 26 |
from safetensors import safe_open
|
| 27 |
|
| 28 |
REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # this file lives in tools/
|
| 29 |
+
sys.path.insert(0, os.path.join(REPO, "src")) # eval_all lives in src/
|
| 30 |
|
| 31 |
# Reuse the variant-aware CPU runtime from eval_all.py
|
| 32 |
from eval_all import GenericThresholdCPU, builtin_program
|
tools/prune_weights.py
CHANGED
|
@@ -13,7 +13,7 @@ import time
|
|
| 13 |
import torch
|
| 14 |
from safetensors.torch import save_file
|
| 15 |
|
| 16 |
-
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) # repo root
|
| 17 |
from eval import BatchedFitnessEvaluator, create_population, load_model
|
| 18 |
|
| 19 |
torch.manual_seed(0)
|
|
|
|
| 13 |
import torch
|
| 14 |
from safetensors.torch import save_file
|
| 15 |
|
| 16 |
+
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "src")) # src/ at repo root
|
| 17 |
from eval import BatchedFitnessEvaluator, create_population, load_model
|
| 18 |
|
| 19 |
torch.manual_seed(0)
|
tools/test_cpu.py
CHANGED
|
@@ -21,7 +21,7 @@ import torch
|
|
| 21 |
from safetensors import safe_open
|
| 22 |
|
| 23 |
REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # this file lives in tools/
|
| 24 |
-
sys.path.insert(0, REPO)
|
| 25 |
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) # cpu_programs is a sibling
|
| 26 |
from eval_all import GenericThresholdCPU, get_manifest
|
| 27 |
from cpu_programs import SUITE
|
|
|
|
| 21 |
from safetensors import safe_open
|
| 22 |
|
| 23 |
REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # this file lives in tools/
|
| 24 |
+
sys.path.insert(0, os.path.join(REPO, "src")) # eval_all lives in src/
|
| 25 |
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) # cpu_programs is a sibling
|
| 26 |
from eval_all import GenericThresholdCPU, get_manifest
|
| 27 |
from cpu_programs import SUITE
|