Skip to content

gen-verilog: a function brought in by use is called but never defined, and gen-verilog exits 0 #8769

Open

Description

@gHashTag

Defect under the self-host epic (see #5980). Found while trying to generate an on-die self-test for specs/queen/actors_hw.t27, the FPGA lane of gHashTag/trios#1763.

Problem

t27c gen-verilog lowers only the functions declared in the spec it is given. A function the spec brings in with use is called in the emitted RTL, but its body is never emitted, and gen-verilog exits 0. yosys then refuses the file. The Zig path compiles and tests the same spec.

So a spec cannot reuse another spec's logic in hardware. The only ways around it are to copy the bodies, which the duplicate-bodies gate rejects, or to instantiate the other module, which gen-verilog cannot do either (see #8660).

Minimal repro (t27c 0.5.2, master c31c059)

specs/xa/lib.t27:

// SPDX-License-Identifier: Apache-2.0
module XaLib;
pub fn twice(x: u8) -> u8 { return x + x; }
test twice_works { assert_eq(twice(3), 6); }

specs/xa/user.t27:

// SPDX-License-Identifier: Apache-2.0
module XaUser;
use xa::lib::twice;
var out : u8 = 0
fn on_clock(v: u8) { out = twice(v); }
test uses_twice { out = 0; on_clock(4); assert_eq(out, 8); }
command result
t27c gen-verilog specs/xa/user.t27 exit 0. The clocked block reads out <= twice(v);. The only function in the file is __mul_noop.
yosys -p "read_verilog user.v; synth_xilinx -family xc7 -top XaUser" (0.63) user.v:55: ERROR: Can't resolve function name '\twice'.
t27c test-report specs/xa/user.t27 --specs-dir specs 1 test, 0 FAIL, 1 runtime assert

Acceptance

What it blocks

The lane needs an on-die self-test of the actor engine: a generated module that runs actors_hw.t27's test vectors through its hw_ decisions and reports a verdict over JTAG. If used functions were lowered, that module could call the decisions directly. Without it, the module has to instantiate QueenActorsHw, which needs module instances (#8660). The JTAG primitives (STARTUPE2, BUFG, BSCANE2) need #8660 on either route.

🤖 Generated with Claude Code

Boundary

  • specs/queen/actors_hw.t27
  • specs/xa/lib.t27
  • specs/xa/user.t27

Activity

  1. tri-claw commented on Oct 11, 2026

    @tri-claw

    The Queen cannot take this issue yet. A bee starts only on an issue whose body has every section below, and this one lacks:

    • missing: ## Boundary -- list every file this task may touch, one per line (- specs/x.t27); without it the Queen reserves nothing and no bee can take the issue
    • missing: ## User Scenarios -- at least one Given/When/Then scenario
    • missing: ## Requirements -- numbered obligations, FR-001: ... MUST ...

    She tried to write them 2 times and could not (last: refused: refused paths: specs/xa/lib.t27, specs/xa/user.t27). Add them and the next round takes it. The rule is specs/policy/issue_shape.t27.

  2. added
    needs-boundaryNo '## Boundary' section, so the Queen can reserve nothing for it and no bee can take it
    and removed
    needs-boundaryNo '## Boundary' section, so the Queen can reserve nothing for it and no bee can take it
    on Oct 11, 2026
  3. dmitrii-f-t27 commented on Oct 15, 2026

    @dmitrii-f-t27
    Contributor

    Technical evidence for this issue, from work on PR #9636 and a local prototype. No approval of any code is requested.

    1. The defect is real and silent. gen-verilog of the unchanged specs/port/scripts/gen_w709.t27 defines function indent, elem_x, elem_y, build_level, build_tree and the rest. gen-verilog of specs/port/scripts/gen_w698.t27 after its helpers moved behind use port::scripts::gen_w_tree; defines only function generate; every helper definition is gone and the test names survive as comments. The command exits 0.

    2. It produced a false green on spec(port): share tree helpers across eight gen_w ports (Closes #9633) #9636. The corpus ratchet reported an unexpected pass for gen_w698 [gen-verilog] and the suite expectation was lowered 83 to 82. A clean local suite ratchet (82 of 82, unexpected fail 0 and pass 0) does not detect the lost definitions. That removal is conditional and unjustified until this issue is fixed.

    3. A local partial candidate (worktree codex/verilog-use-8769, uncommitted, not published) passes the positive case: user.t27 importing twice and biased gets twice, biased, wrap_add and the library BIAS 3; iverilog exits 0 and yosys proc/opt/check -assert exits 0 with 0 problems. Before it, iverilog exited 2 and yosys said Can't resolve function twice.

    4. The candidate is wrong in three ways:

    • Negative capture: an importer that declares its own BIAS = 9 captures the library's BIAS = 3. A direct test biased(4) == 7 prints PROBE 13, FAILED, expected 7 got 13 (vvp exits 0 with FAILED, so read the output, not the exit code).
    • Central routes are not fixed: icarus-simulate user still exits 1 (unknown twice, biased, on_clock), and compile_verilog_for_simulation_at and the path-less compile_verilog used by suite.rs still get the raw source, so a change only in the main.rs handler leaves the corpus and seal paths broken.
    • Foreign budget: the real foreign-budget hook denies the staged main.rs (16 added, 3 deleted, +13). No label or exception overrides that budget, so owner approval alone would not make this diff acceptable.

    A correct fix needs the central compile paths, a negative proof for same-name capture, and no growth of hand-written Rust debt. The existing base exceptions for main.rs (#6509, #6446) are narrow and are not approval for this change.

    Dmitrii Fedorov (@dmitrii-f-t27)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions