packages feed

clash-prelude 1.4.7 → 1.6.0

raw patch · 112 files changed

+7536/−2072 lines, 112 filesdep +directorydep +doctest-paralleldep +filepathdep −bifunctorsdep −doctestdep −text-showdep ~bytestringsetup-changedPVP ok

version bump matches the API change (PVP)

Dependencies added: directory, doctest-parallel, filepath

Dependencies removed: bifunctors, doctest, text-show

Dependency ranges changed: bytestring

API changes (from Hackage documentation)

- Clash.Annotations.BitRepresentation.Internal: instance TextShow.Classes.TextShow Clash.Annotations.BitRepresentation.Internal.Type'
- Clash.Annotations.TH: instance (GHC.Base.Semigroup a, GHC.Base.Monoid a) => GHC.Base.Monoid (Clash.Annotations.TH.Naming a)
- Clash.Class.BitPack: -- bits are needed to represent the constructor.
- Clash.Class.BitPack: -- the sum of each of the constructors fields.
- Clash.Class.BitPack: class GBitPack f where {
- Clash.Class.BitPack: gPackFields :: GBitPack f => Int -> f a -> (Int, BitVector (GFieldSize f))
- Clash.Class.BitPack: gUnpack :: GBitPack f => Int -> Int -> BitVector (GFieldSize f) -> f a
- Clash.Class.BitPack: instance (Clash.Class.BitPack.BitPack a, Clash.Class.BitPack.BitPack b) => Clash.Class.BitPack.BitPack (Data.Either.Either a b)
- Clash.Class.BitPack: instance (Clash.Class.BitPack.BitPack a, Clash.Class.BitPack.BitPack b) => Clash.Class.BitPack.BitPack (a, b)
- Clash.Class.BitPack: instance (Clash.Class.BitPack.BitPack a1, GHC.TypeNats.KnownNat (Clash.Class.BitPack.BitSize a1), Clash.Class.BitPack.BitPack (a2, a3), GHC.TypeNats.KnownNat (Clash.Class.BitPack.BitSize (a2, a3))) => Clash.Class.BitPack.BitPack (a1, a2, a3)
- Clash.Class.BitPack: instance (GHC.TypeNats.KnownNat (Clash.Class.BitPack.GFieldSize g), GHC.TypeNats.KnownNat (Clash.Class.BitPack.GFieldSize f), Clash.Class.BitPack.GBitPack f, Clash.Class.BitPack.GBitPack g) => Clash.Class.BitPack.GBitPack (f GHC.Generics.:*: g)
- Clash.Class.BitPack: instance (GHC.TypeNats.KnownNat (Clash.Class.BitPack.GFieldSize g), GHC.TypeNats.KnownNat (Clash.Class.BitPack.GFieldSize f), GHC.TypeNats.KnownNat (Clash.Class.BitPack.GConstructorCount f), Clash.Class.BitPack.GBitPack f, Clash.Class.BitPack.GBitPack g) => Clash.Class.BitPack.GBitPack (f GHC.Generics.:+: g)
- Clash.Class.BitPack: instance Clash.Class.BitPack.BitPack ()
- Clash.Class.BitPack: instance Clash.Class.BitPack.BitPack Clash.Sized.Internal.BitVector.Bit
- Clash.Class.BitPack: instance Clash.Class.BitPack.BitPack Foreign.C.Types.CUShort
- Clash.Class.BitPack: instance Clash.Class.BitPack.BitPack GHC.Int.Int16
- Clash.Class.BitPack: instance Clash.Class.BitPack.BitPack GHC.Int.Int32
- Clash.Class.BitPack: instance Clash.Class.BitPack.BitPack GHC.Int.Int64
- Clash.Class.BitPack: instance Clash.Class.BitPack.BitPack GHC.Int.Int8
- Clash.Class.BitPack: instance Clash.Class.BitPack.BitPack GHC.Types.Bool
- Clash.Class.BitPack: instance Clash.Class.BitPack.BitPack GHC.Types.Double
- Clash.Class.BitPack: instance Clash.Class.BitPack.BitPack GHC.Types.Float
- Clash.Class.BitPack: instance Clash.Class.BitPack.BitPack GHC.Types.Int
- Clash.Class.BitPack: instance Clash.Class.BitPack.BitPack GHC.Types.Word
- Clash.Class.BitPack: instance Clash.Class.BitPack.BitPack GHC.Word.Word16
- Clash.Class.BitPack: instance Clash.Class.BitPack.BitPack GHC.Word.Word32
- Clash.Class.BitPack: instance Clash.Class.BitPack.BitPack GHC.Word.Word64
- Clash.Class.BitPack: instance Clash.Class.BitPack.BitPack GHC.Word.Word8
- Clash.Class.BitPack: instance Clash.Class.BitPack.BitPack Numeric.Half.Internal.Half
- Clash.Class.BitPack: instance Clash.Class.BitPack.BitPack a => Clash.Class.BitPack.BitPack (Data.Complex.Complex a)
- Clash.Class.BitPack: instance Clash.Class.BitPack.BitPack a => Clash.Class.BitPack.BitPack (Data.Ord.Down a)
- Clash.Class.BitPack: instance Clash.Class.BitPack.BitPack a => Clash.Class.BitPack.BitPack (GHC.Maybe.Maybe a)
- Clash.Class.BitPack: instance Clash.Class.BitPack.BitPack c => Clash.Class.BitPack.GBitPack (GHC.Generics.K1 i c)
- Clash.Class.BitPack: instance Clash.Class.BitPack.GBitPack GHC.Generics.U1
- Clash.Class.BitPack: instance Clash.Class.BitPack.GBitPack a => Clash.Class.BitPack.GBitPack (GHC.Generics.M1 m d a)
- Clash.Class.BitPack: instance GHC.TypeNats.KnownNat n => Clash.Class.BitPack.BitPack (Clash.Sized.Internal.BitVector.BitVector n)
- Clash.Explicit.Prelude: --
- Clash.Explicit.Prelude: -- </pre>
- Clash.Explicit.Prelude: -- <pre>
- Clash.Explicit.Prelude: -- Can be derived using <a>Generics</a>:
- Clash.Explicit.Prelude: -- data MyProductType = MyProductType { a :: Int, b :: Bool }
- Clash.Explicit.Prelude: -- deriving (Generic, BitPack)
- Clash.Explicit.Prelude: -- import GHC.Generics
- Clash.Explicit.Prelude: -- | Number of <a>Bit</a>s needed to represents elements of type <tt>a</tt>
- Clash.Explicit.Prelude: bitCoerce :: (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
- Clash.Explicit.Prelude: bitCoerceMap :: forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => (a -> a) -> b -> b
- Clash.Explicit.Prelude: bitToBool :: Bit -> Bool
- Clash.Explicit.Prelude: boolToBV :: KnownNat n => Bool -> BitVector (n + 1)
- Clash.Explicit.Prelude: boolToBit :: Bool -> Bit
- Clash.Explicit.Prelude: class KnownNat (BitSize a) => BitPack a where {
- Clash.Explicit.Prelude: pack :: (BitPack a, Generic a, GBitPack (Rep a), KnownNat (BitSize a), KnownNat constrSize, KnownNat fieldSize, constrSize ~ CLog 2 (GConstructorCount (Rep a)), fieldSize ~ GFieldSize (Rep a), (constrSize + fieldSize) ~ BitSize a) => a -> BitVector (BitSize a)
- Clash.Explicit.Prelude: packXWith :: KnownNat n => (a -> BitVector n) -> a -> BitVector n
- Clash.Explicit.Prelude: type BitSize a = (CLog 2 (GConstructorCount (Rep a))) + (GFieldSize (Rep a));
- Clash.Explicit.Prelude: type family BitSize a :: Nat;
- Clash.Explicit.Prelude: unpack :: (BitPack a, Generic a, GBitPack (Rep a), KnownNat constrSize, KnownNat fieldSize, constrSize ~ CLog 2 (GConstructorCount (Rep a)), fieldSize ~ GFieldSize (Rep a), (constrSize + fieldSize) ~ BitSize a) => BitVector (BitSize a) -> a
- Clash.Explicit.Prelude: }
- Clash.Prelude: --
- Clash.Prelude: -- </pre>
- Clash.Prelude: -- <pre>
- Clash.Prelude: -- Can be derived using <a>Generics</a>:
- Clash.Prelude: -- data MyProductType = MyProductType { a :: Int, b :: Bool }
- Clash.Prelude: -- deriving (Generic, BitPack)
- Clash.Prelude: -- import GHC.Generics
- Clash.Prelude: -- | Number of <a>Bit</a>s needed to represents elements of type <tt>a</tt>
- Clash.Prelude: bitCoerce :: (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
- Clash.Prelude: bitCoerceMap :: forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => (a -> a) -> b -> b
- Clash.Prelude: bitToBool :: Bit -> Bool
- Clash.Prelude: boolToBV :: KnownNat n => Bool -> BitVector (n + 1)
- Clash.Prelude: boolToBit :: Bool -> Bit
- Clash.Prelude: class KnownNat (BitSize a) => BitPack a where {
- Clash.Prelude: pack :: (BitPack a, Generic a, GBitPack (Rep a), KnownNat (BitSize a), KnownNat constrSize, KnownNat fieldSize, constrSize ~ CLog 2 (GConstructorCount (Rep a)), fieldSize ~ GFieldSize (Rep a), (constrSize + fieldSize) ~ BitSize a) => a -> BitVector (BitSize a)
- Clash.Prelude: packXWith :: KnownNat n => (a -> BitVector n) -> a -> BitVector n
- Clash.Prelude: type BitSize a = (CLog 2 (GConstructorCount (Rep a))) + (GFieldSize (Rep a));
- Clash.Prelude: unpack :: (BitPack a, Generic a, GBitPack (Rep a), KnownNat constrSize, KnownNat fieldSize, constrSize ~ CLog 2 (GConstructorCount (Rep a)), fieldSize ~ GFieldSize (Rep a), (constrSize + fieldSize) ~ BitSize a) => BitVector (BitSize a) -> a
- Clash.Sized.Fixed: instance Clash.Class.BitPack.BitPack (rep (int GHC.TypeNats.+ frac)) => Clash.Class.BitPack.BitPack (Clash.Sized.Fixed.Fixed rep int frac)
- Clash.Sized.Internal.BitVector: isLike :: forall n. KnownNat n => BitVector n -> BitVector n -> Bool
- Clash.Sized.Internal.Index: instance (GHC.TypeNats.KnownNat n, 1 GHC.TypeNats.<= n) => Clash.Class.BitPack.BitPack (Clash.Sized.Internal.Index.Index n)
- Clash.Sized.Internal.Signed: instance GHC.TypeNats.KnownNat n => Clash.Class.BitPack.BitPack (Clash.Sized.Internal.Signed.Signed n)
- Clash.Sized.Internal.Unsigned: instance GHC.TypeNats.KnownNat n => Clash.Class.BitPack.BitPack (Clash.Sized.Internal.Unsigned.Unsigned n)
- Clash.Sized.RTree: instance (GHC.TypeNats.KnownNat d, Clash.Class.BitPack.BitPack a) => Clash.Class.BitPack.BitPack (Clash.Sized.RTree.RTree d a)
- Clash.Sized.Vector: instance (GHC.TypeNats.KnownNat n, Clash.Class.BitPack.BitPack a) => Clash.Class.BitPack.BitPack (Clash.Sized.Vector.Vec n a)
- Clash.Verification.PrettyPrinters: pprProperty :: Property dom -> Text
- Clash.Verification.PrettyPrinters: pprPslProperty :: HDL -> Text -> Text -> ActiveEdge -> Property' Text -> Text
- Clash.Verification.PrettyPrinters: pprSvaProperty :: Text -> Text -> ActiveEdge -> Property' Text -> Text
+ Clash.Annotations.Primitive: InlineYamlPrimitive :: [HDL] -> String -> Primitive
+ Clash.Annotations.TH: instance GHC.Base.Monoid a => GHC.Base.Monoid (Clash.Annotations.TH.Naming a)
+ Clash.Class.AutoReg.Internal: autoReg :: (AutoReg a, HasCallStack, KnownDomain dom) => Clock dom -> Reset dom -> Enable dom -> a -> Signal dom a -> Signal dom a
+ Clash.Class.AutoReg.Internal: class NFDataX a => AutoReg a
+ Clash.Class.AutoReg.Internal: deriveAutoReg :: Name -> DecsQ
+ Clash.Class.AutoReg.Internal: deriveAutoRegTuples :: [Int] -> DecsQ
+ Clash.Class.AutoReg.Internal: instance (GHC.TypeNats.KnownNat d, Clash.Class.AutoReg.Internal.AutoReg a) => Clash.Class.AutoReg.Internal.AutoReg (Clash.Sized.RTree.RTree d a)
+ Clash.Class.AutoReg.Internal: instance (GHC.TypeNats.KnownNat n, Clash.Class.AutoReg.Internal.AutoReg a) => Clash.Class.AutoReg.Internal.AutoReg (Clash.Sized.Vector.Vec n a)
+ Clash.Class.AutoReg.Internal: instance Clash.Class.AutoReg.Internal.AutoReg ()
+ Clash.Class.AutoReg.Internal: instance Clash.Class.AutoReg.Internal.AutoReg (Clash.Sized.Internal.Index.Index n)
+ Clash.Class.AutoReg.Internal: instance Clash.Class.AutoReg.Internal.AutoReg (Clash.Sized.Internal.Signed.Signed n)
+ Clash.Class.AutoReg.Internal: instance Clash.Class.AutoReg.Internal.AutoReg (Clash.Sized.Internal.Unsigned.Unsigned n)
+ Clash.Class.AutoReg.Internal: instance Clash.Class.AutoReg.Internal.AutoReg Clash.Sized.Internal.BitVector.Bit
+ Clash.Class.AutoReg.Internal: instance Clash.Class.AutoReg.Internal.AutoReg Foreign.C.Types.CUShort
+ Clash.Class.AutoReg.Internal: instance Clash.Class.AutoReg.Internal.AutoReg GHC.Int.Int16
+ Clash.Class.AutoReg.Internal: instance Clash.Class.AutoReg.Internal.AutoReg GHC.Int.Int32
+ Clash.Class.AutoReg.Internal: instance Clash.Class.AutoReg.Internal.AutoReg GHC.Int.Int64
+ Clash.Class.AutoReg.Internal: instance Clash.Class.AutoReg.Internal.AutoReg GHC.Int.Int8
+ Clash.Class.AutoReg.Internal: instance Clash.Class.AutoReg.Internal.AutoReg GHC.Integer.Type.Integer
+ Clash.Class.AutoReg.Internal: instance Clash.Class.AutoReg.Internal.AutoReg GHC.Types.Bool
+ Clash.Class.AutoReg.Internal: instance Clash.Class.AutoReg.Internal.AutoReg GHC.Types.Char
+ Clash.Class.AutoReg.Internal: instance Clash.Class.AutoReg.Internal.AutoReg GHC.Types.Double
+ Clash.Class.AutoReg.Internal: instance Clash.Class.AutoReg.Internal.AutoReg GHC.Types.Float
+ Clash.Class.AutoReg.Internal: instance Clash.Class.AutoReg.Internal.AutoReg GHC.Types.Int
+ Clash.Class.AutoReg.Internal: instance Clash.Class.AutoReg.Internal.AutoReg GHC.Types.Word
+ Clash.Class.AutoReg.Internal: instance Clash.Class.AutoReg.Internal.AutoReg GHC.Word.Word16
+ Clash.Class.AutoReg.Internal: instance Clash.Class.AutoReg.Internal.AutoReg GHC.Word.Word32
+ Clash.Class.AutoReg.Internal: instance Clash.Class.AutoReg.Internal.AutoReg GHC.Word.Word64
+ Clash.Class.AutoReg.Internal: instance Clash.Class.AutoReg.Internal.AutoReg GHC.Word.Word8
+ Clash.Class.AutoReg.Internal: instance Clash.Class.AutoReg.Internal.AutoReg Numeric.Half.Internal.Half
+ Clash.Class.AutoReg.Internal: instance Clash.Class.AutoReg.Internal.AutoReg a => Clash.Class.AutoReg.Internal.AutoReg (GHC.Maybe.Maybe a)
+ Clash.Class.AutoReg.Internal: instance Clash.XException.NFDataX (rep (int GHC.TypeNats.+ frac)) => Clash.Class.AutoReg.Internal.AutoReg (Clash.Sized.Fixed.Fixed rep int frac)
+ Clash.Class.AutoReg.Internal: instance GHC.TypeNats.KnownNat n => Clash.Class.AutoReg.Internal.AutoReg (Clash.Sized.Internal.BitVector.BitVector n)
+ Clash.Class.BitPack: (!) :: (BitPack a, Enum i) => a -> i -> Bit
+ Clash.Class.BitPack: isLike :: BitPack a => a -> a -> Bool
+ Clash.Class.BitPack: lsb :: BitPack a => a -> Bit
+ Clash.Class.BitPack: msb :: BitPack a => a -> Bit
+ Clash.Class.BitPack: reduceAnd :: BitPack a => a -> Bit
+ Clash.Class.BitPack: reduceOr :: BitPack a => a -> Bit
+ Clash.Class.BitPack: reduceXor :: BitPack a => a -> Bit
+ Clash.Class.BitPack: replaceBit :: (BitPack a, Enum i) => i -> Bit -> a -> a
+ Clash.Class.BitPack: setSlice :: (BitPack a, BitSize a ~ ((m + 1) + i)) => SNat m -> SNat n -> BitVector ((m + 1) - n) -> a -> a
+ Clash.Class.BitPack: slice :: (BitPack a, BitSize a ~ ((m + 1) + i)) => SNat m -> SNat n -> a -> BitVector ((m + 1) - n)
+ Clash.Class.BitPack: split :: (BitPack a, BitSize a ~ (m + n), KnownNat n) => a -> (BitVector m, BitVector n)
+ Clash.Class.BitPack.BitIndex: (!) :: (BitPack a, Enum i) => a -> i -> Bit
+ Clash.Class.BitPack.BitIndex: lsb :: BitPack a => a -> Bit
+ Clash.Class.BitPack.BitIndex: msb :: BitPack a => a -> Bit
+ Clash.Class.BitPack.BitIndex: replaceBit :: (BitPack a, Enum i) => i -> Bit -> a -> a
+ Clash.Class.BitPack.BitIndex: setSlice :: (BitPack a, BitSize a ~ ((m + 1) + i)) => SNat m -> SNat n -> BitVector ((m + 1) - n) -> a -> a
+ Clash.Class.BitPack.BitIndex: slice :: (BitPack a, BitSize a ~ ((m + 1) + i)) => SNat m -> SNat n -> a -> BitVector ((m + 1) - n)
+ Clash.Class.BitPack.BitIndex: split :: (BitPack a, BitSize a ~ (m + n), KnownNat n) => a -> (BitVector m, BitVector n)
+ Clash.Class.BitPack.BitReduction: reduceAnd :: BitPack a => a -> Bit
+ Clash.Class.BitPack.BitReduction: reduceOr :: BitPack a => a -> Bit
+ Clash.Class.BitPack.BitReduction: reduceXor :: BitPack a => a -> Bit
+ Clash.Class.BitPack.Internal: --
+ Clash.Class.BitPack.Internal: -- </pre>
+ Clash.Class.BitPack.Internal: -- <pre>
+ Clash.Class.BitPack.Internal: -- Can be derived using <a>Generics</a>:
+ Clash.Class.BitPack.Internal: -- bits are needed to represent the constructor.
+ Clash.Class.BitPack.Internal: -- data MyProductType = MyProductType { a :: Int, b :: Bool }
+ Clash.Class.BitPack.Internal: -- deriving (Generic, BitPack)
+ Clash.Class.BitPack.Internal: -- import GHC.Generics
+ Clash.Class.BitPack.Internal: -- the sum of each of the constructors fields.
+ Clash.Class.BitPack.Internal: -- | Number of constructors this type has. Indirectly indicates how many
+ Clash.Class.BitPack.Internal: bitCoerce :: (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
+ Clash.Class.BitPack.Internal: bitCoerceMap :: forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => (a -> a) -> b -> b
+ Clash.Class.BitPack.Internal: bitToBool :: Bit -> Bool
+ Clash.Class.BitPack.Internal: boolToBV :: KnownNat n => Bool -> BitVector (n + 1)
+ Clash.Class.BitPack.Internal: boolToBit :: Bool -> Bit
+ Clash.Class.BitPack.Internal: class KnownNat (BitSize a) => BitPack a where {
+ Clash.Class.BitPack.Internal: class GBitPack f where {
+ Clash.Class.BitPack.Internal: gPackFields :: GBitPack f => Int -> f a -> (Int, BitVector (GFieldSize f))
+ Clash.Class.BitPack.Internal: gUnpack :: GBitPack f => Int -> Int -> BitVector (GFieldSize f) -> f a
+ Clash.Class.BitPack.Internal: instance (Clash.Class.BitPack.Internal.BitPack a, Clash.Class.BitPack.Internal.BitPack b) => Clash.Class.BitPack.Internal.BitPack (Data.Either.Either a b)
+ Clash.Class.BitPack.Internal: instance (Clash.Class.BitPack.Internal.BitPack a, Clash.Class.BitPack.Internal.BitPack b) => Clash.Class.BitPack.Internal.BitPack (a, b)
+ Clash.Class.BitPack.Internal: instance (Clash.Class.BitPack.Internal.BitPack a1, GHC.TypeNats.KnownNat (Clash.Class.BitPack.Internal.BitSize a1), Clash.Class.BitPack.Internal.BitPack (a2, a3), GHC.TypeNats.KnownNat (Clash.Class.BitPack.Internal.BitSize (a2, a3))) => Clash.Class.BitPack.Internal.BitPack (a1, a2, a3)
+ 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 ()
+ Clash.Class.BitPack.Internal: instance Clash.Class.BitPack.Internal.BitPack Clash.Sized.Internal.BitVector.Bit
+ Clash.Class.BitPack.Internal: instance Clash.Class.BitPack.Internal.BitPack Foreign.C.Types.CUShort
+ Clash.Class.BitPack.Internal: instance Clash.Class.BitPack.Internal.BitPack GHC.Int.Int16
+ Clash.Class.BitPack.Internal: instance Clash.Class.BitPack.Internal.BitPack GHC.Int.Int32
+ Clash.Class.BitPack.Internal: instance Clash.Class.BitPack.Internal.BitPack GHC.Int.Int64
+ Clash.Class.BitPack.Internal: instance Clash.Class.BitPack.Internal.BitPack GHC.Int.Int8
+ Clash.Class.BitPack.Internal: instance Clash.Class.BitPack.Internal.BitPack GHC.Types.Bool
+ Clash.Class.BitPack.Internal: instance Clash.Class.BitPack.Internal.BitPack GHC.Types.Double
+ Clash.Class.BitPack.Internal: instance Clash.Class.BitPack.Internal.BitPack GHC.Types.Float
+ Clash.Class.BitPack.Internal: instance Clash.Class.BitPack.Internal.BitPack GHC.Types.Int
+ Clash.Class.BitPack.Internal: instance Clash.Class.BitPack.Internal.BitPack GHC.Types.Word
+ Clash.Class.BitPack.Internal: instance Clash.Class.BitPack.Internal.BitPack GHC.Word.Word16
+ Clash.Class.BitPack.Internal: instance Clash.Class.BitPack.Internal.BitPack GHC.Word.Word32
+ Clash.Class.BitPack.Internal: instance Clash.Class.BitPack.Internal.BitPack GHC.Word.Word64
+ Clash.Class.BitPack.Internal: instance Clash.Class.BitPack.Internal.BitPack GHC.Word.Word8
+ Clash.Class.BitPack.Internal: instance Clash.Class.BitPack.Internal.BitPack Numeric.Half.Internal.Half
+ Clash.Class.BitPack.Internal: instance Clash.Class.BitPack.Internal.BitPack a => Clash.Class.BitPack.Internal.BitPack (Data.Complex.Complex a)
+ Clash.Class.BitPack.Internal: instance Clash.Class.BitPack.Internal.BitPack a => Clash.Class.BitPack.Internal.BitPack (Data.Ord.Down a)
+ Clash.Class.BitPack.Internal: instance Clash.Class.BitPack.Internal.BitPack a => Clash.Class.BitPack.Internal.BitPack (GHC.Maybe.Maybe a)
+ Clash.Class.BitPack.Internal: instance Clash.Class.BitPack.Internal.BitPack c => Clash.Class.BitPack.Internal.GBitPack (GHC.Generics.K1 i c)
+ Clash.Class.BitPack.Internal: instance Clash.Class.BitPack.Internal.GBitPack GHC.Generics.U1
+ Clash.Class.BitPack.Internal: instance Clash.Class.BitPack.Internal.GBitPack a => Clash.Class.BitPack.Internal.GBitPack (GHC.Generics.M1 m d a)
+ Clash.Class.BitPack.Internal: instance GHC.TypeNats.KnownNat n => Clash.Class.BitPack.Internal.BitPack (Clash.Sized.Internal.BitVector.BitVector n)
+ Clash.Class.BitPack.Internal: isLike :: BitPack a => a -> a -> Bool
+ Clash.Class.BitPack.Internal: pack :: (BitPack a, Generic a, GBitPack (Rep a), KnownNat (BitSize a), KnownNat constrSize, KnownNat fieldSize, constrSize ~ CLog 2 (GConstructorCount (Rep a)), fieldSize ~ GFieldSize (Rep a), (constrSize + fieldSize) ~ BitSize a) => a -> BitVector (BitSize a)
+ Clash.Class.BitPack.Internal: packDouble# :: Double -> BitVector 64
+ Clash.Class.BitPack.Internal: packFloat# :: Float -> BitVector 32
+ Clash.Class.BitPack.Internal: packXWith :: KnownNat n => (a -> BitVector n) -> a -> BitVector n
+ Clash.Class.BitPack.Internal: type BitSize a = (CLog 2 (GConstructorCount (Rep a))) + (GFieldSize (Rep a));
+ Clash.Class.BitPack.Internal: type family GConstructorCount f :: Nat;
+ Clash.Class.BitPack.Internal: unpack :: (BitPack a, Generic a, GBitPack (Rep a), KnownNat constrSize, KnownNat fieldSize, constrSize ~ CLog 2 (GConstructorCount (Rep a)), fieldSize ~ GFieldSize (Rep a), (constrSize + fieldSize) ~ BitSize a) => BitVector (BitSize a) -> a
+ Clash.Class.BitPack.Internal: unpackDouble# :: BitVector 64 -> Double
+ Clash.Class.BitPack.Internal: unpackFloat# :: BitVector 32 -> Float
+ Clash.Class.BitPack.Internal: }
+ Clash.Class.BitPack.Internal.TH: deriveBitPackTuples :: Name -> Name -> Name -> Name -> DecsQ
+ Clash.Class.Counter: class Counter a
+ Clash.Class.Counter: countPred :: Counter a => a -> a
+ Clash.Class.Counter: countSucc :: Counter a => a -> a
+ Clash.Class.Counter.Internal: class Counter a
+ Clash.Class.Counter.Internal: countMax :: (Counter a, Bounded a) => a
+ Clash.Class.Counter.Internal: countMin :: (Counter a, Bounded a) => a
+ Clash.Class.Counter.Internal: countPredOverflow :: (Counter a, Eq a, Enum a, Bounded a) => a -> (Bool, a)
+ Clash.Class.Counter.Internal: countSuccOverflow :: (Counter a, Eq a, Enum a, Bounded a) => a -> (Bool, a)
+ Clash.Class.Counter.Internal: instance (1 GHC.TypeNats.<= n, GHC.TypeNats.KnownNat n) => Clash.Class.Counter.Internal.Counter (Clash.Sized.Internal.Index.Index n)
+ Clash.Class.Counter.Internal: instance (Clash.Class.Counter.Internal.Counter a, Clash.Class.Counter.Internal.Counter b) => Clash.Class.Counter.Internal.Counter (Data.Either.Either a b)
+ Clash.Class.Counter.Internal: instance (Clash.Class.Counter.Internal.Counter a0, Clash.Class.Counter.Internal.Counter a1) => Clash.Class.Counter.Internal.Counter (a0, a1)
+ Clash.Class.Counter.Internal: instance (Clash.Class.Counter.Internal.Counter a0, Clash.Class.Counter.Internal.Counter a1, Clash.Class.Counter.Internal.Counter a2) => Clash.Class.Counter.Internal.Counter (a0, a1, a2)
+ Clash.Class.Counter.Internal: instance GHC.TypeNats.KnownNat n => Clash.Class.Counter.Internal.Counter (Clash.Sized.Internal.BitVector.BitVector n)
+ Clash.Class.Counter.Internal: instance GHC.TypeNats.KnownNat n => Clash.Class.Counter.Internal.Counter (Clash.Sized.Internal.Signed.Signed n)
+ Clash.Class.Counter.Internal: instance GHC.TypeNats.KnownNat n => Clash.Class.Counter.Internal.Counter (Clash.Sized.Internal.Unsigned.Unsigned n)
+ Clash.Class.Counter.TH: countMaxName :: Name
+ Clash.Class.Counter.TH: countMinName :: Name
+ Clash.Class.Counter.TH: countPredName :: Name
+ Clash.Class.Counter.TH: countSuccName :: Name
+ Clash.Class.Counter.TH: counterName :: Name
+ Clash.Class.Counter.TH: genCount :: Name -> Int -> Clause
+ Clash.Class.Counter.TH: genCountOverflow :: Name -> Int -> Q Clause
+ Clash.Class.Counter.TH: genTupleInstance :: Int -> Q Dec
+ Clash.Class.Counter.TH: genTupleInstances :: Int -> Q [Dec]
+ Clash.Class.Counter.TH: mkTup :: [Exp] -> Exp
+ Clash.Class.Counter.TH: mkTupTy :: [Type] -> Type
+ Clash.Class.Num: SatError :: SaturationMode
+ Clash.Examples.Internal: RxReg :: BitVector 8 -> BitVector 8 -> Unsigned 4 -> Unsigned 4 -> Bool -> Bool -> Bool -> Bit -> Bit -> Bool -> RxReg
+ Clash.Examples.Internal: TxReg :: BitVector 8 -> Bool -> Bool -> Bit -> Unsigned 4 -> TxReg
+ Clash.Examples.Internal: [_rx_busy] :: RxReg -> Bool
+ Clash.Examples.Internal: [_rx_cnt] :: RxReg -> Unsigned 4
+ Clash.Examples.Internal: [_rx_d1] :: RxReg -> Bit
+ Clash.Examples.Internal: [_rx_d2] :: RxReg -> Bit
+ Clash.Examples.Internal: [_rx_data] :: RxReg -> BitVector 8
+ Clash.Examples.Internal: [_rx_empty] :: RxReg -> Bool
+ Clash.Examples.Internal: [_rx_frame_err] :: RxReg -> Bool
+ Clash.Examples.Internal: [_rx_over_run] :: RxReg -> Bool
+ Clash.Examples.Internal: [_rx_reg] :: RxReg -> BitVector 8
+ Clash.Examples.Internal: [_rx_sample_cnt] :: RxReg -> Unsigned 4
+ Clash.Examples.Internal: [_tx_cnt] :: TxReg -> Unsigned 4
+ Clash.Examples.Internal: [_tx_empty] :: TxReg -> Bool
+ Clash.Examples.Internal: [_tx_out] :: TxReg -> Bit
+ Clash.Examples.Internal: [_tx_over_run] :: TxReg -> Bool
+ Clash.Examples.Internal: [_tx_reg] :: TxReg -> BitVector 8
+ Clash.Examples.Internal: crc :: HiddenClockResetEnable dom => Signal dom Bool -> Signal dom Bool -> Signal dom Bit -> Signal dom (BitVector 16)
+ Clash.Examples.Internal: crcT :: (Bits a, BitPack a) => a -> Bit -> a
+ Clash.Examples.Internal: data RxReg
+ Clash.Examples.Internal: data TxReg
+ Clash.Examples.Internal: decoderCase :: Bool -> BitVector 4 -> BitVector 16
+ Clash.Examples.Internal: decoderShift :: Bool -> BitVector 4 -> BitVector 16
+ Clash.Examples.Internal: encoderCase :: Bool -> BitVector 16 -> BitVector 4
+ Clash.Examples.Internal: grayCounter :: HiddenClockResetEnable dom => Signal dom Bool -> Signal dom (BitVector 8)
+ Clash.Examples.Internal: instance Clash.XException.NFDataX Clash.Examples.Internal.RxReg
+ Clash.Examples.Internal: instance Clash.XException.NFDataX Clash.Examples.Internal.TxReg
+ Clash.Examples.Internal: instance GHC.Generics.Generic Clash.Examples.Internal.RxReg
+ Clash.Examples.Internal: instance GHC.Generics.Generic Clash.Examples.Internal.TxReg
+ Clash.Examples.Internal: lfsrF :: HiddenClockResetEnable dom => BitVector 16 -> Signal dom Bit
+ Clash.Examples.Internal: lfsrF' :: BitVector 16 -> BitVector 16
+ Clash.Examples.Internal: lfsrG :: HiddenClockResetEnable dom => BitVector 16 -> Signal dom Bit
+ Clash.Examples.Internal: lfsrGP :: (KnownNat (n + 1), Bits a) => Vec (n + 1) Bool -> Vec (n + 1) a -> Vec (n + 1) a
+ Clash.Examples.Internal: oneHotCounter :: HiddenClockResetEnable dom => Signal dom Bool -> Signal dom (BitVector 8)
+ Clash.Examples.Internal: rx_busy :: Lens' RxReg Bool
+ Clash.Examples.Internal: rx_cnt :: Lens' RxReg (Unsigned 4)
+ Clash.Examples.Internal: rx_d1 :: Lens' RxReg Bit
+ Clash.Examples.Internal: rx_d2 :: Lens' RxReg Bit
+ Clash.Examples.Internal: rx_data :: Lens' RxReg (BitVector 8)
+ Clash.Examples.Internal: rx_empty :: Lens' RxReg Bool
+ Clash.Examples.Internal: rx_frame_err :: Lens' RxReg Bool
+ Clash.Examples.Internal: rx_over_run :: Lens' RxReg Bool
+ Clash.Examples.Internal: rx_reg :: Lens' RxReg (BitVector 8)
+ Clash.Examples.Internal: rx_sample_cnt :: Lens' RxReg (Unsigned 4)
+ Clash.Examples.Internal: tx_cnt :: Lens' TxReg (Unsigned 4)
+ Clash.Examples.Internal: tx_empty :: Lens' TxReg Bool
+ Clash.Examples.Internal: tx_out :: Lens' TxReg Bit
+ Clash.Examples.Internal: tx_over_run :: Lens' TxReg Bool
+ Clash.Examples.Internal: tx_reg :: Lens' TxReg (BitVector 8)
+ Clash.Examples.Internal: uart :: forall (dom :: Domain). (KnownDomain dom, ?clock :: Clock dom, ?enable :: Enable dom, ?reset :: Reset dom) => Signal dom Bool -> Signal dom (BitVector 8) -> Signal dom Bool -> Signal dom Bit -> Signal dom Bool -> Signal dom Bool -> (Signal dom Bit, Signal dom Bool, Signal dom (BitVector 8), Signal dom Bool)
+ Clash.Examples.Internal: uartRX :: RxReg -> Bit -> Bool -> Bool -> RxReg
+ Clash.Examples.Internal: uartTX :: TxReg -> Bool -> BitVector 8 -> Bool -> TxReg
+ Clash.Examples.Internal: upCounter :: HiddenClockResetEnable dom => Signal dom Bool -> Signal dom (Unsigned 8)
+ Clash.Examples.Internal: upCounterLd :: HiddenClockResetEnable dom => Signal dom (Bool, Bool, Unsigned 8) -> Signal dom (Unsigned 8)
+ Clash.Examples.Internal: upCounterLdT :: Num a => a -> (Bool, Bool, a) -> (a, a)
+ Clash.Examples.Internal: upDownCounter :: HiddenClockResetEnable dom => Signal dom Bool -> Signal dom (Unsigned 8)
+ Clash.Explicit.BlockRam: RamNoOp :: RamOp n a
+ Clash.Explicit.BlockRam: RamRead :: Index n -> RamOp n a
+ Clash.Explicit.BlockRam: RamWrite :: Index n -> a -> RamOp n a
+ Clash.Explicit.BlockRam: data RamOp n a
+ Clash.Explicit.BlockRam: instance Clash.XException.NFDataX a => Clash.XException.NFDataX (Clash.Explicit.BlockRam.RamOp n a)
+ Clash.Explicit.BlockRam: instance GHC.Base.Semigroup Clash.Explicit.BlockRam.Conflict
+ Clash.Explicit.BlockRam: instance GHC.Generics.Generic (Clash.Explicit.BlockRam.RamOp n a)
+ Clash.Explicit.BlockRam: instance GHC.Show.Show a => GHC.Show.Show (Clash.Explicit.BlockRam.RamOp n a)
+ Clash.Explicit.BlockRam: trueDualPortBlockRam :: forall nAddrs domA domB a. (HasCallStack, KnownNat nAddrs, KnownDomain domA, KnownDomain domB, NFDataX a) => Clock domA -> Clock domB -> Signal domA (RamOp nAddrs a) -> Signal domB (RamOp nAddrs a) -> (Signal domA a, Signal domB a)
+ Clash.Explicit.BlockRam: trueDualPortBlockRam# :: forall nAddrs domA domB a. (HasCallStack, KnownNat nAddrs, KnownDomain domA, KnownDomain domB, NFDataX a) => Clock domA -> Signal domA Bool -> Signal domA Bool -> Signal domA (Index nAddrs) -> Signal domA a -> Clock domB -> Signal domB Bool -> Signal domB Bool -> Signal domB (Index nAddrs) -> Signal domB a -> (Signal domA a, Signal domB a)
+ Clash.Explicit.BlockRam.Blob: blockRamBlob :: forall dom addr m n. (KnownDomain dom, Enum addr) => Clock dom -> Enable dom -> MemBlob n m -> Signal dom addr -> Signal dom (Maybe (addr, BitVector m)) -> Signal dom (BitVector m)
+ Clash.Explicit.BlockRam.Blob: blockRamBlob# :: forall dom m n. KnownDomain dom => Clock dom -> Enable dom -> MemBlob n m -> Signal dom Int -> Signal dom Bool -> Signal dom Int -> Signal dom (BitVector m) -> Signal dom (BitVector m)
+ Clash.Explicit.BlockRam.Blob: blockRamBlobPow2 :: forall dom m n. (KnownDomain dom, KnownNat n) => Clock dom -> Enable dom -> MemBlob (2 ^ n) m -> Signal dom (Unsigned n) -> Signal dom (Maybe (Unsigned n, BitVector m)) -> Signal dom (BitVector m)
+ Clash.Explicit.BlockRam.Blob: createMemBlob :: forall a f. (Foldable f, BitPack a) => String -> Maybe Bit -> f a -> DecsQ
+ Clash.Explicit.BlockRam.Blob: data MemBlob (n :: Nat) (m :: Nat)
+ Clash.Explicit.BlockRam.Blob: memBlobTH :: forall a f. (Foldable f, BitPack a) => Maybe Bit -> f a -> ExpQ
+ Clash.Explicit.BlockRam.Blob: unpackMemBlob :: forall n m. MemBlob n m -> [BitVector m]
+ Clash.Explicit.BlockRam.File: memFile :: forall a f. (BitPack a, Foldable f, HasCallStack) => Maybe Bit -> f a -> String
+ Clash.Explicit.BlockRam.Internal: [MemBlob] :: (KnownNat n, KnownNat m) => {memBlobRunsLen :: !Int, memBlobRuns :: Addr#, memBlobEndsLen :: !Int, memBlobEnds :: Addr#} -> MemBlob n m
+ Clash.Explicit.BlockRam.Internal: data MemBlob (n :: Nat) (m :: Nat)
+ Clash.Explicit.BlockRam.Internal: instance GHC.Show.Show (Clash.Explicit.BlockRam.Internal.MemBlob n m)
+ Clash.Explicit.BlockRam.Internal: packAsNats :: forall a f. Foldable f => Int -> (a -> Natural) -> f a -> (ByteString, ByteString)
+ Clash.Explicit.BlockRam.Internal: packBVs :: forall a f. (Foldable f, BitPack a) => Maybe Bit -> f a -> Either String (Int, ByteString, ByteString)
+ Clash.Explicit.BlockRam.Internal: unpackEnds :: Int -> Int -> [Word64] -> [Natural]
+ Clash.Explicit.BlockRam.Internal: unpackMemBlob :: forall n m. MemBlob n m -> [BitVector m]
+ Clash.Explicit.BlockRam.Internal: unpackMemBlob0 :: forall n m. MemBlob n m -> IO [BitVector m]
+ Clash.Explicit.BlockRam.Internal: unpackNats :: Int -> Int -> ByteString -> ByteString -> [Natural]
+ Clash.Explicit.BlockRam.Internal: unpackW64s :: ByteString -> [Word64]
+ Clash.Explicit.Prelude: RamNoOp :: RamOp n a
+ Clash.Explicit.Prelude: RamRead :: Index n -> RamOp n a
+ Clash.Explicit.Prelude: RamWrite :: Index n -> a -> RamOp n a
+ Clash.Explicit.Prelude: asyncRomBlob :: Enum addr => MemBlob n m -> addr -> BitVector m
+ Clash.Explicit.Prelude: asyncRomBlobPow2 :: KnownNat n => MemBlob (2 ^ n) m -> Unsigned n -> BitVector m
+ Clash.Explicit.Prelude: blockRamBlob :: forall dom addr m n. (KnownDomain dom, Enum addr) => Clock dom -> Enable dom -> MemBlob n m -> Signal dom addr -> Signal dom (Maybe (addr, BitVector m)) -> Signal dom (BitVector m)
+ Clash.Explicit.Prelude: blockRamBlobPow2 :: forall dom m n. (KnownDomain dom, KnownNat n) => Clock dom -> Enable dom -> MemBlob (2 ^ n) m -> Signal dom (Unsigned n) -> Signal dom (Maybe (Unsigned n, BitVector m)) -> Signal dom (BitVector m)
+ Clash.Explicit.Prelude: createMemBlob :: forall a f. (Foldable f, BitPack a) => String -> Maybe Bit -> f a -> DecsQ
+ Clash.Explicit.Prelude: data MemBlob (n :: Nat) (m :: Nat)
+ Clash.Explicit.Prelude: data RamOp n a
+ Clash.Explicit.Prelude: memBlobTH :: forall a f. (Foldable f, BitPack a) => Maybe Bit -> f a -> ExpQ
+ Clash.Explicit.Prelude: romBlob :: forall dom addr m n. (KnownDomain dom, Enum addr) => Clock dom -> Enable dom -> MemBlob n m -> Signal dom addr -> Signal dom (BitVector m)
+ Clash.Explicit.Prelude: romBlobPow2 :: forall dom m n. (KnownDomain dom, KnownNat n) => Clock dom -> Enable dom -> MemBlob (2 ^ n) m -> Signal dom (Unsigned n) -> Signal dom (BitVector m)
+ Clash.Explicit.Prelude: trueDualPortBlockRam :: forall nAddrs domA domB a. (HasCallStack, KnownNat nAddrs, KnownDomain domA, KnownDomain domB, NFDataX a) => Clock domA -> Clock domB -> Signal domA (RamOp nAddrs a) -> Signal domB (RamOp nAddrs a) -> (Signal domA a, Signal domB a)
+ Clash.Explicit.Prelude: unpackMemBlob :: forall n m. MemBlob n m -> [BitVector m]
+ Clash.Explicit.Prelude.Safe: RamNoOp :: RamOp n a
+ Clash.Explicit.Prelude.Safe: RamRead :: Index n -> RamOp n a
+ Clash.Explicit.Prelude.Safe: RamWrite :: Index n -> a -> RamOp n a
+ Clash.Explicit.Prelude.Safe: asyncRomBlob :: Enum addr => MemBlob n m -> addr -> BitVector m
+ Clash.Explicit.Prelude.Safe: asyncRomBlobPow2 :: KnownNat n => MemBlob (2 ^ n) m -> Unsigned n -> BitVector m
+ Clash.Explicit.Prelude.Safe: blockRamBlob :: forall dom addr m n. (KnownDomain dom, Enum addr) => Clock dom -> Enable dom -> MemBlob n m -> Signal dom addr -> Signal dom (Maybe (addr, BitVector m)) -> Signal dom (BitVector m)
+ Clash.Explicit.Prelude.Safe: blockRamBlobPow2 :: forall dom m n. (KnownDomain dom, KnownNat n) => Clock dom -> Enable dom -> MemBlob (2 ^ n) m -> Signal dom (Unsigned n) -> Signal dom (Maybe (Unsigned n, BitVector m)) -> Signal dom (BitVector m)
+ Clash.Explicit.Prelude.Safe: createMemBlob :: forall a f. (Foldable f, BitPack a) => String -> Maybe Bit -> f a -> DecsQ
+ Clash.Explicit.Prelude.Safe: data MemBlob (n :: Nat) (m :: Nat)
+ Clash.Explicit.Prelude.Safe: data RamOp n a
+ Clash.Explicit.Prelude.Safe: memBlobTH :: forall a f. (Foldable f, BitPack a) => Maybe Bit -> f a -> ExpQ
+ Clash.Explicit.Prelude.Safe: romBlob :: forall dom addr m n. (KnownDomain dom, Enum addr) => Clock dom -> Enable dom -> MemBlob n m -> Signal dom addr -> Signal dom (BitVector m)
+ Clash.Explicit.Prelude.Safe: romBlobPow2 :: forall dom m n. (KnownDomain dom, KnownNat n) => Clock dom -> Enable dom -> MemBlob (2 ^ n) m -> Signal dom (Unsigned n) -> Signal dom (BitVector m)
+ Clash.Explicit.Prelude.Safe: trueDualPortBlockRam :: forall nAddrs domA domB a. (HasCallStack, KnownNat nAddrs, KnownDomain domA, KnownDomain domB, NFDataX a) => Clock domA -> Clock domB -> Signal domA (RamOp nAddrs a) -> Signal domB (RamOp nAddrs a) -> (Signal domA a, Signal domB a)
+ Clash.Explicit.Prelude.Safe: unpackMemBlob :: forall n m. MemBlob n m -> [BitVector m]
+ Clash.Explicit.ROM.Blob: createMemBlob :: forall a f. (Foldable f, BitPack a) => String -> Maybe Bit -> f a -> DecsQ
+ Clash.Explicit.ROM.Blob: data MemBlob (n :: Nat) (m :: Nat)
+ Clash.Explicit.ROM.Blob: memBlobTH :: forall a f. (Foldable f, BitPack a) => Maybe Bit -> f a -> ExpQ
+ Clash.Explicit.ROM.Blob: romBlob :: forall dom addr m n. (KnownDomain dom, Enum addr) => Clock dom -> Enable dom -> MemBlob n m -> Signal dom addr -> Signal dom (BitVector m)
+ Clash.Explicit.ROM.Blob: romBlob# :: forall dom m n. KnownDomain dom => Clock dom -> Enable dom -> MemBlob n m -> Signal dom Int -> Signal dom (BitVector m)
+ Clash.Explicit.ROM.Blob: romBlobPow2 :: forall dom m n. (KnownDomain dom, KnownNat n) => Clock dom -> Enable dom -> MemBlob (2 ^ n) m -> Signal dom (Unsigned n) -> Signal dom (BitVector m)
+ Clash.Explicit.ROM.Blob: unpackMemBlob :: forall n m. MemBlob n m -> [BitVector m]
+ Clash.Explicit.ROM.File: memFile :: forall a f. (BitPack a, Foldable f, HasCallStack) => Maybe Bit -> f a -> String
+ Clash.Explicit.Signal: andEnable :: Enable dom -> Signal dom Bool -> Enable dom
+ Clash.Explicit.Signal: runUntil :: forall dom a. (KnownDomain dom, NFDataX a, ShowX a) => (a -> Bool) -> Signal dom a -> IO ()
+ Clash.Explicit.Signal.Delayed: forward :: SNat d -> DSignal dom n a -> DSignal dom (n + d) a
+ Clash.Explicit.Testbench: outputVerifierWith :: forall l a testDom circuitDom. (KnownNat l, KnownDomain testDom, KnownDomain circuitDom, Eq a, ShowX a, 1 <= l) => (Clock testDom -> Reset testDom -> Signal testDom a -> Signal testDom a -> Signal testDom Bool -> Signal testDom Bool) -> Clock testDom -> Reset testDom -> Vec l a -> Signal circuitDom a -> Signal testDom Bool
+ Clash.Explicit.Testbench: unsafeSimSynchronizer :: forall dom1 dom2 a. (KnownDomain dom1, KnownDomain dom2) => Clock dom1 -> Clock dom2 -> Signal dom1 a -> Signal dom2 a
+ Clash.Explicit.Verification: YosysFormal :: RenderAs
+ Clash.Explicit.Verification: assume :: AssertionValue dom a => a -> Property dom
+ Clash.Explicit.Verification: eventually :: AssertionValue dom a => a -> Assertion dom
+ Clash.Num.Erroring: data Erroring a
+ Clash.Num.Erroring: instance (GHC.Enum.Bounded a, GHC.Classes.Ord a, Clash.Class.Num.SaturatingNum a) => GHC.Num.Num (Clash.Num.Erroring.Erroring a)
+ Clash.Num.Erroring: instance (GHC.Enum.Enum a, Clash.Class.Num.SaturatingNum a) => GHC.Enum.Enum (Clash.Num.Erroring.Erroring a)
+ Clash.Num.Erroring: instance (GHC.Real.Fractional a, GHC.Classes.Ord a, Clash.Class.Num.SaturatingNum a) => GHC.Real.Fractional (Clash.Num.Erroring.Erroring a)
+ Clash.Num.Erroring: instance (GHC.Real.Integral a, Clash.Class.Num.SaturatingNum a) => GHC.Real.Integral (Clash.Num.Erroring.Erroring a)
+ Clash.Num.Erroring: instance (GHC.Real.Real a, Clash.Class.Num.SaturatingNum a) => GHC.Real.Real (Clash.Num.Erroring.Erroring a)
+ Clash.Num.Erroring: instance (GHC.Real.RealFrac a, Clash.Class.Num.SaturatingNum a) => GHC.Real.RealFrac (Clash.Num.Erroring.Erroring a)
+ Clash.Num.Erroring: instance Clash.Class.BitPack.Internal.BitPack a => Clash.Class.BitPack.Internal.BitPack (Clash.Num.Erroring.Erroring a)
+ Clash.Num.Erroring: instance Clash.Class.Parity.Parity a => Clash.Class.Parity.Parity (Clash.Num.Erroring.Erroring a)
+ Clash.Num.Erroring: instance Clash.Class.Resize.Resize f => Clash.Class.Resize.Resize (Data.Functor.Compose.Compose Clash.Num.Erroring.Erroring f)
+ Clash.Num.Erroring: instance Clash.XException.NFDataX a => Clash.XException.NFDataX (Clash.Num.Erroring.Erroring a)
+ Clash.Num.Erroring: instance Clash.XException.ShowX a => Clash.XException.ShowX (Clash.Num.Erroring.Erroring a)
+ Clash.Num.Erroring: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Clash.Num.Erroring.Erroring a)
+ Clash.Num.Erroring: instance Data.Binary.Class.Binary a => Data.Binary.Class.Binary (Clash.Num.Erroring.Erroring a)
+ Clash.Num.Erroring: instance Data.Bits.Bits a => Data.Bits.Bits (Clash.Num.Erroring.Erroring a)
+ Clash.Num.Erroring: instance Data.Bits.FiniteBits a => Data.Bits.FiniteBits (Clash.Num.Erroring.Erroring a)
+ Clash.Num.Erroring: instance Data.Hashable.Class.Hashable a => Data.Hashable.Class.Hashable (Clash.Num.Erroring.Erroring a)
+ Clash.Num.Erroring: instance GHC.Classes.Eq a => GHC.Classes.Eq (Clash.Num.Erroring.Erroring a)
+ Clash.Num.Erroring: instance GHC.Classes.Ord a => GHC.Classes.Ord (Clash.Num.Erroring.Erroring a)
+ Clash.Num.Erroring: instance GHC.Enum.Bounded a => GHC.Enum.Bounded (Clash.Num.Erroring.Erroring a)
+ Clash.Num.Erroring: instance GHC.Show.Show a => GHC.Show.Show (Clash.Num.Erroring.Erroring a)
+ Clash.Num.Erroring: toErroring :: SaturatingNum a => a -> Erroring a
+ Clash.Num.Overflowing: clearOverflow :: Overflowing a -> Overflowing a
+ Clash.Num.Overflowing: data Overflowing a
+ Clash.Num.Overflowing: instance (Clash.Class.BitPack.Internal.BitPack a, GHC.TypeNats.KnownNat (Clash.Class.BitPack.Internal.BitSize a GHC.TypeNats.+ 1)) => Clash.Class.BitPack.Internal.BitPack (Clash.Num.Overflowing.Overflowing a)
+ Clash.Num.Overflowing: instance (GHC.Enum.Bounded a, GHC.Classes.Ord a, Clash.Class.Num.SaturatingNum a) => GHC.Num.Num (Clash.Num.Overflowing.Overflowing a)
+ Clash.Num.Overflowing: instance (GHC.Enum.Enum a, GHC.Classes.Eq a, Clash.Class.Num.SaturatingNum a) => GHC.Enum.Enum (Clash.Num.Overflowing.Overflowing a)
+ Clash.Num.Overflowing: instance (GHC.Real.Fractional a, GHC.Classes.Ord a, Clash.Class.Num.SaturatingNum a) => GHC.Real.Fractional (Clash.Num.Overflowing.Overflowing a)
+ Clash.Num.Overflowing: instance (GHC.Real.Integral a, Clash.Class.Num.SaturatingNum a) => GHC.Real.Integral (Clash.Num.Overflowing.Overflowing a)
+ Clash.Num.Overflowing: instance (GHC.Real.Real a, Clash.Class.Num.SaturatingNum a) => GHC.Real.Real (Clash.Num.Overflowing.Overflowing a)
+ Clash.Num.Overflowing: instance (GHC.Real.RealFrac a, Clash.Class.Num.SaturatingNum a) => GHC.Real.RealFrac (Clash.Num.Overflowing.Overflowing a)
+ Clash.Num.Overflowing: instance Clash.Class.Parity.Parity a => Clash.Class.Parity.Parity (Clash.Num.Overflowing.Overflowing a)
+ Clash.Num.Overflowing: instance Clash.XException.NFDataX a => Clash.XException.NFDataX (Clash.Num.Overflowing.Overflowing a)
+ Clash.Num.Overflowing: instance Clash.XException.ShowX a => Clash.XException.ShowX (Clash.Num.Overflowing.Overflowing a)
+ Clash.Num.Overflowing: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Clash.Num.Overflowing.Overflowing a)
+ Clash.Num.Overflowing: instance Data.Binary.Class.Binary a => Data.Binary.Class.Binary (Clash.Num.Overflowing.Overflowing a)
+ Clash.Num.Overflowing: instance Data.Hashable.Class.Hashable a => Data.Hashable.Class.Hashable (Clash.Num.Overflowing.Overflowing a)
+ Clash.Num.Overflowing: instance GHC.Classes.Eq a => GHC.Classes.Eq (Clash.Num.Overflowing.Overflowing a)
+ Clash.Num.Overflowing: instance GHC.Classes.Ord a => GHC.Classes.Ord (Clash.Num.Overflowing.Overflowing a)
+ Clash.Num.Overflowing: instance GHC.Enum.Bounded a => GHC.Enum.Bounded (Clash.Num.Overflowing.Overflowing a)
+ Clash.Num.Overflowing: instance GHC.Generics.Generic (Clash.Num.Overflowing.Overflowing a)
+ Clash.Num.Overflowing: instance GHC.Show.Show a => GHC.Show.Show (Clash.Num.Overflowing.Overflowing a)
+ Clash.Num.Overflowing: toOverflowing :: a -> Overflowing a
+ Clash.Num.Saturating: data Saturating a
+ Clash.Num.Saturating: instance (GHC.Classes.Ord a, Clash.Class.Num.SaturatingNum a) => GHC.Num.Num (Clash.Num.Saturating.Saturating a)
+ Clash.Num.Saturating: instance (GHC.Classes.Ord a, GHC.Real.RealFrac a, Clash.Class.Num.SaturatingNum a) => GHC.Real.RealFrac (Clash.Num.Saturating.Saturating a)
+ Clash.Num.Saturating: instance (GHC.Enum.Enum a, Clash.Class.Num.SaturatingNum a) => GHC.Enum.Enum (Clash.Num.Saturating.Saturating a)
+ Clash.Num.Saturating: instance (GHC.Real.Fractional a, GHC.Classes.Ord a, Clash.Class.Num.SaturatingNum a) => GHC.Real.Fractional (Clash.Num.Saturating.Saturating a)
+ Clash.Num.Saturating: instance (GHC.Real.Integral a, Clash.Class.Num.SaturatingNum a) => GHC.Real.Integral (Clash.Num.Saturating.Saturating a)
+ Clash.Num.Saturating: instance (GHC.Real.Real a, Clash.Class.Num.SaturatingNum a) => GHC.Real.Real (Clash.Num.Saturating.Saturating a)
+ Clash.Num.Saturating: instance Clash.Class.BitPack.Internal.BitPack a => Clash.Class.BitPack.Internal.BitPack (Clash.Num.Saturating.Saturating a)
+ Clash.Num.Saturating: instance Clash.Class.Parity.Parity a => Clash.Class.Parity.Parity (Clash.Num.Saturating.Saturating a)
+ Clash.Num.Saturating: instance Clash.Class.Resize.Resize f => Clash.Class.Resize.Resize (Data.Functor.Compose.Compose Clash.Num.Saturating.Saturating f)
+ Clash.Num.Saturating: instance Clash.XException.NFDataX a => Clash.XException.NFDataX (Clash.Num.Saturating.Saturating a)
+ Clash.Num.Saturating: instance Clash.XException.ShowX a => Clash.XException.ShowX (Clash.Num.Saturating.Saturating a)
+ Clash.Num.Saturating: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Clash.Num.Saturating.Saturating a)
+ Clash.Num.Saturating: instance Data.Binary.Class.Binary a => Data.Binary.Class.Binary (Clash.Num.Saturating.Saturating a)
+ Clash.Num.Saturating: instance Data.Bits.Bits a => Data.Bits.Bits (Clash.Num.Saturating.Saturating a)
+ Clash.Num.Saturating: instance Data.Bits.FiniteBits a => Data.Bits.FiniteBits (Clash.Num.Saturating.Saturating a)
+ Clash.Num.Saturating: instance Data.Hashable.Class.Hashable a => Data.Hashable.Class.Hashable (Clash.Num.Saturating.Saturating a)
+ Clash.Num.Saturating: instance GHC.Classes.Eq a => GHC.Classes.Eq (Clash.Num.Saturating.Saturating a)
+ Clash.Num.Saturating: instance GHC.Classes.Ord a => GHC.Classes.Ord (Clash.Num.Saturating.Saturating a)
+ Clash.Num.Saturating: instance GHC.Enum.Bounded a => GHC.Enum.Bounded (Clash.Num.Saturating.Saturating a)
+ Clash.Num.Saturating: instance GHC.Show.Show a => GHC.Show.Show (Clash.Num.Saturating.Saturating a)
+ Clash.Num.Saturating: toSaturating :: SaturatingNum a => a -> Saturating a
+ Clash.Num.Wrapping: data Wrapping a
+ Clash.Num.Wrapping: instance (GHC.Enum.Enum a, Clash.Class.Num.SaturatingNum a) => GHC.Enum.Enum (Clash.Num.Wrapping.Wrapping a)
+ Clash.Num.Wrapping: instance (GHC.Real.Fractional a, Clash.Class.Num.SaturatingNum a) => GHC.Real.Fractional (Clash.Num.Wrapping.Wrapping a)
+ Clash.Num.Wrapping: instance (GHC.Real.Integral a, Clash.Class.Num.SaturatingNum a) => GHC.Real.Integral (Clash.Num.Wrapping.Wrapping a)
+ Clash.Num.Wrapping: instance (GHC.Real.Real a, Clash.Class.Num.SaturatingNum a) => GHC.Real.Real (Clash.Num.Wrapping.Wrapping a)
+ Clash.Num.Wrapping: instance (GHC.Real.RealFrac a, Clash.Class.Num.SaturatingNum a) => GHC.Real.RealFrac (Clash.Num.Wrapping.Wrapping a)
+ Clash.Num.Wrapping: instance Clash.Class.BitPack.Internal.BitPack a => Clash.Class.BitPack.Internal.BitPack (Clash.Num.Wrapping.Wrapping a)
+ Clash.Num.Wrapping: instance Clash.Class.Num.SaturatingNum a => GHC.Num.Num (Clash.Num.Wrapping.Wrapping a)
+ Clash.Num.Wrapping: instance Clash.Class.Parity.Parity a => Clash.Class.Parity.Parity (Clash.Num.Wrapping.Wrapping a)
+ Clash.Num.Wrapping: instance Clash.Class.Resize.Resize f => Clash.Class.Resize.Resize (Data.Functor.Compose.Compose Clash.Num.Wrapping.Wrapping f)
+ Clash.Num.Wrapping: instance Clash.XException.NFDataX a => Clash.XException.NFDataX (Clash.Num.Wrapping.Wrapping a)
+ Clash.Num.Wrapping: instance Clash.XException.ShowX a => Clash.XException.ShowX (Clash.Num.Wrapping.Wrapping a)
+ Clash.Num.Wrapping: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Clash.Num.Wrapping.Wrapping a)
+ Clash.Num.Wrapping: instance Data.Binary.Class.Binary a => Data.Binary.Class.Binary (Clash.Num.Wrapping.Wrapping a)
+ Clash.Num.Wrapping: instance Data.Bits.Bits a => Data.Bits.Bits (Clash.Num.Wrapping.Wrapping a)
+ Clash.Num.Wrapping: instance Data.Bits.FiniteBits a => Data.Bits.FiniteBits (Clash.Num.Wrapping.Wrapping a)
+ Clash.Num.Wrapping: instance Data.Hashable.Class.Hashable a => Data.Hashable.Class.Hashable (Clash.Num.Wrapping.Wrapping a)
+ Clash.Num.Wrapping: instance GHC.Classes.Eq a => GHC.Classes.Eq (Clash.Num.Wrapping.Wrapping a)
+ Clash.Num.Wrapping: instance GHC.Classes.Ord a => GHC.Classes.Ord (Clash.Num.Wrapping.Wrapping a)
+ Clash.Num.Wrapping: instance GHC.Enum.Bounded a => GHC.Enum.Bounded (Clash.Num.Wrapping.Wrapping a)
+ Clash.Num.Wrapping: instance GHC.Show.Show a => GHC.Show.Show (Clash.Num.Wrapping.Wrapping a)
+ Clash.Num.Wrapping: toWrapping :: SaturatingNum a => a -> Wrapping a
+ Clash.Num.Zeroing: data Zeroing a
+ Clash.Num.Zeroing: instance (GHC.Enum.Bounded a, GHC.Classes.Ord a, Clash.Class.Num.SaturatingNum a) => GHC.Num.Num (Clash.Num.Zeroing.Zeroing a)
+ Clash.Num.Zeroing: instance (GHC.Enum.Enum a, Clash.Class.Num.SaturatingNum a) => GHC.Enum.Enum (Clash.Num.Zeroing.Zeroing a)
+ Clash.Num.Zeroing: instance (GHC.Real.Fractional a, GHC.Classes.Ord a, Clash.Class.Num.SaturatingNum a) => GHC.Real.Fractional (Clash.Num.Zeroing.Zeroing a)
+ Clash.Num.Zeroing: instance (GHC.Real.Integral a, Clash.Class.Num.SaturatingNum a) => GHC.Real.Integral (Clash.Num.Zeroing.Zeroing a)
+ Clash.Num.Zeroing: instance (GHC.Real.Real a, Clash.Class.Num.SaturatingNum a) => GHC.Real.Real (Clash.Num.Zeroing.Zeroing a)
+ Clash.Num.Zeroing: instance (GHC.Real.RealFrac a, Clash.Class.Num.SaturatingNum a) => GHC.Real.RealFrac (Clash.Num.Zeroing.Zeroing a)
+ Clash.Num.Zeroing: instance Clash.Class.BitPack.Internal.BitPack a => Clash.Class.BitPack.Internal.BitPack (Clash.Num.Zeroing.Zeroing a)
+ Clash.Num.Zeroing: instance Clash.Class.Parity.Parity a => Clash.Class.Parity.Parity (Clash.Num.Zeroing.Zeroing a)
+ Clash.Num.Zeroing: instance Clash.Class.Resize.Resize f => Clash.Class.Resize.Resize (Data.Functor.Compose.Compose Clash.Num.Zeroing.Zeroing f)
+ Clash.Num.Zeroing: instance Clash.XException.NFDataX a => Clash.XException.NFDataX (Clash.Num.Zeroing.Zeroing a)
+ Clash.Num.Zeroing: instance Clash.XException.ShowX a => Clash.XException.ShowX (Clash.Num.Zeroing.Zeroing a)
+ Clash.Num.Zeroing: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Clash.Num.Zeroing.Zeroing a)
+ Clash.Num.Zeroing: instance Data.Binary.Class.Binary a => Data.Binary.Class.Binary (Clash.Num.Zeroing.Zeroing a)
+ Clash.Num.Zeroing: instance Data.Bits.Bits a => Data.Bits.Bits (Clash.Num.Zeroing.Zeroing a)
+ Clash.Num.Zeroing: instance Data.Bits.FiniteBits a => Data.Bits.FiniteBits (Clash.Num.Zeroing.Zeroing a)
+ Clash.Num.Zeroing: instance Data.Hashable.Class.Hashable a => Data.Hashable.Class.Hashable (Clash.Num.Zeroing.Zeroing a)
+ Clash.Num.Zeroing: instance GHC.Classes.Eq a => GHC.Classes.Eq (Clash.Num.Zeroing.Zeroing a)
+ Clash.Num.Zeroing: instance GHC.Classes.Ord a => GHC.Classes.Ord (Clash.Num.Zeroing.Zeroing a)
+ Clash.Num.Zeroing: instance GHC.Enum.Bounded a => GHC.Enum.Bounded (Clash.Num.Zeroing.Zeroing a)
+ Clash.Num.Zeroing: instance GHC.Show.Show a => GHC.Show.Show (Clash.Num.Zeroing.Zeroing a)
+ Clash.Num.Zeroing: toZeroing :: SaturatingNum a => a -> Zeroing a
+ Clash.Prelude: RamNoOp :: RamOp n a
+ Clash.Prelude: RamRead :: Index n -> RamOp n a
+ Clash.Prelude: RamWrite :: Index n -> a -> RamOp n a
+ Clash.Prelude: andEnable :: forall dom r. HiddenEnable dom => Signal dom Bool -> (HiddenEnable dom => r) -> r
+ Clash.Prelude: asyncRomBlob :: Enum addr => MemBlob n m -> addr -> BitVector m
+ Clash.Prelude: asyncRomBlobPow2 :: KnownNat n => MemBlob (2 ^ n) m -> Unsigned n -> BitVector m
+ Clash.Prelude: blockRamBlob :: forall dom addr m n. (HiddenClock dom, HiddenEnable dom, Enum addr) => MemBlob n m -> Signal dom addr -> Signal dom (Maybe (addr, BitVector m)) -> Signal dom (BitVector m)
+ Clash.Prelude: blockRamBlobPow2 :: forall dom m n. (HiddenClock dom, HiddenEnable dom, KnownNat n) => MemBlob (2 ^ n) m -> Signal dom (Unsigned n) -> Signal dom (Maybe (Unsigned n, BitVector m)) -> Signal dom (BitVector m)
+ Clash.Prelude: createMemBlob :: forall a f. (Foldable f, BitPack a) => String -> Maybe Bit -> f a -> DecsQ
+ Clash.Prelude: data MemBlob (n :: Nat) (m :: Nat)
+ Clash.Prelude: data RamOp n a
+ Clash.Prelude: memBlobTH :: forall a f. (Foldable f, BitPack a) => Maybe Bit -> f a -> ExpQ
+ Clash.Prelude: romBlob :: forall dom addr m n. (HiddenClock dom, HiddenEnable dom, Enum addr) => MemBlob n m -> Signal dom addr -> Signal dom (BitVector m)
+ Clash.Prelude: romBlobPow2 :: forall dom m n. (HiddenClock dom, HiddenEnable dom, KnownNat n) => MemBlob (2 ^ n) m -> Signal dom (Unsigned n) -> Signal dom (BitVector m)
+ Clash.Prelude: runUntil :: forall dom a. (KnownDomain dom, NFDataX a, ShowX a) => (a -> Bool) -> (HiddenClockResetEnable dom => Signal dom a) -> IO ()
+ Clash.Prelude: trueDualPortBlockRam :: forall nAddrs dom a. (HasCallStack, KnownNat nAddrs, HiddenClock dom, NFDataX a) => Signal dom (RamOp nAddrs a) -> Signal dom (RamOp nAddrs a) -> (Signal dom a, Signal dom a)
+ Clash.Prelude: unpackMemBlob :: forall n m. MemBlob n m -> [BitVector m]
+ Clash.Prelude.BlockRam: RamNoOp :: RamOp n a
+ Clash.Prelude.BlockRam: RamRead :: Index n -> RamOp n a
+ Clash.Prelude.BlockRam: RamWrite :: Index n -> a -> RamOp n a
+ Clash.Prelude.BlockRam: data RamOp n a
+ Clash.Prelude.BlockRam: trueDualPortBlockRam :: forall nAddrs dom a. (HasCallStack, KnownNat nAddrs, HiddenClock dom, NFDataX a) => Signal dom (RamOp nAddrs a) -> Signal dom (RamOp nAddrs a) -> (Signal dom a, Signal dom a)
+ Clash.Prelude.BlockRam.Blob: blockRamBlob :: forall dom addr m n. (HiddenClock dom, HiddenEnable dom, Enum addr) => MemBlob n m -> Signal dom addr -> Signal dom (Maybe (addr, BitVector m)) -> Signal dom (BitVector m)
+ Clash.Prelude.BlockRam.Blob: blockRamBlobPow2 :: forall dom m n. (HiddenClock dom, HiddenEnable dom, KnownNat n) => MemBlob (2 ^ n) m -> Signal dom (Unsigned n) -> Signal dom (Maybe (Unsigned n, BitVector m)) -> Signal dom (BitVector m)
+ Clash.Prelude.BlockRam.Blob: createMemBlob :: forall a f. (Foldable f, BitPack a) => String -> Maybe Bit -> f a -> DecsQ
+ Clash.Prelude.BlockRam.Blob: data MemBlob (n :: Nat) (m :: Nat)
+ Clash.Prelude.BlockRam.Blob: memBlobTH :: forall a f. (Foldable f, BitPack a) => Maybe Bit -> f a -> ExpQ
+ Clash.Prelude.BlockRam.Blob: unpackMemBlob :: forall n m. MemBlob n m -> [BitVector m]
+ Clash.Prelude.BlockRam.File: memFile :: forall a f. (BitPack a, Foldable f, HasCallStack) => Maybe Bit -> f a -> String
+ Clash.Prelude.ROM.Blob: asyncRomBlob :: Enum addr => MemBlob n m -> addr -> BitVector m
+ Clash.Prelude.ROM.Blob: asyncRomBlob# :: forall m n. MemBlob n m -> Int -> BitVector m
+ Clash.Prelude.ROM.Blob: asyncRomBlobPow2 :: KnownNat n => MemBlob (2 ^ n) m -> Unsigned n -> BitVector m
+ Clash.Prelude.ROM.Blob: createMemBlob :: forall a f. (Foldable f, BitPack a) => String -> Maybe Bit -> f a -> DecsQ
+ Clash.Prelude.ROM.Blob: data MemBlob (n :: Nat) (m :: Nat)
+ Clash.Prelude.ROM.Blob: memBlobTH :: forall a f. (Foldable f, BitPack a) => Maybe Bit -> f a -> ExpQ
+ Clash.Prelude.ROM.Blob: romBlob :: forall dom addr m n. (HiddenClock dom, HiddenEnable dom, Enum addr) => MemBlob n m -> Signal dom addr -> Signal dom (BitVector m)
+ Clash.Prelude.ROM.Blob: romBlobPow2 :: forall dom m n. (HiddenClock dom, HiddenEnable dom, KnownNat n) => MemBlob (2 ^ n) m -> Signal dom (Unsigned n) -> Signal dom (BitVector m)
+ Clash.Prelude.ROM.Blob: unpackMemBlob :: forall n m. MemBlob n m -> [BitVector m]
+ Clash.Prelude.ROM.File: memFile :: forall a f. (BitPack a, Foldable f, HasCallStack) => Maybe Bit -> f a -> String
+ Clash.Prelude.Safe: RamNoOp :: RamOp n a
+ Clash.Prelude.Safe: RamRead :: Index n -> RamOp n a
+ Clash.Prelude.Safe: RamWrite :: Index n -> a -> RamOp n a
+ Clash.Prelude.Safe: asyncRomBlob :: Enum addr => MemBlob n m -> addr -> BitVector m
+ Clash.Prelude.Safe: asyncRomBlobPow2 :: KnownNat n => MemBlob (2 ^ n) m -> Unsigned n -> BitVector m
+ Clash.Prelude.Safe: blockRamBlob :: forall dom addr m n. (HiddenClock dom, HiddenEnable dom, Enum addr) => MemBlob n m -> Signal dom addr -> Signal dom (Maybe (addr, BitVector m)) -> Signal dom (BitVector m)
+ Clash.Prelude.Safe: blockRamBlobPow2 :: forall dom m n. (HiddenClock dom, HiddenEnable dom, KnownNat n) => MemBlob (2 ^ n) m -> Signal dom (Unsigned n) -> Signal dom (Maybe (Unsigned n, BitVector m)) -> Signal dom (BitVector m)
+ Clash.Prelude.Safe: createMemBlob :: forall a f. (Foldable f, BitPack a) => String -> Maybe Bit -> f a -> DecsQ
+ Clash.Prelude.Safe: data MemBlob (n :: Nat) (m :: Nat)
+ Clash.Prelude.Safe: data RamOp n a
+ Clash.Prelude.Safe: memBlobTH :: forall a f. (Foldable f, BitPack a) => Maybe Bit -> f a -> ExpQ
+ Clash.Prelude.Safe: romBlob :: forall dom addr m n. (HiddenClock dom, HiddenEnable dom, Enum addr) => MemBlob n m -> Signal dom addr -> Signal dom (BitVector m)
+ Clash.Prelude.Safe: romBlobPow2 :: forall dom m n. (HiddenClock dom, HiddenEnable dom, KnownNat n) => MemBlob (2 ^ n) m -> Signal dom (Unsigned n) -> Signal dom (BitVector m)
+ Clash.Prelude.Safe: trueDualPortBlockRam :: forall nAddrs dom a. (HasCallStack, KnownNat nAddrs, HiddenClock dom, NFDataX a) => Signal dom (RamOp nAddrs a) -> Signal dom (RamOp nAddrs a) -> (Signal dom a, Signal dom a)
+ Clash.Prelude.Safe: unpackMemBlob :: forall n m. MemBlob n m -> [BitVector m]
+ Clash.Signal: andEnable :: forall dom r. HiddenEnable dom => Signal dom Bool -> (HiddenEnable dom => r) -> r
+ Clash.Signal: runUntil :: forall dom a. (KnownDomain dom, NFDataX a, ShowX a) => (a -> Bool) -> (HiddenClockResetEnable dom => Signal dom a) -> IO ()
+ Clash.Signal.Delayed: forward :: SNat d -> DSignal dom n a -> DSignal dom (n + d) a
+ Clash.Signal.Delayed.Internal: forward :: SNat d -> DSignal dom n a -> DSignal dom (n + d) a
+ Clash.Signal.Internal: instance Control.DeepSeq.NFData Clash.Signal.Internal.VDomainConfiguration
+ Clash.Signal.Internal: instance GHC.Generics.Generic Clash.Signal.Internal.VDomainConfiguration
+ Clash.Sized.Fixed: instance Clash.Class.BitPack.Internal.BitPack (rep (int GHC.TypeNats.+ frac)) => Clash.Class.BitPack.Internal.BitPack (Clash.Sized.Fixed.Fixed rep int frac)
+ Clash.Sized.Internal.BitVector: fromEnum# :: forall n. KnownNat n => BitVector n -> Int
+ Clash.Sized.Internal.BitVector: isLike# :: forall n. KnownNat n => BitVector n -> BitVector n -> Bool
+ Clash.Sized.Internal.BitVector: toEnum# :: forall n. KnownNat n => Int -> BitVector n
+ Clash.Sized.Internal.BitVector: toEnum## :: Int -> Bit
+ Clash.Sized.Internal.Index: fromEnum# :: forall n. KnownNat n => Index n -> Int
+ Clash.Sized.Internal.Index: instance (GHC.TypeNats.KnownNat n, 1 GHC.TypeNats.<= n) => Clash.Class.BitPack.Internal.BitPack (Clash.Sized.Internal.Index.Index n)
+ Clash.Sized.Internal.Index: negate# :: KnownNat n => Index n -> Index n
+ Clash.Sized.Internal.Index: toEnum# :: forall n. KnownNat n => Int -> Index n
+ Clash.Sized.Internal.Signed: fromEnum# :: forall n. KnownNat n => Signed n -> Int
+ Clash.Sized.Internal.Signed: instance GHC.TypeNats.KnownNat n => Clash.Class.BitPack.Internal.BitPack (Clash.Sized.Internal.Signed.Signed n)
+ Clash.Sized.Internal.Signed: toEnum# :: forall n. KnownNat n => Int -> Signed n
+ Clash.Sized.Internal.Unsigned: fromEnum# :: forall n. KnownNat n => Unsigned n -> Int
+ Clash.Sized.Internal.Unsigned: instance GHC.TypeNats.KnownNat n => Clash.Class.BitPack.Internal.BitPack (Clash.Sized.Internal.Unsigned.Unsigned n)
+ Clash.Sized.Internal.Unsigned: toEnum# :: forall n. KnownNat n => Int -> Unsigned n
+ Clash.Sized.RTree: instance (GHC.TypeNats.KnownNat d, Clash.Class.BitPack.Internal.BitPack a) => Clash.Class.BitPack.Internal.BitPack (Clash.Sized.RTree.RTree d a)
+ Clash.Sized.Vector: instance (GHC.TypeNats.KnownNat n, Clash.Class.BitPack.Internal.BitPack a) => Clash.Class.BitPack.Internal.BitPack (Clash.Sized.Vector.Vec n a)
+ Clash.Verification: YosysFormal :: RenderAs
+ Clash.Verification: eventually :: AssertionValue dom a => a -> Assertion dom
+ Clash.Verification.Internal: CvAssume :: Assertion' a -> Property' a
+ Clash.Verification.Internal: CvEventually :: Assertion' a -> Assertion' a
+ Clash.Verification.Internal: YosysFormal :: RenderAs
+ Clash.XException: seqErrorX :: a -> b -> b
- Clash.Class.BitPack: -- | Number of constructors this type has. Indirectly indicates how many
+ Clash.Class.BitPack: -- | Number of <a>Bit</a>s needed to represents elements of type <tt>a</tt>
- Clash.Class.BitPack: type family GConstructorCount f :: Nat;
+ Clash.Class.BitPack: type family BitSize a :: Nat;
- Clash.Explicit.BlockRam: blockRam# :: (KnownDomain dom, HasCallStack, NFDataX a) => Clock dom -> Enable dom -> Vec n a -> Signal dom Int -> Signal dom Bool -> Signal dom Int -> Signal dom a -> Signal dom a
+ Clash.Explicit.BlockRam: blockRam# :: forall dom a n. (KnownDomain dom, HasCallStack, NFDataX a) => Clock dom -> Enable dom -> Vec n a -> Signal dom Int -> Signal dom Bool -> Signal dom Int -> Signal dom a -> Signal dom a
- Clash.Explicit.Prelude: asyncFIFOSynchronizer :: (KnownDomain wdom, KnownDomain rdom, 2 <= addrSize) => SNat addrSize -> Clock wdom -> Clock rdom -> Reset wdom -> Reset rdom -> Enable wdom -> Enable rdom -> Signal rdom Bool -> Signal wdom (Maybe a) -> (Signal rdom a, Signal rdom Bool, Signal wdom Bool)
+ Clash.Explicit.Prelude: asyncFIFOSynchronizer :: (KnownDomain wdom, KnownDomain rdom, 2 <= addrSize, NFDataX a) => SNat addrSize -> Clock wdom -> Clock rdom -> Reset wdom -> Reset rdom -> Enable wdom -> Enable rdom -> Signal rdom Bool -> Signal wdom (Maybe a) -> (Signal rdom a, Signal rdom Bool, Signal wdom Bool)
- Clash.Explicit.Prelude: asyncRam :: (Enum addr, HasCallStack, KnownDomain wdom, KnownDomain rdom) => Clock wdom -> Clock rdom -> Enable wdom -> SNat n -> Signal rdom addr -> Signal wdom (Maybe (addr, a)) -> Signal rdom a
+ Clash.Explicit.Prelude: asyncRam :: (Enum addr, HasCallStack, KnownDomain wdom, KnownDomain rdom, NFDataX a) => Clock wdom -> Clock rdom -> Enable wdom -> SNat n -> Signal rdom addr -> Signal wdom (Maybe (addr, a)) -> Signal rdom a
- Clash.Explicit.Prelude: asyncRamPow2 :: forall wdom rdom n a. (KnownNat n, HasCallStack, KnownDomain wdom, KnownDomain rdom) => Clock wdom -> Clock rdom -> Enable wdom -> Signal rdom (Unsigned n) -> Signal wdom (Maybe (Unsigned n, a)) -> Signal rdom a
+ Clash.Explicit.Prelude: asyncRamPow2 :: forall wdom rdom n a. (KnownNat n, HasCallStack, KnownDomain wdom, KnownDomain rdom, NFDataX a) => Clock wdom -> Clock rdom -> Enable wdom -> Signal rdom (Unsigned n) -> Signal wdom (Maybe (Unsigned n, a)) -> Signal rdom a
- Clash.Explicit.Prelude: outputVerifier' :: forall l a dom. (KnownNat l, KnownDomain dom, Eq a, ShowX a) => Clock dom -> Reset dom -> Vec l a -> Signal dom a -> Signal dom Bool
+ Clash.Explicit.Prelude: outputVerifier' :: forall l a dom. (KnownNat l, KnownDomain dom, Eq a, ShowX a, 1 <= l) => Clock dom -> Reset dom -> Vec l a -> Signal dom a -> Signal dom Bool
- Clash.Explicit.Prelude.Safe: asyncFIFOSynchronizer :: (KnownDomain wdom, KnownDomain rdom, 2 <= addrSize) => SNat addrSize -> Clock wdom -> Clock rdom -> Reset wdom -> Reset rdom -> Enable wdom -> Enable rdom -> Signal rdom Bool -> Signal wdom (Maybe a) -> (Signal rdom a, Signal rdom Bool, Signal wdom Bool)
+ Clash.Explicit.Prelude.Safe: asyncFIFOSynchronizer :: (KnownDomain wdom, KnownDomain rdom, 2 <= addrSize, NFDataX a) => SNat addrSize -> Clock wdom -> Clock rdom -> Reset wdom -> Reset rdom -> Enable wdom -> Enable rdom -> Signal rdom Bool -> Signal wdom (Maybe a) -> (Signal rdom a, Signal rdom Bool, Signal wdom Bool)
- Clash.Explicit.Prelude.Safe: asyncRam :: (Enum addr, HasCallStack, KnownDomain wdom, KnownDomain rdom) => Clock wdom -> Clock rdom -> Enable wdom -> SNat n -> Signal rdom addr -> Signal wdom (Maybe (addr, a)) -> Signal rdom a
+ Clash.Explicit.Prelude.Safe: asyncRam :: (Enum addr, HasCallStack, KnownDomain wdom, KnownDomain rdom, NFDataX a) => Clock wdom -> Clock rdom -> Enable wdom -> SNat n -> Signal rdom addr -> Signal wdom (Maybe (addr, a)) -> Signal rdom a
- Clash.Explicit.Prelude.Safe: asyncRamPow2 :: forall wdom rdom n a. (KnownNat n, HasCallStack, KnownDomain wdom, KnownDomain rdom) => Clock wdom -> Clock rdom -> Enable wdom -> Signal rdom (Unsigned n) -> Signal wdom (Maybe (Unsigned n, a)) -> Signal rdom a
+ Clash.Explicit.Prelude.Safe: asyncRamPow2 :: forall wdom rdom n a. (KnownNat n, HasCallStack, KnownDomain wdom, KnownDomain rdom, NFDataX a) => Clock wdom -> Clock rdom -> Enable wdom -> Signal rdom (Unsigned n) -> Signal wdom (Maybe (Unsigned n, a)) -> Signal rdom a
- Clash.Explicit.RAM: asyncRam :: (Enum addr, HasCallStack, KnownDomain wdom, KnownDomain rdom) => Clock wdom -> Clock rdom -> Enable wdom -> SNat n -> Signal rdom addr -> Signal wdom (Maybe (addr, a)) -> Signal rdom a
+ Clash.Explicit.RAM: asyncRam :: (Enum addr, HasCallStack, KnownDomain wdom, KnownDomain rdom, NFDataX a) => Clock wdom -> Clock rdom -> Enable wdom -> SNat n -> Signal rdom addr -> Signal wdom (Maybe (addr, a)) -> Signal rdom a
- Clash.Explicit.RAM: asyncRam# :: forall wdom rdom n a. (HasCallStack, KnownDomain wdom, KnownDomain rdom) => Clock wdom -> Clock rdom -> Enable wdom -> SNat n -> Signal rdom Int -> Signal wdom Bool -> Signal wdom Int -> Signal wdom a -> Signal rdom a
+ Clash.Explicit.RAM: asyncRam# :: forall wdom rdom n a. (HasCallStack, KnownDomain wdom, KnownDomain rdom, NFDataX a) => Clock wdom -> Clock rdom -> Enable wdom -> SNat n -> Signal rdom Int -> Signal wdom Bool -> Signal wdom Int -> Signal wdom a -> Signal rdom a
- Clash.Explicit.RAM: asyncRamPow2 :: forall wdom rdom n a. (KnownNat n, HasCallStack, KnownDomain wdom, KnownDomain rdom) => Clock wdom -> Clock rdom -> Enable wdom -> Signal rdom (Unsigned n) -> Signal wdom (Maybe (Unsigned n, a)) -> Signal rdom a
+ Clash.Explicit.RAM: asyncRamPow2 :: forall wdom rdom n a. (KnownNat n, HasCallStack, KnownDomain wdom, KnownDomain rdom, NFDataX a) => Clock wdom -> Clock rdom -> Enable wdom -> Signal rdom (Unsigned n) -> Signal wdom (Maybe (Unsigned n, a)) -> Signal rdom a
- Clash.Explicit.ROM.File: romFile# :: (KnownNat m, KnownDomain dom) => Clock dom -> Enable dom -> SNat n -> FilePath -> Signal dom Int -> Signal dom (BitVector m)
+ Clash.Explicit.ROM.File: romFile# :: forall m dom n. (KnownNat m, KnownDomain dom) => Clock dom -> Enable dom -> SNat n -> FilePath -> Signal dom Int -> Signal dom (BitVector m)
- Clash.Explicit.Reset: resetSynchronizer :: forall dom. KnownDomain dom => Clock dom -> Reset dom -> Enable dom -> Reset dom
+ Clash.Explicit.Reset: resetSynchronizer :: forall dom. KnownDomain dom => Clock dom -> Reset dom -> Reset dom
- Clash.Explicit.Synchronizer: asyncFIFOSynchronizer :: (KnownDomain wdom, KnownDomain rdom, 2 <= addrSize) => SNat addrSize -> Clock wdom -> Clock rdom -> Reset wdom -> Reset rdom -> Enable wdom -> Enable rdom -> Signal rdom Bool -> Signal wdom (Maybe a) -> (Signal rdom a, Signal rdom Bool, Signal wdom Bool)
+ Clash.Explicit.Synchronizer: asyncFIFOSynchronizer :: (KnownDomain wdom, KnownDomain rdom, 2 <= addrSize, NFDataX a) => SNat addrSize -> Clock wdom -> Clock rdom -> Reset wdom -> Reset rdom -> Enable wdom -> Enable rdom -> Signal rdom Bool -> Signal wdom (Maybe a) -> (Signal rdom a, Signal rdom Bool, Signal wdom Bool)
- Clash.Explicit.Testbench: outputVerifier :: forall l a testDom circuitDom. (KnownNat l, KnownDomain testDom, KnownDomain circuitDom, Eq a, ShowX a) => Clock testDom -> Reset testDom -> Vec l a -> Signal circuitDom a -> Signal testDom Bool
+ Clash.Explicit.Testbench: outputVerifier :: forall l a testDom circuitDom. (KnownNat l, KnownDomain testDom, KnownDomain circuitDom, Eq a, ShowX a, 1 <= l) => Clock testDom -> Reset testDom -> Vec l a -> Signal circuitDom a -> Signal testDom Bool
- Clash.Explicit.Testbench: outputVerifier' :: forall l a dom. (KnownNat l, KnownDomain dom, Eq a, ShowX a) => Clock dom -> Reset dom -> Vec l a -> Signal dom a -> Signal dom Bool
+ Clash.Explicit.Testbench: outputVerifier' :: forall l a dom. (KnownNat l, KnownDomain dom, Eq a, ShowX a, 1 <= l) => Clock dom -> Reset dom -> Vec l a -> Signal dom a -> Signal dom Bool
- Clash.Explicit.Testbench: outputVerifierBitVector :: forall l n testDom circuitDom. (KnownNat l, KnownNat n, KnownDomain testDom, KnownDomain circuitDom) => Clock testDom -> Reset testDom -> Vec l (BitVector n) -> Signal circuitDom (BitVector n) -> Signal testDom Bool
+ Clash.Explicit.Testbench: outputVerifierBitVector :: forall l n testDom circuitDom. (KnownNat l, KnownNat n, KnownDomain testDom, KnownDomain circuitDom, 1 <= l) => Clock testDom -> Reset testDom -> Vec l (BitVector n) -> Signal circuitDom (BitVector n) -> Signal testDom Bool
- Clash.Explicit.Testbench: outputVerifierBitVector' :: forall l n dom. (KnownNat l, KnownNat n, KnownDomain dom) => Clock dom -> Reset dom -> Vec l (BitVector n) -> Signal dom (BitVector n) -> Signal dom Bool
+ Clash.Explicit.Testbench: outputVerifierBitVector' :: forall l n dom. (KnownNat l, KnownNat n, KnownDomain dom, 1 <= l) => Clock dom -> Reset dom -> Vec l (BitVector n) -> Signal dom (BitVector n) -> Signal dom Bool
- Clash.Prelude: asyncRam :: (Enum addr, HiddenClock dom, HiddenEnable dom, HasCallStack) => SNat n -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
+ Clash.Prelude: asyncRam :: (Enum addr, HiddenClock dom, HiddenEnable dom, HasCallStack, NFDataX a) => SNat n -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
- Clash.Prelude: asyncRamPow2 :: (KnownNat n, HiddenClock dom, HiddenEnable dom, HasCallStack) => Signal dom (Unsigned n) -> Signal dom (Maybe (Unsigned n, a)) -> Signal dom a
+ Clash.Prelude: asyncRamPow2 :: (KnownNat n, HiddenClock dom, HiddenEnable dom, HasCallStack, NFDataX a) => Signal dom (Unsigned n) -> Signal dom (Maybe (Unsigned n, a)) -> Signal dom a
- Clash.Prelude: resetSynchronizer :: forall dom. KnownDomain dom => Clock dom -> Reset dom -> Enable dom -> Reset dom
+ Clash.Prelude: resetSynchronizer :: forall dom. KnownDomain dom => Clock dom -> Reset dom -> Reset dom
- Clash.Prelude: type family BitSize a :: Nat;
+ Clash.Prelude: type family Unbundled (dom :: Domain) a = res | res -> dom a;
- Clash.Prelude.RAM: asyncRam :: (Enum addr, HiddenClock dom, HiddenEnable dom, HasCallStack) => SNat n -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
+ Clash.Prelude.RAM: asyncRam :: (Enum addr, HiddenClock dom, HiddenEnable dom, HasCallStack, NFDataX a) => SNat n -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
- Clash.Prelude.RAM: asyncRamPow2 :: (KnownNat n, HiddenClock dom, HiddenEnable dom, HasCallStack) => Signal dom (Unsigned n) -> Signal dom (Maybe (Unsigned n, a)) -> Signal dom a
+ Clash.Prelude.RAM: asyncRamPow2 :: (KnownNat n, HiddenClock dom, HiddenEnable dom, HasCallStack, NFDataX a) => Signal dom (Unsigned n) -> Signal dom (Maybe (Unsigned n, a)) -> Signal dom a
- Clash.Prelude.ROM: asyncRom# :: KnownNat n => Vec n a -> Int -> a
+ Clash.Prelude.ROM: asyncRom# :: forall n a. KnownNat n => Vec n a -> Int -> a
- Clash.Prelude.Safe: asyncRam :: (Enum addr, HiddenClock dom, HiddenEnable dom, HasCallStack) => SNat n -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
+ Clash.Prelude.Safe: asyncRam :: (Enum addr, HiddenClock dom, HiddenEnable dom, HasCallStack, NFDataX a) => SNat n -> Signal dom addr -> Signal dom (Maybe (addr, a)) -> Signal dom a
- Clash.Prelude.Safe: asyncRamPow2 :: (KnownNat n, HiddenClock dom, HiddenEnable dom, HasCallStack) => Signal dom (Unsigned n) -> Signal dom (Maybe (Unsigned n, a)) -> Signal dom a
+ Clash.Prelude.Safe: asyncRamPow2 :: (KnownNat n, HiddenClock dom, HiddenEnable dom, HasCallStack, NFDataX a) => Signal dom (Unsigned n) -> Signal dom (Maybe (Unsigned n, a)) -> Signal dom a
- Clash.Prelude.Testbench: outputVerifier' :: (KnownNat l, Eq a, ShowX a, HiddenClock dom, HiddenReset dom) => Vec l a -> Signal dom a -> Signal dom Bool
+ Clash.Prelude.Testbench: outputVerifier' :: (KnownNat l, Eq a, ShowX a, HiddenClock dom, HiddenReset dom, 1 <= l) => Vec l a -> Signal dom a -> Signal dom Bool
- Clash.Prelude.Testbench: outputVerifierBitVector' :: (KnownNat l, KnownNat n, HiddenClock dom, HiddenReset dom) => Vec l (BitVector n) -> Signal dom (BitVector n) -> Signal dom Bool
+ Clash.Prelude.Testbench: outputVerifierBitVector' :: (KnownNat l, KnownNat n, HiddenClock dom, HiddenReset dom, 1 <= l) => Vec l (BitVector n) -> Signal dom (BitVector n) -> Signal dom Bool
- Clash.Signal: resetSynchronizer :: forall dom. KnownDomain dom => Clock dom -> Reset dom -> Enable dom -> Reset dom
+ Clash.Signal: resetSynchronizer :: forall dom. KnownDomain dom => Clock dom -> Reset dom -> Reset dom
- Clash.Sized.BitVector: bLit :: forall n. KnownNat n => String -> Q (TExp (BitVector n))
+ Clash.Sized.BitVector: bLit :: String -> ExpQ
- Clash.Sized.Internal.BitVector: bLit :: forall n. KnownNat n => String -> Q (TExp (BitVector n))
+ Clash.Sized.Internal.BitVector: bLit :: String -> ExpQ
- Clash.Sized.Internal.Signed: div# :: Signed n -> Signed n -> Signed n
+ Clash.Sized.Internal.Signed: div# :: forall n. KnownNat n => Signed n -> Signed n -> Signed n
- Clash.Sized.Internal.Signed: quot# :: Signed n -> Signed n -> Signed n
+ Clash.Sized.Internal.Signed: quot# :: forall n. KnownNat n => Signed n -> Signed n -> Signed n

Files

CHANGELOG.md view
@@ -1,4 +1,77 @@ # Changelog for the Clash project+## 1.6.0 *Feb 10th 2022*+Added:+  * `Clash.Class.Counter`: a class that defines a odometer-style supercounter. [#1763](https://github.com/clash-lang/clash-compiler/pull/1763)+  * `isLike` function for BitPack types. [#1774](https://github.com/clash-lang/clash-compiler/pull/1774)+  * 'seqErrorX' for catching both `XException` and `ErrorCall`. [#1774](https://github.com/clash-lang/clash-compiler/pull/1774)+  * `Clash.Explicit.BlockRam.File.memFile`, a function for creating the contents of the data files this blockRAM uses. Can also be imported from `Clash.Prelude.BlockRam.File`, `Clash.Prelude.ROM.File` and `Clash.Explicit.ROM.File`. [#1840](https://github.com/clash-lang/clash-compiler/pull/1840)+  * Support for Yosys compatible SVA to `Clash.Verification`. This enables formal verification using SymbiYosis for Verilog and SystemVerilog. [#1798](https://github.com/clash-lang/clash-compiler/pull/1798)+  * `Clash.Explicit.Signal.Delayed.forward`, a function that can be used to retime a `DSignal` into the future without applying any logic. [#1882](https://github.com/clash-lang/clash-compiler/pull/1882)+  * `Clash.Signal.andEnable` is the `HiddenEnable` version of `Clash.Explicit.Signal.andEnable` (formerly known as `enable`) [#1849](https://github.com/clash-lang/clash-compiler/pull/1849)+  * `runUntil`, a function to sample a signal until it returns a value that satisfies the user-given test. It is a convenience function that, among others, allow easy running of a `testBench` style function in Haskell simulation, logging assertion failures to stderr. [#1940](https://github.com/clash-lang/clash-compiler/pull/1940)+  * Support for true dual ported block ram through `Clash.Prelude.BlockRam.trueDualPortBlockRam` and `Clash.Explicit.BlockRam.trueDualPortBlockRam`. [#1726](https://github.com/clash-lang/clash-compiler/pull/1726) [#1975](https://github.com/clash-lang/clash-compiler/pull/1975)+  * `clash-{prelude,lib}-hedgehog` packages which provide generators for types in `clash-prelude` and `clash-lib`. The former is published on Hackage. [#1976](https://github.com/clash-lang/clash-compiler/pull/1976)+  * Clash now contains black boxes which are verilator compatible. When running with `--verilog` or `--systemverilog` a C++ shim is automatically produced which can be used to quickly generate a verilated executable. Users who wish to interact with verilator simulations are recommended to use [clashilator](https://github.com/gergoerdi/clashilator). [#2019](https://github.com/clash-lang/clash-compiler/pull/2019)+  * Support for YAML blackboxes. Clash will now pickup on files with a `.primitives.yaml` extension. While we recommend upgrading your primitive files to the new format, old style primitives are still supported. We've included a tool to automatically upgrade your JSON files, see [#2037](https://github.com/clash-lang/clash-compiler/pull/2037)+  * `MemBlob`: a datastructure for efficient constants, typically used for initializing memories. [#2041](https://github.com/clash-lang/clash-compiler/pull/2041)++Fixed:++  * BlockRam simulation is now less strict. [#1458](https://github.com/clash-lang/clash-compiler/issues/1458)+  * Don't overflow VHDL's integer type when addressing RAM/ROM in simulation.Addresses are masked to 32 bits to be sure to keep it within the simulator's range. [#1875](https://github.com/clash-lang/clash-compiler/pull/1875)+  * `show` on `BitVector 0` no longer results in an empty string. [#1785](https://github.com/clash-lang/clash-compiler/pull/1785)+  * Clash now preserves transfinite floating numbers (NaN, Infinity) when packing/unpacking [#1803](https://github.com/clash-lang/clash-compiler/issues/1803)+  * `SynthesisAnnotation`s can now be defined in type synoynms without being excluded from the generated HDL [#1771](https://github.com/clash-lang/clash-compiler/issues/1771)+  * Manifest files now correctly list bidirectional ports as "inout" rather than "in" [#1843](https://github.com/clash-lang/clash-compiler/issues/1843)+  * `div`/`rem`/`mod` now avoid division by zero during VHDL simulation. Due to the use of concurrent statements, even unreachable code would previously result in simulation error [#1873](https://github.com/clash-lang/clash-compiler/pull/1873)+  * 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)+  * `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)+  * `toEnum`/`fromEnum` on sized types is now less eager to report warnings about integer functions being used [#2046](https://github.com/clash-lang/clash-compiler/issues/2046)++Changed:++  * `Clash.Verification.PrettyPrinters` has been moved from clash-prelude to to `Clash.Verification.Pretty` in `clash-lib`. [#1798](https://github.com/clash-lang/clash-compiler/pull/1798)+  * RAM/ROM functions: They now throw `XExeception` for out-of-bounds address inputs, so this condition no longer aborts simulation. [#1875](https://github.com/clash-lang/clash-compiler/pull/1875)+  * `Vec`'s show instance now generates valid Haskell. [#1776](https://github.com/clash-lang/clash-compiler/issues/1776)+  * `ShowX` and its functions now produce valid Haskell [#1782](https://github.com/clash-lang/clash-compiler/issues/1782)+  * `bLit` now infers the size of the generated BitVector from the string given to it. This means you don't have to give it an explicit type signature anymore. This does slightly modify the syntax needed to invoke `bLit`. E.g., `$$(bLit "00..1") :: BitVector 5` should be rewritten as `$(bLit "00..1")`. If you relied on the size inference, wrap the new invocation in `resize`. For example: `resize $(bLit "00..1")`. [#1784](https://github.com/clash-lang/clash-compiler/pull/1784)+  * `NumericUnderscores` is now enabled by default in `clash`, `clashi`, and starter projects using Clash >=1.6. [#1785](https://github.com/clash-lang/clash-compiler/pull/1785)+  * `Show` instance of `BitVector` now includes a `0b` prefix, making it a copyable expression for fully defined vectors. [#1785](https://github.com/clash-lang/clash-compiler/pull/1785)+  * `blockRam` uses `STArray` as the underlying representation to improve simulation performance [#1878](https://github.com/clash-lang/clash-compiler/pull/1878)+  * `asyncRom` now throws `XException` for out-of-bounds addressing, no longer aborting simulation [#1878](https://github.com/clash-lang/clash-compiler/pull/1878)+  * Clash now renders ADTs with all zero-width fields as enumerations in VHDL [#1879](https://github.com/clash-lang/clash-compiler/pull/1879)+  * A warning about possible hard-to-debug issues has been added to the `Clash.Signal` documentation on hidden clocks, resets, and enables, in the form of the section named "Monomorphism restriction leads to surprising behavior" [#1960](https://github.com/clash-lang/clash-compiler/pull/1960)+  * `Clash.Explicit.Testbench.outputVerifier` and `outputVerifierBitVector` now emit a warning if they are used improperly. This situation only arises when they are used in synthesized code rather than a test bench context. When the clock domains `circuitDom` and `testDom` are two different domains, the clock crossing inside `outputVerifier` is only suitable inside a test bench, not inside a synthesized circuit. Clash now emits a warning for this case. [#1931](https://github.com/clash-lang/clash-compiler/pull/1931)+  * `resetSynchronizer` now no longer takes an `Enable` argument. The argument was already marked for removal and was ignored. [#1964](https://github.com/clash-lang/clash-compiler/pull/1964)+  * Clash can now compile multiple entities concurrently, providing speedups to designs with multiple entities to build [#2034](https://github.com/clash-lang/clash-compiler/pull/2034)+  * All `asyncRam` variants and `asyncFIFOSynchronizer` now require that the data has an `NFDataX` instance. [#2055](https://github.com/clash-lang/clash-compiler/pull/2055)+  * Clash now respects the `-Werror` option from GHC [#2066](https://github.com/clash-lang/clash-compiler/pull/2066)+  * `asyncFIFOSynchronizer` now uses the synchronous dual-ported RAM `trueDualPortBlockRam`, where it previously used a dual-ported RAM with an asynchronous read port `asyncRam`. With this change it's nearly guaranteed that `asyncFIFOSynchronizer` actually synthesizes to a circuit that uses the dual-ported RAMs found on most FPGAs. [#2083](https://github.com/clash-lang/clash-compiler/pull/2083)++Deprecated:+  * The function `Clash.Explicit.Signal.enable` is renamed to `andEnable` and the existing name deprecated [#1849](https://github.com/clash-lang/clash-compiler/pull/1849)+  * '-fclash-float-support': it is now on by default and can't be turned off. [#2048](https://github.com/clash-lang/clash-compiler/pull/2048)++Removed:++  * GHC 8.4 is no longer supported. Users should upgrade to at least GHC 8.6. [#1762](https://github.com/clash-lang/clash-compiler/pull/1762)++Internal changes:+  * `clash-lib` now uses `Data.Monoid.Ap` instead of `Data.Semigroup.Monad.Mon`. This means users defining primitives with `TemplateFunction` will need to replace `Mon`/`getMon` with `Ap`/`getAp`. [#1835](https://github.com/clash-lang/clash-compiler/pull/1835)+  * Clash now supports more expressive debug options at the command line [#1800](https://github.com/clash-lang/clash-compiler/issues/1800).+  * Added `zeroWidthSpec` transformation [#1891](https://github.com/clash-lang/clash-compiler/pull/1891)+  * Added `collapseRHSNoops` inlining stage and `WorkIdentity` constructor [#1896](https://github.com/clash-lang/clash-compiler/pull/1896)+  * Added `HasType` and `InferType` classes for getting / inferring core types from data representing some typed "thing" [#1915](https://github.com/clash-lang/clash-compiler/pull/1915)+  * Added `HasFreeVars` class for getting free variables from data "containing" variables [#1917](https://github.com/clash-lang/clash-compiler/pull/1917)+  * Added the primitive equality type (`~#`) to `Clash.Core.TysPrim`. In order to make this change, `undefinedTy` and `unsafeCoerceTy` were moved from `Clash.Core.Type` to `Clash.Core.Util`. [#1955](https://github.com/clash-lang/clash-compiler/pull/1955)+  * Clash now keeps information about which let bindings are recursive from GHC core. This can be used to avoid performing free variable calculations, or sorting bindings in normalization. [#1980](https://github.com/clash-lang/clash-compiler/pull/1980) [#2000](https://github.com/clash-lang/clash-compiler/pull/2000)+  *  Manifest files now use SHA256 for a cache invalidation digest [#1985](https://github.com/clash-lang/clash-compiler/pull/1985)+ ## 1.4.7 *Jan 30th 2022* Fixed:   * Clash now shows days in time strings for compile runs which take longer than a day [#1989](https://github.com/clash-lang/clash-compiler/compare/issue-1989).
− Setup.hs
@@ -1,25 +0,0 @@-{-# LANGUAGE CPP #-}-{-# OPTIONS_GHC -Wall #-}-module Main (main) where-#ifndef MIN_VERSION_cabal_doctest-#define MIN_VERSION_cabal_doctest(x,y,z) 0-#endif-#if MIN_VERSION_cabal_doctest(1,0,0)-import Distribution.Extra.Doctest ( defaultMainWithDoctests )-main :: IO ()-main = defaultMainWithDoctests "doctests"-#else-#ifdef MIN_VERSION_Cabal--- If the macro is defined, we have new cabal-install,--- but for some reason we don't have cabal-doctest in package-db------ Probably we are running cabal sdist, when otherwise using v2-build--- workflow-#warning You are configuring this package without cabal-doctest installed. \-         The doctests test-suite will not work as a result. \-         To fix this, install cabal-doctest before configuring.-#endif-import Distribution.Simple-main :: IO ()-main = defaultMain-#endif
benchmarks/BenchBitVector.hs view
@@ -1,7 +1,5 @@ {-# LANGUAGE CPP, DataKinds, MagicHash, TypeOperators, TemplateHaskell #-}-#if __GLASGOW_HASKELL__ >= 806 {-# LANGUAGE NoStarIsType #-}-#endif  {-# OPTIONS_GHC -ddump-simpl -ddump-splices -ddump-to-file #-} @@ -12,7 +10,7 @@ import Data.Bits import Clash.Sized.BitVector import Clash.Class.Num-import Clash.Prelude.BitIndex+import Clash.Class.BitPack.BitIndex import GHC.TypeLits                   (type (*)) import Criterion                      (Benchmark, env, bench, nf, bgroup) import Language.Haskell.TH.Syntax     (lift)
benchmarks/BenchRAM.hs view
@@ -1,15 +1,20 @@-{-# LANGUAGE MagicHash, TypeApplications #-}+{-# LANGUAGE MagicHash, TypeApplications, DataKinds #-} module BenchRAM (ramBench) where -import Criterion (Benchmark, env, bench, nf, bgroup)+import Criterion (Benchmark, env, bench, nf, bgroup, envWithCleanup)+import System.Directory+import System.IO  import Clash.Explicit.BlockRam+import Clash.Explicit.BlockRam.File import Clash.Explicit.RAM import Clash.Explicit.ROM import Clash.Explicit.Signal import Clash.Prelude.ROM+import Clash.Promoted.Nat import Clash.Promoted.Nat.Literals import qualified Clash.Sized.Vector as V+import Clash.Sized.Internal.BitVector (undefined#)  ramBench :: Benchmark ramBench = bgroup "RAMs"@@ -17,19 +22,21 @@   , asyncRomBench   , blockRamBench   , blockRamROBench+  , blockRamFileBench+  , blockRamFileROBench   , romBench   ]  asyncRamBench :: Benchmark asyncRamBench = env setup $ \m ->   bench "asyncRam#" $-  nf (take 98 . drop 2 . simulate_lazy+  nf (take 298 . drop 2 . simulate_lazy         (\rw -> let (r,w) = unbundle rw                 in  asyncRam# @System                       clockGen                       clockGen                       enableGen-                      d1024+                      (SNat @4096)                       r                       (pure True)                       w@@ -49,36 +56,82 @@ blockRamBench :: Benchmark blockRamBench = env setup $ \m ->   bench "blockRam# (100% writes)" $-  nf (take 98 . drop 2 . simulate_lazy-        (\w -> blockRam# @System-                    clockGen-                    enableGen-                    ramInit-                    w+  nf (take 8298 . drop 2 . simulate_lazy+        (\w -> ram w                     (pure True)                     w                     w-                   )) m+                   )) (cycle m)   where-    ramInit = V.replicate d1024 (1 :: Int)+    ramInit = V.replicate (SNat @4096) (1 :: Int)     setup   = pure ([557,558..857])+    ram     = blockRam# @System+                    clockGen+                    enableGen+                    ramInit  blockRamROBench :: Benchmark blockRamROBench = env setup $ \m ->   bench "blockRam# (0% writes)" $-  nf (take 98 . drop 2 . simulate_lazy-        (\w -> blockRam# @System-                    clockGen-                    enableGen-                    ramInit-                    w+  nf (take 8298 . drop 2 . simulate_lazy+        (\w -> ram w                     (pure False)                     w                     w-                   )) m+                   )) (cycle m)   where-    ramInit = V.replicate d1024 (1 :: Int)+    ramInit = V.replicate (SNat @4096) (1 :: Int)     setup   = pure ([557,558..857])+    ram     = blockRam# @System+                    clockGen+                    enableGen+                    ramInit++blockRamFileBench :: Benchmark+blockRamFileBench = envWithCleanup setup cleanup $ \(~(m,_,ram)) ->+  bench "blockRamFile# (100% writes)" $+  nf (take 8298 . drop 2 . simulate_lazy+        (\w -> ram  w+                    (pure True)+                    w+                    (pure undefined#)+                   )) (cycle m)+  where+    setup = do+      (fp,h) <- openTempFile "." "mem.bin"+      hPutStr h (unlines (replicate 4096 (replicate 63 '0' ++ ['1'])))+      hClose h+      let ram = blockRamFile# @64 @System+              clockGen+              enableGen+              (SNat @4096)+              fp+      fp `seq` ram `seq` return ([557,558..857],fp,ram)++    cleanup (_,f,_) = removeFile f++blockRamFileROBench :: Benchmark+blockRamFileROBench = envWithCleanup setup cleanup $ \(~(m,_,ram)) ->+  bench "blockRamFile# (0% writes)" $+  nf (take 8298 . drop 2 . simulate_lazy+        (\w -> ram w+                   (pure False)+                   w+                   (pure undefined#)+                   )) (cycle m)+  where+    setup = do+      (fp,h) <- openTempFile "." "mem.bin"+      hPutStr h (unlines (replicate 4096 (replicate 63 '0' ++ ['1'])))+      hClose h+      let ram = blockRamFile# @64 @System+                    clockGen+                    enableGen+                    (SNat @4096)+                    fp+      fp `seq` ram `seq` return ([557,558..857], fp, ram)++    cleanup (_,f,_) = removeFile f  romBench :: Benchmark romBench = env setup $ \m ->
benchmarks/BenchSigned.hs view
@@ -1,7 +1,5 @@ {-# LANGUAGE CPP, DataKinds, MagicHash, TypeOperators, TemplateHaskell #-}-#if __GLASGOW_HASKELL__ >= 806 {-# LANGUAGE NoStarIsType #-}-#endif  {-# OPTIONS_GHC -ddump-simpl -ddump-splices -ddump-to-file #-} 
benchmarks/BenchUnsigned.hs view
@@ -1,7 +1,5 @@ {-# LANGUAGE CPP, DataKinds, MagicHash, TypeOperators, TemplateHaskell #-}-#if __GLASGOW_HASKELL__ >= 806 {-# LANGUAGE NoStarIsType #-}-#endif  {-# OPTIONS_GHC -ddump-simpl -ddump-splices -ddump-to-file #-} 
benchmarks/BenchVector.hs view
@@ -1,7 +1,5 @@ {-# LANGUAGE CPP, DataKinds, MagicHash, TypeOperators, TemplateHaskell #-}-#if __GLASGOW_HASKELL__ >= 806 {-# LANGUAGE NoStarIsType #-}-#endif  {-# OPTIONS_GHC -ddump-simpl -ddump-splices -ddump-to-file #-} 
clash-prelude.cabal view
@@ -1,6 +1,6 @@ Cabal-version:        2.2 Name:                 clash-prelude-Version:              1.4.7+Version:              1.6.0 Synopsis:             Clash: a functional hardware description language - Prelude library Description:   Clash is a functional hardware description language that borrows both its@@ -51,9 +51,9 @@ Copyright:            Copyright © 2013-2016, University of Twente,                                   2016-2017, Myrtle Software Ltd,                                   2017-2019, QBayLogic B.V., Google Inc.,-                                  2020-2022, QBayLogic B.V.+                                  2021-2022, QBayLogic B.V. Category:             Hardware-Build-type:           Custom+Build-type:           Simple  Extra-source-files:   README.md                       CHANGELOG.md@@ -69,8 +69,8 @@ flag large-tuples   description:     Generate instances for classes such as `NFDataX` and `BitPack` for tuples-    up to and including 62 elements - the GHC imposed maximum. This greatly-    increases compile times for `clash-prelude`.+    up to and including 62 elements - the GHC imposed maximum. Note that this+    greatly increases compile times for `clash-prelude`.   default: False   manual: True @@ -96,7 +96,7 @@     experimental feature, possibly triggering confusing error messages. By     default, it is enabled on development versions of Clash and disabled on     releases.-  default: False+  default: True   manual: True  flag doctests@@ -133,6 +133,7 @@                       InstanceSigs                       KindSignatures                       MagicHash+                      NoStarIsType                       ScopedTypeVariables                       StandaloneDeriving                       TupleSections@@ -140,15 +141,6 @@                       TypeOperators                       ViewPatterns -  if impl(ghc >= 8.6)-      default-extensions: NoStarIsType--custom-setup-  setup-depends:-    base          >= 4.9 && <5,-    Cabal         >= 1.10,-    cabal-doctest >= 1.0.1 && <1.1- Library   import:             common-options   HS-Source-Dirs:     src@@ -183,7 +175,15 @@                       Clash.Annotations.TH                        Clash.Class.AutoReg+                      Clash.Class.AutoReg.Internal                       Clash.Class.BitPack+                      Clash.Class.BitPack.BitIndex+                      Clash.Class.BitPack.BitReduction+                      Clash.Class.BitPack.Internal+                      Clash.Class.BitPack.Internal.TH+                      Clash.Class.Counter+                      Clash.Class.Counter.Internal+                      Clash.Class.Counter.TH                       Clash.Class.Exp                       Clash.Class.HasDomain                       Clash.Class.HasDomain.HasSingleDomain@@ -198,12 +198,15 @@                       Clash.Clocks.Deriving                        Clash.Explicit.BlockRam+                      Clash.Explicit.BlockRam.Blob                       Clash.Explicit.BlockRam.File+                      Clash.Explicit.BlockRam.Internal                       Clash.Explicit.DDR                       Clash.Explicit.Mealy                       Clash.Explicit.Moore                       Clash.Explicit.RAM                       Clash.Explicit.ROM+                      Clash.Explicit.ROM.Blob                       Clash.Explicit.ROM.File                       Clash.Explicit.Prelude                       Clash.Explicit.Prelude.Safe@@ -224,18 +227,26 @@                        Clash.Magic +                      Clash.Num.Erroring+                      Clash.Num.Overflowing+                      Clash.Num.Saturating+                      Clash.Num.Wrapping+                      Clash.Num.Zeroing+                       Clash.NamedTypes                        Clash.Prelude                       Clash.Prelude.BitIndex                       Clash.Prelude.BitReduction                       Clash.Prelude.BlockRam+                      Clash.Prelude.BlockRam.Blob                       Clash.Prelude.BlockRam.File                       Clash.Prelude.DataFlow                       Clash.Prelude.Mealy                       Clash.Prelude.Moore                       Clash.Prelude.RAM                       Clash.Prelude.ROM+                      Clash.Prelude.ROM.Blob                       Clash.Prelude.ROM.File                       Clash.Prelude.Safe                       Clash.Prelude.Testbench@@ -272,7 +283,6 @@                        Clash.Verification                       Clash.Verification.DSL-                      Clash.Verification.PrettyPrinters                       Clash.Verification.Internal                        Clash.XException@@ -284,13 +294,11 @@                        Clash.Tutorial                       Clash.Examples+                      Clash.Examples.Internal    other-modules:                       Clash.Class.AutoReg.Instances-                      Clash.Class.AutoReg.Internal-                      Clash.Class.BitPack.Internal                       Clash.CPP-                      Clash.Examples.Internal                       Clash.Signal.Bundle.Internal                       Language.Haskell.TH.Compat                       Paths_clash_prelude@@ -311,7 +319,6 @@   Build-depends:      array                     >= 0.5.1.0 && < 0.6,                       arrows                    >= 0.4     && < 0.5,                       base                      >= 4.11    && < 5,-                      bifunctors                >= 5.4.0   && < 6.0,                       binary                    >= 0.8.5   && < 0.11,                       bytestring                >= 0.10.8  && < 0.12,                       constraints               >= 0.9     && < 1.0,@@ -337,7 +344,6 @@                       th-lift                   >= 0.7.0    && < 0.9,                       th-orphans                >= 0.13.1   && < 1.0,                       text                      >= 0.11.3.1 && < 2.1,-                      text-show                 >= 3.7     && < 3.10,                       time                      >= 1.8     && < 1.14,                       transformers              >= 0.5.2.0 && < 0.7,                       type-errors               >= 0.2.0.0 && < 0.3,@@ -358,18 +364,14 @@   ghc-options:      -Wall -Wcompat -threaded   hs-source-dirs:   tests -  x-doctest-options: -fobject-code-   if !flag(doctests)     buildable: False   else     build-depends:       base,-      doctest >= 0.9.1 && < 0.19,-      clash-prelude-  if impl(ghc >= 8.6)-    build-depends:-      doctest >= 0.16.1+      clash-prelude,+      doctest-parallel >= 0.2 && < 0.3,+      filepath  test-suite unittests   import:           common-options@@ -389,6 +391,7 @@       ghc-typelits-extra,        base,+      bytestring,       deepseq,       hedgehog      >= 1.0.3    && < 1.1,       hint          >= 0.7      && < 0.10,@@ -401,15 +404,19 @@       template-haskell    Other-Modules:+                 Clash.Tests.AsyncFIFOSynchronizer                  Clash.Tests.AutoReg                  Clash.Tests.BitPack                  Clash.Tests.BitVector                  Clash.Tests.BlockRam+                 Clash.Tests.BlockRam.Blob+                 Clash.Tests.Counter                  Clash.Tests.DerivingDataRepr                  Clash.Tests.DerivingDataReprTypes                  Clash.Tests.Fixed                  Clash.Tests.FixedExhaustive                  Clash.Tests.NFDataX+                 Clash.Tests.NumNewtypes                  Clash.Tests.Ram                  Clash.Tests.Reset                  Clash.Tests.Resize@@ -435,6 +442,8 @@   ghc-options:      -O2 -Wall   hs-source-dirs:   benchmarks +  ghc-options:      -with-rtsopts=-T+   if !flag(benchmarks)     buildable: False   else@@ -442,6 +451,7 @@       base,       clash-prelude,       criterion         >= 1.3.0.0 && < 1.6,+      directory,       deepseq,       template-haskell 
src/Clash/Annotations/BitRepresentation.hs view
@@ -9,8 +9,6 @@ -}  {-# LANGUAGE RankNTypes #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE TemplateHaskell #-}  {-# OPTIONS_GHC -Wno-orphans #-} 
src/Clash/Annotations/BitRepresentation/Deriving.hs view
@@ -1,7 +1,8 @@ {-|-Copyright  :  (C) 2018, Google Inc.+Copyright  :  (C) 2018, Google Inc.,+                  2022, QBayLogic B.V. License    :  BSD2 (see the file LICENSE)-Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>  This module contains: @@ -58,6 +59,7 @@ import qualified Clash.Annotations.BitRepresentation.Util   as Util +import           Clash.Annotations.Primitive (hasBlackBox) import           Clash.Class.BitPack   (BitPack, BitSize, pack, packXWith, unpack) import           Clash.Class.Resize         (resize)@@ -851,6 +853,7 @@ dontApplyInHDL :: (a -> b) -> a -> b dontApplyInHDL f a = f a {-# NOINLINE dontApplyInHDL #-}+{-# ANN dontApplyInHDL hasBlackBox #-}  buildUnpackField   :: Name
src/Clash/Annotations/BitRepresentation/Internal.hs view
@@ -8,7 +8,6 @@ {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-}-{-# LANGUAGE TemplateHaskell #-}  module Clash.Annotations.BitRepresentation.Internal   ( buildCustomReprs@@ -27,7 +26,6 @@ import           Clash.Annotations.BitRepresentation   (BitMask, Value, Size, FieldAnn, DataReprAnn(..), ConstrRepr(..)) import           Control.DeepSeq                          (NFData)-import           Data.Coerce                              (coerce) import           Data.Hashable                            (Hashable) import qualified Data.Map                                 as Map import           Data.Maybe                               (fromMaybe)@@ -36,8 +34,6 @@ import qualified Language.Haskell.TH.Syntax               as TH import           GHC.Generics                             (Generic) import           GHC.Stack                                (HasCallStack)-import qualified TextShow                                 as TS-import qualified TextShow.Generic                         as TS   -- | Simple version of template haskell type. Used internally to match on.@@ -48,16 +44,7 @@   -- ^ Qualified name of type   | LitTy' Integer   -- ^ Numeral literal (used in BitVector 10, for example)-    deriving (Generic, NFData, Eq, Typeable, Hashable, Ord, Show)---- Replace with------   deriving TS.TextShow via TS.FromGeneric (Type')------ after dropping support for GHC 8.4-instance TS.TextShow Type' where-  showt = TS.showt . coerce @_ @(TS.FromGeneric (Type'))-  showb = TS.showb . coerce @_ @(TS.FromGeneric (Type'))+  deriving (Generic, NFData, Eq, Typeable, Hashable, Ord, Show)  -- | Internal version of DataRepr data DataRepr' = DataRepr'
src/Clash/Annotations/BitRepresentation/Util.hs view
@@ -4,8 +4,6 @@ Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com> -} -{-# LANGUAGE TemplateHaskell #-}- module Clash.Annotations.BitRepresentation.Util   ( bitOrigins   , bitOrigins'
src/Clash/Annotations/Primitive.hs view
@@ -1,7 +1,8 @@ {-|-Copyright  :  (C) 2017-2019, Myrtle Software, QBayLogic+Copyright  :  (C) 2017-2019, Myrtle Software+                  2022,      QBayLogic B.V. License    :  BSD2 (see the file LICENSE)-Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>  Instruct the Clash compiler to look for primitive HDL templates provided inline or in a specified directory. For distribution of new packages with primitive@@ -234,7 +235,7 @@ -- Add more files to the @data-files@ stanza in your @.cabal@ files and more -- @ANN@ pragma's if you want to add more primitive templates for other HDLs ----- === Example of 'InlinePrimitive'+-- === Example of 'InlineYamlPrimitive' -- -- The following example shows off an inline HDL primitive template. It uses the -- [interpolate](https://hackage.haskell.org/package/interpolate) package for@@ -249,20 +250,17 @@ -- import           Data.String.Interpolate      (i) -- import           Data.String.Interpolate.Util (unindent) ----- {\-\# ANN example (InlinePrimitive [VHDL] $ unindent [i|---   [ { \"BlackBox\" :---       { "name" : "InlinePrimitive.example"---       , "kind": \"Declaration\"---       , "template" :---   "-- begin InlinePrimitive example:---   ~GENSYM[example][0] : block---   ~RESULT <= 1 + ~ARG[0];---   end block;---   -- end InlinePrimitive example"---       }---     }---   ]---   |]) \#-\}+-- {\-\# ANN example (InlineYamlPrimitive [VHDL] $ unindent [i|+--  BlackBox:+--    kind: Declaration+--    name: InlinePrimitive.example+--    template: |-+--      -- begin InlinePrimitive example:+--      ~GENSYM[example][0] : block+--      ~RESULT <= 1 + ~ARG[0];+--      end block;+--      end InlinePrimitive example+-- |]) \#-\} -- {\-\# NOINLINE example \#-\} -- example :: Signal System (BitVector 2) -> Signal System (BitVector 2) -- example = fmap succ@@ -271,7 +269,9 @@   = Primitive [HDL] FilePath   -- ^ Description of a primitive for a given 'HDL's in a file at 'FilePath'   | InlinePrimitive [HDL] String-  -- ^ Description of a primitive for a given 'HDL's as an inline 'String'+  -- ^ Description of a primitive for a given 'HDL's as an inline JSON 'String'+  | InlineYamlPrimitive [HDL] String+  -- ^ Description of a primitive for a given 'HDL's as an inline YAML 'String'   deriving (Show, Read, Data, Generic, NFData, Hashable, Eq)  -- | Primitive guard to mark a value as either not translatable or as having a
src/Clash/Annotations/SynthesisAttributes.hs view
@@ -1,14 +1,14 @@ {-|-  Copyright   :  (C) 2018, Google Inc.+  Copyright   :  (C) 2018, Google Inc.,+                     2021, QBayLogic B.V.   License     :  BSD2 (see the file LICENSE)-  Maintainer  :  Christiaan Baaij <christiaan.baaij@gmail.com>+  Maintainer  :  QBayLogic B.V. <devops@qbaylogic.com>    API for synthesis attributes (sometimes refered to as "synthesis directives",   "pragmas", or "logic synthesis directives"). This is an experimental feature,   please report any unexpected or broken behavior to Clash's GitHub page   (<https://github.com/clash-lang/clash-compiler/issues>). -}-{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE PolyKinds #-}  {-# LANGUAGE Safe #-}@@ -68,7 +68,29 @@ -- For VHDL, see: --     <https://www.intel.com/content/www/us/en/programmable/quartushelp/current/index.htm#hdl/vhdl/vhdl_file_dir.htm> ----- Warning: This is an experimental feature, please report any unexpected or broken+-- = Warnings+--+-- When using annotations, it is important that annotated arguments are not+-- eta-reduced, as this may result in the annotation being stripped by GHC. For+-- example+--+-- @+-- f :: Signal System Bool \`Annotate\` 'StringAttr \"chip_pin\" \"C4\"+--   -> Signal System Bool+-- f x = id x -- Using a lambda, i.e. f = \x -> id x also works+-- @+--+-- will reliably show the annotation in the generated HDL, but+--+-- @+-- g :: Signal System Bool \`Annotate\` 'StringAttr \"chip_pin\" \"C4\"+--   -> Signal System Bool+-- g = id+-- @+--+-- will not work.+--+-- This is an experimental feature, please report any unexpected or broken -- behavior to Clash's GitHub page (<https://github.com/clash-lang/clash-compiler/issues>). data Attr   = BoolAttr Symbol Bool
src/Clash/Annotations/TH.hs view
@@ -71,9 +71,6 @@ import           Data.Foldable                  ( fold) import qualified Data.Set                      as Set import qualified Data.Map                      as Map-#if !(MIN_VERSION_base(4,11,0))-import           Data.Semigroup                as Semigroup-#endif import           Data.Maybe                     ( catMaybes ) import           Language.Haskell.TH @@ -114,11 +111,8 @@   _ <> HasFail e               = HasFail e   HasFail e <> _               = HasFail e -instance (Semigroup a, Monoid a) => Monoid (Naming a) where+instance Monoid a => Monoid (Naming a) where   mempty = Complete mempty-#if !(MIN_VERSION_base(4,11,0))-  mappend = (Semigroup.<>)-#endif  -- | Track seen 'Name's, and track current 'Info' for error reporting. type ErrorContext = String
src/Clash/Annotations/TopEntity.hs view
@@ -1,8 +1,9 @@ {-| Copyright  :  (C) 2015-2016, University of Twente,-                  2017     , Google Inc.+                  2017     , Google Inc.,+                  2021     , QBayLogic B.V. License    :  BSD2 (see the file LICENSE)-Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>  'TopEntity' annotations allow us to control hierarchy and naming aspects of the Clash compiler. We have the 'Synthesize' and 'TestBench' annotation.@@ -103,7 +104,6 @@     'Clash.Prelude.resetSynchronizer'       clk50       ('Clash.Signal.unsafeFromLowPolarity' pllStable)-      enableGen  blinkerT   :: (BitVector 8, Bool, Index 16650001)
src/Clash/Class/AutoReg/Instances.hs view
@@ -3,7 +3,6 @@   License     :  BSD2 (see the file LICENSE)   Maintainer  :  Christiaan Baaij <christiaan.baaij@gmail.com> -}-{-# LANGUAGE CPP #-} {-# LANGUAGE TemplateHaskell #-}  {-# OPTIONS_GHC -Wno-orphans #-}@@ -14,18 +13,12 @@ import           Clash.Class.AutoReg.Internal import           Clash.CPP                           (maxTupleSize) -#if MIN_VERSION_base(4,12,0) import           Data.Complex (Complex) import           Data.Ord (Down)-#endif- import           Data.Ratio (Ratio) -#if MIN_VERSION_base(4,12,0) deriveAutoReg ''Complex deriveAutoReg ''Down-#endif- deriveAutoReg ''Ratio  -- | __N.B.__: The documentation only shows instances up to /3/-tuples. By
src/Clash/Class/AutoReg/Internal.hs view
@@ -1,7 +1,9 @@ {-|-  Copyright   :  (C) 2019, Google Inc.+  Copyright   :  (C) 2019     , Google Inc.,+                     2021     , QBayLogic B.V.+                     2021     , Myrtle.ai   License     :  BSD2 (see the file LICENSE)-  Maintainer  :  Christiaan Baaij <christiaan.baaij@gmail.com>+  Maintainer :  QBayLogic B.V. <devops@qbaylogic.com> -} {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-}@@ -9,9 +11,6 @@ {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} -- needed for constraint on the Fixed instance-#if __GLASGOW_HASKELL__ < 806-{-# OPTIONS_GHC -Wwarn=unused-pattern-binds #-}-#endif  module Clash.Class.AutoReg.Internal   ( AutoReg (..)@@ -55,7 +54,7 @@  -- $setup -- >>> import Data.Maybe--- >>> import Clash.Class.BitPack (pack)+-- >>> import Clash.Prelude -- >>> :set -fplugin GHC.TypeLits.Normalise -- >>> :set -fplugin GHC.TypeLits.KnownNat.Solver @@ -77,12 +76,12 @@ --   when viewed as bits, a 'Nothing' would look like: -- --     >>> pack @(Maybe (Signed 16)) Nothing---     0_...._...._...._....+--     0b0_...._...._...._.... -- --   and 'Just' -- --     >>> pack @(Maybe (Signed 16)) (Just 3)---     1_0000_0000_0000_0011+--     0b1_0000_0000_0000_0011 -- --   In the first case, Nothing, we don't particularly care about updating the --   register holding the @Signed 16@ field, as they'll be unknown anyway. We@@ -159,7 +158,7 @@      val = fromMaybe (deepErrorX "autoReg'.val") <$> input      valInit = fromMaybe (deepErrorX "autoReg'.valInit") initVal -     valR = autoReg clk rst (enable en tag) valInit val+     valR = autoReg clk rst (andEnable en tag) valInit val       createMaybe t v = case t of        True -> Just v@@ -210,9 +209,7 @@     go acc (ForallT _ _ ty) = go acc ty     go acc (AppT ty1 ty2)   = go (ty2:acc) ty1     go acc (SigT ty _)      = go acc ty-#if MIN_VERSION_template_haskell(2,11,0)     go acc (ParensT ty)     = go acc ty-#endif #if MIN_VERSION_template_haskell(2,15,0)     go acc (AppKindT ty _)  = go acc ty #endif@@ -461,6 +458,7 @@                   Just m  -> m       ConT _ -> ty'       AppT ty1 ty2 -> AppT (go ty1) (go ty2)+      LitT _ -> ty'       _ -> error $ "TODO applyTyVarSubsts: " ++ show ty'  
src/Clash/Class/BitPack.hs view
@@ -1,27 +1,16 @@+ {-|-Copyright  :  (C) 2013-2016, University of Twente,+Copyright  :  (C) 2013-2016, University of Twente                   2016-2017, Myrtle Software Ltd+                       2021, QBayLogic 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 FlexibleContexts #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE UndecidableInstances #-}--{-# LANGUAGE Trustworthy #-}--{-# OPTIONS_GHC -fplugin=GHC.TypeLits.Extra.Solver #-}-{-# OPTIONS_GHC -fplugin=GHC.TypeLits.Normalise #-}-{-# OPTIONS_GHC -fplugin=GHC.TypeLits.KnownNat.Solver #-}-{-# OPTIONS_HADDOCK show-extensions #-}--#include "MachDeps.h"+{-# LANGUAGE Safe #-}  module Clash.Class.BitPack   ( BitPack (..)+  , isLike   , bitCoerce   , bitCoerceMap   , boolToBV@@ -29,387 +18,22 @@   , bitToBool   , packXWith -  -- * Internals-  , GBitPack(..)+  -- * Bit Indexing+  , (!)+  , slice+  , split+  , replaceBit+  , setSlice+  , msb+  , lsb++  -- * Bit Reduction+  , reduceAnd+  , reduceOr+  , reduceXor   ) where -import Control.Exception              (catch, evaluate)-import Data.Binary.IEEE754            (doubleToWord, floatToWord, wordToDouble,-                                       wordToFloat)--#if MIN_VERSION_base(4,12,0)-import Data.Complex                   (Complex)-import Data.Ord                       (Down)-#endif--import Data.Int-import Data.Word-import Foreign.C.Types                (CUShort)-import GHC.TypeLits                   (KnownNat, Nat, type (+), type (-))-import Numeric.Half                   (Half (..))-import GHC.Generics-import GHC.TypeLits.Extra             (CLog, Max)-import Prelude                        hiding (map)-import System.IO.Unsafe               (unsafeDupablePerformIO)--import Clash.Promoted.Nat             (SNat(..), snatToNum)-import Clash.Class.BitPack.Internal   (deriveBitPackTuples)-import Clash.Class.Resize             (zeroExtend, resize)-import Clash.Sized.BitVector          (Bit, BitVector, (++#))-import Clash.Sized.Internal.BitVector-  (pack#, split#, checkUnpackUndef, undefined#, unpack#, unsafeToNatural)-import Clash.XException--{- $setup->>> :set -XDataKinds->>> import Clash.Prelude--}---- | Convert to and from a 'BitVector'-class KnownNat (BitSize a) => BitPack a where-  -- | Number of 'Clash.Sized.BitVector.Bit's needed to represents elements-  -- of type @a@-  ---  -- Can be derived using `GHC.Generics`:-  ---  -- > import Clash.Prelude-  -- > import GHC.Generics-  -- >-  -- > data MyProductType = MyProductType { a :: Int, b :: Bool }-  -- >   deriving (Generic, BitPack)-  type BitSize a :: Nat-  type BitSize a = (CLog 2 (GConstructorCount (Rep a))) + (GFieldSize (Rep a))-  -- | Convert element of type @a@ to a 'BitVector'-  ---  -- >>> pack (-5 :: Signed 6)-  -- 11_1011-  pack   :: a -> BitVector (BitSize a)-  default pack-    :: ( Generic a-       , GBitPack (Rep a)-       , KnownNat (BitSize a)-       , KnownNat constrSize-       , KnownNat fieldSize-       , constrSize ~ CLog 2 (GConstructorCount (Rep a))-       , fieldSize ~ GFieldSize (Rep a)-       , (constrSize + fieldSize) ~ BitSize a-       )-    => a -> BitVector (BitSize a)-  pack = packXWith go-   where-    go a = resize (pack sc) ++# packedFields-     where-      (sc, packedFields) = gPackFields 0 (from a)--  -- | Convert a 'BitVector' to an element of type @a@-  ---  -- >>> pack (-5 :: Signed 6)-  -- 11_1011-  -- >>> let x = pack (-5 :: Signed 6)-  -- >>> unpack x :: Unsigned 6-  -- 59-  -- >>> pack (59 :: Unsigned 6)-  -- 11_1011-  unpack :: BitVector (BitSize a) -> a-  default unpack-    :: ( Generic a-       , GBitPack (Rep a)-       , KnownNat constrSize-       , KnownNat fieldSize-       , constrSize ~ CLog 2 (GConstructorCount (Rep a))-       , fieldSize ~ GFieldSize (Rep a)-       , (constrSize + fieldSize) ~ BitSize a-       )-    => BitVector (BitSize a) -> a-  unpack b =-    to (gUnpack sc 0 bFields)-   where-    (checkUnpackUndef unpack . resize -> sc, bFields) = split# b--packXWith-  :: KnownNat n-  => (a -> BitVector n)-  -> a-  -> BitVector n-packXWith f x =-  unsafeDupablePerformIO (catch (f <$> evaluate x)-                                (\(XException _) -> return undefined#))-{-# NOINLINE packXWith #-}--{-# INLINE[1] bitCoerce #-}--- | Coerce a value from one type to another through its bit representation.------ >>> pack (-5 :: Signed 6)--- 11_1011--- >>> bitCoerce (-5 :: Signed 6) :: Unsigned 6--- 59--- >>> pack (59 :: Unsigned 6)--- 11_1011-bitCoerce-  :: (BitPack a, BitPack b, BitSize a ~ BitSize b)-  => a-  -> b-bitCoerce = unpack . pack---- | Map a value by first coercing to another type through its bit representation.------ >>> pack (-5 :: Signed 32)--- 1111_1111_1111_1111_1111_1111_1111_1011--- >>> bitCoerceMap @(Vec 4 (BitVector 8)) (replace 1 0) (-5 :: Signed 32)--- -16711685--- >>> pack (-16711685 :: Signed 32)--- 1111_1111_0000_0000_1111_1111_1111_1011-bitCoerceMap-  :: forall a b . (BitPack a, BitPack b, BitSize a ~ BitSize b)-  => (a -> a)-  -> b-  -> b-bitCoerceMap f = bitCoerce . f . bitCoerce--instance BitPack Bool where-  type BitSize Bool = 1-  pack   = let go b = if b then 1 else 0 in packXWith go-  unpack = checkUnpackUndef $ \bv -> if bv == 1 then True else False--instance KnownNat n => BitPack (BitVector n) where-  type BitSize (BitVector n) = n-  pack     = packXWith id-  unpack v = v--instance BitPack Bit where-  type BitSize Bit = 1-  pack   = packXWith pack#-  unpack = unpack#--instance BitPack Int where-  type BitSize Int = WORD_SIZE_IN_BITS-  pack   = packXWith fromIntegral-  unpack = checkUnpackUndef fromIntegral--instance BitPack Int8 where-  type BitSize Int8 = 8-  pack   = packXWith fromIntegral-  unpack = checkUnpackUndef fromIntegral--instance BitPack Int16 where-  type BitSize Int16 = 16-  pack   = packXWith fromIntegral-  unpack = checkUnpackUndef fromIntegral--instance BitPack Int32 where-  type BitSize Int32 = 32-  pack   = packXWith fromIntegral-  unpack = checkUnpackUndef fromIntegral--instance BitPack Int64 where-  type BitSize Int64 = 64-  pack   = packXWith fromIntegral-  unpack = checkUnpackUndef fromIntegral--instance BitPack Word where-  type BitSize Word = WORD_SIZE_IN_BITS-  pack   = packXWith fromIntegral-  unpack = checkUnpackUndef fromIntegral--instance BitPack Word8 where-  type BitSize Word8 = 8-  pack   = packXWith fromIntegral-  unpack = checkUnpackUndef fromIntegral--instance BitPack Word16 where-  type BitSize Word16 = 16-  pack   = packXWith fromIntegral-  unpack = checkUnpackUndef fromIntegral--instance BitPack Word32 where-  type BitSize Word32 = 32-  pack   = packXWith fromIntegral-  unpack = checkUnpackUndef fromIntegral--instance BitPack Word64 where-  type BitSize Word64 = 64-  pack   = packXWith fromIntegral-  unpack = checkUnpackUndef fromIntegral--instance BitPack Float where-  type BitSize Float = 32-  pack   = packXWith packFloat#-  unpack = checkUnpackUndef unpackFloat#--packFloat# :: Float -> BitVector 32-packFloat# = fromIntegral . floatToWord-{-# NOINLINE packFloat# #-}--unpackFloat# :: BitVector 32 -> Float-unpackFloat# (unsafeToNatural -> w) = wordToFloat (fromIntegral w)-{-# NOINLINE unpackFloat# #-}--instance BitPack Double where-  type BitSize Double = 64-  pack   = packXWith packDouble#-  unpack = checkUnpackUndef unpackDouble#--packDouble# :: Double -> BitVector 64-packDouble# = fromIntegral . doubleToWord-{-# NOINLINE packDouble# #-}--unpackDouble# :: BitVector 64 -> Double-unpackDouble# (unsafeToNatural -> w) = wordToDouble (fromIntegral w)-{-# NOINLINE unpackDouble# #-}--instance BitPack CUShort where-  type BitSize CUShort = 16-  pack   = packXWith fromIntegral-  unpack = checkUnpackUndef fromIntegral--instance BitPack Half where-  type BitSize Half = 16-  pack (Half x) = pack x-  unpack        = checkUnpackUndef $ \x -> Half (unpack x)--instance BitPack () where-  type BitSize () = 0-  pack   _ = minBound-  unpack _ = ()---- | __N.B.__: The documentation only shows instances up to /3/-tuples. By--- default, instances up to and including /12/-tuples will exist. If the flag--- @large-tuples@ is set instances up to the GHC imposed limit will exist. The--- GHC imposed limit is either 62 or 64 depending on the GHC version.-instance (BitPack a, BitPack b) =>-    BitPack (a,b) where-  type BitSize (a,b) = BitSize a + BitSize b-  pack = let go (a,b) = pack a ++# pack b in packXWith go-  unpack ab  = let (a,b) = split# ab in (unpack a, unpack b)--class GBitPack f where-  -- | Size of fields. If multiple constructors exist, this is the maximum of-  -- the sum of each of the constructors fields.-  type GFieldSize f :: Nat--  -- | Number of constructors this type has. Indirectly indicates how many bits-  -- are needed to represent the constructor.-  type GConstructorCount f :: Nat--  -- | Pack fields of a type. Caller should pack and prepend the constructor bits.-  gPackFields-    :: Int-    -- ^ Current constructor-    -> f a-    -- ^ Data to pack-    -> (Int, BitVector (GFieldSize f))-    -- ^ (Constructor number, Packed fields)--  -- | Unpack whole type.-  gUnpack-    :: Int-    -- ^ Construct with constructor /n/-    -> Int-    -- ^ Current constructor-    -> BitVector (GFieldSize f)-    -- ^ BitVector containing fields-    -> f a-    -- ^ Unpacked result--instance GBitPack a => GBitPack (M1 m d a) where-  type GFieldSize (M1 m d a) = GFieldSize a-  type GConstructorCount (M1 m d a) = GConstructorCount a--  gPackFields cc (M1 m1) = gPackFields cc m1-  gUnpack c cc b = M1 (gUnpack c cc b)--instance ( KnownNat (GFieldSize g)-         , KnownNat (GFieldSize f)-         , KnownNat (GConstructorCount f)-         , GBitPack f-         , GBitPack g-         ) => GBitPack (f :+: g) where-  type GFieldSize (f :+: g) = Max (GFieldSize f) (GFieldSize g)-  type GConstructorCount (f :+: g) = GConstructorCount f + GConstructorCount g--  gPackFields cc (L1 l) =-    let (sc, packed) = gPackFields cc l in-    let padding = undefined# :: BitVector (Max (GFieldSize f) (GFieldSize g) - GFieldSize f) in-    (sc, packed ++# padding)-  gPackFields cc (R1 r) =-    let cLeft = snatToNum (SNat @(GConstructorCount f)) in-    let (sc, packed) = gPackFields (cc + cLeft) r in-    let padding = undefined# :: BitVector (Max (GFieldSize f) (GFieldSize g) - GFieldSize g) in-    (sc, packed ++# padding)--  gUnpack c cc b =-    let cLeft = snatToNum (SNat @(GConstructorCount f)) in-    if c < cc + cLeft then-      L1 (gUnpack c cc f)-    else-      R1 (gUnpack c (cc + cLeft) g)--   where-    -- It's a thing of beauty, if I may say so myself!-    (f, _ :: BitVector (Max (GFieldSize f) (GFieldSize g) - GFieldSize f)) = split# b-    (g, _ :: BitVector (Max (GFieldSize f) (GFieldSize g) - GFieldSize g)) = split# b---instance (KnownNat (GFieldSize g), KnownNat (GFieldSize f), GBitPack f, GBitPack g) => GBitPack (f :*: g) where-  type GFieldSize (f :*: g) = GFieldSize f + GFieldSize g-  type GConstructorCount (f :*: g) = 1--  gPackFields cc fg =-    (cc, packXWith go fg)-   where-    go (l0 :*: r0) =-      let (_, l1) = gPackFields cc l0 in-      let (_, r1) = gPackFields cc r0 in-      l1 ++# r1--  gUnpack c cc b =-    gUnpack c cc front :*: gUnpack c cc back-   where-    (front, back) = split# b--instance BitPack c => GBitPack (K1 i c) where-  type GFieldSize (K1 i c) = BitSize c-  type GConstructorCount (K1 i c)  = 1--  gPackFields cc (K1 i) = (cc, pack i)-  gUnpack _c _cc b      = K1 (unpack b)--instance GBitPack U1 where-  type GFieldSize U1 = 0-  type GConstructorCount U1 = 1--  gPackFields cc U1 = (cc, 0)-  gUnpack _c _cc _b = U1---- Instances derived using Generic-instance ( BitPack a-         , BitPack b-         ) => BitPack (Either a b)--instance BitPack a => BitPack (Maybe a)--#if MIN_VERSION_base(4,12,0)-instance BitPack a => BitPack (Complex a)-instance BitPack a => BitPack (Down a)-#endif---- | Zero-extend a 'Bool'ean value to a 'BitVector' of the appropriate size.------ >>> boolToBV True :: BitVector 6--- 00_0001--- >>> boolToBV False :: BitVector 6--- 00_0000-boolToBV :: KnownNat n => Bool -> BitVector (n + 1)-boolToBV = zeroExtend . pack---- | Convert a Bool to a Bit-boolToBit :: Bool -> Bit-boolToBit = bitCoerce---- | Convert a Bool to a Bit-bitToBool :: Bit -> Bool-bitToBool = bitCoerce---- Derive the BitPack instance for tuples of size 3 to 62-deriveBitPackTuples ''BitPack ''BitSize 'pack 'unpack+import Clash.Class.BitPack.Internal+import Clash.Class.BitPack.BitIndex+import Clash.Class.BitPack.BitReduction
+ src/Clash/Class/BitPack/BitIndex.hs view
@@ -0,0 +1,160 @@+{-|+Copyright  :  (C) 2013-2016, University of Twente+                       2021, QBayLogic B.V.+License    :  BSD2 (see the file LICENSE)+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>+-}++{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}++{-# LANGUAGE Trustworthy #-}++{-# OPTIONS_HADDOCK show-extensions #-}++module Clash.Class.BitPack.BitIndex where++import GHC.TypeLits                   (KnownNat, type (+), type (-))++import Clash.Class.BitPack.Internal   (BitPack (..))+import Clash.Promoted.Nat             (SNat (..))+import Clash.Sized.Internal.BitVector+  (BitVector, Bit, index#, lsb#, msb#, replaceBit#, setSlice#, slice#, split#)++{- $setup+>>> :set -XDataKinds+>>> import Clash.Prelude+-}++{-# INLINE (!) #-}+-- | Get the bit at the specified bit index.+--+-- __NB:__ Bit indices are __DESCENDING__.+--+-- >>> pack (7 :: Unsigned 6)+-- 0b00_0111+-- >>> (7 :: Unsigned 6) ! 1+-- 1+-- >>> (7 :: Unsigned 6) ! 5+-- 0+-- >>> (7 :: Unsigned 6) ! 6+-- *** Exception: (!): 6 is out of range [5..0]+-- ...+(!) :: (BitPack a, Enum i) => a -> i -> Bit+(!) v i = index# (pack v) (fromEnum i)++{-# INLINE slice #-}+-- | Get a slice between bit index @m@ and and bit index @n@.+--+-- __NB:__ Bit indices are __DESCENDING__.+--+-- >>> pack (7 :: Unsigned 6)+-- 0b00_0111+-- >>> slice d4 d2 (7 :: Unsigned 6)+-- 0b001+-- >>> slice d6 d4 (7 :: Unsigned 6)+-- <BLANKLINE>+-- <interactive>:...+--     • Couldn't match type ‘7 + i0’ with ‘6’+--         arising from a use of ‘slice’+--       The type variable ‘i0’ is ambiguous+--     • In the expression: slice d6 d4 (7 :: Unsigned 6)+--       In an equation for ‘it’: it = slice d6 d4 (7 :: Unsigned 6)+slice+  :: (BitPack a, BitSize a ~ ((m + 1) + i))+  => SNat m+  -> SNat n+  -> a+  -> BitVector (m + 1 - n)+slice m n v = slice# (pack v) m n++{-# INLINE split #-}+-- | Split a value of a bit size @m + n@ into a tuple of values with size @m@+-- and size @n@.+--+-- >>> pack (7 :: Unsigned 6)+-- 0b00_0111+-- >>> split (7 :: Unsigned 6) :: (BitVector 2, BitVector 4)+-- (0b00,0b0111)+split+  :: (BitPack a, BitSize a ~ (m + n), KnownNat n)+  => a+  -> (BitVector m, BitVector n)+split v = split# (pack v)++{-# INLINE replaceBit #-}+-- | Set the bit at the specified index+--+-- __NB:__ Bit indices are __DESCENDING__.+--+-- >>> pack (-5 :: Signed 6)+-- 0b11_1011+-- >>> replaceBit 4 0 (-5 :: Signed 6)+-- -21+-- >>> pack (-21 :: Signed 6)+-- 0b10_1011+-- >>> replaceBit 5 0 (-5 :: Signed 6)+-- 27+-- >>> pack (27 :: Signed 6)+-- 0b01_1011+-- >>> replaceBit 6 0 (-5 :: Signed 6)+-- *** Exception: replaceBit: 6 is out of range [5..0]+-- ...+replaceBit :: (BitPack a, Enum i) => i -> Bit -> a -> a+replaceBit i b v = unpack (replaceBit# (pack v) (fromEnum i) b)++{-# INLINE setSlice #-}+-- | Set the bits between bit index @m@ and bit index @n@.+--+-- __NB:__ Bit indices are __DESCENDING__.+--+-- >>> pack (-5 :: Signed 6)+-- 0b11_1011+-- >>> setSlice d4 d3 0 (-5 :: Signed 6)+-- -29+-- >>> pack (-29 :: Signed 6)+-- 0b10_0011+-- >>> setSlice d6 d5 0 (-5 :: Signed 6)+-- <BLANKLINE>+-- <interactive>:...+--     • Couldn't match type ‘7 + i0’ with ‘6’+--         arising from a use of ‘setSlice’+--       The type variable ‘i0’ is ambiguous+--     • In the expression: setSlice d6 d5 0 (- 5 :: Signed 6)+--       In an equation for ‘it’: it = setSlice d6 d5 0 (- 5 :: Signed 6)+setSlice+  :: (BitPack a, BitSize a ~ ((m + 1) + i))+  => SNat m+  -> SNat n+  -> BitVector (m + 1 - n)+  -> a+  -> a+setSlice m n w v = unpack (setSlice# SNat (pack v) m n w)++{-# INLINE msb #-}+-- | Get the most significant bit.+--+-- >>> pack (-4 :: Signed 6)+-- 0b11_1100+-- >>> msb (-4 :: Signed 6)+-- 1+-- >>> pack (4 :: Signed 6)+-- 0b00_0100+-- >>> msb (4 :: Signed 6)+-- 0+msb :: BitPack a => a -> Bit+msb v = msb# (pack v)++{-# INLINE lsb #-}+-- | Get the least significant bit.+--+-- >>> pack (-9 :: Signed 6)+-- 0b11_0111+-- >>> lsb (-9 :: Signed 6)+-- 1+-- >>> pack (-8 :: Signed 6)+-- 0b11_1000+-- >>> lsb (-8 :: Signed 6)+-- 0+lsb :: BitPack a => a -> Bit+lsb v = lsb# (pack v)
+ src/Clash/Class/BitPack/BitReduction.hs view
@@ -0,0 +1,83 @@+{-|+Copyright  :  (C) 2013-2016, University of Twente,+                  2021,      QBayLogic B.V.+License    :  BSD2 (see the file LICENSE)+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>+-}++{-# LANGUAGE FlexibleContexts #-}++{-# LANGUAGE Trustworthy #-}++{-# OPTIONS_HADDOCK show-extensions #-}++module Clash.Class.BitPack.BitReduction where++import Clash.Class.BitPack.Internal   (BitPack (..))+import Clash.Sized.Internal.BitVector (Bit, reduceAnd#, reduceOr#, reduceXor#)++{- $setup+>>> :set -XDataKinds+>>> import Clash.Prelude+-}++{-# INLINE reduceAnd #-}+-- | Are all bits set to '1'?+--+-- >>> pack (-2 :: Signed 6)+-- 0b11_1110+-- >>> reduceAnd (-2 :: Signed 6)+-- 0+-- >>> pack (-1 :: Signed 6)+-- 0b11_1111+-- >>> reduceAnd (-1 :: Signed 6)+-- 1+--+-- Zero width types will evaluate to '1':+--+-- >>> reduceAnd (0 :: Unsigned 0)+-- 1+reduceAnd :: BitPack a => a -> Bit+reduceAnd v = reduceAnd# (pack v)++{-# INLINE reduceOr #-}+-- | Is there at least one bit set to '1'?+--+-- >>> pack (5 :: Signed 6)+-- 0b00_0101+-- >>> reduceOr (5 :: Signed 6)+-- 1+-- >>> pack (0 :: Signed 6)+-- 0b00_0000+-- >>> reduceOr (0 :: Signed 6)+-- 0+--+-- Zero width types will evaluate to '0':+--+-- >>> reduceOr (0 :: Unsigned 0)+-- 0+reduceOr :: BitPack a => a -> Bit+reduceOr v = reduceOr# (pack v)++{-# INLINE reduceXor #-}+-- | Is the number of bits set to '1' uneven?+--+-- >>> pack (5 :: Signed 6)+-- 0b00_0101+-- >>> reduceXor (5 :: Signed 6)+-- 0+-- >>> pack (28 :: Signed 6)+-- 0b01_1100+-- >>> reduceXor (28 :: Signed 6)+-- 1+-- >>> pack (-5 :: Signed 6)+-- 0b11_1011+-- >>> reduceXor (-5 :: Signed 6)+-- 1+--+-- Zero width types will evaluate to '0':+--+-- >>> reduceXor (0 :: Unsigned 0)+-- 0+reduceXor :: BitPack a => a -> Bit+reduceXor v = reduceXor# (pack v)
src/Clash/Class/BitPack/Internal.hs view
@@ -1,102 +1,464 @@ {-|-Copyright  :  (C) 2019, QBayLogic B.V.+Copyright  :  (C) 2013-2016, University of Twente,+                  2016-2017, Myrtle Software Ltd,+                  2021,      QBayLogic 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 FlexibleContexts #-} {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-} -module Clash.Class.BitPack.Internal (deriveBitPackTuples) where+{-# LANGUAGE Trustworthy #-} -import           Clash.CPP             (maxTupleSize)-import           Language.Haskell.TH.Compat (mkTySynInstD,mkTupE)-import           Control.Monad         (replicateM)-import           Data.List             (foldl')-import           GHC.TypeLits          (KnownNat)-import           Language.Haskell.TH+{-# OPTIONS_GHC -fplugin=GHC.TypeLits.Extra.Solver #-}+{-# OPTIONS_GHC -fplugin=GHC.TypeLits.Normalise #-}+{-# OPTIONS_GHC -fplugin=GHC.TypeLits.KnownNat.Solver #-}+{-# OPTIONS_HADDOCK show-extensions #-} --- | Contruct all the tuple (starting at size 3) instances for BitPack.-deriveBitPackTuples-  :: Name-  -- ^ BitPack-  -> Name-  -- ^ BitSize-  -> Name-  -- ^ pack-  -> Name-  -- ^ unpack-  -> DecsQ-deriveBitPackTuples bitPackName bitSizeName packName unpackName = do-  let bitPack  = ConT bitPackName-      bitSize  = ConT bitSizeName-      knownNat = ConT ''KnownNat-      plus     = ConT $ mkName "+"+#include "MachDeps.h" -  allNames <- replicateM maxTupleSize (newName "a")-  retupName <- newName "retup"-  x <- newName "x"-  y <- newName "y"-  tup <- newName "tup"+module Clash.Class.BitPack.Internal where -  pure $ flip map [3..maxTupleSize] $ \tupleNum ->-    let names  = take tupleNum allNames-        (v:vs) = fmap VarT names-        tuple xs = foldl' AppT (TupleT $ length xs) xs+import Prelude                        hiding (map) -        -- Instance declaration-        context =-          [ bitPack `AppT` v-          , knownNat `AppT` (bitSize `AppT` v)-          , bitPack `AppT` tuple vs-          , knownNat `AppT` (bitSize `AppT` tuple vs)-          ]-        instTy = AppT bitPack $ tuple (v:vs)+import Control.Exception              (catch, evaluate)+import Data.Binary.IEEE754            (doubleToWord, floatToWord, wordToDouble,+                                       wordToFloat) -        -- Associated type BitSize-        bitSizeType =-          mkTySynInstD bitSizeName [tuple (v:vs)]-            $ plus `AppT` (bitSize `AppT` v) `AppT`-              (bitSize `AppT` foldl AppT (TupleT $ tupleNum - 1) vs)+import Data.Complex                   (Complex)+import Data.Int+import Data.Ord                       (Down)+import Data.Word+import Foreign.C.Types                (CUShort)+import GHC.Generics+import GHC.TypeLits                   (KnownNat, Nat, type (+), type (-))+import GHC.TypeLits.Extra             (CLog, Max)+import Numeric.Half                   (Half (..))+import System.IO.Unsafe               (unsafeDupablePerformIO) -        pack =-          FunD-            packName-            [ Clause-                [VarP tup]-                (NormalB (AppE (VarE packName) (AppE (VarE retupName) (VarE tup))))-                [FunD-                    retupName-                    [ Clause-                        [ TupP $ map VarP names ]-                        ( let (e:es) = map VarE names-                          in NormalB (mkTupE [e,mkTupE es])-                        )-                        []-                    ]-                ]-            ]+import Clash.Annotations.Primitive    (hasBlackBox)+import Clash.Class.BitPack.Internal.TH (deriveBitPackTuples)+import Clash.Class.Resize             (zeroExtend, resize)+import Clash.Promoted.Nat             (SNat(..), snatToNum)+import Clash.Sized.BitVector          (Bit, BitVector, (++#))+import Clash.Sized.Internal.BitVector+  (pack#, split#, checkUnpackUndef, undefined#, unpack#, unsafeToNatural, isLike#)+import Clash.XException -        unpack =-          FunD-            unpackName-            [ Clause-                [ VarP x ]-                ( NormalB $-                    let (p:ps) = map VarP names-                    in-                    LetE-                      [ ValD-                          ( TupP [ p, VarP y ] )-                          ( NormalB $ VarE unpackName `AppE` VarE x )-                          []-                      , ValD-                          ( TupP ps )-                          ( NormalB $ VarE unpackName `AppE` VarE y )-                          []-                      ]-                      ( mkTupE $ map VarE names )-                )-                []-            ]+{- $setup+>>> :m -Prelude+>>> :set -XDataKinds+>>> import Clash.Prelude+-} -    in InstanceD Nothing context instTy [bitSizeType, pack, unpack]+-- | Convert data to/from a 'BitVector'. This allows functions to be defined+-- on the underlying representation of data, while exposing a nicer API using+-- 'pack' / 'unpack' at the boundaries. For example:+--+-- @+--     f :: forall a b. (BitPack a, BitPack b) => a -> b+--     f = unpack . go . pack+--      where+--       go :: BitVector (BitSize a) -> BitVector (BitSize b)+--       go = _ -- A function on the underlying bit vector+-- @+--+-- A type should only implement this class if it has a statically known size,+-- as otherwise it is not possible to determine how many bits are needed to+-- represent values. This means that types such as @[a]@ cannot have @BitPack@+-- instances, as even if @a@ has a statically known size, the length of the+-- list cannot be known in advance.+--+-- Clash provides some generic functions on packable types in the prelude, such+-- as indexing into packable stuctures (see "Clash.Class.BitPack.BitIndex") and+-- bitwise reduction of packable data (see "Clash.Class.BitPack.BitReduction").+--+class KnownNat (BitSize a) => BitPack a where+  -- | Number of 'Clash.Sized.BitVector.Bit's needed to represents elements+  -- of type @a@+  --+  -- Can be derived using `GHC.Generics`:+  --+  -- > import Clash.Prelude+  -- > import GHC.Generics+  -- >+  -- > data MyProductType = MyProductType { a :: Int, b :: Bool }+  -- >   deriving (Generic, BitPack)+  type BitSize a :: Nat+  type BitSize a = (CLog 2 (GConstructorCount (Rep a))) + (GFieldSize (Rep a))+  -- | Convert element of type @a@ to a 'BitVector'+  --+  -- >>> pack (-5 :: Signed 6)+  -- 0b11_1011+  pack   :: a -> BitVector (BitSize a)+  default pack+    :: ( Generic a+       , GBitPack (Rep a)+       , KnownNat (BitSize a)+       , KnownNat constrSize+       , KnownNat fieldSize+       , constrSize ~ CLog 2 (GConstructorCount (Rep a))+       , fieldSize ~ GFieldSize (Rep a)+       , (constrSize + fieldSize) ~ BitSize a+       )+    => a -> BitVector (BitSize a)+  pack = packXWith go+   where+    go a = resize (pack sc) ++# packedFields+     where+      (sc, packedFields) = gPackFields 0 (from a)++  -- | Convert a 'BitVector' to an element of type @a@+  --+  -- >>> pack (-5 :: Signed 6)+  -- 0b11_1011+  -- >>> let x = pack (-5 :: Signed 6)+  -- >>> unpack x :: Unsigned 6+  -- 59+  -- >>> pack (59 :: Unsigned 6)+  -- 0b11_1011+  unpack :: BitVector (BitSize a) -> a+  default unpack+    :: ( Generic a+       , GBitPack (Rep a)+       , KnownNat constrSize+       , KnownNat fieldSize+       , constrSize ~ CLog 2 (GConstructorCount (Rep a))+       , fieldSize ~ GFieldSize (Rep a)+       , (constrSize + fieldSize) ~ BitSize a+       )+    => BitVector (BitSize a) -> a+  unpack b =+    to (gUnpack sc 0 bFields)+   where+    (checkUnpackUndef unpack . resize -> sc, bFields) = split# b++packXWith+  :: KnownNat n+  => (a -> BitVector n)+  -> a+  -> BitVector n+packXWith f x =+  unsafeDupablePerformIO (catch (f <$> evaluate x)+                                (\(XException _) -> return undefined#))+{-# NOINLINE packXWith #-}++-- | Pack both arguments to a 'BitVector' and use+-- 'Clash.Sized.Internal.BitVector.isLike#' to compare them. This is a more+-- lentiant comparison than '(==)', behaving more like (but not necessarily+-- exactly the same as) @std_match@ in VHDL or @casez@ in Verilog.+--+-- Unlike '(==)', isLike is not symmetric. The reason for this is that a+-- defined bit is said to be like an undefined bit, but not vice-versa:+--+-- >>> isLike (12 :: Signed 8) undefined+-- True+-- >>> isLike undefined (12 :: Signed 8)+-- False+--+-- However, it is still trivially reflexive and transitive:+--+-- >>> :set -XTemplateHaskell+-- >>> let x1 = $(bLit "0010")+-- >>> let x2 = $(bLit "0.10")+-- >>> let x3 = $(bLit "0.1.")+-- >>> isLike x1 x1+-- True+-- >>> isLike x1 x2+-- True+-- >>> isLike x2 x3+-- True+-- >>> isLike x1 x3+-- True+--+-- __N.B.__: Not synthesizable+--+isLike+  :: (BitPack a)+  => a+  -> a+  -> Bool+isLike x y =+  isLike# (pack x) (pack y)++{-# INLINE[1] bitCoerce #-}+-- | Coerce a value from one type to another through its bit representation.+--+-- >>> pack (-5 :: Signed 6)+-- 0b11_1011+-- >>> bitCoerce (-5 :: Signed 6) :: Unsigned 6+-- 59+-- >>> pack (59 :: Unsigned 6)+-- 0b11_1011+bitCoerce+  :: (BitPack a, BitPack b, BitSize a ~ BitSize b)+  => a+  -> b+bitCoerce = unpack . pack++-- | Map a value by first coercing to another type through its bit representation.+--+-- >>> pack (-5 :: Signed 32)+-- 0b1111_1111_1111_1111_1111_1111_1111_1011+-- >>> bitCoerceMap @(Vec 4 (BitVector 8)) (replace 1 0) (-5 :: Signed 32)+-- -16711685+-- >>> pack (-16711685 :: Signed 32)+-- 0b1111_1111_0000_0000_1111_1111_1111_1011+bitCoerceMap+  :: forall a b . (BitPack a, BitPack b, BitSize a ~ BitSize b)+  => (a -> a)+  -> b+  -> b+bitCoerceMap f = bitCoerce . f . bitCoerce++instance BitPack Bool where+  type BitSize Bool = 1+  pack   = let go b = if b then 1 else 0 in packXWith go+  unpack = checkUnpackUndef $ \bv -> if bv == 1 then True else False++instance KnownNat n => BitPack (BitVector n) where+  type BitSize (BitVector n) = n+  pack     = packXWith id+  unpack v = v++instance BitPack Bit where+  type BitSize Bit = 1+  pack   = packXWith pack#+  unpack = unpack#++instance BitPack Int where+  type BitSize Int = WORD_SIZE_IN_BITS+  pack   = packXWith fromIntegral+  unpack = checkUnpackUndef fromIntegral++instance BitPack Int8 where+  type BitSize Int8 = 8+  pack   = packXWith fromIntegral+  unpack = checkUnpackUndef fromIntegral++instance BitPack Int16 where+  type BitSize Int16 = 16+  pack   = packXWith fromIntegral+  unpack = checkUnpackUndef fromIntegral++instance BitPack Int32 where+  type BitSize Int32 = 32+  pack   = packXWith fromIntegral+  unpack = checkUnpackUndef fromIntegral++instance BitPack Int64 where+  type BitSize Int64 = 64+  pack   = packXWith fromIntegral+  unpack = checkUnpackUndef fromIntegral++instance BitPack Word where+  type BitSize Word = WORD_SIZE_IN_BITS+  pack   = packXWith fromIntegral+  unpack = checkUnpackUndef fromIntegral++instance BitPack Word8 where+  type BitSize Word8 = 8+  pack   = packXWith fromIntegral+  unpack = checkUnpackUndef fromIntegral++instance BitPack Word16 where+  type BitSize Word16 = 16+  pack   = packXWith fromIntegral+  unpack = checkUnpackUndef fromIntegral++instance BitPack Word32 where+  type BitSize Word32 = 32+  pack   = packXWith fromIntegral+  unpack = checkUnpackUndef fromIntegral++instance BitPack Word64 where+  type BitSize Word64 = 64+  pack   = packXWith fromIntegral+  unpack = checkUnpackUndef fromIntegral++instance BitPack Float where+  type BitSize Float = 32+  pack   = packXWith packFloat#+  unpack = checkUnpackUndef unpackFloat#++packFloat# :: Float -> BitVector 32+packFloat# = fromIntegral . floatToWord+{-# NOINLINE packFloat# #-}+{-# ANN packFloat# hasBlackBox #-}++unpackFloat# :: BitVector 32 -> Float+unpackFloat# (unsafeToNatural -> w) = wordToFloat (fromIntegral w)+{-# NOINLINE unpackFloat# #-}+{-# ANN unpackFloat# hasBlackBox #-}++instance BitPack Double where+  type BitSize Double = 64+  pack   = packXWith packDouble#+  unpack = checkUnpackUndef unpackDouble#++packDouble# :: Double -> BitVector 64+packDouble# = fromIntegral . doubleToWord+{-# NOINLINE packDouble# #-}+{-# ANN packDouble# hasBlackBox #-}++unpackDouble# :: BitVector 64 -> Double+unpackDouble# (unsafeToNatural -> w) = wordToDouble (fromIntegral w)+{-# NOINLINE unpackDouble# #-}+{-# ANN unpackDouble# hasBlackBox #-}++instance BitPack CUShort where+  type BitSize CUShort = 16+  pack   = packXWith fromIntegral+  unpack = checkUnpackUndef fromIntegral++instance BitPack Half where+  type BitSize Half = 16+  pack (Half x) = pack x+  unpack        = checkUnpackUndef $ \x -> Half (unpack x)++instance BitPack () where+  type BitSize () = 0+  pack   _ = minBound+  unpack _ = ()++-- | __N.B.__: The documentation only shows instances up to /3/-tuples. By+-- default, instances up to and including /12/-tuples will exist. If the flag+-- @large-tuples@ is set instances up to the GHC imposed limit will exist. The+-- GHC imposed limit is either 62 or 64 depending on the GHC version.+instance (BitPack a, BitPack b) => BitPack (a,b) where+  type BitSize (a,b) = BitSize a + BitSize b+  pack = let go (a,b) = pack a ++# pack b in packXWith go+  unpack ab  = let (a,b) = split# ab in (unpack a, unpack b)++class GBitPack f where+  -- | Size of fields. If multiple constructors exist, this is the maximum of+  -- the sum of each of the constructors fields.+  type GFieldSize f :: Nat++  -- | Number of constructors this type has. Indirectly indicates how many bits+  -- are needed to represent the constructor.+  type GConstructorCount f :: Nat++  -- | Pack fields of a type. Caller should pack and prepend the constructor bits.+  gPackFields+    :: Int+    -- ^ Current constructor+    -> f a+    -- ^ Data to pack+    -> (Int, BitVector (GFieldSize f))+    -- ^ (Constructor number, Packed fields)++  -- | Unpack whole type.+  gUnpack+    :: Int+    -- ^ Construct with constructor /n/+    -> Int+    -- ^ Current constructor+    -> BitVector (GFieldSize f)+    -- ^ BitVector containing fields+    -> f a+    -- ^ Unpacked result++instance GBitPack a => GBitPack (M1 m d a) where+  type GFieldSize (M1 m d a) = GFieldSize a+  type GConstructorCount (M1 m d a) = GConstructorCount a++  gPackFields cc (M1 m1) = gPackFields cc m1+  gUnpack c cc b = M1 (gUnpack c cc b)++instance ( KnownNat (GFieldSize g)+         , KnownNat (GFieldSize f)+         , KnownNat (GConstructorCount f)+         , GBitPack f+         , GBitPack g+         ) => GBitPack (f :+: g) where+  type GFieldSize (f :+: g) = Max (GFieldSize f) (GFieldSize g)+  type GConstructorCount (f :+: g) = GConstructorCount f + GConstructorCount g++  gPackFields cc (L1 l) =+    let (sc, packed) = gPackFields cc l in+    let padding = undefined# :: BitVector (Max (GFieldSize f) (GFieldSize g) - GFieldSize f) in+    (sc, packed ++# padding)+  gPackFields cc (R1 r) =+    let cLeft = snatToNum (SNat @(GConstructorCount f)) in+    let (sc, packed) = gPackFields (cc + cLeft) r in+    let padding = undefined# :: BitVector (Max (GFieldSize f) (GFieldSize g) - GFieldSize g) in+    (sc, packed ++# padding)++  gUnpack c cc b =+    let cLeft = snatToNum (SNat @(GConstructorCount f)) in+    if c < cc + cLeft then+      L1 (gUnpack c cc f)+    else+      R1 (gUnpack c (cc + cLeft) g)++   where+    -- It's a thing of beauty, if I may say so myself!+    (f, _ :: BitVector (Max (GFieldSize f) (GFieldSize g) - GFieldSize f)) = split# b+    (g, _ :: BitVector (Max (GFieldSize f) (GFieldSize g) - GFieldSize g)) = split# b+++instance (KnownNat (GFieldSize g), KnownNat (GFieldSize f), GBitPack f, GBitPack g) => GBitPack (f :*: g) where+  type GFieldSize (f :*: g) = GFieldSize f + GFieldSize g+  type GConstructorCount (f :*: g) = 1++  gPackFields cc fg =+    (cc, packXWith go fg)+   where+    go (l0 :*: r0) =+      let (_, l1) = gPackFields cc l0 in+      let (_, r1) = gPackFields cc r0 in+      l1 ++# r1++  gUnpack c cc b =+    gUnpack c cc front :*: gUnpack c cc back+   where+    (front, back) = split# b++instance BitPack c => GBitPack (K1 i c) where+  type GFieldSize (K1 i c) = BitSize c+  type GConstructorCount (K1 i c)  = 1++  gPackFields cc (K1 i) = (cc, pack i)+  gUnpack _c _cc b      = K1 (unpack b)++instance GBitPack U1 where+  type GFieldSize U1 = 0+  type GConstructorCount U1 = 1++  gPackFields cc U1 = (cc, 0)+  gUnpack _c _cc _b = U1++-- Instances derived using Generic+instance ( BitPack a+         , BitPack b+         ) => BitPack (Either a b)++instance BitPack a => BitPack (Maybe a)++instance BitPack a => BitPack (Complex a)+instance BitPack a => BitPack (Down a)++-- | Zero-extend a 'Bool'ean value to a 'BitVector' of the appropriate size.+--+-- >>> boolToBV True :: BitVector 6+-- 0b00_0001+-- >>> boolToBV False :: BitVector 6+-- 0b00_0000+boolToBV :: KnownNat n => Bool -> BitVector (n + 1)+boolToBV = zeroExtend . pack++-- | Convert a Bool to a Bit+boolToBit :: Bool -> Bit+boolToBit = bitCoerce++-- | Convert a Bool to a Bit+bitToBool :: Bit -> Bool+bitToBool = bitCoerce++-- Derive the BitPack instance for tuples of size 3 to maxTupleSize+deriveBitPackTuples ''BitPack ''BitSize 'pack 'unpack
+ src/Clash/Class/BitPack/Internal/TH.hs view
@@ -0,0 +1,102 @@+{-|+Copyright  :  (C) 2019, QBayLogic B.V.+License    :  BSD2 (see the file LICENSE)+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>+-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE TemplateHaskell #-}++module Clash.Class.BitPack.Internal.TH where++import           Clash.CPP             (maxTupleSize)+import           Language.Haskell.TH.Compat (mkTySynInstD,mkTupE)+import           Control.Monad         (replicateM)+import           Data.List             (foldl')+import           GHC.TypeLits          (KnownNat)+import           Language.Haskell.TH++-- | Contruct all the tuple (starting at size 3) instances for BitPack.+deriveBitPackTuples+  :: Name+  -- ^ BitPack+  -> Name+  -- ^ BitSize+  -> Name+  -- ^ pack+  -> Name+  -- ^ unpack+  -> DecsQ+deriveBitPackTuples bitPackName bitSizeName packName unpackName = do+  let bitPack  = ConT bitPackName+      bitSize  = ConT bitSizeName+      knownNat = ConT ''KnownNat+      plus     = ConT $ mkName "+"++  allNames <- replicateM maxTupleSize (newName "a")+  retupName <- newName "retup"+  x <- newName "x"+  y <- newName "y"+  tup <- newName "tup"++  pure $ flip map [3..maxTupleSize] $ \tupleNum ->+    let names  = take tupleNum allNames+        (v:vs) = fmap VarT names+        tuple xs = foldl' AppT (TupleT $ length xs) xs++        -- Instance declaration+        context =+          [ bitPack `AppT` v+          , knownNat `AppT` (bitSize `AppT` v)+          , bitPack `AppT` tuple vs+          , knownNat `AppT` (bitSize `AppT` tuple vs)+          ]+        instTy = AppT bitPack $ tuple (v:vs)++        -- Associated type BitSize+        bitSizeType =+          mkTySynInstD bitSizeName [tuple (v:vs)]+            $ plus `AppT` (bitSize `AppT` v) `AppT`+              (bitSize `AppT` foldl AppT (TupleT $ tupleNum - 1) vs)++        pack =+          FunD+            packName+            [ Clause+                [VarP tup]+                (NormalB (AppE (VarE packName) (AppE (VarE retupName) (VarE tup))))+                [FunD+                    retupName+                    [ Clause+                        [ TupP $ map VarP names ]+                        ( let (e:es) = map VarE names+                          in NormalB (mkTupE [e,mkTupE es])+                        )+                        []+                    ]+                ]+            ]++        unpack =+          FunD+            unpackName+            [ Clause+                [ VarP x ]+                ( NormalB $+                    let (p:ps) = map VarP names+                    in+                    LetE+                      [ ValD+                          ( TupP [ p, VarP y ] )+                          ( NormalB $ VarE unpackName `AppE` VarE x )+                          []+                      , ValD+                          ( TupP ps )+                          ( NormalB $ VarE unpackName `AppE` VarE y )+                          []+                      ]+                      ( mkTupE $ map VarE names )+                )+                []+            ]++    in InstanceD Nothing context instTy [bitSizeType, pack, unpack]
+ src/Clash/Class/Counter.hs view
@@ -0,0 +1,62 @@+{-|+  Copyright   :  (C) 2021     , QBayLogic B.V.+  License     :  BSD2 (see the file LICENSE)+  Maintainer  :  QBayLogic B.V. <devops@qbaylogic.com>++  Utilities for wrapping counters consisting of multiple individual counters+-}++module Clash.Class.Counter+  ( Counter+  , countSucc+  , countPred+  ) where++import Clash.Class.Counter.Internal++-- $setup+-- >>> import Clash.Class.Counter+-- >>> import Clash.Sized.BitVector (BitVector)+-- >>> import Clash.Sized.Index (Index)+-- >>> import Clash.Sized.Signed (Signed)+-- >>> import Clash.Sized.Unsigned (Unsigned)++-- | Successor of a counter.+--+-- Examples:+--+-- >>> type T = (Unsigned 2, Unsigned 2)+-- >>> countSucc @T (1, 1)+-- (1,2)+-- >>> countSucc @T (1, 2)+-- (1,3)+-- >>> countSucc @T (1, 3)+-- (2,0)+-- >>> countSucc @T (3, 3)+-- (0,0)+-- >>> countSucc @(Index 9, Index 2) (0, 1)+-- (1,0)+-- >>> countSucc @(Either (Index 9) (Index 9)) (Left 8)+-- Right 0+countSucc :: Counter a => a -> a+countSucc = snd . countSuccOverflow++-- | Predecessor of a counter+--+-- Examples:+--+-- >>> type T = (Unsigned 2, Unsigned 2)+-- >>> countPred @T (1, 2)+-- (1,1)+-- >>> countPred @T (1, 3)+-- (1,2)+-- >>> countPred @T (2, 0)+-- (1,3)+-- >>> countPred @T (0, 0)+-- (3,3)+-- >>> countPred @(Index 9, Index 2) (1, 0)+-- (0,1)+-- >>> countPred @(Either (Index 9) (Index 9)) (Right 0)+-- Left 8+countPred :: Counter a => a -> a+countPred = snd . countPredOverflow
+ src/Clash/Class/Counter/Internal.hs view
@@ -0,0 +1,144 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeFamilies #-}++module Clash.Class.Counter.Internal where++import Clash.CPP (maxTupleSize)++import Clash.Class.Counter.TH (genTupleInstances)+import Clash.Sized.BitVector (BitVector)+import Clash.Sized.Index (Index)+import Clash.Sized.Signed (Signed)+import Clash.Sized.Unsigned (Unsigned)++import Data.Bifunctor (bimap)+import GHC.TypeLits (KnownNat, type (<=))++-- $setup+-- >>> import Clash.Class.Counter+-- >>> import Clash.Sized.BitVector (BitVector)+-- >>> import Clash.Sized.Index (Index)+-- >>> import Clash.Sized.Signed (Signed)+-- >>> import Clash.Sized.Unsigned (Unsigned)++-- | 'Clash.Class.Counter.Counter' is a class that composes multiple counters+-- into a single one. It is similar to odometers found in olds cars,+-- once all counters reach their maximum they reset to zero - i.e. odometer+-- rollover. See 'Clash.Class.Counter.countSucc' and 'Clash.Class.Counter.countPred'+-- for API usage examples.+--+-- Example use case: when driving a monitor through VGA you would like to keep+-- track at least two counters: one counting a horizontal position, and one+-- vertical. Perhaps a fancy VGA driver would also like to keep track of the+-- number of drawn frames. To do so, the three counters are setup with different+-- types. On each /round/ of the horizontal counter the vertical counter should+-- be increased. On each /round/ of the vertical counter the frame counter should+-- be increased. With this class you could simply use the type:+--+-- @+-- (FrameCount, VerticalCount, HorizontalCount)+-- @+--+-- and have 'Clash.Class.Counter.countSucc' work as described.+--+-- __N.B.__: This class exposes four functions 'countMin', 'countMax',+-- 'countSuccOverflow', and 'countPredOverflow'. These functions are considered+-- an internal API. Users are encouraged to use 'Clash.Class.Counter.countSucc'+-- and 'Clash.Class.Counter.countPred'.+--+class Counter a where+  -- | Value counter wraps around to on a 'countSuccOverflow' overflow+  countMin :: a+  default countMin :: Bounded a => a+  countMin = minBound++  -- | Value counter wraps around to on a 'countPredOverflow' overflow+  countMax :: a+  default countMax :: Bounded a => a+  countMax = maxBound++  -- | Gets the successor of @a@. If it overflows, the left part of the tuple+  -- will be set to True.+  countSuccOverflow :: a -> (Bool, a)+  default countSuccOverflow :: (Eq a, Enum a, Bounded a) => a -> (Bool, a)+  countSuccOverflow a+    | a == maxBound = (True, countMin)+    | otherwise = (False, succ a)++  -- | Gets the predecessor of @a@. If it overflows, the left part of the tuple+  -- will be set to True.+  countPredOverflow :: a -> (Bool, a)+  default countPredOverflow :: (Eq a, Enum a, Bounded a) => a -> (Bool, a)+  countPredOverflow a+    | a == minBound = (True, countMax)+    | otherwise = (False, pred a)++instance (1 <= n, KnownNat n) => Counter (Index n)+instance KnownNat n => Counter (Unsigned n)+instance KnownNat n => Counter (Signed n)+instance KnownNat n => Counter (BitVector n)++-- | Counter instance that flip-flops between 'Left' and 'Right'. Examples:+--+-- >>> type T = Either (Index 2) (Unsigned 2)+-- >>> countSucc @T (Left 0)+-- Left 1+-- >>> countSucc @T (Left 1)+-- Right 0+-- >>> countSucc @T (Right 0)+-- Right 1+instance (Counter a, Counter b) => Counter (Either a b) where+  countMin = Left countMin+  countMax = Right countMax++  countSuccOverflow e =+    case bimap countSuccOverflow countSuccOverflow e of+      Left (overflow, a)  -> (False, if overflow then Right countMin else Left a)+      Right (overflow, b) -> (overflow, if overflow then Left countMin else Right b)++  countPredOverflow e =+    case bimap countPredOverflow countPredOverflow e of+      Left (overflow, a)  -> (overflow, if overflow then Right countMax else Left a)+      Right (overflow, b) -> (False, if overflow then Left countMax else Right b)++-- | Counters on tuples increment from right-to-left. This makes sense from the+-- perspective of LSB/MSB; MSB is on the left-hand-side and LSB is on the+-- right-hand-side in other Clash types.+--+-- >>> type T = (Unsigned 2, Index 2, Index 2)+-- >>> countSucc @T (0, 0, 0)+-- (0,0,1)+-- >>> countSucc @T (0, 0, 1)+-- (0,1,0)+-- >>> countSucc @T (0, 1, 0)+-- (0,1,1)+-- >>> countSucc @T (0, 1, 1)+-- (1,0,0)+--+-- __N.B.__: The documentation only shows the instances up to /3/-tuples. By+-- default, instances up to and including /12/-tuples will exist. If the flag+-- @large-tuples@ is set instances up to the GHC imposed limit will exist. The+-- GHC imposed limit is either 62 or 64 depending on the GHC version.+instance (Counter a0, Counter a1) => Counter (a0, a1) where+  -- a0/a1 instead of a/b to be consistent with TH generated instances+  countMin = (countMin, countMin)+  countMax = (countMax, countMax)++  countSuccOverflow (a0, b0) =+    if overflowB+    then (overflowA, (a1, b1))+    else (overflowB, (a0, b1))+   where+    (overflowB, b1) = countSuccOverflow b0+    (overflowA, a1) = countSuccOverflow a0++  countPredOverflow (a0, b0) =+    if overflowB+    then (overflowA, (a1, b1))+    else (overflowB, (a0, b1))+   where+    (overflowB, b1) = countPredOverflow b0+    (overflowA, a1) = countPredOverflow a0++genTupleInstances maxTupleSize
+ src/Clash/Class/Counter/TH.hs view
@@ -0,0 +1,81 @@+{-# LANGUAGE CPP #-}++module Clash.Class.Counter.TH where++import Language.Haskell.TH++counterName, countMinName, countMaxName, countSuccName, countPredName :: Name+counterName = mkName "Counter"+countMinName = mkName "countMin"+countMaxName = mkName "countMax"+countSuccName = mkName "countSuccOverflow"+countPredName = mkName "countPredOverflow"++mkTupTy :: [Type] -> Type+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]++genTupleInstance :: Int -> Q Dec+genTupleInstance tupSize = do+  typeVars <- mapM (\n -> VarT <$> newName ("a" <> show n)) [0..tupSize-1]++  succOverflowBody <- genCountOverflow countSuccName tupSize+  predOverflowBody <- genCountOverflow countPredName tupSize++  let+    minBody = genCount countMinName tupSize+    maxBody = genCount countMaxName tupSize+    ctx = map (ConT counterName `AppT`) typeVars+    typ = ConT counterName `AppT` mkTupTy typeVars+    decls =+      [ FunD countMinName [minBody]+      , FunD countMaxName [maxBody]+      , FunD (mkName "countSuccOverflow") [succOverflowBody]+      , FunD (mkName "countPredOverflow") [predOverflowBody]+      ]++  pure (InstanceD Nothing ctx typ decls)++genCount :: Name -> Int -> Clause+genCount nm n = Clause [] (NormalB (mkTup (replicate n (VarE nm)))) []++genCountOverflow :: Name -> Int -> Q Clause+genCountOverflow nm tupSize = do+  varNms <- mapM (\n -> newName ("a" <> show n)) [0..tupSize-1]+  let vars = map VarE varNms++  overflowLastNm <- newName "overflowLast"+  lastNm <- newName "last"++  overflowInitNm <- newName "overflowInit"+  initNms <- mapM (\n -> newName ("a" <> show n)) [0..tupSize-2]++  let+    body =+      CondE+        (VarE overflowLastNm)+        (mkTup [VarE overflowInitNm, mkTup (map VarE (initNms <> [lastNm]))])+        (mkTup [VarE overflowLastNm, mkTup (init vars <> [VarE lastNm])])++    decs =+      [ ValD+          (TupP [VarP overflowLastNm, VarP lastNm])+          (NormalB (VarE nm `AppE` last vars))+          []++      , ValD+          (TupP [VarP overflowInitNm, TupP (map VarP initNms)])+          (NormalB (VarE nm `AppE` mkTup (init vars)))+          []+      ]++  pure (Clause [TupP (map VarP varNms)] (NormalB body) decs)
src/Clash/Class/HasDomain/HasSingleDomain.hs view
@@ -14,10 +14,6 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} -#if __GLASGOW_HASKELL__ < 806-{-# LANGUAGE TypeInType #-}-#endif- {-# OPTIONS_GHC -Wno-missing-methods #-} {-# OPTIONS_HADDOCK not-home #-} 
src/Clash/Class/HasDomain/HasSpecificDomain.hs view
@@ -15,10 +15,6 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} -#if __GLASGOW_HASKELL__ < 806-{-# LANGUAGE TypeInType #-}-#endif- {-# OPTIONS_GHC -Wno-missing-methods #-} {-# OPTIONS_HADDOCK not-home #-} 
src/Clash/Class/Num.hs view
@@ -52,6 +52,7 @@   | SatSymmetric -- ^ Become 'maxBound' on overflow, and (@'minBound' + 1@) on                  -- underflow for signed numbers, and 'minBound' for unsigned                  -- numbers.+  | SatError -- ^ Become an XException on overflow and underflow   deriving (Show, Eq, Enum, Bounded)  -- | 'Num' operators in which overflow and underflow behavior can be specified
src/Clash/Class/Parity.hs view
@@ -30,6 +30,7 @@ import Clash.Promoted.Nat             (SNat(..), snatToNum)  {- $setup+>>> :m -Prelude >>> import Clash.Prelude >>> import Clash.Class.Parity -}
src/Clash/Examples.hs view
@@ -31,8 +31,6 @@  {- $setup >>> :set -XDataKinds->>> :m -Clash.Explicit.Prelude->>> :m -Clash.Signal.Internal >>> import Clash.Prelude >>> import Test.QuickCheck ((===)) >>> import Clash.Examples.Internal@@ -79,9 +77,9 @@ Examples:  >>> decoderCase True 3-0000_0000_0000_1000+0b0000_0000_0000_1000 >>> decoderShift True 7-0000_0000_1000_0000+0b0000_0000_1000_0000  The following property holds: 
src/Clash/Explicit/BlockRam.hs view
@@ -239,7 +239,7 @@  @ >>> printX $ sampleN 32 $ system2 prog systemClockGen resetGen enableGen-[X,X,X,X,X,X,4,4,4,4,4,4,4,4,6,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2]+[undefined,undefined,undefined,undefined,undefined,undefined,4,4,4,4,4,4,4,4,6,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2]  @ @@ -369,7 +369,7 @@  @ >>> printX $ sampleN 34 $ system3 prog2 systemClockGen resetGen enableGen-[X,0,0,0,0,0,0,4,4,4,4,4,4,4,4,6,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2]+[undefined,0,0,0,0,0,0,4,4,4,4,4,4,4,4,6,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2]  @ @@ -377,14 +377,18 @@  -} +{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE GADTs #-}-{-# LANGUAGE NoImplicitPrelude#-}+{-# LANGUAGE NoImplicitPrelude #-}  {-# LANGUAGE Trustworthy #-}  {-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-} {-# OPTIONS_HADDOCK show-extensions #-} +-- See [Note: eta port names for trueDualPortBlockRam]+{-# OPTIONS_GHC -fno-do-lambda-eta-expansion #-}+ -- See: https://github.com/clash-lang/clash-compiler/commit/721fcfa9198925661cd836668705f817bddaae3c -- as to why we need this. {-# OPTIONS_GHC -fno-cpr-anal #-}@@ -396,19 +400,36 @@   , blockRamU   , blockRam1   , ResetStrategy(..)-    -- * Read/Write conflict resolution+    -- ** Read/write conflict resolution   , readNew+    -- * True dual-port block RAM+    -- $tdpbram+  , trueDualPortBlockRam+  , RamOp(..)     -- * Internal   , blockRam#+  , trueDualPortBlockRam#   ) where  import           Clash.HaskellPrelude -import           Data.Maybe             (isJust)+import           Control.Exception      (catch, throw)+import           Control.Monad          (forM_)+import           Control.Monad.ST       (ST, runST)+import           Control.Monad.ST.Unsafe (unsafeInterleaveST, unsafeIOToST, unsafeSTToIO)+import           Data.Array.MArray      (newListArray)+import qualified Data.List              as L+import           Data.Maybe             (isJust, fromMaybe)+import           GHC.Arr+  (STArray, unsafeReadSTArray, unsafeWriteSTArray) import qualified Data.Sequence          as Seq+import           Data.Sequence          (Seq)+import           Data.Tuple             (swap)+import           GHC.Generics           (Generic) import           GHC.Stack              (HasCallStack, withFrozenCallStack) import           GHC.TypeLits           (KnownNat, type (^), type (<=))+import           Unsafe.Coerce          (unsafeCoerce)  import           Clash.Annotations.Primitive   (hasBlackBox)@@ -416,18 +437,33 @@ import           Clash.Explicit.Signal  (KnownDomain, Enable, register, fromEnable) import           Clash.Signal.Internal   (Clock(..), Reset, Signal (..), invertReset, (.&&.), mux)-import           Clash.Promoted.Nat     (SNat(..))-import           Clash.Signal.Bundle    (unbundle)+import           Clash.Promoted.Nat     (SNat(..), snatToNum, natToNum)+import           Clash.Signal.Bundle    (unbundle, bundle)+import           Clash.Signal.Internal.Ambiguous (clockPeriod) import           Clash.Sized.Unsigned   (Unsigned) import           Clash.Sized.Index      (Index)-import           Clash.Sized.Vector     (Vec, replicate, toList, iterateI)+import           Clash.Sized.Vector     (Vec, replicate, iterateI) import qualified Clash.Sized.Vector     as CV import           Clash.XException-  (maybeIsX, seqX, NFDataX, deepErrorX, defaultSeqX, fromJustX, undefined)+  (maybeIsX, NFDataX(deepErrorX), defaultSeqX, fromJustX, undefined,+   XException (..), seqX, isX, errorX) +{- $tdpbram+A true dual-port block RAM has two fully independent, fully functional access+ports: port A and port B. Either port can do both RAM reads and writes. These+two ports can even be on distinct clock domains, but the memory itself is shared+between the ports. This also makes a true dual-port block RAM suitable as a+component in a domain crossing circuit (but it needs additional logic for it to+be safe, see e.g. 'Clash.Explicit.Synchronizer.asyncFIFOSynchronizer').++A version with implicit clocks can be found in "Clash.Prelude.BlockRam".+-}++-- start benchmark only+-- import GHC.Arr (listArray, unsafeThawSTArray)+-- end benchmark only+ {- $setup->>> :m -Clash.Prelude->>> :m -Clash.Prelude.Safe >>> import Clash.Explicit.Prelude as C >>> import qualified Data.List as L >>> :set -XDataKinds -XRecordWildCards -XTupleSections -XDeriveAnyClass -XDeriveGeneric@@ -697,7 +733,7 @@ -- -- * __NB__: Read value is delayed by 1 cycle -- * __NB__: Initial output value is /undefined/, reading it will throw an--- 'Clash.XException.XException'+-- 'XException' -- -- @ -- bram40@@ -714,6 +750,10 @@ -- * See "Clash.Explicit.BlockRam#usingrams" for more information on how to use a -- Block RAM. -- * Use the adapter 'readNew' for obtaining write-before-read semantics like this: @'readNew' clk rst ('blockRam' clk inits) rd wrM@.+-- * A large 'Vec' for the initial content might be too inefficient, depending+-- on how it is constructed. See 'Clash.Explicit.BlockRam.File.blockRamFile' and+-- 'Clash.Explicit.BlockRam.Blob.blockRamBlob' for different approaches that+-- scale well. blockRam   :: ( KnownDomain dom      , HasCallStack@@ -744,7 +784,7 @@ -- -- * __NB__: Read value is delayed by 1 cycle -- * __NB__: Initial output value is /undefined/, reading it will throw an--- 'Clash.XException.XException'+-- 'XException' -- -- @ -- bram32@@ -761,6 +801,10 @@ -- * See "Clash.Prelude.BlockRam#usingrams" for more information on how to use a -- Block RAM. -- * Use the adapter 'readNew' for obtaining write-before-read semantics like this: @'readNew' clk rst ('blockRamPow2' clk inits) rd wrM@.+-- * A large 'Vec' for the initial content might be too inefficient, depending+-- on how it is constructed. See 'Clash.Explicit.BlockRam.File.blockRamFilePow2'+-- and 'Clash.Explicit.BlockRam.Blob.blockRamBlobPow2' for different approaches+-- that scale well. blockRamPow2   :: ( KnownDomain dom      , HasCallStack@@ -970,7 +1014,8 @@  -- | blockRAM primitive blockRam#-  :: ( KnownDomain dom+  :: forall dom a n+   . ( KnownDomain dom      , HasCallStack      , NFDataX a )   => Clock dom@@ -992,33 +1037,74 @@   -- ^ Value to write (at address @w@)   -> Signal dom a   -- ^ Value of the @blockRAM@ at address @r@ from the previous clock cycle-blockRam# (Clock _) gen content rd wen =+blockRam# (Clock _) gen content = \rd wen waS wd -> runST $ do+  ramStart <- newListArray (0,szI-1) contentL+  -- start benchmark only+  -- ramStart <- unsafeThawSTArray ramArr+  -- end benchmark only   go-    (Seq.fromList (toList content))+    ramStart     (withFrozenCallStack (deepErrorX "blockRam: intial value undefined"))     (fromEnable gen)     rd     (fromEnable gen .&&. wen)+    waS+    wd  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 `Seq.index` 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)+  contentL = unsafeCoerce content :: [a]+  szI = L.length contentL+  -- start benchmark only+  -- ramArr = listArray (0,szI-1) contentL+  -- end benchmark only +  go :: STArray s Int a -> a -> Signal dom Bool -> Signal dom Int+     -> Signal dom Bool -> Signal dom Int -> Signal dom a+     -> ST s (Signal dom a)+  go !ram o ret@(~(re :- res)) rt@(~(r :- rs)) et@(~(e :- en)) wt@(~(w :- wr)) dt@(~(d :- din)) = do+    o `seqX` (o :-) <$> (ret `seq` rt `seq` et `seq` wt `seq` dt `seq`+      unsafeInterleaveST+        (do o' <- unsafeIOToST+                    (catch (if re then unsafeSTToIO (ram `safeAt` r) else pure o)+                    (\err@XException {} -> pure (throw err)))+            d `defaultSeqX` upd ram e (fromEnum w) d+            go ram o' res rs en wr din))++  upd :: STArray s Int a -> Bool -> Int -> a -> ST s ()   upd ram we waddr d = case maybeIsX we of     Nothing -> case maybeIsX waddr of       Nothing -> -- Put the XException from `waddr` as the value in all                  -- locations of `ram`.-                 seq waddr d <$ ram+                 forM_ [0..(szI-1)] (\i -> unsafeWriteSTArray ram i (seq waddr d))       Just wa -> -- Put the XException from `we` as the value at address                  -- `waddr`.-                 Seq.update wa (seq we d) ram+                 safeUpdate wa (seq we d) ram     Just True -> case maybeIsX waddr of       Nothing -> -- Put the XException from `waddr` as the value in all                  -- locations of `ram`.-                 seq waddr d <$ ram-      Just wa -> Seq.update wa d ram-    _ -> ram+                 forM_ [0..(szI-1)] (\i -> unsafeWriteSTArray ram i (seq waddr d))+      Just wa -> safeUpdate wa d ram+    _ -> return ()++  safeAt :: HasCallStack => STArray s Int a -> Int -> ST s a+  safeAt s i =+    if (0 <= i) && (i < szI) then+      unsafeReadSTArray s i+    else pure $+      withFrozenCallStack+        (deepErrorX ("blockRam: read address " <> show i <>+                     " not in range [0.." <> show szI <> ")"))+  {-# INLINE safeAt #-}++  safeUpdate :: HasCallStack => Int -> a -> STArray s Int a -> ST s ()+  safeUpdate i a s =+    if (0 <= i) && (i < szI) then+      unsafeWriteSTArray s i a+    else+      let d = withFrozenCallStack+                (deepErrorX ("blockRam: write address " <> show i <>+                             " not in range [0.." <> show szI <> ")"))+       in forM_ [0..(szI-1)] (\j -> unsafeWriteSTArray s j d)+  {-# INLINE safeUpdate #-} {-# ANN blockRam# hasBlackBox #-} {-# NOINLINE blockRam# #-} @@ -1045,3 +1131,308 @@         (wasSame,wasWritten) =           unbundle (register clk rst en (False, undefined)                              (readNewT <$> rdAddr <*> wrM))++-- | Port operation+data RamOp n a+  = RamRead (Index n)+  -- ^ Read from address+  | RamWrite (Index n) a+  -- ^ Write data to address+  | RamNoOp+  -- ^ No operation+  deriving (Generic, NFDataX, Show)++ramOpAddr :: RamOp n a -> Index n+ramOpAddr (RamRead addr)    = addr+ramOpAddr (RamWrite addr _) = addr+ramOpAddr RamNoOp           = errorX "Address for No operation undefined"++isRamWrite :: RamOp n a -> Bool+isRamWrite (RamWrite {}) = True+isRamWrite _             = False++ramOpWriteVal :: RamOp n a -> Maybe a+ramOpWriteVal (RamWrite _ val) = Just val+ramOpWriteVal _                = Nothing++isOp :: RamOp n a -> Bool+isOp RamNoOp = False+isOp _       = True++-- | Produces vendor-agnostic HDL that will be inferred as a true dual-port+-- block RAM+--+-- Any value that is being written on a particular port is also the+-- value that will be read on that port, i.e. the same-port read/write behavior+-- 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 ::+  forall nAddrs domA domB a .+  ( HasCallStack+  , KnownNat nAddrs+  , KnownDomain domA+  , KnownDomain domB+  , NFDataX a+  )+  => Clock domA+  -- ^ Clock for port A+  -> Clock domB+  -- ^ Clock for port B+  -> Signal domA (RamOp nAddrs a)+  -- ^ RAM operation for port A+  -> Signal domB (RamOp nAddrs a)+  -- ^ RAM operation for port B+  -> (Signal domA a, Signal domB a)+  -- ^ Outputs data on /next/ cycle. When writing, the data written+  -- will be echoed. When reading, the read data is returned.++{-# INLINE trueDualPortBlockRam #-}+trueDualPortBlockRam = \clkA clkB opA opB ->+  trueDualPortBlockRamWrapper+    clkA (isOp <$> opA) (isRamWrite <$> opA) (ramOpAddr <$> opA) (fromJustX . ramOpWriteVal <$> opA)+    clkB (isOp <$> opB) (isRamWrite <$> opB) (ramOpAddr <$> opB) (fromJustX . ramOpWriteVal <$> opB)++toMaybeX :: a -> MaybeX a+toMaybeX a =+  case isX a of+    Left _ -> IsX+    Right _ -> IsDefined a++data MaybeX a = IsX | IsDefined !a++data Conflict = Conflict+  { cfWrite :: !(MaybeX Bool)+  , cfAddress :: !(MaybeX Int) }++instance Semigroup Conflict where+  (<>) = mergeConflicts++-- | "Stronger" conflict wins:+--+--   * Writes over read+--   * Undefineds over anything+--+mergeConflicts :: Conflict -> Conflict -> Conflict+mergeConflicts conflict1 conflict2 = Conflict+  { cfWrite = mergeWrite (cfWrite conflict1) (cfWrite conflict2)+  , cfAddress = mergeAddress (cfAddress conflict1) (cfAddress conflict2) }+ where+  mergeX _ IsX _ = IsX+  mergeX _ _ IsX = IsX+  mergeX f (IsDefined a) (IsDefined b) = IsDefined (f a b)++  mergeWrite a b = mergeX (||) a b+  mergeAddress a b = mergeX const a b++-- [Note: eta port names for trueDualPortBlockRam]+--+-- By naming all the arguments and setting the -fno-do-lambda-eta-expansion GHC+-- option for this module, the generated HDL also contains names based on the+-- argument names used here. This greatly improves readability of the HDL.++-- [Note: true dual-port blockRAM separate architecture]+--+-- A multi-clock true dual-port block RAM is only inferred from the generated HDL+-- when it lives in its own Verilog module / VHDL architecture. Add any other+-- logic to the module / architecture, and synthesis will no longer infer a+-- multi-clock true dual-port block RAM. This wrapper pushes the primitive out+-- 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+{-# NOINLINE trueDualPortBlockRamWrapper #-}++-- | Primitive of 'trueDualPortBlockRam'.+trueDualPortBlockRam#, trueDualPortBlockRamWrapper ::+  forall nAddrs domA domB a .+  ( HasCallStack+  , KnownNat nAddrs+  , KnownDomain domA+  , KnownDomain domB+  , NFDataX a+  )+  => Clock domA+  -- ^ Clock for port A+  -> Signal domA Bool+  -- ^ Enable for port A+  -> Signal domA Bool+  -- ^ Write enable for port A+  -> Signal domA (Index nAddrs)+  -- ^ Address to read from or write to on port A+  -> Signal domA a+  -- ^ Data in for port A; ignored when /write enable/ is @False@++  -> Clock domB+  -- ^ Clock for port B+  -> Signal domB Bool+  -- ^ Enable for port B+  -> Signal domB Bool+  -- ^ Write enable for port B+  -> Signal domB (Index nAddrs)+  -- ^ Address to read from or write to on port B+  -> Signal domB a+  -- ^ Data in for port B; ignored when /write enable/ is @False@++  -> (Signal domA a, Signal domB a)+  -- ^ Outputs data on /next/ cycle. If write enable is @True@, the data written+  -- will be echoed. If write enable is @False@, the read data is returned. If+  -- port enable is @False@, it is /undefined/.+trueDualPortBlockRam# clkA enA weA addrA datA clkB enB weB addrB datB+  | snatToNum @Int (clockPeriod @domA) < snatToNum @Int (clockPeriod @domB)+  = swap (trueDualPortBlockRamModel clkB enB weB addrB datB clkA enA weA addrA datA)+  | otherwise+  =       trueDualPortBlockRamModel clkA enA weA addrA datA clkB enB weB addrB datB+{-# NOINLINE trueDualPortBlockRam# #-}+{-# ANN trueDualPortBlockRam# hasBlackBox #-}+++-- | Haskell model for the primitive 'trueDualPortBlockRam#'.+--+-- Warning: this model only works if @domFast@'s clock is faster (or equal to)+-- @domSlow@'s clock.+trueDualPortBlockRamModel ::+  forall nAddrs domFast domSlow a .+  ( HasCallStack+  , KnownNat nAddrs+  , KnownDomain domSlow+  , KnownDomain domFast+  , NFDataX a+  ) =>++  Clock domSlow ->+  Signal domSlow Bool ->+  Signal domSlow Bool ->+  Signal domSlow (Index nAddrs) ->+  Signal domSlow a ->++  Clock domFast ->+  Signal domFast Bool ->+  Signal domFast Bool ->+  Signal domFast (Index nAddrs) ->+  Signal domFast a ->++  (Signal domSlow a, Signal domFast a)+trueDualPortBlockRamModel !_clkA enA weA addrA datA !_clkB enB weB addrB datB =+  ( deepErrorX "trueDualPortBlockRam: Port A: First value undefined" :- outA+  , deepErrorX "trueDualPortBlockRam: Port B: First value undefined" :- outB )+ where+  (outA, outB) =+    go+      Nothing+      (Seq.fromFunction (natToNum @nAddrs) initElement)+      tA -- ensure 'go' hits fast clock first+      (bundle (enA, weA, fromIntegral <$> addrA, datA))+      (bundle (enB, weB, fromIntegral <$> addrB, datB))++  tA = snatToNum @Int (clockPeriod @domSlow)+  tB = snatToNum @Int (clockPeriod @domFast)++  initElement :: Int -> a+  initElement n =+    deepErrorX ("Unknown initial element; position " <> show n)++  unknownEnableAndAddr :: String -> String -> Int -> a+  unknownEnableAndAddr enaMsg addrMsg n =+    deepErrorX ("Write enable and data unknown; position " <> show n <>+                "\nWrite enable error message: " <> enaMsg <>+                "\nAddress error message: " <> addrMsg)++  unknownAddr :: String -> Int -> a+  unknownAddr msg n =+    deepErrorX ("Write enabled, but address unknown; position " <> show n <>+                "\nAddress error message: " <> msg)++  getConflict :: Bool -> Int -> Bool -> Int -> Maybe Conflict+  getConflict enableA addrA_ enableB addrB_ =+    -- If port A or port B is writing on (potentially!) the same address,+    -- there's a conflict+    if sameAddr then maybeConflict else Nothing+   where+    conflict = Conflict+      { cfWrite = toMaybeX enableA+      , cfAddress = toMaybeX addrA_ }++    maybeConflict =+      case (isX enableA, isX enableB) of+        (Left _, _)     -> Just conflict+        (Right True, _) -> Just conflict+        (_, Left _)     -> Just conflict+        (_, Right True) -> Just conflict+        _               -> Nothing++    sameAddr =+      case (isX addrA_, isX addrB_) of+        (Left _, _) -> True+        (_, Left _) -> True+        _           -> addrA_ == addrB_++  writeRam :: Bool -> Int -> a -> Seq a -> (Maybe a, Seq a)+  writeRam enable addr dat mem+    | Left enaMsg <- enableUndefined+    , Left addrMsg <- addrUndefined+    = let msg = "Unknown enable and address" <>+                "\nWrite enable error message: " <> enaMsg <>+                "\nAddress error message: " <> addrMsg+       in ( Just (deepErrorX msg)+          , Seq.fromFunction (natToNum @nAddrs)+                             (unknownEnableAndAddr enaMsg addrMsg) )+    | Left enaMsg <- enableUndefined+    = let msg = "Write enable unknown; position" <> show addr <>+                "\nWrite enable error message: " <> enaMsg+       in writeRam True addr (deepErrorX msg) mem+    | enable+    , Left addrMsg <- addrUndefined+    = ( Just (deepErrorX "Unknown address")+      , Seq.fromFunction (natToNum @nAddrs) (unknownAddr addrMsg) )+    | enable+    = (Just dat, Seq.update addr dat mem)+    | otherwise+    = (Nothing, mem)+   where+    enableUndefined = isX enable+    addrUndefined = isX addr++  go ::+    Maybe Conflict ->+    Seq a ->+    Int ->+    Signal domSlow (Bool, Bool, Int, a) ->+    Signal domFast (Bool, Bool, Int, a) ->+    (Signal domSlow a, Signal domFast a)+  go conflict0 ram0 relativeTime as0 bs0 =+    if relativeTime <= 0 then goSlow else goFast+   where+    (enA_, weA_, addrA_, datA_) :- as1 = as0+    (enB_, weB_, addrB_, datB_) :- bs1 = bs0++    -- 1 iteration here, as this is the slow clock.+    goSlow = out1 `seqX` (out1 :- as2, bs2)+     where+      (wrote, !ram1) = writeRam weA_ addrA_ datA_ ram0+      out0 = fromMaybe (ram1 `Seq.index` addrA_) wrote+      (as2, bs2) = go Nothing ram1 (relativeTime + tA) as1 bs0+      out1 =+        case conflict0 of+          Just Conflict{cfWrite=IsDefined True} ->+            deepErrorX "trueDualPortBlockRam: conflicting read/write queries"+          Just Conflict{cfWrite=IsX} ->+            deepErrorX "trueDualPortBlockRam: conflicting read/write queries"+          _ -> out0++    -- 1 or more iterations here, as this is the fast clock. First iteration+    -- happens here.+    goFast = out1 `seqX` (as2, out1 :- bs2)+     where+      conflict1 | enA_ && enB_ = getConflict weB_ addrB_ weA_ addrA_+                | otherwise    = Nothing+      (wrote, !ram1) = writeRam weB_ addrB_ datB_ ram0+      out0 = fromMaybe (ram1 `Seq.index` addrB_) wrote+      conflict2 = conflict0 <> conflict1+      (as2, bs2) = go conflict2 ram1 (relativeTime - tB) as0 bs1+      out1 =+        case conflict1 of+          Just Conflict{cfWrite=IsDefined False} ->+            deepErrorX "trueDualPortBlockRam: conflicting read/write queries"+          Just Conflict{cfWrite=IsX} ->+            deepErrorX "trueDualPortBlockRam: conflicting read/write queries"+          _ ->+            out0
+ src/Clash/Explicit/BlockRam/Blob.hs view
@@ -0,0 +1,385 @@+{-|+Copyright  :  (C) 2021-2022, QBayLogic B.V.+License    :  BSD2 (see the file LICENSE)+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>++= Efficient bundling of initial RAM content with the compiled code++Leveraging Template Haskell, the initial content for the blockRAM components in+this module is stored alongside the compiled Haskell code. It covers use cases+where passing the initial content as a 'Clash.Sized.Vector.Vec' turns out to be+problematically slow.++The data is stored efficiently, with very little overhead (worst-case 7%, often+no overhead at all).++Unlike "Clash.Explicit.BlockRam.File", "Clash.Explicit.BlockRam.Blob"+generates practically the same HDL as "Clash.Explicit.BlockRam" and is+compatible with all tools consuming the generated HDL.+-}++{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE Trustworthy #-}+{-# LANGUAGE TypeApplications #-}++{-# OPTIONS_HADDOCK show-extensions #-}++module Clash.Explicit.BlockRam.Blob+  ( -- * BlockRAMs initialized with a 'MemBlob'+    blockRamBlob+  , blockRamBlobPow2+    -- * Creating and inspecting 'MemBlob'+  , MemBlob+  , createMemBlob+  , memBlobTH+  , unpackMemBlob+    -- * Internal+  , blockRamBlob#+  ) where++import Control.Exception (catch, throw)+import Control.Monad (forM_)+import Control.Monad.ST (ST, runST)+import Control.Monad.ST.Unsafe (unsafeInterleaveST, unsafeIOToST, unsafeSTToIO)+import Data.Array.MArray (newListArray)+import qualified Data.ByteString.Lazy as L+import Data.Maybe (isJust)+import GHC.Arr (STArray, unsafeReadSTArray, unsafeWriteSTArray)+import GHC.Stack (withFrozenCallStack)+import GHC.TypeLits (KnownNat, type (^))+import Language.Haskell.TH+  (DecsQ, ExpQ, integerL, litE, litT, mkName, normalB, numTyLit, sigD,+   stringPrimL, valD, varP)++import Clash.Annotations.Primitive (hasBlackBox)+import Clash.Class.BitPack.Internal (BitPack, BitSize)+import Clash.Explicit.BlockRam.Internal+  (MemBlob(..), packBVs, unpackMemBlob, unpackMemBlob0)+import Clash.Explicit.Signal (KnownDomain, Enable, fromEnable)+import Clash.Promoted.Nat (natToInteger, natToNum)+import Clash.Signal.Bundle (unbundle)+import Clash.Signal.Internal (Clock, Signal(..), (.&&.))+import Clash.Sized.Internal.BitVector (Bit(..), BitVector(..))+import Clash.Sized.Internal.Unsigned (Unsigned)+import Clash.XException+  (maybeIsX, deepErrorX, defaultSeqX, fromJustX, XException (..), seqX)++-- $setup+-- >>> :set -XTemplateHaskell+-- >>> :set -fplugin GHC.TypeLits.Normalise+-- >>> :set -fplugin GHC.TypeLits.KnownNat.Solver+-- >>> :m -Prelude+-- >>> import Clash.Explicit.Prelude++-- | Create a blockRAM with space for @n@ elements+--+-- * __NB__: Read value is delayed by 1 cycle+-- * __NB__: Initial output value is /undefined/, reading it will throw an+-- 'Clash.XException.XException'+--+--+-- Additional helpful information:+--+-- * See "Clash.Prelude.BlockRam#usingrams" for more information on how to use a+-- Block RAM.+-- * Use the adapter 'Clash.Explicit.BlockRam.readNew' for obtaining+-- write-before-read semantics like this: @'Clash.Explicit.BlockRam.readNew'+-- clk rst en ('blockRamBlob' clk en content) rd wrM@.+blockRamBlob+  :: forall dom addr m n+   . ( KnownDomain dom+     , Enum addr+     )+  => Clock dom+  -- ^ 'Clock' to synchronize to+  -> Enable dom+  -- ^ 'Enable' line+  -> MemBlob n m+  -- ^ Initial content of the RAM, also determines the size, @n@, of the RAM+  --+  -- __NB__: __MUST__ be a constant+  -> Signal dom addr+  -- ^ Read address @r@+  -> Signal dom (Maybe (addr, BitVector m))+  -- ^ (write address @w@, value to write)+  -> Signal dom (BitVector m)+  -- ^ Value of the blockRAM at address @r@ from the previous clock cycle+blockRamBlob = \clk gen content rd wrM ->+  let en       = isJust <$> wrM+      (wr,din) = unbundle (fromJustX <$> wrM)+  in blockRamBlob# clk gen content (fromEnum <$> rd) en (fromEnum <$> wr) din+{-# INLINE blockRamBlob #-}++-- | Create a blockRAM with space for 2^@n@ elements+--+-- * __NB__: Read value is delayed by 1 cycle+-- * __NB__: Initial output value is /undefined/, reading it will throw an+-- 'XException'+--+-- Additional helpful information:+--+-- * See "Clash.Prelude.BlockRam#usingrams" for more information on how to use a+-- Block RAM.+-- * Use the adapter 'Clash.Explicit.BlockRam.readNew' for obtaining+-- write-before-read semantics like this: @'Clash.Explicit.BlockRam.readNew'+-- clk rst en ('blockRamBlobPow2' clk en content) rd wrM@.+blockRamBlobPow2+  :: forall dom m n+   . ( KnownDomain dom+     , KnownNat n+     )+  => Clock dom+  -- ^ 'Clock' to synchronize to+  -> Enable dom+  -- ^ 'Enable' line+  -> MemBlob (2^n) m+  -- ^ Initial content of the RAM, also determines the size, 2^@n@, of the RAM+  --+  -- __NB__: __MUST__ be a constant+  -> Signal dom (Unsigned n)+  -- ^ Read address @r@+  -> Signal dom (Maybe (Unsigned n, BitVector m))+  -- ^ (write address @w@, value to write)+  -> Signal dom (BitVector m)+  -- ^ Value of the blockRAM at address @r@ from the previous clock cycle+blockRamBlobPow2 = blockRamBlob+{-# INLINE blockRamBlobPow2 #-}++-- | BlockRAM primitive+blockRamBlob#+  :: forall dom m n+   . KnownDomain dom+  => Clock dom+  -- ^ 'Clock' to synchronize to+  -> Enable dom+  -- ^ 'Enable' line+  -> MemBlob n m+  -- ^ Initial content of the RAM, also determines the size, @n@, of the RAM+  --+  -- __NB__: __MUST__ be a constant+  -> Signal dom Int+  -- ^ Read address @r@+  -> Signal dom Bool+  -- ^ Write enable+  -> Signal dom Int+  -- ^ Write address @w@+  -> Signal dom (BitVector m)+  -- ^ Value to write (at address @w@)+  -> Signal dom (BitVector m)+  -- ^ Value of the blockRAM at address @r@ from the previous clock cycle+blockRamBlob# !_ gen content@MemBlob{} = \rd wen waS wd -> runST $ do+  bvList <- unsafeIOToST (unpackMemBlob0 content)+  ramStart <- newListArray (0,szI-1) bvList+  go+    ramStart+    (withFrozenCallStack (deepErrorX "blockRamBlob: intial value undefined"))+    (fromEnable gen)+    rd+    (fromEnable gen .&&. wen)+    waS+    wd+ where+  szI = natToNum @n @Int++  go :: STArray s Int (BitVector m) -> BitVector m -> Signal dom Bool+     -> Signal dom Int -> Signal dom Bool -> Signal dom Int+     -> Signal dom (BitVector m) -> ST s (Signal dom (BitVector m))+  go !ram o ret@(~(re :- res)) rt@(~(r :- rs)) et@(~(e :- en)) wt@(~(w :- wr))+     dt@(~(d :- din)) = do+    o `seqX` (o :-) <$> (ret `seq` rt `seq` et `seq` wt `seq` dt `seq`+      unsafeInterleaveST+        (do o' <- unsafeIOToST+                    (catch (if re then unsafeSTToIO (ram `safeAt` r) else pure o)+                    (\err@XException {} -> pure (throw err)))+            d `defaultSeqX` upd ram e w d+            go ram o' res rs en wr din))++  upd :: STArray s Int (BitVector m) -> Bool -> Int -> BitVector m -> ST s ()+  upd ram we waddr d = case maybeIsX we of+    Nothing -> case maybeIsX waddr of+      Nothing -> -- Put the XException from `waddr` as the value in all+                 -- locations of `ram`.+                 forM_ [0..(szI-1)] (\i -> unsafeWriteSTArray ram i (seq waddr d))+      Just wa -> -- Put the XException from `we` as the value at address+                 -- `waddr`.+                 safeUpdate wa (seq we d) ram+    Just True -> case maybeIsX waddr of+      Nothing -> -- Put the XException from `waddr` as the value in all+                 -- locations of `ram`.+                 forM_ [0..(szI-1)] (\i -> unsafeWriteSTArray ram i (seq waddr d))+      Just wa -> safeUpdate wa d ram+    _ -> return ()++  safeAt :: STArray s Int (BitVector m) -> Int -> ST s (BitVector m)+  safeAt s i =+    if (0 <= i) && (i < szI) then+      unsafeReadSTArray s i+    else pure $+      withFrozenCallStack+        (deepErrorX ("blockRamBlob: read address " <> show i <>+                     " not in range [0.." <> show szI <> ")"))+  {-# INLINE safeAt #-}++  safeUpdate :: Int -> BitVector m -> STArray s Int (BitVector m) -> ST s ()+  safeUpdate i a s =+    if (0 <= i) && (i < szI) then+      unsafeWriteSTArray s i a+    else+      let d = withFrozenCallStack+                (deepErrorX ("blockRam: write address " <> show i <>+                             " not in range [0.." <> show szI <> ")"))+       in forM_ [0..(szI-1)] (\j -> unsafeWriteSTArray s j d)+  {-# INLINE safeUpdate #-}+{-# ANN blockRamBlob# hasBlackBox #-}+{-# NOINLINE blockRamBlob# #-}++-- | Create a 'MemBlob' binding from a list of values+--+-- Since this uses Template Haskell, nothing in the arguments given to+-- 'createMemBlob' can refer to something defined in the same module.+--+-- === __Example__+--+-- @+-- 'createMemBlob' "content" 'Nothing' [15 :: Unsigned 8 .. 17]+--+-- ram clk en = 'blockRamBlob' clk en content+-- @+--+-- The 'Data.Maybe.Maybe' datatype has don't care bits, where the actual value+-- does not matter. But the bits need a defined value in the memory. Either 0 or+-- 1 can be used, and both are valid representations of the data.+--+-- >>> import qualified Prelude as P+-- >>> let es = [ Nothing, Just (7 :: Unsigned 8), Just 8 ]+-- >>> :{+-- createMemBlob "content0" (Just 0) es+-- createMemBlob "content1" (Just 1) es+-- x = 1+-- :}+--+-- >>> let pr = mapM_ (putStrLn . show)+-- >>> pr $ P.map pack es+-- 0b0_...._....+-- 0b1_0000_0111+-- 0b1_0000_1000+-- >>> pr $ unpackMemBlob content0+-- 0b0_0000_0000+-- 0b1_0000_0111+-- 0b1_0000_1000+-- >>> pr $ unpackMemBlob content1+-- 0b0_1111_1111+-- 0b1_0000_0111+-- 0b1_0000_1000+-- >>> :{+-- createMemBlob "contentN" Nothing es+-- x = 1+-- :}+-- <BLANKLINE>+-- <interactive>:...: error:+--     packBVs: cannot convert don't care values. Please specify a mapping to a definite value.+--+-- Note how we hinted to @clashi@ that our multi-line command was a list of+-- declarations by including a dummy declaration @x = 1@. Without this trick,+-- @clashi@ would expect an expression and the Template Haskell would not work.+createMemBlob+  :: forall a f+   . ( Foldable f+     , BitPack a+     )+  => String+  -- ^ Name of the binding to generate+  -> Maybe Bit+  -- ^ Value to map don't care bits to. 'Nothing' means throwing an error on+  -- don't care bits.+  -> f a+  -- ^ The content for the 'MemBlob'+  -> DecsQ+createMemBlob name care es =+  case packed of+    Left err -> fail err+    Right _ -> sequence+      [ sigD name0 [t| MemBlob $(n) $(m) |]+      , valD (varP name0) (normalB [| MemBlob { memBlobRunsLen = $(runsLen)+                                              , memBlobRuns = $(runs)+                                              , memBlobEndsLen = $(endsLen)+                                              , memBlobEnds = $(ends)+                                              } |]) []+      ]+ where+  name0 = mkName name+  n = litT . numTyLit . toInteger $ len+  m = litT . numTyLit $ natToInteger @(BitSize a)+  runsLen = litE . integerL . toInteger $ L.length runsB+  runs = litE . stringPrimL $ L.unpack runsB+  endsLen = litE . integerL . toInteger $ L.length endsB+  ends = litE . stringPrimL $ L.unpack endsB+  Right (len, runsB, endsB) = packed+  packed = packBVs care es++-- | Create a 'MemBlob' from a list of values+--+-- Since this uses Template Haskell, nothing in the arguments given to+-- 'memBlobTH' can refer to something defined in the same module.+--+-- === __Example__+--+-- @+-- ram clk en = 'blockRamBlob' clk en $(memBlobTH Nothing [15 :: Unsigned 8 .. 17])+-- @+--+-- The 'Data.Maybe.Maybe' datatype has don't care bits, where the actual value+-- does not matter. But the bits need a defined value in the memory. Either 0 or+-- 1 can be used, and both are valid representations of the data.+--+-- >>> import qualified Prelude as P+-- >>> let es = [ Nothing, Just (7 :: Unsigned 8), Just 8 ]+-- >>> content0 = $(memBlobTH (Just 0) es)+-- >>> content1 = $(memBlobTH (Just 1) es)+-- >>> let pr = mapM_ (putStrLn . show)+-- >>> pr $ P.map pack es+-- 0b0_...._....+-- 0b1_0000_0111+-- 0b1_0000_1000+-- >>> pr $ unpackMemBlob content0+-- 0b0_0000_0000+-- 0b1_0000_0111+-- 0b1_0000_1000+-- >>> pr $ unpackMemBlob content1+-- 0b0_1111_1111+-- 0b1_0000_0111+-- 0b1_0000_1000+-- >>> $(memBlobTH Nothing es)+-- <BLANKLINE>+-- <interactive>:...: error:+--     • packBVs: cannot convert don't care values. Please specify a mapping to a definite value.+--     • In the untyped splice: $(memBlobTH Nothing es)+memBlobTH+  :: forall a f+   . ( Foldable f+     , BitPack a+     )+  => Maybe Bit+  -- ^ Value to map don't care bits to. 'Nothing' means throwing an error on+  -- don't care bits.+  -> f a+  -- ^ The content for the 'MemBlob'+  -> ExpQ+memBlobTH care es =+  case packed of+    Left err -> fail err+    Right _ -> [| MemBlob { memBlobRunsLen = $(runsLen)+                          , memBlobRuns = $(runs)+                          , memBlobEndsLen = $(endsLen)+                          , memBlobEnds = $(ends)+                          }+                    :: MemBlob $(n) $(m) |]+ where+  n = litT . numTyLit . toInteger $ len+  m = litT . numTyLit $ natToInteger @(BitSize a)+  runsLen = litE . integerL . toInteger $ L.length runsB+  runs = litE . stringPrimL $ L.unpack runsB+  endsLen = litE . integerL . toInteger $ L.length endsB+  ends = litE . stringPrimL $ L.unpack endsB+  Right (len, runsB, endsB) = packed+  packed = packBVs care es
src/Clash/Explicit/BlockRam/File.hs view
@@ -1,6 +1,6 @@ {-| Copyright  :  (C) 2015-2016, University of Twente,-                  2017     , Google Inc.+                  2017     , Google Inc.,                   2019     , Myrtle Software Ltd,                   2021-2022, QBayLogic B.V. License    :  BSD2 (see the file LICENSE)@@ -32,6 +32,12 @@ 000001101 @ +Such a file can be produced with 'memFile':++@+writeFile "memory.bin" (memFile Nothing [7 :: Unsigned 9 .. 13])+@+ We can instantiate a BlockRAM using the content of the above file like so:  @@@ -88,34 +94,55 @@   ( -- * BlockRAM synchronized to an arbitrary clock     blockRamFile   , blockRamFilePow2+    -- * Producing files+  , memFile     -- * Internal   , blockRamFile#   , initMem   ) where +import Control.Exception     (catch, throw)+import Control.Monad         (forM_)+import Control.Monad.ST      (ST, runST)+import Control.Monad.ST.Unsafe (unsafeInterleaveST, unsafeIOToST, unsafeSTToIO)+import Data.Array.MArray     (newArray_)+import Data.Bits             ((.&.), (.|.), shiftL, xor) import Data.Char             (digitToInt) import Data.Maybe            (isJust, listToMaybe)-import qualified Data.Sequence as Seq+import GHC.Arr               (STArray, unsafeReadSTArray, unsafeWriteSTArray) import GHC.Stack             (HasCallStack, withFrozenCallStack) import GHC.TypeLits          (KnownNat) import Numeric               (readInt)-import System.IO.Unsafe      (unsafePerformIO)+import System.IO -import Clash.Promoted.Nat    (SNat (..), pow2SNat)-import Clash.Sized.BitVector (BitVector)+import Clash.Annotations.Primitive (hasBlackBox)+import Clash.Class.BitPack   (BitPack, BitSize, pack)+import Clash.Promoted.Nat    (SNat (..), pow2SNat, natToNum, snatToNum)+import Clash.Sized.Internal.BitVector (Bit(..), BitVector(..), undefined#) import Clash.Signal.Internal   (Clock(..), Signal (..), Enable, KnownDomain, fromEnable, (.&&.)) import Clash.Signal.Bundle   (unbundle) import Clash.Sized.Unsigned  (Unsigned)-import Clash.XException      (errorX, maybeIsX, seqX, fromJustX)+import Clash.XException      (errorX, maybeIsX, seqX, fromJustX, XException (..)) +-- start benchmark only+-- import GHC.Arr (unsafeFreezeSTArray, unsafeThawSTArray)+-- end benchmark only +-- $setup+-- >>> :m -Prelude+-- >>> :set -fplugin GHC.TypeLits.Normalise+-- >>> :set -fplugin GHC.TypeLits.KnownNat.Solver+-- >>> import Clash.Prelude+-- >>> import Clash.Prelude.BlockRam.File++ -- | Create a blockRAM with space for 2^@n@ elements -- -- * __NB__: Read value is delayed by 1 cycle -- * __NB__: Initial output value is /undefined/, reading it will throw an--- 'Clash.XException.XException'+-- 'XException' -- * __NB__: This function might not work for specific combinations of -- code-generation backends and hardware targets. Please check the support table -- below:@@ -136,8 +163,9 @@ -- * Use the adapter 'Clash.Explicit.BlockRam.readNew' for obtaining write-before-read semantics like this: @'Clash.Explicit.BlockRam.readNew' clk rst en (blockRamFilePow2' clk en file) rd wrM@. -- * See "Clash.Explicit.BlockRam.File#usingramfiles" for more information on how -- to instantiate a Block RAM with the contents of a data file.--- * See "Clash.Explicit.Fixed#creatingdatafiles" for ideas on how to create your--- own data files.+-- * See 'memFile' for creating a data file with Clash.+-- * See "Clash.Explicit.Fixed#creatingdatafiles" for more ideas on how to+-- create your own data files. blockRamFilePow2   :: forall dom n m    . (KnownDomain dom, KnownNat m, KnownNat n, HasCallStack)@@ -161,7 +189,7 @@ -- -- * __NB__: Read value is delayed by 1 cycle -- * __NB__: Initial output value is /undefined/, reading it will throw an--- 'Clash.XException.XException'+-- 'XException' -- * __NB__: This function might not work for specific combinations of -- code-generation backends and hardware targets. Please check the support table -- below:@@ -182,8 +210,9 @@ -- * Use the adapter 'Clash.Explicit.BlockRam.readNew' for obtaining write-before-read semantics like this: @'Clash.Explicit.BlockRam.readNew' clk rst en ('blockRamFile' clk en size file) rd wrM@. -- * See "Clash.Explicit.BlockRam.File#usingramfiles" for more information on how -- to instantiate a Block RAM with the contents of a data file.--- * See "Clash.Sized.Fixed#creatingdatafiles" for ideas on how to create your--- own data files.+-- * See 'memFile' for creating a data file with Clash.+-- * See "Clash.Sized.Fixed#creatingdatafiles" for more ideas on how to create+-- your own data files. blockRamFile   :: (KnownDomain dom, KnownNat m, Enum addr, HasCallStack)   => Clock dom@@ -208,6 +237,80 @@       (blockRamFile# clk gen sz file (fromEnum <$> rd) en (fromEnum <$> wr) din) {-# INLINE blockRamFile #-} +-- | Convert data to the String contents of a memory file.+--+-- * __NB:__ Not synthesizable+-- * The following document the several ways to instantiate components with+-- files:+--+--     * "Clash.Prelude.BlockRam.File#usingramfiles"+--     * "Clash.Prelude.ROM.File#usingromfiles"+--     * "Clash.Explicit.BlockRam.File#usingramfiles"+--     * "Clash.Explicit.ROM.File#usingromfiles"+--+-- * See "Clash.Sized.Fixed#creatingdatafiles" for more ideas on how to create+-- your own data files.+--+-- = Example+--+-- The @Maybe@ datatype has don't care bits, where the actual value does not+-- matter. But the bits need a defined value in the memory. Either 0 or 1 can be+-- used, and both are valid representations of the data.+--+-- >>> let es = [ Nothing, Just (7 :: Unsigned 8), Just 8]+-- >>> mapM_ (putStrLn . show . pack) es+-- 0b0_...._....+-- 0b1_0000_0111+-- 0b1_0000_1000+-- >>> putStr (memFile (Just 0) es)+-- 000000000+-- 100000111+-- 100001000+-- >>> putStr (memFile (Just 1) es)+-- 011111111+-- 100000111+-- 100001000+--+memFile+  :: forall a f+   . ( BitPack a+     , Foldable f+     , HasCallStack)+  => Maybe Bit+  -- ^ Value to map don't care bits to. Nothing means throwing an error on+  -- don't care bits.+  -> f a+  -- ^ Values to convert.+  -> String+  -- ^ Contents of the memory file.+memFile care = foldr (\e -> showsBV $ pack e) ""+ where+  showsBV :: BitVector (BitSize a) -> String -> String+  showsBV (BV mask val) s =+    if n == 0 then+      '0' : '\n' : s+    else+      case care of+        Just (Bit 0 0) -> go n (val .&. (mask `xor` fullMask)) ('\n' : s)+        Just (Bit 0 1)  -> go n (val .|. mask) ('\n' : s)+        _ -> if mask /= 0 then+               err+             else+               go n val ('\n' : s)+   where+    n = natToNum @(BitSize a) @Int+    fullMask = (1 `shiftL` n) - 1+    err = withFrozenCallStack $ error $+            "memFile: cannot convert don't-care values. "+            ++ "Please specify mapping to definite value."+    go 0  _ s0 = s0+    go n0 v s0 =+      let (!v0, !vBit) = quotRem v 2+      in if vBit == 0 then+           go (n0 - 1) v0 $ '0' : s0+         else+           go (n0 - 1) v0 $ '1' : s0+ -- | blockRamFile primitive blockRamFile#   :: forall m dom n@@ -230,49 +333,95 @@   -- ^ Value to write (at address @w@)   -> Signal dom (BitVector m)   -- ^ Value of the @blockRAM@ at address @r@ from the previous clock cycle-blockRamFile# (Clock _) ena !_sz file rd wen =+blockRamFile# (Clock _) ena sz file = \rd wen waS wd -> runST $ do+  ramStart <- newArray_ (0,szI)+  unsafeIOToST (withFile file ReadMode (\h ->+    forM_ [0..(szI-1)] (\i -> do+      l <- hGetLine h+      let bv = parseBV l+      bv `seq` unsafeSTToIO (unsafeWriteSTArray ramStart i bv)+      )))+  -- start benchmark only+  -- ramStart <- unsafeThawSTArray ramArr+  -- end benchmark only   go-    ramI-    (withFrozenCallStack (errorX "blockRamFile#: intial value undefined"))+    ramStart+    (withFrozenCallStack (errorX "blockRamFile: intial value undefined"))     (fromEnable ena)     rd     (fromEnable ena .&&. wen)-  where-    -- clock enable-    go-      :: Seq.Seq (BitVector m)-      -> BitVector m-      -> Signal dom Bool-      -> Signal dom Int-      -> Signal dom Bool-      -> Signal dom Int-      -> Signal dom (BitVector m)-      -> Signal dom (BitVector m)-    go !ram o (re :- res) (r :- rs) (e :- en) (w :- wr) (d :- din) =-      let ram' = upd ram e (fromEnum w) d-          o'   = if re then ram `Seq.index` r else o-      in  o `seqX` o :- go ram' o' res rs en wr din+    waS+    wd+ where+  szI = snatToNum sz :: Int+  -- start benchmark only+  -- ramArr = runST $ do+  --             ram <- newArray_ (0,szI-1) -- 0 -- (error "QQ")+  --             unsafeIOToST (withFile file ReadMode (\h ->+  --               forM_ [0..(szI-1)] (\i -> do+  --                 l <- hGetLine h+  --                 let bv = parseBV l+  --                 bv `seq` unsafeSTToIO (unsafeWriteSTArray ram i bv))+  --               ))+  --             unsafeFreezeSTArray ram+  -- end benchmark only -    upd ram we waddr d = case maybeIsX we of-      Nothing -> case maybeIsX waddr of-        Nothing -> -- Put the XException from `waddr` as the value in all-                   -- locations of `ram`.-                   seq waddr d <$ ram-        Just wa -> -- Put the XException from `we` as the value at address-                   -- `waddr`.-                   Seq.update wa (seq we d) ram-      Just True -> case maybeIsX waddr of-        Nothing -> -- Put the XException from `waddr` as the value in all-                   -- locations of `ram`.-                   seq waddr d <$ ram-        Just wa -> Seq.update wa d ram-      _ -> ram+  go :: STArray s Int (BitVector m) -> (BitVector m) -> Signal dom Bool -> Signal dom Int+    -> Signal dom Bool -> Signal dom Int -> Signal dom (BitVector m)+    -> ST s (Signal dom (BitVector m))+  go !ram o ret@(~(re :- res)) rt@(~(r :- rs)) et@(~(e :- en)) wt@(~(w :- wr)) dt@(~(d :- din)) = do+    o `seqX` (o :-) <$> (ret `seq` rt `seq` et `seq` wt `seq` dt `seq`+      unsafeInterleaveST+        (do o' <- unsafeIOToST+                    (catch (if re then unsafeSTToIO (ram `safeAt` r) else pure o)+                    (\err@XException {} -> pure (throw err)))+            d `seqX` upd ram e (fromEnum w) d+            go ram o' res rs en wr din)) -    content = unsafePerformIO (initMem file)+  upd :: STArray s Int (BitVector m) -> Bool -> Int -> (BitVector m) -> ST s ()+  upd ram we waddr d = case maybeIsX we of+    Nothing -> case maybeIsX waddr of+      Nothing -> -- Put the XException from `waddr` as the value in all+                 -- locations of `ram`.+                 forM_ [0..(szI-1)] (\i -> unsafeWriteSTArray ram i (seq waddr d))+      Just wa -> -- Put the XException from `we` as the value at address+                 -- `waddr`.+                 safeUpdate wa (seq we d) ram+    Just True -> case maybeIsX waddr of+      Nothing -> -- Put the XException from `waddr` as the value in all+                 -- locations of `ram`.+                 forM_ [0..(szI-1)] (\i -> unsafeWriteSTArray ram i (seq waddr d))+      Just wa -> safeUpdate wa d ram+    _ -> return () -    ramI :: Seq.Seq (BitVector m)-    ramI = Seq.fromList content+  safeAt :: HasCallStack => STArray s Int (BitVector m) -> Int -> ST s (BitVector m)+  safeAt s i =+    if (0 <= i) && (i < szI) then+      unsafeReadSTArray s i+    else pure $+      withFrozenCallStack+        (errorX ("blockRamFile: read address " <> show i <>+                " not in range [0.." <> show szI <> ")"))+  {-# INLINE safeAt #-}++  safeUpdate :: HasCallStack => Int -> a -> STArray s Int a -> ST s ()+  safeUpdate i a s =+    if (0 <= i) && (i < szI) then+      unsafeWriteSTArray s i a+    else+      let d = withFrozenCallStack+                (errorX ("blockRamFile: write address " <> show i <>+                        " not in range [0.." <> show szI <> ")"))+      in forM_ [0..(szI-1)] (\j -> unsafeWriteSTArray s j d)+  {-# INLINE safeUpdate #-}++  parseBV :: String -> BitVector m+  parseBV s = case parseBV' s of+                Just i  -> fromInteger i+                Nothing -> undefined#+  parseBV' = fmap fst . listToMaybe . readInt 2 (`elem` "01") digitToInt {-# NOINLINE blockRamFile# #-}+{-# ANN blockRamFile# hasBlackBox #-}  -- | __NB:__ Not synthesizable initMem :: KnownNat n => FilePath -> IO [BitVector n]
+ src/Clash/Explicit/BlockRam/Internal.hs view
@@ -0,0 +1,193 @@+{-|+Copyright  :  (C) 2021-2022, QBayLogic B.V.+License    :  BSD2 (see the file LICENSE)+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>+-}++{-# LANGUAGE GADTs #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE Trustworthy #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE ViewPatterns #-}++module Clash.Explicit.BlockRam.Internal where++import Data.Bits ((.&.), (.|.), shiftL, xor)+import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as L+import Data.ByteString.Builder (Builder, toLazyByteString, word8, word64BE)+import qualified Data.ByteString.Unsafe as B+import Data.Foldable (foldl')+import Data.Word (Word64)+import GHC.Exts (Addr#)+import GHC.TypeLits (KnownNat, Nat)+import Numeric.Natural (Natural)+import System.IO.Unsafe (unsafePerformIO)++import Clash.Class.BitPack.Internal (BitPack, BitSize, pack)+import Clash.Promoted.Nat (natToNum)+import Clash.Sized.Internal.BitVector (Bit(..), BitVector(..))++-- | Efficient storage of memory content+--+-- It holds @n@ words of @'BitVector' m@.+data MemBlob (n :: Nat) (m :: Nat) where+  MemBlob+    :: ( KnownNat n+       , KnownNat m+       )+    => { memBlobRunsLen :: !Int+       , memBlobRuns :: Addr#+       , memBlobEndsLen :: !Int+       , memBlobEnds :: Addr#+       }+    -> MemBlob n m++instance Show (MemBlob n m) where+  showsPrec _ x@MemBlob{} =+    ("$(memBlobTH @(BitVector " ++) . shows (natToNum @m @Int) .+      (") Nothing " ++) . shows (unpackMemBlob x) . (')':)++-- | Convert a 'MemBlob' back to a list+--+-- __NB__: Not synthesizable+unpackMemBlob+  :: forall n m+   . MemBlob n m+  -> [BitVector m]+unpackMemBlob = unsafePerformIO . unpackMemBlob0++unpackMemBlob0+  :: forall n m+   . MemBlob n m+  -> IO [BitVector m]+unpackMemBlob0 MemBlob{..} = do+  runsB <- B.unsafePackAddressLen memBlobRunsLen memBlobRuns+  endsB <- B.unsafePackAddressLen memBlobEndsLen memBlobEnds+  return $ map (BV 0) $+    unpackNats (natToNum @n) (natToNum @m) runsB endsB++packBVs+  :: forall a f+   . ( Foldable f+     , BitPack a+     )+  => Maybe Bit+  -> f a+  -> Either String (Int, L.ByteString, L.ByteString)+packBVs care es =+  case lenOrErr of+    Nothing  -> Left err+    Just len -> let (runs, ends) = packAsNats mI (knownBVVal . pack) es+                in Right (len, runs, ends)+ where+  lenOrErr = case care of+               Just (Bit 0 _) -> Just $ length es+               _              -> foldl' lenOrErr0 (Just 0) es+  lenOrErr0 (Just len) (pack -> BV 0 _) = Just $ len + 1+  lenOrErr0 _          _                = Nothing++  knownBVVal bv@(BV _ val) = case care of+    Just (Bit 0 bm) -> maskBVVal bm bv+    _               -> val++  maskBVVal _ (BV 0    val) = val+  maskBVVal 0 (BV mask val) = val .&. (mask `xor` fullMask)+  maskBVVal _ (BV mask val) = val .|. mask++  mI = natToNum @(BitSize a) @Int+  fullMask = (1 `shiftL` mI) - 1+  err = "packBVs: cannot convert don't care values. " +++        "Please specify a mapping to a definite value."++packAsNats+  :: forall a f+   . Foldable f+  => Int+  -> (a -> Natural)+  -> f a+  -> (L.ByteString, L.ByteString)+packAsNats width trans es = (toLazyByteString runs0, toLazyByteString ends)+ where+  (runL, endL) = width `divMod` 8+  ends | endC0 > 0 = word64BE endA0 <> ends0+       | otherwise = ends0+  (runs0, ends0, endC0, endA0) = foldr pack0 (mempty, mempty, 0, 0) es++  pack0 :: a -> (Builder, Builder, Int, Word64) ->+           (Builder, Builder, Int, Word64)+  pack0 val (runs1, ends1, endC1, endA1) =+    let (ends2, endC2, endA2) = packEnd val2 ends1 endC1 endA1+        (val2, runs2) = packRun runL (trans val) runs1+    in (runs2, ends2, endC2, endA2)++  packRun :: Int -> Natural -> Builder -> (Natural, Builder)+  packRun 0    val1 runs1 = (val1, runs1)+  packRun runC val1 runs1 = let (val2, runB) = val1 `divMod` 256+                                runs2 = word8 (fromIntegral runB) <> runs1+                            in packRun (runC - 1) val2 runs2++  packEnd :: Natural -> Builder -> Int -> Word64 -> (Builder, Int, Word64)+  packEnd val2 ends1 endC1 endA1+    | endL == 0   = (ends1, endC1, endA1)+    | endC2 <= 64 = let endA2 = endA1 * (2 ^ endL) + valEnd+                    in (ends1, endC2, endA2)+    | otherwise   = let ends2 = word64BE endA1 <> ends1+                    in (ends2, endL, valEnd)+   where+    endC2 = endC1 + endL+    valEnd = fromIntegral val2++unpackNats+  :: Int+  -> Int+  -> B.ByteString+  -> B.ByteString+  -> [Natural]+unpackNats 0 _ _ _ = []+unpackNats len width runBs endBs+  | width < 8 = ends+  | otherwise = go (head ends) runL runBs (tail ends)+ where+  (runL, endL) = width `divMod` 8+  ends = if endL == 0 then+           repeat 0+         else+           unpackEnds endL len $ unpackW64s endBs++  go val 0    runBs0 ~(end0:ends0) = val : go end0 runL runBs0 ends0+  go _   _    runBs0 _             | B.null runBs0 = []+  go val runC runBs0 ends0+    = let Just (runB, runBs1) = B.uncons runBs0+          val0 = val * 256 + fromIntegral runB+      in go val0 (runC - 1) runBs1 ends0++unpackW64s+  :: B.ByteString+  -> [Word64]+unpackW64s = go 8 0+ where+  go :: Int -> Word64 -> B.ByteString -> [Word64]+  go 8 _   endBs | B.null endBs = []+  go 0 val endBs = val : go 8 0 endBs+  go n val endBs = let Just (endB, endBs0) = B.uncons endBs+                       val0 = val * 256 + fromIntegral endB+                   in go (n - 1) val0 endBs0++unpackEnds+  :: Int+  -> Int+  -> [Word64]+  -> [Natural]+unpackEnds _    _   []     = []+unpackEnds endL len (w:ws) = go endCInit w ws+ where+  endPerWord = 64 `div` endL+  leader = len `mod` endPerWord+  endCInit | leader == 0 = endPerWord+           | otherwise   = leader++  go 0 _    []       = []+  go 0 _    (w0:ws0) = go endPerWord w0 ws0+  go n endA ws0      = let (endA0, valEnd) = endA `divMod` (2 ^ endL)+                       in fromIntegral valEnd : go (n - 1) endA0 ws0
src/Clash/Explicit/Mealy.hs view
@@ -27,8 +27,6 @@  {- $setup >>> :set -XDataKinds -XTypeApplications->>> :m -Clash.Prelude->>> :m -Clash.Prelude.Safe >>> import Clash.Explicit.Prelude >>> import qualified Data.List as L >>> :{
src/Clash/Explicit/Moore.hs view
@@ -29,8 +29,6 @@  {- $setup >>> :set -XDataKinds -XTypeApplications->>> :m -Clash.Prelude->>> :m -Clash.Prelude.Safe >>> import Clash.Explicit.Prelude >>> let macT s (x,y) = x * y + s >>> let mac clk rst en = moore clk rst en macT id 0
src/Clash/Explicit/Prelude.hs view
@@ -1,9 +1,10 @@ {-| Copyright  :  (C) 2013-2016, University of Twente,                   2017     , Google Inc.-                  2019     , Myrtle Software Ltd+                  2019     , Myrtle Software Ltd,+                  2021-2022, QBayLogic B.V. License    :  BSD2 (see the file LICENSE)-Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>  This module defines the explicitly clocked counterparts of the functions defined in "Clash.Prelude".@@ -31,7 +32,12 @@   , asyncRomPow2   , rom   , romPow2-    -- ** ROMs initialized with a data file+    -- ** ROMs defined by a 'MemBlob'+  , asyncRomBlob+  , asyncRomBlobPow2+  , romBlob+  , romBlobPow2+    -- ** ROMs defined by a data file   , asyncRomFile   , asyncRomFilePow2   , romFile@@ -45,11 +51,22 @@   , blockRamU   , blockRam1   , ResetStrategy(..)+    -- ** BlockRAM primitives initialized with a 'MemBlob'+  , blockRamBlob+  , blockRamBlobPow2+    -- *** Creating and inspecting 'MemBlob'+  , MemBlob+  , createMemBlob+  , memBlobTH+  , unpackMemBlob     -- ** BlockRAM primitives initialized with a data file   , blockRamFile   , blockRamFilePow2   -- ** BlockRAM read/write conflict resolution   , readNew+    -- ** True dual-port block RAM+  , trueDualPortBlockRam+  , RamOp(..)     -- * Utility functions   , window   , windowD@@ -78,8 +95,6 @@     -- ** Datatypes     -- *** Bit vectors   , module Clash.Sized.BitVector-  , module Clash.Prelude.BitIndex-  , module Clash.Prelude.BitReduction     -- *** Arbitrary-width numbers   , module Clash.Sized.Signed   , module Clash.Sized.Unsigned@@ -138,26 +153,26 @@  import Clash.Annotations.TopEntity import Clash.Class.AutoReg-import Clash.Class.BitPack hiding (GBitPack(..))+import Clash.Class.BitPack import Clash.Class.Exp import Clash.Class.Num import Clash.Class.Resize import Clash.Magic import Clash.NamedTypes import Clash.Explicit.BlockRam+import Clash.Explicit.BlockRam.Blob import Clash.Explicit.BlockRam.File import Clash.Explicit.Mealy import Clash.Explicit.Moore import Clash.Explicit.RAM import Clash.Explicit.ROM+import Clash.Explicit.ROM.Blob import Clash.Explicit.ROM.File import Clash.Explicit.Prelude.Safe import Clash.Explicit.Reset import Clash.Explicit.Signal import Clash.Explicit.Signal.Delayed import Clash.Explicit.Testbench-import Clash.Prelude.BitIndex-import Clash.Prelude.BitReduction import Clash.Prelude.ROM.File       (asyncRomFile, asyncRomFilePow2) import Clash.Promoted.Nat import Clash.Promoted.Nat.TH@@ -175,7 +190,6 @@  {- $setup >>> :set -XDataKinds -XTypeApplications->>> :m -Clash.Prelude >>> import Clash.Explicit.Prelude >>> let window4 = window @3 >>> let windowD3 = windowD @2@@ -203,7 +217,7 @@ -- @ -- -- >>> simulateB (window4 systemClockGen systemResetGen enableGen) [1::Int,2,3,4,5] :: [Vec 4 Int]--- [<1,0,0,0>,<2,1,0,0>,<3,2,1,0>,<4,3,2,1>,<5,4,3,2>...+-- [1 :> 0 :> 0 :> 0 :> Nil,2 :> 1 :> 0 :> 0 :> Nil,3 :> 2 :> 1 :> 0 :> Nil,4 :> 3 :> 2 :> 1 :> Nil,5 :> 4 :> 3 :> 2 :> Nil,... -- ... window   :: ( KnownNat n@@ -242,7 +256,7 @@ -- @ -- -- >>> simulateB (windowD3 systemClockGen resetGen enableGen) [1::Int,1,2,3,4] :: [Vec 3 Int]--- [<0,0,0>,<0,0,0>,<1,0,0>,<2,1,0>,<3,2,1>,<4,3,2>...+-- [0 :> 0 :> 0 :> Nil,0 :> 0 :> 0 :> Nil,1 :> 0 :> 0 :> Nil,2 :> 1 :> 0 :> Nil,3 :> 2 :> 1 :> Nil,4 :> 3 :> 2 :> Nil,... -- ... windowD   :: ( KnownNat n
src/Clash/Explicit/Prelude/Safe.hs view
@@ -1,9 +1,10 @@ {-| Copyright  :  (C) 2013-2016, University of Twente,                   2017     , Google Inc.-                  2019     , Myrtle Software Ltd+                  2019     , Myrtle Software Ltd,+                  2021-2022, QBayLogic B.V. License    :  BSD2 (see the file LICENSE)-Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>  __This is the <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/exts/safe_haskell.html Safe> API only of "Clash.Explicit.Prelude"__ @@ -33,14 +34,30 @@   , asyncRomPow2   , rom   , romPow2+    -- ** ROMs defined by a 'MemBlob'+  , asyncRomBlob+  , asyncRomBlobPow2+  , romBlob+  , romBlobPow2     -- * RAM primitives with a combinational read port   , asyncRam   , asyncRamPow2     -- * BlockRAM primitives   , blockRam   , blockRamPow2+    -- ** BlockRAM primitives initialized with a 'MemBlob'+  , blockRamBlob+  , blockRamBlobPow2+    -- *** Creating and inspecting 'MemBlob'+  , MemBlob+  , createMemBlob+  , memBlobTH+  , unpackMemBlob     -- ** BlockRAM read/write conflict resolution   , readNew+    -- ** True dual-port block RAM+  , trueDualPortBlockRam+  , RamOp(..)     -- * Utility functions   , isRising   , isFalling@@ -53,8 +70,6 @@     -- ** Datatypes     -- *** Bit vectors   , module Clash.Sized.BitVector-  , module Clash.Prelude.BitIndex-  , module Clash.Prelude.BitReduction     -- *** Arbitrary-width numbers   , module Clash.Sized.Signed   , module Clash.Sized.Unsigned@@ -111,16 +126,17 @@ import Clash.NamedTypes  import Clash.Explicit.BlockRam+import Clash.Explicit.BlockRam.Blob import Clash.Explicit.Mealy import Clash.Explicit.Moore import Clash.Explicit.RAM import Clash.Explicit.ROM+import Clash.Explicit.ROM.Blob import Clash.Explicit.Signal import Clash.Explicit.Signal.Delayed import Clash.Explicit.Synchronizer   (dualFlipFlopSynchronizer, asyncFIFOSynchronizer)-import Clash.Prelude.BitIndex-import Clash.Prelude.BitReduction+import Clash.Prelude.ROM.Blob (asyncRomBlob, asyncRomBlobPow2) import Clash.Prelude.ROM             (asyncRom, asyncRomPow2) import Clash.Promoted.Nat import Clash.Promoted.Nat.TH@@ -137,8 +153,7 @@  {- $setup >>> :set -XDataKinds->>> :m -Clash.Prelude->>> :m -Clash.Prelude.Safe+>>> :m -Prelude >>> import Clash.Explicit.Prelude.Safe >>> let rP clk rst en = registerB clk rst en (8::Int,8::Int) -}
src/Clash/Explicit/RAM.hs view
@@ -2,7 +2,7 @@ Copyright  :  (C) 2015-2016, University of Twente,                   2017     , Google Inc.                   2019     , Myrtle Software Ltd,-                  2022     , QBayLogic B.V.+                  2021-2022, QBayLogic B.V. License    :  BSD2 (see the file LICENSE) Maintainer :  QBayLogic B.V. <devops@qbaylogic.com> @@ -35,12 +35,14 @@ import GHC.TypeLits          (KnownNat) import qualified Data.Sequence as Seq -import Clash.Explicit.Signal (unbundle, KnownDomain, enable)+import Clash.Annotations.Primitive (hasBlackBox)+import Clash.Explicit.Signal (unbundle, KnownDomain, andEnable) import Clash.Promoted.Nat    (SNat (..), snatToNum, pow2SNat) import Clash.Signal.Internal (Clock (..), Signal (..), Enable, fromEnable) import Clash.Signal.Internal.Ambiguous (clockPeriod) import Clash.Sized.Unsigned  (Unsigned)-import Clash.XException      (errorX, maybeIsX, fromJustX, seqX)+import Clash.XException+  (defaultSeqX, errorX, fromJustX, maybeIsX, NFDataX)  -- | Create a RAM with space for 2^@n@ elements --@@ -57,6 +59,7 @@      , HasCallStack      , KnownDomain wdom      , KnownDomain rdom+     , NFDataX a      )   => Clock wdom   -- ^ 'Clock' to which to synchronize the write port of the RAM@@ -89,6 +92,7 @@      , HasCallStack      , KnownDomain wdom      , KnownDomain rdom+     , NFDataX a      )   => Clock wdom    -- ^ 'Clock' to which to synchronize the write port of the RAM@@ -116,7 +120,9 @@   :: forall wdom rdom n a    . ( HasCallStack      , KnownDomain wdom-     , KnownDomain rdom )+     , KnownDomain rdom+     , NFDataX a+     )   => Clock wdom   -- ^ 'Clock' to which to synchronize the write port of the RAM   -> Clock rdom@@ -140,7 +146,7 @@     ramI = Seq.replicate               szI               (withFrozenCallStack (errorX "asyncRam#: initial value undefined"))-    en0 = fromEnable (enable en we)+    en0 = fromEnable (andEnable en we)     dout = if rPeriod == wPeriod            then goSingle ramI rd en0 wr din            else go 0 ramI rd en0 wr din@@ -152,8 +158,8 @@        -> Signal wdom Int -> Signal wdom a -> Signal rdom a     goSingle !ram (r :- rs) ~(e :- es) wt@(~(w :- ws)) dt@(~(d :- ds)) =       let ram0 = upd ram e w d-          o    = ram `Seq.index` r-      in  o :- (wt `seq` dt `seq` goSingle ram0 rs es ws ds)+          o    = ram `safeAt` r+      in  o :- (o `defaultSeqX` wt `seq` dt `seq` goSingle ram0 rs es ws ds)      -- Given     --   tR = absolute time of next active edge of read clock@@ -170,8 +176,8 @@       | relTime < 0 = let ram0 = upd ram e w d                       in wt `seq` dt `seq`                          go (relTime + wPeriod) ram0 rt es ws ds-      | otherwise   = let o = ram `Seq.index` r-                      in o :- go (relTime - rPeriod) ram rs et wt dt+      | otherwise   = let o = ram `safeAt` r+                      in o :- (o `defaultSeqX` go (relTime - rPeriod) ram rs et wt dt)      upd ram we0 waddr d = case maybeIsX we0 of       Nothing -> case maybeIsX waddr of@@ -180,11 +186,33 @@                    seq waddr d <$ ram         Just wa -> -- Put the XException from `we` as the value at address                    -- `waddr`.-                   Seq.update wa (seq we0 d) ram+                   safeUpdate wa (seq we0 d) ram       Just True -> case maybeIsX waddr of         Nothing -> -- Put the XException from `waddr` as the value in all                    -- locations of `ram`.                    seq waddr d <$ ram-        Just wa -> d `seqX` Seq.update wa d ram+        Just wa -> d `defaultSeqX` safeUpdate wa d ram       _ -> ram++    safeAt :: HasCallStack => Seq.Seq a -> Int -> a+    safeAt s i =+      if (0 <= i) && (i < szI) then+        Seq.index s i+      else+        withFrozenCallStack+          (errorX ("asyncRam: read address " ++ show i +++                   " not in range [0.." ++ show szI ++ ")"))+    {-# INLINE safeAt #-}++    safeUpdate :: HasCallStack => Int -> a -> Seq.Seq a ->  Seq.Seq a+    safeUpdate i a s =+      if (0 <= i) && (i < szI) then+        Seq.update i a s+      else+        let d = withFrozenCallStack+                  (errorX ("asyncRam: write address " ++ show i +++                           " not in range [0.." ++ show szI ++ ")"))+        in d <$ s+    {-# INLINE safeUpdate #-} {-# NOINLINE asyncRam# #-}+{-# ANN asyncRam# hasBlackBox #-}
src/Clash/Explicit/ROM.hs view
@@ -2,7 +2,7 @@ Copyright  :  (C) 2015-2016, University of Twente,                   2017     , Google Inc.                   2019     , Myrtle Software Ltd,-                  2022     , QBayLogic B.V.+                  2021-2022, QBayLogic B.V. License    :  BSD2 (see the file LICENSE) Maintainer :  QBayLogic B.V. <devops@qbaylogic.com> @@ -27,11 +27,13 @@   ) where -import Data.Array             ((!),listArray)+import Data.Array             (listArray)+import Data.Array.Base        (unsafeAt) import GHC.Stack              (withFrozenCallStack) import GHC.TypeLits           (KnownNat, type (^)) import Prelude hiding         (length) +import Clash.Annotations.Primitive (hasBlackBox) import Clash.Signal.Internal   (Clock (..), KnownDomain, Signal (..), Enable, fromEnable) import Clash.Sized.Unsigned   (Unsigned)@@ -48,6 +50,10 @@ -- -- * See "Clash.Sized.Fixed#creatingdatafiles" and "Clash.Explicit.BlockRam#usingrams" -- for ideas on how to use ROMs and RAMs+-- * A large 'Vec' for the content might be too inefficient, depending on how it+-- is constructed. See 'Clash.Explicit.ROM.File.romFilePow2' and+-- 'Clash.Explicit.ROM.Blob.romBlobPow2' for different approaches that scale+-- well. romPow2   :: (KnownDomain dom, KnownNat n, NFDataX a)   => Clock dom@@ -75,6 +81,9 @@ -- -- * See "Clash.Sized.Fixed#creatingdatafiles" and "Clash.Explicit.BlockRam#usingrams" -- for ideas on how to use ROMs and RAMs+-- * A large 'Vec' for the content might be too inefficient, depending on how it+-- is constructed. See 'Clash.Explicit.ROM.File.romFile' and+-- 'Clash.Explicit.ROM.Blob.romBlob' for different approaches that scale well. rom   :: (KnownDomain dom, KnownNat n, NFDataX a, Enum addr)   => Clock dom@@ -117,7 +126,18 @@   arr = listArray (0,szI-1) (toList content)    go o (e :- es) rd@(~(r :- rs)) =-    let o1 = if e then arr ! r else o+    let o1 = if e then safeAt r else o     -- See [Note: register strictness annotations]     in  o `seqX` o :- (rd `seq` go o1 es rs)++  safeAt :: Int -> a+  safeAt i =+    if (0 <= i) && (i < szI) then+      unsafeAt arr i+    else+      withFrozenCallStack+        (deepErrorX ("rom: address " ++ show i +++                     " not in range [0.." ++ show szI ++ ")"))+  {-# INLINE safeAt #-} {-# NOINLINE rom# #-}+{-# ANN rom# hasBlackBox #-}
+ src/Clash/Explicit/ROM/Blob.hs view
@@ -0,0 +1,153 @@+{-|+Copyright  :  (C) 2021-2022, QBayLogic B.V.+License    :  BSD2 (see the file LICENSE)+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>++= Efficient bundling of ROM content with the compiled code++Leveraging Template Haskell, the content for the ROM components in this module+is stored alongside the compiled Haskell code. It covers use cases where passing+the initial content as a 'Clash.Sized.Vector.Vec' turns out to be+problematically slow.++The data is stored efficiently, with very little overhead (worst-case 7%, often+no overhead at all).++Unlike "Clash.Explicit.ROM.File", "Clash.Explicit.ROM.Blob" generates+practically the same HDL as "Clash.Explicit.ROM" and is compatible with all+tools consuming the generated HDL.+-}++{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE Trustworthy #-}++{-# OPTIONS_HADDOCK show-extensions #-}++module Clash.Explicit.ROM.Blob+  ( -- * ROMs defined by a 'MemBlob'+    romBlob+  , romBlobPow2+    -- * Creating and inspecting 'MemBlob'+  , MemBlob+  , createMemBlob+  , memBlobTH+  , unpackMemBlob+    -- * Internal+  , romBlob#+  ) where++import Data.Array (listArray)+import Data.Array.Base (unsafeAt)+import GHC.Stack (withFrozenCallStack)+import GHC.TypeLits (KnownNat, type (^))++import Clash.Annotations.Primitive (hasBlackBox)+import Clash.Explicit.BlockRam.Blob (createMemBlob, memBlobTH)+import Clash.Explicit.BlockRam.Internal (MemBlob(..), unpackMemBlob)+import Clash.Promoted.Nat (natToNum)+import Clash.Signal.Internal+  (Clock (..), KnownDomain, Signal (..), Enable, fromEnable)+import Clash.Sized.Internal.BitVector (BitVector)+import Clash.Sized.Internal.Unsigned (Unsigned)+import Clash.XException (deepErrorX, seqX)++-- | A ROM with a synchronous read port, with space for @n@ elements+--+-- * __NB__: Read value is delayed by 1 cycle+-- * __NB__: Initial output value is /undefined/, reading it will throw an+-- 'Clash.XException.XException'+--+-- Additional helpful information:+--+-- * See "Clash.Sized.Fixed#creatingdatafiles" and+-- "Clash.Explicit.BlockRam#usingrams" for ideas on how to use ROMs and RAMs+romBlob+  :: forall dom addr m n+   . ( KnownDomain dom+     , Enum addr+     )+  => Clock dom+  -- ^ 'Clock' to synchronize to+  -> Enable dom+  -- ^ 'Enable' line+  -> MemBlob n m+  -- ^ ROM content, also determines the size, @n@, of the ROM+  --+  -- __NB__: __MUST__ be a constant+  -> Signal dom addr+  -- ^ Read address @r@+  -> Signal dom (BitVector m)+  -- ^ The value of the ROM at address @r@ from the previous clock cycle+romBlob = \clk en content rd -> romBlob# clk en content (fromEnum <$> rd)+{-# INLINE romBlob #-}++-- | A ROM with a synchronous read port, with space for 2^@n@ elements+--+-- * __NB__: Read value is delayed by 1 cycle+-- * __NB__: Initial output value is /undefined/, reading it will throw an+-- 'Clash.XException.XException'+--+-- Additional helpful information:+--+-- * See "Clash.Sized.Fixed#creatingdatafiles" and+-- "Clash.Explicit.BlockRam#usingrams" for ideas on how to use ROMs and RAMs+romBlobPow2+  :: forall dom m n+   . ( KnownDomain dom+     , KnownNat n+     )+  => Clock dom+  -- ^ 'Clock' to synchronize to+  -> Enable dom+  -- ^ 'Enable' line+  -> MemBlob (2^n) m+  -- ^ ROM content, also determines the size, 2^@n@, of the ROM+  --+  -- __NB__: __MUST__ be a constant+  -> Signal dom (Unsigned n)+  -- ^ Read address @r@+  -> Signal dom (BitVector m)+  -- ^ The value of the ROM at address @r@ from the previous clock cycle+romBlobPow2 = romBlob+{-# INLINE romBlobPow2 #-}++-- | ROM primitive+romBlob#+  :: forall dom m n+   . KnownDomain dom+  => Clock dom+  -- ^ 'Clock' to synchronize to+  -> Enable dom+  -- ^ 'Enable' line+  -> MemBlob n m+  -- ^ ROM content, also determines the size, @n@, of the ROM+  --+  -- __NB__: __MUST__ be a constant+  -> Signal dom Int+  -- ^ Read address @r@+  -> Signal dom (BitVector m)+  -- ^ The value of the ROM at address @r@ from the previous clock cycle+romBlob# !_ en content@MemBlob{} =+  go+    (withFrozenCallStack (deepErrorX "romBlob: initial value undefined"))+    (fromEnable en)+ where+  szI = natToNum @n @Int+  arr = listArray (0,szI-1) $ unpackMemBlob content++  go o (e :- es) rd@(~(r :- rs)) =+    let o1 = if e then safeAt r else o+    -- See [Note: register strictness annotations]+    in  o `seqX` o :- (rd `seq` go o1 es rs)++  safeAt :: Int -> BitVector m+  safeAt i =+    if (0 <= i) && (i < szI) then+      unsafeAt arr i+    else+      withFrozenCallStack+        (deepErrorX ("romBlob: address " ++ show i +++                     " not in range [0.." ++ show szI ++ ")"))+  {-# INLINE safeAt #-}+{-# NOINLINE romBlob# #-}+{-# ANN romBlob# hasBlackBox #-}
src/Clash/Explicit/ROM/File.hs view
@@ -1,8 +1,8 @@ {-| Copyright  :  (C) 2015-2016, University of Twente,-                  2017     , Google Inc.+                  2017     , Google Inc.,                   2019     , Myrtle Software Ltd.,-                  2022     , QBayLogic B.V.+                  2021-2022, QBayLogic B.V. License    :  BSD2 (see the file LICENSE) Maintainer :  QBayLogic B.V. <devops@qbaylogic.com> @@ -31,6 +31,12 @@ 000001101 @ +Such a file can be produced with 'memFile':++@+writeFile "memory.bin" (memFile Nothing [7 :: Unsigned 9 .. 13])+@+ We can instantiate a synchronous ROM using the content of the above file like so: @@ -80,16 +86,20 @@   ( -- * Synchronous ROM synchronized to an arbitrary clock     romFile   , romFilePow2+    -- * Producing files+  , memFile     -- * Internal   , romFile#   ) where -import Data.Array                   (listArray,(!))+import Data.Array                   (listArray)+import Data.Array.Base              (unsafeAt) import GHC.TypeLits                 (KnownNat) import System.IO.Unsafe             (unsafePerformIO)----import Clash.Explicit.BlockRam.File (initMem)++import Clash.Annotations.Primitive (hasBlackBox)+import Clash.Explicit.BlockRam.File (initMem, memFile) import Clash.Promoted.Nat           (SNat (..), pow2SNat, snatToNum) import Clash.Sized.BitVector        (BitVector) import Clash.Explicit.Signal        (Clock, Enable, Signal, KnownDomain, delay)@@ -119,8 +129,9 @@ -- -- * See "Clash.Explicit.ROM.File#usingromfiles" for more information on how -- to instantiate a ROM with the contents of a data file.--- * See "Clash.Sized.Fixed#creatingdatafiles" for ideas on how to create your--- own data files.+-- * See 'memFile' for creating a data file with Clash.+-- * See "Clash.Sized.Fixed#creatingdatafiles" for more ideas on how to create+-- your own data files. romFilePow2   :: forall dom  n m    . (KnownNat m, KnownNat n, KnownDomain dom)@@ -181,7 +192,8 @@  -- | romFile primitive romFile#-  :: (KnownNat m, KnownDomain dom)+  :: forall m dom n+   . (KnownNat m, KnownDomain dom)   => Clock dom   -- ^ 'Clock' to synchronize to   -> Enable dom@@ -195,9 +207,20 @@   -> Signal dom (BitVector m)   -- ^ The value of the ROM at address @rd@ from the previous clock cycle romFile# clk en sz file rd =-  delay clk en (deepErrorX "First value of romFile is undefined") ((content !) <$> rd)+  delay clk en (deepErrorX "First value of romFile is undefined")+        (safeAt <$> rd)  where   mem     = unsafePerformIO (initMem file)   content = listArray (0,szI-1) mem   szI     = snatToNum sz++  safeAt :: Int -> BitVector m+  safeAt i =+    if (0 <= i) && (i < szI) then+      unsafeAt content i+    else+      deepErrorX ("romFile: address " ++ show i +++                  " not in range [0.." ++ show szI ++ ")")+  {-# INLINE safeAt #-} {-# NOINLINE romFile# #-}+{-# ANN romFile# hasBlackBox #-}
src/Clash/Explicit/Reset.hs view
@@ -1,5 +1,5 @@ {-|-Copyright  :  (C) 2020, QBayLogic B.V.+Copyright  :  (C) 2020-2021, QBayLogic B.V. License    :  BSD2 (see the file LICENSE) Maintainer :  QBayLogic B.V. <devops@qbaylogic.com> @@ -52,8 +52,6 @@ import           GHC.TypeLits (type (+), KnownNat)  {- $setup->>> :m -Clash.Prelude->>> :m -Clash.Prelude.Safe >>> import Clash.Explicit.Prelude -} @@ -92,13 +90,12 @@ -- topEntity --   :: Clock  System --   -> Reset  System---   -> Enable System --   -> Signal System Bit --   -> Signal System (BitVector 8)--- topEntity clk asyncRst ena key1 =---   withClockResetEnable clk rst ena leds+-- topEntity clk asyncRst key1 =+--   withClockResetEnable clk rst enableGen leds --  where---   rst   = 'resetSynchronizer' clk asyncRst ena+--   rst   = 'resetSynchronizer' clk asyncRst --   key1R = isRising 1 key1 --   leds  = mealy blinkerT (1, False, 0) key1R -- @@@ -115,9 +112,9 @@ --   -> Reset  System --   -> Signal System Bit --   -> Signal System (BitVector 8)--- topEntity clk rst ena key1 =+-- topEntity clk rst key1 = --     let  (pllOut,pllStable) = altpll (SSymbol @"altpll50") clk rst---          rstSync            = 'resetSynchronizer' pllOut (unsafeToHighPolarity pllStable) ena+--          rstSync            = 'resetSynchronizer' pllOut (unsafeToHighPolarity pllStable) --     in   exposeClockResetEnable leds pllOut rstSync enableGen --   where --     key1R  = isRising 1 key1@@ -163,10 +160,8 @@    . KnownDomain dom   => Clock dom   -> Reset dom-  -> Enable dom-  -- ^ Warning: this argument will be removed in future versions of Clash.   -> Reset dom-resetSynchronizer clk rst _ = rstOut+resetSynchronizer clk rst = rstOut  where   isActiveHigh = case resetPolarity @dom of { SActiveHigh -> True; _ -> False }   rstOut =@@ -290,4 +285,4 @@   rstA2 =     case (sameDomain @domA @domB) of       Just Refl -> rstA0-      Nothing   -> resetSynchronizer clkB rstA1 enableGen+      Nothing   -> resetSynchronizer clkB rstA1
src/Clash/Explicit/Signal.hs view
@@ -209,7 +209,8 @@   , unsafeFromHighPolarity   , unsafeFromLowPolarity     -- * Basic circuit functions-  , enable+  , andEnable+  , enable -- DEPRECATED   , dflipflop   , delay   , delayMaybe@@ -235,6 +236,7 @@   , simulateB   , simulateWithReset   , simulateWithResetN+  , runUntil     -- ** lazy versions   , simulate_lazy   , simulateB_lazy@@ -278,15 +280,13 @@ import           Clash.Signal.Internal.Ambiguous   (knownVDomain, clockPeriod, activeEdge, resetKind, initBehavior, resetPolarity) import qualified Clash.Sized.Vector-import           Clash.XException               (NFDataX, deepErrorX, fromJustX)+import           Clash.XException+  (NFDataX, deepErrorX, fromJustX, seqX, ShowX(..))  {- $setup >>> :set -XDataKinds -XTypeApplications -XFlexibleInstances -XMultiParamTypeClasses -XTypeFamilies >>> :set -fno-warn-deprecations->>> :m -Clash.Prelude->>> :m -Clash.Prelude.Safe->>> :m -Clash.Explicit.Prelude.Safe->>> :m -Clash.Signal+>>> :m -Prelude >>> import Clash.Explicit.Prelude >>> import Clash.Promoted.Nat (SNat(..)) >>> import qualified Data.List as L@@ -499,14 +499,24 @@  -- | Merge enable signal with signal of bools by applying the boolean AND -- operation.-enable+andEnable   :: Enable dom   -> Signal dom Bool   -> Enable dom-enable e0 e1 =+andEnable e0 e1 =   toEnable (fromEnable e0 .&&. e1) {-# INLINE enable #-} +-- | Merge enable signal with signal of bools by applying the boolean AND+-- operation.+enable+  :: Enable dom+  -> Signal dom Bool+  -> Enable dom+enable = andEnable+{-# DEPRECATED enable+  "Use 'andEnable' instead. This function will be removed in Clash 1.8." #-}+ -- | Special version of 'delay' that doesn't take enable signals of any kind. -- Initial value will be undefined. dflipflop@@ -847,5 +857,89 @@   -> [a] sampleWithResetN nReset nSamples f =   take nSamples (sampleWithReset nReset f)++-- | Simulate a component until it matches a condition+--+-- It prints a message of the form+--+-- @+-- Signal sampled for N cycles until value X+-- @+--+-- __NB__: This function is not synthesizable+--+-- === __Example with test bench__+--+-- A common usage is with a test bench using+-- 'Clash.Explicit.Testbench.outputVerifier'.+--+-- __NB__: Since this uses 'Clash.Explicit.Testbench.assert', when using+-- @clashi@, read the note at "Clash.Explicit.Testbench#assert-clashi".+--+-- @+-- import Clash.Prelude+-- import Clash.Explicit.Testbench+--+-- topEntity+--   :: 'Signal' 'System' Int+--   -> 'Signal' 'System' Int+-- topEntity = id+--+-- testBench+--   :: 'Signal' 'System' Bool+-- testBench = done+--  where+--   testInput = 'Clash.Explicit.Testbench.stimuliGenerator' clk rst $('Clash.Sized.Vector.listToVecTH' [1 :: Int .. 10])+--   expectedOutput =+--     'Clash.Explicit.Testbench.outputVerifier'' clk rst $('Clash.Sized.Vector.listToVecTH' $ [1 :: Int .. 9] '<>' [42])+--   done = expectedOutput $ topEntity testInput+--   clk = 'Clash.Explicit.Testbench.tbSystemClockGen' (not \<$\> done)+--   rst = 'systemResetGen'+-- @+--+-- @+-- > runUntil id testBench+--+--+-- cycle(\<Clock: System\>): 10, outputVerifier+-- expected value: 42, not equal to actual value: 10+-- Signal sampled for 11 cycles until value True+-- @+--+-- When you need to verify multiple test benches, the following invocations come+-- in handy:+--+-- @+-- > 'mapM_' (runUntil id) [ testBenchA, testBenchB ]+-- @+--+-- or when the test benches are in different clock domains:+--+-- @+-- testBenchA :: Signal DomA Bool+-- testBenchB :: Signal DomB Bool+-- @+--+-- @+-- > 'sequence_' [ runUntil id testBenchA, runUntil id testBenchB ]+-- @+runUntil+  :: forall dom a+   . (KnownDomain dom, NFDataX a, ShowX a)+  => (a -> Bool)+  -- ^ Condition checking function, should return @True@ to finish run+  -> Signal dom a+  -- ^ 'Signal' we want to sample for the condition+  -> IO ()+runUntil check s =+  -- Ensure invocations of 'trace' are printed before the result message+  value `seqX`+  putStrLn msg+ where+  msg =   ("Signal sampled for " ++) . shows nSamples+        . (" cycles until value " ++) $ showX value+  (before, after) = break check $ sample s+  nSamples = length before+  value = head after  {-# RULES "sequenceAVecSignal" Clash.Sized.Vector.traverse# (\x -> x) = vecBundle# #-}
src/Clash/Explicit/Signal/Delayed.hs view
@@ -2,6 +2,7 @@ Copyright  :  (C) 2013-2016, University of Twente,                   2017     , Google Inc.                   2019     , Myrtle Software Ltd+                  2021     , LUMI GUIDE FIETSDETECTIE B.V. License    :  BSD2 (see the file LICENSE) Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com> -}@@ -13,10 +14,6 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} -#if __GLASGOW_HASKELL__ < 806-{-# LANGUAGE TypeInType #-}-#endif- {-# LANGUAGE Trustworthy #-}  {-# OPTIONS_GHC -fplugin GHC.TypeLits.Normalise #-}@@ -41,6 +38,7 @@     -- * Experimental   , unsafeFromSignal   , antiDelay+  , forward   ) where @@ -55,7 +53,7 @@ import Clash.Sized.Vector import Clash.Signal.Delayed.Internal   (DSignal(..), dfromList, dfromList_lazy, fromSignal, toSignal,-   unsafeFromSignal, antiDelay, feedback)+   unsafeFromSignal, antiDelay, feedback, forward)  import Clash.Explicit.Signal   (KnownDomain, Clock, Domain, Reset, Signal, Enable, register, delay, bundle, unbundle)@@ -65,8 +63,6 @@ {- $setup >>> :set -XDataKinds >>> :set -XTypeOperators->>> :m -Clash.Prelude->>> :m -Clash.Prelude.Safe >>> import Clash.Explicit.Prelude >>> let delay3 clk rst en = delayed clk rst en (-1 :> -1 :> -1 :> Nil) >>> let delay2 clk rst en = (delayedI clk rst en :: Int -> DSignal System n Int -> DSignal System (n + 2) Int)
src/Clash/Explicit/SimIO.hs view
@@ -1,5 +1,6 @@ {-|-  Copyright   :  (C) 2019, Google Inc+  Copyright   :  (C) 2019, Google Inc.,+                     2022, QBayLogic B.V.   License     :  BSD2 (see the file LICENSE)   Maintainer  :  QBayLogic B.V. <devops@qbaylogic.com> @@ -69,6 +70,7 @@ #else newtype SimIO a = SimIO {unSimIO :: IO a} #endif+{-# ANN unSimIO hasBlackBox #-}  instance Functor SimIO where   fmap = fmapSimIO#@@ -76,6 +78,7 @@ fmapSimIO# :: (a -> b) -> SimIO a -> SimIO b fmapSimIO# f (SimIO m) = SimIO (fmap f m) {-# NOINLINE fmapSimIO# #-}+{-# ANN fmapSimIO# hasBlackBox #-}  instance Applicative SimIO where   pure  = pureSimIO#@@ -84,10 +87,12 @@ pureSimIO# :: a -> SimIO a pureSimIO# a = SimIO (pure a) {-# NOINLINE pureSimIO# #-}+{-# ANN pureSimIO# hasBlackBox #-}  apSimIO# :: SimIO (a -> b) -> SimIO a -> SimIO b apSimIO# (SimIO f) (SimIO m) = SimIO (f <*> m) {-# NOINLINE apSimIO# #-}+{-# ANN apSimIO# hasBlackBox #-}  instance Monad SimIO where   return = pureSimIO#@@ -100,6 +105,7 @@ bindSimIO# (SimIO m) k = SimIO (m >>= (\x -> x `seqX` coerce k x)) #endif {-# NOINLINE bindSimIO# #-}+{-# ANN bindSimIO# hasBlackBox #-}  -- | Display a string on /stdout/ display
src/Clash/Explicit/Synchronizer.hs view
@@ -1,9 +1,10 @@ {-| Copyright   :  (C) 2015-2016, University of Twente,                    2016-2019, Myrtle Software Ltd,-                   2017     , Google Inc.+                   2017     , Google Inc.,+                   2021-2022, QBayLogic B.V. License     :  BSD2 (see the file LICENSE)-Maintainer  :  Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer  :  QBayLogic B.V. <devops@qbaylogic.com>  Synchronizer circuits for safe clock domain crossings -}@@ -15,6 +16,7 @@  {-# OPTIONS_GHC -fplugin GHC.TypeLits.Normalise       #-} {-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}+{-# OPTIONS_GHC -fplugin GHC.TypeLits.Extra.Solver    #-}  {-# OPTIONS_HADDOCK show-extensions #-} @@ -26,25 +28,24 @@   ) where -import Control.Applicative         (liftA2) import Data.Bits                   (complement, shiftR, xor) import Data.Constraint             ((:-)(..), Dict (..)) import Data.Constraint.Nat         (leTrans) import Data.Maybe                  (isJust)-import GHC.TypeLits                (type (+), type (-), type (<=))+import GHC.TypeLits                (type (+), type (-), type (<=), type (^), KnownNat) -import Clash.Class.BitPack         (boolToBV)+import Clash.Class.BitPack         (boolToBV, unpack) import Clash.Class.Resize          (truncateB)-import Clash.Prelude.BitIndex      (slice)+import Clash.Class.BitPack.BitIndex (slice) import Clash.Explicit.Mealy        (mealyB)-import Clash.Explicit.RAM          (asyncRam)+import Clash.Explicit.BlockRam     (RamOp (..), trueDualPortBlockRam) import Clash.Explicit.Signal-  (Clock, Reset, Signal, Enable, register, unsafeSynchronizer)-import Clash.Promoted.Nat          (SNat (..), pow2SNat)+  (Clock, Reset, Signal, Enable, register, unsafeSynchronizer, fromEnable, (.&&.))+import Clash.Promoted.Nat          (SNat (..)) import Clash.Promoted.Nat.Literals (d0) import Clash.Signal                (mux, KnownDomain) import Clash.Sized.BitVector       (BitVector, (++#))-import Clash.XException            (NFDataX)+import Clash.XException            (NFDataX, fromJustX)  -- * Dual flip-flop synchronizer @@ -96,27 +97,63 @@ -- * Asynchronous FIFO synchronizer  fifoMem-  :: ( KnownDomain wdom-     , KnownDomain rdom )+  :: forall wdom rdom a addrSize+   . ( KnownDomain wdom+     , KnownDomain rdom+     , NFDataX a+     , KnownNat addrSize+     , 1 <= addrSize )   => Clock wdom   -> Clock rdom   -> Enable wdom-  -> SNat addrSize+  -> Enable rdom   -> Signal wdom Bool   -> Signal rdom (BitVector addrSize)-  -> Signal wdom (Maybe (BitVector addrSize, a))+  -> Signal wdom (BitVector addrSize)+  -> Signal wdom (Maybe a)   -> Signal rdom a-fifoMem wclk rclk en addrSize@SNat full raddr writeM =-  asyncRam-    wclk rclk en-    (pow2SNat addrSize)-    raddr-    (mux full (pure Nothing) writeM)+fifoMem wclk rclk wen ren full raddr waddr wdataM =+  fst $ trueDualPortBlockRam+    rclk wclk portA portB+ where+   portA :: Signal rdom (RamOp (2 ^ addrSize) a)+   portA = mux (fromEnable ren)+               (RamRead . unpack <$> raddr)+               (pure RamNoOp)+   portB :: Signal wdom (RamOp (2 ^ addrSize) a)+   portB = mux (fromEnable wen .&&. fmap not full .&&. fmap isJust wdataM)+               (RamWrite <$> fmap unpack waddr <*> fmap fromJustX wdataM)+               (pure RamNoOp) -ptrCompareT-  :: SNat addrSize-  -> (BitVector (addrSize + 1) -> BitVector (addrSize + 1) -> Bool)+readPtrCompareT+  :: KnownNat addrSize+  => ( BitVector (addrSize + 1)+     , BitVector (addrSize + 1)+     , Bool )   -> ( BitVector (addrSize + 1)+     , Bool )+  -> ( ( BitVector (addrSize + 1)+       , BitVector (addrSize + 1)+       , Bool )+     , ( Bool+       , BitVector addrSize+       , BitVector (addrSize + 1)+       )+     )+readPtrCompareT (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' = ptr' == s_ptr++writePtrCompareT+  :: (2 <= addrSize)+  => SNat addrSize+  -> ( BitVector (addrSize + 1)      , BitVector (addrSize + 1)      , Bool )   -> ( BitVector (addrSize + 1)@@ -129,7 +166,7 @@        , BitVector (addrSize + 1)        )      )-ptrCompareT SNat flagGen (bin, ptr, flag) (s_ptr, inc) =+writePtrCompareT addrSize@SNat (bin, ptr, flag) (s_ptr, inc) =   ((bin', ptr', flag'), (flag, addr, ptr))  where   -- GRAYSTYLE2 pointer@@ -137,9 +174,9 @@   ptr' = (bin' `shiftR` 1) `xor` bin'   addr = truncateB bin -  flag' = flagGen ptr' s_ptr+  flag' = isFull addrSize ptr' s_ptr --- FIFO full: when next pntr == synchonized {~wptr[addrSize:addrSize-1],wptr[addrSize-1:0]}+-- FIFO full: when next pntr == synchronized {~wptr[addrSize:addrSize-1],wptr[addrSize-2:0]} isFull   :: forall addrSize    . (2 <= addrSize)@@ -154,15 +191,22 @@           a2 = SNat @(addrSize - 2)       in  ptr == (complement (slice addrSize a1 s_ptr) ++# slice a2 d0 s_ptr) --- | Synchronizer implemented as a FIFO around an asynchronous RAM. Based on the+-- | 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+-- actually synthesize into one of the dual-ported RAMs found on most FPGAs. -- -- __NB__: This synchronizer can be used for __word__-synchronization.+-- __NB__: This synchronizer will only work safely when you set up the proper+-- bus skew and maximum delay constraints inside your synthesis tool for the+-- clock domain crossings of the gray pointers. asyncFIFOSynchronizer   :: ( KnownDomain wdom      , KnownDomain rdom-     , 2 <= addrSize )+     , 2 <= addrSize+     , NFDataX a )   => SNat addrSize   -- ^ Size of the internally used addresses, the  FIFO contains @2^addrSize@   -- elements.@@ -188,20 +232,20 @@    rdata =     fifoMem-      wclk rclk wen-      addrSize wfull raddr-      (liftA2 (,) <$> (pure <$> waddr) <*> wdataM)+      wclk rclk wen ren+      wfull raddr+      waddr wdataM    (rempty, raddr, rptr) =     mealyB       rclk rrst ren-      (ptrCompareT addrSize (==))+      readPtrCompareT       (0, 0, True)       (s_wptr, rinc)    (wfull, waddr, wptr) =     mealyB       wclk wrst wen-      (ptrCompareT addrSize (isFull addrSize))+      (writePtrCompareT addrSize)       (0, 0, False)       (s_rptr, isJust <$> wdataM)
src/Clash/Explicit/Testbench.hs view
@@ -1,9 +1,10 @@ {-| Copyright  :  (C) 2013-2016, University of Twente,                   2017     , Google Inc.-                  2019     , Myrtle Software Ltd+                  2019     , Myrtle Software Ltd,+                  2021     , QBayLogic B.V. License    :  BSD2 (see the file LICENSE)-Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com> -}  {-# LANGUAGE TypeFamilies #-}@@ -31,27 +32,31 @@   , outputVerifierBitVector   , outputVerifierBitVector'   , biTbClockGen+  , unsafeSimSynchronizer+  , outputVerifierWith   ) where  import Control.Exception     (catch, evaluate) import Debug.Trace           (trace)-import GHC.TypeLits          (KnownNat, type (+))+import Data.Type.Equality    ((:~:)(..))+import Data.Proxy            (Proxy(..))+import GHC.TypeLits          (KnownNat, type (+), sameSymbol, type (<=)) import Prelude               hiding ((!!), length) import System.IO.Unsafe      (unsafeDupablePerformIO)  import Clash.Annotations.Primitive (hasBlackBox) import Clash.Class.Num       (satSucc, SaturationMode(SatBound))-import Clash.Promoted.Nat    (SNat(..), snatToNum)+import Clash.Promoted.Nat    (SNat(..)) import Clash.Promoted.Symbol (SSymbol (..)) import Clash.Explicit.Signal-  (Clock, Reset, System, Signal, clockPeriod, toEnable, fromList, register,-  unbundle, unsafeSynchronizer, veryUnsafeSynchronizer)+  (Clock, Reset, System, Signal, toEnable, fromList, register,+  unbundle, unsafeSynchronizer) import Clash.Signal.Internal (Clock (..), Reset (..)) import Clash.Signal          (mux, KnownDomain, Enable) import Clash.Sized.Index     (Index) import Clash.Sized.Internal.BitVector-  (BitVector, isLike)+  (BitVector, isLike#) import Clash.Sized.Vector    (Vec, (!!), length) import Clash.XException      (ShowX (..), XException) @@ -61,9 +66,6 @@  {- $setup >>> :set -XTemplateHaskell -XDataKinds -XTypeFamilies->>> :m -Clash.Prelude->>> :m -Clash.Prelude.Safe->>> :m -Clash.Prelude.Testbench >>> import Clash.Explicit.Prelude >>> let testInput clk rst = stimuliGenerator clk rst $(listToVecTH [(1::Int),3..21]) >>> let expectedOutput clk rst = outputVerifier' clk rst $(listToVecTH ([70,99,2,3,4,5,7,8,9,10]::[Int]))@@ -74,7 +76,13 @@ -- function simply returns the third 'Signal' unaltered as its result. This -- function is used by 'outputVerifier'. --+-- === Usage in @clashi@ #assert-clashi# --+-- __NB__: When simulating a component that uses 'assert' in @clashi@, usually,+-- the warnings are only logged the first time the component is simulated.+-- Issuing @:reload@ in @clashi@ will discard the cached result of the+-- computation, and warnings will once again be emitted.+-- -- __NB__: This function /can/ be used in synthesizable designs. assert   :: (KnownDomain dom, Eq a, ShowX a)@@ -109,7 +117,7 @@ {-# NOINLINE assert #-} {-# ANN assert hasBlackBox #-} --- | The same as 'assert', but can handle don't care bits in it's expected value.+-- | The same as 'assert', but can handle don't care bits in its expected value. assertBitVector   :: (KnownDomain dom, KnownNat n)   => Clock dom@@ -138,7 +146,7 @@                             ]) r)   <$> checked <*> expected <*> fromList [(0::Integer)..] <*> returned   where-    eqX a b = unsafeDupablePerformIO (catch (evaluate (a `isLike` b))+    eqX a b = unsafeDupablePerformIO (catch (evaluate (a `isLike#` b))                                             (\(_ :: XException) -> return False)) {-# NOINLINE assertBitVector #-} {-# ANN assertBitVector hasBlackBox #-}@@ -185,18 +193,20 @@                 else s {-# INLINABLE stimuliGenerator #-} --- | Same as 'outputVerifier' but used in cases where the testbench domain and+-- | Same as 'outputVerifier' but used in cases where the test bench domain and -- the domain of the circuit under test are the same. outputVerifier'   :: forall l a dom    . ( KnownNat l      , KnownDomain dom      , Eq a-     , ShowX a )+     , ShowX a+     , 1 <= l+     )   => Clock dom-  -- ^ Clock to which the testbench is synchronized to+  -- ^ Clock to which the test bench is synchronized   -> Reset dom-  -- ^ Reset line of testbench+  -- ^ Reset line of test bench   -> Vec l a   -- ^ Samples to compare with   -> Signal dom a@@ -205,13 +215,18 @@   -- ^ Indicator that all samples are verified outputVerifier' =   outputVerifier @l @a @dom @dom-{-# INLINABLE outputVerifier' #-}+{-# INLINE outputVerifier' #-}  -- | Compare a signal (coming from a circuit) to a vector of samples. If a -- sample from the signal is not equal to the corresponding sample in the -- vector, print to stderr and continue testing. This function is--- synthesizable in the sense that HDL simulators will run it.+-- synthesizable in the sense that HDL simulators will run it. If @testDom@ and+-- @circuitDom@ refer to the same domain, it can also be synthesized into+-- hardware. --+-- __NB__: This function uses 'assert'. When simulating this function in+-- @clashi@, read the [note](#assert-clashi).+-- -- Example: -- -- @@@ -246,7 +261,7 @@ -- expected value: 10, not equal to actual value: 9 -- ,False,True] ----- If your working with 'BitVector's containing don't care bits you should+-- If you're working with 'BitVector's containing don't care bits you should -- use 'outputVerifierBitVector'. outputVerifier   :: forall l a testDom circuitDom@@ -254,51 +269,35 @@      , KnownDomain testDom      , KnownDomain circuitDom      , Eq a-     , ShowX a )+     , ShowX a+     , 1 <= l+     )   => Clock testDom-  -- ^ Clock to which the testbench is synchronized to (but not necessarily+  -- ^ Clock to which the test bench is synchronized (but not necessarily   -- the circuit under test)   -> Reset testDom-  -- ^ Reset line of testbench+  -- ^ Reset line of test bench   -> Vec l a   -- ^ Samples to compare with   -> Signal circuitDom a   -- ^ Signal to verify   -> Signal testDom Bool   -- ^ True if all samples are verified-outputVerifier clk rst samples i0 =-    let t1    = snatToNum (clockPeriod @circuitDom)-        t2    = snatToNum (clockPeriod @testDom)-        i1    = veryUnsafeSynchronizer t1 t2 i0-        en    = toEnable (pure True)-        (s,o) = unbundle (genT <$> register clk rst en 0 s)-        (e,f) = unbundle o-        f'    = register clk rst en False f-        -- Only assert while not finished-    in  mux f' f' $ assert clk rst "outputVerifier" i1 e f'-  where-    genT :: Index l -> (Index l,(a,Bool))-    genT s = (s',(samples !! s,finished))-      where-        maxI = toEnum (length samples - 1)--        s' = if s < maxI-                then s + 1-                else s--        finished = s == maxI-{-# INLINABLE outputVerifier #-}+outputVerifier =+  outputVerifierWith (\clk rst -> assert clk rst "outputVerifier")+{-# INLINE outputVerifier #-} --- | Same as 'outputVerifier'', but can handle don't care bits in it's expected+-- | Same as 'outputVerifier'', but can handle don't care bits in its expected -- values. outputVerifierBitVector'   :: forall l n dom    . ( KnownNat l      , KnownNat n      , KnownDomain dom+     , 1 <= l      )   => Clock dom-  -- ^ Clock to which the input signal is synchronized to+  -- ^ Clock to which the input signal is synchronized   -> Reset dom   -> Vec l (BitVector n)   -- ^ Samples to compare with@@ -308,9 +307,9 @@   -- ^ Indicator that all samples are verified outputVerifierBitVector' =   outputVerifierBitVector @l @n @dom @dom-{-# INLINABLE outputVerifierBitVector' #-}+{-# INLINE outputVerifierBitVector' #-} --- | Same as 'outputVerifier', but can handle don't care bits in it's+-- | Same as 'outputVerifier', but can handle don't care bits in its -- expected values. outputVerifierBitVector   :: forall l n testDom circuitDom@@ -318,38 +317,72 @@      , KnownNat n      , KnownDomain testDom      , KnownDomain circuitDom+     , 1 <= l      )   => Clock testDom-  -- ^ Clock to which the input signal is synchronized to+  -- ^ Clock to which the test bench is synchronized (but not necessarily+  -- the circuit under test)   -> Reset testDom+  -- ^ Reset line of test bench   -> Vec l (BitVector n)   -- ^ Samples to compare with   -> Signal circuitDom (BitVector n)   -- ^ Signal to verify   -> Signal testDom Bool   -- ^ Indicator that all samples are verified-outputVerifierBitVector clk rst samples i0 =-    let t1    = snatToNum (clockPeriod @circuitDom)-        t2    = snatToNum (clockPeriod @testDom)-        i1    = veryUnsafeSynchronizer t1 t2 i0+outputVerifierBitVector =+  outputVerifierWith+    (\clk rst -> assertBitVector clk rst "outputVerifierBitVector")+{-# INLINE outputVerifierBitVector #-}++outputVerifierWith+  :: forall l a testDom circuitDom+   . ( KnownNat l+     , KnownDomain testDom+     , KnownDomain circuitDom+     , Eq a+     , ShowX a+     , 1 <= l+     )+  => (    Clock testDom+       -> Reset testDom+       -> Signal testDom a+       -> Signal testDom a+       -> Signal testDom Bool+       -> Signal testDom Bool+      )+  -- ^ The @assert@ function to use+  -> Clock testDom+  -- ^ Clock to which the test bench is synchronized (but not necessarily+  -- the circuit under test)+  -> Reset testDom+  -- ^ Reset line of test bench+  -> Vec l a+  -- ^ Samples to compare with+  -> Signal circuitDom a+  -- ^ Signal to verify+  -> Signal testDom Bool+  -- ^ True if all samples are verified+outputVerifierWith assertF clk rst samples i0 =+    let i1    = sync i0         en    = toEnable (pure True)         (s,o) = unbundle (genT <$> register clk rst en 0 s)         (e,f) = unbundle o         f'    = register clk rst en False f         -- Only assert while not finished-    in  mux f' f' $ assertBitVector clk rst "outputVerifierBitVector'" i1 e f'+    in  mux f' f' $ assertF clk rst i1 e f'   where-    genT :: Index l -> (Index l,(BitVector n,Bool))+    genT :: Index l -> (Index l,(a,Bool))     genT s = (s',(samples !! s,finished))       where-        maxI = toEnum (length samples - 1)--        s' = if s < maxI-                then s + 1-                else s--        finished = s == maxI-{-# INLINABLE outputVerifierBitVector #-}+        s' = satSucc SatBound s+        finished = s == maxBound+    sync :: Signal circuitDom a+         -> Signal testDom a+    sync = case sameSymbol (Proxy @circuitDom) (Proxy @testDom) of+             Just Refl -> id+             Nothing   -> unsafeSimSynchronizer (Clock SSymbol) clk+{-# INLINABLE outputVerifierWith #-}  -- | Ignore signal for a number of cycles, while outputting a static value. ignoreFor@@ -374,9 +407,8 @@   counter = register clk rst en 0 (satSucc SatBound <$> counter)  -- | Same as 'tbClockGen', but returns two clocks on potentially different--- domains. To be used in situations where the circuit under test runs--- in a different domain than the circuit testing it. Most commonly used--- to test synchronous circuits (with an asynchronous test circuit).+-- domains. To be used in situations where the test circuit potentially operates+-- on a different clock than the device under test. biTbClockGen   :: forall testDom circuitDom    . ( KnownDomain testDom@@ -475,3 +507,24 @@   :: Signal System Bool   -> Clock System tbSystemClockGen = tbClockGen++-- | Cross clock domains in a way that is unsuitable for hardware but good+-- enough for simulation.+--+-- It's equal to 'unsafeSynchronizer' but will warn when used outside of a test+-- bench. 'outputVerifier' uses this function when it needs to cross between+-- clock domains, which will render it unsuitable for synthesis, but good enough+-- for simulating the generated HDL.+unsafeSimSynchronizer+  :: forall dom1 dom2 a+   . ( KnownDomain dom1+     , KnownDomain dom2 )+  => Clock dom1+  -- ^ 'Clock' of the incoming signal+  -> Clock dom2+  -- ^ 'Clock' of the outgoing signal+  -> Signal dom1 a+  -> Signal dom2 a+unsafeSimSynchronizer = unsafeSynchronizer+{-# NOINLINE unsafeSimSynchronizer #-}+{-# ANN unsafeSimSynchronizer hasBlackBox #-}
src/Clash/Explicit/Verification.hs view
@@ -36,10 +36,12 @@   , timpliesOverlapping   , always   , never+  , eventually    -- * Asserts   , assert   , cover+  , assume    -- * Assertion checking   , check@@ -209,11 +211,16 @@ always = Assertion IsTemporal . CvAlways . assertion . toAssertionValue {-# INLINE always #-} --- | Specify assertion should _never_ hold+-- | Specify assertion should _never_ hold (not supported by SVA) never :: AssertionValue dom a => a -> Assertion dom never = Assertion IsTemporal . CvNever . assertion . toAssertionValue {-# INLINE never #-} +-- | Specify assertion should _eventually_ hold+eventually :: AssertionValue dom a => a -> Assertion dom+eventually = Assertion IsTemporal . CvEventually . assertion . toAssertionValue+{-# INLINE eventually #-}+ -- | Check whether given assertion always holds. Results can be collected with -- 'check'. assert :: AssertionValue dom a => a -> Property dom@@ -225,6 +232,13 @@ cover :: AssertionValue dom a => a -> Property dom cover = Property . CvCover . assertion . toAssertionValue {-# INLINE cover #-}++-- | Inform the prover that this property is true. This is the same as 'assert'+-- for simulations.+assume :: AssertionValue dom a => a -> Property dom+assume = Property . CvAssume . assertion . toAssertionValue+{-# INLINE assume #-}+  -- | Print property as PSL/SVA in HDL. Clash simulation support not yet -- implemented.
src/Clash/HaskellPrelude.hs view
@@ -1,5 +1,6 @@ {-|   Copyright   :  (C) 2019, QBayLogic B.V.+                 (C) 2021, QBayLogic B.V.   License     :  BSD2 (see the file LICENSE)   Maintainer  :  QBayLogic B.V <devops@qbaylogic.com> @@ -16,11 +17,54 @@ {-# OPTIONS_HADDOCK show-extensions, not-home #-}  module Clash.HaskellPrelude-  (module Prelude)+  (module Prelude, (&&), (||), not) where  import Prelude hiding   ((++), (!!), concat, concatMap, drop, even, foldl, foldl1, foldr, foldr1, head, init,    iterate, last, length, map, odd, repeat, replicate, reverse, scanl, scanr, splitAt,    tail, take, unzip, unzip3, zip, zip3, zipWith, zipWith3, undefined, (^),-   getChar, putChar, getLine)+   getChar, putChar, getLine, (&&), (||), not)++import qualified Prelude+import GHC.Magic (noinline)++{-+Note [use of noinline]+~~~~~~~~~~~~~~~~~~~~~~+The magic noinline function is used here to prevent GHC inlining these+functions in the simplifier. They are removed (by GHC) post-simplifier, so+they have no negative impact on Clash's normalization.++Why prevent this inlining? When GHC sees a function like++    topEntity :: Bool -> Bool -> Bool+    topEntity a b = a && b++it inlines the definition of && to become++    topEntity a b =+      case a of+        True -> case b of+                  True -> True+                  False -> False+        False -> False++which Clash will render as multiplexer(s) instead of using the and operator+available in the targeted HDL backend. While this has no impact on the quality+of the final result (EDA tools will optimize this with ease in P&R), it makes+the generated HDL (and RTL view of circuits) more obfuscated to read.+-}++infixr 3 &&++(&&) :: Bool -> Bool -> Bool+(&&) = noinline (Prelude.&&)++infixr 2 ||++(||) :: Bool -> Bool -> Bool+(||) = noinline (Prelude.||)++not :: Bool -> Bool+not = noinline Prelude.not
src/Clash/Intel/ClockGen.hs view
@@ -1,8 +1,9 @@ {-| Copyright  :  (C) 2017-2018, Google Inc                   2019     , Myrtle Software+                  2022     , QBayLogic B.V. License    :  BSD2 (see the file LICENSE)-Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>  PLL and other clock-related components for Intel (Altera) FPGAs -}@@ -14,6 +15,7 @@   , alteraPll   ) where +import Clash.Annotations.Primitive (hasBlackBox) import Clash.Clocks           (Clocks (..)) import Clash.Promoted.Symbol  (SSymbol) import Clash.Signal.Internal@@ -57,6 +59,7 @@   -- ^ (Stable PLL clock, PLL lock) altpll !_ = knownDomain @domIn `seq` knownDomain @domOut `seq` clocks {-# NOINLINE altpll #-}+{-# ANN altpll hasBlackBox #-}  -- | A clock source that corresponds to the Intel/Quartus \"Altera PLL\" -- component (Arria V, Stratix V, Cyclone V) with settings to provide a stable@@ -100,3 +103,4 @@   -> t alteraPll !_ = clocks {-# NOINLINE alteraPll #-}+{-# ANN alteraPll hasBlackBox #-}
+ src/Clash/Num/Erroring.hs view
@@ -0,0 +1,155 @@+{-+Copyright   : (C) 2021, QBayLogic B.V.+License     : BSD2 (see the file LICENSE)+Maintainer  : QBayLogic B.V. <devops@qbaylogic.com>+-}++{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++module Clash.Num.Erroring+  ( Erroring(fromErroring)+  , toErroring+  ) where++import Control.DeepSeq (NFData)+import Data.Binary (Binary)+import Data.Bits (Bits, FiniteBits)+import Data.Coerce (coerce)+import Data.Functor.Compose (Compose(..))+import Data.Hashable (Hashable)+import GHC.TypeLits (KnownNat, type (+))++import Clash.Class.BitPack (BitPack)+import Clash.Class.Num (SaturationMode(SatError), SaturatingNum(..))+import Clash.Class.Parity (Parity)+import Clash.Class.Resize (Resize(..))+import Clash.XException (NFDataX, ShowX, errorX)++-- | An erroring number type is one where all operations return a+-- 'Clash.XException.XExecption' if they would go out of bounds for the+-- underlying type.+--+-- Numbers can be converted to error by default using 'toErroring'.+--+newtype Erroring a =+  Erroring { fromErroring :: a }+  deriving newtype+    ( Binary+    , Bits+    , BitPack+    , Bounded+    , Eq+    , FiniteBits+    , Hashable+    , NFData+    , NFDataX+    , Ord+    , Parity+    , Show+    , ShowX+    )++{-# INLINE toErroring #-}+toErroring :: (SaturatingNum a) => a -> Erroring a+toErroring = Erroring++instance (Resize f) => Resize (Compose Erroring f) where+  {-# INLINE resize #-}+  resize+    :: forall a b+     . (KnownNat a, KnownNat b)+    => Compose Erroring f a+    -> Compose Erroring f b+  resize = coerce (resize @f @a @b)++  {-# INLINE zeroExtend #-}+  zeroExtend+    :: forall a b+     . (KnownNat a, KnownNat b)+    => Compose Erroring f a+    -> Compose Erroring f (b + a)+  zeroExtend = coerce (zeroExtend @f @a @b)++  {-# INLINE truncateB #-}+  truncateB+    :: forall a b+     . (KnownNat a)+    => Compose Erroring f (a + b)+    -> Compose Erroring f a+  truncateB = coerce (truncateB @f @a @b)++instance (Bounded a, Ord a, SaturatingNum a) => Num (Erroring a) where+  {-# INLINE (+) #-}+  (+) = coerce (satAdd @a SatError)++  {-# INLINE (-) #-}+  (-) = coerce (satSub @a SatError)++  {-# INLINE (*) #-}+  (*) = coerce (satMul @a SatError)++  negate x+    | 0 == x = x+    | 0 <= minBound @a = errorX "Erroring.negate: result exceeds minBound"+    | x == minBound = errorX "Erroring.negate: result exceeds maxBound"+    | otherwise = coerce (negate @a) x++  abs x+    | x == minBound && x < 0 = errorX "Erroring.abs: result exceeds maxBound"+    | otherwise = coerce (abs @a) x++  {-# INLINE signum #-}+  signum = coerce (signum @a)++  {-# INLINE fromInteger #-}+  -- TODO This does what the underlying representation does if the Integer+  -- is not in range (typically wrapping). It would be better if this also+  -- threw an XException, but in a way which remained synthesizable.+  fromInteger = coerce (fromInteger @a)++instance (Enum a, SaturatingNum a) => Enum (Erroring a) where+  {-# INLINE succ #-}+  succ = coerce (satSucc @a SatError)++  {-# INLINE pred #-}+  pred = coerce (satPred @a SatError)++  {-# INLINE toEnum #-}+  toEnum = coerce (toEnum @a)++  {-# INLINE fromEnum #-}+  fromEnum = coerce (fromEnum @a)++instance (Real a, SaturatingNum a) => Real (Erroring a) where+  {-# INLINE toRational #-}+  toRational = coerce (toRational @a)++instance (Integral a, SaturatingNum a) => Integral (Erroring a) where+  quotRem x y+    | x == minBound && y < 0 && y == -1 =+        (errorX "Erroring.quotRem: result exceeds maxBound", 0)+    | otherwise = coerce (quotRem @a) x y++  divMod x y+    | x == minBound && y < 0 && y == -1 =+        (errorX "Erroring.divMod: result exceeds maxBound", 0)+    | otherwise = coerce (divMod @a) x y++  {-# INLINE toInteger #-}+  toInteger = coerce (toInteger @a)++instance (Fractional a, Ord a, SaturatingNum a) => Fractional (Erroring a) where+  {-# INLINE recip #-}+  recip = coerce (recip @a)++  {-# INLINE fromRational #-}+  -- TODO This does what the underlying representation does if the Rational+  -- is not in range (typically wrapping). It would be better if this also+  -- threw an XException, but in a way which remained synthesizable.+  fromRational = coerce (fromRational @a)++instance (RealFrac a, SaturatingNum a) => RealFrac (Erroring a) where+  {-# INLINE properFraction #-}+  properFraction :: forall b. (Integral b) => Erroring a -> (b, Erroring a)+  properFraction = coerce (properFraction @a @b)
+ src/Clash/Num/Overflowing.hs view
@@ -0,0 +1,189 @@+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}++module Clash.Num.Overflowing+  ( Overflowing(fromOverflowing, hasOverflowed)+  , toOverflowing+  , clearOverflow+  ) where++import Prelude hiding (even, odd)++import Control.DeepSeq (NFData)+import Data.Binary (Binary)+import Data.Function (on)+import Data.Hashable (Hashable)+import GHC.Generics (Generic)+import GHC.TypeLits (KnownNat, type (+))++import Clash.Class.BitPack (BitPack(..))+import Clash.Class.Num (SaturationMode(SatWrap, SatZero), SaturatingNum(..))+import Clash.Class.Parity (Parity(..))+import Clash.XException (NFDataX, ShowX)++-- | An overflowing number behaves similarly to a 'Clash.Num.Wrapping.Wrapping'+-- number, but also includes an overflow status flag which can be used to more+-- easily check if an overflow has occurred.+--+-- Numbers can be converted to be 'Overflowing' using 'toOverflowing'.+--+data Overflowing a = Overflowing+  { fromOverflowing :: a+  , hasOverflowed :: Bool+  }+  deriving stock (Generic, Show)+  deriving anyclass (Binary, Hashable, NFData, NFDataX, ShowX)++{-# INLINE toOverflowing #-}+toOverflowing :: a -> Overflowing a+toOverflowing x = Overflowing x False++{-# INLINE clearOverflow #-}+-- | Reset the overflow status flag to False.+clearOverflow :: Overflowing a -> Overflowing a+clearOverflow x = x { hasOverflowed = False }++instance (Eq a) => Eq (Overflowing a) where+  {-# INLINE (==) #-}+  (==) = (==) `on` fromOverflowing++instance (Ord a) => Ord (Overflowing a) where+  {-# INLINE compare #-}+  compare = compare `on` fromOverflowing++instance (BitPack a, KnownNat (BitSize a + 1)) => BitPack (Overflowing a) where+  type BitSize (Overflowing a) = BitSize a + 1+  -- Default instance, no explicit implementations.++instance (Parity a) => Parity (Overflowing a) where+  {-# INLINE even #-}+  even = even . fromOverflowing++  {-# INLINE odd #-}+  odd = odd . fromOverflowing++instance (Bounded a, Ord a, SaturatingNum a) => Num (Overflowing a) where+  Overflowing x a + Overflowing y b+    | y > 0+    , x > satSub SatWrap maxBound y+    = withOverflow True++    | y < 0+    , x < satSub SatWrap minBound y+    = withOverflow True++    | otherwise+    = withOverflow (a || b)+   where+    withOverflow = Overflowing (satAdd SatWrap x y)++  Overflowing x a - Overflowing y b+    | y < 0+    , x > satAdd SatWrap maxBound y+    = withOverflow True++    | y > 0+    , x < satAdd SatWrap minBound y+    = withOverflow True++    | otherwise+    = withOverflow (a || b)+   where+    withOverflow = Overflowing (satSub SatWrap x y)++  Overflowing x a * Overflowing y b+    | x /= 0+    , y /= 0+    , satMul SatZero x y == 0+    = withOverflow True++    | otherwise+    = withOverflow (a || b)+   where+    withOverflow = Overflowing (satMul SatWrap x y)++  negate n@(Overflowing x a)+    | 0 == x = n+    | 0 <= minBound @a = withOverflow True+    | x == minBound = withOverflow True+    | otherwise = withOverflow a+   where+    withOverflow = Overflowing (negate x)++  abs (Overflowing x a)+    | x == minBound && x < 0 = Overflowing x True+    | otherwise = Overflowing (abs x) a++  signum (Overflowing x a) =+    Overflowing (signum x) a++  -- TODO This does what the underlying representation does if the Integer+  -- is not in range (typically wrapping). It would be better if this also+  -- definitely wrapped, but in a way which remained synthesizable.+  fromInteger i =+    Overflowing (fromInteger i) False++instance (Bounded a) => Bounded (Overflowing a) where+  minBound = Overflowing minBound False+  maxBound = Overflowing maxBound False++instance (Enum a, Eq a, SaturatingNum a) => Enum (Overflowing a) where+  succ (Overflowing x a)+    | x == maxBound = withOverflow True+    | otherwise = withOverflow a+   where+    withOverflow = Overflowing (satSucc SatWrap x)++  pred (Overflowing x a)+    | x == minBound = withOverflow True+    | otherwise = withOverflow a+   where+    withOverflow = Overflowing (satPred SatWrap x)++  toEnum i = Overflowing (toEnum i) False+  fromEnum = fromEnum . fromOverflowing++instance (Real a, SaturatingNum a) => Real (Overflowing a) where+  toRational = toRational . fromOverflowing++instance (Integral a, SaturatingNum a) => Integral (Overflowing a) where+  quotRem (Overflowing x a) (Overflowing y b)+    | x == minBound && y < 0 && y == -1 =+        withOverflow True++    | otherwise =+        withOverflow (a || b)+   where+    withOverflow o =+      let (q, r) = quotRem x y+       in (Overflowing q o, Overflowing r False)++  divMod (Overflowing x a) (Overflowing y b)+    | x == minBound && y < 0 && y == -1 =+        withOverflow True++    | otherwise =+        withOverflow (a || b)+   where+    withOverflow o =+      let (d, m) = divMod x y+       in (Overflowing d o, Overflowing m False)++  toInteger = toInteger . fromOverflowing++instance (Fractional a, Ord a, SaturatingNum a) => Fractional (Overflowing a) where+  recip x =+    x { fromOverflowing = recip (fromOverflowing x) }++  -- TODO This does what the underlying representation does if the Rational+  -- is not in range (typically wrapping). It would be better if this also+  -- definitely wrapped, but in a way which remained synthesizable.+  fromRational i =+    Overflowing (fromRational i) False++instance (RealFrac a, SaturatingNum a) => RealFrac (Overflowing a) where+  properFraction (Overflowing x _) =+    let (n, f) = properFraction x+     in (n, Overflowing f False)
+ src/Clash/Num/Saturating.hs view
@@ -0,0 +1,154 @@+{-+Copyright   : (C) 2021, QBayLogic B.V.+License     : BSD2 (see the file LICENSE)+Maintainer  : QBayLogic B.V. <devops@qbaylogic.com>+-}++{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++module Clash.Num.Saturating+  ( Saturating(fromSaturating)+  , toSaturating+  ) where++import Control.DeepSeq (NFData)+import Data.Binary (Binary)+import Data.Bits (Bits, FiniteBits)+import Data.Coerce (coerce)+import Data.Functor.Compose (Compose(..))+import Data.Hashable (Hashable)+import GHC.TypeLits (KnownNat, type (+))++import Clash.Class.BitPack (BitPack)+import Clash.Class.Num (SaturationMode(SatBound), SaturatingNum(..))+import Clash.Class.Parity (Parity)+import Clash.Class.Resize (Resize(..))+import Clash.XException (NFDataX, ShowX)++-- | A saturating number type is one where all operations saturate at the+-- bounds of the underlying type, i.e. operations which overflow return+-- 'maxBound' and operations that underflow return 'minBound'.+--+-- Numbers can be converted to saturate by default using 'toSaturating'.+--+newtype Saturating a =+  Saturating { fromSaturating :: a }+  deriving newtype+    ( Binary+    , Bits+    , BitPack+    , Bounded+    , Eq+    , FiniteBits+    , Hashable+    , NFData+    , NFDataX+    , Ord+    , Parity+    , Show+    , ShowX+    )++{-# INLINE toSaturating #-}+toSaturating :: (SaturatingNum a) => a -> Saturating a+toSaturating = Saturating++instance (Resize f) => Resize (Compose Saturating f) where+  {-# INLINE resize #-}+  resize+    :: forall a b+     . (KnownNat a, KnownNat b)+    => Compose Saturating f a+    -> Compose Saturating f b+  resize = coerce (resize @f @a @b)++  {-# INLINE zeroExtend #-}+  zeroExtend+    :: forall a b+     . (KnownNat a, KnownNat b)+    => Compose Saturating f a+    -> Compose Saturating f (b + a)+  zeroExtend = coerce (zeroExtend @f @a @b)++  {-# INLINE truncateB #-}+  truncateB+    :: forall a b+     . (KnownNat a)+    => Compose Saturating f (a + b)+    -> Compose Saturating f a+  truncateB = coerce (truncateB @f @a @b)++instance (Ord a, SaturatingNum a) => Num (Saturating a) where+  {-# INLINE (+) #-}+  (+) = coerce (satAdd @a SatBound)++  {-# INLINE (-) #-}+  (-) = coerce (satSub @a SatBound)++  {-# INLINE (*) #-}+  (*) = coerce (satMul @a SatBound)++  negate x+    | 0 <= minBound @a = 0+    | x == minBound = maxBound+    | otherwise = coerce (negate @a) x++  abs x+    | x == minBound && x < 0 = maxBound+    | otherwise = coerce (abs @a) x++  {-# INLINE signum #-}+  signum = coerce (signum @a)++  {-# INLINE fromInteger #-}+  -- TODO This does what the underlying representation does if the Integer+  -- is not in range (typically wrapping). It would be better if this also+  -- saturated, but in a way which remained synthesizable.+  fromInteger = coerce (fromInteger @a)++instance (Enum a, SaturatingNum a) => Enum (Saturating a) where+  {-# INLINE succ #-}+  -- Deliberately breaks the Enum law that succ maxBound ~> error+  succ = coerce (satSucc @a SatBound)++  {-# INLINE pred #-}+  -- Deliberately breaks the Enum law that pred minBound ~> error+  pred = coerce (satPred @a SatBound)++  {-# INLINE toEnum #-}+  toEnum = coerce (toEnum @a)++  {-# INLINE fromEnum #-}+  fromEnum = coerce (fromEnum @a)++instance (Real a, SaturatingNum a) => Real (Saturating a) where+  {-# INLINE toRational #-}+  toRational = coerce (toRational @a)++instance (Integral a, SaturatingNum a) => Integral (Saturating a) where+  quotRem x y+    | x == minBound && y < 0 && y == -1 = (maxBound, 0)+    | otherwise = coerce (quotRem @a) x y++  divMod x y+    | x == minBound && y < 0 && y == -1 = (maxBound, 0)+    | otherwise = coerce (divMod @a) x y++  {-# INLINE toInteger #-}+  toInteger = coerce (toInteger @a)++instance (Fractional a, Ord a, SaturatingNum a) => Fractional (Saturating a) where+  {-# INLINE recip #-}+  recip = coerce (recip @a)++  {-# INLINE fromRational #-}+  -- TODO This does what the underlying representation does if the Rational+  -- is not in range (typically wrapping). It would be better if this also+  -- saturated, but in a way which remained synthesizable.+  fromRational = coerce (fromRational @a)++instance (Ord a, RealFrac a, SaturatingNum a) => RealFrac (Saturating a) where+  {-# INLINE properFraction #-}+  properFraction :: forall b. (Integral b) => Saturating a -> (b, Saturating a)+  properFraction = coerce (properFraction @a @b)
+ src/Clash/Num/Wrapping.hs view
@@ -0,0 +1,151 @@+{-+Copyright   : (C) 2021, QBayLogic B.V.+License     : BSD2 (see the file LICENSE)+Maintainer  : QBayLogic B.V. <devops@qbaylogic.com>+-}++{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++module Clash.Num.Wrapping+  ( Wrapping(fromWrapping)+  , toWrapping+  ) where++import Control.DeepSeq (NFData)+import Data.Binary (Binary)+import Data.Bits (Bits, FiniteBits)+import Data.Coerce (coerce)+import Data.Functor.Compose (Compose(..))+import Data.Hashable (Hashable)+import GHC.TypeLits (KnownNat, type (+))++import Clash.Class.BitPack (BitPack)+import Clash.Class.Num (SaturationMode(SatWrap), SaturatingNum(..))+import Clash.Class.Parity (Parity)+import Clash.Class.Resize (Resize(..))+import Clash.XException (NFDataX, ShowX)++-- | A wrapping number type is one where all operations wrap between minBound+-- and maxBound (and vice-versa) if the result goes out of bounds for the+-- underlying type.+--+-- Numbers can be converted to wrap by default using 'toWrapping'.+--+newtype Wrapping a =+  Wrapping { fromWrapping :: a }+  deriving newtype+    ( Binary+    , Bits+    , BitPack+    , Bounded+    , Eq+    , FiniteBits+    , Hashable+    , NFData+    , NFDataX+    , Ord+    , Parity+    , Show+    , ShowX+    )++{-# INLINE toWrapping #-}+toWrapping :: (SaturatingNum a) => a -> Wrapping a+toWrapping = Wrapping++instance (Resize f) => Resize (Compose Wrapping f) where+  {-# INLINE resize #-}+  resize+    :: forall a b+     . (KnownNat a, KnownNat b)+    => Compose Wrapping f a+    -> Compose Wrapping f b+  resize = coerce (resize @f @a @b)++  {-# INLINE zeroExtend #-}+  zeroExtend+    :: forall a b+     . (KnownNat a, KnownNat b)+    => Compose Wrapping f a+    -> Compose Wrapping f (b + a)+  zeroExtend = coerce (zeroExtend @f @a @b)++  {-# INLINE truncateB #-}+  truncateB+    :: forall a b+     . (KnownNat a)+    => Compose Wrapping f (a + b)+    -> Compose Wrapping f a+  truncateB = coerce (truncateB @f @a @b)++instance (SaturatingNum a) => Num (Wrapping a) where+  {-# INLINE (+) #-}+  (+) = coerce (satAdd @a SatWrap)++  {-# INLINE (-) #-}+  (-) = coerce (satSub @a SatWrap)++  {-# INLINE (*) #-}+  (*) = coerce (satMul @a SatWrap)++  -- Assume the default behaviour is to wrap anyway.++  {-# INLINE negate #-}+  negate = coerce (negate @a)++  {-# INLINE abs #-}+  abs = coerce (abs @a)++  {-# INLINE signum #-}+  signum = coerce (signum @a)++  {-# INLINE fromInteger #-}+  -- TODO This does what the underlying representation does if the Integer+  -- is not in range (typically wrapping). It would be better if this also+  -- definitely wrapped, but in a way which remained synthesizable.+  fromInteger = coerce (fromInteger @a)++instance (Enum a, SaturatingNum a) => Enum (Wrapping a) where+  {-# INLINE succ #-}+  -- Deliberately breaks the Enum law that succ maxBound ~> error+  succ = coerce (satSucc @a SatWrap)++  {-# INLINE pred #-}+  -- Deliberately breaks the Enum law that pred minBound ~> error+  pred = coerce (satPred @a SatWrap)++  {-# INLINE toEnum #-}+  toEnum = coerce (toEnum @a)++  {-# INLINE fromEnum #-}+  fromEnum = coerce (fromEnum @a)++instance (Real a, SaturatingNum a) => Real (Wrapping a) where+  {-# INLINE toRational #-}+  toRational = coerce (toRational @a)++instance (Integral a, SaturatingNum a) => Integral (Wrapping a) where+  {-# INLINE quotRem #-}+  quotRem = coerce (quotRem @a)++  {-# INLINE divMod #-}+  divMod = coerce (divMod @a)++  {-# INLINE toInteger #-}+  toInteger = coerce (toInteger @a)++instance (Fractional a, SaturatingNum a) => Fractional (Wrapping a) where+  {-# INLINE recip #-}+  recip = coerce (recip @a)++  {-# INLINE fromRational #-}+  -- TODO This does what the underlying representation does if the Rational+  -- is not in range (typically wrapping). It would be better if this also+  -- definitely wrapped, but in a way which remained synthesizable.+  fromRational = coerce (fromRational @a)++instance (RealFrac a, SaturatingNum a) => RealFrac (Wrapping a) where+  {-# INLINE properFraction #-}+  properFraction :: forall b. (Integral b) => Wrapping a -> (b, Wrapping a)+  properFraction = coerce (properFraction @a @b)
+ src/Clash/Num/Zeroing.hs view
@@ -0,0 +1,153 @@+{-+Copyright   : (C) 2021, QBayLogic B.V.+License     : BSD2 (see the file LICENSE)+Maintainer  : QBayLogic B.V. <devops@qbaylogic.com>+-}++{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++module Clash.Num.Zeroing+  ( Zeroing(fromZeroing)+  , toZeroing+  ) where++import Control.DeepSeq (NFData)+import Data.Binary (Binary)+import Data.Bits (Bits, FiniteBits)+import Data.Coerce (coerce)+import Data.Functor.Compose (Compose(..))+import Data.Hashable (Hashable)+import GHC.TypeLits (KnownNat, type (+))++import Clash.Class.BitPack (BitPack)+import Clash.Class.Num (SaturationMode(SatZero), SaturatingNum(..))+import Clash.Class.Parity (Parity)+import Clash.Class.Resize (Resize(..))+import Clash.XException (NFDataX, ShowX)++-- | A zeroing number type is one where all operations return zero if they go+-- out of bounds for the underlying type.+--+-- Numbers can be converted to zero by default using `toZeroing`.+--+newtype Zeroing a =+  Zeroing { fromZeroing :: a }+  deriving newtype+    ( Binary+    , Bits+    , BitPack+    , Bounded+    , Eq+    , FiniteBits+    , Hashable+    , NFData+    , NFDataX+    , Ord+    , Parity+    , Show+    , ShowX+    )++{-# INLINE toZeroing #-}+toZeroing :: (SaturatingNum a) => a -> Zeroing a+toZeroing = Zeroing++instance (Resize f) => Resize (Compose Zeroing f) where+  {-# INLINE resize #-}+  resize+    :: forall a b+     . (KnownNat a, KnownNat b)+    => Compose Zeroing f a+    -> Compose Zeroing f b+  resize = coerce (resize @f @a @b)++  {-# INLINE zeroExtend #-}+  zeroExtend+    :: forall a b+     . (KnownNat a, KnownNat b)+    => Compose Zeroing f a+    -> Compose Zeroing f (b + a)+  zeroExtend = coerce (zeroExtend @f @a @b)++  {-# INLINE truncateB #-}+  truncateB+    :: forall a b+     . (KnownNat a)+    => Compose Zeroing f (a + b)+    -> Compose Zeroing f a+  truncateB = coerce (truncateB @f @a @b)++instance (Bounded a, Ord a, SaturatingNum a) => Num (Zeroing a) where+  {-# INLINE (+) #-}+  (+) = coerce (satAdd @a SatZero)++  {-# INLINE (-) #-}+  (-) = coerce (satSub @a SatZero)++  {-# INLINE (*) #-}+  (*) = coerce (satMul @a SatZero)++  negate x+    | 0 <= minBound @a = 0+    | x == minBound = 0+    | otherwise = coerce (negate @a) x++  abs x+    | x == minBound && x < 0 = 0+    | otherwise = coerce (abs @a) x++  {-# INLINE signum #-}+  signum = coerce (signum @a)++  {-# INLINE fromInteger #-}+  -- TODO This does what the underlying representation does if the Integer+  -- is not in range (typically wrapping). It would be better if this also+  -- returned zero, but in a way which remained synthesizable.+  fromInteger = coerce (fromInteger @a)++instance (Enum a, SaturatingNum a) => Enum (Zeroing a) where+  {-# INLINE succ #-}+  -- Deliberately breaks the Enum law that succ maxBound ~> error+  succ = coerce (satSucc @a SatZero)++  {-# INLINE pred #-}+  -- Deliberately breaks the Enum law that pred minBound ~> error+  pred = coerce (satPred @a SatZero)++  {-# INLINE toEnum #-}+  toEnum = coerce (toEnum @a)++  {-# INLINE fromEnum #-}+  fromEnum = coerce (fromEnum @a)++instance (Real a, SaturatingNum a) => Real (Zeroing a) where+  {-# INLINE toRational #-}+  toRational = coerce (toRational @a)++instance (Integral a, SaturatingNum a) => Integral (Zeroing a) where+  quotRem x y+    | x == minBound && y < 0 && y == -1 = (0, 0)+    | otherwise = coerce (quotRem @a) x y++  divMod x y+    | x == minBound && y < 0 && y == -1 = (0, 0)+    | otherwise = coerce (divMod @a) x y++  {-# INLINE toInteger #-}+  toInteger = coerce (toInteger @a)++instance (Fractional a, Ord a, SaturatingNum a) => Fractional (Zeroing a) where+  {-# INLINE recip #-}+  recip = coerce (recip @a)++  {-# INLINE fromRational #-}+  -- TODO This does what the underlying representation does if the Rational+  -- is not in range (typically wrapping). It would be better if this also+  -- returned zero, but in a way which remained synthesizable.+  fromRational = coerce (fromRational @a)++instance (RealFrac a, SaturatingNum a) => RealFrac (Zeroing a) where+  {-# INLINE properFraction #-}+  properFraction :: forall b. (Integral b) => Zeroing a -> (b, Zeroing a)+  properFraction = coerce (properFraction @a @b)
src/Clash/Prelude.hs view
@@ -1,9 +1,10 @@ {-|   Copyright   :  (C) 2013-2016, University of Twente,                      2017-2019, Myrtle Software Ltd-                     2017     , Google Inc.+                     2017     , Google Inc.,+                     2021-2022, QBayLogic B.V.   License     :  BSD2 (see the file LICENSE)-  Maintainer  :  Christiaan Baaij <christiaan.baaij@gmail.com>+  Maintainer  :  QBayLogic B.V. <devops@qbaylogic.com>    Clash is a functional hardware description language that borrows both its   syntax and semantics from the functional programming language Haskell. The@@ -59,7 +60,12 @@   , asyncRomPow2   , rom   , romPow2-    -- ** ROMs initialized with a data file+    -- ** ROMs defined by a 'MemBlob'+  , asyncRomBlob+  , asyncRomBlobPow2+  , romBlob+  , romBlobPow2+    -- ** ROMs defined by a data file   , asyncRomFile   , asyncRomFilePow2   , romFile@@ -73,11 +79,22 @@   , blockRamU   , blockRam1   , E.ResetStrategy(..)+    -- ** BlockRAM primitives initialized with a 'MemBlob'+  , blockRamBlob+  , blockRamBlobPow2+    -- *** Creating and inspecting 'MemBlob'+  , MemBlob+  , createMemBlob+  , memBlobTH+  , unpackMemBlob     -- ** BlockRAM primitives initialized with a data file   , blockRamFile   , blockRamFilePow2     -- ** BlockRAM read/write conflict resolution   , readNew+    -- ** True dual-port block RAM+  , trueDualPortBlockRam+  , RamOp(..)     -- * Utility functions   , window   , windowD@@ -101,8 +118,6 @@     -- ** Datatypes     -- *** Bit vectors   , module Clash.Sized.BitVector-  , module Clash.Prelude.BitIndex-  , module Clash.Prelude.BitReduction     -- *** Arbitrary-width numbers   , module Clash.Sized.Signed   , module Clash.Sized.Unsigned@@ -167,7 +182,7 @@  import           Clash.Annotations.TopEntity import           Clash.Class.AutoReg         (AutoReg, deriveAutoReg)-import           Clash.Class.BitPack hiding  (GBitPack(..))+import           Clash.Class.BitPack import           Clash.Class.Exp import           Clash.Class.Num import           Clash.Class.Parity@@ -176,10 +191,10 @@ import           Clash.Hidden import           Clash.Magic import           Clash.NamedTypes-import           Clash.Prelude.BitIndex-import           Clash.Prelude.BitReduction import           Clash.Prelude.BlockRam+import           Clash.Prelude.BlockRam.Blob import           Clash.Prelude.BlockRam.File+import           Clash.Prelude.ROM.Blob import           Clash.Prelude.ROM.File import           Clash.Prelude.Safe #ifdef CLASH_MULTIPLE_HIDDEN@@ -224,7 +239,7 @@ -- > window4 = window -- -- >>> simulateB @System window4 [1::Int,2,3,4,5] :: [Vec 4 Int]--- [<1,0,0,0>,<2,1,0,0>,<3,2,1,0>,<4,3,2,1>,<5,4,3,2>...+-- [1 :> 0 :> 0 :> 0 :> Nil,2 :> 1 :> 0 :> 0 :> Nil,3 :> 2 :> 1 :> 0 :> Nil,4 :> 3 :> 2 :> 1 :> Nil,5 :> 4 :> 3 :> 2 :> Nil,... -- ... window   :: ( HiddenClockResetEnable dom@@ -247,7 +262,7 @@ -- > windowD3 = windowD -- -- >>> simulateB @System windowD3 [1::Int,2,3,4] :: [Vec 3 Int]--- [<0,0,0>,<1,0,0>,<2,1,0>,<3,2,1>,<4,3,2>...+-- [0 :> 0 :> 0 :> Nil,1 :> 0 :> 0 :> Nil,2 :> 1 :> 0 :> Nil,3 :> 2 :> 1 :> Nil,4 :> 3 :> 2 :> Nil,... -- ... windowD   :: ( HiddenClockResetEnable dom
src/Clash/Prelude/BitIndex.hs view
@@ -1,148 +1,18 @@ {-| Copyright  :  (C) 2013-2016, University of Twente+                  2021,      QBayLogic B.V. License    :  BSD2 (see the file LICENSE)-Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>--}--{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE TypeFamilies #-}--{-# LANGUAGE Trustworthy #-}--{-# OPTIONS_HADDOCK show-extensions #-}--module Clash.Prelude.BitIndex where--import GHC.TypeLits                   (KnownNat, type (+), type (-))--import Clash.Class.BitPack            (BitPack (..))-import Clash.Promoted.Nat             (SNat (..))-import Clash.Sized.Internal.BitVector (BitVector, Bit, index#, lsb#, msb#,-                                       replaceBit#, setSlice#, slice#, split#)--{- $setup->>> :set -XDataKinds->>> import Clash.Prelude+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com> -} -{-# INLINE (!) #-}--- | Get the bit at the specified bit index.------ __NB:__ Bit indices are __DESCENDING__.------ >>> pack (7 :: Unsigned 6)--- 00_0111--- >>> (7 :: Unsigned 6) ! 1--- 1--- >>> (7 :: Unsigned 6) ! 5--- 0--- >>> (7 :: Unsigned 6) ! 6--- *** Exception: (!): 6 is out of range [5..0]--- ...-(!) :: (BitPack a, Enum i) => a -> i -> Bit-(!) v i = index# (pack v) (fromEnum i)--{-# INLINE slice #-}--- | Get a slice between bit index @m@ and and bit index @n@.------ __NB:__ Bit indices are __DESCENDING__.------ >>> pack (7 :: Unsigned 6)--- 00_0111--- >>> slice d4 d2 (7 :: Unsigned 6)--- 001--- >>> slice d6 d4 (7 :: Unsigned 6)--- <BLANKLINE>--- <interactive>:...---     • Couldn't match type ‘7 + i0’ with ‘6’---         arising from a use of ‘slice’---       The type variable ‘i0’ is ambiguous---     • In the expression: slice d6 d4 (7 :: Unsigned 6)---       In an equation for ‘it’: it = slice d6 d4 (7 :: Unsigned 6)-slice :: (BitPack a, BitSize a ~ ((m + 1) + i)) => SNat m -> SNat n -> a-      -> BitVector (m + 1 - n)-slice m n v = slice# (pack v) m n--{-# INLINE split #-}--- | Split a value of a bit size @m + n@ into a tuple of values with size @m@--- and size @n@.------ >>> pack (7 :: Unsigned 6)--- 00_0111--- >>> split (7 :: Unsigned 6) :: (BitVector 2, BitVector 4)--- (00,0111)-split :: (BitPack a, BitSize a ~ (m + n), KnownNat n) => a-      -> (BitVector m, BitVector n)-split v = split# (pack v)--{-# INLINE replaceBit #-}--- | Set the bit at the specified index------ __NB:__ Bit indices are __DESCENDING__.------ >>> pack (-5 :: Signed 6)--- 11_1011--- >>> replaceBit 4 0 (-5 :: Signed 6)--- -21--- >>> pack (-21 :: Signed 6)--- 10_1011--- >>> replaceBit 5 0 (-5 :: Signed 6)--- 27--- >>> pack (27 :: Signed 6)--- 01_1011--- >>> replaceBit 6 0 (-5 :: Signed 6)--- *** Exception: replaceBit: 6 is out of range [5..0]--- ...-replaceBit :: (BitPack a, Enum i) => i -> Bit -> a -> a-replaceBit i b v = unpack (replaceBit# (pack v) (fromEnum i) b)--{-# INLINE setSlice #-}--- | Set the bits between bit index @m@ and bit index @n@.------ __NB:__ Bit indices are __DESCENDING__.------ >>> pack (-5 :: Signed 6)--- 11_1011--- >>> setSlice d4 d3 0 (-5 :: Signed 6)--- -29--- >>> pack (-29 :: Signed 6)--- 10_0011--- >>> setSlice d6 d5 0 (-5 :: Signed 6)--- <BLANKLINE>--- <interactive>:...---     • Couldn't match type ‘7 + i0’ with ‘6’---         arising from a use of ‘setSlice’---       The type variable ‘i0’ is ambiguous---     • In the expression: setSlice d6 d5 0 (- 5 :: Signed 6)---       In an equation for ‘it’: it = setSlice d6 d5 0 (- 5 :: Signed 6)-setSlice :: (BitPack a, BitSize a ~ ((m + 1) + i)) => SNat m -> SNat n-         -> BitVector (m + 1 - n) -> a -> a-setSlice m n w v = unpack (setSlice# SNat (pack v) m n w)--{-# INLINE msb #-}--- | Get the most significant bit.------ >>> pack (-4 :: Signed 6)--- 11_1100--- >>> msb (-4 :: Signed 6)--- 1--- >>> pack (4 :: Signed 6)--- 00_0100--- >>> msb (4 :: Signed 6)--- 0-msb :: BitPack a => a -> Bit-msb v = msb# (pack v)+module Clash.Prelude.BitIndex {-# DEPRECATED "Use Clash.Class.BitPack instead. This module will be removed in Clash 1.8." #-}+  ( (!)+  , slice+  , split+  , replaceBit+  , setSlice+  , msb+  , lsb+  ) where -{-# INLINE lsb #-}--- | Get the least significant bit.------ >>> pack (-9 :: Signed 6)--- 11_0111--- >>> lsb (-9 :: Signed 6)--- 1--- >>> pack (-8 :: Signed 6)--- 11_1000--- >>> lsb (-8 :: Signed 6)--- 0-lsb :: BitPack a => a -> Bit-lsb v = lsb# (pack v)+import Clash.Class.BitPack.BitIndex
src/Clash/Prelude/BitReduction.hs view
@@ -1,82 +1,13 @@ {-| Copyright  :  (C) 2013-2016, University of Twente+                  2021,      QBayLogic B.V. License    :  BSD2 (see the file LICENSE)-Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>--}--{-# LANGUAGE FlexibleContexts #-}--{-# LANGUAGE Trustworthy #-}--{-# OPTIONS_HADDOCK show-extensions #-}--module Clash.Prelude.BitReduction where--import Clash.Class.BitPack            (BitPack (..))-import Clash.Sized.Internal.BitVector (Bit, reduceAnd#, reduceOr#, reduceXor#)--{- $setup->>> :set -XDataKinds->>> import Clash.Prelude+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com> -} -{-# INLINE reduceAnd #-}--- | Are all bits set to '1'?------ >>> pack (-2 :: Signed 6)--- 11_1110--- >>> reduceAnd (-2 :: Signed 6)--- 0--- >>> pack (-1 :: Signed 6)--- 11_1111--- >>> reduceAnd (-1 :: Signed 6)--- 1------ Zero width types will evaluate to '1':------ >>> reduceAnd (0 :: Unsigned 0)--- 1-reduceAnd :: BitPack a => a -> Bit-reduceAnd v = reduceAnd# (pack v)--{-# INLINE reduceOr #-}--- | Is there at least one bit set to '1'?------ >>> pack (5 :: Signed 6)--- 00_0101--- >>> reduceOr (5 :: Signed 6)--- 1--- >>> pack (0 :: Signed 6)--- 00_0000--- >>> reduceOr (0 :: Signed 6)--- 0------ Zero width types will evaluate to '0':------ >>> reduceOr (0 :: Unsigned 0)--- 0-reduceOr :: BitPack a => a -> Bit-reduceOr v = reduceOr# (pack v)+module Clash.Prelude.BitReduction {-# DEPRECATED "Use Clash.Class.BitPack instead. This module will be removed in Clash 1.8." #-}+  ( reduceAnd+  , reduceOr+  , reduceXor ) where -{-# INLINE reduceXor #-}--- | Is the number of bits set to '1' uneven?------ >>> pack (5 :: Signed 6)--- 00_0101--- >>> reduceXor (5 :: Signed 6)--- 0--- >>> pack (28 :: Signed 6)--- 01_1100--- >>> reduceXor (28 :: Signed 6)--- 1--- >>> pack (-5 :: Signed 6)--- 11_1011--- >>> reduceXor (-5 :: Signed 6)--- 1------ Zero width types will evaluate to '0':------ >>> reduceXor (0 :: Unsigned 0)--- 0-reduceXor :: BitPack a => a -> Bit-reduceXor v = reduceXor# (pack v)+import Clash.Class.BitPack.BitReduction
src/Clash/Prelude/BlockRam.hs view
@@ -239,7 +239,7 @@  @ >>> printX $ sampleN @System 32 (system2 prog)-[X,X,X,X,X,X,4,4,4,4,4,4,4,4,6,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2]+[undefined,undefined,undefined,undefined,undefined,undefined,4,4,4,4,4,4,4,4,6,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2]  @ @@ -368,7 +368,7 @@  @ >>> printX $ sampleN @System 34 (system3 prog2)-[X,0,0,0,0,0,0,4,4,4,4,4,4,4,4,6,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2]+[undefined,0,0,0,0,0,0,4,4,4,4,4,4,4,4,6,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2]  @ @@ -376,9 +376,11 @@  -} +{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE GADTs #-}+{-# LANGUAGE ScopedTypeVariables #-}  {-# LANGUAGE Safe #-} @@ -391,8 +393,12 @@   , blockRamU   , blockRam1   , E.ResetStrategy(..)-    -- * Read/Write conflict resolution+    -- ** Read/Write conflict resolution   , readNew+    -- * True dual-port block RAM+    -- $tdpbram+  , trueDualPortBlockRam+  , E.RamOp(..)   ) where @@ -409,10 +415,18 @@ import           Clash.Sized.Vector      (Vec) import           Clash.XException        (NFDataX) +{- $tdpbram+A true dual-port block RAM has two fully independent, fully functional access+ports: port A and port B. Either port can do both RAM reads and writes. These+two ports can even be on distinct clock domains, but the memory itself is shared+between the ports. This also makes a true dual-port block RAM suitable as a+component in a domain crossing circuit (but it needs additional logic for it to+be safe, see e.g. 'Clash.Explicit.Synchronizer.asyncFIFOSynchronizer').++A version with explicit clocks can be found in "Clash.Explicit.BlockRam".+-}+ {- $setup->>> :m -Clash.Explicit.Prelude->>> :m -Clash.Explicit.Prelude.Safe->>> :m -Clash.Prelude.Safe >>> import Clash.Prelude as C >>> import qualified Data.List as L >>> :set -XDataKinds -XRecordWildCards -XTupleSections -XTypeApplications -XFlexibleContexts@@ -691,6 +705,10 @@ -- * See "Clash.Prelude.BlockRam#usingrams" for more information on how to use a -- Block RAM. -- * Use the adapter 'readNew' for obtaining write-before-read semantics like this: @readNew (blockRam inits) rd wrM@.+-- * A large 'Vec' for the initial content might be too inefficient, depending+-- on how it is constructed. See 'Clash.Prelude.BlockRam.File.blockRamFile' and+-- 'Clash.Prelude.BlockRam.Blob.blockRamBlob' for different approaches that+-- scale well. blockRam   :: ( HasCallStack      , HiddenClock dom@@ -789,6 +807,10 @@ -- * See "Clash.Prelude.BlockRam#usingrams" for more information on how to use a -- Block RAM. -- * Use the adapter 'readNew' for obtaining write-before-read semantics like this: @readNew (blockRamPow2 inits) rd wrM@.+-- * A large 'Vec' for the initial content might be too inefficient, depending+-- on how it is constructed. See 'Clash.Prelude.BlockRam.File.blockRamFilePow2'+-- and 'Clash.Prelude.BlockRam.Blob.blockRamBlobPow2' for different approaches+-- that scale well. blockRamPow2   :: ( HasCallStack      , HiddenClock dom@@ -836,3 +858,45 @@   -- ^ Value of the @ram@ at address @r@ from the previous clock cycle readNew = hideClockResetEnable E.readNew {-# INLINE readNew #-}++-- | Produces vendor-agnostic HDL that will be inferred as a true dual-port+-- block RAM+--+-- Any value that is being written on a particular port is also the+-- value that will be read on that port, i.e. the same-port read/write behavior+-- 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+  , HiddenClock dom+  , NFDataX a+  )+  => Signal dom (E.RamOp nAddrs a)+  -- ^ RAM operation for port A+  -> Signal dom (E.RamOp nAddrs a)+  -- ^ RAM operation for port B+  -> (Signal dom a, Signal dom 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 hasClock inA inB+#endif
+ src/Clash/Prelude/BlockRam/Blob.hs view
@@ -0,0 +1,107 @@+{-|+Copyright  :  (C) 2022     , QBayLogic B.V.+License    :  BSD2 (see the file LICENSE)+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>++= Efficient bundling of initial RAM content with the compiled code++Leveraging Template Haskell, the initial content for the blockRAM components in+this module is stored alongside the compiled Haskell code. It covers use cases+where passing the initial content as a 'Clash.Sized.Vector.Vec' turns out to be+problematically slow.++The data is stored efficiently, with very little overhead (worst-case 7%, often+no overhead at all).++Unlike "Clash.Prelude.BlockRam.File", "Clash.Prelude.BlockRam.Blob" generates+practically the same HDL as "Clash.Prelude.BlockRam" and is compatible with all+tools consuming the generated HDL.+-}++{-# LANGUAGE Safe #-}++{-# OPTIONS_HADDOCK show-extensions #-}++module Clash.Prelude.BlockRam.Blob+  ( -- * BlockRAMs initialized with a 'E.MemBlob'+    blockRamBlob+  , blockRamBlobPow2+    -- * Creating and inspecting 'E.MemBlob'+  , E.MemBlob+  , E.createMemBlob+  , E.memBlobTH+  , E.unpackMemBlob+  )+where++import GHC.TypeLits (KnownNat, type (^))++import qualified Clash.Explicit.BlockRam.Blob as E+import Clash.Signal (hideClock, hideEnable, HiddenClock, HiddenEnable, Signal)+import Clash.Sized.BitVector (BitVector)+import Clash.Sized.Unsigned (Unsigned)++-- | Create a blockRAM with space for @n@ elements+--+-- * __NB__: Read value is delayed by 1 cycle+-- * __NB__: Initial output value is /undefined/, reading it will throw an+-- 'Clash.XException.XException'+--+--+-- Additional helpful information:+--+-- * See "Clash.Prelude.BlockRam#usingrams" for more information on how to use a+-- Block RAM.+-- * Use the adapter 'Clash.Prelude.BlockRam.readNew' for obtaining+-- write-before-read semantics like this: @'Clash.Prelude.BlockRam.readNew'+-- ('blockRamBlob' content) rd wrM@.+blockRamBlob+  :: forall dom addr m n+   . ( HiddenClock dom+     , HiddenEnable dom+     , Enum addr+     )+  => E.MemBlob n m+  -- ^ Initial content of the RAM, also determines the size, @n@, of the RAM+  --+  -- __NB__: __MUST__ be a constant+  -> Signal dom addr+  -- ^ Read address @r@+  -> Signal dom (Maybe (addr, BitVector m))+  -- ^ (write address @w@, value to write)+  -> Signal dom (BitVector m)+  -- ^ Value of the blockRAM at address @r@ from the previous clock cycle+blockRamBlob = hideEnable (hideClock E.blockRamBlob)+{-# INLINE blockRamBlob #-}++-- | Create a blockRAM with space for 2^@n@ elements+--+-- * __NB__: Read value is delayed by 1 cycle+-- * __NB__: Initial output value is /undefined/, reading it will throw an+-- 'Clash.XException.XException'+--+-- Additional helpful information:+--+-- * See "Clash.Prelude.BlockRam#usingrams" for more information on how to use a+-- Block RAM.+-- * Use the adapter 'Clash.Prelude.BlockRam.readNew' for obtaining+-- write-before-read semantics like this: @'Clash.Prelude.BlockRam.readNew'+-- ('blockRamBlobPow2' content) rd wrM@.+blockRamBlobPow2+  :: forall dom m n+   . ( HiddenClock dom+     , HiddenEnable dom+     , KnownNat n+     )+  => E.MemBlob (2^n) m+  -- ^ Initial content of the RAM, also determines the size, 2^@n@, of the RAM+  --+  -- __NB__: __MUST__ be a constant+  -> Signal dom (Unsigned n)+  -- ^ Read address @r@+  -> Signal dom (Maybe (Unsigned n, BitVector m))+  -- ^ (write address @w@, value to write)+  -> Signal dom (BitVector m)+  -- ^ Value of the blockRAM at address @r@ from the previous clock cycle+blockRamBlobPow2 = hideEnable (hideClock E.blockRamBlobPow2)+{-# INLINE blockRamBlobPow2 #-}
src/Clash/Prelude/BlockRam/File.hs view
@@ -1,8 +1,8 @@ {-| Copyright  :  (C) 2015-2016, University of Twente,-                  2019     , Myrtle Software Ltd+                  2019     , Myrtle Software Ltd,                   2017     , Google Inc.,-                  2022     , QBayLogic B.V.+                  2021     , QBayLogic B.V. License    :  BSD2 (see the file LICENSE) Maintainer :  QBayLogic B.V. <devops@qbaylogic.com> @@ -32,6 +32,12 @@ 000001101 @ +Such a file can be produced with 'E.memFile':++@+writeFile "memory.bin" (memFile Nothing [7 :: Unsigned 9 .. 13])+@+ We can instantiate a BlockRAM using the content of the above file like so:  @@@ -81,6 +87,8 @@   ( -- * BlockRAM synchronized to an arbitrary clock     blockRamFile   , blockRamFilePow2+    -- * Producing files+  , E.memFile   ) where @@ -117,7 +125,7 @@ -- -- * See "Clash.Prelude.BlockRam#usingrams" for more information on how to use a -- Block RAM.--- * Use the adapter 'Clash.Prelude.BlockRam.readNew' for obtaining write-before-read semantics like this: @'Clash.Prelude.BlockRam.readNew' clk ('blockRamFilePow2' clk file) rd wrM@.+-- * Use the adapter 'Clash.Prelude.BlockRam.readNew' for obtaining write-before-read semantics like this: @'Clash.Prelude.BlockRam.readNew' ('blockRamFilePow2' file) rd wrM@. -- * See "Clash.Prelude.BlockRam.File#usingramfiles" for more information on how -- to instantiate a Block RAM with the contents of a data file. -- * See "Clash.Sized.Fixed#creatingdatafiles" for ideas on how to create your@@ -164,7 +172,7 @@ -- -- * See "Clash.Prelude.BlockRam#usingrams" for more information on how to use a -- Block RAM.--- * Use the adapter 'Clash.Prelude.BlockRam.readNew' for obtaining write-before-read semantics like this: @'Clash.Prelude.BlockRam.readNew' clk ('blockRamFile' clk size file) rd wrM@.+-- * Use the adapter 'Clash.Prelude.BlockRam.readNew' for obtaining write-before-read semantics like this: @'Clash.Prelude.BlockRam.readNew' ('blockRamFile' size file) rd wrM@. -- * See "Clash.Prelude.BlockRam.File#usingramfiles" for more information on how -- to instantiate a Block RAM with the contents of a data file. -- * See "Clash.Sized.Fixed#creatingdatafiles" for ideas on how to create your
src/Clash/Prelude/DataFlow.hs view
@@ -1,9 +1,10 @@ {-| Copyright  :  (C) 2013-2016, University of Twente,                   2017     , Google Inc.-                  2019     , Myrtle Software Ltd+                  2019     , Myrtle Software Ltd,+                  2021     , QBayLogic B.V. License    :  BSD2 (see the file LICENSE)-Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>  Self-synchronizing circuits based on data-flow principles. -}@@ -48,12 +49,12 @@  import Clash.Class.BitPack    (boolToBV) import Clash.Class.Resize     (truncateB)-import Clash.Prelude.BitIndex (msb)+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, enable, register)+import Clash.Explicit.Signal  (Clock, Reset, Signal, Enable, andEnable, register) import Clash.Sized.BitVector  (BitVector) import Clash.Sized.Vector import Clash.XException       (errorX, NFDataX)@@ -161,7 +162,7 @@ mealyDF clk rst gen f iS =   DF (\i iV oR -> let en     = iV .&&. oR                       (s',o) = unbundle (f <$> s <*> i)-                      s      = register clk rst (enable gen en) iS s'+                      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@@ -179,7 +180,7 @@ mooreDF clk rst gen ft fo iS =   DF (\i iV oR -> let en  = iV .&&. oR                       s'  = ft <$> s <*> i-                      s   = register clk rst (enable gen en) iS s'+                      s   = register clk rst (andEnable gen en) iS s'                       o   = fo <$> s                   in  (o,iV,oR)) 
src/Clash/Prelude/Mealy.hs view
@@ -30,9 +30,6 @@  {- $setup >>> :set -XDataKinds -XTypeApplications->>> :m -Clash.Explicit.Prelude->>> :m -Clash.Explicit.Prelude.Safe->>> :m -Clash.Prelude.Safe >>> import Clash.Prelude >>> :{ let macT s (x,y) = (s',s)
src/Clash/Prelude/RAM.hs view
@@ -31,6 +31,7 @@ import           Clash.Promoted.Nat   (SNat) import           Clash.Signal import           Clash.Sized.Unsigned (Unsigned)+import           Clash.XException     (NFDataX)   -- | Create a RAM with space for @n@ elements.@@ -47,6 +48,7 @@      , HiddenClock dom      , HiddenEnable dom      , HasCallStack+     , NFDataX a      )   => SNat n   -- ^ Size @n@ of the RAM@@ -73,7 +75,9 @@   :: ( KnownNat n      , HiddenClock dom      , HiddenEnable dom-     , HasCallStack )+     , HasCallStack+     , NFDataX a+     )   => Signal dom (Unsigned n)   -- ^ Read address @r@   -> Signal dom (Maybe (Unsigned n, a))
src/Clash/Prelude/ROM.hs view
@@ -12,7 +12,7 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE RankNTypes #-} -{-# LANGUAGE Safe #-}+{-# LANGUAGE Trustworthy #-}  {-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-} {-# OPTIONS_HADDOCK show-extensions #-}@@ -29,16 +29,19 @@   ) where -import           Data.Array           ((!),listArray)+import           Data.Array           (listArray)+import           Data.Array.Base      (unsafeAt)+import           GHC.Stack            (withFrozenCallStack) import           GHC.TypeLits         (KnownNat, type (^)) import           Prelude              hiding (length) +import           Clash.Annotations.Primitive (hasBlackBox) import qualified Clash.Explicit.ROM   as E import           Clash.Signal import           Clash.Sized.Unsigned (Unsigned) import           Clash.Sized.Vector   (Vec, length, toList) -import           Clash.XException     (NFDataX)+import           Clash.XException     (NFDataX, errorX)  -- | An asynchronous/combinational ROM with space for @n@ elements --@@ -46,6 +49,10 @@ -- -- * See "Clash.Sized.Fixed#creatingdatafiles" and "Clash.Prelude.BlockRam#usingrams" -- for ideas on how to use ROMs and RAMs+-- * A large 'Vec' for the content might be too inefficient, depending on how it+-- is constructed. See 'Clash.Prelude.ROM.File.asyncRomFile' and+-- 'Clash.Prelude.ROM.Blob.asyncRomBlob' for different approaches that scale+-- well. asyncRom   :: (KnownNat n, Enum addr)   => Vec n a@@ -65,6 +72,10 @@ -- -- * See "Clash.Sized.Fixed#creatingdatafiles" and "Clash.Prelude.BlockRam#usingrams" -- for ideas on how to use ROMs and RAMs+-- * A large 'Vec' for the content might be too inefficient, depending on how it+-- is constructed. See 'Clash.Prelude.ROM.File.asyncRomFilePow2' and+-- 'Clash.Prelude.ROM.Blob.asyncRomBlobPow2' for different approaches that scale+-- well. asyncRomPow2   :: KnownNat n   => Vec (2^n) a@@ -80,7 +91,7 @@  -- | asyncROM primitive asyncRom#-  :: KnownNat n+  :: forall n a . KnownNat n   => Vec n a   -- ^ ROM content, also determines the size, @n@, of the ROM   --@@ -89,21 +100,35 @@   -- ^ Read address @rd@   -> a   -- ^ The value of the ROM at address @rd@-asyncRom# content = \rd -> arr ! rd+asyncRom# content = safeAt   where     szI = length content     arr = listArray (0,szI-1) (toList content)++    safeAt :: Int -> a+    safeAt i =+      if (0 <= i) && (i < szI) then+        unsafeAt arr i+      else+        withFrozenCallStack+          (errorX ("asyncRom: address " ++ show i +++                  " not in range [0.." ++ show szI ++ ")")) {-# NOINLINE asyncRom# #-}+{-# ANN asyncRom# hasBlackBox #-}  -- | A ROM with a synchronous read port, with space for @n@ elements -- -- * __NB__: Read value is delayed by 1 cycle--- * __NB__: Initial output value is 'undefined'+-- * __NB__: Initial output value is /undefined/, reading it will throw an+-- 'Clash.XException.XException' -- -- Additional helpful information: -- -- * See "Clash.Sized.Fixed#creatingdatafiles" and "Clash.Prelude.BlockRam#usingrams" -- for ideas on how to use ROMs and RAMs+-- * A large 'Vec' for the content might be too inefficient, depending on how it+-- is constructed. See 'Clash.Prelude.ROM.File.romFile' and+-- 'Clash.Prelude.ROM.Blob.romBlob' for different approaches that scale well. rom   :: forall dom n m a    . ( NFDataX a@@ -132,6 +157,10 @@ -- -- * See "Clash.Sized.Fixed#creatingdatafiles" and "Clash.Prelude.BlockRam#usingrams" -- for ideas on how to use ROMs and RAMs+-- * A large 'Vec' for the content might be too inefficient, depending on how it+-- is constructed. See 'Clash.Prelude.ROM.File.romFilePow2' and+-- 'Clash.Prelude.ROM.Blob.romBlobPow2' for different approaches that scale+-- well. romPow2   :: forall dom n a    . ( KnownNat n
+ src/Clash/Prelude/ROM/Blob.hs view
@@ -0,0 +1,175 @@+{-|+Copyright  :  (C) 2022     , QBayLogic B.V.+License    :  BSD2 (see the file LICENSE)+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>++= Efficient bundling of ROM content with the compiled code++Leveraging Template Haskell, the content for the ROM components in this module+is stored alongside the compiled Haskell code. It covers use cases where passing+the initial content as a 'Clash.Sized.Vector.Vec' turns out to be+problematically slow.++The data is stored efficiently, with very little overhead (worst-case 7%, often+no overhead at all).++Unlike "Clash.Prelude.ROM.File", "Clash.Prelude.ROM.Blob" generates practically+the same HDL as "Clash.Prelude.ROM" and is compatible with all tools consuming+the generated HDL.+-}++{-# LANGUAGE Trustworthy #-}++{-# OPTIONS_HADDOCK show-extensions #-}++module Clash.Prelude.ROM.Blob+  ( -- * Asynchronous ROM defined by a 'MemBlob'+    asyncRomBlob+  , asyncRomBlobPow2+    -- * Synchronous 'MemBlob' ROM synchronized to an arbitrary clock+  , romBlob+  , romBlobPow2+    -- * Creating and inspecting 'MemBlob'+  , MemBlob+  , createMemBlob+  , memBlobTH+  , unpackMemBlob+    -- * Internal+  , asyncRomBlob#+  )+where++import Data.Array (listArray)+import Data.Array.Base (unsafeAt)+import GHC.Stack (withFrozenCallStack)+import GHC.TypeLits (KnownNat, type (^))++import Clash.Annotations.Primitive (hasBlackBox)+import qualified Clash.Explicit.ROM.Blob as E+import Clash.Explicit.BlockRam.Blob (createMemBlob, memBlobTH)+import Clash.Explicit.BlockRam.Internal (MemBlob(..), unpackMemBlob)+import Clash.Promoted.Nat (natToNum)+import Clash.Signal (hideClock, hideEnable, HiddenClock, HiddenEnable)+import Clash.Signal.Internal (Signal)+import Clash.Sized.Internal.BitVector (BitVector)+import Clash.Sized.Internal.Unsigned (Unsigned)+import Clash.XException (deepErrorX)++-- | An asynchronous/combinational ROM with space for @n@ elements+--+-- Additional helpful information:+--+-- * See "Clash.Sized.Fixed#creatingdatafiles" and+-- "Clash.Prelude.BlockRam#usingrams" for ideas on how to use ROMs and RAMs.+asyncRomBlob+  :: Enum addr+  => MemBlob n m+  -- ^ ROM content, also determines the size, @n@, of the ROM+  --+  -- __NB__: __MUST__ be a constant+  -> addr+  -- ^ Read address @r@+  -> BitVector m+  -- ^ The value of the ROM at address @r@+asyncRomBlob = \content rd -> asyncRomBlob# content (fromEnum rd)+{-# INLINE asyncRomBlob #-}++-- | An asynchronous/combinational ROM with space for 2^@n@ elements+--+-- Additional helpful information:+--+-- * See "Clash.Sized.Fixed#creatingdatafiles" and+-- "Clash.Prelude.BlockRam#usingrams" for ideas on how to use ROMs and RAMs.+asyncRomBlobPow2+  :: KnownNat n+  => MemBlob (2^n) m+  -- ^ ROM content, also determines the size, 2^@n@, of the ROM+  --+  -- __NB__: __MUST__ be a constant+  -> Unsigned n+  -- ^ Read address @r@+  -> BitVector m+  -- ^ The value of the ROM at address @r@+asyncRomBlobPow2 = asyncRomBlob+{-# INLINE asyncRomBlobPow2 #-}++-- | asyncROM primitive+asyncRomBlob#+  :: forall m n+   . MemBlob n m+  -- ^ ROM content, also determines the size, @n@, of the ROM+  --+  -- __NB__: __MUST__ be a constant+  -> Int+  -- ^ Read address @r@+  -> BitVector m+  -- ^ The value of the ROM at address @r@+asyncRomBlob# content@MemBlob{} = safeAt+  where+    szI = natToNum @n @Int+    arr = listArray (0,szI-1) $ unpackMemBlob content++    safeAt :: Int -> BitVector m+    safeAt i =+      if (0 <= i) && (i < szI) then+        unsafeAt arr i+      else+        withFrozenCallStack+          (deepErrorX ("asyncRom: address " ++ show i +++                       " not in range [0.." ++ show szI ++ ")"))+{-# ANN asyncRomBlob# hasBlackBox #-}+{-# NOINLINE asyncRomBlob# #-}++-- | A ROM with a synchronous read port, with space for @n@ elements+--+-- * __NB__: Read value is delayed by 1 cycle+-- * __NB__: Initial output value is /undefined/, reading it will throw an+-- 'Clash.XException.XException'+--+-- Additional helpful information:+--+-- * See "Clash.Sized.Fixed#creatingdatafiles" and+-- "Clash.Explicit.BlockRam#usingrams" for ideas on how to use ROMs and RAMs.+romBlob+  :: forall dom addr m n+   . ( HiddenClock dom+     , HiddenEnable dom+     , Enum addr+     )+  => MemBlob n m+  -- ^ ROM content, also determines the size, @n@, of the ROM+  --+  -- __NB__: __MUST__ be a constant+  -> Signal dom addr+  -- ^ Read address @r@+  -> Signal dom (BitVector m)+  -- ^ The value of the ROM at address @r@ from the previous clock cycle+romBlob = hideEnable (hideClock E.romBlob)+{-# INLINE romBlob #-}++-- | A ROM with a synchronous read port, with space for 2^@n@ elements+--+-- * __NB__: Read value is delayed by 1 cycle+-- * __NB__: Initial output value is /undefined/, reading it will throw an+-- 'Clash.XException.XException'+--+-- Additional helpful information:+--+-- * See "Clash.Sized.Fixed#creatingdatafiles" and+-- "Clash.Explicit.BlockRam#usingrams" for ideas on how to use ROMs and RAMs.+romBlobPow2+  :: forall dom m n+   . ( HiddenClock dom+     , HiddenEnable dom+     , KnownNat n+     )+  => MemBlob (2^n) m+  -- ^ ROM content, also determines the size, 2^@n@, of the ROM+  --+  -- __NB__: __MUST__ be a constant+  -> Signal dom (Unsigned n)+  -- ^ Read address @r@+  -> Signal dom (BitVector m)+  -- ^ The value of the ROM at address @r@ from the previous clock cycle+romBlobPow2 = hideEnable (hideClock E.romBlobPow2)+{-# INLINE romBlobPow2 #-}
src/Clash/Prelude/ROM/File.hs view
@@ -1,8 +1,8 @@ {-| Copyright  :  (C) 2015-2016, University of Twente,-                  2017     , Google Inc.+                  2017     , Google Inc.,                   2019     , Myrtle Software Ltd,-                  2022     , QBayLogic B.V.+                  2021-2022, QBayLogic B.V. License    :  BSD2 (see the file LICENSE) Maintainer :  QBayLogic B.V. <devops@qbaylogic.com> @@ -31,6 +31,12 @@ 000001101 @ +Such a file can be produced with 'memFile':++@+writeFile "memory.bin" (memFile Nothing [7 :: Unsigned 9 .. 13])+@+ We can instantiate a synchronous ROM using the content of the above file like so: @@ -81,6 +87,8 @@     -- * Synchronous ROM synchronized to an arbitrary clock   , romFile   , romFilePow2+    -- * Producing files+  , memFile     -- * Internal   , asyncRomFile#   )@@ -90,7 +98,8 @@ import           GHC.TypeLits                 (KnownNat) import           System.IO.Unsafe             (unsafePerformIO) -import           Clash.Explicit.BlockRam.File (initMem)+import           Clash.Annotations.Primitive (hasBlackBox)+import           Clash.Explicit.BlockRam.File (initMem, memFile) import qualified Clash.Explicit.ROM.File      as E import           Clash.Promoted.Nat           (SNat (..), pow2SNat, snatToNum) import           Clash.Signal@@ -245,6 +254,7 @@     content = listArray (0,szI-1) mem     szI     = snatToNum sz {-# NOINLINE asyncRomFile# #-}+{-# ANN asyncRomFile# hasBlackBox #-}  -- | A ROM with a synchronous read port, with space for @n@ elements --
src/Clash/Prelude/Safe.hs view
@@ -1,9 +1,10 @@ {-|   Copyright   :  (C) 2013-2016, University of Twente,                      2017-2019, Myrtle Software Ltd-                     2017     , Google Inc.+                     2017     , Google Inc.,+                     2021-2022, QBayLogic B.V.   License     :  BSD2 (see the file LICENSE)-  Maintainer  :  Christiaan Baaij <christiaan.baaij@gmail.com>+  Maintainer  :  QBayLogic B.V. <devops@qbaylogic.com>    __This is the <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/exts/safe_haskell.html Safe> API only of "Clash.Prelude"__ @@ -49,14 +50,30 @@   , asyncRomPow2   , rom   , romPow2+    -- ** ROMs defined by a 'MemBlob'+  , asyncRomBlob+  , asyncRomBlobPow2+  , romBlob+  , romBlobPow2     -- * RAM primitives with a combinational read port   , asyncRam   , asyncRamPow2     -- * BlockRAM primitives   , blockRam   , blockRamPow2+    -- ** BlockRAM primitives initialized with a 'MemBlob'+  , blockRamBlob+  , blockRamBlobPow2+    -- *** Creating and inspecting 'MemBlob'+  , MemBlob+  , createMemBlob+  , memBlobTH+  , unpackMemBlob     -- ** BlockRAM read/write conflict resolution   , readNew+    -- ** True dual-port block RAM+  , trueDualPortBlockRam+  , RamOp(..)     -- * Utility functions   , isRising   , isFalling@@ -69,8 +86,6 @@     -- ** Datatypes     -- *** Bit vectors   , module Clash.Sized.BitVector-  , module Clash.Prelude.BitIndex-  , module Clash.Prelude.BitReduction     -- *** Arbitrary-width numbers   , module Clash.Sized.Signed   , module Clash.Sized.Unsigned@@ -128,14 +143,14 @@ import           Clash.Class.Resize import           Clash.Hidden import           Clash.NamedTypes-import           Clash.Prelude.BitIndex-import           Clash.Prelude.BitReduction import           Clash.Prelude.BlockRam+import           Clash.Prelude.BlockRam.Blob import qualified Clash.Explicit.Prelude.Safe as E import           Clash.Prelude.Mealy         (mealy, mealyB, (<^>)) import           Clash.Prelude.Moore         (moore, mooreB) import           Clash.Prelude.RAM           (asyncRam,asyncRamPow2) import           Clash.Prelude.ROM           (asyncRom,asyncRomPow2,rom,romPow2)+import           Clash.Prelude.ROM.Blob import           Clash.Promoted.Nat import           Clash.Promoted.Nat.TH import           Clash.Promoted.Nat.Literals@@ -153,6 +168,7 @@  {- $setup >>> :set -XFlexibleContexts -XTypeApplications+>>> :m -Prelude >>> :m -Clash.Explicit.Prelude >>> import Clash.Prelude.Safe >>> let rP = registerB (8,8)
src/Clash/Prelude/Synchronizer.hs view
@@ -66,7 +66,8 @@ asyncFIFOSynchronizer   :: ( HiddenClockResetEnable rdom      , HiddenClockResetEnable wdom-     , 2 <= addrSize )+     , 2 <= addrSize+     , NFDataX a )   => SNat addrSize   -- ^ Size of the internally used addresses, the  FIFO contains @2^addrSize@   -- elements.
src/Clash/Prelude/Testbench.hs view
@@ -1,9 +1,10 @@ {-| Copyright  :  (C) 2013-2016, University of Twente,                   2017     , Google Inc.-                  2019     , Myrtle Software Ltd+                  2019     , Myrtle Software Ltd,+                  2021     , QBayLogic B.V. License    :  BSD2 (see the file LICENSE)-Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com> -}  {-# LANGUAGE FlexibleContexts #-}@@ -28,7 +29,7 @@   ) where -import GHC.TypeLits                       (KnownNat)+import GHC.TypeLits                       (KnownNat, type (<=))  import qualified Clash.Explicit.Testbench as E import           Clash.Signal@@ -55,7 +56,13 @@ -- function simply returns the third 'Signal' unaltered as its result. This -- function is used by 'outputVerifier''. --+-- === Usage in @clashi@ #assert-clashi# --+-- __NB__: When simulating a component that uses 'assert' in @clashi@, usually,+-- the warnings are only logged the first time the component is simulated.+-- Issuing @:reload@ in @clashi@ will discard the cached result of the+-- computation, and warnings will once again be emitted.+-- -- __NB__: This function /can/ be used in synthesizable designs. assert   :: (Eq a, ShowX a, HiddenClock dom , HiddenReset dom )@@ -72,7 +79,7 @@   hideReset (hideClock E.assert) msg actual expected ret {-# INLINE assert #-} --- | The same as 'assert', but can handle don't care bits in it's expected value.+-- | The same as 'assert', but can handle don't care bits in its expected value. assertBitVector   :: (KnownNat n, HiddenClock dom , HiddenReset dom )   => String@@ -112,8 +119,14 @@ stimuliGenerator = hideReset (hideClock E.stimuliGenerator) {-# INLINE stimuliGenerator #-} --- |+-- | Compare a signal (coming from a circuit) to a vector of samples. If a+-- sample from the signal is not equal to the corresponding sample in the+-- vector, print to stderr and continue testing. This function is+-- synthesizable in the sense that HDL simulators will run it. --+-- __NB__: This function uses 'assert'. When simulating this function in+-- @clashi@, read the [note](#assert-clashi).+-- -- Example: -- -- @@@ -148,13 +161,15 @@ -- expected value: 10, not equal to actual value: 9 -- ,False,True] ----- If your working with 'BitVector's containing don't care bits you should use 'outputVerifierBitVector''.+-- If you're working with 'BitVector's containing don't care bits you should use 'outputVerifierBitVector''. outputVerifier'   :: ( KnownNat l      , Eq a      , ShowX a      , HiddenClock dom-     , HiddenReset dom  )+     , HiddenReset dom+     , 1 <= l+     )   => Vec l a   -- ^ Samples to compare with   -> Signal dom a@@ -166,12 +181,14 @@   -- | Same as 'outputVerifier'',--- but can handle don't care bits in it's expected values.+-- but can handle don't care bits in its expected values. outputVerifierBitVector'   :: ( KnownNat l      , KnownNat n      , HiddenClock dom-     , HiddenReset dom  )+     , HiddenReset dom+     , 1 <= l+     )   => Vec l (BitVector n)   -- ^ Samples to compare with   -> Signal dom (BitVector n)
src/Clash/Promoted/Nat.hs view
@@ -1,8 +1,9 @@ {-| Copyright  :  (C) 2013-2016, University of Twente,                   2016     , Myrtle Software Ltd+                  2022     , QBayLogic B.V. License    :  BSD2 (see the file LICENSE)-Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com> -}  {-# LANGUAGE AllowAmbiguousTypes #-}@@ -82,6 +83,8 @@ #endif import Numeric.Natural    (Natural) import Unsafe.Coerce      (unsafeCoerce)++import Clash.Annotations.Primitive (hasBlackBox) import Clash.XException   (ShowX (..), showsPrecXWith)  {- $setup@@ -265,6 +268,7 @@ powSNat :: SNat a -> SNat b -> SNat (a^b) powSNat SNat SNat = SNat {-# NOINLINE powSNat #-}+{-# ANN powSNat hasBlackBox #-} infixr 8 `powSNat`  -- | Division of two singleton natural numbers@@ -292,6 +296,7 @@              -> SNat (FLog base x) flogBaseSNat SNat SNat = SNat {-# NOINLINE flogBaseSNat #-}+{-# ANN flogBaseSNat hasBlackBox #-}  -- | Ceiling of the logarithm of a natural number clogBaseSNat :: (2 <= base, 1 <= x)@@ -300,6 +305,7 @@              -> SNat (CLog base x) clogBaseSNat SNat SNat = SNat {-# NOINLINE clogBaseSNat #-}+{-# ANN clogBaseSNat hasBlackBox #-}  -- | Exact integer logarithm of a natural number --@@ -310,6 +316,7 @@             -> SNat (Log base x) logBaseSNat SNat SNat = SNat {-# NOINLINE logBaseSNat #-}+{-# ANN logBaseSNat hasBlackBox #-}  -- | Power of two of a singleton natural number pow2SNat :: SNat a -> SNat (2^a)
src/Clash/Promoted/Nat/TH.hs view
@@ -23,6 +23,8 @@  {- $setup >>> :set -XDataKinds+>>> :m -Prelude+>>> import Clash.Prelude >>> let d1111 = SNat :: SNat 1111 >>> let d1200 = SNat :: SNat 1200 >>> let d1201 = SNat :: SNat 1201
src/Clash/Promoted/Nat/Unsafe.hs view
@@ -1,7 +1,8 @@ {-| Copyright  :  (C) 2015-2016, University of Twente+                  2022     , QBayLogic B.V. License    :  BSD2 (see the file LICENSE)-Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com> -}  {-# LANGUAGE Unsafe #-}@@ -13,9 +14,11 @@ import Data.Reflection    (reifyNat) import Unsafe.Coerce      (unsafeCoerce) +import Clash.Annotations.Primitive (hasBlackBox) import Clash.Promoted.Nat (SNat, snatProxy)  -- | I hope you know what you're doing unsafeSNat :: Integer -> SNat k unsafeSNat i = reifyNat i $ (\p -> unsafeCoerce (snatProxy p)) {-# NOINLINE unsafeSNat #-}+{-# ANN unsafeSNat hasBlackBox #-}
src/Clash/Promoted/Symbol.hs view
@@ -1,14 +1,16 @@ {-| Copyright  :  (C) 2013-2016, University of Twente+                  2022     , QBayLogic 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 #-} {-# LANGUAGE TemplateHaskellQuotes #-} -{-# LANGUAGE Safe #-}+-- Annotations are not allowed in safe Haskell+-- {-# LANGUAGE Safe #-}  {-# OPTIONS_HADDOCK show-extensions #-} @@ -20,9 +22,13 @@ import GHC.Show     (appPrec) import GHC.TypeLits (KnownSymbol, Symbol, symbolVal) +import Clash.Annotations.Primitive (hasBlackBox)+ -- | Singleton value for a type-level string @s@ data SSymbol (s :: Symbol) where   SSymbol :: KnownSymbol s => SSymbol s++{-# ANN SSymbol hasBlackBox #-}  instance KnownSymbol s => Lift (SSymbol (s :: Symbol)) where --  lift :: t -> Q Exp
src/Clash/Signal.hs view
@@ -77,10 +77,6 @@  {-# LANGUAGE Trustworthy #-} -#if __GLASGOW_HASKELL__ < 806-{-# LANGUAGE TypeInType #-}-#endif- {-# OPTIONS_HADDOCK show-extensions #-}  module Clash.Signal@@ -157,6 +153,9 @@     -- * Hidden clock, reset, and enable arguments     -- $hiddenclockandreset +    -- ** Monomorphism restriction leads to surprising behavior+    -- $monomorphism+     -- ** Hidden clock   , HiddenClock   , hideClock@@ -198,6 +197,10 @@ #endif   , SystemClockResetEnable     -- * Basic circuit functions+  , andEnable+#ifdef CLASH_MULTIPLE_HIDDEN+  , andSpecificEnable+#endif   , dflipflop   , delay   , delayMaybe@@ -224,6 +227,7 @@   , simulateN   , simulateWithReset   , simulateWithResetN+  , runUntil     -- ** lazy versions   , simulate_lazy   , simulateB_lazy@@ -287,12 +291,11 @@    signalAutomaton) import           Clash.Signal.Internal.Ambiguous   (knownVDomain, clockPeriod, activeEdge, resetKind, initBehavior, resetPolarity)-import           Clash.XException      (NFDataX)+import           Clash.XException      (NFDataX, ShowX)  {- $setup >>> :set -XFlexibleContexts -XTypeApplications->>> :m -Clash.Explicit.Prelude->>> :m -Clash.Explicit.Prelude.Safe+>>> :m -Prelude >>> import Clash.Prelude >>> import Clash.Promoted.Nat (SNat(..)) >>> import Clash.XException (printX)@@ -413,7 +416,7 @@   -> Signal System (BitVector 8) topEntity clk rst key1 =     let  (pllOut,pllStable) = 'Clash.Intel.ClockGen.altpll' (SSymbol \@\"altpll50\") clk rst-         rstSync            = 'resetSynchronizer' pllOut (unsafeToHighPolarity pllStable) enableGen+         rstSync            = 'resetSynchronizer' pllOut (unsafeToHighPolarity pllStable)     in   'exposeClockResetEnable' leds pllOut rstSync enableGen   where     key1R  = isRising 1 key1@@ -430,13 +433,116 @@   -> Signal System (BitVector 8) topEntity clk rst key1 =     let  (pllOut,pllStable) = 'Clash.Intel.ClockGen.altpll' (SSymbol \@\"altpll50\") clk rst-         rstSync            = 'resetSynchronizer' pllOut (unsafeToHighPolarity pllStable) enableGen+         rstSync            = 'resetSynchronizer' pllOut (unsafeToHighPolarity pllStable)     in   'withClockResetEnable' pllOut rstSync enableGen leds   where     key1R  = isRising 1 key1     leds   = mealy blinkerT (1, False, 0) key1R @+-} +{- $monomorphism #monomorphism#++If you don't provide a type signature for a function, Haskell will infer one for+you. Sometimes this inferred type is less general than you would expect. This+can be due to the monomorphism restriction, which is a rather intricate+technical aspect of Haskell's type system. You don't need to understand it to+avoid the problems it creates with hidden parameters, though.++The @expose...@ and @with...@ functions for hidden clocks, resets, and enables+are intended to be used to resolve a function with hidden parameters into a+function without that hidden parameter. Put differently, 'exposeClock' and+'withClock' are not themselves used in a 'HiddenClock' context, and so on for+resets and enables. If the rule that they are not themselves in a @Hidden...@+context is observed, they will function as expected. No specific consideration+is needed in these cases.++However, the function 'andEnable' is explicitly designed to be used within a+'HiddenEnable' context. In such a situation, it is important to provide a type+signature for the component that is given to `andEnable` as an argument, and not+let Haskell infer one.++The use of 'andEnable' has an unfortunate interaction with Haskells monomorphism+restriction that can lead to very surprising behavior. All of the following also+applies to using 'exposeClock' and 'withClock' inside a 'HiddenClock' context,+and so on for resets and enables.++When you write a function++@+f :: HiddenClockResetEnable dom+  => Signal dom Bool+  -> Signal dom Int+  -> Signal dom Int+f en i = andEnable en g i -- BROKEN+ where+  g = register 0+@++you would intuitively think this has the following type for the local function @g@:++@+f :: forall dom+   . HiddenClockResetEnable dom+  => Signal dom Bool+  -> Signal dom Int+  -> Signal dom Int+f en i = andEnable en g i+ where+  g :: HiddenClockResetEnable dom => Signal dom Int -> Signal dom Int+  g = register 0+@++but instead, the monomorphism restriction will cause the following type to be inferred:++@+f :: forall dom+   . HiddenClockResetEnable dom+  => Signal dom Bool+  -> Signal dom Int+  -> Signal dom Int+f en i = andEnable en g i -- BROKEN+ where+  g :: Signal dom Int -> Signal dom Int+  g = register 0+@++The monomorphism restriction essentially misqualifies the implicit parameter as+polymorphism, and tries to remove the implicit parameter from the context of the+function's type. It /can/ do that because the outer scope already has a+'HiddenEnable' context. But by getting that implicit parameter of the enclosing+function as context, it also gets the value of the parameter of the enclosing+function. So the Enable line for @g@ is the Enable line of @f@, and the Enable+line produced by 'andEnable' that was intended to be connected to @g@ is not+connected to anything!++When using 'andEnable', you should always explicitly provide the type signature+for the component given to 'andEnable' as an argument, thereby avoiding+surprising inferred types. We don't advise you to turn off the monomorphism+restriction, as this may have undesirable consequences.++Note that the inferred type is not always incorrect. The following variant works+correctly:++@+f :: HiddenClockResetEnable dom+  => Signal dom Bool+  -> Signal dom Int+  -> Signal dom Int+f en i = andEnable en g i+ where+  g i = register 0 i+@++This is an instance of the very first example on+<https://wiki.haskell.org/Monomorphism_restriction HaskellWiki>, @f1@ (as+opposed to @f4@). The monomorphism restriction works differently for function+bindings and pattern bindings. Since @g@ here has a formal parameter, it is a+function binding, and the monomorphish restriction does not kick in. The code+works as expected. If a later code change removes the formal parameter, all of a+sudden the code silently disregards the @en@ signal! Adhering to the rule that+you should always explicitly provide the type signature for the component given+to 'andEnable' as an argument would have avoided this hard to debug problem. -}  #ifdef CLASH_MULTIPLE_HIDDEN@@ -490,6 +596,7 @@   , Hidden (HiddenEnableName System) (Enable System)   ) + {- | Expose a hidden 'Clock' argument of a component, so it can be applied explicitly. @@ -1136,6 +1243,122 @@ hasEnable = fromLabel @(HiddenEnableName dom) {-# INLINE hasEnable #-} +{- | Merge enable signal with signal of bools by applying the boolean AND+operation.++__NB: The component given to 'andEnable' 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.++#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__+Usage with a /polymorphic/ domain:++>>> reg = register 5 (reg + 1)+>>> f en = andEnable en reg+>>> sampleN @System 10 (f (riseEvery d2))+[5,5,5,6,6,7,7,8,8,9]++Force 'andEnable' to work on 'System' (hence 'sampleN' not needing an explicit+domain later):++>>> reg = register 5 (reg + 1)+>>> f en = andEnable @System en reg+>>> sampleN 10 (f (riseEvery d2))+[5,5,5,6,6,7,7,8,8,9]+-}+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 #-}++{- | 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>++#ifdef CLASH_MULTIPLE_HIDDEN+=== __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+ where+  andSpecificEnable0+    :: Enable dom+    -> Signal dom Bool+    -> (HiddenEnable dom => r)+    -> r+  andSpecificEnable0 gen en f =+    let en0 = E.andEnable gen en+    in withSpecificEnable @dom en0 f+{-# INLINE andSpecificEnable #-}+ {- | Expose hidden 'Clock', 'Reset', and 'Enable' arguments of a component, so they can be applied explicitly. @@ -1887,6 +2110,88 @@ dup1 :: [a] -> [a] dup1 (x:xs) = x:x:xs dup1 _      = error "empty list"+++-- | Simulate a component until it matches a condition+--+-- If the given component has not yet been given a clock, reset, or enable+-- line, 'runUntil' will supply them. The reset will be asserted for a single+-- cycle.+--+-- It prints a message of the form+--+-- @+-- Signal sampled for N cycles until value X+-- @+--+-- __NB__: This function is not synthesizable+--+-- === __Example with test bench__+--+-- A common usage is with a test bench using+-- 'Clash.Explicit.Testbench.outputVerifier'.+--+-- __NB__: Since this uses 'Clash.Explicit.Testbench.assert', when using+-- @clashi@, read the note at "Clash.Explicit.Testbench#assert-clashi".+--+-- @+-- import Clash.Prelude+-- import Clash.Explicit.Testbench+--+-- topEntity+--   :: 'Signal' 'System' Int+--   -> 'Signal' 'System' Int+-- topEntity = id+--+-- testBench+--   :: 'Signal' 'System' Bool+-- testBench = done+--  where+--   testInput = 'Clash.Explicit.Testbench.stimuliGenerator' clk rst $('Clash.Sized.Vector.listToVecTH' [1 :: Int .. 10])+--   expectedOutput =+--     'Clash.Explicit.Testbench.outputVerifier'' clk rst $('Clash.Sized.Vector.listToVecTH' $ [1 :: Int .. 9] '<>' [42])+--   done = expectedOutput $ topEntity testInput+--   clk = 'Clash.Explicit.Testbench.tbSystemClockGen' (not \<$\> done)+--   rst = 'systemResetGen'+-- @+--+-- @+-- > runUntil id testBench+--+--+-- cycle(\<Clock: System\>): 10, outputVerifier+-- expected value: 42, not equal to actual value: 10+-- Signal sampled for 11 cycles until value True+-- @+--+-- When you need to verify multiple test benches, the following invocations come+-- in handy:+--+-- @+-- > 'mapM_' (runUntil id) [ testBenchA, testBenchB ]+-- @+--+-- or when the test benches are in different clock domains:+--+-- @+-- testBenchA :: Signal DomA Bool+-- testBenchB :: Signal DomB Bool+-- @+--+-- @+-- > 'sequence_' [ runUntil id testBenchA, runUntil id testBenchB ]+-- @+runUntil+  :: forall dom a+   . (KnownDomain dom, NFDataX a, ShowX a)+  => (a -> Bool)+  -- ^ Condition checking function, should return @True@ to finish run+  -> (HiddenClockResetEnable dom => Signal dom a)+  -- ^ 'Signal' we want to sample for the condition, potentially having a+  -- hidden clock, reset and/or enable+  -> IO ()+runUntil check s =+  E.runUntil check $ exposeClockResetEnable @dom s clockGen resetGen enableGen  -- * QuickCheck combinators 
src/Clash/Signal/BiSignal.hs view
@@ -1,8 +1,9 @@ {-| Copyright  :  (C) 2017, Google Inc.                   2019, Myrtle Software Ltd+                  2022, QBayLogic B.V. License    :  BSD2 (see the file LICENSE)-Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>  Wires are fundamentally bidirectional, and in traditional HDLs we can exploit this aspect by explicitly marking the endpoint, or port, of such a wire as@@ -99,10 +100,6 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} -#if __GLASGOW_HASKELL__ < 806-{-# LANGUAGE TypeInType #-}-#endif- {-# OPTIONS_GHC -fplugin=GHC.TypeLits.Extra.Solver #-} {-# OPTIONS_GHC -fplugin=GHC.TypeLits.Normalise #-} {-# OPTIONS_GHC -fplugin=GHC.TypeLits.KnownNat.Solver #-}@@ -123,6 +120,7 @@ import           Data.List                  (intercalate) import           Data.Maybe                 (fromMaybe,isJust) +import           Clash.Annotations.Primitive (hasBlackBox) import           Clash.Class.HasDomain import           Clash.Class.BitPack        (BitPack (..)) import           Clash.Sized.BitVector      (BitVector)@@ -179,7 +177,7 @@ type role BiSignalIn nominal nominal nominal  -- | The /in/ part of an __inout__ port.--- BiSignalIn has the <https://downloads.haskell.org/ghc/latest/docs/html/users_guide/glasgow_exts.html#roles type role>+-- BiSignalIn has the <https://downloads.haskell.org/ghc/latest/docs/html/users_guide/exts/roles.html type role> -- -- >>> :i BiSignalIn -- type role BiSignalIn nominal nominal nominal@@ -197,7 +195,7 @@ -- Wraps (multiple) writing signals. The semantics are such that only one of -- the signals may write at a single time step. ----- BiSignalOut has the <https://downloads.haskell.org/ghc/latest/docs/html/users_guide/glasgow_exts.html#roles type role>+-- BiSignalOut has the <https://downloads.haskell.org/ghc/latest/docs/html/users_guide/exts/roles.html type role> -- -- >>> :i BiSignalOut -- type role BiSignalOut nominal nominal nominal@@ -248,6 +246,7 @@     SPullDown  -> fromMaybe minBound <$> s     SPullUp    -> fromMaybe maxBound <$> s {-# NOINLINE readFromBiSignal# #-}+{-# ANN readFromBiSignal# hasBlackBox #-}  -- | Read the value from an __inout__ port readFromBiSignal@@ -267,6 +266,7 @@   -> BiSignalOut defaultState dom m mergeBiSignalOuts = mconcat . V.toList {-# NOINLINE mergeBiSignalOuts #-}+{-# ANN mergeBiSignalOuts hasBlackBox #-}  writeToBiSignal#   :: HasCallStack@@ -278,6 +278,7 @@ -- writeToBiSignal# = writeToBiSignal# writeToBiSignal# _ maybeSignal _ _ = BiSignalOut [maybeSignal] {-# NOINLINE writeToBiSignal# #-}+{-# ANN writeToBiSignal# hasBlackBox #-}  -- | Write to an __inout__ port writeToBiSignal@@ -324,3 +325,4 @@     -- Recursive step     biSignalOut' = veryUnsafeToBiSignalIn $ BiSignalOut $ map tail# signals {-# NOINLINE veryUnsafeToBiSignalIn #-}+{-# ANN veryUnsafeToBiSignalIn hasBlackBox #-}
src/Clash/Signal/Bundle.hs view
@@ -1,22 +1,17 @@ {-| Copyright  :  (C) 2013-2016, University of Twente,                   2017-2019, Myrtle Software Ltd, Google Inc.-                       2019, QBayLogic B.V.+                  2019,2022, QBayLogic B.V. License    :  BSD2 (see the file LICENSE)-Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>  The Product/Signal isomorphism -}  {-# LANGUAGE CPP #-} {-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeFamilyDependencies #-} -#if __GLASGOW_HASKELL__ < 806-{-# LANGUAGE TypeInType #-}-#endif- {-# LANGUAGE Trustworthy #-}  --{-# OPTIONS_GHC -ddump-splices #-}@@ -37,6 +32,7 @@ import GHC.TypeLits                 (KnownNat) import Prelude                      hiding (head, map, tail) +import Clash.Annotations.Primitive (hasBlackBox) import Clash.Signal.Bundle.Internal (deriveBundleTuples) import Clash.Signal.Internal        (Signal (..), Domain) import Clash.Sized.BitVector        (Bit, BitVector)@@ -160,6 +156,7 @@   unbundle = sequenceA . fmap lazyV  {-# NOINLINE vecBundle# #-}+{-# ANN vecBundle# hasBlackBox #-} vecBundle# :: Vec n (Signal t a) -> Signal t (Vec n a) vecBundle# = traverse# id 
src/Clash/Signal/Delayed.hs view
@@ -2,6 +2,7 @@ Copyright  :  (C) 2013-2016, University of Twente,                   2017     , Google Inc.                   2019     , Myrtle Software Ltd+                  2021     , LUMI GUIDE FIETSDETECTIE B.V. License    :  BSD2 (see the file LICENSE) Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com> -}@@ -11,10 +12,6 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} -#if __GLASGOW_HASKELL__ < 806-{-# LANGUAGE TypeInType #-}-#endif- {-# LANGUAGE Safe #-}  {-# OPTIONS_GHC -fplugin GHC.TypeLits.Normalise #-}@@ -38,6 +35,7 @@     -- * Experimental   , unsafeFromSignal   , antiDelay+  , forward   ) where @@ -46,7 +44,7 @@  import Clash.Signal.Delayed.Internal   (DSignal(..), dfromList, dfromList_lazy, fromSignal, toSignal,-   unsafeFromSignal, antiDelay, feedback)+   unsafeFromSignal, antiDelay, feedback, forward) import qualified Clash.Explicit.Signal.Delayed as E import           Clash.Sized.Vector import           Clash.Signal
src/Clash/Signal/Delayed/Bundle.hs view
@@ -9,12 +9,7 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE PolyKinds #-}-{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeFamilyDependencies #-}--#if __GLASGOW_HASKELL__ < 806-{-# LANGUAGE TypeInType #-}-#endif  module Clash.Signal.Delayed.Bundle (     Bundle(..)
src/Clash/Signal/Delayed/Internal.hs view
@@ -2,6 +2,7 @@   Copyright   :  (C) 2019     , Myrtle Software Ltd.                      2018     , @blaxill                      2018-2019, QBayLogic B.V.+                     2021     , LUMI GUIDE FIETSDETECTIE B.V.   License     :  BSD2 (see the file LICENSE)   Maintainer  :  Christiaan Baaij <christiaan.baaij@gmail.com> -}@@ -12,10 +13,6 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TypeFamilies #-} -#if __GLASGOW_HASKELL__ < 806-{-# LANGUAGE TypeInType #-}-#endif- {-# LANGUAGE Trustworthy #-}  {-# OPTIONS_GHC -fplugin GHC.TypeLits.Normalise #-}@@ -33,6 +30,7 @@     -- * Experimental   , unsafeFromSignal   , antiDelay+  , forward   ) where @@ -49,10 +47,8 @@ {- $setup >>> :set -XDataKinds >>> :set -XTypeOperators->>> :m -Clash.Prelude->>> :m -Clash.Prelude.Safe->>> :m -Clash.Signal >>> import Clash.Explicit.Prelude+>>> import qualified Clash.Signal.Delayed.Bundle as DB >>> :{ let mac       :: forall dom@@ -74,12 +70,28 @@                        in  (acc, delayedI clk rst en 0 acc') :} +>>> :{+let numbers+      :: forall dom+       . KnownDomain dom+      => Clock dom+      -> Reset dom+      -> Enable dom+      -> DSignal dom 5 (Int, Int)+    numbers clk rst en = DB.bundle (forward d1 s1, s2)+      where+        s1 :: DSignal dom 4 Int+        s1 = delayed clk rst en (100 :> 10 :> 5 :> 1 :> Nil) (pure 200)+        s2 :: DSignal dom 5 Int+        s2 = fmap (2*) $ delayN d1 0 en clk s1+:}+ -}  -- | A synchronized signal with samples of type @a@, synchronized to clock -- @clk@, that has accumulated @delay@ amount of samples delay along its path. ----- DSignal has the <https://downloads.haskell.org/ghc/latest/docs/html/users_guide/glasgow_exts.html#roles type role>+-- DSignal has the <https://downloads.haskell.org/ghc/latest/docs/html/users_guide/exts/roles.html type role> -- -- >>> :i DSignal -- type role DSignal nominal nominal representational@@ -164,7 +176,8 @@  -- | __EXPERIMENTAL__ ----- Access a /delayed/ signal in the present.+-- Access a /delayed/ signal from the future in the present. Often required+-- When writing a circuit that requires feedback from itself. -- -- @ -- mac@@ -182,3 +195,38 @@ -- @ antiDelay :: SNat d -> DSignal dom (n + d) a -> DSignal dom n a antiDelay _ = coerce++-- | __EXPERIMENTAL__+--+-- Access a /delayed/ signal from the past in the present. In contrast with+-- 'Clash.Explicit.Signal.Delayed.delayed' and friends forward does not insert+-- any logic. This means using this function violates the delay invariant of+-- 'DSignal'. This is sometimes useful when combining unrelated delayed signals+-- where inserting logic is not wanted or when abstracting over internal+-- delayed signals where the internal delay information should not be leaked.+--+-- For example, the circuit below returns a sequence of numbers as a pair+-- but the internal delay information between the elements of the pair+-- should not leak into the type.+--+-- @+-- numbers+--   :: forall dom+--    . KnownDomain dom+--   => Clock dom+--   -> Reset dom+--   -> Enable dom+--   -> 'DSignal' dom 5 (Int, Int)+-- numbers clk rst en = DB.bundle (forward d1 s1, s2)+--   where+--     s1 :: 'DSignal' dom 4 Int+--     s1 = 'Clash.Explicit.Signal.Delayed.delayed' clk rst en (100 :> 10 :> 5 :> 1 :> Nil) (pure 200)+--     s2 :: 'DSignal' dom 5 Int+--     s2 = fmap (2*) $ 'Clash.Explicit.Signal.Delayed.delayN' d1 0 en clk s1+-- @+--+-- >>> sampleN 8 (toSignal (numbers systemClockGen systemResetGen enableGen))+-- [(1,0),(1,2),(5,2),(10,10),(100,20),(200,200),(200,400),(200,400)]++forward :: SNat d -> DSignal dom n a -> DSignal dom (n + d) a+forward _ = coerce
src/Clash/Signal/Internal.hs view
@@ -2,7 +2,7 @@ Copyright  :  (C) 2013-2016, University of Twente,                   2017-2019, Myrtle Software Ltd                   2017     , Google Inc.,-                  2021     , QBayLogic B.V.+                  2021-2022, QBayLogic B.V. License    :  BSD2 (see the file LICENSE) Maintainer :  QBayLogic B.V. <devops@qbaylogic.com> -}@@ -18,10 +18,6 @@ {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} -#if __GLASGOW_HASKELL__ < 806-{-# LANGUAGE TypeInType #-}-#endif- {-# LANGUAGE Unsafe #-}  {-# OPTIONS_GHC -fplugin=GHC.TypeLits.Extra.Solver #-}@@ -180,8 +176,7 @@ >>> :set -XDataKinds >>> :set -XMagicHash >>> :set -XTypeApplications->>> :m -Clash.Prelude->>> :m -Clash.Signal+>>> import Clash.Prelude (SSymbol(..)) >>> import Clash.Signal.Internal >>> import Clash.Promoted.Nat >>> import Clash.XException@@ -507,7 +502,7 @@   , vResetPolarity :: ResetPolarity   -- ^ Corresponds to '_resetPolarity' on 'DomainConfiguration'   }-  deriving (Eq, Show, Read)+  deriving (Eq, Generic, NFData, Show, Read)  -- | Convert 'SDomainConfiguration' to 'VDomainConfiguration'. Should be used in combination with -- 'createDomain' only.@@ -680,7 +675,7 @@ * __NB__: Whether 'System' has good defaults depends on your target platform. Check out 'IntelSystem' and 'XilinxSystem' too! -Signals have the <https://downloads.haskell.org/ghc/latest/docs/html/users_guide/glasgow_exts.html#roles type role>+Signals have the <https://downloads.haskell.org/ghc/latest/docs/html/users_guide/exts/roles.html type role>  >>> :i Signal type role Signal nominal representational
src/Clash/Signal/Trace.hs view
@@ -1,8 +1,9 @@ {-| Copyright  :  (C) 2018, Google Inc.                   2019, Myrtle Software Ltd+                  2022, QBayLogic B.V. License    :  BSD2 (see the file LICENSE)-Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>  Utilities for tracing signals and dumping them in various ways. Example usage: @@ -87,6 +88,7 @@   ) where  -- Clash:+import           Clash.Annotations.Primitive (hasBlackBox) import           Clash.Signal.Internal (fromList) import           Clash.Signal   (KnownDomain(..), SDomainConfiguration(..), Signal, bundle, unbundle)@@ -232,6 +234,7 @@       unsafePerformIO $         traceSignal# traceMap# (snatToNum period) traceName signal {-# NOINLINE traceSignal #-}+{-# ANN traceSignal hasBlackBox #-}  -- | Trace a single signal. Will emit an error if a signal with the same name -- was previously registered.@@ -252,6 +255,7 @@ traceSignal1 traceName signal =   unsafePerformIO (traceSignal# traceMap# 1 traceName signal) {-# NOINLINE traceSignal1 #-}+{-# ANN traceSignal1 hasBlackBox #-}  -- | 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@@ -278,6 +282,7 @@       unsafePerformIO $         traceVecSignal# traceMap# (snatToNum period) traceName signal {-# NOINLINE traceVecSignal #-}+{-# ANN traceVecSignal hasBlackBox #-}  -- | 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@@ -300,6 +305,7 @@ traceVecSignal1 traceName signal =   unsafePerformIO $ traceVecSignal# traceMap# 1 traceName signal {-# NOINLINE traceVecSignal1 #-}+{-# ANN traceVecSignal1 hasBlackBox #-}  iso8601Format :: UTCTime -> String iso8601Format = formatTime defaultTimeLocale "%Y-%m-%dT%H:%M:%S"
src/Clash/Sized/Fixed.hs view
@@ -1,7 +1,8 @@ {-|-Copyright  :  (C) 2013-2016, University of Twente+Copyright  :  (C) 2013-2016, University of Twente,+                  2021,      QBayLogic B.V., License    :  BSD2 (see the file LICENSE)-Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>  Fixed point numbers @@ -142,8 +143,8 @@                                    boundedMul) import Clash.Class.Resize         (Resize (..)) import Clash.Promoted.Nat         (SNat, natToNum, natToInteger)-import Clash.Prelude.BitIndex     (lsb, msb, split)-import Clash.Prelude.BitReduction (reduceAnd, reduceOr)+import Clash.Class.BitPack.BitIndex (lsb, msb, split)+import Clash.Class.BitPack.BitReduction (reduceAnd, reduceOr) import Clash.Sized.BitVector      (BitVector, (++#)) import Clash.Sized.Signed         (Signed) import Clash.Sized.Unsigned       (Unsigned)@@ -170,7 +171,7 @@ -- The 'Num' operators for this type saturate to 'maxBound' on overflow and -- 'minBound' on underflow, and use truncation as the rounding method. ----- Fixed has the <https://downloads.haskell.org/ghc/latest/docs/html/users_guide/glasgow_exts.html#roles type role>+-- Fixed has the <https://downloads.haskell.org/ghc/latest/docs/html/users_guide/exts/roles.html type role> -- -- >>> :i Fixed -- type role Fixed representational nominal nominal@@ -733,14 +734,14 @@  -- | Convert, at run-time, a 'Double' to a 'Fixed'-point. ----- __NB__: this functions is /not/ synthesizable+-- __NB__: this function is /not/ synthesizable -- -- = Creating data-files #creatingdatafiles# ----- An example usage of this function is for example to convert a data file--- containing 'Double's to a data file with ASCI-encoded binary numbers to be--- used by a synthesizable function like 'Clash.Prelude.ROM.File.asyncRomFile'.--- For example, given a file @Data.txt@ containing:+-- An example usage of this function is to convert a data file containing+-- 'Double's to a data file with ASCII-encoded binary numbers to be used by a+-- synthesizable function like 'Clash.Prelude.ROM.File.asyncRomFile'. For+-- example, consider a file @Data.txt@ containing: -- -- @ -- 1.2 2.0 3.0 4.0@@ -757,12 +758,13 @@ -- module Main where -- -- import Clash.Prelude+-- import Clash.Prelude.ROM.File -- import System.Environment -- import qualified Data.List as L -- -- createRomFile---   :: KnownNat n---   => (Double -> BitVector n)+--   :: BitPack a+--   => (Double -> a) --   -> FilePath --   -> FilePath --   -> IO ()@@ -770,8 +772,8 @@ --   f <- readFile fileR --   let ds :: [Double] --       ds = L.concat . (L.map . L.map) read . L.map words $ lines f---       bvs = L.map (filter (/= '_') . show . convert) ds---   writeFile fileW (unlines bvs)+--       fes = L.map convert ds+--   writeFile fileW ('Clash.Prelude.ROM.File.memFile' Nothing fes) -- -- toSFixed8_8 :: Double -> SFixed 8 8 -- toSFixed8_8 = 'fLitR'@@ -779,7 +781,7 @@ -- main :: IO () -- main = do --   [fileR,fileW] <- getArgs---   createRomFile ('pack' . toSFixed8_8) fileR fileW+--   createRomFile toSFixed8_8 fileR fileW -- @ -- -- We then compile this to an executable:@@ -789,7 +791,7 @@ -- @ -- -- We can then use this utility to convert our @Data.txt@ file which contains--- 'Double's to a @Data.bin@ file which will containing the desired ASCI-encoded+-- 'Double's to a @Data.bin@ file which will containing the desired ASCII-encoded -- binary data: -- -- @@@ -830,30 +832,31 @@ -- -- For those of us who like to live on the edge, another option is to convert -- our @Data.txt@ at compile-time using--- <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#template-haskell Template Haskell>.+-- <https://downloads.haskell.org/ghc/latest/docs/html/users_guide/exts/template_haskell.html Template Haskell>. -- For this we first create a module @CreateRomFileTH.hs@: -- -- @ -- module CreateRomFileTH (romDataFromFile) where -- -- import Clash.Prelude--- import qualified Data.List        as L--- import Language.Haskell.TH        (ExpQ, litE, stringL)+-- import Clash.Prelude.ROM.File+-- import qualified Data.List as L+-- import Language.Haskell.TH (ExpQ, litE, stringL) -- import Language.Haskell.TH.Syntax (qRunIO) ----- createRomFile :: KnownNat n => (Double -> BitVector n)+-- createRomFile :: BitPack a => (Double -> a) --               -> FilePath -> FilePath -> IO () -- createRomFile convert fileR fileW = do --   f <- readFile fileR --   let ds :: [Double] --       ds = L.concat . (L.map . L.map) read . L.map words $ lines f---       bvs = L.map (filter (/= '_') . show . convert) ds---   writeFile fileW (unlines bvs)+--       fes = L.map convert ds+--   writeFile fileW ('Clash.Prelude.ROM.File.memFile' Nothing fes) ----- romDataFromFile :: KnownNat n => (Double -> BitVector n) -> String -> ExpQ+-- romDataFromFile :: BitPack a => (Double -> a) -> String -> ExpQ -- romDataFromFile convert fileR = do --   let fileW = fileR L.++ ".bin"---   bvF <- qRunIO (createRomFile convert fileR fileW)+--   qRunIO (createRomFile convert fileR fileW) --   litE (stringL fileW) -- @ --@@ -865,13 +868,10 @@ -- import Clash.Prelude -- import CreateRomFileTH ----- toSFixed8_8 :: Double -> SFixed 8 8--- toSFixed8_8 = 'fLitR'--- -- romF' :: Unsigned 3 -> Unsigned 3 -> SFixed 8 8 -- romF' rowAddr colAddr = unpack $ --   asyncRomFile d8---                $(romDataFromFile (pack . toSFixed8_8) "Data.txt") -- Template Haskell splice+--                $(romDataFromFile (fLitR :: Double -> SFixed 8 8) "Data.txt") -- Template Haskell splice --                ((rowAddr * 4) + colAddr) -- @ --@@ -1121,6 +1121,21 @@                      0 -> unpack (resize (shiftR rR sh))                      _ -> 0 +  satMul SatError (Fixed a) (Fixed b) =+    let res     = a `mul` b+        sh      = natToNum @frac+        (rL,rR) = split res :: (BitVector int, BitVector (int + frac + frac))+    in  case isSigned a of+          True  -> let overflow = complement (reduceOr (pack (msb rR) ++# pack rL)) .|.+                                  reduceAnd (pack (msb rR) ++# pack rL)+                   in  case overflow of+                         1 -> unpack (resize (shiftR rR sh))+                         _ -> errorX "Fixed.satMul: result exceeds bounds"++          False -> case rL of+                     0 -> unpack (resize (shiftR rR sh))+                     _ -> errorX "Fixed.satMul: result exceeds maxBound"+   satMul SatSymmetric (Fixed a) (Fixed b) =     let res     = a `mul` b         sh      = natToNum @frac@@ -1143,6 +1158,7 @@          0 -> case satMode of                 SatWrap -> f                 SatZero -> 0+                SatError -> errorX "Fixed.satSucc: result exceeds maxBound"                 _       -> maxBound          _ -> if isSigned fRep               then satSub satMode f $ Fixed $ fromInteger $ (-1) `shiftL` sh@@ -1159,6 +1175,7 @@                 SatWrap      -> f                 SatBound     -> minBound                 SatZero      -> 0+                SatError     -> errorX "Fixed.satPred: result exceeds minBound"                 SatSymmetric -> symBound          _ -> if isSigned fRep               then satAdd satMode f $ Fixed $ fromInteger $ (-1) `shiftL` sh
src/Clash/Sized/Internal/BitVector.hs view
@@ -1,15 +1,17 @@ {-| Copyright  :  (C) 2013-2016, University of Twente,                   2019     , Gergő Érdi-                  2016-2019, Myrtle Software Ltd+                  2016-2019, Myrtle Software Ltd,+                  2021-2022, QBayLogic 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 DeriveAnyClass #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE MultiWayIf #-} {-# LANGUAGE RoleAnnotations #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-}@@ -36,6 +38,8 @@   , ge##   , gt##   , le##+    -- *** Enum+  , toEnum##     -- *** Num   , fromInteger##     -- *** Bits@@ -72,12 +76,15 @@     -- **** Eq   , eq#   , neq#-  , isLike+  , isLike#     -- *** Ord   , lt#   , ge#   , gt#   , le#+    -- *** Enum+  , toEnum#+  , fromEnum#     -- *** Enum (not synthesizable)   , enumFrom#   , enumFromThen#@@ -149,9 +156,7 @@ import GHC.Natural   (Natural (..), naturalFromInteger, wordToNatural) #endif-#if MIN_VERSION_base(4,12,0) import GHC.Natural                (naturalToInteger)-#endif import GHC.Prim                   (dataToTag#) import GHC.Stack                  (withFrozenCallStack) import GHC.TypeLits               (KnownNat, Nat, type (+), type (-))@@ -161,20 +166,24 @@ import GHC.TypeLits               (natVal) #endif import GHC.TypeLits.Extra         (Max)-import Language.Haskell.TH        (Lit (..), Pat, Q, appT, conT, litE, litP, litT, mkName, numTyLit, sigE, tupE, tupP, varP)+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        (Code, Quote, Type)+import Language.Haskell.TH        (Quote) #else-import Language.Haskell.TH        (TExp, TypeQ)+import Language.Haskell.TH        (TypeQ) #endif import Test.QuickCheck.Arbitrary  (Arbitrary (..), CoArbitrary (..),                                    arbitraryBoundedIntegral,                                    coarbitraryIntegral, shrinkIntegral) +import Clash.Annotations.Primitive (hasBlackBox) import Clash.Class.Num            (ExtendingNum (..), SaturatingNum (..),                                    SaturationMode (..)) import Clash.Class.Resize         (Resize (..))@@ -208,7 +217,7 @@ -- * Bit indices are descending -- * 'Num' instance performs /unsigned/ arithmetic. ----- BitVector has the <https://downloads.haskell.org/ghc/latest/docs/html/users_guide/glasgow_exts.html#roles type role>+-- BitVector has the <https://downloads.haskell.org/ghc/latest/docs/html/users_guide/exts/roles.html type role> -- -- >>> :i BitVector -- type role BitVector nominal@@ -224,6 +233,8 @@        }   deriving (Data, Generic) +{-# ANN BV hasBlackBox #-}+ -- * Bit  -- | Bit@@ -235,14 +246,18 @@       }   deriving (Data, Generic) +{-# ANN Bit hasBlackBox #-}+ -- * Constructions -- ** Initialisation {-# NOINLINE high #-}+{-# ANN high hasBlackBox #-} -- | logic '1' high :: Bit high = Bit 0 1  {-# NOINLINE low #-}+{-# ANN low hasBlackBox #-} -- | logic '0' low :: Bit low = Bit 0 0@@ -281,10 +296,12 @@ eq## :: Bit -> Bit -> Bool eq## b1 b2 = eq# (pack# b1) (pack# b2) {-# NOINLINE eq## #-}+{-# ANN eq## hasBlackBox #-}  neq## :: Bit -> Bit -> Bool neq## b1 b2 = neq# (pack# b1) (pack# b2) {-# NOINLINE neq## #-}+{-# ANN neq## hasBlackBox #-}  instance Ord Bit where   (<)  = lt##@@ -295,17 +312,26 @@ lt##,ge##,gt##,le## :: Bit -> Bit -> Bool lt## b1 b2 = lt# (pack# b1) (pack# b2) {-# NOINLINE lt## #-}+{-# ANN lt## hasBlackBox #-} ge## b1 b2 = ge# (pack# b1) (pack# b2) {-# NOINLINE ge## #-}+{-# ANN ge## hasBlackBox #-} gt## b1 b2 = gt# (pack# b1) (pack# b2) {-# NOINLINE gt## #-}+{-# ANN gt## hasBlackBox #-} le## b1 b2 = le# (pack# b1) (pack# b2) {-# NOINLINE le## #-}+{-# ANN le## hasBlackBox #-}  instance Enum Bit where-  toEnum     = fromInteger## 0## . toInteger+  toEnum     = toEnum##   fromEnum b = if eq## b low then 0 else 1 +toEnum## :: Int -> Bit+toEnum## = fromInteger## 0## . toInteger+{-# NOINLINE toEnum## #-}+{-# ANN toEnum## hasBlackBox #-}+ instance Bounded Bit where   minBound = low   maxBound = high@@ -325,6 +351,7 @@ fromInteger## :: Word# -> Integer -> Bit fromInteger## m# i = Bit ((W# m#) `mod` 2) (fromInteger i `mod` 2) {-# NOINLINE fromInteger## #-}+{-# ANN fromInteger## hasBlackBox #-}  instance Real Bit where   toRational b = if eq## b low then 0 else 1@@ -369,19 +396,23 @@ and## (Bit m1 v1) (Bit m2 v2) = Bit mask (v1 .&. v2 .&. complement mask)   where mask = (m1.&.v2 .|. m1.&.m2 .|. m2.&.v1) {-# NOINLINE 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 {-# NOINLINE or## #-}+{-# ANN or## hasBlackBox #-}  xor## (Bit m1 v1) (Bit m2 v2) = Bit mask ((v1 `xor` v2) .&. complement mask)   where mask = m1 .|. m2 {-# NOINLINE 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##)) {-# NOINLINE complement## #-}+{-# ANN complement## hasBlackBox #-}  -- *** BitPack pack# :: Bit -> BitVector 1@@ -391,6 +422,7 @@ pack# (Bit (W# m) (W# b)) = BV (NatS# m) (NatS# b) #endif {-# NOINLINE pack# #-}+{-# ANN pack# hasBlackBox #-}  unpack# :: BitVector 1 -> Bit unpack# (BV m b) = Bit (go m) (go b)@@ -403,6 +435,7 @@   go (NatJ# w) = W# (bigNatToWord w) #endif {-# NOINLINE unpack# #-}+{-# ANN unpack# hasBlackBox #-}  -- * Instances instance NFData (BitVector n) where@@ -412,19 +445,28 @@   -- coercion  instance KnownNat n => Show (BitVector n) where-  show bv@(BV msk i) = reverse . underScore . reverse $ showBV (natVal bv) msk i []-    where-      showBV 0 _ _ s = s-      showBV n m v s = let (v',vBit) = divMod v 2-                           (m',mBit) = divMod m 2-                       in  case (mBit,vBit) of-                           (0,0) -> showBV (n - 1) m' v' ('0':s)-                           (0,_) -> showBV (n - 1) m' v' ('1':s)-                           _     -> showBV (n - 1) m' v' ('.':s)+  show (BV m i) =+    case natToNum @n @Int of+      0 -> "0"+      _ -> '0' : 'b' : go groupSize (natToNum @n @Int) m i []+   where+    go _ 0 _ _ s = s+    go c n m0 v0 s =+      let+        (!v1, !vBit) = quotRem v0 2+        (!m1, !mBit) = quotRem m0 2+        !renderedBit = showBit mBit vBit+      in+        case c of+          0 -> go (groupSize - 1) (n - 1) m1 v1 (renderedBit : '_' : s)+          _ -> go (c - 1)         (n - 1) m1 v1 (renderedBit :       s) -      underScore xs = case splitAt 5 xs of-                        ([a,b,c,d,e],rest) -> [a,b,c,d,'_'] ++ underScore (e:rest)-                        (rest,_)               -> rest+    showBit 0 0 = '0'+    showBit 0 1 = '1'+    showBit _ _ = '.'++    groupSize :: Int+    groupSize = 4   {-# NOINLINE show #-}  instance KnownNat n => ShowX (BitVector n) where@@ -437,47 +479,43 @@  -- | Create a binary literal ----- >>> $$(bLit "1001") :: BitVector 4--- 1001--- >>> $$(bLit "1001") :: BitVector 3--- 001+-- >>> $(bLit "1001")+-- 0b1001 -- -- __NB__: You can also just write: -- -- >>> 0b1001 :: BitVector 4--- 1001+-- 0b1001 -- -- The advantage of 'bLit' is that you can use computations to create the -- string literal: -- -- >>> import qualified Data.List as List--- >>> $$(bLit (List.replicate 4 '1')) :: BitVector 4--- 1111+-- >>> $(bLit (List.replicate 4 '1'))+-- 0b1111 -- -- Also 'bLit' can handle don't care bits: ----- >>> $$(bLit "1.0.") :: BitVector 4--- 1.0.-#if MIN_VERSION_template_haskell(2,17,0)-bLit :: forall n. KnownNat n => String -> Code Q (BitVector n)-#else-bLit :: forall n. KnownNat n => String -> Q (TExp (BitVector n))-#endif-bLit s = [|| fromInteger# m i1 ||]-  where-    bv :: BitVector n-    bv = read# s--    m,i :: Natural-    BV m i = bv+-- >>> $(bLit "1.0.")+-- 0b1.0.+--+-- __N.B.__: From Clash 1.6 an onwards 'bLit' will deduce the size of the+--           BitVector from the given string and annotate the splice it+--           produces accordingly.+bLit :: String -> ExpQ+bLit s = pure (SigE body typ)+ where+  typ = ConT ''BitVector `AppT` LitT (NumTyLit (toInteger n))+  body = VarE 'fromInteger# `AppE` iLit mask `AppE` iLit value -    i1 :: Integer-    i1 = toInteger i+  iLit = LitE . IntegerL . toInteger+  (n, BV mask value) = read# s :: (Natural, BitVector n) -read# :: KnownNat n => String -> BitVector n-read# cs = BV m v+read# :: String -> (Natural, BitVector n)+read# cs0 = (fromIntegral (length cs1), BV m v)   where-    (vs,ms) = unzip . map readBit . filter (/= '_') $ cs+    cs1 = filter (/= '_') cs0+    (vs, ms) = unzip (map readBit cs1)     combineBits = foldl (\b a -> b*2+a) 0     v = combineBits vs     m = combineBits ms@@ -485,7 +523,9 @@       '0' -> (0,0)       '1' -> (1,0)       '.' -> (0,1)-      _   -> error $ "Clash.Sized.Internal.bLit: unknown character: " ++ show c ++ " in input: " ++ cs+      _   -> error $+           "Clash.Sized.Internal.bLit: unknown character: "+        ++ show c ++ " in input: " ++ cs0   instance KnownNat n => Eq (BitVector n) where@@ -493,11 +533,13 @@   (/=) = neq#  {-# NOINLINE 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  {-# NOINLINE neq# #-}+{-# ANN neq# hasBlackBox #-} neq# :: KnownNat n => BitVector n -> BitVector n -> Bool neq# (BV 0 v1) (BV 0 v2) = v1 /= v2 neq# bv1 bv2 = undefErrorI "/=" bv1 bv2@@ -510,15 +552,19 @@  lt#,ge#,gt#,le# :: KnownNat n => BitVector n -> BitVector n -> Bool {-# NOINLINE lt# #-}+{-# ANN lt# hasBlackBox #-} lt# (BV 0 n) (BV 0 m) = n < m lt# bv1 bv2 = undefErrorI "<" bv1 bv2 {-# NOINLINE ge# #-}+{-# ANN ge# hasBlackBox #-} ge# (BV 0 n) (BV 0 m) = n >= m ge# bv1 bv2 = undefErrorI ">=" bv1 bv2 {-# NOINLINE gt# #-}+{-# ANN gt# hasBlackBox #-} gt# (BV 0 n) (BV 0 m) = n > m gt# bv1 bv2 = undefErrorI ">" bv1 bv2 {-# NOINLINE le# #-}+{-# ANN le# hasBlackBox #-} le# (BV 0 n) (BV 0 m) = n <= m le#  bv1 bv2 = undefErrorI "<=" bv1 bv2 @@ -527,13 +573,23 @@ instance KnownNat n => Enum (BitVector n) where   succ           = (+# fromInteger# 0 1)   pred           = (-# fromInteger# 0 1)-  toEnum         = fromInteger# 0 . toInteger-  fromEnum       = fromEnum . toInteger#+  toEnum         = toEnum#+  fromEnum       = fromEnum#   enumFrom       = enumFrom#   enumFromThen   = enumFromThen#   enumFromTo     = enumFromTo#   enumFromThenTo = enumFromThenTo# +toEnum# :: forall n. KnownNat n => Int -> BitVector n+toEnum# = fromInteger# 0 . toInteger+{-# NOINLINE toEnum# #-}+{-# ANN toEnum# hasBlackBox #-}++fromEnum# :: forall n. KnownNat n => BitVector n -> Int+fromEnum# = fromEnum . toInteger#+{-# NOINLINE 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)@@ -602,10 +658,12 @@ minBound# :: BitVector n minBound# = BV 0 0 {-# NOINLINE minBound# #-}+{-# ANN minBound# hasBlackBox #-}  maxBound# :: forall n. KnownNat n => BitVector n maxBound# = let m = 1 `shiftL` natToNum @n in BV 0 (m-1) {-# NOINLINE maxBound# #-}+{-# ANN maxBound# hasBlackBox #-}  instance KnownNat n => Num (BitVector n) where   (+)         = (+#)@@ -618,6 +676,7 @@  (+#),(-#),(*#) :: forall n . KnownNat n => BitVector n -> BitVector n -> BitVector n {-# NOINLINE (+#) #-}+{-# ANN (+#) hasBlackBox #-} (+#) = go   where     go (BV 0 i) (BV 0 j) = BV 0 (addMod m i j)@@ -630,6 +689,7 @@ #endif  {-# NOINLINE (-#) #-}+{-# ANN (-#) hasBlackBox #-} (-#) = go   where     go (BV 0 i) (BV 0 j) = BV 0 (subMod m i j)@@ -642,6 +702,7 @@ #endif  {-# NOINLINE (*#) #-}+{-# ANN (*#) hasBlackBox #-} (*#) = go  where   go (BV 0 i) (BV 0 j) = BV 0 (mulMod2 m i j)@@ -654,6 +715,7 @@ #endif  {-# NOINLINE negate# #-}+{-# ANN negate# hasBlackBox #-} negate# :: forall n . KnownNat n => BitVector n -> BitVector n negate# = go  where@@ -667,6 +729,7 @@ #endif  {-# NOINLINE fromInteger# #-}+{-# ANN fromInteger# hasBlackBox #-} fromInteger# :: KnownNat n => Natural -> Integer -> BitVector n fromInteger# m i = sz `seq` mx   where@@ -688,11 +751,13 @@   mul = times#  {-# NOINLINE 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  {-# NOINLINE minus# #-}+{-# ANN minus# hasBlackBox #-} minus# :: forall m n . (KnownNat m, KnownNat n) => BitVector m -> BitVector n                                                 -> BitVector (Max m n + 1) minus# = go@@ -707,6 +772,7 @@ #endif  {-# NOINLINE 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) times# bv1 bv2 = undefErrorP "mul" bv1 bv2@@ -725,13 +791,16 @@  quot#,rem# :: KnownNat n => BitVector n -> BitVector n -> BitVector n {-# NOINLINE quot# #-}+{-# ANN quot# hasBlackBox #-} quot# (BV 0 i) (BV 0 j) = BV 0 (i `quot` j) quot# bv1 bv2 = undefErrorP "quot" bv1 bv2 {-# NOINLINE rem# #-}+{-# ANN rem# hasBlackBox #-} rem# (BV 0 i) (BV 0 j) = BV 0 (i `rem` j) rem# bv1 bv2 = undefErrorP "rem" bv1 bv2  {-# NOINLINE toInteger# #-}+{-# ANN toInteger# hasBlackBox #-} toInteger# :: KnownNat n => BitVector n -> Integer toInteger# (BV 0 i) = naturalToInteger i toInteger# bv = undefErrorU "toInteger" bv@@ -770,6 +839,7 @@ {-# INLINE countTrailingZerosBV #-}  {-# NOINLINE reduceAnd# #-}+{-# ANN reduceAnd# hasBlackBox #-} reduceAnd# :: KnownNat n => BitVector n -> Bit reduceAnd# bv@(BV 0 i) = Bit 0 (W# (int2Word# (dataToTag# check)))   where@@ -780,6 +850,7 @@ reduceAnd# bv = V.foldl (.&.) 1 (V.bv2v bv)  {-# NOINLINE reduceOr# #-}+{-# ANN reduceOr# hasBlackBox #-} reduceOr# :: KnownNat n => BitVector n -> Bit reduceOr# (BV 0 i) = Bit 0 (W# (int2Word# (dataToTag# check)))   where@@ -787,6 +858,7 @@ reduceOr# bv = V.foldl (.|.) 0 (V.bv2v bv)  {-# NOINLINE reduceXor# #-}+{-# ANN reduceXor# hasBlackBox #-} reduceXor# :: KnownNat n => BitVector n -> Bit reduceXor# (BV 0 i) = Bit 0 (fromIntegral (popCount i `mod` 2)) reduceXor# bv = undefErrorU "reduceXor" bv@@ -797,6 +869,7 @@ -- * Accessors -- ** Length information {-# NOINLINE size# #-}+{-# ANN size# hasBlackBox #-} size# :: KnownNat n => BitVector n -> Int #if MIN_VERSION_base(4,15,0) size# bv = fromIntegral (natVal bv)@@ -805,6 +878,7 @@ #endif  {-# NOINLINE maxIndex# #-}+{-# ANN maxIndex# hasBlackBox #-} maxIndex# :: KnownNat n => BitVector n -> Int #if MIN_VERSION_base(4,15,0) maxIndex# bv = fromIntegral (natVal bv) - 1@@ -814,6 +888,7 @@  -- ** Indexing {-# NOINLINE index# #-}+{-# ANN index# hasBlackBox #-} index# :: KnownNat n => BitVector n -> Int -> Bit index# bv@(BV m v) i     | i >= 0 && i < sz = Bit (W# (int2Word# (dataToTag# (testBit m i))))@@ -833,6 +908,7 @@                          ]  {-# NOINLINE msb# #-}+{-# ANN msb# hasBlackBox #-} -- | MSB msb# :: forall n . KnownNat n => BitVector n -> Bit msb# (BV m v)@@ -858,12 +934,14 @@ #endif  {-# NOINLINE 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))))  {-# NOINLINE 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')                            (shiftR (i   .&. mask) n')@@ -877,6 +955,7 @@  -- ** Concatenation {-# NOINLINE (++#) #-}+{-# 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)@@ -893,6 +972,7 @@  -- * Modifying BitVectors {-# NOINLINE 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)@@ -916,6 +996,7 @@                           ]  {-# NOINLINE setSlice# #-}+{-# ANN setSlice# hasBlackBox #-} setSlice#   :: forall m i n    . SNat (m + 1 + i)@@ -937,6 +1018,7 @@   complementN = complementMod (natVal (Proxy @(m + 1 + i)))  {-# NOINLINE split# #-}+{-# ANN split# hasBlackBox #-} split#   :: forall n m    . KnownNat n@@ -962,6 +1044,7 @@  and#, or#, xor# :: forall n . KnownNat n => BitVector n -> BitVector n -> BitVector n {-# NOINLINE and# #-}+{-# ANN and# hasBlackBox #-} and# =   \(BV m1 v1) (BV m2 v2) ->     let mask = (m1.&.v2 .|. m1.&.m2 .|. m2.&.v1)@@ -970,6 +1053,7 @@     complementN = complementMod (natVal (Proxy @n))  {-# NOINLINE or# #-}+{-# ANN or# hasBlackBox #-} or# =   \(BV m1 v1) (BV m2 v2) ->     let mask = m1 .&. complementN v2  .|.  m1.&.m2  .|.  m2 .&. complementN v1@@ -978,6 +1062,7 @@     complementN = complementMod (natVal (Proxy @n))  {-# NOINLINE xor# #-}+{-# ANN xor# hasBlackBox #-} xor# =   \(BV m1 v1) (BV m2 v2) ->     let mask  = m1 .|. m2@@ -986,6 +1071,7 @@     complementN = complementMod (natVal (Proxy @n))  {-# NOINLINE complement# #-}+{-# ANN complement# hasBlackBox #-} complement# :: forall n . KnownNat n => BitVector n -> BitVector n complement# = \(BV m v) -> BV m (complementN v .&. complementN m)   where complementN = complementMod (natVal (Proxy @n))@@ -994,26 +1080,32 @@   :: forall n . KnownNat n => BitVector n -> Int -> BitVector n  {-# NOINLINE shiftL# #-}-shiftL# =-  \(BV msk v) i ->-    if i >= 0 then-      BV ((shiftL msk i) `mod` m) ((shiftL v i) `mod` m)-    else-      error ("'shiftL' undefined for negative number: " ++ show i)+{-# ANN shiftL# hasBlackBox #-}+shiftL# = \(BV msk v) i ->+  if | i < 0+     -> error $ "'shiftL' undefined for negative number: " ++ show i+     | fromIntegral i >= sz+     -> BV 0 0+     | otherwise+     -> BV ((shiftL msk i) `mod` m) ((shiftL v i) `mod` m)  where #if MIN_VERSION_base(4,15,0)-  m = 1 `naturalShiftL` naturalToWord (natVal (Proxy @n))+  sz = naturalToWord (natVal (Proxy @n))+  m = 1 `naturalShiftL` sz #else-  m = 1 `shiftL` fromInteger (natVal (Proxy @n))+  sz = fromInteger (natVal (Proxy @n))+  m = 1 `shiftL` sz #endif  {-# NOINLINE shiftR# #-}+{-# ANN shiftR# hasBlackBox #-} shiftR# (BV m v) i   | i < 0     = error-              $ "'shiftR undefined for negative number: " ++ show i+              $ "'shiftR' undefined for negative number: " ++ show i   | otherwise = BV (shiftR m i) (shiftR v i)  {-# NOINLINE rotateL# #-}+{-# ANN rotateL# hasBlackBox #-} rotateL# =   \(BV msk v) b ->     if b >= 0 then@@ -1037,7 +1129,7 @@           b''  = sz - b'       in  BV ((ml .|. mr) `mod` m) ((vl .|. vr) `mod` m)     else-      error "'rotateL' undefined for negative numbers"+      error $ "'rotateL' undefined for negative number: " ++ show b  where #if MIN_VERSION_base(4,15,0)   sz = naturalToWord (natVal (Proxy @n))@@ -1048,6 +1140,7 @@ #endif  {-# NOINLINE rotateR# #-}+{-# ANN rotateR# hasBlackBox #-} rotateR# =   \(BV msk v) b ->     if b >= 0 then@@ -1067,7 +1160,7 @@           b''  = sz - b'       in  BV ((ml .|. mr) `mod` m) ((vl .|. vr) `mod` m)     else-      error "'rotateR' undefined for negative numbers"+      error $ "'rotateR' undefined for negative number: " ++ show b  where #if MIN_VERSION_base(4,15,0)   sz = naturalToWord (natVal (Proxy @n))@@ -1103,6 +1196,7 @@   where m = 1 `shiftL` fromInteger (natVal (Proxy @a)) #endif {-# NOINLINE 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))@@ -1126,6 +1220,11 @@     in  if msb# r == low            then truncateB# r            else minBound#+  satAdd SatError a b =+    let r = plus# a b+    in  if msb# r == low+           then truncateB# r+           else undefined#   satAdd _ a b =     let r  = plus# a b     in  if msb# r == low@@ -1133,6 +1232,11 @@            else maxBound#    satSub SatWrap a b = a -# b+  satSub SatError a b =+    let r = minus# a b+    in  if msb# r == low+           then truncateB# r+           else undefined#   satSub _ a b =     let r = minus# a b     in  if msb# r == low@@ -1146,6 +1250,12 @@     in  case rL of           0 -> rR           _ -> minBound#+  satMul SatError a b =+    let r       = times# a b+        (rL,rR) = split# r+    in  case rL of+          0 -> rR+          _ -> undefined#   satMul _ a b =     let r       = times# a b         (rL,rR) = split# r@@ -1214,7 +1324,7 @@   ++ unwords (L.map show bvs)  --- | Implement BitVector undefinedness checking for unpack funtions+-- | Implement BitVector undefinedness checking for unpack functions checkUnpackUndef :: (KnownNat n, Typeable a)                  => (BitVector n -> a) -- ^ unpack function                  -> BitVector n -> a@@ -1224,6 +1334,7 @@     ty = typeOf res     res = undefError (show ty ++ ".unpack") [bv] {-# NOINLINE checkUnpackUndef #-}+{-# ANN checkUnpackUndef hasBlackBox #-}  -- | Create a BitVector with all its bits undefined undefined# :: forall n . KnownNat n => BitVector n@@ -1235,20 +1346,24 @@ #endif   in  BV (m-1) 0 {-# NOINLINE undefined# #-}+{-# ANN undefined# hasBlackBox #-} --- | Check if one BitVector is like another.--- NFDataX bits in the second argument are interpreted as don't care bits.+-- | Check if one BitVector is similar to another, interpreting undefined bits+-- in the second argument as being "don't care" bits. This is a more lenient+-- version of '(==)', similar to @std_match@ in VHDL or @casez@ in Verilog. ----- >>> let expected = $$(bLit "1.") :: BitVector 2--- >>> let checked  = $$(bLit "11") :: BitVector 2--- >>> checked  `isLike` expected+-- >>> let expected = $(bLit "1.")+-- >>> let checked  = $(bLit "11")+--+-- >>> checked  `isLike#` expected -- True--- >>> expected `isLike` checked+-- >>> expected `isLike#` checked -- False -- -- __NB__: Not synthesizable-isLike :: forall n . KnownNat n => BitVector n -> BitVector n -> Bool-isLike =+--+isLike# :: forall n . KnownNat n => BitVector n -> BitVector n -> Bool+isLike# =   \(BV cMask c) (BV eMask e) ->         -- set don't care bits to 0     let e' = e .&. complementN eMask@@ -1259,7 +1374,7 @@     in  e' == c' && e' == c''  where   complementN = complementMod (natVal (Proxy @n))-{-# NOINLINE isLike #-}+{-# NOINLINE isLike# #-}  fromBits :: [Bit] -> Integer fromBits = L.foldl (\v b -> v `shiftL` 1 .|. fromIntegral b) 0
src/Clash/Sized/Internal/Index.hs view
@@ -1,8 +1,9 @@ {-| Copyright  :  (C) 2013-2016, University of Twente,-                  2016-2019, Myrtle Software Ltd+                  2016-2019, Myrtle Software Ltd,+                  2021-2022, QBayLogic B.V. License    :  BSD2 (see the file LICENSE)-Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com> -}  {-# LANGUAGE CPP #-}@@ -41,6 +42,9 @@   , ge#   , gt#   , le#+    -- ** Enum+  , toEnum#+  , fromEnum#     -- ** Enum (not synthesizable)   , enumFrom#   , enumFromThen#@@ -52,6 +56,7 @@   , (+#)   , (-#)   , (*#)+  , negate#   , fromInteger#     -- ** ExtendingNum   , plus#@@ -87,11 +92,7 @@ #endif import GHC.Generics               (Generic) import GHC.Natural                (Natural, naturalFromInteger)-#if MIN_VERSION_base(4,12,0) import GHC.Natural                (naturalToInteger)-#else-import Clash.Sized.Internal.Mod   (naturalToInteger)-#endif import GHC.Stack                  (HasCallStack) import GHC.TypeLits               (KnownNat, Nat, type (+), type (-),                                    type (*), type (<=), natVal)@@ -100,12 +101,13 @@                                    arbitraryBoundedIntegral,                                    coarbitraryIntegral, shrinkIntegral) -import Clash.Class.BitPack        (BitPack (..), packXWith)+import Clash.Annotations.Primitive (hasBlackBox)+import Clash.Class.BitPack.Internal (BitPack (..), packXWith) import Clash.Class.Num            (ExtendingNum (..), SaturatingNum (..),                                    SaturationMode (..)) import Clash.Class.Parity         (Parity (..)) import Clash.Class.Resize         (Resize (..))-import Clash.Prelude.BitIndex     (replaceBit)+import Clash.Class.BitPack.BitIndex (replaceBit) 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)@@ -142,7 +144,7 @@ -- *** Exception: X: Clash.Sized.Index: result 8 is out of bounds: [0..7] -- ... ----- Index has the <https://downloads.haskell.org/ghc/latest/docs/html/users_guide/glasgow_exts.html#roles type role>+-- Index has the <https://downloads.haskell.org/ghc/latest/docs/html/users_guide/exts/roles.html type role> -- -- >>> :i Index -- type role Index nominal@@ -163,6 +165,8 @@ #endif   deriving (Data, Generic) +{-# ANN I hasBlackBox #-}+ {-# NOINLINE size# #-} size# :: (KnownNat n, 1 <= n) => Index n -> Int size# = BV.size# . pack#@@ -183,10 +187,12 @@ fromSNat = snatToNum  {-# NOINLINE pack# #-}+{-# ANN pack# hasBlackBox #-} pack# :: Index n -> BitVector (CLog 2 n) pack# (I i) = BV 0 (naturalFromInteger i)  {-# NOINLINE unpack# #-}+{-# ANN unpack# hasBlackBox #-} unpack# :: (KnownNat n, 1 <= n) => BitVector (CLog 2 n) -> Index n unpack# (BV 0 i) = fromInteger_INLINE (naturalToInteger i) unpack# bv = undefError "Index.unpack" [bv]@@ -196,10 +202,12 @@   (/=) = neq#  {-# NOINLINE eq# #-}+{-# ANN eq# hasBlackBox #-} eq# :: (Index n) -> (Index n) -> Bool (I n) `eq#` (I m) = n == m  {-# NOINLINE neq# #-}+{-# ANN neq# hasBlackBox #-} neq# :: (Index n) -> (Index n) -> Bool (I n) `neq#` (I m) = n /= m @@ -211,12 +219,16 @@  lt#,ge#,gt#,le# :: Index n -> Index n -> Bool {-# NOINLINE lt# #-}+{-# ANN lt# hasBlackBox #-} lt# (I n) (I m) = n < m {-# NOINLINE ge# #-}+{-# ANN ge# hasBlackBox #-} ge# (I n) (I m) = n >= m {-# NOINLINE gt# #-}+{-# ANN gt# hasBlackBox #-} gt# (I n) (I m) = n > m {-# NOINLINE le# #-}+{-# ANN le# hasBlackBox #-} le# (I n) (I m) = n <= m  -- | The functions: 'enumFrom', 'enumFromThen', 'enumFromTo', and@@ -224,13 +236,23 @@ instance KnownNat n => Enum (Index n) where   succ           = (+# fromInteger# 1)   pred           = (-# fromInteger# 1)-  toEnum         = fromInteger# . toInteger-  fromEnum       = fromEnum . toInteger#+  toEnum         = toEnum#+  fromEnum       = fromEnum#   enumFrom       = enumFrom#   enumFromThen   = enumFromThen#   enumFromTo     = enumFromTo#   enumFromThenTo = enumFromThenTo# +toEnum# :: forall n. KnownNat n => Int -> Index n+toEnum# = fromInteger# . toInteger+{-# NOINLINE toEnum# #-}+{-# ANN toEnum# hasBlackBox #-}++fromEnum# :: forall n. KnownNat n => Index n -> Int+fromEnum# = fromEnum . toInteger#+{-# NOINLINE fromEnum# #-}+{-# ANN fromEnum# hasBlackBox #-}+ enumFrom# :: forall n. KnownNat n => Index n -> [Index n] enumFrom# x = [x .. maxBound] {-# NOINLINE enumFrom# #-}@@ -257,29 +279,38 @@     0 -> errorX "maxBound of 'Index 0' is undefined"     n -> fromInteger_INLINE (n - 1) {-# NOINLINE maxBound# #-}+{-# ANN maxBound# hasBlackBox #-}  -- | Operators report an error on overflow and underflow instance KnownNat n => Num (Index n) where   (+)         = (+#)   (-)         = (-#)   (*)         = (*#)-  negate      = (maxBound# -#)+  negate      = negate#   abs         = id   signum i    = if i == 0 then 0 else 1   fromInteger = fromInteger#  (+#),(-#),(*#) :: KnownNat n => Index n -> Index n -> Index n {-# NOINLINE (+#) #-}+{-# ANN (+#) hasBlackBox #-} (+#) (I a) (I b) = fromInteger_INLINE $ a + b  {-# NOINLINE (-#) #-}+{-# ANN (-#) hasBlackBox #-} (-#) (I a) (I b) = fromInteger_INLINE $ a - b  {-# NOINLINE (*#) #-}+{-# ANN (*#) hasBlackBox #-} (*#) (I a) (I b) = fromInteger_INLINE $ a * b +negate# :: KnownNat n => Index n -> Index n+negate# 0 = 0+negate# i = maxBound -# i +# 1+ fromInteger# :: KnownNat n => Integer -> Index n {-# NOINLINE fromInteger# #-}+{-# ANN fromInteger# hasBlackBox #-} fromInteger# = fromInteger_INLINE {-# INLINE fromInteger_INLINE #-} fromInteger_INLINE :: forall n . (HasCallStack, KnownNat n) => Integer -> Index n@@ -298,9 +329,11 @@  plus#, minus# :: Index m -> Index n -> Index (m + n - 1) {-# NOINLINE plus# #-}+{-# ANN plus# hasBlackBox #-} plus# (I a) (I b) = I (a + b)  {-# NOINLINE minus# #-}+{-# ANN minus# hasBlackBox #-} minus# (I a) (I b) =   let z   = a - b       err = error ("Clash.Sized.Index.minus: result " ++ show z ++@@ -309,6 +342,7 @@   in  res  {-# NOINLINE times# #-}+{-# ANN times# hasBlackBox #-} times# :: Index m -> Index n -> Index (((m - 1) * (n - 1)) + 1) times# (I a) (I b) = I (a * b) @@ -327,6 +361,12 @@         z | let m = fromInteger# (natToInteger @(n - 1))           , z > m -> fromInteger# 0         z -> resize# z+  satAdd SatError a b =+    leToPlusKN @1 @n $+      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 $       case plus# a b of@@ -338,7 +378,10 @@     if lt# a b        then maxBound -# (b -# a) +# 1        else a -# b-+  satSub SatError a b =+    if lt# a b+       then errorX "Index.satSub: underflow"+       else a -# b   satSub _ a b =     if lt# a b        then fromInteger# 0@@ -358,6 +401,12 @@         z | let m = fromInteger# (natToInteger @(n - 1))           , z > m -> fromInteger# 0         z -> resize# z+  satMul SatError a b =+    leToPlusKN @1 @n $+      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 $       case times# a b of@@ -365,12 +414,20 @@           , z > m -> maxBound#         z -> resize# z +  satSucc SatError !a =+    case natToInteger @n of+      1 -> errorX "Index.satSucc: overflow"+      _ -> satAdd SatError a $ fromInteger# 1   satSucc satMode !a =     case natToInteger @n of       1 -> fromInteger# 0       _ -> satAdd satMode a $ fromInteger# 1   {-# INLINE satSucc #-} +  satPred SatError !a =+    case natToInteger @n of+      1 -> errorX "Index.satPred: underflow"+      _ -> satSub SatError a $ fromInteger# 1   satPred satMode !a =     case natToInteger @n of       1 -> fromInteger# 0@@ -391,11 +448,14 @@  quot#,rem# :: Index n -> Index n -> Index n {-# NOINLINE quot# #-}+{-# ANN quot# hasBlackBox #-} (I a) `quot#` (I b) = I (a `div` b) {-# NOINLINE rem# #-}+{-# ANN rem# hasBlackBox #-} (I a) `rem#` (I b) = I (a `rem` b)  {-# NOINLINE toInteger# #-}+{-# ANN toInteger# hasBlackBox #-} toInteger# :: Index n -> Integer toInteger# (I n) = n @@ -439,6 +499,7 @@ resize# :: KnownNat m => Index n -> Index m resize# (I i) = fromInteger_INLINE i {-# NOINLINE resize# #-}+{-# ANN resize# hasBlackBox #-}  instance KnownNat n => Lift (Index n) where   lift u@(I i) = sigE [| fromInteger# i |] (decIndex (natVal u))
src/Clash/Sized/Internal/Mod.hs view
@@ -36,13 +36,7 @@ #endif import GHC.Exts   ((<=#), geWord#, isTrue#, minusWord#, plusWord#, uncheckedShiftL#, xor#,-   timesWord2#, quotRemWord2#, and#)-#if MIN_VERSION_base(4,12,0)-import GHC.Exts (addWordC#)-#endif-#if !MIN_VERSION_base(4,12,0)-import GHC.Exts (Int#, Word#, plusWord2#, word2Int#)-#endif+   timesWord2#, quotRemWord2#, and#, addWordC#) #if MIN_VERSION_base(4,15,0) import GHC.Num.BigNat   (BigNat#, bigNatAdd, bigNatAddWord#, bigNatAnd, bigNatBit#, bigNatCompare,@@ -56,9 +50,6 @@    plusBigNat, plusBigNatWord, sizeofBigNat#, bitBigNat, wordToBigNat2,    remBigNat, timesBigNat, timesBigNatWord, xorBigNat, wordToBigNat, andBigNat) #endif-#if !MIN_VERSION_base(4,12,0)-import GHC.Integer.GMP.Internals (wordToInteger)-#endif  #include "MachDeps.h" @@ -357,16 +348,6 @@   EQ -> NatS# 0##   GT -> bigNatToNat $ z# `minusBigNat` m# -#if !MIN_VERSION_base(4,12,0)-addWordC# :: Word# -> Word# -> (# Word#, Int# #)-addWordC# x# y# = (# z#, word2Int# c# #)-  where-    !(# c#, z# #) = x# `plusWord2#` y#--naturalToInteger :: Natural -> Integer-naturalToInteger (NatS# w)  = wordToInteger w-naturalToInteger (NatJ# bn) = Jp# bn-#endif #endif  brokenInvariant :: a
src/Clash/Sized/Internal/Signed.hs view
@@ -1,13 +1,15 @@ {-| Copyright  :  (C) 2013-2016, University of Twente,-                  2016     , Myrtle Software Ltd+                  2016     , Myrtle Software Ltd,+                  2021-2022, QBayLogic 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 DeriveAnyClass #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE MultiWayIf #-} {-# LANGUAGE RoleAnnotations #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-}@@ -37,6 +39,9 @@   , ge#   , gt#   , le#+    -- ** Enum+  , toEnum#+  , fromEnum#     -- ** Enum (not synthesizable)   , enumFrom#   , enumFromThen#@@ -90,12 +95,7 @@ import Text.Read                      (Read (..), ReadPrec) import Text.Printf                    (PrintfArg (..), printf) import GHC.Generics                   (Generic)-import GHC.Natural                    (naturalFromInteger)-#if MIN_VERSION_base(4,12,0)-import GHC.Natural                    (naturalToInteger)-#else-import Clash.Sized.Internal.Mod       (naturalToInteger)-#endif+import GHC.Natural                    (naturalFromInteger, naturalToInteger)  import GHC.TypeLits                   (KnownNat, Nat, type (+), natVal) import GHC.TypeLits.Extra             (Max)@@ -114,19 +114,25 @@                                        arbitraryBoundedIntegral,                                        coarbitraryIntegral, shrinkIntegral) +import Clash.Annotations.Primitive (hasBlackBox) import Clash.Class.BitPack            (BitPack (..), packXWith) import Clash.Class.Num                (ExtendingNum (..), SaturatingNum (..),                                        SaturationMode (..)) import Clash.Class.Parity             (Parity (..)) import Clash.Class.Resize             (Resize (..))-import Clash.Prelude.BitIndex         ((!), msb, replaceBit, split)-import Clash.Prelude.BitReduction     (reduceAnd, reduceOr)+import Clash.Class.BitPack.BitIndex   ((!), msb, replaceBit, split)+import Clash.Class.BitPack.BitReduction (reduceAnd, reduceOr) import Clash.Promoted.Nat             (natToNatural) import Clash.Sized.Internal.BitVector (BitVector (BV), Bit, (++#), high, low, undefError) import qualified Clash.Sized.Internal.BitVector as BV import Clash.XException   (ShowX (..), NFDataX (..), errorX, showsPrecXWith, rwhnfX) +{- $setup+>>> :m -Prelude+>>> import Clash.Prelude+-}+ type role Signed nominal  -- | Arbitrary-width signed integer represented by @n@ bits, including the sign@@ -166,7 +172,7 @@ -- >>> satAdd SatSymmetric (-2) (-3) :: Signed 3 -- -3 ----- Signed has the <https://downloads.haskell.org/ghc/latest/docs/html/users_guide/glasgow_exts.html#roles type role>+-- Signed has the <https://downloads.haskell.org/ghc/latest/docs/html/users_guide/exts/roles.html type role> -- -- >>> :i Signed -- type role Signed nominal@@ -187,11 +193,14 @@ #endif   deriving (Data, Generic) +{-# ANN S hasBlackBox #-}+ instance NFDataX (Signed n) where   deepErrorX = errorX   rnfX = rwhnfX  {-# NOINLINE size# #-}+{-# ANN size# hasBlackBox #-} size# :: KnownNat n => Signed n -> Int size# bv = fromInteger (natVal bv) @@ -218,11 +227,13 @@   unpack = unpack#  {-# NOINLINE 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)  {-# NOINLINE unpack# #-}+{-# ANN unpack# hasBlackBox #-} unpack# :: forall n . KnownNat n => BitVector n -> Signed n unpack# (BV 0 i) =   let m = 1 `shiftL0` fromInteger (natVal (Proxy @n) - 1)@@ -235,10 +246,12 @@   (/=) = neq#  {-# NOINLINE eq# #-}+{-# ANN eq# hasBlackBox #-} eq# :: Signed n -> Signed n -> Bool eq# (S v1) (S v2) = v1 == v2  {-# NOINLINE neq# #-}+{-# ANN neq# hasBlackBox #-} neq# :: Signed n -> Signed n -> Bool neq# (S v1) (S v2) = v1 /= v2 @@ -250,12 +263,16 @@  lt#,ge#,gt#,le# :: Signed n -> Signed n -> Bool {-# NOINLINE lt# #-}+{-# ANN lt# hasBlackBox #-} lt# (S n) (S m) = n < m {-# NOINLINE ge# #-}+{-# ANN ge# hasBlackBox #-} ge# (S n) (S m) = n >= m {-# NOINLINE gt# #-}+{-# ANN gt# hasBlackBox #-} gt# (S n) (S m) = n > m {-# NOINLINE le# #-}+{-# ANN le# hasBlackBox #-} le# (S n) (S m) = n <= m  -- | The functions: 'enumFrom', 'enumFromThen', 'enumFromTo', and@@ -277,14 +294,23 @@              <> "need other behavior."     | otherwise = n -# fromInteger# 1 -  toEnum         = fromInteger# . toInteger-  fromEnum       = fromEnum . toInteger#+  toEnum         = toEnum#+  fromEnum       = fromEnum#   enumFrom       = enumFrom#   enumFromThen   = enumFromThen#   enumFromTo     = enumFromTo#   enumFromThenTo = enumFromThenTo# +toEnum# :: forall n. KnownNat n => Int -> Signed n+toEnum# = fromInteger# . toInteger+{-# NOINLINE toEnum# #-}+{-# ANN toEnum# hasBlackBox #-} +fromEnum# :: forall n. KnownNat n => Signed n -> Int+fromEnum# = fromEnum . toInteger#+{-# NOINLINE fromEnum# #-}+{-# ANN fromEnum# hasBlackBox #-}+ enumFrom# :: forall n. KnownNat n => Signed n -> [Signed n] enumFrom# x = map (fromInteger_INLINE sz mB mask) [unsafeToInteger x .. unsafeToInteger (maxBound :: Signed n)]   where sz   = fromInteger (natVal (Proxy @n)) - 1@@ -328,6 +354,7 @@     0 -> 0     n -> S (negate $ 2 ^ (n - 1)) {-# NOINLINE minBound# #-}+{-# ANN minBound# hasBlackBox #-}  maxBound# :: forall n. KnownNat n => Signed n maxBound# =@@ -335,6 +362,7 @@     0 -> 0     n -> S (2 ^ (n - 1) - 1) {-# NOINLINE maxBound# #-}+{-# ANN maxBound# hasBlackBox #-}  -- | Operators do @wrap-around@ on overflow instance KnownNat n => Num (Signed n) where@@ -349,6 +377,7 @@  (+#), (-#), (*#) :: forall n . KnownNat n => Signed n -> Signed n -> Signed n {-# NOINLINE (+#) #-}+{-# ANN (+#) hasBlackBox #-} (+#) =   \(S a) (S b) ->     let z = a + b@@ -362,6 +391,7 @@   m = 1 `shiftL0` fromInteger (natVal (Proxy @n) -1)  {-# NOINLINE (-#) #-}+{-# ANN (-#) hasBlackBox #-} (-#) =   \(S a) (S b) ->     let z = a - b@@ -375,6 +405,7 @@   m  = 1 `shiftL0` fromInteger (natVal (Proxy @n) -1)  {-# NOINLINE (*#) #-}+{-# ANN (*#) hasBlackBox #-} (*#) = \(S a) (S b) -> fromInteger_INLINE sz mB mask (a * b)   where sz   = fromInteger (natVal (Proxy @n)) - 1         mB   = 1 `shiftL` sz@@ -382,6 +413,7 @@  negate#,abs# :: forall n . KnownNat n => Signed n -> Signed n {-# NOINLINE negate# #-}+{-# ANN negate# hasBlackBox #-} negate# =   \(S n) ->     let z = negate n@@ -390,6 +422,7 @@   m = 1 `shiftL0` fromInteger (natVal (Proxy @n) -1)  {-# NOINLINE abs# #-}+{-# ANN abs# hasBlackBox #-} abs# =   \(S n) ->     let z = abs n@@ -398,6 +431,7 @@   m = 1 `shiftL0` fromInteger (natVal (Proxy @n) -1)  {-# NOINLINE fromInteger# #-}+{-# ANN fromInteger# hasBlackBox #-} fromInteger# :: forall n . KnownNat n => Integer -> Signed (n :: Nat) fromInteger# = fromInteger_INLINE sz mB mask   where sz   = fromInteger (natVal (Proxy @n)) - 1@@ -422,12 +456,15 @@  plus#, minus# :: Signed m -> Signed n -> Signed (Max m n + 1) {-# NOINLINE plus# #-}+{-# ANN plus# hasBlackBox #-} plus# (S a) (S b) = S (a + b)  {-# NOINLINE minus# #-}+{-# ANN minus# hasBlackBox #-} minus# (S a) (S b) = S (a - b)  {-# NOINLINE times# #-}+{-# ANN times# hasBlackBox #-} times# :: Signed m -> Signed n -> Signed (m + n) times# (S a) (S b) = S (a * b) @@ -443,19 +480,36 @@   divMod  n d = (n `div#`  d,n `mod#` d)   toInteger   = toInteger# -quot#,rem# :: Signed n -> Signed n -> Signed n {-# NOINLINE quot# #-}-quot# (S a) (S b) = S (a `quot` b)+{-# ANN quot# hasBlackBox #-}+quot# :: forall n. KnownNat n => Signed n -> Signed n -> Signed n+quot# (S a) (S b)+  | a == minB && b == (-1) = S minB+  | otherwise = S (a `quot` b)+ where+  S minB = minBound @(Signed n)+ {-# NOINLINE rem# #-}+{-# ANN rem# hasBlackBox #-}+rem# :: Signed n -> Signed n -> Signed n rem# (S a) (S b) = S (a `rem` b) -div#,mod# :: Signed n -> Signed n -> Signed n {-# NOINLINE div# #-}-div# (S a) (S b) = S (a `div` b)+{-# ANN div# hasBlackBox #-}+div# :: forall n. KnownNat n => Signed n -> Signed n -> Signed n+div# (S a) (S b)+  | a == minB && b == (-1) = S minB+  | otherwise = S (a `div` b)+ where+  S minB = minBound @(Signed n)+ {-# NOINLINE mod# #-}+{-# ANN mod# hasBlackBox #-}+mod# :: Signed n -> Signed n -> Signed n mod# (S a) (S b) = S (a `mod` b)  {-# NOINLINE toInteger# #-}+{-# ANN toInteger# hasBlackBox #-} toInteger# :: Signed n -> Integer toInteger# (S n) = n @@ -488,24 +542,28 @@  and#,or#,xor# :: forall n . KnownNat n => Signed n -> Signed n -> Signed n {-# NOINLINE 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  {-# NOINLINE 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  {-# NOINLINE 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  {-# NOINLINE complement# #-}+{-# ANN complement# hasBlackBox #-} complement# :: forall n . KnownNat n => Signed n -> Signed n complement# = \(S a) -> fromInteger_INLINE sz mB mask (complement a)   where sz   = fromInteger (natVal (Proxy @n)) - 1@@ -514,30 +572,31 @@  shiftL#,shiftR#,rotateL#,rotateR# :: forall n . KnownNat n => Signed n -> Int -> Signed n {-# NOINLINE shiftL# #-}-shiftL# =-  \(S n) b ->-    if b >= 0 then-      fromInteger_INLINE sz mB mask (shiftL n b)-    else-      error "'shiftL' undefined for negative numbers"+{-# ANN shiftL# hasBlackBox #-}+shiftL# = \(S n) b ->+  if | b < 0     -> error $ "'shiftL' undefined for negative number: " ++ show b+     | b > sz    -> S 0+     | otherwise -> fromInteger_INLINE sz mB mask (shiftL n b)  where   sz   = fromInteger (natVal (Proxy @n)) - 1   mB   = 1 `shiftL` sz   mask = mB - 1  {-# NOINLINE shiftR# #-}+{-# ANN shiftR# hasBlackBox #-} shiftR# =   \(S n) b ->     if b >= 0 then       fromInteger_INLINE sz mB mask (shiftR n b)     else-      error "'shiftR' undefined for negative numbers"+      error $ "'shiftR' undefined for negative number: " ++ show b  where   sz   = fromInteger (natVal (Proxy @n)) - 1   mB   = 1 `shiftL` sz   mask = mB - 1  {-# NOINLINE rotateL# #-}+{-# ANN rotateL# hasBlackBox #-} rotateL# =   \(S n) b ->     if b >= 0 then@@ -549,7 +608,7 @@           b''  = sz - b'       in  fromInteger_INLINE sz1 mB maskM (l .|. r)     else-      error "'rotateL undefined for negative numbers"+      error $ "'rotateL undefined for negative number: " ++ show b  where   sz    = fromInteger (natVal (Proxy @n))   sz1   = sz-1@@ -557,6 +616,7 @@   maskM = mB - 1  {-# NOINLINE rotateR# #-}+{-# ANN rotateR# hasBlackBox #-} rotateR# =   \(S n) b ->     if b >= 0 then@@ -568,7 +628,7 @@           b'' = sz - b'       in  fromInteger_INLINE sz1 mB maskM (l .|. r)     else-      error "'rotateR' undefined for negative numbers"+      error $ "'rotateR' undefined for negative number: " ++ show b  where   sz    = fromInteger (natVal (Proxy @n))   sz1   = sz - 1@@ -586,6 +646,7 @@   truncateB    = truncateB#  {-# NOINLINE resize# #-}+{-# ANN resize# hasBlackBox #-} resize# :: forall m n . (KnownNat n, KnownNat m) => Signed n -> Signed m resize# s@(S i)   | natToNatural @m == 0 = S 0@@ -604,6 +665,7 @@                    else S i'  {-# NOINLINE truncateB# #-}+{-# ANN truncateB# hasBlackBox #-} truncateB# :: forall m n . KnownNat m => Signed (m + n) -> Signed m truncateB# = \(S n) -> fromInteger_INLINE sz mB mask n   where sz   = fromInteger (natVal (Proxy @m)) - 1@@ -643,6 +705,12 @@     in  case msb r `xor` msb r' of           0 -> unpack# r'           _ -> fromInteger# 0+  satAdd SatError a b =+    let r      = plus# a b+        (_,r') = split r+    in  case msb r `xor` msb r' of+          0 -> unpack# r'+          _ -> errorX "Signed.satAdd: overflow/underflow"   satAdd SatSymmetric a b =     let r      = plus# a b         (_,r') = split r@@ -667,6 +735,12 @@     in  case msb r `xor` msb r' of           0 -> unpack# r'           _ -> fromInteger# 0+  satSub SatError a b =+    let r      = minus# a b+        (_,r') = split r+    in  case msb r `xor` msb r' of+          0 -> unpack# r'+          _ -> errorX "Signed.satSub: overflow/underflow"   satSub SatSymmetric a b =     let r      = minus# a b         (_,r') = split r@@ -695,6 +769,14 @@     in  case overflow of           1 -> unpack# rR           _ -> fromInteger# 0+  satMul SatError a b =+    let r        = times# a b+        (rL,rR)  = split r+        overflow = complement (reduceOr (BV.pack# (msb rR) ++# pack rL)) .|.+                   reduceAnd (BV.pack# (msb rR) ++# pack rL)+    in  case overflow of+          1 -> unpack# rR+          _ -> errorX "Signed.satMul: overflow/underflow"   satMul SatSymmetric a b =     let r        = times# a b         (rL,rR)  = split r@@ -706,8 +788,13 @@             0 -> maxBound#             _ -> minBoundSym# +  satSucc SatError a+    | a == maxBound = errorX "Signed.satSucc: overflow"   satSucc satMode a = satSub satMode a $ fromInteger# (-1)   {-# INLINE satSucc #-}++  satPred SatError a+    | a == minBound = errorX "Signed.satPred: underflow"   satPred satMode a = satAdd satMode a $ fromInteger# (-1)   {-# INLINE satPred #-} 
src/Clash/Sized/Internal/Unsigned.hs view
@@ -1,13 +1,15 @@ {-| Copyright  :  (C) 2013-2016, University of Twente,-                  2016     , Myrtle Software Ltd+                  2016     , Myrtle Software Ltd,+                  2021-2022, QBayLogic 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 DeriveAnyClass #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE MultiWayIf #-} {-# LANGUAGE RoleAnnotations #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-}@@ -36,6 +38,9 @@   , ge#   , gt#   , le#+    -- ** Enum+  , toEnum#+  , fromEnum#     -- ** Enum (not synthesizable)   , enumFrom#   , enumFromThen#@@ -99,9 +104,7 @@ import GHC.Integer.GMP.Internals      (bigNatToWord) import GHC.Natural                    (Natural (..), naturalFromInteger) #endif-#if MIN_VERSION_base(4,12,0) import GHC.Natural                    (naturalToInteger)-#endif import GHC.TypeLits                   (KnownNat, Nat, type (+)) #if MIN_VERSION_base(4,15,0) import GHC.TypeNats                   (natVal)@@ -125,13 +128,14 @@                                        arbitraryBoundedIntegral,                                        coarbitraryIntegral) +import Clash.Annotations.Primitive (hasBlackBox) import Clash.Class.BitPack            (BitPack (..), packXWith, bitCoerce) import Clash.Class.Num                (ExtendingNum (..), SaturatingNum (..),                                        SaturationMode (..)) import Clash.Class.Parity             (Parity (..)) import Clash.Class.Resize             (Resize (..))-import Clash.Prelude.BitIndex         ((!), msb, replaceBit, split)-import Clash.Prelude.BitReduction     (reduceOr)+import Clash.Class.BitPack.BitIndex   ((!), msb, replaceBit, split)+import Clash.Class.BitPack.BitReduction (reduceOr) import Clash.Promoted.Nat             (natToNum, natToNatural) import Clash.Sized.Internal.BitVector (BitVector (BV), Bit, high, low, undefError) import qualified Clash.Sized.Internal.BitVector as BV@@ -139,6 +143,11 @@ import Clash.XException   (ShowX (..), NFDataX (..), errorX, showsPrecXWith, rwhnfX) +{- $setup+>>> :m -Prelude+>>> import Clash.Prelude+-}+ #include "MachDeps.h"  type role Unsigned nominal@@ -175,7 +184,7 @@ -- >>> satSub SatSymmetric 2 3 :: Unsigned 3 -- 0 ----- Unsigned has the <https://downloads.haskell.org/ghc/latest/docs/html/users_guide/glasgow_exts.html#roles type role>+-- Unsigned has the <https://downloads.haskell.org/ghc/latest/docs/html/users_guide/exts/roles.html type role> -- -- >>> :i Unsigned -- type role Unsigned nominal@@ -196,7 +205,10 @@ #endif   deriving (Data, Generic) +{-# ANN U hasBlackBox #-}+ {-# NOINLINE size# #-}+{-# ANN size# hasBlackBox #-} size# :: KnownNat n => Unsigned n -> Int #if MIN_VERSION_base(4,15,0) size# u = fromIntegral (natVal u)@@ -231,10 +243,12 @@   unpack = unpack#  {-# NOINLINE pack# #-}+{-# ANN pack# hasBlackBox #-} pack# :: Unsigned n -> BitVector n pack# (U i) = BV 0 i  {-# NOINLINE unpack# #-}+{-# ANN unpack# hasBlackBox #-} unpack# :: KnownNat n => BitVector n -> Unsigned n unpack# (BV 0 i) = U i unpack# bv = undefError "Unsigned.unpack" [bv]@@ -244,10 +258,12 @@   (/=) = neq#  {-# NOINLINE eq# #-}+{-# ANN eq# hasBlackBox #-} eq# :: Unsigned n -> Unsigned n -> Bool eq# (U v1) (U v2) = v1 == v2  {-# NOINLINE neq# #-}+{-# ANN neq# hasBlackBox #-} neq# :: Unsigned n -> Unsigned n -> Bool neq# (U v1) (U v2) = v1 /= v2 @@ -259,12 +275,16 @@  lt#,ge#,gt#,le# :: Unsigned n -> Unsigned n -> Bool {-# NOINLINE lt# #-}+{-# ANN lt# hasBlackBox #-} lt# (U n) (U m) = n < m {-# NOINLINE ge# #-}+{-# ANN ge# hasBlackBox #-} ge# (U n) (U m) = n >= m {-# NOINLINE gt# #-}+{-# ANN gt# hasBlackBox #-} gt# (U n) (U m) = n > m {-# NOINLINE le# #-}+{-# ANN le# hasBlackBox #-} le# (U n) (U m) = n <= m  -- | The functions: 'enumFrom', 'enumFromThen', 'enumFromTo', and@@ -286,13 +306,23 @@              <> "need other behavior."     | otherwise = n -# fromInteger# 1 -  toEnum         = fromInteger# . toInteger-  fromEnum       = fromEnum . toInteger#+  toEnum         = toEnum#+  fromEnum       = fromEnum#   enumFrom       = enumFrom#   enumFromThen   = enumFromThen#   enumFromTo     = enumFromTo#   enumFromThenTo = enumFromThenTo# +toEnum# :: forall n. KnownNat n => Int -> Unsigned n+toEnum# = fromInteger# . toInteger+{-# NOINLINE toEnum# #-}+{-# ANN toEnum# hasBlackBox #-}++fromEnum# :: forall n. KnownNat n => Unsigned n -> Int+fromEnum# = fromEnum . toInteger#+{-# NOINLINE 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)@@ -339,10 +369,12 @@ minBound# :: Unsigned n minBound# = U 0 {-# NOINLINE minBound# #-}+{-# ANN minBound# hasBlackBox #-}  maxBound# :: forall n. KnownNat n => Unsigned n maxBound# = let m = 1 `shiftL` (natToNum @n) in  U (m - 1) {-# NOINLINE maxBound# #-}+{-# ANN maxBound# hasBlackBox #-}  instance KnownNat n => Num (Unsigned n) where   (+)         = (+#)@@ -355,6 +387,7 @@  (+#),(-#),(*#) :: forall n . KnownNat n => Unsigned n -> Unsigned n -> Unsigned n {-# NOINLINE (+#) #-}+{-# 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))@@ -363,6 +396,7 @@ #endif  {-# NOINLINE (-#) #-}+{-# 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))@@ -371,6 +405,7 @@ #endif  {-# NOINLINE (*#) #-}+{-# 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@@ -379,6 +414,7 @@ #endif  {-# NOINLINE 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)@@ -388,6 +424,7 @@ #endif  {-# NOINLINE 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))@@ -407,10 +444,12 @@   mul = times#  {-# NOINLINE plus# #-}+{-# ANN plus# hasBlackBox #-} plus# :: Unsigned m -> Unsigned n -> Unsigned (Max m n + 1) plus# (U a) (U b) = U (a + b)  {-# NOINLINE 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)@@ -424,6 +463,7 @@ #endif  {-# NOINLINE times# #-}+{-# ANN times# hasBlackBox #-} times# :: Unsigned m -> Unsigned n -> Unsigned (m + n) times# (U a) (U b) = U (a * b) @@ -441,11 +481,14 @@  quot#,rem# :: Unsigned n -> Unsigned n -> Unsigned n {-# NOINLINE quot# #-}+{-# ANN quot# hasBlackBox #-} quot# (U i) (U j) = U (i `quot` j) {-# NOINLINE rem# #-}+{-# ANN rem# hasBlackBox #-} rem# (U i) (U j) = U (i `rem` j)  {-# NOINLINE toInteger# #-}+{-# ANN toInteger# hasBlackBox #-} toInteger# :: Unsigned n -> Integer toInteger# (U i) = naturalToInteger i @@ -477,51 +520,59 @@   popCount u        = popCount (pack# u)  {-# NOINLINE and# #-}+{-# ANN and# hasBlackBox #-} and# :: Unsigned n -> Unsigned n -> Unsigned n and# (U v1) (U v2) = U (v1 .&. v2)  {-# NOINLINE or# #-}+{-# ANN or# hasBlackBox #-} or# :: Unsigned n -> Unsigned n -> Unsigned n or# (U v1) (U v2) = U (v1 .|. v2)  {-# NOINLINE xor# #-}+{-# ANN xor# hasBlackBox #-} xor# :: Unsigned n -> Unsigned n -> Unsigned n xor# (U v1) (U v2) = U (v1 `xor` v2)  {-# NOINLINE 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 {-# NOINLINE shiftL# #-}-shiftL# =-  \(U v) i ->-    if i >= 0 then-#if MIN_VERSION_base-      U ((naturalShiftL v i) `mod` m)-#else-      U ((shiftL v i) `mod` m)-#endif-    else-      error ("'shiftL undefined for negative number: " ++ show i)- where+{-# ANN shiftL# hasBlackBox #-}+shiftL# = \(U v) i -> #if MIN_VERSION_base(4,15,0)-  m = 1 `naturalShiftL` naturalToWord (natVal (Proxy @n))+  let i' = fromIntegral i in+  if | i < 0     -> error $ "'shiftL' undefined for negative number: " ++ show i+     | i' >= sz  -> U 0+     | otherwise -> U ((naturalShiftL v i') `mod` m)+ where+  sz = naturalToWord (natVal (Proxy @n))+  m  = 1 `naturalShiftL` sz #else-  m = 1 `shiftL` fromInteger (natVal (Proxy @n))+  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  {-# NOINLINE shiftR# #-}+{-# ANN shiftR# hasBlackBox #-} -- shiftR# doesn't need the KnownNat constraint -- But having the same type signature for all shift and rotate functions -- makes implementing the Evaluator easier. shiftR# (U v) i   | i < 0     = error-              $ "'shiftR undefined for negative number: " ++ show i+              $ "'shiftR' undefined for negative number: " ++ show i   | otherwise = U (shiftR v i)  {-# NOINLINE rotateL# #-}+{-# ANN rotateL# hasBlackBox #-} rotateL# =   \(U n) b ->     if b >= 0 then@@ -537,7 +588,7 @@           b'' = sz - b'       in  U ((l .|. r) `mod` m)     else-      error "'rotateL undefined for negative numbers"+      error $ "'rotateL' undefined for negative number: " ++ show b   where #if MIN_VERSION_base(4,15,0)     sz = naturalToWord (natVal (Proxy @n))@@ -548,6 +599,7 @@ #endif  {-# NOINLINE rotateR# #-}+{-# ANN rotateR# hasBlackBox #-} rotateR# =   \(U n) b ->     if b >= 0 then@@ -563,7 +615,7 @@           b'' = sz - b'       in  U ((l .|. r) `mod` m)     else-      error "'rotateR undefined for negative numbers"+      error $ "'rotateR' undefined for negative number: " ++ show b   where #if MIN_VERSION_base(4,15,0)     sz = naturalToWord (natVal (Proxy @n))@@ -585,6 +637,7 @@   truncateB  = resize#  {-# NOINLINE 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)@@ -618,6 +671,11 @@     in  case msb r of           0 -> resize# r           _ -> minBound#+  satAdd SatError a b =+    let r = plus# a b+    in  case msb r of+          0 -> resize# r+          _ -> errorX "Unsigned.satAdd: overflow"   satAdd _ a b =     let r  = plus# a b     in  case msb r of@@ -625,6 +683,11 @@           _ -> maxBound#    satSub SatWrap a b = a -# b+  satSub SatError a b =+    let r = minus# a b+    in  case msb r of+          0 -> resize# r+          _ -> errorX "Unsigned.satSub: underflow"   satSub _ a b =     let r = minus# a b     in  case msb r of@@ -638,6 +701,12 @@     in  case rL of           0 -> unpack# rR           _ -> minBound#+  satMul SatError a b =+    let r       = times# a b+        (rL,rR) = split r+    in  case rL of+          0 -> unpack# rR+          _ -> errorX "Unsigned.satMul: overflow"   satMul _ a b =     let r       = times# a b         (rL,rR) = split r@@ -645,6 +714,19 @@           0 -> unpack# rR           _ -> maxBound# +  -- Implementations for satSucc and satPred are needed because 1 :: Unsigned 0+  -- overflows to 0, meaning without the first check SatError would return 0.++  satSucc SatError a+    | a == maxBound = errorX "Unsigned.satSucc: overflow"+  satSucc satMode a = satAdd satMode a 1+  {-# INLINE satSucc #-}++  satPred SatError a+    | a == minBound = errorX "Unsigned.satPred: underflow"+  satPred satMode a = satSub satMode a 1+  {-# INLINE satPred #-}+ instance KnownNat n => Arbitrary (Unsigned n) where   arbitrary = arbitraryBoundedIntegral   shrink    = BV.shrinkSizedUnsigned@@ -674,6 +756,7 @@ unsignedToWord (U (NatJ# u#)) = W# (bigNatToWord u#) #endif {-# NOINLINE unsignedToWord #-}+{-# ANN unsignedToWord hasBlackBox #-}  unsigned8toWord8 :: Unsigned 8 -> Word8 #if MIN_VERSION_base(4,15,0)@@ -684,6 +767,7 @@ unsigned8toWord8 (U (NatJ# u#)) = W8# (narrow8Word# (bigNatToWord u#)) #endif {-# NOINLINE unsigned8toWord8 #-}+{-# ANN unsigned8toWord8 hasBlackBox #-}  unsigned16toWord16 :: Unsigned 16 -> Word16 #if MIN_VERSION_base(4,15,0)@@ -694,6 +778,7 @@ unsigned16toWord16 (U (NatJ# u#)) = W16# (narrow16Word# (bigNatToWord u#)) #endif {-# NOINLINE unsigned16toWord16 #-}+{-# ANN unsigned16toWord16 hasBlackBox #-}  unsigned32toWord32 :: Unsigned 32 -> Word32 #if MIN_VERSION_base(4,15,0)@@ -704,6 +789,7 @@ unsigned32toWord32 (U (NatJ# u#)) = W32# (narrow32Word# (bigNatToWord u#)) #endif {-# NOINLINE unsigned32toWord32 #-}+{-# ANN unsigned32toWord32 hasBlackBox #-}  {-# RULES "bitCoerce/Unsigned WORD_SIZE_IN_BITS -> Word" bitCoerce = unsignedToWord
src/Clash/Sized/RTree.hs view
@@ -1,7 +1,8 @@ {-| Copyright  :  (C) 2016, University of Twente+                  2022, QBayLogic B.V. License    :  BSD2 (see the file LICENSE)-Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com> -}  {-# LANGUAGE CPP #-}@@ -65,6 +66,7 @@ import Prelude                     hiding ((++), (!!)) import Test.QuickCheck             (Arbitrary (..), CoArbitrary (..)) +import Clash.Annotations.Primitive (hasBlackBox) import Clash.Class.BitPack         (BitPack (..), packXWith) import Clash.Promoted.Nat          (SNat (..), UNat (..), pow2SNat, snatToNum,                                     subSNat, toUNat)@@ -114,11 +116,13 @@ textract (LR_ x)   = x textract (BR_ _ _) = error $ "textract: nodes hold no values" {-# NOINLINE textract #-}+{-# ANN textract hasBlackBox #-}  tsplit :: RTree (d+1) a -> (RTree d a,RTree d a) tsplit (BR_ l r) = (l,r) tsplit (LR_ _)   = error $ "tsplit: leaf is atomic" {-# NOINLINE tsplit #-}+{-# ANN tsplit hasBlackBox #-}  -- | Leaf of a perfect depth tree --@@ -370,6 +374,7 @@     go sn (BR_ l r) = let sn' = sn `subSNat` d1                       in  g sn' (go sn' l) (go sn' r) {-# NOINLINE tdfold #-}+{-# ANN tdfold hasBlackBox #-}  data TfoldTree (a :: Type) (f :: TyFun Nat Type) :: Type type instance Apply (TfoldTree a) d = a@@ -398,6 +403,7 @@     go UZero      = LR a     go (USucc un) = BR (go un) (go un) {-# NOINLINE treplicate #-}+{-# ANN treplicate hasBlackBox #-}  -- | \"'trepeat' @a@\" creates a tree with as many copies of /a/ as demanded by -- the context.@@ -434,7 +440,7 @@ -- | Convert a vector with /2^d/ elements to a tree of depth /d/. -- -- >>> (1:>2:>3:>4:>Nil)--- <1,2,3,4>+-- 1 :> 2 :> 3 :> 4 :> Nil -- >>> v2t (1:>2:>3:>4:>Nil) -- <<1,2>,<3,4>> v2t :: forall d a . KnownNat d => Vec (2^d) a -> RTree d a@@ -448,7 +454,7 @@ -- >>> (BR (BR (LR 1) (LR 2)) (BR (LR 3) (LR 4))) -- <<1,2>,<3,4>> -- >>> t2v (BR (BR (LR 1) (LR 2)) (BR (LR 3) (LR 4)))--- <1,2,3,4>+-- 1 :> 2 :> 3 :> 4 :> Nil t2v :: forall d a . KnownNat d => RTree d a -> Vec (2^d) a t2v = tdfold (Proxy @(T2VTree a)) (:> Nil) (\_ l r -> l ++ r) 
src/Clash/Sized/Vector.hs view
@@ -1,19 +1,21 @@ {-| Copyright  :  (C) 2013-2016, University of Twente,                   2017     , Myrtle Software Ltd+                  2022     , QBayLogic 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 FlexibleInstances #-} {-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE QuasiQuotes #-}  {-# LANGUAGE Trustworthy #-} @@ -42,12 +44,12 @@   , splitAt, splitAtI   , unconcat, unconcatI     -- * Construction-    -- ** Initialisation+    -- ** Initialization   , singleton   , replicate, repeat   , iterate, iterateI, generate, generateI   , unfoldr, unfoldrI-    -- *** Initialisation from a list+    -- *** Initialization from a list   , listToVecTH     -- ** Concatenation   , (++), (+>>), (<<+), concat, concatMap@@ -57,7 +59,7 @@   , replace     -- ** Permutations   , permute, backpermute, scatter, gather-    -- *** Specialised permutations+    -- *** Specialized permutations   , reverse, transpose, interleave   , rotateLeft, rotateRight, rotateLeftS, rotateRightS     -- * Element-wise operations@@ -72,7 +74,7 @@     -- * Folding   , foldr, foldl, foldr1, foldl1, fold   , ifoldr, ifoldl-    -- ** Specialised folds+    -- ** Specialized folds   , dfold, dtfold, vfold     -- * Prefix sums (scans)   , scanl, scanr, postscanl, postscanr@@ -134,7 +136,7 @@ import Unsafe.Coerce              (unsafeCoerce)  import Clash.Annotations.Primitive-  (Primitive(InlinePrimitive), HDL(..), dontTranslate)+  (Primitive(InlinePrimitive), HDL(..), dontTranslate, hasBlackBox) import Clash.Promoted.Nat   (SNat (..), SNatLE (..), UNat (..), compareSNat, leToPlus, pow2SNat,    snatProxy, snatToInteger, subSNat, withSNat, toUNat, natToInteger)@@ -143,66 +145,21 @@ import Clash.Sized.Index          (Index)  import Clash.Class.BitPack        (packXWith, BitPack (..))-import Clash.XException-  (ShowX (..), NFDataX (..), showsX, seqX, isX)+import Clash.XException           (ShowX (..), NFDataX (..), seqX, isX)  {- $setup->>> :set -XDataKinds >>> :set -XTypeFamilies >>> :set -XTypeOperators >>> :set -XTemplateHaskell >>> :set -XFlexibleContexts->>> :set -XTypeApplications->>> :set -fplugin GHC.TypeLits.Normalise+>>> :m -Prelude >>> import Clash.Prelude->>> import Data.Kind->>> import Data.Proxy >>> import qualified Clash.Sized.Vector as Vec->>> 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 sortV_flip xs = map fst sorted :< (snd (last sorted))-      where-        lefts  = head xs :> map snd (init sorted)-        rights = tail xs-        sorted = zipWith (flip compareSwapL) rights lefts-:}-->>> 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->>> let compareSwap a b = if a > b then (a,b) else (b,a)->>> let insert y xs     = let (y',xs') = mapAccumL compareSwap y xs in xs' :< y'->>> let insertionSort   = vfold (const insert)->>> data IIndex (f :: TyFun Nat Type) :: Type->>> :set -XUndecidableInstances->>> type instance Apply IIndex l = Index ((2^l)+1)->>> :{-let populationCount' :: (KnownNat k, KnownNat (2^k)) => BitVector (2^k) -> Index ((2^k)+1)-    populationCount' bv = dtfold (Proxy @IIndex)-                                 fromIntegral-                                 (\_ x y -> add x y)-                                 (bv2v bv)-:}- -} -infixr 5 `Cons`+#define CONS_PREC 5++infixr CONS_PREC `Cons` -- | Fixed size vectors. -- -- * Lists with their length encoded in their type@@ -277,7 +234,7 @@ -- | Add an element to the head of a vector. -- -- >>> 3:>4:>5:>Nil--- <3,4,5>+-- 3 :> 4 :> 5 :> Nil -- >>> let x = 3:>4:>5:>Nil -- >>> :t x -- x :: Num a => Vec 3 a@@ -302,24 +259,35 @@   where     (:>) x xs = Cons x xs -infixr 5 :>+infixr CONS_PREC :>  instance Show a => Show (Vec n a) where-  showsPrec _ vs = \s -> '<':punc vs ('>':s)-    where-      punc :: Vec m a -> ShowS-      punc Nil            = id-      punc (x `Cons` Nil) = shows x-      punc (x `Cons` xs)  = \s -> shows x (',':punc xs s)+  showsPrec n = \case+    Nil -> showString "Nil"+    vs -> showParen (n > CONS_PREC) (go vs) +   where+    go :: Vec m a -> ShowS+    go Nil = showString "Nil"+    go (x `Cons` xs) =+        showsPrec (CONS_PREC + 1) x+      . showString " :> "+      . go xs+ instance ShowX a => ShowX (Vec n a) where-  showsPrecX _n vs = showString "<" . punc vs+  showsPrecX n vs =+    case isX vs of+      Right Nil -> showString "Nil"+      Left _ -> showString "undefined"+      _ -> showParen (n > CONS_PREC) (go vs)    where-    punc :: Vec m a -> ShowS-    punc (isX -> Left _) = showString "X"-    punc Nil = showString ">"-    punc (Cons x (isX -> Right Nil)) = showsX x . ('>':)-    punc (Cons x xs) = showsX x . showString "," . punc xs+    go :: Vec m a -> ShowS+    go (isX -> Left _) = showString "undefined"+    go Nil = showString "Nil"+    go (x `Cons` xs) =+        showsPrecX (CONS_PREC + 1) x+      . showString " :> "+      . go xs  instance (KnownNat n, Eq a) => Eq (Vec n a) where   (==) Nil _            = True@@ -367,6 +335,7 @@   traverse = traverse#  {-# NOINLINE 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 traverse# f (x `Cons` xs) = Cons <$> f x <*> traverse# f xs@@ -396,11 +365,12 @@ -- | Create a vector of one element -- -- >>> singleton 5--- <5>+-- 5 :> Nil singleton :: a -> Vec 1 a singleton = (`Cons` Nil)  {-# NOINLINE head #-}+{-# ANN head hasBlackBox #-} {- | Extract the first element of a vector  >>> head (1:>2:>3:>Nil)@@ -434,10 +404,11 @@ head (x `Cons` _) = x  {-# NOINLINE tail #-}+{-# ANN tail hasBlackBox #-} {- | Extract the elements after the head of a vector  >>> tail (1:>2:>3:>Nil)-<2,3>+2 :> 3 :> Nil  #if __GLASGOW_HASKELL__ >= 900 >>> tail Nil@@ -467,6 +438,7 @@ tail (_ `Cons` xs) = xs  {-# NOINLINE last #-}+{-# ANN last hasBlackBox #-} {- | Extract the last element of a vector  >>> last (1:>2:>3:>Nil)@@ -501,10 +473,11 @@ last (_ `Cons` y `Cons` ys) = last (y `Cons` ys)  {-# NOINLINE init #-}+{-# ANN init hasBlackBox #-} {- | Extract all the elements of a vector except the last element  >>> init (1:>2:>3:>Nil)-<1,2>+1 :> 2 :> Nil  #if __GLASGOW_HASKELL__ >= 900 >>> init Nil@@ -542,9 +515,9 @@ -- * The shifted out elements -- -- >>> shiftInAt0 (1 :> 2 :> 3 :> 4 :> Nil) ((-1) :> 0 :> Nil)--- (<-1,0,1,2>,<3,4>)+-- (-1 :> 0 :> 1 :> 2 :> Nil,3 :> 4 :> Nil) -- >>> shiftInAt0 (1 :> Nil) ((-1) :> 0 :> Nil)--- (<-1>,<0,1>)+-- (-1 :> Nil,0 :> 1 :> Nil) shiftInAt0 :: KnownNat n            => Vec n a -- ^ The old vector            -> Vec m a -- ^ The elements to shift in at the head@@ -561,9 +534,9 @@ -- * The shifted out elements -- -- >>> shiftInAtN (1 :> 2 :> 3 :> 4 :> Nil) (5 :> 6 :> Nil)--- (<3,4,5,6>,<1,2>)+-- (3 :> 4 :> 5 :> 6 :> Nil,1 :> 2 :> Nil) -- >>> shiftInAtN (1 :> Nil) (2 :> 3 :> Nil)--- (<3>,<1,2>)+-- (3 :> Nil,1 :> 2 :> Nil) shiftInAtN :: KnownNat m            => Vec n a -- ^ The old vector            -> Vec m a -- ^ The elements to shift in at the tail@@ -577,7 +550,7 @@ -- | Add an element to the tail of a vector. -- -- >>> (3:>4:>5:>Nil) :< 1--- <3,4,5,1>+-- 3 :> 4 :> 5 :> 1 :> Nil -- >>> let x = (3:>4:>5:>Nil) :< 1 -- >>> :t x -- x :: Num a => Vec 4 a@@ -607,9 +580,9 @@ -- element. -- -- >>> 1 +>> (3:>4:>5:>Nil)--- <1,3,4>+-- 1 :> 3 :> 4 :> Nil -- >>> 1 +>> Nil--- <>+-- Nil (+>>) :: KnownNat n => a -> Vec n a -> Vec n a s +>> xs = fst (shiftInAt0 xs (singleton s)) {-# INLINE (+>>) #-}@@ -620,9 +593,9 @@ -- element. -- -- >>> (3:>4:>5:>Nil) <<+ 1--- <4,5,1>+-- 4 :> 5 :> 1 :> Nil -- >>> Nil <<+ 1--- <>+-- Nil (<<+) :: Vec n a -> a -> Vec n a xs <<+ s = fst (shiftInAtN xs (singleton s)) {-# INLINE (<<+) #-}@@ -634,7 +607,7 @@ -- * The shifted out values -- -- >>> shiftOutFrom0 d2 ((1 :> 2 :> 3 :> 4 :> 5 :> Nil) :: Vec 5 Integer)--- (<3,4,5,0,0>,<1,2>)+-- (3 :> 4 :> 5 :> 0 :> 0 :> Nil,1 :> 2 :> Nil) shiftOutFrom0 :: (Default a, KnownNat m)               => SNat m        -- ^ @m@, the number of elements to shift out               -> Vec (m + n) a -- ^ The old vector@@ -650,7 +623,7 @@ -- * The shifted out values -- -- >>> shiftOutFromN d2 ((1 :> 2 :> 3 :> 4 :> 5 :> Nil) :: Vec 5 Integer)--- (<0,0,1,2,3>,<4,5>)+-- (0 :> 0 :> 1 :> 2 :> 3 :> Nil,4 :> 5 :> Nil) shiftOutFromN :: (Default a, KnownNat n)               => SNat m        -- ^ @m@, the number of elements to shift out               -> Vec (m + n) a -- ^ The old vector@@ -663,21 +636,23 @@ -- | Append two vectors. -- -- >>> (1:>2:>3:>Nil) ++ (7:>8:>Nil)--- <1,2,3,7,8>+-- 1 :> 2 :> 3 :> 7 :> 8 :> Nil (++) :: Vec n a -> Vec m a -> Vec (n + m) a Nil           ++ ys = ys (x `Cons` xs) ++ ys = x `Cons` xs ++ ys {-# NOINLINE (++) #-}+{-# ANN (++) hasBlackBox #-}  -- | Split a vector into two vectors at the given point. -- -- >>> splitAt (SNat :: SNat 3) (1:>2:>3:>7:>8:>Nil)--- (<1,2,3>,<7,8>)+-- (1 :> 2 :> 3 :> Nil,7 :> 8 :> Nil) -- >>> splitAt d3 (1:>2:>3:>7:>8:>Nil)--- (<1,2,3>,<7,8>)+-- (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 {-# NOINLINE splitAt #-}+{-# ANN splitAt hasBlackBox #-}  splitAtU :: UNat m -> Vec (m + n) a -> (Vec m a, Vec n a) splitAtU UZero     ys            = (Nil,ys)@@ -688,7 +663,7 @@ -- by the context. -- -- >>> splitAtI (1:>2:>3:>7:>8:>Nil) :: (Vec 2 Int, Vec 3 Int)--- (<1,2>,<3,7,8>)+-- (1 :> 2 :> Nil,3 :> 7 :> 8 :> Nil) splitAtI :: KnownNat m => Vec (m + n) a -> (Vec m a, Vec n a) splitAtI = withSNat splitAt {-# INLINE splitAtI #-}@@ -696,16 +671,17 @@ -- | Concatenate a vector of vectors. -- -- >>> concat ((1:>2:>3:>Nil) :> (4:>5:>6:>Nil) :> (7:>8:>9:>Nil) :> (10:>11:>12:>Nil) :> Nil)--- <1,2,3,4,5,6,7,8,9,10,11,12>+-- 1 :> 2 :> 3 :> 4 :> 5 :> 6 :> 7 :> 8 :> 9 :> 10 :> 11 :> 12 :> Nil concat :: Vec n (Vec m a) -> Vec (n * m) a concat Nil           = Nil concat (x `Cons` xs) = x ++ concat xs {-# NOINLINE concat #-}+{-# ANN concat hasBlackBox #-}  -- | Map a function over all the elements of a vector and concatentate the resulting vectors. -- -- >>> concatMap (replicate d3) (1:>2:>3:>Nil)--- <1,1,1,2,2,2,3,3,3>+-- 1 :> 1 :> 1 :> 2 :> 2 :> 2 :> 3 :> 3 :> 3 :> Nil concatMap :: (a -> Vec m b) -> Vec n a -> Vec (n * m) b concatMap f xs = concat (map f xs) {-# INLINE concatMap #-}@@ -714,10 +690,11 @@ -- /m/\", where the length /m/ is given. -- -- >>> unconcat d4 (1:>2:>3:>4:>5:>6:>7:>8:>9:>10:>11:>12:>Nil)--- <<1,2,3,4>,<5,6,7,8>,<9,10,11,12>>+-- (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 {-# NOINLINE unconcat #-}+{-# ANN unconcat hasBlackBox #-}  unconcatU :: UNat n -> UNat m -> Vec (n * m) a -> Vec n (Vec m a) unconcatU UZero      _ _  = Nil@@ -728,7 +705,7 @@ -- /m/\", where the length /m/ is determined by the context. -- -- >>> unconcatI (1:>2:>3:>4:>5:>6:>7:>8:>9:>10:>11:>12:>Nil) :: Vec 2 (Vec 6 Int)--- <<1,2,3,4,5,6>,<7,8,9,10,11,12>>+-- (1 :> 2 :> 3 :> 4 :> 5 :> 6 :> Nil) :> (7 :> 8 :> 9 :> 10 :> 11 :> 12 :> Nil) :> Nil unconcatI :: (KnownNat n, KnownNat m) => Vec (n * m) a -> Vec n (Vec m a) unconcatI = withSNat unconcat {-# INLINE unconcatI #-}@@ -736,7 +713,7 @@ -- | Merge two vectors, alternating their elements, i.e., -- -- >>> merge (1 :> 2 :> 3 :> 4 :> Nil) (5 :> 6 :> 7 :> 8 :> Nil)--- <1,5,2,6,3,7,4,8>+-- 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)) {-# INLINE merge #-}@@ -744,11 +721,12 @@ -- | The elements in a vector in reverse order. -- -- >>> reverse (1:>2:>3:>4:>Nil)--- <4,3,2,1>+-- 4 :> 3 :> 2 :> 1 :> Nil reverse :: Vec n a -> Vec n a reverse Nil           = Nil reverse (x `Cons` xs) = reverse xs :< x {-# NOINLINE reverse #-}+{-# ANN reverse hasBlackBox #-}  -- | \"'map' @f xs@\" is the vector obtained by applying /f/ to each element -- of /xs/, i.e.,@@ -762,16 +740,17 @@ map _ Nil           = Nil map f (x `Cons` xs) = f x `Cons` map f xs {-# NOINLINE map #-}+{-# ANN map hasBlackBox #-}  -- | Apply a function of every element of a vector and its index. -- -- >>> :t imap (+) (2 :> 2 :> 2 :> 2 :> Nil) -- imap (+) (2 :> 2 :> 2 :> 2 :> Nil) :: Vec 4 (Index 4) -- >>> imap (+) (2 :> 2 :> 2 :> 2 :> Nil)--- <2,3,*** Exception: X: Clash.Sized.Index: result 4 is out of bounds: [0..3]+-- 2 :> 3 :> *** Exception: X: Clash.Sized.Index: result 4 is out of bounds: [0..3] -- ... -- >>> imap (\i a -> fromIntegral i + a) (2 :> 2 :> 2 :> 2 :> Nil) :: Vec 4 (Unsigned 8)--- <2,3,4,5>+-- 2 :> 3 :> 4 :> 5 :> Nil -- -- \"'imap' @f xs@\" corresponds to the following circuit layout: --@@ -779,24 +758,26 @@ imap :: forall n a b . KnownNat n => (Index n -> a -> b) -> Vec n a -> Vec n b imap f = go 0   where+    -- NOTE This has a black box called imap_go     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 {-# NOINLINE imap #-}+{-# ANN imap hasBlackBox #-}  {- | Zip two vectors with a functions that also takes the elements' indices.  #if __GLASGOW_HASKELL__ >= 900 >>> izipWith (\i a b -> i + a + b) (2 :> 2 :> Nil)  (3 :> 3:> Nil)-<*** Exception: X: Clash.Sized.Index: result 2 is out of bounds: [0..1]+*** Exception: X: Clash.Sized.Index: result 2 is out of bounds: [0..1] ... #else >>> izipWith (\i a b -> i + a + b) (2 :> 2 :> Nil)  (3 :> 3:> Nil)-<*** Exception: X: Clash.Sized.Index: result 3 is out of bounds: [0..1]+*** Exception: X: Clash.Sized.Index: result 3 is out of bounds: [0..1] ... #endif >>> izipWith (\i a b -> fromIntegral i + a + b) (2 :> 2 :> Nil) (3 :> 3 :> Nil) :: Vec 2 (Unsigned 8)-<5,6>+5 :> 6 :> Nil  \"'imap' @f xs@\" corresponds to the following circuit layout: @@ -848,7 +829,7 @@ -- | Generate a vector of indices. -- -- >>> indices d4--- <0,1,2,3>+-- 0 :> 1 :> 2 :> 3 :> Nil indices :: KnownNat n => SNat n -> Vec n (Index n) indices _ = indicesI {-# INLINE indices #-}@@ -857,7 +838,7 @@ -- by the context. -- -- >>> indicesI :: Vec 4 (Index 4)--- <0,1,2,3>+-- 0 :> 1 :> 2 :> 3 :> Nil indicesI :: KnownNat n => Vec n (Index n) indicesI = imap const (repeat ()) {-# INLINE indicesI #-}@@ -903,6 +884,7 @@ zipWith _ Nil           _  = Nil zipWith f (x `Cons` xs) ys = f x (head ys) `Cons` zipWith f xs (tail ys) {-# NOINLINE zipWith #-}+{-# ANN zipWith hasBlackBox #-}  -- | 'zipWith3' generalizes 'zip3' by zipping with the function given -- as the first argument, instead of a tupling function.@@ -1012,6 +994,7 @@ foldr _ z Nil           = z foldr f z (x `Cons` xs) = f x (foldr f z xs) {-# NOINLINE foldr #-}+{-# ANN foldr hasBlackBox #-}  -- | 'foldl', applied to a binary operator, a starting value (typically -- the left-identity of the operator), and a vector, reduces the vector@@ -1113,7 +1096,7 @@ -- > scanl f z (x1 :> x2 :> ... :> Nil) == z :> (z `f` x1) :> ((z `f` x1) `f` x2) :> ... :> Nil -- -- >>> scanl (+) 0 (5 :> 4 :> 3 :> 2 :> Nil)--- <0,5,9,12,14>+-- 0 :> 5 :> 9 :> 12 :> 14 :> Nil -- -- \"'scanl' @f z xs@\" corresponds to the following circuit layout: --@@ -1133,7 +1116,7 @@ -- > postscanl f z (x1 :> x2 :> ... :> Nil) == (z `f` x1) :> ((z `f` x1) `f` x2) :> ... :> Nil -- -- >>> postscanl (+) 0 (5 :> 4 :> 3 :> 2 :> Nil)--- <5,9,12,14>+-- 5 :> 9 :> 12 :> 14 :> Nil -- -- \"'postscanl' @f z xs@\" corresponds to the following circuit layout: --@@ -1148,7 +1131,7 @@ -- > scanr f z (... :> xn1 :> xn :> Nil) == ... :> (xn1 `f` (xn `f` z)) :> (xn `f` z) :> z :> Nil -- -- >>> scanr (+) 0 (5 :> 4 :> 3 :> 2 :> Nil)--- <14,9,5,2,0>+-- 14 :> 9 :> 5 :> 2 :> 0 :> Nil -- -- \"'scanr' @f z xs@\" corresponds to the following circuit layout: --@@ -1168,7 +1151,7 @@ -- > postscanr f z (... :> xn1 :> xn :> Nil) == ... :> (xn1 `f` (xn `f` z)) :> (xn `f` z) :> Nil -- -- >>> postscanr (+) 0 (5 :> 4 :> 3 :> 2 :> Nil)--- <14,9,5,2>+-- 14 :> 9 :> 5 :> 2 :> Nil -- -- \"'postscanr' @f z xs@\" corresponds to the following circuit layout: --@@ -1183,7 +1166,7 @@ -- together with the new vector. -- -- >>> mapAccumL (\acc x -> (acc + x,acc + 1)) 0 (1 :> 2 :> 3 :> 4 :> Nil)--- (10,<1,2,4,7>)+-- (10,1 :> 2 :> 4 :> 7 :> Nil) -- -- \"'mapAccumL' @f acc xs@\" corresponds to the following circuit layout: --@@ -1204,7 +1187,7 @@ -- together with the new vector. -- -- >>> mapAccumR (\acc x -> (acc + x,acc + 1)) 0 (1 :> 2 :> 3 :> 4 :> Nil)--- (10,<10,8,5,1>)+-- (10,10 :> 8 :> 5 :> 1 :> Nil) -- -- \"'mapAccumR' @f acc xs@\" corresponds to the following circuit layout: --@@ -1222,7 +1205,7 @@ -- | 'zip' takes two vectors and returns a vector of corresponding pairs. -- -- >>> zip (1:>2:>3:>4:>Nil) (4:>3:>2:>1:>Nil)--- <(1,4),(2,3),(3,2),(4,1)>+-- (1,4) :> (2,3) :> (3,2) :> (4,1) :> Nil zip :: Vec n a -> Vec n b -> Vec n (a,b) zip = zipWith (,) {-# INLINE zip #-}@@ -1230,7 +1213,7 @@ -- | 'zip3' takes three vectors and returns a vector of corresponding triplets. -- -- >>> zip3 (1:>2:>3:>4:>Nil) (4:>3:>2:>1:>Nil) (5:>6:>7:>8:>Nil)--- <(1,4,5),(2,3,6),(3,2,7),(4,1,8)>+-- (1,4,5) :> (2,3,6) :> (3,2,7) :> (4,1,8) :> Nil zip3 :: Vec n a -> Vec n b -> Vec n c -> Vec n (a,b,c) zip3 = zipWith3 (,,) {-# INLINE zip3 #-}@@ -1278,7 +1261,7 @@ -- and a vector of second components. -- -- >>> unzip ((1,4):>(2,3):>(3,2):>(4,1):>Nil)--- (<1,2,3,4>,<4,3,2,1>)+-- (1 :> 2 :> 3 :> 4 :> Nil,4 :> 3 :> 2 :> 1 :> Nil) unzip :: Vec n (a,b) -> (Vec n a, Vec n b) unzip xs = (map fst xs, map snd xs) {-# INLINE unzip #-}@@ -1287,7 +1270,7 @@ -- a vector of second components, and a vector of third components. -- -- >>> unzip3 ((1,4,5):>(2,3,6):>(3,2,7):>(4,1,8):>Nil)--- (<1,2,3,4>,<4,3,2,1>,<5,6,7,8>)+-- (1 :> 2 :> 3 :> 4 :> Nil,4 :> 3 :> 2 :> 1 :> Nil,5 :> 6 :> 7 :> 8 :> Nil) unzip3 :: Vec n (a,b,c) -> (Vec n a, Vec n b, Vec n c) unzip3 xs = ( map (\(x,_,_) -> x) xs             , map (\(_,y,_) -> y) xs@@ -1361,6 +1344,7 @@                                 then y                                 else sub ys (n -# 1#) {-# NOINLINE index_int #-}+{-# ANN index_int hasBlackBox #-}  -- | \"@xs@ '!!' @n@\" returns the /n/'th element of /xs/. --@@ -1387,6 +1371,7 @@ length :: KnownNat n => Vec n a -> Int length = fromInteger . natVal . asNatProxy {-# NOINLINE length #-}+{-# ANN length hasBlackBox #-}  replace_int :: KnownNat n => Vec n a -> Int -> a -> Vec n a replace_int xs i@(I# n0) a@@ -1403,6 +1388,7 @@                                  then b `Cons` ys                                  else y `Cons` sub ys (n -# 1#) b {-# NOINLINE replace_int #-}+{-# ANN replace_int hasBlackBox #-}  -- | \"'replace' @n a xs@\" returns the vector /xs/ where the /n/'th element is -- replaced by /a/.@@ -1411,11 +1397,11 @@ -- ending at @'length' - 1@. -- -- >>> replace 3 7 (1:>2:>3:>4:>5:>Nil)--- <1,2,3,7,5>+-- 1 :> 2 :> 3 :> 7 :> 5 :> Nil -- >>> replace 0 7 (1:>2:>3:>4:>5:>Nil)--- <7,2,3,4,5>+-- 7 :> 2 :> 3 :> 4 :> 5 :> Nil -- >>> replace 9 7 (1:>2:>3:>4:>5:>Nil)--- <1,2,3,4,*** 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 larger than maximum index 4 -- ... replace :: (KnownNat n, Enum i) => i -> a -> Vec n a -> Vec n a replace i y xs = replace_int xs (fromEnum i) y@@ -1424,11 +1410,11 @@ {- | \"'take' @n xs@\" returns the /n/-length prefix of /xs/.  >>> take (SNat :: SNat 3) (1:>2:>3:>4:>5:>Nil)-<1,2,3>+1 :> 2 :> 3 :> Nil >>> take d3               (1:>2:>3:>4:>5:>Nil)-<1,2,3>+1 :> 2 :> 3 :> Nil >>> take d0               (1:>2:>Nil)-<>+Nil  #if __GLASGOW_HASKELL__ >= 900 >>> take d4               (1:>2:>Nil)@@ -1463,7 +1449,7 @@ -- | \"'takeI' @xs@\" returns the prefix of /xs/ as demanded by the context. -- -- >>> takeI (1:>2:>3:>4:>5:>Nil) :: Vec 2 Int--- <1,2>+-- 1 :> 2 :> Nil takeI :: KnownNat m => Vec (m + n) a -> Vec m a takeI = withSNat take {-# INLINE takeI #-}@@ -1471,11 +1457,11 @@ -- | \"'drop' @n xs@\" returns the suffix of /xs/ after the first /n/ elements. -- -- >>> drop (SNat :: SNat 3) (1:>2:>3:>4:>5:>Nil)--- <4,5>+-- 4 :> 5 :> Nil -- >>> drop d3               (1:>2:>3:>4:>5:>Nil)--- <4,5>+-- 4 :> 5 :> Nil -- >>> drop d0               (1:>2:>Nil)--- <1,2>+-- 1 :> 2 :> Nil -- >>> drop d4               (1:>2:>Nil) -- <BLANKLINE> -- <interactive>:...: error:@@ -1490,7 +1476,7 @@ -- | \"'dropI' @xs@\" returns the suffix of /xs/ as demanded by the context. -- -- >>> dropI (1:>2:>3:>4:>5:>Nil) :: Vec 2 Int--- <4,5>+-- 4 :> 5 :> Nil dropI :: KnownNat m => Vec (m + n) a -> Vec n a dropI = withSNat drop {-# INLINE dropI #-}@@ -1512,9 +1498,9 @@ -- offset @f@ from /xs/. -- -- >>> select (SNat :: SNat 1) (SNat :: SNat 2) (SNat :: SNat 3) (1:>2:>3:>4:>5:>6:>7:>8:>Nil)--- <2,4,6>+-- 2 :> 4 :> 6 :> Nil -- >>> select d1 d2 d3 (1:>2:>3:>4:>5:>6:>7:>8:>Nil)--- <2,4,6>+-- 2 :> 4 :> 6 :> Nil select :: (CmpNat (i + s) (s * n) ~ 'GT)        => SNat f        -> SNat s@@ -1528,12 +1514,13 @@     select' (USucc n') vs@(x `Cons` _) = x `Cons`                                          select' n' (drop s (unsafeCoerce vs)) {-# NOINLINE select #-}+{-# ANN select hasBlackBox #-}  -- | \"'selectI' @f s xs@\" selects as many elements as demanded by the context -- with step-size /s/ and offset /f/ from /xs/. -- -- >>> selectI d1 d2 (1:>2:>3:>4:>5:>6:>7:>8:>Nil) :: Vec 2 Int--- <2,4>+-- 2 :> 4 :> Nil selectI :: (CmpNat (i + s) (s * n) ~ 'GT, KnownNat n)         => SNat f         -> SNat s@@ -1545,12 +1532,13 @@ -- | \"'replicate' @n a@\" returns a vector that has /n/ copies of /a/. -- -- >>> replicate (SNat :: SNat 3) 6--- <6,6,6>+-- 6 :> 6 :> 6 :> Nil -- >>> replicate d3 6--- <6,6,6>+-- 6 :> 6 :> 6 :> Nil replicate :: SNat n -> a -> Vec n a replicate n a = replicateU (toUNat n) a {-# NOINLINE replicate #-}+{-# ANN replicate hasBlackBox #-}  replicateU :: UNat n -> a -> Vec n a replicateU UZero     _ = Nil@@ -1560,7 +1548,7 @@ -- by the context. -- -- >>> repeat 6 :: Vec 5 Int--- <6,6,6,6,6>+-- 6 :> 6 :> 6 :> 6 :> 6 :> Nil repeat :: KnownNat n => a -> Vec n a repeat = withSNat replicate {-# INLINE repeat #-}@@ -1572,7 +1560,7 @@ -- > iterate d4 f x               == (x :> f x :> f (f x) :> f (f (f x)) :> Nil) -- -- >>> iterate d4 (+1) 1--- <1,2,3,4>+-- 1 :> 2 :> 3 :> 4 :> Nil -- -- \"'iterate' @n f z@\" corresponds to the following circuit layout: --@@ -1587,7 +1575,7 @@ -- > iterateI f x :: Vec 3 a == (x :> f x :> f (f x) :> Nil) -- -- >>> iterateI (+1) 1 :: Vec 3 Int--- <1,2,3>+-- 1 :> 2 :> 3 :> Nil -- -- \"'iterateI' @f z@\" corresponds to the following circuit layout: --@@ -1612,7 +1600,7 @@ -- a simple use of 'unfoldr': -- -- >>> unfoldr d10 (\s -> (s,s-1)) 10--- <10,9,8,7,6,5,4,3,2,1>+-- 10 :> 9 :> 8 :> 7 :> 6 :> 5 :> 4 :> 3 :> 2 :> 1 :> Nil unfoldr :: SNat n -> (s -> (a,s)) -> s -> Vec n a unfoldr SNat = unfoldrI {-# INLINE unfoldr #-}@@ -1626,7 +1614,7 @@ -- a simple use of 'unfoldrI': -- -- >>> unfoldrI (\s -> (s,s-1)) 10 :: Vec 10 Int--- <10,9,8,7,6,5,4,3,2,1>+-- 10 :> 9 :> 8 :> 7 :> 6 :> 5 :> 4 :> 3 :> 2 :> 1 :> Nil unfoldrI :: KnownNat n => (s -> (a,s)) -> s -> Vec n a unfoldrI f s0 = map fst xs  where@@ -1641,7 +1629,7 @@ -- > generate d4 f x               == (f x :> f (f x) :> f (f (f x)) :> f (f (f (f x))) :> Nil) -- -- >>> generate d4 (+1) 1--- <2,3,4,5>+-- 2 :> 3 :> 4 :> 5 :> Nil -- -- \"'generate' @n f z@\" corresponds to the following circuit layout: --@@ -1656,7 +1644,7 @@ -- > generateI f x :: Vec 3 a == (f x :> f (f x) :> f (f (f x)) :> Nil) -- -- >>> generateI (+1) 1 :: Vec 3 Int--- <2,3,4>+-- 2 :> 3 :> 4 :> Nil -- -- \"'generateI' @f z@\" corresponds to the following circuit layout: --@@ -1669,12 +1657,13 @@ -- -- >>> let xss = (1:>2:>Nil):>(3:>4:>Nil):>(5:>6:>Nil):>Nil -- >>> xss--- <<1,2>,<3,4>,<5,6>>+-- (1 :> 2 :> Nil) :> (3 :> 4 :> Nil) :> (5 :> 6 :> Nil) :> Nil -- >>> transpose xss--- <<1,3,5>,<2,4,6>>+-- (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 {-# NOINLINE transpose #-}+{-# ANN transpose hasBlackBox #-}  -- | 1-dimensional stencil computations --@@ -1688,7 +1677,7 @@ -- >>> :t stencil1d d2 sum xs -- stencil1d d2 sum xs :: Num b => Vec 5 b -- >>> stencil1d d2 sum xs--- <3,5,7,9,11>+-- 3 :> 5 :> 7 :> 9 :> 11 :> Nil stencil1d :: KnownNat n           => SNat (stX + 1) -- ^ Windows length /stX/, at least size 1           -> (Vec (stX + 1) a -> b) -- ^ The stencil (function)@@ -1710,7 +1699,7 @@ -- >>> :t stencil2d d2 d2 (sum . map sum) xss -- stencil2d d2 d2 (sum . map sum) xss :: Num b => Vec 3 (Vec 3 b) -- >>> stencil2d d2 d2 (sum . map sum) xss--- <<14,18,22>,<30,34,38>,<46,50,54>>+-- (14 :> 18 :> 22 :> Nil) :> (30 :> 34 :> 38 :> Nil) :> (46 :> 50 :> 54 :> Nil) :> Nil stencil2d :: (KnownNat n, KnownNat m)           => SNat (stY + 1) -- ^ Window hight /stY/, at least size 1           -> SNat (stX + 1) -- ^ Window width /stX/, at least size 1@@ -1729,7 +1718,7 @@ -- >>> :t windows1d d2 xs -- windows1d d2 xs :: Num a => Vec 5 (Vec 2 a) -- >>> windows1d d2 xs--- <<1,2>,<2,3>,<3,4>,<4,5>,<5,6>>+-- (1 :> 2 :> Nil) :> (2 :> 3 :> Nil) :> (3 :> 4 :> Nil) :> (4 :> 5 :> Nil) :> (5 :> 6 :> Nil) :> Nil windows1d :: KnownNat n           => SNat (stX + 1) -- ^ Length of the window, at least size 1           -> Vec ((stX + n) + 1) a@@ -1751,7 +1740,7 @@ -- >>> :t windows2d d2 d2 xss -- windows2d d2 d2 xss :: Num a => Vec 3 (Vec 3 (Vec 2 (Vec 2 a))) -- >>> windows2d d2 d2 xss--- <<<<1,2>,<5,6>>,<<2,3>,<6,7>>,<<3,4>,<7,8>>>,<<<5,6>,<9,10>>,<<6,7>,<10,11>>,<<7,8>,<11,12>>>,<<<9,10>,<13,14>>,<<10,11>,<14,15>>,<<11,12>,<15,16>>>>+-- (((1 :> 2 :> Nil) :> (5 :> 6 :> Nil) :> Nil) :> ((2 :> 3 :> Nil) :> (6 :> 7 :> Nil) :> Nil) :> ((3 :> 4 :> Nil) :> (7 :> 8 :> Nil) :> Nil) :> Nil) :> (((5 :> 6 :> Nil) :> (9 :> 10 :> Nil) :> Nil) :> ((6 :> 7 :> Nil) :> (10 :> 11 :> Nil) :> Nil) :> ((7 :> 8 :> Nil) :> (11 :> 12 :> Nil) :> Nil) :> Nil) :> (((9 :> 10 :> Nil) :> (13 :> 14 :> Nil) :> Nil) :> ((10 :> 11 :> Nil) :> (14 :> 15 :> Nil) :> Nil) :> ((11 :> 12 :> Nil) :> (15 :> 16 :> Nil) :> Nil) :> Nil) :> Nil windows2d :: (KnownNat n,KnownNat m)           => SNat (stY + 1) -- ^ Window hight /stY/, at least size 1           -> SNat (stX + 1) -- ^ Window width /stX/, at least size 1@@ -1789,7 +1778,7 @@ -- >>> let input = 1:>9:>6:>4:>4:>2:>0:>1:>2:>Nil -- >>> let from  = 1:>3:>7:>2:>5:>3:>Nil -- >>> backpermute input from--- <9,4,1,6,2,4>+-- 9 :> 4 :> 1 :> 6 :> 2 :> 4 :> Nil backpermute :: (Enum i, KnownNat n)             => Vec n a  -- ^ Source vector, /xs/             -> Vec m i  -- ^ Index mapping, /is/@@ -1808,7 +1797,7 @@ -- >>> let to = 1:>3:>7:>2:>5:>8:>Nil -- >>> let input = 1:>9:>6:>4:>4:>2:>5:>Nil -- >>> scatter defVec to input--- <0,1,4,9,0,4,0,6,2>+-- 0 :> 1 :> 4 :> 9 :> 0 :> 4 :> 0 :> 6 :> 2 :> Nil -- -- __NB__: If the same index appears in the index mapping more than once, the -- latest mapping is chosen.@@ -1831,7 +1820,7 @@ -- >>> let input = 1:>9:>6:>4:>4:>2:>0:>1:>2:>Nil -- >>> let from  = 1:>3:>7:>2:>5:>3:>Nil -- >>> gather input from--- <9,4,1,6,2,4>+-- 9 :> 4 :> 1 :> 6 :> 2 :> 4 :> Nil gather :: (Enum i, KnownNat n)        => Vec n a  -- ^ Source vector, /xs/        -> Vec m i  -- ^ Index mapping, /is/@@ -1847,7 +1836,7 @@ -- -- >>> let xs = 1 :> 2 :> 3 :> 4 :> 5 :> 6 :> 7 :> 8 :> 9 :> Nil -- >>> interleave d3 xs--- <1,4,7,2,5,8,3,6,9>+-- 1 :> 4 :> 7 :> 2 :> 5 :> 8 :> 3 :> 6 :> 9 :> Nil interleave :: (KnownNat n, KnownNat d)            => SNat d -- ^ Interleave step, /d/            -> Vec (n * d) a@@ -1859,11 +1848,11 @@ -- -- >>> let xs = 1 :> 2 :> 3 :> 4 :> Nil -- >>> rotateLeft xs 1--- <2,3,4,1>+-- 2 :> 3 :> 4 :> 1 :> Nil -- >>> rotateLeft xs 2--- <3,4,1,2>+-- 3 :> 4 :> 1 :> 2 :> Nil -- >>> rotateLeft xs (-1)--- <4,1,2,3>+-- 4 :> 1 :> 2 :> 3 :> Nil -- -- __NB:__ use `rotateLeftS` if you want to rotate left by a /static/ amount. rotateLeft :: (Enum i, KnownNat n)@@ -1880,11 +1869,11 @@ -- -- >>> let xs = 1 :> 2 :> 3 :> 4 :> Nil -- >>> rotateRight xs 1--- <4,1,2,3>+-- 4 :> 1 :> 2 :> 3 :> Nil -- >>> rotateRight xs 2--- <3,4,1,2>+-- 3 :> 4 :> 1 :> 2 :> Nil -- >>> rotateRight xs (-1)--- <2,3,4,1>+-- 2 :> 3 :> 4 :> 1 :> Nil -- -- __NB:__ use `rotateRightS` if you want to rotate right by a /static/ amount. rotateRight :: (Enum i, KnownNat n)@@ -1901,7 +1890,7 @@ -- -- >>> let xs = 1 :> 2 :> 3 :> 4 :> Nil -- >>> rotateLeftS xs d1--- <2,3,4,1>+-- 2 :> 3 :> 4 :> 1 :> Nil -- -- __NB:__ use `rotateLeft` if you want to rotate left by a /dynamic/ amount. rotateLeftS :: KnownNat n@@ -1915,12 +1904,13 @@     go 0 ys            = ys     go n (y `Cons` ys) = go (n-1) (ys :< y) {-# NOINLINE rotateLeftS #-}+{-# ANN rotateLeftS hasBlackBox #-}  -- | /Statically/ rotate a 'Vec'tor to the right: -- -- >>> let xs = 1 :> 2 :> 3 :> 4 :> Nil -- >>> rotateRightS xs d1--- <4,1,2,3>+-- 4 :> 1 :> 2 :> 3 :> Nil -- -- __NB:__ use `rotateRight` if you want to rotate right by a /dynamic/ amount. rotateRightS :: KnownNat n@@ -1933,11 +1923,14 @@     go 0 ys             = ys     go n ys@(Cons _ _)  = go (n-1) (last ys :> init ys) {-# NOINLINE rotateRightS #-}+{-# ANN rotateRightS hasBlackBox #-}  -- | Convert a vector to a list. -- -- >>> toList (1:>2:>3:>Nil) -- [1,2,3]+--+-- __NB:__ this function is not synthesizable toList :: Vec n a -> [a] toList = foldr (:) [] {-# INLINE toList #-}@@ -1946,7 +1939,7 @@ -- the list is not equal to the size of the resulting vector. -- -- >>> Vec.fromList [1,2,3,4,5] :: Maybe (Vec 5 Int)--- Just <1,2,3,4,5>+-- Just (1 :> 2 :> 3 :> 4 :> 5 :> Nil) -- -- >>> Vec.fromList [1,2,3,4,5] :: Maybe (Vec 3 Int) -- Nothing@@ -1954,8 +1947,8 @@ -- >>> Vec.fromList [1,2,3,4,5] :: Maybe (Vec 10 Int) -- Nothing ----- __NB:__ use `listToVecTH` if you want to make a /statically known/ vector--- __NB:__ this function is not synthesizable+-- * __NB:__ use `listToVecTH` if you want to make a /statically known/ vector+-- * __NB:__ this function is not synthesizable -- fromList :: forall n a. (KnownNat n) => [a] -> Maybe (Vec n a) fromList xs@@ -1973,17 +1966,17 @@ -- undefined elements. -- -- >>> Vec.unsafeFromList [1,2,3,4,5] :: Vec 5 Int--- <1,2,3,4,5>+-- 1 :> 2 :> 3 :> 4 :> 5 :> Nil -- -- >>> Vec.unsafeFromList [1,2,3,4,5] :: Vec 3 Int--- <1,2,3>+-- 1 :> 2 :> 3 :> Nil -- -- >>> Vec.unsafeFromList [1,2,3,4,5] :: Vec 10 Int--- <1,2,3,4,5,*** Exception: Clash.Sized.Vector.unsafeFromList: vector larger than list+-- 1 :> 2 :> 3 :> 4 :> 5 :> *** Exception: Clash.Sized.Vector.unsafeFromList: vector larger than list -- ... ----- __NB:__ use `listToVecTH` if you want to make a /statically known/ vector--- __NB:__ this function is not synthesizable+-- * __NB:__ use `listToVecTH` if you want to make a /statically known/ vector+-- * __NB:__ this function is not synthesizable -- unsafeFromList :: forall n a. (KnownNat n) => [a] -> Vec n a unsafeFromList = unfoldr SNat go@@ -2003,7 +1996,7 @@ -- >>> [1 :: Signed 8,2,3,4,5] -- [1,2,3,4,5] -- >>> $(listToVecTH [1::Signed 8,2,3,4,5])--- <1,2,3,4,5>+-- 1 :> 2 :> 3 :> 4 :> 5 :> Nil listToVecTH :: Lift a => [a] -> ExpQ listToVecTH []     = [| Nil |] listToVecTH (x:xs) = [| x :> $(listToVecTH xs) |]@@ -2020,6 +2013,27 @@ -- | What you should use when your vector functions are too strict in their -- arguments. --+-- === __doctests setup__+-- >>> let compareSwapL a b = if a < b then (a,b) else (b,a)+-- >>> :{+-- let sortVL :: (Ord a, KnownNat (n + 1)) => Vec ((n + 1) + 1) a -> Vec ((n + 1) + 1) a+--     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 sortV_flip xs = map fst sorted :< (snd (last sorted))+--       where+--         lefts  = head xs :> map snd (init sorted)+--         rights = tail xs+--         sorted = zipWith (flip compareSwapL) rights lefts+-- :}+--+-- === Example usage+-- -- For example: -- -- @@@ -2050,7 +2064,7 @@ -- Results in a successful computation: -- -- >>> sortVL (4 :> 1 :> 2 :> 3 :> Nil)--- <1,2,3,4>+-- 1 :> 2 :> 3 :> 4 :> Nil -- -- __NB__: There is also a solution using 'flip', but it slightly obfuscates the -- meaning of the code:@@ -2064,7 +2078,7 @@ -- @ -- -- >>> sortV_flip (4 :> 1 :> 2 :> 3 :> Nil)--- <1,2,3,4>+-- 1 :> 2 :> 3 :> 4 :> Nil lazyV :: KnownNat n       => Vec n a       -> Vec n a@@ -2074,9 +2088,19 @@     lazyV' Nil           _  = Nil     lazyV' (_ `Cons` xs) ys = head ys `Cons` lazyV' xs (tail ys) {-# NOINLINE lazyV #-}+{-# ANN lazyV hasBlackBox #-}  -- | A /dependently/ typed fold. --+-- === __doctests setup__+-- >>> :seti -fplugin GHC.TypeLits.Normalise+-- >>> 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+--+-- === Example usage+-- -- Using lists, we can define /append/ (a.k.a. @Data.List.@'Data.List.++') in -- terms of @Data.List.@'Data.List.foldr': --@@ -2144,7 +2168,7 @@ -- And that it works: -- -- >>> append' (1 :> 2 :> Nil) (3 :> 4 :> Nil)--- <1,2,3,4>+-- 1 :> 2 :> 3 :> 4 :> Nil -- -- __NB__: \"@'dfold' m f z xs@\" creates a linear structure, which has a depth, -- or delay, of O(@'length' xs@). Look at 'dtfold' for a /dependently/ typed@@ -2168,10 +2192,26 @@       let s' = s `subSNat` d1       in  f s' y (go s' ys) {-# NOINLINE dfold #-}+{-# ANN dfold hasBlackBox #-}  {- | A combination of 'dfold' and 'fold': a /dependently/ typed fold that reduces a vector in a tree-like structure. +=== __doctests setup__+>>> :seti -XUndecidableInstances+>>> import Data.Singletons (Apply, Proxy (..), TyFun)+>>> data IIndex (f :: TyFun Nat Type) :: Type+>>> type instance Apply IIndex l = Index ((2^l)+1)+>>> :{+let populationCount' :: (KnownNat k, KnownNat (2^k)) => BitVector (2^k) -> Index ((2^k)+1)+    populationCount' bv = dtfold (Proxy @IIndex)+                                 fromIntegral+                                 (\_ x y -> add x y)+                                 (bv2v bv)+:}++=== Example usage+ As an example of when you might want to use 'dtfold' we will build a population counter: a circuit that counts the number of bits set to '1' in a 'BitVector'. Given a vector of /n/ bits, we only need we need a data type@@ -2315,6 +2355,7 @@           (xsL,xsR) = splitAt (pow2SNat sn') xs       in  g sn' (go sn' xsL) (go sn' xsR) {-# NOINLINE dtfold #-}+{-# ANN dtfold hasBlackBox #-}  -- | To be used as the motive /p/ for 'dfold', when the /f/ in \"'dfold' @p f@\" -- is a variation on (':>'), e.g.:@@ -2329,8 +2370,13 @@ -- | Specialised version of 'dfold' that builds a triangular computational -- structure. ----- Example:+-- === __doctests setup__+-- >>> let compareSwap a b = if a > b then (a,b) else (b,a)+-- >>> let insert y xs = let (y',xs') = mapAccumL compareSwap y xs in xs' :< y'+-- >>> let insertionSort = vfold (const insert) --+-- === Example usage+-- -- @ -- compareSwap a b = if a > b then (a,b) else (b,a) -- insert y xs     = let (y',xs') = 'mapAccumL' compareSwap y xs in xs' ':<' y'@@ -2340,7 +2386,7 @@ -- Builds a triangular structure of compare and swaps to sort a row. -- -- >>> insertionSort (7 :> 3 :> 9 :> 1 :> Nil)--- <1,3,7,9>+-- 1 :> 3 :> 7 :> 9 :> Nil -- -- The circuit layout of @insertionSort@, build using 'vfold', is: --@@ -2358,9 +2404,9 @@ -- >>> let rotateMatrix = smap (flip rotateRightS) -- >>> let xss = (1:>2:>3:>Nil):>(1:>2:>3:>Nil):>(1:>2:>3:>Nil):>Nil -- >>> xss--- <<1,2,3>,<1,2,3>,<1,2,3>>+-- (1 :> 2 :> 3 :> Nil) :> (1 :> 2 :> 3 :> Nil) :> (1 :> 2 :> 3 :> Nil) :> Nil -- >>> rotateMatrix xss--- <<1,2,3>,<3,1,2>,<2,3,1>>+-- (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 f xs = reverse           $ dfold (Proxy @(VCons b))@@ -2386,6 +2432,7 @@     let sh = fromInteger (natVal (Proxy @m)) :: Int in     go (BV (shiftL accMsk sh .|. xMsk) (shiftL accVal sh .|. xVal)) xs {-# NOINLINE concatBitVector# #-}+{-# ANN concatBitVector# hasBlackBox #-}  unconcatBitVector#   :: forall n m@@ -2401,14 +2448,15 @@           (l,x) = (GHC.Magic.noinline split#) bv       in  (l,x :> xs) {-# NOINLINE unconcatBitVector# #-}+{-# ANN unconcatBitVector# hasBlackBox #-}  -- | Convert a 'BitVector' to a 'Vec' of 'Bit's. -- -- >>> let x = 6 :: BitVector 8 -- >>> x--- 0000_0110+-- 0b0000_0110 -- >>> bv2v x--- <0,0,0,0,0,1,1,0>+-- 0 :> 0 :> 0 :> 0 :> 0 :> 1 :> 1 :> 0 :> Nil bv2v :: KnownNat n => BitVector n -> Vec n Bit bv2v = unpack @@ -2416,9 +2464,9 @@ -- -- >>> let x = (0:>0:>0:>1:>0:>0:>1:>0:>Nil) :: Vec 8 Bit -- >>> x--- <0,0,0,1,0,0,1,0>+-- 0 :> 0 :> 0 :> 1 :> 0 :> 0 :> 1 :> 0 :> Nil -- >>> v2bv x--- 0001_0010+-- 0b0001_0010 v2bv :: KnownNat n => Vec n Bit -> BitVector n v2bv = pack @@ -2432,6 +2480,7 @@   let s () e = seq e () in   foldl s () v `seq` b {-# NOINLINE seqV #-}+{-# ANN seqV hasBlackBox #-} infixr 0 `seqV`  -- | Evaluate all elements of a vector to WHNF@@ -2454,6 +2503,7 @@   let s () e = seqX e () in   foldl s () v `seqX` b {-# NOINLINE seqVX #-}+{-# ANN seqVX hasBlackBox #-} infixr 0 `seqVX`  -- | Evaluate all elements of a vector to WHNF. Does not propagate
src/Clash/Tutorial.hs view
@@ -93,7 +93,7 @@  {- $setup >>> :set -XTemplateHaskell -XDataKinds -XConstraintKinds -XTypeApplications->>> :m -Clash.Explicit.Prelude+>>> :m -Prelude >>> import Clash.Prelude >>> import Clash.Explicit.Testbench >>> :{@@ -917,7 +917,7 @@     'exposeClockResetEnable' ('mealy' blinkerT (1,False,0) . Clash.Prelude.isRising 1) pllOut rstSync 'enableGen'   where     (pllOut,pllStable) = 'Clash.Intel.ClockGen.altpll' \@Dom100 (SSymbol \@\"altpll100\") clk ('Clash.Signal.unsafeFromLowPolarity' rst)-    rstSync            = 'Clash.Signal.resetSynchronizer' pllOut ('Clash.Signal.unsafeFromLowPolarity' pllStable) enableGen+    rstSync            = 'Clash.Signal.resetSynchronizer' pllOut ('Clash.Signal.unsafeFromLowPolarity' pllStable)  blinkerT (leds,mode,cntr) key1R = ((leds',mode',cntr'),leds)   where@@ -1033,7 +1033,7 @@  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@ file-extension.+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@@ -1050,13 +1050,11 @@ 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])"-  }-}+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@@ -1143,71 +1141,68 @@ 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]))+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-      after 1 ps+                    mod ~LENGTH[~TYP[5]]       -- 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])+                    ;+      ~SYM[5] <= to_integer(~ARG[8])       -- pragma translate_off-      after 1 ps+                    mod ~LENGTH[~TYP[5]]       -- pragma translate_on-      ;-    end if;-  end process; ~FI-end block;---end blockRam"-  }-}+                    ;+    ~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@@ -1318,71 +1313,67 @@ 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]"-  }-}+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"-    , "outputReg" : true-    , "template" :-"// blockRam begin-reg ~TYPO ~GENSYM[~RESULT_RAM][1] [0:~LENGTH[~TYP[5]]-1];+BlackBox:+  name: Clash.Explicit.BlockRam.blockRam#+  kind: Declaration+  outputReg: true+  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];+    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-    ~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"-  }-}+    ~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 @  -}@@ -1391,65 +1382,61 @@ 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]"-  }-}+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"-  }-}+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 @  -}@@ -2032,7 +2019,7 @@     Results in a successful computation:      >>> sortVL (4 :> 1 :> 2 :> 3 :> Nil)-    <1,2,3,4>+    1 :> 2 :> 3 :> 4 :> Nil -}  {- $limitations #limitations#
src/Clash/Verification.hs view
@@ -31,6 +31,7 @@   , EV.timpliesOverlapping   , EV.always   , EV.never+  , EV.eventually    -- * Asserts   , EV.assert
src/Clash/Verification/Internal.hs view
@@ -11,10 +11,6 @@ {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskell #-} -#if __GLASGOW_HASKELL__ < 806-{-# LANGUAGE TypeInType #-}-#endif- module Clash.Verification.Internal  ( AssertionResult(..)  , Property(..)@@ -44,6 +40,13 @@   -- ^ SystemVerilog Assertions   | AutoRenderAs   -- ^ Use SVA for SystemVerilog, PSL for others+  | YosysFormal+  -- ^ Yosys Formal Extensions for Verilog and SystemVerilog. See:+  -- https://symbiyosys.readthedocs.io/en/latest/verilog.html and+  -- https://symbiyosys.readthedocs.io/en/latest/verific.html+  --+  -- Falls back to PSL for VHDL, however currently Clash's PSL syntax isn't+  -- suported by GHDL+SymbiYosys;   deriving (Show, Eq)  data IsTemporal@@ -83,6 +86,8 @@   -- ^ Assertion should _always_ hold   | CvNever (Assertion' a)   -- ^ Assertion should _never_ hold (not supported by SVA)+  | CvEventually (Assertion' a)+  -- ^ Assertion should _eventually_ hold   deriving (Show, Functor, Foldable, Traversable)  -- | Internal version of 'Property'. All user facing will instantiate @a@@@ -91,6 +96,7 @@ data Property' a   = CvAssert (Assertion' a)   | CvCover (Assertion' a)+  | CvAssume (Assertion' a)   deriving (Show, Functor, Foldable, Traversable)  data Assertion (dom :: Domain) =
− src/Clash/Verification/PrettyPrinters.hs
@@ -1,244 +0,0 @@-{-|-Copyright  :  (C) 2019, Myrtle Software Ltd-License    :  BSD2 (see the file LICENSE)-Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>--Verification--}--{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE OverloadedStrings #-}--module Clash.Verification.PrettyPrinters-  ( pprPslProperty-  , pprSvaProperty--  -- * Debugging functions-  , pprProperty-  ) where--import           Clash.Annotations.Primitive      (HDL(..))-import           Clash.Signal.Internal            (ActiveEdge, ActiveEdge(..))-import           Clash.Verification.Internal      hiding (assertion)-import           Data.Maybe                       (fromMaybe)-import           Data.Text                        (Text)-import           TextShow                         (showt)--data Symbol-  = TImpliesOverlapping-  | TImplies-  | Implies-  | BiImplies-  | Not-  | And-  | Or-  | To-  | Equals-  -- + [] ?-  | Assign-  | Is-----------------------------------------------                 UTIL                 ------------------------------------------------ | Collapse constructs such as `next (next a)` down to `next[2] a`-squashBefore :: Assertion' a -> [Assertion' a]-squashBefore (CvBefore e1 e2) = e1s ++ e2s- where-  e1s = case squashBefore e1 of {[] -> [e1]; es -> es}-  e2s = case squashBefore e2 of {[] -> [e2]; es -> es}-squashBefore _ = []--parensIf :: Bool -> Text -> Text-parensIf True s = "(" <> s <> ")"-parensIf False s = s--------------------------------------------                PSL                -------------------------------------------pslBinOp-  :: HDL-  -> Bool-  -> Symbol-  -> Assertion' Text-  -> Assertion' Text-  -> Text-pslBinOp hdl parens op e1 e2 =-  parensIf parens (e1' <> symbol hdl op <> e2')- where-  e1' = pprPslAssertion hdl True e1-  e2' = pprPslAssertion hdl True e2--pslEdge :: HDL -> ActiveEdge -> Text -> Text-pslEdge SystemVerilog activeEdge clkId = pslEdge Verilog activeEdge clkId-pslEdge Verilog Rising clkId = "posedge " <> clkId-pslEdge Verilog Falling clkId = "negedge " <> clkId-pslEdge VHDL Rising clkId = "rising_edge(" <> clkId <> ")"-pslEdge VHDL Falling clkId = "falling_edge(" <> clkId <> ")"---- | Taken from IEEE Std 1850-2010a, Annex B.1, p149-symbol :: HDL -> Symbol -> Text-symbol SystemVerilog = symbol Verilog-symbol Verilog = \case-  TImpliesOverlapping -> "|->"-  TImplies  -> "|=>"-  Implies   -> "->"-  BiImplies -> "<->"-  Not       -> "!"-  And       -> "&&"-  Or        -> "||"-  To        -> ":"-  Assign    -> "<="-  Is        -> "="-  Equals    -> "=="--symbol VHDL = \case-  TImpliesOverlapping -> "|->"-  TImplies  -> "|=>"-  Implies   -> " -> "-  BiImplies -> " <-> "-  Not       -> "not"-  And       -> " and "-  Or        -> " or "-  To        -> " to "-  Assign    -> "<="-  Is        -> "is"-  Equals    -> "="---- | Pretty print Property. Doesn't print valid HDL, but can be used for--- debugging purposes.-pprProperty :: Property dom -> Text-pprProperty (Property prop0) =-  let prop1 = fromMaybe "__autogen__" . fst <$> prop0 in-  pprPslProperty VHDL "prop" "clk" Rising prop1--pprPslProperty-  :: HDL-  -- ^ HDL to generate PSL expression for-  -> Text-  -- ^ Property name-  -> Text-  -- ^ Clock name-  -> ActiveEdge-  -- ^ Edge property should be sensitive to-  -> Property' Text-  -- ^ Assertion / Cover statement-  -> Text-pprPslProperty hdl propName clkId edge assertion =-  "psl property " <> propName <> " " <> symbol hdl Is <> "\n" <>-  "(" <> prop <> ") @(" <> pslEdge hdl edge clkId <> ")" <>-  ";\n" <> "psl " <> coverOrAssert <> " " <>-  propName <> ";"- where-  (coverOrAssert, prop) =-    case assertion of-      CvCover e -> ("cover", pprPslAssertion hdl False e)-      CvAssert e -> ("assert", pprPslAssertion hdl False e)--pprPslAssertion :: HDL -> Bool -> Assertion' Text -> Text-pprPslAssertion hdl parens e =-  case e of-    (CvPure p) -> p--    -- ModelSim/QuastaSim doesn't support booleans in PSL. Anytime we want to-    -- use a boolean literal we use (0 == 0) or (0 == 1) instead.-    (CvLit False) -> parensIf parens ("0" <> symbol hdl Equals <> "1")-    (CvLit True) -> parensIf parens ("0" <> symbol hdl Equals <> "0")--    (CvNot e1) ->-      parensIf parens (symbol hdl Not <> " " <> pprPslAssertion hdl True e1)-    (CvAnd e1 e2) -> pslBinOp1 And e1 e2-    (CvOr e1 e2) -> pslBinOp1 Or e1 e2-    (CvImplies e1 e2) -> pslBinOp1 Implies e1 e2--    (CvToTemporal e1) -> "{" <> pprPslAssertion hdl False e1 <> "}"--    (CvNext 0 e1) -> pprPslAssertion hdl parens e1-    (CvNext 1 e1) -> " ## " <> pprPslAssertion hdl True e1-    (CvNext n e1) -> " ##" <> showt n <> " " <> pprPslAssertion hdl False e1--    (CvBefore _ _) -> "{" <> afters1 <> "}"-     where-      afters0 = map (pprPslAssertion hdl False) (squashBefore e)-      afters1 = foldl1 (\e1 e2 -> e1 <> "; " <> e2) afters0--    (CvTemporalImplies 0 e1 e2) -> pslBinOp1 TImpliesOverlapping e1 e2-    (CvTemporalImplies 1 e1 e2) -> pslBinOp1 TImplies e1 e2-    (CvTemporalImplies n e1 e2) -> pslBinOp1 TImplies e1 (CvNext n e2)--    (CvAlways e1) -> "always " <> pprPslAssertion hdl True e1-    (CvNever e1) -> "never " <> pprPslAssertion hdl True e1- where-  pslBinOp1 = pslBinOp hdl True---------------------------------------------                SVA                -------------------------------------------svaEdge :: ActiveEdge -> Text -> Text-svaEdge Rising clkId = "posedge " <> clkId-svaEdge Falling clkId = "negedge " <> clkId--svaBinOp-  :: Bool-  -> Symbol-  -> Assertion' Text-  -> Assertion' Text-  -> Text-svaBinOp parens op e1 e2 =-  parensIf parens (e1' <> symbol SystemVerilog op <> e2')- where-  e1' = pprSvaAssertion True e1-  e2' = pprSvaAssertion True e2--pprSvaAssertion :: Bool -> Assertion' Text -> Text-pprSvaAssertion parens e =-  case e of-    (CvPure p) -> p-    (CvLit False) -> "false"-    (CvLit True) -> "true"--    (CvNot e1) ->-      parensIf parens (symbol' Not <> pprSvaAssertion True e1)-    (CvAnd e1 e2) -> svaBinOp1 And e1 e2-    (CvOr e1 e2) -> svaBinOp1 Or e1 e2-    (CvImplies e1 e2) -> svaBinOp1 Implies e1 e2--    (CvToTemporal e1) -> "{" <> pprSvaAssertion False e1 <> "}"--    (CvNext 0 e1) -> pprSvaAssertion parens e1-    (CvNext n e1) -> "nexttime[" <> showt n <> "] " <> pprSvaAssertion False e1--    (CvBefore _ _) -> "{" <> afters1 <> "}"-     where-      afters0 = map (pprSvaAssertion False) (squashBefore e)-      afters1 = foldl1 (\e1 e2 -> "(" <> e1 <> ") ##1 (" <> e2 <> ")") afters0--    (CvTemporalImplies 0 e1 e2) -> svaBinOp1 TImpliesOverlapping e1 e2-    (CvTemporalImplies 1 e1 e2) -> svaBinOp1 TImplies e1 e2-    (CvTemporalImplies n e1 e2) -> svaBinOp1 TImplies e1 (CvNext n e2)--    (CvAlways e1) -> "always (" <> pprSvaAssertion False e1 <> ")"-    (CvNever _e) -> error "'never' not supported in SVA"- where-  svaBinOp1 = svaBinOp parens-  symbol' = symbol SystemVerilog--pprSvaProperty-  :: Text-  -- ^ Property name-  -> Text-  -- ^ Clock name-  -> ActiveEdge-  -- ^ Edge property should be sensitive to-  -> Property' Text-  -- ^ Assertion / Cover statement-  -> Text-pprSvaProperty propName clkId edge assertion =-  propName <> ": " <> coverOrAssert <> " property (@(" <>-  svaEdge edge clkId <> ") " <> prop <> ");"- where-  (coverOrAssert, prop) =-    case assertion of-      CvCover e -> ("cover", pprSvaAssertion False e)-      CvAssert e -> ("assert", pprSvaAssertion False e)
src/Clash/XException.hs view
@@ -1,9 +1,10 @@ {-| Copyright  :  (C) 2016,      University of Twente,                   2017,      QBayLogic, Google Inc.-                  2017-2019, Myrtle Software Ltd+                  2017-2019, Myrtle Software Ltd,+                  2021-2022, QBayLogic B.V. License    :  BSD2 (see the file LICENSE)-Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>  'XException': An exception for uninitialized values @@ -12,7 +13,7 @@ CallStack (from HasCallStack): ... >>> showX (errorX "undefined" :: Integer, 4 :: Int)-"(X,4)"+"(undefined,4)" -}  {-# LANGUAGE CPP #-}@@ -31,10 +32,10 @@   ( -- * 'XException': An exception for uninitialized values     XException(..), errorX, isX, hasX, maybeIsX, maybeHasX, fromJustX, undefined,     xToErrorCtx, xToError-    -- * Printing 'XException's as \"X\"+    -- * Printing 'XException's as @undefined@   , ShowX (..), showsX, printX, showsPrecXWith     -- * Strict evaluation-  , seqX, forceX, deepseqX, rwhnfX, defaultSeqX, hwSeqX+  , seqX, seqErrorX, forceX, deepseqX, rwhnfX, defaultSeqX, hwSeqX     -- * Structured undefined / deep evaluation with undefined values   , NFDataX (rnfX, deepErrorX, hasUndefined, ensureSpine)   )@@ -47,7 +48,7 @@ import           Clash.XException.Internal import           Clash.XException.TH import           Control.Exception-  (ErrorCall (..), catch, evaluate, throw)+  (ErrorCall (..), Handler(..), catch, catches, evaluate, throw) import           Control.DeepSeq     (NFData, rnf) import           Data.Complex        (Complex) import           Data.Either         (isLeft)@@ -68,6 +69,8 @@ import           System.IO.Unsafe    (unsafeDupablePerformIO)  -- $setup+-- >>> :m -Prelude+-- >>> import Clash.Prelude -- >>> import Clash.Class.BitPack (pack) -- >>> import Clash.Sized.Vector (Vec) -- >>> import Clash.Sized.RTree (RTree)@@ -85,7 +88,7 @@  -- | Like 'error', but throwing an 'XException' instead of an 'ErrorCall' ----- The 'ShowX' methods print these error-values as \"X\"; instead of error'ing+-- The 'ShowX' methods print these error-values as @undefined@; instead of error'ing -- out with an exception. errorX :: HasCallStack => String -> a errorX msg = throw (XException ("X: " ++ msg ++ "\n" ++ prettyCallStack callStack))@@ -128,7 +131,7 @@ -- :} -- -- >>> h' (errorX "QQ") 3--- 0000_0011+-- 0b0000_0011 -- >>> h (errorX "QQ") 3 -- *** Exception: a is X -- X: QQ@@ -184,7 +187,7 @@ -- :} -- -- >>> h' (errorX "QQ") 3--- 0000_0011+-- 0b0000_0011 -- >>> f (errorX "QQ") 3 -- *** Exception: CallStack (from HasCallStack): --   xToError, called at ...@@ -211,8 +214,25 @@ seqX a b = unsafeDupablePerformIO   (catch (evaluate a >> return b) (\(XException _) -> return b)) {-# NOINLINE seqX #-}+{-# ANN seqX hasBlackBox #-} infixr 0 `seqX` +-- | Like 'seqX', but will also catch ErrorCall exceptions which are thrown.+-- This should be used with care.+--+-- > seqErrorX (ErrorCall msg)  b = b+-- > seqErrorX (XException msg) b = b+-- > seqErrorX _|_              b = _|_+seqErrorX :: a -> b -> b+seqErrorX a b = unsafeDupablePerformIO+  ((evaluate a >> return b) `catches`+     [ Handler (\(XException _) -> return b)+     , Handler (\(ErrorCall _) -> return b)+     ])+{-# NOINLINE seqErrorX #-}+{-# ANN seqErrorX hasBlackBox #-}+infixr 0 `seqErrorX`+ -- | Like 'seqX' in simulation, but will force its first argument to be rendered -- in HDL. This is useful for components that need to be rendered in hardware, -- but otherwise have no meaning in simulation. An example of such a component@@ -307,14 +327,14 @@ {-# NOINLINE isX #-}  -- | Like the 'Show' class, but values that normally throw an 'XException' are--- converted to \"X\", instead of error'ing out with an exception.+-- converted to @undefined@, instead of error'ing out with an exception. -- -- >>> show (errorX "undefined" :: Integer, 4 :: Int) -- "(*** Exception: X: undefined -- CallStack (from HasCallStack): -- ... -- >>> showX (errorX "undefined" :: Integer, 4 :: Int)--- "(X,4)"+-- "(undefined,4)" -- -- Can be derived using 'GHC.Generics': --@@ -327,16 +347,16 @@ -- >   deriving (Show,Generic,ShowX) class ShowX a where   -- | Like 'showsPrec', but values that normally throw an 'XException' are-  -- converted to \"X\", instead of error'ing out with an exception.+  -- converted to @undefined@, instead of error'ing out with an exception.   showsPrecX :: Int -> a -> ShowS    -- | Like 'show', but values that normally throw an 'XException' are-  -- converted to \"X\", instead of error'ing out with an exception.+  -- converted to @undefined@, instead of error'ing out with an exception.   showX :: a -> String   showX x = showsX x ""    -- | Like 'showList', but values that normally throw an 'XException' are-  -- converted to \"X\", instead of error'ing out with an exception.+  -- converted to @undefined@, instead of error'ing out with an exception.   showListX :: [a] -> ShowS   showListX ls s = showListX__ showsX ls s @@ -344,7 +364,7 @@   showsPrecX = genericShowsPrecX  -- | Like 'print', but values that normally throw an 'XException' are--- converted to \"X\", instead of error'ing out with an exception+-- converted to @undefined@, instead of error'ing out with an exception printX :: ShowX a => a -> IO () printX x = putStrLn $ showX x @@ -431,6 +451,7 @@ deepseqX :: NFDataX a => a -> b -> b deepseqX a b = rnfX a `seq` b {-# NOINLINE deepseqX #-}+{-# ANN deepseqX hasBlackBox #-} infixr 0 `deepseqX`  -- | Reduce to weak head normal form@@ -460,7 +481,7 @@   -- >>> hasUndefined m   -- False   -- >>> pack m-  -- 0.+  -- 0b0.   -- >>> hasUndefined (pack m)   -- True   --@@ -475,7 +496,7 @@   -- >>> case spined of (_, _) -> 'a'   -- 'a'   -- >>> fmap (const 'b') (ensureSpine undefined :: Vec 3 Int)-  -- <'b','b','b'>+  -- 'b' :> 'b' :> 'b' :> Nil   -- >>> fmap (const 'c') (ensureSpine undefined :: RTree 2 Int)   -- <<'c','c'>,<'c','c'>>   --@@ -678,5 +699,5 @@ -- | Same as 'Data.Maybe.fromJust', but returns a bottom/undefined value that -- other Clash constructs are aware of. fromJustX :: HasCallStack => Maybe a -> a-fromJustX Nothing = errorX "isJustX: Nothing"+fromJustX Nothing = errorX "fromJustX: Nothing" fromJustX (Just a) = a
src/Clash/XException/Internal.hs view
@@ -12,7 +12,7 @@ CallStack (from HasCallStack): ... >>> showX (errorX "undefined" :: Integer, 4 :: Int)-"(X,4)"+"(undefined,4)" -}  {-# LANGUAGE CPP #-}@@ -22,8 +22,6 @@ {-# LANGUAGE GADTs #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE TemplateHaskell #-}  {-# LANGUAGE Trustworthy #-} @@ -31,7 +29,7 @@  module Clash.XException.Internal   ( XException(..)-    -- * Printing 'XException's as \"X\"+    -- * Printing 'XException's as @undefined@   , showsX, showsPrecXWith   , showXWith @@ -55,6 +53,9 @@ import           GHC.Stack           (HasCallStack) import           System.IO.Unsafe    (unsafeDupablePerformIO) +-- $setup+-- >>> import Clash.Prelude+ -- | An exception representing an \"uninitialized\" value. newtype XException = XException String @@ -64,7 +65,7 @@ instance Exception XException  -- | Like 'shows', but values that normally throw an 'XException' are--- converted to \"X\", instead of error'ing out with an exception.+-- converted to @undefined@, instead of error'ing out with an exception. showsX :: ShowX a => a -> ShowS showsX = showsPrecX 0 @@ -82,15 +83,17 @@  showXWith :: (a -> ShowS) -> a -> ShowS showXWith f x =-  \s -> unsafeDupablePerformIO (catch (f <$> evaluate x <*> pure s)-                                      (\(XException _) -> return ('X': s)))+  unsafeDupablePerformIO $+    catch+      (f <$> evaluate x)+      (\(XException _) -> return (showString "undefined"))  -- | Use when you want to create a 'ShowX' instance where: -- -- - There is no 'Generic' instance for your data type -- - The 'Generic' derived ShowX method would traverse into the (hidden) --   implementation details of your data type, and you just want to show the---   entire value as \"X\".+--   entire value as @undefined@. -- -- Can be used like: --
+ tests/Clash/Tests/AsyncFIFOSynchronizer.hs view
@@ -0,0 +1,996 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS_GHC -Wno-orphans #-}+{-# OPTIONS_GHC -Wno-unused-top-binds #-}++module Clash.Tests.AsyncFIFOSynchronizer (tests) where++import qualified Prelude as P++import Test.Tasty+import Test.Tasty.HUnit++import Clash.Explicit.Prelude++createDomain vSystem{vName = "Slow", vPeriod = 2 * vPeriod vSystem}++sync12RW+  :: ( KnownDomain dom1+     , KnownDomain dom2+     )+  => Int+  -> Int+  -> Int+  -> ( Signal dom1 (Bool, (Int, Bool))+     , Signal dom2 (Maybe Int, Bool)+     )+sync12RW w1 w2 w3 =+  ( bundle (inputRInc, bundle (rdata, rempty))+  , bundle (inputWDataM, wfull)+  )+ where+  (rdata, rempty, wfull) =+    asyncFIFOSynchronizer d4 clockGen clockGen resetGen resetGen enableGen+      enableGen inputRInc inputWDataM+  inputRInc = fromList $ P.replicate w1 False <> P.replicate 4 True <>+                P.replicate w2 False <> P.replicate 4 True <> P.repeat False+  inputWDataM = fromList $ Nothing : P.map Just [1 .. 4] <>+                  P.replicate w3 Nothing <> P.map Just [5 .. 8] <>+                  P.repeat Nothing++-- Test n.1:+--  - Write 4+--  - Empty as soon as we can stream all in a row+--  - Stay empty for a moment+--  - Write another 4+--  - Empty as soon as we can stream all in a row++sync1R1 :: Signal Slow (Bool, (Int, Bool))+sync1W1 :: Signal System (Maybe Int, Bool)+(sync1R1, sync1W1) = sync12RW 4 2 7++sync2R1 :: Signal System (Bool, (Int, Bool))+sync2W1 :: Signal Slow (Maybe Int, Bool)+(sync2R1, sync2W1) = sync12RW 9 6 1++-- Test n.2:+--  - Write 4+--  - Don't start immediately, but then empty all in a row+--  - Stay empty for a moment+--  - Write another 4+--  - Empty as soon as we can stream all in a row++sync1R2 :: Signal Slow (Bool, (Int, Bool))+sync1W2 :: Signal System (Maybe Int, Bool)+(sync1R2, sync1W2) = sync12RW 5 2 8++sync2R2 :: Signal System (Bool, (Int, Bool))+sync2W2 :: Signal Slow (Maybe Int, Bool)+(sync2R2, sync2W2) = sync12RW 10 10 1++-- Test n.3:+--  - Write 4+--  - Empty as soon as we can stream all in a row+--  - Stay empty for a moment+--  - Write another 4+--  - Don't start immediately, but then empty all in a row++sync1R3 :: Signal Slow (Bool, (Int, Bool))+sync1W3 :: Signal System (Maybe Int, Bool)+(sync1R3, sync1W3) = sync12RW 4 4 7++sync2R3 :: Signal System (Bool, (Int, Bool))+sync2W3 :: Signal Slow (Maybe Int, Bool)+(sync2R3, sync2W3) = sync12RW 9 8 1++-- Test n.4:+--  - Write 4+--  - Don't start immediately, but then empty all in a row+--  - Stay empty for a moment+--  - Write another 4+--  - Don't start immediately, but then empty all in a row++sync1R4 :: Signal Slow (Bool, (Int, Bool))+sync1W4 :: Signal System (Maybe Int, Bool)+(sync1R4, sync1W4) = sync12RW 5 3 8++sync2R4 :: Signal System (Bool, (Int, Bool))+sync2W4 :: Signal Slow (Maybe Int, Bool)+(sync2R4, sync2W4) = sync12RW 10 12 1++sync34RW+  :: ( KnownDomain dom1+     , KnownDomain dom2+     )+  => Int+  -> Int+  -> Int+  -> Int+  -> ( Signal dom1 (Bool, (Int, Bool))+     , Signal dom2 (Maybe Int, Bool)+     )+sync34RW w1 n1 w2 w3 =+  ( bundle (inputRInc, bundle (rdata, rempty))+  , bundle (inputWDataM, wfull)+  )+ where+  (rdata, rempty, wfull) =+    asyncFIFOSynchronizer d4 clockGen clockGen resetGen resetGen enableGen+      enableGen inputRInc inputWDataM+  inputRInc = fromList $ P.replicate w1 False <> P.replicate n1 True <>+                P.replicate w2 False <> P.replicate 16 True <> P.repeat False+  inputWDataM = fromList $ Nothing : P.map Just [1 .. n1] <>+                  P.replicate w3 Nothing <> P.map Just [n1 + 1 .. n1 + 16] <>+                  P.repeat Nothing++-- Test n.5: Fully fill the FIFO, then empty it again++sync3R5 :: Signal Slow (Bool, (Int, Bool))+sync3W5 :: Signal System (Maybe Int, Bool)+(sync3R5, sync3W5) = sync34RW 0 0 7 0++sync4R5 :: Signal System (Bool, (Int, Bool))+sync4W5 :: Signal Slow (Maybe Int, Bool)+(sync4R5, sync4W5) = sync34RW 0 0 28 0++-- Test n.6: Transfer 3 elements (so pointers are not zero), then fully fill+-- the FIFO, then empty it again++sync3R6 :: Signal Slow (Bool, (Int, Bool))+sync3W6 :: Signal System (Maybe Int, Bool)+(sync3R6, sync3W6) = sync34RW 4 3 4 4++sync4R6 :: Signal System (Bool, (Int, Bool))+sync4W6 :: Signal Slow (Maybe Int, Bool)+(sync4R6, sync4W6) = sync34RW 8 3 25 1++sync56RW+  :: ( KnownDomain dom1+     , KnownDomain dom2+     )+  => ( Signal dom1 (Bool, (Int, Bool))+     , Signal dom2 (Maybe Int, Bool)+     )+sync56RW =+  ( bundle (inputRInc, bundle (rdata, rempty))+  , bundle (inputWDataM, wfull)+  )+ where+  (rdata, rempty, wfull) =+    asyncFIFOSynchronizer d4 clockGen clockGen resetGen resetGen enableGen+      enableGen inputRInc inputWDataM+  inputRInc = not <$> rempty+  inputWDataM = fromList $ Nothing : P.map Just [1 .. 17] <> P.repeat Nothing++-- Test n.7: Read data as quickly as it comes, all through the memory and one+--           beyond the wrap of the circular buffer++sync5R7 :: Signal Slow (Bool, (Int, Bool))+sync5W7 :: Signal System (Maybe Int, Bool)+(sync5R7, sync5W7) = sync56RW++sync6R7 :: Signal System (Bool, (Int, Bool))+sync6W7 :: Signal Slow (Maybe Int, Bool)+(sync6R7, sync6W7) = sync56RW++-- For use with syncXRY syncXWY.+-- It prints (sample number, (input, output))+printTest+  :: (Foldable f, NFDataX a, ShowX a)+  => f a+  -> IO ()+printTest t = P.mapM_ (putStrLn . showX) $ P.zip [1 :: Int ..] $ sampleN 60 t++sampleR+  :: Foldable f+  => Int+  -> f (Bool, (Int, Bool))+  -> [(Bool, (Maybe Int, Bool))]+sampleR n r =+  P.map (\(inputRInc, (rdata, rempty)) -> (inputRInc, (maybeIsX rdata, rempty)))+    (sampleN n r)++-- For creating the expected constants below+printR+  :: Foldable f+  => f (Bool, (Int, Bool))+  -> IO ()+printR r = do+  let (first:rest) = P.map show $ sampleR 60 r+  putStrLn $ (P.foldl (\b a -> b <> "  , " <> a <> "\n")+                ("  [ " <> first <> "\n") rest) <> "  ]"++printW+  :: (Foldable f, NFDataX a, Show a)+  => f a+  -> IO ()+printW w = do+  let (first:rest) = P.map show $ sampleN 60 w+  putStrLn $ (P.foldl (\b a -> b <> "  , " <> a <> "\n")+                ("  [ " <> first <> "\n") rest) <> "  ]"++testR+  :: Foldable f+  => f (Bool, (Int, Bool))+  -> [(Bool, (Maybe Int, Bool))]+  -> Assertion+testR r expected = sampleR (P.length expected) r @?= expected++testW+  :: (Foldable f, NFDataX a, Eq a, Show a)+  => f a+  -> [a]+  -> Assertion+testW w expected = sampleN (P.length expected) w @?= expected+++test1R1 :: Assertion+test1R1 = testR sync1R1+  [ (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Just 1,True))+  , (False,(Just 1,True))+  , (True,(Just 1,False))+  , (True,(Just 2,False))+  , (True,(Just 3,False))+  , (True,(Just 4,False))+  , (False,(Just 5,True))+  , (False,(Just 5,True))+  , (True,(Just 5,False))+  , (True,(Just 6,False))+  , (True,(Just 7,False))+  , (True,(Just 8,False))+  , (False,(Nothing,True))+  ]++test1W1 :: Assertion+test1W1 = testW sync1W1+  [ (Nothing,False)+  , (Just 1,False)+  , (Just 2,False)+  , (Just 3,False)+  , (Just 4,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Just 5,False)+  , (Just 6,False)+  , (Just 7,False)+  , (Just 8,False)+  , (Nothing,False)+  ]++test2R1 :: Assertion+test2R1 = testR sync2R1+  [ (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Just 1,True))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (True,(Just 1,False))+  , (True,(Just 2,False))+  , (True,(Just 3,False))+  , (True,(Just 4,False))+  , (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Just 5,True))+  , (False,(Just 5,False))+  , (False,(Just 5,False))+  , (False,(Just 5,False))+  , (True,(Just 5,False))+  , (True,(Just 6,False))+  , (True,(Just 7,False))+  , (True,(Just 8,False))+  , (False,(Nothing,True))+  ]++test2W1 :: Assertion+test2W1 = testW sync2W1+  [ (Nothing,False)+  , (Just 1,False)+  , (Just 2,False)+  , (Just 3,False)+  , (Just 4,False)+  , (Nothing,False)+  , (Just 5,False)+  , (Just 6,False)+  , (Just 7,False)+  , (Just 8,False)+  , (Nothing,False)+  ]++test1R2 :: Assertion+test1R2 = testR sync1R2+  [ (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Just 1,True))+  , (False,(Just 1,True))+  , (False,(Just 1,False))+  , (True,(Just 1,False))+  , (True,(Just 2,False))+  , (True,(Just 3,False))+  , (True,(Just 4,False))+  , (False,(Just 5,True))+  , (False,(Just 5,False))+  , (True,(Just 5,False))+  , (True,(Just 6,False))+  , (True,(Just 7,False))+  , (True,(Just 8,False))+  , (False,(Nothing,True))+  ]++test1W2 :: Assertion+test1W2 = testW sync1W2+  [ (Nothing,False)+  , (Just 1,False)+  , (Just 2,False)+  , (Just 3,False)+  , (Just 4,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Just 5,False)+  , (Just 6,False)+  , (Just 7,False)+  , (Just 8,False)+  , (Nothing,False)+  ]++test2R2 :: Assertion+test2R2 = testR sync2R2+  [ (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Just 1,True))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (True,(Just 1,False))+  , (True,(Just 2,False))+  , (True,(Just 3,False))+  , (True,(Just 4,False))+  , (False,(Nothing,True))+  , (False,(Just 5,True))+  , (False,(Just 5,False))+  , (False,(Just 5,False))+  , (False,(Just 5,False))+  , (False,(Just 5,False))+  , (False,(Just 5,False))+  , (False,(Just 5,False))+  , (False,(Just 5,False))+  , (False,(Just 5,False))+  , (True,(Just 5,False))+  , (True,(Just 6,False))+  , (True,(Just 7,False))+  , (True,(Just 8,False))+  , (False,(Nothing,True))+  ]++test2W2 :: Assertion+test2W2 = testW sync2W2+  [ (Nothing,False)+  , (Just 1,False)+  , (Just 2,False)+  , (Just 3,False)+  , (Just 4,False)+  , (Nothing,False)+  , (Just 5,False)+  , (Just 6,False)+  , (Just 7,False)+  , (Just 8,False)+  , (Nothing,False)+  ]++test1R3 :: Assertion+test1R3 = testR sync1R3+  [ (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Just 1,True))+  , (False,(Just 1,True))+  , (True,(Just 1,False))+  , (True,(Just 2,False))+  , (True,(Just 3,False))+  , (True,(Just 4,False))+  , (False,(Just 5,True))+  , (False,(Just 5,True))+  , (False,(Just 5,False))+  , (False,(Just 5,False))+  , (True,(Just 5,False))+  , (True,(Just 6,False))+  , (True,(Just 7,False))+  , (True,(Just 8,False))+  , (False,(Nothing,True))+  ]++test1W3 :: Assertion+test1W3 = testW sync1W3+  [ (Nothing,False)+  , (Just 1,False)+  , (Just 2,False)+  , (Just 3,False)+  , (Just 4,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Just 5,False)+  , (Just 6,False)+  , (Just 7,False)+  , (Just 8,False)+  , (Nothing,False)+  ]++test2R3 :: Assertion+test2R3 = testR sync2R3+  [ (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Just 1,True))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (True,(Just 1,False))+  , (True,(Just 2,False))+  , (True,(Just 3,False))+  , (True,(Just 4,False))+  , (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Just 5,True))+  , (False,(Just 5,False))+  , (False,(Just 5,False))+  , (False,(Just 5,False))+  , (False,(Just 5,False))+  , (False,(Just 5,False))+  , (True,(Just 5,False))+  , (True,(Just 6,False))+  , (True,(Just 7,False))+  , (True,(Just 8,False))+  , (False,(Nothing,True))+  ]++test2W3 :: Assertion+test2W3 = testW sync2W3+  [ (Nothing,False)+  , (Just 1,False)+  , (Just 2,False)+  , (Just 3,False)+  , (Just 4,False)+  , (Nothing,False)+  , (Just 5,False)+  , (Just 6,False)+  , (Just 7,False)+  , (Just 8,False)+  , (Nothing,False)+  ]++test1R4 :: Assertion+test1R4 = testR sync1R4+  [ (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Just 1,True))+  , (False,(Just 1,True))+  , (False,(Just 1,False))+  , (True,(Just 1,False))+  , (True,(Just 2,False))+  , (True,(Just 3,False))+  , (True,(Just 4,False))+  , (False,(Just 5,True))+  , (False,(Just 5,False))+  , (False,(Just 5,False))+  , (True,(Just 5,False))+  , (True,(Just 6,False))+  , (True,(Just 7,False))+  , (True,(Just 8,False))+  , (False,(Nothing,True))+  ]++test1W4 :: Assertion+test1W4 = testW sync1W4+  [ (Nothing,False)+  , (Just 1,False)+  , (Just 2,False)+  , (Just 3,False)+  , (Just 4,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Just 5,False)+  , (Just 6,False)+  , (Just 7,False)+  , (Just 8,False)+  , (Nothing,False)+  ]++test2R4 :: Assertion+test2R4 = testR sync2R4+  [ (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Just 1,True))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (True,(Just 1,False))+  , (True,(Just 2,False))+  , (True,(Just 3,False))+  , (True,(Just 4,False))+  , (False,(Nothing,True))+  , (False,(Just 5,True))+  , (False,(Just 5,False))+  , (False,(Just 5,False))+  , (False,(Just 5,False))+  , (False,(Just 5,False))+  , (False,(Just 5,False))+  , (False,(Just 5,False))+  , (False,(Just 5,False))+  , (False,(Just 5,False))+  , (False,(Just 5,False))+  , (False,(Just 5,False))+  , (True,(Just 5,False))+  , (True,(Just 6,False))+  , (True,(Just 7,False))+  , (True,(Just 8,False))+  , (False,(Nothing,True))+  ]++test2W4 :: Assertion+test2W4 = testW sync2W4+  [ (Nothing,False)+  , (Just 1,False)+  , (Just 2,False)+  , (Just 3,False)+  , (Just 4,False)+  , (Nothing,False)+  , (Just 5,False)+  , (Just 6,False)+  , (Just 7,False)+  , (Just 8,False)+  , (Nothing,False)+  ]++test3R5 :: Assertion+test3R5 = testR sync3R5+  [ (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Just 1,True))+  , (False,(Just 1,True))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (True,(Just 1,False))+  , (True,(Just 2,False))+  , (True,(Just 3,False))+  , (True,(Just 4,False))+  , (True,(Just 5,False))+  , (True,(Just 6,False))+  , (True,(Just 7,False))+  , (True,(Just 8,False))+  , (True,(Just 9,False))+  , (True,(Just 10,False))+  , (True,(Just 11,False))+  , (True,(Just 12,False))+  , (True,(Just 13,False))+  , (True,(Just 14,False))+  , (True,(Just 15,False))+  , (True,(Just 16,False))+  , (False,(Just 1,True))+  ]++test3W5 :: Assertion+test3W5 = testW sync3W5+  [ (Nothing,False)+  , (Just 1,False)+  , (Just 2,False)+  , (Just 3,False)+  , (Just 4,False)+  , (Just 5,False)+  , (Just 6,False)+  , (Just 7,False)+  , (Just 8,False)+  , (Just 9,False)+  , (Just 10,False)+  , (Just 11,False)+  , (Just 12,False)+  , (Just 13,False)+  , (Just 14,False)+  , (Just 15,False)+  , (Just 16,False)+  , (Nothing,True)+  , (Nothing,False)+  ]++test4R5 :: Assertion+test4R5 = testR sync4R5+  [ (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Just 1,True))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (True,(Just 1,False))+  , (True,(Just 2,False))+  , (True,(Just 3,False))+  , (True,(Just 4,False))+  , (True,(Just 5,False))+  , (True,(Just 6,False))+  , (True,(Just 7,False))+  , (True,(Just 8,False))+  , (True,(Just 9,False))+  , (True,(Just 10,False))+  , (True,(Just 11,False))+  , (True,(Just 12,False))+  , (True,(Just 13,False))+  , (True,(Just 14,False))+  , (True,(Just 15,False))+  , (True,(Just 16,False))+  , (False,(Just 1,True))+  ]++test4W5 :: Assertion+test4W5 = testW sync4W5+  [ (Nothing,False)+  , (Just 1,False)+  , (Just 2,False)+  , (Just 3,False)+  , (Just 4,False)+  , (Just 5,False)+  , (Just 6,False)+  , (Just 7,False)+  , (Just 8,False)+  , (Just 9,False)+  , (Just 10,False)+  , (Just 11,False)+  , (Just 12,False)+  , (Just 13,False)+  , (Just 14,False)+  , (Just 15,False)+  , (Just 16,False)+  , (Nothing,True)+  , (Nothing,False)+  ]++test3R6 :: Assertion+test3R6 = testR sync3R6+  [ (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Just 1,True))+  , (False,(Just 1,True))+  , (True,(Just 1,False))+  , (True,(Just 2,False))+  , (True,(Just 3,False))+  , (False,(Just 4,True))+  , (False,(Just 4,False))+  , (False,(Just 4,False))+  , (False,(Just 4,False))+  , (True,(Just 4,False))+  , (True,(Just 5,False))+  , (True,(Just 6,False))+  , (True,(Just 7,False))+  , (True,(Just 8,False))+  , (True,(Just 9,False))+  , (True,(Just 10,False))+  , (True,(Just 11,False))+  , (True,(Just 12,False))+  , (True,(Just 13,False))+  , (True,(Just 14,False))+  , (True,(Just 15,False))+  , (True,(Just 16,False))+  , (True,(Just 17,False))+  , (True,(Just 18,False))+  , (True,(Just 19,False))+  , (False,(Just 4,True))+  ]++test3W6 :: Assertion+test3W6 = testW sync3W6+  [ (Nothing,False)+  , (Just 1,False)+  , (Just 2,False)+  , (Just 3,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Nothing,False)+  , (Just 4,False)+  , (Just 5,False)+  , (Just 6,False)+  , (Just 7,False)+  , (Just 8,False)+  , (Just 9,False)+  , (Just 10,False)+  , (Just 11,False)+  , (Just 12,False)+  , (Just 13,False)+  , (Just 14,False)+  , (Just 15,False)+  , (Just 16,False)+  , (Just 17,False)+  , (Just 18,False)+  , (Just 19,False)+  , (Nothing,True)+  , (Nothing,True)+  , (Nothing,False)+  ]++test4R6 :: Assertion+test4R6 = testR sync4R6+  [ (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Just 1,True))+  , (False,(Just 1,False))+  , (False,(Just 1,False))+  , (True,(Just 1,False))+  , (True,(Just 2,False))+  , (True,(Just 3,False))+  , (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Just 4,True))+  , (False,(Just 4,False))+  , (False,(Just 4,False))+  , (False,(Just 4,False))+  , (False,(Just 4,False))+  , (False,(Just 4,False))+  , (False,(Just 4,False))+  , (False,(Just 4,False))+  , (False,(Just 4,False))+  , (False,(Just 4,False))+  , (False,(Just 4,False))+  , (False,(Just 4,False))+  , (False,(Just 4,False))+  , (False,(Just 4,False))+  , (False,(Just 4,False))+  , (False,(Just 4,False))+  , (False,(Just 4,False))+  , (False,(Just 4,False))+  , (False,(Just 4,False))+  , (False,(Just 4,False))+  , (False,(Just 4,False))+  , (False,(Just 4,False))+  , (False,(Just 4,False))+  , (True,(Just 4,False))+  , (True,(Just 5,False))+  , (True,(Just 6,False))+  , (True,(Just 7,False))+  , (True,(Just 8,False))+  , (True,(Just 9,False))+  , (True,(Just 10,False))+  , (True,(Just 11,False))+  , (True,(Just 12,False))+  , (True,(Just 13,False))+  , (True,(Just 14,False))+  , (True,(Just 15,False))+  , (True,(Just 16,False))+  , (True,(Just 17,False))+  , (True,(Just 18,False))+  , (True,(Just 19,False))+  , (False,(Just 4,True))+  ]++test4W6 :: Assertion+test4W6 = testW sync4W6+  [ (Nothing,False)+  , (Just 1,False)+  , (Just 2,False)+  , (Just 3,False)+  , (Nothing,False)+  , (Just 4,False)+  , (Just 5,False)+  , (Just 6,False)+  , (Just 7,False)+  , (Just 8,False)+  , (Just 9,False)+  , (Just 10,False)+  , (Just 11,False)+  , (Just 12,False)+  , (Just 13,False)+  , (Just 14,False)+  , (Just 15,False)+  , (Just 16,False)+  , (Just 17,False)+  , (Just 18,False)+  , (Just 19,False)+  , (Nothing,True)+  , (Nothing,False)+  ]++test5R7 :: Assertion+test5R7 = testR sync5R7+  [ (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Just 1,True))+  , (False,(Just 1,True))+  , (True,(Just 1,False))+  , (True,(Just 2,False))+  , (True,(Just 3,False))+  , (True,(Just 4,False))+  , (True,(Just 5,False))+  , (True,(Just 6,False))+  , (True,(Just 7,False))+  , (True,(Just 8,False))+  , (True,(Just 9,False))+  , (True,(Just 10,False))+  , (True,(Just 11,False))+  , (True,(Just 12,False))+  , (True,(Just 13,False))+  , (True,(Just 14,False))+  , (True,(Just 15,False))+  , (True,(Just 16,False))+  , (True,(Just 17,False))+  , (False,(Just 2,True))+  ]++test5W7 :: Assertion+test5W7 = testW sync5W7+  [ (Nothing,False)+  , (Just 1,False)+  , (Just 2,False)+  , (Just 3,False)+  , (Just 4,False)+  , (Just 5,False)+  , (Just 6,False)+  , (Just 7,False)+  , (Just 8,False)+  , (Just 9,False)+  , (Just 10,False)+  , (Just 11,False)+  , (Just 12,False)+  , (Just 13,False)+  , (Just 14,False)+  , (Just 15,False)+  , (Just 16,False)+  , (Just 17,False)+  , (Nothing,False)+  ]++test6R7 :: Assertion+test6R7 = testR sync6R7+  [ (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Nothing,True))+  , (False,(Just 1,True))+  , (True,(Just 1,False))+  , (False,(Just 2,True))+  , (True,(Just 2,False))+  , (False,(Just 3,True))+  , (True,(Just 3,False))+  , (False,(Just 4,True))+  , (True,(Just 4,False))+  , (False,(Just 5,True))+  , (True,(Just 5,False))+  , (False,(Just 6,True))+  , (True,(Just 6,False))+  , (False,(Just 7,True))+  , (True,(Just 7,False))+  , (False,(Just 8,True))+  , (True,(Just 8,False))+  , (False,(Just 9,True))+  , (True,(Just 9,False))+  , (False,(Just 10,True))+  , (True,(Just 10,False))+  , (False,(Just 11,True))+  , (True,(Just 11,False))+  , (False,(Just 12,True))+  , (True,(Just 12,False))+  , (False,(Just 13,True))+  , (True,(Just 13,False))+  , (False,(Just 14,True))+  , (True,(Just 14,False))+  , (False,(Just 15,True))+  , (True,(Just 15,False))+  , (False,(Just 16,True))+  , (True,(Just 16,False))+  , (False,(Just 17,True))+  , (True,(Just 17,False))+  , (False,(Just 2,True))+  ]++test6W7 :: Assertion+test6W7 = testW sync6W7+  [ (Nothing,False)+  , (Just 1,False)+  , (Just 2,False)+  , (Just 3,False)+  , (Just 4,False)+  , (Just 5,False)+  , (Just 6,False)+  , (Just 7,False)+  , (Just 8,False)+  , (Just 9,False)+  , (Just 10,False)+  , (Just 11,False)+  , (Just 12,False)+  , (Just 13,False)+  , (Just 14,False)+  , (Just 15,False)+  , (Just 16,False)+  , (Just 17,False)+  , (Nothing,False)+  ]++tests :: TestTree+tests = testGroup "asyncFIFOSynchronizer"+  [ testCase "Test 1.1 Read" test1R1+  , testCase "Test 1.1 Write" test1W1+  , testCase "Test 2.1 Read" test2R1+  , testCase "Test 2.1 Write" test2W1+  , testCase "Test 1.2 Read" test1R2+  , testCase "Test 1.2 Write" test1W2+  , testCase "Test 2.2 Read" test2R2+  , testCase "Test 2.2 Write" test2W2+  , testCase "Test 1.3 Read" test1R3+  , testCase "Test 1.3 Write" test1W3+  , testCase "Test 2.3 Read" test2R3+  , testCase "Test 2.3 Write" test2W3+  , testCase "Test 1.4 Read" test1R4+  , testCase "Test 1.4 Write" test1W4+  , testCase "Test 2.4 Read" test2R4+  , testCase "Test 2.4 Write" test2W4+  , testCase "Test 3.5 Read" test3R5+  , testCase "Test 3.5 Write" test3W5+  , testCase "Test 4.5 Read" test4R5+  , testCase "Test 4.5 Write" test4W5+  , testCase "Test 3.6 Read" test3R6+  , testCase "Test 3.6 Write" test3W6+  , testCase "Test 4.6 Read" test4R6+  , testCase "Test 4.6 Write" test4W6+  , testCase "Test 5.7 Read" test5R7+  , testCase "Test 5.7 Write" test5W7+  , testCase "Test 6.7 Read" test6R7+  , testCase "Test 6.7 Write" test6W7+  ]
tests/Clash/Tests/BitVector.hs view
@@ -23,7 +23,7 @@ import qualified Test.Tasty.QuickCheck as Q  import Clash.Prelude-  (Bit, high, low, bitPattern, type (<=), type (-), natToInteger, liftA2, msb)+  (Bit, high, low, bitPattern, type (<=), type (-), natToInteger, liftA2, msb, bLit) import Clash.Sized.Internal.BitVector (BitVector (..))  import Clash.Tests.SizedNum@@ -104,6 +104,22 @@     , H.testProperty "msb @(BitVector 64)" (msbTest @64)     , H.testProperty "msb @(BitVector 128)" (msbTest @128)     , H.testProperty "msb @(BitVector 129)" (msbTest @129)+    ]+  , testGroup "show"+    [ testCase "show0"  $ show @(BitVector 0) 0b0 @?= "0"+    , testCase "show1"  $ show @(BitVector 1) 0b1 @?= "0b1"+    , testCase "show2"  $ show @(BitVector 1) 0b0 @?= "0b0"+    , testCase "show3"  $ show @(BitVector 2) 0b00 @?= "0b00"+    , testCase "show4"  $ show @(BitVector 2) 0b01 @?= "0b01"+    , testCase "show5"  $ show @(BitVector 2) 0b10 @?= "0b10"+    , testCase "show6"  $ show @(BitVector 2) 0b11 @?= "0b11"+    , testCase "show7"  $ show @(BitVector 3) 0b111 @?= "0b111"+    , testCase "show8"  $ show @(BitVector 4) $(bLit "0000") @?= "0b0000"+    , testCase "show9"  $ show @(BitVector 4) $(bLit "000.") @?= "0b000."+    , testCase "show10" $ show @(BitVector 4) $(bLit "010.") @?= "0b010."+    , testCase "show11" $ show @(BitVector 5) $(bLit "1010.") @?= "0b1_010."+    , testCase "show12" $ show @(BitVector 8) $(bLit "0001010.") @?= "0b0001_010."+    , testCase "show13" $ show @(BitVector 9) $(bLit "10001010.") @?= "0b1_0001_010."     ]   ] 
tests/Clash/Tests/BlockRam.hs view
@@ -10,6 +10,23 @@ import Clash.Explicit.BlockRam (blockRam#) import Clash.Prelude +readRam+  :: (HiddenClockResetEnable dom)+  => Signal dom (Unsigned 4)+  -> Signal dom (Unsigned 8)+readRam addr = mux (register False $ addr .<. 8) ram (pure 0xff)+  where+    ram = blockRam1 NoClearOnReset (SNat @8) 0 addr (pure Nothing)++-- If the block RAM uses the address argument too strictly, then it will+-- attempt to access an out of bounds address when using readRam.+--+addrNotTooStrict :: Assertion+addrNotTooStrict =+  let addr = fromList [0..15]+   in List.tail (sampleN @System 15 (readRam addr)) @?=+        [255,0,0,0,0,0,0,0,255,255,255,255,255,255]+ primRam   :: Signal System Int   -> Signal System Bool@@ -48,5 +65,6 @@  tests :: TestTree tests = testGroup "BlockRam"-  [ testCase "Undefined enable" $ primRamAssertion undefEn+  [ testCase "Address strictness" addrNotTooStrict+  , testCase "Undefined enable" $ primRamAssertion undefEn   ]
+ tests/Clash/Tests/BlockRam/Blob.hs view
@@ -0,0 +1,36 @@+module Clash.Tests.BlockRam.Blob where++import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as L+import Data.Functor.Identity+import Hedgehog+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range+import Numeric.Natural+import Test.Tasty+import Test.Tasty.Hedgehog++import Clash.Explicit.BlockRam.Internal (packAsNats, unpackNats)++roundTripProperty :: Property+roundTripProperty = property $ do+  len <- forAll $ Gen.integral $ Range.linear 0 256+  width <- forAll $ Gen.integral $ Range.linear 1 128+  es <- forAll $ Gen.list (Range.singleton len) $+    Gen.integral_ $ Range.constant 0 (2 ^ width - 1)+  tripping (len, width, es) encode decode+ where+  encode :: (Int, Int, [Natural]) -> (Int, Int, B.ByteString, B.ByteString)+  encode (len, width, es) = let (runs, ends) = packAsNats width id es+                            in (len, width, L.toStrict runs, L.toStrict ends)+  decode :: (Int, Int, B.ByteString, B.ByteString)+         -> Identity (Int, Int, [Natural])+  decode (len, width, runs, ends) =+    let es = take 300 $ unpackNats len width runs ends+    in Identity (len, width, es)++tests :: TestTree+tests = testGroup "BlockRam"+  [ testGroup "Blob"+    [ testProperty "Round trip" roundTripProperty ]+  ]
+ tests/Clash/Tests/Counter.hs view
@@ -0,0 +1,110 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE NumericUnderscores #-}++module Clash.Tests.Counter where++import qualified Prelude as P++import Clash.Class.Counter+import Clash.Class.Counter.Internal+import Clash.Prelude+import Data.Proxy+import Data.Typeable++import qualified Hedgehog as H+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range++import           Test.Tasty+import qualified Test.Tasty.Hedgehog as H+import           Test.Tasty.HUnit++genUnsigned :: SNat n -> H.Gen (Unsigned n)+genUnsigned SNat = Gen.frequency+  [ (80, Gen.integral (Range.linear minBound maxBound))+  , (20, pure maxBound) ]++packTest2 ::+  forall a b.+  (KnownNat a, KnownNat b, KnownNat (a + b)) =>+  (Unsigned (a + b) -> Unsigned (a + b)) ->+  ((Unsigned a, Unsigned b) -> (Unsigned a, Unsigned b)) ->+  H.Property+packTest2 f1 f2 = H.property $ do+  a <- H.forAll (genUnsigned (SNat @a))+  b <- H.forAll (genUnsigned (SNat @b))+  let ab = unpack @(Unsigned (a + b)) (pack (a, b))+  f1 ab H.=== unpack (pack (f2 (a, b)))++packSuccTest2 ::+  forall a b.+  (KnownNat a, KnownNat b, KnownNat (a + b)) =>+  Proxy a ->+  Proxy b ->+  H.Property+packSuccTest2 _ _ = packTest2 (satSucc SatWrap) (countSucc @(Unsigned a, Unsigned b))++packPredTest2 ::+  forall a b.+  (KnownNat a, KnownNat b, KnownNat (a + b)) =>+  Proxy a ->+  Proxy b ->+  H.Property+packPredTest2 _ _ = packTest2 (satPred SatWrap) (countPred @(Unsigned a, Unsigned b))++-- | Counting /down/ from 'countMin' should yield 'countMin' at some point+predShouldWrapAround :: forall a. (Eq a, Counter a, Show a) => Proxy a -> Assertion+predShouldWrapAround Proxy =+  let counter = P.take 100_0000 (P.tail (P.iterate countPred countMin)) in+  assertBool "Pred should wrap-around" (countMin @a `P.elem` counter)++-- | Counting /up/ from 'countMin' should yield 'countMin' at some point+succShouldWrapAround :: forall a. (Eq a, Counter a, Show a) => Proxy a -> Assertion+succShouldWrapAround Proxy =+  let counter = P.take 100_000 (P.tail (P.iterate countSucc countMin)) in+  assertBool "Succ should wrap-around" (countMin @a `P.elem` counter)++-- | Counting /down/ from 'countMax' should yield 'countMin' at some point+predShouldSeeCountMin :: forall a. (Eq a, Counter a, Show a) => Proxy a -> Assertion+predShouldSeeCountMin Proxy =+  let counter = P.take 100_0000 (P.tail (P.iterate countPred countMax)) in+  assertBool "Pred should see countMin" (countMin @a `P.elem` counter)++-- | Counting /up/ from 'countMin' should yield 'countMax' at some point+succShouldSeeCountMax :: forall a. (Eq a, Counter a, Show a) => Proxy a -> Assertion+succShouldSeeCountMax Proxy =+  let counter = P.take 100_000 (P.tail (P.iterate countSucc countMin)) in+  assertBool "Succ should see countMax" (countMax @a `P.elem` counter)++quadTest :: forall a. (Eq a, Counter a, Typeable a, Show a) => Proxy a -> TestTree+quadTest proxy = testGroup (show (typeRep proxy))+  [ testCase "succShouldWrapAround" (succShouldWrapAround proxy)+  , testCase "predShouldWrapAround" (predShouldWrapAround proxy)+  , testCase "succShouldSeeCountMax" (succShouldSeeCountMax proxy)+  , testCase "predShouldSeeCountMin" (predShouldSeeCountMin proxy)+  ]++tests :: TestTree+tests = testGroup "All"+  [ H.testProperty "packSuccTest @2 @2"    (packSuccTest2 @2   @2 Proxy Proxy)+  , H.testProperty "packSuccTest @3 @2"    (packSuccTest2 @3   @2 Proxy Proxy)+  , H.testProperty "packSuccTest2 @129 @5" (packSuccTest2 @129 @5 Proxy Proxy)+  , H.testProperty "packPredTest @2 @2"    (packPredTest2 @2   @2 Proxy Proxy)+  , H.testProperty "packPredTest @3 @2"    (packPredTest2 @3   @2 Proxy Proxy)+  , H.testProperty "packPredTest2 @129 @5" (packPredTest2 @129 @5 Proxy Proxy)++  , quadTest (Proxy @(Signed 5))+  , quadTest (Proxy @(Signed 5, Signed 5))+  , quadTest (Proxy @(Signed 2, Signed 2, Unsigned 7))+  , quadTest (Proxy @(Either (Signed 5) (Index 5)))+  ]+++-- Run with:+--+--    ./repld p:tests -T Clash.Tests.Counter.main+--+-- Add -W if you want to run tests in spite of warnings+--+main :: IO ()+main = defaultMain tests
tests/Clash/Tests/Fixed.hs view
@@ -14,6 +14,7 @@  import Clash.Class.Num import Clash.Sized.Fixed (Fixed(..), FracFixedC, NumFixedC, SFixed, UFixed)+import Clash.XException (errorX)  import GHC.TypeLits (KnownNat) @@ -48,6 +49,10 @@   | x < minB  = if minB < 0 then (-maxB) else minB   | x > maxB  = maxB   | otherwise = x+saturate minB maxB _ SatError x+  | x < minB  = errorX "saturate: underflow"+  | x > maxB  = errorX "saturate: overflow"+  | otherwise = x  -- Saturate to bounds of type b. --@@ -83,9 +88,17 @@ satSuccProperty genA = property $ do   satMode <- forAll Gen.enumBounded   a <- forAll genA-  toRational (satSucc satMode a) === (saturateToBounded (Proxy @a) satMode)-                                        (toRational a + 1) +  case satMode of+    SatError+      | toRational (maxBound @a) - 1 < toRational a+      , toRational a <= toRational (maxBound @a)+      -> throwsException (satSucc satMode a)++    _ ->+      toRational (satSucc satMode a) ===+        saturateToBounded (Proxy @a) satMode (toRational a + 1)+ satPredProperty   :: forall a    . (SaturatingNum a, Real a, Show a)@@ -94,8 +107,16 @@ satPredProperty genA = property $ do   satMode <- forAll Gen.enumBounded   a <- forAll genA-  toRational (satPred satMode a) === (saturateToBounded (Proxy @a) satMode)-                                        (toRational a - 1)++  case satMode of+    SatError+      | toRational (minBound @a) <= toRational a+      , toRational a < toRational (minBound @a) + 1+      -> throwsException (satPred satMode a)++    _ ->+      toRational (satPred satMode a) ===+        saturateToBounded (Proxy @a) satMode (toRational a - 1)  saturatingNumLaws   :: (SaturatingNum a, Real a, Show a)
tests/Clash/Tests/Laws/SaturatingNum.hs view
@@ -9,6 +9,7 @@ import Test.Tasty import Test.Tasty.Hedgehog import Test.Tasty.HUnit+import Test.Tasty.HUnit.Extra  import Clash.Class.Num import Clash.Sized.Index (Index)@@ -30,6 +31,8 @@   Gen a ->   Assertion +-- Check that all modes apart from SatError are total. SatError cannot be total+-- as it throws an XException on overflow/underflow. isTotal ::   forall a.   (NFData a, Show a, Eq a) =>@@ -40,9 +43,14 @@   satMode <- forAll Gen.enumBounded   a <- forAll genA   b <- forAll genA-  _ <- evalNF (f satMode a b)-  pure () +  if isTotalMode satMode+     then evalNF (f satMode a b) *> success+     else success+ where+  isTotalMode SatError = False+  isTotalMode _ = True+ satWrapOverflowLaw :: forall a. SaturationLaw a satWrapOverflowLaw _ = satSucc @a SatWrap maxBound @?= minBound @@ -61,6 +69,12 @@ satZeroUnderflowLaw :: forall a. SaturationLaw a satZeroUnderflowLaw _ = satPred @a SatZero minBound @?= 0 +satErrorOverflowLaw :: forall a. SaturationLaw a+satErrorOverflowLaw _ = expectXException (satSucc @a SatError maxBound)++satErrorUnderflowLaw :: forall a. SaturationLaw a+satErrorUnderflowLaw _ = expectXException (satPred @a SatError minBound)+ satSymmetricOverflow :: forall a. SaturationLaw a satSymmetricOverflow _ = satSucc @a SatSymmetric maxBound @?= maxBound @@ -91,7 +105,10 @@     , testCase "SatBound: Become minBound on underflow"                (satBoundUnderflowLaw genA)     , testCase "SatZero: Become 0 on overflow" (satZeroOverflowLaw genA)-    , testCase "SatZero: Become 0 on underflow" (satZeroUnderflowLaw genA) ]+    , testCase "SatZero: Become 0 on underflow" (satZeroUnderflowLaw genA)+    , testCase "SatError: Error on overflow" (satErrorOverflowLaw genA)+    , testCase "SatError: Error on underflow" (satErrorUnderflowLaw genA)+    ]   else     []) <>   [ testProperty "satAddTotal" (isTotal satAdd genA)
+ tests/Clash/Tests/NumNewtypes.hs view
@@ -0,0 +1,286 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeApplications #-}++module Clash.Tests.NumNewtypes (tests) where++import Control.DeepSeq (NFData, force)+import Data.Kind (Type)+import Data.Proxy (Proxy(..))+import GHC.TypeLits (KnownNat)+import Hedgehog+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range+import Hedgehog.Extra+import Hedgehog.Internal.Exception (tryEvaluate)+import Test.Tasty+import Test.Tasty.Hedgehog++import Clash.Class.Num+import Clash.Num.Erroring+import Clash.Num.Overflowing+import Clash.Num.Saturating+import Clash.Num.Wrapping+import Clash.Num.Zeroing+import Clash.Sized.Index (Index)+import Clash.Sized.Signed (Signed)+import Clash.Sized.Unsigned (Unsigned)++tests :: TestTree+tests = testGroup "Numeric Newtypes"+  [ testGroup "Erroring"+      [ testIntegral "Index 4" Error (genErroring (genIndex @4))+      , testIntegral "Signed 4" Error (genErroring (genSigned @4))+      , testIntegral "Unsigned 4" Error (genErroring (genUnsigned @4))+      ]+  , testGroup "Overflowing"+      [ testIntegral "Index 4" Over (genOverflowing (genIndex @4))+      , testIntegral "Signed 4" Over (genOverflowing (genSigned @4))+      , testIntegral "Unsigned 4" Over (genOverflowing (genUnsigned @4))+      ]+  , testGroup "Saturating"+      [ testIntegral "Index 4" Sat (genSaturating (genIndex @4))+      , testIntegral "Signed 4" Sat (genSaturating (genSigned @4))+      , testIntegral "Unsigned 4" Sat (genSaturating (genUnsigned @4))+      ]+  , testGroup "Wrapping"+      [ testIntegral "Index 4" Wrap (genWrapping (genIndex @4))+      , testIntegral "Signed 4" Wrap (genWrapping (genSigned @4))+      , testIntegral "Unsigned 4" Wrap (genWrapping (genUnsigned @4))+      ]+  , testGroup "Zeroing"+      [ testIntegral "Index 4" Zero (genZeroing (genIndex @4))+      , testIntegral "Signed 4" Zero (genZeroing (genSigned @4))+      , testIntegral "Unsigned 4" Zero (genZeroing (genUnsigned @4))+      ]+  ]++testIntegral+  :: (Bounded (f a), Integral (f a), Show (f a), NFData (f a))+  => TestName+  -> Mode f+  -> Gen (f a)+  -> TestTree+testIntegral name mode gen =+  testGroup name+    [ testProperty "Addition" $ checkIntegral2 mode gen (+)+    , testProperty "Subtraction" $ checkIntegral2 mode gen (-)+    , testProperty "Multiplication" $ checkIntegral2 mode gen (*)+    , testProperty "Negation" $ checkIntegral mode gen negate+    , testProperty "Absolute" $ checkIntegral mode gen abs+    , testProperty "Successor" $ checkIntegral mode gen succ+    , testProperty "Predecessor" $ checkIntegral mode gen pred+    , testProperty "Division" $ checkIntegral2 mode gen div+    , testProperty "Modulo" $ checkIntegral2 mode gen mod+    , testProperty "Quotient" $ checkIntegral2 mode gen quot+    , testProperty "Remainder" $ checkIntegral2 mode gen rem+    ]++data Mode :: (Type -> Type) -> Type where+  Error :: Mode Erroring+  Over  :: Mode Overflowing+  Sat   :: Mode Saturating+  Wrap  :: Mode Wrapping+  Zero  :: Mode Zeroing++data BoundsCheck+  = Overflow | Underflow+  deriving (Show)++boundsIntegral+  :: forall a+   . (Bounded a, Integral a)+  => Proxy a+  -> Maybe Integer+  -> Maybe BoundsCheck+boundsIntegral Proxy (Just x)+  | toInteger (maxBound @a) < x = Just Overflow+  | x < toInteger (minBound @a) = Just Underflow+  | otherwise = Nothing++boundsIntegral Proxy Nothing = Just Overflow++tryArithmetic :: (Show a, NFData a) => a -> PropertyT IO (Maybe a)+tryArithmetic x =+  case tryEvaluate (force x) of+    Left err -> do+      footnoteShow err+      pure Nothing++    Right res ->+      pure (Just res)++-- fromInteger wraps for most types, but not Index. So we need this to get the+-- wrapping behaviour we expect.+wrapIntegral+  :: forall a+   . (Bounded a, Integral a)+  => Integer+  -> a+wrapIntegral x =+  let minB = toInteger (minBound @a)+      maxB = toInteger (maxBound @a) + 1+   in fromInteger $! minB + (x - minB) `mod` (maxB - minB)++checkIntegral+  :: forall f a+   . (Bounded (f a), Integral (f a), Show (f a), NFData (f a))+  => Mode f+  -> Gen (f a)+  -> (forall b. Integral b => b -> b)+  -> Property+checkIntegral mode gen op =+  property $ do+    x <- forAll gen+    result <- tryArithmetic (op (toInteger x))++    case boundsIntegral (Proxy @(f a)) result of+      Nothing -> do+        label "InBounds"+        goInBounds result x++      Just info -> do+        collect info+        goOutBounds info result x+ where+  goInBounds mInteger x+    | Over <- mode+    , Just i <- mInteger+    = do let result = op x+         assert (not (hasOverflowed result))+         fromInteger i === result++    | Just i <- mInteger+    = fromInteger i === op x++    | otherwise+    -- If we reach here, the operation which should be in bounds and valid+    -- resulted in an exception being thrown.+    = error "checkIntegral.goInBounds: mInteger should not be Nothing"++  goOutBounds info mInteger x+    | Nothing <- mInteger+    = throwsDeepException (op x)++    | Error <- mode+    = throwsDeepException (op x)++    | Over <- mode+    , Just i <- mInteger+    = do let result = op x+         assert (hasOverflowed result)+         wrapIntegral i === result++    | Sat <- mode+    , Overflow <- info+    = maxBound === op x++    | Sat <- mode+    , Underflow <- info+    = minBound === op x++    | Wrap <- mode+    , Just i <- mInteger+    = wrapIntegral i === op x++    | Zero <- mode+    = 0 === op x++checkIntegral2+  :: forall f a+   . (Bounded (f a), Integral (f a), Show (f a), NFData (f a))+  => Mode f+  -> Gen (f a)+  -> (forall b. Integral b => b -> b -> b)+  -> Property+checkIntegral2 mode gen op =+  property $ do+    x <- forAll gen+    y <- forAll gen+    result <- tryArithmetic (op (toInteger x) (toInteger y))+    footnote ("result: " <> show result)++    case boundsIntegral (Proxy @(f a)) result of+      Nothing -> do+        label "InBounds"+        footnote "InBounds"+        goInBounds result x y++      Just info -> do+        collect info+        footnoteShow info+        goOutBounds info result x y+ where+  goInBounds mInteger x y+    | Over <- mode+    , Just i <- mInteger+    = do let result = op x y+         assert (not (hasOverflowed result))+         fromInteger i === result++    | Just i <- mInteger+    = fromInteger i === op x y++    | otherwise+    = error "checkIntegral2.goInBounds: mInteger should not be Nothing"++  goOutBounds info mInteger x y+    | Nothing <- mInteger+    = throwsDeepException (op x y)++    | Error <- mode+    = throwsDeepException (op x y)++    | Over <- mode+    , Just i <- mInteger+    = do let result = op x y+         assert (hasOverflowed result)+         wrapIntegral i === result++    | Sat <- mode+    , Overflow <- info+    = maxBound === op x y++    | Sat <- mode+    , Underflow <- info+    = minBound === op x y++    | Wrap <- mode+    , Just i <- mInteger+    = wrapIntegral i === op x y++    | Zero <- mode+    = 0 === op x y++genErroring :: forall a. (SaturatingNum a) => Gen a -> Gen (Erroring a)+genErroring = fmap toErroring++genOverflowing :: forall a. (SaturatingNum a) => Gen a -> Gen (Overflowing a)+genOverflowing = fmap toOverflowing++genSaturating :: forall a. (SaturatingNum a) => Gen a -> Gen (Saturating a)+genSaturating = fmap toSaturating++genWrapping :: forall a. (SaturatingNum a) => Gen a -> Gen (Wrapping a)+genWrapping = fmap toWrapping++genZeroing :: forall a. (SaturatingNum a) => Gen a -> Gen (Zeroing a)+genZeroing = fmap toZeroing++genBoundedIntegral :: forall a. (Bounded a, Integral a) => Gen a+genBoundedIntegral = Gen.frequency+  [ (10, pure minBound)+  , (10, pure 0)+  , (40, Gen.integral (Range.linear minBound maxBound))+  , (40, pure maxBound)+  ]++genIndex :: forall n. (KnownNat n) => Gen (Index n)+genIndex = genBoundedIntegral++genSigned :: forall n. (KnownNat n) => Gen (Signed n)+genSigned = genBoundedIntegral++genUnsigned :: forall n. (KnownNat n) => Gen (Unsigned n)+genUnsigned = genBoundedIntegral
tests/Clash/Tests/Ram.hs view
@@ -7,6 +7,9 @@ -- Undefined write address: --    All addresses should read 'undefined'. --+-- OOB write address+--    All addresses should read 'undefined.+-- -- Undefined write data: --    The written-to address should read 'undefined', but other addresses --    should still have their data.@@ -17,6 +20,9 @@ -- Deasserted enable, OOB address --    It shouldn't matter that it is out of bounds. --+-- OOB read address+--    The sample should be undefined, nothing more.+-- -- Read address strictness --    If the read result is not used, out-of-bounds read address shouldn't --    matter (equivalent to issue #1458).@@ -51,8 +57,8 @@  type Samples = [(Int, Bool, Int, Int, Maybe Int)] -initMem, undefEn, undefWAddr, undefWData, enFalse, enFalseOobWAddr,-  oobRAddrStrict+initMem, undefEn, undefWAddr, oobWAddr, undefWData, enFalse, enFalseOobWAddr,+  oobRAddr, oobRAddrStrict   :: Samples  --                               rd  enable     waddr      wdata      dout@@ -70,6 +76,11 @@                               , ( 1, False    , 0        , 3        , Nothing)                               ] +oobWAddr = initMem <>         [ ( 0, True     , 3        , 2        , Just 0 )+                              , ( 0, False    , 0        , 3        , Nothing)+                              , ( 1, False    , 0        , 3        , Nothing)+                              ]+ undefWData = initMem <>       [ ( 0, True     , 0        , undefined, Just 0 )                               , ( 0, False    , 0        , 3        , Nothing)                               , ( 1, False    , 0        , 3        , Just 1 )@@ -85,6 +96,11 @@                               , ( 1, False    , 0        , 3        , Just 1 )                               ] +oobRAddr = initMem <>         [ ( 2, False    , 0        , 3        , Nothing)+                              , ( 0, False    , 0        , 3        , Just 0 )+                              , ( 1, False    , 0        , 3        , Just 1 )+                              ]+ oobRAddrStrict = initMem <>   [ ( 1, False    , 0        , 3        , Just 1 )                               , ( 2, False    , 0        , 3        , Just 4 )                               , ( 0, False    , 0        , 3        , Just 0 )@@ -105,8 +121,10 @@ tests = testGroup "Ram"   [ testCase "Undefined enable" $ ramAssertion ram undefEn   , testCase "Undefined write address" $ ramAssertion ram undefWAddr+  , testCase "OOB write address" $ ramAssertion ram oobWAddr   , testCase "Undefined write data" $ ramAssertion ram undefWData   , testCase "Deasserted enable" $ ramAssertion ram enFalse   , testCase "Deasserted enable, OOB address" $ ramAssertion ram enFalseOobWAddr+  , testCase "OOB read address" $ ramAssertion ram oobRAddr   , testCase "Read address strictness" $ ramAssertion maskOobRead oobRAddrStrict   ]
tests/Clash/Tests/Vector.hs view
@@ -13,10 +13,28 @@ i = id  case_showXVector :: Assertion-case_showXVector = "<1,2,X" @=? showX (1 :> i 2 :> errorX "def")+case_showXVector = "1 :> 2 :> undefined" @=? showX (1 :> i 2 :> errorX "def")  case_showX2DVector :: Assertion-case_showX2DVector = "<<1,X,<3,5>>" @=? showX ((1 :> errorX "def") :> (3 :> i 5 :> Nil) :> Nil)+case_showX2DVector =+      "(1 :> undefined) :> (3 :> 5 :> Nil) :> Nil"+  @=? showX ((1 :> errorX "def") :> (3 :> i 5 :> Nil) :> Nil)++case_showX2DVectorInList :: Assertion+case_showX2DVectorInList =+      "[1 :> undefined,3 :> 5 :> Nil]"+  @=? showX [(1 :> errorX "def"), (3 :> i 5 :> Nil)]++case_showVector :: Assertion+case_showVector = "1 :> 2 :> 3 :> Nil" @=? show (1 :> 2 :> i 3 :> Nil)++case_show2DVector :: Assertion+case_show2DVector =+  "(1 :> 2 :> 3 :> Nil) :> Nil" @=? show ((1 :> 2 :> i 3 :> Nil) :> Nil)++case_showVectorInList :: Assertion+case_showVectorInList =+  "[1 :> 2 :> Nil,3 :> 4 :> Nil]" @=? show [1 :> 2 :> Nil, 3 :> i 4 :> Nil]  tests :: TestTree tests = testGroup "All"
tests/Hedgehog/Extra.hs view
@@ -1,6 +1,12 @@+{-# LANGUAGE TypeApplications #-}+ module Hedgehog.Extra-  (throwsException) where+  ( throwsException+  , throwsDeepException+  ) where +import Control.DeepSeq (NFData, force)+ import Hedgehog (failure, MonadTest, success) import Hedgehog.Internal.Exception (tryEvaluate) import Hedgehog.Internal.Source (HasCallStack, withFrozenCallStack)@@ -15,3 +21,13 @@   case (tryEvaluate x) of     Left _  -> success     Right _ -> withFrozenCallStack failure++throwsDeepException+  :: ( MonadTest m+     , NFData a+     , HasCallStack+     )+  => a+  -> m ()+throwsDeepException =+  throwsException . force
tests/Test/Tasty/HUnit/Extra.hs view
@@ -13,7 +13,7 @@ import Clash.XException (XException)  -- | Succeed if evaluating leads to an XException-expectXException :: (Show a, NFData a) => a -> Assertion+expectXException :: (Show a) => a -> Assertion expectXException a0 =   try @XException (evaluate a0) >>= \case     Left _ -> pure ()
tests/doctests.hs view
@@ -1,14 +1,7 @@-{-# LANGUAGE CPP #-}- module Main where -import Build_doctests (flags, pkgs, module_sources)-import Data.Foldable (traverse_)-import Test.DocTest (doctest)+import System.Environment (getArgs)+import Test.DocTest (mainFromCabal)  main :: IO ()-main = do-  traverse_ putStrLn args-  doctest args- where-  args = flags ++ pkgs ++ module_sources+main = mainFromCabal "clash-prelude" =<< getArgs
tests/unittests.hs view
@@ -2,14 +2,18 @@  import Test.Tasty +import qualified Clash.Tests.AsyncFIFOSynchronizer import qualified Clash.Tests.AutoReg import qualified Clash.Tests.BitPack import qualified Clash.Tests.BitVector import qualified Clash.Tests.BlockRam+import qualified Clash.Tests.BlockRam.Blob+import qualified Clash.Tests.Counter import qualified Clash.Tests.DerivingDataRepr import qualified Clash.Tests.Fixed import qualified Clash.Tests.FixedExhaustive import qualified Clash.Tests.NFDataX+import qualified Clash.Tests.NumNewtypes import qualified Clash.Tests.Ram import qualified Clash.Tests.Reset import qualified Clash.Tests.Resize@@ -24,14 +28,18 @@  tests :: TestTree tests = testGroup "Unittests"-  [ Clash.Tests.AutoReg.tests+  [ Clash.Tests.AsyncFIFOSynchronizer.tests+  , Clash.Tests.AutoReg.tests   , Clash.Tests.BitPack.tests   , Clash.Tests.BitVector.tests   , Clash.Tests.BlockRam.tests+  , Clash.Tests.BlockRam.Blob.tests+  , Clash.Tests.Counter.tests   , Clash.Tests.DerivingDataRepr.tests   , Clash.Tests.Fixed.tests   , Clash.Tests.FixedExhaustive.tests   , Clash.Tests.NFDataX.tests+  , Clash.Tests.NumNewtypes.tests   , Clash.Tests.Ram.tests   , Clash.Tests.Reset.tests   , Clash.Tests.Resize.tests