Skip to content

gen-verilog emits a range literal where a bound belongs: for (i = 0; i < (0 .. 1000); …) -- 38 specs, and 10 in synthesizable RTL #2997

Description

@gHashTag

A range literal reaches emitted Verilog: for (i = 0; i < (0 .. 1000); i = i + 1)

Largest single class among the 410 specs iverilog rejects. Found by classifying
every one of those 410 by the construct on the offending line rather than by
the diagnostic text.

The construct, and the three backends beside it

specs/base/ops.t27:1285 — for (0..1000) |_| { … }

/* gen-c        */  for (int __t27_i = 0; __t27_i < 1000; __t27_i++) {
/* gen          */  for (0 .. 1000) |_| {                      // native Zig
/* gen-verilog-for-simulation */
                    for (i = 0; i < (0 .. 1000); i = i + 1) begin

C takes the range's endpoint as the bound. Zig writes the range because Zig has
one. Verilog emits the range expression itself where a bound belongs, and
iverilog answers syntax error.

The C half of this is #2849 — "gen_c_for_stmt opened with 'C doesn't have
for-each natively; emit as a for loop with index' and then emitted a comment,
{, the body, }"
, which moved real loops 15 → 309. The repair did not
travel to Verilog
, which emits the loop skeleton correctly and puts the range
in the bound.

Population, both paths, measured per spec

  gen-verilog                 (synthesizable)   10 specs
  gen-verilog-for-simulation                    38 specs

So it is not simulation-only: ten synthesizable modules carry (0 .. N) in
emitted RTL today. The simulation path carries more because test and bench bodies
are only emitted there.

It is not only the loop bound

The same literal reaches slice positions, where it is a different repair:

specs/igla/race/backend.t27       left   = expr[(0 .. idx)];
specs/memory/semantic_search.t27  top_k  = result[(0 .. 0)];
specs/vsa/similarity_search.t27   get_vector = $signed(dummy[(((0 .. 10)) * 32) +: 32]);
specs/provider/stream.t27         … (line[(0 .. SSE_DATA_PREFIX_len)]) …
specs/queen/brain/summaries.t27   summary = aggregate_episodes(episodes[(0 .. count)], …);

Verilog spells a part-select [msb:lsb] or [base +: width]. A range in an
index is a slice; a range in a for bound is an endpoint. Two shapes, two
repairs
, and a fix that only teaches the loop leaves five specs where they are.

Not established

  • Whether C and Zig lower the slice form correctly — I compared the three
    backends on the loop form only.
  • Whether repairing this alone makes any of the 38 elaborate. Each carries other
    first-errors too; this is the first diagnostic for 38, not the only one.

Refs #2849, #2987

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