clash-prelude-1.6.2: Clash: a functional hardware description language - Prelude library
Copyright(C) 2013-2016 University of Twente
2016-2017 Myrtle Software Ltd
2021 QBayLogic B.V.
LicenseBSD2 (see the file LICENSE)
MaintainerQBayLogic B.V. <devops@qbaylogic.com>
Safe HaskellSafe
LanguageHaskell2010

Clash.Class.BitPack

Description

 
Synopsis

Documentation

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.

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).

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)

Methods

pack :: a -> BitVector (BitSize a) Source #

Convert element of type a to a BitVector

>>> 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

>>> pack (-5 :: Signed 6)
0b11_1011
>>> let x = pack (-5 :: Signed 6)
>>> unpack x :: Unsigned 6
59
>>> 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 #

Instances

Instances details
BitPack Bool Source # 
Instance details

Defined in Clash.Class.BitPack.Internal

Associated Types

type BitSize Bool :: Nat Source #

BitPack Double Source # 
Instance details

Defined in Clash.Class.BitPack.Internal

Associated Types

type BitSize Double :: Nat Source #

BitPack Float Source # 
Instance details

Defined in Clash.Class.BitPack.Internal

Associated Types

type BitSize Float :: Nat Source #

BitPack Int Source # 
Instance details

Defined in Clash.Class.BitPack.Internal

Associated Types

type BitSize Int :: Nat Source #

BitPack Int8 Source # 
Instance details

Defined in Clash.Class.BitPack.Internal

Associated Types

type BitSize Int8 :: Nat Source #

BitPack Int16 Source # 
Instance details

Defined in Clash.Class.BitPack.Internal

Associated Types

type BitSize Int16 :: Nat Source #

BitPack Int32 Source # 
Instance details

Defined in Clash.Class.BitPack.Internal

Associated Types

type BitSize Int32 :: Nat Source #

BitPack Int64 Source # 
Instance details

Defined in Clash.Class.BitPack.Internal

Associated Types

type BitSize Int64 :: Nat Source #

BitPack Word Source # 
Instance details

Defined in Clash.Class.BitPack.Internal

Associated Types

type BitSize Word :: Nat Source #

BitPack Word8 Source # 
Instance details

Defined in Clash.Class.BitPack.Internal

Associated Types

type BitSize Word8 :: Nat Source #

BitPack Word16 Source # 
Instance details

Defined in Clash.Class.BitPack.Internal

Associated Types

type BitSize Word16 :: Nat Source #

BitPack Word32 Source # 
Instance details

Defined in Clash.Class.BitPack.Internal

Associated Types

type BitSize Word32 :: Nat Source #

BitPack Word64 Source # 
Instance details

Defined in Clash.Class.BitPack.Internal

Associated Types

type BitSize Word64 :: Nat Source #

BitPack () Source # 
Instance details

Defined in Clash.Class.BitPack.Internal

Associated Types

type BitSize () :: Nat Source #

Methods

pack :: () -> BitVector (BitSize ()) Source #

unpack :: BitVector (BitSize ()) -> () Source #

BitPack CUShort Source # 
Instance details

Defined in Clash.Class.BitPack.Internal

Associated Types

type BitSize CUShort :: Nat Source #

BitPack Half Source # 
Instance details

Defined in Clash.Class.BitPack.Internal

Associated Types

type BitSize Half :: Nat Source #

BitPack Bit Source # 
Instance details

Defined in Clash.Class.BitPack.Internal

Associated Types

type BitSize Bit :: Nat Source #

BitPack a => BitPack (Maybe a) Source # 
Instance details

Defined in Clash.Class.BitPack.Internal

Associated Types

type BitSize (Maybe a) :: Nat Source #

BitPack a => BitPack (Complex a) Source # 
Instance details

Defined in Clash.Class.BitPack.Internal

Associated Types

type BitSize (Complex a) :: Nat Source #

BitPack a => BitPack (Down a) Source # 
Instance details

Defined in Clash.Class.BitPack.Internal

Associated Types

type BitSize (Down a) :: Nat Source #

KnownNat n => BitPack (BitVector n) Source # 
Instance details

Defined in Clash.Class.BitPack.Internal

Associated Types

type BitSize (BitVector n) :: Nat Source #

(KnownNat n, 1 <= n) => BitPack (Index n) Source # 
Instance details

Defined in Clash.Sized.Internal.Index

Associated Types

type BitSize (Index n) :: Nat Source #

KnownNat n => BitPack (Unsigned n) Source # 
Instance details

Defined in Clash.Sized.Internal.Unsigned

Associated Types

type BitSize (Unsigned n) :: Nat Source #

KnownNat n => BitPack (Signed n) Source # 
Instance details

Defined in Clash.Sized.Internal.Signed

Associated Types

type BitSize (Signed n) :: Nat Source #

BitPack a => BitPack (Zeroing a) Source # 
Instance details

Defined in Clash.Num.Zeroing

Associated Types

type BitSize (Zeroing a) :: Nat Source #

BitPack a => BitPack (Wrapping a) Source # 
Instance details

Defined in Clash.Num.Wrapping

Associated Types

type BitSize (Wrapping a) :: Nat Source #

BitPack a => BitPack (Saturating a) Source # 
Instance details

Defined in Clash.Num.Saturating

Associated Types

type BitSize (Saturating a) :: Nat Source #

(BitPack a, KnownNat (BitSize a + 1)) => BitPack (Overflowing a) Source # 
Instance details

Defined in Clash.Num.Overflowing

Associated Types

type BitSize (Overflowing a) :: Nat Source #

BitPack a => BitPack (Erroring a) Source # 
Instance details

Defined in Clash.Num.Erroring

Associated Types

type BitSize (Erroring a) :: Nat Source #

(BitPack a, BitPack b) => BitPack (Either a b) Source # 
Instance details

Defined in Clash.Class.BitPack.Internal

Associated Types

type BitSize (Either a b) :: Nat Source #

Methods

pack :: Either a b -> BitVector (BitSize (Either a b)) Source #

unpack :: BitVector (BitSize (Either a b)) -> Either a b Source #

(BitPack a, BitPack b) => BitPack (a, b) Source #

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 details

Defined in Clash.Class.BitPack.Internal

Associated Types

type BitSize (a, b) :: Nat Source #

Methods

pack :: (a, b) -> BitVector (BitSize (a, b)) Source #

unpack :: BitVector (BitSize (a, b)) -> (a, b) Source #

(KnownNat n, BitPack a) => BitPack (Vec n a) Source # 
Instance details

Defined in Clash.Sized.Vector

Associated Types

type BitSize (Vec n a) :: Nat Source #

Methods

pack :: Vec n a -> BitVector (BitSize (Vec n a)) Source #

unpack :: BitVector (BitSize (Vec n a)) -> Vec n a Source #

(KnownNat d, BitPack a) => BitPack (RTree d a) Source # 
Instance details

Defined in Clash.Sized.RTree

Associated Types

type BitSize (RTree d a) :: Nat Source #

Methods

pack :: RTree d a -> BitVector (BitSize (RTree d a)) Source #

unpack :: BitVector (BitSize (RTree d a)) -> RTree d a Source #

(BitPack a1, KnownNat (BitSize a1), BitPack (a2, a3), KnownNat (BitSize (a2, a3))) => BitPack (a1, a2, a3) Source # 
Instance details

Defined in Clash.Class.BitPack.Internal

Associated Types

type BitSize (a1, a2, a3) :: Nat Source #

Methods

pack :: (a1, a2, a3) -> BitVector (BitSize (a1, a2, a3)) Source #

unpack :: BitVector (BitSize (a1, a2, a3)) -> (a1, a2, a3) Source #

BitPack (rep (int + frac)) => BitPack (Fixed rep int frac) Source # 
Instance details

Defined in Clash.Sized.Fixed

Associated Types

type BitSize (Fixed rep int frac) :: Nat Source #

Methods

pack :: Fixed rep int frac -> BitVector (BitSize (Fixed rep int frac)) Source #

unpack :: BitVector (BitSize (Fixed rep int frac)) -> Fixed rep int frac Source #

isLike :: BitPack a => a -> a -> Bool Source #

Pack both arguments to a BitVector and use 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

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 6
59
>>> 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

boolToBV :: KnownNat n => Bool -> BitVector (n + 1) Source #

Zero-extend a Boolean value to a BitVector of the appropriate size.

>>> boolToBV True :: BitVector 6
0b00_0001
>>> boolToBV False :: BitVector 6
0b00_0000

boolToBit :: Bool -> Bit Source #

Convert a Bool to a Bit

bitToBool :: Bit -> Bool Source #

Convert a Bool to a Bit

packXWith :: KnownNat n => (a -> BitVector n) -> a -> BitVector n Source #

Bit Indexing

(!) :: (BitPack a, Enum i) => a -> i -> Bit Source #

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]
...

slice :: (BitPack a, BitSize a ~ ((m + 1) + i)) => SNat m -> SNat n -> a -> BitVector ((m + 1) - n) Source #

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)

<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)

split :: (BitPack a, BitSize a ~ (m + n), KnownNat n) => a -> (BitVector m, BitVector n) Source #

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)

replaceBit :: (BitPack a, Enum i) => i -> Bit -> a -> a Source #

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]
...

setSlice :: (BitPack a, BitSize a ~ ((m + 1) + i)) => SNat m -> SNat n -> BitVector ((m + 1) - n) -> a -> a Source #

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)

<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)

msb :: BitPack a => a -> Bit Source #

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

lsb :: BitPack a => a -> Bit Source #

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

Bit Reduction

reduceAnd :: BitPack a => a -> Bit Source #

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

reduceOr :: BitPack a => a -> Bit Source #

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

reduceXor :: BitPack a => a -> Bit Source #

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