clash-compiler icon indicating copy to clipboard operation
clash-compiler copied to clipboard

`Counter` for `Vec`tors

Open gergoerdi opened this issue 6 months ago • 3 comments

How about something like this?

data Endian = BigEndian | LittleEndian

newtype Counters (endianness :: Endian) n a = Counters{ getCounters :: Vec n a }
    deriving (Generic, NFDataX, Eq, Show)

ripple :: ((Bool -> a -> (Bool, a)) -> Bool -> Vec n a -> (Bool, Vec n a)) -> (a -> (Bool, a)) -> Vec n a -> (Bool, Vec n a)
ripple mapAccum f = mapAccum step True
  where
    step carry x = if carry then f x else (False, x)

instance (Counter a, KnownNat n, 1 <= n) => Counter (Counters BigEndian n a) where
    countMin = Counters $ repeat countMin
    countMax = Counters $ repeat countMax

    countSuccOverflow = fmap Counters . ripple mapAccumR countSuccOverflow . getCounters
    countPredOverflow = fmap Counters . ripple mapAccumR countPredOverflow . getCounters

instance (Counter a, KnownNat n, 1 <= n) => Counter (Counters LittleEndian n a) where
    countMin = Counters $ repeat countMin
    countMax = Counters $ repeat countMax

    countSuccOverflow = fmap Counters . ripple mapAccumL countSuccOverflow . getCounters
    countPredOverflow = fmap Counters . ripple mapAccumL countPredOverflow . getCounters

Mostly I just want to be able to use a Counter BigEndian n (Index 10) as the world's least-effort BCD counter...

gergoerdi avatar Aug 17 '24 14:08 gergoerdi