fix(parser): const X = packed struct {} was emitted as parameter = packed - #3384
Merged
Conversation
… packed`
There is no KwPacked in this lexer -- `packed` arrives as an Ident, exactly like
`union` does. parse_const_decl handled `= struct {` and `= union(enum) {` but
not `= packed struct {`, so the declaration fell through to the generic
expression path and became a ConstDecl whose initializer started at the token
`packed`. The Verilog backend then rendered it as a scalar parameter:
parameter [31:0] Greeting = packed;
`packed` is not a value.
No spec in this repository declares one today -- `grep -rn '= packed struct'
--include='*.t27'` returns 0 -- which is why nothing caught it. That also means
this fix changes no corpus number in either direction, and I am not claiming one.
The damage is in the corpus snapshot the website vendors, which carries
specs/demos/hello_world.t27: the spec the Spec Explorer opens on, described as
showing "every part of the language", with that line live under its Verilog tab
on t27.ai.
A packed struct is the declaration that matters most to a hardware backend -- it
IS a bit layout -- so losing it to a keyword token is the worst-placed gap in
the emitter.
Packedness itself is deliberately NOT recorded on the node. Nothing downstream
reads it, and inventing a field no emitter consumes would look like support that
does not exist. The declaration now reaches the backends as a struct, which is
the part that was missing.
Because no spec exercises this, the two regression tests are the only thing
standing between the construct and a silent return. Verified by negative
control: with the new parser branch disabled, packed_struct_const_parses_as_a_
struct_declaration FAILS and the plain-struct test still passes. Full suite
1694 passed, 0 failed.
FROZEN_HASH resealed per FROZEN.md §5 / CANON.md M5; the digest was computed
with shasum and written by the shell, never transcribed.
Closes #3383
Contributor
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
Contributor
gHashTag
added a commit
to gHashTag/trinity-fpga
that referenced
this pull request
Sep 6, 2026
…the defect
A47. Competitor research, done through the browser after WebSearch failed in
two consecutive iterations. It placed the Chip tab BEHIND prior art: netlistsvg,
DigitalJS, d3-hwschematic and FEntwumS all render an elaborated netlist, ours
renders declared widths -- because our Verilog is module shells. On the other
axis, searching for published silicon-level format conformance returns our own
paper as the top hit. Behind on visualisation, alone on evidence.
Following that into the emitter: hello_world -- the spec the Spec Explorer
opens on -- emits `parameter [31:0] Greeting = packed;`. There is no KwPacked
in the lexer, so `packed` arrives as an Ident; parse_const_decl handles
`= struct {` and `= union(enum) {` but not `= packed struct {`.
gHashTag/t27#3384, closing #3383.
I first wrote that this was likely a major cause of the 315 yosys rejections,
then counted: zero specs on master declare it. The fix changes no corpus number
in either direction, and the commit and PR say so instead of leaving the
earlier framing standing.
Because nothing exercises the construct, the two regression tests are the whole
guard -- so they were checked against the defect: branch disabled, the packed
test fails and the plain one still passes. Suite 1694 passed, 0 failed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Both NOW gates refused the PR: every change to master must ADD a docs/now/ entry, and the local pre-commit hook only checks that an EXISTING entry is fresh, so it passed while CI did not. Two gates disagreeing about the same requirement is exactly what the second one exists to report, and it did. Closes #3383
Contributor
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
Contributor
PR DashboardGenerated at: 2026-09-06 12:13:49 UTC
Summary
Seal Status
|
gHashTag
added a commit
to gHashTag/trinity-fpga
that referenced
this pull request
Sep 6, 2026
gHashTag/t27#3384 merged as f5d8564ab, closing #3383. 38 checks pass, 0 fail, 0 pending -- including the Corpus ratchet, which agrees with the zero-specs finding rather than merely tolerating it. Two NOW gates refused the first push: every change to master must ADD a docs/now/ entry, while the local pre-commit hook only checks that an EXISTING entry is fresh. The hook passed and CI did not, and the second gate exists to report exactly that disagreement. t27.ai still shows the old line under hello_world's Verilog tab, because the website vendors an older corpus snapshot. Re-vendoring is the follow-up. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
gHashTag
added a commit
that referenced
this pull request
Sep 6, 2026
#3384) (#3385) There is no KwPacked in this lexer -- `packed` arrives as an Ident, exactly like `union` does. parse_const_decl handled `= struct {` and `= union(enum) {` but not `= packed struct {`, so the declaration fell through to the generic expression path and became a ConstDecl whose initializer started at that token. Cherry-picked from master (f5d8564). Master's corpus contains no `packed struct` at all, so master could not test the fix. THIS branch is where specs/demos/hello_world.t27 lives -- the spec the Spec Explorer opens on -- so it is the first place the fix could be verified end to end. The conflict was real and resolved by keeping both: the branch's `union(enum)` case occupies the slot the fix used on master, and both now sit side by side ahead of KwStruct. Measured on hello_world, same branch, same spec, only the parser differing. before: parameter [31:0] Greeting = packed; // struct reg [7:0] _length; // .length reg signed [7:0] _trit; // .trit after: // struct Greeting reg [7:0] greeting_length; // Greeting.length reg signed [7:0] greeting_trit; // Greeting.trit So the struct was already being emitted -- anonymously, because the declaration was a ConstDecl. The fix removes the bogus parameter and restores the name. WHAT IT DOES NOT DO, measured rather than assumed. yosys 0.63 synthesises both versions to 0 cells, 4 wires, 4 ports. It never rejected the old output either: it printed Lexer warning: The SystemVerilog keyword `packed' is not recognized unless read_verilog is called with -sv! and carried on. So this removes a warning and restores a lost name; it does not change synthesis, and it was never a cause of the corpus's yosys failures. I had speculated otherwise two iterations ago and am recording the refutation next to the fix rather than leaving the guess in a commit message. The module-shell / 0-LUT condition has a different root cause -- no hardware boundary -- which the `entry-points` service already measures at 387 specs. Suite green on this branch: 889 plus the per-crate suites, 0 failed. FROZEN_HASH resealed with a shasum-computed digest, never transcribed. Cargo.lock was left alone: `cargo build -p t27c` prunes ~1000 lines from it, which is a build artifact and not a change. Closes #3383
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
There is no
KwPackedin this lexer —packedarrives as anIdent, exactlylike
uniondoes.parse_const_declhandled= struct {and= union(enum) {but not
= packed struct {, so the declaration fell through to the genericexpression path and became a
ConstDeclwhose initializer started at the tokenpacked.The Verilog backend then rendered it as a scalar parameter:
packedis not a value.Scope, stated plainly
No spec in this repository declares one today —
grep -rn '= packed struct' --include='*.t27'returns 0. That is why nothing caught it, and it also meansthis fix changes no corpus number in either direction. I am not claiming one.
The damage is in the corpus snapshot the website vendors, which carries
specs/demos/hello_world.t27— the spec the Spec Explorer opens on, described asshowing "every part of the language" — with that line live under its Verilog tab
on t27.ai.
A packed struct is the declaration that matters most to a hardware backend: it
is a bit layout. Losing it to a keyword token is the worst-placed gap in the
emitter.
What this deliberately does not do
Packedness itself is not recorded on the node. Nothing downstream reads it,
and inventing a field no emitter consumes would look like support that does not
exist. The declaration now reaches the backends as a struct, which is the part
that was missing.
Verification
Because no spec exercises this construct, the two regression tests are the only
thing standing between it and a silent return — so they were checked against the
defect, not just run:
packed_struct_const_parses_as_a_struct_declarationFAILS, plain-struct test still passesFROZEN_HASHresealed per FROZEN.md §5 / CANON.md M5. The digest was computedwith
shasumand written by the shell — never transcribed by hand.Closes #3383