Skip to content

gen-verilog: break lowers to disable fork; and continue to a comment -- 17 no-ops in 8 files, and no fork exists anywhere in the corpus #2988

Description

@gHashTag

break lowers to disable fork;, and there is no fork anywhere in the generated corpus

bootstrap/src/compiler.rs:16230:

NodeKind::StmtBreak => {
    self.write_line("disable fork;");
}
NodeKind::StmtContinue => {
    self.write_line("/* continue */;");
}

In Verilog, disable fork terminates processes spawned by a fork in the
current scope. Measured over the 581 .v files gen-verilog produces from the
650 specs under specs/:

$ grep -c 'disable fork;' *.v | grep -v ':0$'
specs_ar_asp_solver.v:5   specs_compiler_lexer.v:4
specs_math_phi_universal_attractor.v:2   specs_base_types.v:1
specs_fpga_testbench_mac_tb.v:1   specs_sync_schema.v:1
-> 6 files, 14 sites

$ grep -h '\bfork\b' *.v | sort -u
disable fork;

The only occurrence of the token fork in the entire generated corpus is
inside disable fork; itself.
All 14 are no-ops: the loop runs to completion
and later iterations overwrite whatever the break was meant to preserve.
iverilog -g2012 accepts them silently.

continue is the same class: /* continue */; is a comment plus an empty
statement. 1 surviving site (specs_nn_attention.v).

Why it is not a one-line fix, which is the part worth writing down

The obvious repair -- disable __t27_loop_N; -- is available for one branch of
one of the three loop forms
. __t27_loop_{n} is emitted at compiler.rs:16377,
inside gen_verilog_while_stmt, and only when while_literal_bound returns
Some. gen_verilog_for_stmt (16494), gen_verilog_for_range_stmt (16533) and
the unbounded while branch emit no named block at all, and
write_line("disable fork;") has no knowledge of which loop encloses it.

So the repair is: a name stack on the codegen, a named block on every loop, and
disable <top of stack>. continue has no ready target even then -- it needs a
per-iteration block, which does not exist.

A hand-patch of the OUTPUT does fix it: substituting disable __t27_loop_N; in
a generated file and re-running the same testbench makes Verilog agree with C,
Rust, Zig and hand arithmetic at all 12 measured points, with one line changed.
That is a control on the artifact, not a repair available in the emitter, and
the two should not be quoted as one.

The artifact is committed

specs/fpga/testbench/mac_tb.v carries the defective lowering in the tree; its
own header says it was produced by t27c gen-verilog.

Found by pointing icarus-simulate at the corpus -- see #2987, which is why
nothing has ever reported this.

Activity

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