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 top
src/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 Wrapper
scala 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 commit
Full 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 #465 did not cover.
DFHDL#454 — @targetName rejected on a top-level design class, which forecloses renaming
the class while keeping the emitted module name top.
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 stay top to 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
Context
DFHDL#458/dfhdl_by_agents#82documented that a design class namedtopcollides withDFHDL's internal
@topannotation, producing an unhelpful "Cyclic reference involving classtop" at the declaration site.
#458says this was "Fixed in #465".Translating
HOG_fpga/src/top_wrapper.v(runhog-1), which instantiates a child module alsonamed
top(HOG_fpga/src/top.v), I confirmed the declaration-site fix:class top extends EDDesignnow compiles fine on its own against current HEAD. But a second, distinctcollision remains when another file references it with
new top(...)— with a completelydifferent, and equally unhelpful, error.
Minimal reproduction (verified against
0.22.0+106-847a1a10-SNAPSHOT)src/top.scala:src/Wrapper.scala:Full verbatim error text
import dfhdl.*inWrapper.scalais bringingdfhdl.top(the built-in annotation class,constructor
(genMain: Boolean)) into scope, and it wins name resolution over the siblingtop-level class
topdefined intop.scalain 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
topsuddenly has agenMain: Booleanconstructorparameter and no
WIDTHparameter, 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)— thatdoes not appear anywhere in the 6-line
top.scalaabove, with no indication that theidentifier 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 DFHDLrequires every top-level design to declare a
genMain: Booleanparameter — neither is true.Only recognizing
dfhdl.top does not have a parameter WIDTHas a reference to a differenttype 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
topto the local class:With only this one-line change to
Wrapper.scala's import, the same file compiles cleanly andelaborates correctly.
Suggested clearer message
Since the plugin's
TopAnnotPhasealready knows about@top/dfhdl.top, and the position is anew <ident>(...)call, it should be feasible to detect "the resolved type isdfhdl.top, buta same-named user design class also exists in this compilation," and emit something like:
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 renamingthe class while keeping the emitted module name
top.dfhdl_by_agents#82— the knowledge-gap side; its documented workaround ("rename the classto e.g.
hog_top") is now the wrong advice for anyone doing a literal translation where thegenerated module name must stay
topto match the gold Verilog — the shadow-import above isthe workaround that preserves the class name. Filing a follow-up knowledge-gap ticket
separately.
Version
0.22.0+106-847a1a10-SNAPSHOT