clash-lang / clash-compiler

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

Heisenbug? Inlining makes synthesis fail with "Can't translate non-tycon (function) type' #2327

Open pbreuer opened 2 years ago

pbreuer commented 2 years ago

How can more inlining make a function appear where before there was none? Inlining should substitute the arguments of a function evoking partial evaluation to a result. If someone can explain what may be going on I would be very grateful.

Clash 1.6.4, ghc 9.0.2, 64-bit AMD.

KPU/RFC7693/Blake2b.hs:500:1: error: Clash.Netlist.BlackBox(680): Can't translate non-tycon type: Clash.Sized.Internal.Unsigned.Unsigned ... 64 -> Clash.Sized.Internal.Unsigned.Unsigned ... 64

I was synthesising verilog with -fclash-no-render-enums. On seeing that error I NOINLINEd every function in that file, intending to locate the problem, but it then synthesized.

The error is reported in the top level function, the only one exported from that file. I believe it used to synthesize with clash 1.6.3/ghc 8.8.4 .

The failed synthesis is of a hash function ... from 512 bits to 384 bits, so the 64b -> 64b complaint is for a subfunction. The hash is done in 12 rounds (24 half rounds), each of them stateful. It's a blake2b hash as described in https://tools.ietf.org/html/rfc7693 .

The state consists of a length 16 vector of 64b words so a transform on a vector element is likely the site of the error... but how can that go away with less inlining?

I would have guessed that I did something like create a vector of the rounds/half-round functions and then composed the elements of the vector of functions. But I have looked at the code and no. It avoids that kind of thing, with synthesis in mind.

Does anyone want me to try to chase this down further? Right now it looks (to me) like it will be a heisenbug - one that appears and disappears randomly. But if there is a possible explanation, that may help in locating it.

Regards

PTB

leonschoorl commented 2 years ago

Going on the error location, it seems clash encounters a primitive/blackbox which is somehow under-applied, because its "result type" is a function Unsigned 64 -> Unsigned 64. And it fails to compute a HDL type for the result of the primitive.

I'd guess there is a bug where some transformation is somehow dropping an argument in some special situation, causing this under-applied primitive. And this special situation may only occur when certain things are inlined. Thus causing the problem to dissappear when you force them to be not inlined.

it would be great if you have an simple way to reproduce this that you can share, then we could take a look. Selectively adding/removing NOINLINEs until the error (dis)appears should help locating which part your code is triggering the bug.

leonschoorl commented 2 years ago

You can also try passing arguments -fclash-debug DebugSilent to clash, that'll enable some extra internal checks during compilation that might also help tracing things down.