{-# LANGUAGE CPP #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
#if __GLASGOW_HASKELL__ < 806
{-# LANGUAGE TypeInType #-}
#endif
{-# LANGUAGE Trustworthy #-}
{-# OPTIONS_GHC -fplugin GHC.TypeLits.Normalise #-}
{-# OPTIONS_HADDOCK show-extensions #-}
module Clash.Explicit.Signal.Delayed
( DSignal
, delayed
, delayedI
, delayN
, delayI
, delayedFold
, feedback
, fromSignal
, toSignal
, dfromList
, dfromList_lazy
, unsafeFromSignal
, antiDelay
)
where
import Data.Coerce (coerce)
import Data.Kind (Type)
import Data.Proxy (Proxy (..))
import Data.Singletons.Prelude (Apply, TyFun, type (@@))
import GHC.TypeLits (KnownNat, Nat, type (+), type (^), type (*))
import Prelude hiding (head, length, repeat)
import Clash.Sized.Vector
(Vec, dtfold, head, length, repeat, shiftInAt0, singleton)
import Clash.Signal.Delayed.Internal
(DSignal(..), dfromList, dfromList_lazy, fromSignal, toSignal,
unsafeFromSignal, antiDelay, feedback)
import Clash.Explicit.Signal
(KnownDomain, Clock, Domain, Reset, Signal, Enable, register, delay, bundle, unbundle)
import Clash.Promoted.Nat (SNat (..), snatToInteger)
import Clash.XException (NFDataX)
delayed
:: forall dom a n d
. ( KnownDomain dom
, KnownNat d
, NFDataX a )
=> Clock dom
-> Reset dom
-> Enable dom
-> Vec d a
-> DSignal dom n a
-> DSignal dom (n + d) a
delayed :: Clock dom
-> Reset dom
-> Enable dom
-> Vec d a
-> DSignal dom n a
-> DSignal dom (n + d) a
delayed clk :: Clock dom
clk rst :: Reset dom
rst en :: Enable dom
en m :: Vec d a
m ds :: DSignal dom n a
ds = Signal dom a -> DSignal dom (n + d) a
forall a b. Coercible a b => a -> b
coerce (Signal dom a -> Signal dom a
delaySignal (DSignal dom n a -> Signal dom a
forall a b. Coercible a b => a -> b
coerce DSignal dom n a
ds))
where
delaySignal :: Signal dom a -> Signal dom a
delaySignal :: Signal dom a -> Signal dom a
delaySignal s :: Signal dom a
s = case Vec d a -> Int
forall (n :: Nat) a. KnownNat n => Vec n a -> Int
length Vec d a
m of
0 -> Signal dom a
s
_ -> let (r' :: Vec d (Signal dom a)
r',o :: Vec 1 (Signal dom a)
o) = Vec d (Signal dom a)
-> Vec 1 (Signal dom a)
-> (Vec d (Signal dom a), Vec 1 (Signal dom a))
forall (n :: Nat) a (m :: Nat).
KnownNat n =>
Vec n a -> Vec m a -> (Vec n a, Vec m a)
shiftInAt0 (Signal dom (Vec d a) -> Unbundled dom (Vec d a)
forall a (dom :: Domain).
Bundle a =>
Signal dom a -> Unbundled dom a
unbundle Signal dom (Vec d a)
r) (Signal dom a -> Vec 1 (Signal dom a)
forall a. a -> Vec 1 a
singleton Signal dom a
s)
r :: Signal dom (Vec d a)
r = Clock dom
-> Reset dom
-> Enable dom
-> Vec d a
-> Signal dom (Vec d a)
-> Signal dom (Vec d a)
forall (dom :: Domain) a.
(KnownDomain dom, NFDataX a) =>
Clock dom
-> Reset dom -> Enable dom -> a -> Signal dom a -> Signal dom a
register Clock dom
clk Reset dom
rst Enable dom
en Vec d a
m (Unbundled dom (Vec d a) -> Signal dom (Vec d a)
forall a (dom :: Domain).
Bundle a =>
Unbundled dom a -> Signal dom a
bundle Vec d (Signal dom a)
Unbundled dom (Vec d a)
r')
in Vec (0 + 1) (Signal dom a) -> Signal dom a
forall (n :: Nat) a. Vec (n + 1) a -> a
head Vec 1 (Signal dom a)
Vec (0 + 1) (Signal dom a)
o
delayedI
:: ( KnownNat d
, KnownDomain dom
, NFDataX a )
=> Clock dom
-> Reset dom
-> Enable dom
-> a
-> DSignal dom n a
-> DSignal dom (n + d) a
delayedI :: Clock dom
-> Reset dom
-> Enable dom
-> a
-> DSignal dom n a
-> DSignal dom (n + d) a
delayedI clk :: Clock dom
clk rst :: Reset dom
rst en :: Enable dom
en dflt :: a
dflt = Clock dom
-> Reset dom
-> Enable dom
-> Vec d a
-> DSignal dom n a
-> DSignal dom (n + d) a
forall (dom :: Domain) a (n :: Nat) (d :: Nat).
(KnownDomain dom, KnownNat d, NFDataX a) =>
Clock dom
-> Reset dom
-> Enable dom
-> Vec d a
-> DSignal dom n a
-> DSignal dom (n + d) a
delayed Clock dom
clk Reset dom
rst Enable dom
en (a -> Vec d a
forall (n :: Nat) a. KnownNat n => a -> Vec n a
repeat a
dflt)
delayN
:: forall dom a d n
. ( KnownDomain dom
, NFDataX a )
=> SNat d
-> a
-> Enable dom
-> Clock dom
-> DSignal dom n a
-> DSignal dom (n+d) a
delayN :: SNat d
-> a
-> Enable dom
-> Clock dom
-> DSignal dom n a
-> DSignal dom (n + d) a
delayN d :: SNat d
d dflt :: a
dflt ena :: Enable dom
ena clk :: Clock dom
clk = Signal dom a -> DSignal dom (n + d) a
forall a b. Coercible a b => a -> b
coerce (Signal dom a -> DSignal dom (n + d) a)
-> (DSignal dom n a -> Signal dom a)
-> DSignal dom n a
-> DSignal dom (n + d) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Signal dom a -> Signal dom a
go (SNat d -> Integer
forall (n :: Nat). SNat n -> Integer
snatToInteger SNat d
d) (Signal dom a -> Signal dom a)
-> (DSignal dom n a -> Signal dom a)
-> DSignal dom n a
-> Signal dom a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Coercible (DSignal dom n a) (Signal dom a) =>
DSignal dom n a -> Signal dom a
forall a b. Coercible a b => a -> b
coerce @_ @(Signal dom a)
where
go :: Integer -> Signal dom a -> Signal dom a
go 0 = Signal dom a -> Signal dom a
forall a. a -> a
id
go i :: Integer
i = Clock dom -> Enable dom -> a -> Signal dom a -> Signal dom a
forall (dom :: Domain) a.
(KnownDomain dom, NFDataX a) =>
Clock dom -> Enable dom -> a -> Signal dom a -> Signal dom a
delay Clock dom
clk Enable dom
ena a
dflt (Signal dom a -> Signal dom a)
-> (Signal dom a -> Signal dom a) -> Signal dom a -> Signal dom a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Signal dom a -> Signal dom a
go (Integer
iInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-1)
delayI
:: forall d n a dom
. ( NFDataX a
, KnownDomain dom
, KnownNat d )
=> a
-> Enable dom
-> Clock dom
-> DSignal dom n a
-> DSignal dom (n+d) a
delayI :: a
-> Enable dom
-> Clock dom
-> DSignal dom n a
-> DSignal dom (n + d) a
delayI dflt :: a
dflt = SNat d
-> a
-> Enable dom
-> Clock dom
-> DSignal dom n a
-> DSignal dom (n + d) a
forall (dom :: Domain) a (d :: Nat) (n :: Nat).
(KnownDomain dom, NFDataX a) =>
SNat d
-> a
-> Enable dom
-> Clock dom
-> DSignal dom n a
-> DSignal dom (n + d) a
delayN (SNat d
forall (n :: Nat). KnownNat n => SNat n
SNat :: SNat d) a
dflt
data DelayedFold (dom :: Domain) (n :: Nat) (delay :: Nat) (a :: Type) (f :: TyFun Nat Type) :: Type
type instance Apply (DelayedFold dom n delay a) k = DSignal dom (n + (delay*k)) a
delayedFold
:: forall dom n delay k a
. ( NFDataX a
, KnownDomain dom
, KnownNat delay
, KnownNat k )
=> SNat delay
-> a
-> (a -> a -> a)
-> Enable dom
-> Clock dom
-> Vec (2^k) (DSignal dom n a)
-> DSignal dom (n + (delay * k)) a
delayedFold :: SNat delay
-> a
-> (a -> a -> a)
-> Enable dom
-> Clock dom
-> Vec (2 ^ k) (DSignal dom n a)
-> DSignal dom (n + (delay * k)) a
delayedFold _ dflt :: a
dflt op :: a -> a -> a
op ena :: Enable dom
ena clk :: Clock dom
clk = Proxy (DelayedFold dom n delay a)
-> (DSignal dom n a -> DelayedFold dom n delay a @@ 0)
-> (forall (l :: Nat).
SNat l
-> (DelayedFold dom n delay a @@ l)
-> (DelayedFold dom n delay a @@ l)
-> DelayedFold dom n delay a @@ (l + 1))
-> Vec (2 ^ k) (DSignal dom n a)
-> DelayedFold dom n delay a @@ k
forall (p :: TyFun Nat Type -> Type) (k :: Nat) a.
KnownNat k =>
Proxy p
-> (a -> p @@ 0)
-> (forall (l :: Nat).
SNat l -> (p @@ l) -> (p @@ l) -> p @@ (l + 1))
-> Vec (2 ^ k) a
-> p @@ k
dtfold (Proxy (DelayedFold dom n delay a)
forall k (t :: k). Proxy t
Proxy :: Proxy (DelayedFold dom n delay a)) DSignal dom n a -> DelayedFold dom n delay a @@ 0
forall a. a -> a
id forall (l :: Nat).
SNat l
-> (DelayedFold dom n delay a @@ l)
-> (DelayedFold dom n delay a @@ l)
-> DelayedFold dom n delay a @@ (l + 1)
go
where
go :: SNat l
-> DelayedFold dom n delay a @@ l
-> DelayedFold dom n delay a @@ l
-> DelayedFold dom n delay a @@ (l+1)
go :: SNat l
-> (DelayedFold dom n delay a @@ l)
-> (DelayedFold dom n delay a @@ l)
-> DelayedFold dom n delay a @@ (l + 1)
go SNat x :: DelayedFold dom n delay a @@ l
x y :: DelayedFold dom n delay a @@ l
y = a
-> Enable dom
-> Clock dom
-> DSignal dom (n + (delay * l)) a
-> DSignal dom ((n + (delay * l)) + delay) a
forall (d :: Nat) (n :: Nat) a (dom :: Domain).
(NFDataX a, KnownDomain dom, KnownNat d) =>
a
-> Enable dom
-> Clock dom
-> DSignal dom n a
-> DSignal dom (n + d) a
delayI a
dflt Enable dom
ena Clock dom
clk (a -> a -> a
op (a -> a -> a)
-> DSignal dom (n + (delay * l)) a
-> DSignal dom (n + (delay * l)) (a -> a)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> DelayedFold dom n delay a @@ l
DSignal dom (n + (delay * l)) a
x DSignal dom (n + (delay * l)) (a -> a)
-> DSignal dom (n + (delay * l)) a
-> DSignal dom (n + (delay * l)) a
forall (f :: Type -> Type) a b.
Applicative f =>
f (a -> b) -> f a -> f b
<*> DelayedFold dom n delay a @@ l
DSignal dom (n + (delay * l)) a
y)