Very slow simulation of recursive function in Clashi

I get a very slow simulation of values in Clashi for the following function.
I don’t see anything wrong with the generated verilog code though.

I guess that the simulator might be stuck in some recursive calls. Any ideas?

“Clashi, version 1.6.4 (using clash-lib, version 1.6.4)”

import Clash.Prelude

hotPotato :: HiddenClockResetEnable dom => Int -> Signal dom Int
hotPotato n = register 0 (mux (hotPotato n .==. pure (n-1)) 0 (hotPotato n + 1))

topEntity :: Clock System -> Reset System -> Enable System -> Signal System Int
topEntity = exposeClockResetEnable (hotPotato 8)

The following is the summary based on the replies from Christiaan in Slack.

Restructuring the code as below we no longer observe this problem.

hotPotato :: HiddenClockResetEnable dom => Int -> Signal dom Int
hotPotato n = 
  let s = register 0 (mux (s .==. pure (n-1)) 0 (s + 1)) in s

This is likely due to the memoization of results in the let-binding form. The results were not memoized in the original form making Haskell recalculate previous values in each clock cycle.

He also pointed out the limitations of Clash with a recursive function.
For example, Clash can’t generate a VHDL, or Verilog for the following code.

fibR :: Word -> Word
fibR 0 = 0
fibR 1 = 1
fibR n = fibR (n-1) + fibR (n-2)

When taken a structural view, it gives an infinitely deep structure making it impossible to layout a finite circuit.

Further details can be found here.

2 Likes