{-# 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 (<=))
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 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