clash-lang / clash-compiler

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

Failing to normalize innocuous function? #102

Closed wyager closed 8 years ago

wyager commented 8 years ago

See https://github.com/wyager/HaSKI/blob/36055dbe9085d62b90912671faf2c707dace3dad/Hardware/StackMachine.hs#L161

When compiled with clash --verilog Adapter.hs, I get

CLaSH.Normalize.Transformations(173): InlineNonRep: Hardware.StackMachine.shiftOffL1912632169 already inlined 20 times in:Hardware.StackMachine.reads7

christiaanb commented 8 years ago

Char is considered non-representable. You might wonder why? Well, I don't know what a Char is in Haskell. Is it 7-bit ANSI, 8-bit ASCI, Latin-encoding, UTF-8, UTF-16?

SKIs is defined in terms of SKI, and SKI is defined in terms of Char.

wyager commented 8 years ago

Ah, thanks! I actually figured Chars might be weird due to the encoding ambiguity, but I forgot to check if that was causing any problems. The error did show up in a strange way, though...

christiaanb commented 8 years ago

Yeah, error messages are not the best in CLaSH... So the the reason you got the above error is that CLaSH is trying to get rid of non-representable types in a meaning-preserving way through inlining and specialisation. For example, the following code compiles:

f 'c' = 4
f _   = 5
{-# NOINLINE f #-}

g 3 = 'c'
g _ = 'a'
{-# NOINLINE g #-}

topEntity :: Unsigned 8 -> Unsigned 8
topEntity = f . g

The NOINLINE pragma's are there to stop GHC from doing the transformation for us, and let the CLaSH compiler do it.

Getting rid of non-representable types through inlining and specialisation doesn't work for all cases, so there's a hard limit to how many times a function may be inlined before we stop trying. That's the error you're seeing. I guess I should make the error more informative, for example by explaining why CLaSH is trying to inline the function.

comonoidial commented 8 years ago

In GHC a Char is an UTF-32 character which is effictively 21 bits, so it could be represented as an unsigned of that length. I'd rather have CLaSH being permissive even if the VHDL generated is not efficient or well behaved. And then have CLaSH produce some kind of synthesis log containing all potential issues, as using Char and having things like full dividers in the design.