{-| Copyright : (C) 2013-2016, University of Twente 2021-2024, QBayLogic B.V. License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> -} {-# LANGUAGE CPP #-} {-# 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 [0..5] -- ... (!) :: (BitPack a, Enum i) => a -> i -> Bit (!) a v i i = BitVector (BitSize a) -> Int -> Bit forall (n :: Nat). KnownNat n => BitVector n -> Int -> Bit index# (a -> BitVector (BitSize a) forall a. BitPack a => a -> BitVector (BitSize a) pack a v) (i -> Int forall a. Enum a => a -> Int fromEnum i 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 #if __GLASGOW_HASKELL__ >= 910 >>> 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) <BLANKLINE> #elif __GLASGOW_HASKELL__ == 906 >>> 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) #else >>> 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) #endif -} slice :: (BitPack a, BitSize a ~ ((m + 1) + i)) => SNat m -> SNat n -> a -> BitVector (m + 1 - n) slice :: SNat m -> SNat n -> a -> BitVector ((m + 1) - n) slice SNat m m SNat n n a v = BitVector ((m + 1) + i) -> SNat m -> SNat n -> BitVector ((m + 1) - n) forall (m :: Nat) (i :: Nat) (n :: Nat). BitVector ((m + 1) + i) -> SNat m -> SNat n -> BitVector ((m + 1) - n) slice# (a -> BitVector (BitSize a) forall a. BitPack a => a -> BitVector (BitSize a) pack a v) SNat m m SNat n 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 :: a -> (BitVector m, BitVector n) split a v = BitVector (m + n) -> (BitVector m, BitVector n) forall (n :: Nat) (m :: Nat). KnownNat n => BitVector (m + n) -> (BitVector m, BitVector n) split# (a -> BitVector (BitSize a) forall a. BitPack a => a -> BitVector (BitSize a) pack a 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 [0..5] -- ... replaceBit :: (BitPack a, Enum i) => i -> Bit -> a -> a replaceBit :: i -> Bit -> a -> a replaceBit i i Bit b a v = BitVector (BitSize a) -> a forall a. BitPack a => BitVector (BitSize a) -> a unpack (BitVector (BitSize a) -> Int -> Bit -> BitVector (BitSize a) forall (n :: Nat). KnownNat n => BitVector n -> Int -> Bit -> BitVector n replaceBit# (a -> BitVector (BitSize a) forall a. BitPack a => a -> BitVector (BitSize a) pack a v) (i -> Int forall a. Enum a => a -> Int fromEnum i i) Bit 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 #if __GLASGOW_HASKELL__ >= 910 >>> 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) <BLANKLINE> #elif __GLASGOW_HASKELL__ == 906 >>> 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) #else >>> 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) #endif -} setSlice :: (BitPack a, BitSize a ~ ((m + 1) + i)) => SNat m -> SNat n -> BitVector (m + 1 - n) -> a -> a setSlice :: SNat m -> SNat n -> BitVector ((m + 1) - n) -> a -> a setSlice SNat m m SNat n n BitVector ((m + 1) - n) w a v = BitVector (BitSize a) -> a forall a. BitPack a => BitVector (BitSize a) -> a unpack (SNat ((m + 1) + i) -> BitVector ((m + 1) + i) -> SNat m -> SNat n -> BitVector ((m + 1) - n) -> BitVector ((m + 1) + i) forall (m :: Nat) (i :: Nat) (n :: Nat). SNat ((m + 1) + i) -> BitVector ((m + 1) + i) -> SNat m -> SNat n -> BitVector ((m + 1) - n) -> BitVector ((m + 1) + i) setSlice# SNat ((m + 1) + i) forall (n :: Nat). KnownNat n => SNat n SNat (a -> BitVector (BitSize a) forall a. BitPack a => a -> BitVector (BitSize a) pack a v) SNat m m SNat n n BitVector ((m + 1) - 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 :: a -> Bit msb a v = BitVector (BitSize a) -> Bit forall (n :: Nat). KnownNat n => BitVector n -> Bit msb# (a -> BitVector (BitSize a) forall a. BitPack a => a -> BitVector (BitSize a) pack a 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 :: a -> Bit lsb a v = BitVector (BitSize a) -> Bit forall (n :: Nat). BitVector n -> Bit lsb# (a -> BitVector (BitSize a) forall a. BitPack a => a -> BitVector (BitSize a) pack a v)