Repository navigation
[Bug] Referencing a sibling design class named top still fails post-#465, with a new, unrelated-looking error #482
Description
Context
DFHDL#458 / dfhdl_by_agents#82 documented that a design class named top collides with
DFHDL's internal @top annotation, producing an unhelpful "Cyclic reference involving class
top" at the declaration site. #458 says this was "Fixed in #465".
Translating HOG_fpga/src/top_wrapper.v (run hog-1), which instantiates a child module also
named top (HOG_fpga/src/top.v), I confirmed the declaration-site fix: class top extends EDDesign now compiles fine on its own against current HEAD. But a second, distinct
collision remains when another file references it with new top(...) — with a completely
different, and equally unhelpful, error.
Minimal reproduction (verified against 0.22.0+106-847a1a10-SNAPSHOT)
src/top.scala:
import dfhdl.*
class top(
val WIDTH: Int <> CONST = 8
) extends EDDesign:
val clk, rst = Bit <> IN
val din = Bits(WIDTH) <> IN
val dout = Bits(WIDTH) <> OUT
dout <> din
end topsrc/Wrapper.scala:
import dfhdl.*
class Wrapper extends EDDesign:
val clk, rst = Bit <> IN
val din = Bits(8) <> IN
val dout = Bits(8) <> OUT
val u_top = new top(WIDTH = 8)
u_top.clk <> clk
u_top.rst <> rst
u_top.din <> din
u_top.dout <> dout
end Wrapperscala run src/ --scala 3.8.4 \
--dep "io.github.dfianthdl::dfhdl::$V" \
--compiler-plugin "io.github.dfianthdl:::dfhdl-plugin::$V" \
-O -deprecation -M Wrapper -- --nocache commitFull verbatim error text
[error] ./src/Wrapper.scala:8:23
[error] constructor top in class top: (genMain: Boolean)
[error] (using annot: dfhdl.internals.AnnotatedWith[dfhdl.top, Any])
[error] (using
[error] elaborationOptions: dfhdl.options.ElaborationOptions.Defaults[annot.Out],
[error] compilerOptions: dfhdl.options.CompilerOptions.Defaults[annot.Out],
[error] printerOptions: dfhdl.options.PrinterOptions.Defaults[annot.Out],
[error] linterOptions: dfhdl.options.LinterOptions.Defaults[annot.Out],
[error] simulatorOptions: dfhdl.options.SimulatorOptions.Defaults[annot.Out],
[error] appOptions: dfhdl.options.AppOptions.Defaults[annot.Out],
[error] builderOptions: dfhdl.options.BuilderOptions.Defaults[annot.Out],
[error] programmerOptions: dfhdl.options.ProgrammerOptions.Defaults[annot.Out]):
[error] dfhdl.top does not have a parameter WIDTH
[error] val u_top = new top(WIDTH = 8)
[error] ^^^^^^^^^^
[error] ./src/Wrapper.scala:8:15
[error] missing argument for parameter genMain of constructor top in class top: (genMain: Boolean)
[error] (using annot: dfhdl.internals.AnnotatedWith[dfhdl.top, Any])
[error] ... (same using clauses as above)
[error] dfhdl.top
[error] val u_top = new top(WIDTH = 8)
[error] ^^^^^^^^^^^^^^^^^^
Warning: 2 errors found
import dfhdl.* in Wrapper.scala is bringing dfhdl.top (the built-in annotation class,
constructor (genMain: Boolean)) into scope, and it wins name resolution over the sibling
top-level class top defined in top.scala in the same project. Nothing in the message says
"name collision" or mentions the annotation by name in a way that explains what happened;
it reads as if the user's own class top suddenly has a genMain: Boolean constructor
parameter and no WIDTH parameter, which is not true of any code the user wrote.
Where I expected the error to point vs. where it pointed
Expected either a normal successful compile (the class and its usage are both syntactically
and semantically correct DFHDL), or, if this is genuinely a reserved-name collision, a message
saying so explicitly. Instead it reports a constructor signature — (genMain: Boolean) — that
does not appear anywhere in the 6-line top.scala above, with no indication that the
identifier resolved to a completely different, DFHDL-internal top.
What I thought the message meant vs. what was actually wrong
First reading suggested class top's own constructor was somehow malformed or that DFHDL
requires every top-level design to declare a genMain: Boolean parameter — neither is true.
Only recognizing dfhdl.top does not have a parameter WIDTH as a reference to a different
type than the one just declared revealed the actual cause: the wildcard import silently
shadows a same-named sibling design.
Confirmed fix
Shadowing the built-in annotation out of the wildcard import resolves top to the local class:
import dfhdl.{top => _, *}With only this one-line change to Wrapper.scala's import, the same file compiles cleanly and
elaborates correctly.
Suggested clearer message
Since the plugin's TopAnnotPhase already knows about @top/dfhdl.top, and the position is a
new <ident>(...) call, it should be feasible to detect "the resolved type is dfhdl.top, but
a same-named user design class also exists in this compilation," and emit something like:
error: `top` resolved to the built-in `dfhdl.top` annotation, not your design class `top`
(defined in top.scala). The wildcard import `import dfhdl.*` gives the built-in name priority.
Shadow it explicitly: `import dfhdl.{top => _, *}`.
Cross-references
DFHDL#458— the declaration-site "Cyclic reference" variant, closed as fixed by#465.
This ticket is the residual use-site variant that#465did not cover.DFHDL#454—@targetNamerejected on a top-level design class, which forecloses renaming
the class while keeping the emitted module nametop.dfhdl_by_agents#82— the knowledge-gap side; its documented workaround ("rename the class
to e.g.hog_top") is now the wrong advice for anyone doing a literal translation where the
generated module name must staytopto match the gold Verilog — the shadow-import above is
the workaround that preserves the class name. Filing a follow-up knowledge-gap ticket
separately.
Version
0.22.0+106-847a1a10-SNAPSHOT
Activity
core+lib+plugin: the `@top` annotation moves out of the `dfhdl` wildc…
benchmarks: pick up the `@top` import the annotation's move requires