Skip to content

wave-36f: t27c add gen-interrupt-controller + gen-bitnet-engine-top, closing BitNet HLS at 9/9 (R-BN-6, Closes #770)#771

Merged
gHashTag merged 1 commit into
masterfrom
wave-36f/irq-engine-top
May 23, 2026
Merged

wave-36f: t27c add gen-interrupt-controller + gen-bitnet-engine-top, closing BitNet HLS at 9/9 (R-BN-6, Closes #770)#771
gHashTag merged 1 commit into
masterfrom
wave-36f/irq-engine-top

Conversation

@gHashTag
Copy link
Copy Markdown
Owner

Closes #770

This wave (R-BN-6) closes the BitNet HLS pipeline at 9/9 modules by porting the last two vibee-lang emitters:

  • writeInterruptController (vibee-lang src/vibeec/verilog_codegen.zig lines 1550-1590) -- async completion signalling for the host CPU.
  • writeBitNetEngineTop (vibee-lang src/vibeec/verilog_codegen.zig lines 1667-1725) -- top-level wrapper that instantiates multilayer_sequencer + double_buffer_ctrl and adds a 32-bit cycle counter.

After this PR, t27c can emit every block in the BitNet HLS pipeline from the upstream vibee-lang spec.

What changed

  • bootstrap/src/bitnet_irq.rs (new, ~200 lines): build_interrupt_controller(module_name) pure string emitter + Verilog-ident validator with safe fallback + 11 inline unit tests.
  • bootstrap/src/bitnet_top.rs (new, ~265 lines): build_bitnet_engine_top(module_name) pure string emitter + Verilog-ident validator with safe fallback + 14 inline unit tests.
  • bootstrap/src/main.rs (additive only): mod bitnet_irq; and mod bitnet_top;, two new Commands::Gen* variants, two new run_gen_* helpers routed through the shared write_verilog_to_output(...), dispatch in both HTTP-server and CLI match arms.
  • bootstrap/tests/bitnet_irq.rs (new, 16 integration tests) and bootstrap/tests/bitnet_top.rs (new, 17 integration tests), both via CARGO_BIN_EXE_t27c, no tempfile crate -- both use std::env::temp_dir().
  • docs/NOW.md prepended with the W36f section.

CLI surface

t27c gen-interrupt-controller --module-name irq_ctrl
t27c gen-interrupt-controller --module-name irq_ctrl --output /tmp/irq.sv
t27c gen-bitnet-engine-top --module-name bitnet_engine_top
t27c gen-bitnet-engine-top --module-name engine_top_v1 --output /tmp/top.sv

Invalid Verilog identifiers ("", "9bad", "has space", "dash-name", ...) fall back to the default module name in both subcommands.

Sample output (interrupt_controller)

// ===========================================================================
// INTERRUPT CONTROLLER - Async completion signaling
// ===========================================================================
// Generated by t27c gen-interrupt-controller (Wave 36f, R-BN-6).
// Three sticky IRQ sources (inference_done, dma_done, error)
// gated by a 3-bit irq_enable mask. status_read clears latches.

module irq_ctrl (
    input  wire        clk,
    input  wire        rst_n,
    // Interrupt sources
    input  wire        inference_done,
    input  wire        dma_done,
    input  wire        error,
    // Interrupt enable
    input  wire [2:0]  irq_enable,
    // Status (active-high, clear on read)
    output reg  [2:0]  irq_status,
    input  wire        status_read,
    // Interrupt output
    output wire        irq_out
);

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) irq_status <= 3'b000;
        else begin
            if (inference_done) irq_status[0] <= 1'b1;
            if (dma_done)       irq_status[1] <= 1'b1;
            if (error)          irq_status[2] <= 1'b1;
            if (status_read)    irq_status     <= 3'b000;  // Clear on read
        end
    end

    assign irq_out = |(irq_status & irq_enable);

endmodule

Sample output (bitnet_engine_top, excerpt)

module bitnet_engine_top (
    input  wire        clk,
    input  wire        rst_n,
    input  wire        start,
    input  wire [5:0]  num_layers,
    input  wire [15:0] neurons_per_layer,
    input  wire [7:0]  chunks_per_neuron,
    input  wire signed [15:0] threshold,
    // External memory interface (simplified)
    output wire [31:0] mem_addr,
    output wire        mem_rd_en,
    input  wire [63:0] mem_rd_data,
    input  wire        mem_rd_valid,
    // Status
    output wire        busy,
    output wire        done,
    output wire [31:0] cycle_count
);
    // Multi-layer sequencer
    wire [5:0] current_layer;
    wire layer_start, layer_done, start_prefetch, prefetch_done;
    multilayer_sequencer seq (
        .clk(clk), .rst_n(rst_n), .start(start), .num_layers(num_layers),
        .layer_done(layer_done), .prefetch_done(prefetch_done),
        .current_layer(current_layer), .layer_start(layer_start),
        .start_prefetch(start_prefetch), .inference_done(done)
    );
    ...
    reg [31:0] cycles;
    always @(posedge clk or negedge rst_n)
        if (!rst_n) cycles <= 32'd0;
        else if (start) cycles <= 32'd0;
        else if (busy) cycles <= cycles + 32'd1;
    assign cycle_count = cycles;
    assign busy = (current_layer != 6'd0) || layer_start;
    ...
endmodule

Constitutional gates (L1-L7)

  • L1 TRACEABILITY: Closes #770 in title + body + commit message
  • L2 SCOPE: edits confined to bootstrap/src/{bitnet_irq.rs,bitnet_top.rs,main.rs}, bootstrap/tests/bitnet_{irq,top}.rs, docs/NOW.md. Zero changes under gen/, coq/, trios-coq/, proofs/, specs/, conformance/, architecture/, rings/, root Cargo.toml.
  • L3 ASCII: source ASCII-only, English doc-comments, emitted Verilog ASCII-only (asserted by tests irq_output_is_pure_ascii and top_output_is_pure_ascii).
  • L4 TESTS: 16 + 17 = 33 new integration tests + 11 + 14 = 25 inline unit tests = 58 new tests. Full regression sweep (138 tests across 13 existing suites) re-runs green. Total 171/171.
  • L5 KERNEL UNTOUCHED: numeric kernel and trinity invariant phi^2 + 1/phi^2 = 3 not touched -- both emitters are control-plane / structural-wrapper only.
  • L6 SPEC FROZEN: zero spec / kernel changes.
  • *L7 NO NEW .sh: no shell scripts added.

Tests

  • W36f integration (irq): 16 / 16 passed (cargo test -p t27c --release --test bitnet_irq).
  • W36f integration (top): 17 / 17 passed (cargo test -p t27c --release --test bitnet_top).
  • W36f inline unit: 25 / 25 (11 in bitnet_irq.rs + 14 in bitnet_top.rs; compiled and embedded; verified locally).
  • Regression sweep across 13 existing suites: behavior_sva 8, bitnet_axi 18, bitnet_buffers 22, bitnet_dma 22, bitnet_pipeline 20, phi_selfcheck 11, trit_stdlib 14, verilog_array_literal_expr 2, verilog_const_array 2, verilog_initial_decl 2, verilog_r_si_1 2, verilog_translate_off 2, weight_bram 13 = 138 / 138.
  • Total: 171 / 171.

Source attribution

Ported from gHashTag/vibee-lang, file src/vibeec/verilog_codegen.zig, functions writeInterruptController (lines 1550-1590) and writeBitNetEngineTop (lines 1667-1725). Original author: Dmitrii Vasilev (@gHashTag). The only deliberate divergence from the upstream emitter is two assign mem_addr = 32'd0; assign mem_rd_en = 1'b0; tie-offs in the engine-top wrapper to prevent X-driver inference at the composition layer (the upstream emitter relies on a higher assembly to drive these). Everything else is bit-level equivalent.

Known orthogonal CI failures

The fpga-formal, fpga-synthesis-arty, and fpga-bitstream jobs are expected to fail on every PR until their upstream toolchains are wired in -- they are not gated by anything this wave changes. All other required gates (check, coverage, fpga-conformance, fpga-smoke, fpga-lint, fpga-synthesis, phi-loop-check, Check L1 TRACEABILITY, NotebookLM, validate, pr-dashboard) are expected to pass.

Roadmap

BitNet HLS pipeline closes at 9 / 9 modules: weight_bram (W36a), pipeline_stage2_compute + layer_sequencer (W36b), double_buffer_ctrl + weight_prefetch_ctrl (W36c), axi_lite_slave (W36d), dma_controller (W36e), and now interrupt_controller + bitnet_engine_top (W36f).

Next program phase:

  • W37 -- richer behavior-DSL (multi-clause antecedents, ##N delay-clock, s_eventually strong-fairness). Bootstrap-scoped, tested through behavior_sva.
  • W38+ -- wire stdlib + behavior emitter into existing gen_verilog_* spec emits. First wave needing L2 / L6 reconsideration.
  • Beyond W38+ -- host-side Rust driver crate that talks to the AXI-Lite CSR aperture (W36d) plus an IRQ-handler harness around the W36f interrupt_controller.

@github-actions
Copy link
Copy Markdown

📓 NotebookLM Notebook linked to this PR

This notebook contains session context, decisions, and artifacts for this work.

@github-actions
Copy link
Copy Markdown

PR Dashboard

Generated at: 2026-05-23 13:35:22 UTC

Summary

Status Count
Total Open PRs 22
PRs with Failing Checks 20
PRs with All Checks Green 2
READY 1
FAILING 20
PENDING 0

@gHashTag gHashTag merged commit 65d0738 into master May 23, 2026
20 of 23 checks passed
@gHashTag gHashTag deleted the wave-36f/irq-engine-top branch May 23, 2026 13:39
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.

Wave 36f (R-BN-6): t27c add gen-interrupt-controller + gen-bitnet-engine-top to close BitNet HLS (9/9)

1 participant