    {-|
    Copyright  :  (C) 2013-2016, University of Twente,
                      2017     , Google Inc.
                      2019     , Myrtle Software Ltd,
                      2021-2022, QBayLogic B.V.
    License    :  BSD2 (see the file LICENSE)
    Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>

    __This is the <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/exts/safe_haskell.html Safe> API only of "Clash.Explicit.Prelude"__

    This module defines the explicitly clocked counterparts of the functions
    defined in "Clash.Prelude".
    -}

    {-# LANGUAGE CPP #-}
    {-# LANGUAGE FlexibleContexts #-}
    {-# LANGUAGE NoGeneralizedNewtypeDeriving #-}
    {-# LANGUAGE NoImplicitPrelude #-}

    {-# LANGUAGE Safe #-}

    {-# OPTIONS_HADDOCK show-extensions, not-home #-}

    module Clash.Explicit.Prelude.Safe
      ( -- * Creating synchronous sequential circuits
        mealy
      , mealyB
      , moore
      , mooreB
      , registerB
        -- * Synchronizer circuits for safe clock domain crossing
      , dualFlipFlopSynchronizer
      , asyncFIFOSynchronizer
        -- * ROMs
      , asyncRom
      , asyncRomPow2
      , rom
      , romPow2
        -- ** ROMs defined by a 'MemBlob'
      , asyncRomBlob
      , asyncRomBlobPow2
      , romBlob
      , romBlobPow2
        -- * RAM primitives with a combinational read port
      , asyncRam
      , asyncRamPow2
        -- * Block RAM primitives
      , blockRam
      , blockRamPow2
        -- ** Block RAM primitives initialized with a 'MemBlob'
      , blockRamBlob
      , blockRamBlobPow2
        -- *** Creating and inspecting 'MemBlob'
      , MemBlob
      , createMemBlob
      , memBlobTH
      , unpackMemBlob
        -- ** Block RAM read/write conflict resolution
      , readNew
        -- ** True dual-port block RAM
      , trueDualPortBlockRam
      , RamOp(..)
        -- * Utility functions
      , isRising
      , isFalling
      , riseEvery
      , oscillate
        -- * Exported modules
        -- ** Synchronous signals
      , module Clash.Explicit.Signal
      , module Clash.Explicit.Signal.Delayed
        -- ** Datatypes
        -- *** Bit vectors
      , module Clash.Sized.BitVector
        -- *** Arbitrary-width numbers
      , module Clash.Sized.Signed
      , module Clash.Sized.Unsigned
      , module Clash.Sized.Index
        -- *** Fixed point numbers
      , module Clash.Sized.Fixed
        -- *** Fixed size vectors
      , module Clash.Sized.Vector
        -- *** Perfect depth trees
      , module Clash.Sized.RTree
        -- ** Annotations
      , module Clash.Annotations.TopEntity
        -- ** Generics type-classes
      , Generic
      , Generic1
        -- ** Type-level natural numbers
      , module GHC.TypeLits
      , module GHC.TypeLits.Extra
      , module Clash.Promoted.Nat
      , module Clash.Promoted.Nat.Literals
      , module Clash.Promoted.Nat.TH
        -- ** Type-level strings
      , module Clash.Promoted.Symbol
        -- ** Type classes
        -- *** Clash
      , module Clash.Class.BitPack
      , module Clash.Class.Num
      , module Clash.Class.Resize
        -- *** Other
      , module Control.Applicative
      , module Data.Bits
          -- ** Exceptions
      , module Clash.XException
        -- ** Named types
      , module Clash.NamedTypes
        -- ** Haskell Prelude
        -- $hiding
      , module Clash.HaskellPrelude
      )
    where

    import Control.Applicative
    import Data.Bits
    import GHC.Generics (Generic, Generic1)
    import GHC.TypeLits
    #if MIN_VERSION_base(4,18,0)
      hiding (SNat, SSymbol, fromSNat)
    #endif
    import GHC.TypeLits.Extra
    import Clash.HaskellPrelude
    import qualified Prelude

    import Clash.Annotations.TopEntity
    import Clash.Class.BitPack
    import Clash.Class.Num
    import Clash.Class.Resize
    import Clash.NamedTypes

    import Clash.Explicit.BlockRam
    import Clash.Explicit.BlockRam.Blob
    import Clash.Explicit.Mealy
    import Clash.Explicit.Moore
    import Clash.Explicit.RAM
    import Clash.Explicit.ROM
    import Clash.Explicit.ROM.Blob
    import Clash.Explicit.Signal
    import Clash.Explicit.Signal.Delayed
    import Clash.Explicit.Synchronizer
      (dualFlipFlopSynchronizer, asyncFIFOSynchronizer)
    import Clash.Prelude.ROM.Blob (asyncRomBlob, asyncRomBlobPow2)
    import Clash.Prelude.ROM             (asyncRom, asyncRomPow2)
    import Clash.Promoted.Nat
    import Clash.Promoted.Nat.TH
    import Clash.Promoted.Nat.Literals
    import Clash.Promoted.Symbol
    import Clash.Sized.BitVector
    import Clash.Sized.Fixed
    import Clash.Sized.Index
    import Clash.Sized.RTree
    import Clash.Sized.Signed
    import Clash.Sized.Unsigned
    import Clash.Sized.Vector hiding (fromList, unsafeFromList)
    import Clash.XException

    {- $setup
    >>> :set -XDataKinds
    >>> :m -Prelude
    >>> import Clash.Explicit.Prelude.Safe
    >>> let rP clk rst en = registerB clk rst en (8::Int,8::Int)
    -}

    {- $hiding
    "Clash.Explicit.Prelude.Safe" re-exports most of the Haskell "Prelude" with the
    exception of those functions that the Clash API defines to work on 'Vec' from
    "Clash.Sized.Vector" instead of on lists as the Haskell Prelude does. In
    addition, for the 'Clash.Class.Parity.odd' and 'Clash.Class.Parity.even'
    functions a type class called 'Clash.Class.Parity.Parity' is available at
    "Clash.Class.Parity".
    -}

    -- | Create a 'register' function for product-type like signals (e.g.
    -- @('Signal' a, 'Signal' b)@)
    --
    -- @
    -- rP :: Clock dom -> Reset dom -> Enable dom
    --    -> ('Signal' dom Int, 'Signal' dom Int)
    --    -> ('Signal' dom Int, 'Signal' dom Int)
    -- rP clk rst en = 'registerB' clk rst en (8,8)
    -- @
    --
    -- >>> simulateB (rP systemClockGen systemResetGen enableGen) [(1,1),(1,1),(2,2),(3,3)] :: [(Int,Int)]
    -- [(8,8),(8,8),(1,1),(2,2),(3,3)...
    -- ...
    registerB
      :: ( KnownDomain dom
         , NFDataX a
         , Bundle a )
      => Clock dom
      -> Reset dom
      -> Enable dom
      -> a
      -> Unbundled dom a
      -> Unbundled dom a
    registerB :: forall (dom :: Domain) a.
    (KnownDomain dom, NFDataX a, Bundle a) =>
    Clock dom
    -> Reset dom
    -> Enable dom
    -> a
    -> Unbundled dom a
    -> Unbundled dom a
    registerB Clock dom
    clk Reset dom
    rst Enable dom
    en a
    i =
      Signal dom a -> Unbundled dom a
    forall a (dom :: Domain).
    Bundle a =>
    Signal dom a -> Unbundled dom a
    forall (dom :: Domain). Signal dom a -> Unbundled dom a
    unbundle (Signal dom a -> Unbundled dom a)
    -> (Unbundled dom a -> Signal dom a)
    -> Unbundled dom a
    -> Unbundled dom a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    Prelude.. Clock dom
    -> Reset dom -> Enable dom -> a -> Signal dom a -> Signal dom 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 a
    i (Signal dom a -> Signal dom a)
    -> (Unbundled dom a -> Signal dom a)
    -> Unbundled dom a
    -> Signal dom a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    Prelude.. Unbundled dom a -> Signal dom a
    forall a (dom :: Domain).
    Bundle a =>
    Unbundled dom a -> Signal dom a
    forall (dom :: Domain). Unbundled dom a -> Signal dom a
    bundle
    {-# INLINE registerB #-}

    -- | Give a pulse when the 'Signal' goes from 'minBound' to 'maxBound'
    isRising
      :: ( KnownDomain dom
         , NFDataX a
         , Bounded a
         , Eq a )
      => Clock dom
      -> Reset dom
      -> Enable dom
      -> a -- ^ Starting value
      -> Signal dom a
      -> Signal dom Bool
    isRising :: forall (dom :: Domain) a.
    (KnownDomain dom, NFDataX a, Bounded a, Eq a) =>
    Clock dom
    -> Reset dom -> Enable dom -> a -> Signal dom a -> Signal dom Bool
    isRising Clock dom
    clk Reset dom
    rst Enable dom
    en a
    is Signal dom a
    s = (a -> a -> Bool) -> Signal dom a -> Signal dom a -> Signal dom Bool
    forall a b c.
    (a -> b -> c) -> Signal dom a -> Signal dom b -> Signal dom c
    forall (f :: Type -> Type) a b c.
    Applicative f =>
    (a -> b -> c) -> f a -> f b -> f c
    liftA2 a -> a -> Bool
    forall {a} {a}.
    (Eq a, Eq a, Bounded a, Bounded a) =>
    a -> a -> Bool
    edgeDetect Signal dom a
    prev Signal dom a
    s
      where
        prev :: Signal dom a
    prev = Clock dom
    -> Reset dom -> Enable dom -> a -> Signal dom a -> Signal dom 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 a
    is Signal dom a
    s
        edgeDetect :: a -> a -> Bool
    edgeDetect a
    old a
    new = a
    old a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    == a
    forall a. Bounded a => a
    minBound Bool -> Bool -> Bool
    && a
    new a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    == a
    forall a. Bounded a => a
    maxBound
    {-# INLINABLE isRising #-}

    -- | Give a pulse when the 'Signal' goes from 'maxBound' to 'minBound'
    isFalling
      :: ( KnownDomain dom
         , NFDataX a
         , Bounded a
         , Eq a )
      => Clock dom
      -> Reset dom
      -> Enable dom
      -> a -- ^ Starting value
      -> Signal dom a
      -> Signal dom Bool
    isFalling :: forall (dom :: Domain) a.
    (KnownDomain dom, NFDataX a, Bounded a, Eq a) =>
    Clock dom
    -> Reset dom -> Enable dom -> a -> Signal dom a -> Signal dom Bool
    isFalling Clock dom
    clk Reset dom
    rst Enable dom
    en a
    is Signal dom a
    s = (a -> a -> Bool) -> Signal dom a -> Signal dom a -> Signal dom Bool
    forall a b c.
    (a -> b -> c) -> Signal dom a -> Signal dom b -> Signal dom c
    forall (f :: Type -> Type) a b c.
    Applicative f =>
    (a -> b -> c) -> f a -> f b -> f c
    liftA2 a -> a -> Bool
    forall {a} {a}.
    (Eq a, Eq a, Bounded a, Bounded a) =>
    a -> a -> Bool
    edgeDetect Signal dom a
    prev Signal dom a
    s
      where
        prev :: Signal dom a
    prev = Clock dom
    -> Reset dom -> Enable dom -> a -> Signal dom a -> Signal dom 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 a
    is Signal dom a
    s
        edgeDetect :: a -> a -> Bool
    edgeDetect a
    old a
    new = a
    old a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    == a
    forall a. Bounded a => a
    maxBound Bool -> Bool -> Bool
    && a
    new a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    == a
    forall a. Bounded a => a
    minBound
    {-# INLINABLE isFalling #-}

    -- | Give a pulse every @n@ clock cycles. This is a useful helper function when
    -- combined with functions like @'Clash.Explicit.Signal.regEn'@ or
    -- @'Clash.Explicit.Signal.mux'@, in order to delay a register by a known amount.
    riseEvery
      :: forall dom  n
       . KnownDomain dom
      => Clock dom
      -> Reset dom
      -> Enable dom
      -> SNat n
      -> Signal dom Bool
    riseEvery :: forall (dom :: Domain) (n :: Nat).
    KnownDomain dom =>
    Clock dom -> Reset dom -> Enable dom -> SNat n -> Signal dom Bool
    riseEvery Clock dom
    clk Reset dom
    rst Enable dom
    en SNat n
    SNat = Clock dom
    -> Reset dom
    -> Enable dom
    -> (Index n -> () -> Index n)
    -> (Index n -> Bool)
    -> Index n
    -> Signal dom ()
    -> Signal dom Bool
    forall (dom :: Domain) s i o.
    (KnownDomain dom, NFDataX s) =>
    Clock dom
    -> Reset dom
    -> Enable dom
    -> (s -> i -> s)
    -> (s -> o)
    -> s
    -> Signal dom i
    -> Signal dom o
    moore Clock dom
    clk Reset dom
    rst Enable dom
    en Index n -> () -> Index n
    transfer Index n -> Bool
    output Index n
    0 (() -> Signal dom ()
    forall a. a -> Signal dom a
    forall (f :: Type -> Type) a. Applicative f => a -> f a
    pure ())
      where
        output :: Index n -> Bool
        output :: Index n -> Bool
    output = (Index n -> Index n -> Bool
    forall a. Eq a => a -> a -> Bool
    == Index n
    forall a. Bounded a => a
    maxBound)

        transfer :: Index n -> () -> Index n
        transfer :: Index n -> () -> Index n
    transfer Index n
    s ()
    _ = if (Index n
    s Index n -> Index n -> Bool
    forall a. Eq a => a -> a -> Bool
    == Index n
    forall a. Bounded a => a
    maxBound) then Index n
    0 else Index n
    sIndex n -> Index n -> Index n
    forall a. Num a => a -> a -> a
    +Index n
    1
    {-# INLINEABLE riseEvery #-}

    -- | Oscillate a @'Bool'@ for a given number of cycles, given the starting state.
    oscillate
      :: forall dom  n
       . KnownDomain dom
      => Clock dom
      -> Reset dom
      -> Enable dom
      -> Bool
      -> SNat n
      -> Signal dom Bool
    oscillate :: forall (dom :: Domain) (n :: Nat).
    KnownDomain dom =>
    Clock dom
    -> Reset dom -> Enable dom -> Bool -> SNat n -> Signal dom Bool
    oscillate Clock dom
    clk Reset dom
    rst Enable dom
    en Bool
    begin SNat n
    SNat =
      Clock dom
    -> Reset dom
    -> Enable dom
    -> ((Index n, Bool) -> () -> (Index n, Bool))
    -> ((Index n, Bool) -> Bool)
    -> (Index n, Bool)
    -> Signal dom ()
    -> Signal dom Bool
    forall (dom :: Domain) s i o.
    (KnownDomain dom, NFDataX s) =>
    Clock dom
    -> Reset dom
    -> Enable dom
    -> (s -> i -> s)
    -> (s -> o)
    -> s
    -> Signal dom i
    -> Signal dom o
    moore Clock dom
    clk Reset dom
    rst Enable dom
    en (Index n, Bool) -> () -> (Index n, Bool)
    transfer (Index n, Bool) -> Bool
    forall a b. (a, b) -> b
    snd (Index n
    0, Bool
    begin) (() -> Signal dom ()
    forall a. a -> Signal dom a
    forall (f :: Type -> Type) a. Applicative f => a -> f a
    pure ())
     where
      transfer :: (Index n, Bool) -> () -> (Index n, Bool)
      transfer :: (Index n, Bool) -> () -> (Index n, Bool)
    transfer (Index n
    s, Bool
    i) ()
    _ =
        if Index n
    s Index n -> Index n -> Bool
    forall a. Eq a => a -> a -> Bool
    == Index n
    forall a. Bounded a => a
    maxBound
          then (Index n
    0,   Bool -> Bool
    not Bool
    i) -- reset state and oscillate output
          else (Index n
    sIndex n -> Index n -> Index n
    forall a. Num a => a -> a -> a
    +Index n
    1, Bool
    i)     -- hold current output
    {-# INLINEABLE oscillate #-}