Skip to content
This repository has been archived by the owner on Sep 7, 2018. It is now read-only.

moore' can't be synthesized? #53

Open
dented42 opened this issue Apr 26, 2016 · 4 comments
Open

moore' can't be synthesized? #53

dented42 opened this issue Apr 26, 2016 · 4 comments

Comments

@dented42
Copy link
Contributor

dented42 commented Apr 26, 2016

When I try to compile a design that uses a moore machine, I get the following error:

Loading dependencies took 17.130628s

<no location info>:
    CLaSH Error:
CLaSH.Normalize(180): Callgraph after normalisation contains following recursive cycles: [[CLaSH.Prelude.Moore.$wmoore'_s1138]]
make: *** [out/gen/vhdl/*.vhdl] Error 1

It seems to indicate that moore machines can't be synthesized? but I'm wondering if perhaps optimizations are hiding the fact that the problem is in my program. If that's the case then I suppose this is really a compiler bug because it's failing to leave an appropriate error message.

@christiaanb
Copy link
Member

I guess you mean that the moore' function cannot be synthesized? Also, you are using clash 0.6.17, correct?

Now, moore' should definitely be synthesizable. However, CLaSH cannot synthesize recursive functions. Now, assuming you didn't actually write a recursive function, there are several reasons you might be getting the above error:

  • The recursive where clause in moore', https://github.com/clash-lang/clash-prelude/blob/master/src/CLaSH/Prelude/Moore.hs#L167, is turned into a recursive function by GHC, and CLaSH fails to transform it back to a recursive where-clause. (Yes, GHC actually does that, and yes, CLaSH has a transformation to does the inverse of what GHC does).
  • You are using a function from a library that is defined recursively, and which got inlined, and now CLaSH thinks the function moore' is recursive.

To figure out what's going on, could you run clash using the -clash-debug DebugFinal flag, and give me the entire function definition after the lines: CLaSH.Prelude.Moore.$wmoore'_s1138 before normalization: and CLaSH.Prelude.Moore.$wmoore'_s1138 after normalization:.

@dented42
Copy link
Contributor Author

I think you mean this?

CLaSH.Normalize(147): Expr belonging to bndr: CLaSH.Prelude.Moore.$wmoore'_s1138 (:: CLaSH.Signal.Internal.Signal'
  (CLaSH.Signal.Internal.Clk io 2000)
  (GHC.Tuple.(,) GHC.Types.Bool GHC.Types.Bool)
-> CLaSH.Signal.Internal.Signal'
     (CLaSH.Signal.Internal.Clk io 2000)
     (GHC.Tuple.(,)
        GHC.Types.Bool (SerialDecoder.DecodeST 8 GHC.Types.Bool))) has a non-representable return type. Not normalising:
λ(w3 :: CLaSH.Signal.Internal.Signal'
          (CLaSH.Signal.Internal.Clk io 2000)
          (GHC.Tuple.(,) GHC.Types.Bool GHC.Types.Bool)) ->
CLaSH.Signal.Internal.register#
@(CLaSH.Signal.Internal.Clk io 2000)
@(GHC.Tuple.(,)
    GHC.Types.Bool (SerialDecoder.DecodeST 8 GHC.Types.Bool))
  (Control.Exception.Base.absentError
   @(CLaSH.Signal.Internal.SClock (CLaSH.Signal.Internal.Clk io 2000))
     "w_s1Jjd SClock clk")
  (GHC.Tuple.(,)
   @GHC.Types.Bool
   @(SerialDecoder.DecodeST 8 GHC.Types.Bool)
     GHC.Types.False
     (SerialDecoder.Halted
      @8
      @GHC.Types.Bool
        8))
  (case (CLaSH.Prelude.Moore.$wmoore'_s1138
           w3) of
     GHC.Tuple.(,)
       (ds2 :: GHC.Types.Bool)
       (x :: SerialDecoder.DecodeST 8 GHC.Types.Bool) ->
       case ds2 of
         GHC.Types.False ->
           GHC.Tuple.(,)
           @GHC.Types.Bool
           @(SerialDecoder.DecodeST 8 GHC.Types.Bool)
             GHC.Types.True
             x
         GHC.Types.True ->
           case w3 of
             GHC.Tuple.(,)
               (ds3 :: GHC.Types.Bool)
               (ds4 :: GHC.Types.Bool) ->
               case ds3 of
                 GHC.Types.False ->
                   GHC.Tuple.(,)
                   @GHC.Types.Bool
                   @(SerialDecoder.DecodeST 8 GHC.Types.Bool)
                     GHC.Types.False
                     (SerialDecoder.Halted
                      @8
                      @GHC.Types.Bool
                        8)
                 GHC.Types.True ->
                   case x of
                     SerialDecoder.Halted
                       ($dKnownNat :: GHC.TypeLits.KnownNat 8) ->
                       GHC.Tuple.(,)
                       @GHC.Types.Bool
                       @(SerialDecoder.DecodeST 8 GHC.Types.Bool)
                         GHC.Types.False
                         (SerialDecoder.ReadShift
                          @8
                          @GHC.Types.Bool
                            $dKnownNat
                            (GHC.Base.Nothing
                             @(CLaSH.Sized.Vector.Vec 8 GHC.Types.Bool)))
                     SerialDecoder.ReadShift
                       ($dKnownNat :: GHC.TypeLits.KnownNat 8)
                       (ov :: GHC.Base.Maybe (CLaSH.Sized.Vector.Vec 8 GHC.Types.Bool)) ->
                       GHC.Tuple.(,)
                       @GHC.Types.Bool
                       @(SerialDecoder.DecodeST 8 GHC.Types.Bool)
                         GHC.Types.False
                         (SerialDecoder.RcvBit
                          @8
                          @GHC.Types.Bool
                          @GHC.Integer.Type.Integer
                            $dKnownNat
                            GHC.Enum.$fEnumInteger1912624553
                            $dKnownNat
                            (CLaSH.Sized.Vector.replicate
                             @8
                             @GHC.Types.Bool
                               (CLaSH.Promoted.Nat.SNat
                                @8
                                  $dKnownNat
                                  (Data.Proxy.Proxy
                                   @GHC.TypeLits.Nat
                                   @8))
                               (GHC.Err.undefined
                                @GHC.Types.Bool))
                            ov)
                     SerialDecoder.RcvBit idx
                       ($dKnownNat :: GHC.TypeLits.KnownNat 8)
                       ($dEnum :: GHC.Enum.Enum idx)
                       (idx1 :: idx)
                       (v :: CLaSH.Sized.Vector.Vec 8 GHC.Types.Bool)
                       (ds5 :: GHC.Base.Maybe
                                 (CLaSH.Sized.Vector.Vec 8 GHC.Types.Bool)) ->
                       case case $dEnum of
                              GHC.Enum.D:Enum
                                (wild6 :: idx -> idx)
                                (wild5 :: idx -> idx)
                                (wild4 :: GHC.Types.Int -> idx)
                                (sel :: idx -> GHC.Types.Int)
                                (wild3 :: idx -> GHC.Types.[] idx)
                                (wild2 :: idx -> idx -> GHC.Types.[] idx)
                                (wild1 :: idx -> idx -> GHC.Types.[] idx)
                                (wild :: idx -> idx -> idx -> GHC.Types.[] idx) ->
                                sel
                                  idx1 of
                         GHC.Types.I#
                           (y :: GHC.Prim.Int#) ->
                           case y of
                             _ ->
                               GHC.Tuple.(,)
                               @GHC.Types.Bool
                               @(SerialDecoder.DecodeST 8 GHC.Types.Bool)
                                 GHC.Types.False
                                 (SerialDecoder.RcvBit
                                  @8
                                  @GHC.Types.Bool
                                  @idx
                                    $dKnownNat
                                    $dEnum
                                    (GHC.Enum.pred1912603236
                                     @idx
                                       $dEnum
                                       idx1)
                                    (CLaSH.Sized.Vector.replace_int
                                     @8
                                     @GHC.Types.Bool
                                       $dKnownNat
                                       v
                                       (case $dEnum of
                                          GHC.Enum.D:Enum
                                            (wild6 :: idx -> idx)
                                            (wild5 :: idx -> idx)
                                            (wild4 :: GHC.Types.Int -> idx)
                                            (sel :: idx -> GHC.Types.Int)
                                            (wild3 :: idx -> GHC.Types.[] idx)
                                            (wild2 :: idx -> idx -> GHC.Types.[] idx)
                                            (wild1 :: idx -> idx -> GHC.Types.[] idx)
                                            (wild :: idx -> idx -> idx -> GHC.Types.[] idx) ->
                                            sel
                                              idx1)
                                       ds4)
                                    ds5)
                             0 ->
                               GHC.Tuple.(,)
                               @GHC.Types.Bool
                               @(SerialDecoder.DecodeST 8 GHC.Types.Bool)
                                 GHC.Types.False
                                 (SerialDecoder.ReadShift
                                  @8
                                  @GHC.Types.Bool
                                    $dKnownNat
                                    (GHC.Base.Just
                                     @(CLaSH.Sized.Vector.Vec 8 GHC.Types.Bool)
                                       (CLaSH.Sized.Vector.replace_int
                                        @8
                                        @GHC.Types.Bool
                                          $dKnownNat
                                          v
                                          (GHC.Types.I#
                                             0)
                                          ds4))))

@dented42 dented42 changed the title mealy' can't be synthesized? moore' can't be synthesized? Apr 26, 2016
@dented42
Copy link
Contributor Author

And yes, I am using 0.6.17

@christiaanb
Copy link
Member

The "problem" is the DecodeST GADT, specifically, pattern matching on GADTs is not supported: http://hackage.haskell.org/package/clash-prelude-0.10.7/docs/CLaSH-Tutorial.html#g:19

So here's what's happening:

  • GADTs cannot be synthesized due to their existential members/fields/arguments
  • You have a function, mooreTransition, which is returning a GADT
  • CLaSH does not synthesize mooreTransition because it knows it will never be able to get rid of the GADT result.
  • Consequently, CLaSH does not synthesize moore', because a function used by moore' is non-synthesizable.
  • Because moore' does not undergo the normalisation process, the recursive where-clause turned to recursive function is not transformed back to a recursive where-clause.
  • CLaSH complains about the recursive nature of non-normalised moore'.

So yeah, instead of just reporting that moore' remains recursive, CLaSH should've told you that this is due to the DecodeST GADT

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants