clash-lang / clash-prelude

CLaSH prelude library containing datatypes and functions for circuit design
http://www.clash-lang.org/
Other
31 stars 27 forks source link

Use the `reflection` package for implicit clocks and resets #135

Closed christiaanb closed 6 years ago

christiaanb commented 7 years ago

No longer do we have to be amazed by ImplicitParams dynamic scoping behaviour. The reflection-based API suffers from the same scoping annoyances as the ImplicitParams one [1]. Additionally, we can now have multiple hidden clocks, e.g.:

f :: (HiddenClock domA, HiddenClock domB) 
  => Signal domA Bool 
  -> Signal domB Int 
  -> Signal domB Int

which is something that didn't work when we used implicit parameters.

However, you do lose the convenience of ImplicitParams binding construct.

[1] The scoping issue:

ImplicitParams

With the ImplicitParams API, this works

f :: Signal dom a -> Clock dom gated -> Signal dom b
f x = withClockReset ... $
    let rr = register undefined
    in ... g ...

but the following gives an "Unbound implicit param" error:

f :: Signal dom a -> Clock dom gated -> Signal dom b
f x = withClockReset ... g
  where rr = register undefined
        g = ...

Reflection

With the reflection API, this works

f :: Signal dom a -> Clock dom gated -> Signal dom b
f x = exposeClockReset $
    let rr = register undefined
    in ... g ...

but the following gives an "No instance for Given (SomeClock domain)" error:

f :: Signal dom a ->  Clock dom gated -> Signal dom b
f x = exposeClockReset g
  where rr = register undefined
        g = ...