1+ {-# LANGUAGE ConstraintKinds #-}
12{-# LANGUAGE FlexibleContexts #-}
23{-# LANGUAGE FlexibleInstances #-}
34{-# LANGUAGE GADTs #-}
@@ -16,6 +17,8 @@ Maintainer : QBayLogic B.V. <devops@qbaylogic.com>
1617module Clash.Class.NumConvert.Internal.MaybeNumConvert where
1718
1819import Clash.Class.BitPack
20+ import Clash.Class.NumConvert.Internal.NumConvert (NumConvertCanonical (.. ))
21+ import Clash.Class.NumConvert.Internal.Canonical (Canonical )
1922import Clash.Class.Resize
2023import Clash.Sized.BitVector
2124import Clash.Sized.Index
@@ -25,29 +28,35 @@ import Clash.Sized.Unsigned
2528import GHC.TypeLits (KnownNat , type (+ ), type (<= ), type (^ ))
2629import GHC.TypeLits.Extra (CLog )
2730
28- import Data.Int (Int16 , Int32 , Int64 , Int8 )
29- import Data.Word (Word16 , Word32 , Word64 , Word8 )
30-
3131{- $setup
3232>>> import Clash.Prelude
3333>>> import Clash.Class.NumConvert
34+ >>> import Data.Word
35+ >>> import Data.Int
36+ -}
37+
38+ {- | Internal class for concrete conversions that may fail. This class is used
39+ internally by 'MaybeNumConvert' and should not be used directly. Use
40+ 'MaybeNumConvert' instead.
3441-}
42+ class MaybeNumConvertCanonical a b where
43+ maybeNumConvertCanonical :: a -> Maybe b
3544
3645{- | Conversions that may fail for some values. A successful conversion retains
3746the numerical value interpretation of the source type in the target type. A
3847failure is expressed by returning 'Nothing', never by an 'Clash.XException.XException'.
3948
4049== __Laws__
4150A conversion is either successful or it fails gracefully. I.e., it does not
42- produces produce errors (also see "Clash.XException"). I.e.,
51+ produce errors (also see "Clash.XException"). I.e.,
4352
4453> x == fromMaybe x (maybeNumConvert @a @b x >>= maybeNumConvert @b @a)
4554
4655for all values @x@ of type @a@. It should also preserve the numerical value
4756interpretation of the bits. For types that have an @Integral@ instance, this
4857intuition is captured by:
4958
50- > toInteger x == fromMaybe (toInteger x) (toInteger (numConvert @a @b x) )
59+ > toInteger x == fromMaybe (toInteger x) (toInteger <$> maybeNumConvert @a @b x)
5160
5261If a conversion succeeds one way, it should also succeed the other way. I.e.,
5362
@@ -65,117 +74,79 @@ All implementations should be total, i.e., they should not produce \"bottoms\".
6574
6675Additionally, any implementation should be translatable to synthesizable HDL.
6776-}
68- class MaybeNumConvert a b where
69- {- | Convert a supplied value of type @a@ to a value of type @b@. If the value
70- cannot be represented in the target type, 'Nothing' is returned.
71-
72- >>> maybeNumConvert (1 :: Index 8) :: Maybe (Unsigned 2)
73- Just 1
74- >>> maybeNumConvert (7 :: Index 8) :: Maybe (Unsigned 2)
75- Nothing
76-
77- For the time being, if the input is an 'Clash.XException.XException', then
78- the output is too. This property might be relaxed in the future.
79- -}
80- maybeNumConvert :: a -> Maybe b
77+ type MaybeNumConvert a b =
78+ ( NumConvertCanonical a (Canonical a )
79+ , MaybeNumConvertCanonical (Canonical a ) (Canonical b )
80+ , NumConvertCanonical (Canonical b ) b
81+ )
82+
83+ {- | Convert a supplied value of type @a@ to a value of type @b@. If the value
84+ cannot be represented in the target type, 'Nothing' is returned.
85+
86+ >>> maybeNumConvert (1 :: Index 8) :: Maybe (Unsigned 2)
87+ Just 1
88+ >>> maybeNumConvert (7 :: Index 8) :: Maybe (Unsigned 2)
89+ Nothing
90+
91+ For the time being, if the input is an 'Clash.XException.XException', then
92+ the output is too. This property might be relaxed in the future.
93+ -}
94+ maybeNumConvert :: forall a b . MaybeNumConvert a b => a -> Maybe b
95+ maybeNumConvert a =
96+ fmap (numConvertCanonical @ (Canonical b ) @ b )
97+ $ maybeNumConvertCanonical @ (Canonical a ) @ (Canonical b )
98+ $ numConvertCanonical @ a @ (Canonical a ) a
8199
82- instance (KnownNat n , KnownNat m ) => MaybeNumConvert (Index n ) (Index m ) where
83- maybeNumConvert ! a = maybeResize a
100+ instance (KnownNat n , KnownNat m ) => MaybeNumConvertCanonical (Index n ) (Index m ) where
101+ maybeNumConvertCanonical ! a = maybeResize a
84102
85- instance (KnownNat n , KnownNat m , 1 <= n ) => MaybeNumConvert (Index n ) (Unsigned m ) where
86- maybeNumConvert ! a = maybeResize $ bitCoerce @ _ @ (Unsigned (CLog 2 n )) a
103+ instance (KnownNat n , KnownNat m , 1 <= n ) => MaybeNumConvertCanonical (Index n ) (Unsigned m ) where
104+ maybeNumConvertCanonical ! a = maybeResize $ bitCoerce @ _ @ (Unsigned (CLog 2 n )) a
87105
88- instance (KnownNat n , KnownNat m , 1 <= n ) => MaybeNumConvert (Index n ) (Signed m ) where
89- maybeNumConvert ! a = maybeNumConvert $ bitCoerce @ _ @ (Unsigned (CLog 2 n )) a
106+ instance (KnownNat n , KnownNat m , 1 <= n ) => MaybeNumConvertCanonical (Index n ) (Signed m ) where
107+ maybeNumConvertCanonical ! a = maybeNumConvertCanonical $ bitCoerce @ _ @ (Unsigned (CLog 2 n )) a
90108
91- instance (KnownNat n , KnownNat m , 1 <= n ) => MaybeNumConvert (Index n ) (BitVector m ) where
92- maybeNumConvert ! a = maybeResize $ pack a
109+ instance (KnownNat n , KnownNat m , 1 <= n ) => MaybeNumConvertCanonical (Index n ) (BitVector m ) where
110+ maybeNumConvertCanonical ! a = maybeResize $ pack a
93111
94- instance (KnownNat n , KnownNat m ) => MaybeNumConvert (Unsigned n ) (Index m ) where
95- maybeNumConvert ! a = maybeResize $ bitCoerce @ _ @ (Index (2 ^ n )) a
112+ instance (KnownNat n , KnownNat m ) => MaybeNumConvertCanonical (Unsigned n ) (Index m ) where
113+ maybeNumConvertCanonical ! a = maybeResize $ bitCoerce @ _ @ (Index (2 ^ n )) a
96114
97- instance (KnownNat n , KnownNat m ) => MaybeNumConvert (Unsigned n ) (Unsigned m ) where
98- maybeNumConvert ! a = maybeResize a
115+ instance (KnownNat n , KnownNat m ) => MaybeNumConvertCanonical (Unsigned n ) (Unsigned m ) where
116+ maybeNumConvertCanonical ! a = maybeResize a
99117
100- instance (KnownNat n , KnownNat m ) => MaybeNumConvert (Unsigned n ) (Signed m ) where
101- maybeNumConvert ! a = maybeResize $ bitCoerce @ (Unsigned (n + 1 )) $ extend a
118+ instance (KnownNat n , KnownNat m ) => MaybeNumConvertCanonical (Unsigned n ) (Signed m ) where
119+ maybeNumConvertCanonical ! a = maybeResize $ bitCoerce @ (Unsigned (n + 1 )) $ extend a
102120
103- instance (KnownNat n , KnownNat m ) => MaybeNumConvert (Unsigned n ) (BitVector m ) where
104- maybeNumConvert ! a = maybeResize $ pack a
121+ instance (KnownNat n , KnownNat m ) => MaybeNumConvertCanonical (Unsigned n ) (BitVector m ) where
122+ maybeNumConvertCanonical ! a = maybeResize $ pack a
105123
106- instance (KnownNat n , KnownNat m ) => MaybeNumConvert (Signed n ) (Index m ) where
107- maybeNumConvert n
124+ instance (KnownNat n , KnownNat m ) => MaybeNumConvertCanonical (Signed n ) (Index m ) where
125+ maybeNumConvertCanonical n
108126 | n < 0 = Nothing
109127 | otherwise = maybeResize (bitCoerce @ _ @ (Index (2 ^ n )) (resize n))
110128
111- instance (KnownNat n , KnownNat m ) => MaybeNumConvert (Signed n ) (Unsigned m ) where
112- maybeNumConvert n
129+ instance (KnownNat n , KnownNat m ) => MaybeNumConvertCanonical (Signed n ) (Unsigned m ) where
130+ maybeNumConvertCanonical n
113131 | n < 0 = Nothing
114132 | otherwise = maybeResize (bitCoerce @ (Signed (n + 1 )) (extend n))
115133
116- instance (KnownNat n , KnownNat m ) => MaybeNumConvert (Signed n ) (Signed m ) where
117- maybeNumConvert ! a = maybeResize a
134+ instance (KnownNat n , KnownNat m ) => MaybeNumConvertCanonical (Signed n ) (Signed m ) where
135+ maybeNumConvertCanonical ! a = maybeResize a
118136
119- instance (KnownNat n , KnownNat m ) => MaybeNumConvert (Signed n ) (BitVector m ) where
120- maybeNumConvert n
137+ instance (KnownNat n , KnownNat m ) => MaybeNumConvertCanonical (Signed n ) (BitVector m ) where
138+ maybeNumConvertCanonical n
121139 | n < 0 = Nothing
122140 | otherwise = maybeResize (pack @ (Signed (n + 1 )) (extend n))
123141
124- instance (KnownNat n , KnownNat m ) => MaybeNumConvert (BitVector n ) (Index m ) where
125- maybeNumConvert ! a = maybeResize $ unpack @ (Index (2 ^ n )) a
126-
127- instance (KnownNat n , KnownNat m ) => MaybeNumConvert (BitVector n ) (Unsigned m ) where
128- maybeNumConvert ! a = maybeResize $ unpack @ (Unsigned n ) a
129-
130- instance (KnownNat n , KnownNat m ) => MaybeNumConvert (BitVector n ) (Signed m ) where
131- maybeNumConvert ! a = maybeResize $ unpack @ (Signed (n + 1 )) $ extend a
132-
133- instance (KnownNat n , KnownNat m ) => MaybeNumConvert (BitVector n ) (BitVector m ) where
134- maybeNumConvert ! a = maybeResize a
135-
136- instance (MaybeNumConvert (Unsigned 64 ) a ) => MaybeNumConvert Word a where
137- maybeNumConvert ! a = maybeNumConvert $ bitCoerce @ _ @ (Unsigned 64 ) a
138- instance (MaybeNumConvert (Unsigned 64 ) a ) => MaybeNumConvert Word64 a where
139- maybeNumConvert ! a = maybeNumConvert $ bitCoerce @ _ @ (Unsigned 64 ) a
140- instance (MaybeNumConvert (Unsigned 32 ) a ) => MaybeNumConvert Word32 a where
141- maybeNumConvert ! a = maybeNumConvert $ bitCoerce @ _ @ (Unsigned 32 ) a
142- instance (MaybeNumConvert (Unsigned 16 ) a ) => MaybeNumConvert Word16 a where
143- maybeNumConvert ! a = maybeNumConvert $ bitCoerce @ _ @ (Unsigned 16 ) a
144- instance (MaybeNumConvert (Unsigned 8 ) a ) => MaybeNumConvert Word8 a where
145- maybeNumConvert ! a = maybeNumConvert $ bitCoerce @ _ @ (Unsigned 8 ) a
146-
147- instance (MaybeNumConvert (Signed 64 ) a ) => MaybeNumConvert Int a where
148- maybeNumConvert ! a = maybeNumConvert $ bitCoerce @ _ @ (Signed 64 ) a
149- instance (MaybeNumConvert (Signed 64 ) a ) => MaybeNumConvert Int64 a where
150- maybeNumConvert ! a = maybeNumConvert $ bitCoerce @ _ @ (Signed 64 ) a
151- instance (MaybeNumConvert (Signed 32 ) a ) => MaybeNumConvert Int32 a where
152- maybeNumConvert ! a = maybeNumConvert $ bitCoerce @ _ @ (Signed 32 ) a
153- instance (MaybeNumConvert (Signed 16 ) a ) => MaybeNumConvert Int16 a where
154- maybeNumConvert ! a = maybeNumConvert $ bitCoerce @ _ @ (Signed 16 ) a
155- instance (MaybeNumConvert (Signed 8 ) a ) => MaybeNumConvert Int8 a where
156- maybeNumConvert ! a = maybeNumConvert $ bitCoerce @ _ @ (Signed 8 ) a
157-
158- instance (MaybeNumConvert a (Unsigned 64 )) => MaybeNumConvert a Word where
159- maybeNumConvert ! a = fmap (bitCoerce @ (Unsigned 64 )) $ maybeNumConvert a
160- instance (MaybeNumConvert a (Unsigned 64 )) => MaybeNumConvert a Word64 where
161- maybeNumConvert ! a = fmap (bitCoerce @ (Unsigned 64 )) $ maybeNumConvert a
162- instance (MaybeNumConvert a (Unsigned 32 )) => MaybeNumConvert a Word32 where
163- maybeNumConvert ! a = fmap (bitCoerce @ (Unsigned 32 )) $ maybeNumConvert a
164- instance (MaybeNumConvert a (Unsigned 16 )) => MaybeNumConvert a Word16 where
165- maybeNumConvert ! a = fmap (bitCoerce @ (Unsigned 16 )) $ maybeNumConvert a
166- instance (MaybeNumConvert a (Unsigned 8 )) => MaybeNumConvert a Word8 where
167- maybeNumConvert ! a = fmap (bitCoerce @ (Unsigned 8 )) $ maybeNumConvert a
168-
169- instance (MaybeNumConvert a (Signed 64 )) => MaybeNumConvert a Int64 where
170- maybeNumConvert ! a = fmap (bitCoerce @ (Signed 64 )) $ maybeNumConvert a
171- instance (MaybeNumConvert a (Signed 32 )) => MaybeNumConvert a Int32 where
172- maybeNumConvert ! a = fmap (bitCoerce @ (Signed 32 )) $ maybeNumConvert a
173- instance (MaybeNumConvert a (Signed 16 )) => MaybeNumConvert a Int16 where
174- maybeNumConvert ! a = fmap (bitCoerce @ (Signed 16 )) $ maybeNumConvert a
175- instance (MaybeNumConvert a (Signed 8 )) => MaybeNumConvert a Int8 where
176- maybeNumConvert ! a = fmap (bitCoerce @ (Signed 8 )) $ maybeNumConvert a
177-
178- instance (MaybeNumConvert a (BitVector 1 )) => MaybeNumConvert a Bit where
179- maybeNumConvert ! a = unpack <$> maybeNumConvert a
180- instance (MaybeNumConvert (BitVector 1 ) a ) => MaybeNumConvert Bit a where
181- maybeNumConvert ! a = maybeNumConvert (pack a)
142+ instance (KnownNat n , KnownNat m ) => MaybeNumConvertCanonical (BitVector n ) (Index m ) where
143+ maybeNumConvertCanonical ! a = maybeResize $ unpack @ (Index (2 ^ n )) a
144+
145+ instance (KnownNat n , KnownNat m ) => MaybeNumConvertCanonical (BitVector n ) (Unsigned m ) where
146+ maybeNumConvertCanonical ! a = maybeResize $ unpack @ (Unsigned n ) a
147+
148+ instance (KnownNat n , KnownNat m ) => MaybeNumConvertCanonical (BitVector n ) (Signed m ) where
149+ maybeNumConvertCanonical ! a = maybeResize $ unpack @ (Signed (n + 1 )) $ extend a
150+
151+ instance (KnownNat n , KnownNat m ) => MaybeNumConvertCanonical (BitVector n ) (BitVector m ) where
152+ maybeNumConvertCanonical ! a = maybeResize a
0 commit comments