Skip to content

Commit 1c5c939

Browse files
Merge pull request #1057 from clash-lang/fix1033
Update 'TopEntity' annotations in 'splitArguments'. Fix #1033
2 parents 613c6af + 0ec6cef commit 1c5c939

File tree

15 files changed

+323
-96
lines changed

15 files changed

+323
-96
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
* [#1046](https://github.com/clash-lang/clash-compiler/issues/1046): Don't confuse term/type namespaces in 'lookupIdSubst'
8989
* [#1041](https://github.com/clash-lang/clash-compiler/issues/1041): Nested product types incorrectly decomposed into ports
9090
* [#1058](https://github.com/clash-lang/clash-compiler/issues/1058): Prevent substitution warning when using type equalities in top entities
91+
* [#1033](https://github.com/clash-lang/clash-compiler/issues/1033): Fix issue where Clash breaks when using Clock/Reset/Enable in product types in combination with Synthesize annotations
9192

9293
* Fixes without issue reports:
9394
* Fix bug in `rnfX` defined for `Down` ([baef30e](https://github.com/clash-lang/clash-compiler/commit/baef30eae03dc02ba847ffbb8fae7f365c5287c2))

benchmark/benchmark-normalization.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44
{-# OPTIONS_GHC -Wno-partial-type-signatures #-}
55

66
import Clash.Annotations.BitRepresentation.Internal (CustomReprs)
7-
import Clash.Annotations.TopEntity
87
import Clash.Core.TyCon
98
import Clash.Core.Var
109
import Clash.Driver
1110
import Clash.Driver.Types
1211
import Clash.GHC.Evaluator
12+
import Clash.Netlist.Types (TopEntityT)
1313
import Clash.Primitives.Types
1414

1515
import Criterion.Main
@@ -52,7 +52,7 @@ setupEnv
5252
:: [FilePath]
5353
-> FilePath
5454
-> IO ((BindingMap, TyConMap, IntMap TyConName
55-
,[(Id, Maybe TopEntity, Maybe Id)]
55+
,[TopEntityT]
5656
,CompiledPrimMap, CustomReprs, [Id], Id
5757
)
5858
,Supply.Supply

benchmark/common/BenchmarkCommon.hs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
module BenchmarkCommon where
77

88
import Clash.Annotations.BitRepresentation.Internal (CustomReprs, buildCustomReprs)
9-
import Clash.Annotations.TopEntity
109
import Clash.Backend
1110
import Clash.Backend.VHDL
1211
import Clash.Core.TyCon
@@ -18,7 +17,7 @@ import Clash.GHC.Evaluator
1817
import Clash.GHC.GenerateBindings
1918
import Clash.GHC.NetlistTypes
2019
import Clash.Netlist.BlackBox.Types (HdlSyn(Other))
21-
import Clash.Netlist.Types (HWMap, FilteredHWType)
20+
import Clash.Netlist.Types (HWMap, FilteredHWType, TopEntityT, topId)
2221
import Clash.Primitives.Types
2322

2423
import Util (OverridingBool(..))
@@ -58,7 +57,7 @@ runInputStage
5857
-> IO (BindingMap
5958
,TyConMap
6059
,IntMap TyConName
61-
,[(Id, Maybe TopEntity, Maybe Id)]
60+
,[TopEntityT]
6261
,CompiledPrimMap
6362
,CustomReprs
6463
,[Id]
@@ -67,16 +66,15 @@ runInputStage
6766
runInputStage idirs src = do
6867
pds <- primDirs backend
6968
(bindingsMap,tcm,tupTcm,topEntities,primMap,reprs) <- generateBindings Auto pds idirs [] (hdlKind backend) src Nothing
70-
let topEntityNames = map (\(x,_,_) -> x) topEntities
71-
((topEntity,_,_):_) = topEntities
72-
tm = topEntity
69+
let topEntityNames = map topId topEntities
70+
tm = head topEntityNames
7371
return (bindingsMap,tcm,tupTcm,topEntities, primMap, buildCustomReprs reprs, topEntityNames,tm)
7472

7573
runNormalisationStage
7674
:: [FilePath]
7775
-> String
7876
-> IO (BindingMap
79-
,[(Id, Maybe TopEntity, Maybe Id)]
77+
,[TopEntityT]
8078
,CompiledPrimMap
8179
,TyConMap
8280
,CustomReprs

benchmark/profiling/run/profile-netlist-run.hs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import Clash.Annotations.TopEntity
21
import Clash.Annotations.BitRepresentation.Internal (CustomReprs)
32
import Clash.Backend
43
import Clash.Core.Name
@@ -61,7 +60,7 @@ benchFile idirs src = do
6160
setupEnv
6261
:: FilePath
6362
-> IO (BindingMap
64-
,[(Id, Maybe TopEntity, Maybe Id)]
63+
,[TopEntityT]
6564
,CompiledPrimMap'
6665
,TyConMap
6766
,CustomReprs

clash-ghc/src-ghc/Clash/GHC/GenerateBindings.hs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ import qualified Var as GHC
4141
import qualified SrcLoc as GHC
4242

4343
import Clash.Annotations.BitRepresentation.Internal (DataRepr')
44-
import Clash.Annotations.TopEntity (TopEntity)
4544
import Clash.Annotations.Primitive (HDL, extractPrim)
4645

4746
import Clash.Core.Subst (extendGblSubstList, mkSubst, substTm)
@@ -60,6 +59,7 @@ import Clash.GHC.GHC2Core
6059
makeAllTyCons, qualifiedNameString, emptyGHC2CoreState)
6160
import Clash.GHC.LoadModules (ghcLibDir, loadModules)
6261
import Clash.Netlist.BlackBox.Util (usedArguments)
62+
import Clash.Netlist.Types (TopEntityT(..))
6363
import Clash.Primitives.Types
6464
(Primitive (..), CompiledPrimMap)
6565
import Clash.Primitives.Util (generatePrimMap)
@@ -85,10 +85,7 @@ generateBindings
8585
-> IO ( BindingMap
8686
, TyConMap
8787
, IntMap TyConName
88-
, [( Id
89-
, Maybe TopEntity -- (maybe) TopEntity annotation
90-
, Maybe Id -- (maybe) associated testbench
91-
)]
88+
, [TopEntityT]
9289
, CompiledPrimMap -- The primitives found in '.' and 'primDir'
9390
, [DataRepr']
9491
)
@@ -124,11 +121,13 @@ generateBindings useColor primDirs importDirs dbs hdl modName dflagsM = do
124121
(\m -> fst (RWS.evalRWS m GHC.noSrcSpan tcMap')) $ mapM (\(topEnt,annM,benchM) -> do
125122
topEnt' <- coreToName GHC.varName GHC.varUnique qualifiedNameString topEnt
126123
benchM' <- traverse coreToId benchM
127-
return (topEnt',annM,benchM')) topEntities
128-
topEntities'' = map (\(topEnt,annM,benchM) -> case lookupUniqMap topEnt allBindings of
129-
Just (v,_,_,_) -> (v,annM,benchM)
130-
Nothing -> error "This shouldn't happen"
131-
) topEntities'
124+
return (topEnt', annM, benchM')) topEntities
125+
topEntities'' =
126+
map (\(topEnt, annM, benchM) ->
127+
case lookupUniqMap topEnt allBindings of
128+
Just (v,_,_,_) -> TopEntityT v annM benchM
129+
Nothing -> error "This shouldn't happen"
130+
) topEntities'
132131
-- Parsing / compiling primitives:
133132
prepTime <- startTime `deepseq` primMapC `seq` Clock.getCurrentTime
134133
let prepStartDiff = reportTimeDiff prepTime startTime

clash-lib/src/Clash/Annotations/TopEntity/Extra.hs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@
99
module Clash.Annotations.TopEntity.Extra where
1010

1111
import Clash.Annotations.TopEntity (TopEntity, PortName)
12+
import Clash.Netlist.Types (TopEntityT)
1213
import Language.Haskell.TH.Syntax
1314
(ModName, Name, NameFlavour, NameSpace, PkgName, OccName)
1415
import Data.Binary (Binary)
1516
import Data.Hashable (Hashable)
1617
import Control.DeepSeq (NFData)
1718

19+
instance Binary TopEntityT
1820
instance Binary TopEntity
1921
instance Binary PortName
2022

@@ -25,6 +27,7 @@ instance Binary ModName
2527
instance Binary NameSpace
2628
instance Binary PkgName
2729

30+
instance Hashable TopEntityT
2831
instance Hashable TopEntity
2932
instance Hashable PortName
3033

@@ -35,6 +38,7 @@ instance Hashable NameSpace
3538
instance Hashable PkgName
3639
instance Hashable OccName
3740

41+
instance NFData TopEntityT
3842
instance NFData TopEntity
3943
instance NFData PortName
4044

clash-lib/src/Clash/Core/Util.hs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -982,11 +982,32 @@ shouldSplit0 tcm (TyConApp tcNm tyArgs)
982982
, [dc] <- tyConDataCons tc
983983
, let dcArgs = substArgTys dc tyArgs
984984
, let dcArgVs = map (tyView . coreView tcm) dcArgs
985-
= if any (\ty -> isJust (shouldSplit0 tcm ty) || splitTy ty) dcArgVs then
985+
= if any shouldSplitTy dcArgVs && not (isHidden tcNm tyArgs) then
986986
Just (mkApps (Data dc) (map Right tyArgs), dcArgs)
987987
else
988988
Nothing
989989
where
990+
shouldSplitTy :: TypeView -> Bool
991+
shouldSplitTy ty = isJust (shouldSplit0 tcm ty) || splitTy ty
992+
993+
-- Hidden constructs (HiddenClock, HiddenReset, ..) don't need to be split
994+
-- because KnownDomain will be filtered anyway during netlist generation due
995+
-- to it being a zero-width type
996+
--
997+
-- TODO: This currently only handles (IP $x, KnownDomain) given that $x is any
998+
-- TODO: of the constructs handled in 'splitTy'. In practise this means only
999+
-- TODO: HiddenClock, HiddenReset, and HiddenEnable are handled. If a user were
1000+
-- TODO: to define their own versions with -for example- the elements of the
1001+
-- TODO: tuple swapped, 'isHidden' wouldn't recognize it. We could generalize
1002+
-- TODO: this in the future.
1003+
--
1004+
isHidden :: Name a -> [Type] -> Bool
1005+
isHidden nm [a1, a2] | TyConApp a2Nm _ <- tyView a2 =
1006+
nameOcc nm == "GHC.Classes.(%,%)"
1007+
&& splitTy (tyView (stripIP a1))
1008+
&& nameOcc a2Nm == "Clash.Signal.Internal.KnownDomain"
1009+
isHidden _ _ = False
1010+
9901011
-- Currently we're only interested in splitting of Clock, Reset, and Enable
9911012
splitTy (TyConApp tcNm0 _)
9921013
= nameOcc tcNm0 `elem` [ "Clash.Signal.Internal.Clock"
@@ -1025,6 +1046,12 @@ splitShouldSplit tcm = foldr go []
10251046
Just (_,tys) -> splitShouldSplit tcm tys ++ rest
10261047
Nothing -> ty : rest
10271048

1049+
-- | Strip implicit parameter wrappers (IP)
1050+
stripIP :: Type -> Type
1051+
stripIP t@(tyView -> TyConApp tcNm [_a1, a2]) =
1052+
if nameOcc tcNm == "GHC.Classes.IP" then a2 else t
1053+
stripIP t = t
1054+
10281055
-- | Do an inverse topological sorting of the let-bindings in a let-expression
10291056
inverseTopSortLetBindings
10301057
:: HasCallStack

0 commit comments

Comments
 (0)