Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Troubleshooting

A list of often encountered errors and their solutions:

  • Type error: Couldn't match expected type Signal dom (a,b) with actual type (Signal dom a, Signal dom b):

    Signals of product types and product types of signals are isomorphic due to synchronisity principle, but are not (structurally) equal. Tuples are a product type. Use the bundle function to convert from a product type to the signal type. So if your code which gives the error looks like:

    ... = f a b (c,d)
    

    add the bundle function like so:

    ... = f a b (bundle (c,d))
    

    Product types supported by bundle are:

    • All tuples up to and including 62-tuples (GHC limit)
    • The Vector type
  • Type error: Couldn't match expected type (Signal dom a, Signal dom b) with actual type Signal dom (a,b):

    Product types of signals and signals of product types are isomorphic due to synchronicity principle, but are not (structurally) equal. Tuples are a product type. Use the unbundle function to convert from a signal type to the product type. So if your code which gives the error looks like:

    (c,d) = f a b
    

    add the unbundle function like so:

    (c,d) = unbundle (f a b)
    

    Product types supported by unbundle are:

    • All tuples up to and including 62-tuples (GHC limit)
    • The Vector type
  • Clash.Netlist(..): Not in normal form: <REASON>: <EXPR>:

    A function could not be transformed into the expected normal form. This usually means one of the following:

    • The topEntity has higher-order arguments, or a higher-order result.
    • You are using types which cannot be represented in hardware.

    The solution for all the above listed reasons is quite simple: remove them. That is, make sure that the topEntity is completely monomorphic and first-order. Also remove any variables and constants/literals that have a non-representable type; see Limitations of Clash to find out which types are not representable.

  • Clash.Normalize(..): Clash can only normalize monomorphic functions, but this is polymorphic:

    If this happens for a topEntity or something with a Synthesize annotation, add a monomorphic type signature. Non topEntites should be type-specialized by clash automatically, if not please report this as a bug. But adding a monomorphic type signature should still help (when possible).

  • Clash.Normalize(..): Expr belonging to bndr: <FUNCTION> remains recursive after normalization:

    • If you actually wrote a recursive function, rewrite it to a non-recursive one using e.g. one of the higher-order functions in Clash.Sized.Vector

    • You defined a recursively defined value, but left it polymorphic:

    topEntity x y = acc
      where
        acc = register 3 (acc + x * y)
    

    The above function, works for any number-like type. This means that acc is a recursively defined polymorphic value. Adding a monomorphic type annotation makes the error go away:

    topEntity
      :: SystemClockResetEnable
      => Signal System (Signed 8)
      -> Signal System (Signed 8)
      -> Signal System (Signed 8)
    topEntity x y = acc
      where
        acc = register 3 (acc + x * y)
    
  • Clash.Normalize.Transformations(..): InlineNonRep: <FUNCTION> already inlined 100 times in:<FUNCTION>, <TYPE>:

    You left the topEntity function polymorphic or higher-order: use :i topEntity to check if the type is indeed polymorphic or higher-order. If it is, add a monomorphic type signature, and/or supply higher-order arguments.

  • <*** Exception: <<loop>> or "blinking cursor"

    You are using value-recursion, but one of the Vector functions that you are using is too strict in one of the recursive arguments. For example:

    -- Bubble sort for 1 iteration
    sortV xs = map fst sorted :< (snd (last sorted))
     where
       lefts  = head xs :> map snd (init sorted)
       rights = tail xs
       sorted = zipWith compareSwapL lefts rights
    
    -- Compare and swap
    compareSwapL a b = if a < b then (a,b) else (b,a)
    

    Will not terminate because zipWith is too strict in its second argument.

    In this case, adding lazyV on zipWiths second argument:

    sortVL xs = map fst sorted :< (snd (last sorted))
     where
       lefts  = head xs :> map snd (init sorted)
       rights = tail xs
       sorted = zipWith compareSwapL (lazyV lefts) rights
    

    Results in a successful computation:

    clashi> sortVL (4 :> 1 :> 2 :> 3 :> Nil)
    1 :> 2 :> 3 :> 4 :> Nil