clash-compiler icon indicating copy to clipboard operation
clash-compiler copied to clipboard

Constants do not get propagated to blackboxes requiring them in some situations

Open martijnbastiaan opened this issue 5 years ago • 0 comments

Consider:

module Test where

import Clash.Explicit.Prelude

topEntity
  :: Clock System
  -> Reset System
  -> Enable System
  -> Vec 3 (Signal System Int)
topEntity clk rst gen =
  map (register clk rst gen) (iterateI succ 0) <*> pure 3

register requires its reset value to be a constant. Clash doesn't seem to propagate it however:

Test.hs:10:1: error:
    
    Clash.Netlist.BlackBox(183): Couldn't instantiate blackbox for Clash.Signal.Internal.register#. Verification procedure reported:
    
    Argument 5 should be literal, as blackbox used ~CONST[5], but was:
    
    Identifier "~ARGN[1][0]" Nothing
    
    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.
   |
10 | topEntity clk rst gen =
   | ^^^^^^^^^

The core of the problem is that Clash ends up with the following core:

  result[8] :: Clash.Sized.Vector.Vec[8214565720323789611]
                 3
                 (Clash.Signal.Internal.Signal[8214565720323789571]
                    "System"
                    GHC.Types.Int[3674937295934324766])
  = Clash.Sized.Vector.zipWith
      @GHC.Types.Int[3674937295934324766]
      @(Clash.Signal.Internal.Signal[8214565720323789571]
          "System"
          GHC.Types.Int[3674937295934324766])
      @(Clash.Signal.Internal.Signal[8214565720323789571]
          "System"
          GHC.Types.Int[3674937295934324766])
      @3
      (λ(initial[6989586621679073303] :: GHC.Types.Int[3674937295934324766]) ->
      λ(i[6989586621679073304] :: Clash.Signal.Internal.Signal[8214565720323789571]
                                    "System"
                                    GHC.Types.Int[3674937295934324766]) ->
      Clash.Signal.Internal.register# @"System"
        @GHC.Types.Int[3674937295934324766]
        (Clash.Transformations.removedArg
           @(Clash.Signal.Internal.KnownDomain[8214565720323789548]
               "System"))
        (Clash.Transformations.removedArg
           @(Clash.XException.NFDataX[8214565720323789616]
               GHC.Types.Int[3674937295934324766]))
        clk[6989586621679069551][LocalId]
        rst[6989586621679069552][LocalId]
        gen[6989586621679069553][LocalId]
        initial[6989586621679073303][LocalId]
        initial[6989586621679073303][LocalId]
        i[6989586621679073304][LocalId])
      xs[8286623314361782424][LocalId]
      (Clash.Sized.Vector.replicate @3
         @(Clash.Signal.Internal.Signal[8214565720323789571]
             "System"
             GHC.Types.Int[3674937295934324766])
         (Clash.Promoted.Nat.SNat[8214565720323789502] @3
            3)
         (GHC.Types.I# 3))

This is representable, so reduceNonRepPrim won't fire. Ideally we'd somehow track / annotate what vars need to be a constant. Preferably across global binders, which could potentially eliminate a lot of work in constantSpec.

martijnbastiaan avatar Feb 24 '20 12:02 martijnbastiaan