{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralisedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
module Clash.Class.Counter.Internal where
import Clash.CPP (maxTupleSize)
import Clash.Class.Counter.TH (genTupleInstances)
import Clash.Sized.BitVector (BitVector, Bit)
import Clash.Sized.Index (Index)
import Clash.Sized.Signed (Signed)
import Clash.Sized.Unsigned (Unsigned)
import Clash.Sized.Vector as Vec (Vec, repeat, mapAccumR)
import Data.Bifunctor (bimap)
import Data.Functor.Identity (Identity(..))
import Data.Int (Int8, Int16, Int32, Int64)
import Data.Word (Word8, Word16, Word32, Word64)
import GHC.TypeLits (KnownNat, type (<=))
class Counter a where
countMin :: a
default countMin :: Bounded a => a
countMin = a
forall a. Bounded a => a
minBound
countMax :: a
default countMax :: Bounded a => a
countMax = a
forall a. Bounded a => a
maxBound
countSuccOverflow :: a -> (Bool, a)
default countSuccOverflow :: (Eq a, Enum a, Bounded a) => a -> (Bool, a)
countSuccOverflow a
a
| a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. Bounded a => a
maxBound = (Bool
True, a
forall a. Counter a => a
countMin)
| Bool
otherwise = (Bool
False, a -> a
forall a. Enum a => a -> a
succ a
a)
countPredOverflow :: a -> (Bool, a)
default countPredOverflow :: (Eq a, Enum a, Bounded a) => a -> (Bool, a)
countPredOverflow a
a
| a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. Bounded a => a
minBound = (Bool
True, a
forall a. Counter a => a
countMax)
| Bool
otherwise = (Bool
False, a -> a
forall a. Enum a => a -> a
pred a
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)
instance Counter Bool
instance Counter Bit
instance Counter Int
instance Counter Int8
instance Counter Int16
instance Counter Int32
instance Counter Int64
instance Counter Word
instance Counter Word8
instance Counter Word16
instance Counter Word32
instance Counter Word64
deriving newtype instance Counter a => Counter (Identity a)
instance Counter a => Counter (Maybe a) where
countMin :: Maybe a
countMin = Maybe a
forall a. Maybe a
Nothing
countMax :: Maybe a
countMax = a -> Maybe a
forall a. a -> Maybe a
Just a
forall a. Counter a => a
countMax
countSuccOverflow :: Maybe a -> (Bool, Maybe a)
countSuccOverflow = \case
Maybe a
Nothing -> (Bool
False, a -> Maybe a
forall a. a -> Maybe a
Just a
forall a. Counter a => a
countMin)
Just a
a0 ->
case a -> (Bool, a)
forall a. Counter a => a -> (Bool, a)
countSuccOverflow a
a0 of
(Bool
True, a
_) -> (Bool
True, Maybe a
forall a. Maybe a
Nothing)
(Bool
False, a
a1) -> (Bool
False, a -> Maybe a
forall a. a -> Maybe a
Just a
a1)
countPredOverflow :: Maybe a -> (Bool, Maybe a)
countPredOverflow = \case
Maybe a
Nothing -> (Bool
True, a -> Maybe a
forall a. a -> Maybe a
Just a
forall a. Counter a => a
countMax)
Just a
a0 ->
case a -> (Bool, a)
forall a. Counter a => a -> (Bool, a)
countPredOverflow a
a0 of
(Bool
True, a
_) -> (Bool
False, Maybe a
forall a. Maybe a
Nothing)
(Bool
False, a
a1) -> (Bool
False, a -> Maybe a
forall a. a -> Maybe a
Just a
a1)
instance (Counter a, Counter b) => Counter (Either a b) where
countMin :: Either a b
countMin = a -> Either a b
forall a b. a -> Either a b
Left a
forall a. Counter a => a
countMin
countMax :: Either a b
countMax = b -> Either a b
forall a b. b -> Either a b
Right b
forall a. Counter a => a
countMax
countSuccOverflow :: Either a b -> (Bool, Either a b)
countSuccOverflow Either a b
e =
case (a -> (Bool, a))
-> (b -> (Bool, b)) -> Either a b -> Either (Bool, a) (Bool, b)
forall (p :: Type -> Type -> Type) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap a -> (Bool, a)
forall a. Counter a => a -> (Bool, a)
countSuccOverflow b -> (Bool, b)
forall a. Counter a => a -> (Bool, a)
countSuccOverflow Either a b
e of
Left (Bool
overflow, a
a) -> (Bool
False, if Bool
overflow then b -> Either a b
forall a b. b -> Either a b
Right b
forall a. Counter a => a
countMin else a -> Either a b
forall a b. a -> Either a b
Left a
a)
Right (Bool
overflow, b
b) -> (Bool
overflow, if Bool
overflow then a -> Either a b
forall a b. a -> Either a b
Left a
forall a. Counter a => a
countMin else b -> Either a b
forall a b. b -> Either a b
Right b
b)
countPredOverflow :: Either a b -> (Bool, Either a b)
countPredOverflow Either a b
e =
case (a -> (Bool, a))
-> (b -> (Bool, b)) -> Either a b -> Either (Bool, a) (Bool, b)
forall (p :: Type -> Type -> Type) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap a -> (Bool, a)
forall a. Counter a => a -> (Bool, a)
countPredOverflow b -> (Bool, b)
forall a. Counter a => a -> (Bool, a)
countPredOverflow Either a b
e of
Left (Bool
overflow, a
a) -> (Bool
overflow, if Bool
overflow then b -> Either a b
forall a b. b -> Either a b
Right b
forall a. Counter a => a
countMax else a -> Either a b
forall a b. a -> Either a b
Left a
a)
Right (Bool
overflow, b
b) -> (Bool
False, if Bool
overflow then a -> Either a b
forall a b. a -> Either a b
Left a
forall a. Counter a => a
countMax else b -> Either a b
forall a b. b -> Either a b
Right b
b)
instance (Counter a0, Counter a1) => Counter (a0, a1) where
countMin :: (a0, a1)
countMin = (a0
forall a. Counter a => a
countMin, a1
forall a. Counter a => a
countMin)
countMax :: (a0, a1)
countMax = (a0
forall a. Counter a => a
countMax, a1
forall a. Counter a => a
countMax)
countSuccOverflow :: (a0, a1) -> (Bool, (a0, a1))
countSuccOverflow (a0
a0, a1
b0) =
if Bool
overflowB
then (Bool
overflowA, (a0
a1, a1
b1))
else (Bool
overflowB, (a0
a0, a1
b1))
where
(Bool
overflowB, a1
b1) = a1 -> (Bool, a1)
forall a. Counter a => a -> (Bool, a)
countSuccOverflow a1
b0
(Bool
overflowA, a0
a1) = a0 -> (Bool, a0)
forall a. Counter a => a -> (Bool, a)
countSuccOverflow a0
a0
countPredOverflow :: (a0, a1) -> (Bool, (a0, a1))
countPredOverflow (a0
a0, a1
b0) =
if Bool
overflowB
then (Bool
overflowA, (a0
a1, a1
b1))
else (Bool
overflowB, (a0
a0, a1
b1))
where
(Bool
overflowB, a1
b1) = a1 -> (Bool, a1)
forall a. Counter a => a -> (Bool, a)
countPredOverflow a1
b0
(Bool
overflowA, a0
a1) = a0 -> (Bool, a0)
forall a. Counter a => a -> (Bool, a)
countPredOverflow a0
a0
genTupleInstances maxTupleSize
rippleR :: (a -> (Bool, a)) -> Vec n a -> (Bool, Vec n a)
rippleR :: (a -> (Bool, a)) -> Vec n a -> (Bool, Vec n a)
rippleR a -> (Bool, a)
f = (Bool -> a -> (Bool, a)) -> Bool -> Vec n a -> (Bool, Vec n a)
forall acc x y (n :: Nat).
(acc -> x -> (acc, y)) -> acc -> Vec n x -> (acc, Vec n y)
mapAccumR Bool -> a -> (Bool, a)
step Bool
True
where
step :: Bool -> a -> (Bool, a)
step Bool
carry a
x = if Bool
carry then a -> (Bool, a)
f a
x else (Bool
False, a
x)
instance (Counter a, KnownNat n, 1 <= n) => Counter (Vec n a) where
countMin :: Vec n a
countMin = a -> Vec n a
forall (n :: Nat) a. KnownNat n => a -> Vec n a
Vec.repeat a
forall a. Counter a => a
countMin
countMax :: Vec n a
countMax = a -> Vec n a
forall (n :: Nat) a. KnownNat n => a -> Vec n a
Vec.repeat a
forall a. Counter a => a
countMax
countSuccOverflow :: Vec n a -> (Bool, Vec n a)
countSuccOverflow = (a -> (Bool, a)) -> Vec n a -> (Bool, Vec n a)
forall a (n :: Nat). (a -> (Bool, a)) -> Vec n a -> (Bool, Vec n a)
rippleR a -> (Bool, a)
forall a. Counter a => a -> (Bool, a)
countSuccOverflow
countPredOverflow :: Vec n a -> (Bool, Vec n a)
countPredOverflow = (a -> (Bool, a)) -> Vec n a -> (Bool, Vec n a)
forall a (n :: Nat). (a -> (Bool, a)) -> Vec n a -> (Bool, Vec n a)
rippleR a -> (Bool, a)
forall a. Counter a => a -> (Bool, a)
countPredOverflow