Skip to content

feat(fpga): port trios-mesh BPSK modem core to a .t27 spec#1244

Closed
gHashTag wants to merge 872 commits into
masterfrom
feat/bpsk-modem-spec
Closed

feat(fpga): port trios-mesh BPSK modem core to a .t27 spec#1244
gHashTag wants to merge 872 commits into
masterfrom
feat/bpsk-modem-spec

Conversation

@gHashTag

@gHashTag gHashTag commented Jul 1, 2026

Copy link
Copy Markdown
Owner

Closes #1243. Ports the synthesizable core of the TRI-NET 5.8 GHz drone-mesh BPSK modem (gHashTag/trios-mesh) into t27 as a spec-first FPGA module.

specs/fpga/bpsk.t27 (ZeroDSP_BPSK)

  • TX: bit_to_symbol (bit -> +/-1), tx_load/tx_next_symbol — a byte -> +/-1 BPSK serializer (LSB first), Barker-13 preamble.
  • RX: chip_contrib + correlate — an integer Barker-13 correlator (unrolled 13-tap sum of +/-1 chip products), sync_locked threshold gate, rx_push sliding window.
  • Framing: frame_symbol_count = 13 preamble + 8 length + 8*payload symbols.

Validation (mirrors the Rust modem's unit tests)

12 tests / 4 invariants: autocorrelation peak == 13; 180-degree channel inversion == -13 (phase-inversion detection); off-peak sidelobes -5 / +5; LSB-first serialization; sync threshold gate; smallest frame == 21 symbols. parse + typecheck clean; all functions lower to Verilog / C / Rust / Zig (no TODO); sealed (.trinity/seals/fpga_ZeroDSP_BPSK.json). Counted in the local suite: parse/typecheck/gen(x4) 504/504.

Notes for reviewers (T27 Verilog backend limits worked around in-spec)

Barker chips are packed into one u16 const (array consts abort Verilog lowering); the correlator is unrolled (no local temporaries, which are dropped); functions use if/else single-assignment (no early-return in the Verilog function lowering); TX state is flat scalar vars (struct fields are declared <type>_<field> but referenced <var>_<field>). These are pre-existing backend behaviors (also visible in specs/fpga/uart.t27); filing a separate issue with the specifics. Datapath functions + state record only — clocking/ports remain a backend concern.

phi^2 + phi^-2 = 3 | TRINITY

gHashTag and others added 30 commits April 16, 2026 00:58
- Remove 50 music album files from trixphi-album/ directory
- Clean up ~4918 lines of album content
- Keep clara-bridge components intact

Closes #487

Co-authored-by: Dmitrii Vasilev <admin@t27.ai>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Add formal adversarial robustness (unique among SOA)
- Add guaranteed polynomial bounds (84 Coq theorems)
- Add ML+AR composition patterns (4 complete patterns)
- Add energy efficiency advantage (49x vs GPU)
- Add scientific contributions (theoretical + empirical)
- Update competitive advantages and differentiations

Comprehensive scientific enhancement for DARPA CLARA PA-25-07-02 submission. All research contributions documented in evidence/ directory.
- FAQ document with 14 Q&A pairs
- 8 technical figures for评审
- Complete documentation package for TRINITY CLARA

All deliverables present for DARPA PA-25-07-02 deadline.
- Add ring_32.t27 — Ring 32 definition
- Add railway_deploy.t27 — Railway deployment orchestrator
- Add debounce.t27 — φ-structured debouncing (618ms)
- Add task_analysis.t27 — Task priority analysis for 27 bees
- Add mod_structure.t27 — Module structure validation

Ring 32: Cloud Orchestration
- 27 sacred environment variables
- 9-state deployment machine
- φ-structured timeouts (618ms, 1618ms)
- TDD coverage: 12 tests, 6 invariants, 1 benchmark

Constitutional Compliance (L1-L7):
- L2: Spec-first (.t27 → Zig/C/Verilog)
- L3: ASCII-only, English identifiers
- L4: Full TDD coverage
- L5: Phi-structured constants

Closes #484
Ring 32: Cloud Orchestration
- specs/base/ring_32.t27
- specs/cloud/railway_deploy.t27
- specs/base/debounce.t27
- specs/queen/task_analysis.t27
- specs/compiler/mod_structure.t27

Closes #484
…ate Scott's new text

- Resolved 4 unresolved git merge conflicts in LaTeX source
- Removed duplicate \begin{document} block and reversed content
- Moved orphaned sections 4.4-4.6 (Quasicrystal, Majorana, Hofstadter) inside \end{document}
- Deduplicated bibliography (conway1999, tsirelson1980, trinity2026 were duplicated)
- Updated Scott Olsen affiliation: College of Central Florida -> Wisdom Traditions Center, LLC, Ocala, FL
- Renumbered sections sequentially (1-11) for consistency
- Integrated Scott's new text from email:
  - Plato's Republic golden section derivation (Introduction)
  - Kepler's full 'two great treasures' quote (Introduction)
  - Shechtman and Kroto Nobel prizes (Introduction)
  - Golden balance / paradigmatic symmetry concept (Introduction)
  - El Naschie's golden mean number system (Introduction)
  - Binnig and Prigogine endorsement letters (Section 2)
- Updated Scott's Author Contributions to include golden balance and Plato connection
…ative

Add opening epigraph, rewrite Introduction with rhythmic cadence,
elevate Section 3 to genealogy narrative, enhance Discussion with
fragrance/source metaphor, rewrite Conclusion as 'The Flower in Full Bloom'.

Closes #420
- Remove 50 music album files from trixphi-album/ directory
- Clean up ~4918 lines of album content
- Keep clara-bridge components intact (LICENSE updated)

Closes #??

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove README_RU.md and docs/README_RU.md
- Keep only English documentation in main README.md
- Restore bilingual language selector

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…pport

- Add proper CommonJS exports
- Multi-agent configuration with Set-based agent tracking
- Add/remove agent methods for dynamic observation
- Improve ObserverConfig with shouldObserve and getAgents methods

Ring 32 — Cloud Orchestration

Closes #484

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ecode (#553)

* fix(ffi): GF16 round-to-nearest + overflow→Inf, GF4/8/12/20/24 encode/decode

BUG-001 (#546): encode_gf16 mantissa truncation → round-to-nearest-even
  - Add half-ULP detection + tie-break to even
  - Carry into exponent on mantissa overflow

BUG-002 (#547): encode_gf16 overflow saturates to max-finite → +Inf
  - exp >= max_exp now returns canonical ±Inf (exp=max, mant=0)

BUG-003 (#548): gf32_from_f64 — fix comment (GF32 = IEEE fp32 for FPGA)

API-COMPLETENESS (#549): add from_f32/to_f32 for GF4/8/12/20/24
  - All 7 GoldenFloat formats now have full encode/decode
  - Round-to-nearest-even on all formats
  - Proper overflow→Inf and underflow→zero handling

build.rs: tolerate CC_FORCE_DISABLE for testing without C deps

16 tests passing

Closes #546, Closes #547, Closes #548, Closes #549

* docs: update NOW.md for PR #553

Closes #546, Closes #547, Closes #548, Closes #549, Closes #545
…heck (#554)

* feat(ci): pre-commit gate for t27 (Ring 073)

4 gates: NOW freshness, seal coverage, no new .sh (L7), cargo check
Install: ln -sf ../../scripts/pre-commit .git/hooks/pre-commit

Closes #332

* docs: update NOW.md for PR #554 (pre-commit gate)

Closes #332
…ern, graph, tree, set, hash (#558)

* feat(ring-080..087): add 6 ternary collection specs

Closes #260  Closes #262  Closes #264  Closes #267  Closes #269  Closes #271  Closes #275

Ring 080: ternary_sorting — bubble/selection/insertion/quick sort
Ring 081: ternary_search — linear/binary/ternary search, count, min/max
Ring 082: ternary_pattern_matching — exact match, wildcard, hamming, LCP
Ring 083: ternary_graph — adjacency matrix, degree, 2-hop path
Ring 084: ternary_tree — binary tree with depth, count, sum, balance
Ring 085: ternary_set — sorted set with union/intersection/difference
Ring 087: ternary_hash — hash table with linear probing

* fix: update NOW.md date to UTC-valid 2026-04-29

Closes #260  Closes #262  Closes #264  Closes #267  Closes #269  Closes #271  Closes #275
Closes #339  Closes #287

- Add --hybrid-v2 --n <N> --theta flags to tri math compare
- L2 cosine between phi^k and Pell P_{k+1} vectors
- f64 Pell numbers to avoid u64 overflow at N>60
- Golden test table: N={5,10,15,20,50,152}
- Plateau: cos ~0.9617, theta ~15.90 deg by N=15
- 10 Rust unit tests for golden values + convergence
- Update hybrid-conjecture.md with frozen golden values
…pecs (#560)

Closes #289

Phase 0: scripts/verify_precision.py — mpmath 100-digit sacred constants
Phase 1: specs/numeric/gf_competitive.t27 — GF vs IEEE comparison spec
Phase 2: specs/numeric/pellis_verify.t27 — Pellis closed form verification

- phi, pi, e at 100 decimal digits via mpmath
- Trinity identity check: phi^2 + phi^-2 = 3 (verified to 10^-100)
- Phi identity check: phi^2 = phi + 1 (verified to 10^-100)
- Pellis closed form computation
- GF competitive: roundtrip, accumulation, phi representation tests
- All specs L4-compliant: test + invariant + bench
… + tech tree (#566)

Closes #490  Closes #517

Pipeline specs (Ring 028):
- e2e_test.t27: 9-stage pipeline with success/failure injection
- experience_save.t27: tri experience save command spec
- benchmarks.t27: performance targets and throughput calculations

Memory primitives (Ring 029):
- memory_primitives.t27: remember/recall/forget/reflect operations
- Scoped memory: agent, session, permanent lifetimes
- Phi-hash content addressing for memory cells

Documentation:
- docs/TECH_TREE.md: 5-level technology tree (core→runtime→memory→swarm→unfair)
feat(fpga): Vivado cloud synthesis workflow
fix(ci): Vivado docker run approach
fix(ci): source Vivado settings64.sh
fix(fpga): CLOCK_DEDICATED_ROUTE FALSE per QMTECH Wukong V3 ref
agent and others added 17 commits May 31, 2026 03:57
The host-wave merge union re-exported RingError from both descring and
ring_buffer (two distinct types), causing E0252 'defined multiple
times' in cargo build -p t27c. Alias them to DescRingError and
RingBufError respectively. No external code references the re-exported
names (both types are used only within their own modules), so the
aliases are non-breaking.

Refs FPGA E2E Build failure on master aeeb6b5.
…W87/W111) (#998)

* fix(trit_stdlib): combine half-adder carries by signed addition (W64/W87/W111)

The previous trit_full_adder combined its two half-adder carries with
trit_or (Kleene max). That is wrong in 6 of the 27 (a, b, cin) cases in
balanced ternary {-1, 0, +1}:

  - When either carry is the digit -1, Kleene OR returns 0 because the
    encoding has TRIT_Z (0) > TRIT_N (-1). Inputs (-1,-1,-1), (-1,-1,0),
    (-1,0,-1), (0,-1,-1) all lost the negative carry-out.
  - For (-1,-1,+1) and (+1,+1,-1) the two half carries have opposite
    sign and Kleene max picks the wrong magnitude.

Fix: decode each half-adder carry to a signed integer in {-1, 0, +1},
add them, encode the sum back to a trit. Exhaustive case analysis over
all 27 input triples shows |c1 + c2| <= 1 always, so cout fits in a
single trit and no secondary carry chain is needed.

Tests:
  - trit_full_adder_combines_carries_with_signed_addition asserts the
    emitted Verilog uses c1_val/c2_val/c_total with signed addition and
    does NOT contain the old 'trit_or carry_combine' pattern.
  - trit_full_adder_truth_table_is_correct_all_27_cases drives a
    pure-Rust functional model of the new chain against the canonical
    a + b + cin truth table for every (a, b, cin) in {-1, 0, +1}^3.
    Also asserts the |c1 + c2| <= 1 invariant inline.

Closes #989
Closes #963
Closes #936

* docs(NOW): record W46/W47 optimiser + trit_full_adder carry fixes

Adds two NOW entries:

- opt-cse-dse-fix (Closes #918, #919): the W46 / W47 critical-priority
  optimiser bugs, with the same root-cause / fix / test summary that
  appears in the PR bodies.
- trit-full-adder-carry-fix (Closes #936, #963, #989): the W64 / W87 /
  W111 trit_full_adder carry combine bug, summarised for the doc
  freshness check.

This commit is required because the repo's check-now-freshness CI gate
fails every PR that doesn't update docs/NOW.md. Both fixes are landed
in separate branches / PRs (#998 trit_full_adder, #999 optimizer); the
W46/W47 branch carries this update first so its CI can pass, and the
same entries will be cherry-picked onto the trit-full-adder branch.

Refs #918 #919 #936 #963 #989

---------

Co-authored-by: Perplexity Computer <computer@perplexity.ai>
…or StmtAssign (W46/W47) (#999)

* fix(compiler/optimize): sound CSE for ExprCall + correct DSE target for StmtAssign (W46/W47)

Two critical optimiser bugs in bootstrap/src/compiler.rs that produce
wrong code on every program that goes through optimize() with the
default OptConfig:

  W47 (#919, R-OPT-2) -- CSE hash collision on every function call:
    child_key() fell through to format!("{:?}", node.kind) for
    ExprCall, so all calls produced the literal key "ExprCall". Two
    distinct calls in similar contexts (e.g. `foo() + 1` and
    `bar() + 1`) therefore shared a CSE entry, and the second binary
    was silently rewritten to reference the first one's cached
    temporary -- replacing bar() with foo() in the emitted code. For
    calls with side effects (IO, state mutation) this is a wrong-code
    bug; the issue's suggested fix (CALL:name(args) key) still permits
    de-duplication of two textually identical impure calls, which is
    also incorrect.

    Fix: child_key() now treats ExprCall (and any other non-pure
    expression kind we cannot prove safe to merge) as un-CSE-able by
    returning a unique key from a process-wide AtomicU64 counter on
    every visit. Pure leaves (ExprLiteral, ExprIdentifier) and pure
    ExprBinary expressions built from them remain CSE-able.

  W46 (#918, R-OPT-1) -- dead store elimination removes every assign:
    dead_store_elim() tested `reads.contains(&s.name)` for StmtAssign,
    but the target of a StmtAssign lives in `s.children[0]` (an
    ExprIdentifier) and `s.name` is always "". Since reads never
    contains the empty string, the test was always false and `retain`
    dropped every assignment statement from every optimised function.

    Fix: for StmtAssign we now read the target name from
    `s.children[0].name` and only eliminate the statement when its
    LHS is a simple ExprIdentifier (not arr[i], not obj.field, where
    dropping the write is unsound even if the variable itself isn't
    read later).

Tests (new `tests_optimizer` test cases inside compiler.rs):
  - dead_store_elim_keeps_assignment_whose_target_is_later_read
  - dead_store_elim_does_not_drop_index_or_field_assignment
  - dead_store_elim_drops_truly_dead_assignment_to_simple_identifier
  - cse_does_not_collide_distinct_function_calls (the W47 reproducer:
    foo()+1 / bar()+1 must NOT share a temporary)
  - cse_does_not_dedupe_repeated_calls_to_same_function (two foo()
    call sites must remain distinct because foo may have side effects)
  - cse_still_works_on_pure_repeated_subexpression (sanity: x+y
    repeated twice still hoists into a _cseN local)

Closes #918
Closes #919

* docs(NOW): clarify test strategy for opt-cse-dse-fix

Adds a one-line test-strategy note to the opt-cse-dse-fix entry: the
six new tests in tests_phase40_coverage build ASTs by hand rather than
going through the parser, so they exercise dead_store_elim and
common_subexpr_elim directly and stay stable across surface-syntax
evolution.

Refs #918 #919

---------

Co-authored-by: Perplexity Computer <computer@perplexity.ai>
…loses #1008) (#1009)

* fix(conformance): repair invalid JSON in gf_competitive_bench.json

Add the missing comma after "gf32_one_third_repeats_binary": true and
remove a stray extra closing brace after the first benchmark entry. Both
errors are pre-existing on master and made the file unparseable, so
t27c validate-conformance reported 101 total, 100 valid, 1 invalid and
failed the gate.

After this fix the file parses (2 benchmark entries: sacred_constants,
cross_language_1_3) and validate-conformance reports 101 total, 101 valid,
0 invalid. No semantic change to any benchmark data.

Closes #1008

* docs(now): NOW.md entry for conformance JSON fix (Refs #1008)

---------

Co-authored-by: Perplexity Computer <computer@perplexity.ai>
) (#1006)

Add append-only test/invariant/bench blocks and two new specs implementing
Phases A-D of the phi->IGLA epic, treating phi as a falsifiable design prior
(not proven theory). Every phi performance claim is [Open conjecture] with an
explicit falsification path; only phi^2 + phi^-2 = 3 (Lucas L2) is [Verified].

- A3 specs/numeric/phi_ratio.t27: L5 Trinity identity blocks (f64 tol 1e-14)
- A1/A2 specs/ml/optimizer/race_config.t27 (NEW): frozen RACE config,
  80/20 blind split (seed=17), Chinchilla budget note
- B1 specs/ml/optimizer/adamw.t27: four-arm optimizer control
  (phi-canonical beta1=phi^-1 / wd=phi^-3 vs Damped vs TunedStd vs RandomRat)
- B2 specs/nn/attention.t27: AttentionQKGainAblation module
  (gain=phi^2 vs 1.0 vs learned)
- C1/C2 specs/numeric/gfternary.t27: GFTernary {-phi,0,+phi} vs BitNet
  {-1,0,+1} + CPU bench
- C3 specs/numeric/gf16.t27: GF16 1-6-9 split under FP8 (append-only)
- D specs/nn/gla.t27 (NEW): Gated Linear Attention (Yang 2023 arXiv:2312.06635)

All 7 specs parse + typecheck (0 errors); seals refreshed and validate-seals
passes; FORMAT-SPEC-001.json unchanged (L6); ASCII-only, no Cyrillic (L3).
No hype words. delta_CP=3/phi^2 is [Retracted] and not cited.

Refs #181

Co-authored-by: Perplexity Computer <computer@perplexity.ai>
…er rows (Phase E) (#1007)

Phase E (accounting / publication) of the phi->IGLA epic. Treats phi as a
falsifiable design prior, not a proven theory -- "the method survives, phi
does not (yet)."

- specs/ml/igla_champion_capsule.t27 (NEW): freezes the champion control
  anchor (seed=43, ~81K steps, hidden=828, BPB=2.1919 Wave-8 honest baseline).
  7 test + 4 invariant + 1 bench (L4). Asserts beta1=phi^-1,
  weight_decay=phi^-3=1/(2*phi+1) (NOT the stale 0.118=phi^-3/2),
  the L5 identity phi^2+phi^-2=3, and that the corpus is sub-Chinchilla
  so BPB is preliminary. ASCII-only (L3).
- docs/nona-03-manifest/RESEARCH_CLAIMS.md: new section 5a with three
  CONJECTURAL falsification-ledger rows (FL-001 optimizer, FL-002 QK-Gain,
  FL-003 GFTernary), each with an explicit falsification path; ASHA eta=3
  relabel (Hyperband field default, NOT phi) and delta_CP=3/phi^2 retraction.
- docs/NOW.md: Phase E sync entry.
- .trinity/seals/ml_IglaChampionCapsule.json: seal (validate-seals OK).

Additive only (185 insertions, 0 deletions). FORMAT-SPEC-001 + gf16 numeric
SSOT untouched (L6). The capsule is the CONTROL ANCHOR for equal-budget
ablations, not evidence of phi superiority.

Closes #1005
Refs #181 (epic in gHashTag/trios-trainer-igla)

Co-authored-by: Perplexity Computer <computer@perplexity.ai>
TimingConstraint::from_mhz computed period_ps = 1_000_000_000 / mhz, which
is 1000x too large. 1 MHz = 1e6 Hz; period in ps = 1e12 / (mhz * 1e6) =
1_000_000 / mhz. A 100 MHz target therefore produced 10_000_000 ps (10 us)
instead of 10_000 ps (10 ns), so every test that fed a clock-MHz constraint
into TimingModel::analyze_module compared nanosecond-scale path delays
against a 10-microsecond budget and passed vacuously.

- bootstrap/src/compiler.rs:
  - from_mhz: 1_000_000 / mhz (was 1_000_000_000 / mhz)
  - mhz == 0 fallback: 1_000_000 ps (1 MHz, satisfiable but obviously
    slow) instead of 10_000 ps which collided with the broken 100 MHz
    value
  - test_clock_mhz now expects 10_000 (was 10_000_000)
  - new test_clock_mhz_various_frequencies covers 1/50/100/200/500 MHz
  - test_clock_mhz_zero now expects 1_000_000
- docs/NOW.md: 3-line entry for the W106 fix.

Closes #984

Co-authored-by: Perplexity Computer <admin@t27.ai>
In Verilog, the equality operator `==` binds tighter than the bitwise
AND `&`. The emitter previously wrote

    #delay assert(uut.signal & 32'hMASK == 32'hEXPECTED)

which Verilog parses as `signal & (MASK == EXPECTED)` -- a 1-bit AND
of `signal` with the result of the comparison, never the intended
masked equality. Every masked testbench check in the generated Verilog
therefore silently checked the wrong condition and could only ever
produce false passes (and on rare occasions false fails) on real
silicon.

Emit the parenthesised form instead:

    #delay assert((uut.signal & 32'hMASK) == 32'hEXPECTED)

Added regression `test_testbench_masked_assert_parenthesises_and_before_eq_w49`
that asserts both the corrected shape is emitted and the bare-precedence
shape is not, plus a doc-comment at the emit site explaining the
Verilog precedence rule.

Closes #921

Co-authored-by: Perplexity Computer <admin@t27.ai>
bootstrap/src/compiler.rs lexer:

The multi-char operator lookahead was written as

    if ch == b'&' && self.peek() == b'&' { ...emit && token... }
    if ch == b'|' && self.peek() == b'|' { ...emit || token... }

`Lexer::peek` returns the byte at `self.pos` -- the same character
already captured in `ch` -- not a lookahead. The condition was
therefore tautologically true for any single `&` or `|`, and the
lexer emitted a `&&` / `||` token (with lexeme "&&" / "||") for
every plain bitwise `&` / `|`. Downstream, the parser routed every
Amp/Pipe with that lexeme into `parse_expr_and` / `parse_expr_or` and
tagged the AST `ExprBinary` with `extra_op = "and"` / "or". The
Verilog, C, and Rust backends faithfully translate "and" -> && and
"or" -> ||, so every masked expression in generated code -- 28+
instances in `gf16.t27` alone -- became a 1-bit logical AND/OR rather
than the intended bitwise mask. This silently broke every bit-extract,
sign-bit test, exponent/mantissa split, and mask-equality in the
generated Verilog/C/Rust.

Use `self.peek_offset(1)` for true lookahead at `self.pos + 1`.

Tests:
- test_lexer_distinguishes_bitwise_and_logical_w65: lexer tokenises
  `x & 0xFF` as Amp/lexeme "&" followed by Number/lexeme "0xFF",
  `x && y` as Amp/lexeme "&&", `x | 0xFF` as Pipe/lexeme "|", and
  `x || y` as Pipe/lexeme "||".
- test_parser_tags_bitwise_and_with_amp_op_w65: AST for `return x & 0xFF`
  has `ExprBinary { extra_op = "&" }`, and AST for `return x && y`
  has `ExprBinary { extra_op = "and" }`.

Scope: this PR fixes ONLY the lexer slice (filed as #1011). The
Zig-builtin leaks (`@as`, `@intCast`, `@bitCast`, `@floatFromInt`,
`@exp2`, `@enumFromInt`, `std.math.*`) called out in #937 require
per-backend lowering for each builtin and remain a follow-up; #937
stays open for that work.

Closes #1011
Refs #937

Co-authored-by: Perplexity Computer <admin@t27.ai>
#1013)

bootstrap/src/bitnet_pipeline.rs (layer_sequencer FSM):

  The IDLE state was emitted as

      IDLE: if(start) begin state<=RUN; neuron_id<=0; chunk_id<=0; end

  and DONE_ST sets done<=1 then transitions back to IDLE. Because
  the IDLE body only fires on start, done was sticky forever after
  the first layer -- the parent multilayer_sequencer saw
  layer_done == 1 immediately and skipped layers 2..N. Rewrote IDLE as

      IDLE: begin done<=0;
              if(start) begin state<=RUN; neuron_id<=0; chunk_id<=0; end
            end

  so done is an unconditional 1-cycle pulse: high in DONE_ST, cleared
  on the next IDLE entry, and held low until the next DONE_ST.

bootstrap/src/bitnet_top.rs (top-level busy):

  Previous form:

      assign busy = (current_layer != 6'd0) || layer_start;

  Layer 0 has current_layer == 0 for its entire run and layer_start
  is a 1-cycle pulse, so busy was almost always low during layer 0
  and the on-chip cycle counter (gated by busy) stalled. Replaced
  with a latched started flag:

      reg started;
      always @(posedge clk or negedge rst_n) begin
          if (!rst_n)     started <= 0;
          else if (done)  started <= 0;
          else if (start) started <= 1;
      end
      assign busy = started && !done;

  busy now tracks the full inference window: rises on start, falls on
  the top-level done assertion from multilayer_sequencer.

Tests:
- sequencer_idle_clears_done_w88: layer_sequencer text contains
  'IDLE: begin done<=0;' and the old buggy 'IDLE: if(start)' prefix
  is gone.
- busy_tracks_start_to_done_w88: top contains the started register,
  the done/start branches, the new busy assignment, and the buggy
  current_layer-based form is gone.
- sequencer_idle_arms_on_start: relaxed match to the substring that
  is unchanged across the fix ('if(start) begin state<=RUN; ...').

Full suite: 1403 pass; 6 pre-existing master failures unrelated to
this change (test_verilog_cast_no_as_keyword, two jwt tests,
test_encode_decode, full_adder_uses_two_half_adders_and_or_combine,
trit_full_adder_uses_two_half_adders).

Status: PROVEN -- regression tests pin the corrected emitter text and
the bug shapes that previously slipped through.

Closes #964

Co-authored-by: Perplexity Computer <admin@t27.ai>
…#1014)

The host MMIO + IRQ stack assumed write-1-to-clear (W1C) semantics on
IRQ_STAT (offset 0x0C):

  - MockMmio.write32(IRQ_STAT, mask) masked off the bits.
  - BitnetDriver::clear_irq(mask) wrote mask to IRQ_STAT.
  - IrqHandler::service emitted a W1C write after dispatch.

The RTL slave does the opposite (bootstrap/src/bitnet_irq.rs,
bootstrap/src/bitnet_axi.rs):

  - bitnet_irq clears ALL irq_status bits on the status_read pulse
    generated by an AXI READ of offset 0x0C (read-to-clear).
  - bitnet_axi has no write case for offset 0x0C -- writes to
    IRQ_STAT are silently dropped.

So on real silicon every host acknowledgement was a no-op (the W1C
write was dropped by the slave), and every read of IRQ_STAT silently
consumed every latched event. Latched IRQs were never acknowledged
correctly, and any incidental read destroyed pending state.

Changes:

bootstrap/src/host/mmio.rs:
  - MockMmio.read32(IRQ_STAT) now returns the latched value and clears
    all bits (read-to-clear), matching the RTL.
  - MockMmio.write32(IRQ_STAT, _) is recorded in the log (so write_count
    bookkeeping still reflects the bus transaction) but leaves the
    register untouched, matching the AXI slave.

bootstrap/src/host/driver.rs:
  - read_irq_status carries a DESTRUCTIVE doc warning.
  - clear_irq is #[deprecated]; body is empty (the hardware drops it
    anyway). Kept for source compatibility with pre-W57 callers.

bootstrap/src/host/irq.rs:
  - IrqHandler::service reads IRQ_STAT once (which clears all bits)
    and dispatches handlers for bits present in raw_status. The W1C
    write after dispatch is removed; it was a no-op on hardware and
    only added a misleading log entry on the mock.

bootstrap/src/host/csr_map.rs:
  - CSR-map docstring updated to call out read-to-clear and the
    write-is-dropped slave behaviour.

Tests:
  - mmio.rs::read_irq_stat_is_destructive_w57 -- read clears latches.
  - mmio.rs::write_irq_stat_is_dropped_w57 -- write leaves latches
    intact, transaction still in log.
  - irq.rs::service_skips_latched_but_unregistered_source_w57 --
    documents that unregistered bits are observed in raw_status and
    then consumed by the read.
  - tests/host_irq.rs: poll-vs-irq integration suite updated to
    expect 8w/11r on both paths (was 8w/11r poll + 9w/11r irq, with
    the one extra write being the dropped W1C). writes_match=true
    and writes_diff=0 are now the regression invariants.

Full suite: 1405 pass; 6 pre-existing master failures unrelated to
this change (test_verilog_cast_no_as_keyword, two jwt tests,
test_encode_decode, full_adder_uses_two_half_adders_and_or_combine,
trit_full_adder).

Status: PROVEN -- regression tests pin the corrected read-to-clear /
drop-on-write semantics and the previous W1C-shaped bugs.

Closes #929

Co-authored-by: Perplexity Computer <admin@t27.ai>
bootstrap/src/compiler.rs strength_reduce / reduce_expr:

  The optimizer used to rewrite `x / N` as `x >> log2(N)` whenever
  the RHS was a power-of-two literal. This is correct for unsigned
  integers but is semantically wrong for signed integers in C / Rust
  / Zig: signed `/` rounds toward zero, but arithmetic `>>` rounds
  toward negative infinity. Worked example with i32:

      x = -7
      x /  4  == -1       (truncation toward zero)
      x >> 2  == -2       (arithmetic shift, toward -inf)

  The strength_reduce pass runs before typechecking and the AST Node
  has no per-node type information, so signedness cannot be proved
  at this stage. The only safe rule is to skip the `/` -> `>>`
  rewrite entirely. `*` -> `<<` is retained because
  `x * 2^k == x << k` (mod 2^n) is true under 2's-complement wrap
  for both signed and unsigned operands.

  Backends are free to perform the same lowering later, after
  typechecking, where signedness is known and a guarded
  unsigned-only path can be selected.

Tests:
- strength_reduce_does_not_lower_division_w73: AST for `return x / 4`
  after the pass keeps `extra_op = "/"` with literal `4`, and
  `stats.strengths_reduced == 0`.
- strength_reduce_still_lowers_multiplication_w73: AST for
  `return x * 8` after the pass has `extra_op = "<<"` with literal
  `3` (the shift count), and `stats.strengths_reduced == 1`.

Full suite: 1407 pass; 6 pre-existing master failures unrelated to
this change (test_verilog_cast_no_as_keyword, two jwt tests,
test_encode_decode, full_adder_uses_two_half_adders_and_or_combine,
trit_full_adder).

Status: PROVEN -- regression tests pin both the corrected behaviour
(division skipped) and the preserved one (multiplication still lowered).

Closes #949

Co-authored-by: Perplexity Computer <admin@t27.ai>
…W74) (#1016)

The optimizer DCE pass dropped every typed uninitialized StmtLocal
unconditionally, including locals that were assigned to and read by
subsequent statements in the same block. The downstream emitters then
referenced an undeclared name.

Build a per-block reference set (reads via ExprIdentifier + assign LHS
names) before the retain step and keep any uninit local whose name is
in that set. The genuinely-dead case still gets removed.

Two regression tests cover the keep paths (assign+read, read only).

Closes #950

Co-authored-by: Perplexity Computer <admin@t27.ai>
…er (#1018)

Add specs/numeric/lucas_accumulator.t27 capturing the F1 leg of the
GoldenFloat breadth-as-moat bet: phi^(2n) + phi^(-2n) = L_(2n) (integer
Lucas), the basis for an integer-backed, Lucas-exact phi-scaled
accumulator with no hardware half-type dependency. 9 tests, 3 invariants,
1 bench; parse + typecheck clean; sealed (all 5 hashes match). Verified to
60 decimal digits with mpmath (max residual 7.1e-56).

Add ledger row FL-004 (CONJECTURAL / [Open conjecture]) for the
breadth-as-moat claim: the advantage is breadth / toolchain-coherence,
NOT per-rung accuracy and NOT base-uniqueness. Fpath names takum
(arXiv:2412.20273) and the posit es-schedule control. F1 verifies the
arithmetic, never the moat.

L5 anchor phi^2 + phi^-2 = 3 = L_2. L6 SSOT (gf16, conformance) untouched.

Closes #1017

Co-authored-by: Perplexity Computer <computer@perplexity.ai>
…ix (#1020)

Add specs/numeric/posit_ladder_control.t27, the F3 control for the
GoldenFloat breadth-as-moat bet (FL-004). Models the posit ladder with
BOTH published exponent-size schedules so the comparison is faithful, not
a strawman: pre-standard es=0/1/2/3/4 at 8/16/32/64/128 (de Dinechin et
al. 2019) and the ratified-2022 fixed es=2 for all widths (Posit Standard
2022). Encodes useed=2^(2^es), best-case fraction bits, and the structural
contrast (posit's split is data-dependent regime run-length; GoldenFloat
fixes it via e=round((N-1)/phi^2)). 5 tests, 2 invariants, 1 bench;
parse+typecheck clean; sealed.

Corrects a sourcing error in the FL-004 ledger row: the previous
"posit es-schedule 1/3/4/7/10" was wrong; replaced with the two
correctly-sourced schedules. The spec asserts no phi-superiority over
posit (that stays [Open conjecture]); it only encodes the control.

L5 anchor phi^2 + phi^-2 = 3. L6 SSOT untouched.

Closes #1019

Co-authored-by: Perplexity Computer <computer@perplexity.ai>
… comments (#1023)

Extend specs/numeric/goldenfloat_family.t27 from 7 rungs (GF4..GF32) to the
full 9-rung ladder by adding GF64 (S1 E24 M39, e=round(63/phi^2)=24, the rung
closest to 1/phi at |ratio-1/phi|=0.002649) and GF256 (S1 E97 M158,
e=round(255/phi^2)=97, |ratio-1/phi|=0.004110). Resize the registry [7]->[9];
update names_seen, format_count==9, avg=total/9.0, len()==9, and the last-index
invariant to [8]==GF256. Correct the best_phi_format test to GF64 (the old GF12
assertion was already wrong vs GF32). Add bit-count tests for GF64 and GF256.

Repair corrupted comments overwritten by a botched non-ASCII strip (monotonic
digit runs such as 1/143, 1/284 285 0.618, ordered by bits (4 286 32),
within 0.1 of 1/563) back to readable ASCII (1/phi, 4 .. 256).

[Verified] ladder arithmetic only (one rule, 9/9 field widths, mpmath 50 digit).
No quality claim added: the moat stays [Open conjecture] (FL-004); GF256 bias
stays [Open]. 27 tests / 11 invariants / 5 benches; sealed (5/5 match).
L6 untouched (gf16 SSOT and conformance JSON unchanged).

Closes #1022

Co-authored-by: Perplexity Computer <computer@perplexity.ai>
New specs/fpga/bpsk.t27 (ZeroDSP_BPSK): byte -> +/-1 BPSK serializer with a
Barker-13 preamble + an integer Barker-13 correlator + threshold frame sync.
Barker chips packed into one u16 const (no array lowering); correlator is an
unrolled 13-tap +/-1 sum; TX state as flat scalar vars. 12 tests / 4 invariants
mirror the Rust modem (peak==13, inversion==-13, sidelobes -5/+5, LSB-first
serialize, sync gate). parse/typecheck clean; lowers to Verilog/C/Rust/Zig; sealed.

Closes #1243

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@gHashTag

gHashTag commented Jul 4, 2026

Copy link
Copy Markdown
Owner Author

Superseded — closing without merge. This PR branched off an old master that was later REBASED, so it now conflicts. The same specs/fpga/bpsk.t27 (ZeroDSP_BPSK) was re-ported onto the current master and merged in #1250 (Closes #1245), and it is already present on master. Nothing here to merge; the modem spec is live. See tri-net#16 for the broader Rust->T27 port.

@gHashTag gHashTag closed this Jul 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Port trios-mesh BPSK modem core to a .t27 FPGA spec (TRI-NET radio PHY)

3 participants