clash-prelude-1.2.0: src/Clash/Signal/Delayed.hs
{-|
Copyright : (C) 2013-2016, University of Twente,
2017 , Google Inc.
2019 , Myrtle Software Ltd
License : BSD2 (see the file LICENSE)
Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>
-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
#if __GLASGOW_HASKELL__ < 806
{-# LANGUAGE TypeInType #-}
#endif
{-# LANGUAGE Safe #-}
{-# OPTIONS_GHC -fplugin GHC.TypeLits.Normalise #-}
module Clash.Signal.Delayed
( -- * Delay-annotated synchronous signals
DSignal
, delayed
, delayedI
, delayN
, delayI
, delayedFold
, feedback
-- * Signal \<-\> DSignal conversion
, fromSignal
, toSignal
-- * List \<-\> DSignal conversion (not synthesizable)
, dfromList
-- ** lazy versions
, dfromList_lazy
-- * Experimental
, unsafeFromSignal
, antiDelay
)
where
import GHC.TypeLits
(KnownNat, type (^), type (+), type (*))
import Clash.Signal.Delayed.Internal
(DSignal(..), dfromList, dfromList_lazy, fromSignal, toSignal,
unsafeFromSignal, antiDelay, feedback)
import qualified Clash.Explicit.Signal.Delayed as E
import Clash.Sized.Vector (Vec)
import Clash.Signal
(HiddenClock, HiddenClockResetEnable, HiddenEnable, hideClock,
hideClockResetEnable, hideEnable)
import Clash.Promoted.Nat (SNat (..))
import Clash.XException (NFDataX)
{- $setup
>>> :set -XDataKinds -XTypeOperators -XTypeApplications -XFlexibleContexts
>>> import Clash.Prelude
>>> let delay3 = delayed (-1 :> -1 :> -1 :> Nil)
>>> let delay2 = delayedI :: HiddenClockResetEnable dom => Int -> DSignal dom n Int -> DSignal dom (n + 2) Int
>>> let delayN2 = delayN d2
>>> let delayI2 = delayI :: HiddenClockResetEnable dom => Int -> DSignal dom n Int -> DSignal dom (n + 2) Int
>>> let countingSignals = Clash.Prelude.repeat (dfromList [0..]) :: Vec 4 (DSignal dom 0 Int)
-}
-- | Delay a 'DSignal' for @d@ periods.
--
-- @
-- delay3
-- :: HiddenClockResetEnable dom
-- => 'DSignal' dom n Int
-- -> 'DSignal' dom (n + 3) Int
-- delay3 = 'delayed' (-1 ':>' -1 ':>' -1 ':>' 'Nil')
-- @
--
-- >>> sampleN @System 7 (toSignal (delay3 (dfromList [0..])))
-- [-1,-1,-1,-1,1,2,3]
delayed
:: ( KnownNat d
, HiddenClockResetEnable dom
, NFDataX a
)
=> Vec d a
-> DSignal dom n a
-> DSignal dom (n + d) a
delayed = hideClockResetEnable E.delayed
-- | Delay a 'DSignal' for @d@ periods, where @d@ is derived from the context.
--
-- @
-- delay2
-- :: HiddenClockResetEnable dom
-- => Int
-- -> 'DSignal' dom n Int
-- -> 'DSignal' dom (n + 2) Int
-- delay2 = 'delayedI'
-- @
--
-- >>> sampleN @System 7 (toSignal (delay2 (-1) (dfromList [0..])))
-- [-1,-1,-1,1,2,3,4]
--
-- Or @d@ can be specified using type application:
--
-- >>> :t delayedI @3
-- delayedI @3
-- :: (...
-- ...
-- ...
-- ...) =>
-- a -> DSignal dom n a -> DSignal dom (n + 3) a
delayedI
:: ( KnownNat d
, NFDataX a
, HiddenClockResetEnable dom )
=> a
-- ^ Initial value
-> DSignal dom n a
-> DSignal dom (n + d) a
delayedI = hideClockResetEnable E.delayedI
-- | Delay a 'DSignal' for @d@ cycles, the value at time 0..d-1 is /a/.
--
-- @
-- delayN2
-- :: HiddenClockResetEnable dom
-- => Int
-- -> 'DSignal' dom n Int
-- -> 'DSignal' dom (n + 2) Int
-- delayN2 = 'delayN' d2
-- @
--
-- >>> printX $ sampleN @System 6 (toSignal (delayN2 (-1) (dfromList [1..])))
-- [-1,-1,1,2,3,4]
delayN
:: forall dom a d n
. ( HiddenClock dom
, HiddenEnable dom
, NFDataX a )
=> SNat d
-> a
-- ^ Initial value
-> DSignal dom n a
-> DSignal dom (n+d) a
delayN d dflt = hideClock (hideEnable (E.delayN d dflt))
-- | Delay a 'DSignal' for @d@ cycles, where @d@ is derived from the context.
-- The value at time 0..d-1 is a default value.
--
-- @
-- delayI2
-- :: HiddenClockResetEnable dom
-- => Int
-- -> 'DSignal' dom n Int
-- -> 'DSignal' dom (n + 2) Int
-- delayI2 = 'delayI'
-- @
--
-- >>> sampleN @System 6 (toSignal (delayI2 (-1) (dfromList [1..])))
-- [-1,-1,1,2,3,4]
--
-- You can also use type application to do the same:
-- >>> sampleN @System 6 (toSignal (delayI @2 (-1) (dfromList [1..])))
-- [-1,-1,1,2,3,4]
delayI
:: forall d n a dom
. ( HiddenClockResetEnable dom
, NFDataX a
, KnownNat d )
=> a
-- ^ Initial value
-> DSignal dom n a
-> DSignal dom (n+d) a
delayI dflt = delayN (SNat :: SNat d) dflt
-- | Tree fold over a 'Vec' of 'DSignal's with a combinatorial function,
-- and delaying @delay@ cycles after each application.
-- Values at times 0..(delay*k)-1 are set to a default.
--
-- @
-- countingSignals :: Vec 4 (DSignal dom 0 Int)
-- countingSignals = repeat (dfromList [0..])
-- @
--
-- >>> printX $ sampleN @System 6 (toSignal (delayedFold d1 (-1) (+) countingSignals))
-- [-1,-2,0,4,8,12]
--
-- >>> printX $ sampleN @System 8 (toSignal (delayedFold d2 (-1) (*) countingSignals))
-- [-1,-1,1,1,0,1,16,81]
delayedFold
:: forall dom n delay k a
. ( HiddenClock dom
, HiddenEnable dom
, NFDataX a
, KnownNat delay
, KnownNat k )
=> SNat delay
-- ^ Delay applied after each step
-> a
-- ^ Initial value
-> (a -> a -> a)
-- ^ Fold operation to apply
-> Vec (2^k) (DSignal dom n a)
-- ^ Vector input of size 2^k
-> DSignal dom (n + (delay * k)) a
-- ^ Output Signal delayed by (delay * k)
delayedFold d dflt f = hideClock (hideEnable (E.delayedFold d dflt f))