@@ -13,6 +13,8 @@ module Protocols.BiDf (
1313 loopback ,
1414 -- * Mapping
1515 dimap ,
16+ -- * Fan-in
17+ fanin
1618) where
1719
1820import Prelude ()
@@ -100,3 +102,40 @@ dimap f g = circuit $ \biDf -> do
100102 resp' <- Df. map g -< resp
101103 (biDf', resp) <- fromDfs -< req'
102104 idC -< biDf'
105+
106+ -- | Merge a number of 'BiDf's, preferring requests from the last channel.
107+ fanin
108+ :: forall n dom req resp .
109+ ( KnownNat n
110+ , 1 <= n
111+ , NFDataX req
112+ , NFDataX resp
113+ , HiddenClockResetEnable dom
114+ )
115+ => Circuit (Vec n (BiDf dom req resp )) (BiDf dom req resp )
116+ fanin = fromSignals $ \ (upFwds, (reqAck, respData)) ->
117+ let reqDatas :: Vec n (Signal dom (Df. Data req ))
118+ reqDatas = map fst upFwds
119+ respAcks :: Vec n (Signal dom Ack )
120+ respAcks = map snd upFwds
121+
122+ ((reqAcks, respAck), (respDatas, reqData)) =
123+ toSignals fanin' ((reqDatas, respData), (respAcks, reqAck))
124+ in (zip reqAcks respDatas, (reqData, respAck))
125+ where
126+ fanin'
127+ :: Circuit (Vec n (Df dom req ), Df dom resp )
128+ (Vec n (Df dom resp ), Df dom req )
129+ fanin' = circuit $ \ (reqs, resp) -> do
130+ [fwd0, fwd1]
131+ <- Df. fanout
132+ <| Df. roundrobinCollect @ n Df. Parallel
133+ <| Df. unbundleVec
134+ <| Df. map (zip indicesI)
135+ <| Df. bundleVec
136+ -< reqs
137+
138+ activeN <- Df. map fst -< fwd1
139+ resps <- Df. route <| Df. zip -< (activeN, resp)
140+ req <- Df. map snd -< fwd0
141+ idC -< (resps, req)
0 commit comments