clash-prelude 1.8.5 → 1.10.0
raw patch · 103 files changed
+3404/−6136 lines, 103 filesdep +adjunctionsdep +data-defaultdep +distributivedep −data-default-classdep −integer-gmpdep ~QuickCheckdep ~basedep ~containersPVP ok
version bump matches the API change (PVP)
Dependencies added: adjunctions, data-default, distributive
Dependencies removed: data-default-class, integer-gmp
Dependency ranges changed: QuickCheck, base, containers, doctest-parallel, ghc, ghc-prim, ghc-typelits-extra, ghc-typelits-knownnat, ghc-typelits-natnormalise, hedgehog, template-haskell, th-abstraction
API changes (from Hackage documentation)
- Clash.Class.BitPack.Internal: instance (Clash.Class.BitPack.Internal.BitPack (f a), Clash.Class.BitPack.Internal.BitPack (g a)) => Clash.Class.BitPack.Internal.BitPack (Data.Functor.Product.Product f g a)
- Clash.Class.BitPack.Internal: instance (Clash.Class.BitPack.Internal.BitPack (f a), Clash.Class.BitPack.Internal.BitPack (g a)) => Clash.Class.BitPack.Internal.BitPack (Data.Functor.Sum.Sum f g a)
- Clash.Class.BitPack.Internal: instance (GHC.TypeNats.KnownNat (Clash.Class.BitPack.Internal.GFieldSize g), GHC.TypeNats.KnownNat (Clash.Class.BitPack.Internal.GFieldSize f), Clash.Class.BitPack.Internal.GBitPack f, Clash.Class.BitPack.Internal.GBitPack g) => Clash.Class.BitPack.Internal.GBitPack (f GHC.Generics.:*: g)
- Clash.Class.BitPack.Internal: instance (GHC.TypeNats.KnownNat (Clash.Class.BitPack.Internal.GFieldSize g), GHC.TypeNats.KnownNat (Clash.Class.BitPack.Internal.GFieldSize f), GHC.TypeNats.KnownNat (Clash.Class.BitPack.Internal.GConstructorCount f), Clash.Class.BitPack.Internal.GBitPack f, Clash.Class.BitPack.Internal.GBitPack g) => Clash.Class.BitPack.Internal.GBitPack (f GHC.Generics.:+: g)
- Clash.Class.BitPack.Internal: instance Clash.Class.BitPack.Internal.BitPack (f (g a)) => Clash.Class.BitPack.Internal.BitPack (Data.Functor.Compose.Compose f g a)
- Clash.Class.BitPack.Internal: instance Clash.Class.BitPack.Internal.BitPack a => Clash.Class.BitPack.Internal.BitPack (Data.Functor.Const.Const a b)
- Clash.Class.BitPack.Internal: instance Clash.Class.BitPack.Internal.GBitPack a => Clash.Class.BitPack.Internal.GBitPack (GHC.Generics.M1 m d a)
- Clash.Intel.ClockGen: alteraPll :: forall t domIn name. (HasAsynchronousReset domIn, Clocks t, ClocksCxt t, NumOutClocks t <= 18) => SSymbol name -> Clock domIn -> Reset domIn -> t
- Clash.Intel.ClockGen: altpll :: forall domOut domIn name. (HasAsynchronousReset domIn, KnownDomain domOut) => SSymbol name -> Clock domIn -> Reset domIn -> (Clock domOut, Signal domOut Bool)
- Clash.Prelude.DataFlow: DF :: (Signal dom i -> Signal dom iEn -> Signal dom oEn -> (Signal dom o, Signal dom oEn, Signal dom iEn)) -> DataFlow dom iEn oEn i o
- Clash.Prelude.DataFlow: [df] :: DataFlow dom iEn oEn i o -> Signal dom i -> Signal dom iEn -> Signal dom oEn -> (Signal dom o, Signal dom oEn, Signal dom iEn)
- Clash.Prelude.DataFlow: class LockStep a b
- Clash.Prelude.DataFlow: fifoDF :: forall addrSize m n a dom. (KnownDomain dom, NFDataX a, KnownNat addrSize, KnownNat n, KnownNat m, (m + n) ~ (2 ^ addrSize)) => Clock dom -> Reset dom -> Enable dom -> SNat (m + n) -> Vec m a -> DataFlow dom Bool Bool a a
- Clash.Prelude.DataFlow: firstDF :: DataFlow dom aEn bEn a b -> DataFlow dom (aEn, cEn) (bEn, cEn) (a, c) (b, c)
- Clash.Prelude.DataFlow: idDF :: DataFlow dom en en a a
- Clash.Prelude.DataFlow: instance (Clash.Prelude.DataFlow.LockStep a x, Clash.Prelude.DataFlow.LockStep b y) => Clash.Prelude.DataFlow.LockStep (a, b) (x, y)
- Clash.Prelude.DataFlow: instance (Clash.Prelude.DataFlow.LockStep en a, GHC.TypeNats.KnownNat n) => Clash.Prelude.DataFlow.LockStep (Clash.Sized.Vector.Vec n en) (Clash.Sized.Vector.Vec n a)
- Clash.Prelude.DataFlow: instance Clash.Prelude.DataFlow.LockStep GHC.Types.Bool c
- Clash.Prelude.DataFlow: liftDF :: (Signal dom i -> Signal dom Bool -> Signal dom Bool -> (Signal dom o, Signal dom Bool, Signal dom Bool)) -> DataFlow dom Bool Bool i o
- Clash.Prelude.DataFlow: lockStep :: LockStep a b => DataFlow dom a Bool b b
- Clash.Prelude.DataFlow: loopDF :: (KnownDomain dom, NFDataX d, KnownNat m, KnownNat n, KnownNat addrSize, (m + n) ~ (2 ^ addrSize)) => Clock dom -> Reset dom -> Enable dom -> SNat (m + n) -> Vec m d -> DataFlow dom (Bool, Bool) (Bool, Bool) (a, d) (b, d) -> DataFlow dom Bool Bool a b
- Clash.Prelude.DataFlow: loopDF_nobuf :: DataFlow dom (Bool, Bool) (Bool, Bool) (a, d) (b, d) -> DataFlow dom Bool Bool a b
- Clash.Prelude.DataFlow: mealyDF :: (KnownDomain dom, NFDataX s) => Clock dom -> Reset dom -> Enable dom -> (s -> i -> (s, o)) -> s -> DataFlow dom Bool Bool i o
- Clash.Prelude.DataFlow: mooreDF :: (KnownDomain dom, NFDataX s) => Clock dom -> Reset dom -> Enable dom -> (s -> i -> s) -> (s -> o) -> s -> DataFlow dom Bool Bool i o
- Clash.Prelude.DataFlow: newtype DataFlow dom iEn oEn i o
- Clash.Prelude.DataFlow: parDF :: DataFlow dom aEn bEn a b -> DataFlow dom cEn dEn c d -> DataFlow dom (aEn, cEn) (bEn, dEn) (a, c) (b, d)
- Clash.Prelude.DataFlow: parNDF :: KnownNat n => Vec n (DataFlow dom aEn bEn a b) -> DataFlow dom (Vec n aEn) (Vec n bEn) (Vec n a) (Vec n b)
- Clash.Prelude.DataFlow: pureDF :: (i -> o) -> DataFlow dom Bool Bool i o
- Clash.Prelude.DataFlow: secondDF :: DataFlow dom aEn bEn a b -> DataFlow dom (cEn, aEn) (cEn, bEn) (c, a) (c, b)
- Clash.Prelude.DataFlow: seqDF :: DataFlow dom aEn bEn a b -> DataFlow dom bEn cEn b c -> DataFlow dom aEn cEn a c
- Clash.Prelude.DataFlow: stepLock :: LockStep a b => DataFlow dom Bool a b b
- Clash.Prelude.DataFlow: swapDF :: DataFlow dom (aEn, bEn) (bEn, aEn) (a, b) (b, a)
- Clash.Signal.Bundle: instance Clash.Signal.Bundle.Bundle ((GHC.Generics.:*:) f g a)
- Clash.Sized.Internal.Index: instance (GHC.TypeNats.KnownNat n, 1 Data.Type.Ord.<= n) => Clash.Class.BitPack.Internal.BitPack (Clash.Sized.Internal.Index.Index n)
- Clash.Sized.Internal.Index: instance (GHC.TypeNats.KnownNat n, 1 Data.Type.Ord.<= n) => Clash.Class.Num.SaturatingNum (Clash.Sized.Internal.Index.Index n)
- Clash.Sized.Internal.Index: instance (GHC.TypeNats.KnownNat n, 1 Data.Type.Ord.<= n) => Clash.Class.Parity.Parity (Clash.Sized.Internal.Index.Index n)
- Clash.Sized.Internal.Index: instance (GHC.TypeNats.KnownNat n, 1 Data.Type.Ord.<= n) => GHC.Bits.Bits (Clash.Sized.Internal.Index.Index n)
- Clash.Sized.Internal.Index: instance (GHC.TypeNats.KnownNat n, 1 Data.Type.Ord.<= n) => GHC.Bits.FiniteBits (Clash.Sized.Internal.Index.Index n)
- Clash.XException: instance (Clash.XException.NFDataX (f a), Clash.XException.NFDataX (g a)) => Clash.XException.NFDataX (Data.Functor.Product.Product f g a)
- Clash.XException: instance (Clash.XException.NFDataX (f a), Clash.XException.NFDataX (g a)) => Clash.XException.NFDataX (Data.Functor.Sum.Sum f g a)
- Clash.XException: instance (Clash.XException.ShowX (f a), Clash.XException.ShowX (g a)) => Clash.XException.ShowX (Data.Functor.Product.Product f g a)
- Clash.XException: instance (Clash.XException.ShowX (f a), Clash.XException.ShowX (g a)) => Clash.XException.ShowX (Data.Functor.Sum.Sum f g a)
- Clash.XException: instance Clash.XException.NFDataX (Data.Proxy.Proxy a)
- Clash.XException: instance Clash.XException.NFDataX (f (g a)) => Clash.XException.NFDataX (Data.Functor.Compose.Compose f g a)
- Clash.XException: instance Clash.XException.NFDataX a => Clash.XException.NFDataX (Data.Functor.Const.Const a b)
- Clash.XException: instance Clash.XException.ShowX (Data.Proxy.Proxy a)
- Clash.XException: instance Clash.XException.ShowX (f (g a)) => Clash.XException.ShowX (Data.Functor.Compose.Compose f g a)
- Clash.XException: instance Clash.XException.ShowX a => Clash.XException.ShowX (Data.Functor.Const.Const a b)
- Clash.XException.Internal: instance (Clash.XException.Internal.GDeepErrorX f, Clash.XException.Internal.GDeepErrorX g) => Clash.XException.Internal.GDeepErrorX (f GHC.Generics.:*: g)
- Clash.XException.Internal: instance (Clash.XException.Internal.GEnsureSpine a, Clash.XException.Internal.GEnsureSpine b) => Clash.XException.Internal.GEnsureSpine (a GHC.Generics.:*: b)
- Clash.XException.Internal: instance (Clash.XException.Internal.GEnsureSpine a, Clash.XException.Internal.GEnsureSpine b) => Clash.XException.Internal.GEnsureSpine (a GHC.Generics.:+: b)
- Clash.XException.Internal: instance (Clash.XException.Internal.GHasUndefined a, Clash.XException.Internal.GHasUndefined b) => Clash.XException.Internal.GHasUndefined (a GHC.Generics.:*: b)
- Clash.XException.Internal: instance (Clash.XException.Internal.GHasUndefined a, Clash.XException.Internal.GHasUndefined b) => Clash.XException.Internal.GHasUndefined (a GHC.Generics.:+: b)
- Clash.XException.Internal: instance (Clash.XException.Internal.GShowX a, Clash.XException.Internal.GShowX b) => Clash.XException.Internal.GShowX (a GHC.Generics.:*: b)
- Clash.XException.Internal: instance (Clash.XException.Internal.GShowX a, Clash.XException.Internal.GShowX b) => Clash.XException.Internal.GShowX (a GHC.Generics.:+: b)
- Clash.XException.Internal: instance (Clash.XException.Internal.GShowX a, GHC.Generics.Constructor c) => Clash.XException.Internal.GShowX (GHC.Generics.M1 GHC.Generics.C c a)
- Clash.XException.Internal: instance (GHC.Generics.Selector s, Clash.XException.Internal.GShowX a) => Clash.XException.Internal.GShowX (GHC.Generics.M1 GHC.Generics.S s a)
- Clash.XException.Internal: instance Clash.XException.Internal.GDeepErrorX (f GHC.Generics.:+: g)
- Clash.XException.Internal: instance Clash.XException.Internal.GDeepErrorX a => Clash.XException.Internal.GDeepErrorX (GHC.Generics.M1 m d a)
- Clash.XException.Internal: instance Clash.XException.Internal.GEnsureSpine a => Clash.XException.Internal.GEnsureSpine (GHC.Generics.M1 i c a)
- Clash.XException.Internal: instance Clash.XException.Internal.GHasUndefined a => Clash.XException.Internal.GHasUndefined (GHC.Generics.M1 i c a)
- Clash.XException.Internal: instance Clash.XException.Internal.GShowX a => Clash.XException.Internal.GShowX (GHC.Generics.M1 GHC.Generics.D d a)
+ Clash.Class.BitPack.Internal: instance forall k (a :: k -> GHC.Types.Type) m (d :: GHC.Generics.Meta). Clash.Class.BitPack.Internal.GBitPack a => Clash.Class.BitPack.Internal.GBitPack (GHC.Generics.M1 m d a)
+ Clash.Class.BitPack.Internal: instance forall k (a :: k). Clash.Class.BitPack.Internal.BitPack (Data.Proxy.Proxy a)
+ Clash.Class.BitPack.Internal: instance forall k (f :: k -> GHC.Types.Type) (a :: k) (g :: k -> GHC.Types.Type). (Clash.Class.BitPack.Internal.BitPack (f a), Clash.Class.BitPack.Internal.BitPack (g a)) => Clash.Class.BitPack.Internal.BitPack (Data.Functor.Product.Product f g a)
+ Clash.Class.BitPack.Internal: instance forall k (f :: k -> GHC.Types.Type) (a :: k) (g :: k -> GHC.Types.Type). (Clash.Class.BitPack.Internal.BitPack (f a), Clash.Class.BitPack.Internal.BitPack (g a)) => Clash.Class.BitPack.Internal.BitPack (Data.Functor.Sum.Sum f g a)
+ Clash.Class.BitPack.Internal: instance forall k (g :: k -> GHC.Types.Type) (f :: k -> GHC.Types.Type). (GHC.TypeNats.KnownNat (Clash.Class.BitPack.Internal.GFieldSize g), GHC.TypeNats.KnownNat (Clash.Class.BitPack.Internal.GFieldSize f), Clash.Class.BitPack.Internal.GBitPack f, Clash.Class.BitPack.Internal.GBitPack g) => Clash.Class.BitPack.Internal.GBitPack (f GHC.Generics.:*: g)
+ Clash.Class.BitPack.Internal: instance forall k (g :: k -> GHC.Types.Type) (f :: k -> GHC.Types.Type). (GHC.TypeNats.KnownNat (Clash.Class.BitPack.Internal.GFieldSize g), GHC.TypeNats.KnownNat (Clash.Class.BitPack.Internal.GFieldSize f), GHC.TypeNats.KnownNat (Clash.Class.BitPack.Internal.GConstructorCount f), Clash.Class.BitPack.Internal.GBitPack f, Clash.Class.BitPack.Internal.GBitPack g) => Clash.Class.BitPack.Internal.GBitPack (f GHC.Generics.:+: g)
+ Clash.Class.BitPack.Internal: instance forall k a (b :: k). Clash.Class.BitPack.Internal.BitPack a => Clash.Class.BitPack.Internal.BitPack (Data.Functor.Const.Const a b)
+ Clash.Class.BitPack.Internal: instance forall k k1 (f :: k -> GHC.Types.Type) (g :: k1 -> k) (a :: k1). Clash.Class.BitPack.Internal.BitPack (f (g a)) => Clash.Class.BitPack.Internal.BitPack (Data.Functor.Compose.Compose f g a)
+ Clash.Class.BitPack.Internal: packCUShort# :: CUShort -> BitVector 16
+ Clash.Class.BitPack.Internal: packInt16# :: Int16 -> BitVector 16
+ Clash.Class.BitPack.Internal: packInt32# :: Int32 -> BitVector 32
+ Clash.Class.BitPack.Internal: packInt64# :: Int64 -> BitVector 64
+ Clash.Class.BitPack.Internal: packInt8# :: Int8 -> BitVector 8
+ Clash.Class.BitPack.Internal: packWord# :: Word -> BitVector 64
+ Clash.Class.BitPack.Internal: packWord16# :: Word16 -> BitVector 16
+ Clash.Class.BitPack.Internal: packWord32# :: Word32 -> BitVector 32
+ Clash.Class.BitPack.Internal: packWord64# :: Word64 -> BitVector 64
+ Clash.Class.BitPack.Internal: packWord8# :: Word8 -> BitVector 8
+ Clash.Class.BitPack.Internal: unpackCUShort# :: BitVector 16 -> CUShort
+ Clash.Class.BitPack.Internal: unpackInt16# :: BitVector 16 -> Int16
+ Clash.Class.BitPack.Internal: unpackInt32# :: BitVector 32 -> Int32
+ Clash.Class.BitPack.Internal: unpackInt64# :: BitVector 64 -> Int64
+ Clash.Class.BitPack.Internal: unpackInt8# :: BitVector 8 -> Int8
+ Clash.Class.BitPack.Internal: unpackWord# :: BitVector 64 -> Word
+ Clash.Class.BitPack.Internal: unpackWord16# :: BitVector 16 -> Word16
+ Clash.Class.BitPack.Internal: unpackWord32# :: BitVector 32 -> Word32
+ Clash.Class.BitPack.Internal: unpackWord64# :: BitVector 64 -> Word64
+ Clash.Class.BitPack.Internal: unpackWord8# :: BitVector 8 -> Word8
+ Clash.Class.Counter.Internal: instance (Clash.Class.Counter.Internal.Counter a, GHC.TypeNats.KnownNat n) => Clash.Class.Counter.Internal.Counter (Clash.Sized.Vector.Vec n a)
+ Clash.Class.Counter.Internal: rippleR :: (a -> (Bool, a)) -> Vec n a -> (Bool, Vec n a)
+ Clash.Class.NumConvert: class MaybeNumConvertCanonical a b
+ Clash.Class.NumConvert: class NumConvertCanonical a b
+ Clash.Class.NumConvert: maybeNumConvert :: forall a b. MaybeNumConvert a b => a -> Maybe b
+ Clash.Class.NumConvert: maybeNumConvertCanonical :: MaybeNumConvertCanonical a b => a -> Maybe b
+ Clash.Class.NumConvert: numConvert :: forall a b. NumConvert a b => a -> b
+ Clash.Class.NumConvert: numConvertCanonical :: NumConvertCanonical a b => a -> b
+ Clash.Class.NumConvert: type MaybeNumConvert a b = (NumConvertCanonical a (Canonical a), MaybeNumConvertCanonical (Canonical a) (Canonical b), NumConvertCanonical (Canonical b) b)
+ Clash.Class.NumConvert: type NumConvert a b = (NumConvertCanonical a (Canonical a), NumConvertCanonical (Canonical a) (Canonical b), NumConvertCanonical (Canonical b) b)
+ Clash.Class.NumConvert: type family Canonical a
+ Clash.Class.Resize: maybeResize :: forall a b f. (Resize f, KnownNat a, Integral (f a), KnownNat b, Integral (f b), Bounded (f b)) => f a -> Maybe (f b)
+ Clash.Class.Resize: maybeTruncateB :: forall a b f. (Resize f, KnownNat b, Integral (f (a + b)), KnownNat a, Integral (f a), Bounded (f a)) => f (a + b) -> Maybe (f a)
+ Clash.Explicit.BlockRam: instance (Clash.Class.BitPack.Internal.BitPack a, GHC.TypeNats.KnownNat n) => Clash.Class.BitPack.Internal.BitPack (Clash.Explicit.BlockRam.RamOp n a)
+ Clash.Explicit.BlockRam: instance Clash.XException.ShowX a => Clash.XException.ShowX (Clash.Explicit.BlockRam.RamOp n a)
+ Clash.Explicit.BlockRam: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Clash.Explicit.BlockRam.RamOp n a)
+ Clash.Explicit.BlockRam: instance GHC.Classes.Eq a => GHC.Classes.Eq (Clash.Explicit.BlockRam.RamOp n a)
+ Clash.Explicit.DDR: ddrForwardClock :: forall domDDR domOut domIn. KnownDomain domOut => DomainPeriod domIn ~ DomainPeriod domOut => DomainPeriod domIn ~ (2 * DomainPeriod domDDR) => Clock domIn -> Reset domIn -> Enable domIn -> Maybe Bit -> Maybe Bit -> (Clock domIn -> Reset domIn -> Enable domIn -> Signal domIn (Bit, Bit) -> Signal domDDR Bit) -> Clock domOut
+ Clash.Explicit.DDR: ddrForwardClock# :: KnownDomain domOut => DomainPeriod domIn ~ DomainPeriod domOut => DomainPeriod domIn ~ (2 * DomainPeriod domDDR) => Clock domIn -> Signal domDDR Bit -> Clock domOut
+ Clash.Explicit.Prelude: maybeNumConvert :: forall a b. MaybeNumConvert a b => a -> Maybe b
+ Clash.Explicit.Prelude: numConvert :: forall a b. NumConvert a b => a -> b
+ Clash.Explicit.Prelude: smapWithBounds :: forall k a b. KnownNat k => (forall n. (n + 1) <= k => SNat n -> a -> b) -> Vec k a -> Vec k b
+ Clash.Explicit.Prelude: type MaybeNumConvert a b = (NumConvertCanonical a (Canonical a), MaybeNumConvertCanonical (Canonical a) (Canonical b), NumConvertCanonical (Canonical b) b)
+ Clash.Explicit.Prelude: type NumConvert a b = (NumConvertCanonical a (Canonical a), NumConvertCanonical (Canonical a) (Canonical b), NumConvertCanonical (Canonical b) b)
+ Clash.Explicit.Prelude.Safe: smapWithBounds :: forall k a b. KnownNat k => (forall n. (n + 1) <= k => SNat n -> a -> b) -> Vec k a -> Vec k b
+ Clash.Explicit.Signal: (./=) :: (Eq a, Functor f) => f a -> a -> f Bool
+ Clash.Explicit.Signal: (.<) :: (Ord a, Functor f) => f a -> a -> f Bool
+ Clash.Explicit.Signal: (.<=) :: (Ord a, Functor f) => f a -> a -> f Bool
+ Clash.Explicit.Signal: (.==) :: (Eq a, Functor f) => f a -> a -> f Bool
+ Clash.Explicit.Signal: (.>) :: (Ord a, Functor f) => f a -> a -> f Bool
+ Clash.Explicit.Signal: (.>=) :: (Ord a, Functor f) => f a -> a -> f Bool
+ Clash.Explicit.Signal: (/=.) :: (Eq a, Functor f) => a -> f a -> f Bool
+ Clash.Explicit.Signal: (<.) :: (Ord a, Functor f) => a -> f a -> f Bool
+ Clash.Explicit.Signal: (<=.) :: (Ord a, Functor f) => a -> f a -> f Bool
+ Clash.Explicit.Signal: (==.) :: (Eq a, Functor f) => a -> f a -> f Bool
+ Clash.Explicit.Signal: (>.) :: (Ord a, Functor f) => a -> f a -> f Bool
+ Clash.Explicit.Signal: (>=.) :: (Ord a, Functor f) => a -> f a -> f Bool
+ Clash.Explicit.Signal: apEn :: Applicative f => f Bool -> (a -> a) -> f a -> f a
+ Clash.Explicit.Signal: regEnN :: forall dom a n. (KnownDomain dom, NFDataX a) => Clock dom -> Reset dom -> Enable dom -> SNat n -> a -> Signal dom Bool -> Signal dom a -> Signal dom a
+ Clash.Explicit.Signal: type ClockDivider (dom :: Domain) (period :: Nat) = PeriodToCycles dom period
+ Clash.Explicit.Signal: type DomainToHz (dom :: Domain) = PeriodToHz (DomainPeriod dom)
+ Clash.Explicit.Signal: type HzToPeriod (hz :: Nat) = Seconds 1 `Div` hz
+ Clash.Explicit.Signal: type Microseconds (us :: Nat) = Nanoseconds (1000 * us)
+ Clash.Explicit.Signal: type Milliseconds (ms :: Nat) = Microseconds (1000 * ms)
+ Clash.Explicit.Signal: type Nanoseconds (ns :: Nat) = Picoseconds (1000 * ns)
+ Clash.Explicit.Signal: type PeriodToCycles (dom :: Domain) (period :: Nat) = period `DivRU` DomainPeriod dom
+ Clash.Explicit.Signal: type PeriodToHz (period :: Nat) = (Seconds 1) `Div` period
+ Clash.Explicit.Signal: type Picoseconds (ps :: Nat) = ps
+ Clash.Explicit.Signal: type Seconds (s :: Nat) = Milliseconds (1000 * s)
+ Clash.Intel.DDR: altddioIn# :: forall deviceFamily n dom domDDR. HasCallStack => KnownDomain dom => KnownDomain domDDR => DomainPeriod dom ~ (2 * DomainPeriod domDDR) => DomainActiveEdge dom ~ 'Rising => KnownNat n => SSymbol deviceFamily -> Clock dom -> Reset dom -> Enable dom -> Signal domDDR (BitVector n) -> Signal dom (BitVector n, BitVector n)
+ Clash.Intel.DDR: altddioOut# :: forall deviceFamily n dom domDDR. HasCallStack => KnownDomain dom => KnownDomain domDDR => DomainPeriod dom ~ (2 * DomainPeriod domDDR) => DomainActiveEdge dom ~ 'Rising => KnownNat n => SSymbol deviceFamily -> Clock dom -> Reset dom -> Enable dom -> Signal dom (BitVector n) -> Signal dom (BitVector n) -> Signal domDDR (BitVector n)
+ Clash.Prelude: (&&.) :: Functor f => Bool -> f Bool -> f Bool
+ Clash.Prelude: (.&&) :: Functor f => f Bool -> Bool -> f Bool
+ Clash.Prelude: (./=) :: (Eq a, Functor f) => f a -> a -> f Bool
+ Clash.Prelude: (.<) :: (Ord a, Functor f) => f a -> a -> f Bool
+ Clash.Prelude: (.<=) :: (Ord a, Functor f) => f a -> a -> f Bool
+ Clash.Prelude: (.==) :: (Eq a, Functor f) => f a -> a -> f Bool
+ Clash.Prelude: (.>) :: (Ord a, Functor f) => f a -> a -> f Bool
+ Clash.Prelude: (.>=) :: (Ord a, Functor f) => f a -> a -> f Bool
+ Clash.Prelude: (.||) :: Functor f => f Bool -> Bool -> f Bool
+ Clash.Prelude: (/=.) :: (Eq a, Functor f) => a -> f a -> f Bool
+ Clash.Prelude: (<.) :: (Ord a, Functor f) => a -> f a -> f Bool
+ Clash.Prelude: (<=.) :: (Ord a, Functor f) => a -> f a -> f Bool
+ Clash.Prelude: (==.) :: (Eq a, Functor f) => a -> f a -> f Bool
+ Clash.Prelude: (>.) :: (Ord a, Functor f) => a -> f a -> f Bool
+ Clash.Prelude: (>=.) :: (Ord a, Functor f) => a -> f a -> f Bool
+ Clash.Prelude: (||.) :: Functor f => Bool -> f Bool -> f Bool
+ Clash.Prelude: apEn :: Applicative f => f Bool -> (a -> a) -> f a -> f a
+ Clash.Prelude: infix 2 .||
+ Clash.Prelude: maybeNumConvert :: forall a b. MaybeNumConvert a b => a -> Maybe b
+ Clash.Prelude: numConvert :: forall a b. NumConvert a b => a -> b
+ Clash.Prelude: regEnN :: forall dom a n. (HiddenClockResetEnable dom, NFDataX a) => SNat n -> a -> Signal dom Bool -> Signal dom a -> Signal dom a
+ Clash.Prelude: smapWithBounds :: forall k a b. KnownNat k => (forall n. (n + 1) <= k => SNat n -> a -> b) -> Vec k a -> Vec k b
+ Clash.Prelude: type ClockDivider (dom :: Domain) (period :: Nat) = PeriodToCycles dom period
+ Clash.Prelude: type DomainToHz (dom :: Domain) = PeriodToHz (DomainPeriod dom)
+ Clash.Prelude: type HzToPeriod (hz :: Nat) = Seconds 1 `Div` hz
+ Clash.Prelude: type MaybeNumConvert a b = (NumConvertCanonical a (Canonical a), MaybeNumConvertCanonical (Canonical a) (Canonical b), NumConvertCanonical (Canonical b) b)
+ Clash.Prelude: type Microseconds (us :: Nat) = Nanoseconds (1000 * us)
+ Clash.Prelude: type Milliseconds (ms :: Nat) = Microseconds (1000 * ms)
+ Clash.Prelude: type Nanoseconds (ns :: Nat) = Picoseconds (1000 * ns)
+ Clash.Prelude: type NumConvert a b = (NumConvertCanonical a (Canonical a), NumConvertCanonical (Canonical a) (Canonical b), NumConvertCanonical (Canonical b) b)
+ Clash.Prelude: type PeriodToCycles (dom :: Domain) (period :: Nat) = period `DivRU` DomainPeriod dom
+ Clash.Prelude: type PeriodToHz (period :: Nat) = (Seconds 1) `Div` period
+ Clash.Prelude: type Picoseconds (ps :: Nat) = ps
+ Clash.Prelude: type Seconds (s :: Nat) = Milliseconds (1000 * s)
+ Clash.Prelude.Safe: smapWithBounds :: forall k a b. KnownNat k => (forall n. (n + 1) <= k => SNat n -> a -> b) -> Vec k a -> Vec k b
+ Clash.Signal: (&&.) :: Functor f => Bool -> f Bool -> f Bool
+ Clash.Signal: (.&&) :: Functor f => f Bool -> Bool -> f Bool
+ Clash.Signal: (./=) :: (Eq a, Functor f) => f a -> a -> f Bool
+ Clash.Signal: (.<) :: (Ord a, Functor f) => f a -> a -> f Bool
+ Clash.Signal: (.<=) :: (Ord a, Functor f) => f a -> a -> f Bool
+ Clash.Signal: (.==) :: (Eq a, Functor f) => f a -> a -> f Bool
+ Clash.Signal: (.>) :: (Ord a, Functor f) => f a -> a -> f Bool
+ Clash.Signal: (.>=) :: (Ord a, Functor f) => f a -> a -> f Bool
+ Clash.Signal: (.||) :: Functor f => f Bool -> Bool -> f Bool
+ Clash.Signal: (/=.) :: (Eq a, Functor f) => a -> f a -> f Bool
+ Clash.Signal: (<.) :: (Ord a, Functor f) => a -> f a -> f Bool
+ Clash.Signal: (<=.) :: (Ord a, Functor f) => a -> f a -> f Bool
+ Clash.Signal: (==.) :: (Eq a, Functor f) => a -> f a -> f Bool
+ Clash.Signal: (>.) :: (Ord a, Functor f) => a -> f a -> f Bool
+ Clash.Signal: (>=.) :: (Ord a, Functor f) => a -> f a -> f Bool
+ Clash.Signal: (||.) :: Functor f => Bool -> f Bool -> f Bool
+ Clash.Signal: apEn :: Applicative f => f Bool -> (a -> a) -> f a -> f a
+ Clash.Signal: infix 2 .||
+ Clash.Signal: regEnN :: forall dom a n. (HiddenClockResetEnable dom, NFDataX a) => SNat n -> a -> Signal dom Bool -> Signal dom a -> Signal dom a
+ Clash.Signal: type ClockDivider (dom :: Domain) (period :: Nat) = PeriodToCycles dom period
+ Clash.Signal: type DomainToHz (dom :: Domain) = PeriodToHz (DomainPeriod dom)
+ Clash.Signal: type HzToPeriod (hz :: Nat) = Seconds 1 `Div` hz
+ Clash.Signal: type Microseconds (us :: Nat) = Nanoseconds (1000 * us)
+ Clash.Signal: type Milliseconds (ms :: Nat) = Microseconds (1000 * ms)
+ Clash.Signal: type Nanoseconds (ns :: Nat) = Picoseconds (1000 * ns)
+ Clash.Signal: type PeriodToCycles (dom :: Domain) (period :: Nat) = period `DivRU` DomainPeriod dom
+ Clash.Signal: type PeriodToHz (period :: Nat) = (Seconds 1) `Div` period
+ Clash.Signal: type Picoseconds (ps :: Nat) = ps
+ Clash.Signal: type Seconds (s :: Nat) = Milliseconds (1000 * s)
+ Clash.Signal.Bundle: instance forall k (f :: k -> GHC.Types.Type) (g :: k -> GHC.Types.Type) (a :: k). Clash.Signal.Bundle.Bundle ((GHC.Generics.:*:) f g a)
+ Clash.Signal.Internal: (&&.) :: Functor f => Bool -> f Bool -> f Bool
+ Clash.Signal.Internal: (.&&) :: Functor f => f Bool -> Bool -> f Bool
+ Clash.Signal.Internal: (./=) :: (Eq a, Functor f) => f a -> a -> f Bool
+ Clash.Signal.Internal: (.<) :: (Ord a, Functor f) => f a -> a -> f Bool
+ Clash.Signal.Internal: (.<=) :: (Ord a, Functor f) => f a -> a -> f Bool
+ Clash.Signal.Internal: (.==) :: (Eq a, Functor f) => f a -> a -> f Bool
+ Clash.Signal.Internal: (.>) :: (Ord a, Functor f) => f a -> a -> f Bool
+ Clash.Signal.Internal: (.>=) :: (Ord a, Functor f) => f a -> a -> f Bool
+ Clash.Signal.Internal: (.||) :: Functor f => f Bool -> Bool -> f Bool
+ Clash.Signal.Internal: (/=.) :: (Eq a, Functor f) => a -> f a -> f Bool
+ Clash.Signal.Internal: (<.) :: (Ord a, Functor f) => a -> f a -> f Bool
+ Clash.Signal.Internal: (<=.) :: (Ord a, Functor f) => a -> f a -> f Bool
+ Clash.Signal.Internal: (==.) :: (Eq a, Functor f) => a -> f a -> f Bool
+ Clash.Signal.Internal: (>.) :: (Ord a, Functor f) => a -> f a -> f Bool
+ Clash.Signal.Internal: (>=.) :: (Ord a, Functor f) => a -> f a -> f Bool
+ Clash.Signal.Internal: (||.) :: Functor f => Bool -> f Bool -> f Bool
+ Clash.Signal.Internal: apEn :: Applicative f => f Bool -> (a -> a) -> f a -> f a
+ Clash.Signal.Internal: infix 2 .||
+ Clash.Signal.Internal: instance Clash.Class.Num.SaturatingNum a => Clash.Class.Num.SaturatingNum (Clash.Signal.Internal.Signal dom a)
+ Clash.Signal.Internal: instance GHC.Enum.Bounded a => GHC.Enum.Bounded (Clash.Signal.Internal.Signal dom a)
+ Clash.Signal.Internal: instance forall k (x :: k) r a (dom :: Clash.Signal.Internal.Domain). GHC.Records.HasField x r a => GHC.Records.HasField x (Clash.Signal.Internal.Signal dom r) (Clash.Signal.Internal.Signal dom a)
+ Clash.Signal.Internal: type ClockDivider (dom :: Domain) (period :: Nat) = PeriodToCycles dom period
+ Clash.Signal.Internal: type DomainToHz (dom :: Domain) = PeriodToHz (DomainPeriod dom)
+ Clash.Signal.Internal: type HzToPeriod (hz :: Nat) = Seconds 1 `Div` hz
+ Clash.Signal.Internal: type Microseconds (us :: Nat) = Nanoseconds (1000 * us)
+ Clash.Signal.Internal: type Milliseconds (ms :: Nat) = Microseconds (1000 * ms)
+ Clash.Signal.Internal: type Nanoseconds (ns :: Nat) = Picoseconds (1000 * ns)
+ Clash.Signal.Internal: type PeriodToCycles (dom :: Domain) (period :: Nat) = period `DivRU` DomainPeriod dom
+ Clash.Signal.Internal: type PeriodToHz (period :: Nat) = (Seconds 1) `Div` period
+ Clash.Signal.Internal: type Picoseconds (ps :: Nat) = ps
+ Clash.Signal.Internal: type Seconds (s :: Nat) = Milliseconds (1000 * s)
+ Clash.Sized.Internal.Index: instance GHC.TypeNats.KnownNat n => Clash.Class.BitPack.Internal.BitPack (Clash.Sized.Internal.Index.Index n)
+ Clash.Sized.Internal.Index: instance GHC.TypeNats.KnownNat n => Clash.Class.Num.SaturatingNum (Clash.Sized.Internal.Index.Index n)
+ Clash.Sized.Internal.Index: instance GHC.TypeNats.KnownNat n => Clash.Class.Parity.Parity (Clash.Sized.Internal.Index.Index n)
+ Clash.Sized.Internal.Index: instance GHC.TypeNats.KnownNat n => GHC.Bits.Bits (Clash.Sized.Internal.Index.Index n)
+ Clash.Sized.Internal.Index: instance GHC.TypeNats.KnownNat n => GHC.Bits.FiniteBits (Clash.Sized.Internal.Index.Index n)
+ Clash.Sized.Vector: instance GHC.TypeNats.KnownNat n => Data.Distributive.Distributive (Clash.Sized.Vector.Vec n)
+ Clash.Sized.Vector: instance GHC.TypeNats.KnownNat n => Data.Functor.Rep.Representable (Clash.Sized.Vector.Vec n)
+ Clash.Sized.Vector: smapWithBounds :: forall k a b. KnownNat k => (forall n. (n + 1) <= k => SNat n -> a -> b) -> Vec k a -> Vec k b
+ Clash.XException: instance Clash.XException.ShowX Foreign.C.Types.CUShort
+ Clash.XException: instance forall k (a :: k). Clash.XException.NFDataX (Data.Proxy.Proxy a)
+ Clash.XException: instance forall k (a :: k). Clash.XException.ShowX (Data.Proxy.Proxy a)
+ Clash.XException: instance forall k (f :: k -> GHC.Types.Type) (a :: k) (g :: k -> GHC.Types.Type). (Clash.XException.NFDataX (f a), Clash.XException.NFDataX (g a)) => Clash.XException.NFDataX (Data.Functor.Product.Product f g a)
+ Clash.XException: instance forall k (f :: k -> GHC.Types.Type) (a :: k) (g :: k -> GHC.Types.Type). (Clash.XException.NFDataX (f a), Clash.XException.NFDataX (g a)) => Clash.XException.NFDataX (Data.Functor.Sum.Sum f g a)
+ Clash.XException: instance forall k (f :: k -> GHC.Types.Type) (a :: k) (g :: k -> GHC.Types.Type). (Clash.XException.ShowX (f a), Clash.XException.ShowX (g a)) => Clash.XException.ShowX (Data.Functor.Product.Product f g a)
+ Clash.XException: instance forall k (f :: k -> GHC.Types.Type) (a :: k) (g :: k -> GHC.Types.Type). (Clash.XException.ShowX (f a), Clash.XException.ShowX (g a)) => Clash.XException.ShowX (Data.Functor.Sum.Sum f g a)
+ Clash.XException: instance forall k a (b :: k). Clash.XException.NFDataX a => Clash.XException.NFDataX (Data.Functor.Const.Const a b)
+ Clash.XException: instance forall k a (b :: k). Clash.XException.ShowX a => Clash.XException.ShowX (Data.Functor.Const.Const a b)
+ Clash.XException: instance forall k k1 (f :: k -> GHC.Types.Type) (g :: k1 -> k) (a :: k1). Clash.XException.NFDataX (f (g a)) => Clash.XException.NFDataX (Data.Functor.Compose.Compose f g a)
+ Clash.XException: instance forall k k1 (f :: k -> GHC.Types.Type) (g :: k1 -> k) (a :: k1). Clash.XException.ShowX (f (g a)) => Clash.XException.ShowX (Data.Functor.Compose.Compose f g a)
+ Clash.XException.Internal: instance forall k (a :: k -> GHC.Types.Type) (b :: k -> GHC.Types.Type). (Clash.XException.Internal.GEnsureSpine a, Clash.XException.Internal.GEnsureSpine b) => Clash.XException.Internal.GEnsureSpine (a GHC.Generics.:*: b)
+ Clash.XException.Internal: instance forall k (a :: k -> GHC.Types.Type) (b :: k -> GHC.Types.Type). (Clash.XException.Internal.GEnsureSpine a, Clash.XException.Internal.GEnsureSpine b) => Clash.XException.Internal.GEnsureSpine (a GHC.Generics.:+: b)
+ Clash.XException.Internal: instance forall k (a :: k -> GHC.Types.Type) (b :: k -> GHC.Types.Type). (Clash.XException.Internal.GHasUndefined a, Clash.XException.Internal.GHasUndefined b) => Clash.XException.Internal.GHasUndefined (a GHC.Generics.:*: b)
+ Clash.XException.Internal: instance forall k (a :: k -> GHC.Types.Type) (b :: k -> GHC.Types.Type). (Clash.XException.Internal.GHasUndefined a, Clash.XException.Internal.GHasUndefined b) => Clash.XException.Internal.GHasUndefined (a GHC.Generics.:+: b)
+ Clash.XException.Internal: instance forall k (a :: k -> GHC.Types.Type) (b :: k -> GHC.Types.Type). (Clash.XException.Internal.GShowX a, Clash.XException.Internal.GShowX b) => Clash.XException.Internal.GShowX (a GHC.Generics.:*: b)
+ Clash.XException.Internal: instance forall k (a :: k -> GHC.Types.Type) (b :: k -> GHC.Types.Type). (Clash.XException.Internal.GShowX a, Clash.XException.Internal.GShowX b) => Clash.XException.Internal.GShowX (a GHC.Generics.:+: b)
+ Clash.XException.Internal: instance forall k (a :: k -> GHC.Types.Type) (c :: GHC.Generics.Meta). (Clash.XException.Internal.GShowX a, GHC.Generics.Constructor c) => Clash.XException.Internal.GShowX (GHC.Generics.M1 GHC.Generics.C c a)
+ Clash.XException.Internal: instance forall k (a :: k -> GHC.Types.Type) (d :: GHC.Generics.Meta). Clash.XException.Internal.GShowX a => Clash.XException.Internal.GShowX (GHC.Generics.M1 GHC.Generics.D d a)
+ Clash.XException.Internal: instance forall k (a :: k -> GHC.Types.Type) i (c :: GHC.Generics.Meta). Clash.XException.Internal.GEnsureSpine a => Clash.XException.Internal.GEnsureSpine (GHC.Generics.M1 i c a)
+ Clash.XException.Internal: instance forall k (a :: k -> GHC.Types.Type) i (c :: GHC.Generics.Meta). Clash.XException.Internal.GHasUndefined a => Clash.XException.Internal.GHasUndefined (GHC.Generics.M1 i c a)
+ Clash.XException.Internal: instance forall k (a :: k -> GHC.Types.Type) m (d :: GHC.Generics.Meta). Clash.XException.Internal.GDeepErrorX a => Clash.XException.Internal.GDeepErrorX (GHC.Generics.M1 m d a)
+ Clash.XException.Internal: instance forall k (f :: k -> GHC.Types.Type) (g :: k -> GHC.Types.Type). (Clash.XException.Internal.GDeepErrorX f, Clash.XException.Internal.GDeepErrorX g) => Clash.XException.Internal.GDeepErrorX (f GHC.Generics.:*: g)
+ Clash.XException.Internal: instance forall k (f :: k -> GHC.Types.Type) (g :: k -> GHC.Types.Type). Clash.XException.Internal.GDeepErrorX (f GHC.Generics.:+: g)
+ Clash.XException.Internal: instance forall k (s :: GHC.Generics.Meta) (a :: k -> GHC.Types.Type). (GHC.Generics.Selector s, Clash.XException.Internal.GShowX a) => Clash.XException.Internal.GShowX (GHC.Generics.M1 GHC.Generics.S s a)
+ Clash.Xilinx.DDR: iddr# :: forall n dom domDDR. HasCallStack => KnownDomain dom => KnownDomain domDDR => DomainPeriod dom ~ (2 * DomainPeriod domDDR) => DomainActiveEdge dom ~ 'Rising => KnownNat n => Clock dom -> Reset dom -> Enable dom -> Signal domDDR (BitVector n) -> Signal dom (BitVector n, BitVector n)
+ Clash.Xilinx.DDR: oddr# :: forall n dom domDDR. HasCallStack => KnownDomain dom => KnownDomain domDDR => DomainPeriod dom ~ (2 * DomainPeriod domDDR) => DomainActiveEdge dom ~ 'Rising => KnownNat n => Clock dom -> Reset dom -> Enable dom -> Signal dom (BitVector n) -> Signal dom (BitVector n) -> Signal domDDR (BitVector n)
- Clash.Explicit.BlockRam: [ClearOnReset] :: ResetStrategy 'True
+ Clash.Explicit.BlockRam: [ClearOnReset] :: a -> ResetStrategy 'True a
- Clash.Explicit.BlockRam: [NoClearOnReset] :: ResetStrategy 'False
+ Clash.Explicit.BlockRam: [NoClearOnReset] :: ResetStrategy 'False a
- Clash.Explicit.BlockRam: blockRam1 :: forall n dom a r addr. (KnownDomain dom, HasCallStack, NFDataX a, Enum addr, NFDataX addr, 1 <= n) => Clock dom -> Reset dom -> Enable dom -> ResetStrategy r -> SNat n -> a -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
+ Clash.Explicit.BlockRam: blockRam1 :: forall n dom a r addr. (KnownDomain dom, HasCallStack, NFDataX a, Enum addr, NFDataX addr) => Clock dom -> Reset dom -> Enable dom -> ResetStrategy r () -> SNat n -> a -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
- Clash.Explicit.BlockRam: blockRamU :: forall n dom a r addr. (KnownDomain dom, HasCallStack, NFDataX a, Enum addr, NFDataX addr, 1 <= n) => Clock dom -> Reset dom -> Enable dom -> ResetStrategy r -> SNat n -> (Index n -> a) -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
+ Clash.Explicit.BlockRam: blockRamU :: forall n dom a r addr. (KnownDomain dom, HasCallStack, NFDataX a, Enum addr, NFDataX addr) => Clock dom -> Reset dom -> Enable dom -> ResetStrategy r (Index n -> a) -> SNat n -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
- Clash.Explicit.BlockRam: data ResetStrategy (r :: Bool)
+ Clash.Explicit.BlockRam: data ResetStrategy (r :: Bool) a
- Clash.Explicit.DDR: ddrIn :: (HasCallStack, NFDataX a, KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity), KnownConfiguration slow ('DomainConfiguration slow (2 * fPeriod) edge reset init polarity)) => Clock slow -> Reset slow -> Enable slow -> (a, a, a) -> Signal fast a -> Signal slow (a, a)
+ Clash.Explicit.DDR: ddrIn :: forall a dom domDDR. HasCallStack => NFDataX a => KnownDomain dom => KnownDomain domDDR => DomainPeriod dom ~ (2 * DomainPeriod domDDR) => Clock dom -> Reset dom -> Enable dom -> (a, a, a) -> Signal domDDR a -> Signal dom (a, a)
- Clash.Explicit.DDR: ddrIn# :: forall a slow fast fPeriod polarity edge reset init. (HasCallStack, NFDataX a, KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity), KnownConfiguration slow ('DomainConfiguration slow (2 * fPeriod) edge reset init polarity)) => Clock slow -> Reset slow -> Enable slow -> a -> a -> a -> Signal fast a -> Signal slow (a, a)
+ Clash.Explicit.DDR: ddrIn# :: forall a dom domDDR. HasCallStack => NFDataX a => KnownDomain dom => KnownDomain domDDR => DomainPeriod dom ~ (2 * DomainPeriod domDDR) => Clock dom -> Reset dom -> Enable dom -> a -> a -> a -> Signal domDDR a -> Signal dom (a, a)
- Clash.Explicit.DDR: ddrOut :: (HasCallStack, NFDataX a, KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity), KnownConfiguration slow ('DomainConfiguration slow (2 * fPeriod) edge reset init polarity)) => Clock slow -> Reset slow -> Enable slow -> a -> Signal slow (a, a) -> Signal fast a
+ Clash.Explicit.DDR: ddrOut :: forall a dom domDDR. HasCallStack => NFDataX a => KnownDomain dom => KnownDomain domDDR => DomainPeriod dom ~ (2 * DomainPeriod domDDR) => Clock dom -> Reset dom -> Enable dom -> a -> Signal dom (a, a) -> Signal domDDR a
- Clash.Explicit.DDR: ddrOut# :: (HasCallStack, NFDataX a, KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity), KnownConfiguration slow ('DomainConfiguration slow (2 * fPeriod) edge reset init polarity)) => Clock slow -> Reset slow -> Enable slow -> a -> Signal slow a -> Signal slow a -> Signal fast a
+ Clash.Explicit.DDR: ddrOut# :: forall a dom domDDR. HasCallStack => NFDataX a => KnownDomain dom => KnownDomain domDDR => DomainPeriod dom ~ (2 * DomainPeriod domDDR) => Clock dom -> Reset dom -> Enable dom -> a -> Signal dom a -> Signal dom a -> Signal domDDR a
- Clash.Explicit.Prelude: (+>>) :: KnownNat n => a -> Vec n a -> Vec n a
+ Clash.Explicit.Prelude: (+>>) :: forall n a. a -> Vec n a -> Vec n a
- Clash.Explicit.Prelude: [ClearOnReset] :: ResetStrategy 'True
+ Clash.Explicit.Prelude: [ClearOnReset] :: a -> ResetStrategy 'True a
- Clash.Explicit.Prelude: [NoClearOnReset] :: ResetStrategy 'False
+ Clash.Explicit.Prelude: [NoClearOnReset] :: ResetStrategy 'False a
- Clash.Explicit.Prelude: blockRam1 :: forall n dom a r addr. (KnownDomain dom, HasCallStack, NFDataX a, Enum addr, NFDataX addr, 1 <= n) => Clock dom -> Reset dom -> Enable dom -> ResetStrategy r -> SNat n -> a -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
+ Clash.Explicit.Prelude: blockRam1 :: forall n dom a r addr. (KnownDomain dom, HasCallStack, NFDataX a, Enum addr, NFDataX addr) => Clock dom -> Reset dom -> Enable dom -> ResetStrategy r () -> SNat n -> a -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
- Clash.Explicit.Prelude: blockRamU :: forall n dom a r addr. (KnownDomain dom, HasCallStack, NFDataX a, Enum addr, NFDataX addr, 1 <= n) => Clock dom -> Reset dom -> Enable dom -> ResetStrategy r -> SNat n -> (Index n -> a) -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
+ Clash.Explicit.Prelude: blockRamU :: forall n dom a r addr. (KnownDomain dom, HasCallStack, NFDataX a, Enum addr, NFDataX addr) => Clock dom -> Reset dom -> Enable dom -> ResetStrategy r (Index n -> a) -> SNat n -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
- Clash.Explicit.Prelude: data ResetStrategy (r :: Bool)
+ Clash.Explicit.Prelude: data ResetStrategy (r :: Bool) a
- Clash.Explicit.Prelude: dfold :: forall p k a. KnownNat k => Proxy (p :: TyFun Nat Type -> Type) -> (forall l. SNat l -> a -> (p @@ l) -> p @@ (l + 1)) -> (p @@ 0) -> Vec k a -> p @@ k
+ Clash.Explicit.Prelude: dfold :: forall p k a. KnownNat k => Proxy (p :: TyFun Nat Type -> Type) -> (forall n. (n + 1) <= k => SNat n -> a -> (p @@ n) -> p @@ (n + 1)) -> (p @@ 0) -> Vec k a -> p @@ k
- Clash.Explicit.Prelude: dtfold :: forall p k a. KnownNat k => Proxy (p :: TyFun Nat Type -> Type) -> (a -> p @@ 0) -> (forall l. SNat l -> (p @@ l) -> (p @@ l) -> p @@ (l + 1)) -> Vec (2 ^ k) a -> p @@ k
+ Clash.Explicit.Prelude: dtfold :: forall p k a. KnownNat k => Proxy (p :: TyFun Nat Type -> Type) -> (a -> p @@ 0) -> (forall n. SNat n -> (p @@ n) -> (p @@ n) -> p @@ (n + 1)) -> Vec (2 ^ k) a -> p @@ k
- Clash.Explicit.Prelude: foldl :: (b -> a -> b) -> b -> Vec n a -> b
+ Clash.Explicit.Prelude: foldl :: forall b a n. (b -> a -> b) -> b -> Vec n a -> b
- Clash.Explicit.Prelude: interleave :: (KnownNat n, KnownNat d) => SNat d -> Vec (n * d) a -> Vec (d * n) a
+ Clash.Explicit.Prelude: interleave :: KnownNat n => SNat d -> Vec (n * d) a -> Vec (d * n) a
- Clash.Explicit.Prelude: merge :: KnownNat n => Vec n a -> Vec n a -> Vec (2 * n) a
+ Clash.Explicit.Prelude: merge :: Vec n a -> Vec n a -> Vec (2 * n) a
- Clash.Explicit.Prelude: scanl1 :: KnownNat n => (a -> a -> a) -> Vec (n + 1) a -> Vec (n + 1) a
+ Clash.Explicit.Prelude: scanl1 :: forall n a. (a -> a -> a) -> Vec (n + 1) a -> Vec (n + 1) a
- Clash.Explicit.Prelude: scanr1 :: KnownNat n => (a -> a -> a) -> Vec (n + 1) a -> Vec (n + 1) a
+ Clash.Explicit.Prelude: scanr1 :: forall n a. (a -> a -> a) -> Vec (n + 1) a -> Vec (n + 1) a
- Clash.Explicit.Prelude: select :: CmpNat (i + s) (s * n) ~ 'GT => SNat f -> SNat s -> SNat n -> Vec (f + i) a -> Vec n a
+ Clash.Explicit.Prelude: select :: forall i s n f a. ((s * n) + 1) <= (i + s) => SNat f -> SNat s -> SNat n -> Vec (f + i) a -> Vec n a
- Clash.Explicit.Prelude: selectI :: (CmpNat (i + s) (s * n) ~ 'GT, KnownNat n) => SNat f -> SNat s -> Vec (f + i) a -> Vec n a
+ Clash.Explicit.Prelude: selectI :: (1 <= s, ((s * n) + 1) <= (i + s), KnownNat n) => SNat f -> SNat s -> Vec (f + i) a -> Vec n a
- Clash.Explicit.Prelude: smap :: forall k a b. KnownNat k => (forall l. SNat l -> a -> b) -> Vec k a -> Vec k b
+ Clash.Explicit.Prelude: smap :: forall k a b. KnownNat k => (forall n. SNat n -> a -> b) -> Vec k a -> Vec k b
- Clash.Explicit.Prelude: vfold :: forall k a b. KnownNat k => (forall l. SNat l -> a -> Vec l b -> Vec (l + 1) b) -> Vec k a -> Vec k b
+ Clash.Explicit.Prelude: vfold :: forall k a b. KnownNat k => (forall n. SNat n -> a -> Vec n b -> Vec (n + 1) b) -> Vec k a -> Vec k b
- Clash.Explicit.Prelude.Safe: (+>>) :: KnownNat n => a -> Vec n a -> Vec n a
+ Clash.Explicit.Prelude.Safe: (+>>) :: forall n a. a -> Vec n a -> Vec n a
- Clash.Explicit.Prelude.Safe: dfold :: forall p k a. KnownNat k => Proxy (p :: TyFun Nat Type -> Type) -> (forall l. SNat l -> a -> (p @@ l) -> p @@ (l + 1)) -> (p @@ 0) -> Vec k a -> p @@ k
+ Clash.Explicit.Prelude.Safe: dfold :: forall p k a. KnownNat k => Proxy (p :: TyFun Nat Type -> Type) -> (forall n. (n + 1) <= k => SNat n -> a -> (p @@ n) -> p @@ (n + 1)) -> (p @@ 0) -> Vec k a -> p @@ k
- Clash.Explicit.Prelude.Safe: dtfold :: forall p k a. KnownNat k => Proxy (p :: TyFun Nat Type -> Type) -> (a -> p @@ 0) -> (forall l. SNat l -> (p @@ l) -> (p @@ l) -> p @@ (l + 1)) -> Vec (2 ^ k) a -> p @@ k
+ Clash.Explicit.Prelude.Safe: dtfold :: forall p k a. KnownNat k => Proxy (p :: TyFun Nat Type -> Type) -> (a -> p @@ 0) -> (forall n. SNat n -> (p @@ n) -> (p @@ n) -> p @@ (n + 1)) -> Vec (2 ^ k) a -> p @@ k
- Clash.Explicit.Prelude.Safe: foldl :: (b -> a -> b) -> b -> Vec n a -> b
+ Clash.Explicit.Prelude.Safe: foldl :: forall b a n. (b -> a -> b) -> b -> Vec n a -> b
- Clash.Explicit.Prelude.Safe: interleave :: (KnownNat n, KnownNat d) => SNat d -> Vec (n * d) a -> Vec (d * n) a
+ Clash.Explicit.Prelude.Safe: interleave :: KnownNat n => SNat d -> Vec (n * d) a -> Vec (d * n) a
- Clash.Explicit.Prelude.Safe: merge :: KnownNat n => Vec n a -> Vec n a -> Vec (2 * n) a
+ Clash.Explicit.Prelude.Safe: merge :: Vec n a -> Vec n a -> Vec (2 * n) a
- Clash.Explicit.Prelude.Safe: scanl1 :: KnownNat n => (a -> a -> a) -> Vec (n + 1) a -> Vec (n + 1) a
+ Clash.Explicit.Prelude.Safe: scanl1 :: forall n a. (a -> a -> a) -> Vec (n + 1) a -> Vec (n + 1) a
- Clash.Explicit.Prelude.Safe: scanr1 :: KnownNat n => (a -> a -> a) -> Vec (n + 1) a -> Vec (n + 1) a
+ Clash.Explicit.Prelude.Safe: scanr1 :: forall n a. (a -> a -> a) -> Vec (n + 1) a -> Vec (n + 1) a
- Clash.Explicit.Prelude.Safe: select :: CmpNat (i + s) (s * n) ~ 'GT => SNat f -> SNat s -> SNat n -> Vec (f + i) a -> Vec n a
+ Clash.Explicit.Prelude.Safe: select :: forall i s n f a. ((s * n) + 1) <= (i + s) => SNat f -> SNat s -> SNat n -> Vec (f + i) a -> Vec n a
- Clash.Explicit.Prelude.Safe: selectI :: (CmpNat (i + s) (s * n) ~ 'GT, KnownNat n) => SNat f -> SNat s -> Vec (f + i) a -> Vec n a
+ Clash.Explicit.Prelude.Safe: selectI :: (1 <= s, ((s * n) + 1) <= (i + s), KnownNat n) => SNat f -> SNat s -> Vec (f + i) a -> Vec n a
- Clash.Explicit.Prelude.Safe: smap :: forall k a b. KnownNat k => (forall l. SNat l -> a -> b) -> Vec k a -> Vec k b
+ Clash.Explicit.Prelude.Safe: smap :: forall k a b. KnownNat k => (forall n. SNat n -> a -> b) -> Vec k a -> Vec k b
- Clash.Explicit.Prelude.Safe: vfold :: forall k a b. KnownNat k => (forall l. SNat l -> a -> Vec l b -> Vec (l + 1) b) -> Vec k a -> Vec k b
+ Clash.Explicit.Prelude.Safe: vfold :: forall k a b. KnownNat k => (forall n. SNat n -> a -> Vec n b -> Vec (n + 1) b) -> Vec k a -> Vec k b
- Clash.Explicit.Signal: [SDomainConfiguration] :: SSymbol dom -> SNat period -> SActiveEdge edge -> SResetKind reset -> SInitBehavior init -> SResetPolarity polarity -> SDomainConfiguration dom ('DomainConfiguration dom period edge reset init polarity)
+ Clash.Explicit.Signal: [SDomainConfiguration] :: 1 <= period => SSymbol dom -> SNat period -> SActiveEdge edge -> SResetKind reset -> SInitBehavior init -> SResetPolarity polarity -> SDomainConfiguration dom ('DomainConfiguration dom period edge reset init polarity)
- Clash.Explicit.Signal: infix 4 .>.
+ Clash.Explicit.Signal: infix 4 >.
- Clash.Intel.DDR: altddioIn :: forall fast fPeriod edge reset init polarity slow m deviceFamily. (HasCallStack, KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity), KnownConfiguration slow ('DomainConfiguration slow (2 * fPeriod) edge reset init polarity), KnownNat m) => SSymbol deviceFamily -> Clock slow -> Reset slow -> Enable slow -> Signal fast (BitVector m) -> Signal slow (BitVector m, BitVector m)
+ Clash.Intel.DDR: altddioIn :: forall deviceFamily a dom domDDR. HasCallStack => KnownDomain dom => KnownDomain domDDR => DomainPeriod dom ~ (2 * DomainPeriod domDDR) => DomainActiveEdge dom ~ 'Rising => BitPack a => SSymbol deviceFamily -> Clock dom -> Reset dom -> Enable dom -> Signal domDDR a -> Signal dom (a, a)
- Clash.Intel.DDR: altddioOut :: forall fast fPeriod edge reset init polarity slow m deviceFamily. (HasCallStack, KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity), KnownConfiguration slow ('DomainConfiguration slow (2 * fPeriod) edge reset init polarity), KnownNat m) => SSymbol deviceFamily -> Clock slow -> Reset slow -> Enable slow -> Signal slow (BitVector m, BitVector m) -> Signal fast (BitVector m)
+ Clash.Intel.DDR: altddioOut :: forall deviceFamily a dom domDDR. HasCallStack => KnownDomain dom => KnownDomain domDDR => DomainPeriod dom ~ (2 * DomainPeriod domDDR) => DomainActiveEdge dom ~ 'Rising => BitPack a => SSymbol deviceFamily -> Clock dom -> Reset dom -> Enable dom -> Signal dom (a, a) -> Signal domDDR a
- Clash.Prelude: (+>>) :: KnownNat n => a -> Vec n a -> Vec n a
+ Clash.Prelude: (+>>) :: forall n a. a -> Vec n a -> Vec n a
- Clash.Prelude: [ClearOnReset] :: ResetStrategy 'True
+ Clash.Prelude: [ClearOnReset] :: a -> ResetStrategy 'True a
- Clash.Prelude: [NoClearOnReset] :: ResetStrategy 'False
+ Clash.Prelude: [NoClearOnReset] :: ResetStrategy 'False a
- Clash.Prelude: [SDomainConfiguration] :: SSymbol dom -> SNat period -> SActiveEdge edge -> SResetKind reset -> SInitBehavior init -> SResetPolarity polarity -> SDomainConfiguration dom ('DomainConfiguration dom period edge reset init polarity)
+ Clash.Prelude: [SDomainConfiguration] :: 1 <= period => SSymbol dom -> SNat period -> SActiveEdge edge -> SResetKind reset -> SInitBehavior init -> SResetPolarity polarity -> SDomainConfiguration dom ('DomainConfiguration dom period edge reset init polarity)
- Clash.Prelude: blockRam1 :: forall n dom a r addr. (HasCallStack, HiddenClockResetEnable dom, NFDataX a, Enum addr, NFDataX addr, 1 <= n) => ResetStrategy r -> SNat n -> a -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
+ Clash.Prelude: blockRam1 :: forall n dom a r addr. (HasCallStack, HiddenClockResetEnable dom, NFDataX a, Enum addr, NFDataX addr) => ResetStrategy r () -> SNat n -> a -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
- Clash.Prelude: blockRamU :: forall n dom a r addr. (HasCallStack, HiddenClockResetEnable dom, NFDataX a, Enum addr, NFDataX addr, 1 <= n) => ResetStrategy r -> SNat n -> (Index n -> a) -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
+ Clash.Prelude: blockRamU :: forall n dom a r addr. (HasCallStack, HiddenClockResetEnable dom, NFDataX a, Enum addr, NFDataX addr) => ResetStrategy r (Index n -> a) -> SNat n -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
- Clash.Prelude: data ResetStrategy (r :: Bool)
+ Clash.Prelude: data ResetStrategy (r :: Bool) a
- Clash.Prelude: dfold :: forall p k a. KnownNat k => Proxy (p :: TyFun Nat Type -> Type) -> (forall l. SNat l -> a -> (p @@ l) -> p @@ (l + 1)) -> (p @@ 0) -> Vec k a -> p @@ k
+ Clash.Prelude: dfold :: forall p k a. KnownNat k => Proxy (p :: TyFun Nat Type -> Type) -> (forall n. (n + 1) <= k => SNat n -> a -> (p @@ n) -> p @@ (n + 1)) -> (p @@ 0) -> Vec k a -> p @@ k
- Clash.Prelude: dtfold :: forall p k a. KnownNat k => Proxy (p :: TyFun Nat Type -> Type) -> (a -> p @@ 0) -> (forall l. SNat l -> (p @@ l) -> (p @@ l) -> p @@ (l + 1)) -> Vec (2 ^ k) a -> p @@ k
+ Clash.Prelude: dtfold :: forall p k a. KnownNat k => Proxy (p :: TyFun Nat Type -> Type) -> (a -> p @@ 0) -> (forall n. SNat n -> (p @@ n) -> (p @@ n) -> p @@ (n + 1)) -> Vec (2 ^ k) a -> p @@ k
- Clash.Prelude: foldl :: (b -> a -> b) -> b -> Vec n a -> b
+ Clash.Prelude: foldl :: forall b a n. (b -> a -> b) -> b -> Vec n a -> b
- Clash.Prelude: infixr 2 .||.
+ Clash.Prelude: infixr 2 ||.
- Clash.Prelude: infixr 3 `regMaybe`
+ Clash.Prelude: infixr 3 .&&
- Clash.Prelude: interleave :: (KnownNat n, KnownNat d) => SNat d -> Vec (n * d) a -> Vec (d * n) a
+ Clash.Prelude: interleave :: KnownNat n => SNat d -> Vec (n * d) a -> Vec (d * n) a
- Clash.Prelude: merge :: KnownNat n => Vec n a -> Vec n a -> Vec (2 * n) a
+ Clash.Prelude: merge :: Vec n a -> Vec n a -> Vec (2 * n) a
- Clash.Prelude: scanl1 :: KnownNat n => (a -> a -> a) -> Vec (n + 1) a -> Vec (n + 1) a
+ Clash.Prelude: scanl1 :: forall n a. (a -> a -> a) -> Vec (n + 1) a -> Vec (n + 1) a
- Clash.Prelude: scanr1 :: KnownNat n => (a -> a -> a) -> Vec (n + 1) a -> Vec (n + 1) a
+ Clash.Prelude: scanr1 :: forall n a. (a -> a -> a) -> Vec (n + 1) a -> Vec (n + 1) a
- Clash.Prelude: select :: CmpNat (i + s) (s * n) ~ 'GT => SNat f -> SNat s -> SNat n -> Vec (f + i) a -> Vec n a
+ Clash.Prelude: select :: forall i s n f a. ((s * n) + 1) <= (i + s) => SNat f -> SNat s -> SNat n -> Vec (f + i) a -> Vec n a
- Clash.Prelude: selectI :: (CmpNat (i + s) (s * n) ~ 'GT, KnownNat n) => SNat f -> SNat s -> Vec (f + i) a -> Vec n a
+ Clash.Prelude: selectI :: (1 <= s, ((s * n) + 1) <= (i + s), KnownNat n) => SNat f -> SNat s -> Vec (f + i) a -> Vec n a
- Clash.Prelude: smap :: forall k a b. KnownNat k => (forall l. SNat l -> a -> b) -> Vec k a -> Vec k b
+ Clash.Prelude: smap :: forall k a b. KnownNat k => (forall n. SNat n -> a -> b) -> Vec k a -> Vec k b
- Clash.Prelude: vfold :: forall k a b. KnownNat k => (forall l. SNat l -> a -> Vec l b -> Vec (l + 1) b) -> Vec k a -> Vec k b
+ Clash.Prelude: vfold :: forall k a b. KnownNat k => (forall n. SNat n -> a -> Vec n b -> Vec (n + 1) b) -> Vec k a -> Vec k b
- Clash.Prelude.BlockRam: [ClearOnReset] :: ResetStrategy 'True
+ Clash.Prelude.BlockRam: [ClearOnReset] :: a -> ResetStrategy 'True a
- Clash.Prelude.BlockRam: [NoClearOnReset] :: ResetStrategy 'False
+ Clash.Prelude.BlockRam: [NoClearOnReset] :: ResetStrategy 'False a
- Clash.Prelude.BlockRam: blockRam1 :: forall n dom a r addr. (HasCallStack, HiddenClockResetEnable dom, NFDataX a, Enum addr, NFDataX addr, 1 <= n) => ResetStrategy r -> SNat n -> a -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
+ Clash.Prelude.BlockRam: blockRam1 :: forall n dom a r addr. (HasCallStack, HiddenClockResetEnable dom, NFDataX a, Enum addr, NFDataX addr) => ResetStrategy r () -> SNat n -> a -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
- Clash.Prelude.BlockRam: blockRamU :: forall n dom a r addr. (HasCallStack, HiddenClockResetEnable dom, NFDataX a, Enum addr, NFDataX addr, 1 <= n) => ResetStrategy r -> SNat n -> (Index n -> a) -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
+ Clash.Prelude.BlockRam: blockRamU :: forall n dom a r addr. (HasCallStack, HiddenClockResetEnable dom, NFDataX a, Enum addr, NFDataX addr) => ResetStrategy r (Index n -> a) -> SNat n -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
- Clash.Prelude.BlockRam: data ResetStrategy (r :: Bool)
+ Clash.Prelude.BlockRam: data ResetStrategy (r :: Bool) a
- Clash.Prelude.Safe: (+>>) :: KnownNat n => a -> Vec n a -> Vec n a
+ Clash.Prelude.Safe: (+>>) :: forall n a. a -> Vec n a -> Vec n a
- Clash.Prelude.Safe: dfold :: forall p k a. KnownNat k => Proxy (p :: TyFun Nat Type -> Type) -> (forall l. SNat l -> a -> (p @@ l) -> p @@ (l + 1)) -> (p @@ 0) -> Vec k a -> p @@ k
+ Clash.Prelude.Safe: dfold :: forall p k a. KnownNat k => Proxy (p :: TyFun Nat Type -> Type) -> (forall n. (n + 1) <= k => SNat n -> a -> (p @@ n) -> p @@ (n + 1)) -> (p @@ 0) -> Vec k a -> p @@ k
- Clash.Prelude.Safe: dtfold :: forall p k a. KnownNat k => Proxy (p :: TyFun Nat Type -> Type) -> (a -> p @@ 0) -> (forall l. SNat l -> (p @@ l) -> (p @@ l) -> p @@ (l + 1)) -> Vec (2 ^ k) a -> p @@ k
+ Clash.Prelude.Safe: dtfold :: forall p k a. KnownNat k => Proxy (p :: TyFun Nat Type -> Type) -> (a -> p @@ 0) -> (forall n. SNat n -> (p @@ n) -> (p @@ n) -> p @@ (n + 1)) -> Vec (2 ^ k) a -> p @@ k
- Clash.Prelude.Safe: foldl :: (b -> a -> b) -> b -> Vec n a -> b
+ Clash.Prelude.Safe: foldl :: forall b a n. (b -> a -> b) -> b -> Vec n a -> b
- Clash.Prelude.Safe: interleave :: (KnownNat n, KnownNat d) => SNat d -> Vec (n * d) a -> Vec (d * n) a
+ Clash.Prelude.Safe: interleave :: KnownNat n => SNat d -> Vec (n * d) a -> Vec (d * n) a
- Clash.Prelude.Safe: merge :: KnownNat n => Vec n a -> Vec n a -> Vec (2 * n) a
+ Clash.Prelude.Safe: merge :: Vec n a -> Vec n a -> Vec (2 * n) a
- Clash.Prelude.Safe: scanl1 :: KnownNat n => (a -> a -> a) -> Vec (n + 1) a -> Vec (n + 1) a
+ Clash.Prelude.Safe: scanl1 :: forall n a. (a -> a -> a) -> Vec (n + 1) a -> Vec (n + 1) a
- Clash.Prelude.Safe: scanr1 :: KnownNat n => (a -> a -> a) -> Vec (n + 1) a -> Vec (n + 1) a
+ Clash.Prelude.Safe: scanr1 :: forall n a. (a -> a -> a) -> Vec (n + 1) a -> Vec (n + 1) a
- Clash.Prelude.Safe: select :: CmpNat (i + s) (s * n) ~ 'GT => SNat f -> SNat s -> SNat n -> Vec (f + i) a -> Vec n a
+ Clash.Prelude.Safe: select :: forall i s n f a. ((s * n) + 1) <= (i + s) => SNat f -> SNat s -> SNat n -> Vec (f + i) a -> Vec n a
- Clash.Prelude.Safe: selectI :: (CmpNat (i + s) (s * n) ~ 'GT, KnownNat n) => SNat f -> SNat s -> Vec (f + i) a -> Vec n a
+ Clash.Prelude.Safe: selectI :: (1 <= s, ((s * n) + 1) <= (i + s), KnownNat n) => SNat f -> SNat s -> Vec (f + i) a -> Vec n a
- Clash.Prelude.Safe: smap :: forall k a b. KnownNat k => (forall l. SNat l -> a -> b) -> Vec k a -> Vec k b
+ Clash.Prelude.Safe: smap :: forall k a b. KnownNat k => (forall n. SNat n -> a -> b) -> Vec k a -> Vec k b
- Clash.Prelude.Safe: vfold :: forall k a b. KnownNat k => (forall l. SNat l -> a -> Vec l b -> Vec (l + 1) b) -> Vec k a -> Vec k b
+ Clash.Prelude.Safe: vfold :: forall k a b. KnownNat k => (forall n. SNat n -> a -> Vec n b -> Vec (n + 1) b) -> Vec k a -> Vec k b
- Clash.Promoted.Nat: toBNat :: SNat n -> BNat n
+ Clash.Promoted.Nat: toBNat :: forall n. SNat n -> BNat n
- Clash.Signal: [SDomainConfiguration] :: SSymbol dom -> SNat period -> SActiveEdge edge -> SResetKind reset -> SInitBehavior init -> SResetPolarity polarity -> SDomainConfiguration dom ('DomainConfiguration dom period edge reset init polarity)
+ Clash.Signal: [SDomainConfiguration] :: 1 <= period => SSymbol dom -> SNat period -> SActiveEdge edge -> SResetKind reset -> SInitBehavior init -> SResetPolarity polarity -> SDomainConfiguration dom ('DomainConfiguration dom period edge reset init polarity)
- Clash.Signal: infix 4 .>.
+ Clash.Signal: infix 4 >.
- Clash.Signal: infixr 2 .||.
+ Clash.Signal: infixr 2 ||.
- Clash.Signal: infixr 3 .&&.
+ Clash.Signal: infixr 3 .&&
- Clash.Signal.Internal: [SDomainConfiguration] :: SSymbol dom -> SNat period -> SActiveEdge edge -> SResetKind reset -> SInitBehavior init -> SResetPolarity polarity -> SDomainConfiguration dom ('DomainConfiguration dom period edge reset init polarity)
+ Clash.Signal.Internal: [SDomainConfiguration] :: 1 <= period => SSymbol dom -> SNat period -> SActiveEdge edge -> SResetKind reset -> SInitBehavior init -> SResetPolarity polarity -> SDomainConfiguration dom ('DomainConfiguration dom period edge reset init polarity)
- Clash.Signal.Internal: infix 4 .>.
+ Clash.Signal.Internal: infix 4 >.
- Clash.Signal.Internal: infixr 2 .||.
+ Clash.Signal.Internal: infixr 2 ||.
- Clash.Signal.Internal: infixr 3 .&&.
+ Clash.Signal.Internal: infixr 3 .&&
- Clash.Sized.Internal.Index: pack# :: Index n -> BitVector (CLog 2 n)
+ Clash.Sized.Internal.Index: pack# :: Index n -> BitVector (CLogWZ 2 n 0)
- Clash.Sized.Internal.Index: size# :: (KnownNat n, 1 <= n) => Index n -> Int
+ Clash.Sized.Internal.Index: size# :: KnownNat n => Index n -> Int
- Clash.Sized.Internal.Index: unpack# :: (KnownNat n, 1 <= n) => BitVector (CLog 2 n) -> Index n
+ Clash.Sized.Internal.Index: unpack# :: KnownNat n => BitVector (CLogWZ 2 n 0) -> Index n
- Clash.Sized.Vector: (+>>) :: KnownNat n => a -> Vec n a -> Vec n a
+ Clash.Sized.Vector: (+>>) :: forall n a. a -> Vec n a -> Vec n a
- Clash.Sized.Vector: dfold :: forall p k a. KnownNat k => Proxy (p :: TyFun Nat Type -> Type) -> (forall l. SNat l -> a -> (p @@ l) -> p @@ (l + 1)) -> (p @@ 0) -> Vec k a -> p @@ k
+ Clash.Sized.Vector: dfold :: forall p k a. KnownNat k => Proxy (p :: TyFun Nat Type -> Type) -> (forall n. (n + 1) <= k => SNat n -> a -> (p @@ n) -> p @@ (n + 1)) -> (p @@ 0) -> Vec k a -> p @@ k
- Clash.Sized.Vector: dtfold :: forall p k a. KnownNat k => Proxy (p :: TyFun Nat Type -> Type) -> (a -> p @@ 0) -> (forall l. SNat l -> (p @@ l) -> (p @@ l) -> p @@ (l + 1)) -> Vec (2 ^ k) a -> p @@ k
+ Clash.Sized.Vector: dtfold :: forall p k a. KnownNat k => Proxy (p :: TyFun Nat Type -> Type) -> (a -> p @@ 0) -> (forall n. SNat n -> (p @@ n) -> (p @@ n) -> p @@ (n + 1)) -> Vec (2 ^ k) a -> p @@ k
- Clash.Sized.Vector: foldl :: (b -> a -> b) -> b -> Vec n a -> b
+ Clash.Sized.Vector: foldl :: forall b a n. (b -> a -> b) -> b -> Vec n a -> b
- Clash.Sized.Vector: interleave :: (KnownNat n, KnownNat d) => SNat d -> Vec (n * d) a -> Vec (d * n) a
+ Clash.Sized.Vector: interleave :: KnownNat n => SNat d -> Vec (n * d) a -> Vec (d * n) a
- Clash.Sized.Vector: merge :: KnownNat n => Vec n a -> Vec n a -> Vec (2 * n) a
+ Clash.Sized.Vector: merge :: Vec n a -> Vec n a -> Vec (2 * n) a
- Clash.Sized.Vector: scanl1 :: KnownNat n => (a -> a -> a) -> Vec (n + 1) a -> Vec (n + 1) a
+ Clash.Sized.Vector: scanl1 :: forall n a. (a -> a -> a) -> Vec (n + 1) a -> Vec (n + 1) a
- Clash.Sized.Vector: scanr1 :: KnownNat n => (a -> a -> a) -> Vec (n + 1) a -> Vec (n + 1) a
+ Clash.Sized.Vector: scanr1 :: forall n a. (a -> a -> a) -> Vec (n + 1) a -> Vec (n + 1) a
- Clash.Sized.Vector: select :: CmpNat (i + s) (s * n) ~ 'GT => SNat f -> SNat s -> SNat n -> Vec (f + i) a -> Vec n a
+ Clash.Sized.Vector: select :: forall i s n f a. ((s * n) + 1) <= (i + s) => SNat f -> SNat s -> SNat n -> Vec (f + i) a -> Vec n a
- Clash.Sized.Vector: selectI :: (CmpNat (i + s) (s * n) ~ 'GT, KnownNat n) => SNat f -> SNat s -> Vec (f + i) a -> Vec n a
+ Clash.Sized.Vector: selectI :: (1 <= s, ((s * n) + 1) <= (i + s), KnownNat n) => SNat f -> SNat s -> Vec (f + i) a -> Vec n a
- Clash.Sized.Vector: smap :: forall k a b. KnownNat k => (forall l. SNat l -> a -> b) -> Vec k a -> Vec k b
+ Clash.Sized.Vector: smap :: forall k a b. KnownNat k => (forall n. SNat n -> a -> b) -> Vec k a -> Vec k b
- Clash.Sized.Vector: vfold :: forall k a b. KnownNat k => (forall l. SNat l -> a -> Vec l b -> Vec (l + 1) b) -> Vec k a -> Vec k b
+ Clash.Sized.Vector: vfold :: forall k a b. KnownNat k => (forall n. SNat n -> a -> Vec n b -> Vec (n + 1) b) -> Vec k a -> Vec k b
- Clash.Xilinx.DDR: iddr :: forall fast fPeriod edge reset init polarity slow m. (HasCallStack, KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity), KnownConfiguration slow ('DomainConfiguration slow (2 * fPeriod) edge reset init polarity), KnownNat m) => Clock slow -> Reset slow -> Enable slow -> Signal fast (BitVector m) -> Signal slow (BitVector m, BitVector m)
+ Clash.Xilinx.DDR: iddr :: forall a dom domDDR. HasCallStack => KnownDomain dom => KnownDomain domDDR => DomainPeriod dom ~ (2 * DomainPeriod domDDR) => DomainActiveEdge dom ~ 'Rising => BitPack a => Clock dom -> Reset dom -> Enable dom -> Signal domDDR a -> Signal dom (a, a)
- Clash.Xilinx.DDR: oddr :: forall fast fPeriod edge reset init polarity slow m. (KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity), KnownConfiguration slow ('DomainConfiguration slow (2 * fPeriod) edge reset init polarity), KnownNat m) => Clock slow -> Reset slow -> Enable slow -> Signal slow (BitVector m, BitVector m) -> Signal fast (BitVector m)
+ Clash.Xilinx.DDR: oddr :: forall a dom domDDR. HasCallStack => KnownDomain dom => KnownDomain domDDR => DomainPeriod dom ~ (2 * DomainPeriod domDDR) => DomainActiveEdge dom ~ 'Rising => BitPack a => Clock dom -> Reset dom -> Enable dom -> Signal dom (a, a) -> Signal domDDR a
Files
- CHANGELOG.md +101/−1
- LICENSE +1/−1
- README.md +2/−2
- clash-prelude.cabal +36/−44
- src/Clash/Annotations/BitRepresentation.hs +11/−2
- src/Clash/Annotations/BitRepresentation/Deriving.hs +7/−17
- src/Clash/Annotations/BitRepresentation/Internal.hs +14/−3
- src/Clash/Annotations/SynthesisAttributes.hs +3/−4
- src/Clash/Annotations/TH.hs +1/−33
- src/Clash/Annotations/TopEntity.hs +0/−4
- src/Clash/CPP.hs +0/−4
- src/Clash/Class/AutoReg/Internal.hs +0/−10
- src/Clash/Class/BitPack/Internal.hs +144/−37
- src/Clash/Class/Counter/Internal.hs +33/−0
- src/Clash/Class/Counter/TH.hs +0/−4
- src/Clash/Class/Exp.hs +3/−6
- src/Clash/Class/HasDomain.hs +3/−1
- src/Clash/Class/HasDomain/Common.hs +1/−2
- src/Clash/Class/HasDomain/HasSingleDomain.hs +3/−4
- src/Clash/Class/HasDomain/HasSpecificDomain.hs +3/−3
- src/Clash/Class/NumConvert.hs +44/−0
- src/Clash/Class/NumConvert/Internal/Canonical.hs +48/−0
- src/Clash/Class/NumConvert/Internal/MaybeNumConvert.hs +161/−0
- src/Clash/Class/NumConvert/Internal/NumConvert.hs +228/−0
- src/Clash/Class/Resize.hs +45/−13
- src/Clash/Clocks/Internal.hs +1/−1
- src/Clash/Explicit/BlockRam.hs +36/−36
- src/Clash/Explicit/BlockRam/Blob.hs +1/−2
- src/Clash/Explicit/BlockRam/File.hs +2/−4
- src/Clash/Explicit/BlockRam/Model.hs +0/−3
- src/Clash/Explicit/DDR.hs +182/−58
- src/Clash/Explicit/Prelude.hs +9/−5
- src/Clash/Explicit/Prelude/Safe.hs +0/−2
- src/Clash/Explicit/RAM.hs +1/−2
- src/Clash/Explicit/ROM.hs +1/−2
- src/Clash/Explicit/ROM/Blob.hs +1/−2
- src/Clash/Explicit/ROM/File.hs +1/−2
- src/Clash/Explicit/Signal.hs +50/−13
- src/Clash/Explicit/Signal/Delayed.hs +1/−1
- src/Clash/Explicit/SimIO.hs +20/−82
- src/Clash/Explicit/Synchronizer.hs +0/−1
- src/Clash/Explicit/Testbench.hs +5/−10
- src/Clash/Explicit/Verification.hs +1/−2
- src/Clash/Intel/ClockGen.hs +4/−70
- src/Clash/Intel/DDR.hs +63/−64
- src/Clash/Magic.hs +12/−22
- src/Clash/NamedTypes.hs +0/−1
- src/Clash/Prelude.hs +12/−15
- src/Clash/Prelude/BlockRam.hs +9/−40
- src/Clash/Prelude/DataFlow.hs +0/−574
- src/Clash/Prelude/ROM.hs +1/−2
- src/Clash/Prelude/ROM/Blob.hs +1/−2
- src/Clash/Prelude/ROM/File.hs +1/−2
- src/Clash/Prelude/Safe.hs +3/−4
- src/Clash/Prelude/Synchronizer.hs +0/−88
- src/Clash/Promoted/Nat.hs +41/−34
- src/Clash/Promoted/Nat/Unsafe.hs +1/−2
- src/Clash/Promoted/Symbol.hs +0/−4
- src/Clash/Signal.hs +70/−696
- src/Clash/Signal/BiSignal.hs +7/−8
- src/Clash/Signal/Bundle.hs +1/−2
- src/Clash/Signal/Bundle/Internal.hs +0/−8
- src/Clash/Signal/Delayed.hs +1/−12
- src/Clash/Signal/Delayed/Bundle.hs +0/−4
- src/Clash/Signal/Delayed/Internal.hs +3/−3
- src/Clash/Signal/Internal.hs +305/−57
- src/Clash/Signal/Internal/Ambiguous.hs +5/−10
- src/Clash/Signal/Trace.hs +7/−14
- src/Clash/Sized/Fixed.hs +2/−18
- src/Clash/Sized/Index.hs +1/−1
- src/Clash/Sized/Internal/BitVector.hs +80/−303
- src/Clash/Sized/Internal/Index.hs +76/−107
- src/Clash/Sized/Internal/Mod.hs +0/−162
- src/Clash/Sized/Internal/Signed.hs +48/−100
- src/Clash/Sized/Internal/Unsigned.hs +47/−221
- src/Clash/Sized/RTree.hs +10/−43
- src/Clash/Sized/Vector.hs +171/−204
- src/Clash/Sized/Vector/ToTuple.hs +0/−17
- src/Clash/Sized/Vector/ToTuple/TH.hs +1/−15
- src/Clash/Tutorial.hs +20/−2500
- src/Clash/XException.hs +13/−24
- src/Clash/XException.hs-boot +3/−2
- src/Clash/XException/MaybeX.hs +0/−3
- src/Clash/Xilinx/ClockGen.hs +2/−4
- src/Clash/Xilinx/DDR.hs +64/−63
- src/Language/Haskell/TH/Compat.hs +0/−13
- tests/Clash/Tests/BitVector.hs +21/−4
- tests/Clash/Tests/BlockRam.hs +1/−1
- tests/Clash/Tests/Index.hs +25/−0
- tests/Clash/Tests/Laws/Num.hs +51/−0
- tests/Clash/Tests/Laws/SaturatingNum.hs +10/−1
- tests/Clash/Tests/MaybeNumConvert.hs +350/−0
- tests/Clash/Tests/MaybeX.hs +0/−3
- tests/Clash/Tests/NumConvert.hs +403/−0
- tests/Clash/Tests/Ram.hs +1/−1
- tests/Clash/Tests/Reset.hs +0/−1
- tests/Clash/Tests/Resize.hs +170/−8
- tests/Clash/Tests/Signal.hs +34/−140
- tests/Clash/Tests/Signed.hs +22/−0
- tests/Clash/Tests/TopEntityGeneration.hs +0/−14
- tests/Clash/Tests/Unsigned.hs +16/−0
- tests/doctests.hs +2/−1
- tests/unittests.hs +9/−1
CHANGELOG.md view
@@ -1,5 +1,105 @@ # Changelog for the Clash project +## 1.10.0 *Apr 23rd, 2026*++Release highlight:+* `Clash.Class.NumConvert`: Utilities for safely converting between various Clash number types [#2915](https://github.com/clash-lang/clash-compiler/pull/2915)++Added:+* Added GHC 9.12 support+* `Clash.Class.NumConvert`: Utilities for safely converting between various Clash number types [#2915](https://github.com/clash-lang/clash-compiler/pull/2915)+* Add `Clash.XException.ShowX` instance for `Foreign.C.Types.CUShort`. [#2397](https://github.com/clash-lang/clash-compiler/pull/2397)+* Introduced various new types to `Clash.Signal` to more easily represent time and its relation to your clock domain. New types: `Seconds`, `Milliseconds`, `Microseconds`, `Nanoseconds`, `Picoseconds`, `DomainToHz`, `HzToPeriod`, `PeriodToHz`, `PeriodToCycles`, `ClockDivider`. [#2734](https://github.com/clash-lang/clash-compiler/pull/2734)+* `Distributive` and `Representable` instances for `Vec`+* Resize functions `maybeResize` and `maybeTruncateB` to `Clash.Class.Resize`. Can be used to resize without loss of information. [#2779](https://github.com/clash-lang/clash-compiler/issues/2779)+* Alongside the existing Eq-like and Ord-like signal operators like `.==.` and `.<=.` etc., there are now new functions for comparing with constants: `.==`, `==.`, `./=`, `/=.`, `.<=`, `<=.`, `.>=`, `>=.`, `.>`, `>.`, `.<`, `<.`, `.&&`, `&&.`, `.||`, `||.`. These are useful for comparing signals with constants in a more readable way. For example, `a .==. pure True` can now be replaced with `a .== True`. [#2545](https://github.com/clash-lang/clash-compiler/pull/2545)+* instance `HasField f (Signal dom r) (Signal dom a)`. This means record dot accesses will be passed to the underlying type. For example, this will work:++ ```haskell+ data MyRecord = MyRecord { myField :: Int }++ a :: Signal dom MyRecord+ a = pure (MyRecord 3)++ b :: Signal dom Int+ b = a.myField+ ```+* `BitPack` instance for `Data.Proxy.Proxy`+* `apEn`, which is a `mux` that optionally applies an update function to a value. [#3029](https://github.com/clash-lang/clash-compiler/pull/3029)+* `regEnN`, which is a chain of `regEn`s. [#3029](https://github.com/clash-lang/clash-compiler/pull/3029)+* `Index 0` instances for `BitPack`, `Bits`, `Counter`, `FiniteBits`, `Parity`, and `SaturatingNum`. [#2784](https://github.com/clash-lang/clash-compiler/pull/2784)+* Zero-sized block RAM implementations for `blockRam1` and `blockRamU`. [#2784](https://github.com/clash-lang/clash-compiler/pull/2784)+* `Counter a => Counter (Vec 0 a)` instance. [#2784](https://github.com/clash-lang/clash-compiler/pull/2784)+* `SaturatingNum` and `Bounded` instances for `Signal dom a`. The `sat` family (`satAdd`, `satSucc`, ...) can now be used on `Signal`s and `{min,max}Bound` can be used to construct them [#2931](https://github.com/clash-lang/clash-compiler/issues/2931)+* `-fclash-no-concurrent-topentity-compilation` flag to disable concurrent compilation of top entities. This is mostly useful to get a consistent debug output.+* `SomeBoundedSNat` and Hedgehog generators [#3183](https://github.com/clash-lang/clash-compiler/pull/3183)+* `Eq`, `NFData`, `ShowX` and `BitPack` instances for `RamOp`.+* `smapWithBounds` extending `smap` via offering a proof witness for the upper bound of the vector size to the mapping function. [#2686](https://github.com/clash-lang/clash-compiler/pull/2686)+* The function `Clash.Explicit.DDR.ddrForwardClock`, which uses a DDR output primitive to forward a clock signal to a DDR-capable output pin. [#2876](https://github.com/clash-lang/clash-compiler/pull/2876)++Removed:+* Support for GHC versions 9.4 and older+* Newer Verilators (> v5) can deal with delay statements, hence removing the need for Clash specific workarounds. If you relied on Clash-generated Verilator shims, consider using `verilator --build --binary` instead.+* Experimental feature "multiple hidden domains" [#2750](https://github.com/clash-lang/clash-compiler/pull/2750)+* The deprecated module `Clash.Prelude.DataFlow` was removed. The `clash-protocols` package provides dataflow-based protocols and circuits. [#3181](https://github.com/clash-lang/clash-compiler/pull/3181)+* The deprecated functions `altpll` and `alteraPll` were removed from the `Clash.Intel.ClockGen` module. Clash 1.8 introduced the new functions `altpllSync`, `alteraPllSync`, `unsafeAltpll` and `unsafeAlteraPll`. A name for the IP instantiation, handled by the _name_ argument to `altpll` and `alteraPll`, can be provided with the `Clash.Magic.setName` function. [#3181](https://github.com/clash-lang/clash-compiler/pull/3181)++Changed:+* `dfold` now offers a proof witness for the upper bound of the vector size to the folding function. Note that this change may require additional type annotations, as solutions working in the past may complain with an untouchable type error now. [#2686](https://github.com/clash-lang/clash-compiler/pull/2686)+* You can now only create an `SDomainConfiguration` when the `period` of the domain is at least `1`. Pattern matching on an `SDomainConfiguration` bring the `1 <= period` into scope. This in turns enables the following code to typecheck:+ ```+ import Clash.Prelude+ import Data.Proxy++ f ::+ forall dom .+ KnownDomain dom =>+ Proxy dom ->+ SNat (PeriodToCycles dom (Milliseconds 1))+ f Proxy = case knownDomain @dom of+ SDomainConfiguration {} -> SNat+ ```+ where the `DivRU` in+ ```+ type PeriodToCycles (dom :: Domain) (period :: Nat) = period `DivRU` DomainPeriod dom+ ```+ requires that the `DomainPeriod dom` is at least `1`. [#2740](https://github.com/clash-lang/clash-compiler/pull/2740)+* `select` and `selectI` now use `<=` constraints instead of `CmpNat`. [#2873](https://github.com/clash-lang/clash-compiler/pull/2873)+* `ResetStrategy` now contains the reset function, to avoid dummy arguments on `NoClearOnReset` [#2849](https://github.com/clash-lang/clash-compiler/pull/2849)+* `Clash.Explicit.DDR`, `Clash.Intel.DDR` and `Clash.Xilinx.DDR`: [#2833](https://github.com/clash-lang/clash-compiler/pull/2833)+ - The constraints for the functions have been rewritten to use `DomainPeriod`, which makes them more readable and relaxes unnecessary constraints on the virtual DDR domain. The type-level variables for the domains have been renamed. `dom` is a real domain, `domDDR` is the virtual DDR domain.+ - The Xilinx and Intel primitives only support domains where the rising edge is the active edge. This is now enforced at the type level by adding a constraint.+ - The Xilinx and Intel primitives now directly support any data type that has a `BitPack` instance.+* Order of type arguments for functions in `clash-prelude-hedgehog` now follows _size_, _domain_, _monad_. [#2880](https://github.com/clash-lang/clash-compiler/pull/2880)+* The Clash Prelude now exports the `Default` class from the package `data-default` instead of from the now superseded `data-default-class`. If you import the `Default` class name or the `def` function from the `data-default-class` package _older than version 0.2_, or one of your dependencies does, you might get a bewildering error message. You might get the error "No instance for (Default T)" even though there appears to be such an instance. The best solution is to make sure all your packages and dependencies use the `data-default` package and not the `data-default-class` package. The next most obvious solution is to make sure `data-default-class` is of version 0.2 or higher, for instance by depending on it in your own package. If this creates a dependency conflict, another solution is to import the correct module. `Default` and `def` from `Clash.Prelude` or `Data.Default` are for the new `data-default` package. `Data.Default.Class` is for the `data-default-class` package. There are situations where this will still not be enough, but luckily the `Default` class is not used all that much. [#2891](https://github.com/clash-lang/clash-compiler/pull/2891)+* Changed implementation of `(+>>)` to no longer require `KnownNat`+* The `clash-prelude` package now uses `PolyKinds` by default, meaning all its type class instances are now more general than before. As an example, without `PolyKinds`, `BitPack (Proxy a)` would only be defined when `a :: Type`, with the extension it would be defined for any `a :: k`. After this change, some instances in user code might now overlap. [#2994](https://github.com/clash-lang/clash-compiler/pull/2994)+* When generating (System)Verilog, Clash now resets the default net type from none to the verilog default after the generated module. [#3005](https://github.com/clash-lang/clash-compiler/pull/3005)+* The content from the `Clash.Tutorial` module and from https://clash-lang.readthedocs.io/ has been split and moved to two new locations.+ 1. The actual tutorial parts has been moved to: https://docs.clash-lang.org/tutorial/+ 2. Parts that fit better in the clash compiler user guide have been moved to: https://docs.clash-lang.org/compiler-user-guide/++ Moving the documentation to these locations makes it easier to update their content as it is no longer needed to release a new version of the `clash-prelude` package for the publication of this content.+* Vector functions in Verilog now have indices consistent with the Vec inputs/outputs (before they were reversed). This is convenient when writing design constraints, which can now be referenced consistently like `imap[0],imap[1],..`. See [#3088](https://github.com/clash-lang/clash-compiler/issues/3088).++Fixed:+* Clash no longer gives `Dubious primitive instantiation warning` when using `unpack` [#2386](https://github.com/clash-lang/clash-compiler/issues/2386).+* Clash now generates more intuitive names for specialized binders. See [#2508](https://github.com/clash-lang/clash-compiler/issues/2508).+* `foldl` on `Vec` is now strict. See [this GitHub discussion](https://github.com/hasura/graphql-engine/pull/2933#discussion_r328821960) and [this blog post](https://well-typed.com/blog/90/) for more information. [#2482](https://github.com/clash-lang/clash-compiler/issues/2482)+* Type families that appear in GHC core types are now normalized before being translated into their Clash core equivalent. See [#3063](https://github.com/clash-lang/clash-compiler/issues/3063).+* Added an evaluator rule for `bigNatEq#` with compile-time constant arguments [#3084](https://github.com/clash-lang/clash-compiler/issues/3084)+* Reduce constants to NF before specialization [#3129](https://github.com/clash-lang/clash-compiler/issues/3129)+* `rotateL` and `rotateR` no longer error when used on `BitVector 0` [#2980](https://github.com/clash-lang/clash-compiler/issues/2980)+* Behavior of `shiftR` is now documented for `Unsigned`, `BitVector`, `Index`, and `Signed` [#2959](https://github.com/clash-lang/clash-compiler/issues/2959)+* Clash will no longer error if it finds the same data file more than once due to duplicate `-i` flags [#3141](https://github.com/clash-lang/clash-compiler/issues/3141)+* Higher order blackboxes not propagating usage metadata for generated results [#3147](https://github.com/clash-lang/clash-compiler/issues/3147)+* Run `caseCon` after post-normalization `inlineCleanup` [#3159](https://github.com/clash-lang/clash-compiler/issues/3159)+* Failure to generate binder assignments in very specific cases [#3185](https://github.com/clash-lang/clash-compiler/issues/3185)+* Clash won't create (invalid) netlist cases on Integer and Natural constructors anymore [#3157](https://github.com/clash-lang/clash-compiler/issues/3157)+* Post-normalization flattening could leave a `Just` constructor as the scrutinee of a `case` after simplifying tuple projections [#3204](https://github.com/clash-lang/clash-compiler/issues/3204)+* Clash no longer crashes on false positive free variable introduction in `reduceConst` and `constantSpec`. Fixes [#3206](https://github.com/clash-lang/clash-compiler/issues/3206).+* `negate` for `Num Bit` is now defined as the additive inverse, i.e., `negate = id`. [#2999](https://github.com/clash-lang/clash-compiler/issues/2999)+ ## 1.8.5 *Mar 24th, 2026* Added:@@ -358,7 +458,7 @@ * Don't overflow the range of VHDL's natural type in shift/rotate, leading to simulation issues. Shift now saturates to a 31-bit shift amount. For rotate, in simulation only, the rotate amount is modulo the word width of the rotated value [#1874](https://github.com/clash-lang/clash-compiler/pull/1874) * `shiftL` for Clash datatypes does not cause a crash anymore when running Clash code with a really large shift amount [#1874](https://github.com/clash-lang/clash-compiler/pull/1874) * VHDL generated for `Signed.fromInteger` now truncates, like the Clash simulation, when the result is smaller than the argument [#1874](https://github.com/clash-lang/clash-compiler/pull/1874)- * Clash now preserves boolean combinatorial logic better when generating HDL [#1881](https://github.com/clash-lang/clash-compiler/issues/1881)+ * Clash now preserves boolean combinational logic better when generating HDL [#1881](https://github.com/clash-lang/clash-compiler/issues/1881) * `valid` field of `TemplateFunction` is now checked for includes [#1945](https://github.com/clash-lang/clash-compiler/issues/1945) * Clash now generates clock generators that ensure that the amount of time between simulation start and the first active edge of the clock is equal to (/or longer than/) the period of the clock. The first active edges of the clocks do still occur simultaneously. [#2001](https://github.com/clash-lang/clash-compiler/issues/2001) * Expected values in assert become undefined when using `-fclash-compile-ultra` [#2040](https://github.com/clash-lang/clash-compiler/issues/2040)
LICENSE view
@@ -1,6 +1,6 @@ Copyright (c) 2013-2016, University of Twente, 2016-2019, Myrtle Software Ltd,- 2017-2019, QBayLogic B.V., Google Inc.+ 2017-2025, QBayLogic B.V., Google Inc. All rights reserved. Redistribution and use in source and binary forms, with or without
README.md view
@@ -31,6 +31,6 @@ - [Discourse: long form discussions and questions](https://clash-lang.discourse.group/) - [Discord: short form discussions and community chat room](https://discord.gg/rebGq25FB4)-- [Slack: short form discussions and questions](https://functionalprogramming.slack.com/archives/CPGMJFF50)- (Invite yourself at [fpslack.com](https://fpslack.com))+- [Fosstodon: microblogging and community chat room](https://fosstodon.org/@ClashHDL)+- [Bluesky: microblogging and community chat room](https://bsky.app/profile/clash-lang.bsky.social) - [Github: issue tracker](https://github.com/clash-lang/clash-compiler/issues)
clash-prelude.cabal view
@@ -1,6 +1,6 @@ Cabal-version: 2.2 Name: clash-prelude-Version: 1.8.5+Version: 1.10.0 Synopsis: Clash: a functional hardware description language - Prelude library Description: Clash is a functional hardware description language that borrows both its@@ -39,9 +39,10 @@ "Clash.Prelude" and "Clash.Explicit.Prelude" at the same time as they have overlapping definitions. .- A preliminary version of a tutorial can be found in "Clash.Tutorial", for a- general overview of the library you should however check out "Clash.Prelude".- Some circuit examples can be found in "Clash.Examples".+ A preliminary version of a tutorial can be found at+ <https://docs.clash-lang.org/tutorial>, for a general overview of the library+ you should however check out "Clash.Prelude". Some circuit examples can be+ found in "Clash.Examples". Homepage: https://clash-lang.org/ bug-reports: https://github.com/clash-lang/clash-compiler/issues License: BSD-2-Clause@@ -51,9 +52,13 @@ Copyright: Copyright © 2013-2016, University of Twente, 2016-2017, Myrtle Software Ltd, 2017-2019, QBayLogic B.V., Google Inc.,- 2021-2025, QBayLogic B.V.+ 2021-2026, QBayLogic B.V. Category: Hardware Build-type: Simple+tested-with: GHC == 9.6.7,+ GHC == 9.8.4,+ GHC == 9.10.3,+ GHC == 9.12.4 Extra-source-files: README.md CHANGELOG.md@@ -90,15 +95,6 @@ default: False manual: True -flag multiple-hidden- description:- Allow multiple hidden clocks, resets, and enables to be used. This is an- experimental feature, possibly triggering confusing error messages. By- default, it is enabled on development versions of Clash and disabled on- releases.- default: False- manual: True- flag doctests description: You can disable testing with doctests using `-f-doctests`.@@ -140,6 +136,7 @@ KindSignatures MagicHash NoStarIsType+ PolyKinds PostfixOperators ScopedTypeVariables StandaloneDeriving@@ -155,12 +152,6 @@ ghc-options: -Wall -Wcompat -fexpose-all-unfoldings -fno-worker-wrapper CPP-Options: -DCABAL - -- See https://github.com/clash-lang/clash-compiler/pull/2511- if impl(ghc >= 9.4)- CPP-Options: -DCLASH_OPAQUE=OPAQUE- else- CPP-Options: -DCLASH_OPAQUE=NOINLINE- if flag(large-tuples) CPP-Options: -DLARGE_TUPLES @@ -170,12 +161,6 @@ if flag(strict-mapSignal) CPP-Options: -DCLASH_STRICT_MAPSIGNAL - if flag(multiple-hidden)- CPP-Options: -DCLASH_MULTIPLE_HIDDEN-- if flag(multiple-hidden)- Exposed-modules: Clash.Prelude.Synchronizer- Autogen-Modules: Paths_clash_prelude Exposed-modules: Clash.Annotations.TopEntity@@ -204,6 +189,10 @@ Clash.Class.HasDomain.CodeGen Clash.Class.HasDomain.Common Clash.Class.Num+ Clash.Class.NumConvert+ Clash.Class.NumConvert.Internal.NumConvert+ Clash.Class.NumConvert.Internal.MaybeNumConvert+ Clash.Class.NumConvert.Internal.Canonical Clash.Class.Parity Clash.Class.Resize @@ -252,7 +241,6 @@ Clash.Prelude.BlockRam Clash.Prelude.BlockRam.Blob Clash.Prelude.BlockRam.File- Clash.Prelude.DataFlow Clash.Prelude.Mealy Clash.Prelude.Moore Clash.Prelude.RAM@@ -332,21 +320,24 @@ TypeFamilies UndecidableInstances - Build-depends: array >= 0.5.1.0 && < 0.6,+ Build-depends: adjunctions >= 4.0 && < 5.0,+ array >= 0.5.1.0 && < 0.6, arrows >= 0.4 && < 0.5,- base >= 4.11 && < 5,+ base >= 4.18 && < 5, binary >= 0.8.5 && < 0.11, bytestring >= 0.10.8 && < 0.13, constraints >= 0.9 && < 1.0,- containers >= 0.4.0 && < 0.8,+ containers >= 0.4.0 && < 0.9, data-binary-ieee754 >= 0.4.4 && < 0.6,- data-default-class >= 0.1.2 && < 0.3,+ data-default >= 0.7 && < 0.9, deepseq >= 1.4.1.0 && < 1.6,+ distributive >= 0.1 && < 1.0, extra >= 1.6.17 && < 1.9,- ghc-prim >= 0.5.1.0 && < 0.13,- ghc-typelits-extra >= 0.4 && < 0.6,- ghc-typelits-knownnat >= 0.7.2 && < 0.9,- ghc-typelits-natnormalise >= 0.7.2 && < 0.10,+ ghc-bignum >= 1.0 && < 1.4,+ ghc-prim >= 0.5.1.0 && < 0.14,+ ghc-typelits-extra >= 0.5.3 && < 0.6,+ ghc-typelits-knownnat >= 0.8.3 && < 0.9,+ ghc-typelits-natnormalise >= 0.9.5 && < 0.10, hashable >= 1.2.1.0 && < 1.6, half >= 0.2.2.3 && < 1.0, infinite-list ^>= 0.1,@@ -357,8 +348,8 @@ singletons >= 2.0 && < 3.1, string-interpolate ^>= 0.3, tagged >= 0.8 && < 0.9,- template-haskell >= 2.12.0.0 && < 2.23,- th-abstraction >= 0.2.10 && < 0.8.0,+ template-haskell >= 2.20.0.0 && < 2.24,+ th-abstraction >= 0.3.0 && < 0.8.0, th-lift >= 0.7.0 && < 0.9, th-orphans >= 0.13.1 && < 1.0, text >= 0.11.3.1 && < 2.2,@@ -368,13 +359,10 @@ uniplate >= 1.6.12 && < 1.7, vector >= 0.11 && < 1.0, mtl >= 2.0 && < 3.0-- if impl(ghc >= 9.0.0)- Build-Depends: ghc-bignum >= 1.0 && < 1.4- else- Build-Depends: integer-gmp >= 1.0.1.0 && < 2.0+ -- Depend on GHC to obtain the maximum tuple size via+ -- import GHC.Settings.Constants (mAX_TUPLE_SIZE) if flag(large-tuples)- Build-Depends: ghc+ Build-Depends: ghc >= 9.6.0 && < 9.13 test-suite doctests type: exitcode-stdio-1.0@@ -389,7 +377,7 @@ build-depends: base, clash-prelude,- doctest-parallel >= 0.2 && < 0.5,+ doctest-parallel >= 0.3.1 && < 0.5, filepath if arch(x86_64) && flag(workaround-ghc-mmap-crash)@@ -446,10 +434,13 @@ Clash.Tests.Clocks Clash.Tests.Counter Clash.Tests.DumpVCD+ Clash.Tests.NumConvert Clash.Tests.DerivingDataRepr Clash.Tests.DerivingDataReprTypes Clash.Tests.Fixed Clash.Tests.FixedExhaustive+ Clash.Tests.Index+ Clash.Tests.MaybeNumConvert Clash.Tests.MaybeX Clash.Tests.NFDataX Clash.Tests.NumNewtypes@@ -465,6 +456,7 @@ Clash.Tests.XException Clash.Tests.Laws.Enum+ Clash.Tests.Laws.Num Clash.Tests.Laws.SaturatingNum Hedgehog.Extra
src/Clash/Annotations/BitRepresentation.hs view
@@ -8,6 +8,7 @@ -} +{-# LANGUAGE CPP #-} {-# LANGUAGE RankNTypes #-} {-# OPTIONS_GHC -Wno-orphans #-}@@ -28,7 +29,9 @@ ) where import Data.Data (Data)+#if __GLASGOW_HASKELL__ <= 910 import Data.Typeable (Typeable)+#endif import Language.Haskell.TH.Instances () import qualified Language.Haskell.TH.Lift () import qualified Language.Haskell.TH.Syntax as TH@@ -112,7 +115,10 @@ Size -- Constructors: [ConstrRepr]- deriving (Show, Data, Typeable, Eq, Generic, TH.Lift)+ deriving (Show, Data, Eq, Generic, TH.Lift)+#if __GLASGOW_HASKELL__ <= 910+ deriving Typeable+#endif -- | Annotation for constructors. Indicates how to match this constructor based -- off of the whole datatype.@@ -126,4 +132,7 @@ Value -- Masks for fields. Indicates where fields are stored: [FieldAnn]- deriving (Show, Data, Typeable, Eq, Generic, TH.Lift)+ deriving (Show, Data, Eq, Generic, TH.Lift)+#if __GLASGOW_HASKELL__ <= 910+ deriving Typeable+#endif
src/Clash/Annotations/BitRepresentation/Deriving.hs view
@@ -74,7 +74,9 @@ import Data.Containers.ListUtils (nubOrd) import Data.List (mapAccumL, zipWith4, sortOn, partition, uncons)+#if __GLASGOW_HASKELL__ < 912 import Data.Typeable (Typeable)+#endif import qualified Data.Map as Map import Data.Maybe (fromMaybe) import qualified Data.Set as Set@@ -93,7 +95,10 @@ -- ^ Constructor bit should be stored externally | Embedded BitMask Value -- ^ Constructor bit should be stored in one of the constructor's fields- deriving (Show, Data, Typeable, Lift)+ deriving (Show, Data, Lift)+#if __GLASGOW_HASKELL__ < 912+ deriving (Typeable)+#endif isExternal :: BitMaskOrigin -> Bool isExternal External = True@@ -162,15 +167,9 @@ bitsNeeded :: Integer -> Int bitsNeeded = integerLog2Ceil -#if MIN_VERSION_template_haskell(2,17,0) tyVarBndrName :: TyVarBndr f -> Name tyVarBndrName (PlainTV n _f) = n tyVarBndrName (KindedTV n _f _k) = n-#else-tyVarBndrName :: TyVarBndr -> Name-tyVarBndrName (PlainTV n) = n-tyVarBndrName (KindedTV n _k) = n-#endif -- | Replace Vars types given in mapping resolve :: NameMap -> Type -> Type@@ -210,11 +209,7 @@ fail $ unwords [ "Could not find custom bit representation nor BitSize instance" , "for", show typ ++ "." ]-#if MIN_VERSION_template_haskell(2,15,0) [TySynInstD (TySynEqn _ _ (LitT (NumTyLit n)))] ->-#else- [TySynInstD _ (TySynEqn _ (LitT (NumTyLit n)))] ->-#endif [| n |] [_impl] -> [| fromIntegral $ natVal (Proxy :: Proxy (BitSize $(return typ))) |]@@ -895,11 +890,7 @@ (\v1 v2 -> [| $v1 ++# $v2 |]) (map (select $ map VarE fieldPackedNames) origins) -#if MIN_VERSION_template_haskell(2,18,0) return $ Match (ConP name [] (VarP <$> fieldNames)) (NormalB vec) fieldPackedDecls-#else- return $ Match (ConP name (VarP <$> fieldNames)) (NormalB vec) fieldPackedDecls-#endif -- | Build a /pack/ function corresponding to given DataRepr buildPack@@ -922,8 +913,7 @@ -- This is used in the generated pack/unpack to not do anything in HDL. dontApplyInHDL :: (a -> b) -> a -> b dontApplyInHDL f a = f a--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE dontApplyInHDL #-}+{-# OPAQUE dontApplyInHDL #-} {-# ANN dontApplyInHDL hasBlackBox #-} buildUnpackField
src/Clash/Annotations/BitRepresentation/Internal.hs view
@@ -31,7 +31,9 @@ import qualified Data.Map as Map import Data.Maybe (fromMaybe) import qualified Data.Text as Text+#if __GLASGOW_HASKELL__ <= 910 import Data.Typeable (Typeable)+#endif import qualified Language.Haskell.TH.Syntax as TH import GHC.Generics (Generic) import GHC.Stack (HasCallStack)@@ -47,7 +49,10 @@ -- ^ Numeral literal (used in BitVector 10, for example) | SymLitTy' Text.Text -- ^ Symbol literal (used in for example (Signal "System" Int))- deriving (Generic, NFData, Eq, Typeable, Hashable, Ord, Show)+ deriving (Generic, NFData, Eq, Hashable, Ord, Show)+#if __GLASGOW_HASKELL__ <= 910+ deriving Typeable+#endif -- | Internal version of DataRepr data DataRepr' = DataRepr'@@ -58,7 +63,10 @@ , drConstrs :: [ConstrRepr'] -- ^ Constructors }- deriving (Show, Generic, NFData, Eq, Typeable, Hashable, Ord)+ deriving (Show, Generic, NFData, Eq, Hashable, Ord)+#if __GLASGOW_HASKELL__ <= 910+ deriving Typeable+#endif -- | Internal version of ConstrRepr data ConstrRepr' = ConstrRepr'@@ -73,7 +81,10 @@ , crFieldAnns :: [FieldAnn] -- ^ Indicates where fields are stored }- deriving (Show, Generic, NFData, Eq, Typeable, Ord, Hashable)+ deriving (Show, Generic, NFData, Eq, Ord, Hashable)+#if __GLASGOW_HASKELL__ <= 910+ deriving Typeable+#endif constrReprToConstrRepr' :: Int -> ConstrRepr -> ConstrRepr' constrReprToConstrRepr' n (ConstrRepr name mask value fieldanns) =
src/Clash/Annotations/SynthesisAttributes.hs view
@@ -1,6 +1,6 @@ {-| Copyright : (C) 2018, Google Inc.,- 2021-2023, QBayLogic B.V.+ 2021-2025, QBayLogic B.V. License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> @@ -13,7 +13,6 @@ {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE CPP #-} {-# LANGUAGE NoGeneralizedNewtypeDeriving #-}-{-# LANGUAGE PolyKinds #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskellQuotes #-} @@ -129,7 +128,7 @@ -- "Clash.Magic". annotate :: forall n dom a . Vec n (Attr String) -> Signal dom a -> Signal dom a annotate !_attrs !a = a-{-# CLASH_OPAQUE annotate #-}+{-# OPAQUE annotate #-} {-# ANN annotate hasBlackBox #-} {-# ANN annotate let primName = show 'annotate@@ -243,5 +242,5 @@ -} annotateReg :: forall n dom a . Vec n (Attr String) -> Signal dom a -> Signal dom a annotateReg !_ x = x-{-# CLASH_OPAQUE annotateReg #-}+{-# OPAQUE annotateReg #-} {-# ANN annotateReg hasBlackBox #-}
src/Clash/Annotations/TH.hs view
@@ -51,7 +51,6 @@ {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE PatternSynonyms #-}-{-# LANGUAGE PolyKinds #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-}@@ -163,15 +162,7 @@ -- | Grab the 'Name's of type variables in a datatype datatypeVars' :: DatatypeInfo -> [Name]-#if MIN_VERSION_th_abstraction(0,3,0) datatypeVars' d = tvName <$> datatypeVars d-#else-datatypeVars' d = name <$> datatypeVars d- where- name (VarT n) = n- name (SigT n _) = name n- name e = error $ "Unexpected datatype variable name of type " ++ show e-#endif -- | Run a 'Name' through the template haskell machinery, getting a -- 'DatatypeInfo' if the 'Name' specified a datatype. The result is processed by@@ -322,11 +313,7 @@ -- port tree from the constructor _ | familyArity info == Just (length xs) -> do (lift $ reifyInstances x xs) >>= \case-#if MIN_VERSION_template_haskell(2,15,0) [TySynInstD (TySynEqn _ _ r)] ->-#else- [TySynInstD _ (TySynEqn _ r)] ->-#endif gatherNames (applyFamilyBindings xs info r) [NewtypeInstD _ _ _ _ c _] -> constructorToPorts c (familyTyMap xs info)@@ -375,17 +362,9 @@ = applyContext ctx (tvName <$> holes) t applyFamilyBindings _ _ _ = error "familyTyMap called with non family argument!" -#if MIN_VERSION_template_haskell(2,15,0) tySynArgs (TySynEqn _ args _) = drop 1 (unapp args)-#else- tySynArgs (TySynEqn args _) = args-#endif -#if MIN_VERSION_template_haskell(2,15,0) tySynRHS (TySynEqn _ _ r) = r-#else- tySynRHS (TySynEqn _ r) = r-#endif familyBindings (FamilyI (ClosedTypeFamilyD (TypeFamilyHead _ xs _ _) _) _) = Just xs familyBindings (FamilyI (OpenTypeFamilyD (TypeFamilyHead _ xs _ _)) _) = Just xs@@ -444,7 +423,6 @@ -- -- Fail if: -- - There are free type variables.--- - There are multiple hidden clocks handleConstraints :: Type -> ClockType -> Q (Type, ClockType) handleConstraints (ForallT [] [] x) clk = handleConstraints x clk handleConstraints (ForallT xs@(_:_) _ _) _ =@@ -470,7 +448,7 @@ clockToPorts (SingleClockResetEnable) = return [PortProduct "" [ PortName "clk" , PortName "rst" , PortName "en" ]] clockToPorts Other =- fail $ failMsg "TH generation for multiple hidden clocks and"+ fail $ failMsg "TH generation for" ++ " HiddenClock/HiddenReset/HiddenEnable currently unsupported!" -- *@@ -487,11 +465,7 @@ Just name' -> name' -- user specified name Nothing -> nameBase name -- auto-generated from Haskell name -#if MIN_VERSION_template_haskell(2,17,0) (examineCode-#else- (-#endif [|| Synthesize { t_name = outName , t_inputs = ins@@ -502,15 +476,9 @@ -- This will return an 'TExp' of 'Nothing' if 'TopEntity' generation failed. maybeBuildTopEntity :: Maybe String -> Name -> Q (TExp (Maybe TopEntity)) maybeBuildTopEntity topName name = do-#if MIN_VERSION_template_haskell(2,17,0) recover (examineCode [|| Nothing ||]) $ do let expr = liftCode (getNameBinding name >>= buildTopEntity topName) examineCode [|| Just ($$expr) ||]-#else- recover ([|| Nothing ||]) $ do- let expr = getNameBinding name >>= buildTopEntity topName- [|| Just ($$expr) ||]-#endif -- | Turn the 'Name' of a value to a @('Name', 'Type')@ getNameBinding :: Name -> Q (Name, Type)
src/Clash/Annotations/TopEntity.hs view
@@ -231,9 +231,7 @@ import GHC.Generics import qualified Language.Haskell.TH as TH import Language.Haskell.TH.Syntax (Lift(..))-#if MIN_VERSION_template_haskell(2,16,0) import Language.Haskell.TH.Compat-#endif import Data.Data -- | TopEntity annotation@@ -271,9 +269,7 @@ , lift output ] lift (TestBench _) = error "Cannot lift a TestBench"-#if MIN_VERSION_template_haskell(2,16,0) liftTyped = liftTypedFromUntyped-#endif -- | Give port names for arguments/results. --
src/Clash/CPP.hs view
@@ -21,11 +21,7 @@ #ifndef MAX_TUPLE_SIZE #ifdef LARGE_TUPLES -#if MIN_VERSION_ghc(9,0,0) import GHC.Settings.Constants (mAX_TUPLE_SIZE)-#else-import Constants (mAX_TUPLE_SIZE)-#endif #define MAX_TUPLE_SIZE (fromIntegral mAX_TUPLE_SIZE) #else
src/Clash/Class/AutoReg/Internal.hs view
@@ -207,9 +207,7 @@ go acc (AppT ty1 ty2) = go (ty2:acc) ty1 go acc (SigT ty _) = go acc ty go acc (ParensT ty) = go acc ty-#if MIN_VERSION_template_haskell(2,15,0) go acc (AppKindT ty _) = go acc ty-#endif go acc ty = (ty, acc) -- | Automatically derives an 'AutoReg' instance for a product type@@ -255,11 +253,7 @@ deriveAutoRegProduct tyInfo conInfo = go (constructorName conInfo) fieldInfos where tyNm = datatypeName tyInfo-#if MIN_VERSION_th_abstraction(0,3,0) tyArgs = datatypeInstTypes tyInfo-#else- tyArgs = datatypeVars tyInfo-#endif ty = conAppsT tyNm tyArgs fieldInfos =@@ -423,12 +417,8 @@ (InfixT x1 _ y1 , InfixT x2 _ y2) -> go x1 x2 ++ go y1 y2 (UInfixT x1 _ y1, UInfixT x2 _ y2) -> go x1 x2 ++ go y1 y2 (ParensT x1 , ParensT x2) -> go x1 x2--#if __GLASGOW_HASKELL__ >= 808 (AppKindT t1 k1 , AppKindT t2 k2) -> go t1 t2 ++ go k1 k2 (ImplicitParamT _ x1, ImplicitParamT _ x2) -> go x1 x2-#endif- (PromotedT _ , PromotedT _ ) -> [] (TupleT _ , TupleT _ ) -> [] (UnboxedTupleT _ , UnboxedTupleT _ ) -> []
src/Clash/Class/BitPack/Internal.hs view
@@ -1,8 +1,9 @@ {-| Copyright : (C) 2013-2016, University of Twente, 2016-2017, Myrtle Software Ltd,- 2021-2025, QBayLogic B.V.,+ 2021-2026, QBayLogic B.V., 2022, Google Inc.+ 2023, LumiGuide Fietsdetectie B.V. License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> -}@@ -29,15 +30,16 @@ import Data.Binary.IEEE754 (doubleToWord, floatToWord, wordToDouble, wordToFloat) +import Data.Char (chr, ord) import Data.Complex (Complex) import Data.Functor.Compose (Compose) import Data.Functor.Const (Const) import Data.Functor.Identity (Identity) import Data.Functor.Product (Product) import Data.Functor.Sum (Sum)-import Data.Char (chr, ord) import Data.Int import Data.Ord (Down)+import Data.Proxy (Proxy) import Data.Word import Foreign.C.Types (CUShort) import GHC.Generics@@ -57,6 +59,7 @@ >>> :m -Prelude >>> :set -XDataKinds >>> import Clash.Prelude+>>> import Data.Proxy -} -- | Convert data to/from a 'BitVector'. This allows functions to be defined@@ -91,7 +94,7 @@ -- places. -- -- Clash provides some generic functions on packable types in the prelude, such--- as indexing into packable stuctures (see "Clash.Class.BitPack.BitIndex") and+-- as indexing into packable structures (see "Clash.Class.BitPack.BitIndex") and -- bitwise reduction of packable data (see "Clash.Class.BitPack.BitReduction"). -- class KnownNat (BitSize a) => BitPack a where@@ -251,54 +254,144 @@ instance BitPack Int where type BitSize Int = WORD_SIZE_IN_BITS- pack = packXWith fromIntegral- unpack = checkUnpackUndef fromIntegral+ pack = packXWith toEnum+ unpack = checkUnpackUndef fromEnum instance BitPack Int8 where type BitSize Int8 = 8- pack = packXWith fromIntegral- unpack = checkUnpackUndef fromIntegral+ pack = packXWith packInt8#+ unpack = checkUnpackUndef unpackInt8# +packInt8# :: Int8 -> BitVector 8+packInt8# = fromIntegral+{-# OPAQUE packInt8# #-}+{-# ANN packInt8# hasBlackBox #-}++unpackInt8# :: BitVector 8 -> Int8+unpackInt8# = fromIntegral+{-# OPAQUE unpackInt8# #-}+{-# ANN unpackInt8# hasBlackBox #-}+ instance BitPack Int16 where type BitSize Int16 = 16- pack = packXWith fromIntegral- unpack = checkUnpackUndef fromIntegral+ pack = packXWith packInt16#+ unpack = checkUnpackUndef unpackInt16# +packInt16# :: Int16 -> BitVector 16+packInt16# = fromIntegral+{-# OPAQUE packInt16# #-}+{-# ANN packInt16# hasBlackBox #-}++unpackInt16# :: BitVector 16 -> Int16+unpackInt16# = fromIntegral+{-# OPAQUE unpackInt16# #-}+{-# ANN unpackInt16# hasBlackBox #-}+ instance BitPack Int32 where type BitSize Int32 = 32- pack = packXWith fromIntegral- unpack = checkUnpackUndef fromIntegral+ pack = packXWith packInt32#+ unpack = checkUnpackUndef unpackInt32# +packInt32# :: Int32 -> BitVector 32+packInt32# = fromIntegral+{-# OPAQUE packInt32# #-}+{-# ANN packInt32# hasBlackBox #-}++unpackInt32# :: BitVector 32 -> Int32+unpackInt32# = fromIntegral+{-# OPAQUE unpackInt32# #-}+{-# ANN unpackInt32# hasBlackBox #-}+ instance BitPack Int64 where type BitSize Int64 = 64- pack = packXWith fromIntegral- unpack = checkUnpackUndef fromIntegral+ pack = packXWith packInt64#+ unpack = checkUnpackUndef unpackInt64# +packInt64# :: Int64 -> BitVector 64+packInt64# = fromIntegral+{-# OPAQUE packInt64# #-}+{-# ANN packInt64# hasBlackBox #-}++unpackInt64# :: BitVector 64 -> Int64+unpackInt64# = fromIntegral+{-# OPAQUE unpackInt64# #-}+{-# ANN unpackInt64# hasBlackBox #-}+ instance BitPack Word where type BitSize Word = WORD_SIZE_IN_BITS- pack = packXWith fromIntegral- unpack = checkUnpackUndef fromIntegral+ pack = packXWith packWord#+ unpack = checkUnpackUndef unpackWord# +packWord# :: Word -> BitVector WORD_SIZE_IN_BITS+packWord# = fromIntegral+{-# OPAQUE packWord# #-}+{-# ANN packWord# hasBlackBox #-}++unpackWord# :: BitVector WORD_SIZE_IN_BITS -> Word+unpackWord# = fromIntegral+{-# OPAQUE unpackWord# #-}+{-# ANN unpackWord# hasBlackBox #-}+ instance BitPack Word8 where type BitSize Word8 = 8- pack = packXWith fromIntegral- unpack = checkUnpackUndef fromIntegral+ pack = packXWith packWord8#+ unpack = checkUnpackUndef unpackWord8# +packWord8# :: Word8 -> BitVector 8+packWord8# = fromIntegral+{-# OPAQUE packWord8# #-}+{-# ANN packWord8# hasBlackBox #-}++unpackWord8# :: BitVector 8 -> Word8+unpackWord8# = fromIntegral+{-# OPAQUE unpackWord8# #-}+{-# ANN unpackWord8# hasBlackBox #-}+ instance BitPack Word16 where type BitSize Word16 = 16- pack = packXWith fromIntegral- unpack = checkUnpackUndef fromIntegral+ pack = packXWith packWord16#+ unpack = checkUnpackUndef unpackWord16# +packWord16# :: Word16 -> BitVector 16+packWord16# = fromIntegral+{-# OPAQUE packWord16# #-}+{-# ANN packWord16# hasBlackBox #-}++unpackWord16# :: BitVector 16 -> Word16+unpackWord16# = fromIntegral+{-# OPAQUE unpackWord16# #-}+{-# ANN unpackWord16# hasBlackBox #-}+ instance BitPack Word32 where type BitSize Word32 = 32- pack = packXWith fromIntegral- unpack = checkUnpackUndef fromIntegral+ pack = packXWith packWord32#+ unpack = checkUnpackUndef unpackWord32# +packWord32# :: Word32 -> BitVector 32+packWord32# = fromIntegral+{-# OPAQUE packWord32# #-}+{-# ANN packWord32# hasBlackBox #-}++unpackWord32# :: BitVector 32 -> Word32+unpackWord32# = fromIntegral+{-# OPAQUE unpackWord32# #-}+{-# ANN unpackWord32# hasBlackBox #-}+ instance BitPack Word64 where type BitSize Word64 = 64- pack = packXWith fromIntegral- unpack = checkUnpackUndef fromIntegral+ pack = packXWith packWord64#+ unpack = checkUnpackUndef unpackWord64# +packWord64# :: Word64 -> BitVector 64+packWord64# = fromIntegral+{-# OPAQUE packWord64# #-}+{-# ANN packWord64# hasBlackBox #-}++unpackWord64# :: BitVector 64 -> Word64+unpackWord64# = fromIntegral+{-# OPAQUE unpackWord64# #-}+{-# ANN unpackWord64# hasBlackBox #-}+ instance BitPack Float where type BitSize Float = 32 pack = packXWith packFloat#@@ -306,14 +399,12 @@ packFloat# :: Float -> BitVector 32 packFloat# = fromIntegral . floatToWord--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE packFloat# #-}+{-# OPAQUE packFloat# #-} {-# ANN packFloat# hasBlackBox #-} unpackFloat# :: BitVector 32 -> Float unpackFloat# (unsafeToNatural -> w) = wordToFloat (fromIntegral w)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE unpackFloat# #-}+{-# OPAQUE unpackFloat# #-} {-# ANN unpackFloat# hasBlackBox #-} instance BitPack Double where@@ -323,21 +414,29 @@ packDouble# :: Double -> BitVector 64 packDouble# = fromIntegral . doubleToWord--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE packDouble# #-}+{-# OPAQUE packDouble# #-} {-# ANN packDouble# hasBlackBox #-} unpackDouble# :: BitVector 64 -> Double unpackDouble# (unsafeToNatural -> w) = wordToDouble (fromIntegral w)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE unpackDouble# #-}+{-# OPAQUE unpackDouble# #-} {-# ANN unpackDouble# hasBlackBox #-} instance BitPack CUShort where type BitSize CUShort = 16- pack = packXWith fromIntegral- unpack = checkUnpackUndef fromIntegral+ pack = packXWith packCUShort#+ unpack = checkUnpackUndef unpackCUShort# +packCUShort# :: CUShort -> BitVector 16+packCUShort# = fromIntegral+{-# OPAQUE packCUShort# #-}+{-# ANN packCUShort# hasBlackBox #-}++unpackCUShort# :: BitVector 16 -> CUShort+unpackCUShort# = fromIntegral+{-# OPAQUE unpackCUShort# #-}+{-# ANN unpackCUShort# hasBlackBox #-}+ instance BitPack Half where type BitSize Half = 16 pack (Half x) = pack x@@ -355,14 +454,12 @@ packChar# :: Char -> BitVector 21 packChar# = fromIntegral . ord--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE packChar# #-}+{-# OPAQUE packChar# #-} {-# ANN packChar# hasBlackBox #-} unpackChar# :: BitVector 21 -> Char unpackChar# = chr . fromIntegral--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE unpackChar# #-}+{-# OPAQUE unpackChar# #-} {-# ANN unpackChar# hasBlackBox #-} -- | __NB__: The documentation only shows instances up to /3/-tuples. By@@ -481,6 +578,16 @@ ) => BitPack (Either a b) instance BitPack a => BitPack (Maybe a)++-- | Any 'Proxy' has a bit size of 0 and hence packs to @0 :: BitVector 0@.+--+-- >>> pack (Proxy @())+-- 0+-- >>> pack (Proxy @5)+-- 0+-- >>> pack (Proxy @Bool)+-- 0+instance BitPack (Proxy a) instance BitPack a => BitPack (Complex a) instance BitPack a => BitPack (Down a)
src/Clash/Class/Counter/Internal.hs view
@@ -1,3 +1,9 @@+{- |+Copyright : (C) 2021-2026, QBayLogic B.V.+License : BSD2 (see the file LICENSE)+Maintainer : QBayLogic B.V. <devops@qbaylogic.com>+-}+ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralisedNewtypeDeriving #-} {-# LANGUAGE LambdaCase #-}@@ -14,6 +20,7 @@ import Clash.Sized.Index (Index) import Clash.Sized.Signed (Signed) import Clash.Sized.Unsigned (Unsigned)+import Clash.Sized.Vector as Vec (Vec, repeat, mapAccumR) import Data.Bifunctor (bimap) import Data.Functor.Identity (Identity(..))@@ -22,11 +29,14 @@ import GHC.TypeLits (KnownNat, type (<=)) -- $setup+-- >>> :m -Prelude+-- >>> import Clash.Prelude -- >>> import Clash.Class.Counter -- >>> import Clash.Sized.BitVector (BitVector) -- >>> import Clash.Sized.Index (Index) -- >>> import Clash.Sized.Signed (Signed) -- >>> import Clash.Sized.Unsigned (Unsigned)+-- >>> import Clash.Sized.Vector (Vec(..), iterate) -- | t'Clash.Class.Counter.Counter' is a class that composes multiple counters -- into a single one. It is similar to odometers found in olds cars,@@ -193,3 +203,26 @@ (overflowA, a1) = countPredOverflow a0 genTupleInstances maxTupleSize++rippleR :: (a -> (Bool, a)) -> Vec n a -> (Bool, Vec n a)+rippleR f = mapAccumR step True+ where+ step carry x = if carry then f x else (False, x)++-- | Counters on vectors increment from right to left.+--+-- >>> type T = Vec 2 (Index 10)+-- >>> countSucc @T (0 :> 0 :> Nil)+-- 0 :> 1 :> Nil+-- >>> countSucc @T (0 :> 1 :> Nil)+-- 0 :> 2 :> Nil+-- >>> countSucc @T (0 :> 9 :> Nil)+-- 1 :> 0 :> Nil+-- >>> iterate (SNat @5) (countSucc @T) (9 :> 8 :> Nil)+-- (9 :> 8 :> Nil) :> (9 :> 9 :> Nil) :> (0 :> 0 :> Nil) :> (0 :> 1 :> Nil) :> (0 :> 2 :> Nil) :> Nil+instance (Counter a, KnownNat n) => Counter (Vec n a) where+ countMin = Vec.repeat countMin+ countMax = Vec.repeat countMax++ countSuccOverflow = rippleR countSuccOverflow+ countPredOverflow = rippleR countPredOverflow
src/Clash/Class/Counter/TH.hs view
@@ -15,11 +15,7 @@ mkTupTy names@(length -> n) = foldl AppT (TupleT n) names mkTup :: [Exp] -> Exp-#if MIN_VERSION_template_haskell(2,16,0) mkTup = TupE . map Just-#else-mkTup = TupE-#endif genTupleInstances :: Int -> Q [Dec] genTupleInstances maxTupleSize = mapM genTupleInstance [3..maxTupleSize]
src/Clash/Class/Exp.hs view
@@ -75,8 +75,7 @@ -> Index (Max 2 (m ^ n)) expIndex# b e@SNat = fromInteger (toInteger b P.^ snatToInteger e)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE expIndex# #-}+{-# OPAQUE expIndex# #-} {-# ANN expIndex# hasBlackBox #-} expSigned#@@ -86,8 +85,7 @@ -> Signed (Max 2 (m * n)) expSigned# b e@SNat = fromInteger (toInteger b P.^ snatToInteger e)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE expSigned# #-}+{-# OPAQUE expSigned# #-} {-# ANN expSigned# hasBlackBox #-} expUnsigned#@@ -97,6 +95,5 @@ -> Unsigned (Max 1 (m * n)) expUnsigned# b e@SNat = fromInteger (toInteger b P.^ snatToInteger e)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE expUnsigned# #-}+{-# OPAQUE expUnsigned# #-} {-# ANN expUnsigned# hasBlackBox #-}
src/Clash/Class/HasDomain.hs view
@@ -1,4 +1,6 @@-module Clash.Class.HasDomain+{-# OPTIONS_GHC -Wno-deprecations #-}++module Clash.Class.HasDomain {-# DEPRECATED "Experimental feature multiple hidden has been removed. This module will therefore be removed in Clash 1.12." #-} ( WithSpecificDomain , WithSingleDomain
src/Clash/Class/HasDomain/Common.hs view
@@ -4,10 +4,9 @@ Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com> -} -{-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeFamilies #-} -module Clash.Class.HasDomain.Common+module Clash.Class.HasDomain.Common {-# DEPRECATED "Experimental feature multiple hidden has been removed. This module will therefore be removed in Clash 1.12." #-} ( Unlines , (:<<>>:) , (:$$$:)
src/Clash/Class/HasDomain/HasSingleDomain.hs view
@@ -1,6 +1,6 @@ {-| Copyright : (C) 2019, Myrtle Software Ltd- 2022, QBayLogic B.V.+ 2022-2025, QBayLogic B.V. License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> @@ -10,15 +10,14 @@ {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE PolyKinds #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} -{-# OPTIONS_GHC -Wno-missing-methods #-}+{-# OPTIONS_GHC -Wno-missing-methods -Wno-deprecations #-} {-# OPTIONS_HADDOCK not-home #-} -module Clash.Class.HasDomain.HasSingleDomain where+module Clash.Class.HasDomain.HasSingleDomain {-# DEPRECATED "Experimental feature multiple hidden has been removed. This module will therefore be removed in Clash 1.12." #-} where import Clash.Class.HasDomain.Common import Clash.Class.HasDomain.CodeGen (mkTryDomainTuples)
src/Clash/Class/HasDomain/HasSpecificDomain.hs view
@@ -1,5 +1,6 @@ {-| Copyright : (C) 2019, Myrtle Software Ltd+ 2022-2025, QBayLogic B.V. License : BSD2 (see the file LICENSE) Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com> @@ -10,15 +11,14 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE PolyKinds #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} -{-# OPTIONS_GHC -Wno-missing-methods #-}+{-# OPTIONS_GHC -Wno-missing-methods -Wno-deprecations #-} {-# OPTIONS_HADDOCK not-home #-} -module Clash.Class.HasDomain.HasSpecificDomain where+module Clash.Class.HasDomain.HasSpecificDomain {-# DEPRECATED "Experimental feature multiple hidden has been removed. This module will therefore be removed in Clash 1.12." #-} where import Clash.Class.HasDomain.CodeGen (mkHasDomainTuples) import Clash.Class.HasDomain.Common
+ src/Clash/Class/NumConvert.hs view
@@ -0,0 +1,44 @@+{- |+Copyright : (C) 2025 , Martijn Bastiaan+License : BSD2 (see the file LICENSE)+Maintainer : QBayLogic B.V. <devops@qbaylogic.com>++Utilities for converting between Clash number types in a non-erroring way. Its+existence is motivated by the observation that Clash users often need to convert+between different number types (e.g., @Unsigned@ to @Signed@) and that it is not+always clear how to do so properly. Two classes are exported:++* 'NumConvert': for conversions that, based on types, are guaranteed to succeed.+* 'MaybeNumConvert': for conversions that may fail for some values.++As opposed to 'Prelude.fromIntegral', all conversions are translatable to+synthesizable HDL.++== __Relation to @convertible@__+Type classes exported here are similar to the @convertible@ package in that it+aims to facilitate conversions between different types. It is different in three+ways:++ 1. It offers no partial functions+ 2. All its conversions are translatable to synthesizable HDL+ 3. It is focused on (Clash's) number types++== __Implementing 'NumConvert' for your own type__+If you want to implement 'NumConvert' and 'MaybeNumConvert' for your own type,+see 'NumConvertCanonical'.+-}+module Clash.Class.NumConvert (+ NumConvert,+ numConvert,+ MaybeNumConvert,+ maybeNumConvert,++ -- * For implementers only+ NumConvertCanonical(..),+ MaybeNumConvertCanonical(..),+ Canonical,+) where++import Clash.Class.NumConvert.Internal.MaybeNumConvert+import Clash.Class.NumConvert.Internal.NumConvert+import Clash.Class.NumConvert.Internal.Canonical
+ src/Clash/Class/NumConvert/Internal/Canonical.hs view
@@ -0,0 +1,48 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS_HADDOCK hide #-}++#include "MachDeps.h"++{- |+Copyright : (C) 2026 , Martijn Bastiaan+License : BSD2 (see the file LICENSE)+Maintainer : QBayLogic B.V. <devops@qbaylogic.com>+-}+module Clash.Class.NumConvert.Internal.Canonical where++import Clash.Sized.BitVector+import Clash.Sized.Index+import Clash.Sized.Signed+import Clash.Sized.Unsigned++import Data.Int (Int16, Int32, Int64, Int8)+import Data.Word (Word16, Word32, Word64, Word8)++-- | Type family mapping types to their canonical \"unwrapped\" Clash form.+-- This is used by 'Clash.Class.NumConvert.numConvert' and+-- 'Clash.Class.NumConvert.maybeNumConvert' to determine the intermediate type.+type family Canonical a++-- Instances for Data.Word types+type instance Canonical Word = Unsigned WORD_SIZE_IN_BITS+type instance Canonical Word64 = Unsigned 64+type instance Canonical Word32 = Unsigned 32+type instance Canonical Word16 = Unsigned 16+type instance Canonical Word8 = Unsigned 8++-- Instances for Data.Int types+type instance Canonical Int = Signed WORD_SIZE_IN_BITS+type instance Canonical Int64 = Signed 64+type instance Canonical Int32 = Signed 32+type instance Canonical Int16 = Signed 16+type instance Canonical Int8 = Signed 8++-- Bit+type instance Canonical Bit = BitVector 1++-- Clash types are already in canonical form+type instance Canonical (Unsigned n) = Unsigned n+type instance Canonical (Signed n) = Signed n+type instance Canonical (BitVector n) = BitVector n+type instance Canonical (Index n) = Index n
+ src/Clash/Class/NumConvert/Internal/MaybeNumConvert.hs view
@@ -0,0 +1,161 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_GHC -fplugin=GHC.TypeLits.Extra.Solver #-}+{-# OPTIONS_GHC -fplugin=GHC.TypeLits.KnownNat.Solver #-}+{-# OPTIONS_GHC -fplugin=GHC.TypeLits.Normalise #-}+{-# OPTIONS_HADDOCK hide #-}++{- |+Copyright : (C) 2025 , Martijn Bastiaan+ 2025-2026, QBayLogic B.V.+License : BSD2 (see the file LICENSE)+Maintainer : QBayLogic B.V. <devops@qbaylogic.com>+-}+module Clash.Class.NumConvert.Internal.MaybeNumConvert where++import Clash.Class.BitPack+import Clash.Class.NumConvert.Internal.NumConvert (NumConvertCanonical (..))+import Clash.Class.NumConvert.Internal.Canonical (Canonical)+import Clash.Class.Resize+import Clash.Promoted.Nat+import Clash.Sized.BitVector+import Clash.Sized.Index+import Clash.Sized.Signed+import Clash.Sized.Unsigned++import GHC.TypeLits (KnownNat, type (+), type (^))+import GHC.TypeLits.Extra (CLogWZ)++{- $setup+>>> import Clash.Prelude+>>> import Clash.Class.NumConvert+>>> import Data.Word+>>> import Data.Int+-}++{- | Internal class for concrete conversions that may fail. This class is used+internally by 'MaybeNumConvert' and should not be used directly. Use+'MaybeNumConvert' instead.+-}+class MaybeNumConvertCanonical a b where+ maybeNumConvertCanonical :: a -> Maybe b++{- | Conversions that may fail for some values. A successful conversion retains+the numerical value interpretation of the source type in the target type. A+failure is expressed by returning 'Nothing', never by an 'Clash.XException.XException'.++== __Laws__+A conversion is either successful or it fails gracefully. I.e., it does not+produce errors (also see "Clash.XException"). I.e.,++> x == fromMaybe x (maybeNumConvert @a @b x >>= maybeNumConvert @b @a)++for all values @x@ of type @a@. It should also preserve the numerical value+interpretation of the bits. For types that have an @Integral@ instance, this+intuition is captured by:++> toInteger x == fromMaybe (toInteger x) (toInteger <$> maybeNumConvert @a @b x)++If a conversion succeeds one way, it should also succeed the other way. I.e.,++> isJust (maybeNumConvert @a @b x) `implies` isJust (maybeNumConvert @a @b x >>= maybeNumConvert @b @a)++A conversion should succeed if and only if the value is representable in the+target type. For types that have a @Bounded@ and @Integral@ instance, this+intuition is captured by:++> isJust (maybeNumConvert @a @b x) == (i x >= i (minBound @b) && i x <= i (maxBound @b))++where @i = toInteger@.++All implementations should be total, i.e., they should not produce \"bottoms\".++Additionally, any implementation should be translatable to synthesizable HDL.+-}+type MaybeNumConvert a b =+ ( NumConvertCanonical a (Canonical a)+ , MaybeNumConvertCanonical (Canonical a) (Canonical b)+ , NumConvertCanonical (Canonical b) b+ )++{- | Convert a supplied value of type @a@ to a value of type @b@. If the value+cannot be represented in the target type, 'Nothing' is returned.++>>> maybeNumConvert (1 :: Index 8) :: Maybe (Unsigned 2)+Just 1+>>> maybeNumConvert (7 :: Index 8) :: Maybe (Unsigned 2)+Nothing++For the time being, if the input is an 'Clash.XException.XException', then+the output is too. This property might be relaxed in the future.+-}+maybeNumConvert :: forall a b. MaybeNumConvert a b => a -> Maybe b+maybeNumConvert a =+ fmap (numConvertCanonical @(Canonical b) @b)+ $ maybeNumConvertCanonical @(Canonical a) @(Canonical b)+ $ numConvertCanonical @a @(Canonical a) a++instance (KnownNat n, KnownNat m) => MaybeNumConvertCanonical (Index n) (Index m) where+ maybeNumConvertCanonical !a = case natToInteger @m of+ 0 -> Nothing+ _ -> maybeResize a++instance (KnownNat n, KnownNat m) => MaybeNumConvertCanonical (Index n) (Unsigned m) where+ maybeNumConvertCanonical !a = maybeResize $ bitCoerce @_ @(Unsigned (CLogWZ 2 n 0)) a++instance (KnownNat n, KnownNat m) => MaybeNumConvertCanonical (Index n) (Signed m) where+ maybeNumConvertCanonical !a = maybeNumConvertCanonical $ bitCoerce @_ @(Unsigned (CLogWZ 2 n 0)) a++instance (KnownNat n, KnownNat m) => MaybeNumConvertCanonical (Index n) (BitVector m) where+ maybeNumConvertCanonical !a = maybeResize $ pack a++instance (KnownNat n, KnownNat m) => MaybeNumConvertCanonical (Unsigned n) (Index m) where+ maybeNumConvertCanonical !a = case natToInteger @m of+ 0 -> Nothing+ _ -> maybeResize $ bitCoerce @_ @(Index (2 ^ n)) a++instance (KnownNat n, KnownNat m) => MaybeNumConvertCanonical (Unsigned n) (Unsigned m) where+ maybeNumConvertCanonical !a = maybeResize a++instance (KnownNat n, KnownNat m) => MaybeNumConvertCanonical (Unsigned n) (Signed m) where+ maybeNumConvertCanonical !a = maybeResize $ bitCoerce @(Unsigned (n + 1)) $ extend a++instance (KnownNat n, KnownNat m) => MaybeNumConvertCanonical (Unsigned n) (BitVector m) where+ maybeNumConvertCanonical !a = maybeResize $ pack a++instance (KnownNat n, KnownNat m) => MaybeNumConvertCanonical (Signed n) (Index m) where+ maybeNumConvertCanonical n = case natToInteger @m of+ 0 -> Nothing+ _ | n < 0 -> Nothing+ | otherwise -> maybeResize (bitCoerce @_ @(Index (2 ^ n)) (resize n))++instance (KnownNat n, KnownNat m) => MaybeNumConvertCanonical (Signed n) (Unsigned m) where+ maybeNumConvertCanonical n+ | n < 0 = Nothing+ | otherwise = maybeResize (bitCoerce @(Signed (n + 1)) (extend n))++instance (KnownNat n, KnownNat m) => MaybeNumConvertCanonical (Signed n) (Signed m) where+ maybeNumConvertCanonical !a = maybeResize a++instance (KnownNat n, KnownNat m) => MaybeNumConvertCanonical (Signed n) (BitVector m) where+ maybeNumConvertCanonical n+ | n < 0 = Nothing+ | otherwise = maybeResize (pack @(Signed (n + 1)) (extend n))++instance (KnownNat n, KnownNat m) => MaybeNumConvertCanonical (BitVector n) (Index m) where+ maybeNumConvertCanonical !a = case natToInteger @m of+ 0 -> Nothing+ _ -> maybeResize $ unpack @(Index (2 ^ n)) a++instance (KnownNat n, KnownNat m) => MaybeNumConvertCanonical (BitVector n) (Unsigned m) where+ maybeNumConvertCanonical !a = maybeResize $ unpack @(Unsigned n) a++instance (KnownNat n, KnownNat m) => MaybeNumConvertCanonical (BitVector n) (Signed m) where+ maybeNumConvertCanonical !a = maybeResize $ unpack @(Signed (n + 1)) $ extend a++instance (KnownNat n, KnownNat m) => MaybeNumConvertCanonical (BitVector n) (BitVector m) where+ maybeNumConvertCanonical !a = maybeResize a
+ src/Clash/Class/NumConvert/Internal/NumConvert.hs view
@@ -0,0 +1,228 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_GHC -fplugin=GHC.TypeLits.KnownNat.Solver #-}+{-# OPTIONS_HADDOCK hide #-}++#include "MachDeps.h"++{- |+Copyright : (C) 2025 , Martijn Bastiaan+ 2025-2026, QBayLogic B.V.+License : BSD2 (see the file LICENSE)+Maintainer : QBayLogic B.V. <devops@qbaylogic.com>+-}+module Clash.Class.NumConvert.Internal.NumConvert where++import Prelude++import Clash.Class.BitPack+import Clash.Class.NumConvert.Internal.Canonical+import Clash.Class.Resize+import Clash.Sized.BitVector+import Clash.Sized.Index+import Clash.Sized.Signed+import Clash.Sized.Unsigned++import GHC.TypeLits (KnownNat, type (+), type (<=), type (^))+import GHC.TypeLits.Extra (CLogWZ)++import Data.Int (Int16, Int32, Int64, Int8)+import Data.Word (Word16, Word32, Word64, Word8)++{- $setup+>>> import Clash.Prelude+>>> import Clash.Class.NumConvert+>>> import Data.Word+>>> import Data.Int+-}++{- | Internal class for concrete conversions. This class is used internally by+'NumConvert' and should not be used directly. Use 'NumConvert' instead.++If you want to provide an instance for your own type, please only make an+instance for a direct mapping from and to Clash types and tell the instance+what Clash type it corresponds to. For example, implementing 'Int16' looks like:++> instance NumConvertCanonical Int16 (Signed 16) where+> numConvertCanonical = bitCoerce+>+> instance NumConvertCanonical (Signed 16) Int16 where+> numConvertCanonical = bitCoerce+>+> type instance Canonical Int16 = Signed 16++By doing this, your type will be convertable from and to any other type. For+example:++>>> numConvert (10 :: Int16) :: Int32+10+>>> numConvert (15 :: Signed 8) :: Int16+15+-}+class NumConvertCanonical a b where+ numConvertCanonical :: a -> b++{- | Conversions that are, based on their types, guaranteed to succeed. A+successful conversion retains the numerical value interpretation of the source+type in the target type and does not produce errors.++== __Laws__+A conversion is successful if a round trip conversion is lossless. I.e.,++> Just x == maybeNumConvert (numConvert @a @b x)++for all values @x@ of type @a@. It should also preserve the numerical value+interpretation of the bits. For types that have an @Integral@ instance, this+intuition is captured by:++> toInteger x == toInteger (numConvert @a @b x)++Instances should make sure their constraints are as \"tight\" as possible. I.e.,+if an instance's constraints cannot be satisfied, then for the same types+'Clash.Class.NumConvert.maybeNumConvert' should return 'Nothing' for one or more+values in the domain of the source type @a@:++> L.any isNothing (L.map (maybeNumConvert @a @b) [minBound ..])++All implementations should be total, i.e., they should not produce \"bottoms\".++Additionally, any implementation should be translatable to synthesizable HDL.+-}+type NumConvert a b =+ ( NumConvertCanonical a (Canonical a)+ , NumConvertCanonical (Canonical a) (Canonical b)+ , NumConvertCanonical (Canonical b) b+ )++{- | Convert a supplied value of type @a@ to a value of type @b@. The conversion+is guaranteed to succeed.++>>> numConvert (3 :: Index 8) :: Unsigned 8+3++The following will fail with a type error, as we cannot prove that all values+of @Index 8@ can be represented by an @Unsigned 2@:++>>> numConvert (3 :: Index 8) :: Unsigned 2+...++For the time being, if the input is an 'Clash.XException.XException', then+the output is too. This property might be relaxed in the future.+-}+numConvert :: forall a b. NumConvert a b => a -> b+numConvert =+ numConvertCanonical @(Canonical b) @b+ . numConvertCanonical @(Canonical a) @(Canonical b)+ . numConvertCanonical @a @(Canonical a)++instance (KnownNat n, KnownNat m, n <= m) => NumConvertCanonical (Index n) (Index m) where+ numConvertCanonical = resize++instance (KnownNat n, KnownNat m, n <= 2 ^ m) => NumConvertCanonical (Index n) (Unsigned m) where+ numConvertCanonical !a = resize $ bitCoerce a++{- | Note: Conversion from @Index 1@ to @Signed 0@ is lossless, but not within the+constraints of the instance.+-}+instance (KnownNat n, KnownNat m, CLogWZ 2 n 0 + 1 <= m) => NumConvertCanonical (Index n) (Signed m) where+ numConvertCanonical !a = numConvertCanonical $ bitCoerce @_ @(Unsigned (CLogWZ 2 n 0)) a++instance (KnownNat n, KnownNat m, n <= 2 ^ m) => NumConvertCanonical (Index n) (BitVector m) where+ numConvertCanonical !a = resize $ pack a++instance (KnownNat n, KnownNat m, 2 ^ n <= m) => NumConvertCanonical (Unsigned n) (Index m) where+ numConvertCanonical !a = bitCoerce $ resize a++instance (KnownNat n, KnownNat m, n <= m) => NumConvertCanonical (Unsigned n) (Unsigned m) where+ numConvertCanonical = resize++{- | Note: Conversion from @Unsigned 0@ to @Signed 0@ is lossless, but not within the+constraints of the instance.+-}+instance (KnownNat n, KnownNat m, n + 1 <= m) => NumConvertCanonical (Unsigned n) (Signed m) where+ numConvertCanonical !a = bitCoerce $ resize a++instance (KnownNat n, KnownNat m, n <= m) => NumConvertCanonical (Unsigned n) (BitVector m) where+ numConvertCanonical !a = resize $ pack a++instance (KnownNat n, KnownNat m, n <= m) => NumConvertCanonical (Signed n) (Signed m) where+ numConvertCanonical !a = resize a++instance (KnownNat n, KnownNat m, 2 ^ n <= m) => NumConvertCanonical (BitVector n) (Index m) where+ numConvertCanonical = unpack . resize++instance (KnownNat n, KnownNat m, n <= m) => NumConvertCanonical (BitVector n) (Unsigned m) where+ numConvertCanonical = unpack . resize++{- | Note: Conversion from @BitVector 0@ to @Signed 0@ is lossless, but not within the+constraints of the instance.+-}+instance (KnownNat n, KnownNat m, n + 1 <= m) => NumConvertCanonical (BitVector n) (Signed m) where+ numConvertCanonical = unpack . resize++instance (KnownNat n, KnownNat m, n <= m) => NumConvertCanonical (BitVector n) (BitVector m) where+ numConvertCanonical = resize++-- Concrete bidirectional instances for Word types+instance NumConvertCanonical Word (Unsigned WORD_SIZE_IN_BITS) where+ numConvertCanonical = bitCoerce+instance NumConvertCanonical (Unsigned WORD_SIZE_IN_BITS) Word where+ numConvertCanonical = bitCoerce++instance NumConvertCanonical Word64 (Unsigned 64) where+ numConvertCanonical = bitCoerce+instance NumConvertCanonical (Unsigned 64) Word64 where+ numConvertCanonical = bitCoerce++instance NumConvertCanonical Word32 (Unsigned 32) where+ numConvertCanonical = bitCoerce+instance NumConvertCanonical (Unsigned 32) Word32 where+ numConvertCanonical = bitCoerce++instance NumConvertCanonical Word16 (Unsigned 16) where+ numConvertCanonical = bitCoerce+instance NumConvertCanonical (Unsigned 16) Word16 where+ numConvertCanonical = bitCoerce++instance NumConvertCanonical Word8 (Unsigned 8) where+ numConvertCanonical = bitCoerce+instance NumConvertCanonical (Unsigned 8) Word8 where+ numConvertCanonical = bitCoerce++-- Concrete bidirectional instances for Int types+instance NumConvertCanonical Int (Signed WORD_SIZE_IN_BITS) where+ numConvertCanonical = bitCoerce+instance NumConvertCanonical (Signed WORD_SIZE_IN_BITS) Int where+ numConvertCanonical = bitCoerce++instance NumConvertCanonical Int64 (Signed 64) where+ numConvertCanonical = bitCoerce+instance NumConvertCanonical (Signed 64) Int64 where+ numConvertCanonical = bitCoerce++instance NumConvertCanonical Int32 (Signed 32) where+ numConvertCanonical = bitCoerce+instance NumConvertCanonical (Signed 32) Int32 where+ numConvertCanonical = bitCoerce++instance NumConvertCanonical Int16 (Signed 16) where+ numConvertCanonical = bitCoerce+instance NumConvertCanonical (Signed 16) Int16 where+ numConvertCanonical = bitCoerce++instance NumConvertCanonical Int8 (Signed 8) where+ numConvertCanonical = bitCoerce+instance NumConvertCanonical (Signed 8) Int8 where+ numConvertCanonical = bitCoerce++-- Concrete bidirectional instances for Bit+instance NumConvertCanonical Bit (BitVector 1) where+ numConvertCanonical = pack+instance NumConvertCanonical (BitVector 1) Bit where+ numConvertCanonical = unpack
src/Clash/Class/Resize.hs view
@@ -6,7 +6,8 @@ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> -} -{-# LANGUAGE NoGeneralizedNewtypeDeriving #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE MonoLocalBinds #-} {-# LANGUAGE Safe #-} @@ -20,6 +21,8 @@ , checkedResize , checkedFromIntegral , checkedTruncateB+ , maybeResize+ , maybeTruncateB ) where import Data.Kind (Type)@@ -27,8 +30,11 @@ import GHC.Stack (HasCallStack) import GHC.TypeLits (Nat, KnownNat, type (+)) +import Clash.Magic (clashSimulation) import Clash.Sized.Internal (formatRange) +import GHC.TypeLits (OrderingI(EQI, GTI), cmpNat)+ -- | Coerce a value to be represented by a different number of bits class Resize (f :: Nat -> Type) where -- | A sign-preserving resize operation@@ -54,20 +60,21 @@ truncateB :: KnownNat a => f (a + b) -> f a -- | Helper function of 'checkedFromIntegral', 'checkedResize' and 'checkedTruncateB'-checkIntegral ::+checkIntegralSimOnly :: forall a b. HasCallStack => (Integral a, Integral b, Bounded b) => Proxy b ->- a -> ()-checkIntegral Proxy v =- if toInteger v > toInteger (maxBound @b)- || toInteger v < toInteger (minBound @b) then+ a -> a+checkIntegralSimOnly Proxy v =+ if clashSimulation+ && (toInteger v > toInteger (maxBound @b)+ || toInteger v < toInteger (minBound @b)) then error $ "Given integral " <> show (toInteger v) <> " is out of bounds for" <> " target type. Bounds of target type are: " <> formatRange (toInteger (minBound @b)) (toInteger (maxBound @b)) <> "." else- ()+ v -- | Like 'fromIntegral', but errors if /a/ is out of bounds for /b/. Useful when -- you "know" /a/ can't be out of bounds, but would like to have your assumptions@@ -83,8 +90,7 @@ HasCallStack => (Integral a, Integral b, Bounded b) => a -> b-checkedFromIntegral v =- checkIntegral (Proxy @b) v `seq` fromIntegral v+checkedFromIntegral v = fromIntegral (checkIntegralSimOnly (Proxy @b) v) -- | Like 'resize', but errors if /f a/ is out of bounds for /f b/. Useful when -- you "know" /f a/ can't be out of bounds, but would like to have your@@ -99,8 +105,7 @@ , KnownNat a, Integral (f a) , KnownNat b, Integral (f b), Bounded (f b) ) => f a -> f b-checkedResize v =- checkIntegral (Proxy @(f b)) v `seq` resize v+checkedResize v = resize (checkIntegralSimOnly (Proxy @(f b)) v) -- | Like 'truncateB', but errors if /f (a + b)/ is out of bounds for /f a/. Useful -- when you "know" /f (a + b)/ can't be out of bounds, but would like to have your@@ -115,5 +120,32 @@ , KnownNat b, Integral (f (a + b)) , KnownNat a, Integral (f a), Bounded (f a) ) => f (a + b) -> f a-checkedTruncateB v =- checkIntegral (Proxy @(f a)) v `seq` truncateB v+checkedTruncateB v = truncateB (checkIntegralSimOnly (Proxy @(f a)) v)++-- | Like 'resize', but returns 'Nothing' if the argument is out of bounds for+-- the result type.+maybeResize ::+ forall a b f.+ ( Resize f+ , KnownNat a, Integral (f a)+ , KnownNat b, Integral (f b), Bounded (f b) ) =>+ f a -> Maybe (f b)+maybeResize v =+ case Proxy @a `cmpNat` Proxy @b of+ GTI | v > resize (maxBound @(f b)) -> Nothing+ GTI | v < resize (minBound @(f b)) -> Nothing+ EQI -> Just v+ _ -> Just (resize v)++-- | Like 'truncateB', but returns 'Nothing' if the argument is out of bounds for+-- the result type.+maybeTruncateB ::+ forall a b f.+ ( Resize f+ , KnownNat b, Integral (f (a + b))+ , KnownNat a, Integral (f a), Bounded (f a) ) =>+ f (a + b) -> Maybe (f a)+maybeTruncateB v+ | v > resize (maxBound @(f a)) = Nothing+ | v < resize (minBound @(f a)) = Nothing+ | otherwise = Just (truncateB v)
src/Clash/Clocks/Internal.hs view
@@ -53,7 +53,7 @@ clocks (Clock _ Nothing) $(varP rst) = $funcImpl clocks _ _ = error "clocks: dynamic clocks unsupported"- {-# CLASH_OPAQUE clocks #-}+ {-# OPAQUE clocks #-} |] where clkTyVar m = varT $ mkName $ "c" <> show m
src/Clash/Explicit/BlockRam.hs view
@@ -2,7 +2,7 @@ Copyright : (C) 2013-2016, University of Twente, 2016-2017, Myrtle Software Ltd, 2017 , Google Inc.,- 2021-2023, QBayLogic B.V.,+ 2021-2026, QBayLogic B.V., 2022 , Google Inc., 2024 , Alex Mason, License : BSD2 (see the file LICENSE)@@ -406,6 +406,8 @@ -- as to why we need this. {-# OPTIONS_GHC -fno-cpr-anal #-} +{-# OPTIONS_GHC -fconstraint-solver-iterations=12 #-}+ module Clash.Explicit.BlockRam ( -- * Block RAM synchronized to an arbitrary clock blockRam@@ -429,6 +431,7 @@ import Clash.HaskellPrelude +import Control.DeepSeq (NFData) import Control.Exception (catch, throw) import Control.Monad (forM_) import Control.Monad.ST (ST, runST)@@ -441,17 +444,17 @@ import GHC.Arr (STArray, unsafeReadSTArray, unsafeWriteSTArray) import GHC.Generics (Generic) import GHC.Stack (HasCallStack, withFrozenCallStack)-import GHC.TypeLits (KnownNat, type (^), type (<=))+import GHC.TypeLits (KnownNat, type (^)) import Unsafe.Coerce (unsafeCoerce) import Clash.Annotations.Primitive (Primitive(InlineYamlPrimitive), HDL(..), hasBlackBox) import Clash.Class.AutoReg (AutoReg(autoReg))-import Clash.Class.BitPack (bitToBool, msb)+import Clash.Class.BitPack (BitPack, bitToBool, msb) import Clash.Class.Num (SaturationMode(SatBound), satSucc) import Clash.Explicit.BlockRam.Model (TdpbramModelConfig(..), tdpbramModel) import Clash.Explicit.Signal (KnownDomain, Enable, register, fromEnable, andEnable)-import Clash.Promoted.Nat (SNat(..))+import Clash.Promoted.Nat (SNat(..), UNat(..), toUNat) import Clash.Signal.Bundle (unbundle) import Clash.Signal.Internal (Clock(..), Reset, Signal (..), invertReset, (.&&.), mux)@@ -460,7 +463,7 @@ import Clash.Sized.Unsigned (Unsigned) import Clash.Sized.Vector (Vec, replicate, iterateI) import Clash.XException- (maybeIsX, NFDataX(deepErrorX), defaultSeqX, fromJustX, undefined,+ (ShowX, maybeIsX, NFDataX(deepErrorX), defaultSeqX, fromJustX, undefined, XException (..), seqX, errorX) import Clash.XException.MaybeX (MaybeX(..), andX) @@ -854,9 +857,9 @@ (blockRam clk en cnt rd wrM) {-# INLINE blockRamPow2 #-} -data ResetStrategy (r :: Bool) where- ClearOnReset :: ResetStrategy 'True- NoClearOnReset :: ResetStrategy 'False+data ResetStrategy (r :: Bool) a where+ ClearOnReset :: a -> ResetStrategy 'True a+ NoClearOnReset :: ResetStrategy 'False a -- | A version of 'blockRam' that has no default values set. May be cleared to -- an arbitrary state using a reset function.@@ -867,7 +870,7 @@ , NFDataX a , Enum addr , NFDataX addr- , 1 <= n )+ ) => Clock dom -- ^ 'Clock' to synchronize to -> Reset dom@@ -875,25 +878,31 @@ -- for the BRAM to be reset to its initial state. -> Enable dom -- ^ 'Enable' line- -> ResetStrategy r+ -> ResetStrategy r (Index n -> a) -- ^ Whether to clear BRAM on asserted reset ('ClearOnReset') or -- not ('NoClearOnReset'). The reset needs to be asserted for at least /n/ -- cycles to clear the BRAM. -> SNat n -- ^ Number of elements in BRAM- -> (Index n -> a)- -- ^ If applicable (see 'ResetStrategy' argument), reset BRAM using this function -> Signal dom addr -- ^ Read address @r@ -> Signal dom (Maybe (addr, a)) -- ^ (write address @w@, value to write) -> Signal dom a -- ^ Value of the BRAM at address @r@ from the previous clock cycle-blockRamU clk rst0 en rstStrategy n@SNat initF rd0 mw0 =- case rstStrategy of- ClearOnReset ->+blockRamU clk rst0 en rstStrategy n@SNat rd0 mw0 = case toUNat n of+ UZero -> case rstStrategy of+ ClearOnReset f -> pure $ f undefined+ NoClearOnReset -> pure undefined+ USucc _ -> case rstStrategy of+ ClearOnReset initF -> -- Use reset infrastructure blockRamU# clk en n rd1 we1 wa1 w1+ where+ rd1 = mux rstBool 0 (fromEnum <$> rd0)+ we1 = mux rstBool (pure True) we0+ wa1 = mux rstBool (fromInteger . toInteger <$> waCounter) (fromEnum <$> wa0)+ w1 = mux rstBool (initF <$> waCounter) w0 NoClearOnReset -> -- Ignore reset infrastructure, pass values unchanged blockRamU# clk en n@@ -912,11 +921,6 @@ w0 = snd . fromJustX <$> mw0 we0 = isJust <$> mw0 - rd1 = mux rstBool 0 (fromEnum <$> rd0)- we1 = mux rstBool (pure True) we0- wa1 = mux rstBool (fromInteger . toInteger <$> waCounter) (fromEnum <$> wa0)- w1 = mux rstBool (initF <$> waCounter) w0- -- | blockRAMU primitive blockRamU# :: forall n dom a@@ -947,8 +951,7 @@ (CV.map (\i -> deepErrorX $ "Initial value at index " <> show i <> " undefined.") (iterateI @n succ (0 :: Int)))--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE blockRamU# #-}+{-# OPAQUE blockRamU# #-} {-# ANN blockRamU# hasBlackBox #-} -- | A version of 'blockRam' that is initialized with the same value on all@@ -960,7 +963,7 @@ , NFDataX a , Enum addr , NFDataX addr- , 1 <= n )+ ) => Clock dom -- ^ 'Clock' to synchronize to -> Reset dom@@ -968,7 +971,7 @@ -- for the BRAM to be reset to its initial state. -> Enable dom -- ^ 'Enable' line- -> ResetStrategy r+ -> ResetStrategy r () -- ^ Whether to clear BRAM on asserted reset ('ClearOnReset') or -- not ('NoClearOnReset'). The reset needs to be asserted for at least /n/ -- cycles to clear the BRAM.@@ -982,9 +985,10 @@ -- ^ (write address @w@, value to write) -> Signal dom a -- ^ Value of the BRAM at address @r@ from the previous clock cycle-blockRam1 clk rst0 en rstStrategy n@SNat a rd0 mw0 =- case rstStrategy of- ClearOnReset ->+blockRam1 clk rst0 en rstStrategy n@SNat a rd0 mw0 = case toUNat n of+ UZero -> pure a+ USucc _ -> case rstStrategy of+ ClearOnReset () -> -- Use reset infrastructure blockRam1# clk en n a rd1 we1 wa1 w1 NoClearOnReset ->@@ -1037,8 +1041,7 @@ blockRam1# clk en n a = -- TODO: Generalize to single BRAM primitive taking an initialization function blockRam# clk en (replicate n a)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE blockRam1# #-}+{-# OPAQUE blockRam1# #-} {-# ANN blockRam1# hasBlackBox #-} -- | blockRAM primitive@@ -1135,8 +1138,7 @@ {-# INLINE safeUpdate #-} blockRam# _ _ _ = error "blockRam#: dynamic clocks not supported" {-# ANN blockRam# hasBlackBox #-}--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE blockRam# #-}+{-# OPAQUE blockRam# #-} -- | Create a read-after-write block RAM from a read-before-write one readNew@@ -1170,7 +1172,7 @@ -- ^ Write data to address | RamNoOp -- ^ No operation- deriving (Generic, NFDataX, Show)+ deriving (Eq, Generic, NFData, NFDataX, Show, ShowX, BitPack) instance (AutoReg a, KnownNat n) => AutoReg (RamOp n a) where autoReg clk rst en initVal input =@@ -1278,11 +1280,9 @@ -- into its own module / architecture. trueDualPortBlockRamWrapper clkA enA weA addrA datA clkB enB weB addrB datB = trueDualPortBlockRam# clkA enA weA addrA datA clkB enB weB addrB datB--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE trueDualPortBlockRamWrapper #-}+{-# OPAQUE trueDualPortBlockRamWrapper #-} --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE trueDualPortBlockRam# #-}+{-# OPAQUE trueDualPortBlockRam# #-} {-# ANN trueDualPortBlockRam# hasBlackBox #-} {-# ANN trueDualPortBlockRam# ( let
src/Clash/Explicit/BlockRam/Blob.hs view
@@ -233,8 +233,7 @@ in forM_ [0..(szI-1)] (\j -> unsafeWriteSTArray s j d) {-# INLINE safeUpdate #-} {-# ANN blockRamBlob# hasBlackBox #-}--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE blockRamBlob# #-}+{-# OPAQUE blockRamBlob# #-} {- | Create a 'MemBlob' binding from a list of values
src/Clash/Explicit/BlockRam/File.hs view
@@ -423,8 +423,7 @@ parseBV' = fmap fst . listToMaybe . readInt 2 (`elem` "01") digitToInt blockRamFile# _ _ _ _ = error "blockRamFile#: dynamic clocks not supported" --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE blockRamFile# #-}+{-# OPAQUE blockRamFile# #-} {-# ANN blockRamFile# hasBlackBox #-} -- | __NB__: Not synthesizable@@ -435,5 +434,4 @@ Just i -> fromInteger i Nothing -> error ("Failed to parse: " ++ s) parseBV' = fmap fst . listToMaybe . readInt 2 (`elem` "01") digitToInt--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE initMem #-}+{-# OPAQUE initMem #-}
src/Clash/Explicit/BlockRam/Model.hs view
@@ -14,9 +14,6 @@ module Clash.Explicit.BlockRam.Model where -#if !MIN_VERSION_base(4,18,0)-import Control.Applicative (liftA2)-#endif import Control.Exception (throw) import Data.Sequence (Seq) import GHC.Stack (HasCallStack)
src/Clash/Explicit/DDR.hs view
@@ -21,21 +21,28 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TemplateHaskellQuotes #-} {-# LANGUAGE TypeFamilies #-} module Clash.Explicit.DDR ( ddrIn , ddrOut+ , ddrForwardClock -- * Internal , ddrIn# , ddrOut#+ , ddrForwardClock# ) where +import Data.List.Infinite (Infinite(..), (...))+import Data.String.Interpolate (__i) import GHC.Stack (HasCallStack, withFrozenCallStack)+import Unsafe.Coerce (unsafeCoerce) -import Clash.Annotations.Primitive (hasBlackBox)-import Clash.Explicit.Prelude+import Clash.Annotations.Primitive (hasBlackBox, Primitive(..), HDL(..))+import Clash.Explicit.Prelude hiding ((:<)) import Clash.Signal.Internal {- $setup@@ -43,9 +50,9 @@ >>> import Clash.Explicit.Prelude >>> import Clash.Explicit.DDR >>> :{-type Fast = ("Fast" :: Domain)-instance KnownDomain "Fast" where- type KnownConf "Fast" = 'DomainConfiguration "Fast" 5000 'Rising 'Asynchronous 'Defined 'ActiveHigh+type DDR = "DDR" :: Domain+instance KnownDomain "DDR" where+ type KnownConf "DDR" = 'DomainConfiguration "DDR" 5000 'Rising 'Asynchronous 'Defined 'ActiveHigh knownDomain = SDomainConfiguration SSymbol SNat SRising SAsynchronous SDefined SActiveHigh :} @@ -69,21 +76,23 @@ -- in on the rising clock edge. For a domain with the falling edge as the active -- edge, this is the other way around, but @o0@ still comes before @o1@ in time. ----- >>> sampleN 5 $ ddrIn systemClockGen systemResetGen enableGen (-1,-2,-3) (fromList [0..10] :: Signal Fast Int)+-- >>> sampleN 5 $ ddrIn @Int @System @DDR clockGen resetGen enableGen (-1,-2,-3) (fromList [0..10]) -- [(-1,-2),(-1,-2),(-3,2),(3,4),(5,6)] ddrIn- :: ( HasCallStack- , NFDataX a- , KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity)- , KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) edge reset init polarity) )- => Clock slow- -> Reset slow- -> Enable slow+ :: forall a dom domDDR+ . HasCallStack+ => NFDataX a+ => KnownDomain dom+ => KnownDomain domDDR+ => DomainPeriod dom ~ (2 * DomainPeriod domDDR)+ => Clock dom+ -> Reset dom+ -> Enable dom -> (a, a, a) -- ^ Reset values- -> Signal fast a+ -> Signal domDDR a -- ^ DDR input signal- -> Signal slow (a, a)+ -> Signal dom (a, a) -- ^ Normal speed output pair @(o0, o1)@ ddrIn clk rst en (i0,i1,i2) = withFrozenCallStack $ ddrIn# clk rst en i0 i1 i2@@ -92,21 +101,22 @@ -- For details about all the seq's en seqX's -- see the [Note: register strictness annotations] in Clash.Signal.Internal ddrIn#- :: forall a slow fast fPeriod polarity edge reset init- . ( HasCallStack- , NFDataX a- , KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity)- , KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) edge reset init polarity) )- => Clock slow- -> Reset slow- -> Enable slow+ :: forall a dom domDDR+ . HasCallStack+ => NFDataX a+ => KnownDomain dom+ => KnownDomain domDDR+ => DomainPeriod dom ~ (2 * DomainPeriod domDDR)+ => Clock dom+ -> Reset dom+ -> Enable dom -> a -> a -> a- -> Signal fast a- -> Signal slow (a,a)+ -> Signal domDDR a+ -> Signal dom (a,a) ddrIn# (Clock _ Nothing) (unsafeToActiveHigh -> hRst) (fromEnable -> ena) i0 i1 i2 =- case resetKind @fast of+ case resetKind @domDDR of SAsynchronous -> goAsync ( deepErrorX "ddrIn: initial value 0 undefined"@@ -124,10 +134,10 @@ where goSync :: (a, a, a)- -> Signal slow Bool- -> Signal slow Bool- -> Signal fast a- -> Signal slow (a,a)+ -> Signal dom Bool+ -> Signal dom Bool+ -> Signal domDDR a+ -> Signal dom (a,a) goSync (o0,o1,o2) rt@(~(r :- rs)) ~(e :- es) as@(~(x0 :- x1 :- xs)) = let (o0',o1',o2') = if r then (i0,i1,i2) else (o2,x0,x1) in o0 `seqX` o1 `seqX` (o0,o1)@@ -136,10 +146,10 @@ goAsync :: (a, a, a)- -> Signal slow Bool- -> Signal slow Bool- -> Signal fast a- -> Signal slow (a, a)+ -> Signal dom Bool+ -> Signal dom Bool+ -> Signal domDDR a+ -> Signal dom (a, a) goAsync (o0,o1,o2) ~(r :- rs) ~(e :- es) as@(~(x0 :- x1 :- xs)) = let (o0',o1',o2',o3',o4') = if r then (i0,i1,i0,i1,i2) else (o0,o1,o2,x0,x1) in o0' `seqX` o1' `seqX` (o0',o1')@@ -148,8 +158,7 @@ ddrIn# _ _ _ _ _ _ = error "ddrIn#: dynamic clocks not supported"--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE ddrIn# #-}+{-# OPAQUE ddrIn# #-} {-# ANN ddrIn# hasBlackBox #-} -- | DDR output primitive@@ -170,38 +179,42 @@ -- active edge, this is the other way around, but @i0@ still comes before @i1@ -- in time. ----- >>> sampleN 7 (ddrOut systemClockGen systemResetGen enableGen (-1) (fromList [(0,1),(2,3),(4,5)]) :: Signal Fast Int)+-- >>> sampleN 7 (ddrOut @Int @System @DDR clockGen resetGen enableGen (-1) (fromList [(0,1),(2,3),(4,5)])) -- [-1,-1,-1,2,3,4,5] ddrOut- :: ( HasCallStack- , NFDataX a- , KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity)- , KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) edge reset init polarity) )- => Clock slow- -> Reset slow- -> Enable slow+ :: forall a dom domDDR+ . HasCallStack+ => NFDataX a+ => KnownDomain dom+ => KnownDomain domDDR+ => DomainPeriod dom ~ (2 * DomainPeriod domDDR)+ => Clock dom+ -> Reset dom+ -> Enable dom -> a -- ^ Reset value- -> Signal slow (a, a)+ -> Signal dom (a, a) -- ^ Normal speed input pair @(i0, i1)@- -> Signal fast a+ -> Signal domDDR a -- ^ DDR output signal ddrOut clk rst en i0 = uncurry (withFrozenCallStack $ ddrOut# clk rst en i0) . unbundle ddrOut#- :: ( HasCallStack- , NFDataX a- , KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity)- , KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) edge reset init polarity) )- => Clock slow- -> Reset slow- -> Enable slow+ :: forall a dom domDDR+ . HasCallStack+ => NFDataX a+ => KnownDomain dom+ => KnownDomain domDDR+ => DomainPeriod dom ~ (2 * DomainPeriod domDDR)+ => Clock dom+ -> Reset dom+ -> Enable dom -> a- -> Signal slow a- -> Signal slow a- -> Signal fast a+ -> Signal dom a+ -> Signal dom a+ -> Signal domDDR a ddrOut# clk rst en i0 xs ys = -- We only observe one reset value, because when the mux switches on the -- next clock level, the second register will already be outputting its@@ -213,6 +226,117 @@ xs' = register# clk rst en (errorX "ddrOut: unreachable error") i0 xs ys' = register# clk rst en (deepErrorX "ddrOut: initial value undefined") i0 ys zipSig (a :- as) (b :- bs) = a :- b :- zipSig as bs--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE ddrOut# #-}+{-# OPAQUE ddrOut# #-} {-# ANN ddrOut# hasBlackBox #-}++-- | Use a DDR output primitive to forward a clock to an output pin+--+-- This function allows outputting a clock signal on a DDR-capable output pin.+-- As with the DDR output primitive itself, the created clock cannot be used+-- internally in the design.+--+-- The @ddrOut@ primitive passed in will always have its enable asserted. If the+-- @Enable@ input of @ddrForwardClock@ is deasserted, the data inputs of the+-- @ddrOut@ primitive will switch to achieve the desired output signal. This is+-- because the behavior of the enable input of the DDR primitive differs between+-- vendor-specific primitives.+--+-- The @Reset@ input of this function is passed on to the @ddrOut@ primitive and+-- not otherwise used by @ddrForwardClock@.+--+-- With the @phase@ argument, the phase relation between input and output clock+-- can be defined. With the argument @Nothing@, the clocks are in phase: the+-- active edge of the output clock is on the active edge of the input clock,+-- even if the domains differ on what the active edge is.+--+-- With the @idle@ argument, the output level when the @Enable@ input is+-- deasserted can be defined. With @Nothing@, it will be 0 for a clock with the+-- rising edge as the active edge, and 1 for a clock with the falling edge as+-- the active edge.+--+-- __NB__: The deassertion of the @Enable@ input or the assertion of the @Reset@+-- input is not faithfully simulated in Haskell simulation: Haskell simulation+-- of a Clash design has clocks that always run. The generated HDL will actually+-- output an idle state when @Enable@ is deasserted (and the reset depends on+-- the @ddrOut@ primitive used).+ddrForwardClock+ :: forall domDDR domOut domIn+ . KnownDomain domOut+ => DomainPeriod domIn ~ DomainPeriod domOut+ => DomainPeriod domIn ~ (2 * DomainPeriod domDDR)+ => Clock domIn+ -> Reset domIn+ -> Enable domIn+ -> Maybe Bit+ -- ^ @idle@: Output value when @Enable@ is deasserted+ -> Maybe Bit+ -- ^ @phase@: Value to output at active edge of incoming clock+ -> (Clock domIn -> Reset domIn -> Enable domIn -> Signal domIn (Bit, Bit)+ -> Signal domDDR Bit)+ -- ^ @ddrOut@ primitive to use+ -> Clock domOut+ddrForwardClock clk rst en idle phase oddr =+ ddrForwardClock# clk $ oddr clk rst enableGen ins+ where+ ins =+ mux+ (fromEnable en)+ (pure (activeLevel, complement activeLevel))+ (pure (idleLevel, idleLevel))+ activeLevel =+ case phase of+ Nothing ->+ case activeEdge @domOut of+ SRising -> 1+ SFalling -> 0+ Just x -> x+ idleLevel =+ case idle of+ Nothing ->+ case activeEdge @domOut of+ SRising -> 0+ SFalling -> 1+ Just x -> x++ddrForwardClock#+ :: KnownDomain domOut+ => DomainPeriod domIn ~ DomainPeriod domOut+ => DomainPeriod domIn ~ (2 * DomainPeriod domDDR)+ => Clock domIn+ -> Signal domDDR Bit+ -> Clock domOut+ddrForwardClock# (Clock SSymbol periods) ddrSignal =+ Clock (ddrSignal `seq` SSymbol) (unsafeCoerce periods)+{-# OPAQUE ddrForwardClock# #-}+{-# ANN ddrForwardClock# (+ let+ bbName = show 'ddrForwardClock#+ _knownDomOut+ :< _domInOutPeriod+ :< _domDDRPeriod+ :< _clkIn+ :< ddrSignal+ :< _ = ((0 :: Int)...)+ in InlineYamlPrimitive [VHDL] [__i|+ BlackBox:+ name: #{bbName}+ kind: Expression+ template: ~TYPMO'(~ARG[#{ddrSignal}])+ workInfo: Never+ |]) #-}+{-# ANN ddrForwardClock# (+ let+ bbName = show 'ddrForwardClock#+ _knownDomOut+ :< _domInOutPeriod+ :< _domDDRPeriod+ :< _clkIn+ :< ddrSignal+ :< _ = ((0 :: Int)...)+ in InlineYamlPrimitive [Verilog, SystemVerilog] [__i|+ BlackBox:+ name: #{bbName}+ kind: Expression+ template: ~ARG[#{ddrSignal}]+ workInfo: Never+ |]) #-}
src/Clash/Explicit/Prelude.hs view
@@ -2,7 +2,7 @@ Copyright : (C) 2013-2016, University of Twente, 2017 , Google Inc. 2019 , Myrtle Software Ltd,- 2021-2023, QBayLogic B.V.,+ 2021-2025, QBayLogic B.V., 2022 , Myrtle.ai, License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com>@@ -125,6 +125,11 @@ -- ** Template Haskell , Lift (..) -- ** Type classes+ -- *** Number conversion+ , NumConvert+ , numConvert+ , MaybeNumConvert+ , maybeNumConvert -- *** Clash , module Clash.Class.AutoReg , module Clash.Class.BitPack@@ -134,7 +139,7 @@ -- *** Other , module Control.Applicative , module Data.Bits- , module Data.Default.Class+ , module Data.Default -- ** Exceptions , module Clash.XException -- ** Named types@@ -149,11 +154,9 @@ import Control.Applicative import Data.Bits-import Data.Default.Class+import Data.Default import GHC.TypeLits-#if MIN_VERSION_base(4,18,0) hiding (SNat, SSymbol, fromSNat)-#endif import GHC.TypeLits.Extra import Language.Haskell.TH.Syntax (Lift(..)) import Clash.HaskellPrelude@@ -163,6 +166,7 @@ import Clash.Class.BitPack import Clash.Class.Exp import Clash.Class.Num+import Clash.Class.NumConvert import Clash.Class.Resize import Clash.Magic import Clash.NamedTypes
src/Clash/Explicit/Prelude/Safe.hs view
@@ -117,9 +117,7 @@ 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
src/Clash/Explicit/RAM.hs view
@@ -212,6 +212,5 @@ " not in range [0.." ++ show szI ++ ")")) in d <$ s {-# INLINE safeUpdate #-}--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE asyncRam# #-}+{-# OPAQUE asyncRam# #-} {-# ANN asyncRam# hasBlackBox #-}
src/Clash/Explicit/ROM.hs view
@@ -140,6 +140,5 @@ (deepErrorX ("rom: address " ++ show i ++ " not in range [0.." ++ show szI ++ ")")) {-# INLINE safeAt #-}--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE rom# #-}+{-# OPAQUE rom# #-} {-# ANN rom# hasBlackBox #-}
src/Clash/Explicit/ROM/Blob.hs view
@@ -150,6 +150,5 @@ (deepErrorX ("romBlob: address " ++ show i ++ " not in range [0.." ++ show szI ++ ")")) {-# INLINE safeAt #-}--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE romBlob# #-}+{-# OPAQUE romBlob# #-} {-# ANN romBlob# hasBlackBox #-}
src/Clash/Explicit/ROM/File.hs view
@@ -222,6 +222,5 @@ deepErrorX ("romFile: address " ++ show i ++ " not in range [0.." ++ show szI ++ ")") {-# INLINE safeAt #-}--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE romFile# #-}+{-# OPAQUE romFile# #-} {-# ANN romFile# hasBlackBox #-}
src/Clash/Explicit/Signal.hs view
@@ -3,7 +3,7 @@ 2016-2019, Myrtle Software, 2017-2022, Google Inc. 2020 , Ben Gamari,- 2021-2023, QBayLogic B.V.+ 2021-2025, QBayLogic B.V. License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> @@ -173,12 +173,23 @@ , DomainInitBehavior , DomainResetPolarity -- *** Convenience types #conveniencetypes#- -- **** Simplifying -- $conveniencetypes , HasSynchronousReset , HasAsynchronousReset , HasDefinedInitialValues+ -- **** Time representations+ , Seconds+ , Milliseconds+ , Microseconds+ , Nanoseconds+ , Picoseconds+ -- **** Time conversions+ , DomainToHz+ , HzToPeriod+ , PeriodToHz+ , PeriodToCycles+ , ClockDivider -- ** Default domains , System , XilinxSystem@@ -226,7 +237,9 @@ , register , regMaybe , regEn+ , regEnN , mux+ , apEn -- * Simulation and testbench functions , clockGen , resetGen@@ -265,9 +278,9 @@ , testFor -- * Type classes -- ** 'Eq'-like- , (.==.), (./=.)+ , (.==.), (.==), (==.), (./=.), (./=), (/=.) -- ** 'Ord'-like- , (.<.), (.<=.), (.>=.), (.>.)+ , (.<.), (.<), (<.), (.<=.), (.<=), (<=.), (.>=.), (.>=), (>=.), (.>.), (.>), (>.) -- * Bisignal functions , veryUnsafeToBiSignalIn , readFromBiSignal@@ -289,7 +302,8 @@ import GHC.TypeLits (type (<=)) import Clash.Annotations.Primitive (hasBlackBox)-import Clash.Promoted.Nat (SNat(..), snatToNum)+import Clash.Promoted.Nat+ (SNat(..), SNatLE(..), compareSNat, leToPlus, snatToNum) import Clash.Signal.Bundle (Bundle (..), EmptyTuple(..), TaggedEmptyTuple(..), vecBundle#) import Clash.Signal.BiSignal@@ -346,6 +360,8 @@ {- $conveniencetypes +==== Simplifying+ If you want to write part of your Clash design as domain-polymorphic functions, it can be practical to define a design-wide constraint synonym that captures the characteristics of the clock domains of the design. Such a constraint synonym@@ -503,8 +519,7 @@ ClockA -> go ticks as ClockB -> a :- go ticks ass ClockAB -> go (ClockB:ClockA:ticks) ass--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE unsafeSynchronizer #-}+{-# OPAQUE unsafeSynchronizer #-} {-# ANN unsafeSynchronizer hasBlackBox #-} -- | Same as 'unsafeSynchronizer', but with manually supplied clock periods.@@ -554,8 +569,7 @@ ClockA -> go ticks as ClockB -> a :- go ticks ass ClockAB -> go (ClockB:ClockA:ticks) ass--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE veryUnsafeSynchronizer #-}+{-# OPAQUE veryUnsafeSynchronizer #-} {-# ANN veryUnsafeSynchronizer hasBlackBox #-} -- * Basic circuit functions@@ -746,6 +760,31 @@ register# clk rst (andEnable gen en) initial initial i {-# INLINE regEn #-} +-- | A chain of 'regEn's.+regEnN ::+ forall dom a n.+ (KnownDomain dom, NFDataX a) =>+ -- | Clock+ Clock dom ->+ -- | Reset, 'regEnN' outputs the reset value when the reset value is active+ Reset dom ->+ -- | Global enable+ Enable dom ->+ -- | The number of stored elements+ SNat n ->+ -- | Initial content of all elements in the chain.+ a ->+ -- | The "push next input" indicator+ Signal dom Bool ->+ Signal dom a ->+ Signal dom a+regEnN clk rst gen n@SNat initial en = case compareSNat n (SNat @0) of+ SNatLE -> id+ SNatGT -> leToPlus @1 @n+ $ Clash.Sized.Vector.last+ . Clash.Sized.Vector.generate n (regEn clk rst gen initial en)+{-# INLINE regEnN #-}+ -- * Simulation functions -- | Same as 'simulate', but with the reset line asserted for /n/ cycles. Similar@@ -779,8 +818,7 @@ clk = clockGen en = enableGen out = simulate (f clk rst en) inp--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE simulateWithReset #-}+{-# OPAQUE simulateWithReset #-} -- | Same as 'simulateWithReset', but only sample the first /Int/ output values. simulateWithResetN@@ -886,8 +924,7 @@ sampleWithReset nReset f0 = let f1 = f0 clockGen (resetGenN @dom nReset) enableGen in drop (snatToNum nReset) (sample f1)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE sampleWithReset #-}+{-# OPAQUE sampleWithReset #-} -- | Get a fine list of /m/ samples from a 'Signal', while asserting the reset line -- for /n/ clock cycles. 'sampleWithReset' does not return the first /n/ cycles,
src/Clash/Explicit/Signal/Delayed.hs view
@@ -233,7 +233,7 @@ 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 --- | Tree fold over a 'Vec' of 'DSignal's with a combinatorial function,+-- | Tree fold over a 'Vec' of 'DSignal's with a combinational function, -- and delaying @delay@ cycles after each application. -- Values at times 0..(delay*k)-1 are set to a default. --
src/Clash/Explicit/SimIO.hs view
@@ -45,14 +45,9 @@ where import Control.Monad (when)-#if __GLASGOW_HASKELL__ < 900-import Data.Coerce-#endif import Data.IORef import GHC.TypeLits-#if MIN_VERSION_base(4,18,0) hiding (SNat)-#endif import Prelude hiding (getChar, putChar, getLine) import qualified System.IO as IO import System.IO.Unsafe@@ -68,11 +63,7 @@ -- itself is unlikely to be synthesisable to a digital circuit. -- -- See 'mealyIO' as to its use.-#if __GLASGOW_HASKELL__ >= 900 data SimIO a = SimIO {unSimIO :: !(IO a)}-#else-newtype SimIO a = SimIO {unSimIO :: IO a}-#endif {-# ANN unSimIO hasBlackBox #-} instance Functor SimIO where@@ -80,8 +71,7 @@ fmapSimIO# :: (a -> b) -> SimIO a -> SimIO b fmapSimIO# f (SimIO m) = SimIO (fmap f m)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE fmapSimIO# #-}+{-# OPAQUE fmapSimIO# #-} {-# ANN fmapSimIO# hasBlackBox #-} instance Applicative SimIO where@@ -90,30 +80,20 @@ pureSimIO# :: a -> SimIO a pureSimIO# a = SimIO (pure a)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE pureSimIO# #-}+{-# OPAQUE pureSimIO# #-} {-# ANN pureSimIO# hasBlackBox #-} apSimIO# :: SimIO (a -> b) -> SimIO a -> SimIO b apSimIO# (SimIO f) (SimIO m) = SimIO (f <*> m)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE apSimIO# #-}+{-# OPAQUE apSimIO# #-} {-# ANN apSimIO# hasBlackBox #-} instance Monad SimIO where-#if !MIN_VERSION_base(4,16,0)- return = pureSimIO#-#endif (>>=) = bindSimIO# bindSimIO# :: SimIO a -> (a -> SimIO b) -> SimIO b-#if __GLASGOW_HASKELL__ >= 900 bindSimIO# (SimIO m) k = SimIO (m >>= (\x -> x `seqX` unSimIO (k x)))-#else-bindSimIO# (SimIO m) k = SimIO (m >>= (\x -> x `seqX` coerce k x))-#endif--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE bindSimIO# #-}+{-# OPAQUE bindSimIO# #-} {-# ANN bindSimIO# hasBlackBox #-} -- | Display a string on /stdout/@@ -122,8 +102,7 @@ -- ^ String you want to display -> SimIO () display s = SimIO (putStrLn s)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE display #-}+{-# OPAQUE display #-} {-# ANN display hasBlackBox #-} -- | Finish the simulation with an exit code@@ -132,16 +111,11 @@ -- ^ The exit code you want to return at the end of the simulation -> SimIO a finish i = return (error (show i))--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE finish #-}+{-# OPAQUE finish #-} {-# ANN finish hasBlackBox #-} -- | Mutable reference-#if __GLASGOW_HASKELL__ >= 900 data Reg a = Reg !(IORef a)-#else-newtype Reg a = Reg (IORef a)-#endif -- | Create a new mutable reference with the given starting value reg@@ -149,15 +123,13 @@ -- ^ The starting value -> SimIO (Reg a) reg a = SimIO (Reg <$> newIORef a)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE reg #-}+{-# OPAQUE reg #-} {-# ANN reg hasBlackBox #-} -- | Read value from a mutable reference readReg :: Reg a -> SimIO a readReg (Reg a) = SimIO (readIORef a)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE readReg #-}+{-# OPAQUE readReg #-} {-# ANN readReg hasBlackBox #-} -- | Write new value to the mutable reference@@ -168,16 +140,11 @@ -- ^ The new value -> SimIO () writeReg (Reg r) a = SimIO (writeIORef r a)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE writeReg #-}+{-# OPAQUE writeReg #-} {-# ANN writeReg hasBlackBox #-} -- | File handle-#if __GLASGOW_HASKELL__ >= 900 data File = File !IO.Handle-#else-newtype File = File IO.Handle-#endif -- | Open a file openFile@@ -193,7 +160,6 @@ -- * "w+": Create for update -- * "a+": Append, open or create for update at end-of-file -> SimIO File-#if __GLASGOW_HASKELL__ >= 900 openFile fp "r" = SimIO $ fmap File (IO.openFile fp IO.ReadMode) openFile fp "w" = SimIO $ fmap File (IO.openFile fp IO.WriteMode) openFile fp "a" = SimIO $ fmap File (IO.openFile fp IO.AppendMode)@@ -209,26 +175,8 @@ openFile fp "rb+" = SimIO $ fmap File (IO.openBinaryFile fp IO.ReadWriteMode) openFile fp "wb+" = SimIO $ fmap File (IO.openBinaryFile fp IO.WriteMode) openFile fp "ab+" = SimIO $ fmap File (IO.openBinaryFile fp IO.AppendMode)-#else-openFile fp "r" = coerce (IO.openFile fp IO.ReadMode)-openFile fp "w" = coerce (IO.openFile fp IO.WriteMode)-openFile fp "a" = coerce (IO.openFile fp IO.AppendMode)-openFile fp "rb" = coerce (IO.openBinaryFile fp IO.ReadMode)-openFile fp "wb" = coerce (IO.openBinaryFile fp IO.WriteMode)-openFile fp "ab" = coerce (IO.openBinaryFile fp IO.AppendMode)-openFile fp "r+" = coerce (IO.openFile fp IO.ReadWriteMode)-openFile fp "w+" = coerce (IO.openFile fp IO.WriteMode)-openFile fp "a+" = coerce (IO.openFile fp IO.AppendMode)-openFile fp "r+b" = coerce (IO.openBinaryFile fp IO.ReadWriteMode)-openFile fp "w+b" = coerce (IO.openBinaryFile fp IO.WriteMode)-openFile fp "a+b" = coerce (IO.openBinaryFile fp IO.AppendMode)-openFile fp "rb+" = coerce (IO.openBinaryFile fp IO.ReadWriteMode)-openFile fp "wb+" = coerce (IO.openBinaryFile fp IO.WriteMode)-openFile fp "ab+" = coerce (IO.openBinaryFile fp IO.AppendMode)-#endif openFile _ m = error ("openFile unknown mode: " ++ show m)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE openFile #-}+{-# OPAQUE openFile #-} {-# ANN openFile hasBlackBox #-} -- | Close a file@@ -236,8 +184,7 @@ :: File -> SimIO () closeFile (File fp) = SimIO (IO.hClose fp)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE closeFile #-}+{-# OPAQUE closeFile #-} {-# ANN closeFile hasBlackBox #-} -- | Read one character from a file@@ -246,8 +193,7 @@ -- ^ File to read from -> SimIO Char getChar (File fp) = SimIO (IO.hGetChar fp)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE getChar #-}+{-# OPAQUE getChar #-} {-# ANN getChar hasBlackBox #-} -- | Insert a character into a buffer specified by the file@@ -258,8 +204,7 @@ -- ^ Buffer to insert to -> SimIO () putChar c (File fp) = SimIO (IO.hPutChar fp c)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE putChar #-}+{-# OPAQUE putChar #-} {-# ANN putChar hasBlackBox #-} -- | Read one line from a file@@ -282,8 +227,7 @@ rep [] vs = vs rep (x:xs) (Cons _ vs) = Cons (toEnum (fromEnum x)) (rep xs vs) rep _ Nil = Nil--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE getLine #-}+{-# OPAQUE getLine #-} {-# ANN getLine hasBlackBox #-} -- | Determine whether we've reached the end of the file@@ -292,8 +236,7 @@ -- ^ File we want to inspect -> SimIO Bool isEOF (File fp) = SimIO (IO.hIsEOF fp)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE isEOF #-}+{-# OPAQUE isEOF #-} {-# ANN isEOF hasBlackBox #-} -- | Set the position of the next operation on the file@@ -310,8 +253,7 @@ -- * 2: From the end of the file -> SimIO Int seek (File fp) pos mode = SimIO (IO.hSeek fp (toEnum mode) pos >> return 0)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE seek #-}+{-# OPAQUE seek #-} {-# ANN seek hasBlackBox #-} -- | Set the position of the next operation to the beginning of the file@@ -319,8 +261,7 @@ :: File -> SimIO Int rewind (File fp) = SimIO (IO.hSeek fp IO.AbsoluteSeek 0 >> return 0)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE rewind #-}+{-# OPAQUE rewind #-} {-# ANN rewind hasBlackBox #-} -- | Returns the offset from the beginning of the file (in bytes).@@ -329,8 +270,7 @@ -- ^ File we want to inspect -> SimIO Integer tell (File fp) = SimIO (IO.hTell fp)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE tell #-}+{-# OPAQUE tell #-} {-# ANN tell hasBlackBox #-} -- | Write any buffered output to file@@ -338,8 +278,7 @@ :: File -> SimIO () flush (File fp) = SimIO (IO.hFlush fp)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE flush #-}+{-# OPAQUE flush #-} {-# ANN flush hasBlackBox #-} -- | Simulation-level I/O environment that can be synthesized to HDL-level I\/O.@@ -397,5 +336,4 @@ where go q@(~(k :- ks)) s = (:-) <$> unSimIO (f s k) <*> unsafeInterleaveIO ((q `seq` go ks s))--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE mealyIO #-}+{-# OPAQUE mealyIO #-}
src/Clash/Explicit/Synchronizer.hs view
@@ -193,7 +193,6 @@ in ptr == (complement (slice addrSize a1 s_ptr) ++# slice a2 d0 s_ptr) -- | Synchronizer implemented as a FIFO around a synchronous RAM. Based on the--- design described in "Clash.Tutorial#multiclock", which is itself based on the -- design described in <http://www.sunburst-design.com/papers/CummingsSNUG2002SJ_FIFO1.pdf>. -- However, this FIFO uses a synchronous dual-ported RAM which, unlike those -- designs using RAM with an asynchronous read port, is nearly guaranteed to
src/Clash/Explicit/Testbench.hs view
@@ -115,8 +115,7 @@ where eqX a b = unsafeDupablePerformIO (catch (evaluate (a == b)) (\(_ :: XException) -> return False))--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE assert #-}+{-# OPAQUE assert #-} {-# ANN assert hasBlackBox #-} -- | The same as 'assert', but can handle don't care bits in its expected value.@@ -150,8 +149,7 @@ where eqX a b = unsafeDupablePerformIO (catch (evaluate (a `isLike#` b)) (\(_ :: XException) -> return False))--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE assertBitVector #-}+{-# OPAQUE assertBitVector #-} {-# ANN assertBitVector hasBlackBox #-} @@ -430,8 +428,7 @@ -- be optimized away. tbEnableGen :: Enable tag tbEnableGen = toEnable (pure True)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE tbEnableGen #-}+{-# OPAQUE tbEnableGen #-} {-# ANN tbEnableGen hasBlackBox #-} -- | Clock generator for the 'System' clock domain.@@ -479,8 +476,7 @@ -- | Differential output DiffClock dom clockToDiffClock clk = DiffClock clk (ClockN SSymbol)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE clockToDiffClock #-}+{-# OPAQUE clockToDiffClock #-} {-# ANN clockToDiffClock hasBlackBox #-} -- | Cross clock domains in a way that is unsuitable for hardware but good@@ -501,6 +497,5 @@ -> Signal dom1 a -> Signal dom2 a unsafeSimSynchronizer = unsafeSynchronizer--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE unsafeSimSynchronizer #-}+{-# OPAQUE unsafeSimSynchronizer #-} {-# ANN unsafeSimSynchronizer hasBlackBox #-}
src/Clash/Explicit/Verification.hs view
@@ -248,8 +248,7 @@ pure (errorX (concat [ "Simulation for Clash.Verification not yet implemented. If you need this," , " create an issue at https://github.com/clash-compiler/clash-lang/issues." ]))--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE check #-}+{-# OPAQUE check #-} {-# ANN check (InlineYamlPrimitive [Verilog, SystemVerilog, VHDL] [__i| BlackBoxHaskell: name: Clash.Explicit.Verification.check
src/Clash/Intel/ClockGen.hs view
@@ -1,7 +1,7 @@ {-| Copyright : (C) 2017-2018, Google Inc 2019 , Myrtle Software- 2022-2023, QBayLogic B.V.+ 2022-2026, QBayLogic B.V. License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> @@ -55,9 +55,6 @@ -- $unsafe_example , unsafeAltpll , unsafeAlteraPll- -- * Deprecated- , altpll- , alteraPll ) where import GHC.TypeLits (type (<=))@@ -65,10 +62,8 @@ import Clash.Annotations.Primitive (hasBlackBox) import Clash.Clocks (Clocks(..), ClocksSync(..), ClocksSyncCxt, NumOutClocksSync)-import Clash.Magic (setName)-import Clash.Promoted.Symbol (SSymbol) import Clash.Signal.Internal- (Signal, Clock, Reset, KnownDomain, HasAsynchronousReset)+ (Clock, Reset, KnownDomain, HasAsynchronousReset) {- $domains Synthesis domains are denoted by the type-parameter@@ -323,36 +318,6 @@ -- | Instantiate an Intel clock generator corresponding to the Intel/Quartus -- \"ALTPLL\" IP core (Arria GX, Arria II, Stratix IV, Stratix III, Stratix II, -- Stratix, Cyclone 10 LP, Cyclone IV, Cyclone III, Cyclone II, Cyclone) with 1--- reference clock input and a reset input and 1 output clock and a @locked@--- output.------ This function is deprecated because the @locked@ output is an asynchronous--- signal. This means the user is required to add a synchronizer and as such--- this function is unsafe. The common use case is now covered by 'altpllSync'--- and 'unsafeAltpll' offers the functionality of this deprecated function for--- advanced use cases.-altpll ::- forall domOut domIn name .- ( HasAsynchronousReset domIn- , KnownDomain domOut- ) =>- -- | Name of the component instance- --- -- Instantiate as follows: @(SSymbol \@\"altpll50\")@- SSymbol name ->- -- | Free running clock (e.g. a clock pin connected to a crystal oscillator)- Clock domIn ->- -- | Reset for the clock generator- Reset domIn ->- -- | (Output clock, Clock generator locked)- (Clock domOut, Signal domOut Bool)-altpll _ = setName @name unsafeAltpll-{-# INLINE altpll #-}-{-# DEPRECATED altpll "This function is unsafe. Please see documentation of the function for alternatives." #-}---- | Instantiate an Intel clock generator corresponding to the Intel/Quartus--- \"ALTPLL\" IP core (Arria GX, Arria II, Stratix IV, Stratix III, Stratix II,--- Stratix, Cyclone 10 LP, Cyclone IV, Cyclone III, Cyclone II, Cyclone) with 1 -- reference clock input and a reset input and 1 to 5 output clocks and a -- @locked@ output. --@@ -373,8 +338,7 @@ Reset domIn -> t unsafeAltpll = clocks--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE unsafeAltpll #-}+{-# OPAQUE unsafeAltpll #-} {-# ANN unsafeAltpll hasBlackBox #-} -- | Instantiate an Intel clock generator corresponding to the Intel/Quartus@@ -404,35 +368,6 @@ -- \"Altera PLL\" IP core (Arria V, Stratix V, Cyclone V) with 1 reference clock -- input and a reset input and 1 to 18 output clocks and a @locked@ output. ----- This function is deprecated because the @locked@ output is an asynchronous--- signal. This means the user is required to add a synchronizer and as such--- this function is unsafe. The common use case is now covered by--- 'alteraPllSync' and 'unsafeAlteraPll' offers the functionality of this--- deprecated function for advanced use cases.-alteraPll ::- forall t domIn name .- ( HasAsynchronousReset domIn- , Clocks t- , ClocksCxt t- , NumOutClocks t <= 18- ) =>- -- | Name of the component instance- --- -- Instantiate as follows: @(SSymbol \@\"alterapll50\")@- SSymbol name ->- -- | Free running clock (e.g. a clock pin connected to a crystal oscillator)- Clock domIn ->- -- | Reset for the clock generator- Reset domIn ->- t-alteraPll _ = setName @name unsafeAlteraPll-{-# INLINE alteraPll #-}-{-# DEPRECATED alteraPll "This function is unsafe. Please see documentation of the function for alternatives." #-}---- | Instantiate an Intel clock generator corresponding to the Intel/Quartus--- \"Altera PLL\" IP core (Arria V, Stratix V, Cyclone V) with 1 reference clock--- input and a reset input and 1 to 18 output clocks and a @locked@ output.--- -- __NB__: Because the clock generator reacts asynchronously to the incoming -- reset input, the signal __must__ be glitch-free. --@@ -450,6 +385,5 @@ Reset domIn -> t unsafeAlteraPll = clocks--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE unsafeAlteraPll #-}+{-# OPAQUE unsafeAlteraPll #-} {-# ANN unsafeAlteraPll hasBlackBox #-}
src/Clash/Intel/DDR.hs view
@@ -1,9 +1,8 @@ {-| Copyright : (C) 2017, Google Inc 2019, Myrtle Software Ltd- 2025, QBayLogic B.V. License : BSD2 (see the file LICENSE)-Maintainer : QBayLogic B.V. <devops@qbaylogic.com>+Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com> DDR primitives for Intel FPGAs using ALTDDIO primitives. @@ -21,9 +20,13 @@ module Clash.Intel.DDR ( altddioIn , altddioOut+ -- * Internal+ , altddioIn#+ , altddioOut# ) where +import Data.Bifunctor import GHC.Stack (HasCallStack, withFrozenCallStack) import Clash.Annotations.Primitive (hasBlackBox)@@ -38,50 +41,48 @@ -- edge and @o1@ is the data clocked in on the /rising/ edge, and @o0@ comes -- before @o1@ in time. ----- __NB__: This primitive only supports rising edges as the active edge. Trying--- to instantiate this function in a domain where falling edges are the active--- edge will lead to a HDL generation or Haskell simulation error.+-- __NB__: This primitive only supports rising edges as the active edge. altddioIn- :: forall fast fPeriod edge reset init polarity slow m deviceFamily- . ( HasCallStack- , KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity)- , KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) edge reset init polarity)- , KnownNat m )+ :: forall deviceFamily a dom domDDR+ . HasCallStack+ => KnownDomain dom+ => KnownDomain domDDR+ => DomainPeriod dom ~ (2 * DomainPeriod domDDR)+ => DomainActiveEdge dom ~ 'Rising+ => BitPack a => SSymbol deviceFamily -- ^ The FPGA family -- -- For example this can be instantiated as follows: -- -- > SSymbol @"Cyclone IV GX"- -> Clock slow- -> Reset slow- -> Enable slow- -> Signal fast (BitVector m)+ -> Clock dom+ -> Reset dom+ -> Enable dom+ -> Signal domDDR a -- ^ DDR input signal- -> Signal slow (BitVector m,BitVector m)+ -> Signal dom (a, a) -- ^ Normal speed output pair @(o0, o1)@-altddioIn =- case activeEdge @slow of- SRising ->- withFrozenCallStack altddioIn#- SFalling ->- clashCompileError- "altddioIn: Primitive only supports rising active edge"+altddioIn devFam clk rst en =+ fmap (bimap unpack unpack) .+ withFrozenCallStack (altddioIn# devFam clk rst en) . fmap pack altddioIn#- :: ( HasCallStack- , KnownConfiguration fast ('DomainConfiguration fast fPeriod 'Rising reset init polarity)- , KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) 'Rising reset init polarity)- , KnownNat m )+ :: forall deviceFamily n dom domDDR+ . HasCallStack+ => KnownDomain dom+ => KnownDomain domDDR+ => DomainPeriod dom ~ (2 * DomainPeriod domDDR)+ => DomainActiveEdge dom ~ 'Rising+ => KnownNat n => SSymbol deviceFamily- -> Clock slow- -> Reset slow- -> Enable slow- -> Signal fast (BitVector m)- -> Signal slow (BitVector m,BitVector m)+ -> Clock dom+ -> Reset dom+ -> Enable dom+ -> Signal domDDR (BitVector n)+ -> Signal dom (BitVector n, BitVector n) altddioIn# SSymbol clk rst en = withFrozenCallStack ddrIn# clk rst en 0 0 0--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE altddioIn# #-}+{-# OPAQUE altddioIn# #-} {-# ANN altddioIn# hasBlackBox #-} -- | Intel specific variant of 'ddrOut' implemented using the ALTDDIO_OUT IP core.@@ -92,49 +93,47 @@ -- edge and @i1@ is the data clocked out on the /falling/ edge, and @i0@ comes -- before @i1@ in time. ----- __NB__: This primitive only supports rising edges as the active edge. Trying--- to instantiate this function in a domain where falling edges are the active--- edge will lead to a HDL generation or Haskell simulation error.+-- __NB__: This primitive only supports rising edges as the active edge. altddioOut- :: forall fast fPeriod edge reset init polarity slow m deviceFamily- . ( HasCallStack- , KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity)- , KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) edge reset init polarity)- , KnownNat m )+ :: forall deviceFamily a dom domDDR+ . HasCallStack+ => KnownDomain dom+ => KnownDomain domDDR+ => DomainPeriod dom ~ (2 * DomainPeriod domDDR)+ => DomainActiveEdge dom ~ 'Rising+ => BitPack a => SSymbol deviceFamily -- ^ The FPGA family -- -- For example this can be instantiated as follows: -- -- > SSymbol @"Cyclone IV E"- -> Clock slow- -> Reset slow- -> Enable slow- -> Signal slow (BitVector m,BitVector m)+ -> Clock dom+ -> Reset dom+ -> Enable dom+ -> Signal dom (a, a) -- ^ Normal speed input pair @(i0, i1)@- -> Signal fast (BitVector m)+ -> Signal domDDR a -- ^ DDR output signal altddioOut devFam clk rst en =- case activeEdge @slow of- SRising ->- uncurry (withFrozenCallStack altddioOut# devFam clk rst en) . unbundle- SFalling ->- clashCompileError- "altddioOut: Primitive only supports rising active edge"+ fmap unpack . uncurry (withFrozenCallStack altddioOut# devFam clk rst en) .+ unbundle . fmap (bimap pack pack) altddioOut#- :: ( HasCallStack- , KnownConfiguration fast ('DomainConfiguration fast fPeriod 'Rising reset init polarity)- , KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) 'Rising reset init polarity)- , KnownNat m )+ :: forall deviceFamily n dom domDDR+ . HasCallStack+ => KnownDomain dom+ => KnownDomain domDDR+ => DomainPeriod dom ~ (2 * DomainPeriod domDDR)+ => DomainActiveEdge dom ~ 'Rising+ => KnownNat n => SSymbol deviceFamily- -> Clock slow- -> Reset slow- -> Enable slow- -> Signal slow (BitVector m)- -> Signal slow (BitVector m)- -> Signal fast (BitVector m)+ -> Clock dom+ -> Reset dom+ -> Enable dom+ -> Signal dom (BitVector n)+ -> Signal dom (BitVector n)+ -> Signal domDDR (BitVector n) altddioOut# SSymbol clk rst en = ddrOut# clk rst en 0--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE altddioOut# #-}+{-# OPAQUE altddioOut# #-} {-# ANN altddioOut# hasBlackBox #-}
src/Clash/Magic.hs view
@@ -20,6 +20,7 @@ {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskellQuotes #-}+{-# LANGUAGE Trustworthy #-} module Clash.Magic (@@ -58,22 +59,19 @@ prefixName :: forall (name :: Symbol) a . a -> name ::: a prefixName = id--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE prefixName #-}+{-# OPAQUE prefixName #-} -- | Suffix instance and register names with the given 'Symbol' suffixName :: forall (name :: Symbol) a . a -> name ::: a suffixName = id--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE suffixName #-}+{-# OPAQUE suffixName #-} -- | Suffix instance and register names with the given 'Nat' suffixNameFromNat :: forall (name :: Nat) a . a -> name ::: a suffixNameFromNat = id--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE suffixNameFromNat #-}+{-# OPAQUE suffixNameFromNat #-} -- | Suffix instance and register names with the given 'Symbol', but add it -- in front of other suffixes.@@ -96,8 +94,7 @@ suffixNameP :: forall (name :: Symbol) a . a -> name ::: a suffixNameP = id--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE suffixNameP #-}+{-# OPAQUE suffixNameP #-} -- | Suffix instance and register names with the given 'Nat', but add it in -- front of other suffixes.@@ -120,8 +117,7 @@ suffixNameFromNatP :: forall (name :: Nat) a . a -> name ::: a suffixNameFromNatP = id--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE suffixNameFromNatP #-}+{-# OPAQUE suffixNameFromNatP #-} -- | Name the instance or register with the given 'Symbol', instead of using -- an auto-generated name. Pre- and suffixes annotated with 'prefixName' and@@ -130,8 +126,7 @@ setName :: forall (name :: Symbol) a . a -> name ::: a setName = id--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE setName #-}+{-# OPAQUE setName #-} -- | Name a given term, such as one of type 'Clash.Signal.Signal', using the -- given 'SSymbol'. Results in a declaration with the name used as the@@ -150,8 +145,7 @@ -- ^ A hint for a name -> a -> a nameHint = seq--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE nameHint #-}+{-# OPAQUE nameHint #-} {-# ANN nameHint hasBlackBox #-} -- | Force deduplication, i.e. share a function or operator between multiple@@ -198,8 +192,7 @@ deDup :: forall a . a -> a deDup = id--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE deDup #-}+{-# OPAQUE deDup #-} -- | Do not deduplicate, i.e. /keep/, an applied function inside a -- case-alternative; do not try to share the function between multiple@@ -258,15 +251,13 @@ noDeDup :: forall a . a -> a noDeDup = id--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE noDeDup #-}+{-# OPAQUE noDeDup #-} -- | 'True' in Haskell/Clash simulation. Replaced by 'False' when generating HDL. clashSimulation :: Bool clashSimulation = noinline True -- The 'noinline' is here to prevent SpecConstr from poking through the OPAQUE, see #2736--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE clashSimulation #-}+{-# OPAQUE clashSimulation #-} -- | A container for data you only want to have around during simulation and -- is ignored during synthesis. Useful for carrying around things such as:@@ -304,8 +295,7 @@ -- descriptive. clashCompileError :: forall a . HasCallStack => String -> a clashCompileError msg = withFrozenCallStack $ error msg--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE clashCompileError #-}+{-# OPAQUE clashCompileError #-} {-# ANN clashCompileError ( let primName = 'clashCompileError in InlineYamlPrimitive [minBound..] [__i|
src/Clash/NamedTypes.hs view
@@ -34,7 +34,6 @@ -} {-# LANGUAGE NoGeneralizedNewtypeDeriving #-}-{-# LANGUAGE PolyKinds #-} {-# LANGUAGE Safe #-}
src/Clash/Prelude.hs view
@@ -2,7 +2,7 @@ Copyright : (C) 2013-2016, University of Twente, 2017-2019, Myrtle Software Ltd 2017 , Google Inc.,- 2021-2023, QBayLogic B.V.+ 2021-2025, QBayLogic B.V. License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> @@ -29,8 +29,9 @@ have overlapping definitions. For now, "Clash.Prelude" is also the best starting point for exploring the- library. A preliminary version of a tutorial can be found in "Clash.Tutorial".- Some circuit examples can be found in "Clash.Examples".+ library. A preliminary version of a tutorial can be found at+ https://docs.clash-lang.org/tutorial. Some circuit examples can be found in+ "Clash.Examples". -} {-# LANGUAGE CPP #-}@@ -52,11 +53,6 @@ , moore , mooreB , registerB-#ifdef CLASH_MULTIPLE_HIDDEN- -- * Synchronizer circuits for safe clock domain crossings- , dualFlipFlopSynchronizer- , asyncFIFOSynchronizer-#endif -- * ROMs , asyncRom , asyncRomPow2@@ -146,6 +142,11 @@ -- ** Template Haskell , Lift (..) -- ** Type classes+ -- *** Number conversion+ , NumConvert+ , numConvert+ , MaybeNumConvert+ , maybeNumConvert -- *** Clash , AutoReg, autoReg, deriveAutoReg , module Clash.Class.BitPack@@ -156,7 +157,7 @@ -- *** Other , module Control.Applicative , module Data.Bits- , module Data.Default.Class+ , module Data.Default , module Data.Kind -- ** Exceptions , module Clash.XException@@ -174,13 +175,11 @@ import Control.Applicative import Data.Bits-import Data.Default.Class+import Data.Default import Data.Kind (Type, Constraint) import GHC.Stack (HasCallStack) import GHC.TypeLits-#if MIN_VERSION_base(4,18,0) hiding (SNat, SSymbol, fromSNat)-#endif import GHC.TypeLits.Extra import Language.Haskell.TH.Syntax (Lift(..)) import Clash.HaskellPrelude@@ -190,6 +189,7 @@ import Clash.Class.BitPack import Clash.Class.Exp import Clash.Class.Num+import Clash.Class.NumConvert import Clash.Class.Parity import Clash.Class.Resize import qualified Clash.Explicit.Prelude as E@@ -202,9 +202,6 @@ import Clash.Prelude.ROM.Blob import Clash.Prelude.ROM.File import Clash.Prelude.Safe-#ifdef CLASH_MULTIPLE_HIDDEN-import Clash.Prelude.Synchronizer-#endif import Clash.Promoted.Nat import Clash.Promoted.Nat.TH import Clash.Promoted.Nat.Literals
src/Clash/Prelude/BlockRam.hs view
@@ -2,7 +2,7 @@ Copyright : (C) 2013-2016, University of Twente, 2016-2019, Myrtle Software Ltd, 2017 , Google Inc.,- 2021-2022, QBayLogic B.V.+ 2021-2026, QBayLogic B.V. License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> @@ -404,7 +404,7 @@ import Prelude (Enum, Maybe, Eq) -import GHC.TypeLits (KnownNat, type (^), type (<=))+import GHC.TypeLits (KnownNat, type (^)) import GHC.Stack (HasCallStack, withFrozenCallStack) import qualified Clash.Explicit.BlockRam as E@@ -740,15 +740,13 @@ , NFDataX a , Enum addr , NFDataX addr- , 1 <= n )- => E.ResetStrategy r+ )+ => E.ResetStrategy r (Index n -> a) -- ^ Whether to clear BRAM on asserted reset ('Clash.Explicit.BlockRam.ClearOnReset') -- or not ('Clash.Explicit.BlockRam.NoClearOnReset'). The reset needs to be -- asserted for at least /n/ cycles to clear the BRAM. -> SNat n -- ^ Number of elements in BRAM- -> (Index n -> a)- -- ^ If applicable (see first argument), reset BRAM using this function -> Signal dom addr -- ^ Read address @r@ -> Signal dom (Maybe (addr, a))@@ -756,8 +754,8 @@ -> Signal dom a -- ^ Value of the BRAM at address @r@ from the previous clock cycle blockRamU =- \rstStrategy cnt initF rd wrM -> withFrozenCallStack- (hideClockResetEnable E.blockRamU) rstStrategy cnt initF rd wrM+ \rstStrategy cnt rd wrM -> withFrozenCallStack+ (hideClockResetEnable E.blockRamU) rstStrategy cnt rd wrM {-# INLINE blockRamU #-} -- | A version of 'blockRam' that is initialized with the same value on all@@ -769,8 +767,8 @@ , NFDataX a , Enum addr , NFDataX addr- , 1 <= n )- => E.ResetStrategy r+ )+ => E.ResetStrategy r () -- ^ Whether to clear BRAM on asserted reset ('Clash.Explicit.BlockRam.ClearOnReset') -- or not ('Clash.Explicit.BlockRam.NoClearOnReset'). The reset needs to be -- asserted for at least /n/ cycles to clear the BRAM.@@ -838,7 +836,7 @@ {- | Create a read-after-write block RAM from a read-before-write one -#if __GLASGOW_HASKELL__ >= 908 && !defined(CLASH_MULTIPLE_HIDDEN)+#if __GLASGOW_HASKELL__ >= 908 >>> :t readNew (blockRam (0 :> 1 :> Nil)) readNew (blockRam (0 :> 1 :> Nil)) :: ...@@ -846,20 +844,10 @@ ... => Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a -#elif __GLASGOW_HASKELL__ >= 902 && !defined(CLASH_MULTIPLE_HIDDEN)->>> :t readNew (blockRam (0 :> 1 :> Nil))-readNew (blockRam (0 :> 1 :> Nil))- :: ...- ... =>- Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a- #else >>> :t readNew (blockRam (0 :> 1 :> Nil)) readNew (blockRam (0 :> 1 :> Nil)) :: ...- ...- ...- ... ... => Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a @@ -888,24 +876,6 @@ -- is: WriteFirst. For mixed-port read/write, when port A writes to the address -- port B reads from, the output of port B is undefined, and vice versa. trueDualPortBlockRam ::-#ifdef CLASH_MULTIPLE_HIDDEN- forall nAddrs dom1 dom2 a .- ( HasCallStack- , KnownNat nAddrs- , HiddenClock dom1- , HiddenClock dom2- , NFDataX a- )- => Signal dom1 (E.RamOp nAddrs a)- -- ^ RAM operation for port A- -> Signal dom2 (E.RamOp nAddrs a)- -- ^ RAM operation for port B- -> (Signal dom1 a, Signal dom2 a)- -- ^ Outputs data on /next/ cycle. When writing, the data written- -- will be echoed. When reading, the read data is returned.-trueDualPortBlockRam inA inB =- E.trueDualPortBlockRam (hasClock @dom1) (hasClock @dom2) inA inB-#else forall nAddrs dom a . ( HasCallStack , KnownNat nAddrs@@ -920,4 +890,3 @@ -- ^ Outputs data on /next/ cycle. When writing, the data written -- will be echoed. When reading, the read data is returned. trueDualPortBlockRam inA inB = E.trueDualPortBlockRam hasClock hasClock inA inB-#endif
− src/Clash/Prelude/DataFlow.hs
@@ -1,574 +0,0 @@-{-|-Copyright : (C) 2013-2016, University of Twente,- 2017 , Google Inc.- 2019 , Myrtle Software Ltd,- 2021 , QBayLogic B.V.-License : BSD2 (see the file LICENSE)-Maintainer : QBayLogic B.V. <devops@qbaylogic.com>--Self-synchronizing circuits based on data-flow principles.--}--{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE NoGeneralizedNewtypeDeriving #-}-{-# LANGUAGE TypeFamilies #-}--{-# LANGUAGE Safe #-}--{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}-{-# OPTIONS_GHC -fplugin GHC.TypeLits.Normalise #-}-{-# OPTIONS_HADDOCK show-extensions #-}--module Clash.Prelude.DataFlow {-# DEPRECATED "Module will be removed in Clash 1.10 in favor of clash-protocols. See: https://github.com/clash-lang/clash-protocols/." #-}- ( -- * Data types- DataFlow (..)- -- * Creating DataFlow circuits- , liftDF- , pureDF- , mealyDF- , mooreDF- , fifoDF- -- * Composition combinators- , idDF- , seqDF- , firstDF- , swapDF- , secondDF- , parDF- , parNDF- , loopDF- , loopDF_nobuf- -- * Lock-Step operation- , LockStep (..)- )-where--import GHC.TypeLits (KnownNat, type (+), type (^))-import Prelude- hiding ((++), (!!), length, map, repeat, tail, unzip3, zip3, zipWith)--import Clash.Class.BitPack (boolToBV)-import Clash.Class.Resize (truncateB)-import Clash.Class.BitPack.BitIndex (msb)-import Clash.Explicit.Mealy (mealyB)-import Clash.Promoted.Nat (SNat)-import Clash.Signal (KnownDomain, (.&&.))-import Clash.Signal.Bundle (Bundle (..))-import Clash.Explicit.Signal (Clock, Reset, Signal, Enable, andEnable, register)-import Clash.Sized.BitVector (BitVector)-import Clash.Sized.Vector-import Clash.XException (errorX, NFDataX)--{- | Dataflow circuit with bidirectional synchronization channels.--In the /forward/ direction we assert /validity/ of the data. In the /backward/-direction we assert that the circuit is /ready/ to receive new data. A circuit-adhering to the 'DataFlow' type should:-- * Not consume data when validity is deasserted.- * Only update its output when readiness is asserted.--The 'DataFlow' type is defined as:--@-newtype DataFlow' dom iEn oEn i o- = DF- { df :: 'Signal' dom i -- Incoming data- -> 'Signal' dom iEn -- Flagged with \/valid\/ bits \@iEn\@.- -> 'Signal' dom oEn -- Incoming back-pressure, \/ready\/ edge.- -> ( 'Signal' dom o -- Outgoing data.- , 'Signal' dom oEn -- Flagged with \/valid\/ bits \@oEn\@.- , 'Signal' dom iEn -- Outgoing back-pressure, \/ready\/ edge.- )- }-@--where:-- * @dom@ is the domain to which the circuit is synchronized.- * @iEn@ is the type of the bidirectional incoming synchronization channel.- * @oEn@ is the type of the bidirectional outgoing synchronization channel.- * @i@ is the incoming data type.- * @o@ is the outgoing data type.--We define several composition operators for our 'DataFlow' circuits:-- * 'seqDF' sequential composition.- * 'parDF' parallel composition.- * 'loopDF' add a feedback arc.- * 'lockStep' proceed in lock-step.--When you look at the types of the above operators it becomes clear why we-parametrize in the types of the synchronization channels.--}-newtype DataFlow dom iEn oEn i o- = DF- { -- | Create an ordinary circuit from a 'DataFlow' circuit- df :: Signal dom i -- Incoming data- -> Signal dom iEn -- Flagged with /valid/ bits @iEn@.- -> Signal dom oEn -- Incoming back-pressure, /ready/ edge.- -> ( Signal dom o -- Outgoing data.- , Signal dom oEn -- Flagged with /valid/ bits @oEn@.- , Signal dom iEn -- Outgoing back-pressure, /ready/ edge.- )- }---- | Dataflow circuit synchronized to the 'Clash.Signal.systemClockGen'.--- type DataFlow iEn oEn i o = DataFlow' systemClockGen iEn oEn i o---- | Create a 'DataFlow' circuit from a circuit description with the appropriate--- type:------ @--- 'Signal' dom i -- Incoming data.--- -> 'Signal' dom Bool -- Flagged with a single \/valid\/ bit.--- -> 'Signal' dom Bool -- Incoming back-pressure, \/ready\/ bit.--- -> ( 'Signal' dom o -- Outgoing data.--- , 'Signal' dom oEn -- Flagged with a single \/valid\/ bit.--- , 'Signal' dom iEn -- Outgoing back-pressure, \/ready\/ bit.--- )--- @------ A circuit adhering to the 'DataFlow' type should:------ * Not consume data when validity is deasserted.--- * Only update its output when readiness is asserted.-liftDF- :: ( Signal dom i- -> Signal dom Bool- -> Signal dom Bool- -> (Signal dom o, Signal dom Bool, Signal dom Bool))- -> DataFlow dom Bool Bool i o-liftDF = DF---- | Create a 'DataFlow' circuit where the given function @f@ operates on the--- data, and the synchronization channels are passed unaltered.-pureDF- :: (i -> o)- -> DataFlow dom Bool Bool i o-pureDF f = DF (\i iV oR -> (fmap f i,iV,oR))---- | Create a 'DataFlow' circuit from a Mealy machine description as those of--- "Clash.Prelude.Mealy"-mealyDF- :: ( KnownDomain dom- , NFDataX s )- => Clock dom- -> Reset dom- -> Enable dom- -> (s -> i -> (s,o))- -> s- -> DataFlow dom Bool Bool i o-mealyDF clk rst gen f iS =- DF (\i iV oR -> let en = iV .&&. oR- (s',o) = unbundle (f <$> s <*> i)- s = register clk rst (andEnable gen en) iS s'- in (o,iV,oR))---- | Create a 'DataFlow' circuit from a Moore machine description as those of--- "Clash.Prelude.Moore"-mooreDF- :: ( KnownDomain dom- , NFDataX s )- => Clock dom- -> Reset dom- -> Enable dom- -> (s -> i -> s)- -> (s -> o)- -> s- -> DataFlow dom Bool Bool i o-mooreDF clk rst gen ft fo iS =- DF (\i iV oR -> let en = iV .&&. oR- s' = ft <$> s <*> i- s = register clk rst (andEnable gen en) iS s'- o = fo <$> s- in (o,iV,oR))--fifoDF_mealy- :: forall addrSize a- . KnownNat addrSize- => (Vec (2^addrSize) a, BitVector (addrSize + 1), BitVector (addrSize + 1))- -> (a, Bool, Bool)- -> ((Vec (2^addrSize) a, BitVector (addrSize + 1), BitVector (addrSize + 1))- ,(a, Bool, Bool))-fifoDF_mealy (mem,rptr,wptr) (wdata,winc,rinc) =- let raddr = truncateB rptr :: BitVector addrSize- waddr = truncateB wptr :: BitVector addrSize-- mem' | winc && not full = replace waddr wdata mem- | otherwise = mem-- rdata = mem !! raddr-- rptr' = rptr + boolToBV (rinc && not empty)- wptr' = wptr + boolToBV (winc && not full)- empty = rptr == wptr- full = msb rptr /= msb wptr && raddr == waddr- in ((mem',rptr',wptr'), (rdata,empty,full))---- | Create a FIFO buffer adhering to the 'DataFlow' protocol. Can be filled--- with initial content.------ To create a FIFO of size 4, with two initial values 2 and 3 you would write:------ @--- fifo4 = 'fifoDF' d4 (2 :> 3 :> Nil)--- @-fifoDF- :: forall addrSize m n a dom- . ( KnownDomain dom- , NFDataX a- , KnownNat addrSize- , KnownNat n- , KnownNat m- , (m + n) ~ (2 ^ addrSize) )- => Clock dom- -> Reset dom- -> Enable dom- -> SNat (m + n) -- ^ Depth of the FIFO buffer. Must be a power of two.- -> Vec m a -- ^ Initial content. Can be smaller than the size of the- -- FIFO. Empty spaces are initialized with 'undefined'.- -> DataFlow dom Bool Bool a a-fifoDF clk rst en _ iS = DF $ \i iV oR ->- let initRdPtr = 0- initWrPtr = fromIntegral (length iS)- initMem = iS ++ repeat (errorX "fifoDF: undefined") :: Vec (m + n) a- initS = (initMem,initRdPtr,initWrPtr)- (o,empty,full) = mealyB clk rst en fifoDF_mealy initS (i,iV,oR)- in (o,not <$> empty, not <$> full)---- | Identity circuit------ <<doc/idDF.svg>>-idDF :: DataFlow dom en en a a-idDF = DF (\a val rdy -> (a,val,rdy))---- | Sequential composition of two 'DataFlow' circuits.------ <<doc/seqDF.svg>>-seqDF- :: DataFlow dom aEn bEn a b- -> DataFlow dom bEn cEn b c- -> DataFlow dom aEn cEn a c-(DF f) `seqDF` (DF g) = DF (\a aVal cRdy -> let (b,bVal,aRdy) = f a aVal bRdy- (c,cVal,bRdy) = g b bVal cRdy- in (c,cVal,aRdy))---- | Apply the circuit to the first halve of the communication channels, leave--- the second halve unchanged.------ <<doc/firstDF.svg>>-firstDF- :: DataFlow dom aEn bEn a b- -> DataFlow dom (aEn, cEn) (bEn, cEn) (a, c) (b, c)-firstDF (DF f) = DF (\ac acV bcR -> let (a,c) = unbundle ac- (aV,cV) = unbundle acV- (bR,cR) = unbundle bcR- (b,bV,aR) = f a aV bR- bc = bundle (b,c)- bcV = bundle (bV,cV)- acR = bundle (aR,cR)- in (bc,bcV,acR)- )---- | Swap the two communication channels.------ <<doc/swapDF.svg>>-swapDF :: DataFlow dom (aEn, bEn) (bEn, aEn) (a, b) (b, a)-swapDF = DF (\ab abV baR -> (swap <$> ab, swap <$> abV, swap <$> baR))- where- swap ~(a,b) = (b,a)---- | Apply the circuit to the second halve of the communication channels, leave--- the first halve unchanged.------ <<doc/secondDF.svg>>-secondDF- :: DataFlow dom aEn bEn a b- -> DataFlow dom (cEn, aEn) (cEn, bEn) (c, a) (c, b)-secondDF f = swapDF `seqDF` firstDF f `seqDF` swapDF---- | Compose two 'DataFlow' circuits in parallel.------ <<doc/parDF.svg>>-parDF- :: DataFlow dom aEn bEn a b- -> DataFlow dom cEn dEn c d- -> DataFlow dom (aEn, cEn) (bEn, dEn) (a, c) (b, d)-f `parDF` g = firstDF f `seqDF` secondDF g---- | Compose /n/ 'DataFlow' circuits in parallel.-parNDF- :: KnownNat n- => Vec n (DataFlow dom aEn bEn a b)- -> DataFlow dom (Vec n aEn) (Vec n bEn) (Vec n a) (Vec n b)-parNDF fs =- DF (\as aVs bRs ->- let as' = unbundle as- aVs' = unbundle aVs- bRs' = unbundle bRs- (bs,bVs,aRs) = unzip3 (zipWith (\k (a,b,r) -> df k a b r) fs- (zip3 (lazyV as') (lazyV aVs') bRs'))- in (bundle bs,bundle bVs, bundle aRs)- )---- | Feed back the second halve of the communication channel. The feedback loop--- is buffered by a 'fifoDF' circuit.------ So given a circuit /h/ with two synchronization channels:------ @--- __h__ :: 'DataFlow' (Bool,Bool) (Bool,Bool) (a,d) (b,d)--- @------ Feeding back the /d/ part (including its synchronization channels) results--- in:------ @--- 'loopDF' d4 Nil h--- @------ <<doc/loopDF.svg>>------ When you have a circuit @h'@, with only a single synchronization channel:------ @--- __h'__ :: 'DataFlow' Bool Bool (a,d) (b,d)--- @------ and you want to compose /h'/ in a feedback loop, the following will not work:------ @--- f \`@'seqDF'@\` ('loopDF' d4 Nil h') \`@'seqDF'@\` g--- @------ The circuits @f@, @h@, and @g@, must operate in /lock-step/ because the /h'/--- circuit only has a single synchronization channel. Consequently, there--- should only be progress when all three circuits are producing /valid/ data--- and all three circuits are /ready/ to receive new data. We need to compose--- /h'/ with the 'lockStep' and 'stepLock' functions to achieve the /lock-step/--- operation.------ @--- f \`@'seqDF'@\` ('lockStep' \`@'seqDF'@\` 'loopDF' d4 Nil h' \`@'seqDF'@\` 'stepLock') \`@'seqDF'@\` g--- @------ <<doc/loopDF_sync.svg>>-loopDF- :: ( KnownDomain dom- , NFDataX d- , KnownNat m- , KnownNat n- , KnownNat addrSize- , (m+n) ~ (2^addrSize) )- => Clock dom- -> Reset dom- -> Enable dom- -> SNat (m + n)- -- ^ Depth of the FIFO buffer. Must be a power of two- -> Vec m d- -- ^ Initial content of the FIFO buffer. Can be smaller than the size of the- -- FIFO. Empty spaces are initialized with 'undefined'.- -> DataFlow dom (Bool,Bool) (Bool,Bool) (a,d) (b,d)- -> DataFlow dom Bool Bool a b-loopDF clk rst en sz is (DF f) =- DF (\a aV bR -> let (bd,bdV,adR) = f ad adV bdR- (b,d) = unbundle bd- (bV,dV) = unbundle bdV- (aR,dR) = unbundle adR- (d_buf,dV_buf,dR_buf) = df (fifoDF clk rst en sz is) d dV dR-- ad = bundle (a,d_buf)- adV = bundle (aV,dV_buf)- bdR = bundle (bR,dR_buf)- in (b,bV,aR)- )---- | Feed back the second halve of the communication channel. Unlike 'loopDF',--- the feedback loop is /not/ buffered.-loopDF_nobuf :: DataFlow dom (Bool,Bool) (Bool,Bool) (a,d) (b,d)- -> DataFlow dom Bool Bool a b-loopDF_nobuf (DF f) = DF (\a aV bR -> let (bd,bdV,adR) = f ad adV bdR- (b,d) = unbundle bd- (bV,dV) = unbundle bdV- (aR,dR) = unbundle adR- ad = bundle (a,d)- adV = bundle (aV,dV)- bdR = bundle (bR,dR)- in (b,bV,aR)- )---- | Reduce or extend the synchronization granularity of parallel compositions.-class LockStep a b where- -- | Reduce the synchronization granularity to a single 'Bool'ean value.- --- -- Given:- --- -- @- -- __f__ :: 'DataFlow' Bool Bool a b- -- __g__ :: 'DataFlow' Bool Bool c d- -- __h__ :: 'DataFlow' Bool Bool (b,d) (p,q)- -- @- --- -- We /cannot/ simply write:- --- -- @- -- (f \`@'parDF'@\` g) \`@'seqDF'@\` h- -- @- --- -- because, @f \`parDF\` g@, has type, @'DataFlow' (Bool,Bool) (Bool,Bool) (a,c) (b,d)@,- -- which does not match the expected synchronization granularity of @h@. We- -- need a circuit in between that has the type:- --- -- @- -- 'DataFlow' (Bool,Bool) Bool (b,d) (b,d)- -- @- --- -- Simply '&&'-ing the /valid/ signals in the forward direction, and- -- duplicating the /ready/ signal in the backward direction is however not- -- enough. We also need to make sure that @f@ does not update its output when- -- @g@'s output is invalid and visa versa, as @h@ can only consume its input- -- when both @f@ and @g@ are producing valid data. @g@'s /ready/ port is hence- -- only asserted when @h@ is ready and @f@ is producing /valid/ data. And @f@'s- -- ready port is only asserted when @h@ is ready and @g@ is producing valid- -- data. @f@ and @g@ will hence be proceeding in /lock-step/.- --- -- The 'lockStep' function ensures that all synchronization signals are- -- properly connected:- --- -- @- -- (f \`@'parDF'@\` g) \`@'seqDF'@\` 'lockStep' \`@'seqDF'@\` h- -- @- --- -- <<doc/lockStep.svg>>- --- -- __Note 1__: ensure that the components that you are synchronizing have- -- buffered/delayed @ready@ and @valid@ signals, or 'lockStep' has the- -- potential to introduce combinational loops. You can do this by placing- -- 'fifoDF's on the parallel channels. Extending the above example, you would- -- write:- --- -- @- -- ((f \`@'seqDF'@\` 'fifoDF' d4 Nil) \`@'parDF'@\` (g \`@'seqDF'@\` 'fifoDF' d4 Nil)) \`@'seqDF'@\` 'lockStep' \`@'seqDF'@\` h- -- @- --- -- __Note 2__: 'lockStep' works for arbitrarily nested tuples. That is:- --- -- @- -- p :: 'DataFlow' Bool Bool ((b,d),d) z- --- -- q :: 'DataFlow' ((Bool,Bool),Bool) ((Bool,Bool),Bool) ((a,c),c) ((b,d),d)- -- q = f \`@'parDF'@\` g \`@'parDF'@\` g- --- -- r = q \`@'seqDF'@\` 'lockStep' \`@'seqDF'@\` p- -- @- --- -- Does the right thing.- lockStep :: DataFlow dom a Bool b b-- -- | Extend the synchronization granularity from a single 'Bool'ean value.- --- -- Given:- --- -- @- -- __f__ :: 'DataFlow' Bool Bool a b- -- __g__ :: 'DataFlow' Bool Bool c d- -- __h__ :: 'DataFlow' Bool Bool (p,q) (a,c)- -- @- --- -- We /cannot/ simply write:- --- -- @- -- h \`@'seqDF'@\` (f \`@'parDF'@\` g)- -- @- --- -- because, @f \`parDF\` g@, has type, @'DataFlow' (Bool,Bool) (Bool,Bool) (a,c) (b,d)@,- -- which does not match the expected synchronization granularity of @h@. We- -- need a circuit in between that has the type:- --- -- @- -- 'DataFlow' Bool (Bool,Bool) (a,c) (a,c)- -- @- --- -- Simply '&&'-ing the /ready/ signals in the backward direction, and- -- duplicating the /valid/ signal in the forward direction is however not- -- enough. We need to make sure that @f@ does not consume values when @g@ is- -- not /ready/ and visa versa, because @h@ cannot update the values of its- -- output tuple independently. @f@'s /valid/ port is hence only asserted when- -- @h@ is valid and @g@ is ready to receive new values. @g@'s /valid/ port is- -- only asserted when @h@ is valid and @f@ is ready to receive new values.- -- @f@ and @g@ will hence be proceeding in /lock-step/.- --- -- The 'stepLock' function ensures that all synchronization signals are- -- properly connected:- --- -- @- -- h \`@'seqDF'@\` 'stepLock' \`@'seqDF'@\` (f \`@'parDF'@\` g)- -- @- --- -- <<doc/stepLock.svg>>- --- -- __Note 1__: ensure that the components that you are synchronizing have- -- buffered/delayed @ready@ and @valid@ signals, or 'stepLock' has the- -- potential to introduce combinational loops. You can do this by placing- -- 'fifoDF's on the parallel channels. Extending the above example, you would- -- write:- --- -- @- -- h \`@'seqDF'@\` 'stepLock' \`@'seqDF'@\` ((`fifoDF` d4 Nil \`@'seqDF'@\` f) \`@'parDF'@\` (`fifoDF` d4 Nil \`@'seqDF'@\` g))- -- @- --- -- __Note 2__: 'stepLock' works for arbitrarily nested tuples. That is:- --- -- @- -- p :: 'DataFlow' Bool Bool z ((a,c),c)- --- -- q :: 'DataFlow' ((Bool,Bool),Bool) ((Bool,Bool),Bool) ((a,c),c) ((b,d),d)- -- q = f \`@'parDF'@\` g \`@'parDF'@\` g- --- -- r = p \`@'seqDF'@\` 'stepLock' \`@'seqDF'@\` q- -- @- --- -- Does the right thing.- stepLock :: DataFlow dom Bool a b b--instance LockStep Bool c where- lockStep = idDF- stepLock = idDF--instance (LockStep a x, LockStep b y) => LockStep (a,b) (x,y) where- lockStep = (lockStep `parDF` lockStep) `seqDF`- (DF (\xy xyV rdy -> let (xV,yV) = unbundle xyV- val = xV .&&. yV- xR = yV .&&. rdy- yR = xV .&&. rdy- xyR = bundle (xR,yR)- in (xy,val,xyR)))-- stepLock = (DF (\xy val xyR -> let (xR,yR) = unbundle xyR- rdy = xR .&&. yR- xV = val .&&. yR- yV = val .&&. xR- xyV = bundle (xV,yV)- in (xy,xyV,rdy))) `seqDF` (stepLock `parDF` stepLock)--instance (LockStep en a, KnownNat n) => LockStep (Vec n en) (Vec n a) where- lockStep = parNDF (repeat lockStep) `seqDF`- DF (\xs vals rdy ->- let val = (and . (True :>)) <$> vals- rdys = allReady <$> rdy <*> (repeat . (:< True) <$> vals)- in (xs,val,rdys)- )- stepLock =- DF (\xs val rdys ->- let rdy = (and . (True :>)) <$> rdys- vals = allReady <$> val <*> (repeat . (:< True) <$> rdys)- in (xs,vals,rdy)- ) `seqDF` parNDF (repeat stepLock)--allReady :: KnownNat n- => Bool- -> Vec n (Vec (n+1) Bool)- -> Vec n Bool-allReady b vs = map (and . (b :>) . tail) (smap (flip rotateLeftS) vs)
src/Clash/Prelude/ROM.hs view
@@ -122,8 +122,7 @@ withFrozenCallStack (deepErrorX ("asyncRom: address " ++ show i ++ " not in range [0.." ++ show szI ++ ")"))--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE asyncRom# #-}+{-# OPAQUE asyncRom# #-} {-# ANN asyncRom# hasBlackBox #-} -- | A ROM with a synchronous read port, with space for @n@ elements
src/Clash/Prelude/ROM/Blob.hs view
@@ -119,8 +119,7 @@ (deepErrorX ("asyncRom: address " ++ show i ++ " not in range [0.." ++ show szI ++ ")")) {-# ANN asyncRomBlob# hasBlackBox #-}--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE asyncRomBlob# #-}+{-# OPAQUE asyncRomBlob# #-} -- | A ROM with a synchronous read port, with space for @n@ elements --
src/Clash/Prelude/ROM/File.hs view
@@ -252,8 +252,7 @@ mem = unsafePerformIO (initMem file) content = listArray (0,szI-1) mem szI = snatToNum sz--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE asyncRomFile# #-}+{-# OPAQUE asyncRomFile# #-} {-# ANN asyncRomFile# hasBlackBox #-} -- | A ROM with a synchronous read port, with space for @n@ elements
src/Clash/Prelude/Safe.hs view
@@ -26,8 +26,9 @@ explicitly clocked circuits in a multi-clock setting For now, "Clash.Prelude" is also the best starting point for exploring the- library. A preliminary version of a tutorial can be found in "Clash.Tutorial".- Some circuit examples can be found in "Clash.Examples".+ library. A preliminary version of a tutorial can be found at+ https://docs.clash-lang.org/tutorial. Some circuit examples can be found in+ "Clash.Examples". -} {-# LANGUAGE CPP #-}@@ -138,9 +139,7 @@ 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
− src/Clash/Prelude/Synchronizer.hs
@@ -1,88 +0,0 @@-{-|-Copyright : (C) 2019, Myrtle Software Ltd,-License : BSD2 (see the file LICENSE)-Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>--Synchronizer circuits for safe clock domain crossings--}--{-# LANGUAGE TypeFamilies #-}--module Clash.Prelude.Synchronizer- ( -- * Bit-synchronizers- dualFlipFlopSynchronizer- -- * Word-synchronizers- , asyncFIFOSynchronizer- ) where--import qualified Clash.Explicit.Synchronizer as E-import Clash.Promoted.Nat (SNat)-import Clash.Signal- (HiddenClockResetEnable, HiddenClock, Signal, hasClock, hasReset, hasEnable)-import Clash.XException (NFDataX)-import GHC.TypeLits (type (<=))---- | Synchronizer based on two sequentially connected flip-flops.------ * __NB__: This synchronizer can be used for __bit__-synchronization.------ * __NB__: Although this synchronizer does reduce metastability, it does--- not guarantee the proper synchronization of a whole __word__. For--- example, given that the output is sampled twice as fast as the input is--- running, and we have two samples in the input stream that look like:------ @[0111,1000]@------ But the circuit driving the input stream has a longer propagation delay--- on __msb__ compared to the __lsb__s. What can happen is an output stream--- that looks like this:------ @[0111,0111,0000,1000]@------ Where the level-change of the __msb__ was not captured, but the level--- change of the __lsb__s were.------ If you want to have /safe/ __word__-synchronization use--- 'asyncFIFOSynchronizer'.-dualFlipFlopSynchronizer- :: ( NFDataX a- , HiddenClock dom1- , HiddenClockResetEnable dom2- )- => a- -- ^ Initial value of the two synchronization registers- -> Signal dom1 a- -- ^ Incoming data- -> Signal dom2 a- -- ^ Outgoing, synchronized, data-dualFlipFlopSynchronizer =- E.dualFlipFlopSynchronizer hasClock hasClock hasReset hasEnable---- | Synchronizer implemented as a FIFO around an asynchronous RAM. Based on the--- design described in "Clash.Tutorial#multiclock", which is itself based on the--- design described in <http://www.sunburst-design.com/papers/CummingsSNUG2002SJ_FIFO1.pdf>.------ __NB__: This synchronizer can be used for __word__-synchronization.-asyncFIFOSynchronizer- :: ( HiddenClockResetEnable rdom- , HiddenClockResetEnable wdom- , 2 <= addrSize- , NFDataX a )- => SNat addrSize- -- ^ Size of the internally used addresses, the FIFO contains @2^addrSize@- -- elements.- -> Signal rdom Bool- -- ^ Read request- -> Signal wdom (Maybe a)- -- ^ Element to insert- -> (Signal rdom a, Signal rdom Bool, Signal wdom Bool)- -- ^ (Oldest element in the FIFO, @empty@ flag, @full@ flag)-asyncFIFOSynchronizer addrSize =- E.asyncFIFOSynchronizer- addrSize- hasClock -- wdom- hasClock -- rdom- hasReset -- wdom- hasReset -- rdom- hasEnable -- wdom- hasEnable -- rdom
src/Clash/Promoted/Nat.hs view
@@ -1,7 +1,7 @@ {-| Copyright : (C) 2013-2016, University of Twente, 2016 , Myrtle Software Ltd- 2022 , QBayLogic B.V.+ 2022-2025, QBayLogic B.V. License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> -}@@ -70,19 +70,22 @@ ) where +import Data.Constraint (Dict(..), (:-)(Sub))+import Data.Constraint.Nat (euclideanNat) import Data.Kind (Type)+import Data.Type.Equality ((:~:)(..))+import Data.Type.Ord (OrderingI(..)) import GHC.Show (appPrec) import GHC.TypeLits (KnownNat, Nat, type (+), type (-), type (*),- type (^), type (<=), natVal)+ type (^), type (<=),+ cmpNat, sameNat,+ natVal) import GHC.TypeLits.Extra (CLog, FLog, Div, Log, Mod, Min, Max) import GHC.Natural (naturalFromInteger) import Language.Haskell.TH (appT, conT, litT, numTyLit, sigE) import Language.Haskell.TH.Syntax (Lift (..))-#if MIN_VERSION_template_haskell(2,16,0) import Language.Haskell.TH.Compat-#endif import Numeric.Natural (Natural)-import Unsafe.Coerce (unsafeCoerce) import Clash.Annotations.Primitive (hasBlackBox) import Clash.XException (ShowX (..), showsPrecXWith)@@ -103,9 +106,7 @@ instance Lift (SNat n) where lift s = sigE [| SNat |] (appT (conT ''SNat) (litT $ numTyLit (snatToInteger s)))-#if MIN_VERSION_template_haskell(2,16,0) liftTyped = liftTypedFromUntyped-#endif -- | Create an @`SNat` n@ from a proxy for /n/ snatProxy :: KnownNat n => proxy n -> SNat n@@ -184,11 +185,12 @@ -- -- __NB__: Not synthesizable toUNat :: forall n . SNat n -> UNat n-toUNat p@SNat = fromI @n (snatToInteger p)- where- fromI :: forall m . Integer -> UNat m- fromI 0 = unsafeCoerce @(UNat 0) @(UNat m) UZero- fromI n = unsafeCoerce @(UNat ((m-1)+1)) @(UNat m) (USucc (fromI @(m-1) (n - 1)))+toUNat p@SNat = case cmpNat (SNat @1) p of+ LTI -> USucc (toUNat @(n - 1) (predSNat p))+ EQI -> USucc UZero+ GTI -> case sameNat p (SNat @0) of+ Just Refl -> UZero+ _ -> error "toUNat: impossible: 1 > n and n /= 0 for (n :: Nat)" -- | Convert a unary-encoded natural number to its singleton representation --@@ -225,7 +227,7 @@ -- __NB__: Not synthesizable predUNat :: UNat (n+1) -> UNat n predUNat (USucc x) = x-#if __GLASGOW_HASKELL__ != 902+#if __GLASGOW_HASKELL__ < 912 predUNat UZero = error "predUNat: impossible: 0 minus 1, -1 is not a natural number" #endif@@ -236,7 +238,9 @@ subUNat :: UNat (m+n) -> UNat n -> UNat m subUNat x UZero = x subUNat (USucc x) (USucc y) = subUNat x y+#if __GLASGOW_HASKELL__ < 912 subUNat UZero _ = error "subUNat: impossible: 0 + (n + 1) ~ 0"+#endif -- | Predecessor of a singleton natural number predSNat :: SNat (a+1) -> SNat (a)@@ -269,8 +273,7 @@ -- | Power of two singleton natural numbers powSNat :: SNat a -> SNat b -> SNat (a^b) powSNat SNat SNat = SNat--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE powSNat #-}+{-# OPAQUE powSNat #-} {-# ANN powSNat hasBlackBox #-} infixr 8 `powSNat` @@ -298,8 +301,7 @@ -> SNat x -> SNat (FLog base x) flogBaseSNat SNat SNat = SNat--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE flogBaseSNat #-}+{-# OPAQUE flogBaseSNat #-} {-# ANN flogBaseSNat hasBlackBox #-} -- | Ceiling of the logarithm of a natural number@@ -308,8 +310,7 @@ -> SNat x -> SNat (CLog base x) clogBaseSNat SNat SNat = SNat--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE clogBaseSNat #-}+{-# OPAQUE clogBaseSNat #-} {-# ANN clogBaseSNat hasBlackBox #-} -- | Exact integer logarithm of a natural number@@ -320,8 +321,7 @@ -> SNat x -> SNat (Log base x) logBaseSNat SNat SNat = SNat--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE logBaseSNat #-}+{-# OPAQUE logBaseSNat #-} {-# ANN logBaseSNat hasBlackBox #-} -- | Power of two of a singleton natural number@@ -338,10 +338,13 @@ -- | Get an ordering relation between two SNats compareSNat :: forall a b . SNat a -> SNat b -> SNatLE a b-compareSNat a b =- if snatToInteger a <= snatToInteger b- then unsafeCoerce (SNatLE @0 @0)- else unsafeCoerce (SNatGT @1 @0)+compareSNat a@SNat b@SNat = case cmpNat a b of+ LTI -> SNatLE+ EQI -> SNatLE+ GTI -> case cmpNat (succSNat b) a of+ LTI -> SNatGT+ EQI -> SNatGT+ GTI -> error "compareSNat: impossible: a > b and b + 1 > a" -- | Base-2 encoded natural number --@@ -404,14 +407,18 @@ -- | Convert a singleton natural number to its base-2 representation -- -- __NB__: Not synthesizable-toBNat :: SNat n -> BNat n-toBNat s@SNat = toBNat' (snatToInteger s)- where- toBNat' :: forall m . Integer -> BNat m- toBNat' 0 = unsafeCoerce BT- toBNat' n = case n `divMod` 2 of- (n',1) -> unsafeCoerce (B1 (toBNat' @(Div (m-1) 2) n'))- (n',_) -> unsafeCoerce (B0 (toBNat' @(Div m 2) n'))+toBNat :: forall n. SNat n -> BNat n+toBNat s@SNat = case cmpNat (SNat @1) s of+ LTI -> case euclideanNat @2 @n of+ Sub Dict -> case sameNat (SNat @(n `Mod` 2)) (SNat @0) of+ Just Refl -> B0 (toBNat (SNat @(n `Div` 2)))+ Nothing -> case sameNat (SNat @(n `Mod` 2)) (SNat @1) of+ Just Refl -> B1 (toBNat (SNat @(n `Div` 2)))+ Nothing -> error "toBNat: impossible: n mod 2 is either 0 or 1"+ EQI -> B1 BT+ GTI -> case sameNat s (SNat @0) of+ Just Refl -> BT+ _ -> error "toBNat: impossible: 1 > n and n /= 0 for (n :: Nat)" -- | Convert a base-2 encoded natural number to its singleton representation --@@ -488,7 +495,7 @@ -- -- __NB__: Not synthesizable log2BNat :: BNat (2^n) -> BNat n-#if __GLASGOW_HASKELL__ != 902+#if __GLASGOW_HASKELL__ < 912 log2BNat BT = error "log2BNat: log2(0) not defined" #endif log2BNat (B1 x) = case stripZeros x of
src/Clash/Promoted/Nat/Unsafe.hs view
@@ -21,6 +21,5 @@ -- | I hope you know what you're doing unsafeSNat :: Integer -> SNat k unsafeSNat i = reifyNat i $ (\p -> unsafeCoerce (snatProxy p))--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE unsafeSNat #-}+{-# OPAQUE unsafeSNat #-} {-# ANN unsafeSNat hasBlackBox #-}
src/Clash/Promoted/Symbol.hs view
@@ -36,11 +36,7 @@ where tt = LitT (StrTyLit (ssymbolToString t)) -#if MIN_VERSION_template_haskell(2,17,0) liftTyped = unsafeCodeCoerce . lift-#elif MIN_VERSION_template_haskell(2,16,0)- liftTyped = unsafeTExpCoerce . lift-#endif instance Show (SSymbol s) where showsPrec d s@SSymbol = showParen (d > appPrec) $
src/Clash/Signal.hs view
@@ -107,12 +107,23 @@ , DomainInitBehavior , DomainResetPolarity -- *** Convenience types- -- **** Simplifying -- $conveniencetypes , HasSynchronousReset , HasAsynchronousReset , HasDefinedInitialValues+ -- **** Time representations+ , Seconds+ , Milliseconds+ , Microseconds+ , Nanoseconds+ , Picoseconds+ -- **** Time conversions+ , DomainToHz+ , HzToPeriod+ , PeriodToHz+ , PeriodToCycles+ , ClockDivider -- ** Default domains , System , XilinxSystem@@ -135,10 +146,6 @@ , DiffClock , periodToHz , hzToPeriod-#ifdef CLASH_MULTIPLE_HIDDEN- -- ** Synchronization primitive- , unsafeSynchronizer-#endif -- * Reset , Reset , unsafeToReset@@ -147,9 +154,6 @@ , unsafeToActiveLow , unsafeFromActiveHigh , unsafeFromActiveLow-#ifdef CLASH_MULTIPLE_HIDDEN- , convertReset-#endif , resetSynchronizer , resetGlitchFilter , registerSyncReset@@ -170,46 +174,27 @@ , hideClock , exposeClock , withClock-#ifdef CLASH_MULTIPLE_HIDDEN- , exposeSpecificClock- , withSpecificClock-#endif , hasClock -- ** Hidden reset , HiddenReset , hideReset , exposeReset , withReset-#ifdef CLASH_MULTIPLE_HIDDEN- , exposeSpecificReset- , withSpecificReset-#endif , hasReset -- ** Hidden enable , HiddenEnable , hideEnable , exposeEnable , withEnable-#ifdef CLASH_MULTIPLE_HIDDEN- , exposeSpecificEnable- , withSpecificEnable-#endif , hasEnable -- ** Hidden clock, reset, and enable , HiddenClockResetEnable , hideClockResetEnable , exposeClockResetEnable , withClockResetEnable-#ifdef CLASH_MULTIPLE_HIDDEN- , exposeSpecificClockResetEnable- , withSpecificClockResetEnable-#endif , SystemClockResetEnable -- * Basic circuit functions , andEnable-#ifdef CLASH_MULTIPLE_HIDDEN- , andSpecificEnable-#endif , dflipflop , delay , delayMaybe@@ -217,7 +202,9 @@ , register , regMaybe , regEn+ , regEnN , mux+ , apEn -- * Simulation and testbench functions , clockGen , resetGen@@ -225,7 +212,7 @@ , systemClockGen , systemResetGen -- * Boolean connectives- , (.&&.), (.||.)+ ,(.&&.), (&&.), (.&&), (.||.), (||.), (.||) -- * Product/Signal isomorphism , Bundle(..) , EmptyTuple(..)@@ -257,9 +244,9 @@ , testFor -- * Type classes -- ** 'Eq'-like- , (.==.), (./=.)+ , (.==.), (.==), (==.), (./=.), (./=), (/=.) -- ** 'Ord'-like- , (.<.), (.<=.), (.>=.), (.>.)+ , (.<.), (.<), (<.), (.<=.), (.<=), (<=.), (.>=.), (.>=), (>=.), (.>.), (.>), (>.) -- * Bisignal functions , veryUnsafeToBiSignalIn , readFromBiSignal@@ -286,13 +273,6 @@ import Prelude import Test.QuickCheck (Property, property) --#ifdef CLASH_MULTIPLE_HIDDEN-import GHC.TypeLits (AppendSymbol)-import Clash.Class.HasDomain (WithSingleDomain)-#endif--import Clash.Class.HasDomain (WithSpecificDomain) import qualified Clash.Explicit.Signal as E import qualified Clash.Explicit.Reset as E import Clash.Explicit.Reset (resetSynchronizer, resetGlitchFilter)@@ -335,6 +315,8 @@ {- $conveniencetypes +==== Simplifying+ If you want to write part of your Clash design as domain-polymorphic functions, it can be practical to define a design-wide constraint synonym that captures the characteristics of the clock domains of the design. Such a constraint synonym@@ -587,15 +569,9 @@ to 'andEnable' as an argument would have avoided this hard to debug problem. -} -#ifdef CLASH_MULTIPLE_HIDDEN-type HiddenClockName dom = AppendSymbol dom "_clk"-type HiddenResetName dom = AppendSymbol dom "_rst"-type HiddenEnableName dom = AppendSymbol dom "_en"-#else type HiddenClockName (dom :: Domain) = "clock" type HiddenResetName (dom :: Domain) = "reset" type HiddenEnableName (dom :: Domain) = "enable"-#endif -- | A /constraint/ that indicates the component has a hidden 'Clock' --@@ -642,24 +618,6 @@ {- | Expose a hidden 'Clock' argument of a component, so it can be applied explicitly. -#ifdef CLASH_MULTIPLE_HIDDEN-This function can only be used on components with a single-domain. For example, this function will refuse when:--@-r ~ HiddenClock dom1 => Signal dom1 a -> Signal dom2 a-@--But will work when:--@-r ~ HiddenClock dom => Signal dom a -> Signal dom a-@--If you want to expose a clock of a component working on multiple domains-(such as the first example), use 'exposeSpecificClock'.--#endif <Clash-Signal.html#hiddenclockandreset Click here to read more about hidden clocks, resets, and enables> === __Example__@@ -680,100 +638,13 @@ -} exposeClock :: forall dom r- .-#ifdef CLASH_MULTIPLE_HIDDEN- WithSingleDomain dom r =>-#endif- (HiddenClock dom => r)+ . (HiddenClock dom => r) -- ^ The component with a hidden clock -> (KnownDomain dom => Clock dom -> r) -- ^ The component with its clock argument exposed-exposeClock = \f clk -> exposeSpecificClock (const f) clk (Proxy @dom)--- See Note [Going from WithSingleDomain to WithSpecificDomain]+exposeClock = \f clk -> expose @(HiddenClockName dom) f clk {-# INLINE exposeClock #-} --- Note [Going from WithSingleDomain to WithSpecificDomain]------ Functions like 'exposeSpecificClock' have a 'WithSpecificDomain dom r'--- constraint on the component with type 'r' that's passed to them. This--- requires 'dom' to be present in 'r' at the time the function is used,--- otherwise it will not type-check.------ Functions like 'exposeClock' have a 'WithSingleDomain dom r' constraint, so--- it is known that the domain 'dom' is indeed in 'r'. So we can safely--- introduce 'dom' into the type passed to 'exposeSpecificClock'. By introducing--- 'dom' into the type, the type checker can find the 'dom' when it type-checks--- that the use of 'exposeSpecificClock' in 'exposeClock' satisies the--- 'WithSpecificDomain dom r' constraint.------ So given:------ exposeClock--- :: forall dom r--- . WithSingleDomain dom r--- => (HiddenClock dom => r)--- -> (KnownDomain dom => Clock dom -> r)--- exposeClock = \f clk -> exposeSpecificClock (const f) clk (Proxy @dom)------ The type of 'exposeSpecificClock' as called from 'exposeClock' could be--- written something like:------ exposeSpecificClock--- :: ( WithSpecificDomain dom s--- , s ~ (Proxy dom -> r)--- )--- => (HiddenClock dom => Proxy dom -> r)--- -> (KnownDomain dom => Clock dom -> Proxy dom -> r)------ The type-checker can now find 'dom' in the 'Proxy', so it type-checks.------ The argument------ (HiddenClock dom => Proxy dom -> r)------ is filled in as 'const f', consuming the 'Proxy' before passing on to 'f'.------ In the resulting------ (KnownDomain dom => Clock dom -> Proxy dom -> r)------ the filled in values are 'clk' and 'Proxy @dom', leaving 'r'.--{- | Expose a hidden 'Clock' argument of a component, so it can be applied-explicitly. This function can be used on components with multiple domains.-As opposed to 'exposeClock', callers should explicitly state what the clock-domain is. See the examples for more information.--<Clash-Signal.html#hiddenclockandreset Click here to read more about hidden clocks, resets, and enables>--#ifdef CLASH_MULTIPLE_HIDDEN-=== __Example__-'exposeSpecificClock' can only be used when it can find the specified domain-in /r/:-->>> reg = register @System 5 (reg + 1)->>> sig = exposeSpecificClock @System reg clockGen->>> sampleN 10 sig-[5,5,6,7,8,9,10,11,12,13]--Type variables work too, if they are in scope. For example:--@-reg = 'register' @@dom 5 (reg + 1)-sig = 'exposeSpecificClock' @@dom reg 'clockGen'-@-#endif--}-exposeSpecificClock- :: forall dom r- . WithSpecificDomain dom r- => (HiddenClock dom => r)- -- ^ The component with a hidden clock- -> (KnownDomain dom => Clock dom -> r)- -- ^ The component with its clock argument exposed-exposeSpecificClock = \f clk -> expose @(HiddenClockName dom) f clk-{-# INLINE exposeSpecificClock #-}- -- | Hide the 'Clock' argument of a component, so it can be routed implicitly. -- -- <Clash-Signal.html#hiddenclockandreset Click here to read more about hidden clocks, resets, and enables>@@ -788,24 +659,6 @@ {- | Connect an explicit 'Clock' to a function with a hidden 'Clock'. -#ifdef CLASH_MULTIPLE_HIDDEN-This function can only be used on components with a single domain. For-example, this function will refuse when:--@-r ~ HiddenClock dom1 => Signal dom1 a -> Signal dom2 a-@--But will work when:--@-r ~ HiddenClock dom => Signal dom a -> Signal dom a-@--If you want to connect a clock to a component working on multiple domains-(such as the first example), use 'withSpecificClock'.--#endif <Clash-Signal.html#hiddenclockandreset Click here to read more about hidden clocks, resets, and enables> === __Example__@@ -826,56 +679,15 @@ -} withClock :: forall dom r- .-#ifdef CLASH_MULTIPLE_HIDDEN- WithSingleDomain dom r =>-#endif- KnownDomain dom+ . KnownDomain dom => Clock dom -- ^ The 'Clock' we want to connect -> (HiddenClock dom => r) -- ^ The function with a hidden 'Clock' argument -> r-withClock clk f = withSpecificClock clk (const f) (Proxy @dom)--- See Note [Going from WithSingleDomain to WithSpecificDomain]+withClock = \clk f -> expose @(HiddenClockName dom) f clk {-# INLINE withClock #-} -{- | Connect an explicit 'Clock' to a function with a hidden 'Clock'. This-function can be used on components with multiple domains. As opposed to-'withClock', callers should explicitly state what the clock domain is. See-the examples for more information.--<Clash-Signal.html#hiddenclockandreset Click here to read more about hidden clocks, resets, and enables>--#ifdef CLASH_MULTIPLE_HIDDEN-=== __Example__-'withSpecificClock' can only be used when it can find the specified domain-in /r/:-->>> reg = register @System 5 (reg + 1)->>> sig = withSpecificClock @System clockGen reg->>> sampleN 10 sig-[5,5,6,7,8,9,10,11,12,13]--Type variables work too, if they are in scope. For example:--@-reg = 'register' @@dom 5 (reg + 1)-sig = 'withSpecificClock' @@dom 'clockGen' reg-@-#endif--}-withSpecificClock- :: forall dom r- . (KnownDomain dom, WithSpecificDomain dom r)- => Clock dom- -- ^ The 'Clock' we want to connect- -> (HiddenClock dom => r)- -- ^ The function with a hidden 'Clock' argument- -> r-withSpecificClock = \clk f -> expose @(HiddenClockName dom) f clk-{-# INLINE withSpecificClock #-}- -- | Connect a hidden 'Clock' to an argument where a normal 'Clock' argument -- was expected. --@@ -890,26 +702,6 @@ {- | Expose a hidden 'Reset' argument of a component, so it can be applied explicitly. -#ifdef CLASH_MULTIPLE_HIDDEN-This function can only be used on components with a single domain. For-example, this function will refuse when:--@-r ~ HiddenReset dom1 => Signal dom1 a -> Signal dom2 a-@--But will work when:--@-r ~ HiddenReset dom => Signal dom a -> Signal dom a-@--If you want to expose a reset of a component working on multiple domains-(such as the first example), use 'exposeSpecificReset'.--<Clash-Signal.html#hiddenclockandreset Click here to read more about hidden clocks, resets, and enables>--#endif === __Example__ Usage with a /polymorphic/ domain: @@ -928,53 +720,13 @@ -} exposeReset :: forall dom r- .-#ifdef CLASH_MULTIPLE_HIDDEN- WithSingleDomain dom r =>-#endif- (HiddenReset dom => r)+ . (HiddenReset dom => r) -- ^ The component with a hidden reset -> (KnownDomain dom => Reset dom -> r) -- ^ The component with its reset argument exposed-exposeReset = \f rst -> exposeSpecificReset (const f) rst (Proxy @dom)--- See Note [Going from WithSingleDomain to WithSpecificDomain]+exposeReset = \f rst -> expose @(HiddenResetName dom) f rst {-# INLINE exposeReset #-} -{- | Expose a hidden 'Reset' argument of a component, so it can be applied-explicitly. This function can be used on components with multiple domains.-As opposed to 'exposeReset', callers should explicitly state what the reset-domain is. See the examples for more information.--<Clash-Signal.html#hiddenclockandreset Click here to read more about hidden clocks, resets, and enables>--#ifdef CLASH_MULTIPLE_HIDDEN-=== __Example__-'exposeSpecificReset' can only be used when it can find the specified domain-in /r/:-->>> reg = register @System 5 (reg + 1)->>> sig = exposeSpecificReset @System reg resetGen->>> sampleN 10 sig-[5,5,6,7,8,9,10,11,12,13]--Type variables work too, if they are in scope. For example:--@-reg = 'register' @@dom 5 (reg + 1)-sig = 'exposeSpecificReset' @@dom reg 'resetGen'-@-#endif--}-exposeSpecificReset- :: forall dom r- . WithSpecificDomain dom r- => (HiddenReset dom => r)- -- ^ The component with a hidden reset- -> (KnownDomain dom => Reset dom -> r)- -- ^ The component with its reset argument exposed-exposeSpecificReset = \f rst -> expose @(HiddenResetName dom) f rst-{-# INLINE exposeSpecificReset #-}- -- | Hide the 'Reset' argument of a component, so it can be routed implicitly. -- -- <Clash-Signal.html#hiddenclockandreset Click here to read more about hidden clocks, resets, and enables>@@ -989,26 +741,7 @@ {- | Connect an explicit 'Reset' to a function with a hidden 'Reset'. -#ifdef CLASH_MULTIPLE_HIDDEN-This function can only be used on components with a single domain. For-example, this function will refuse when: -@-r ~ HiddenReset dom1 => Signal dom1 a -> Signal dom2 a-@--But will work when:--@-r ~ HiddenReset dom => Signal dom a -> Signal dom a-@--If you want to connect a reset to a component working on multiple domains-(such as the first example), use 'withSpecificReset'.--<Clash-Signal.html#hiddenclockandreset Click here to read more about hidden clocks, resets, and enables>--#endif === __Example__ Usage with a /polymorphic/ domain: @@ -1027,11 +760,7 @@ -} withReset :: forall dom r- .-#ifdef CLASH_MULTIPLE_HIDDEN- WithSingleDomain dom r =>-#endif- KnownDomain dom+ . KnownDomain dom => Reset dom -- ^ The 'Reset' we want to connect -> (HiddenReset dom => r)@@ -1040,42 +769,6 @@ withReset = \rst f -> expose @(HiddenResetName dom) f rst {-# INLINE withReset #-} -{- | Connect an explicit 'Reset' to a function with a hidden 'Reset'. This-function can be used on components with multiple domains. As opposed to-'withReset', callers should explicitly state what the reset domain is. See-the examples for more information.--<Clash-Signal.html#hiddenclockandreset Click here to read more about hidden clocks, resets, and enables>--#ifdef CLASH_MULTIPLE_HIDDEN-=== __Example__-'withSpecificReset' can only be used when it can find the specified domain-in /r/:-->>> reg = register @System 5 (reg + 1)->>> sig = withSpecificReset @System resetGen reg->>> sampleN 10 sig-[5,5,6,7,8,9,10,11,12,13]--Type variables work too, if they are in scope. For example:--@-reg = 'register' @@dom 5 (reg + 1)-sig = 'withSpecificReset' @@dom 'resetGen' reg-@-#endif--}-withSpecificReset- :: forall dom r- . (KnownDomain dom, WithSpecificDomain dom r)- => Reset dom- -- ^ The 'Reset' we want to connect- -> (HiddenReset dom => r)- -- ^ The function with a hidden 'Reset' argument- -> r-withSpecificReset = \rst f -> expose @(HiddenResetName dom) f rst-{-# INLINE withSpecificReset #-}- -- | Connect a hidden 'Reset' to an argument where a normal 'Reset' argument -- was expected. --@@ -1090,24 +783,6 @@ {- | Expose a hidden 'Enable' argument of a component, so it can be applied explicitly. -#ifdef CLASH_MULTIPLE_HIDDEN-This function can only be used on components with a single domain. For-example, this function will refuse when:--@-r ~ HiddenEnable dom1 => Signal dom1 a -> Signal dom2 a-@--But will work when:--@-r ~ HiddenEnable dom => Signal dom a -> Signal dom a-@--If you want to expose a enable of a component working on multiple domains-(such as the first example), use 'exposeSpecificEnable'.--#endif <Clash-Signal.html#hiddenclockandreset Click here to read more about hidden clocks, resets, and enables> === __Example__@@ -1127,53 +802,14 @@ [5,5,6,7,8,9,10,11,12,13] -} exposeEnable- :: forall dom r .-#ifdef CLASH_MULTIPLE_HIDDEN- WithSingleDomain dom r =>-#endif- (HiddenEnable dom => r)+ :: forall dom r+ . (HiddenEnable dom => r) -- ^ The component with a hidden enable -> (KnownDomain dom => Enable dom -> r) -- ^ The component with its enable argument exposed-exposeEnable = \f gen -> exposeSpecificEnable (const f) gen (Proxy @dom)--- See Note [Going from WithSingleDomain to WithSpecificDomain]+exposeEnable = \f gen -> expose @(HiddenEnableName dom) f gen {-# INLINE exposeEnable #-} -{- | Expose a hidden 'Enable' argument of a component, so it can be applied-explicitly. This function can be used on components with multiple domains.-As opposed to 'exposeEnable', callers should explicitly state what the enable-domain is. See the examples for more information.--<Clash-Signal.html#hiddenclockandreset Click here to read more about hidden clocks, resets, and enables>--#ifdef CLASH_MULTIPLE_HIDDEN-=== __Example__-'exposeSpecificEnable' can only be used when it can find the specified domain-in /r/:-->>> reg = register @System 5 (reg + 1)->>> sig = exposeSpecificEnable @System reg enableGen->>> sampleN 10 sig-[5,5,6,7,8,9,10,11,12,13]--Type variables work too, if they are in scope. For example:--@-reg = 'register' @@dom 5 (reg + 1)-sig = 'exposeSpecificEnable' @@dom reg 'enableGen'-@-#endif--}-exposeSpecificEnable- :: forall dom r- . WithSpecificDomain dom r- => (HiddenEnable dom => r)- -- ^ The component with a hidden enable- -> (KnownDomain dom => Enable dom -> r)- -- ^ The component with its enable argument exposed-exposeSpecificEnable = \f gen -> expose @(HiddenEnableName dom) f gen-{-# INLINE exposeSpecificEnable #-}- -- | Hide the 'Enable' argument of a component, so it can be routed implicitly. -- -- <Clash-Signal.html#hiddenclockandreset Click here to read more about hidden clocks, resets, and enables>@@ -1188,24 +824,6 @@ {- | Connect an explicit 'Enable' to a function with a hidden 'Enable'. -#ifdef CLASH_MULTIPLE_HIDDEN-This function can only be used on components with a single domain. For-example, this function will refuse when:--@-r ~ HiddenEnable dom1 => Signal dom1 a -> Signal dom2 a-@--But will work when:--@-r ~ HiddenEnable dom => Signal dom a -> Signal dom a-@--If you want to connect a enable to a component working on multiple domains-(such as the first example), use 'withSpecificEnable'.--#endif <Clash-Signal.html#hiddenclockandreset Click here to read more about hidden clocks, resets, and enables> === __Example__@@ -1227,9 +845,6 @@ withEnable :: forall dom r . KnownDomain dom-#ifdef CLASH_MULTIPLE_HIDDEN- => WithSingleDomain dom r-#endif => Enable dom -- ^ The 'Enable' we want to connect -> (HiddenEnable dom => r)@@ -1238,42 +853,6 @@ withEnable = \gen f -> expose @(HiddenEnableName dom) f gen {-# INLINE withEnable #-} -{- | Connect an explicit 'Enable' to a function with a hidden 'Enable'. This-function can be used on components with multiple domains. As opposed to-'withEnable', callers should explicitly state what the enable domain is. See-the examples for more information.--<Clash-Signal.html#hiddenclockandreset Click here to read more about hidden clocks, resets, and enables>--#ifdef CLASH_MULTIPLE_HIDDEN-=== __Example__-'withSpecificEnable' can only be used when it can find the specified domain-in /r/:-->>> reg = register @System 5 (reg + 1)->>> sig = withSpecificEnable @System enableGen reg->>> sampleN 10 sig-[5,5,6,7,8,9,10,11,12,13]--Type variables work too, if they are in scope. For example:--@-reg = 'register' @@dom 5 (reg + 1)-sig = 'withSpecificEnable' @@dom 'enableGen' reg-@-#endif--}-withSpecificEnable- :: forall dom r- . (KnownDomain dom, WithSpecificDomain dom r)- => Enable dom- -- ^ The 'Enable' we want to connect- -> (HiddenEnable dom => r)- -- ^ The function with a hidden 'Enable' argument- -> r-withSpecificEnable = \gen f -> expose @(HiddenEnableName dom) f gen-{-# INLINE withSpecificEnable #-}- -- | Connect a hidden 'Enable' to an argument where a normal 'Enable' argument -- was expected. --@@ -1295,24 +874,6 @@ The component whose enable is modified will only be enabled when both the encompassing 'HiddenEnable' and the 'Signal' @dom@ 'Bool' are asserted. -#ifdef CLASH_MULTIPLE_HIDDEN-This function can only be used on components with a single-domain. For example, this function will refuse when:--@-r ~ HiddenEnable dom1 => Signal dom1 a -> Signal dom2 a-@--But will work when:--@-r ~ HiddenEnable dom => Signal dom a -> Signal dom a-@--If you want to merge an enable of a component working on multiple domains-(such as the first example), use 'andSpecificEnable'.-#endif- <#hiddenclockandreset Click here to read more about hidden clocks, resets, and enables> === __Example__@@ -1334,94 +895,26 @@ andEnable :: forall dom r . HiddenEnable dom-#ifdef CLASH_MULTIPLE_HIDDEN- => WithSingleDomain dom r-#endif => Signal dom Bool -- ^ The signal to AND with -> (HiddenEnable dom => r) -- ^ The component whose enable is modified -> r-andEnable = \en f -> andSpecificEnable en (const f) (Proxy @dom)--- See Note [Going from WithSingleDomain to WithSpecificDomain]-{-# INLINE andEnable #-}--#ifdef CLASH_MULTIPLE_HIDDEN-{- | Merge enable signal with signal of bools by applying the boolean AND-operation.--__NB: The component given to 'andSpecificEnable' as an argument needs an explicit type signature.__-Please read [Monomorphism restriction leads to-surprising behavior](#monomorphism).--The component whose enable is modified will only be enabled when both the-encompassing 'HiddenEnable' and the 'Signal' @dom@ 'Bool' are asserted.--This function can be used on components with multiple domains. As opposed to-'andEnable', callers should explicitly state what the enable domain is. See the-examples for more information.--<#hiddenclockandreset Click here to read more about hidden clocks, resets, and enables>--=== __Example__-'andSpecificEnable' can only be used when it can find the specified domain-in /r/:-->>> reg = register @System 5 (reg + 1)->>> f en = andSpecificEnable @System en reg->>> sampleN 10 (f (riseEvery d2))-[5,5,5,6,6,7,7,8,8,9]--Type variables work too, if they are in scope. For example:--@-reg = 'register' @@dom 5 (reg + 1)-f en = 'andSpecificEnable' @@dom en reg-@--}-#endif-andSpecificEnable- :: forall dom r- . ( HiddenEnable dom- , WithSpecificDomain dom r)- => Signal dom Bool- -- ^ The signal to AND with- -> (HiddenEnable dom => r)- -- ^ The component whose enable is modified- -> r-andSpecificEnable = \en f -> andSpecificEnable0 hasEnable en f+andEnable = \en f -> andEnable0 hasEnable en f where- andSpecificEnable0+ andEnable0 :: Enable dom -> Signal dom Bool -> (HiddenEnable dom => r) -> r- andSpecificEnable0 gen en f =+ andEnable0 gen en f = let en0 = E.andEnable gen en- in withSpecificEnable @dom en0 f-{-# INLINE andSpecificEnable #-}+ in withEnable @dom en0 f+{-# INLINE andEnable #-} {- | Expose hidden 'Clock', 'Reset', and 'Enable' arguments of a component, so they can be applied explicitly. -#ifdef CLASH_MULTIPLE_HIDDEN-This function can only be used on components with a single domain. For-example, this function will refuse when:--@-r ~ HiddenClockResetEnable dom1 => Signal dom1 a -> Signal dom2 a-@--But will work when:--@-r ~ HiddenClockResetEnable dom => Signal dom a -> Signal dom a-@--If you want to expose a clock, reset, and enable of a component working on-multiple domains (such as the first example), use 'exposeSpecificClockResetEnable'.--#endif <Clash-Signal.html#hiddenclockandreset Click here to read more about hidden clocks, resets, and enables> === __Example__@@ -1459,55 +952,15 @@ -} exposeClockResetEnable :: forall dom r .-#ifdef CLASH_MULTIPLE_HIDDEN- WithSingleDomain dom r =>-#endif (HiddenClockResetEnable dom => r) -- ^ The component with hidden clock, reset, and enable arguments -> (KnownDomain dom => Clock dom -> Reset dom -> Enable dom -> r) -- ^ The component with its clock, reset, and enable arguments exposed exposeClockResetEnable = \f clk rst en ->- exposeSpecificClock (exposeSpecificReset (exposeEnable f)) clk rst en+ exposeClock (exposeReset (exposeEnable f)) clk rst en {-# INLINE exposeClockResetEnable #-} -#ifdef CLASH_MULTIPLE_HIDDEN--- | Expose hidden 'Clock', 'Reset', and 'Enable' arguments of a component, so--- they can be applied explicitly. This function can be used on components with--- multiple domains. As opposed to 'exposeClockResetEnable', callers should--- explicitly state what the domain is. See the examples for more information.------ <Clash-Signal.html#hiddenclockandreset Click here to read more about hidden clocks, resets, and enables>------ === __Example__--- 'exposeSpecificClockResetEnable' can only be used when it can find the--- specified domain in /r/:------ >>> reg = register @System 5 (reg + 1)--- >>> sig = exposeSpecificClockResetEnable @System reg clockGen resetGen enableGen--- >>> sampleN 10 sig--- [5,5,6,7,8,9,10,11,12,13]------ Type variables work too, if they are in scope. For example:------ @--- reg = 'register' @@dom 5 (reg + 1)--- sig = exposeSpecificClockResetEnable @@dom reg 'clockGen' 'resetGen' 'enableGen'--- @----exposeSpecificClockResetEnable- :: forall dom r- . WithSpecificDomain dom r- => (HiddenClockResetEnable dom => r)- -- ^ The function with hidden 'Clock', 'Reset', and 'Enable' arguments- -> (KnownDomain dom => Clock dom -> Reset dom -> Enable dom -> r)- -- ^ The component with its 'Clock', 'Reset', and 'Enable' arguments exposed-exposeSpecificClockResetEnable =- \f clk rst en ->- exposeSpecificClock (exposeSpecificReset (exposeSpecificEnable f)) clk rst en-{-# INLINE exposeSpecificClockResetEnable #-}-#endif- -- | Hide the 'Clock', 'Reset', and 'Enable' arguments of a component, so they -- can be routed implicitly. --@@ -1529,25 +982,6 @@ {- | Connect an explicit 'Clock', 'Reset', and 'Enable' to a function with a hidden 'Clock', 'Reset', and 'Enable'. -#ifdef CLASH_MULTIPLE_HIDDEN-This function can only be used on components with a single domain. For-example, this function will refuse when:--@-r ~ HiddenClockResetEnable dom1 => Signal dom1 a -> Signal dom2 a-@--But will work when:--@-r ~ HiddenClockResetEnable dom => Signal dom a -> Signal dom a-@--If you want to connect a clock, reset, and enable to a component working on-multiple domains (such as the first example), use-'withSpecificClockResetEnable'.--#endif <Clash-Signal.html#hiddenclockandreset Click here to read more about hidden clocks, resets, and enables> === __Example__@@ -1569,9 +1003,6 @@ withClockResetEnable :: forall dom r . KnownDomain dom-#ifdef CLASH_MULTIPLE_HIDDEN- => WithSingleDomain dom r-#endif => Clock dom -- ^ The 'Clock' we want to connect -> Reset dom@@ -1583,52 +1014,9 @@ -- 'Enable' argument -> r withClockResetEnable =- \clk rst en f -> withSpecificClockResetEnable clk rst en (const f) (Proxy @dom)--- See Note [Going from WithSingleDomain to WithSpecificDomain]+ \clk rst en f -> withClock clk (withReset rst (withEnable en f)) {-# INLINE withClockResetEnable #-} -{- | Connect an explicit 'Clock', 'Reset', and 'Enable' to a function with-hidden 'Clock', 'Reset', and 'Enable' arguments. This function can be used on-components with multiple domains. As opposed to 'withClockResetEnable',-callers should explicitly state what the domain is. See the examples for more-information.--<Clash-Signal.html#hiddenclockandreset Click here to read more about hidden clocks, resets, and enables>--#ifdef CLASH_MULTIPLE_HIDDEN-=== __Example__-'withSpecificClockResetEnable' can only be used when it can find the-specified domain in /r/:-->>> reg = register @System 5 (reg + 1)->>> sig = withSpecificClockResetEnable @System clockGen resetGen enableGen reg->>> sampleN 10 sig-[5,5,6,7,8,9,10,11,12,13]--Type variables work too, if they are in scope. For example:--@-reg = 'register' @@dom 5 (reg + 1)-sig = 'withSpecificClockResetEnable' @@dom 'clockGen' 'resetGen' 'enableGen' reg-@-#endif--}-withSpecificClockResetEnable- :: forall dom r- . (KnownDomain dom, WithSpecificDomain dom r)- => Clock dom- -- ^ The 'Clock' we want to connect- -> Reset dom- -- ^ The 'Reset' we want to connect- -> Enable dom- -- ^ The 'Enable' we want to connect- -> (HiddenClockResetEnable dom => r)- -- ^ The function with hidden 'Clock', 'Reset', and 'Enable' arguments- -> r-withSpecificClockResetEnable =- \clk rst en f -> withSpecificClock clk (withSpecificReset rst (withSpecificEnable en f))-{-# INLINE withSpecificClockResetEnable #-}- -- * Basic circuit functions -- | Special version of 'delay' that doesn't take enable signals of any kind.@@ -1816,6 +1204,29 @@ i {-# INLINE regEn #-} +-- | A chain of 'regEn's.+regEnN ::+ forall dom a n.+ (HiddenClockResetEnable dom, NFDataX a) =>+ -- | The number of stored elements+ SNat n ->+ -- | Initial content of all elements in the chain.+ a ->+ -- | The "push next input" indicator+ Signal dom Bool ->+ Signal dom a ->+ Signal dom a+regEnN = \sn initial en i ->+ E.regEnN+ (fromLabel @(HiddenClockName dom))+ (fromLabel @(HiddenResetName dom))+ (fromLabel @(HiddenEnableName dom))+ sn+ initial+ en+ i+{-# INLINE regEnN #-}+ -- * Signal -> List conversion -- | Get an infinite list of samples from a 'Signal'@@ -1842,8 +1253,7 @@ -> [a] sample s = E.sample (exposeClockResetEnable @dom s clockGen resetGen enableGen)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE sample #-}+{-# OPAQUE sample #-} -- | Get a list of /n/ samples from a 'Signal' --@@ -1872,8 +1282,7 @@ sampleN n s0 = let s1 = exposeClockResetEnable @dom s0 clockGen resetGen enableGen in E.sampleN n s1--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE sampleN #-}+{-# OPAQUE sampleN #-} -- | Get an infinite list of samples from a 'Signal', while asserting the reset -- line for /m/ clock cycles. 'sampleWithReset' does not return the first /m/@@ -1894,8 +1303,7 @@ sampleWithReset nReset f0 = let f1 = exposeClockResetEnable f0 clockGen (resetGenN @dom nReset) enableGen in drop (snatToNum nReset) (E.sample f1)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE sampleWithReset #-}+{-# OPAQUE sampleWithReset #-} -- | Get a list of /n/ samples from a 'Signal', while asserting the reset line -- for /m/ clock cycles. 'sampleWithReset' does not return the first /m/ cycles,@@ -1940,8 +1348,7 @@ -> [a] sample_lazy s = E.sample_lazy (exposeClockResetEnable @dom s clockGen resetGen enableGen)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE sample_lazy #-}+{-# OPAQUE sample_lazy #-} -- | Lazily get a list of /n/ samples from a 'Signal' --@@ -1966,8 +1373,7 @@ -> [a] sampleN_lazy n s = E.sampleN_lazy n (exposeClockResetEnable @dom s clockGen resetGen enableGen)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE sampleN_lazy #-}+{-# OPAQUE sampleN_lazy #-} -- * Simulation functions @@ -2089,8 +1495,7 @@ simulate_lazy f0 = let f1 = exposeClockResetEnable @dom f0 clockGen resetGen enableGen in drop 1 . E.simulate_lazy f1 . dup1--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE simulate_lazy #-}+{-# OPAQUE simulate_lazy #-} -- | Simulate a (@'Unbundled' a -> 'Unbundled' b@) function given a list of -- samples of type @a@@@ -2118,15 +1523,13 @@ drop 1 . E.simulateB f1 . dup1 where f1 =- withSpecificClockResetEnable- @dom+ withClockResetEnable clockGen resetGen enableGen (const f0) (Proxy @dom)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE simulateB #-}+{-# OPAQUE simulateB #-} -- | /Lazily/ simulate a (@'Unbundled' a -> 'Unbundled' b@) function given a -- list of samples of type @a@@@ -2151,15 +1554,13 @@ drop 1 . E.simulateB_lazy f1 . dup1 where f1 =- withSpecificClockResetEnable- @dom+ withClockResetEnable clockGen resetGen enableGen (const f0) (Proxy @dom)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE simulateB_lazy #-}+{-# OPAQUE simulateB_lazy #-} dup1 :: [a] -> [a] dup1 (x:xs) = x:x:xs@@ -2260,18 +1661,6 @@ -> Property testFor n s = property (and (Clash.Signal.sampleN n s)) -#ifdef CLASH_MULTIPLE_HIDDEN--- ** Synchronization primitive--- | Implicit version of 'Clash.Explicit.Signal.unsafeSynchronizer'.-unsafeSynchronizer- :: forall dom1 dom2 a- . ( HiddenClock dom1- , HiddenClock dom2 )- => Signal dom1 a- -> Signal dom2 a-unsafeSynchronizer =- hideClock (hideClock E.unsafeSynchronizer)-#endif -- | Register a synchronous reset signal. --@@ -2348,20 +1737,6 @@ fromListWithReset = hideReset E.fromListWithReset {-# INLINE fromListWithReset #-} -#ifdef CLASH_MULTIPLE_HIDDEN--- | Convert between different types of reset, adding a synchronizer in case--- it needs to convert from an asynchronous to a synchronous reset.-convertReset- :: forall domA domB- . ( HiddenClock domA- , HiddenClock domB- )- => Reset domA- -> Reset domB-convertReset =- E.convertReset hasClock hasClock-#endif- -- | Build an 'Automaton' from a function over 'Signal's. -- -- __NB__: Consumption of continuation of the 'Automaton' must be affine; that@@ -2375,5 +1750,4 @@ signalAutomaton f0 = let f1 = exposeClockResetEnable @dom f0 clockGen resetGen enableGen in E.signalAutomaton f1--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE signalAutomaton #-}+{-# OPAQUE signalAutomaton #-}
src/Clash/Signal/BiSignal.hs view
@@ -104,6 +104,9 @@ {-# OPTIONS_GHC -fplugin=GHC.TypeLits.Normalise #-} {-# OPTIONS_GHC -fplugin=GHC.TypeLits.KnownNat.Solver #-} +-- TryDomain / HasDomain instances+{-# OPTIONS_GHC -Wno-deprecations #-}+ module Clash.Signal.BiSignal ( BiSignalIn() , BiSignalOut()@@ -240,8 +243,7 @@ SFloating -> fromMaybe (errorX " undefined value on BiSignalIn") <$> s SPullDown -> fromMaybe minBound <$> s SPullUp -> fromMaybe maxBound <$> s--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE readFromBiSignal# #-}+{-# OPAQUE readFromBiSignal# #-} {-# ANN readFromBiSignal# hasBlackBox #-} -- | Read the value from an __inout__ port@@ -261,8 +263,7 @@ => Vec n (BiSignalOut defaultState dom m) -> BiSignalOut defaultState dom m mergeBiSignalOuts = mconcat . V.toList--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE mergeBiSignalOuts #-}+{-# OPAQUE mergeBiSignalOuts #-} {-# ANN mergeBiSignalOuts hasBlackBox #-} writeToBiSignal#@@ -273,8 +274,7 @@ -> Signal d (BitVector n) -> BiSignalOut ds d n writeToBiSignal# bIn maybeSignal wEn val = BiSignalOut [bIn `seq` wEn `seq` val `seq` maybeSignal]--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE writeToBiSignal# #-}+{-# OPAQUE writeToBiSignal# #-} {-# ANN writeToBiSignal# hasBlackBox #-} -- | Write to an __inout__ port@@ -321,6 +321,5 @@ -- Recursive step biSignalOut' = veryUnsafeToBiSignalIn $ BiSignalOut $ map tail# signals--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE veryUnsafeToBiSignalIn #-}+{-# OPAQUE veryUnsafeToBiSignalIn #-} {-# ANN veryUnsafeToBiSignalIn hasBlackBox #-}
src/Clash/Signal/Bundle.hs view
@@ -155,8 +155,7 @@ bundle = vecBundle# unbundle = sequenceA . fmap lazyV --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE vecBundle# #-}+{-# OPAQUE vecBundle# #-} {-# ANN vecBundle# hasBlackBox #-} vecBundle# :: Vec n (Signal t a) -> Signal t (Vec n a) vecBundle# = traverse# id
src/Clash/Signal/Bundle/Internal.hs view
@@ -73,20 +73,12 @@ instTy = AppT bundleTy $ mkTupleT vars -- Associated type Unbundled-#if MIN_VERSION_template_haskell(2,15,0) unbundledTypeEq = TySynEqn Nothing ((ConT unbundledTyName `AppT` VarT tNm ) `AppT` mkTupleT vars ) $ mkTupleT $ map (AppT (signal `AppT` VarT tNm)) vars unbundledType = TySynInstD unbundledTypeEq-#else- unbundledTypeEq =- TySynEqn- [ VarT tNm, mkTupleT vars ]- $ mkTupleT $ map (AppT (signal `AppT` VarT tNm)) vars- unbundledType = TySynInstD unbundledTyName unbundledTypeEq-#endif mkFunD nm alias = FunD nm [Clause [] (NormalB (VarE alias)) []] bundleD = mkFunD bundleName bundlePrimName
src/Clash/Signal/Delayed.hs view
@@ -105,22 +105,11 @@ Or @d@ can be specified using type application: -#if __GLASGOW_HASKELL__ >= 902 >>> :t delayedI @3 delayedI @3 :: ... => a -> DSignal dom n a -> DSignal dom (n + 3) a -#else->>> :t delayedI @3-delayedI @3- :: (...- ...- ...- ...) =>- a -> DSignal dom n a -> DSignal dom (n + 3) a--#endif -} delayedI :: ( KnownNat d@@ -190,7 +179,7 @@ -> DSignal dom (n+d) a delayI dflt = hideClock (hideEnable (E.delayI dflt)) --- | Tree fold over a 'Vec' of 'DSignal's with a combinatorial function,+-- | Tree fold over a 'Vec' of 'DSignal's with a combinational function, -- and delaying @delay@ cycles after each application. -- Values at times 0..(delay*k)-1 are set to a default. --
src/Clash/Signal/Delayed/Bundle.hs view
@@ -8,7 +8,6 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeFamilyDependencies #-} module Clash.Signal.Delayed.Bundle (@@ -18,9 +17,6 @@ , TaggedEmptyTuple(..) ) where -#if !MIN_VERSION_base(4,18,0)-import Control.Applicative (liftA2)-#endif import GHC.TypeLits (KnownNat) import Prelude hiding (head, map, tail)
src/Clash/Signal/Delayed/Internal.hs view
@@ -1,10 +1,10 @@ {-| Copyright : (C) 2019 , Myrtle Software Ltd. 2018 , @blaxill- 2018-2019, QBayLogic B.V.+ 2018-2025, QBayLogic B.V. 2021 , LUMI GUIDE FIETSDETECTIE B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> -} {-# LANGUAGE CPP #-} {-# LANGUAGE GADTs #-}@@ -35,7 +35,7 @@ where import Data.Coerce (coerce)-import Data.Default.Class (Default(..))+import Data.Default (Default(..)) import GHC.TypeLits (Nat, type (+)) import Language.Haskell.TH.Syntax (Lift) import Test.QuickCheck (Arbitrary, CoArbitrary)
src/Clash/Signal/Internal.hs view
@@ -1,8 +1,9 @@ {-| Copyright : (C) 2013-2016, University of Twente,- 2017-2019, Myrtle Software Ltd+ 2017-2019, Myrtle Software Ltd, 2017-2022, Google Inc.,- 2021-2023, QBayLogic B.V.+ 2020 , Gergő Érdi,+ 2021-2025, QBayLogic B.V. License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> -}@@ -20,6 +21,7 @@ {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE Unsafe #-} @@ -67,12 +69,22 @@ , DomainConfigurationInitBehavior , DomainConfigurationResetPolarity - -- *** Convenience types-+ -- *** Convenience types , HasSynchronousReset , HasAsynchronousReset , HasDefinedInitialValues-+ -- **** Time representations+ , Seconds+ , Milliseconds+ , Microseconds+ , Nanoseconds+ , Picoseconds+ -- **** Time conversions+ , DomainToHz+ , HzToPeriod+ , PeriodToHz+ , PeriodToCycles+ , ClockDivider -- ** Default domains , System , XilinxSystem@@ -114,6 +126,7 @@ , syncRegister# , registerPowerup# , mux+ , apEn -- * Simulation and testbench functions , clockGen , tbClockGen@@ -127,7 +140,7 @@ , resetGen , resetGenN -- * Boolean connectives- , (.&&.), (.||.)+ , (.&&.), (&&.), (.&&), (.||.), (||.), (.||) -- * Simulation functions (not synthesizable) , simulate -- ** lazy version@@ -146,9 +159,9 @@ , testFor -- * Type classes -- ** 'Eq'-like- , (.==.), (./=.)+ , (.==.), (.==), (==.), (./=.), (./=), (/=.) -- ** 'Ord'-like- , (.<.), (.<=.), (.>=.), (.>.)+ , (.<.), (.<), (<.), (.<=.), (.<=), (<=.), (.>=.), (.>=), (>=.), (.>.), (.>), (>.) -- ** 'Functor' , mapSignal# -- ** 'Applicative'@@ -170,11 +183,10 @@ where import Data.IORef (IORef, atomicModifyIORef, newIORef, readIORef)+#if __GLASGOW_HASKELL__ < 912 import Type.Reflection (Typeable)-import Control.Arrow.Transformer.Automaton-#if !MIN_VERSION_base(4,18,0)-import Control.Applicative (liftA2) #endif+import Control.Arrow.Transformer.Automaton import Control.Applicative (liftA3) import Control.DeepSeq (NFData) import Clash.Annotations.Primitive (hasBlackBox, dontTranslate)@@ -182,7 +194,7 @@ import Data.Char (isAsciiUpper, isAlphaNum, isAscii) import Data.Coerce (coerce) import Data.Data (Data)-import Data.Default.Class (Default (..))+import Data.Default (Default (..)) import Data.Hashable (Hashable) import Data.Int (Int64) import Data.Maybe (isJust)@@ -191,7 +203,10 @@ import Data.Type.Equality ((:~:)) import GHC.Generics (Generic) import GHC.Stack (HasCallStack, withFrozenCallStack)-import GHC.TypeLits (KnownSymbol, KnownNat, Nat, Symbol, type (<=), sameSymbol)+import GHC.TypeLits+ (Div, KnownSymbol, KnownNat, Nat, Symbol, type (<=), type (*), sameSymbol)+import GHC.TypeLits.Extra (DivRU)+import GHC.Records (HasField(getField)) import Language.Haskell.TH.Syntax -- (Lift (..), Q, Dec) import Language.Haskell.TH.Compat import Numeric.Natural (Natural)@@ -199,6 +214,7 @@ import Test.QuickCheck (Arbitrary (..), CoArbitrary(..), Property, property) +import Clash.Class.Num (SaturatingNum(..)) import Clash.CPP (fStrictMapSignal) import Clash.NamedTypes import Clash.Promoted.Nat (SNat (..), snatToNum, snatToNatural)@@ -331,7 +347,9 @@ , _resetPolarity :: ResetPolarity -- ^ Whether resets are active high or active low }+#if __GLASGOW_HASKELL__ < 912 deriving (Typeable)+#endif -- | Helper type family for 'DomainPeriod' type family DomainConfigurationPeriod (config :: DomainConfiguration) :: Nat where@@ -439,9 +457,43 @@ type DomainResetPolarity (dom :: Domain) = DomainConfigurationResetPolarity (KnownConf dom) +-- * Time representation++-- | Gets time in 'Picoseconds' from time in 'Seconds'+type Seconds (s :: Nat) = Milliseconds (1000 * s)+-- | Gets time in 'Picoseconds' from time in 'Milliseconds'+type Milliseconds (ms :: Nat) = Microseconds (1000 * ms)+-- | Gets time in 'Picoseconds' from time in 'Microseconds'+type Microseconds (us :: Nat) = Nanoseconds (1000 * us)+-- | Gets time in 'Picoseconds' from time in 'Nanoseconds'+type Nanoseconds (ns :: Nat) = Picoseconds (1000 * ns)+-- | Gets time in 'Picoseconds' from time in picoseconds, essentially 'id'+type Picoseconds (ps :: Nat) = ps++-- | Converts a frequency in hertz to a period in picoseconds. This might lead to rounding+-- errors.+type HzToPeriod (hz :: Nat) = Seconds 1 `Div` hz++-- | The domain's clock frequency in hertz, calculated based on the period stored in+-- picoseconds. This might lead to rounding errors.+type DomainToHz (dom :: Domain) = PeriodToHz (DomainPeriod dom)++-- | Number of clock cycles required at the clock frequency of @dom@ before a minimum+-- @period@ has passed+type PeriodToCycles (dom :: Domain) (period :: Nat) = period `DivRU` DomainPeriod dom++-- | Converts a period in picoseconds to a frequency in hertz. This might lead to rounding+-- errors.+type PeriodToHz (period :: Nat) = (Seconds 1) `Div` period++-- | Number of clock cycles required at the clock frequency of @dom@ before a minimum+-- @period@ has passed. The same as 'PeriodToCycles'.+type ClockDivider (dom :: Domain) (period :: Nat) = PeriodToCycles dom period+ -- | Singleton version of 'DomainConfiguration' data SDomainConfiguration (dom :: Domain) (conf :: DomainConfiguration) where SDomainConfiguration ::+ 1 <= period => { sName :: SSymbol dom -- ^ Domain name , sPeriod :: SNat period@@ -775,14 +827,15 @@ tail# :: Signal dom a -> Signal dom a tail# (_ :- xs') = xs' +instance HasField (x :: k) r a => HasField x (Signal dom r) (Signal dom a) where+ getField = fmap (getField @x @r @a)+ instance Show a => Show (Signal dom a) where show (x :- xs) = show x ++ " " ++ show xs instance Lift a => Lift (Signal dom a) where lift ~(x :- _) = [| signal# x |]-#if MIN_VERSION_template_haskell(2,16,0) liftTyped = liftTypedFromUntyped-#endif instance Default a => Default (Signal dom a) where def = signal# def@@ -796,8 +849,7 @@ -- See -fstrict-mapSignal documentation in clash-prelude.cabal theSeq = if fStrictMapSignal then seqX else flip const go ~(xs@(a :- as)) = f a :- (a `theSeq` (xs `seq` go as))--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE mapSignal# #-}+{-# OPAQUE mapSignal# #-} {-# ANN mapSignal# hasBlackBox #-} instance Applicative (Signal dom) where@@ -806,14 +858,12 @@ signal# :: a -> Signal dom a signal# a = let s = a :- s in s--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE signal# #-}+{-# OPAQUE signal# #-} {-# ANN signal# hasBlackBox #-} appSignal# :: Signal dom (a -> b) -> Signal dom a -> Signal dom b appSignal# (f :- fs) xs@(~(a :- as)) = f a :- (xs `seq` appSignal# fs as) -- See [NOTE: Lazy ap]--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE appSignal# #-}+{-# OPAQUE appSignal# #-} {-# ANN appSignal# hasBlackBox #-} instance NFDataX a => NFDataX (Signal domain a) where@@ -854,8 +904,7 @@ -- Is currently treated as 'id' by the Clash compiler. joinSignal# :: Signal dom (Signal dom a) -> Signal dom a joinSignal# ~(xs :- xss) = head# xs :- joinSignal# (mapSignal# tail# xss)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE joinSignal# #-}+{-# OPAQUE joinSignal# #-} {-# ANN joinSignal# hasBlackBox #-} instance Num a => Num (Signal dom a) where@@ -867,6 +916,17 @@ signum = fmap signum fromInteger = signal# . fromInteger +instance Bounded a => Bounded (Signal dom a) where+ minBound = pure minBound+ maxBound = pure maxBound++instance SaturatingNum a => SaturatingNum (Signal dom a) where+ satAdd mode = liftA2 (satAdd mode)+ satSub mode = liftA2 (satSub mode)+ satMul mode = liftA2 (satMul mode)+ satSucc mode = fmap (satSucc mode)+ satPred mode = fmap (satPred mode)+ -- | __NB__: Not synthesizable -- -- __NB__: In \"@'foldr' f z s@\":@@ -884,8 +944,7 @@ -- * The @z@ element will never be used. foldr# :: (a -> b -> b) -> b -> Signal dom a -> b foldr# f z (a :- s) = a `f` (foldr# f z s)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE foldr# #-}+{-# OPAQUE foldr# #-} {-# ANN foldr# hasBlackBox #-} instance Traversable (Signal dom) where@@ -893,8 +952,7 @@ traverse# :: Applicative f => (a -> f b) -> Signal dom a -> f (Signal dom b) traverse# f (a :- s) = (:-) <$> f a <*> traverse# f s--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE traverse# #-}+{-# OPAQUE traverse# #-} {-# ANN traverse# hasBlackBox #-} -- * Clocks, resets, and enables@@ -1026,8 +1084,7 @@ => Signal testDom Bool -> Clock testDom tbClockGen done = Clock (done `seq` SSymbol) Nothing--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE tbClockGen #-}+{-# OPAQUE tbClockGen #-} {-# ANN tbClockGen hasBlackBox #-} -- | Femtoseconds expressed as an 'Int64'. Is a newtype to prevent accidental@@ -1105,8 +1162,7 @@ Clock dom tbDynamicClockGen periods ena = Clock (ena `seq` periods `seq` SSymbol) (Just periods)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE tbDynamicClockGen #-}+{-# OPAQUE tbDynamicClockGen #-} {-# ANN tbDynamicClockGen hasBlackBox #-} @@ -1156,8 +1212,7 @@ let asserted = replicate (snatToNum n) True in unsafeFromActiveHigh (fromList (asserted ++ repeat False)) {-# ANN resetGenN hasBlackBox #-}--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE resetGenN #-}+{-# OPAQUE resetGenN #-} -- | A reset signal belonging to a domain called /dom/.@@ -1181,7 +1236,7 @@ -- -- * <Clash-Explicit-Signal.html#metastability meta-stability> ----- For asynchronous resets it is unsafe because it can cause combinatorial+-- For asynchronous resets it is unsafe because it can cause combinational -- loops. In case of synchronous resets it can lead to -- <Clash-Explicit-Signal.html#metastability meta-stability> in the presence of -- asynchronous resets.@@ -1201,7 +1256,7 @@ -- -- * <Clash-Explicit-Signal.html#metastability meta-stability> ----- For asynchronous resets it is unsafe because it can cause combinatorial+-- For asynchronous resets it is unsafe because it can cause combinational -- loops. In case of synchronous resets it can lead to -- <Clash-Explicit-Signal.html#metastability meta-stability> in the presence of -- asynchronous resets.@@ -1219,7 +1274,7 @@ -- -- * <Clash-Explicit-Signal.html#metastability meta-stability> ----- For asynchronous resets it is unsafe because it can cause combinatorial+-- For asynchronous resets it is unsafe because it can cause combinational -- loops. In case of synchronous resets it can lead to -- <Clash-Explicit-Signal.html#metastability meta-stability> in the presence of -- asynchronous resets.@@ -1239,7 +1294,7 @@ -- -- * <Clash-Explicit-Signal.html#metastability meta-stability> ----- For asynchronous resets it is unsafe because it can cause combinatorial+-- For asynchronous resets it is unsafe because it can cause combinational -- loops. In case of synchronous resets it can lead to -- <Clash-Explicit-Signal.html#metastability meta-stability> in the presence of -- asynchronous resets.@@ -1256,7 +1311,7 @@ -- -- * <Clash-Explicit-Signal.html#metastability meta-stability> ----- For asynchronous resets it is unsafe because it can cause combinatorial+-- For asynchronous resets it is unsafe because it can cause combinational -- loops. In case of synchronous resets it can lead to -- <Clash-Explicit-Signal.html#metastability meta-stability> in the presence of -- asynchronous resets.@@ -1267,12 +1322,11 @@ :: Reset dom -> Signal dom Bool unsafeFromReset (Reset r) = r--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE unsafeFromReset #-}+{-# OPAQUE unsafeFromReset #-} {-# ANN unsafeFromReset hasBlackBox #-} -- | 'unsafeToReset' is unsafe. For asynchronous resets it is unsafe--- because it can introduce combinatorial loops. In case of synchronous resets+-- because it can introduce combinational loops. In case of synchronous resets -- it can lead to <Clash-Explicit-Signal.html#metastability meta-stability> -- issues in the presence of asynchronous resets. --@@ -1283,14 +1337,13 @@ => Signal dom Bool -> Reset dom unsafeToReset r = Reset r--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE unsafeToReset #-}+{-# OPAQUE unsafeToReset #-} {-# ANN unsafeToReset hasBlackBox #-} -- | Interpret a signal of bools as an active high reset and convert it to -- a reset signal corresponding to the domain's setting. ----- For asynchronous resets it is unsafe because it can cause combinatorial+-- For asynchronous resets it is unsafe because it can cause combinational -- loops. In case of synchronous resets it can lead to -- <Clash-Explicit-Signal.html#metastability meta-stability> in the presence of -- asynchronous resets.@@ -1307,7 +1360,7 @@ -- | Interpret a signal of bools as an active high reset and convert it to -- a reset signal corresponding to the domain's setting. ----- For asynchronous resets it is unsafe because it can cause combinatorial+-- For asynchronous resets it is unsafe because it can cause combinational -- loops. In case of synchronous resets it can lead to -- <Clash-Explicit-Signal.html#metastability meta-stability> in the presence of -- asynchronous resets.@@ -1326,7 +1379,7 @@ -- | Interpret a signal of bools as an active low reset and convert it to -- a reset signal corresponding to the domain's setting. ----- For asynchronous resets it is unsafe because it can cause combinatorial+-- For asynchronous resets it is unsafe because it can cause combinational -- loops. In case of synchronous resets it can lead to -- <Clash-Explicit-Signal.html#metastability meta-stability> in the presence of -- asynchronous resets.@@ -1343,7 +1396,7 @@ -- | Interpret a signal of bools as an active low reset and convert it to -- a reset signal corresponding to the domain's setting. ----- For asynchronous resets it is unsafe because it can cause combinatorial+-- For asynchronous resets it is unsafe because it can cause combinational -- loops. In case of synchronous resets it can lead to -- <Clash-Explicit-Signal.html#metastability meta-stability> in the presence of -- asynchronous resets.@@ -1374,6 +1427,30 @@ (.||.) :: Applicative f => f Bool -> f Bool -> f Bool (.||.) = liftA2 (||) +infix 2 .||+-- | The above type is a generalization for:+--+-- @+-- __(.||)__ :: 'Ord' a => 'Clash.Signal.Signal' Bool -> 'Bool' -> 'Clash.Signal.Signal' 'Bool'+-- @+--+-- It is a version of ('||') that allows comparing a @'Clash.Signal.Signal' Bool@ with a constant+-- @Bool@ and returns a 'Clash.Signal.Signal' of 'Bool'+(.||) :: Functor f => f Bool -> Bool -> f Bool+a .|| b = fmap (|| b) a++infixr 2 ||.+-- | The above type is a generalization for:+--+-- @+-- __(||.)__ :: 'Clash.Signal.Signal' 'Bool' -> 'Clash.Signal.Signal' 'Bool' -> 'Clash.Signal.Signal' 'Bool'+-- @+--+-- It is a version of ('||') that allows comparing a constant @Bool@ with a @'Clash.Signal.Signal' Bool@+-- and returns a 'Clash.Signal.Signal' of 'Bool'+(||.) :: Functor f => Bool -> f Bool -> f Bool+a ||. b = fmap (a ||) b+ infixr 3 .&&. -- | The above type is a generalization for: --@@ -1385,6 +1462,30 @@ (.&&.) :: Applicative f => f Bool -> f Bool -> f Bool (.&&.) = liftA2 (&&) +infixr 3 .&&+-- | The above type is a generalization for:+--+-- @+-- __(.&&)__ :: 'Clash.Signal.Signal' 'Bool' -> 'Clash.Signal.Signal' 'Bool' -> 'Clash.Signal.Signal' 'Bool'+-- @+--+-- It is a version of ('&&') that allows comparing a @'Clash.Signal.Signal' Bool@ with a+-- constant @Bool@ and returns a 'Clash.Signal.Signal' of 'Bool'+(.&&) :: (Functor f) => f Bool -> Bool -> f Bool+(.&&) a b = fmap (&& b) a++infixr 3 &&.+-- | The above type is a generalization for:+--+-- @+-- __(&&.)__ :: 'Clash.Signal.Signal' 'Bool' -> 'Clash.Signal.Signal' 'Bool' -> 'Clash.Signal.Signal' 'Bool'+-- @+--+-- It is a version of ('&&') that allows comparing a constant @'Bool@ with a+-- @'Clash.Signal.Signal' Bool@ and returns a 'Clash.Signal.Signal' of 'Bool'+(&&.) :: (Functor f) => Bool -> f Bool -> f Bool+(&&.) a b = fmap (a &&) b+ -- [Note: register strictness annotations] -- -- In order to produce the first (current) value of the register's output@@ -1427,8 +1528,7 @@ let o' = if e then x else o -- See [Note: register strictness annotations] in o `defaultSeqX` o :- (as `seq` go o' es xs)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE delay# #-}+{-# OPAQUE delay# #-} {-# ANN delay# hasBlackBox #-} -- | A register with a power up and reset value. Power up values are not@@ -1461,8 +1561,7 @@ syncRegister# clk rst ena powerUpVal resetVal SDomainConfiguration _name _period _edge SAsynchronous _init _polarity -> asyncRegister# clk rst ena powerUpVal resetVal--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE register# #-}+{-# OPAQUE register# #-} {-# ANN register# hasBlackBox #-} -- | Acts like 'id' if given domain allows powerup values, but returns a@@ -1507,8 +1606,7 @@ oE = if r then resetVal else (if e then x else o) -- [Note: register strictness annotations] in o `defaultSeqX` oR :- (as `seq` enas `seq` go oE rs es xs)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE asyncRegister# #-}+{-# OPAQUE asyncRegister# #-} {-# ANN asyncRegister# hasBlackBox #-} -- | Version of 'register#' that simulates a register on a synchronous@@ -1537,8 +1635,7 @@ oR = if r then resetVal else oE -- [Note: register strictness annotations] in o `defaultSeqX` o :- (rt `seq` enas `seq` as `seq` go oR rs es xs)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE syncRegister# #-}+{-# OPAQUE syncRegister# #-} {-# ANN syncRegister# dontTranslate #-} -- | The above type is a generalization for:@@ -1553,6 +1650,13 @@ mux = liftA3 (\b t f -> if b then t else f) {-# INLINE mux #-} +-- | A 'mux' extension muxing between a given argument and an updated version.+-- Given @apEn b f s@, output an updated version of @s@ (i.e., @f s@)+-- when @b@ is 'True', but return it unchanged (i.e., @s@) when @b@ is 'False'.+apEn :: Applicative f => f Bool -> (a -> a) -> f a -> f a+apEn cond upd x = mux cond (upd <$> x) x+{-# INLINE apEn #-}+ infix 4 .==. -- | The above type is a generalization for: --@@ -1564,6 +1668,30 @@ (.==.) :: (Eq a, Applicative f) => f a -> f a -> f Bool (.==.) = liftA2 (==) +infix 4 .==+-- | The above type is a generalization for:+--+-- @+-- __(.==)__ :: 'Eq' a => 'Clash.Signal.Signal' a -> a -> 'Clash.Signal.Signal' 'Bool'+-- @+--+-- It is a version of ('==') that allows comparing a @'Clash.Signal.Signal' a@ with a+-- constant @a@ and returns a 'Clash.Signal.Signal' of 'Bool'+(.==) :: (Eq a, Functor f) => f a -> a -> f Bool+(.==) a b = fmap (==b) a++infix 4 ==.+-- | The above type is a generalization for:+--+-- @+-- __(==.)__ :: 'Eq' a => a -> 'Clash.Signal.Signal' a -> 'Clash.Signal.Signal' 'Bool'+-- @+--+-- It is a version of ('==') that allows comparing a @'Clash.Signal.Signal' a@ with a+-- constant @a@ and returns a 'Clash.Signal.Signal' of 'Bool'+(==.) :: (Eq a, Functor f) => a -> f a -> f Bool+(==.) a b = fmap (a==) b+ infix 4 ./=. -- | The above type is a generalization for: --@@ -1575,6 +1703,31 @@ (./=.) :: (Eq a, Applicative f) => f a -> f a -> f Bool (./=.) = liftA2 (/=) +infix 4 ./=+-- | The above type is a generalization for:+--+-- @+-- __(./=)__ :: 'Eq' a => 'Clash.Signal.Signal' a -> a -> 'Clash.Signal.Signal' 'Bool'+-- @+--+-- It is a version of ('/=') that allows comparing a @'Clash.Signal.Signal' a@ with a+-- constant @a@ and returns a 'Clash.Signal.Signal' of 'Bool'+(./=) :: (Eq a, Functor f) => f a -> a -> f Bool+(./=) a b = fmap (/=b) a++infix 4 /=.+-- | The above type is a generalization for:+--+-- @+-- __(/=.)__ :: 'Eq' a => a -> 'Clash.Signal.Signal' a -> 'Clash.Signal.Signal' 'Bool'+-- @+--+-- It is a version of ('/=') that allows comparing a @'Clash.Signal.Signal' a@ with a+-- constant @a@ and returns a 'Clash.Signal.Signal' of 'Bool'++(/=.) :: (Eq a, Functor f) => a -> f a -> f Bool+(/=.) a b = fmap (a /=) b+ infix 4 .<. -- | The above type is a generalization for: --@@ -1586,6 +1739,30 @@ (.<.) :: (Ord a, Applicative f) => f a -> f a -> f Bool (.<.) = liftA2 (<) +infix 4 <.+-- | The above type is a generalization for:+--+-- @+-- __(<.)__ :: 'Ord' a => a -> 'Clash.Signal.Signal' a -> 'Clash.Signal.Signal' 'Bool'+-- @+--+-- It is a version of ('<') that allows comparing a @'Clash.Signal.Signal' a@ with a constant+-- @a@ and returns a 'Clash.Signal.Signal' of 'Bool'+(<.) :: (Ord a, Functor f) => a -> f a -> f Bool+(<.) a b = fmap (a<) b++infix 4 .<+-- | The above type is a generalization for:+--+-- @+-- __(.<)__ :: 'Ord' a => 'Clash.Signal.Signal' a -> a -> 'Clash.Signal.Signal' 'Bool'+-- @+--+-- It is a version of ('<') that allows comparing a @'Clash.Signal.Signal' a@ with a constant+-- @a@ and returns a 'Clash.Signal.Signal' of 'Bool'+(.<) :: (Ord a, Functor f) => f a -> a -> f Bool+(.<) a b = fmap (<b) a+ infix 4 .<=. -- | The above type is a generalization for: --@@ -1597,6 +1774,30 @@ (.<=.) :: (Ord a, Applicative f) => f a -> f a -> f Bool (.<=.) = liftA2 (<=) +infix 4 .<=+-- | The above type is a generalization for:+--+-- @+-- __(.<=)__ :: 'Ord' a => 'Clash.Signal.Signal' a -> a -> 'Clash.Signal.Signal' 'Bool'+-- @+--+-- It is a version of ('GHC.TypeNats.<=') that allows comparing a @'Clash.Signal.Signal' a@ with a constant+-- @a@ and returns a 'Clash.Signal.Signal' of 'Bool'+(.<=) :: (Ord a, Functor f) => f a -> a -> f Bool+(.<=) a b = fmap (<=b) a++infix 4 <=.+-- | The above type is a generalization for:+--+-- @+-- __(<=.)__ :: 'Ord' a => a -> 'Clash.Signal.Signal' a -> 'Clash.Signal.Signal' 'Bool'+-- @+--+-- It is a version of ('GHC.TypeNats.<=') that allows comparing a @'Clash.Signal.Signal' a@ with a constant+-- @a@ and returns a 'Clash.Signal.Signal' of 'Bool'+(<=.) :: (Ord a, Functor f) => a -> f a -> f Bool+(<=.) a b = fmap (a<=)b+ infix 4 .>. -- | The above type is a generalization for: --@@ -1608,6 +1809,30 @@ (.>.) :: (Ord a, Applicative f) => f a -> f a -> f Bool (.>.) = liftA2 (>) +infix 4 .>+-- | The above type is a generalization for:+--+-- @+-- __(.>)__ :: 'Ord' a => 'Clash.Signal.Signal' a -> a -> 'Clash.Signal.Signal' 'Bool'+-- @+--+-- It is a version of ('>') that allows comparing a @'Clash.Signal.Signal' a@ with a constant+-- @a@ and returns a 'Clash.Signal.Signal' of 'Bool'+(.>) :: (Ord a, Functor f) => f a -> a -> f Bool+(.>) a b = fmap (>b) a++infix 4 >.+-- | The above type is a generalization for:+--+-- @+-- __(>.)__ :: 'Ord' a => a -> 'Clash.Signal.Signal' a -> 'Clash.Signal.Signal' 'Bool'+-- @+--+-- It is a version of ('>') that allows comparing a @'Clash.Signal.Signal' a@ with a constant+-- @a@ and returns a 'Clash.Signal.Signal' of 'Bool'+(>.) :: (Ord a, Functor f) => a -> f a -> f Bool+(>.) a b = fmap (a>) b+ infix 4 .>=. -- | The above type is a generalization for: --@@ -1619,6 +1844,30 @@ (.>=.) :: (Ord a, Applicative f) => f a -> f a -> f Bool (.>=.) = liftA2 (>=) +infix 4 .>=+-- | The above type is a generalization for:+--+-- @+-- __(.>=)__ :: 'Ord' a => 'Clash.Signal.Signal' a -> a -> 'Clash.Signal.Signal' 'Bool'+-- @+--+-- It is a version of ('>=') that allows comparing a @'Clash.Signal.Signal' a@ with a constant+-- @a@ and returns a 'Clash.Signal.Signal' of 'Bool'+(.>=) :: (Ord a, Functor f) => f a -> a -> f Bool+(.>=) a b = fmap (>=b) a++infix 4 >=.+-- | The above type is a generalization for:+--+-- @+-- __(>=.)__ :: 'Ord' a => a -> 'Clash.Signal.Signal' a -> 'Clash.Signal.Signal' 'Bool'+-- @+--+-- It is a version of ('>=') that allows comparing a @'Clash.Signal.Signal' a@ with a constant+-- @a@ and returns a 'Clash.Signal.Signal' of 'Bool'+(>=.) :: (Ord a, Functor f) => a -> f a -> f Bool+(>=.) a b = fmap (a>=) b+ instance Fractional a => Fractional (Signal dom a) where (/) = liftA2 (/) recip = fmap recip@@ -1875,8 +2124,7 @@ return (out, next) go inputRefs (dut inputs)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE signalAutomaton #-}+{-# OPAQUE signalAutomaton #-} infiniteRefList :: a -> IO (Signal dom (IORef a)) infiniteRefList val = go
src/Clash/Signal/Internal/Ambiguous.hs view
@@ -25,8 +25,7 @@ case knownDomain @dom of SDomainConfiguration{sPeriod} -> sPeriod--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE clockPeriod #-}+{-# OPAQUE clockPeriod #-} -- @NOINLINE: https://github.com/clash-lang/clash-compiler/issues/662 -- | Get 'ActiveEdge' from a KnownDomain context. Example usage:@@ -46,8 +45,7 @@ case knownDomain @dom of SDomainConfiguration{sActiveEdge} -> sActiveEdge--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE activeEdge #-}+{-# OPAQUE activeEdge #-} -- @NOINLINE: https://github.com/clash-lang/clash-compiler/issues/662 -- | Get 'ResetKind' from a KnownDomain context. Example usage:@@ -67,8 +65,7 @@ case knownDomain @dom of SDomainConfiguration{sResetKind} -> sResetKind--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE resetKind #-}+{-# OPAQUE resetKind #-} -- @NOINLINE: https://github.com/clash-lang/clash-compiler/issues/662 -- | Get 'InitBehavior' from a KnownDomain context. Example usage:@@ -88,8 +85,7 @@ case knownDomain @dom of SDomainConfiguration{sInitBehavior} -> sInitBehavior--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE initBehavior #-}+{-# OPAQUE initBehavior #-} -- @NOINLINE: https://github.com/clash-lang/clash-compiler/issues/662 -- | Get 'ResetPolarity' from a KnownDomain context. Example usage:@@ -109,8 +105,7 @@ case knownDomain @dom of SDomainConfiguration{sResetPolarity} -> sResetPolarity--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE resetPolarity #-}+{-# OPAQUE resetPolarity #-} -- @NOINLINE: https://github.com/clash-lang/clash-compiler/issues/662 -- | Like 'knownDomain but yields a 'VDomainConfiguration'. Should only be used
src/Clash/Signal/Trace.hs view
@@ -155,8 +155,7 @@ -- | Map of traces used by the non-internal trace and dumpvcd functions. traceMap# :: IORef TraceMap traceMap# = unsafePerformIO (newIORef Map.empty)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE traceMap# #-}+{-# OPAQUE traceMap# #-} mkTrace :: HasCallStack@@ -199,8 +198,7 @@ , signal) where width = snatToNum (SNat @(BitSize a))--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE traceSignal# #-}+{-# OPAQUE traceSignal# #-} -- | Trace a single vector signal: each element in the vector will show up as -- a different trace. If the trace name already exists, this function will emit@@ -226,8 +224,7 @@ where trace' i s = traceSignal# traceMap period (name' i) s name' i = vecTraceName ++ "_" ++ show i--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE traceVecSignal# #-}+{-# OPAQUE traceVecSignal# #-} -- | Trace a single signal. Will emit an error if a signal with the same name -- was previously registered.@@ -251,8 +248,7 @@ SDomainConfiguration{sPeriod} -> unsafePerformIO $ traceSignal# traceMap# (snatToNum sPeriod) traceName signal--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE traceSignal #-}+{-# OPAQUE traceSignal #-} {-# ANN traceSignal hasBlackBox #-} -- | Trace a single signal. Will emit an error if a signal with the same name@@ -273,8 +269,7 @@ -> Signal dom a traceSignal1 traceName signal = unsafePerformIO (traceSignal# traceMap# 1 traceName signal)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE traceSignal1 #-}+{-# OPAQUE traceSignal1 #-} {-# ANN traceSignal1 hasBlackBox #-} -- | Trace a single vector signal: each element in the vector will show up as@@ -301,8 +296,7 @@ SDomainConfiguration{sPeriod} -> unsafePerformIO $ traceVecSignal# traceMap# (snatToNum sPeriod) traceName signal--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE traceVecSignal #-}+{-# OPAQUE traceVecSignal #-} {-# ANN traceVecSignal hasBlackBox #-} -- | Trace a single vector signal: each element in the vector will show up as@@ -325,8 +319,7 @@ -> Signal dom (Vec (n+1) a) traceVecSignal1 traceName signal = unsafePerformIO $ traceVecSignal# traceMap# 1 traceName signal--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE traceVecSignal1 #-}+{-# OPAQUE traceVecSignal1 #-} {-# ANN traceVecSignal1 hasBlackBox #-} data VCDFile = VCDFile [DeclarationCommand] [SimulationCommand]
src/Clash/Sized/Fixed.hs view
@@ -1,6 +1,6 @@ {-| Copyright : (C) 2013-2016, University of Twente,- 2021, QBayLogic B.V.,+ 2021-2025, QBayLogic B.V., License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> @@ -113,7 +113,7 @@ import Control.Arrow ((***), second) import Data.Bits (Bits (..), FiniteBits) import Data.Data (Data)-import Data.Default.Class (Default (..))+import Data.Default (Default (..)) import Data.Either (isLeft) import Data.Kind (Type) import Text.Read (Read(..))@@ -126,15 +126,9 @@ import Language.Haskell.TH (Q, appT, conT, litT, mkName, numTyLit, sigE) import Language.Haskell.TH.Syntax (Lift(..))-#if MIN_VERSION_template_haskell(2,16,0) import Language.Haskell.TH.Compat-#endif-#if MIN_VERSION_template_haskell(2,17,0) import Language.Haskell.TH (Quote) import qualified Language.Haskell.TH as TH-#else-import Language.Haskell.TH (TExp, TypeQ)-#endif import Test.QuickCheck (Arbitrary, CoArbitrary) import Clash.Class.BitPack (BitPack (..))@@ -558,15 +552,9 @@ (decFixed (typeRep (asRepProxy f)) (natVal (asIntProxy f)) (natVal f))-#if MIN_VERSION_template_haskell(2,16,0) liftTyped = liftTypedFromUntyped-#endif -#if MIN_VERSION_template_haskell(2,17,0) decFixed :: Quote m => TypeRep -> Integer -> Integer -> m TH.Type-#else-decFixed :: TypeRep -> Integer -> Integer -> TypeQ-#endif decFixed r i f = do foldl appT (conT ''Fixed) [ conT (mkName (show r)) , litT (numTyLit i)@@ -715,11 +703,7 @@ , Bounded (rep size) , Integral (rep size) ) => Double-#if MIN_VERSION_template_haskell(2,17,0) -> TH.Code Q (Fixed rep int frac)-#else- -> Q (TExp (Fixed rep int frac))-#endif fLit a = [|| Fixed (fromInteger sat) ||] where rMax = toInteger (maxBound :: rep size)
src/Clash/Sized/Index.hs view
@@ -1,5 +1,6 @@ {-| Copyright : (C) 2013-2016, University of Twente+ 2025 , QBayLogic B.V. License : BSD2 (see the file LICENSE) Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com> -}@@ -18,7 +19,6 @@ import GHC.TypeLits (KnownNat, type (^)) import GHC.TypeLits.Extra (CLog) -- documentation only -import Clash.Promoted.Nat (SNat (..), pow2SNat) import Clash.Sized.Internal.BitVector (BitVector) import Clash.Sized.Internal.Index
src/Clash/Sized/Internal/BitVector.hs view
@@ -2,7 +2,7 @@ Copyright : (C) 2013-2016, University of Twente, 2019 , Gergő Érdi 2016-2019, Myrtle Software Ltd,- 2021-2024, QBayLogic B.V.+ 2021-2025, QBayLogic B.V. 2023 , Nadia Chambers License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com>@@ -140,7 +140,7 @@ import Control.Lens (Index, Ixed (..), IxValue) import Data.Bits (Bits (..), FiniteBits (..)) import Data.Data (Data)-import Data.Default.Class (Default (..))+import Data.Default (Default (..)) import Data.Either (isLeft) import Data.Proxy (Proxy (..)) import Data.Typeable (Typeable, typeOf)@@ -149,41 +149,23 @@ import Numeric (readOct, readHex) import GHC.Exts (Word#, Word (W#), eqWord#, int2Word#, isTrue#, uncheckedShiftRL#)-#if MIN_VERSION_base(4,15,0) import GHC.Exts (minusWord#, gtWord#, word2Int#, dataToTag#) import GHC.Num.BigNat (bigNatShiftR#, bigNatToWord) import GHC.Num.Integer (integerFromNatural, integerToNatural) import GHC.Num.Natural (Natural (..), naturalFromWord, naturalShiftL, naturalShiftR, naturalToWord)-#else-import GHC.Exts ((>#), dataToTag#)-import qualified GHC.Exts-import GHC.Integer.GMP.Internals (Integer (..), bigNatToWord, shiftRBigNat)-import GHC.Natural- (Natural (..), naturalFromInteger, wordToNatural)-#endif import GHC.Natural (naturalToInteger) import GHC.Stack (withFrozenCallStack) import GHC.TypeLits (KnownNat, Nat, type (+), type (-))-#if MIN_VERSION_base(4,15,0) import GHC.TypeNats (natVal)-#else-import GHC.TypeLits (natVal)-#endif import GHC.TypeLits.Extra (Max) import Language.Haskell.TH (Lit (..), ExpQ, Type(ConT, AppT, LitT), Exp(VarE, AppE, SigE, LitE), TyLit(NumTyLit), Pat, Q, appT, conT, litE, litP, litT, mkName, numTyLit, sigE, tupE, tupP, varP) import Language.Haskell.TH.Syntax (Lift(..))-#if MIN_VERSION_template_haskell(2,16,0) import Language.Haskell.TH.Compat-#endif-#if MIN_VERSION_template_haskell(2,17,0) import Language.Haskell.TH (Quote)-#else-import Language.Haskell.TH (TypeQ)-#endif import System.IO.Unsafe (unsafeDupablePerformIO) import Test.QuickCheck.Arbitrary (Arbitrary (..), CoArbitrary (..), arbitraryBoundedIntegral,@@ -267,15 +249,13 @@ -- * Constructions -- ** Initialisation--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE high #-}+{-# OPAQUE high #-} {-# ANN high hasBlackBox #-} -- | logic '1' high :: Bit high = Bit 0 1 --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE low #-}+{-# OPAQUE low #-} {-# ANN low hasBlackBox #-} -- | logic '0' low :: Bit@@ -305,9 +285,7 @@ instance Lift Bit where lift (Bit m i) = [| fromInteger## $(litE (WordPrimL (toInteger m))) i |] {-# NOINLINE lift #-}-#if MIN_VERSION_template_haskell(2,16,0) liftTyped = liftTypedFromUntyped-#endif instance Eq Bit where (==) = eq##@@ -315,14 +293,12 @@ eq## :: Bit -> Bit -> Bool eq## b1 b2 = eq# (pack# b1) (pack# b2)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE eq## #-}+{-# OPAQUE eq## #-} {-# ANN eq## hasBlackBox #-} neq## :: Bit -> Bit -> Bool neq## b1 b2 = neq# (pack# b1) (pack# b2)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE neq## #-}+{-# OPAQUE neq## #-} {-# ANN neq## hasBlackBox #-} instance Ord Bit where@@ -333,20 +309,16 @@ lt##,ge##,gt##,le## :: Bit -> Bit -> Bool lt## b1 b2 = lt# (pack# b1) (pack# b2)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE lt## #-}+{-# OPAQUE lt## #-} {-# ANN lt## hasBlackBox #-} ge## b1 b2 = ge# (pack# b1) (pack# b2)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE ge## #-}+{-# OPAQUE ge## #-} {-# ANN ge## hasBlackBox #-} gt## b1 b2 = gt# (pack# b1) (pack# b2)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE gt## #-}+{-# OPAQUE gt## #-} {-# ANN gt## hasBlackBox #-} le## b1 b2 = le# (pack# b1) (pack# b2)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE le## #-}+{-# OPAQUE le## #-} {-# ANN le## hasBlackBox #-} instance Enum Bit where@@ -355,8 +327,7 @@ toEnum## :: Int -> Bit toEnum## = fromInteger## 0## . toInteger--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE toEnum## #-}+{-# OPAQUE toEnum## #-} {-# ANN toEnum## hasBlackBox #-} instance Bounded Bit where@@ -370,15 +341,14 @@ (+) = xor## (-) = xor## (*) = and##- negate = complement##+ negate = id abs = id signum b = b fromInteger = fromInteger## 0## fromInteger## :: Word# -> Integer -> Bit fromInteger## m# i = Bit ((W# m#) `mod` 2) (fromInteger i `mod` 2)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE fromInteger## #-}+{-# OPAQUE fromInteger## #-} {-# ANN fromInteger## hasBlackBox #-} instance Real Bit where@@ -423,52 +393,37 @@ and##, or##, xor## :: Bit -> Bit -> Bit and## (Bit m1 v1) (Bit m2 v2) = Bit mask (v1 .&. v2 .&. complement mask) where mask = (m1.&.v2 .|. m1.&.m2 .|. m2.&.v1)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE and## #-}+{-# OPAQUE and## #-} {-# ANN and## hasBlackBox #-} or## (Bit m1 v1) (Bit m2 v2) = Bit mask ((v1 .|. v2) .&. complement mask) where mask = m1 .&. complement v2 .|. m1.&.m2 .|. m2 .&. complement v1--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE or## #-}+{-# OPAQUE or## #-} {-# ANN or## hasBlackBox #-} xor## (Bit m1 v1) (Bit m2 v2) = Bit mask ((v1 `xor` v2) .&. complement mask) where mask = m1 .|. m2--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE xor## #-}+{-# OPAQUE xor## #-} {-# ANN xor## hasBlackBox #-} complement## :: Bit -> Bit complement## (Bit m v) = Bit m (complementB v .&. complementB m) where complementB (W# b#) = W# (int2Word# (eqWord# b# 0##))--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE complement## #-}+{-# OPAQUE complement## #-} {-# ANN complement## hasBlackBox #-} -- *** BitPack pack# :: Bit -> BitVector 1-#if MIN_VERSION_base(4,15,0) pack# (Bit (W# m) (W# b)) = BV (NS m) (NS b)-#else-pack# (Bit (W# m) (W# b)) = BV (NatS# m) (NatS# b)-#endif--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE pack# #-}+{-# OPAQUE pack# #-} {-# ANN pack# hasBlackBox #-} unpack# :: BitVector 1 -> Bit unpack# (BV m b) = Bit (go m) (go b) where-#if MIN_VERSION_base(4,15,0) go (NS w) = W# w go (NB w) = bigNatToWord w-#else- go (NatS# w) = W# w- go (NatJ# w) = W# (bigNatToWord w)-#endif--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE unpack# #-}+{-# OPAQUE unpack# #-} {-# ANN unpack# hasBlackBox #-} -- * Instances@@ -635,15 +590,13 @@ (==) = eq# (/=) = neq# --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE eq# #-}+{-# OPAQUE eq# #-} {-# ANN eq# hasBlackBox #-} eq# :: KnownNat n => BitVector n -> BitVector n -> Bool eq# (BV 0 v1) (BV 0 v2 ) = v1 == v2 eq# bv1 bv2 = undefErrorI "==" bv1 bv2 --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE neq# #-}+{-# OPAQUE neq# #-} {-# ANN neq# hasBlackBox #-} neq# :: KnownNat n => BitVector n -> BitVector n -> Bool neq# (BV 0 v1) (BV 0 v2) = v1 /= v2@@ -656,23 +609,19 @@ (<=) = le# lt#,ge#,gt#,le# :: KnownNat n => BitVector n -> BitVector n -> Bool--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE lt# #-}+{-# OPAQUE lt# #-} {-# ANN lt# hasBlackBox #-} lt# (BV 0 n) (BV 0 m) = n < m lt# bv1 bv2 = undefErrorI "<" bv1 bv2--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE ge# #-}+{-# OPAQUE ge# #-} {-# ANN ge# hasBlackBox #-} ge# (BV 0 n) (BV 0 m) = n >= m ge# bv1 bv2 = undefErrorI ">=" bv1 bv2--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE gt# #-}+{-# OPAQUE gt# #-} {-# ANN gt# hasBlackBox #-} gt# (BV 0 n) (BV 0 m) = n > m gt# bv1 bv2 = undefErrorI ">" bv1 bv2--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE le# #-}+{-# OPAQUE le# #-} {-# ANN le# hasBlackBox #-} le# (BV 0 n) (BV 0 m) = n <= m le# bv1 bv2 = undefErrorI "<=" bv1 bv2@@ -691,26 +640,19 @@ toEnum# :: forall n. KnownNat n => Int -> BitVector n toEnum# = fromInteger# 0 . toInteger--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE toEnum# #-}+{-# OPAQUE toEnum# #-} {-# ANN toEnum# hasBlackBox #-} fromEnum# :: forall n. KnownNat n => BitVector n -> Int fromEnum# = fromEnum . toInteger#--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE fromEnum# #-}+{-# OPAQUE fromEnum# #-} {-# ANN fromEnum# hasBlackBox #-} enumFrom# :: forall n. KnownNat n => BitVector n -> [BitVector n] enumFrom# (BV 0 x) = map (BV 0 . (`mod` m)) [x .. unsafeToNatural (maxBound :: BitVector n)]-#if MIN_VERSION_base(4,15,0) where m = 1 `naturalShiftL` naturalToWord (natVal (Proxy @n))-#else- where m = 1 `shiftL` fromInteger (natVal (Proxy @n))-#endif enumFrom# bv = undefErrorU "enumFrom" bv--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE enumFrom# #-}+{-# OPAQUE enumFrom# #-} enumFromThen# :: forall n@@ -723,14 +665,9 @@ where bound = if x <= y then maxBound else minBound :: BitVector n toBvs = map (BV 0 . (`mod` m))-#if MIN_VERSION_base(4,15,0) m = 1 `naturalShiftL` naturalToWord (natVal (Proxy @n))-#else- m = 1 `shiftL` fromInteger (natVal (Proxy @n))-#endif enumFromThen# bv1 bv2 = undefErrorP "enumFromThen" bv1 bv2--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE enumFromThen# #-}+{-# OPAQUE enumFromThen# #-} enumFromTo# :: forall n@@ -739,14 +676,9 @@ -> BitVector n -> [BitVector n] enumFromTo# (BV 0 x) (BV 0 y) = map (BV 0 . (`mod` m)) [x .. y]-#if MIN_VERSION_base(4,15,0) where m = 1 `naturalShiftL` naturalToWord (natVal (Proxy @n))-#else- where m = 1 `shiftL` fromInteger (natVal (Proxy @n))-#endif enumFromTo# bv1 bv2 = undefErrorP "enumFromTo" bv1 bv2--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE enumFromTo# #-}+{-# OPAQUE enumFromTo# #-} enumFromThenTo# :: forall n@@ -756,14 +688,9 @@ -> BitVector n -> [BitVector n] enumFromThenTo# (BV 0 x1) (BV 0 x2) (BV 0 y) = map (BV 0 . (`mod` m)) [x1, x2 .. y]-#if MIN_VERSION_base(4,15,0) where m = 1 `naturalShiftL` naturalToWord (natVal (Proxy @n))-#else- where m = 1 `shiftL` fromInteger (natVal (Proxy @n))-#endif enumFromThenTo# bv1 bv2 bv3 = undefErrorP3 "enumFromTo" bv1 bv2 bv3--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE enumFromThenTo# #-}+{-# OPAQUE enumFromThenTo# #-} instance KnownNat n => Bounded (BitVector n) where@@ -772,14 +699,12 @@ minBound# :: BitVector n minBound# = BV 0 0--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE minBound# #-}+{-# OPAQUE minBound# #-} {-# ANN minBound# hasBlackBox #-} maxBound# :: forall n. KnownNat n => BitVector n maxBound# = let m = 1 `shiftL` natToNum @n in BV 0 (m-1)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE maxBound# #-}+{-# OPAQUE maxBound# #-} {-# ANN maxBound# hasBlackBox #-} -- | __NB__: 'fromInteger'/'fromIntegral' can cause unexpected truncation, as@@ -795,50 +720,34 @@ fromInteger = fromInteger# 0 (+#),(-#),(*#) :: forall n . KnownNat n => BitVector n -> BitVector n -> BitVector n--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE (+#) #-}+{-# OPAQUE (+#) #-} {-# ANN (+#) hasBlackBox #-} (+#) = go where go (BV 0 i) (BV 0 j) = BV 0 (addMod m i j) go bv1 bv2 = undefErrorI "+" bv1 bv2 -#if MIN_VERSION_base(4,15,0) m = 1 `naturalShiftL` naturalToWord (natVal (Proxy @n))-#else- m = 1 `shiftL` fromInteger (natVal (Proxy @n))-#endif --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE (-#) #-}+{-# OPAQUE (-#) #-} {-# ANN (-#) hasBlackBox #-} (-#) = go where go (BV 0 i) (BV 0 j) = BV 0 (subMod m i j) go bv1 bv2 = undefErrorI "-" bv1 bv2 -#if MIN_VERSION_base(4,15,0) m = 1 `naturalShiftL` naturalToWord (natVal (Proxy @n))-#else- m = 1 `shiftL` fromInteger (natVal (Proxy @n))-#endif --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE (*#) #-}+{-# OPAQUE (*#) #-} {-# ANN (*#) hasBlackBox #-} (*#) = go where go (BV 0 i) (BV 0 j) = BV 0 (mulMod2 m i j) go bv1 bv2 = undefErrorI "*" bv1 bv2 -#if MIN_VERSION_base(4,15,0) m = (1 `naturalShiftL` naturalToWord (natVal (Proxy @n))) - 1-#else- m = (1 `shiftL` fromInteger (natVal (Proxy @n))) - 1-#endif --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE negate# #-}+{-# OPAQUE negate# #-} {-# ANN negate# hasBlackBox #-} negate# :: forall n . KnownNat n => BitVector n -> BitVector n negate# = go@@ -846,27 +755,16 @@ go (BV 0 i) = BV 0 (negateMod m i) go bv = undefErrorU "negate" bv -#if MIN_VERSION_base(4,15,0) m = 1 `naturalShiftL` naturalToWord (natVal (Proxy @n))-#else- m = 1 `shiftL` fromInteger (natVal (Proxy @n))-#endif --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE fromInteger# #-}+{-# OPAQUE fromInteger# #-} {-# ANN fromInteger# hasBlackBox #-} fromInteger# :: KnownNat n => Natural -> Integer -> BitVector n fromInteger# m i = sz `seq` mx where-#if MIN_VERSION_base(4,15,0) mx = BV (m `mod` sz) (integerToNatural (i `mod` integerFromNatural sz)) sz = 1 `naturalShiftL` naturalToWord (natVal mx)-#else- mx = BV (m `mod` naturalFromInteger sz)- (naturalFromInteger (i `mod` sz))- sz = 1 `shiftL` fromInteger (natVal mx) :: Integer-#endif instance (KnownNat m, KnownNat n) => ExtendingNum (BitVector m) (BitVector n) where type AResult (BitVector m) (BitVector n) = BitVector (Max m n + 1)@@ -875,15 +773,13 @@ type MResult (BitVector m) (BitVector n) = BitVector (m + n) mul = times# --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE plus# #-}+{-# OPAQUE plus# #-} {-# ANN plus# hasBlackBox #-} plus# :: (KnownNat m, KnownNat n) => BitVector m -> BitVector n -> BitVector (Max m n + 1) plus# (BV 0 a) (BV 0 b) = BV 0 (a + b) plus# bv1 bv2 = undefErrorP "add" bv1 bv2 --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE minus# #-}+{-# OPAQUE minus# #-} {-# ANN minus# hasBlackBox #-} minus# :: forall m n . (KnownNat m, KnownNat n) => BitVector m -> BitVector n -> BitVector (Max m n + 1)@@ -892,14 +788,9 @@ go (BV 0 a) (BV 0 b) = BV 0 (subMod m a b) go bv1 bv2 = undefErrorP "sub" bv1 bv2 -#if MIN_VERSION_base(4,15,0) m = 1 `naturalShiftL` naturalToWord (natVal (Proxy @(Max m n + 1)))-#else- m = 1 `shiftL` fromInteger (natVal (Proxy @(Max m n + 1)))-#endif --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE times# #-}+{-# OPAQUE times# #-} {-# ANN times# hasBlackBox #-} times# :: (KnownNat m, KnownNat n) => BitVector m -> BitVector n -> BitVector (m + n) times# (BV 0 a) (BV 0 b) = BV 0 (a * b)@@ -921,24 +812,25 @@ toInteger = toInteger# quot#,rem# :: KnownNat n => BitVector n -> BitVector n -> BitVector n--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE quot# #-}+{-# OPAQUE quot# #-} {-# ANN quot# hasBlackBox #-} quot# (BV 0 i) (BV 0 j) = BV 0 (i `quot` j) quot# bv1 bv2 = undefErrorP "quot" bv1 bv2--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE rem# #-}+{-# OPAQUE rem# #-} {-# ANN rem# hasBlackBox #-} rem# (BV 0 i) (BV 0 j) = BV 0 (i `rem` j) rem# bv1 bv2 = undefErrorP "rem" bv1 bv2 --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE toInteger# #-}+{-# OPAQUE toInteger# #-} {-# ANN toInteger# hasBlackBox #-} toInteger# :: KnownNat n => BitVector n -> Integer toInteger# (BV 0 i) = naturalToInteger i toInteger# bv = undefErrorU "toInteger" bv +-- | @'shiftR' a n@:+--+-- * Returns 0 if @n >= 'bitSize' a@+-- * 'Clash.XException.XException' if @n < 0@ instance KnownNat n => Bits (BitVector n) where (.&.) = and# (.|.) = or#@@ -972,8 +864,7 @@ countTrailingZerosBV = V.foldl (\l r -> if eq## r low then 1 + l else 0) 0 . V.bv2v {-# INLINE countTrailingZerosBV #-} --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE reduceAnd# #-}+{-# OPAQUE reduceAnd# #-} {-# ANN reduceAnd# hasBlackBox #-} reduceAnd# :: KnownNat n => BitVector n -> Bit reduceAnd# bv@(BV 0 i) = Bit 0 (W# (int2Word# (dataToTag# check)))@@ -992,8 +883,7 @@ sz = natVal bv maxI = (2 ^ sz) - 1 --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE reduceOr# #-}+{-# OPAQUE reduceOr# #-} {-# ANN reduceOr# hasBlackBox #-} reduceOr# :: KnownNat n => BitVector n -> Bit reduceOr# (BV 0 i) = Bit 0 (W# (int2Word# (dataToTag# check)))@@ -1005,8 +895,7 @@ complementN = complementMod $ natVal bv defI = i .&. (complementN m) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE reduceXor# #-}+{-# OPAQUE reduceXor# #-} {-# ANN reduceXor# hasBlackBox #-} reduceXor# :: KnownNat n => BitVector n -> Bit reduceXor# (BV 0 i) = Bit 0 (fromIntegral (popCount i `mod` 2))@@ -1017,29 +906,18 @@ -- * Accessors -- ** Length information--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE size# #-}+{-# OPAQUE size# #-} {-# ANN size# hasBlackBox #-} size# :: KnownNat n => BitVector n -> Int-#if MIN_VERSION_base(4,15,0) size# bv = fromIntegral (natVal bv)-#else-size# bv = fromInteger (natVal bv)-#endif --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE maxIndex# #-}+{-# OPAQUE maxIndex# #-} {-# ANN maxIndex# hasBlackBox #-} maxIndex# :: KnownNat n => BitVector n -> Int-#if MIN_VERSION_base(4,15,0) maxIndex# bv = fromIntegral (natVal bv) - 1-#else-maxIndex# bv = fromInteger (natVal bv) - 1-#endif -- ** Indexing--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE index# #-}+{-# OPAQUE index# #-} {-# ANN index# hasBlackBox #-} index# :: KnownNat n => BitVector n -> Int -> Bit index# bv@(BV m v) i@@ -1047,19 +925,14 @@ (W# (int2Word# (dataToTag# (testBit v i)))) | otherwise = err where-#if MIN_VERSION_base(4,15,0) sz = fromIntegral (natVal bv)-#else- sz = fromInteger (natVal bv)-#endif err = error $ concat [ "(!): " , show i , " is out of range " , formatRange 0 (sz - 1) ] --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE msb# #-}+{-# OPAQUE msb# #-} {-# ANN msb# hasBlackBox #-} -- | MSB msb# :: forall n . KnownNat n => BitVector n -> Bit@@ -1067,7 +940,6 @@ = Bit (msbN m) (msbN v) where-#if MIN_VERSION_base(4,15,0) !(NS i#) = natVal (Proxy @n) msbN (NS w) =@@ -1075,26 +947,15 @@ then W# 0## else W# (w `uncheckedShiftRL#` (word2Int# (i# `minusWord#` 1##))) msbN (NB bn) = bigNatToWord (bigNatShiftR# bn (i# `minusWord#` 1##))-#else- !(S# i#) = natVal (Proxy @n) - msbN (NatS# w) =- if isTrue# (i# ># WORD_SIZE_IN_BITS#)- then W# 0##- else W# (w `uncheckedShiftRL#` (i# GHC.Exts.-# 1#))- msbN (NatJ# bn) = W# (bigNatToWord (shiftRBigNat bn (i# GHC.Exts.-# 1#)))-#endif---- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE lsb# #-}+{-# OPAQUE lsb# #-} {-# ANN lsb# hasBlackBox #-} -- | LSB lsb# :: BitVector n -> Bit lsb# (BV m v) = Bit (W# (int2Word# (dataToTag# (testBit m 0)))) (W# (int2Word# (dataToTag# (testBit v 0)))) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE slice# #-}+{-# OPAQUE slice# #-} {-# ANN slice# hasBlackBox #-} slice# :: BitVector (m + 1 + i) -> SNat m -> SNat n -> BitVector (m + 1 - n) slice# (BV msk i) m n = BV (shiftR (msk .&. mask) n')@@ -1108,50 +969,33 @@ -- * Constructions -- ** Concatenation--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE (++#) #-}+{-# OPAQUE (++#) #-} {-# ANN (++#) hasBlackBox #-} -- | Concatenate two 'BitVector's (++#) :: KnownNat m => BitVector n -> BitVector m -> BitVector (n + m) (BV m1 v1) ++# bv2@(BV m2 v2) = BV (m1' .|. m2) (v1' .|. v2) where-#if MIN_VERSION_base(4,15,0) size2 = fromIntegral (natVal bv2) v1' = naturalShiftL v1 size2 m1' = naturalShiftL m1 size2-#else- size2 = fromInteger (natVal bv2)- v1' = shiftL v1 size2- m1' = shiftL m1 size2-#endif -- * Modifying BitVectors--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE replaceBit# #-}+{-# OPAQUE replaceBit# #-} {-# ANN replaceBit# hasBlackBox #-} replaceBit# :: KnownNat n => BitVector n -> Int -> Bit -> BitVector n replaceBit# bv@(BV m v) i (Bit mb b)-#if MIN_VERSION_base(4,15,0) | i >= 0 && i < sz = BV (clearBit m i .|. (naturalFromWord mb `shiftL` i))-#else- | i >= 0 && i < sz = BV (clearBit m i .|. (wordToNatural mb `shiftL` i))-#endif (if testBit b 0 && mb == 0 then setBit v i else clearBit v i) | otherwise = err where-#if MIN_VERSION_base(4,15,0) sz = fromIntegral (natVal bv)-#else- sz = fromInteger (natVal bv)-#endif err = error $ concat [ "replaceBit: " , show i , " is out of range " , formatRange 0 (sz - 1) ] --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE setSlice# #-}+{-# OPAQUE setSlice# #-} {-# ANN setSlice# hasBlackBox #-} setSlice# :: forall m i n@@ -1173,8 +1017,7 @@ where complementN = complementMod (natVal (Proxy @(m + 1 + i))) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE split# #-}+{-# OPAQUE split# #-} {-# ANN split# hasBlackBox #-} split# :: forall n m@@ -1182,26 +1025,16 @@ => BitVector (m + n) -> (BitVector m, BitVector n) split# (BV m i) =-#if MIN_VERSION_base(4,15,0) let n = naturalToWord (natVal (Proxy @n)) mask = maskMod (natVal (Proxy @n)) r = mask i rMask = mask m l = i `naturalShiftR` n lMask = m `naturalShiftR` n-#else- let n = fromInteger (natVal (Proxy @n))- mask = maskMod (natVal (Proxy @n))- r = mask i- rMask = mask m- l = i `shiftR` n- lMask = m `shiftR` n-#endif in (BV lMask l, BV rMask r) and#, or#, xor# :: forall n . KnownNat n => BitVector n -> BitVector n -> BitVector n--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE and# #-}+{-# OPAQUE and# #-} {-# ANN and# hasBlackBox #-} and# = \(BV m1 v1) (BV m2 v2) ->@@ -1210,8 +1043,7 @@ where complementN = complementMod (natVal (Proxy @n)) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE or# #-}+{-# OPAQUE or# #-} {-# ANN or# hasBlackBox #-} or# = \(BV m1 v1) (BV m2 v2) ->@@ -1220,8 +1052,7 @@ where complementN = complementMod (natVal (Proxy @n)) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE xor# #-}+{-# OPAQUE xor# #-} {-# ANN xor# hasBlackBox #-} xor# = \(BV m1 v1) (BV m2 v2) ->@@ -1230,8 +1061,7 @@ where complementN = complementMod (natVal (Proxy @n)) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE complement# #-}+{-# OPAQUE complement# #-} {-# ANN complement# hasBlackBox #-} complement# :: forall n . KnownNat n => BitVector n -> BitVector n complement# = \(BV m v) -> BV m (complementN v .&. complementN m)@@ -1240,8 +1070,7 @@ shiftL#, shiftR#, rotateL#, rotateR# :: forall n . KnownNat n => BitVector n -> Int -> BitVector n --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE shiftL# #-}+{-# OPAQUE shiftL# #-} {-# ANN shiftL# hasBlackBox #-} shiftL# = \(BV msk v) i -> if | i < 0@@ -1251,29 +1080,23 @@ | otherwise -> BV ((shiftL msk i) `mod` m) ((shiftL v i) `mod` m) where-#if MIN_VERSION_base(4,15,0) sz = naturalToWord (natVal (Proxy @n)) m = 1 `naturalShiftL` sz-#else- sz = fromInteger (natVal (Proxy @n))- m = 1 `shiftL` sz-#endif --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE shiftR# #-}+{-# OPAQUE shiftR# #-} {-# ANN shiftR# hasBlackBox #-} shiftR# (BV m v) i | i < 0 = error $ "'shiftR' undefined for negative number: " ++ show i | otherwise = BV (shiftR m i) (shiftR v i) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE rotateL# #-}+{-# OPAQUE rotateL# #-} {-# ANN rotateL# hasBlackBox #-} rotateL# = \(BV msk v) b ->- if b >= 0 then-#if MIN_VERSION_base(4,15,0)+ if sz == 0 then+ BV msk v+ else if b >= 0 then let vl = naturalShiftL v b' vr = naturalShiftR v b'' @@ -1281,59 +1104,33 @@ mr = naturalShiftR msk b'' b' = fromIntegral b `mod` sz-#else- let vl = shiftL v b'- vr = shiftR v b''-- ml = shiftL msk b'- mr = shiftR msk b''-- b' = b `mod` sz-#endif b'' = sz - b' in BV ((ml .|. mr) `mod` m) ((vl .|. vr) `mod` m) else error $ "'rotateL' undefined for negative number: " ++ show b where-#if MIN_VERSION_base(4,15,0) sz = naturalToWord (natVal (Proxy @n)) m = 1 `naturalShiftL` sz-#else- sz = fromInteger (natVal (Proxy @n)) :: Int- m = 1 `shiftL` sz-#endif --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE rotateR# #-}+{-# OPAQUE rotateR# #-} {-# ANN rotateR# hasBlackBox #-} rotateR# = \(BV msk v) b ->- if b >= 0 then-#if MIN_VERSION_base(4,15,0)+ if sz == 0 then+ BV msk v+ else if b >= 0 then let vl = naturalShiftR v b' vr = naturalShiftL v b'' ml = naturalShiftR msk b' mr = naturalShiftL msk b'' b' = fromIntegral b `mod` sz-#else- let vl = shiftR v b'- vr = shiftL v b''- ml = shiftR msk b'- mr = shiftL msk b''- b' = b `mod` sz-#endif b'' = sz - b' in BV ((ml .|. mr) `mod` m) ((vl .|. vr) `mod` m) else error $ "'rotateR' undefined for negative number: " ++ show b where-#if MIN_VERSION_base(4,15,0) sz = naturalToWord (natVal (Proxy @n)) m = 1 `naturalShiftL` sz-#else- sz = fromInteger (natVal (Proxy @n)) :: Int- m = 1 `shiftL` sz-#endif popCountBV :: forall n . KnownNat n => BitVector (n+1) -> I.Index (n+2) popCountBV bv =@@ -1355,29 +1152,17 @@ truncateB# :: forall a b . KnownNat a => BitVector (a + b) -> BitVector a truncateB# = \(BV msk i) -> BV (msk `mod` m) (i `mod` m)-#if MIN_VERSION_base(4,15,0) where m = 1 `naturalShiftL` naturalToWord (natVal (Proxy @a))-#else- where m = 1 `shiftL` fromInteger (natVal (Proxy @a))-#endif--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE truncateB# #-}+{-# OPAQUE truncateB# #-} {-# ANN truncateB# hasBlackBox #-} instance KnownNat n => Lift (BitVector n) where lift bv@(BV m i) = sigE [| fromInteger# m $(litE (IntegerL (toInteger i))) |] (decBitVector (natVal bv)) {-# NOINLINE lift #-}-#if MIN_VERSION_template_haskell(2,16,0) liftTyped = liftTypedFromUntyped-#endif -#if MIN_VERSION_template_haskell(2,17,0) decBitVector :: Quote m => Natural -> m Type decBitVector n = appT (conT ''BitVector) (litT $ numTyLit (integerFromNatural n))-#else-decBitVector :: Integer -> TypeQ-decBitVector n = appT (conT ''BitVector) (litT $ numTyLit n)-#endif instance KnownNat n => SaturatingNum (BitVector n) where satAdd SatWrap a b = a +# b@@ -1499,21 +1284,15 @@ where ty = typeOf res res = undefError (show ty ++ ".unpack") [bv]--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE checkUnpackUndef #-}+{-# OPAQUE checkUnpackUndef #-} {-# ANN checkUnpackUndef hasBlackBox #-} -- | Create a BitVector with all its bits undefined undefined# :: forall n . KnownNat n => BitVector n undefined# =-#if MIN_VERSION_base(4,15,0) let m = 1 `naturalShiftL` naturalToWord (natVal (Proxy @n))-#else- let m = 1 `shiftL` fromInteger (natVal (Proxy @n))-#endif in BV (m-1) 0--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE undefined# #-}+{-# OPAQUE undefined# #-} {-# ANN undefined# hasBlackBox #-} -- | Check if one BitVector is similar to another, interpreting undefined bits@@ -1542,8 +1321,7 @@ in e' == c' && e' == c'' where complementN = complementMod (natVal (Proxy @n))--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE isLike# #-}+{-# OPAQUE isLike# #-} fromBits :: [Bit] -> Integer fromBits = L.foldl (\v b -> v `shiftL` 1 .|. fromIntegral b) 0@@ -1613,6 +1391,5 @@ xToBV x = unsafeDupablePerformIO (catch (evaluate x) (\(XException _) -> return undefined#))--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE xToBV #-}+{-# OPAQUE xToBV #-} {-# ANN xToBV hasBlackBox #-}
src/Clash/Sized/Internal/Index.hs view
@@ -1,7 +1,7 @@ {-| Copyright : (C) 2013-2016, University of Twente, 2016-2019, Myrtle Software Ltd,- 2021-2024, QBayLogic B.V.+ 2021-2026, QBayLogic B.V. License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> -}@@ -76,27 +76,21 @@ import Control.DeepSeq (NFData (..)) import Data.Bits (Bits (..), FiniteBits (..)) import Data.Data (Data)-import Data.Default.Class (Default (..))+import Data.Default (Default (..)) import Text.Read (Read (..), ReadPrec) import Text.Printf (PrintfArg (..), printf) import Data.Ix (Ix(..)) import Language.Haskell.TH (appT, conT, litT, numTyLit, sigE) import Language.Haskell.TH.Syntax (Lift(..))-#if MIN_VERSION_template_haskell(2,16,0) import Language.Haskell.TH.Compat-#endif-#if MIN_VERSION_template_haskell(2,17,0) import Language.Haskell.TH (Quote, Type)-#else-import Language.Haskell.TH (TypeQ)-#endif import GHC.Generics (Generic) import GHC.Natural (Natural, naturalFromInteger) import GHC.Natural (naturalToInteger) import GHC.Stack (HasCallStack) import GHC.TypeLits (KnownNat, Nat, type (+), type (-), type (*), type (<=), natVal)-import GHC.TypeLits.Extra (CLog)+import GHC.TypeLits.Extra (CLogWZ) import Test.QuickCheck.Arbitrary (Arbitrary (..), CoArbitrary (..), arbitraryBoundedIntegral, coarbitraryIntegral, shrinkIntegral)@@ -111,7 +105,7 @@ import Clash.Sized.Internal (formatRange) import {-# SOURCE #-} Clash.Sized.Internal.BitVector (BitVector (BV), high, low, undefError) import qualified Clash.Sized.Internal.BitVector as BV-import Clash.Promoted.Nat (SNat(..), snatToNum, natToInteger, leToPlusKN)+import Clash.Promoted.Nat (SNat(..), UNat(..), toUNat, snatToNum, natToInteger) import Clash.XException (ShowX (..), NFDataX (..), errorX, showsPrecXWith, rwhnfX, seqX) @@ -166,9 +160,8 @@ {-# ANN I hasBlackBox #-} --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE size# #-}-size# :: (KnownNat n, 1 <= n) => Index n -> Int+{-# OPAQUE size# #-}+size# :: KnownNat n => Index n -> Int size# = BV.size# . pack# instance NFData (Index n) where@@ -177,8 +170,8 @@ -- NOINLINE is needed so that Clash doesn't trip on the "Index ~# Integer" -- coercion -instance (KnownNat n, 1 <= n) => BitPack (Index n) where- type BitSize (Index n) = CLog 2 n+instance KnownNat n => BitPack (Index n) where+ type BitSize (Index n) = CLogWZ 2 n 0 pack = packXWith pack# unpack = unpack# @@ -186,16 +179,14 @@ fromSNat :: (KnownNat m, n + 1 <= m) => SNat n -> Index m fromSNat = snatToNum --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE pack# #-}+{-# OPAQUE pack# #-} {-# ANN pack# hasBlackBox #-}-pack# :: Index n -> BitVector (CLog 2 n)+pack# :: Index n -> BitVector (CLogWZ 2 n 0) pack# (I i) = BV 0 (naturalFromInteger i) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE unpack# #-}+{-# OPAQUE unpack# #-} {-# ANN unpack# hasBlackBox #-}-unpack# :: (KnownNat n, 1 <= n) => BitVector (CLog 2 n) -> Index n+unpack# :: KnownNat n => BitVector (CLogWZ 2 n 0) -> Index n unpack# (BV 0 i) = fromInteger_INLINE (naturalToInteger i) unpack# bv = undefError "Index.unpack" [bv] @@ -203,14 +194,12 @@ (==) = eq# (/=) = neq# --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE eq# #-}+{-# OPAQUE eq# #-} {-# ANN eq# hasBlackBox #-} eq# :: (Index n) -> (Index n) -> Bool (I n) `eq#` (I m) = n == m --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE neq# #-}+{-# OPAQUE neq# #-} {-# ANN neq# hasBlackBox #-} neq# :: (Index n) -> (Index n) -> Bool (I n) `neq#` (I m) = n /= m@@ -222,20 +211,16 @@ (<=) = le# lt#,ge#,gt#,le# :: Index n -> Index n -> Bool--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE lt# #-}+{-# OPAQUE lt# #-} {-# ANN lt# hasBlackBox #-} lt# (I n) (I m) = n < m--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE ge# #-}+{-# OPAQUE ge# #-} {-# ANN ge# hasBlackBox #-} ge# (I n) (I m) = n >= m--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE gt# #-}+{-# OPAQUE gt# #-} {-# ANN gt# hasBlackBox #-} gt# (I n) (I m) = n > m--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE le# #-}+{-# OPAQUE le# #-} {-# ANN le# hasBlackBox #-} le# (I n) (I m) = n <= m @@ -253,35 +238,29 @@ toEnum# :: forall n. KnownNat n => Int -> Index n toEnum# = fromInteger# . toInteger--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE toEnum# #-}+{-# OPAQUE toEnum# #-} {-# ANN toEnum# hasBlackBox #-} fromEnum# :: forall n. KnownNat n => Index n -> Int fromEnum# = fromEnum . toInteger#--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE fromEnum# #-}+{-# OPAQUE fromEnum# #-} {-# ANN fromEnum# hasBlackBox #-} enumFrom# :: forall n. KnownNat n => Index n -> [Index n] enumFrom# x = [x .. maxBound]--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE enumFrom# #-}+{-# OPAQUE enumFrom# #-} enumFromThen# :: forall n. KnownNat n => Index n -> Index n -> [Index n] enumFromThen# x y = if x <= y then [x, y .. maxBound] else [x, y .. minBound]--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE enumFromThen# #-}+{-# OPAQUE enumFromThen# #-} enumFromTo# :: Index n -> Index n -> [Index n] enumFromTo# x y = map I [unsafeToInteger x .. unsafeToInteger y]--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE enumFromTo# #-}+{-# OPAQUE enumFromTo# #-} enumFromThenTo# :: Index n -> Index n -> Index n -> [Index n] enumFromThenTo# x1 x2 y = map I [unsafeToInteger x1, unsafeToInteger x2 .. unsafeToInteger y]--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE enumFromThenTo# #-}+{-# OPAQUE enumFromThenTo# #-} instance KnownNat n => Bounded (Index n) where minBound = fromInteger# 0@@ -292,8 +271,7 @@ case natToInteger @n of 0 -> errorX "maxBound of 'Index 0' is undefined" n -> fromInteger_INLINE (n - 1)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE maxBound# #-}+{-# OPAQUE maxBound# #-} {-# ANN maxBound# hasBlackBox #-} -- | Operators report an error on overflow and underflow@@ -311,18 +289,15 @@ fromInteger = fromInteger# (+#),(-#),(*#) :: KnownNat n => Index n -> Index n -> Index n--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE (+#) #-}+{-# OPAQUE (+#) #-} {-# ANN (+#) hasBlackBox #-} (+#) (I a) (I b) = fromInteger_INLINE $ a + b --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE (-#) #-}+{-# OPAQUE (-#) #-} {-# ANN (-#) hasBlackBox #-} (-#) (I a) (I b) = fromInteger_INLINE $ a - b --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE (*#) #-}+{-# OPAQUE (*#) #-} {-# ANN (*#) hasBlackBox #-} (*#) (I a) (I b) = fromInteger_INLINE $ a * b @@ -331,8 +306,7 @@ negate# i = maxBound -# i +# 1 fromInteger# :: KnownNat n => Integer -> Index n--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE fromInteger# #-}+{-# OPAQUE fromInteger# #-} {-# ANN fromInteger# hasBlackBox #-} fromInteger# = fromInteger_INLINE {-# INLINE fromInteger_INLINE #-}@@ -351,13 +325,11 @@ mul = times# plus#, minus# :: Index m -> Index n -> Index (m + n - 1)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE plus# #-}+{-# OPAQUE plus# #-} {-# ANN plus# hasBlackBox #-} plus# (I a) (I b) = I (a + b) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE minus# #-}+{-# OPAQUE minus# #-} {-# ANN minus# hasBlackBox #-} minus# (I a) (I b) = let z = a - b@@ -366,35 +338,36 @@ res = if z < 0 then err else I z in res --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE times# #-}+{-# OPAQUE times# #-} {-# ANN times# hasBlackBox #-} times# :: Index m -> Index n -> Index (((m - 1) * (n - 1)) + 1) times# (I a) (I b) = I (a * b) -instance (KnownNat n, 1 <= n) => SaturatingNum (Index n) where- satAdd SatWrap a b =- case natToInteger @n of- 1 -> a +# b- _ -> leToPlusKN @1 @n $- case plus# a b of- z | let m = fromInteger# (natToInteger @n)- , z >= m -> resize# (z - m)- z -> resize# z- satAdd SatZero a b =- leToPlusKN @1 @n $+instance KnownNat n => SaturatingNum (Index n) where+ satAdd SatWrap a b = case toUNat (SNat @n) of+ UZero -> a+ USucc UZero -> a +# b+ USucc (USucc _) -> case plus# a b of+ z | let m = fromInteger# (natToInteger @n)+ , z >= m -> resize# (z - m)+ z -> resize# z+ satAdd SatZero a b = case toUNat (SNat @n) of+ UZero -> a+ USucc _ -> case plus# a b of z | let m = fromInteger# (natToInteger @(n - 1)) , z > m -> fromInteger# 0 z -> resize# z- satAdd SatError a b =- leToPlusKN @1 @n $+ satAdd SatError a b = case toUNat (SNat @n) of+ UZero -> a+ USucc _ -> case plus# a b of z | let m = fromInteger# (natToInteger @(n - 1)) , z > m -> errorX "Index.satAdd: overflow" z -> resize# z- satAdd _ a b =- leToPlusKN @1 @n $+ satAdd _ a b = case toUNat (SNat @n) of+ UZero -> a+ USucc _ -> case plus# a b of z | let m = fromInteger# (natToInteger @(n - 1)) , z > m -> maxBound#@@ -413,28 +386,30 @@ then fromInteger# 0 else a -# b - satMul SatWrap a b =- case natToInteger @n of- 1 -> a *# b- 2 -> case a of {0 -> 0; _ -> b}- _ -> leToPlusKN @1 @n $- case times# a b of- z -> let m = fromInteger# (natToInteger @n)- in resize# (z `mod` m)- satMul SatZero a b =- leToPlusKN @1 @n $+ satMul SatWrap a b = case toUNat (SNat @n) of+ UZero -> a+ USucc UZero -> a *# b+ USucc (USucc UZero) -> case a of {0 -> 0; _ -> b}+ USucc (USucc (USucc _)) -> case times# a b of+ z -> let m = fromInteger# (natToInteger @n)+ in resize# (z `mod` m)+ satMul SatZero a b = case toUNat (SNat @n) of+ UZero -> a+ USucc _ -> case times# a b of z | let m = fromInteger# (natToInteger @(n - 1)) , z > m -> fromInteger# 0 z -> resize# z- satMul SatError a b =- leToPlusKN @1 @n $+ satMul SatError a b = case toUNat (SNat @n) of+ UZero -> a+ USucc _ -> case times# a b of z | let m = fromInteger# (natToInteger @(n - 1)) , z > m -> errorX "Index.satMul: overflow" z -> resize# z- satMul _ a b =- leToPlusKN @1 @n $+ satMul _ a b = case toUNat (SNat @n) of+ UZero -> a+ USucc _ -> case times# a b of z | let m = fromInteger# (natToInteger @(n - 1)) , z > m -> maxBound#@@ -476,17 +451,14 @@ toInteger = toInteger# quot#,rem# :: Index n -> Index n -> Index n--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE quot# #-}+{-# OPAQUE quot# #-} {-# ANN quot# hasBlackBox #-} (I a) `quot#` (I b) = I (a `div` b)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE rem# #-}+{-# OPAQUE rem# #-} {-# ANN rem# hasBlackBox #-} (I a) `rem#` (I b) = I (a `rem` b) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE toInteger# #-}+{-# OPAQUE toInteger# #-} {-# ANN toInteger# hasBlackBox #-} toInteger# :: Index n -> Integer toInteger# (I n) = n@@ -494,11 +466,15 @@ instance KnownNat n => PrintfArg (Index n) where formatArg = formatArg . toInteger -instance (KnownNat n, 1 <= n) => Parity (Index n) where+instance KnownNat n => Parity (Index n) where even = even . pack odd = odd . pack -instance (KnownNat n, 1 <= n) => Bits (Index n) where+-- | @'shiftR' a n@:+--+-- * Returns 0 if @n >= 'bitSize' a@+-- * 'Clash.XException.XException' if @n < 0@+instance KnownNat n => Bits (Index n) where a .&. b = unpack# $ BV.and# (pack# a) (pack# b) a .|. b = unpack# $ BV.or# (pack# a) (pack# b) xor a b = unpack# $ BV.xor# (pack# a) (pack# b)@@ -518,7 +494,7 @@ rotateR v i = unpack# $ rotateR (pack# v) i popCount i = popCount (pack# i) -instance (KnownNat n, 1 <= n) => FiniteBits (Index n) where+instance KnownNat n => FiniteBits (Index n) where finiteBitSize = size# countLeadingZeros i = countLeadingZeros (pack# i) countTrailingZeros i = countTrailingZeros (pack# i)@@ -530,22 +506,15 @@ resize# :: KnownNat m => Index n -> Index m resize# (I i) = fromInteger_INLINE i--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE resize# #-}+{-# OPAQUE resize# #-} {-# ANN resize# hasBlackBox #-} instance KnownNat n => Lift (Index n) where lift u@(I i) = sigE [| fromInteger# i |] (decIndex (natVal u)) {-# NOINLINE lift #-}-#if MIN_VERSION_template_haskell(2,16,0) liftTyped = liftTypedFromUntyped-#endif -#if MIN_VERSION_template_haskell(2,17,0) decIndex :: Quote m => Integer -> m Type-#else-decIndex :: Integer -> TypeQ-#endif decIndex n = appT (conT ''Index) (litT $ numTyLit n) instance Show (Index n) where
src/Clash/Sized/Internal/Mod.hs view
@@ -29,31 +29,18 @@ module Clash.Sized.Internal.Mod where -#if MIN_VERSION_base(4,15,0) import GHC.Exts (eqWord#, leWord#, word2Int#)-#else-import GHC.Exts ((==#))-#endif import GHC.Exts ((<=#), geWord#, isTrue#, minusWord#, plusWord#, uncheckedShiftL#, xor#, timesWord2#, quotRemWord2#, and#, addWordC#)-#if MIN_VERSION_base(4,15,0) import GHC.Num.BigNat (BigNat#, bigNatAdd, bigNatAddWord#, bigNatAnd, bigNatBit#, bigNatCompare, bigNatFromWord#, bigNatFromWord2#, bigNatMul, bigNatMulWord#, bigNatRem, bigNatSize#, bigNatSubUnsafe, bigNatSubWordUnsafe#, bigNatToWord#, bigNatXor) import GHC.Num.Natural (Natural (..))-#else-import GHC.Natural (Natural (..))-import GHC.Integer.GMP.Internals- (BigNat, Integer (..), bigNatToWord, compareBigNat, minusBigNat, minusBigNatWord,- plusBigNat, plusBigNatWord, sizeofBigNat#, bitBigNat, wordToBigNat2,- remBigNat, timesBigNat, timesBigNatWord, xorBigNat, wordToBigNat, andBigNat)-#endif #include "MachDeps.h" -#if MIN_VERSION_base(4,15,0) -- | modular subtraction subMod :: Natural -> Natural -> Natural -> Natural subMod (NS m#) (NS x#) (NS y#) =@@ -200,155 +187,6 @@ LT -> NB z# EQ -> NS 0## GT -> bigNatToNat (z# `bigNatSubUnsafe` m#)-#else--- | modular subtraction-subMod :: Natural -> Natural -> Natural -> Natural-subMod (NatS# m#) (NatS# x#) (NatS# y#) =- if isTrue# (x# `geWord#` y#) then NatS# z# else NatS# (z# `plusWord#` m#)- where- z# = x# `minusWord#` y#-subMod NatS#{} _ _ = brokenInvariant-subMod (NatJ# m#) (NatS# x#) (NatS# y#) =- if isTrue# (x# `geWord#` y#)- then NatS# (x# `minusWord#` y#)- else bigNatToNat $ m# `minusBigNatWord` (y# `minusWord#` x#)-subMod (NatJ# m#) (NatS# x#) (NatJ# y#) =- bigNatToNat $ (m# `minusBigNat` y#) `plusBigNatWord` x#-subMod NatJ#{} (NatJ# x#) (NatS# y#) =- bigNatToNat $ x# `minusBigNatWord` y#-subMod (NatJ# m#) (NatJ# x#) (NatJ# y#) = case x# `compareBigNat` y# of- LT -> bigNatToNat $ (m# `minusBigNat` y#) `plusBigNat` x#- EQ -> NatS# 0##- GT -> bigNatToNat $ x# `minusBigNat` y#---- | modular addition-addMod :: Natural -> Natural -> Natural -> Natural-addMod (NatS# m#) (NatS# x#) (NatS# y#) =- if isTrue# c# || isTrue# (z# `geWord#` m#) then NatS# (z# `minusWord#` m#) else NatS# z#- where- !(# z#, c# #) = x# `addWordC#` y#-addMod NatS#{} _ _ = brokenInvariant-addMod (NatJ# m#) (NatS# x#) (NatS# y#) =- if isTrue# c# then subIfGe (wordToBigNat2 1## z#) m# else NatS# z#- where- !(# z#, c# #) = x# `addWordC#` y#-addMod (NatJ# m#) (NatS# x#) (NatJ# y#) = subIfGe (y# `plusBigNatWord` x#) m#-addMod (NatJ# m#) (NatJ# x#) (NatS# y#) = subIfGe (x# `plusBigNatWord` y#) m#-addMod (NatJ# m#) (NatJ# x#) (NatJ# y#) = subIfGe (x# `plusBigNat` y#) m#---- | modular multiplication-mulMod :: Natural -> Natural -> Natural -> Natural-mulMod (NatS# m#) (NatS# x#) (NatS# y#) = NatS# r#- where- !(# z1#, z2# #) = timesWord2# x# y#- !(# _, r# #) = quotRemWord2# z1# z2# m#-mulMod NatS#{} _ _ = brokenInvariant-mulMod (NatJ# m#) (NatS# x#) (NatS# y#) =- bigNatToNat $ wordToBigNat2 z1# z2# `remBigNat` m#- where- !(# z1#, z2# #) = timesWord2# x# y#-mulMod (NatJ# m#) (NatS# x#) (NatJ# y#) =- bigNatToNat $ (y# `timesBigNatWord` x#) `remBigNat` m#-mulMod (NatJ# m#) (NatJ# x#) (NatS# y#) =- bigNatToNat $ (x# `timesBigNatWord` y#) `remBigNat` m#-mulMod (NatJ# m#) (NatJ# x#) (NatJ# y#) =- bigNatToNat $ (x# `timesBigNat` y#) `remBigNat` m#---- | modular multiplication for powers of 2, takes a mask instead of a--- wrap-around point-mulMod2 :: Natural -> Natural -> Natural -> Natural-mulMod2 (NatS# m#) (NatS# x#) (NatS# y#) = NatS# (z2# `and#` m#)- where- !(# _, z2# #) = timesWord2# x# y#-mulMod2 NatS#{} _ _ = brokenInvariant-mulMod2 (NatJ# m#) (NatS# x#) (NatS# y#) =- bigNatToNat $ wordToBigNat2 z1# z2# `andBigNat` m#- where- !(# z1#, z2# #) = timesWord2# x# y#-mulMod2 (NatJ# m#) (NatS# x#) (NatJ# y#) =- bigNatToNat $ (y# `timesBigNatWord` x#) `andBigNat` m#-mulMod2 (NatJ# m#) (NatJ# x#) (NatS# y#) =- bigNatToNat $ (x# `timesBigNatWord` y#) `andBigNat` m#-mulMod2 (NatJ# m#) (NatJ# x#) (NatJ# y#) =- bigNatToNat $ (x# `timesBigNat` y#) `andBigNat` m#---- | modular negations-negateMod :: Natural -> Natural -> Natural-negateMod _ (NatS# 0##) = NatS# 0##-negateMod (NatS# m#) (NatS# x#) = NatS# (m# `minusWord#` x#)-negateMod NatS#{} _ = brokenInvariant-negateMod (NatJ# m#) (NatS# x#) = bigNatToNat $ m# `minusBigNatWord` x#-negateMod (NatJ# m#) (NatJ# x#) = bigNatToNat $ m# `minusBigNat` x#---- | Given a size in bits, return a function that complements the bits in a--- 'Natural' up to that size.-complementMod- :: Integer- -> (Natural -> Natural)-complementMod (S# sz#) =- if isTrue# (sz# <=# WORD_SIZE_IN_BITS#) then- let m# = if isTrue# (sz# ==# WORD_SIZE_IN_BITS#) then-#if WORD_SIZE_IN_BITS == 64- 0xFFFFFFFFFFFFFFFF##-#elif WORD_SIZE_IN_BITS == 32- 0xFFFFFFFF##-#else-#error Unhandled value for WORD_SIZE_IN_BITS-#endif- else- (1## `uncheckedShiftL#` sz#) `minusWord#` 1##- go (NatS# x#) = NatS# (x# `xor#` m#)- go (NatJ# r#) = NatS# (bigNatToWord r# `xor#` m#)- in go- else- let m# = bitBigNat sz# `minusBigNatWord` 1##-- go (NatS# x#) = bigNatToNat (xorBigNat (wordToBigNat x#) m#)- go (NatJ# x#) = bigNatToNat (xorBigNat x# m#)- in go-complementMod _ = error "size too large"---- | Keep all the bits up to a certain size-maskMod- :: Integer- -> (Natural -> Natural)-maskMod (S# sz#) =- if isTrue# (sz# <=# WORD_SIZE_IN_BITS#) then- if isTrue# (sz# ==# WORD_SIZE_IN_BITS#) then- -- Mask equal to the word size- let go (NatJ# x#) = NatS# (bigNatToWord x#)- go n = n- in go- else- let m# = (1## `uncheckedShiftL#` sz#) `minusWord#` 1##-- go (NatS# x#) = NatS# (x# `and#` m#)- go (NatJ# x#) = NatS# (bigNatToWord x# `and#` m#)- in go- else- let m# = bitBigNat sz#-- -- faster than `andBigNat (m# `minuxBigNatWord` 1##)`- go (NatJ# x#) = bigNatToNat (remBigNat x# m#)- -- The mask is larger than the word size, so we can keep all the bits- go x = x- in go-maskMod _ = error "size too large"--bigNatToNat :: BigNat -> Natural-bigNatToNat r# =- if isTrue# (sizeofBigNat# r# ==# 1#) then- NatS# (bigNatToWord r#)- else- NatJ# r#--subIfGe :: BigNat -> BigNat -> Natural-subIfGe z# m# = case z# `compareBigNat` m# of- LT -> NatJ# z#- EQ -> NatS# 0##- GT -> bigNatToNat $ z# `minusBigNat` m#--#endif brokenInvariant :: a brokenInvariant = error "argument is larger than modulo"
src/Clash/Sized/Internal/Signed.hs view
@@ -1,7 +1,7 @@ {-| Copyright : (C) 2013-2016, University of Twente, 2016 , Myrtle Software Ltd,- 2021-2024, QBayLogic B.V.+ 2021-2025, QBayLogic B.V. License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> -}@@ -90,7 +90,7 @@ import Control.Lens (Index, Ixed (..), IxValue) import Data.Bits (Bits (..), FiniteBits (..)) import Data.Data (Data)-import Data.Default.Class (Default (..))+import Data.Default (Default (..)) import Data.Proxy (Proxy (..)) import Text.Read (Read (..), ReadPrec) import Text.Printf (PrintfArg (..), printf)@@ -102,14 +102,8 @@ import Data.Ix (Ix(..)) import Language.Haskell.TH (appT, conT, litT, numTyLit, sigE) import Language.Haskell.TH.Syntax (Lift(..))-#if MIN_VERSION_template_haskell(2,16,0) import Language.Haskell.TH.Compat-#endif-#if MIN_VERSION_template_haskell(2,17,0) import Language.Haskell.TH (Quote, Type)-#else-import Language.Haskell.TH (TypeQ)-#endif import Test.QuickCheck.Arbitrary (Arbitrary (..), CoArbitrary (..), arbitraryBoundedIntegral, coarbitraryIntegral, shrinkIntegral)@@ -197,8 +191,7 @@ ensureSpine = id rnfX = rwhnfX --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE size# #-}+{-# OPAQUE size# #-} {-# ANN size# hasBlackBox #-} size# :: KnownNat n => Signed n -> Int size# bv = fromInteger (natVal bv)@@ -225,15 +218,13 @@ pack = packXWith pack# unpack = unpack# --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE pack# #-}+{-# OPAQUE pack# #-} {-# ANN pack# hasBlackBox #-} pack# :: forall n . KnownNat n => Signed n -> BitVector n pack# (S i) = let m = 1 `shiftL0` fromInteger (natVal (Proxy @n)) in if i < 0 then BV 0 (naturalFromInteger (m + i)) else BV 0 (naturalFromInteger i) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE unpack# #-}+{-# OPAQUE unpack# #-} {-# ANN unpack# hasBlackBox #-} unpack# :: forall n . KnownNat n => BitVector n -> Signed n unpack# (BV 0 i) =@@ -246,14 +237,12 @@ (==) = eq# (/=) = neq# --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE eq# #-}+{-# OPAQUE eq# #-} {-# ANN eq# hasBlackBox #-} eq# :: Signed n -> Signed n -> Bool eq# (S v1) (S v2) = v1 == v2 --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE neq# #-}+{-# OPAQUE neq# #-} {-# ANN neq# hasBlackBox #-} neq# :: Signed n -> Signed n -> Bool neq# (S v1) (S v2) = v1 /= v2@@ -265,20 +254,16 @@ (<=) = le# lt#,ge#,gt#,le# :: Signed n -> Signed n -> Bool--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE lt# #-}+{-# OPAQUE lt# #-} {-# ANN lt# hasBlackBox #-} lt# (S n) (S m) = n < m--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE ge# #-}+{-# OPAQUE ge# #-} {-# ANN ge# hasBlackBox #-} ge# (S n) (S m) = n >= m--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE gt# #-}+{-# OPAQUE gt# #-} {-# ANN gt# hasBlackBox #-} gt# (S n) (S m) = n > m--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE le# #-}+{-# OPAQUE le# #-} {-# ANN le# hasBlackBox #-} le# (S n) (S m) = n <= m @@ -310,14 +295,12 @@ toEnum# :: forall n. KnownNat n => Int -> Signed n toEnum# = fromInteger# . toInteger--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE toEnum# #-}+{-# OPAQUE toEnum# #-} {-# ANN toEnum# hasBlackBox #-} fromEnum# :: forall n. KnownNat n => Signed n -> Int fromEnum# = fromEnum . toInteger#--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE fromEnum# #-}+{-# OPAQUE fromEnum# #-} {-# ANN fromEnum# hasBlackBox #-} enumFrom# :: forall n. KnownNat n => Signed n -> [Signed n]@@ -325,8 +308,7 @@ where sz = fromInteger (natVal (Proxy @n)) - 1 mB = 1 `shiftL` sz mask = mB - 1--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE enumFrom# #-}+{-# OPAQUE enumFrom# #-} enumFromThen# :: forall n. KnownNat n => Signed n -> Signed n -> [Signed n] enumFromThen# x y =@@ -337,24 +319,21 @@ sz = fromInteger (natVal (Proxy @n)) - 1 mB = 1 `shiftL` sz mask = mB - 1--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE enumFromThen# #-}+{-# OPAQUE enumFromThen# #-} enumFromTo# :: forall n. KnownNat n => Signed n -> Signed n -> [Signed n] enumFromTo# x y = map (fromInteger_INLINE sz mB mask) [unsafeToInteger x .. unsafeToInteger y] where sz = fromInteger (natVal (Proxy @n)) - 1 mB = 1 `shiftL` sz mask = mB - 1--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE enumFromTo# #-}+{-# OPAQUE enumFromTo# #-} enumFromThenTo# :: forall n. KnownNat n => Signed n -> Signed n -> Signed n -> [Signed n] enumFromThenTo# x1 x2 y = map (fromInteger_INLINE sz mB mask) [unsafeToInteger x1, unsafeToInteger x2 .. unsafeToInteger y] where sz = fromInteger (natVal (Proxy @n)) - 1 mB = 1 `shiftL` sz mask = mB - 1--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE enumFromThenTo# #-}+{-# OPAQUE enumFromThenTo# #-} instance KnownNat n => Bounded (Signed n) where@@ -366,8 +345,7 @@ case natToNatural @n of 0 -> 0 n -> S (negate $ 2 ^ (n - 1))--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE minBound# #-}+{-# OPAQUE minBound# #-} {-# ANN minBound# hasBlackBox #-} maxBound# :: forall n. KnownNat n => Signed n@@ -375,8 +353,7 @@ case natToNatural @n of 0 -> 0 n -> S (2 ^ (n - 1) - 1)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE maxBound# #-}+{-# OPAQUE maxBound# #-} {-# ANN maxBound# hasBlackBox #-} -- | Operators do @wrap-around@ on overflow@@ -395,8 +372,7 @@ fromInteger = fromInteger# (+#), (-#), (*#) :: forall n . KnownNat n => Signed n -> Signed n -> Signed n--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE (+#) #-}+{-# OPAQUE (+#) #-} {-# ANN (+#) hasBlackBox #-} (+#) = \(S a) (S b) ->@@ -410,8 +386,7 @@ where m = 1 `shiftL0` fromInteger (natVal (Proxy @n) -1) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE (-#) #-}+{-# OPAQUE (-#) #-} {-# ANN (-#) hasBlackBox #-} (-#) = \(S a) (S b) ->@@ -425,8 +400,7 @@ where m = 1 `shiftL0` fromInteger (natVal (Proxy @n) -1) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE (*#) #-}+{-# OPAQUE (*#) #-} {-# ANN (*#) hasBlackBox #-} (*#) = \(S a) (S b) -> fromInteger_INLINE sz mB mask (a * b) where sz = fromInteger (natVal (Proxy @n)) - 1@@ -434,8 +408,7 @@ mask = mB - 1 negate#,abs# :: forall n . KnownNat n => Signed n -> Signed n--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE negate# #-}+{-# OPAQUE negate# #-} {-# ANN negate# hasBlackBox #-} negate# = \(S n) ->@@ -444,8 +417,7 @@ where m = 1 `shiftL0` fromInteger (natVal (Proxy @n) -1) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE abs# #-}+{-# OPAQUE abs# #-} {-# ANN abs# hasBlackBox #-} abs# = \(S n) ->@@ -454,8 +426,7 @@ where m = 1 `shiftL0` fromInteger (natVal (Proxy @n) -1) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE fromInteger# #-}+{-# OPAQUE fromInteger# #-} {-# ANN fromInteger# hasBlackBox #-} fromInteger# :: forall n . KnownNat n => Integer -> Signed (n :: Nat) fromInteger# = fromInteger_INLINE sz mB mask@@ -480,18 +451,15 @@ mul = times# plus#, minus# :: Signed m -> Signed n -> Signed (Max m n + 1)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE plus# #-}+{-# OPAQUE plus# #-} {-# ANN plus# hasBlackBox #-} plus# (S a) (S b) = S (a + b) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE minus# #-}+{-# OPAQUE minus# #-} {-# ANN minus# hasBlackBox #-} minus# (S a) (S b) = S (a - b) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE times# #-}+{-# OPAQUE times# #-} {-# ANN times# hasBlackBox #-} times# :: Signed m -> Signed n -> Signed (m + n) times# (S a) (S b) = S (a * b)@@ -511,8 +479,7 @@ divMod n d = (n `div#` d,n `mod#` d) toInteger = toInteger# --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE quot# #-}+{-# OPAQUE quot# #-} {-# ANN quot# hasBlackBox #-} quot# :: forall n. KnownNat n => Signed n -> Signed n -> Signed n quot# (S a) (S b)@@ -521,14 +488,12 @@ where S minB = minBound @(Signed n) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE rem# #-}+{-# OPAQUE rem# #-} {-# ANN rem# hasBlackBox #-} rem# :: Signed n -> Signed n -> Signed n rem# (S a) (S b) = S (a `rem` b) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE div# #-}+{-# OPAQUE div# #-} {-# ANN div# hasBlackBox #-} div# :: forall n. KnownNat n => Signed n -> Signed n -> Signed n div# (S a) (S b)@@ -537,14 +502,12 @@ where S minB = minBound @(Signed n) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE mod# #-}+{-# OPAQUE mod# #-} {-# ANN mod# hasBlackBox #-} mod# :: Signed n -> Signed n -> Signed n mod# (S a) (S b) = S (a `mod` b) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE toInteger# #-}+{-# OPAQUE toInteger# #-} {-# ANN toInteger# hasBlackBox #-} toInteger# :: Signed n -> Integer toInteger# (S n) = n@@ -556,6 +519,11 @@ even = even . pack odd = odd . pack +-- | @'shiftR' a n@:+--+-- * Returns 0 if @a >= 0@ and @n >= 'bitSize' a@+-- * Returns -1 if @a < 0@ and @n >= 'bitSize' a@+-- * 'Clash.XException.XException' if @n < 0@ instance KnownNat n => Bits (Signed n) where (.&.) = and# (.|.) = or#@@ -577,32 +545,28 @@ popCount s = popCount (pack# s) and#,or#,xor# :: forall n . KnownNat n => Signed n -> Signed n -> Signed n--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE and# #-}+{-# OPAQUE and# #-} {-# ANN and# hasBlackBox #-} and# = \(S a) (S b) -> fromInteger_INLINE sz mB mask (a .&. b) where sz = fromInteger (natVal (Proxy @n)) - 1 mB = 1 `shiftL` sz mask = mB - 1 --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE or# #-}+{-# OPAQUE or# #-} {-# ANN or# hasBlackBox #-} or# = \(S a) (S b) -> fromInteger_INLINE sz mB mask (a .|. b) where sz = fromInteger (natVal (Proxy @n)) - 1 mB = 1 `shiftL` sz mask = mB - 1 --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE xor# #-}+{-# OPAQUE xor# #-} {-# ANN xor# hasBlackBox #-} xor# = \(S a) (S b) -> fromInteger_INLINE sz mB mask (xor a b) where sz = fromInteger (natVal (Proxy @n)) - 1 mB = 1 `shiftL` sz mask = mB - 1 --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE complement# #-}+{-# OPAQUE complement# #-} {-# ANN complement# hasBlackBox #-} complement# :: forall n . KnownNat n => Signed n -> Signed n complement# = \(S a) -> fromInteger_INLINE sz mB mask (complement a)@@ -611,8 +575,7 @@ mask = mB - 1 shiftL#,shiftR#,rotateL#,rotateR# :: forall n . KnownNat n => Signed n -> Int -> Signed n--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE shiftL# #-}+{-# OPAQUE shiftL# #-} {-# ANN shiftL# hasBlackBox #-} shiftL# = \(S n) b -> if | b < 0 -> error $ "'shiftL' undefined for negative number: " ++ show b@@ -623,8 +586,7 @@ mB = 1 `shiftL` sz mask = mB - 1 --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE shiftR# #-}+{-# OPAQUE shiftR# #-} {-# ANN shiftR# hasBlackBox #-} shiftR# = \(S n) b ->@@ -637,8 +599,7 @@ mB = 1 `shiftL` sz mask = mB - 1 --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE rotateL# #-}+{-# OPAQUE rotateL# #-} {-# ANN rotateL# hasBlackBox #-} rotateL# = \(S n) b ->@@ -658,8 +619,7 @@ mB = 1 `shiftL` sz1 maskM = mB - 1 --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE rotateR# #-}+{-# OPAQUE rotateR# #-} {-# ANN rotateR# hasBlackBox #-} rotateR# = \(S n) b ->@@ -689,8 +649,7 @@ zeroExtend s = unpack# (0 ++# pack s) truncateB = truncateB# --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE resize# #-}+{-# OPAQUE resize# #-} {-# ANN resize# hasBlackBox #-} resize# :: forall m n . (KnownNat n, KnownNat m) => Signed n -> Signed m resize# s@(S i)@@ -709,8 +668,7 @@ then S (i' - mask) else S i' --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE truncateB# #-}+{-# OPAQUE truncateB# #-} {-# ANN truncateB# hasBlackBox #-} truncateB# :: forall m n . KnownNat m => Signed (m + n) -> Signed m truncateB# = \(S n) -> fromInteger_INLINE sz mB mask n@@ -724,15 +682,9 @@ instance KnownNat n => Lift (Signed n) where lift s@(S i) = sigE [| fromInteger# i |] (decSigned (natVal s)) {-# NOINLINE lift #-}-#if MIN_VERSION_template_haskell(2,16,0) liftTyped = liftTypedFromUntyped-#endif -#if MIN_VERSION_template_haskell(2,17,0) decSigned :: Quote m => Integer -> m Type-#else-decSigned :: Integer -> TypeQ-#endif decSigned n = appT (conT ''Signed) (litT $ numTyLit n) instance KnownNat n => SaturatingNum (Signed n) where@@ -880,9 +832,5 @@ -- | Shift left that ties to zero on negative shifts shiftL0 :: Integer -> Int -> Integer-#if MIN_VERSION_base(4,15,0) shiftL0 = \a sh -> if sh >= 0 then shiftL a sh else 0-#else-shiftL0 = shiftL -- True for use with this module-#endif {-# INLINE shiftL0 #-}
src/Clash/Sized/Internal/Unsigned.hs view
@@ -1,7 +1,7 @@ {-| Copyright : (C) 2013-2016, University of Twente, 2016 , Myrtle Software Ltd,- 2021-2024, QBayLogic B.V.+ 2021-2025, QBayLogic B.V. License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> -}@@ -88,46 +88,27 @@ import Control.Lens (Index, Ixed (..), IxValue) import Data.Bits (Bits (..), FiniteBits (..)) import Data.Data (Data)-import Data.Default.Class (Default (..))+import Data.Default (Default (..)) import Data.Proxy (Proxy (..)) import Text.Read (Read (..), ReadPrec) import Text.Printf (PrintfArg (..), printf)-#if MIN_VERSION_base(4,16,0) import GHC.Exts (wordToWord8#, wordToWord16#, wordToWord32#)-#else-import GHC.Exts (narrow8Word#, narrow16Word#, narrow32Word#)-#endif import GHC.Generics (Generic)-#if MIN_VERSION_base(4,15,0) import GHC.Num.BigNat (bigNatToWord, bigNatToWord#) import GHC.Num.Integer (integerFromNatural, integerShiftL, integerToNatural) import GHC.Num.Natural (Natural (..), naturalShiftL, naturalShiftR, naturalToWord)-#else-import GHC.Integer.GMP.Internals (bigNatToWord)-import GHC.Natural (Natural (..), naturalFromInteger)-#endif import GHC.Natural (naturalToInteger) import GHC.TypeLits (KnownNat, Nat, type (+))-#if MIN_VERSION_base(4,15,0) import GHC.TypeNats (natVal)-#else-import GHC.TypeLits (natVal)-#endif import GHC.TypeLits.Extra (Max) import GHC.Word (Word (..), Word8 (..), Word16 (..), Word32 (..)) import Data.Ix (Ix(..)) import Language.Haskell.TH (appT, conT, litT, numTyLit, sigE) import Language.Haskell.TH.Syntax (Lift(..))-#if MIN_VERSION_template_haskell(2,16,0) import Language.Haskell.TH.Compat-#endif-#if MIN_VERSION_template_haskell(2,17,0) import Language.Haskell.TH (Quote, Type)-#else-import Language.Haskell.TH (TypeQ)-#endif import Test.QuickCheck.Arbitrary (Arbitrary (..), CoArbitrary (..), arbitraryBoundedIntegral, coarbitraryIntegral)@@ -208,15 +189,10 @@ {-# ANN U hasBlackBox #-} --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE size# #-}+{-# OPAQUE size# #-} {-# ANN size# hasBlackBox #-} size# :: KnownNat n => Unsigned n -> Int-#if MIN_VERSION_base(4,15,0) size# u = fromIntegral (natVal u)-#else-size# u = fromInteger (natVal u)-#endif instance NFData (Unsigned n) where rnf (U i) = rnf i `seq` ()@@ -245,14 +221,12 @@ pack = packXWith pack# unpack = unpack# --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE pack# #-}+{-# OPAQUE pack# #-} {-# ANN pack# hasBlackBox #-} pack# :: Unsigned n -> BitVector n pack# (U i) = BV 0 i --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE unpack# #-}+{-# OPAQUE unpack# #-} {-# ANN unpack# hasBlackBox #-} unpack# :: KnownNat n => BitVector n -> Unsigned n unpack# (BV 0 i) = U i@@ -262,14 +236,12 @@ (==) = eq# (/=) = neq# --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE eq# #-}+{-# OPAQUE eq# #-} {-# ANN eq# hasBlackBox #-} eq# :: Unsigned n -> Unsigned n -> Bool eq# (U v1) (U v2) = v1 == v2 --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE neq# #-}+{-# OPAQUE neq# #-} {-# ANN neq# hasBlackBox #-} neq# :: Unsigned n -> Unsigned n -> Bool neq# (U v1) (U v2) = v1 /= v2@@ -281,20 +253,16 @@ (<=) = le# lt#,ge#,gt#,le# :: Unsigned n -> Unsigned n -> Bool--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE lt# #-}+{-# OPAQUE lt# #-} {-# ANN lt# hasBlackBox #-} lt# (U n) (U m) = n < m--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE ge# #-}+{-# OPAQUE ge# #-} {-# ANN ge# hasBlackBox #-} ge# (U n) (U m) = n >= m--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE gt# #-}+{-# OPAQUE gt# #-} {-# ANN gt# hasBlackBox #-} gt# (U n) (U m) = n > m--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE le# #-}+{-# OPAQUE le# #-} {-# ANN le# hasBlackBox #-} le# (U n) (U m) = n <= m @@ -325,58 +293,36 @@ toEnum# :: forall n. KnownNat n => Int -> Unsigned n toEnum# = fromInteger# . toInteger--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE toEnum# #-}+{-# OPAQUE toEnum# #-} {-# ANN toEnum# hasBlackBox #-} fromEnum# :: forall n. KnownNat n => Unsigned n -> Int fromEnum# = fromEnum . toInteger#--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE fromEnum# #-}+{-# OPAQUE fromEnum# #-} {-# ANN fromEnum# hasBlackBox #-} enumFrom# :: forall n. KnownNat n => Unsigned n -> [Unsigned n] enumFrom# = \x -> map (U . (`mod` m)) [unsafeToNatural x .. unsafeToNatural (maxBound :: Unsigned n)]-#if MIN_VERSION_base(4,15,0) where m = 1 `naturalShiftL` naturalToWord (natVal (Proxy @n))-#else- where m = 1 `shiftL` fromInteger (natVal (Proxy @n))-#endif--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE enumFrom# #-}+{-# OPAQUE enumFrom# #-} enumFromThen# :: forall n. KnownNat n => Unsigned n -> Unsigned n -> [Unsigned n] enumFromThen# = \x y -> toUnsigneds [unsafeToNatural x, unsafeToNatural y .. bound x y] where toUnsigneds = map (U . (`mod` m)) bound x y = unsafeToNatural (if x <= y then maxBound else minBound :: Unsigned n)-#if MIN_VERSION_base(4,15,0) m = 1 `naturalShiftL` naturalToWord (natVal (Proxy @n))-#else- m = 1 `shiftL` fromInteger (natVal (Proxy @n))-#endif--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE enumFromThen# #-}+{-# OPAQUE enumFromThen# #-} enumFromTo# :: forall n. KnownNat n => Unsigned n -> Unsigned n -> [Unsigned n] enumFromTo# = \x y -> map (U . (`mod` m)) [unsafeToNatural x .. unsafeToNatural y]-#if MIN_VERSION_base(4,15,0) where m = 1 `naturalShiftL` naturalToWord (natVal (Proxy @n))-#else- where m = 1 `shiftL` fromInteger (natVal (Proxy @n))-#endif--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE enumFromTo# #-}+{-# OPAQUE enumFromTo# #-} enumFromThenTo# :: forall n. KnownNat n => Unsigned n -> Unsigned n -> Unsigned n -> [Unsigned n] enumFromThenTo# = \x1 x2 y -> map (U . (`mod` m)) [unsafeToNatural x1, unsafeToNatural x2 .. unsafeToNatural y]-#if MIN_VERSION_base(4,15,0) where m = 1 `naturalShiftL` naturalToWord (natVal (Proxy @n))-#else- where m = 1 `shiftL` fromInteger (natVal (Proxy @n))-#endif--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE enumFromThenTo# #-}+{-# OPAQUE enumFromThenTo# #-} instance KnownNat n => Bounded (Unsigned n) where minBound = minBound#@@ -384,14 +330,12 @@ minBound# :: Unsigned n minBound# = U 0--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE minBound# #-}+{-# OPAQUE minBound# #-} {-# ANN minBound# hasBlackBox #-} maxBound# :: forall n. KnownNat n => Unsigned n maxBound# = let m = 1 `shiftL` (natToNum @n) in U (m - 1)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE maxBound# #-}+{-# OPAQUE maxBound# #-} {-# ANN maxBound# hasBlackBox #-} -- | __NB__: 'fromInteger'/'fromIntegral' can cause unexpected truncation, as@@ -407,60 +351,33 @@ fromInteger = fromInteger# (+#),(-#),(*#) :: forall n . KnownNat n => Unsigned n -> Unsigned n -> Unsigned n--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE (+#) #-}+{-# OPAQUE (+#) #-} {-# ANN (+#) hasBlackBox #-} (+#) = \(U i) (U j) -> U (addMod m i j)-#if MIN_VERSION_base(4,15,0) where m = 1 `naturalShiftL` naturalToWord (natVal (Proxy @n))-#else- where m = 1 `shiftL` fromInteger (natVal (Proxy @n))-#endif --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE (-#) #-}+{-# OPAQUE (-#) #-} {-# ANN (-#) hasBlackBox #-} (-#) = \(U i) (U j) -> U (subMod m i j)-#if MIN_VERSION_base(4,15,0) where m = 1 `naturalShiftL` naturalToWord (natVal (Proxy @n))-#else- where m = 1 `shiftL` fromInteger (natVal (Proxy @n))-#endif --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE (*#) #-}+{-# OPAQUE (*#) #-} {-# ANN (*#) hasBlackBox #-} (*#) = \(U i) (U j) -> U (mulMod2 m i j)-#if MIN_VERSION_base(4,15,0) where m = (1 `naturalShiftL` naturalToWord (natVal (Proxy @n))) - 1-#else- where m = (1 `shiftL` fromInteger (natVal (Proxy @n))) - 1-#endif --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE negate# #-}+{-# OPAQUE negate# #-} {-# ANN negate# hasBlackBox #-} negate# :: forall n . KnownNat n => Unsigned n -> Unsigned n negate# = \(U i) -> U (negateMod m i)-#if MIN_VERSION_base(4,15,0) where m = 1 `naturalShiftL` naturalToWord (natVal (Proxy @n))-#else- where m = 1 `shiftL` fromInteger (natVal (Proxy @n))-#endif --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE fromInteger# #-}+{-# OPAQUE fromInteger# #-} {-# ANN fromInteger# hasBlackBox #-} fromInteger# :: forall n . KnownNat n => Integer -> Unsigned n-#if MIN_VERSION_base(4,15,0) fromInteger# = \x -> U (integerToNatural (x `mod` m)) where m = 1 `integerShiftL` naturalToWord (natVal (Proxy @n))-#else-fromInteger# = \x -> U (naturalFromInteger (x `mod` m))- where- m = 1 `shiftL` fromInteger (natVal (Proxy @n))-#endif instance (KnownNat m, KnownNat n) => ExtendingNum (Unsigned m) (Unsigned n) where type AResult (Unsigned m) (Unsigned n) = Unsigned (Max m n + 1)@@ -469,29 +386,21 @@ type MResult (Unsigned m) (Unsigned n) = Unsigned (m + n) mul = times# --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE plus# #-}+{-# OPAQUE plus# #-} {-# ANN plus# hasBlackBox #-} plus# :: Unsigned m -> Unsigned n -> Unsigned (Max m n + 1) plus# (U a) (U b) = U (a + b) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE minus# #-}+{-# OPAQUE minus# #-} {-# ANN minus# hasBlackBox #-} minus# :: forall m n . (KnownNat m, KnownNat n) => Unsigned m -> Unsigned n -> Unsigned (Max m n + 1) minus# = \(U a) (U b) -> U (subMod mask a b) where-#if MIN_VERSION_base(4,15,0) sz = naturalToWord (natVal (Proxy @(Max m n + 1))) mask = 1 `naturalShiftL` sz-#else- sz = fromInteger (natVal (Proxy @(Max m n + 1)))- mask = 1 `shiftL` sz-#endif --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE times# #-}+{-# OPAQUE times# #-} {-# ANN times# hasBlackBox #-} times# :: Unsigned m -> Unsigned n -> Unsigned (m + n) times# (U a) (U b) = U (a * b)@@ -512,17 +421,14 @@ toInteger = toInteger# quot#,rem# :: Unsigned n -> Unsigned n -> Unsigned n--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE quot# #-}+{-# OPAQUE quot# #-} {-# ANN quot# hasBlackBox #-} quot# (U i) (U j) = U (i `quot` j)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE rem# #-}+{-# OPAQUE rem# #-} {-# ANN rem# hasBlackBox #-} rem# (U i) (U j) = U (i `rem` j) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE toInteger# #-}+{-# OPAQUE toInteger# #-} {-# ANN toInteger# hasBlackBox #-} toInteger# :: Unsigned n -> Integer toInteger# (U i) = naturalToInteger i@@ -534,6 +440,10 @@ even = even . pack odd = odd . pack +-- | @'shiftR' a n@:+--+-- * Returns 0 if @n >= 'bitSize' a@+-- * 'Clash.XException.XException' if @n < 0@ instance KnownNat n => Bits (Unsigned n) where (.&.) = and# (.|.) = or#@@ -554,37 +464,31 @@ rotateR v i = rotateR# v i popCount u = popCount (pack# u) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE and# #-}+{-# OPAQUE and# #-} {-# ANN and# hasBlackBox #-} and# :: Unsigned n -> Unsigned n -> Unsigned n and# (U v1) (U v2) = U (v1 .&. v2) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE or# #-}+{-# OPAQUE or# #-} {-# ANN or# hasBlackBox #-} or# :: Unsigned n -> Unsigned n -> Unsigned n or# (U v1) (U v2) = U (v1 .|. v2) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE xor# #-}+{-# OPAQUE xor# #-} {-# ANN xor# hasBlackBox #-} xor# :: Unsigned n -> Unsigned n -> Unsigned n xor# (U v1) (U v2) = U (v1 `xor` v2) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE complement# #-}+{-# OPAQUE complement# #-} {-# ANN complement# hasBlackBox #-} complement# :: forall n . KnownNat n => Unsigned n -> Unsigned n complement# = \(U i) -> U (complementN i) where complementN = complementMod (natVal (Proxy @n)) shiftL#, shiftR#, rotateL#, rotateR# :: forall n .KnownNat n => Unsigned n -> Int -> Unsigned n--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE shiftL# #-}+{-# OPAQUE shiftL# #-} {-# ANN shiftL# hasBlackBox #-} shiftL# = \(U v) i ->-#if MIN_VERSION_base(4,15,0) let i' = fromIntegral i in if | i < 0 -> error $ "'shiftL' undefined for negative number: " ++ show i | i' >= sz -> U 0@@ -592,17 +496,8 @@ where sz = naturalToWord (natVal (Proxy @n)) m = 1 `naturalShiftL` sz-#else- if | i < 0 -> error $ "'shiftL' undefined for negative number: " ++ show i- | i >= sz -> U 0- | otherwise -> U ((shiftL v i) `mod` m)- where- sz = fromInteger (natVal (Proxy @n))- m = 1 `shiftL` sz-#endif --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE shiftR# #-}+{-# OPAQUE shiftR# #-} {-# ANN shiftR# hasBlackBox #-} -- shiftR# doesn't need the KnownNat constraint -- But having the same type signature for all shift and rotate functions@@ -612,61 +507,37 @@ $ "'shiftR' undefined for negative number: " ++ show i | otherwise = U (shiftR v i) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE rotateL# #-}+{-# OPAQUE rotateL# #-} {-# ANN rotateL# hasBlackBox #-} rotateL# = \(U n) b -> if b >= 0 then-#if MIN_VERSION_base(4,15,0) let l = naturalShiftL n b' r = naturalShiftR n b'' b' = fromIntegral b `mod` sz-#else- let l = shiftL n b'- r = shiftR n b''- b' = b `mod` sz-#endif b'' = sz - b' in U ((l .|. r) `mod` m) else error $ "'rotateL' undefined for negative number: " ++ show b where-#if MIN_VERSION_base(4,15,0) sz = naturalToWord (natVal (Proxy @n)) m = 1 `naturalShiftL` sz-#else- sz = fromInteger (natVal (Proxy @n)) :: Int- m = 1 `shiftL` sz-#endif --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE rotateR# #-}+{-# OPAQUE rotateR# #-} {-# ANN rotateR# hasBlackBox #-} rotateR# = \(U n) b -> if b >= 0 then-#if MIN_VERSION_base(4,15,0) let l = naturalShiftR n b' r = naturalShiftL n b'' b' = fromIntegral b `mod` sz-#else- let l = shiftR n b'- r = shiftL n b''- b' = b `mod` sz-#endif b'' = sz - b' in U ((l .|. r) `mod` m) else error $ "'rotateR' undefined for negative number: " ++ show b where-#if MIN_VERSION_base(4,15,0) sz = naturalToWord (natVal (Proxy @n)) m = 1 `naturalShiftL` sz-#else- sz = fromInteger (natVal (Proxy @n)) :: Int- m = 1 `shiftL` sz-#endif instance KnownNat n => FiniteBits (Unsigned n) where@@ -679,16 +550,11 @@ zeroExtend = extend truncateB = resize# --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE resize# #-}+{-# OPAQUE resize# #-} {-# ANN resize# hasBlackBox #-} resize# :: forall n m . KnownNat m => Unsigned n -> Unsigned m resize# = \(U i) -> if i >= m then U (i `mod` m) else U i-#if MIN_VERSION_base(4,15,0) where m = 1 `naturalShiftL` naturalToWord (natVal (Proxy @m))-#else- where m = 1 `shiftL` fromInteger (natVal (Proxy @m))-#endif instance Default (Unsigned n) where def = minBound#@@ -696,17 +562,10 @@ instance KnownNat n => Lift (Unsigned n) where lift u@(U i) = sigE [| fromInteger# i |] (decUnsigned (natVal u)) {-# NOINLINE lift #-}-#if MIN_VERSION_template_haskell(2,16,0) liftTyped = liftTypedFromUntyped-#endif -#if MIN_VERSION_template_haskell(2,17,0) decUnsigned :: Quote m => Natural -> m Type decUnsigned n = appT (conT ''Unsigned) (litT $ numTyLit (integerFromNatural n))-#else-decUnsigned :: Integer -> TypeQ-decUnsigned n = appT (conT ''Unsigned) (litT $ numTyLit n)-#endif instance KnownNat n => SaturatingNum (Unsigned n) where satAdd SatWrap a b = a +# b@@ -792,60 +651,27 @@ inRange (a, b) x = a <= x && x <= b unsignedToWord :: Unsigned WORD_SIZE_IN_BITS -> Word-#if MIN_VERSION_base(4,15,0) unsignedToWord (U (NS u#)) = W# u# unsignedToWord (U (NB u#)) = bigNatToWord u#-#else-unsignedToWord (U (NatS# u#)) = W# u#-unsignedToWord (U (NatJ# u#)) = W# (bigNatToWord u#)-#endif--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE unsignedToWord #-}+{-# OPAQUE unsignedToWord #-} {-# ANN unsignedToWord hasBlackBox #-} unsigned8toWord8 :: Unsigned 8 -> Word8-#if MIN_VERSION_base(4,16,0) unsigned8toWord8 (U (NS u#)) = W8# (wordToWord8# u#) unsigned8toWord8 (U (NB u#)) = W8# (wordToWord8# (bigNatToWord# u#))-#elif MIN_VERSION_base(4,15,0)-unsigned8toWord8 (U (NS u#)) = W8# (narrow8Word# u#)-unsigned8toWord8 (U (NB u#)) = W8# (narrow8Word# (bigNatToWord# u#))-#else-unsigned8toWord8 (U (NatS# u#)) = W8# (narrow8Word# u#)-unsigned8toWord8 (U (NatJ# u#)) = W8# (narrow8Word# (bigNatToWord u#))-#endif--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE unsigned8toWord8 #-}+{-# OPAQUE unsigned8toWord8 #-} {-# ANN unsigned8toWord8 hasBlackBox #-} unsigned16toWord16 :: Unsigned 16 -> Word16-#if MIN_VERSION_base(4,16,0) unsigned16toWord16 (U (NS u#)) = W16# (wordToWord16# u#) unsigned16toWord16 (U (NB u#)) = W16# (wordToWord16# (bigNatToWord# u#))-#elif MIN_VERSION_base(4,15,0)-unsigned16toWord16 (U (NS u#)) = W16# (narrow16Word# u#)-unsigned16toWord16 (U (NB u#)) = W16# (narrow16Word# (bigNatToWord# u#))-#else-unsigned16toWord16 (U (NatS# u#)) = W16# (narrow16Word# u#)-unsigned16toWord16 (U (NatJ# u#)) = W16# (narrow16Word# (bigNatToWord u#))-#endif--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE unsigned16toWord16 #-}+{-# OPAQUE unsigned16toWord16 #-} {-# ANN unsigned16toWord16 hasBlackBox #-} unsigned32toWord32 :: Unsigned 32 -> Word32-#if MIN_VERSION_base(4,16,0) unsigned32toWord32 (U (NS u#)) = W32# (wordToWord32# u#) unsigned32toWord32 (U (NB u#)) = W32# (wordToWord32# (bigNatToWord# u#))-#elif MIN_VERSION_base(4,15,0)-unsigned32toWord32 (U (NS u#)) = W32# (narrow32Word# u#)-unsigned32toWord32 (U (NB u#)) = W32# (narrow32Word# (bigNatToWord# u#))-#else-unsigned32toWord32 (U (NatS# u#)) = W32# (narrow32Word# u#)-unsigned32toWord32 (U (NatJ# u#)) = W32# (narrow32Word# (bigNatToWord u#))-#endif--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE unsigned32toWord32 #-}+{-# OPAQUE unsigned32toWord32 #-} {-# ANN unsigned32toWord32 hasBlackBox #-} {-# RULES
src/Clash/Sized/RTree.hs view
@@ -1,6 +1,6 @@ {-| Copyright : (C) 2016, University of Twente- 2022-2024, QBayLogic B.V.+ 2022-2025, QBayLogic B.V. License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> -}@@ -61,12 +61,9 @@ ) where -#if !MIN_VERSION_base(4,18,0)-import Control.Applicative (liftA2)-#endif import Control.DeepSeq (NFData(..)) import qualified Control.Lens as Lens-import Data.Default.Class (Default (..))+import Data.Default (Default (..)) import Data.Either (isLeft) import Data.Foldable (toList) import Data.Kind (Type)@@ -74,9 +71,7 @@ import Data.Proxy (Proxy (..)) import GHC.TypeLits (KnownNat, Nat, type (+), type (^), type (*)) import Language.Haskell.TH.Syntax (Lift(..))-#if MIN_VERSION_template_haskell(2,16,0) import Language.Haskell.TH.Compat-#endif import Prelude hiding ((++), (!!), map) import Test.QuickCheck (Arbitrary (..), CoArbitrary (..)) @@ -128,20 +123,18 @@ textract :: RTree 0 a -> a textract (RLeaf x) = x-#if __GLASGOW_HASKELL__ != 902+#if __GLASGOW_HASKELL__ < 912 textract (RBranch _ _) = error $ "textract: nodes hold no values" #endif--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE textract #-}+{-# OPAQUE textract #-} {-# ANN textract hasBlackBox #-} tsplit :: RTree (d+1) a -> (RTree d a,RTree d a) tsplit (RBranch l r) = (l,r)-#if __GLASGOW_HASKELL__ != 902+#if __GLASGOW_HASKELL__ < 912 tsplit (RLeaf _) = error $ "tsplit: leaf is atomic" #endif--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE tsplit #-}+{-# OPAQUE tsplit #-} {-# ANN tsplit hasBlackBox #-} -- | RLeaf of a perfect depth tree@@ -237,9 +230,7 @@ instance Lift a => Lift (RTree d a) where lift (RLeaf a) = [| RLeaf a |] lift (RBranch t1 t2) = [| RBranch $(lift t1) $(lift t2) |]-#if MIN_VERSION_template_haskell(2,16,0) liftTyped = liftTypedFromUntyped-#endif instance (KnownNat d, Arbitrary a) => Arbitrary (RTree d a) where arbitrary = sequenceA (trepeat arbitrary)@@ -326,7 +317,7 @@ (bound at ...) <BLANKLINE> -#elif __GLASGOW_HASKELL__ >= 900+#else >>> :{ let populationCount' :: (KnownNat (2^d), KnownNat d, KnownNat (2^d+1)) => BitVector (2^d) -> Index (2^d+1)@@ -349,28 +340,6 @@ populationCount' :: BitVector (2 ^ d) -> Index ((2 ^ d) + 1) (bound at ...) -#else->>> :{-let populationCount' :: (KnownNat (2^d), KnownNat d, KnownNat (2^d+1))- => BitVector (2^d) -> Index (2^d+1)- populationCount' = tfold (resize . bv2i . pack) add . v2t . bv2v-:}-<BLANKLINE>-<interactive>:...-...- Expected type: Index ((2 ^ d) + 1)- -> Index ((2 ^ d) + 1) -> Index ((2 ^ d) + 1)- Actual type: Index ((2 ^ d) + 1)- -> Index ((2 ^ d) + 1)- -> AResult (Index ((2 ^ d) + 1)) (Index ((2 ^ d) + 1))- • In the second argument of ‘tfold’, namely ‘add’- In the first argument of ‘(.)’, namely- ‘tfold (resize . bv2i . pack) add’- In the expression: tfold (resize . bv2i . pack) add . v2t . bv2v- • Relevant bindings include- populationCount' :: BitVector (2 ^ d) -> Index ((2 ^ d) + 1)- (bound at ...)- #endif because 'tfold' expects a function of type \"@b -> b -> b@\", i.e. a function@@ -417,8 +386,7 @@ go _ (RLeaf a) = f a go sn (RBranch l r) = let sn' = sn `subSNat` d1 in g sn' (go sn' l) (go sn' r)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE tdfold #-}+{-# OPAQUE tdfold #-} {-# ANN tdfold hasBlackBox #-} data TfoldTree (a :: Type) (f :: TyFun Nat Type) :: Type@@ -447,8 +415,7 @@ go :: UNat n -> RTree n a go UZero = LR a go (USucc un) = BR (go un) (go un)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE treplicate #-}+{-# OPAQUE treplicate #-} {-# ANN treplicate hasBlackBox #-} -- | \"'trepeat' @a@\" creates a tree with as many copies of /a/ as demanded by@@ -528,7 +495,7 @@ -- >>> replaceTree 2 7 (BR (BR (LR 1) (LR 2)) (BR (LR 3) (LR 4))) -- <<1,2>,<7,4>> -- >>> replaceTree 9 6 (BR (BR (LR 1) (LR 2)) (BR (LR 3) (LR 4)))--- <<1,2>,<3,*** Exception: Clash.Sized.Vector.replace: index 9 is larger than maximum index 3+-- <<1,2>,<3,*** Exception: Clash.Sized.Vector.replace: index 9 is out of bounds: [0..3] -- ... replaceTree :: (KnownNat d, Enum i) => i -> a -> RTree d a -> RTree d a replaceTree i a = v2t . replace i a . t2v
src/Clash/Sized/Vector.hs view
@@ -8,6 +8,7 @@ -} {-# LANGUAGE CPP #-}+{-# LANGUAGE EmptyCase #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-}@@ -23,8 +24,6 @@ {-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-} {-# OPTIONS_GHC -fplugin GHC.TypeLits.Normalise #-} -{-# OPTIONS_GHC -fno-warn-incomplete-patterns -fno-warn-redundant-constraints #-}- {-# OPTIONS_HADDOCK show-extensions #-} module Clash.Sized.Vector@@ -65,7 +64,7 @@ , rotateLeft, rotateRight, rotateLeftS, rotateRightS -- * Element-wise operations -- ** Mapping- , map, imap, smap+ , map, imap, smap, smapWithBounds -- ** Zipping , zipWith, zipWith3, zipWith4, zipWith5, zipWith6, zipWith7 , zip, zip3, zip4, zip5, zip6, zip7@@ -108,15 +107,15 @@ import Data.Data (Data (..), Constr, DataType, Fixity (..), Typeable, mkConstr, mkDataType) import Data.Either (isLeft)-#if MIN_VERSION_base(4,18,0)+import Data.Distributive+import Data.Functor.Rep import qualified Data.Foldable1 as F1-#endif-import Data.Default.Class (Default (..))+import Data.Default (Default (..)) import qualified Data.Foldable as F import Data.Kind (Type) import Data.Proxy (Proxy (..)) import Data.Singletons (TyFun,Apply,type (@@))-import GHC.TypeLits (CmpNat, KnownNat, Nat, type (+), type (-), type (*),+import GHC.TypeLits (KnownNat, Nat, type (+), type (-), type (*), type (^), type (<=), natVal) import GHC.Base (Int(I#),Int#,isTrue#) import GHC.Generics hiding (Fixity (..))@@ -124,9 +123,7 @@ import GHC.Prim ((==#),(<#),(-#)) import Language.Haskell.TH (ExpQ) import Language.Haskell.TH.Syntax (Lift(..))-#if MIN_VERSION_template_haskell(2,16,0) import Language.Haskell.TH.Compat-#endif import Prelude hiding ((++), (!!), concat, concatMap, drop, foldl, foldl1, foldr, foldr1, head, init, iterate, last, length, map,@@ -138,7 +135,6 @@ import qualified Prelude as P import Test.QuickCheck (Arbitrary(arbitrary, shrink), CoArbitrary(coarbitrary))-import Unsafe.Coerce (unsafeCoerce) import Clash.Annotations.Primitive (Primitive(InlineYamlPrimitive), HDL(..), dontTranslate, hasBlackBox)@@ -146,9 +142,7 @@ import Clash.Promoted.Nat (SNat (..), SNatLE (..), UNat (..), compareSNat, pow2SNat, snatProxy, snatToInteger, subSNat, withSNat, toUNat, natToInteger)-#if MIN_VERSION_base(4,18,0) import Clash.Promoted.Nat (leToPlus)-#endif import Clash.Promoted.Nat.Literals (d1) import Clash.Sized.Internal.BitVector (Bit, BitVector (..), split#) import Clash.Sized.Index (Index)@@ -183,6 +177,9 @@ {-# COMPLETE Nil, (:>) #-} +-- | Tag for K1: @n ~ 0@ proof+data N+ -- | In many cases, this Generic instance only allows generic -- functions/instances over vectors of at least size 1, due to the -- /n-1/ in the /Rep (Vec n a)/ definition.@@ -193,7 +190,7 @@ instance KnownNat n => Generic (Vec n a) where type Rep (Vec n a) = D1 ('MetaData "Vec" "Clash.Data.Vector" "clash-prelude" 'False)- (C1 ('MetaCons "Nil" 'PrefixI 'False) U1 :+:+ (C1 ('MetaCons "Nil" 'PrefixI 'False) (K1 N (Dict (n ~ 0))) :+: C1 ('MetaCons "Cons" 'PrefixI 'False) (S1 ('MetaSel 'Nothing 'NoSourceUnpackedness@@ -205,13 +202,14 @@ 'NoSourceStrictness 'DecidedLazy) (Rec0 (Vec (n-1) a))))- from Nil = M1 (L1 (M1 U1))+ from Nil = M1 (L1 (M1 (K1 Dict))) from (Cons x xs) = M1 (R1 (M1 (M1 (K1 x) :*: M1 (K1 xs)))) to (M1 g) = case compareSNat (SNat @n) (SNat @0) of SNatLE -> case leZero @n of Sub Dict -> Nil SNatGT -> case g of R1 (M1 (M1 (K1 p) :*: M1 (K1 q))) -> Cons p q+ L1 (M1 (K1 eqZero)) -> case eqZero of {} instance (KnownNat n, Typeable a, Data a) => Data (Vec n a) where gunfold k z _ = case compareSNat (SNat @n) (SNat @0) of@@ -351,7 +349,6 @@ product Nil = 1 product z@Cons{} = fold (*) z -#if MIN_VERSION_base(4,18,0) instance (KnownNat n, 1 <= n) => F1.Foldable1 (Vec n) where fold1 = leToPlus @1 @n $ fold (<>) foldMap1 f = leToPlus @1 @n $ fold (<>) . map f@@ -359,7 +356,6 @@ minimum = leToPlus @1 @n minimum head = leToPlus @1 @n head last = leToPlus @1 @n last-#endif instance Functor (Vec n) where fmap = map@@ -367,8 +363,7 @@ instance KnownNat n => Traversable (Vec n) where traverse = traverse# --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE traverse# #-}+{-# OPAQUE traverse# #-} {-# ANN traverse# hasBlackBox #-} traverse# :: forall a f b n . Applicative f => (a -> f b) -> Vec n a -> f (Vec n b) traverse# _ Nil = pure Nil@@ -403,8 +398,7 @@ singleton :: a -> Vec 1 a singleton = (`Cons` Nil) --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE head #-}+{-# OPAQUE head #-} {-# ANN head hasBlackBox #-} {- | Extract the first element of a vector @@ -422,7 +416,7 @@ In an equation for ‘it’: it = head Nil <BLANKLINE> -#elif __GLASGOW_HASKELL__ >= 900+#else >>> head Nil <BLANKLINE> <interactive>:...@@ -433,24 +427,18 @@ In the expression: head Nil In an equation for ‘it’: it = head Nil -#else->>> head Nil-<BLANKLINE>-<interactive>:...- • Couldn't match type ‘1’ with ‘0’- Expected type: Vec (0 + 1) a- Actual type: Vec 0 a- • In the first argument of ‘head’, namely ‘Nil’- In the expression: head Nil- In an equation for ‘it’: it = head Nil- #endif -} head :: Vec (n + 1) a -> a head (x `Cons` _) = x+#if __GLASGOW_HASKELL__ < 912+head xs = unreachable xs+ where+ unreachable :: forall n a. 1 <= n => Vec n a -> a+ unreachable (x `Cons` _) = x+#endif --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE tail #-}+{-# OPAQUE tail #-} {-# ANN tail hasBlackBox #-} {- | Extract the elements after the head of a vector @@ -468,7 +456,7 @@ In an equation for ‘it’: it = tail Nil <BLANKLINE> -#elif __GLASGOW_HASKELL__ >= 900+#else >>> tail Nil <BLANKLINE> <interactive>:...@@ -479,24 +467,18 @@ In the expression: tail Nil In an equation for ‘it’: it = tail Nil -#else->>> tail Nil-<BLANKLINE>-<interactive>:...- • Couldn't match type ‘1’ with ‘0’- Expected type: Vec (0 + 1) a- Actual type: Vec 0 a- • In the first argument of ‘tail’, namely ‘Nil’- In the expression: tail Nil- In an equation for ‘it’: it = tail Nil- #endif -} tail :: Vec (n + 1) a -> Vec n a-tail (_ `Cons` xs) = xs+tail (_ `Cons` xr) = xr+#if __GLASGOW_HASKELL__ < 912+tail xs = unreachable xs+ where+ unreachable :: forall n a. 1 <= n => Vec n a -> Vec (n - 1) a+ unreachable (_ `Cons` xr) = xr+#endif --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE last #-}+{-# OPAQUE last #-} {-# ANN last hasBlackBox #-} {- | Extract the last element of a vector @@ -514,7 +496,7 @@ In an equation for ‘it’: it = last Nil <BLANKLINE> -#elif __GLASGOW_HASKELL__ >= 900+#else >>> last Nil <BLANKLINE> <interactive>:...@@ -525,25 +507,19 @@ In the expression: last Nil In an equation for ‘it’: it = last Nil -#else->>> last Nil-<BLANKLINE>-<interactive>:...- • Couldn't match type ‘1’ with ‘0’- Expected type: Vec (0 + 1) a- Actual type: Vec 0 a- • In the first argument of ‘last’, namely ‘Nil’- In the expression: last Nil- In an equation for ‘it’: it = last Nil- #endif -} last :: Vec (n + 1) a -> a last (x `Cons` Nil) = x-last (_ `Cons` y `Cons` ys) = last (y `Cons` ys)+last (_ `Cons` y `Cons` xr) = last (y `Cons` xr)+#if __GLASGOW_HASKELL__ < 912+last xs = unreachable xs+ where+ unreachable :: 1 <= n => Vec n a -> a+ unreachable ys@(Cons _ _) = last ys+#endif --- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE init #-}+{-# OPAQUE init #-} {-# ANN init hasBlackBox #-} {- | Extract all the elements of a vector except the last element @@ -561,7 +537,7 @@ In an equation for ‘it’: it = init Nil <BLANKLINE> -#elif __GLASGOW_HASKELL__ >= 900+#else >>> init Nil <BLANKLINE> <interactive>:...@@ -572,22 +548,17 @@ In the expression: init Nil In an equation for ‘it’: it = init Nil -#else->>> init Nil-<BLANKLINE>-<interactive>:...- • Couldn't match type ‘1’ with ‘0’- Expected type: Vec (0 + 1) a- Actual type: Vec 0 a- • In the first argument of ‘init’, namely ‘Nil’- In the expression: init Nil- In an equation for ‘it’: it = init Nil- #endif -} init :: Vec (n + 1) a -> Vec n a init (_ `Cons` Nil) = Nil-init (x `Cons` y `Cons` ys) = x `Cons` init (y `Cons` ys)+init (x `Cons` y `Cons` xr) = x `Cons` init (y `Cons` xr)+#if __GLASGOW_HASKELL__ < 912+init xs = unreachable xs+ where+ unreachable :: 1 <= n => Vec n a -> Vec (n - 1) a+ unreachable ys@(Cons _ _) = init ys+#endif {-# INLINE shiftInAt0 #-} -- | Shift in elements to the head of a vector, bumping out elements at the@@ -665,8 +636,8 @@ -- 1 :> 3 :> 4 :> Nil -- >>> 1 +>> Nil -- Nil-(+>>) :: KnownNat n => a -> Vec n a -> Vec n a-s +>> xs = fst (shiftInAt0 xs (singleton s))+(+>>) :: forall n a . a -> Vec n a -> Vec n a+s +>> xs = init (s :> xs) {-# INLINE (+>>) #-} @@ -722,8 +693,7 @@ (++) :: Vec n a -> Vec m a -> Vec (n + m) a Nil ++ ys = ys (x `Cons` xs) ++ ys = x `Cons` xs ++ ys--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE (++) #-}+{-# OPAQUE (++) #-} {-# ANN (++) hasBlackBox #-} -- | Split a vector into two vectors at the given point.@@ -734,14 +704,13 @@ -- (1 :> 2 :> 3 :> Nil,7 :> 8 :> Nil) splitAt :: SNat m -> Vec (m + n) a -> (Vec m a, Vec n a) splitAt n xs = splitAtU (toUNat n) xs--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE splitAt #-}+{-# OPAQUE splitAt #-} {-# ANN splitAt hasBlackBox #-} splitAtU :: UNat m -> Vec (m + n) a -> (Vec m a, Vec n a)-splitAtU UZero ys = (Nil,ys)-splitAtU (USucc s) (y `Cons` ys) = let (as,bs) = splitAtU s ys- in (y `Cons` as, bs)+splitAtU UZero ys = (Nil, ys)+splitAtU (USucc s) ys = let (as, bs) = splitAtU s $ tail ys+ in (head ys `Cons` as, bs) -- | Split a vector into two vectors where the length of the two is determined -- by the context.@@ -759,8 +728,7 @@ concat :: Vec n (Vec m a) -> Vec (n * m) a concat Nil = Nil concat (x `Cons` xs) = x ++ concat xs--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE concat #-}+{-# OPAQUE concat #-} {-# ANN concat hasBlackBox #-} -- | Map a function over all the elements of a vector and concatentate the resulting vectors.@@ -778,8 +746,7 @@ -- (1 :> 2 :> 3 :> 4 :> Nil) :> (5 :> 6 :> 7 :> 8 :> Nil) :> (9 :> 10 :> 11 :> 12 :> Nil) :> Nil unconcat :: KnownNat n => SNat m -> Vec (n * m) a -> Vec n (Vec m a) unconcat n xs = unconcatU (withSNat toUNat) (toUNat n) xs--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE unconcat #-}+{-# OPAQUE unconcat #-} {-# ANN unconcat hasBlackBox #-} unconcatU :: UNat n -> UNat m -> Vec (n * m) a -> Vec n (Vec m a)@@ -800,8 +767,8 @@ -- -- >>> merge (1 :> 2 :> 3 :> 4 :> Nil) (5 :> 6 :> 7 :> 8 :> Nil) -- 1 :> 5 :> 2 :> 6 :> 3 :> 7 :> 4 :> 8 :> Nil-merge :: KnownNat n => Vec n a -> Vec n a -> Vec (2 * n) a-merge x y = concat (transpose (x :> singleton y))+merge :: Vec n a -> Vec n a -> Vec (2 * n) a+merge x y = concat $ zipWith (\a b -> a :> singleton b) x y {-# INLINE merge #-} -- | The elements in a vector in reverse order.@@ -814,8 +781,7 @@ go :: i <= n => Vec (n - i) a -> Vec i a -> Vec n a go a (y `Cons` ys) = go (y `Cons` a) ys go a Nil = a--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE reverse #-}+{-# OPAQUE reverse #-} {-# ANN reverse hasBlackBox #-} -- | \"'map' @f xs@\" is the vector obtained by applying /f/ to each element@@ -829,8 +795,7 @@ map :: (a -> b) -> Vec n a -> Vec n b map _ Nil = Nil map f (x `Cons` xs) = f x `Cons` map f xs--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE map #-}+{-# OPAQUE map #-} {-# ANN map hasBlackBox #-} -- | Apply a function of every element of a vector and its index.@@ -853,8 +818,7 @@ go :: Index n -> Vec m a -> Vec m b go _ Nil = Nil go n (x `Cons` xs) = f n x `Cons` go (n+1) xs--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE imap #-}+{-# OPAQUE imap #-} {-# ANN imap hasBlackBox #-} {- | Zip two vectors with a functions that also takes the elements' indices.@@ -969,8 +933,7 @@ zipWith :: (a -> b -> c) -> Vec n a -> Vec n b -> Vec n c zipWith _ Nil _ = Nil zipWith f (x `Cons` xs) ys = f x (head ys) `Cons` zipWith f xs (tail ys)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE zipWith #-}+{-# OPAQUE zipWith #-} {-# ANN zipWith hasBlackBox #-} -- | 'zipWith3' generalizes 'zip3' by zipping with the function given@@ -1080,8 +1043,7 @@ foldr :: (a -> b -> b) -> b -> Vec n a -> b foldr _ z Nil = z foldr f z (x `Cons` xs) = f x (foldr f z xs)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE foldr #-}+{-# OPAQUE foldr #-} {-# ANN foldr hasBlackBox #-} -- | 'foldl', applied to a binary operator, a starting value (typically@@ -1102,8 +1064,26 @@ -- delay, of O(@'length' xs@). Use 'fold' if your binary operator @f@ is -- associative, as @"'fold' f xs"@ produces a structure with a depth of -- O(log_2(@'length' xs@)).-foldl :: (b -> a -> b) -> b -> Vec n a -> b-foldl f z xs = last (scanl f z xs)+foldl :: forall b a n . (b -> a -> b) -> b -> Vec n a -> b+foldl f z0 xs0+ -- We use 'go' to make 'foldl' strict during Haskell simulation, while using+ -- 'scanl' to make Clash's life easier during normalization. We make 'foldl'+ -- strict due to similar reasoning to:+ --+ -- https://well-typed.com/blog/90/+ --+ -- Also see:+ --+ -- https://github.com/hasura/graphql-engine/pull/2933#discussion_r328821960+ --+ | clashSimulation = go z0 xs0+ | otherwise = last (scanl f z0 xs0)+ where+ go :: forall m. b -> Vec m a -> b+ go z Nil = z+ go z (Cons x xs) =+ let z1 = f z x+ in z1 `seq` go z1 xs {-# INLINE foldl #-} -- | 'foldr1' is a variant of 'foldr' that has no starting value argument,@@ -1175,8 +1155,7 @@ fold' xs = fold' ys `f` fold' zs where (ys,zs) = P.splitAt (P.length xs `div` 2) xs--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE fold #-}+{-# OPAQUE fold #-} {-# ANN fold (InlineYamlPrimitive [VHDL,Verilog,SystemVerilog] [I.__i| BlackBoxHaskell: name: Clash.Sized.Vector.fold@@ -1211,15 +1190,15 @@ -- -- >>> scanl1 (-) (1 :> 2 :> 3 :> 4 :> Nil) -- 1 :> -1 :> -4 :> -8 :> Nil-scanl1 :: KnownNat n => (a -> a -> a) -> Vec (n+1) a -> Vec (n+1) a-scanl1 op (v:>vs) = scanl op v vs+scanl1 :: forall n a. (a -> a -> a) -> Vec (n+1) a -> Vec (n+1) a+scanl1 op vs = scanl op (head vs) (tail vs) {-# INLINE scanl1 #-} -- | 'scanr' with no seed value -- -- >>> scanr1 (-) (1 :> 2 :> 3 :> 4 :> Nil) -- -2 :> 3 :> -1 :> 4 :> Nil-scanr1 :: KnownNat n => (a -> a -> a) -> Vec (n+1) a -> Vec (n+1) a+scanr1 :: forall n a. (a -> a -> a) -> Vec (n+1) a -> Vec (n+1) a scanr1 op vs = scanr op (last vs) (init vs) {-# INLINE scanr1 #-} @@ -1504,8 +1483,7 @@ sub (y `Cons` (!ys)) n = if isTrue# (n ==# 0#) then y else sub ys (n -# 1#)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE index_int #-}+{-# OPAQUE index_int #-} {-# ANN index_int hasBlackBox #-} -- | \"@xs@ '!!' @n@\" returns the /n/'th element of /xs/.@@ -1532,8 +1510,7 @@ -- 3 length :: KnownNat n => Vec n a -> Int length = fromInteger . natVal . asNatProxy--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE length #-}+{-# OPAQUE length #-} {-# ANN length hasBlackBox #-} replace_int :: KnownNat n => Vec n a -> Int -> a -> Vec n a@@ -1544,14 +1521,15 @@ sub :: Vec m b -> Int# -> b -> Vec m b sub Nil _ _ = error (P.concat [ "Clash.Sized.Vector.replace: index " , show i- , " is larger than maximum index "- , show (length xs - 1)+ , " is out of bounds: "+ , if length xs == 0+ then "<empty range>"+ else "[0.." <> show (length xs - 1) <> "]" ]) sub (y `Cons` (!ys)) n b = if isTrue# (n ==# 0#) then b `Cons` ys else y `Cons` sub ys (n -# 1#) b--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE replace_int #-}+{-# OPAQUE replace_int #-} {-# ANN replace_int hasBlackBox #-} -- | \"'replace' @n a xs@\" returns the vector /xs/ where the /n/'th element is@@ -1565,7 +1543,7 @@ -- >>> replace 0 7 (1:>2:>3:>4:>5:>Nil) -- 7 :> 2 :> 3 :> 4 :> 5 :> Nil -- >>> replace 9 7 (1:>2:>3:>4:>5:>Nil)--- 1 :> 2 :> 3 :> 4 :> 5 :> *** Exception: Clash.Sized.Vector.replace: index 9 is larger than maximum index 4+-- 1 :> 2 :> 3 :> 4 :> 5 :> *** Exception: Clash.Sized.Vector.replace: index 9 is out of bounds: [0..4] -- ... replace :: (KnownNat n, Enum i) => i -> a -> Vec n a -> Vec n a replace i y xs = replace_int xs (fromEnum i) y@@ -1604,7 +1582,7 @@ In the expression: take d4 (1 :> 2 :> Nil) In an equation for ‘it’: it = take d4 (1 :> 2 :> Nil) -#elif __GLASGOW_HASKELL__ >= 900+#else >>> take d4 (1:>2:>Nil) <BLANKLINE> <interactive>:...@@ -1616,18 +1594,6 @@ In the expression: take d4 (1 :> 2 :> Nil) In an equation for ‘it’: it = take d4 (1 :> 2 :> Nil) -#else->>> take d4 (1:>2:>Nil)-<BLANKLINE>-<interactive>:...- • Couldn't match type ‘4 + n0’ with ‘2’- Expected type: Vec (4 + n0) a- Actual type: Vec (1 + 1) a- The type variable ‘n0’ is ambiguous- • In the second argument of ‘take’, namely ‘(1 :> 2 :> Nil)’- In the expression: take d4 (1 :> 2 :> Nil)- In an equation for ‘it’: it = take d4 (1 :> 2 :> Nil)- #endif -} take :: SNat m -> Vec (m + n) a -> Vec m a@@ -1712,20 +1678,25 @@ -- 2 :> 4 :> 6 :> Nil -- >>> select d1 d2 d3 (1:>2:>3:>4:>5:>6:>7:>8:>Nil) -- 2 :> 4 :> 6 :> Nil-select :: (CmpNat (i + s) (s * n) ~ 'GT)+select :: forall i s n f a. s * n + 1 <= i + s => SNat f -> SNat s -> SNat n -> Vec (f + i) a -> Vec n a select f s n xs = select' (toUNat n) $ drop f xs- where- select' :: UNat n -> Vec i a -> Vec n a- select' UZero _ = Nil- select' (USucc n') vs@(x `Cons` _) = x `Cons`- select' n' (drop s (unsafeCoerce vs))--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE select #-}+ where+ select' :: forall m j b. (s * m + 1 <= j + s) => UNat m -> Vec j b -> Vec m b+ select' m vs = case m of+ UZero -> Nil+ USucc UZero -> head @(j - 1) vs `Cons` Nil+ USucc m'@(USucc _) -> case deduce @(s * (m - 1) + 1) @j Proxy Proxy of+ Dict -> head @(j - 1) vs `Cons` select' m' (drop @s @(j - s) s vs)++ deduce :: e + s <= k + s => p e -> p k -> Dict (e <= k)+ deduce _ _ = Dict++{-# OPAQUE select #-} {-# ANN select hasBlackBox #-} -- | \"'selectI' @f s xs@\" selects as many elements as demanded by the context@@ -1733,7 +1704,7 @@ -- -- >>> selectI d1 d2 (1:>2:>3:>4:>5:>6:>7:>8:>Nil) :: Vec 2 Int -- 2 :> 4 :> Nil-selectI :: (CmpNat (i + s) (s * n) ~ 'GT, KnownNat n)+selectI :: (1 <= s, s * n + 1 <= i + s, KnownNat n) => SNat f -> SNat s -> Vec (f + i) a@@ -1749,8 +1720,7 @@ -- 6 :> 6 :> 6 :> Nil replicate :: SNat n -> a -> Vec n a replicate n a = replicateU (toUNat n) a--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE replicate #-}+{-# OPAQUE replicate #-} {-# ANN replicate hasBlackBox #-} replicateU :: UNat n -> a -> Vec n a@@ -1799,8 +1769,7 @@ iterateU :: forall m. UNat m -> a -> Vec m a iterateU UZero _ = Nil iterateU (USucc s) a = a `Cons` iterateU s (f a)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE iterateI #-}+{-# OPAQUE iterateI #-} {-# ANN iterateI (InlineYamlPrimitive [VHDL,Verilog,SystemVerilog] [I.__i| BlackBoxHaskell: name: Clash.Sized.Vector.iterateI@@ -1877,8 +1846,7 @@ -- (1 :> 3 :> 5 :> Nil) :> (2 :> 4 :> 6 :> Nil) :> Nil transpose :: KnownNat n => Vec m (Vec n a) -> Vec n (Vec m a) transpose = traverse# id--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE transpose #-}+{-# OPAQUE transpose #-} {-# ANN transpose hasBlackBox #-} -- | 1-dimensional stencil computations@@ -1913,15 +1881,9 @@ >>> :t xss xss :: Num a => Vec 4 (Vec 4 a) -#if __GLASGOW_HASKELL__ >= 902 >>> :t stencil2d d2 d2 (sum . map sum) xss stencil2d d2 d2 (sum . map sum) xss :: Num a => Vec 3 (Vec 3 a) -#else->>> :t stencil2d d2 d2 (sum . map sum) xss-stencil2d d2 d2 (sum . map sum) xss :: Num b => Vec 3 (Vec 3 b)--#endif >>> stencil2d d2 d2 (sum . map sum) xss (14 :> 18 :> 22 :> Nil) :> (30 :> 34 :> 38 :> Nil) :> (46 :> 50 :> 54 :> Nil) :> Nil -}@@ -2060,11 +2022,11 @@ -- >>> let xs = 1 :> 2 :> 3 :> 4 :> 5 :> 6 :> 7 :> 8 :> 9 :> Nil -- >>> interleave d3 xs -- 1 :> 4 :> 7 :> 2 :> 5 :> 8 :> 3 :> 6 :> 9 :> Nil-interleave :: (KnownNat n, KnownNat d)+interleave :: KnownNat n => SNat d -- ^ Interleave step, /d/ -> Vec (n * d) a -> Vec (d * n) a-interleave d = concat . transpose . unconcat d+interleave d@SNat = concat . transpose . unconcat d {-# INLINE interleave #-} -- | /Dynamically/ rotate a 'Vec'tor to the left:@@ -2126,8 +2088,7 @@ go _ Nil = Nil go 0 ys = ys go n (y `Cons` ys) = go (n-1) (ys :< y)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE rotateLeftS #-}+{-# OPAQUE rotateLeftS #-} {-# ANN rotateLeftS hasBlackBox #-} -- | /Statically/ rotate a 'Vec'tor to the right:@@ -2146,8 +2107,7 @@ go _ Nil = Nil go 0 ys = ys go n ys@(Cons _ _) = go (n-1) (last ys :> init ys)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE rotateRightS #-}+{-# OPAQUE rotateRightS #-} {-# ANN rotateRightS hasBlackBox #-} -- | Convert a vector to a list.@@ -2183,8 +2143,7 @@ exactLength 0 acc = null acc exactLength _ [] = False exactLength i (_:ys) = exactLength (i - 1) ys--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE fromList #-}+{-# OPAQUE fromList #-} {-# ANN fromList dontTranslate #-} -- | Convert a list to a vector. This function always returns a vector of the@@ -2212,8 +2171,7 @@ go [] = let item = error "Clash.Sized.Vector.unsafeFromList: vector larger than list" in (item, [])--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE unsafeFromList #-}+{-# OPAQUE unsafeFromList #-} {-# ANN unsafeFromList dontTranslate #-} -- | Create a vector literal from a list literal.@@ -2314,8 +2272,7 @@ lazyV' :: Vec n () -> Vec n a -> Vec n a lazyV' Nil _ = Nil lazyV' (_ `Cons` xs) ys = head ys `Cons` lazyV' xs (tail ys)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE lazyV #-}+{-# OPAQUE lazyV #-} {-# ANN lazyV hasBlackBox #-} -- | A /dependently/ typed fold.@@ -2325,7 +2282,10 @@ -- >>> import Data.Singletons (Apply, Proxy (..), TyFun) -- >>> data Append (m :: Nat) (a :: Type) (f :: TyFun Nat Type) :: Type -- >>> type instance Apply (Append m a) l = Vec (l + m) a--- >>> let append' xs ys = dfold (Proxy :: Proxy (Append m a)) (const (:>)) ys xs+-- >>> :{+-- >>> append' :: forall a k m. KnownNat k => Vec k a -> Vec m a -> Vec (k + m) a+-- >>> append' xs ys = dfold (Proxy :: Proxy (Append m a)) (const ((:>) @a)) ys xs+-- >>> :} -- -- === Example usage --@@ -2403,7 +2363,7 @@ -- fold that produces a structure with a depth of O(log_2(@'length' xs@)). dfold :: forall p k a . KnownNat k => Proxy (p :: TyFun Nat Type -> Type) -- ^ The /motive/- -> (forall l . SNat l -> a -> (p @@ l) -> (p @@ (l + 1)))+ -> (forall n . n + 1 <= k => SNat n -> a -> (p @@ n) -> (p @@ (n + 1))) -- ^ Function to fold. -- -- __NB__: The @SNat l@ is __not__ the index (see (`!!`)) to the@@ -2414,13 +2374,12 @@ -> (p @@ k) dfold _ f z xs = go (snatProxy (asNatProxy xs)) xs where- go :: SNat n -> Vec n a -> (p @@ n)+ go :: n <= k => SNat n -> Vec n a -> (p @@ n) go _ Nil = z go s (y `Cons` ys) = let s' = s `subSNat` d1 in f s' y (go s' ys)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE dfold #-}+{-# OPAQUE dfold #-} {-# ANN dfold hasBlackBox #-} {- | A combination of 'dfold' and 'fold': a /dependently/ typed fold that@@ -2496,7 +2455,7 @@ (bound at ...) <BLANKLINE> -#elif __GLASGOW_HASKELL__ >= 900+#else >>> :{ let populationCount' :: (KnownNat (n+1), KnownNat (n+2)) => BitVector (n+1) -> Index (n+2)@@ -2516,25 +2475,6 @@ populationCount' :: BitVector (n + 1) -> Index (n + 2) (bound at ...) -#else->>> :{-let populationCount' :: (KnownNat (n+1), KnownNat (n+2))- => BitVector (n+1) -> Index (n+2)- populationCount' = fold add . map fromIntegral . bv2v-:}-<BLANKLINE>-<interactive>:...- • Couldn't match type ‘((n + 2) + (n + 2)) - 1’ with ‘n + 2’- Expected type: Index (n + 2) -> Index (n + 2) -> Index (n + 2)- Actual type: Index (n + 2)- -> Index (n + 2) -> AResult (Index (n + 2)) (Index (n + 2))- • In the first argument of ‘fold’, namely ‘add’- In the first argument of ‘(.)’, namely ‘fold add’- In the expression: fold add . map fromIntegral . bv2v- • Relevant bindings include- populationCount' :: BitVector (n + 1) -> Index (n + 2)- (bound at ...)- #endif because 'fold' expects a function of type \"@a -> a -> a@\", i.e. a function@@ -2583,7 +2523,7 @@ dtfold :: forall p k a . KnownNat k => Proxy (p :: TyFun Nat Type -> Type) -- ^ The /motive/ -> (a -> (p @@ 0)) -- ^ Function to apply to every element- -> (forall l . SNat l -> (p @@ l) -> (p @@ l) -> (p @@ (l + 1)))+ -> (forall n . SNat n -> (p @@ n) -> (p @@ n) -> (p @@ (n + 1))) -- ^ Function to combine results. -- -- __NB__: The @SNat l@ indicates the depth/height of the node in the@@ -2603,8 +2543,12 @@ sn' = sn `subSNat` d1 (xsL,xsR) = splitAt (pow2SNat sn') xs in g sn' (go sn' xsL) (go sn' xsR)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE dtfold #-}+#if __GLASGOW_HASKELL__ < 912+ go _ Nil =+ case (const Dict :: forall m. Proxy m -> Dict (1 <= 2 ^ m)) (Proxy @n) of+ {}+#endif+{-# OPAQUE dtfold #-} {-# ANN dtfold hasBlackBox #-} -- | To be used as the motive /p/ for 'dfold', when the /f/ in \"'dfold' @p f@\"@@ -2642,7 +2586,7 @@ -- -- <<doc/csSort.svg>> vfold :: forall k a b . KnownNat k- => (forall l . SNat l -> a -> Vec l b -> Vec (l + 1) b)+ => (forall n . SNat n -> a -> Vec n b -> Vec (n + 1) b) -> Vec k a -> Vec k b vfold f xs = dfold (Proxy @(VCons b)) f Nil xs@@ -2671,13 +2615,29 @@ -- (1 :> 2 :> 3 :> Nil) :> (1 :> 2 :> 3 :> Nil) :> (1 :> 2 :> 3 :> Nil) :> Nil -- >>> rotateMatrix xss -- (1 :> 2 :> 3 :> Nil) :> (3 :> 1 :> 2 :> Nil) :> (2 :> 3 :> 1 :> Nil) :> Nil-smap :: forall k a b . KnownNat k => (forall l . SNat l -> a -> b) -> Vec k a -> Vec k b+smap :: forall k a b . KnownNat k => (forall n . SNat n -> a -> b) -> Vec k a -> Vec k b smap f xs = reverse $ dfold (Proxy @(VCons b)) (\sn x xs' -> f sn x :> xs') Nil (reverse xs) {-# INLINE smap #-} +-- | Extended version of 'smap' offering an additional boundary proof to+-- the mapped function. Note that the type checker may need additional type+-- annotations to resolve type ambiguity for this. Thus, if the boundary constraint+-- is not needed it is recommended to stay with 'smap' instead.+smapWithBounds ::+ forall k a b .+ KnownNat k =>+ (forall n . n + 1 <= k => SNat n -> a -> b) ->+ Vec k a ->+ Vec k b+smapWithBounds f xs = reverse+ $ dfold (Proxy @(VCons b))+ (\sn x xs' -> f sn x :> xs')+ Nil (reverse xs)+{-# INLINE smapWithBounds #-}+ instance (KnownNat n, BitPack a) => BitPack (Vec n a) where type BitSize (Vec n a) = n * (BitSize a) pack = concatBitVector# . map pack . lazyV@@ -2695,8 +2655,7 @@ go (BV accMsk accVal) ((BV xMsk xVal) `Cons` xs) = let sh = fromInteger (natVal (Proxy @m)) :: Int in go (BV (shiftL accMsk sh .|. xMsk) (shiftL accVal sh .|. xVal)) xs--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE concatBitVector# #-}+{-# OPAQUE concatBitVector# #-} {-# ANN concatBitVector# hasBlackBox #-} unconcatBitVector#@@ -2712,8 +2671,7 @@ let (bv,xs) = go n (l,x) = (GHC.Magic.noinline split#) bv in (l,x :> xs)--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE unconcatBitVector# #-}+{-# OPAQUE unconcatBitVector# #-} {-# ANN unconcatBitVector# hasBlackBox #-} -- | Convert a 'BitVector' to a 'Vec' of 'Bit's.@@ -2745,8 +2703,7 @@ seqV v b = let s () e = seq e () in foldl s () v `seq` b--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE seqV #-}+{-# OPAQUE seqV #-} {-# ANN seqV hasBlackBox #-} infixr 0 `seqV` @@ -2769,8 +2726,7 @@ seqVX v b = let s () e = seqX e () in foldl s () v `seqX` b--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE seqVX #-}+{-# OPAQUE seqVX #-} {-# ANN seqVX hasBlackBox #-} infixr 0 `seqVX` @@ -2787,9 +2743,7 @@ instance Lift a => Lift (Vec n a) where lift Nil = [| Nil |] lift (x `Cons` xs) = [| x `Cons` $(lift xs) |]-#if MIN_VERSION_template_haskell(2,16,0) liftTyped = liftTypedFromUntyped-#endif instance (KnownNat n, Arbitrary a) => Arbitrary (Vec n a) where arbitrary = traverse# id $ repeat arbitrary@@ -2802,3 +2756,16 @@ type instance Lens.IxValue (Vec n a) = a instance KnownNat n => Lens.Ixed (Vec n a) where ix i f xs = replace_int xs (fromEnum i) <$> f (index_int xs (fromEnum i))++instance KnownNat n => Distributive (Vec n) where+ distribute fxs = tabulate $ \i -> fmap (!! i) fxs+ {-# INLINE distribute #-}++instance KnownNat n => Representable (Vec n) where+ type Rep (Vec n) = Index n++ tabulate f = map f indicesI+ {-# INLINE tabulate #-}++ index = (!!)+ {-# INLINE index #-}
src/Clash/Sized/Vector/ToTuple.hs view
@@ -30,11 +30,7 @@ import Data.Tagged (Tagged(..)) -#if MIN_VERSION_base(4,18,0) import Data.Tuple (Solo(MkSolo))-#elif MIN_VERSION_base(4,16,0)-import Data.Tuple (Solo(Solo))-#endif {- $setup >>> :set -XMonoLocalBinds -XGADTs@@ -62,14 +58,8 @@ -- -- >>> (a, b, c, d) = vecToTuple myVec -- ...-#if __GLASGOW_HASKELL__ > 900 -- • Couldn't match type: (a, b, c, d) -- with: (Int, Int, Int)-#else- -- • Couldn't match type: (Int, Int, Int)- -- ^- -- with: (a, b, c, d)-#endif -- ... vecToTuple :: a -> TupType a @@ -77,17 +67,10 @@ type TupType (Vec 0 a) = Tagged a () vecToTuple _ = Tagged () -#if MIN_VERSION_base(4,18,0) -- | Instead of using 'vecToTuple' for @Vec 1 _@, you could also consider using 'head' instance VecToTuple (Vec 1 a) where type TupType (Vec 1 a) = Solo a vecToTuple (a1 :> _) = MkSolo a1-#elif MIN_VERSION_base(4,16,0)--- | Instead of using 'vecToTuple' for @Vec 1 _@, you could also consider using 'head'-instance VecToTuple (Vec 1 a) where- type TupType (Vec 1 a) = Solo a- vecToTuple (a1 :> _) = Solo a1-#endif -- | __NB__: The documentation only shows instances up to /3/-tuples. By -- default, instances up to and including /12/-tuples will exist. If the flag
src/Clash/Sized/Vector/ToTuple/TH.hs view
@@ -1,6 +1,5 @@ {-# OPTIONS_HADDOCK hide #-} -{-# LANGUAGE CPP #-} {-# LANGUAGE TemplateHaskellQuotes #-} module Clash.Sized.Vector.ToTuple.TH (vecToTupleInstance, vecToTupleInstances) where@@ -20,7 +19,6 @@ vecToTupleInstances :: Integer -> Q [Dec] vecToTupleInstances n = mapM vecToTupleInstance [3..n] - vecToTupleInstance :: Integer -> Q Dec vecToTupleInstance n = instanceD@@ -31,17 +29,7 @@ (vecToTupleCon `appT` vecType) -- Implementation- [ tySynInstD-#if !MIN_VERSION_template_haskell(2,15,0)- (mkName "TupType")-#endif- ( tySynEqn-#if MIN_VERSION_template_haskell(2,15,0)- Nothing aTypeLhs-#else- [vecType]-#endif- aTypeRhs )+ [ tySynInstD (tySynEqn Nothing aTypeLhs aTypeRhs) , funD vecToTupleFunName [clause [vecToTuplePat] (normalB vecToTupleImpl) []] ] @@ -50,10 +38,8 @@ vecType = conT ''Vec `appT` litT (numTyLit n) `appT` varT (mkName "a") -- associated type-#if MIN_VERSION_template_haskell(2,15,0) tupTypeCon = conT (mkName "TupType") aTypeLhs = tupTypeCon `appT` vecType-#endif aTypeRhs = tupT [varT (mkName "a") | _ <- [1..n]] -- vecToTuple
src/Clash/Tutorial.hs view
@@ -2,2504 +2,24 @@ Copyright : © 2014-2016, Christiaan Baaij, 2017-2019, Myrtle Software Ltd 2017 , QBayLogic, Google Inc.,- 2021-2023, QBayLogic B.V.- 2022 , LUMI GUIDE FIETSDETECTIE B.V.- 2023 , Alex Mason--Licence : Creative Commons 4.0 (CC BY 4.0) (https://creativecommons.org/licenses/by/4.0/)-Maintainer: QBayLogic B.V. <devops@qbaylogic.com>--}--{-# LANGUAGE NoImplicitPrelude #-}--{-# OPTIONS_GHC -fno-warn-unused-imports #-}--module Clash.Tutorial (- -- * Introduction- -- $introduction-- -- * Install Clash- -- $installation-- -- * Working with this tutorial- -- $working-- -- * Your first circuit- -- $mac_example-- -- *** Sequential circuit- -- $mac2-- -- *** Generating VHDL- -- $mac3-- -- *** Circuit testbench- -- $mac4-- -- *** Generating Verilog and SystemVerilog- -- $mac5-- -- *** Alternative specifications- -- $mac6-- -- * Higher-order functions- -- $higher_order-- -- * Composition of sequential circuits- -- $composition_sequential-- -- * Synthesize annotations: controlling the VHDL\/(System)Verilog generation.- -- $annotations-- -- * Multiple clock domains- -- $multiclock-- -- * Advanced: Primitives- -- $primitives-- -- *** Verilog primitives- -- $vprimitives-- -- *** SystemVerilog primitives- -- $svprimitives-- -- * Conclusion- -- $conclusion-- -- * Troubleshooting- -- $errorsandsolutions-- -- * Limitations of Clash- -- $limitations-- -- * Clash vs Lava- -- $vslava-- -- * Migration guide from Clash 0.99- -- $migration- )-where--import Clash.Prelude-import Clash.Prelude.Mealy-import Clash.Explicit.Testbench-import Clash.XException (NFDataX)-import Control.Monad.ST-import Data.Array-import Data.Char-import Data.Int-import GHC.Prim-import GHC.TypeLits-import GHC.Word-import GHC.Stack-import Data.Default.Class--{- $setup->>> :set -XTemplateHaskell -XDataKinds -XConstraintKinds -XTypeApplications->>> :m -Prelude->>> import Clash.Prelude->>> import Clash.Prelude.Mealy->>> import Clash.Explicit.Testbench->>> :{-let ma :: Num a => a -> (a, a) -> a- ma acc (x,y) = acc + x * y-:}-->>> :{-let macT :: Num a => a -> (a,a) -> (a,a)- macT acc (x,y) = (acc',o)- where- acc' = ma acc (x,y)- o = acc-:}-->>> :set -XFlexibleContexts->>> :set -fplugin GHC.TypeLits.Normalise->>> let compareSwapL a b = if a < b then (a,b) else (b,a)->>> :{-let sortV xs = map fst sorted :< (snd (last sorted))- where- lefts = head xs :> map snd (init sorted)- rights = tail xs- sorted = zipWith compareSwapL lefts rights-:}-->>> :{-let sortVL xs = map fst sorted :< (snd (last sorted))- where- lefts = head xs :> map snd (init sorted)- rights = tail xs- sorted = zipWith compareSwapL (lazyV lefts) rights-:}-->>> let mac = mealy macT 0->>> :{-let topEntity- :: Clock System- -> Reset System- -> Enable System- -> Signal System (Signed 9, Signed 9)- -> Signal System (Signed 9)- topEntity = exposeClockResetEnable mac-:}-->>> :{-let testBench :: Signal System Bool- testBench = done- where- testInput = stimuliGenerator clk rst $(listToVecTH [(1,1) :: (Signed 9,Signed 9),(2,2),(3,3),(4,4)])- expectedOutput = outputVerifier' clk rst $(listToVecTH [0 :: Signed 9,1,5,14,14,14,14])- done = expectedOutput (topEntity clk rst enableGen testInput)- clk = tbSystemClockGen (not <$> done)- rst = systemResetGen-:}-->>> :{-let fibR :: Unsigned 64 -> Unsigned 64- fibR 0 = 0- fibR 1 = 1- fibR n = fibR (n-1) + fibR (n-2)-:}-->>> :{-let fibS :: SystemClockResetEnable => Signal System (Unsigned 64)- fibS = r- where r = register 0 r + register 0 (register 1 r)-:}---}--{- $introduction-Clash is a functional hardware description language that borrows both its syntax-and semantics from the functional programming language Haskell. It provides a-familiar structural design approach to both combination and synchronous-sequential circuits. The Clash compiler transforms these high-level descriptions-to low-level synthesizable VHDL, Verilog, or SystemVerilog.--Features of Clash:-- * Strongly typed, but with a very high degree of type inference, enabling- both safe and fast prototyping using concise descriptions.- * Interactive REPL: load your designs in an interpreter and easily test all- your component without needing to setup a test bench.- * Compile your designs for fast simulation.- * Higher-order functions, in combination with type inference, result in- designs that are fully parametric by default.- * Synchronous sequential circuit design based on streams of values, called- @Signal@s, lead to natural descriptions of feedback loops.- * Multiple clock domains, with type safe clock domain crossing.- * Template language for introducing new VHDL/(System)Verilog primitives.--Although we say that Clash borrows the semantics of Haskell, that statement-should be taken with a grain of salt. What we mean to say is that the Clash-compiler views a circuit description as /structural/ description. This means,-in an academic handwavy way, that every function denotes a component and every-function application denotes an instantiation of said component. Now, this has-consequences on how we view /recursively/ defined functions: structurally, a-recursively defined function would denote an /infinitely/ deep / structured-component, something that cannot be turned into an actual circuit-(See also <#limitations Limitations of Clash>).--On the other hand, Haskell's by-default non-strict evaluation works very well-for the simulation of the feedback loops, which are ubiquitous in digital-circuits. That is, when we take our structural view to circuit descriptions,-value-recursion corresponds directly to a feedback loop:--@-counter = s- where- s = 'register' 0 (s + 1)-@--The above definition, which uses value-recursion, /can/ be synthesized to a-circuit by the Clash compiler.--Over time, you will get a better feeling for the consequences of taking a-/structural/ view on circuit descriptions. What is always important to-remember is that every applied functions results in an instantiated component,-and also that the compiler will /never/ infer / invent more logic than what is-specified in the circuit description.--With that out of the way, let us continue with installing Clash and building-our first circuit.--}--{- $installation-For installation instructions, see <https://clash-lang.org/install/ clash-lang.org/install/>.--}--{- $working-This tutorial can be followed best whilst having the Clash interpreter running-at the same time. If you followed the installation instructions based on-<https://docs.haskellstack.org/en/stable/README/#how-to-install Stack>, you can-start the Clash compiler in interpretive mode by:--> stack exec --resolver lts-19 --package clash-ghc -- clashi--If instead you followed the [instructions](https://clash-lang.org/install/linux/)-to setup a starter project with Stack, you can also run @clashi@ inside such a-project. Change to the directory of the project, and invoke--> stack run -- clashi--If you instead set up the starter project with GHC and Cabal, change to the-directory of the project and invoke--> cabal run -- clashi--For those familiar with Haskell/GHC, this is indeed just @GHCi@, with three-added commands (@:vhdl@, @:verilog@, and @:systemverilog@). You can load files-into the interpreter using the @:l \<FILENAME\>@ command. Now, depending on your-choice in editor, the following @edit-load-run@ cycle probably work best for you:-- * __Commandline (e.g. emacs, vim):__-- * You can run system commands using @:!@, for example @:! touch \<FILENAME\>@- * Set the /editor/ mode to your favourite editor using: @:set editor \<EDITOR\>@- * You can load files using @:l@ as noted above.- * You can go into /editor/ mode using: @:e@- * Leave the editor mode by quitting the editor (e.g. @:wq@ in @vim@)-- * __GUI (e.g. SublimeText, Notepad++):__-- * Just create new files in your editor.- * Load the files using @:l@ as noted above.- * Once a file has been edited and saved, type @:r@ to reload the files in- the interpreter--You are of course free to deviate from these suggestions as you see fit :-). It-is just recommended that you have the Clash interpreter open during this-tutorial.--}--{- $mac_example-The very first circuit that we will build is the \"classic\" multiply-and-accumulate-(MAC) circuit. This circuit is as simple as it sounds, it multiplies its inputs-and accumulates them. Before we describe any logic, we must first create the-file we will be working on and input some preliminaries:--* Create the file:-- @- MAC.hs- @--* Write on the first line the module header:-- @- module MAC where- @-- Module names must always start with a __C__apital letter. Also make sure that- the file name corresponds to the module name.--* Add the import statement for the Clash prelude library:-- @- import Clash.Prelude- @-- This imports all the necessary functions and datatypes for circuit description.--We can now finally start describing the logic of our circuit, starting with just-the multiplication and addition:--@-ma acc (x, y) = acc + x * y-@--The circuit we just wrote is a combinational circuit: no registers are inserted-(you describe explicitly where Clash will insert registers, as we'll later see). We usually-refer to circuits as /functions/, similar to programming languages such as C,-Python, or Haskell. In this case, the function we just defined is called @ma@.-Its first argument is @acc@, its second is @(x, y)@ - a composite type called a-tuple. This component is "unpacked", and its first element is called @x@, its-second @y@. Everything to the right of the equals symbol is @ma@'s-result.-If you followed the instructions of running the interpreter side-by-side, you-can already test this function:-->>> ma 4 (8, 9)-76->>> ma 2 (3, 4)-14--We can also examine the inferred type of @ma@ in the interpreter:-->>> :t ma-ma :: Num a => a -> (a, a) -> a--You should read this as follows:-- * __@ma ::@__, @ma@ is of type..-- * __@Num a@__, there is some type called @a@ that is a 'Num'. Examples of- instances of 'Num' are 'Int', @'Signed' 16@, @'Index' 32@, and 'Float'.-- * __@a@__, @ma@'s first argument is of type @a@-- * __@(a, a)@__, @ma@'s second argument is of type @(a, a)@-- * __@a@__, @ma@'s result is of type @a@--Note that @ma@ therefore works on multiple types! The only condition we-imposed is that @a@ should be a 'Num'ber type. In Clash this means it should-support the operations 'Prelude.+', 'Prelude.-', 'Prelude.*', and some-others. Indeed, this is why Clash adds the constraint in the first place: the-definition of @ma@ uses @+@ and @*@. Whenever a function works over multiple-types, we call it /polymorphic/ ("poly" meaning "many", "morphic" meaning-"forms"). While powerful, its not clear how Clash should synthesize this as-numbers come in a great variety in (bit)sizes. We will later see how to use this-function in a /monomorphic/ manner.--Talking about /types/ also brings us to one of the most important parts of this-tutorial: /types/ and /synchronous sequential logic/. Especially how we can-always determine, through the types of a specification, if it describes-combinational logic or (synchronous) sequential logic. We do this by examining-the definition of one of the sequential primitives, the 'register' function:--@-register- :: ( 'HiddenClockResetEnable' dom- , 'NFDataX' a )- => a- -> 'Signal' dom a- -> 'Signal' dom a-register i s = ...-@--Where we see that the second argument and the result are not just of the-/polymorphic/ @a@ type, but of the type: @'Signal' dom a@. All (synchronous)-sequential circuits work on values of type @'Signal' dom a@. Combinational-circuits always work on values of, well, not of type @'Signal' dom a@. A 'Signal'-is an (infinite) list of samples, where the samples correspond to the values-of the 'Signal' at discrete, consecutive, ticks of the /clock/. All (sequential)-components in the circuit are synchronized to this global /clock/. For the-rest of this tutorial, and probably at any moment where you will be working with-Clash, you should probably not actively think about 'Signal's as infinite lists-of samples, but just as values that are manipulated by sequential circuits. To-make this even easier, it actually not possible to manipulate the underlying-representation directly: you can only modify 'Signal' values through a set of-primitives such as the 'register' function above.--Now, let us get back to the functionality of the 'register' function: it is-a simple <https://en.wikipedia.org/wiki/Flip-flop_(electronics) latch> that-only changes state at the tick of the global /clock/, and-it has an initial value @a@ which is its output at time 0. We can further-examine the 'register' function by taking a look at the first 4 samples of the-'register' functions applied to a constant signal with the value 8:-->>> sampleN @System 4 (register 0 (pure (8 :: Signed 8)))-[0,0,8,8]--Where we see that the initial value of the signal is the specified 0 value,-followed by 8's. You might be surprised to see /two/ zeros instead of just a-single zero. What happens is that in Clash you get to see the output of the-circuit /before/ the clock becomes active. In other words, in Clash you get to-describe the powerup values of registers too. Whether this is a defined or-unknown value depends on your hardware target, and can be configured by using a-different synthesis 'Domain'. The default synthesis domain, @'System', assumes-that registers do have a powerup value - as is true for most FPGA platforms in-most contexts.--}--{- $mac2-The 'register' function is our primary sequential building block to capture-/state/. It is used internally by one of the "Clash.Prelude" function that we-will use to describe our MAC circuit. Note that the following paragraphs will-only show one of many ways to specify a sequential circuit, in the section-<#mac6 Alternative specifications> we will show a couple more.--A principled way to describe a sequential circuit is to use one of the classic-machine models, within the Clash prelude library offer standard function to-support the <http://en.wikipedia.org/wiki/Mealy_machine Mealy machine>.-To improve sharing, we will combine the transition function and output function-into one. This gives rise to the following Mealy specification of the MAC-circuit:--@-macT acc (x, y) = (acc', o)- where- acc' = ma acc (x, y)- o = acc-@--Note that the @where@ clause and explicit tuple are just for demonstrative-purposes, without loss of sharing we could've also written:--@-macT acc inp = (ma acc inp, acc)-@--Going back to the original specification we note the following:-- * @acc@ is the current /state/ of the circuit.- * @(x, y)@ is its input.- * @acc'@ is the updated, or next, /state/.- * @o@ is the output.--When we examine the type of @macT@ we see that is still completely combinational:-->>> :t macT-macT :: Num a => a -> (a, a) -> (a, a)--The "Clash.Prelude" library contains a function that creates a sequential-circuit from a combinational circuit that has the same Mealy machine type /-shape of @macT@:--@-mealy- :: ('HiddenClockResetEnable' dom, 'NFDataX' s)- => (s -> i -> (s,o))- -> s- -> ('Signal' dom i -> 'Signal' dom o)-mealy f initS = ...-@--The complete sequential MAC circuit can now be specified as:--@-mac inp = 'mealy' macT 0 inp-@--Where the first argument of 'mealy' is our @macT@ function, and the second-argument is the initial state, in this case 0. We can see it is functioning-correctly in our interpreter:-->>> import qualified Data.List as L->>> L.take 4 $ simulate @System mac [(1,1),(2,2),(3,3),(4,4)]-[0,1,5,14]--Where we simulate our sequential circuit over a list of input samples and take-the first 4 output samples. We have now completed our first sequential circuit-and have made an initial confirmation that it is working as expected.--}--{- $mac3-We are now almost at the point that we can create actual hardware, in the form-of a <http://en.wikipedia.org/wiki/VHDL VHDL> netlist, from our sequential-circuit specification. The first thing we have to do is create a function-called @topEntity@ and ensure that it has a __monomorphic__ type. In our case-that means that we have to give it an explicit type annotation. It might not-always be needed, you can always check the type with the @:t@ command and see-if the function is monomorphic:--@-topEntity- :: 'Clock' 'System'- -> 'Reset' 'System'- -> 'Enable' 'System'- -> 'Signal' 'System' ('Signed' 9, 'Signed' 9)- -> 'Signal' 'System' ('Signed' 9)-topEntity = 'exposeClockResetEnable' mac-@--Which makes our circuit work on 9-bit signed integers. Including the above-definition, our complete @MAC.hs@ should now have the following content:--@-module MAC where--import "Clash.Prelude"--ma acc (x,y) = acc + x * y--macT acc (x,y) = (acc',o)- where- acc' = ma acc (x,y)- o = acc--mac xy = 'mealy' macT 0 xy--topEntity- :: 'Clock' 'System'- -> 'Reset' 'System'- -> 'Enable' 'System'- -> 'Signal' 'System' ('Signed' 9, 'Signed' 9)- -> 'Signal' 'System' ('Signed' 9)-topEntity = 'exposeClockResetEnable' mac-@--The @topEntity@ function is the starting point for the Clash compiler to-transform your circuit description into a VHDL netlist. It must meet the-following restrictions in order for the Clash compiler to work:-- * It must be completely monomorphic- * It must be completely first-order- * Although not strictly necessary, it is recommended to /expose/ 'Hidden'- clock and reset arguments, as it makes user-controlled- <Clash-Tutorial.html#annotations name assignment> in the generated HDL- easier to do.--Our @topEntity@ meets those restrictions, and so we can convert it successfully-to VHDL by executing the @:vhdl@ command in the interpreter. This will create-a directory called @vhdl@, which contains a directory called @MAC@, which-ultimately contains all the generated VHDL files. You can now load these files-into your favourite VHDL synthesis tool, marking @topentity.vhdl@ as the file-containing the top level entity.--}--{- $mac4-There are multiple reasons as to why you might want to create a so-called-/test bench/ for the generated HDL:-- * You want to compare post-synthesis / post-place&route behavior to that of- the behavior of the original generated HDL.- * Need representative stimuli for your dynamic power calculations.- * Verify that the HDL output of the Clash compiler has the same behavior as- the Haskell / Clash specification.--For these purposes, you can have the Clash compiler generate a /test bench/. In-order for the Clash compiler to do this you need to do one of the following:-- * Create a function called /testBench/ in the root module.- * Annotate your /topEntity/ function (or function with a- <Clash-Tutorial.html#g:12 Synthesize> annotation)- with a 'TestBench' annotation.--For example, you can test the earlier defined /topEntity/ by:--@-import "Clash.Explicit.Testbench"--topEntity- :: 'Clock' System- -> 'Reset' System- -> 'Enable' System- -> 'Signal' System ('Signed' 9, 'Signed' 9)- -> 'Signal' System ('Signed' 9)-topEntity = 'exposeClockResetEnable' mac--testBench :: 'Signal' System Bool-testBench = done- where- testInput = 'stimuliGenerator' clk rst $('listToVecTH' [(1,1) :: ('Signed' 9,'Signed' 9),(2,2),(3,3),(4,4)])- expectOutput = 'outputVerifier'' clk rst $('listToVecTH' [0 :: 'Signed' 9,1,5,14,14,14,14])- done = expectOutput (topEntity clk rst en testInput)- en = 'enableGen'- clk = 'tbSystemClockGen' (not '<$>' done)- rst = 'systemResetGen'-@--This will create a stimulus generator that creates the same inputs as we used-earlier for the simulation of the circuit, and creates an output verifier that-compares against the results we got from our earlier simulation. We can even-simulate the behavior of the /testBench/:-->>> sampleN 8 testBench-[False,False,False,False,False-cycle(<Clock: System>): 5, outputVerifier-expected value: 14, not equal to actual value: 30-,False-cycle(<Clock: System>): 6, outputVerifier-expected value: 14, not equal to actual value: 46-,False-cycle(<Clock: System>): 7, outputVerifier-expected value: 14, not equal to actual value: 62-,False]--We can see that for the first 4 samples, everything is working as expected,-after which warnings are being reported. The reason is that 'stimuliGenerator'-will keep on producing the last sample, (4,4), while the 'outputVerifier'' will-keep on expecting the last sample, 14. In the VHDL testbench these errors won't-show, as the global clock will be stopped after 4 ticks.--You should now again run @:vhdl@ in the interpreter; this time the compiler-will take a bit longer to generate all the circuits. Inside the @.\/vhdl\/MAC@-directory you will now also find a /testbench/ subdirectory containing all the-@vhdl@ files for the /test bench/.---After compilation is finished you load all the files in your favourite VHDL-simulation tool. Once all files are loaded into the VHDL simulator, run the-simulation on the @testbench@ entity.-On questasim / modelsim: doing a @run -all@ will finish once the output verifier-will assert its output to @true@. The generated testbench, modulo the clock-signal generator(s), is completely synthesizable. This means that if you want to-test your circuit on an FPGA, you will only have to replace the clock signal-generator(s) by actual clock sources, such as an onboard PLL.--}--{- $mac5-Aside from being able to generate VHDL, the Clash compiler can also generate Verilog-and SystemVerilog. You can repeat the previous two parts of the tutorial, but-instead of executing the @:vhdl@ command, you execute the @:verilog@ or-@:sytemverilog@ command in the interpreter. This will create a directory called-@verilog@, respectively @systemverilog@, which contains a directory called @MAC@,-which ultimately contains all the generated Verilog and SystemVerilog files.-Verilog files end in the file extension @v@, while SystemVerilog files end in-the file extension @sv@.--This concludes the main part of this section on \"Your first circuit\", read on-for alternative specifications for the same @mac@ circuit, or just skip to the-next section where we will describe another DSP classic: an FIR filter-structure.--}--{- $mac6 #mac6#--* __'Num' instance for 'Signal'__:-- @'Signal' a@ is also also considered a 'Num'eric type as long as the value- type /a/ is also 'Num'eric. This means that we can also use the standard- numeric operators, such as ('GHC.Num.*') and ('GHC.Num.+'), directly on signals. An- alternative specification of the @mac@ circuit will also use the 'register'- function directly:-- @- macN xy = acc- where- (x,y) = 'unbundle' xy- acc = 'register' 0 (acc + x * y)- @--* __'Applicative' instance for 'Signal'__:-- We can also mix the combinational @ma@ function, with the sequential- 'register' function, by lifting the @ma@ function to the sequential 'Signal'- domain using the operators ('<$>' and '<*>') of the 'Applicative' type- class:-- @- macA xy = acc- where- acc = 'register' 0 acc'- acc' = ma '<$>' acc '<*>' xy- @--* __t'Control.Monad.State.Strict.State' Monad__-- We can also implement the original @macT@ function as- a t'Control.Monad.State.Strict.State' monadic computation. First we must add- an extra import statement, right after the import of "Clash.Prelude":-- @- import Control.Monad.State.Strict- @-- We can then implement macT as follows:-- @- macTS (x,y) = do- acc <- 'Control.Monad.State.Strict.get'- 'Control.Monad.State.Strict.put' (acc + x * y)- return acc- @-- We can use the 'mealyS' function to run our stateful implementation, this- can simplify translating algorithms which are described imperatively.-- @- mealyS- :: ( HiddenClockResetEnable dom, NFDataX s )- => (i -> State s o)- -> s- -> (Signal dom i -> Signal dom o)- mealyS f initS = ...- @-- We can then create the complete @mac@ circuit as:-- @- macS xy = 'mealyS' macTS 0 xy- @--}--{- $higher_order-An FIR filter is defined as: the dot-product of a set of filter coefficients and-a window over the input, where the size of the window matches the number-of coefficients.--@-dotp as bs = 'sum' ('zipWith' (*) as bs)--fir coeffs x_t = y_t- where- y_t = dotp coeffs xs- xs = 'window' x_t--topEntity- :: 'Clock' 'System'- -> 'Reset' 'System'- -> 'Enable' 'System'- -> 'Signal' 'System' ('Signed' 16)- -> 'Signal' 'System' ('Signed' 16)-topEntity = exposeClockResetEnable (fir (0 ':>' 1 ':>' 2 ':>' 3 ':>' 'Nil'))-@--Here we can see that, although the Clash compiler handles recursive function-definitions poorly, many of the regular patterns that we often encounter in-circuit design are already captured by the higher-order functions that are-present for the 'Vec'tor type.--}--{- $composition_sequential-Given a function @f@ of type:--@-__f__ :: Int -> (Bool, Int) -> (Int, (Int, Bool))-@--When we want to make compositions of @f@ in @g@ using 'mealy', we have to-write:--@-g a b c = (b1,b2,i2)- where- (i1,b1) = 'unbundle' ('mealy' f 0 ('bundle' (a,b)))- (i2,b2) = 'unbundle' ('mealy' f 3 ('bundle' (c,i1)))-@--Why do we need these 'bundle', and 'unbundle' functions you might ask? When we-look at the type of 'mealy':--@-__mealy__- :: HiddenClockResetEnable dom- => (s -> i -> (s,o))- -> s- -> ('Signal' dom i -> 'Signal' dom o)-@--we see that the resulting function has an input of type @'Signal' dom i@, and-an output of @'Signal' dom o@. However, the type of @(a,b)@ in the definition-of @g@ is: @('Signal' dom Bool, 'Signal' dom Int)@. And the type of @(i1,b1)@-is of type @('Signal' dom Int, 'Signal' dom Bool)@.--Syntactically, @'Signal' dom (Bool,Int)@ and @('Signal' dom Bool,-'Signal' dom Int)@ are /unequal/.-So we need to make a conversion between the two, that is what 'bundle' and-'unbundle' are for. In the above case 'bundle' gets the type:--@-__bundle__ :: ('Signal' dom Bool, 'Signal' dom Int) -> 'Signal' dom (Bool,Int)-@--and 'unbundle':--@-__unbundle__ :: 'Signal' dom (Int,Bool) -> ('Signal' dom Int, 'Signal' dom Bool)-@--The /true/ types of these two functions are, however:--@-__bundle__ :: 'Bundle' a => 'Unbundled' dom a -> 'Signal' dom a-__unbundle__ :: 'Bundle' a => 'Signal' dom a -> 'Unbundled' dom a-@--'Unbundled' is an <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#associated-data-and-type-families associated type family>-belonging to the 'Bundle' <http://en.wikipedia.org/wiki/Type_class type class>,-which, together with 'bundle' and 'unbundle' defines the isomorphism between a-product type of 'Signal's and a 'Signal' of a product type. That is, while-@('Signal' dom a, 'Signal' dom b)@ and @'Signal' dom (a,b)@ are not equal,-they are /isomorphic/ and can be converted from, or to, the other using-'bundle' and 'unbundle'.--Instances of this 'Bundle' type-class are defined as /isomorphisms/ for:-- * All tuples up to and including 62-tuples (GHC limit)- * The 'Vec'tor type--But they are defined as /identities/ for:-- * All elementary / primitive types such as: 'Bit', 'Bool', @'Signed' n@, etc.--That is:--@-instance 'Bundle' (a,b) where- type 'Unbundled' dom (a,b) = ('Signal' dom a, 'Signal' dom b)- bundle (a,b) = (,) '<$>' a '<*>' b- unbundle tup = (fst '<$>' tup, snd '<*>' tup)-@--but,--@-instance 'Bundle' Bool where- type 'Unbundled' dom Bool = 'Signal' dom Bool- bundle s = s- unbundle s = s-@--What you need take away from the above is that a product type (e.g. a tuple) of-'Signal's is not syntactically equal to a 'Signal' of a product type, but that-the functions of the 'Bundle' type class allow easy conversion between the two.--As a final note on this section we also want to mention the 'mealyB' function,-which does the bundling and unbundling for us:--@-mealyB- :: ('Bundle' i, 'Bundle' o)- => (s -> i -> (s,o))- -> s- -> 'Unbundled' dom i- -> 'Unbundled' dom o-@--Using 'mealyB' we can define @g@ as:--@-g a b c = (b1,b2,i2)- where- (i1,b1) = 'mealyB' f 0 (a,b)- (i2,b2) = 'mealyB' f 3 (c,i1)-@--The general rule of thumb is: always use 'mealy', unless you do pattern matching-or construction of product types, then use 'mealyB'.--}--{- $annotations #annotations#-'Synthesize' annotations allow us to control hierarchy and naming aspects of the-Clash compiler, specifically, they allow us to:-- * Assign names to entities (VHDL) \/ modules ((System)Verilog), and their- ports.- * Put generated HDL files of a logical (sub)entity in their own directory.- * Use cached versions of generated HDL, i.e., prevent recompilation of- (sub)entities that have not changed since the last run. Caching is based- on a @.manifest@ which is generated alongside the HDL; deleting this file- means deleting the cache; changing this file will result in /undefined/- behavior.--Functions with a 'Synthesize' annotation must adhere to the following-restrictions:-- * Although functions with a 'Synthesize' annotation can of course depend- on functions with another 'Synthesize' annotation, they must not be- mutually recursive.- * Functions with a 'Synthesize' annotation must be completely /monomorphic/- and /first-order/, and cannot have any /non-representable/ arguments or- result.--Also take the following into account when using 'Synthesize' annotations.-- * The Clash compiler is based on the GHC Haskell compiler, and the GHC- machinery does not understand 'Synthesize' annotations and it might- subsequently decide to inline those functions. You should therefor also- add a @{\-\# NOINLINE f \#-\}@ pragma to the functions which you give- a 'Synthesize' functions.- * Functions with a 'Synthesize' annotation will not be specialized- on constants.--Finally, the root module, the module which you pass as an argument to the-Clash compiler must either have:-- * A function with a 'Synthesize' annotation.- * A function called /topEntity/.--You apply 'Synthesize' annotations to functions using an @ANN@ pragma:--@-{\-\# ANN topEntity (Synthesize {t_name = ..., ... }) \#-\}-topEntity x = ...-@--For example, given the following specification:--@-module Blinker where--import "Clash.Signal"-import "Clash.Prelude"-import "Clash.Intel.ClockGen"--'createDomain' vSystem{vName=\"DomInput\", vPeriod=20000, vResetPolarity=ActiveLow}-'createDomain' vSystem{vName=\"Dom100\", vPeriod=10000}--topEntity- :: Clock DomInput- -> Reset DomInput- -> Signal Dom100 Bit- -> Signal Dom100 (BitVector 8)-topEntity clk rst =- 'exposeClockResetEnable' ('mealy' blinkerT (1,False,0) . 'Clash.Prelude.isRising' 1) pllOut pllRst 'enableGen'- where- (pllOut,pllRst) = 'Clash.Intel.ClockGen.altpllSync' clk rst--blinkerT (leds,mode,cntr) key1R = ((leds',mode',cntr'),leds)- where- -- clock frequency = 100e6 (100 MHz)- -- led update rate = 333e-3 (every 333ms)- cnt_max = 'maxBound' :: ('Index' 33300000) -- 100e6 * 333e-3-- cntr' | cntr == cnt_max = 0- | otherwise = cntr + 1-- mode' | key1R = not mode- | otherwise = mode-- leds' | cntr == 0 = if mode then complement leds- else rotateL leds 1- | otherwise = leds-@--The Clash compiler will normally generate the following @topentity.vhdl@ file:--> -- Automatically generated VHDL-93-> library IEEE;-> use IEEE.STD_LOGIC_1164.ALL;-> use IEEE.NUMERIC_STD.ALL;-> use IEEE.MATH_REAL.ALL;-> use std.textio.all;-> use work.all;-> use work.Blinker_topEntity_types.all;->-> entity topEntity is-> port(-- clock-> clk : in Blinker_topEntity_types.clk_DomInput;-> -- reset-> rst : in Blinker_topEntity_types.rst_DomInput;-> eta : in std_logic;-> result : out std_logic_vector(7 downto 0));-> end;->-> architecture structural of topEntity is-> ...-> end;--However, if we add the following 'Synthesize' annotation in the file:--@-{\-\# ANN topEntity- ('Synthesize'- { t_name = "blinker"- , t_inputs = [PortName \"CLOCK_50\", PortName \"KEY0\", PortName \"KEY1\"]- , t_output = PortName \"LED\"- }) \#-\}-@--The Clash compiler will generate the following @blinker.vhdl@ file instead:--> -- Automatically generated VHDL-93-> library IEEE;-> use IEEE.STD_LOGIC_1164.ALL;-> use IEEE.NUMERIC_STD.ALL;-> use IEEE.MATH_REAL.ALL;-> use std.textio.all;-> use work.all;-> use work.blinker_types.all;->-> entity blinker is-> port(-- clock-> CLOCK_50 : in blinker_types.clk_DomInput;-> -- reset-> KEY0 : in blinker_types.rst_DomInput;-> KEY1 : in std_logic;-> LED : out std_logic_vector(7 downto 0));-> end;->-> architecture structural of blinker is-> ...-> end;--Where we now have:--* A top-level component that is called @blinker@.-* Inputs and outputs that have a /user/-chosen name: @CLOCK_50@, @KEY0@, @KEY1@, @LED@, etc.--See the documentation of 'Synthesize' for the meaning of all its fields.--}--{- $primitives #primitives#-There are times when you already have an existing piece of IP, or there are-times where you need the VHDL to have a specific shape so that the VHDL-synthesis tool can infer a specific component. In these specific cases you can-resort to defining your own VHDL primitives. Actually, most of the primitives-in Clash are specified in the same way as you will read about in this section.-There are perhaps 10 (at most) functions which are truly hard-coded into the-Clash compiler. You can take a look at the files in-<https://github.com/clash-lang/clash-compiler/tree/master/clash-lib/prims/vhdl>-(or <https://github.com/clash-lang/clash-compiler/tree/master/clash-lib/prims/verilog>-for the Verilog primitives or <https://github.com/clash-lang/clash-compiler/tree/master/clash-lib/prims/systemverilog>-for the SystemVerilog primitives) if you want to know which functions are defined-as \"regular\" primitives. The compiler looks for primitives in four locations:--* The official install location: e.g.-- * @$CABAL_DIR\/share\/\<GHC_VERSION\>\/clash-lib\-<VERSION\>\/prims\/common@- * @$CABAL_DIR\/share\/\<GHC_VERSION\>\/clash-lib\-<VERSION\>\/prims\/commonverilog@- * @$CABAL_DIR\/share\/\<GHC_VERSION\>\/clash-lib\-<VERSION\>\/prims\/systemverilog@- * @$CABAL_DIR\/share\/\<GHC_VERSION\>\/clash-lib\-<VERSION\>\/prims\/verilog@- * @$CABAL_DIR\/share\/\<GHC_VERSION\>\/clash-lib\-<VERSION\>\/prims\/vhdl@--* Directories indicated by a 'Clash.Annotations.Primitive.Primitive' annotation-* The current directory (the location given by @pwd@)-* The include directories specified on the command-line: @-i\<DIR\>@--Where redefined primitives in the current directory or include directories will-overwrite those in the official install location. For now, files containing-primitive definitions must have a @.primitives.yaml@ file-extension.--Clash differentiates between two types of primitives, /expression/ primitives-and /declaration/ primitives, corresponding to whether the primitive is a VHDL-/expression/ or a VHDL /declaration/. We will first explore /expression/-primitives, using 'Signed' multiplication (@*@) as an example. The-"Clash.Sized.Internal.Signed" module specifies multiplication as follows:--@-(*#) :: 'KnownNat' n => 'Signed' n -> 'Signed' n -> 'Signed' n-(S a) *# (S b) = fromInteger_INLINE (a * b)-{\-\# NOINLINE (*#) \#-\}-@--For which the VHDL /expression/ primitive is:--> BlackBox:-> name: Clash.Sized.Internal.Signed.*#-> kind: Expression-> type: '(*#) :: KnownNat n => Signed n -> Signed n -> Signed n'-> template: resize(~ARG[1] * ~ARG[2], ~LIT[0])--The @name@ of the primitive is the /fully qualified/ name of the function you-are creating the primitive for. Because we are creating an /expression/-primitive the kind must be set to @Expression@. As the name suggest, it is a VHDL-/template/, meaning that the compiler must fill in the holes heralded by the-tilde (~). Here:-- * @~ARG[1]@ denotes the second argument given to the @(*#)@ function, which- corresponds to the LHS of the (@*@) operator.- * @~ARG[2]@ denotes the third argument given to the @(*#)@ function, which- corresponds to the RHS of the (@*@) operator.- * @~LIT[0]@ denotes the first argument given to the @(*#)@ function, with- the extra condition that it must be a @LIT@eral. If for some reason this- first argument does not turn out to be a literal then the compiler will- raise an error. This first arguments corresponds to the \"@'KnownNat' n@\"- class constraint.--An extensive list with all of the template holes will be given the end of this-section. What we immediately notice is that class constraints are counted as-normal arguments in the primitive definition. This is because these class-constraints are actually represented by ordinary record types, with fields-corresponding to the methods of the type class. In the above case, 'KnownNat'-is actually just like a @newtype@ wrapper for 'Integer'.--The second kind of primitive that we will explore is the /declaration/ primitive.-We will use @blockRam#@ as an example, for which the Haskell/Clash code is:--@-{\-\# LANGUAGE BangPatterns \#\-\}--module BlockRam where--import Clash.Explicit.Prelude-import Clash.Annotations.Primitive (hasBlackBox)-import Clash.Signal.Internal (Clock, Signal (..), (.&&.))-import Clash.Sized.Vector (Vec, toList)-import Clash.XException (defaultSeqX)--import qualified Data.Vector as V-import GHC.Stack (HasCallStack, withFrozenCallStack)--blockRam#- :: ( KnownDomain dom- , HasCallStack- , NFDataX a )- => 'Clock' dom -- ^ Clock to synchronize to- -> 'Enable' dom -- ^ Global enable- -> 'Vec' n a -- ^ Initial content of the BRAM, also- -- determines the size, \@n\@, of the BRAM.- --- -- \_\_NB\_\_: \_\_MUST\_\_ be a constant.- -> 'Signal' dom Int -- ^ Read address \@r\@- -> 'Signal' dom Bool -- ^ Write enable- -> 'Signal' dom Int -- ^ Write address \@w\@- -> 'Signal' dom a -- ^ Value to write (at address \@w\@)- -> 'Signal' dom a -- ^ Value of the BRAM at address \@r\@ from- -- the previous clock cycle-blockRam# (Clock _) gen content rd wen =- go- (V.fromList ('toList' content))- (withFrozenCallStack ('deepErrorX' "blockRam: intial value undefined"))- (fromEnable gen)- rd- (fromEnable gen '.&&.' wen)- where- go !ram o ret\@(~(re :- res)) rt\@(~(r :- rs)) et\@(~(e :- en)) wt\@(~(w :- wr)) dt\@(~(d :- din)) =- let ram' = d ``defaultSeqX`` upd ram e (fromEnum w) d- o' = if re then ram V.! r else o- in o ``seqX`` o :- (ret ``seq`` rt ``seq`` et ``seq`` wt ``seq`` dt ``seq`` go ram' o' res rs en wr din)-- upd ram we waddr d = case maybeIsX we of- Nothing -> case maybeIsX waddr of- Nothing -> V.map (const (seq waddr d)) ram- Just wa -> ram V.// [(wa,d)]- Just True -> case maybeIsX waddr of- Nothing -> V.map (const (seq waddr d)) ram- Just wa -> ram V.// [(wa,d)]- _ -> ram-{\-\# NOINLINE blockRam# \#\-\}-{\-\# ANN blockRam# hasBlackBox \#\-\}-@--And for which the /declaration/ primitive is:--> BlackBox:-> name: Clash.Explicit.BlockRam.blockRam#-> kind: Declaration-> type: |--> blockRam#-> :: ( KnownDomain dom ARG[0]-> , HasCallStack -- ARG[1]-> , NFDataX a ) -- ARG[2]-> => Clock dom -- clk, ARG[3]-> -> Enable dom -- en, ARG[4]-> -> Vec n a -- init, ARG[5]-> -> Signal dom Int -- rd, ARG[6]-> -> Signal dom Bool -- wren, ARG[7]-> -> Signal dom Int -- wr, ARG[8]-> -> Signal dom a -- din, ARG[9]-> -> Signal dom a-> template: |--> -- blockRam begin-> ~GENSYM[~RESULT_blockRam][1] : block-> signal ~GENSYM[~RESULT_RAM][2] : ~TYP[5] := ~CONST[5];-> signal ~GENSYM[rd][4] : integer range 0 to ~LENGTH[~TYP[5]] - 1;-> signal ~GENSYM[wr][5] : integer range 0 to ~LENGTH[~TYP[5]] - 1;-> begin-> ~SYM[4] <= to_integer(~ARG[6])-> -- pragma translate_off-> mod ~LENGTH[~TYP[5]]-> -- pragma translate_on-> ;-> ~SYM[5] <= to_integer(~ARG[8])-> -- pragma translate_off-> mod ~LENGTH[~TYP[5]]-> -- pragma translate_on-> ;-> ~IF ~VIVADO ~THEN-> ~SYM[6] : process(~ARG[3])-> begin-> if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3]) then-> if ~ARG[7] ~IF ~ISACTIVEENABLE[4] ~THEN and ~ARG[4] ~ELSE ~FI then-> ~SYM[2](~SYM[5]) <= ~TOBV[~ARG[9]][~TYP[9]];-> end if;-> ~RESULT <= fromSLV(~SYM[2](~SYM[4]))-> -- pragma translate_off-> after 1 ps-> -- pragma translate_on-> ;-> end if;-> end process; ~ELSE-> ~SYM[6] : process(~ARG[3])-> begin-> if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3]) then-> if ~ARG[7] ~IF ~ISACTIVEENABLE[4] ~THEN and ~ARG[4] ~ELSE ~FI then-> ~SYM[2](~SYM[5]) <= ~ARG[9];-> end if;-> ~RESULT <= ~SYM[2](~SYM[4])-> -- pragma translate_off-> after 1 ps-> -- pragma translate_on-> ;-> end if;-> end process; ~FI-> end block;-> --end blockRam--Again, the @name@ of the primitive is the fully qualified name of the function-you are creating the primitive for. Because we are creating a /declaration/-primitive the /kind/ must be set to @Declaration@. Instead of discussing what the-individual template holes mean in the above context, we will instead just give-a general listing of the available template holes:--* @~RESULT@: Signal to which the result of a primitive must be assigned- to. NB: Only used in a /declaration/ primitive.-* @~ARG[N]@: @(N+1)@'th argument to the function.-* @~CONST[N]@: @(N+1)@'th argument to the function. Like @~ARG@, but Clash will- try to reduce this to a literal, even if it would otherwise consider it too- expensive. And if Clash fails to reduce this argument to a literal it will- produce an error.-* @~LIT[N]@: @(N+1)@'th argument to the function. Like @~CONST~ but values are- rendered as a bare literals, without any size or type annotations.- This only works for numeric types, and not for BitVector.-* @~TYP[N]@: VHDL type of the @(N+1)@'th argument.-* @~TYPO@: VHDL type of the result.-* @~TYPM[N]@: VHDL type/name/ of the @(N+1)@'th argument; used in /type/- /qualification/.-* @~TYPMO@: VHDL type/name/ of the result; used in /type qualification/.-* @~ERROR[N]@: Error value for the VHDL type of the @(N+1)@'th argument.-* @~ERRORO@: Error value for the VHDL type of the result.-* @~GENSYM[\<NAME\>][N]@: Create a unique name, trying to stay as close to- the given @\<NAME\>@ as possible. This unique symbol can be referred to in- other places using @~SYM[N]@.-* @~SYM[N]@: a reference to the unique symbol created by @~GENSYM[\<NAME\>][N]@.-* @~SIGD[\<HOLE\>][N]@: Create a signal declaration, using @\<HOLE\>@ as the name- of the signal, and the type of the @(N+1)@'th argument.-* @~SIGDO[\<HOLE\>]@: Create a signal declaration, using @\<HOLE\>@ as the name- of the signal, and the type of the result.-* @~TYPEL[\<HOLE\>]@: The element type of the vector type represented by @\<HOLE\>@.- The content of @\<HOLE\>@ must either be: @~TYP[N]@, @~TYPO@, or @~TYPEL[\<HOLE\>]@.-* @~COMPNAME@: The name of the component in which the primitive is instantiated.-* @~LENGTH[\<HOLE\>]@: The vector length of the type represented by @\<HOLE\>@.-* @~DEPTH[\<HOLE\>]@: The tree depth of the type represented by @\<HOLE\>@.- The content of @\<HOLE\>@ must either be: @~TYP[N]@, @~TYPO@, or @~TYPEL[\<HOLE\>]@.-* @~SIZE[\<HOLE\>]@: The number of bits needed to encode the type represented by @\<HOLE\>@.- The content of @\<HOLE\>@ must either be: @~TYP[N]@, @~TYPO@, or @~TYPEL[\<HOLE\>]@.-* @~IF \<CONDITION\> ~THEN \<THEN\> ~ELSE \<ELSE\> ~FI@: renders the @\<ELSE\>@- part when @\<CONDITION\>@ evaluates to /0/, and renders the @\<THEN\>@ in all- other cases. Valid @\<CONDITION\>@s are @~LENGTH[\<HOLE\>]@, @~SIZE[\<HOLE\>]@,- @~CMPLE[\<HOLE1\>][\<HOLE2\>]@,- @~DEPTH[\<HOLE\>]@, @~VIVADO@, @~IW64@, @~ISLIT[N]@, @~ISVAR[N]@, @~ISACTIVEENABLE[N]@,- @~ISSYNC[N]@, and @~AND[\<HOLE1\>,\<HOLE2\>,..]@.-* @~VIVADO@: /1/ when Clash compiler is invoked with the @-fclash-xilinx@ or- @-fclash-vivado@ flag. To be used with in an @~IF .. ~THEN .. ~ELSE .. ~FI@- statement.-* @~CMPLE[\<HOLE1\>][\<HOLE2\>]@: /1/ when @\<HOLE1\> \<= \<HOLE2\>@, otherwise /0/-* @~IW64@: /1/ when @Int@\/@Word@\/@Integer@ types are represented with 64 bits in HDL.- /0/ when they're represented by 32 bits.-* @~TOBV[\<HOLE\>][\<TYPE\>]@: create conversion code that so that the- expression in @\<HOLE\>@ is converted to a bit vector (@std_logic_vector@).- The @\<TYPE\>@ hole indicates the type of the expression and must be either- @~TYP[N]@, @~TYPO@, or @~TYPEL[\<HOLE\>]@.-* @~FROMBV[\<HOLE\>][\<TYPE\>]@: create conversion code that so that the- expression in @\<HOLE\>@, which has a bit vector (@std_logic_vector@) type,- is converted to type indicated by @\<TYPE\>@. The @\<TYPE\>@ hole must be- either @~TYP[N]@, @~TYPO@, or @~TYPEL[\<HOLE\>]@.-* @~INCLUDENAME[N]@: the generated name of the @N@'th included component.-* @~FILE[\<HOLE\>]@: The argument mentioned in @\<HOLE\>@ is a file which- must be copied to the location of the generated HDL.-* @~GENERATE@: Verilog: create a /generate/ statement, except when already in- a /generate/ context.-* @~ENDGENERATE@: Verilog: create an /endgenerate/ statement, except when already- in a /generate/ context.-* @~ISLIT[N]@: Is the @(N+1)@'th argument to the function a literal.-* @~ISVAR[N]@: Is the @(N+1)@'th argument to the function explicitly not a- literal.-* @~ISSCALAR[N]@: Is the @(N+1)@'th argument to the function a scalar. Note- that this means different things for different HDLs. In (System)Verilog only- @Bit@ and @Bool@ are considered scalar. In VHDL, in addition to those two,- enumeration types and integers are considered scalar.-* @~TAG[N]@: Name of given domain. Errors when called on an argument which is not- a 'KnownDomain', 'Reset', or 'Clock'.-* @~PERIOD[N]@: Clock period of given domain. Errors when called on an argument- which is not a 'Clock', 'Reset', 'KnownDomain' or 'KnownConf'.-* @~ISACTIVEENABLE[N]@: Is the @(N+1)@'th argument a an Enable line __not__ set to a- constant True. Can be used instead of deprecated (and removed) template tag-* @~ISSYNC[N]@: Does synthesis domain at the @(N+1)@'th argument have synchronous resets. Errors- when called on an argument which is not a 'Reset', 'Clock', 'Enable', 'KnownDomain' or 'KnownConf'.-* @~ISINITDEFINED[N]@: Does synthesis domain at the @(N+1)@'th argument have defined initial- values. Errors when called on an argument which is not a 'Clock', 'Reset', 'Enable', 'KnownDomain' or 'KnownConf'.-* @~ACTIVEEDGE[edge][N]@: Does synthesis domain at the @(N+1)@'th argument respond to- /edge/. /edge/ must be one of 'Falling' or 'Rising'. Errors when called on an- argument which is not a 'Clock', 'Reset', 'Enable', 'KnownDomain' or 'KnownConf'.-* @~AND[\<HOLE1\>,\<HOLE2\>,..]@: Logically /and/ the conditions in the @\<HOLE\>@'s-* @~VAR[\<NAME\>][N]@: Like @~ARG[N]@ but binds the argument to a variable named NAME.- The @\<NAME\>@ can be left blank, then Clash will come up with a (unique) name.-* @~VARS[N]@: VHDL: Return the variables at the @(N+1)@'th argument.-* @~NAME[N]@: Render the @(N+1)@'th string literal argument as an identifier- instead of a string literal. Fails when the @(N+1)@'th argument is not a- string literal.-* @~DEVNULL[\<HOLE\>]@: Render all dependencies of @\<HOLE\>@, but disregard direct output.-* @~REPEAT[\<HOLE\>][N]@: Repeat literal value of @\<HOLE\>@ a total of @N@ times.-* @~TEMPLATE[\<HOLE1\>][\<HOLE2\>]@: Render a file @\<HOLE1\>@ with contents @\<HOLE2\>@.---Some final remarks to end this section: VHDL primitives are there to instruct the-Clash compiler to use the given VHDL template, instead of trying to do normal-synthesis. As a consequence you can use constructs inside the Haskell-definitions that are normally not synthesizable by the Clash compiler. However,-VHDL primitives do not give us /co-simulation/: where you would be able to-simulate VHDL and Haskell in a /single/ environment. If you still want to-simulate your design in Haskell, you will have to describe, in a cycle- and-bit-accurate way, the behavior of that (potentially complex) IP you are trying-to include in your design.--Perhaps in the future, someone will figure out how to connect the two simulation-worlds, using e.g. VHDL's foreign function interface VHPI.--}--{- $vprimitives-For those who are interested, the equivalent Verilog primitives are:--> BlackBox:-> name: Clash.Sized.Internal.Signed.*#-> kind: Expression-> type: '(*#) :: KnownNat n => Signed n -> Signed n -> Signed n'-> template: ~ARG[1] * ~ARG[2]--and--> BlackBox:-> name: Clash.Explicit.BlockRam.blockRam#-> kind: Declaration-> outputUsage: NonBlocking-> type: |--> blockRam#-> :: ( KnownDomain dom ARG[0]-> , HasCallStack -- ARG[1]-> , NFDataX a ) -- ARG[2]-> => Clock dom -- clk, ARG[3]-> => Enable dom -- en, ARG[4]-> -> Vec n a -- init, ARG[5]-> -> Signal dom Int -- rd, ARG[6]-> -> Signal dom Bool -- wren, ARG[7]-> -> Signal dom Int -- wr, ARG[8]-> -> Signal dom a -- din, ARG[9]-> -> Signal dom a-> template: |--> // blockRam begin-> reg ~TYPO ~GENSYM[~RESULT_RAM][1] [0:~LENGTH[~TYP[5]]-1];->-> reg ~TYP[5] ~GENSYM[ram_init][3];-> integer ~GENSYM[i][4];-> initial begin-> ~SYM[3] = ~CONST[5];-> for (~SYM[4]=0; ~SYM[4] < ~LENGTH[~TYP[5]]; ~SYM[4] = ~SYM[4] + 1) begin-> ~SYM[1][~LENGTH[~TYP[5]]-1-~SYM[4]] = ~SYM[3][~SYM[4]*~SIZE[~TYPO]+:~SIZE[~TYPO]];-> end-> end-> ~IF ~ISACTIVEENABLE[4] ~THEN-> always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~GENSYM[~RESULT_blockRam][5]~IF ~VIVADO ~THEN-> if (~ARG[4]) begin-> if (~ARG[7]) begin-> ~SYM[1][~ARG[8]] <= ~ARG[9];-> end-> ~RESULT <= ~SYM[1][~ARG[6]];-> end~ELSE-> if (~ARG[7] & ~ARG[4]) begin-> ~SYM[1][~ARG[8]] <= ~ARG[9];-> end-> if (~ARG[4]) begin-> ~RESULT <= ~SYM[1][~ARG[6]];-> end~FI-> end~ELSE-> always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~SYM[5]-> if (~ARG[7]) begin-> ~SYM[1][~ARG[8]] <= ~ARG[9];-> end-> ~RESULT <= ~SYM[1][~ARG[6]];-> end~FI-> // blockRam end---}--{- $svprimitives-And the equivalent SystemVerilog primitives are:--> BlackBox:-> name: Clash.Sized.Internal.Signed.*#-> kind: Expression-> type: '(*#) :: KnownNat n => Signed n -> Signed n -> Signed n'-> template: ~ARG[1] * ~ARG[2]--and--> BlackBox:-> name: Clash.Explicit.BlockRam.blockRam#-> kind: Declaration-> type: |--> blockRam#-> :: ( KnownDomain dom ARG[0]-> , HasCallStack -- ARG[1]-> , NFDataX a ) -- ARG[2]-> => Clock dom -- clk, ARG[3]-> -> Enable dom -- en, ARG[4]-> -> Vec n a -- init, ARG[5]-> -> Signal dom Int -- rd, ARG[6]-> -> Signal dom Bool -- wren, ARG[7]-> -> Signal dom Int -- wr, ARG[8]-> -> Signal dom a -- din, ARG[9]-> -> Signal dom a-> template: |--> // blockRam begin-> ~SIGD[~GENSYM[RAM][1]][5];-> logic [~SIZE[~TYP[9]]-1:0] ~GENSYM[~RESULT_q][2];-> initial begin-> ~SYM[1] = ~CONST[5];-> end~IF ~ISACTIVEENABLE[4] ~THEN-> always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~GENSYM[~COMPNAME_blockRam][3]~IF ~VIVADO ~THEN-> if (~ARG[4]) begin-> if (~ARG[7]) begin-> ~SYM[1][~ARG[8]] <= ~TOBV[~ARG[9]][~TYP[9]];-> end-> ~SYM[2] <= ~SYM[1][~ARG[6]];-> end~ELSE-> if (~ARG[7] & ~ARG[4]) begin-> ~SYM[1][~ARG[8]] <= ~TOBV[~ARG[9]][~TYP[9]];-> end-> if (~ARG[4]) begin-> ~SYM[2] <= ~SYM[1][~ARG[6]];-> end~FI-> end~ELSE-> always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~SYM[3]-> if (~ARG[7]) begin-> ~SYM[1][~ARG[8]] <= ~TOBV[~ARG[9]][~TYP[9]];-> end-> ~SYM[2] <= ~SYM[1][~ARG[6]];-> end~FI-> assign ~RESULT = ~FROMBV[~SYM[2]][~TYP[9]];-> // blockRam end---}--{- $multiclock #multiclock#-Clash supports designs multiple /clock/ (and /reset/) domains, though perhaps in-a slightly limited form. What is possible is:--* Create clock primitives, such as PLLs, which have an accompanying HDL primitive- (described <#primitives later on> in this tutorial).-* Explicitly assign clocks to memory primitives.-* Synchronize between differently-clocked parts of your design in a type-safe- way.--What is /not/ possible is:--* Directly generate a clock signal in module A, and assign this clock signal to- a memory primitive in module B. For example, the following is not possible:-- @- pow2Clocks- :: ( 'KnownConfiguration' domIn (''DomainConfiguration' domIn pIn eIn rIn iIn polIn)- , 'KnownConfiguration' dom2 (''DomainConfiguration' dom2 (2*pIn) e2 r2 i2 p2)- , 'KnownConfiguration' dom4 (''DomainConfiguration' dom4 (4*pIn) e4 r4 i4 p4)- , 'KnownConfiguration' dom8 (''DomainConfiguration' dom8 (8*pIn) e8 r8 i8 p8)- , 'KnownConfiguration' dom16 (''DomainConfiguration' dom16 (16*pIn) e16 r16 i16 p16)- => 'Clock' domIn- -> 'Reset' domIn- -> ( 'Clock' dom16- , 'Clock' dom8- , 'Clock' dom4- , 'Clock' dom2 )- pow2Clocks clk rst = (cnt!3, cnt!2, cnt!1, cnt!0)- where- cnt = 'Clash.Explicit.Signal.register' clk rst 0 (cnt + 1)- @-- As it is not possible to convert the individual bits to a 'Clock'.-- However! What is possible is to do the following:-- @- pow2Clocks'- :: ( 'KnownConfiguration' domIn (''DomainConfiguration' domIn pIn eIn rIn iIn polIn)- , 'KnownConfiguration' dom2 (''DomainConfiguration' dom2 (2*pIn) e2 r2 i2 p2)- , 'KnownConfiguration' dom4 (''DomainConfiguration' dom4 (4*pIn) e4 r4 i4 p4)- , 'KnownConfiguration' dom8 (''DomainConfiguration' dom8 (8*pIn) e8 r8 i8 p8)- , 'KnownConfiguration' dom16 (''DomainConfiguration' dom16 (16*pIn) e16 r16 i16 p16)- => 'Clock' domIn- -> 'Reset' domIn- -> ( 'Clock' dom16- , 'Clock' dom8- , 'Clock' dom4- , 'Clock' dom2 )- pow2Clocks' clk rst = ('clockGen', 'clockGen', 'clockGen', 'clockGen')- {\-\# NOINLINE pow2Clocks' \#-\}- @-- And then create a HDL primitive, as described in later on in- this <#primitives tutorial>, to implement the desired behavior in HDL.--What this means is that when Clash converts your design to VHDL/(System)Verilog,-you end up with a top-level module/entity with multiple clock and reset ports-for the different clock domains. If you're targeting an FPGA, you can use e.g. a-<https://www.altera.com/literature/ug/ug_altpll.pdf PLL> or-<http://www.xilinx.com/support/documentation/user_guides/ug472_7Series_Clocking.pdf MMCM>-to provide the clock signals.--== Building a FIFO synchronizer--This part of the tutorial assumes you know what <https://en.wikipedia.org/wiki/Metastability_in_electronics metastability>-is, and how it can never truly be avoided in any asynchronous circuit. Also-it assumes that you are familiar with the design of synchronizer circuits, and-why a dual flip-flop synchronizer only works for bit-synchronization and not-word-synchronization.-The explicitly clocked versions of all synchronous functions and primitives can-be found in "Clash.Explicit.Prelude", which also re-exports the functions in-"Clash.Signal.Explicit". We will use those functions to create a FIFO where-the read and write port are synchronized to different clocks. Below you can find-the code to build the FIFO synchronizer based on the design described in:-<http://www.sunburst-design.com/papers/CummingsSNUG2002SJ_FIFO1.pdf>--We start with enable a few options that will make writing the type-signatures for-our components a bit easier. Instead of importing the standard "Clash.Prelude"-module, we will import the "Clash.Explicit.Prelude" module where all our clocks-and resets must be explicitly routed (other imports will be used later):--@-module MultiClockFifo where--import "Clash.Explicit.Prelude"-import "Clash.Prelude" (mux)-import Data.Maybe (isJust)-import Data.Constraint (Dict (..), (:-)( Sub ))-import Data.Constraint.Nat (leTrans)-@--Then we'll start with the /heart/ of the FIFO synchronizer, an asynchronous RAM-in the form of 'asyncRam'. It's called an asynchronous RAM because the read-port is not synchronized to any clock (though the write port is). Note that in-Clash we don't really have asynchronous logic, there is only combinational and-synchronous logic. As a consequence, we see in the type signature of-'Clash.Explicit.Prelude.asyncRam':--@-__asyncRam__- :: ( 'Enum' addr- , 'HasCallStack'- , 'KnownDomain' wdom- , 'KnownDomain' rdom- , 'NFDataX' a- )- => 'Clock' wdom -- ^ Clock to which to synchronize the write port of the RAM- -> 'Clock' rdom -- ^ Clock to which the read address signal, \@r\@, is synchronized to- -> 'Enable' wdom -- ^ Global enable- -> 'SNat' n -- ^ Size \@n\@ of the RAM- -> 'Signal' rdom addr -- ^ Read address \@r\@- -> 'Signal' wdom (Maybe (addr, a)) -- ^ (write address \@w\@, value to write)- -> 'Signal' rdom a -- ^ Value of the RAM at address \@r\@-@--that the signal containing the read address __r__ is synchronized to a different-clock. That is, there is __no__ such thing as an @AsyncSignal@ in Clash.--We continue by instantiating the 'Clash.Explicit.Prelude.asyncRam':--@-fifoMem wclk rclk en addrSize\@SNat full raddr writeM =- 'Clash.Explicit.Prelude.asyncRam'- wclk rclk en- ('pow2SNat' addrSize)- raddr- ('mux' full (pure Nothing) writeM)-@--We see that we give it @2^addrSize@ elements, where @addrSize@ is the bit-size-of the address. Also, we only write new values to the RAM when a new write is-requested, indicated by @wdataM@ having a 'Data.Maybe.Just' value, and the-buffer is not full, indicated by @wfull@.--The next part of the design calculates the read and write address for the-asynchronous RAM, and creates the flags indicating whether the FIFO is full-or empty. The address and flag generator is given in 'mealy' machine style:--@-ptrCompareT- :: SNat addrSize- -> (BitVector (addrSize + 1) -> BitVector (addrSize + 1) -> Bool)- -> ( BitVector (addrSize + 1)- , BitVector (addrSize + 1)- , Bool )- -> ( BitVector (addrSize + 1)- , Bool )- -> ( ( BitVector (addrSize + 1)- , BitVector (addrSize + 1)- , Bool )- , ( Bool- , BitVector addrSize- , BitVector (addrSize + 1)- )- )-ptrCompareT addrSize\@SNat flagGen (bin, ptr, flag) (s_ptr, inc) =- ( (bin', ptr', flag')- , (flag, addr, ptr) )- where- -- GRAYSTYLE2 pointer- bin' = bin + 'boolToBV' (inc && not flag)- ptr' = (bin' \`shiftR\` 1) \`xor\` bin'- addr = 'truncateB' bin- flag' = flagGen ptr' s_ptr-@--It is parametrized in both address size, @addrSize@, and status flag generator,-@flagGen@. It has two inputs, @s_ptr@, the synchronized pointer from the other-clock domain, and @inc@, which indicates we want to perform a write or read of-the FIFO. It creates three outputs: @flag@, the full or empty flag, @addr@, the-read or write address into the RAM, and @ptr@, the Gray-encoded version of the-read or write address which will be synchronized between the two clock domains.--Next follow the initial states of address generators, and the flag generators-for the empty and full flags:--@--- FIFO empty: when next pntr == synchronized wptr or on reset-isEmpty = (==)-rptrEmptyInit = (0, 0, True)---- FIFO full: when next pntr == synchronized {~wptr[addrSize:addrSize-1],wptr[addrSize-2:0]}-isFull- :: forall addrSize- . (2 <= addrSize)- => 'SNat' addrSize- -> 'BitVector' (addrSize + 1)- -> 'BitVector' (addrSize + 1)- -> Bool-isFull addrSize\@SNat ptr s_ptr = case leTrans \@1 \@2 \@addrSize of- Sub Dict ->- let a1 = 'SNat' \@(addrSize - 1)- a2 = 'SNat' \@(addrSize - 2)- in ptr == ('complement' ('slice' addrSize a1 s_ptr) '++#' 'slice' a2 d0 s_ptr)--wptrFullInit = (0, 0, False)-@--We create a dual flip-flop synchronizer to be used to synchronize the-Gray-encoded pointers between the two clock domains:--@-ptrSync clk1 clk2 rst2 en2 =- 'Clash.Explicit.Signal.register' clk2 rst2 en2 0 . 'Clash.Explicit.Signal.register' clk2 rst2 en2 0 . 'Clash.Explicit.Signal.unsafeSynchronizer' clk1 clk2-@--It uses the 'Clash.Explicit.Signal.unsafeSynchronizer' primitive, which is-needed to go from one clock domain to the other. The 'Clash.Explicit.Signal.unsafeSynchronizer'-primitive is turned into a (bundle of) wire(s) by the Clash compiler, so-developers must ensure that it is only used as part of a proper synchronizer.--Finally we combine all the components in:--@-asyncFIFOSynchronizer- :: ( 'KnownDomain' wdom- , 'KnownDomain' rdom- , 2 <= addrSize )- => SNat addrSize- -- ^ Size of the internally used addresses, the FIFO contains \@2^addrSize\@- -- elements.- -> 'Clock' wdom- -- ^ Clock to which the write port is synchronized- -> 'Clock' rdom- -- ^ Clock to which the read port is synchronized- -> 'Reset' wdom- -> 'Reset' rdom- -> 'Enable' wdom- -> 'Enable' rdom- -> 'Signal' rdom Bool- -- ^ Read request- -> 'Signal' wdom (Maybe a)- -- ^ Element to insert- -> ('Signal' rdom a, 'Signal' rdom Bool, 'Signal' wdom Bool)- -- ^ (Oldest element in the FIFO, \@empty\@ flag, \@full\@ flag)-asyncFIFOSynchronizer addrSize\@SNat wclk rclk wrst rrst wen ren rinc wdataM =- (rdata, rempty, wfull)- where- s_rptr = ptrSync rclk wclk wrst wen rptr- s_wptr = ptrSync wclk rclk rrst ren wptr-- rdata =- fifoMem- wclk rclk wen- addrSize wfull raddr- (liftA2 (,) \<$\> (pure \<$\> waddr) \<*\> wdataM)-- (rempty, raddr, rptr) =- 'mealyB'- rclk rrst ren- (ptrCompareT addrSize isEmpty)- (0, 0, True)- (s_wptr, rinc)-- (wfull, waddr, wptr) =- 'mealyB'- wclk wrst wen- (ptrCompareT addrSize (isFull addrSize))- (0, 0, False)- (s_rptr, isJust \<$\> wdataM)-@--where we first specify the synchronization of the read and the write pointers,-instantiate the asynchronous RAM, and instantiate the read address \/ pointer \/-flag generator and write address \/ pointer \/ flag generator.--Ultimately, the whole file containing our FIFO design will look like this:--@-module MultiClockFifo where--import "Clash.Explicit.Prelude"-import "Clash.Prelude" (mux)-import Data.Maybe (isJust)-import Data.Constraint (Dict (..), (:-)( Sub ))-import Data.Constraint.Nat (leTrans)--fifoMem wclk rclk en addrSize\@SNat full raddr writeM =- 'Clash.Explicit.Prelude.asyncRam'- wclk rclk en- ('pow2SNat' addrSize)- raddr- ('mux' full (pure Nothing) writeM)--ptrCompareT- :: SNat addrSize- -> (BitVector (addrSize + 1) -> BitVector (addrSize + 1) -> Bool)- -> ( BitVector (addrSize + 1)- , BitVector (addrSize + 1)- , Bool )- -> ( BitVector (addrSize + 1)- , Bool )- -> ( ( BitVector (addrSize + 1)- , BitVector (addrSize + 1)- , Bool )- , ( Bool- , BitVector addrSize- , BitVector (addrSize + 1)- )- )-ptrCompareT addrSize\@SNat flagGen (bin, ptr, flag) (s_ptr, inc) =- ( (bin', ptr', flag')- , (flag, addr, ptr) )- where- -- GRAYSTYLE2 pointer- bin' = bin + 'boolToBV' (inc && not flag)- ptr' = (bin' \`shiftR\` 1) \`xor\` bin'- addr = 'truncateB' bin- flag' = flagGen ptr' s_ptr---- FIFO empty: when next pntr == synchronized wptr or on reset-isEmpty = (==)-rptrEmptyInit = (0, 0, True)---- FIFO full: when next pntr == synchronized {~wptr[addrSize:addrSize-1],wptr[addrSize-2:0]}-isFull- :: forall addrSize- . (2 <= addrSize)- => 'SNat' addrSize- -> 'BitVector' (addrSize + 1)- -> 'BitVector' (addrSize + 1)- -> Bool-isFull addrSize\@SNat ptr s_ptr = case leTrans \@1 \@2 \@addrSize of- Sub Dict ->- let a1 = 'SNat' \@(addrSize - 1)- a2 = 'SNat' \@(addrSize - 2)- in ptr == ('complement' ('slice' addrSize a1 s_ptr) '++#' 'slice' a2 d0 s_ptr)--wptrFullInit = (0, 0, False)---- Dual flip-flop synchronizer-ptrSync clk1 clk2 rst2 en2 =- 'Clash.Explicit.Signal.register' clk2 rst2 en2 0 . 'Clash.Explicit.Signal.register' clk2 rst2 en2 0 . 'Clash.Explicit.Signal.unsafeSynchronizer' clk1 clk2---- Async FIFO synchronizer-asyncFIFOSynchronizer- :: ( 'KnownDomain' wdom- , 'KnownDomain' rdom- , 2 <= addrSize )- => SNat addrSize- -- ^ Size of the internally used addresses, the FIFO contains \@2^addrSize\@- -- elements.- -> 'Clock' wdom- -- ^ Clock to which the write port is synchronized- -> 'Clock' rdom- -- ^ Clock to which the read port is synchronized- -> 'Reset' wdom- -> 'Reset' rdom- -> 'Enable' wdom- -> 'Enable' rdom- -> 'Signal' rdom Bool- -- ^ Read request- -> 'Signal' wdom (Maybe a)- -- ^ Element to insert- -> ('Signal' rdom a, 'Signal' rdom Bool, 'Signal' wdom Bool)- -- ^ (Oldest element in the FIFO, \@empty\@ flag, \@full\@ flag)-asyncFIFOSynchronizer addrSize\@SNat wclk rclk wrst rrst wen ren rinc wdataM =- (rdata, rempty, wfull)- where- s_rptr = ptrSync rclk wclk wrst wen rptr- s_wptr = ptrSync wclk rclk rrst ren wptr-- rdata =- fifoMem- wclk rclk wen- addrSize wfull raddr- (liftA2 (,) \<$\> (pure \<$\> waddr) \<*\> wdataM)-- (rempty, raddr, rptr) =- 'mealyB'- rclk rrst ren- (ptrCompareT addrSize isEmpty)- (0, 0, True)- (s_wptr, rinc)-- (wfull, waddr, wptr) =- 'mealyB'- wclk wrst wen- (ptrCompareT addrSize (isFull addrSize))- (0, 0, False)- (s_rptr, isJust \<$\> wdataM)-@--== Instantiating a FIFO synchronizer--Having finished our FIFO synchronizer it's time to instantiate with concrete-clock domains. Let us assume we have part of our system connected to an ADC-which runs at 20 MHz, and we have created an FFT component running at only 9-MHz. We want to connect part of our design connected to the ADC, and running-at 20 MHz, to part of our design connected to the FFT running at 9 MHz.--We can calculate the clock periods using 'hzToPeriod':-->>> hzToPeriod 20e6-50000->>> hzToPeriod 9e6-111111--We can then create the clock and reset domains:--@-'createDomain' vSystem{vName=\"ADC\", vPeriod=hzToPeriod 20e6}-'createDomain' vSystem{vName=\"FFT\", vPeriod=hzToPeriod 9e6}-@--and subsequently a 256-space FIFO synchronizer that safely bridges the ADC clock-domain and to the FFT clock domain:--@-adcToFFT- :: 'Clock' \"ADC\"- -> 'Clock' \"FFT\"- -> 'Reset' \"ADC\"- -> 'Reset' \"FFT\"- -> 'Enable' \"ADC\"- -> 'Enable' \"FFT\"- -> 'Signal' \"FFT\" Bool- -> 'Signal' \"ADC\" (Maybe (SFixed 8 8))- -> ( 'Signal' \"FFT\" (SFixed 8 8)- , 'Signal' \"FFT\" Bool- , 'Signal' \"ADC\" Bool )-adcToFFT = asyncFIFOSynchronizer d8-@---}--{- $conclusion-For now, this is the end of this tutorial. We will be adding updates over time,-so check back from time to time. We recommend that you continue with-exploring the "Clash.Prelude" module, and get a better understanding of the-capabilities of Clash in the process.--}--{- $errorsandsolutions-A list of often encountered errors and their solutions:--* __Type error: Couldn't match expected type @'Signal' dom (a,b)@ with actual type__- __@('Signal' dom a, 'Signal' dom b)@__:-- Signals of product types and product types of signals are __isomorphic__- due to synchronisity principle, but are not (structurally) equal. Tuples- are a product type. Use the 'bundle' function to convert from a product- type to the signal type. So if your code which gives the error looks like:-- @- ... = f a b (c,d)- @-- add the 'bundle' function like so:-- @- ... = f a b ('bundle' (c,d))- @-- Product types supported by 'bundle' are:-- * All tuples up to and including 62-tuples (GHC limit)- * The 'Vec'tor type--* __Type error: Couldn't match expected type @('Signal' dom a, 'Signal' dom b)@ with__- __ actual type @'Signal' dom (a,b)@__:-- Product types of signals and signals of product types are __isomorphic__- due to synchronicity principle, but are not (structurally) equal. Tuples- are a product type. Use the 'unbundle' function to convert from a signal- type to the product type. So if your code which gives the error looks- like:-- @- (c,d) = f a b- @-- add the 'unbundle' function like so:-- @- (c,d) = 'unbundle' (f a b)- @-- Product types supported by 'unbundle' are:-- * All tuples up to and including 62-tuples (GHC limit)- * The 'Vec'tor type--* __Clash.Netlist(..): Not in normal form: \<REASON\>: \<EXPR\>__:-- A function could not be transformed into the expected normal form. This- usually means one of the following:-- * The @topEntity@ has higher-order arguments, or a higher-order result.- * You are using types which cannot be represented in hardware.-- The solution for all the above listed reasons is quite simple: remove them.- That is, make sure that the @topEntity@ is completely monomorphic and- first-order. Also remove any variables and constants/literals that have a- non-representable type; see <#limitations Limitations of Clash> to find- out which types are not representable.--* __Clash.Normalize(..): Clash can only normalize monomorphic functions, but this is polymorphic__:-- If this happens for a @topEntity@ or something with a @Synthesize@ annotation,- add a monomorphic type signature.- Non topEntites should be type-specialized by clash automatically, if not please report this as a bug.- But adding a monomorphic type signature should still help (when possible).---* __Clash.Normalize(..): Expr belonging to bndr: \<FUNCTION\> remains__- __recursive after normalization__:-- * If you actually wrote a recursive function, rewrite it to a non-recursive- one using e.g. one of the higher-order functions in "Clash.Sized.Vector" :-)-- * You defined a recursively defined value, but left it polymorphic:-- @- topEntity x y = acc- where- acc = 'register' 3 (acc + x * y)- @-- The above function, works for any number-like type. This means that @acc@ is- a recursively defined __polymorphic__ value. Adding a monomorphic type- annotation makes the error go away:-- @- topEntity- :: 'SystemClockResetEnable'- => 'Signal' 'System' ('Signed' 8)- -> 'Signal' 'System' ('Signed' 8)- -> 'Signal' 'System' ('Signed' 8)- topEntity x y = acc- where- acc = 'register' 3 (acc + x * y)- @--* __Clash.Normalize.Transformations(..): InlineNonRep: \<FUNCTION\> already__- __inlined 100 times in:\<FUNCTION\>, \<TYPE\>__:-- You left the @topEntity@ function polymorphic or higher-order: use- @:t topEntity@ to check if the type is indeed polymorphic or higher-order.- If it is, add a monomorphic type signature, and / or supply higher-order- arguments.--* __\<*** Exception: \<\<loop\>\>__ or "blinking cursor"-- You are using value-recursion, but one of the 'Vec'tor functions that you- are using is too /strict/ in one of the recursive arguments. For example:-- @- -- Bubble sort for 1 iteration- sortV xs = 'map' fst sorted ':<' (snd ('last' sorted))- where- lefts = 'head' xs :> 'map' snd ('init' sorted)- rights = 'tail' xs- sorted = 'zipWith' compareSwapL lefts rights-- -- Compare and swap- compareSwapL a b = if a < b then (a,b)- else (b,a)- @-- Will not terminate because 'zipWith' is too strict in its second argument.-- In this case, adding 'lazyV' on 'zipWith's second argument:-- @- sortVL xs = 'map' fst sorted ':<' (snd ('last' sorted))- where- lefts = 'head' xs :> map snd ('init' sorted)- rights = 'tail' xs- sorted = 'zipWith' compareSwapL ('lazyV' lefts) rights- @-- Results in a successful computation:-- >>> sortVL (4 :> 1 :> 2 :> 3 :> Nil)- 1 :> 2 :> 3 :> 4 :> Nil--}--{- $limitations #limitations#-Here is a list of Haskell features for which the Clash compiler has only-/limited/ support (for now):--* __Recursively defined functions__-- At first hand, it seems rather bad that a compiler for a functional language- cannot synthesize recursively defined functions to circuits. However, when- viewing your functions as a /structural/ specification of a circuit, this- /feature/ of the Clash compiler makes sense. Also, only certain types of- recursion are considered non-synthesizable; recursively defined values are- for example synthesizable: they are (often) synthesized to feedback loops.-- Let us distinguish between three variants of recursion:-- * __Dynamic data-dependent recursion__-- As demonstrated in this definition of a function that calculates the- n'th Fibbonacci number:-- @- fibR 0 = 0- fibR 1 = 1- fibR n = fibR (n-1) + fibR (n-2)- @-- To get the first 10 numbers, we do the following:-- >>> import qualified Data.List as L- >>> L.map fibR [0..9]- [0,1,1,2,3,5,8,13,21,34]-- The @fibR@ function is not synthesizable by the Clash compiler, because,- when we take a /structural/ view, @fibR@ describes an infinitely deep- structure.-- In principal, descriptions like the above could be synthesized to a- circuit, but it would have to be a /sequential/ circuit. Where the most- general synthesis would then require a stack. Such a synthesis approach- is also known as /behavioral/ synthesis, something which the Clash- compiler simply does not do. One reason that Clash does not do this is- because it does not fit the paradigm that only functions working on- values of type 'Signal' result in sequential circuits, and all other- (non higher-order) functions result in combinational circuits. This- paradigm gives the designer the most straightforward mapping from the- original Haskell description to generated circuit, and thus the greatest- control over the eventual size of the circuit and longest propagation- delay.-- * __Value-recursion__-- As demonstrated in this definition of a function that calculates the- n'th Fibbonaci number on the n'th clock cycle:-- @- fibS :: SystemClockResetEnable => Signal System (Unsigned 64)- fibS = r- where r = 'register' 0 r + 'register' 0 ('register' 1 r)- @-- To get the first 10 numbers, we do the following:-- >>> sampleN @System 11 fibS- [0,0,1,1,2,3,5,8,13,21,34]-- Unlike the @fibR@ function, the above @fibS@ function /is/ synthesizable- by the Clash compiler. Where the recursively defined (non-function)- value /r/ is synthesized to a feedback loop containing three registers- and one adder.-- Note that not all recursively defined values result in a feedback loop.- An example that uses recursively defined values which does not result- in a feedback loop is the following function that performs one iteration- of bubble sort:-- @- sortVL xs = 'map' fst sorted ':<' (snd ('last' sorted))- where- lefts = 'head' xs :> map snd ('init' sorted)- rights = 'tail' xs- sorted = 'zipWith' compareSwapL ('lazyV' lefts) rights- @-- Where we can clearly see that @lefts@ and @sorted@ are defined in terms- of each other. Also the above @sortV@ function /is/ synthesizable.-- * __Static/Structure-dependent recursion__-- Static, or, structure-dependent recursion is a rather /vague/ concept.- What we mean by this concept are recursive definitions where a user can- sensibly imagine that the recursive definition can be completely- unfolded (all recursion is eliminated) at compile-time in a finite- amount of time.-- Such definitions would e.g. be:-- @- mapV :: (a -> b) -> Vec n a -> Vec n b- mapV _ Nil = Nil- mapV f (Cons x xs) = Cons (f x) (mapV f xs)-- topEntity :: Vec 4 Int -> Vec 4 Int- topEntity = mapV (+1)- @-- Where one can imagine that a compiler can unroll the definition of- @mapV@ four times, knowing that the @topEntity@ function applies @mapV@- to a 'Vec' of length 4. Sadly, the compile-time evaluation mechanisms in- the Clash compiler are very poor, and a user-defined function such as- the @mapV@ function defined above, is /currently/ not synthesizable.- We /do/ plan to add support for this in the future. In the mean time,- this poor support for user-defined recursive functions is amortized by- the fact that the Clash compiler has built-in support for the- higher-order functions defined in "Clash.Sized.Vector". Most regular- design patterns often encountered in circuit design are captured by the- higher-order functions in "Clash.Sized.Vector".--* __Recursive datatypes__-- The Clash compiler needs to be able to determine a bit-size for any value- that will be represented in the eventual circuit. More specifically, we need- to know the maximum number of bits needed to represent a value. While this- is trivial for values of the elementary types, sum types, and product types,- putting a fixed upper bound on recursive types is not (always) feasible.- This means that the ubiquitous list type is unsupported! The only recursive- types that are currently supported by the Clash compiler is the 'Vec'tor and- 'RTree' types, for which the compiler has hard-coded knowledge.-- For \"easy\" 'Vec'tor literals you should use Template Haskell splices and- the 'listToVecTH' /meta/-function that as we have seen earlier in this tutorial.--* __GADTs__-- Clash has experimental support for GADTs. Similar to recursive types, Clash- can't determine bit-sizes of GADTs. Notable exceptions to this rule are- 'Vec' and 'RTree'. You can still use your own GADTs, as long as they can be- removed through static analysis. For example, the following case will be- optimized away and is therefore fine to use:-- @- x =- case 'resetKind' @'System' of- SAsynchronous -> \'a\'- SSynchronous -> \'b\'- @--* __Floating point types__-- There is no support for the 'Float' and 'Double' types, if you need numbers- with a /fractional/ part you can use the 'Fixed' point type.-- As to why there is no support for these floating point types:-- 1. In order to achieve reasonable operating frequencies, arithmetic- circuits for floating point data types must be pipelined.- 2. Haskell's primitive arithmetic operators on floating point data types,- such as 'plusFloat#'-- @- __plusFloat#__ :: 'Float#' -> 'Float#' -> 'Float#'- @-- which underlie 'Float'\'s 'Num' instance, must be implemented as- purely combinational circuits according to their type. Remember,- sequential circuits operate on values of type \"@'Signal' a@\".-- Although it is possible to implement purely combinational (not pipelined)- arithmetic circuits for floating point data types, the circuit would be- unreasonable slow. And so, without synthesis possibilities for the basic- arithmetic operations, there is no point in supporting the floating point- data types.--* __Haskell primitive types__-- Only the following primitive Haskell types are supported:-- * 'Integer'- * 'Int'- * 'Int8'- * 'Int16'- * 'Int32'- * 'Int64' (not available when compiling with @-fclash-intwidth=32@ on a 64-bit machine)- * 'Word'- * 'Word8'- * 'Word16'- * 'Word32'- * 'Word64' (not available when compiling with @-fclash-intwidth=32@ on a 64-bit machine)- * 'Char'-- There are several aspects of which you should take note:-- * 'Int' and 'Word' are represented by the same number of bits as is- native for the architecture of the computer on which the Clash- compiler is executed. This means that if you are working on a 64-bit- machine, 'Int' and 'Word' will be 64-bit. This might be problematic- when you are working in a team, and one designer has a 32-bit- machine, and the other has a 64-bit machine. In general, you should- be avoiding 'Int' in such cases, but as a band-aid solution, you can- force the Clash compiler to use a specific bit-width for `Int` and- `Word` using the @-fclash-intwidth=N@ flag, where /N/ must either be- /32/ or /64/.-- * When you use the @-fclash-intwidth=32@ flag on a /64-bit/ machine,- the 'Word64' and 'Int64' types /cannot/ be translated. This- restriction does /not/ apply to the other three combinations of- @-fclash-intwidth@ flag and machine type.-- * The translation of 'Integer' is not meaning-preserving. 'Integer' in- Haskell is an arbitrary precision integer, something that cannot- be represented in a statically known number of bits. In the Clash- compiler, we chose to represent 'Integer' by the same number of bits- as we do for 'Int' and 'Word'. As you have read in a previous- bullet point, this number of bits is either 32 or 64, depending on- the architecture of the machine the Clash compiler is running on, or- the setting of the @-fclash-intwidth@ flag.-- Consequently, you should use `Integer` with due diligence; be- especially careful when using `fromIntegral` as it does a conversion- via 'Integer'. For example:-- > signedToUnsigned :: Signed 128 -> Unsigned 128- > signedToUnsigned = fromIntegral-- can either lose the top 64 or 96 bits depending on whether 'Integer'- is represented by 64 or 32 bits. Instead, when doing such conversions,- you should use 'bitCoerce':-- > signedToUnsigned :: Signed 128 -> Unsigned 128- > signedToUnsigned = bitCoerce--* __Side-effects: 'IO', 'ST', etc.__-- There is no support for side-effecting computations such as those in the- 'IO' or 'ST' monad. There is also no support for Haskell's- <http://www.haskell.org/haskellwiki/Foreign_Function_Interface FFI>.--}--{- $vslava-In Haskell land the most well-known way of describing digital circuits is the-Lava family of languages:--* <http://hackage.haskell.org/package/chalmers-lava2000 Chalmers Lava>-* <http://hackage.haskell.org/package/xilinx-lava Xilinx Lava>-* <http://hackage.haskell.org/package/york-lava York Lava>-* <http://hackage.haskell.org/package/kansas-lava Kansas Lava>--The big difference between Clash and Lava is that Clash uses a \"standard\"-compiler (static analysis) approach towards synthesis, where Lava is an-embedded domain specific language. One downside of static analysis vs. the-embedded language approach is already clearly visible: synthesis of recursive-descriptions does not come for \"free\". This will be implemented in Clash in-due time, but that doesn't help the circuit designer right now. As already-mentioned earlier, the poor support for recursive functions is amortized by-the built-in support for the higher-order in "Clash.Sized.Vector".--The big upside of Clash and its static analysis approach is that Clash can-do synthesis of \"normal\" functions: there is no forced encasing datatype (often-called /Signal/ in Lava) on all the arguments and results of a synthesizable-function. This enables the following features not available to Lava:--* Automatic synthesis for user-defined ADTs-* Synthesis of all choice constructs (pattern matching, guards, etc.)-* 'Applicative' instance for the 'Signal' type-* Working with \"normal\" functions permits the use of e.g.- the t'Control.Monad.State.Strict.State' monad to describe the functionality of- a circuit.--Although there are Lava alternatives to some of the above features (e.g.-first-class patterns to replace pattern matching) they are not as \"beautiful\"-and / or easy to use as the standard Haskell features.--}--{- $migration--* Clash has overhauled the way synthesis options are represented. You can read- about this change in the blogpost: <https://clash-lang.org/blog/0005-synthesis-domain/ New feature: configurable initial values>.- The executive summary is as follows:--+------------------------------------------------------------------------------+--------------------------------------------------------------------+-| __0.99__ | __1.0__ |-+------------------------------------------------------------------------------+--------------------------------------------------------------------+-| @topEntity (clk::Clock d 'Source) rst = withClockReset f clk rst@ | @topEntity clk rst = withClockResetEnable clk rst enableGen f@ |-+------------------------------------------------------------------------------+--------------------------------------------------------------------+-| @topEntity (clk::Clock d 'Gated) rst = withClockReset f clk rst@ | @topEntity clk rst enable = withClockResetEnable clk rst enable f@ |-+------------------------------------------------------------------------------+--------------------------------------------------------------------+-| @data A = ... @ (and @A@ is used as state, for example in register or mealy) | @data A = ... deriving (Generic,NFDataX)@ |-+------------------------------------------------------------------------------+--------------------------------------------------------------------+-| @SystemClockReset@ | @SystemClockResetEnable@ |-+------------------------------------------------------------------------------+--------------------------------------------------------------------+-| @HiddenClockReset dom gated sync@ | @HiddenClockResetEnable dom@ |-+------------------------------------------------------------------------------+--------------------------------------------------------------------+-| @HiddenClock dom gated@ | @HiddenClock dom@ |-+------------------------------------------------------------------------------+--------------------------------------------------------------------+-| @HiddenReset dom sync@ | @HiddenReset dom@ |-+------------------------------------------------------------------------------+--------------------------------------------------------------------+-| @Clock dom gated@ | @Clock dom@ |-+------------------------------------------------------------------------------+--------------------------------------------------------------------+-| @Reset dom sync@ | @Reset dom@ |-+------------------------------------------------------------------------------+--------------------------------------------------------------------+--* @outputVerifier@ now operates on two domains. If you only need one, simply- change it to @outputVerifier'@--* For an overview of all other changes, check out <https://github.com/clash-lang/clash-compiler/blob/1.0/clash-ghc/CHANGELOG.md the changelog>--=== Examples--==== FIR filter--FIR filter in Clash 0.99:--@-module FIR where--import Clash.Prelude-import Clash.Explicit.Testbench--dotp :: SaturatingNum a- => Vec (n + 1) a- -> Vec (n + 1) a- -> a-dotp as bs = fold boundedPlus (zipWith boundedMult as bs)--fir- :: (Default a, KnownNat n, SaturatingNum a, HiddenClockReset domain gated synchronous)- => Vec (n + 1) a -> Signal domain a -> Signal domain a-fir coeffs x_t = y_t- where- y_t = dotp coeffs \<$\> bundle xs- xs = window x_t--topEntity- :: Clock System Source- -> Reset System Asynchronous- -> Signal System (Signed 16)- -> Signal System (Signed 16)-topEntity = exposeClockReset (fir (2:>3:>(-2):>8:>Nil))-{\-\# NOINLINE topEntity \#-\}--testBench :: Signal System Bool-testBench = done- where- testInput = stimuliGenerator clk rst (2:>3:>(-2):>8:>Nil)- expectedOutput = outputVerifier' clk rst (4:>12:>1:>20:>Nil)- done = expectedOutput (topEntity clk rst testInput)- clk = tbSystemClockGen (not \<$\> done)- rst = systemResetGen-@--FIR filter in Clash 1.0:--@--module FIR where--import Clash.Prelude-import Clash.Explicit.Testbench--dotp :: 'SaturatingNum' a- => 'Vec' (n + 1) a- -> 'Vec' (n + 1) a- -> a-dotp as bs = 'fold' 'boundedAdd' ('zipWith' 'boundedMul' as bs)--fir- :: ( 'HiddenClockResetEnable' dom- , 'KnownNat' n- , 'SaturatingNum' a- , 'NFDataX' a- , 'Default' a )- => 'Vec' (n + 1) a -> 'Signal' dom a -> 'Signal' dom a-fir coeffs x_t = y_t- where- y_t = dotp coeffs \<$\> 'bundle' xs- xs = 'window' x_t--topEntity- :: 'Clock' 'System'- -> 'Reset' 'System'- -> 'Enable' 'System'- -> 'Signal' 'System' ('Signed' 16)- -> 'Signal' 'System' ('Signed' 16)-topEntity = 'exposeClockResetEnable' (fir (2:>3:>(-2):>8:>'Nil'))-{\-\# NOINLINE topEntity \#-\}--testBench :: 'Signal' 'System' 'Bool'-testBench = done- where- testInput = 'stimuliGenerator' clk rst (2:>3:>(-2):>8:>'Nil')- expectedOutput = 'outputVerifier'' clk rst (4:>12:>1:>20:>'Nil')- done = expectedOutput (topEntity clk rst 'enableGen' testInput)- clk = 'tbSystemClockGen' (not \<$\> done)- rst = 'systemResetGen'-@--==== Blinker circuit--Blinker circuit in Clash 0.99:--@-{\-\# LANGUAGE NoMonoLocalBinds \#-\}--module Blinker where--import Clash.Prelude-import Clash.Promoted.Symbol-import Clash.Intel.ClockGen--type Dom50 = Dom \"System\" 20000--{\-\# ANN topEntity- (Synthesize- { t_name = \"blinker\"- , t_inputs = [ PortName \"CLOCK_50\"- , PortName \"KEY0\"- , PortName \"KEY1\"- ]- , t_output = PortName \"LED\"- }) \#-\}-topEntity- :: Clock Dom50 Source- -> Reset Dom50 Asynchronous- -> Signal Dom50 Bit- -> Signal Dom50 (BitVector 8)-topEntity clk rst =- exposeClockReset (mealy blinkerT (1,False,0) . isRising 1) pllOut rstSync- where- (pllOut,pllStable) = altpll \@Dom50 (SSymbol \@\"altpll50\") clk rst- rstSync = resetSynchronizer pllOut (unsafeToAsyncReset pllStable)--blinkerT (leds,mode,cntr) key1R = ((leds',mode',cntr'),leds)- where- -- clock frequency = 50e6 (50 MHz)- -- led update rate = 333e-3 (every 333ms)- cnt_max = 16650000 -- 50e6 * 333e-3-- cntr' | cntr == cnt_max = 0- | otherwise = cntr + 1-- mode' | key1R = not mode- | otherwise = mode-- leds' | cntr == 0 = if mode then complement leds- else rotateL leds 1- | otherwise = leds-@--Blinker in Clash 1.0:--@-module Blinker where--import "Clash.Signal"-import "Clash.Prelude"-import "Clash.Intel.ClockGen"--'createDomain' vSystem{vName=\"DomInput\", vPeriod=20000}-'createDomain' vSystem{vName=\"Dom100\", vPeriod=10000}--topEntity- :: Clock DomInput- -> Signal DomInput Bool- -> Signal Dom100 Bit- -> Signal Dom100 (BitVector 8)-topEntity clk rst =- 'exposeClockResetEnable' ('mealy' blinkerT (1,False,0) . Clash.Prelude.isRising 1) pllOut rstSync 'enableGen'- where- (pllOut,pllStable) = 'Clash.Intel.ClockGen.altpll' \@Dom100 (SSymbol \@\"altpll100\") clk ('unsafeFromActiveLow' rst)- rstSync = 'Clash.Signal.resetSynchronizer' pllOut ('unsafeFromActiveLow' pllStable)--blinkerT (leds,mode,cntr) key1R = ((leds',mode',cntr'),leds)- where- -- clock frequency = 100e6 (100 MHz)- -- led update rate = 333e-3 (every 333ms)- cnt_max = 'maxBound' :: ('Index' 33300000) -- 100e6 * 333e-3-- cntr' | cntr == cnt_max = 0- | otherwise = cntr + 1-- mode' | key1R = not mode- | otherwise = mode-- leds' | cntr == 0 = if mode then complement leds- else rotateL leds 1- | otherwise = leds-@+ 2021-2025, QBayLogic B.V.+ 2022 , LUMI GUIDE FIETSDETECTIE B.V.+ 2023 , Alex Mason++Licence : Creative Commons 4.0 (CC BY 4.0) (https://creativecommons.org/licenses/by/4.0/)+Maintainer: QBayLogic B.V. <devops@qbaylogic.com>+-}++module Clash.Tutorial (+ -- * The content of this page has been moved+ -- $moved+ )+where++{- $moved+The content of this page has been moved:++* The tutorial can now be found at: https://docs.clash-lang.org/tutorial/+* Compiler user guide material can now be found at: https://docs.clash-lang.org/compiler-user-guide/+ -}
src/Clash/XException.hs view
@@ -101,7 +101,7 @@ -- out with an exception. errorX :: HasCallStack => String -> a errorX msg = throw (XException ("X: " ++ msg ++ "\n" ++ prettyCallStack callStack))-{-# NOINLINE errorX #-}+{-# OPAQUE errorX #-} {-# ANN errorX hasBlackBox #-} -- | Convert 'XException' to 'ErrorCall'@@ -148,14 +148,13 @@ -- X: QQ -- CallStack (from HasCallStack): -- errorX, called at ...--- <BLANKLINE>+-- ... xToErrorCtx :: String -> a -> a xToErrorCtx ctx a = unsafeDupablePerformIO (catch (evaluate a >> return a) (\(XException msg) -> throw (ErrorCall (unlines [ctx,msg]))))--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE xToErrorCtx #-}+{-# OPAQUE xToErrorCtx #-} -- | Convert 'XException' to 'ErrorCall' --@@ -209,7 +208,7 @@ -- X: QQ -- CallStack (from HasCallStack): -- errorX, called at ...--- <BLANKLINE>+-- ... xToError :: HasCallStack => a -> a xToError = xToErrorCtx (prettyCallStack callStack) {-# INLINE xToError #-}@@ -225,8 +224,7 @@ seqX :: a -> b -> b seqX a b = unsafeDupablePerformIO (catch (evaluate a >> return b) (\(XException _) -> return b))--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE seqX #-}+{-# OPAQUE seqX #-} {-# ANN seqX hasBlackBox #-} infixr 0 `seqX` @@ -242,8 +240,7 @@ [ Handler (\(XException _) -> return b) , Handler (\(ErrorCall _) -> return b) ])--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE seqErrorX #-}+{-# OPAQUE seqErrorX #-} {-# ANN seqErrorX hasBlackBox #-} infixr 0 `seqErrorX` @@ -262,8 +259,7 @@ -- uses 'Clash.Netlist.BlackBox.Types.RenderVoid' hwSeqX :: a -> b -> b hwSeqX = seqX--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE hwSeqX #-}+{-# OPAQUE hwSeqX #-} {-# ANN hwSeqX hasBlackBox #-} infixr 0 `hwSeqX` @@ -336,8 +332,7 @@ (catch (evaluate (rnf a) >> return (Right a)) (\(XException msg) -> evaluate (rnfX a) >> return (Left msg)))--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE hasX #-}+{-# OPAQUE hasX #-} -- | Evaluate a value to WHNF, returning @'Left' msg@ if is a 'XException'. --@@ -352,8 +347,7 @@ (catch (evaluate a >> return (Right a)) (\(XException msg) -> return (Left msg)))--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE isX #-}+{-# OPAQUE isX #-} -- | Like the 'Show' class, but values that normally throw an 'XException' are -- converted to @undefined@, instead of error'ing out with an exception.@@ -466,6 +460,9 @@ instance ShowX Word64 where showsPrecX = showsPrecXWith showsPrec +instance ShowX CUShort where+ showsPrecX = showsPrecXWith showsPrec+ instance ShowX a => ShowX (Maybe a) instance ShowX a => ShowX (Ratio a) where@@ -488,8 +485,7 @@ -- second. Does not propagate 'XException's. deepseqX :: NFDataX a => a -> b -> b deepseqX a b = rnfX a `seq` b--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE deepseqX #-}+{-# OPAQUE deepseqX #-} {-# ANN deepseqX hasBlackBox #-} infixr 0 `deepseqX` @@ -735,13 +731,6 @@ instance NFDataX a => NFDataX (SG.Sum a) instance NFDataX a => NFDataX (M.First a) instance NFDataX a => NFDataX (M.Last a)---- Sg.Option will be removed in 9.2. We can't locally disable deprecation--- warnings (i.e., for this instance only) so we're prematurely removing it--- instead.-#if __GLASGOW_HASKELL__ < 900-instance NFDataX a => NFDataX (SG.Option a)-#endif -- | __NB__: The documentation only shows instances up to /3/-tuples. By -- default, instances up to and including /12/-tuples will exist. If the flag
src/Clash/XException.hs-boot view
@@ -1,13 +1,14 @@ module Clash.XException where +import Data.Kind (Type) import GHC.Stack (HasCallStack) isX :: a -> Either String a -class ShowX a+class ShowX (a :: Type) showsPrecX :: ShowX a => Int -> a -> ShowS -class NFDataX a+class NFDataX (a :: Type) deepErrorX :: NFDataX a => HasCallStack => String -> a hasUndefined :: NFDataX a => a -> Bool rnfX :: NFDataX a => a -> ()
src/Clash/XException/MaybeX.hs view
@@ -32,9 +32,6 @@ import Prelude -#if !MIN_VERSION_base(4,18,0)-import Control.Applicative-#endif import Control.DeepSeq (NFData) import Control.Exception (throw)
src/Clash/Xilinx/ClockGen.hs view
@@ -338,8 +338,7 @@ Reset domIn -> t unsafeClockWizard = clocks--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE unsafeClockWizard #-}+{-# OPAQUE unsafeClockWizard #-} {-# ANN unsafeClockWizard hasBlackBox #-} -- | Instantiate a Xilinx MMCM clock generator corresponding to the Xilinx@@ -390,6 +389,5 @@ Reset domIn -> t unsafeClockWizardDifferential (DiffClock clk _) = clocks clk--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE unsafeClockWizardDifferential #-}+{-# OPAQUE unsafeClockWizardDifferential #-} {-# ANN unsafeClockWizardDifferential hasBlackBox #-}
src/Clash/Xilinx/DDR.hs view
@@ -1,8 +1,7 @@ {-|-Copyright : (C) 2017 , Google Inc,- 2025 , QBayLogic B.V.,+Copyright : (C) 2017, Google Inc License : BSD2 (see the file LICENSE)-Maintainer : QBayLogic B.V. <devops@qbaylogic.com>+Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com> DDR primitives for Xilinx FPGAs @@ -22,9 +21,13 @@ module Clash.Xilinx.DDR ( iddr , oddr+ -- * Internal+ , iddr#+ , oddr# ) where +import Data.Bifunctor import GHC.Stack (HasCallStack, withFrozenCallStack) import Clash.Annotations.Primitive (hasBlackBox)@@ -40,43 +43,41 @@ -- edge and @o1@ is the data clocked in on the /rising/ edge, and @o0@ comes -- before @o1@ in time. ----- __NB__: This primitive only supports rising edges as the active edge. Trying--- to instantiate this function in a domain where falling edges are the active--- edge will lead to a HDL generation or Haskell simulation error.+-- __NB__: This primitive only supports rising edges as the active edge. iddr- :: forall fast fPeriod edge reset init polarity slow m- . ( HasCallStack- , KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity)- , KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) edge reset init polarity)- , KnownNat m )- => Clock slow- -> Reset slow- -> Enable slow- -> Signal fast (BitVector m)+ :: forall a dom domDDR+ . HasCallStack+ => KnownDomain dom+ => KnownDomain domDDR+ => DomainPeriod dom ~ (2 * DomainPeriod domDDR)+ => DomainActiveEdge dom ~ 'Rising+ => BitPack a+ => Clock dom+ -> Reset dom+ -> Enable dom+ -> Signal domDDR a -- ^ DDR input signal- -> Signal slow ((BitVector m),(BitVector m))+ -> Signal dom (a, a) -- ^ Normal speed output pair @(o0, o1)@-iddr =- case activeEdge @slow of- SRising ->- withFrozenCallStack iddr#- SFalling ->- clashCompileError- "iddr: Primitive only supports rising active edge"+iddr clk rst en =+ fmap (bimap unpack unpack) . withFrozenCallStack (iddr# clk rst en) .+ fmap pack iddr#- :: ( HasCallStack- , KnownConfiguration fast ('DomainConfiguration fast fPeriod 'Rising reset init polarity)- , KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) 'Rising reset init polarity)- , KnownNat m )- => Clock slow- -> Reset slow- -> Enable slow- -> Signal fast (BitVector m)- -> Signal slow ((BitVector m),(BitVector m))+ :: forall n dom domDDR+ . HasCallStack+ => KnownDomain dom+ => KnownDomain domDDR+ => DomainPeriod dom ~ (2 * DomainPeriod domDDR)+ => DomainActiveEdge dom ~ 'Rising+ => KnownNat n+ => Clock dom+ -> Reset dom+ -> Enable dom+ -> Signal domDDR (BitVector n)+ -> Signal dom (BitVector n, BitVector n) iddr# clk rst en = withFrozenCallStack ddrIn# clk rst en 0 0 0--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE iddr# #-}+{-# OPAQUE iddr# #-} {-# ANN iddr# hasBlackBox #-} -- | Xilinx specific variant of 'ddrOut' implemented using the Xilinx ODDR@@ -88,40 +89,40 @@ -- edge and @i1@ is the data clocked out on the /falling/ edge, and @i0@ comes -- before @i1@ in time. ----- __NB__: This primitive only supports rising edges as the active edge. Trying--- to instantiate this function in a domain where falling edges are the active--- edge will lead to a HDL generation or Haskell simulation error.+-- __NB__: This primitive only supports rising edges as the active edge. oddr- :: forall fast fPeriod edge reset init polarity slow m- . ( KnownConfiguration fast ('DomainConfiguration fast fPeriod edge reset init polarity)- , KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) edge reset init polarity)- , KnownNat m )- => Clock slow- -> Reset slow- -> Enable slow- -> Signal slow (BitVector m, BitVector m)+ :: forall a dom domDDR+ . HasCallStack+ => KnownDomain dom+ => KnownDomain domDDR+ => DomainPeriod dom ~ (2 * DomainPeriod domDDR)+ => DomainActiveEdge dom ~ 'Rising+ => BitPack a+ => Clock dom+ -> Reset dom+ -> Enable dom+ -> Signal dom (a, a) -- ^ Normal speed input pair @(i0, i1)@- -> Signal fast (BitVector m)+ -> Signal domDDR a -- ^ DDR output signal oddr clk rst en =- case activeEdge @slow of- SRising ->- uncurry (withFrozenCallStack oddr# clk rst en) . unbundle- SFalling ->- clashCompileError- "oddr: Primitive only supports rising active edge"+ fmap unpack . uncurry (withFrozenCallStack oddr# clk rst en) . unbundle .+ fmap (bimap pack pack) oddr#- :: ( KnownConfiguration fast ('DomainConfiguration fast fPeriod 'Rising reset init polarity)- , KnownConfiguration slow ('DomainConfiguration slow (2*fPeriod) 'Rising reset init polarity)- , KnownNat m )- => Clock slow- -> Reset slow- -> Enable slow- -> Signal slow (BitVector m)- -> Signal slow (BitVector m)- -> Signal fast (BitVector m)+ :: forall n dom domDDR+ . HasCallStack+ => KnownDomain dom+ => KnownDomain domDDR+ => DomainPeriod dom ~ (2 * DomainPeriod domDDR)+ => DomainActiveEdge dom ~ 'Rising+ => KnownNat n+ => Clock dom+ -> Reset dom+ -> Enable dom+ -> Signal dom (BitVector n)+ -> Signal dom (BitVector n)+ -> Signal domDDR (BitVector n) oddr# clk rst en = ddrOut# clk rst en 0--- See: https://github.com/clash-lang/clash-compiler/pull/2511-{-# CLASH_OPAQUE oddr# #-}+{-# OPAQUE oddr# #-} {-# ANN oddr# hasBlackBox #-}
src/Language/Haskell/TH/Compat.hs view
@@ -6,27 +6,14 @@ -- | Compatibility helper to create TySynInstD mkTySynInstD :: Name -> [Type] -> Type -> Dec mkTySynInstD tyConNm tyArgs rhs =-#if MIN_VERSION_template_haskell(2,15,0) TySynInstD (TySynEqn Nothing (foldl AppT (ConT tyConNm) tyArgs) rhs)-#else- TySynInstD tyConNm- (TySynEqn tyArgs- rhs)-#endif -- | Compatibility helper to create (total) tuple expressions mkTupE :: [Exp] -> Exp mkTupE = TupE-#if MIN_VERSION_template_haskell(2,16,0) . map Just-#endif -#if MIN_VERSION_template_haskell(2,17,0) liftTypedFromUntyped :: (Lift a, Quote m) => a -> Code m a liftTypedFromUntyped = unsafeCodeCoerce . lift-#elif MIN_VERSION_template_haskell(2,16,0)-liftTypedFromUntyped :: Lift a => a -> Q (TExp a)-liftTypedFromUntyped = unsafeTExpCoerce . lift-#endif
tests/Clash/Tests/BitVector.hs view
@@ -23,13 +23,14 @@ import qualified Test.Tasty.Hedgehog.Extra as H import qualified Test.Tasty.QuickCheck as Q -#if !MIN_VERSION_base(4,18,0)-import Control.Applicative (liftA2)-#endif+import Data.Bits (Bits(shiftR))+ import Clash.Prelude- (Bit, high, low, bitPattern, type (<=), type (-), natToInteger, msb, bLit, hLit, oLit)+ (Bit, high, low, bitPattern, type (<=), type (-), natToInteger, msb, bLit, hLit, oLit, rotateL, rotateR) import Clash.Sized.Internal.BitVector (BitVector (..)) +import Test.Tasty.HUnit.Extra (expectException)+ import Clash.Tests.SizedNum -- | Generates a BitVector either with the MSB set or not, and checks whether@@ -100,6 +101,10 @@ [ testCase "maxBound :: BitVector 0" $ maxBound @(BitVector 0) @?= 0 , testCase "minBound :: BitVector 0" $ minBound @(BitVector 0) @?= 0 ]+ , testGroup "Rotate"+ [ testCase "rotateL BitVector 0" $ rotateL @(BitVector 0) 0 2 @?= 0+ , testCase "rotateR BitVector 0" $ rotateR @(BitVector 0) 0 2 @?= 0+ ] , testGroup "MSB" [ H.testPropertyXXX "msb @(BitVector 1)" (msbTest @1) , H.testPropertyXXX "msb @(BitVector 2)" (msbTest @2)@@ -108,6 +113,18 @@ , H.testPropertyXXX "msb @(BitVector 64)" (msbTest @64) , H.testPropertyXXX "msb @(BitVector 128)" (msbTest @128) , H.testPropertyXXX "msb @(BitVector 129)" (msbTest @129)+ ]+ , testGroup "shiftR"+ [ testCase "shiftR 5 0 == 5" $+ shiftR (5 :: BitVector 8) 0 @?= 5+ , testCase "returns 0 when n == bitSize" $+ shiftR (0xFF :: BitVector 8) 8 @?= 0+ , testCase "returns 0 when n > bitSize" $+ shiftR (0xFF :: BitVector 8) (8 + 1) @?= 0+ , testCase "returns 0 when n >> bitSize" $+ shiftR (0xFF :: BitVector 8) (8 + 1000) @?= 0+ , testCase "undefined when n < 0" $+ expectException (shiftR (1 :: BitVector 8) (-1)) ] , testGroup "show" [ testCase "show0" $ show @(BitVector 0) 0b0 @?= "0"
tests/Clash/Tests/BlockRam.hs view
@@ -14,7 +14,7 @@ :: (HiddenClockResetEnable dom) => Signal dom (Unsigned 4) -> Signal dom (Unsigned 8)-readRam addr = mux (register False $ addr .<. 8) ram (pure 0xff)+readRam addr = mux (register False $ addr .< 8) ram (pure 0xff) where ram = blockRam1 NoClearOnReset (SNat @8) 0 addr (pure Nothing)
+ tests/Clash/Tests/Index.hs view
@@ -0,0 +1,25 @@+module Clash.Tests.Index (tests) where++import Data.Bits (Bits(shiftR))+import Test.Tasty+import Test.Tasty.HUnit++import Clash.Sized.Internal.Index (Index)++import Test.Tasty.HUnit.Extra (expectException)++tests :: TestTree+tests = testGroup "Index"+ [ testGroup "shiftR"+ [ testCase "shiftR 5 0 == 5" $+ shiftR (5 :: Index 128) 0 @?= 5+ , testCase "returns 0 when n == bitSize" $+ shiftR (127 :: Index 128) 7 @?= 0+ , testCase "returns 0 when n > bitSize" $+ shiftR (127 :: Index 128) (7 + 1) @?= 0+ , testCase "returns 0 when n >> bitSize" $+ shiftR (127 :: Index 128) (7 + 1000) @?= 0+ , testCase "undefined when n < 0" $+ expectException (shiftR (1 :: Index 128) (-1))+ ]+ ]
+ tests/Clash/Tests/Laws/Num.hs view
@@ -0,0 +1,51 @@+module Clash.Tests.Laws.Num (tests) where++import Clash.Tests.Laws.SaturatingNum+ ( genBoundedIntegral+ , genUnsigned+ )++import Test.Tasty+import Test.Tasty.Hedgehog.Extra++import Clash.Sized.BitVector (Bit, BitVector)++import Control.DeepSeq (NFData)+import GHC.TypeLits (KnownNat)++import Hedgehog++genBit :: Gen Bit+genBit = genBoundedIntegral++genBitVector :: forall n. KnownNat n => Gen (BitVector n)+genBitVector = genBoundedIntegral++additiveInverse :: (Num a, Show a, Eq a) => Gen a -> TestTree+additiveInverse genA = testPropertyXXX "x + negate x == 0" $ property $ do+ a <- forAll genA+ a + negate a === 0++testAdditiveInverse :: (NFData a, Ord a, Show a, Eq a, Num a) => String -> Gen a -> TestTree+testAdditiveInverse typeName genA =+ testGroup typeName [testGroup "additiveInverse" [additiveInverse genA]]++tests :: TestTree+tests = testGroup "Num"+ [ testAdditiveInverse "Bit" genBit++ , testAdditiveInverse "Unsigned 0" (genUnsigned @0)+ , testAdditiveInverse "Unsigned 1" (genUnsigned @1)+ , testAdditiveInverse "Unsigned 32" (genUnsigned @32)+ , testAdditiveInverse "Unsigned 127" (genUnsigned @127)+ , testAdditiveInverse "Unsigned 128" (genUnsigned @128)++ , testAdditiveInverse "BitVector 0" (genBitVector @0)+ , testAdditiveInverse "BitVector 1" (genBitVector @1)+ , testAdditiveInverse "BitVector 32" (genBitVector @32)+ , testAdditiveInverse "BitVector 127" (genBitVector @127)+ , testAdditiveInverse "BitVector 128" (genBitVector @128)++ -- TODO: Index, Signed, UFixed, SFixed. See discussion in+ -- https://github.com/clash-lang/clash-compiler/issues/3015+ ]
tests/Clash/Tests/Laws/SaturatingNum.hs view
@@ -4,7 +4,16 @@ {-# OPTIONS_GHC -fplugin=GHC.TypeLits.Normalise #-} {-# OPTIONS_GHC -fplugin=GHC.TypeLits.KnownNat.Solver #-} -module Clash.Tests.Laws.SaturatingNum (tests) where+module Clash.Tests.Laws.SaturatingNum+ ( tests++ , genBoundedIntegral+ , genIndex+ , genSFixed+ , genSigned+ , genUFixed+ , genUnsigned+ ) where import Test.Tasty import Test.Tasty.Hedgehog.Extra
+ tests/Clash/Tests/MaybeNumConvert.hs view
@@ -0,0 +1,350 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# OPTIONS_GHC -fplugin=GHC.TypeLits.Extra.Solver #-}+{-# OPTIONS_GHC -fplugin=GHC.TypeLits.KnownNat.Solver #-}+{-# OPTIONS_GHC -fplugin=GHC.TypeLits.Normalise #-}++{- |+Copyright : (C) 2025 , Martijn Bastiaan+License : BSD2 (see the file LICENSE)+Maintainer : QBayLogic B.V. <devops@qbaylogic.com>++Test generation of 'MaybeNumConvert' instances:++> for a in ["Index", "Unsigned", "Signed", "BitVector"]:+> for b in ["Index", "Unsigned", "Signed", "BitVector"]:+> ia_max = "indexMax" if a == "Index" else "otherMax"+> ib_max = "indexMax" if b == "Index" else "otherMax"+> n = "(n + 1)" if a == "Index" else "n"+> m = "(m + 1)" if b == "Index" else "m"+> print(f"""case_maybeConvert{a}{b} :: Assertion+> case_maybeConvert{a}{b} =+> forM_ [0 .. {ia_max}] $ \\n ->+> forM_ [0 .. {ib_max}] $ \\m ->+> withSomeSNat n $ \(SNat :: SNat n) ->+> withSomeSNat m $ \(SNat :: SNat m) ->+> forM_ [minBound .. maxBound] $ \(i :: {a} {n}) -> do+> assertBool (show (n, m, i)) (maybeConvertLaw1 (Proxy @({b} {m})) i)+> assertBool (show (n, m, i)) (maybeConvertLaw2 (Proxy @({b} {m})) i)+> assertBool (show (n, m, i)) (maybeConvertLaw3 (Proxy @({b} {m})) i)+> assertBool (show (n, m, i)) (maybeConvertLaw4 (Proxy @({b} {m})) i)+> """)+-}+module Clash.Tests.MaybeNumConvert where++import Control.Monad (forM_)+import Data.Data (Proxy (..))+import Data.Int (Int64)+import Data.Maybe (fromMaybe, isJust)+import Data.Word (Word64)+import GHC.TypeNats (someNatVal)+import Test.Tasty (TestTree, defaultMain)+import Test.Tasty.HUnit (Assertion, assertBool, testCase)+import Test.Tasty.TH (testGroupGenerator)++import Clash.Prelude hiding (someNatVal, withSomeSNat)++import qualified Data.List as L++main :: IO ()+main = defaultMain tests++tests :: TestTree+tests = $(testGroupGenerator)++-- Tests for maybeNumConvert (conversions that can fail)++case_MaybeInt64Word64 :: Assertion+case_MaybeInt64Word64 = do+ -- Successful conversions (non-negative values)+ assertBool "0" $ maybeNumConvert (0 :: Int64) == Just (0 :: Word64)+ assertBool "1" $ maybeNumConvert (1 :: Int64) == Just (1 :: Word64)+ assertBool "42" $ maybeNumConvert (42 :: Int64) == Just (42 :: Word64)+ assertBool "maxBound" $ maybeNumConvert (maxBound :: Int64) == Just (9223372036854775807 :: Word64)+ -- Failed conversions (negative values)+ assertBool "-1" $ maybeNumConvert (-1 :: Int64) == (Nothing :: Maybe Word64)+ assertBool "-42" $ maybeNumConvert (-42 :: Int64) == (Nothing :: Maybe Word64)+ assertBool "minBound" $ maybeNumConvert (minBound :: Int64) == (Nothing :: Maybe Word64)++case_MaybeWord64Unsigned32 :: Assertion+case_MaybeWord64Unsigned32 = do+ -- Successful conversions (small values)+ assertBool "0" $ maybeNumConvert (0 :: Word64) == Just (0 :: Unsigned 32)+ assertBool "1" $ maybeNumConvert (1 :: Word64) == Just (1 :: Unsigned 32)+ assertBool "42" $ maybeNumConvert (42 :: Word64) == Just (42 :: Unsigned 32)+ assertBool "maxBound32" $ maybeNumConvert (4294967295 :: Word64) == Just (maxBound :: Unsigned 32)+ -- Failed conversions (values too large)+ assertBool "overflow1" $ maybeNumConvert (4294967296 :: Word64) == (Nothing :: Maybe (Unsigned 32))+ assertBool "overflow2" $ maybeNumConvert (5000000000 :: Word64) == (Nothing :: Maybe (Unsigned 32))+ assertBool "maxBound64" $ maybeNumConvert (maxBound :: Word64) == (Nothing :: Maybe (Unsigned 32))++withSomeSNat :: Natural -> (forall (n :: Nat). SNat n -> r) -> r+withSomeSNat n f = case someNatVal n of+ SomeNat (_ :: Proxy n) -> f (SNat @n)++maybeConvertLaw1 ::+ forall a b.+ (Eq a, MaybeNumConvert a b, MaybeNumConvert b a) =>+ Proxy b ->+ a ->+ Bool+maybeConvertLaw1 Proxy x =+ x == fromMaybe x (maybeNumConvert @_ @b x >>= maybeNumConvert)++maybeConvertLaw2 ::+ forall a b.+ (MaybeNumConvert a b, MaybeNumConvert b a, Integral b, Integral a) =>+ Proxy b ->+ a ->+ Bool+maybeConvertLaw2 Proxy x =+ toInteger x == fromMaybe (toInteger x) (toInteger <$> maybeNumConvert @_ @b x)++maybeConvertLaw3 ::+ forall a b.+ (MaybeNumConvert a b, MaybeNumConvert b a, Integral b, Integral a) =>+ Proxy b ->+ a ->+ Bool+maybeConvertLaw3 Proxy x =+ isJust (maybeNumConvert @_ @b x) `implies` isJust (maybeNumConvert @_ @a =<< maybeNumConvert @_ @b x)+ where+ implies :: Bool -> Bool -> Bool+ implies True False = False+ implies _ _ = True++maybeConvertLaw4 ::+ forall a b.+ (MaybeNumConvert a b, MaybeNumConvert b a, Integral b, Integral a, Bounded b, Bounded a) =>+ Proxy b ->+ a ->+ Bool+maybeConvertLaw4 Proxy x =+ isJust (maybeNumConvert @_ @b x) == (i x >= i (minBound @b) && i x <= i (maxBound @b))+ where+ i :: (Integral c) => c -> Integer+ i = toInteger++-- | Checks whether an 'XException' in, means an 'XException' out+convertXException :: forall a b. (MaybeNumConvert a b) => Proxy a -> Proxy b -> Bool+convertXException _ _ = case isX $ maybeNumConvert @a @b (errorX "BOO" :: a) of+ Left s -> "BOO" `L.isInfixOf` s+ Right _ -> False++indexMax :: Natural+indexMax = 128++otherMax :: Natural+otherMax = 8++case_maybeConvertIndexIndex :: Assertion+case_maybeConvertIndexIndex =+ forM_ [0 .. indexMax] $ \n ->+ forM_ [0 .. indexMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) -> do+ assertBool (show (n, m)) (convertXException (Proxy @(Index (n + 1))) (Proxy @(Index (m + 1))))+ forM_ [minBound .. maxBound] $ \(i :: Index (n + 1)) -> do+ assertBool (show (n, m, i)) (maybeConvertLaw1 (Proxy @(Index (m + 1))) i)+ assertBool (show (n, m, i)) (maybeConvertLaw2 (Proxy @(Index (m + 1))) i)+ assertBool (show (n, m, i)) (maybeConvertLaw3 (Proxy @(Index (m + 1))) i)+ assertBool (show (n, m, i)) (maybeConvertLaw4 (Proxy @(Index (m + 1))) i)++case_maybeConvertIndexUnsigned :: Assertion+case_maybeConvertIndexUnsigned =+ forM_ [0 .. indexMax] $ \n ->+ forM_ [0 .. otherMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) -> do+ assertBool (show (n, m)) (convertXException (Proxy @(Index (n + 1))) (Proxy @(Unsigned m)))+ forM_ [minBound .. maxBound] $ \(i :: Index (n + 1)) -> do+ assertBool (show (n, m, i)) (maybeConvertLaw1 (Proxy @(Unsigned m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw2 (Proxy @(Unsigned m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw3 (Proxy @(Unsigned m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw4 (Proxy @(Unsigned m)) i)++case_maybeConvertIndexSigned :: Assertion+case_maybeConvertIndexSigned =+ forM_ [0 .. indexMax] $ \n ->+ forM_ [0 .. otherMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) -> do+ assertBool (show (n, m)) (convertXException (Proxy @(Index (n + 1))) (Proxy @(Signed m)))+ forM_ [minBound .. maxBound] $ \(i :: Index (n + 1)) -> do+ assertBool (show (n, m, i)) (maybeConvertLaw1 (Proxy @(Signed m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw2 (Proxy @(Signed m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw3 (Proxy @(Signed m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw4 (Proxy @(Signed m)) i)++case_maybeConvertIndexBitVector :: Assertion+case_maybeConvertIndexBitVector =+ forM_ [0 .. indexMax] $ \n ->+ forM_ [0 .. otherMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) -> do+ assertBool (show (n, m)) (convertXException (Proxy @(Index (n + 1))) (Proxy @(BitVector m)))+ forM_ [minBound .. maxBound] $ \(i :: Index (n + 1)) -> do+ assertBool (show (n, m, i)) (maybeConvertLaw1 (Proxy @(BitVector m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw2 (Proxy @(BitVector m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw3 (Proxy @(BitVector m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw4 (Proxy @(BitVector m)) i)++case_maybeConvertUnsignedIndex :: Assertion+case_maybeConvertUnsignedIndex =+ forM_ [0 .. otherMax] $ \n ->+ forM_ [0 .. indexMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) -> do+ assertBool (show (n, m)) (convertXException (Proxy @(Unsigned n)) (Proxy @(Index (m + 1))))+ forM_ [minBound .. maxBound] $ \(i :: Unsigned n) -> do+ assertBool (show (n, m, i)) (maybeConvertLaw1 (Proxy @(Index (m + 1))) i)+ assertBool (show (n, m, i)) (maybeConvertLaw2 (Proxy @(Index (m + 1))) i)+ assertBool (show (n, m, i)) (maybeConvertLaw3 (Proxy @(Index (m + 1))) i)+ assertBool (show (n, m, i)) (maybeConvertLaw4 (Proxy @(Index (m + 1))) i)++case_maybeConvertUnsignedUnsigned :: Assertion+case_maybeConvertUnsignedUnsigned =+ forM_ [0 .. otherMax] $ \n ->+ forM_ [0 .. otherMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) -> do+ assertBool (show (n, m)) (convertXException (Proxy @(Unsigned n)) (Proxy @(Unsigned m)))+ forM_ [minBound .. maxBound] $ \(i :: Unsigned n) -> do+ assertBool (show (n, m, i)) (maybeConvertLaw1 (Proxy @(Unsigned m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw2 (Proxy @(Unsigned m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw3 (Proxy @(Unsigned m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw4 (Proxy @(Unsigned m)) i)++case_maybeConvertUnsignedSigned :: Assertion+case_maybeConvertUnsignedSigned =+ forM_ [0 .. otherMax] $ \n ->+ forM_ [0 .. otherMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) -> do+ assertBool (show (n, m)) (convertXException (Proxy @(Unsigned n)) (Proxy @(Signed m)))+ forM_ [minBound .. maxBound] $ \(i :: Unsigned n) -> do+ assertBool (show (n, m, i)) (maybeConvertLaw1 (Proxy @(Signed m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw2 (Proxy @(Signed m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw3 (Proxy @(Signed m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw4 (Proxy @(Signed m)) i)++case_maybeConvertUnsignedBitVector :: Assertion+case_maybeConvertUnsignedBitVector =+ forM_ [0 .. otherMax] $ \n ->+ forM_ [0 .. otherMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) -> do+ assertBool (show (n, m)) (convertXException (Proxy @(Unsigned n)) (Proxy @(BitVector m)))+ forM_ [minBound .. maxBound] $ \(i :: Unsigned n) -> do+ assertBool (show (n, m, i)) (maybeConvertLaw1 (Proxy @(BitVector m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw2 (Proxy @(BitVector m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw3 (Proxy @(BitVector m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw4 (Proxy @(BitVector m)) i)++case_maybeConvertSignedIndex :: Assertion+case_maybeConvertSignedIndex =+ forM_ [0 .. otherMax] $ \n ->+ forM_ [0 .. indexMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) -> do+ assertBool (show (n, m)) (convertXException (Proxy @(Signed n)) (Proxy @(Index (m + 1))))+ forM_ [minBound .. maxBound] $ \(i :: Signed n) -> do+ assertBool (show (n, m, i)) (maybeConvertLaw1 (Proxy @(Index (m + 1))) i)+ assertBool (show (n, m, i)) (maybeConvertLaw2 (Proxy @(Index (m + 1))) i)+ assertBool (show (n, m, i)) (maybeConvertLaw3 (Proxy @(Index (m + 1))) i)+ assertBool (show (n, m, i)) (maybeConvertLaw4 (Proxy @(Index (m + 1))) i)++case_maybeConvertSignedUnsigned :: Assertion+case_maybeConvertSignedUnsigned =+ forM_ [0 .. otherMax] $ \n ->+ forM_ [0 .. otherMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) -> do+ assertBool (show (n, m)) (convertXException (Proxy @(Signed n)) (Proxy @(Unsigned m)))+ forM_ [minBound .. maxBound] $ \(i :: Signed n) -> do+ assertBool (show (n, m, i)) (maybeConvertLaw1 (Proxy @(Unsigned m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw2 (Proxy @(Unsigned m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw3 (Proxy @(Unsigned m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw4 (Proxy @(Unsigned m)) i)++case_maybeConvertSignedSigned :: Assertion+case_maybeConvertSignedSigned =+ forM_ [0 .. otherMax] $ \n ->+ forM_ [0 .. otherMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) -> do+ assertBool (show (n, m)) (convertXException (Proxy @(Signed n)) (Proxy @(Signed m)))+ forM_ [minBound .. maxBound] $ \(i :: Signed n) -> do+ assertBool (show (n, m, i)) (maybeConvertLaw1 (Proxy @(Signed m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw2 (Proxy @(Signed m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw3 (Proxy @(Signed m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw4 (Proxy @(Signed m)) i)++case_maybeConvertSignedBitVector :: Assertion+case_maybeConvertSignedBitVector =+ forM_ [0 .. otherMax] $ \n ->+ forM_ [0 .. otherMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) -> do+ assertBool (show (n, m)) (convertXException (Proxy @(Signed n)) (Proxy @(BitVector m)))+ forM_ [minBound .. maxBound] $ \(i :: Signed n) -> do+ assertBool (show (n, m, i)) (maybeConvertLaw1 (Proxy @(BitVector m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw2 (Proxy @(BitVector m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw3 (Proxy @(BitVector m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw4 (Proxy @(BitVector m)) i)++case_maybeConvertBitVectorIndex :: Assertion+case_maybeConvertBitVectorIndex =+ forM_ [0 .. otherMax] $ \n ->+ forM_ [0 .. indexMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) -> do+ assertBool (show (n, m)) (convertXException (Proxy @(BitVector n)) (Proxy @(Index (m + 1))))+ forM_ [minBound .. maxBound] $ \(i :: BitVector n) -> do+ assertBool (show (n, m, i)) (maybeConvertLaw1 (Proxy @(Index (m + 1))) i)+ assertBool (show (n, m, i)) (maybeConvertLaw2 (Proxy @(Index (m + 1))) i)+ assertBool (show (n, m, i)) (maybeConvertLaw3 (Proxy @(Index (m + 1))) i)+ assertBool (show (n, m, i)) (maybeConvertLaw4 (Proxy @(Index (m + 1))) i)++case_maybeConvertBitVectorUnsigned :: Assertion+case_maybeConvertBitVectorUnsigned =+ forM_ [0 .. otherMax] $ \n ->+ forM_ [0 .. otherMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) -> do+ assertBool (show (n, m)) (convertXException (Proxy @(BitVector n)) (Proxy @(Unsigned m)))+ forM_ [minBound .. maxBound] $ \(i :: BitVector n) -> do+ assertBool (show (n, m, i)) (maybeConvertLaw1 (Proxy @(Unsigned m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw2 (Proxy @(Unsigned m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw3 (Proxy @(Unsigned m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw4 (Proxy @(Unsigned m)) i)++case_maybeConvertBitVectorSigned :: Assertion+case_maybeConvertBitVectorSigned =+ forM_ [0 .. otherMax] $ \n ->+ forM_ [0 .. otherMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) -> do+ assertBool (show (n, m)) (convertXException (Proxy @(BitVector n)) (Proxy @(Signed m)))+ forM_ [minBound .. maxBound] $ \(i :: BitVector n) -> do+ assertBool (show (n, m, i)) (maybeConvertLaw1 (Proxy @(Signed m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw2 (Proxy @(Signed m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw3 (Proxy @(Signed m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw4 (Proxy @(Signed m)) i)++case_maybeConvertBitVectorBitVector :: Assertion+case_maybeConvertBitVectorBitVector =+ forM_ [0 .. otherMax] $ \n ->+ forM_ [0 .. otherMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) -> do+ assertBool (show (n, m)) (convertXException (Proxy @(BitVector n)) (Proxy @(BitVector m)))+ forM_ [minBound .. maxBound] $ \(i :: BitVector n) -> do+ assertBool (show (n, m, i)) (maybeConvertLaw1 (Proxy @(BitVector m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw2 (Proxy @(BitVector m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw3 (Proxy @(BitVector m)) i)+ assertBool (show (n, m, i)) (maybeConvertLaw4 (Proxy @(BitVector m)) i)
tests/Clash/Tests/MaybeX.hs view
@@ -7,9 +7,6 @@ import Clash.XException (errorX) import Clash.XException.MaybeX (MaybeX(IsX, IsDefined), toMaybeX) -#if !MIN_VERSION_base(4,18,0)-import Control.Applicative (liftA2)-#endif import Test.Tasty import Test.Tasty.HUnit import Test.Tasty.TH
+ tests/Clash/Tests/NumConvert.hs view
@@ -0,0 +1,403 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# OPTIONS_GHC -fplugin=GHC.TypeLits.Extra.Solver #-}+{-# OPTIONS_GHC -fplugin=GHC.TypeLits.KnownNat.Solver #-}+{-# OPTIONS_GHC -fplugin=GHC.TypeLits.Normalise #-}++{- |+Copyright : (C) 2025 , Martijn Bastiaan+ 2025-2026, QBayLogic B.V.+License : BSD2 (see the file LICENSE)+Maintainer : QBayLogic B.V. <devops@qbaylogic.com>++Test generation of 'NumConvert' instances:++> constraints = {+> ("Index", "Index") : (False, "SNat @{n} `compareSNat` SNat @{m}"),+> ("Index", "Unsigned") : (False, "SNat @{n} `compareSNat` SNat @(2 ^ {m})"),+> ("Index", "Signed") : (True, "SNat @(CLog 2 {n} + 1) `compareSNat` SNat @{m}"),+> ("Index", "BitVector") : (False, "SNat @{n} `compareSNat` SNat @(2 ^ {m})"),+> ("Unsigned", "Index") : (False, "SNat @(2^{n}) `compareSNat` SNat @{m}"),+> ("Unsigned", "Unsigned") : (False, "SNat @{n} `compareSNat` SNat @{m}"),+> ("Unsigned", "Signed") : (True, "SNat @({n} + 1) `compareSNat` SNat @{m}"),+> ("Unsigned", "BitVector") : (False, "SNat @{n} `compareSNat` SNat @{m}"),+> ("Signed", "Signed") : (False, "SNat @{n} `compareSNat` SNat @{m}"),+> ("BitVector", "Index") : (False, "SNat @(2^{n}) `compareSNat` SNat @{m}"),+> ("BitVector", "Unsigned") : (False, "SNat @{n} `compareSNat` SNat @{m}"),+> ("BitVector", "Signed") : (True, "SNat @({n} + 1) `compareSNat` SNat @{m}"),+> ("BitVector", "BitVector") : (False, "SNat @{n} `compareSNat` SNat @{m}"),+> }+>+> for a in ["Index", "Unsigned", "Signed", "BitVector"]:+> for b in ["Index", "Unsigned", "Signed", "BitVector"]:+> ia_max = "indexMax" if a == "Index" else "otherMax"+> ib_max = "indexMax" if b == "Index" else "otherMax"+> n = "(n + 1)" if a == "Index" else "n"+> m = "(m + 1)" if b == "Index" else "m"+> if (a, b) not in constraints:+> continue+> print(f"""case_convert{a}{b} :: Assertion+> case_convert{a}{b} =+> forM_ [0 .. {ia_max}] $ \\n ->+> forM_ [0 .. {ib_max}] $ \\m ->+> withSomeSNat n $ \\(SNat :: SNat n) ->+> withSomeSNat m $ \\(SNat :: SNat m) ->+> case {constraints[(a, b)][1].format(n=n, m=m)} of+> SNatLE -> do+> assertBool (show (n, m)) (convertXException (Proxy @({a} {n})) (Proxy @({b} {m})))+> forM_ [minBound .. maxBound] $ \\(i :: {a} {n}) -> do+> assertBool (show (n, m, i)) (convertLaw1 (Proxy @({b} {m})) i)+> assertBool (show (n, m, i)) (convertLaw2 (Proxy @({b} {m})) i)+> _ | (n == 0 && m == 0 && zeroWidthSkip) -> pure ()+> _ -> assertBool (show (n, m)) (convertLaw3 (Proxy @({a} {n})) (Proxy @({b} {m})))+> where+> zeroWidthSkip = {constraints[(a, b)][0]}+> """)+-}+module Clash.Tests.NumConvert where++import Control.Monad (forM_)+import Data.Data (Proxy (..))+import Data.Int (Int16, Int32, Int64, Int8)+import Data.Maybe (isNothing)+import Data.Word (Word16, Word32, Word64, Word8)+import GHC.TypeNats (someNatVal)+import Test.Tasty (TestTree, defaultMain)+import Test.Tasty.HUnit (Assertion, assertBool, testCase)+import Test.Tasty.TH (testGroupGenerator)++import qualified Data.List as L++import Clash.Prelude hiding (someNatVal, withSomeSNat)++convertLaw1 :: forall a b. (NumConvert a b, MaybeNumConvert b a, Eq a) => Proxy b -> a -> Bool+convertLaw1 _ x = Just x == maybeNumConvert (numConvert @a @b x)++convertLaw2 :: forall a b. (NumConvert a b, Eq a, Integral b, Integral a) => Proxy b -> a -> Bool+convertLaw2 _ x = toInteger x == toInteger (numConvert @a @b x)++{- | Tightness law: this law is tested for if there is _no_ instance of+'NumConvert'. If this is the case, 'MaybeNumConvert' should at least return a 'Nothing'+once when converting the domain of @a@ to @b@. If all conversions are possible,+the constraints of the instances should be relaxed. If the domain of @a@ is+empty, this law is considered satisfied too.+-}+convertLaw3 :: forall a b. (MaybeNumConvert a b, Bounded a, Enum a) => Proxy a -> Proxy b -> Bool+convertLaw3 _ _ = L.any isNothing results+ where+ results = L.map (maybeNumConvert @a @b) [minBound ..]++-- | Checks whether an 'XException' in, means an 'XException' out+convertXException :: forall a b. (NumConvert a b) => Proxy a -> Proxy b -> Bool+convertXException _ _ = case isX $ numConvert @a @b (errorX "BOO" :: a) of+ Left s -> "BOO" `L.isInfixOf` s+ Right _ -> False++main :: IO ()+main = defaultMain tests++tests :: TestTree+tests = $(testGroupGenerator)++-- Tests for numConvert (Word-to-Word conversions)++case_Word8Word16 :: Assertion+case_Word8Word16 = do+ assertBool "0" $ numConvert (0 :: Word8) == (0 :: Word16)+ assertBool "1" $ numConvert (1 :: Word8) == (1 :: Word16)+ assertBool "42" $ numConvert (42 :: Word8) == (42 :: Word16)+ assertBool "maxBound" $ numConvert (maxBound :: Word8) == (255 :: Word16)++case_Word8Word32 :: Assertion+case_Word8Word32 = do+ assertBool "0" $ numConvert (0 :: Word8) == (0 :: Word32)+ assertBool "1" $ numConvert (1 :: Word8) == (1 :: Word32)+ assertBool "42" $ numConvert (42 :: Word8) == (42 :: Word32)+ assertBool "maxBound" $ numConvert (maxBound :: Word8) == (255 :: Word32)++case_Word16Word32 :: Assertion+case_Word16Word32 = do+ assertBool "0" $ numConvert (0 :: Word16) == (0 :: Word32)+ assertBool "1" $ numConvert (1 :: Word16) == (1 :: Word32)+ assertBool "42" $ numConvert (42 :: Word16) == (42 :: Word32)+ assertBool "maxBound" $ numConvert (maxBound :: Word16) == (65535 :: Word32)++case_Word32Word64 :: Assertion+case_Word32Word64 = do+ assertBool "0" $ numConvert (0 :: Word32) == (0 :: Word64)+ assertBool "1" $ numConvert (1 :: Word32) == (1 :: Word64)+ assertBool "42" $ numConvert (42 :: Word32) == (42 :: Word64)+ assertBool "maxBound" $ numConvert (maxBound :: Word32) == (4294967295 :: Word64)++-- Tests for numConvert (Int-to-Int conversions)++case_Int8Int16 :: Assertion+case_Int8Int16 = do+ assertBool "0" $ numConvert (0 :: Int8) == (0 :: Int16)+ assertBool "1" $ numConvert (1 :: Int8) == (1 :: Int16)+ assertBool "42" $ numConvert (42 :: Int8) == (42 :: Int16)+ assertBool "-1" $ numConvert (-1 :: Int8) == (-1 :: Int16)+ assertBool "-42" $ numConvert (-42 :: Int8) == (-42 :: Int16)+ assertBool "minBound" $ numConvert (minBound :: Int8) == (-128 :: Int16)+ assertBool "maxBound" $ numConvert (maxBound :: Int8) == (127 :: Int16)++case_Int32Int64 :: Assertion+case_Int32Int64 = do+ assertBool "0" $ numConvert (0 :: Int32) == (0 :: Int64)+ assertBool "1" $ numConvert (1 :: Int32) == (1 :: Int64)+ assertBool "42" $ numConvert (42 :: Int32) == (42 :: Int64)+ assertBool "-1" $ numConvert (-1 :: Int32) == (-1 :: Int64)+ assertBool "-42" $ numConvert (-42 :: Int32) == (-42 :: Int64)+ assertBool "minBound" $ numConvert (minBound :: Int32) == (-2147483648 :: Int64)+ assertBool "maxBound" $ numConvert (maxBound :: Int32) == (2147483647 :: Int64)++-- Tests for mixed conversions (cross Haskell/Clash boundary)++case_Word32Unsigned64 :: Assertion+case_Word32Unsigned64 = do+ assertBool "0" $ numConvert (0 :: Word32) == (0 :: Unsigned 64)+ assertBool "1" $ numConvert (1 :: Word32) == (1 :: Unsigned 64)+ assertBool "42" $ numConvert (42 :: Word32) == (42 :: Unsigned 64)+ assertBool "maxBound" $ numConvert (maxBound :: Word32) == (4294967295 :: Unsigned 64)++case_Unsigned32Word64 :: Assertion+case_Unsigned32Word64 = do+ assertBool "0" $ numConvert (0 :: Unsigned 32) == (0 :: Word64)+ assertBool "1" $ numConvert (1 :: Unsigned 32) == (1 :: Word64)+ assertBool "42" $ numConvert (42 :: Unsigned 32) == (42 :: Word64)+ assertBool "maxBound" $ numConvert (maxBound :: Unsigned 32) == (4294967295 :: Word64)++withSomeSNat :: Natural -> (forall (n :: Nat). SNat n -> r) -> r+withSomeSNat n f = case someNatVal n of+ SomeNat (_ :: Proxy n) -> f (SNat @n)++indexMax :: Natural+indexMax = 128++otherMax :: Natural+otherMax = 8++case_convertIndexIndex :: Assertion+case_convertIndexIndex =+ forM_ [0 .. indexMax] $ \n ->+ forM_ [0 .. indexMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) ->+ case SNat @(n + 1) `compareSNat` SNat @(m + 1) of+ SNatLE -> do+ assertBool (show (n, m)) (convertXException (Proxy @(Index (n + 1))) (Proxy @(Index (m + 1))))+ forM_ [minBound .. maxBound] $ \(i :: Index (n + 1)) -> do+ assertBool (show (n, m, i)) (convertLaw1 (Proxy @(Index (m + 1))) i)+ assertBool (show (n, m, i)) (convertLaw2 (Proxy @(Index (m + 1))) i)+ _ | (n == 0 && m == 0 && zeroWidthSkip) -> pure ()+ _ -> assertBool (show (n, m)) (convertLaw3 (Proxy @(Index (n + 1))) (Proxy @(Index (m + 1))))+ where+ zeroWidthSkip = False++case_convertIndexUnsigned :: Assertion+case_convertIndexUnsigned =+ forM_ [0 .. indexMax] $ \n ->+ forM_ [0 .. otherMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) ->+ case SNat @(n + 1) `compareSNat` SNat @(2 ^ m) of+ SNatLE -> do+ assertBool (show (n, m)) (convertXException (Proxy @(Index (n + 1))) (Proxy @(Unsigned m)))+ forM_ [minBound .. maxBound] $ \(i :: Index (n + 1)) -> do+ assertBool (show (n, m, i)) (convertLaw1 (Proxy @(Unsigned m)) i)+ assertBool (show (n, m, i)) (convertLaw2 (Proxy @(Unsigned m)) i)+ _ | (n == 0 && m == 0 && zeroWidthSkip) -> pure ()+ _ -> assertBool (show (n, m)) (convertLaw3 (Proxy @(Index (n + 1))) (Proxy @(Unsigned m)))+ where+ zeroWidthSkip = False++case_convertIndexSigned :: Assertion+case_convertIndexSigned =+ forM_ [0 .. indexMax] $ \n ->+ forM_ [0 .. otherMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) ->+ case SNat @(CLogWZ 2 (n + 1) 0 + 1) `compareSNat` SNat @m of+ SNatLE -> do+ assertBool (show (n, m)) (convertXException (Proxy @(Index (n + 1))) (Proxy @(Signed m)))+ forM_ [minBound .. maxBound] $ \(i :: Index (n + 1)) -> do+ assertBool (show (n, m, i)) (convertLaw1 (Proxy @(Signed m)) i)+ assertBool (show (n, m, i)) (convertLaw2 (Proxy @(Signed m)) i)+ _ | (n == 0 && m == 0 && zeroWidthSkip) -> pure ()+ _ -> assertBool (show (n, m)) (convertLaw3 (Proxy @(Index (n + 1))) (Proxy @(Signed m)))+ where+ zeroWidthSkip = True++case_convertIndexBitVector :: Assertion+case_convertIndexBitVector =+ forM_ [0 .. indexMax] $ \n ->+ forM_ [0 .. otherMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) ->+ case SNat @(n + 1) `compareSNat` SNat @(2 ^ m) of+ SNatLE -> do+ assertBool (show (n, m)) (convertXException (Proxy @(Index (n + 1))) (Proxy @(BitVector m)))+ forM_ [minBound .. maxBound] $ \(i :: Index (n + 1)) -> do+ assertBool (show (n, m, i)) (convertLaw1 (Proxy @(BitVector m)) i)+ assertBool (show (n, m, i)) (convertLaw2 (Proxy @(BitVector m)) i)+ _ | (n == 0 && m == 0 && zeroWidthSkip) -> pure ()+ _ -> assertBool (show (n, m)) (convertLaw3 (Proxy @(Index (n + 1))) (Proxy @(BitVector m)))+ where+ zeroWidthSkip = False++case_convertUnsignedIndex :: Assertion+case_convertUnsignedIndex =+ forM_ [0 .. otherMax] $ \n ->+ forM_ [0 .. indexMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) ->+ case SNat @(2 ^ n) `compareSNat` SNat @(m + 1) of+ SNatLE -> do+ assertBool (show (n, m)) (convertXException (Proxy @(Unsigned n)) (Proxy @(Index (m + 1))))+ forM_ [minBound .. maxBound] $ \(i :: Unsigned n) -> do+ assertBool (show (n, m, i)) (convertLaw1 (Proxy @(Index (m + 1))) i)+ assertBool (show (n, m, i)) (convertLaw2 (Proxy @(Index (m + 1))) i)+ _ | (n == 0 && m == 0 && zeroWidthSkip) -> pure ()+ _ -> assertBool (show (n, m)) (convertLaw3 (Proxy @(Unsigned n)) (Proxy @(Index (m + 1))))+ where+ zeroWidthSkip = False++case_convertUnsignedUnsigned :: Assertion+case_convertUnsignedUnsigned =+ forM_ [0 .. otherMax] $ \n ->+ forM_ [0 .. otherMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) ->+ case SNat @n `compareSNat` SNat @m of+ SNatLE -> do+ assertBool (show (n, m)) (convertXException (Proxy @(Unsigned n)) (Proxy @(Unsigned m)))+ forM_ [minBound .. maxBound] $ \(i :: Unsigned n) -> do+ assertBool (show (n, m, i)) (convertLaw1 (Proxy @(Unsigned m)) i)+ assertBool (show (n, m, i)) (convertLaw2 (Proxy @(Unsigned m)) i)+ _ | (n == 0 && m == 0 && zeroWidthSkip) -> pure ()+ _ -> assertBool (show (n, m)) (convertLaw3 (Proxy @(Unsigned n)) (Proxy @(Unsigned m)))+ where+ zeroWidthSkip = False++case_convertUnsignedSigned :: Assertion+case_convertUnsignedSigned =+ forM_ [0 .. otherMax] $ \n ->+ forM_ [0 .. otherMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) ->+ case SNat @(n + 1) `compareSNat` SNat @m of+ SNatLE -> do+ assertBool (show (n, m)) (convertXException (Proxy @(Unsigned n)) (Proxy @(Signed m)))+ forM_ [minBound .. maxBound] $ \(i :: Unsigned n) -> do+ assertBool (show (n, m, i)) (convertLaw1 (Proxy @(Signed m)) i)+ assertBool (show (n, m, i)) (convertLaw2 (Proxy @(Signed m)) i)+ _ | (n == 0 && m == 0 && zeroWidthSkip) -> pure ()+ _ -> assertBool (show (n, m)) (convertLaw3 (Proxy @(Unsigned n)) (Proxy @(Signed m)))+ where+ zeroWidthSkip = True++case_convertUnsignedBitVector :: Assertion+case_convertUnsignedBitVector =+ forM_ [0 .. otherMax] $ \n ->+ forM_ [0 .. otherMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) ->+ case SNat @n `compareSNat` SNat @m of+ SNatLE -> do+ assertBool (show (n, m)) (convertXException (Proxy @(Unsigned n)) (Proxy @(BitVector m)))+ forM_ [minBound .. maxBound] $ \(i :: Unsigned n) -> do+ assertBool (show (n, m, i)) (convertLaw1 (Proxy @(BitVector m)) i)+ assertBool (show (n, m, i)) (convertLaw2 (Proxy @(BitVector m)) i)+ _ | (n == 0 && m == 0 && zeroWidthSkip) -> pure ()+ _ -> assertBool (show (n, m)) (convertLaw3 (Proxy @(Unsigned n)) (Proxy @(BitVector m)))+ where+ zeroWidthSkip = False++case_convertSignedSigned :: Assertion+case_convertSignedSigned =+ forM_ [0 .. otherMax] $ \n ->+ forM_ [0 .. otherMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) ->+ case SNat @n `compareSNat` SNat @m of+ SNatLE -> do+ assertBool (show (n, m)) (convertXException (Proxy @(Signed n)) (Proxy @(Signed m)))+ forM_ [minBound .. maxBound] $ \(i :: Signed n) -> do+ assertBool (show (n, m, i)) (convertLaw1 (Proxy @(Signed m)) i)+ assertBool (show (n, m, i)) (convertLaw2 (Proxy @(Signed m)) i)+ _ | (n == 0 && m == 0 && zeroWidthSkip) -> pure ()+ _ -> assertBool (show (n, m)) (convertLaw3 (Proxy @(Signed n)) (Proxy @(Signed m)))+ where+ zeroWidthSkip = False++case_convertBitVectorIndex :: Assertion+case_convertBitVectorIndex =+ forM_ [0 .. otherMax] $ \n ->+ forM_ [0 .. indexMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) ->+ case SNat @(2 ^ n) `compareSNat` SNat @(m + 1) of+ SNatLE -> do+ assertBool (show (n, m)) (convertXException (Proxy @(BitVector n)) (Proxy @(Index (m + 1))))+ forM_ [minBound .. maxBound] $ \(i :: BitVector n) -> do+ assertBool (show (n, m, i)) (convertLaw1 (Proxy @(Index (m + 1))) i)+ assertBool (show (n, m, i)) (convertLaw2 (Proxy @(Index (m + 1))) i)+ _ | (n == 0 && m == 0 && zeroWidthSkip) -> pure ()+ _ -> assertBool (show (n, m)) (convertLaw3 (Proxy @(BitVector n)) (Proxy @(Index (m + 1))))+ where+ zeroWidthSkip = False++case_convertBitVectorUnsigned :: Assertion+case_convertBitVectorUnsigned =+ forM_ [0 .. otherMax] $ \n ->+ forM_ [0 .. otherMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) ->+ case SNat @n `compareSNat` SNat @m of+ SNatLE -> do+ assertBool (show (n, m)) (convertXException (Proxy @(BitVector n)) (Proxy @(Unsigned m)))+ forM_ [minBound .. maxBound] $ \(i :: BitVector n) -> do+ assertBool (show (n, m, i)) (convertLaw1 (Proxy @(Unsigned m)) i)+ assertBool (show (n, m, i)) (convertLaw2 (Proxy @(Unsigned m)) i)+ _ | (n == 0 && m == 0 && zeroWidthSkip) -> pure ()+ _ -> assertBool (show (n, m)) (convertLaw3 (Proxy @(BitVector n)) (Proxy @(Unsigned m)))+ where+ zeroWidthSkip = False++case_convertBitVectorSigned :: Assertion+case_convertBitVectorSigned =+ forM_ [0 .. otherMax] $ \n ->+ forM_ [0 .. otherMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) ->+ case SNat @(n + 1) `compareSNat` SNat @m of+ SNatLE -> do+ assertBool (show (n, m)) (convertXException (Proxy @(BitVector n)) (Proxy @(Signed m)))+ forM_ [minBound .. maxBound] $ \(i :: BitVector n) -> do+ assertBool (show (n, m, i)) (convertLaw1 (Proxy @(Signed m)) i)+ assertBool (show (n, m, i)) (convertLaw2 (Proxy @(Signed m)) i)+ _ | (n == 0 && m == 0 && zeroWidthSkip) -> pure ()+ _ -> assertBool (show (n, m)) (convertLaw3 (Proxy @(BitVector n)) (Proxy @(Signed m)))+ where+ zeroWidthSkip = True++case_convertBitVectorBitVector :: Assertion+case_convertBitVectorBitVector =+ forM_ [0 .. otherMax] $ \n ->+ forM_ [0 .. otherMax] $ \m ->+ withSomeSNat n $ \(SNat :: SNat n) ->+ withSomeSNat m $ \(SNat :: SNat m) ->+ case SNat @n `compareSNat` SNat @m of+ SNatLE -> do+ assertBool (show (n, m)) (convertXException (Proxy @(BitVector n)) (Proxy @(BitVector m)))+ forM_ [minBound .. maxBound] $ \(i :: BitVector n) -> do+ assertBool (show (n, m, i)) (convertLaw1 (Proxy @(BitVector m)) i)+ assertBool (show (n, m, i)) (convertLaw2 (Proxy @(BitVector m)) i)+ _ | (n == 0 && m == 0 && zeroWidthSkip) -> pure ()+ _ -> assertBool (show (n, m)) (convertLaw3 (Proxy @(BitVector n)) (Proxy @(BitVector m)))+ where+ zeroWidthSkip = False
tests/Clash/Tests/Ram.hs view
@@ -51,7 +51,7 @@ maskOobRead :: Ram maskOobRead rd we wr din =- maybeIsX <$> mux (rd .<. 2) ram0 (pure 4)+ maybeIsX <$> mux (rd .< 2) ram0 (pure 4) where ram0 = asyncRam# clockGen clockGen enableGen d2 rd we wr din
tests/Clash/Tests/Reset.hs view
@@ -2,7 +2,6 @@ {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE DataKinds #-}-{-# LANGUAGE PolyKinds #-} {-# OPTIONS_GHC -Wno-orphans #-}
tests/Clash/Tests/Resize.hs view
@@ -1,19 +1,38 @@+{-# LANGUAGE NumericUnderscores #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-} {-# LANGUAGE TypeFamilies #-} -module Clash.Tests.Resize (tests) where+{-# OPTIONS_GHC -fplugin=GHC.TypeLits.Extra.Solver #-}+{-# OPTIONS_GHC -fplugin=GHC.TypeLits.Normalise #-}+{-# OPTIONS_GHC -fplugin=GHC.TypeLits.KnownNat.Solver #-} +module Clash.Tests.Resize (tests, main) where++import Clash.Prelude (Unsigned, Signed, BitVector, Index)+import Clash.Promoted.Nat (SNat(..))+import Clash.XException (XException) import Control.DeepSeq (NFData) import Control.Exception (SomeException, try, evaluate)-import Clash.XException (XException) import Data.Either (isLeft) import Data.Proxy (Proxy(Proxy))-import GHC.TypeNats (KnownNat, type (<=))-import Test.Tasty (TestTree, testGroup)-import Test.Tasty.QuickCheck+import GHC.TypeNats (KnownNat, SomeNat(..), type (<=), type (+), Nat, someNatVal)+import Hedgehog ((===))+import Numeric.Natural (Natural)+import Test.Tasty (TestTree, testGroup, defaultMain)+import Test.Tasty.Hedgehog (testPropertyNamed)+import Test.Tasty.QuickCheck (testProperty, discard, ioProperty, counterexample) import qualified Clash.Class.Resize as Resize-import Clash.Sized.Index+import qualified Hedgehog as H+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range+import qualified Test.Tasty.QuickCheck as Q +withSomeSNat :: Natural -> (forall (n :: Nat). SNat n -> r) -> r+withSomeSNat n f = case someNatVal n of+ SomeNat (_ :: Proxy n) -> f (SNat @n)+ -- | Anything that's in bounds should not cause an error indexProp :: forall a b.@@ -26,7 +45,7 @@ indexFailProp :: forall a b. ((b <= a), KnownNat a, KnownNat b) =>- Proxy b -> Index a -> Property+ Proxy b -> Index a -> Q.Property indexFailProp Proxy v = let checked = Resize.checkedResize @a @b v in if toInteger v > toInteger (maxBound @(Index b)) then@@ -34,8 +53,138 @@ else discard +maybeResizePropT ::+ forall f a b .+ ( Integral (f a)+ , Bounded (f a)+ , Show (f a)+ , Integral (f b)+ , Bounded (f b)+ , Show (f b)+ , Resize.Resize f+ , KnownNat a+ , KnownNat b+ ) =>+ Proxy (f a) ->+ Proxy (f b) ->+ H.PropertyT IO ()+maybeResizePropT _ _ = do+ let+ minFa = fromIntegral (minBound @(f a)) :: Integer+ maxFa = fromIntegral (maxBound @(f a)) :: Integer+ minFb = fromIntegral (minBound @(f b)) :: Integer+ maxFb = fromIntegral (maxBound @(f b)) :: Integer++ H.footnote $ "minFa: " <> show minFa+ H.footnote $ "maxFa: " <> show maxFa+ H.footnote $ "minFb: " <> show minFb+ H.footnote $ "maxFb: " <> show maxFb++ input <- H.forAll $ Gen.integral (Range.constant minFa maxFa)+ let output = Resize.maybeResize @a @b @f (fromIntegral input)+ if minFb <= input && input <= maxFb+ then output === Just (fromIntegral input)+ else output === Nothing++maybeResizeUnsignedProp :: H.Property+maybeResizeUnsignedProp = H.property $ do+ a <- H.forAll $ Gen.integral (Range.linear 0 100)+ b <- H.forAll $ Gen.integral (Range.linear 0 100)+ withSomeSNat a $ \(SNat :: SNat a) -> do+ withSomeSNat b $ \(SNat :: SNat b) -> do+ maybeResizePropT @Unsigned @a @b Proxy Proxy++maybeResizeSignedProp :: H.Property+maybeResizeSignedProp = H.property $ do+ a <- H.forAll $ Gen.integral (Range.linear 0 100)+ b <- H.forAll $ Gen.integral (Range.linear 0 100)+ withSomeSNat a $ \(SNat :: SNat a) -> do+ withSomeSNat b $ \(SNat :: SNat b) -> do+ maybeResizePropT @Signed @a @b Proxy Proxy++maybeResizeIndexProp :: H.Property+maybeResizeIndexProp = H.property $ do+ a <- H.forAll $ Gen.integral (Range.linear 1 (2^(128::Natural)))+ b <- H.forAll $ Gen.integral (Range.linear 1 (2^(128::Natural)))+ withSomeSNat a $ \(SNat :: SNat a) -> do+ withSomeSNat b $ \(SNat :: SNat b) -> do+ maybeResizePropT @Index @a @b Proxy Proxy++maybeResizeBitVectorProp :: H.Property+maybeResizeBitVectorProp = H.property $ do+ a <- H.forAll $ Gen.integral (Range.linear 0 100)+ b <- H.forAll $ Gen.integral (Range.linear 0 100)+ withSomeSNat a $ \(SNat :: SNat a) -> do+ withSomeSNat b $ \(SNat :: SNat b) -> do+ maybeResizePropT @BitVector @a @b Proxy Proxy++maybeTruncatePropT ::+ forall f a b .+ ( Integral (f a)+ , Bounded (f a)+ , Show (f a)+ , Integral (f (a + b))+ , Bounded (f (a + b))+ , Show (f (a + b))+ , Resize.Resize f+ , KnownNat a+ , KnownNat b+ ) =>+ Proxy (f a) ->+ Proxy (f (a + b)) ->+ H.PropertyT IO ()+maybeTruncatePropT _ _ = do+ let+ minFa = fromIntegral (minBound @(f a)) :: Integer+ maxFa = fromIntegral (maxBound @(f a)) :: Integer+ minFab = fromIntegral (minBound @(f (a + b))) :: Integer+ maxFab = fromIntegral (maxBound @(f (a + b))) :: Integer++ H.footnote $ "minFa: " <> show minFa+ H.footnote $ "maxFa: " <> show maxFa+ H.footnote $ "minFab: " <> show minFab+ H.footnote $ "maxFab: " <> show maxFab++ input <- H.forAll $ Gen.integral (Range.constant minFa maxFa)+ let output = Resize.maybeTruncateB @a @b @f (fromIntegral input)+ if minFab <= input && input <= maxFab+ then output === Just (fromIntegral input)+ else output === Nothing++maybeTruncateUnsignedProp :: H.Property+maybeTruncateUnsignedProp = H.property $ do+ a <- H.forAll $ Gen.integral (Range.linear 0 100)+ b <- H.forAll $ Gen.integral (Range.linear 0 100)+ withSomeSNat a $ \(SNat :: SNat a) -> do+ withSomeSNat b $ \(SNat :: SNat b) -> do+ maybeTruncatePropT @Unsigned @a @b Proxy Proxy++maybeTruncateSignedProp :: H.Property+maybeTruncateSignedProp = H.property $ do+ a <- H.forAll $ Gen.integral (Range.linear 0 100)+ b <- H.forAll $ Gen.integral (Range.linear 0 100)+ withSomeSNat a $ \(SNat :: SNat a) -> do+ withSomeSNat b $ \(SNat :: SNat b) -> do+ maybeTruncatePropT @Signed @a @b Proxy Proxy++maybeTruncateIndexProp :: H.Property+maybeTruncateIndexProp = H.property $ do+ a <- H.forAll $ Gen.integral (Range.linear 1 (2^(128::Natural)))+ b <- H.forAll $ Gen.integral (Range.linear 1 (2^(128::Natural)))+ withSomeSNat a $ \(SNat :: SNat a) -> do+ withSomeSNat b $ \(SNat :: SNat b) -> do+ maybeTruncatePropT @Index @a @b Proxy Proxy++maybeTruncateBitVectorProp :: H.Property+maybeTruncateBitVectorProp = H.property $ do+ a <- H.forAll $ Gen.integral (Range.linear 0 100)+ b <- H.forAll $ Gen.integral (Range.linear 0 100)+ withSomeSNat a $ \(SNat :: SNat a) -> do+ withSomeSNat b $ \(SNat :: SNat b) -> do+ maybeTruncatePropT @BitVector @a @b Proxy Proxy+ -- | Succeed if evaluating leads to a non-XException Exception-expectExceptionNoX :: (Show a, NFData a) => a -> Property+expectExceptionNoX :: (Show a, NFData a) => a -> Q.Property expectExceptionNoX a0 = ioProperty $ do a1 <- try @SomeException (try @XException (evaluate a0)) pure $@@ -49,5 +198,18 @@ [ testProperty "indexProp @17 @19" (indexProp @17 @19 Proxy) , testProperty "indexProp @19 @19" (indexProp @19 @19 Proxy) , testProperty "indexFailProp @37 @7" (indexFailProp @37 @7 Proxy)+ , testPropertyNamed "maybeResizeUnsignedProp" "maybeResizeUnsignedProp" maybeResizeUnsignedProp+ , testPropertyNamed "maybeResizeSignedProp" "maybeResizeSignedProp" maybeResizeSignedProp+ , testPropertyNamed "maybeResizeIndexProp" "maybeResizeIndexProp" maybeResizeIndexProp+ , testPropertyNamed "maybeResizeBitVectorProp" "maybeResizeBitVectorProp" maybeResizeBitVectorProp+ , testPropertyNamed "maybeTruncateUnsignedProp" "maybeTruncateUnsignedProp" maybeTruncateUnsignedProp+ , testPropertyNamed "maybeTruncateSignedProp" "maybeTruncateSignedProp" maybeTruncateSignedProp+ , testPropertyNamed "maybeTruncateIndexProp" "maybeTruncateIndexProp" maybeTruncateIndexProp+ , testPropertyNamed "maybeTruncateBitVectorProp" "maybeTruncateBitVectorProp" maybeTruncateBitVectorProp ] ]++main :: IO ()+main = defaultMain+ -- $ adjustOption (\_ -> HedgehogTestLimit (Just 1_000_000))+ $ tests
tests/Clash/Tests/Signal.hs view
@@ -6,7 +6,6 @@ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> -} -{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE NoMonomorphismRestriction #-}@@ -29,83 +28,18 @@ (Femtoseconds(..), dynamicClockGen, sample, head#) import Control.Exception (evaluate)-import Data.List (isInfixOf) import Test.Tasty import Test.Tasty.HUnit -import qualified Language.Haskell.Interpreter as Hint-import Language.Haskell.Interpreter (OptionVal((:=)))- createDomain vSystem{vName="H11", vPeriod=hzToPeriod 11} createDomain vSystem{vName="H77", vPeriod=hzToPeriod 77} createDomain vSystem{vName="F1", vPeriod=20} createDomain vSystem{vName="F6", vPeriod=250} -customTypeMark :: String-customTypeMark = "You tried to apply an explicitly routed clock, reset, or enable line"--typeCheck- :: String- -> IO (Either Hint.InterpreterError ())-typeCheck expr =- Hint.runInterpreter $ do- Hint.setImports ["Clash.Prelude"]- Hint.set [Hint.languageExtensions := [Hint.RankNTypes, Hint.TypeApplications]]- mapM_ Hint.runStmt [test0s, test1s, test2s, test3s, test4s]- Hint.interpret expr (Hint.as :: ())--assertCustomTypeError :: String -> String -> Assertion-assertCustomTypeError expectedErr expr = do- result <- typeCheck expr- case result of- Left err ->- if expectedErr `isInfixOf` show err then- pure ()- else- assertFailure $- "Expression failed to typecheck as expected, but did not contain "- <> "expected type error. Instead it contained: " <> show err- Right () ->- assertFailure "Expression should have failed to typecheck, but succeeded."- main :: IO () main = defaultMain tests -test0s, test1s, test2s, test3s :: String-test0s = "let test0 = undefined :: Signal dom1 a -> Signal dom2 Int"-test1s = "let test1 = undefined :: Int -> Char -> Int"-test2s = "let test2 = undefined :: Signal System a -> Signal XilinxSystem Int"-test3s = "let test3 = () :: ()"-test4s = "let test4 = undefined :: ((Signal dom1 a, Signal dom2 a), Signal dom3 a)"-test5s = "let test5 = undefined :: ((Char, Signal dom1 a), Signal dom2 a)"--test0 :: forall dom1 dom2. Signal dom1 Int -> Signal dom2 Int-test0 = undefined--test1 :: Int -> Char -> Int-test1 = undefined--test2 :: Signal System a -> Signal XilinxSystem Int-test2 = undefined--test3 :: ()-test3 = ()--test4- :: forall dom1 dom2 dom3 dom4 a- . ((Signal dom1 a, Signal dom2 a), Signal dom3 a)- -> Signal dom4 a-test4 = undefined--test5- :: forall dom1 dom2 a b- . ((b, Signal dom1 a), Signal dom2 a)-test5 = undefined--acte :: String -> Assertion-acte = assertCustomTypeError customTypeMark- tests :: TestTree tests = testGroup@@ -116,65 +50,9 @@ let rst0 = fromList [True, True, False, False, True, True] rst1 = unsafeFromActiveHigh rst0 reg = register 'a' (pure 'b')-#ifdef CLASH_MULTIPLE_HIDDEN- sig = withReset rst1 reg-#else sig = withReset @System rst1 reg-#endif in testCase "withReset behavior" (sampleN @System 6 sig @?= "aaabaa") -#ifdef CLASH_MULTIPLE_HIDDEN- -- See: https://github.com/clash-lang/clash-compiler/pull/669- , testCase "test0nok_0" (acte "withReset resetGen test0")- , testCase "test0nok_1" (acte "withReset (resetGen @System) test0")- , testCase "test0nok_2" (acte "withReset @System (resetGen @System) test0")- , testCase- "test0nok_3"- (acte- (unwords- [ "withReset", "@System", "(resetGen @System)"- , "(test0 :: Signal System a -> Signal dom Int)"- ]))-- , testCase "test0nok_4" (acte "withSpecificReset resetGen test0")- , testCase "test0nok_5" (acte "withSpecificReset (resetGen @System) test0")-- , testCase "test1nok_0" (acte "withReset resetGen test1")- , testCase "test1nok_1" (acte "withReset (resetGen @System) test1")- , testCase "test1nok_2" (acte "withSpecificReset resetGen test1")- , testCase "test1nok_3" (acte "withSpecificReset (resetGen @System) test1")-- , testCase "test2nok_0" (acte "withReset resetGen test2")- , testCase "test2nok_1" (acte "withReset (resetGen @System) test2")- , testCase "test2nok_2" (acte "withSpecificReset resetGen test2")-- , testCase "test3nok_0" (acte "withReset resetGen test3")- , testCase "test3nok_1" (acte "withReset (resetGen @System) test3")- , testCase "test3nok_2" (acte "withSpecificReset resetGen test3")- , testCase "test3nok_3" (acte "withSpecificReset (resetGen @System) test3")-- , testCase "test4nok_0" (acte $- "withSpecificReset resetGen (test4 :: "- ++ "((Signal System a, Signal dom2 a), Signal dom3 a)"- ++ "-> Signal dom4 a)" )-- , testCase "test4nok_1" (acte $- "withSpecificReset resetGen (test4 :: "- ++ "((Signal dom1 a, Signal System a), Signal dom3 a)"- ++ "-> Signal dom4 a)" )-- , testCase "test4nok_2" (acte $- "withReset resetGen (test4 :: "- ++ "((Signal System a, Signal dom2 a), Signal dom3 a)"- ++ "-> Signal dom4 a)" )-- , testCase "test4nok_3" (acte $- "withReset resetGen (test4 :: "- ++ "((Signal dom1 a, Signal System a), Signal dom3 a)"- ++ "-> Signal dom4 a)" )-- , testCase "test5nok_0" (acte "withSpecificReset resetGen test5")-#endif , testCase "T1521" $ let f (_, b) = (b, b)@@ -183,6 +61,12 @@ in evaluate a >> pure () ]+ , testGroup "SaturatingNum"+ [ testCase "satSucc SatWrap" case_satSuccSatWrap+ , testCase "satSucc SatBound" case_satSuccSatBound+ , testCase "satPred SatWrap" case_satPredSatWrap+ , testCase "satPred SatBound" case_satPredSatBound+ ] , testGroup "unsafeSynchronizer" [ testCase "case_dynamicStaticEq" case_dynamicStaticEq , testCase "case_dynamicHasEffect" case_dynamicHasEffect@@ -192,24 +76,6 @@ ] ] --- Tests below should survive compilation:-test0ok_0 = withReset @System (resetGen @System) (test0 @System @System)-#ifdef CLASH_MULTIPLE_HIDDEN-test0ok_1 = withReset resetGen (test0 @System @System)-test0ok_2 = withSpecificReset (resetGen @System) (test0 @System)-test0ok_3 = withSpecificReset (resetGen @System) (test0 @_ @System)--test2ok_0 = withSpecificReset (resetGen @System) test2-test2ok_1 = withSpecificReset @System resetGen test2--test4ok_0 = withReset resetGen (test4 @System @System @System @System)-test4ok_1 = withSpecificReset (resetGen @System) (test4 @System @_ @_ @_)-test4ok_2 = withSpecificReset (resetGen @System) (test4 @_ @System @_ @_)-test4ok_3 = withSpecificReset (resetGen @System) (test4 @_ @_ @System @_)--test5ok_0 = withSpecificReset (resetGen @System) (test5 @System @_)-#endif- -- | Asserts that static clocks behave the same as dynamic clocks with a static -- period signal passed into it. case_dynamicStaticEq :: Assertion@@ -320,3 +186,31 @@ , 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 , 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6 ]++-- | Test that satSucc SatWrap works on signals+case_satSuccSatWrap :: Assertion+case_satSuccSatWrap = do+ let s = fromList [255, 254] :: Signal System (Unsigned 8)+ result = satSucc SatWrap s+ sampleN @System 2 result @?= [0, 255]++-- | Test that satSucc SatBound works on signals+case_satSuccSatBound :: Assertion+case_satSuccSatBound = do+ let s = fromList [255, 254] :: Signal System (Unsigned 8)+ result = satSucc SatBound s+ sampleN @System 2 result @?= [255, 255]++-- | Test that satPred SatWrap works on signals+case_satPredSatWrap :: Assertion+case_satPredSatWrap = do+ let s = fromList [0, 1] :: Signal System (Unsigned 8)+ result = satPred SatWrap s+ sampleN @System 2 result @?= [255, 0]++-- | Test that satPred SatBound works on signals+case_satPredSatBound :: Assertion+case_satPredSatBound = do+ let s = fromList [0, 1] :: Signal System (Unsigned 8)+ result = satPred SatBound s+ sampleN @System 2 result @?= [0, 0]
tests/Clash/Tests/Signed.hs view
@@ -6,9 +6,13 @@ import Test.Tasty.HUnit import Test.Tasty.QuickCheck +import Data.Bits (Bits(shiftR))+ import Clash.Sized.Internal.Signed import Clash.Tests.SizedNum +import Test.Tasty.HUnit.Extra (expectException)+ tests :: TestTree tests = localOption (QuickCheckMaxRatio 2) $ testGroup "All" [ testGroup "Signed 1" $@@ -35,6 +39,24 @@ , testGroup "Bounds" [ testCase "maxBound :: Signed 0" $ maxBound @(Signed 0) @?= 0 , testCase "minBound :: Signed 0" $ minBound @(Signed 0) @?= 0+ ]+ , testGroup "shiftR"+ [ testCase "shiftR 5 0 == 5" $+ shiftR (5 :: Signed 8) 0 @?= 5+ , testCase "returns 0 when non-negative and n == bitSize" $+ shiftR (0x7F :: Signed 8) 8 @?= 0+ , testCase "returns 0 when non-negative and n > bitSize" $+ shiftR (0x7F :: Signed 8) (8 + 1) @?= 0+ , testCase "returns 0 when non-negative and n >> bitSize" $+ shiftR (0x7F :: Signed 8) (8 + 1000) @?= 0+ , testCase "returns -1 when negative and n == bitSize" $+ shiftR (-1 :: Signed 8) 8 @?= (-1)+ , testCase "returns -1 when negative and n > bitSize" $+ shiftR (-50 :: Signed 8) (8 + 1) @?= (-1)+ , testCase "returns -1 when negative and n >> bitSize" $+ shiftR (-1 :: Signed 8) (8 + 1000) @?= (-1)+ , testCase "undefined when n < 0" $+ expectException (shiftR (1 :: Signed 8) (-1)) ] ]
tests/Clash/Tests/TopEntityGeneration.hs view
@@ -1,6 +1,5 @@ {-# OPTIONS_GHC -Wwarn #-} -{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE TemplateHaskell #-}@@ -300,15 +299,6 @@ -> "out" ::: Signal System Bool topEntityFailure6 = undefined -#if MULTIPLE_HIDDEN-topEntityFailure7- :: HiddenClockResetEnable System- => HiddenClockResetEnable XilinxSystem- => "int" ::: Signal System Int- -> "out" ::: Signal System Bool-topEntityFailure7 = undefined-#endif- topEntityFailure8 :: "int" ::: Signal System (Passthrough Int Simple) -> "out" ::: Signal System Bool@@ -366,10 +356,6 @@ $(unTypeQ $ maybeBuildTopEntity Nothing 'topEntityFailure5) @?= failed , testCase "topEntityFailure6" $ $(unTypeQ $ maybeBuildTopEntity Nothing 'topEntityFailure6) @?= failed-#if MULTIPLE_HIDDEN- , testCase "topEntityFailure7" $- $(unTypeQ $ maybeBuildTopEntity Nothing 'topEntityFailure7) @?= failed-#endif , testCase "topEntityFailure8" $ $(unTypeQ $ maybeBuildTopEntity Nothing 'topEntityFailure8) @?= failed ]
tests/Clash/Tests/Unsigned.hs view
@@ -6,9 +6,13 @@ import Test.Tasty.HUnit import Test.Tasty.QuickCheck +import Data.Bits (Bits(shiftR))+ import Clash.Sized.Internal.Unsigned import Clash.Tests.SizedNum +import Test.Tasty.HUnit.Extra (expectException)+ tests :: TestTree tests = localOption (QuickCheckMaxRatio 2) $ testGroup "All" [ testGroup "Unsigned 1" $@@ -35,6 +39,18 @@ , testGroup "Bounds" [ testCase "maxBound :: Unsigned 0" $ maxBound @(Unsigned 0) @?= 0 , testCase "minBound :: Unsigned 0" $ minBound @(Unsigned 0) @?= 0+ ]+ , testGroup "shiftR"+ [ testCase "shiftR 5 0 == 5" $+ shiftR (5 :: Unsigned 8) 0 @?= 5+ , testCase "returns 0 when n == bitSize" $+ shiftR (0xFF :: Unsigned 8) 8 @?= 0+ , testCase "returns 0 when n > bitSize" $+ shiftR (0xFF :: Unsigned 8) (8 + 1) @?= 0+ , testCase "returns 0 when n >> bitSize" $+ shiftR (0xFF :: Unsigned 8) (8 + 1000) @?= 0+ , testCase "undefined when n < 0" $+ expectException (shiftR (1 :: Unsigned 8) (-1)) ] ]
tests/doctests.hs view
@@ -1,7 +1,8 @@+{-# LANGUAGE CPP #-} module Main where -import System.Environment (getArgs) import Test.DocTest (mainFromCabal)+import System.Environment (getArgs) main :: IO () main = mainFromCabal "clash-prelude" =<< getArgs
tests/unittests.hs view
@@ -14,8 +14,11 @@ import qualified Clash.Tests.DumpVCD import qualified Clash.Tests.Fixed import qualified Clash.Tests.FixedExhaustive+import qualified Clash.Tests.Index+import qualified Clash.Tests.MaybeNumConvert import qualified Clash.Tests.MaybeX import qualified Clash.Tests.NFDataX+import qualified Clash.Tests.NumConvert import qualified Clash.Tests.NumNewtypes import qualified Clash.Tests.Ram import qualified Clash.Tests.Reset@@ -28,6 +31,7 @@ import qualified Clash.Tests.XException import qualified Clash.Tests.Laws.Enum+import qualified Clash.Tests.Laws.Num import qualified Clash.Tests.Laws.SaturatingNum tests :: TestTree@@ -36,16 +40,19 @@ , Clash.Tests.AutoReg.tests , Clash.Tests.BitPack.tests , Clash.Tests.BitVector.tests- , Clash.Tests.BlockRam.tests , Clash.Tests.BlockRam.Blob.tests+ , Clash.Tests.BlockRam.tests , Clash.Tests.Clocks.tests , Clash.Tests.Counter.tests , Clash.Tests.DerivingDataRepr.tests , Clash.Tests.DumpVCD.tests , Clash.Tests.Fixed.tests , Clash.Tests.FixedExhaustive.tests+ , Clash.Tests.Index.tests+ , Clash.Tests.MaybeNumConvert.tests , Clash.Tests.MaybeX.tests , Clash.Tests.NFDataX.tests+ , Clash.Tests.NumConvert.tests , Clash.Tests.NumNewtypes.tests , Clash.Tests.Ram.tests , Clash.Tests.Reset.tests@@ -58,6 +65,7 @@ , Clash.Tests.XException.tests , testGroup "Laws" [ Clash.Tests.Laws.Enum.tests+ , Clash.Tests.Laws.Num.tests , Clash.Tests.Laws.SaturatingNum.tests ] ]