clash-lang / clash-compiler

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

Internal error in 'reduceBindersCleanup' #1536

Open gergoerdi opened 3 years ago

gergoerdi commented 3 years ago

Internal error: reduceBindersCleanup encountered a variable reference that was neither in doneInl, origInl, or in the transformation's in scope set. Unique was: 3.

CallStack (from HasCallStack):

  • error, called at src/Clash/Normalize/Transformations.hs:2654:11 in clash-lib-1.3.0-7LqQya9E8am3HCoXGJ8tNP:Clash.Normalize.Transformations
  • reduceBindersCleanup, called at src/Clash/Normalize/Transformations.hs:2615:30 in clash-lib-1.3.0-7LqQya9E8am3HCoXGJ8tNP:Clash.Normalize.Transformations
    • inlineBndrsCleanup, called at src/Clash/Normalize/Transformations.hs:2500:19 in clash-lib-1.3.0-7LqQya9E8am3HCoXGJ8tNP:Clash.Normalize.Transformations
  • inlineCleanup, called at src/Clash/Normalize/Strategy.hs:56:53 in clash-lib-1.3.0-7LqQya9E8am3HCoXGJ8tNP:Clash.Normalize.Strategy

This will be quite difficult to minimize... I have uploaded the whole shebang to https://github.com/gergoerdi/clash-spaceinvaders/tree/clash-bug-reduceBindersCleanup.

Naive bisection shows that the first change on my side that causes it is somewhere between https://github.com/gergoerdi/clash-intel8080/commits/66ca632 and https://github.com/gergoerdi/clash-intel8080/commits/ff9e07b (change rendered: https://github.com/gergoerdi/clash-intel8080/compare/66ca632..ff9e07b)

gergoerdi commented 3 years ago

I have uploaded a version that at least doesn't contain a full Space Invaders machine :)

https://github.com/gergoerdi/clash-intel8080/tree/clash-issue-1536

Build with stack build && stack runhaskell -- build.hs.

Compiles to Verilog: https://github.com/gergoerdi/clash-intel8080/tree/57c1939bd6967ef9a851055a9288a2596436036b Fails: https://github.com/gergoerdi/clash-intel8080/tree/84b6e5fe5417e8f64190e2329a7267ab080f88f8

martijnbastiaan commented 3 years ago

A few pointers for people looking to solve this bug:

  1. It's probably useful to trace origInl. A thing with a unique of 3 heavily implies it was generated by Clash. It'd be interesting to see how it's used.
  2. reduceBindersCleanup is tested in isolation here: https://github.com/clash-lang/clash-compiler/blob/b0a239e1a6b0e0d0f7cf63a0c85f2c1448a0a13e/clash-lib/tests/Clash/Tests/Normalize/Transformations.hs. If there's nothing obvious wrong in step (1), try to put the entirety of the graph in origInl in there (like t1337a) and start reducing it until it doesn't fail.

@gergoerdi This might just be a frivolous error message. If you're in a hurry you might want to try removing it entirely from reduceBindersCleanup and see if your design still works.

gergoerdi commented 3 years ago

I tried removing the error message, but then I get this:

../src/top.hs:20:1: error:

    Clash.Netlist(385): Not in normal form: Var-application with Type arguments:

    <prefixName>"$p2(%,%)"
    c$sel[3][LocalId]
      @(GHC.Maybe.Maybe[3674937295934324792]
          (Data.Either.Either[3674937295934324904]
             Hardware.Intel8080.Microcode.Addressing[8214565720324144085]
             Hardware.Intel8080.Microcode.Addressing[8214565720324144085]))

    The source location of the error is not exact, only indicative, as it is acquired 
    after optimizations. The actual location of the error can be in a function that is 
    inlined. To prevent inlining of those functions, annotate them with a NOINLINE pragma.
   |
20 | topEntity = withEnableGen board
   | ^^^^^^^^^
gergoerdi commented 3 years ago

It seems I can work around this issue by doing some Template Haskell to force microcode to normal form before hitting Clash.

martijnbastiaan commented 3 years ago

@gergoerdi When I try to run

stack build && stack runhaskell -- build.hs

I get:

<no location info>: error: can't find file: build.hs

Did you forget to add build.hs? :)

gergoerdi commented 3 years ago

Are you on the right branch? It should be clash-issue-1536. I can see the file right there.

martijnbastiaan commented 3 years ago

facepalm

I removed the repo because I forgot --recursive (and didn't want to bother looking up how to clone submodules after the fact), and then forgot to checkout the branch again.

gergoerdi commented 3 years ago

As of e6738d181690c22e931779f47ad058eb50c266f4 I managed to trigger this again:

<no location info>: error:
    Clash error call:
    Internal error: 'reduceBindersCleanup' encountered a variable reference that was 
    neither in 'doneInl', 'origInl', or in the transformation's in scope set. Unique 
    was: '6989586621679302210'.
    CallStack (from HasCallStack):
      error, called at src/Clash/Normalize/Transformations.hs:2664:11 in clash-lib-1.3.0-BtaSQT9Z6y828nb9DyhjHh:Clash.Normalize.Transformations
      reduceBindersCleanup, called at src/Clash/Normalize/Transformations.hs:2625:30 in clash-lib-1.3.0-BtaSQT9Z6y828nb9DyhjHh:Clash.Normalize.Transformations
      inlineBndrsCleanup, called at src/Clash/Normalize/Transformations.hs:2510:19 in clash-lib-1.3.0-BtaSQT9Z6y828nb9DyhjHh:Clash.Normalize.Transformations
      inlineCleanup, called at src/Clash/Normalize/Strategy.hs:57:53 in clash-lib-1.3.0-BtaSQT9Z6y828nb9DyhjHh:Clash.Normalize.Strategy

Full code is at https://github.com/gergoerdi/clash-issue-1536/tree/5a4f39db790eb1bac425e1d3883e27a353df6d42 just run build.sh after checkout

gergoerdi commented 3 years ago

I will keep pushing to https://github.com/gergoerdi/clash-issue-1536/tree/clash-issue-1536 as I try to simplify my code.

gergoerdi commented 3 years ago

Hrmpf, I managed to simplify my code to the point where I am getting "Clash.Normalize(192): Clash can only normalize monomorphic functions, but this is polymorphic" instead, so I guess I'll have to completely rethink my approach in https://github.com/gergoerdi/retroclash-lib/blob/05b6f8cdaebfb77edb4db4a422b0817feeaca770/src/RetroClash/Memory.hs anyway...

christiaanb commented 3 years ago

Adding -fclash-debug DebugSilent shows that it goes wrong earlier: ANF introduces free variables. However, that again is a proxy for a failure upstream. That is, I'm seeing that the expression on which ANF fails is:

<no location info>: error:
    Clash error call:
    Clash.Rewrite.Util(249): Error when applying rewrite ANF to:
    λ(r1[8286623314361845567] :: Clash.Signal.Internal.Signal[8214565720323789676]
                                   "System"
                                   (GHC.Maybe.Maybe[3674937295934324792]
                                      (Clash.Sized.Internal.Unsigned.Unsigned[8214565720323789711]
                                         16))) ->
    case Data.Dependent.Map.unionWithKey

where I expect that that unionWithKey should have been compile-time evaluated. (The ANF transform happens after compile-time evaluation). The problem is that ANF only works correctly when certain invariants hold, but those invariants aren't checked (adding that check would make the common case expensive, so we don't do it), and those invariants only don't hold when something is bugged earlier in the compile process.

Anyhow... investigating further why the compile-time evaluation of that unionWithKey isn't being evaluated at compile-time.

gergoerdi commented 3 years ago

Well ideally the whole of this memoryMap stuff should be evaluated at compile-time. In the meantime, in desperation I started rewriting the whole shebang using Template Haskell but it is looking way worse...

christiaanb commented 3 years ago

Mmm... if that Data.Dependent.Map.unionWithKey is this one: https://hackage.haskell.org/package/dependent-map-0.4.0.0/docs/src/Data.Dependent.Map.html#unionWithKey

Than I think what is going on is that there is no unfolding / Core expression corresponding to that unionWithKey, as it is recursive, and so Clash cannot evaluate at compile time. Top-level recursive bindings never get an unfolding, unless the library is build with -fexpose-all-unfoldings. @gergoerdi Are you building all your dependencies with -fexpose-all-unfoldings? Is that possbible with stack?

With cabal you could add the following to your cabal.project file:

package *
  ghc-options: -fexpose-all-unfoldings

That still won't get you all the unfoldings for all of your dependencies though, libraries that are bundled with GHC, such as base still won't have unfoldings for things like the recursive Data.List.map.

gergoerdi commented 3 years ago

Hmm that's a very good point -- I build all my own libraries with -fexpose-all-unfoldings but I don't know how to pass that to all eternal dependencies as well. Let me look around.

gergoerdi commented 3 years ago

@gergoerdi Are you building all your dependencies with -fexpose-all-unfoldings? Is that possbible with stack?

There is an option, but the details aren't pretty. I am now trying to compile with the flag set on only the dependent-map package, and, well, all I can say so far is that it hasn't errored out yet... it's been running for 5+ minutes, so let's wait and see.

gergoerdi commented 3 years ago

BTW, what exactly does the 'inlining limit' mean? I am getting error messages from Clash that an inlining limit of e.g. 100 isn't enough to deal with the unionWithKey stuff, but I am building tiny DMaps with 4 entry...

christiaanb commented 3 years ago

It limits how often a (global) function f is inlined in the subject of the expression case (f ...) of. The inlining currently only happens when f returns a data type that cannot be represented by a bundle of wires. It is limited because Clash cannot determine beforehand whether inlining will ever terminate.

gergoerdi commented 3 years ago

So does that mean I am somehow getting a 100-deep recursive chain of calls to go in unionWithKey? That would be very surprising for a 4-element DMap.

christiaanb commented 3 years ago

Yes, that’s what it means. The eager parallel reduction is not necessarily efficient. Actually, Clash doesn’t have a well defined compile-time semantics at all. The underlying rewrite mechanism is only guaranteed to be able to translate a Haskell program to a circuit when all transformations are applied exhaustively; the implementation has picked a somewhat ad-hoc set of tree traversals to achieve this exhaustive rewrite.

What this means is that Clash is/can be very bad at compile-time evaluation, especially partial evaluation (where the expression under evaluation has variables). That is why @alex-mckenna is hard at work to create a proper partial evaluator. But the problem is very non-trivial to solve, so an industrial-strength implementation is still far away.

gergoerdi commented 3 years ago

Soooo does this mean this is hopeless, and I should start thinking seriously about the TH based approach?

gergoerdi commented 3 years ago

Is there some debug flag I could pass to clash to see what exactly (if anything) it is doing while it is spinning at 100% CPU with -fexpose-all-unfoldings on dependent-map and a large enough -fclash-inline-limit?

martijnbastiaan commented 3 years ago

You could try -fclash-debug DebugName to see a list of (applied) transformations. More verbose options exist but aren't guaranteed to producte readable output :^).

gergoerdi commented 3 years ago

My hunch is that the problem is going to be this recursive piece of code:

{-# INLINE memoryMap #-}
memoryMap
    :: Signal dom (Maybe addr)
    -> Signal dom (Maybe dat)
    -> (forall s. Addressing s dom dat addr a)
    -> (Signal dom (Maybe dat), a)
memoryMap addr wr body = (join <$> firstIn read, x)
  where
    (x, (read, conns)) = evalRWS (unAddressing body) (fanInMaybe addr, wr, conns) 0

Here, we tie the knot on conns which is an essential part of the code: we need to know the address line going into a memory element when we create that memory element, but we need memory element handles so we can connect address lines to them.

gergoerdi commented 3 years ago

You could try -fclash-debug DebugName to see a list of (applied) transformations.

It ends up cycling on the following:

caseCase {205290}
caseCase {205291}
applicationPropagation {205292}
bindOrLiftNonRep {205293}
caseCon {205294}
applicationPropagation {205295}
bindOrLiftNonRep {205296}
bindOrLiftNonRep {205297}
caseCase {205298}
applicationPropagation {205299}
bindOrLiftNonRep {205300}
caseCon {205301}
caseCase {205302}
caseCase {205303}
applicationPropagation {205304}
caseCase {205305}
applicationPropagation {205306}
caseCase {205307}
applicationPropagation {205308}
bindOrLiftNonRep {205309}
christiaanb commented 3 years ago

Does it terminate if you don't use a knot-tied defined conns? But something like:

{-# INLINE memoryMap #-}
memoryMap
    :: Signal dom (Maybe addr)
    -> Signal dom (Maybe dat)
    -> (forall s. Addressing s dom dat addr a)
    -> _  
    -> (Signal dom (Maybe dat), a)
memoryMap addr wr body bogusConns = (join <$> firstIn read, x)
  where
    (x, (read, _conns)) = evalRWS (unAddressing body) (fanInMaybe addr, wr, bogusConns) 0
gergoerdi commented 3 years ago

The only bogusConns I can easily come up with is mempty, so I tried that, and that causes Clash to synthesize in 40 seconds. Of course, the resulting circuit isn't what I want :)

christiaanb commented 3 years ago

There's not some singleton singleBogusCon implementation where you can float the singleBogusCon value all the way up? So that we can at least get some additional structure.

gergoerdi commented 3 years ago

While trying to minimize https://github.com/clash-lang/clash-compiler/issues/1611, I managed to trigger this bug again, with a fairly small & self-contained way of reproducing it!

https://github.com/gergoerdi/clash-issue-1611/tree/clash-issue-1536

<no location info>: error:
    Clash error call:
    Internal error: 'reduceBindersCleanup' encountered a variable reference that was 
    neither in 'doneInl', 'origInl', or in the transformation's in scope set. Unique 
    was: '6989586621679258275'.
    CallStack (from HasCallStack):
      error, called at src/Clash/Normalize/Transformations.hs:2664:11 in clash-lib-1.3.0-BtaSQT9Z6y828nb9DyhjHh:Clash.Normalize.Transformations
      reduceBindersCleanup, called at src/Clash/Normalize/Transformations.hs:2625:30 in clash-lib-1.3.0-BtaSQT9Z6y828nb9DyhjHh:Clash.Normalize.Transformations
      inlineBndrsCleanup, called at src/Clash/Normalize/Transformations.hs:2510:19 in clash-lib-1.3.0-BtaSQT9Z6y828nb9DyhjHh:Clash.Normalize.Transformations
      inlineCleanup, called at src/Clash/Normalize/Strategy.hs:57:53 in clash-lib-1.3.0-BtaSQT9Z6y828nb9DyhjHh:Clash.Normalize.Strategy
gergoerdi commented 3 years ago

There's not some singleton singleBogusCon implementation where you can float the singleBogusCon value all the way up? So that we can at least get some additional structure.

OK I have now done that (see this commit), but I'm not sure what we're supposed to see here. Compiling with an inliner limit of 1000, it doesn't diverge (so that's an improvement compared to the knot-tying version), but it still complains about not enough inlinings:

Clash.Normalize.Transformations(432): InlineNonRep: c$Hardware.SpaceInvaders.mainBoard_go_go[660417] already inlined 1000 times in:c$Hardware.SpaceInvaders.mainBoard_go[358191]
Type of the subject is: Data.Dependent.Map.Internal.DMap[8214565720324068564]
  (GHC.Prim.TYPE[3674937295934324912]
     GHC.Types.LiftedRep[3891110078048108766])
  (RetroClash.Memory.Component[8214565720324068547]
     (GHC.Types.Any[3674937295934325098]
        (GHC.Prim.TYPE[3674937295934324912]
           GHC.Types.LiftedRep[3891110078048108766]))
     (GHC.Types.Any[3674937295934325098]
        (GHC.Types.Any[3674937295934325098]
           (GHC.Prim.TYPE[3674937295934324912]
              GHC.Types.LiftedRep[3891110078048108766]))))
  (RetroClash.Memory.FanIn[8214565720324068556] "Dom25")
Function c$Hardware.SpaceInvaders.mainBoard_go[358191] will not reach a normal form, and compilation might fail.
Run with '-fclash-inline-limit=N' to increase the inlining limit to N.
gergoerdi commented 3 years ago

Would it help if I put in the effort to make a single-module version of this (similar to https://github.com/clash-lang/clash-compiler/issues/1611#issuecomment-740572475)? Or it's not going to change anything, because even if the non-knotted version could be synthesized, the current evaluator has no chance of normalizing the knotted one?

christiaanb commented 3 years ago

Right now, I don't see any reason why the compiler should not be able to normalize the knotted one, aside from:

  1. There being a bug in the compiler
  2. Some function from a dependency not having a Core unfolding
gergoerdi commented 3 years ago

Here's a managable (<100 lines!) standalone version of this code:

{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving #-}
{-# LANGUAGE RankNTypes #-}
module Board where

import Clash.Prelude
import Data.Maybe
import Control.Monad
import Control.Monad.RWS

import Data.Kind
import Data.Dependent.Map as DMap
import Data.GADT.Compare
import Type.Reflection

data Component s (addr :: Type) = Component (TypeRep addr) Int

instance GEq (Component s) where
    geq (Component a _) (Component b _) = geq a b

instance GCompare (Component s) where
    gcompare (Component a _) (Component b _) = gcompare a b

newtype FanIn dom a = FanIn{ getFanIn :: Signal dom `Ap` First a }
    deriving newtype (Semigroup, Monoid)

newtype AddrMap s dom = AddrMap{ addrMap :: DMap (Component s) (FanIn dom) }
    deriving newtype (Monoid)

instance Semigroup (AddrMap s dom) where
    AddrMap map1 <> AddrMap map2 = AddrMap $ unionWithKey (const mappend) map1 map2

newtype Addressing s dom dat addr a = Addressing
    { unAddressing :: RWS
          (FanIn dom addr, AddrMap s dom)
          (FanIn dom (Maybe dat), AddrMap s dom)
          Int
          a
    }
    deriving newtype (Functor, Applicative, Monad)

memoryMap
    :: Signal dom (Maybe addr)
    -> Signal dom (Maybe dat)
    -> (forall s. Addressing s dom dat addr a)
    -> (Signal dom (Maybe dat), a)
memoryMap addr wr body = (join <$> firstIn read, x)
  where
    (x, (read, conns)) = evalRWS (unAddressing body) (fanInMaybe addr, conns) 0

readWrite_
    :: (HiddenClockResetEnable dom, Typeable addr')
    => (Signal dom (Maybe addr') -> Signal dom (Maybe dat))
    -> Addressing s dom dat addr (Component s addr')
readWrite_ mkComponent = Addressing $ do
    component <- Component typeRep <$> get <* modify succ
    (_, addrs) <- ask
    let addr = firstIn . fromMaybe mempty $ DMap.lookup component (addrMap addrs)
        read = mkComponent addr
    tell (fanIn read, mempty)
    return component

ram0
    :: (HiddenClockResetEnable dom, 1 <= n, NFDataX dat, Num dat)
    => SNat n
    -> Addressing s dom dat addr (Component s (Index n))
ram0 size@SNat = readWrite_ $ \addr ->
    fmap Just $ blockRam1 ClearOnReset size 0 (fromMaybe 0 <$> addr) (pure Nothing)

connect
    :: Component s addr
    -> Addressing s dom dat addr ()
connect component@(Component _ i) = Addressing $ do
    (addr, _) <- ask
    tell (mempty, AddrMap $ DMap.singleton component addr)

firstIn :: FanIn dom a -> Signal dom (Maybe a)
firstIn = fmap getFirst . getAp . getFanIn

fanInMaybe :: Signal dom (Maybe a) -> FanIn dom a
fanInMaybe = FanIn . Ap . fmap First

fanIn :: Signal dom a -> FanIn dom a
fanIn = fanInMaybe . fmap pure

topEntity
    :: Clock System
    -> Reset System
    -> Signal System (Maybe (Index 0x0400))
    -> Signal System (Maybe (Unsigned 8))
    -> (Signal System (Maybe (Unsigned 8)), ())
topEntity clk rst addr wr = withClockResetEnable clk rst enableGen $ memoryMap addr wr $ do
    ram <- ram0 (SNat @0x0400)
    connect ram

Crucially, this version still uses knot-tying in memoryMap, which according to @christiaanb 's latest comment, should be fine. Compared to #1611, I don't see anything in Clash's output about TypeRep:

Clash.Normalize.Transformations(430): InlineNonRep: c$Board.memoryMap_r1[3867] already inlined 100 times in:Board.memoryMap[3860]
Type of the subject is: GHC.Tuple.(,)[3746994889972252676]
  (Board.FanIn[8214565720323973518]
     "System"
     (Clash.Sized.Internal.Index.Index[8214565720323789680]
        1024))
  (Board.AddrMap[8214565720323973515]
     (GHC.Types.Any[3674937295934325098]
        (GHC.Prim.TYPE[3674937295934324912]
           GHC.Types.LiftedRep[3891110078048108766]))
     "System")
Function Board.memoryMap[3860] will not reach a normal form, and compilation might fail.
Run with '-fclash-inline-limit=N' to increase the inlining limit to N.
Clash.Normalize.Transformations(430): InlineNonRep: c$Board.memoryMap_r1[3867] already inlined 100 times in:Board.memoryMap[3860]
Type of the subject is: GHC.Tuple.(,)[3746994889972252676]
  (Board.FanIn[8214565720323973518]
     "System"
     (Clash.Sized.Internal.Index.Index[8214565720323789680]
        1024))
  (Board.AddrMap[8214565720323973515]
     (GHC.Types.Any[3674937295934325098]
        (GHC.Prim.TYPE[3674937295934324912]
           GHC.Types.LiftedRep[3891110078048108766]))
     "System")
Function Board.memoryMap[3860] will not reach a normal form, and compilation might fail.
Run with '-fclash-inline-limit=N' to increase the inlining limit to N.
Clash.Normalize.Transformations(430): InlineNonRep: c$Board.memoryMap_r1[3867] already inlined 100 times in:Board.memoryMap[3860]
Type of the subject is: GHC.Tuple.(,)[3746994889972252676]
  (Board.FanIn[8214565720323973518]
     "System"
     (Clash.Sized.Internal.Index.Index[8214565720323789680]
        1024))
  (Board.AddrMap[8214565720323973515]
     (GHC.Types.Any[3674937295934325098]
        (GHC.Prim.TYPE[3674937295934324912]
           GHC.Types.LiftedRep[3891110078048108766]))
     "System")
Function Board.memoryMap[3860] will not reach a normal form, and compilation might fail.
Run with '-fclash-inline-limit=N' to increase the inlining limit to N.
Clash.Normalize.Transformations(430): InlineNonRep: c$Board.memoryMap_r1[3867] already inlined 100 times in:Board.memoryMap[3860]
Type of the subject is: GHC.Tuple.(,)[3746994889972252676]
  (Board.FanIn[8214565720323973518]
     "System"
     (Clash.Sized.Internal.Index.Index[8214565720323789680]
        1024))
  (Board.AddrMap[8214565720323973515]
     (GHC.Types.Any[3674937295934325098]
        (GHC.Prim.TYPE[3674937295934324912]
           GHC.Types.LiftedRep[3891110078048108766]))
     "System")
Function Board.memoryMap[3860] will not reach a normal form, and compilation might fail.
Run with '-fclash-inline-limit=N' to increase the inlining limit to N.

src/Board.hs:91:1: error:

    Hit specialisation limit 20 on function `c$Board.topEntity_go[14209]'.

    The function `c$Board.topEntity_go[14209] :: Data.Dependent.Map.Internal.DMap[8214565720323790117]
                                     (GHC.Prim.TYPE[3674937295934324912]
                                        GHC.Types.LiftedRep[3891110078048108766])
                                     (Board.Component[8214565720323973521]
                                        (GHC.Types.Any[3674937295934325098]
                                           (GHC.Prim.TYPE[3674937295934324912]
                                              GHC.Types.LiftedRep[3891110078048108766])))
                                     (Board.FanIn[8214565720323973518] "System")
                               -> Clash.Signal.Internal.Signal[8214565720323789647]
                                    "System"
                                    (Data.Monoid.First[8214565720323789960]
                                       (Clash.Sized.Internal.Index.Index[8214565720323789680]
                                          1024))' is most likely recursive, and looks like it is being indefinitely specialized on a growing argument.

    Body of `c$Board.topEntity_go[14209] :: Data.Dependent.Map.Internal.DMap[8214565720323790117]
                                     (GHC.Prim.TYPE[3674937295934324912]
                                        GHC.Types.LiftedRep[3891110078048108766])
                                     (Board.Component[8214565720323973521]
                                        (GHC.Types.Any[3674937295934325098]
                                           (GHC.Prim.TYPE[3674937295934324912]
                                              GHC.Types.LiftedRep[3891110078048108766])))
                                     (Board.FanIn[8214565720323973518] "System")
                               -> Clash.Signal.Internal.Signal[8214565720323789647]
                                    "System"
                                    (Data.Monoid.First[8214565720323789960]
                                       (Clash.Sized.Internal.Index.Index[8214565720323789680]
                                          1024))':
    (Λs[6989586621679212316] ->
      λ(ds2[6989586621679214230] :: Data.Dependent.Map.Internal.DMap[8214565720323790117]
                                      (GHC.Prim.TYPE[3674937295934324912]
                                         GHC.Types.LiftedRep[3891110078048108766])
                                      (Board.Component[8214565720323973521]
                                         s[6989586621679212316])
                                      (Board.FanIn[8214565720323973518]
                                         "System")) ->
      case ds2[6989586621679214230][LocalId] of
        Data.Dependent.Map.Internal.Tip[8214565720323790142]
           ->
          Board.$fMonoidFanIn_z[8214565720323996529][GlobalId]
            @(Clash.Sized.Internal.Index.Index[8214565720323789680]
                1024)
            @"System"
        Data.Dependent.Map.Internal.Bin[8214565720323790143] v1[6989586621679214234]
          (dt[6989586621679214235] :: GHC.Prim.Int#[3674937295934324764])
            (kx[6989586621679214236] :: Board.Component[8214565720323973521]
                                          s[6989586621679212316]
                                          v1[6989586621679214234])
            (x[6989586621679214237] :: Board.FanIn[8214565720323973518]
                                         "System"
                                         v1[6989586621679214234])
            (l[6989586621679214238] :: Data.Dependent.Map.Internal.DMap[8214565720323790117]
                                         (GHC.Prim.TYPE[3674937295934324912]
                                            GHC.Types.LiftedRep[3891110078048108766])
                                         (Board.Component[8214565720323973521]
                                            s[6989586621679212316])
                                         (Board.FanIn[8214565720323973518]
                                            "System"))
            (r[6989586621679214239] :: Data.Dependent.Map.Internal.DMap[8214565720323790117]
                                         (GHC.Prim.TYPE[3674937295934324912]
                                            GHC.Types.LiftedRep[3891110078048108766])
                                         (Board.Component[8214565720323973521]
                                            s[6989586621679212316])
                                         (Board.FanIn[8214565720323973518]
                                            "System")) ->
          case kx[6989586621679214236][LocalId] of
            Board.Component[8214565720323973522]
              (b1[6989586621679200383] :: Data.Typeable.Internal.TypeRep[3674937295934325110]
                                            (GHC.Prim.TYPE[3674937295934324912]
                                               GHC.Types.LiftedRep[3891110078048108766])
                                            v1[6989586621679214234])
                (ds3[7205759403793008602] :: GHC.Types.Int[3674937295934324766]) ->
              case Data.GADT.Internal.$fGComparekTypeRep_$cgcompare[8214565720323973567][GlobalId]
                     @(GHC.Prim.TYPE[3674937295934324912]
                         GHC.Types.LiftedRep[3891110078048108766])
                     @(Clash.Sized.Internal.Index.Index[8214565720323789680]
                         1024)
                     @v1[6989586621679214234]
                     c$Board.topEntity_$dTypeable[2817][GlobalId]
                     b1[6989586621679200383][LocalId] of
                Data.GADT.Internal.GLT[8214565720323790214]  ->
                  c$Board.topEntity_go[3045][GlobalId]
                    @s[6989586621679212316]
                    l[6989586621679214238][LocalId]
                Data.GADT.Internal.GEQ[8214565720323790216]
                  (co[6989586621679214248] :: GHC.Prim.~#[3674937295934324842]
                                                (GHC.Prim.TYPE[3674937295934324912]
                                                   GHC.Types.LiftedRep[3891110078048108766])
                                                (GHC.Prim.TYPE[3674937295934324912]
                                                   GHC.Types.LiftedRep[3891110078048108766])
                                                v1[6989586621679214234]
                                                (Clash.Sized.Internal.Index.Index[8214565720323789680]
                                                   1024)) ->
                  x[6989586621679214237][LocalId]
                Data.GADT.Internal.GGT[8214565720323790217]  ->
                  c$Board.topEntity_go[3045][GlobalId]
                    @s[6989586621679212316]
                    r[6989586621679214239][LocalId])
      @(GHC.Types.Any[3674937295934325098]
          (GHC.Prim.TYPE[3674937295934324912]
             GHC.Types.LiftedRep[3891110078048108766]))

    Argument (in position: 0) that triggered termination:
    <prefixName>"memoryMap_r1"
    letrec
      $dIP[8286623314361928287] :: GHC.Classes.IP[3602879701896396848]
                                     "enable"
                                     (Clash.Signal.Internal.Enable[8214565720323789617]
                                        "System")
      = <prefixName>"memoryMap_ds"
      <prefixName>"topEntity_ds"
      <prefixName>"ram0"
      letrec
        $d(%,%)[8286623314361928111] :: GHC.Classes.(%,%)[7710162562058289156]
                                          (GHC.Classes.IP[3602879701896396848]
                                             "enable"
                                             (Clash.Signal.Internal.Enable[8214565720323789617]
                                                "System"))
                                          (Clash.Signal.Internal.KnownDomain[8214565720323789624]
                                             "System")
        = <prefixName>"$p3(%,,%)"
        GHC.Classes.C:(%,%)[8214565720323984092]
          @(GHC.Classes.IP[3602879701896396848]
              "enable"
              (Clash.Signal.Internal.Enable[8214565720323789617]
                 "System"))
          @(Clash.Signal.Internal.KnownDomain[8214565720323789624]
              "System")
          <prefixName>"enableGen"
          (Clash.Signal.Internal.Enable[8214565720323854607]
             @"System"
             <prefixName>"enableGen1"
             GHC.Types.True[3891110078048108589])
          (Clash.Signal.Internal.C:KnownDomain[8214565720323856279]
             @"System"
             (GHC.CString.unpackCString# "System")
             (Clash.Signal.Internal.SDomainConfiguration[8214565720323789637]
                @"System"
                @(Clash.Signal.Internal.DomainConfiguration[8214565720323789606]
                    "System"
                    10000
                    Clash.Signal.Internal.Rising[8214565720323789601]
                    Clash.Signal.Internal.Asynchronous[8214565720323789628]
                    Clash.Signal.Internal.Defined[8214565720323789619]
                    Clash.Signal.Internal.ActiveHigh[8214565720323789631])
                @10000
                @Clash.Signal.Internal.Rising[8214565720323789601]
                @Clash.Signal.Internal.Asynchronous[8214565720323789628]
                @Clash.Signal.Internal.Defined[8214565720323789619]
                @Clash.Signal.Internal.ActiveHigh[8214565720323789631]
                (_CO_
                   @(GHC.Prim.~#[3674937295934324842]
                       Clash.Signal.Internal.DomainConfiguration[8214565720323789605]
                       Clash.Signal.Internal.DomainConfiguration[8214565720323789605]
                       (Clash.Signal.Internal.DomainConfiguration[8214565720323789606]
                          "System"
                          10000
                          Clash.Signal.Internal.Rising[8214565720323789601]
                          Clash.Signal.Internal.Asynchronous[8214565720323789628]
                          Clash.Signal.Internal.Defined[8214565720323789619]
                          Clash.Signal.Internal.ActiveHigh[8214565720323789631])
                       (Clash.Signal.Internal.DomainConfiguration[8214565720323789606]
                          "System"
                          10000
                          Clash.Signal.Internal.Rising[8214565720323789601]
                          Clash.Signal.Internal.Asynchronous[8214565720323789628]
                          Clash.Signal.Internal.Defined[8214565720323789619]
                          Clash.Signal.Internal.ActiveHigh[8214565720323789631])))
                (Clash.Promoted.Symbol.SSymbol @"System"
                   (GHC.CString.unpackCString# "System"))
                (Clash.Promoted.Nat.SNat[8214565720323789569]
                   @10000
                   10000)
                (Clash.Signal.Internal.SRising[8214565720323789635]
                   @Clash.Signal.Internal.Rising[8214565720323789601]
                   (_CO_
                      @(GHC.Prim.~#[3674937295934324842]
                          Clash.Signal.Internal.ActiveEdge[8214565720323789599]
                          Clash.Signal.Internal.ActiveEdge[8214565720323789599]
                          Clash.Signal.Internal.Rising[8214565720323789601]
                          Clash.Signal.Internal.Rising[8214565720323789601])))
                (Clash.Signal.Internal.SAsynchronous[8214565720323789642]
                   @Clash.Signal.Internal.Asynchronous[8214565720323789628]
                   (_CO_
                      @(GHC.Prim.~#[3674937295934324842]
                          Clash.Signal.Internal.ResetKind[8214565720323789627]
                          Clash.Signal.Internal.ResetKind[8214565720323789627]
                          Clash.Signal.Internal.Asynchronous[8214565720323789628]
                          Clash.Signal.Internal.Asynchronous[8214565720323789628])))
                (Clash.Signal.Internal.SDefined[8214565720323789639]
                   @Clash.Signal.Internal.Defined[8214565720323789619]
                   (_CO_
                      @(GHC.Prim.~#[3674937295934324842]
                          Clash.Signal.Internal.InitBehavior[8214565720323789618]
                          Clash.Signal.Internal.InitBehavior[8214565720323789618]
                          Clash.Signal.Internal.Defined[8214565720323789619]
                          Clash.Signal.Internal.Defined[8214565720323789619])))
                (Clash.Signal.Internal.SActiveHigh[8214565720323789645]
                   @Clash.Signal.Internal.ActiveHigh[8214565720323789631]
                   (_CO_
                      @(GHC.Prim.~#[3674937295934324842]
                          Clash.Signal.Internal.ResetPolarity[8214565720323789630]
                          Clash.Signal.Internal.ResetPolarity[8214565720323789630]
                          Clash.Signal.Internal.ActiveHigh[8214565720323789631]
                          Clash.Signal.Internal.ActiveHigh[8214565720323789631])))))
      in <prefixName>"$p1(%,%)"
      case $d(%,%)[8286623314361928111][LocalId] of
        GHC.Classes.C:(%,%)[8214565720323984092]
          (c$sel[3] :: GHC.Classes.IP[3602879701896396848]
                         "enable"
                         (Clash.Signal.Internal.Enable[8214565720323789617]
                            "System"))
            (c$wild[2] :: Clash.Signal.Internal.KnownDomain[8214565720323789624]
                            "System") ->
          c$sel[3][LocalId]
    in letrec
         a'[6989586621679217849] :: Board.FanIn[8214565720323973518]
                                      "System"
                                      (GHC.Maybe.Maybe[3674937295934324792]
                                         (Clash.Sized.Internal.Unsigned.Unsigned[8214565720323789682]
                                            8))
         = <prefixName>"$fMonoidFirst_$c<>"
         letrec
           ds4[8214565720324007144] :: Data.Monoid.First[8214565720323789960]
                                         (GHC.Maybe.Maybe[3674937295934324792]
                                            (Clash.Sized.Internal.Unsigned.Unsigned[8214565720323789682]
                                               8))
           = <prefixName>"fanIn2"
           letrec
             eta1[4755801206503243959] :: GHC.Maybe.Maybe[3674937295934324792]
                                            (GHC.Maybe.Maybe[3674937295934324792]
                                               (Clash.Sized.Internal.Unsigned.Unsigned[8214565720323789682]
                                                  8))
             = GHC.Maybe.Just[3891110078048108571]
                 @(GHC.Maybe.Maybe[3674937295934324792]
                     (Clash.Sized.Internal.Unsigned.Unsigned[8214565720323789682]
                        8))
                 (letrec
                    addr1[6989586621679204334] :: Clash.Signal.Internal.Signal[8214565720323789647]
                                                    "System"
                                                    (GHC.Maybe.Maybe[3674937295934324792]
                                                       (Clash.Sized.Internal.Index.Index[8214565720323789680]
                                                          1024))
                    = <prefixName>"$fGeneric1First2"
                    letrec
                      x[8214565720324007947] :: Data.Monoid.First[8214565720323789960]
                                                  (Clash.Sized.Internal.Index.Index[8214565720323789680]
                                                     1024)
                      = c$Board.topEntity_go[14245][GlobalId]
                          addr1[3858][LocalId]
                          clk[6989586621679204400][LocalId]
                          rst[6989586621679204401][LocalId]
                    in x[8214565720324007947][LocalId]
                 in GHC.Maybe.Just[3891110078048108571]
                      @(Clash.Sized.Internal.Unsigned.Unsigned[8214565720323789682]
                          8)
                      (Clash.Explicit.BlockRam.blockRam1[3856][GlobalId]
                         <prefixName>"topEntity_ds"
                         <prefixName>"ram0"
                         <prefixName>"$p2(%,%)"
                         <prefixName>"topEntity_ds"
                         <prefixName>"ram0"
                         <prefixName>"$p1(%,,%)"
                         (Clash.Signal.Internal.C:KnownDomain[8214565720323856279]
                            @"System"
                            (GHC.CString.unpackCString# "System")
                            (Clash.Signal.Internal.SDomainConfiguration[8214565720323789637]
                               @"System"
                               @(Clash.Signal.Internal.DomainConfiguration[8214565720323789606]
                                   "System"
                                   10000
                                   Clash.Signal.Internal.Rising[8214565720323789601]
                                   Clash.Signal.Internal.Asynchronous[8214565720323789628]
                                   Clash.Signal.Internal.Defined[8214565720323789619]
                                   Clash.Signal.Internal.ActiveHigh[8214565720323789631])
                               @10000
                               @Clash.Signal.Internal.Rising[8214565720323789601]
                               @Clash.Signal.Internal.Asynchronous[8214565720323789628]
                               @Clash.Signal.Internal.Defined[8214565720323789619]
                               @Clash.Signal.Internal.ActiveHigh[8214565720323789631]
                               (_CO_
                                  @(GHC.Prim.~#[3674937295934324842]
                                      Clash.Signal.Internal.DomainConfiguration[8214565720323789605]
                                      Clash.Signal.Internal.DomainConfiguration[8214565720323789605]
                                      (Clash.Signal.Internal.DomainConfiguration[8214565720323789606]
                                         "System"
                                         10000
                                         Clash.Signal.Internal.Rising[8214565720323789601]
                                         Clash.Signal.Internal.Asynchronous[8214565720323789628]
                                         Clash.Signal.Internal.Defined[8214565720323789619]
                                         Clash.Signal.Internal.ActiveHigh[8214565720323789631])
                                      (Clash.Signal.Internal.DomainConfiguration[8214565720323789606]
                                         "System"
                                         10000
                                         Clash.Signal.Internal.Rising[8214565720323789601]
                                         Clash.Signal.Internal.Asynchronous[8214565720323789628]
                                         Clash.Signal.Internal.Defined[8214565720323789619]
                                         Clash.Signal.Internal.ActiveHigh[8214565720323789631])))
                               (Clash.Promoted.Symbol.SSymbol @"System"
                                  (GHC.CString.unpackCString# "System"))
                               (Clash.Promoted.Nat.SNat[8214565720323789569]
                                  @10000
                                  10000)
                               (Clash.Signal.Internal.SRising[8214565720323789635]
                                  @Clash.Signal.Internal.Rising[8214565720323789601]
                                  (_CO_
                                     @(GHC.Prim.~#[3674937295934324842]
                                         Clash.Signal.Internal.ActiveEdge[8214565720323789599]
                                         Clash.Signal.Internal.ActiveEdge[8214565720323789599]
                                         Clash.Signal.Internal.Rising[8214565720323789601]
                                         Clash.Signal.Internal.Rising[8214565720323789601])))
                               (Clash.Signal.Internal.SAsynchronous[8214565720323789642]
                                  @Clash.Signal.Internal.Asynchronous[8214565720323789628]
                                  (_CO_
                                     @(GHC.Prim.~#[3674937295934324842]
                                         Clash.Signal.Internal.ResetKind[8214565720323789627]
                                         Clash.Signal.Internal.ResetKind[8214565720323789627]
                                         Clash.Signal.Internal.Asynchronous[8214565720323789628]
                                         Clash.Signal.Internal.Asynchronous[8214565720323789628])))
                               (Clash.Signal.Internal.SDefined[8214565720323789639]
                                  @Clash.Signal.Internal.Defined[8214565720323789619]
                                  (_CO_
                                     @(GHC.Prim.~#[3674937295934324842]
                                         Clash.Signal.Internal.InitBehavior[8214565720323789618]
                                         Clash.Signal.Internal.InitBehavior[8214565720323789618]
                                         Clash.Signal.Internal.Defined[8214565720323789619]
                                         Clash.Signal.Internal.Defined[8214565720323789619])))
                               (Clash.Signal.Internal.SActiveHigh[8214565720323789645]
                                  @Clash.Signal.Internal.ActiveHigh[8214565720323789631]
                                  (_CO_
                                     @(GHC.Prim.~#[3674937295934324842]
                                         Clash.Signal.Internal.ResetPolarity[8214565720323789630]
                                         Clash.Signal.Internal.ResetPolarity[8214565720323789630]
                                         Clash.Signal.Internal.ActiveHigh[8214565720323789631]
                                         Clash.Signal.Internal.ActiveHigh[8214565720323789631])))))
                         GHC.Stack.Types.EmptyCallStack[8214565720323979068]
                         (GHC.Types.Eq#[3891110078048108574]
                            @GHC.Types.Bool[3674937295934324744]
                            @(GHC.TypeNats.<=?[3674937295934325074] 1 1024)
                            @GHC.Types.True[3891110078048108589]
                            (_CO_
                               @(GHC.Prim.~#[3674937295934324842]
                                   GHC.Types.Bool[3674937295934324744]
                                   GHC.Types.Bool[3674937295934324744]
                                   (GHC.TypeNats.<=?[3674937295934325074] 1 1024)
                                   GHC.Types.True[3891110078048108589])))
                         <prefixName>"topEntity_ds"
                         <prefixName>"ram0"
                         <prefixName>"$p1(%,%)"
                         <prefixName>"topEntity_ds"
                         <prefixName>"ram0"
                         <prefixName>"$p1(%,,%)"
                         clk[6989586621679204400][LocalId]
                         <prefixName>"topEntity_ds"
                         <prefixName>"ram0"
                         <prefixName>"$p1(%,%)"
                         <prefixName>"$p2(%,,%)"
                         rst[6989586621679204401][LocalId]
                         $dIP[8286623314361928287][LocalId]
                         (Clash.Explicit.BlockRam.ClearOnReset[8214565720323789560]
                            @GHC.Types.True[3891110078048108589]
                            (_CO_
                               @(GHC.Prim.~#[3674937295934324842]
                                   GHC.Types.Bool[3674937295934324744]
                                   GHC.Types.Bool[3674937295934324744]
                                   GHC.Types.True[3891110078048108589]
                                   GHC.Types.True[3891110078048108589])))
                         (Clash.Promoted.Nat.SNat[8214565720323789569]
                            @1024
                            1024)
                         <prefixName>"fromInteger"
                         (<prefixName>"$s$fNumUnsigned"
                            <prefixName>"$s$fNumUnsigned6"
                            Clash.Sized.Internal.Unsigned.fromInteger# @8 8
                            0)
                         (case addr1[6989586621679204334][LocalId] of
                            GHC.Maybe.Nothing[3891110078048108568]  ->
                              Clash.Sized.Internal.Index.fromInteger# @1024
                                1024
                                0
                            GHC.Maybe.Just[3891110078048108571]
                              (v[6989586621679214219] :: Clash.Sized.Internal.Index.Index[8214565720323789680]
                                                           1024) ->
                              v[6989586621679214219][LocalId])
                         (GHC.Maybe.Nothing[3891110078048108568]
                            @(GHC.Tuple.(,)[3746994889972252676]
                                (Clash.Sized.Internal.Index.Index[8214565720323789680]
                                   1024)
                                (Clash.Sized.Internal.Unsigned.Unsigned[8214565720323789682]
                                   8)))))
           in eta1[4755801206503243959][LocalId]
         in case ds4[8214565720324007144][LocalId] of
              GHC.Maybe.Nothing[3891110078048108568]  ->
                <prefixName>"$fMonoidFanIn_z"
                GHC.Maybe.Nothing[3891110078048108568]
                  @(GHC.Maybe.Maybe[3674937295934324792]
                      (Clash.Sized.Internal.Unsigned.Unsigned[8214565720323789682]
                         8))
              GHC.Maybe.Just[3891110078048108571]
                (ipv[8214565720324006969] :: GHC.Maybe.Maybe[3674937295934324792]
                                               (Clash.Sized.Internal.Unsigned.Unsigned[8214565720323789682]
                                                  8)) ->
                ds4[8214565720324007144][LocalId]
    in Board.$fApplicativeAddressing2[14224][GlobalId]
         addr1[3858][LocalId]
    Run with '-fclash-spec-limit=N' to increase the specialisation limit to N.

    The source location of the error is not exact, only indicative, as it is acquired 
    after optimizations. The actual location of the error can be in a function that is 
    inlined. To prevent inlining of those functions, annotate them with a NOINLINE pragma.
   |
91 | topEntity clk rst addr wr = withClockResetEnable clk rst enableGen $ memoryMap addr wr $ do
   | ^^^^^^^^^

However, similar to #1611, if I remove the part that actually uses TypeReps, i.e. if I change topEntity to

topEntity clk rst addr wr = withClockResetEnable clk rst enableGen $ memoryMap addr wr $ do
    () <- return ()
    return ()

then it synthesizes without complaints. So now I don't know if this is the same problem as #1611 or not...

gergoerdi commented 3 years ago

Using the Clash instrumentation from https://github.com/clash-lang/clash-compiler/issues/1611#issuecomment-743139000, I see the following set of unfoldable definitions:

--
Control.Monad.Trans.RWS.Lazy.$tcRWST1 
Data.Monoid.$fSemigroupAp_$cstimes 
Data.Monoid.$fSemigroupFirst1 
Data.Monoid.$tcAp1 
Data.OldList.intercalate_$spoly_go 
Data.OldList.prependToAll 
Data.Semigroup.Internal.$wstimesDefault 
Data.Sequence.Internal.$fFunctorSeq_$cfmap 
Data.Sequence.Internal.$fIsListSeq_mkTree 
Data.Sequence.Internal.$w$slookupTree 
Data.Sequence.Internal.$wupdate 
Data.Typeable.Internal.$tcAppOrCon1 
Data.Typeable.Internal.$wmkTrCon 
Data.Typeable.Internal.eqTypeRep 
Data.Typeable.Internal.fpTYPELiftedRep 
Data.Typeable.Internal.typeRepTyCon 
Foreign.Storable.$fStorableFingerprint_$s$wpeekW64 
Foreign.Storable.$fStorableFingerprint_$s$wpokeW64 
GHC.Base.++ 
GHC.Base.++_$s++ 
GHC.Base.map 
GHC.CString.unpackAppendCString# 
GHC.Fingerprint.fingerprintString_go 
GHC.Integer.Type.czeroBigNat 
GHC.Integer.Type.nullBigNat 
GHC.Integer.Type.oneBigNat 
GHC.Integer.Type.zeroBigNat 
GHC.List.$wlenAcc 
GHC.List.reverse1 
GHC.List.splitAt_$s$wsplitAt' 
GHC.Prim.addWordC# 
GHC.Prim.byteArrayContents# 
GHC.Prim.catch# 
GHC.Prim.getSizeofMutableByteArray# 
GHC.Prim.indexWordArray# 
GHC.Prim.newAlignedPinnedByteArray# 
GHC.Prim.newByteArray# 
GHC.Prim.newPinnedByteArray# 
GHC.Prim.plusAddr# 
GHC.Prim.proxy# 
GHC.Prim.raise# 
GHC.Prim.raiseIO# 
GHC.Prim.readWord8OffAddr# 
GHC.Prim.readWordArray# 
GHC.Prim.realWorld# 
GHC.Prim.reallyUnsafePtrEquality# 
GHC.Prim.resizeMutableByteArray# 
GHC.Prim.seq# 
GHC.Prim.setByteArray# 
GHC.Prim.shrinkMutableByteArray# 
GHC.Prim.sizeofByteArray# 
GHC.Prim.timesWord2# 
GHC.Prim.touch# 
GHC.Prim.unsafeFreezeByteArray# 
GHC.Prim.void# 
GHC.Prim.writeWord8OffAddr# 
GHC.Prim.writeWordArray# 
GHC.Show.$fShowInteger_jprintb 
GHC.Show.$witos' 
GHC.Show.$wjblock' 
GHC.Show.$wjsplitf 
GHC.Show.$wshowWord 
GHC.Show.showLitString 
GHC.Stack.Types.getCallStack 
GHC.Types.$tc'AddrRep1 
GHC.Types.$tcTYPE1 

Most of these are base definitions so they aren't recompiled with -fexpose-all-unfoldings. The RWS one is surprising to me, because I have asked stack to recompile mtl and transformers with the flag. @christiaanb are you seeing a similar list?

And as for the Typeable stuff, of course if the whole of memoryMap is compiled away, there is no HDL-time stuff remaining that uses them. So there shouldn't be a need for blackboxes implementing the Typeable methods, I think.

alex-mckenna commented 3 years ago

Conjecture: things from transformers are likely included because it is a boot library. I believe this is why things from integer-gmp are included as well. Most of these seem alright to be missing from the primitive evaluation to me, although some I can't immediately figure out what they are (other than some worker)

christiaanb commented 3 years ago

@gergoerdi Yeah, I'm seeing a similar list. And you're correct, we should not have blackboxes for the Typeable methods, but we do need their Core representations in order to do any compile-time evaluation.

Edit: wrt Control.Monad.Trans.RWS.Lazy.$tcRWST1 perhaps stack is refusing to rebuild transformer because as @alex-mckenna suggests, it's a boot library. That's my conjecture as I have the exact same unfolding missing and I didn't rebuild transformers.

gergoerdi commented 3 years ago

So dependent-map (and specifically, its use of Typeable) is the only blocking problem here? I will try to think about a non-dependent-map-using solution then.

christiaanb commented 3 years ago

It's hard to determine whether there is an additional problem on top of dependent-maps use of Typeable.

gergoerdi commented 3 years ago

I got rid of using dependent-map by using unsafeCoerce internally (yuck!). First, it looks promising, because taking the smallest example and pushing it through Clash works:

{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving #-}
{-# LANGUAGE RankNTypes #-}
module Board where

import Clash.Prelude
import Data.Maybe
import Control.Monad
import Control.Monad.RWS

import Unsafe.Coerce
import Data.Map as Map

newtype Component s addr = Component Int
    deriving newtype (Eq, Ord)

newtype FanIn dom a = FanIn{ getFanIn :: Signal dom `Ap` First a }
    deriving newtype (Semigroup, Monoid)

newtype AddrMap s dom = AddrMap{ addrMap :: Map Int (FanIn dom ()) }
    deriving newtype (Monoid)

instance Semigroup (AddrMap s dom) where
    AddrMap map1 <> AddrMap map2 = AddrMap $ unionWithKey (const mappend) map1 map2

newtype Addressing s dom dat addr a = Addressing
    { unAddressing :: RWS
          (FanIn dom addr, AddrMap s dom)
          (FanIn dom (Maybe dat), AddrMap s dom)
          Int
          a
    }
    deriving newtype (Functor, Applicative, Monad)

memoryMap
    :: Signal dom (Maybe addr)
    -> (forall s. Addressing s dom dat addr a)
    -> (Signal dom (Maybe dat), a)
memoryMap addr body = (join <$> firstIn read, x)
  where
    (x, (read, conns)) = evalRWS (unAddressing body) (fanInMaybe addr, conns) 0

readWrite_
    :: (HiddenClockResetEnable dom)
    => (Signal dom (Maybe addr') -> Signal dom (Maybe dat))
    -> Addressing s dom dat addr (Component s addr')
readWrite_ mkComponent = Addressing $ do
    component@(Component i) <- Component <$> get <* modify succ
    (_, addrs) <- ask
    let addr = firstIn . fromMaybe mempty $ Map.lookup i (addrMap addrs)
        read = mkComponent $ unsafeCoerce addr
    tell (fanIn read, mempty)
    return component

ram0
    :: (HiddenClockResetEnable dom, 1 <= n, NFDataX dat, Num dat)
    => SNat n
    -> Addressing s dom dat addr (Component s (Index n))
ram0 size@SNat = readWrite_ $ \addr ->
    fmap Just $ blockRam1 ClearOnReset size 0 (fromMaybe 0 <$> addr) (pure Nothing)

connect
    :: Component s addr
    -> Addressing s dom dat addr ()
connect component@(Component i) = Addressing $ do
    (addr, _) <- ask
    tell (mempty, AddrMap $ Map.singleton i $ unsafeCoerce addr)

firstIn :: FanIn dom a -> Signal dom (Maybe a)
firstIn = fmap getFirst . getAp . getFanIn

fanInMaybe :: Signal dom (Maybe a) -> FanIn dom a
fanInMaybe = FanIn . Ap . fmap First

fanIn :: Signal dom a -> FanIn dom a
fanIn = fanInMaybe . fmap pure

topEntity
    :: Clock System
    -> Reset System
    -> Signal System (Maybe (Index 0x0400))
    -> (Signal System (Maybe (Unsigned 8)), ())
topEntity clk rst addr = withClockResetEnable clk rst enableGen $ memoryMap addr $ do
    ram <- ram0 (SNat @0x0400)
    connect ram

But then if I add matchAddr back so that topEntity can get a bit more complex, we are back to square one, except this time it's containers's Data.Map.lookup screwing things up:

matchAddr
    :: (addr -> Maybe addr')
    -> Addressing s dom dat addr' a
    -> Addressing s dom dat addr a
matchAddr match body = Addressing $ rws $ \(addr, addrs) s ->
  let addr' = fanInMaybe . fmap (match =<<) . firstIn $ addr
  in runRWS (unAddressing body) (addr', addrs) s

from
    :: forall addr' s dom dat addr a. (Integral addr, Ord addr, Integral addr', Bounded addr')
    => addr
    -> Addressing s dom dat addr' a
    -> Addressing s dom dat addr a
from base = matchAddr $ \addr -> do
    guard $ addr >= base
    let offset = addr - base
    guard $ offset <= lim
    return $ fromIntegral offset
  where
    lim = fromIntegral (maxBound :: addr')

topEntity
    :: Clock System
    -> Reset System
    -> Signal System (Maybe (Index 0x0800))
    -> (Signal System (Maybe (Unsigned 8)), ())
topEntity clk rst addr = withClockResetEnable clk rst enableGen $ memoryMap addr $ do
    ram <- ram0 (SNat @0x0400)
    from 0x0000 $ connect ram
    from 0x0400 $ connect ram
Clash.Normalize.Transformations(432): InlineNonRep: c$Board.$slookup_go13_wild[12457728] already inlined 200 times in:Board.$slookup_go13[12025728]
Type of the subject is: Data.Map.Internal.Map[8214565720323790163]
  GHC.Types.Int[3674937295934324766]
  (Clash.Signal.Internal.Signal[8214565720323789649]
     "System"
     (GHC.Maybe.Maybe[3674937295934324792]
        GHC.Tuple.()[3746994889972252672]))

So it seems this will never quite work out, unless we can get the boot libraries compiled with -fexpose-all-unfoldings (and probably also -fno-worker-wrapper)... Would this approach work for that, to decouple Clash from GHC and have Clash compile everything on its own?

christiaanb commented 3 years ago

I think we want the “fat interface files” described here: https://gitlab.haskell.org/ghc/ghc/-/issues/10871 Which apparently is something ghcide wants as well.

Also to check whether fat interface files would be a solution is to import Data.Map.Internal and copy/paste the definitions of the functions that you’re using from Data.Map

gergoerdi commented 3 years ago

Also to check whether fat interface files would be a solution is to import Data.Map.Internal and copy/paste the definitions of the functions that you’re using from Data.Map

Yeah I had the same idea in the meantime, I'm working on this right now.

gergoerdi commented 3 years ago

Well, it's pretty much the same with an included copy of Data.Map, just with different non-unfoldable functions remaining:

--
Control.Monad.Trans.RWS.Lazy.$tcRWST1 
Data.Data.$c(,) 
Data.Data.$fData[]_$cgfoldl 
Data.Data.$fData[]_$cgmapM 
Data.Data.$fData[]_$cgmapQ 
Data.Data.$fData[]_$cgmapQi 
Data.Data.$fData[]_$cgmapQl 
Data.Data.$fData[]_$cgmapQr 
Data.Data.$fData[]_$cgmapT 
Data.Data.$fData[]_$cgunfold 
Data.Data.$w$cgmapMo11 
Data.Data.$w$cgmapMp16 
Data.Data.consConstr 
Data.Data.listDataType 
Data.Data.nilConstr 
Data.Functor.Classes.$fEq1NonEmpty_$cliftEq1 
Data.Functor.Classes.$fOrd1NonEmpty_$cliftCompare1 
Data.Functor.Classes.$fRead1(,)_$cliftReadList 
Data.Monoid.$fSemigroupAp_$cstimes 
Data.Monoid.$fSemigroupFirst1 
Data.Monoid.$tcAp1 
Data.OldList.intercalate_$spoly_go 
Data.OldList.prependToAll 
Data.Semigroup.Internal.$wstimesDefault 
Data.Sequence.Internal.$fFunctorSeq_$cfmap 
Data.Sequence.Internal.$fIsListSeq_mkTree 
Data.Sequence.Internal.$w$slookupTree 
Data.Sequence.Internal.$wupdate 
Data.Typeable.Internal.$wmkTrCon 
Data.Typeable.Internal.eqTypeRep 
Data.Typeable.Internal.fpTYPELiftedRep 
Foreign.Storable.$fStorableFingerprint_$s$wpeekW64 
Foreign.Storable.$fStorableFingerprint_$s$wpokeW64 
GHC.Base.++ 
GHC.Base.++_$s++ 
GHC.Base.eqString 
GHC.Base.map 
GHC.CString.unpackAppendCString# 
GHC.Classes.$fEq[]_$c== 
GHC.Classes.$fOrd[]_$ccompare 
GHC.Integer.Type.czeroBigNat 
GHC.Integer.Type.nullBigNat 
GHC.Integer.Type.oneBigNat 
GHC.Integer.Type.zeroBigNat 
GHC.List.$wlenAcc 
GHC.List.reverse1 
GHC.List.splitAt_$s$wsplitAt' 
GHC.Prim.addWordC# 
GHC.Prim.byteArrayContents# 
GHC.Prim.catch# 
GHC.Prim.getSizeofMutableByteArray# 
GHC.Prim.indexWordArray# 
GHC.Prim.newAlignedPinnedByteArray# 
GHC.Prim.newByteArray# 
GHC.Prim.newPinnedByteArray# 
GHC.Prim.plusAddr# 
GHC.Prim.proxy# 
GHC.Prim.raise# 
GHC.Prim.raiseIO# 
GHC.Prim.readWord8OffAddr# 
GHC.Prim.readWordArray# 
GHC.Prim.realWorld# 
GHC.Prim.reallyUnsafePtrEquality# 
GHC.Prim.resizeMutableByteArray# 
GHC.Prim.seq# 
GHC.Prim.setByteArray# 
GHC.Prim.shrinkMutableByteArray# 
GHC.Prim.sizeofByteArray# 
GHC.Prim.timesWord2# 
GHC.Prim.touch# 
GHC.Prim.unsafeFreezeByteArray# 
GHC.Prim.void# 
GHC.Prim.writeWord8OffAddr# 
GHC.Prim.writeWordArray# 
GHC.Read.list 
GHC.Real.$wf1 
GHC.Show.$fShow(,)_$sgo1 
GHC.Show.$fShowInteger_jprintb 
GHC.Show.$witos' 
GHC.Show.$wjblock' 
GHC.Show.$wjsplitf 
GHC.Show.showLitString 
GHC.Stack.Types.getCallStack 
GHC.Types.$tc'AddrRep1 
GHC.Types.$tcTYPE1 
Text.ParserCombinators.ReadP.$fAlternativeP_$c<|> 
Text.ParserCombinators.ReadP.gather_gath 
Text.ParserCombinators.ReadP.run 
Text.ParserCombinators.ReadP.skipSpaces2 
Text.Read.Lex.expect2 
_INTERNAL_.{__pkg_ccall base-4.13.0.0 Addr#
_INTERNAL_.{__pkg_ccall base-4.13.0.0 Int#
_INTERNAL_.{__pkg_ccall integer-gmp-1.0.2.0 ByteArray#
_INTERNAL_.{__pkg_ccall integer-gmp-1.0.2.0 forall s.
gergoerdi commented 3 years ago

Eventualy, the specializer chokes on the (copied, and thus unfoldable) version of Data.Map.lookup:

    Hit specialisation limit 100 on function `c$Board.topEntity_go[11136]'.

    The function `c$Board.topEntity_go[11136] :: GHC.Types.Int[3674937295934324766]
                               -> Containers.Data.Map.Internal.Map[8214565720323896040]
                                    GHC.Types.Int[3674937295934324766]
                                    (Board.FanIn[8214565720324216431]
                                       "System"
                                       GHC.Tuple.()[3746994889972252672])
                               -> Clash.Signal.Internal.Signal[8214565720324039903]
                                    "System"
                                    (Data.Monoid.First[8214565720323804916]
                                       GHC.Tuple.()[3746994889972252672])' is most likely recursive, and looks like it is being indefinitely specialized on a growing argument.

    Body of `c$Board.topEntity_go[11136] :: GHC.Types.Int[3674937295934324766]
                               -> Containers.Data.Map.Internal.Map[8214565720323896040]
                                    GHC.Types.Int[3674937295934324766]
                                    (Board.FanIn[8214565720324216431]
                                       "System"
                                       GHC.Tuple.()[3746994889972252672])
                               -> Clash.Signal.Internal.Signal[8214565720324039903]
                                    "System"
                                    (Data.Monoid.First[8214565720323804916]
                                       GHC.Tuple.()[3746994889972252672])':
    λ(ds2[7205759403792923820] :: GHC.Types.Int[3674937295934324766]) ->
    λ(ds3[7205759403792923821] :: Containers.Data.Map.Internal.Map[8214565720323896040]
                                    GHC.Types.Int[3674937295934324766]
                                    (Board.FanIn[8214565720324216431]
                                       "System"
                                       GHC.Tuple.()[3746994889972252672])) ->
    letrec
      ds4[6341068275337788595] :: GHC.Types.Int[3674937295934324766]
      = ds2[7205759403792923820][LocalId]
    in case ds4[6341068275337788595][LocalId] of
         GHC.Types.I#[3891110078048108562]
           (ipv[8286623314362161582] :: GHC.Prim.Int#[3674937295934324764]) ->
           case ds3[7205759403792923821][LocalId] of
             Containers.Data.Map.Internal.Bin[8214565720323896041]
               (ipv1[8286623314361847773] :: GHC.Types.Int[3674937295934324766])
                 (ipv2[8286623314361847774] :: GHC.Types.Int[3674937295934324766])
                 (ipv3[8286623314361847775] :: Board.FanIn[8214565720324216431]
                                                 "System"
                                                 GHC.Tuple.()[3746994889972252672])
                 (ipv4[8286623314361847776] :: Containers.Data.Map.Internal.Map[8214565720323896040]
                                                 GHC.Types.Int[3674937295934324766]
                                                 (Board.FanIn[8214565720324216431]
                                                    "System"
                                                    GHC.Tuple.()[3746994889972252672]))
                 (ipv5[8286623314361847777] :: Containers.Data.Map.Internal.Map[8214565720323896040]
                                                 GHC.Types.Int[3674937295934324766]
                                                 (Board.FanIn[8214565720324216431]
                                                    "System"
                                                    GHC.Tuple.()[3746994889972252672])) ->
               case ipv2[8286623314361847774][LocalId] of
                 GHC.Types.I#[3891110078048108562]
                   (y#[6989586621679066384] :: GHC.Prim.Int#[3674937295934324764]) ->
                   case GHC.Prim.<#
                          ipv[8286623314362161582][LocalId]
                          y#[6989586621679066384][LocalId] of
                     _ ->
                       case GHC.Prim.==#
                              ipv[8286623314362161582][LocalId]
                              y#[6989586621679066384][LocalId] of
                         _ ->
                           c$Board.topEntity_go[11136][GlobalId]
                             ds4[6341068275337788595][LocalId]
                             ipv5[8286623314361847777][LocalId]
                         1 ->
                           ipv3[8286623314361847775][LocalId]
                     1 ->
                       c$Board.topEntity_go[11136][GlobalId]
                         ds4[6341068275337788595][LocalId]
                         ipv4[8286623314361847776][LocalId]
             Containers.Data.Map.Internal.Tip[8214565720323896042]
                ->
               Board.$fMonoidFanIn1[8214565720324228805][GlobalId]
                 @GHC.Tuple.()[3746994889972252672]
                 @"System"

    Argument (in position: 1) that triggered termination:
    <prefixName>"memoryMap_r1"
    letrec
      $dIP2[8286623314362162379] :: GHC.Classes.IP[3602879701896396848]
                                      "enable"
                                      (Clash.Signal.Internal.Enable[8214565720324039873]
                                         "System")
      = <prefixName>"memoryMap_ds"
      <prefixName>"topEntity_ds"
      <prefixName>"ram0"
      letrec
        $d(%,%)1[8286623314362161981] :: GHC.Classes.(%,%)[7710162562058289156]
                                           (GHC.Classes.IP[3602879701896396848]
                                              "enable"
                                              (Clash.Signal.Internal.Enable[8214565720324039873]
                                                 "System"))
                                           (Clash.Signal.Internal.KnownDomain[8214565720324039880]
                                              "System")
        = <prefixName>"$p3(%,,%)"
        GHC.Classes.C:(%,%)[8214565720323792659]
          @(GHC.Classes.IP[3602879701896396848]
              "enable"
              (Clash.Signal.Internal.Enable[8214565720324039873]
                 "System"))
          @(Clash.Signal.Internal.KnownDomain[8214565720324039880]
              "System")
          <prefixName>"enableGen"
          (Clash.Signal.Internal.Enable[8214565720324098780]
             @"System"
             <prefixName>"enableGen1"
             GHC.Types.True[3891110078048108589])
          (Clash.Signal.Internal.C:KnownDomain[8214565720324100457]
             @"System"
             (GHC.CString.unpackCString# "System")
             (Clash.Signal.Internal.SDomainConfiguration[8214565720324039893]
                @"System"
                @(Clash.Signal.Internal.DomainConfiguration[8214565720324039862]
                    "System"
                    10000
                    Clash.Signal.Internal.Rising[8214565720324039857]
                    Clash.Signal.Internal.Asynchronous[8214565720324039884]
                    Clash.Signal.Internal.Defined[8214565720324039875]
                    Clash.Signal.Internal.ActiveHigh[8214565720324039887])
                @10000
                @Clash.Signal.Internal.Rising[8214565720324039857]
                @Clash.Signal.Internal.Asynchronous[8214565720324039884]
                @Clash.Signal.Internal.Defined[8214565720324039875]
                @Clash.Signal.Internal.ActiveHigh[8214565720324039887]
                (_CO_
                   @(GHC.Prim.~#[3674937295934324842]
                       Clash.Signal.Internal.DomainConfiguration[8214565720324039861]
                       Clash.Signal.Internal.DomainConfiguration[8214565720324039861]
                       (Clash.Signal.Internal.DomainConfiguration[8214565720324039862]
                          "System"
                          10000
                          Clash.Signal.Internal.Rising[8214565720324039857]
                          Clash.Signal.Internal.Asynchronous[8214565720324039884]
                          Clash.Signal.Internal.Defined[8214565720324039875]
                          Clash.Signal.Internal.ActiveHigh[8214565720324039887])
                       (Clash.Signal.Internal.DomainConfiguration[8214565720324039862]
                          "System"
                          10000
                          Clash.Signal.Internal.Rising[8214565720324039857]
                          Clash.Signal.Internal.Asynchronous[8214565720324039884]
                          Clash.Signal.Internal.Defined[8214565720324039875]
                          Clash.Signal.Internal.ActiveHigh[8214565720324039887])))
                (Clash.Promoted.Symbol.SSymbol @"System"
                   (GHC.CString.unpackCString# "System"))
                (Clash.Promoted.Nat.SNat[8214565720324039825]
                   @10000
                   10000)
                (Clash.Signal.Internal.SRising[8214565720324039891]
                   @Clash.Signal.Internal.Rising[8214565720324039857]
                   (_CO_
                      @(GHC.Prim.~#[3674937295934324842]
                          Clash.Signal.Internal.ActiveEdge[8214565720324039855]
                          Clash.Signal.Internal.ActiveEdge[8214565720324039855]
                          Clash.Signal.Internal.Rising[8214565720324039857]
                          Clash.Signal.Internal.Rising[8214565720324039857])))
                (Clash.Signal.Internal.SAsynchronous[8214565720324039898]
                   @Clash.Signal.Internal.Asynchronous[8214565720324039884]
                   (_CO_
                      @(GHC.Prim.~#[3674937295934324842]
                          Clash.Signal.Internal.ResetKind[8214565720324039883]
                          Clash.Signal.Internal.ResetKind[8214565720324039883]
                          Clash.Signal.Internal.Asynchronous[8214565720324039884]
                          Clash.Signal.Internal.Asynchronous[8214565720324039884])))
                (Clash.Signal.Internal.SDefined[8214565720324039895]
                   @Clash.Signal.Internal.Defined[8214565720324039875]
                   (_CO_
                      @(GHC.Prim.~#[3674937295934324842]
                          Clash.Signal.Internal.InitBehavior[8214565720324039874]
                          Clash.Signal.Internal.InitBehavior[8214565720324039874]
                          Clash.Signal.Internal.Defined[8214565720324039875]
                          Clash.Signal.Internal.Defined[8214565720324039875])))
                (Clash.Signal.Internal.SActiveHigh[8214565720324039901]
                   @Clash.Signal.Internal.ActiveHigh[8214565720324039887]
                   (_CO_
                      @(GHC.Prim.~#[3674937295934324842]
                          Clash.Signal.Internal.ResetPolarity[8214565720324039886]
                          Clash.Signal.Internal.ResetPolarity[8214565720324039886]
                          Clash.Signal.Internal.ActiveHigh[8214565720324039887]
                          Clash.Signal.Internal.ActiveHigh[8214565720324039887])))))
      in <prefixName>"$p1(%,%)"
      case $d(%,%)1[8286623314362161981][LocalId] of
        GHC.Classes.C:(%,%)[8214565720323792659]
          (c$sel[3] :: GHC.Classes.IP[3602879701896396848]
                         "enable"
                         (Clash.Signal.Internal.Enable[8214565720324039873]
                            "System"))
            (c$wild[2] :: Clash.Signal.Internal.KnownDomain[8214565720324039880]
                            "System") ->
          c$sel[3][LocalId]
    in letrec
         a'[6989586621679449989] :: Board.FanIn[8214565720324216431]
                                      "System"
                                      (GHC.Maybe.Maybe[3674937295934324792]
                                         (Clash.Sized.Internal.Unsigned.Unsigned[8214565720324039938]
                                            8))
         = <prefixName>"$fMonoidFirst_$c<>"
         letrec
           ds4[8214565720324239755] :: Data.Monoid.First[8214565720323804916]
                                         (GHC.Maybe.Maybe[3674937295934324792]
                                            (Clash.Sized.Internal.Unsigned.Unsigned[8214565720324039938]
                                               8))
           = <prefixName>"fanIn2"
           letrec
             eta[4755801206503244181] :: GHC.Maybe.Maybe[3674937295934324792]
                                           (GHC.Maybe.Maybe[3674937295934324792]
                                              (Clash.Sized.Internal.Unsigned.Unsigned[8214565720324039938]
                                                 8))
             = GHC.Maybe.Just[3891110078048108571]
                 @(GHC.Maybe.Maybe[3674937295934324792]
                     (Clash.Sized.Internal.Unsigned.Unsigned[8214565720324039938]
                        8))
                 (letrec
                    addr1[6989586621679445142] :: Clash.Signal.Internal.Signal[8214565720324039903]
                                                    "System"
                                                    (GHC.Maybe.Maybe[3674937295934324792]
                                                       (Clash.Sized.Internal.Index.Index[8214565720324039936]
                                                          1024))
                    = <prefixName>"$fGeneric1First2"
                    letrec
                      x[8214565720324239622] :: Data.Monoid.First[8214565720323804916]
                                                  GHC.Tuple.()[3746994889972252672]
                      = c$Board.topEntity_go[24275126][GlobalId]
                          (GHC.Types.I# 0)
                          addr1[25363][LocalId]
                          clk[6989586621679444994][LocalId]
                          rst[6989586621679444995][LocalId]
                    in x[8214565720324239622][LocalId]
                 in GHC.Maybe.Just[3891110078048108571]
                      @(Clash.Sized.Internal.Unsigned.Unsigned[8214565720324039938]
                          8)
                      (Clash.Explicit.BlockRam.blockRam1[25360][GlobalId]
                         <prefixName>"topEntity_ds"
                         <prefixName>"ram0"
                         <prefixName>"$p2(%,%)"
                         <prefixName>"topEntity_ds"
                         <prefixName>"ram0"
                         <prefixName>"$p1(%,,%)"
                         (Clash.Signal.Internal.C:KnownDomain[8214565720324100457]
                            @"System"
                            (GHC.CString.unpackCString# "System")
                            (Clash.Signal.Internal.SDomainConfiguration[8214565720324039893]
                               @"System"
                               @(Clash.Signal.Internal.DomainConfiguration[8214565720324039862]
                                   "System"
                                   10000
                                   Clash.Signal.Internal.Rising[8214565720324039857]
                                   Clash.Signal.Internal.Asynchronous[8214565720324039884]
                                   Clash.Signal.Internal.Defined[8214565720324039875]
                                   Clash.Signal.Internal.ActiveHigh[8214565720324039887])
                               @10000
                               @Clash.Signal.Internal.Rising[8214565720324039857]
                               @Clash.Signal.Internal.Asynchronous[8214565720324039884]
                               @Clash.Signal.Internal.Defined[8214565720324039875]
                               @Clash.Signal.Internal.ActiveHigh[8214565720324039887]
                               (_CO_
                                  @(GHC.Prim.~#[3674937295934324842]
                                      Clash.Signal.Internal.DomainConfiguration[8214565720324039861]
                                      Clash.Signal.Internal.DomainConfiguration[8214565720324039861]
                                      (Clash.Signal.Internal.DomainConfiguration[8214565720324039862]
                                         "System"
                                         10000
                                         Clash.Signal.Internal.Rising[8214565720324039857]
                                         Clash.Signal.Internal.Asynchronous[8214565720324039884]
                                         Clash.Signal.Internal.Defined[8214565720324039875]
                                         Clash.Signal.Internal.ActiveHigh[8214565720324039887])
                                      (Clash.Signal.Internal.DomainConfiguration[8214565720324039862]
                                         "System"
                                         10000
                                         Clash.Signal.Internal.Rising[8214565720324039857]
                                         Clash.Signal.Internal.Asynchronous[8214565720324039884]
                                         Clash.Signal.Internal.Defined[8214565720324039875]
                                         Clash.Signal.Internal.ActiveHigh[8214565720324039887])))
                               (Clash.Promoted.Symbol.SSymbol @"System"
                                  (GHC.CString.unpackCString# "System"))
                               (Clash.Promoted.Nat.SNat[8214565720324039825]
                                  @10000
                                  10000)
                               (Clash.Signal.Internal.SRising[8214565720324039891]
                                  @Clash.Signal.Internal.Rising[8214565720324039857]
                                  (_CO_
                                     @(GHC.Prim.~#[3674937295934324842]
                                         Clash.Signal.Internal.ActiveEdge[8214565720324039855]
                                         Clash.Signal.Internal.ActiveEdge[8214565720324039855]
                                         Clash.Signal.Internal.Rising[8214565720324039857]
                                         Clash.Signal.Internal.Rising[8214565720324039857])))
                               (Clash.Signal.Internal.SAsynchronous[8214565720324039898]
                                  @Clash.Signal.Internal.Asynchronous[8214565720324039884]
                                  (_CO_
                                     @(GHC.Prim.~#[3674937295934324842]
                                         Clash.Signal.Internal.ResetKind[8214565720324039883]
                                         Clash.Signal.Internal.ResetKind[8214565720324039883]
                                         Clash.Signal.Internal.Asynchronous[8214565720324039884]
                                         Clash.Signal.Internal.Asynchronous[8214565720324039884])))
                               (Clash.Signal.Internal.SDefined[8214565720324039895]
                                  @Clash.Signal.Internal.Defined[8214565720324039875]
                                  (_CO_
                                     @(GHC.Prim.~#[3674937295934324842]
                                         Clash.Signal.Internal.InitBehavior[8214565720324039874]
                                         Clash.Signal.Internal.InitBehavior[8214565720324039874]
                                         Clash.Signal.Internal.Defined[8214565720324039875]
                                         Clash.Signal.Internal.Defined[8214565720324039875])))
                               (Clash.Signal.Internal.SActiveHigh[8214565720324039901]
                                  @Clash.Signal.Internal.ActiveHigh[8214565720324039887]
                                  (_CO_
                                     @(GHC.Prim.~#[3674937295934324842]
                                         Clash.Signal.Internal.ResetPolarity[8214565720324039886]
                                         Clash.Signal.Internal.ResetPolarity[8214565720324039886]
                                         Clash.Signal.Internal.ActiveHigh[8214565720324039887]
                                         Clash.Signal.Internal.ActiveHigh[8214565720324039887])))))
                         GHC.Stack.Types.EmptyCallStack[8214565720323830335]
                         (GHC.Types.Eq#[3891110078048108574]
                            @GHC.Types.Bool[3674937295934324744]
                            @(GHC.TypeNats.<=?[3674937295934325074] 1 1024)
                            @GHC.Types.True[3891110078048108589]
                            (_CO_
                               @(GHC.Prim.~#[3674937295934324842]
                                   GHC.Types.Bool[3674937295934324744]
                                   GHC.Types.Bool[3674937295934324744]
                                   (GHC.TypeNats.<=?[3674937295934325074] 1 1024)
                                   GHC.Types.True[3891110078048108589])))
                         <prefixName>"topEntity_ds"
                         <prefixName>"ram0"
                         <prefixName>"$p1(%,%)"
                         <prefixName>"topEntity_ds"
                         <prefixName>"ram0"
                         <prefixName>"$p1(%,,%)"
                         clk[6989586621679444994][LocalId]
                         <prefixName>"topEntity_ds"
                         <prefixName>"ram0"
                         <prefixName>"$p1(%,%)"
                         <prefixName>"$p2(%,,%)"
                         rst[6989586621679444995][LocalId]
                         $dIP2[8286623314362162379][LocalId]
                         (Clash.Explicit.BlockRam.ClearOnReset[8214565720324039816]
                            @GHC.Types.True[3891110078048108589]
                            (_CO_
                               @(GHC.Prim.~#[3674937295934324842]
                                   GHC.Types.Bool[3674937295934324744]
                                   GHC.Types.Bool[3674937295934324744]
                                   GHC.Types.True[3891110078048108589]
                                   GHC.Types.True[3891110078048108589])))
                         (Clash.Promoted.Nat.SNat[8214565720324039825]
                            @1024
                            1024)
                         <prefixName>"fromInteger"
                         (<prefixName>"$s$fNumUnsigned"
                            <prefixName>"$s$fNumUnsigned6"
                            Clash.Sized.Internal.Unsigned.fromInteger# @8 8
                            0)
                         (case addr1[6989586621679445142][LocalId] of
                            GHC.Maybe.Nothing[3891110078048108568]  ->
                              Clash.Sized.Internal.Index.fromInteger# @1024
                                1024
                                0
                            GHC.Maybe.Just[3891110078048108571]
                              (v[6989586621679448424] :: Clash.Sized.Internal.Index.Index[8214565720324039936]
                                                           1024) ->
                              v[6989586621679448424][LocalId])
                         (GHC.Maybe.Nothing[3891110078048108568]
                            @(GHC.Tuple.(,)[3746994889972252676]
                                (Clash.Sized.Internal.Index.Index[8214565720324039936]
                                   1024)
                                (Clash.Sized.Internal.Unsigned.Unsigned[8214565720324039938]
                                   8)))))
           in eta[4755801206503244181][LocalId]
         in case ds4[8214565720324239755][LocalId] of
              GHC.Maybe.Nothing[3891110078048108568]  ->
                <prefixName>"$fMonoidFanIn1"
                GHC.Maybe.Nothing[3891110078048108568]
                  @(GHC.Maybe.Maybe[3674937295934324792]
                      (Clash.Sized.Internal.Unsigned.Unsigned[8214565720324039938]
                         8))
              GHC.Maybe.Just[3891110078048108571]
                (ipv[8214565720324239762] :: GHC.Maybe.Maybe[3674937295934324792]
                                               (Clash.Sized.Internal.Unsigned.Unsigned[8214565720324039938]
                                                  8)) ->
                ds4[8214565720324239755][LocalId]
    in letrec
         addr1[6989586621679445000] :: Board.FanIn[8214565720324216431]
                                         "System"
                                         (Clash.Sized.Internal.Index.Index[8214565720324039936]
                                            1024)
         = <prefixName>"topEntity_eta"
         <prefixName>"fanIn2"
         letrec
           eta[4755801206503243795] :: GHC.Maybe.Maybe[3674937295934324792]
                                         (Clash.Sized.Internal.Index.Index[8214565720324039936]
                                            1024)
           = <prefixName>"$fMonadMaybe_$c>>="
           case <prefixName>"firstIn"
             <prefixName>"$fGeneric1First2"
             <prefixName>"memoryMap_r1"
             <prefixName>"fanInMaybe2"
             <prefixName>"fanIn2"
             addr1[25363][LocalId] of
             GHC.Maybe.Nothing[3891110078048108568]  ->
               GHC.Maybe.Nothing[3891110078048108568]
                 @(Clash.Sized.Internal.Index.Index[8214565720324039936]
                     1024)
             GHC.Maybe.Just[3891110078048108571]
               (x[8214565720324239227] :: Clash.Sized.Internal.Index.Index[8214565720324039936]
                                            2048) ->
               case Clash.Sized.Internal.Index.ge# @2048
                      x[8214565720324239227][LocalId]
                      (Clash.Sized.Internal.Index.fromInteger# @2048
                         2048
                         0) of
                 GHC.Types.False[3891110078048108556]  ->
                   GHC.Maybe.Nothing[3891110078048108568]
                     @(Clash.Sized.Internal.Index.Index[8214565720324039936]
                         1024)
                 GHC.Types.True[3891110078048108589]  ->
                   letrec
                     offset[8286623314362161957] :: Clash.Sized.Internal.Index.Index[8214565720324039936]
                                                      2048
                     = Clash.Sized.Internal.Index.-# @2048
                         (Clash.Transformations.removedArg
                            @GHC.Natural.Natural[3674937295934324786])
                         x[8214565720324239227][LocalId]
                         (Clash.Sized.Internal.Index.fromInteger# @2048
                            2048
                            0)
                   in case Clash.Sized.Internal.Index.le# @2048
                             offset[8286623314362161957][LocalId]
                             <prefixName>"topEntity_ds1"
                             <prefixName>"from_$sfrom"
                             (Clash.Sized.Internal.Index.fromInteger# @2048
                                2048
                                (Clash.Sized.Internal.Index.toInteger# @1024
                                   (Clash.Sized.Internal.Index.maxBound# @1024
                                      1024))) of
                        GHC.Types.False[3891110078048108556]  ->
                          GHC.Maybe.Nothing[3891110078048108568]
                            @(Clash.Sized.Internal.Index.Index[8214565720324039936]
                                1024)
                        GHC.Types.True[3891110078048108589]  ->
                          GHC.Maybe.Just[3891110078048108571]
                            @(Clash.Sized.Internal.Index.Index[8214565720324039936]
                                1024)
                            (Clash.Sized.Internal.Index.fromInteger# @1024
                               1024
                               (Clash.Sized.Internal.Index.toInteger# @2048
                                  offset[8286623314362161957][LocalId]))
         in eta[4755801206503243795][LocalId]
    in letrec
         addr1[6989586621679445436] :: Board.FanIn[8214565720324216431]
                                         "System"
                                         (Clash.Sized.Internal.Index.Index[8214565720324039936]
                                            1024)
         = <prefixName>"topEntity_eta"
         <prefixName>"fanIn2"
         letrec
           eta[4755801206503243789] :: GHC.Maybe.Maybe[3674937295934324792]
                                         (Clash.Sized.Internal.Index.Index[8214565720324039936]
                                            1024)
           = <prefixName>"$fMonadMaybe_$c>>="
           case <prefixName>"firstIn"
             <prefixName>"$fGeneric1First2"
             <prefixName>"memoryMap_r1"
             <prefixName>"fanInMaybe2"
             <prefixName>"fanIn2"
             addr1[25363][LocalId] of
             GHC.Maybe.Nothing[3891110078048108568]  ->
               GHC.Maybe.Nothing[3891110078048108568]
                 @(Clash.Sized.Internal.Index.Index[8214565720324039936]
                     1024)
             GHC.Maybe.Just[3891110078048108571]
               (x[8214565720324239227] :: Clash.Sized.Internal.Index.Index[8214565720324039936]
                                            2048) ->
               case Clash.Sized.Internal.Index.ge# @2048
                      x[8214565720324239227][LocalId]
                      (Clash.Sized.Internal.Index.fromInteger# @2048
                         2048
                         1024) of
                 GHC.Types.False[3891110078048108556]  ->
                   GHC.Maybe.Nothing[3891110078048108568]
                     @(Clash.Sized.Internal.Index.Index[8214565720324039936]
                         1024)
                 GHC.Types.True[3891110078048108589]  ->
                   letrec
                     offset[8286623314362161957] :: Clash.Sized.Internal.Index.Index[8214565720324039936]
                                                      2048
                     = Clash.Sized.Internal.Index.-# @2048
                         (Clash.Transformations.removedArg
                            @GHC.Natural.Natural[3674937295934324786])
                         x[8214565720324239227][LocalId]
                         (Clash.Sized.Internal.Index.fromInteger# @2048
                            2048
                            1024)
                   in case Clash.Sized.Internal.Index.le# @2048
                             offset[8286623314362161957][LocalId]
                             <prefixName>"topEntity_ds2"
                             <prefixName>"from_$sfrom"
                             (Clash.Sized.Internal.Index.fromInteger# @2048
                                2048
                                (Clash.Sized.Internal.Index.toInteger# @1024
                                   (Clash.Sized.Internal.Index.maxBound# @1024
                                      1024))) of
                        GHC.Types.False[3891110078048108556]  ->
                          GHC.Maybe.Nothing[3891110078048108568]
                            @(Clash.Sized.Internal.Index.Index[8214565720324039936]
                                1024)
                        GHC.Types.True[3891110078048108589]  ->
                          GHC.Maybe.Just[3891110078048108571]
                            @(Clash.Sized.Internal.Index.Index[8214565720324039936]
                                1024)
                            (Clash.Sized.Internal.Index.fromInteger# @1024
                               1024
                               (Clash.Sized.Internal.Index.toInteger# @2048
                                  offset[8286623314362161957][LocalId]))
         in eta[4755801206503243789][LocalId]
    in Board.$fApplicativeAddressing_$sunionWithKey[24274924][GlobalId]
         addr1[6989586621679445000][LocalId]
         addr1[6989586621679445436][LocalId]
    Run with '-fclash-spec-limit=N' to increase the specialisation limit to N.

    The source location of the error is not exact, only indicative, as it is acquired 
    after optimizations. The actual location of the error can be in a function that is 
    inlined. To prevent inlining of those functions, annotate them with a NOINLINE pragma.
    |
103 | topEntity clk rst addr = withClockResetEnable clk rst enableGen $ memoryMap addr $ do
    | ^^^^^^^^^
christiaanb commented 3 years ago

This is somewhat better. Specialization is run last in the “eliminate-non-representable-values” phase, indicating the compiler got a whole lot further.

I’ll see whether I can make sense of the Debug output once I have a chance to sit behind a computer.

Thanks for all the effort in helping with the debugging so far!

gergoerdi commented 3 years ago

Thanks for all the effort in helping with the debugging so far!

Well I am completely blocked on this so I am trying everything I can in frustration...

gergoerdi commented 3 years ago

My full code including the copied containers is at https://github.com/gergoerdi/clash-issue-1536/tree/no-typeable

christiaanb commented 3 years ago

I've "somewhat" reduced it to:

{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE MagicHash #-}
module Test where

import Clash.Prelude
import Data.Maybe
import Control.Monad
import Control.Monad.RWS

import Unsafe.Coerce
import GHC.Magic (lazy)

import Data.Foldable as Foldable
import GHC.Exts ( reallyUnsafePtrEquality#, isTrue# )

type Size     = Int

data Map k a  = Bin {-# UNPACK #-} !Size !k a !(Map k a) !(Map k a)
              | Tip

data StrictPair a b = !a :*: !b

infixr 1 :*:

-- | Convert a strict pair to a standard pair.
toPair :: StrictPair a b -> (a, b)
toPair (x :*: y) = (x, y)
{-# INLINE toPair #-}

unions :: (Foldable f, Ord k) => f (Map k a) -> Map k a
unions ts
  = Foldable.foldl' union Test.empty ts

singleton :: k -> a -> Map k a
singleton k x = Bin 1 k x Tip Tip
{-# INLINE singleton #-}

lookup :: Ord k => k -> Map k a -> Maybe a
lookup = go
  where
    go !_ Tip = Nothing
    go k (Bin _ kx x l r) = case compare k kx of
      LT -> go k l
      GT -> go k r
      EQ -> Just x
{-# INLINABLE lookup #-}

instance (Ord k) => Monoid (Map k v) where
    mempty  = Test.empty
    mconcat = unions
    mappend = union

instance (Ord k) => Semigroup (Map k v) where
    (<>)    = union

ptrEq :: a -> a -> Bool
-- ptrEq x y = isTrue# (reallyUnsafePtrEquality# x y)
ptrEq _ _ = False

empty :: Map k a
empty = Tip
{-# INLINE empty #-}

insert :: Ord k => k -> a -> Map k a -> Map k a
insert kx0 = go kx0 kx0
  where
    -- Unlike insertR, we only get sharing here
    -- when the inserted value is at the same address
    -- as the present value. We try anyway; this condition
    -- seems particularly likely to occur in 'union'.
    go :: Ord k => k -> k -> a -> Map k a -> Map k a
    go orig !_  x Tip = Test.singleton (lazy orig) x
    go orig !kx x t@(Bin sz ky y l r) =
        case compare kx ky of
            LT | l' `ptrEq` l -> t
               | otherwise -> balanceL ky y l' r
               where !l' = go orig kx x l
            GT | r' `ptrEq` r -> t
               | otherwise -> balanceR ky y l r'
               where !r' = go orig kx x r
            EQ | x `ptrEq` y && (lazy orig `seq` (orig `ptrEq` ky)) -> t
               | otherwise -> Bin sz (lazy orig) x l r
{-# INLINABLE insert #-}

insertR :: Ord k => k -> a -> Map k a -> Map k a
insertR kx0 = go kx0 kx0
  where
    go :: Ord k => k -> k -> a -> Map k a -> Map k a
    go orig !_  x Tip = Test.singleton (lazy orig) x
    go orig !kx x t@(Bin _ ky y l r) =
        case compare kx ky of
            LT | l' `ptrEq` l -> t
               | otherwise -> balanceL ky y l' r
               where !l' = go orig kx x l
            GT | r' `ptrEq` r -> t
               | otherwise -> balanceR ky y l r'
               where !r' = go orig kx x r
            EQ -> t
{-# INLINABLE insertR #-}

union :: Ord k => Map k a -> Map k a -> Map k a
union t1 Tip  = t1
union t1 (Bin _ k x Tip Tip) = insertR k x t1
union (Bin _ k x Tip Tip) t2 = insert k x t2
union Tip t2 = t2
union t1@(Bin _ k1 x1 l1 r1) t2 = case Test.split k1 t2 of
  (l2, r2) | l1l2 `ptrEq` l1 && r1r2 `ptrEq` r1 -> t1
           | otherwise -> link k1 x1 l1l2 r1r2
           where !l1l2 = union l1 l2
                 !r1r2 = union r1 r2
{-# INLINABLE union #-}

unionWithKey :: Ord k => (k -> a -> a -> a) -> Map k a -> Map k a -> Map k a
unionWithKey _f t1 Tip = t1
unionWithKey f t1 (Bin _ k x Tip Tip) = insertWithKeyR f k x t1
unionWithKey f (Bin _ k x Tip Tip) t2 = insertWithKey f k x t2
unionWithKey _f Tip t2 = t2
unionWithKey f (Bin _ k1 x1 l1 r1) t2 = case splitLookup k1 t2 of
  (l2, mb, r2) -> case mb of
      Nothing -> link k1 x1 l1l2 r1r2
      Just x2 -> link k1 (f k1 x1 x2) l1l2 r1r2
    where !l1l2 = unionWithKey f l1 l2
          !r1r2 = unionWithKey f r1 r2
{-# INLINABLE unionWithKey #-}

link :: k -> a -> Map k a -> Map k a -> Map k a
link kx x Tip r  = insertMin kx x r
link kx x l Tip  = insertMax kx x l
link kx x l@(Bin sizeL ky y ly ry) r@(Bin sizeR kz z lz rz)
  | delta*sizeL < sizeR  = balanceL kz z (link kx x l lz) rz
  | delta*sizeR < sizeL  = balanceR ky y ly (link kx x ry r)
  | otherwise            = bin kx x l r

bin :: k -> a -> Map k a -> Map k a -> Map k a
bin k x l r
  = Bin (size l + size r + 1) k x l r
{-# INLINE bin #-}

size :: Map k a -> Int
size Tip              = 0
size (Bin sz _ _ _ _) = sz
{-# INLINE size #-}

balanceR :: k -> a -> Map k a -> Map k a -> Map k a
balanceR k x l r = case l of
  Tip -> case r of
           Tip -> Bin 1 k x Tip Tip
           (Bin _ _ _ Tip Tip) -> Bin 2 k x Tip r
           (Bin _ rk rx Tip rr@(Bin _ _ _ _ _)) -> Bin 3 rk rx (Bin 1 k x Tip Tip) rr
           (Bin _ rk rx (Bin _ rlk rlx _ _) Tip) -> Bin 3 rlk rlx (Bin 1 k x Tip Tip) (Bin 1 rk rx Tip Tip)
           (Bin rs rk rx rl@(Bin rls rlk rlx rll rlr) rr@(Bin rrs _ _ _ _))
             | rls < ratio*rrs -> Bin (1+rs) rk rx (Bin (1+rls) k x Tip rl) rr
             | otherwise -> Bin (1+rs) rlk rlx (Bin (1+size rll) k x Tip rll) (Bin (1+rrs+size rlr) rk rx rlr rr)

  (Bin ls _ _ _ _) -> case r of
           Tip -> Bin (1+ls) k x l Tip

           (Bin rs rk rx rl rr)
              | rs > delta*ls  -> case (rl, rr) of
                   (Bin rls rlk rlx rll rlr, Bin rrs _ _ _ _)
                     | rls < ratio*rrs -> Bin (1+ls+rs) rk rx (Bin (1+ls+rls) k x l rl) rr
                     | otherwise -> Bin (1+ls+rs) rlk rlx (Bin (1+ls+size rll) k x l rll) (Bin (1+rrs+size rlr) rk rx rlr rr)
                   (_, _) -> error "Failure in Data.Map.balanceR"
              | otherwise -> Bin (1+ls+rs) k x l r
{-# NOINLINE balanceR #-}

delta,ratio :: Int
delta = 3
ratio = 2

balanceL :: k -> a -> Map k a -> Map k a -> Map k a
balanceL k x l r = case r of
  Tip -> case l of
           Tip -> Bin 1 k x Tip Tip
           (Bin _ _ _ Tip Tip) -> Bin 2 k x l Tip
           (Bin _ lk lx Tip (Bin _ lrk lrx _ _)) -> Bin 3 lrk lrx (Bin 1 lk lx Tip Tip) (Bin 1 k x Tip Tip)
           (Bin _ lk lx ll@(Bin _ _ _ _ _) Tip) -> Bin 3 lk lx ll (Bin 1 k x Tip Tip)
           (Bin ls lk lx ll@(Bin lls _ _ _ _) lr@(Bin lrs lrk lrx lrl lrr))
             | lrs < ratio*lls -> Bin (1+ls) lk lx ll (Bin (1+lrs) k x lr Tip)
             | otherwise -> Bin (1+ls) lrk lrx (Bin (1+lls+size lrl) lk lx ll lrl) (Bin (1+size lrr) k x lrr Tip)

  (Bin rs _ _ _ _) -> case l of
           Tip -> Bin (1+rs) k x Tip r

           (Bin ls lk lx ll lr)
              | ls > delta*rs  -> case (ll, lr) of
                   (Bin lls _ _ _ _, Bin lrs lrk lrx lrl lrr)
                     | lrs < ratio*lls -> Bin (1+ls+rs) lk lx ll (Bin (1+rs+lrs) k x lr r)
                     | otherwise -> Bin (1+ls+rs) lrk lrx (Bin (1+lls+size lrl) lk lx ll lrl) (Bin (1+rs+size lrr) k x lrr r)
                   (_, _) -> error "Failure in Data.Map.balanceL"
              | otherwise -> Bin (1+ls+rs) k x l r
{-# NOINLINE balanceL #-}

insertMax,insertMin :: k -> a -> Map k a -> Map k a
insertMax kx x t
  = case t of
      Tip -> Test.singleton kx x
      Bin _ ky y l r
          -> balanceR ky y l (insertMax kx x r)

insertMin kx x t
  = case t of
      Tip -> Test.singleton kx x
      Bin _ ky y l r
          -> balanceL ky y (insertMin kx x l) r

splitLookup :: Ord k => k -> Map k a -> (Map k a,Maybe a,Map k a)
splitLookup k0 m = case go k0 m of
     StrictTriple l mv r -> (l, mv, r)
  where
    go :: Ord k => k -> Map k a -> StrictTriple (Map k a) (Maybe a) (Map k a)
    go !k t =
      case t of
        Tip            -> StrictTriple Tip Nothing Tip
        Bin _ kx x l r -> case compare k kx of
          LT -> let StrictTriple lt z gt = go k l
                    !gt' = link kx x gt r
                in StrictTriple lt z gt'
          GT -> let StrictTriple lt z gt = go k r
                    !lt' = link kx x l lt
                in StrictTriple lt' z gt
          EQ -> StrictTriple l (Just x) r
{-# INLINABLE splitLookup #-}

data StrictTriple a b c = StrictTriple !a !b !c

insertWithKey :: Ord k => (k -> a -> a -> a) -> k -> a -> Map k a -> Map k a
insertWithKey = go
  where
    go :: Ord k => (k -> a -> a -> a) -> k -> a -> Map k a -> Map k a
    go _ !kx x Tip = Test.singleton kx x
    go f kx x (Bin sy ky y l r) =
        case compare kx ky of
            LT -> balanceL ky y (go f kx x l) r
            GT -> balanceR ky y l (go f kx x r)
            EQ -> Bin sy kx (f kx x y) l r
{-# INLINABLE insertWithKey #-}

insertWithKeyR :: Ord k => (k -> a -> a -> a) -> k -> a -> Map k a -> Map k a
insertWithKeyR = go
  where
    go :: Ord k => (k -> a -> a -> a) -> k -> a -> Map k a -> Map k a
    go _ !kx x Tip = Test.singleton kx x
    go f kx x (Bin sy ky y l r) =
        case compare kx ky of
            LT -> balanceL ky y (go f kx x l) r
            GT -> balanceR ky y l (go f kx x r)
            EQ -> Bin sy ky (f ky y x) l r
{-# INLINABLE insertWithKeyR #-}

split :: Ord k => k -> Map k a -> (Map k a,Map k a)
split !k0 t0 = toPair $ go k0 t0
  where
    go k t =
      case t of
        Tip            -> Tip :*: Tip
        Bin _ kx x l r -> case compare k kx of
          LT -> let (lt :*: gt) = go k l in lt :*: link kx x gt r
          GT -> let (lt :*: gt) = go k r in link kx x l lt :*: gt
          EQ -> (l :*: r)
{-# INLINABLE split #-}

newtype Component s addr = Component Int
    deriving newtype (Eq, Ord)

newtype FanIn a = FanIn{ getFanIn :: First a }
    deriving newtype (Semigroup, Monoid)

newtype AddrMap s = AddrMap{ addrMap :: Map Int (FanIn (Index 0x0400)) }
    deriving newtype (Monoid)

instance Semigroup (AddrMap s) where
    AddrMap map1 <> AddrMap map2 = AddrMap $ unionWithKey (const mappend) map1 map2

newtype Addressing s dat addr a = Addressing
    { unAddressing :: RWS
          (FanIn addr, AddrMap s)
          (FanIn (Maybe dat), AddrMap s)
          Int
          a
    }
    deriving newtype (Functor, Applicative, Monad)

memoryMap
    :: Maybe addr
    -> (forall s. Addressing s dat addr a)
    -> (Maybe dat, a)
memoryMap addr body = (join (firstIn read), x)
  where
    (x, (read, conns)) = evalRWS (unAddressing body) (fanInMaybe addr, conns) 0

readWrite_
    :: ((Maybe (Index 1024)) -> (Maybe dat))
    -> Addressing s dat addr (Component s (Index 1024))
readWrite_ mkComponent = Addressing $ do
    component@(Component i) <- Component <$> get <* modify succ
    (_, addrs) <- ask
    let addr = firstIn . fromMaybe mempty $ Test.lookup i (addrMap addrs)
        read = mkComponent addr
    tell (fanIn read, mempty)
    return component

ram0
    :: (1 <= n)
    => SNat n
    -> Addressing s (Index 1024) addr (Component s (Index 1024))
ram0 size@SNat = readWrite_ $ \addr ->
    Just $ negate (fromMaybe 2 addr)

connect
    :: Component s (Index 1024)
    -> Addressing s dat (Index 1024) ()
connect component@(Component i) = Addressing $ do
    (addr, _) <- ask
    tell (mempty, AddrMap $ Test.singleton i $ addr)

firstIn :: FanIn a -> Maybe a
firstIn = getFirst . getFanIn

fanInMaybe :: Maybe a -> FanIn a
fanInMaybe = FanIn . First

fanIn :: a -> FanIn a
fanIn = fanInMaybe . pure

matchAddr
    :: (addr -> Maybe addr')
    -> Addressing s dat addr' a
    -> Addressing s dat addr a
matchAddr match body = Addressing $ rws $ \(addr, addrs) s ->
  let addr' = fanInMaybe . (match =<<) . firstIn $ addr
  in runRWS (unAddressing body) (addr', addrs) s

from
    :: forall addr' s dat addr a. (Integral addr, Ord addr, Integral addr', Bounded addr')
    => addr
    -> Addressing s dat addr' a
    -> Addressing s dat addr a
from base = matchAddr $ \addr -> do
    guard $ addr >= base
    let offset = addr - base
    guard $ offset <= lim
    return $ fromIntegral offset
  where
    lim = fromIntegral (maxBound :: addr')

topEntity
    :: Maybe (Index 0x0400)
    -> ((Maybe (Index 0x0400)), ())
topEntity addr = memoryMap addr $ do
    ram <- ram0 (SNat @0x0400)
    from 0x0000 $ connect ram
    -- from 0x0400 $ connect ram

I've removed the Ap (Signal dom) aspect of it, and also removed the unsafeCoerce, uncommenting the last from 0x0400 $ connect ram seems to throw Clash into an infinite loop.

One thing I also noticed is that sometimes we have:

\x -> let y = expr_using_x in expr_not_using_y

Which is problamatic because dead code elimination happens at a very late stage because the transformation is deemed expensive: n^2 for n number of let-bindings. But n is in general small before the ANF transform, so perhaps we should run it more often during the constant propagation phase, which is also doing all the inlining. It might be that it's doing all the inlining in the expr_using_x from the above example.

christiaanb commented 3 years ago

I've tried adding dead code elimination inside of the main loop, but it doesn't seem to solve the issue.

We don't really have the resources to investigate further (the debug logs are just too big to analyze in a sensible amount of time). I think we must conclude that Clash currently cannot translate the kind of recursive descriptions given here, or those of #1611

Hopefully, the partial evaluation work done at https://github.com/clash-lang/clash-compiler/tree/partial-evaluator-primitives-easier will be able to handle these kind of recursive description properly. The problem there is that the work is far from production ready, and due to circumstances, development on that feature will be halted for the coming year (unless it becomes sponsored).

It thus pains me to say that (typed) template haskell is probably the only way forward at this moment in time.

gergoerdi commented 3 years ago

We don't really have the resources to investigate further (the debug logs are just too big to analyze in a sensible amount of time).

By this, do you mean they are too big because Clash is doing a lot of work, or because the code to reproduce this issue is still too large? In other words, is there room for me to try to reduce my code further, or is this a lost cause?

christiaanb commented 3 years ago

Clash is doing too much work, which is both a result of the size of the test case and fact it seems to get stuck in an inlining loop. But the logs are huge (thousands of transformations, order of gigabytes size), and so it's hard to pin down whether one of the transformations is doing something dumb/wrong or where a (slightly) different order/strategy of the transformations would lead to termination.

Anyhow, I've managed to get something which does compile while still being close to the original code in spirit:

{-# LANGUAGE DerivingStrategies, GeneralizedNewtypeDeriving #-}
module Test3 where

import Clash.Prelude
import Data.Maybe
import Control.Monad
import Control.Monad.RWS

newtype Component addr = Component Int
    deriving newtype (Eq, Ord)

newtype FanIn a = FanIn{ getFanIn :: First a }
    deriving newtype (Semigroup, Monoid)

newtype AddrMap = AddrMap{ addrMap :: [(Int,(FanIn (Index 0x0400)))] }
    deriving newtype (Monoid)

instance Semigroup (AddrMap) where
    AddrMap map1 <> AddrMap map2 = AddrMap $ unionWithKeyList (const mappend) map1 map2

unionWithKeyList :: Ord k => (k -> a -> a -> a) -> [(k,a)] -> [(k,a)] -> [(k,a)]
unionWithKeyList f l r = foldList (insertWithKeyList f) r l

foldList :: (a -> b -> b) -> b -> [a] -> b
foldList _ z []     = z
foldList f z (x:xs) = foldList f (f x z) xs

insertWithKeyList :: Ord k => (k -> a -> a -> a) -> (k,a) -> [(k,a)] -> [(k,a)]
insertWithKeyList _ k [] = [k]
insertWithKeyList f (k,a) ((k1,b):xs) = case compare k k1 of
  LT -> (k,a):(k1,b):xs
  EQ -> (k,f k a b) : xs
  GT -> (k1,b):insertWithKeyList f (k,a) xs

lookupList :: Eq k => k -> [(k,a)] -> Maybe a
lookupList _ [] = Nothing
lookupList k ((k1,a):xs) = if k == k1 then Just a else lookupList k xs

singletonList :: k -> a -> [(k,a)]
singletonList k a = [(k,a)]

newtype Addressing dat addr a = Addressing
    { unAddressing :: RWS
          (FanIn addr, AddrMap)
          (FanIn (Maybe dat), AddrMap)
          Int
          a
    }
    deriving newtype (Functor, Applicative, Monad)

memoryMap
    :: Maybe addr
    -> (Addressing dat addr a)
    -> (Maybe dat, a)
memoryMap addr body = (join (firstIn read), x)
  where
    (x, (read, conns)) = evalRWS (unAddressing body) (fanInMaybe addr, conns) 0

readWrite_
    :: ((Maybe (Index 1024)) -> (Maybe dat))
    -> Addressing dat addr (Component (Index 1024))
readWrite_ mkComponent = Addressing $ do
    component@(Component i) <- Component <$> get <* modify succ
    (_, addrs) <- ask
    let addr = firstIn . fromMaybe mempty $ lookupList i (addrMap addrs)
        read = mkComponent addr
    tell (fanIn read, mempty)
    return component

ram0
    :: (1 <= n)
    => SNat n
    -> Addressing (Index 1024) addr (Component (Index 1024))
ram0 size@SNat = readWrite_ $ \addr ->
    Just $ negate (fromMaybe 2 addr)

connect
    :: Component (Index 1024)
    -> Addressing dat (Index 1024) ()
connect component@(Component i) = Addressing $ do
    (addr, _) <- ask
    tell (mempty, AddrMap $ singletonList i $ addr)

firstIn :: FanIn a -> Maybe a
firstIn = getFirst . getFanIn

fanInMaybe :: Maybe a -> FanIn a
fanInMaybe = FanIn . First

fanIn :: a -> FanIn a
fanIn = fanInMaybe . pure

matchAddr
    :: (addr -> Maybe addr')
    -> Addressing dat addr' a
    -> Addressing dat addr a
matchAddr match body = Addressing $ rws $ \(addr, addrs) s ->
  let addr' = fanInMaybe . (match =<<) . firstIn $ addr
  in runRWS (unAddressing body) (addr', addrs) s

from
    :: forall addr' dat addr a. (Integral addr, Ord addr, Integral addr', Bounded addr')
    => addr
    -> Addressing dat addr' a
    -> Addressing dat addr a
from base = matchAddr $ \addr -> do
    guard $ addr >= base
    let offset = addr - base
    guard $ offset <= lim
    return $ fromIntegral offset
  where
    lim = fromIntegral (maxBound :: addr')

topEntity
    :: Maybe (Index 0x0400)
    -> ((Maybe (Index 0x0400)), ())
topEntity addr = memoryMap addr $ do
    ram <- ram0 (SNat @0x0400)
    from 0x0000 $ connect ram
    from 0x0200 $ connect ram

I think slowly building this code back up to the intended use would be a more fruitful exercise than trying figure out how we could get the original code to compile. I would go towards building up in this order:

  1. Add back the RankN type
  2. Introduce the Ap Signal again
  3. Introduce the use of blockRam again
  4. Introduce the use of unsafeCoerce again.

Perhaps there's a step 3.5 between 3 and 4 so that connect has a polymorphic type signature again, but perhaps that requires the unsafeCoerce of step 4. You'll need to synthesize often to make sure it keeps working, and report back when it stops working. As you can see, when you build back up, you cannot depend on recursive functions from pre-compiled dependencies as they might not have an unfolding. Perhaps that would be a step 5, try and use functions from pre-compiled dependencies.

gergoerdi commented 3 years ago

I think slowly building this code back up to the intended use would be a more fruitful exercise than trying figure out how we could get the original code to compile.

This is great stuff!

I managed to get it back to the unsafeCoerce-using version (albeit without testing its runtime behaviour yet... but hey, it compiles!) using your alist-for-Map idea (see this version). Then, when I try to apply the same idea to DMap (i.e. an assoc-list of DSum k fs), then I get the following which I think could be the result of an easy-to-fix oversight:

src/Board.hs:17:1: error:

    Hit specialisation limit 100 on function `c$Board.topEntity_go_go[4436866]'.

    The function `c$Board.topEntity_go_go[4436866] :: GHC.Prim.Int#[3674937295934324764]
                                    -> GHC.Ptr.Ptr[3674937295934324890]
                                         GHC.Word.Word8[3674937295934324860]
                                    -> GHC.Prim.Addr#[3674937295934324738]
                                    -> GHC.Types.[][3674937295934324788]
                                         GHC.Word.Word8[3674937295934324860]
                                    -> GHC.Prim.Int#[3674937295934324764]
                                    -> GHC.Prim.State#[3674937295934324836]
                                         GHC.Prim.RealWorld[3674937295934324808]
                                    -> GHC.Prim.(#,#)[3819052484010180612]
                                         (GHC.Types.TupleRep[3891110078048108760]
                                            (GHC.Types.[][3891110078048108577]
                                               GHC.Types.RuntimeRep[3674937295934324926]))
                                         GHC.Types.LiftedRep[3891110078048108766]
                                         (GHC.Prim.State#[3674937295934324836]
                                            GHC.Prim.RealWorld[3674937295934324808])
                                         GHC.Fingerprint.Type.Fingerprint[8214565720323785011]' is most likely recursive, and looks like it is being indefinitely specialized on a growing argument.

    Body of `c$Board.topEntity_go_go[4436866] :: GHC.Prim.Int#[3674937295934324764]
                                    -> GHC.Ptr.Ptr[3674937295934324890]
                                         GHC.Word.Word8[3674937295934324860]
                                    -> GHC.Prim.Addr#[3674937295934324738]
                                    -> GHC.Types.[][3674937295934324788]
                                         GHC.Word.Word8[3674937295934324860]
                                    -> GHC.Prim.Int#[3674937295934324764]
                                    -> GHC.Prim.State#[3674937295934324836]
                                         GHC.Prim.RealWorld[3674937295934324808]
                                    -> GHC.Prim.(#,#)[3819052484010180612]
                                         (GHC.Types.TupleRep[3891110078048108760]
                                            (GHC.Types.[][3891110078048108577]
                                               GHC.Types.RuntimeRep[3674937295934324926]))
                                         GHC.Types.LiftedRep[3891110078048108766]
                                         (GHC.Prim.State#[3674937295934324836]
                                            GHC.Prim.RealWorld[3674937295934324808])
                                         GHC.Fingerprint.Type.Fingerprint[8214565720323785011]':
    λ(ww2[8214565720324017915] :: GHC.Prim.Int#[3674937295934324764]) ->
    λ(ptr[8214565720324017917] :: GHC.Ptr.Ptr[3674937295934324890]
                                    GHC.Word.Word8[3674937295934324860]) ->
    λ(a[8214565720324017934] :: GHC.Prim.Addr#[3674937295934324738]) ->
    λ(ds[8214565720324017942] :: GHC.Types.[][3674937295934324788]
                                   GHC.Word.Word8[3674937295934324860]) ->
    λ(ds1[8214565720324017943] :: GHC.Prim.Int#[3674937295934324764]) ->
    λ(eta2[8214565720324017944] :: GHC.Prim.State#[3674937295934324836]
                                     GHC.Prim.RealWorld[3674937295934324808]) ->
    case ds[8214565720324017942][LocalId] of
      GHC.Types.[][3891110078048108577]  ->
        c$Board.topEntity_exit[14273][GlobalId]
          ww2[8214565720324017915][LocalId]
          ptr[8214565720324017917][LocalId]
          eta2[8214565720324017944][LocalId]
      GHC.Types.:[3891110078048108550]
        (val1[8214565720324017949] :: GHC.Word.Word8[3674937295934324860])
          (vals2[8214565720324017950] :: GHC.Types.[][3674937295934324788]
                                           GHC.Word.Word8[3674937295934324860]) ->
        case val1[8214565720324017949][LocalId] of
          GHC.Word.W8#[3891110078048108583]
            (x1[8214565720324017954] :: GHC.Prim.Word#[3674937295934324854]) ->
            letrec
              s1[8214565720324017956] :: GHC.Prim.State#[3674937295934324836]
                                           GHC.Prim.RealWorld[3674937295934324808]
              = GHC.Prim.writeWord8OffAddr#
                  @GHC.Prim.RealWorld[3674937295934324808]
                  a[8214565720324017934][LocalId]
                  ds1[8214565720324017943][LocalId]
                  x1[8214565720324017954][LocalId]
                  eta2[8214565720324017944][LocalId]
            in case s1[8214565720324017956][LocalId] of
                 _ ->
                   c$Board.topEntity_go_go[4436866][GlobalId]
                     ww2[8214565720324017915][LocalId]
                     ptr[8214565720324017917][LocalId]
                     a[8214565720324017934][LocalId]
                     vals2[8214565720324017950][LocalId]
                     (GHC.Prim.+# ds1[8214565720324017943][LocalId]
                        1)
                     s1[8214565720324017956][LocalId]

    Argument (in position: 4) that triggered termination:
    GHC.Prim.+#
      (GHC.Prim.+#
         (GHC.Prim.+#
            (GHC.Prim.+#
               (GHC.Prim.+#
                  (GHC.Prim.+#
                     (GHC.Prim.+#
                        (GHC.Prim.+#
                           (GHC.Prim.+#
                              (GHC.Prim.+#
                                 (GHC.Prim.+#
                                    (GHC.Prim.+#
                                       (GHC.Prim.+#
                                          (GHC.Prim.+#
                                             (GHC.Prim.+#
                                                (GHC.Prim.+#
                                                   (GHC.Prim.+#
                                                      (GHC.Prim.+#
                                                         (GHC.Prim.+#
                                                            (GHC.Prim.+#
                                                               (GHC.Prim.+#
                                                                  (GHC.Prim.+#
                                                                     (GHC.Prim.+#
                                                                        (GHC.Prim.+#
                                                                           (GHC.Prim.+#
                                                                              (GHC.Prim.+#
                                                                                 (GHC.Prim.+#
                                                                                    (GHC.Prim.+#
                                                                                       (GHC.Prim.+#
                                                                                          (GHC.Prim.+#
                                                                                             (GHC.Prim.+#
                                                                                                (GHC.Prim.+#
                                                                                                   (GHC.Prim.+#
                                                                                                      (GHC.Prim.+#
                                                                                                         (GHC.Prim.+#
                                                                                                            (GHC.Prim.+#
                                                                                                               (GHC.Prim.+#
                                                                                                                  (GHC.Prim.+#
                                                                                                                     (GHC.Prim.+#
                                                                                                                        (GHC.Prim.+#
                                                                                                                           (GHC.Prim.+#
                                                                                                                              (GHC.Prim.+#
                                                                                                                                 (GHC.Prim.+#
                                                                                                                                    (GHC.Prim.+#
                                                                                                                                       (GHC.Prim.+#
                                                                                                                                          (GHC.Prim.+#
                                                                                                                                             (GHC.Prim.+#
                                                                                                                                                (GHC.Prim.+#
                                                                                                                                                   (GHC.Prim.+#
                                                                                                                                                      (GHC.Prim.+#
                                                                                                                                                         (GHC.Prim.+#
                                                                                                                                                            (GHC.Prim.+#
                                                                                                                                                               (GHC.Prim.+#
                                                                                                                                                                  (GHC.Prim.+#
                                                                                                                                                                     (GHC.Prim.+#
                                                                                                                                                                        (GHC.Prim.+#
                                                                                                                                                                           (GHC.Prim.+#
                                                                                                                                                                              (GHC.Prim.+#
                                                                                                                                                                                 (GHC.Prim.+#
                                                                                                                                                                                    (GHC.Prim.+#
                                                                                                                                                                                       (GHC.Prim.+#
                                                                                                                                                                                          (GHC.Prim.+#
                                                                                                                                                                                             (GHC.Prim.+#
                                                                                                                                                                                                (GHC.Prim.+#
                                                                                                                                                                                                   (GHC.Prim.+#
                                                                                                                                                                                                      (GHC.Prim.+#
                                                                                                                                                                                                         (GHC.Prim.+#
                                                                                                                                                                                                            (GHC.Prim.+#
                                                                                                                                                                                                               (GHC.Prim.+#
                                                                                                                                                                                                                  (GHC.Prim.+#
                                                                                                                                                                                                                     (GHC.Prim.+#
                                                                                                                                                                                                                        (GHC.Prim.+#
                                                                                                                                                                                                                           (GHC.Prim.+#
                                                                                                                                                                                                                              (GHC.Prim.+#
                                                                                                                                                                                                                                 (GHC.Prim.+#
                                                                                                                                                                                                                                    (GHC.Prim.+#
                                                                                                                                                                                                                                       (GHC.Prim.+#
                                                                                                                                                                                                                                          (GHC.Prim.+#
                                                                                                                                                                                                                                             (GHC.Prim.+#
                                                                                                                                                                                                                                                (GHC.Prim.+#
                                                                                                                                                                                                                                                   (GHC.Prim.+#
                                                                                                                                                                                                                                                      (GHC.Prim.+#
                                                                                                                                                                                                                                                         (GHC.Prim.+#
                                                                                                                                                                                                                                                            (GHC.Prim.+#
                                                                                                                                                                                                                                                               (GHC.Prim.+#
                                                                                                                                                                                                                                                                  (GHC.Prim.+#
                                                                                                                                                                                                                                                                     (GHC.Prim.+#
                                                                                                                                                                                                                                                                        (GHC.Prim.+#
                                                                                                                                                                                                                                                                           (GHC.Prim.+#
                                                                                                                                                                                                                                                                              (GHC.Prim.+#
                                                                                                                                                                                                                                                                                 (GHC.Prim.+#
                                                                                                                                                                                                                                                                                    (GHC.Prim.+#
                                                                                                                                                                                                                                                                                       (GHC.Prim.+#
                                                                                                                                                                                                                                                                                          (GHC.Prim.+#
                                                                                                                                                                                                                                                                                             (GHC.Prim.+#
                                                                                                                                                                                                                                                                                                (GHC.Prim.+#
                                                                                                                                                                                                                                                                                                   (GHC.Prim.+#
                                                                                                                                                                                                                                                                                                      (GHC.Prim.+#
                                                                                                                                                                                                                                                                                                         (GHC.Prim.+#
                                                                                                                                                                                                                                                                                                            (GHC.Prim.+#
                                                                                                                                                                                                                                                                                                               (GHC.Prim.+#
                                                                                                                                                                                                                                                                                                                  1
                                                                                                                                                                                                                                                                                                                  1)
                                                                                                                                                                                                                                                                                                               1)
                                                                                                                                                                                                                                                                                                            1)
                                                                                                                                                                                                                                                                                                         1)
                                                                                                                                                                                                                                                                                                      1)
                                                                                                                                                                                                                                                                                                   1)
                                                                                                                                                                                                                                                                                                1)
                                                                                                                                                                                                                                                                                             1)
                                                                                                                                                                                                                                                                                          1)
                                                                                                                                                                                                                                                                                       1)
                                                                                                                                                                                                                                                                                    1)
                                                                                                                                                                                                                                                                                 1)
                                                                                                                                                                                                                                                                              1)
                                                                                                                                                                                                                                                                           1)
                                                                                                                                                                                                                                                                        1)
                                                                                                                                                                                                                                                                     1)
                                                                                                                                                                                                                                                                  1)
                                                                                                                                                                                                                                                               1)
                                                                                                                                                                                                                                                            1)
                                                                                                                                                                                                                                                         1)
                                                                                                                                                                                                                                                      1)
                                                                                                                                                                                                                                                   1)
                                                                                                                                                                                                                                                1)
                                                                                                                                                                                                                                             1)
                                                                                                                                                                                                                                          1)
                                                                                                                                                                                                                                       1)
                                                                                                                                                                                                                                    1)
                                                                                                                                                                                                                                 1)
                                                                                                                                                                                                                              1)
                                                                                                                                                                                                                           1)
                                                                                                                                                                                                                        1)
                                                                                                                                                                                                                     1)
                                                                                                                                                                                                                  1)
                                                                                                                                                                                                               1)
                                                                                                                                                                                                            1)
                                                                                                                                                                                                         1)
                                                                                                                                                                                                      1)
                                                                                                                                                                                                   1)
                                                                                                                                                                                                1)
                                                                                                                                                                                             1)
                                                                                                                                                                                          1)
                                                                                                                                                                                       1)
                                                                                                                                                                                    1)
                                                                                                                                                                                 1)
                                                                                                                                                                              1)
                                                                                                                                                                           1)
                                                                                                                                                                        1)
                                                                                                                                                                     1)
                                                                                                                                                                  1)
                                                                                                                                                               1)
                                                                                                                                                            1)
                                                                                                                                                         1)
                                                                                                                                                      1)
                                                                                                                                                   1)
                                                                                                                                                1)
                                                                                                                                             1)
                                                                                                                                          1)
                                                                                                                                       1)
                                                                                                                                    1)
                                                                                                                                 1)
                                                                                                                              1)
                                                                                                                           1)
                                                                                                                        1)
                                                                                                                     1)
                                                                                                                  1)
                                                                                                               1)
                                                                                                            1)
                                                                                                         1)
                                                                                                      1)
                                                                                                   1)
                                                                                                1)
                                                                                             1)
                                                                                          1)
                                                                                       1)
                                                                                    1)
                                                                                 1)
                                                                              1)
                                                                           1)
                                                                        1)
                                                                     1)
                                                                  1)
                                                               1)
                                                            1)
                                                         1)
                                                      1)
                                                   1)
                                                1)
                                             1)
                                          1)
                                       1)
                                    1)
                                 1)
                              1)
                           1)
                        1)
                     1)
                  1)
               1)
            1)
         1)
      1
    Run with '-fclash-spec-limit=N' to increase the specialisation limit to N.

    The source location of the error is not exact, only indicative, as it is acquired 
    after optimizations. The actual location of the error can be in a function that is 
    inlined. To prevent inlining of those functions, annotate them with a NOINLINE pragma.
   |
17 | topEntity addr wr = memoryMap addr wr $ do
   | ^^^^^^^^^

Note, however, that I can probably make do with the unsafeCoerce-using variant, so I'll do further testing after the holidays and if this works I will be good to go!