{-# LANGUAGE RoleAnnotations #-}
{-# LANGUAGE TypeFamilyDependencies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -fconstraint-solver-iterations=20 #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
{-# OPTIONS_GHC -fplugin Protocols.Plugin #-}
module Protocols.Internal (
module Protocols.Internal,
module Protocols.Internal.Types,
module Protocols.Plugin,
module Protocols.Plugin.Units,
module Protocols.Plugin.TaggedBundle,
) where
import Control.DeepSeq (NFData)
import Data.Hashable (Hashable)
import Data.Maybe (fromMaybe)
import Data.Proxy
import Prelude hiding (const, map)
import Clash.Prelude qualified as C
import Protocols.Internal.Types
import Protocols.Plugin
import Protocols.Plugin.TaggedBundle
import Protocols.Plugin.Units
import Control.Arrow ((***))
import Data.Coerce (coerce)
import Data.Default (Default (def))
import Data.Functor.Identity (Identity (..), runIdentity)
import Data.Kind (Type)
import Data.Tuple (swap)
import GHC.Generics (Generic)
newtype Ack = Ack Bool
deriving stock (Generic, Show)
deriving anyclass (C.Bundle, C.ShowX)
deriving newtype (C.NFDataX, Eq, Ord, C.BitPack)
instance Default Ack where
def = Ack True
infixr 1 |>
(|>) :: Circuit a b -> Circuit b c -> Circuit a c
(Circuit fab) |> (Circuit fbc) = Circuit $ \(s2rAc, r2sAc) ->
let
~(r2sAb, s2rAb) = fab (s2rAc, r2sBc)
~(r2sBc, s2rBc) = fbc (s2rAb, r2sAc)
in
(r2sAb, s2rBc)
infixr 1 <|
(<|) :: Circuit b c -> Circuit a b -> Circuit a c
(<|) = flip (|>)
toSignals :: Circuit a b -> ((Fwd a, Bwd b) -> (Bwd a, Fwd b))
toSignals = coerce
fromSignals :: ((Fwd a, Bwd b) -> (Bwd a, Fwd b)) -> Circuit a b
fromSignals = coerce
idC :: forall a. Circuit a a
idC = Circuit swap
repeatC ::
forall n a b.
Circuit a b ->
Circuit (C.Vec n a) (C.Vec n b)
repeatC (Circuit f) =
Circuit (C.unzip . C.map f . uncurry C.zip)
applyC ::
forall a b.
(Fwd a -> Fwd b) ->
(Bwd b -> Bwd a) ->
Circuit a b
applyC fwdFn bwdFn = Circuit go
where
go :: (Fwd a, Bwd b) -> (Bwd a, Fwd b)
go (fwdA, bwdB) = (bwdFn bwdB, fwdFn fwdA)
prod2C ::
forall a c b d.
Circuit a b ->
Circuit c d ->
Circuit (a, c) (b, d)
prod2C ab cd = circuit $ \(a, c) -> do
b <- ab -< a
d <- cd -< c
idC -< (b, d)
prod3C ::
forall a c b d e f.
Circuit a b ->
Circuit c d ->
Circuit e f ->
Circuit (a, c, e) (b, d, f)
prod3C ab cd ef = circuit $ \(a, c, e) -> do
b <- ab -< a
d <- cd -< c
f <- ef -< e
idC -< (b, d, f)
prod4C ::
forall a c b d e f g h.
Circuit a b ->
Circuit c d ->
Circuit e f ->
Circuit g h ->
Circuit (a, c, e, g) (b, d, f, h)
prod4C ab cd ef gh = circuit $ \(a, c, e, g) -> do
b <- ab -< a
d <- cd -< c
f <- ef -< e
h <- gh -< g
idC -< (b, d, f, h)
type family KeepType (keep :: Bool) (optionalType :: Type) = t | t -> keep optionalType where
KeepType 'True optionalType = Identity optionalType
KeepType 'False optionalType = Proxy optionalType
#if !MIN_VERSION_clash_prelude(1, 8, 2)
deriving instance (C.ShowX t) => (C.ShowX (Proxy t))
deriving instance (C.NFDataX t) => (C.NFDataX (Proxy t))
#endif
class
( Eq (KeepType keep Bool)
, Show (KeepType keep Bool)
, C.ShowX (KeepType keep Bool)
, NFData (KeepType keep Bool)
, C.NFDataX (KeepType keep Bool)
, Hashable (KeepType keep Bool)
) =>
KeepTypeClass (keep :: Bool)
where
getKeep :: KeepType keep optionalType -> Bool
fromKeepType :: KeepType keep optionalType -> Maybe optionalType
toKeepType :: optionalType -> KeepType keep optionalType
mapKeepType ::
(optionalType -> optionalType) -> KeepType keep optionalType -> KeepType keep optionalType
instance KeepTypeClass 'True where
getKeep _ = True
fromKeepType i = Just (runIdentity i)
toKeepType v = Identity v
mapKeepType = fmap
instance KeepTypeClass 'False where
getKeep _ = False
fromKeepType _ = Nothing
toKeepType _ = Proxy
mapKeepType = fmap
fromKeepTypeDef ::
(KeepTypeClass keep) =>
optionalType ->
KeepType keep optionalType ->
optionalType
fromKeepTypeDef deflt val = fromMaybe deflt (fromKeepType val)
convKeepType ::
(KeepTypeClass a, KeepTypeClass b) => t -> KeepType a t -> KeepType b t
convKeepType b = toKeepType . fromKeepTypeDef b
keepTypeFalse :: KeepType 'False t
keepTypeFalse = Proxy
fromKeepTypeTrue :: KeepType 'True t -> t
fromKeepTypeTrue = runIdentity
data Reverse a
instance (Protocol a) => Protocol (Reverse a) where
type Fwd (Reverse a) = Bwd a
type Bwd (Reverse a) = Fwd a
reverseCircuit :: Circuit a b -> Circuit (Reverse b) (Reverse a)
reverseCircuit ckt = Circuit (swap . toSignals ckt . swap)
coerceCircuit ::
(Fwd a ~ Fwd a', Bwd a ~ Bwd a', Fwd b ~ Fwd b', Bwd b ~ Bwd b') =>
Circuit a b ->
Circuit a' b'
coerceCircuit (Circuit f) = Circuit f
mapCircuit ::
(Fwd a' -> Fwd a) ->
(Bwd a -> Bwd a') ->
(Fwd b -> Fwd b') ->
(Bwd b' -> Bwd b) ->
Circuit a b ->
Circuit a' b'
mapCircuit ia oa ob ib (Circuit f) = Circuit ((oa *** ob) . f . (ia *** ib))
tupCircuits :: Circuit a b -> Circuit c d -> Circuit (a, c) (b, d)
tupCircuits (Circuit f) (Circuit g) = Circuit (reorder . (f *** g) . reorder)
where
reorder ~(~(aKeepType 'False optionalType
, b), ~(c, d)) = ((a, c), (b, d))
circuitMonitor ::
(Protocol p, Fwd p ~ C.Signal dom fwd, Bwd p ~ C.Signal dom bwd) =>
Circuit p (p, CSignal dom (fwd, bwd))
circuitMonitor = Circuit (\ ~(fwd, (bwd, _)) -> (bwd, (fwd, C.bundle (fwd, bwd))))