-
Notifications
You must be signed in to change notification settings - Fork 147
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
satAdd and satMul produce errors for Index 1 #682
Comments
Good catch. So we should change bound checking to 'greater than', instead of 'greater than or equal to'. For example, in --- a/clash-prelude/src/Clash/Sized/Internal/Index.hs
+++ b/clash-prelude/src/Clash/Sized/Internal/Index.hs
@@ -281,8 +281,8 @@ instance (KnownNat n, 1 <= n) => SaturatingNum (Index n) where
satAdd SatWrap a b =
leToPlusKN @1 @n $
case plus# a b of
- z | let m = fromInteger# (natVal (Proxy @ n))
- , z >= m -> resize# (z - m)
+ z | let m = fromInteger# (natVal (Proxy @ (n - 1)))
+ , z > m -> resize# (z - m)
z -> resize# z
satAdd SatZero a b =
leToPlusKN @1 @n $ ..would presumably fix the issue. |
Unfortunately it's not so simple. When you make |
Oh darn, of course. Would --- a/clash-prelude/src/Clash/Sized/Internal/Index.hs
+++ b/clash-prelude/src/Clash/Sized/Internal/Index.hs
@@ -281,8 +281,8 @@ instance (KnownNat n, 1 <= n) => SaturatingNum (Index n) where
satAdd SatWrap a b =
leToPlusKN @1 @n $
case plus# a b of
- z | let m = fromInteger# (natVal (Proxy @ n))
- , z >= m -> resize# (z - m)
+ z | let m0 = fromInteger# (natVal (Proxy @ (n - 1)))
+ m1 = fromInteger# (natVal (Proxy @ n))
+ , z > m0 -> resize# (z - m1)
z -> resize# z
satAdd SatZero a b =
leToPlusKN @1 @n $ work? I guess this case only happens for |
Maybe even something "radical" like: instance SaturatingNum (Index 1) where |
I think special casing it is the most simple and obvious. You could also do something like this at the type level: I created a new function so I can quickly iterate on it:
However This would add quite a few constraints. |
We can't really add constraints to {-# LANGUAGE BangPatterns #-}
instance {-# OVERLAPPING #-} SaturatingNum (Index 1) where
satAdd _ !a !b = 0
satSub _ !a !b = 0
... and change the original instance to: instance (KnownNat n, 2 <= n) => SaturatingNum (Index n) where |
It's not possible to do this with the
|
You're right that, by default,
.. it explains how specificness works in face of
Because Usually, overlapping instances are frowned upon in the Haskell world (due to them potentially breaking consistency), but they're perfectly okay if you use them next to the definition of the type you're making an instance for. |
I interpret this specificity as the specifity of types. E.g. Tried it just now and I can't get it to work. It always complains about the overlapping instances. |
Blimey, you're right! Looks like this isn't going to work! I could have sworn the conditions mentioned were either not and. |
I guess that just forces us to case on the /n/ then. Something like: +{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
@@ -101,7 +102,7 @@ import Clash.Class.Resize (Resize (..))
import Clash.Prelude.BitIndex (replaceBit)
import {-# SOURCE #-} Clash.Sized.Internal.BitVector (BitVector (BV), high, low, undefError)
import qualified Clash.Sized.Internal.BitVector as BV
-import Clash.Promoted.Nat (SNat, snatToNum, leToPlusKN)
+import Clash.Promoted.Nat (SNat(..), snatToNum, leToPlusKN)
import Clash.XException
(ShowX (..), Undefined (..), errorX, showsPrecXWith, rwhnfX)
@@ -278,12 +279,14 @@ times# :: Index m -> Index n -> Index (((m - 1) * (n - 1)) + 1)
times# (I a) (I b) = I (a * b)
instance (KnownNat n, 1 <= n) => SaturatingNum (Index n) where
- satAdd SatWrap a b =
- leToPlusKN @1 @n $
- case plus# a b of
- z | let m = fromInteger# (natVal (Proxy @ n))
- , z >= m -> resize# (z - m)
- z -> resize# z
+ satAdd SatWrap !a !b =
+ case snatToNum @Int (SNat @n) of
+ 1 -> 0
+ _ -> leToPlusKN @1 @n $
+ case plus# a b of
+ z | let m = fromInteger# (natVal (Proxy @ n))
+ , z >= m -> resize# (z - m)
+ z -> resize# z
satAdd SatZero a b =
leToPlusKN @1 @n $
case plus# a b of Clash eliminates |
Actually I discovered something more sinister. For all numeric types which have
VHDL
Verilog
I know that at least in VHDL you can't have an
|
We actually do this on purpose! It's quite common in Haskell to write code in such a way that you end up with zero-width constructs. Because HDL tools don't handle zero-width constructs well, we strip it out entirely. |
I See. My panic was for nothing then 😅. |
Fixed bug that Saturating operations on `Index 1` were unsafe (#682).
Fixed after merging #686 |
satAdd
andsatMul
with any of theSaturationModes
results in out of bounds exceptions when used withIndex 1
even though the operations should be safe.satSub
works fine.It's due to usage of the following code in each of those operations:
m
thus has value1
and sinceAResult (Index 1) (Index 1) ~ Index 1
andMResult (Index 1) (Index 1) ~ Index 1
this is never a valid value and the error is triggered.See here.
The text was updated successfully, but these errors were encountered: