clash-lang / clash-compiler

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

Top entities with monomorphic constraints are potentially untranslatable #1028

Open martijnbastiaan opened 4 years ago

martijnbastiaan commented 4 years ago

Consider

module Test2 where

import Clash.Prelude

subFun
  :: forall dom
   . HiddenClockResetEnable dom
  => Signal dom Int
  -> Signal dom Int
subFun =
  case knownDomain @dom of
    SDomainConfiguration dom period edge reset init_ polarity ->
      case snatToInteger period of
        10 -> fmap succ
        _ -> fmap pred
{-# NOINLINE subFun #-}

topEntity
  :: ( HiddenClock System
     , HiddenReset System )
  => Signal System Int
  -> Signal System Int
topEntity = withEnable enableGen subFun

topEntity's core looks like:

λ($d(%,%)6989586621679075218 :: GHC.Classes.(%,%)7710162562058289156
                                  (GHC.Classes.IP3602879701896396848
                                     (GHC.TypeLits.AppendSymbol3674937295934325116
                                        "System"
                                        "_clk")
                                     (Clash.Signal.Internal.Clock8214565720323789554
                                        "System"))
                                  (Clash.Signal.Internal.KnownDomain8214565720323789576
                                     "System")) ->
λ($d(%,%)16989586621679075219 :: GHC.Classes.(%,%)7710162562058289156
                                   (GHC.Classes.IP3602879701896396848
                                      (GHC.TypeLits.AppendSymbol3674937295934325116
                                         "System"
                                         "_rst")
                                      (Clash.Signal.Internal.Reset8214565720323789578
                                         "System"))
                                   (Clash.Signal.Internal.KnownDomain8214565720323789576
                                      "System")) ->
letrec
  $dKnownDomain8286623314361781744 :: Clash.Signal.Internal.KnownDomain8214565720323789576
                                        "System"
  = GHC.Classes.$p2(%,%)8214565720323789678[GlobalId]
      @(GHC.Classes.IP3602879701896396848
          (GHC.TypeLits.AppendSymbol3674937295934325116
             "System"
             "_clk")
          (Clash.Signal.Internal.Clock8214565720323789554
             "System"))
      @(Clash.Signal.Internal.KnownDomain8214565720323789576
          "System")
      $d(%,%)6989586621679075218[LocalId]
in Test2.subFun8214565720323841755[GlobalId]
     @"System"
     (GHC.Classes.C:(%,,%)8214565720323846615
        @(GHC.Classes.(%,%)7710162562058289156
            (GHC.Classes.IP3602879701896396848
               "System_clk"
               (Clash.Signal.Internal.Clock8214565720323789554
                  "System"))
            (Clash.Signal.Internal.KnownDomain8214565720323789576
               "System"))
        @(GHC.Classes.(%,%)7710162562058289156
            (GHC.Classes.IP3602879701896396848
               "System_rst"
               (Clash.Signal.Internal.Reset8214565720323789578
                  "System"))
            (Clash.Signal.Internal.KnownDomain8214565720323789576
               "System"))
        @(GHC.Classes.(%,%)7710162562058289156
            (GHC.Classes.IP3602879701896396848
               "System_en"
               (Clash.Signal.Internal.Enable8214565720323789569
                  "System"))
            (Clash.Signal.Internal.KnownDomain8214565720323789576
               "System"))
        (GHC.Classes.C:(%,%)8214565720323846612
           @(GHC.Classes.IP3602879701896396848
               "System_clk"
               (Clash.Signal.Internal.Clock8214565720323789554
                  "System"))
           @(Clash.Signal.Internal.KnownDomain8214565720323789576
               "System")
           (GHC.Classes.$p1(%,%)8214565720323789680[GlobalId]
              @(GHC.Classes.IP3602879701896396848
                  (GHC.TypeLits.AppendSymbol3674937295934325116
                     "System"
                     "_clk")
                  (Clash.Signal.Internal.Clock8214565720323789554
                     "System"))
              @(Clash.Signal.Internal.KnownDomain8214565720323789576
                  "System")
              $d(%,%)6989586621679075218[LocalId])
           $dKnownDomain8286623314361781744[LocalId])
        (GHC.Classes.C:(%,%)8214565720323846612
           @(GHC.Classes.IP3602879701896396848
               "System_rst"
               (Clash.Signal.Internal.Reset8214565720323789578
                  "System"))
           @(Clash.Signal.Internal.KnownDomain8214565720323789576
               "System")
           (GHC.Classes.$p1(%,%)8214565720323789680[GlobalId]
              @(GHC.Classes.IP3602879701896396848
                  (GHC.TypeLits.AppendSymbol3674937295934325116
                     "System"
                     "_rst")
                  (Clash.Signal.Internal.Reset8214565720323789578
                     "System"))
              @(Clash.Signal.Internal.KnownDomain8214565720323789576
                  "System")
              $d(%,%)16989586621679075219[LocalId])
           $dKnownDomain8286623314361781744[LocalId])
        (GHC.Classes.C:(%,%)8214565720323846612
           @(GHC.Classes.IP3602879701896396848
               "System_en"
               (Clash.Signal.Internal.Enable8214565720323789569
                  "System"))
           @(Clash.Signal.Internal.KnownDomain8214565720323789576
               "System")
           (Clash.Signal.Internal.enableGen18214565720323789944[GlobalId]
              @"System")
           $dKnownDomain8286623314361781744[LocalId]))

In this core the dictionary of KnownDomain is unavailable. This leaves Clash unable to solve the case in subFun.

We should lookup dictionaries of monomorphic constraints and inline them.

christiaanb commented 9 months ago

Another option is to not make KnownDomain dom not part of the HiddenClock/Reset/Enable constraint synonym.

With regards to “just inlining the dictionaries” I take is you mean that as a preprocessing step for synthesis boundaries/entry points; not all binders that have a type-class type.

martijnbastiaan commented 9 months ago

With regards to “just inlining the dictionaries” I take is you mean that as a preprocessing step for synthesis boundaries/entry points; not all binders that have a type-class type.

Yeah, that was a poorly phrased way of saying we could conjure up the term (in fact, we should already have it somewhere in a ClashEnvy type).

not all binders that have a type-class type

Not sure I understand, could you elaborate?

christiaanb commented 9 months ago

We could write a transformation that’s part of the normalization process that for every variable reference:

x :: TC

replaces x with a fresh dictionary. But I assumed that’s not what you meant.

DigitalBrains1 commented 9 months ago

Another option is to not make KnownDomain dom not part of the HiddenClock/Reset/Enable constraint synonym.

Ah but I recently wrote some documentation recommending people construct such tuples themselves...

martijnbastiaan commented 9 months ago

But I assumed that’s not what you meant.

Gotcha. I meant synthesis boundaries, yes. The rest should be solved by constant propagation.