Skip to content

Commit d0f65c4

Browse files
authored
Merge pull request #3106 from clash-lang/eager-collection
`pack` for `Vec` and `RTree`: more defined bits
2 parents 2423678 + 616d33c commit d0f65c4

File tree

6 files changed

+50
-13
lines changed

6 files changed

+50
-13
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
FIXED: In Clash simulation, `pack` for `Vec` and `RTree` had all bits undefined when the spine of the value had an `XException`. Now, those elements with defined bits will output those defined bits. In HDL, this was already the case. Example: consider `xs = 1 :> undefined :> Nil :: Vec 2 (Unsigned 4)` and `ys = 1 :> undefined :: Vec 2 (Unsigned 4). `xs` merely has an undefined element, but `ys` has an undefined spine: it is a `:>` constructor that is undefined. `pack ys` used to be `0b...._....` but is now `0b0001_....`, just as `pack xs` already was.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
FIXED: Clash drops cached normalization result [#3109](https://github.com/clash-lang/clash-compiler/issues/3109)

clash-lib/src/Clash/Normalize.hs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ module Clash.Normalize where
1818

1919
import Control.Exception (throw)
2020
import qualified Control.Lens as Lens
21-
import Control.Monad (when)
21+
import Control.Monad ((>=>), when)
2222
import Control.Monad.State.Strict (State)
2323
import Data.Default (def)
2424
import Data.Either (lefts,partitionEithers)
@@ -143,11 +143,24 @@ runNormalization env supply globals typeTrans peEval eval rcsMap topEnts =
143143
normalize
144144
:: [Id]
145145
-> NormalizeSession BindingMap
146-
normalize [] = return emptyVarEnv
147-
normalize top = do
148-
(new,topNormalized) <- unzip <$> mapM normalize' top
149-
newNormalized <- normalize (concat new)
150-
return (unionVarEnv (mkVarEnv topNormalized) newNormalized)
146+
normalize = go >=> unionWithCache
147+
where
148+
go [] = return emptyVarEnv
149+
go top = do
150+
(new,topNormalized) <- unzip <$> mapM normalize' top
151+
newNormalized <- normalize (concat new)
152+
return (unionVarEnv (mkVarEnv topNormalized) newNormalized)
153+
154+
unionWithCache :: BindingMap -> NormalizeSession BindingMap
155+
unionWithCache env = do
156+
cache <- Lens.use (extra.normalized)
157+
-- We need to include the cache in our final result, forgetting to do so
158+
-- leads to https://github.com/clash-lang/clash-compiler/issues/3109
159+
--
160+
-- On the other hand, just returning the cache as our final result could
161+
-- not be enough, because normalize' might return a non-normalized binder
162+
-- that is later picked up and cleaned up by flattenCallTree.
163+
return (unionVarEnv cache env)
151164

152165
normalize' :: Id -> NormalizeSession ([Id], (Id, Binding Term))
153166
normalize' nm = do

clash-prelude/src/Clash/Sized/RTree.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ import Prelude hiding ((++), (!!), map)
7676
import Test.QuickCheck (Arbitrary (..), CoArbitrary (..))
7777

7878
import Clash.Annotations.Primitive (hasBlackBox)
79-
import Clash.Class.BitPack (BitPack (..), packXWith)
79+
import Clash.Class.BitPack (BitPack (..))
8080
import Clash.Promoted.Nat (SNat (..), UNat (..),
8181
pow2SNat, snatToNum, subSNat, toUNat)
8282
import Clash.Promoted.Nat.Literals (d1)
@@ -212,7 +212,7 @@ instance KnownNat d => Traversable (RTree d) where
212212
instance (KnownNat d, BitPack a) =>
213213
BitPack (RTree d a) where
214214
type BitSize (RTree d a) = (2^d) * (BitSize a)
215-
pack = packXWith (pack . t2v)
215+
pack = pack . t2v . lazyT
216216
unpack = v2t . unpack
217217

218218
type instance Lens.Index (RTree d a) = Int

clash-prelude/src/Clash/Sized/Vector.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ import Clash.Promoted.Nat.Literals (d1)
147147
import Clash.Sized.Internal.BitVector (Bit, BitVector (..), split#)
148148
import Clash.Sized.Index (Index)
149149

150-
import Clash.Class.BitPack (packXWith, BitPack (..))
150+
import Clash.Class.BitPack (BitPack (..))
151151
import Clash.XException (ShowX (..), NFDataX (..), seqX, isX)
152152

153153
{- $setup
@@ -2630,7 +2630,7 @@ smapWithBounds f xs = reverse
26302630

26312631
instance (KnownNat n, BitPack a) => BitPack (Vec n a) where
26322632
type BitSize (Vec n a) = n * (BitSize a)
2633-
pack = packXWith (concatBitVector# . map pack)
2633+
pack = concatBitVector# . map pack . lazyV
26342634
unpack = map unpack . unconcatBitVector#
26352635

26362636
concatBitVector#

clash-prelude/tests/Clash/Tests/BitPack.hs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@ import Test.Tasty
99
import Test.Tasty.HUnit
1010

1111
import Clash.Class.BitPack
12-
import Clash.Sized.Vector
12+
import Clash.Sized.RTree
1313
import Clash.Sized.Signed
14+
import Clash.Sized.Unsigned
15+
import Clash.Sized.Vector
16+
import Clash.XException
1417

1518
import GHC.Generics (Generic)
1619

@@ -26,6 +29,24 @@ data Rec2 = Rec2 { b :: Int, c :: Int } deriving (Generic, BitPack, Eq, Show)
2629
rtt :: (Eq a, Show a, BitPack a) => a -> Assertion
2730
rtt u = unpack (pack u) @?= u
2831

32+
{-
33+
@pack@ will still output defined elements even if the spine is not fully defined.
34+
-}
35+
undefSpineVec :: Assertion
36+
undefSpineVec = showX (pack v) @?= "0b0001_...._...."
37+
where
38+
v :: Vec 3 (Unsigned 4)
39+
v = 1 :> Clash.XException.undefined
40+
41+
{-
42+
@pack@ will still output defined elements even if the spine is not fully defined.
43+
-}
44+
undefSpineRTree :: Assertion
45+
undefSpineRTree = showX (pack t) @?= "0b...._...._0101_...."
46+
where
47+
t :: RTree 2 (Unsigned 4)
48+
t = BR Clash.XException.undefined (BR (LR 5) Clash.XException.undefined)
49+
2950
tests :: TestTree
3051
tests =
3152
testGroup
@@ -46,7 +67,8 @@ tests =
4667
, testCase "SP2" (rtt (P 10))
4768
, testCase "Rec1" (rtt (Rec1 10))
4869
, testCase "Rec2" (rtt (Rec2 10 30))
49-
, testCase "Vec" (rtt ((1 :: Signed 6) :> 2 :> (-5) :> 4 :> Nil))
5070
]
71+
, testCase "Vec" (rtt ((1 :: Signed 6) :> 2 :> (-5) :> 4 :> Nil))
72+
, testCase "undefSpineVec" undefSpineVec
73+
, testCase "undefSpineRTree" undefSpineRTree
5174
]
52-

0 commit comments

Comments
 (0)