{-# LANGUAGE NoImplicitPrelude #-}
{-# OPTIONS_HADDOCK hide #-}
module Protocols.PacketStream.Routing (
packetArbiterC,
packetDispatcherC,
routeBy,
) where
import Clash.Prelude
import Protocols
import Protocols.Df qualified as Df
import Protocols.PacketStream.Base
import Data.Bifunctor qualified as B
import Data.Maybe
packetArbiterC ::
forall dataWidth sources meta dom.
(HiddenClockResetEnable dom) =>
(KnownNat sources) =>
(1 <= sources) =>
Df.CollectMode ->
Circuit
(Vec sources (PacketStream dom dataWidth meta))
(PacketStream dom dataWidth meta)
packetArbiterC mode =
Circuit (B.first unbundle . mealyB go (maxBound, True) . B.first bundle)
where
go (i, first) (fwds, bwd@(PacketStreamS2M ack)) = ((i', continue), (bwds, fwd))
where
bwds = replace i bwd (repeat (PacketStreamS2M False))
fwd = fwds !! i
continue = case (fwd, mode) of
(Nothing, Df.NoSkip) -> False
(Nothing, _) -> first
(Just transferIn, _) -> isJust (_last transferIn) && ack
i' = case (mode, continue) of
(_, False) -> i
(Df.NoSkip, _) -> satSucc SatWrap i
(Df.Skip, _) -> satSucc SatWrap i
(Df.Parallel, _) ->
fromMaybe maxBound
$ fold @(sources - 1) (<|>) (zipWith (<$) indicesI fwds)
packetDispatcherC ::
forall dataWidth sinks meta dom.
(HiddenClockResetEnable dom) =>
(KnownNat sinks) =>
Vec sinks (meta -> Bool) ->
Circuit
(PacketStream dom dataWidth meta)
(Vec sinks (PacketStream dom dataWidth meta))
packetDispatcherC predicates =
Circuit (B.second unbundle . unbundle . fmap go . bundle . B.second bundle)
where
idleOtp = repeat Nothing
go (Nothing, _) = (deepErrorX "undefined ack", idleOtp)
go (Just x, bwds) = case findIndex id (zipWith ($) predicates (pure $ _meta x)) of
Just i -> (bwds !! i, replace i (Just x) idleOtp)
Nothing -> (PacketStreamS2M True, idleOtp)
routeBy ::
(Eq a) =>
(meta -> a) ->
Vec sinks a ->
Vec sinks (meta -> Bool)
routeBy f = map $ \x -> (== x) . f