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

asyncRam' :: Enum addr => SClock wclk -> SClock rclk -> SNat n -> Signal' wclk (Maybe (addr, a)) -> Signal' rclk (addr -> a) #92

Open strake opened 7 years ago

strake commented 7 years ago

and likewise asyncRam.

The path from read address to output is combinational, which we can so encode in the type.

My use case is a register file where we have a Signal (Either RegNum Word), either a register number or an immediate value, and we want a Signal Word, either the value in that register or the immediate value. It is much more convenient and less heinous with the proposed type of asyncRam:

liftA2 (flip either id) (asyncRam _ _) :: Signal (Either RegNum Word) -> Signal Word

versus

(\ rsi ->
 let rs = either id (pure undefined) <$> rsi
 in liftA2 (\ x -> either (pure x) id) (asyncRam _ _ rs) rsi) :: Signal (Either RegNum Word) -> Signal Word
christiaanb commented 7 years ago

I assume another varient of asyncRam will also work for you. I'd like to keep the current signature for people who are new to Clash/Haskell.

comonoidial commented 7 years ago

What about adding a special operation on signal functions, so that current simple asyncRam can be converted into the more flexible proposed variant. It would be something alike to currying on signals that needs to be a primitive in the prelude:

curryS :: (Signal a -> Signal b) -> Signal (a ->b)

Then you could write the following (with an extra flip because of unfortunate argument ordering):

liftA2 (flip either id) (curryS $ flip (asyncRam _) _) :: Signal (Either RegNum Word) -> Signal Word
christiaanb commented 7 years ago

@comonoidial, i dont think is is possible to write that function.

curryS f = g :- gs
  where
     g  = ???
     gs = ???
comonoidial commented 7 years ago

Right this function can not exist, although the other way around is trivial. Even with other Signal representations it seems you can not enforce all the properties to allow for this function. Does this mean we should provide signal of function returning variants for all primitives where it is feasible?

strake commented 7 years ago

Does this mean we should provide signal of function returning variants for all primitives where it is feasible?

I would prefer that myself. Essentially this means it returns time-varying combinational logic, i believe.

strake commented 7 years ago

@christiaanb: Could we have another term, say asyncRamFn or somewhat, and define asyncRam ... = (<*>) (asyncRamFn ...)?

christiaanb commented 7 years ago

@strake: yes, that'll work. Will you write a patch?

strake commented 7 years ago

Yep, once i figure out how to do so ☺