clash-lang / clash-protocols

a battery-included library for dataflow protocols
Other
19 stars 7 forks source link

Add variants of Df functions that handle function arguments wrapped in signals #107

Closed t-wallet closed 2 months ago

t-wallet commented 2 months ago

Various Df combinators are higher-order functions, such as map and filter. Sometimes it is handy if those combinators are able to handle functions that are wrapped inside of a Signal. For example:

arpReceiverC
  :: forall (dom :: Domain) (dataWidth :: Nat)
   . HiddenClockResetEnable dom
  => KnownNat dataWidth
  => 1 <= dataWidth
  => Signal dom IPv4Address
  -> Circuit (PacketStream dom dataWidth EthernetHeader) (Df dom ArpEntry, Df dom ArpLite)
arpReceiverC myIP = circuit $ \ethStream -> do
  arpDf <- depacketizeToDfC const -< ethStream
  arpDf' <- Df.filterS (isValidArp <$> myIP) -< arpDf
  (arpRequests, arpEntries) <- partitionS (isRequest <$> myIP) -< arpDf'
  ...

In this case we want to filter out all invalid ARP packets from a Df stream. But such a filter depends on our IPv4 address, which may change over time and is thus wrapped in a Signal. Then, the filter function itself is also wrapped in a Signal.

This PR adds such combinators, named with an S suffix. For map and filter we already have such functions. This PR adds:

bimapS
eitherS
firstS
secondS
mapLeftS
mapRightS
selectUntilS
partitionS
zipWithS
faninS