From 388a4998997a36a796144ca14d33faa37b740928 Mon Sep 17 00:00:00 2001 From: Jasper Vinkenvleugel Date: Fri, 2 Aug 2024 11:37:33 +0200 Subject: [PATCH 1/2] Add maybeResize (and friends) --- clash-prelude/src/Clash/Class/Resize.hs | 65 +++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/clash-prelude/src/Clash/Class/Resize.hs b/clash-prelude/src/Clash/Class/Resize.hs index e19d778e5b..e596530c6b 100644 --- a/clash-prelude/src/Clash/Class/Resize.hs +++ b/clash-prelude/src/Clash/Class/Resize.hs @@ -20,6 +20,9 @@ module Clash.Class.Resize , checkedResize , checkedFromIntegral , checkedTruncateB + , maybeResize + , maybeFromIntegral + , maybeTruncateB ) where import Data.Kind (Type) @@ -117,3 +120,65 @@ checkedTruncateB :: f (a + b) -> f a checkedTruncateB v = checkIntegral (Proxy @(f a)) v `seq` truncateB v + +-- | Helper function of 'maybeFromIntegral', 'maybeResize' and 'maybeTruncateB' +maybeIntegral :: + forall a b. + (Integral a, Integral b, Bounded b) => + Proxy b -> + a -> Bool +maybeIntegral Proxy v = + toInteger v < toInteger (maxBound @b) + && toInteger v > toInteger (minBound @b) + +-- | Like 'fromIntegral', but returns 'Nothing' if /a/ is out of bounds for /b/. +-- Useful when you "know" /a/ can't be out of bounds, but would like to have your +-- assumptions checked. +-- +-- * __NB__: Check only affects simulation. I.e., no checks will be inserted +-- into the generated HDL +-- * __NB__: 'fromIntegral' is not well suited for Clash as it will go through +-- 'Integer' which is arbitrarily bounded in HDL. Instead use +-- 'Clash.Class.BitPack.bitCoerce' and the 'Resize' class. +maybeFromIntegral :: + forall a b. + (Integral a, Integral b, Bounded b) => + a -> Maybe b +maybeFromIntegral v = + if maybeIntegral (Proxy @b) v + then Just (fromIntegral v) + else Nothing + +-- | Like 'resize', but returns 'Nothing' if /f a/ is out of bounds for /f b/. +-- Useful when you "know" /f a/ can't be out of bounds, but would like to have your +-- assumptions checked. +-- +-- __NB__: Check only affects simulation. I.e., no checks will be inserted +-- into the generated HDL +maybeResize :: + forall a b f. + ( Resize f + , KnownNat a, Integral (f a) + , KnownNat b, Integral (f b), Bounded (f b) ) => + f a -> Maybe (f b) +maybeResize v = + if maybeIntegral (Proxy @(f b)) v + then Just (resize v) + else Nothing + +-- | Like 'truncateB', but returns 'Nothing' if /f (a + b)/ is out of bounds for +-- /f a/. Useful when you "know" /f (a + b)/ can't be out of bounds, but would +-- like to have your assumptions checked. +-- +-- __NB__: Check only affects simulation. I.e., no checks will be inserted +-- into the generated HDL +maybeTruncateB :: + forall a b f. + ( Resize f + , KnownNat b, Integral (f (a + b)) + , KnownNat a, Integral (f a), Bounded (f a) ) => + f (a + b) -> Maybe (f a) +maybeTruncateB v = + if maybeIntegral (Proxy @(f a)) v + then Just (truncateB v) + else Nothing From c5b9bef3a112b5073aa94ef9cf6fa991e798f51d Mon Sep 17 00:00:00 2001 From: Jasper Vinkenvleugel Date: Fri, 2 Aug 2024 11:45:14 +0200 Subject: [PATCH 2/2] Fix incorrect text in Haddock --- clash-prelude/src/Clash/Class/Resize.hs | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/clash-prelude/src/Clash/Class/Resize.hs b/clash-prelude/src/Clash/Class/Resize.hs index e596530c6b..83db739a38 100644 --- a/clash-prelude/src/Clash/Class/Resize.hs +++ b/clash-prelude/src/Clash/Class/Resize.hs @@ -132,11 +132,9 @@ maybeIntegral Proxy v = && toInteger v > toInteger (minBound @b) -- | Like 'fromIntegral', but returns 'Nothing' if /a/ is out of bounds for /b/. --- Useful when you "know" /a/ can't be out of bounds, but would like to have your --- assumptions checked. --- --- * __NB__: Check only affects simulation. I.e., no checks will be inserted --- into the generated HDL +-- Useful when you do not know /a/ can be out of bounds, and would like to have +-- your assumptions checked. + -- * __NB__: 'fromIntegral' is not well suited for Clash as it will go through -- 'Integer' which is arbitrarily bounded in HDL. Instead use -- 'Clash.Class.BitPack.bitCoerce' and the 'Resize' class. @@ -150,11 +148,8 @@ maybeFromIntegral v = else Nothing -- | Like 'resize', but returns 'Nothing' if /f a/ is out of bounds for /f b/. --- Useful when you "know" /f a/ can't be out of bounds, but would like to have your --- assumptions checked. --- --- __NB__: Check only affects simulation. I.e., no checks will be inserted --- into the generated HDL +-- Useful when you do not know /f a/ can be out of bounds, and would like to +-- have your assumptions checked. maybeResize :: forall a b f. ( Resize f @@ -167,11 +162,8 @@ maybeResize v = else Nothing -- | Like 'truncateB', but returns 'Nothing' if /f (a + b)/ is out of bounds for --- /f a/. Useful when you "know" /f (a + b)/ can't be out of bounds, but would --- like to have your assumptions checked. --- --- __NB__: Check only affects simulation. I.e., no checks will be inserted --- into the generated HDL +-- /f a/. Useful when you do not know /f (a + b)/ can be out of bounds, and +-- would like to have your assumptions checked. maybeTruncateB :: forall a b f. ( Resize f