| Copyright | (C) 2013-2016 University of Twente 2016-2017 Myrtle Software Ltd 2021-2026 QBayLogic B.V. 2022 Google Inc. 2023 LumiGuide Fietsdetectie B.V. |
|---|---|
| License | BSD2 (see the file LICENSE) |
| Maintainer | QBayLogic B.V. <devops@qbaylogic.com> |
| Safe Haskell | Trustworthy |
| Language | Haskell2010 |
| Extensions |
|
Clash.Class.BitPack.Internal
Description
Synopsis
- class KnownNat (BitSize a) => BitPack a where
- packXWith :: KnownNat n => (a -> BitVector n) -> a -> BitVector n
- isLike :: BitPack a => a -> a -> Bool
- bitCoerce :: (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
- bitCoerceMap :: forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => (a -> a) -> b -> b
- packInt8# :: Int8 -> BitVector 8
- unpackInt8# :: BitVector 8 -> Int8
- packInt16# :: Int16 -> BitVector 16
- unpackInt16# :: BitVector 16 -> Int16
- packInt32# :: Int32 -> BitVector 32
- unpackInt32# :: BitVector 32 -> Int32
- packInt64# :: Int64 -> BitVector 64
- unpackInt64# :: BitVector 64 -> Int64
- packWord# :: Word -> BitVector 64
- unpackWord# :: BitVector 64 -> Word
- packWord8# :: Word8 -> BitVector 8
- unpackWord8# :: BitVector 8 -> Word8
- packWord16# :: Word16 -> BitVector 16
- unpackWord16# :: BitVector 16 -> Word16
- packWord32# :: Word32 -> BitVector 32
- unpackWord32# :: BitVector 32 -> Word32
- packWord64# :: Word64 -> BitVector 64
- unpackWord64# :: BitVector 64 -> Word64
- packFloat# :: Float -> BitVector 32
- unpackFloat# :: BitVector 32 -> Float
- packDouble# :: Double -> BitVector 64
- unpackDouble# :: BitVector 64 -> Double
- packCUShort# :: CUShort -> BitVector 16
- unpackCUShort# :: BitVector 16 -> CUShort
- packChar# :: Char -> BitVector 21
- unpackChar# :: BitVector 21 -> Char
- class GBitPack f where
- type GFieldSize f :: Nat
- type GConstructorCount f :: Nat
- gPackFields :: Int -> f a -> (Int, BitVector (GFieldSize f))
- gUnpack :: Int -> Int -> BitVector (GFieldSize f) -> f a
- gMaybeUnpack :: Bool -> Int -> Int -> BitVector (GFieldSize f) -> Maybe (f a)
- boolToBV :: KnownNat n => Bool -> BitVector (n + 1)
- boolToBit :: Bool -> Bit
- bitToBool :: Bit -> Bool
Documentation
>>>:m -Prelude>>>:set -XDataKinds>>>:set -XDeriveAnyClass>>>:set -fplugin GHC.TypeLits.KnownNat.Solver>>>:set -fplugin GHC.TypeLits.Extra.Solver>>>:set -fplugin GHC.TypeLits.Normalise>>>import Clash.Prelude>>>import Data.Proxy
class KnownNat (BitSize a) => BitPack a where Source #
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.
It is not possible to give data a custom bit representation by providing a
BitPack instance. A BitPack instance allows no creativity and should
always accurately reflect the bit representation of the data in HDL. You
should always derive ( unless you use a custom data
representation, in which case you should use
Generic, BitPack)deriveBitPack. Custom
encodings can be created with Clash.Annotations.BitRepresentation and
Clash.Annotations.BitRepresentation.Deriving.
If the BitPack instance does not accurately match the bit representation of
the data in HDL, Clash designs will exhibit incorrect behavior in various
places.
Clash provides some generic functions on packable types in the prelude, such as indexing into packable structures (see Clash.Class.BitPack.BitIndex) and bitwise reduction of packable data (see Clash.Class.BitPack.BitReduction).
Minimal complete definition
Nothing
Associated Types
type BitSize a :: Nat Source #
Number of Bits needed to represents elements
of type a
Can be derived using Generics:
import Clash.Prelude
import GHC.Generics
data MyProductType = MyProductType { a :: Int, b :: Bool }
deriving (Generic, BitPack)type BitSize a = CLog 2 (GConstructorCount (Rep a)) + GFieldSize (Rep a)
Methods
pack :: a -> BitVector (BitSize a) Source #
Convert element of type a to a BitVector
pack will never raise XException; as BitVector is three-valued,
pack applied to an XException will return a BitVector filled with
undefined bits.
>>>pack (-5 :: Signed 6)0b11_1011
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) Source #
unpack :: BitVector (BitSize a) -> a Source #
Convert a BitVector to an element of type a
When the bit pattern is not the representation of any value of type a,
unpack can return an invalid value, or some value y where
is not equal to the input. Use pack ymaybeUnpack to detect such bit patterns.
>>>pack (-5 :: Signed 6)0b11_1011>>>let x = pack (-5 :: Signed 6)>>>unpack x :: Unsigned 659>>>pack (59 :: Unsigned 6)0b11_1011
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 Source #
maybeUnpack :: BitVector (BitSize a) -> Maybe a Source #
Attempt to convert a BitVector to an element of type a. If the unpacking
is successful, outputs Just a, otherwise outputs Nothing.
Not every bit pattern is necessarily the representation of a value of type
a. If there is no x such that bv == , then pack xmaybeUnpack bv
returns Nothing. Conversely, unpack bv would return an invalid value,
or some value y where is not equal to pack ybv.
>>>pack (maxBound :: Index 13)0b1100>>>let y = pack (maxBound :: Index 13)>>>maybeUnpack y :: Maybe (Index 13)Just 12>>>maybeUnpack (succ y) :: Maybe (Index 13)Nothing>>>data Example1 = Foo | Bar | Baz | Baq | Qux deriving (Generic, NFDataX, BitPack, Show, Eq)>>>maybeUnpack @Example1 0b0000Just Foo>>>fmap (maybeUnpack @Example1 . pack) $ indicesI @(2 ^ (BitSize Example1))Just Foo :> Just Bar :> Just Baz :> Just Baq :> Just Qux :> Nothing :> Nothing :> Nothing :> Nil
It should be noted that if the unpacking fails at any stage, the function returns Nothing:
>>>data Example2 = EIdx (Index 6) Example1 | EUns (Unsigned 3) Example1 deriving (Generic, NFDataX, BitPack, Show, Eq)>>>maybeUnpack @Example2 0b0000000Just (EIdx 0 Foo)>>>maybeUnpack @Example2 0b0101000Just (EIdx 5 Foo)>>>maybeUnpack @Example2 0b0110000 -- Fails to unpack `Index 6`Nothing>>>maybeUnpack @Example2 0b1110000 -- Switching to `EUns` constructor with `Unsigned` arg worksJust (EUns 6 Foo)>>>maybeUnpack @Example2 0b0101111 -- Fails to unpack `Example1`Nothing>>>maybeUnpack @Example2 0b1101111 -- Still fails to unpack `Example1`Nothing>>>maybeUnpack @Example2 0b0111111 -- Fails to unpack both `Index 6` and `Example 1`Nothing
Instances
isLike :: BitPack a => a -> a -> Bool Source #
Pack both arguments to a BitVector and use
isLike# to compare them. This is a more
lenient 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) undefinedTrue>>>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 x1True>>>isLike x1 x2True>>>isLike x2 x3True>>>isLike x1 x3True
NB: Not synthesizable
bitCoerce :: (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b Source #
Coerce a value from one type to another through its bit representation.
>>>pack (-5 :: Signed 6)0b11_1011>>>bitCoerce (-5 :: Signed 6) :: Unsigned 659>>>pack (59 :: Unsigned 6)0b11_1011
bitCoerceMap :: forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => (a -> a) -> b -> b Source #
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
unpackInt8# :: BitVector 8 -> Int8 Source #
packInt16# :: Int16 -> BitVector 16 Source #
unpackInt16# :: BitVector 16 -> Int16 Source #
packInt32# :: Int32 -> BitVector 32 Source #
unpackInt32# :: BitVector 32 -> Int32 Source #
packInt64# :: Int64 -> BitVector 64 Source #
unpackInt64# :: BitVector 64 -> Int64 Source #
unpackWord# :: BitVector 64 -> Word Source #
packWord8# :: Word8 -> BitVector 8 Source #
unpackWord8# :: BitVector 8 -> Word8 Source #
packWord16# :: Word16 -> BitVector 16 Source #
unpackWord16# :: BitVector 16 -> Word16 Source #
packWord32# :: Word32 -> BitVector 32 Source #
unpackWord32# :: BitVector 32 -> Word32 Source #
packWord64# :: Word64 -> BitVector 64 Source #
unpackWord64# :: BitVector 64 -> Word64 Source #
packFloat# :: Float -> BitVector 32 Source #
unpackFloat# :: BitVector 32 -> Float Source #
packDouble# :: Double -> BitVector 64 Source #
unpackDouble# :: BitVector 64 -> Double Source #
packCUShort# :: CUShort -> BitVector 16 Source #
unpackCUShort# :: BitVector 16 -> CUShort Source #
unpackChar# :: BitVector 21 -> Char Source #
class GBitPack f where Source #
Associated Types
type GFieldSize f :: Nat Source #
Size of fields. If multiple constructors exist, this is the maximum of the sum of each of the constructors fields.
type GConstructorCount f :: Nat Source #
Number of constructors this type has. Indirectly indicates how many bits are needed to represent the constructor.
Methods
Arguments
| :: Int | Current constructor |
| -> f a | Data to pack |
| -> (Int, BitVector (GFieldSize f)) | (Constructor number, Packed fields) |
Pack fields of a type. Caller should pack and prepend the constructor bits.
Arguments
| :: Int | Construct with constructor n |
| -> Int | Current constructor |
| -> BitVector (GFieldSize f) | BitVector containing fields |
| -> f a | Unpacked result |
Unpack whole type.
Arguments
| :: Bool | Check whether the constructor is in range. This should only be |
| -> Int | Construct with constructor n |
| -> Int | Current constructor |
| -> BitVector (GFieldSize f) | BitVector containing fields |
| -> Maybe (f a) | Possibly unpacked result |
Attempt to unpack whole type.