clash-lang / clash-compiler

Haskell to VHDL/Verilog/SystemVerilog compiler
https://clash-lang.org/
Other
1.4k stars 149 forks source link

Bug: HDL generation failure with GHC 9.0.2, multiple hidden, synthesis attribute #2593

Closed DigitalBrains1 closed 5 months ago

DigitalBrains1 commented 9 months ago

In Clash master and 1.6, there is a bug when generating HDL under very specific conditions. Only with GHC 9.0.2 (out of the versions we test in CI), with multiple hidden enabled, an annotation from Clash.Annotations.SynthesisAttributes and the following reproducer:

topEntity ::
  Signal System Bit ->
  Signal System Bit `Annotate` 'StringAttr "break" "me"
topEntity dIn =
  exposeClockResetEnable (register 0) clk rst en dIn
 where
   clk = clockGen
   rst = resetGen
   en = enableGen

VHDL generation will produce the error:

<no location info>: error:
    Clash error call:
    Clash.Netlist.BlackBox.Util(585): IsActiveEnable: Expected Bool or Enable, not: Void Nothing
    CallStack (from HasCallStack):
      error, called at src/Clash/Netlist/BlackBox/Util.hs:585:13 in clash-lib-1.7.0-inplace:Clash.Netlist.BlackBox.Util
      renderElem, called at src/Clash/Netlist/BlackBox/Util.hs:319:15 in clash-lib-1.7.0-inplace:Clash.Netlist.BlackBox.Util

Verilog and SystemVerilog instead say:

<no location info>: error:
    Clash error call:
    Clash.Netlist.BlackBox(290): Forced to evaluate untranslatable type: (resetGenN
      @(IfStuck
          TryDomainResult
          [...]
               (TryDomain (Signal "System" Bit -> Signal "System" Bit) (Signal "System" Bit -> Signal "System" Bit))))))
    CallStack (from HasCallStack):
      error, called at src/Clash/Netlist/BlackBox.hs:290:21 in clash-lib-1.7.0-inplace:Clash.Netlist.BlackBox

Each of the following is enough to make the code produce HDL again:

Type-applying register, though, does not help.

I created a branch issue-2593 which tests the reproducer in CI. The full file with the reproducer is T2593.hs For 1.6, the branch is issue-2593-1.6.

DigitalBrains1 commented 9 months ago

This issue prevents me from writing the code I want to write in the examples in #2592 (I need to add type signatures where they aren't needed).

leonschoorl commented 9 months ago

When run with -fclash-debug DebugSilent or higher you can see it stumble over the type of the enable signal a little earlier:

Clash.Normalize(212): Expr belonging to bndr: enableGen (:: Enable
  (ErrOnConflict
     (Signal "System" Bit -> Signal "System" Bit)
     (Merge' (Found "System") (TryDomain (Signal "System" Bit -> Signal "System" Bit) (Signal "System" Bit))))) has a non-representable return type. Not normalising:
(Λdom ->
  Enable @dom (clockGen1[GlobalId] @dom))
  @(ErrOnConflict
      (Signal "System" Bit -> Signal "System" Bit)
      (Merge' (Found "System") (TryDomain (Signal "System" Bit -> Signal "System" Bit) (Signal "System" Bit))))

Some alternative workarounds you might like better:

DigitalBrains1 commented 9 months ago

Oh, such a register 0 dIn workaround is much smoother, thanks!