Translating demos/mandelbrot/mandelbrot.sv from projf-explore
(https://github.com/projf/projf-explore) to DFHDL. The Verilog module has a
parameter list where one parameter's default depends on an earlier one:
module mandelbrot #(
parameter FP_WIDTH=25,
parameter FP_INT=4,
parameter ITER_MAX=255,
parameter ITERW=$clog2(ITER_MAX+1) // depends on ITER_MAX
) ( ... );
A single DFHDL parameter list does not allow a later parameter's default to
reference an earlier one by simple name (confirmed this is also true in plain
Scala 3, not DFHDL-specific: class Probe2(val a: Int = 5, val b: Int = a + 1)
fails to compile with Not found: a). The standard Scala workaround for this
is a second (curried) parameter list, e.g. class Foo(a: Int)(b: Int = a + 1).
That workaround crashes the DFHDL compiler. The crash reproduces even with a
default that does not reference the first list at all — any DFHDL design
class with two curried parameter lists where the second list has a default
value crashes.
Minimal reproduction
import dfhdl.*
// two curried DFHDL param lists, default value on 2nd list param,
// no cross-reference between the lists
class Probe7(val A: Int <> CONST = 4)(val B: Int <> CONST = 8) extends EDDesign:
val o = UInt(B) <> OUT
o <> 0
Run with:
scala run src/ --scala 3.8.4 \
--dep "io.github.dfianthdl::dfhdl::$V" \
--compiler-plugin "io.github.dfianthdl:::dfhdl-plugin::$V" \
-O -deprecation -M Probe7 -- --nocache commit
Expected behavior
Either a successful compile (curried parameter lists are ordinary Scala and
should be supported), or a clear DFHDL-level diagnostic saying curried
parameter lists / defaults in a non-first parameter list are unsupported.
Actual behavior
Internal compiler crash (not a normal DFHDL elaboration error):
[90mCompiling project (Scala 3.8.4, JVM (25))[0m
[90mError compiling project (Scala 3.8.4, JVM (25))[0m
Error: java.lang.AssertionError: assertion failed: bad adapt for Probe7.$lessinit$greater$default$2: (A: dfhdl.core.DFVal): dfhdl.core.DFVal
at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:10)
at dotty.tools.dotc.transform.Erasure$Boxing$.adaptToType(Erasure.scala:389)
at dotty.tools.dotc.transform.Erasure$Typer.adapt(Erasure.scala:1059)
at dotty.tools.dotc.typer.Typer.typed(Typer.scala:4017)
...
The assertion message oddly names the first list's parameter (A) even
though the crash is triggered by the second list's default value having any
default at all (tested with = 8, a literal with no reference to A) — this
mislabeling may itself be a clue to the root cause (something in how the
plugin synthesizes/threads the $default$N accessor across parameter-list
boundaries).
Also reproduces with the original motivating case, where the second list's
default genuinely references the first list's parameter:
import dfhdl.*
class Probe4(val ITER_MAX: Int <> CONST = 255)(
val ITERW: Int <> CONST = clog2(ITER_MAX + 1)
) extends EDDesign:
val o = UInt(ITERW) <> OUT
o <> 0
```//same crash, message: "bad adapt for Probe4.$lessinit$greater$default$2: (ITER_MAX: dfhdl.core.DFVal): dfhdl.core.DFVal"
Two curried parameter lists with **no** default value on the second list
compile fine:
```scala
import dfhdl.*
class Probe6(val A: Int <> CONST)(val B: Int <> CONST) extends EDDesign:
val o = UInt(B) <> OUT
o <> 0
This one compiles successfully (fails only later, expectedly, because no
AppMode default exists for a class requiring constructor args to run
without CLI arguments).
DFHDL version
v0.22.0+39-03afffb1-SNAPSHOT
Workaround used
Converted the dependent parameter into a plain derived val in the design
body instead of a constructor parameter (losing external overridability of
that one parameter, which was the only way to keep the translation
compiling):
class mandelbrot(
val FP_WIDTH: Int <> CONST = 25,
val FP_INT: Int <> CONST = 4,
val ITER_MAX: Int <> CONST = 255
) extends EDDesign:
val ITERW = clog2(ITER_MAX + 1)
...
Translating
demos/mandelbrot/mandelbrot.svfrom projf-explore(https://github.com/projf/projf-explore) to DFHDL. The Verilog module has a
parameter list where one parameter's default depends on an earlier one:
A single DFHDL parameter list does not allow a later parameter's default to
reference an earlier one by simple name (confirmed this is also true in plain
Scala 3, not DFHDL-specific:
class Probe2(val a: Int = 5, val b: Int = a + 1)fails to compile with
Not found: a). The standard Scala workaround for thisis a second (curried) parameter list, e.g.
class Foo(a: Int)(b: Int = a + 1).That workaround crashes the DFHDL compiler. The crash reproduces even with a
default that does not reference the first list at all — any DFHDL design
class with two curried parameter lists where the second list has a default
value crashes.
Minimal reproduction
Run with:
Expected behavior
Either a successful compile (curried parameter lists are ordinary Scala and
should be supported), or a clear DFHDL-level diagnostic saying curried
parameter lists / defaults in a non-first parameter list are unsupported.
Actual behavior
Internal compiler crash (not a normal DFHDL elaboration error):
The assertion message oddly names the first list's parameter (
A) eventhough the crash is triggered by the second list's default value having any
default at all (tested with
= 8, a literal with no reference toA) — thismislabeling may itself be a clue to the root cause (something in how the
plugin synthesizes/threads the
$default$Naccessor across parameter-listboundaries).
Also reproduces with the original motivating case, where the second list's
default genuinely references the first list's parameter:
This one compiles successfully (fails only later, expectedly, because no
AppModedefault exists for a class requiring constructor args to runwithout CLI arguments).
DFHDL version
v0.22.0+39-03afffb1-SNAPSHOT
Workaround used
Converted the dependent parameter into a plain derived
valin the designbody instead of a constructor parameter (losing external overridability of
that one parameter, which was the only way to keep the translation
compiling):