From 4d67c5fe8be600ca99b7b07125a4c095275ce818 Mon Sep 17 00:00:00 2001 From: Gergo ERDI Date: Mon, 19 Aug 2024 17:56:28 +0800 Subject: [PATCH] Add `Counter a => Counter (Vec n a)` instance #2787 --- .../src/Clash/Class/Counter/Internal.hs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/clash-prelude/src/Clash/Class/Counter/Internal.hs b/clash-prelude/src/Clash/Class/Counter/Internal.hs index 150bf79fc2..21dc888e28 100644 --- a/clash-prelude/src/Clash/Class/Counter/Internal.hs +++ b/clash-prelude/src/Clash/Class/Counter/Internal.hs @@ -14,6 +14,7 @@ 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(..)) @@ -27,6 +28,7 @@ import GHC.TypeLits (KnownNat, type (<=)) -- >>> import Clash.Sized.Index (Index) -- >>> import Clash.Sized.Signed (Signed) -- >>> import Clash.Sized.Unsigned (Unsigned) +-- >>> import Clash.Sized.Vector (Vec(..)) -- | t'Clash.Class.Counter.Counter' is a class that composes multiple counters -- into a single one. It is similar to odometers found in olds cars, @@ -193,3 +195,26 @@ instance (Counter a0, Counter a1) => Counter (a0, a1) where (overflowA, a1) = countPredOverflow a0 genTupleInstances maxTupleSize + +rippleR :: (a -> (Bool, a)) -> Vec n a -> (Bool, Vec n a) +rippleR f = mapAccumR step True + where + step carry x = if carry then f x else (False, x) + +-- | Counters on vectors increment from right to left. +-- +-- >>> type T = Vec 2 (Index 10) +-- >>> countSucc @T (0 :> 0 :> Nil) +-- 0 :> 1 :> Nil +-- >>> countSucc @T (0 :> 1 :> Nil) +-- 0 :> 2 :> Nil +-- >>> countSucc @T (0 :> 9 :> Nil) +-- 1 :> 0 :> Nil +-- >>> iterate (SNat @5) (countSucc @T) (9 :> 8 :> Nil) +-- (9 :> 8 :> Nil) :> (9 :> 9 :> Nil) :> (0 :> 0 :> Nil) :> (0 :> 1 :> Nil) :> (0 :> 2 :> Nil) :> Nil +instance (Counter a, KnownNat n, 1 <= n) => Counter (Vec n a) where + countMin = Vec.repeat countMin + countMax = Vec.repeat countMax + + countSuccOverflow = rippleR countSuccOverflow + countPredOverflow = rippleR countPredOverflow