clash-lib 1.4.7 → 1.6.0
raw patch · 386 files changed
+24090/−21834 lines, 386 filesdep +Globdep +asyncdep +stringsearchdep −errorsdep −parsersdep −processdep ~aesondep ~basedep ~bytestringnew-component:exe:v16-upgrade-primitivesPVP ok
version bump matches the API change (PVP)
Dependencies added: Glob, async, stringsearch, yaml
Dependencies removed: errors, parsers, process, reducers, text-show, utf8-string
Dependency ranges changed: aeson, base, bytestring, clash-prelude, containers, deepseq, directory, ghc
API changes (from Hackage documentation)
- Clash.Core.EqSolver: altEqs :: TyConMap -> Alt -> [(Type, Type)]
- Clash.Core.EqSolver: isAbsurdAlt :: TyConMap -> Alt -> Bool
- Clash.Core.FreeVars: hasLocalFreeVars :: Term -> Bool
- Clash.Core.FreeVars: localFVsOfTerms :: Foldable f => f Term -> VarSet
- Clash.Core.FreeVars: localIdDoesNotOccurIn :: Id -> Term -> Bool
- Clash.Core.FreeVars: localIdOccursIn :: Id -> Term -> Bool
- Clash.Core.FreeVars: localIdsDoNotOccurIn :: [Id] -> Term -> Bool
- Clash.Core.FreeVars: noFreeVarsOfType :: Type -> Bool
- Clash.Core.FreeVars: tyFVsOfTypes :: Foldable f => f Type -> VarSet
- Clash.Core.Literal: literalType :: Literal -> Type
- Clash.Core.PartialEval.NormalForm: NeLetrec :: ![(Id, a)] -> !a -> Neutral a
- Clash.Core.Term: Letrec :: [LetBinding] -> Term -> Term
- Clash.Core.Term: idToVar :: Id -> Term
- Clash.Core.TermInfo: applyTypeToArgs :: Term -> TyConMap -> Type -> [Either Term Type] -> Type
- Clash.Core.TermInfo: isLam :: Term -> Bool
- Clash.Core.TermInfo: multiPrimType :: PrimInfo -> Type
- Clash.Core.TermInfo: piResultTy :: HasCallStack => TyConMap -> Type -> Type -> Type
- Clash.Core.TermInfo: piResultTyMaybe :: HasCallStack => TyConMap -> Type -> Type -> Maybe Type
- Clash.Core.TermInfo: piResultTys :: HasCallStack => TyConMap -> Type -> [Type] -> Type
- Clash.Core.TermInfo: termType :: TyConMap -> Term -> Type
- Clash.Core.TermLiteral: uncheckedTermToData :: TermLiteral a => Term -> a
- Clash.Core.Termination: data RecInfo
- Clash.Core.Termination: instance GHC.Base.Monoid Clash.Core.Termination.RecInfo
- Clash.Core.Termination: instance GHC.Base.Semigroup Clash.Core.Termination.RecInfo
- Clash.Core.Termination: instance GHC.Show.Show Clash.Core.Termination.RecInfo
- Clash.Core.Termination: isRecursive :: Id -> RecInfo -> Bool
- Clash.Core.Termination: mkRecInfo :: BindingMap -> RecInfo
- Clash.Core.Termination: recursiveGroup :: Id -> RecInfo -> Maybe VarSet
- Clash.Core.TyCon: SuperKindTyCon :: {-# UNPACK #-} !Unique -> !TyConName -> TyCon
- Clash.Core.Type: typeKind :: TyConMap -> Type -> Kind
- Clash.Core.Type: undefinedTy :: Type
- Clash.Core.Util: undefinedTm :: Type -> Term
- Clash.Core.Var: setVarType :: Var a -> Type -> Var a
- Clash.Core.Var: setVarUnique :: Var a -> Unique -> Var a
- Clash.Debug: traceShowWith :: Show b => (a -> b) -> a -> a
- Clash.Debug: traceWith :: (a -> String) -> a -> a
- Clash.Driver.Manifest: [inPorts] :: Manifest -> [ManifestPort]
- Clash.Driver.Manifest: [outPorts] :: Manifest -> [ManifestPort]
- Clash.Driver.Types: DebugAll :: DebugLevel
- Clash.Driver.Types: DebugApplied :: DebugLevel
- Clash.Driver.Types: DebugFinal :: DebugLevel
- Clash.Driver.Types: DebugName :: DebugLevel
- Clash.Driver.Types: DebugNone :: DebugLevel
- Clash.Driver.Types: DebugSilent :: DebugLevel
- Clash.Driver.Types: DebugTry :: DebugLevel
- Clash.Driver.Types: [opt_dbgLevel] :: ClashOpts -> DebugLevel
- Clash.Driver.Types: [opt_dbgRewriteHistoryFile] :: ClashOpts -> Maybe FilePath
- Clash.Driver.Types: [opt_dbgTransformationsFrom] :: ClashOpts -> Int
- Clash.Driver.Types: [opt_dbgTransformationsLimit] :: ClashOpts -> Int
- Clash.Driver.Types: [opt_dbgTransformations] :: ClashOpts -> Set String
- Clash.Driver.Types: [opt_floatSupport] :: ClashOpts -> Bool
- Clash.Driver.Types: data DebugLevel
- Clash.Driver.Types: instance Data.Hashable.Class.Hashable Clash.Driver.Types.DebugLevel
- Clash.Driver.Types: instance GHC.Classes.Eq Clash.Driver.Types.DebugLevel
- Clash.Driver.Types: instance GHC.Classes.Ord Clash.Driver.Types.DebugLevel
- Clash.Driver.Types: instance GHC.Enum.Enum Clash.Driver.Types.DebugLevel
- Clash.Driver.Types: instance GHC.Generics.Generic Clash.Driver.Types.DebugLevel
- Clash.Driver.Types: instance GHC.Read.Read Clash.Driver.Types.DebugLevel
- Clash.Driver.Types: instance GHC.Show.Show Clash.Driver.Types.SdcInfo
- Clash.Netlist.Types: instance Clash.Netlist.Types.IdentifierSetMonad m => Clash.Netlist.Types.IdentifierSetMonad (Data.Semigroup.Monad.Mon m)
- Clash.Netlist.Types: netlistId :: (Identifier -> r) -> (Id -> r) -> NetlistId -> [r]
- Clash.Netlist.Util: id2type :: Id -> Type
- Clash.Netlist.Util: typeLength :: HWType -> Int
- Clash.Netlist.Util: unsafeCoreTypeToHWType' :: SrcSpan -> String -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> CustomReprs -> TyConMap -> Type -> State HWMap HWType
- Clash.Normalize.DEC: collectGlobals :: InScopeSet -> [(Term, Term)] -> [Term] -> Term -> RewriteMonad NormalizeState (Term, InScopeSet, [(Term, ([Term], CaseTree [Either Term Type]))])
- Clash.Normalize.DEC: collectGlobalsArgs :: InScopeSet -> [(Term, Term)] -> [Term] -> [Either Term Type] -> RewriteMonad NormalizeState ([Either Term Type], InScopeSet, [(Term, ([Term], CaseTree [Either Term Type]))])
- Clash.Normalize.DEC: instance Data.Foldable.Foldable Clash.Normalize.DEC.CaseTree
- Clash.Normalize.DEC: instance GHC.Base.Functor Clash.Normalize.DEC.CaseTree
- Clash.Normalize.DEC: instance GHC.Classes.Eq a => GHC.Classes.Eq (Clash.Normalize.DEC.CaseTree a)
- Clash.Normalize.DEC: instance GHC.Show.Show a => GHC.Show.Show (Clash.Normalize.DEC.CaseTree a)
- Clash.Normalize.DEC: isDisjoint :: CaseTree [Either Term Type] -> Bool
- Clash.Normalize.DEC: mkDisjointGroup :: InScopeSet -> (Term, ([Term], CaseTree [Either Term Type])) -> RewriteMonad NormalizeState (Term, [Term])
- Clash.Normalize.PrimitiveReductions: extractHead :: DataCon -> Type -> Integer -> Term -> Term
- Clash.Normalize.PrimitiveReductions: extractTail :: DataCon -> Type -> Integer -> Term -> Term
- Clash.Normalize.Strategy: topdownRR :: Rewrite extra -> Rewrite extra
- Clash.Normalize.Transformations: appPropFast :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: argCastSpec :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: bindConstantVar :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: caseCase :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: caseCast :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: caseCon :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: caseElemNonReachable :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: caseFlat :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: caseLet :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: constantSpec :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: deadCode :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: disjointExpressionConsolidation :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: elemExistentials :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: eliminateCastCast :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: etaExpandSyn :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: etaExpansionTL :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: flattenLet :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: inlineBndrsCleanup :: HasCallStack => InScopeSet -> VarEnv ((Id, Term), VarEnv Int) -> VarEnv ((Id, Term), VarEnv Int, Mark) -> [((Id, Term), VarEnv Int)] -> [(Id, Term)]
- Clash.Normalize.Transformations: inlineCast :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: inlineCleanup :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: inlineHO :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: inlineNonRep :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: inlineOrLiftNonRep :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: inlineSimIO :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: inlineSmall :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: inlineWorkFree :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: letCast :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: makeANF :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: nonRepANF :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: nonRepSpec :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: recToLetRec :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: reduceConst :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: reduceNonRepPrim :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: removeUnusedExpr :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: separateArguments :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: separateLambda :: TyConMap -> TransformContext -> Id -> Term -> Maybe Term
- Clash.Normalize.Transformations: setupMultiResultPrim :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: simpleCSE :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: splitCastWork :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: topLet :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: typeSpec :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: xOptimize :: HasCallStack => NormRewrite
- Clash.Normalize.Types: [_inlineConstantLimit] :: NormalizeState -> !Word
- Clash.Normalize.Types: [_inlineFunctionLimit] :: NormalizeState -> !Word
- Clash.Normalize.Types: [_inlineLimit] :: NormalizeState -> !Int
- Clash.Normalize.Types: [_inlineWFCacheLimit] :: NormalizeState -> !Word
- Clash.Normalize.Types: [_newInlineStrategy] :: NormalizeState -> Bool
- Clash.Normalize.Types: [_normalizeUltra] :: NormalizeState -> Bool
- Clash.Normalize.Types: [_primitives] :: NormalizeState -> CompiledPrimMap
- Clash.Normalize.Types: [_specialisationLimit] :: NormalizeState -> !Int
- Clash.Normalize.Types: inlineConstantLimit :: Lens' NormalizeState Word
- Clash.Normalize.Types: inlineFunctionLimit :: Lens' NormalizeState Word
- Clash.Normalize.Types: inlineLimit :: Lens' NormalizeState Int
- Clash.Normalize.Types: inlineWFCacheLimit :: Lens' NormalizeState Word
- Clash.Normalize.Types: newInlineStrategy :: Lens' NormalizeState Bool
- Clash.Normalize.Types: normalizeUltra :: Lens' NormalizeState Bool
- Clash.Normalize.Types: primitives :: Lens' NormalizeState CompiledPrimMap
- Clash.Normalize.Types: specialisationLimit :: Lens' NormalizeState Int
- Clash.Normalize.Util: isClosed :: TyConMap -> Term -> Bool
- Clash.Normalize.Util: removedTm :: Type -> Term
- Clash.Normalize.Util: specializeNorm :: NormRewrite
- Clash.Primitives.Util: decodeOrErr :: (HasCallStack, FromJSON a) => FilePath -> ByteString -> a
- Clash.Rewrite.Combinators: bottomupWhenR :: Monad m => (TransformContext -> Term -> m Bool) -> Transform m -> Transform m
- Clash.Rewrite.Combinators: whenR :: Monad m => (TransformContext -> Term -> m Bool) -> Transform m -> Transform m
- Clash.Rewrite.Types: [_aggressiveXOpt] :: RewriteEnv -> Bool
- Clash.Rewrite.Types: [_customReprs] :: RewriteEnv -> CustomReprs
- Clash.Rewrite.Types: [_dbgLevel] :: RewriteEnv -> DebugLevel
- Clash.Rewrite.Types: [_dbgRewriteHistoryFile] :: RewriteEnv -> Maybe FilePath
- Clash.Rewrite.Types: [_dbgTransformationsFrom] :: RewriteEnv -> Int
- Clash.Rewrite.Types: [_dbgTransformationsLimit] :: RewriteEnv -> Int
- Clash.Rewrite.Types: [_dbgTransformations] :: RewriteEnv -> Set String
- Clash.Rewrite.Types: [_fuelLimit] :: RewriteEnv -> Word
- Clash.Rewrite.Types: [_tcCache] :: RewriteEnv -> TyConMap
- Clash.Rewrite.Types: [_tupleTcCache] :: RewriteEnv -> IntMap TyConName
- Clash.Rewrite.Types: dbgLevel :: Lens' RewriteEnv DebugLevel
- Clash.Rewrite.Types: dbgRewriteHistoryFile :: Lens' RewriteEnv (Maybe FilePath)
- Clash.Rewrite.Types: dbgTransformations :: Lens' RewriteEnv (Set String)
- Clash.Rewrite.Types: dbgTransformationsFrom :: Lens' RewriteEnv Int
- Clash.Rewrite.Types: dbgTransformationsLimit :: Lens' RewriteEnv Int
- Clash.Rewrite.Types: instance Control.Monad.Fail.MonadFail (Clash.Rewrite.Types.RewriteMonad extra)
- Clash.Rewrite.Util: specArgBndrsAndVars :: Either Term Type -> ([Either Id TyVar], [Either Term Type])
- Clash.Rewrite.Util: specialise :: Lens' extra (Map (Id, Int, Either Term Type) Id) -> Lens' extra (VarEnv Int) -> Lens' extra Int -> Rewrite extra
- Clash.Rewrite.Util: specialise' :: Lens' extra (Map (Id, Int, Either Term Type) Id) -> Lens' extra (VarEnv Int) -> Lens' extra Int -> TransformContext -> Term -> (Term, [Either Term Type], [TickInfo]) -> Either Term Type -> RewriteMonad extra Term
- Clash.Rewrite.Util: uniqAwayBinder :: BindingMap -> Name a -> Name a
- Clash.Util: (&&&) :: Arrow a => a b c -> a b c' -> a b (c, c')
- Clash.Util: (***) :: Arrow a => a b c -> a b' c' -> a (b, b') (c, c')
- Clash.Util: (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
- Clash.Util: (>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
- Clash.Util: combineM :: Applicative f => (a -> f b) -> (c -> f d) -> (a, c) -> f (b, d)
- Clash.Util: first :: Arrow a => a b c -> a (b, d) (c, d)
- Clash.Util: infixl 0 `on`
- Clash.Util: infixr 1 >=>
- Clash.Util: infixr 3 ***
- Clash.Util: makeLenses :: Name -> DecsQ
- Clash.Util: on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
- Clash.Util: orElse :: Maybe a -> Maybe a -> Maybe a
- Clash.Util: second :: Arrow a => a b c -> a (d, b) (d, c)
- Clash.Util: type HasCallStack = ?callStack :: CallStack
+ Clash.Backend: RenderEnums :: Bool -> RenderEnums
+ Clash.Backend: domainConfigurations :: Backend state => State state DomainMap
+ Clash.Backend: emptyDomainMap :: DomainMap
+ Clash.Backend: newtype RenderEnums
+ Clash.Backend: renderEnums :: Backend state => State state RenderEnums
+ Clash.Backend: setDomainConfigurations :: Backend state => DomainMap -> state -> state
+ Clash.Backend: type DomainMap = HashMap Text VDomainConfiguration
+ Clash.Core.DataCon: Lazy :: DcStrictness
+ Clash.Core.DataCon: Strict :: DcStrictness
+ Clash.Core.DataCon: [dcArgStrict] :: DataCon -> [DcStrictness]
+ Clash.Core.DataCon: data DcStrictness
+ Clash.Core.DataCon: instance Control.DeepSeq.NFData Clash.Core.DataCon.DcStrictness
+ Clash.Core.DataCon: instance Data.Binary.Class.Binary Clash.Core.DataCon.DcStrictness
+ Clash.Core.DataCon: instance Data.Hashable.Class.Hashable Clash.Core.DataCon.DcStrictness
+ Clash.Core.DataCon: instance GHC.Classes.Eq Clash.Core.DataCon.DcStrictness
+ Clash.Core.DataCon: instance GHC.Generics.Generic Clash.Core.DataCon.DcStrictness
+ Clash.Core.EqSolver: isAbsurdPat :: TyConMap -> Pat -> Bool
+ Clash.Core.EqSolver: patEqs :: TyConMap -> Pat -> [(Type, Type)]
+ Clash.Core.HasFreeVars: class HasFreeVars a
+ Clash.Core.HasFreeVars: disjointFreeVars :: HasFreeVars a => VarSet -> a -> Bool
+ Clash.Core.HasFreeVars: elemFreeVars :: HasFreeVars a => Var a -> a -> Bool
+ Clash.Core.HasFreeVars: freeVarsOf :: HasFreeVars a => a -> VarSet
+ Clash.Core.HasFreeVars: instance (Data.Foldable.Foldable f, Clash.Core.HasFreeVars.HasFreeVars a) => Clash.Core.HasFreeVars.HasFreeVars (f a)
+ Clash.Core.HasFreeVars: instance Clash.Core.HasFreeVars.HasFreeVars Clash.Core.Term.Term
+ Clash.Core.HasFreeVars: instance Clash.Core.HasFreeVars.HasFreeVars Clash.Core.Type.Type
+ Clash.Core.HasFreeVars: isClosed :: HasFreeVars a => a -> Bool
+ Clash.Core.HasFreeVars: notElemFreeVars :: HasFreeVars a => Var a -> a -> Bool
+ Clash.Core.HasFreeVars: subsetFreeVars :: HasFreeVars a => VarSet -> a -> Bool
+ Clash.Core.HasType: applyTypeToArgs :: Term -> TyConMap -> Type -> [Either Term Type] -> Type
+ Clash.Core.HasType: class HasType a
+ Clash.Core.HasType: class InferType a
+ Clash.Core.HasType: coreKindOf :: HasType a => a -> Kind
+ Clash.Core.HasType: coreTypeOf :: HasType a => a -> Type
+ Clash.Core.HasType: inferCoreKindOf :: InferType a => TyConMap -> a -> Kind
+ Clash.Core.HasType: inferCoreTypeOf :: InferType a => TyConMap -> a -> Type
+ Clash.Core.HasType: instance Clash.Core.HasType.HasType (Clash.Core.Var.Var a)
+ Clash.Core.HasType: instance Clash.Core.HasType.HasType Clash.Core.DataCon.DataCon
+ Clash.Core.HasType: instance Clash.Core.HasType.HasType Clash.Core.Literal.Literal
+ Clash.Core.HasType: instance Clash.Core.HasType.HasType Clash.Core.Term.PrimInfo
+ Clash.Core.HasType: instance Clash.Core.HasType.HasType Clash.Core.TyCon.TyCon
+ Clash.Core.HasType: instance Clash.Core.HasType.HasType Clash.Core.Type.Type
+ Clash.Core.HasType: instance Clash.Core.HasType.InferType Clash.Core.Term.Term
+ Clash.Core.HasType: instance Clash.Core.HasType.InferType Clash.Core.Type.Type
+ Clash.Core.HasType: piResultTy :: HasCallStack => TyConMap -> Type -> Type -> Type
+ Clash.Core.HasType: piResultTys :: HasCallStack => TyConMap -> Type -> [Type] -> Type
+ Clash.Core.PartialEval.NormalForm: NeLet :: !Bind a -> !a -> Neutral a
+ Clash.Core.Term: Let :: !Bind Term -> Term -> Term
+ Clash.Core.Term: NoUnfolding :: PrimUnfolding
+ Clash.Core.Term: NonRec :: Id -> a -> Bind a
+ Clash.Core.Term: Rec :: [(Id, a)] -> Bind a
+ Clash.Core.Term: Unfolding :: !Id -> PrimUnfolding
+ Clash.Core.Term: WorkIdentity :: Int -> [Int] -> WorkInfo
+ Clash.Core.Term: [primUnfolding] :: PrimInfo -> !PrimUnfolding
+ Clash.Core.Term: data Bind a
+ Clash.Core.Term: data PrimUnfolding
+ Clash.Core.Term: instance Control.DeepSeq.NFData Clash.Core.Term.PrimUnfolding
+ Clash.Core.Term: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Clash.Core.Term.Bind a)
+ Clash.Core.Term: instance Data.Binary.Class.Binary Clash.Core.Term.PrimUnfolding
+ Clash.Core.Term: instance Data.Binary.Class.Binary a => Data.Binary.Class.Binary (Clash.Core.Term.Bind a)
+ Clash.Core.Term: instance Data.Hashable.Class.Hashable Clash.Core.Term.PrimUnfolding
+ Clash.Core.Term: instance Data.Hashable.Class.Hashable a => Data.Hashable.Class.Hashable (Clash.Core.Term.Bind a)
+ Clash.Core.Term: instance GHC.Base.Functor Clash.Core.Term.Bind
+ Clash.Core.Term: instance GHC.Classes.Eq Clash.Core.Term.PrimUnfolding
+ Clash.Core.Term: instance GHC.Classes.Eq a => GHC.Classes.Eq (Clash.Core.Term.Bind a)
+ Clash.Core.Term: instance GHC.Generics.Generic (Clash.Core.Term.Bind a)
+ Clash.Core.Term: instance GHC.Generics.Generic Clash.Core.Term.PrimUnfolding
+ Clash.Core.Term: instance GHC.Show.Show Clash.Core.Term.PrimUnfolding
+ Clash.Core.Term: instance GHC.Show.Show a => GHC.Show.Show (Clash.Core.Term.Bind a)
+ Clash.Core.Term: pattern Letrec :: [LetBinding] -> Term -> Term
+ Clash.Core.TermInfo: isTick :: Term -> Bool
+ Clash.Core.TyCon: PromotedDataCon :: {-# UNPACK #-} !Unique -> !TyConName -> !Kind -> !Int -> !DataCon -> TyCon
+ Clash.Core.TyCon: [tyConData] :: TyCon -> !DataCon
+ Clash.Core.TyCon: isPrimTc :: TyCon -> Bool
+ Clash.Core.TyCon: isPromotedDc :: TyCon -> Bool
+ Clash.Core.TysPrim: eqPrimTy :: Type
+ Clash.Core.Util: listToLets :: [LetBinding] -> Term -> Term
+ Clash.Core.Util: primUCo :: Term
+ Clash.Core.Util: undefinedPrims :: [Text]
+ Clash.Core.Util: undefinedTy :: Type
+ Clash.Core.Util: unsafeCoerceTy :: Type
+ Clash.Core.VarEnv: differenceVarSet :: VarSet -> VarSet -> VarSet
+ Clash.Core.VarEnv: disjointVarSet :: VarSet -> VarSet -> Bool
+ Clash.Core.VarEnv: nullVarSet :: VarSet -> Bool
+ Clash.Core.VarEnv: subsetVarSet :: VarSet -> VarSet -> Bool
+ Clash.Driver: pprVerilatorShim :: Identifier -> Doc
+ Clash.Driver: prefixModuleName :: HDL -> Maybe Text -> Maybe TopEntity -> String -> (String, Maybe String)
+ Clash.Driver: removeHistoryFile :: Maybe FilePath -> IO ()
+ Clash.Driver: writeVerilatorShim :: FilePath -> Identifier -> [(FilePath, ByteString)] -> IO [(FilePath, ByteString)]
+ Clash.Driver.Manifest: FilesManifest :: [(FilePath, ByteString)] -> FilesManifest
+ Clash.Driver.Manifest: In :: PortDirection
+ Clash.Driver.Manifest: InOut :: PortDirection
+ Clash.Driver.Manifest: Out :: PortDirection
+ Clash.Driver.Manifest: [mpDirection] :: ManifestPort -> PortDirection
+ Clash.Driver.Manifest: [ports] :: Manifest -> [ManifestPort]
+ Clash.Driver.Manifest: data PortDirection
+ Clash.Driver.Manifest: instance Data.Aeson.Types.FromJSON.FromJSON Clash.Driver.Manifest.FilesManifest
+ Clash.Driver.Manifest: instance Data.Aeson.Types.FromJSON.FromJSON Clash.Driver.Manifest.PortDirection
+ Clash.Driver.Manifest: instance Data.Aeson.Types.ToJSON.ToJSON Clash.Driver.Manifest.PortDirection
+ Clash.Driver.Manifest: instance GHC.Classes.Eq Clash.Driver.Manifest.PortDirection
+ Clash.Driver.Manifest: instance GHC.Generics.Generic Clash.Driver.Manifest.PortDirection
+ Clash.Driver.Manifest: instance GHC.Read.Read Clash.Driver.Manifest.PortDirection
+ Clash.Driver.Manifest: instance GHC.Show.Show Clash.Driver.Manifest.PortDirection
+ Clash.Driver.Manifest: newtype FilesManifest
+ Clash.Driver.Manifest: parseFiles :: Object -> Parser [(FilePath, ByteString)]
+ Clash.Driver.Manifest: toHexDigest :: ByteString -> Text
+ Clash.Driver.Manifest: unsafeFromHexDigest :: Text -> ByteString
+ Clash.Driver.Types: AppliedName :: TransformationInfo
+ Clash.Driver.Types: AppliedTerm :: TransformationInfo
+ Clash.Driver.Types: ClashDesign :: [TopEntityT] -> DomainMap -> BindingMap -> ClashDesign
+ Clash.Driver.Types: ClashEnv :: ClashOpts -> TyConMap -> IntMap TyConName -> CompiledPrimMap -> CustomReprs -> ClashEnv
+ Clash.Driver.Types: DebugOpts :: Bool -> TransformationInfo -> Set String -> Bool -> Maybe Word -> Maybe Word -> Maybe FilePath -> DebugOpts
+ Clash.Driver.Types: FinalTerm :: TransformationInfo
+ Clash.Driver.Types: None :: TransformationInfo
+ Clash.Driver.Types: TryName :: TransformationInfo
+ Clash.Driver.Types: TryTerm :: TransformationInfo
+ Clash.Driver.Types: [bindingRecursive] :: Binding a -> Bool
+ Clash.Driver.Types: [dbg_countTransformations] :: DebugOpts -> Bool
+ Clash.Driver.Types: [dbg_historyFile] :: DebugOpts -> Maybe FilePath
+ Clash.Driver.Types: [dbg_invariants] :: DebugOpts -> Bool
+ Clash.Driver.Types: [dbg_transformationInfo] :: DebugOpts -> TransformationInfo
+ Clash.Driver.Types: [dbg_transformationsFrom] :: DebugOpts -> Maybe Word
+ Clash.Driver.Types: [dbg_transformationsLimit] :: DebugOpts -> Maybe Word
+ Clash.Driver.Types: [dbg_transformations] :: DebugOpts -> Set String
+ Clash.Driver.Types: [designBindings] :: ClashDesign -> BindingMap
+ Clash.Driver.Types: [designDomains] :: ClashDesign -> DomainMap
+ Clash.Driver.Types: [designEntities] :: ClashDesign -> [TopEntityT]
+ Clash.Driver.Types: [envCustomReprs] :: ClashEnv -> CustomReprs
+ Clash.Driver.Types: [envOpts] :: ClashEnv -> ClashOpts
+ Clash.Driver.Types: [envPrimitives] :: ClashEnv -> CompiledPrimMap
+ Clash.Driver.Types: [envTupleTyCons] :: ClashEnv -> IntMap TyConName
+ Clash.Driver.Types: [envTyConMap] :: ClashEnv -> TyConMap
+ Clash.Driver.Types: [opt_debug] :: ClashOpts -> DebugOpts
+ Clash.Driver.Types: [opt_renderEnums] :: ClashOpts -> Bool
+ Clash.Driver.Types: [opt_werror] :: ClashOpts -> Bool
+ Clash.Driver.Types: data ClashDesign
+ Clash.Driver.Types: data ClashEnv
+ Clash.Driver.Types: data DebugOpts
+ Clash.Driver.Types: data TransformationInfo
+ Clash.Driver.Types: debugAll :: DebugOpts
+ Clash.Driver.Types: debugApplied :: DebugOpts
+ Clash.Driver.Types: debugCount :: DebugOpts
+ Clash.Driver.Types: debugFinal :: DebugOpts
+ Clash.Driver.Types: debugName :: DebugOpts
+ Clash.Driver.Types: debugNone :: DebugOpts
+ Clash.Driver.Types: debugSilent :: DebugOpts
+ Clash.Driver.Types: debugTry :: DebugOpts
+ Clash.Driver.Types: hasDebugInfo :: TransformationInfo -> String -> DebugOpts -> Bool
+ Clash.Driver.Types: hasTransformationInfo :: TransformationInfo -> DebugOpts -> Bool
+ Clash.Driver.Types: instance Control.DeepSeq.NFData Clash.Driver.Types.ClashDesign
+ Clash.Driver.Types: instance Control.DeepSeq.NFData Clash.Driver.Types.ClashEnv
+ Clash.Driver.Types: instance Control.DeepSeq.NFData Clash.Driver.Types.ClashOpts
+ Clash.Driver.Types: instance Control.DeepSeq.NFData Clash.Driver.Types.DebugOpts
+ Clash.Driver.Types: instance Control.DeepSeq.NFData Clash.Driver.Types.TransformationInfo
+ Clash.Driver.Types: instance Data.Hashable.Class.Hashable Clash.Driver.Types.DebugOpts
+ Clash.Driver.Types: instance Data.Hashable.Class.Hashable Clash.Driver.Types.TransformationInfo
+ Clash.Driver.Types: instance GHC.Classes.Eq Clash.Driver.Types.DebugOpts
+ Clash.Driver.Types: instance GHC.Classes.Eq Clash.Driver.Types.TransformationInfo
+ Clash.Driver.Types: instance GHC.Classes.Ord Clash.Driver.Types.TransformationInfo
+ Clash.Driver.Types: instance GHC.Generics.Generic Clash.Driver.Types.ClashEnv
+ Clash.Driver.Types: instance GHC.Generics.Generic Clash.Driver.Types.DebugOpts
+ Clash.Driver.Types: instance GHC.Generics.Generic Clash.Driver.Types.TransformationInfo
+ Clash.Driver.Types: instance GHC.Read.Read Clash.Driver.Types.TransformationInfo
+ Clash.Driver.Types: instance GHC.Show.Show Clash.Driver.Types.ClashOpts
+ Clash.Driver.Types: instance GHC.Show.Show Clash.Driver.Types.DebugOpts
+ Clash.Driver.Types: instance GHC.Show.Show Clash.Driver.Types.TransformationInfo
+ Clash.Driver.Types: isDebugging :: DebugOpts -> Bool
+ Clash.Driver.Types: type DomainMap = HashMap Text VDomainConfiguration
+ Clash.Netlist.BlackBox.Types: LongestPeriod :: Element
+ Clash.Netlist.Types: Comment :: Comment -> CommentOrDirective
+ Clash.Netlist.Types: ConditionalDecl :: !Text -> [Declaration] -> Declaration
+ Clash.Netlist.Types: Directive :: Directive -> CommentOrDirective
+ Clash.Netlist.Types: MemBlob :: !Size -> !Size -> HWType
+ Clash.Netlist.Types: data CommentOrDirective
+ Clash.Netlist.Types: instance Clash.Netlist.Types.IdentifierSetMonad m => Clash.Netlist.Types.IdentifierSetMonad (Data.Monoid.Ap m)
+ Clash.Netlist.Types: instance GHC.Generics.Generic Clash.Netlist.Types.Component
+ Clash.Netlist.Types: instance GHC.Show.Show Clash.Netlist.Types.CommentOrDirective
+ Clash.Netlist.Types: isBiDirectional :: (Identifier, HWType) -> Bool
+ Clash.Netlist.Types: type Directive = Text
+ Clash.Netlist.Util: squashLets :: Term -> Term
+ Clash.Normalize.Primitives: removedArg :: PrimInfo
+ Clash.Normalize.Primitives: undefined :: PrimInfo
+ Clash.Normalize.Transformations.ANF: makeANF :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.ANF: nonRepANF :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Case: caseCase :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Case: caseCon :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Case: caseElemNonReachable :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Case: caseFlat :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Case: caseLet :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Case: caseOneAlt :: Term -> NormalizeSession Term
+ Clash.Normalize.Transformations.Case: elimExistentials :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Cast: argCastSpec :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Cast: caseCast :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Cast: elimCastCast :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Cast: letCast :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Cast: splitCastWork :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.DEC: disjointExpressionConsolidation :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.DEC: instance Data.Foldable.Foldable Clash.Normalize.Transformations.DEC.CaseTree
+ Clash.Normalize.Transformations.DEC: instance GHC.Base.Functor Clash.Normalize.Transformations.DEC.CaseTree
+ Clash.Normalize.Transformations.DEC: instance GHC.Classes.Eq a => GHC.Classes.Eq (Clash.Normalize.Transformations.DEC.CaseTree a)
+ Clash.Normalize.Transformations.DEC: instance GHC.Show.Show a => GHC.Show.Show (Clash.Normalize.Transformations.DEC.CaseTree a)
+ Clash.Normalize.Transformations.EtaExpand: etaExpandSyn :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.EtaExpand: etaExpansionTL :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Inline: bindConstantVar :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Inline: collapseRHSNoops :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Inline: inlineBndrsCleanup :: HasCallStack => InScopeSet -> VarEnv ((Id, Term), VarEnv Int) -> VarEnv ((Id, Term), VarEnv Int, Mark) -> [((Id, Term), VarEnv Int)] -> [(Id, Term)]
+ Clash.Normalize.Transformations.Inline: inlineCast :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Inline: inlineCleanup :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Inline: inlineNonRep :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Inline: inlineOrLiftNonRep :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Inline: inlineSimIO :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Inline: inlineSmall :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Inline: inlineWorkFree :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Letrec: deadCode :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Letrec: flattenLet :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Letrec: recToLetRec :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Letrec: removeUnusedExpr :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Letrec: simpleCSE :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Letrec: topLet :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.MultiPrim: setupMultiResultPrim :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Reduce: reduceBinders :: Subst -> [LetBinding] -> [LetBinding] -> NormalizeSession (Subst, [LetBinding])
+ Clash.Normalize.Transformations.Reduce: reduceConst :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Reduce: reduceNonRepPrim :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.SeparateArgs: separateArguments :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Specialize: appProp :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Specialize: constantSpec :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Specialize: nonRepSpec :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Specialize: specialize :: NormRewrite
+ Clash.Normalize.Transformations.Specialize: typeSpec :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Specialize: zeroWidthSpec :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.XOptimize: xOptimize :: HasCallStack => NormRewrite
+ Clash.Primitives.Sized.Signed: fromIntegerTF :: TemplateFunction
+ Clash.Primitives.Util: decodeOrErrJson :: (HasCallStack, FromJSON a) => FilePath -> ByteString -> a
+ Clash.Primitives.Util: decodeOrErrYaml :: (HasCallStack, FromJSON a) => FilePath -> ByteString -> a
+ Clash.Rewrite.Types: [_clashEnv] :: RewriteEnv -> ClashEnv
+ Clash.Rewrite.Types: [_peEvaluator] :: RewriteEnv -> Evaluator
+ Clash.Rewrite.Types: [_transformCounters] :: RewriteState extra -> HashMap Text Word
+ Clash.Rewrite.Types: clashEnv :: Lens' RewriteEnv ClashEnv
+ Clash.Rewrite.Types: debugOpts :: Getter RewriteEnv DebugOpts
+ Clash.Rewrite.Types: inlineConstantLimit :: Getter RewriteEnv Word
+ Clash.Rewrite.Types: inlineFunctionLimit :: Getter RewriteEnv Word
+ Clash.Rewrite.Types: inlineLimit :: Getter RewriteEnv Int
+ Clash.Rewrite.Types: inlineWFCacheLimit :: Getter RewriteEnv Word
+ Clash.Rewrite.Types: newInlineStrategy :: Getter RewriteEnv Bool
+ Clash.Rewrite.Types: normalizeUltra :: Getter RewriteEnv Bool
+ Clash.Rewrite.Types: peEvaluator :: Lens' RewriteEnv Evaluator
+ Clash.Rewrite.Types: primitives :: Getter RewriteEnv CompiledPrimMap
+ Clash.Rewrite.Types: specializationLimit :: Getter RewriteEnv Int
+ Clash.Rewrite.Types: transformCounters :: forall extra_a3UVI. Lens' (RewriteState extra_a3UVI) (HashMap Text Word)
+ Clash.Unique: differenceUniqSet :: UniqSet a -> UniqSet a -> UniqSet a
+ Clash.Unique: disjointUniqSet :: UniqSet a -> UniqSet a -> Bool
+ Clash.Unique: nullUniqSet :: UniqSet a -> Bool
+ Clash.Util.Eq: fastEq :: Eq a => a -> a -> Bool
+ Clash.Util.Eq: fastEqBy :: (a -> a -> Bool) -> a -> a -> Bool
+ Clash.Verification.Pretty: pprProperty :: Property dom -> Declaration
+ Clash.Verification.Pretty: pprPslProperty :: HDL -> Text -> Text -> ActiveEdge -> Property' Text -> Declaration
+ Clash.Verification.Pretty: pprSvaProperty :: Text -> Text -> ActiveEdge -> Property' Text -> Declaration
+ Clash.Verification.Pretty: pprYosysSvaProperty :: Text -> Expr -> ActiveEdge -> Property' Text -> Declaration
- Clash.Backend: blockDecl :: Backend state => Identifier -> [Declaration] -> Mon (State state) Doc
+ Clash.Backend: blockDecl :: Backend state => Identifier -> [Declaration] -> Ap (State state) Doc
- Clash.Backend: expr :: Backend state => Bool -> Expr -> Mon (State state) Doc
+ Clash.Backend: expr :: Backend state => Bool -> Expr -> Ap (State state) Doc
- Clash.Backend: fromBV :: Backend state => HWType -> Text -> Mon (State state) Doc
+ Clash.Backend: fromBV :: Backend state => HWType -> Text -> Ap (State state) Doc
- Clash.Backend: genHDL :: Backend state => ModName -> SrcSpan -> IdentifierSet -> Component -> Mon (State state) ((String, Doc), [(String, Doc)])
+ Clash.Backend: genHDL :: Backend state => ModName -> SrcSpan -> IdentifierSet -> Component -> Ap (State state) ((String, Doc), [(String, Doc)])
- Clash.Backend: hdlRecSel :: Backend state => HWType -> Int -> Mon (State state) Doc
+ Clash.Backend: hdlRecSel :: Backend state => HWType -> Int -> Ap (State state) Doc
- Clash.Backend: hdlSig :: Backend state => Text -> HWType -> Mon (State state) Doc
+ Clash.Backend: hdlSig :: Backend state => Text -> HWType -> Ap (State state) Doc
- Clash.Backend: hdlType :: Backend state => Usage -> HWType -> Mon (State state) Doc
+ Clash.Backend: hdlType :: Backend state => Usage -> HWType -> Ap (State state) Doc
- Clash.Backend: hdlTypeErrValue :: Backend state => HWType -> Mon (State state) Doc
+ Clash.Backend: hdlTypeErrValue :: Backend state => HWType -> Ap (State state) Doc
- Clash.Backend: hdlTypeMark :: Backend state => HWType -> Mon (State state) Doc
+ Clash.Backend: hdlTypeMark :: Backend state => HWType -> Ap (State state) Doc
- Clash.Backend: initBackend :: Backend state => Int -> HdlSyn -> Bool -> PreserveCase -> Maybe (Maybe Int) -> AggressiveXOptBB -> state
+ Clash.Backend: initBackend :: Backend state => ClashOpts -> state
- Clash.Backend: inst :: Backend state => Declaration -> Mon (State state) (Maybe Doc)
+ Clash.Backend: inst :: Backend state => Declaration -> Ap (State state) (Maybe Doc)
- Clash.Backend: mkTyPackage :: Backend state => ModName -> [HWType] -> Mon (State state) [(String, Doc)]
+ Clash.Backend: mkTyPackage :: Backend state => ModName -> [HWType] -> Ap (State state) [(String, Doc)]
- Clash.Backend: toBV :: Backend state => HWType -> Text -> Mon (State state) Doc
+ Clash.Backend: toBV :: Backend state => HWType -> Text -> Ap (State state) Doc
- Clash.Backend.Verilog: bit_char :: Lens' s (Maybe (Maybe Int)) -> Bit -> Mon (State s) Doc
+ Clash.Backend.Verilog: bit_char :: Lens' s (Maybe (Maybe Int)) -> Bit -> Ap (State s) Doc
- Clash.Backend.Verilog: bits :: Lens' s (Maybe (Maybe Int)) -> [Bit] -> Mon (State s) Doc
+ Clash.Backend.Verilog: bits :: Lens' s (Maybe (Maybe Int)) -> [Bit] -> Ap (State s) Doc
- Clash.Backend.Verilog: exprLit :: Lens' s (Maybe (Maybe Int)) -> Maybe (HWType, Size) -> Literal -> Mon (State s) Doc
+ Clash.Backend.Verilog: exprLit :: Lens' s (Maybe (Maybe Int)) -> Maybe (HWType, Size) -> Literal -> Ap (State s) Doc
- Clash.Backend.Verilog: include :: Monad m => [Text] -> Mon m Doc
+ Clash.Backend.Verilog: include :: Monad m => [Text] -> Ap m Doc
- Clash.Backend.Verilog: uselibs :: Monad m => [Text] -> Mon m Doc
+ Clash.Backend.Verilog: uselibs :: Monad m => [Text] -> Ap m Doc
- Clash.Core.DataCon: MkData :: !DcName -> {-# UNPACK #-} !Unique -> !ConTag -> !Type -> [TyVar] -> [TyVar] -> [Type] -> [Text] -> DataCon
+ Clash.Core.DataCon: MkData :: !DcName -> {-# UNPACK #-} !Unique -> !ConTag -> !Type -> [TyVar] -> [TyVar] -> [Type] -> [DcStrictness] -> [Text] -> DataCon
- Clash.Core.Literal: DoubleLiteral :: !Rational -> Literal
+ Clash.Core.Literal: DoubleLiteral :: !Word64 -> Literal
- Clash.Core.Literal: FloatLiteral :: !Rational -> Literal
+ Clash.Core.Literal: FloatLiteral :: !Word32 -> Literal
- Clash.Core.Subst: deshadowLetExpr :: HasCallStack => InScopeSet -> [LetBinding] -> Term -> ([LetBinding], Term)
+ Clash.Core.Subst: deshadowLetExpr :: HasCallStack => InScopeSet -> Bind Term -> Term -> (Bind Term, Term)
- Clash.Core.Term: PrimInfo :: !Text -> !Type -> !WorkInfo -> !IsMultiPrim -> PrimInfo
+ Clash.Core.Term: PrimInfo :: !Text -> !Type -> !WorkInfo -> !IsMultiPrim -> !PrimUnfolding -> PrimInfo
- Clash.Core.Util: extractElems :: Supply -> InScopeSet -> DataCon -> Type -> Char -> Integer -> Term -> (Supply, [(Term, [LetBinding])])
+ Clash.Core.Util: extractElems :: Supply -> InScopeSet -> DataCon -> Type -> Char -> Integer -> Term -> (Supply, [(Term, [(Id, Term)])])
- Clash.Core.Util: extractTElems :: Supply -> InScopeSet -> DataCon -> DataCon -> Type -> Char -> Integer -> Term -> (Supply, ([Term], [LetBinding]))
+ Clash.Core.Util: extractTElems :: Supply -> InScopeSet -> DataCon -> DataCon -> Type -> Char -> Integer -> Term -> (Supply, ([Term], [(Id, Term)]))
- Clash.Core.Util: sccLetBindings :: HasCallStack => [LetBinding] -> [SCC LetBinding]
+ Clash.Core.Util: sccLetBindings :: HasCallStack => [(Id, Term)] -> [SCC (Id, Term)]
- Clash.Driver: generateHDL :: forall backend. Backend backend => CustomReprs -> HashMap Text VDomainConfiguration -> BindingMap -> Maybe backend -> CompiledPrimMap -> TyConMap -> IntMap TyConName -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> Evaluator -> [TopEntityT] -> Maybe (TopEntityT, [TopEntityT]) -> ClashOpts -> (UTCTime, UTCTime) -> IO ()
+ Clash.Driver: generateHDL :: forall backend. Backend backend => ClashEnv -> ClashDesign -> Maybe backend -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> Evaluator -> Evaluator -> Maybe (TopEntityT, [TopEntityT]) -> UTCTime -> IO ()
- Clash.Driver: normalizeEntity :: CustomReprs -> BindingMap -> CompiledPrimMap -> TyConMap -> IntMap TyConName -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> Evaluator -> [Id] -> ClashOpts -> Supply -> Id -> BindingMap
+ Clash.Driver: normalizeEntity :: ClashEnv -> BindingMap -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> Evaluator -> Evaluator -> [Id] -> Supply -> Id -> IO BindingMap
- Clash.Driver.Manifest: Manifest :: Int -> (Int, Int, Bool) -> [ManifestPort] -> [ManifestPort] -> [Text] -> Text -> [(FilePath, ByteString)] -> HashMap Text VDomainConfiguration -> [Text] -> Manifest
+ Clash.Driver.Manifest: Manifest :: ByteString -> (Int, Int) -> [ManifestPort] -> [Text] -> Text -> [(FilePath, ByteString)] -> HashMap Text VDomainConfiguration -> [Text] -> Manifest
- Clash.Driver.Manifest: ManifestPort :: Text -> Text -> Int -> Bool -> Maybe Text -> ManifestPort
+ Clash.Driver.Manifest: ManifestPort :: Text -> Text -> PortDirection -> Int -> Bool -> Maybe Text -> ManifestPort
- Clash.Driver.Manifest: [manifestHash] :: Manifest -> Int
+ Clash.Driver.Manifest: [manifestHash] :: Manifest -> ByteString
- Clash.Driver.Manifest: [successFlags] :: Manifest -> (Int, Int, Bool)
+ Clash.Driver.Manifest: [successFlags] :: Manifest -> (Int, Int)
- Clash.Driver.Manifest: isUserModified :: FilePath -> Manifest -> IO [UnexpectedModification]
+ Clash.Driver.Manifest: isUserModified :: FilePath -> FilesManifest -> IO [UnexpectedModification]
- Clash.Driver.Manifest: mkManifest :: Backend backend => backend -> HashMap Text VDomainConfiguration -> ClashOpts -> Component -> [Component] -> [Id] -> [(FilePath, ByteString)] -> Int -> Manifest
+ Clash.Driver.Manifest: mkManifest :: Backend backend => backend -> HashMap Text VDomainConfiguration -> ClashOpts -> Component -> [Component] -> [Id] -> [(FilePath, ByteString)] -> ByteString -> Manifest
- Clash.Driver.Manifest: mkManifestPort :: Backend backend => backend -> Identifier -> HWType -> ManifestPort
+ Clash.Driver.Manifest: mkManifestPort :: Backend backend => backend -> Identifier -> HWType -> PortDirection -> ManifestPort
- Clash.Driver.Manifest: readFreshManifest :: [TopEntityT] -> (BindingMap, Id) -> CompiledPrimMap -> ClashOpts -> UTCTime -> FilePath -> IO (Maybe [UnexpectedModification], Maybe Manifest, Int)
+ Clash.Driver.Manifest: readFreshManifest :: [TopEntityT] -> (BindingMap, Id) -> CompiledPrimMap -> ClashOpts -> UTCTime -> FilePath -> IO (Maybe [UnexpectedModification], Maybe Manifest, ByteString)
- Clash.Driver.Manifest: readManifest :: FilePath -> IO (Maybe Manifest)
+ Clash.Driver.Manifest: readManifest :: FromJSON a => FilePath -> IO (Maybe a)
- Clash.Driver.Types: Binding :: Id -> SrcSpan -> InlineSpec -> IsPrim -> a -> Binding a
+ Clash.Driver.Types: Binding :: Id -> SrcSpan -> InlineSpec -> IsPrim -> a -> Bool -> Binding a
- Clash.Driver.Types: ClashOpts :: Int -> Int -> Word -> Word -> Word -> DebugLevel -> Set String -> Int -> Int -> Maybe FilePath -> Bool -> Bool -> Bool -> OverridingBool -> Int -> Maybe String -> HdlSyn -> Bool -> Bool -> [FilePath] -> Maybe Text -> Bool -> Bool -> PreserveCase -> Bool -> Maybe (Maybe Int) -> Bool -> Bool -> Bool -> Word -> Bool -> ClashOpts
+ Clash.Driver.Types: ClashOpts :: Bool -> Int -> Int -> Word -> Word -> Word -> DebugOpts -> Bool -> Bool -> Bool -> OverridingBool -> Int -> Maybe String -> HdlSyn -> Bool -> [FilePath] -> Maybe Text -> Bool -> Bool -> PreserveCase -> Bool -> Maybe (Maybe Int) -> Bool -> Bool -> Bool -> Word -> Bool -> Bool -> ClashOpts
- Clash.Netlist: genNetlist :: Bool -> ClashOpts -> CustomReprs -> BindingMap -> VarEnv TopEntityT -> VarEnv Identifier -> CompiledPrimMap -> TyConMap -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> Int -> Bool -> SomeBackend -> IdentifierSet -> FilePath -> Maybe Text -> Id -> IO (Component, ComponentMap, IdentifierSet)
+ Clash.Netlist: genNetlist :: ClashEnv -> Bool -> BindingMap -> VarEnv TopEntityT -> VarEnv Identifier -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> Bool -> SomeBackend -> IdentifierSet -> FilePath -> Maybe Text -> Id -> IO (Component, ComponentMap, IdentifierSet)
- Clash.Netlist: genTopNames :: Maybe Text -> Bool -> PreserveCase -> HDL -> [TopEntityT] -> (VarEnv Identifier, IdentifierSet)
+ Clash.Netlist: genTopNames :: ClashOpts -> HDL -> [TopEntityT] -> (VarEnv Identifier, IdentifierSet)
- Clash.Netlist.BlackBox.Util: prettyBlackBox :: Monad m => BlackBoxTemplate -> Mon m Text
+ Clash.Netlist.BlackBox.Util: prettyBlackBox :: Monad m => BlackBoxTemplate -> Ap m Text
- Clash.Netlist.BlackBox.Util: prettyElem :: (HasCallStack, Monad m) => Element -> Mon m Text
+ Clash.Netlist.BlackBox.Util: prettyElem :: (HasCallStack, Monad m) => Element -> Ap m Text
- Clash.Netlist.Types: TickDecl :: Comment -> Declaration
+ Clash.Netlist.Types: TickDecl :: CommentOrDirective -> Declaration
- Clash.Normalize: runNormalization :: ClashOpts -> Supply -> BindingMap -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> CustomReprs -> TyConMap -> IntMap TyConName -> Evaluator -> CompiledPrimMap -> VarEnv Bool -> [Id] -> NormalizeSession a -> a
+ Clash.Normalize: runNormalization :: ClashEnv -> Supply -> BindingMap -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> Evaluator -> Evaluator -> VarEnv Bool -> [Id] -> NormalizeSession a -> IO a
- Clash.Normalize.Types: NormalizeState :: BindingMap -> Map (Id, Int, Either Term Type) Id -> VarEnv Int -> !Int -> VarEnv (VarEnv Int) -> !Int -> !Word -> !Word -> CompiledPrimMap -> Map Text (Set Int) -> VarEnv Bool -> Bool -> Bool -> !Word -> NormalizeState
+ Clash.Normalize.Types: NormalizeState :: BindingMap -> Map (Id, Int, Either Term Type) Id -> VarEnv Int -> VarEnv (VarEnv Int) -> Map Text (Set Int) -> VarEnv Bool -> NormalizeState
- Clash.Rewrite.Types: R :: (RewriteEnv -> RewriteState extra -> Any -> (a, RewriteState extra, Any)) -> RewriteMonad extra a
+ Clash.Rewrite.Types: R :: RWST RewriteEnv Any (RewriteState extra) IO a -> RewriteMonad extra a
- Clash.Rewrite.Types: RewriteEnv :: DebugLevel -> Set String -> Int -> Int -> Maybe FilePath -> Bool -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> TyConMap -> IntMap TyConName -> Evaluator -> VarSet -> CustomReprs -> Word -> RewriteEnv
+ Clash.Rewrite.Types: RewriteEnv :: ClashEnv -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> Evaluator -> Evaluator -> VarSet -> RewriteEnv
- Clash.Rewrite.Types: RewriteState :: {-# UNPACK #-} !Int -> !BindingMap -> !Supply -> (Id, SrcSpan) -> {-# UNPACK #-} !Int -> PrimHeap -> VarEnv Bool -> !extra -> RewriteState extra
+ Clash.Rewrite.Types: RewriteState :: {-# UNPACK #-} !Word -> HashMap Text Word -> !BindingMap -> !Supply -> (Id, SrcSpan) -> {-# UNPACK #-} !Int -> PrimHeap -> VarEnv Bool -> !extra -> RewriteState extra
- Clash.Rewrite.Types: [_transformCounter] :: RewriteState extra -> {-# UNPACK #-} !Int
+ Clash.Rewrite.Types: [_transformCounter] :: RewriteState extra -> {-# UNPACK #-} !Word
- Clash.Rewrite.Types: [unR] :: RewriteMonad extra a -> RewriteEnv -> RewriteState extra -> Any -> (a, RewriteState extra, Any)
+ Clash.Rewrite.Types: [unR] :: RewriteMonad extra a -> RWST RewriteEnv Any (RewriteState extra) IO a
- Clash.Rewrite.Types: aggressiveXOpt :: Lens' RewriteEnv Bool
+ Clash.Rewrite.Types: aggressiveXOpt :: Getter RewriteEnv Bool
- Clash.Rewrite.Types: bindings :: forall extra_a3AFC. Lens' (RewriteState extra_a3AFC) BindingMap
+ Clash.Rewrite.Types: bindings :: forall extra_a3UVI. Lens' (RewriteState extra_a3UVI) BindingMap
- Clash.Rewrite.Types: curFun :: forall extra_a3AFC. Lens' (RewriteState extra_a3AFC) (Id, SrcSpan)
+ Clash.Rewrite.Types: curFun :: forall extra_a3UVI. Lens' (RewriteState extra_a3UVI) (Id, SrcSpan)
- Clash.Rewrite.Types: customReprs :: Lens' RewriteEnv CustomReprs
+ Clash.Rewrite.Types: customReprs :: Getter RewriteEnv CustomReprs
- Clash.Rewrite.Types: extra :: forall extra_a3AFC extra_a3ANj. Lens (RewriteState extra_a3AFC) (RewriteState extra_a3ANj) extra_a3AFC extra_a3ANj
+ Clash.Rewrite.Types: extra :: forall extra_a3UVI extra_a3V3u. Lens (RewriteState extra_a3UVI) (RewriteState extra_a3V3u) extra_a3UVI extra_a3V3u
- Clash.Rewrite.Types: fuelLimit :: Lens' RewriteEnv Word
+ Clash.Rewrite.Types: fuelLimit :: Getter RewriteEnv Word
- Clash.Rewrite.Types: globalHeap :: forall extra_a3AFC. Lens' (RewriteState extra_a3AFC) PrimHeap
+ Clash.Rewrite.Types: globalHeap :: forall extra_a3UVI. Lens' (RewriteState extra_a3UVI) PrimHeap
- Clash.Rewrite.Types: nameCounter :: forall extra_a3AFC. Lens' (RewriteState extra_a3AFC) Int
+ Clash.Rewrite.Types: nameCounter :: forall extra_a3UVI. Lens' (RewriteState extra_a3UVI) Int
- Clash.Rewrite.Types: runR :: RewriteMonad extra a -> RewriteEnv -> RewriteState extra -> (a, RewriteState extra, Any)
+ Clash.Rewrite.Types: runR :: RewriteMonad extra a -> RewriteEnv -> RewriteState extra -> IO (a, RewriteState extra, Any)
- Clash.Rewrite.Types: tcCache :: Lens' RewriteEnv TyConMap
+ Clash.Rewrite.Types: tcCache :: Getter RewriteEnv TyConMap
- Clash.Rewrite.Types: transformCounter :: forall extra_a3AFC. Lens' (RewriteState extra_a3AFC) Int
+ Clash.Rewrite.Types: transformCounter :: forall extra_a3UVI. Lens' (RewriteState extra_a3UVI) Word
- Clash.Rewrite.Types: tupleTcCache :: Lens' RewriteEnv (IntMap TyConName)
+ Clash.Rewrite.Types: tupleTcCache :: Getter RewriteEnv (IntMap TyConName)
- Clash.Rewrite.Types: uniqSupply :: forall extra_a3AFC. Lens' (RewriteState extra_a3AFC) Supply
+ Clash.Rewrite.Types: uniqSupply :: forall extra_a3UVI. Lens' (RewriteState extra_a3UVI) Supply
- Clash.Rewrite.Types: workFreeBinders :: forall extra_a3AFC. Lens' (RewriteState extra_a3AFC) (VarEnv Bool)
+ Clash.Rewrite.Types: workFreeBinders :: forall extra_a3UVI. Lens' (RewriteState extra_a3UVI) (VarEnv Bool)
- Clash.Rewrite.Util: applyDebug :: DebugLevel -> Set String -> Maybe (Int, Int) -> String -> Term -> Bool -> Term -> RewriteMonad extra Term
+ Clash.Rewrite.Util: applyDebug :: String -> Term -> Bool -> Term -> RewriteMonad extra Term
- Clash.Rewrite.Util: mkBinderFor :: (MonadUnique m, MonadFail m) => InScopeSet -> TyConMap -> Name a -> Either Term Type -> m (Either Id TyVar)
+ Clash.Rewrite.Util: mkBinderFor :: MonadUnique m => InScopeSet -> TyConMap -> Name a -> Either Term Type -> m (Either Id TyVar)
- Clash.Rewrite.Util: mkTmBinderFor :: (MonadUnique m, MonadFail m) => InScopeSet -> TyConMap -> Name a -> Term -> m Id
+ Clash.Rewrite.Util: mkTmBinderFor :: MonadUnique m => InScopeSet -> TyConMap -> Name a -> Term -> m Id
- Clash.Rewrite.Util: removeUnusedBinders :: [LetBinding] -> Term -> Maybe Term
+ Clash.Rewrite.Util: removeUnusedBinders :: Bind Term -> Term -> Maybe Term
- Clash.Rewrite.Util: runRewriteSession :: RewriteEnv -> RewriteState extra -> RewriteMonad extra a -> a
+ Clash.Rewrite.Util: runRewriteSession :: RewriteEnv -> RewriteState extra -> RewriteMonad extra a -> IO a
Files
- CHANGELOG.md +73/−0
- clash-lib.cabal +54/−35
- prims/common/Clash_Annotations_BitRepresentation_Deriving.primitives +0/−9
- prims/common/Clash_Annotations_BitRepresentation_Deriving.primitives.yaml +7/−0
- prims/common/Clash_Class_BitPack.primitives +0/−37
- prims/common/Clash_Class_BitPack.primitives.yaml +28/−0
- prims/common/Clash_Explicit_Signal.primitives +0/−14
- prims/common/Clash_Explicit_Signal.primitives.yaml +11/−0
- prims/common/Clash_Explicit_Testbench.primitives.yaml +15/−0
- prims/common/Clash_GHC_GHC2Core.primitives +0/−20
- prims/common/Clash_GHC_GHC2Core.primitives.yaml +13/−0
- prims/common/Clash_Intel_ClockGen.primitives +0/−29
- prims/common/Clash_Intel_ClockGen.primitives.yaml +22/−0
- prims/common/Clash_Magic.primitives +0/−31
- prims/common/Clash_Magic.primitives.yaml +18/−0
- prims/common/Clash_Normalize_Primitives.primitives.yaml +18/−0
- prims/common/Clash_Promoted_Nat.primitives +0/−9
- prims/common/Clash_Promoted_Nat.primitives.yaml +7/−0
- prims/common/Clash_Promoted_Nat_Unsafe.primitives +0/−9
- prims/common/Clash_Promoted_Nat_Unsafe.primitives.yaml +7/−0
- prims/common/Clash_Promoted_Symbol.primitives +0/−17
- prims/common/Clash_Promoted_Symbol.primitives.yaml +14/−0
- prims/common/Clash_Signal_BiSignal.primitives +0/−30
- prims/common/Clash_Signal_BiSignal.primitives.yaml +25/−0
- prims/common/Clash_Signal_Bundle.primitives +0/−7
- prims/common/Clash_Signal_Bundle.primitives.yaml +4/−0
- prims/common/Clash_Signal_Internal.primitives +0/−37
- prims/common/Clash_Signal_Internal.primitives.yaml +24/−0
- prims/common/Clash_Signal_Trace.primitives +0/−67
- prims/common/Clash_Signal_Trace.primitives.yaml +58/−0
- prims/common/Clash_Sized_Internal_BitVector.primitives +0/−43
- prims/common/Clash_Sized_Internal_BitVector.primitives.yaml +35/−0
- prims/common/Clash_Sized_Internal_Index.primitives +0/−8
- prims/common/Clash_Sized_Internal_Signed.primitives +0/−22
- prims/common/Clash_Sized_Internal_Signed.primitives.yaml +12/−0
- prims/common/Clash_Sized_Internal_Unsigned.primitives +0/−46
- prims/common/Clash_Sized_Internal_Unsigned.primitives.yaml +28/−0
- prims/common/Clash_Sized_RTree.primitives +0/−7
- prims/common/Clash_Sized_RTree.primitives.yaml +4/−0
- prims/common/Clash_Sized_Vector.primitives +0/−47
- prims/common/Clash_Sized_Vector.primitives.yaml +33/−0
- prims/common/Clash_Transformations.primitives +0/−24
- prims/common/Clash_XException.primitives +0/−38
- prims/common/Clash_XException.primitives.yaml +38/−0
- prims/common/Control_Exception_Base.primitives +0/−73
- prims/common/Control_Exception_Base.primitives.yaml +63/−0
- prims/common/Debug_Trace.primitives +0/−9
- prims/common/Debug_Trace.primitives.yaml +7/−0
- prims/common/GHC_Base.primitives +0/−14
- prims/common/GHC_Base.primitives.yaml +4/−0
- prims/common/GHC_CString.primitives +0/−21
- prims/common/GHC_CString.primitives.yaml +14/−0
- prims/common/GHC_Classes.primitives +0/−29
- prims/common/GHC_Classes.primitives.yaml +24/−0
- prims/common/GHC_Err.primitives +0/−25
- prims/common/GHC_Err.primitives.yaml +20/−0
- prims/common/GHC_IO_Exception.primitives +0/−14
- prims/common/GHC_IO_Exception.primitives.yaml +13/−0
- prims/common/GHC_Integer_Type.primitives +0/−50
- prims/common/GHC_Integer_Type.primitives.yaml +48/−0
- prims/common/GHC_Magic.primitives +0/−20
- prims/common/GHC_Magic.primitives.yaml +13/−0
- prims/common/GHC_Natural.primitives +0/−52
- prims/common/GHC_Natural.primitives.yaml +42/−0
- prims/common/GHC_Num_Integer.primitives +0/−78
- prims/common/GHC_Num_Integer.primitives.yaml +75/−0
- prims/common/GHC_Num_Natural.primitives +0/−84
- prims/common/GHC_Num_Natural.primitives.yaml +64/−0
- prims/common/GHC_Prim.primitives +0/−61
- prims/common/GHC_Prim.primitives.yaml +37/−0
- prims/common/GHC_Real.primitives +0/−25
- prims/common/GHC_Real.primitives.yaml +21/−0
- prims/common/GHC_TypeNats.primitives +0/−9
- prims/common/GHC_TypeNats.primitives.yaml +7/−0
- prims/common/GHC_Typelits.primitives +0/−9
- prims/common/GHC_Typelits.primitives.yaml +7/−0
- prims/common/GHC_Types.primitives +0/−31
- prims/common/GHC_Types.primitives.yaml +11/−0
- prims/common/Unsafe_Coerce.primitives +0/−9
- prims/common/Unsafe_Coerce.primitives.yaml +7/−0
- prims/commonverilog/Clash_Class_Exp.primitives +0/−29
- prims/commonverilog/Clash_Class_Exp.primitives.yaml +24/−0
- prims/commonverilog/Clash_Explicit_SimIO.primitives +0/−127
- prims/commonverilog/Clash_Explicit_SimIO.primitives.yaml +90/−0
- prims/commonverilog/Clash_Explicit_Testbench.primitives +0/−9
- prims/commonverilog/Clash_Explicit_Testbench.primitives.yaml +7/−0
- prims/commonverilog/Clash_Intel_DDR.primitives +0/−49
- prims/commonverilog/Clash_Intel_DDR.primitives.yaml +47/−0
- prims/commonverilog/Clash_Magic.primitives +0/−13
- prims/commonverilog/Clash_Magic.primitives.yaml +11/−0
- prims/commonverilog/Clash_Promoted_Nat.primitives +0/−78
- prims/commonverilog/Clash_Promoted_Nat.primitives.yaml +71/−0
- prims/commonverilog/Clash_Signal_Internal.primitives +0/−19
- prims/commonverilog/Clash_Signal_Internal.primitives.yaml +14/−0
- prims/commonverilog/Clash_Sized_Internal_BitVector.primitives +0/−375
- prims/commonverilog/Clash_Sized_Internal_BitVector.primitives.yaml +346/−0
- prims/commonverilog/Clash_Sized_Internal_Index.primitives +0/−138
- prims/commonverilog/Clash_Sized_Internal_Index.primitives.yaml +141/−0
- prims/commonverilog/Clash_Sized_Internal_Signed.primitives +0/−206
- prims/commonverilog/Clash_Sized_Internal_Signed.primitives.yaml +203/−0
- prims/commonverilog/Clash_Sized_Internal_Unsigned.primitives +0/−189
- prims/commonverilog/Clash_Sized_Internal_Unsigned.primitives.yaml +188/−0
- prims/commonverilog/Clash_Sized_Vector.primitives +0/−17
- prims/commonverilog/Clash_Sized_Vector.primitives.yaml +14/−0
- prims/commonverilog/Clash_Transformations.primitives +0/−8
- prims/commonverilog/Clash_Xilinx_ClockGen.primitives +0/−47
- prims/commonverilog/Clash_Xilinx_ClockGen.primitives.yaml +42/−0
- prims/commonverilog/GHC_Base.primitives +0/−8
- prims/commonverilog/GHC_Base.primitives.yaml +12/−0
- prims/commonverilog/GHC_Classes.primitives +0/−36
- prims/commonverilog/GHC_Classes.primitives.yaml +30/−0
- prims/commonverilog/GHC_Int.primitives +0/−30
- prims/commonverilog/GHC_Int.primitives.yaml +16/−0
- prims/commonverilog/GHC_Integer_Logarithms.primitives +0/−23
- prims/commonverilog/GHC_Integer_Logarithms.primitives.yaml +22/−0
- prims/commonverilog/GHC_Integer_Type.primitives +0/−189
- prims/commonverilog/GHC_Integer_Type.primitives.yaml +223/−0
- prims/commonverilog/GHC_Natural.primitives +0/−31
- prims/commonverilog/GHC_Natural.primitives.yaml +26/−0
- prims/commonverilog/GHC_Num_Integer.primitives +0/−244
- prims/commonverilog/GHC_Num_Integer.primitives.yaml +281/−0
- prims/commonverilog/GHC_Num_Natural.primitives +0/−113
- prims/commonverilog/GHC_Num_Natural.primitives.yaml +128/−0
- prims/commonverilog/GHC_Prim.primitives +0/−478
- prims/commonverilog/GHC_Prim.primitives.yaml +434/−0
- prims/commonverilog/GHC_Word.primitives +0/−30
- prims/commonverilog/GHC_Word.primitives.yaml +16/−0
- prims/systemverilog/Clash_Explicit_BlockRam.primitives +0/−140
- prims/systemverilog/Clash_Explicit_BlockRam.primitives.yaml +190/−0
- prims/systemverilog/Clash_Explicit_BlockRam_Blob.primitives.yaml +43/−0
- prims/systemverilog/Clash_Explicit_BlockRam_File.primitives +0/−52
- prims/systemverilog/Clash_Explicit_BlockRam_File.primitives.yaml +49/−0
- prims/systemverilog/Clash_Explicit_DDR.primitives +0/−93
- prims/systemverilog/Clash_Explicit_DDR.primitives.yaml +88/−0
- prims/systemverilog/Clash_Explicit_RAM.primitives +0/−31
- prims/systemverilog/Clash_Explicit_RAM.primitives.yaml +29/−0
- prims/systemverilog/Clash_Explicit_ROM.primitives +0/−32
- prims/systemverilog/Clash_Explicit_ROM.primitives.yaml +29/−0
- prims/systemverilog/Clash_Explicit_ROM_Blob.primitives.yaml +28/−0
- prims/systemverilog/Clash_Explicit_ROM_File.primitives +0/−35
- prims/systemverilog/Clash_Explicit_ROM_File.primitives.yaml +32/−0
- prims/systemverilog/Clash_Explicit_Testbench.primitives +0/−91
- prims/systemverilog/Clash_Explicit_Testbench.primitives.yaml +118/−0
- prims/systemverilog/Clash_Intel_DDR.primitives +0/−48
- prims/systemverilog/Clash_Intel_DDR.primitives.yaml +46/−0
- prims/systemverilog/Clash_Prelude_ROM.primitives +0/−18
- prims/systemverilog/Clash_Prelude_ROM.primitives.yaml +15/−0
- prims/systemverilog/Clash_Prelude_ROM_Blob.primitives.yaml +15/−0
- prims/systemverilog/Clash_Prelude_ROM_File.primitives +0/−22
- prims/systemverilog/Clash_Prelude_ROM_File.primitives.yaml +19/−0
- prims/systemverilog/Clash_Signal_BiSignal.primitives +0/−35
- prims/systemverilog/Clash_Signal_BiSignal.primitives.yaml +30/−0
- prims/systemverilog/Clash_Signal_Internal.primitives +0/−135
- prims/systemverilog/Clash_Signal_Internal.primitives.yaml +183/−0
- prims/systemverilog/Clash_Sized_Internal_BitVector.primitives +0/−79
- prims/systemverilog/Clash_Sized_Internal_BitVector.primitives.yaml +70/−0
- prims/systemverilog/Clash_Sized_Internal_Signed.primitives +0/−69
- prims/systemverilog/Clash_Sized_Internal_Signed.primitives.yaml +64/−0
- prims/systemverilog/Clash_Sized_Internal_Unsigned.primitives +0/−25
- prims/systemverilog/Clash_Sized_Internal_Unsigned.primitives.yaml +22/−0
- prims/systemverilog/Clash_Sized_RTree.primitives +0/−25
- prims/systemverilog/Clash_Sized_RTree.primitives.yaml +21/−0
- prims/systemverilog/Clash_Sized_Vector.primitives +0/−377
- prims/systemverilog/Clash_Sized_Vector.primitives.yaml +349/−0
- prims/systemverilog/Clash_Xilinx_DDR.primitives +0/−92
- prims/systemverilog/Clash_Xilinx_DDR.primitives.yaml +87/−0
- prims/systemverilog/GHC_Base.primitives +0/−33
- prims/systemverilog/GHC_Base.primitives.yaml +30/−0
- prims/systemverilog/GHC_Classes.primitives +0/−45
- prims/systemverilog/GHC_Classes.primitives.yaml +42/−0
- prims/systemverilog/GHC_Integer_Type.primitives +0/−97
- prims/systemverilog/GHC_Integer_Type.primitives.yaml +100/−0
- prims/systemverilog/GHC_Num_Integer.primitives +0/−97
- prims/systemverilog/GHC_Num_Integer.primitives.yaml +100/−0
- prims/systemverilog/GHC_Prim.primitives +0/−1459
- prims/systemverilog/GHC_Prim.primitives.yaml +1426/−0
- prims/verilog/Clash_Explicit_BlockRam.primitives +0/−151
- prims/verilog/Clash_Explicit_BlockRam.primitives.yaml +202/−0
- prims/verilog/Clash_Explicit_BlockRam_Blob.primitives.yaml +49/−0
- prims/verilog/Clash_Explicit_BlockRam_File.primitives +0/−50
- prims/verilog/Clash_Explicit_BlockRam_File.primitives.yaml +47/−0
- prims/verilog/Clash_Explicit_DDR.primitives +0/−88
- prims/verilog/Clash_Explicit_DDR.primitives.yaml +83/−0
- prims/verilog/Clash_Explicit_RAM.primitives +0/−31
- prims/verilog/Clash_Explicit_RAM.primitives.yaml +29/−0
- prims/verilog/Clash_Explicit_ROM.primitives +0/−38
- prims/verilog/Clash_Explicit_ROM.primitives.yaml +35/−0
- prims/verilog/Clash_Explicit_ROM_Blob.primitives.yaml +34/−0
- prims/verilog/Clash_Explicit_ROM_File.primitives +0/−33
- prims/verilog/Clash_Explicit_ROM_File.primitives.yaml +30/−0
- prims/verilog/Clash_Explicit_Testbench.primitives +0/−94
- prims/verilog/Clash_Explicit_Testbench.primitives.yaml +122/−0
- prims/verilog/Clash_Intel_DDR.primitives +0/−48
- prims/verilog/Clash_Intel_DDR.primitives.yaml +46/−0
- prims/verilog/Clash_Prelude_ROM.primitives +0/−26
- prims/verilog/Clash_Prelude_ROM.primitives.yaml +23/−0
- prims/verilog/Clash_Prelude_ROM_Blob.primitives.yaml +23/−0
- prims/verilog/Clash_Prelude_ROM_File.primitives +0/−22
- prims/verilog/Clash_Prelude_ROM_File.primitives.yaml +19/−0
- prims/verilog/Clash_Signal_BiSignal.primitives +0/−35
- prims/verilog/Clash_Signal_BiSignal.primitives.yaml +30/−0
- prims/verilog/Clash_Signal_Internal.primitives +0/−144
- prims/verilog/Clash_Signal_Internal.primitives.yaml +190/−0
- prims/verilog/Clash_Sized_Internal_BitVector.primitives +0/−75
- prims/verilog/Clash_Sized_Internal_BitVector.primitives.yaml +66/−0
- prims/verilog/Clash_Sized_Internal_Signed.primitives +0/−69
- prims/verilog/Clash_Sized_Internal_Signed.primitives.yaml +64/−0
- prims/verilog/Clash_Sized_Internal_Unsigned.primitives +0/−25
- prims/verilog/Clash_Sized_Internal_Unsigned.primitives.yaml +22/−0
- prims/verilog/Clash_Sized_RTree.primitives +0/−25
- prims/verilog/Clash_Sized_RTree.primitives.yaml +21/−0
- prims/verilog/Clash_Sized_Vector.primitives +0/−379
- prims/verilog/Clash_Sized_Vector.primitives.yaml +348/−0
- prims/verilog/Clash_Xilinx_DDR.primitives +0/−92
- prims/verilog/Clash_Xilinx_DDR.primitives.yaml +87/−0
- prims/verilog/GHC_Base.primitives +0/−33
- prims/verilog/GHC_Base.primitives.yaml +30/−0
- prims/verilog/GHC_Classes.primitives +0/−45
- prims/verilog/GHC_Classes.primitives.yaml +42/−0
- prims/verilog/GHC_Integer_Type.primitives +0/−99
- prims/verilog/GHC_Integer_Type.primitives.yaml +102/−0
- prims/verilog/GHC_Num_Integer.primitives +0/−99
- prims/verilog/GHC_Num_Integer.primitives.yaml +102/−0
- prims/verilog/GHC_Prim.primitives +0/−1507
- prims/verilog/GHC_Prim.primitives.yaml +1474/−0
- prims/vhdl/Clash_Class_Exp.primitives +0/−29
- prims/vhdl/Clash_Class_Exp.primitives.yaml +24/−0
- prims/vhdl/Clash_Explicit_BlockRam.primitives +0/−177
- prims/vhdl/Clash_Explicit_BlockRam.primitives.yaml +234/−0
- prims/vhdl/Clash_Explicit_BlockRam_Blob.primitives.yaml +43/−0
- prims/vhdl/Clash_Explicit_BlockRam_File.primitives +0/−95
- prims/vhdl/Clash_Explicit_BlockRam_File.primitives.yaml +92/−0
- prims/vhdl/Clash_Explicit_DDR.primitives +0/−166
- prims/vhdl/Clash_Explicit_DDR.primitives.yaml +161/−0
- prims/vhdl/Clash_Explicit_RAM.primitives +0/−54
- prims/vhdl/Clash_Explicit_RAM.primitives.yaml +52/−0
- prims/vhdl/Clash_Explicit_ROM.primitives +0/−37
- prims/vhdl/Clash_Explicit_ROM.primitives.yaml +34/−0
- prims/vhdl/Clash_Explicit_ROM_Blob.primitives.yaml +32/−0
- prims/vhdl/Clash_Explicit_ROM_File.primitives +0/−57
- prims/vhdl/Clash_Explicit_ROM_File.primitives.yaml +54/−0
- prims/vhdl/Clash_Explicit_SimIO.primitives +0/−31
- prims/vhdl/Clash_Explicit_SimIO.primitives.yaml +18/−0
- prims/vhdl/Clash_Explicit_Testbench.primitives +0/−199
- prims/vhdl/Clash_Explicit_Testbench.primitives.yaml +189/−0
- prims/vhdl/Clash_Intel_DDR.primitives +0/−97
- prims/vhdl/Clash_Intel_DDR.primitives.yaml +96/−0
- prims/vhdl/Clash_Magic.primitives +0/−13
- prims/vhdl/Clash_Magic.primitives.yaml +11/−0
- prims/vhdl/Clash_Prelude_ROM.primitives +0/−28
- prims/vhdl/Clash_Prelude_ROM.primitives.yaml +25/−0
- prims/vhdl/Clash_Prelude_ROM_Blob.primitives.yaml +24/−0
- prims/vhdl/Clash_Prelude_ROM_File.primitives +0/−41
- prims/vhdl/Clash_Prelude_ROM_File.primitives.yaml +38/−0
- prims/vhdl/Clash_Promoted_Nat.primitives +0/−34
- prims/vhdl/Clash_Promoted_Nat.primitives.yaml +30/−0
- prims/vhdl/Clash_Signal_BiSignal.primitives +0/−35
- prims/vhdl/Clash_Signal_BiSignal.primitives.yaml +30/−0
- prims/vhdl/Clash_Signal_Internal.primitives +0/−193
- prims/vhdl/Clash_Signal_Internal.primitives.yaml +190/−0
- prims/vhdl/Clash_Sized_Internal_BitVector.primitives +0/−585
- prims/vhdl/Clash_Sized_Internal_BitVector.primitives.yaml +592/−0
- prims/vhdl/Clash_Sized_Internal_Index.primitives +0/−138
- prims/vhdl/Clash_Sized_Internal_Index.primitives.yaml +148/−0
- prims/vhdl/Clash_Sized_Internal_Signed.primitives +0/−270
- prims/vhdl/Clash_Sized_Internal_Signed.primitives.yaml +318/−0
- prims/vhdl/Clash_Sized_Internal_Unsigned.primitives +0/−223
- prims/vhdl/Clash_Sized_Internal_Unsigned.primitives.yaml +263/−0
- prims/vhdl/Clash_Sized_RTree.primitives +0/−25
- prims/vhdl/Clash_Sized_RTree.primitives.yaml +23/−0
- prims/vhdl/Clash_Sized_Vector.primitives +0/−444
- prims/vhdl/Clash_Sized_Vector.primitives.yaml +411/−0
- prims/vhdl/Clash_Transformations.primitives +0/−8
- prims/vhdl/Clash_Xilinx_ClockGen.primitives +0/−70
- prims/vhdl/Clash_Xilinx_ClockGen.primitives.yaml +65/−0
- prims/vhdl/Clash_Xilinx_DDR.primitives +0/−103
- prims/vhdl/Clash_Xilinx_DDR.primitives.yaml +102/−0
- prims/vhdl/GHC_Base.primitives +0/−31
- prims/vhdl/GHC_Base.primitives.yaml +52/−0
- prims/vhdl/GHC_Classes.primitives +0/−66
- prims/vhdl/GHC_Classes.primitives.yaml +62/−0
- prims/vhdl/GHC_Int.primitives +0/−33
- prims/vhdl/GHC_Int.primitives.yaml +28/−0
- prims/vhdl/GHC_Integer_Logarithms.primitives +0/−8
- prims/vhdl/GHC_Integer_Logarithms.primitives.yaml +8/−0
- prims/vhdl/GHC_Integer_Type.primitives +0/−267
- prims/vhdl/GHC_Integer_Type.primitives.yaml +359/−0
- prims/vhdl/GHC_Natural.primitives +0/−32
- prims/vhdl/GHC_Natural.primitives.yaml +27/−0
- prims/vhdl/GHC_Num_Integer.primitives +0/−327
- prims/vhdl/GHC_Num_Integer.primitives.yaml +413/−0
- prims/vhdl/GHC_Num_Natural.primitives +0/−114
- prims/vhdl/GHC_Num_Natural.primitives.yaml +157/−0
- prims/vhdl/GHC_Prim.primitives +0/−1238
- prims/vhdl/GHC_Prim.primitives.yaml +1279/−0
- prims/vhdl/GHC_Word.primitives +0/−33
- prims/vhdl/GHC_Word.primitives.yaml +28/−0
- src/Clash/Backend.hs +33/−23
- src/Clash/Backend/SystemVerilog.hs +107/−72
- src/Clash/Backend/VHDL.hs +263/−141
- src/Clash/Backend/Verilog.hs +71/−45
- src/Clash/Core/DataCon.hs +13/−4
- src/Clash/Core/EqSolver.hs +13/−13
- src/Clash/Core/Evaluator/Types.hs +5/−6
- src/Clash/Core/FreeVars.hs +13/−72
- src/Clash/Core/HasFreeVars.hs +93/−0
- src/Clash/Core/HasType.hs +264/−0
- src/Clash/Core/Literal.hs +24/−29
- src/Clash/Core/Name.hs +0/−1
- src/Clash/Core/PartialEval/AsTerm.hs +10/−17
- src/Clash/Core/PartialEval/Monad.hs +5/−5
- src/Clash/Core/PartialEval/NormalForm.hs +12/−11
- src/Clash/Core/Pretty.hs +75/−16
- src/Clash/Core/Subst.hs +67/−45
- src/Clash/Core/Term.hs +49/−17
- src/Clash/Core/TermInfo.hs +14/−208
- src/Clash/Core/TermLiteral.hs +3/−8
- src/Clash/Core/Termination.hs +0/−95
- src/Clash/Core/TyCon.hs +27/−9
- src/Clash/Core/Type.hs +13/−43
- src/Clash/Core/TysPrim.hs +33/−17
- src/Clash/Core/Util.hs +71/−29
- src/Clash/Core/Var.hs +2/−15
- src/Clash/Core/VarEnv.hs +26/−3
- src/Clash/Debug.hs +0/−8
- src/Clash/Driver.hs +235/−146
- src/Clash/Driver/Manifest.hs +105/−59
- src/Clash/Driver/Types.hs +289/−103
- src/Clash/Netlist.hs +47/−48
- src/Clash/Netlist/BlackBox.hs +56/−43
- src/Clash/Netlist/BlackBox/Parser.hs +4/−3
- src/Clash/Netlist/BlackBox/Types.hs +11/−13
- src/Clash/Netlist/BlackBox/Util.hs +71/−50
- src/Clash/Netlist/Id.hs +0/−4
- src/Clash/Netlist/Id/Common.hs +3/−4
- src/Clash/Netlist/Id/Internal.hs +1/−1
- src/Clash/Netlist/Types.hs +90/−91
- src/Clash/Netlist/Types.hs-boot +8/−2
- src/Clash/Netlist/Util.hs +30/−46
- src/Clash/Normalize.hs +49/−86
- src/Clash/Normalize/DEC.hs +0/−662
- src/Clash/Normalize/PrimitiveReductions.hs +54/−79
- src/Clash/Normalize/Primitives.hs +48/−0
- src/Clash/Normalize/Strategy.hs +55/−17
- src/Clash/Normalize/Transformations.hs +24/−3271
- src/Clash/Normalize/Transformations/ANF.hs +413/−0
- src/Clash/Normalize/Transformations/Case.hs +702/−0
- src/Clash/Normalize/Transformations/Cast.hs +146/−0
- src/Clash/Normalize/Transformations/DEC.hs +777/−0
- src/Clash/Normalize/Transformations/EtaExpand.hs +107/−0
- src/Clash/Normalize/Transformations/Inline.hs +664/−0
- src/Clash/Normalize/Transformations/Letrec.hs +458/−0
- src/Clash/Normalize/Transformations/MultiPrim.hs +130/−0
- src/Clash/Normalize/Transformations/Reduce.hs +480/−0
- src/Clash/Normalize/Transformations/SeparateArgs.hs +120/−0
- src/Clash/Normalize/Transformations/Specialize.hs +699/−0
- src/Clash/Normalize/Transformations/XOptimize.hs +156/−0
- src/Clash/Normalize/Types.hs +5/−25
- src/Clash/Normalize/Util.hs +57/−78
- src/Clash/Primitives/DSL.hs +5/−4
- src/Clash/Primitives/GHC/Literal.hs +1/−1
- src/Clash/Primitives/Intel/ClockGen.hs +7/−7
- src/Clash/Primitives/Sized/Signed.hs +43/−0
- src/Clash/Primitives/Sized/Vector.hs +12/−11
- src/Clash/Primitives/Types.hs +7/−1
- src/Clash/Primitives/Util.hs +23/−14
- src/Clash/Primitives/Verification.hs +30/−22
- src/Clash/Rewrite/Combinators.hs +3/−28
- src/Clash/Rewrite/Types.hs +109/−101
- src/Clash/Rewrite/Util.hs +156/−396
- src/Clash/Rewrite/WorkFree.hs +17/−11
- src/Clash/Unique.hs +29/−4
- src/Clash/Util.hs +1/−23
- src/Clash/Util/Eq.hs +46/−0
- src/Clash/Verification/Pretty.hs +278/−0
- src/Control/Applicative/Extra.hs +0/−18
- src/Data/Aeson/Extra.hs +30/−2
- src/Data/IntMap/Extra.hs +36/−0
- src/Data/Monoid/Extra.hs +16/−0
- src/Data/Semigroup/Monad/Extra.hs +0/−22
- src/Data/Set/Ordered/Extra.hs +1/−15
- src/Data/Text/Extra.hs +13/−0
- src/GHC/SrcLoc/Extra.hs +0/−2
- tests/Clash/Tests/Driver/Manifest.hs +18/−15
- tests/Test/Clash/Rewrite.hs +16/−30
- tools/v16-upgrade-primitives.hs +125/−0
CHANGELOG.md view
@@ -1,4 +1,77 @@ # Changelog for the Clash project+## 1.6.0 *Feb 10th 2022*+Added:+ * `Clash.Class.Counter`: a class that defines a odometer-style supercounter. [#1763](https://github.com/clash-lang/clash-compiler/pull/1763)+ * `isLike` function for BitPack types. [#1774](https://github.com/clash-lang/clash-compiler/pull/1774)+ * 'seqErrorX' for catching both `XException` and `ErrorCall`. [#1774](https://github.com/clash-lang/clash-compiler/pull/1774)+ * `Clash.Explicit.BlockRam.File.memFile`, a function for creating the contents of the data files this blockRAM uses. Can also be imported from `Clash.Prelude.BlockRam.File`, `Clash.Prelude.ROM.File` and `Clash.Explicit.ROM.File`. [#1840](https://github.com/clash-lang/clash-compiler/pull/1840)+ * Support for Yosys compatible SVA to `Clash.Verification`. This enables formal verification using SymbiYosis for Verilog and SystemVerilog. [#1798](https://github.com/clash-lang/clash-compiler/pull/1798)+ * `Clash.Explicit.Signal.Delayed.forward`, a function that can be used to retime a `DSignal` into the future without applying any logic. [#1882](https://github.com/clash-lang/clash-compiler/pull/1882)+ * `Clash.Signal.andEnable` is the `HiddenEnable` version of `Clash.Explicit.Signal.andEnable` (formerly known as `enable`) [#1849](https://github.com/clash-lang/clash-compiler/pull/1849)+ * `runUntil`, a function to sample a signal until it returns a value that satisfies the user-given test. It is a convenience function that, among others, allow easy running of a `testBench` style function in Haskell simulation, logging assertion failures to stderr. [#1940](https://github.com/clash-lang/clash-compiler/pull/1940)+ * Support for true dual ported block ram through `Clash.Prelude.BlockRam.trueDualPortBlockRam` and `Clash.Explicit.BlockRam.trueDualPortBlockRam`. [#1726](https://github.com/clash-lang/clash-compiler/pull/1726) [#1975](https://github.com/clash-lang/clash-compiler/pull/1975)+ * `clash-{prelude,lib}-hedgehog` packages which provide generators for types in `clash-prelude` and `clash-lib`. The former is published on Hackage. [#1976](https://github.com/clash-lang/clash-compiler/pull/1976)+ * Clash now contains black boxes which are verilator compatible. When running with `--verilog` or `--systemverilog` a C++ shim is automatically produced which can be used to quickly generate a verilated executable. Users who wish to interact with verilator simulations are recommended to use [clashilator](https://github.com/gergoerdi/clashilator). [#2019](https://github.com/clash-lang/clash-compiler/pull/2019)+ * Support for YAML blackboxes. Clash will now pickup on files with a `.primitives.yaml` extension. While we recommend upgrading your primitive files to the new format, old style primitives are still supported. We've included a tool to automatically upgrade your JSON files, see [#2037](https://github.com/clash-lang/clash-compiler/pull/2037)+ * `MemBlob`: a datastructure for efficient constants, typically used for initializing memories. [#2041](https://github.com/clash-lang/clash-compiler/pull/2041)++Fixed:++ * BlockRam simulation is now less strict. [#1458](https://github.com/clash-lang/clash-compiler/issues/1458)+ * Don't overflow VHDL's integer type when addressing RAM/ROM in simulation.Addresses are masked to 32 bits to be sure to keep it within the simulator's range. [#1875](https://github.com/clash-lang/clash-compiler/pull/1875)+ * `show` on `BitVector 0` no longer results in an empty string. [#1785](https://github.com/clash-lang/clash-compiler/pull/1785)+ * Clash now preserves transfinite floating numbers (NaN, Infinity) when packing/unpacking [#1803](https://github.com/clash-lang/clash-compiler/issues/1803)+ * `SynthesisAnnotation`s can now be defined in type synoynms without being excluded from the generated HDL [#1771](https://github.com/clash-lang/clash-compiler/issues/1771)+ * Manifest files now correctly list bidirectional ports as "inout" rather than "in" [#1843](https://github.com/clash-lang/clash-compiler/issues/1843)+ * `div`/`rem`/`mod` now avoid division by zero during VHDL simulation. Due to the use of concurrent statements, even unreachable code would previously result in simulation error [#1873](https://github.com/clash-lang/clash-compiler/pull/1873)+ * Don't overflow the range of VHDL's natural type in shift/rotate, leading to simulation issues. Shift now saturates to a 31-bit shift amount. For rotate, in simulation only, the rotate amount is modulo the word width of the rotated value [#1874](https://github.com/clash-lang/clash-compiler/pull/1874)+ * `shiftL` for Clash datatypes does not cause a crash anymore when running Clash code with a really large shift amount [#1874](https://github.com/clash-lang/clash-compiler/pull/1874)+ * VHDL generated for `Signed.fromInteger` now truncates, like the Clash simulation, when the result is smaller than the argument [#1874](https://github.com/clash-lang/clash-compiler/pull/1874)+ * Clash now preserves boolean combinatorial logic better when generating HDL [#1881](https://github.com/clash-lang/clash-compiler/issues/1881)+ * `valid` field of `TemplateFunction` is now checked for includes [#1945](https://github.com/clash-lang/clash-compiler/issues/1945)+ * Clash now generates clock generators that ensure that the amount of time between simulation start and the first active edge of the clock is equal to (/or longer than/) the period of the clock. The first active edges of the clocks do still occur simultaneously. [#2001](https://github.com/clash-lang/clash-compiler/issues/2001)+ * Expected values in assert become undefined when using `-fclash-compile-ultra` [#2040](https://github.com/clash-lang/clash-compiler/issues/2040)+ * `toEnum`/`fromEnum` on sized types is now less eager to report warnings about integer functions being used [#2046](https://github.com/clash-lang/clash-compiler/issues/2046)++Changed:++ * `Clash.Verification.PrettyPrinters` has been moved from clash-prelude to to `Clash.Verification.Pretty` in `clash-lib`. [#1798](https://github.com/clash-lang/clash-compiler/pull/1798)+ * RAM/ROM functions: They now throw `XExeception` for out-of-bounds address inputs, so this condition no longer aborts simulation. [#1875](https://github.com/clash-lang/clash-compiler/pull/1875)+ * `Vec`'s show instance now generates valid Haskell. [#1776](https://github.com/clash-lang/clash-compiler/issues/1776)+ * `ShowX` and its functions now produce valid Haskell [#1782](https://github.com/clash-lang/clash-compiler/issues/1782)+ * `bLit` now infers the size of the generated BitVector from the string given to it. This means you don't have to give it an explicit type signature anymore. This does slightly modify the syntax needed to invoke `bLit`. E.g., `$$(bLit "00..1") :: BitVector 5` should be rewritten as `$(bLit "00..1")`. If you relied on the size inference, wrap the new invocation in `resize`. For example: `resize $(bLit "00..1")`. [#1784](https://github.com/clash-lang/clash-compiler/pull/1784)+ * `NumericUnderscores` is now enabled by default in `clash`, `clashi`, and starter projects using Clash >=1.6. [#1785](https://github.com/clash-lang/clash-compiler/pull/1785)+ * `Show` instance of `BitVector` now includes a `0b` prefix, making it a copyable expression for fully defined vectors. [#1785](https://github.com/clash-lang/clash-compiler/pull/1785)+ * `blockRam` uses `STArray` as the underlying representation to improve simulation performance [#1878](https://github.com/clash-lang/clash-compiler/pull/1878)+ * `asyncRom` now throws `XException` for out-of-bounds addressing, no longer aborting simulation [#1878](https://github.com/clash-lang/clash-compiler/pull/1878)+ * Clash now renders ADTs with all zero-width fields as enumerations in VHDL [#1879](https://github.com/clash-lang/clash-compiler/pull/1879)+ * A warning about possible hard-to-debug issues has been added to the `Clash.Signal` documentation on hidden clocks, resets, and enables, in the form of the section named "Monomorphism restriction leads to surprising behavior" [#1960](https://github.com/clash-lang/clash-compiler/pull/1960)+ * `Clash.Explicit.Testbench.outputVerifier` and `outputVerifierBitVector` now emit a warning if they are used improperly. This situation only arises when they are used in synthesized code rather than a test bench context. When the clock domains `circuitDom` and `testDom` are two different domains, the clock crossing inside `outputVerifier` is only suitable inside a test bench, not inside a synthesized circuit. Clash now emits a warning for this case. [#1931](https://github.com/clash-lang/clash-compiler/pull/1931)+ * `resetSynchronizer` now no longer takes an `Enable` argument. The argument was already marked for removal and was ignored. [#1964](https://github.com/clash-lang/clash-compiler/pull/1964)+ * Clash can now compile multiple entities concurrently, providing speedups to designs with multiple entities to build [#2034](https://github.com/clash-lang/clash-compiler/pull/2034)+ * All `asyncRam` variants and `asyncFIFOSynchronizer` now require that the data has an `NFDataX` instance. [#2055](https://github.com/clash-lang/clash-compiler/pull/2055)+ * Clash now respects the `-Werror` option from GHC [#2066](https://github.com/clash-lang/clash-compiler/pull/2066)+ * `asyncFIFOSynchronizer` now uses the synchronous dual-ported RAM `trueDualPortBlockRam`, where it previously used a dual-ported RAM with an asynchronous read port `asyncRam`. With this change it's nearly guaranteed that `asyncFIFOSynchronizer` actually synthesizes to a circuit that uses the dual-ported RAMs found on most FPGAs. [#2083](https://github.com/clash-lang/clash-compiler/pull/2083)++Deprecated:+ * The function `Clash.Explicit.Signal.enable` is renamed to `andEnable` and the existing name deprecated [#1849](https://github.com/clash-lang/clash-compiler/pull/1849)+ * '-fclash-float-support': it is now on by default and can't be turned off. [#2048](https://github.com/clash-lang/clash-compiler/pull/2048)++Removed:++ * GHC 8.4 is no longer supported. Users should upgrade to at least GHC 8.6. [#1762](https://github.com/clash-lang/clash-compiler/pull/1762)++Internal changes:+ * `clash-lib` now uses `Data.Monoid.Ap` instead of `Data.Semigroup.Monad.Mon`. This means users defining primitives with `TemplateFunction` will need to replace `Mon`/`getMon` with `Ap`/`getAp`. [#1835](https://github.com/clash-lang/clash-compiler/pull/1835)+ * Clash now supports more expressive debug options at the command line [#1800](https://github.com/clash-lang/clash-compiler/issues/1800).+ * Added `zeroWidthSpec` transformation [#1891](https://github.com/clash-lang/clash-compiler/pull/1891)+ * Added `collapseRHSNoops` inlining stage and `WorkIdentity` constructor [#1896](https://github.com/clash-lang/clash-compiler/pull/1896)+ * Added `HasType` and `InferType` classes for getting / inferring core types from data representing some typed "thing" [#1915](https://github.com/clash-lang/clash-compiler/pull/1915)+ * Added `HasFreeVars` class for getting free variables from data "containing" variables [#1917](https://github.com/clash-lang/clash-compiler/pull/1917)+ * Added the primitive equality type (`~#`) to `Clash.Core.TysPrim`. In order to make this change, `undefinedTy` and `unsafeCoerceTy` were moved from `Clash.Core.Type` to `Clash.Core.Util`. [#1955](https://github.com/clash-lang/clash-compiler/pull/1955)+ * Clash now keeps information about which let bindings are recursive from GHC core. This can be used to avoid performing free variable calculations, or sorting bindings in normalization. [#1980](https://github.com/clash-lang/clash-compiler/pull/1980) [#2000](https://github.com/clash-lang/clash-compiler/pull/2000)+ * Manifest files now use SHA256 for a cache invalidation digest [#1985](https://github.com/clash-lang/clash-compiler/pull/1985)+ ## 1.4.7 *Jan 30th 2022* Fixed: * Clash now shows days in time strings for compile runs which take longer than a day [#1989](https://github.com/clash-lang/clash-compiler/compare/issue-1989).
clash-lib.cabal view
@@ -1,6 +1,6 @@ Cabal-version: 2.2 Name: clash-lib-Version: 1.4.7+Version: 1.6.0 Synopsis: Clash: a functional hardware description language - As a library Description: Clash is a functional hardware description language that borrows both its@@ -61,11 +61,11 @@ src/ClashDebug.h Data-files:- prims/common/*.primitives,- prims/commonverilog/*.primitives,- prims/verilog/*.primitives,- prims/systemverilog/*.primitives,- prims/vhdl/*.primitives+ prims/common/*.primitives.yaml,+ prims/commonverilog/*.primitives.yaml,+ prims/verilog/*.primitives.yaml,+ prims/systemverilog/*.primitives.yaml,+ prims/vhdl/*.primitives.yaml source-repository head type: git@@ -84,12 +84,6 @@ default: True manual: True -flag experimental-evaluator- description:- Use the new partial evaluator (experimental; may break)- default: False- manual: True- common common-options default-language: Haskell2010 default-extensions: BangPatterns@@ -105,6 +99,7 @@ DerivingStrategies InstanceSigs KindSignatures+ NoStarIsType ScopedTypeVariables StandaloneDeriving TupleSections@@ -112,10 +107,6 @@ TypeOperators ViewPatterns - if impl(ghc >= 8.6)- default-extensions: NoStarIsType-- Library import: common-options HS-Source-Dirs: src@@ -139,12 +130,13 @@ aeson-pretty >= 0.8 && < 0.9, ansi-terminal >= 0.8.0.0 && < 0.12, array,+ async >= 2.2.0 && < 2.3, attoparsec >= 0.10.4.0 && < 0.15, base >= 4.11 && < 5, base16-bytestring >= 0.1.1 && < 1.1, binary >= 0.8.5 && < 0.11, bytestring >= 0.10.0.2 && < 0.12,- clash-prelude == 1.4.7,+ clash-prelude == 1.6.0, concurrent-supply >= 0.1.7 && < 0.2, containers >= 0.5.0.0 && < 0.7, cryptohash-sha256 >= 0.11 && < 0.12,@@ -153,11 +145,10 @@ deepseq >= 1.3.0.2 && < 1.5, dlist >= 0.8 && < 1.1, directory >= 1.2.0.1 && < 1.4,- errors >= 1.4.2 && < 2.4, exceptions >= 0.8.3 && < 0.11.0, extra >= 1.6.17 && < 1.8, filepath >= 1.3.0.1 && < 1.5,- ghc >= 8.4.0 && < 9.1,+ ghc >= 8.6.0 && < 9.1, ghc-boot-th, hashable >= 1.2.1.0 && < 1.5, haskell-src-meta >= 0.8 && < 0.9,@@ -166,24 +157,20 @@ lens >= 4.10 && < 5.1.0, mtl >= 2.1.2 && < 2.3, ordered-containers >= 0.2 && < 0.3,- parsers >= 0.12.8 && < 1.0, prettyprinter >= 1.2.0.1 && < 1.8, pretty-show >= 1.9 && < 2.0, primitive >= 0.5.0.1 && < 1.0,- process >= 1.1.0.2 && < 1.7,- reducers >= 3.12.2 && < 4.0, template-haskell >= 2.8.0.0 && < 2.18, temporary >= 1.2.1 && < 1.4, terminal-size >= 0.3 && < 0.4, text >= 1.2.2 && < 2.1,- text-show >= 3.7 && < 3.10, time >= 1.4.0.1 && < 1.14, transformers >= 0.5.2.0 && < 0.7, trifecta >= 1.7.1.1 && < 2.2,- utf8-string >= 1.0.1 && < 1.1, vector >= 0.11 && < 1.0, vector-binary-instances >= 0.2.3.5 && < 0.3,- unordered-containers >= 0.2.3.3 && < 0.3+ unordered-containers >= 0.2.3.3 && < 0.3,+ yaml >= 0.11 && < 0.12, if impl(ghc >= 9.0.0) build-depends: ghc-bignum >=1.0 && <1.3@@ -203,6 +190,8 @@ Clash.Core.EqSolver Clash.Core.Evaluator.Types Clash.Core.FreeVars+ Clash.Core.HasType+ Clash.Core.HasFreeVars Clash.Core.Literal Clash.Core.Name Clash.Core.PartialEval@@ -215,7 +204,6 @@ Clash.Core.TermInfo Clash.Core.TermLiteral Clash.Core.TermLiteral.TH- Clash.Core.Termination Clash.Core.TyCon Clash.Core.Type Clash.Core.TysPrim@@ -246,10 +234,22 @@ Clash.Netlist.Util Clash.Normalize- Clash.Normalize.DEC Clash.Normalize.PrimitiveReductions+ Clash.Normalize.Primitives Clash.Normalize.Strategy Clash.Normalize.Transformations+ Clash.Normalize.Transformations.ANF+ Clash.Normalize.Transformations.Case+ Clash.Normalize.Transformations.Cast+ Clash.Normalize.Transformations.DEC+ Clash.Normalize.Transformations.EtaExpand+ Clash.Normalize.Transformations.Inline+ Clash.Normalize.Transformations.Letrec+ Clash.Normalize.Transformations.MultiPrim+ Clash.Normalize.Transformations.Reduce+ Clash.Normalize.Transformations.SeparateArgs+ Clash.Normalize.Transformations.Specialize+ Clash.Normalize.Transformations.XOptimize Clash.Normalize.Types Clash.Normalize.Util @@ -262,6 +262,7 @@ Clash.Primitives.GHC.Word Clash.Primitives.Intel.ClockGen Clash.Primitives.Sized.ToInteger+ Clash.Primitives.Sized.Signed Clash.Primitives.Sized.Vector Clash.Primitives.Verification @@ -272,20 +273,28 @@ Clash.Unique Clash.Util+ Clash.Util.Eq Clash.Util.Graph Clash.Util.Interpolate Clash.Pretty + Clash.Verification.Pretty++ -- Used in v16-upgrade-primitives to decode our non-standard+ -- JSON primitive files.+ Data.Aeson.Extra++ -- Used in clash-cores Data.Text.Prettyprint.Doc.Extra Other-Modules: Clash.Annotations.TopEntity.Extra- Control.Applicative.Extra- Data.Aeson.Extra+ Data.IntMap.Extra Data.List.Extra Data.Map.Ordered.Extra+ Data.Monoid.Extra Data.Primitive.ByteArray.Extra- Data.Semigroup.Monad.Extra Data.Set.Ordered.Extra+ Data.Text.Extra GHC.BasicTypes.Extra GHC.SrcLoc.Extra Paths_clash_lib@@ -293,8 +302,21 @@ if flag(debug) cpp-options: -DDEBUG - if flag(experimental-evaluator)- cpp-options: -DEXPERIMENTAL_EVALUATOR+executable v16-upgrade-primitives+ Main-Is: tools/v16-upgrade-primitives.hs+ Build-Depends:+ base,+ aeson,+ deepseq,+ yaml,+ bytestring,+ clash-lib,+ containers,+ directory,+ stringsearch,+ Glob+ GHC-Options: -Wall -Wcompat+ default-language: Haskell2010 test-suite unittests import: common-options@@ -343,6 +365,3 @@ Clash.Tests.Normalize.Transformations Test.Clash.Rewrite-- if flag(experimental-evaluator)- cpp-options: -DEXPERIMENTAL_EVALUATOR
− prims/common/Clash_Annotations_BitRepresentation_Deriving.primitives
@@ -1,9 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Annotations.BitRepresentation.Deriving.dontApplyInHDL"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "dontApplyInHDL :: (a -> b) -> a -> b"- , "template" : "~ARG[1]"- }- }-]
+ prims/common/Clash_Annotations_BitRepresentation_Deriving.primitives.yaml view
@@ -0,0 +1,7 @@+- BlackBox:+ name: Clash.Annotations.BitRepresentation.Deriving.dontApplyInHDL+ kind: Expression+ type: 'dontApplyInHDL+ :: (a -> b) -> a -> b'+ template: ~ARG[1]+ workInfo: Never
− prims/common/Clash_Class_BitPack.primitives
@@ -1,37 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Class.BitPack.packFloat#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" :-"packFloat# :: Float -> BitVector 32"- , "template" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Class.BitPack.unpackFloat#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" :-"packFloat# :: BitVector 32 -> Float"- , "template" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Class.BitPack.packDouble#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" :-"packFloat# :: Double -> BitVector 64"- , "template" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Class.BitPack.unpackDouble#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" :-"packFloat# :: BitVector 64 -> Double"- , "template" : "~ARG[0]"- }- }-]
+ prims/common/Clash_Class_BitPack.primitives.yaml view
@@ -0,0 +1,28 @@+- BlackBox:+ name: Clash.Class.BitPack.Internal.packFloat#+ kind: Expression+ type: 'packFloat# :: Float+ -> BitVector 32'+ template: ~ARG[0]+ workInfo: Never+- BlackBox:+ name: Clash.Class.BitPack.Internal.unpackFloat#+ kind: Expression+ type: 'packFloat# :: BitVector+ 32 -> Float'+ template: ~ARG[0]+ workInfo: Never+- BlackBox:+ name: Clash.Class.BitPack.Internal.packDouble#+ kind: Expression+ type: 'packFloat# :: Double+ -> BitVector 64'+ template: ~ARG[0]+ workInfo: Never+- BlackBox:+ name: Clash.Class.BitPack.Internal.unpackDouble#+ kind: Expression+ type: 'packFloat# :: BitVector+ 64 -> Double'+ template: ~ARG[0]+ workInfo: Never
− prims/common/Clash_Explicit_Signal.primitives
@@ -1,14 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Explicit.Signal.veryUnsafeSynchronizer"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" :-"veryUnsafeSynchronizer- :: Int -- ARG[0]- -> Int -- ARG[1]- -> Signal dom1 a -- ARG[2]- -> Signal dom2 a"- , "template" : "~ARG[2]"- }- }-]
+ prims/common/Clash_Explicit_Signal.primitives.yaml view
@@ -0,0 +1,11 @@+- BlackBox:+ name: Clash.Explicit.Signal.veryUnsafeSynchronizer+ kind: Expression+ type: |-+ veryUnsafeSynchronizer+ :: Int -- ARG[0]+ -> Int -- ARG[1]+ -> Signal dom1 a -- ARG[2]+ -> Signal dom2 a+ template: ~ARG[2]+ workInfo: Never
+ prims/common/Clash_Explicit_Testbench.primitives.yaml view
@@ -0,0 +1,15 @@+- BlackBox:+ name: Clash.Explicit.Testbench.unsafeSimSynchronizer+ kind: Expression+ type: |-+ unsafeSimSynchronizer+ :: forall dom1 dom2 a+ . ( KnownDomain dom1 -- ARG[0]+ , KnownDomain dom2 ) -- ARG[1]+ => Clock dom1 -- ARG[2]+ -> Clock dom2 -- ARG[3]+ -> Signal dom1 a -- ARG[4]+ -> Signal dom2 a+ template: ~ARG[4]+ warning: Clash.Explicit.Testbench.unsafeSimSynchronizer is not safely synthesizable!+ workInfo: Never
− prims/common/Clash_GHC_GHC2Core.primitives
@@ -1,20 +0,0 @@-[ { "BlackBox" :- { "name" : "EmptyCase"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "template" : "~ERRORO"- }- }-, { "Primitive" :- { "name" : "_CO_"- , "workInfo" : "Constant"- , "primType" : "Constructor"- }- }-, { "Primitive" :- { "name" : "_TY_"- , "workInfo" : "Constant"- , "primType" : "Constructor"- }- }-]
+ prims/common/Clash_GHC_GHC2Core.primitives.yaml view
@@ -0,0 +1,13 @@+- BlackBox:+ name: EmptyCase+ kind: Expression+ template: ~ERRORO+ workInfo: Constant+- Primitive:+ name: _CO_+ primType: Constructor+ workInfo: Constant+- Primitive:+ name: _TY_+ primType: Constructor+ workInfo: Constant
− prims/common/Clash_Intel_ClockGen.primitives
@@ -1,29 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Intel.ClockGen.altpll"- , "workInfo" : "Always"- , "kind" : "Declaration"- , "includes" : [ {"extension": "qsys"- ,"name": "altpll"- ,"format": "Haskell"- ,"templateFunction": "Clash.Primitives.Intel.ClockGen.altpllQsysTF"- }- ]- , "format" : "Haskell"- , "templateFunction" : "Clash.Primitives.Intel.ClockGen.altpllTF"- }- }-, { "BlackBox" :- { "name" : "Clash.Intel.ClockGen.alteraPll"- , "workInfo" : "Always"- , "kind" : "Declaration"- , "includes" : [ {"extension": "qsys"- ,"name": "altera_pll"- ,"format": "Haskell"- ,"templateFunction": "Clash.Primitives.Intel.ClockGen.alteraPllQsysTF"- }- ]- , "format" : "Haskell"- , "templateFunction" : "Clash.Primitives.Intel.ClockGen.alteraPllTF"- }- }-]
+ prims/common/Clash_Intel_ClockGen.primitives.yaml view
@@ -0,0 +1,22 @@+- BlackBox:+ name: Clash.Intel.ClockGen.altpll+ format: Haskell+ includes:+ - name: altpll+ extension: qsys+ format: Haskell+ templateFunction: Clash.Primitives.Intel.ClockGen.altpllQsysTF+ kind: Declaration+ templateFunction: Clash.Primitives.Intel.ClockGen.altpllTF+ workInfo: Always+- BlackBox:+ name: Clash.Intel.ClockGen.alteraPll+ format: Haskell+ includes:+ - name: altera_pll+ extension: qsys+ format: Haskell+ templateFunction: Clash.Primitives.Intel.ClockGen.alteraPllQsysTF+ kind: Declaration+ templateFunction: Clash.Primitives.Intel.ClockGen.alteraPllTF+ workInfo: Always
− prims/common/Clash_Magic.primitives
@@ -1,31 +0,0 @@-[ { "Primitive" :- { "name" : "Clash.Magic.prefixName"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Magic.suffixName"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Magic.suffixNameFromNat"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Magic.suffixNameP"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Magic.suffixNameFromNatP"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Magic.setName"- , "primType" : "Function"- }- }-]
+ prims/common/Clash_Magic.primitives.yaml view
@@ -0,0 +1,18 @@+- Primitive:+ name: Clash.Magic.prefixName+ primType: Function+- Primitive:+ name: Clash.Magic.suffixName+ primType: Function+- Primitive:+ name: Clash.Magic.suffixNameFromNat+ primType: Function+- Primitive:+ name: Clash.Magic.suffixNameP+ primType: Function+- Primitive:+ name: Clash.Magic.suffixNameFromNatP+ primType: Function+- Primitive:+ name: Clash.Magic.setName+ primType: Function
+ prims/common/Clash_Normalize_Primitives.primitives.yaml view
@@ -0,0 +1,18 @@+- BlackBox:+ name: Clash.Normalize.Primitives.removedArg+ kind: Expression+ type: 'removedArg :: a'+ template: ~ERRORO+ workInfo: Constant+- BlackBox:+ name: Clash.Normalize.Primitives.undefined+ kind: Expression+ type: 'undefined :: forall+ a . a'+ template: ~ERRORO+ workInfo: Constant+- BlackBox:+ name: c$multiPrimSelect+ kind: Expression+ template: '!__SHOULD NOT BE RENDERED__! ~ARG[0]~ARG[1]'+ workInfo: Always
− prims/common/Clash_Promoted_Nat.primitives
@@ -1,9 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Promoted.Nat.powSNat"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "Clash.Promoted.Nat.powSNat :: SNat a -> SNat b -> SNat (a^b)"- , "template" : "~LIT[0] ** ~LIT[1]"- }- }-]
+ prims/common/Clash_Promoted_Nat.primitives.yaml view
@@ -0,0 +1,7 @@+- BlackBox:+ name: Clash.Promoted.Nat.powSNat+ kind: Expression+ type: 'Clash.Promoted.Nat.powSNat+ :: SNat a -> SNat b -> SNat (a^b)'+ template: ~LIT[0] ** ~LIT[1]+ workInfo: Never
− prims/common/Clash_Promoted_Nat_Unsafe.primitives
@@ -1,9 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Promoted.Nat.Unsafe.unsafeSNat"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "Clash.Promoted.Nat.Unsafe.unsafeSNat :: Integer -> SNat k"- , "template" : "~LIT[0]"- }- }-]
+ prims/common/Clash_Promoted_Nat_Unsafe.primitives.yaml view
@@ -0,0 +1,7 @@+- BlackBox:+ name: Clash.Promoted.Nat.Unsafe.unsafeSNat+ kind: Expression+ type: 'Clash.Promoted.Nat.Unsafe.unsafeSNat+ :: Integer -> SNat k'+ template: ~LIT[0]+ workInfo: Never
− prims/common/Clash_Promoted_Symbol.primitives
@@ -1,17 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Promoted.Symbol.SSymbol"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "SSymbol :: KnownNat n => Proxy n -> SSymbol n"- , "template" : "~LIT[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Promoted.Symbol.symbolToString"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "symbolToString :: SSymbol n -> String"- , "template" : "~LIT[0]"- }- }-]
+ prims/common/Clash_Promoted_Symbol.primitives.yaml view
@@ -0,0 +1,14 @@+- BlackBox:+ name: Clash.Promoted.Symbol.SSymbol+ kind: Expression+ type: 'SSymbol :: KnownNat+ n => Proxy n -> SSymbol n'+ template: ~LIT[0]+ workInfo: Never+- BlackBox:+ name: Clash.Promoted.Symbol.symbolToString+ kind: Expression+ type: 'symbolToString+ :: SSymbol n -> String'+ template: ~LIT[0]+ workInfo: Never
− prims/common/Clash_Signal_BiSignal.primitives
@@ -1,30 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Signal.BiSignal.veryUnsafeToBiSignalIn"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" :-"veryUnsafeToBiSignalIn- :: ( HasCallStack -- ARG[0]- , KnownNat n -- ARG[1]- , Given (SBiSignalDefault ds) -- ARG[2]- )- => BiSignalOut ds d n -- ARG[3]- -> BiSignalIn ds d n"- , "template" : "~DEVNULL[~ARG[3]]"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.BiSignal.mergeBiSignalOuts"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" :-"mergeBiSignalOuts- :: ( HasCallStack -- ARG[0]- , KnownNat n -- ARG[1]- )- => Vec n (BiSignalOut defaultState dom m) -- ARG[2]- -> BiSignalOut defaultState dom m"- , "template" : "~DEVNULL[~ARG[2]]"- }- }-]
+ prims/common/Clash_Signal_BiSignal.primitives.yaml view
@@ -0,0 +1,25 @@+- BlackBox:+ name: Clash.Signal.BiSignal.veryUnsafeToBiSignalIn+ kind: Declaration+ type: |-+ veryUnsafeToBiSignalIn+ :: ( HasCallStack -- ARG[0]+ , KnownNat n -- ARG[1]+ , Given (SBiSignalDefault ds) -- ARG[2]+ )+ => BiSignalOut ds d n -- ARG[3]+ -> BiSignalIn ds d n+ template: ~DEVNULL[~ARG[3]]+ workInfo: Never+- BlackBox:+ name: Clash.Signal.BiSignal.mergeBiSignalOuts+ kind: Expression+ type: |-+ mergeBiSignalOuts+ :: ( HasCallStack -- ARG[0]+ , KnownNat n -- ARG[1]+ )+ => Vec n (BiSignalOut defaultState dom m) -- ARG[2]+ -> BiSignalOut defaultState dom m+ template: ~DEVNULL[~ARG[2]]+ workInfo: Never
− prims/common/Clash_Signal_Bundle.primitives
@@ -1,7 +0,0 @@-[ { "Primitive" :- { "name" : "Clash.Signal.Bundle.vecBundle#"- , "workInfo" : "Never"- , "primType" : "Function"- }- }-]
+ prims/common/Clash_Signal_Bundle.primitives.yaml view
@@ -0,0 +1,4 @@+- Primitive:+ name: Clash.Signal.Bundle.vecBundle#+ primType: Function+ workInfo: Never
− prims/common/Clash_Signal_Internal.primitives
@@ -1,37 +0,0 @@-[ { "Primitive" :- { "name" : "Clash.Signal.Internal.signal#"- , "workInfo" : "Never"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Signal.Internal.mapSignal#"- , "workInfo" : "Never"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Signal.Internal.appSignal#"- , "workInfo" : "Never"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Signal.Internal.foldr#"- , "workInfo" : "Never"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Signal.Internal.traverse#"- , "workInfo" : "Never"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Signal.Internal.joinSignal#"- , "workInfo" : "Never"- , "primType" : "Function"- }- }-]
+ prims/common/Clash_Signal_Internal.primitives.yaml view
@@ -0,0 +1,24 @@+- Primitive:+ name: Clash.Signal.Internal.signal#+ primType: Function+ workInfo: Never+- Primitive:+ name: Clash.Signal.Internal.mapSignal#+ primType: Function+ workInfo: Never+- Primitive:+ name: Clash.Signal.Internal.appSignal#+ primType: Function+ workInfo: Never+- Primitive:+ name: Clash.Signal.Internal.foldr#+ primType: Function+ workInfo: Never+- Primitive:+ name: Clash.Signal.Internal.traverse#+ primType: Function+ workInfo: Never+- Primitive:+ name: Clash.Signal.Internal.joinSignal#+ primType: Function+ workInfo: Never
− prims/common/Clash_Signal_Trace.primitives
@@ -1,67 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Signal.Trace.traceSignal1"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" :-"traceSignal1- :: ( BitPack a -- ARG[0]- , NFDataX a -- ARG[1]- , Typeable a ) -- ARG[2]- => String -- ARG[3]- -> Signal dom a -- ARG[4]- -> Signal dom a"- , "template" : "~ARG[4]"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Trace.traceVecSignal1"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" :-"traceVecSignal1- :: ( KnownNat n -- ARG[0]- , BitPack a -- ARG[1]- , NFDataX a -- ARG[2]- , Typeable a ) -- ARG[3]- => String -- ARG[4]- -> Signal dom (Vec (n+1) a) -- ARG[5]- -> Signal dom (Vec (n+1) a)"- , "template" : "~ARG[5]"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Trace.traceSignal"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" :-"traceSignal- :: forall dom a- . ( KnownDomain dom -- ARG[0]- , BitPack a -- ARG[1]- , NFDataX a -- ARG[2]- , Typeable a ) -- ARG[3]- => String -- ARG[4]- -> Signal dom a -- ARG[5]- -> Signal dom a"- , "template" : "~ARG[5]"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Trace.traceVecSignal"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" :-"traceVecSignal- :: forall dom a n- . ( KnownDomain dom -- ARG[0]- , KnownNat n -- ARG[1]- , BitPack a -- ARG[2]- , NFDataX a -- ARG[3]- , Typeable a ) -- ARG[4]- => String -- ARG[5]- -> Signal dom (Vec (n+1) a) -- ARG[6]- -> Signal dom (Vec (n+1) a)"- , "template" : "~ARG[6]"- }- }-]
+ prims/common/Clash_Signal_Trace.primitives.yaml view
@@ -0,0 +1,58 @@+- BlackBox:+ name: Clash.Signal.Trace.traceSignal1+ kind: Expression+ type: |-+ traceSignal1+ :: ( BitPack a -- ARG[0]+ , NFDataX a -- ARG[1]+ , Typeable a ) -- ARG[2]+ => String -- ARG[3]+ -> Signal dom a -- ARG[4]+ -> Signal dom a+ template: ~ARG[4]+ workInfo: Never+- BlackBox:+ name: Clash.Signal.Trace.traceVecSignal1+ kind: Expression+ type: |-+ traceVecSignal1+ :: ( KnownNat n -- ARG[0]+ , BitPack a -- ARG[1]+ , NFDataX a -- ARG[2]+ , Typeable a ) -- ARG[3]+ => String -- ARG[4]+ -> Signal dom (Vec (n+1) a) -- ARG[5]+ -> Signal dom (Vec (n+1) a)+ template: ~ARG[5]+ workInfo: Never+- BlackBox:+ name: Clash.Signal.Trace.traceSignal+ kind: Expression+ type: |-+ traceSignal+ :: forall dom a+ . ( KnownDomain dom -- ARG[0]+ , BitPack a -- ARG[1]+ , NFDataX a -- ARG[2]+ , Typeable a ) -- ARG[3]+ => String -- ARG[4]+ -> Signal dom a -- ARG[5]+ -> Signal dom a+ template: ~ARG[5]+ workInfo: Never+- BlackBox:+ name: Clash.Signal.Trace.traceVecSignal+ kind: Expression+ type: |-+ traceVecSignal+ :: forall dom a n+ . ( KnownDomain dom -- ARG[0]+ , KnownNat n -- ARG[1]+ , BitPack a -- ARG[2]+ , NFDataX a -- ARG[3]+ , Typeable a ) -- ARG[4]+ => String -- ARG[5]+ -> Signal dom (Vec (n+1) a) -- ARG[6]+ -> Signal dom (Vec (n+1) a)+ template: ~ARG[6]+ workInfo: Never
− prims/common/Clash_Sized_Internal_BitVector.primitives
@@ -1,43 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.undefined#"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "undefined# :: forall n . KnownNat n => BitVector n"- , "template" : "~ERRORO"- }- }-, { "Primitive" :- { "name" : "Clash.Sized.Internal.BitVector.checkUnpackUndef"- , "workInfo" : "Never"- , "primType" : "Function"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.lt##"- , "kind" : "Expression"- , "type" : "lt## :: Bit -> Bit -> Bool"- , "template" : "~ARG[0] < ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.ge##"- , "kind" : "Expression"- , "type" : "ge## :: Bit -> Bit -> Bool"- , "template" : "~ARG[0] >= ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.gt##"- , "kind" : "Expression"- , "type" : "gt## :: Bit -> Bit -> Bool"- , "template" : "~ARG[0] > ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.le##"- , "kind" : "Expression"- , "type" : "le## :: Bit -> Bit -> Bool"- , "template" : "~ARG[0] <= ~ARG[1]"- }- }-]
+ prims/common/Clash_Sized_Internal_BitVector.primitives.yaml view
@@ -0,0 +1,35 @@+- BlackBox:+ name: Clash.Sized.Internal.BitVector.undefined#+ kind: Expression+ type: 'undefined# :: forall+ n . KnownNat n => BitVector n'+ template: ~ERRORO+ workInfo: Constant+- Primitive:+ name: Clash.Sized.Internal.BitVector.checkUnpackUndef+ primType: Function+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.lt##+ kind: Expression+ type: 'lt## :: Bit ->+ Bit -> Bool'+ template: ~ARG[0] < ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.ge##+ kind: Expression+ type: 'ge## :: Bit ->+ Bit -> Bool'+ template: ~ARG[0] >= ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.gt##+ kind: Expression+ type: 'gt## :: Bit ->+ Bit -> Bool'+ template: ~ARG[0] > ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.le##+ kind: Expression+ type: 'le## :: Bit ->+ Bit -> Bool'+ template: ~ARG[0] <= ~ARG[1]
− prims/common/Clash_Sized_Internal_Index.primitives
@@ -1,8 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.quot#"- , "kind" : "Expression"- , "type" : "quot# :: Index n -> Index n -> Index n"- , "template" : "~ARG[0] / ~ARG[1]"- }- }-]
− prims/common/Clash_Sized_Internal_Signed.primitives
@@ -1,22 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.+#"- , "kind" : "Expression"- , "type" : "(+#) :: KnownNat n => Signed n -> Signed n -> Signed n"- , "template" : "~ARG[1] + ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.-#"- , "kind" : "Expression"- , "type" : "(-#) :: KnownNat n => Signed n -> Signed n -> Signed n"- , "template" : "~ARG[1] - ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.quot#"- , "kind" : "Expression"- , "type" : "quot# :: Signed n -> Signed n -> Signed n"- , "template" : "~ARG[0] / ~ARG[1]"- }- }-]
+ prims/common/Clash_Sized_Internal_Signed.primitives.yaml view
@@ -0,0 +1,12 @@+- BlackBox:+ name: Clash.Sized.Internal.Signed.+#+ kind: Expression+ type: '(+#) :: KnownNat+ n => Signed n -> Signed n -> Signed n'+ template: ~ARG[1] + ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.Signed.-#+ kind: Expression+ type: '(-#) :: KnownNat+ n => Signed n -> Signed n -> Signed n'+ template: ~ARG[1] - ~ARG[2]
− prims/common/Clash_Sized_Internal_Unsigned.primitives
@@ -1,46 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.+#"- , "kind" : "Expression"- , "type" : "(+#) :: KnownNat n => Unsigned n -> Unsigned n -> Unsigned n"- , "template" : "~ARG[1] + ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.-#"- , "kind" : "Expression"- , "type" : "(-#) :: KnownNat n => Unsigned n -> Unsigned n -> Unsigned n"- , "template" : "~ARG[1] - ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.quot#"- , "kind" : "Expression"- , "type" : "quot# :: Unsigned n -> Unsigned n -> Unsigned n"- , "template" : "~ARG[0] / ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.unsignedToWord"- , "kind" : "Expression"- , "template" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.unsigned8toWord8"- , "kind" : "Expression"- , "template" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.unsigned16toWord16"- , "kind" : "Expression"- , "template" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.unsigned32toWord32"- , "kind" : "Expression"- , "template" : "~ARG[0]"- }- }-]
+ prims/common/Clash_Sized_Internal_Unsigned.primitives.yaml view
@@ -0,0 +1,28 @@+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.+#+ kind: Expression+ type: '(+#) :: KnownNat+ n => Unsigned n -> Unsigned n -> Unsigned n'+ template: ~ARG[1] + ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.-#+ kind: Expression+ type: '(-#) :: KnownNat+ n => Unsigned n -> Unsigned n -> Unsigned n'+ template: ~ARG[1] - ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.unsignedToWord+ kind: Expression+ template: ~ARG[0]+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.unsigned8toWord8+ kind: Expression+ template: ~ARG[0]+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.unsigned16toWord16+ kind: Expression+ template: ~ARG[0]+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.unsigned32toWord32+ kind: Expression+ template: ~ARG[0]
− prims/common/Clash_Sized_RTree.primitives
@@ -1,7 +0,0 @@-[ { "Primitive" :- { "name" : "Clash.Sized.RTree.tdfold"- , "workInfo" : "Never"- , "primType" : "Function"- }- }-]
+ prims/common/Clash_Sized_RTree.primitives.yaml view
@@ -0,0 +1,4 @@+- Primitive:+ name: Clash.Sized.RTree.tdfold+ primType: Function+ workInfo: Never
− prims/common/Clash_Sized_Vector.primitives
@@ -1,47 +0,0 @@-[- {- "BlackBox": {- "name": "Clash.Sized.Vector.lazyV",- "workInfo" : "Never",- "kind": "Expression",- "type": "lazyV :: KnownNat n => Vec n a -> Vec n a",- "template": "~ARG[1]"- }- },- {- "BlackBox": {- "name": "Clash.Sized.Vector.seqV",- "workInfo" : "Never",- "kind": "Expression",- "type": "seqV :: KnownNat n => Vec n a -> b -> b",- "template": "~ARG[2]"- }- },- {- "BlackBox": {- "name": "Clash.Sized.Vector.seqVX",- "workInfo" : "Never",- "kind": "Expression",- "type": "seqVX :: KnownNat n => Vec n a -> b -> b",- "template": "~ARG[2]"- }- }-, { "Primitive" :- { "name" : "Clash.Sized.Vector.dfold"- , "workInfo" : "Never"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Sized.Vector.dtfold"- , "workInfo" : "Never"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Sized.Vector.traverse#"- , "workInfo" : "Never"- , "primType" : "Function"- }- }-]
+ prims/common/Clash_Sized_Vector.primitives.yaml view
@@ -0,0 +1,33 @@+- BlackBox:+ name: Clash.Sized.Vector.lazyV+ kind: Expression+ type: 'lazyV :: KnownNat+ n => Vec n a -> Vec n a'+ template: ~ARG[1]+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.seqV+ kind: Expression+ type: 'seqV :: KnownNat+ n => Vec n a -> b -> b'+ template: ~ARG[2]+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.seqVX+ kind: Expression+ type: 'seqVX :: KnownNat+ n => Vec n a -> b -> b'+ template: ~ARG[2]+ workInfo: Never+- Primitive:+ name: Clash.Sized.Vector.dfold+ primType: Function+ workInfo: Never+- Primitive:+ name: Clash.Sized.Vector.dtfold+ primType: Function+ workInfo: Never+- Primitive:+ name: Clash.Sized.Vector.traverse#+ primType: Function+ workInfo: Never
− prims/common/Clash_Transformations.primitives
@@ -1,24 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Transformations.removedArg"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "removedArg :: a"- , "template" : "~ERRORO"- }- }-, { "BlackBox" :- { "name" : "Clash.Transformations.undefined"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "undefined :: forall a . a"- , "template" : "~ERRORO"- }- }-, { "BlackBox" :- { "name" : "c$multiPrimSelect"- , "workInfo" : "Always"- , "kind" : "Expression"- , "template" : "!__SHOULD NOT BE RENDERED__! ~ARG[0]~ARG[1]"- }- }-]
− prims/common/Clash_XException.primitives
@@ -1,38 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.XException.seqX"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "seqX :: a -> b -> b"- , "template" : "~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.XException.errorX"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "errorX :: HasCallStack => String -> a"- , "template" : "~ERRORO"- }- }-, { "BlackBox" :- { "name" : "Clash.XException.deepseqX"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "deepseqX :: Undefined a => a -> b -> b"- , "template" : "~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.XException.hwSeqX"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "hwSeqX :: a -> b -> b"- , "template" : "~DEVNULL[~VAR[x][0]]~ARG[1]"- }- }-, { "Primitive" :- { "name" : "Clash.XException.xToErrorCtx"- , "primType" : "Function"- }- }-]
+ prims/common/Clash_XException.primitives.yaml view
@@ -0,0 +1,38 @@+- BlackBox:+ name: Clash.XException.seqX+ kind: Expression+ type: 'seqX :: a -> b+ -> b'+ template: ~ARG[1]+ workInfo: Never+- BlackBox:+ name: Clash.XException.seqErrorX+ kind: Expression+ type: 'seqErrorX :: a+ -> b -> b'+ template: ~ARG[1]+ workInfo: Never+- BlackBox:+ name: Clash.XException.errorX+ kind: Expression+ type: 'errorX :: HasCallStack+ => String -> a'+ template: ~ERRORO+ workInfo: Constant+- BlackBox:+ name: Clash.XException.deepseqX+ kind: Expression+ type: 'deepseqX :: Undefined+ a => a -> b -> b'+ template: ~ARG[2]+ workInfo: Never+- BlackBox:+ name: Clash.XException.hwSeqX+ kind: Expression+ type: 'hwSeqX :: a ->+ b -> b'+ template: ~DEVNULL[~VAR[x][0]]~ARG[1]+ workInfo: Never+- Primitive:+ name: Clash.XException.xToErrorCtx+ primType: Function
− prims/common/Control_Exception_Base.primitives
@@ -1,73 +0,0 @@-[ { "BlackBox" :- { "name" : "Control.Exception.Base.recSelError"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "recSelError :: Addr# -> a"- , "template" : "~ERRORO"- }- }-, { "BlackBox" :- { "name" : "Control.Exception.Base.recConError"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "recConError :: Addr# -> a"- , "template" : "~ERRORO"- }- }-, { "BlackBox" :- { "name" : "Control.Exception.Base.irrefutPatError"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "irrefutPatError :: Addr# -> a"- , "template" : "~ERRORO"- }- }-, { "BlackBox" :- { "name" : "Control.Exception.Base.runtimeError"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "runtimeError :: Addr# -> a"- , "template" : "~ERRORO"- }- }-, { "BlackBox" :- { "name" : "Control.Exception.Base.nonExhaustiveGuardsError"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "nonExhaustiveGuardsError :: Addr# -> a"- , "template" : "~ERRORO"- }- }-, { "BlackBox" :- { "name" : "Control.Exception.Base.patError"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "patError :: Addr# -> a"- , "template" : "~ERRORO"- }- }-, { "BlackBox" :- { "name" : "Control.Exception.Base.noMethodBindingError"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "noMethodBindingError :: Addr# -> a"- , "template" : "~ERRORO"- }- }-, { "BlackBox" :- { "name" : "Control.Exception.Base.absentError"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "absentError :: Addr# -> a"- , "template" : "~ERRORO"- }- }-, { "BlackBox" :- { "name" : "Control.Exception.Base.typeError"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "typeError :: Addr# -> a"- , "template" : "~ERRORO"- }- }-]
+ prims/common/Control_Exception_Base.primitives.yaml view
@@ -0,0 +1,63 @@+- BlackBox:+ name: Control.Exception.Base.recSelError+ kind: Expression+ type: 'recSelError ::+ Addr# -> a'+ template: ~ERRORO+ workInfo: Constant+- BlackBox:+ name: Control.Exception.Base.recConError+ kind: Expression+ type: 'recConError ::+ Addr# -> a'+ template: ~ERRORO+ workInfo: Constant+- BlackBox:+ name: Control.Exception.Base.irrefutPatError+ kind: Expression+ type: 'irrefutPatError+ :: Addr# -> a'+ template: ~ERRORO+ workInfo: Constant+- BlackBox:+ name: Control.Exception.Base.runtimeError+ kind: Expression+ type: 'runtimeError ::+ Addr# -> a'+ template: ~ERRORO+ workInfo: Constant+- BlackBox:+ name: Control.Exception.Base.nonExhaustiveGuardsError+ kind: Expression+ type: 'nonExhaustiveGuardsError+ :: Addr# -> a'+ template: ~ERRORO+ workInfo: Constant+- BlackBox:+ name: Control.Exception.Base.patError+ kind: Expression+ type: 'patError :: Addr#+ -> a'+ template: ~ERRORO+ workInfo: Constant+- BlackBox:+ name: Control.Exception.Base.noMethodBindingError+ kind: Expression+ type: 'noMethodBindingError+ :: Addr# -> a'+ template: ~ERRORO+ workInfo: Constant+- BlackBox:+ name: Control.Exception.Base.absentError+ kind: Expression+ type: 'absentError ::+ Addr# -> a'+ template: ~ERRORO+ workInfo: Constant+- BlackBox:+ name: Control.Exception.Base.typeError+ kind: Expression+ type: 'typeError :: Addr#+ -> a'+ template: ~ERRORO+ workInfo: Constant
− prims/common/Debug_Trace.primitives
@@ -1,9 +0,0 @@-[ { "BlackBox" :- { "name" : "Debug.Trace.trace"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "trace :: String -> a -> a"- , "template" : "~ARG[1]"- }- }-]
+ prims/common/Debug_Trace.primitives.yaml view
@@ -0,0 +1,7 @@+- BlackBox:+ name: Debug.Trace.trace+ kind: Expression+ type: 'trace :: String+ -> a -> a'+ template: ~ARG[1]+ workInfo: Never
− prims/common/GHC_Base.primitives
@@ -1,14 +0,0 @@-[ { "Primitive" :- { "name" : "GHC.Base.$"- , "workInfo" : "Never"- , "primType" : "Function"- }- }-, { "BlackBox" :- { "name" : "GHC.Base.quotInt"- , "kind" : "Expression"- , "type" : "quotInt :: Int -> Int -> Int"- , "template" : "~ARG[0] / ~ARG[1]"- }- }-]
+ prims/common/GHC_Base.primitives.yaml view
@@ -0,0 +1,4 @@+- Primitive:+ name: GHC.Base.$+ primType: Function+ workInfo: Never
− prims/common/GHC_CString.primitives
@@ -1,21 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.CString.unpackCString#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "template" : "~LIT[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.CString.unpackFoldrCString#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "template" : "~LIT[0]"- }- }-, { "Primitive" :- { "name" : "GHC.CString.unpackCStringUtf8#"- , "workInfo" : "Never"- , "primType" : "Function"- }- }-]
+ prims/common/GHC_CString.primitives.yaml view
@@ -0,0 +1,14 @@+- BlackBox:+ name: GHC.CString.unpackCString#+ kind: Expression+ template: ~LIT[0]+ workInfo: Never+- BlackBox:+ name: GHC.CString.unpackFoldrCString#+ kind: Expression+ template: ~LIT[0]+ workInfo: Never+- Primitive:+ name: GHC.CString.unpackCStringUtf8#+ primType: Function+ workInfo: Never
− prims/common/GHC_Classes.primitives
@@ -1,29 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Classes.gtInt"- , "kind" : "Expression"- , "type" : "gtInt :: Int -> Int -> Bool"- , "template" : "~ARG[0] > ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.geInt"- , "kind" : "Expression"- , "type" : "geInt :: Int -> Int -> Bool"- , "template" : "~ARG[0] >= ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.ltInt"- , "kind" : "Expression"- , "type" : "ltInt :: Int -> Int -> Bool"- , "template" : "~ARG[0] < ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.leInt"- , "kind" : "Expression"- , "type" : "leInt :: Int -> Int -> Bool"- , "template" : "~ARG[0] <= ~ARG[1]"- }- }-]
+ prims/common/GHC_Classes.primitives.yaml view
@@ -0,0 +1,24 @@+- BlackBox:+ name: GHC.Classes.gtInt+ kind: Expression+ type: 'gtInt :: Int ->+ Int -> Bool'+ template: ~ARG[0] > ~ARG[1]+- BlackBox:+ name: GHC.Classes.geInt+ kind: Expression+ type: 'geInt :: Int ->+ Int -> Bool'+ template: ~ARG[0] >= ~ARG[1]+- BlackBox:+ name: GHC.Classes.ltInt+ kind: Expression+ type: 'ltInt :: Int ->+ Int -> Bool'+ template: ~ARG[0] < ~ARG[1]+- BlackBox:+ name: GHC.Classes.leInt+ kind: Expression+ type: 'leInt :: Int ->+ Int -> Bool'+ template: ~ARG[0] <= ~ARG[1]
− prims/common/GHC_Err.primitives
@@ -1,25 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Err.error"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "error :: [Char] -> a"- , "template" : "~ERRORO"- }- }-, { "BlackBox" :- { "name" : "GHC.Err.errorWithoutStackTrace"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "errorWithoutStackTrace :: [Char] -> a"- , "template" : "~ERRORO"- }- }-, { "BlackBox" :- { "name" : "GHC.Err.undefined"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "undefined :: a"- , "template" : "~ERRORO"- }- }-]
+ prims/common/GHC_Err.primitives.yaml view
@@ -0,0 +1,20 @@+- BlackBox:+ name: GHC.Err.error+ kind: Expression+ type: 'error :: [Char]+ -> a'+ template: ~ERRORO+ workInfo: Constant+- BlackBox:+ name: GHC.Err.errorWithoutStackTrace+ kind: Expression+ type: 'errorWithoutStackTrace+ :: [Char] -> a'+ template: ~ERRORO+ workInfo: Constant+- BlackBox:+ name: GHC.Err.undefined+ kind: Expression+ type: 'undefined :: a'+ template: ~ERRORO+ workInfo: Constant
− prims/common/GHC_IO_Exception.primitives
@@ -1,14 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.IO.Exception.assertError"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "assertError :: HasCallStack => Bool -> a -> a"- , "comment" : "It would be nice if we could use a HDL assertion, however,- because in HDL, case alternatives are evaluated- concurrently, we would end up with the assertion being- triggered, even when the result of that branch is not- chosen in the multiplexer"- , "template" : "~ARG[2]"- }- }-]
+ prims/common/GHC_IO_Exception.primitives.yaml view
@@ -0,0 +1,13 @@+- BlackBox:+ name: GHC.IO.Exception.assertError+ comment: |-+ It would be nice if we could use a HDL assertion, however,+ because in HDL, case alternatives are evaluated+ concurrently, we would end up with the assertion being+ triggered, even when the result of that branch is not+ chosen in the multiplexer+ kind: Expression+ type: 'assertError ::+ HasCallStack => Bool -> a -> a'+ template: ~ARG[2]+ workInfo: Never
− prims/common/GHC_Integer_Type.primitives
@@ -1,50 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Integer.Type.plusInteger"- , "kind" : "Expression"- , "type" : "plusInteger :: Integer -> Integer -> Integer"- , "template" : "~ARG[0] + ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.minusInteger"- , "kind" : "Expression"- , "type" : "minusInteger :: Integer -> Integer -> Integer"- , "template" : "~ARG[0] - ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.quotInteger"- , "kind" : "Expression"- , "type" : "quotInteger :: Integer -> Integer -> Integer"- , "template" : "~ARG[0] / ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.leInteger"- , "kind" : "Expression"- , "type" : "leInteger :: Integer -> Integer -> Bool"- , "template" : "~ARG[0] <= ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.gtInteger"- , "kind" : "Expression"- , "type" : "gtInteger :: Integer -> Integer -> Bool"- , "template" : "~ARG[0] > ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.ltInteger"- , "kind" : "Expression"- , "type" : "ltInteger :: Integer -> Integer -> Bool"- , "template" : "~ARG[0] < ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.geInteger"- , "kind" : "Expression"- , "type" : "geInteger :: Integer -> Integer -> Bool"- , "template" : "~ARG[0] >= ~ARG[1]"- }- }-]
+ prims/common/GHC_Integer_Type.primitives.yaml view
@@ -0,0 +1,48 @@+- BlackBox:+ name: GHC.Integer.Type.plusInteger+ kind: Expression+ type: 'plusInteger ::+ Integer -> Integer -> Integer'+ template: ~ARG[0] + ~ARG[1]+ warning: 'GHC.Integer.Type.plusInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.minusInteger+ kind: Expression+ type: 'minusInteger ::+ Integer -> Integer -> Integer'+ template: ~ARG[0] - ~ARG[1]+ warning: 'GHC.Integer.Type.minusInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.leInteger+ kind: Expression+ type: 'leInteger :: Integer+ -> Integer -> Bool'+ template: ~ARG[0] <= ~ARG[1]+ warning: 'GHC.Integer.Type.leInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.gtInteger+ kind: Expression+ type: 'gtInteger :: Integer+ -> Integer -> Bool'+ template: ~ARG[0] > ~ARG[1]+ warning: 'GHC.Integer.Type.gtInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.ltInteger+ kind: Expression+ type: 'ltInteger :: Integer+ -> Integer -> Bool'+ template: ~ARG[0] < ~ARG[1]+ warning: 'GHC.Integer.Type.ltInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.geInteger+ kind: Expression+ type: 'geInteger :: Integer+ -> Integer -> Bool'+ template: ~ARG[0] >= ~ARG[1]+ warning: 'GHC.Integer.Type.geInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'
− prims/common/GHC_Magic.primitives
@@ -1,20 +0,0 @@-[ { "Primitive" :- { "name" : "GHC.Magic.lazy"- , "workInfo" : "Never"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "GHC.Magic.noinline"- , "workInfo" : "Never"- , "type" : "forall a. a -> a"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "GHC.Magic.runRW#"- , "workInfo" : "Never"- , "primType" : "Function"- }- }-]
+ prims/common/GHC_Magic.primitives.yaml view
@@ -0,0 +1,13 @@+- Primitive:+ name: GHC.Magic.lazy+ primType: Function+ workInfo: Never+- Primitive:+ name: GHC.Magic.noinline+ primType: Function+ type: forall a. a -> a+ workInfo: Never+- Primitive:+ name: GHC.Magic.runRW#+ primType: Function+ workInfo: Never
− prims/common/GHC_Natural.primitives
@@ -1,52 +0,0 @@-[- {- "Primitive": {- "name": "GHC.Natural.NatS#",- "workInfo" : "Never",- "primType": "Constructor",- "comment": "Needed to make the evaluator handle this constructor strictly"- }- },- {- "Primitive": {- "name": "GHC.Natural.naturalToInteger",- "workInfo": "Never",- "primType": "Function",- "warning": "GHC.Natural.naturalToInteger: No blackbox available without size inference for Natural and Integer"- }- },- {- "BlackBox": {- "name": "GHC.Natural.underflowError",- "workInfo" : "Constant",- "kind": "Expression",- "type": "underflowError :: a",- "template": "~ERRORO"- }- },- {- "BlackBox": {- "name": "GHC.Natural.plusNatural",- "kind": "Expression",- "type": "plusNatural :: Natural -> Natural -> Natural",- "template": "~ARG[0] + ~ARG[1]",- "warning": "GHC.Natural.plusNatural: Naturals are dynamically sized in simulation, but fixed-length after synthesization. Use carefully."- }- },- {- "BlackBox": {- "name": "GHC.Natural.minusNatural",- "kind": "Expression",- "type": "minusNatural :: Natural -> Natural -> Natural",- "template": "~ARG[0] - ~ARG[1]",- "warning": "GHC.Natural.minusNatural: Naturals are dynamically sized in simulation, but fixed-length after synthesization. Use carefully."- }- },- {- "Primitive": {- "name": "GHC.Natural.gcdNatural",- "workInfo" : "Never",- "primType": "Function"- }- }-]
+ prims/common/GHC_Natural.primitives.yaml view
@@ -0,0 +1,42 @@+- Primitive:+ name: GHC.Natural.NatS#+ comment: Needed to make the evaluator handle this constructor strictly+ primType: Constructor+ warning: 'GHC.Natural.NatS#: Naturals are dynamically sized in simulation, but+ fixed-length after synthesization. Use carefully.'+ workInfo: Never+- Primitive:+ name: GHC.Natural.naturalToInteger+ primType: Function+ warning: 'GHC.Natural.naturalToInteger: No blackbox available without size inference+ for Natural and Integer'+ workInfo: Never+- BlackBox:+ name: GHC.Natural.underflowError+ kind: Expression+ type: 'underflowError+ :: a'+ template: ~ERRORO+ workInfo: Constant+- BlackBox:+ name: GHC.Natural.plusNatural+ kind: Expression+ type: 'plusNatural ::+ Natural -> Natural -> Natural'+ template: ~ARG[0] + ~ARG[1]+ warning: 'GHC.Natural.plusNatural: Naturals are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Natural.minusNatural+ kind: Expression+ type: 'minusNatural ::+ Natural -> Natural -> Natural'+ template: ~ARG[0] - ~ARG[1]+ warning: 'GHC.Natural.minusNatural: Naturals are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- Primitive:+ name: GHC.Natural.gcdNatural+ primType: Function+ warning: 'GHC.Natural.gcdNatural: Naturals are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+ workInfo: Never
− prims/common/GHC_Num_Integer.primitives
@@ -1,78 +0,0 @@-[ { "Primitive":- { "name": "GHC.Num.Integer.IS"- , "workInfo": "Never"- , "primType": "Constructor"- , "comment": "Needed to make the evaluator handle this constructor strictly"- }-}-, { "Primitive":- { "name": "GHC.Num.Integer.IP"- , "workInfo": "Never"- , "primType": "Constructor"- , "comment": "Needed to make the evaluator handle this constructor strictly"- }-}-, { "Primitive":- { "name": "GHC.Num.Integer.IN"- , "workInfo": "Never"- , "primType": "Constructor"- , "comment": "Needed to make the evaluator handle this constructor strictly"- }-}-, { "Primitive":- { "name": "GHC.Num.Integer.integerFromNatural"- , "workInfo": "Never"- , "primType": "Function"- , "warning": "GHC.Num.Integer.integerFromNatural: No blackbox available without size inference for Natural and Integer"- }-}-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerAdd"- , "kind" : "Expression"- , "type" : "integerAdd :: Integer -> Integer -> Integer"- , "template" : "~ARG[0] + ~ARG[1]"- }-}-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerSub"- , "kind" : "Expression"- , "type" : "integerSub :: Integer -> Integer -> Integer"- , "template" : "~ARG[0] - ~ARG[1]"- }-}-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerQuot"- , "kind" : "Expression"- , "type" : "integerQuot :: Integer -> Integer -> Integer"- , "template" : "~ARG[0] / ~ARG[1]"- }-}-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerLe"- , "kind" : "Expression"- , "type" : "integerLe :: Integer -> Integer -> Bool"- , "template" : "~ARG[0] <= ~ARG[1]"- }-}-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerGt"- , "kind" : "Expression"- , "type" : "integerGt :: Integer -> Integer -> Bool"- , "template" : "~ARG[0] > ~ARG[1]"- }-}-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerLt"- , "kind" : "Expression"- , "type" : "integerLt :: Integer -> Integer -> Bool"- , "template" : "~ARG[0] < ~ARG[1]"- }-}-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerGe"- , "kind" : "Expression"- , "type" : "integerGe :: Integer -> Integer -> Bool"- , "template" : "~ARG[0] >= ~ARG[1]"- }-}-]
+ prims/common/GHC_Num_Integer.primitives.yaml view
@@ -0,0 +1,75 @@+- Primitive:+ name: GHC.Num.Integer.IS+ comment: Needed to make the evaluator handle this constructor strictly+ primType: Constructor+ warning: 'GHC.Num.Integer.IS: Integers are dynamically sized in simulation, but+ fixed-length after synthesization. Use carefully.'+ workInfo: Never+- Primitive:+ name: GHC.Num.Integer.IP+ comment: Needed to make the evaluator handle this constructor strictly+ primType: Constructor+ warning: 'GHC.Num.Integer.IP: Integers are dynamically sized in simulation, but+ fixed-length after synthesization. Use carefully.'+ workInfo: Never+- Primitive:+ name: GHC.Num.Integer.IN+ comment: Needed to make the evaluator handle this constructor strictly+ primType: Constructor+ warning: 'GHC.Num.Integer.IN: Integers are dynamically sized in simulation, but+ fixed-length after synthesization. Use carefully.'+ workInfo: Never+- Primitive:+ name: GHC.Num.Integer.integerFromNatural+ primType: Function+ warning: 'GHC.Num.Integer.integerFromNatural: No blackbox available without size+ inference for Natural and Integer'+ workInfo: Never+- BlackBox:+ name: GHC.Num.Integer.integerAdd+ kind: Expression+ type: 'integerAdd :: Integer+ -> Integer -> Integer'+ template: ~ARG[0] + ~ARG[1]+ warning: 'GHC.Num.Integer.integerAdd: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerSub+ kind: Expression+ type: 'integerSub :: Integer+ -> Integer -> Integer'+ template: ~ARG[0] - ~ARG[1]+ warning: 'GHC.Num.Integer.integerSub: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerLe+ kind: Expression+ type: 'integerLe :: Integer+ -> Integer -> Bool'+ template: ~ARG[0] <= ~ARG[1]+ warning: 'GHC.Num.Integer.integerLe: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerGt+ kind: Expression+ type: 'integerGt :: Integer+ -> Integer -> Bool'+ template: ~ARG[0] > ~ARG[1]+ warning: 'GHC.Num.Integer.integerGt: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerLt+ kind: Expression+ type: 'integerLt :: Integer+ -> Integer -> Bool'+ template: ~ARG[0] < ~ARG[1]+ warning: 'GHC.Num.Integer.integerLt: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerGe+ kind: Expression+ type: 'integerGe :: Integer+ -> Integer -> Bool'+ template: ~ARG[0] >= ~ARG[1]+ warning: 'GHC.Num.Integer.integerGe: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'
− prims/common/GHC_Num_Natural.primitives
@@ -1,84 +0,0 @@-[- {- "Primitive": {- "name": "GHC.Num.Natural.NS",- "workInfo" : "Never",- "primType": "Constructor",- "comment": "Needed to make the evaluator handle this constructor strictly"- }- },- {- "Primitive": {- "name": "GHC.Num.Natural.NB",- "workInfo" : "Never",- "primType": "Constructor",- "comment": "Needed to make the evaluator handle this constructor strictly"- }- },- {- "BlackBox": {- "name": "GHC.Num.Natural.naturalAdd",- "kind": "Expression",- "type": "naturalSub :: Natural -> Natural -> Natural",- "template": "~ARG[0] + ~ARG[1]",- "warning": "GHC.Num.Natural.naturalAdd: Naturals are dynamically sized in simulation, but fixed-length after synthesis. Use carefully."- }- },- {- "Primitive": {- "name": "GHC.Num.Natural.naturalSub",- "workInfo" : "Never",- "primType": "Function"- }- },- {- "BlackBox": {- "name": "GHC.Num.Natural.naturalSubUnsafe",- "kind": "Expression",- "type": "naturalSubUnsafe :: Natural -> Natural -> Natural",- "template": "~ARG[0] - ~ARG[1]",- "warning": "GHC.Num.Natural.naturalSubUnsafe: Naturals are dynamically sized in simulation, but fixed-length after synthesis. Use carefully."- }- },- {- "BlackBox": {- "name": "GHC.Num.Natural.naturalSubThrow",- "kind": "Expression",- "type": "naturalSubThrow :: Natural -> Natural -> Natural",- "template": "~ARG[0] - ~ARG[1]",- "warning": "GHC.Num.Natural.naturalSubThrow: Naturals are dynamically sized in simulation, but fixed-length after synthesis. Use carefully."- }- },- {- "BlackBox": {- "name": "GHC.Num.Natural.naturalMul",- "kind": "Expression",- "type": "naturalMul :: Natural -> Natural -> Natural",- "template": "~ARG[0] * ~ARG[1]",- "warning": "GHC.Num.Natural.naturalMul: Naturals are dynamically sized in simulation, but fixed-length after synthesis. Use carefully."- }- },- {- "BlackBox": {- "name": "GHC.Num.Natural.naturalQuot",- "kind": "Expression",- "type": "naturalQuot :: Natural -> Natural -> Natural",- "template": "~ARG[0] / ~ARG[1]",- "warning": "GHC.Num.Natural.naturalQuot: Naturals are dynamically sized in simulation, but fixed-length after synthesis. Use carefully."- }- },- {- "Primitive": {- "name": "GHC.Num.Natural.naturalGcd",- "workInfo" : "Never",- "primType": "Function"- }- },- {- "Primitive": {- "name": "GHC.Num.Natural.naturalLcm",- "workInfo" : "Never",- "primType": "Function"- }- }-]
+ prims/common/GHC_Num_Natural.primitives.yaml view
@@ -0,0 +1,64 @@+- Primitive:+ name: GHC.Num.Natural.NS+ comment: Needed to make the evaluator handle this constructor strictly+ primType: Constructor+ warning: 'GHC.Num.Natural.NS: Naturals are dynamically sized in simulation, but+ fixed-length after synthesization. Use carefully.'+ workInfo: Never+- Primitive:+ name: GHC.Num.Natural.NB+ comment: Needed to make the evaluator handle this constructor strictly+ primType: Constructor+ warning: 'GHC.Num.Natural.NB: Naturals are dynamically sized in simulation, but+ fixed-length after synthesization. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Num.Natural.naturalAdd+ kind: Expression+ type: 'naturalSub :: Natural+ -> Natural -> Natural'+ template: ~ARG[0] + ~ARG[1]+ warning: 'GHC.Num.Natural.naturalAdd: Naturals are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- Primitive:+ name: GHC.Num.Natural.naturalSub+ primType: Function+ warning: 'GHC.Num.Natural.naturalSub: Naturals are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Num.Natural.naturalSubUnsafe+ kind: Expression+ type: 'naturalSubUnsafe+ :: Natural -> Natural -> Natural'+ template: ~ARG[0] - ~ARG[1]+ warning: 'GHC.Num.Natural.naturalSubUnsafe: Naturals are dynamically sized in+ simulation, but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Natural.naturalSubThrow+ kind: Expression+ type: 'naturalSubThrow+ :: Natural -> Natural -> Natural'+ template: ~ARG[0] - ~ARG[1]+ warning: 'GHC.Num.Natural.naturalSubThrow: Naturals are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Natural.naturalMul+ kind: Expression+ type: 'naturalMul :: Natural+ -> Natural -> Natural'+ template: ~ARG[0] * ~ARG[1]+ warning: 'GHC.Num.Natural.naturalMul: Naturals are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- Primitive:+ name: GHC.Num.Natural.naturalGcd+ primType: Function+ warning: 'GHC.Num.Natural.naturalGcd: Naturals are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+ workInfo: Never+- Primitive:+ name: GHC.Num.Natural.naturalLcm+ primType: Function+ warning: 'GHC.Num.Natural.naturalLcm: Naturals are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+ workInfo: Never
− prims/common/GHC_Prim.primitives
@@ -1,61 +0,0 @@-[ { "Primitive" :- { "name" : "GHC.Prim.dataToTag#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "GHC.Prim.tagToEnum#"- , "primType" : "Function"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.unsafeCoerce#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "unsafeCoerce# :: a -> b"- , "template" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.+#"- , "kind" : "Expression"- , "type" : "(+#) :: Int# -> Int# -> Int#"- , "template" : "~ARG[0] + ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.-#"- , "kind" : "Expression"- , "type" : "(-#) :: Int# -> Int# -> Int#"- , "template" : "~ARG[0] - ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.quotInt#"- , "kind" : "Expression"- , "type" : "quotInt# :: Int# -> Int# -> Int#"- , "template" : "~ARG[0] / ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.plusWord#"- , "kind" : "Expression"- , "type" : "plusWord# :: Word# -> Word# -> Word#"- , "template" : "~ARG[0] + ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.minusWord#"- , "kind" : "Expression"- , "type" : "minusWord# :: Word# -> Word# -> Word#"- , "template" : "~ARG[0] - ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.quotWord#"- , "kind" : "Expression"- , "type" : "quotWord# :: Word# -> Word# -> Word#"- , "template" : "~ARG[0] / ~ARG[1]"- }- }-]
+ prims/common/GHC_Prim.primitives.yaml view
@@ -0,0 +1,37 @@+- Primitive:+ name: GHC.Prim.dataToTag#+ primType: Function+- Primitive:+ name: GHC.Prim.tagToEnum#+ primType: Function+- BlackBox:+ name: GHC.Prim.unsafeCoerce#+ kind: Expression+ type: 'unsafeCoerce# ::+ a -> b'+ template: ~ARG[0]+ workInfo: Never+- BlackBox:+ name: GHC.Prim.+#+ kind: Expression+ type: '(+#) :: Int# ->+ Int# -> Int#'+ template: ~ARG[0] + ~ARG[1]+- BlackBox:+ name: GHC.Prim.-#+ kind: Expression+ type: '(-#) :: Int# ->+ Int# -> Int#'+ template: ~ARG[0] - ~ARG[1]+- BlackBox:+ name: GHC.Prim.plusWord#+ kind: Expression+ type: 'plusWord# :: Word#+ -> Word# -> Word#'+ template: ~ARG[0] + ~ARG[1]+- BlackBox:+ name: GHC.Prim.minusWord#+ kind: Expression+ type: 'minusWord# :: Word#+ -> Word# -> Word#'+ template: ~ARG[0] - ~ARG[1]
− prims/common/GHC_Real.primitives
@@ -1,25 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Real.divZeroError"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "divZeroError :: a"- , "template" : "~ERRORO"- }- }-, { "BlackBox" :- { "name" : "GHC.Real.ratioZeroDenominatorError"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "ratioZeroDenominatorError :: a"- , "template" : "~ERRORO"- }- }-, { "BlackBox" :- { "name" : "GHC.Real.overflowError"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "overflowError :: a"- , "template" : "~ERRORO"- }- }-]
+ prims/common/GHC_Real.primitives.yaml view
@@ -0,0 +1,21 @@+- BlackBox:+ name: GHC.Real.divZeroError+ kind: Expression+ type: 'divZeroError ::+ a'+ template: ~ERRORO+ workInfo: Constant+- BlackBox:+ name: GHC.Real.ratioZeroDenominatorError+ kind: Expression+ type: 'ratioZeroDenominatorError+ :: a'+ template: ~ERRORO+ workInfo: Constant+- BlackBox:+ name: GHC.Real.overflowError+ kind: Expression+ type: 'overflowError ::+ a'+ template: ~ERRORO+ workInfo: Constant
− prims/common/GHC_TypeNats.primitives
@@ -1,9 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.TypeNats.natVal"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "natVal :: forall n proxy. KnownNat n => proxy n -> Natural"- , "template" : "~ARG[0]"- }- }-]
+ prims/common/GHC_TypeNats.primitives.yaml view
@@ -0,0 +1,7 @@+- BlackBox:+ name: GHC.TypeNats.natVal+ kind: Expression+ type: 'natVal :: forall+ n proxy. KnownNat n => proxy n -> Natural'+ template: ~ARG[0]+ workInfo: Never
− prims/common/GHC_Typelits.primitives
@@ -1,9 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.TypeLits.natVal"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "natVal :: forall n proxy. KnownNat n => proxy n -> Integer"- , "template" : "~ARG[0]"- }- }-]
+ prims/common/GHC_Typelits.primitives.yaml view
@@ -0,0 +1,7 @@+- BlackBox:+ name: GHC.TypeLits.natVal+ kind: Expression+ type: 'natVal :: forall+ n proxy. KnownNat n => proxy n -> Integer'+ template: ~ARG[0]+ workInfo: Never
− prims/common/GHC_Types.primitives
@@ -1,31 +0,0 @@-[ { "Primitive" :- { "name" : "GHC.Types.MkCoercible"- , "workInfo" : "Never"- , "primType" : "Constructor"- }- }-, { "BlackBox" :- { "name" : "GHC.Types.C#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "I# :: Char# -> Char"- , "template" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Types.I#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "I# :: Int# -> Int"- , "template" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Types.W#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "W# :: Word# -> Word"- , "template" : "~ARG[0]"- }- }-]
+ prims/common/GHC_Types.primitives.yaml view
@@ -0,0 +1,11 @@+- Primitive:+ name: GHC.Types.MkCoercible+ primType: Constructor+ workInfo: Never+- BlackBox:+ name: GHC.Types.C#+ kind: Expression+ type: 'I# :: Char# ->+ Char'+ template: ~ARG[0]+ workInfo: Never
− prims/common/Unsafe_Coerce.primitives
@@ -1,9 +0,0 @@-[ { "BlackBox" :- { "name" : "Unsafe.Coerce.unsafeCoerce"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "unsafeCoerce :: a -> b"- , "template" : "~ARG[0]"- }- }-]
+ prims/common/Unsafe_Coerce.primitives.yaml view
@@ -0,0 +1,7 @@+- BlackBox:+ name: Unsafe.Coerce.unsafeCoerce+ kind: Expression+ type: 'unsafeCoerce ::+ a -> b'+ template: ~ARG[0]+ workInfo: Never
− prims/commonverilog/Clash_Class_Exp.primitives
@@ -1,29 +0,0 @@-[- {- "BlackBox": {- "name": "Clash.Class.Exp.expIndex#",- "kind": "Declaration",- "type": "expIndex# :: KnownNat m => Index m -> SNat n -> Index (m^n)",- "template": "assign ~RESULT = ~DEVNULL[~ARG[0]]$signed(~ARG[1] ** ~LIT[2]);",- "warning": "Exponentiation is only supported on relatively small constructs (< 32 bits). Ideally, Clash should have constant folded your expression. See https://github.com/clash-lang/clash-compiler/issues/593."- }- },- {- "BlackBox": {- "name": "Clash.Class.Exp.expSigned#",- "kind": "Declaration",- "type": "expSigned# :: KnownNat m => Signed m -> SNat n -> Signed (m*n)",- "template": "assign ~RESULT = ~DEVNULL[~ARG[0]]$signed(~ARG[1] ** ~LIT[2]);",- "warning": "Exponentiation is only supported on relatively small constructs (< 32 bits). Ideally, Clash should have constant folded your expression. See https://github.com/clash-lang/clash-compiler/issues/593."- }- },- {- "BlackBox": {- "name": "Clash.Class.Exp.expUnsigned#",- "kind": "Declaration",- "type": "expUnsigned# :: KnownNat m => Unsigned m -> SNat n -> Unsigned (m*n)",- "template": "assign ~RESULT = ~DEVNULL[~ARG[0]]$unsigned(~ARG[1] ** ~LIT[2]);",- "warning": "Exponentiation is only supported on relatively small constructs (< 32 bits). Ideally, Clash should have constant folded your expression. See https://github.com/clash-lang/clash-compiler/issues/593."- }- }-]
+ prims/commonverilog/Clash_Class_Exp.primitives.yaml view
@@ -0,0 +1,24 @@+- BlackBox:+ name: Clash.Class.Exp.expIndex#+ kind: Declaration+ type: 'expIndex# :: KnownNat+ m => Index m -> SNat n -> Index (m^n)'+ template: assign ~RESULT = ~DEVNULL[~ARG[0]]$signed(~ARG[1] ** ~LIT[2]);+ warning: Exponentiation is only supported on relatively small constructs (< 32+ bits). Ideally, Clash should have constant folded your expression. See https://github.com/clash-lang/clash-compiler/issues/593.+- BlackBox:+ name: Clash.Class.Exp.expSigned#+ kind: Declaration+ type: 'expSigned# :: KnownNat+ m => Signed m -> SNat n -> Signed (m*n)'+ template: assign ~RESULT = ~DEVNULL[~ARG[0]]$signed(~ARG[1] ** ~LIT[2]);+ warning: Exponentiation is only supported on relatively small constructs (< 32+ bits). Ideally, Clash should have constant folded your expression. See https://github.com/clash-lang/clash-compiler/issues/593.+- BlackBox:+ name: Clash.Class.Exp.expUnsigned#+ kind: Declaration+ type: 'expUnsigned# ::+ KnownNat m => Unsigned m -> SNat n -> Unsigned (m*n)'+ template: assign ~RESULT = ~DEVNULL[~ARG[0]]$unsigned(~ARG[1] ** ~LIT[2]);+ warning: Exponentiation is only supported on relatively small constructs (< 32+ bits). Ideally, Clash should have constant folded your expression. See https://github.com/clash-lang/clash-compiler/issues/593.
− prims/commonverilog/Clash_Explicit_SimIO.primitives
@@ -1,127 +0,0 @@-[ { "Primitive" :- { "name" : "Clash.Explicit.SimIO.mealyIO"- , "primType" : "Function"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.SimIO.display"- , "kind" : "Declaration"- , "renderVoid" : "RenderVoid"- , "template" : "$display(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.SimIO.finish"- , "kind" : "Declaration"- , "renderVoid" : "RenderVoid"- , "template" : "$finish_and_return(~LIT[0]);"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.SimIO.reg"- , "kind" : "Expression"- , "template" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.SimIO.readReg"- , "kind" : "Expression"- , "template" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.SimIO.writeReg"- , "kind" : "Declaration"- , "renderVoid" : "RenderVoid"- , "template" : "~ARG[0] = ~ARG[1];"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.SimIO.openFile"- , "kind" : "Expression"- , "template" : "$fopen(~FILE[~LIT[0]],~LIT[1])"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.SimIO.closeFile"- , "kind" : "Declaration"- , "renderVoid" : "RenderVoid"- , "template" : "$fclose(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.SimIO.getChar"- , "kind" : "Expression"- , "template" : "$fgetc(~ARG[0])"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.SimIO.putChar"- , "kind" : "Declaration"- , "renderVoid" : "RenderVoid"- , "template" : "$ungetc(~ARG[0],~ARG[1]);"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.SimIO.getLine"- , "kind" : "Declaration"- , "template" : "~RESULT = $fgets(~ARG[2],~ARG[1]);"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.SimIO.isEOF"- , "kind" : "Expression"- , "template" : "$feof(~ARG[0])"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.SimIO.flush"- , "kind" : "Declaration"- , "renderVoid" : "RenderVoid"- , "template" : "$fflush(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.SimIO.seek"- , "kind" : "Declaration"- , "template" : "~RESULT = $fseek(~ARG[0],~ARG[1],~ARG[2]);"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.SimIO.rewind"- , "kind" : "Declaration"- , "template" : "~RESULT = $rewind(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.SimIO.tell"- , "kind" : "Expression"- , "template" : "$ftell(~ARG[0])"- }- }-, { "Primitive" :- { "name" : "Clash.Explicit.SimIO.fmapSimIO#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Explicit.SimIO.pureSimIO#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Explicit.SimIO.apSimIO#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Explicit.SimIO.bindSimIO#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Explicit.SimIO.unSimIO#"- , "primType" : "Function"- }- }-]
+ prims/commonverilog/Clash_Explicit_SimIO.primitives.yaml view
@@ -0,0 +1,90 @@+- Primitive:+ name: Clash.Explicit.SimIO.mealyIO+ primType: Function+- BlackBox:+ name: Clash.Explicit.SimIO.display+ kind: Declaration+ renderVoid: RenderVoid+ template: $display(~ARG[0]);+- BlackBox:+ name: Clash.Explicit.SimIO.finish+ kind: Declaration+ renderVoid: RenderVoid+ template: |-+ `ifdef VERILATOR+ $c("std::exit(~LIT[0]);");+ `else+ // NOTE: $finish_and_return is an iverilog extension!+ $finish_and_return(~LIT[0]);+ `endif+- BlackBox:+ name: Clash.Explicit.SimIO.reg+ kind: Expression+ template: ~ARG[0]+- BlackBox:+ name: Clash.Explicit.SimIO.readReg+ kind: Expression+ template: ~ARG[0]+- BlackBox:+ name: Clash.Explicit.SimIO.writeReg+ kind: Declaration+ renderVoid: RenderVoid+ template: ~ARG[0] = ~ARG[1];+- BlackBox:+ name: Clash.Explicit.SimIO.openFile+ kind: Expression+ template: $fopen(~FILE[~LIT[0]],~LIT[1])+- BlackBox:+ name: Clash.Explicit.SimIO.closeFile+ kind: Declaration+ renderVoid: RenderVoid+ template: $fclose(~ARG[0]);+- BlackBox:+ name: Clash.Explicit.SimIO.getChar+ kind: Expression+ template: $fgetc(~ARG[0])+- BlackBox:+ name: Clash.Explicit.SimIO.putChar+ kind: Declaration+ renderVoid: RenderVoid+ template: $ungetc(~ARG[0],~ARG[1]);+- BlackBox:+ name: Clash.Explicit.SimIO.getLine+ kind: Declaration+ template: ~RESULT = $fgets(~ARG[2],~ARG[1]);+- BlackBox:+ name: Clash.Explicit.SimIO.isEOF+ kind: Expression+ template: $feof(~ARG[0])+- BlackBox:+ name: Clash.Explicit.SimIO.flush+ kind: Declaration+ renderVoid: RenderVoid+ template: $fflush(~ARG[0]);+- BlackBox:+ name: Clash.Explicit.SimIO.seek+ kind: Declaration+ template: ~RESULT = $fseek(~ARG[0],~ARG[1],~ARG[2]);+- BlackBox:+ name: Clash.Explicit.SimIO.rewind+ kind: Declaration+ template: ~RESULT = $rewind(~ARG[0]);+- BlackBox:+ name: Clash.Explicit.SimIO.tell+ kind: Expression+ template: $ftell(~ARG[0])+- Primitive:+ name: Clash.Explicit.SimIO.fmapSimIO#+ primType: Function+- Primitive:+ name: Clash.Explicit.SimIO.pureSimIO#+ primType: Function+- Primitive:+ name: Clash.Explicit.SimIO.apSimIO#+ primType: Function+- Primitive:+ name: Clash.Explicit.SimIO.bindSimIO#+ primType: Function+- Primitive:+ name: Clash.Explicit.SimIO.unSimIO+ primType: Function
− prims/commonverilog/Clash_Explicit_Testbench.primitives
@@ -1,9 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Explicit.Testbench.tbEnableGen"- , "workInfo" : "Always"- , "kind" : "Declaration"- , "type" : "tbEnableGen :: Enable dom"- , "template" : "assign ~RESULT = 1'b1;"- }- }-]
+ prims/commonverilog/Clash_Explicit_Testbench.primitives.yaml view
@@ -0,0 +1,7 @@+- BlackBox:+ name: Clash.Explicit.Testbench.tbEnableGen+ kind: Declaration+ type: 'tbEnableGen ::+ Enable dom'+ template: assign ~RESULT = 1'b1;+ workInfo: Always
− prims/commonverilog/Clash_Intel_DDR.primitives
@@ -1,49 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Intel.DDR.altddioOut#"- , "kind" : "Declaration"- , "type" :-"altddioOut#- :: ( HasCallStack -- ARG[0]- , KnownConfi~ fast domf -- ARG[1]- , KnownConfi~ slow doms -- ARG[2]- , KnownNat m ) -- ARG[3]- => SSymbol deviceFamily -- ARG[4]- -> Clock slow -- ARG[5]- -> Reset slow -- ARG[6]- -> Enable slow -- ARG[7]- -> Signal slow (BitVector m) -- ARG[8]- -> Signal slow (BitVector m) -- ARG[9]- -> Signal fast (BitVector m)"- , "libraries" : ["altera_mf"]- , "template" :-"// altddioOut begin-altddio_out- #(- .extend_oe_disable (\"OFF\"),- .intended_device_family (~LIT[4]),- .invert_output (\"OFF\"),- .lpm_hint (\"UNUSED\"),- .lpm_type (\"altddio_out\"),- .oe_reg (\"UNREGISTERED\"),- .power_up_high (\"OFF\"),- .width (~SIZE[~TYPO])- )- ~GENSYM[~COMPNAME_ALTDDIO_OUT][7] (~IF ~ISSYNC[2] ~THEN- .sclr (~ARG[6]),- .aclr (1'b0),~ELSE- .aclr (~ARG[6]),- .sclr (1'b0),~FI- .datain_h (~ARG[8]),- .datain_l (~ARG[9]),- .outclock (~ARG[5]),- .outclocken (~IF ~ISACTIVEENABLE[7] ~THEN ~ARG[7] ~ELSE 1'b1 ~FI),- .dataout (~RESULT),- .aset (1'b0),- .sset (1'b0),- .oe (1'b1),- .oe_out ()- );-// altddioOut end"- }- }-]
+ prims/commonverilog/Clash_Intel_DDR.primitives.yaml view
@@ -0,0 +1,47 @@+- BlackBox:+ name: Clash.Intel.DDR.altddioOut#+ kind: Declaration+ libraries:+ - altera_mf+ type: |-+ altddioOut#+ :: ( HasCallStack -- ARG[0]+ , KnownConfi~ fast domf -- ARG[1]+ , KnownConfi~ slow doms -- ARG[2]+ , KnownNat m ) -- ARG[3]+ => SSymbol deviceFamily -- ARG[4]+ -> Clock slow -- ARG[5]+ -> Reset slow -- ARG[6]+ -> Enable slow -- ARG[7]+ -> Signal slow (BitVector m) -- ARG[8]+ -> Signal slow (BitVector m) -- ARG[9]+ -> Signal fast (BitVector m)+ template: |-+ // altddioOut begin+ altddio_out+ #(+ .extend_oe_disable ("OFF"),+ .intended_device_family (~LIT[4]),+ .invert_output ("OFF"),+ .lpm_hint ("UNUSED"),+ .lpm_type ("altddio_out"),+ .oe_reg ("UNREGISTERED"),+ .power_up_high ("OFF"),+ .width (~SIZE[~TYPO])+ )+ ~GENSYM[~COMPNAME_ALTDDIO_OUT][7] (~IF ~ISSYNC[2] ~THEN+ .sclr (~ARG[6]),+ .aclr (1'b0),~ELSE+ .aclr (~ARG[6]),+ .sclr (1'b0),~FI+ .datain_h (~ARG[8]),+ .datain_l (~ARG[9]),+ .outclock (~ARG[5]),+ .outclocken (~IF ~ISACTIVEENABLE[7] ~THEN ~ARG[7] ~ELSE 1'b1 ~FI),+ .dataout (~RESULT),+ .aset (1'b0),+ .sset (1'b0),+ .oe (1'b1),+ .oe_out ()+ );+ // altddioOut end
− prims/commonverilog/Clash_Magic.primitives
@@ -1,13 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Magic.nameHint"- , "kind" : "Declaration"- , "type" :-"nameHint- :: SSymbol sym -- ARG[0]- -> a -- ARG[1]- -> a"- , "resultName" : { "template" : "~NAME[0]" }- , "template" : "assign ~RESULT = ~ARG[1];"- }- }-]
+ prims/commonverilog/Clash_Magic.primitives.yaml view
@@ -0,0 +1,11 @@+- BlackBox:+ name: Clash.Magic.nameHint+ kind: Declaration+ type: |-+ nameHint+ :: SSymbol sym -- ARG[0]+ -> a -- ARG[1]+ -> a+ resultName:+ template: ~NAME[0]+ template: assign ~RESULT = ~ARG[1];
− prims/commonverilog/Clash_Promoted_Nat.primitives
@@ -1,78 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Promoted.Nat.flogBaseSNat"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "Clash.Promoted.Nat.flogBaseSNat :: (2 <= base, 1 <= x)- => SNat base -- ARG[2]- -> SNat x -- ARG[3]- -> SNat (FLog base x"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "flogBase"- , "extension" : "inc"- , "template" :-"// floor of logBase-function integer ~INCLUDENAME[0];- input integer base, value;- begin- for (~INCLUDENAME[0] = 0; value >= base; ~INCLUDENAME[0]=~INCLUDENAME[0]+1)- value = value / base;- end-endfunction"- }- ]- , "template" : "~INCLUDENAME[0](~LIT[2],~LIT[3])"- }- }-, { "BlackBox" :- { "name" : "Clash.Promoted.Nat.clogBaseSNat"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "Clash.Promoted.Nat.clogBaseSNat :: (2 <= base, 1 <= x)- => SNat base -- ARG[2]- -> SNat x -- ARG[3]- -> SNat (CLog base x"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "clogBase"- , "extension" : "inc"- , "template" :-"// ceiling of logBase-function integer ~INCLUDENAME[0];- input integer base, value;- begin- for (~INCLUDENAME[0] = 0; base ** ~INCLUDENAME[0] < value; ~~INCLUDENAME[0]=~INCLUDENAME[0]+1);- end-endfunction"- }- ]- , "template" : "~INCLUDENAME[0](~LIT[2],~LIT[3])"- }- }-, { "BlackBox" :- { "name" : "Clash.Promoted.Nat.logBaseSNat"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "Clash.Promoted.Nat.logBaseSNat :: (FLog base x ~ CLog base x)- => SNat base -- ARG[1]- -> SNat x -- ARG[2]- -> SNat (Log base x)"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "clogBase"- , "extension" : "inc"- , "template" :-"// logBaseSNat begin-function integer ~INCLUDENAME[0];- input integer base, value;- begin- for (~INCLUDENAME[0] = 0; value >= base; ~INCLUDENAME[0]=~INCLUDENAME[0]+1)- value = value / base;- end-endfunction"- }- ]- , "template" : "~INCLUDENAME[0](~LIT[1],~LIT[2])"- }- }-]
+ prims/commonverilog/Clash_Promoted_Nat.primitives.yaml view
@@ -0,0 +1,71 @@+- BlackBox:+ name: Clash.Promoted.Nat.flogBaseSNat+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: flogBase+ extension: inc+ template: |-+ // floor of logBase+ function integer ~INCLUDENAME[0];+ input integer base, value;+ begin+ for (~INCLUDENAME[0] = 0; value >= base; ~INCLUDENAME[0]=~INCLUDENAME[0]+1)+ value = value / base;+ end+ endfunction+ kind: Expression+ type: |-+ Clash.Promoted.Nat.flogBaseSNat :: (2 <= base, 1 <= x)+ => SNat base -- ARG[2]+ -> SNat x -- ARG[3]+ -> SNat (FLog base x+ template: ~INCLUDENAME[0](~LIT[2],~LIT[3])+ workInfo: Never+- BlackBox:+ name: Clash.Promoted.Nat.clogBaseSNat+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: clogBase+ extension: inc+ template: |-+ // ceiling of logBase+ function integer ~INCLUDENAME[0];+ input integer base, value;+ begin+ for (~INCLUDENAME[0] = 0; base ** ~INCLUDENAME[0] < value; ~~INCLUDENAME[0]=~INCLUDENAME[0]+1);+ end+ endfunction+ kind: Expression+ type: |-+ Clash.Promoted.Nat.clogBaseSNat :: (2 <= base, 1 <= x)+ => SNat base -- ARG[2]+ -> SNat x -- ARG[3]+ -> SNat (CLog base x+ template: ~INCLUDENAME[0](~LIT[2],~LIT[3])+ workInfo: Never+- BlackBox:+ name: Clash.Promoted.Nat.logBaseSNat+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: clogBase+ extension: inc+ template: |-+ // logBaseSNat begin+ function integer ~INCLUDENAME[0];+ input integer base, value;+ begin+ for (~INCLUDENAME[0] = 0; value >= base; ~INCLUDENAME[0]=~INCLUDENAME[0]+1)+ value = value / base;+ end+ endfunction+ kind: Expression+ type: |-+ Clash.Promoted.Nat.logBaseSNat :: (FLog base x ~ CLog base x)+ => SNat base -- ARG[1]+ -> SNat x -- ARG[2]+ -> SNat (Log base x)+ template: ~INCLUDENAME[0](~LIT[1],~LIT[2])+ workInfo: Never
− prims/commonverilog/Clash_Signal_Internal.primitives
@@ -1,19 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Signal.Internal.unsafeFromReset"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" :-"unsafeFromReset :: Reset dom -> Signal dom Bool"- , "template" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.unsafeToReset"- , "kind" : "Expression"- , "workInfo" : "Never"- , "type" :-"unsafeToReset :: Signal dom Bool -> Reset dom"- , "template" : "~ARG[0]"- }- }-]
+ prims/commonverilog/Clash_Signal_Internal.primitives.yaml view
@@ -0,0 +1,14 @@+- BlackBox:+ name: Clash.Signal.Internal.unsafeFromReset+ kind: Expression+ type: 'unsafeFromReset+ :: Reset dom -> Signal dom Bool'+ template: ~ARG[0]+ workInfo: Never+- BlackBox:+ name: Clash.Signal.Internal.unsafeToReset+ kind: Expression+ type: 'unsafeToReset ::+ Signal dom Bool -> Reset dom'+ template: ~ARG[0]+ workInfo: Never
− prims/commonverilog/Clash_Sized_Internal_BitVector.primitives
@@ -1,375 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.BV"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "BV :: Integer -> Integer -> BitVector n"- , "comment" : "THIS IS ONLY USED WHEN WW EXPOSES BITVECTOR INTERNALS"- , "template" : "~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[1]]]~THEN$unsigned(~VAR[i][1][0+:~SIZE[~TYPO]])~ELSE$unsigned({{(~SIZE[~TYPO]-~SIZE[~TYP[1]]) {1'b0}},~VAR[i][1]})~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.Bit"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "Bit :: Integer -> Integer -> BitVector n"- , "comment" : "THIS IS ONLY USED WHEN WW EXPOSES BIT INTERNALS"- , "template" : "~VAR[i][1][0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.high"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "high :: Bit"- , "template" : "1'b1"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.low"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "low :: Bit"- , "template" : "1'b0"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.pack#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "pack# :: Bit -> BitVector 1"- , "template" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.unpack#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "unpack# :: BitVector 1 -> Bit"- , "template" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.reduceAnd#"- , "kind" : "Expression"- , "type" : "reduceAnd# :: KnownNat n => BitVector n -> Bit"- , "template" : "~IF~SIZE[~TYP[1]]~THEN& (~ARG[1])~ELSE1'b1~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.reduceOr#"- , "kind" : "Expression"- , "type" : "reduceOr# :: KnownNat n => BitVector n -> Bit"- , "template" : "~IF~SIZE[~TYP[1]]~THEN| (~ARG[1])~ELSE1'b0~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.reduceXor#"- , "kind" : "Expression"- , "type" : "reduceXor# :: KnownNat n => BitVector n -> Bit"- , "template" : "~IF~SIZE[~TYP[1]]~THEN^ (~ARG[1])~ELSE1'b0~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.eq##"- , "kind" : "Expression"- , "type" : "eq## :: Bit -> Bit -> Bool"- , "template" : "~ARG[0] == ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.neq##"- , "kind" : "Expression"- , "type" : "neq## :: Bit -> Bit -> Bool"- , "template" : "~ARG[0] != ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.fromInteger##"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "fromInteger## :: Integer -> Integer -> Bit"- , "template" : "~VAR[i][0][0] ? 1'bx : ~VAR[i][1][0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.and##"- , "kind" : "Expression"- , "type" : "and## :: Bit -> Bit -> Bit"- , "template" : "~ARG[0] & ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.or##"- , "kind" : "Expression"- , "type" : "or## :: Bit -> Bit -> Bit"- , "template" : "~ARG[0] | ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.xor##"- , "kind" : "Expression"- , "type" : "xor## :: Bit -> Bit -> Bit"- , "template" : "~ARG[0] ^ ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.complement##"- , "kind" : "Expression"- , "type" : "complement## :: Bit -> Bit"- , "template" : "~ ~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.eq#"- , "kind" : "Expression"- , "type" : "eq# :: KnownNat n => BitVector n -> BitVector n -> Bool"- , "template" : "~IF~SIZE[~TYP[1]]~THEN~ARG[1] == ~ARG[2]~ELSE1'b1~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.neq#"- , "kind" : "Expression"- , "type" : "neq# :: KnownNat n => BitVector n -> BitVector n -> Bool"- , "template" : "~IF~SIZE[~TYP[1]]~THEN~ARG[1] != ~ARG[2]~ELSE1'b0~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.lt#"- , "kind" : "Expression"- , "type" : "lt# :: KnownNat n => BitVector n -> BitVector n -> Bool"- , "template" : "~IF~SIZE[~TYP[1]]~THEN~ARG[1] < ~ARG[2]~ELSE1'b0~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.ge#"- , "kind" : "Expression"- , "type" : "ge# :: KnownNat n => BitVector n -> BitVector n -> Bool"- , "template" : "~IF~SIZE[~TYP[1]]~THEN~ARG[1] >= ~ARG[2]~ELSE1'b1~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.gt#"- , "kind" : "Expression"- , "type" : "gt# :: KnownNat n => BitVector n -> BitVector n -> Bool"- , "template" : "~IF~SIZE[~TYP[1]]~THEN~ARG[1] > ~ARG[2]~ELSE1'b0~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.le#"- , "kind" : "Expression"- , "type" : "le# :: KnownNat n => BitVector n -> BitVector n -> Bool"- , "template" : "~IF~SIZE[~TYP[1]]~THEN~ARG[1] <= ~ARG[2]~ELSE1'b1~FI"- }- }-, { "BlackBoxHaskell" :- { "name" : "Clash.Sized.Internal.BitVector.toInteger#"- , "workInfo" : "Never"- , "templateFunction" : "Clash.Primitives.Sized.ToInteger.bvToIntegerVerilog"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.size#"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "size# :: KnownNat n => BitVector n -> Int"- , "template" : "~SIZE[~TYPO]'sd~SIZE[~TYP[1]]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.maxIndex#"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "maxIndex# :: KnownNat n => BitVector n -> Int"- , "template" : "~SIZE[~TYPO]'sd~SIZE[~TYP[1]] - ~SIZE[~TYPO]'sd1"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.++#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "(++#) :: KnownNat m => BitVector n -> BitVector m -> BitVector (n + m)"- , "template" : "~IF~AND[~SIZE[~TYP[1]],~SIZE[~TYP[2]]]~THEN{~ARG[1],~ARG[2]}~ELSE~IF~SIZE[~TYP[1]]~THEN~ARG[1]~ELSE~ARG[2]~FI~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.index#"- , "kind" : "Expression"- , "type" :-"index# :: KnownNat n -- ARG[0]- => BitVector n -- ARG[1]- -> Int -- ARG[2]- -> Bit"- , "template" : "~VAR[bv][1][~ARG[2]]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.slice#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" :-"slice# :: BitVector (m + 1 + i) -- ARG[0]- -> SNat m -- ARG[1]- -> SNat n -- ARG[2]- -> BitVector (m + 1 - n)"- , "template" : "~VAR[bv][0][~LIT[1] : ~LIT[2]]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.msb#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" :-"msb# :: KnownNat n -- ARG[0]- => BitVector n -- ARG[1]- -> Bit"- , "template" : "~IF ~SIZE[~TYP[1]] ~THEN ~VAR[bv][1][~SIZE[~TYP[1]]-1] ~ELSE 1'b0 ~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.lsb#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" :-"lsb# :: BitVector n -- ARG[0]- -> Bit"- , "template" : "~IF ~SIZE[~TYP[0]] ~THEN ~VAR[bv][0][0] ~ELSE 1'b0 ~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.minBound#"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "minBound# :: BitVector n"- , "template" : "~SIZE[~TYPO]'d0"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.maxBound#"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "maxBound# :: KnownNat n => BitVector n"- , "template" : "{~SIZE[~TYPO] {1'b1}}"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.+#"- , "kind" : "Expression"- , "type" : "(+#) :: KnownNat n => BitVector n -> BitVector n -> BitVector n"- , "template" : "~ARG[1] + ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.-#"- , "kind" : "Expression"- , "type" : "(-#) :: KnownNat n => BitVector n -> BitVector n -> BitVector n"- , "template" : "~ARG[1] - ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.*#"- , "kind" : "Expression"- , "type" : "(*#) :: KnownNat n => BitVector n -> BitVector n -> BitVector n"- , "template" : "~ARG[1] * ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.negate#"- , "kind" : "Expression"- , "type" : "negate# :: KnownNat n => BitVector n -> BitVector n"- , "template" : "-~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.fromInteger#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "fromInteger# :: KnownNat n => Integer -> Integer -> BitVector n"- , "template" : "~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[2]]]~THEN$unsigned(~VAR[i][2][0+:~SIZE[~TYPO]])~ELSE$unsigned({{(~SIZE[~TYPO]-~SIZE[~TYP[2]]) {1'b0}},~VAR[i][2]})~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.plus#"- , "kind" : "Declaration"- , "type" : "plus# :: (KnownNat m, KnownNat n) => BitVector m -> BitVector n -> BitVector (Max m n + 1)"- , "template" : "assign ~RESULT = ~IF~AND[~SIZE[~TYP[2]],~SIZE[~TYP[3]]]~THEN~ARG[2] + ~ARG[3]~ELSE~IF~SIZE[~TYP[2]]~THEN~ARG[2]~ELSE~ARG[3]~FI~FI;"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.minus#"- , "kind" : "Declaration"- , "type" : "minus# :: (KnownNat m, KnownNat n) => BitVector m -> BitVector n -> BitVector (Max m n + 1)"- , "template" : "assign ~RESULT = ~IF~AND[~SIZE[~TYP[2]],~SIZE[~TYP[3]]]~THEN~ARG[2] - ~ARG[3]~ELSE~IF~SIZE[~TYP[2]]~THEN~ARG[2]~ELSE-~ARG[3]~FI~FI;"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.times#"- , "kind" : "Declaration"- , "type" : "times# :: (KnownNat m, KnownNat n) => BitVector m -> BitVector n -> BitVector (m + n)"- , "template" : "assign ~RESULT = ~IF~AND[~SIZE[~TYP[2]],~SIZE[~TYP[3]]]~THEN~ARG[2] * ~ARG[3]~ELSE~SIZE[~TYPO]'d0~FI;"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.quot#"- , "kind" : "Expression"- , "type" : "quot# :: KnownNat n => BitVector n -> BitVector n -> BitVector n"- , "template" : "~ARG[1] / ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.rem#"- , "kind" : "Expression"- , "type" : "rem# :: KnownNat n => BitVector n -> BitVector n -> BitVector n"- , "template" : "~ARG[1] % ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.and#"- , "kind" : "Expression"- , "type" : "and# :: KnownNat n => BitVector n -> BitVector n -> BitVector n"- , "template" : "~ARG[1] & ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.or#"- , "kind" : "Expression"- , "type" : "or# :: KnownNat n => BitVector n -> BitVector n -> BitVector n"- , "template" : "~ARG[1] | ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.xor#"- , "kind" : "Expression"- , "type" : "xor# :: KnownNat => BitVector n -> BitVector n -> BitVector n"- , "template" : "~ARG[1] ^ ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.complement#"- , "kind" : "Expression"- , "type" : "complement# :: KnownNat n => BitVector n -> BitVector n"- , "template" : "~ ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.shiftL#"- , "kind" : "Expression"- , "type" : "shiftL# :: KnownNat n => BitVector n -> Int -> BitVector n"- , "template" : "~ARG[1] << ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.shiftR#"- , "kind" : "Expression"- , "type" : "shiftR# :: KnownNat n => BitVector n -> Int -> BitVector n"- , "template" : "~ARG[1] >> ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.truncateB#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "truncateB# :: forall a b . KnownNat a => BitVector (a + b) -> BitVector a"- , "template" : "~VAR[bv][1][0+:~SIZE[~TYPO]]"- }- }-]
+ prims/commonverilog/Clash_Sized_Internal_BitVector.primitives.yaml view
@@ -0,0 +1,346 @@+- BlackBox:+ name: Clash.Sized.Internal.BitVector.BV+ comment: THIS IS ONLY USED WHEN WW EXPOSES BITVECTOR INTERNALS+ kind: Expression+ type: 'BV :: Integer ->+ Integer -> BitVector n'+ template: ~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[1]]]~THEN$unsigned(~VAR[i][1][0+:~SIZE[~TYPO]])~ELSE$unsigned({{(~SIZE[~TYPO]-~SIZE[~TYP[1]])+ {1'b0}},~VAR[i][1]})~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.Bit+ comment: THIS IS ONLY USED WHEN WW EXPOSES BIT INTERNALS+ kind: Expression+ type: 'Bit :: Integer+ -> Integer -> BitVector n'+ template: ~VAR[i][1][0]+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.high+ kind: Expression+ type: 'high :: Bit'+ template: 1'b1+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.low+ kind: Expression+ type: 'low :: Bit'+ template: 1'b0+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.pack#+ kind: Expression+ type: 'pack# :: Bit ->+ BitVector 1'+ template: ~ARG[0]+ workInfo: Identity 0 []+- BlackBox:+ name: Clash.Sized.Internal.BitVector.unpack#+ kind: Expression+ type: 'unpack# :: BitVector+ 1 -> Bit'+ template: ~ARG[0]+ workInfo: Identity 0 []+- BlackBox:+ name: Clash.Sized.Internal.BitVector.reduceAnd#+ kind: Expression+ type: 'reduceAnd# :: KnownNat+ n => BitVector n -> Bit'+ template: ~IF~SIZE[~TYP[1]]~THEN& (~ARG[1])~ELSE1'b1~FI+- BlackBox:+ name: Clash.Sized.Internal.BitVector.reduceOr#+ kind: Expression+ type: 'reduceOr# :: KnownNat+ n => BitVector n -> Bit'+ template: ~IF~SIZE[~TYP[1]]~THEN| (~ARG[1])~ELSE1'b0~FI+- BlackBox:+ name: Clash.Sized.Internal.BitVector.reduceXor#+ kind: Expression+ type: 'reduceXor# :: KnownNat+ n => BitVector n -> Bit'+ template: ~IF~SIZE[~TYP[1]]~THEN^ (~ARG[1])~ELSE1'b0~FI+- BlackBox:+ name: Clash.Sized.Internal.BitVector.eq##+ kind: Expression+ type: 'eq## :: Bit ->+ Bit -> Bool'+ template: ~ARG[0] == ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.neq##+ kind: Expression+ type: 'neq## :: Bit ->+ Bit -> Bool'+ template: ~ARG[0] != ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.fromInteger##+ kind: Expression+ type: 'fromInteger## ::+ Integer -> Integer -> Bit'+ template: '~VAR[i][0][0] ? 1''bx : ~VAR[i][1][0]'+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.toEnum##+ kind: Expression+ type: 'toEnum## :: Int+ -> Bit'+ template: '~VAR[i][0][0] ? 1''b1 : 1''b0'+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.and##+ kind: Expression+ type: 'and## :: Bit ->+ Bit -> Bit'+ template: ~ARG[0] & ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.or##+ kind: Expression+ type: 'or## :: Bit ->+ Bit -> Bit'+ template: ~ARG[0] | ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.xor##+ kind: Expression+ type: 'xor## :: Bit ->+ Bit -> Bit'+ template: ~ARG[0] ^ ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.complement##+ kind: Expression+ type: 'complement## ::+ Bit -> Bit'+ template: ~ ~ARG[0]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.eq#+ kind: Expression+ type: 'eq# :: KnownNat+ n => BitVector n -> BitVector n -> Bool'+ template: ~IF~SIZE[~TYP[1]]~THEN~ARG[1] == ~ARG[2]~ELSE1'b1~FI+- BlackBox:+ name: Clash.Sized.Internal.BitVector.neq#+ kind: Expression+ type: 'neq# :: KnownNat+ n => BitVector n -> BitVector n -> Bool'+ template: ~IF~SIZE[~TYP[1]]~THEN~ARG[1] != ~ARG[2]~ELSE1'b0~FI+- BlackBox:+ name: Clash.Sized.Internal.BitVector.lt#+ kind: Expression+ type: 'lt# :: KnownNat+ n => BitVector n -> BitVector n -> Bool'+ template: ~IF~SIZE[~TYP[1]]~THEN~ARG[1] < ~ARG[2]~ELSE1'b0~FI+- BlackBox:+ name: Clash.Sized.Internal.BitVector.ge#+ kind: Expression+ type: 'ge# :: KnownNat+ n => BitVector n -> BitVector n -> Bool'+ template: ~IF~SIZE[~TYP[1]]~THEN~ARG[1] >= ~ARG[2]~ELSE1'b1~FI+- BlackBox:+ name: Clash.Sized.Internal.BitVector.gt#+ kind: Expression+ type: 'gt# :: KnownNat+ n => BitVector n -> BitVector n -> Bool'+ template: ~IF~SIZE[~TYP[1]]~THEN~ARG[1] > ~ARG[2]~ELSE1'b0~FI+- BlackBox:+ name: Clash.Sized.Internal.BitVector.le#+ kind: Expression+ type: 'le# :: KnownNat+ n => BitVector n -> BitVector n -> Bool'+ template: ~IF~SIZE[~TYP[1]]~THEN~ARG[1] <= ~ARG[2]~ELSE1'b1~FI+- BlackBoxHaskell:+ name: Clash.Sized.Internal.BitVector.toInteger#+ templateFunction: Clash.Primitives.Sized.ToInteger.bvToIntegerVerilog+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.fromEnum#+ kind: Expression+ type: 'fromEnum# :: KnownNat+ n => BitVector n -> Int'+ template: ~IF~SIZE[~TYP[1]]~THEN~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[1]]]~THEN$unsigned(~VAR[bv][1][0+:~SIZE[~TYPO]])~ELSE$unsigned({{(~SIZE[~TYPO]-~SIZE[~TYP[1]])+ {1'b0}},~VAR[bv][1]})~FI~ELSE~SIZE[~TYPO]'sd0~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.size#+ kind: Expression+ type: 'size# :: KnownNat+ n => BitVector n -> Int'+ template: ~SIZE[~TYPO]'sd~SIZE[~TYP[1]]+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Internal.BitVector.maxIndex#+ kind: Expression+ type: 'maxIndex# :: KnownNat+ n => BitVector n -> Int'+ template: ~SIZE[~TYPO]'sd~SIZE[~TYP[1]] - ~SIZE[~TYPO]'sd1+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Internal.BitVector.++#+ kind: Expression+ type: '(++#) :: KnownNat+ m => BitVector n -> BitVector m -> BitVector (n + m)'+ template: ~IF~AND[~SIZE[~TYP[1]],~SIZE[~TYP[2]]]~THEN{~ARG[1],~ARG[2]}~ELSE~IF~SIZE[~TYP[1]]~THEN~ARG[1]~ELSE~ARG[2]~FI~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.index#+ kind: Expression+ type: |-+ index# :: KnownNat n -- ARG[0]+ => BitVector n -- ARG[1]+ -> Int -- ARG[2]+ -> Bit+ template: ~VAR[bv][1][~ARG[2]]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.slice#+ kind: Expression+ type: |-+ slice# :: BitVector (m + 1 + i) -- ARG[0]+ -> SNat m -- ARG[1]+ -> SNat n -- ARG[2]+ -> BitVector (m + 1 - n)+ template: '~VAR[bv][0][~LIT[1] : ~LIT[2]]'+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.msb#+ kind: Expression+ type: |-+ msb# :: KnownNat n -- ARG[0]+ => BitVector n -- ARG[1]+ -> Bit+ template: ~IF ~SIZE[~TYP[1]] ~THEN ~VAR[bv][1][~SIZE[~TYP[1]]-1] ~ELSE 1'b0 ~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.lsb#+ kind: Expression+ type: |-+ lsb# :: BitVector n -- ARG[0]+ -> Bit+ template: ~IF ~SIZE[~TYP[0]] ~THEN ~VAR[bv][0][0] ~ELSE 1'b0 ~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.minBound#+ kind: Expression+ type: 'minBound# :: BitVector+ n'+ template: ~SIZE[~TYPO]'d0+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Internal.BitVector.maxBound#+ kind: Expression+ type: 'maxBound# :: KnownNat+ n => BitVector n'+ template: '{~SIZE[~TYPO] {1''b1}}'+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Internal.BitVector.+#+ kind: Expression+ type: '(+#) :: KnownNat+ n => BitVector n -> BitVector n -> BitVector n'+ template: ~ARG[1] + ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.-#+ kind: Expression+ type: '(-#) :: KnownNat+ n => BitVector n -> BitVector n -> BitVector n'+ template: ~ARG[1] - ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.*#+ kind: Expression+ type: '(*#) :: KnownNat+ n => BitVector n -> BitVector n -> BitVector n'+ template: ~ARG[1] * ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.negate#+ kind: Expression+ type: 'negate# :: KnownNat+ n => BitVector n -> BitVector n'+ template: -~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.fromInteger#+ kind: Expression+ type: 'fromInteger# ::+ KnownNat n => Integer -> Integer -> BitVector n'+ template: ~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[2]]]~THEN$unsigned(~VAR[i][2][0+:~SIZE[~TYPO]])~ELSE$unsigned({{(~SIZE[~TYPO]-~SIZE[~TYP[2]])+ {1'b0}},~VAR[i][2]})~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.toEnum#+ kind: Expression+ type: 'toEnum# :: KnownNat+ n => Int -> BitVector n'+ template: ~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[1]]]~THEN$unsigned(~VAR[i][1][0+:~SIZE[~TYPO]])~ELSE$unsigned({{(~SIZE[~TYPO]-~SIZE[~TYP[1]])+ {1'b0}},~VAR[i][1]})~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.plus#+ kind: Declaration+ type: 'plus# :: (KnownNat+ m, KnownNat n) => BitVector m -> BitVector n -> BitVector (Max m n + 1)'+ template: assign ~RESULT = ~IF~AND[~SIZE[~TYP[2]],~SIZE[~TYP[3]]]~THEN~ARG[2]+ + ~ARG[3]~ELSE~IF~SIZE[~TYP[2]]~THEN~ARG[2]~ELSE~ARG[3]~FI~FI;+- BlackBox:+ name: Clash.Sized.Internal.BitVector.minus#+ kind: Declaration+ type: 'minus# :: (KnownNat+ m, KnownNat n) => BitVector m -> BitVector n -> BitVector (Max m n + 1)'+ template: assign ~RESULT = ~IF~AND[~SIZE[~TYP[2]],~SIZE[~TYP[3]]]~THEN~ARG[2]+ - ~ARG[3]~ELSE~IF~SIZE[~TYP[2]]~THEN~ARG[2]~ELSE-~ARG[3]~FI~FI;+- BlackBox:+ name: Clash.Sized.Internal.BitVector.times#+ kind: Declaration+ type: 'times# :: (KnownNat+ m, KnownNat n) => BitVector m -> BitVector n -> BitVector (m + n)'+ template: assign ~RESULT = ~IF~AND[~SIZE[~TYP[2]],~SIZE[~TYP[3]]]~THEN~ARG[2]+ * ~ARG[3]~ELSE~SIZE[~TYPO]'d0~FI;+- BlackBox:+ name: Clash.Sized.Internal.BitVector.quot#+ kind: Expression+ type: 'quot# :: KnownNat+ n => BitVector n -> BitVector n -> BitVector n'+ template: ~ARG[1] / ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.rem#+ kind: Expression+ type: 'rem# :: KnownNat+ n => BitVector n -> BitVector n -> BitVector n'+ template: ~ARG[1] % ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.and#+ kind: Expression+ type: 'and# :: KnownNat+ n => BitVector n -> BitVector n -> BitVector n'+ template: ~ARG[1] & ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.or#+ kind: Expression+ type: 'or# :: KnownNat+ n => BitVector n -> BitVector n -> BitVector n'+ template: ~ARG[1] | ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.xor#+ kind: Expression+ type: 'xor# :: KnownNat+ => BitVector n -> BitVector n -> BitVector n'+ template: ~ARG[1] ^ ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.complement#+ kind: Expression+ type: 'complement# ::+ KnownNat n => BitVector n -> BitVector n'+ template: ~ ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.shiftL#+ kind: Expression+ type: 'shiftL# :: KnownNat+ n => BitVector n -> Int -> BitVector n'+ template: ~ARG[1] << ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.shiftR#+ kind: Expression+ type: 'shiftR# :: KnownNat+ n => BitVector n -> Int -> BitVector n'+ template: ~ARG[1] >> ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.truncateB#+ kind: Expression+ type: 'truncateB# :: forall+ a b . KnownNat a => BitVector (a + b) -> BitVector a'+ template: ~VAR[bv][1][0+:~SIZE[~TYPO]]+ workInfo: Never
− prims/commonverilog/Clash_Sized_Internal_Index.primitives
@@ -1,138 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.pack#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "pack# :: Index n -> BitVector (CLog 2 n)"- , "template" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.unpack#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "unpack# :: (KnownNat n, 1 <= n) => BitVector (CLog 2 n) -> Index n"- , "template" : "~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.eq#"- , "kind" : "Expression"- , "type" : "eq# :: Index n -> Index n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] == ~ARG[1]~ELSE1'b1~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.neq#"- , "kind" : "Expression"- , "type" : "neq# :: Index n -> Index n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] != ~ARG[1]~ELSE1'b0~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.lt#"- , "kind" : "Expression"- , "type" : "lt# :: Index n -> Index n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] < ~ARG[1]~ELSE1'b0~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.ge#"- , "kind" : "Expression"- , "type" : "ge# :: Index n -> Index n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] >= ~ARG[1]~ELSE1'b1~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.gt#"- , "kind" : "Expression"- , "type" : "gt# :: Index n -> Index n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] > ~ARG[1]~ELSE1'b0~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.le#"- , "kind" : "Expression"- , "type" : "le# :: Index n -> Index n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] <= ~ARG[1]~ELSE1'b1~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.maxBound#"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "maxBound# :: KnownNat n => Index n"- , "template" : "~ARG[0]-~SIZE[~TYPO]'d1"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.+#"- , "kind" : "Expression"- , "type" : "(+#) :: KnownNat n => Index n -> Index n -> Index n"- , "template" : "~ARG[1] + ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.-#"- , "kind" : "Expression"- , "type" : "(-#) :: KnownNat n => Index n -> Index n -> Index n"- , "template" : "~ARG[1] - ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.*#"- , "kind" : "Expression"- , "type" : "(*#) :: KnownNat n => Index n -> Index n -> Index n"- , "template" : "~ARG[1] * ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.fromInteger#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "fromInteger# :: KnownNat n => Integer -> Index n"- , "template" : "~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[1]]]~THEN$unsigned(~VAR[i][1][0+:~SIZE[~TYPO]])~ELSE$unsigned({{(~SIZE[~TYPO]-~SIZE[~TYP[1]]) {1'b0}},~VAR[i][1]})~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.plus#"- , "kind" : "Declaration"- , "type" : "Index m -> Index n -> Index (m + n - 1)"- , "template" : "assign ~RESULT = ~ARG[0] + ~ARG[1];"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.minus#"- , "kind" : "Declaration"- , "type" : "Index m -> Index n -> Index (m + n - 1)"- , "template" : "assign ~RESULT = ~ARG[0] - ~ARG[1];"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.times#"- , "kind" : "Declaration"- , "type" : "Index m -> Index n -> Index (((m-1) * (n-1)) + 1)"- , "template" : "assign ~RESULT = ~ARG[0] * ~ARG[1];"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.rem#"- , "kind" : "Expression"- , "type" : "rem# :: Index n -> Index n -> Index n"- , "template" : "~ARG[0] % ~ARG[1]"- }- }-, { "BlackBoxHaskell" :- { "name" : "Clash.Sized.Internal.Index.toInteger#"- , "workInfo" : "Never"- , "templateFunction" : "Clash.Primitives.Sized.ToInteger.indexToIntegerVerilog"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.resize#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "resize# :: KnownNat m => Index n -> Index m"- , "template" : "~IF~SIZE[~TYP[1]]~THEN~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[1]]]~THEN~VAR[bv][1][0+:~SIZE[~TYPO]]~ELSE{{(~SIZE[~TYPO]-~SIZE[~TYP[1]]) {1'b0}},~ARG[1]}~FI~ELSE~SIZE[~TYPO]'d0~FI"- }- }-]
+ prims/commonverilog/Clash_Sized_Internal_Index.primitives.yaml view
@@ -0,0 +1,141 @@+- BlackBox:+ name: Clash.Sized.Internal.Index.pack#+ kind: Expression+ type: 'pack# :: Index+ n -> BitVector (CLog 2 n)'+ template: ~ARG[0]+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Index.unpack#+ kind: Expression+ type: 'unpack# :: (KnownNat+ n, 1 <= n) => BitVector (CLog 2 n) -> Index n'+ template: ~ARG[2]+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Index.eq#+ kind: Expression+ type: 'eq# :: Index n+ -> Index n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] == ~ARG[1]~ELSE1'b1~FI+- BlackBox:+ name: Clash.Sized.Internal.Index.neq#+ kind: Expression+ type: 'neq# :: Index n+ -> Index n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] != ~ARG[1]~ELSE1'b0~FI+- BlackBox:+ name: Clash.Sized.Internal.Index.lt#+ kind: Expression+ type: 'lt# :: Index n+ -> Index n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] < ~ARG[1]~ELSE1'b0~FI+- BlackBox:+ name: Clash.Sized.Internal.Index.ge#+ kind: Expression+ type: 'ge# :: Index n+ -> Index n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] >= ~ARG[1]~ELSE1'b1~FI+- BlackBox:+ name: Clash.Sized.Internal.Index.gt#+ kind: Expression+ type: 'gt# :: Index n+ -> Index n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] > ~ARG[1]~ELSE1'b0~FI+- BlackBox:+ name: Clash.Sized.Internal.Index.le#+ kind: Expression+ type: 'le# :: Index n+ -> Index n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] <= ~ARG[1]~ELSE1'b1~FI+- BlackBox:+ name: Clash.Sized.Internal.Index.maxBound#+ kind: Expression+ type: 'maxBound# :: KnownNat+ n => Index n'+ template: ~ARG[0]-~SIZE[~TYPO]'d1+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Internal.Index.fromEnum#+ kind: Expression+ type: 'fromEnum# :: KnownNat+ n => Index n -> Int'+ template: ~IF~SIZE[~TYP[1]]~THEN~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[1]]]~THEN$unsigned(~VAR[i][1][0+:~SIZE[~TYPO]])~ELSE$unsigned({{(~SIZE[~TYPO]-~SIZE[~TYP[1]])+ {1'b0}},~VAR[i][1]})~FI~ELSE~SIZE[~TYPO]'sd0~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Index.toEnum#+ kind: Expression+ type: 'toEnum# :: KnownNat+ n => Int -> Index n'+ template: ~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[1]]]~THEN$unsigned(~VAR[i][1][0+:~SIZE[~TYPO]])~ELSE$unsigned({{(~SIZE[~TYPO]-~SIZE[~TYP[1]])+ {1'b0}},~VAR[i][1]})~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Index.+#+ kind: Expression+ type: '(+#) :: KnownNat+ n => Index n -> Index n -> Index n'+ template: ~ARG[1] + ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.Index.-#+ kind: Expression+ type: '(-#) :: KnownNat+ n => Index n -> Index n -> Index n'+ template: ~ARG[1] - ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.Index.*#+ kind: Expression+ type: '(*#) :: KnownNat+ n => Index n -> Index n -> Index n'+ template: ~ARG[1] * ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.Index.fromInteger#+ kind: Expression+ type: 'fromInteger# ::+ KnownNat n => Integer -> Index n'+ template: ~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[1]]]~THEN$unsigned(~VAR[i][1][0+:~SIZE[~TYPO]])~ELSE$unsigned({{(~SIZE[~TYPO]-~SIZE[~TYP[1]])+ {1'b0}},~VAR[i][1]})~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Index.plus#+ kind: Declaration+ type: Index m -> Index+ n -> Index (m + n - 1)+ template: assign ~RESULT = ~ARG[0] + ~ARG[1];+- BlackBox:+ name: Clash.Sized.Internal.Index.minus#+ kind: Declaration+ type: Index m -> Index+ n -> Index (m + n - 1)+ template: assign ~RESULT = ~ARG[0] - ~ARG[1];+- BlackBox:+ name: Clash.Sized.Internal.Index.times#+ kind: Declaration+ type: Index m -> Index+ n -> Index (((m-1) * (n-1)) + 1)+ template: assign ~RESULT = ~ARG[0] * ~ARG[1];+- BlackBox:+ name: Clash.Sized.Internal.Index.rem#+ kind: Expression+ type: 'rem# :: Index n+ -> Index n -> Index n'+ template: ~ARG[0] % ~ARG[1]+- BlackBoxHaskell:+ name: Clash.Sized.Internal.Index.toInteger#+ templateFunction: Clash.Primitives.Sized.ToInteger.indexToIntegerVerilog+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Index.resize#+ kind: Expression+ type: 'resize# :: KnownNat+ m => Index n -> Index m'+ template: ~IF~SIZE[~TYP[1]]~THEN~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[1]]]~THEN~VAR[bv][1][0+:~SIZE[~TYPO]]~ELSE{{(~SIZE[~TYPO]-~SIZE[~TYP[1]])+ {1'b0}},~ARG[1]}~FI~ELSE~SIZE[~TYPO]'d0~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Index.quot#+ kind: Expression+ type: 'quot# :: Index+ n -> Index n -> Index n'+ template: ~ARG[0] / ~ARG[1]
− prims/commonverilog/Clash_Sized_Internal_Signed.primitives
@@ -1,206 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.eq#"- , "kind" : "Expression"- , "type" : "eq# :: Signed n -> Signed n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] == ~ARG[1]~ELSE1'b1~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.neq#"- , "kind" : "Expression"- , "type" : "neq# :: Signed n -> Signed n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] != ~ARG[1]~ELSE1'b0~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.lt#"- , "kind" : "Expression"- , "type" : "lt# :: Signed n -> Signed n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] < ~ARG[1]~ELSE1'b0~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.ge#"- , "kind" : "Expression"- , "type" : "ge# :: Signed n -> Signed n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] >= ~ARG[1]~ELSE1'b1~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.gt#"- , "kind" : "Expression"- , "type" : "gt# :: Signed n -> Signed n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] > ~ARG[1]~ELSE1'b0~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.le#"- , "kind" : "Expression"- , "type" : "le# :: Signed n -> Signed n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] <= ~ARG[1]~ELSE1'b1~FI"- }- }-, { "BlackBoxHaskell" :- { "name" : "Clash.Sized.Internal.Signed.toInteger#"- , "workInfo" : "Never"- , "templateFunction" : "Clash.Primitives.Sized.ToInteger.signedToIntegerVerilog"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.size#"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "size# :: KnownNat n => Signed n -> Int"- , "template" : "~SIZE[~TYPO]'sd~LIT[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.pack#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "pack# :: KnownNat n => Signed n -> BitVector n"- , "template" : "$unsigned(~ARG[1])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.unpack#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "unpack# :: KnownNat n => BitVector n -> Signed n"- , "template" : "$signed(~ARG[1])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.minBound#"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "minBound# :: KnownNat n => Signed n"- , "comment" : "Generates incorrect SV for n=0"- , "template" : "$signed({1'b1, {(~LIT[0]-1) {1'b0}}})"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.maxBound#"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "maxBound# :: KnownNat n => Signed n"- , "comment" : "Generates incorrect SV for n=0"- , "template" : "$signed({1'b0, {(~LIT[0]-1) {1'b1}}})"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.*#"- , "kind" : "Expression"- , "type" : "(*#) :: KnownNat n => Signed n -> Signed n -> Signed n"- , "template" : "~ARG[1] * ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.negate#"- , "kind" : "Expression"- , "type" : "negate# :: KnownNat n => Signed n -> Signed n"- , "template" : "-~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.abs#"- , "kind" : "Expression"- , "type" : "abs# :: KnownNat n => Signed n -> Signed n"- , "template" : "(~ARG[1] < ~LIT[0]'sd0) ? -~ARG[1] : ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.fromInteger#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "fromInteger# :: KnownNat n => Integer -> Signed (n :: Nat)"- , "template" : "~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[1]]]~THEN$signed(~VAR[i][1][0+:~SIZE[~TYPO]])~ELSE$signed({{(~SIZE[~TYPO]-~SIZE[~TYP[1]]) {1'b0}},~VAR[i][1]})~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.plus#"- , "kind" : "Declaration"- , "type" : "plus# :: Signed m -> Signed n -> Signed (1 + Max m n)"- , "template" : "assign ~RESULT = ~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THEN~ARG[0] + ~ARG[1]~ELSE~IF~SIZE[~TYP[0]]~THEN~ARG[0]~ELSE~ARG[1]~FI~FI;"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.minus#"- , "kind" : "Declaration"- , "type" : "minus# :: Signed m -> Signed n -> Signed (1 + Max m n)"- , "template" : "assign ~RESULT = ~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THEN ~ARG[0] - ~ARG[1]~ELSE~IF~SIZE[~TYP[0]]~THEN ~ARG[0]~ELSE - ~ARG[1] ~FI~FI;"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.times#"- , "kind" : "Declaration"- , "type" : "times# :: Signed m -> Signed n -> Signed (m + n)"- , "template" : "assign ~RESULT = ~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THEN~ARG[0] * ~ARG[1]~ELSE~SIZE[~TYPO]'d0~FI;"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.rem#"- , "kind" : "Expression"- , "type" : "rem# :: Signed n -> Signed n -> Signed n"- , "template" : "~ARG[0] % ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.and#"- , "kind" : "Expression"- , "type" : "and# :: KnownNat n => Signed n -> Signed n -> Signed n"- , "template" : "~ARG[1] & ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.or#"- , "kind" : "Expression"- , "type" : "or# :: KnownNat n => Signed n -> Signed n -> Signed n"- , "template" : "~ARG[1] | ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.xor#"- , "kind" : "Expression"- , "type" : "xor# :: KnownNat n => Signed n -> Signed n -> Signed n"- , "template" : "~ARG[1] ^ ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.complement#"- , "kind" : "Expression"- , "type" : "complement# :: KnownNat n => Signed n -> Signed n"- , "template" : "~ ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.shiftL#"- , "kind" : "Expression"- , "type" : "shiftL# :: KnownNat n => Signed n -> Int -> Signed n"- , "template" : "~ARG[1] <<< ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.shiftR#"- , "kind" : "Expression"- , "type" : "shiftR# :: KnownNat n => Signed n -> Int -> Signed n"- , "template" : "~ARG[1] >>> ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.truncateB#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "truncateB# :: KnownNat m => Signed (n + m) -> Signed m"- , "template" : "$signed(~VAR[s][1][0+:~SIZE[~TYPO]])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.resize#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "resize# :: (KnownNat n, KnownNat m) => Signed n -> Signed m"- , "template" : "~IF~SIZE[~TYP[2]]~THEN~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[2]]]~THEN$signed({~VAR[s][2][~LIT[0]-1],~VAR[s][2][0+:(~SIZE[~TYPO]-1)]})~ELSE$signed({{(~SIZE[~TYPO]-~SIZE[~TYP[2]]) {~VAR[s][2][~LIT[0]-1]}},~VAR[s][2]})~FI~ELSE~SIZE[~TYPO]'sd0~FI"- }- }-]
+ prims/commonverilog/Clash_Sized_Internal_Signed.primitives.yaml view
@@ -0,0 +1,203 @@+- BlackBox:+ name: Clash.Sized.Internal.Signed.eq#+ kind: Expression+ type: 'eq# :: Signed n+ -> Signed n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] == ~ARG[1]~ELSE1'b1~FI+- BlackBox:+ name: Clash.Sized.Internal.Signed.neq#+ kind: Expression+ type: 'neq# :: Signed+ n -> Signed n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] != ~ARG[1]~ELSE1'b0~FI+- BlackBox:+ name: Clash.Sized.Internal.Signed.lt#+ kind: Expression+ type: 'lt# :: Signed n+ -> Signed n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] < ~ARG[1]~ELSE1'b0~FI+- BlackBox:+ name: Clash.Sized.Internal.Signed.ge#+ kind: Expression+ type: 'ge# :: Signed n+ -> Signed n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] >= ~ARG[1]~ELSE1'b1~FI+- BlackBox:+ name: Clash.Sized.Internal.Signed.gt#+ kind: Expression+ type: 'gt# :: Signed n+ -> Signed n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] > ~ARG[1]~ELSE1'b0~FI+- BlackBox:+ name: Clash.Sized.Internal.Signed.le#+ kind: Expression+ type: 'le# :: Signed n+ -> Signed n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] <= ~ARG[1]~ELSE1'b1~FI+- BlackBoxHaskell:+ name: Clash.Sized.Internal.Signed.toInteger#+ templateFunction: Clash.Primitives.Sized.ToInteger.signedToIntegerVerilog+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Signed.fromEnum#+ kind: Expression+ type: 'fromEnum# :: KnownNat+ n => Signed n -> Int'+ template: ~IF~SIZE[~TYP[1]]~THEN~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[1]]]~THEN$signed(~VAR[i][1][0+:~SIZE[~TYPO]])~ELSE$signed({{(~SIZE[~TYPO]-~SIZE[~TYP[1]])+ {1'b0}},~VAR[i][1]})~FI~ELSE~SIZE[~TYPO]'sd0~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Signed.size#+ kind: Expression+ type: 'size# :: KnownNat+ n => Signed n -> Int'+ template: ~SIZE[~TYPO]'sd~LIT[0]+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Internal.Signed.pack#+ kind: Expression+ type: 'pack# :: KnownNat+ n => Signed n -> BitVector n'+ template: $unsigned(~ARG[1])+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Signed.unpack#+ kind: Expression+ type: 'unpack# :: KnownNat+ n => BitVector n -> Signed n'+ template: $signed(~ARG[1])+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Signed.minBound#+ comment: Generates incorrect SV for n=0+ kind: Expression+ type: 'minBound# :: KnownNat+ n => Signed n'+ template: $signed({1'b1, {(~LIT[0]-1) {1'b0}}})+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Internal.Signed.maxBound#+ comment: Generates incorrect SV for n=0+ kind: Expression+ type: 'maxBound# :: KnownNat+ n => Signed n'+ template: $signed({1'b0, {(~LIT[0]-1) {1'b1}}})+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Internal.Signed.*#+ kind: Expression+ type: '(*#) :: KnownNat+ n => Signed n -> Signed n -> Signed n'+ template: ~ARG[1] * ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.Signed.negate#+ kind: Expression+ type: 'negate# :: KnownNat+ n => Signed n -> Signed n'+ template: -~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.Signed.abs#+ kind: Expression+ type: 'abs# :: KnownNat+ n => Signed n -> Signed n'+ template: '(~ARG[1] < ~LIT[0]''sd0) ? -~ARG[1] : ~ARG[1]'+- BlackBox:+ name: Clash.Sized.Internal.Signed.fromInteger#+ kind: Expression+ type: 'fromInteger# ::+ KnownNat n => Integer -> Signed (n :: Nat)'+ template: ~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[1]]]~THEN$signed(~VAR[i][1][0+:~SIZE[~TYPO]])~ELSE$signed({{(~SIZE[~TYPO]-~SIZE[~TYP[1]])+ {1'b0}},~VAR[i][1]})~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Signed.toEnum#+ kind: Expression+ type: 'toEnum# :: KnownNat+ n => Int -> Signed n'+ template: ~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[1]]]~THEN$signed(~VAR[i][1][0+:~SIZE[~TYPO]])~ELSE$signed({{(~SIZE[~TYPO]-~SIZE[~TYP[1]])+ {1'b0}},~VAR[i][1]})~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Signed.plus#+ kind: Declaration+ type: 'plus# :: Signed+ m -> Signed n -> Signed (1 + Max m n)'+ template: assign ~RESULT = ~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THEN~ARG[0]+ + ~ARG[1]~ELSE~IF~SIZE[~TYP[0]]~THEN~ARG[0]~ELSE~ARG[1]~FI~FI;+- BlackBox:+ name: Clash.Sized.Internal.Signed.minus#+ kind: Declaration+ type: 'minus# :: Signed+ m -> Signed n -> Signed (1 + Max m n)'+ template: assign ~RESULT = ~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THEN ~ARG[0]+ - ~ARG[1]~ELSE~IF~SIZE[~TYP[0]]~THEN ~ARG[0]~ELSE - ~ARG[1] ~FI~FI;+- BlackBox:+ name: Clash.Sized.Internal.Signed.times#+ kind: Declaration+ type: 'times# :: Signed+ m -> Signed n -> Signed (m + n)'+ template: assign ~RESULT = ~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THEN~ARG[0]+ * ~ARG[1]~ELSE~SIZE[~TYPO]'d0~FI;+- BlackBox:+ name: Clash.Sized.Internal.Signed.rem#+ kind: Expression+ type: 'rem# :: Signed+ n -> Signed n -> Signed n'+ template: ~ARG[0] % ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.Signed.and#+ kind: Expression+ type: 'and# :: KnownNat+ n => Signed n -> Signed n -> Signed n'+ template: ~ARG[1] & ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.Signed.or#+ kind: Expression+ type: 'or# :: KnownNat+ n => Signed n -> Signed n -> Signed n'+ template: ~ARG[1] | ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.Signed.xor#+ kind: Expression+ type: 'xor# :: KnownNat+ n => Signed n -> Signed n -> Signed n'+ template: ~ARG[1] ^ ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.Signed.complement#+ kind: Expression+ type: 'complement# ::+ KnownNat n => Signed n -> Signed n'+ template: ~ ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.Signed.shiftL#+ kind: Expression+ type: 'shiftL# :: KnownNat+ n => Signed n -> Int -> Signed n'+ template: ~ARG[1] <<< ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.Signed.shiftR#+ kind: Expression+ type: 'shiftR# :: KnownNat+ n => Signed n -> Int -> Signed n'+ template: ~ARG[1] >>> ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.Signed.truncateB#+ kind: Expression+ type: 'truncateB# :: KnownNat+ m => Signed (n + m) -> Signed m'+ template: $signed(~VAR[s][1][0+:~SIZE[~TYPO]])+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Signed.resize#+ kind: Expression+ type: 'resize# :: (KnownNat+ n, KnownNat m) => Signed n -> Signed m'+ template: ~IF~SIZE[~TYP[2]]~THEN~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[2]]]~THEN$signed({~VAR[s][2][~LIT[0]-1],~VAR[s][2][0+:(~SIZE[~TYPO]-1)]})~ELSE$signed({{(~SIZE[~TYPO]-~SIZE[~TYP[2]])+ {~VAR[s][2][~LIT[0]-1]}},~VAR[s][2]})~FI~ELSE~SIZE[~TYPO]'sd0~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Signed.quot#+ kind: Expression+ type: 'quot# :: KnownNat+ n => Signed n -> Signed n -> Signed n'+ template: ~ARG[1] / ~ARG[2]
− prims/commonverilog/Clash_Sized_Internal_Unsigned.primitives
@@ -1,189 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.eq#"- , "kind" : "Expression"- , "type" : "eq# :: Unsigned n -> Unsigned n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] == ~ARG[1]~ELSE1'b1~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.neq#"- , "kind" : "Expression"- , "type" : "neq# :: Unsigned n -> Unsigned n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] != ~ARG[1]~ELSE1'b0~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.lt#"- , "kind" : "Expression"- , "type" : "lt# :: Unsigned n -> Unsigned n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] < ~ARG[1]~ELSE1'b0~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.ge#"- , "kind" : "Expression"- , "type" : "ge# :: Unsigned n -> Unsigned n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] >= ~ARG[1]~ELSE1'b1~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.gt#"- , "kind" : "Expression"- , "type" : "gt# :: Unsigned n -> Unsigned n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] > ~ARG[1]~ELSE1'b0~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.le#"- , "kind" : "Expression"- , "type" : "le# :: Unsigned n -> Unsigned n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] <= ~ARG[1]~ELSE1'b1~FI"- }- }-, { "BlackBoxHaskell" :- { "name" : "Clash.Sized.Internal.Unsigned.toInteger#"- , "workInfo" : "Never"- , "templateFunction" : "Clash.Primitives.Sized.ToInteger.unsignedToIntegerVerilog"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.size#"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "size# :: KnownNat n => Unsigned n -> Int"- , "template" : "~SIZE[~TYPO]'sd~LIT[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.pack#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "pack# :: Unsigned n -> BitVector n"- , "template" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.unpack#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "unpack# :: KnownNat n => BitVector n -> Unsigned n"- , "template" : "~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.minBound#"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "minBound# :: Unsigned n"- , "template" : "~SIZE[~TYPO]'d0"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.maxBound#"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "maxBound# :: KnownNat n => Unsigned n"- , "template" : "{~LIT[0] {1'b1}}"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.*#"- , "kind" : "Expression"- , "type" : "(*#) :: KnownNat n => Unsigned n -> Unsigned n -> Unsigned n"- , "template" : "~ARG[1] * ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.negate#"- , "kind" : "Expression"- , "type" : "negate# :: KnownNat n => Unsigned n -> Unsigned n"- , "template" : "- ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.fromInteger#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "fromInteger# :: KnownNat n => Integer -> Unsigned n"- , "template" : "~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[1]]]~THEN$unsigned(~VAR[i][1][0+:~SIZE[~TYPO]])~ELSE$unsigned({{(~SIZE[~TYPO]-~SIZE[~TYP[1]]) {1'b0}},~VAR[i][1]})~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.plus#"- , "kind" : "Declaration"- , "type" : "plus# :: Unsigned m -> Unsigned n -> Unsigned (1 + Max m n)"- , "template" : "assign ~RESULT = ~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THEN~ARG[0] + ~ARG[1]~ELSE~IF~SIZE[~TYP[0]]~THEN~ARG[0]~ELSE~ARG[1]~FI~FI;"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.minus#"- , "kind" : "Declaration"- , "type" : "minus# :: (KnownNat m, KnownNat n) => Unsigned m -> Unsigned n -> Unsigned (1 + Max m n)"- , "template" : "assign ~RESULT = ~IF~AND[~SIZE[~TYP[2]],~SIZE[~TYP[3]]]~THEN ~ARG[2] - ~ARG[3]~ELSE~IF~SIZE[~TYP[2]]~THEN ~ARG[2]~ELSE - ~ARG[3]~FI~FI;"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.times#"- , "kind" : "Declaration"- , "type" : "times# :: Unsigned m -> Unsigned n -> Unsigned (m + n)"- , "template" : "assign ~RESULT = ~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THEN~ARG[0] * ~ARG[1]~ELSE~SIZE[~TYPO]'d0~FI;"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.rem#"- , "kind" : "Expression"- , "type" : "rem# :: Unsigned n -> Unsigned n -> Unsigned n"- , "template" : "~ARG[0] % ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.and#"- , "kind" : "Expression"- , "type" : "and# :: Unsigned n -> Unsigned n -> Unsigned n"- , "template" : "~ARG[0] & ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.or#"- , "kind" : "Expression"- , "type" : "or# :: Unsigned n -> Unsigned n -> Unsigned n"- , "template" : "~ARG[0] | ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.xor#"- , "kind" : "Expression"- , "type" : "xor# :: Unsigned n -> Unsigned n -> Unsigned n"- , "template" : "~ARG[0] ^ ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.complement#"- , "kind" : "Expression"- , "type" : "complement# :: KnownNat n => Unsigned n -> Unsigned n"- , "template" : "~ ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.shiftL#"- , "kind" : "Expression"- , "type" : "shiftL# :: KnownNat n => Unsigned n -> Int -> Unsigned n"- , "template" : "~ARG[1] << ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.shiftR#"- , "kind" : "Expression"- , "type" : "shiftR# :: KnownNat n => Unsigned n -> Int -> Unsigned n"- , "template" : "~ARG[1] >> ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.resize#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "resize# :: KnownNat m => Unsigned n -> Unsigned m"- , "template" : "~IF~SIZE[~TYP[1]]~THEN~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[1]]]~THEN~VAR[bv][1][0+:~SIZE[~TYPO]]~ELSE{{(~SIZE[~TYPO]-~SIZE[~TYP[1]]) {1'b0}},~ARG[1]}~FI~ELSE~SIZE[~TYPO]'d0~FI"- }- }-]
+ prims/commonverilog/Clash_Sized_Internal_Unsigned.primitives.yaml view
@@ -0,0 +1,188 @@+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.eq#+ kind: Expression+ type: 'eq# :: Unsigned+ n -> Unsigned n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] == ~ARG[1]~ELSE1'b1~FI+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.neq#+ kind: Expression+ type: 'neq# :: Unsigned+ n -> Unsigned n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] != ~ARG[1]~ELSE1'b0~FI+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.lt#+ kind: Expression+ type: 'lt# :: Unsigned+ n -> Unsigned n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] < ~ARG[1]~ELSE1'b0~FI+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.ge#+ kind: Expression+ type: 'ge# :: Unsigned+ n -> Unsigned n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] >= ~ARG[1]~ELSE1'b1~FI+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.gt#+ kind: Expression+ type: 'gt# :: Unsigned+ n -> Unsigned n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] > ~ARG[1]~ELSE1'b0~FI+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.le#+ kind: Expression+ type: 'le# :: Unsigned+ n -> Unsigned n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] <= ~ARG[1]~ELSE1'b1~FI+- BlackBoxHaskell:+ name: Clash.Sized.Internal.Unsigned.toInteger#+ templateFunction: Clash.Primitives.Sized.ToInteger.unsignedToIntegerVerilog+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.fromEnum#+ kind: Expression+ type: 'fromEnum# :: KnownNat+ n => Unsigned n -> Int'+ template: ~IF~SIZE[~TYP[1]]~THEN~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[1]]]~THEN$unsigned(~VAR[i][1][0+:~SIZE[~TYPO]])~ELSE$unsigned({{(~SIZE[~TYPO]-~SIZE[~TYP[1]])+ {1'b0}},~VAR[i][1]})~FI~ELSE~SIZE[~TYPO]'sd0~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.size#+ kind: Expression+ type: 'size# :: KnownNat+ n => Unsigned n -> Int'+ template: ~SIZE[~TYPO]'sd~LIT[0]+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.pack#+ kind: Expression+ type: 'pack# :: Unsigned+ n -> BitVector n'+ template: ~ARG[0]+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.unpack#+ kind: Expression+ type: 'unpack# :: KnownNat+ n => BitVector n -> Unsigned n'+ template: ~ARG[1]+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.minBound#+ kind: Expression+ type: 'minBound# :: Unsigned+ n'+ template: ~SIZE[~TYPO]'d0+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.maxBound#+ kind: Expression+ type: 'maxBound# :: KnownNat+ n => Unsigned n'+ template: '{~LIT[0] {1''b1}}'+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.*#+ kind: Expression+ type: '(*#) :: KnownNat+ n => Unsigned n -> Unsigned n -> Unsigned n'+ template: ~ARG[1] * ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.negate#+ kind: Expression+ type: 'negate# :: KnownNat+ n => Unsigned n -> Unsigned n'+ template: '- ~ARG[1]'+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.fromInteger#+ kind: Expression+ type: 'fromInteger# ::+ KnownNat n => Integer -> Unsigned n'+ template: ~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[1]]]~THEN$unsigned(~VAR[i][1][0+:~SIZE[~TYPO]])~ELSE$unsigned({{(~SIZE[~TYPO]-~SIZE[~TYP[1]])+ {1'b0}},~VAR[i][1]})~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.toEnum#+ kind: Expression+ type: 'toEnum# :: KnownNat+ n => Int -> Unsigned n'+ template: ~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[1]]]~THEN$unsigned(~VAR[i][1][0+:~SIZE[~TYPO]])~ELSE$unsigned({{(~SIZE[~TYPO]-~SIZE[~TYP[1]])+ {1'b0}},~VAR[i][1]})~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.plus#+ kind: Declaration+ type: 'plus# :: Unsigned+ m -> Unsigned n -> Unsigned (1 + Max m n)'+ template: assign ~RESULT = ~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THEN~ARG[0]+ + ~ARG[1]~ELSE~IF~SIZE[~TYP[0]]~THEN~ARG[0]~ELSE~ARG[1]~FI~FI;+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.minus#+ kind: Declaration+ type: 'minus# :: (KnownNat+ m, KnownNat n) => Unsigned m -> Unsigned n -> Unsigned (1 + Max m n)'+ template: assign ~RESULT = ~IF~AND[~SIZE[~TYP[2]],~SIZE[~TYP[3]]]~THEN ~ARG[2]+ - ~ARG[3]~ELSE~IF~SIZE[~TYP[2]]~THEN ~ARG[2]~ELSE - ~ARG[3]~FI~FI;+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.times#+ kind: Declaration+ type: 'times# :: Unsigned+ m -> Unsigned n -> Unsigned (m + n)'+ template: assign ~RESULT = ~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THEN~ARG[0]+ * ~ARG[1]~ELSE~SIZE[~TYPO]'d0~FI;+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.rem#+ kind: Expression+ type: 'rem# :: Unsigned+ n -> Unsigned n -> Unsigned n'+ template: ~ARG[0] % ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.and#+ kind: Expression+ type: 'and# :: Unsigned+ n -> Unsigned n -> Unsigned n'+ template: ~ARG[0] & ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.or#+ kind: Expression+ type: 'or# :: Unsigned+ n -> Unsigned n -> Unsigned n'+ template: ~ARG[0] | ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.xor#+ kind: Expression+ type: 'xor# :: Unsigned+ n -> Unsigned n -> Unsigned n'+ template: ~ARG[0] ^ ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.complement#+ kind: Expression+ type: 'complement# ::+ KnownNat n => Unsigned n -> Unsigned n'+ template: ~ ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.shiftL#+ kind: Expression+ type: 'shiftL# :: KnownNat+ n => Unsigned n -> Int -> Unsigned n'+ template: ~ARG[1] << ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.shiftR#+ kind: Expression+ type: 'shiftR# :: KnownNat+ n => Unsigned n -> Int -> Unsigned n'+ template: ~ARG[1] >> ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.resize#+ kind: Expression+ type: 'resize# :: KnownNat+ m => Unsigned n -> Unsigned m'+ template: ~IF~SIZE[~TYP[1]]~THEN~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[1]]]~THEN~VAR[bv][1][0+:~SIZE[~TYPO]]~ELSE{{(~SIZE[~TYPO]-~SIZE[~TYP[1]])+ {1'b0}},~ARG[1]}~FI~ELSE~SIZE[~TYPO]'d0~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.quot#+ kind: Expression+ type: 'quot# :: Unsigned+ n -> Unsigned n -> Unsigned n'+ template: ~ARG[0] / ~ARG[1]
− prims/commonverilog/Clash_Sized_Vector.primitives
@@ -1,17 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Sized.Vector.maxIndex"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "maxIndex :: KnownNat n => Vec n a -> Int"- , "template" : "~SIZE[~TYPO]'sd~LIT[0] - ~SIZE[~TYPO]'sd1"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.length"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "length :: KnownNat n => Vec n a -> Int"- , "template" : "~SIZE[~TYPO]'sd~LIT[0]"- }- }-]
+ prims/commonverilog/Clash_Sized_Vector.primitives.yaml view
@@ -0,0 +1,14 @@+- BlackBox:+ name: Clash.Sized.Vector.maxIndex+ kind: Expression+ type: 'maxIndex :: KnownNat+ n => Vec n a -> Int'+ template: ~SIZE[~TYPO]'sd~LIT[0] - ~SIZE[~TYPO]'sd1+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Vector.length+ kind: Expression+ type: 'length :: KnownNat+ n => Vec n a -> Int'+ template: ~SIZE[~TYPO]'sd~LIT[0]+ workInfo: Constant
− prims/commonverilog/Clash_Transformations.primitives
@@ -1,8 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Transformations.eqInt"- , "kind" : "Expression"- , "type" : "eqInt :: Int -> Int -> Bool"- , "template" : "~ARG[0] == ~ARG[1]"- }- }-]
− prims/commonverilog/Clash_Xilinx_ClockGen.primitives
@@ -1,47 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Xilinx.ClockGen.clockWizard"- , "workInfo" : "Always"- , "kind" : "Declaration"- , "type" :-"clockWizard- :: ( KnownDomain domIn confIn -- ARG[0]- , KnownDomain domOut confOut ) -- ARG[1]- => SSymbol name -- ARG[2]- -> Clock pllIn -- ARG[3]- -> Reset pllIn -- ARG[4]- -> (Clock pllOut, Enable pllOut)"- , "template" :-"// clockWizard begin-~NAME[2] ~GENSYM[clockWizard_inst][2]-(.CLK_IN1 (~ARG[3])-,.RESET (~IF ~ISACTIVEHIGH[0] ~THEN ~ELSE ! ~FI ~ARG[4])-,.CLK_OUT1 (~RESULT[1])-,.LOCKED (~RESULT[0]));-// clockWizard end"- }- }-, { "BlackBox" :- { "name" : "Clash.Xilinx.ClockGen.clockWizardDifferential"- , "workInfo" : "Always"- , "kind" : "Declaration"- , "type" :-"clockWizardDifferential- :: ( KnownDomain domIn confIn -- ARG[0]- , KnownDomain domOut confOut ) -- ARG[1]- :: SSymbol name -- ARG[2]- -> Clock pllIn -- ARG[3]- -> Clock pllIn -- ARG[4]- -> Reset pllIn -- ARG[5]- -> (Clock pllOut, Enable pllOut)"- , "template" :-"// clockWizardDifferential begin-~NAME[2] ~GENSYM[clockWizardDifferential_inst][2]-(.CLK_IN1_D_clk_n (~ARG[3])-,.CLK_IN1_D_clk_n (~ARG[4])-,.RESET (~IF ~ISACTIVEHIGH[0] ~THEN ~ELSE ! ~FI ~ARG[5])-,.CLK_OUT1 (~RESULT[1])-,.LOCKED (~RESULT[0]));-// clockWizardDifferential end"- }- }-]
+ prims/commonverilog/Clash_Xilinx_ClockGen.primitives.yaml view
@@ -0,0 +1,42 @@+- BlackBox:+ name: Clash.Xilinx.ClockGen.clockWizard+ kind: Declaration+ type: |-+ clockWizard+ :: ( KnownDomain domIn confIn -- ARG[0]+ , KnownDomain domOut confOut ) -- ARG[1]+ => SSymbol name -- ARG[2]+ -> Clock pllIn -- ARG[3]+ -> Reset pllIn -- ARG[4]+ -> (Clock pllOut, Enable pllOut)+ template: |-+ // clockWizard begin+ ~NAME[2] ~GENSYM[clockWizard_inst][2]+ (.CLK_IN1 (~ARG[3])+ ,.RESET (~IF ~ISACTIVEHIGH[0] ~THEN ~ELSE ! ~FI ~ARG[4])+ ,.CLK_OUT1 (~RESULT[1])+ ,.LOCKED (~RESULT[0]));+ // clockWizard end+ workInfo: Always+- BlackBox:+ name: Clash.Xilinx.ClockGen.clockWizardDifferential+ kind: Declaration+ type: |-+ clockWizardDifferential+ :: ( KnownDomain domIn confIn -- ARG[0]+ , KnownDomain domOut confOut ) -- ARG[1]+ :: SSymbol name -- ARG[2]+ -> Clock pllIn -- ARG[3]+ -> Clock pllIn -- ARG[4]+ -> Reset pllIn -- ARG[5]+ -> (Clock pllOut, Enable pllOut)+ template: |-+ // clockWizardDifferential begin+ ~NAME[2] ~GENSYM[clockWizardDifferential_inst][2]+ (.CLK_IN1_D_clk_n (~ARG[3])+ ,.CLK_IN1_D_clk_n (~ARG[4])+ ,.RESET (~IF ~ISACTIVEHIGH[0] ~THEN ~ELSE ! ~FI ~ARG[5])+ ,.CLK_OUT1 (~RESULT[1])+ ,.LOCKED (~RESULT[0]));+ // clockWizardDifferential end+ workInfo: Always
− prims/commonverilog/GHC_Base.primitives
@@ -1,8 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Base.remInt"- , "kind" : "Expression"- , "type" : "remInt :: Int -> Int -> Int"- , "template" : "~ARG[0] % ~ARG[1]"- }- }-]
+ prims/commonverilog/GHC_Base.primitives.yaml view
@@ -0,0 +1,12 @@+- BlackBox:+ name: GHC.Base.remInt+ kind: Expression+ type: 'remInt :: Int ->+ Int -> Int'+ template: ~ARG[0] % ~ARG[1]+- BlackBox:+ name: GHC.Base.quotInt+ kind: Expression+ type: 'quotInt :: Int+ -> Int -> Int'+ template: ~ARG[0] / ~ARG[1]
− prims/commonverilog/GHC_Classes.primitives
@@ -1,36 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Classes.eqInt"- , "kind" : "Expression"- , "type" : "eqInt :: Int -> Int -> Bool"- , "template" : "~ARG[0] == ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.neInt"- , "kind" : "Expression"- , "type" : "neInt :: Int -> Int -> Bool"- , "template" : "~ARG[0] != ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.&&"- , "kind" : "Expression"- , "type" : "(&&) :: Bool -> Bool -> Bool"- , "template" : "~ARG[0] & ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.||"- , "kind" : "Expression"- , "type" : "(::) :: Bool -> Bool -> Bool"- , "template" : "~ARG[0] | ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.not"- , "kind" : "Expression"- , "type" : "not :: Bool -> Bool"- , "template" : "~ ~ARG[0]"- }- }-]
+ prims/commonverilog/GHC_Classes.primitives.yaml view
@@ -0,0 +1,30 @@+- BlackBox:+ name: GHC.Classes.eqInt+ kind: Expression+ type: 'eqInt :: Int ->+ Int -> Bool'+ template: ~ARG[0] == ~ARG[1]+- BlackBox:+ name: GHC.Classes.neInt+ kind: Expression+ type: 'neInt :: Int ->+ Int -> Bool'+ template: ~ARG[0] != ~ARG[1]+- BlackBox:+ name: GHC.Classes.&&+ kind: Expression+ type: '(&&) :: Bool ->+ Bool -> Bool'+ template: ~ARG[0] & ~ARG[1]+- BlackBox:+ name: GHC.Classes.||+ kind: Expression+ type: '(||) :: Bool ->+ Bool -> Bool'+ template: ~ARG[0] | ~ARG[1]+- BlackBox:+ name: GHC.Classes.not+ kind: Expression+ type: 'not :: Bool ->+ Bool'+ template: ~ ~ARG[0]
− prims/commonverilog/GHC_Int.primitives
@@ -1,30 +0,0 @@-[- {- "BlackBoxHaskell": {- "name": "GHC.Int.I8#",- "workInfo" : "Never",- "templateFunction": "Clash.Primitives.GHC.Int.intTF"- }- },- {- "BlackBoxHaskell": {- "name": "GHC.Int.I16#",- "workInfo" : "Never",- "templateFunction": "Clash.Primitives.GHC.Int.intTF"- }- },- {- "BlackBoxHaskell": {- "name": "GHC.Int.I32#",- "workInfo" : "Never",- "templateFunction": "Clash.Primitives.GHC.Int.intTF"- }- },- {- "BlackBoxHaskell": {- "name": "GHC.Int.I64#",- "workInfo" : "Never",- "templateFunction": "Clash.Primitives.GHC.Int.intTF"- }- }-]
+ prims/commonverilog/GHC_Int.primitives.yaml view
@@ -0,0 +1,16 @@+- BlackBoxHaskell:+ name: GHC.Int.I8#+ templateFunction: Clash.Primitives.GHC.Int.intTF+ workInfo: Never+- BlackBoxHaskell:+ name: GHC.Int.I16#+ templateFunction: Clash.Primitives.GHC.Int.intTF+ workInfo: Never+- BlackBoxHaskell:+ name: GHC.Int.I32#+ templateFunction: Clash.Primitives.GHC.Int.intTF+ workInfo: Never+- BlackBoxHaskell:+ name: GHC.Int.I64#+ templateFunction: Clash.Primitives.GHC.Int.intTF+ workInfo: Never
− prims/commonverilog/GHC_Integer_Logarithms.primitives
@@ -1,23 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Integer.Logarithms.integerLogBase#"- , "kind" : "Expression"- , "type" : "integerLogBase# :: Integer -> Integer -> Int#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "integerLogBase"- , "extension" : "inc"- , "template" :-"// integer logBase-function integer ~INCLUDENAME[0];- input integer base, value;- begin- for (~INCLUDENAME[0] = 0; value >= base; ~INCLUDENAME[0]=~INCLUDENAME[0]+1)- value = value / base;- end-endfunction"- }- ]- , "template" : "~INCLUDENAME[0](~ARG[0],~ARG[1])"- }- }-]
+ prims/commonverilog/GHC_Integer_Logarithms.primitives.yaml view
@@ -0,0 +1,22 @@+- BlackBox:+ name: GHC.Integer.Logarithms.integerLogBase#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: integerLogBase+ extension: inc+ template: |-+ // integer logBase+ function integer ~INCLUDENAME[0];+ input integer base, value;+ begin+ for (~INCLUDENAME[0] = 0; value >= base; ~INCLUDENAME[0]=~INCLUDENAME[0]+1)+ value = value / base;+ end+ endfunction+ kind: Expression+ type: 'integerLogBase#+ :: Integer -> Integer -> Int#'+ template: ~INCLUDENAME[0](~ARG[0],~ARG[1])+ warning: 'GHC.Integer.Logarithms.integerLogBase#: Integers are dynamically sized+ in simulation, but fixed-length after synthesization. Use carefully.'
− prims/commonverilog/GHC_Integer_Type.primitives
@@ -1,189 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Integer.Type.smallInteger"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "smallInteger :: Int# -> Integer"- , "template" : "assign ~RESULT = $signed(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.integerToInt"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "integerToInt :: Integer -> Int#"- , "template" : "assign ~RESULT = $signed(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.timesInteger"- , "kind" : "Expression"- , "type" : "timesInteger :: Integer -> Integer -> Integer"- , "template" : "~ARG[0] * ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.negateInteger"- , "kind" : "Expression"- , "type" : "negateInteger :: Integer -> Integer"- , "template" : "-~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.absInteger"- , "kind" : "Expression"- , "type" : "absInteger :: Integer -> Integer"- , "template" : "(~ARG[0] < ~SIZE[~TYPO]'sd0) ? -~ARG[0] : ~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.remInteger"- , "kind" : "Expression"- , "type" : "remInteger :: Integer -> Integer -> Integer"- , "template" : "~ARG[0] % ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.eqInteger"- , "kind" : "Expression"- , "type" : "eqInteger :: Integer -> Integer -> Bool"- , "template" : "~ARG[0] == ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.neqInteger"- , "kind" : "Expression"- , "type" : "neqInteger :: Integer -> Integer -> Bool"- , "template" : "~ARG[0] != ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.eqInteger#"- , "kind" : "Expression"- , "type" : "eqInteger :: Integer -> Integer -> Bool"- , "template" : "(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.neqInteger#"- , "kind" : "Expression"- , "type" : "neqInteger :: Integer -> Integer -> Bool"- , "template" : "(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.leInteger#"- , "kind" : "Expression"- , "type" : "leInteger :: Integer -> Integer -> Bool"- , "template" : "(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.gtInteger#"- , "kind" : "Expression"- , "type" : "gtInteger :: Integer -> Integer -> Bool"- , "template" : "(~ARG[0] > ~ARG[1] ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.ltInteger#"- , "kind" : "Expression"- , "type" : "ltInteger :: Integer -> Integer -> Bool"- , "template" : "(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.geInteger#"- , "kind" : "Expression"- , "type" : "geInteger :: Integer -> Integer -> Bool"- , "template" : "(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.shiftRInteger"- , "kind" : "Expression"- , "type" : "shiftRInteger :: Integer -> Int# -> Integer"- , "template" : "~ARG[0] >>> ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.shiftLInteger"- , "kind" : "Expression"- , "type" : "shiftLInteger :: Integer -> Int# -> Integer"- , "template" : "~ARG[0] <<< ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.testBitInteger"- , "kind" : "Expression"- , "type" : "testBitInteger :: Integer -> Int# -> Bool"- , "template" : "~VAR[input][0][~ARG[1]] == 1'b1"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.wordToInteger"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "wordToInteger :: Word# -> Integer"- , "template" : "assign ~RESULT = $signed(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.integerToWord"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "integerToWord :: Integer -> Word#"- , "template" : "assign ~RESULT = $unsigned(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.integerToWord64"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "integerToWord :: Integer -> Word64#"- , "comment" : "only used by 32 bit GHC"- , "template" : "assign ~RESULT = $unsigned(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.bitInteger"- , "kind" : "Expression"- , "type" : "bitInteger :: Int -> Integer"- , "template" : "1 << ~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.complementInteger"- , "kind" : "Expression"- , "type" : "complementInteger :: Integer -> Integer"- , "template" : "~ ~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.xorInteger"- , "kind" : "Expression"- , "type" : "xorInteger :: Integer -> Integer -> Integer"- , "template" : "~ARG[0] ^ ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.orInteger"- , "kind" : "Expression"- , "type" : "orInteger :: Integer -> Integer -> Integer"- , "template" : "~ARG[0] | ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.andInteger"- , "kind" : "Expression"- , "type" : "andInteger :: Integer -> Integer -> Integer"- , "template" : "~ARG[0] & ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.$wsignumInteger"- , "kind" : "Expression"- , "type" : "$wsignumInteger :: Integer -> Integer"- , "template" : "(~ARG[0] < ~SIZE[~TYPO]'sd0) ? -~SIZE[~TYPO]'sd1 : ((~ARG[0] == ~SIZE[~TYPO]'sd0) ? ~SIZE[~TYPO]'sd0 : ~SIZE[~TYPO]'sd1)"- }- }-]
+ prims/commonverilog/GHC_Integer_Type.primitives.yaml view
@@ -0,0 +1,223 @@+- BlackBox:+ name: GHC.Integer.Type.smallInteger+ kind: Declaration+ type: 'smallInteger ::+ Int# -> Integer'+ template: assign ~RESULT = $signed(~ARG[0]);+ warning: 'GHC.Integer.Type.smallInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Integer.Type.integerToInt+ kind: Declaration+ type: 'integerToInt ::+ Integer -> Int#'+ template: assign ~RESULT = $signed(~ARG[0]);+ warning: 'GHC.Integer.Type.integerToInt: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Integer.Type.timesInteger+ kind: Expression+ type: 'timesInteger ::+ Integer -> Integer -> Integer'+ template: ~ARG[0] * ~ARG[1]+ warning: 'GHC.Integer.Type.timesInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.negateInteger+ kind: Expression+ type: 'negateInteger ::+ Integer -> Integer'+ template: -~ARG[0]+ warning: 'GHC.Integer.Type.negateInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.absInteger+ kind: Expression+ type: 'absInteger :: Integer+ -> Integer'+ template: '(~ARG[0] < ~SIZE[~TYPO]''sd0) ? -~ARG[0] : ~ARG[0]'+ warning: 'GHC.Integer.Type.absInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.remInteger+ kind: Expression+ type: 'remInteger :: Integer+ -> Integer -> Integer'+ template: ~ARG[0] % ~ARG[1]+ warning: 'GHC.Integer.Type.remInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.eqInteger+ kind: Expression+ type: 'eqInteger :: Integer+ -> Integer -> Bool'+ template: ~ARG[0] == ~ARG[1]+ warning: 'GHC.Integer.Type.eqInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.neqInteger+ kind: Expression+ type: 'neqInteger :: Integer+ -> Integer -> Bool'+ template: ~ARG[0] != ~ARG[1]+ warning: 'GHC.Integer.Type.neqInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.eqInteger#+ kind: Expression+ type: 'eqInteger :: Integer+ -> Integer -> Bool'+ template: '(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+ warning: 'GHC.Integer.Type.eqInteger#: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.neqInteger#+ kind: Expression+ type: 'neqInteger :: Integer+ -> Integer -> Bool'+ template: '(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+ warning: 'GHC.Integer.Type.neqInteger#: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.leInteger#+ kind: Expression+ type: 'leInteger :: Integer+ -> Integer -> Bool'+ template: '(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+ warning: 'GHC.Integer.Type.leInteger#: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.gtInteger#+ kind: Expression+ type: 'gtInteger :: Integer+ -> Integer -> Bool'+ template: '(~ARG[0] > ~ARG[1] ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+ warning: 'GHC.Integer.Type.gtInteger#: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.ltInteger#+ kind: Expression+ type: 'ltInteger :: Integer+ -> Integer -> Bool'+ template: '(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+ warning: 'GHC.Integer.Type.ltInteger#: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.geInteger#+ kind: Expression+ type: 'geInteger :: Integer+ -> Integer -> Bool'+ template: '(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+ warning: 'GHC.Integer.Type.geInteger#: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.shiftRInteger+ kind: Expression+ type: 'shiftRInteger ::+ Integer -> Int# -> Integer'+ template: ~ARG[0] >>> ~ARG[1]+ warning: 'GHC.Integer.Type.shiftRInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.shiftLInteger+ kind: Expression+ type: 'shiftLInteger ::+ Integer -> Int# -> Integer'+ template: ~ARG[0] <<< ~ARG[1]+ warning: 'GHC.Integer.Type.shiftLInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.testBitInteger+ kind: Expression+ type: 'testBitInteger+ :: Integer -> Int# -> Bool'+ template: ~VAR[input][0][~ARG[1]] == 1'b1+ warning: 'GHC.Integer.Type.testBitInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.wordToInteger+ kind: Declaration+ type: 'wordToInteger ::+ Word# -> Integer'+ template: assign ~RESULT = $signed(~ARG[0]);+ warning: 'GHC.Integer.Type.wordToInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Integer.Type.integerToWord+ kind: Declaration+ type: 'integerToWord ::+ Integer -> Word#'+ template: assign ~RESULT = $unsigned(~ARG[0]);+ warning: 'GHC.Integer.Type.integerToWord: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Integer.Type.integerToWord64+ comment: only used by 32 bit GHC+ kind: Declaration+ type: 'integerToWord ::+ Integer -> Word64#'+ template: assign ~RESULT = $unsigned(~ARG[0]);+ warning: 'GHC.Integer.Type.integerToWord64: Integers are dynamically sized in+ simulation, but fixed-length after synthesization. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Integer.Type.bitInteger+ kind: Expression+ type: 'bitInteger :: Int+ -> Integer'+ template: 1 << ~ARG[0]+ warning: 'GHC.Integer.Type.bitInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.complementInteger+ kind: Expression+ type: 'complementInteger+ :: Integer -> Integer'+ template: ~ ~ARG[0]+ warning: 'GHC.Integer.Type.complementInteger: Integers are dynamically sized in+ simulation, but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.xorInteger+ kind: Expression+ type: 'xorInteger :: Integer+ -> Integer -> Integer'+ template: ~ARG[0] ^ ~ARG[1]+ warning: 'GHC.Integer.Type.xorInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.orInteger+ kind: Expression+ type: 'orInteger :: Integer+ -> Integer -> Integer'+ template: ~ARG[0] | ~ARG[1]+ warning: 'GHC.Integer.Type.orInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.andInteger+ kind: Expression+ type: 'andInteger :: Integer+ -> Integer -> Integer'+ template: ~ARG[0] & ~ARG[1]+ warning: 'GHC.Integer.Type.andInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.$wsignumInteger+ kind: Expression+ type: '$wsignumInteger+ :: Integer -> Integer'+ template: '(~ARG[0] < ~SIZE[~TYPO]''sd0) ? -~SIZE[~TYPO]''sd1 : ((~ARG[0] == ~SIZE[~TYPO]''sd0)+ ? ~SIZE[~TYPO]''sd0 : ~SIZE[~TYPO]''sd1)'+ warning: 'GHC.Integer.Type.$wsignumInteger: Integers are dynamically sized in+ simulation, but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.quotInteger+ kind: Expression+ type: 'quotInteger ::+ Integer -> Integer -> Integer'+ template: ~ARG[0] / ~ARG[1]+ warning: 'GHC.Integer.Type.quotInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'
− prims/commonverilog/GHC_Natural.primitives
@@ -1,31 +0,0 @@-[- {- "BlackBox": {- "name": "GHC.Natural.naturalFromInteger",- "workInfo" : "Never",- "kind": "Expression",- "type": "naturalFromInteger :: Integer -> Natural",- "template": "$unsigned(~VAR[n][0][(~SIZE[~TYPO]-1):0])",- "warning": "GHC.Natural.naturalFromInteger: Naturals are dynamically sized in simulation, but fixed-length after synthesization. Use carefully."- }- },- {- "BlackBox": {- "name": "GHC.Natural.timesNatural",- "kind": "Expression",- "type": "timesNatural :: Natural -> Natural -> Natural",- "template": "~ARG[0] * ~ARG[1]",- "warning": "GHC.Natural.timesNatural: Naturals are dynamically sized in simulation, but fixed-length after synthesization. Use carefully."- }- },- {- "BlackBox": {- "name": "GHC.Natural.wordToNatural#",- "workInfo" : "Never",- "kind": "Declaration",- "type": "wordToNatural# :: Word# -> Natural",- "template": "assign ~RESULT = $unsigned(~ARG[0]);",- "warning": "GHC.Natural.wordToNatural#: Naturals are dynamically sized in simulation, but fixed-length after synthesization. Use carefully."- }- }-]
+ prims/commonverilog/GHC_Natural.primitives.yaml view
@@ -0,0 +1,26 @@+- BlackBox:+ name: GHC.Natural.naturalFromInteger+ kind: Expression+ type: 'naturalFromInteger+ :: Integer -> Natural'+ template: $unsigned(~VAR[n][0][(~SIZE[~TYPO]-1):0])+ warning: 'GHC.Natural.naturalFromInteger: Naturals are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Natural.timesNatural+ kind: Expression+ type: 'timesNatural ::+ Natural -> Natural -> Natural'+ template: ~ARG[0] * ~ARG[1]+ warning: 'GHC.Natural.timesNatural: Naturals are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Natural.wordToNatural#+ kind: Declaration+ type: 'wordToNatural#+ :: Word# -> Natural'+ template: assign ~RESULT = $unsigned(~ARG[0]);+ warning: 'GHC.Natural.wordToNatural#: Naturals are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+ workInfo: Never
− prims/commonverilog/GHC_Num_Integer.primitives
@@ -1,244 +0,0 @@-[ { "BlackBox":- { "name": "GHC.Num.Integer.integerToNatural"- , "workInfo" : "Never"- , "kind": "Expression"- , "type": "integerToNatural :: Integer -> Natural"- , "template": "$unsigned(~VAR[n][0][(~SIZE[~TYPO]-1):0])"- , "warning": "GHC.Num.Integer.integerToNatural: Naturals are dynamically sized in simulation, but fixed-length after synthesis. Use carefully."- }- }-, { "BlackBox":- { "name": "GHC.Num.Integer.integerToNaturalThrow"- , "workInfo" : "Never"- , "kind": "Expression"- , "type": "integerToNaturalThrow :: Integer -> Natural"- , "template": "(~ARG[0] < ~SIZE[~TYP[0]]'d0 ? ~ERRORO: $unsigned(~VAR[n][0][(~SIZE[~TYPO]-1):0]))"- , "warning": "GHC.Num.Integer.integerToNaturalThrow: Naturals are dynamically sized in simulation, but fixed-length after synthesis. Use carefully."- }-}-, { "BlackBox":- { "name": "GHC.Num.Integer.integerToNaturalClamp"- , "workInfo" : "Never"- , "kind": "Expression"- , "type": "integerToNatural :: Integer -> Natural"- , "template": "(~ARG[0] < ~SIZE[~TYP[0]]'d0 ? ~SIZE[~TYPO]'d0 : $unsigned(~VAR[n][0][(~SIZE[~TYPO]-1):0]))"- , "warning": "GHC.Num.Integer.integerToNaturalClamp: Naturals are dynamically sized in simulation, but fixed-length after synthesis. Use carefully."- }-}-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerToInt#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "integerToInt :: Integer -> Int#"- , "template" : "assign ~RESULT = $signed(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerMul"- , "kind" : "Expression"- , "type" : "integerMul :: Integer -> Integer -> Integer"- , "template" : "~ARG[0] * ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerNegate"- , "kind" : "Expression"- , "type" : "integerNegate :: Integer -> Integer"- , "template" : "-~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerAbs"- , "kind" : "Expression"- , "type" : "integerAbs :: Integer -> Integer"- , "template" : "(~ARG[0] < ~SIZE[~TYPO]'sd0) ? -~ARG[0] : ~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerRem"- , "kind" : "Expression"- , "type" : "integerRem :: Integer -> Integer -> Integer"- , "template" : "~ARG[0] % ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerEq"- , "kind" : "Expression"- , "type" : "integerEq :: Integer -> Integer -> Bool"- , "template" : "~ARG[0] == ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerNe"- , "kind" : "Expression"- , "type" : "integerNe :: Integer -> Integer -> Bool"- , "template" : "~ARG[0] != ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerEq#"- , "kind" : "Expression"- , "type" : "integerEq :: Integer -> Integer -> Int#"- , "template" : "(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerNe#"- , "kind" : "Expression"- , "type" : "integerNe# :: Integer -> Integer -> Int#"- , "template" : "(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerLe#"- , "kind" : "Expression"- , "type" : "integerLe :: Integer -> Integer -> Int#"- , "template" : "(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerGt#"- , "kind" : "Expression"- , "type" : "integerGt# :: Integer -> Integer -> Int#"- , "template" : "(~ARG[0] > ~ARG[1] ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerLt#"- , "kind" : "Expression"- , "type" : "integerLt# :: Integer -> Integer -> Int#"- , "template" : "(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerGe#"- , "kind" : "Expression"- , "type" : "integerGe# :: Integer -> Integer -> Int#"- , "template" : "(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerShiftR#"- , "kind" : "Expression"- , "type" : "integerShiftR :: Integer -> Word# -> Integer"- , "template" : "~ARG[0] >>> ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerShiftL#"- , "kind" : "Expression"- , "type" : "integerShiftL :: Integer -> Word# -> Integer"- , "template" : "~ARG[0] <<< ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerTestBit#"- , "kind" : "Expression"- , "type" : "integerTestBit :: Integer -> Word# -> Bool"- , "template" : "~VAR[input][0][~ARG[1]] == 1'b1"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerFromWord#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "integerFromWord# :: Word# -> Integer"- , "template" : "assign ~RESULT = $signed(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerToWord#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "integerToWord# :: Integer -> Word#"- , "template" : "assign ~RESULT = $unsigned(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerToWord64#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "integerToWord64# :: Integer -> Word64#"- , "comment" : "only used by 32 bit GHC"- , "template" : "assign ~RESULT = $unsigned(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerBit#"- , "kind" : "Expression"- , "type" : "integerBit# :: Word# -> Integer"- , "template" : "1 << ~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerComplement"- , "kind" : "Expression"- , "type" : "integerComplement :: Integer -> Integer"- , "template" : "~ ~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerXor"- , "kind" : "Expression"- , "type" : "integerXor :: Integer -> Integer -> Integer"- , "template" : "~ARG[0] ^ ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerOr"- , "kind" : "Expression"- , "type" : "integerOr :: Integer -> Integer -> Integer"- , "template" : "~ARG[0] | ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerAnd"- , "kind" : "Expression"- , "type" : "andInteger :: Integer -> Integer -> Integer"- , "template" : "~ARG[0] & ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerSignum"- , "kind" : "Expression"- , "type" : "integerSignum :: Integer -> Integer"- , "template" : "(~ARG[0] < ~SIZE[~TYPO]'sd0) ? -~SIZE[~TYPO]'sd1 : ((~ARG[0] == ~SIZE[~TYPO]'sd0) ? ~SIZE[~TYPO]'sd0 : ~SIZE[~TYPO]'sd1)"- }- }- , { "BlackBox" :- { "name" : "GHC.Num.Integer.$wintegerSignum"- , "kind" : "Expression"- , "type" : "integerSignum :: Integer -> Int#"- , "template" : "(~ARG[0] < ~SIZE[~TYPO]'sd0) ? -~SIZE[~TYPO]'sd1 : ((~ARG[0] == ~SIZE[~TYPO]'sd0) ? ~SIZE[~TYPO]'sd0 : ~SIZE[~TYPO]'sd1)"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerLogBase#"- , "kind" : "Expression"- , "type" : "integerLogBase# :: Integer -> Integer -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "integerLogBase"- , "extension" : "inc"- , "template" :-"// integer logBase-function integer ~INCLUDENAME[0];-input integer base, value;-begin- for (~INCLUDENAME[0] = 0; value >= base; ~INCLUDENAME[0]=~INCLUDENAME[0]+1)- value = value / base;-end-endfunction"- }- ]- , "template" : "~INCLUDENAME[0](~ARG[0],~ARG[1])"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerCompare"- , "kind" : "Expression"- , "type" : "integerCompare :: Integer -> Integer -> Ordering"- , "template" : "(~ARG[0] < ~ARG[1]) ? -~SIZE[~TYPO]'d0 : ((~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]'d1 : ~SIZE[~TYPO]'d2)"- }- }-]
+ prims/commonverilog/GHC_Num_Integer.primitives.yaml view
@@ -0,0 +1,281 @@+- BlackBox:+ name: GHC.Num.Integer.integerToNatural+ kind: Expression+ type: 'integerToNatural+ :: Integer -> Natural'+ template: $unsigned(~VAR[n][0][(~SIZE[~TYPO]-1):0])+ warning: 'GHC.Num.Integer.integerToNatural: Naturals are dynamically sized in+ simulation, but fixed-length after synthesis. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Num.Integer.integerToNaturalThrow+ kind: Expression+ type: 'integerToNaturalThrow+ :: Integer -> Natural'+ template: '(~ARG[0] < ~SIZE[~TYP[0]]''d0 ? ~ERRORO: $unsigned(~VAR[n][0][(~SIZE[~TYPO]-1):0]))'+ warning: 'GHC.Num.Integer.integerToNaturalThrow: Naturals are dynamically sized+ in simulation, but fixed-length after synthesis. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Num.Integer.integerToNaturalClamp+ kind: Expression+ type: 'integerToNatural+ :: Integer -> Natural'+ template: '(~ARG[0] < ~SIZE[~TYP[0]]''d0 ? ~SIZE[~TYPO]''d0 : $unsigned(~VAR[n][0][(~SIZE[~TYPO]-1):0]))'+ warning: 'GHC.Num.Integer.integerToNaturalClamp: Naturals are dynamically sized+ in simulation, but fixed-length after synthesis. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Num.Integer.integerToInt#+ kind: Declaration+ type: 'integerToInt ::+ Integer -> Int#'+ template: assign ~RESULT = $signed(~ARG[0]);+ warning: 'GHC.Num.Integer.integerToInt#: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Num.Integer.integerMul+ kind: Expression+ type: 'integerMul :: Integer+ -> Integer -> Integer'+ template: ~ARG[0] * ~ARG[1]+ warning: 'GHC.Num.Integer.integerMul: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerNegate+ kind: Expression+ type: 'integerNegate ::+ Integer -> Integer'+ template: -~ARG[0]+ warning: 'GHC.Num.Integer.integerNegate: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerAbs+ kind: Expression+ type: 'integerAbs :: Integer+ -> Integer'+ template: '(~ARG[0] < ~SIZE[~TYPO]''sd0) ? -~ARG[0] : ~ARG[0]'+ warning: 'GHC.Num.Integer.integerAbs: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerRem+ kind: Expression+ type: 'integerRem :: Integer+ -> Integer -> Integer'+ template: ~ARG[0] % ~ARG[1]+ warning: 'GHC.Num.Integer.integerRem: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerEq+ kind: Expression+ type: 'integerEq :: Integer+ -> Integer -> Bool'+ template: ~ARG[0] == ~ARG[1]+ warning: 'GHC.Num.Integer.integerEq: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerNe+ kind: Expression+ type: 'integerNe :: Integer+ -> Integer -> Bool'+ template: ~ARG[0] != ~ARG[1]+ warning: 'GHC.Num.Integer.integerNe: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerEq#+ kind: Expression+ type: 'integerEq :: Integer+ -> Integer -> Int#'+ template: '(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+ warning: 'GHC.Num.Integer.integerEq#: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerNe#+ kind: Expression+ type: 'integerNe# :: Integer+ -> Integer -> Int#'+ template: '(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+ warning: 'GHC.Num.Integer.integerNe#: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerLe#+ kind: Expression+ type: 'integerLe :: Integer+ -> Integer -> Int#'+ template: '(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+ warning: 'GHC.Num.Integer.integerLe#: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerGt#+ kind: Expression+ type: 'integerGt# :: Integer+ -> Integer -> Int#'+ template: '(~ARG[0] > ~ARG[1] ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+ warning: 'GHC.Num.Integer.integerGt#: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerLt#+ kind: Expression+ type: 'integerLt# :: Integer+ -> Integer -> Int#'+ template: '(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+ warning: 'GHC.Num.Integer.integerLt#: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerGe#+ kind: Expression+ type: 'integerGe# :: Integer+ -> Integer -> Int#'+ template: '(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+ warning: 'GHC.Num.Integer.integerGe#: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerShiftR#+ kind: Expression+ type: 'integerShiftR ::+ Integer -> Word# -> Integer'+ template: ~ARG[0] >>> ~ARG[1]+ warning: 'GHC.Num.Integer.integerShiftR#: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerShiftL#+ kind: Expression+ type: 'integerShiftL ::+ Integer -> Word# -> Integer'+ template: ~ARG[0] <<< ~ARG[1]+ warning: 'GHC.Num.Integer.integerShiftL#: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerTestBit#+ kind: Expression+ type: 'integerTestBit+ :: Integer -> Word# -> Bool'+ template: ~VAR[input][0][~ARG[1]] == 1'b1+ warning: 'GHC.Num.Integer.integerTestBit#: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerFromWord#+ kind: Declaration+ type: 'integerFromWord#+ :: Word# -> Integer'+ template: assign ~RESULT = $signed(~ARG[0]);+ warning: 'GHC.Num.Integer.integerFromWord#: Integers are dynamically sized in+ simulation, but fixed-length after synthesization. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Num.Integer.integerToWord#+ kind: Declaration+ type: 'integerToWord#+ :: Integer -> Word#'+ template: assign ~RESULT = $unsigned(~ARG[0]);+ warning: 'GHC.Num.Integer.integerToWord#: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Num.Integer.integerToWord64#+ comment: only used by 32 bit GHC+ kind: Declaration+ type: 'integerToWord64#+ :: Integer -> Word64#'+ template: assign ~RESULT = $unsigned(~ARG[0]);+ warning: 'GHC.Num.Integer.integerToWord64#: Integers are dynamically sized in+ simulation, but fixed-length after synthesization. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Num.Integer.integerBit#+ kind: Expression+ type: 'integerBit# ::+ Word# -> Integer'+ template: 1 << ~ARG[0]+ warning: 'GHC.Num.Integer.integerBit#: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerComplement+ kind: Expression+ type: 'integerComplement+ :: Integer -> Integer'+ template: ~ ~ARG[0]+ warning: 'GHC.Num.Integer.integerComplement: Integers are dynamically sized in+ simulation, but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerXor+ kind: Expression+ type: 'integerXor :: Integer+ -> Integer -> Integer'+ template: ~ARG[0] ^ ~ARG[1]+ warning: 'GHC.Num.Integer.integerXor: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerOr+ kind: Expression+ type: 'integerOr :: Integer+ -> Integer -> Integer'+ template: ~ARG[0] | ~ARG[1]+ warning: 'GHC.Num.Integer.integerOr: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerAnd+ kind: Expression+ type: 'andInteger :: Integer+ -> Integer -> Integer'+ template: ~ARG[0] & ~ARG[1]+ warning: 'GHC.Num.Integer.integerAnd: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerSignum+ kind: Expression+ type: 'integerSignum ::+ Integer -> Integer'+ template: '(~ARG[0] < ~SIZE[~TYPO]''sd0) ? -~SIZE[~TYPO]''sd1 : ((~ARG[0] == ~SIZE[~TYPO]''sd0)+ ? ~SIZE[~TYPO]''sd0 : ~SIZE[~TYPO]''sd1)'+ warning: 'GHC.Num.Integer.integerSignum: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.$wintegerSignum+ kind: Expression+ type: 'integerSignum ::+ Integer -> Int#'+ template: '(~ARG[0] < ~SIZE[~TYPO]''sd0) ? -~SIZE[~TYPO]''sd1 : ((~ARG[0] == ~SIZE[~TYPO]''sd0)+ ? ~SIZE[~TYPO]''sd0 : ~SIZE[~TYPO]''sd1)'+ warning: 'GHC.Num.Integer.$wintegerSignum: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerLogBase#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: integerLogBase+ extension: inc+ template: |-+ // integer logBase+ function integer ~INCLUDENAME[0];+ input integer base, value;+ begin+ for (~INCLUDENAME[0] = 0; value >= base; ~INCLUDENAME[0]=~INCLUDENAME[0]+1)+ value = value / base;+ end+ endfunction+ kind: Expression+ type: 'integerLogBase#+ :: Integer -> Integer -> Word#'+ template: ~INCLUDENAME[0](~ARG[0],~ARG[1])+ warning: 'GHC.Num.Integer.integerLogBase#: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerCompare+ kind: Expression+ type: 'integerCompare+ :: Integer -> Integer -> Ordering'+ template: '(~ARG[0] < ~ARG[1]) ? -~SIZE[~TYPO]''d0 : ((~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]''d1+ : ~SIZE[~TYPO]''d2)'+ warning: 'GHC.Num.Integer.integerCompare: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerQuot+ kind: Expression+ type: 'integerQuot ::+ Integer -> Integer -> Integer'+ template: ~ARG[0] / ~ARG[1]+ warning: 'GHC.Num.Integer.integerQuot: Integers are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'
− prims/commonverilog/GHC_Num_Natural.primitives
@@ -1,113 +0,0 @@-[- {- "BlackBox": {- "name": "GHC.Num.Natural.naturalMul",- "kind": "Expression",- "type": "naturalMul :: Natural -> Natural -> Natural",- "template": "~ARG[0] * ~ARG[1]",- "warning": "GHC.Num.Natural.naturalMul: Naturals are dynamically sized in simulation, but fixed-length after synthesis. Use carefully."- }- },- {- "BlackBox": {- "name": "GHC.Num.Natural.naturalFromWord#",- "workInfo" : "Never",- "kind": "Declaration",- "type": "naturalFromWord# :: Word# -> Natural",- "template": "assign ~RESULT = $unsigned(~ARG[0]);",- "warning": "GHC.Num.Natural.naturalFromWord#: Naturals are dynamically sized in simulation, but fixed-length after synthesis. Use carefully."- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Natural.naturalRem"- , "kind" : "Expression"- , "type" : "naturalRem :: Natural -> Natural -> Natural"- , "template" : "~ARG[0] % ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Natural.naturalLogBase#"- , "kind" : "Expression"- , "type" : "naturalLogBase# :: Natural -> Natural -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "naturalLogBase"- , "extension" : "inc"- , "template" :-"// natural logBase-function integer ~INCLUDENAME[0];-input [~SIZE[~TYP[0]]-1:0] base, value;-begin- for (~INCLUDENAME[0] = 0; value >= base; ~INCLUDENAME[0]=~INCLUDENAME[0]+1)- value = value / base;-end-endfunction"- }- ]- , "template" : "~INCLUDENAME[0](~ARG[0],~ARG[1])"- }-}-, { "BlackBox" :- { "name" : "GHC.Num.Natural.naturalEq#"- , "kind" : "Expression"- , "type" : "naturalEq :: Natural -> Natural -> Int#"- , "template" : "(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]'d1 : ~SIZE[~TYPO]'d0"- }-}-, { "BlackBox" :- { "name" : "GHC.Num.Natural.naturalNe#"- , "kind" : "Expression"- , "type" : "naturalNe# :: Natural -> Natural -> Int#"- , "template" : "(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]'d1 : ~SIZE[~TYPO]'d0"- }-}-, { "BlackBox" :- { "name" : "GHC.Num.Natural.naturalLe#"- , "kind" : "Expression"- , "type" : "naturalLe :: Natural -> Natural -> Int#"- , "template" : "(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]'d1 : ~SIZE[~TYPO]'d0"- }-}-, { "BlackBox" :- { "name" : "GHC.Num.Natural.naturalGt#"- , "kind" : "Expression"- , "type" : "naturalGt# :: Natural -> Natural -> Int#"- , "template" : "(~ARG[0] > ~ARG[1] ? ~SIZE[~TYPO]'d1 : ~SIZE[~TYPO]'d0"- }-}-, { "BlackBox" :- { "name" : "GHC.Num.Natural.naturalLt#"- , "kind" : "Expression"- , "type" : "naturalLt# :: Natural -> Natural -> Int#"- , "template" : "(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]'d1 : ~SIZE[~TYPO]'d0"- }-}-, { "BlackBox" :- { "name" : "GHC.Num.Natural.naturalGe#"- , "kind" : "Expression"- , "type" : "naturalGe# :: Natural -> Natural -> Int#"- , "template" : "(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]'d1 : ~SIZE[~TYPO]'d0"- }-}-, { "BlackBox" :- { "name" : "GHC.Num.Natural.naturalShiftL#"- , "kind" : "Expression"- , "type" : "naturalShiftL# :: Natural -> Word# -> Natural"- , "template" : "~ARG[0] <<< ~ARG[1]"- }-}-, { "BlackBox" :- { "name" : "GHC.Num.Natural.naturalShiftR#"- , "kind" : "Expression"- , "type" : "naturalShiftR# :: Natuarl -> Word# -> Natural"- , "template" : "~ARG[0] >>> ~ARG[1]"- }-}-, { "BlackBox" :- { "name" : "GHC.Num.Natural.NaturalCompare"- , "kind" : "Expression"- , "type" : "naturalCompare :: Natural -> Natural -> Ordering"- , "template" : "(~ARG[0] < ~ARG[1]) ? -~SIZE[~TYPO]'d0 : ((~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]'d1 : ~SIZE[~TYPO]'d2)"- }-}-]
+ prims/commonverilog/GHC_Num_Natural.primitives.yaml view
@@ -0,0 +1,128 @@+- BlackBox:+ name: GHC.Num.Natural.naturalMul+ kind: Expression+ type: 'naturalMul :: Natural+ -> Natural -> Natural'+ template: ~ARG[0] * ~ARG[1]+ warning: 'GHC.Num.Natural.naturalMul: Naturals are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Natural.naturalFromWord#+ kind: Declaration+ type: 'naturalFromWord#+ :: Word# -> Natural'+ template: assign ~RESULT = $unsigned(~ARG[0]);+ warning: 'GHC.Num.Natural.naturalFromWord#: Naturals are dynamically sized in+ simulation, but fixed-length after synthesis. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Num.Natural.naturalRem+ kind: Expression+ type: 'naturalRem :: Natural+ -> Natural -> Natural'+ template: ~ARG[0] % ~ARG[1]+ warning: 'GHC.Num.Natural.naturalRem: Naturals are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Natural.naturalLogBase#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: naturalLogBase+ extension: inc+ template: |-+ // natural logBase+ function integer ~INCLUDENAME[0];+ input [~SIZE[~TYP[0]]-1:0] base, value;+ begin+ for (~INCLUDENAME[0] = 0; value >= base; ~INCLUDENAME[0]=~INCLUDENAME[0]+1)+ value = value / base;+ end+ endfunction+ kind: Expression+ type: 'naturalLogBase#+ :: Natural -> Natural -> Word#'+ template: ~INCLUDENAME[0](~ARG[0],~ARG[1])+ warning: 'GHC.Num.Natural.naturalLogBase#: Naturals are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Natural.naturalEq#+ kind: Expression+ type: 'naturalEq :: Natural+ -> Natural -> Int#'+ template: '(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]''d1 : ~SIZE[~TYPO]''d0'+ warning: 'GHC.Num.Natural.naturalEq#: Naturals are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Natural.naturalNe#+ kind: Expression+ type: 'naturalNe# :: Natural+ -> Natural -> Int#'+ template: '(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]''d1 : ~SIZE[~TYPO]''d0'+ warning: 'GHC.Num.Natural.naturalNe#: Naturals are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Natural.naturalLe#+ kind: Expression+ type: 'naturalLe :: Natural+ -> Natural -> Int#'+ template: '(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]''d1 : ~SIZE[~TYPO]''d0'+ warning: 'GHC.Num.Natural.naturalLe#: Naturals are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Natural.naturalGt#+ kind: Expression+ type: 'naturalGt# :: Natural+ -> Natural -> Int#'+ template: '(~ARG[0] > ~ARG[1] ? ~SIZE[~TYPO]''d1 : ~SIZE[~TYPO]''d0'+ warning: 'GHC.Num.Natural.naturalGt#: Naturals are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Natural.naturalLt#+ kind: Expression+ type: 'naturalLt# :: Natural+ -> Natural -> Int#'+ template: '(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]''d1 : ~SIZE[~TYPO]''d0'+ warning: 'GHC.Num.Natural.naturalLt#: Naturals are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Natural.naturalGe#+ kind: Expression+ type: 'naturalGe# :: Natural+ -> Natural -> Int#'+ template: '(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]''d1 : ~SIZE[~TYPO]''d0'+ warning: 'GHC.Num.Natural.naturalGe#: Naturals are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Natural.naturalShiftL#+ kind: Expression+ type: 'naturalShiftL#+ :: Natural -> Word# -> Natural'+ template: ~ARG[0] <<< ~ARG[1]+ warning: 'GHC.Num.Natural.naturalShiftL#: Naturals are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Natural.naturalShiftR#+ kind: Expression+ type: 'naturalShiftR#+ :: Natuarl -> Word# -> Natural'+ template: ~ARG[0] >>> ~ARG[1]+ warning: 'GHC.Num.Natural.naturalShiftR#: Naturals are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Natural.NaturalCompare+ kind: Expression+ type: 'naturalCompare+ :: Natural -> Natural -> Ordering'+ template: '(~ARG[0] < ~ARG[1]) ? -~SIZE[~TYPO]''d0 : ((~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]''d1+ : ~SIZE[~TYPO]''d2)'+ warning: 'GHC.Num.Natural.naturalCompare: Naturals are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+- BlackBox:+ name: GHC.Num.Natural.naturalQuot+ kind: Expression+ type: 'naturalQuot ::+ Natural -> Natural -> Natural'+ template: ~ARG[0] / ~ARG[1]+ warning: 'GHC.Num.Natural.naturalQuot: Naturals are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'
− prims/commonverilog/GHC_Prim.primitives
@@ -1,478 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Prim.gtChar#"- , "kind" : "Expression"- , "type" : "gtChar# :: Char# -> Char# -> Int#"- , "template" : "(~ARG[0] > ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.geChar#"- , "kind" : "Expression"- , "type" : "geChar# :: Char# -> Char# -> Int#"- , "template" : "(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.eqChar#"- , "kind" : "Expression"- , "type" : "eqChar# :: Char# -> Char# -> Int#"- , "template" : "(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.neChar#"- , "kind" : "Expression"- , "type" : "neChar# :: Char# -> Char# -> Int#"- , "template" : "(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ltChar#"- , "kind" : "Expression"- , "type" : "ltChar# :: Char# -> Char# -> Int#"- , "template" : "(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.leChar#"- , "kind" : "Expression"- , "type" : "leChar# :: Char# -> Char# -> Int#"- , "template" : "(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ord#"- , "kind" : "Expression"- , "type" : "ord :: Char# -> Int#"- , "template" : "$signed({{(~SIZE[~TYPO]-~SIZE[~TYP[0]]) {1'b0}},~VAR[c][0]})"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.*#"- , "kind" : "Expression"- , "type" : "(*#) :: Int# -> Int# -> Int#"- , "template" : "~ARG[0] * ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.remInt#"- , "kind" : "Expression"- , "type" : "remInt# :: Int# -> Int# -> Int#"- , "template" : "~ARG[0] % ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.andI#"- , "kind" : "Expression"- , "type" : "andI# :: Int# -> Int# -> Int#"- , "template" : "~ARG[0] & ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.orI#"- , "kind" : "Expression"- , "type" : "orI# :: Int# -> Int# -> Int#"- , "template" : "~ARG[0] | ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.xorI#"- , "kind" : "Expression"- , "type" : "xorI# :: Int# -> Int# -> Int#"- , "template" : "~ARG[0] ^ ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.notI#"- , "kind" : "Expression"- , "type" : "notI# :: Int# -> Int#"- , "template" : "~ ~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.negateInt#"- , "kind" : "Expression"- , "type" : "negateInt# :: Int# -> Int#"- , "template" : "-(~ARG[0])"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.>#"- , "kind" : "Expression"- , "type" : "(>#) :: Int# -> Int# -> Int#"- , "template" : "(~ARG[0] > ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.>=#"- , "kind" : "Expression"- , "type" : "(>=#) :: Int# -> Int# -> Int#"- , "template" : "(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.==#"- , "kind" : "Expression"- , "type" : "(==) :: Int# -> Int# -> Int#"- , "template" : "(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim./=#"- , "kind" : "Expression"- , "type" : "(/=#) :: Int# -> Int# -> Int#"- , "template" : "(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.<#"- , "kind" : "Expression"- , "type" : "(<#) :: Int# -> Int# -> Int#"- , "template" : "(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.<=#"- , "kind" : "Expression"- , "type" : "(<=#) :: Int# -> Int# -> Int#"- , "template" : "(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.chr#"- , "kind" : "Expression"- , "type" : "ord :: Int# -> Char#"- , "template" : "$unsigned(~VAR[i][0][0+:~SIZE[~TYPO]])"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.int2Word#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "int2Word# :: Int# -> Word#"- , "template" : "$unsigned(~ARG[0])"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.uncheckedIShiftL#"- , "kind" : "Expression"- , "type" : "uncheckedIShiftL# :: Int# -> Int# -> Int#"- , "template" : "~ARG[0] <<< ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.uncheckedIShiftRA#"- , "kind" : "Expression"- , "type" : "uncheckedIShiftRA# :: Int# -> Int# -> Int#"- , "template" : "~ARG[0] >>> ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.uncheckedIShiftRL#"- , "kind" : "Expression"- , "type" : "uncheckedIShiftRL# :: Int# -> Int# -> Int#"- , "template" : "~ARG[0] >> ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.timesWord#"- , "kind" : "Expression"- , "type" : "timesWord# :: Word# -> Word# -> Word#"- , "template" : "~ARG[0] * ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.remWord#"- , "kind" : "Expression"- , "type" : "remWord# :: Word# -> Word# -> Word#"- , "template" : "~ARG[0] % ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.and#"- , "kind" : "Expression"- , "type" : "and# :: Word# -> Word# -> Word#"- , "template" : "~ARG[0] & ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.or#"- , "kind" : "Expression"- , "type" : "or# :: Word# -> Word# -> Word#"- , "template" : "~ARG[0] | ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.xor#"- , "kind" : "Expression"- , "type" : "xor# :: Word# -> Word# -> Word#"- , "template" : "~ARG[0] ^ ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.not#"- , "kind" : "Expression"- , "type" : "not# :: Word# -> Word#"- , "template" : "~ ~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.uncheckedShiftL#"- , "kind" : "Expression"- , "type" : "uncheckedShiftL# :: Word# -> Int# -> Word#"- , "template" : "~ARG[0] << ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.uncheckedShiftRL#"- , "kind" : "Expression"- , "type" : "uncheckedShiftRL# :: Word# -> Int# -> Word#"- , "template" : "~ARG[0] >> ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.word2Int#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "int2Word# :: Word# -> Int#"- , "template" : "$signed(~ARG[0])"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.gtWord#"- , "kind" : "Expression"- , "type" : "gtWord# :: Word# -> Word# -> Int#"- , "template" : "(~ARG[0] > ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.geWord#"- , "kind" : "Expression"- , "type" : "geWord# :: Word# -> Word# -> Int#"- , "template" : "(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.eqWord#"- , "kind" : "Expression"- , "type" : "eqWord# :: Word# -> Word# -> Int#"- , "template" : "(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.neWord#"- , "kind" : "Expression"- , "type" : "neWord# :: Word# -> Word# -> Int#"- , "template" : "(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ltWord#"- , "kind" : "Expression"- , "type" : "ltWord# :: Word# -> Word# -> Int#"- , "template" : "(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.leWord#"- , "kind" : "Expression"- , "type" : "leWord# :: Word# -> Word# -> Int#"- , "template" : "(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.byteSwap16#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "byteSwap16# :: Word# -> Word#"- , "template" :-"// byteSwap16 begin~IF ~IW64 ~THEN-assign ~RESULT = {~VAR[w][0][63:16],~VAR[w][0][7:0],~VAR[w][0][15:8]};~ELSE-assign ~RESULT = {~VAR[w][0][31:16],~VAR[w][0][7:0],~VAR[w][0][15:8]};~FI-// byteSwap16 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.byteSwap32#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "byteSwap32# :: Word# -> Word#"- , "template" :-"// byteSwap32 begin~IF ~IW64 ~THEN-assign ~RESULT = {~VAR[w][0][63:32],~VAR[w][0][7:0],~VAR[w][0][15:8],~VAR[w][0][23:16],~VAR[w][0][31:24]};~ELSE-assign ~RESULT = {~VAR[w][0][7:0],~VAR[w][0][15:8],~VAR[w][0][23:16],~VAR[w][0][31:24]};~FI-// byteSwap32 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.byteSwap64#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "byteSwap64# :: Word# -> Word#"- , "template" :-"// byteSwap64 begin-assign ~RESULT = {~VAR[w][0][7:0],~VAR[w][0][15:8],~VAR[w][0][23:16],~VAR[w][0][31:24]- ,~VAR[w][0][39:32],~VAR[w][0][47:40],~VAR[w][0][55:48],~VAR[w][0][63:56]};-// byteSwap64 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.byteSwap#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "byteSwap# :: Word# -> Word#"- , "template" :-"// byteSwap begin~IF ~IW64 ~THEN-assign ~RESULT = {~VAR[w][0][7:0],~VAR[w][0][15:8],~VAR[w][0][23:16],~VAR[w][0][31:24]- ,~VAR[w][0][39:32],~VAR[w][0][47:40],~VAR[w][0][55:48],~VAR[w][0][63:56]};~ELSE-assign ~RESULT = {~VAR[w][0][7:0],~VAR[w][0][15:8],~VAR[w][0][23:16],~VAR[w][0][31:24]};~FI-// byteSwap end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.narrow8Int#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "narrow8Int# :: Int# -> Int#"- , "template" :-"// narrow8Int begin-assign ~RESULT = $signed(~VAR[i][0][7:0]);-// narrow8Int end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.narrow16Int#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "narrow16Int# :: Int# -> Int#"- , "template" :-"// narrow16Int begin-assign ~RESULT = $signed(~VAR[i][0][15:0]);-// narrow16Int end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.narrow32Int#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "narrow32Int# :: Int# -> Int#"- , "template" :-"// narrow32Int begin-assign ~RESULT = $signed(~VAR[i][0][31:0]);-// narrow32Int end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.narrow8Word#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "narrow8Int# :: Word# -> Word#"- , "template" :-"// narrow8Word begin-assign ~RESULT = $unsigned(~VAR[w][0][7:0]);-// narrow8Word end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.narrow16Word#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "narrow16Word# :: Word# -> Word#"- , "template" :-"// narrow16Word begin-assign ~RESULT = $unsigned(~VAR[w][0][15:0]);-// narrow16Word end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.narrow32Word#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "narrow32Int# :: Word# -> Word#"- , "template" :-"// narrow32Word begin-assign ~RESULT = $unsigned(~VAR[w][0][31:0]);-// narrow32Word end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.bitReverse#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "bitReverse# :: Word# -> Word#"- , "template" :-"// bitReverse begin-genvar ~GENSYM[i][0];-~GENERATE-for (~SYM[0] = 0; ~SYM[0] < ~IF ~IW64 ~THEN 64 ~ELSE 32 ~FI; ~SYM[0]=~SYM[0]+1) begin : ~GENSYM[bitReverse][2]- assign ~RESULT[~SYM[0]] = ~VAR[x][0][~IF ~IW64 ~THEN 63 ~ELSE 31 ~FI-~SYM[0]];-end-~ENDGENERATE-// bitReverse end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.bitReverse8#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "bitReverse8# :: Word# -> Word#"- , "template" :-"// bitReverse8 begin-genvar ~GENSYM[i][0];-~GENERATE-for (~SYM[0] = 0; ~SYM[0] < 8; ~SYM[0]=~SYM[0]+1) begin : ~GENSYM[bitReverse8][2]- assign ~RESULT[~SYM[0]] = ~VAR[x][0][7-~SYM[0]];-end-~ENDGENERATE-// bitReverse8 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.bitReverse16#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "bitReverse16# :: Word# -> Word#"- , "template" :-"// bitReverse16 begin-genvar ~GENSYM[i][0];-~GENERATE-for (~SYM[0] = 0; ~SYM[0] < 16; ~SYM[0]=~SYM[0]+1) begin : ~GENSYM[bitReverse16][2]- assign ~RESULT[~SYM[0]] = ~VAR[x][0][15-~SYM[0]];-end-~ENDGENERATE-// bitReverse16 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.bitReverse32#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "bitReverse32# :: Word# -> Word#"- , "template" :-"// bitReverse32 begin-genvar ~GENSYM[i][0];-~GENERATE-for (~SYM[0] = 0; ~SYM[0] < 32; ~SYM[0]=~SYM[0]+1) begin : ~GENSYM[bitReverse32][2]- assign ~RESULT[~SYM[0]] = ~VAR[x][0][31-~SYM[0]];-end-~ENDGENERATE-// bitReverse32 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.bitReverse64#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "bitReverse64# :: Word# -> Word#"- , "template" :-"// bitReverse64 begin-genvar ~GENSYM[i][0];-~GENERATE-for (~SYM[0] = 0; ~SYM[0] < 64; ~SYM[0]=~SYM[0]+1) begin : ~GENSYM[bitReverse64][2]- assign ~RESULT[~SYM[0]] = ~VAR[x][0][63-~SYM[0]];-end-~ENDGENERATE-// bitReverse64 end"- }- }-]
+ prims/commonverilog/GHC_Prim.primitives.yaml view
@@ -0,0 +1,434 @@+- BlackBox:+ name: GHC.Prim.gtChar#+ kind: Expression+ type: 'gtChar# :: Char#+ -> Char# -> Int#'+ template: '(~ARG[0] > ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+- BlackBox:+ name: GHC.Prim.geChar#+ kind: Expression+ type: 'geChar# :: Char#+ -> Char# -> Int#'+ template: '(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+- BlackBox:+ name: GHC.Prim.eqChar#+ kind: Expression+ type: 'eqChar# :: Char#+ -> Char# -> Int#'+ template: '(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+- BlackBox:+ name: GHC.Prim.neChar#+ kind: Expression+ type: 'neChar# :: Char#+ -> Char# -> Int#'+ template: '(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+- BlackBox:+ name: GHC.Prim.ltChar#+ kind: Expression+ type: 'ltChar# :: Char#+ -> Char# -> Int#'+ template: '(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+- BlackBox:+ name: GHC.Prim.leChar#+ kind: Expression+ type: 'leChar# :: Char#+ -> Char# -> Int#'+ template: '(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+- BlackBox:+ name: GHC.Prim.ord#+ kind: Expression+ type: 'ord :: Char# ->+ Int#'+ template: $signed({{(~SIZE[~TYPO]-~SIZE[~TYP[0]]) {1'b0}},~VAR[c][0]})+- BlackBox:+ name: GHC.Prim.*#+ kind: Expression+ type: '(*#) :: Int# ->+ Int# -> Int#'+ template: ~ARG[0] * ~ARG[1]+- BlackBox:+ name: GHC.Prim.remInt#+ kind: Expression+ type: 'remInt# :: Int#+ -> Int# -> Int#'+ template: ~ARG[0] % ~ARG[1]+- BlackBox:+ name: GHC.Prim.andI#+ kind: Expression+ type: 'andI# :: Int# ->+ Int# -> Int#'+ template: ~ARG[0] & ~ARG[1]+- BlackBox:+ name: GHC.Prim.orI#+ kind: Expression+ type: 'orI# :: Int# ->+ Int# -> Int#'+ template: ~ARG[0] | ~ARG[1]+- BlackBox:+ name: GHC.Prim.xorI#+ kind: Expression+ type: 'xorI# :: Int# ->+ Int# -> Int#'+ template: ~ARG[0] ^ ~ARG[1]+- BlackBox:+ name: GHC.Prim.notI#+ kind: Expression+ type: 'notI# :: Int# ->+ Int#'+ template: ~ ~ARG[0]+- BlackBox:+ name: GHC.Prim.negateInt#+ kind: Expression+ type: 'negateInt# :: Int#+ -> Int#'+ template: -(~ARG[0])+- BlackBox:+ name: GHC.Prim.>#+ kind: Expression+ type: '(>#) :: Int# ->+ Int# -> Int#'+ template: '(~ARG[0] > ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+- BlackBox:+ name: GHC.Prim.>=#+ kind: Expression+ type: '(>=#) :: Int# ->+ Int# -> Int#'+ template: '(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+- BlackBox:+ name: GHC.Prim.==#+ kind: Expression+ type: '(==) :: Int# ->+ Int# -> Int#'+ template: '(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+- BlackBox:+ name: GHC.Prim./=#+ kind: Expression+ type: '(/=#) :: Int# ->+ Int# -> Int#'+ template: '(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+- BlackBox:+ name: GHC.Prim.<#+ kind: Expression+ type: '(<#) :: Int# ->+ Int# -> Int#'+ template: '(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+- BlackBox:+ name: GHC.Prim.<=#+ kind: Expression+ type: '(<=#) :: Int# ->+ Int# -> Int#'+ template: '(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+- BlackBox:+ name: GHC.Prim.chr#+ kind: Expression+ type: 'ord :: Int# ->+ Char#'+ template: $unsigned(~VAR[i][0][0+:~SIZE[~TYPO]])+- BlackBox:+ name: GHC.Prim.int2Word#+ kind: Expression+ type: 'int2Word# :: Int#+ -> Word#'+ template: $unsigned(~ARG[0])+ workInfo: Never+- BlackBox:+ name: GHC.Prim.uncheckedIShiftL#+ kind: Expression+ type: 'uncheckedIShiftL#+ :: Int# -> Int# -> Int#'+ template: ~ARG[0] <<< ~ARG[1]+- BlackBox:+ name: GHC.Prim.uncheckedIShiftRA#+ kind: Expression+ type: 'uncheckedIShiftRA#+ :: Int# -> Int# -> Int#'+ template: ~ARG[0] >>> ~ARG[1]+- BlackBox:+ name: GHC.Prim.uncheckedIShiftRL#+ kind: Expression+ type: 'uncheckedIShiftRL#+ :: Int# -> Int# -> Int#'+ template: ~ARG[0] >> ~ARG[1]+- BlackBox:+ name: GHC.Prim.timesWord#+ kind: Expression+ type: 'timesWord# :: Word#+ -> Word# -> Word#'+ template: ~ARG[0] * ~ARG[1]+- BlackBox:+ name: GHC.Prim.remWord#+ kind: Expression+ type: 'remWord# :: Word#+ -> Word# -> Word#'+ template: ~ARG[0] % ~ARG[1]+- BlackBox:+ name: GHC.Prim.and#+ kind: Expression+ type: 'and# :: Word# ->+ Word# -> Word#'+ template: ~ARG[0] & ~ARG[1]+- BlackBox:+ name: GHC.Prim.or#+ kind: Expression+ type: 'or# :: Word# ->+ Word# -> Word#'+ template: ~ARG[0] | ~ARG[1]+- BlackBox:+ name: GHC.Prim.xor#+ kind: Expression+ type: 'xor# :: Word# ->+ Word# -> Word#'+ template: ~ARG[0] ^ ~ARG[1]+- BlackBox:+ name: GHC.Prim.not#+ kind: Expression+ type: 'not# :: Word# ->+ Word#'+ template: ~ ~ARG[0]+- BlackBox:+ name: GHC.Prim.uncheckedShiftL#+ kind: Expression+ type: 'uncheckedShiftL#+ :: Word# -> Int# -> Word#'+ template: ~ARG[0] << ~ARG[1]+- BlackBox:+ name: GHC.Prim.uncheckedShiftRL#+ kind: Expression+ type: 'uncheckedShiftRL#+ :: Word# -> Int# -> Word#'+ template: ~ARG[0] >> ~ARG[1]+- BlackBox:+ name: GHC.Prim.word2Int#+ kind: Expression+ type: 'int2Word# :: Word#+ -> Int#'+ template: $signed(~ARG[0])+ workInfo: Never+- BlackBox:+ name: GHC.Prim.gtWord#+ kind: Expression+ type: 'gtWord# :: Word#+ -> Word# -> Int#'+ template: '(~ARG[0] > ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+- BlackBox:+ name: GHC.Prim.geWord#+ kind: Expression+ type: 'geWord# :: Word#+ -> Word# -> Int#'+ template: '(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+- BlackBox:+ name: GHC.Prim.eqWord#+ kind: Expression+ type: 'eqWord# :: Word#+ -> Word# -> Int#'+ template: '(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+- BlackBox:+ name: GHC.Prim.neWord#+ kind: Expression+ type: 'neWord# :: Word#+ -> Word# -> Int#'+ template: '(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+- BlackBox:+ name: GHC.Prim.ltWord#+ kind: Expression+ type: 'ltWord# :: Word#+ -> Word# -> Int#'+ template: '(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+- BlackBox:+ name: GHC.Prim.leWord#+ kind: Expression+ type: 'leWord# :: Word#+ -> Word# -> Int#'+ template: '(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0'+- BlackBox:+ name: GHC.Prim.byteSwap16#+ kind: Declaration+ type: 'byteSwap16# ::+ Word# -> Word#'+ template: |-+ // byteSwap16 begin~IF ~IW64 ~THEN+ assign ~RESULT = {~VAR[w][0][63:16],~VAR[w][0][7:0],~VAR[w][0][15:8]};~ELSE+ assign ~RESULT = {~VAR[w][0][31:16],~VAR[w][0][7:0],~VAR[w][0][15:8]};~FI+ // byteSwap16 end+ workInfo: Never+- BlackBox:+ name: GHC.Prim.byteSwap32#+ kind: Declaration+ type: 'byteSwap32# ::+ Word# -> Word#'+ template: |-+ // byteSwap32 begin~IF ~IW64 ~THEN+ assign ~RESULT = {~VAR[w][0][63:32],~VAR[w][0][7:0],~VAR[w][0][15:8],~VAR[w][0][23:16],~VAR[w][0][31:24]};~ELSE+ assign ~RESULT = {~VAR[w][0][7:0],~VAR[w][0][15:8],~VAR[w][0][23:16],~VAR[w][0][31:24]};~FI+ // byteSwap32 end+ workInfo: Never+- BlackBox:+ name: GHC.Prim.byteSwap64#+ kind: Declaration+ type: 'byteSwap64# ::+ Word# -> Word#'+ template: |-+ // byteSwap64 begin+ assign ~RESULT = {~VAR[w][0][7:0],~VAR[w][0][15:8],~VAR[w][0][23:16],~VAR[w][0][31:24]+ ,~VAR[w][0][39:32],~VAR[w][0][47:40],~VAR[w][0][55:48],~VAR[w][0][63:56]};+ // byteSwap64 end+ workInfo: Never+- BlackBox:+ name: GHC.Prim.byteSwap#+ kind: Declaration+ type: 'byteSwap# :: Word#+ -> Word#'+ template: |-+ // byteSwap begin~IF ~IW64 ~THEN+ assign ~RESULT = {~VAR[w][0][7:0],~VAR[w][0][15:8],~VAR[w][0][23:16],~VAR[w][0][31:24]+ ,~VAR[w][0][39:32],~VAR[w][0][47:40],~VAR[w][0][55:48],~VAR[w][0][63:56]};~ELSE+ assign ~RESULT = {~VAR[w][0][7:0],~VAR[w][0][15:8],~VAR[w][0][23:16],~VAR[w][0][31:24]};~FI+ // byteSwap end+ workInfo: Never+- BlackBox:+ name: GHC.Prim.narrow8Int#+ kind: Declaration+ type: 'narrow8Int# ::+ Int# -> Int#'+ template: |-+ // narrow8Int begin+ assign ~RESULT = $signed(~VAR[i][0][7:0]);+ // narrow8Int end+ workInfo: Never+- BlackBox:+ name: GHC.Prim.narrow16Int#+ kind: Declaration+ type: 'narrow16Int# ::+ Int# -> Int#'+ template: |-+ // narrow16Int begin+ assign ~RESULT = $signed(~VAR[i][0][15:0]);+ // narrow16Int end+ workInfo: Never+- BlackBox:+ name: GHC.Prim.narrow32Int#+ kind: Declaration+ type: 'narrow32Int# ::+ Int# -> Int#'+ template: |-+ // narrow32Int begin+ assign ~RESULT = $signed(~VAR[i][0][31:0]);+ // narrow32Int end+ workInfo: Never+- BlackBox:+ name: GHC.Prim.narrow8Word#+ kind: Declaration+ type: 'narrow8Int# ::+ Word# -> Word#'+ template: |-+ // narrow8Word begin+ assign ~RESULT = $unsigned(~VAR[w][0][7:0]);+ // narrow8Word end+ workInfo: Never+- BlackBox:+ name: GHC.Prim.narrow16Word#+ kind: Declaration+ type: 'narrow16Word# ::+ Word# -> Word#'+ template: |-+ // narrow16Word begin+ assign ~RESULT = $unsigned(~VAR[w][0][15:0]);+ // narrow16Word end+ workInfo: Never+- BlackBox:+ name: GHC.Prim.narrow32Word#+ kind: Declaration+ type: 'narrow32Int# ::+ Word# -> Word#'+ template: |-+ // narrow32Word begin+ assign ~RESULT = $unsigned(~VAR[w][0][31:0]);+ // narrow32Word end+ workInfo: Never+- BlackBox:+ name: GHC.Prim.bitReverse#+ kind: Declaration+ type: 'bitReverse# ::+ Word# -> Word#'+ template: |-+ // bitReverse begin+ genvar ~GENSYM[i][0];+ ~GENERATE+ for (~SYM[0] = 0; ~SYM[0] < ~IF ~IW64 ~THEN 64 ~ELSE 32 ~FI; ~SYM[0]=~SYM[0]+1) begin : ~GENSYM[bitReverse][2]+ assign ~RESULT[~SYM[0]] = ~VAR[x][0][~IF ~IW64 ~THEN 63 ~ELSE 31 ~FI-~SYM[0]];+ end+ ~ENDGENERATE+ // bitReverse end+ workInfo: Never+- BlackBox:+ name: GHC.Prim.bitReverse8#+ kind: Declaration+ type: 'bitReverse8# ::+ Word# -> Word#'+ template: |-+ // bitReverse8 begin+ genvar ~GENSYM[i][0];+ ~GENERATE+ for (~SYM[0] = 0; ~SYM[0] < 8; ~SYM[0]=~SYM[0]+1) begin : ~GENSYM[bitReverse8][2]+ assign ~RESULT[~SYM[0]] = ~VAR[x][0][7-~SYM[0]];+ end+ ~ENDGENERATE+ // bitReverse8 end+ workInfo: Never+- BlackBox:+ name: GHC.Prim.bitReverse16#+ kind: Declaration+ type: 'bitReverse16# ::+ Word# -> Word#'+ template: |-+ // bitReverse16 begin+ genvar ~GENSYM[i][0];+ ~GENERATE+ for (~SYM[0] = 0; ~SYM[0] < 16; ~SYM[0]=~SYM[0]+1) begin : ~GENSYM[bitReverse16][2]+ assign ~RESULT[~SYM[0]] = ~VAR[x][0][15-~SYM[0]];+ end+ ~ENDGENERATE+ // bitReverse16 end+ workInfo: Never+- BlackBox:+ name: GHC.Prim.bitReverse32#+ kind: Declaration+ type: 'bitReverse32# ::+ Word# -> Word#'+ template: |-+ // bitReverse32 begin+ genvar ~GENSYM[i][0];+ ~GENERATE+ for (~SYM[0] = 0; ~SYM[0] < 32; ~SYM[0]=~SYM[0]+1) begin : ~GENSYM[bitReverse32][2]+ assign ~RESULT[~SYM[0]] = ~VAR[x][0][31-~SYM[0]];+ end+ ~ENDGENERATE+ // bitReverse32 end+ workInfo: Never+- BlackBox:+ name: GHC.Prim.bitReverse64#+ kind: Declaration+ type: 'bitReverse64# ::+ Word# -> Word#'+ template: |-+ // bitReverse64 begin+ genvar ~GENSYM[i][0];+ ~GENERATE+ for (~SYM[0] = 0; ~SYM[0] < 64; ~SYM[0]=~SYM[0]+1) begin : ~GENSYM[bitReverse64][2]+ assign ~RESULT[~SYM[0]] = ~VAR[x][0][63-~SYM[0]];+ end+ ~ENDGENERATE+ // bitReverse64 end+ workInfo: Never+- BlackBox:+ name: GHC.Prim.quotInt#+ kind: Expression+ type: 'quotInt# :: Int#+ -> Int# -> Int#'+ template: ~ARG[0] / ~ARG[1]+- BlackBox:+ name: GHC.Prim.quotWord#+ kind: Expression+ type: 'quotWord# :: Word#+ -> Word# -> Word#'+ template: ~ARG[0] / ~ARG[1]
− prims/commonverilog/GHC_Word.primitives
@@ -1,30 +0,0 @@-[- {- "BlackBoxHaskell": {- "name": "GHC.Word.W8#",- "workInfo" : "Never",- "templateFunction": "Clash.Primitives.GHC.Word.wordTF"- }- },- {- "BlackBoxHaskell": {- "name": "GHC.Word.W16#",- "workInfo" : "Never",- "templateFunction": "Clash.Primitives.GHC.Word.wordTF"- }- },- {- "BlackBoxHaskell": {- "name": "GHC.Word.W32#",- "workInfo" : "Never",- "templateFunction": "Clash.Primitives.GHC.Word.wordTF"- }- },- {- "BlackBoxHaskell": {- "name": "GHC.Word.W64#",- "workInfo" : "Never",- "templateFunction": "Clash.Primitives.GHC.Word.wordTF"- }- }-]
+ prims/commonverilog/GHC_Word.primitives.yaml view
@@ -0,0 +1,16 @@+- BlackBoxHaskell:+ name: GHC.Word.W8#+ templateFunction: Clash.Primitives.GHC.Word.wordTF+ workInfo: Never+- BlackBoxHaskell:+ name: GHC.Word.W16#+ templateFunction: Clash.Primitives.GHC.Word.wordTF+ workInfo: Never+- BlackBoxHaskell:+ name: GHC.Word.W32#+ templateFunction: Clash.Primitives.GHC.Word.wordTF+ workInfo: Never+- BlackBoxHaskell:+ name: GHC.Word.W64#+ templateFunction: Clash.Primitives.GHC.Word.wordTF+ workInfo: Never
− prims/systemverilog/Clash_Explicit_BlockRam.primitives
@@ -1,140 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Explicit.BlockRam.blockRam#"- , "kind" : "Declaration"- , "type" :-"blockRam#- :: ( KnownDomain dom ARG[0]- , HasCallStack -- ARG[1]- , Undefined a ) -- ARG[2]- => Clock dom -- clk, ARG[3]- -> Enable dom -- en, ARG[4]- -> Vec n a -- init, ARG[5]- -> Signal dom Int -- rd, ARG[6]- -> Signal dom Bool -- wren, ARG[7]- -> Signal dom Int -- wr, ARG[8]- -> Signal dom a -- din, ARG[9]- -> Signal dom a"- , "template" :-"// blockRam begin-~SIGD[~GENSYM[RAM][1]][5];-logic [~SIZE[~TYP[9]]-1:0] ~GENSYM[~RESULT_q][2];-initial begin- ~SYM[1] = ~CONST[5];-end~IF ~ISACTIVEENABLE[4] ~THEN-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~GENSYM[~COMPNAME_blockRam][3]~IF ~VIVADO ~THEN- if (~ARG[4]) begin- if (~ARG[7]) begin- ~SYM[1][~ARG[8]] <= ~TOBV[~ARG[9]][~TYP[9]];- end- ~SYM[2] <= ~SYM[1][~ARG[6]];- end~ELSE- if (~ARG[7] & ~ARG[4]) begin- ~SYM[1][~ARG[8]] <= ~TOBV[~ARG[9]][~TYP[9]];- end- if (~ARG[4]) begin- ~SYM[2] <= ~SYM[1][~ARG[6]];- end~FI-end~ELSE-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~SYM[3]- if (~ARG[7]) begin- ~SYM[1][~ARG[8]] <= ~TOBV[~ARG[9]][~TYP[9]];- end- ~SYM[2] <= ~SYM[1][~ARG[6]];-end~FI-assign ~RESULT = ~FROMBV[~SYM[2]][~TYP[9]];-// blockRam end"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.BlockRam.blockRamU#"- , "kind" : "Declaration"- , "type" :-"blockRamU#- :: ( KnownDomain dom ARG[0]- , HasCallStack -- ARG[1]- , Undefined a ) -- ARG[2]- => Clock dom -- clk, ARG[3]- -> Enable dom -- en, ARG[4]- -> SNat n -- len, ARG[5]- -> Signal dom Int -- rd, ARG[6]- -> Signal dom Bool -- wren, ARG[7]- -> Signal dom Int -- wr, ARG[8]- -> Signal dom a -- din, ARG[9]- -> Signal dom a"- , "template" :-"// blockRamU begin,-~TYPO ~GENSYM[~RESULT_RAM][1] [0:~LIT[5]-1];-logic [~SIZE[~TYP[9]]-1:0] ~GENSYM[~RESULT_q][2];~IF ~ISACTIVEENABLE[4] ~THEN-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~GENSYM[~COMPNAME_blockRam][3]~IF ~VIVADO ~THEN- if (~ARG[4]) begin- if (~ARG[7]) begin- ~SYM[1][~ARG[8]] <= ~TOBV[~ARG[9]][~TYP[9]];- end- ~SYM[2] <= ~SYM[1][~ARG[6]];- end~ELSE- if (~ARG[7] & ~ARG[4]) begin- ~SYM[1][~ARG[8]] <= ~TOBV[~ARG[9]][~TYP[9]];- end- if (~ARG[4]) begin- ~SYM[2] <= ~SYM[1][~ARG[6]];- end~FI-end~ELSE-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~SYM[3]- if (~ARG[7]) begin- ~SYM[1][~ARG[8]] <= ~TOBV[~ARG[9]][~TYP[9]];- end- ~SYM[2] <= ~SYM[1][~ARG[6]];-end~FI-assign ~RESULT = ~FROMBV[~SYM[2]][~TYP[9]];-// blockRamU end"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.BlockRam.blockRam1#"- , "kind" : "Declaration"- , "type" :-"blockRam1#- :: ( KnownDomain dom ARG[0]- , HasCallStack -- ARG[1]- , Undefined a ) -- ARG[2]- => Clock dom -- clk, ARG[3]- -> Enable dom -- en, ARG[4]- -> SNat n -- len, ARG[5]- -> a -- init, ARG[6]- -> Signal dom Int -- rd, ARG[7]- -> Signal dom Bool -- wren, ARG[8]- -> Signal dom Int -- wr, ARG[9]- -> Signal dom a -- din, ARG[10]- -> Signal dom a"- , "template" :-"// blockRam1 begin,-~TYPO ~GENSYM[~RESULT_RAM][1] [0:~LIT[5]-1];-logic [~SIZE[~TYP[10]]-1:0] ~GENSYM[~RESULT_q][2];-initial begin- ~SYM[1] = '{default: ~CONST[6]};-end~IF ~ISACTIVEENABLE[4] ~THEN-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~GENSYM[~COMPNAME_blockRam][3]~IF ~VIVADO ~THEN- if (~ARG[4]) begin- if (~ARG[8]) begin- ~SYM[1][~ARG[9]] <= ~TOBV[~ARG[10]][~TYP[10]];- end- ~SYM[2] <= ~SYM[1][~ARG[7]];- end~ELSE- if (~ARG[8] & ~ARG[4]) begin- ~SYM[1][~ARG[9]] <= ~TOBV[~ARG[10]][~TYP[10]];- end- if (~ARG[4]) begin- ~SYM[2] <= ~SYM[1][~ARG[7]];- end~FI-end~ELSE-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~SYM[3]- if (~ARG[8]) begin- ~SYM[1][~ARG[9]] <= ~TOBV[~ARG[10]][~TYP[10]];- end- ~SYM[2] <= ~SYM[1][~ARG[7]];-end~FI-assign ~RESULT = ~FROMBV[~SYM[2]][~TYP[10]];-// blockRam1 end"- }- }-]
+ prims/systemverilog/Clash_Explicit_BlockRam.primitives.yaml view
@@ -0,0 +1,190 @@+- BlackBox:+ name: Clash.Explicit.BlockRam.blockRam#+ kind: Declaration+ type: |-+ blockRam#+ :: ( KnownDomain dom ARG[0]+ , HasCallStack -- ARG[1]+ , Undefined a ) -- ARG[2]+ => Clock dom -- clk, ARG[3]+ -> Enable dom -- en, ARG[4]+ -> Vec n a -- init, ARG[5]+ -> Signal dom Int -- rd, ARG[6]+ -> Signal dom Bool -- wren, ARG[7]+ -> Signal dom Int -- wr, ARG[8]+ -> Signal dom a -- din, ARG[9]+ -> Signal dom a+ template: |-+ // blockRam begin+ ~SIGD[~GENSYM[RAM][1]][5];+ logic [~SIZE[~TYP[9]]-1:0] ~GENSYM[~RESULT_q][2];+ initial begin+ ~SYM[1] = ~CONST[5];+ end~IF ~ISACTIVEENABLE[4] ~THEN+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~GENSYM[~COMPNAME_blockRam][3]~IF ~VIVADO ~THEN+ if (~ARG[4]) begin+ if (~ARG[7]) begin+ ~SYM[1][~ARG[8]] <= ~TOBV[~ARG[9]][~TYP[9]];+ end+ ~SYM[2] <= ~SYM[1][~ARG[6]];+ end~ELSE+ if (~ARG[7] & ~ARG[4]) begin+ ~SYM[1][~ARG[8]] <= ~TOBV[~ARG[9]][~TYP[9]];+ end+ if (~ARG[4]) begin+ ~SYM[2] <= ~SYM[1][~ARG[6]];+ end~FI+ end~ELSE+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~SYM[3]+ if (~ARG[7]) begin+ ~SYM[1][~ARG[8]] <= ~TOBV[~ARG[9]][~TYP[9]];+ end+ ~SYM[2] <= ~SYM[1][~ARG[6]];+ end~FI+ assign ~RESULT = ~FROMBV[~SYM[2]][~TYP[9]];+ // blockRam end+- BlackBox:+ name: Clash.Explicit.BlockRam.blockRamU#+ kind: Declaration+ type: |-+ blockRamU#+ :: ( KnownDomain dom ARG[0]+ , HasCallStack -- ARG[1]+ , Undefined a ) -- ARG[2]+ => Clock dom -- clk, ARG[3]+ -> Enable dom -- en, ARG[4]+ -> SNat n -- len, ARG[5]+ -> Signal dom Int -- rd, ARG[6]+ -> Signal dom Bool -- wren, ARG[7]+ -> Signal dom Int -- wr, ARG[8]+ -> Signal dom a -- din, ARG[9]+ -> Signal dom a+ template: |-+ // blockRamU begin,+ ~TYPO ~GENSYM[~RESULT_RAM][1] [0:~LIT[5]-1];+ logic [~SIZE[~TYP[9]]-1:0] ~GENSYM[~RESULT_q][2];~IF ~ISACTIVEENABLE[4] ~THEN+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~GENSYM[~COMPNAME_blockRam][3]~IF ~VIVADO ~THEN+ if (~ARG[4]) begin+ if (~ARG[7]) begin+ ~SYM[1][~ARG[8]] <= ~TOBV[~ARG[9]][~TYP[9]];+ end+ ~SYM[2] <= ~SYM[1][~ARG[6]];+ end~ELSE+ if (~ARG[7] & ~ARG[4]) begin+ ~SYM[1][~ARG[8]] <= ~TOBV[~ARG[9]][~TYP[9]];+ end+ if (~ARG[4]) begin+ ~SYM[2] <= ~SYM[1][~ARG[6]];+ end~FI+ end~ELSE+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~SYM[3]+ if (~ARG[7]) begin+ ~SYM[1][~ARG[8]] <= ~TOBV[~ARG[9]][~TYP[9]];+ end+ ~SYM[2] <= ~SYM[1][~ARG[6]];+ end~FI+ assign ~RESULT = ~FROMBV[~SYM[2]][~TYP[9]];+ // blockRamU end+- BlackBox:+ name: Clash.Explicit.BlockRam.blockRam1#+ kind: Declaration+ type: |-+ blockRam1#+ :: ( KnownDomain dom ARG[0]+ , HasCallStack -- ARG[1]+ , Undefined a ) -- ARG[2]+ => Clock dom -- clk, ARG[3]+ -> Enable dom -- en, ARG[4]+ -> SNat n -- len, ARG[5]+ -> a -- init, ARG[6]+ -> Signal dom Int -- rd, ARG[7]+ -> Signal dom Bool -- wren, ARG[8]+ -> Signal dom Int -- wr, ARG[9]+ -> Signal dom a -- din, ARG[10]+ -> Signal dom a+ template: |-+ // blockRam1 begin,+ ~TYPO ~GENSYM[~RESULT_RAM][1] [0:~LIT[5]-1];+ logic [~SIZE[~TYP[10]]-1:0] ~GENSYM[~RESULT_q][2];+ initial begin+ ~SYM[1] = '{default: ~CONST[6]};+ end~IF ~ISACTIVEENABLE[4] ~THEN+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~GENSYM[~COMPNAME_blockRam][3]~IF ~VIVADO ~THEN+ if (~ARG[4]) begin+ if (~ARG[8]) begin+ ~SYM[1][~ARG[9]] <= ~TOBV[~ARG[10]][~TYP[10]];+ end+ ~SYM[2] <= ~SYM[1][~ARG[7]];+ end~ELSE+ if (~ARG[8] & ~ARG[4]) begin+ ~SYM[1][~ARG[9]] <= ~TOBV[~ARG[10]][~TYP[10]];+ end+ if (~ARG[4]) begin+ ~SYM[2] <= ~SYM[1][~ARG[7]];+ end~FI+ end~ELSE+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~SYM[3]+ if (~ARG[8]) begin+ ~SYM[1][~ARG[9]] <= ~TOBV[~ARG[10]][~TYP[10]];+ end+ ~SYM[2] <= ~SYM[1][~ARG[7]];+ end~FI+ assign ~RESULT = ~FROMBV[~SYM[2]][~TYP[10]];+ // blockRam1 end+- BlackBox:+ name: Clash.Explicit.BlockRam.trueDualPortBlockRam#+ kind: Declaration+ type: |-+ trueDualPortBlockRam# ::+ forall nAddrs domA domB a .+ ( HasCallStack ~ARG[0]+ , KnownNat nAddrs ~ARG[1]+ , KnownDomain domA ~ARG[2]+ , KnownDomain domB ~ARG[3]+ , NFDataX a ~ARG[4]+ ) =>++ Clock domA -> ~ARG[5]+ Signal domA Bool -> ~ARG[6]+ Signal domA Bool -> ~ARG[7]+ Signal domA (Index nAddrs) -> ~ARG[8]+ Signal domA a -> ~ARG[9]++ Clock domB -> ~ARG[10]+ Signal domB Bool -> ~ARG[11]+ Signal domB Bool -> ~ARG[12]+ Signal domB (Index nAddrs) -> ~ARG[13]+ Signal domB a -> ~ARG[14]+ (Signal domA a, Signal domB a)+ template: |-+ // trueDualPortBlockRam begin+ // Shared memory+ logic [~SIZE[~TYP[9]]-1:0] ~GENSYM[mem][0] [~LIT[1]-1:0];++ ~SIGD[~GENSYM[data_slow][1]][9];+ ~SIGD[~GENSYM[data_fast][2]][14];++ // Port A+ always @(~IF~ACTIVEEDGE[Rising][2]~THENposedge~ELSEnegedge~FI ~ARG[5]) begin+ if(~ARG[6]) begin+ ~SYM[1] <= ~SYM[0][~IF~SIZE[~TYP[8]]~THEN~ARG[8]~ELSE0~FI];+ if(~ARG[7]) begin+ ~SYM[1] <= ~ARG[9];+ ~SYM[0][~IF~SIZE[~TYP[8]]~THEN~ARG[8]~ELSE0~FI] <= ~ARG[9];+ end+ end+ end++ // Port B+ always @(~IF~ACTIVEEDGE[Rising][3]~THENposedge~ELSEnegedge~FI ~ARG[10]) begin+ if(~ARG[11]) begin+ ~SYM[2] <= ~SYM[0][~IF~SIZE[~TYP[13]]~THEN~ARG[13]~ELSE0~FI];+ if(~ARG[12]) begin+ ~SYM[2] <= ~ARG[14];+ ~SYM[0][~IF~SIZE[~TYP[13]]~THEN~ARG[13]~ELSE0~FI] <= ~ARG[14];+ end+ end+ end++ assign ~RESULT = {~SYM[1], ~SYM[2]};+ // end trueDualPortBlockRam
+ prims/systemverilog/Clash_Explicit_BlockRam_Blob.primitives.yaml view
@@ -0,0 +1,43 @@+- BlackBox:+ name: Clash.Explicit.BlockRam.Blob.blockRamBlob#+ kind: Declaration+ type: |-+ blockRamBlob#+ :: KnownDomain dom -- ARG[0]+ => Clock dom -- clk, ARG[1]+ -> Enable dom -- en, ARG[2]+ -> MemBlob n m -- init, ARG[3]+ -> Signal dom Int -- rd, ARG[4]+ -> Signal dom Bool -- wren, ARG[5]+ -> Signal dom Int -- wr, ARG[6]+ -> Signal dom (BitVector m) -- din, ARG[7]+ -> Signal dom (BitVector m)+ template: |-+ // blockRamBlob begin+ ~SIGD[~GENSYM[RAM][1]][3];+ logic [~SIZE[~TYP[7]]-1:0] ~GENSYM[~RESULT_q][2];+ initial begin+ ~SYM[1] = ~CONST[3];+ end~IF ~ISACTIVEENABLE[2] ~THEN+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[1]) begin : ~GENSYM[~COMPNAME_blockRam][3]~IF ~VIVADO ~THEN+ if (~ARG[2]) begin+ if (~ARG[5]) begin+ ~SYM[1][~ARG[6]] <= ~ARG[7];+ end+ ~SYM[2] <= ~SYM[1][~ARG[4]];+ end~ELSE+ if (~ARG[5] & ~ARG[2]) begin+ ~SYM[1][~ARG[6]] <= ~ARG[7];+ end+ if (~ARG[2]) begin+ ~SYM[2] <= ~SYM[1][~ARG[4]];+ end~FI+ end~ELSE+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[1]) begin : ~SYM[3]+ if (~ARG[5]) begin+ ~SYM[1][~ARG[6]] <= ~ARG[7];+ end+ ~SYM[2] <= ~SYM[1][~ARG[4]];+ end~FI+ assign ~RESULT = ~SYM[2];+ // blockRamBlob end
− prims/systemverilog/Clash_Explicit_BlockRam_File.primitives
@@ -1,52 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Explicit.BlockRam.File.blockRamFile#"- , "kind" : "Declaration"- , "type" :-"blockRamFile#- :: ( KnownDomain dom -- ARG[0]- , KnownNat m -- ARG[1]- , HasCallStack ) -- ARG[2]- => Clock dom -- clk, ARG[3]- => Enable dom -- en, ARG[4]- -> SNat n -- sz, ARG[5]- -> FilePath -- file, ARG[6]- -> Signal dom Int -- rd, ARG[7]- -> Signal dom Bool -- wren, ARG[8]- -> Signal dom Int -- wr, ARG[9]- -> Signal dom (BitVector m) -- din, ARG[10]- -> Signal dom (BitVector m)"- , "template" :-"// blockRamFile begin-~SIGDO[~GENSYM[RAM][1]] [0:~LIT[5]-1];-~SIGD[~GENSYM[~RESULT_q][2]][10];--initial begin- $readmemb(~FILE[~LIT[6]],~SYM[1]);-end-~IF ~ISACTIVEENABLE[4] ~THEN-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~GENSYM[~COMPNAME_blockRamFile][3]~IF ~VIVADO ~THEN- if (~ARG[4]) begin- if (~ARG[8]) begin- ~SYM[1][~ARG[9]] <= ~ARG[10];- end- ~SYM[2] <= ~SYM[1][~ARG[7]];- end~ELSE- if (~ARG[8] & ~ARG[4]) begin- ~SYM[1][~ARG[9]] <= ~ARG[10];- end- if (~ARG[4]) begin- ~SYM[2] <= ~SYM[1][~ARG[7]];- end~FI-end~ELSE-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~SYM[3]- if (~ARG[8]) begin- ~SYM[1][~ARG[9]] <= ~ARG[10];- end- ~SYM[2] <= ~SYM[1][~ARG[7]];-end~FI--assign ~RESULT = ~SYM[2];-// blockRamFile end"- }- }-]
+ prims/systemverilog/Clash_Explicit_BlockRam_File.primitives.yaml view
@@ -0,0 +1,49 @@+- BlackBox:+ name: Clash.Explicit.BlockRam.File.blockRamFile#+ kind: Declaration+ type: |-+ blockRamFile#+ :: ( KnownDomain dom -- ARG[0]+ , KnownNat m -- ARG[1]+ , HasCallStack ) -- ARG[2]+ => Clock dom -- clk, ARG[3]+ => Enable dom -- en, ARG[4]+ -> SNat n -- sz, ARG[5]+ -> FilePath -- file, ARG[6]+ -> Signal dom Int -- rd, ARG[7]+ -> Signal dom Bool -- wren, ARG[8]+ -> Signal dom Int -- wr, ARG[9]+ -> Signal dom (BitVector m) -- din, ARG[10]+ -> Signal dom (BitVector m)+ template: |-+ // blockRamFile begin+ ~SIGDO[~GENSYM[RAM][1]] [0:~LIT[5]-1];+ ~SIGD[~GENSYM[~RESULT_q][2]][10];++ initial begin+ $readmemb(~FILE[~LIT[6]],~SYM[1]);+ end+ ~IF ~ISACTIVEENABLE[4] ~THEN+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~GENSYM[~COMPNAME_blockRamFile][3]~IF ~VIVADO ~THEN+ if (~ARG[4]) begin+ if (~ARG[8]) begin+ ~SYM[1][~ARG[9]] <= ~ARG[10];+ end+ ~SYM[2] <= ~SYM[1][~ARG[7]];+ end~ELSE+ if (~ARG[8] & ~ARG[4]) begin+ ~SYM[1][~ARG[9]] <= ~ARG[10];+ end+ if (~ARG[4]) begin+ ~SYM[2] <= ~SYM[1][~ARG[7]];+ end~FI+ end~ELSE+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~SYM[3]+ if (~ARG[8]) begin+ ~SYM[1][~ARG[9]] <= ~ARG[10];+ end+ ~SYM[2] <= ~SYM[1][~ARG[7]];+ end~FI++ assign ~RESULT = ~SYM[2];+ // blockRamFile end
− prims/systemverilog/Clash_Explicit_DDR.primitives
@@ -1,93 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Explicit.DDR.ddrIn#"- , "kind" : "Declaration"- , "type" :-"ddrIn# :: forall a slow fast n pFast gated synchronous.- ( HasCallStack -- ARG[0]- , Undefined a -- ARG[1]- , KnownConfi~ fast domf -- ARG[2]- , KnownConfi~ slow doms -- ARG[3]- => Clock slow -- ARG[4], clk- -> Reset slow -- ARG[5], rst- -> Enable slow -- ARG[6], en- -> a -- ARG[7]- -> a -- ARG[8]- -> a -- ARG[9]- -> Signal fast a -- ARG[10]- -> Signal slow (a,a)"- , "template" :-"// ddrIn begin-~SIGD[~GENSYM[data_Pos][1]][9];-~SIGD[~GENSYM[data_Neg][2]][9];-~SIGD[~GENSYM[data_Neg_Latch][3]][9];-always @(~IF~ACTIVEEDGE[Rising][2]~THENposedge~ELSEnegedge~FI ~ARG[4]~IF~ISSYNC[3]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[5])~FI begin : ~GENSYM[~COMPNAME_ddrIn_pos][6]- if (~IF~ISACTIVEHIGH[2]~THEN~ARG[5]~ELSE! ~ARG[5]~FI) begin- ~SYM[1] <= ~ARG[8];- end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin- ~SYM[1] <= ~ARG[10];- end-end-always @(~IF~ACTIVEEDGE[Rising][2]~THENnegedge~ELSEposedge~FI ~ARG[4]~IF~ISSYNC[3]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[5])~FI begin : ~GENSYM[~COMPNAME_ddrIn_neg][7]- if (~IF~ISACTIVEHIGH[2]~THEN~ARG[5]~ELSE! ~ARG[5]~FI) begin- ~SYM[2] <= ~ARG[9];- end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin- ~SYM[2] <= ~ARG[10];- end-end-always @(~IF~ACTIVEEDGE[Rising][2]~THENposedge~ELSEnegedge~FI ~ARG[4]~IF~ISSYNC[3]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[5])~FI begin : ~GENSYM[~COMPNAME_ddrIn_neg_latch][8]- if (~IF~ISACTIVEHIGH[2]~THEN~ARG[5]~ELSE! ~ARG[5]~FI) begin- ~SYM[3] <= ~ARG[7];- end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin- ~SYM[3] <= ~SYM[2];- end-end--assign ~RESULT = {~SYM[3], ~SYM[1]};-// ddrIn end"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.DDR.ddrOut#"- , "kind" : "Declaration"- , "type" :-"ddrOut# :: ( HasCallStack -- ARG[0]- , Undefined a -- ARG[1]- , KnownConfi~ fast domf -- ARG[2]- , KnownConfi~ slow doms -- ARG[3]- => Clock slow -- ARG[4]- -> Reset slow -- ARG[5]- -> Enable slow -- ARG[6]- -> a -- ARG[7]- -> Signal slow a -- ARG[8]- -> Signal slow a -- ARG[9]- -> Signal fast a"- , "template" :-"// ddrOut begin-~SIGD[~GENSYM[data_Pos][1]][7];-~SIGD[~GENSYM[data_Neg][2]][7];-always @(~IF~ACTIVEEDGE[Rising][2]~THENposedge~ELSEnegedge~FI ~ARG[4]~IF~ISSYNC[3]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[5])~FI begin : ~GENSYM[~COMPNAME_ddrOut_pos][5]- if (~IF~ISACTIVEHIGH[2]~THEN~ARG[5]~ELSE! ~ARG[5]~FI) begin- ~SYM[1] <= ~ARG[7];- end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin- ~SYM[1] <= ~ARG[8];- end-end-always @(~IF~ACTIVEEDGE[Rising][2]~THENposedge~ELSEnegedge~FI ~ARG[4]~IF~ISSYNC[3]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[5])~FI begin : ~GENSYM[~COMPNAME_ddrOut_neg][6]- if (~IF~ISACTIVEHIGH[2]~THEN~ARG[5]~ELSE! ~ARG[5]~FI) begin- ~SYM[2] <= ~ARG[7];- end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin- ~SYM[2] <= ~ARG[9];- end-end--always @(*) begin- if (~ARG[4]) begin- ~RESULT = ~IF~ACTIVEEDGE[Rising][2]~THEN~SYM[1]~ELSE~SYM[2]~FI;- end else begin- ~RESULT = ~IF~ACTIVEEDGE[Rising][2]~THEN~SYM[2]~ELSE~SYM[1]~FI;- end-end-// ddrOut end"- }- }-]
+ prims/systemverilog/Clash_Explicit_DDR.primitives.yaml view
@@ -0,0 +1,88 @@+- BlackBox:+ name: Clash.Explicit.DDR.ddrIn#+ kind: Declaration+ type: |-+ ddrIn# :: forall a slow fast n pFast gated synchronous.+ ( HasCallStack -- ARG[0]+ , Undefined a -- ARG[1]+ , KnownConfi~ fast domf -- ARG[2]+ , KnownConfi~ slow doms -- ARG[3]+ => Clock slow -- ARG[4], clk+ -> Reset slow -- ARG[5], rst+ -> Enable slow -- ARG[6], en+ -> a -- ARG[7]+ -> a -- ARG[8]+ -> a -- ARG[9]+ -> Signal fast a -- ARG[10]+ -> Signal slow (a,a)+ template: |-+ // ddrIn begin+ ~SIGD[~GENSYM[data_Pos][1]][9];+ ~SIGD[~GENSYM[data_Neg][2]][9];+ ~SIGD[~GENSYM[data_Neg_Latch][3]][9];+ always @(~IF~ACTIVEEDGE[Rising][2]~THENposedge~ELSEnegedge~FI ~ARG[4]~IF~ISSYNC[3]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[5])~FI begin : ~GENSYM[~COMPNAME_ddrIn_pos][6]+ if (~IF~ISACTIVEHIGH[2]~THEN~ARG[5]~ELSE! ~ARG[5]~FI) begin+ ~SYM[1] <= ~ARG[8];+ end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin+ ~SYM[1] <= ~ARG[10];+ end+ end+ always @(~IF~ACTIVEEDGE[Rising][2]~THENnegedge~ELSEposedge~FI ~ARG[4]~IF~ISSYNC[3]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[5])~FI begin : ~GENSYM[~COMPNAME_ddrIn_neg][7]+ if (~IF~ISACTIVEHIGH[2]~THEN~ARG[5]~ELSE! ~ARG[5]~FI) begin+ ~SYM[2] <= ~ARG[9];+ end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin+ ~SYM[2] <= ~ARG[10];+ end+ end+ always @(~IF~ACTIVEEDGE[Rising][2]~THENposedge~ELSEnegedge~FI ~ARG[4]~IF~ISSYNC[3]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[5])~FI begin : ~GENSYM[~COMPNAME_ddrIn_neg_latch][8]+ if (~IF~ISACTIVEHIGH[2]~THEN~ARG[5]~ELSE! ~ARG[5]~FI) begin+ ~SYM[3] <= ~ARG[7];+ end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin+ ~SYM[3] <= ~SYM[2];+ end+ end++ assign ~RESULT = {~SYM[3], ~SYM[1]};+ // ddrIn end+- BlackBox:+ name: Clash.Explicit.DDR.ddrOut#+ kind: Declaration+ type: |-+ ddrOut# :: ( HasCallStack -- ARG[0]+ , Undefined a -- ARG[1]+ , KnownConfi~ fast domf -- ARG[2]+ , KnownConfi~ slow doms -- ARG[3]+ => Clock slow -- ARG[4]+ -> Reset slow -- ARG[5]+ -> Enable slow -- ARG[6]+ -> a -- ARG[7]+ -> Signal slow a -- ARG[8]+ -> Signal slow a -- ARG[9]+ -> Signal fast a+ template: |-+ // ddrOut begin+ ~SIGD[~GENSYM[data_Pos][1]][7];+ ~SIGD[~GENSYM[data_Neg][2]][7];+ always @(~IF~ACTIVEEDGE[Rising][2]~THENposedge~ELSEnegedge~FI ~ARG[4]~IF~ISSYNC[3]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[5])~FI begin : ~GENSYM[~COMPNAME_ddrOut_pos][5]+ if (~IF~ISACTIVEHIGH[2]~THEN~ARG[5]~ELSE! ~ARG[5]~FI) begin+ ~SYM[1] <= ~ARG[7];+ end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin+ ~SYM[1] <= ~ARG[8];+ end+ end+ always @(~IF~ACTIVEEDGE[Rising][2]~THENposedge~ELSEnegedge~FI ~ARG[4]~IF~ISSYNC[3]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[5])~FI begin : ~GENSYM[~COMPNAME_ddrOut_neg][6]+ if (~IF~ISACTIVEHIGH[2]~THEN~ARG[5]~ELSE! ~ARG[5]~FI) begin+ ~SYM[2] <= ~ARG[7];+ end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin+ ~SYM[2] <= ~ARG[9];+ end+ end++ always @(*) begin+ if (~ARG[4]) begin+ ~RESULT = ~IF~ACTIVEEDGE[Rising][2]~THEN~SYM[1]~ELSE~SYM[2]~FI;+ end else begin+ ~RESULT = ~IF~ACTIVEEDGE[Rising][2]~THEN~SYM[2]~ELSE~SYM[1]~FI;+ end+ end+ // ddrOut end
− prims/systemverilog/Clash_Explicit_RAM.primitives
@@ -1,31 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Explicit.RAM.asyncRam#"- , "kind" : "Declaration"- , "type" :-"asyncRam#- :: ( HasCallStack -- ARG[0]- , KnownDomain wdom wconf -- ARG[1]- , KnownDomain rdom rconf ) -- ARG[2]- => Clock wdom -- ^ wclk, ARG[3]- -> Clock rdom -- ^ rclk, ARG[4]- -> Enable wdom -- ^ wen, ARG[5]- -> SNat n -- ^ sz, ARG[6]- -> Signal rdom Int -- ^ rd, ARG[7]- -> Signal wdom Bool -- ^ en, ARG[8]- -> Signal wdom Int -- ^ wr, ARG[9]- -> Signal wdom a -- ^ din, ARG[10]- -> Signal rdom a"- , "template" :-"// asyncRam begin-logic [~SIZE[~TYP[10]]-1:0] ~GENSYM[RAM][0] [0:~LIT[6]-1];-always @(~IF~ACTIVEEDGE[Rising][1]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~GENSYM[~COMPNAME_Ram][1]- if (~IF ~ISACTIVEENABLE[5] ~THEN ~ARG[5] & ~ELSE ~FI ~ARG[8]) begin- ~SYM[0][~ARG[9]] <= ~TOBV[~ARG[10]][~TYP[10]];- end-end--assign ~RESULT = ~FROMBV[~SYM[0][\\~ARG[7]\\]][~TYPO];-// asyncRam end"- }- }-]
+ prims/systemverilog/Clash_Explicit_RAM.primitives.yaml view
@@ -0,0 +1,29 @@+- BlackBox:+ name: Clash.Explicit.RAM.asyncRam#+ kind: Declaration+ type: |-+ asyncRam#+ :: ( HasCallStack -- ARG[0]+ , KnownDomain wdom -- ARG[1]+ , KnownDomain rdom -- ARG[2]+ , NFDataX a ) -- ARG[3]+ => Clock wdom -- ^ wclk, ARG[4]+ -> Clock rdom -- ^ rclk, ARG[5]+ -> Enable wdom -- ^ wen, ARG[6]+ -> SNat n -- ^ sz, ARG[7]+ -> Signal rdom Int -- ^ rd, ARG[8]+ -> Signal wdom Bool -- ^ en, ARG[9]+ -> Signal wdom Int -- ^ wr, ARG[10]+ -> Signal wdom a -- ^ din, ARG[11]+ -> Signal rdom a+ template: |-+ // asyncRam begin+ logic [~SIZE[~TYP[11]]-1:0] ~GENSYM[RAM][0] [0:~LIT[7]-1];+ always @(~IF~ACTIVEEDGE[Rising][1]~THENposedge~ELSEnegedge~FI ~ARG[4]) begin : ~GENSYM[~COMPNAME_Ram][1]+ if (~IF ~ISACTIVEENABLE[6] ~THEN ~ARG[6] & ~ELSE ~FI ~ARG[9]) begin+ ~SYM[0][~ARG[10]] <= ~TOBV[~ARG[11]][~TYP[11]];+ end+ end++ assign ~RESULT = ~FROMBV[~SYM[0][\~ARG[8]\]][~TYPO];+ // asyncRam end
− prims/systemverilog/Clash_Explicit_ROM.primitives
@@ -1,32 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Explicit.ROM.rom#"- , "kind" : "Declaration"- , "type" :-"rom# :: ( KnownDomain dom ARG[0]- , KnownNat n -- ARG[1]- , Undefined a ) -- ARG[2]- => Clock dom -- clk, ARG[3]- => Enable dom -- en, ARG[4]- -> Vec n a -- init, ARG[5]- -> Signal dom Int -- rd, ARG[6]- -> Signal dom a"- , "template" :-"// rom begin-~SIGD[~GENSYM[ROM][1]][5];-assign ~SYM[1] = ~LIT[5];--logic [~SIZE[~TYPO]-1:0] ~GENSYM[~RESULT_q][2];~IF ~ISACTIVEENABLE[4] ~THEN-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~GENSYM[~COMPNAME_rom][3]- if (~ARG[4]) begin- ~SYM[2] <= ~SYM[1][~ARG[6]];- end-end~ELSE-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~SYM[3]- ~SYM[2] <= ~SYM[1][~ARG[6]];-end~FI--assign ~RESULT = ~FROMBV[~SYM[2]][~TYPO];-// rom end"- }- }-]
+ prims/systemverilog/Clash_Explicit_ROM.primitives.yaml view
@@ -0,0 +1,29 @@+- BlackBox:+ name: Clash.Explicit.ROM.rom#+ kind: Declaration+ type: |-+ rom# :: ( KnownDomain dom ARG[0]+ , KnownNat n -- ARG[1]+ , Undefined a ) -- ARG[2]+ => Clock dom -- clk, ARG[3]+ => Enable dom -- en, ARG[4]+ -> Vec n a -- init, ARG[5]+ -> Signal dom Int -- rd, ARG[6]+ -> Signal dom a+ template: |-+ // rom begin+ ~SIGD[~GENSYM[ROM][1]][5];+ assign ~SYM[1] = ~LIT[5];++ logic [~SIZE[~TYPO]-1:0] ~GENSYM[~RESULT_q][2];~IF ~ISACTIVEENABLE[4] ~THEN+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~GENSYM[~COMPNAME_rom][3]+ if (~ARG[4]) begin+ ~SYM[2] <= ~SYM[1][~ARG[6]];+ end+ end~ELSE+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~SYM[3]+ ~SYM[2] <= ~SYM[1][~ARG[6]];+ end~FI++ assign ~RESULT = ~FROMBV[~SYM[2]][~TYPO];+ // rom end
+ prims/systemverilog/Clash_Explicit_ROM_Blob.primitives.yaml view
@@ -0,0 +1,28 @@+- BlackBox:+ name: Clash.Explicit.ROM.Blob.romBlob#+ kind: Declaration+ type: |-+ romBlob#+ :: KnownDomain dom -- ARG[0]+ => Clock dom -- clk, ARG[1]+ -> Enable dom -- en, ARG[2]+ -> MemBlob n m -- init, ARG[3]+ -> Signal dom Int -- rd, ARG[4]+ -> Signal dom (BitVector m)+ template: |-+ // romBlob begin+ ~SIGD[~GENSYM[ROM][1]][3];+ assign ~SYM[1] = ~CONST[3];++ logic [~SIZE[~TYPO]-1:0] ~GENSYM[~RESULT_q][2];~IF ~ISACTIVEENABLE[2] ~THEN+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[1]) begin : ~GENSYM[~COMPNAME_rom][3]+ if (~ARG[2]) begin+ ~SYM[2] <= ~SYM[1][~ARG[4]];+ end+ end~ELSE+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[1]) begin : ~SYM[3]+ ~SYM[2] <= ~SYM[1][~ARG[4]];+ end~FI++ assign ~RESULT = ~SYM[2];+ // rom end
− prims/systemverilog/Clash_Explicit_ROM_File.primitives
@@ -1,35 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Explicit.ROM.File.romFile#"- , "kind" : "Declaration"- , "type" :-"romFile# :: ( KnownNat m -- ARG[0]- , KnownDomain dom ) -- ARG[1]- => Clock dom -- clk, ARG[2]- -> Enable dom -- en, ARG[3]- -> SNat n -- sz, ARG[4]- -> FilePath -- file, ARG[5]- -> Signal dom Int -- rd, ARG[6]- -> Signal dom (BitVector m)"- , "template" :-"// romFile begin-~SIGDO[~GENSYM[ROM][0]] [0:~LIT[4]-1];--initial begin- $readmemb(~FILE[~LIT[5]],~SYM[0]);-end--~SIGDO[~GENSYM[~RESULT_q][1]];~IF ~ISACTIVEENABLE[3] ~THEN-always @(~IF~ACTIVEEDGE[Rising][1]~THENposedge~ELSEnegedge~FI ~ARG[2]) begin : ~GENSYM[~COMPNAME_romFile][2]- if (~ARG[3]) begin- ~SYM[1] <= ~SYM[0][~ARG[6]];- end-end~ELSE-always @(~IF~ACTIVEEDGE[Rising][1]~THENposedge~ELSEnegedge~FI ~ARG[2]) begin : ~SYM[2]- ~SYM[1] <= ~SYM[0][~ARG[6]];-end~FI--assign ~RESULT = ~SYM[1];-// romFile end"- }- }-]
+ prims/systemverilog/Clash_Explicit_ROM_File.primitives.yaml view
@@ -0,0 +1,32 @@+- BlackBox:+ name: Clash.Explicit.ROM.File.romFile#+ kind: Declaration+ type: |-+ romFile# :: ( KnownNat m -- ARG[0]+ , KnownDomain dom ) -- ARG[1]+ => Clock dom -- clk, ARG[2]+ -> Enable dom -- en, ARG[3]+ -> SNat n -- sz, ARG[4]+ -> FilePath -- file, ARG[5]+ -> Signal dom Int -- rd, ARG[6]+ -> Signal dom (BitVector m)+ template: |-+ // romFile begin+ ~SIGDO[~GENSYM[ROM][0]] [0:~LIT[4]-1];++ initial begin+ $readmemb(~FILE[~LIT[5]],~SYM[0]);+ end++ ~SIGDO[~GENSYM[~RESULT_q][1]];~IF ~ISACTIVEENABLE[3] ~THEN+ always @(~IF~ACTIVEEDGE[Rising][1]~THENposedge~ELSEnegedge~FI ~ARG[2]) begin : ~GENSYM[~COMPNAME_romFile][2]+ if (~ARG[3]) begin+ ~SYM[1] <= ~SYM[0][~ARG[6]];+ end+ end~ELSE+ always @(~IF~ACTIVEEDGE[Rising][1]~THENposedge~ELSEnegedge~FI ~ARG[2]) begin : ~SYM[2]+ ~SYM[1] <= ~SYM[0][~ARG[6]];+ end~FI++ assign ~RESULT = ~SYM[1];+ // romFile end
− prims/systemverilog/Clash_Explicit_Testbench.primitives
@@ -1,91 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Explicit.Testbench.assert"- , "kind" : "Declaration"- , "type" :-"assert- :: (KnownDomain dom, Eq a, ShowX a) -- (ARG[0], ARG[1], ARG[2])- => Clock dom -- ARG[3]- -> Reset dom -- ARG[4]- -> String -- ARG[5]- -> Signal dom a -- Checked value (ARG[6])- -> Signal dom a -- Expected value (ARG[7])- -> Signal dom b -- Return valued (ARG[8])- -> Signal dom b"- , "template" :-"// assert begin-// pragma translate_off-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin- if (~ARG[6] !== ~ARG[7]) begin- $display(\"@%0tns: %s, expected: %b, actual: %b\", $time, ~LIT[5], ~TOBV[~ARG[7]][~TYP[7]], ~TOBV[~ARG[6]][~TYP[6]]);- $stop;- end-end-// pragma translate_on-assign ~RESULT = ~ARG[8];-// assert end"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.Testbench.assertBitVector"- , "kind" : "Declaration"- , "type" :-"assertBitVector- :: ( KnownDomain dom -- ARG[0]- , KnownNat n ) -- ARG[1]- => Clock dom -- ARG[2]- -> Reset dom -- ARG[3]- -> String -- ARG[4]- -> Signal dom (BitVector n) -- Checked value (ARG[5])- -> Signal dom (BitVector n) -- Expected value (ARG[6])- -> Signal dom b -- Return valued (ARG[7])- -> Signal dom b"- , "template" :-"// assertBitVector begin-// pragma translate_off-wire ~TYP[6] ~GENSYM[maskXor][0] = ~ARG[6] ^ ~ARG[6];-wire ~TYP[6] ~GENSYM[checked][1] = ~ARG[5] ^ ~SYM[0];-wire ~TYP[6] ~GENSYM[expected][2] = ~ARG[6] ^ ~SYM[0];--always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[2]) begin- if (~SYM[1] !== ~SYM[2]) begin- $display(\"@%0tns: %s, expected: %b, actual: %b\", $time, ~LIT[4], ~TOBV[~ARG[6]][~TYP[6]], ~TOBV[~ARG[5]][~TYP[5]]);- $stop;- end-end-// pragma translate_on-assign ~RESULT = ~ARG[7];-// assertBitVector end"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.Testbench.tbClockGen"- , "workInfo" : "Always"- , "kind" : "Declaration"- , "warning" : "Clash.Signal.Internal.tbClockGen is not synthesizable!"- , "type" :-"tbClockGen- :: KnownDomain dom -- ARG[0]- => Signal dom Bool -- ARG[1]- -> Clock dom"- , "template" :-"// tbClockGen begin-// pragma translate_off-// 1 = 0.1ps-localparam ~GENSYM[half_period][0] = (~PERIOD[0]0 / 2);-always begin- ~RESULT = ~IF~ACTIVEEDGE[Rising][0]~THEN 0 ~ELSE 1 ~FI;- #30000 forever begin- if (~ ~ARG[1]) begin- $finish;- end- ~RESULT = ~ ~RESULT;- #~SYM[0];- ~RESULT = ~ ~RESULT;- #~SYM[0];- end-end-// pragma translate_on-// tbClockGen end"- }- }-]
+ prims/systemverilog/Clash_Explicit_Testbench.primitives.yaml view
@@ -0,0 +1,118 @@+- BlackBox:+ name: Clash.Explicit.Testbench.assert+ kind: Declaration+ type: |-+ assert+ :: (KnownDomain dom, Eq a, ShowX a) -- (ARG[0], ARG[1], ARG[2])+ => Clock dom -- ARG[3]+ -> Reset dom -- ARG[4]+ -> String -- ARG[5]+ -> Signal dom a -- Checked value (ARG[6])+ -> Signal dom a -- Expected value (ARG[7])+ -> Signal dom b -- Return valued (ARG[8])+ -> Signal dom b+ template: |-+ // assert begin+ // pragma translate_off+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin+ if (~ARG[6] !== ~ARG[7]) begin+ $display("@%0tns: %s, expected: %b, actual: %b", $time, ~LIT[5], ~TOBV[~ARG[7]][~TYP[7]], ~TOBV[~ARG[6]][~TYP[6]]);+ $stop;+ end+ end+ // pragma translate_on+ assign ~RESULT = ~ARG[8];+ // assert end+- BlackBox:+ name: Clash.Explicit.Testbench.assertBitVector+ kind: Declaration+ type: |-+ assertBitVector+ :: ( KnownDomain dom -- ARG[0]+ , KnownNat n ) -- ARG[1]+ => Clock dom -- ARG[2]+ -> Reset dom -- ARG[3]+ -> String -- ARG[4]+ -> Signal dom (BitVector n) -- Checked value (ARG[5])+ -> Signal dom (BitVector n) -- Expected value (ARG[6])+ -> Signal dom b -- Return valued (ARG[7])+ -> Signal dom b+ template: |-+ // assertBitVector begin+ // pragma translate_off+ wire ~TYP[6] ~GENSYM[maskXor][0] = ~ARG[6] ^ ~ARG[6];+ wire ~TYP[6] ~GENSYM[checked][1] = ~ARG[5] ^ ~SYM[0];+ wire ~TYP[6] ~GENSYM[expected][2] = ~ARG[6] ^ ~SYM[0];++ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[2]) begin+ if (~SYM[1] !== ~SYM[2]) begin+ $display("@%0tns: %s, expected: %b, actual: %b", $time, ~LIT[4], ~TOBV[~ARG[6]][~TYP[6]], ~TOBV[~ARG[5]][~TYP[5]]);+ $stop;+ end+ end+ // pragma translate_on+ assign ~RESULT = ~ARG[7];+ // assertBitVector end+- BlackBox:+ name: Clash.Explicit.Testbench.tbClockGen+ kind: Declaration+ type: |-+ tbClockGen+ :: KnownDomain dom -- ARG[0]+ => Signal dom Bool -- ARG[1]+ -> Clock dom+ template: |-+ // tbClockGen begin+ // pragma translate_off+ // 1 = 0.1ps+ localparam ~GENSYM[half_period][0] = (~PERIOD[0]0 / 2);+ always begin+ ~RESULT = ~IF~ACTIVEEDGE[Rising][0]~THEN 0 ~ELSE 1 ~FI;+ `ifndef VERILATOR+ #~LONGESTPERIOD0 forever begin+ if (~ ~ARG[1]) begin+ $finish;+ end+ ~RESULT = ~ ~RESULT;+ #~SYM[0];+ ~RESULT = ~ ~RESULT;+ #~SYM[0];+ end+ `else+ ~RESULT = $c("this->~GENSYM[tb_clock_gen][1](",~SYM[0],",~IF~ACTIVEEDGE[Rising][0]~THENtrue~ELSEfalse~FI,",(~ ~ARG[1]),")");+ `endif+ end++ `ifdef VERILATOR+ `systemc_interface+ CData ~SYM[1](vluint32_t half_period, bool active_rising, bool result_rec) {+ static vluint32_t init_wait = ~LONGESTPERIOD0;+ static vluint32_t to_wait = 0;+ static CData clock = active_rising ? 0 : 1;++ if(init_wait == 0) {+ if(result_rec) {+ std::exit(0);+ }+ else {+ if(to_wait == 0) {+ to_wait = half_period - 1;+ clock = clock == 0 ? 1 : 0;+ }+ else {+ to_wait = to_wait - 1;+ }+ }+ }+ else {+ init_wait = init_wait - 1;+ }++ return clock;+ }+ `verilog+ `endif+ // pragma translate_on+ // tbClockGen end+ warning: Clash.Signal.Internal.tbClockGen is not synthesizable!+ workInfo: Always
− prims/systemverilog/Clash_Intel_DDR.primitives
@@ -1,48 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Intel.DDR.altddioIn"- , "kind" : "Declaration"- , "type" :-"altddioIn- :: ( HasCallStack -- ARG[0]- , KnownConfi~ fast domf -- ARG[1]- , KnownConfi~ slow doms -- ARG[2]- , KnownNat m ) -- ARG[3]- => SSymbol deviceFamily -- ARG[4]- -> Clock slow -- ARG[5]- -> Reset slow -- ARG[6]- -> Enable slow -- ARG[7]- -> Signal fast (BitVector m) -- ARG[8]- -> Signal slow (BitVector m,BitVector m)"- , "libraries" : ["altera_mf"]- , "template" :-"// altddioIn begin-~SIGD[~GENSYM[dataout_l][1]][8];-~SIGD[~GENSYM[dataout_h][2]][8];--altddio_in- #(- .intended_device_family (~LIT[4]),- .invert_input_clocks (\"OFF\"),- .lpm_hint (\"UNUSED\"),- .lpm_type (\"altddio_in\"),- .power_up_high (\"OFF\"),- .width (~SIZE[~TYP[8]])- )- ~GENSYM[~COMPNAME_ALTDDIO_IN][7] (~IF ~ISSYNC[2] ~THEN- .sclr (~ARG[6]),- .aclr (1'b0),~ELSE- .aclr (~ARG[6]),- .sclr (1'b0),~FI- .datain (~ARG[8]),- .inclock (~ARG[5]),- .inclocken (~IF ~ISACTIVEENABLE[7] ~THEN~ARG[7]~ELSE1'b1,~FI),- .dataout_h (~SYM[2]),- .dataout_l (~SYM[1]),- .aset (1'b0),- .sset (1'b0)- );-assign ~RESULT = {~SYM[1],~SYM[2]};-// altddioIn end"- }- }-]
+ prims/systemverilog/Clash_Intel_DDR.primitives.yaml view
@@ -0,0 +1,46 @@+- BlackBox:+ name: Clash.Intel.DDR.altddioIn+ kind: Declaration+ libraries:+ - altera_mf+ type: |-+ altddioIn+ :: ( HasCallStack -- ARG[0]+ , KnownConfi~ fast domf -- ARG[1]+ , KnownConfi~ slow doms -- ARG[2]+ , KnownNat m ) -- ARG[3]+ => SSymbol deviceFamily -- ARG[4]+ -> Clock slow -- ARG[5]+ -> Reset slow -- ARG[6]+ -> Enable slow -- ARG[7]+ -> Signal fast (BitVector m) -- ARG[8]+ -> Signal slow (BitVector m,BitVector m)+ template: |-+ // altddioIn begin+ ~SIGD[~GENSYM[dataout_l][1]][8];+ ~SIGD[~GENSYM[dataout_h][2]][8];++ altddio_in+ #(+ .intended_device_family (~LIT[4]),+ .invert_input_clocks ("OFF"),+ .lpm_hint ("UNUSED"),+ .lpm_type ("altddio_in"),+ .power_up_high ("OFF"),+ .width (~SIZE[~TYP[8]])+ )+ ~GENSYM[~COMPNAME_ALTDDIO_IN][7] (~IF ~ISSYNC[2] ~THEN+ .sclr (~ARG[6]),+ .aclr (1'b0),~ELSE+ .aclr (~ARG[6]),+ .sclr (1'b0),~FI+ .datain (~ARG[8]),+ .inclock (~ARG[5]),+ .inclocken (~IF ~ISACTIVEENABLE[7] ~THEN~ARG[7]~ELSE1'b1,~FI),+ .dataout_h (~SYM[2]),+ .dataout_l (~SYM[1]),+ .aset (1'b0),+ .sset (1'b0)+ );+ assign ~RESULT = {~SYM[1],~SYM[2]};+ // altddioIn end
− prims/systemverilog/Clash_Prelude_ROM.primitives
@@ -1,18 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Prelude.ROM.asyncRom#"- , "kind" : "Declaration"- , "type" :-"asyncRom# :: KnownNat n -- ^ ARG[0]- => Vec n a -- ^ ARG[1]- -> Int -- ^ ARG[2]- -> a"- , "template" :-"// asyncRom begin-~SIGD[~GENSYM[ROM][0]][1];-assign ~SYM[0] = ~LIT[1];--assign ~RESULT = ~FROMBV[~SYM[0][\\~ARG[2]\\]][~TYPO];-// asyncRom end"- }- }-]
+ prims/systemverilog/Clash_Prelude_ROM.primitives.yaml view
@@ -0,0 +1,15 @@+- BlackBox:+ name: Clash.Prelude.ROM.asyncRom#+ kind: Declaration+ type: |-+ asyncRom# :: KnownNat n -- ^ ARG[0]+ => Vec n a -- ^ ARG[1]+ -> Int -- ^ ARG[2]+ -> a+ template: |-+ // asyncRom begin+ ~SIGD[~GENSYM[ROM][0]][1];+ assign ~SYM[0] = ~CONST[1];++ assign ~RESULT = ~FROMBV[~SYM[0][\~ARG[2]\]][~TYPO];+ // asyncRom end
+ prims/systemverilog/Clash_Prelude_ROM_Blob.primitives.yaml view
@@ -0,0 +1,15 @@+- BlackBox:+ name: Clash.Prelude.ROM.Blob.asyncRomBlob#+ kind: Declaration+ type: |-+ asyncRomBlob#+ :: MemBlob n m -- ARG[0]+ -> Int -- ARG[1]+ -> BitVector m+ template: |-+ // asyncRomBlob begin+ ~SIGD[~GENSYM[ROM][0]][0];+ assign ~SYM[0] = ~CONST[0];++ assign ~RESULT = ~SYM[0][~ARG[1]];+ // asyncRomBlob end
− prims/systemverilog/Clash_Prelude_ROM_File.primitives
@@ -1,22 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Prelude.ROM.File.asyncRomFile#"- , "kind" : "Declaration"- , "type" :-"asyncRomFile :: KnownNat m -- ARG[0]- => SNat n -- sz, ARG[1]- -> FilePath -- file, ARG[2]- -> Int -- rd, ARG[3]- -> BitVector m"- , "template" :-"// asyncRomFile begin-~SIGDO[~GENSYM[ROM][0]] [0:~LIT[1]-1];--initial begin- $readmemb(~FILE[~LIT[2]],~SYM[0]);-end--assign ~RESULT = ~SYM[0][~ARG[3]];-// asyncRomFile end"- }- }-]
+ prims/systemverilog/Clash_Prelude_ROM_File.primitives.yaml view
@@ -0,0 +1,19 @@+- BlackBox:+ name: Clash.Prelude.ROM.File.asyncRomFile#+ kind: Declaration+ type: |-+ asyncRomFile :: KnownNat m -- ARG[0]+ => SNat n -- sz, ARG[1]+ -> FilePath -- file, ARG[2]+ -> Int -- rd, ARG[3]+ -> BitVector m+ template: |-+ // asyncRomFile begin+ ~SIGDO[~GENSYM[ROM][0]] [0:~LIT[1]-1];++ initial begin+ $readmemb(~FILE[~LIT[2]],~SYM[0]);+ end++ assign ~RESULT = ~SYM[0][~ARG[3]];+ // asyncRomFile end
− prims/systemverilog/Clash_Signal_BiSignal.primitives
@@ -1,35 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Signal.BiSignal.writeToBiSignal#",- "kind" : "Declaration",- "renderVoid": "RenderVoid",- "type" :-"writeToBiSignal#- :: HasCallStack -- ARG[0]- => BiSignalIn ds d n -- ARG[1]- -> Signal d (Maybe (BitVector n)) -- ARG[2]- -> Signal d Bool -- ARG[3]- -> Signal d (BitVector n) -- ARG[4]- -> BiSignalOut ds d n",- "template":-"// writeToBiSignal# begin-assign ~ARG[1] = (~ARG[3] == 1'b1) ? ~ARG[4] : {~SIZE[~TYP[1]] {1'bz}};-// writeToBiSignal# end"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.BiSignal.readFromBiSignal#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" :-"readFromBiSignal#- :: ( HasCallStack -- ARG[0]- , KnownNat n) -- ARG[1]- => BiSignalIn ds d n -- ARG[2]- -> Signal d (BitVector n)"- , "template" :-"// readFromBiSignal begin-assign ~RESULT = ~ARG[2];-// readFromBiSignal end"- }- }-]
+ prims/systemverilog/Clash_Signal_BiSignal.primitives.yaml view
@@ -0,0 +1,30 @@+- BlackBox:+ name: Clash.Signal.BiSignal.writeToBiSignal#+ kind: Declaration+ type: |-+ writeToBiSignal#+ :: HasCallStack -- ARG[0]+ => BiSignalIn ds d n -- ARG[1]+ -> Signal d (Maybe (BitVector n)) -- ARG[2]+ -> Signal d Bool -- ARG[3]+ -> Signal d (BitVector n) -- ARG[4]+ -> BiSignalOut ds d n+ renderVoid: RenderVoid+ template: |-+ // writeToBiSignal# begin+ assign ~ARG[1] = (~ARG[3] == 1'b1) ? ~ARG[4] : {~SIZE[~TYP[1]] {1'bz}};+ // writeToBiSignal# end+- BlackBox:+ name: Clash.Signal.BiSignal.readFromBiSignal#+ kind: Declaration+ type: |-+ readFromBiSignal#+ :: ( HasCallStack -- ARG[0]+ , KnownNat n) -- ARG[1]+ => BiSignalIn ds d n -- ARG[2]+ -> Signal d (BitVector n)+ template: |-+ // readFromBiSignal begin+ assign ~RESULT = ~ARG[2];+ // readFromBiSignal end+ workInfo: Never
− prims/systemverilog/Clash_Signal_Internal.primitives
@@ -1,135 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Signal.Internal.delay#"- , "kind" : "Declaration"- , "type" :-"delay#- :: ( KnownDomain dom -- ARG[0]- , Undefined a ) -- ARG[1]- => Clock dom -- ARG[2]- -> Enable dom -- ARG[3]- -> a -- ARG[4]- -> Signal clk a -- ARG[5]- -> Signal clk a"- , "resultName" : { "template" : "~CTXNAME" }- , "resultInit" : { "template" : "~IF~ISINITDEFINED[0]~THEN~CONST[4]~ELSE~FI" }- , "template" :-"// delay begin~IF ~ISACTIVEENABLE[3] ~THEN-always_ff @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[2]) begin : ~GENSYM[~RESULT_delay][1]- if (~ARG[3]) begin- ~RESULT <= ~ARG[5];- end-end~ELSE-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[2]) begin : ~SYM[1]- ~RESULT <= ~ARG[5];-end~FI-// delay end"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.asyncRegister#"- , "kind" : "Declaration"- , "type" :-"asyncRegister#- :: ( KnownDomain dom -- ARG[0]- , NFDataX a ) -- ARG[1]- => Clock dom -- ARG[2]- -> Reset dom -- ARG[3]- -> Enable dom -- ARG[4]- -> a -- ARG[5] (powerup value)- -> a -- ARG[6] (reset value)- -> Signal clk a -- ARG[7]- -> Signal clk a"- , "resultName" : { "template" : "~CTXNAME" }- , "resultInit" : { "template" : "~IF~ISINITDEFINED[0]~THEN~CONST[5]~ELSE~FI" }- , "template" :-"// async register begin-always_ff @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[2]~IF ~ISUNDEFINED[6] ~THEN ~ELSE or ~IF ~ISACTIVEHIGH[0] ~THEN posedge ~ELSE negedge ~FI ~VAR[rst][3]~FI) begin : ~GENSYM[~RESULT_register][1]- ~IF ~ISUNDEFINED[6] ~THEN ~ELSEif (~IF ~ISACTIVEHIGH[0] ~THEN ~ELSE ! ~FI~VAR[rst][3]) begin- ~RESULT <= ~CONST[6];- end else ~FI~IF ~ISACTIVEENABLE[4] ~THEN if (~ARG[4]) ~ELSE ~FI begin- ~RESULT <= ~ARG[7];- end-end-// async register end"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.register#"- , "kind" : "Declaration"- , "type" :-"register#- :: ( KnownDomain dom -- ARG[0]- , Undefined a ) -- ARG[1]- => Clock dom -- ARG[2]- -> Reset dom -- ARG[3]- -> Enable dom -- ARG[4]- -> a -- ARG[5] (powerup value)- -> a -- ARG[6] (reset value)- -> Signal clk a -- ARG[7]- -> Signal clk a"- , "resultName" : { "template" : "~CTXNAME" }- , "resultInit" : { "template" : "~IF~ISINITDEFINED[0]~THEN~CONST[5]~ELSE~FI" }- , "template" :-"// register begin-always_ff @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[2]~IF ~ISSYNC[0] ~THEN ~ELSE~IF ~ISUNDEFINED[6] ~THEN ~ELSE or ~IF ~ISACTIVEHIGH[0] ~THEN posedge ~ELSE negedge ~FI ~VAR[rst][3]~FI~FI) begin : ~GENSYM[~RESULT_register][1]- ~IF ~ISUNDEFINED[6] ~THEN ~ELSEif (~IF ~ISACTIVEHIGH[0] ~THEN ~ELSE ! ~FI~VAR[rst][3]) begin- ~RESULT <= ~CONST[6];- end else ~FI~IF ~ISACTIVEENABLE[4] ~THEN if (~ARG[4]) ~ELSE ~FI begin- ~RESULT <= ~ARG[7];- end-end-// register end"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.clockGen"- , "workInfo" : "Always"- , "kind" : "Declaration"- , "warning" : "Clash.Signal.Internal.clockGen is not synthesizable!"- , "type" :-"clockGen- :: KnownDomain dom -- ARG[0]- => Clock dom"- , "template" :-"// clockGen begin-// pragma translate_off-// 1 = 0.1ps-localparam ~GENSYM[half_period][0] = (~PERIOD[0]0 / 2);-always begin- ~RESULT = ~IF~ACTIVEEDGE[Rising][0]~THEN 0 ~ELSE 1 ~FI;- #30000 forever begin- ~RESULT = ~ ~RESULT;- #~SYM[0];- ~RESULT = ~ ~RESULT;- #~SYM[0];- end-end-// pragma translate_on-// clockGen end"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.resetGenN"- , "workInfo" : "Always"- , "kind" : "Declaration"- , "type" : "resetGenN :: (KnownDomain dom, 1 <= n) => SNat n -> Reset dom"- , "template" :-"// resetGen begin-// pragma translate_off-~IF~ISSYNC[0]~THEN-localparam ~GENSYM[reset_period][1] = 29998 + (~LIT[2] * ~PERIOD[0]0);-initial begin- #1 ~RESULT = ~IF ~ISACTIVEHIGH[0] ~THEN 1 ~ELSE 0 ~FI;- #~SYM[1] ~RESULT = ~IF ~ISACTIVEHIGH[0] ~THEN 0 ~ELSE 1 ~FI;-end~ELSE-localparam ~SYM[1] = 30001 + ((~LIT[2] - 1) * ~PERIOD[0]0);-initial begin- #1 ~RESULT = ~IF ~ISACTIVEHIGH[0] ~THEN 1 ~ELSE 0 ~FI;- #~SYM[1] ~RESULT = ~IF ~ISACTIVEHIGH[0] ~THEN 0 ~ELSE 1 ~FI;-end-~FI-// pragma translate_on-// resetGen end"- }- }-]
+ prims/systemverilog/Clash_Signal_Internal.primitives.yaml view
@@ -0,0 +1,183 @@+- BlackBox:+ name: Clash.Signal.Internal.delay#+ kind: Declaration+ type: |-+ delay#+ :: ( KnownDomain dom -- ARG[0]+ , Undefined a ) -- ARG[1]+ => Clock dom -- ARG[2]+ -> Enable dom -- ARG[3]+ -> a -- ARG[4]+ -> Signal clk a -- ARG[5]+ -> Signal clk a+ resultInit:+ template: ~IF~ISINITDEFINED[0]~THEN~CONST[4]~ELSE~FI+ resultName:+ template: ~CTXNAME+ template: |-+ // delay begin~IF ~ISACTIVEENABLE[3] ~THEN+ always_ff @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[2]) begin : ~GENSYM[~RESULT_delay][1]+ if (~ARG[3]) begin+ ~RESULT <= ~ARG[5];+ end+ end~ELSE+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[2]) begin : ~SYM[1]+ ~RESULT <= ~ARG[5];+ end~FI+ // delay end+- BlackBox:+ name: Clash.Signal.Internal.asyncRegister#+ kind: Declaration+ type: |-+ asyncRegister#+ :: ( KnownDomain dom -- ARG[0]+ , NFDataX a ) -- ARG[1]+ => Clock dom -- ARG[2]+ -> Reset dom -- ARG[3]+ -> Enable dom -- ARG[4]+ -> a -- ARG[5] (powerup value)+ -> a -- ARG[6] (reset value)+ -> Signal clk a -- ARG[7]+ -> Signal clk a+ resultInit:+ template: ~IF~ISINITDEFINED[0]~THEN~CONST[5]~ELSE~FI+ resultName:+ template: ~CTXNAME+ template: |-+ // async register begin+ always_ff @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[2]~IF ~ISUNDEFINED[6] ~THEN ~ELSE or ~IF ~ISACTIVEHIGH[0] ~THEN posedge ~ELSE negedge ~FI ~VAR[rst][3]~FI) begin : ~GENSYM[~RESULT_register][1]+ ~IF ~ISUNDEFINED[6] ~THEN ~ELSEif (~IF ~ISACTIVEHIGH[0] ~THEN ~ELSE ! ~FI~VAR[rst][3]) begin+ ~RESULT <= ~CONST[6];+ end else ~FI~IF ~ISACTIVEENABLE[4] ~THEN if (~ARG[4]) ~ELSE ~FI begin+ ~RESULT <= ~ARG[7];+ end+ end+ // async register end+- BlackBox:+ name: Clash.Signal.Internal.register#+ kind: Declaration+ type: |-+ register#+ :: ( KnownDomain dom -- ARG[0]+ , Undefined a ) -- ARG[1]+ => Clock dom -- ARG[2]+ -> Reset dom -- ARG[3]+ -> Enable dom -- ARG[4]+ -> a -- ARG[5] (powerup value)+ -> a -- ARG[6] (reset value)+ -> Signal clk a -- ARG[7]+ -> Signal clk a+ resultInit:+ template: ~IF~ISINITDEFINED[0]~THEN~CONST[5]~ELSE~FI+ resultName:+ template: ~CTXNAME+ template: |-+ // register begin+ always_ff @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[2]~IF ~ISSYNC[0] ~THEN ~ELSE~IF ~ISUNDEFINED[6] ~THEN ~ELSE or ~IF ~ISACTIVEHIGH[0] ~THEN posedge ~ELSE negedge ~FI ~VAR[rst][3]~FI~FI) begin : ~GENSYM[~RESULT_register][1]+ ~IF ~ISUNDEFINED[6] ~THEN ~ELSEif (~IF ~ISACTIVEHIGH[0] ~THEN ~ELSE ! ~FI~VAR[rst][3]) begin+ ~RESULT <= ~CONST[6];+ end else ~FI~IF ~ISACTIVEENABLE[4] ~THEN if (~ARG[4]) ~ELSE ~FI begin+ ~RESULT <= ~ARG[7];+ end+ end+ // register end+- BlackBox:+ name: Clash.Signal.Internal.clockGen+ kind: Declaration+ type: |-+ clockGen+ :: KnownDomain dom -- ARG[0]+ => Clock dom+ template: |-+ // clockGen begin+ // pragma translate_off+ // 1 = 0.1ps+ localparam ~GENSYM[half_period][0] = (~PERIOD[0]0 / 2);+ always begin+ ~RESULT = ~IF~ACTIVEEDGE[Rising][0]~THEN 0 ~ELSE 1 ~FI;+ `ifndef VERILATOR+ #~LONGESTPERIOD0 forever begin+ ~RESULT = ~ ~RESULT;+ #~SYM[0];+ ~RESULT = ~ ~RESULT;+ #~SYM[0];+ end+ `else+ ~RESULT = $c("this->~GENSYM[tb_clock_gen][1](",~SYM[0],",~IF~ACTIVEEDGE[Rising][0]~THENtrue~ELSEfalse~FI)");+ `endif+ end++ `ifdef VERILATOR+ `systemc_interface+ CData ~SYM[1](vluint32_t half_period, bool active_rising) {+ static vluint32_t init_wait = ~LONGESTPERIOD0;+ static vluint32_t to_wait = 0;+ static CData clock = active_rising ? 0 : 1;++ if(init_wait == 0) {+ if(to_wait == 0) {+ to_wait = half_period - 1;+ clock = clock == 0 ? 1 : 0;+ }+ else {+ to_wait = to_wait - 1;+ }+ }+ else {+ init_wait = init_wait - 1;+ }++ return clock;+ }+ `verilog+ `endif++ // pragma translate_on+ // clockGen end+ warning: Clash.Signal.Internal.clockGen is not synthesizable!+ workInfo: Always+- BlackBox:+ name: Clash.Signal.Internal.resetGenN+ kind: Declaration+ type: 'resetGenN :: (KnownDomain+ dom, 1 <= n) => SNat n -> Reset dom'+ template: |-+ // resetGen begin+ // pragma translate_off+ localparam ~GENSYM[reset_period][0] = ~LONGESTPERIOD0 - 10 + (~LIT[2] * ~PERIOD[0]0);+ `ifndef VERILATOR+ initial begin+ #1 ~RESULT = ~IF ~ISACTIVEHIGH[0] ~THEN 1 ~ELSE 0 ~FI;+ #~SYM[0] ~RESULT = ~IF ~ISACTIVEHIGH[0] ~THEN 0 ~ELSE 1 ~FI;+ end+ `else+ always begin+ // The redundant (~RESULT | ~ ~RESULT) is needed to ensure that this is+ // calculated in every cycle by verilator. Without it, the reset will stop+ // being updated and will be stuck as asserted forever.+ ~RESULT =+ $c("this->~GENSYM[reset_gen][1](",~SYM[0],",~IF~ISACTIVEHIGH[0]~THENtrue~ELSEfalse~FI)") & (~RESULT | ~ ~RESULT);+ end+ `systemc_interface+ CData ~SYM[1](vluint32_t reset_period, bool active_high) {+ static vluint32_t to_wait = reset_period;+ static CData reset = active_high ? 1 : 0;+ static bool finished = false;++ if(!finished) {+ if(to_wait == 0) {+ reset = reset == 0 ? 1 : 0;+ finished = true;+ }+ else {+ to_wait = to_wait - 1;+ }+ }++ return reset;+ }+ `verilog+ `endif+ // pragma translate_on+ // resetGen end+ workInfo: Always
− prims/systemverilog/Clash_Sized_Internal_BitVector.primitives
@@ -1,79 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.replaceBit#"- , "kind" : "Declaration"- , "type" :-"replaceBit# :: KnownNat n -- ARG[0]- => BitVector n -- ARG[1]- -> Int -- ARG[2]- -> Bit -- ARG[3]- -> BitVector n"- , "template" :-"// replaceBit start-always_comb begin- ~RESULT = ~ARG[1];- ~RESULT[~ARG[2]] = ~ARG[3];-end-// replaceBit end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.setSlice#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" :-"setSlice# :: SNat (m + 1 + i)- -> BitVector (m + 1 + i) -- ARG[1]- -> SNat m -- ARG[2]- -> SNat n -- ARG[3]- -> BitVector (m + 1 - n) -- ARG[4]- -> BitVector (m + 1 + i)"- , "template" :-"// setSlice begin-always_comb begin- ~RESULT = ~ARG[1];- ~RESULT[~LIT[2] : ~LIT[3]] = ~ARG[4];-end-// setSlice end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.split#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" :-"split# :: KnownNat n -- ARG[0]- => BitVector (m + n) -- ARG[1]- -> (BitVector m, BitVector n)"- , "template" :-"// split begin-assign ~RESULT = { ~VAR[bv][1][$high(~VAR[bv][1]) : ~LIT[0]]- , ~VAR[bv][1][(~LIT[0]-1) : 0]- };-// split end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.rotateL#"- , "kind" : "Declaration"- , "type" : "rotateL# :: KnownNat n => BitVector n -> Int -> BitVector n"- , "template" :-"// rotateL begin-logic [2*~SIZE[~TYPO]-1:0] ~GENSYM[bv][0];-assign ~SYM[0] = {~ARG[1],~ARG[1]} << (~ARG[2] % ~SIZE[~TYPO]);-assign ~RESULT = ~SYM[0][2*~SIZE[~TYPO]-1 : ~SIZE[~TYPO]];-// rotateL end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.rotateR#"- , "kind" : "Declaration"- , "type" : "rotateR# :: KnownNat n => BitVector n -> Int -> BitVector n"- , "template" :-"// rotateR begin-logic [2*~SIZE[~TYPO]-1:0] ~GENSYM[bv][0];-assign ~SYM[0] = {~ARG[1],~ARG[1]} >> (~ARG[2] % ~SIZE[~TYPO]);-assign ~RESULT = ~SYM[0][~SIZE[~TYPO]-1 : 0];-// rotateR end"- }- }-]
+ prims/systemverilog/Clash_Sized_Internal_BitVector.primitives.yaml view
@@ -0,0 +1,70 @@+- BlackBox:+ name: Clash.Sized.Internal.BitVector.replaceBit#+ kind: Declaration+ type: |-+ replaceBit# :: KnownNat n -- ARG[0]+ => BitVector n -- ARG[1]+ -> Int -- ARG[2]+ -> Bit -- ARG[3]+ -> BitVector n+ template: |-+ // replaceBit start+ always_comb begin+ ~RESULT = ~ARG[1];+ ~RESULT[~ARG[2]] = ~ARG[3];+ end+ // replaceBit end+- BlackBox:+ name: Clash.Sized.Internal.BitVector.setSlice#+ kind: Declaration+ type: |-+ setSlice# :: SNat (m + 1 + i)+ -> BitVector (m + 1 + i) -- ARG[1]+ -> SNat m -- ARG[2]+ -> SNat n -- ARG[3]+ -> BitVector (m + 1 - n) -- ARG[4]+ -> BitVector (m + 1 + i)+ template: |-+ // setSlice begin+ always_comb begin+ ~RESULT = ~ARG[1];+ ~RESULT[~LIT[2] : ~LIT[3]] = ~ARG[4];+ end+ // setSlice end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.split#+ kind: Declaration+ type: |-+ split# :: KnownNat n -- ARG[0]+ => BitVector (m + n) -- ARG[1]+ -> (BitVector m, BitVector n)+ template: |-+ // split begin+ assign ~RESULT = { ~VAR[bv][1][$high(~VAR[bv][1]) : ~LIT[0]]+ , ~VAR[bv][1][(~LIT[0]-1) : 0]+ };+ // split end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.rotateL#+ kind: Declaration+ type: 'rotateL# :: KnownNat+ n => BitVector n -> Int -> BitVector n'+ template: |-+ // rotateL begin+ logic [2*~SIZE[~TYPO]-1:0] ~GENSYM[bv][0];+ assign ~SYM[0] = {~ARG[1],~ARG[1]} << (~ARG[2] % ~SIZE[~TYPO]);+ assign ~RESULT = ~SYM[0][2*~SIZE[~TYPO]-1 : ~SIZE[~TYPO]];+ // rotateL end+- BlackBox:+ name: Clash.Sized.Internal.BitVector.rotateR#+ kind: Declaration+ type: 'rotateR# :: KnownNat+ n => BitVector n -> Int -> BitVector n'+ template: |-+ // rotateR begin+ logic [2*~SIZE[~TYPO]-1:0] ~GENSYM[bv][0];+ assign ~SYM[0] = {~ARG[1],~ARG[1]} >> (~ARG[2] % ~SIZE[~TYPO]);+ assign ~RESULT = ~SYM[0][~SIZE[~TYPO]-1 : 0];+ // rotateR end
− prims/systemverilog/Clash_Sized_Internal_Signed.primitives
@@ -1,69 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.div#"- , "kind" : "Declaration"- , "type" : "div# :: Signed n -> Signed n -> Signed n"- , "template" :-"// divSigned begin-logic ~GENSYM[resultPos][1];-logic ~GENSYM[dividerNeg][2];-logic signed [~SIZE[~TYPO]:0] ~GENSYM[dividend2][3];-logic signed [~SIZE[~TYPO]:0] ~GENSYM[dividendE][4];-logic signed [~SIZE[~TYPO]:0] ~GENSYM[dividerE][5];-logic signed [~SIZE[~TYPO]:0] ~GENSYM[quot_res][6];--assign ~SYM[1] = ~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1];-assign ~SYM[2] = ~VAR[divider][1][~SIZE[~TYPO]-1] == 1'b1;-assign ~SYM[4] = $signed({{~VAR[dividend][0][~SIZE[~TYPO]-1]},~VAR[dividend][0]}); // sign extension-assign ~SYM[5] = $signed({{~VAR[divider][1][~SIZE[~TYPO]-1]} ,~VAR[divider][1]} ); // sign extension--assign ~SYM[3] = ~SYM[1] ? ~SYM[4]- : (~SYM[2] ? (~SYM[4] - ~SYM[5] - ~SIZE[~TYPO]'sd1)- : (~SYM[4] - ~SYM[5] + ~SIZE[~TYPO]'sd1));--assign ~SYM[6] = ~SYM[3] / ~SYM[5];-assign ~RESULT = $signed(~SYM[6][~SIZE[~TYPO]-1:0]);-// divSigned end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.mod#"- , "kind" : "Declaration"- , "type" : "mod# :: Signed n -> Signed n -> Signed n"- , "template" :-"// modSigned begin-// remainder-~SIGD[~GENSYM[rem_res][0]][0];-assign ~SYM[0] = ~VAR[dividend][0] % ~VAR[divider][1];--// modulo-assign ~RESULT = (~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1]) ?- ~SYM[0] :- (~SYM[0] == ~SIZE[~TYPO]'sd0 ? ~SIZE[~TYPO]'sd0 : ~SYM[0] + ~VAR[divider][1]);-// modSigned end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.rotateL#"- , "kind" : "Declaration"- , "type" : "rotateL# :: KnownNat n => Signed n -> Int -> Signed n"- , "template" :-"// rotateL begin-logic [2*~SIZE[~TYPO]-1:0] ~GENSYM[s][0];-assign ~SYM[0] = {~ARG[1],~ARG[1]} << (~ARG[2] % ~SIZE[~TYPO]);-assign ~RESULT = $signed(~SYM[0][2*~SIZE[~TYPO]-1 : ~SIZE[~TYPO]]);-// rotateL end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.rotateR#"- , "kind" : "Declaration"- , "type" : "rotateR# :: KnownNat n => Signed n -> Int -> Signed n"- , "template" :-"// rotateR begin-logic [2*~SIZE[~TYPO]-1:0] ~GENSYM[s][0];-assign ~SYM[0] = {~ARG[1],~ARG[1]} >> (~ARG[2] % ~SIZE[~TYPO]);-assign ~RESULT = $signed(~SYM[0][~SIZE[~TYPO]-1 : 0]);-// rotateR end"- }- }-]
+ prims/systemverilog/Clash_Sized_Internal_Signed.primitives.yaml view
@@ -0,0 +1,64 @@+- BlackBox:+ name: Clash.Sized.Internal.Signed.div#+ kind: Declaration+ type: 'div# :: KnownNat+ n => Signed n -> Signed n -> Signed n'+ template: |-+ // divSigned begin+ logic ~GENSYM[resultPos][1];+ logic ~GENSYM[dividerNeg][2];+ logic signed [~SIZE[~TYPO]:0] ~GENSYM[dividend2][3];+ logic signed [~SIZE[~TYPO]:0] ~GENSYM[dividendE][4];+ logic signed [~SIZE[~TYPO]:0] ~GENSYM[dividerE][5];+ logic signed [~SIZE[~TYPO]:0] ~GENSYM[quot_res][6];++ assign ~SYM[1] = ~VAR[dividend][1][~SIZE[~TYPO]-1] == ~VAR[divider][2][~SIZE[~TYPO]-1];+ assign ~SYM[2] = ~VAR[divider][2][~SIZE[~TYPO]-1] == 1'b1;+ assign ~SYM[4] = $signed({{~VAR[dividend][1][~SIZE[~TYPO]-1]},~VAR[dividend][1]}); // sign extension+ assign ~SYM[5] = $signed({{~VAR[divider][2][~SIZE[~TYPO]-1]} ,~VAR[divider][2]} ); // sign extension++ assign ~SYM[3] = ~SYM[1] ? ~SYM[4]+ : (~SYM[2] ? (~SYM[4] - ~SYM[5] - ~SIZE[~TYPO]'sd1)+ : (~SYM[4] - ~SYM[5] + ~SIZE[~TYPO]'sd1));++ assign ~SYM[6] = ~SYM[3] / ~SYM[5];+ assign ~RESULT = $signed(~SYM[6][~SIZE[~TYPO]-1:0]);+ // divSigned end+- BlackBox:+ name: Clash.Sized.Internal.Signed.mod#+ kind: Declaration+ type: 'mod# :: Signed+ n -> Signed n -> Signed n'+ template: |-+ // modSigned begin+ // remainder+ ~SIGD[~GENSYM[rem_res][0]][0];+ assign ~SYM[0] = ~VAR[dividend][0] % ~VAR[divider][1];++ // modulo+ assign ~RESULT = (~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1]) ?+ ~SYM[0] :+ (~SYM[0] == ~SIZE[~TYPO]'sd0 ? ~SIZE[~TYPO]'sd0 : ~SYM[0] + ~VAR[divider][1]);+ // modSigned end+- BlackBox:+ name: Clash.Sized.Internal.Signed.rotateL#+ kind: Declaration+ type: 'rotateL# :: KnownNat+ n => Signed n -> Int -> Signed n'+ template: |-+ // rotateL begin+ logic [2*~SIZE[~TYPO]-1:0] ~GENSYM[s][0];+ assign ~SYM[0] = {~ARG[1],~ARG[1]} << (~ARG[2] % ~SIZE[~TYPO]);+ assign ~RESULT = $signed(~SYM[0][2*~SIZE[~TYPO]-1 : ~SIZE[~TYPO]]);+ // rotateL end+- BlackBox:+ name: Clash.Sized.Internal.Signed.rotateR#+ kind: Declaration+ type: 'rotateR# :: KnownNat+ n => Signed n -> Int -> Signed n'+ template: |-+ // rotateR begin+ logic [2*~SIZE[~TYPO]-1:0] ~GENSYM[s][0];+ assign ~SYM[0] = {~ARG[1],~ARG[1]} >> (~ARG[2] % ~SIZE[~TYPO]);+ assign ~RESULT = $signed(~SYM[0][~SIZE[~TYPO]-1 : 0]);+ // rotateR end
− prims/systemverilog/Clash_Sized_Internal_Unsigned.primitives
@@ -1,25 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.rotateL#"- , "kind" : "Declaration"- , "type" : "rotateL# :: KnownNat n => Unsigned n -> Int -> Unsigned n"- , "template" :-"// rotateL begin-logic [2*~SIZE[~TYPO]-1:0] ~GENSYM[u][0];-assign ~SYM[0] = {~ARG[1],~ARG[1]} << (~ARG[2] % ~SIZE[~TYPO]);-assign ~RESULT = ~SYM[0][2*~SIZE[~TYPO]-1 : ~SIZE[~TYPO]];-// rotateL end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.rotateR#"- , "kind" : "Declaration"- , "type" : "rotateR# :: KnownNat n => Unsigned n -> Int -> Unsigned n"- , "template" :-"// rotateR begin-logic [2*~SIZE[~TYPO]-1:0] ~GENSYM[u][0];-assign ~SYM[0] = {~ARG[1],~ARG[1]} >> (~ARG[2] % ~SIZE[~TYPO]);-assign ~RESULT = ~SYM[0][~SIZE[~TYPO]-1 : 0];-// rotateR end"- }- }-]
+ prims/systemverilog/Clash_Sized_Internal_Unsigned.primitives.yaml view
@@ -0,0 +1,22 @@+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.rotateL#+ kind: Declaration+ type: 'rotateL# :: KnownNat+ n => Unsigned n -> Int -> Unsigned n'+ template: |-+ // rotateL begin+ logic [2*~SIZE[~TYPO]-1:0] ~GENSYM[u][0];+ assign ~SYM[0] = {~ARG[1],~ARG[1]} << (~ARG[2] % ~SIZE[~TYPO]);+ assign ~RESULT = ~SYM[0][2*~SIZE[~TYPO]-1 : ~SIZE[~TYPO]];+ // rotateL end+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.rotateR#+ kind: Declaration+ type: 'rotateR# :: KnownNat+ n => Unsigned n -> Int -> Unsigned n'+ template: |-+ // rotateR begin+ logic [2*~SIZE[~TYPO]-1:0] ~GENSYM[u][0];+ assign ~SYM[0] = {~ARG[1],~ARG[1]} >> (~ARG[2] % ~SIZE[~TYPO]);+ assign ~RESULT = ~SYM[0][~SIZE[~TYPO]-1 : 0];+ // rotateR end
− prims/systemverilog/Clash_Sized_RTree.primitives
@@ -1,25 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Sized.RTree.treplicate"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "replicate :: SNat d -> a -> RTree d a"- , "template" : "'{(2**~LIT[0]) {~TOBV[~ARG[1]][~TYP[1]]}}"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.RTree.textract"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "textract :: RTree 0 a -> a"- , "template" : "~FROMBV[~VAR[tree][0][\\0\\]][~TYPO]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.RTree.tsplit"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "tsplit:: RTree (d+1) a -> (RTree d a,RTree d a)"- , "template" : "~TOBV[~VAR[tree][0]][~TYP[0]]"- }- }-]
+ prims/systemverilog/Clash_Sized_RTree.primitives.yaml view
@@ -0,0 +1,21 @@+- BlackBox:+ name: Clash.Sized.RTree.treplicate+ kind: Expression+ type: 'replicate :: SNat+ d -> a -> RTree d a'+ template: '''{(2**~LIT[0]) {~TOBV[~ARG[1]][~TYP[1]]}}'+ workInfo: Never+- BlackBox:+ name: Clash.Sized.RTree.textract+ kind: Expression+ type: 'textract :: RTree+ 0 a -> a'+ template: ~FROMBV[~VAR[tree][0][\0\]][~TYPO]+ workInfo: Never+- BlackBox:+ name: Clash.Sized.RTree.tsplit+ kind: Expression+ type: 'tsplit:: RTree+ (d+1) a -> (RTree d a,RTree d a)'+ template: ~TOBV[~VAR[tree][0]][~TYP[0]]+ workInfo: Never
− prims/systemverilog/Clash_Sized_Vector.primitives
@@ -1,377 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Sized.Vector.head"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "head :: Vec (n + 1) a -> a"- , "template" : "~FROMBV[~VAR[vec][0][\\0\\]][~TYPO]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.tail"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "tail :: Vec (n + 1) a -> Vec n a"- , "template" : "~VAR[vec][0][1 : $high(~VAR[vec][0])]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.last"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "Vec (n + 1) a -> a"- , "template" : "~FROMBV[~VAR[vec][0][\\$high(~VAR[vec][0])\\]][~TYPO]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.init"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "Vec (n + 1) a -> Vec n a"- , "template" : "~VAR[vec][0][0 : $high(~VAR[vec][0]) - 1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.select"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" :-"select :: (CmpNat (i + s) (s * n) ~ GT) -- ARG[0]- => SNat f -- ARG[1]- -> SNat s -- ARG[2]- -> SNat n -- ARG[3]- -> Vec i a -- ARG[4]- -> Vec n a"- , "template" :-"// select begin-genvar ~GENSYM[n][1];-~GENERATE- for (~SYM[1]=0; ~SYM[1] < ~LIT[3]; ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[select][2]- assign ~RESULT[~SYM[1]] = ~VAR[vec][4][~LIT[1] + (~LIT[2] * ~SYM[1])];- end-~ENDGENERATE-// select end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.++"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "(++) :: Vec n a -> Vec m a -> Vec (n + m) a"- , "template" : "~FROMBV[{~TOBV[~ARG[0]][~TYP[0]],~TOBV[~ARG[1]][~TYP[1]]}][~TYPO]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.concat"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "concat :: Vec n (Vec m a) -> Vec (n * m) a"- , "template" :-"// concat begin-genvar ~GENSYM[n][1];-~GENERATE- for (~SYM[1]=0; ~SYM[1] < $size(~VAR[vec][0]); ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[concat][2]- assign ~RESULT[~SYM[1]*~LENGTH[~TYPEL[~TYP[0]]] : ~SYM[1]*~LENGTH[~TYPEL[~TYP[0]]]+(~LENGTH[~TYPEL[~TYP[0]]]-1)] = ~FROMBV[~VAR[vec][0][\\~SYM[1]\\]][~TYPEL[~TYP[0]]];- end-~ENDGENERATE-// concat end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.splitAt"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "splitAt :: SNat m -> Vec (m + n) a -> (Vec m a, Vec n a)"- , "template" :-"// splitAt begin~IF~LENGTH[~TYPO]~THEN-assign ~RESULT = ~ARG[1];~ELSE-logic [0:~LENGTH[~TYP[1]]-1] [0:~SIZE[~TYPEL[~TYP[1]]]-1] ~GENSYM[vec][0];-assign ~SYM[0] = ~TOBV[~ARG[1]][~TYP[1]];-~GENERATE- if (~LIT[0] == ~LENGTH[~TYP[1]]) begin : ~GENSYM[no_split][1]- assign ~RESULT = {~SYM[0]};- end else begin : ~GENSYM[do_split][2]- assign ~RESULT = {~SYM[0][0:~LIT[0]-1]- ,~SYM[0][~LIT[0]:~LENGTH[~TYP[1]]-1]- };- end-~ENDGENERATE~FI-// splitAt end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.unconcat"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" :- "unconcat :: KnownNat n -- ARG[0]- => SNat m -- ARG[1]- -> Vec (n * m) a -- ARG[2]- -> Vec n (Vec m a)"- , "template" :-"// unconcat begin~DEVNULL[~ARG[0]]-genvar ~GENSYM[n][1];-~GENERATE- for (~SYM[1] = 0; ~SYM[1] < $size(~RESULT); ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[unconcat][2]- assign ~RESULT[~SYM[1]] = ~TOBV[~VAR[vec][2][\\(~SYM[1] * ~LIT[1]) : ((~SYM[1] * ~LIT[1]) + ~LIT[1] - 1)\\]][~TYPEL[~TYPO]];- end-~ENDGENERATE-// unconcat end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.map"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "map :: (a -> b) -> Vec n a -> Vec n b"- , "template" :-"// map begin-genvar ~GENSYM[n][1];-~GENERATE-for (~SYM[1]=0; ~SYM[1] < $size(~RESULT); ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[map][2]~IF~SIZE[~TYP[1]]~THEN- ~TYPEL[~TYP[1]] ~GENSYM[map_in][3];- assign ~SYM[3] = ~FROMBV[~VAR[vec][1][\\~SYM[1]\\]][~TYPEL[~TYP[1]]];~ELSE ~FI- ~TYPEL[~TYPO] ~GENSYM[map_out][4];- ~INST 0- ~OUTPUT <= ~SYM[4]~ ~TYPEL[~TYPO]~- ~INPUT <= ~SYM[3]~ ~TYPEL[~TYP[1]]~- ~INST- assign ~RESULT[~SYM[1]] = ~TOBV[~SYM[4]][~TYPEL[~TYPO]];-end-~ENDGENERATE-// map end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.imap"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "imap :: KnownNat n => (Index n -> a -> b) -> Vec n a -> Vec n b"- , "template" :-"// imap begin-genvar ~GENSYM[n][1];-~GENERATE-for (~SYM[1]=0; ~SYM[1] < $size(~RESULT); ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[imap][2]- ~INDEXTYPE[~LIT[0]] ~GENSYM[i][3];- assign ~SYM[3] = ~SYM[1];~IF~SIZE[~TYP[2]]~THEN- ~TYPEL[~TYP[2]] ~GENSYM[imap_in][4];- assign ~SYM[4] = ~FROMBV[~VAR[vec][2][\\~SYM[1]\\]][~TYPEL[~TYP[2]]];~ELSE ~FI- ~TYPEL[~TYPO] ~GENSYM[imap_out][5];- ~INST 1- ~OUTPUT <= ~SYM[5]~ ~TYPEL[~TYPO]~- ~INPUT <= ~SYM[3]~ ~INDEXTYPE[~LIT[0]]~- ~INPUT <= ~SYM[4]~ ~TYPEL[~TYP[2]]~- ~INST- assign ~RESULT[~SYM[1]] = ~TOBV[~SYM[5]][~TYPEL[~TYPO]];-end-~ENDGENERATE-// imap end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.imap_go"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "imap_go :: Index n -> (Index n -> a -> b) -> Vec m a -> Vec m b"- , "template" :-"// imap begin-genvar ~GENSYM[n][1];-~GENERATE-for (~SYM[1]=0; ~SYM[1] < $size(~RESULT); ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[imap][2]- ~TYP[0] ~GENSYM[i][3];- assign ~SYM[3] = ~SYM[1] + ~ARG[0];~IF~SIZE[~TYP[2]]~THEN- ~TYPEL[~TYP[2]] ~GENSYM[imap_in][4];- assign ~SYM[4] = ~FROMBV[~VAR[vec][2][\\~SYM[1]\\]][~TYPEL[~TYP[2]]];~ELSE ~FI- ~TYPEL[~TYPO] ~GENSYM[imap_out][5];- ~INST 1- ~OUTPUT <= ~SYM[5]~ ~TYPEL[~TYPO]~- ~INPUT <= ~SYM[3]~ ~TYP[0]~- ~INPUT <= ~SYM[4]~ ~TYPEL[~TYP[2]]~- ~INST- assign ~RESULT[~SYM[1]] = ~TOBV[~SYM[5]][~TYPEL[~TYPO]];-end-~ENDGENERATE-// imap end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.zipWith"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "zipWith :: (a -> b -> c) -> Vec n a -> Vec n b -> Vec n c"- , "template" :-"// zipWith begin-genvar ~GENSYM[n][2];-~GENERATE-for (~SYM[2] = 0; ~SYM[2] < $size(~RESULT); ~SYM[2] = ~SYM[2] + 1) begin : ~GENSYM[zipWith][3]~IF~SIZE[~TYP[1]]~THEN- ~TYPEL[~TYP[1]] ~GENSYM[zipWith_in1][4];- assign ~SYM[4] = ~FROMBV[~VAR[vec1][1][\\~SYM[2]\\]][~TYPEL[~TYP[1]]];~ELSE ~FI~IF~SIZE[~TYP[2]]~THEN- ~TYPEL[~TYP[2]] ~GENSYM[zipWith_in2][5];- assign ~SYM[5] = ~FROMBV[~VAR[vec2][2][\\~SYM[2]\\]][~TYPEL[~TYP[2]]];~ELSE ~FI- ~TYPEL[~TYPO] ~GENSYM[zipWith_out][6];- ~INST 0- ~OUTPUT <= ~SYM[6]~ ~TYPEL[~TYPO]~- ~INPUT <= ~SYM[4]~ ~TYPEL[~TYP[1]]~- ~INPUT <= ~SYM[5]~ ~TYPEL[~TYP[2]]~- ~INST- assign ~RESULT[~SYM[2]] = ~TOBV[~SYM[6]][~TYPEL[~TYPO]];-end-~ENDGENERATE-// zipWith end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.foldr"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "foldr :: (a -> b -> b) -> b -> Vec n a -> b"- , "template" :-"// foldr start~IF ~LENGTH[~TYP[2]] ~THEN-~SIGDO[~GENSYM[intermediate][0]] [0:~LENGTH[~TYP[2]]];-assign ~SYM[0][~LENGTH[~TYP[2]]] = ~ARG[1];--genvar ~GENSYM[i][3];-~GENERATE-for (~SYM[3]=0; ~SYM[3] < ~LENGTH[~TYP[2]]; ~SYM[3]=~SYM[3]+1) begin : ~GENSYM[foldr_loop][4]~IF~SIZE[~TYP[2]]~THEN- ~TYPEL[~TYP[2]] ~GENSYM[foldr_in][5];- assign ~SYM[5] = ~FROMBV[~VAR[xs][2][\\~SYM[3]\\]][~TYPEL[~TYP[2]]];~ELSE ~FI- ~INST 0- ~OUTPUT <= ~SYM[0][~SYM[3]]~ ~TYP[1]~- ~INPUT <= ~SYM[5]~ ~TYPEL[~TYP[2]]~- ~INPUT <= ~SYM[0][~SYM[3]+1]~ ~TYP[1]~- ~INST-end-~ENDGENERATE--assign ~RESULT = ~SYM[0][0];-~ELSE-assign ~RESULT = ~ARG[1];-~FI// foldr end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.index_int"- , "kind" : "Expression"- , "type" : "index_int :: KnownNat n => Vec n a -> Int -> a"- , "template" : "~IF~SIZE[~TYP[1]]~THEN~FROMBV[~VAR[vec][1][\\~ARG[2]\\]][~TYPO]~ELSE~ERRORO~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.replace_int"- , "kind" : "Declaration"- , "type" : "replace_int :: KnownNat n => Vec n a -> Int -> a -> Vec n a"- , "template" :-"// replaceVec start-always_comb begin- ~RESULT = ~ARG[1];- ~RESULT[~ARG[2]] = ~TOBV[~ARG[3]][~TYP[3]];-end-// replaceVec end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.replicate"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "replicate :: SNat n -> a -> Vec n a"- , "template" : "'{~LIT[0] {~TOBV[~ARG[1]][~TYP[1]]}}"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.transpose"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "transpose :: KnownNat n => Vec m (Vec n a) -> Vec n (Vec m a)"- , "template" :-"// transpose begin-genvar ~GENSYM[row_index][1];-genvar ~GENSYM[col_index][2];-~GENERATE- for (~SYM[1] = 0; ~SYM[1] < $size(~VAR[matrix][1]); ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[transpose_outer][3]- for (~SYM[2] = 0; ~SYM[2] < $size(~RESULT); ~SYM[2] = ~SYM[2] + 1) begin : ~GENSYM[transpose_inner][4]~IF ~VIVADO ~THEN- assign ~RESULT[~SYM[2]][($size(~VAR[matrix][1])-~SYM[1])*~SIZE[~TYPEL[~TYPEL[~TYPO]]]-1 : ($size(~VAR[matrix][1])-~SYM[1]-1)*~SIZE[~TYPEL[~TYPEL[~TYPO]]]] = ~VAR[matrix][1][~SYM[1]][($size(~RESULT)-~SYM[2])*~SIZE[~TYPEL[~TYPEL[~TYPO]]]-1 : ($size(~RESULT)-~SYM[2]-1)*~SIZE[~TYPEL[~TYPEL[~TYPO]]]];~ELSE- assign ~RESULT[~SYM[2]][~SYM[1]] = ~VAR[matrix][1][~SYM[1]][~SYM[2]];~FI- end- end-~ENDGENERATE-// transpose end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.reverse"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "reverse :: Vec n a -> Vec n a"- , "template" :-"// reverse begin-genvar ~GENSYM[n][1];-~GENERATE- for (~SYM[1] = 0; ~SYM[1] < $size(~VAR[vec][0]); ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[reverse][2]- assign ~RESULT[$high(~VAR[vec][0]) - ~SYM[1]] = ~VAR[vec][0][~SYM[1]];- end-~ENDGENERATE-// reverse end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.concatBitVector#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" :-"concatBitVector# :: (KnownNat n,KnownNat m) -- (ARG[0],ARG[1])- => Vec n (BitVector m) -- ARG[2]- -> BitVector (n * m)"- , "template" : "~TOBV[~ARG[2]][~TYP[2]]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.unconcatBitVector#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" :-"unconcatBitVector# :: (KnownNat n, KnownNat m) -- (ARG[0],ARG[1])- => BitVector (n * m) -- ARG[2]- -> Vec n (BitVector m)"- , "template" : "~FROMBV[~ARG[2]][~TYPO]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.rotateLeftS"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "rotateLeftS :: KnownNat n => Vec n a -> SNat d -> Vec n a"- , "template" :-"// rotateLeftS begin-localparam ~GENSYM[shift_amount][2] = ~LIT[2] % ~LIT[0];--~GENERATE-if (~SYM[2] == 0) begin : ~GENSYM[no_shift][3]- assign ~RESULT = ~VAR[vec][1];-end else begin : ~GENSYM[do_shift][4]- assign ~RESULT[0:~LIT[0]-~SYM[2]-1] = ~VAR[vec][1][~SYM[2]:~LIT[0]-1];- assign ~RESULT[~LIT[0]-~SYM[2]:~LIT[0]-1] = ~VAR[vec][1][0:~SYM[2]-1];-end-~ENDGENERATE-// rotateLeftS end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.rotateRightS"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "rotateRightS :: KnownNat n => Vec n a -> SNat d -> Vec n a"- , "template" :-"// rotateRightS begin-localparam ~GENSYM[shift_amount][2] = ~LIT[2] % ~LIT[0];--~GENERATE-if (~SYM[2] == 0) begin : ~GENSYM[no_shift][3]- assign ~RESULT = ~VAR[vec][1];-end else begin : ~GENSYM[do_shift][4]- assign ~RESULT[0:~SYM[2]-1] = ~VAR[vec][1][~LIT[0]-~SYM[2]:~LIT[0]-1];- assign ~RESULT[~SYM[2]:~LIT[0]-1] = ~VAR[vec][1][0:~LIT[0]-~SYM[2]-1];-end-~ENDGENERATE-// rotateRightS end"- }- }-]
+ prims/systemverilog/Clash_Sized_Vector.primitives.yaml view
@@ -0,0 +1,349 @@+- BlackBox:+ name: Clash.Sized.Vector.head+ kind: Expression+ type: 'head :: Vec (n+ + 1) a -> a'+ template: ~FROMBV[~VAR[vec][0][\0\]][~TYPO]+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.tail+ kind: Expression+ type: 'tail :: Vec (n+ + 1) a -> Vec n a'+ template: '~VAR[vec][0][1 : $high(~VAR[vec][0])]'+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.last+ kind: Expression+ type: Vec (n + 1) a ->+ a+ template: ~FROMBV[~VAR[vec][0][\$high(~VAR[vec][0])\]][~TYPO]+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.init+ kind: Expression+ type: Vec (n + 1) a ->+ Vec n a+ template: '~VAR[vec][0][0 : $high(~VAR[vec][0]) - 1]'+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.select+ kind: Declaration+ type: |-+ select :: (CmpNat (i + s) (s * n) ~ GT) -- ARG[0]+ => SNat f -- ARG[1]+ -> SNat s -- ARG[2]+ -> SNat n -- ARG[3]+ -> Vec i a -- ARG[4]+ -> Vec n a+ template: |-+ // select begin+ genvar ~GENSYM[n][1];+ ~GENERATE+ for (~SYM[1]=0; ~SYM[1] < ~LIT[3]; ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[select][2]+ assign ~RESULT[~SYM[1]] = ~VAR[vec][4][~LIT[1] + (~LIT[2] * ~SYM[1])];+ end+ ~ENDGENERATE+ // select end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.+++ kind: Expression+ type: '(++) :: Vec n a+ -> Vec m a -> Vec (n + m) a'+ template: ~FROMBV[{~TOBV[~ARG[0]][~TYP[0]],~TOBV[~ARG[1]][~TYP[1]]}][~TYPO]+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.concat+ kind: Declaration+ type: 'concat :: Vec n+ (Vec m a) -> Vec (n * m) a'+ template: |-+ // concat begin+ genvar ~GENSYM[n][1];+ ~GENERATE+ for (~SYM[1]=0; ~SYM[1] < $size(~VAR[vec][0]); ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[concat][2]+ assign ~RESULT[~SYM[1]*~LENGTH[~TYPEL[~TYP[0]]] : ~SYM[1]*~LENGTH[~TYPEL[~TYP[0]]]+(~LENGTH[~TYPEL[~TYP[0]]]-1)] = ~FROMBV[~VAR[vec][0][\~SYM[1]\]][~TYPEL[~TYP[0]]];+ end+ ~ENDGENERATE+ // concat end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.splitAt+ kind: Declaration+ type: 'splitAt :: SNat+ m -> Vec (m + n) a -> (Vec m a, Vec n a)'+ template: |-+ // splitAt begin~IF~LENGTH[~TYPO]~THEN+ assign ~RESULT = ~ARG[1];~ELSE+ logic [0:~LENGTH[~TYP[1]]-1] [0:~SIZE[~TYPEL[~TYP[1]]]-1] ~GENSYM[vec][0];+ assign ~SYM[0] = ~TOBV[~ARG[1]][~TYP[1]];+ ~GENERATE+ if (~LIT[0] == ~LENGTH[~TYP[1]]) begin : ~GENSYM[no_split][1]+ assign ~RESULT = {~SYM[0]};+ end else begin : ~GENSYM[do_split][2]+ assign ~RESULT = {~SYM[0][0:~LIT[0]-1]+ ,~SYM[0][~LIT[0]:~LENGTH[~TYP[1]]-1]+ };+ end+ ~ENDGENERATE~FI+ // splitAt end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.unconcat+ kind: Declaration+ type: |-+ unconcat :: KnownNat n -- ARG[0]+ => SNat m -- ARG[1]+ -> Vec (n * m) a -- ARG[2]+ -> Vec n (Vec m a)+ template: |-+ // unconcat begin~DEVNULL[~ARG[0]]+ genvar ~GENSYM[n][1];+ ~GENERATE+ for (~SYM[1] = 0; ~SYM[1] < $size(~RESULT); ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[unconcat][2]+ assign ~RESULT[~SYM[1]] = ~TOBV[~VAR[vec][2][\(~SYM[1] * ~LIT[1]) : ((~SYM[1] * ~LIT[1]) + ~LIT[1] - 1)\]][~TYPEL[~TYPO]];+ end+ ~ENDGENERATE+ // unconcat end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.map+ kind: Declaration+ type: 'map :: (a -> b)+ -> Vec n a -> Vec n b'+ template: |-+ // map begin+ genvar ~GENSYM[n][1];+ ~GENERATE+ for (~SYM[1]=0; ~SYM[1] < $size(~RESULT); ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[map][2]~IF~SIZE[~TYP[1]]~THEN+ ~TYPEL[~TYP[1]] ~GENSYM[map_in][3];+ assign ~SYM[3] = ~FROMBV[~VAR[vec][1][\~SYM[1]\]][~TYPEL[~TYP[1]]];~ELSE ~FI+ ~TYPEL[~TYPO] ~GENSYM[map_out][4];+ ~INST 0+ ~OUTPUT <= ~SYM[4]~ ~TYPEL[~TYPO]~+ ~INPUT <= ~SYM[3]~ ~TYPEL[~TYP[1]]~+ ~INST+ assign ~RESULT[~SYM[1]] = ~TOBV[~SYM[4]][~TYPEL[~TYPO]];+ end+ ~ENDGENERATE+ // map end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.imap+ kind: Declaration+ type: 'imap :: KnownNat+ n => (Index n -> a -> b) -> Vec n a -> Vec n b'+ template: |-+ // imap begin+ genvar ~GENSYM[n][1];+ ~GENERATE+ for (~SYM[1]=0; ~SYM[1] < $size(~RESULT); ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[imap][2]+ ~INDEXTYPE[~LIT[0]] ~GENSYM[i][3];+ assign ~SYM[3] = ~SYM[1];~IF~SIZE[~TYP[2]]~THEN+ ~TYPEL[~TYP[2]] ~GENSYM[imap_in][4];+ assign ~SYM[4] = ~FROMBV[~VAR[vec][2][\~SYM[1]\]][~TYPEL[~TYP[2]]];~ELSE ~FI+ ~TYPEL[~TYPO] ~GENSYM[imap_out][5];+ ~INST 1+ ~OUTPUT <= ~SYM[5]~ ~TYPEL[~TYPO]~+ ~INPUT <= ~SYM[3]~ ~INDEXTYPE[~LIT[0]]~+ ~INPUT <= ~SYM[4]~ ~TYPEL[~TYP[2]]~+ ~INST+ assign ~RESULT[~SYM[1]] = ~TOBV[~SYM[5]][~TYPEL[~TYPO]];+ end+ ~ENDGENERATE+ // imap end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.imap_go+ kind: Declaration+ type: 'imap_go :: Index+ n -> (Index n -> a -> b) -> Vec m a -> Vec m b'+ template: |-+ // imap begin+ genvar ~GENSYM[n][1];+ ~GENERATE+ for (~SYM[1]=0; ~SYM[1] < $size(~RESULT); ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[imap][2]+ ~TYP[0] ~GENSYM[i][3];+ assign ~SYM[3] = ~SYM[1] + ~ARG[0];~IF~SIZE[~TYP[2]]~THEN+ ~TYPEL[~TYP[2]] ~GENSYM[imap_in][4];+ assign ~SYM[4] = ~FROMBV[~VAR[vec][2][\~SYM[1]\]][~TYPEL[~TYP[2]]];~ELSE ~FI+ ~TYPEL[~TYPO] ~GENSYM[imap_out][5];+ ~INST 1+ ~OUTPUT <= ~SYM[5]~ ~TYPEL[~TYPO]~+ ~INPUT <= ~SYM[3]~ ~TYP[0]~+ ~INPUT <= ~SYM[4]~ ~TYPEL[~TYP[2]]~+ ~INST+ assign ~RESULT[~SYM[1]] = ~TOBV[~SYM[5]][~TYPEL[~TYPO]];+ end+ ~ENDGENERATE+ // imap end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.zipWith+ kind: Declaration+ type: 'zipWith :: (a ->+ b -> c) -> Vec n a -> Vec n b -> Vec n c'+ template: |-+ // zipWith begin+ genvar ~GENSYM[n][2];+ ~GENERATE+ for (~SYM[2] = 0; ~SYM[2] < $size(~RESULT); ~SYM[2] = ~SYM[2] + 1) begin : ~GENSYM[zipWith][3]~IF~SIZE[~TYP[1]]~THEN+ ~TYPEL[~TYP[1]] ~GENSYM[zipWith_in1][4];+ assign ~SYM[4] = ~FROMBV[~VAR[vec1][1][\~SYM[2]\]][~TYPEL[~TYP[1]]];~ELSE ~FI~IF~SIZE[~TYP[2]]~THEN+ ~TYPEL[~TYP[2]] ~GENSYM[zipWith_in2][5];+ assign ~SYM[5] = ~FROMBV[~VAR[vec2][2][\~SYM[2]\]][~TYPEL[~TYP[2]]];~ELSE ~FI+ ~TYPEL[~TYPO] ~GENSYM[zipWith_out][6];+ ~INST 0+ ~OUTPUT <= ~SYM[6]~ ~TYPEL[~TYPO]~+ ~INPUT <= ~SYM[4]~ ~TYPEL[~TYP[1]]~+ ~INPUT <= ~SYM[5]~ ~TYPEL[~TYP[2]]~+ ~INST+ assign ~RESULT[~SYM[2]] = ~TOBV[~SYM[6]][~TYPEL[~TYPO]];+ end+ ~ENDGENERATE+ // zipWith end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.foldr+ kind: Declaration+ type: 'foldr :: (a ->+ b -> b) -> b -> Vec n a -> b'+ template: |-+ // foldr start~IF ~LENGTH[~TYP[2]] ~THEN+ ~SIGDO[~GENSYM[intermediate][0]] [0:~LENGTH[~TYP[2]]];+ assign ~SYM[0][~LENGTH[~TYP[2]]] = ~ARG[1];++ genvar ~GENSYM[i][3];+ ~GENERATE+ for (~SYM[3]=0; ~SYM[3] < ~LENGTH[~TYP[2]]; ~SYM[3]=~SYM[3]+1) begin : ~GENSYM[foldr_loop][4]~IF~SIZE[~TYP[2]]~THEN+ ~TYPEL[~TYP[2]] ~GENSYM[foldr_in][5];+ assign ~SYM[5] = ~FROMBV[~VAR[xs][2][\~SYM[3]\]][~TYPEL[~TYP[2]]];~ELSE ~FI+ ~INST 0+ ~OUTPUT <= ~SYM[0][~SYM[3]]~ ~TYP[1]~+ ~INPUT <= ~SYM[5]~ ~TYPEL[~TYP[2]]~+ ~INPUT <= ~SYM[0][~SYM[3]+1]~ ~TYP[1]~+ ~INST+ end+ ~ENDGENERATE++ assign ~RESULT = ~SYM[0][0];+ ~ELSE+ assign ~RESULT = ~ARG[1];+ ~FI// foldr end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.index_int+ kind: Expression+ type: 'index_int :: KnownNat+ n => Vec n a -> Int -> a'+ template: ~IF~SIZE[~TYP[1]]~THEN~FROMBV[~VAR[vec][1][\~ARG[2]\]][~TYPO]~ELSE~ERRORO~FI+- BlackBox:+ name: Clash.Sized.Vector.replace_int+ kind: Declaration+ type: 'replace_int ::+ KnownNat n => Vec n a -> Int -> a -> Vec n a'+ template: |-+ // replaceVec start+ always_comb begin+ ~RESULT = ~ARG[1];+ ~RESULT[~ARG[2]] = ~TOBV[~ARG[3]][~TYP[3]];+ end+ // replaceVec end+- BlackBox:+ name: Clash.Sized.Vector.replicate+ kind: Expression+ type: 'replicate :: SNat+ n -> a -> Vec n a'+ template: '''{~LIT[0] {~TOBV[~ARG[1]][~TYP[1]]}}'+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.transpose+ kind: Declaration+ type: 'transpose :: KnownNat+ n => Vec m (Vec n a) -> Vec n (Vec m a)'+ template: |-+ // transpose begin+ genvar ~GENSYM[row_index][1];+ genvar ~GENSYM[col_index][2];+ ~GENERATE+ for (~SYM[1] = 0; ~SYM[1] < $size(~VAR[matrix][1]); ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[transpose_outer][3]+ for (~SYM[2] = 0; ~SYM[2] < $size(~RESULT); ~SYM[2] = ~SYM[2] + 1) begin : ~GENSYM[transpose_inner][4]~IF ~VIVADO ~THEN+ assign ~RESULT[~SYM[2]][($size(~VAR[matrix][1])-~SYM[1])*~SIZE[~TYPEL[~TYPEL[~TYPO]]]-1 : ($size(~VAR[matrix][1])-~SYM[1]-1)*~SIZE[~TYPEL[~TYPEL[~TYPO]]]] = ~VAR[matrix][1][~SYM[1]][($size(~RESULT)-~SYM[2])*~SIZE[~TYPEL[~TYPEL[~TYPO]]]-1 : ($size(~RESULT)-~SYM[2]-1)*~SIZE[~TYPEL[~TYPEL[~TYPO]]]];~ELSE+ assign ~RESULT[~SYM[2]][~SYM[1]] = ~VAR[matrix][1][~SYM[1]][~SYM[2]];~FI+ end+ end+ ~ENDGENERATE+ // transpose end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.reverse+ kind: Declaration+ type: 'reverse :: Vec+ n a -> Vec n a'+ template: |-+ // reverse begin+ genvar ~GENSYM[n][1];+ ~GENERATE+ for (~SYM[1] = 0; ~SYM[1] < $size(~VAR[vec][0]); ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[reverse][2]+ assign ~RESULT[$high(~VAR[vec][0]) - ~SYM[1]] = ~VAR[vec][0][~SYM[1]];+ end+ ~ENDGENERATE+ // reverse end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.concatBitVector#+ kind: Expression+ type: |-+ concatBitVector# :: (KnownNat n,KnownNat m) -- (ARG[0],ARG[1])+ => Vec n (BitVector m) -- ARG[2]+ -> BitVector (n * m)+ template: ~TOBV[~ARG[2]][~TYP[2]]+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.unconcatBitVector#+ kind: Expression+ type: |-+ unconcatBitVector# :: (KnownNat n, KnownNat m) -- (ARG[0],ARG[1])+ => BitVector (n * m) -- ARG[2]+ -> Vec n (BitVector m)+ template: ~FROMBV[~ARG[2]][~TYPO]+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.rotateLeftS+ kind: Declaration+ type: 'rotateLeftS ::+ KnownNat n => Vec n a -> SNat d -> Vec n a'+ template: |-+ // rotateLeftS begin+ localparam ~GENSYM[shift_amount][2] = ~LIT[2] % ~LIT[0];++ ~GENERATE+ if (~SYM[2] == 0) begin : ~GENSYM[no_shift][3]+ assign ~RESULT = ~VAR[vec][1];+ end else begin : ~GENSYM[do_shift][4]+ assign ~RESULT[0:~LIT[0]-~SYM[2]-1] = ~VAR[vec][1][~SYM[2]:~LIT[0]-1];+ assign ~RESULT[~LIT[0]-~SYM[2]:~LIT[0]-1] = ~VAR[vec][1][0:~SYM[2]-1];+ end+ ~ENDGENERATE+ // rotateLeftS end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.rotateRightS+ kind: Declaration+ type: 'rotateRightS ::+ KnownNat n => Vec n a -> SNat d -> Vec n a'+ template: |-+ // rotateRightS begin+ localparam ~GENSYM[shift_amount][2] = ~LIT[2] % ~LIT[0];++ ~GENERATE+ if (~SYM[2] == 0) begin : ~GENSYM[no_shift][3]+ assign ~RESULT = ~VAR[vec][1];+ end else begin : ~GENSYM[do_shift][4]+ assign ~RESULT[0:~SYM[2]-1] = ~VAR[vec][1][~LIT[0]-~SYM[2]:~LIT[0]-1];+ assign ~RESULT[~SYM[2]:~LIT[0]-1] = ~VAR[vec][1][0:~LIT[0]-~SYM[2]-1];+ end+ ~ENDGENERATE+ // rotateRightS end+ workInfo: Never
− prims/systemverilog/Clash_Xilinx_DDR.primitives
@@ -1,92 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Xilinx.DDR.iddr"- , "kind" : "Declaration"- , "type" :-"iddr- :: ( HasCallStack -- ARG[0]- , KnownConfi~ fast domf -- ARG[1]- , KnownConfi~ slow doms -- ARG[2]- , KnownNat m ) -- ARG[3]- -> Clock slow -- ARG[4]- -> Reset slow -- ARG[5]- -> Enable slow -- ARG[6]- -> Signal fast (BitVector m) -- ARG[7]- -> Signal slow (BitVector m,BitVector m)"- , "template" :-"// iddr begin-~SIGD[~GENSYM[dataout_l][1]][7];-~SIGD[~GENSYM[dataout_h][2]][7];-~SIGD[~GENSYM[d][3]][7];-assign ~SYM[3] = ~ARG[7];--genvar ~GENSYM[i][8];-~GENERATE-for (~SYM[8]=0; ~SYM[8] < ~SIZE[~TYP[7]]; ~SYM[8]=~SYM[8]+1) begin : ~GENSYM[ddri_array][7]- IDDR #(- .DDR_CLK_EDGE(\"SAME_EDGE\"),- .INIT_Q1(1'b0),- .INIT_Q2(1'b0),- .SRTYPE(~IF ~ISSYNC[2] ~THEN \"SYNC\" ~ELSE \"ASYNC\" ~FI)- ) ~GENSYM[~COMPNAME_IDDR][9] (- .Q1(~SYM[1][~SYM[8]]),- .Q2(~SYM[2][~SYM[8]]),- .C(~ARG[4]),- .CE(~IF ~ISACTIVEENABLE[6] ~THEN ~ARG[6] ~ELSE 1'b1 ~FI),- .D(~SYM[3][~SYM[8]]),- .R(~ARG[5]),- .S(1'b0)- );-end-~ENDGENERATE--assign ~RESULT = {~SYM[2],~SYM[1]};-// iddr end"- }- }-, { "BlackBox" :- { "name" : "Clash.Xilinx.DDR.oddr#"- , "kind" : "Declaration"- , "type" :-"oddr#- :: ( KnownConfi~ fast domf -- ARG[0]- , KnownConfi~ slow doms -- ARG[1]- , KnownNat m ) -- ARG[2]- => Clock slow -- ARG[3]- -> Reset slow -- ARG[4]- -> Enable slow -- ARG[5]- -> Signal slow (BitVector m) -- ARG[6]- -> Signal slow (BitVector m) -- ARG[7]- -> Signal fast (BitVector m)"- , "template" :-"// oddr begin-~SIGD[~GENSYM[datain_l][1]][7];-~SIGD[~GENSYM[datain_h][2]][7];-~SIGD[~GENSYM[q][3]][7];--assign ~SYM[1] = ~ARG[6];-assign ~SYM[2] = ~ARG[7];--genvar ~GENSYM[i][8];-~GENERATE-for (~SYM[8]=0; ~SYM[8] < ~SIZE[~TYP[7]]; ~SYM[8]=~SYM[8]+1) begin : ~GENSYM[ddro_array][7]- ODDR #(- .DDR_CLK_EDGE(\"SAME_EDGE\"),- .INIT(1'b0),- .SRTYPE(~IF ~ISSYNC[2] ~THEN \"SYNC\" ~ELSE \"ASYNC\" ~FI)- ) ~GENSYM[~COMPNAME_ODDR][9] (- .Q(~SYM[3][~SYM[8]]),- .C(~ARG[3]),- .CE(~IF ~ISACTIVEENABLE[5] ~THEN ~ARG[5] ~ELSE 1'b1 ~FI),- .D1(~SYM[1][~SYM[8]]),- .D2(~SYM[2][~SYM[8]]),- .R(~ARG[4]),- .S(1'b0)- );-end-~ENDGENERATE--assign ~RESULT = ~SYM[3];-// oddr end"- }- }-]
+ prims/systemverilog/Clash_Xilinx_DDR.primitives.yaml view
@@ -0,0 +1,87 @@+- BlackBox:+ name: Clash.Xilinx.DDR.iddr+ kind: Declaration+ type: |-+ iddr+ :: ( HasCallStack -- ARG[0]+ , KnownConfi~ fast domf -- ARG[1]+ , KnownConfi~ slow doms -- ARG[2]+ , KnownNat m ) -- ARG[3]+ -> Clock slow -- ARG[4]+ -> Reset slow -- ARG[5]+ -> Enable slow -- ARG[6]+ -> Signal fast (BitVector m) -- ARG[7]+ -> Signal slow (BitVector m,BitVector m)+ template: |-+ // iddr begin+ ~SIGD[~GENSYM[dataout_l][1]][7];+ ~SIGD[~GENSYM[dataout_h][2]][7];+ ~SIGD[~GENSYM[d][3]][7];+ assign ~SYM[3] = ~ARG[7];++ genvar ~GENSYM[i][8];+ ~GENERATE+ for (~SYM[8]=0; ~SYM[8] < ~SIZE[~TYP[7]]; ~SYM[8]=~SYM[8]+1) begin : ~GENSYM[ddri_array][7]+ IDDR #(+ .DDR_CLK_EDGE("SAME_EDGE"),+ .INIT_Q1(1'b0),+ .INIT_Q2(1'b0),+ .SRTYPE(~IF ~ISSYNC[2] ~THEN "SYNC" ~ELSE "ASYNC" ~FI)+ ) ~GENSYM[~COMPNAME_IDDR][9] (+ .Q1(~SYM[1][~SYM[8]]),+ .Q2(~SYM[2][~SYM[8]]),+ .C(~ARG[4]),+ .CE(~IF ~ISACTIVEENABLE[6] ~THEN ~ARG[6] ~ELSE 1'b1 ~FI),+ .D(~SYM[3][~SYM[8]]),+ .R(~ARG[5]),+ .S(1'b0)+ );+ end+ ~ENDGENERATE++ assign ~RESULT = {~SYM[2],~SYM[1]};+ // iddr end+- BlackBox:+ name: Clash.Xilinx.DDR.oddr#+ kind: Declaration+ type: |-+ oddr#+ :: ( KnownConfi~ fast domf -- ARG[0]+ , KnownConfi~ slow doms -- ARG[1]+ , KnownNat m ) -- ARG[2]+ => Clock slow -- ARG[3]+ -> Reset slow -- ARG[4]+ -> Enable slow -- ARG[5]+ -> Signal slow (BitVector m) -- ARG[6]+ -> Signal slow (BitVector m) -- ARG[7]+ -> Signal fast (BitVector m)+ template: |-+ // oddr begin+ ~SIGD[~GENSYM[datain_l][1]][7];+ ~SIGD[~GENSYM[datain_h][2]][7];+ ~SIGD[~GENSYM[q][3]][7];++ assign ~SYM[1] = ~ARG[6];+ assign ~SYM[2] = ~ARG[7];++ genvar ~GENSYM[i][8];+ ~GENERATE+ for (~SYM[8]=0; ~SYM[8] < ~SIZE[~TYP[7]]; ~SYM[8]=~SYM[8]+1) begin : ~GENSYM[ddro_array][7]+ ODDR #(+ .DDR_CLK_EDGE("SAME_EDGE"),+ .INIT(1'b0),+ .SRTYPE(~IF ~ISSYNC[2] ~THEN "SYNC" ~ELSE "ASYNC" ~FI)+ ) ~GENSYM[~COMPNAME_ODDR][9] (+ .Q(~SYM[3][~SYM[8]]),+ .C(~ARG[3]),+ .CE(~IF ~ISACTIVEENABLE[5] ~THEN ~ARG[5] ~ELSE 1'b1 ~FI),+ .D1(~SYM[1][~SYM[8]]),+ .D2(~SYM[2][~SYM[8]]),+ .R(~ARG[4]),+ .S(1'b0)+ );+ end+ ~ENDGENERATE++ assign ~RESULT = ~SYM[3];+ // oddr end
− prims/systemverilog/GHC_Base.primitives
@@ -1,33 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Base.divInt"- , "kind" : "Declaration"- , "type" : "divInt :: Int -> Int -> Int"- , "template" :-"// divInt begin-// divide (rounds towards zero)-~SIGD[~GENSYM[quot_res][0]][0];-assign ~SYM[0] = ~VAR[dividend][0] / ~VAR[divider][1];--// round toward minus infinity-assign ~RESULT = (~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1]) ? ~SYM[0] : ~SYM[0] - ~SIZE[~TYPO]'sd1;-// divInt end"- }- }-, { "BlackBox" :- { "name" : "GHC.Base.modInt"- , "kind" : "Declaration"- , "type" : "modInt :: Int -> Int -> Int"- , "template" :-"// modInt begin-// remainder-~SIGD[~GENSYM[rem_res][0]][0];-assign ~SYM[0] = ~VAR[dividend][0] % ~VAR[divider][1];--// modulo-assign ~RESULT = (~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1]) ?- ~SYM[0] :- ((~VAR[dividend][0] == ~SIZE[~TYPO]'sd0) ? ~SIZE[~TYPO]'sd0 : ~SYM[0] + ~VAR[divider][1]);-// modInt end"- }- }-]
+ prims/systemverilog/GHC_Base.primitives.yaml view
@@ -0,0 +1,30 @@+- BlackBox:+ name: GHC.Base.divInt+ kind: Declaration+ type: 'divInt :: Int ->+ Int -> Int'+ template: |-+ // divInt begin+ // divide (rounds towards zero)+ ~SIGD[~GENSYM[quot_res][0]][0];+ assign ~SYM[0] = ~VAR[dividend][0] / ~VAR[divider][1];++ // round toward minus infinity+ assign ~RESULT = (~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1]) ? ~SYM[0] : ~SYM[0] - ~SIZE[~TYPO]'sd1;+ // divInt end+- BlackBox:+ name: GHC.Base.modInt+ kind: Declaration+ type: 'modInt :: Int ->+ Int -> Int'+ template: |-+ // modInt begin+ // remainder+ ~SIGD[~GENSYM[rem_res][0]][0];+ assign ~SYM[0] = ~VAR[dividend][0] % ~VAR[divider][1];++ // modulo+ assign ~RESULT = (~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1]) ?+ ~SYM[0] :+ ((~VAR[dividend][0] == ~SIZE[~TYPO]'sd0) ? ~SIZE[~TYPO]'sd0 : ~SYM[0] + ~VAR[divider][1]);+ // modInt end
− prims/systemverilog/GHC_Classes.primitives
@@ -1,45 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Classes.divInt#"- , "kind" : "Declaration"- , "type" : "divInt# :: Int# -> Int# -> Int#"- , "template" :-"// divInt# begin-logic ~GENSYM[resultPos][1];-logic ~GENSYM[dividerNeg][2];-logic signed [~SIZE[~TYPO]:0] ~GENSYM[dividend2][3];-logic signed [~SIZE[~TYPO]:0] ~GENSYM[dividendE][4];-logic signed [~SIZE[~TYPO]:0] ~GENSYM[dividerE][5];-logic signed [~SIZE[~TYPO]:0] ~GENSYM[quot_res][6];--assign ~SYM[1] = ~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1];-assign ~SYM[2] = ~VAR[divider][1][~SIZE[~TYPO]-1] == 1'b1;-assign ~SYM[4] = $signed({{~VAR[dividend][0][~SIZE[~TYPO]-1]},~VAR[dividend][0]}); // sign extension-assign ~SYM[5] = $signed({{~VAR[divider][1][~SIZE[~TYPO]-1]} ,~VAR[divider][1]} ); // sign extension--assign ~SYM[3] = ~SYM[1] ? ~SYM[4]- : (~SYM[2] ? (~SYM[4] - ~SYM[5] - ~SIZE[~TYPO]'sd1)- : (~SYM[4] - ~SYM[5] + ~SIZE[~TYPO]'sd1));--assign ~SYM[6] = ~SYM[3] / ~SYM[5];-assign ~RESULT = $signed(~SYM[6][~SIZE[~TYPO]-1:0]);-// divInt# end"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.modInt#"- , "kind" : "Declaration"- , "type" : "modInt# :: Int# -> Int# -> Int#"- , "template" :-"// modInt# begin-// remainder-~SIGD[~GENSYM[rem_res][0]][0];-assign ~SYM[0] = ~VAR[dividend][0] % ~VAR[divider][1];--// modulo-assign ~RESULT = (~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1]) ?- ~SYM[0] :- ((~SYM[0] == ~SIZE[~TYPO]'sd0) ? ~SIZE[~TYPO]'sd0 : ~SYM[0] + ~VAR[divider][1]);-// modInt# end"- }- }-]
+ prims/systemverilog/GHC_Classes.primitives.yaml view
@@ -0,0 +1,42 @@+- BlackBox:+ name: GHC.Classes.divInt#+ kind: Declaration+ type: 'divInt# :: Int#+ -> Int# -> Int#'+ template: |-+ // divInt# begin+ logic ~GENSYM[resultPos][1];+ logic ~GENSYM[dividerNeg][2];+ logic signed [~SIZE[~TYPO]:0] ~GENSYM[dividend2][3];+ logic signed [~SIZE[~TYPO]:0] ~GENSYM[dividendE][4];+ logic signed [~SIZE[~TYPO]:0] ~GENSYM[dividerE][5];+ logic signed [~SIZE[~TYPO]:0] ~GENSYM[quot_res][6];++ assign ~SYM[1] = ~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1];+ assign ~SYM[2] = ~VAR[divider][1][~SIZE[~TYPO]-1] == 1'b1;+ assign ~SYM[4] = $signed({{~VAR[dividend][0][~SIZE[~TYPO]-1]},~VAR[dividend][0]}); // sign extension+ assign ~SYM[5] = $signed({{~VAR[divider][1][~SIZE[~TYPO]-1]} ,~VAR[divider][1]} ); // sign extension++ assign ~SYM[3] = ~SYM[1] ? ~SYM[4]+ : (~SYM[2] ? (~SYM[4] - ~SYM[5] - ~SIZE[~TYPO]'sd1)+ : (~SYM[4] - ~SYM[5] + ~SIZE[~TYPO]'sd1));++ assign ~SYM[6] = ~SYM[3] / ~SYM[5];+ assign ~RESULT = $signed(~SYM[6][~SIZE[~TYPO]-1:0]);+ // divInt# end+- BlackBox:+ name: GHC.Classes.modInt#+ kind: Declaration+ type: 'modInt# :: Int#+ -> Int# -> Int#'+ template: |-+ // modInt# begin+ // remainder+ ~SIGD[~GENSYM[rem_res][0]][0];+ assign ~SYM[0] = ~VAR[dividend][0] % ~VAR[divider][1];++ // modulo+ assign ~RESULT = (~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1]) ?+ ~SYM[0] :+ ((~SYM[0] == ~SIZE[~TYPO]'sd0) ? ~SIZE[~TYPO]'sd0 : ~SYM[0] + ~VAR[divider][1]);+ // modInt# end
− prims/systemverilog/GHC_Integer_Type.primitives
@@ -1,97 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Integer.Type.divInteger"- , "kind" : "Declaration"- , "type" : "divInteger :: Integer -> Integer -> Integer"- , "template" :-"// divInteger begin-logic ~GENSYM[resultPos][1];-logic ~GENSYM[dividerNeg][2];-logic signed [~SIZE[~TYPO]:0] ~GENSYM[dividend2][3];-logic signed [~SIZE[~TYPO]:0] ~GENSYM[dividendE][4];-logic signed [~SIZE[~TYPO]:0] ~GENSYM[dividerE][5];-logic signed [~SIZE[~TYPO]:0] ~GENSYM[quot_res][6];--assign ~SYM[1] = ~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1];-assign ~SYM[2] = ~VAR[divider][1][~SIZE[~TYPO]-1] == 1'b1;-assign ~SYM[4] = $signed({{~VAR[dividend][0][~SIZE[~TYPO]-1]},~VAR[dividend][0]}); // sign extension-assign ~SYM[5] = $signed({{~VAR[divider][1][~SIZE[~TYPO]-1]} ,~VAR[divider][1]} ); // sign extension--assign ~SYM[3] = ~SYM[1] ? ~SYM[4]- : (~SYM[2] ? (~SYM[4] - ~SYM[5] - ~SIZE[~TYPO]'sd1)- : (~SYM[4] - ~SYM[5] + ~SIZE[~TYPO]'sd1));--assign ~SYM[6] = ~SYM[3] / ~SYM[5];-assign ~RESULT = $signed(~SYM[6][~SIZE[~TYPO]-1:0]);-// divInteger end"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.modInteger"- , "kind" : "Declaration"- , "type" : "modInteger :: Integer -> Integer -> Integer"- , "template" :-"// modInteger begin-// remainder-~SIGD[~GENSYM[rem_res][0]][0];-assign ~SYM[0] = ~VAR[dividend][0] % ~VAR[divider][1];--// modulo-assign ~RESULT = (~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1]) ?- ~SYM[0] :- ((~SYM[0] == ~SIZE[~TYPO]'sd0) ? ~SIZE[~TYPO]'sd0 : ~SYM[0] + ~VAR[divider][1]);-// modInteger end"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.divModInteger"- , "kind" : "Declaration"- , "type" : "divModInteger :: Integer -> Integer -> (# Integer, Integer #)"- , "template" :-"// divModInteger begin-logic ~GENSYM[resultPos][1];-logic ~GENSYM[dividerNeg][2];-logic signed [~SIZE[~TYP[0]]:0] ~GENSYM[dividend2][3];-logic signed [~SIZE[~TYP[0]]:0] ~GENSYM[dividendE][4];-logic signed [~SIZE[~TYP[0]]:0] ~GENSYM[dividerE][5];-logic signed [~SIZE[~TYP[0]]:0] ~GENSYM[quot_res][6];-logic signed [~SIZE[~TYP[0]]-1:0] ~GENSYM[div_res][7];--assign ~SYM[1] = ~VAR[dividend][0][~SIZE[~TYP[0]]-1] == ~VAR[divider][1][~SIZE[~TYP[0]]-1];-assign ~SYM[2] = ~VAR[divider][1][~SIZE[~TYP[0]]-1] == 1'b1;-assign ~SYM[4] = $signed({{~VAR[dividend][0][~SIZE[~TYP[0]]-1]},~VAR[dividend][0]}); // sign extension-assign ~SYM[5] = $signed({{~VAR[divider][1][~SIZE[~TYP[0]]-1]} ,~VAR[divider][1]} ); // sign extension--assign ~SYM[3] = ~SYM[1] ? ~SYM[4]- : (~SYM[2] ? (~SYM[4] - ~SYM[5] - ~SIZE[~TYP[0]]'sd1)- : (~SYM[4] - ~SYM[5] + ~SIZE[~TYP[0]]'sd1));--assign ~SYM[6] = ~SYM[3] / ~SYM[5];-assign ~SYM[7] = $signed(~SYM[6][~SIZE[~TYP[0]]-1:0]);--logic signed [~SIZE[~TYP[0]]-1:0] ~GENSYM[rem_res][8];-logic signed [~SIZE[~TYP[0]]-1:0] ~GENSYM[mod_res][9];-assign ~SYM[8] = ~VAR[dividend][0] % ~VAR[divider][1];-assign ~SYM[9] = (~VAR[dividend][0][~SIZE[~TYP[0]]-1] == ~VAR[divider][1][~SIZE[~TYP[0]]-1]) ?- ~SYM[8] :- ((~SYM[8] == ~SIZE[~TYP[0]]'sd0) ? ~SIZE[~TYP[0]]'sd0 : ~SYM[8] + ~VAR[divider][1]);--assign ~RESULT = {~SYM[7],~SYM[9]};-// divModInteger end"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.quotRemInteger"- , "kind" : "Declaration"- , "type" : "quotRemInteger :: Integer -> Integer -> (# Integer, Integer #)"- , "template" :-"// quotRemInteger begin-~SIGD[~GENSYM[quot_res][0]][0];-~SIGD[~GENSYM[rem_res][1]][0];-assign ~SYM[0] = ~ARG[0] / ~ARG[1];-assign ~SYM[1] = ~ARG[0] % ~ARG[1];--assign ~RESULT = {~SYM[0],~SYM[1]};-// quotRemInteger end"- }- }-]
+ prims/systemverilog/GHC_Integer_Type.primitives.yaml view
@@ -0,0 +1,100 @@+- BlackBox:+ name: GHC.Integer.Type.divInteger+ kind: Declaration+ type: 'divInteger :: Integer+ -> Integer -> Integer'+ template: |-+ // divInteger begin+ logic ~GENSYM[resultPos][1];+ logic ~GENSYM[dividerNeg][2];+ logic signed [~SIZE[~TYPO]:0] ~GENSYM[dividend2][3];+ logic signed [~SIZE[~TYPO]:0] ~GENSYM[dividendE][4];+ logic signed [~SIZE[~TYPO]:0] ~GENSYM[dividerE][5];+ logic signed [~SIZE[~TYPO]:0] ~GENSYM[quot_res][6];++ assign ~SYM[1] = ~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1];+ assign ~SYM[2] = ~VAR[divider][1][~SIZE[~TYPO]-1] == 1'b1;+ assign ~SYM[4] = $signed({{~VAR[dividend][0][~SIZE[~TYPO]-1]},~VAR[dividend][0]}); // sign extension+ assign ~SYM[5] = $signed({{~VAR[divider][1][~SIZE[~TYPO]-1]} ,~VAR[divider][1]} ); // sign extension++ assign ~SYM[3] = ~SYM[1] ? ~SYM[4]+ : (~SYM[2] ? (~SYM[4] - ~SYM[5] - ~SIZE[~TYPO]'sd1)+ : (~SYM[4] - ~SYM[5] + ~SIZE[~TYPO]'sd1));++ assign ~SYM[6] = ~SYM[3] / ~SYM[5];+ assign ~RESULT = $signed(~SYM[6][~SIZE[~TYPO]-1:0]);+ // divInteger end+ warning: 'GHC.Integer.Type.divInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.modInteger+ kind: Declaration+ type: 'modInteger :: Integer+ -> Integer -> Integer'+ template: |-+ // modInteger begin+ // remainder+ ~SIGD[~GENSYM[rem_res][0]][0];+ assign ~SYM[0] = ~VAR[dividend][0] % ~VAR[divider][1];++ // modulo+ assign ~RESULT = (~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1]) ?+ ~SYM[0] :+ ((~SYM[0] == ~SIZE[~TYPO]'sd0) ? ~SIZE[~TYPO]'sd0 : ~SYM[0] + ~VAR[divider][1]);+ // modInteger end+ warning: 'GHC.Integer.Type.modInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.divModInteger+ kind: Declaration+ type: 'divModInteger ::+ Integer -> Integer -> (# Integer, Integer #)'+ template: |-+ // divModInteger begin+ logic ~GENSYM[resultPos][1];+ logic ~GENSYM[dividerNeg][2];+ logic signed [~SIZE[~TYP[0]]:0] ~GENSYM[dividend2][3];+ logic signed [~SIZE[~TYP[0]]:0] ~GENSYM[dividendE][4];+ logic signed [~SIZE[~TYP[0]]:0] ~GENSYM[dividerE][5];+ logic signed [~SIZE[~TYP[0]]:0] ~GENSYM[quot_res][6];+ logic signed [~SIZE[~TYP[0]]-1:0] ~GENSYM[div_res][7];++ assign ~SYM[1] = ~VAR[dividend][0][~SIZE[~TYP[0]]-1] == ~VAR[divider][1][~SIZE[~TYP[0]]-1];+ assign ~SYM[2] = ~VAR[divider][1][~SIZE[~TYP[0]]-1] == 1'b1;+ assign ~SYM[4] = $signed({{~VAR[dividend][0][~SIZE[~TYP[0]]-1]},~VAR[dividend][0]}); // sign extension+ assign ~SYM[5] = $signed({{~VAR[divider][1][~SIZE[~TYP[0]]-1]} ,~VAR[divider][1]} ); // sign extension++ assign ~SYM[3] = ~SYM[1] ? ~SYM[4]+ : (~SYM[2] ? (~SYM[4] - ~SYM[5] - ~SIZE[~TYP[0]]'sd1)+ : (~SYM[4] - ~SYM[5] + ~SIZE[~TYP[0]]'sd1));++ assign ~SYM[6] = ~SYM[3] / ~SYM[5];+ assign ~SYM[7] = $signed(~SYM[6][~SIZE[~TYP[0]]-1:0]);++ logic signed [~SIZE[~TYP[0]]-1:0] ~GENSYM[rem_res][8];+ logic signed [~SIZE[~TYP[0]]-1:0] ~GENSYM[mod_res][9];+ assign ~SYM[8] = ~VAR[dividend][0] % ~VAR[divider][1];+ assign ~SYM[9] = (~VAR[dividend][0][~SIZE[~TYP[0]]-1] == ~VAR[divider][1][~SIZE[~TYP[0]]-1]) ?+ ~SYM[8] :+ ((~SYM[8] == ~SIZE[~TYP[0]]'sd0) ? ~SIZE[~TYP[0]]'sd0 : ~SYM[8] + ~VAR[divider][1]);++ assign ~RESULT = {~SYM[7],~SYM[9]};+ // divModInteger end+ warning: 'GHC.Integer.Type.divModInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.quotRemInteger+ kind: Declaration+ type: 'quotRemInteger+ :: Integer -> Integer -> (# Integer, Integer #)'+ template: |-+ // quotRemInteger begin+ ~SIGD[~GENSYM[quot_res][0]][0];+ ~SIGD[~GENSYM[rem_res][1]][0];+ assign ~SYM[0] = ~ARG[0] / ~ARG[1];+ assign ~SYM[1] = ~ARG[0] % ~ARG[1];++ assign ~RESULT = {~SYM[0],~SYM[1]};+ // quotRemInteger end+ warning: 'GHC.Integer.Type.quotRemInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'
− prims/systemverilog/GHC_Num_Integer.primitives
@@ -1,97 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Num.Integer.integerDiv"- , "kind" : "Declaration"- , "type" : "integerDiv :: Integer -> Integer -> Integer"- , "template" :-"// integerDiv begin-logic ~GENSYM[resultPos][1];-logic ~GENSYM[dividerNeg][2];-logic signed [~SIZE[~TYPO]:0] ~GENSYM[dividend2][3];-logic signed [~SIZE[~TYPO]:0] ~GENSYM[dividendE][4];-logic signed [~SIZE[~TYPO]:0] ~GENSYM[dividerE][5];-logic signed [~SIZE[~TYPO]:0] ~GENSYM[quot_res][6];--assign ~SYM[1] = ~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1];-assign ~SYM[2] = ~VAR[divider][1][~SIZE[~TYPO]-1] == 1'b1;-assign ~SYM[4] = $signed({{~VAR[dividend][0][~SIZE[~TYPO]-1]},~VAR[dividend][0]}); // sign extension-assign ~SYM[5] = $signed({{~VAR[divider][1][~SIZE[~TYPO]-1]} ,~VAR[divider][1]} ); // sign extension--assign ~SYM[3] = ~SYM[1] ? ~SYM[4]- : (~SYM[2] ? (~SYM[4] - ~SYM[5] - ~SIZE[~TYPO]'sd1)- : (~SYM[4] - ~SYM[5] + ~SIZE[~TYPO]'sd1));--assign ~SYM[6] = ~SYM[3] / ~SYM[5];-assign ~RESULT = $signed(~SYM[6][~SIZE[~TYPO]-1:0]);-// integerDiv end"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerMod"- , "kind" : "Declaration"- , "type" : "integerMod :: Integer -> Integer -> Integer"- , "template" :-"// integerMod begin-// remainder-~SIGD[~GENSYM[rem_res][0]][0];-assign ~SYM[0] = ~VAR[dividend][0] % ~VAR[divider][1];--// modulo-assign ~RESULT = (~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1]) ?- ~SYM[0] :- ((~SYM[0] == ~SIZE[~TYPO]'sd0) ? ~SIZE[~TYPO]'sd0 : ~SYM[0] + ~VAR[divider][1]);-// integerMod end"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerDivMod#"- , "kind" : "Declaration"- , "type" : "integerDivMod :: Integer -> Integer -> (# Integer, Integer #)"- , "template" :-"// integerDivMod begin-logic ~GENSYM[resultPos][1];-logic ~GENSYM[dividerNeg][2];-logic signed [~SIZE[~TYP[0]]:0] ~GENSYM[dividend2][3];-logic signed [~SIZE[~TYP[0]]:0] ~GENSYM[dividendE][4];-logic signed [~SIZE[~TYP[0]]:0] ~GENSYM[dividerE][5];-logic signed [~SIZE[~TYP[0]]:0] ~GENSYM[quot_res][6];-logic signed [~SIZE[~TYP[0]]-1:0] ~GENSYM[div_res][7];--assign ~SYM[1] = ~VAR[dividend][0][~SIZE[~TYP[0]]-1] == ~VAR[divider][1][~SIZE[~TYP[0]]-1];-assign ~SYM[2] = ~VAR[divider][1][~SIZE[~TYP[0]]-1] == 1'b1;-assign ~SYM[4] = $signed({{~VAR[dividend][0][~SIZE[~TYP[0]]-1]},~VAR[dividend][0]}); // sign extension-assign ~SYM[5] = $signed({{~VAR[divider][1][~SIZE[~TYP[0]]-1]} ,~VAR[divider][1]} ); // sign extension--assign ~SYM[3] = ~SYM[1] ? ~SYM[4]- : (~SYM[2] ? (~SYM[4] - ~SYM[5] - ~SIZE[~TYP[0]]'sd1)- : (~SYM[4] - ~SYM[5] + ~SIZE[~TYP[0]]'sd1));--assign ~SYM[6] = ~SYM[3] / ~SYM[5];-assign ~SYM[7] = $signed(~SYM[6][~SIZE[~TYP[0]]-1:0]);--logic signed [~SIZE[~TYP[0]]-1:0] ~GENSYM[rem_res][8];-logic signed [~SIZE[~TYP[0]]-1:0] ~GENSYM[mod_res][9];-assign ~SYM[8] = ~VAR[dividend][0] % ~VAR[divider][1];-assign ~SYM[9] = (~VAR[dividend][0][~SIZE[~TYP[0]]-1] == ~VAR[divider][1][~SIZE[~TYP[0]]-1]) ?- ~SYM[8] :- ((~SYM[8] == ~SIZE[~TYP[0]]'sd0) ? ~SIZE[~TYP[0]]'sd0 : ~SYM[8] + ~VAR[divider][1]);--assign ~RESULT = {~SYM[7],~SYM[9]};-// integerDivMod end"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerQuotRem#"- , "kind" : "Declaration"- , "type" : "integerQuotRem :: Integer -> Integer -> (# Integer, Integer #)"- , "template" :-"// integerQuotRem begin-~SIGD[~GENSYM[quot_res][0]][0];-~SIGD[~GENSYM[rem_res][1]][0];-assign ~SYM[0] = ~ARG[0] / ~ARG[1];-assign ~SYM[1] = ~ARG[0] % ~ARG[1];--assign ~RESULT = {~SYM[0],~SYM[1]};-// integerQuotRem end"- }- }-]
+ prims/systemverilog/GHC_Num_Integer.primitives.yaml view
@@ -0,0 +1,100 @@+- BlackBox:+ name: GHC.Num.Integer.integerDiv+ kind: Declaration+ type: 'integerDiv :: Integer+ -> Integer -> Integer'+ template: |-+ // integerDiv begin+ logic ~GENSYM[resultPos][1];+ logic ~GENSYM[dividerNeg][2];+ logic signed [~SIZE[~TYPO]:0] ~GENSYM[dividend2][3];+ logic signed [~SIZE[~TYPO]:0] ~GENSYM[dividendE][4];+ logic signed [~SIZE[~TYPO]:0] ~GENSYM[dividerE][5];+ logic signed [~SIZE[~TYPO]:0] ~GENSYM[quot_res][6];++ assign ~SYM[1] = ~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1];+ assign ~SYM[2] = ~VAR[divider][1][~SIZE[~TYPO]-1] == 1'b1;+ assign ~SYM[4] = $signed({{~VAR[dividend][0][~SIZE[~TYPO]-1]},~VAR[dividend][0]}); // sign extension+ assign ~SYM[5] = $signed({{~VAR[divider][1][~SIZE[~TYPO]-1]} ,~VAR[divider][1]} ); // sign extension++ assign ~SYM[3] = ~SYM[1] ? ~SYM[4]+ : (~SYM[2] ? (~SYM[4] - ~SYM[5] - ~SIZE[~TYPO]'sd1)+ : (~SYM[4] - ~SYM[5] + ~SIZE[~TYPO]'sd1));++ assign ~SYM[6] = ~SYM[3] / ~SYM[5];+ assign ~RESULT = $signed(~SYM[6][~SIZE[~TYPO]-1:0]);+ // integerDiv end+ warning: 'GHC.Num.Integer.integerDiv: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerMod+ kind: Declaration+ type: 'integerMod :: Integer+ -> Integer -> Integer'+ template: |-+ // integerMod begin+ // remainder+ ~SIGD[~GENSYM[rem_res][0]][0];+ assign ~SYM[0] = ~VAR[dividend][0] % ~VAR[divider][1];++ // modulo+ assign ~RESULT = (~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1]) ?+ ~SYM[0] :+ ((~SYM[0] == ~SIZE[~TYPO]'sd0) ? ~SIZE[~TYPO]'sd0 : ~SYM[0] + ~VAR[divider][1]);+ // integerMod end+ warning: 'GHC.Num.Integer.integerMod: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerDivMod#+ kind: Declaration+ type: 'integerDivMod ::+ Integer -> Integer -> (# Integer, Integer #)'+ template: |-+ // integerDivMod begin+ logic ~GENSYM[resultPos][1];+ logic ~GENSYM[dividerNeg][2];+ logic signed [~SIZE[~TYP[0]]:0] ~GENSYM[dividend2][3];+ logic signed [~SIZE[~TYP[0]]:0] ~GENSYM[dividendE][4];+ logic signed [~SIZE[~TYP[0]]:0] ~GENSYM[dividerE][5];+ logic signed [~SIZE[~TYP[0]]:0] ~GENSYM[quot_res][6];+ logic signed [~SIZE[~TYP[0]]-1:0] ~GENSYM[div_res][7];++ assign ~SYM[1] = ~VAR[dividend][0][~SIZE[~TYP[0]]-1] == ~VAR[divider][1][~SIZE[~TYP[0]]-1];+ assign ~SYM[2] = ~VAR[divider][1][~SIZE[~TYP[0]]-1] == 1'b1;+ assign ~SYM[4] = $signed({{~VAR[dividend][0][~SIZE[~TYP[0]]-1]},~VAR[dividend][0]}); // sign extension+ assign ~SYM[5] = $signed({{~VAR[divider][1][~SIZE[~TYP[0]]-1]} ,~VAR[divider][1]} ); // sign extension++ assign ~SYM[3] = ~SYM[1] ? ~SYM[4]+ : (~SYM[2] ? (~SYM[4] - ~SYM[5] - ~SIZE[~TYP[0]]'sd1)+ : (~SYM[4] - ~SYM[5] + ~SIZE[~TYP[0]]'sd1));++ assign ~SYM[6] = ~SYM[3] / ~SYM[5];+ assign ~SYM[7] = $signed(~SYM[6][~SIZE[~TYP[0]]-1:0]);++ logic signed [~SIZE[~TYP[0]]-1:0] ~GENSYM[rem_res][8];+ logic signed [~SIZE[~TYP[0]]-1:0] ~GENSYM[mod_res][9];+ assign ~SYM[8] = ~VAR[dividend][0] % ~VAR[divider][1];+ assign ~SYM[9] = (~VAR[dividend][0][~SIZE[~TYP[0]]-1] == ~VAR[divider][1][~SIZE[~TYP[0]]-1]) ?+ ~SYM[8] :+ ((~SYM[8] == ~SIZE[~TYP[0]]'sd0) ? ~SIZE[~TYP[0]]'sd0 : ~SYM[8] + ~VAR[divider][1]);++ assign ~RESULT = {~SYM[7],~SYM[9]};+ // integerDivMod end+ warning: 'GHC.Num.Integer.integerDivMod#: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerQuotRem#+ kind: Declaration+ type: 'integerQuotRem+ :: Integer -> Integer -> (# Integer, Integer #)'+ template: |-+ // integerQuotRem begin+ ~SIGD[~GENSYM[quot_res][0]][0];+ ~SIGD[~GENSYM[rem_res][1]][0];+ assign ~SYM[0] = ~ARG[0] / ~ARG[1];+ assign ~SYM[1] = ~ARG[0] % ~ARG[1];++ assign ~RESULT = {~SYM[0],~SYM[1]};+ // integerQuotRem end+ warning: 'GHC.Num.Integer.integerQuotRem#: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'
− prims/systemverilog/GHC_Prim.primitives
@@ -1,1459 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Prim.quotRemInt#"- , "kind" : "Declaration"- , "type" : "quotRemInt# :: Int# -> Int# -> (#Int#, Int##)"- , "template" :-"// quotRemInt begin-~SIGD[~GENSYM[quot_res][0]][0];-~SIGD[~GENSYM[rem_res][1]][0];-assign ~SYM[0] = ~ARG[0] / ~ARG[1];-assign ~SYM[1] = ~ARG[0] % ~ARG[1];--assign ~RESULT = {~SYM[0],~SYM[1]};-// quotRemInt end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.quotRemWord#"- , "kind" : "Declaration"- , "type" : "quotRemWord# :: Word# -> Word# -> (#Word#, Word##)"- , "template" :-"// quotRemWord begin-~SIGD[~GENSYM[quot_res][0]][0];-~SIGD[~GENSYM[rem_res][1]][0];-assign ~SYM[0] = ~ARG[0] / ~ARG[1];-assign ~SYM[1] = ~ARG[0] % ~ARG[1];--assign ~RESULT = {~SYM[0],~SYM[1]};-// quotRemWord end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.popCnt8#"- , "kind" : "Declaration"- , "type" : "popCnt8# :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "depth2Index"- , "extension" : "inc"- , "template" :-"// given a level and a depth, calculate the corresponding index into the-// intermediate array-function integer ~INCLUDENAME[0];- input integer levels;- input integer depth;-- ~INCLUDENAME[0] = (2 ** levels) - (2 ** depth);-endfunction"- }- ]- , "template" :-"// popCnt8 begin-localparam ~GENSYM[width][0] = 8;--// depth of the tree-localparam ~GENSYM[levels][2] = $clog2(~SYM[0]);--logic [~SYM[2]:0] ~GENSYM[intermediate][3] [0:(2*~SYM[0])-2];--// put input into the first half of the intermediate array-genvar ~GENSYM[i][4];-~GENERATE-for (~SYM[4] = 0; ~SYM[4] < ~SYM[0]; ~SYM[4]=~SYM[4]+1) begin : ~GENSYM[mk_array][11]- assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]);-end-~ENDGENERATE--// Create the tree of instantiated components-genvar ~GENSYM[d][6];-genvar ~GENSYM[i][7];-~GENERATE-if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]- for (~SYM[6] = ~SYM[2]; ~SYM[6] > 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]- for (~SYM[7] = 0; ~SYM[7] < (2**(~SYM[6]-1)); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]- assign ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6])+~SYM[7]] =- ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])] +- ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])+1];- end- end-end-~ENDGENERATE--// The last element of the intermediate array holds the result-assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);-// popCnt8 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.popCnt16#"- , "kind" : "Declaration"- , "type" : "popCnt16# :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "depth2Index"- , "extension" : "inc"- , "template" :-"// given a level and a depth, calculate the corresponding index into the-// intermediate array-function integer ~INCLUDENAME[0];- input integer levels;- input integer depth;-- ~INCLUDENAME[0] = (2 ** levels) - (2 ** depth);-endfunction"- }- ]- , "template" :-"// popCnt16 begin-localparam ~GENSYM[width][0] = 16;--// depth of the tree-localparam ~GENSYM[levels][2] = $clog2(~SYM[0]);--logic [~SYM[2]:0] ~GENSYM[intermediate][3] [0:(2*~SYM[0])-2];--// put input into the first half of the intermediate array-genvar ~GENSYM[i][4];-~GENERATE-for (~SYM[4] = 0; ~SYM[4] < ~SYM[0]; ~SYM[4]=~SYM[4]+1) begin : ~GENSYM[mk_array][11]- assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]);-end-~ENDGENERATE--// Create the tree of instantiated components-genvar ~GENSYM[d][6];-genvar ~GENSYM[i][7];-~GENERATE-if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]- for (~SYM[6] = ~SYM[2]; ~SYM[6] > 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]- for (~SYM[7] = 0; ~SYM[7] < (2**(~SYM[6]-1)); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]- assign ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6])+~SYM[7]] =- ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])] +- ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])+1];- end- end-end-~ENDGENERATE--// The last element of the intermediate array holds the result-assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);-// popCnt16 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.popCnt32#"- , "kind" : "Declaration"- , "type" : "popCnt32# :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "depth2Index"- , "extension" : "inc"- , "template" :-"// given a level and a depth, calculate the corresponding index into the-// intermediate array-function integer ~INCLUDENAME[0];- input integer levels;- input integer depth;-- ~INCLUDENAME[0] = (2 ** levels) - (2 ** depth);-endfunction"- }- ]- , "template" :-"// popCnt32 begin-localparam ~GENSYM[width][0] = 32;--// depth of the tree-localparam ~GENSYM[levels][2] = $clog2(~SYM[0]);--logic [~SYM[2]:0] ~GENSYM[intermediate][3] [0:(2*~SYM[0])-2];--// put input into the first half of the intermediate array-genvar ~GENSYM[i][4];-~GENERATE-for (~SYM[4] = 0; ~SYM[4] < ~SYM[0]; ~SYM[4]=~SYM[4]+1) begin : ~GENSYM[mk_array][11]- assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]);-end-~ENDGENERATE--// Create the tree of instantiated components-genvar ~GENSYM[d][6];-genvar ~GENSYM[i][7];-~GENERATE-if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]- for (~SYM[6] = ~SYM[2]; ~SYM[6] > 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]- for (~SYM[7] = 0; ~SYM[7] < (2**(~SYM[6]-1)); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]- assign ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6])+~SYM[7]] =- ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])] +- ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])+1];- end- end-end-~ENDGENERATE--// The last element of the intermediate array holds the result-assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);-// popCnt32 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.popCnt64#"- , "kind" : "Declaration"- , "type" : "popCnt64# :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "depth2Index"- , "extension" : "inc"- , "template" :-"// given a level and a depth, calculate the corresponding index into the-// intermediate array-function integer ~INCLUDENAME[0];- input integer levels;- input integer depth;-- ~INCLUDENAME[0] = (2 ** levels) - (2 ** depth);-endfunction"- }- ]- , "template" :-"// popCnt64 begin-localparam ~GENSYM[width][0] = 64;--// depth of the tree-localparam ~GENSYM[levels][2] = $clog2(~SYM[0]);--logic [~SYM[2]:0] ~GENSYM[intermediate][3] [0:(2*~SYM[0])-2];--// put input into the first half of the intermediate array-genvar ~GENSYM[i][4];-~GENERATE-for (~SYM[4] = 0; ~SYM[4] < ~SYM[0]; ~SYM[4]=~SYM[4]+1) begin : ~GENSYM[mk_array][11]- assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]);-end-~ENDGENERATE--// Create the tree of instantiated components-genvar ~GENSYM[d][6];-genvar ~GENSYM[i][7];-~GENERATE-if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]- for (~SYM[6] = ~SYM[2]; ~SYM[6] > 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]- for (~SYM[7] = 0; ~SYM[7] < (2**(~SYM[6]-1)); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]- assign ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6])+~SYM[7]] =- ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])] +- ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])+1];- end- end-end-~ENDGENERATE--// The last element of the intermediate array holds the result-assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);-// popCnt64 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.popCnt#"- , "kind" : "Declaration"- , "type" : "popCnt# :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "depth2Index"- , "extension" : "inc"- , "template" :-"// given a level and a depth, calculate the corresponding index into the-// intermediate array-function integer ~INCLUDENAME[0];- input integer levels;- input integer depth;-- ~INCLUDENAME[0] = (2 ** levels) - (2 ** depth);-endfunction"- }- ]- , "template" :-"// popCnt begin-localparam ~GENSYM[width][0] = ~SIZE[~TYPO];--// depth of the tree-localparam ~GENSYM[levels][2] = $clog2(~SYM[0]);--logic [~SYM[2]:0] ~GENSYM[intermediate][3] [0:(2*~SYM[0])-2];--// put input into the first half of the intermediate array-genvar ~GENSYM[i][4];-~GENERATE-for (~SYM[4] = 0; ~SYM[4] < ~SYM[0]; ~SYM[4]=~SYM[4]+1) begin : ~GENSYM[mk_array][11]- assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]);-end-~ENDGENERATE--// Create the tree of instantiated components-genvar ~GENSYM[d][6];-genvar ~GENSYM[i][7];-~GENERATE-if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]- for (~SYM[6] = ~SYM[2]; ~SYM[6] > 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]- for (~SYM[7] = 0; ~SYM[7] < (2**(~SYM[6]-1)); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]- assign ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6])+~SYM[7]] =- ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])] +- ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])+1];- end- end-end-~ENDGENERATE--// The last element of the intermediate array holds the result-assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);-// popCnt end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.clz8#"- , "kind" : "Declaration"- , "type" : "clz8 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "enc"- , "extension" : "inc"- , "template" :-"function [1:0] ~INCLUDENAME[0];- input [1:0] a;- case (a)- 2'b00: ~INCLUDENAME[0] = 2'b10;- 2'b01: ~INCLUDENAME[0] = 2'b01;- 2'b10: ~INCLUDENAME[0] = 2'b00;- default: ~INCLUDENAME[0] = 2'b00;- endcase-endfunction"- }- ]- , "template" :-"// clz8 begin-logic [0:7] ~GENSYM[v][1];-assign ~SYM[1] = ~VAR[i][0][7:0];--logic [0:7] ~GENSYM[e][2];-genvar ~GENSYM[n][3];-~GENERATE-for (~SYM[3]=0;~SYM[3]<4;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]- assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);-end-~ENDGENERATE--logic [0:5] ~GENSYM[a][4];-genvar ~GENSYM[i1][5];-~GENERATE-for (~SYM[5]=0;~SYM[5]<2;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage1][6]- localparam n = 2;- logic [3:0] i;- assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:3] ~GENSYM[res][7];-~GENERATE-if (1) begin-localparam n = 3;-logic [5:0] i;-assign i = ~SYM[4][0:5];-always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase-end-end-~ENDGENERATE--assign ~RESULT = $unsigned(~SYM[7]);-// clz8 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.clz16#"- , "kind" : "Declaration"- , "type" : "clz16 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "enc"- , "extension" : "inc"- , "template" :-"function [1:0] ~INCLUDENAME[0];- input [1:0] a;- case (a)- 2'b00: ~INCLUDENAME[0] = 2'b10;- 2'b01: ~INCLUDENAME[0] = 2'b01;- 2'b10: ~INCLUDENAME[0] = 2'b00;- default: ~INCLUDENAME[0] = 2'b00;- endcase-endfunction"- }- ]- , "template" :-"// clz16 begin-logic [0:15] ~GENSYM[v][1];-assign ~SYM[1] = ~VAR[i][0][15:0];--logic [0:15] ~GENSYM[e][2];-genvar ~GENSYM[i][3];-~GENERATE-for (~SYM[3]=0;~SYM[3]<8;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]- assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);-end-~ENDGENERATE--logic [0:11] ~GENSYM[a][4];-genvar ~GENSYM[i1][5];-~GENERATE-for (~SYM[5]=0;~SYM[5]<4;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]- localparam n = 2;- logic [3:0] i;- assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:7] ~GENSYM[b][9];-genvar ~GENSYM[i2][10];-~GENERATE-for (~SYM[10]=0;~SYM[10]<2;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]- localparam n = 3;- logic [5:0] i;- assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:4] ~GENSYM[res][7];-~GENERATE-if (1) begin-localparam n = 4;-logic [7:0] i;-assign i = ~SYM[9][0:7];-always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase-end-end-~ENDGENERATE--assign ~RESULT = $unsigned(~SYM[7]);-// clz16 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.clz32#"- , "kind" : "Declaration"- , "type" : "clz32 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "enc"- , "extension" : "inc"- , "template" :-"function [1:0] ~INCLUDENAME[0];- input [1:0] a;- case (a)- 2'b00: ~INCLUDENAME[0] = 2'b10;- 2'b01: ~INCLUDENAME[0] = 2'b01;- 2'b10: ~INCLUDENAME[0] = 2'b00;- default: ~INCLUDENAME[0] = 2'b00;- endcase-endfunction"- }- ]- , "template" :-"// clz32 begin-logic [0:31] ~GENSYM[v][1];-assign ~SYM[1] = ~VAR[i][0][31:0];--logic [0:31] ~GENSYM[e][2];-genvar ~GENSYM[i][3];-~GENERATE-for (~SYM[3]=0;~SYM[3]<16;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]- assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);-end-~ENDGENERATE--logic [0:23] ~GENSYM[a][4];-genvar ~GENSYM[i1][5];-~GENERATE-for (~SYM[5]=0;~SYM[5]<8;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]- localparam n = 2;- logic [3:0] i;- assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:15] ~GENSYM[b][9];-genvar ~GENSYM[i2][10];-~GENERATE-for (~SYM[10]=0;~SYM[10]<4;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]- localparam n = 3;- logic [5:0] i;- assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:9] ~GENSYM[c][12];-genvar ~GENSYM[i3][13];-~GENERATE-for (~SYM[13]=0;~SYM[13]<2;~SYM[13]=~SYM[13]+1) begin : ~GENSYM[mux_stage3][14]- localparam n = 4;- logic [7:0] i;- assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:5] ~GENSYM[res][7];-~GENERATE-if (1) begin-localparam n = 5;-logic [9:0] i;-assign i = ~SYM[12][0:9];-always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase-end-end-~ENDGENERATE--assign ~RESULT = $unsigned(~SYM[7]);-// clz32 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.clz64#"- , "kind" : "Declaration"- , "type" : "clz64 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "enc"- , "extension" : "inc"- , "template" :-"function [1:0] ~INCLUDENAME[0];- input [1:0] a;- case (a)- 2'b00: ~INCLUDENAME[0] = 2'b10;- 2'b01: ~INCLUDENAME[0] = 2'b01;- 2'b10: ~INCLUDENAME[0] = 2'b00;- default: ~INCLUDENAME[0] = 2'b00;- endcase-endfunction"- }- ]- , "template" :-"// clz64 begin-logic [0:63] ~GENSYM[v][1];-assign ~SYM[1] = ~VAR[i][0][63:0];--logic [0:63] ~GENSYM[e][2];-genvar ~GENSYM[i][3];-~GENERATE-for (~SYM[3]=0;~SYM[3]<32;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]- assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);-end-~ENDGENERATE--logic [0:47] ~GENSYM[a][4];-genvar ~GENSYM[i1][5];-~GENERATE-for (~SYM[5]=0;~SYM[5]<16;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]- localparam n = 2;- logic [3:0] i;- assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:31] ~GENSYM[b][9];-genvar ~GENSYM[i2][10];-~GENERATE-for (~SYM[10]=0;~SYM[10]<8;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]- localparam n = 3;- logic [5:0] i;- assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:19] ~GENSYM[c][12];-genvar ~GENSYM[i3][13];-~GENERATE-for (~SYM[13]=0;~SYM[13]<4;~SYM[13]=~SYM[13]+1) begin : ~GENSYM[mux_stage3][14]- localparam n = 4;- logic [7:0] i;- assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:11] ~GENSYM[d][15];-genvar ~GENSYM[i4][16];-~GENERATE-for (~SYM[16]=0;~SYM[16]<2;~SYM[16]=~SYM[16]+1) begin : ~GENSYM[mux_stage4][17]- localparam n = 5;- logic [9:0] i;- assign i = ~SYM[12][~SYM[16]*10:~SYM[16]*10+9];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:6] ~GENSYM[res][7];-~GENERATE-if (1) begin-localparam n = 6;-logic [11:0] i;-assign i = ~SYM[15][0:11];-always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase-end-end-~ENDGENERATE--assign ~RESULT = $unsigned(~SYM[7]);-// clz64 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.clz#"- , "kind" : "Declaration"- , "type" : "clz :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "enc"- , "extension" : "inc"- , "template" :-"function [1:0] ~INCLUDENAME[0];- input [1:0] a;- case (a)- 2'b00: ~INCLUDENAME[0] = 2'b10;- 2'b01: ~INCLUDENAME[0] = 2'b01;- 2'b10: ~INCLUDENAME[0] = 2'b00;- default: ~INCLUDENAME[0] = 2'b00;- endcase-endfunction"- }- ]- , "template" :-"// clz begin-~IF ~IW64 ~THEN-logic [0:63] ~GENSYM[v][1];-assign ~SYM[1] = ~VAR[i][0][63:0];--logic [0:63] ~GENSYM[e][2];-genvar ~GENSYM[i][3];-~GENERATE-for (~SYM[3]=0;~SYM[3]<32;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]- assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);-end-~ENDGENERATE--logic [0:47] ~GENSYM[a][4];-genvar ~GENSYM[i1][5];-~GENERATE-for (~SYM[5]=0;~SYM[5]<16;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]- localparam n = 2;- logic [3:0] i;- assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:31] ~GENSYM[b][9];-genvar ~GENSYM[i2][10];-~GENERATE-for (~SYM[10]=0;~SYM[10]<8;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]- localparam n = 3;- logic [5:0] i;- assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:19] ~GENSYM[c][12];-genvar ~GENSYM[i3][13];-~GENERATE-for (~SYM[13]=0;~SYM[13]<4;~SYM[13]=~SYM[13]+1) begin : ~GENSYM[mux_stage3][14]- localparam n = 4;- logic [7:0] i;- assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:11] ~GENSYM[d][15];-genvar ~GENSYM[i4][16];-~GENERATE-for (~SYM[16]=0;~SYM[16]<2;~SYM[16]=~SYM[16]+1) begin : ~GENSYM[mux_stage4][17]- localparam n = 5;- logic [9:0] i;- assign i = ~SYM[12][~SYM[16]*10:~SYM[16]*10+9];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:6] ~GENSYM[res][7];-~GENERATE-if (1) begin-localparam n = 6;-logic [11:0] i;-assign i = ~SYM[15][0:11];-always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase-end-end-~ENDGENERATE-~ELSE-logic [0:31] ~SYM[1];-assign ~SYM[1] = ~VAR[i][0][31:0];--logic [0:31] ~SYM[2];-genvar ~SYM[3];-~GENERATE-for (~SYM[3]=0;~SYM[3]<16;~SYM[3]=~SYM[3]+1) begin : ~SYM[8]- assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);-end-~ENDGENERATE--logic [0:23] ~SYM[4];-genvar ~SYM[5];-~GENERATE-for (~SYM[5]=0;~SYM[5]<8;~SYM[5]=~SYM[5]+1) begin : ~SYM[6]- localparam n = 2;- logic [3:0] i;- assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:15] ~SYM[9];-genvar ~SYM[10];-~GENERATE-for (~SYM[10]=0;~SYM[10]<4;~SYM[10]=~SYM[10]+1) begin : ~SYM[11]- localparam n = 3;- logic [5:0] i;- assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:9] ~SYM[12];-genvar ~SYM[13];-~GENERATE-for (~SYM[13]=0;~SYM[13]<2;~SYM[13]=~SYM[13]+1) begin : ~SYM[14]- localparam n = 4;- logic [7:0] i;- assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:5] ~SYM[7];-~GENERATE-if (1) begin-localparam n = 5;-logic [9:0] i;-assign i = ~SYM[12][0:9];-always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase-end-end-~ENDGENERATE-~FI-assign ~RESULT = $unsigned(~SYM[7]);-// clz end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ctz8#"- , "kind" : "Declaration"- , "type" : "ctz8 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "enc"- , "extension" : "inc"- , "template" :-"function [1:0] ~INCLUDENAME[0];- input [1:0] a;- case (a)- 2'b00: ~INCLUDENAME[0] = 2'b10;- 2'b01: ~INCLUDENAME[0] = 2'b01;- 2'b10: ~INCLUDENAME[0] = 2'b00;- default: ~INCLUDENAME[0] = 2'b00;- endcase-endfunction"- }- ]- , "template" :-"// ctz8 begin-logic [0:7] ~GENSYM[v][1];-genvar ~GENSYM[k][18];-~GENERATE-for (~SYM[18]=0;~SYM[18]<8;~SYM[18]=~SYM[18]+1) begin : ~GENSYM[reverse][19]- assign ~SYM[1][~SYM[18]] = ~ARG[0][~SYM[18]];-end-~ENDGENERATE--logic [0:7] ~GENSYM[e][2];-genvar ~GENSYM[i][3];-~GENERATE-for (~SYM[3]=0;~SYM[3]<4;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]- assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);-end-~ENDGENERATE--logic [0:5] ~GENSYM[a][4];-genvar ~GENSYM[i1][5];-~GENERATE-for (~SYM[5]=0;~SYM[5]<2;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]- localparam n = 2;- logic [3:0] i;- assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:3] ~GENSYM[res][7];-~GENERATE-if (1) begin-localparam n = 3;-logic [5:0] i;-assign i = ~SYM[4][0:5];-always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase-end-end-~ENDGENERATE--assign ~RESULT = $unsigned(~SYM[7]);-// ctz8 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ctz16#"- , "kind" : "Declaration"- , "type" : "ctz16 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "enc"- , "extension" : "inc"- , "template" :-"function [1:0] ~INCLUDENAME[0];- input [1:0] a;- case (a)- 2'b00: ~INCLUDENAME[0] = 2'b10;- 2'b01: ~INCLUDENAME[0] = 2'b01;- 2'b10: ~INCLUDENAME[0] = 2'b00;- default: ~INCLUDENAME[0] = 2'b00;- endcase-endfunction"- }- ]- , "template" :-"// ctz16 begin-logic [0:15] ~GENSYM[v][1];-genvar ~GENSYM[k][18];-~GENERATE-for (~SYM[18]=0;~SYM[18]<16;~SYM[18]=~SYM[18]+1) begin : ~GENSYM[reverse][19]- assign ~SYM[1][~SYM[18]] = ~ARG[0][~SYM[18]];-end-~ENDGENERATE--logic [0:15] ~GENSYM[e][2];-genvar ~GENSYM[i][3];-~GENERATE-for (~SYM[3]=0;~SYM[3]<8;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]- assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);-end-~ENDGENERATE--logic [0:11] ~GENSYM[a][4];-genvar ~GENSYM[i1][5];-~GENERATE-for (~SYM[5]=0;~SYM[5]<4;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]- localparam n = 2;- logic [3:0] i;- assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:7] ~GENSYM[b][9];-genvar ~GENSYM[i2][10];-~GENERATE-for (~SYM[10]=0;~SYM[10]<2;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]- localparam n = 3;- logic [5:0] i;- assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:4] ~GENSYM[res][7];-~GENERATE-if (1) begin-localparam n = 4;-logic [7:0] i;-assign i = ~SYM[9][0:7];-always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase-end-end-~ENDGENERATE--assign ~RESULT = $unsigned(~SYM[7]);-// ctz16 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ctz32#"- , "kind" : "Declaration"- , "type" : "ctz32 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "enc"- , "extension" : "inc"- , "template" :-"function [1:0] ~INCLUDENAME[0];- input [1:0] a;- case (a)- 2'b00: ~INCLUDENAME[0] = 2'b10;- 2'b01: ~INCLUDENAME[0] = 2'b01;- 2'b10: ~INCLUDENAME[0] = 2'b00;- default: ~INCLUDENAME[0] = 2'b00;- endcase-endfunction"- }- ]- , "template" :-"// ctz32 begin-logic [0:31] ~GENSYM[v][1];-genvar ~GENSYM[k][18];-~GENERATE-for (~SYM[18]=0;~SYM[18]<32;~SYM[18]=~SYM[18]+1) begin : ~GENSYM[reverse][19]- assign ~SYM[1][~SYM[18]] = ~ARG[0][~SYM[18]];-end-~ENDGENERATE--logic [0:31] ~GENSYM[e][2];-genvar ~GENSYM[i][3];-~GENERATE-for (~SYM[3]=0;~SYM[3]<16;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]- assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);-end-~ENDGENERATE--logic [0:23] ~GENSYM[a][4];-genvar ~GENSYM[i1][5];-~GENERATE-for (~SYM[5]=0;~SYM[5]<8;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]- localparam n = 2;- logic [3:0] i;- assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:15] ~GENSYM[b][9];-genvar ~GENSYM[i2][10];-~GENERATE-for (~SYM[10]=0;~SYM[10]<4;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]- localparam n = 3;- logic [5:0] i;- assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:9] ~GENSYM[c][12];-genvar ~GENSYM[i3][13];-~GENERATE-for (~SYM[13]=0;~SYM[13]<2;~SYM[13]=~SYM[13]+1) begin : ~GENSYM[mux_stage3][14]- localparam n = 4;- logic [7:0] i;- assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:5] ~GENSYM[res][7];-~GENERATE-if (1) begin-localparam n = 5;-logic [9:0] i;-assign i = ~SYM[12][0:9];-always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase-end-end-~ENDGENERATE--assign ~RESULT = $unsigned(~SYM[7]);-// ctz32 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ctz64#"- , "kind" : "Declaration"- , "type" : "ctz64 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "enc"- , "extension" : "inc"- , "template" :-"function [1:0] ~INCLUDENAME[0];- input [1:0] a;- case (a)- 2'b00: ~INCLUDENAME[0] = 2'b10;- 2'b01: ~INCLUDENAME[0] = 2'b01;- 2'b10: ~INCLUDENAME[0] = 2'b00;- default: ~INCLUDENAME[0] = 2'b00;- endcase-endfunction"- }- ]- , "template" :-"// ctz64 begin-logic [0:63] ~GENSYM[v][1];-genvar ~GENSYM[k][18];-~GENERATE-for (~SYM[18]=0;~SYM[18]<64;~SYM[18]=~SYM[18]+1) begin : ~GENSYM[reverse][19]- assign ~SYM[1][~SYM[18]] = ~ARG[0][~SYM[18]];-end-~ENDGENERATE--logic [0:63] ~GENSYM[e][2];-genvar ~GENSYM[i][3];-~GENERATE-for (~SYM[3]=0;~SYM[3]<32;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]- assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);-end-~ENDGENERATE--logic [0:47] a;-genvar ~GENSYM[i1][5];-~GENERATE-for (~SYM[5]=0;~SYM[5]<16;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]- localparam n = 2;- logic [3:0] i;- assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:31] ~GENSYM[b][9];-genvar ~GENSYM[i2][10];-~GENERATE-for (~SYM[10]=0;~SYM[10]<8;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]- localparam n = 3;- logic [5:0] i;- assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:19] ~GENSYM[c][12];-genvar ~GENSYM[i3][13];-~GENERATE-for (~SYM[13]=0;~SYM[13]<4;~SYM[13]=~SYM[13]+1) begin : ~GENSYM[mux_stage3][14]- localparam n = 4;- logic [7:0] i;- assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:11] ~GENSYM[d][15];-genvar ~GENSYM[i4][16];-~GENERATE-for (~SYM[16]=0;~SYM[16]<2;~SYM[16]=~SYM[16]+1) begin : ~GENSYM[mux_stage4][17]- localparam n = 5;- logic [9:0] i;- assign i = ~SYM[12][~SYM[16]*10:~SYM[16]*10+9];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:6] ~GENSYM[res][7];-~GENERATE-if (1) begin-localparam n = 6;-logic [11:0] i;-assign i = ~SYM[15][0:11];-always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase-end-end-~ENDGENERATE--assign ~RESULT = $unsigned(~SYM[7]);-// ctz64 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ctz#"- , "kind" : "Declaration"- , "type" : "ctz :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "enc"- , "extension" : "inc"- , "template" :-"function [1:0] ~INCLUDENAME[0];- input [1:0] a;- case (a)- 2'b00: ~INCLUDENAME[0] = 2'b10;- 2'b01: ~INCLUDENAME[0] = 2'b01;- 2'b10: ~INCLUDENAME[0] = 2'b00;- default: ~INCLUDENAME[0] = 2'b00;- endcase-endfunction"- }- ]- , "template" :-"// ctz begin-~IF ~IW64 ~THEN-logic [0:63] ~GENSYM[v][1];-genvar ~GENSYM[k][18];-~GENERATE-for (~SYM[18]=0;~SYM[18]<64;~SYM[18]=~SYM[18]+1) begin : ~GENSYM[reverse][19]- assign ~SYM[1][~SYM[18]] = ~ARG[0][~SYM[18]];-end-~ENDGENERATE--logic [0:63] ~GENSYM[e][2];-genvar ~GENSYM[i][3];-~GENERATE-for (~SYM[3]=0;~SYM[3]<32;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]- assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);-end-~ENDGENERATE--logic [0:47] ~GENSYM[a][4];-genvar ~GENSYM[i1][5];-~GENERATE-for (~SYM[5]=0;~SYM[5]<16;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]- localparam n = 2;- logic [3:0] i;- assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:31] ~GENSYM[b][9];-genvar ~GENSYM[i2][10];-~GENERATE-for (~SYM[10]=0;~SYM[10]<8;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]- localparam n = 3;- logic [5:0] i;- assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:19] ~GENSYM[c][12];-genvar ~GENSYM[i3][13];-~GENERATE-for (~SYM[13]=0;~SYM[13]<4;~SYM[13]=~SYM[13]+1) begin : ~GENSYM[mux_stage3][14]- localparam n = 4;- logic [7:0] i;- assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:11] ~GENSYM[d][15];-genvar ~GENSYM[i4][16];-~GENERATE-for (~SYM[16]=0;~SYM[16]<2;~SYM[16]=~SYM[16]+1) begin : ~GENSYM[mux_stage4][17]- localparam n = 5;- logic [9:0] i;- assign i = ~SYM[12][~SYM[16]*10:~SYM[16]*10+9];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:6] ~GENSYM[res][7];-~GENERATE-if (1) begin-localparam n = 6;-logic [11:0] i;-assign i = ~SYM[15][0:11];-always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase-end-end-~ENDGENERATE-~ELSE-logic [0:31] ~SYM[1];-genvar ~SYM[18];-~GENERATE-for (~SYM[18]=0;~SYM[18]<32;~SYM[18]=~SYM[18]+1) begin : ~SYM[19]- assign ~SYM[1][~SYM[18]] = ~ARG[0][~SYM[18]];-end-~ENDGENERATE--logic [0:31] ~SYM[2];-genvar ~SYM[3];-~GENERATE-for (~SYM[3]=0;~SYM[3]<16;~SYM[3]=~SYM[3]+1) begin : ~SYM[8]- assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);-end-~ENDGENERATE--logic [0:23] ~SYM[4];-genvar ~SYM[5];-~GENERATE-for (~SYM[5]=0;~SYM[5]<8;~SYM[5]=~SYM[5]+1) begin : ~SYM[6]- localparam n = 2;- logic [3:0] i;- assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:15] ~SYM[9];-genvar ~SYM[10];-~GENERATE-for (~SYM[10]=0;~SYM[10]<4;~SYM[10]=~SYM[10]+1) begin : ~SYM[11]- localparam n = 3;- logic [5:0] i;- assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:9] ~SYM[12];-genvar ~SYM[13];-~GENERATE-for (~SYM[13]=0;~SYM[13]<2;~SYM[13]=~SYM[13]+1) begin : ~SYM[14]- localparam n = 4;- logic [7:0] i;- assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];- always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--logic [0:5] ~SYM[7];-~GENERATE-if (1) begin-localparam n = 5;-logic [9:0] i;-assign i = ~SYM[12][0:9];-always_comb begin- case (i[n-1+n])- 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase-end-end-~ENDGENERATE-~FI-assign ~RESULT = $unsigned(~SYM[7]);-// ctz end"- }- }-]
+ prims/systemverilog/GHC_Prim.primitives.yaml view
@@ -0,0 +1,1426 @@+- BlackBox:+ name: GHC.Prim.quotRemInt#+ kind: Declaration+ type: 'quotRemInt# ::+ Int# -> Int# -> (#Int#, Int##)'+ template: |-+ // quotRemInt begin+ ~SIGD[~GENSYM[quot_res][0]][0];+ ~SIGD[~GENSYM[rem_res][1]][0];+ assign ~SYM[0] = ~ARG[0] / ~ARG[1];+ assign ~SYM[1] = ~ARG[0] % ~ARG[1];++ assign ~RESULT = {~SYM[0],~SYM[1]};+ // quotRemInt end+- BlackBox:+ name: GHC.Prim.quotRemWord#+ kind: Declaration+ type: 'quotRemWord# ::+ Word# -> Word# -> (#Word#, Word##)'+ template: |-+ // quotRemWord begin+ ~SIGD[~GENSYM[quot_res][0]][0];+ ~SIGD[~GENSYM[rem_res][1]][0];+ assign ~SYM[0] = ~ARG[0] / ~ARG[1];+ assign ~SYM[1] = ~ARG[0] % ~ARG[1];++ assign ~RESULT = {~SYM[0],~SYM[1]};+ // quotRemWord end+- BlackBox:+ name: GHC.Prim.popCnt8#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: depth2Index+ extension: inc+ template: |-+ // given a level and a depth, calculate the corresponding index into the+ // intermediate array+ function integer ~INCLUDENAME[0];+ input integer levels;+ input integer depth;++ ~INCLUDENAME[0] = (2 ** levels) - (2 ** depth);+ endfunction+ kind: Declaration+ type: 'popCnt8# :: Word#+ -> Word#'+ template: |-+ // popCnt8 begin+ localparam ~GENSYM[width][0] = 8;++ // depth of the tree+ localparam ~GENSYM[levels][2] = $clog2(~SYM[0]);++ logic [~SYM[2]:0] ~GENSYM[intermediate][3] [0:(2*~SYM[0])-2];++ // put input into the first half of the intermediate array+ genvar ~GENSYM[i][4];+ ~GENERATE+ for (~SYM[4] = 0; ~SYM[4] < ~SYM[0]; ~SYM[4]=~SYM[4]+1) begin : ~GENSYM[mk_array][11]+ assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]);+ end+ ~ENDGENERATE++ // Create the tree of instantiated components+ genvar ~GENSYM[d][6];+ genvar ~GENSYM[i][7];+ ~GENERATE+ if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]+ for (~SYM[6] = ~SYM[2]; ~SYM[6] > 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]+ for (~SYM[7] = 0; ~SYM[7] < (2**(~SYM[6]-1)); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]+ assign ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6])+~SYM[7]] =+ ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])] ++ ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])+1];+ end+ end+ end+ ~ENDGENERATE++ // The last element of the intermediate array holds the result+ assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);+ // popCnt8 end+- BlackBox:+ name: GHC.Prim.popCnt16#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: depth2Index+ extension: inc+ template: |-+ // given a level and a depth, calculate the corresponding index into the+ // intermediate array+ function integer ~INCLUDENAME[0];+ input integer levels;+ input integer depth;++ ~INCLUDENAME[0] = (2 ** levels) - (2 ** depth);+ endfunction+ kind: Declaration+ type: 'popCnt16# :: Word#+ -> Word#'+ template: |-+ // popCnt16 begin+ localparam ~GENSYM[width][0] = 16;++ // depth of the tree+ localparam ~GENSYM[levels][2] = $clog2(~SYM[0]);++ logic [~SYM[2]:0] ~GENSYM[intermediate][3] [0:(2*~SYM[0])-2];++ // put input into the first half of the intermediate array+ genvar ~GENSYM[i][4];+ ~GENERATE+ for (~SYM[4] = 0; ~SYM[4] < ~SYM[0]; ~SYM[4]=~SYM[4]+1) begin : ~GENSYM[mk_array][11]+ assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]);+ end+ ~ENDGENERATE++ // Create the tree of instantiated components+ genvar ~GENSYM[d][6];+ genvar ~GENSYM[i][7];+ ~GENERATE+ if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]+ for (~SYM[6] = ~SYM[2]; ~SYM[6] > 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]+ for (~SYM[7] = 0; ~SYM[7] < (2**(~SYM[6]-1)); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]+ assign ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6])+~SYM[7]] =+ ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])] ++ ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])+1];+ end+ end+ end+ ~ENDGENERATE++ // The last element of the intermediate array holds the result+ assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);+ // popCnt16 end+- BlackBox:+ name: GHC.Prim.popCnt32#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: depth2Index+ extension: inc+ template: |-+ // given a level and a depth, calculate the corresponding index into the+ // intermediate array+ function integer ~INCLUDENAME[0];+ input integer levels;+ input integer depth;++ ~INCLUDENAME[0] = (2 ** levels) - (2 ** depth);+ endfunction+ kind: Declaration+ type: 'popCnt32# :: Word#+ -> Word#'+ template: |-+ // popCnt32 begin+ localparam ~GENSYM[width][0] = 32;++ // depth of the tree+ localparam ~GENSYM[levels][2] = $clog2(~SYM[0]);++ logic [~SYM[2]:0] ~GENSYM[intermediate][3] [0:(2*~SYM[0])-2];++ // put input into the first half of the intermediate array+ genvar ~GENSYM[i][4];+ ~GENERATE+ for (~SYM[4] = 0; ~SYM[4] < ~SYM[0]; ~SYM[4]=~SYM[4]+1) begin : ~GENSYM[mk_array][11]+ assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]);+ end+ ~ENDGENERATE++ // Create the tree of instantiated components+ genvar ~GENSYM[d][6];+ genvar ~GENSYM[i][7];+ ~GENERATE+ if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]+ for (~SYM[6] = ~SYM[2]; ~SYM[6] > 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]+ for (~SYM[7] = 0; ~SYM[7] < (2**(~SYM[6]-1)); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]+ assign ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6])+~SYM[7]] =+ ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])] ++ ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])+1];+ end+ end+ end+ ~ENDGENERATE++ // The last element of the intermediate array holds the result+ assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);+ // popCnt32 end+- BlackBox:+ name: GHC.Prim.popCnt64#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: depth2Index+ extension: inc+ template: |-+ // given a level and a depth, calculate the corresponding index into the+ // intermediate array+ function integer ~INCLUDENAME[0];+ input integer levels;+ input integer depth;++ ~INCLUDENAME[0] = (2 ** levels) - (2 ** depth);+ endfunction+ kind: Declaration+ type: 'popCnt64# :: Word#+ -> Word#'+ template: |-+ // popCnt64 begin+ localparam ~GENSYM[width][0] = 64;++ // depth of the tree+ localparam ~GENSYM[levels][2] = $clog2(~SYM[0]);++ logic [~SYM[2]:0] ~GENSYM[intermediate][3] [0:(2*~SYM[0])-2];++ // put input into the first half of the intermediate array+ genvar ~GENSYM[i][4];+ ~GENERATE+ for (~SYM[4] = 0; ~SYM[4] < ~SYM[0]; ~SYM[4]=~SYM[4]+1) begin : ~GENSYM[mk_array][11]+ assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]);+ end+ ~ENDGENERATE++ // Create the tree of instantiated components+ genvar ~GENSYM[d][6];+ genvar ~GENSYM[i][7];+ ~GENERATE+ if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]+ for (~SYM[6] = ~SYM[2]; ~SYM[6] > 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]+ for (~SYM[7] = 0; ~SYM[7] < (2**(~SYM[6]-1)); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]+ assign ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6])+~SYM[7]] =+ ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])] ++ ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])+1];+ end+ end+ end+ ~ENDGENERATE++ // The last element of the intermediate array holds the result+ assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);+ // popCnt64 end+- BlackBox:+ name: GHC.Prim.popCnt#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: depth2Index+ extension: inc+ template: |-+ // given a level and a depth, calculate the corresponding index into the+ // intermediate array+ function integer ~INCLUDENAME[0];+ input integer levels;+ input integer depth;++ ~INCLUDENAME[0] = (2 ** levels) - (2 ** depth);+ endfunction+ kind: Declaration+ type: 'popCnt# :: Word#+ -> Word#'+ template: |-+ // popCnt begin+ localparam ~GENSYM[width][0] = ~SIZE[~TYPO];++ // depth of the tree+ localparam ~GENSYM[levels][2] = $clog2(~SYM[0]);++ logic [~SYM[2]:0] ~GENSYM[intermediate][3] [0:(2*~SYM[0])-2];++ // put input into the first half of the intermediate array+ genvar ~GENSYM[i][4];+ ~GENERATE+ for (~SYM[4] = 0; ~SYM[4] < ~SYM[0]; ~SYM[4]=~SYM[4]+1) begin : ~GENSYM[mk_array][11]+ assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]);+ end+ ~ENDGENERATE++ // Create the tree of instantiated components+ genvar ~GENSYM[d][6];+ genvar ~GENSYM[i][7];+ ~GENERATE+ if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]+ for (~SYM[6] = ~SYM[2]; ~SYM[6] > 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]+ for (~SYM[7] = 0; ~SYM[7] < (2**(~SYM[6]-1)); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]+ assign ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6])+~SYM[7]] =+ ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])] ++ ~SYM[3][~INCLUDENAME[0](~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])+1];+ end+ end+ end+ ~ENDGENERATE++ // The last element of the intermediate array holds the result+ assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);+ // popCnt end+- BlackBox:+ name: GHC.Prim.clz8#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: enc+ extension: inc+ template: |-+ function [1:0] ~INCLUDENAME[0];+ input [1:0] a;+ case (a)+ 2'b00: ~INCLUDENAME[0] = 2'b10;+ 2'b01: ~INCLUDENAME[0] = 2'b01;+ 2'b10: ~INCLUDENAME[0] = 2'b00;+ default: ~INCLUDENAME[0] = 2'b00;+ endcase+ endfunction+ kind: Declaration+ type: 'clz8 :: Word# ->+ Word#'+ template: |-+ // clz8 begin+ logic [0:7] ~GENSYM[v][1];+ assign ~SYM[1] = ~VAR[i][0][7:0];++ logic [0:7] ~GENSYM[e][2];+ genvar ~GENSYM[n][3];+ ~GENERATE+ for (~SYM[3]=0;~SYM[3]<4;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ end+ ~ENDGENERATE++ logic [0:5] ~GENSYM[a][4];+ genvar ~GENSYM[i1][5];+ ~GENERATE+ for (~SYM[5]=0;~SYM[5]<2;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage1][6]+ localparam n = 2;+ logic [3:0] i;+ assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:3] ~GENSYM[res][7];+ ~GENERATE+ if (1) begin+ localparam n = 3;+ logic [5:0] i;+ assign i = ~SYM[4][0:5];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ assign ~RESULT = $unsigned(~SYM[7]);+ // clz8 end+- BlackBox:+ name: GHC.Prim.clz16#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: enc+ extension: inc+ template: |-+ function [1:0] ~INCLUDENAME[0];+ input [1:0] a;+ case (a)+ 2'b00: ~INCLUDENAME[0] = 2'b10;+ 2'b01: ~INCLUDENAME[0] = 2'b01;+ 2'b10: ~INCLUDENAME[0] = 2'b00;+ default: ~INCLUDENAME[0] = 2'b00;+ endcase+ endfunction+ kind: Declaration+ type: 'clz16 :: Word#+ -> Word#'+ template: |-+ // clz16 begin+ logic [0:15] ~GENSYM[v][1];+ assign ~SYM[1] = ~VAR[i][0][15:0];++ logic [0:15] ~GENSYM[e][2];+ genvar ~GENSYM[i][3];+ ~GENERATE+ for (~SYM[3]=0;~SYM[3]<8;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ end+ ~ENDGENERATE++ logic [0:11] ~GENSYM[a][4];+ genvar ~GENSYM[i1][5];+ ~GENERATE+ for (~SYM[5]=0;~SYM[5]<4;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]+ localparam n = 2;+ logic [3:0] i;+ assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:7] ~GENSYM[b][9];+ genvar ~GENSYM[i2][10];+ ~GENERATE+ for (~SYM[10]=0;~SYM[10]<2;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]+ localparam n = 3;+ logic [5:0] i;+ assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:4] ~GENSYM[res][7];+ ~GENERATE+ if (1) begin+ localparam n = 4;+ logic [7:0] i;+ assign i = ~SYM[9][0:7];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ assign ~RESULT = $unsigned(~SYM[7]);+ // clz16 end+- BlackBox:+ name: GHC.Prim.clz32#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: enc+ extension: inc+ template: |-+ function [1:0] ~INCLUDENAME[0];+ input [1:0] a;+ case (a)+ 2'b00: ~INCLUDENAME[0] = 2'b10;+ 2'b01: ~INCLUDENAME[0] = 2'b01;+ 2'b10: ~INCLUDENAME[0] = 2'b00;+ default: ~INCLUDENAME[0] = 2'b00;+ endcase+ endfunction+ kind: Declaration+ type: 'clz32 :: Word#+ -> Word#'+ template: |-+ // clz32 begin+ logic [0:31] ~GENSYM[v][1];+ assign ~SYM[1] = ~VAR[i][0][31:0];++ logic [0:31] ~GENSYM[e][2];+ genvar ~GENSYM[i][3];+ ~GENERATE+ for (~SYM[3]=0;~SYM[3]<16;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ end+ ~ENDGENERATE++ logic [0:23] ~GENSYM[a][4];+ genvar ~GENSYM[i1][5];+ ~GENERATE+ for (~SYM[5]=0;~SYM[5]<8;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]+ localparam n = 2;+ logic [3:0] i;+ assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:15] ~GENSYM[b][9];+ genvar ~GENSYM[i2][10];+ ~GENERATE+ for (~SYM[10]=0;~SYM[10]<4;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]+ localparam n = 3;+ logic [5:0] i;+ assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:9] ~GENSYM[c][12];+ genvar ~GENSYM[i3][13];+ ~GENERATE+ for (~SYM[13]=0;~SYM[13]<2;~SYM[13]=~SYM[13]+1) begin : ~GENSYM[mux_stage3][14]+ localparam n = 4;+ logic [7:0] i;+ assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:5] ~GENSYM[res][7];+ ~GENERATE+ if (1) begin+ localparam n = 5;+ logic [9:0] i;+ assign i = ~SYM[12][0:9];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ assign ~RESULT = $unsigned(~SYM[7]);+ // clz32 end+- BlackBox:+ name: GHC.Prim.clz64#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: enc+ extension: inc+ template: |-+ function [1:0] ~INCLUDENAME[0];+ input [1:0] a;+ case (a)+ 2'b00: ~INCLUDENAME[0] = 2'b10;+ 2'b01: ~INCLUDENAME[0] = 2'b01;+ 2'b10: ~INCLUDENAME[0] = 2'b00;+ default: ~INCLUDENAME[0] = 2'b00;+ endcase+ endfunction+ kind: Declaration+ type: 'clz64 :: Word#+ -> Word#'+ template: |-+ // clz64 begin+ logic [0:63] ~GENSYM[v][1];+ assign ~SYM[1] = ~VAR[i][0][63:0];++ logic [0:63] ~GENSYM[e][2];+ genvar ~GENSYM[i][3];+ ~GENERATE+ for (~SYM[3]=0;~SYM[3]<32;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ end+ ~ENDGENERATE++ logic [0:47] ~GENSYM[a][4];+ genvar ~GENSYM[i1][5];+ ~GENERATE+ for (~SYM[5]=0;~SYM[5]<16;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]+ localparam n = 2;+ logic [3:0] i;+ assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:31] ~GENSYM[b][9];+ genvar ~GENSYM[i2][10];+ ~GENERATE+ for (~SYM[10]=0;~SYM[10]<8;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]+ localparam n = 3;+ logic [5:0] i;+ assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:19] ~GENSYM[c][12];+ genvar ~GENSYM[i3][13];+ ~GENERATE+ for (~SYM[13]=0;~SYM[13]<4;~SYM[13]=~SYM[13]+1) begin : ~GENSYM[mux_stage3][14]+ localparam n = 4;+ logic [7:0] i;+ assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:11] ~GENSYM[d][15];+ genvar ~GENSYM[i4][16];+ ~GENERATE+ for (~SYM[16]=0;~SYM[16]<2;~SYM[16]=~SYM[16]+1) begin : ~GENSYM[mux_stage4][17]+ localparam n = 5;+ logic [9:0] i;+ assign i = ~SYM[12][~SYM[16]*10:~SYM[16]*10+9];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:6] ~GENSYM[res][7];+ ~GENERATE+ if (1) begin+ localparam n = 6;+ logic [11:0] i;+ assign i = ~SYM[15][0:11];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ assign ~RESULT = $unsigned(~SYM[7]);+ // clz64 end+- BlackBox:+ name: GHC.Prim.clz#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: enc+ extension: inc+ template: |-+ function [1:0] ~INCLUDENAME[0];+ input [1:0] a;+ case (a)+ 2'b00: ~INCLUDENAME[0] = 2'b10;+ 2'b01: ~INCLUDENAME[0] = 2'b01;+ 2'b10: ~INCLUDENAME[0] = 2'b00;+ default: ~INCLUDENAME[0] = 2'b00;+ endcase+ endfunction+ kind: Declaration+ type: 'clz :: Word# ->+ Word#'+ template: |-+ // clz begin+ ~IF ~IW64 ~THEN+ logic [0:63] ~GENSYM[v][1];+ assign ~SYM[1] = ~VAR[i][0][63:0];++ logic [0:63] ~GENSYM[e][2];+ genvar ~GENSYM[i][3];+ ~GENERATE+ for (~SYM[3]=0;~SYM[3]<32;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ end+ ~ENDGENERATE++ logic [0:47] ~GENSYM[a][4];+ genvar ~GENSYM[i1][5];+ ~GENERATE+ for (~SYM[5]=0;~SYM[5]<16;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]+ localparam n = 2;+ logic [3:0] i;+ assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:31] ~GENSYM[b][9];+ genvar ~GENSYM[i2][10];+ ~GENERATE+ for (~SYM[10]=0;~SYM[10]<8;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]+ localparam n = 3;+ logic [5:0] i;+ assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:19] ~GENSYM[c][12];+ genvar ~GENSYM[i3][13];+ ~GENERATE+ for (~SYM[13]=0;~SYM[13]<4;~SYM[13]=~SYM[13]+1) begin : ~GENSYM[mux_stage3][14]+ localparam n = 4;+ logic [7:0] i;+ assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:11] ~GENSYM[d][15];+ genvar ~GENSYM[i4][16];+ ~GENERATE+ for (~SYM[16]=0;~SYM[16]<2;~SYM[16]=~SYM[16]+1) begin : ~GENSYM[mux_stage4][17]+ localparam n = 5;+ logic [9:0] i;+ assign i = ~SYM[12][~SYM[16]*10:~SYM[16]*10+9];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:6] ~GENSYM[res][7];+ ~GENERATE+ if (1) begin+ localparam n = 6;+ logic [11:0] i;+ assign i = ~SYM[15][0:11];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE+ ~ELSE+ logic [0:31] ~SYM[1];+ assign ~SYM[1] = ~VAR[i][0][31:0];++ logic [0:31] ~SYM[2];+ genvar ~SYM[3];+ ~GENERATE+ for (~SYM[3]=0;~SYM[3]<16;~SYM[3]=~SYM[3]+1) begin : ~SYM[8]+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ end+ ~ENDGENERATE++ logic [0:23] ~SYM[4];+ genvar ~SYM[5];+ ~GENERATE+ for (~SYM[5]=0;~SYM[5]<8;~SYM[5]=~SYM[5]+1) begin : ~SYM[6]+ localparam n = 2;+ logic [3:0] i;+ assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:15] ~SYM[9];+ genvar ~SYM[10];+ ~GENERATE+ for (~SYM[10]=0;~SYM[10]<4;~SYM[10]=~SYM[10]+1) begin : ~SYM[11]+ localparam n = 3;+ logic [5:0] i;+ assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:9] ~SYM[12];+ genvar ~SYM[13];+ ~GENERATE+ for (~SYM[13]=0;~SYM[13]<2;~SYM[13]=~SYM[13]+1) begin : ~SYM[14]+ localparam n = 4;+ logic [7:0] i;+ assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:5] ~SYM[7];+ ~GENERATE+ if (1) begin+ localparam n = 5;+ logic [9:0] i;+ assign i = ~SYM[12][0:9];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE+ ~FI+ assign ~RESULT = $unsigned(~SYM[7]);+ // clz end+- BlackBox:+ name: GHC.Prim.ctz8#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: enc+ extension: inc+ template: |-+ function [1:0] ~INCLUDENAME[0];+ input [1:0] a;+ case (a)+ 2'b00: ~INCLUDENAME[0] = 2'b10;+ 2'b01: ~INCLUDENAME[0] = 2'b01;+ 2'b10: ~INCLUDENAME[0] = 2'b00;+ default: ~INCLUDENAME[0] = 2'b00;+ endcase+ endfunction+ kind: Declaration+ type: 'ctz8 :: Word# ->+ Word#'+ template: |-+ // ctz8 begin+ logic [0:7] ~GENSYM[v][1];+ genvar ~GENSYM[k][18];+ ~GENERATE+ for (~SYM[18]=0;~SYM[18]<8;~SYM[18]=~SYM[18]+1) begin : ~GENSYM[reverse][19]+ assign ~SYM[1][~SYM[18]] = ~ARG[0][~SYM[18]];+ end+ ~ENDGENERATE++ logic [0:7] ~GENSYM[e][2];+ genvar ~GENSYM[i][3];+ ~GENERATE+ for (~SYM[3]=0;~SYM[3]<4;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ end+ ~ENDGENERATE++ logic [0:5] ~GENSYM[a][4];+ genvar ~GENSYM[i1][5];+ ~GENERATE+ for (~SYM[5]=0;~SYM[5]<2;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]+ localparam n = 2;+ logic [3:0] i;+ assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:3] ~GENSYM[res][7];+ ~GENERATE+ if (1) begin+ localparam n = 3;+ logic [5:0] i;+ assign i = ~SYM[4][0:5];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ assign ~RESULT = $unsigned(~SYM[7]);+ // ctz8 end+- BlackBox:+ name: GHC.Prim.ctz16#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: enc+ extension: inc+ template: |-+ function [1:0] ~INCLUDENAME[0];+ input [1:0] a;+ case (a)+ 2'b00: ~INCLUDENAME[0] = 2'b10;+ 2'b01: ~INCLUDENAME[0] = 2'b01;+ 2'b10: ~INCLUDENAME[0] = 2'b00;+ default: ~INCLUDENAME[0] = 2'b00;+ endcase+ endfunction+ kind: Declaration+ type: 'ctz16 :: Word#+ -> Word#'+ template: |-+ // ctz16 begin+ logic [0:15] ~GENSYM[v][1];+ genvar ~GENSYM[k][18];+ ~GENERATE+ for (~SYM[18]=0;~SYM[18]<16;~SYM[18]=~SYM[18]+1) begin : ~GENSYM[reverse][19]+ assign ~SYM[1][~SYM[18]] = ~ARG[0][~SYM[18]];+ end+ ~ENDGENERATE++ logic [0:15] ~GENSYM[e][2];+ genvar ~GENSYM[i][3];+ ~GENERATE+ for (~SYM[3]=0;~SYM[3]<8;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ end+ ~ENDGENERATE++ logic [0:11] ~GENSYM[a][4];+ genvar ~GENSYM[i1][5];+ ~GENERATE+ for (~SYM[5]=0;~SYM[5]<4;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]+ localparam n = 2;+ logic [3:0] i;+ assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:7] ~GENSYM[b][9];+ genvar ~GENSYM[i2][10];+ ~GENERATE+ for (~SYM[10]=0;~SYM[10]<2;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]+ localparam n = 3;+ logic [5:0] i;+ assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:4] ~GENSYM[res][7];+ ~GENERATE+ if (1) begin+ localparam n = 4;+ logic [7:0] i;+ assign i = ~SYM[9][0:7];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ assign ~RESULT = $unsigned(~SYM[7]);+ // ctz16 end+- BlackBox:+ name: GHC.Prim.ctz32#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: enc+ extension: inc+ template: |-+ function [1:0] ~INCLUDENAME[0];+ input [1:0] a;+ case (a)+ 2'b00: ~INCLUDENAME[0] = 2'b10;+ 2'b01: ~INCLUDENAME[0] = 2'b01;+ 2'b10: ~INCLUDENAME[0] = 2'b00;+ default: ~INCLUDENAME[0] = 2'b00;+ endcase+ endfunction+ kind: Declaration+ type: 'ctz32 :: Word#+ -> Word#'+ template: |-+ // ctz32 begin+ logic [0:31] ~GENSYM[v][1];+ genvar ~GENSYM[k][18];+ ~GENERATE+ for (~SYM[18]=0;~SYM[18]<32;~SYM[18]=~SYM[18]+1) begin : ~GENSYM[reverse][19]+ assign ~SYM[1][~SYM[18]] = ~ARG[0][~SYM[18]];+ end+ ~ENDGENERATE++ logic [0:31] ~GENSYM[e][2];+ genvar ~GENSYM[i][3];+ ~GENERATE+ for (~SYM[3]=0;~SYM[3]<16;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ end+ ~ENDGENERATE++ logic [0:23] ~GENSYM[a][4];+ genvar ~GENSYM[i1][5];+ ~GENERATE+ for (~SYM[5]=0;~SYM[5]<8;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]+ localparam n = 2;+ logic [3:0] i;+ assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:15] ~GENSYM[b][9];+ genvar ~GENSYM[i2][10];+ ~GENERATE+ for (~SYM[10]=0;~SYM[10]<4;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]+ localparam n = 3;+ logic [5:0] i;+ assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:9] ~GENSYM[c][12];+ genvar ~GENSYM[i3][13];+ ~GENERATE+ for (~SYM[13]=0;~SYM[13]<2;~SYM[13]=~SYM[13]+1) begin : ~GENSYM[mux_stage3][14]+ localparam n = 4;+ logic [7:0] i;+ assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:5] ~GENSYM[res][7];+ ~GENERATE+ if (1) begin+ localparam n = 5;+ logic [9:0] i;+ assign i = ~SYM[12][0:9];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ assign ~RESULT = $unsigned(~SYM[7]);+ // ctz32 end+- BlackBox:+ name: GHC.Prim.ctz64#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: enc+ extension: inc+ template: |-+ function [1:0] ~INCLUDENAME[0];+ input [1:0] a;+ case (a)+ 2'b00: ~INCLUDENAME[0] = 2'b10;+ 2'b01: ~INCLUDENAME[0] = 2'b01;+ 2'b10: ~INCLUDENAME[0] = 2'b00;+ default: ~INCLUDENAME[0] = 2'b00;+ endcase+ endfunction+ kind: Declaration+ type: 'ctz64 :: Word#+ -> Word#'+ template: |-+ // ctz64 begin+ logic [0:63] ~GENSYM[v][1];+ genvar ~GENSYM[k][18];+ ~GENERATE+ for (~SYM[18]=0;~SYM[18]<64;~SYM[18]=~SYM[18]+1) begin : ~GENSYM[reverse][19]+ assign ~SYM[1][~SYM[18]] = ~ARG[0][~SYM[18]];+ end+ ~ENDGENERATE++ logic [0:63] ~GENSYM[e][2];+ genvar ~GENSYM[i][3];+ ~GENERATE+ for (~SYM[3]=0;~SYM[3]<32;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ end+ ~ENDGENERATE++ logic [0:47] a;+ genvar ~GENSYM[i1][5];+ ~GENERATE+ for (~SYM[5]=0;~SYM[5]<16;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]+ localparam n = 2;+ logic [3:0] i;+ assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:31] ~GENSYM[b][9];+ genvar ~GENSYM[i2][10];+ ~GENERATE+ for (~SYM[10]=0;~SYM[10]<8;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]+ localparam n = 3;+ logic [5:0] i;+ assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:19] ~GENSYM[c][12];+ genvar ~GENSYM[i3][13];+ ~GENERATE+ for (~SYM[13]=0;~SYM[13]<4;~SYM[13]=~SYM[13]+1) begin : ~GENSYM[mux_stage3][14]+ localparam n = 4;+ logic [7:0] i;+ assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:11] ~GENSYM[d][15];+ genvar ~GENSYM[i4][16];+ ~GENERATE+ for (~SYM[16]=0;~SYM[16]<2;~SYM[16]=~SYM[16]+1) begin : ~GENSYM[mux_stage4][17]+ localparam n = 5;+ logic [9:0] i;+ assign i = ~SYM[12][~SYM[16]*10:~SYM[16]*10+9];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:6] ~GENSYM[res][7];+ ~GENERATE+ if (1) begin+ localparam n = 6;+ logic [11:0] i;+ assign i = ~SYM[15][0:11];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ assign ~RESULT = $unsigned(~SYM[7]);+ // ctz64 end+- BlackBox:+ name: GHC.Prim.ctz#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: enc+ extension: inc+ template: |-+ function [1:0] ~INCLUDENAME[0];+ input [1:0] a;+ case (a)+ 2'b00: ~INCLUDENAME[0] = 2'b10;+ 2'b01: ~INCLUDENAME[0] = 2'b01;+ 2'b10: ~INCLUDENAME[0] = 2'b00;+ default: ~INCLUDENAME[0] = 2'b00;+ endcase+ endfunction+ kind: Declaration+ type: 'ctz :: Word# ->+ Word#'+ template: |-+ // ctz begin+ ~IF ~IW64 ~THEN+ logic [0:63] ~GENSYM[v][1];+ genvar ~GENSYM[k][18];+ ~GENERATE+ for (~SYM[18]=0;~SYM[18]<64;~SYM[18]=~SYM[18]+1) begin : ~GENSYM[reverse][19]+ assign ~SYM[1][~SYM[18]] = ~ARG[0][~SYM[18]];+ end+ ~ENDGENERATE++ logic [0:63] ~GENSYM[e][2];+ genvar ~GENSYM[i][3];+ ~GENERATE+ for (~SYM[3]=0;~SYM[3]<32;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ end+ ~ENDGENERATE++ logic [0:47] ~GENSYM[a][4];+ genvar ~GENSYM[i1][5];+ ~GENERATE+ for (~SYM[5]=0;~SYM[5]<16;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]+ localparam n = 2;+ logic [3:0] i;+ assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:31] ~GENSYM[b][9];+ genvar ~GENSYM[i2][10];+ ~GENERATE+ for (~SYM[10]=0;~SYM[10]<8;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]+ localparam n = 3;+ logic [5:0] i;+ assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:19] ~GENSYM[c][12];+ genvar ~GENSYM[i3][13];+ ~GENERATE+ for (~SYM[13]=0;~SYM[13]<4;~SYM[13]=~SYM[13]+1) begin : ~GENSYM[mux_stage3][14]+ localparam n = 4;+ logic [7:0] i;+ assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:11] ~GENSYM[d][15];+ genvar ~GENSYM[i4][16];+ ~GENERATE+ for (~SYM[16]=0;~SYM[16]<2;~SYM[16]=~SYM[16]+1) begin : ~GENSYM[mux_stage4][17]+ localparam n = 5;+ logic [9:0] i;+ assign i = ~SYM[12][~SYM[16]*10:~SYM[16]*10+9];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:6] ~GENSYM[res][7];+ ~GENERATE+ if (1) begin+ localparam n = 6;+ logic [11:0] i;+ assign i = ~SYM[15][0:11];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE+ ~ELSE+ logic [0:31] ~SYM[1];+ genvar ~SYM[18];+ ~GENERATE+ for (~SYM[18]=0;~SYM[18]<32;~SYM[18]=~SYM[18]+1) begin : ~SYM[19]+ assign ~SYM[1][~SYM[18]] = ~ARG[0][~SYM[18]];+ end+ ~ENDGENERATE++ logic [0:31] ~SYM[2];+ genvar ~SYM[3];+ ~GENERATE+ for (~SYM[3]=0;~SYM[3]<16;~SYM[3]=~SYM[3]+1) begin : ~SYM[8]+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ end+ ~ENDGENERATE++ logic [0:23] ~SYM[4];+ genvar ~SYM[5];+ ~GENERATE+ for (~SYM[5]=0;~SYM[5]<8;~SYM[5]=~SYM[5]+1) begin : ~SYM[6]+ localparam n = 2;+ logic [3:0] i;+ assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:15] ~SYM[9];+ genvar ~SYM[10];+ ~GENERATE+ for (~SYM[10]=0;~SYM[10]<4;~SYM[10]=~SYM[10]+1) begin : ~SYM[11]+ localparam n = 3;+ logic [5:0] i;+ assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:9] ~SYM[12];+ genvar ~SYM[13];+ ~GENERATE+ for (~SYM[13]=0;~SYM[13]<2;~SYM[13]=~SYM[13]+1) begin : ~SYM[14]+ localparam n = 4;+ logic [7:0] i;+ assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ logic [0:5] ~SYM[7];+ ~GENERATE+ if (1) begin+ localparam n = 5;+ logic [9:0] i;+ assign i = ~SYM[12][0:9];+ always_comb begin+ case (i[n-1+n])+ 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE+ ~FI+ assign ~RESULT = $unsigned(~SYM[7]);+ // ctz end
− prims/verilog/Clash_Explicit_BlockRam.primitives
@@ -1,151 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Explicit.BlockRam.blockRam#"- , "kind" : "Declaration"- , "type" :-"blockRam#- :: ( KnownDomain dom ARG[0]- , HasCallStack -- ARG[1]- , Undefined a ) -- ARG[2]- => Clock dom -- clk, ARG[3]- => Enable dom -- en, ARG[4]- -> Vec n a -- init, ARG[5]- -> Signal dom Int -- rd, ARG[6]- -> Signal dom Bool -- wren, ARG[7]- -> Signal dom Int -- wr, ARG[8]- -> Signal dom a -- din, ARG[9]- -> Signal dom a"- , "outputReg" : true- , "template" :-"// blockRam begin-reg ~TYPO ~GENSYM[~RESULT_RAM][1] [0:~LENGTH[~TYP[5]]-1];--reg ~TYP[5] ~GENSYM[ram_init][3];-integer ~GENSYM[i][4];-initial begin- ~SYM[3] = ~CONST[5];- for (~SYM[4]=0; ~SYM[4] < ~LENGTH[~TYP[5]]; ~SYM[4] = ~SYM[4] + 1) begin- ~SYM[1][~LENGTH[~TYP[5]]-1-~SYM[4]] = ~SYM[3][~SYM[4]*~SIZE[~TYPO]+:~SIZE[~TYPO]];- end-end-~IF ~ISACTIVEENABLE[4] ~THEN-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~GENSYM[~RESULT_blockRam][5]~IF ~VIVADO ~THEN- if (~ARG[4]) begin- if (~ARG[7]) begin- ~SYM[1][~ARG[8]] <= ~ARG[9];- end- ~RESULT <= ~SYM[1][~ARG[6]];- end~ELSE- if (~ARG[7] & ~ARG[4]) begin- ~SYM[1][~ARG[8]] <= ~ARG[9];- end- if (~ARG[4]) begin- ~RESULT <= ~SYM[1][~ARG[6]];- end~FI-end~ELSE-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~SYM[5]- if (~ARG[7]) begin- ~SYM[1][~ARG[8]] <= ~ARG[9];- end- ~RESULT <= ~SYM[1][~ARG[6]];-end~FI-// blockRam end"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.BlockRam.blockRamU#"- , "kind" : "Declaration"- , "type" :-"blockRamU#- :: ( KnownDomain dom ARG[0]- , HasCallStack -- ARG[1]- , Undefined a ) -- ARG[2]- => Clock dom -- clk, ARG[3]- -> Enable dom -- en, ARG[4]- -> SNat n -- len, ARG[5]- -> Signal dom Int -- rd, ARG[6]- -> Signal dom Bool -- wren, ARG[7]- -> Signal dom Int -- wr, ARG[8]- -> Signal dom a -- din, ARG[9]- -> Signal dom a"- , "outputReg" : true- , "template" :-"// blockRamU begin-reg ~TYPO ~GENSYM[~RESULT_RAM][0] [0:~LIT[5]-1];--~IF ~ISACTIVEENABLE[4] ~THEN-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~GENSYM[~RESULT_blockRam][5]~IF ~VIVADO ~THEN- if (~ARG[4]) begin- if (~ARG[7]) begin- ~SYM[0][~ARG[8]] <= ~ARG[9];- end- ~RESULT <= ~SYM[0][~ARG[6]];- end~ELSE- if (~ARG[7] & ~ARG[4]) begin- ~SYM[0][~ARG[8]] <= ~ARG[9];- end- if (~ARG[4]) begin- ~RESULT <= ~SYM[0][~ARG[6]];- end~FI-end~ELSE-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~SYM[5]- if (~ARG[7]) begin- ~SYM[0][~ARG[8]] <= ~ARG[9];- end- ~RESULT <= ~SYM[0][~ARG[6]];-end~FI-// blockRamU end"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.BlockRam.blockRam1#"- , "kind" : "Declaration"- , "type" :-"blockRam1#- :: ( KnownDomain dom ARG[0]- , HasCallStack -- ARG[1]- , Undefined a ) -- ARG[2]- => Clock dom -- clk, ARG[3]- -> Enable dom -- en, ARG[4]- -> SNat n -- len, ARG[5]- -> a -- init, ARG[6]- -> Signal dom Int -- rd, ARG[7]- -> Signal dom Bool -- wren, ARG[8]- -> Signal dom Int -- wr, ARG[9]- -> Signal dom a -- din, ARG[10]- -> Signal dom a"- , "outputReg" : true- , "template" :-"// blockRam1 begin-reg ~TYPO ~GENSYM[~RESULT_RAM][0] [0:~LIT[5]-1];-integer ~GENSYM[i][1];-initial begin- for (~SYM[1]=0;~SYM[1]<~LIT[5];~SYM[1]=~SYM[1]+1) begin- ~SYM[0][~SYM[1]] = ~CONST[6];- end-end--~IF ~ISACTIVEENABLE[4] ~THEN-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~GENSYM[~RESULT_blockRam][5]~IF ~VIVADO ~THEN- if (~ARG[4]) begin- if (~ARG[8]) begin- ~SYM[0][~ARG[9]] <= ~ARG[10];- end- ~RESULT <= ~SYM[0][~ARG[7]];- end~ELSE- if (~ARG[8] & ~ARG[4]) begin- ~SYM[0][~ARG[9]] <= ~ARG[10];- end- if (~ARG[4]) begin- ~RESULT <= ~SYM[0][~ARG[7]];- end~FI-end~ELSE-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~SYM[5]- if (~ARG[8]) begin- ~SYM[0][~ARG[9]] <= ~ARG[10];- end- ~RESULT <= ~SYM[0][~ARG[7]];-end~FI-// blockRam1 end"- }- }-]
+ prims/verilog/Clash_Explicit_BlockRam.primitives.yaml view
@@ -0,0 +1,202 @@+- BlackBox:+ name: Clash.Explicit.BlockRam.blockRam#+ kind: Declaration+ outputReg: true+ type: |-+ blockRam#+ :: ( KnownDomain dom ARG[0]+ , HasCallStack -- ARG[1]+ , Undefined a ) -- ARG[2]+ => Clock dom -- clk, ARG[3]+ => Enable dom -- en, ARG[4]+ -> Vec n a -- init, ARG[5]+ -> Signal dom Int -- rd, ARG[6]+ -> Signal dom Bool -- wren, ARG[7]+ -> Signal dom Int -- wr, ARG[8]+ -> Signal dom a -- din, ARG[9]+ -> Signal dom a+ template: |-+ // blockRam begin+ reg ~TYPO ~GENSYM[~RESULT_RAM][1] [0:~LENGTH[~TYP[5]]-1];++ reg ~TYP[5] ~GENSYM[ram_init][3];+ integer ~GENSYM[i][4];+ initial begin+ ~SYM[3] = ~CONST[5];+ for (~SYM[4]=0; ~SYM[4] < ~LENGTH[~TYP[5]]; ~SYM[4] = ~SYM[4] + 1) begin+ ~SYM[1][~LENGTH[~TYP[5]]-1-~SYM[4]] = ~SYM[3][~SYM[4]*~SIZE[~TYPO]+:~SIZE[~TYPO]];+ end+ end+ ~IF ~ISACTIVEENABLE[4] ~THEN+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~GENSYM[~RESULT_blockRam][5]~IF ~VIVADO ~THEN+ if (~ARG[4]) begin+ if (~ARG[7]) begin+ ~SYM[1][~ARG[8]] <= ~ARG[9];+ end+ ~RESULT <= ~SYM[1][~ARG[6]];+ end~ELSE+ if (~ARG[7] & ~ARG[4]) begin+ ~SYM[1][~ARG[8]] <= ~ARG[9];+ end+ if (~ARG[4]) begin+ ~RESULT <= ~SYM[1][~ARG[6]];+ end~FI+ end~ELSE+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~SYM[5]+ if (~ARG[7]) begin+ ~SYM[1][~ARG[8]] <= ~ARG[9];+ end+ ~RESULT <= ~SYM[1][~ARG[6]];+ end~FI+ // blockRam end+- BlackBox:+ name: Clash.Explicit.BlockRam.blockRamU#+ kind: Declaration+ outputReg: true+ type: |-+ blockRamU#+ :: ( KnownDomain dom ARG[0]+ , HasCallStack -- ARG[1]+ , Undefined a ) -- ARG[2]+ => Clock dom -- clk, ARG[3]+ -> Enable dom -- en, ARG[4]+ -> SNat n -- len, ARG[5]+ -> Signal dom Int -- rd, ARG[6]+ -> Signal dom Bool -- wren, ARG[7]+ -> Signal dom Int -- wr, ARG[8]+ -> Signal dom a -- din, ARG[9]+ -> Signal dom a+ template: |-+ // blockRamU begin+ reg ~TYPO ~GENSYM[~RESULT_RAM][0] [0:~LIT[5]-1];++ ~IF ~ISACTIVEENABLE[4] ~THEN+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~GENSYM[~RESULT_blockRam][5]~IF ~VIVADO ~THEN+ if (~ARG[4]) begin+ if (~ARG[7]) begin+ ~SYM[0][~ARG[8]] <= ~ARG[9];+ end+ ~RESULT <= ~SYM[0][~ARG[6]];+ end~ELSE+ if (~ARG[7] & ~ARG[4]) begin+ ~SYM[0][~ARG[8]] <= ~ARG[9];+ end+ if (~ARG[4]) begin+ ~RESULT <= ~SYM[0][~ARG[6]];+ end~FI+ end~ELSE+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~SYM[5]+ if (~ARG[7]) begin+ ~SYM[0][~ARG[8]] <= ~ARG[9];+ end+ ~RESULT <= ~SYM[0][~ARG[6]];+ end~FI+ // blockRamU end+- BlackBox:+ name: Clash.Explicit.BlockRam.blockRam1#+ kind: Declaration+ outputReg: true+ type: |-+ blockRam1#+ :: ( KnownDomain dom ARG[0]+ , HasCallStack -- ARG[1]+ , Undefined a ) -- ARG[2]+ => Clock dom -- clk, ARG[3]+ -> Enable dom -- en, ARG[4]+ -> SNat n -- len, ARG[5]+ -> a -- init, ARG[6]+ -> Signal dom Int -- rd, ARG[7]+ -> Signal dom Bool -- wren, ARG[8]+ -> Signal dom Int -- wr, ARG[9]+ -> Signal dom a -- din, ARG[10]+ -> Signal dom a+ template: |-+ // blockRam1 begin+ reg ~TYPO ~GENSYM[~RESULT_RAM][0] [0:~LIT[5]-1];+ integer ~GENSYM[i][1];+ initial begin+ for (~SYM[1]=0;~SYM[1]<~LIT[5];~SYM[1]=~SYM[1]+1) begin+ ~SYM[0][~SYM[1]] = ~CONST[6];+ end+ end++ ~IF ~ISACTIVEENABLE[4] ~THEN+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~GENSYM[~RESULT_blockRam][5]~IF ~VIVADO ~THEN+ if (~ARG[4]) begin+ if (~ARG[8]) begin+ ~SYM[0][~ARG[9]] <= ~ARG[10];+ end+ ~RESULT <= ~SYM[0][~ARG[7]];+ end~ELSE+ if (~ARG[8] & ~ARG[4]) begin+ ~SYM[0][~ARG[9]] <= ~ARG[10];+ end+ if (~ARG[4]) begin+ ~RESULT <= ~SYM[0][~ARG[7]];+ end~FI+ end~ELSE+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~SYM[5]+ if (~ARG[8]) begin+ ~SYM[0][~ARG[9]] <= ~ARG[10];+ end+ ~RESULT <= ~SYM[0][~ARG[7]];+ end~FI+ // blockRam1 end+- BlackBox:+ name: Clash.Explicit.BlockRam.trueDualPortBlockRam#+ kind: Declaration+ type: |-+ trueDualPortBlockRam# ::+ forall nAddrs domA domB a .+ ( HasCallStack ~ARG[0]+ , KnownNat nAddrs ~ARG[1]+ , KnownDomain domA ~ARG[2]+ , KnownDomain domB ~ARG[3]+ , NFDataX a ~ARG[4]+ ) =>++ Clock domA -> ~ARG[5]+ Signal domA Bool -> ~ARG[6]+ Signal domA Bool -> ~ARG[7]+ Signal domA (Index nAddrs) -> ~ARG[8]+ Signal domA a -> ~ARG[9]++ Clock domB -> ~ARG[10]+ Signal domB Bool -> ~ARG[11]+ Signal domB Bool -> ~ARG[12]+ Signal domB (Index nAddrs) -> ~ARG[13]+ Signal domB a -> ~ARG[14]+ (Signal domA a, Signal domB a)+ template: |-+ // trueDualPortBlockRam begin+ // Shared memory+ reg [~SIZE[~TYP[9]]-1:0] ~GENSYM[mem][0] [~LIT[1]-1:0];++ reg ~SIGD[~GENSYM[data_slow][1]][9];+ reg ~SIGD[~GENSYM[data_fast][2]][14];++ // Port A+ always @(~IF~ACTIVEEDGE[Rising][2]~THENposedge~ELSEnegedge~FI ~ARG[5]) begin+ if(~ARG[6]) begin+ ~SYM[1] <= ~SYM[0][~IF~SIZE[~TYP[8]]~THEN~ARG[8]~ELSE0~FI];+ if(~ARG[7]) begin+ ~SYM[1] <= ~ARG[9];+ ~SYM[0][~IF~SIZE[~TYP[8]]~THEN~ARG[8]~ELSE0~FI] <= ~ARG[9];+ end+ end+ end++ // Port B+ always @(~IF~ACTIVEEDGE[Rising][3]~THENposedge~ELSEnegedge~FI ~ARG[10]) begin+ if(~ARG[11]) begin+ ~SYM[2] <= ~SYM[0][~IF~SIZE[~TYP[13]]~THEN~ARG[13]~ELSE0~FI];+ if(~ARG[12]) begin+ ~SYM[2] <= ~ARG[14];+ ~SYM[0][~IF~SIZE[~TYP[13]]~THEN~ARG[13]~ELSE0~FI] <= ~ARG[14];+ end+ end+ end++ assign ~RESULT = {~SYM[1], ~SYM[2]};++ // end trueDualPortBlockRam
+ prims/verilog/Clash_Explicit_BlockRam_Blob.primitives.yaml view
@@ -0,0 +1,49 @@+- BlackBox:+ name: Clash.Explicit.BlockRam.Blob.blockRamBlob#+ kind: Declaration+ outputReg: true+ type: |-+ blockRamBlob#+ :: KnownDomain dom -- ARG[0]+ => Clock dom -- clk, ARG[1]+ -> Enable dom -- en, ARG[2]+ -> MemBlob n m -- init, ARG[3]+ -> Signal dom Int -- rd, ARG[4]+ -> Signal dom Bool -- wren, ARG[5]+ -> Signal dom Int -- wr, ARG[6]+ -> Signal dom (BitVector m) -- din, ARG[7]+ -> Signal dom (BitVector m)+ template: |-+ // blockRamBlob begin+ reg ~TYPO ~GENSYM[~RESULT_RAM][1] [0:~LENGTH[~TYP[3]]-1];++ reg ~TYP[3] ~GENSYM[ram_init][3];+ integer ~GENSYM[i][4];+ initial begin+ ~SYM[3] = ~CONST[3];+ for (~SYM[4]=0; ~SYM[4] < ~LENGTH[~TYP[3]]; ~SYM[4] = ~SYM[4] + 1) begin+ ~SYM[1][~LENGTH[~TYP[3]]-1-~SYM[4]] = ~SYM[3][~SYM[4]*~SIZE[~TYPO]+:~SIZE[~TYPO]];+ end+ end+ ~IF ~ISACTIVEENABLE[2] ~THEN+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[1]) begin : ~GENSYM[~RESULT_blockRam][5]~IF ~VIVADO ~THEN+ if (~ARG[2]) begin+ if (~ARG[5]) begin+ ~SYM[1][~ARG[6]] <= ~ARG[7];+ end+ ~RESULT <= ~SYM[1][~ARG[4]];+ end~ELSE+ if (~ARG[5] & ~ARG[2]) begin+ ~SYM[1][~ARG[6]] <= ~ARG[7];+ end+ if (~ARG[2]) begin+ ~RESULT <= ~SYM[1][~ARG[4]];+ end~FI+ end~ELSE+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[1]) begin : ~SYM[5]+ if (~ARG[5]) begin+ ~SYM[1][~ARG[6]] <= ~ARG[7];+ end+ ~RESULT <= ~SYM[1][~ARG[4]];+ end~FI+ // blockRamBlob end
− prims/verilog/Clash_Explicit_BlockRam_File.primitives
@@ -1,50 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Explicit.BlockRam.File.blockRamFile#"- , "kind" : "Declaration"- , "type" :-"blockRamFile#- :: ( KnownDomain dom -- ARG[0]- , KnownNat m -- ARG[1]- , HasCallStack ) -- ARG[2]- => Clock dom -- clk, ARG[3]- => Enable dom -- en, ARG[4]- -> SNat n -- sz, ARG[5]- -> FilePath -- file, ARG[6]- -> Signal dom Int -- rd, ARG[7]- -> Signal dom Bool -- wren, ARG[8]- -> Signal dom Int -- wr, ARG[9]- -> Signal dom (BitVector m) -- din, ARG[10]- -> Signal dom (BitVector m)"- , "outputReg" : true- , "template" :-"// blockRamFile begin-reg ~TYPO ~GENSYM[RAM][1] [0:~LIT[5]-1];--initial begin- $readmemb(~FILE[~LIT[6]],~SYM[1]);-end-~IF ~ISACTIVEENABLE[4] ~THEN-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~GENSYM[~COMPNAME_blockRamFile][3]~IF ~VIVADO ~THEN- if (~ARG[4]) begin- if (~ARG[8]) begin- ~SYM[1][~ARG[9]] <= ~ARG[10];- end- ~RESULT <= ~SYM[1][~ARG[7]];- end~ELSE- if (~ARG[8] & ~ARG[4]) begin- ~SYM[1][~ARG[9]] <= ~ARG[10];- end- if (~ARG[4]) begin- ~RESULT <= ~SYM[1][~ARG[7]];- end~FI-end~ELSE-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~SYM[3]- if (~ARG[8]) begin- ~SYM[1][~ARG[9]] <= ~ARG[10];- end- ~RESULT <= ~SYM[1][~ARG[7]];-end~FI-// blockRamFile end"- }- }-]
+ prims/verilog/Clash_Explicit_BlockRam_File.primitives.yaml view
@@ -0,0 +1,47 @@+- BlackBox:+ name: Clash.Explicit.BlockRam.File.blockRamFile#+ kind: Declaration+ outputReg: true+ type: |-+ blockRamFile#+ :: ( KnownDomain dom -- ARG[0]+ , KnownNat m -- ARG[1]+ , HasCallStack ) -- ARG[2]+ => Clock dom -- clk, ARG[3]+ => Enable dom -- en, ARG[4]+ -> SNat n -- sz, ARG[5]+ -> FilePath -- file, ARG[6]+ -> Signal dom Int -- rd, ARG[7]+ -> Signal dom Bool -- wren, ARG[8]+ -> Signal dom Int -- wr, ARG[9]+ -> Signal dom (BitVector m) -- din, ARG[10]+ -> Signal dom (BitVector m)+ template: |-+ // blockRamFile begin+ reg ~TYPO ~GENSYM[RAM][1] [0:~LIT[5]-1];++ initial begin+ $readmemb(~FILE[~LIT[6]],~SYM[1]);+ end+ ~IF ~ISACTIVEENABLE[4] ~THEN+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~GENSYM[~COMPNAME_blockRamFile][3]~IF ~VIVADO ~THEN+ if (~ARG[4]) begin+ if (~ARG[8]) begin+ ~SYM[1][~ARG[9]] <= ~ARG[10];+ end+ ~RESULT <= ~SYM[1][~ARG[7]];+ end~ELSE+ if (~ARG[8] & ~ARG[4]) begin+ ~SYM[1][~ARG[9]] <= ~ARG[10];+ end+ if (~ARG[4]) begin+ ~RESULT <= ~SYM[1][~ARG[7]];+ end~FI+ end~ELSE+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~SYM[3]+ if (~ARG[8]) begin+ ~SYM[1][~ARG[9]] <= ~ARG[10];+ end+ ~RESULT <= ~SYM[1][~ARG[7]];+ end~FI+ // blockRamFile end
− prims/verilog/Clash_Explicit_DDR.primitives
@@ -1,88 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Explicit.DDR.ddrIn#"- , "kind" : "Declaration"- , "type" :-"ddrIn# :: forall a slow fast n pFast gated synchronous.- ( HasCallStack -- ARG[0]- , Undefined a -- ARG[1]- , KnownConfi~ fast domf -- ARG[2]- , KnownConfi~ slow doms -- ARG[3]- => Clock slow -- ARG[4]- -> Reset slow -- ARG[5]- -> Enable slow -- ARG[6]- -> a -- ARG[7]- -> a -- ARG[8]- -> a -- ARG[9]- -> Signal fast a -- ARG[10]- -> Signal slow (a,a)"- , "template" :-"// ddrIn begin-reg ~SIGD[~GENSYM[data_Pos][1]][9];-reg ~SIGD[~GENSYM[data_Neg][2]][9];-reg ~SIGD[~GENSYM[data_Neg_Latch][3]][9];-always @(~IF~ACTIVEEDGE[Rising][2]~THENposedge~ELSEnegedge~FI ~ARG[4]~IF~ISSYNC[3]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[5])~FI begin : ~GENSYM[~COMPNAME_ddrIn_pos][6]- if (~IF~ISACTIVEHIGH[2]~THEN~ARG[5]~ELSE! ~ARG[5]~FI) begin- ~SYM[1] <= ~ARG[8];- end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin- ~SYM[1] <= ~ARG[10];- end-end-always @(~IF~ACTIVEEDGE[Rising][2]~THENnegedge~ELSEposedge~FI ~ARG[4]~IF~ISSYNC[3]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[5])~FI begin : ~GENSYM[~COMPNAME_ddrIn_neg][7]- if (~IF~ISACTIVEHIGH[2]~THEN~ARG[5]~ELSE! ~ARG[5]~FI) begin- ~SYM[2] <= ~ARG[9];- end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin- ~SYM[2] <= ~ARG[10];- end-end-always @(~IF~ACTIVEEDGE[Rising][2]~THENposedge~ELSEnegedge~FI ~ARG[4]~IF~ISSYNC[3]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[5])~FI begin : ~GENSYM[~COMPNAME_ddrIn_neg_latch][8]- if (~IF~ISACTIVEHIGH[2]~THEN~ARG[5]~ELSE! ~ARG[5]~FI) begin- ~SYM[3] <= ~ARG[7];- end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin- ~SYM[3] <= ~SYM[2];- end-end--assign ~RESULT = {~SYM[3], ~SYM[1]};-// ddrIn end"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.DDR.ddrOut#"- , "kind" : "Declaration"- , "type" :-"ddrOut# :: ( HasCallStack -- ARG[0]- , Undefined a -- ARG[1]- , KnownConfi~ fast domf -- ARG[2]- , KnownConfi~ slow doms -- ARG[3]- => Clock slow -- ARG[4]- -> Reset slow -- ARG[5]- -> Enable slow -- ARG[6]- -> a -- ARG[7]- -> Signal slow a -- ARG[8]- -> Signal slow a -- ARG[9]- -> Signal fast a"- , "template" :-"// ddrOut begin-reg ~SIGD[~GENSYM[data_Pos][1]][7];-reg ~SIGD[~GENSYM[data_Neg][2]][7];-always @(~IF~ACTIVEEDGE[Rising][2]~THENposedge~ELSEnegedge~FI ~ARG[4]~IF~ISSYNC[3]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[5])~FI begin : ~GENSYM[~COMPNAME_ddrOut_pos][5]- if (~IF~ISACTIVEHIGH[2]~THEN~ARG[5]~ELSE! ~ARG[5]~FI) begin- ~SYM[1] <= ~ARG[7];- end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin- ~SYM[1] <= ~ARG[8];- end-end-always @(~IF~ACTIVEEDGE[Rising][2]~THENposedge~ELSEnegedge~FI ~ARG[4]~IF~ISSYNC[3]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[5])~FI begin : ~GENSYM[~COMPNAME_ddrOut_neg][6]- if (~IF~ISACTIVEHIGH[2]~THEN~ARG[5]~ELSE! ~ARG[5]~FI) begin- ~SYM[2] <= ~ARG[7];- end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin- ~SYM[2] <= ~ARG[9];- end-end--assign ~RESULT = ~ARG[4] ? ~IF~ACTIVEEDGE[Rising][2]~THEN~SYM[1] : ~SYM[2]~ELSE~SYM[2] : ~SYM[1]~FI;--// ddrOut end"- }- }-]
+ prims/verilog/Clash_Explicit_DDR.primitives.yaml view
@@ -0,0 +1,83 @@+- BlackBox:+ name: Clash.Explicit.DDR.ddrIn#+ kind: Declaration+ type: |-+ ddrIn# :: forall a slow fast n pFast gated synchronous.+ ( HasCallStack -- ARG[0]+ , Undefined a -- ARG[1]+ , KnownConfi~ fast domf -- ARG[2]+ , KnownConfi~ slow doms -- ARG[3]+ => Clock slow -- ARG[4]+ -> Reset slow -- ARG[5]+ -> Enable slow -- ARG[6]+ -> a -- ARG[7]+ -> a -- ARG[8]+ -> a -- ARG[9]+ -> Signal fast a -- ARG[10]+ -> Signal slow (a,a)+ template: |-+ // ddrIn begin+ reg ~SIGD[~GENSYM[data_Pos][1]][9];+ reg ~SIGD[~GENSYM[data_Neg][2]][9];+ reg ~SIGD[~GENSYM[data_Neg_Latch][3]][9];+ always @(~IF~ACTIVEEDGE[Rising][2]~THENposedge~ELSEnegedge~FI ~ARG[4]~IF~ISSYNC[3]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[5])~FI begin : ~GENSYM[~COMPNAME_ddrIn_pos][6]+ if (~IF~ISACTIVEHIGH[2]~THEN~ARG[5]~ELSE! ~ARG[5]~FI) begin+ ~SYM[1] <= ~ARG[8];+ end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin+ ~SYM[1] <= ~ARG[10];+ end+ end+ always @(~IF~ACTIVEEDGE[Rising][2]~THENnegedge~ELSEposedge~FI ~ARG[4]~IF~ISSYNC[3]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[5])~FI begin : ~GENSYM[~COMPNAME_ddrIn_neg][7]+ if (~IF~ISACTIVEHIGH[2]~THEN~ARG[5]~ELSE! ~ARG[5]~FI) begin+ ~SYM[2] <= ~ARG[9];+ end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin+ ~SYM[2] <= ~ARG[10];+ end+ end+ always @(~IF~ACTIVEEDGE[Rising][2]~THENposedge~ELSEnegedge~FI ~ARG[4]~IF~ISSYNC[3]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[5])~FI begin : ~GENSYM[~COMPNAME_ddrIn_neg_latch][8]+ if (~IF~ISACTIVEHIGH[2]~THEN~ARG[5]~ELSE! ~ARG[5]~FI) begin+ ~SYM[3] <= ~ARG[7];+ end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin+ ~SYM[3] <= ~SYM[2];+ end+ end++ assign ~RESULT = {~SYM[3], ~SYM[1]};+ // ddrIn end+- BlackBox:+ name: Clash.Explicit.DDR.ddrOut#+ kind: Declaration+ type: |-+ ddrOut# :: ( HasCallStack -- ARG[0]+ , Undefined a -- ARG[1]+ , KnownConfi~ fast domf -- ARG[2]+ , KnownConfi~ slow doms -- ARG[3]+ => Clock slow -- ARG[4]+ -> Reset slow -- ARG[5]+ -> Enable slow -- ARG[6]+ -> a -- ARG[7]+ -> Signal slow a -- ARG[8]+ -> Signal slow a -- ARG[9]+ -> Signal fast a+ template: |-+ // ddrOut begin+ reg ~SIGD[~GENSYM[data_Pos][1]][7];+ reg ~SIGD[~GENSYM[data_Neg][2]][7];+ always @(~IF~ACTIVEEDGE[Rising][2]~THENposedge~ELSEnegedge~FI ~ARG[4]~IF~ISSYNC[3]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[5])~FI begin : ~GENSYM[~COMPNAME_ddrOut_pos][5]+ if (~IF~ISACTIVEHIGH[2]~THEN~ARG[5]~ELSE! ~ARG[5]~FI) begin+ ~SYM[1] <= ~ARG[7];+ end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin+ ~SYM[1] <= ~ARG[8];+ end+ end+ always @(~IF~ACTIVEEDGE[Rising][2]~THENposedge~ELSEnegedge~FI ~ARG[4]~IF~ISSYNC[3]~THEN)~ELSE or ~IF~ISACTIVEHIGH[2]~THENposedge~ELSEnegedge~FI ~ARG[5])~FI begin : ~GENSYM[~COMPNAME_ddrOut_neg][6]+ if (~IF~ISACTIVEHIGH[2]~THEN~ARG[5]~ELSE! ~ARG[5]~FI) begin+ ~SYM[2] <= ~ARG[7];+ end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin+ ~SYM[2] <= ~ARG[9];+ end+ end++ assign ~RESULT = ~ARG[4] ? ~IF~ACTIVEEDGE[Rising][2]~THEN~SYM[1] : ~SYM[2]~ELSE~SYM[2] : ~SYM[1]~FI;++ // ddrOut end
− prims/verilog/Clash_Explicit_RAM.primitives
@@ -1,31 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Explicit.RAM.asyncRam#"- , "kind" : "Declaration"- , "type" :-"asyncRam#- :: ( HasCallStack -- ARG[0]- , KnownDomain wdom wconf -- ARG[1]- , KnownDomain rdom rconf ) -- ARG[2]- => Clock wdom -- ^ wclk, ARG[3]- -> Clock rdom -- ^ rclk, ARG[4]- -> Enable wdom -- ^ wen, ARG[5]- -> SNat n -- ^ sz, ARG[6]- -> Signal rdom Int -- ^ rd, ARG[7]- -> Signal wdom Bool -- ^ en, ARG[8]- -> Signal wdom Int -- ^ wr, ARG[9]- -> Signal wdom a -- ^ din, ARG[10]- -> Signal rdom a"- , "template" :-"// asyncRam begin-reg ~TYPO ~GENSYM[RAM][0] [0:~LIT[6]-1];-always @(~IF~ACTIVEEDGE[Rising][1]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~GENSYM[~COMPNAME_Ram][1]- if (~ARG[8] ~IF ~ISACTIVEENABLE[5] ~THEN & ~ARG[5] ~ELSE ~FI) begin- ~SYM[0][~ARG[9]] <= ~ARG[10];- end-end--assign ~RESULT = ~SYM[0][~ARG[7]];-// asyncRam end"- }- }-]
+ prims/verilog/Clash_Explicit_RAM.primitives.yaml view
@@ -0,0 +1,29 @@+- BlackBox:+ name: Clash.Explicit.RAM.asyncRam#+ kind: Declaration+ type: |-+ asyncRam#+ :: ( HasCallStack -- ARG[0]+ , KnownDomain wdom -- ARG[1]+ , KnownDomain rdom -- ARG[2]+ , NFDataX a ) -- ARG[3]+ => Clock wdom -- ^ wclk, ARG[4]+ -> Clock rdom -- ^ rclk, ARG[5]+ -> Enable wdom -- ^ wen, ARG[6]+ -> SNat n -- ^ sz, ARG[7]+ -> Signal rdom Int -- ^ rd, ARG[8]+ -> Signal wdom Bool -- ^ en, ARG[9]+ -> Signal wdom Int -- ^ wr, ARG[10]+ -> Signal wdom a -- ^ din, ARG[11]+ -> Signal rdom a+ template: |-+ // asyncRam begin+ reg ~TYPO ~GENSYM[RAM][0] [0:~LIT[7]-1];+ always @(~IF~ACTIVEEDGE[Rising][1]~THENposedge~ELSEnegedge~FI ~ARG[4]) begin : ~GENSYM[~COMPNAME_Ram][1]+ if (~ARG[9] ~IF ~ISACTIVEENABLE[6] ~THEN & ~ARG[6] ~ELSE ~FI) begin+ ~SYM[0][~ARG[10]] <= ~ARG[11];+ end+ end++ assign ~RESULT = ~SYM[0][~ARG[8]];+ // asyncRam end
− prims/verilog/Clash_Explicit_ROM.primitives
@@ -1,38 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Explicit.ROM.rom#"- , "kind" : "Declaration"- , "type" :-"rom# :: ( KnownDomain dom ARG[0]- , KnownNat n -- ARG[1]- , Undefined a ) -- ARG[2]- => Clock dom -- clk, ARG[3]- -> Enable dom -- en, ARG[4]- -> Vec n a -- init, ARG[5]- -> Signal dom Int -- rd, ARG[6]- -> Signal dom a"- , "outputReg" : true- , "template" :-"// rom begin-reg ~TYPO ~GENSYM[ROM][1] [0:~LIT[1]-1];--reg ~TYP[5] ~GENSYM[rom_init][3];-integer ~GENSYM[i][4];-initial begin- ~SYM[3] = ~LIT[5];- for (~SYM[4]=0; ~SYM[4] < ~LIT[1]; ~SYM[4] = ~SYM[4] + 1) begin- ~SYM[1][~LIT[1]-1-~SYM[4]] = ~SYM[3][~SYM[4]*~SIZE[~TYPO]+:~SIZE[~TYPO]];- end-end-~IF ~ISACTIVEENABLE[4] ~THEN-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~GENSYM[~COMPNAME_rom][5]- if (~ARG[4]) begin- ~RESULT <= ~SYM[1][~ARG[6]];- end-end~ELSE-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~SYM[5]- ~RESULT <= ~SYM[1][~ARG[6]];-end~FI-// rom end"- }- }-]
+ prims/verilog/Clash_Explicit_ROM.primitives.yaml view
@@ -0,0 +1,35 @@+- BlackBox:+ name: Clash.Explicit.ROM.rom#+ kind: Declaration+ outputReg: true+ type: |-+ rom# :: ( KnownDomain dom ARG[0]+ , KnownNat n -- ARG[1]+ , Undefined a ) -- ARG[2]+ => Clock dom -- clk, ARG[3]+ -> Enable dom -- en, ARG[4]+ -> Vec n a -- init, ARG[5]+ -> Signal dom Int -- rd, ARG[6]+ -> Signal dom a+ template: |-+ // rom begin+ reg ~TYPO ~GENSYM[ROM][1] [0:~LIT[1]-1];++ reg ~TYP[5] ~GENSYM[rom_init][3];+ integer ~GENSYM[i][4];+ initial begin+ ~SYM[3] = ~LIT[5];+ for (~SYM[4]=0; ~SYM[4] < ~LIT[1]; ~SYM[4] = ~SYM[4] + 1) begin+ ~SYM[1][~LIT[1]-1-~SYM[4]] = ~SYM[3][~SYM[4]*~SIZE[~TYPO]+:~SIZE[~TYPO]];+ end+ end+ ~IF ~ISACTIVEENABLE[4] ~THEN+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~GENSYM[~COMPNAME_rom][5]+ if (~ARG[4]) begin+ ~RESULT <= ~SYM[1][~ARG[6]];+ end+ end~ELSE+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin : ~SYM[5]+ ~RESULT <= ~SYM[1][~ARG[6]];+ end~FI+ // rom end
+ prims/verilog/Clash_Explicit_ROM_Blob.primitives.yaml view
@@ -0,0 +1,34 @@+- BlackBox:+ name: Clash.Explicit.ROM.Blob.romBlob#+ kind: Declaration+ outputReg: true+ type: |-+ romBlob#+ :: KnownDomain dom -- ARG[0]+ => Clock dom -- clk, ARG[1]+ -> Enable dom -- en, ARG[2]+ -> MemBlob n m -- init, ARG[3]+ -> Signal dom Int -- rd, ARG[4]+ -> Signal dom (BitVector m)+ template: |-+ // romBlob begin+ reg ~TYPO ~GENSYM[ROM][1] [0:~LENGTH[~TYP[3]]-1];++ reg ~TYP[3] ~GENSYM[rom_init][3];+ integer ~GENSYM[i][4];+ initial begin+ ~SYM[3] = ~CONST[3];+ for (~SYM[4]=0; ~SYM[4] < ~LENGTH[~TYP[3]]; ~SYM[4] = ~SYM[4] + 1) begin+ ~SYM[1][~LENGTH[~TYP[3]]-1-~SYM[4]] = ~SYM[3][~SYM[4]*~SIZE[~TYPO]+:~SIZE[~TYPO]];+ end+ end+ ~IF ~ISACTIVEENABLE[2] ~THEN+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[1]) begin : ~GENSYM[~COMPNAME_rom][5]+ if (~ARG[2]) begin+ ~RESULT <= ~SYM[1][~ARG[4]];+ end+ end~ELSE+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[1]) begin : ~SYM[5]+ ~RESULT <= ~SYM[1][~ARG[4]];+ end~FI+ // romBlob end
− prims/verilog/Clash_Explicit_ROM_File.primitives
@@ -1,33 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Explicit.ROM.File.romFile#"- , "kind" : "Declaration"- , "type" :-"romFile# :: ( KnownNat m -- ARG[0]- , KnownDomain dom ) -- ARG[1]- => Clock dom -- clk, ARG[2]- -> Enable dom -- en, ARG[3]- -> SNat n -- sz, ARG[4]- -> FilePath -- file, ARG[5]- -> Signal dom Int -- rd, ARG[6]- -> Signal dom (BitVector m)"- , "outputReg" : true- , "template" :-"// romFile begin-reg ~TYPO ~GENSYM[ROM][0] [0:~LIT[4]-1];--initial begin- $readmemb(~FILE[~LIT[5]],~SYM[0]);-end-~IF ~ISACTIVEENABLE[3] ~THEN-always @(~IF~ACTIVEEDGE[Rising][1]~THENposedge~ELSEnegedge~FI ~ARG[2]) begin : ~GENSYM[~COMPNAME_romFile][2]- if (~ARG[3]) begin- ~RESULT <= ~SYM[0][~ARG[6]];- end-end~ELSE-always @(~IF~ACTIVEEDGE[Rising][1]~THENposedge~ELSEnegedge~FI ~ARG[2]) begin : ~SYM[2]- ~RESULT <= ~SYM[0][~ARG[6]];-end~FI-// romFile end"- }- }-]
+ prims/verilog/Clash_Explicit_ROM_File.primitives.yaml view
@@ -0,0 +1,30 @@+- BlackBox:+ name: Clash.Explicit.ROM.File.romFile#+ kind: Declaration+ outputReg: true+ type: |-+ romFile# :: ( KnownNat m -- ARG[0]+ , KnownDomain dom ) -- ARG[1]+ => Clock dom -- clk, ARG[2]+ -> Enable dom -- en, ARG[3]+ -> SNat n -- sz, ARG[4]+ -> FilePath -- file, ARG[5]+ -> Signal dom Int -- rd, ARG[6]+ -> Signal dom (BitVector m)+ template: |-+ // romFile begin+ reg ~TYPO ~GENSYM[ROM][0] [0:~LIT[4]-1];++ initial begin+ $readmemb(~FILE[~LIT[5]],~SYM[0]);+ end+ ~IF ~ISACTIVEENABLE[3] ~THEN+ always @(~IF~ACTIVEEDGE[Rising][1]~THENposedge~ELSEnegedge~FI ~ARG[2]) begin : ~GENSYM[~COMPNAME_romFile][2]+ if (~ARG[3]) begin+ ~RESULT <= ~SYM[0][~ARG[6]];+ end+ end~ELSE+ always @(~IF~ACTIVEEDGE[Rising][1]~THENposedge~ELSEnegedge~FI ~ARG[2]) begin : ~SYM[2]+ ~RESULT <= ~SYM[0][~ARG[6]];+ end~FI+ // romFile end
− prims/verilog/Clash_Explicit_Testbench.primitives
@@ -1,94 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Explicit.Testbench.assert"- , "kind" : "Declaration"- , "type" :-"assert- :: (KnownDomain dom, Eq a, ShowX a) -- (ARG[0], ARG[1], ARG[2])- => Clock dom -- ARG[3]- -> Reset dom -- ARG[4]- -> String -- ARG[5]- -> Signal dom a -- Checked value (ARG[6])- -> Signal dom a -- Expected value (ARG[7])- -> Signal dom b -- Return valued (ARG[8])- -> Signal dom b"- , "template" :-"// assert begin-// pragma translate_off-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin- if (~ARG[6] !== ~ARG[7]) begin- $display(\"@%0tns: %s, expected: %b, actual: %b\", $time, ~LIT[5], ~ARG[7], ~ARG[6]);- $finish;- end-end-// pragma translate_on-assign ~RESULT = ~ARG[8];-// assert end"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.Testbench.assertBitVector"- , "kind" : "Declaration"- , "type" :-"assertBitVector- :: ( KnownDomain dom -- ARG[0]- , KnownNat n -- ARG[1]- => Clock dom -- ARG[2]- -> Reset dom -- ARG[3]- -> String -- ARG[4]- -> Signal dom (BitVector n) -- Checked value (ARG[5])- -> Signal dom (BitVector n) -- Expected value (ARG[6])- -> Signal dom b -- Return valued (ARG[7])- -> Signal dom b"- , "template" :-"// assertBitVector begin-// pragma translate_off-wire ~TYP[5] ~GENSYM[maskXor][0] = ~ARG[6] ^ ~ARG[6];-wire ~TYP[5] ~GENSYM[checked][1] = ~ARG[5] ^ ~SYM[0];-wire ~TYP[5] ~GENSYM[expected][2] = ~ARG[6] ^ ~SYM[0];--always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[2]) begin- if (~SYM[1] !== ~SYM[2]) begin- $display(\"@%0tns: %s, expected: %b, actual: %b\", $time, ~LIT[4], ~ARG[6], ~ARG[5]);- $finish;- end-end-// pragma translate_on-assign ~RESULT = ~ARG[7];-// assertBitVector end"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.Testbench.tbClockGen"- , "workInfo" : "Always"- , "kind" : "Declaration"- , "warning" : "Clash.Signal.Internal.tbClockGen is not synthesizable!"- , "type" :-"tbClockGen- :: KnownDomain dom -- ARG[0]- => Signal dom Bool -- ARG[1]- -> Clock dom"- , "template" :-"// tbClockGen begin-// pragma translate_off-reg ~TYPO ~GENSYM[clk][0];-// 1 = 0.1ps-localparam ~GENSYM[half_period][1] = (~PERIOD[0]0 / 2);-always begin- // Delay of 1 mitigates race conditions (https://github.com/steveicarus/iverilog/issues/160)- #1 ~SYM[0] = ~IF~ACTIVEEDGE[Rising][0]~THEN 0 ~ELSE 1 ~FI;- #30000 forever begin- if (~ ~ARG[1]) begin- $finish;- end- ~SYM[0] = ~ ~SYM[0];- #~SYM[1];- ~SYM[0] = ~ ~SYM[0];- #~SYM[1];- end-end-assign ~RESULT = ~SYM[0];-// pragma translate_on-// tbClockGen end"- }- }-]
+ prims/verilog/Clash_Explicit_Testbench.primitives.yaml view
@@ -0,0 +1,122 @@+- BlackBox:+ name: Clash.Explicit.Testbench.assert+ kind: Declaration+ type: |-+ assert+ :: (KnownDomain dom, Eq a, ShowX a) -- (ARG[0], ARG[1], ARG[2])+ => Clock dom -- ARG[3]+ -> Reset dom -- ARG[4]+ -> String -- ARG[5]+ -> Signal dom a -- Checked value (ARG[6])+ -> Signal dom a -- Expected value (ARG[7])+ -> Signal dom b -- Return valued (ARG[8])+ -> Signal dom b+ template: |-+ // assert begin+ // pragma translate_off+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[3]) begin+ if (~ARG[6] !== ~ARG[7]) begin+ $display("@%0tns: %s, expected: %b, actual: %b", $time, ~LIT[5], ~ARG[7], ~ARG[6]);+ $finish;+ end+ end+ // pragma translate_on+ assign ~RESULT = ~ARG[8];+ // assert end+- BlackBox:+ name: Clash.Explicit.Testbench.assertBitVector+ kind: Declaration+ type: |-+ assertBitVector+ :: ( KnownDomain dom -- ARG[0]+ , KnownNat n -- ARG[1]+ => Clock dom -- ARG[2]+ -> Reset dom -- ARG[3]+ -> String -- ARG[4]+ -> Signal dom (BitVector n) -- Checked value (ARG[5])+ -> Signal dom (BitVector n) -- Expected value (ARG[6])+ -> Signal dom b -- Return valued (ARG[7])+ -> Signal dom b+ template: |-+ // assertBitVector begin+ // pragma translate_off+ wire ~TYP[5] ~GENSYM[maskXor][0] = ~ARG[6] ^ ~ARG[6];+ wire ~TYP[5] ~GENSYM[checked][1] = ~ARG[5] ^ ~SYM[0];+ wire ~TYP[5] ~GENSYM[expected][2] = ~ARG[6] ^ ~SYM[0];++ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[2]) begin+ if (~SYM[1] !== ~SYM[2]) begin+ $display("@%0tns: %s, expected: %b, actual: %b", $time, ~LIT[4], ~ARG[6], ~ARG[5]);+ $finish;+ end+ end+ // pragma translate_on+ assign ~RESULT = ~ARG[7];+ // assertBitVector end+- BlackBox:+ name: Clash.Explicit.Testbench.tbClockGen+ kind: Declaration+ type: |-+ tbClockGen+ :: KnownDomain dom -- ARG[0]+ => Signal dom Bool -- ARG[1]+ -> Clock dom+ template: |-+ // tbClockGen begin+ // pragma translate_off+ reg ~TYPO ~GENSYM[clk][0];+ // 1 = 0.1ps+ localparam ~GENSYM[half_period][1] = (~PERIOD[0]0 / 2);+ always begin+ // Delay of 1 mitigates race conditions (https://github.com/steveicarus/iverilog/issues/160)+ #1 ~SYM[0] = ~IF~ACTIVEEDGE[Rising][0]~THEN 0 ~ELSE 1 ~FI;+ `ifndef VERILATOR+ #~LONGESTPERIOD0 forever begin+ if (~ ~ARG[1]) begin+ $finish;+ end+ ~SYM[0] = ~ ~SYM[0];+ #~SYM[1];+ ~SYM[0] = ~ ~SYM[0];+ #~SYM[1];+ end+ `else+ ~SYM[0] = $c("this->~GENSYM[tb_clock_gen][2](",~SYM[1],",~IF~ACTIVEEDGE[Rising][0]~THENtrue~ELSEfalse~FI,",(~ ~ARG[1]),")");+ `endif+ end++ `ifdef VERILATOR+ `systemc_interface+ CData ~SYM[2](vluint32_t half_period, bool active_rising, bool result_rec) {+ static vluint32_t init_wait = ~LONGESTPERIOD0;+ static vluint32_t to_wait = 0;+ static CData clock = active_rising ? 0 : 1;++ if(init_wait == 0) {+ if(result_rec) {+ std::exit(0);+ }+ else {+ if(to_wait == 0) {+ to_wait = half_period - 1;+ clock = clock == 0 ? 1 : 0;+ }+ else {+ to_wait = to_wait - 1;+ }+ }+ }+ else {+ init_wait = init_wait - 1;+ }++ return clock;+ }+ `verilog+ `endif++ assign ~RESULT = ~SYM[0];+ // pragma translate_on+ // tbClockGen end+ warning: Clash.Signal.Internal.tbClockGen is not synthesizable!+ workInfo: Always
− prims/verilog/Clash_Intel_DDR.primitives
@@ -1,48 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Intel.DDR.altddioIn"- , "kind" : "Declaration"- , "type" :-"altddioIn- :: ( HasCallStack -- ARG[0]- , KnownConfi~ fast domf -- ARG[1]- , KnownConfi~ slow doms -- ARG[2]- , KnownNat m ) -- ARG[3]- => SSymbol deviceFamily -- ARG[4]- -> Clock slow -- ARG[5]- -> Reset slow -- ARG[6]- -> Enable slow -- ARG[7]- -> Signal fast (BitVector m) -- ARG[8]- -> Signal slow (BitVector m,BitVector m)"- , "libraries" : ["altera_mf"]- , "template" :-"// altddioIn begin-wire ~SIGD[~GENSYM[dataout_l][1]][8];-wire ~SIGD[~GENSYM[dataout_h][2]][8];--altddio_in- #(- .intended_device_family (~LIT[4]),- .invert_input_clocks (\"OFF\"),- .lpm_hint (\"UNUSED\"),- .lpm_type (\"altddio_in\"),- .power_up_high (\"OFF\"),- .width (~SIZE[~TYP[7]])- )- ~GENSYM[~COMPNAME_ALTDDIO_IN][7] (~IF ~ISSYNC[2] ~THEN- .sclr (~ARG[6]),- .aclr (1'b0),~ELSE- .aclr (~ARG[6]),- .sclr (1'b0),~FI- .datain (~ARG[8]),~- .inclock (~ARG[5]),- .inclocken (~IF ~ISACTIVEENABLE[7] ~THEN ~ARG[7] ~ELSE 1'b1 ~FI),- .dataout_h (~SYM[2]),- .dataout_l (~SYM[1]),- .aset (1'b0),- .sset (1'b0)- );-assign ~RESULT = {~SYM[1],~SYM[2]};-// altddioIn end"- }- }-]
+ prims/verilog/Clash_Intel_DDR.primitives.yaml view
@@ -0,0 +1,46 @@+- BlackBox:+ name: Clash.Intel.DDR.altddioIn+ kind: Declaration+ libraries:+ - altera_mf+ type: |-+ altddioIn+ :: ( HasCallStack -- ARG[0]+ , KnownConfi~ fast domf -- ARG[1]+ , KnownConfi~ slow doms -- ARG[2]+ , KnownNat m ) -- ARG[3]+ => SSymbol deviceFamily -- ARG[4]+ -> Clock slow -- ARG[5]+ -> Reset slow -- ARG[6]+ -> Enable slow -- ARG[7]+ -> Signal fast (BitVector m) -- ARG[8]+ -> Signal slow (BitVector m,BitVector m)+ template: |-+ // altddioIn begin+ wire ~SIGD[~GENSYM[dataout_l][1]][8];+ wire ~SIGD[~GENSYM[dataout_h][2]][8];++ altddio_in+ #(+ .intended_device_family (~LIT[4]),+ .invert_input_clocks ("OFF"),+ .lpm_hint ("UNUSED"),+ .lpm_type ("altddio_in"),+ .power_up_high ("OFF"),+ .width (~SIZE[~TYP[7]])+ )+ ~GENSYM[~COMPNAME_ALTDDIO_IN][7] (~IF ~ISSYNC[2] ~THEN+ .sclr (~ARG[6]),+ .aclr (1'b0),~ELSE+ .aclr (~ARG[6]),+ .sclr (1'b0),~FI+ .datain (~ARG[8]),~+ .inclock (~ARG[5]),+ .inclocken (~IF ~ISACTIVEENABLE[7] ~THEN ~ARG[7] ~ELSE 1'b1 ~FI),+ .dataout_h (~SYM[2]),+ .dataout_l (~SYM[1]),+ .aset (1'b0),+ .sset (1'b0)+ );+ assign ~RESULT = {~SYM[1],~SYM[2]};+ // altddioIn end
− prims/verilog/Clash_Prelude_ROM.primitives
@@ -1,26 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Prelude.ROM.asyncRom#"- , "kind" : "Declaration"- , "type" :-"asyncRom# :: KnownNat n -- ^ ARG[0]- => Vec n a -- ^ ARG[1]- -> Int -- ^ ARG[2]- -> a"- , "template" :-"// asyncRom begin-wire ~TYPO ~GENSYM[ROM][0] [0:~LIT[0]-1];--wire ~TYP[1] ~GENSYM[romflat][1];-assign ~SYM[1] = ~LIT[1];-genvar ~GENSYM[i][2];-~GENERATE-for (~SYM[2]=0; ~SYM[2] < ~LIT[0]; ~SYM[2]=~SYM[2]+1) begin : ~GENSYM[mk_array][3]- assign ~SYM[0][(~LIT[0]-1)-~SYM[2]] = ~SYM[1][~SYM[2]*~SIZE[~TYPO]+:~SIZE[~TYPO]];-end-~ENDGENERATE--assign ~RESULT = ~SYM[0][~ARG[2]];-// asyncRom end"- }- }-]
+ prims/verilog/Clash_Prelude_ROM.primitives.yaml view
@@ -0,0 +1,23 @@+- BlackBox:+ name: Clash.Prelude.ROM.asyncRom#+ kind: Declaration+ type: |-+ asyncRom# :: KnownNat n -- ^ ARG[0]+ => Vec n a -- ^ ARG[1]+ -> Int -- ^ ARG[2]+ -> a+ template: |-+ // asyncRom begin+ wire ~TYPO ~GENSYM[ROM][0] [0:~LIT[0]-1];++ wire ~TYP[1] ~GENSYM[romflat][1];+ assign ~SYM[1] = ~CONST[1];+ genvar ~GENSYM[i][2];+ ~GENERATE+ for (~SYM[2]=0; ~SYM[2] < ~LIT[0]; ~SYM[2]=~SYM[2]+1) begin : ~GENSYM[mk_array][3]+ assign ~SYM[0][(~LIT[0]-1)-~SYM[2]] = ~SYM[1][~SYM[2]*~SIZE[~TYPO]+:~SIZE[~TYPO]];+ end+ ~ENDGENERATE++ assign ~RESULT = ~SYM[0][~ARG[2]];+ // asyncRom end
+ prims/verilog/Clash_Prelude_ROM_Blob.primitives.yaml view
@@ -0,0 +1,23 @@+- BlackBox:+ name: Clash.Prelude.ROM.Blob.asyncRomBlob#+ kind: Declaration+ type: |-+ asyncRomBlob#+ :: MemBlob n m -- ARG[0]+ -> Int -- ARG[1]+ -> BitVector m+ template: |-+ // asyncRomBlob begin+ wire ~TYPO ~GENSYM[ROM][0] [0:~LENGTH[~TYP[0]]-1];++ wire ~TYP[0] ~GENSYM[romflat][1];+ assign ~SYM[1] = ~CONST[0];+ genvar ~GENSYM[i][2];+ ~GENERATE+ for (~SYM[2]=0; ~SYM[2] < ~LENGTH[~TYP[0]]; ~SYM[2]=~SYM[2]+1) begin : ~GENSYM[mk_array][3]+ assign ~SYM[0][(~LENGTH[~TYP[0]]-1)-~SYM[2]] = ~SYM[1][~SYM[2]*~SIZE[~TYPO]+:~SIZE[~TYPO]];+ end+ ~ENDGENERATE++ assign ~RESULT = ~SYM[0][~ARG[1]];+ // asyncRomBlob end
− prims/verilog/Clash_Prelude_ROM_File.primitives
@@ -1,22 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Prelude.ROM.File.asyncRomFile#"- , "kind" : "Declaration"- , "type" :-"asyncRomFile :: KnownNat m -- ARG[0]- => SNat n -- sz, ARG[1]- -> FilePath -- file, ARG[2]- -> Int -- rd, ARG[3]- -> BitVector m"- , "template" :-"// asyncRomFile begin-reg ~TYPO ~GENSYM[ROM][0] [0:~LIT[1]-1];--initial begin- $readmemb(~FILE[~LIT[2]],~SYM[0]);-end--assign ~RESULT = ~SYM[0][~ARG[3]];-// asyncRomFile end"- }- }-]
+ prims/verilog/Clash_Prelude_ROM_File.primitives.yaml view
@@ -0,0 +1,19 @@+- BlackBox:+ name: Clash.Prelude.ROM.File.asyncRomFile#+ kind: Declaration+ type: |-+ asyncRomFile :: KnownNat m -- ARG[0]+ => SNat n -- sz, ARG[1]+ -> FilePath -- file, ARG[2]+ -> Int -- rd, ARG[3]+ -> BitVector m+ template: |-+ // asyncRomFile begin+ reg ~TYPO ~GENSYM[ROM][0] [0:~LIT[1]-1];++ initial begin+ $readmemb(~FILE[~LIT[2]],~SYM[0]);+ end++ assign ~RESULT = ~SYM[0][~ARG[3]];+ // asyncRomFile end
− prims/verilog/Clash_Signal_BiSignal.primitives
@@ -1,35 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Signal.BiSignal.writeToBiSignal#",- "kind" : "Declaration",- "renderVoid": "RenderVoid",- "type" :-"writeToBiSignal#- :: HasCallStack -- ARG[0]- => BiSignalIn ds d n -- ARG[1]- -> Signal d (Maybe (BitVector n)) -- ARG[2]- -> Signal d Bool -- ARG[3]- -> Signal d (BitVector n) -- ARG[4]- -> BiSignalOut ds d n",- "template":-"// writeToBiSignal# begin-assign ~ARG[1] = (~ARG[3] == 1'b1) ? ~ARG[4] : {~SIZE[~TYP[1]] {1'bz}};-// writeToBiSignal# end"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.BiSignal.readFromBiSignal#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" :-"readFromBiSignal#- :: ( HasCallStack -- ARG[0]- , KnownNat n) -- ARG[1]- => BiSignalIn ds d n -- ARG[2]- -> Signal d (BitVector n)"- , "template" :-"// readFromBiSignal begin-assign ~RESULT = ~ARG[2];-// readFromBiSignal end"- }- }-]
+ prims/verilog/Clash_Signal_BiSignal.primitives.yaml view
@@ -0,0 +1,30 @@+- BlackBox:+ name: Clash.Signal.BiSignal.writeToBiSignal#+ kind: Declaration+ type: |-+ writeToBiSignal#+ :: HasCallStack -- ARG[0]+ => BiSignalIn ds d n -- ARG[1]+ -> Signal d (Maybe (BitVector n)) -- ARG[2]+ -> Signal d Bool -- ARG[3]+ -> Signal d (BitVector n) -- ARG[4]+ -> BiSignalOut ds d n+ renderVoid: RenderVoid+ template: |-+ // writeToBiSignal# begin+ assign ~ARG[1] = (~ARG[3] == 1'b1) ? ~ARG[4] : {~SIZE[~TYP[1]] {1'bz}};+ // writeToBiSignal# end+- BlackBox:+ name: Clash.Signal.BiSignal.readFromBiSignal#+ kind: Declaration+ type: |-+ readFromBiSignal#+ :: ( HasCallStack -- ARG[0]+ , KnownNat n) -- ARG[1]+ => BiSignalIn ds d n -- ARG[2]+ -> Signal d (BitVector n)+ template: |-+ // readFromBiSignal begin+ assign ~RESULT = ~ARG[2];+ // readFromBiSignal end+ workInfo: Never
− prims/verilog/Clash_Signal_Internal.primitives
@@ -1,144 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Signal.Internal.delay#"- , "kind" : "Declaration"- , "type" :-"delay#- :: ( KnownDomain dom -- ARG[0]- , Undefined a ) -- ARG[1]- => Clock dom -- ARG[2]- -> Enable dom -- ARG[3]- -> a -- ARG[4]- -> Signal clk a -- ARG[5]- -> Signal clk a"- , "outputReg" : true- , "resultName" : { "template" : "~CTXNAME" }- , "resultInit" : { "template" : "~IF~ISINITDEFINED[0]~THEN~CONST[4]~ELSE~FI" }- , "template" :-"// delay begin~IF ~ISACTIVEENABLE[3] ~THEN-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[2]) begin : ~GENSYM[~RESULT_delay][1]- if (~ARG[3]) begin- ~RESULT <= ~ARG[5];- end-end~ELSE-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[2]) begin : ~SYM[1]- ~RESULT <= ~ARG[5];-end~FI-// delay end"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.asyncRegister#"- , "kind" : "Declaration"- , "type" :-"asyncRegister#- :: ( KnownDomain dom -- ARG[0]- , NFDataX a ) -- ARG[1]- => Clock dom -- ARG[2]- -> Reset dom -- ARG[3]- -> Enable dom -- ARG[4]- -> a -- ARG[5] (powerup value)- -> a -- ARG[6] (reset value)- -> Signal clk a -- ARG[7]- -> Signal clk a"- , "outputReg" : true- , "resultName" : { "template" : "~CTXNAME" }- , "resultInit" : { "template" : "~IF~ISINITDEFINED[0]~THEN~CONST[5]~ELSE~FI" }- , "template" :-"// async register begin-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[2]~IF ~ISUNDEFINED[6] ~THEN ~ELSE or ~IF ~ISACTIVEHIGH[0] ~THEN posedge ~ELSE negedge ~FI ~VAR[rst][3]~FI) begin : ~GENSYM[~RESULT_register][1]- ~IF ~ISUNDEFINED[6] ~THEN ~ELSEif (~IF ~ISACTIVEHIGH[0] ~THEN ~ELSE ! ~FI~VAR[rst][3]) begin- ~RESULT <= ~CONST[6];- end else ~FI~IF ~ISACTIVEENABLE[4] ~THENif (~ARG[4]) ~ELSE~FIbegin- ~RESULT <= ~ARG[7];- end-end-// async register end"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.register#"- , "kind" : "Declaration"- , "type" :-"register#- :: ( KnownDomain dom -- ARG[0]- , Undefined a ) -- ARG[1]- => Clock dom -- ARG[2]- -> Reset dom -- ARG[3]- -> Enable dom -- ARG[4]- -> a -- ARG[5] (powerup value)- -> a -- ARG[6] (reset value)- -> Signal clk a -- ARG[7]- -> Signal clk a"- , "outputReg" : true- , "resultName" : { "template" : "~CTXNAME" }- , "resultInit" : { "template" : "~IF~ISINITDEFINED[0]~THEN~CONST[5]~ELSE~FI" }- , "template" :-"// register begin-always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[2]~IF ~ISSYNC[0] ~THEN ~ELSE~IF ~ISUNDEFINED[6] ~THEN ~ELSE or ~IF ~ISACTIVEHIGH[0] ~THEN posedge ~ELSE negedge ~FI ~VAR[rst][3]~FI~FI) begin : ~GENSYM[~RESULT_register][1]- ~IF ~ISUNDEFINED[6] ~THEN ~ELSEif (~IF ~ISACTIVEHIGH[0] ~THEN ~ELSE ! ~FI~VAR[rst][3]) begin- ~RESULT <= ~CONST[6];- end else ~FI~IF ~ISACTIVEENABLE[4] ~THENif (~ARG[4]) ~ELSE~FIbegin- ~RESULT <= ~ARG[7];- end-end-// register end"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.clockGen"- , "workInfo" : "Always"- , "kind" : "Declaration"- , "warning" : "Clash.Signal.Internal.clockGen is not synthesizable!"- , "type" :-"clockGen- :: KnownDomain dom -- ARG[0]- => Clock dom"- , "template" :-"// clockGen begin-// pragma translate_off-reg ~TYPO ~GENSYM[clk][0];-// 1 = 0.1ps-localparam ~GENSYM[half_period][1] = (~PERIOD[0]0 / 2);-always begin- // Delay of 1 mitigates race conditions (https://github.com/steveicarus/iverilog/issues/160)- #1 ~SYM[0] = ~IF~ACTIVEEDGE[Rising][0]~THEN 0 ~ELSE 1 ~FI;- #30000 forever begin- ~SYM[0] = ~ ~SYM[0];- #~SYM[1];- ~SYM[0] = ~ ~SYM[0];- #~SYM[1];- end-end-assign ~RESULT = ~SYM[0];-// pragma translate_on-// clockGen end"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.resetGenN"- , "workInfo" : "Always"- , "kind" : "Declaration"- , "type" : "resetGenN :: (KnownDomain dom, 1 <= n) => SNat n -> Reset dom"- , "template" :-"// resetGen on-// pragma translate_off-~IF~ISSYNC[0]~THEN-reg ~TYPO ~GENSYM[rst][0];-localparam ~GENSYM[reset_period][1] = 29998 + (~LIT[2] * ~PERIOD[0]0);-initial begin- #1 ~SYM[0] = ~IF ~ISACTIVEHIGH[0] ~THEN 1 ~ELSE 0 ~FI;- #~SYM[1] ~SYM[0] = ~IF ~ISACTIVEHIGH[0] ~THEN 0 ~ELSE 1 ~FI;-end-assign ~RESULT = ~SYM[0];~ELSE-reg ~TYPO ~SYM[0];-localparam ~SYM[1] = 30001 + ((~LIT[2] - 1) * ~PERIOD[0]0);-initial begin- #1 ~SYM[0] = ~IF ~ISACTIVEHIGH[0] ~THEN 1 ~ELSE 0 ~FI;- #~SYM[1] ~SYM[0] = ~IF ~ISACTIVEHIGH[0] ~THEN 0 ~ELSE 1 ~FI;-end-assign ~RESULT = ~SYM[0]; ~FI-// pragma translate_on-// resetGen end"- }- }-]
+ prims/verilog/Clash_Signal_Internal.primitives.yaml view
@@ -0,0 +1,190 @@+- BlackBox:+ name: Clash.Signal.Internal.delay#+ kind: Declaration+ outputReg: true+ type: |-+ delay#+ :: ( KnownDomain dom -- ARG[0]+ , Undefined a ) -- ARG[1]+ => Clock dom -- ARG[2]+ -> Enable dom -- ARG[3]+ -> a -- ARG[4]+ -> Signal clk a -- ARG[5]+ -> Signal clk a+ resultInit:+ template: ~IF~ISINITDEFINED[0]~THEN~CONST[4]~ELSE~FI+ resultName:+ template: ~CTXNAME+ template: |-+ // delay begin~IF ~ISACTIVEENABLE[3] ~THEN+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[2]) begin : ~GENSYM[~RESULT_delay][1]+ if (~ARG[3]) begin+ ~RESULT <= ~ARG[5];+ end+ end~ELSE+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[2]) begin : ~SYM[1]+ ~RESULT <= ~ARG[5];+ end~FI+ // delay end+- BlackBox:+ name: Clash.Signal.Internal.asyncRegister#+ kind: Declaration+ outputReg: true+ type: |-+ asyncRegister#+ :: ( KnownDomain dom -- ARG[0]+ , NFDataX a ) -- ARG[1]+ => Clock dom -- ARG[2]+ -> Reset dom -- ARG[3]+ -> Enable dom -- ARG[4]+ -> a -- ARG[5] (powerup value)+ -> a -- ARG[6] (reset value)+ -> Signal clk a -- ARG[7]+ -> Signal clk a+ resultInit:+ template: ~IF~ISINITDEFINED[0]~THEN~CONST[5]~ELSE~FI+ resultName:+ template: ~CTXNAME+ template: |-+ // async register begin+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[2]~IF ~ISUNDEFINED[6] ~THEN ~ELSE or ~IF ~ISACTIVEHIGH[0] ~THEN posedge ~ELSE negedge ~FI ~VAR[rst][3]~FI) begin : ~GENSYM[~RESULT_register][1]+ ~IF ~ISUNDEFINED[6] ~THEN ~ELSEif (~IF ~ISACTIVEHIGH[0] ~THEN ~ELSE ! ~FI~VAR[rst][3]) begin+ ~RESULT <= ~CONST[6];+ end else ~FI~IF ~ISACTIVEENABLE[4] ~THENif (~ARG[4]) ~ELSE~FIbegin+ ~RESULT <= ~ARG[7];+ end+ end+ // async register end+- BlackBox:+ name: Clash.Signal.Internal.register#+ kind: Declaration+ outputReg: true+ type: |-+ register#+ :: ( KnownDomain dom -- ARG[0]+ , Undefined a ) -- ARG[1]+ => Clock dom -- ARG[2]+ -> Reset dom -- ARG[3]+ -> Enable dom -- ARG[4]+ -> a -- ARG[5] (powerup value)+ -> a -- ARG[6] (reset value)+ -> Signal clk a -- ARG[7]+ -> Signal clk a+ resultInit:+ template: ~IF~ISINITDEFINED[0]~THEN~CONST[5]~ELSE~FI+ resultName:+ template: ~CTXNAME+ template: |-+ // register begin+ always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[2]~IF ~ISSYNC[0] ~THEN ~ELSE~IF ~ISUNDEFINED[6] ~THEN ~ELSE or ~IF ~ISACTIVEHIGH[0] ~THEN posedge ~ELSE negedge ~FI ~VAR[rst][3]~FI~FI) begin : ~GENSYM[~RESULT_register][1]+ ~IF ~ISUNDEFINED[6] ~THEN ~ELSEif (~IF ~ISACTIVEHIGH[0] ~THEN ~ELSE ! ~FI~VAR[rst][3]) begin+ ~RESULT <= ~CONST[6];+ end else ~FI~IF ~ISACTIVEENABLE[4] ~THENif (~ARG[4]) ~ELSE~FIbegin+ ~RESULT <= ~ARG[7];+ end+ end+ // register end+- BlackBox:+ name: Clash.Signal.Internal.clockGen+ kind: Declaration+ type: |-+ clockGen+ :: KnownDomain dom -- ARG[0]+ => Clock dom+ template: |-+ // clockGen begin+ // pragma translate_off+ reg ~TYPO ~GENSYM[clk][0];+ // 1 = 0.1ps+ localparam ~GENSYM[half_period][1] = (~PERIOD[0]0 / 2);+ always begin+ // Delay of 1 mitigates race conditions (https://github.com/steveicarus/iverilog/issues/160)+ #1 ~SYM[0] = ~IF~ACTIVEEDGE[Rising][0]~THEN 0 ~ELSE 1 ~FI;+ `ifndef VERILATOR+ #~LONGESTPERIOD0 forever begin+ ~SYM[0] = ~ ~SYM[0];+ #~SYM[1];+ ~SYM[0] = ~ ~SYM[0];+ #~SYM[1];+ end+ `else+ ~SYM[0] = $c("this->~GENSYM[tb_clock_gen][2](",~SYM[1],",~IF~ACTIVEEDGE[Rising][0]~THENtrue~ELSEfalse~FI)");+ `endif+ end++ `ifdef VERILATOR+ `systemc_interface+ CData ~SYM[2](vluint32_t half_period, bool active_rising) {+ static vluint32_t init_wait = ~LONGESTPERIOD0;+ static vluint32_t to_wait = 0;+ static CData clock = active_rising ? 0 : 1;++ if(init_wait == 0) {+ if(to_wait == 0) {+ to_wait = half_period - 1;+ clock = clock == 0 ? 1 : 0;+ }+ else {+ to_wait = to_wait - 1;+ }+ }+ else {+ init_wait = init_wait - 1;+ }++ return clock;+ }+ `verilog+ `endif++ assign ~RESULT = ~SYM[0];+ // pragma translate_on+ // clockGen end+ warning: Clash.Signal.Internal.clockGen is not synthesizable!+ workInfo: Always+- BlackBox:+ name: Clash.Signal.Internal.resetGenN+ kind: Declaration+ type: 'resetGenN :: (KnownDomain+ dom, 1 <= n) => SNat n -> Reset dom'+ template: |-+ // resetGen begin+ // pragma translate_off+ reg ~TYPO ~GENSYM[rst][0];+ localparam ~GENSYM[reset_period][1] = ~LONGESTPERIOD0 - 10 + (~LIT[2] * ~PERIOD[0]0);+ `ifndef VERILATOR+ initial begin+ #1 ~SYM[0] = ~IF ~ISACTIVEHIGH[0] ~THEN 1 ~ELSE 0 ~FI;+ #~SYM[1] ~SYM[0] = ~IF ~ISACTIVEHIGH[0] ~THEN 0 ~ELSE 1 ~FI;+ end+ `else+ always begin+ // The redundant (~SYM[0] | ~ ~SYM[0]) is needed to ensure that this is+ // calculated in every cycle by verilator. Without it, the reset will stop+ // being updated and will be stuck as asserted forever.+ ~SYM[0] = $c("this->~GENSYM[reset_gen][2](",~SYM[1],",~IF~ISACTIVEHIGH[0]~THENtrue~ELSEfalse~FI)") & (~SYM[0] | ~ ~SYM[0]);+ end+ `systemc_interface+ CData ~SYM[2](vluint32_t reset_period, bool active_high) {+ static vluint32_t to_wait = reset_period;+ static CData reset = active_high ? 1 : 0;+ static bool finished = false;++ if(!finished) {+ if(to_wait == 0) {+ reset = reset == 0 ? 1 : 0;+ finished = true;+ }+ else {+ to_wait = to_wait - 1;+ }+ }++ return reset;+ }+ `verilog+ `endif+ assign ~RESULT = ~SYM[0];+ // pragma translate_on+ // resetGen end+ workInfo: Always
− prims/verilog/Clash_Sized_Internal_BitVector.primitives
@@ -1,75 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.replaceBit#"- , "kind" : "Declaration"- , "type" :-"replaceBit# :: KnownNat n -- ARG[0]- => BitVector n -- ARG[1]- -> Int -- ARG[2]- -> Bit -- ARG[3]- -> BitVector n"- , "outputReg" : true- , "template" :-"// replaceBit start-always @(*) begin- ~RESULT = ~ARG[1];- ~RESULT[~ARG[2]] = ~VAR[din][3];-end-// replaceBit end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.setSlice#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" :-"setSlice# :: SNat (m + 1 + i)- -> BitVector (m + 1 + i) -- ARG[1]- -> SNat m -- ARG[2]- -> SNat n -- ARG[3]- -> BitVector (m + 1 - n) -- ARG[4]- -> BitVector (m + 1 + i)"- , "outputReg" : true- , "template" :-"// setSlice begin-always @(*) begin- ~RESULT = ~ARG[1];- ~RESULT[~LIT[2] : ~LIT[3]] = ~VAR[din][4];-end-// setSlice end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.split#"- , "kind" : "Expression"- , "type" :-"split# :: KnownNat n -- ARG[0]- => BitVector (m + n) -- ARG[1]- -> (BitVector m, BitVector n)"- , "template" : "~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.rotateL#"- , "kind" : "Declaration"- , "type" : "rotateL# :: KnownNat n => BitVector n -> Int -> BitVector n"- , "template" :-"// rotateL begin-wire [2*~SIZE[~TYPO]-1:0] ~GENSYM[bv][0];-assign ~SYM[0] = {~ARG[1],~ARG[1]} << (~ARG[2] % ~SIZE[~TYPO]);-assign ~RESULT = ~SYM[0][2*~SIZE[~TYPO]-1 : ~SIZE[~TYPO]];-// rotateL end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.rotateR#"- , "kind" : "Declaration"- , "type" : "rotateR# :: KnownNat n => BitVector n -> Int -> BitVector n"- , "template" :-"// rotateR begin-wire [2*~SIZE[~TYPO]-1:0] ~GENSYM[bv][0];-assign ~SYM[0] = {~ARG[1],~ARG[1]} >> (~ARG[2] % ~SIZE[~TYPO]);-assign ~RESULT = ~SYM[0][~SIZE[~TYPO]-1 : 0];-// rotateR end"- }- }-]
+ prims/verilog/Clash_Sized_Internal_BitVector.primitives.yaml view
@@ -0,0 +1,66 @@+- BlackBox:+ name: Clash.Sized.Internal.BitVector.replaceBit#+ kind: Declaration+ outputReg: true+ type: |-+ replaceBit# :: KnownNat n -- ARG[0]+ => BitVector n -- ARG[1]+ -> Int -- ARG[2]+ -> Bit -- ARG[3]+ -> BitVector n+ template: |-+ // replaceBit start+ always @(*) begin+ ~RESULT = ~ARG[1];+ ~RESULT[~ARG[2]] = ~VAR[din][3];+ end+ // replaceBit end+- BlackBox:+ name: Clash.Sized.Internal.BitVector.setSlice#+ kind: Declaration+ outputReg: true+ type: |-+ setSlice# :: SNat (m + 1 + i)+ -> BitVector (m + 1 + i) -- ARG[1]+ -> SNat m -- ARG[2]+ -> SNat n -- ARG[3]+ -> BitVector (m + 1 - n) -- ARG[4]+ -> BitVector (m + 1 + i)+ template: |-+ // setSlice begin+ always @(*) begin+ ~RESULT = ~ARG[1];+ ~RESULT[~LIT[2] : ~LIT[3]] = ~VAR[din][4];+ end+ // setSlice end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.split#+ kind: Expression+ type: |-+ split# :: KnownNat n -- ARG[0]+ => BitVector (m + n) -- ARG[1]+ -> (BitVector m, BitVector n)+ template: ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.rotateL#+ kind: Declaration+ type: 'rotateL# :: KnownNat+ n => BitVector n -> Int -> BitVector n'+ template: |-+ // rotateL begin+ wire [2*~SIZE[~TYPO]-1:0] ~GENSYM[bv][0];+ assign ~SYM[0] = {~ARG[1],~ARG[1]} << (~ARG[2] % ~SIZE[~TYPO]);+ assign ~RESULT = ~SYM[0][2*~SIZE[~TYPO]-1 : ~SIZE[~TYPO]];+ // rotateL end+- BlackBox:+ name: Clash.Sized.Internal.BitVector.rotateR#+ kind: Declaration+ type: 'rotateR# :: KnownNat+ n => BitVector n -> Int -> BitVector n'+ template: |-+ // rotateR begin+ wire [2*~SIZE[~TYPO]-1:0] ~GENSYM[bv][0];+ assign ~SYM[0] = {~ARG[1],~ARG[1]} >> (~ARG[2] % ~SIZE[~TYPO]);+ assign ~RESULT = ~SYM[0][~SIZE[~TYPO]-1 : 0];+ // rotateR end
− prims/verilog/Clash_Sized_Internal_Signed.primitives
@@ -1,69 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.div#"- , "kind" : "Declaration"- , "type" : "div# :: Signed n -> Signed n -> Signed n"- , "template" :-"// divSigned begin-wire ~GENSYM[resultPos][1];-wire ~GENSYM[dividerNeg][2];-wire signed [~SIZE[~TYPO]:0] ~GENSYM[dividend2][3];-wire signed [~SIZE[~TYPO]:0] ~GENSYM[dividendE][4];-wire signed [~SIZE[~TYPO]:0] ~GENSYM[dividerE][5];-wire signed [~SIZE[~TYPO]:0] ~GENSYM[quot_res][6];--assign ~SYM[1] = ~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1];-assign ~SYM[2] = ~VAR[divider][1][~SIZE[~TYPO]-1] == 1'b1;-assign ~SYM[4] = $signed({{~VAR[dividend][0][~SIZE[~TYPO]-1]},~VAR[dividend][0]}); // sign extension-assign ~SYM[5] = $signed({{~VAR[divider][1][~SIZE[~TYPO]-1]} ,~VAR[divider][1]} ); // sign extension--assign ~SYM[3] = ~SYM[1] ? ~SYM[4]- : (~SYM[2] ? (~SYM[4] - ~SYM[5] - ~SIZE[~TYPO]'sd1)- : (~SYM[4] - ~SYM[5] + ~SIZE[~TYPO]'sd1));--assign ~SYM[6] = ~SYM[3] / ~SYM[5];-assign ~RESULT = $signed(~SYM[6][~SIZE[~TYPO]-1:0]);-// divSigned end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.mod#"- , "kind" : "Declaration"- , "type" : "mod# :: Signed n -> Signed n -> Signed n"- , "template" :-"// modSigned begin-// remainder-wire ~SIGD[~GENSYM[rem_res][0]][0];-assign ~SYM[0] = ~VAR[dividend][0] % ~VAR[divider][1];--// modulo-assign ~RESULT = (~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1]) ?- ~SYM[0] :- (~SYM[0] == ~SIZE[~TYPO]'sd0 ? ~SIZE[~TYPO]'sd0 : ~SYM[0] + ~VAR[divider][1]);-// modSigned end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.rotateL#"- , "kind" : "Declaration"- , "type" : "rotateL# :: KnownNat n => Signed n -> Int -> Signed n"- , "template" :-"// rotateL begin-wire [2*~SIZE[~TYPO]-1:0] ~GENSYM[s][0];-assign ~SYM[0] = {~ARG[1],~ARG[1]} << (~ARG[2] % ~SIZE[~TYPO]);-assign ~RESULT = $signed(~SYM[0][2*~SIZE[~TYPO]-1 : ~SIZE[~TYPO]]);-// rotateL end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.rotateR#"- , "kind" : "Declaration"- , "type" : "rotateR# :: KnownNat n => Signed n -> Int -> Signed n"- , "template" :-"// rotateR begin-wire [2*~SIZE[~TYPO]-1:0] ~GENSYM[s][0];-assign ~SYM[0] = {~ARG[1],~ARG[1]} >> (~ARG[2] % ~SIZE[~TYPO]);-assign ~RESULT = $signed(~SYM[0][~SIZE[~TYPO]-1 : 0]);-// rotateR end"- }- }-]
+ prims/verilog/Clash_Sized_Internal_Signed.primitives.yaml view
@@ -0,0 +1,64 @@+- BlackBox:+ name: Clash.Sized.Internal.Signed.div#+ kind: Declaration+ type: 'div# :: KnownNat+ n => Signed n -> Signed n -> Signed n'+ template: |-+ // divSigned begin+ wire ~GENSYM[resultPos][1];+ wire ~GENSYM[dividerNeg][2];+ wire signed [~SIZE[~TYPO]:0] ~GENSYM[dividend2][3];+ wire signed [~SIZE[~TYPO]:0] ~GENSYM[dividendE][4];+ wire signed [~SIZE[~TYPO]:0] ~GENSYM[dividerE][5];+ wire signed [~SIZE[~TYPO]:0] ~GENSYM[quot_res][6];++ assign ~SYM[1] = ~VAR[dividend][1][~SIZE[~TYPO]-1] == ~VAR[divider][2][~SIZE[~TYPO]-1];+ assign ~SYM[2] = ~VAR[divider][2][~SIZE[~TYPO]-1] == 1'b1;+ assign ~SYM[4] = $signed({{~VAR[dividend][1][~SIZE[~TYPO]-1]},~VAR[dividend][1]}); // sign extension+ assign ~SYM[5] = $signed({{~VAR[divider][2][~SIZE[~TYPO]-1]} ,~VAR[divider][2]} ); // sign extension++ assign ~SYM[3] = ~SYM[1] ? ~SYM[4]+ : (~SYM[2] ? (~SYM[4] - ~SYM[5] - ~SIZE[~TYPO]'sd1)+ : (~SYM[4] - ~SYM[5] + ~SIZE[~TYPO]'sd1));++ assign ~SYM[6] = ~SYM[3] / ~SYM[5];+ assign ~RESULT = $signed(~SYM[6][~SIZE[~TYPO]-1:0]);+ // divSigned end+- BlackBox:+ name: Clash.Sized.Internal.Signed.mod#+ kind: Declaration+ type: 'mod# :: Signed+ n -> Signed n -> Signed n'+ template: |-+ // modSigned begin+ // remainder+ wire ~SIGD[~GENSYM[rem_res][0]][0];+ assign ~SYM[0] = ~VAR[dividend][0] % ~VAR[divider][1];++ // modulo+ assign ~RESULT = (~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1]) ?+ ~SYM[0] :+ (~SYM[0] == ~SIZE[~TYPO]'sd0 ? ~SIZE[~TYPO]'sd0 : ~SYM[0] + ~VAR[divider][1]);+ // modSigned end+- BlackBox:+ name: Clash.Sized.Internal.Signed.rotateL#+ kind: Declaration+ type: 'rotateL# :: KnownNat+ n => Signed n -> Int -> Signed n'+ template: |-+ // rotateL begin+ wire [2*~SIZE[~TYPO]-1:0] ~GENSYM[s][0];+ assign ~SYM[0] = {~ARG[1],~ARG[1]} << (~ARG[2] % ~SIZE[~TYPO]);+ assign ~RESULT = $signed(~SYM[0][2*~SIZE[~TYPO]-1 : ~SIZE[~TYPO]]);+ // rotateL end+- BlackBox:+ name: Clash.Sized.Internal.Signed.rotateR#+ kind: Declaration+ type: 'rotateR# :: KnownNat+ n => Signed n -> Int -> Signed n'+ template: |-+ // rotateR begin+ wire [2*~SIZE[~TYPO]-1:0] ~GENSYM[s][0];+ assign ~SYM[0] = {~ARG[1],~ARG[1]} >> (~ARG[2] % ~SIZE[~TYPO]);+ assign ~RESULT = $signed(~SYM[0][~SIZE[~TYPO]-1 : 0]);+ // rotateR end
− prims/verilog/Clash_Sized_Internal_Unsigned.primitives
@@ -1,25 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.rotateL#"- , "kind" : "Declaration"- , "type" : "rotateL# :: KnownNat n => Unsigned n -> Int -> Unsigned n"- , "template" :-"// rotateL begin-wire [2*~SIZE[~TYPO]-1:0] ~GENSYM[u][0];-assign ~SYM[0] = {~ARG[1],~ARG[1]} << (~ARG[2] % ~SIZE[~TYPO]);-assign ~RESULT = ~SYM[0][2*~SIZE[~TYPO]-1 : ~SIZE[~TYPO]];-// rotateL end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.rotateR#"- , "kind" : "Declaration"- , "type" : "rotateR# :: KnownNat n => Unsigned n -> Int -> Unsigned n"- , "template" :-"// rotateR begin-wire [2*~SIZE[~TYPO]-1:0] ~GENSYM[u][0];-assign ~SYM[0] = {~ARG[1],~ARG[1]} >> (~ARG[2] % ~SIZE[~TYPO]);-assign ~RESULT = ~SYM[0][~SIZE[~TYPO]-1 : 0];-// rotateR end"- }- }-]
+ prims/verilog/Clash_Sized_Internal_Unsigned.primitives.yaml view
@@ -0,0 +1,22 @@+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.rotateL#+ kind: Declaration+ type: 'rotateL# :: KnownNat+ n => Unsigned n -> Int -> Unsigned n'+ template: |-+ // rotateL begin+ wire [2*~SIZE[~TYPO]-1:0] ~GENSYM[u][0];+ assign ~SYM[0] = {~ARG[1],~ARG[1]} << (~ARG[2] % ~SIZE[~TYPO]);+ assign ~RESULT = ~SYM[0][2*~SIZE[~TYPO]-1 : ~SIZE[~TYPO]];+ // rotateL end+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.rotateR#+ kind: Declaration+ type: 'rotateR# :: KnownNat+ n => Unsigned n -> Int -> Unsigned n'+ template: |-+ // rotateR begin+ wire [2*~SIZE[~TYPO]-1:0] ~GENSYM[u][0];+ assign ~SYM[0] = {~ARG[1],~ARG[1]} >> (~ARG[2] % ~SIZE[~TYPO]);+ assign ~RESULT = ~SYM[0][~SIZE[~TYPO]-1 : 0];+ // rotateR end
− prims/verilog/Clash_Sized_RTree.primitives
@@ -1,25 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Sized.RTree.treplicate"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "replicate :: SNat d -> a -> RTree d a"- , "template" : "{(2**~LIT[0]) {~ARG[1]}}"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.RTree.textract"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "textract :: RTree 0 a -> a"- , "template" : "~VAR[tree][0][~SIZE[~TYP[0]]-1 -: ~SIZE[~TYPO]]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.RTree.tsplit"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "tsplit:: RTree (d+1) a -> (RTree d a,RTree d a)"- , "template" : "~ARG[0]"- }- }-]
+ prims/verilog/Clash_Sized_RTree.primitives.yaml view
@@ -0,0 +1,21 @@+- BlackBox:+ name: Clash.Sized.RTree.treplicate+ kind: Expression+ type: 'replicate :: SNat+ d -> a -> RTree d a'+ template: '{(2**~LIT[0]) {~ARG[1]}}'+ workInfo: Never+- BlackBox:+ name: Clash.Sized.RTree.textract+ kind: Expression+ type: 'textract :: RTree+ 0 a -> a'+ template: '~VAR[tree][0][~SIZE[~TYP[0]]-1 -: ~SIZE[~TYPO]]'+ workInfo: Never+- BlackBox:+ name: Clash.Sized.RTree.tsplit+ kind: Expression+ type: 'tsplit:: RTree+ (d+1) a -> (RTree d a,RTree d a)'+ template: ~ARG[0]+ workInfo: Never
− prims/verilog/Clash_Sized_Vector.primitives
@@ -1,379 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Sized.Vector.head"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "head :: Vec (n + 1) a -> a"- , "template" : "~FROMBV[~VAR[vec][0][\\~SIZE[~TYP[0]]-1 -: ~SIZE[~TYPO]\\]][~TYPO]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.tail"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "tail :: Vec (n + 1) a -> Vec n a"- , "template" : "~VAR[vec][0][~SIZE[~TYPO]-1 : 0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.last"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "Vec (n + 1) a -> a"- , "template" : "~FROMBV[~VAR[vec][0][\\~SIZE[~TYPO]-1:0\\]][~TYPO]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.init"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "Vec (n + 1) a -> Vec n a"- , "template" : "~VAR[vec][0][~SIZE[~TYP[0]]-1 : ~SIZE[~TYPEL[~TYP[0]]]]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.select"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" :-"select :: (CmpNat (i + s) (s * n) ~ GT) -- ARG[0]- => SNat f -- ARG[1]- -> SNat s -- ARG[2]- -> SNat n -- ARG[3]- -> Vec i a -- ARG[4]- -> Vec n a"- , "template" :-"// select begin-wire ~TYPEL[~TYPO] ~SYM[1] [0:~LENGTH[~TYP[4]]-1];-genvar ~GENSYM[i][2];-~GENERATE-for (~SYM[2]=0; ~SYM[2] < ~LENGTH[~TYP[4]]; ~SYM[2]=~SYM[2]+1) begin : ~GENSYM[mk_array][3]- assign ~SYM[1][(~LENGTH[~TYP[4]]-1)-~SYM[2]] = ~VAR[vec][4][~SYM[2]*~SIZE[~TYPEL[~TYPO]]+:~SIZE[~TYPEL[~TYPO]]];-end-~ENDGENERATE--genvar ~GENSYM[i][4];-~GENERATE-for (~SYM[4]=0; ~SYM[4] < ~LIT[3]; ~SYM[4] = ~SYM[4] + 1) begin : ~GENSYM[select][5]- assign ~RESULT[(~LIT[3]-1-~SYM[4])*~SIZE[~TYPEL[~TYPO]]+:~SIZE[~TYPEL[~TYPO]]] = ~SYM[1][~LIT[1] + (~LIT[2] * ~SYM[4])];-end-~ENDGENERATE-// select end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.++"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "(++) :: Vec n a -> Vec m a -> Vec (n + m) a"- , "template" : "{~ARG[0],~ARG[1]}"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.concat"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "concat :: Vec n (Vec m a) -> Vec (n * m) a"- , "template" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.splitAt"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "splitAt :: SNat m -> Vec (m + n) a -> (Vec m a, Vec n a)"- , "template" : "~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.unconcat"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" :- "unconcat :: KnownNat n -- ARG[0]- => SNat m -- ARG[1]- -> Vec (n * m) a -- ARG[2]- -> Vec n (Vec m a)"- , "template" : "~ARG[2]~DEVNULL[~ARG[0]]~DEVNULL[~ARG[1]]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.map"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "map :: (a -> b) -> Vec n a -> Vec n b"- , "template" :-"// map begin-genvar ~GENSYM[i][1];-~GENERATE-for (~SYM[1]=0; ~SYM[1] < ~LENGTH[~TYPO]; ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[map][2]~IF~SIZE[~TYP[1]]~THEN- wire ~TYPEL[~TYP[1]] ~GENSYM[map_in][3];- assign ~SYM[3] = ~VAR[vec][1][~SYM[1]*~SIZE[~TYPEL[~TYP[1]]]+:~SIZE[~TYPEL[~TYP[1]]]];~ELSE ~FI- ~OUTPUTWIREREG[0] ~TYPEL[~TYPO] ~GENSYM[map_out][4];- ~INST 0- ~OUTPUT <= ~SYM[4]~ ~TYPEL[~TYPO]~- ~INPUT <= ~SYM[3]~ ~TYPEL[~TYP[1]]~- ~INST- assign ~RESULT[~SYM[1]*~SIZE[~TYPEL[~TYPO]]+:~SIZE[~TYPEL[~TYPO]]] = ~SYM[4];-end-~ENDGENERATE-// map end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.imap"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "imap :: KnownNat n => (Index n -> a -> b) -> Vec n a -> Vec n b"- , "template" :-"// imap begin-genvar ~GENSYM[i][1];-~GENERATE-for (~SYM[1]=0; ~SYM[1] < ~LENGTH[~TYPO]; ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[imap][2]- wire [~SIZE[~INDEXTYPE[~LIT[0]]]-1:0] ~GENSYM[map_index][3];~IF~SIZE[~TYP[2]]~THEN- wire ~TYPEL[~TYP[2]] ~GENSYM[map_in][4];- assign ~SYM[4] = ~VAR[vec][2][~SYM[1]*~SIZE[~TYPEL[~TYP[2]]]+:~SIZE[~TYPEL[~TYP[2]]]];~ELSE ~FI- ~OUTPUTWIREREG[1] ~TYPEL[~TYPO] ~GENSYM[map_out][5];-- assign ~SYM[3] = ~SIZE[~INDEXTYPE[~LIT[0]]]'d~MAXINDEX[~TYPO] - ~SYM[1][0+:~SIZE[~INDEXTYPE[~LIT[0]]]];- ~INST 1- ~OUTPUT <= ~SYM[5]~ ~TYPEL[~TYPO]~- ~INPUT <= ~SYM[3]~ ~INDEXTYPE[~LIT[0]]~- ~INPUT <= ~SYM[4]~ ~TYPEL[~TYP[2]]~- ~INST- assign ~RESULT[~SYM[1]*~SIZE[~TYPEL[~TYPO]]+:~SIZE[~TYPEL[~TYPO]]] = ~SYM[5];-end-~ENDGENERATE-// imap end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.imap_go"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "imap :: Index n -> (Index n -> a -> b) -> Vec m a -> Vec m b"- , "template" :-"// imap begin-genvar ~GENSYM[i][1];-~GENERATE-for (~SYM[1]=0; ~SYM[1] < ~LENGTH[~TYPO]; ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[imap][2]- wire ~TYP[0] ~GENSYM[map_index][3];~IF~SIZE[~TYP[2]]~THEN- wire ~TYPEL[~TYP[2]] ~GENSYM[map_in][4];- assign ~SYM[4] = ~VAR[vec][2][~SYM[1]*~SIZE[~TYPEL[~TYP[2]]]+:~SIZE[~TYPEL[~TYP[2]]]];~ELSE ~FI- ~OUTPUTWIREREG[1] ~TYPEL[~TYPO] ~GENSYM[map_out][5];-- assign ~SYM[3] = ~SIZE[~TYP[0]]'d~MAXINDEX[~TYPO] - ~SYM[1][0+:~SIZE[~TYP[0]]] + ~ARG[0];- ~INST 1- ~OUTPUT <= ~SYM[5]~ ~TYPEL[~TYPO]~- ~INPUT <= ~SYM[3]~ ~TYP[0]~- ~INPUT <= ~SYM[4]~ ~TYPEL[~TYP[2]]~- ~INST- assign ~RESULT[~SYM[1]*~SIZE[~TYPEL[~TYPO]]+:~SIZE[~TYPEL[~TYPO]]] = ~SYM[5];-end-~ENDGENERATE-// imap end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.zipWith"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "zipWith :: (a -> b -> c) -> Vec n a -> Vec n b -> Vec n c"- , "template" :-"// zipWith start-genvar ~GENSYM[i][2];-~GENERATE-for (~SYM[2] = 0; ~SYM[2] < ~LENGTH[~TYPO]; ~SYM[2] = ~SYM[2] + 1) begin : ~GENSYM[zipWith][6]~IF~SIZE[~TYP[1]]~THEN- wire ~TYPEL[~TYP[1]] ~GENSYM[zipWith_in1][3];- assign ~SYM[3] = ~VAR[vec1][1][~SYM[2]*~SIZE[~TYPEL[~TYP[1]]]+:~SIZE[~TYPEL[~TYP[1]]]];~ELSE ~FI~IF~SIZE[~TYP[2]]~THEN- wire ~TYPEL[~TYP[2]] ~GENSYM[zipWith_in2][4];- assign ~SYM[4] = ~VAR[vec2][2][~SYM[2]*~SIZE[~TYPEL[~TYP[2]]]+:~SIZE[~TYPEL[~TYP[2]]]];~ELSE ~FI- ~OUTPUTWIREREG[0] ~TYPEL[~TYPO] ~SYM[5];- ~INST 0- ~OUTPUT <= ~SYM[5]~ ~TYPEL[~TYPO]~- ~INPUT <= ~SYM[3]~ ~TYPEL[~TYP[1]]~- ~INPUT <= ~SYM[4]~ ~TYPEL[~TYP[2]]~- ~INST- assign ~RESULT[~SYM[2]*~SIZE[~TYPEL[~TYPO]]+:~SIZE[~TYPEL[~TYPO]]] = ~SYM[5];-end-~ENDGENERATE-// zipWith end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.foldr"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "foldr :: (a -> b -> b) -> b -> Vec n a -> b"- , "template" :-"// foldr start~IF ~LENGTH[~TYP[2]] ~THEN-wire ~TYPO ~GENSYM[intermediate][0] [0:~LENGTH[~TYP[2]]];-assign ~SYM[0][~LENGTH[~TYP[2]]] = ~ARG[1];--genvar ~GENSYM[i][3];-~GENERATE-for (~SYM[3]=0; ~SYM[3] < ~LENGTH[~TYP[2]]; ~SYM[3]=~SYM[3]+1) begin : ~GENSYM[foldr][4]~IF~SIZE[~TYP[2]]~THEN- wire ~TYPEL[~TYP[2]] ~GENSYM[foldr_in1][5];- assign ~SYM[5] = ~VAR[xs][2][(~LENGTH[~TYP[2]]-1-~SYM[3])*~SIZE[~TYPEL[~TYP[2]]]+:~SIZE[~TYPEL[~TYP[2]]]];~ELSE ~FI- wire ~TYPO ~GENSYM[foldr_in2][6];- ~OUTPUTWIREREG[0] ~TYPO ~GENSYM[foldr_out][7];-- assign ~SYM[6] = ~SYM[0][~SYM[3]+1];- ~INST 0- ~OUTPUT <= ~SYM[7]~ ~TYP[1]~- ~INPUT <= ~SYM[5]~ ~TYPEL[~TYP[2]]~- ~INPUT <= ~SYM[6]~ ~TYP[1]~- ~INST- assign ~SYM[0][~SYM[3]] = ~SYM[7];-end-~ENDGENERATE--assign ~RESULT = ~SYM[0][0];-~ELSE-assign ~RESULT = ~ARG[1];-~FI// foldr end"- }- }-, { "BlackBoxHaskell" :- { "name" : "Clash.Sized.Vector.index_int"- , "templateFunction" : "Clash.Primitives.Sized.Vector.indexIntVerilog"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.replace_int"- , "kind" : "Declaration"- , "type" : "replace_int :: KnownNat n => Vec n a -> Int -> a -> Vec n a"- , "template" :-"// vector replace begin-genvar ~GENSYM[i][0];-~GENERATE-for (~SYM[0]=0;~SYM[0]<~LENGTH[~TYPO];~SYM[0]=~SYM[0]+1) begin : ~GENSYM[vector_replace][1]- assign ~RESULT[(~MAXINDEX[~TYPO]-~SYM[0])*~SIZE[~TYP[3]]+:~SIZE[~TYP[3]]] = ~ARG[2] == ~SYM[0] ? ~ARG[3] : ~VAR[vec][1][(~MAXINDEX[~TYPO]-~SYM[0])*~SIZE[~TYP[3]]+:~SIZE[~TYP[3]]];-end-~ENDGENERATE-// vector replace end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.maxIndex"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "maxIndex :: KnownNat n => Vec n a -> Int"- , "template" : "~SIZE[~TYPO]'sd~LIT[0] - ~SIZE[~TYPO]'d1"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.length"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "length :: KnownNat n => Vec n a -> Int"- , "template" : "~SIZE[~TYPO]'sd~LIT[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.replicate"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "replicate :: SNat n -> a -> Vec n a"- , "template" : "{~LIT[0] {~ARG[1]}}"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.transpose"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "transpose :: KnownNat n => Vec m (Vec n a) -> Vec n (Vec m a)"- , "template" :-"// transpose begin-genvar ~GENSYM[row_index][1];-genvar ~GENSYM[col_index][2];-~GENERATE-for (~SYM[1] = 0; ~SYM[1] < ~LENGTH[~TYP[1]]; ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[transpose_outer][3]- for (~SYM[2] = 0; ~SYM[2] < ~LENGTH[~TYPO]; ~SYM[2] = ~SYM[2] + 1) begin : ~GENSYM[transpose_inner][4]- assign ~RESULT[((~SYM[2]*~SIZE[~TYPEL[~TYPO]])+(~SYM[1]*~SIZE[~TYPEL[~TYPEL[~TYPO]]]))+:~SIZE[~TYPEL[~TYPEL[~TYPO]]]] = ~VAR[matrix][1][((~SYM[1]*~SIZE[~TYPEL[~TYP[1]]])+(~SYM[2]*~SIZE[~TYPEL[~TYPEL[~TYPO]]]))+:~SIZE[~TYPEL[~TYPEL[~TYPO]]]];- end-end-~ENDGENERATE-// transpose end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.reverse"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "reverse :: Vec n a -> Vec n a"- , "template" :-"// reverse begin-genvar ~GENSYM[i][1];-~GENERATE-for (~SYM[1] = 0; ~SYM[1] < ~LENGTH[~TYPO]; ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[reverse][2]- assign ~RESULT[(~LENGTH[~TYPO] - 1 - ~SYM[1])*~SIZE[~TYPEL[~TYPO]]+:~SIZE[~TYPEL[~TYPO]]] = ~VAR[vec][0][~SYM[1]*~SIZE[~TYPEL[~TYPO]]+:~SIZE[~TYPEL[~TYPO]]];-end-~ENDGENERATE-// reverse end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.concatBitVector#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" :-"concatBitVector# :: (KnownNat n, KnownNat m) -- (ARG[0],ARG[1])- => Vec n (BitVector m) -- ARG[2]- -> BitVector (n * m)"- , "template" : "~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.unconcatBitVector#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" :-"unconcatBitVector# :: (KnownNat n, KnownNat m) -- (ARG[0],ARG[1])- => BitVector (n * m) -- ARG[2]- -> Vec n (BitVector m)"- , "template" : "~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.rotateLeftS"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "rotateLeftS :: KnownNat n => Vec n a -> SNat d -> Vec n a"- , "template" :-"// rotateLeftS begin-localparam ~GENSYM[shift_amount][2] = ~LIT[2] % ~LIT[0];--~GENERATE-if (~SYM[2] == 0) begin : ~GENSYM[no_shift][3]- assign ~RESULT = ~VAR[vec][1];-end else begin : ~GENSYM[do_shift][4]- assign ~RESULT = {~VAR[vec][1][((~LIT[0]-~SYM[2])*~SIZE[~TYPEL[~TYPO]])-1 : 0]- ,~VAR[vec][1][~SIZE[~TYPO]-1 : (~LIT[0]-~SYM[2])*~SIZE[~TYPEL[~TYPO]]]- };-end-~ENDGENERATE-// rotateLeftS end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.rotateRightS"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "rotateRightS :: KnownNat n => Vec n a -> SNat d -> Vec n a"- , "template" :-"// rotateRightS begin-localparam ~GENSYM[shift_amount][2] = ~LIT[2] % ~LIT[0];--~GENERATE-if (~SYM[2] == 0) begin : ~GENSYM[no_shift][3]- assign ~RESULT = ~VAR[vec][1];-end else begin : ~GENSYM[do_shift][4]- assign ~RESULT = {~VAR[vec][1][(~SYM[2]*~SIZE[~TYPEL[~TYPO]])-1 : 0]- ,~VAR[vec][1][~SIZE[~TYPO]-1 : ~SYM[2]*~SIZE[~TYPEL[~TYPO]]]- };-end-~ENDGENERATE-// rotateRightS end"- }- }-]
+ prims/verilog/Clash_Sized_Vector.primitives.yaml view
@@ -0,0 +1,348 @@+- BlackBox:+ name: Clash.Sized.Vector.head+ kind: Expression+ type: 'head :: Vec (n+ + 1) a -> a'+ template: '~FROMBV[~VAR[vec][0][\~SIZE[~TYP[0]]-1 -: ~SIZE[~TYPO]\]][~TYPO]'+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.tail+ kind: Expression+ type: 'tail :: Vec (n+ + 1) a -> Vec n a'+ template: '~VAR[vec][0][~SIZE[~TYPO]-1 : 0]'+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.last+ kind: Expression+ type: Vec (n + 1) a ->+ a+ template: ~FROMBV[~VAR[vec][0][\~SIZE[~TYPO]-1:0\]][~TYPO]+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.init+ kind: Expression+ type: Vec (n + 1) a ->+ Vec n a+ template: '~VAR[vec][0][~SIZE[~TYP[0]]-1 : ~SIZE[~TYPEL[~TYP[0]]]]'+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.select+ kind: Declaration+ type: |-+ select :: (CmpNat (i + s) (s * n) ~ GT) -- ARG[0]+ => SNat f -- ARG[1]+ -> SNat s -- ARG[2]+ -> SNat n -- ARG[3]+ -> Vec i a -- ARG[4]+ -> Vec n a+ template: |-+ // select begin+ wire ~TYPEL[~TYPO] ~SYM[1] [0:~LENGTH[~TYP[4]]-1];+ genvar ~GENSYM[i][2];+ ~GENERATE+ for (~SYM[2]=0; ~SYM[2] < ~LENGTH[~TYP[4]]; ~SYM[2]=~SYM[2]+1) begin : ~GENSYM[mk_array][3]+ assign ~SYM[1][(~LENGTH[~TYP[4]]-1)-~SYM[2]] = ~VAR[vec][4][~SYM[2]*~SIZE[~TYPEL[~TYPO]]+:~SIZE[~TYPEL[~TYPO]]];+ end+ ~ENDGENERATE++ genvar ~GENSYM[i][4];+ ~GENERATE+ for (~SYM[4]=0; ~SYM[4] < ~LIT[3]; ~SYM[4] = ~SYM[4] + 1) begin : ~GENSYM[select][5]+ assign ~RESULT[(~LIT[3]-1-~SYM[4])*~SIZE[~TYPEL[~TYPO]]+:~SIZE[~TYPEL[~TYPO]]] = ~SYM[1][~LIT[1] + (~LIT[2] * ~SYM[4])];+ end+ ~ENDGENERATE+ // select end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.+++ kind: Expression+ type: '(++) :: Vec n a+ -> Vec m a -> Vec (n + m) a'+ template: '{~ARG[0],~ARG[1]}'+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.concat+ kind: Expression+ type: 'concat :: Vec n+ (Vec m a) -> Vec (n * m) a'+ template: ~ARG[0]+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.splitAt+ kind: Expression+ type: 'splitAt :: SNat+ m -> Vec (m + n) a -> (Vec m a, Vec n a)'+ template: ~ARG[1]+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.unconcat+ kind: Expression+ type: |-+ unconcat :: KnownNat n -- ARG[0]+ => SNat m -- ARG[1]+ -> Vec (n * m) a -- ARG[2]+ -> Vec n (Vec m a)+ template: ~ARG[2]~DEVNULL[~ARG[0]]~DEVNULL[~ARG[1]]+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.map+ kind: Declaration+ type: 'map :: (a -> b)+ -> Vec n a -> Vec n b'+ template: |-+ // map begin+ genvar ~GENSYM[i][1];+ ~GENERATE+ for (~SYM[1]=0; ~SYM[1] < ~LENGTH[~TYPO]; ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[map][2]~IF~SIZE[~TYP[1]]~THEN+ wire ~TYPEL[~TYP[1]] ~GENSYM[map_in][3];+ assign ~SYM[3] = ~VAR[vec][1][~SYM[1]*~SIZE[~TYPEL[~TYP[1]]]+:~SIZE[~TYPEL[~TYP[1]]]];~ELSE ~FI+ ~OUTPUTWIREREG[0] ~TYPEL[~TYPO] ~GENSYM[map_out][4];+ ~INST 0+ ~OUTPUT <= ~SYM[4]~ ~TYPEL[~TYPO]~+ ~INPUT <= ~SYM[3]~ ~TYPEL[~TYP[1]]~+ ~INST+ assign ~RESULT[~SYM[1]*~SIZE[~TYPEL[~TYPO]]+:~SIZE[~TYPEL[~TYPO]]] = ~SYM[4];+ end+ ~ENDGENERATE+ // map end+ workInfo: Identity 1 [0]+- BlackBox:+ name: Clash.Sized.Vector.imap+ kind: Declaration+ type: 'imap :: KnownNat+ n => (Index n -> a -> b) -> Vec n a -> Vec n b'+ template: |-+ // imap begin+ genvar ~GENSYM[i][1];+ ~GENERATE+ for (~SYM[1]=0; ~SYM[1] < ~LENGTH[~TYPO]; ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[imap][2]+ wire [~SIZE[~INDEXTYPE[~LIT[0]]]-1:0] ~GENSYM[map_index][3];~IF~SIZE[~TYP[2]]~THEN+ wire ~TYPEL[~TYP[2]] ~GENSYM[map_in][4];+ assign ~SYM[4] = ~VAR[vec][2][~SYM[1]*~SIZE[~TYPEL[~TYP[2]]]+:~SIZE[~TYPEL[~TYP[2]]]];~ELSE ~FI+ ~OUTPUTWIREREG[1] ~TYPEL[~TYPO] ~GENSYM[map_out][5];++ assign ~SYM[3] = ~SIZE[~INDEXTYPE[~LIT[0]]]'d~MAXINDEX[~TYPO] - ~SYM[1][0+:~SIZE[~INDEXTYPE[~LIT[0]]]];+ ~INST 1+ ~OUTPUT <= ~SYM[5]~ ~TYPEL[~TYPO]~+ ~INPUT <= ~SYM[3]~ ~INDEXTYPE[~LIT[0]]~+ ~INPUT <= ~SYM[4]~ ~TYPEL[~TYP[2]]~+ ~INST+ assign ~RESULT[~SYM[1]*~SIZE[~TYPEL[~TYPO]]+:~SIZE[~TYPEL[~TYPO]]] = ~SYM[5];+ end+ ~ENDGENERATE+ // imap end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.imap_go+ kind: Declaration+ type: 'imap :: Index n+ -> (Index n -> a -> b) -> Vec m a -> Vec m b'+ template: |-+ // imap begin+ genvar ~GENSYM[i][1];+ ~GENERATE+ for (~SYM[1]=0; ~SYM[1] < ~LENGTH[~TYPO]; ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[imap][2]+ wire ~TYP[0] ~GENSYM[map_index][3];~IF~SIZE[~TYP[2]]~THEN+ wire ~TYPEL[~TYP[2]] ~GENSYM[map_in][4];+ assign ~SYM[4] = ~VAR[vec][2][~SYM[1]*~SIZE[~TYPEL[~TYP[2]]]+:~SIZE[~TYPEL[~TYP[2]]]];~ELSE ~FI+ ~OUTPUTWIREREG[1] ~TYPEL[~TYPO] ~GENSYM[map_out][5];++ assign ~SYM[3] = ~SIZE[~TYP[0]]'d~MAXINDEX[~TYPO] - ~SYM[1][0+:~SIZE[~TYP[0]]] + ~ARG[0];+ ~INST 1+ ~OUTPUT <= ~SYM[5]~ ~TYPEL[~TYPO]~+ ~INPUT <= ~SYM[3]~ ~TYP[0]~+ ~INPUT <= ~SYM[4]~ ~TYPEL[~TYP[2]]~+ ~INST+ assign ~RESULT[~SYM[1]*~SIZE[~TYPEL[~TYPO]]+:~SIZE[~TYPEL[~TYPO]]] = ~SYM[5];+ end+ ~ENDGENERATE+ // imap end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.zipWith+ kind: Declaration+ type: 'zipWith :: (a ->+ b -> c) -> Vec n a -> Vec n b -> Vec n c'+ template: |-+ // zipWith start+ genvar ~GENSYM[i][2];+ ~GENERATE+ for (~SYM[2] = 0; ~SYM[2] < ~LENGTH[~TYPO]; ~SYM[2] = ~SYM[2] + 1) begin : ~GENSYM[zipWith][6]~IF~SIZE[~TYP[1]]~THEN+ wire ~TYPEL[~TYP[1]] ~GENSYM[zipWith_in1][3];+ assign ~SYM[3] = ~VAR[vec1][1][~SYM[2]*~SIZE[~TYPEL[~TYP[1]]]+:~SIZE[~TYPEL[~TYP[1]]]];~ELSE ~FI~IF~SIZE[~TYP[2]]~THEN+ wire ~TYPEL[~TYP[2]] ~GENSYM[zipWith_in2][4];+ assign ~SYM[4] = ~VAR[vec2][2][~SYM[2]*~SIZE[~TYPEL[~TYP[2]]]+:~SIZE[~TYPEL[~TYP[2]]]];~ELSE ~FI+ ~OUTPUTWIREREG[0] ~TYPEL[~TYPO] ~SYM[5];+ ~INST 0+ ~OUTPUT <= ~SYM[5]~ ~TYPEL[~TYPO]~+ ~INPUT <= ~SYM[3]~ ~TYPEL[~TYP[1]]~+ ~INPUT <= ~SYM[4]~ ~TYPEL[~TYP[2]]~+ ~INST+ assign ~RESULT[~SYM[2]*~SIZE[~TYPEL[~TYPO]]+:~SIZE[~TYPEL[~TYPO]]] = ~SYM[5];+ end+ ~ENDGENERATE+ // zipWith end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.foldr+ kind: Declaration+ type: 'foldr :: (a ->+ b -> b) -> b -> Vec n a -> b'+ template: |-+ // foldr start~IF ~LENGTH[~TYP[2]] ~THEN+ wire ~TYPO ~GENSYM[intermediate][0] [0:~LENGTH[~TYP[2]]];+ assign ~SYM[0][~LENGTH[~TYP[2]]] = ~ARG[1];++ genvar ~GENSYM[i][3];+ ~GENERATE+ for (~SYM[3]=0; ~SYM[3] < ~LENGTH[~TYP[2]]; ~SYM[3]=~SYM[3]+1) begin : ~GENSYM[foldr][4]~IF~SIZE[~TYP[2]]~THEN+ wire ~TYPEL[~TYP[2]] ~GENSYM[foldr_in1][5];+ assign ~SYM[5] = ~VAR[xs][2][(~LENGTH[~TYP[2]]-1-~SYM[3])*~SIZE[~TYPEL[~TYP[2]]]+:~SIZE[~TYPEL[~TYP[2]]]];~ELSE ~FI+ wire ~TYPO ~GENSYM[foldr_in2][6];+ ~OUTPUTWIREREG[0] ~TYPO ~GENSYM[foldr_out][7];++ assign ~SYM[6] = ~SYM[0][~SYM[3]+1];+ ~INST 0+ ~OUTPUT <= ~SYM[7]~ ~TYP[1]~+ ~INPUT <= ~SYM[5]~ ~TYPEL[~TYP[2]]~+ ~INPUT <= ~SYM[6]~ ~TYP[1]~+ ~INST+ assign ~SYM[0][~SYM[3]] = ~SYM[7];+ end+ ~ENDGENERATE++ assign ~RESULT = ~SYM[0][0];+ ~ELSE+ assign ~RESULT = ~ARG[1];+ ~FI// foldr end+ workInfo: Never+- BlackBoxHaskell:+ name: Clash.Sized.Vector.index_int+ templateFunction: Clash.Primitives.Sized.Vector.indexIntVerilog+- BlackBox:+ name: Clash.Sized.Vector.replace_int+ kind: Declaration+ type: 'replace_int ::+ KnownNat n => Vec n a -> Int -> a -> Vec n a'+ template: |-+ // vector replace begin+ genvar ~GENSYM[i][0];+ ~GENERATE+ for (~SYM[0]=0;~SYM[0]<~LENGTH[~TYPO];~SYM[0]=~SYM[0]+1) begin : ~GENSYM[vector_replace][1]+ assign ~RESULT[(~MAXINDEX[~TYPO]-~SYM[0])*~SIZE[~TYP[3]]+:~SIZE[~TYP[3]]] = ~ARG[2] == ~SYM[0] ? ~ARG[3] : ~VAR[vec][1][(~MAXINDEX[~TYPO]-~SYM[0])*~SIZE[~TYP[3]]+:~SIZE[~TYP[3]]];+ end+ ~ENDGENERATE+ // vector replace end+- BlackBox:+ name: Clash.Sized.Vector.maxIndex+ kind: Expression+ type: 'maxIndex :: KnownNat+ n => Vec n a -> Int'+ template: ~SIZE[~TYPO]'sd~LIT[0] - ~SIZE[~TYPO]'d1+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Vector.length+ kind: Expression+ type: 'length :: KnownNat+ n => Vec n a -> Int'+ template: ~SIZE[~TYPO]'sd~LIT[0]+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Vector.replicate+ kind: Expression+ type: 'replicate :: SNat+ n -> a -> Vec n a'+ template: '{~LIT[0] {~ARG[1]}}'+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.transpose+ kind: Declaration+ type: 'transpose :: KnownNat+ n => Vec m (Vec n a) -> Vec n (Vec m a)'+ template: |-+ // transpose begin+ genvar ~GENSYM[row_index][1];+ genvar ~GENSYM[col_index][2];+ ~GENERATE+ for (~SYM[1] = 0; ~SYM[1] < ~LENGTH[~TYP[1]]; ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[transpose_outer][3]+ for (~SYM[2] = 0; ~SYM[2] < ~LENGTH[~TYPO]; ~SYM[2] = ~SYM[2] + 1) begin : ~GENSYM[transpose_inner][4]+ assign ~RESULT[((~SYM[2]*~SIZE[~TYPEL[~TYPO]])+(~SYM[1]*~SIZE[~TYPEL[~TYPEL[~TYPO]]]))+:~SIZE[~TYPEL[~TYPEL[~TYPO]]]] = ~VAR[matrix][1][((~SYM[1]*~SIZE[~TYPEL[~TYP[1]]])+(~SYM[2]*~SIZE[~TYPEL[~TYPEL[~TYPO]]]))+:~SIZE[~TYPEL[~TYPEL[~TYPO]]]];+ end+ end+ ~ENDGENERATE+ // transpose end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.reverse+ kind: Declaration+ type: 'reverse :: Vec+ n a -> Vec n a'+ template: |-+ // reverse begin+ genvar ~GENSYM[i][1];+ ~GENERATE+ for (~SYM[1] = 0; ~SYM[1] < ~LENGTH[~TYPO]; ~SYM[1] = ~SYM[1] + 1) begin : ~GENSYM[reverse][2]+ assign ~RESULT[(~LENGTH[~TYPO] - 1 - ~SYM[1])*~SIZE[~TYPEL[~TYPO]]+:~SIZE[~TYPEL[~TYPO]]] = ~VAR[vec][0][~SYM[1]*~SIZE[~TYPEL[~TYPO]]+:~SIZE[~TYPEL[~TYPO]]];+ end+ ~ENDGENERATE+ // reverse end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.concatBitVector#+ kind: Expression+ type: |-+ concatBitVector# :: (KnownNat n, KnownNat m) -- (ARG[0],ARG[1])+ => Vec n (BitVector m) -- ARG[2]+ -> BitVector (n * m)+ template: ~ARG[2]+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.unconcatBitVector#+ kind: Expression+ type: |-+ unconcatBitVector# :: (KnownNat n, KnownNat m) -- (ARG[0],ARG[1])+ => BitVector (n * m) -- ARG[2]+ -> Vec n (BitVector m)+ template: ~ARG[2]+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.rotateLeftS+ kind: Declaration+ type: 'rotateLeftS ::+ KnownNat n => Vec n a -> SNat d -> Vec n a'+ template: |-+ // rotateLeftS begin+ localparam ~GENSYM[shift_amount][2] = ~LIT[2] % ~LIT[0];++ ~GENERATE+ if (~SYM[2] == 0) begin : ~GENSYM[no_shift][3]+ assign ~RESULT = ~VAR[vec][1];+ end else begin : ~GENSYM[do_shift][4]+ assign ~RESULT = {~VAR[vec][1][((~LIT[0]-~SYM[2])*~SIZE[~TYPEL[~TYPO]])-1 : 0]+ ,~VAR[vec][1][~SIZE[~TYPO]-1 : (~LIT[0]-~SYM[2])*~SIZE[~TYPEL[~TYPO]]]+ };+ end+ ~ENDGENERATE+ // rotateLeftS end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.rotateRightS+ kind: Declaration+ type: 'rotateRightS ::+ KnownNat n => Vec n a -> SNat d -> Vec n a'+ template: |-+ // rotateRightS begin+ localparam ~GENSYM[shift_amount][2] = ~LIT[2] % ~LIT[0];++ ~GENERATE+ if (~SYM[2] == 0) begin : ~GENSYM[no_shift][3]+ assign ~RESULT = ~VAR[vec][1];+ end else begin : ~GENSYM[do_shift][4]+ assign ~RESULT = {~VAR[vec][1][(~SYM[2]*~SIZE[~TYPEL[~TYPO]])-1 : 0]+ ,~VAR[vec][1][~SIZE[~TYPO]-1 : ~SYM[2]*~SIZE[~TYPEL[~TYPO]]]+ };+ end+ ~ENDGENERATE+ // rotateRightS end+ workInfo: Never
− prims/verilog/Clash_Xilinx_DDR.primitives
@@ -1,92 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Xilinx.DDR.iddr"- , "kind" : "Declaration"- , "type" :-"iddr- :: ( HasCallStack -- ARG[0]- , KnownConfi~ fast domf -- ARG[1]- , KnownConfi~ slow doms -- ARG[2]- , KnownNat m ) -- ARG[3]- -> Clock slow -- ARG[4]- -> Reset slow -- ARG[5]- -> Enable slow -- ARG[6]- -> Signal fast (BitVector m) -- ARG[7]- -> Signal slow (BitVector m,BitVector m)"- , "template" :-"// iddr begin-wire ~SIGD[~GENSYM[dataout_l][1]][7];-wire ~SIGD[~GENSYM[dataout_h][2]][7];-wire ~SIGD[~GENSYM[d][3]][7];-assign ~SYM[3] = ~ARG[7];--genvar ~GENSYM[i][8];-~GENERATE-for (~SYM[8]=0; ~SYM[8] < ~SIZE[~TYP[7]]; ~SYM[8]=~SYM[8]+1) begin : ~GENSYM[ddri_array][7]- IDDR #(- .DDR_CLK_EDGE(\"SAME_EDGE\"),- .INIT_Q1(1'b0),- .INIT_Q2(1'b0),- .SRTYPE(~IF ~ISSYNC[2] ~THEN \"SYNC\" ~ELSE \"ASYNC\" ~FI)- ) ~GENSYM[~COMPNAME_IDDR][9] (- .Q1(~SYM[1][~SYM[8]]),- .Q2(~SYM[2][~SYM[8]]),- .C(~ARG[4]),- .CE(~IF ~ISACTIVEENABLE[6] ~THEN ~ARG[6] ~ELSE 1'b1 ~FI),- .D(~SYM[3][~SYM[8]]),- .R(~ARG[5]),- .S(1'b0)- );-end-~ENDGENERATE--assign ~RESULT = {~SYM[2],~SYM[1]};-// iddr end"- }- }-, { "BlackBox" :- { "name" : "Clash.Xilinx.DDR.oddr#"- , "kind" : "Declaration"- , "type" :-"oddr#- :: ( KnownConfi~ fast domf -- ARG[0]- , KnownConfi~ slow doms -- ARG[1]- , KnownNat m ) -- ARG[2]- => Clock slow -- ARG[3]- -> Reset slow -- ARG[4]- -> Enable slow -- ARG[5]- -> Signal slow (BitVector m) -- ARG[6]- -> Signal slow (BitVector m) -- ARG[7]- -> Signal fast (BitVector m)"- , "template" :-"// oddr begin-wire ~SIGD[~GENSYM[datain_l][1]][7];-wire ~SIGD[~GENSYM[datain_h][2]][7];-wire ~SIGD[~GENSYM[q][3]][7];--assign ~SYM[1] = ~ARG[6];-assign ~SYM[2] = ~ARG[7];--genvar ~GENSYM[i][8];-~GENERATE-for (~SYM[8]=0; ~SYM[8] < ~SIZE[~TYP[7]]; ~SYM[8]=~SYM[8]+1) begin : ~GENSYM[ddro_array][7]- ODDR #(- .DDR_CLK_EDGE(\"SAME_EDGE\"),- .INIT(1'b0),- .SRTYPE(~IF ~ISSYNC[1] ~THEN \"SYNC\" ~ELSE \"ASYNC\" ~FI)- ) ~GENSYM[~COMPNAME_ODDR][9] (- .Q(~SYM[3][~SYM[8]]),- .C(~ARG[3]),- .CE(~IF ~ISACTIVEENABLE[5] ~THEN ~ARG[5] ~ELSE 1'b1 ~FI),- .D1(~SYM[1][~SYM[8]]),- .D2(~SYM[2][~SYM[8]]),- .R(~ARG[4]),- .S(1'b0)- );-end-~ENDGENERATE--assign ~RESULT = ~SYM[3];-// oddr end"- }- }-]
+ prims/verilog/Clash_Xilinx_DDR.primitives.yaml view
@@ -0,0 +1,87 @@+- BlackBox:+ name: Clash.Xilinx.DDR.iddr+ kind: Declaration+ type: |-+ iddr+ :: ( HasCallStack -- ARG[0]+ , KnownConfi~ fast domf -- ARG[1]+ , KnownConfi~ slow doms -- ARG[2]+ , KnownNat m ) -- ARG[3]+ -> Clock slow -- ARG[4]+ -> Reset slow -- ARG[5]+ -> Enable slow -- ARG[6]+ -> Signal fast (BitVector m) -- ARG[7]+ -> Signal slow (BitVector m,BitVector m)+ template: |-+ // iddr begin+ wire ~SIGD[~GENSYM[dataout_l][1]][7];+ wire ~SIGD[~GENSYM[dataout_h][2]][7];+ wire ~SIGD[~GENSYM[d][3]][7];+ assign ~SYM[3] = ~ARG[7];++ genvar ~GENSYM[i][8];+ ~GENERATE+ for (~SYM[8]=0; ~SYM[8] < ~SIZE[~TYP[7]]; ~SYM[8]=~SYM[8]+1) begin : ~GENSYM[ddri_array][7]+ IDDR #(+ .DDR_CLK_EDGE("SAME_EDGE"),+ .INIT_Q1(1'b0),+ .INIT_Q2(1'b0),+ .SRTYPE(~IF ~ISSYNC[2] ~THEN "SYNC" ~ELSE "ASYNC" ~FI)+ ) ~GENSYM[~COMPNAME_IDDR][9] (+ .Q1(~SYM[1][~SYM[8]]),+ .Q2(~SYM[2][~SYM[8]]),+ .C(~ARG[4]),+ .CE(~IF ~ISACTIVEENABLE[6] ~THEN ~ARG[6] ~ELSE 1'b1 ~FI),+ .D(~SYM[3][~SYM[8]]),+ .R(~ARG[5]),+ .S(1'b0)+ );+ end+ ~ENDGENERATE++ assign ~RESULT = {~SYM[2],~SYM[1]};+ // iddr end+- BlackBox:+ name: Clash.Xilinx.DDR.oddr#+ kind: Declaration+ type: |-+ oddr#+ :: ( KnownConfi~ fast domf -- ARG[0]+ , KnownConfi~ slow doms -- ARG[1]+ , KnownNat m ) -- ARG[2]+ => Clock slow -- ARG[3]+ -> Reset slow -- ARG[4]+ -> Enable slow -- ARG[5]+ -> Signal slow (BitVector m) -- ARG[6]+ -> Signal slow (BitVector m) -- ARG[7]+ -> Signal fast (BitVector m)+ template: |-+ // oddr begin+ wire ~SIGD[~GENSYM[datain_l][1]][7];+ wire ~SIGD[~GENSYM[datain_h][2]][7];+ wire ~SIGD[~GENSYM[q][3]][7];++ assign ~SYM[1] = ~ARG[6];+ assign ~SYM[2] = ~ARG[7];++ genvar ~GENSYM[i][8];+ ~GENERATE+ for (~SYM[8]=0; ~SYM[8] < ~SIZE[~TYP[7]]; ~SYM[8]=~SYM[8]+1) begin : ~GENSYM[ddro_array][7]+ ODDR #(+ .DDR_CLK_EDGE("SAME_EDGE"),+ .INIT(1'b0),+ .SRTYPE(~IF ~ISSYNC[1] ~THEN "SYNC" ~ELSE "ASYNC" ~FI)+ ) ~GENSYM[~COMPNAME_ODDR][9] (+ .Q(~SYM[3][~SYM[8]]),+ .C(~ARG[3]),+ .CE(~IF ~ISACTIVEENABLE[5] ~THEN ~ARG[5] ~ELSE 1'b1 ~FI),+ .D1(~SYM[1][~SYM[8]]),+ .D2(~SYM[2][~SYM[8]]),+ .R(~ARG[4]),+ .S(1'b0)+ );+ end+ ~ENDGENERATE++ assign ~RESULT = ~SYM[3];+ // oddr end
− prims/verilog/GHC_Base.primitives
@@ -1,33 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Base.divInt"- , "kind" : "Declaration"- , "type" : "divInt :: Int -> Int -> Int"- , "template" :-"// divInt begin-// divide (rounds towards zero)-wire ~SIGD[~GENSYM[quot_res][0]][0];-assign ~SYM[0] = ~VAR[dividend][0] / ~VAR[divider][1];--// round toward minus infinity-assign ~RESULT = (~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1]) ? ~SYM[0] : ~SYM[0] - ~SIZE[~TYPO]'sd1;-// divInt end"- }- }-, { "BlackBox" :- { "name" : "GHC.Base.modInt"- , "kind" : "Declaration"- , "type" : "modInt :: Int -> Int -> Int"- , "template" :-"// modInt begin-// remainder-wire ~SIGD[~GENSYM[rem_res][0]][0];-assign ~SYM[0] = ~VAR[dividend][0] % ~VAR[divider][1];--// modulo-assign ~RESULT = (~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1]) ?- ~SYM[0] :- ((~VAR[dividend][0] == ~SIZE[~TYPO]'sd0) ? ~SIZE[~TYPO]'sd0 : ~SYM[0] + ~VAR[divider][1]);-// modInt end"- }- }-]
+ prims/verilog/GHC_Base.primitives.yaml view
@@ -0,0 +1,30 @@+- BlackBox:+ name: GHC.Base.divInt+ kind: Declaration+ type: 'divInt :: Int ->+ Int -> Int'+ template: |-+ // divInt begin+ // divide (rounds towards zero)+ wire ~SIGD[~GENSYM[quot_res][0]][0];+ assign ~SYM[0] = ~VAR[dividend][0] / ~VAR[divider][1];++ // round toward minus infinity+ assign ~RESULT = (~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1]) ? ~SYM[0] : ~SYM[0] - ~SIZE[~TYPO]'sd1;+ // divInt end+- BlackBox:+ name: GHC.Base.modInt+ kind: Declaration+ type: 'modInt :: Int ->+ Int -> Int'+ template: |-+ // modInt begin+ // remainder+ wire ~SIGD[~GENSYM[rem_res][0]][0];+ assign ~SYM[0] = ~VAR[dividend][0] % ~VAR[divider][1];++ // modulo+ assign ~RESULT = (~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1]) ?+ ~SYM[0] :+ ((~VAR[dividend][0] == ~SIZE[~TYPO]'sd0) ? ~SIZE[~TYPO]'sd0 : ~SYM[0] + ~VAR[divider][1]);+ // modInt end
− prims/verilog/GHC_Classes.primitives
@@ -1,45 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Classes.divInt#"- , "kind" : "Declaration"- , "type" : "divInt# :: Int# -> Int# -> Int#"- , "template" :-"// divInt# begin-wire ~GENSYM[resultPos][1];-wire ~GENSYM[dividerNeg][2];-wire signed [~SIZE[~TYPO]:0] ~GENSYM[dividend2][3];-wire signed [~SIZE[~TYPO]:0] ~GENSYM[dividendE][4];-wire signed [~SIZE[~TYPO]:0] ~GENSYM[dividerE][5];-wire signed [~SIZE[~TYPO]:0] ~GENSYM[quot_res][6];--assign ~SYM[1] = ~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1];-assign ~SYM[2] = ~VAR[divider][1][~SIZE[~TYPO]-1] == 1'b1;-assign ~SYM[4] = $signed({{~VAR[dividend][0][~SIZE[~TYPO]-1]},~VAR[dividend][0]}); // sign extension-assign ~SYM[5] = $signed({{~VAR[divider][1][~SIZE[~TYPO]-1]} ,~VAR[divider][1]} ); // sign extension--assign ~SYM[3] = ~SYM[1] ? ~SYM[4]- : (~SYM[2] ? (~SYM[4] - ~SYM[5] - ~SIZE[~TYPO]'sd1)- : (~SYM[4] - ~SYM[5] + ~SIZE[~TYPO]'sd1));--assign ~SYM[6] = ~SYM[3] / ~SYM[5];-assign ~RESULT = $signed(~SYM[6][~SIZE[~TYPO]-1:0]);-// divInt# end"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.modInt#"- , "kind" : "Declaration"- , "type" : "modInt# :: Int# -> Int# -> Int#"- , "template" :-"// modInt# begin-// remainder-wire ~SIGD[~GENSYM[rem_res][0]][0];-assign ~SYM[0] = ~VAR[dividend][0] % ~VAR[divider][1];--// modulo-assign ~RESULT = (~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1]) ?- ~SYM[0] :- ((~SYM[0] == ~SIZE[~TYPO]'sd0) ? ~SIZE[~TYPO]'sd0 : ~SYM[0] + ~VAR[divider][1]);-// modInt# end"- }- }-]
+ prims/verilog/GHC_Classes.primitives.yaml view
@@ -0,0 +1,42 @@+- BlackBox:+ name: GHC.Classes.divInt#+ kind: Declaration+ type: 'divInt# :: Int#+ -> Int# -> Int#'+ template: |-+ // divInt# begin+ wire ~GENSYM[resultPos][1];+ wire ~GENSYM[dividerNeg][2];+ wire signed [~SIZE[~TYPO]:0] ~GENSYM[dividend2][3];+ wire signed [~SIZE[~TYPO]:0] ~GENSYM[dividendE][4];+ wire signed [~SIZE[~TYPO]:0] ~GENSYM[dividerE][5];+ wire signed [~SIZE[~TYPO]:0] ~GENSYM[quot_res][6];++ assign ~SYM[1] = ~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1];+ assign ~SYM[2] = ~VAR[divider][1][~SIZE[~TYPO]-1] == 1'b1;+ assign ~SYM[4] = $signed({{~VAR[dividend][0][~SIZE[~TYPO]-1]},~VAR[dividend][0]}); // sign extension+ assign ~SYM[5] = $signed({{~VAR[divider][1][~SIZE[~TYPO]-1]} ,~VAR[divider][1]} ); // sign extension++ assign ~SYM[3] = ~SYM[1] ? ~SYM[4]+ : (~SYM[2] ? (~SYM[4] - ~SYM[5] - ~SIZE[~TYPO]'sd1)+ : (~SYM[4] - ~SYM[5] + ~SIZE[~TYPO]'sd1));++ assign ~SYM[6] = ~SYM[3] / ~SYM[5];+ assign ~RESULT = $signed(~SYM[6][~SIZE[~TYPO]-1:0]);+ // divInt# end+- BlackBox:+ name: GHC.Classes.modInt#+ kind: Declaration+ type: 'modInt# :: Int#+ -> Int# -> Int#'+ template: |-+ // modInt# begin+ // remainder+ wire ~SIGD[~GENSYM[rem_res][0]][0];+ assign ~SYM[0] = ~VAR[dividend][0] % ~VAR[divider][1];++ // modulo+ assign ~RESULT = (~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1]) ?+ ~SYM[0] :+ ((~SYM[0] == ~SIZE[~TYPO]'sd0) ? ~SIZE[~TYPO]'sd0 : ~SYM[0] + ~VAR[divider][1]);+ // modInt# end
− prims/verilog/GHC_Integer_Type.primitives
@@ -1,99 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Integer.Type.divInteger"- , "kind" : "Declaration"- , "type" : "divInteger :: Integer -> Integer -> Integer"- , "template" :-"// divInteger begin-wire ~GENSYM[resultPos][1];-wire ~GENSYM[dividerNeg][2];-wire signed [~SIZE[~TYPO]:0] ~GENSYM[dividend2][3];-wire signed [~SIZE[~TYPO]:0] ~GENSYM[dividendE][4];-wire signed [~SIZE[~TYPO]:0] ~GENSYM[dividerE][5];-wire signed [~SIZE[~TYPO]:0] ~GENSYM[quot_res][6];--assign ~SYM[1] = ~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1];-assign ~SYM[2] = ~VAR[divider][1][~SIZE[~TYPO]-1] == 1'b1;-assign ~SYM[4] = $signed({{~VAR[dividend][0][~SIZE[~TYPO]-1]},~VAR[dividend][0]}); // sign extension-assign ~SYM[5] = $signed({{~VAR[divider][1][~SIZE[~TYPO]-1]} ,~VAR[divider][1]} ); // sign extension--assign ~SYM[3] = ~SYM[1] ? ~SYM[4]- : (~SYM[2] ? (~SYM[4] - ~SYM[5] - ~SIZE[~TYPO]'sd1)- : (~SYM[4] - ~SYM[5] + ~SIZE[~TYPO]'sd1));--assign ~SYM[6] = ~SYM[3] / ~SYM[5];-assign ~RESULT = $signed(~SYM[6][~SIZE[~TYPO]-1:0]);-// divInteger end"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.modInteger"- , "kind" : "Declaration"- , "type" : "modInteger :: Integer -> Integer -> Integer"- , "template" :-"// modInteger begin-// remainder-wire ~SIGD[~GENSYM[rem_res][0]][0];-assign ~SYM[0] = ~VAR[dividend][0] % ~VAR[divider][1];--// modulo-assign ~RESULT = (~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1]) ?- ~SYM[0] :- ((~SYM[0] == ~SIZE[~TYPO]'sd0) ? ~SIZE[~TYPO]'sd0 : ~SYM[0] + ~VAR[divider][1]);-// modInteger end"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.divModInteger"- , "kind" : "Declaration"- , "type" : "divModInteger :: Integer -> Integer -> (# Integer, Integer #)"- , "template" :-"// divModInteger begin-wire ~GENSYM[resultPos][1];-wire ~GENSYM[dividerNeg][2];-wire signed [~SIZE[~TYP[0]]:0] ~GENSYM[dividend2][3];-wire signed [~SIZE[~TYP[0]]:0] ~GENSYM[dividendE][4];-wire signed [~SIZE[~TYP[0]]:0] ~GENSYM[dividerE][5];-wire signed [~SIZE[~TYP[0]]:0] ~GENSYM[quot_res][6];-wire signed [~SIZE[~TYP[0]]-1:0] ~GENSYM[div_res][7];--assign ~SYM[1] = ~VAR[dividend][0][~SIZE[~TYP[0]]-1] == ~VAR[divider][1][~SIZE[~TYP[0]]-1];-assign ~SYM[2] = ~VAR[divider][1][~SIZE[~TYP[0]]-1] == 1'b1;-assign ~SYM[4] = $signed({{~VAR[dividend][0][~SIZE[~TYP[0]]-1]},~VAR[dividend][0]}); // sign extension-assign ~SYM[5] = $signed({{~VAR[divider][1][~SIZE[~TYP[0]]-1]} ,~VAR[divider][1]} ); // sign extension--assign ~SYM[3] = ~SYM[1] ? ~SYM[4]- : (~SYM[2] ? (~SYM[4] - ~SYM[5] - ~SIZE[~TYP[0]]'sd1)- : (~SYM[4] - ~SYM[5] + ~SIZE[~TYP[0]]'sd1));--assign ~SYM[6] = ~SYM[3] / ~SYM[5];-assign ~SYM[7] = $signed(~SYM[6][~SIZE[~TYP[0]]-1:0]);--wire ~SIGD[~GENSYM[rem_res][8]][0];-wire ~SIGD[~GENSYM[mod_res][9]][0];-assign ~SYM[8] = ~VAR[dividend][0] % ~VAR[divider][1];--// modulo-assign ~SYM[9] = (~VAR[dividend][0][~SIZE[~TYP[0]]-1] == ~VAR[divider][1][~SIZE[~TYP[0]]-1]) ?- ~SYM[8] :- ((~SYM[8] == ~SIZE[~TYP[0]]'sd0) ? ~SIZE[~TYP[0]]'sd0 : ~SYM[8] + ~VAR[divider][1]);--assign ~RESULT = {~SYM[7],~SYM[9]};-// divModInteger end"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.quotRemInteger"- , "kind" : "Declaration"- , "type" : "quotRemInteger :: Integer -> Integer -> (# Integer, Integer #)"- , "template" :-"// quotRemInteger begin-wire ~SIGD[~GENSYM[quot_res][0]][0];-wire ~SIGD[~GENSYM[rem_res][1]][0];-assign ~SYM[0] = ~ARG[0] / ~ARG[1];-assign ~SYM[1] = ~ARG[0] % ~ARG[1];--assign ~RESULT = {~SYM[0],~SYM[1]};-// quotRemInteger end"- }- }-]
+ prims/verilog/GHC_Integer_Type.primitives.yaml view
@@ -0,0 +1,102 @@+- BlackBox:+ name: GHC.Integer.Type.divInteger+ kind: Declaration+ type: 'divInteger :: Integer+ -> Integer -> Integer'+ template: |-+ // divInteger begin+ wire ~GENSYM[resultPos][1];+ wire ~GENSYM[dividerNeg][2];+ wire signed [~SIZE[~TYPO]:0] ~GENSYM[dividend2][3];+ wire signed [~SIZE[~TYPO]:0] ~GENSYM[dividendE][4];+ wire signed [~SIZE[~TYPO]:0] ~GENSYM[dividerE][5];+ wire signed [~SIZE[~TYPO]:0] ~GENSYM[quot_res][6];++ assign ~SYM[1] = ~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1];+ assign ~SYM[2] = ~VAR[divider][1][~SIZE[~TYPO]-1] == 1'b1;+ assign ~SYM[4] = $signed({{~VAR[dividend][0][~SIZE[~TYPO]-1]},~VAR[dividend][0]}); // sign extension+ assign ~SYM[5] = $signed({{~VAR[divider][1][~SIZE[~TYPO]-1]} ,~VAR[divider][1]} ); // sign extension++ assign ~SYM[3] = ~SYM[1] ? ~SYM[4]+ : (~SYM[2] ? (~SYM[4] - ~SYM[5] - ~SIZE[~TYPO]'sd1)+ : (~SYM[4] - ~SYM[5] + ~SIZE[~TYPO]'sd1));++ assign ~SYM[6] = ~SYM[3] / ~SYM[5];+ assign ~RESULT = $signed(~SYM[6][~SIZE[~TYPO]-1:0]);+ // divInteger end+ warning: 'GHC.Integer.Type.divInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.modInteger+ kind: Declaration+ type: 'modInteger :: Integer+ -> Integer -> Integer'+ template: |-+ // modInteger begin+ // remainder+ wire ~SIGD[~GENSYM[rem_res][0]][0];+ assign ~SYM[0] = ~VAR[dividend][0] % ~VAR[divider][1];++ // modulo+ assign ~RESULT = (~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1]) ?+ ~SYM[0] :+ ((~SYM[0] == ~SIZE[~TYPO]'sd0) ? ~SIZE[~TYPO]'sd0 : ~SYM[0] + ~VAR[divider][1]);+ // modInteger end+ warning: 'GHC.Integer.Type.modInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.divModInteger+ kind: Declaration+ type: 'divModInteger ::+ Integer -> Integer -> (# Integer, Integer #)'+ template: |-+ // divModInteger begin+ wire ~GENSYM[resultPos][1];+ wire ~GENSYM[dividerNeg][2];+ wire signed [~SIZE[~TYP[0]]:0] ~GENSYM[dividend2][3];+ wire signed [~SIZE[~TYP[0]]:0] ~GENSYM[dividendE][4];+ wire signed [~SIZE[~TYP[0]]:0] ~GENSYM[dividerE][5];+ wire signed [~SIZE[~TYP[0]]:0] ~GENSYM[quot_res][6];+ wire signed [~SIZE[~TYP[0]]-1:0] ~GENSYM[div_res][7];++ assign ~SYM[1] = ~VAR[dividend][0][~SIZE[~TYP[0]]-1] == ~VAR[divider][1][~SIZE[~TYP[0]]-1];+ assign ~SYM[2] = ~VAR[divider][1][~SIZE[~TYP[0]]-1] == 1'b1;+ assign ~SYM[4] = $signed({{~VAR[dividend][0][~SIZE[~TYP[0]]-1]},~VAR[dividend][0]}); // sign extension+ assign ~SYM[5] = $signed({{~VAR[divider][1][~SIZE[~TYP[0]]-1]} ,~VAR[divider][1]} ); // sign extension++ assign ~SYM[3] = ~SYM[1] ? ~SYM[4]+ : (~SYM[2] ? (~SYM[4] - ~SYM[5] - ~SIZE[~TYP[0]]'sd1)+ : (~SYM[4] - ~SYM[5] + ~SIZE[~TYP[0]]'sd1));++ assign ~SYM[6] = ~SYM[3] / ~SYM[5];+ assign ~SYM[7] = $signed(~SYM[6][~SIZE[~TYP[0]]-1:0]);++ wire ~SIGD[~GENSYM[rem_res][8]][0];+ wire ~SIGD[~GENSYM[mod_res][9]][0];+ assign ~SYM[8] = ~VAR[dividend][0] % ~VAR[divider][1];++ // modulo+ assign ~SYM[9] = (~VAR[dividend][0][~SIZE[~TYP[0]]-1] == ~VAR[divider][1][~SIZE[~TYP[0]]-1]) ?+ ~SYM[8] :+ ((~SYM[8] == ~SIZE[~TYP[0]]'sd0) ? ~SIZE[~TYP[0]]'sd0 : ~SYM[8] + ~VAR[divider][1]);++ assign ~RESULT = {~SYM[7],~SYM[9]};+ // divModInteger end+ warning: 'GHC.Integer.Type.divModInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.quotRemInteger+ kind: Declaration+ type: 'quotRemInteger+ :: Integer -> Integer -> (# Integer, Integer #)'+ template: |-+ // quotRemInteger begin+ wire ~SIGD[~GENSYM[quot_res][0]][0];+ wire ~SIGD[~GENSYM[rem_res][1]][0];+ assign ~SYM[0] = ~ARG[0] / ~ARG[1];+ assign ~SYM[1] = ~ARG[0] % ~ARG[1];++ assign ~RESULT = {~SYM[0],~SYM[1]};+ // quotRemInteger end+ warning: 'GHC.Integer.Type.quotRemInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'
− prims/verilog/GHC_Num_Integer.primitives
@@ -1,99 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Num.Integer.integerDiv"- , "kind" : "Declaration"- , "type" : "integerDiv :: Integer -> Integer -> Integer"- , "template" :-"// integerDiv begin-wire ~GENSYM[resultPos][1];-wire ~GENSYM[dividerNeg][2];-wire signed [~SIZE[~TYPO]:0] ~GENSYM[dividend2][3];-wire signed [~SIZE[~TYPO]:0] ~GENSYM[dividendE][4];-wire signed [~SIZE[~TYPO]:0] ~GENSYM[dividerE][5];-wire signed [~SIZE[~TYPO]:0] ~GENSYM[quot_res][6];--assign ~SYM[1] = ~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1];-assign ~SYM[2] = ~VAR[divider][1][~SIZE[~TYPO]-1] == 1'b1;-assign ~SYM[4] = $signed({{~VAR[dividend][0][~SIZE[~TYPO]-1]},~VAR[dividend][0]}); // sign extension-assign ~SYM[5] = $signed({{~VAR[divider][1][~SIZE[~TYPO]-1]} ,~VAR[divider][1]} ); // sign extension--assign ~SYM[3] = ~SYM[1] ? ~SYM[4]- : (~SYM[2] ? (~SYM[4] - ~SYM[5] - ~SIZE[~TYPO]'sd1)- : (~SYM[4] - ~SYM[5] + ~SIZE[~TYPO]'sd1));--assign ~SYM[6] = ~SYM[3] / ~SYM[5];-assign ~RESULT = $signed(~SYM[6][~SIZE[~TYPO]-1:0]);-// integerDiv end"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerMod"- , "kind" : "Declaration"- , "type" : "integerMod :: Integer -> Integer -> Integer"- , "template" :-"// integerMod begin-// remainder-wire ~SIGD[~GENSYM[rem_res][0]][0];-assign ~SYM[0] = ~VAR[dividend][0] % ~VAR[divider][1];--// modulo-assign ~RESULT = (~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1]) ?- ~SYM[0] :- ((~SYM[0] == ~SIZE[~TYPO]'sd0) ? ~SIZE[~TYPO]'sd0 : ~SYM[0] + ~VAR[divider][1]);-// integerMod end"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerDivMod#"- , "kind" : "Declaration"- , "type" : "integerDivMod :: Integer -> Integer -> (# Integer, Integer #)"- , "template" :-"// integerDivMod begin-wire ~GENSYM[resultPos][1];-wire ~GENSYM[dividerNeg][2];-wire signed [~SIZE[~TYP[0]]:0] ~GENSYM[dividend2][3];-wire signed [~SIZE[~TYP[0]]:0] ~GENSYM[dividendE][4];-wire signed [~SIZE[~TYP[0]]:0] ~GENSYM[dividerE][5];-wire signed [~SIZE[~TYP[0]]:0] ~GENSYM[quot_res][6];-wire signed [~SIZE[~TYP[0]]-1:0] ~GENSYM[div_res][7];--assign ~SYM[1] = ~VAR[dividend][0][~SIZE[~TYP[0]]-1] == ~VAR[divider][1][~SIZE[~TYP[0]]-1];-assign ~SYM[2] = ~VAR[divider][1][~SIZE[~TYP[0]]-1] == 1'b1;-assign ~SYM[4] = $signed({{~VAR[dividend][0][~SIZE[~TYP[0]]-1]},~VAR[dividend][0]}); // sign extension-assign ~SYM[5] = $signed({{~VAR[divider][1][~SIZE[~TYP[0]]-1]} ,~VAR[divider][1]} ); // sign extension--assign ~SYM[3] = ~SYM[1] ? ~SYM[4]- : (~SYM[2] ? (~SYM[4] - ~SYM[5] - ~SIZE[~TYP[0]]'sd1)- : (~SYM[4] - ~SYM[5] + ~SIZE[~TYP[0]]'sd1));--assign ~SYM[6] = ~SYM[3] / ~SYM[5];-assign ~SYM[7] = $signed(~SYM[6][~SIZE[~TYP[0]]-1:0]);--wire ~SIGD[~GENSYM[rem_res][8]][0];-wire ~SIGD[~GENSYM[mod_res][9]][0];-assign ~SYM[8] = ~VAR[dividend][0] % ~VAR[divider][1];--// modulo-assign ~SYM[9] = (~VAR[dividend][0][~SIZE[~TYP[0]]-1] == ~VAR[divider][1][~SIZE[~TYP[0]]-1]) ?- ~SYM[8] :- ((~SYM[8] == ~SIZE[~TYP[0]]'sd0) ? ~SIZE[~TYP[0]]'sd0 : ~SYM[8] + ~VAR[divider][1]);--assign ~RESULT = {~SYM[7],~SYM[9]};-// integerDivMod end"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerQuotRem#"- , "kind" : "Declaration"- , "type" : "integerQuotRem :: Integer -> Integer -> (# Integer, Integer #)"- , "template" :-"// integerQuotRem begin-wire ~SIGD[~GENSYM[quot_res][0]][0];-wire ~SIGD[~GENSYM[rem_res][1]][0];-assign ~SYM[0] = ~ARG[0] / ~ARG[1];-assign ~SYM[1] = ~ARG[0] % ~ARG[1];--assign ~RESULT = {~SYM[0],~SYM[1]};-// integerQuotRem end"- }- }-]
+ prims/verilog/GHC_Num_Integer.primitives.yaml view
@@ -0,0 +1,102 @@+- BlackBox:+ name: GHC.Num.Integer.integerDiv+ kind: Declaration+ type: 'integerDiv :: Integer+ -> Integer -> Integer'+ template: |-+ // integerDiv begin+ wire ~GENSYM[resultPos][1];+ wire ~GENSYM[dividerNeg][2];+ wire signed [~SIZE[~TYPO]:0] ~GENSYM[dividend2][3];+ wire signed [~SIZE[~TYPO]:0] ~GENSYM[dividendE][4];+ wire signed [~SIZE[~TYPO]:0] ~GENSYM[dividerE][5];+ wire signed [~SIZE[~TYPO]:0] ~GENSYM[quot_res][6];++ assign ~SYM[1] = ~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1];+ assign ~SYM[2] = ~VAR[divider][1][~SIZE[~TYPO]-1] == 1'b1;+ assign ~SYM[4] = $signed({{~VAR[dividend][0][~SIZE[~TYPO]-1]},~VAR[dividend][0]}); // sign extension+ assign ~SYM[5] = $signed({{~VAR[divider][1][~SIZE[~TYPO]-1]} ,~VAR[divider][1]} ); // sign extension++ assign ~SYM[3] = ~SYM[1] ? ~SYM[4]+ : (~SYM[2] ? (~SYM[4] - ~SYM[5] - ~SIZE[~TYPO]'sd1)+ : (~SYM[4] - ~SYM[5] + ~SIZE[~TYPO]'sd1));++ assign ~SYM[6] = ~SYM[3] / ~SYM[5];+ assign ~RESULT = $signed(~SYM[6][~SIZE[~TYPO]-1:0]);+ // integerDiv end+ warning: 'GHC.Num.Integer.integerDiv: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerMod+ kind: Declaration+ type: 'integerMod :: Integer+ -> Integer -> Integer'+ template: |-+ // integerMod begin+ // remainder+ wire ~SIGD[~GENSYM[rem_res][0]][0];+ assign ~SYM[0] = ~VAR[dividend][0] % ~VAR[divider][1];++ // modulo+ assign ~RESULT = (~VAR[dividend][0][~SIZE[~TYPO]-1] == ~VAR[divider][1][~SIZE[~TYPO]-1]) ?+ ~SYM[0] :+ ((~SYM[0] == ~SIZE[~TYPO]'sd0) ? ~SIZE[~TYPO]'sd0 : ~SYM[0] + ~VAR[divider][1]);+ // integerMod end+ warning: 'GHC.Num.Integer.integerMod: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerDivMod#+ kind: Declaration+ type: 'integerDivMod ::+ Integer -> Integer -> (# Integer, Integer #)'+ template: |-+ // integerDivMod begin+ wire ~GENSYM[resultPos][1];+ wire ~GENSYM[dividerNeg][2];+ wire signed [~SIZE[~TYP[0]]:0] ~GENSYM[dividend2][3];+ wire signed [~SIZE[~TYP[0]]:0] ~GENSYM[dividendE][4];+ wire signed [~SIZE[~TYP[0]]:0] ~GENSYM[dividerE][5];+ wire signed [~SIZE[~TYP[0]]:0] ~GENSYM[quot_res][6];+ wire signed [~SIZE[~TYP[0]]-1:0] ~GENSYM[div_res][7];++ assign ~SYM[1] = ~VAR[dividend][0][~SIZE[~TYP[0]]-1] == ~VAR[divider][1][~SIZE[~TYP[0]]-1];+ assign ~SYM[2] = ~VAR[divider][1][~SIZE[~TYP[0]]-1] == 1'b1;+ assign ~SYM[4] = $signed({{~VAR[dividend][0][~SIZE[~TYP[0]]-1]},~VAR[dividend][0]}); // sign extension+ assign ~SYM[5] = $signed({{~VAR[divider][1][~SIZE[~TYP[0]]-1]} ,~VAR[divider][1]} ); // sign extension++ assign ~SYM[3] = ~SYM[1] ? ~SYM[4]+ : (~SYM[2] ? (~SYM[4] - ~SYM[5] - ~SIZE[~TYP[0]]'sd1)+ : (~SYM[4] - ~SYM[5] + ~SIZE[~TYP[0]]'sd1));++ assign ~SYM[6] = ~SYM[3] / ~SYM[5];+ assign ~SYM[7] = $signed(~SYM[6][~SIZE[~TYP[0]]-1:0]);++ wire ~SIGD[~GENSYM[rem_res][8]][0];+ wire ~SIGD[~GENSYM[mod_res][9]][0];+ assign ~SYM[8] = ~VAR[dividend][0] % ~VAR[divider][1];++ // modulo+ assign ~SYM[9] = (~VAR[dividend][0][~SIZE[~TYP[0]]-1] == ~VAR[divider][1][~SIZE[~TYP[0]]-1]) ?+ ~SYM[8] :+ ((~SYM[8] == ~SIZE[~TYP[0]]'sd0) ? ~SIZE[~TYP[0]]'sd0 : ~SYM[8] + ~VAR[divider][1]);++ assign ~RESULT = {~SYM[7],~SYM[9]};+ // integerDivMod end+ warning: 'GHC.Num.Integer.integerDivMod#: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerQuotRem#+ kind: Declaration+ type: 'integerQuotRem+ :: Integer -> Integer -> (# Integer, Integer #)'+ template: |-+ // integerQuotRem begin+ wire ~SIGD[~GENSYM[quot_res][0]][0];+ wire ~SIGD[~GENSYM[rem_res][1]][0];+ assign ~SYM[0] = ~ARG[0] / ~ARG[1];+ assign ~SYM[1] = ~ARG[0] % ~ARG[1];++ assign ~RESULT = {~SYM[0],~SYM[1]};+ // integerQuotRem end+ warning: 'GHC.Num.Integer.integerQuotRem#: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'
− prims/verilog/GHC_Prim.primitives
@@ -1,1507 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Prim.quotRemInt#"- , "kind" : "Declaration"- , "type" : "quotRemInt# :: Int# -> Int# -> (#Int#, Int##)"- , "template" :-"// quotRemInt begin-wire ~SIGD[~GENSYM[quot_res][0]][0];-wire ~SIGD[~GENSYM[rem_res][1]][0];-assign ~SYM[0] = ~ARG[0] / ~ARG[1];-assign ~SYM[1] = ~ARG[0] % ~ARG[1];--assign ~RESULT = {~SYM[0],~SYM[1]};-// quotRemInt end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.quotRemWord#"- , "kind" : "Declaration"- , "type" : "quotRemWord# :: Word# -> Word# -> (#Word#, Word##)"- , "template" :-"// quotRemWord begin-wire ~SIGD[~GENSYM[quot_res][0]][0];-wire ~SIGD[~GENSYM[rem_res][1]][0];-assign ~SYM[0] = ~ARG[0] / ~ARG[1];-assign ~SYM[1] = ~ARG[0] % ~ARG[1];--assign ~RESULT = {~SYM[0],~SYM[1]};-// quotRemWord end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.popCnt8#"- , "kind" : "Declaration"- , "type" : "popCnt8# :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "popCnt8"- , "extension" : "inc"- , "template" :-"// ceiling of log2-function integer ~INCLUDENAME[0]_clog2;- input integer value;- begin- value = value-1;- for (~INCLUDENAME[0]_clog2=0; value>0; ~INCLUDENAME[0]_clog2=~INCLUDENAME[0]_clog2+1)- value = value>>1;- end-endfunction--// given a level and a depth, calculate the corresponding index into the-// intermediate array-function integer ~INCLUDENAME[0]_depth2Index;- input integer levels;- input integer depth;-- ~INCLUDENAME[0]_depth2Index = (2 ** levels) - (2 ** depth);-endfunction"- }- ]- , "template" :-"// popCnt8 begin-localparam ~GENSYM[width][0] = 8;--// depth of the tree-localparam ~GENSYM[levels][2] = ~INCLUDENAME[0]_clog2(~SYM[0]);--wire [~SYM[2]:0] ~GENSYM[intermediate][3] [0:(2*~SYM[0])-2];--// put input into the first half of the intermediate array-genvar ~GENSYM[i][4];-~GENERATE-for (~SYM[4] = 0; ~SYM[4] < ~SYM[0]; ~SYM[4]=~SYM[4]+1) begin : ~GENSYM[mk_array][11]- assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]);-end-~ENDGENERATE--// Create the tree of instantiated components-genvar ~GENSYM[d][6];-genvar ~GENSYM[i][7];-~GENERATE-if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]- for (~SYM[6] = ~SYM[2]; ~SYM[6] > 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]- for (~SYM[7] = 0; ~SYM[7] < (2**(~SYM[6]-1)); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]- assign ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6])+~SYM[7]] =- ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])] +- ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])+1];- end- end-end-~ENDGENERATE--// The last element of the intermediate array holds the result-assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);-// popCnt8 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.popCnt16#"- , "kind" : "Declaration"- , "type" : "popCnt16# :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "popCnt16"- , "extension" : "inc"- , "template" :-"// ceiling of log2-function integer ~INCLUDENAME[0]_clog2;- input integer value;- begin- value = value-1;- for (~INCLUDENAME[0]_clog2=0; value>0; ~INCLUDENAME[0]_clog2=~INCLUDENAME[0]_clog2+1)- value = value>>1;- end-endfunction--// given a level and a depth, calculate the corresponding index into the-// intermediate array-function integer ~INCLUDENAME[0]_depth2Index;- input integer levels;- input integer depth;-- ~INCLUDENAME[0]_depth2Index = (2 ** levels) - (2 ** depth);-endfunction"- }- ]- , "template" :-"// popCnt16 begin-localparam ~GENSYM[width][0] = 16;--// depth of the tree-localparam ~GENSYM[levels][2] = ~INCLUDENAME[0]_clog2(~SYM[0]);--wire [~SYM[2]:0] ~GENSYM[intermediate][3] [0:(2*~SYM[0])-2];--// put input into the first half of the intermediate array-genvar ~GENSYM[i][4];-~GENERATE-for (~SYM[4] = 0; ~SYM[4] < ~SYM[0]; ~SYM[4]=~SYM[4]+1) begin : ~GENSYM[mk_array][11]- assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]);-end-~ENDGENERATE--// Create the tree of instantiated components-genvar ~GENSYM[d][6];-genvar ~GENSYM[i][7];-~GENERATE-if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]- for (~SYM[6] = ~SYM[2]; ~SYM[6] > 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]- for (~SYM[7] = 0; ~SYM[7] < (2**(~SYM[6]-1)); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]- assign ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6])+~SYM[7]] =- ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])] +- ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])+1];- end- end-end-~ENDGENERATE--// The last element of the intermediate array holds the result-assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);-// popCnt16 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.popCnt32#"- , "kind" : "Declaration"- , "type" : "popCnt32# :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "popCnt32"- , "extension" : "inc"- , "template" :-"// ceiling of log2-function integer ~INCLUDENAME[0]_clog2;- input integer value;- begin- value = value-1;- for (~INCLUDENAME[0]_clog2=0; value>0; ~INCLUDENAME[0]_clog2=~INCLUDENAME[0]_clog2+1)- value = value>>1;- end-endfunction--// given a level and a depth, calculate the corresponding index into the-// intermediate array-function integer ~INCLUDENAME[0]_depth2Index;- input integer levels;- input integer depth;-- ~INCLUDENAME[0]_depth2Index = (2 ** levels) - (2 ** depth);-endfunction"- }- ]- , "template" :-"// popCnt32 begin-localparam ~GENSYM[width][0] = 32;--// depth of the tree-localparam ~GENSYM[levels][2] = ~INCLUDENAME[0]_clog2(~SYM[0]);--wire [~SYM[2]:0] ~GENSYM[intermediate][3] [0:(2*~SYM[0])-2];--// put input into the first half of the intermediate array-genvar ~GENSYM[i][4];-~GENERATE-for (~SYM[4] = 0; ~SYM[4] < ~SYM[0]; ~SYM[4]=~SYM[4]+1) begin : ~GENSYM[mk_array][11]- assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]);-end-~ENDGENERATE--// Create the tree of instantiated components-genvar ~GENSYM[d][6];-genvar ~GENSYM[i][7];-~GENERATE-if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]- for (~SYM[6] = ~SYM[2]; ~SYM[6] > 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]- for (~SYM[7] = 0; ~SYM[7] < (2**(~SYM[6]-1)); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]- assign ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6])+~SYM[7]] =- ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])] +- ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])+1];- end- end-end-~ENDGENERATE--// The last element of the intermediate array holds the result-assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);-// popCnt32 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.popCnt64#"- , "kind" : "Declaration"- , "type" : "popCnt64# :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "popCnt64"- , "extension" : "inc"- , "template" :-"// ceiling of log2-function integer ~INCLUDENAME[0]_clog2;- input integer value;- begin- value = value-1;- for (~INCLUDENAME[0]_clog2=0; value>0; ~INCLUDENAME[0]_clog2=~INCLUDENAME[0]_clog2+1)- value = value>>1;- end-endfunction--// given a level and a depth, calculate the corresponding index into the-// intermediate array-function integer ~INCLUDENAME[0]_depth2Index;- input integer levels;- input integer depth;-- ~INCLUDENAME[0]_depth2Index = (2 ** levels) - (2 ** depth);-endfunction"- }- ]- , "template" :-"// popCnt64 begin-localparam ~GENSYM[width][0] = 64;--// depth of the tree-localparam ~GENSYM[levels][2] = ~INCLUDENAME[0]_clog2(~SYM[0]);--wire [~SYM[2]:0] ~GENSYM[intermediate][3] [0:(2*~SYM[0])-2];--// put input into the first half of the intermediate array-genvar ~GENSYM[i][4];-~GENERATE-for (~SYM[4] = 0; ~SYM[4] < ~SYM[0]; ~SYM[4]=~SYM[4]+1) begin : ~GENSYM[mk_array][11]- assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]);-end-~ENDGENERATE--// Create the tree of instantiated components-genvar ~GENSYM[d][6];-genvar ~GENSYM[i][7];-~GENERATE-if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]- for (~SYM[6] = ~SYM[2]; ~SYM[6] > 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]- for (~SYM[7] = 0; ~SYM[7] < (2**(~SYM[6]-1)); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]- assign ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6])+~SYM[7]] =- ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])] +- ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])+1];- end- end-end-~ENDGENERATE--// The last element of the intermediate array holds the result-assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);-// popCnt64 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.popCnt#"- , "kind" : "Declaration"- , "type" : "popCnt# :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "popCnt"- , "extension" : "inc"- , "template" :-"// ceiling of log2-function integer ~INCLUDENAME[0]_clog2;- input integer value;- begin- value = value-1;- for (~INCLUDENAME[0]_clog2=0; value>0; ~INCLUDENAME[0]_clog2=~INCLUDENAME[0]_clog2+1)- value = value>>1;- end-endfunction--// given a level and a depth, calculate the corresponding index into the-// intermediate array-function integer ~INCLUDENAME[0]_depth2Index;- input integer levels;- input integer depth;-- ~INCLUDENAME[0]_depth2Index = (2 ** levels) - (2 ** depth);-endfunction"- }- ]- , "template" :-"// popCnt begin-localparam ~GENSYM[width][0] = ~SIZE[~TYPO];--// depth of the tree-localparam ~GENSYM[levels][2] = ~INCLUDENAME[0]_clog2(~SYM[0]);--wire [~SYM[2]:0] ~GENSYM[intermediate][3] [0:(2*~SYM[0])-2];--// put input into the first half of the intermediate array-genvar ~GENSYM[i][4];-~GENERATE-for (~SYM[4] = 0; ~SYM[4] < ~SYM[0]; ~SYM[4]=~SYM[4]+1) begin : ~GENSYM[mk_array][11]- assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]);-end-~ENDGENERATE--// Create the tree of instantiated components-genvar ~GENSYM[d][6];-genvar ~GENSYM[i][7];-~GENERATE-if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]- for (~SYM[6] = ~SYM[2]; ~SYM[6] > 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]- for (~SYM[7] = 0; ~SYM[7] < (2**(~SYM[6]-1)); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]- assign ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6])+~SYM[7]] =- ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])] +- ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])+1];- end- end-end-~ENDGENERATE--// The last element of the intermediate array holds the result-assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);-// popCnt end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.clz8#"- , "kind" : "Declaration"- , "type" : "clz8 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "enc"- , "extension" : "inc"- , "template" :-"function [1:0] ~INCLUDENAME[0];- input [1:0] a;- case (a)- 2'b00: ~INCLUDENAME[0] = 2'b10;- 2'b01: ~INCLUDENAME[0] = 2'b01;- 2'b10: ~INCLUDENAME[0] = 2'b00;- default: ~INCLUDENAME[0] = 2'b00;- endcase-endfunction"- }- ]- , "template" :-"// clz8 begin-wire [0:7] ~GENSYM[v][1];-assign ~SYM[1] = ~VAR[i][0][7:0];--wire [0:7] ~GENSYM[e][2];-genvar ~GENSYM[n][3];-~GENERATE-for (~SYM[3]=0;~SYM[3]<4;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]- assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);-end-~ENDGENERATE--reg [0:5] ~GENSYM[a][4];-genvar ~GENSYM[i1][5];-~GENERATE-for (~SYM[5]=0;~SYM[5]<2;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage1][6]- localparam n = 2;- wire [3:0] i;- assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:3] ~GENSYM[res][7];-~GENERATE-if (1) begin-localparam n = 3;-wire [5:0] i;-assign i = ~SYM[4][0:5];-always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase-end-end-~ENDGENERATE--assign ~RESULT = $unsigned(~SYM[7]);-// clz8 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.clz16#"- , "kind" : "Declaration"- , "type" : "clz16 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "enc"- , "extension" : "inc"- , "template" :-"function [1:0] ~INCLUDENAME[0];- input [1:0] a;- case (a)- 2'b00: ~INCLUDENAME[0] = 2'b10;- 2'b01: ~INCLUDENAME[0] = 2'b01;- 2'b10: ~INCLUDENAME[0] = 2'b00;- default: ~INCLUDENAME[0] = 2'b00;- endcase-endfunction"- }- ]- , "template" :-"// clz16 begin-wire [0:15] ~GENSYM[v][1];-assign ~SYM[1] = ~VAR[i][0][15:0];--wire [0:15] ~GENSYM[e][2];-genvar ~GENSYM[i][3];-~GENERATE-for (~SYM[3]=0;~SYM[3]<8;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]- assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);-end-~ENDGENERATE--reg [0:11] ~GENSYM[a][4];-genvar ~GENSYM[i1][5];-~GENERATE-for (~SYM[5]=0;~SYM[5]<4;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]- localparam n = 2;- wire [3:0] i;- assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:7] ~GENSYM[b][9];-genvar ~GENSYM[i2][10];-~GENERATE-for (~SYM[10]=0;~SYM[10]<2;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]- localparam n = 3;- wire [5:0] i;- assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:4] ~GENSYM[res][7];-~GENERATE-if (1) begin-localparam n = 4;-wire [7:0] i;-assign i = ~SYM[9][0:7];-always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase-end-end-~ENDGENERATE--assign ~RESULT = $unsigned(~SYM[7]);-// clz16 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.clz32#"- , "kind" : "Declaration"- , "type" : "clz32 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "enc"- , "extension" : "inc"- , "template" :-"function [1:0] ~INCLUDENAME[0];- input [1:0] a;- case (a)- 2'b00: ~INCLUDENAME[0] = 2'b10;- 2'b01: ~INCLUDENAME[0] = 2'b01;- 2'b10: ~INCLUDENAME[0] = 2'b00;- default: ~INCLUDENAME[0] = 2'b00;- endcase-endfunction"- }- ]- , "template" :-"// clz32 begin-wire [0:31] ~GENSYM[v][1];-assign ~SYM[1] = ~VAR[i][0][31:0];--wire [0:31] ~GENSYM[e][2];-genvar ~GENSYM[i][3];-~GENERATE-for (~SYM[3]=0;~SYM[3]<16;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]- assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);-end-~ENDGENERATE--reg [0:23] ~GENSYM[a][4];-genvar ~GENSYM[i1][5];-~GENERATE-for (~SYM[5]=0;~SYM[5]<8;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]- localparam n = 2;- wire [3:0] i;- assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:15] ~GENSYM[b][9];-genvar ~GENSYM[i2][10];-~GENERATE-for (~SYM[10]=0;~SYM[10]<4;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]- localparam n = 3;- wire [5:0] i;- assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:9] ~GENSYM[c][12];-genvar ~GENSYM[i3][13];-~GENERATE-for (~SYM[13]=0;~SYM[13]<2;~SYM[13]=~SYM[13]+1) begin : ~GENSYM[mux_stage3][14]- localparam n = 4;- wire [7:0] i;- assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:5] ~GENSYM[res][7];-~GENERATE-if (1) begin-localparam n = 5;-wire [9:0] i;-assign i = ~SYM[12][0:9];-always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase-end-end-~ENDGENERATE--assign ~RESULT = $unsigned(~SYM[7]);-// clz32 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.clz64#"- , "kind" : "Declaration"- , "type" : "clz64 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "enc"- , "extension" : "inc"- , "template" :-"function [1:0] ~INCLUDENAME[0];- input [1:0] a;- case (a)- 2'b00: ~INCLUDENAME[0] = 2'b10;- 2'b01: ~INCLUDENAME[0] = 2'b01;- 2'b10: ~INCLUDENAME[0] = 2'b00;- default: ~INCLUDENAME[0] = 2'b00;- endcase-endfunction"- }- ]- , "template" :-"// clz64 begin-wire [0:63] ~GENSYM[v][1];-assign ~SYM[1] = ~VAR[i][0][63:0];--wire [0:63] ~GENSYM[e][2];-genvar ~GENSYM[i][3];-~GENERATE-for (~SYM[3]=0;~SYM[3]<32;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]- assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);-end-~ENDGENERATE--reg [0:47] ~GENSYM[a][4];-genvar ~GENSYM[i1][5];-~GENERATE-for (~SYM[5]=0;~SYM[5]<16;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]- localparam n = 2;- wire [3:0] i;- assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:31] ~GENSYM[b][9];-genvar ~GENSYM[i2][10];-~GENERATE-for (~SYM[10]=0;~SYM[10]<8;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]- localparam n = 3;- wire [5:0] i;- assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:19] ~GENSYM[c][12];-genvar ~GENSYM[i3][13];-~GENERATE-for (~SYM[13]=0;~SYM[13]<4;~SYM[13]=~SYM[13]+1) begin : ~GENSYM[mux_stage3][14]- localparam n = 4;- wire [7:0] i;- assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:11] ~GENSYM[d][15];-genvar ~GENSYM[i4][16];-~GENERATE-for (~SYM[16]=0;~SYM[16]<2;~SYM[16]=~SYM[16]+1) begin : ~GENSYM[mux_stage4][17]- localparam n = 5;- wire [9:0] i;- assign i = ~SYM[12][~SYM[16]*10:~SYM[16]*10+9];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:6] ~GENSYM[res][7];-~GENERATE-if (1) begin-localparam n = 6;-wire [11:0] i;-assign i = ~SYM[15][0:11];-always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase-end-end-~ENDGENERATE--assign ~RESULT = $unsigned(~SYM[7]);-// clz64 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.clz#"- , "kind" : "Declaration"- , "type" : "clz :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "enc"- , "extension" : "inc"- , "template" :-"function [1:0] ~INCLUDENAME[0];- input [1:0] a;- case (a)- 2'b00: ~INCLUDENAME[0] = 2'b10;- 2'b01: ~INCLUDENAME[0] = 2'b01;- 2'b10: ~INCLUDENAME[0] = 2'b00;- default: ~INCLUDENAME[0] = 2'b00;- endcase-endfunction"- }- ]- , "template" :-"// clz begin~IF ~IW64 ~THEN-wire [0:63] ~GENSYM[v][1];-assign ~SYM[1] = ~VAR[i][0][63:0];--wire [0:63] ~GENSYM[e][2];-genvar ~GENSYM[i][3];-~GENERATE-for (~SYM[3]=0;~SYM[3]<32;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]- assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);-end-~ENDGENERATE--reg [0:47] ~GENSYM[a][4];-genvar ~GENSYM[i1][5];-~GENERATE-for (~SYM[5]=0;~SYM[5]<16;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]- localparam n = 2;- wire [3:0] i;- assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:31] ~GENSYM[b][9];-genvar ~GENSYM[i2][10];-~GENERATE-for (~SYM[10]=0;~SYM[10]<8;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]- localparam n = 3;- wire [5:0] i;- assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:19] ~GENSYM[c][12];-genvar ~GENSYM[i3][13];-~GENERATE-for (~SYM[13]=0;~SYM[13]<4;~SYM[13]=~SYM[13]+1) begin : ~GENSYM[mux_stage3][14]- localparam n = 4;- wire [7:0] i;- assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:11] ~GENSYM[d][15];-genvar ~GENSYM[i4][16];-~GENERATE-for (~SYM[16]=0;~SYM[16]<2;~SYM[16]=~SYM[16]+1) begin : ~GENSYM[mux_stage4][17]- localparam n = 5;- wire [9:0] i;- assign i = ~SYM[12][~SYM[16]*10:~SYM[16]*10+9];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:6] ~GENSYM[res][7];-~GENERATE-if (1) begin-localparam n = 6;-wire [11:0] i;-assign i = ~SYM[15][0:11];-always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase-end-end-~ENDGENERATE-~ELSE-wire [0:31] ~SYM[1];-assign ~SYM[1] = ~VAR[i][0][31:0];--wire [0:31] ~SYM[2];-genvar ~SYM[3];-~GENERATE-for (~SYM[3]=0;~SYM[3]<16;~SYM[3]=~SYM[3]+1) begin : ~SYM[8]- assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);-end-~ENDGENERATE--reg [0:23] ~SYM[4];-genvar ~SYM[5];-~GENERATE-for (~SYM[5]=0;~SYM[5]<8;~SYM[5]=~SYM[5]+1) begin : ~SYM[6]- localparam n = 2;- wire [3:0] i;- assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:15] ~SYM[9];-genvar ~SYM[10];-~GENERATE-for (~SYM[10]=0;~SYM[10]<4;~SYM[10]=~SYM[10]+1) begin : ~SYM[11]- localparam n = 3;- wire [5:0] i;- assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:9] ~SYM[12];-genvar ~SYM[13];-~GENERATE-for (~SYM[13]=0;~SYM[13]<2;~SYM[13]=~SYM[13]+1) begin : ~SYM[14]- localparam n = 4;- wire [7:0] i;- assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:5] ~SYM[7];-~GENERATE-if (1) begin-localparam n = 5;-wire [9:0] i;-assign i = ~SYM[12][0:9];-always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase-end-end-~ENDGENERATE-~FI-assign ~RESULT = $unsigned(~SYM[7]);-// clz end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ctz8#"- , "kind" : "Declaration"- , "type" : "ctz8 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "enc"- , "extension" : "inc"- , "template" :-"function [1:0] ~INCLUDENAME[0];- input [1:0] a;- case (a)- 2'b00: ~INCLUDENAME[0] = 2'b10;- 2'b01: ~INCLUDENAME[0] = 2'b01;- 2'b10: ~INCLUDENAME[0] = 2'b00;- default: ~INCLUDENAME[0] = 2'b00;- endcase-endfunction"- }- ]- , "template" :-"// ctz8 begin-wire [0:7] ~GENSYM[v][1];-genvar ~GENSYM[k][18];-~GENERATE-for (~SYM[18]=0;~SYM[18]<8;~SYM[18]=~SYM[18]+1) begin : ~GENSYM[reverse][19]- assign ~SYM[1][~SYM[18]] = ~ARG[0][~SYM[18]];-end-~ENDGENERATE--wire [0:7] ~GENSYM[e][2];-genvar ~GENSYM[i][3];-~GENERATE-for (~SYM[3]=0;~SYM[3]<4;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]- assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);-end-~ENDGENERATE--reg [0:5] ~GENSYM[a][4];-genvar ~GENSYM[i1][5];-~GENERATE-for (~SYM[5]=0;~SYM[5]<2;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]- localparam n = 2;- wire [3:0] i;- assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:3] ~GENSYM[res][7];-~GENERATE-if (1) begin-localparam n = 3;-wire [5:0] i;-assign i = ~SYM[4][0:5];-always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase-end-end-~ENDGENERATE--assign ~RESULT = $unsigned(~SYM[7]);-// ctz8 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ctz16#"- , "kind" : "Declaration"- , "type" : "ctz16 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "enc"- , "extension" : "inc"- , "template" :-"function [1:0] ~INCLUDENAME[0];- input [1:0] a;- case (a)- 2'b00: ~INCLUDENAME[0] = 2'b10;- 2'b01: ~INCLUDENAME[0] = 2'b01;- 2'b10: ~INCLUDENAME[0] = 2'b00;- default: ~INCLUDENAME[0] = 2'b00;- endcase-endfunction"- }- ]- , "template" :-"// ctz16 begin-wire [0:15] ~GENSYM[v][1];-genvar ~GENSYM[k][18];-~GENERATE-for (~SYM[18]=0;~SYM[18]<16;~SYM[18]=~SYM[18]+1) begin : ~GENSYM[reverse][19]- assign ~SYM[1][~SYM[18]] = ~ARG[0][~SYM[18]];-end-~ENDGENERATE--wire [0:15] ~GENSYM[e][2];-genvar ~GENSYM[i][3];-~GENERATE-for (~SYM[3]=0;~SYM[3]<8;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]- assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);-end-~ENDGENERATE--reg [0:11] ~GENSYM[a][4];-genvar ~GENSYM[i1][5];-~GENERATE-for (~SYM[5]=0;~SYM[5]<4;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]- localparam n = 2;- wire [3:0] i;- assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:7] ~GENSYM[b][9];-genvar ~GENSYM[i2][10];-~GENERATE-for (~SYM[10]=0;~SYM[10]<2;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]- localparam n = 3;- wire [5:0] i;- assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:4] ~GENSYM[res][7];-~GENERATE-if (1) begin-localparam n = 4;-wire [7:0] i;-assign i = ~SYM[9][0:7];-always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase-end-end-~ENDGENERATE--assign ~RESULT = $unsigned(~SYM[7]);-// ctz16 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ctz32#"- , "kind" : "Declaration"- , "type" : "ctz32 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "enc"- , "extension" : "inc"- , "template" :-"function [1:0] ~INCLUDENAME[0];- input [1:0] a;- case (a)- 2'b00: ~INCLUDENAME[0] = 2'b10;- 2'b01: ~INCLUDENAME[0] = 2'b01;- 2'b10: ~INCLUDENAME[0] = 2'b00;- default: ~INCLUDENAME[0] = 2'b00;- endcase-endfunction"- }- ]- , "template" :-"// ctz32 begin-wire [0:31] ~GENSYM[v][1];-genvar ~GENSYM[k][18];-~GENERATE-for (~SYM[18]=0;~SYM[18]<32;~SYM[18]=~SYM[18]+1) begin : ~GENSYM[reverse][19]- assign ~SYM[1][~SYM[18]] = ~ARG[0][~SYM[18]];-end-~ENDGENERATE--wire [0:31] ~GENSYM[e][2];-genvar ~GENSYM[i][3];-~GENERATE-for (~SYM[3]=0;~SYM[3]<16;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]- assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);-end-~ENDGENERATE--reg [0:23] ~GENSYM[a][4];-genvar ~GENSYM[i1][5];-~GENERATE-for (~SYM[5]=0;~SYM[5]<8;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]- localparam n = 2;- wire [3:0] i;- assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:15] ~GENSYM[b][9];-genvar ~GENSYM[i2][10];-~GENERATE-for (~SYM[10]=0;~SYM[10]<4;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]- localparam n = 3;- wire [5:0] i;- assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:9] ~GENSYM[c][12];-genvar ~GENSYM[i3][13];-~GENERATE-for (~SYM[13]=0;~SYM[13]<2;~SYM[13]=~SYM[13]+1) begin : ~GENSYM[mux_stage3][14]- localparam n = 4;- wire [7:0] i;- assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:5] ~GENSYM[res][7];-~GENERATE-if (1) begin-localparam n = 5;-wire [9:0] i;-assign i = ~SYM[12][0:9];-always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase-end-end-~ENDGENERATE--assign ~RESULT = $unsigned(~SYM[7]);-// ctz32 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ctz64#"- , "kind" : "Declaration"- , "type" : "ctz64 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "enc"- , "extension" : "inc"- , "template" :-"function [1:0] ~INCLUDENAME[0];- input [1:0] a;- case (a)- 2'b00: ~INCLUDENAME[0] = 2'b10;- 2'b01: ~INCLUDENAME[0] = 2'b01;- 2'b10: ~INCLUDENAME[0] = 2'b00;- default: ~INCLUDENAME[0] = 2'b00;- endcase-endfunction"- }- ]- , "template" :-"// ctz64 begin-wire [0:63] ~GENSYM[v][1];-genvar ~GENSYM[k][18];-~GENERATE-for (~SYM[18]=0;~SYM[18]<64;~SYM[18]=~SYM[18]+1) begin : ~GENSYM[reverse][19]- assign ~SYM[1][~SYM[18]] = ~ARG[0][~SYM[18]];-end-~ENDGENERATE--wire [0:63] ~GENSYM[e][2];-genvar ~GENSYM[i][3];-~GENERATE-for (~SYM[3]=0;~SYM[3]<32;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]- assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);-end-~ENDGENERATE--reg [0:47] a;-genvar ~GENSYM[i1][5];-~GENERATE-for (~SYM[5]=0;~SYM[5]<16;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]- localparam n = 2;- wire [3:0] i;- assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:31] ~GENSYM[b][9];-genvar ~GENSYM[i2][10];-~GENERATE-for (~SYM[10]=0;~SYM[10]<8;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]- localparam n = 3;- wire [5:0] i;- assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:19] ~GENSYM[c][12];-genvar ~GENSYM[i3][13];-~GENERATE-for (~SYM[13]=0;~SYM[13]<4;~SYM[13]=~SYM[13]+1) begin : ~GENSYM[mux_stage3][14]- localparam n = 4;- wire [7:0] i;- assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:11] ~GENSYM[d][15];-genvar ~GENSYM[i4][16];-~GENERATE-for (~SYM[16]=0;~SYM[16]<2;~SYM[16]=~SYM[16]+1) begin : ~GENSYM[mux_stage4][17]- localparam n = 5;- wire [9:0] i;- assign i = ~SYM[12][~SYM[16]*10:~SYM[16]*10+9];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:6] ~GENSYM[res][7];-~GENERATE-if (1) begin-localparam n = 6;-wire [11:0] i;-assign i = ~SYM[15][0:11];-always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase-end-end-~ENDGENERATE--assign ~RESULT = $unsigned(~SYM[7]);-// ctz64 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ctz#"- , "kind" : "Declaration"- , "type" : "ctz :: Word# -> Word#"- , "imports" : ["~INCLUDENAME[0].inc"]- , "includes" :- [ { "name" : "enc"- , "extension" : "inc"- , "template" :-"function [1:0] ~INCLUDENAME[0];- input [1:0] a;- case (a)- 2'b00: ~INCLUDENAME[0] = 2'b10;- 2'b01: ~INCLUDENAME[0] = 2'b01;- 2'b10: ~INCLUDENAME[0] = 2'b00;- default: ~INCLUDENAME[0] = 2'b00;- endcase-endfunction"- }- ]- , "template" :-"// ctz begin~IF ~IW64 ~THEN-wire [0:63] ~GENSYM[v][1];-genvar ~GENSYM[k][18];-~GENERATE-for (~SYM[18]=0;~SYM[18]<64;~SYM[18]=~SYM[18]+1) begin : ~GENSYM[reverse][19]- assign ~SYM[1][~SYM[18]] = ~ARG[0][~SYM[18]];-end-~ENDGENERATE--wire [0:63] ~GENSYM[e][2];-genvar ~GENSYM[i][3];-~GENERATE-for (~SYM[3]=0;~SYM[3]<32;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]- assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);-end-~ENDGENERATE--reg [0:47] ~GENSYM[a][4];-genvar ~GENSYM[i1][5];-~GENERATE-for (~SYM[5]=0;~SYM[5]<16;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]- localparam n = 2;- wire [3:0] i;- assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:31] ~GENSYM[b][9];-genvar ~GENSYM[i2][10];-~GENERATE-for (~SYM[10]=0;~SYM[10]<8;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]- localparam n = 3;- wire [5:0] i;- assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:19] ~GENSYM[c][12];-genvar ~GENSYM[i3][13];-~GENERATE-for (~SYM[13]=0;~SYM[13]<4;~SYM[13]=~SYM[13]+1) begin : ~GENSYM[mux_stage3][14]- localparam n = 4;- wire [7:0] i;- assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:11] ~GENSYM[d][15];-genvar ~GENSYM[i4][16];-~GENERATE-for (~SYM[16]=0;~SYM[16]<2;~SYM[16]=~SYM[16]+1) begin : ~GENSYM[mux_stage4][17]- localparam n = 5;- wire [9:0] i;- assign i = ~SYM[12][~SYM[16]*10:~SYM[16]*10+9];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:6] ~GENSYM[res][7];-~GENERATE-if (1) begin-localparam n = 6;-wire [11:0] i;-assign i = ~SYM[15][0:11];-always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase-end-end-~ENDGENERATE-~ELSE-wire [0:31] ~SYM[1];-genvar ~SYM[18];-~GENERATE-for (~SYM[18]=0;~SYM[18]<32;~SYM[18]=~SYM[18]+1) begin : ~SYM[19]- assign ~SYM[1][~SYM[18]] = ~ARG[0][~SYM[18]];-end-~ENDGENERATE--wire [0:31] ~SYM[2];-genvar ~SYM[3];-~GENERATE-for (~SYM[3]=0;~SYM[3]<16;~SYM[3]=~SYM[3]+1) begin : ~SYM[8]- assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);-end-~ENDGENERATE--reg [0:23] ~SYM[4];-genvar ~SYM[5];-~GENERATE-for (~SYM[5]=0;~SYM[5]<8;~SYM[5]=~SYM[5]+1) begin : ~SYM[6]- localparam n = 2;- wire [3:0] i;- assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:15] ~SYM[9];-genvar ~SYM[10];-~GENERATE-for (~SYM[10]=0;~SYM[10]<4;~SYM[10]=~SYM[10]+1) begin : ~SYM[11]- localparam n = 3;- wire [5:0] i;- assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:9] ~SYM[12];-genvar ~SYM[13];-~GENERATE-for (~SYM[13]=0;~SYM[13]<2;~SYM[13]=~SYM[13]+1) begin : ~SYM[14]- localparam n = 4;- wire [7:0] i;- assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];- always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase- end-end-~ENDGENERATE--reg [0:5] ~SYM[7];-~GENERATE-if (1) begin-localparam n = 5;-wire [9:0] i;-assign i = ~SYM[12][0:9];-always @(*) begin- case (i[n-1+n])- 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};- default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};- endcase-end-end-~ENDGENERATE-~FI-assign ~RESULT = $unsigned(~SYM[7]);-// ctz end"- }- }-]
+ prims/verilog/GHC_Prim.primitives.yaml view
@@ -0,0 +1,1474 @@+- BlackBox:+ name: GHC.Prim.quotRemInt#+ kind: Declaration+ type: 'quotRemInt# ::+ Int# -> Int# -> (#Int#, Int##)'+ template: |-+ // quotRemInt begin+ wire ~SIGD[~GENSYM[quot_res][0]][0];+ wire ~SIGD[~GENSYM[rem_res][1]][0];+ assign ~SYM[0] = ~ARG[0] / ~ARG[1];+ assign ~SYM[1] = ~ARG[0] % ~ARG[1];++ assign ~RESULT = {~SYM[0],~SYM[1]};+ // quotRemInt end+- BlackBox:+ name: GHC.Prim.quotRemWord#+ kind: Declaration+ type: 'quotRemWord# ::+ Word# -> Word# -> (#Word#, Word##)'+ template: |-+ // quotRemWord begin+ wire ~SIGD[~GENSYM[quot_res][0]][0];+ wire ~SIGD[~GENSYM[rem_res][1]][0];+ assign ~SYM[0] = ~ARG[0] / ~ARG[1];+ assign ~SYM[1] = ~ARG[0] % ~ARG[1];++ assign ~RESULT = {~SYM[0],~SYM[1]};+ // quotRemWord end+- BlackBox:+ name: GHC.Prim.popCnt8#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: popCnt8+ extension: inc+ template: |-+ // ceiling of log2+ function integer ~INCLUDENAME[0]_clog2;+ input integer value;+ begin+ value = value-1;+ for (~INCLUDENAME[0]_clog2=0; value>0; ~INCLUDENAME[0]_clog2=~INCLUDENAME[0]_clog2+1)+ value = value>>1;+ end+ endfunction++ // given a level and a depth, calculate the corresponding index into the+ // intermediate array+ function integer ~INCLUDENAME[0]_depth2Index;+ input integer levels;+ input integer depth;++ ~INCLUDENAME[0]_depth2Index = (2 ** levels) - (2 ** depth);+ endfunction+ kind: Declaration+ type: 'popCnt8# :: Word#+ -> Word#'+ template: |-+ // popCnt8 begin+ localparam ~GENSYM[width][0] = 8;++ // depth of the tree+ localparam ~GENSYM[levels][2] = ~INCLUDENAME[0]_clog2(~SYM[0]);++ wire [~SYM[2]:0] ~GENSYM[intermediate][3] [0:(2*~SYM[0])-2];++ // put input into the first half of the intermediate array+ genvar ~GENSYM[i][4];+ ~GENERATE+ for (~SYM[4] = 0; ~SYM[4] < ~SYM[0]; ~SYM[4]=~SYM[4]+1) begin : ~GENSYM[mk_array][11]+ assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]);+ end+ ~ENDGENERATE++ // Create the tree of instantiated components+ genvar ~GENSYM[d][6];+ genvar ~GENSYM[i][7];+ ~GENERATE+ if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]+ for (~SYM[6] = ~SYM[2]; ~SYM[6] > 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]+ for (~SYM[7] = 0; ~SYM[7] < (2**(~SYM[6]-1)); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]+ assign ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6])+~SYM[7]] =+ ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])] ++ ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])+1];+ end+ end+ end+ ~ENDGENERATE++ // The last element of the intermediate array holds the result+ assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);+ // popCnt8 end+- BlackBox:+ name: GHC.Prim.popCnt16#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: popCnt16+ extension: inc+ template: |-+ // ceiling of log2+ function integer ~INCLUDENAME[0]_clog2;+ input integer value;+ begin+ value = value-1;+ for (~INCLUDENAME[0]_clog2=0; value>0; ~INCLUDENAME[0]_clog2=~INCLUDENAME[0]_clog2+1)+ value = value>>1;+ end+ endfunction++ // given a level and a depth, calculate the corresponding index into the+ // intermediate array+ function integer ~INCLUDENAME[0]_depth2Index;+ input integer levels;+ input integer depth;++ ~INCLUDENAME[0]_depth2Index = (2 ** levels) - (2 ** depth);+ endfunction+ kind: Declaration+ type: 'popCnt16# :: Word#+ -> Word#'+ template: |-+ // popCnt16 begin+ localparam ~GENSYM[width][0] = 16;++ // depth of the tree+ localparam ~GENSYM[levels][2] = ~INCLUDENAME[0]_clog2(~SYM[0]);++ wire [~SYM[2]:0] ~GENSYM[intermediate][3] [0:(2*~SYM[0])-2];++ // put input into the first half of the intermediate array+ genvar ~GENSYM[i][4];+ ~GENERATE+ for (~SYM[4] = 0; ~SYM[4] < ~SYM[0]; ~SYM[4]=~SYM[4]+1) begin : ~GENSYM[mk_array][11]+ assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]);+ end+ ~ENDGENERATE++ // Create the tree of instantiated components+ genvar ~GENSYM[d][6];+ genvar ~GENSYM[i][7];+ ~GENERATE+ if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]+ for (~SYM[6] = ~SYM[2]; ~SYM[6] > 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]+ for (~SYM[7] = 0; ~SYM[7] < (2**(~SYM[6]-1)); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]+ assign ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6])+~SYM[7]] =+ ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])] ++ ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])+1];+ end+ end+ end+ ~ENDGENERATE++ // The last element of the intermediate array holds the result+ assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);+ // popCnt16 end+- BlackBox:+ name: GHC.Prim.popCnt32#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: popCnt32+ extension: inc+ template: |-+ // ceiling of log2+ function integer ~INCLUDENAME[0]_clog2;+ input integer value;+ begin+ value = value-1;+ for (~INCLUDENAME[0]_clog2=0; value>0; ~INCLUDENAME[0]_clog2=~INCLUDENAME[0]_clog2+1)+ value = value>>1;+ end+ endfunction++ // given a level and a depth, calculate the corresponding index into the+ // intermediate array+ function integer ~INCLUDENAME[0]_depth2Index;+ input integer levels;+ input integer depth;++ ~INCLUDENAME[0]_depth2Index = (2 ** levels) - (2 ** depth);+ endfunction+ kind: Declaration+ type: 'popCnt32# :: Word#+ -> Word#'+ template: |-+ // popCnt32 begin+ localparam ~GENSYM[width][0] = 32;++ // depth of the tree+ localparam ~GENSYM[levels][2] = ~INCLUDENAME[0]_clog2(~SYM[0]);++ wire [~SYM[2]:0] ~GENSYM[intermediate][3] [0:(2*~SYM[0])-2];++ // put input into the first half of the intermediate array+ genvar ~GENSYM[i][4];+ ~GENERATE+ for (~SYM[4] = 0; ~SYM[4] < ~SYM[0]; ~SYM[4]=~SYM[4]+1) begin : ~GENSYM[mk_array][11]+ assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]);+ end+ ~ENDGENERATE++ // Create the tree of instantiated components+ genvar ~GENSYM[d][6];+ genvar ~GENSYM[i][7];+ ~GENERATE+ if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]+ for (~SYM[6] = ~SYM[2]; ~SYM[6] > 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]+ for (~SYM[7] = 0; ~SYM[7] < (2**(~SYM[6]-1)); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]+ assign ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6])+~SYM[7]] =+ ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])] ++ ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])+1];+ end+ end+ end+ ~ENDGENERATE++ // The last element of the intermediate array holds the result+ assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);+ // popCnt32 end+- BlackBox:+ name: GHC.Prim.popCnt64#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: popCnt64+ extension: inc+ template: |-+ // ceiling of log2+ function integer ~INCLUDENAME[0]_clog2;+ input integer value;+ begin+ value = value-1;+ for (~INCLUDENAME[0]_clog2=0; value>0; ~INCLUDENAME[0]_clog2=~INCLUDENAME[0]_clog2+1)+ value = value>>1;+ end+ endfunction++ // given a level and a depth, calculate the corresponding index into the+ // intermediate array+ function integer ~INCLUDENAME[0]_depth2Index;+ input integer levels;+ input integer depth;++ ~INCLUDENAME[0]_depth2Index = (2 ** levels) - (2 ** depth);+ endfunction+ kind: Declaration+ type: 'popCnt64# :: Word#+ -> Word#'+ template: |-+ // popCnt64 begin+ localparam ~GENSYM[width][0] = 64;++ // depth of the tree+ localparam ~GENSYM[levels][2] = ~INCLUDENAME[0]_clog2(~SYM[0]);++ wire [~SYM[2]:0] ~GENSYM[intermediate][3] [0:(2*~SYM[0])-2];++ // put input into the first half of the intermediate array+ genvar ~GENSYM[i][4];+ ~GENERATE+ for (~SYM[4] = 0; ~SYM[4] < ~SYM[0]; ~SYM[4]=~SYM[4]+1) begin : ~GENSYM[mk_array][11]+ assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]);+ end+ ~ENDGENERATE++ // Create the tree of instantiated components+ genvar ~GENSYM[d][6];+ genvar ~GENSYM[i][7];+ ~GENERATE+ if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]+ for (~SYM[6] = ~SYM[2]; ~SYM[6] > 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]+ for (~SYM[7] = 0; ~SYM[7] < (2**(~SYM[6]-1)); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]+ assign ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6])+~SYM[7]] =+ ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])] ++ ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])+1];+ end+ end+ end+ ~ENDGENERATE++ // The last element of the intermediate array holds the result+ assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);+ // popCnt64 end+- BlackBox:+ name: GHC.Prim.popCnt#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: popCnt+ extension: inc+ template: |-+ // ceiling of log2+ function integer ~INCLUDENAME[0]_clog2;+ input integer value;+ begin+ value = value-1;+ for (~INCLUDENAME[0]_clog2=0; value>0; ~INCLUDENAME[0]_clog2=~INCLUDENAME[0]_clog2+1)+ value = value>>1;+ end+ endfunction++ // given a level and a depth, calculate the corresponding index into the+ // intermediate array+ function integer ~INCLUDENAME[0]_depth2Index;+ input integer levels;+ input integer depth;++ ~INCLUDENAME[0]_depth2Index = (2 ** levels) - (2 ** depth);+ endfunction+ kind: Declaration+ type: 'popCnt# :: Word#+ -> Word#'+ template: |-+ // popCnt begin+ localparam ~GENSYM[width][0] = ~SIZE[~TYPO];++ // depth of the tree+ localparam ~GENSYM[levels][2] = ~INCLUDENAME[0]_clog2(~SYM[0]);++ wire [~SYM[2]:0] ~GENSYM[intermediate][3] [0:(2*~SYM[0])-2];++ // put input into the first half of the intermediate array+ genvar ~GENSYM[i][4];+ ~GENERATE+ for (~SYM[4] = 0; ~SYM[4] < ~SYM[0]; ~SYM[4]=~SYM[4]+1) begin : ~GENSYM[mk_array][11]+ assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]);+ end+ ~ENDGENERATE++ // Create the tree of instantiated components+ genvar ~GENSYM[d][6];+ genvar ~GENSYM[i][7];+ ~GENERATE+ if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]+ for (~SYM[6] = ~SYM[2]; ~SYM[6] > 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]+ for (~SYM[7] = 0; ~SYM[7] < (2**(~SYM[6]-1)); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]+ assign ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6])+~SYM[7]] =+ ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])] ++ ~SYM[3][~INCLUDENAME[0]_depth2Index(~SYM[2]+1,~SYM[6]+1)+(2*~SYM[7])+1];+ end+ end+ end+ ~ENDGENERATE++ // The last element of the intermediate array holds the result+ assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);+ // popCnt end+- BlackBox:+ name: GHC.Prim.clz8#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: enc+ extension: inc+ template: |-+ function [1:0] ~INCLUDENAME[0];+ input [1:0] a;+ case (a)+ 2'b00: ~INCLUDENAME[0] = 2'b10;+ 2'b01: ~INCLUDENAME[0] = 2'b01;+ 2'b10: ~INCLUDENAME[0] = 2'b00;+ default: ~INCLUDENAME[0] = 2'b00;+ endcase+ endfunction+ kind: Declaration+ type: 'clz8 :: Word# ->+ Word#'+ template: |-+ // clz8 begin+ wire [0:7] ~GENSYM[v][1];+ assign ~SYM[1] = ~VAR[i][0][7:0];++ wire [0:7] ~GENSYM[e][2];+ genvar ~GENSYM[n][3];+ ~GENERATE+ for (~SYM[3]=0;~SYM[3]<4;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ end+ ~ENDGENERATE++ reg [0:5] ~GENSYM[a][4];+ genvar ~GENSYM[i1][5];+ ~GENERATE+ for (~SYM[5]=0;~SYM[5]<2;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage1][6]+ localparam n = 2;+ wire [3:0] i;+ assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:3] ~GENSYM[res][7];+ ~GENERATE+ if (1) begin+ localparam n = 3;+ wire [5:0] i;+ assign i = ~SYM[4][0:5];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ assign ~RESULT = $unsigned(~SYM[7]);+ // clz8 end+- BlackBox:+ name: GHC.Prim.clz16#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: enc+ extension: inc+ template: |-+ function [1:0] ~INCLUDENAME[0];+ input [1:0] a;+ case (a)+ 2'b00: ~INCLUDENAME[0] = 2'b10;+ 2'b01: ~INCLUDENAME[0] = 2'b01;+ 2'b10: ~INCLUDENAME[0] = 2'b00;+ default: ~INCLUDENAME[0] = 2'b00;+ endcase+ endfunction+ kind: Declaration+ type: 'clz16 :: Word#+ -> Word#'+ template: |-+ // clz16 begin+ wire [0:15] ~GENSYM[v][1];+ assign ~SYM[1] = ~VAR[i][0][15:0];++ wire [0:15] ~GENSYM[e][2];+ genvar ~GENSYM[i][3];+ ~GENERATE+ for (~SYM[3]=0;~SYM[3]<8;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ end+ ~ENDGENERATE++ reg [0:11] ~GENSYM[a][4];+ genvar ~GENSYM[i1][5];+ ~GENERATE+ for (~SYM[5]=0;~SYM[5]<4;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]+ localparam n = 2;+ wire [3:0] i;+ assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:7] ~GENSYM[b][9];+ genvar ~GENSYM[i2][10];+ ~GENERATE+ for (~SYM[10]=0;~SYM[10]<2;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]+ localparam n = 3;+ wire [5:0] i;+ assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:4] ~GENSYM[res][7];+ ~GENERATE+ if (1) begin+ localparam n = 4;+ wire [7:0] i;+ assign i = ~SYM[9][0:7];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ assign ~RESULT = $unsigned(~SYM[7]);+ // clz16 end+- BlackBox:+ name: GHC.Prim.clz32#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: enc+ extension: inc+ template: |-+ function [1:0] ~INCLUDENAME[0];+ input [1:0] a;+ case (a)+ 2'b00: ~INCLUDENAME[0] = 2'b10;+ 2'b01: ~INCLUDENAME[0] = 2'b01;+ 2'b10: ~INCLUDENAME[0] = 2'b00;+ default: ~INCLUDENAME[0] = 2'b00;+ endcase+ endfunction+ kind: Declaration+ type: 'clz32 :: Word#+ -> Word#'+ template: |-+ // clz32 begin+ wire [0:31] ~GENSYM[v][1];+ assign ~SYM[1] = ~VAR[i][0][31:0];++ wire [0:31] ~GENSYM[e][2];+ genvar ~GENSYM[i][3];+ ~GENERATE+ for (~SYM[3]=0;~SYM[3]<16;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ end+ ~ENDGENERATE++ reg [0:23] ~GENSYM[a][4];+ genvar ~GENSYM[i1][5];+ ~GENERATE+ for (~SYM[5]=0;~SYM[5]<8;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]+ localparam n = 2;+ wire [3:0] i;+ assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:15] ~GENSYM[b][9];+ genvar ~GENSYM[i2][10];+ ~GENERATE+ for (~SYM[10]=0;~SYM[10]<4;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]+ localparam n = 3;+ wire [5:0] i;+ assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:9] ~GENSYM[c][12];+ genvar ~GENSYM[i3][13];+ ~GENERATE+ for (~SYM[13]=0;~SYM[13]<2;~SYM[13]=~SYM[13]+1) begin : ~GENSYM[mux_stage3][14]+ localparam n = 4;+ wire [7:0] i;+ assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:5] ~GENSYM[res][7];+ ~GENERATE+ if (1) begin+ localparam n = 5;+ wire [9:0] i;+ assign i = ~SYM[12][0:9];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ assign ~RESULT = $unsigned(~SYM[7]);+ // clz32 end+- BlackBox:+ name: GHC.Prim.clz64#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: enc+ extension: inc+ template: |-+ function [1:0] ~INCLUDENAME[0];+ input [1:0] a;+ case (a)+ 2'b00: ~INCLUDENAME[0] = 2'b10;+ 2'b01: ~INCLUDENAME[0] = 2'b01;+ 2'b10: ~INCLUDENAME[0] = 2'b00;+ default: ~INCLUDENAME[0] = 2'b00;+ endcase+ endfunction+ kind: Declaration+ type: 'clz64 :: Word#+ -> Word#'+ template: |-+ // clz64 begin+ wire [0:63] ~GENSYM[v][1];+ assign ~SYM[1] = ~VAR[i][0][63:0];++ wire [0:63] ~GENSYM[e][2];+ genvar ~GENSYM[i][3];+ ~GENERATE+ for (~SYM[3]=0;~SYM[3]<32;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ end+ ~ENDGENERATE++ reg [0:47] ~GENSYM[a][4];+ genvar ~GENSYM[i1][5];+ ~GENERATE+ for (~SYM[5]=0;~SYM[5]<16;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]+ localparam n = 2;+ wire [3:0] i;+ assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:31] ~GENSYM[b][9];+ genvar ~GENSYM[i2][10];+ ~GENERATE+ for (~SYM[10]=0;~SYM[10]<8;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]+ localparam n = 3;+ wire [5:0] i;+ assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:19] ~GENSYM[c][12];+ genvar ~GENSYM[i3][13];+ ~GENERATE+ for (~SYM[13]=0;~SYM[13]<4;~SYM[13]=~SYM[13]+1) begin : ~GENSYM[mux_stage3][14]+ localparam n = 4;+ wire [7:0] i;+ assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:11] ~GENSYM[d][15];+ genvar ~GENSYM[i4][16];+ ~GENERATE+ for (~SYM[16]=0;~SYM[16]<2;~SYM[16]=~SYM[16]+1) begin : ~GENSYM[mux_stage4][17]+ localparam n = 5;+ wire [9:0] i;+ assign i = ~SYM[12][~SYM[16]*10:~SYM[16]*10+9];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:6] ~GENSYM[res][7];+ ~GENERATE+ if (1) begin+ localparam n = 6;+ wire [11:0] i;+ assign i = ~SYM[15][0:11];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ assign ~RESULT = $unsigned(~SYM[7]);+ // clz64 end+- BlackBox:+ name: GHC.Prim.clz#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: enc+ extension: inc+ template: |-+ function [1:0] ~INCLUDENAME[0];+ input [1:0] a;+ case (a)+ 2'b00: ~INCLUDENAME[0] = 2'b10;+ 2'b01: ~INCLUDENAME[0] = 2'b01;+ 2'b10: ~INCLUDENAME[0] = 2'b00;+ default: ~INCLUDENAME[0] = 2'b00;+ endcase+ endfunction+ kind: Declaration+ type: 'clz :: Word# ->+ Word#'+ template: |-+ // clz begin~IF ~IW64 ~THEN+ wire [0:63] ~GENSYM[v][1];+ assign ~SYM[1] = ~VAR[i][0][63:0];++ wire [0:63] ~GENSYM[e][2];+ genvar ~GENSYM[i][3];+ ~GENERATE+ for (~SYM[3]=0;~SYM[3]<32;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ end+ ~ENDGENERATE++ reg [0:47] ~GENSYM[a][4];+ genvar ~GENSYM[i1][5];+ ~GENERATE+ for (~SYM[5]=0;~SYM[5]<16;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]+ localparam n = 2;+ wire [3:0] i;+ assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:31] ~GENSYM[b][9];+ genvar ~GENSYM[i2][10];+ ~GENERATE+ for (~SYM[10]=0;~SYM[10]<8;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]+ localparam n = 3;+ wire [5:0] i;+ assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:19] ~GENSYM[c][12];+ genvar ~GENSYM[i3][13];+ ~GENERATE+ for (~SYM[13]=0;~SYM[13]<4;~SYM[13]=~SYM[13]+1) begin : ~GENSYM[mux_stage3][14]+ localparam n = 4;+ wire [7:0] i;+ assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:11] ~GENSYM[d][15];+ genvar ~GENSYM[i4][16];+ ~GENERATE+ for (~SYM[16]=0;~SYM[16]<2;~SYM[16]=~SYM[16]+1) begin : ~GENSYM[mux_stage4][17]+ localparam n = 5;+ wire [9:0] i;+ assign i = ~SYM[12][~SYM[16]*10:~SYM[16]*10+9];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:6] ~GENSYM[res][7];+ ~GENERATE+ if (1) begin+ localparam n = 6;+ wire [11:0] i;+ assign i = ~SYM[15][0:11];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE+ ~ELSE+ wire [0:31] ~SYM[1];+ assign ~SYM[1] = ~VAR[i][0][31:0];++ wire [0:31] ~SYM[2];+ genvar ~SYM[3];+ ~GENERATE+ for (~SYM[3]=0;~SYM[3]<16;~SYM[3]=~SYM[3]+1) begin : ~SYM[8]+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ end+ ~ENDGENERATE++ reg [0:23] ~SYM[4];+ genvar ~SYM[5];+ ~GENERATE+ for (~SYM[5]=0;~SYM[5]<8;~SYM[5]=~SYM[5]+1) begin : ~SYM[6]+ localparam n = 2;+ wire [3:0] i;+ assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:15] ~SYM[9];+ genvar ~SYM[10];+ ~GENERATE+ for (~SYM[10]=0;~SYM[10]<4;~SYM[10]=~SYM[10]+1) begin : ~SYM[11]+ localparam n = 3;+ wire [5:0] i;+ assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:9] ~SYM[12];+ genvar ~SYM[13];+ ~GENERATE+ for (~SYM[13]=0;~SYM[13]<2;~SYM[13]=~SYM[13]+1) begin : ~SYM[14]+ localparam n = 4;+ wire [7:0] i;+ assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:5] ~SYM[7];+ ~GENERATE+ if (1) begin+ localparam n = 5;+ wire [9:0] i;+ assign i = ~SYM[12][0:9];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE+ ~FI+ assign ~RESULT = $unsigned(~SYM[7]);+ // clz end+- BlackBox:+ name: GHC.Prim.ctz8#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: enc+ extension: inc+ template: |-+ function [1:0] ~INCLUDENAME[0];+ input [1:0] a;+ case (a)+ 2'b00: ~INCLUDENAME[0] = 2'b10;+ 2'b01: ~INCLUDENAME[0] = 2'b01;+ 2'b10: ~INCLUDENAME[0] = 2'b00;+ default: ~INCLUDENAME[0] = 2'b00;+ endcase+ endfunction+ kind: Declaration+ type: 'ctz8 :: Word# ->+ Word#'+ template: |-+ // ctz8 begin+ wire [0:7] ~GENSYM[v][1];+ genvar ~GENSYM[k][18];+ ~GENERATE+ for (~SYM[18]=0;~SYM[18]<8;~SYM[18]=~SYM[18]+1) begin : ~GENSYM[reverse][19]+ assign ~SYM[1][~SYM[18]] = ~ARG[0][~SYM[18]];+ end+ ~ENDGENERATE++ wire [0:7] ~GENSYM[e][2];+ genvar ~GENSYM[i][3];+ ~GENERATE+ for (~SYM[3]=0;~SYM[3]<4;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ end+ ~ENDGENERATE++ reg [0:5] ~GENSYM[a][4];+ genvar ~GENSYM[i1][5];+ ~GENERATE+ for (~SYM[5]=0;~SYM[5]<2;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]+ localparam n = 2;+ wire [3:0] i;+ assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:3] ~GENSYM[res][7];+ ~GENERATE+ if (1) begin+ localparam n = 3;+ wire [5:0] i;+ assign i = ~SYM[4][0:5];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ assign ~RESULT = $unsigned(~SYM[7]);+ // ctz8 end+- BlackBox:+ name: GHC.Prim.ctz16#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: enc+ extension: inc+ template: |-+ function [1:0] ~INCLUDENAME[0];+ input [1:0] a;+ case (a)+ 2'b00: ~INCLUDENAME[0] = 2'b10;+ 2'b01: ~INCLUDENAME[0] = 2'b01;+ 2'b10: ~INCLUDENAME[0] = 2'b00;+ default: ~INCLUDENAME[0] = 2'b00;+ endcase+ endfunction+ kind: Declaration+ type: 'ctz16 :: Word#+ -> Word#'+ template: |-+ // ctz16 begin+ wire [0:15] ~GENSYM[v][1];+ genvar ~GENSYM[k][18];+ ~GENERATE+ for (~SYM[18]=0;~SYM[18]<16;~SYM[18]=~SYM[18]+1) begin : ~GENSYM[reverse][19]+ assign ~SYM[1][~SYM[18]] = ~ARG[0][~SYM[18]];+ end+ ~ENDGENERATE++ wire [0:15] ~GENSYM[e][2];+ genvar ~GENSYM[i][3];+ ~GENERATE+ for (~SYM[3]=0;~SYM[3]<8;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ end+ ~ENDGENERATE++ reg [0:11] ~GENSYM[a][4];+ genvar ~GENSYM[i1][5];+ ~GENERATE+ for (~SYM[5]=0;~SYM[5]<4;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]+ localparam n = 2;+ wire [3:0] i;+ assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:7] ~GENSYM[b][9];+ genvar ~GENSYM[i2][10];+ ~GENERATE+ for (~SYM[10]=0;~SYM[10]<2;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]+ localparam n = 3;+ wire [5:0] i;+ assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:4] ~GENSYM[res][7];+ ~GENERATE+ if (1) begin+ localparam n = 4;+ wire [7:0] i;+ assign i = ~SYM[9][0:7];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ assign ~RESULT = $unsigned(~SYM[7]);+ // ctz16 end+- BlackBox:+ name: GHC.Prim.ctz32#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: enc+ extension: inc+ template: |-+ function [1:0] ~INCLUDENAME[0];+ input [1:0] a;+ case (a)+ 2'b00: ~INCLUDENAME[0] = 2'b10;+ 2'b01: ~INCLUDENAME[0] = 2'b01;+ 2'b10: ~INCLUDENAME[0] = 2'b00;+ default: ~INCLUDENAME[0] = 2'b00;+ endcase+ endfunction+ kind: Declaration+ type: 'ctz32 :: Word#+ -> Word#'+ template: |-+ // ctz32 begin+ wire [0:31] ~GENSYM[v][1];+ genvar ~GENSYM[k][18];+ ~GENERATE+ for (~SYM[18]=0;~SYM[18]<32;~SYM[18]=~SYM[18]+1) begin : ~GENSYM[reverse][19]+ assign ~SYM[1][~SYM[18]] = ~ARG[0][~SYM[18]];+ end+ ~ENDGENERATE++ wire [0:31] ~GENSYM[e][2];+ genvar ~GENSYM[i][3];+ ~GENERATE+ for (~SYM[3]=0;~SYM[3]<16;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ end+ ~ENDGENERATE++ reg [0:23] ~GENSYM[a][4];+ genvar ~GENSYM[i1][5];+ ~GENERATE+ for (~SYM[5]=0;~SYM[5]<8;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]+ localparam n = 2;+ wire [3:0] i;+ assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:15] ~GENSYM[b][9];+ genvar ~GENSYM[i2][10];+ ~GENERATE+ for (~SYM[10]=0;~SYM[10]<4;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]+ localparam n = 3;+ wire [5:0] i;+ assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:9] ~GENSYM[c][12];+ genvar ~GENSYM[i3][13];+ ~GENERATE+ for (~SYM[13]=0;~SYM[13]<2;~SYM[13]=~SYM[13]+1) begin : ~GENSYM[mux_stage3][14]+ localparam n = 4;+ wire [7:0] i;+ assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:5] ~GENSYM[res][7];+ ~GENERATE+ if (1) begin+ localparam n = 5;+ wire [9:0] i;+ assign i = ~SYM[12][0:9];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ assign ~RESULT = $unsigned(~SYM[7]);+ // ctz32 end+- BlackBox:+ name: GHC.Prim.ctz64#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: enc+ extension: inc+ template: |-+ function [1:0] ~INCLUDENAME[0];+ input [1:0] a;+ case (a)+ 2'b00: ~INCLUDENAME[0] = 2'b10;+ 2'b01: ~INCLUDENAME[0] = 2'b01;+ 2'b10: ~INCLUDENAME[0] = 2'b00;+ default: ~INCLUDENAME[0] = 2'b00;+ endcase+ endfunction+ kind: Declaration+ type: 'ctz64 :: Word#+ -> Word#'+ template: |-+ // ctz64 begin+ wire [0:63] ~GENSYM[v][1];+ genvar ~GENSYM[k][18];+ ~GENERATE+ for (~SYM[18]=0;~SYM[18]<64;~SYM[18]=~SYM[18]+1) begin : ~GENSYM[reverse][19]+ assign ~SYM[1][~SYM[18]] = ~ARG[0][~SYM[18]];+ end+ ~ENDGENERATE++ wire [0:63] ~GENSYM[e][2];+ genvar ~GENSYM[i][3];+ ~GENERATE+ for (~SYM[3]=0;~SYM[3]<32;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ end+ ~ENDGENERATE++ reg [0:47] a;+ genvar ~GENSYM[i1][5];+ ~GENERATE+ for (~SYM[5]=0;~SYM[5]<16;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]+ localparam n = 2;+ wire [3:0] i;+ assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:31] ~GENSYM[b][9];+ genvar ~GENSYM[i2][10];+ ~GENERATE+ for (~SYM[10]=0;~SYM[10]<8;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]+ localparam n = 3;+ wire [5:0] i;+ assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:19] ~GENSYM[c][12];+ genvar ~GENSYM[i3][13];+ ~GENERATE+ for (~SYM[13]=0;~SYM[13]<4;~SYM[13]=~SYM[13]+1) begin : ~GENSYM[mux_stage3][14]+ localparam n = 4;+ wire [7:0] i;+ assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:11] ~GENSYM[d][15];+ genvar ~GENSYM[i4][16];+ ~GENERATE+ for (~SYM[16]=0;~SYM[16]<2;~SYM[16]=~SYM[16]+1) begin : ~GENSYM[mux_stage4][17]+ localparam n = 5;+ wire [9:0] i;+ assign i = ~SYM[12][~SYM[16]*10:~SYM[16]*10+9];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:6] ~GENSYM[res][7];+ ~GENERATE+ if (1) begin+ localparam n = 6;+ wire [11:0] i;+ assign i = ~SYM[15][0:11];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ assign ~RESULT = $unsigned(~SYM[7]);+ // ctz64 end+- BlackBox:+ name: GHC.Prim.ctz#+ imports:+ - ~INCLUDENAME[0].inc+ includes:+ - name: enc+ extension: inc+ template: |-+ function [1:0] ~INCLUDENAME[0];+ input [1:0] a;+ case (a)+ 2'b00: ~INCLUDENAME[0] = 2'b10;+ 2'b01: ~INCLUDENAME[0] = 2'b01;+ 2'b10: ~INCLUDENAME[0] = 2'b00;+ default: ~INCLUDENAME[0] = 2'b00;+ endcase+ endfunction+ kind: Declaration+ type: 'ctz :: Word# ->+ Word#'+ template: |-+ // ctz begin~IF ~IW64 ~THEN+ wire [0:63] ~GENSYM[v][1];+ genvar ~GENSYM[k][18];+ ~GENERATE+ for (~SYM[18]=0;~SYM[18]<64;~SYM[18]=~SYM[18]+1) begin : ~GENSYM[reverse][19]+ assign ~SYM[1][~SYM[18]] = ~ARG[0][~SYM[18]];+ end+ ~ENDGENERATE++ wire [0:63] ~GENSYM[e][2];+ genvar ~GENSYM[i][3];+ ~GENERATE+ for (~SYM[3]=0;~SYM[3]<32;~SYM[3]=~SYM[3]+1) begin : ~GENSYM[enc_stage][8]+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ end+ ~ENDGENERATE++ reg [0:47] ~GENSYM[a][4];+ genvar ~GENSYM[i1][5];+ ~GENERATE+ for (~SYM[5]=0;~SYM[5]<16;~SYM[5]=~SYM[5]+1) begin : ~GENSYM[mux_stage][6]+ localparam n = 2;+ wire [3:0] i;+ assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:31] ~GENSYM[b][9];+ genvar ~GENSYM[i2][10];+ ~GENERATE+ for (~SYM[10]=0;~SYM[10]<8;~SYM[10]=~SYM[10]+1) begin : ~GENSYM[mux_stage2][11]+ localparam n = 3;+ wire [5:0] i;+ assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:19] ~GENSYM[c][12];+ genvar ~GENSYM[i3][13];+ ~GENERATE+ for (~SYM[13]=0;~SYM[13]<4;~SYM[13]=~SYM[13]+1) begin : ~GENSYM[mux_stage3][14]+ localparam n = 4;+ wire [7:0] i;+ assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:11] ~GENSYM[d][15];+ genvar ~GENSYM[i4][16];+ ~GENERATE+ for (~SYM[16]=0;~SYM[16]<2;~SYM[16]=~SYM[16]+1) begin : ~GENSYM[mux_stage4][17]+ localparam n = 5;+ wire [9:0] i;+ assign i = ~SYM[12][~SYM[16]*10:~SYM[16]*10+9];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[15][~SYM[16]*6:~SYM[16]*6+5] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:6] ~GENSYM[res][7];+ ~GENERATE+ if (1) begin+ localparam n = 6;+ wire [11:0] i;+ assign i = ~SYM[15][0:11];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE+ ~ELSE+ wire [0:31] ~SYM[1];+ genvar ~SYM[18];+ ~GENERATE+ for (~SYM[18]=0;~SYM[18]<32;~SYM[18]=~SYM[18]+1) begin : ~SYM[19]+ assign ~SYM[1][~SYM[18]] = ~ARG[0][~SYM[18]];+ end+ ~ENDGENERATE++ wire [0:31] ~SYM[2];+ genvar ~SYM[3];+ ~GENERATE+ for (~SYM[3]=0;~SYM[3]<16;~SYM[3]=~SYM[3]+1) begin : ~SYM[8]+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ end+ ~ENDGENERATE++ reg [0:23] ~SYM[4];+ genvar ~SYM[5];+ ~GENERATE+ for (~SYM[5]=0;~SYM[5]<8;~SYM[5]=~SYM[5]+1) begin : ~SYM[6]+ localparam n = 2;+ wire [3:0] i;+ assign i = ~SYM[2][~SYM[5]*4:~SYM[5]*4+3];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[4][~SYM[5]*3:~SYM[5]*3+2] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:15] ~SYM[9];+ genvar ~SYM[10];+ ~GENERATE+ for (~SYM[10]=0;~SYM[10]<4;~SYM[10]=~SYM[10]+1) begin : ~SYM[11]+ localparam n = 3;+ wire [5:0] i;+ assign i = ~SYM[4][~SYM[10]*6:~SYM[10]*6+5];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[9][~SYM[10]*4:~SYM[10]*4+3] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:9] ~SYM[12];+ genvar ~SYM[13];+ ~GENERATE+ for (~SYM[13]=0;~SYM[13]<2;~SYM[13]=~SYM[13]+1) begin : ~SYM[14]+ localparam n = 4;+ wire [7:0] i;+ assign i = ~SYM[9][~SYM[13]*8:~SYM[13]*8+7];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[12][~SYM[13]*5:~SYM[13]*5+4] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE++ reg [0:5] ~SYM[7];+ ~GENERATE+ if (1) begin+ localparam n = 5;+ wire [9:0] i;+ assign i = ~SYM[12][0:9];+ always @(*) begin+ case (i[n-1+n])+ 1'b0 : ~SYM[7] = {i[n-1+n] && i[n-1],1'b0,i[2*n-2:n]};+ default : ~SYM[7] = {i[n-1+n] && i[n-1],~ i[n-1],i[n-2:0]};+ endcase+ end+ end+ ~ENDGENERATE+ ~FI+ assign ~RESULT = $unsigned(~SYM[7]);+ // ctz end
− prims/vhdl/Clash_Class_Exp.primitives
@@ -1,29 +0,0 @@-[- {- "BlackBox": {- "name": "Clash.Class.Exp.expIndex#",- "kind": "Expression",- "type": "expIndex# :: KnownNat m => Index m -> SNat n -> Index (m^n)",- "template": "~DEVNULL[~ARG[0]]to_unsigned(to_integer(~ARG[1]) ** ~LIT[2], ~SIZE[~TYPO])",- "warning": "Exponentiation is only supported on relatively small constructs (< 32 bits). Ideally, Clash should have constant folded your expression. See https://github.com/clash-lang/clash-compiler/issues/593."- }- },- {- "BlackBox": {- "name": "Clash.Class.Exp.expSigned#",- "kind": "Expression",- "type": "expSigned# :: KnownNat m => Signed m -> SNat n -> Signed (m*n)",- "template": "~DEVNULL[~ARG[0]]to_signed(to_integer(~ARG[1]) ** ~LIT[2], ~SIZE[~TYPO])",- "warning": "Exponentiation is only supported on relatively small constructs (< 32 bits). Ideally, Clash should have constant folded your expression. See https://github.com/clash-lang/clash-compiler/issues/593."- }- },- {- "BlackBox": {- "name": "Clash.Class.Exp.expUnsigned#",- "kind": "Expression",- "type": "expUnsigned# :: KnownNat m => Unsigned m -> SNat n -> Unsigned (m*n)",- "template": "~DEVNULL[~ARG[0]]to_unsigned(to_integer(~ARG[1]) ** ~LIT[2], ~SIZE[~TYPO])",- "warning": "Exponentiation is only supported on relatively small constructs (< 32 bits). Ideally, Clash should have constant folded your expression. See https://github.com/clash-lang/clash-compiler/issues/593."- }- }-]
+ prims/vhdl/Clash_Class_Exp.primitives.yaml view
@@ -0,0 +1,24 @@+- BlackBox:+ name: Clash.Class.Exp.expIndex#+ kind: Expression+ type: 'expIndex# :: KnownNat+ m => Index m -> SNat n -> Index (m^n)'+ template: ~DEVNULL[~ARG[0]]to_unsigned(to_integer(~ARG[1]) ** ~LIT[2], ~SIZE[~TYPO])+ warning: Exponentiation is only supported on relatively small constructs (< 32+ bits). Ideally, Clash should have constant folded your expression. See https://github.com/clash-lang/clash-compiler/issues/593.+- BlackBox:+ name: Clash.Class.Exp.expSigned#+ kind: Expression+ type: 'expSigned# :: KnownNat+ m => Signed m -> SNat n -> Signed (m*n)'+ template: ~DEVNULL[~ARG[0]]to_signed(to_integer(~ARG[1]) ** ~LIT[2], ~SIZE[~TYPO])+ warning: Exponentiation is only supported on relatively small constructs (< 32+ bits). Ideally, Clash should have constant folded your expression. See https://github.com/clash-lang/clash-compiler/issues/593.+- BlackBox:+ name: Clash.Class.Exp.expUnsigned#+ kind: Expression+ type: 'expUnsigned# ::+ KnownNat m => Unsigned m -> SNat n -> Unsigned (m*n)'+ template: ~DEVNULL[~ARG[0]]to_unsigned(to_integer(~ARG[1]) ** ~LIT[2], ~SIZE[~TYPO])+ warning: Exponentiation is only supported on relatively small constructs (< 32+ bits). Ideally, Clash should have constant folded your expression. See https://github.com/clash-lang/clash-compiler/issues/593.
− prims/vhdl/Clash_Explicit_BlockRam.primitives
@@ -1,177 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Explicit.BlockRam.blockRam#"- , "kind" : "Declaration"- , "type" :-"blockRam#- :: ( KnownDomain dom ARG[0]- , HasCallStack -- ARG[1]- , Undefined a ) -- ARG[2]- => Clock dom -- clk, ARG[3]- -> Enable dom -- en, ARG[4]- -> Vec n a -- init, ARG[5]- -> Signal dom Int -- rd, ARG[6]- -> Signal dom Bool -- wren, ARG[7]- -> Signal dom Int -- wr, ARG[8]- -> Signal dom a -- din, ARG[9]- -> Signal dom a"- , "template" :-"-- blockRam begin-~GENSYM[~RESULT_blockRam][1] : block- signal ~GENSYM[~RESULT_RAM][2] : ~TYP[5] := ~CONST[5];- signal ~GENSYM[rd][4] : integer range 0 to ~LENGTH[~TYP[5]] - 1;- signal ~GENSYM[wr][5] : integer range 0 to ~LENGTH[~TYP[5]] - 1;-begin- ~SYM[4] <= to_integer(~ARG[6])- -- pragma translate_off- mod ~LENGTH[~TYP[5]]- -- pragma translate_on- ;-- ~SYM[5] <= to_integer(~ARG[8])- -- pragma translate_off- mod ~LENGTH[~TYP[5]]- -- pragma translate_on- ;-~IF ~VIVADO ~THEN- ~SYM[6] : process(~ARG[3])- begin- if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3]) then- if ~ARG[7] ~IF ~ISACTIVEENABLE[4] ~THEN and ~ARG[4] ~ELSE ~FI then- ~SYM[2](~SYM[5]) <= ~TOBV[~ARG[9]][~TYP[9]];- end if;- ~RESULT <= fromSLV(~SYM[2](~SYM[4]));- end if;- end process; ~ELSE- ~SYM[6] : process(~ARG[3])- begin- if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3]) then- if ~ARG[7] ~IF ~ISACTIVEENABLE[4] ~THEN and ~ARG[4] ~ELSE ~FI then- ~SYM[2](~SYM[5]) <= ~ARG[9];- end if;- ~RESULT <= ~SYM[2](~SYM[4]);- end if;- end process; ~FI-end block;---end blockRam"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.BlockRam.blockRamU#"- , "kind" : "Declaration"- , "type" :-"blockRamU#- :: ( KnownDomain dom ARG[0]- , HasCallStack -- ARG[1]- , Undefined a ) -- ARG[2]- => Clock dom -- clk, ARG[3]- -> Enable dom -- en, ARG[4]- -> SNat n -- len, ARG[5]- -> Signal dom Int -- rd, ARG[6]- -> Signal dom Bool -- wren, ARG[7]- -> Signal dom Int -- wr, ARG[8]- -> Signal dom a -- din, ARG[9]- -> Signal dom a"- , "template" :-"-- blockRamU begin-~GENSYM[~RESULT_blockRam][1] : block~IF~VIVADO~THEN- type ~GENSYM[ram_t][8] is array (0 to integer'(~LIT[5])-1) of std_logic_vector(~SIZE[~TYP[9]]-1 downto 0);~ELSE- type ~SYM[8] is array (0 to integer'(~LIT[5])-1) of ~TYP[9];~FI- signal ~GENSYM[~RESULT_RAM][2] : ~SYM[8];- signal ~GENSYM[rd][4] : integer range 0 to ~LIT[5] - 1;- signal ~GENSYM[wr][5] : integer range 0 to ~LIT[5] - 1;-begin- ~SYM[4] <= to_integer(~ARG[6])- -- pragma translate_off- mod ~LIT[5]- -- pragma translate_on- ;-- ~SYM[5] <= to_integer(~ARG[8])- -- pragma translate_off- mod ~LIT[5]- -- pragma translate_on- ;-~IF ~VIVADO ~THEN- ~SYM[6] : process(~ARG[3])- begin- if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3]) then- if ~ARG[7] ~IF ~ISACTIVEENABLE[4] ~THEN and ~ARG[4] ~ELSE ~FI then- ~SYM[2](~SYM[5]) <= ~TOBV[~ARG[9]][~TYP[9]];- end if;- ~RESULT <= fromSLV(~SYM[2](~SYM[4]));- end if;- end process; ~ELSE- ~SYM[6] : process(~ARG[3])- begin- if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3]) then- if ~ARG[7] ~IF ~ISACTIVEENABLE[4] ~THEN and ~ARG[4] ~ELSE ~FI then- ~SYM[2](~SYM[5]) <= ~ARG[9];- end if;- ~RESULT <= ~SYM[2](~SYM[4]);- end if;- end process; ~FI-end block;---end blockRamU"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.BlockRam.blockRam1#"- , "kind" : "Declaration"- , "type" :-"blockRam1#- :: ( KnownDomain dom ARG[0]- , HasCallStack -- ARG[1]- , Undefined a ) -- ARG[2]- => Clock dom -- clk, ARG[3]- -> Enable dom -- en, ARG[4]- -> SNat n -- len, ARG[5]- -> a -- init, ARG[6]- -> Signal dom Int -- rd, ARG[7]- -> Signal dom Bool -- wren, ARG[8]- -> Signal dom Int -- wr, ARG[9]- -> Signal dom a -- din, ARG[10]- -> Signal dom a"- , "template" :-"-- blockRam1 begin-~GENSYM[~RESULT_blockRam][1] : block~IF~VIVADO~THEN- type ~GENSYM[ram_t][8] is array (0 to integer'(~LIT[5])-1) of std_logic_vector(~SIZE[~TYP[6]]-1 downto 0);~ELSE- type ~SYM[8] is array (0 to integer'(~LIT[5])-1) of ~TYP[6];~FI- signal ~GENSYM[~RESULT_RAM][2] : ~SYM[8] := (others => ~IF~VIVADO~THEN~TOBV[~CONST[6]][~TYP[6]]~ELSE~CONST[6]~FI);- signal ~GENSYM[rd][4] : integer range 0 to ~LIT[5] - 1;- signal ~GENSYM[wr][5] : integer range 0 to ~LIT[5] - 1;-begin- ~SYM[4] <= to_integer(~ARG[7])- -- pragma translate_off- mod ~LIT[5]- -- pragma translate_on- ;-- ~SYM[5] <= to_integer(~ARG[9])- -- pragma translate_off- mod ~LIT[5]- -- pragma translate_on- ;-~IF ~VIVADO ~THEN- ~SYM[6] : process(~ARG[3])- begin- if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3]) then- if ~ARG[8] ~IF ~ISACTIVEENABLE[4] ~THEN and ~ARG[4] ~ELSE ~FI then- ~SYM[2](~SYM[5]) <= ~TOBV[~ARG[10]][~TYP[10]];- end if;- ~RESULT <= fromSLV(~SYM[2](~SYM[4]));- end if;- end process; ~ELSE- ~SYM[6] : process(~ARG[3])- begin- if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3]) then- if ~ARG[8] ~IF ~ISACTIVEENABLE[4] ~THEN and ~ARG[4] ~ELSE ~FI then- ~SYM[2](~SYM[5]) <= ~ARG[10];- end if;- ~RESULT <= ~SYM[2](~SYM[4]);- end if;- end process; ~FI-end block;---end blockRam1"- }- }-]
+ prims/vhdl/Clash_Explicit_BlockRam.primitives.yaml view
@@ -0,0 +1,234 @@+- BlackBox:+ name: Clash.Explicit.BlockRam.blockRam#+ kind: Declaration+ type: |-+ blockRam#+ :: ( KnownDomain dom ARG[0]+ , HasCallStack -- ARG[1]+ , Undefined a ) -- ARG[2]+ => Clock dom -- clk, ARG[3]+ -> Enable dom -- en, ARG[4]+ -> Vec n a -- init, ARG[5]+ -> Signal dom Int -- rd, ARG[6]+ -> Signal dom Bool -- wren, ARG[7]+ -> Signal dom Int -- wr, ARG[8]+ -> Signal dom a -- din, ARG[9]+ -> Signal dom a+ template: |-+ -- blockRam begin+ ~GENSYM[~RESULT_blockRam][1] : block+ signal ~GENSYM[~RESULT_RAM][2] : ~TYP[5] := ~CONST[5];+ signal ~GENSYM[rd][4] : integer range 0 to ~LENGTH[~TYP[5]] - 1;+ signal ~GENSYM[wr][5] : integer range 0 to ~LENGTH[~TYP[5]] - 1;+ begin+ ~SYM[4] <= to_integer(~VAR[rdI][6](31 downto 0))+ -- pragma translate_off+ mod ~LENGTH[~TYP[5]]+ -- pragma translate_on+ ;++ ~SYM[5] <= to_integer(~VAR[wrI][8](31 downto 0))+ -- pragma translate_off+ mod ~LENGTH[~TYP[5]]+ -- pragma translate_on+ ;+ ~IF ~VIVADO ~THEN+ ~SYM[6] : process(~ARG[3])+ begin+ if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3]) then+ if ~ARG[7] ~IF ~ISACTIVEENABLE[4] ~THEN and ~ARG[4] ~ELSE ~FI then+ ~SYM[2](~SYM[5]) <= ~TOBV[~ARG[9]][~TYP[9]];+ end if;+ ~RESULT <= fromSLV(~SYM[2](~SYM[4]));+ end if;+ end process; ~ELSE+ ~SYM[6] : process(~ARG[3])+ begin+ if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3]) then+ if ~ARG[7] ~IF ~ISACTIVEENABLE[4] ~THEN and ~ARG[4] ~ELSE ~FI then+ ~SYM[2](~SYM[5]) <= ~ARG[9];+ end if;+ ~RESULT <= ~SYM[2](~SYM[4]);+ end if;+ end process; ~FI+ end block;+ --end blockRam+- BlackBox:+ name: Clash.Explicit.BlockRam.blockRamU#+ kind: Declaration+ type: |-+ blockRamU#+ :: ( KnownDomain dom ARG[0]+ , HasCallStack -- ARG[1]+ , Undefined a ) -- ARG[2]+ => Clock dom -- clk, ARG[3]+ -> Enable dom -- en, ARG[4]+ -> SNat n -- len, ARG[5]+ -> Signal dom Int -- rd, ARG[6]+ -> Signal dom Bool -- wren, ARG[7]+ -> Signal dom Int -- wr, ARG[8]+ -> Signal dom a -- din, ARG[9]+ -> Signal dom a+ template: |-+ -- blockRamU begin+ ~GENSYM[~RESULT_blockRam][1] : block~IF~VIVADO~THEN+ type ~GENSYM[ram_t][8] is array (0 to integer'(~LIT[5])-1) of std_logic_vector(~SIZE[~TYP[9]]-1 downto 0);~ELSE+ type ~SYM[8] is array (0 to integer'(~LIT[5])-1) of ~TYP[9];~FI+ signal ~GENSYM[~RESULT_RAM][2] : ~SYM[8];+ signal ~GENSYM[rd][4] : integer range 0 to ~LIT[5] - 1;+ signal ~GENSYM[wr][5] : integer range 0 to ~LIT[5] - 1;+ begin+ ~SYM[4] <= to_integer(~VAR[rdI][6](31 downto 0))+ -- pragma translate_off+ mod ~LIT[5]+ -- pragma translate_on+ ;++ ~SYM[5] <= to_integer(~VAR[wrI][8](31 downto 0))+ -- pragma translate_off+ mod ~LIT[5]+ -- pragma translate_on+ ;+ ~IF ~VIVADO ~THEN+ ~SYM[6] : process(~ARG[3])+ begin+ if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3]) then+ if ~ARG[7] ~IF ~ISACTIVEENABLE[4] ~THEN and ~ARG[4] ~ELSE ~FI then+ ~SYM[2](~SYM[5]) <= ~TOBV[~ARG[9]][~TYP[9]];+ end if;+ ~RESULT <= fromSLV(~SYM[2](~SYM[4]));+ end if;+ end process; ~ELSE+ ~SYM[6] : process(~ARG[3])+ begin+ if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3]) then+ if ~ARG[7] ~IF ~ISACTIVEENABLE[4] ~THEN and ~ARG[4] ~ELSE ~FI then+ ~SYM[2](~SYM[5]) <= ~ARG[9];+ end if;+ ~RESULT <= ~SYM[2](~SYM[4]);+ end if;+ end process; ~FI+ end block;+ --end blockRamU+- BlackBox:+ name: Clash.Explicit.BlockRam.blockRam1#+ kind: Declaration+ type: |-+ blockRam1#+ :: ( KnownDomain dom ARG[0]+ , HasCallStack -- ARG[1]+ , Undefined a ) -- ARG[2]+ => Clock dom -- clk, ARG[3]+ -> Enable dom -- en, ARG[4]+ -> SNat n -- len, ARG[5]+ -> a -- init, ARG[6]+ -> Signal dom Int -- rd, ARG[7]+ -> Signal dom Bool -- wren, ARG[8]+ -> Signal dom Int -- wr, ARG[9]+ -> Signal dom a -- din, ARG[10]+ -> Signal dom a+ template: |-+ -- blockRam1 begin+ ~GENSYM[~RESULT_blockRam][1] : block~IF~VIVADO~THEN+ type ~GENSYM[ram_t][8] is array (0 to integer'(~LIT[5])-1) of std_logic_vector(~SIZE[~TYP[6]]-1 downto 0);~ELSE+ type ~SYM[8] is array (0 to integer'(~LIT[5])-1) of ~TYP[6];~FI+ signal ~GENSYM[~RESULT_RAM][2] : ~SYM[8] := (others => ~IF~VIVADO~THEN~TOBV[~CONST[6]][~TYP[6]]~ELSE~CONST[6]~FI);+ signal ~GENSYM[rd][4] : integer range 0 to ~LIT[5] - 1;+ signal ~GENSYM[wr][5] : integer range 0 to ~LIT[5] - 1;+ begin+ ~SYM[4] <= to_integer(~VAR[rdI][7](31 downto 0))+ -- pragma translate_off+ mod ~LIT[5]+ -- pragma translate_on+ ;++ ~SYM[5] <= to_integer(~VAR[wrI][9](31 downto 0))+ -- pragma translate_off+ mod ~LIT[5]+ -- pragma translate_on+ ;+ ~IF ~VIVADO ~THEN+ ~SYM[6] : process(~ARG[3])+ begin+ if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3]) then+ if ~ARG[8] ~IF ~ISACTIVEENABLE[4] ~THEN and ~ARG[4] ~ELSE ~FI then+ ~SYM[2](~SYM[5]) <= ~TOBV[~ARG[10]][~TYP[10]];+ end if;+ ~RESULT <= fromSLV(~SYM[2](~SYM[4]));+ end if;+ end process; ~ELSE+ ~SYM[6] : process(~ARG[3])+ begin+ if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3]) then+ if ~ARG[8] ~IF ~ISACTIVEENABLE[4] ~THEN and ~ARG[4] ~ELSE ~FI then+ ~SYM[2](~SYM[5]) <= ~ARG[10];+ end if;+ ~RESULT <= ~SYM[2](~SYM[4]);+ end if;+ end process; ~FI+ end block;+ --end blockRam1+- BlackBox:+ name: Clash.Explicit.BlockRam.trueDualPortBlockRam#+ kind: Declaration+ type: |-+ trueDualPortBlockRam# ::+ forall nAddrs domA domB a .+ ( HasCallStack ~ARG[0]+ , KnownNat nAddrs ~ARG[1]+ , KnownDomain domA ~ARG[2]+ , KnownDomain domB ~ARG[3]+ , NFDataX a ~ARG[4]+ ) =>++ Clock domA -> ~ARG[5]+ Signal domA Bool -> ~ARG[6]+ Signal domA Bool -> ~ARG[7]+ Signal domA (Index nAddrs) -> ~ARG[8]+ Signal domA a -> ~ARG[9]++ Clock domB -> ~ARG[10]+ Signal domB Bool -> ~ARG[11]+ Signal domB Bool -> ~ARG[12]+ Signal domB (Index nAddrs) -> ~ARG[13]+ Signal domB a -> ~ARG[14]+ (Signal domA a, Signal domB a)+ template: |-+ -- trueDualPortBlockRam begin+ ~GENSYM[~RESULT_trueDualPortBlockRam][1] : block+ -- Shared memory+ type mem_type is array ( ~LIT[1]-1 downto 0 ) of ~TYP[9];+ shared variable mem : mem_type;+ signal ~GENSYM[a_dout][2] : ~TYP[9];+ signal ~GENSYM[b_dout][3] : ~TYP[14];+ begin++ -- Port A+ process(~ARG[5])+ begin+ if(rising_edge(~ARG[5])) then+ if(~ARG[6]) then+ if(~ARG[7]) then+ mem(~IF~SIZE[~TYP[8]]~THENto_integer(~ARG[8])~ELSE0~FI) := ~ARG[9];+ end if;+ ~SYM[2] <= mem(~IF~SIZE[~TYP[8]]~THENto_integer(~ARG[8])~ELSE0~FI);+ end if;+ end if;+ end process;++ -- Port B+ process(~ARG[10])+ begin+ if(rising_edge(~ARG[10])) then+ if(~ARG[11]) then+ if(~ARG[12]) then+ mem(~IF~SIZE[~TYP[13]]~THENto_integer(~ARG[13])~ELSE0~FI) := ~ARG[14];+ end if;+ ~SYM[3] <= mem(~IF~SIZE[~TYP[13]]~THENto_integer(~ARG[13])~ELSE0~FI);+ end if;+ end if;+ end process;++ ~RESULT <= (~SYM[2], ~SYM[3]);+ end block;+ -- end trueDualPortBlockRam
+ prims/vhdl/Clash_Explicit_BlockRam_Blob.primitives.yaml view
@@ -0,0 +1,43 @@+- BlackBox:+ name: Clash.Explicit.BlockRam.Blob.blockRamBlob#+ kind: Declaration+ type: |-+ blockRamBlob#+ :: KnownDomain dom -- ARG[0]+ => Clock dom -- clk, ARG[1]+ -> Enable dom -- en, ARG[2]+ -> MemBlob n m -- init, ARG[3]+ -> Signal dom Int -- rd, ARG[4]+ -> Signal dom Bool -- wren, ARG[5]+ -> Signal dom Int -- wr, ARG[6]+ -> Signal dom (BitVector m) -- din, ARG[7]+ -> Signal dom (BitVector m)+ template: |-+ -- blockRamBlob begin+ ~GENSYM[~RESULT_blockRam][1] : block+ signal ~GENSYM[~RESULT_RAM][2] : ~TYP[3] := ~CONST[3];+ signal ~GENSYM[rd][4] : integer range 0 to ~LENGTH[~TYP[3]] - 1;+ signal ~GENSYM[wr][5] : integer range 0 to ~LENGTH[~TYP[3]] - 1;+ begin+ ~SYM[4] <= to_integer(~VAR[rdI][4](31 downto 0))+ -- pragma translate_off+ mod ~LENGTH[~TYP[3]]+ -- pragma translate_on+ ;++ ~SYM[5] <= to_integer(~VAR[wrI][6](31 downto 0))+ -- pragma translate_off+ mod ~LENGTH[~TYP[3]]+ -- pragma translate_on+ ;+ ~SYM[6] : process(~ARG[1])+ begin+ if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[1]) then+ if ~ARG[5]~IF~ISACTIVEENABLE[2]~THEN and ~ARG[2]~ELSE~FI then+ ~SYM[2](~SYM[5]) <= ~ARG[7];+ end if;+ ~RESULT <= ~SYM[2](~SYM[4]);+ end if;+ end process;+ end block;+ -- blockRamBlob end
− prims/vhdl/Clash_Explicit_BlockRam_File.primitives
@@ -1,95 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Explicit.BlockRam.File.blockRamFile#"- , "kind" : "Declaration"- , "type" :-"blockRamFile#- :: ( KnownDomain dom -- ARG[0]- , KnownNat m -- ARG[1]- , HasCallStack ) -- ARG[2]- => Clock dom -- clk, ARG[3]- => Enable dom -- en, ARG[4]- -> SNat n -- sz, ARG[5]- -> FilePath -- file, ARG[6]- -> Signal dom Int -- rd, ARG[7]- -> Signal dom Bool -- wren, ARG[8]- -> Signal dom Int -- wr, ARG[9]- -> Signal dom (BitVector m) -- din, ARG[10]- -> Signal dom (BitVector m)"- , "template" :-"-- blockRamFile begin-~GENSYM[~COMPNAME_blockRamFile][1] : block- type ~GENSYM[RamType][7] is array(natural range <>) of bit_vector(~LIT[1]-1 downto 0);-- impure function ~GENSYM[InitRamFromFile][2] (RamFileName : in string) return ~SYM[7] is- FILE RamFile : text open read_mode is RamFileName;- variable RamFileLine : line;- variable RAM : ~SYM[7](0 to ~LIT[5]-1);- begin- for i in RAM'range loop- readline(RamFile,RamFileLine);- read(RamFileLine,RAM(i));- end loop;- return RAM;- end function;-- signal ~GENSYM[RAM][3] : ~SYM[7](0 to ~LIT[5]-1) := ~SYM[2](~FILE[~LIT[6]]);- signal ~GENSYM[rd][5] : integer range 0 to ~LIT[5]-1;- signal ~GENSYM[wr][6] : integer range 0 to ~LIT[5]-1;-begin- ~SYM[5] <= to_integer(~ARG[7])- -- pragma translate_off- mod ~LIT[5]- -- pragma translate_on- ;-- ~SYM[6] <= to_integer(~ARG[9])- -- pragma translate_off- mod ~LIT[5]- -- pragma translate_on- ;- ~IF ~VIVADO ~THEN ~IF ~ISACTIVEENABLE[4] ~THEN- ~GENSYM[blockRamFile_sync][10] : process(~ARG[3])- begin- if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3]) then- if ~ARG[4] then- if ~ARG[8] then- ~SYM[3](~SYM[6]) <= to_bitvector(~ARG[10]);- end if;- ~RESULT <= to_stdlogicvector(~SYM[3](~SYM[5]));- end if;- end if;- end process;~ELSE- ~SYM[10] : process(~ARG[3])- begin- if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3]) then- if ~ARG[8] then- ~SYM[3](~SYM[6]) <= to_bitvector(~ARG[10]);- end if;- ~RESULT <= to_stdlogicvector(~SYM[3](~SYM[5]));- end if;- end process;~FI ~ELSE ~IF ~ISACTIVEENABLE[4] ~THEN- ~SYM[10] : process(~ARG[3])- begin- if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3]) then- if ~ARG[8] and ~ARG[4] then- ~SYM[3](~SYM[6]) <= to_bitvector(~ARG[10]);- end if;- if ~ARG[4] then- ~RESULT <= to_stdlogicvector(~SYM[3](~SYM[5]));- end if;- end if;- end process;~ELSE- ~SYM[10] : process(~ARG[3])- begin- if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3]) then- if ~ARG[8] then- ~SYM[3](~SYM[6]) <= to_bitvector(~ARG[10]);- end if;- ~RESULT <= to_stdlogicvector(~SYM[3](~SYM[5]));- end if;- end process;~FI ~FI-end block;--- blockRamFile end"- }- }-]
+ prims/vhdl/Clash_Explicit_BlockRam_File.primitives.yaml view
@@ -0,0 +1,92 @@+- BlackBox:+ name: Clash.Explicit.BlockRam.File.blockRamFile#+ kind: Declaration+ type: |-+ blockRamFile#+ :: ( KnownDomain dom -- ARG[0]+ , KnownNat m -- ARG[1]+ , HasCallStack ) -- ARG[2]+ => Clock dom -- clk, ARG[3]+ => Enable dom -- en, ARG[4]+ -> SNat n -- sz, ARG[5]+ -> FilePath -- file, ARG[6]+ -> Signal dom Int -- rd, ARG[7]+ -> Signal dom Bool -- wren, ARG[8]+ -> Signal dom Int -- wr, ARG[9]+ -> Signal dom (BitVector m) -- din, ARG[10]+ -> Signal dom (BitVector m)+ template: |-+ -- blockRamFile begin+ ~GENSYM[~COMPNAME_blockRamFile][1] : block+ type ~GENSYM[RamType][7] is array(natural range <>) of bit_vector(~LIT[1]-1 downto 0);++ impure function ~GENSYM[InitRamFromFile][2] (RamFileName : in string) return ~SYM[7] is+ FILE RamFile : text open read_mode is RamFileName;+ variable RamFileLine : line;+ variable RAM : ~SYM[7](0 to ~LIT[5]-1);+ begin+ for i in RAM'range loop+ readline(RamFile,RamFileLine);+ read(RamFileLine,RAM(i));+ end loop;+ return RAM;+ end function;++ signal ~GENSYM[RAM][3] : ~SYM[7](0 to ~LIT[5]-1) := ~SYM[2](~FILE[~LIT[6]]);+ signal ~GENSYM[rd][5] : integer range 0 to ~LIT[5]-1;+ signal ~GENSYM[wr][6] : integer range 0 to ~LIT[5]-1;+ begin+ ~SYM[5] <= to_integer(~VAR[rdI][7](31 downto 0))+ -- pragma translate_off+ mod ~LIT[5]+ -- pragma translate_on+ ;++ ~SYM[6] <= to_integer(~VAR[wrI][9](31 downto 0))+ -- pragma translate_off+ mod ~LIT[5]+ -- pragma translate_on+ ;+ ~IF ~VIVADO ~THEN ~IF ~ISACTIVEENABLE[4] ~THEN+ ~GENSYM[blockRamFile_sync][10] : process(~ARG[3])+ begin+ if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3]) then+ if ~ARG[4] then+ if ~ARG[8] then+ ~SYM[3](~SYM[6]) <= to_bitvector(~ARG[10]);+ end if;+ ~RESULT <= to_stdlogicvector(~SYM[3](~SYM[5]));+ end if;+ end if;+ end process;~ELSE+ ~SYM[10] : process(~ARG[3])+ begin+ if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3]) then+ if ~ARG[8] then+ ~SYM[3](~SYM[6]) <= to_bitvector(~ARG[10]);+ end if;+ ~RESULT <= to_stdlogicvector(~SYM[3](~SYM[5]));+ end if;+ end process;~FI ~ELSE ~IF ~ISACTIVEENABLE[4] ~THEN+ ~SYM[10] : process(~ARG[3])+ begin+ if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3]) then+ if ~ARG[8] and ~ARG[4] then+ ~SYM[3](~SYM[6]) <= to_bitvector(~ARG[10]);+ end if;+ if ~ARG[4] then+ ~RESULT <= to_stdlogicvector(~SYM[3](~SYM[5]));+ end if;+ end if;+ end process;~ELSE+ ~SYM[10] : process(~ARG[3])+ begin+ if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3]) then+ if ~ARG[8] then+ ~SYM[3](~SYM[6]) <= to_bitvector(~ARG[10]);+ end if;+ ~RESULT <= to_stdlogicvector(~SYM[3](~SYM[5]));+ end if;+ end process;~FI ~FI+ end block;+ -- blockRamFile end
− prims/vhdl/Clash_Explicit_DDR.primitives
@@ -1,166 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Explicit.DDR.ddrIn#"- , "kind" : "Declaration"- , "type" :-"ddrIn# :: forall a slow fast n pFast enabled synchronous.- ( HasCallStack -- ARG[0]- , Undefined a -- ARG[1]- , KnownConfi~ fast domf -- ARG[2]- , KnownConfi~ slow doms -- ARG[3]- => Clock slow -- ARG[4]- -> Reset slow -- ARG[5]- -> Enable slow -- ARG[6]- -> a -- ARG[7]- -> a -- ARG[8]- -> a -- ARG[9]- -> Signal fast a -- ARG[10]- -> Signal slow (a,a)"- , "template" :-"-- ddrIn begin-~GENSYM[~COMPNAME_ddrIn][0] : block- signal ~GENSYM[data_Pos][1] : ~TYP[9];- signal ~GENSYM[data_Neg][2] : ~TYP[9];- signal ~GENSYM[data_Neg_Latch][3] : ~TYP[9];-begin- ~IF ~ISSYNC[3] ~THEN- -- sync- -------------- ~GENSYM[~COMPNAME_ddrIn_pos][6] : process(~ARG[4])- begin- if ~IF~ACTIVEEDGE[Rising][2]~THENrising_edge~ELSEfalling_edge~FI(~ARG[4]) then- if ~ARG[5] = ~IF~ISACTIVEHIGH[2]~THEN'1'~ELSE'0'~FI then- ~SYM[1] <= ~ARG[8];- els~IF ~ISACTIVEENABLE[6] ~THENif ~ARG[6] then~ELSEe~FI- ~SYM[1] <= ~ARG[10];- end if;- end if;- end process;-- ~GENSYM[~COMPNAME_ddrIn_neg][7] : process(~ARG[4])- begin- if ~IF~ACTIVEEDGE[Rising][2]~THENfalling_edge~ELSErising_edge~FI(~ARG[4]) then- if ~ARG[5] = ~IF~ISACTIVEHIGH[2]~THEN'1'~ELSE'0'~FI then- ~SYM[2] <= ~ARG[9];- els~IF ~ISACTIVEENABLE[6] ~THENif ~ARG[6] then~ELSEe~FI- ~SYM[2] <= ~ARG[10];- end if;- end if;- end process;-- ~GENSYM[~COMPNAME_ddrIn_neg_latch][8] : process(~ARG[4])- begin- if ~IF~ACTIVEEDGE[Rising][2]~THENrising_edge~ELSEfalling_edge~FI(~ARG[4]) then- if ~ARG[5] = ~IF~ISACTIVEHIGH[2]~THEN'1'~ELSE'0'~FI then- ~SYM[3] <= ~ARG[7];- els~IF ~ISACTIVEENABLE[6] ~THENif ~ARG[6] then~ELSEe~FI- ~SYM[3] <= ~SYM[2];- end if;- end if;- end process;- ~ELSE- -- async- --------------- ~SYM[6] : process(~ARG[4],~ARG[5]~VARS[9])- begin- if ~ARG[5] = ~IF~ISACTIVEHIGH[2]~THEN'1'~ELSE'0'~FI then- ~SYM[1] <= ~ARG[8];- elsif ~IF ~ISACTIVEENABLE[6] ~THEN ~ARG[6] and ~ELSE ~FI ~IF~ACTIVEEDGE[Rising][2]~THENrising_edge~ELSEfalling_edge~FI(~ARG[4]) then- ~SYM[1] <= ~ARG[10];- end if;- end process;-- ~SYM[7] : process(~ARG[4],~ARG[5]~VARS[9])- begin- if ~ARG[5] = ~IF~ISACTIVEHIGH[2]~THEN'1'~ELSE'0'~FI then- ~SYM[2] <= ~ARG[9];- elsif ~IF ~ISACTIVEENABLE[6] ~THEN ~ARG[6] and ~ELSE ~FI ~IF~ACTIVEEDGE[Rising][2]~THENfalling_edge~ELSErising_edge~FI(~ARG[4]) then- ~SYM[2] <= ~ARG[10];- end if;- end process;-- ~SYM[8] : process(~ARG[4],~ARG[5],~SYM[2])- begin- if ~ARG[5] = ~IF~ISACTIVEHIGH[2]~THEN'1'~ELSE'0'~FI then- ~SYM[3] <= ~ARG[7];- elsif ~IF ~ISACTIVEENABLE[6] ~THEN ~ARG[6] and ~ELSE ~FI ~IF~ACTIVEEDGE[Rising][2]~THENrising_edge~ELSEfalling_edge~FI(~ARG[4]) then- ~SYM[3] <= ~SYM[2];- end if;- end process;- ~FI- ~RESULT <= (~SYM[3], ~SYM[1]);-end block;--- ddrIn end"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.DDR.ddrOut#"- , "kind" : "Declaration"- , "type" :-"ddrOut# :: ( HasCallStack -- ARG[0]- , Undefined a -- ARG[1]- , KnownConfi~ fast domf -- ARG[2]- , KnownConfi~ slow doms -- ARG[3]- => Clock slow -- ARG[4]- -> Reset slow -- ARG[5]- -> Enable slow -- ARG[6]- -> a -- ARG[7]- -> Signal slow a -- ARG[8]- -> Signal slow a -- ARG[9]- -> Signal fast a"- , "template" :-"-- ddrOut begin-~GENSYM[~COMPNAME_ddrIn][0] : block- signal ~GENSYM[data_Pos][1] : ~TYP[7];- signal ~GENSYM[data_Neg][2] : ~TYP[7];-begin- ~IF ~ISSYNC[3] ~THEN- -- sync- -------------- ~GENSYM[~COMPNAME_ddrOut_pos][5] : process(~ARG[4])- begin- if ~IF~ACTIVEEDGE[Rising][2]~THENrising_edge~ELSEfalling_edge~FI(~ARG[4]) then- if ~ARG[5] = ~IF~ISACTIVEHIGH[2]~THEN'1'~ELSE'0'~FI then- ~SYM[1] <= ~ARG[7];- els~IF ~ISACTIVEENABLE[6] ~THENif ~ARG[6] then~ELSEe~FI- ~SYM[1] <= ~ARG[8];- end if;- end if;- end process;-- ~GENSYM[~COMPNAME_ddrOut_neg][6] : process(~ARG[4])- begin- if ~IF~ACTIVEEDGE[Rising][2]~THENrising_edge~ELSEfalling_edge~FI(~ARG[4]) then- if ~ARG[5] = ~IF~ISACTIVEHIGH[2]~THEN'1'~ELSE'0'~FI then- ~SYM[2] <= ~ARG[7];- els~IF ~ISACTIVEENABLE[6] ~THENif ~ARG[6] then~ELSEe~FI- ~SYM[2] <= ~ARG[9];- end if;- end if;- end process;- ~ELSE- -- async- --------------- ~SYM[5] : process(~ARG[4],~ARG[5]~VARS[8])- begin- if ~ARG[5] = ~IF~ISACTIVEHIGH[2]~THEN'1'~ELSE'0'~FI then- ~SYM[1] <= ~ARG[7];- elsif ~IF~ACTIVEEDGE[Rising][2]~THENrising_edge~ELSEfalling_edge~FI(~ARG[4]) then- ~SYM[1] <= ~ARG[8];- end if;- end process;-- ~SYM[6] : process(~ARG[4],~ARG[5]~VARS[9])- begin- if ~ARG[5] = ~IF~ISACTIVEHIGH[2]~THEN'1'~ELSE'0'~FI then- ~SYM[2] <= ~ARG[7];- elsif ~IF~ACTIVEEDGE[Rising][2]~THENrising_edge~ELSEfalling_edge~FI(~ARG[4]) then- ~SYM[2] <= ~ARG[9];- end if;- end process;- ~FI- ~RESULT <= ~IF~ACTIVEEDGE[Rising][2]~THEN~SYM[1]~ELSE~SYM[2]~FI when (~ARG[4] = '1' ~IF ~ISACTIVEENABLE[6] ~THEN and ~ARG[6] ~ELSE ~FI) else ~IF~ACTIVEEDGE[Rising][2]~THEN~SYM[2]~ELSE~SYM[1]~FI;-end block;--- ddrOut end"- }- }-]
+ prims/vhdl/Clash_Explicit_DDR.primitives.yaml view
@@ -0,0 +1,161 @@+- BlackBox:+ name: Clash.Explicit.DDR.ddrIn#+ kind: Declaration+ type: |-+ ddrIn# :: forall a slow fast n pFast enabled synchronous.+ ( HasCallStack -- ARG[0]+ , Undefined a -- ARG[1]+ , KnownConfi~ fast domf -- ARG[2]+ , KnownConfi~ slow doms -- ARG[3]+ => Clock slow -- ARG[4]+ -> Reset slow -- ARG[5]+ -> Enable slow -- ARG[6]+ -> a -- ARG[7]+ -> a -- ARG[8]+ -> a -- ARG[9]+ -> Signal fast a -- ARG[10]+ -> Signal slow (a,a)+ template: |-+ -- ddrIn begin+ ~GENSYM[~COMPNAME_ddrIn][0] : block+ signal ~GENSYM[data_Pos][1] : ~TYP[9];+ signal ~GENSYM[data_Neg][2] : ~TYP[9];+ signal ~GENSYM[data_Neg_Latch][3] : ~TYP[9];+ begin+ ~IF ~ISSYNC[3] ~THEN+ -- sync+ -------------+ ~GENSYM[~COMPNAME_ddrIn_pos][6] : process(~ARG[4])+ begin+ if ~IF~ACTIVEEDGE[Rising][2]~THENrising_edge~ELSEfalling_edge~FI(~ARG[4]) then+ if ~ARG[5] = ~IF~ISACTIVEHIGH[2]~THEN'1'~ELSE'0'~FI then+ ~SYM[1] <= ~ARG[8];+ els~IF ~ISACTIVEENABLE[6] ~THENif ~ARG[6] then~ELSEe~FI+ ~SYM[1] <= ~ARG[10];+ end if;+ end if;+ end process;++ ~GENSYM[~COMPNAME_ddrIn_neg][7] : process(~ARG[4])+ begin+ if ~IF~ACTIVEEDGE[Rising][2]~THENfalling_edge~ELSErising_edge~FI(~ARG[4]) then+ if ~ARG[5] = ~IF~ISACTIVEHIGH[2]~THEN'1'~ELSE'0'~FI then+ ~SYM[2] <= ~ARG[9];+ els~IF ~ISACTIVEENABLE[6] ~THENif ~ARG[6] then~ELSEe~FI+ ~SYM[2] <= ~ARG[10];+ end if;+ end if;+ end process;++ ~GENSYM[~COMPNAME_ddrIn_neg_latch][8] : process(~ARG[4])+ begin+ if ~IF~ACTIVEEDGE[Rising][2]~THENrising_edge~ELSEfalling_edge~FI(~ARG[4]) then+ if ~ARG[5] = ~IF~ISACTIVEHIGH[2]~THEN'1'~ELSE'0'~FI then+ ~SYM[3] <= ~ARG[7];+ els~IF ~ISACTIVEENABLE[6] ~THENif ~ARG[6] then~ELSEe~FI+ ~SYM[3] <= ~SYM[2];+ end if;+ end if;+ end process;+ ~ELSE+ -- async+ --------------+ ~SYM[6] : process(~ARG[4],~ARG[5]~VARS[9])+ begin+ if ~ARG[5] = ~IF~ISACTIVEHIGH[2]~THEN'1'~ELSE'0'~FI then+ ~SYM[1] <= ~ARG[8];+ elsif ~IF ~ISACTIVEENABLE[6] ~THEN ~ARG[6] and ~ELSE ~FI ~IF~ACTIVEEDGE[Rising][2]~THENrising_edge~ELSEfalling_edge~FI(~ARG[4]) then+ ~SYM[1] <= ~ARG[10];+ end if;+ end process;++ ~SYM[7] : process(~ARG[4],~ARG[5]~VARS[9])+ begin+ if ~ARG[5] = ~IF~ISACTIVEHIGH[2]~THEN'1'~ELSE'0'~FI then+ ~SYM[2] <= ~ARG[9];+ elsif ~IF ~ISACTIVEENABLE[6] ~THEN ~ARG[6] and ~ELSE ~FI ~IF~ACTIVEEDGE[Rising][2]~THENfalling_edge~ELSErising_edge~FI(~ARG[4]) then+ ~SYM[2] <= ~ARG[10];+ end if;+ end process;++ ~SYM[8] : process(~ARG[4],~ARG[5],~SYM[2])+ begin+ if ~ARG[5] = ~IF~ISACTIVEHIGH[2]~THEN'1'~ELSE'0'~FI then+ ~SYM[3] <= ~ARG[7];+ elsif ~IF ~ISACTIVEENABLE[6] ~THEN ~ARG[6] and ~ELSE ~FI ~IF~ACTIVEEDGE[Rising][2]~THENrising_edge~ELSEfalling_edge~FI(~ARG[4]) then+ ~SYM[3] <= ~SYM[2];+ end if;+ end process;+ ~FI+ ~RESULT <= (~SYM[3], ~SYM[1]);+ end block;+ -- ddrIn end+- BlackBox:+ name: Clash.Explicit.DDR.ddrOut#+ kind: Declaration+ type: |-+ ddrOut# :: ( HasCallStack -- ARG[0]+ , Undefined a -- ARG[1]+ , KnownConfi~ fast domf -- ARG[2]+ , KnownConfi~ slow doms -- ARG[3]+ => Clock slow -- ARG[4]+ -> Reset slow -- ARG[5]+ -> Enable slow -- ARG[6]+ -> a -- ARG[7]+ -> Signal slow a -- ARG[8]+ -> Signal slow a -- ARG[9]+ -> Signal fast a+ template: |-+ -- ddrOut begin+ ~GENSYM[~COMPNAME_ddrIn][0] : block+ signal ~GENSYM[data_Pos][1] : ~TYP[7];+ signal ~GENSYM[data_Neg][2] : ~TYP[7];+ begin+ ~IF ~ISSYNC[3] ~THEN+ -- sync+ -------------+ ~GENSYM[~COMPNAME_ddrOut_pos][5] : process(~ARG[4])+ begin+ if ~IF~ACTIVEEDGE[Rising][2]~THENrising_edge~ELSEfalling_edge~FI(~ARG[4]) then+ if ~ARG[5] = ~IF~ISACTIVEHIGH[2]~THEN'1'~ELSE'0'~FI then+ ~SYM[1] <= ~ARG[7];+ els~IF ~ISACTIVEENABLE[6] ~THENif ~ARG[6] then~ELSEe~FI+ ~SYM[1] <= ~ARG[8];+ end if;+ end if;+ end process;++ ~GENSYM[~COMPNAME_ddrOut_neg][6] : process(~ARG[4])+ begin+ if ~IF~ACTIVEEDGE[Rising][2]~THENrising_edge~ELSEfalling_edge~FI(~ARG[4]) then+ if ~ARG[5] = ~IF~ISACTIVEHIGH[2]~THEN'1'~ELSE'0'~FI then+ ~SYM[2] <= ~ARG[7];+ els~IF ~ISACTIVEENABLE[6] ~THENif ~ARG[6] then~ELSEe~FI+ ~SYM[2] <= ~ARG[9];+ end if;+ end if;+ end process;+ ~ELSE+ -- async+ --------------+ ~SYM[5] : process(~ARG[4],~ARG[5]~VARS[8])+ begin+ if ~ARG[5] = ~IF~ISACTIVEHIGH[2]~THEN'1'~ELSE'0'~FI then+ ~SYM[1] <= ~ARG[7];+ elsif ~IF~ACTIVEEDGE[Rising][2]~THENrising_edge~ELSEfalling_edge~FI(~ARG[4]) then+ ~SYM[1] <= ~ARG[8];+ end if;+ end process;++ ~SYM[6] : process(~ARG[4],~ARG[5]~VARS[9])+ begin+ if ~ARG[5] = ~IF~ISACTIVEHIGH[2]~THEN'1'~ELSE'0'~FI then+ ~SYM[2] <= ~ARG[7];+ elsif ~IF~ACTIVEEDGE[Rising][2]~THENrising_edge~ELSEfalling_edge~FI(~ARG[4]) then+ ~SYM[2] <= ~ARG[9];+ end if;+ end process;+ ~FI+ ~RESULT <= ~IF~ACTIVEEDGE[Rising][2]~THEN~SYM[1]~ELSE~SYM[2]~FI when (~ARG[4] = '1' ~IF ~ISACTIVEENABLE[6] ~THEN and ~ARG[6] ~ELSE ~FI) else ~IF~ACTIVEEDGE[Rising][2]~THEN~SYM[2]~ELSE~SYM[1]~FI;+ end block;+ -- ddrOut end
− prims/vhdl/Clash_Explicit_RAM.primitives
@@ -1,54 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Explicit.RAM.asyncRam#"- , "kind" : "Declaration"- , "type" :-"asyncRam#- :: ( HasCallStack -- ARG[0]- , KnownDomain wdom wconf -- ARG[1]- , KnownDomain rdom rconf ) -- ARG[2]- => Clock wdom -- ^ wclk, ARG[3]- -> Clock rdom -- ^ rclk, ARG[4]- -> Enable wdom -- ^ wen, ARG[5]- -> SNat n -- ^ sz, ARG[6]- -> Signal rdom Int -- ^ rd, ARG[7]- -> Signal wdom Bool -- ^ en, ARG[8]- -> Signal wdom Int -- ^ wr, ARG[9]- -> Signal wdom a -- ^ din, ARG[10]- -> Signal rdom a"- , "template" :-"-- asyncRam begin-~GENSYM[~COMPNAME_asyncRam][0] : block~IF ~VIVADO ~THEN- type ~GENSYM[RamType][4] is array(natural range <>) of std_logic_vector(~SIZE[~TYP[10]]-1 downto 0);~ELSE- type ~SYM[4] is array(natural range <>) of ~TYP[10];~FI- signal ~GENSYM[RAM][1] : ~SYM[4](0 to ~LIT[6]-1);- signal ~GENSYM[rd][2] : integer range 0 to ~LIT[6] - 1;- signal ~GENSYM[wr][3] : integer range 0 to ~LIT[6] - 1;-begin- ~SYM[2] <= to_integer(~ARG[7])- -- pragma translate_off- mod ~LIT[6]- -- pragma translate_on- ;-- ~SYM[3] <= to_integer(~ARG[9])- -- pragma translate_off- mod ~LIT[6]- -- pragma translate_on- ;- ~GENSYM[asyncRam_sync][7] : process(~ARG[3])- begin- if ~IF~ACTIVEEDGE[Rising][1]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3]) then- if (~ARG[8] ~IF ~ISACTIVEENABLE[5] ~THEN and ~ARG[5] ~ELSE ~FI) then~IF ~VIVADO ~THEN- ~SYM[1](~SYM[3]) <= ~TOBV[~ARG[10]][~TYP[10]];~ELSE- ~SYM[1](~SYM[3]) <= ~ARG[10];~FI- end if;- end if;- end process;- ~IF ~VIVADO ~THEN- ~RESULT <= ~FROMBV[~SYM[1](~SYM[2])][~TYP[10]];~ELSE- ~RESULT <= ~SYM[1](~SYM[2]);~FI-end block;--- asyncRam end"- }- }-]
+ prims/vhdl/Clash_Explicit_RAM.primitives.yaml view
@@ -0,0 +1,52 @@+- BlackBox:+ name: Clash.Explicit.RAM.asyncRam#+ kind: Declaration+ type: |-+ asyncRam#+ :: ( HasCallStack -- ARG[0]+ , KnownDomain wdom -- ARG[1]+ , KnownDomain rdom -- ARG[2]+ , NFDataX a ) -- ARG[3]+ => Clock wdom -- ^ wclk, ARG[4]+ -> Clock rdom -- ^ rclk, ARG[5]+ -> Enable wdom -- ^ wen, ARG[6]+ -> SNat n -- ^ sz, ARG[7]+ -> Signal rdom Int -- ^ rd, ARG[8]+ -> Signal wdom Bool -- ^ en, ARG[9]+ -> Signal wdom Int -- ^ wr, ARG[10]+ -> Signal wdom a -- ^ din, ARG[11]+ -> Signal rdom a+ template: |-+ -- asyncRam begin+ ~GENSYM[~COMPNAME_asyncRam][0] : block~IF ~VIVADO ~THEN+ type ~GENSYM[RamType][4] is array(natural range <>) of std_logic_vector(~SIZE[~TYP[11]]-1 downto 0);~ELSE+ type ~SYM[4] is array(natural range <>) of ~TYP[11];~FI+ signal ~GENSYM[RAM][1] : ~SYM[4](0 to ~LIT[7]-1);+ signal ~GENSYM[rd][2] : integer range 0 to ~LIT[7] - 1;+ signal ~GENSYM[wr][3] : integer range 0 to ~LIT[7] - 1;+ begin+ ~SYM[2] <= to_integer(~VAR[rdI][8](31 downto 0))+ -- pragma translate_off+ mod ~LIT[7]+ -- pragma translate_on+ ;++ ~SYM[3] <= to_integer(~VAR[wrI][10](31 downto 0))+ -- pragma translate_off+ mod ~LIT[7]+ -- pragma translate_on+ ;+ ~GENSYM[asyncRam_sync][7] : process(~ARG[4])+ begin+ if ~IF~ACTIVEEDGE[Rising][1]~THENrising_edge~ELSEfalling_edge~FI(~ARG[4]) then+ if (~ARG[9] ~IF ~ISACTIVEENABLE[6] ~THEN and ~ARG[6] ~ELSE ~FI) then~IF ~VIVADO ~THEN+ ~SYM[1](~SYM[3]) <= ~TOBV[~ARG[11]][~TYP[11]];~ELSE+ ~SYM[1](~SYM[3]) <= ~ARG[11];~FI+ end if;+ end if;+ end process;+ ~IF ~VIVADO ~THEN+ ~RESULT <= ~FROMBV[~SYM[1](~SYM[2])][~TYP[11]];~ELSE+ ~RESULT <= ~SYM[1](~SYM[2]);~FI+ end block;+ -- asyncRam end
− prims/vhdl/Clash_Explicit_ROM.primitives
@@ -1,37 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Explicit.ROM.rom#"- , "kind" : "Declaration"- , "type" :-"rom# :: ( KnownDomain dom ARG[0]- , KnownNat n -- ARG[1]- , Undefined a ) -- ARG[2]- => Clock dom -- clk, ARG[3]- -> Enable dom -- en, ARG[4]- -> Vec n a -- init, ARG[5]- -> Signal dom Int -- rd, ARG[6]- -> Signal dom a"- , "template" :-"-- rom begin-~GENSYM[~COMPNAME_rom][1] : block- signal ~GENSYM[ROM][2] : ~TYP[5];- signal ~GENSYM[rd][3] : integer range 0 to ~LIT[1]-1;-begin- ~SYM[2] <= ~LIT[5];-- ~SYM[3] <= to_integer(~ARG[6])- -- pragma translate_off- mod ~LIT[1]- -- pragma translate_on- ;- ~GENSYM[romSync][6] : process (~ARG[3])- begin- if (~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3])~IF ~ISACTIVEENABLE[4] ~THEN and ~ARG[4] ~ELSE ~FI) then~IF ~VIVADO ~THEN- ~RESULT <= ~FROMBV[~SYM[2](~SYM[3])][~TYPO];~ELSE- ~RESULT <= ~SYM[2](~SYM[3]);~FI- end if;- end process;-end block;--- rom end"- }- }-]
+ prims/vhdl/Clash_Explicit_ROM.primitives.yaml view
@@ -0,0 +1,34 @@+- BlackBox:+ name: Clash.Explicit.ROM.rom#+ kind: Declaration+ type: |-+ rom# :: ( KnownDomain dom ARG[0]+ , KnownNat n -- ARG[1]+ , Undefined a ) -- ARG[2]+ => Clock dom -- clk, ARG[3]+ -> Enable dom -- en, ARG[4]+ -> Vec n a -- init, ARG[5]+ -> Signal dom Int -- rd, ARG[6]+ -> Signal dom a+ template: |-+ -- rom begin+ ~GENSYM[~COMPNAME_rom][1] : block+ signal ~GENSYM[ROM][2] : ~TYP[5];+ signal ~GENSYM[rd][3] : integer range 0 to ~LIT[1]-1;+ begin+ ~SYM[2] <= ~CONST[5];++ ~SYM[3] <= to_integer(~VAR[rdI][6](31 downto 0))+ -- pragma translate_off+ mod ~LIT[1]+ -- pragma translate_on+ ;+ ~GENSYM[romSync][6] : process (~ARG[3])+ begin+ if (~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3])~IF ~ISACTIVEENABLE[4] ~THEN and ~ARG[4] ~ELSE ~FI) then~IF ~VIVADO ~THEN+ ~RESULT <= ~FROMBV[~SYM[2](~SYM[3])][~TYPO];~ELSE+ ~RESULT <= ~SYM[2](~SYM[3]);~FI+ end if;+ end process;+ end block;+ -- rom end
+ prims/vhdl/Clash_Explicit_ROM_Blob.primitives.yaml view
@@ -0,0 +1,32 @@+- BlackBox:+ name: Clash.Explicit.ROM.Blob.romBlob#+ kind: Declaration+ type: |-+ romBlob#+ :: KnownDomain dom -- ARG[0]+ => Clock dom -- clk, ARG[1]+ -> Enable dom -- en, ARG[2]+ -> MemBlob n m -- init, ARG[3]+ -> Signal dom Int -- rd, ARG[4]+ -> Signal dom (BitVector m)+ template: |-+ -- romBlob begin+ ~GENSYM[~COMPNAME_rom][1] : block+ signal ~GENSYM[ROM][2] : ~TYP[3];+ signal ~GENSYM[rd][3] : integer range 0 to ~LENGTH[~TYP[3]]-1;+ begin+ ~SYM[2] <= ~CONST[3];++ ~SYM[3] <= to_integer(~VAR[rdI][4](31 downto 0))+ -- pragma translate_off+ mod ~LENGTH[~TYP[3]]+ -- pragma translate_on+ ;+ ~GENSYM[romSync][6] : process (~ARG[1])+ begin+ if (~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[1])~IF~ISACTIVEENABLE[2]~THEN and ~ARG[2]~ELSE~FI) then+ ~RESULT <= ~SYM[2](~SYM[3]);+ end if;+ end process;+ end block;+ -- romBlob end
− prims/vhdl/Clash_Explicit_ROM_File.primitives
@@ -1,57 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Explicit.ROM.File.romFile#"- , "kind" : "Declaration"- , "type" :-"romFile# :: ( KnownNat m -- ARG[0]- , KnownDomain dom -- ARG[1]- => Clock dom -- clk, ARG[2]- -> Enable dom -- en, ARG[3]- -> SNat n -- sz, ARG[4]- -> FilePath -- file, ARG[5]- -> Signal dom Int -- rd, ARG[6]- -> Signal dom (BitVector m)"- , "template" :-"-- romFile begin-~GENSYM[~COMPNAME_romFile][0] : block- type ~GENSYM[RomType][4] is array(natural range <>) of bit_vector(~LIT[0]-1 downto 0);-- impure function ~GENSYM[InitRomFromFile][1] (RomFileName : in string) return ~SYM[4] is- FILE RomFile : text open read_mode is RomFileName;- variable RomFileLine : line;- variable ROM : ~SYM[4](0 to ~LIT[4]-1);- begin- for i in ROM'range loop- readline(RomFile,RomFileLine);- read(RomFileLine,ROM(i));- end loop;- return ROM;- end function;-- signal ~GENSYM[ROM][2] : ~SYM[4](0 to ~LIT[4]-1) := ~SYM[1](~FILE[~LIT[5]]);- signal ~GENSYM[rd][3] : integer range 0 to ~LIT[4]-1;-begin- ~SYM[3] <= to_integer(~ARG[6])- -- pragma translate_off- mod ~LIT[4]- -- pragma translate_on- ;- ~IF ~ISACTIVEENABLE[3] ~THEN- ~GENSYM[romFileSync][7] : process (~ARG[2])- begin- if (~IF~ACTIVEEDGE[Rising][1]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2])) then- if ~ARG[3] then- ~RESULT <= to_stdlogicvector(~SYM[2](~SYM[3]));- end if;- end if;- end process;~ELSE- ~SYM[7] : process (~ARG[2])- begin- if (~IF~ACTIVEEDGE[Rising][1]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2])) then- ~RESULT <= to_stdlogicvector(~SYM[2](~SYM[3]));- end if;- end process;~FI-end block;--- romFile end"- }- }-]
+ prims/vhdl/Clash_Explicit_ROM_File.primitives.yaml view
@@ -0,0 +1,54 @@+- BlackBox:+ name: Clash.Explicit.ROM.File.romFile#+ kind: Declaration+ type: |-+ romFile# :: ( KnownNat m -- ARG[0]+ , KnownDomain dom -- ARG[1]+ => Clock dom -- clk, ARG[2]+ -> Enable dom -- en, ARG[3]+ -> SNat n -- sz, ARG[4]+ -> FilePath -- file, ARG[5]+ -> Signal dom Int -- rd, ARG[6]+ -> Signal dom (BitVector m)+ template: |-+ -- romFile begin+ ~GENSYM[~COMPNAME_romFile][0] : block+ type ~GENSYM[RomType][4] is array(natural range <>) of bit_vector(~LIT[0]-1 downto 0);++ impure function ~GENSYM[InitRomFromFile][1] (RomFileName : in string) return ~SYM[4] is+ FILE RomFile : text open read_mode is RomFileName;+ variable RomFileLine : line;+ variable ROM : ~SYM[4](0 to ~LIT[4]-1);+ begin+ for i in ROM'range loop+ readline(RomFile,RomFileLine);+ read(RomFileLine,ROM(i));+ end loop;+ return ROM;+ end function;++ signal ~GENSYM[ROM][2] : ~SYM[4](0 to ~LIT[4]-1) := ~SYM[1](~FILE[~LIT[5]]);+ signal ~GENSYM[rd][3] : integer range 0 to ~LIT[4]-1;+ begin+ ~SYM[3] <=to_integer(~VAR[rdI][6](31 downto 0))+ -- pragma translate_off+ mod ~LIT[4]+ -- pragma translate_on+ ;+ ~IF ~ISACTIVEENABLE[3] ~THEN+ ~GENSYM[romFileSync][7] : process (~ARG[2])+ begin+ if (~IF~ACTIVEEDGE[Rising][1]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2])) then+ if ~ARG[3] then+ ~RESULT <= to_stdlogicvector(~SYM[2](~SYM[3]));+ end if;+ end if;+ end process;~ELSE+ ~SYM[7] : process (~ARG[2])+ begin+ if (~IF~ACTIVEEDGE[Rising][1]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2])) then+ ~RESULT <= to_stdlogicvector(~SYM[2](~SYM[3]));+ end if;+ end process;~FI+ end block;+ -- romFile end
− prims/vhdl/Clash_Explicit_SimIO.primitives
@@ -1,31 +0,0 @@-[ { "Primitive" :- { "name" : "Clash.Explicit.SimIO.mealyIO"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Explicit.SimIO.fmapSimIO#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Explicit.SimIO.pureSimIO#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Explicit.SimIO.apSimIO#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Explicit.SimIO.bindSimIO#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Explicit.SimIO.unSimIO#"- , "primType" : "Function"- }- }-]
+ prims/vhdl/Clash_Explicit_SimIO.primitives.yaml view
@@ -0,0 +1,18 @@+- Primitive:+ name: Clash.Explicit.SimIO.mealyIO+ primType: Function+- Primitive:+ name: Clash.Explicit.SimIO.fmapSimIO#+ primType: Function+- Primitive:+ name: Clash.Explicit.SimIO.pureSimIO#+ primType: Function+- Primitive:+ name: Clash.Explicit.SimIO.apSimIO#+ primType: Function+- Primitive:+ name: Clash.Explicit.SimIO.bindSimIO#+ primType: Function+- Primitive:+ name: Clash.Explicit.SimIO.unSimIO#+ primType: Function
− prims/vhdl/Clash_Explicit_Testbench.primitives
@@ -1,199 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Explicit.Testbench.assert"- , "kind" : "Declaration"- , "type" :-"assert- :: (KnownDomain dom, Eq a, ShowX a) -- (ARG[0],ARG[1],ARG[2])- => Clock dom -- ARG[3]- -> Reset dom -- ARG[4]- -> String -- ARG[5]- -> Signal dom a -- Checked value (ARG[6])- -> Signal dom a -- Expected value (ARG[7])- -> Signal dom b -- Return valued (ARG[8])- -> Signal dom b"- , "imports": ["~INCLUDENAME[0].all"]- , "includes" :- [ { "name" : "slv2string"- , "extension" : "vhdl"- , "template" :-"-- helper function of Clash.Explicit.Testbench.assert-library IEEE;-use IEEE.STD_LOGIC_1164.ALL;--package ~INCLUDENAME[0] is- function slv2string (slv : std_logic_vector) return STRING;-end;--package body ~INCLUDENAME[0] is- function slv2string (slv : std_logic_vector) return STRING is- variable result : string (1 to slv'length);- variable res_l : string (1 to 3);- variable r : integer;- begin- r := 1;- for i in slv'range loop- res_l := std_logic'image(slv(i));- result(r) := res_l(2);- r := r + 1;- end loop;- return result;- end slv2string;-end;"- }- ]- , "template" :-"-- assert begin-~GENSYM[assert][0] : block- -- pragma translate_off- signal ~GENSYM[actual][2] : ~TYP[6];- signal ~GENSYM[expected][3] : ~TYP[7];- -- pragma translate_on-begin- -- pragma translate_off- ~SYM[2] <= ~ARG[6];- ~SYM[3] <= ~ARG[7];- process(~ARG[3]) is- begin- if (~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3])) then- assert (toSLV(~SYM[2]) = toSLV(~SYM[3])) report (~LIT[5] & \", expected: \" & ~INCLUDENAME[0].slv2string(toSLV(~SYM[3])) & \", actual: \" & ~INCLUDENAME[0].slv2string(toSLV(~SYM[2]))) severity error;- end if;- end process;- -- pragma translate_on- ~RESULT <= ~ARG[8];-end block;--- assert end"- }- }-,{ "BlackBox" :- { "name" : "Clash.Explicit.Testbench.assertBitVector"- , "kind" : "Declaration"- , "type" :-"assertBitVector- :: ( KnownDomain dom -- ARG[0]- , KnownNat n ) -- ARG[1]- => Clock dom -- ARG[2]- -> Reset dom -- ARG[3]- -> String -- ARG[4]- -> Signal dom (BitVector n) -- Checked value (ARG[5])- -> Signal dom (BitVector n) -- Expected value (ARG[6])- -> Signal dom b -- Return valued (ARG[7])- -> Signal dom b"- , "imports" : ["~INCLUDENAME[0].all"]- , "includes" :- [{ "name" : "assertBitVector"- , "extension" : "vhdl"- , "template" :-"-- helper functions of Clash.Explicit.Testbench.assertBitVector-library IEEE;-use IEEE.STD_LOGIC_1164.ALL;--package ~INCLUDENAME[0] is- function non_std_match (l, r : std_logic_vector) return boolean;- function slv2string (slv : std_logic_vector) return STRING;-end;--package body ~INCLUDENAME[0] is- type match_table_type is array (std_ulogic, std_ulogic) of boolean;- constant match_table: match_table_type :=- ('0' | 'L' => ('0' | 'L' | '-' => true, others => false),- '1' | 'H' => ('1' | 'H' | '-' => true, others => false),- '-' => ('-' => true, others => false),- others => ('-' => true, others => false)- );- -- non_std_match is like std_match- -- But only accepts '-' as don't care in its the second argument r.- function non_std_match (l, r : std_logic_vector) return boolean is- alias la : std_logic_vector (l'length downto 1) is l;- alias ra : std_logic_vector (r'length downto 1) is r;- begin- for i in l'range loop- if not match_table (l (i), r (i)) then- return false;- end if;- end loop;- return true;- end non_std_match;-- function slv2string (slv : std_logic_vector) return STRING is- variable result : string (1 to slv'length);- variable res_l : string (1 to 3);- variable r : integer;- begin- r := 1;- for i in slv'range loop- res_l := std_logic'image(slv(i));- result(r) := res_l(2);- r := r + 1;- end loop;- return result;- end slv2string;--end;-"- }]- , "template" :-"-- assertBitVector begin-~GENSYM[assert][0] : block- -- pragma translate_off- signal ~GENSYM[actual][2] : ~TYP[5];- signal ~GENSYM[expected][3] : ~TYP[6];- -- pragma translate_on-begin- -- pragma translate_off- ~SYM[2] <= ~ARG[5];- ~SYM[3] <= ~ARG[6];- process(~ARG[2]) is- begin- if (~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2])) then- assert (~INCLUDENAME[0].non_std_match(toSLV(~SYM[2]),toSLV(~SYM[3]))) report (~LIT[4] & \", expected: \" & ~INCLUDENAME[0].slv2string(toSLV(~SYM[3])) & \", actual: \" & ~INCLUDENAME[0].slv2string(toSLV(~SYM[2]))) severity error;- end if;- end process;- -- pragma translate_on- ~RESULT <= ~ARG[7];-end block;--- assertBitVector end"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.Testbench.tbClockGen"- , "workInfo" : "Always"- , "kind" : "Declaration"- , "warning" : "Clash.Signal.Internal.tbClockGen is not synthesizable!"- , "type" :-"tbClockGen- :: KnownDomain dom -- ARG[0]- => Signal dom Bool -- ARG[1]- -> Clock dom"- , "comment" :- "ModelSim and Vivado seem to round time values to an integer number of picoseconds.- Use two half periods to prevent rounding errors from affecting the full period."- , "template" :-"-- tbClockGen begin--- pragma translate_off-~GENSYM[clkGen][0] : process is- constant ~GENSYM[half_periodH][1] : time := ~PERIOD[0]000 fs / 2;- constant ~GENSYM[half_periodL][2] : time := ~PERIOD[0]000 fs - ~SYM[1];-begin- ~RESULT <= ~IF~ACTIVEEDGE[Rising][0]~THEN'0'~ELSE'1'~FI;- wait for 3000 ps;- while ~ARG[1] loop- ~RESULT <= not ~RESULT;- wait for ~SYM[1];- ~RESULT <= not ~RESULT;- wait for ~SYM[2];- end loop;- wait;-end process;--- pragma translate_on--- tbClockGen end"- }- }-, { "BlackBox" :- { "name" : "Clash.Explicit.Testbench.tbEnableGen"- , "workInfo" : "Always"- , "kind" : "Declaration"- , "type" : "tbEnableGen :: Enable dom"- , "template" : "~RESULT <= true;"- }- }-]
+ prims/vhdl/Clash_Explicit_Testbench.primitives.yaml view
@@ -0,0 +1,189 @@+- BlackBox:+ name: Clash.Explicit.Testbench.assert+ imports:+ - ~INCLUDENAME[0].all+ includes:+ - name: slv2string+ extension: vhdl+ template: |-+ -- helper function of Clash.Explicit.Testbench.assert+ library IEEE;+ use IEEE.STD_LOGIC_1164.ALL;++ package ~INCLUDENAME[0] is+ function slv2string (slv : std_logic_vector) return STRING;+ end;++ package body ~INCLUDENAME[0] is+ function slv2string (slv : std_logic_vector) return STRING is+ variable result : string (1 to slv'length);+ variable res_l : string (1 to 3);+ variable r : integer;+ begin+ r := 1;+ for i in slv'range loop+ res_l := std_logic'image(slv(i));+ result(r) := res_l(2);+ r := r + 1;+ end loop;+ return result;+ end slv2string;+ end;+ kind: Declaration+ type: |-+ assert+ :: (KnownDomain dom, Eq a, ShowX a) -- (ARG[0],ARG[1],ARG[2])+ => Clock dom -- ARG[3]+ -> Reset dom -- ARG[4]+ -> String -- ARG[5]+ -> Signal dom a -- Checked value (ARG[6])+ -> Signal dom a -- Expected value (ARG[7])+ -> Signal dom b -- Return valued (ARG[8])+ -> Signal dom b+ template: |-+ -- assert begin+ ~GENSYM[assert][0] : block+ -- pragma translate_off+ signal ~GENSYM[actual][2] : ~TYP[6];+ signal ~GENSYM[expected][3] : ~TYP[7];+ -- pragma translate_on+ begin+ -- pragma translate_off+ ~SYM[2] <= ~ARG[6];+ ~SYM[3] <= ~ARG[7];+ process(~ARG[3]) is+ begin+ if (~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[3])) then+ assert (toSLV(~SYM[2]) = toSLV(~SYM[3])) report (~LIT[5] & ", expected: " & ~INCLUDENAME[0].slv2string(toSLV(~SYM[3])) & ", actual: " & ~INCLUDENAME[0].slv2string(toSLV(~SYM[2]))) severity error;+ end if;+ end process;+ -- pragma translate_on+ ~RESULT <= ~ARG[8];+ end block;+ -- assert end+- BlackBox:+ name: Clash.Explicit.Testbench.assertBitVector+ imports:+ - ~INCLUDENAME[0].all+ includes:+ - name: assertBitVector+ extension: vhdl+ template: |+ -- helper functions of Clash.Explicit.Testbench.assertBitVector+ library IEEE;+ use IEEE.STD_LOGIC_1164.ALL;++ package ~INCLUDENAME[0] is+ function non_std_match (l, r : std_logic_vector) return boolean;+ function slv2string (slv : std_logic_vector) return STRING;+ end;++ package body ~INCLUDENAME[0] is+ type match_table_type is array (std_ulogic, std_ulogic) of boolean;+ constant match_table: match_table_type :=+ ('0' | 'L' => ('0' | 'L' | '-' => true, others => false),+ '1' | 'H' => ('1' | 'H' | '-' => true, others => false),+ '-' => ('-' => true, others => false),+ others => ('-' => true, others => false)+ );+ -- non_std_match is like std_match+ -- But only accepts '-' as don't care in its the second argument r.+ function non_std_match (l, r : std_logic_vector) return boolean is+ alias la : std_logic_vector (l'length downto 1) is l;+ alias ra : std_logic_vector (r'length downto 1) is r;+ begin+ for i in l'range loop+ if not match_table (l (i), r (i)) then+ return false;+ end if;+ end loop;+ return true;+ end non_std_match;++ function slv2string (slv : std_logic_vector) return STRING is+ variable result : string (1 to slv'length);+ variable res_l : string (1 to 3);+ variable r : integer;+ begin+ r := 1;+ for i in slv'range loop+ res_l := std_logic'image(slv(i));+ result(r) := res_l(2);+ r := r + 1;+ end loop;+ return result;+ end slv2string;++ end;+ kind: Declaration+ type: |-+ assertBitVector+ :: ( KnownDomain dom -- ARG[0]+ , KnownNat n ) -- ARG[1]+ => Clock dom -- ARG[2]+ -> Reset dom -- ARG[3]+ -> String -- ARG[4]+ -> Signal dom (BitVector n) -- Checked value (ARG[5])+ -> Signal dom (BitVector n) -- Expected value (ARG[6])+ -> Signal dom b -- Return valued (ARG[7])+ -> Signal dom b+ template: |-+ -- assertBitVector begin+ ~GENSYM[assert][0] : block+ -- pragma translate_off+ signal ~GENSYM[actual][2] : ~TYP[5];+ signal ~GENSYM[expected][3] : ~TYP[6];+ -- pragma translate_on+ begin+ -- pragma translate_off+ ~SYM[2] <= ~ARG[5];+ ~SYM[3] <= ~ARG[6];+ process(~ARG[2]) is+ begin+ if (~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2])) then+ assert (~INCLUDENAME[0].non_std_match(toSLV(~SYM[2]),toSLV(~SYM[3]))) report (~LIT[4] & ", expected: " & ~INCLUDENAME[0].slv2string(toSLV(~SYM[3])) & ", actual: " & ~INCLUDENAME[0].slv2string(toSLV(~SYM[2]))) severity error;+ end if;+ end process;+ -- pragma translate_on+ ~RESULT <= ~ARG[7];+ end block;+ -- assertBitVector end+- BlackBox:+ name: Clash.Explicit.Testbench.tbClockGen+ comment: |-+ ModelSim and Vivado seem to round time values to an integer number of picoseconds.+ Use two half periods to prevent rounding errors from affecting the full period.+ kind: Declaration+ type: |-+ tbClockGen+ :: KnownDomain dom -- ARG[0]+ => Signal dom Bool -- ARG[1]+ -> Clock dom+ template: |-+ -- tbClockGen begin+ -- pragma translate_off+ ~GENSYM[clkGen][0] : process is+ constant ~GENSYM[half_periodH][1] : time := ~PERIOD[0]000 fs / 2;+ constant ~GENSYM[half_periodL][2] : time := ~PERIOD[0]000 fs - ~SYM[1];+ begin+ ~RESULT <= ~IF~ACTIVEEDGE[Rising][0]~THEN'0'~ELSE'1'~FI;+ wait for ~LONGESTPERIOD ps;+ while ~ARG[1] loop+ ~RESULT <= not ~RESULT;+ wait for ~SYM[1];+ ~RESULT <= not ~RESULT;+ wait for ~SYM[2];+ end loop;+ wait;+ end process;+ -- pragma translate_on+ -- tbClockGen end+ warning: Clash.Signal.Internal.tbClockGen is not synthesizable!+ workInfo: Always+- BlackBox:+ name: Clash.Explicit.Testbench.tbEnableGen+ kind: Declaration+ type: 'tbEnableGen ::+ Enable dom'+ template: ~RESULT <= true;+ workInfo: Always
− prims/vhdl/Clash_Intel_DDR.primitives
@@ -1,97 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Intel.DDR.altddioIn"- , "kind" : "Declaration"- , "type" :-"altddioIn- :: ( HasCallStack -- ARG[0]- , KnownConfi~ fast domf -- ARG[1]- , KnownConfi~ slow doms -- ARG[2]- , KnownNat m ) -- ARG[3]- => SSymbol deviceFamily -- ARG[4]- -> Clock slow -- ARG[5]- -> Reset slow -- ARG[6]- -> Enable slow -- ARG[7]- -> Signal fast (BitVector m) -- ARG[8]- -> Signal slow (BitVector m,BitVector m)"- , "libraries" : ["altera_mf"]- , "imports" : ["altera_mf.altera_mf_components.all"]- , "template" :-"-- altddioIn begin-~GENSYM[~COMPNAME_ALTDDIO_IN][0] : block- signal ~GENSYM[dataout_l][1] : ~TYP[8];- signal ~GENSYM[dataout_h][2] : ~TYP[8];~IF ~ISACTIVEENABLE[7] ~THEN- signal ~GENSYM[ce_logic][4]: std_logic;~ELSE ~FI-begin~IF ~ISACTIVEENABLE[5] ~THEN- ~SYM[4] <= '1' when (~ARG[7]) else '0';~ELSE ~FI- ~GENSYM[~COMPNAME_ALTDDIO_IN][7] : ALTDDIO_IN- GENERIC MAP (- intended_device_family => ~LIT[4],- invert_input_clocks => \"OFF\",- lpm_hint => \"UNUSED\",- lpm_type => \"altddio_in\",- power_up_high => \"OFF\",- width => ~SIZE[~TYP[8]]- )- PORT MAP (~IF ~ISSYNC[6] ~THEN- sclr => ~ARG[6],~ELSE- aclr => ~ARG[6],~FI- datain => ~ARG[8],~IF ~ISACTIVEENABLE[5] ~THEN- inclocken => ~SYM[4],~ELSE ~FI- inclock => ~ARG[5],- dataout_h => ~SYM[2],- dataout_l => ~SYM[1]- );- ~RESULT <= (~SYM[1],~SYM[2]);-end block;--- altddioIn end"- }- }-, { "BlackBox" :- { "name" : "Clash.Intel.DDR.altddioOut#"- , "kind" : "Declaration"- , "type" :-"altddioOut#- :: ( HasCallStack -- ARG[0]- , KnownConfi~ fast domf -- ARG[1]- , KnownConfi~ slow doms -- ARG[2]- , KnownNat m ) -- ARG[3]- => SSymbol deviceFamily -- ARG[4]- -> Clock slow -- ARG[5]- -> Reset slow -- ARG[6]- -> Enable slow -- ARG[7]- -> Signal slow (BitVector m) -- ARG[8]- -> Signal slow (BitVector m) -- ARG[9]- -> Signal fast (BitVector m)"- , "libraries" : ["altera_mf"]- , "imports" : ["altera_mf.altera_mf_components.all"]- , "template" :-"-- altddioOut begin-~GENSYM[~COMPNAME_ALTDDIO_OUT][0] : block ~IF ~ISACTIVEENABLE[7] ~THEN- signal ~GENSYM[ce_logic][1] : std_logic; ~ELSE ~FI-begin~IF ~ISACTIVEENABLE[7] ~THEN- ~SYM[3] <= '1' when (~ARG[7]) else '0'; ~ELSE ~FI- ~GENSYM[~COMPNAME_ALTDDIO_OUT][7] : ALTDDIO_OUT- GENERIC MAP (- extend_oe_disable => \"OFF\",- intended_device_family => ~LIT[4],- invert_output => \"OFF\",- lpm_hint => \"UNUSED\",- lpm_type => \"altddio_out\",- oe_reg => \"UNREGISTERED\",- power_up_high => \"OFF\",- width => ~SIZE[~TYPO]- )- PORT MAP (~IF ~ISSYNC[2] ~THEN- sclr => ~ARG[6],~ELSE- aclr => ~ARG[6],~FI ~IF ~ISACTIVEENABLE[7] ~THEN- outclocken => ~SYM[1],~ELSE ~FI- outclock => ~ARG[5],- datain_h => ~ARG[7],- datain_l => ~ARG[8],- dataout => ~RESULT- );-end block;--- altddioOut end"- }- }-]
+ prims/vhdl/Clash_Intel_DDR.primitives.yaml view
@@ -0,0 +1,96 @@+- BlackBox:+ name: Clash.Intel.DDR.altddioIn+ imports:+ - altera_mf.altera_mf_components.all+ kind: Declaration+ libraries:+ - altera_mf+ type: |-+ altddioIn+ :: ( HasCallStack -- ARG[0]+ , KnownConfi~ fast domf -- ARG[1]+ , KnownConfi~ slow doms -- ARG[2]+ , KnownNat m ) -- ARG[3]+ => SSymbol deviceFamily -- ARG[4]+ -> Clock slow -- ARG[5]+ -> Reset slow -- ARG[6]+ -> Enable slow -- ARG[7]+ -> Signal fast (BitVector m) -- ARG[8]+ -> Signal slow (BitVector m,BitVector m)+ template: |-+ -- altddioIn begin+ ~GENSYM[~COMPNAME_ALTDDIO_IN][0] : block+ signal ~GENSYM[dataout_l][1] : ~TYP[8];+ signal ~GENSYM[dataout_h][2] : ~TYP[8];~IF ~ISACTIVEENABLE[7] ~THEN+ signal ~GENSYM[ce_logic][4]: std_logic;~ELSE ~FI+ begin~IF ~ISACTIVEENABLE[5] ~THEN+ ~SYM[4] <= '1' when (~ARG[7]) else '0';~ELSE ~FI+ ~GENSYM[~COMPNAME_ALTDDIO_IN][7] : ALTDDIO_IN+ GENERIC MAP (+ intended_device_family => ~LIT[4],+ invert_input_clocks => "OFF",+ lpm_hint => "UNUSED",+ lpm_type => "altddio_in",+ power_up_high => "OFF",+ width => ~SIZE[~TYP[8]]+ )+ PORT MAP (~IF ~ISSYNC[6] ~THEN+ sclr => ~ARG[6],~ELSE+ aclr => ~ARG[6],~FI+ datain => ~ARG[8],~IF ~ISACTIVEENABLE[5] ~THEN+ inclocken => ~SYM[4],~ELSE ~FI+ inclock => ~ARG[5],+ dataout_h => ~SYM[2],+ dataout_l => ~SYM[1]+ );+ ~RESULT <= (~SYM[1],~SYM[2]);+ end block;+ -- altddioIn end+- BlackBox:+ name: Clash.Intel.DDR.altddioOut#+ imports:+ - altera_mf.altera_mf_components.all+ kind: Declaration+ libraries:+ - altera_mf+ type: |-+ altddioOut#+ :: ( HasCallStack -- ARG[0]+ , KnownConfi~ fast domf -- ARG[1]+ , KnownConfi~ slow doms -- ARG[2]+ , KnownNat m ) -- ARG[3]+ => SSymbol deviceFamily -- ARG[4]+ -> Clock slow -- ARG[5]+ -> Reset slow -- ARG[6]+ -> Enable slow -- ARG[7]+ -> Signal slow (BitVector m) -- ARG[8]+ -> Signal slow (BitVector m) -- ARG[9]+ -> Signal fast (BitVector m)+ template: |-+ -- altddioOut begin+ ~GENSYM[~COMPNAME_ALTDDIO_OUT][0] : block ~IF ~ISACTIVEENABLE[7] ~THEN+ signal ~GENSYM[ce_logic][1] : std_logic; ~ELSE ~FI+ begin~IF ~ISACTIVEENABLE[7] ~THEN+ ~SYM[3] <= '1' when (~ARG[7]) else '0'; ~ELSE ~FI+ ~GENSYM[~COMPNAME_ALTDDIO_OUT][7] : ALTDDIO_OUT+ GENERIC MAP (+ extend_oe_disable => "OFF",+ intended_device_family => ~LIT[4],+ invert_output => "OFF",+ lpm_hint => "UNUSED",+ lpm_type => "altddio_out",+ oe_reg => "UNREGISTERED",+ power_up_high => "OFF",+ width => ~SIZE[~TYPO]+ )+ PORT MAP (~IF ~ISSYNC[2] ~THEN+ sclr => ~ARG[6],~ELSE+ aclr => ~ARG[6],~FI ~IF ~ISACTIVEENABLE[7] ~THEN+ outclocken => ~SYM[1],~ELSE ~FI+ outclock => ~ARG[5],+ datain_h => ~ARG[7],+ datain_l => ~ARG[8],+ dataout => ~RESULT+ );+ end block;+ -- altddioOut end
− prims/vhdl/Clash_Magic.primitives
@@ -1,13 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Magic.nameHint"- , "kind" : "Declaration"- , "type" :-"nameHint- :: SSymbol sym -- ARG[0]- -> a -- ARG[1]- -> a"- , "resultName" : { "template" : "~NAME[0]" }- , "template" : "~RESULT <= ~ARG[1];"- }- }-]
+ prims/vhdl/Clash_Magic.primitives.yaml view
@@ -0,0 +1,11 @@+- BlackBox:+ name: Clash.Magic.nameHint+ kind: Declaration+ type: |-+ nameHint+ :: SSymbol sym -- ARG[0]+ -> a -- ARG[1]+ -> a+ resultName:+ template: ~NAME[0]+ template: ~RESULT <= ~ARG[1];
− prims/vhdl/Clash_Prelude_ROM.primitives
@@ -1,28 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Prelude.ROM.asyncRom#"- , "kind" : "Declaration"- , "type" :-"asyncRom# :: KnownNat n -- ^ ARG[0]- => Vec n a -- ^ ARG[1]- -> Int -- ^ ARG[2]- -> a"- , "template" :-"-- asyncRom begin-~GENSYM[asyncRom][0] : block- signal ~GENSYM[ROM][1] : ~TYP[1];- signal ~GENSYM[rd][2] : integer range 0 to ~LIT[0]-1;-begin- ~SYM[1] <= ~LIT[1];-- ~SYM[2] <= to_integer(~ARG[2])- -- pragma translate_off- mod ~LIT[0]- -- pragma translate_on- ;~IF ~VIVADO ~THEN- ~RESULT <= ~FROMBV[~SYM[1](~SYM[2])][~TYPO];~ELSE- ~RESULT <= ~SYM[1](~SYM[2]);~FI-end block;--- asyncRom end"- }- }-]
+ prims/vhdl/Clash_Prelude_ROM.primitives.yaml view
@@ -0,0 +1,25 @@+- BlackBox:+ name: Clash.Prelude.ROM.asyncRom#+ kind: Declaration+ type: |-+ asyncRom# :: KnownNat n -- ^ ARG[0]+ => Vec n a -- ^ ARG[1]+ -> Int -- ^ ARG[2]+ -> a+ template: |-+ -- asyncRom begin+ ~GENSYM[asyncRom][0] : block+ signal ~GENSYM[ROM][1] : ~TYP[1];+ signal ~GENSYM[rd][2] : integer range 0 to ~LIT[0]-1;+ begin+ ~SYM[1] <= ~CONST[1];++ ~SYM[2] <= to_integer(~VAR[rdI][2](31 downto 0))+ -- pragma translate_off+ mod ~LIT[0]+ -- pragma translate_on+ ;~IF ~VIVADO ~THEN+ ~RESULT <= ~FROMBV[~SYM[1](~SYM[2])][~TYPO];~ELSE+ ~RESULT <= ~SYM[1](~SYM[2]);~FI+ end block;+ -- asyncRom end
+ prims/vhdl/Clash_Prelude_ROM_Blob.primitives.yaml view
@@ -0,0 +1,24 @@+- BlackBox:+ name: Clash.Prelude.ROM.Blob.asyncRomBlob#+ kind: Declaration+ type: |-+ asyncRomBlob#+ :: MemBlob n m -- ARG[0]+ -> Int -- ARG[1]+ -> BitVector m+ template: |-+ -- asyncRomBlob begin+ ~GENSYM[asyncRom][0] : block+ signal ~GENSYM[ROM][1] : ~TYP[0];+ signal ~GENSYM[rd][2] : integer range 0 to ~LENGTH[~TYP[0]]-1;+ begin+ ~SYM[1] <= ~CONST[0];++ ~SYM[2] <= to_integer(~VAR[rdI][1](31 downto 0))+ -- pragma translate_off+ mod ~LENGTH[~TYP[0]]+ -- pragma translate_on+ ;+ ~RESULT <= ~SYM[1](~SYM[2]);+ end block;+ -- asyncRomBlob end
− prims/vhdl/Clash_Prelude_ROM_File.primitives
@@ -1,41 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Prelude.ROM.File.asyncRomFile#"- , "kind" : "Declaration"- , "type" :-"asyncRomFile# :: KnownNat m -- ARG[0]- => SNat n -- sz, ARG[1]- -> FilePath -- file, ARG[2]- -> Int -- rd, ARG[3]- -> BitVector m"- , "template" :-"-- asyncRomFile begin-~GENSYM[asyncROMFile][0] : block- type ~GENSYM[RomType][4] is array(natural range <>) of bit_vector(~LIT[0]-1 downto 0);-- impure function ~GENSYM[InitRomFromFile][1] (RomFileName : in string) return ~SYM[4] is- FILE RomFile : text open read_mode is RomFileName;- variable RomFileLine : line;- variable ROM : ~SYM[4](0 to ~LIT[1]-1);- begin- for i in ROM'range loop- readline(RomFile,RomFileLine);- read(RomFileLine,ROM(i));- end loop;- return ROM;- end function;-- signal ~GENSYM[ROM][2] : ~SYM[4](0 to ~LIT[1]-1) := ~SYM[1](~FILE[~LIT[2]]);- signal ~GENSYM[rd][3] : integer range 0 to ~LIT[1]-1;-begin- ~SYM[3] <= to_integer(~ARG[3])- -- pragma translate_off- mod ~LIT[1]- -- pragma translate_on- ;-- ~RESULT <= to_stdlogicvector(~SYM[2](~SYM[3]));-end block;--- asyncRomFile end"- }- }-]
+ prims/vhdl/Clash_Prelude_ROM_File.primitives.yaml view
@@ -0,0 +1,38 @@+- BlackBox:+ name: Clash.Prelude.ROM.File.asyncRomFile#+ kind: Declaration+ type: |-+ asyncRomFile# :: KnownNat m -- ARG[0]+ => SNat n -- sz, ARG[1]+ -> FilePath -- file, ARG[2]+ -> Int -- rd, ARG[3]+ -> BitVector m+ template: |-+ -- asyncRomFile begin+ ~GENSYM[asyncROMFile][0] : block+ type ~GENSYM[RomType][4] is array(natural range <>) of bit_vector(~LIT[0]-1 downto 0);++ impure function ~GENSYM[InitRomFromFile][1] (RomFileName : in string) return ~SYM[4] is+ FILE RomFile : text open read_mode is RomFileName;+ variable RomFileLine : line;+ variable ROM : ~SYM[4](0 to ~LIT[1]-1);+ begin+ for i in ROM'range loop+ readline(RomFile,RomFileLine);+ read(RomFileLine,ROM(i));+ end loop;+ return ROM;+ end function;++ signal ~GENSYM[ROM][2] : ~SYM[4](0 to ~LIT[1]-1) := ~SYM[1](~FILE[~LIT[2]]);+ signal ~GENSYM[rd][3] : integer range 0 to ~LIT[1]-1;+ begin+ ~SYM[3] <= to_integer(~VAR[rdI][3](31 downto 0))+ -- pragma translate_off+ mod ~LIT[1]+ -- pragma translate_on+ ;++ ~RESULT <= to_stdlogicvector(~SYM[2](~SYM[3]));+ end block;+ -- asyncRomFile end
− prims/vhdl/Clash_Promoted_Nat.primitives
@@ -1,34 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Promoted.Nat.flogBaseSNat"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "Clash.Promoted.Nat.flogBaseSNat :: (2 <= base, 1 <= x)- => SNat base -- ARG[2]- -> SNat x -- ARG[3]- -> SNat (FLog base x)"- , "template" : "integer(floor(log(real(~LIT[3]),real(~LIT[2]))))"- }- }-, { "BlackBox" :- { "name" : "Clash.Promoted.Nat.clogBaseSNat"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "Clash.Promoted.Nat.clogBaseSNat :: (2 <= base, 1 <= x)- => SNat base -- ARG[2]- -> SNat x -- ARG[3]- -> SNat (CLog base x)"- , "template" : "integer(ceiling(log(real(~LIT[3]),real(~LIT[2]))))"- }- }-, { "BlackBox" :- { "name" : "Clash.Promoted.Nat.logBaseSNat"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "Clash.Promoted.Nat.logBaseSNat :: (FLog base x ~ CLog base x)- => SNat base -- ARG[1]- -> SNat x -- ARG[2]- -> SNat (Log base x)"- , "template" : "integer(ceiling(log(real(~LIT[2]),real(~LIT[1]))))"- }- }-]
+ prims/vhdl/Clash_Promoted_Nat.primitives.yaml view
@@ -0,0 +1,30 @@+- BlackBox:+ name: Clash.Promoted.Nat.flogBaseSNat+ kind: Expression+ type: |-+ Clash.Promoted.Nat.flogBaseSNat :: (2 <= base, 1 <= x)+ => SNat base -- ARG[2]+ -> SNat x -- ARG[3]+ -> SNat (FLog base x)+ template: integer(floor(log(real(~LIT[3]),real(~LIT[2]))))+ workInfo: Never+- BlackBox:+ name: Clash.Promoted.Nat.clogBaseSNat+ kind: Expression+ type: |-+ Clash.Promoted.Nat.clogBaseSNat :: (2 <= base, 1 <= x)+ => SNat base -- ARG[2]+ -> SNat x -- ARG[3]+ -> SNat (CLog base x)+ template: integer(ceiling(log(real(~LIT[3]),real(~LIT[2]))))+ workInfo: Never+- BlackBox:+ name: Clash.Promoted.Nat.logBaseSNat+ kind: Expression+ type: |-+ Clash.Promoted.Nat.logBaseSNat :: (FLog base x ~ CLog base x)+ => SNat base -- ARG[1]+ -> SNat x -- ARG[2]+ -> SNat (Log base x)+ template: integer(ceiling(log(real(~LIT[2]),real(~LIT[1]))))+ workInfo: Never
− prims/vhdl/Clash_Signal_BiSignal.primitives
@@ -1,35 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Signal.BiSignal.writeToBiSignal#",- "kind" : "Declaration",- "renderVoid": "RenderVoid",- "type" :-"writeToBiSignal#- :: HasCallStack -- ARG[0]- => BiSignalIn ds d n -- ARG[1]- -> Signal d (Maybe (BitVector n)) -- ARG[2]- -> Signal d Bool -- ARG[3]- -> Signal d (BitVector n) -- ARG[4]- -> BiSignalOut ds d n",- "template":-"-- writeToBiSignal# begin-~ARG[1] <= ~ARG[4] when ~ARG[3] else (~SIZE[~TYP[1]]-1 downto 0 => 'Z');--- writeToBiSignal# end"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.BiSignal.readFromBiSignal#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" :-"readFromBiSignal#- :: ( HasCallStack -- ARG[0]- , KnownNat n) -- ARG[1]- => BiSignalIn ds d n -- ARG[2]- -> Signal d (BitVector n)"- , "template" :-"-- readFromBiSignal begin-~RESULT <= ~ARG[2];--- readFromBiSignal end"- }- }-]
+ prims/vhdl/Clash_Signal_BiSignal.primitives.yaml view
@@ -0,0 +1,30 @@+- BlackBox:+ name: Clash.Signal.BiSignal.writeToBiSignal#+ kind: Declaration+ type: |-+ writeToBiSignal#+ :: HasCallStack -- ARG[0]+ => BiSignalIn ds d n -- ARG[1]+ -> Signal d (Maybe (BitVector n)) -- ARG[2]+ -> Signal d Bool -- ARG[3]+ -> Signal d (BitVector n) -- ARG[4]+ -> BiSignalOut ds d n+ renderVoid: RenderVoid+ template: |-+ -- writeToBiSignal# begin+ ~ARG[1] <= ~ARG[4] when ~ARG[3] else (~SIZE[~TYP[1]]-1 downto 0 => 'Z');+ -- writeToBiSignal# end+- BlackBox:+ name: Clash.Signal.BiSignal.readFromBiSignal#+ kind: Declaration+ type: |-+ readFromBiSignal#+ :: ( HasCallStack -- ARG[0]+ , KnownNat n) -- ARG[1]+ => BiSignalIn ds d n -- ARG[2]+ -> Signal d (BitVector n)+ template: |-+ -- readFromBiSignal begin+ ~RESULT <= ~ARG[2];+ -- readFromBiSignal end+ workInfo: Never
− prims/vhdl/Clash_Signal_Internal.primitives
@@ -1,193 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Signal.Internal.delay#"- , "kind" : "Declaration"- , "type" :-"delay#- :: ( KnownDomain dom -- ARG[0]- , Undefined a ) -- ARG[1]- => Clock dom -- ARG[2]- -> Enable dom -- ARG[3]- -> a -- ARG[4]- -> Signal clk a -- ARG[5]- -> Signal clk a"- , "resultName" : { "template" : "~CTXNAME" }- , "resultInit" : { "template" : "~IF~ISINITDEFINED[0]~THEN~CONST[4]~ELSE~FI" }- , "template" :-"-- delay begin~IF ~ISACTIVEENABLE[3] ~THEN-~GENSYM[~RESULT_delay][4] : process(~ARG[2])-begin- if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2]) then- if ~ARG[3] then- ~RESULT <= ~ARG[5];- end if;- end if;-end process;~ELSE-~SYM[4] : process(~ARG[2])-begin- if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2]) then- ~RESULT <= ~ARG[5];- end if;-end process;~FI--- delay end"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.asyncRegister#"- , "kind" : "Declaration"- , "type" :-"asyncRegister#- :: ( KnownDomain dom -- ARG[0]- , NFDataX a ) -- ARG[1]- => Clock dom -- ARG[2]- -> Reset dom -- ARG[3]- -> Enable dom -- ARG[4]- -> a -- ARG[5] (powerup value)- -> a -- ARG[6] (reset value)- -> Signal clk a -- ARG[7]- -> Signal clk a"- , "resultName" : { "template" : "~CTXNAME" }- , "resultInit" : { "template" : "~IF~ISINITDEFINED[0]~THEN~CONST[5]~ELSE~FI" }- , "template" :-"-- async register begin-~SYM[2] : process(~ARG[2]~IF ~ISUNDEFINED[6] ~THEN ~ELSE,~ARG[3]~FI)-begin- ~IF ~ISUNDEFINED[6] ~THEN ~ELSEif ~ARG[3] = ~IF ~ISACTIVEHIGH[0] ~THEN '1' ~ELSE '0' ~FI then- ~RESULT <= ~CONST[6];- els~FIif ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2]) then- ~IF ~ISACTIVEENABLE[4] ~THEN- if ~ARG[4] then- ~RESULT <= ~ARG[7];- end if;- ~ELSE- ~RESULT <= ~ARG[7];- ~FI- end if;-end process;--- async register end"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.register#"- , "kind" : "Declaration"- , "type" :-"register#- :: ( KnownDomain dom -- ARG[0]- , NFDataX a ) -- ARG[1]- => Clock dom -- ARG[2]- -> Reset dom -- ARG[3]- -> Enable dom -- ARG[4]- -> a -- ARG[5] (powerup value)- -> a -- ARG[6] (reset value)- -> Signal clk a -- ARG[7]- -> Signal clk a"- , "resultName" : { "template" : "~CTXNAME" }- , "resultInit" : { "template" : "~IF~ISINITDEFINED[0]~THEN~CONST[5]~ELSE~FI" }- , "template" :-"-- register begin~IF ~ISACTIVEENABLE[4] ~THEN ~IF ~ISSYNC[0] ~THEN-~GENSYM[~RESULT_register][2] : process(~ARG[2])-begin- if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2]) then- ~IF ~ISUNDEFINED[6] ~THEN ~ELSEif ~ARG[3] = ~IF ~ISACTIVEHIGH[0] ~THEN '1' ~ELSE '0' ~FI then- ~RESULT <= ~CONST[6];- els~FIif ~ARG[4] then- ~RESULT <= ~ARG[7];- end if;- end if;-end process;~ELSE-~SYM[2] : process(~ARG[2]~IF ~ISUNDEFINED[6] ~THEN ~ELSE,~ARG[3]~FI)-begin- ~IF ~ISUNDEFINED[6] ~THEN ~ELSEif ~ARG[3] = ~IF ~ISACTIVEHIGH[0] ~THEN '1' ~ELSE '0' ~FI then- ~RESULT <= ~CONST[6];- els~FIif ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2]) then- if ~ARG[4] then- ~RESULT <= ~ARG[7];- end if;- end if;-end process;~FI~ELSE ~IF ~ISSYNC[0] ~THEN-~SYM[2] : process(~ARG[2])-begin- if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2]) then- ~IF ~ISUNDEFINED[6] ~THEN ~ELSEif ~ARG[3] = ~IF ~ISACTIVEHIGH[0] ~THEN '1' ~ELSE '0' ~FI then- ~RESULT <= ~CONST[6];- else- ~FI~RESULT <= ~ARG[7];- ~IF ~ISUNDEFINED[6] ~THEN ~ELSEend if;~FI- end if;-end process;~ELSE-~SYM[2] : process(~ARG[2]~IF ~ISUNDEFINED[6] ~THEN ~ELSE,~ARG[3]~FI)-begin- ~IF ~ISUNDEFINED[6] ~THEN ~ELSEif ~ARG[3] = ~IF ~ISACTIVEHIGH[0] ~THEN '1' ~ELSE '0' ~FI then- ~RESULT <= ~CONST[6];- els~FIif ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2]) then- ~RESULT <= ~ARG[7];- end if;-end process;~FI~FI--- register end"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.clockGen"- , "workInfo" : "Always"- , "kind" : "Declaration"- , "warning" : "Clash.Signal.Internal.clockGen is not synthesizable!"- , "type" :-"clockGen- :: KnownDomain dom -- ARG[0]- => Clock dom"- , "comment" :- "ModelSim and Vivado seem to round time values to an integer number of picoseconds.- Use two half periods to prevent rounding errors from affecting the full period."- , "template" :-"-- clockGen begin--- pragma translate_off-~GENSYM[clkGen][0] : process is- constant ~GENSYM[half_periodH][1] : time := ~PERIOD[0]000 fs / 2;- constant ~GENSYM[half_periodL][2] : time := ~PERIOD[0]000 fs - ~SYM[1];-begin- ~RESULT <= ~IF~ACTIVEEDGE[Rising][0]~THEN'0'~ELSE'1'~FI;- wait for 3000 ps;- loop- ~RESULT <= not ~RESULT;- wait for ~SYM[1];- ~RESULT <= not ~RESULT;- wait for ~SYM[2];- end loop;- wait;-end process;--- pragma translate_on--- clockGen end"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.resetGenN"- , "workInfo" : "Always"- , "kind" : "Declaration"- , "type" : "resetGenN :: (KnownDomain dom, 1 <= n) => SNat n -> Reset dom"- , "template" :-"-- resetGen begin--- pragma translate_off-~RESULT <= ~IF ~ISACTIVEHIGH[0] ~THEN '1' ~ELSE '0' ~FI,- ~IF ~ISACTIVEHIGH[0] ~THEN '0' ~ELSE '1' ~FI after ~IF~ISSYNC[0]~THEN(2999 ps + (integer'(~LIT[2]) * ~PERIOD[0] ps))~ELSE(3001 ps + integer'(~LIT[2] - 1) * ~PERIOD[0] ps)~FI;--- pragma translate_on--- resetGen end"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.unsafeFromReset"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" :-"unsafeFromReset :: Reset dom -> Signal dom Bool"- , "template" : "~RESULT <= true when ~ARG[0] = '1' else false;"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.unsafeToReset"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" :-"unsafeToReset :: Signal dom Bool -> Reset dom"- , "template" : "~RESULT <= '1' when ~ARG[0] = true else '0';"- }- }-]
+ prims/vhdl/Clash_Signal_Internal.primitives.yaml view
@@ -0,0 +1,190 @@+- BlackBox:+ name: Clash.Signal.Internal.delay#+ kind: Declaration+ type: |-+ delay#+ :: ( KnownDomain dom -- ARG[0]+ , Undefined a ) -- ARG[1]+ => Clock dom -- ARG[2]+ -> Enable dom -- ARG[3]+ -> a -- ARG[4]+ -> Signal clk a -- ARG[5]+ -> Signal clk a+ resultInit:+ template: ~IF~ISINITDEFINED[0]~THEN~CONST[4]~ELSE~FI+ resultName:+ template: ~CTXNAME+ template: |-+ -- delay begin~IF ~ISACTIVEENABLE[3] ~THEN+ ~GENSYM[~RESULT_delay][4] : process(~ARG[2])+ begin+ if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2]) then+ if ~ARG[3] then+ ~RESULT <= ~ARG[5];+ end if;+ end if;+ end process;~ELSE+ ~SYM[4] : process(~ARG[2])+ begin+ if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2]) then+ ~RESULT <= ~ARG[5];+ end if;+ end process;~FI+ -- delay end+- BlackBox:+ name: Clash.Signal.Internal.asyncRegister#+ kind: Declaration+ type: |-+ asyncRegister#+ :: ( KnownDomain dom -- ARG[0]+ , NFDataX a ) -- ARG[1]+ => Clock dom -- ARG[2]+ -> Reset dom -- ARG[3]+ -> Enable dom -- ARG[4]+ -> a -- ARG[5] (powerup value)+ -> a -- ARG[6] (reset value)+ -> Signal clk a -- ARG[7]+ -> Signal clk a+ resultInit:+ template: ~IF~ISINITDEFINED[0]~THEN~CONST[5]~ELSE~FI+ resultName:+ template: ~CTXNAME+ template: |-+ -- async register begin+ ~SYM[2] : process(~ARG[2]~IF ~ISUNDEFINED[6] ~THEN ~ELSE,~ARG[3]~FI)+ begin+ ~IF ~ISUNDEFINED[6] ~THEN ~ELSEif ~ARG[3] = ~IF ~ISACTIVEHIGH[0] ~THEN '1' ~ELSE '0' ~FI then+ ~RESULT <= ~CONST[6];+ els~FIif ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2]) then+ ~IF ~ISACTIVEENABLE[4] ~THEN+ if ~ARG[4] then+ ~RESULT <= ~ARG[7];+ end if;+ ~ELSE+ ~RESULT <= ~ARG[7];+ ~FI+ end if;+ end process;+ -- async register end+- BlackBox:+ name: Clash.Signal.Internal.register#+ kind: Declaration+ type: |-+ register#+ :: ( KnownDomain dom -- ARG[0]+ , NFDataX a ) -- ARG[1]+ => Clock dom -- ARG[2]+ -> Reset dom -- ARG[3]+ -> Enable dom -- ARG[4]+ -> a -- ARG[5] (powerup value)+ -> a -- ARG[6] (reset value)+ -> Signal clk a -- ARG[7]+ -> Signal clk a+ resultInit:+ template: ~IF~ISINITDEFINED[0]~THEN~CONST[5]~ELSE~FI+ resultName:+ template: ~CTXNAME+ template: |-+ -- register begin~IF ~ISACTIVEENABLE[4] ~THEN ~IF ~ISSYNC[0] ~THEN+ ~GENSYM[~RESULT_register][2] : process(~ARG[2])+ begin+ if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2]) then+ ~IF ~ISUNDEFINED[6] ~THEN ~ELSEif ~ARG[3] = ~IF ~ISACTIVEHIGH[0] ~THEN '1' ~ELSE '0' ~FI then+ ~RESULT <= ~CONST[6];+ els~FIif ~ARG[4] then+ ~RESULT <= ~ARG[7];+ end if;+ end if;+ end process;~ELSE+ ~SYM[2] : process(~ARG[2]~IF ~ISUNDEFINED[6] ~THEN ~ELSE,~ARG[3]~FI)+ begin+ ~IF ~ISUNDEFINED[6] ~THEN ~ELSEif ~ARG[3] = ~IF ~ISACTIVEHIGH[0] ~THEN '1' ~ELSE '0' ~FI then+ ~RESULT <= ~CONST[6];+ els~FIif ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2]) then+ if ~ARG[4] then+ ~RESULT <= ~ARG[7];+ end if;+ end if;+ end process;~FI~ELSE ~IF ~ISSYNC[0] ~THEN+ ~SYM[2] : process(~ARG[2])+ begin+ if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2]) then+ ~IF ~ISUNDEFINED[6] ~THEN ~ELSEif ~ARG[3] = ~IF ~ISACTIVEHIGH[0] ~THEN '1' ~ELSE '0' ~FI then+ ~RESULT <= ~CONST[6];+ else+ ~FI~RESULT <= ~ARG[7];+ ~IF ~ISUNDEFINED[6] ~THEN ~ELSEend if;~FI+ end if;+ end process;~ELSE+ ~SYM[2] : process(~ARG[2]~IF ~ISUNDEFINED[6] ~THEN ~ELSE,~ARG[3]~FI)+ begin+ ~IF ~ISUNDEFINED[6] ~THEN ~ELSEif ~ARG[3] = ~IF ~ISACTIVEHIGH[0] ~THEN '1' ~ELSE '0' ~FI then+ ~RESULT <= ~CONST[6];+ els~FIif ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2]) then+ ~RESULT <= ~ARG[7];+ end if;+ end process;~FI~FI+ -- register end+- BlackBox:+ name: Clash.Signal.Internal.clockGen+ comment: |-+ ModelSim and Vivado seem to round time values to an integer number of picoseconds.+ Use two half periods to prevent rounding errors from affecting the full period.+ kind: Declaration+ type: |-+ clockGen+ :: KnownDomain dom -- ARG[0]+ => Clock dom+ template: |-+ -- clockGen begin+ -- pragma translate_off+ ~GENSYM[clkGen][0] : process is+ constant ~GENSYM[half_periodH][1] : time := ~PERIOD[0]000 fs / 2;+ constant ~GENSYM[half_periodL][2] : time := ~PERIOD[0]000 fs - ~SYM[1];+ begin+ ~RESULT <= ~IF~ACTIVEEDGE[Rising][0]~THEN'0'~ELSE'1'~FI;+ wait for ~LONGESTPERIOD ps;+ loop+ ~RESULT <= not ~RESULT;+ wait for ~SYM[1];+ ~RESULT <= not ~RESULT;+ wait for ~SYM[2];+ end loop;+ wait;+ end process;+ -- pragma translate_on+ -- clockGen end+ warning: Clash.Signal.Internal.clockGen is not synthesizable!+ workInfo: Always+- BlackBox:+ name: Clash.Signal.Internal.resetGenN+ kind: Declaration+ type: 'resetGenN :: (KnownDomain+ dom, 1 <= n) => SNat n -> Reset dom'+ template: |-+ -- resetGen begin+ ~GENSYM[resetGen][0] : block+ constant ~GENSYM[reset_delay][1] : time := ~LONGESTPERIOD ps - 1 ps + (integer'(~LIT[2]) * ~PERIOD[0] ps);+ begin+ -- pragma translate_off+ ~RESULT+ <= ~IF ~ISACTIVEHIGH[0] ~THEN'1'~ELSE'0'~FI,+ ~IF ~ISACTIVEHIGH[0] ~THEN'0'~ELSE'1'~FI after ~SYM[1];+ -- pragma translate_on+ end block;+ -- resetGen end+ workInfo: Always+- BlackBox:+ name: Clash.Signal.Internal.unsafeFromReset+ kind: Declaration+ type: 'unsafeFromReset+ :: Reset dom -> Signal dom Bool'+ template: ~RESULT <= true when ~ARG[0] = '1' else false;+ workInfo: Never+- BlackBox:+ name: Clash.Signal.Internal.unsafeToReset+ kind: Declaration+ type: 'unsafeToReset ::+ Signal dom Bool -> Reset dom'+ template: ~RESULT <= '1' when ~ARG[0] = true else '0';+ workInfo: Never
− prims/vhdl/Clash_Sized_Internal_BitVector.primitives
@@ -1,585 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.BV"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "BV :: Integer -> Integer -> BitVector n"- , "comment" : "THIS IS ONLY USED WHEN WW EXPOSES BITVECTOR INTERNALS"- , "template" : "std_logic_vector(resize(unsigned(std_logic_vector(~ARG[1])),~SIZE[~TYPO]))"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.Bit"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "Bit :: Integer -> Integer -> BitVector n"- , "comment" : "THIS IS ONLY USED WHEN WW EXPOSES BIT INTERNALS"- , "template" : "~VAR[i][1][0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.size#"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "size# :: KnownNat n => BitVector n -> Int"- , "template" : "to_signed(~SIZE[~TYP[1]],~SIZE[~TYPO])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.maxIndex#"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "maxIndex# :: KnownNat n => BitVector n -> Int"- , "template" : "to_signed(~SIZE[~TYP[1]] - 1,~SIZE[~TYPO])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.high"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "high :: Bit"- , "template" : "'1'"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.low"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "low :: Bit"- , "template" : "'0'"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.pack#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "pack# :: Bit -> BitVector 1"- , "template" : "std_logic_vector'(0 => ~ARG[0])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.unpack#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "unpack# :: BitVector 1 -> Bit"- , "template" : "~VAR[bv][0](0)"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.eq##"- , "kind" : "Expression"- , "type" : "eq## :: Bit -> Bit -> Bool"- , "template" : "~ARG[0] = ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.neq##"- , "kind" : "Expression"- , "type" : "neq## :: Bit -> Bit -> Bool"- , "template" : "~ARG[0] /= ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.fromInteger##"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "fromInteger## :: Integer -> Integer -> Bit"- , "template" : "~IF~LIT[0]~THEN'U'~ELSE~ARG[1](0)~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.and##"- , "kind" : "Expression"- , "type" : "and## :: Bit -> Bit -> Bit"- , "template" : "~ARG[0] and ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.or##"- , "kind" : "Expression"- , "type" : "or## :: Bit -> Bit -> Bit"- , "template" : "~ARG[0] or ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.xor##"- , "kind" : "Expression"- , "type" : "xor## :: Bit -> Bit -> Bit"- , "template" : "~ARG[0] xor ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.complement##"- , "kind" : "Expression"- , "type" : "complement## :: Bit -> Bit"- , "template" : "not ~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.++#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "(++#) :: KnownNat m => BitVector n -> BitVector m -> BitVector (n + m)"- , "template" : "~IF~AND[~SIZE[~TYP[1]],~SIZE[~TYP[2]]]~THENstd_logic_vector'(std_logic_vector'(~ARG[1]) & std_logic_vector'(~ARG[2]))~ELSE~IF~SIZE[~TYP[1]]~THENstd_logic_vector'(~ARG[1])~ELSEstd_logic_vector'(~ARG[2])~FI~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.reduceAnd#"- , "kind" : "Declaration"- , "type" : "reduceAnd# :: KnownNat n => BitVector n -> Bit"- , "template" :-"-- reduceAnd begin,-~IF~SIZE[~TYP[1]]~THEN-~GENSYM[reduceAnd][0] : block- function and_reduce (arg : std_logic_vector) return std_logic is- variable upper, lower : std_logic;- variable half : integer;- variable argi : std_logic_vector (arg'length - 1 downto 0);- variable result : std_logic;- begin- if (arg'length < 1) then- result := '1';- else- argi := arg;- if (argi'length = 1) then- result := argi(argi'left);- else- half := (argi'length + 1) / 2; -- lsb-biased tree- upper := and_reduce (argi (argi'left downto half));- lower := and_reduce (argi (half - 1 downto argi'right));- result := upper and lower;- end if;- end if;- return result;- end;-begin- ~RESULT <= and_reduce(~ARG[1]);-end block;~ELSE-~RESULT <= '1';~FI--- reduceAnd end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.reduceOr#"- , "kind" : "Declaration"- , "type" : "reduceOr# :: KnownNat n => BitVector n -> Bit"- , "template" :-"-- reduceOr begin ~IF~SIZE[~TYP[1]]~THEN-~GENSYM[reduceOr][0] : block- function or_reduce (arg : std_logic_vector) return std_logic is- variable upper, lower : std_logic;- variable half : integer;- variable argi : std_logic_vector (arg'length - 1 downto 0);- variable result : std_logic;- begin- if (arg'length < 1) then- result := '0';- else- argi := arg;- if (argi'length = 1) then- result := argi(argi'left);- else- half := (argi'length + 1) / 2; -- lsb-biased tree- upper := or_reduce (argi (argi'left downto half));- lower := or_reduce (argi (half - 1 downto argi'right));- result := upper or lower;- end if;- end if;- return result;- end;-begin- ~RESULT <= or_reduce(~ARG[1]);-end block;~ELSE-~RESULT <= '0'; ~FI--- reduceOr end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.reduceXor#"- , "kind" : "Declaration"- , "type" : "reduceXor# :: KnownNat n => BitVector n -> Bit"- , "template" :-"-- reduceXor begin ~IF~SIZE[~TYP[1]]~THEN-~GENSYM[reduceXor][0] : block- function xor_reduce (arg : std_logic_vector) return std_logic is- variable upper, lower : std_logic;- variable half : integer;- variable argi : std_logic_vector (arg'length - 1 downto 0);- variable result : std_logic;- begin- if (arg'length < 1) then- result := '0';- else- argi := arg;- if (argi'length = 1) then- result := argi(argi'left);- else- half := (argi'length + 1) / 2; -- lsb-biased tree- upper := xor_reduce (argi (argi'left downto half));- lower := xor_reduce (argi (half - 1 downto argi'right));- result := upper xor lower;- end if;- end if;- return result;- end;-begin- ~RESULT <= xor_reduce(~ARG[1]);-end block;~ELSE-~RESULT <= '0';~FI--- reduceXor end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.index#"- , "kind" : "Declaration"- , "type" :-"index# :: KnownNat n -- ARG[0]- => BitVector n -- ARG[1]- -> Int -- ARG[2]- -> Bit"- , "template" :-"-- indexBitVector begin ~IF~SIZE[~TYP[1]]~THEN~IF ~ISVAR[1] ~THEN-~GENSYM[indexBitVector][0] : block- signal ~GENSYM[vec_index][1] : integer range 0 to ~SIZE[~TYP[1]]-1;-begin- ~SYM[1] <= to_integer(~ARG[2])- -- pragma translate_off- mod ~SIZE[~TYP[1]]- -- pragma translate_on- ;-- ~RESULT <= ~ARG[1](~SYM[1]);-end block;~ELSE-~SYM[0] : block- signal ~SYM[1] : integer range 0 to ~SIZE[~TYP[1]]-1;-begin- ~SYM[1] <= to_integer(~ARG[2])- -- pragma translate_off- mod ~SIZE[~TYP[1]]- -- pragma translate_on- ;-- ~RESULT <= ~VAR[bv][1](~SYM[1]);-end block;~FI~ELSE-~RESULT <= ~ERRORO;~FI--- indexBitVector end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.replaceBit#"- , "kind" : "Declaration"- , "type" :-"replaceBit# :: KnownNat n -- ARG[0]- => BitVector n -- ARG[1]- -> Int -- ARG[2]- -> Bit -- ARG[3]- -> BitVector n"- , "template" :-"-- replaceBit begin ~IF~SIZE[~TYP[1]]~THEN-~GENSYM[replaceBit][0] : block- signal ~GENSYM[vec_index][1] : integer range 0 to ~SIZE[~TYP[1]]-1;-begin- ~SYM[1] <= to_integer(~ARG[2])- -- pragma translate_off- mod ~SIZE[~TYP[1]]- -- pragma translate_on- ;-- process(~SYM[1],~VAR[b][3]~VARS[1])- variable ~GENSYM[ivec][2] : ~TYP[1];- begin- ~SYM[2] := ~ARG[1];- ~SYM[2](~SYM[1]) := ~ARG[3];- ~RESULT <= ~SYM[2];- end process;-end block; ~ELSE-~RESULT <= ~ERRORO;~FI--- replaceBit end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.setSlice#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" :-"setSlice# :: SNat (m + 1 + i)- => BitVector (m + 1 + i) -- ARG[1]- -> SNat m -- ARG[2]- -> SNat n -- ARG[3]- -> BitVector (m + 1 - n) -- ARG[4]- -> BitVector (m + 1 + i)"- , "template" :-"-- setSlice begin-~GENSYM[setSlice][0] : process(~VAR[bv][1]~VARS[4])- variable ~GENSYM[ivec][1] : ~TYP[1];-begin- ~SYM[1] := ~VAR[bv][1];- ~SYM[1](~LIT[2] downto ~LIT[3]) := ~ARG[4];- ~RESULT <= ~SYM[1];-end process;--- setSlice end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.slice#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" :-"slice# :: BitVector (m + 1 + i) -- ARG[0]- -> SNat m -- ARG[1]- -> SNat n -- ARG[2]- -> BitVector (m + 1 - n)"- , "template" : "~VAR[bv][0](~LIT[1] downto ~LIT[2])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.split#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" :-"split# :: KnownNat n -- ARG[0]- => BitVector (m + n) -- ARG[1]- -> (BitVector m, BitVector n)"- , "template" : "(~VAR[bv][1](~VAR[bv][1]'high downto ~LIT[0]),~VAR[bv][1](~LIT[0]-1 downto 0))"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.msb#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" :-"msb# :: KnownNat n -- ARG[0]- => BitVector n -- ARG[1]- -> Bit"- , "template" : "~IF ~SIZE[~TYP[1]] ~THEN ~VAR[bv][1](~VAR[bv][1]'high) ~ELSE \"0\" ~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.lsb#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" :-"lsb# :: BitVector n -- ARG[0]- -> Bit"- , "template" : "~IF ~SIZE[~TYP[0]] ~THEN ~VAR[bv][0](0) ~ELSE \"0\" ~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.eq#"- , "kind" : "Expression"- , "type" : "eq# :: KnownNat n => BitVector n -> BitVector n -> Bool"- , "template" : "~IF~SIZE[~TYP[1]]~THEN~ARG[1] = ~ARG[2]~ELSEtrue~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.neq#"- , "kind" : "Expression"- , "type" : "neq# :: KnownNat n => BitVector n -> BitVector n -> Bool"- , "template" : "~IF~SIZE[~TYP[1]]~THEN~ARG[1] /= ~ARG[2]~ELSEfalse~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.lt#"- , "kind" : "Expression"- , "type" : "lt# :: KnownNat n => BitVector n -> BitVector n -> Bool"- , "template" : "~IF~SIZE[~TYP[1]]~THEN~ARG[1] < ~ARG[2]~ELSEfalse~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.ge#"- , "kind" : "Expression"- , "type" : "ge# :: KnownNat n => BitVector n -> BitVector n -> Bool"- , "template" : "~IF~SIZE[~TYP[1]]~THEN~ARG[1] >= ~ARG[2]~ELSEtrue~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.gt#"- , "kind" : "Expression"- , "type" : "gt# :: KnownNat n => BitVector n -> BitVector n -> Bool"- , "template" : "~IF~SIZE[~TYP[1]]~THEN~ARG[1] > ~ARG[2]~ELSEfalse~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.le#"- , "kind" : "Expression"- , "type" : "le# :: KnownNat n => BitVector n -> BitVector n -> Bool"- , "template" : "~IF~SIZE[~TYP[1]]~THEN~ARG[1] <= ~ARG[2]~ELSEtrue~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.minBound#"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "minBound# :: BitVector n"- , "template" : "~IF~SIZE[~TYPO]~THENstd_logic_vector'(~SIZE[~TYPO]-1 downto 0 => '0')~ELSEstd_logic_vector'(0 downto 1 => '0')~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.maxBound#"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "maxBound# :: KnownNat n => BitVector n"- , "template" : "~IF~SIZE[~TYPO]~THENstd_logic_vector'(~SIZE[~TYPO]-1 downto 0 => '1')~ELSEstd_logic_vector'(0 downto 1 => '1')~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.+#"- , "kind" : "Expression"- , "type" : "(+#) :: KnownNat n => BitVector n -> BitVector n -> BitVector n"- , "template" : "std_logic_vector(unsigned(~ARG[1]) + unsigned(~ARG[2]))"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.-#"- , "kind" : "Expression"- , "type" : "(-#) :: KnownNat n => BitVector n -> BitVector n -> BitVector n"- , "template" : "std_logic_vector(unsigned(~ARG[1]) - unsigned(~ARG[2]))"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.*#"- , "kind" : "Expression"- , "type" : "(*#) :: KnownNat n => BitVector n -> BitVector n -> BitVector n"- , "template" : "std_logic_vector(resize(unsigned(~ARG[1]) * unsigned(~ARG[2]), ~SIZE[~TYP[1]]))"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.negate#"- , "kind" : "Expression"- , "type" : "negate# :: KnownNat n => BitVector n -> BitVector n"- , "template" : "std_logic_vector(-(signed(~ARG[1])))"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.fromInteger#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "fromInteger# :: KnownNat n => Integer -> Integer -> BitVector n"- , "template" : "std_logic_vector(resize(unsigned(std_logic_vector(~ARG[2])),~SIZE[~TYPO]))"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.plus#"- , "kind" : "Expression"- , "type" : "plus# :: (KnownNat m, KnownNat n) => BitVector m -> BitVector n -> BitVector (Max m n + 1)"- , "template" : "~IF~AND[~SIZE[~TYP[2]],~SIZE[~TYP[3]]]~THENstd_logic_vector(resize(unsigned(~ARG[2]),~SIZE[~TYPO]) + resize(unsigned(~ARG[3]),~SIZE[~TYPO]))~ELSE~IF~SIZE[~TYP[2]]~THENstd_logic_vector(resize(unsigned(~ARG[2]),~SIZE[~TYPO]))~ELSEstd_logic_vector(resize(unsigned(~ARG[3]),~SIZE[~TYPO]))~FI~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.minus#"- , "kind" : "Expression"- , "type" : "minus# :: (KnownNat m, KnownNat n) => BitVector m -> BitVector n -> BitVector (Max m n + 1)"- , "template" : "~IF~AND[~SIZE[~TYP[2]],~SIZE[~TYP[3]]]~THENstd_logic_vector(resize(unsigned(~ARG[2]),~SIZE[~TYPO]) - resize(unsigned(~ARG[3]),~SIZE[~TYPO]))~ELSE~IF~SIZE[~TYP[2]]~THENstd_logic_vector(resize(unsigned(~ARG[2]),~SIZE[~TYPO]))~ELSEstd_logic_vector(-resize(signed(~ARG[3]),~SIZE[~TYPO]))~FI~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.times#"- , "kind" : "Expression"- , "type" : "times# :: (KnownNat m, KnownNat n) => BitVector m -> BitVector n -> BitVector (m + n)"- , "template" : "~IF~AND[~SIZE[~TYP[2]],~SIZE[~TYP[3]]]~THENstd_logic_vector(unsigned(~ARG[2]) * unsigned(~ARG[3]))~ELSE(~SIZE[~TYPO]-1 downto 0 => '0')~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.quot#"- , "kind" : "Expression"- , "type" : "quot# :: KnownNat n => BitVector n -> BitVector n -> BitVector n"- , "template" : "std_logic_vector(unsigned(~ARG[1]) / unsigned(~ARG[2]))"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.rem#"- , "kind" : "Expression"- , "type" : "rem# :: KnownNat n => BitVector n -> BitVector n -> BitVector n"- , "template" : "std_logic_vector(unsigned(~ARG[1]) rem unsigned(~ARG[2]))"- }- }-, { "BlackBoxHaskell" :- { "name" : "Clash.Sized.Internal.BitVector.toInteger#"- , "workInfo" : "Never"- , "templateFunction" : "Clash.Primitives.Sized.ToInteger.bvToIntegerVHDL"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.and#"- , "kind" : "Expression"- , "type" : "and# :: KnownNat n => BitVector n -> BitVector n -> BitVector n"- , "template" : "~ARG[1] and ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.or#"- , "kind" : "Expression"- , "type" : "or# :: KnownNat n => BitVector n -> BitVector n -> BitVector n"- , "template" : "~ARG[1] or ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.xor#"- , "kind" : "Expression"- , "type" : "xor# :: KnownNat n => BitVector n -> BitVector n -> BitVector n"- , "template" : "~ARG[1] xor ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.complement#"- , "kind" : "Expression"- , "type" : "complement# :: KnownNat n => BitVector n -> BitVector n"- , "template" : "not ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.shiftL#"- , "kind" : "Declaration"- , "type" : "shiftL# :: KnownNat n => BitVector n -> Int -> BitVector n"- , "template" :-"~RESULT <= std_logic_vector(shift_left(unsigned(~ARG[1]), to_integer(~ARG[2])))- -- pragma translate_off- when (~ARG[2] >= 0) else (others => 'X')- -- pragma translate_on- ;"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.shiftR#"- , "kind" : "Declaration"- , "type" : "shiftR# :: KnownNat n => BitVector n -> Int -> BitVector n"- , "template" :-"~RESULT <= std_logic_vector(shift_right(unsigned(~ARG[1]),to_integer(~ARG[2])))- -- pragma translate_off- when (~ARG[2] >= 0) else (others => 'X')- -- pragma translate_on- ;"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.rotateL#"- , "kind" : "Declaration"- , "type" : "rotateL# :: KnownNat n => BitVector n -> Int -> BitVector n"- , "template" :-"~RESULT <= std_logic_vector(rotate_left(unsigned(~ARG[1]),to_integer(~ARG[2])))- -- pragma translate_off- when (~ARG[2] >= 0) else (others => 'X')- -- pragma translate_on- ;"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.rotateR#"- , "kind" : "Declaration"- , "type" : "rotateR# :: KnownNat n => BitVector n -> Int -> BitVector n"- , "template" :-"~RESULT <= std_logic_vector(rotate_right(unsigned(~ARG[1]),to_integer(~ARG[2])))- -- pragma translate_off- when (~ARG[2] >= 0) else (others => 'X')- -- pragma translate_on- ;"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.truncateB#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "truncateB# :: forall a b . KnownNat a => BitVector (a + b) -> BitVector a"- , "template" : "std_logic_vector(resize(unsigned(~ARG[1]),~SIZE[~TYPO]))"- }- }-]
+ prims/vhdl/Clash_Sized_Internal_BitVector.primitives.yaml view
@@ -0,0 +1,592 @@+- BlackBox:+ name: Clash.Sized.Internal.BitVector.BV+ comment: THIS IS ONLY USED WHEN WW EXPOSES BITVECTOR INTERNALS+ kind: Expression+ type: 'BV :: Integer ->+ Integer -> BitVector n'+ template: std_logic_vector(resize(unsigned(std_logic_vector(~ARG[1])),~SIZE[~TYPO]))+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.Bit+ comment: THIS IS ONLY USED WHEN WW EXPOSES BIT INTERNALS+ kind: Expression+ type: 'Bit :: Integer+ -> Integer -> BitVector n'+ template: ~VAR[i][1][0]+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.size#+ kind: Expression+ type: 'size# :: KnownNat+ n => BitVector n -> Int'+ template: to_signed(~SIZE[~TYP[1]],~SIZE[~TYPO])+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Internal.BitVector.maxIndex#+ kind: Expression+ type: 'maxIndex# :: KnownNat+ n => BitVector n -> Int'+ template: to_signed(~SIZE[~TYP[1]] - 1,~SIZE[~TYPO])+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Internal.BitVector.high+ kind: Expression+ type: 'high :: Bit'+ template: '''1'''+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Internal.BitVector.low+ kind: Expression+ type: 'low :: Bit'+ template: '''0'''+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Internal.BitVector.pack#+ kind: Expression+ type: 'pack# :: Bit ->+ BitVector 1'+ template: std_logic_vector'(0 => ~ARG[0])+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.unpack#+ kind: Expression+ type: 'unpack# :: BitVector+ 1 -> Bit'+ template: ~VAR[bv][0](0)+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.eq##+ kind: Expression+ type: 'eq## :: Bit ->+ Bit -> Bool'+ template: ~ARG[0] = ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.neq##+ kind: Expression+ type: 'neq## :: Bit ->+ Bit -> Bool'+ template: ~ARG[0] /= ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.fromInteger##+ kind: Expression+ type: 'fromInteger## ::+ Integer -> Integer -> Bit'+ template: ~IF~LIT[0]~THEN'U'~ELSE~ARG[1](0)~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.toEnum##+ kind: Expression+ type: 'toEnum## :: Int+ -> Bit'+ template: ~ARG[0](0)+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.and##+ kind: Expression+ type: 'and## :: Bit ->+ Bit -> Bit'+ template: ~ARG[0] and ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.or##+ kind: Expression+ type: 'or## :: Bit ->+ Bit -> Bit'+ template: ~ARG[0] or ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.xor##+ kind: Expression+ type: 'xor## :: Bit ->+ Bit -> Bit'+ template: ~ARG[0] xor ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.complement##+ kind: Expression+ type: 'complement## ::+ Bit -> Bit'+ template: not ~ARG[0]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.++#+ kind: Expression+ type: '(++#) :: KnownNat+ m => BitVector n -> BitVector m -> BitVector (n + m)'+ template: ~IF~AND[~SIZE[~TYP[1]],~SIZE[~TYP[2]]]~THENstd_logic_vector'(std_logic_vector'(~ARG[1])+ & std_logic_vector'(~ARG[2]))~ELSE~IF~SIZE[~TYP[1]]~THENstd_logic_vector'(~ARG[1])~ELSEstd_logic_vector'(~ARG[2])~FI~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.reduceAnd#+ kind: Declaration+ type: 'reduceAnd# :: KnownNat+ n => BitVector n -> Bit'+ template: |-+ -- reduceAnd begin,+ ~IF~SIZE[~TYP[1]]~THEN+ ~GENSYM[reduceAnd][0] : block+ function and_reduce (arg : std_logic_vector) return std_logic is+ variable upper, lower : std_logic;+ variable half : integer;+ variable argi : std_logic_vector (arg'length - 1 downto 0);+ variable result : std_logic;+ begin+ if (arg'length < 1) then+ result := '1';+ else+ argi := arg;+ if (argi'length = 1) then+ result := argi(argi'left);+ else+ half := (argi'length + 1) / 2; -- lsb-biased tree+ upper := and_reduce (argi (argi'left downto half));+ lower := and_reduce (argi (half - 1 downto argi'right));+ result := upper and lower;+ end if;+ end if;+ return result;+ end;+ begin+ ~RESULT <= and_reduce(~ARG[1]);+ end block;~ELSE+ ~RESULT <= '1';~FI+ -- reduceAnd end+- BlackBox:+ name: Clash.Sized.Internal.BitVector.reduceOr#+ kind: Declaration+ type: 'reduceOr# :: KnownNat+ n => BitVector n -> Bit'+ template: |-+ -- reduceOr begin ~IF~SIZE[~TYP[1]]~THEN+ ~GENSYM[reduceOr][0] : block+ function or_reduce (arg : std_logic_vector) return std_logic is+ variable upper, lower : std_logic;+ variable half : integer;+ variable argi : std_logic_vector (arg'length - 1 downto 0);+ variable result : std_logic;+ begin+ if (arg'length < 1) then+ result := '0';+ else+ argi := arg;+ if (argi'length = 1) then+ result := argi(argi'left);+ else+ half := (argi'length + 1) / 2; -- lsb-biased tree+ upper := or_reduce (argi (argi'left downto half));+ lower := or_reduce (argi (half - 1 downto argi'right));+ result := upper or lower;+ end if;+ end if;+ return result;+ end;+ begin+ ~RESULT <= or_reduce(~ARG[1]);+ end block;~ELSE+ ~RESULT <= '0'; ~FI+ -- reduceOr end+- BlackBox:+ name: Clash.Sized.Internal.BitVector.reduceXor#+ kind: Declaration+ type: 'reduceXor# :: KnownNat+ n => BitVector n -> Bit'+ template: |-+ -- reduceXor begin ~IF~SIZE[~TYP[1]]~THEN+ ~GENSYM[reduceXor][0] : block+ function xor_reduce (arg : std_logic_vector) return std_logic is+ variable upper, lower : std_logic;+ variable half : integer;+ variable argi : std_logic_vector (arg'length - 1 downto 0);+ variable result : std_logic;+ begin+ if (arg'length < 1) then+ result := '0';+ else+ argi := arg;+ if (argi'length = 1) then+ result := argi(argi'left);+ else+ half := (argi'length + 1) / 2; -- lsb-biased tree+ upper := xor_reduce (argi (argi'left downto half));+ lower := xor_reduce (argi (half - 1 downto argi'right));+ result := upper xor lower;+ end if;+ end if;+ return result;+ end;+ begin+ ~RESULT <= xor_reduce(~ARG[1]);+ end block;~ELSE+ ~RESULT <= '0';~FI+ -- reduceXor end+- BlackBox:+ name: Clash.Sized.Internal.BitVector.index#+ kind: Declaration+ type: |-+ index# :: KnownNat n -- ARG[0]+ => BitVector n -- ARG[1]+ -> Int -- ARG[2]+ -> Bit+ template: |-+ -- indexBitVector begin ~IF~SIZE[~TYP[1]]~THEN~IF ~ISVAR[1] ~THEN+ ~GENSYM[indexBitVector][0] : block+ signal ~GENSYM[vec_index][1] : integer range 0 to ~SIZE[~TYP[1]]-1;+ begin+ ~SYM[1] <= to_integer(~ARG[2])+ -- pragma translate_off+ mod ~SIZE[~TYP[1]]+ -- pragma translate_on+ ;++ ~RESULT <= ~ARG[1](~SYM[1]);+ end block;~ELSE+ ~SYM[0] : block+ signal ~SYM[1] : integer range 0 to ~SIZE[~TYP[1]]-1;+ begin+ ~SYM[1] <= to_integer(~ARG[2])+ -- pragma translate_off+ mod ~SIZE[~TYP[1]]+ -- pragma translate_on+ ;++ ~RESULT <= ~VAR[bv][1](~SYM[1]);+ end block;~FI~ELSE+ ~RESULT <= ~ERRORO;~FI+ -- indexBitVector end+- BlackBox:+ name: Clash.Sized.Internal.BitVector.replaceBit#+ kind: Declaration+ type: |-+ replaceBit# :: KnownNat n -- ARG[0]+ => BitVector n -- ARG[1]+ -> Int -- ARG[2]+ -> Bit -- ARG[3]+ -> BitVector n+ template: |-+ -- replaceBit begin ~IF~SIZE[~TYP[1]]~THEN+ ~GENSYM[replaceBit][0] : block+ signal ~GENSYM[vec_index][1] : integer range 0 to ~SIZE[~TYP[1]]-1;+ begin+ ~SYM[1] <= to_integer(~ARG[2])+ -- pragma translate_off+ mod ~SIZE[~TYP[1]]+ -- pragma translate_on+ ;++ process(~SYM[1],~VAR[b][3]~VARS[1])+ variable ~GENSYM[ivec][2] : ~TYP[1];+ begin+ ~SYM[2] := ~ARG[1];+ ~SYM[2](~SYM[1]) := ~ARG[3];+ ~RESULT <= ~SYM[2];+ end process;+ end block; ~ELSE+ ~RESULT <= ~ERRORO;~FI+ -- replaceBit end+- BlackBox:+ name: Clash.Sized.Internal.BitVector.setSlice#+ kind: Declaration+ type: |-+ setSlice# :: SNat (m + 1 + i)+ => BitVector (m + 1 + i) -- ARG[1]+ -> SNat m -- ARG[2]+ -> SNat n -- ARG[3]+ -> BitVector (m + 1 - n) -- ARG[4]+ -> BitVector (m + 1 + i)+ template: |-+ -- setSlice begin+ ~GENSYM[setSlice][0] : process(~VAR[bv][1]~VARS[4])+ variable ~GENSYM[ivec][1] : ~TYP[1];+ begin+ ~SYM[1] := ~VAR[bv][1];+ ~SYM[1](~LIT[2] downto ~LIT[3]) := ~ARG[4];+ ~RESULT <= ~SYM[1];+ end process;+ -- setSlice end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.slice#+ kind: Expression+ type: |-+ slice# :: BitVector (m + 1 + i) -- ARG[0]+ -> SNat m -- ARG[1]+ -> SNat n -- ARG[2]+ -> BitVector (m + 1 - n)+ template: ~VAR[bv][0](~LIT[1] downto ~LIT[2])+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.split#+ kind: Expression+ type: |-+ split# :: KnownNat n -- ARG[0]+ => BitVector (m + n) -- ARG[1]+ -> (BitVector m, BitVector n)+ template: (~VAR[bv][1](~VAR[bv][1]'high downto ~LIT[0]),~VAR[bv][1](~LIT[0]-1+ downto 0))+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.msb#+ kind: Expression+ type: |-+ msb# :: KnownNat n -- ARG[0]+ => BitVector n -- ARG[1]+ -> Bit+ template: ~IF ~SIZE[~TYP[1]] ~THEN ~VAR[bv][1](~VAR[bv][1]'high) ~ELSE "0" ~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.lsb#+ kind: Expression+ type: |-+ lsb# :: BitVector n -- ARG[0]+ -> Bit+ template: ~IF ~SIZE[~TYP[0]] ~THEN ~VAR[bv][0](0) ~ELSE "0" ~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.eq#+ kind: Expression+ type: 'eq# :: KnownNat+ n => BitVector n -> BitVector n -> Bool'+ template: ~IF~SIZE[~TYP[1]]~THEN~ARG[1] = ~ARG[2]~ELSEtrue~FI+- BlackBox:+ name: Clash.Sized.Internal.BitVector.neq#+ kind: Expression+ type: 'neq# :: KnownNat+ n => BitVector n -> BitVector n -> Bool'+ template: ~IF~SIZE[~TYP[1]]~THEN~ARG[1] /= ~ARG[2]~ELSEfalse~FI+- BlackBox:+ name: Clash.Sized.Internal.BitVector.lt#+ kind: Expression+ type: 'lt# :: KnownNat+ n => BitVector n -> BitVector n -> Bool'+ template: ~IF~SIZE[~TYP[1]]~THEN~ARG[1] < ~ARG[2]~ELSEfalse~FI+- BlackBox:+ name: Clash.Sized.Internal.BitVector.ge#+ kind: Expression+ type: 'ge# :: KnownNat+ n => BitVector n -> BitVector n -> Bool'+ template: ~IF~SIZE[~TYP[1]]~THEN~ARG[1] >= ~ARG[2]~ELSEtrue~FI+- BlackBox:+ name: Clash.Sized.Internal.BitVector.gt#+ kind: Expression+ type: 'gt# :: KnownNat+ n => BitVector n -> BitVector n -> Bool'+ template: ~IF~SIZE[~TYP[1]]~THEN~ARG[1] > ~ARG[2]~ELSEfalse~FI+- BlackBox:+ name: Clash.Sized.Internal.BitVector.le#+ kind: Expression+ type: 'le# :: KnownNat+ n => BitVector n -> BitVector n -> Bool'+ template: ~IF~SIZE[~TYP[1]]~THEN~ARG[1] <= ~ARG[2]~ELSEtrue~FI+- BlackBox:+ name: Clash.Sized.Internal.BitVector.minBound#+ kind: Expression+ type: 'minBound# :: BitVector+ n'+ template: ~IF~SIZE[~TYPO]~THENstd_logic_vector'(~SIZE[~TYPO]-1 downto 0 => '0')~ELSEstd_logic_vector'(0+ downto 1 => '0')~FI+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Internal.BitVector.maxBound#+ kind: Expression+ type: 'maxBound# :: KnownNat+ n => BitVector n'+ template: ~IF~SIZE[~TYPO]~THENstd_logic_vector'(~SIZE[~TYPO]-1 downto 0 => '1')~ELSEstd_logic_vector'(0+ downto 1 => '1')~FI+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Internal.BitVector.+#+ kind: Expression+ type: '(+#) :: KnownNat+ n => BitVector n -> BitVector n -> BitVector n'+ template: std_logic_vector(unsigned(~ARG[1]) + unsigned(~ARG[2]))+- BlackBox:+ name: Clash.Sized.Internal.BitVector.-#+ kind: Expression+ type: '(-#) :: KnownNat+ n => BitVector n -> BitVector n -> BitVector n'+ template: std_logic_vector(unsigned(~ARG[1]) - unsigned(~ARG[2]))+- BlackBox:+ name: Clash.Sized.Internal.BitVector.*#+ kind: Expression+ type: '(*#) :: KnownNat+ n => BitVector n -> BitVector n -> BitVector n'+ template: std_logic_vector(resize(unsigned(~ARG[1]) * unsigned(~ARG[2]), ~SIZE[~TYP[1]]))+- BlackBox:+ name: Clash.Sized.Internal.BitVector.negate#+ kind: Expression+ type: 'negate# :: KnownNat+ n => BitVector n -> BitVector n'+ template: std_logic_vector(-(signed(~ARG[1])))+- BlackBox:+ name: Clash.Sized.Internal.BitVector.fromInteger#+ kind: Expression+ type: 'fromInteger# ::+ KnownNat n => Integer -> Integer -> BitVector n'+ template: std_logic_vector(resize(unsigned(std_logic_vector(~ARG[2])),~SIZE[~TYPO]))+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.toEnum#+ kind: Expression+ type: 'toEnum# :: KnownNat+ n => Int -> BitVector n'+ template: std_logic_vector(resize(unsigned(std_logic_vector(~ARG[1])),~SIZE[~TYPO]))+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.fromEnum#+ kind: Expression+ type: 'fromEnum# :: KnownNat+ n => BitVector n -> Int'+ template: ~IF~SIZE[~TYP[1]]~THENsigned(std_logic_vector(resize(unsigned(~ARG[1]),~SIZE[~TYPO])))~ELSEto_signed(0,~SIZE[~TYPO])~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.plus#+ kind: Expression+ type: 'plus# :: (KnownNat+ m, KnownNat n) => BitVector m -> BitVector n -> BitVector (Max m n + 1)'+ template: ~IF~AND[~SIZE[~TYP[2]],~SIZE[~TYP[3]]]~THENstd_logic_vector(resize(unsigned(~ARG[2]),~SIZE[~TYPO])+ + resize(unsigned(~ARG[3]),~SIZE[~TYPO]))~ELSE~IF~SIZE[~TYP[2]]~THENstd_logic_vector(resize(unsigned(~ARG[2]),~SIZE[~TYPO]))~ELSEstd_logic_vector(resize(unsigned(~ARG[3]),~SIZE[~TYPO]))~FI~FI+- BlackBox:+ name: Clash.Sized.Internal.BitVector.minus#+ kind: Expression+ type: 'minus# :: (KnownNat+ m, KnownNat n) => BitVector m -> BitVector n -> BitVector (Max m n + 1)'+ template: ~IF~AND[~SIZE[~TYP[2]],~SIZE[~TYP[3]]]~THENstd_logic_vector(resize(unsigned(~ARG[2]),~SIZE[~TYPO])+ - resize(unsigned(~ARG[3]),~SIZE[~TYPO]))~ELSE~IF~SIZE[~TYP[2]]~THENstd_logic_vector(resize(unsigned(~ARG[2]),~SIZE[~TYPO]))~ELSEstd_logic_vector(-resize(signed(~ARG[3]),~SIZE[~TYPO]))~FI~FI+- BlackBox:+ name: Clash.Sized.Internal.BitVector.times#+ kind: Expression+ type: 'times# :: (KnownNat+ m, KnownNat n) => BitVector m -> BitVector n -> BitVector (m + n)'+ template: ~IF~AND[~SIZE[~TYP[2]],~SIZE[~TYP[3]]]~THENstd_logic_vector(unsigned(~ARG[2])+ * unsigned(~ARG[3]))~ELSE(~SIZE[~TYPO]-1 downto 0 => '0')~FI+- BlackBox:+ name: Clash.Sized.Internal.BitVector.quot#+ kind: Declaration+ type: 'quot# :: KnownNat+ n => BitVector n -> BitVector n -> BitVector n'+ template: |-+ ~RESULT <= std_logic_vector(unsigned(~ARG[1]) / unsigned(~ARG[2]))+ -- pragma translate_off+ when (~ARG[2] /= std_logic_vector(to_unsigned(0,~SIZE[~TYP[2]]))) else (others => 'X')+ -- pragma translate_on+ ;+- BlackBox:+ name: Clash.Sized.Internal.BitVector.rem#+ kind: Declaration+ type: 'rem# :: KnownNat+ n => BitVector n -> BitVector n -> BitVector n'+ template: |-+ ~RESULT <= std_logic_vector(unsigned(~ARG[1]) rem unsigned(~ARG[2]))+ -- pragma translate_off+ when (~ARG[2] /= std_logic_vector(to_unsigned(0,~SIZE[~TYP[2]]))) else (others => 'X')+ -- pragma translate_on+ ;+- BlackBoxHaskell:+ name: Clash.Sized.Internal.BitVector.toInteger#+ templateFunction: Clash.Primitives.Sized.ToInteger.bvToIntegerVHDL+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.BitVector.and#+ kind: Expression+ type: 'and# :: KnownNat+ n => BitVector n -> BitVector n -> BitVector n'+ template: ~ARG[1] and ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.or#+ kind: Expression+ type: 'or# :: KnownNat+ n => BitVector n -> BitVector n -> BitVector n'+ template: ~ARG[1] or ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.xor#+ kind: Expression+ type: 'xor# :: KnownNat+ n => BitVector n -> BitVector n -> BitVector n'+ template: ~ARG[1] xor ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.complement#+ kind: Expression+ type: 'complement# ::+ KnownNat n => BitVector n -> BitVector n'+ template: not ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.BitVector.shiftL#+ kind: Declaration+ type: 'shiftL# :: KnownNat+ n => BitVector n -> Int -> BitVector n'+ template: |-+ ~GENSYM[~RESULT_shiftL][0] : block+ signal ~GENSYM[sh][1] : natural;+ begin+ ~SYM[1] <=+ -- pragma translate_off+ natural'high when (~VAR[shI][2](~SIZE[~TYP[2]]-1 downto 31) /= 0) else+ -- pragma translate_on+ to_integer(~VAR[shI][2]+ -- pragma translate_off+ (30 downto 0)+ -- pragma translate_on+ );+ ~RESULT <= std_logic_vector(shift_left(unsigned(~ARG[1]),~SYM[1]))+ -- pragma translate_off+ when (~ARG[2] >= 0) else (others => 'X')+ -- pragma translate_on+ ;+ end block;+- BlackBox:+ name: Clash.Sized.Internal.BitVector.shiftR#+ kind: Declaration+ type: 'shiftR# :: KnownNat+ n => BitVector n -> Int -> BitVector n'+ template: |-+ ~GENSYM[~RESULT_shiftR][0] : block+ signal ~GENSYM[sh][1] : natural;+ begin+ ~SYM[1] <=+ -- pragma translate_off+ natural'high when (~VAR[shI][2](~SIZE[~TYP[2]]-1 downto 31) /= 0) else+ -- pragma translate_on+ to_integer(~VAR[shI][2]+ -- pragma translate_off+ (30 downto 0)+ -- pragma translate_on+ );+ ~RESULT <= std_logic_vector(shift_right(unsigned(~ARG[1]),~SYM[1]))+ -- pragma translate_off+ when (~ARG[2] >= 0) else (others => 'X')+ -- pragma translate_on+ ;+ end block;+- BlackBox:+ name: Clash.Sized.Internal.BitVector.rotateL#+ kind: Declaration+ type: 'rotateL# :: KnownNat+ n => BitVector n -> Int -> BitVector n'+ template: |-+ ~RESULT <= std_logic_vector(rotate_left(unsigned(~ARG[1]),to_integer((~ARG[2])+ -- pragma translate_off+ mod ~SIZE[~TYP[1]]+ -- pragma translate_on+ )))+ -- pragma translate_off+ when (~ARG[2] >= 0) else (others => 'X')+ -- pragma translate_on+ ;+- BlackBox:+ name: Clash.Sized.Internal.BitVector.rotateR#+ kind: Declaration+ type: 'rotateR# :: KnownNat+ n => BitVector n -> Int -> BitVector n'+ template: |-+ ~RESULT <= std_logic_vector(rotate_right(unsigned(~ARG[1]),to_integer((~ARG[2])+ -- pragma translate_off+ mod ~SIZE[~TYP[1]]+ -- pragma translate_on+ )))+ -- pragma translate_off+ when (~ARG[2] >= 0) else (others => 'X')+ -- pragma translate_on+ ;+- BlackBox:+ name: Clash.Sized.Internal.BitVector.truncateB#+ kind: Expression+ type: 'truncateB# :: forall+ a b . KnownNat a => BitVector (a + b) -> BitVector a'+ template: std_logic_vector(resize(unsigned(~ARG[1]),~SIZE[~TYPO]))+ workInfo: Never
− prims/vhdl/Clash_Sized_Internal_Index.primitives
@@ -1,138 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.pack#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "pack# :: Index n -> BitVector (CLog 2 n)"- , "template" : "std_logic_vector(~ARG[0])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.unpack#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "unpack# :: (KnownNat n, 1 <= n) => BitVector (CLog 2 n) -> Index n"- , "template" : "unsigned(~ARG[2])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.eq#"- , "kind" : "Expression"- , "type" : "eq# :: Index n -> Index n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] = ~ARG[1]~ELSEtrue~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.neq#"- , "kind" : "Expression"- , "type" : "neq# :: Index n -> Index n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] /= ~ARG[1]~ELSEfalse~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.lt#"- , "kind" : "Expression"- , "type" : "lt# :: Index n -> Index n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] < ~ARG[1]~ELSEfalse~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.ge#"- , "kind" : "Expression"- , "type" : "ge# :: Index n -> Index n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] >= ~ARG[1]~ELSEtrue~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.gt#"- , "kind" : "Expression"- , "type" : "gt# :: Index n -> Index n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] > ~ARG[1]~ELSEfalse~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.le#"- , "kind" : "Expression"- , "type" : "le# :: Index n -> Index n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] <= ~ARG[1]~ELSEtrue~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.maxBound#"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "maxBound# :: KnownNat n => Index n"- , "template" : "to_unsigned(~LIT[0]-1,~SIZE[~TYPO])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.+#"- , "kind" : "Expression"- , "type" : "(+#) :: KnownNat n => Index n -> Index n -> Index n"- , "template" : "~ARG[1] + ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.-#"- , "kind" : "Expression"- , "type" : "(-#) :: KnownNat n => Index n -> Index n -> Index n"- , "template" : "~ARG[1] - ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.*#"- , "kind" : "Expression"- , "type" : "(*#) :: KnownNat n => Index n -> Index n -> Index n"- , "template" : "resize(~ARG[1] * ~ARG[2], ~SIZE[~TYPO])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.fromInteger#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "fromInteger# :: KnownNat n => Integer -> Index n"- , "template" : "resize(unsigned(std_logic_vector(~ARG[1])),~SIZE[~TYPO])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.plus#"- , "kind" : "Expression"- , "type" : "Index m -> Index n -> Index (m + n - 1)"- , "template" : "resize(~ARG[0],~SIZE[~TYPO]) + resize(~ARG[1],~SIZE[~TYPO])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.minus#"- , "kind" : "Expression"- , "type" : "Index m -> Index n -> Index (m + n - 1)"- , "template" : "resize(~ARG[0],~SIZE[~TYPO]) - resize(~ARG[1],~SIZE[~TYPO])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.times#"- , "kind" : "Expression"- , "type" : "Index m -> Index n -> Index (((m-1) * (n-1)) + 1)"- , "template" : "resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.rem#"- , "kind" : "Expression"- , "type" : "rem# :: Index n -> Index n -> Index n"- , "template" : "~ARG[0] rem ~ARG[1]"- }- }-, { "BlackBoxHaskell" :- { "name" : "Clash.Sized.Internal.Index.toInteger#"- , "workInfo" : "Never"- , "templateFunction" : "Clash.Primitives.Sized.ToInteger.indexToIntegerVHDL"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.resize#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "resize# :: KnownNat m => Index n -> Index m"- , "template" : "~IF~SIZE[~TYP[1]]~THENresize(~ARG[1],~SIZE[~TYPO])~ELSEunsigned'(~SIZE[~TYPO]-1 downto 0 => '0')~FI"- }- }-]
+ prims/vhdl/Clash_Sized_Internal_Index.primitives.yaml view
@@ -0,0 +1,148 @@+- BlackBox:+ name: Clash.Sized.Internal.Index.pack#+ kind: Expression+ type: 'pack# :: Index+ n -> BitVector (CLog 2 n)'+ template: std_logic_vector(~ARG[0])+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Index.unpack#+ kind: Expression+ type: 'unpack# :: (KnownNat+ n, 1 <= n) => BitVector (CLog 2 n) -> Index n'+ template: unsigned(~ARG[2])+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Index.eq#+ kind: Expression+ type: 'eq# :: Index n+ -> Index n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] = ~ARG[1]~ELSEtrue~FI+- BlackBox:+ name: Clash.Sized.Internal.Index.neq#+ kind: Expression+ type: 'neq# :: Index n+ -> Index n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] /= ~ARG[1]~ELSEfalse~FI+- BlackBox:+ name: Clash.Sized.Internal.Index.lt#+ kind: Expression+ type: 'lt# :: Index n+ -> Index n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] < ~ARG[1]~ELSEfalse~FI+- BlackBox:+ name: Clash.Sized.Internal.Index.ge#+ kind: Expression+ type: 'ge# :: Index n+ -> Index n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] >= ~ARG[1]~ELSEtrue~FI+- BlackBox:+ name: Clash.Sized.Internal.Index.gt#+ kind: Expression+ type: 'gt# :: Index n+ -> Index n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] > ~ARG[1]~ELSEfalse~FI+- BlackBox:+ name: Clash.Sized.Internal.Index.le#+ kind: Expression+ type: 'le# :: Index n+ -> Index n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] <= ~ARG[1]~ELSEtrue~FI+- BlackBox:+ name: Clash.Sized.Internal.Index.maxBound#+ kind: Expression+ type: 'maxBound# :: KnownNat+ n => Index n'+ template: to_unsigned(~LIT[0]-1,~SIZE[~TYPO])+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Internal.Index.toEnum#+ kind: Expression+ type: 'toEnum# :: KnownNat+ n => Int -> Index n'+ template: resize(unsigned(std_logic_vector(~ARG[1])),~SIZE[~TYPO])+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Index.fromEnum#+ kind: Expression+ type: 'fromEnum# :: KnownNat+ n => Index n -> Int'+ template: ~IF~SIZE[~TYP[1]]~THENsigned(std_logic_vector(resize(~ARG[1],~SIZE[~TYPO])))~ELSEto_signed(0,~SIZE[~TYPO])~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Index.+#+ kind: Expression+ type: '(+#) :: KnownNat+ n => Index n -> Index n -> Index n'+ template: ~ARG[1] + ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.Index.-#+ kind: Expression+ type: '(-#) :: KnownNat+ n => Index n -> Index n -> Index n'+ template: ~ARG[1] - ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.Index.*#+ kind: Expression+ type: '(*#) :: KnownNat+ n => Index n -> Index n -> Index n'+ template: resize(~ARG[1] * ~ARG[2], ~SIZE[~TYPO])+- BlackBox:+ name: Clash.Sized.Internal.Index.fromInteger#+ kind: Expression+ type: 'fromInteger# ::+ KnownNat n => Integer -> Index n'+ template: resize(unsigned(std_logic_vector(~ARG[1])),~SIZE[~TYPO])+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Index.plus#+ kind: Expression+ type: Index m -> Index+ n -> Index (m + n - 1)+ template: resize(~ARG[0],~SIZE[~TYPO]) + resize(~ARG[1],~SIZE[~TYPO])+- BlackBox:+ name: Clash.Sized.Internal.Index.minus#+ kind: Expression+ type: Index m -> Index+ n -> Index (m + n - 1)+ template: resize(~ARG[0],~SIZE[~TYPO]) - resize(~ARG[1],~SIZE[~TYPO])+- BlackBox:+ name: Clash.Sized.Internal.Index.times#+ kind: Expression+ type: Index m -> Index+ n -> Index (((m-1) * (n-1)) + 1)+ template: resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO])+- BlackBox:+ name: Clash.Sized.Internal.Index.rem#+ kind: Declaration+ type: 'rem# :: Index n+ -> Index n -> Index n'+ template: |-+ ~RESULT <= ~ARG[0] rem ~ARG[1]+ -- pragma translate_off+ when (~ARG[1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;+- BlackBoxHaskell:+ name: Clash.Sized.Internal.Index.toInteger#+ templateFunction: Clash.Primitives.Sized.ToInteger.indexToIntegerVHDL+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Index.resize#+ kind: Expression+ type: 'resize# :: KnownNat+ m => Index n -> Index m'+ template: ~IF~SIZE[~TYP[1]]~THENresize(~ARG[1],~SIZE[~TYPO])~ELSEunsigned'(~SIZE[~TYPO]-1+ downto 0 => '0')~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Index.quot#+ kind: Declaration+ type: 'quot# :: Index+ n -> Index n -> Index n'+ template: |-+ ~RESULT <= ~ARG[0] / ~ARG[1]+ -- pragma translate_off+ when (~ARG[1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;
− prims/vhdl/Clash_Sized_Internal_Signed.primitives
@@ -1,270 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.size#"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "size# :: KnownNat n => Signed n -> Int"- , "template" : "to_signed(~LIT[0],~SIZE[~TYPO])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.pack#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "pack# :: KnownNat n => Signed n -> BitVector n"- , "template" : "std_logic_vector(~ARG[1])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.unpack#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "unpack# :: KnownNat n => BitVector n -> Signed n"- , "template" : "signed(~ARG[1])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.eq#"- , "kind" : "Expression"- , "type" : "eq# :: Signed n -> Signed n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] = ~ARG[1]~ELSEtrue~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.neq#"- , "kind" : "Expression"- , "type" : "neq# :: Signed n -> Signed n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] /= ~ARG[1]~ELSEfalse~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.lt#"- , "kind" : "Expression"- , "type" : "lt# :: Signed n -> Signed n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] < ~ARG[1]~ELSEfalse~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.ge#"- , "kind" : "Expression"- , "type" : "ge# :: Signed n -> Signed n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] >= ~ARG[1]~ELSEtrue~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.gt#"- , "kind" : "Expression"- , "type" : "gt# :: Signed n -> Signed n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] > ~ARG[1]~ELSEfalse~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.le#"- , "kind" : "Expression"- , "type" : "le# :: Signed n -> Signed n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] <= ~ARG[1]~ELSEtrue~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.minBound#"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "minBound# :: KnownNat n => Signed n"- , "comment" : "the quantification with signed gives the array an ascending index"- , "template" : "~IF~SIZE[~TYPO]~THENsigned'(0 => '1', 1 to ~LIT[0]-1 => '0')~ELSEsigned'(1 downto 0 => '0')~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.maxBound#"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "maxBound# :: KnownNat n => Signed n"- , "comment" : "the quantification with signed gives the array an ascending index"- , "template" : "~IF~SIZE[~TYPO]~THENsigned'(0 => '0', 1 to ~LIT[0]-1 => '1')~ELSEsigned'(1 downto 0 => '0')~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.*#"- , "kind" : "Expression"- , "type" : "(*#) :: KnownNat n => Signed n -> Signed n -> Signed n"- , "template" : "resize(~ARG[1] * ~ARG[2], ~LIT[0])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.negate#"- , "kind" : "Expression"- , "type" : "negate# :: KnownNat n => Signed n -> Signed n"- , "template" : "-~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.abs#"- , "kind" : "Expression"- , "type" : "abs# :: KnownNat n => Signed n -> Signed n"- , "template" : "abs ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.fromInteger#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "fromInteger# :: KnownNat n => Integer -> Signed (n :: Nat)"- , "template" : "resize(~ARG[1],~LIT[0])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.plus#"- , "kind" : "Expression"- , "type" : "plus# :: Signed m -> Signed n -> Signed (1 + Max m n)"- , "template" : "~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THENresize(~ARG[0],~SIZE[~TYPO]) + resize(~ARG[1],~SIZE[~TYPO])~ELSE~IF~SIZE[~TYP[0]]~THENresize(~ARG[0],~SIZE[~TYPO])~ELSEresize(~ARG[1],~SIZE[~TYPO])~FI~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.minus#"- , "kind" : "Expression"- , "type" : "minus# :: Signed m -> Signed n -> Signed (1 + Max m n)"- , "template" : "~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THENresize(~ARG[0],~SIZE[~TYPO]) - resize(~ARG[1],~SIZE[~TYPO])~ELSE~IF~SIZE[~TYP[0]]~THENresize(~ARG[0],~SIZE[~TYPO])~ELSEresize(- ~ARG[1],~SIZE[~TYPO])~FI~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.times#"- , "kind" : "Expression"- , "type" : "times# :: Signed m -> Signed n -> Signed (m + n)"- , "template" : "~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THEN~ARG[0] * ~ARG[1]~ELSEsigned'(~SIZE[~TYPO]-1 downto 0 => '0')~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.rem#"- , "kind" : "Expression"- , "type" : "rem# :: Signed n -> Signed n -> Signed n"- , "template" : "~ARG[0] rem ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.div#"- , "kind" : "Declaration"- , "type" : "div# :: Signed n -> Signed n -> Signed n"- , "template" :-"-- divSigned begin-~GENSYM[divSigned][0] : block- signal ~GENSYM[resultPos][1] : boolean;- signal ~GENSYM[dividerNeg][2] : boolean;- signal ~GENSYM[dividend2][3] : signed(~SIZE[~TYPO] downto 0);- signal ~GENSYM[quot_res][4] : signed(~SIZE[~TYPO] downto 0);-begin- ~SYM[1] <= ~VAR[dividend][0](~VAR[dividend][0]'high) = ~VAR[divider][1](~VAR[divider][1]'high);- ~SYM[2] <= ~VAR[divider][1](~VAR[divider][1]'high) = '1';- ~SYM[3] <= resize(~VAR[dividend][0],~SIZE[~TYPO]+1) when ~SYM[1] else- (resize(~VAR[dividend][0],~SIZE[~TYPO]+1) - resize(~VAR[divider][1],~SIZE[~TYPO]+1) - 1) when ~SYM[2] else- (resize(~VAR[dividend][0],~SIZE[~TYPO]+1) - resize(~VAR[divider][1],~SIZE[~TYPO]+1) + 1);- ~SYM[4] <= ~SYM[3] / ~VAR[divider][1];- ~RESULT <= signed(~SYM[4](~SIZE[~TYPO]-1 downto 0));-end block;--- divSigned end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.mod#"- , "kind" : "Expression"- , "type" : "mod# :: Signed n -> Signed n -> Signed n"- , "template" : "~ARG[0] mod ~ARG[1]"- }- }-, { "BlackBoxHaskell" :- { "name" : "Clash.Sized.Internal.Signed.toInteger#"- , "workInfo" : "Never"- , "templateFunction" : "Clash.Primitives.Sized.ToInteger.signedToIntegerVHDL"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.and#"- , "kind" : "Expression"- , "type" : "and# :: KnownNat n => Signed n -> Signed n -> Signed n"- , "template" : "~ARG[1] and ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.or#"- , "kind" : "Expression"- , "type" : "or# :: KnownNat n => Signed n -> Signed n -> Signed n"- , "template" : "~ARG[1] or ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.xor#"- , "kind" : "Expression"- , "type" : "xor# :: KnownNat n => Signed n -> Signed n -> Signed n"- , "template" : "~ARG[1] xor ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.complement#"- , "kind" : "Expression"- , "type" : "complement# :: KnownNat n => Signed n -> Signed n"- , "template" : "not ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.shiftL#"- , "kind" : "Declaration"- , "type" : "shiftL# :: KnownNat n => Signed n -> Int -> Signed n"- , "template" :-"~RESULT <= shift_left(~ARG[1],to_integer(~ARG[2]))- -- pragma translate_off- when (~ARG[2] >= 0) else (others => 'X')- -- pragma translate_on- ;"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.shiftR#"- , "kind" : "Declaration"- , "type" : "shiftR# :: KnownNat n => Signed n -> Int -> Signed n"- , "template" :-"~RESULT <= shift_right(~ARG[1],to_integer(~ARG[2]))- -- pragma translate_off- when (~ARG[2] >= 0) else (others => 'X')- -- pragma translate_on- ;"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.rotateL#"- , "kind" : "Declaration"- , "type" : "rotateL# :: KnownNat n => Signed n -> Int -> Signed n"- , "template" :-"~RESULT <= rotate_left(~ARG[1],to_integer(~ARG[2]))- -- pragma translate_off- when (~ARG[2] >= 0) else (others => 'X')- -- pragma translate_on- ;"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.rotateR#"- , "kind" : "Declaration"- , "type" : "rotateR# :: KnownNat n => Signed n -> Int -> Signed n"- , "template" :-"~RESULT <= rotate_right(~ARG[1],to_integer(~ARG[2]))- -- pragma translate_off- when (~ARG[2] >= 0) else (others => 'X')- -- pragma translate_on- ;"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.resize#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "resize# :: (KnownNat n, KnownNat m) => Signed n -> Signed m"- , "template" : "~IF~SIZE[~TYP[2]]~THENresize(~ARG[2],~LIT[1])~ELSEsigned'(~SIZE[~TYPO]-1 downto 0 => '0')~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.truncateB#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "truncateB# :: KnownNat m => Signed (n + m) -> Signed m"- , "template" : "~IF~SIZE[~TYPO]~THEN~VAR[s][1](~LIT[0]-1 downto 0)~ELSEsigned'(0 downto 1 => '0')~FI"- }- }-]
+ prims/vhdl/Clash_Sized_Internal_Signed.primitives.yaml view
@@ -0,0 +1,318 @@+- BlackBox:+ name: Clash.Sized.Internal.Signed.size#+ kind: Expression+ type: 'size# :: KnownNat+ n => Signed n -> Int'+ template: to_signed(~LIT[0],~SIZE[~TYPO])+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Internal.Signed.pack#+ kind: Expression+ type: 'pack# :: KnownNat+ n => Signed n -> BitVector n'+ template: std_logic_vector(~ARG[1])+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Signed.unpack#+ kind: Expression+ type: 'unpack# :: KnownNat+ n => BitVector n -> Signed n'+ template: signed(~ARG[1])+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Signed.eq#+ kind: Expression+ type: 'eq# :: Signed n+ -> Signed n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] = ~ARG[1]~ELSEtrue~FI+- BlackBox:+ name: Clash.Sized.Internal.Signed.neq#+ kind: Expression+ type: 'neq# :: Signed+ n -> Signed n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] /= ~ARG[1]~ELSEfalse~FI+- BlackBox:+ name: Clash.Sized.Internal.Signed.lt#+ kind: Expression+ type: 'lt# :: Signed n+ -> Signed n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] < ~ARG[1]~ELSEfalse~FI+- BlackBox:+ name: Clash.Sized.Internal.Signed.ge#+ kind: Expression+ type: 'ge# :: Signed n+ -> Signed n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] >= ~ARG[1]~ELSEtrue~FI+- BlackBox:+ name: Clash.Sized.Internal.Signed.gt#+ kind: Expression+ type: 'gt# :: Signed n+ -> Signed n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] > ~ARG[1]~ELSEfalse~FI+- BlackBox:+ name: Clash.Sized.Internal.Signed.le#+ kind: Expression+ type: 'le# :: Signed n+ -> Signed n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] <= ~ARG[1]~ELSEtrue~FI+- BlackBox:+ name: Clash.Sized.Internal.Signed.minBound#+ comment: the quantification with signed gives the array an ascending index+ kind: Expression+ type: 'minBound# :: KnownNat+ n => Signed n'+ template: ~IF~SIZE[~TYPO]~THENsigned'(0 => '1', 1 to ~LIT[0]-1 => '0')~ELSEsigned'(1+ downto 0 => '0')~FI+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Internal.Signed.maxBound#+ comment: the quantification with signed gives the array an ascending index+ kind: Expression+ type: 'maxBound# :: KnownNat+ n => Signed n'+ template: ~IF~SIZE[~TYPO]~THENsigned'(0 => '0', 1 to ~LIT[0]-1 => '1')~ELSEsigned'(1+ downto 0 => '0')~FI+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Internal.Signed.*#+ kind: Expression+ type: '(*#) :: KnownNat+ n => Signed n -> Signed n -> Signed n'+ template: resize(~ARG[1] * ~ARG[2], ~LIT[0])+- BlackBox:+ name: Clash.Sized.Internal.Signed.negate#+ kind: Expression+ type: 'negate# :: KnownNat+ n => Signed n -> Signed n'+ template: -~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.Signed.abs#+ kind: Expression+ type: 'abs# :: KnownNat+ n => Signed n -> Signed n'+ template: abs ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.Signed.fromInteger#+ format: Haskell+ kind: Expression+ type: 'fromInteger# ::+ KnownNat n => Integer -> Signed (n :: Nat)'+ templateFunction: Clash.Primitives.Sized.Signed.fromIntegerTF+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Signed.toEnum#+ kind: Expression+ type: 'toEnum# :: KnownNat+ n => Int -> Signed n'+ template: resize(signed(std_logic_vector(~ARG[1])),~SIZE[~TYPO])+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Signed.fromEnum#+ kind: Expression+ type: 'fromEnum# :: KnownNat+ n => Signed n -> Int'+ template: ~IF~SIZE[~TYP[1]]~THENresize(~ARG[1],~SIZE[~TYPO])~ELSEto_signed(0,~SIZE[~TYPO])~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Signed.plus#+ kind: Expression+ type: 'plus# :: Signed+ m -> Signed n -> Signed (1 + Max m n)'+ template: ~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THENresize(~ARG[0],~SIZE[~TYPO])+ + resize(~ARG[1],~SIZE[~TYPO])~ELSE~IF~SIZE[~TYP[0]]~THENresize(~ARG[0],~SIZE[~TYPO])~ELSEresize(~ARG[1],~SIZE[~TYPO])~FI~FI+- BlackBox:+ name: Clash.Sized.Internal.Signed.minus#+ kind: Expression+ type: 'minus# :: Signed+ m -> Signed n -> Signed (1 + Max m n)'+ template: ~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THENresize(~ARG[0],~SIZE[~TYPO])+ - resize(~ARG[1],~SIZE[~TYPO])~ELSE~IF~SIZE[~TYP[0]]~THENresize(~ARG[0],~SIZE[~TYPO])~ELSEresize(-+ ~ARG[1],~SIZE[~TYPO])~FI~FI+- BlackBox:+ name: Clash.Sized.Internal.Signed.times#+ kind: Expression+ type: 'times# :: Signed+ m -> Signed n -> Signed (m + n)'+ template: ~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THEN~ARG[0] * ~ARG[1]~ELSEsigned'(~SIZE[~TYPO]-1+ downto 0 => '0')~FI+- BlackBox:+ name: Clash.Sized.Internal.Signed.rem#+ kind: Declaration+ type: 'rem# :: Signed+ n -> Signed n -> Signed n'+ template: |-+ ~RESULT <= ~ARG[0] rem ~ARG[1]+ -- pragma translate_off+ when (~ARG[1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;+- BlackBox:+ name: Clash.Sized.Internal.Signed.div#+ kind: Declaration+ type: 'div# :: KnownNat+ n => Signed n -> Signed n -> Signed n'+ template: |-+ -- divSigned begin+ ~GENSYM[divSigned][0] : block+ signal ~GENSYM[resultPos][1] : boolean;+ signal ~GENSYM[dividerNeg][2] : boolean;+ signal ~GENSYM[dividend2][3] : signed(~SIZE[~TYPO] downto 0);+ signal ~GENSYM[quot_res][4] : signed(~SIZE[~TYPO] downto 0);+ begin+ ~SYM[1] <= ~VAR[dividend][1](~VAR[dividend][1]'high) = ~VAR[divider][2](~VAR[divider][2]'high);+ ~SYM[2] <= ~VAR[divider][2](~VAR[divider][2]'high) = '1';+ ~SYM[3] <= resize(~VAR[dividend][1],~SIZE[~TYPO]+1) when ~SYM[1] else+ (resize(~VAR[dividend][1],~SIZE[~TYPO]+1) - resize(~VAR[divider][2],~SIZE[~TYPO]+1) - 1) when ~SYM[2] else+ (resize(~VAR[dividend][1],~SIZE[~TYPO]+1) - resize(~VAR[divider][2],~SIZE[~TYPO]+1) + 1);+ ~SYM[4] <= ~SYM[3] / ~VAR[divider][2]+ -- pragma translate_off+ when (~VAR[divider][2] /= 0) else (others => 'X')+ -- pragma translate_on+ ;+ ~RESULT <= signed(~SYM[4](~SIZE[~TYPO]-1 downto 0));+ end block;+ -- divSigned end+- BlackBox:+ name: Clash.Sized.Internal.Signed.mod#+ kind: Declaration+ type: 'mod# :: Signed+ n -> Signed n -> Signed n'+ template: |-+ ~RESULT <= ~ARG[0] mod ~ARG[1]+ -- pragma translate_off+ when (~ARG[1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;+- BlackBoxHaskell:+ name: Clash.Sized.Internal.Signed.toInteger#+ templateFunction: Clash.Primitives.Sized.ToInteger.signedToIntegerVHDL+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Signed.and#+ kind: Expression+ type: 'and# :: KnownNat+ n => Signed n -> Signed n -> Signed n'+ template: ~ARG[1] and ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.Signed.or#+ kind: Expression+ type: 'or# :: KnownNat+ n => Signed n -> Signed n -> Signed n'+ template: ~ARG[1] or ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.Signed.xor#+ kind: Expression+ type: 'xor# :: KnownNat+ n => Signed n -> Signed n -> Signed n'+ template: ~ARG[1] xor ~ARG[2]+- BlackBox:+ name: Clash.Sized.Internal.Signed.complement#+ kind: Expression+ type: 'complement# ::+ KnownNat n => Signed n -> Signed n'+ template: not ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.Signed.shiftL#+ kind: Declaration+ type: 'shiftL# :: KnownNat+ n => Signed n -> Int -> Signed n'+ template: |-+ ~GENSYM[~RESULT_shiftL][0] : block+ signal ~GENSYM[sh][1] : natural;+ begin+ ~SYM[1] <=+ -- pragma translate_off+ natural'high when (~VAR[shI][2](~SIZE[~TYP[2]]-1 downto 31) /= 0) else+ -- pragma translate_on+ to_integer(~VAR[shI][2]+ -- pragma translate_off+ (30 downto 0)+ -- pragma translate_on+ );+ ~RESULT <= shift_left(~ARG[1],~SYM[1])+ -- pragma translate_off+ when (~ARG[2] >= 0) else (others => 'X')+ -- pragma translate_on+ ;+ end block;+- BlackBox:+ name: Clash.Sized.Internal.Signed.shiftR#+ kind: Declaration+ type: 'shiftR# :: KnownNat+ n => Signed n -> Int -> Signed n'+ template: |-+ ~GENSYM[~RESULT_shiftR][0] : block+ signal ~GENSYM[sh][1] : natural;+ begin+ ~SYM[1] <=+ -- pragma translate_off+ natural'high when (~VAR[shI][2](~SIZE[~TYP[2]]-1 downto 31) /= 0) else+ -- pragma translate_on+ to_integer(~VAR[shI][2]+ -- pragma translate_off+ (30 downto 0)+ -- pragma translate_on+ );+ ~RESULT <= shift_right(~ARG[1],~SYM[1])+ -- pragma translate_off+ when (~ARG[2] >= 0) else (others => 'X')+ -- pragma translate_on+ ;+ end block;+- BlackBox:+ name: Clash.Sized.Internal.Signed.rotateL#+ kind: Declaration+ type: 'rotateL# :: KnownNat+ n => Signed n -> Int -> Signed n'+ template: |-+ ~RESULT <= rotate_left(~ARG[1],to_integer((~ARG[2])+ -- pragma translate_off+ mod ~SIZE[~TYP[1]]+ -- pragma translate_on+ ))+ -- pragma translate_off+ when (~ARG[2] >= 0) else (others => 'X')+ -- pragma translate_on+ ;+- BlackBox:+ name: Clash.Sized.Internal.Signed.rotateR#+ kind: Declaration+ type: 'rotateR# :: KnownNat+ n => Signed n -> Int -> Signed n'+ template: |-+ ~RESULT <= rotate_right(~ARG[1],to_integer((~ARG[2])+ -- pragma translate_off+ mod ~SIZE[~TYP[1]]+ -- pragma translate_on+ ))+ -- pragma translate_off+ when (~ARG[2] >= 0) else (others => 'X')+ -- pragma translate_on+ ;+- BlackBox:+ name: Clash.Sized.Internal.Signed.resize#+ kind: Expression+ type: 'resize# :: (KnownNat+ n, KnownNat m) => Signed n -> Signed m'+ template: ~IF~SIZE[~TYP[2]]~THENresize(~ARG[2],~LIT[1])~ELSEsigned'(~SIZE[~TYPO]-1+ downto 0 => '0')~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Signed.truncateB#+ kind: Expression+ type: 'truncateB# :: KnownNat+ m => Signed (n + m) -> Signed m'+ template: ~IF~SIZE[~TYPO]~THEN~VAR[s][1](~LIT[0]-1 downto 0)~ELSEsigned'(0 downto+ 1 => '0')~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Signed.quot#+ kind: Declaration+ type: 'quot# :: KnownNat+ n => Signed n -> Signed n -> Signed n'+ template: |-+ ~RESULT <= ~ARG[1] / ~ARG[2]+ -- pragma translate_off+ when (~ARG[2] /= 0) else (others => 'X')+ -- pragma translate_on+ ;
− prims/vhdl/Clash_Sized_Internal_Unsigned.primitives
@@ -1,223 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.size#"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "size# :: KnownNat n => Unsigned n -> Int"- , "template" : "to_signed(~LIT[0],~SIZE[~TYPO])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.pack#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "pack# :: Unsigned n -> BitVector n"- , "template" : "std_logic_vector(~ARG[0])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.unpack#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "unpack# :: KnownNat n => BitVector n -> Unsigned n"- , "template" : "unsigned(~ARG[1])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.eq#"- , "kind" : "Expression"- , "type" : "eq# :: Unsigned n -> Unsigned n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] = ~ARG[1]~ELSEtrue~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.neq#"- , "kind" : "Expression"- , "type" : "neq# :: Unsigned n -> Unsigned n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] /= ~ARG[1]~ELSEfalse~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.lt#"- , "kind" : "Expression"- , "type" : "lt# :: Unsigned n -> Unsigned n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] < ~ARG[1]~ELSEfalse~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.ge#"- , "kind" : "Expression"- , "type" : "ge# :: Unsigned n -> Unsigned n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] >= ~ARG[1]~ELSEtrue~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.gt#"- , "kind" : "Expression"- , "type" : "gt# :: Unsigned n -> Unsigned n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] > ~ARG[1]~ELSEfalse~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.le#"- , "kind" : "Expression"- , "type" : "le# :: Unsigned n -> Unsigned n -> Bool"- , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] <= ~ARG[1]~ELSEtrue~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.minBound#"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "minBound# :: Unsigned n"- , "template" : "~IF~SIZE[~TYPO]~THENunsigned'(~SIZE[~TYPO]-1 downto 0 => '0')~ELSEunsigned'(0 downto 1 => '0')~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.maxBound#"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "maxBound# :: KnownNat n => Unsigned n"- , "template" : "~IF~SIZE[~TYPO]~THENunsigned'(~LIT[0]-1 downto 0 => '1')~ELSEunsigned'(0 downto 1 => '1')~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.*#"- , "kind" : "Expression"- , "type" : "(*#) :: KnownNat n => Unsigned n -> Unsigned n -> Unsigned n"- , "template" : "resize(~ARG[1] * ~ARG[2], ~LIT[0])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.negate#"- , "kind" : "Expression"- , "type" : "negate# :: KnownNat n => Unsigned n -> Unsigned n"- , "template" : "unsigned(std_logic_vector(-(signed(std_logic_vector(~ARG[1])))))"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.fromInteger#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "fromInteger# :: KnownNat n => Integer -> Unsigned n"- , "template" : "resize(unsigned(std_logic_vector(~ARG[1])),~LIT[0])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.plus#"- , "kind" : "Expression"- , "type" : "plus# :: Unsigned m -> Unsigned n -> Unsigned (1 + Max m n)"- , "template" : "~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THENresize(~ARG[0],~SIZE[~TYPO]) + resize(~ARG[1],~SIZE[~TYPO])~ELSE~IF~SIZE[~TYP[0]]~THENresize(~ARG[0],~SIZE[~TYPO])~ELSEresize(~ARG[1],~SIZE[~TYPO])~FI~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.minus#"- , "kind" : "Expression"- , "type" : "minus# :: (KnownNat m,KnownNat n) => Unsigned m -> Unsigned n -> Unsigned (1 + Max m n)"- , "template" : "~IF~AND[~SIZE[~TYP[2]],~SIZE[~TYP[3]]]~THENresize(~ARG[2],~SIZE[~TYPO]) - resize(~ARG[3],~SIZE[~TYPO])~ELSE~IF~SIZE[~TYP[2]]~THENresize(~ARG[2],~SIZE[~TYPO])~ELSEresize(~ARG[3],~SIZE[~TYPO])~FI~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.times#"- , "kind" : "Expression"- , "type" : "times# :: Unsigned m -> Unsigned n -> Unsigned (m + n)"- , "template" : "~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THEN~ARG[0] * ~ARG[1]~ELSEunsigned'(~SIZE[~TYPO]-1 downto 0 => '0')~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.rem#"- , "kind" : "Expression"- , "type" : "rem# :: Unsigned n -> Unsigned n -> Unsigned n"- , "template" : "~ARG[0] rem ~ARG[1]"- }- }-, { "BlackBoxHaskell" :- { "name" : "Clash.Sized.Internal.Unsigned.toInteger#"- , "workInfo" : "Never"- , "templateFunction" : "Clash.Primitives.Sized.ToInteger.unsignedToIntegerVHDL"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.and#"- , "kind" : "Expression"- , "type" : "and# :: Unsigned n -> Unsigned n -> Unsigned n"- , "template" : "~ARG[0] and ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.or#"- , "kind" : "Expression"- , "type" : "or# :: Unsigned n -> Unsigned n -> Unsigned n"- , "template" : "~ARG[0] or ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.xor#"- , "kind" : "Expression"- , "type" : "xor# :: Unsigned n -> Unsigned n -> Unsigned n"- , "template" : "~ARG[0] xor ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.complement#"- , "kind" : "Expression"- , "type" : "complement# :: KnownNat n => Unsigned n -> Unsigned n"- , "template" : "not ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.shiftL#"- , "kind" : "Declaration"- , "type" : "shiftL# :: KnownNat n => Unsigned n -> Int -> Unsigned n"- , "template" :-"~RESULT <= shift_left(~ARG[1],to_integer(~ARG[2]))- -- pragma translate_off- when (~ARG[2] >= 0) else (others => 'X')- -- pragma translate_on- ;"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.shiftR#"- , "kind" : "Declaration"- , "type" : "shiftR# :: KnownNat n => Unsigned n -> Int -> Unsigned n"- , "template" :-"~RESULT <= shift_right(~ARG[1],to_integer(~ARG[2]))- -- pragma translate_off- when (~ARG[2] >= 0) else (others => 'X')- -- pragma translate_on- ;"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.rotateL#"- , "kind" : "Declaration"- , "type" : "rotateL# :: KnownNat n => Unsigned n -> Int -> Unsigned n"- , "template" :-"~RESULT <= rotate_left(~ARG[1],to_integer(~ARG[2]))- -- pragma translate_off- when (~ARG[2] >= 0) else (others => 'X')- -- pragma translate_on- ;"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.rotateR#"- , "kind" : "Declaration"- , "type" : "rotateR# :: KnownNat n => Unsigned n -> Int -> Unsigned n"- , "template" :-"~RESULT <= rotate_right(~ARG[1],to_integer(~ARG[2]))- -- pragma translate_off- when (~ARG[2] >= 0) else (others => 'X')- -- pragma translate_on- ;"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.resize#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "resize# :: KnownNat m => Unsigned n -> Unsigned m"- , "template" : "~IF~SIZE[~TYP[1]]~THENresize(~ARG[1],~LIT[0])~ELSEunsigned'(~SIZE[~TYPO]-1 downto 0 => '0')~FI"- }- }-]
+ prims/vhdl/Clash_Sized_Internal_Unsigned.primitives.yaml view
@@ -0,0 +1,263 @@+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.size#+ kind: Expression+ type: 'size# :: KnownNat+ n => Unsigned n -> Int'+ template: to_signed(~LIT[0],~SIZE[~TYPO])+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.pack#+ kind: Expression+ type: 'pack# :: Unsigned+ n -> BitVector n'+ template: std_logic_vector(~ARG[0])+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.unpack#+ kind: Expression+ type: 'unpack# :: KnownNat+ n => BitVector n -> Unsigned n'+ template: unsigned(~ARG[1])+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.eq#+ kind: Expression+ type: 'eq# :: Unsigned+ n -> Unsigned n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] = ~ARG[1]~ELSEtrue~FI+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.neq#+ kind: Expression+ type: 'neq# :: Unsigned+ n -> Unsigned n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] /= ~ARG[1]~ELSEfalse~FI+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.lt#+ kind: Expression+ type: 'lt# :: Unsigned+ n -> Unsigned n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] < ~ARG[1]~ELSEfalse~FI+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.ge#+ kind: Expression+ type: 'ge# :: Unsigned+ n -> Unsigned n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] >= ~ARG[1]~ELSEtrue~FI+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.gt#+ kind: Expression+ type: 'gt# :: Unsigned+ n -> Unsigned n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] > ~ARG[1]~ELSEfalse~FI+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.le#+ kind: Expression+ type: 'le# :: Unsigned+ n -> Unsigned n -> Bool'+ template: ~IF~SIZE[~TYP[0]]~THEN~ARG[0] <= ~ARG[1]~ELSEtrue~FI+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.minBound#+ kind: Expression+ type: 'minBound# :: Unsigned+ n'+ template: ~IF~SIZE[~TYPO]~THENunsigned'(~SIZE[~TYPO]-1 downto 0 => '0')~ELSEunsigned'(0+ downto 1 => '0')~FI+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.maxBound#+ kind: Expression+ type: 'maxBound# :: KnownNat+ n => Unsigned n'+ template: ~IF~SIZE[~TYPO]~THENunsigned'(~LIT[0]-1 downto 0 => '1')~ELSEunsigned'(0+ downto 1 => '1')~FI+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.*#+ kind: Expression+ type: '(*#) :: KnownNat+ n => Unsigned n -> Unsigned n -> Unsigned n'+ template: resize(~ARG[1] * ~ARG[2], ~LIT[0])+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.negate#+ kind: Expression+ type: 'negate# :: KnownNat+ n => Unsigned n -> Unsigned n'+ template: unsigned(std_logic_vector(-(signed(std_logic_vector(~ARG[1])))))+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.fromInteger#+ kind: Expression+ type: 'fromInteger# ::+ KnownNat n => Integer -> Unsigned n'+ template: resize(unsigned(std_logic_vector(~ARG[1])),~LIT[0])+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.toEnum#+ kind: Expression+ type: 'toEnum# :: KnownNat+ n => Int -> Unsigned n'+ template: resize(unsigned(std_logic_vector(~ARG[1])),~SIZE[~TYPO])+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.fromEnum#+ kind: Expression+ type: 'fromEnum# :: KnownNat+ n => Unsigned n -> Int'+ template: ~IF~SIZE[~TYP[1]]~THENsigned(std_logic_vector(resize(~ARG[1],~SIZE[~TYPO])))~ELSEto_signed(0,~SIZE[~TYPO])~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.plus#+ kind: Expression+ type: 'plus# :: Unsigned+ m -> Unsigned n -> Unsigned (1 + Max m n)'+ template: ~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THENresize(~ARG[0],~SIZE[~TYPO])+ + resize(~ARG[1],~SIZE[~TYPO])~ELSE~IF~SIZE[~TYP[0]]~THENresize(~ARG[0],~SIZE[~TYPO])~ELSEresize(~ARG[1],~SIZE[~TYPO])~FI~FI+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.minus#+ kind: Expression+ type: 'minus# :: (KnownNat+ m,KnownNat n) => Unsigned m -> Unsigned n -> Unsigned (1 + Max m n)'+ template: ~IF~AND[~SIZE[~TYP[2]],~SIZE[~TYP[3]]]~THENresize(~ARG[2],~SIZE[~TYPO])+ - resize(~ARG[3],~SIZE[~TYPO])~ELSE~IF~SIZE[~TYP[2]]~THENresize(~ARG[2],~SIZE[~TYPO])~ELSEresize(~ARG[3],~SIZE[~TYPO])~FI~FI+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.times#+ kind: Expression+ type: 'times# :: Unsigned+ m -> Unsigned n -> Unsigned (m + n)'+ template: ~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THEN~ARG[0] * ~ARG[1]~ELSEunsigned'(~SIZE[~TYPO]-1+ downto 0 => '0')~FI+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.rem#+ kind: Declaration+ type: 'rem# :: Unsigned+ n -> Unsigned n -> Unsigned n'+ template: |-+ ~RESULT <= ~ARG[0] rem ~ARG[1]+ -- pragma translate_off+ when (~ARG[1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;+- BlackBoxHaskell:+ name: Clash.Sized.Internal.Unsigned.toInteger#+ templateFunction: Clash.Primitives.Sized.ToInteger.unsignedToIntegerVHDL+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.and#+ kind: Expression+ type: 'and# :: Unsigned+ n -> Unsigned n -> Unsigned n'+ template: ~ARG[0] and ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.or#+ kind: Expression+ type: 'or# :: Unsigned+ n -> Unsigned n -> Unsigned n'+ template: ~ARG[0] or ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.xor#+ kind: Expression+ type: 'xor# :: Unsigned+ n -> Unsigned n -> Unsigned n'+ template: ~ARG[0] xor ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.complement#+ kind: Expression+ type: 'complement# ::+ KnownNat n => Unsigned n -> Unsigned n'+ template: not ~ARG[1]+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.shiftL#+ kind: Declaration+ type: 'shiftL# :: KnownNat+ n => Unsigned n -> Int -> Unsigned n'+ template: |-+ ~GENSYM[~RESULT_shiftL][0] : block+ signal ~GENSYM[sh][1] : natural;+ begin+ ~SYM[1] <=+ -- pragma translate_off+ natural'high when (~VAR[shI][2](~SIZE[~TYP[2]]-1 downto 31) /= 0) else+ -- pragma translate_on+ to_integer(~VAR[shI][2]+ -- pragma translate_off+ (30 downto 0)+ -- pragma translate_on+ );+ ~RESULT <= shift_left(~ARG[1],~SYM[1])+ -- pragma translate_off+ when (~ARG[2] >= 0) else (others => 'X')+ -- pragma translate_on+ ;+ end block;+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.shiftR#+ kind: Declaration+ type: 'shiftR# :: KnownNat+ n => Unsigned n -> Int -> Unsigned n'+ template: |-+ ~GENSYM[~RESULT_shiftL][0] : block+ signal ~GENSYM[sh][1] : natural;+ begin+ ~SYM[1] <=+ -- pragma translate_off+ natural'high when (~VAR[shI][2](~SIZE[~TYP[2]]-1 downto 31) /= 0) else+ -- pragma translate_on+ to_integer(~VAR[shI][2]+ -- pragma translate_off+ (30 downto 0)+ -- pragma translate_on+ );+ ~RESULT <= shift_right(~ARG[1],~SYM[1])+ -- pragma translate_off+ when (~ARG[2] >= 0) else (others => 'X')+ -- pragma translate_on+ ;+ end block;+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.rotateL#+ kind: Declaration+ type: 'rotateL# :: KnownNat+ n => Unsigned n -> Int -> Unsigned n'+ template: |-+ ~RESULT <= rotate_left(~ARG[1],to_integer((~ARG[2])+ -- pragma translate_off+ mod ~SIZE[~TYP[1]]+ -- pragma translate_on+ ))+ -- pragma translate_off+ when (~ARG[2] >= 0) else (others => 'X')+ -- pragma translate_on+ ;+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.rotateR#+ kind: Declaration+ type: 'rotateR# :: KnownNat+ n => Unsigned n -> Int -> Unsigned n'+ template: |-+ ~RESULT <= rotate_right(~ARG[1],to_integer((~ARG[2])+ -- pragma translate_off+ mod ~SIZE[~TYP[1]]+ -- pragma translate_on+ ))+ -- pragma translate_off+ when (~ARG[2] >= 0) else (others => 'X')+ -- pragma translate_on+ ;+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.resize#+ kind: Expression+ type: 'resize# :: KnownNat+ m => Unsigned n -> Unsigned m'+ template: ~IF~SIZE[~TYP[1]]~THENresize(~ARG[1],~LIT[0])~ELSEunsigned'(~SIZE[~TYPO]-1+ downto 0 => '0')~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Internal.Unsigned.quot#+ kind: Declaration+ type: 'quot# :: Unsigned+ n -> Unsigned n -> Unsigned n'+ template: |-+ ~RESULT <= ~ARG[0] / ~ARG[1]+ -- pragma translate_off+ when (~ARG[1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;
− prims/vhdl/Clash_Sized_RTree.primitives
@@ -1,25 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Sized.RTree.treplicate"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "replicate :: SNat n -> a -> RTree d a"- , "template" : "~TYPMO'(0 to (2**~LIT[0])-1 => ~IF~VIVADO~THEN~TOBV[~ARG[1]][~TYP[1]]~ELSE~ARG[1]~FI)"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.RTree.textract"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "textract :: RTree 0 a -> a"- , "template" : "~IF ~VIVADO ~THEN ~FROMBV[~VAR[t][0](0)][~TYPO] ~ELSE ~VAR[t][0](0) ~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.RTree.tsplit"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "tsplit:: RTree (d+1) a -> (RTree d a,RTree d a)"- , "template" : "(~VAR[t][0](0 to (2**(~DEPTH[~TYP[0]]-1))-1) ,~VAR[t][0](2**(~DEPTH[~TYP[0]]-1) to (2**~DEPTH[~TYP[0]])-1))"- }- }-]
+ prims/vhdl/Clash_Sized_RTree.primitives.yaml view
@@ -0,0 +1,23 @@+- BlackBox:+ name: Clash.Sized.RTree.treplicate+ kind: Expression+ type: 'replicate :: SNat+ n -> a -> RTree d a'+ template: ~TYPMO'(0 to (2**~LIT[0])-1 => ~IF~VIVADO~THEN~TOBV[~ARG[1]][~TYP[1]]~ELSE~ARG[1]~FI)+ workInfo: Never+- BlackBox:+ name: Clash.Sized.RTree.textract+ kind: Expression+ type: 'textract :: RTree+ 0 a -> a'+ template: ~IF ~VIVADO ~THEN ~FROMBV[~VAR[t][0](0)][~TYPO] ~ELSE ~VAR[t][0](0)+ ~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.RTree.tsplit+ kind: Expression+ type: 'tsplit:: RTree+ (d+1) a -> (RTree d a,RTree d a)'+ template: (~VAR[t][0](0 to (2**(~DEPTH[~TYP[0]]-1))-1) ,~VAR[t][0](2**(~DEPTH[~TYP[0]]-1)+ to (2**~DEPTH[~TYP[0]])-1))+ workInfo: Never
− prims/vhdl/Clash_Sized_Vector.primitives
@@ -1,444 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Sized.Vector.head"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "head :: Vec (n + 1) a -> a"- , "template" : "~IF ~VIVADO ~THEN ~TYPMO'(fromSLV(~VAR[vec][0](0))) ~ELSE ~VAR[vec][0](0) ~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.tail"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "tail :: Vec (n + 1) a -> Vec n a"- , "template" : "~VAR[vec][0](1 to ~VAR[vec][0]'high)"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.last"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "Vec (n + 1) a -> a"- , "template" : "~IF ~VIVADO ~THEN ~TYPMO'(fromSLV(~VAR[vec][0](~VAR[vec][0]'high))) ~ELSE ~VAR[vec][0](~VAR[vec][0]'high) ~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.init"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "Vec (n + 1) a -> Vec n a"- , "template" : "~VAR[vec][0](0 to ~VAR[vec][0]'high - 1)"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.select"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" :-"select :: (CmpNat (i + s) (s * n) ~ GT) -- ARG[0]- => SNat f -- ARG[1]- -> SNat s -- ARG[2]- -> SNat n -- ARG[3]- -> Vec i a -- ARG[4]- -> Vec n a"- , "template" :-"-- select begin-~GENSYM[select][0] : for ~GENSYM[i][1] in ~RESULT'range generate- ~RESULT(~SYM[1]) <= ~VAR[vec][4](~LIT[1]+(~LIT[2]*~SYM[1]));-end generate;--- select end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.++"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "(++) :: Vec n a -> Vec m a -> Vec (n + m) a"- , "template" : "~TYPMO'(~TYPM[0]'(~ARG[0]) & ~TYPM[1]'(~ARG[1]))"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.concat"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "concat :: Vec n (Vec m a) -> Vec (n * m) a"- , "template" :-"-- concat begin-~GENSYM[concat][0] : for ~GENSYM[i][1] in 0 to (~LENGTH[~TYP[0]] - 1) generate-begin~IF ~VIVADO ~THEN-~RESULT(~SYM[1] * ~LENGTH[~TYPEL[~TYP[0]]] to ((~SYM[1]+1) * ~LENGTH[~TYPEL[~TYP[0]]]) - 1) <= fromSLV(~VAR[vec][0](~SYM[1]));~ELSE-~RESULT(~SYM[1] * ~LENGTH[~TYPEL[~TYP[0]]] to ((~SYM[1]+1) * ~LENGTH[~TYPEL[~TYP[0]]]) - 1) <= ~VAR[vec][0](~SYM[1]);~FI-end generate;--- concat end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.splitAt"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "splitAt :: SNat m -> Vec (m + n) a -> (Vec m a, Vec n a)"- , "template" : "~IF~LENGTH[~TYPO]~THEN~ARG[1]~ELSE(~VAR[vec][1](0 to ~LIT[0]-1),~VAR[vec][1](~LIT[0] to ~VAR[vec][1]'high))~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.unconcat"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" :-"unconcat :: KnownNat n -- ARG[0]- => SNat m -- ARG[1]- -> Vec (n * m) a -- ARG[2]- -> Vec n (Vec m a)"- , "template" :-"-- unconcat begin~DEVNULL[~ARG[0]]-~GENSYM[unconcat][0] : for ~GENSYM[i][2] in ~RESULT'range generate-begin~IF ~VIVADO ~THEN- ~RESULT(~SYM[2]) <= ~TOBV[~VAR[vec][2]((~SYM[2] * ~LIT[1]) to ((~SYM[2] * ~LIT[1]) + ~LIT[1] - 1))][~TYPEL[~TYPO]];~ELSE- ~RESULT(~SYM[2]) <= ~VAR[vec][2]((~SYM[2] * ~LIT[1]) to ((~SYM[2] * ~LIT[1]) + ~LIT[1] - 1));~FI-end generate;--- unconcat end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.map"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "map :: (a -> b) -> Vec n a -> Vec n b"- , "template" :-"-- map begin-~GENSYM[map][0] : for ~GENSYM[i][1] in ~RESULT'range generate~IF ~VIVADO ~THEN~IF~SIZE[~TYP[1]]~THEN- signal ~GENSYM[map_in][2] : ~TYPEL[~TYP[1]];~ELSE ~FI- signal ~GENSYM[map_out][3] : ~TYPEL[~TYPO];-begin~IF~SIZE[~TYP[1]]~THEN- ~SYM[2] <= fromSLV(~VAR[vec][1](~SYM[1]));~ELSE ~FI- ~INST 0- ~OUTPUT <= ~SYM[3]~ ~TYPEL[~TYPO]~- ~INPUT <= ~SYM[2]~ ~TYPEL[~TYP[1]]~- ~INST- ~RESULT(~SYM[1]) <= ~TOBV[~SYM[3]][~TYPEL[~TYPO]];-end generate;~ELSE-begin- ~INST 0- ~OUTPUT <= ~RESULT(~SYM[1])~ ~TYPEL[~TYPO]~- ~INPUT <= ~VAR[vec][1](~SYM[1])~ ~TYPEL[~TYP[1]]~- ~INST-end generate;~FI--- map end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.imap"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "imap :: KnownNat n => (Index n -> a -> b) -> Vec n a -> Vec n b"- , "template" :-"-- imap begin-~GENSYM[imap][0] : block- function ~GENSYM[max][6] (l,r : in natural) return natural is- begin- if l > r then return l;- else return r;- end if;- end function;-begin- ~GENSYM[imap][5] : for ~GENSYM[i][1] in ~RESULT'range generate~IF ~VIVADO ~THEN~IF~SIZE[~TYP[2]]~THEN- signal ~GENSYM[map_in][2] : ~TYPEL[~TYP[2]];~ELSE ~FI- signal ~GENSYM[map_out][3] : ~TYPEL[~TYPO];- begin~IF~SIZE[~TYP[2]]~THEN- ~SYM[2] <= fromSLV(~VAR[vec][2](~SYM[1]));~ELSE ~FI- ~INST 1- ~OUTPUT <= ~SYM[3]~ ~TYPEL[~TYPO]~- ~INPUT <= to_unsigned(~SYM[1],~SYM[6](1,integer(ceil(log2(real(~LIT[0]))))))~ ~INDEXTYPE[~LIT[0]]~- ~INPUT <= ~SYM[2]~ ~TYPEL[~TYP[2]]~- ~INST- ~RESULT(~SYM[1]) <= ~TOBV[~SYM[3]][~TYPEL[~TYPO]];- end generate;~ELSE- begin- ~INST 1- ~OUTPUT <= ~RESULT(~SYM[1])~ ~TYPEL[~TYPO]~- ~INPUT <= to_unsigned(~SYM[1],~SYM[6](1,integer(ceil(log2(real(~LIT[0]))))))~ ~INDEXTYPE[~LIT[0]]~- ~INPUT <= ~VAR[vec][2](~SYM[1])~ ~TYPEL[~TYP[2]]~- ~INST- end generate;~FI-end block;--- imap end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.imap_go"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "imap_go :: Index n -> (Index n -> a -> b) -> Vec m a -> Vec m b"- , "template" :-"-- imap_go begin-~GENSYM[imap][5] : for ~GENSYM[i][1] in ~RESULT'range generate~IF ~VIVADO ~THEN~IF~SIZE[~TYP[2]]~THEN- signal ~GENSYM[map_in][2] : ~TYPEL[~TYP[2]];~ELSE ~FI- signal ~GENSYM[map_out][3] : ~TYPEL[~TYPO];- signal ~GENSYM[i2][4] : ~TYP[0];-begin~IF~SIZE[~TYP[2]]~THEN- ~SYM[2] <= fromSLV(~VAR[vec][2](~SYM[1]));~ELSE ~FI- ~SYM[4] <= ~ARG[0] + to_unsigned(~SYM[1],~SIZE[~TYP[0]]);- ~INST 1- ~OUTPUT <= ~SYM[3]~ ~TYPEL[~TYPO]~- ~INPUT <= ~SYM[4]~ ~TYP[0]~- ~INPUT <= ~SYM[2]~ ~TYPEL[~TYP[2]]~- ~INST- ~RESULT(~SYM[1]) <= ~TOBV[~SYM[3]][~TYPEL[~TYPO]];-end generate;~ELSE- signal ~SYM[4] : ~TYP[0];-begin- ~SYM[4] <= ~ARG[0] + to_unsigned(~SYM[1],~SIZE[~TYP[0]]);- ~INST 1- ~OUTPUT <= ~RESULT(~SYM[1])~ ~TYPEL[~TYPO]~- ~INPUT <= ~SYM[4]~ ~TYP[0]~- ~INPUT <= ~VAR[vec][2](~SYM[1])~ ~TYPEL[~TYP[2]]~- ~INST-end generate;~FI--- imap_go end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.zipWith"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "zipWith :: (a -> b -> c) -> Vec n a -> Vec n b -> Vec n c"- , "template" :-"-- zipWith begin-~GENSYM[zipWith][0] : for ~GENSYM[i][1] in ~RESULT'range generate~IF ~VIVADO ~THEN~IF~SIZE[~TYP[1]]~THEN- signal ~GENSYM[zipWith_in1][2] : ~TYPEL[~TYP[1]];~ELSE ~FI~IF~SIZE[~TYP[2]]~THEN- signal ~GENSYM[zipWith_in2][6] : ~TYPEL[~TYP[2]];~ELSE ~FI- signal ~GENSYM[zipWith_out][3] : ~TYPEL[~TYPO];-begin~IF~SIZE[~TYP[1]]~THEN- ~SYM[2] <= fromSLV(~VAR[vec1][1](~SYM[1]));~ELSE ~FI~IF~SIZE[~TYP[2]]~THEN- ~SYM[6] <= fromSLV(~VAR[vec2][2](~SYM[1]));~ELSE ~FI- ~INST 0- ~OUTPUT <= ~SYM[3]~ ~TYPEL[~TYPO]~- ~INPUT <= ~SYM[2]~ ~TYPEL[~TYP[1]]~- ~INPUT <= ~SYM[6]~ ~TYPEL[~TYP[2]]~- ~INST- ~RESULT(~SYM[1]) <= ~TOBV[~SYM[3]][~TYPEL[~TYPO]];-end generate;~ELSE-begin- ~INST 0- ~OUTPUT <= ~RESULT(~SYM[1])~ ~TYPEL[~TYPO]~- ~INPUT <= ~VAR[vec1][1](~SYM[1])~ ~TYPEL[~TYP[1]]~- ~INPUT <= ~VAR[vec2][2](~SYM[1])~ ~TYPEL[~TYP[2]]~- ~INST-end generate;~FI--- zipWith end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.foldr"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "foldr :: (a -> b -> b) -> b -> Vec n a -> b"- , "template" :-"-- foldr begin~IF ~LENGTH[~TYP[2]] ~THEN-~GENSYM[foldr][0] : block- type ~GENSYM[foldr_res_type][1] is array (natural range <>) of ~TYP[1];- signal ~GENSYM[intermediate][2] : ~SYM[1] (0 to ~LENGTH[~TYP[2]]);-begin- ~SYM[2](~LENGTH[~TYP[2]]) <= ~ARG[1];-- foldr_loop : for ~GENSYM[i][3] in 0 to (~LENGTH[~TYP[2]] - 1) generate~IF ~VIVADO ~THEN~IF~SIZE[~TYP[2]]~THEN- signal ~GENSYM[foldr_in][4] : ~TYPEL[~TYP[2]];~ELSE ~FI- begin~IF~SIZE[~TYP[2]]~THEN- ~SYM[4] <= fromSLV(~VAR[vec][2](~SYM[3]));~ELSE ~FI- ~INST 0- ~OUTPUT <= ~SYM[2](~SYM[3])~ ~TYP[1]~- ~INPUT <= ~SYM[4]~ ~TYPEL[~TYP[2]]~- ~INPUT <= ~SYM[2](~SYM[3]+1)~ ~TYP[1]~- ~INST- end generate;~ELSE- begin- ~INST 0- ~OUTPUT <= ~SYM[2](~SYM[3])~ ~TYP[1]~- ~INPUT <= ~VAR[vec][2](~SYM[3])~ ~TYPEL[~TYP[2]]~- ~INPUT <= ~SYM[2](~SYM[3]+1)~ ~TYP[1]~- ~INST- end generate;~FI-- ~RESULT <= ~SYM[2](0);-end block;~ELSE-~RESULT <= ~ARG[1];~FI--- foldr end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.index_int"- , "kind" : "Declaration"- , "type" : "index_int :: KnownNat n => Vec n a -> Int -> a"- , "template" :-"-- index begin-~IF~SIZE[~TYP[1]]~THEN~GENSYM[indexVec][0] : block- signal ~GENSYM[vec_index][1] : integer range 0 to ~LIT[0]-1;-begin- ~SYM[1] <= to_integer(~ARG[2])- -- pragma translate_off- mod ~LIT[0]- -- pragma translate_on- ;~IF ~VIVADO ~THEN- ~RESULT <= fromSLV(~VAR[vec][1](~SYM[1]));~ELSE- ~RESULT <= ~VAR[vec][1](~SYM[1]);~FI-end block;~ELSE~RESULT <= ~ERRORO;~FI--- index end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.replace_int"- , "kind" : "Declaration"- , "type" : "replace_int :: KnownNat n => Vec n a -> Int -> a -> Vec n a"- , "template" :-"-- replace begin-~GENSYM[replaceVec][0] : block- signal ~GENSYM[vec_index][1] : integer range 0 to ~LIT[0]-1;-begin- ~SYM[1] <= to_integer(~ARG[2])- -- pragma translate_off- mod ~LIT[0]- -- pragma translate_on- ;-- process(~SYM[1]~VARS[1]~VARS[3])- variable ~GENSYM[ivec][2] : ~TYP[1];- begin- ~SYM[2] := ~ARG[1];~IF ~VIVADO ~THEN- ~SYM[2](~SYM[1]) := ~TOBV[~ARG[3]][~TYP[3]];~ELSE- ~SYM[2](~SYM[1]) := ~ARG[3];~FI- ~RESULT <= ~SYM[2];- end process;-end block;--- replace end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.maxIndex"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "maxIndex :: KnownNat n => Vec n a -> Int"- , "template" : "to_signed(~LIT[0] - 1,~SIZE[~TYPO])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.length"- , "workInfo" : "Constant"- , "kind" : "Expression"- , "type" : "length :: KnownNat n => Vec n a -> Int"- , "template" : "to_signed(~LIT[0],~SIZE[~TYPO])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.replicate"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "replicate :: SNat n -> a -> Vec n a"- , "template" : "~TYPMO'(0 to ~LIT[0]-1 => ~IF ~VIVADO ~THEN ~TOBV[~ARG[1]][~TYP[1]] ~ELSE ~ARG[1] ~FI)"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.transpose"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "transpose :: KnownNat n => Vec m (Vec n a) -> Vec n (Vec m a)"- , "template" :-"-- transpose begin-~GENSYM[transpose_outer][2] : for ~GENSYM[row_index][3] in 0 to (~LENGTH[~TYP[1]] - 1) generate- ~GENSYM[transpose_inner][4] : for ~GENSYM[col_index][5] in ~RESULT'range generate~IF ~VIVADO ~THEN- ~RESULT(~SYM[5])((~LENGTH[~TYP[1]]-~SYM[3])*~SIZE[~TYPEL[~TYPEL[~TYPO]]]-1 downto (~LENGTH[~TYP[1]]-~SYM[3]-1)*~SIZE[~TYPEL[~TYPEL[~TYPO]]]) <= ~VAR[vec][1](~SYM[3])((~RESULT'length-~SYM[5])*~SIZE[~TYPEL[~TYPEL[~TYPO]]]-1 downto (~RESULT'length-~SYM[5]-1)*~SIZE[~TYPEL[~TYPEL[~TYPO]]]);~ELSE- ~RESULT(~SYM[5])(~SYM[3]) <= ~VAR[matrix][1](~SYM[3])(~SYM[5]);~FI- end generate;-end generate;--- transpose end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.reverse"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "reverse :: Vec n a -> Vec n a"- , "template" :-"-- reverse begin-~GENSYM[reverse_loop][2] : for ~GENSYM[i][3] in 0 to (~LENGTH[~TYP[0]] - 1) generate- ~RESULT(~VAR[vec][0]'high - ~SYM[3]) <= ~VAR[vec][0](~SYM[3]);-end generate;--- reverse end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.concatBitVector#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" :-"concatBitVector# :: (KnownNat n,KnownNat m) -- (ARG[0],ARG[1])- => Vec n (BitVector m) -- ARG[2]- -> BitVector (n * m)"- , "template" :-"-- concatBitVector begin-~GENSYM[concatBitVectorIter_loop][2] : for ~GENSYM[i][3] in 0 to (~LENGTH[~TYP[2]] - 1) generate- ~RESULT(((~SYM[3] * ~LIT[1]) + ~LIT[1] - 1) downto (~SYM[3] * ~LIT[1])) <= ~TYPMO'(~VAR[vec][2](~VAR[vec][2]'high - ~SYM[3]));-end generate;--- concatBitVector end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.unconcatBitVector#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" :-"unconcatBitVector# :: (KnownNat n, KnownNat m) -- (ARG[0],ARG[1])- => BitVector (n * m) -- ARG[2]- -> Vec n (BitVector m)"- , "template" :-"-- unconcatBitVector begin-~GENSYM[unconcatBitVectorIter_loop][2] : for ~GENSYM[i][3] in ~RESULT'range generate- ~RESULT(~RESULT'high - ~SYM[3]) <= ~VAR[vec][2](((~SYM[3] * ~LIT[1]) + ~LIT[1] - 1) downto (~SYM[3] * ~LIT[1]));-end generate;--- unconcatBitVector end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.rotateLeftS"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "rotateLeftS :: KnownNat n => Vec n a -> SNat d -> Vec n a"- , "template" :-"-- rotateLeftS begin-~GENSYM[rotateLeftS][0] : block- constant ~GENSYM[shift_amount][2] : natural := ~LIT[2] mod ~LIT[0];-begin- ~GENSYM[no_shift][3] : if ~SYM[2] = 0 generate- ~RESULT <= ~VAR[vec][1];- end generate;-- ~GENSYM[do_shift][4] : if ~SYM[2] /= 0 generate- ~RESULT <= ~VAR[vec][1](~SYM[2] to ~LIT[0]-1) &- ~VAR[vec][1](0 to ~SYM[2]-1);- end generate;-end block;--- rotateLeftS end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.rotateRightS"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "rotateRightS :: KnownNat n => Vec n a -> SNat d -> Vec n a"- , "template" :-"-- rotateRightS begin-~GENSYM[rotateLeftS][0] : block- constant ~GENSYM[shift_amount][2] : natural := ~LIT[2] mod ~LIT[0];-begin- ~GENSYM[no_shift][3] : if ~SYM[2] = 0 generate- ~RESULT <= ~VAR[vec][1];- end generate;-- ~GENSYM[do_shift][4] : if ~SYM[2] /= 0 generate- ~RESULT <= ~VAR[vec][1](~LIT[0]-~SYM[2] to ~LIT[0]-1) &- ~VAR[vec][1](0 to ~LIT[0]-~SYM[2]-1);- end generate;-end block;--- rotateRightS end"- }- }-]
+ prims/vhdl/Clash_Sized_Vector.primitives.yaml view
@@ -0,0 +1,411 @@+- BlackBox:+ name: Clash.Sized.Vector.head+ kind: Expression+ type: 'head :: Vec (n+ + 1) a -> a'+ template: ~IF ~VIVADO ~THEN ~TYPMO'(fromSLV(~VAR[vec][0](0))) ~ELSE ~VAR[vec][0](0)+ ~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.tail+ kind: Expression+ type: 'tail :: Vec (n+ + 1) a -> Vec n a'+ template: ~VAR[vec][0](1 to ~VAR[vec][0]'high)+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.last+ kind: Expression+ type: Vec (n + 1) a ->+ a+ template: ~IF ~VIVADO ~THEN ~TYPMO'(fromSLV(~VAR[vec][0](~VAR[vec][0]'high)))+ ~ELSE ~VAR[vec][0](~VAR[vec][0]'high) ~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.init+ kind: Expression+ type: Vec (n + 1) a ->+ Vec n a+ template: ~VAR[vec][0](0 to ~VAR[vec][0]'high - 1)+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.select+ kind: Declaration+ type: |-+ select :: (CmpNat (i + s) (s * n) ~ GT) -- ARG[0]+ => SNat f -- ARG[1]+ -> SNat s -- ARG[2]+ -> SNat n -- ARG[3]+ -> Vec i a -- ARG[4]+ -> Vec n a+ template: |-+ -- select begin+ ~GENSYM[select][0] : for ~GENSYM[i][1] in ~RESULT'range generate+ ~RESULT(~SYM[1]) <= ~VAR[vec][4](~LIT[1]+(~LIT[2]*~SYM[1]));+ end generate;+ -- select end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.+++ kind: Expression+ type: '(++) :: Vec n a+ -> Vec m a -> Vec (n + m) a'+ template: ~TYPMO'(~TYPM[0]'(~ARG[0]) & ~TYPM[1]'(~ARG[1]))+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.concat+ kind: Declaration+ type: 'concat :: Vec n+ (Vec m a) -> Vec (n * m) a'+ template: |-+ -- concat begin+ ~GENSYM[concat][0] : for ~GENSYM[i][1] in 0 to (~LENGTH[~TYP[0]] - 1) generate+ begin~IF ~VIVADO ~THEN+ ~RESULT(~SYM[1] * ~LENGTH[~TYPEL[~TYP[0]]] to ((~SYM[1]+1) * ~LENGTH[~TYPEL[~TYP[0]]]) - 1) <= fromSLV(~VAR[vec][0](~SYM[1]));~ELSE+ ~RESULT(~SYM[1] * ~LENGTH[~TYPEL[~TYP[0]]] to ((~SYM[1]+1) * ~LENGTH[~TYPEL[~TYP[0]]]) - 1) <= ~VAR[vec][0](~SYM[1]);~FI+ end generate;+ -- concat end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.splitAt+ kind: Expression+ type: 'splitAt :: SNat+ m -> Vec (m + n) a -> (Vec m a, Vec n a)'+ template: ~IF~LENGTH[~TYPO]~THEN~ARG[1]~ELSE(~VAR[vec][1](0 to ~LIT[0]-1),~VAR[vec][1](~LIT[0]+ to ~VAR[vec][1]'high))~FI+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.unconcat+ kind: Declaration+ type: |-+ unconcat :: KnownNat n -- ARG[0]+ => SNat m -- ARG[1]+ -> Vec (n * m) a -- ARG[2]+ -> Vec n (Vec m a)+ template: |-+ -- unconcat begin~DEVNULL[~ARG[0]]+ ~GENSYM[unconcat][0] : for ~GENSYM[i][2] in ~RESULT'range generate+ begin~IF ~VIVADO ~THEN+ ~RESULT(~SYM[2]) <= ~TOBV[~VAR[vec][2]((~SYM[2] * ~LIT[1]) to ((~SYM[2] * ~LIT[1]) + ~LIT[1] - 1))][~TYPEL[~TYPO]];~ELSE+ ~RESULT(~SYM[2]) <= ~VAR[vec][2]((~SYM[2] * ~LIT[1]) to ((~SYM[2] * ~LIT[1]) + ~LIT[1] - 1));~FI+ end generate;+ -- unconcat end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.map+ kind: Declaration+ type: 'map :: (a -> b)+ -> Vec n a -> Vec n b'+ template: |-+ -- map begin+ ~GENSYM[map][0] : for ~GENSYM[i][1] in ~RESULT'range generate~IF ~VIVADO ~THEN~IF~SIZE[~TYP[1]]~THEN+ signal ~GENSYM[map_in][2] : ~TYPEL[~TYP[1]];~ELSE ~FI+ signal ~GENSYM[map_out][3] : ~TYPEL[~TYPO];+ begin~IF~SIZE[~TYP[1]]~THEN+ ~SYM[2] <= fromSLV(~VAR[vec][1](~SYM[1]));~ELSE ~FI+ ~INST 0+ ~OUTPUT <= ~SYM[3]~ ~TYPEL[~TYPO]~+ ~INPUT <= ~SYM[2]~ ~TYPEL[~TYP[1]]~+ ~INST+ ~RESULT(~SYM[1]) <= ~TOBV[~SYM[3]][~TYPEL[~TYPO]];+ end generate;~ELSE+ begin+ ~INST 0+ ~OUTPUT <= ~RESULT(~SYM[1])~ ~TYPEL[~TYPO]~+ ~INPUT <= ~VAR[vec][1](~SYM[1])~ ~TYPEL[~TYP[1]]~+ ~INST+ end generate;~FI+ -- map end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.imap+ kind: Declaration+ type: 'imap :: KnownNat+ n => (Index n -> a -> b) -> Vec n a -> Vec n b'+ template: |-+ -- imap begin+ ~GENSYM[imap][0] : block+ function ~GENSYM[max][6] (l,r : in natural) return natural is+ begin+ if l > r then return l;+ else return r;+ end if;+ end function;+ begin+ ~GENSYM[imap][5] : for ~GENSYM[i][1] in ~RESULT'range generate~IF ~VIVADO ~THEN~IF~SIZE[~TYP[2]]~THEN+ signal ~GENSYM[map_in][2] : ~TYPEL[~TYP[2]];~ELSE ~FI+ signal ~GENSYM[map_out][3] : ~TYPEL[~TYPO];+ begin~IF~SIZE[~TYP[2]]~THEN+ ~SYM[2] <= fromSLV(~VAR[vec][2](~SYM[1]));~ELSE ~FI+ ~INST 1+ ~OUTPUT <= ~SYM[3]~ ~TYPEL[~TYPO]~+ ~INPUT <= to_unsigned(~SYM[1],~SYM[6](1,integer(ceil(log2(real(~LIT[0]))))))~ ~INDEXTYPE[~LIT[0]]~+ ~INPUT <= ~SYM[2]~ ~TYPEL[~TYP[2]]~+ ~INST+ ~RESULT(~SYM[1]) <= ~TOBV[~SYM[3]][~TYPEL[~TYPO]];+ end generate;~ELSE+ begin+ ~INST 1+ ~OUTPUT <= ~RESULT(~SYM[1])~ ~TYPEL[~TYPO]~+ ~INPUT <= to_unsigned(~SYM[1],~SYM[6](1,integer(ceil(log2(real(~LIT[0]))))))~ ~INDEXTYPE[~LIT[0]]~+ ~INPUT <= ~VAR[vec][2](~SYM[1])~ ~TYPEL[~TYP[2]]~+ ~INST+ end generate;~FI+ end block;+ -- imap end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.imap_go+ kind: Declaration+ type: 'imap_go :: Index+ n -> (Index n -> a -> b) -> Vec m a -> Vec m b'+ template: |-+ -- imap_go begin+ ~GENSYM[imap][5] : for ~GENSYM[i][1] in ~RESULT'range generate~IF ~VIVADO ~THEN~IF~SIZE[~TYP[2]]~THEN+ signal ~GENSYM[map_in][2] : ~TYPEL[~TYP[2]];~ELSE ~FI+ signal ~GENSYM[map_out][3] : ~TYPEL[~TYPO];+ signal ~GENSYM[i2][4] : ~TYP[0];+ begin~IF~SIZE[~TYP[2]]~THEN+ ~SYM[2] <= fromSLV(~VAR[vec][2](~SYM[1]));~ELSE ~FI+ ~SYM[4] <= ~ARG[0] + to_unsigned(~SYM[1],~SIZE[~TYP[0]]);+ ~INST 1+ ~OUTPUT <= ~SYM[3]~ ~TYPEL[~TYPO]~+ ~INPUT <= ~SYM[4]~ ~TYP[0]~+ ~INPUT <= ~SYM[2]~ ~TYPEL[~TYP[2]]~+ ~INST+ ~RESULT(~SYM[1]) <= ~TOBV[~SYM[3]][~TYPEL[~TYPO]];+ end generate;~ELSE+ signal ~SYM[4] : ~TYP[0];+ begin+ ~SYM[4] <= ~ARG[0] + to_unsigned(~SYM[1],~SIZE[~TYP[0]]);+ ~INST 1+ ~OUTPUT <= ~RESULT(~SYM[1])~ ~TYPEL[~TYPO]~+ ~INPUT <= ~SYM[4]~ ~TYP[0]~+ ~INPUT <= ~VAR[vec][2](~SYM[1])~ ~TYPEL[~TYP[2]]~+ ~INST+ end generate;~FI+ -- imap_go end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.zipWith+ kind: Declaration+ type: 'zipWith :: (a ->+ b -> c) -> Vec n a -> Vec n b -> Vec n c'+ template: |-+ -- zipWith begin+ ~GENSYM[zipWith][0] : for ~GENSYM[i][1] in ~RESULT'range generate~IF ~VIVADO ~THEN~IF~SIZE[~TYP[1]]~THEN+ signal ~GENSYM[zipWith_in1][2] : ~TYPEL[~TYP[1]];~ELSE ~FI~IF~SIZE[~TYP[2]]~THEN+ signal ~GENSYM[zipWith_in2][6] : ~TYPEL[~TYP[2]];~ELSE ~FI+ signal ~GENSYM[zipWith_out][3] : ~TYPEL[~TYPO];+ begin~IF~SIZE[~TYP[1]]~THEN+ ~SYM[2] <= fromSLV(~VAR[vec1][1](~SYM[1]));~ELSE ~FI~IF~SIZE[~TYP[2]]~THEN+ ~SYM[6] <= fromSLV(~VAR[vec2][2](~SYM[1]));~ELSE ~FI+ ~INST 0+ ~OUTPUT <= ~SYM[3]~ ~TYPEL[~TYPO]~+ ~INPUT <= ~SYM[2]~ ~TYPEL[~TYP[1]]~+ ~INPUT <= ~SYM[6]~ ~TYPEL[~TYP[2]]~+ ~INST+ ~RESULT(~SYM[1]) <= ~TOBV[~SYM[3]][~TYPEL[~TYPO]];+ end generate;~ELSE+ begin+ ~INST 0+ ~OUTPUT <= ~RESULT(~SYM[1])~ ~TYPEL[~TYPO]~+ ~INPUT <= ~VAR[vec1][1](~SYM[1])~ ~TYPEL[~TYP[1]]~+ ~INPUT <= ~VAR[vec2][2](~SYM[1])~ ~TYPEL[~TYP[2]]~+ ~INST+ end generate;~FI+ -- zipWith end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.foldr+ kind: Declaration+ type: 'foldr :: (a ->+ b -> b) -> b -> Vec n a -> b'+ template: |-+ -- foldr begin~IF ~LENGTH[~TYP[2]] ~THEN+ ~GENSYM[foldr][0] : block+ type ~GENSYM[foldr_res_type][1] is array (natural range <>) of ~TYP[1];+ signal ~GENSYM[intermediate][2] : ~SYM[1] (0 to ~LENGTH[~TYP[2]]);+ begin+ ~SYM[2](~LENGTH[~TYP[2]]) <= ~ARG[1];++ foldr_loop : for ~GENSYM[i][3] in 0 to (~LENGTH[~TYP[2]] - 1) generate~IF ~VIVADO ~THEN~IF~SIZE[~TYP[2]]~THEN+ signal ~GENSYM[foldr_in][4] : ~TYPEL[~TYP[2]];~ELSE ~FI+ begin~IF~SIZE[~TYP[2]]~THEN+ ~SYM[4] <= fromSLV(~VAR[vec][2](~SYM[3]));~ELSE ~FI+ ~INST 0+ ~OUTPUT <= ~SYM[2](~SYM[3])~ ~TYP[1]~+ ~INPUT <= ~SYM[4]~ ~TYPEL[~TYP[2]]~+ ~INPUT <= ~SYM[2](~SYM[3]+1)~ ~TYP[1]~+ ~INST+ end generate;~ELSE+ begin+ ~INST 0+ ~OUTPUT <= ~SYM[2](~SYM[3])~ ~TYP[1]~+ ~INPUT <= ~VAR[vec][2](~SYM[3])~ ~TYPEL[~TYP[2]]~+ ~INPUT <= ~SYM[2](~SYM[3]+1)~ ~TYP[1]~+ ~INST+ end generate;~FI++ ~RESULT <= ~SYM[2](0);+ end block;~ELSE+ ~RESULT <= ~ARG[1];~FI+ -- foldr end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.index_int+ kind: Declaration+ type: 'index_int :: KnownNat+ n => Vec n a -> Int -> a'+ template: |-+ -- index begin+ ~IF~SIZE[~TYP[1]]~THEN~GENSYM[indexVec][0] : block+ signal ~GENSYM[vec_index][1] : integer range 0 to ~LIT[0]-1;+ begin+ ~SYM[1] <= to_integer(~ARG[2])+ -- pragma translate_off+ mod ~LIT[0]+ -- pragma translate_on+ ;~IF ~VIVADO ~THEN+ ~RESULT <= fromSLV(~VAR[vec][1](~SYM[1]));~ELSE+ ~RESULT <= ~VAR[vec][1](~SYM[1]);~FI+ end block;~ELSE~RESULT <= ~ERRORO;~FI+ -- index end+- BlackBox:+ name: Clash.Sized.Vector.replace_int+ kind: Declaration+ type: 'replace_int ::+ KnownNat n => Vec n a -> Int -> a -> Vec n a'+ template: |-+ -- replace begin+ ~GENSYM[replaceVec][0] : block+ signal ~GENSYM[vec_index][1] : integer range 0 to ~LIT[0]-1;+ begin+ ~SYM[1] <= to_integer(~ARG[2])+ -- pragma translate_off+ mod ~LIT[0]+ -- pragma translate_on+ ;++ process(~SYM[1]~VARS[1]~VARS[3])+ variable ~GENSYM[ivec][2] : ~TYP[1];+ begin+ ~SYM[2] := ~ARG[1];~IF ~VIVADO ~THEN+ ~SYM[2](~SYM[1]) := ~TOBV[~ARG[3]][~TYP[3]];~ELSE+ ~SYM[2](~SYM[1]) := ~ARG[3];~FI+ ~RESULT <= ~SYM[2];+ end process;+ end block;+ -- replace end+- BlackBox:+ name: Clash.Sized.Vector.length+ kind: Expression+ type: 'length :: KnownNat+ n => Vec n a -> Int'+ template: to_signed(~LIT[0],~SIZE[~TYPO])+ workInfo: Constant+- BlackBox:+ name: Clash.Sized.Vector.replicate+ kind: Expression+ type: 'replicate :: SNat+ n -> a -> Vec n a'+ template: ~TYPMO'(0 to ~LIT[0]-1 => ~IF ~VIVADO ~THEN ~TOBV[~ARG[1]][~TYP[1]]+ ~ELSE ~ARG[1] ~FI)+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.transpose+ kind: Declaration+ type: 'transpose :: KnownNat+ n => Vec m (Vec n a) -> Vec n (Vec m a)'+ template: |-+ -- transpose begin+ ~GENSYM[transpose_outer][2] : for ~GENSYM[row_index][3] in 0 to (~LENGTH[~TYP[1]] - 1) generate+ ~GENSYM[transpose_inner][4] : for ~GENSYM[col_index][5] in ~RESULT'range generate~IF ~VIVADO ~THEN+ ~RESULT(~SYM[5])((~LENGTH[~TYP[1]]-~SYM[3])*~SIZE[~TYPEL[~TYPEL[~TYPO]]]-1 downto (~LENGTH[~TYP[1]]-~SYM[3]-1)*~SIZE[~TYPEL[~TYPEL[~TYPO]]]) <= ~VAR[vec][1](~SYM[3])((~RESULT'length-~SYM[5])*~SIZE[~TYPEL[~TYPEL[~TYPO]]]-1 downto (~RESULT'length-~SYM[5]-1)*~SIZE[~TYPEL[~TYPEL[~TYPO]]]);~ELSE+ ~RESULT(~SYM[5])(~SYM[3]) <= ~VAR[matrix][1](~SYM[3])(~SYM[5]);~FI+ end generate;+ end generate;+ -- transpose end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.reverse+ kind: Declaration+ type: 'reverse :: Vec+ n a -> Vec n a'+ template: |-+ -- reverse begin+ ~GENSYM[reverse_loop][2] : for ~GENSYM[i][3] in 0 to (~LENGTH[~TYP[0]] - 1) generate+ ~RESULT(~VAR[vec][0]'high - ~SYM[3]) <= ~VAR[vec][0](~SYM[3]);+ end generate;+ -- reverse end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.concatBitVector#+ kind: Declaration+ type: |-+ concatBitVector# :: (KnownNat n,KnownNat m) -- (ARG[0],ARG[1])+ => Vec n (BitVector m) -- ARG[2]+ -> BitVector (n * m)+ template: |-+ -- concatBitVector begin+ ~GENSYM[concatBitVectorIter_loop][2] : for ~GENSYM[i][3] in 0 to (~LENGTH[~TYP[2]] - 1) generate+ ~RESULT(((~SYM[3] * ~LIT[1]) + ~LIT[1] - 1) downto (~SYM[3] * ~LIT[1])) <= ~TYPMO'(~VAR[vec][2](~VAR[vec][2]'high - ~SYM[3]));+ end generate;+ -- concatBitVector end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.unconcatBitVector#+ kind: Declaration+ type: |-+ unconcatBitVector# :: (KnownNat n, KnownNat m) -- (ARG[0],ARG[1])+ => BitVector (n * m) -- ARG[2]+ -> Vec n (BitVector m)+ template: |-+ -- unconcatBitVector begin+ ~GENSYM[unconcatBitVectorIter_loop][2] : for ~GENSYM[i][3] in ~RESULT'range generate+ ~RESULT(~RESULT'high - ~SYM[3]) <= ~VAR[vec][2](((~SYM[3] * ~LIT[1]) + ~LIT[1] - 1) downto (~SYM[3] * ~LIT[1]));+ end generate;+ -- unconcatBitVector end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.rotateLeftS+ kind: Declaration+ type: 'rotateLeftS ::+ KnownNat n => Vec n a -> SNat d -> Vec n a'+ template: |-+ -- rotateLeftS begin+ ~GENSYM[rotateLeftS][0] : block+ constant ~GENSYM[shift_amount][2] : natural := ~LIT[2] mod ~LIT[0];+ begin+ ~GENSYM[no_shift][3] : if ~SYM[2] = 0 generate+ ~RESULT <= ~VAR[vec][1];+ end generate;++ ~GENSYM[do_shift][4] : if ~SYM[2] /= 0 generate+ ~RESULT <= ~VAR[vec][1](~SYM[2] to ~LIT[0]-1) &+ ~VAR[vec][1](0 to ~SYM[2]-1);+ end generate;+ end block;+ -- rotateLeftS end+ workInfo: Never+- BlackBox:+ name: Clash.Sized.Vector.rotateRightS+ kind: Declaration+ type: 'rotateRightS ::+ KnownNat n => Vec n a -> SNat d -> Vec n a'+ template: |-+ -- rotateRightS begin+ ~GENSYM[rotateLeftS][0] : block+ constant ~GENSYM[shift_amount][2] : natural := ~LIT[2] mod ~LIT[0];+ begin+ ~GENSYM[no_shift][3] : if ~SYM[2] = 0 generate+ ~RESULT <= ~VAR[vec][1];+ end generate;++ ~GENSYM[do_shift][4] : if ~SYM[2] /= 0 generate+ ~RESULT <= ~VAR[vec][1](~LIT[0]-~SYM[2] to ~LIT[0]-1) &+ ~VAR[vec][1](0 to ~LIT[0]-~SYM[2]-1);+ end generate;+ end block;+ -- rotateRightS end+ workInfo: Never
− prims/vhdl/Clash_Transformations.primitives
@@ -1,8 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Transformations.eqInt"- , "kind" : "Expression"- , "type" : "eqInt :: Int -> Int -> Bool"- , "template" : "~ARG[0] = ~ARG[1]"- }- }-]
− prims/vhdl/Clash_Xilinx_ClockGen.primitives
@@ -1,70 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Xilinx.ClockGen.clockWizard"- , "workInfo" : "Always"- , "kind" : "Declaration"- , "type" :-"clockWizard- :: ( KnownDomain domIn confIn -- ARG[0]- , KnownDomain domOut confOut ) -- ARG[1]- => SSymbol name -- ARG[2]- -> Clock pllIn -- ARG[3]- -> Reset pllIn -- ARG[4]- -> (Clock pllOut, Enable pllOut)"- , "template" :-"-- clockWizard begin-~GENSYM[clockWizard][0] : block- signal ~GENSYM[pllOut][1] : std_logic;- signal ~GENSYM[locked][2] : std_logic;- signal ~GENSYM[pllLock][3] : boolean;-- component ~NAME[2]- port (CLK_IN1 : in std_logic;- RESET : in std_logic;- CLK_OUT1 : out std_logic;- LOCKED : out std_logic);- end component;-begin- ~GENSYM[clockWizard_inst][4] : component ~NAME[2] port map (~ARG[3],~IF ~ISACTIVEHIGH[0] ~THEN ~ARG[4] ~ELSE NOT(~ARG[4]) ~FI,~SYM[1],~SYM[2]);- ~SYM[3] <= true when ~SYM[2] = '1' else false;- ~RESULT <= (~SYM[1],~SYM[3]);-end block;--- clockWizard end"- }- }-, { "BlackBox" :- { "name" : "Clash.Xilinx.ClockGen.clockWizardDifferential"- , "workInfo" : "Always"- , "kind" : "Declaration"- , "type" :-"clockWizardDifferential- :: ( KnownDomain domIn confIn -- ARG[0]- , KnownDomain domOut confOut ) -- ARG[1]- => SSymbol name -- ARG[2]- -> Clock pllIn -- ARG[3]- -> Clock pllIn -- ARG[4]- -> Reset pllIn -- ARG[5]- -> (Clock pllOut, Enable pllOut)"- , "template" :-"-- clockWizardDifferential begin-~GENSYM[clockWizardDifferential][0] : block- signal ~GENSYM[pllOut][1] : std_logic;- signal ~GENSYM[locked][2] : std_logic;- signal ~GENSYM[pllLock][3] : boolean;-- component ~NAME[2]- port (CLK_IN1_D_clk_n : in std_logic;- CLK_IN1_D_clk_p : in std_logic;- RESET : in std_logic;- CLK_OUT1 : out std_logic;- LOCKED : out std_logic);- end component;-begin- ~GENSYM[clockWizardDifferential_inst][4] : component ~NAME[2]- port map (~ARG[3],~ARG[4],~IF ~ISACTIVEHIGH[0] ~THEN ~ARG[5] ~ELSE NOT(~ARG[5]) ~FI,~SYM[1],~SYM[2]);- ~SYM[3] <= true when ~SYM[2] = '1' else false;- ~RESULT <= (~SYM[1],~SYM[3]);-end block;--- clockWizardDifferential end"- }- }-]
+ prims/vhdl/Clash_Xilinx_ClockGen.primitives.yaml view
@@ -0,0 +1,65 @@+- BlackBox:+ name: Clash.Xilinx.ClockGen.clockWizard+ kind: Declaration+ type: |-+ clockWizard+ :: ( KnownDomain domIn confIn -- ARG[0]+ , KnownDomain domOut confOut ) -- ARG[1]+ => SSymbol name -- ARG[2]+ -> Clock pllIn -- ARG[3]+ -> Reset pllIn -- ARG[4]+ -> (Clock pllOut, Enable pllOut)+ template: |-+ -- clockWizard begin+ ~GENSYM[clockWizard][0] : block+ signal ~GENSYM[pllOut][1] : std_logic;+ signal ~GENSYM[locked][2] : std_logic;+ signal ~GENSYM[pllLock][3] : boolean;++ component ~NAME[2]+ port (CLK_IN1 : in std_logic;+ RESET : in std_logic;+ CLK_OUT1 : out std_logic;+ LOCKED : out std_logic);+ end component;+ begin+ ~GENSYM[clockWizard_inst][4] : component ~NAME[2] port map (~ARG[3],~IF ~ISACTIVEHIGH[0] ~THEN ~ARG[4] ~ELSE NOT(~ARG[4]) ~FI,~SYM[1],~SYM[2]);+ ~SYM[3] <= true when ~SYM[2] = '1' else false;+ ~RESULT <= (~SYM[1],~SYM[3]);+ end block;+ -- clockWizard end+ workInfo: Always+- BlackBox:+ name: Clash.Xilinx.ClockGen.clockWizardDifferential+ kind: Declaration+ type: |-+ clockWizardDifferential+ :: ( KnownDomain domIn confIn -- ARG[0]+ , KnownDomain domOut confOut ) -- ARG[1]+ => SSymbol name -- ARG[2]+ -> Clock pllIn -- ARG[3]+ -> Clock pllIn -- ARG[4]+ -> Reset pllIn -- ARG[5]+ -> (Clock pllOut, Enable pllOut)+ template: |-+ -- clockWizardDifferential begin+ ~GENSYM[clockWizardDifferential][0] : block+ signal ~GENSYM[pllOut][1] : std_logic;+ signal ~GENSYM[locked][2] : std_logic;+ signal ~GENSYM[pllLock][3] : boolean;++ component ~NAME[2]+ port (CLK_IN1_D_clk_n : in std_logic;+ CLK_IN1_D_clk_p : in std_logic;+ RESET : in std_logic;+ CLK_OUT1 : out std_logic;+ LOCKED : out std_logic);+ end component;+ begin+ ~GENSYM[clockWizardDifferential_inst][4] : component ~NAME[2]+ port map (~ARG[3],~ARG[4],~IF ~ISACTIVEHIGH[0] ~THEN ~ARG[5] ~ELSE NOT(~ARG[5]) ~FI,~SYM[1],~SYM[2]);+ ~SYM[3] <= true when ~SYM[2] = '1' else false;+ ~RESULT <= (~SYM[1],~SYM[3]);+ end block;+ -- clockWizardDifferential end+ workInfo: Always
− prims/vhdl/Clash_Xilinx_DDR.primitives
@@ -1,103 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Xilinx.DDR.iddr"- , "kind" : "Declaration"- , "type" :-"iddr- :: ( HasCallStack -- ARG[0]- , KnownConfi~ fast domf -- ARG[1]- , KnownConfi~ slow doms -- ARG[2]- , KnownNat m ) -- ARG[3]- -> Clock slow -- ARG[4]- -> Reset slow -- ARG[5]- -> Enable slow -- ARG[6]- -> Signal fast (BitVector m) -- ARG[7]- -> Signal slow (BitVector m,BitVector m)"- , "libraries" : ["UNISIM"]- , "imports" : ["UNISIM.vcomponents.all"]- , "template" :-"-- iddr begin-~GENSYM[~COMPNAME_IDDR][0] : block- signal ~GENSYM[dataout_l][1] : ~TYP[7];- signal ~GENSYM[dataout_h][2] : ~TYP[7];- signal ~GENSYM[d][3] : ~TYP[7];~IF ~ISACTIVEENABLE[4] ~THEN- signal ~GENSYM[ce_logic][4]: std_logic;~ELSE ~FI-begin~IF ~ISACTIVEENABLE[4] ~THEN- ~SYM[4] <= '1' when (~ARG[6]) else '0';~ELSE ~FI- ~SYM[3] <= ~ARG[7];-- ~GENSYM[gen_iddr][7] : for ~GENSYM[i][8] in ~SYM[3]'range generate- begin- ~GENSYM[~COMPNAME_IDDR_inst][9] : IDDR- generic map (- DDR_CLK_EDGE => \"SAME_EDGE\",- INIT_Q1 => '0',- INIT_Q2 => '0',- SRTYPE => ~IF ~ISSYNC[2] ~THEN \"SYNC\" ~ELSE \"ASYNC\" ~FI)- port map (- Q1 => ~SYM[1](~SYM[8]), -- 1-bit output for positive edge of clock- Q2 => ~SYM[2](~SYM[8]), -- 1-bit output for negative edge of clock- C => ~ARG[4], -- 1-bit clock input- CE => ~IF ~ISACTIVEENABLE[6] ~THEN ~SYM[4] ~ELSE '1' ~FI, -- 1-bit clock enable input- D => ~SYM[3](~SYM[8]), -- 1-bit DDR data input- R => ~ARG[5], -- 1-bit reset- S => '0' -- 1-bit set- );- end generate;-- ~RESULT <= (~SYM[2], ~SYM[1]);-end block;--- iddr# end"- }- }-, { "BlackBox" :- { "name" : "Clash.Xilinx.DDR.oddr#"- , "kind" : "Declaration"- , "type" :-"oddr#- :: ( KnownConfi~ fast domf -- ARG[0]- , KnownConfi~ slow doms -- ARG[1]- , KnownNat m ) -- ARG[2]- => Clock slow -- ARG[3]- -> Reset slow -- ARG[4]- -> Enable slow -- ARG[5]- -> Signal slow (BitVector m) -- ARG[6]- -> Signal slow (BitVector m) -- ARG[7]- -> Signal fast (BitVector m)"- , "libraries" : ["UNISIM"]- , "imports" : ["UNISIM.vcomponents.all"]- , "template" :-"-- oddr begin-~GENSYM[~COMPNAME_ODDR][0] : block- signal ~GENSYM[dataout_l][1] : ~TYPO;- signal ~GENSYM[dataout_h][2] : ~TYPO;- signal ~GENSYM[q][3] : ~TYPO;~IF ~ISACTIVEENABLE[5] ~THEN- signal ~GENSYM[ce_logic][4] : std_logic;~ELSE ~FI-begin~IF ~ISACTIVEENABLE[5] ~THEN- ~SYM[4] <= '1' when (~ARG[5]) else '0';~ELSE ~FI- ~SYM[1] <= ~ARG[6];- ~SYM[2] <= ~ARG[7];-- ~GENSYM[gen_iddr][7] : for ~GENSYM[i][8] in ~SYM[3]'range generate- begin- ~GENSYM[~COMPNAME_ODDR_inst][9] : ODDR- generic map(- DDR_CLK_EDGE => \"SAME_EDGE\",- INIT => '0',- SRTYPE => ~IF ~ISSYNC[2] ~THEN \"SYNC\" ~ELSE \"ASYNC\" ~FI)- port map (- Q => ~SYM[3](~SYM[8]), -- 1-bit DDR output- C => ~ARG[3], -- 1-bit clock input- CE => ~IF ~ISACTIVEENABLE[5] ~THEN ~SYM[4] ~ELSE '1' ~FI, -- 1-bit clock enable input- D1 => ~SYM[1](~SYM[8]), -- 1-bit data input (positive edge)- D2 => ~SYM[2](~SYM[8]), -- 1-bit data input (negative edge)- R => ~ARG[4], -- 1-bit reset input- S => '0' -- 1-bit set input- );- end generate;-- ~RESULT <= ~SYM[3];-end block;--- oddr end"- }- }-]
+ prims/vhdl/Clash_Xilinx_DDR.primitives.yaml view
@@ -0,0 +1,102 @@+- BlackBox:+ name: Clash.Xilinx.DDR.iddr+ imports:+ - UNISIM.vcomponents.all+ kind: Declaration+ libraries:+ - UNISIM+ type: |-+ iddr+ :: ( HasCallStack -- ARG[0]+ , KnownConfi~ fast domf -- ARG[1]+ , KnownConfi~ slow doms -- ARG[2]+ , KnownNat m ) -- ARG[3]+ -> Clock slow -- ARG[4]+ -> Reset slow -- ARG[5]+ -> Enable slow -- ARG[6]+ -> Signal fast (BitVector m) -- ARG[7]+ -> Signal slow (BitVector m,BitVector m)+ template: |-+ -- iddr begin+ ~GENSYM[~COMPNAME_IDDR][0] : block+ signal ~GENSYM[dataout_l][1] : ~TYP[7];+ signal ~GENSYM[dataout_h][2] : ~TYP[7];+ signal ~GENSYM[d][3] : ~TYP[7];~IF ~ISACTIVEENABLE[4] ~THEN+ signal ~GENSYM[ce_logic][4]: std_logic;~ELSE ~FI+ begin~IF ~ISACTIVEENABLE[4] ~THEN+ ~SYM[4] <= '1' when (~ARG[6]) else '0';~ELSE ~FI+ ~SYM[3] <= ~ARG[7];++ ~GENSYM[gen_iddr][7] : for ~GENSYM[i][8] in ~SYM[3]'range generate+ begin+ ~GENSYM[~COMPNAME_IDDR_inst][9] : IDDR+ generic map (+ DDR_CLK_EDGE => "SAME_EDGE",+ INIT_Q1 => '0',+ INIT_Q2 => '0',+ SRTYPE => ~IF ~ISSYNC[2] ~THEN "SYNC" ~ELSE "ASYNC" ~FI)+ port map (+ Q1 => ~SYM[1](~SYM[8]), -- 1-bit output for positive edge of clock+ Q2 => ~SYM[2](~SYM[8]), -- 1-bit output for negative edge of clock+ C => ~ARG[4], -- 1-bit clock input+ CE => ~IF ~ISACTIVEENABLE[6] ~THEN ~SYM[4] ~ELSE '1' ~FI, -- 1-bit clock enable input+ D => ~SYM[3](~SYM[8]), -- 1-bit DDR data input+ R => ~ARG[5], -- 1-bit reset+ S => '0' -- 1-bit set+ );+ end generate;++ ~RESULT <= (~SYM[2], ~SYM[1]);+ end block;+ -- iddr# end+- BlackBox:+ name: Clash.Xilinx.DDR.oddr#+ imports:+ - UNISIM.vcomponents.all+ kind: Declaration+ libraries:+ - UNISIM+ type: |-+ oddr#+ :: ( KnownConfi~ fast domf -- ARG[0]+ , KnownConfi~ slow doms -- ARG[1]+ , KnownNat m ) -- ARG[2]+ => Clock slow -- ARG[3]+ -> Reset slow -- ARG[4]+ -> Enable slow -- ARG[5]+ -> Signal slow (BitVector m) -- ARG[6]+ -> Signal slow (BitVector m) -- ARG[7]+ -> Signal fast (BitVector m)+ template: |-+ -- oddr begin+ ~GENSYM[~COMPNAME_ODDR][0] : block+ signal ~GENSYM[dataout_l][1] : ~TYPO;+ signal ~GENSYM[dataout_h][2] : ~TYPO;+ signal ~GENSYM[q][3] : ~TYPO;~IF ~ISACTIVEENABLE[5] ~THEN+ signal ~GENSYM[ce_logic][4] : std_logic;~ELSE ~FI+ begin~IF ~ISACTIVEENABLE[5] ~THEN+ ~SYM[4] <= '1' when (~ARG[5]) else '0';~ELSE ~FI+ ~SYM[1] <= ~ARG[6];+ ~SYM[2] <= ~ARG[7];++ ~GENSYM[gen_iddr][7] : for ~GENSYM[i][8] in ~SYM[3]'range generate+ begin+ ~GENSYM[~COMPNAME_ODDR_inst][9] : ODDR+ generic map(+ DDR_CLK_EDGE => "SAME_EDGE",+ INIT => '0',+ SRTYPE => ~IF ~ISSYNC[2] ~THEN "SYNC" ~ELSE "ASYNC" ~FI)+ port map (+ Q => ~SYM[3](~SYM[8]), -- 1-bit DDR output+ C => ~ARG[3], -- 1-bit clock input+ CE => ~IF ~ISACTIVEENABLE[5] ~THEN ~SYM[4] ~ELSE '1' ~FI, -- 1-bit clock enable input+ D1 => ~SYM[1](~SYM[8]), -- 1-bit data input (positive edge)+ D2 => ~SYM[2](~SYM[8]), -- 1-bit data input (negative edge)+ R => ~ARG[4], -- 1-bit reset input+ S => '0' -- 1-bit set input+ );+ end generate;++ ~RESULT <= ~SYM[3];+ end block;+ -- oddr end
− prims/vhdl/GHC_Base.primitives
@@ -1,31 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Base.remInt"- , "kind" : "Expression"- , "type" : "remInt :: Int -> Int -> Int"- , "template" : "~ARG[0] rem ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Base.divInt"- , "kind" : "Declaration"- , "type" : "divInt :: Int -> Int -> Int"- , "template" :-"-- divInt begin-~GENSYM[divInt][0] : block- signal ~GENSYM[quot_res][1] : ~TYP[1];-begin- ~SYM[1] <= ~ARG[0] / ~ARG[1];- ~RESULT <= ~SYM[1] - 1 when ((~ARG[0] = abs ~ARG[0]) /= (~ARG[1] = abs ~ARG[1])) else- ~SYM[1];-end block;--- divInt end"- }- }-, { "BlackBox" :- { "name" : "GHC.Base.modInt"- , "kind" : "Expression"- , "type" : "modInt :: Int -> Int -> Int"- , "template" : "~ARG[0] mod ~ARG[1]"- }- }-]
+ prims/vhdl/GHC_Base.primitives.yaml view
@@ -0,0 +1,52 @@+- BlackBox:+ name: GHC.Base.remInt+ kind: Declaration+ type: 'remInt :: Int ->+ Int -> Int'+ template: |-+ ~RESULT <= ~ARG[0] rem ~ARG[1]+ -- pragma translate_off+ when (~ARG[1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;+- BlackBox:+ name: GHC.Base.divInt+ kind: Declaration+ type: 'divInt :: Int ->+ Int -> Int'+ template: |-+ -- divInt begin+ ~GENSYM[divInt][0] : block+ signal ~GENSYM[quot_res][1] : ~TYP[1];+ begin+ ~SYM[1] <= ~ARG[0] / ~ARG[1]+ -- pragma translate_off+ when (ARG[1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;+ ~RESULT <= ~SYM[1] - 1 when ((~ARG[0] = abs ~ARG[0]) /= (~ARG[1] = abs ~ARG[1])) else+ ~SYM[1];+ end block;+ -- divInt end+- BlackBox:+ name: GHC.Base.modInt+ kind: Declaration+ type: 'modInt :: Int ->+ Int -> Int'+ template: |-+ ~RESULT <= ~ARG[0] mod ~ARG[1]+ -- pragma translate_off+ when (~ARG[1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;+- BlackBox:+ name: GHC.Base.quotInt+ kind: Declaration+ type: 'quotInt :: Int+ -> Int -> Int'+ template: |-+ ~RESULT <= ~ARG[0] / ~ARG[1]+ -- pragma translate_off+ when (~ARG[1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;
− prims/vhdl/GHC_Classes.primitives
@@ -1,66 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Classes.eqInt"- , "kind" : "Expression"- , "type" : "eqInt :: Int -> Int -> Bool"- , "template" : "~ARG[0] = ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.neInt"- , "kind" : "Expression"- , "type" : "neInt :: Int -> Int -> Bool"- , "template" : "~ARG[0] /= ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.&&"- , "kind" : "Expression"- , "type" : "(&&) :: Bool -> Bool -> Bool"- , "template" : "~ARG[0] and ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.||"- , "kind" : "Expression"- , "type" : "(::) :: Bool -> Bool -> Bool"- , "template" : "~ARG[0] or ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.not"- , "kind" : "Expression"- , "type" : "not :: Bool -> Bool"- , "template" : "not ~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.divInt#"- , "kind" : "Declaration"- , "type" : "divInt# :: Int# -> Int# -> Int#"- , "template" :-"-- divInt# begin-~GENSYM[divInt][0] : block- signal ~GENSYM[resultPos][1] : boolean;- signal ~GENSYM[dividerNeg][2] : boolean;- signal ~GENSYM[dividend2][3] : signed(~SIZE[~TYPO] downto 0);- signal ~GENSYM[quot_res][4] : signed(~SIZE[~TYPO] downto 0);-begin- ~SYM[1] <= ~VAR[dividend][0](~VAR[dividend][0]'high) = ~VAR[divider][1](~VAR[divider][1]'high);- ~SYM[2] <= ~VAR[divider][1](~VAR[divider][1]'high) = '1';- ~SYM[3] <= resize(~VAR[dividend][0],~SIZE[~TYPO]+1) when ~SYM[1] else- (resize(~VAR[dividend][0],~SIZE[~TYPO]+1) - resize(~VAR[divider][1],~SIZE[~TYPO]+1) - 1) when ~SYM[2] else- (resize(~VAR[dividend][0],~SIZE[~TYPO]+1) - resize(~VAR[divider][1],~SIZE[~TYPO]+1) + 1);- ~SYM[4] <= ~SYM[3] / ~VAR[divider][1];- ~RESULT <= signed(~SYM[4](~SIZE[~TYPO]-1 downto 0));-end block;--- divInt# end"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.modInt#"- , "kind" : "Expression"- , "type" : "modInt# :: Int# -> Int# -> Int#"- , "template" : "~ARG[0] mod ~ARG[1]"- }- }-]
+ prims/vhdl/GHC_Classes.primitives.yaml view
@@ -0,0 +1,62 @@+- BlackBox:+ name: GHC.Classes.eqInt+ kind: Expression+ type: 'eqInt :: Int ->+ Int -> Bool'+ template: ~ARG[0] = ~ARG[1]+- BlackBox:+ name: GHC.Classes.neInt+ kind: Expression+ type: 'neInt :: Int ->+ Int -> Bool'+ template: ~ARG[0] /= ~ARG[1]+- BlackBox:+ name: GHC.Classes.&&+ kind: Expression+ type: '(&&) :: Bool ->+ Bool -> Bool'+ template: ~ARG[0] and ~ARG[1]+- BlackBox:+ name: GHC.Classes.||+ kind: Expression+ type: '(::) :: Bool ->+ Bool -> Bool'+ template: ~ARG[0] or ~ARG[1]+- BlackBox:+ name: GHC.Classes.not+ kind: Expression+ type: 'not :: Bool ->+ Bool'+ template: not ~ARG[0]+- BlackBox:+ name: GHC.Classes.divInt#+ kind: Declaration+ type: 'divInt# :: Int#+ -> Int# -> Int#'+ template: |-+ -- divInt# begin+ ~GENSYM[divInt][0] : block+ signal ~GENSYM[resultPos][1] : boolean;+ signal ~GENSYM[dividerNeg][2] : boolean;+ signal ~GENSYM[dividend2][3] : signed(~SIZE[~TYPO] downto 0);+ signal ~GENSYM[quot_res][4] : signed(~SIZE[~TYPO] downto 0);+ begin+ ~SYM[1] <= ~VAR[dividend][0](~VAR[dividend][0]'high) = ~VAR[divider][1](~VAR[divider][1]'high);+ ~SYM[2] <= ~VAR[divider][1](~VAR[divider][1]'high) = '1';+ ~SYM[3] <= resize(~VAR[dividend][0],~SIZE[~TYPO]+1) when ~SYM[1] else+ (resize(~VAR[dividend][0],~SIZE[~TYPO]+1) - resize(~VAR[divider][1],~SIZE[~TYPO]+1) - 1) when ~SYM[2] else+ (resize(~VAR[dividend][0],~SIZE[~TYPO]+1) - resize(~VAR[divider][1],~SIZE[~TYPO]+1) + 1);+ ~SYM[4] <= ~SYM[3] / ~VAR[divider][1]+ -- pragma translate_off+ when (~VAR[divider][1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;+ ~RESULT <= signed(~SYM[4](~SIZE[~TYPO]-1 downto 0));+ end block;+ -- divInt# end+- BlackBox:+ name: GHC.Classes.modInt#+ kind: Expression+ type: 'modInt# :: Int#+ -> Int# -> Int#'+ template: ~ARG[0] mod ~ARG[1]
− prims/vhdl/GHC_Int.primitives
@@ -1,33 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Int.I8#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "I8# :: Int# -> Int8"- , "template" : "resize(~ARG[0],8)"- }- }-, { "BlackBox" :- { "name" : "GHC.Int.I16#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "I16# :: Int# -> Int16"- , "template" : "resize(~ARG[0],16)"- }- }-, { "BlackBox" :- { "name" : "GHC.Int.I32#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "I32# :: Int# -> Int32"- , "template" : "resize(~ARG[0],32)"- }- }-, { "BlackBox" :- { "name" : "GHC.Int.I64#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "I64# :: Int# -> Int64"- , "template" : "resize(~ARG[0],64)"- }- }-]
+ prims/vhdl/GHC_Int.primitives.yaml view
@@ -0,0 +1,28 @@+- BlackBox:+ name: GHC.Int.I8#+ kind: Expression+ type: 'I8# :: Int# ->+ Int8'+ template: resize(~ARG[0],8)+ workInfo: Never+- BlackBox:+ name: GHC.Int.I16#+ kind: Expression+ type: 'I16# :: Int# ->+ Int16'+ template: resize(~ARG[0],16)+ workInfo: Never+- BlackBox:+ name: GHC.Int.I32#+ kind: Expression+ type: 'I32# :: Int# ->+ Int32'+ template: resize(~ARG[0],32)+ workInfo: Never+- BlackBox:+ name: GHC.Int.I64#+ kind: Expression+ type: 'I64# :: Int# ->+ Int64'+ template: resize(~ARG[0],64)+ workInfo: Never
− prims/vhdl/GHC_Integer_Logarithms.primitives
@@ -1,8 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Integer.Logarithms.integerLogBase#"- , "kind" : "Expression"- , "type" : "integerLogBase# :: Integer -> Integer -> Int#"- , "template" : "integer(floor(log(real(~ARG[1]),real(~ARG[0]))))"- }- }-]
+ prims/vhdl/GHC_Integer_Logarithms.primitives.yaml view
@@ -0,0 +1,8 @@+- BlackBox:+ name: GHC.Integer.Logarithms.integerLogBase#+ kind: Expression+ type: 'integerLogBase#+ :: Integer -> Integer -> Int#'+ template: integer(floor(log(real(~ARG[1]),real(~ARG[0]))))+ warning: 'GHC.Integer.Logarithms.integerLogBase#: Integers are dynamically sized+ in simulation, but fixed-length after synthesis. Use carefully.'
− prims/vhdl/GHC_Integer_Type.primitives
@@ -1,267 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Integer.Type.smallInteger"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "smallInteger :: Int# -> Integer"- , "template" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.integerToInt"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "integerToInt :: Integer -> Int#"- , "template" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.timesInteger"- , "kind" : "Expression"- , "type" : "timesInteger :: Integer -> Integer -> Integer"- , "template" : "resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO])"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.negateInteger"- , "kind" : "Expression"- , "type" : "negateInteger :: Integer -> Integer"- , "template" : "-~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.absInteger"- , "kind" : "Expression"- , "type" : "absInteger :: Integer -> Integer"- , "template" : "abs ~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.divInteger"- , "kind" : "Declaration"- , "type" : "divInteger :: Integer -> Integer -> Integer"- , "template" :-"-- divInteger begin-~GENSYM[divInteger][0] : block- signal ~GENSYM[resultPos][1] : boolean;- signal ~GENSYM[dividerNeg][2] : boolean;- signal ~GENSYM[dividend2][3] : signed(~SIZE[~TYPO] downto 0);- signal ~GENSYM[quot_res][4] : signed(~SIZE[~TYPO] downto 0);-begin- ~SYM[1] <= ~VAR[dividend][0](~VAR[dividend][0]'high) = ~VAR[divider][1](~VAR[divider][1]'high);- ~SYM[2] <= ~VAR[divider][1](~VAR[divider][1]'high) = '1';- ~SYM[3] <= resize(~VAR[dividend][0],~SIZE[~TYPO]+1) when ~SYM[1] else- (resize(~VAR[dividend][0],~SIZE[~TYPO]+1) - resize(~VAR[divider][1],~SIZE[~TYPO]+1) - 1) when ~SYM[2] else- (resize(~VAR[dividend][0],~SIZE[~TYPO]+1) - resize(~VAR[divider][1],~SIZE[~TYPO]+1) + 1);- ~SYM[4] <= ~SYM[3] / ~VAR[divider][1];- ~RESULT <= signed(~SYM[4](~SIZE[~TYPO]-1 downto 0));-end block;--- divInteger end"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.modInteger"- , "kind" : "Expression"- , "type" : "modInteger :: Integer -> Integer -> Integer"- , "template" : "~ARG[0] mod ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.divModInteger"- , "kind" : "Declaration"- , "type" : "divModInteger :: Integer -> Integer -> (# Integer, Integer #)"- , "template" :-"-- divModInteger begin-~GENSYM[divModInteger][0] : block- signal ~GENSYM[resultPos][1] : boolean;- signal ~GENSYM[dividerNeg][2] : boolean;- signal ~GENSYM[dividend2][3] : signed(~SIZE[~TYP[0]] downto 0);- signal ~GENSYM[quot_res][4] : signed(~SIZE[~TYP[0]] downto 0);- signal ~GENSYM[div_res][5] : signed(~SIZE[~TYP[0]]-1 downto 0);-begin- ~SYM[1] <= ~VAR[dividend][0](~VAR[dividend][0]'high) = ~VAR[divider][1](~VAR[divider][1]'high);- ~SYM[2] <= ~VAR[divider][1](~VAR[divider][1]'high) = '1';- ~SYM[3] <= resize(~VAR[dividend][0],~SIZE[~TYP[0]]+1) when ~SYM[1] else- (resize(~VAR[dividend][0],~SIZE[~TYP[0]]+1) - resize(~VAR[divider][1],~SIZE[~TYP[0]]+1) - 1) when ~SYM[2] else- (resize(~VAR[dividend][0],~SIZE[~TYP[0]]+1) - resize(~VAR[divider][1],~SIZE[~TYP[0]]+1) + 1);- ~SYM[4] <= ~SYM[3] / ~VAR[divider][1];- ~SYM[5] <= signed(~SYM[4](~SIZE[~TYP[0]]-1 downto 0));- ~RESULT <= (~SYM[5], ~VAR[dividend][0] mod ~VAR[divider][1]);-end block;--- divModInteger end"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.quotRemInteger"- , "kind" : "Expression"- , "type" : "quotRemInteger :: Integer -> Integer -> (# Integer, Integer #)"- , "template" : "(~ARG[0] / ~ARG[1], ~ARG[0] rem ~ARG[1])"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.remInteger"- , "kind" : "Expression"- , "type" : "remInteger :: Integer -> Integer -> Integer"- , "template" : "~ARG[0] rem ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.eqInteger"- , "kind" : "Expression"- , "type" : "eqInteger :: Integer -> Integer -> Bool"- , "template" : "~ARG[0] = ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.neqInteger"- , "kind" : "Expression"- , "type" : "neqInteger :: Integer -> Integer -> Bool"- , "template" : "~ARG[0] /= ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.eqInteger#"- , "kind" : "Declaration"- , "type" : "eqInteger# :: Integer -> Integer -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.neqInteger#"- , "kind" : "Declaration"- , "type" : "neqInteger# :: Integer -> Integer -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.leInteger#"- , "kind" : "Declaration"- , "type" : "leInteger# :: Integer -> Integer -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.gtInteger#"- , "kind" : "Declaration"- , "type" : "gtInteger# :: Integer -> Integer -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.ltInteger#"- , "kind" : "Declaration"- , "type" : "ltInteger# :: Integer -> Integer -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.geInteger#"- , "kind" : "Declaration"- , "type" : "geInteger# :: Integer -> Integer -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.shiftRInteger"- , "kind" : "Declaration"- , "type" : "shiftRInteger :: Integer -> Int# -> Integer"- , "template" :-"~RESULT <= shift_right(~ARG[0], to_integer(~ARG[1]))- -- pragma translate_off- when (~ARG[1] >= 0) else (others => 'X')- -- pragma translate_on- ;"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.shiftLInteger"- , "kind" : "Declaration"- , "type" : "shiftLInteger :: Integer -> Int# -> Integer"- , "template" :-"~RESULT <= shift_left(~ARG[0], to_integer(~ARG[1]))- -- pragma translate_off- when (~ARG[1] >= 0) else (others => 'X')- -- pragma translate_on- ;"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.testBitInteger"- , "kind" : "Expression"- , "type" : "testBitInteger :: Integer -> Int# -> Bool"- , "template" : "~VAR[input][0](to_integer(~ARG[1])) = '1'"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.wordToInteger"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "wordToInteger :: Word# -> Integer"- , "template" : "signed(std_logic_vector(~ARG[0]))"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.integerToWord"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "integerToWord :: Integer -> Word#"- , "template" : "unsigned(std_logic_vector(~ARG[0]))"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.integerToWord64"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "integerToWord :: Integer -> Word64#"- , "comment" : "only used by 32 bit GHC"- , "template" : "unsigned(std_logic_vector(~ARG[0]))"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.bitInteger"- , "kind" : "Expression"- , "type" : "bitInteger :: Int -> Integer"- , "template" : "shift_left(to_signed(1, ~SIZE[~TYPO]),to_integer(~ARG[0]))"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.complementInteger"- , "kind" : "Expression"- , "type" : "complementInteger :: Integer -> Integer"- , "template" : "not ~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.xorInteger"- , "kind" : "Expression"- , "type" : "xorInteger :: Integer -> Integer -> Integer"- , "template" : "~ARG[0] xor ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.orInteger"- , "kind" : "Expression"- , "type" : "orInteger :: Integer -> Integer -> Integer"- , "template" : "~ARG[0] or ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.andInteger"- , "kind" : "Expression"- , "type" : "andInteger :: Integer -> Integer -> Integer"- , "template" : "~ARG[0] and ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.$wsignumInteger"- , "kind" : "Declaration"- , "type" : "$wsignumInteger :: Integer -> Integer"- , "template" : "--- begin signumInteger-~RESULT <= to_signed(-1, ~SIZE[~TYPO]) when ~ARG[0] < 0- else to_signed(0, ~SIZE[~TYPO]) when ~ARG[0] = 0- else to_signed(1, ~SIZE[~TYPO]);--- end signumInteger-"- }- }-]
+ prims/vhdl/GHC_Integer_Type.primitives.yaml view
@@ -0,0 +1,359 @@+- BlackBox:+ name: GHC.Integer.Type.smallInteger+ kind: Expression+ type: 'smallInteger ::+ Int# -> Integer'+ template: ~ARG[0]+ warning: 'GHC.Integer.Type.smallInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Integer.Type.integerToInt+ kind: Expression+ type: 'integerToInt ::+ Integer -> Int#'+ template: ~ARG[0]+ warning: 'GHC.Integer.Type.integerToInt: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Integer.Type.timesInteger+ kind: Expression+ type: 'timesInteger ::+ Integer -> Integer -> Integer'+ template: resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO])+ warning: 'GHC.Integer.Type.timesInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.negateInteger+ kind: Expression+ type: 'negateInteger ::+ Integer -> Integer'+ template: -~ARG[0]+ warning: 'GHC.Integer.Type.negateInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.absInteger+ kind: Expression+ type: 'absInteger :: Integer+ -> Integer'+ template: abs ~ARG[0]+ warning: 'GHC.Integer.Type.absInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.divInteger+ kind: Declaration+ type: 'divInteger :: Integer+ -> Integer -> Integer'+ template: |-+ -- divInteger begin+ ~GENSYM[divInteger][0] : block+ signal ~GENSYM[resultPos][1] : boolean;+ signal ~GENSYM[dividerNeg][2] : boolean;+ signal ~GENSYM[dividend2][3] : signed(~SIZE[~TYPO] downto 0);+ signal ~GENSYM[quot_res][4] : signed(~SIZE[~TYPO] downto 0);+ begin+ ~SYM[1] <= ~VAR[dividend][0](~VAR[dividend][0]'high) = ~VAR[divider][1](~VAR[divider][1]'high);+ ~SYM[2] <= ~VAR[divider][1](~VAR[divider][1]'high) = '1';+ ~SYM[3] <= resize(~VAR[dividend][0],~SIZE[~TYPO]+1) when ~SYM[1] else+ (resize(~VAR[dividend][0],~SIZE[~TYPO]+1) - resize(~VAR[divider][1],~SIZE[~TYPO]+1) - 1) when ~SYM[2] else+ (resize(~VAR[dividend][0],~SIZE[~TYPO]+1) - resize(~VAR[divider][1],~SIZE[~TYPO]+1) + 1);+ ~SYM[4] <= ~SYM[3] / ~VAR[divider][1]+ -- pragma translate_off+ when (~VAR[divider][1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;+ ~RESULT <= signed(~SYM[4](~SIZE[~TYPO]-1 downto 0));+ end block;+ -- divInteger end+ warning: 'GHC.Integer.Type.divInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.modInteger+ kind: Expression+ type: 'modInteger :: Integer+ -> Integer -> Integer'+ template: ~ARG[0] mod ~ARG[1]+ warning: 'GHC.Integer.Type.modInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.divModInteger+ kind: Declaration+ type: 'divModInteger ::+ Integer -> Integer -> (# Integer, Integer #)'+ template: |-+ -- divModInteger begin+ ~GENSYM[divModInteger][0] : block+ signal ~GENSYM[resultPos][1] : boolean;+ signal ~GENSYM[dividerNeg][2] : boolean;+ signal ~GENSYM[dividend2][3] : signed(~SIZE[~TYP[0]] downto 0);+ signal ~GENSYM[quot_res][4] : signed(~SIZE[~TYP[0]] downto 0);+ signal ~GENSYM[div_res][5] : signed(~SIZE[~TYP[0]]-1 downto 0);+ signal ~GENSYM[mod_res][6] : signed(~SIZE[~TYP[0]]-1 downto 0);+ begin+ ~SYM[1] <= ~VAR[dividend][0](~VAR[dividend][0]'high) = ~VAR[divider][1](~VAR[divider][1]'high);+ ~SYM[2] <= ~VAR[divider][1](~VAR[divider][1]'high) = '1';+ ~SYM[3] <= resize(~VAR[dividend][0],~SIZE[~TYP[0]]+1) when ~SYM[1] else+ (resize(~VAR[dividend][0],~SIZE[~TYP[0]]+1) - resize(~VAR[divider][1],~SIZE[~TYP[0]]+1) - 1) when ~SYM[2] else+ (resize(~VAR[dividend][0],~SIZE[~TYP[0]]+1) - resize(~VAR[divider][1],~SIZE[~TYP[0]]+1) + 1);+ ~SYM[4] <= ~SYM[3] / ~VAR[divider][1]+ -- pragma translate_off+ when (~VAR[divider][1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;+ ~SYM[5] <= signed(~SYM[4](~SIZE[~TYP[0]]-1 downto 0));+ ~SYM[6] <= ~VAR[dividend][0] mod ~VAR[divider][1]+ -- pragma translate_off+ when (~VAR[divider][1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;+ ~RESULT <= (~SYM[5], ~SYM[6]);+ end block;+ -- divModInteger end+ warning: 'GHC.Integer.Type.divModInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.quotRemInteger+ kind: Declaration+ type: 'quotRemInteger+ :: Integer -> Integer -> (# Integer, Integer #)'+ template: |-+ ~RESULT <= (~ARG[0] / ~ARG[1], ~ARG[0] rem ~ARG[1])+ -- pragma translate_off+ when (~ARG[1] /= 0) else ((others => 'X'), (others => 'X'))+ -- pragma translate_on+ ;+ warning: 'GHC.Integer.Type.quotRemInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.remInteger+ kind: Declaration+ type: 'remInteger :: Integer+ -> Integer -> Integer'+ template: |-+ ~RESULT <= ~ARG[0] rem ~ARG[1]+ -- pragma translate_off+ when (~ARG[1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;+ warning: 'GHC.Integer.Type.remInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.eqInteger+ kind: Expression+ type: 'eqInteger :: Integer+ -> Integer -> Bool'+ template: ~ARG[0] = ~ARG[1]+ warning: 'GHC.Integer.Type.eqInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.neqInteger+ kind: Expression+ type: 'neqInteger :: Integer+ -> Integer -> Bool'+ template: ~ARG[0] /= ~ARG[1]+ warning: 'GHC.Integer.Type.neqInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.eqInteger#+ kind: Declaration+ type: 'eqInteger# :: Integer+ -> Integer -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+ warning: 'GHC.Integer.Type.eqInteger#: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.neqInteger#+ kind: Declaration+ type: 'neqInteger# ::+ Integer -> Integer -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+ warning: 'GHC.Integer.Type.neqInteger#: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.leInteger#+ kind: Declaration+ type: 'leInteger# :: Integer+ -> Integer -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+ warning: 'GHC.Integer.Type.leInteger#: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.gtInteger#+ kind: Declaration+ type: 'gtInteger# :: Integer+ -> Integer -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+ warning: 'GHC.Integer.Type.gtInteger#: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.ltInteger#+ kind: Declaration+ type: 'ltInteger# :: Integer+ -> Integer -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+ warning: 'GHC.Integer.Type.ltInteger#: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.geInteger#+ kind: Declaration+ type: 'geInteger# :: Integer+ -> Integer -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+ warning: 'GHC.Integer.Type.geInteger#: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.shiftRInteger+ kind: Declaration+ type: 'shiftRInteger ::+ Integer -> Int# -> Integer'+ template: |-+ ~GENSYM[~RESULT_shiftR][0] : block+ signal ~GENSYM[sh][1] : natural;+ begin+ ~SYM[1] <=+ -- pragma translate_off+ natural'high when (~VAR[shI][1](~SIZE[~TYP[1]]-1 downto 31) /= 0) else+ -- pragma translate_on+ to_integer(~VAR[shI][1]+ -- pragma translate_off+ (30 downto 0)+ -- pragma translate_on+ );+ ~RESULT <= shift_right(~ARG[0],~SYM[1])+ -- pragma translate_off+ when (~ARG[1] >= 0) else (others => 'X')+ -- pragma translate_on+ ;+ end block;+ warning: 'GHC.Integer.Type.shiftRInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.shiftLInteger+ kind: Declaration+ type: 'shiftLInteger ::+ Integer -> Int# -> Integer'+ template: |-+ ~GENSYM[~RESULT_shiftL][0] : block+ signal ~GENSYM[sh][1] : natural;+ begin+ ~SYM[1] <=+ -- pragma translate_off+ natural'high when (~VAR[shI][1](~SIZE[~TYP[1]]-1 downto 31) /= 0) else+ -- pragma translate_on+ to_integer(~VAR[shI][1]+ -- pragma translate_off+ (30 downto 0)+ -- pragma translate_on+ );+ ~RESULT <= shift_left(~ARG[0],~SYM[1])+ -- pragma translate_off+ when (~ARG[1] >= 0) else (others => 'X')+ -- pragma translate_on+ ;+ end block;+ warning: 'GHC.Integer.Type.shiftLInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.testBitInteger+ kind: Expression+ type: 'testBitInteger+ :: Integer -> Int# -> Bool'+ template: ~VAR[input][0](to_integer(~ARG[1])) = '1'+ warning: 'GHC.Integer.Type.testBitInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.wordToInteger+ kind: Expression+ type: 'wordToInteger ::+ Word# -> Integer'+ template: signed(std_logic_vector(~ARG[0]))+ warning: 'GHC.Integer.Type.wordToInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Integer.Type.integerToWord+ kind: Expression+ type: 'integerToWord ::+ Integer -> Word#'+ template: unsigned(std_logic_vector(~ARG[0]))+ warning: 'GHC.Integer.Type.integerToWord: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Integer.Type.integerToWord64+ comment: only used by 32 bit GHC+ kind: Expression+ type: 'integerToWord ::+ Integer -> Word64#'+ template: unsigned(std_logic_vector(~ARG[0]))+ warning: 'GHC.Integer.Type.integerToWord64: Integers are dynamically sized in+ simulation, but fixed-length after synthesis. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Integer.Type.bitInteger+ kind: Expression+ type: 'bitInteger :: Int+ -> Integer'+ template: shift_left(to_signed(1, ~SIZE[~TYPO]),to_integer(~ARG[0]))+ warning: 'GHC.Integer.Type.bitInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.complementInteger+ kind: Expression+ type: 'complementInteger+ :: Integer -> Integer'+ template: not ~ARG[0]+ warning: 'GHC.Integer.Type.complementInteger: Integers are dynamically sized in+ simulation, but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.xorInteger+ kind: Expression+ type: 'xorInteger :: Integer+ -> Integer -> Integer'+ template: ~ARG[0] xor ~ARG[1]+ warning: 'GHC.Integer.Type.xorInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.orInteger+ kind: Expression+ type: 'orInteger :: Integer+ -> Integer -> Integer'+ template: ~ARG[0] or ~ARG[1]+ warning: 'GHC.Integer.Type.orInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.andInteger+ kind: Expression+ type: 'andInteger :: Integer+ -> Integer -> Integer'+ template: ~ARG[0] and ~ARG[1]+ warning: 'GHC.Integer.Type.andInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.$wsignumInteger+ kind: Declaration+ type: '$wsignumInteger+ :: Integer -> Integer'+ template: |2++ -- begin signumInteger+ ~RESULT <= to_signed(-1, ~SIZE[~TYPO]) when ~ARG[0] < 0+ else to_signed(0, ~SIZE[~TYPO]) when ~ARG[0] = 0+ else to_signed(1, ~SIZE[~TYPO]);+ -- end signumInteger+ warning: 'GHC.Integer.Type.$wsignumInteger: Integers are dynamically sized in+ simulation, but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Integer.Type.quotInteger+ kind: Declaration+ type: 'quotInteger ::+ Integer -> Integer -> Integer'+ template: |-+ ~RESULT <= ~ARG[0] / ~ARG[1]+ -- pragma translate_off+ when (~ARG[1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;+ warning: 'GHC.Integer.Type.quotInteger: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'
− prims/vhdl/GHC_Natural.primitives
@@ -1,32 +0,0 @@-[- {- "BlackBox": {- "name": "GHC.Natural.naturalFromInteger",- "workInfo" : "Never",- "kind": "Expression",- "type": "naturalFromInteger :: Integer -> Natural",- "template": "resize(unsigned(std_logic_vector(~ARG[0])),~SIZE[~TYPO])",- "warning": "GHC.Natural.naturalFromInteger: Naturals are dynamically sized in simulation, but fixed-length after synthesization. Use carefully."- }- },- {- "BlackBox": {- "name": "GHC.Natural.timesNatural",- "workInfo" : "Never",- "kind": "Expression",- "type": "timesNatural :: Natural -> Natural -> Natural",- "template": "resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO])",- "warning": "GHC.Natural.timesNatural: Naturals are dynamically sized in simulation, but fixed-length after synthesization. Use carefully."- }- },- {- "BlackBox": {- "name": "GHC.Natural.wordToNatural#",- "workInfo" : "Never",- "kind": "Expression",- "type": "wordToNatural# :: Word# -> Natural",- "template": "unsigned(std_logic_vector(~ARG[0]))",- "warning": "GHC.Natural.wordToNatural#: Naturals are dynamically sized in simulation, but fixed-length after synthesization. Use carefully."- }- }-]
+ prims/vhdl/GHC_Natural.primitives.yaml view
@@ -0,0 +1,27 @@+- BlackBox:+ name: GHC.Natural.naturalFromInteger+ kind: Expression+ type: 'naturalFromInteger+ :: Integer -> Natural'+ template: resize(unsigned(std_logic_vector(~ARG[0])),~SIZE[~TYPO])+ warning: 'GHC.Natural.naturalFromInteger: Naturals are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Natural.timesNatural+ kind: Expression+ type: 'timesNatural ::+ Natural -> Natural -> Natural'+ template: resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO])+ warning: 'GHC.Natural.timesNatural: Naturals are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Natural.wordToNatural#+ kind: Expression+ type: 'wordToNatural#+ :: Word# -> Natural'+ template: unsigned(std_logic_vector(~ARG[0]))+ warning: 'GHC.Natural.wordToNatural#: Naturals are dynamically sized in simulation,+ but fixed-length after synthesization. Use carefully.'+ workInfo: Never
− prims/vhdl/GHC_Num_Integer.primitives
@@ -1,327 +0,0 @@-[ { "BlackBox":- { "name": "GHC.Num.Integer.integerToNatural"- , "workInfo" : "Never"- , "kind": "Expression"- , "type": "integerToNatural :: Integer -> Natural"- , "template": "resize(unsigned(std_logic_vector(~ARG[0])),~SIZE[~TYPO])"- , "warning": "GHC.Num.Integer.integerToNatural: Naturals are dynamically sized in simulation, but fixed-length after synthesis. Use carefully."- }- }- , { "BlackBox":- { "name": "GHC.Num.Integer.integerToNaturalThrow"- , "workInfo" : "Never"- , "kind": "Declaration"- , "type": "integerToNaturalThrow :: Integer -> Natural"- , "template":-"-- integerToNaturalThrow begin-~RESULT <= ~ERRORO when ~ARG[0] < ~SIZE[~TYP[0]]'d0 else- resize(unsigned(std_logic_vector(~ARG[0])),~SIZE[~TYPO]);--- integerToNaturalThrow end"- , "warning": "GHC.Num.Integer.integerToNaturalThrow: Naturals are dynamically sized in simulation, but fixed-length after synthesis. Use carefully."- }- }-, { "BlackBox":- { "name": "GHC.Num.Integer.integerToNaturalClamp"- , "workInfo" : "Never"- , "kind": "Declaration"- , "type": "integerToNatural :: Integer -> Natural"- , "template":-"-- integerToNaturalClamp begin-~RESULT <= to_unsigned(0,~SIZE[~TYPO]]) when ~ARG[0] < ~SIZE[~TYP[0]]'d0 else- resize(unsigned(std_logic_vector(~ARG[0])),~SIZE[~TYPO]);--- integerToNaturalClamp end"- , "warning": "GHC.Num.Integer.integerToNaturalClamp: Naturals are dynamically sized in simulation, but fixed-length after synthesis. Use carefully."- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerToInt#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "integerToInt :: Integer -> Int#"- , "template" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerMul"- , "kind" : "Expression"- , "type" : "integerMul :: Integer -> Integer -> Integer"- , "template" : "resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO])"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerNegate"- , "kind" : "Expression"- , "type" : "integerNegate :: Integer -> Integer"- , "template" : "-~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerAbs"- , "kind" : "Expression"- , "type" : "integerAbs :: Integer -> Integer"- , "template" : "abs ~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerDiv"- , "kind" : "Declaration"- , "type" : "integerDiv :: Integer -> Integer -> Integer"- , "template" :-"-- integerDiv begin-~GENSYM[integerDiv][0] : block- signal ~GENSYM[resultPos][1] : boolean;- signal ~GENSYM[dividerNeg][2] : boolean;- signal ~GENSYM[dividend2][3] : signed(~SIZE[~TYPO] downto 0);- signal ~GENSYM[quot_res][4] : signed(~SIZE[~TYPO] downto 0);-begin- ~SYM[1] <= ~VAR[dividend][0](~VAR[dividend][0]'high) = ~VAR[divider][1](~VAR[divider][1]'high);- ~SYM[2] <= ~VAR[divider][1](~VAR[divider][1]'high) = '1';- ~SYM[3] <= resize(~VAR[dividend][0],~SIZE[~TYPO]+1) when ~SYM[1] else- (resize(~VAR[dividend][0],~SIZE[~TYPO]+1) - resize(~VAR[divider][1],~SIZE[~TYPO]+1) - 1) when ~SYM[2] else- (resize(~VAR[dividend][0],~SIZE[~TYPO]+1) - resize(~VAR[divider][1],~SIZE[~TYPO]+1) + 1);- ~SYM[4] <= ~SYM[3] / ~VAR[divider][1];- ~RESULT <= signed(~SYM[4](~SIZE[~TYPO]-1 downto 0));-end block;--- integerDiv end"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerMod"- , "kind" : "Expression"- , "type" : "integerMod :: Integer -> Integer -> Integer"- , "template" : "~ARG[0] mod ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerDivMod#"- , "kind" : "Declaration"- , "type" : "integerDivMod :: Integer -> Integer -> (# Integer, Integer #)"- , "template" :-"-- integerDivMod begin-~GENSYM[integerDivMod][0] : block- signal ~GENSYM[resultPos][1] : boolean;- signal ~GENSYM[dividerNeg][2] : boolean;- signal ~GENSYM[dividend2][3] : signed(~SIZE[~TYP[0]] downto 0);- signal ~GENSYM[quot_res][4] : signed(~SIZE[~TYP[0]] downto 0);- signal ~GENSYM[div_res][5] : signed(~SIZE[~TYP[0]]-1 downto 0);-begin- ~SYM[1] <= ~VAR[dividend][0](~VAR[dividend][0]'high) = ~VAR[divider][1](~VAR[divider][1]'high);- ~SYM[2] <= ~VAR[divider][1](~VAR[divider][1]'high) = '1';- ~SYM[3] <= resize(~VAR[dividend][0],~SIZE[~TYP[0]]+1) when ~SYM[1] else- (resize(~VAR[dividend][0],~SIZE[~TYP[0]]+1) - resize(~VAR[divider][1],~SIZE[~TYP[0]]+1) - 1) when ~SYM[2] else- (resize(~VAR[dividend][0],~SIZE[~TYP[0]]+1) - resize(~VAR[divider][1],~SIZE[~TYP[0]]+1) + 1);- ~SYM[4] <= ~SYM[3] / ~VAR[divider][1];- ~SYM[5] <= signed(~SYM[4](~SIZE[~TYP[0]]-1 downto 0));- ~RESULT <= (~SYM[5], ~VAR[dividend][0] mod ~VAR[divider][1]);-end block;--- integerDivMod end"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerQuotRem#"- , "kind" : "Expression"- , "type" : "integerQuotRem :: Integer -> Integer -> (# Integer, Integer #)"- , "template" : "(~ARG[0] / ~ARG[1], ~ARG[0] rem ~ARG[1])"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerRem"- , "kind" : "Expression"- , "type" : "integerRem :: Integer -> Integer -> Integer"- , "template" : "~ARG[0] rem ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerEq"- , "kind" : "Expression"- , "type" : "integerEq :: Integer -> Integer -> Bool"- , "template" : "~ARG[0] = ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerNe"- , "kind" : "Expression"- , "type" : "integerNe :: Integer -> Integer -> Bool"- , "template" : "~ARG[0] /= ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerEq#"- , "kind" : "Declaration"- , "type" : "integerEq# :: Integer -> Integer -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerNe#"- , "kind" : "Declaration"- , "type" : "integerNe# :: Integer -> Integer -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerLe#"- , "kind" : "Declaration"- , "type" : "integerLe# :: Integer -> Integer -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerGt#"- , "kind" : "Declaration"- , "type" : "integerGt# :: Integer -> Integer -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerLt#"- , "kind" : "Declaration"- , "type" : "integerLt# :: Integer -> Integer -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerGe#"- , "kind" : "Declaration"- , "type" : "integerGe# :: Integer -> Integer -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerShiftR#"- , "kind" : "Declaration"- , "type" : "integerShiftR# :: Integer -> Word# -> Integer"- , "template" :-"~RESULT <= shift_right(~ARG[0], to_integer(~VAR[count][1](30 downto 0)))- -- pragma translate_off- when (~ARG[1] >= 0) else (others => 'X')- -- pragma translate_on- ;"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerShiftL#"- , "kind" : "Declaration"- , "type" : "integerShiftL# :: Integer -> Word# -> Integer"- , "template" :-"~RESULT <= shift_left(~ARG[0], to_integer(~VAR[count][1](30 downto 0)))- -- pragma translate_off- when (~ARG[1] >= 0) else (others => 'X')- -- pragma translate_on- ;"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerTestBit#"- , "kind" : "Expression"- , "type" : "integerTestBit :: Integer -> Word# -> Bool"- , "template" : "~VAR[input][0](to_integer(~ARG[1])) = '1'"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerFromWord#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "integerFromWord :: Word# -> Integer"- , "template" : "signed(std_logic_vector(~ARG[0]))"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerToWord#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "integerToWord :: Integer -> Word#"- , "template" : "unsigned(std_logic_vector(~ARG[0]))"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerToWord64#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "integerToWord :: Integer -> Word64#"- , "comment" : "only used by 32 bit GHC"- , "template" : "unsigned(std_logic_vector(~ARG[0]))"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerBit#"- , "kind" : "Expression"- , "type" : "integerBit :: Word# -> Integer"- , "template" : "shift_left(to_signed(1, ~SIZE[~TYPO]),to_integer(~ARG[0]))"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerComplement"- , "kind" : "Expression"- , "type" : "integerComplement :: Integer -> Integer"- , "template" : "not ~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerXor"- , "kind" : "Expression"- , "type" : "integerXor :: Integer -> Integer -> Integer"- , "template" : "~ARG[0] xor ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerOr"- , "kind" : "Expression"- , "type" : "integerOr :: Integer -> Integer -> Integer"- , "template" : "~ARG[0] or ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerAnd"- , "kind" : "Expression"- , "type" : "integerAnd :: Integer -> Integer -> Integer"- , "template" : "~ARG[0] and ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerSigmum"- , "kind" : "Declaration"- , "type" : "integerSigmum :: Integer -> Integer"- , "template" : "--- begin integerSigmum-~RESULT <= to_signed(-1, ~SIZE[~TYPO]) when ~ARG[0] < 0- else to_signed(0, ~SIZE[~TYPO]) when ~ARG[0] = 0- else to_signed(1, ~SIZE[~TYPO]);--- end integerSigmum-"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.$wintegerSignum"- , "kind" : "Declaration"- , "type" : "$wsignumInteger :: Integer -> Int#"- , "template" : "--- begin signumInteger-~RESULT <= to_signed(-1, ~SIZE[~TYPO]) when ~ARG[0] < 0- else to_signed(0, ~SIZE[~TYPO]) when ~ARG[0] = 0- else to_signed(1, ~SIZE[~TYPO]);--- end signumInteger-"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerLogBase#"- , "kind" : "Expression"- , "type" : "integerLogBase# :: Integer -> Integer -> Int#"- , "template" : "integer(floor(log(real(~ARG[1]),real(~ARG[0]))))"- }-}-, { "BlackBox" :- { "name" : "GHC.Num.Integer.integerCompare"- , "kind" : "Declaration"- , "type" : "integerCompare :: Integer -> Integer -> Ordering"- , "template" : "--- begin integerCompare-~RESULT <= \"00\" when ~ARG[0] < ~ARG[1] else- \"01\" when ~ARG[0] = ~ARG[1] else- \"10\";--- end integerCompare-"- }- }-]
+ prims/vhdl/GHC_Num_Integer.primitives.yaml view
@@ -0,0 +1,413 @@+- BlackBox:+ name: GHC.Num.Integer.integerToNatural+ kind: Expression+ type: 'integerToNatural+ :: Integer -> Natural'+ template: resize(unsigned(std_logic_vector(~ARG[0])),~SIZE[~TYPO])+ warning: 'GHC.Num.Integer.integerToNatural: Naturals are dynamically sized in+ simulation, but fixed-length after synthesis. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Num.Integer.integerToNaturalThrow+ kind: Declaration+ type: 'integerToNaturalThrow+ :: Integer -> Natural'+ template: |-+ -- integerToNaturalThrow begin+ ~RESULT <= ~ERRORO when ~ARG[0] < ~SIZE[~TYP[0]]'d0 else+ resize(unsigned(std_logic_vector(~ARG[0])),~SIZE[~TYPO]);+ -- integerToNaturalThrow end+ warning: 'GHC.Num.Integer.integerToNaturalThrow: Naturals are dynamically sized+ in simulation, but fixed-length after synthesis. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Num.Integer.integerToNaturalClamp+ kind: Declaration+ type: 'integerToNatural+ :: Integer -> Natural'+ template: |-+ -- integerToNaturalClamp begin+ ~RESULT <= to_unsigned(0,~SIZE[~TYPO]]) when ~ARG[0] < ~SIZE[~TYP[0]]'d0 else+ resize(unsigned(std_logic_vector(~ARG[0])),~SIZE[~TYPO]);+ -- integerToNaturalClamp end+ warning: 'GHC.Num.Integer.integerToNaturalClamp: Naturals are dynamically sized+ in simulation, but fixed-length after synthesis. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Num.Integer.integerToInt#+ kind: Expression+ type: 'integerToInt ::+ Integer -> Int#'+ template: ~ARG[0]+ warning: 'GHC.Num.Integer.integerToInt#: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Num.Integer.integerMul+ kind: Expression+ type: 'integerMul :: Integer+ -> Integer -> Integer'+ template: resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO])+ warning: 'GHC.Num.Integer.integerMul: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerNegate+ kind: Expression+ type: 'integerNegate ::+ Integer -> Integer'+ template: -~ARG[0]+ warning: 'GHC.Num.Integer.integerNegate: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerAbs+ kind: Expression+ type: 'integerAbs :: Integer+ -> Integer'+ template: abs ~ARG[0]+ warning: 'GHC.Num.Integer.integerAbs: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerDiv+ kind: Declaration+ type: 'integerDiv :: Integer+ -> Integer -> Integer'+ template: |-+ -- integerDiv begin+ ~GENSYM[integerDiv][0] : block+ signal ~GENSYM[resultPos][1] : boolean;+ signal ~GENSYM[dividerNeg][2] : boolean;+ signal ~GENSYM[dividend2][3] : signed(~SIZE[~TYPO] downto 0);+ signal ~GENSYM[quot_res][4] : signed(~SIZE[~TYPO] downto 0);+ begin+ ~SYM[1] <= ~VAR[dividend][0](~VAR[dividend][0]'high) = ~VAR[divider][1](~VAR[divider][1]'high);+ ~SYM[2] <= ~VAR[divider][1](~VAR[divider][1]'high) = '1';+ ~SYM[3] <= resize(~VAR[dividend][0],~SIZE[~TYPO]+1) when ~SYM[1] else+ (resize(~VAR[dividend][0],~SIZE[~TYPO]+1) - resize(~VAR[divider][1],~SIZE[~TYPO]+1) - 1) when ~SYM[2] else+ (resize(~VAR[dividend][0],~SIZE[~TYPO]+1) - resize(~VAR[divider][1],~SIZE[~TYPO]+1) + 1);+ ~SYM[4] <= ~SYM[3] / ~VAR[divider][1]+ -- pragma translate_off+ when (~VAR[divider][1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;+ ~RESULT <= signed(~SYM[4](~SIZE[~TYPO]-1 downto 0));+ end block;+ -- integerDiv end+ warning: 'GHC.Num.Integer.integerDiv: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerMod+ kind: Expression+ type: 'integerMod :: Integer+ -> Integer -> Integer'+ template: ~ARG[0] mod ~ARG[1]+ warning: 'GHC.Num.Integer.integerMod: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerDivMod#+ kind: Declaration+ type: 'integerDivMod ::+ Integer -> Integer -> (# Integer, Integer #)'+ template: |-+ -- integerDivMod begin+ ~GENSYM[integerDivMod][0] : block+ signal ~GENSYM[resultPos][1] : boolean;+ signal ~GENSYM[dividerNeg][2] : boolean;+ signal ~GENSYM[dividend2][3] : signed(~SIZE[~TYP[0]] downto 0);+ signal ~GENSYM[quot_res][4] : signed(~SIZE[~TYP[0]] downto 0);+ signal ~GENSYM[div_res][5] : signed(~SIZE[~TYP[0]]-1 downto 0);+ signal ~GENSYM[mod_res][6] : signed(~SIZE[~TYP[0]]-1 downto 0);+ begin+ ~SYM[1] <= ~VAR[dividend][0](~VAR[dividend][0]'high) = ~VAR[divider][1](~VAR[divider][1]'high);+ ~SYM[2] <= ~VAR[divider][1](~VAR[divider][1]'high) = '1';+ ~SYM[3] <= resize(~VAR[dividend][0],~SIZE[~TYP[0]]+1) when ~SYM[1] else+ (resize(~VAR[dividend][0],~SIZE[~TYP[0]]+1) - resize(~VAR[divider][1],~SIZE[~TYP[0]]+1) - 1) when ~SYM[2] else+ (resize(~VAR[dividend][0],~SIZE[~TYP[0]]+1) - resize(~VAR[divider][1],~SIZE[~TYP[0]]+1) + 1);+ ~SYM[4] <= ~SYM[3] / ~VAR[divider][1]+ -- pragma translate_off+ when (~VAR[divider][1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;+ ~SYM[5] <= signed(~SYM[4](~SIZE[~TYP[0]]-1 downto 0));+ ~SYM[6] <= ~VAR[dividend][0] mod ~VAR[divider][1]+ -- pragma translate_off+ when (~VAR[divider][1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;+ ~RESULT <= (~SYM[5], ~SYM[6]);+ end block;+ -- integerDivMod end+ warning: 'GHC.Num.Integer.integerDivMod#: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerQuotRem#+ kind: Declaration+ type: 'integerQuotRem+ :: Integer -> Integer -> (# Integer, Integer #)'+ template: |-+ ~RESULT <= (~ARG[0] / ~ARG[1], ~ARG[0] rem ~ARG[1])+ -- pragma translate_off+ when (~ARG[1] /= 0) else ((others => 'X'), (others => 'X'))+ -- pragma translate_on+ ;+ warning: 'GHC.Num.Integer.integerQuotRem#: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerRem+ kind: Declaration+ type: 'integerRem :: Integer+ -> Integer -> Integer'+ template: |-+ ~RESULT <= ~ARG[0] rem ~ARG[1]+ -- pragma translate_off+ when (~ARG[1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;+ warning: 'GHC.Num.Integer.integerRem: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerEq+ kind: Expression+ type: 'integerEq :: Integer+ -> Integer -> Bool'+ template: ~ARG[0] = ~ARG[1]+ warning: 'GHC.Num.Integer.integerEq: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerNe+ kind: Expression+ type: 'integerNe :: Integer+ -> Integer -> Bool'+ template: ~ARG[0] /= ~ARG[1]+ warning: 'GHC.Num.Integer.integerNe: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerEq#+ kind: Declaration+ type: 'integerEq# :: Integer+ -> Integer -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+ warning: 'GHC.Num.Integer.integerEq#: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerNe#+ kind: Declaration+ type: 'integerNe# :: Integer+ -> Integer -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+ warning: 'GHC.Num.Integer.integerNe#: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerLe#+ kind: Declaration+ type: 'integerLe# :: Integer+ -> Integer -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+ warning: 'GHC.Num.Integer.integerLe#: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerGt#+ kind: Declaration+ type: 'integerGt# :: Integer+ -> Integer -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+ warning: 'GHC.Num.Integer.integerGt#: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerLt#+ kind: Declaration+ type: 'integerLt# :: Integer+ -> Integer -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+ warning: 'GHC.Num.Integer.integerLt#: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerGe#+ kind: Declaration+ type: 'integerGe# :: Integer+ -> Integer -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+ warning: 'GHC.Num.Integer.integerGe#: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerShiftR#+ kind: Declaration+ type: 'integerShiftR#+ :: Integer -> Word# -> Integer'+ template: |-+ ~GENSYM[~RESULT_shiftR][0] : block+ signal ~GENSYM[sh][1] : natural;+ begin+ ~SYM[1] <=+ -- pragma translate_off+ natural'high when (~VAR[shI][1](~SIZE[~TYP[1]]-1 downto 31) /= 0) else+ -- pragma translate_on+ to_integer(~VAR[shI][1]+ -- pragma translate_off+ (30 downto 0)+ -- pragma translate_on+ );+ ~RESULT <= shift_right(~ARG[0],~SYM[1]);+ end block;+ warning: 'GHC.Num.Integer.integerShiftR#: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerShiftL#+ kind: Declaration+ type: 'integerShiftL#+ :: Integer -> Word# -> Integer'+ template: |-+ ~GENSYM[~RESULT_shiftL][0] : block+ signal ~GENSYM[sh][1] : natural;+ begin+ ~SYM[1] <=+ -- pragma translate_off+ natural'high when (~VAR[shI][1](~SIZE[~TYP[1]]-1 downto 31) /= 0) else+ -- pragma translate_on+ to_integer(~VAR[shI][1]+ -- pragma translate_off+ (30 downto 0)+ -- pragma translate_on+ );+ ~RESULT <= shift_left(~ARG[0],~SYM[1]);+ end block;+ warning: 'GHC.Num.Integer.integerShiftL#: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerTestBit#+ kind: Expression+ type: 'integerTestBit+ :: Integer -> Word# -> Bool'+ template: ~VAR[input][0](to_integer(~ARG[1])) = '1'+ warning: 'GHC.Num.Integer.integerTestBit#: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerFromWord#+ kind: Expression+ type: 'integerFromWord+ :: Word# -> Integer'+ template: signed(std_logic_vector(~ARG[0]))+ warning: 'GHC.Num.Integer.integerFromWord#: Integers are dynamically sized in+ simulation, but fixed-length after synthesis. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Num.Integer.integerToWord#+ kind: Expression+ type: 'integerToWord ::+ Integer -> Word#'+ template: unsigned(std_logic_vector(~ARG[0]))+ warning: 'GHC.Num.Integer.integerToWord#: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Num.Integer.integerToWord64#+ comment: only used by 32 bit GHC+ kind: Expression+ type: 'integerToWord ::+ Integer -> Word64#'+ template: unsigned(std_logic_vector(~ARG[0]))+ warning: 'GHC.Num.Integer.integerToWord64#: Integers are dynamically sized in+ simulation, but fixed-length after synthesis. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Num.Integer.integerBit#+ kind: Expression+ type: 'integerBit :: Word#+ -> Integer'+ template: shift_left(to_signed(1, ~SIZE[~TYPO]),to_integer(~ARG[0]))+ warning: 'GHC.Num.Integer.integerBit#: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerComplement+ kind: Expression+ type: 'integerComplement+ :: Integer -> Integer'+ template: not ~ARG[0]+ warning: 'GHC.Num.Integer.integerComplement: Integers are dynamically sized in+ simulation, but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerXor+ kind: Expression+ type: 'integerXor :: Integer+ -> Integer -> Integer'+ template: ~ARG[0] xor ~ARG[1]+ warning: 'GHC.Num.Integer.integerXor: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerOr+ kind: Expression+ type: 'integerOr :: Integer+ -> Integer -> Integer'+ template: ~ARG[0] or ~ARG[1]+ warning: 'GHC.Num.Integer.integerOr: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerAnd+ kind: Expression+ type: 'integerAnd :: Integer+ -> Integer -> Integer'+ template: ~ARG[0] and ~ARG[1]+ warning: 'GHC.Num.Integer.integerAnd: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerSigmum+ kind: Declaration+ type: 'integerSigmum ::+ Integer -> Integer'+ template: |2++ -- begin integerSigmum+ ~RESULT <= to_signed(-1, ~SIZE[~TYPO]) when ~ARG[0] < 0+ else to_signed(0, ~SIZE[~TYPO]) when ~ARG[0] = 0+ else to_signed(1, ~SIZE[~TYPO]);+ -- end integerSigmum+ warning: 'GHC.Num.Integer.integerSignum: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.$wintegerSignum+ kind: Declaration+ type: '$wsignumInteger+ :: Integer -> Int#'+ template: |2++ -- begin signumInteger+ ~RESULT <= to_signed(-1, ~SIZE[~TYPO]) when ~ARG[0] < 0+ else to_signed(0, ~SIZE[~TYPO]) when ~ARG[0] = 0+ else to_signed(1, ~SIZE[~TYPO]);+ -- end signumInteger+ warning: 'GHC.Num.Integer.$wintegerSignum: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerLogBase#+ kind: Expression+ type: 'integerLogBase#+ :: Integer -> Integer -> Int#'+ template: integer(floor(log(real(~ARG[1]),real(~ARG[0]))))+ warning: 'GHC.Num.Integer.integerLogBase#: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerCompare+ kind: Declaration+ type: 'integerCompare+ :: Integer -> Integer -> Ordering'+ template: |2++ -- begin integerCompare+ ~RESULT <= "00" when ~ARG[0] < ~ARG[1] else+ "01" when ~ARG[0] = ~ARG[1] else+ "10";+ -- end integerCompare+ warning: 'GHC.Num.Integer.integerCompare: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Integer.integerQuot+ kind: Declaration+ type: 'integerQuot ::+ Integer -> Integer -> Integer'+ template: |-+ ~RESULT <= ~ARG[0] / ~ARG[1]+ -- pragma translate_off+ when (~ARG[1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;+ warning: 'GHC.Num.Integer.integerQuot: Integers are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'
− prims/vhdl/GHC_Num_Natural.primitives
@@ -1,114 +0,0 @@-[- {- "BlackBox": {- "name": "GHC.Num.Natural.naturalMul",- "kind": "Expression",- "type": "timesNatural :: Natural -> Natural -> Natural",- "template": "resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO])",- "warning": "GHC.Num.Natural.timesNatural: Naturals are dynamically sized in simulation, but fixed-length after synthesis. Use carefully."- }- },- {- "BlackBox": {- "name": "GHC.Num.Natural.naturalFromWord#",- "workInfo" : "Never",- "kind": "Expression",- "type": "naturalFromWord# :: Word# -> Natural",- "template": "unsigned(std_logic_vector(~ARG[0]))",- "warning": "GHC.Num.Natural.naturalFromWord#: Naturals are dynamically sized in simulation, but fixed-length after synthesis. Use carefully."- }- }- , { "BlackBox" :- { "name" : "GHC.Num.Natural.naturalRem"- , "kind" : "Expression"- , "type" : "naturalRem :: Natural -> Natural -> Natural"- , "template" : "~ARG[0] rem ~ARG[1]"- , "warning": "GHC.Num.Natural.naturalRem: Naturals are dynamically sized in simulation, but fixed-length after synthesis. Use carefully."- }- }- , { "BlackBox" :- { "name" : "GHC.Num.Natural.naturalLogBase#"- , "kind" : "Expression"- , "type" : "naturalLogBase# :: Natural -> Natural -> Word#"- , "template" : "to_unsigned(integer(floor(log(real(to_integer(~ARG[1])),real(to_integer(~ARG[0]))))),~SIZE[~TYPO])"- }- }-, { "BlackBox" :- { "name" : "GHC.Num.Natural.naturalEq#"- , "kind" : "Declaration"- , "type" : "naturalEq# :: Natural -> Natural -> Int#"- , "template" : "~RESULT <= to_unsigned(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_unsigned(0,~SIZE[~TYPO]);"- }-}-, { "BlackBox" :- { "name" : "GHC.Num.Natural.naturalNe#"- , "kind" : "Declaration"- , "type" : "naturalNe# :: Natural -> Natural -> Int#"- , "template" : "~RESULT <= to_unsigned(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else to_unsigned(0,~SIZE[~TYPO]);"- }-}-, { "BlackBox" :- { "name" : "GHC.Num.Natural.naturalLe#"- , "kind" : "Declaration"- , "type" : "naturalLe# :: Natural -> Natural -> Int#"- , "template" : "~RESULT <= to_unsigned(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else to_unsigned(0,~SIZE[~TYPO]);"- }-}-, { "BlackBox" :- { "name" : "GHC.Num.Natural.naturalGt#"- , "kind" : "Declaration"- , "type" : "naturalGt# :: Natural -> Natural -> Int#"- , "template" : "~RESULT <= to_unsigned(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_unsigned(0,~SIZE[~TYPO]);"- }-}-, { "BlackBox" :- { "name" : "GHC.Num.Natural.naturalLt#"- , "kind" : "Declaration"- , "type" : "naturalLt# :: Natural -> Natural -> Int#"- , "template" : "~RESULT <= to_unsigned(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_unsigned(0,~SIZE[~TYPO]);"- }-}-, { "BlackBox" :- { "name" : "GHC.Num.Natural.naturalGe#"- , "kind" : "Declaration"- , "type" : "naturalGe# :: Natural -> Natural -> Int#"- , "template" : "~RESULT <= to_unsigned(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else to_unsigned(0,~SIZE[~TYPO]);"- }-}-, { "BlackBox" :- { "name" : "GHC.Num.Natural.naturalShiftL#"- , "kind" : "Declaration"- , "type" : "naturalShiftL# :: Natural -> Word# -> Natural"- , "template" :-"~RESULT <= shift_left(~ARG[0],to_integer(~VAR[count][1](30 downto 0)))- -- pragma translate_off- when (~ARG[1] >= to_unsigned(0, ~SIZE[~TYP[1]]-1)) else (others => 'X')- -- pragma translate_on- ;"- }-}-, { "BlackBox" :- { "name" : "GHC.Num.Natural.naturalShiftR#"- , "kind" : "Declaration"- , "type" : "naturalShiftR# :: Natural -> Word# -> Natural"- , "template" :-"~RESULT <= shift_right(~ARG[0], to_integer(~VAR[count][1](30 downto 0)))- -- pragma translate_off- when (~ARG[1] >= to_unsigned(0, ~SIZE[~TYP[1]]-1)) else (others => 'X')- -- pragma translate_on- ;"- }-}-, { "BlackBox" :- { "name" : "GHC.Num.Natural.naturalCompare"- , "kind" : "Declaration"- , "type" : "naturalCompare :: Natural -> Natural -> Ordering"- , "template" :-"-- begin naturalCompare-~RESULT <= \"00\" when ~ARG[0] < ~ARG[1] else- \"01\" when ~ARG[0] = ~ARG[1] else- \"10\";--- end naturalCompare"- }-}-]
+ prims/vhdl/GHC_Num_Natural.primitives.yaml view
@@ -0,0 +1,157 @@+- BlackBox:+ name: GHC.Num.Natural.naturalMul+ kind: Expression+ type: 'timesNatural ::+ Natural -> Natural -> Natural'+ template: resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO])+ warning: 'GHC.Num.Natural.timesNatural: Naturals are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Natural.naturalFromWord#+ kind: Expression+ type: 'naturalFromWord#+ :: Word# -> Natural'+ template: unsigned(std_logic_vector(~ARG[0]))+ warning: 'GHC.Num.Natural.naturalFromWord#: Naturals are dynamically sized in+ simulation, but fixed-length after synthesis. Use carefully.'+ workInfo: Never+- BlackBox:+ name: GHC.Num.Natural.naturalRem+ kind: Declaration+ type: 'naturalRem :: Natural+ -> Natural -> Natural'+ template: |-+ ~RESULT <= ~ARG[0] rem ~ARG[1]+ -- pragma translate_off+ when (~ARG[1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;+ warning: 'GHC.Num.Natural.naturalRem: Naturals are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Natural.naturalLogBase#+ kind: Expression+ type: 'naturalLogBase#+ :: Natural -> Natural -> Word#'+ template: to_unsigned(integer(floor(log(real(to_integer(~ARG[1])),real(to_integer(~ARG[0]))))),~SIZE[~TYPO])+ warning: 'GHC.Num.Natural.naturalLogBase#: Naturals are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Natural.naturalEq#+ kind: Declaration+ type: 'naturalEq# :: Natural+ -> Natural -> Int#'+ template: ~RESULT <= to_unsigned(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_unsigned(0,~SIZE[~TYPO]);+ warning: 'GHC.Num.Natural.naturalEq#: Naturals are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Natural.naturalNe#+ kind: Declaration+ type: 'naturalNe# :: Natural+ -> Natural -> Int#'+ template: ~RESULT <= to_unsigned(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else+ to_unsigned(0,~SIZE[~TYPO]);+ warning: 'GHC.Num.Natural.naturalNe#: Naturals are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Natural.naturalLe#+ kind: Declaration+ type: 'naturalLe# :: Natural+ -> Natural -> Int#'+ template: ~RESULT <= to_unsigned(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else+ to_unsigned(0,~SIZE[~TYPO]);+ warning: 'GHC.Num.Natural.naturalLe#: Naturals are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Natural.naturalGt#+ kind: Declaration+ type: 'naturalGt# :: Natural+ -> Natural -> Int#'+ template: ~RESULT <= to_unsigned(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_unsigned(0,~SIZE[~TYPO]);+ warning: 'GHC.Num.Natural.naturalGt#: Naturals are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Natural.naturalLt#+ kind: Declaration+ type: 'naturalLt# :: Natural+ -> Natural -> Int#'+ template: ~RESULT <= to_unsigned(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_unsigned(0,~SIZE[~TYPO]);+ warning: 'GHC.Num.Natural.naturalLt#: Naturals are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Natural.naturalGe#+ kind: Declaration+ type: 'naturalGe# :: Natural+ -> Natural -> Int#'+ template: ~RESULT <= to_unsigned(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else+ to_unsigned(0,~SIZE[~TYPO]);+ warning: 'GHC.Num.Natural.naturalGe#: Naturals are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Natural.naturalShiftL#+ kind: Declaration+ type: 'naturalShiftL#+ :: Natural -> Word# -> Natural'+ template: |-+ ~GENSYM[~RESULT_shiftL][0] : block+ signal ~GENSYM[sh][1] : natural;+ begin+ ~SYM[1] <=+ -- pragma translate_off+ natural'high when (~VAR[shI][1](~SIZE[~TYP[1]]-1 downto 31) /= 0) else+ -- pragma translate_on+ to_integer(~VAR[shI][1]+ -- pragma translate_off+ (30 downto 0)+ -- pragma translate_on+ );+ ~RESULT <= shift_left(~ARG[0],~SYM[1]);+ end block;+ warning: 'GHC.Num.Natural.naturalShiftL#: Naturals are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Natural.naturalShiftR#+ kind: Declaration+ type: 'naturalShiftR#+ :: Natural -> Word# -> Natural'+ template: |-+ ~GENSYM[~RESULT_shiftR][0] : block+ signal ~GENSYM[sh][1] : natural;+ begin+ ~SYM[1] <=+ -- pragma translate_off+ natural'high when (~VAR[shI][1](~SIZE[~TYP[1]]-1 downto 31) /= 0) else+ -- pragma translate_on+ to_integer(~VAR[shI][1]+ -- pragma translate_off+ (30 downto 0)+ -- pragma translate_on+ );+ ~RESULT <= shift_right(~ARG[0],~SYM[1]);+ end block;+ warning: 'GHC.Num.Natural.naturalShiftR#: Naturals are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'+- BlackBox:+ name: GHC.Num.Natural.naturalCompare+ kind: Declaration+ type: 'naturalCompare+ :: Natural -> Natural -> Ordering'+ template: |-+ -- begin naturalCompare+ ~RESULT <= "00" when ~ARG[0] < ~ARG[1] else+ "01" when ~ARG[0] = ~ARG[1] else+ "10";+ -- end naturalCompare+- BlackBox:+ name: GHC.Num.Natural.naturalQuot+ kind: Declaration+ type: 'naturalQuot ::+ Natural -> Natural -> Natural'+ template: |-+ ~RESULT <= ~ARG[0] / ~ARG[1]+ -- pragma translate_off+ when (~ARG[1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;+ warning: 'GHC.Num.Natural.naturalQuot: Naturals are dynamically sized in simulation,+ but fixed-length after synthesis. Use carefully.'
− prims/vhdl/GHC_Prim.primitives
@@ -1,1238 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Prim.gtChar#"- , "kind" : "Declaration"- , "type" : "gtChar# :: Char# -> Char# -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.geChar#"- , "kind" : "Declaration"- , "type" : "geChar# :: Char# -> Char# -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.eqChar#"- , "kind" : "Declaration"- , "type" : "eqChar# :: Char# -> Char# -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.neChar#"- , "kind" : "Declaration"- , "type" : "neChar# :: Char# -> Char# -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ltChar#"- , "kind" : "Declaration"- , "type" : "ltChar# :: Char# -> Char# -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.leChar#"- , "kind" : "Declaration"- , "type" : "leChar# :: Char# -> Char# -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ord#"- , "kind" : "Expression"- , "type" : "ord# :: Char# -> Int#"- , "template" : "signed(std_logic_vector(resize(~ARG[0],~SIZE[~TYPO])))"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.*#"- , "kind" : "Expression"- , "type" : "(*#) :: Int# -> Int# -> Int#"- , "template" : "resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO])"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.remInt#"- , "kind" : "Expression"- , "type" : "remInt# :: Int# -> Int# -> Int#"- , "template" : "~ARG[0] rem ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.quotRemInt#"- , "kind" : "Expression"- , "type" : "quotRemInt# :: Int# -> Int# -> (#Int#, Int##)"- , "template" : "(~ARG[0] / ~ARG[1], ~ARG[0] rem ~ARG[1])"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.andI#"- , "kind" : "Expression"- , "type" : "and# :: Int# -> Int# -> Int#"- , "template" : "~ARG[0] and ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.orI#"- , "kind" : "Expression"- , "type" : "or# :: Int# -> Int# -> Int#"- , "template" : "~ARG[0] or ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.xorI#"- , "kind" : "Expression"- , "type" : "xor# :: Int# -> Int# -> Int#"- , "template" : "~ARG[0] xor ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.notI#"- , "kind" : "Expression"- , "type" : "not# :: Int# -> Int#"- , "template" : "not ~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.negateInt#"- , "kind" : "Expression"- , "type" : "negateInt# :: Int# -> Int#"- , "template" : "-~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.>#"- , "kind" : "Declaration"- , "type" : "(>#) :: Int# -> Int# -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.>=#"- , "kind" : "Declaration"- , "type" : "(>=#) :: Int# -> Int# -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.==#"- , "kind" : "Declaration"- , "type" : "(==) :: Int# -> Int# -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim./=#"- , "kind" : "Declaration"- , "type" : "(/=#) :: Int# -> Int# -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.<#"- , "kind" : "Declaration"- , "type" : "(<#) :: Int# -> Int# -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.<=#"- , "kind" : "Declaration"- , "type" : "(<=#) :: Int# -> Int# -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.chr#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "ord# :: Int# -> Chr#"- , "template" : "resize(unsigned(std_logic_vector(~ARG[0])),21)"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.int2Word#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "word2Int# :: Int# -> Word#"- , "template" : "unsigned(std_logic_vector(~ARG[0]))"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.uncheckedIShiftL#"- , "kind" : "Declaration"- , "type" : "uncheckedIShiftL# :: Int# -> Int# -> Int#"- , "template" :-"~RESULT <= shift_left(~ARG[0],to_integer(~ARG[1]))- -- pragma translate_off- when (~ARG[1] >= 0) else (others => 'X')- -- pragma translate_on- ;"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.uncheckedIShiftRA#"- , "kind" : "Declaration"- , "type" : "uncheckedIShiftRA# :: Int# -> Int# -> Int#"- , "template" :-"~RESULT <= shift_right(~ARG[0],to_integer(~ARG[1]))- -- pragma translate_off- when (~ARG[1] >= 0) else (others => 'X')- -- pragma translate_on- ;"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.uncheckedIShiftRL#"- , "kind" : "Expression"- , "type" : "uncheckedIShiftRL# :: Int# -> Int# -> Int#"- , "template" : "~ARG[0] srl to_integer(~ARG[1])"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.timesWord#"- , "kind" : "Expression"- , "type" : "timesWord# :: Word# -> Word# -> Word#"- , "template" : "resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO])"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.remWord#"- , "kind" : "Expression"- , "type" : "remWord# :: Word# -> Word# -> Word#"- , "template" : "~ARG[0] rem ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.quotRemWord#"- , "kind" : "Expression"- , "type" : "quotRemWord# :: Word# -> Word# -> (#Word#, Word##)"- , "template" : "(~ARG[0] / ~ARG[1], ~ARG[0] rem ~ARG[1])"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.and#"- , "kind" : "Expression"- , "type" : "and# :: Word# -> Word# -> Word#"- , "template" : "~ARG[0] and ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.or#"- , "kind" : "Expression"- , "type" : "or# :: Word# -> Word# -> Word#"- , "template" : "~ARG[0] or ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.xor#"- , "kind" : "Expression"- , "type" : "xor# :: Word# -> Word# -> Word#"- , "template" : "~ARG[0] xor ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.not#"- , "kind" : "Expression"- , "type" : "not# :: Word# -> Word#"- , "template" : "not ~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.uncheckedShiftL#"- , "kind" : "Declaration"- , "type" : "uncheckedShiftL# :: Word# -> Int# -> Word#"- , "template" :-"~RESULT <= shift_left(~ARG[0],to_integer(~ARG[1]))- -- pragma translate_off- when (~ARG[1] >= 0) else (others => 'X')- -- pragma translate_on- ;"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.uncheckedShiftRL#"- , "kind" : "Declaration"- , "type" : "uncheckedShiftR# :: Word# -> Int# -> Word#"- , "template" :-"~RESULT <= shift_right(~ARG[0],to_integer(~ARG[1]))- -- pragma translate_off- when (~ARG[1] >= 0) else (others => 'X')- -- pragma translate_on- ;"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.word2Int#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "word2Int# :: word# -> Int#"- , "template" : "signed(std_logic_vector(~ARG[0]))"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.gtWord#"- , "kind" : "Declaration"- , "type" : "gtWord# :: Word# -> Word# -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.geWord#"- , "kind" : "Declaration"- , "type" : "geWord# :: Word# -> Word# -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.eqWord#"- , "kind" : "Declaration"- , "type" : "eqWord# :: Word# -> Word# -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.neWord#"- , "kind" : "Declaration"- , "type" : "neWord# :: Word# -> Word# -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ltWord#"- , "kind" : "Declaration"- , "type" : "ltWord# :: Word# -> Word# -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.leWord#"- , "kind" : "Declaration"- , "type" : "leWord# :: Word# -> Word# -> Int#"- , "template" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.popCnt8#"- , "kind" : "Declaration"- , "type" : "popCnt8 :: Word# -> Word#"- , "template" :-"-- popCnt8 begin-~GENSYM[popCnt8][0] : block- -- given a level and a depth, calculate the corresponding index into the- -- intermediate array- function ~GENSYM[depth2Index][1] (levels,depth : in natural) return natural is- begin- return (2 ** levels - 2 ** depth);- end function;-- constant ~GENSYM[width][2] : natural := 8;- constant ~GENSYM[levels][3] : natural := natural (ceil (log2 (real (~SYM[2]))));- type ~GENSYM[popCnt_res_vec][4] is array (natural range <>) of unsigned(~SYM[3] downto 0);- signal ~GENSYM[intermediate][5] : ~SYM[4](0 to (2*~SYM[2])-2);-begin- -- put input into the first half of the intermediate array- ~GENSYM[make_array][6]: for ~GENSYM[i][7] in 0 to (~SYM[2] - 1) generate- ~SYM[5](~SYM[7]) <= resize(~VAR[input][0](~SYM[7] downto ~SYM[7]),~SYM[3]+1);- end generate;-- -- Create the tree of adders- ~GENSYM[make_tree][8] : if ~SYM[3] /= 0 generate- ~GENSYM[tree_depth][9] : for ~GENSYM[d][10] in ~SYM[3]-1 downto 0 generate- ~GENSYM[tree_depth_loop][11] : for ~GENSYM[i][12] in 0 to (natural(2**~SYM[10]) - 1) generate- ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+1)+~SYM[12]) <=- ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+2)+(2*~SYM[12])) +- ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+2)+(2*~SYM[12])+1);- end generate;- end generate;- end generate;-- -- The last element of the intermediate array holds the result- ~RESULT <= resize(~SYM[5]((2*~SYM[2])-2),~SIZE[~TYPO]);-end block;--- popCnt8 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.popCnt16#"- , "kind" : "Declaration"- , "type" : "popCnt16 :: Word# -> Word#"- , "template" :-"-- popCnt16 begin-~GENSYM[popCnt16][0] : block- -- given a level and a depth, calculate the corresponding index into the- -- intermediate array- function ~GENSYM[depth2Index][1] (levels,depth : in natural) return natural is- begin- return (2 ** levels - 2 ** depth);- end function;-- constant ~GENSYM[width][2] : natural := 16;- constant ~GENSYM[levels][3] : natural := natural (ceil (log2 (real (~SYM[2]))));- type ~GENSYM[popCnt_res_vec][4] is array (natural range <>) of unsigned(~SYM[3] downto 0);- signal ~GENSYM[intermediate][5] : ~SYM[4](0 to (2*~SYM[2])-2);-begin- -- put input into the first half of the intermediate array- ~GENSYM[make_array][6]: for ~GENSYM[i][7] in 0 to (~SYM[2] - 1) generate- ~SYM[5](~SYM[7]) <= resize(~VAR[input][0](~SYM[7] downto ~SYM[7]),~SYM[3]+1);- end generate;-- -- Create the tree of adders- ~GENSYM[make_tree][8] : if ~SYM[3] /= 0 generate- ~GENSYM[tree_depth][9] : for ~GENSYM[d][10] in ~SYM[3]-1 downto 0 generate- ~GENSYM[tree_depth_loop][11] : for ~GENSYM[i][12] in 0 to (natural(2**~SYM[10]) - 1) generate- ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+1)+~SYM[12]) <=- ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+2)+(2*~SYM[12])) +- ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+2)+(2*~SYM[12])+1);- end generate;- end generate;- end generate;-- -- The last element of the intermediate array holds the result- ~RESULT <= resize(~SYM[5]((2*~SYM[2])-2),~SIZE[~TYPO]);-end block;--- popCnt16 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.popCnt32#"- , "kind" : "Declaration"- , "type" : "popCnt32 :: Word# -> Word#"- , "template" :-"-- popCnt32 begin-~GENSYM[popCnt32][0] : block- -- given a level and a depth, calculate the corresponding index into the- -- intermediate array- function ~GENSYM[depth2Index][1] (levels,depth : in natural) return natural is- begin- return (2 ** levels - 2 ** depth);- end function;-- constant ~GENSYM[width][2] : natural := 32;- constant ~GENSYM[levels][3] : natural := natural (ceil (log2 (real (~SYM[2]))));- type ~GENSYM[popCnt_res_vec][4] is array (natural range <>) of unsigned(~SYM[3] downto 0);- signal ~GENSYM[intermediate][5] : ~SYM[4](0 to (2*~SYM[2])-2);-begin- -- put input into the first half of the intermediate array- ~GENSYM[make_array][6]: for ~GENSYM[i][7] in 0 to (~SYM[2] - 1) generate- ~SYM[5](~SYM[7]) <= resize(~VAR[input][0](~SYM[7] downto ~SYM[7]),~SYM[3]+1);- end generate;-- -- Create the tree of adders- ~GENSYM[make_tree][8] : if ~SYM[3] /= 0 generate- ~GENSYM[tree_depth][9] : for ~GENSYM[d][10] in ~SYM[3]-1 downto 0 generate- ~GENSYM[tree_depth_loop][11] : for ~GENSYM[i][12] in 0 to (natural(2**~SYM[10]) - 1) generate- ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+1)+~SYM[12]) <=- ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+2)+(2*~SYM[12])) +- ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+2)+(2*~SYM[12])+1);- end generate;- end generate;- end generate;-- -- The last element of the intermediate array holds the result- ~RESULT <= resize(~SYM[5]((2*~SYM[2])-2),~SIZE[~TYPO]);-end block;--- popCnt32 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.popCnt64#"- , "kind" : "Declaration"- , "type" : "popCnt64 :: Word# -> Word#"- , "template" :-"-- popCnt64 begin-~GENSYM[popCnt64][0] : block- -- given a level and a depth, calculate the corresponding index into the- -- intermediate array- function ~GENSYM[depth2Index][1] (levels,depth : in natural) return natural is- begin- return (2 ** levels - 2 ** depth);- end function;-- constant ~GENSYM[width][2] : natural := 64;- constant ~GENSYM[levels][3] : natural := natural (ceil (log2 (real (~SYM[2]))));- type ~GENSYM[popCnt_res_vec][4] is array (natural range <>) of unsigned(~SYM[3] downto 0);- signal ~GENSYM[intermediate][5] : ~SYM[4](0 to (2*~SYM[2])-2);-begin- -- put input into the first half of the intermediate array- ~GENSYM[make_array][6]: for ~GENSYM[i][7] in 0 to (~SYM[2] - 1) generate- ~SYM[5](~SYM[7]) <= resize(~VAR[input][0](~SYM[7] downto ~SYM[7]),~SYM[3]+1);- end generate;-- -- Create the tree of adders- ~GENSYM[make_tree][8] : if ~SYM[3] /= 0 generate- ~GENSYM[tree_depth][9] : for ~GENSYM[d][10] in ~SYM[3]-1 downto 0 generate- ~GENSYM[tree_depth_loop][11] : for ~GENSYM[i][12] in 0 to (natural(2**~SYM[10]) - 1) generate- ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+1)+~SYM[12]) <=- ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+2)+(2*~SYM[12])) +- ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+2)+(2*~SYM[12])+1);- end generate;- end generate;- end generate;-- -- The last element of the intermediate array holds the result- ~RESULT <= resize(~SYM[5]((2*~SYM[2])-2),~SIZE[~TYPO]);-end block;--- popCnt64 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.popCnt#"- , "kind" : "Declaration"- , "type" : "popCnt :: Word# -> Word#"- , "template" :-"-- popCnt begin-~GENSYM[popCnt][0] : block- -- given a level and a depth, calculate the corresponding index into the- -- intermediate array- function ~GENSYM[depth2Index][1] (levels,depth : in natural) return natural is- begin- return (2 ** levels - 2 ** depth);- end function;-- constant ~GENSYM[width][2] : natural := ~SIZE[~TYPO];- constant ~GENSYM[levels][3] : natural := natural (ceil (log2 (real (~SYM[2]))));- type ~GENSYM[popCnt_res_vec][4] is array (natural range <>) of unsigned(~SYM[3] downto 0);- signal ~GENSYM[intermediate][5] : ~SYM[4](0 to (2*~SYM[2])-2);-begin- -- put input into the first half of the intermediate array- ~GENSYM[make_array][6]: for ~GENSYM[i][7] in 0 to (~SYM[2] - 1) generate- ~SYM[5](~SYM[7]) <= resize(~VAR[input][0](~SYM[7] downto ~SYM[7]),~SYM[3]+1);- end generate;-- -- Create the tree of adders- ~GENSYM[make_tree][8] : if ~SYM[3] /= 0 generate- ~GENSYM[tree_depth][9] : for ~GENSYM[d][10] in ~SYM[3]-1 downto 0 generate- ~GENSYM[tree_depth_loop][11] : for ~GENSYM[i][12] in 0 to (natural(2**~SYM[10]) - 1) generate- ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+1)+~SYM[12]) <=- ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+2)+(2*~SYM[12])) +- ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+2)+(2*~SYM[12])+1);- end generate;- end generate;- end generate;-- -- The last element of the intermediate array holds the result- ~RESULT <= resize(~SYM[5]((2*~SYM[2])-2),~SIZE[~TYPO]);-end block;--- popCnt end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.clz8#"- , "kind" : "Declaration"- , "type" : "clz8 :: Word# -> Word#"- , "template" :-"-- clz8 begin-~GENSYM[clz8][0] : block- function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is- begin- case a is- when \"00\" => return \"10\";- when \"01\" => return \"01\";- when \"10\" => return \"00\";- when others => return \"00\";- end case;- end function;-- function ~GENSYM[clzi][2] (- constant n : in natural;- constant i : in unsigned) return unsigned is- variable v : unsigned(i'length-1 downto 0):=i;- begin- if v(n-1+n)='0' then- return (v(n-1+n) and v(n-1)) & '0' & v(2*n-2 downto n);- else- return (v(n-1+n) and v(n-1)) & not v(n-1) & v(n-2 downto 0);- end if;- end function;-- function ~GENSYM[clz8][3] (constant v : unsigned(0 to 7)) return unsigned is- variable e : unsigned(0 to 7); -- 8- variable a : unsigned(0 to 2*3-1); -- 6- begin- for i in 0 to 3 loop e(i*2 to i*2+1):=~SYM[1](v(i*2 to i*2+1)); end loop;- for i in 0 to 1 loop a(i*3 to i*3+2):=~SYM[2](2,e(i*4 to i*4+3)); end loop;- return ~SYM[2](3,a(0 to 5));- end function;-begin- ~RESULT <= resize(~SYM[3](~ARG[0](7 downto 0)),~SIZE[~TYPO]);-end block;--- clz8 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.clz16#"- , "kind" : "Declaration"- , "type" : "clz16 :: Word# -> Word#"- , "template" :-"-- clz16 begin-~GENSYM[clz16][0] : block- function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is- begin- case a is- when \"00\" => return \"10\";- when \"01\" => return \"01\";- when \"10\" => return \"00\";- when others => return \"00\";- end case;- end function;-- function ~GENSYM[clzi][2] (- constant n : in natural;- constant i : in unsigned) return unsigned is- variable v : unsigned(i'length-1 downto 0):=i;- begin- if v(n-1+n)='0' then- return (v(n-1+n) and v(n-1)) & '0' & v(2*n-2 downto n);- else- return (v(n-1+n) and v(n-1)) & not v(n-1) & v(n-2 downto 0);- end if;- end function;-- function ~GENSYM[clz16][3] (constant v : unsigned(0 to 15)) return unsigned is- variable e : unsigned(0 to 15); -- 16- variable a : unsigned(0 to 4*3-1); -- 12- variable b : unsigned(0 to 2*4-1); -- 8- begin- for i in 0 to 7 loop e(i*2 to i*2+1):=~SYM[1](v(i*2 to i*2+1)); end loop;- for i in 0 to 3 loop a(i*3 to i*3+2):=~SYM[2](2,e(i*4 to i*4+3)); end loop;- for i in 0 to 1 loop b(i*4 to i*4+3):=~SYM[2](3,a(i*6 to i*6+5)); end loop;- return ~SYM[2](4,b(0 to 7));- end function;-begin- ~RESULT <= resize(~SYM[3](~ARG[0](15 downto 0)),~SIZE[~TYPO]);-end block;--- clz16 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.clz32#"- , "kind" : "Declaration"- , "type" : "clz32 :: Word# -> Word#"- , "template" :-"-- clz32 begin-~GENSYM[clz32][0] : block- function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is- begin- case a is- when \"00\" => return \"10\";- when \"01\" => return \"01\";- when \"10\" => return \"00\";- when others => return \"00\";- end case;- end function;-- function ~GENSYM[clzi][2] (- constant n : in natural;- constant i : in unsigned) return unsigned is- variable v : unsigned(i'length-1 downto 0):=i;- begin- if v(n-1+n)='0' then- return (v(n-1+n) and v(n-1)) & '0' & v(2*n-2 downto n);- else- return (v(n-1+n) and v(n-1)) & not v(n-1) & v(n-2 downto 0);- end if;- end function;-- function ~GENSYM[clz32][3] (constant v : unsigned(0 to 31)) return unsigned is- variable e : unsigned(0 to 31); -- 32- variable a : unsigned(0 to 8*3-1); -- 24- variable b : unsigned(0 to 4*4-1); -- 16- variable c : unsigned(0 to 2*5-1); -- 10- begin- for i in 0 to 15 loop e(i*2 to i*2+1):=~SYM[1](v(i*2 to i*2+1)); end loop;- for i in 0 to 7 loop a(i*3 to i*3+2):=~SYM[2](2,e(i*4 to i*4+3)); end loop;- for i in 0 to 3 loop b(i*4 to i*4+3):=~SYM[2](3,a(i*6 to i*6+5)); end loop;- for i in 0 to 1 loop c(i*5 to i*5+4):=~SYM[2](4,b(i*8 to i*8+7)); end loop;- return ~SYM[2](5,c(0 to 9));- end function;-begin- ~RESULT <= resize(~SYM[3](~ARG[0](31 downto 0)),~SIZE[~TYPO]);-end block;--- clz32 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.clz64#"- , "kind" : "Declaration"- , "type" : "clz64 :: Word# -> Word#"- , "template" :-"-- clz64 begin-~GENSYM[clz64][0] : block- function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is- begin- case a is- when \"00\" => return \"10\";- when \"01\" => return \"01\";- when \"10\" => return \"00\";- when others => return \"00\";- end case;- end function;-- function ~GENSYM[clzi][2] (- constant n : in natural;- constant i : in unsigned) return unsigned is- variable v : unsigned(i'length-1 downto 0):=i;- begin- if v(n-1+n)='0' then- return (v(n-1+n) and v(n-1)) & '0' & v(2*n-2 downto n);- else- return (v(n-1+n) and v(n-1)) & not v(n-1) & v(n-2 downto 0);- end if;- end function;-- function ~GENSYM[clz64][3] (constant v : unsigned(0 to 63)) return unsigned is- variable e : unsigned(0 to 63); -- 64- variable a : unsigned(0 to 16*3-1); -- 48- variable b : unsigned(0 to 8*4-1); -- 32- variable c : unsigned(0 to 4*5-1); -- 20- variable d : unsigned(0 to 2*6-1); -- 12- begin- for i in 0 to 31 loop e(i*2 to i*2+1):=~SYM[1](v(i*2 to i*2+1)); end loop;- for i in 0 to 15 loop a(i*3 to i*3+2):=~SYM[2](2,e(i*4 to i*4+3)); end loop;- for i in 0 to 7 loop b(i*4 to i*4+3):=~SYM[2](3,a(i*6 to i*6+5)); end loop;- for i in 0 to 3 loop c(i*5 to i*5+4):=~SYM[2](4,b(i*8 to i*8+7)); end loop;- for i in 0 to 1 loop d(i*6 to i*6+5):=~SYM[2](5,c(i*10 to i*10+9)); end loop;- return ~SYM[2](6,d(0 to 11));- end function;-begin- ~RESULT <= resize(~SYM[3](~ARG[0]),~SIZE[~TYPO]);-end block;--- clz64 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.clz#"- , "kind" : "Declaration"- , "type" : "clz :: Word# -> Word#"- , "template" :-"-- clz begin-~GENSYM[clz][0] : block- function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is- begin- case a is- when \"00\" => return \"10\";- when \"01\" => return \"01\";- when \"10\" => return \"00\";- when others => return \"00\";- end case;- end function;-- function ~GENSYM[clzi][2] (- constant n : in natural;- constant i : in unsigned) return unsigned is- variable v : unsigned(i'length-1 downto 0):=i;- begin- if v(n-1+n)='0' then- return (v(n-1+n) and v(n-1)) & '0' & v(2*n-2 downto n);- else- return (v(n-1+n) and v(n-1)) & not v(n-1) & v(n-2 downto 0);- end if;- end function;-~IF ~IW64 ~THEN- function ~GENSYM[clz64][3] (constant v : unsigned(0 to 63)) return unsigned is- variable e : unsigned(0 to 63); -- 64- variable a : unsigned(0 to 16*3-1); -- 48- variable b : unsigned(0 to 8*4-1); -- 32- variable c : unsigned(0 to 4*5-1); -- 20- variable d : unsigned(0 to 2*6-1); -- 12- begin- for i in 0 to 31 loop e(i*2 to i*2+1):=~SYM[1](v(i*2 to i*2+1)); end loop;- for i in 0 to 15 loop a(i*3 to i*3+2):=~SYM[2](2,e(i*4 to i*4+3)); end loop;- for i in 0 to 7 loop b(i*4 to i*4+3):=~SYM[2](3,a(i*6 to i*6+5)); end loop;- for i in 0 to 3 loop c(i*5 to i*5+4):=~SYM[2](4,b(i*8 to i*8+7)); end loop;- for i in 0 to 1 loop d(i*6 to i*6+5):=~SYM[2](5,c(i*10 to i*10+9)); end loop;- return ~SYM[2](6,d(0 to 11));- end function;-~ELSE- function ~GENSYM[clz32][4] (constant v : unsigned(0 to 31)) return unsigned is- variable e : unsigned(0 to 31); -- 32- variable a : unsigned(0 to 8*3-1); -- 24- variable b : unsigned(0 to 4*4-1); -- 16- variable c : unsigned(0 to 2*5-1); -- 10- begin- for i in 0 to 15 loop e(i*2 to i*2+1):=~SYM[1](v(i*2 to i*2+1)); end loop;- for i in 0 to 7 loop a(i*3 to i*3+2):=~SYM[2](2,e(i*4 to i*4+3)); end loop;- for i in 0 to 3 loop b(i*4 to i*4+3):=~SYM[2](3,a(i*6 to i*6+5)); end loop;- for i in 0 to 1 loop c(i*5 to i*5+4):=~SYM[2](4,b(i*8 to i*8+7)); end loop;- return ~SYM[2](5,c(0 to 9));- end function;-~FI-begin-~IF ~IW64 ~THEN- ~RESULT <= resize(~SYM[3](~ARG[0]),~SIZE[~TYPO]);-~ELSE- ~RESULT <= resize(~SYM[4](~ARG[0]),~SIZE[~TYPO]);-~FI-end block;--- clz end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ctz8#"- , "kind" : "Declaration"- , "type" : "ctz8 :: Word# -> Word#"- , "template" :-"-- ctz8 begin-~GENSYM[ctz8][0] : block- function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is- begin- case a is- when \"00\" => return \"10\";- when \"01\" => return \"01\";- when \"10\" => return \"00\";- when others => return \"00\";- end case;- end function;-- function ~GENSYM[clzi][2] (- constant n : in natural;- constant i : in unsigned) return unsigned is- variable v : unsigned(i'length-1 downto 0):=i;- begin- if v(n-1+n)='0' then- return (v(n-1+n) and v(n-1)) & '0' & v(2*n-2 downto n);- else- return (v(n-1+n) and v(n-1)) & not v(n-1) & v(n-2 downto 0);- end if;- end function;-- function ~GENSYM[clz8][3] (constant v : unsigned(0 to 7)) return unsigned is- variable e : unsigned(0 to 7); -- 8- variable a : unsigned(0 to 2*3-1); -- 6- begin- for i in 0 to 3 loop e(i*2 to i*2+1):=~SYM[1](v(i*2 to i*2+1)); end loop;- for i in 0 to 1 loop a(i*3 to i*3+2):=~SYM[2](2,e(i*4 to i*4+3)); end loop;- return ~SYM[2](3,a(0 to 5));- end function;-- signal ~GENSYM[w_reversed][5] : ~TYP[0];-begin- ~GENSYM[reverse_loop][6] : for ~GENSYM[n][7] in ~VAR[w][0]'range generate- ~SYM[5](~VAR[w][0]'high - ~SYM[7]) <= ~VAR[w][0](~SYM[7]);- end generate;-~IF ~IW64 ~THEN- ~RESULT <= resize(~SYM[3](~SYM[5](63 downto 56)),~SIZE[~TYPO]);-~ELSE- ~RESULT <= resize(~SYM[3](~SYM[5](31 downto 24)),~SIZE[~TYPO]);-~FI-end block;--- ctz8 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ctz16#"- , "kind" : "Declaration"- , "type" : "ctz16 :: Word# -> Word#"- , "template" :-"-- ctz16 begin-~GENSYM[ctz16][0] : block- function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is- begin- case a is- when \"00\" => return \"10\";- when \"01\" => return \"01\";- when \"10\" => return \"00\";- when others => return \"00\";- end case;- end function;-- function ~GENSYM[clzi][2] (- constant n : in natural;- constant i : in unsigned) return unsigned is- variable v : unsigned(i'length-1 downto 0):=i;- begin- if v(n-1+n)='0' then- return (v(n-1+n) and v(n-1)) & '0' & v(2*n-2 downto n);- else- return (v(n-1+n) and v(n-1)) & not v(n-1) & v(n-2 downto 0);- end if;- end function;-- function ~GENSYM[clz16][3] (constant v : unsigned(0 to 15)) return unsigned is- variable e : unsigned(0 to 15); -- 16- variable a : unsigned(0 to 4*3-1); -- 12- variable b : unsigned(0 to 2*4-1); -- 8- begin- for i in 0 to 7 loop e(i*2 to i*2+1):=~SYM[1](v(i*2 to i*2+1)); end loop;- for i in 0 to 3 loop a(i*3 to i*3+2):=~SYM[2](2,e(i*4 to i*4+3)); end loop;- for i in 0 to 1 loop b(i*4 to i*4+3):=~SYM[2](3,a(i*6 to i*6+5)); end loop;- return ~SYM[2](4,b(0 to 7));- end function;-- signal ~GENSYM[w_reversed][5] : ~TYP[0];-begin- ~GENSYM[reverse_loop][6] : for ~GENSYM[n][7] in ~VAR[w][0]'range generate- ~SYM[5](~VAR[w][0]'high - ~SYM[7]) <= ~VAR[w][0](~SYM[7]);- end generate;-~IF ~IW64 ~THEN- ~RESULT <= resize(~SYM[3](~SYM[5](63 downto 48)),~SIZE[~TYPO]);-~ELSE- ~RESULT <= resize(~SYM[3](~SYM[5](31 downto 16)),~SIZE[~TYPO]);-~FI-end block;--- ctz16 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ctz32#"- , "kind" : "Declaration"- , "type" : "ctz32 :: Word# -> Word#"- , "template" :-"-- ctz32 begin-~GENSYM[ctz32][0] : block- function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is- begin- case a is- when \"00\" => return \"10\";- when \"01\" => return \"01\";- when \"10\" => return \"00\";- when others => return \"00\";- end case;- end function;-- function ~GENSYM[clzi][2] (- constant n : in natural;- constant i : in unsigned) return unsigned is- variable v : unsigned(i'length-1 downto 0):=i;- begin- if v(n-1+n)='0' then- return (v(n-1+n) and v(n-1)) & '0' & v(2*n-2 downto n);- else- return (v(n-1+n) and v(n-1)) & not v(n-1) & v(n-2 downto 0);- end if;- end function;-- function ~GENSYM[clz32][3] (constant v : unsigned(0 to 31)) return unsigned is- variable e : unsigned(0 to 31); -- 32- variable a : unsigned(0 to 8*3-1); -- 24- variable b : unsigned(0 to 4*4-1); -- 16- variable c : unsigned(0 to 2*5-1); -- 10- begin- for i in 0 to 15 loop e(i*2 to i*2+1):=~SYM[1](v(i*2 to i*2+1)); end loop;- for i in 0 to 7 loop a(i*3 to i*3+2):=~SYM[2](2,e(i*4 to i*4+3)); end loop;- for i in 0 to 3 loop b(i*4 to i*4+3):=~SYM[2](3,a(i*6 to i*6+5)); end loop;- for i in 0 to 1 loop c(i*5 to i*5+4):=~SYM[2](4,b(i*8 to i*8+7)); end loop;- return ~SYM[2](5,c(0 to 9));- end function;-- signal ~GENSYM[w_reversed][5] : ~TYP[0];-begin- ~GENSYM[reverse_loop][6] : for ~GENSYM[n][7] in ~VAR[w][0]'range generate- ~SYM[5](~VAR[w][0]'high - ~SYM[7]) <= ~VAR[w][0](~SYM[3]);- end generate;-~IF ~IW64 ~THEN- ~RESULT <= resize(~SYM[3](~SYM[5](63 downto 32)),~SIZE[~TYPO]);-~ELSE- ~RESULT <= resize(~SYM[3](~SYM[5]),~SIZE[~TYPO]);-~FI-end block;--- ctz32 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ctz64#"- , "kind" : "Declaration"- , "type" : "ctz64 :: Word# -> Word#"- , "template" :-"-- ctz64 begin-~GENSYM[ctz64][0] : block- function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is- begin- case a is- when \"00\" => return \"10\";- when \"01\" => return \"01\";- when \"10\" => return \"00\";- when others => return \"00\";- end case;- end function;-- function ~GENSYM[clzi][2] (- constant n : in natural;- constant i : in unsigned) return unsigned is- variable v : unsigned(i'length-1 downto 0):=i;- begin- if v(n-1+n)='0' then- return (v(n-1+n) and v(n-1)) & '0' & v(2*n-2 downto n);- else- return (v(n-1+n) and v(n-1)) & not v(n-1) & v(n-2 downto 0);- end if;- end function;-- function ~GENSYM[clz64][3] (constant v : unsigned(0 to 63)) return unsigned is- variable e : unsigned(0 to 63); -- 64- variable a : unsigned(0 to 16*3-1); -- 48- variable b : unsigned(0 to 8*4-1); -- 32- variable c : unsigned(0 to 4*5-1); -- 20- variable d : unsigned(0 to 2*6-1); -- 12- begin- for i in 0 to 31 loop e(i*2 to i*2+1):=~SYM[1](v(i*2 to i*2+1)); end loop;- for i in 0 to 15 loop a(i*3 to i*3+2):=~SYM[2](2,e(i*4 to i*4+3)); end loop;- for i in 0 to 7 loop b(i*4 to i*4+3):=~SYM[2](3,a(i*6 to i*6+5)); end loop;- for i in 0 to 3 loop c(i*5 to i*5+4):=~SYM[2](4,b(i*8 to i*8+7)); end loop;- for i in 0 to 1 loop d(i*6 to i*6+5):=~SYM[2](5,c(i*10 to i*10+9)); end loop;- return ~SYM[2](6,d(0 to 11));- end function;-- signal ~GENSYM[w_reversed][5] : ~TYP[0];-begin- ~GENSYM[reverse_loop][6] : for ~GENSYM[n][7] in ~VAR[w][0]'range generate- ~SYM[5](~VAR[w][0]'high - ~SYM[7]) <= ~VAR[w][0](~SYM[7]);- end generate;-- ~RESULT <= resize(~SYM[3](~SYM[5]),~SIZE[~TYPO]);-end block;--- ctz64 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ctz#"- , "kind" : "Declaration"- , "type" : "ctz :: Word# -> Word#"- , "template" :-"-- ctz begin-~GENSYM[ctz][0] : block- function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is- begin- case a is- when \"00\" => return \"10\";- when \"01\" => return \"01\";- when \"10\" => return \"00\";- when others => return \"00\";- end case;- end function;-- function ~GENSYM[clzi][2] (- constant n : in natural;- constant i : in unsigned) return unsigned is- variable v : unsigned(i'length-1 downto 0):=i;- begin- if v(n-1+n)='0' then- return (v(n-1+n) and v(n-1)) & '0' & v(2*n-2 downto n);- else- return (v(n-1+n) and v(n-1)) & not v(n-1) & v(n-2 downto 0);- end if;- end function;--~IF ~IW64 ~THEN- function ~GENSYM[clz64][3] (constant v : unsigned(0 to 63)) return unsigned is- variable e : unsigned(0 to 63); -- 64- variable a : unsigned(0 to 16*3-1); -- 48- variable b : unsigned(0 to 8*4-1); -- 32- variable c : unsigned(0 to 4*5-1); -- 20- variable d : unsigned(0 to 2*6-1); -- 12- begin- for i in 0 to 31 loop e(i*2 to i*2+1):=~SYM[1](v(i*2 to i*2+1)); end loop;- for i in 0 to 15 loop a(i*3 to i*3+2):=~SYM[2](2,e(i*4 to i*4+3)); end loop;- for i in 0 to 7 loop b(i*4 to i*4+3):=~SYM[2](3,a(i*6 to i*6+5)); end loop;- for i in 0 to 3 loop c(i*5 to i*5+4):=~SYM[2](4,b(i*8 to i*8+7)); end loop;- for i in 0 to 1 loop d(i*6 to i*6+5):=~SYM[2](5,c(i*10 to i*10+9)); end loop;- return ~SYM[2](6,d(0 to 11));- end function;-~ELSE- function ~GENSYM[clz32][4] (constant v : unsigned(0 to 31)) return unsigned is- variable e : unsigned(0 to 31); -- 32- variable a : unsigned(0 to 8*3-1); -- 24- variable b : unsigned(0 to 4*4-1); -- 16- variable c : unsigned(0 to 2*5-1); -- 10- begin- for i in 0 to 15 loop e(i*2 to i*2+1):=~SYM[1](v(i*2 to i*2+1)); end loop;- for i in 0 to 7 loop a(i*3 to i*3+2):=~SYM[2](2,e(i*4 to i*4+3)); end loop;- for i in 0 to 3 loop b(i*4 to i*4+3):=~SYM[2](3,a(i*6 to i*6+5)); end loop;- for i in 0 to 1 loop c(i*5 to i*5+4):=~SYM[2](4,b(i*8 to i*8+7)); end loop;- return ~SYM[2](5,c(0 to 9));- end function;-~FI-- signal ~GENSYM[w_reversed][6] : ~TYP[0];-begin- ~GENSYM[reverse_loop][7] : for ~GENSYM[n][8] in ~VAR[w][0]'range generate- ~SYM[6](~VAR[w][0]'high - ~SYM[8]) <= ~VAR[w][0](~SYM[8]);- end generate;-~IF ~IW64 ~THEN- ~RESULT <= resize(~SYM[3](~SYM[6]),~SIZE[~TYPO]);-~ELSE- ~RESULT <= resize(~SYM[4](~SYM[6]),~SIZE[~TYPO]);-~FI-end block;--- ctz end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.byteSwap16#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "byteSwap16# :: Word# -> Word#"- , "template" :-"-- byteSwap16 begin~IF ~IW64 ~THEN-~RESULT <= ~VAR[w][0](63 downto 16) & ~VAR[w][0](7 downto 0) & ~VAR[w][0](15 downto 8);~ELSE-~RESULT <= ~VAR[w][0](31 downto 16) & ~VAR[w][0](7 downto 0) & ~VAR[w][0](15 downto 8);~FI--- byteSwap16 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.byteSwap32#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "byteSwap32# :: Word# -> Word#"- , "template" :-"-- byteSwap32 begin~IF ~IW64 ~THEN-~RESULT <= ~VAR[w][0](63 downto 32) & ~VAR[w][0](7 downto 0 ) & ~VAR[w][0](15 downto 8)- & ~VAR[w][0](23 downto 16) & ~VAR[w][0](31 downto 24);~ELSE-~RESULT <= ~VAR[w][0](7 downto 0 ) & ~VAR[w][0](15 downto 8)- & ~VAR[w][0](23 downto 16) & ~VAR[w][0](31 downto 24);~FI--- byteSwap32 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.byteSwap64#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "byteSwap64# :: Word# -> Word#"- , "template" :-"-- byteSwap64 begin-~RESULT <= ~VAR[w][0](7 downto 0 ) & ~VAR[w][0](15 downto 8)- & ~VAR[w][0](23 downto 16) & ~VAR[w][0](31 downto 24)- & ~VAR[w][0](39 downto 32) & ~VAR[w][0](47 downto 40)- & ~VAR[w][0](55 downto 48) & ~VAR[w][0](63 downto 56);--- byteSwap64 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.byteSwap#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "byteSwap# :: Word# -> Word#"- , "template" :-"-- byteSwap begin ~IF ~IW64 ~THEN-~RESULT <= ~VAR[w][0](7 downto 0 ) & ~VAR[w][0](15 downto 8)- & ~VAR[w][0](23 downto 16) & ~VAR[w][0](31 downto 24)- & ~VAR[w][0](39 downto 32) & ~VAR[w][0](47 downto 40)- & ~VAR[w][0](55 downto 48) & ~VAR[w][0](63 downto 56);~ELSE-~RESULT <= ~VAR[w][0](7 downto 0 ) & ~VAR[w][0](15 downto 8)- & ~VAR[w][0](23 downto 16) & ~VAR[w][0](31 downto 24);~FI--- byteSwap end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.narrow8Int#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "narrow8Int# :: Int# -> Int#"- , "template" : "resize(~VAR[i][0](7 downto 0),~SIZE[~TYPO])"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.narrow16Int#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "narrow16Int# :: Int# -> Int#"- , "template" : "resize(~VAR[i][0](15 downto 0),~SIZE[~TYPO])"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.narrow32Int#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "narrow32Int# :: Int# -> Int#"- , "template" : "resize(~VAR[i][0](31 downto 0),~SIZE[~TYPO])"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.narrow8Word#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "narrow8Word# :: Word# -> Word#"- , "template" : "resize(~VAR[w][0](7 downto 0),~SIZE[~TYPO])"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.narrow16Word#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "narrow16Word# :: Word# -> Word#"- , "template" : "resize(~VAR[w][0](15 downto 0),~SIZE[~TYPO])"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.narrow32Word#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "narrow32Word# :: Word# -> Word#"- , "template" : "resize(~VAR[w][0](31 downto 0),~SIZE[~TYPO])"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.bitReverse#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "bitReverse# :: Word# -> Word#"- , "template" :-"-- bitReverse begin-~GENSYM[bitReverse][0] : for ~GENSYM[i][1] in 0 to ~IF ~IW64 ~THEN 63 ~ELSE 31 ~FI generate-begin-~RESULT(~SYM[1]) <= ~VAR[x][0](~IF ~IW64 ~THEN 63 ~ELSE 31 ~FI-~SYM[1]);-end generate;--- bitReverse end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.bitReverse8#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "bitReverse8# :: Word# -> Word#"- , "template" :-"-- bitReverse8 begin-~GENSYM[bitReverse8][0] : for ~GENSYM[i][1] in 0 to 7 generate-begin-~RESULT(~SYM[1]) <= ~VAR[x][0](7-~SYM[1]);-end generate;--- bitReverse8 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.bitReverse16#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "bitReverse16# :: Word# -> Word#"- , "template" :-"-- bitReverse16 begin-~GENSYM[bitReverse16][0] : for ~GENSYM[i][1] in 0 to 15 generate-begin-~RESULT(~SYM[1]) <= ~VAR[x][0](15-~SYM[1]);-end generate;--- bitReverse16 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.bitReverse32#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "bitReverse32# :: Word# -> Word#"- , "template" :-"-- bitReverse32 begin-~GENSYM[bitReverse32][0] : for ~GENSYM[i][1] in 0 to 31 generate-begin-~RESULT(~SYM[1]) <= ~VAR[x][0](31-~SYM[1]);-end generate;--- bitReverse32 end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.bitReverse64#"- , "workInfo" : "Never"- , "kind" : "Declaration"- , "type" : "bitReverse64# :: Word# -> Word#"- , "template" :-"-- bitReverse64 begin-~GENSYM[bitReverse64][0] : for ~GENSYM[i][1] in 0 to 63 generate-begin-~RESULT(~SYM[1]) <= ~VAR[x][0](63-~SYM[1]);-end generate;--- bitReverse64 end"- }- }-]
+ prims/vhdl/GHC_Prim.primitives.yaml view
@@ -0,0 +1,1279 @@+- BlackBox:+ name: GHC.Prim.gtChar#+ kind: Declaration+ type: 'gtChar# :: Char#+ -> Char# -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+- BlackBox:+ name: GHC.Prim.geChar#+ kind: Declaration+ type: 'geChar# :: Char#+ -> Char# -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+- BlackBox:+ name: GHC.Prim.eqChar#+ kind: Declaration+ type: 'eqChar# :: Char#+ -> Char# -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+- BlackBox:+ name: GHC.Prim.neChar#+ kind: Declaration+ type: 'neChar# :: Char#+ -> Char# -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+- BlackBox:+ name: GHC.Prim.ltChar#+ kind: Declaration+ type: 'ltChar# :: Char#+ -> Char# -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+- BlackBox:+ name: GHC.Prim.leChar#+ kind: Declaration+ type: 'leChar# :: Char#+ -> Char# -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+- BlackBox:+ name: GHC.Prim.ord#+ kind: Expression+ type: 'ord# :: Char# ->+ Int#'+ template: signed(std_logic_vector(resize(~ARG[0],~SIZE[~TYPO])))+- BlackBox:+ name: GHC.Prim.*#+ kind: Expression+ type: '(*#) :: Int# ->+ Int# -> Int#'+ template: resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO])+- BlackBox:+ name: GHC.Prim.remInt#+ kind: Declaration+ type: 'remInt# :: Int#+ -> Int# -> Int#'+ template: |-+ ~RESULT <= ~ARG[0] rem ~ARG[1]+ -- pragma translate_off+ when (~ARG[1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;+- BlackBox:+ name: GHC.Prim.quotRemInt#+ kind: Declaration+ type: 'quotRemInt# ::+ Int# -> Int# -> (#Int#, Int##)'+ template: |2-++ ~RESULT <= (~ARG[0] / ~ARG[1], ~ARG[0] rem ~ARG[1])+ -- pragma translate_off+ when (~ARG[1] /= 0) else ((others => 'X'), (others => 'X'))+ -- pragma translate_on+ ;+- BlackBox:+ name: GHC.Prim.andI#+ kind: Expression+ type: 'and# :: Int# ->+ Int# -> Int#'+ template: ~ARG[0] and ~ARG[1]+- BlackBox:+ name: GHC.Prim.orI#+ kind: Expression+ type: 'or# :: Int# ->+ Int# -> Int#'+ template: ~ARG[0] or ~ARG[1]+- BlackBox:+ name: GHC.Prim.xorI#+ kind: Expression+ type: 'xor# :: Int# ->+ Int# -> Int#'+ template: ~ARG[0] xor ~ARG[1]+- BlackBox:+ name: GHC.Prim.notI#+ kind: Expression+ type: 'not# :: Int# ->+ Int#'+ template: not ~ARG[0]+- BlackBox:+ name: GHC.Prim.negateInt#+ kind: Expression+ type: 'negateInt# :: Int#+ -> Int#'+ template: -~ARG[0]+- BlackBox:+ name: GHC.Prim.>#+ kind: Declaration+ type: '(>#) :: Int# ->+ Int# -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+- BlackBox:+ name: GHC.Prim.>=#+ kind: Declaration+ type: '(>=#) :: Int# ->+ Int# -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+- BlackBox:+ name: GHC.Prim.==#+ kind: Declaration+ type: '(==) :: Int# ->+ Int# -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+- BlackBox:+ name: GHC.Prim./=#+ kind: Declaration+ type: '(/=#) :: Int# ->+ Int# -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+- BlackBox:+ name: GHC.Prim.<#+ kind: Declaration+ type: '(<#) :: Int# ->+ Int# -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+- BlackBox:+ name: GHC.Prim.<=#+ kind: Declaration+ type: '(<=#) :: Int# ->+ Int# -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+- BlackBox:+ name: GHC.Prim.chr#+ kind: Expression+ type: 'ord# :: Int# ->+ Chr#'+ template: resize(unsigned(std_logic_vector(~ARG[0])),21)+ workInfo: Never+- BlackBox:+ name: GHC.Prim.int2Word#+ kind: Expression+ type: 'word2Int# :: Int#+ -> Word#'+ template: unsigned(std_logic_vector(~ARG[0]))+ workInfo: Never+- BlackBox:+ name: GHC.Prim.uncheckedIShiftL#+ kind: Declaration+ type: 'uncheckedIShiftL#+ :: Int# -> Int# -> Int#'+ template: |-+ ~GENSYM[~RESULT_shiftL][0] : block+ signal ~GENSYM[sh][1] : natural;+ begin+ ~SYM[1] <=+ -- pragma translate_off+ natural'high when (~VAR[shI][1](~SIZE[~TYP[1]]-1 downto 31) /= 0) else+ -- pragma translate_on+ to_integer(~VAR[shI][1]+ -- pragma translate_off+ (30 downto 0)+ -- pragma translate_on+ );+ ~RESULT <= shift_left(~ARG[0],~SYM[1])+ -- pragma translate_off+ when (~ARG[1] >= 0) else (others => 'X')+ -- pragma translate_on+ ;+ end block;+- BlackBox:+ name: GHC.Prim.uncheckedIShiftRA#+ kind: Declaration+ type: 'uncheckedIShiftRA#+ :: Int# -> Int# -> Int#'+ template: |-+ ~GENSYM[~RESULT_shiftR][0] : block+ signal ~GENSYM[sh][1] : natural;+ begin+ ~SYM[1] <=+ -- pragma translate_off+ natural'high when (~VAR[shI][1](~SIZE[~TYP[1]]-1 downto 31) /= 0) else+ -- pragma translate_on+ to_integer(~VAR[shI][1]+ -- pragma translate_off+ (30 downto 0)+ -- pragma translate_on+ );+ ~RESULT <= shift_right(~ARG[0],~SYM[1])+ -- pragma translate_off+ when (~ARG[1] >= 0) else (others => 'X')+ -- pragma translate_on+ ;+ end block;+- BlackBox:+ name: GHC.Prim.uncheckedIShiftRL#+ kind: Declaration+ type: 'uncheckedIShiftRL#+ :: Int# -> Int# -> Int#'+ template: |-+ ~GENSYM[~RESULT_shiftRL][0] : block+ signal ~GENSYM[sh][1] : natural;+ begin+ ~SYM[1] <=+ -- pragma translate_off+ natural'high when (~VAR[shI][1](~SIZE[~TYP[1]]-1 downto 31) /= 0) else+ -- pragma translate_on+ to_integer(~VAR[shI][1]+ -- pragma translate_off+ (30 downto 0)+ -- pragma translate_on+ );+ ~RESULT <= ~ARG[0] srl ~SYM[1]+ -- pragma translate_off+ when (~ARG[1] >= 0) else (others => 'X')+ -- pragma translate_on+ ;+ end block;+- BlackBox:+ name: GHC.Prim.timesWord#+ kind: Expression+ type: 'timesWord# :: Word#+ -> Word# -> Word#'+ template: resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO])+- BlackBox:+ name: GHC.Prim.remWord#+ kind: Declaration+ type: 'remWord# :: Word#+ -> Word# -> Word#'+ template: |-+ ~RESULT <= ~ARG[0] rem ~ARG[1]+ -- pragma translate_off+ when (~ARG[1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;+- BlackBox:+ name: GHC.Prim.quotRemWord#+ kind: Declaration+ type: 'quotRemWord# ::+ Word# -> Word# -> (#Word#, Word##)'+ template: |2-++ ~RESULT <= (~ARG[0] / ~ARG[1], ~ARG[0] rem ~ARG[1])+ -- pragma translate_off+ when (~ARG[1] /= 0) else ((others => 'X'), (others => 'X'))+ -- pragma translate_on+ ;+- BlackBox:+ name: GHC.Prim.and#+ kind: Expression+ type: 'and# :: Word# ->+ Word# -> Word#'+ template: ~ARG[0] and ~ARG[1]+- BlackBox:+ name: GHC.Prim.or#+ kind: Expression+ type: 'or# :: Word# ->+ Word# -> Word#'+ template: ~ARG[0] or ~ARG[1]+- BlackBox:+ name: GHC.Prim.xor#+ kind: Expression+ type: 'xor# :: Word# ->+ Word# -> Word#'+ template: ~ARG[0] xor ~ARG[1]+- BlackBox:+ name: GHC.Prim.not#+ kind: Expression+ type: 'not# :: Word# ->+ Word#'+ template: not ~ARG[0]+- BlackBox:+ name: GHC.Prim.uncheckedShiftL#+ kind: Declaration+ type: 'uncheckedShiftL#+ :: Word# -> Int# -> Word#'+ template: |-+ ~GENSYM[~RESULT_shiftL][0] : block+ signal ~GENSYM[sh][1] : natural;+ begin+ ~SYM[1] <=+ -- pragma translate_off+ natural'high when (~VAR[shI][1](~SIZE[~TYP[1]]-1 downto 31) /= 0) else+ -- pragma translate_on+ to_integer(~VAR[shI][1]+ -- pragma translate_off+ (30 downto 0)+ -- pragma translate_on+ );+ ~RESULT <= shift_left(~ARG[0],~SYM[1])+ -- pragma translate_off+ when (~ARG[1] >= 0) else (others => 'X')+ -- pragma translate_on+ ;+ end block;+- BlackBox:+ name: GHC.Prim.uncheckedShiftRL#+ kind: Declaration+ type: 'uncheckedShiftR#+ :: Word# -> Int# -> Word#'+ template: |-+ ~GENSYM[~RESULT_shiftR][0] : block+ signal ~GENSYM[sh][1] : natural;+ begin+ ~SYM[1] <=+ -- pragma translate_off+ natural'high when (~VAR[shI][1](~SIZE[~TYP[1]]-1 downto 31) /= 0) else+ -- pragma translate_on+ to_integer(~VAR[shI][1]+ -- pragma translate_off+ (30 downto 0)+ -- pragma translate_on+ );+ ~RESULT <= shift_right(~ARG[0],~SYM[1])+ -- pragma translate_off+ when (~ARG[1] >= 0) else (others => 'X')+ -- pragma translate_on+ ;+ end block;+- BlackBox:+ name: GHC.Prim.word2Int#+ kind: Expression+ type: 'word2Int# :: word#+ -> Int#'+ template: signed(std_logic_vector(~ARG[0]))+ workInfo: Never+- BlackBox:+ name: GHC.Prim.gtWord#+ kind: Declaration+ type: 'gtWord# :: Word#+ -> Word# -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+- BlackBox:+ name: GHC.Prim.geWord#+ kind: Declaration+ type: 'geWord# :: Word#+ -> Word# -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+- BlackBox:+ name: GHC.Prim.eqWord#+ kind: Declaration+ type: 'eqWord# :: Word#+ -> Word# -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+- BlackBox:+ name: GHC.Prim.neWord#+ kind: Declaration+ type: 'neWord# :: Word#+ -> Word# -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+- BlackBox:+ name: GHC.Prim.ltWord#+ kind: Declaration+ type: 'ltWord# :: Word#+ -> Word# -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+- BlackBox:+ name: GHC.Prim.leWord#+ kind: Declaration+ type: 'leWord# :: Word#+ -> Word# -> Int#'+ template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);+- BlackBox:+ name: GHC.Prim.popCnt8#+ kind: Declaration+ type: 'popCnt8 :: Word#+ -> Word#'+ template: |-+ -- popCnt8 begin+ ~GENSYM[popCnt8][0] : block+ -- given a level and a depth, calculate the corresponding index into the+ -- intermediate array+ function ~GENSYM[depth2Index][1] (levels,depth : in natural) return natural is+ begin+ return (2 ** levels - 2 ** depth);+ end function;++ constant ~GENSYM[width][2] : natural := 8;+ constant ~GENSYM[levels][3] : natural := natural (ceil (log2 (real (~SYM[2]))));+ type ~GENSYM[popCnt_res_vec][4] is array (natural range <>) of unsigned(~SYM[3] downto 0);+ signal ~GENSYM[intermediate][5] : ~SYM[4](0 to (2*~SYM[2])-2);+ begin+ -- put input into the first half of the intermediate array+ ~GENSYM[make_array][6]: for ~GENSYM[i][7] in 0 to (~SYM[2] - 1) generate+ ~SYM[5](~SYM[7]) <= resize(~VAR[input][0](~SYM[7] downto ~SYM[7]),~SYM[3]+1);+ end generate;++ -- Create the tree of adders+ ~GENSYM[make_tree][8] : if ~SYM[3] /= 0 generate+ ~GENSYM[tree_depth][9] : for ~GENSYM[d][10] in ~SYM[3]-1 downto 0 generate+ ~GENSYM[tree_depth_loop][11] : for ~GENSYM[i][12] in 0 to (natural(2**~SYM[10]) - 1) generate+ ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+1)+~SYM[12]) <=+ ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+2)+(2*~SYM[12])) ++ ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+2)+(2*~SYM[12])+1);+ end generate;+ end generate;+ end generate;++ -- The last element of the intermediate array holds the result+ ~RESULT <= resize(~SYM[5]((2*~SYM[2])-2),~SIZE[~TYPO]);+ end block;+ -- popCnt8 end+- BlackBox:+ name: GHC.Prim.popCnt16#+ kind: Declaration+ type: 'popCnt16 :: Word#+ -> Word#'+ template: |-+ -- popCnt16 begin+ ~GENSYM[popCnt16][0] : block+ -- given a level and a depth, calculate the corresponding index into the+ -- intermediate array+ function ~GENSYM[depth2Index][1] (levels,depth : in natural) return natural is+ begin+ return (2 ** levels - 2 ** depth);+ end function;++ constant ~GENSYM[width][2] : natural := 16;+ constant ~GENSYM[levels][3] : natural := natural (ceil (log2 (real (~SYM[2]))));+ type ~GENSYM[popCnt_res_vec][4] is array (natural range <>) of unsigned(~SYM[3] downto 0);+ signal ~GENSYM[intermediate][5] : ~SYM[4](0 to (2*~SYM[2])-2);+ begin+ -- put input into the first half of the intermediate array+ ~GENSYM[make_array][6]: for ~GENSYM[i][7] in 0 to (~SYM[2] - 1) generate+ ~SYM[5](~SYM[7]) <= resize(~VAR[input][0](~SYM[7] downto ~SYM[7]),~SYM[3]+1);+ end generate;++ -- Create the tree of adders+ ~GENSYM[make_tree][8] : if ~SYM[3] /= 0 generate+ ~GENSYM[tree_depth][9] : for ~GENSYM[d][10] in ~SYM[3]-1 downto 0 generate+ ~GENSYM[tree_depth_loop][11] : for ~GENSYM[i][12] in 0 to (natural(2**~SYM[10]) - 1) generate+ ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+1)+~SYM[12]) <=+ ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+2)+(2*~SYM[12])) ++ ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+2)+(2*~SYM[12])+1);+ end generate;+ end generate;+ end generate;++ -- The last element of the intermediate array holds the result+ ~RESULT <= resize(~SYM[5]((2*~SYM[2])-2),~SIZE[~TYPO]);+ end block;+ -- popCnt16 end+- BlackBox:+ name: GHC.Prim.popCnt32#+ kind: Declaration+ type: 'popCnt32 :: Word#+ -> Word#'+ template: |-+ -- popCnt32 begin+ ~GENSYM[popCnt32][0] : block+ -- given a level and a depth, calculate the corresponding index into the+ -- intermediate array+ function ~GENSYM[depth2Index][1] (levels,depth : in natural) return natural is+ begin+ return (2 ** levels - 2 ** depth);+ end function;++ constant ~GENSYM[width][2] : natural := 32;+ constant ~GENSYM[levels][3] : natural := natural (ceil (log2 (real (~SYM[2]))));+ type ~GENSYM[popCnt_res_vec][4] is array (natural range <>) of unsigned(~SYM[3] downto 0);+ signal ~GENSYM[intermediate][5] : ~SYM[4](0 to (2*~SYM[2])-2);+ begin+ -- put input into the first half of the intermediate array+ ~GENSYM[make_array][6]: for ~GENSYM[i][7] in 0 to (~SYM[2] - 1) generate+ ~SYM[5](~SYM[7]) <= resize(~VAR[input][0](~SYM[7] downto ~SYM[7]),~SYM[3]+1);+ end generate;++ -- Create the tree of adders+ ~GENSYM[make_tree][8] : if ~SYM[3] /= 0 generate+ ~GENSYM[tree_depth][9] : for ~GENSYM[d][10] in ~SYM[3]-1 downto 0 generate+ ~GENSYM[tree_depth_loop][11] : for ~GENSYM[i][12] in 0 to (natural(2**~SYM[10]) - 1) generate+ ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+1)+~SYM[12]) <=+ ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+2)+(2*~SYM[12])) ++ ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+2)+(2*~SYM[12])+1);+ end generate;+ end generate;+ end generate;++ -- The last element of the intermediate array holds the result+ ~RESULT <= resize(~SYM[5]((2*~SYM[2])-2),~SIZE[~TYPO]);+ end block;+ -- popCnt32 end+- BlackBox:+ name: GHC.Prim.popCnt64#+ kind: Declaration+ type: 'popCnt64 :: Word#+ -> Word#'+ template: |-+ -- popCnt64 begin+ ~GENSYM[popCnt64][0] : block+ -- given a level and a depth, calculate the corresponding index into the+ -- intermediate array+ function ~GENSYM[depth2Index][1] (levels,depth : in natural) return natural is+ begin+ return (2 ** levels - 2 ** depth);+ end function;++ constant ~GENSYM[width][2] : natural := 64;+ constant ~GENSYM[levels][3] : natural := natural (ceil (log2 (real (~SYM[2]))));+ type ~GENSYM[popCnt_res_vec][4] is array (natural range <>) of unsigned(~SYM[3] downto 0);+ signal ~GENSYM[intermediate][5] : ~SYM[4](0 to (2*~SYM[2])-2);+ begin+ -- put input into the first half of the intermediate array+ ~GENSYM[make_array][6]: for ~GENSYM[i][7] in 0 to (~SYM[2] - 1) generate+ ~SYM[5](~SYM[7]) <= resize(~VAR[input][0](~SYM[7] downto ~SYM[7]),~SYM[3]+1);+ end generate;++ -- Create the tree of adders+ ~GENSYM[make_tree][8] : if ~SYM[3] /= 0 generate+ ~GENSYM[tree_depth][9] : for ~GENSYM[d][10] in ~SYM[3]-1 downto 0 generate+ ~GENSYM[tree_depth_loop][11] : for ~GENSYM[i][12] in 0 to (natural(2**~SYM[10]) - 1) generate+ ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+1)+~SYM[12]) <=+ ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+2)+(2*~SYM[12])) ++ ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+2)+(2*~SYM[12])+1);+ end generate;+ end generate;+ end generate;++ -- The last element of the intermediate array holds the result+ ~RESULT <= resize(~SYM[5]((2*~SYM[2])-2),~SIZE[~TYPO]);+ end block;+ -- popCnt64 end+- BlackBox:+ name: GHC.Prim.popCnt#+ kind: Declaration+ type: 'popCnt :: Word#+ -> Word#'+ template: |-+ -- popCnt begin+ ~GENSYM[popCnt][0] : block+ -- given a level and a depth, calculate the corresponding index into the+ -- intermediate array+ function ~GENSYM[depth2Index][1] (levels,depth : in natural) return natural is+ begin+ return (2 ** levels - 2 ** depth);+ end function;++ constant ~GENSYM[width][2] : natural := ~SIZE[~TYPO];+ constant ~GENSYM[levels][3] : natural := natural (ceil (log2 (real (~SYM[2]))));+ type ~GENSYM[popCnt_res_vec][4] is array (natural range <>) of unsigned(~SYM[3] downto 0);+ signal ~GENSYM[intermediate][5] : ~SYM[4](0 to (2*~SYM[2])-2);+ begin+ -- put input into the first half of the intermediate array+ ~GENSYM[make_array][6]: for ~GENSYM[i][7] in 0 to (~SYM[2] - 1) generate+ ~SYM[5](~SYM[7]) <= resize(~VAR[input][0](~SYM[7] downto ~SYM[7]),~SYM[3]+1);+ end generate;++ -- Create the tree of adders+ ~GENSYM[make_tree][8] : if ~SYM[3] /= 0 generate+ ~GENSYM[tree_depth][9] : for ~GENSYM[d][10] in ~SYM[3]-1 downto 0 generate+ ~GENSYM[tree_depth_loop][11] : for ~GENSYM[i][12] in 0 to (natural(2**~SYM[10]) - 1) generate+ ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+1)+~SYM[12]) <=+ ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+2)+(2*~SYM[12])) ++ ~SYM[5](~SYM[1](~SYM[3]+1,~SYM[10]+2)+(2*~SYM[12])+1);+ end generate;+ end generate;+ end generate;++ -- The last element of the intermediate array holds the result+ ~RESULT <= resize(~SYM[5]((2*~SYM[2])-2),~SIZE[~TYPO]);+ end block;+ -- popCnt end+- BlackBox:+ name: GHC.Prim.clz8#+ kind: Declaration+ type: 'clz8 :: Word# ->+ Word#'+ template: |-+ -- clz8 begin+ ~GENSYM[clz8][0] : block+ function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is+ begin+ case a is+ when "00" => return "10";+ when "01" => return "01";+ when "10" => return "00";+ when others => return "00";+ end case;+ end function;++ function ~GENSYM[clzi][2] (+ constant n : in natural;+ constant i : in unsigned) return unsigned is+ variable v : unsigned(i'length-1 downto 0):=i;+ begin+ if v(n-1+n)='0' then+ return (v(n-1+n) and v(n-1)) & '0' & v(2*n-2 downto n);+ else+ return (v(n-1+n) and v(n-1)) & not v(n-1) & v(n-2 downto 0);+ end if;+ end function;++ function ~GENSYM[clz8][3] (constant v : unsigned(0 to 7)) return unsigned is+ variable e : unsigned(0 to 7); -- 8+ variable a : unsigned(0 to 2*3-1); -- 6+ begin+ for i in 0 to 3 loop e(i*2 to i*2+1):=~SYM[1](v(i*2 to i*2+1)); end loop;+ for i in 0 to 1 loop a(i*3 to i*3+2):=~SYM[2](2,e(i*4 to i*4+3)); end loop;+ return ~SYM[2](3,a(0 to 5));+ end function;+ begin+ ~RESULT <= resize(~SYM[3](~ARG[0](7 downto 0)),~SIZE[~TYPO]);+ end block;+ -- clz8 end+- BlackBox:+ name: GHC.Prim.clz16#+ kind: Declaration+ type: 'clz16 :: Word#+ -> Word#'+ template: |-+ -- clz16 begin+ ~GENSYM[clz16][0] : block+ function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is+ begin+ case a is+ when "00" => return "10";+ when "01" => return "01";+ when "10" => return "00";+ when others => return "00";+ end case;+ end function;++ function ~GENSYM[clzi][2] (+ constant n : in natural;+ constant i : in unsigned) return unsigned is+ variable v : unsigned(i'length-1 downto 0):=i;+ begin+ if v(n-1+n)='0' then+ return (v(n-1+n) and v(n-1)) & '0' & v(2*n-2 downto n);+ else+ return (v(n-1+n) and v(n-1)) & not v(n-1) & v(n-2 downto 0);+ end if;+ end function;++ function ~GENSYM[clz16][3] (constant v : unsigned(0 to 15)) return unsigned is+ variable e : unsigned(0 to 15); -- 16+ variable a : unsigned(0 to 4*3-1); -- 12+ variable b : unsigned(0 to 2*4-1); -- 8+ begin+ for i in 0 to 7 loop e(i*2 to i*2+1):=~SYM[1](v(i*2 to i*2+1)); end loop;+ for i in 0 to 3 loop a(i*3 to i*3+2):=~SYM[2](2,e(i*4 to i*4+3)); end loop;+ for i in 0 to 1 loop b(i*4 to i*4+3):=~SYM[2](3,a(i*6 to i*6+5)); end loop;+ return ~SYM[2](4,b(0 to 7));+ end function;+ begin+ ~RESULT <= resize(~SYM[3](~ARG[0](15 downto 0)),~SIZE[~TYPO]);+ end block;+ -- clz16 end+- BlackBox:+ name: GHC.Prim.clz32#+ kind: Declaration+ type: 'clz32 :: Word#+ -> Word#'+ template: |-+ -- clz32 begin+ ~GENSYM[clz32][0] : block+ function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is+ begin+ case a is+ when "00" => return "10";+ when "01" => return "01";+ when "10" => return "00";+ when others => return "00";+ end case;+ end function;++ function ~GENSYM[clzi][2] (+ constant n : in natural;+ constant i : in unsigned) return unsigned is+ variable v : unsigned(i'length-1 downto 0):=i;+ begin+ if v(n-1+n)='0' then+ return (v(n-1+n) and v(n-1)) & '0' & v(2*n-2 downto n);+ else+ return (v(n-1+n) and v(n-1)) & not v(n-1) & v(n-2 downto 0);+ end if;+ end function;++ function ~GENSYM[clz32][3] (constant v : unsigned(0 to 31)) return unsigned is+ variable e : unsigned(0 to 31); -- 32+ variable a : unsigned(0 to 8*3-1); -- 24+ variable b : unsigned(0 to 4*4-1); -- 16+ variable c : unsigned(0 to 2*5-1); -- 10+ begin+ for i in 0 to 15 loop e(i*2 to i*2+1):=~SYM[1](v(i*2 to i*2+1)); end loop;+ for i in 0 to 7 loop a(i*3 to i*3+2):=~SYM[2](2,e(i*4 to i*4+3)); end loop;+ for i in 0 to 3 loop b(i*4 to i*4+3):=~SYM[2](3,a(i*6 to i*6+5)); end loop;+ for i in 0 to 1 loop c(i*5 to i*5+4):=~SYM[2](4,b(i*8 to i*8+7)); end loop;+ return ~SYM[2](5,c(0 to 9));+ end function;+ begin+ ~RESULT <= resize(~SYM[3](~ARG[0](31 downto 0)),~SIZE[~TYPO]);+ end block;+ -- clz32 end+- BlackBox:+ name: GHC.Prim.clz64#+ kind: Declaration+ type: 'clz64 :: Word#+ -> Word#'+ template: |-+ -- clz64 begin+ ~GENSYM[clz64][0] : block+ function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is+ begin+ case a is+ when "00" => return "10";+ when "01" => return "01";+ when "10" => return "00";+ when others => return "00";+ end case;+ end function;++ function ~GENSYM[clzi][2] (+ constant n : in natural;+ constant i : in unsigned) return unsigned is+ variable v : unsigned(i'length-1 downto 0):=i;+ begin+ if v(n-1+n)='0' then+ return (v(n-1+n) and v(n-1)) & '0' & v(2*n-2 downto n);+ else+ return (v(n-1+n) and v(n-1)) & not v(n-1) & v(n-2 downto 0);+ end if;+ end function;++ function ~GENSYM[clz64][3] (constant v : unsigned(0 to 63)) return unsigned is+ variable e : unsigned(0 to 63); -- 64+ variable a : unsigned(0 to 16*3-1); -- 48+ variable b : unsigned(0 to 8*4-1); -- 32+ variable c : unsigned(0 to 4*5-1); -- 20+ variable d : unsigned(0 to 2*6-1); -- 12+ begin+ for i in 0 to 31 loop e(i*2 to i*2+1):=~SYM[1](v(i*2 to i*2+1)); end loop;+ for i in 0 to 15 loop a(i*3 to i*3+2):=~SYM[2](2,e(i*4 to i*4+3)); end loop;+ for i in 0 to 7 loop b(i*4 to i*4+3):=~SYM[2](3,a(i*6 to i*6+5)); end loop;+ for i in 0 to 3 loop c(i*5 to i*5+4):=~SYM[2](4,b(i*8 to i*8+7)); end loop;+ for i in 0 to 1 loop d(i*6 to i*6+5):=~SYM[2](5,c(i*10 to i*10+9)); end loop;+ return ~SYM[2](6,d(0 to 11));+ end function;+ begin+ ~RESULT <= resize(~SYM[3](~ARG[0]),~SIZE[~TYPO]);+ end block;+ -- clz64 end+- BlackBox:+ name: GHC.Prim.clz#+ kind: Declaration+ type: 'clz :: Word# ->+ Word#'+ template: |-+ -- clz begin+ ~GENSYM[clz][0] : block+ function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is+ begin+ case a is+ when "00" => return "10";+ when "01" => return "01";+ when "10" => return "00";+ when others => return "00";+ end case;+ end function;++ function ~GENSYM[clzi][2] (+ constant n : in natural;+ constant i : in unsigned) return unsigned is+ variable v : unsigned(i'length-1 downto 0):=i;+ begin+ if v(n-1+n)='0' then+ return (v(n-1+n) and v(n-1)) & '0' & v(2*n-2 downto n);+ else+ return (v(n-1+n) and v(n-1)) & not v(n-1) & v(n-2 downto 0);+ end if;+ end function;+ ~IF ~IW64 ~THEN+ function ~GENSYM[clz64][3] (constant v : unsigned(0 to 63)) return unsigned is+ variable e : unsigned(0 to 63); -- 64+ variable a : unsigned(0 to 16*3-1); -- 48+ variable b : unsigned(0 to 8*4-1); -- 32+ variable c : unsigned(0 to 4*5-1); -- 20+ variable d : unsigned(0 to 2*6-1); -- 12+ begin+ for i in 0 to 31 loop e(i*2 to i*2+1):=~SYM[1](v(i*2 to i*2+1)); end loop;+ for i in 0 to 15 loop a(i*3 to i*3+2):=~SYM[2](2,e(i*4 to i*4+3)); end loop;+ for i in 0 to 7 loop b(i*4 to i*4+3):=~SYM[2](3,a(i*6 to i*6+5)); end loop;+ for i in 0 to 3 loop c(i*5 to i*5+4):=~SYM[2](4,b(i*8 to i*8+7)); end loop;+ for i in 0 to 1 loop d(i*6 to i*6+5):=~SYM[2](5,c(i*10 to i*10+9)); end loop;+ return ~SYM[2](6,d(0 to 11));+ end function;+ ~ELSE+ function ~GENSYM[clz32][4] (constant v : unsigned(0 to 31)) return unsigned is+ variable e : unsigned(0 to 31); -- 32+ variable a : unsigned(0 to 8*3-1); -- 24+ variable b : unsigned(0 to 4*4-1); -- 16+ variable c : unsigned(0 to 2*5-1); -- 10+ begin+ for i in 0 to 15 loop e(i*2 to i*2+1):=~SYM[1](v(i*2 to i*2+1)); end loop;+ for i in 0 to 7 loop a(i*3 to i*3+2):=~SYM[2](2,e(i*4 to i*4+3)); end loop;+ for i in 0 to 3 loop b(i*4 to i*4+3):=~SYM[2](3,a(i*6 to i*6+5)); end loop;+ for i in 0 to 1 loop c(i*5 to i*5+4):=~SYM[2](4,b(i*8 to i*8+7)); end loop;+ return ~SYM[2](5,c(0 to 9));+ end function;+ ~FI+ begin+ ~IF ~IW64 ~THEN+ ~RESULT <= resize(~SYM[3](~ARG[0]),~SIZE[~TYPO]);+ ~ELSE+ ~RESULT <= resize(~SYM[4](~ARG[0]),~SIZE[~TYPO]);+ ~FI+ end block;+ -- clz end+- BlackBox:+ name: GHC.Prim.ctz8#+ kind: Declaration+ type: 'ctz8 :: Word# ->+ Word#'+ template: |-+ -- ctz8 begin+ ~GENSYM[ctz8][0] : block+ function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is+ begin+ case a is+ when "00" => return "10";+ when "01" => return "01";+ when "10" => return "00";+ when others => return "00";+ end case;+ end function;++ function ~GENSYM[clzi][2] (+ constant n : in natural;+ constant i : in unsigned) return unsigned is+ variable v : unsigned(i'length-1 downto 0):=i;+ begin+ if v(n-1+n)='0' then+ return (v(n-1+n) and v(n-1)) & '0' & v(2*n-2 downto n);+ else+ return (v(n-1+n) and v(n-1)) & not v(n-1) & v(n-2 downto 0);+ end if;+ end function;++ function ~GENSYM[clz8][3] (constant v : unsigned(0 to 7)) return unsigned is+ variable e : unsigned(0 to 7); -- 8+ variable a : unsigned(0 to 2*3-1); -- 6+ begin+ for i in 0 to 3 loop e(i*2 to i*2+1):=~SYM[1](v(i*2 to i*2+1)); end loop;+ for i in 0 to 1 loop a(i*3 to i*3+2):=~SYM[2](2,e(i*4 to i*4+3)); end loop;+ return ~SYM[2](3,a(0 to 5));+ end function;++ signal ~GENSYM[w_reversed][5] : ~TYP[0];+ begin+ ~GENSYM[reverse_loop][6] : for ~GENSYM[n][7] in ~VAR[w][0]'range generate+ ~SYM[5](~VAR[w][0]'high - ~SYM[7]) <= ~VAR[w][0](~SYM[7]);+ end generate;+ ~IF ~IW64 ~THEN+ ~RESULT <= resize(~SYM[3](~SYM[5](63 downto 56)),~SIZE[~TYPO]);+ ~ELSE+ ~RESULT <= resize(~SYM[3](~SYM[5](31 downto 24)),~SIZE[~TYPO]);+ ~FI+ end block;+ -- ctz8 end+- BlackBox:+ name: GHC.Prim.ctz16#+ kind: Declaration+ type: 'ctz16 :: Word#+ -> Word#'+ template: |-+ -- ctz16 begin+ ~GENSYM[ctz16][0] : block+ function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is+ begin+ case a is+ when "00" => return "10";+ when "01" => return "01";+ when "10" => return "00";+ when others => return "00";+ end case;+ end function;++ function ~GENSYM[clzi][2] (+ constant n : in natural;+ constant i : in unsigned) return unsigned is+ variable v : unsigned(i'length-1 downto 0):=i;+ begin+ if v(n-1+n)='0' then+ return (v(n-1+n) and v(n-1)) & '0' & v(2*n-2 downto n);+ else+ return (v(n-1+n) and v(n-1)) & not v(n-1) & v(n-2 downto 0);+ end if;+ end function;++ function ~GENSYM[clz16][3] (constant v : unsigned(0 to 15)) return unsigned is+ variable e : unsigned(0 to 15); -- 16+ variable a : unsigned(0 to 4*3-1); -- 12+ variable b : unsigned(0 to 2*4-1); -- 8+ begin+ for i in 0 to 7 loop e(i*2 to i*2+1):=~SYM[1](v(i*2 to i*2+1)); end loop;+ for i in 0 to 3 loop a(i*3 to i*3+2):=~SYM[2](2,e(i*4 to i*4+3)); end loop;+ for i in 0 to 1 loop b(i*4 to i*4+3):=~SYM[2](3,a(i*6 to i*6+5)); end loop;+ return ~SYM[2](4,b(0 to 7));+ end function;++ signal ~GENSYM[w_reversed][5] : ~TYP[0];+ begin+ ~GENSYM[reverse_loop][6] : for ~GENSYM[n][7] in ~VAR[w][0]'range generate+ ~SYM[5](~VAR[w][0]'high - ~SYM[7]) <= ~VAR[w][0](~SYM[7]);+ end generate;+ ~IF ~IW64 ~THEN+ ~RESULT <= resize(~SYM[3](~SYM[5](63 downto 48)),~SIZE[~TYPO]);+ ~ELSE+ ~RESULT <= resize(~SYM[3](~SYM[5](31 downto 16)),~SIZE[~TYPO]);+ ~FI+ end block;+ -- ctz16 end+- BlackBox:+ name: GHC.Prim.ctz32#+ kind: Declaration+ type: 'ctz32 :: Word#+ -> Word#'+ template: |-+ -- ctz32 begin+ ~GENSYM[ctz32][0] : block+ function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is+ begin+ case a is+ when "00" => return "10";+ when "01" => return "01";+ when "10" => return "00";+ when others => return "00";+ end case;+ end function;++ function ~GENSYM[clzi][2] (+ constant n : in natural;+ constant i : in unsigned) return unsigned is+ variable v : unsigned(i'length-1 downto 0):=i;+ begin+ if v(n-1+n)='0' then+ return (v(n-1+n) and v(n-1)) & '0' & v(2*n-2 downto n);+ else+ return (v(n-1+n) and v(n-1)) & not v(n-1) & v(n-2 downto 0);+ end if;+ end function;++ function ~GENSYM[clz32][3] (constant v : unsigned(0 to 31)) return unsigned is+ variable e : unsigned(0 to 31); -- 32+ variable a : unsigned(0 to 8*3-1); -- 24+ variable b : unsigned(0 to 4*4-1); -- 16+ variable c : unsigned(0 to 2*5-1); -- 10+ begin+ for i in 0 to 15 loop e(i*2 to i*2+1):=~SYM[1](v(i*2 to i*2+1)); end loop;+ for i in 0 to 7 loop a(i*3 to i*3+2):=~SYM[2](2,e(i*4 to i*4+3)); end loop;+ for i in 0 to 3 loop b(i*4 to i*4+3):=~SYM[2](3,a(i*6 to i*6+5)); end loop;+ for i in 0 to 1 loop c(i*5 to i*5+4):=~SYM[2](4,b(i*8 to i*8+7)); end loop;+ return ~SYM[2](5,c(0 to 9));+ end function;++ signal ~GENSYM[w_reversed][5] : ~TYP[0];+ begin+ ~GENSYM[reverse_loop][6] : for ~GENSYM[n][7] in ~VAR[w][0]'range generate+ ~SYM[5](~VAR[w][0]'high - ~SYM[7]) <= ~VAR[w][0](~SYM[3]);+ end generate;+ ~IF ~IW64 ~THEN+ ~RESULT <= resize(~SYM[3](~SYM[5](63 downto 32)),~SIZE[~TYPO]);+ ~ELSE+ ~RESULT <= resize(~SYM[3](~SYM[5]),~SIZE[~TYPO]);+ ~FI+ end block;+ -- ctz32 end+- BlackBox:+ name: GHC.Prim.ctz64#+ kind: Declaration+ type: 'ctz64 :: Word#+ -> Word#'+ template: |-+ -- ctz64 begin+ ~GENSYM[ctz64][0] : block+ function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is+ begin+ case a is+ when "00" => return "10";+ when "01" => return "01";+ when "10" => return "00";+ when others => return "00";+ end case;+ end function;++ function ~GENSYM[clzi][2] (+ constant n : in natural;+ constant i : in unsigned) return unsigned is+ variable v : unsigned(i'length-1 downto 0):=i;+ begin+ if v(n-1+n)='0' then+ return (v(n-1+n) and v(n-1)) & '0' & v(2*n-2 downto n);+ else+ return (v(n-1+n) and v(n-1)) & not v(n-1) & v(n-2 downto 0);+ end if;+ end function;++ function ~GENSYM[clz64][3] (constant v : unsigned(0 to 63)) return unsigned is+ variable e : unsigned(0 to 63); -- 64+ variable a : unsigned(0 to 16*3-1); -- 48+ variable b : unsigned(0 to 8*4-1); -- 32+ variable c : unsigned(0 to 4*5-1); -- 20+ variable d : unsigned(0 to 2*6-1); -- 12+ begin+ for i in 0 to 31 loop e(i*2 to i*2+1):=~SYM[1](v(i*2 to i*2+1)); end loop;+ for i in 0 to 15 loop a(i*3 to i*3+2):=~SYM[2](2,e(i*4 to i*4+3)); end loop;+ for i in 0 to 7 loop b(i*4 to i*4+3):=~SYM[2](3,a(i*6 to i*6+5)); end loop;+ for i in 0 to 3 loop c(i*5 to i*5+4):=~SYM[2](4,b(i*8 to i*8+7)); end loop;+ for i in 0 to 1 loop d(i*6 to i*6+5):=~SYM[2](5,c(i*10 to i*10+9)); end loop;+ return ~SYM[2](6,d(0 to 11));+ end function;++ signal ~GENSYM[w_reversed][5] : ~TYP[0];+ begin+ ~GENSYM[reverse_loop][6] : for ~GENSYM[n][7] in ~VAR[w][0]'range generate+ ~SYM[5](~VAR[w][0]'high - ~SYM[7]) <= ~VAR[w][0](~SYM[7]);+ end generate;++ ~RESULT <= resize(~SYM[3](~SYM[5]),~SIZE[~TYPO]);+ end block;+ -- ctz64 end+- BlackBox:+ name: GHC.Prim.ctz#+ kind: Declaration+ type: 'ctz :: Word# ->+ Word#'+ template: |-+ -- ctz begin+ ~GENSYM[ctz][0] : block+ function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is+ begin+ case a is+ when "00" => return "10";+ when "01" => return "01";+ when "10" => return "00";+ when others => return "00";+ end case;+ end function;++ function ~GENSYM[clzi][2] (+ constant n : in natural;+ constant i : in unsigned) return unsigned is+ variable v : unsigned(i'length-1 downto 0):=i;+ begin+ if v(n-1+n)='0' then+ return (v(n-1+n) and v(n-1)) & '0' & v(2*n-2 downto n);+ else+ return (v(n-1+n) and v(n-1)) & not v(n-1) & v(n-2 downto 0);+ end if;+ end function;++ ~IF ~IW64 ~THEN+ function ~GENSYM[clz64][3] (constant v : unsigned(0 to 63)) return unsigned is+ variable e : unsigned(0 to 63); -- 64+ variable a : unsigned(0 to 16*3-1); -- 48+ variable b : unsigned(0 to 8*4-1); -- 32+ variable c : unsigned(0 to 4*5-1); -- 20+ variable d : unsigned(0 to 2*6-1); -- 12+ begin+ for i in 0 to 31 loop e(i*2 to i*2+1):=~SYM[1](v(i*2 to i*2+1)); end loop;+ for i in 0 to 15 loop a(i*3 to i*3+2):=~SYM[2](2,e(i*4 to i*4+3)); end loop;+ for i in 0 to 7 loop b(i*4 to i*4+3):=~SYM[2](3,a(i*6 to i*6+5)); end loop;+ for i in 0 to 3 loop c(i*5 to i*5+4):=~SYM[2](4,b(i*8 to i*8+7)); end loop;+ for i in 0 to 1 loop d(i*6 to i*6+5):=~SYM[2](5,c(i*10 to i*10+9)); end loop;+ return ~SYM[2](6,d(0 to 11));+ end function;+ ~ELSE+ function ~GENSYM[clz32][4] (constant v : unsigned(0 to 31)) return unsigned is+ variable e : unsigned(0 to 31); -- 32+ variable a : unsigned(0 to 8*3-1); -- 24+ variable b : unsigned(0 to 4*4-1); -- 16+ variable c : unsigned(0 to 2*5-1); -- 10+ begin+ for i in 0 to 15 loop e(i*2 to i*2+1):=~SYM[1](v(i*2 to i*2+1)); end loop;+ for i in 0 to 7 loop a(i*3 to i*3+2):=~SYM[2](2,e(i*4 to i*4+3)); end loop;+ for i in 0 to 3 loop b(i*4 to i*4+3):=~SYM[2](3,a(i*6 to i*6+5)); end loop;+ for i in 0 to 1 loop c(i*5 to i*5+4):=~SYM[2](4,b(i*8 to i*8+7)); end loop;+ return ~SYM[2](5,c(0 to 9));+ end function;+ ~FI++ signal ~GENSYM[w_reversed][6] : ~TYP[0];+ begin+ ~GENSYM[reverse_loop][7] : for ~GENSYM[n][8] in ~VAR[w][0]'range generate+ ~SYM[6](~VAR[w][0]'high - ~SYM[8]) <= ~VAR[w][0](~SYM[8]);+ end generate;+ ~IF ~IW64 ~THEN+ ~RESULT <= resize(~SYM[3](~SYM[6]),~SIZE[~TYPO]);+ ~ELSE+ ~RESULT <= resize(~SYM[4](~SYM[6]),~SIZE[~TYPO]);+ ~FI+ end block;+ -- ctz end+- BlackBox:+ name: GHC.Prim.byteSwap16#+ kind: Declaration+ type: 'byteSwap16# ::+ Word# -> Word#'+ template: |-+ -- byteSwap16 begin~IF ~IW64 ~THEN+ ~RESULT <= ~VAR[w][0](63 downto 16) & ~VAR[w][0](7 downto 0) & ~VAR[w][0](15 downto 8);~ELSE+ ~RESULT <= ~VAR[w][0](31 downto 16) & ~VAR[w][0](7 downto 0) & ~VAR[w][0](15 downto 8);~FI+ -- byteSwap16 end+ workInfo: Never+- BlackBox:+ name: GHC.Prim.byteSwap32#+ kind: Declaration+ type: 'byteSwap32# ::+ Word# -> Word#'+ template: |-+ -- byteSwap32 begin~IF ~IW64 ~THEN+ ~RESULT <= ~VAR[w][0](63 downto 32) & ~VAR[w][0](7 downto 0 ) & ~VAR[w][0](15 downto 8)+ & ~VAR[w][0](23 downto 16) & ~VAR[w][0](31 downto 24);~ELSE+ ~RESULT <= ~VAR[w][0](7 downto 0 ) & ~VAR[w][0](15 downto 8)+ & ~VAR[w][0](23 downto 16) & ~VAR[w][0](31 downto 24);~FI+ -- byteSwap32 end+ workInfo: Never+- BlackBox:+ name: GHC.Prim.byteSwap64#+ kind: Declaration+ type: 'byteSwap64# ::+ Word# -> Word#'+ template: |-+ -- byteSwap64 begin+ ~RESULT <= ~VAR[w][0](7 downto 0 ) & ~VAR[w][0](15 downto 8)+ & ~VAR[w][0](23 downto 16) & ~VAR[w][0](31 downto 24)+ & ~VAR[w][0](39 downto 32) & ~VAR[w][0](47 downto 40)+ & ~VAR[w][0](55 downto 48) & ~VAR[w][0](63 downto 56);+ -- byteSwap64 end+ workInfo: Never+- BlackBox:+ name: GHC.Prim.byteSwap#+ kind: Declaration+ type: 'byteSwap# :: Word#+ -> Word#'+ template: |-+ -- byteSwap begin ~IF ~IW64 ~THEN+ ~RESULT <= ~VAR[w][0](7 downto 0 ) & ~VAR[w][0](15 downto 8)+ & ~VAR[w][0](23 downto 16) & ~VAR[w][0](31 downto 24)+ & ~VAR[w][0](39 downto 32) & ~VAR[w][0](47 downto 40)+ & ~VAR[w][0](55 downto 48) & ~VAR[w][0](63 downto 56);~ELSE+ ~RESULT <= ~VAR[w][0](7 downto 0 ) & ~VAR[w][0](15 downto 8)+ & ~VAR[w][0](23 downto 16) & ~VAR[w][0](31 downto 24);~FI+ -- byteSwap end+ workInfo: Never+- BlackBox:+ name: GHC.Prim.narrow8Int#+ kind: Expression+ type: 'narrow8Int# ::+ Int# -> Int#'+ template: resize(~VAR[i][0](7 downto 0),~SIZE[~TYPO])+ workInfo: Never+- BlackBox:+ name: GHC.Prim.narrow16Int#+ kind: Expression+ type: 'narrow16Int# ::+ Int# -> Int#'+ template: resize(~VAR[i][0](15 downto 0),~SIZE[~TYPO])+ workInfo: Never+- BlackBox:+ name: GHC.Prim.narrow32Int#+ kind: Expression+ type: 'narrow32Int# ::+ Int# -> Int#'+ template: resize(~VAR[i][0](31 downto 0),~SIZE[~TYPO])+ workInfo: Never+- BlackBox:+ name: GHC.Prim.narrow8Word#+ kind: Expression+ type: 'narrow8Word# ::+ Word# -> Word#'+ template: resize(~VAR[w][0](7 downto 0),~SIZE[~TYPO])+ workInfo: Never+- BlackBox:+ name: GHC.Prim.narrow16Word#+ kind: Expression+ type: 'narrow16Word# ::+ Word# -> Word#'+ template: resize(~VAR[w][0](15 downto 0),~SIZE[~TYPO])+ workInfo: Never+- BlackBox:+ name: GHC.Prim.narrow32Word#+ kind: Expression+ type: 'narrow32Word# ::+ Word# -> Word#'+ template: resize(~VAR[w][0](31 downto 0),~SIZE[~TYPO])+ workInfo: Never+- BlackBox:+ name: GHC.Prim.bitReverse#+ kind: Declaration+ type: 'bitReverse# ::+ Word# -> Word#'+ template: |-+ -- bitReverse begin+ ~GENSYM[bitReverse][0] : for ~GENSYM[i][1] in 0 to ~IF ~IW64 ~THEN 63 ~ELSE 31 ~FI generate+ begin+ ~RESULT(~SYM[1]) <= ~VAR[x][0](~IF ~IW64 ~THEN 63 ~ELSE 31 ~FI-~SYM[1]);+ end generate;+ -- bitReverse end+ workInfo: Never+- BlackBox:+ name: GHC.Prim.bitReverse8#+ kind: Declaration+ type: 'bitReverse8# ::+ Word# -> Word#'+ template: |-+ -- bitReverse8 begin+ ~GENSYM[bitReverse8][0] : for ~GENSYM[i][1] in 0 to 7 generate+ begin+ ~RESULT(~SYM[1]) <= ~VAR[x][0](7-~SYM[1]);+ end generate;+ -- bitReverse8 end+ workInfo: Never+- BlackBox:+ name: GHC.Prim.bitReverse16#+ kind: Declaration+ type: 'bitReverse16# ::+ Word# -> Word#'+ template: |-+ -- bitReverse16 begin+ ~GENSYM[bitReverse16][0] : for ~GENSYM[i][1] in 0 to 15 generate+ begin+ ~RESULT(~SYM[1]) <= ~VAR[x][0](15-~SYM[1]);+ end generate;+ -- bitReverse16 end+ workInfo: Never+- BlackBox:+ name: GHC.Prim.bitReverse32#+ kind: Declaration+ type: 'bitReverse32# ::+ Word# -> Word#'+ template: |-+ -- bitReverse32 begin+ ~GENSYM[bitReverse32][0] : for ~GENSYM[i][1] in 0 to 31 generate+ begin+ ~RESULT(~SYM[1]) <= ~VAR[x][0](31-~SYM[1]);+ end generate;+ -- bitReverse32 end+ workInfo: Never+- BlackBox:+ name: GHC.Prim.bitReverse64#+ kind: Declaration+ type: 'bitReverse64# ::+ Word# -> Word#'+ template: |-+ -- bitReverse64 begin+ ~GENSYM[bitReverse64][0] : for ~GENSYM[i][1] in 0 to 63 generate+ begin+ ~RESULT(~SYM[1]) <= ~VAR[x][0](63-~SYM[1]);+ end generate;+ -- bitReverse64 end+ workInfo: Never+- BlackBox:+ name: GHC.Prim.quotInt#+ kind: Declaration+ type: 'quotInt# :: Int#+ -> Int# -> Int#'+ template: |-+ ~RESULT <= ~ARG[0] / ~ARG[1]+ -- pragma translate_off+ when (~ARG[1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;+- BlackBox:+ name: GHC.Prim.quotWord#+ kind: Declaration+ type: 'quotWord# :: Word#+ -> Word# -> Word#'+ template: |-+ ~RESULT <= ~ARG[0] / ~ARG[1]+ -- pragma translate_off+ when (~ARG[1] /= 0) else (others => 'X')+ -- pragma translate_on+ ;
− prims/vhdl/GHC_Word.primitives
@@ -1,33 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Word.W8#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "W8# :: Word# -> Word8"- , "template" : "resize(~ARG[0],8)"- }- }-, { "BlackBox" :- { "name" : "GHC.Word.W16#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "W16# :: Word# -> Word16"- , "template" : "resize(~ARG[0],16)"- }- }-, { "BlackBox" :- { "name" : "GHC.Word.W32#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "W32# :: Word# -> Word32"- , "template" : "resize(~ARG[0],32)"- }- }-, { "BlackBox" :- { "name" : "GHC.Word.W64#"- , "workInfo" : "Never"- , "kind" : "Expression"- , "type" : "W64# :: Word# -> Word64"- , "template" : "resize(~ARG[0],64)"- }- }-]
+ prims/vhdl/GHC_Word.primitives.yaml view
@@ -0,0 +1,28 @@+- BlackBox:+ name: GHC.Word.W8#+ kind: Expression+ type: 'W8# :: Word# ->+ Word8'+ template: resize(~ARG[0],8)+ workInfo: Never+- BlackBox:+ name: GHC.Word.W16#+ kind: Expression+ type: 'W16# :: Word# ->+ Word16'+ template: resize(~ARG[0],16)+ workInfo: Never+- BlackBox:+ name: GHC.Word.W32#+ kind: Expression+ type: 'W32# :: Word# ->+ Word32'+ template: resize(~ARG[0],32)+ workInfo: Never+- BlackBox:+ name: GHC.Word.W64#+ kind: Expression+ type: 'W64# :: Word# ->+ Word64'+ template: resize(~ARG[0],64)+ workInfo: Never
src/Clash/Backend.hs view
@@ -1,8 +1,9 @@ {-| Copyright : (C) 2015-2016, University of Twente,- 2017 , Myrtle Software Ltd, Google Inc.+ 2017 , Myrtle Software Ltd, Google Inc.,+ 2021-2022, QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> -} {-# LANGUAGE CPP #-}@@ -10,8 +11,9 @@ module Clash.Backend where +import Data.HashMap.Strict (HashMap, empty) import Data.HashSet (HashSet)-import Data.Semigroup.Monad (Mon (..))+import Data.Monoid (Ap) import Data.Text (Text) import qualified Data.Text.Lazy as LT import Control.Monad.State (State)@@ -23,9 +25,11 @@ import SrcLoc (SrcSpan) #endif +import Clash.Driver.Types (ClashOpts) import {-# SOURCE #-} Clash.Netlist.Types import Clash.Netlist.BlackBox.Types +import Clash.Signal.Internal (VDomainConfiguration) import Clash.Annotations.Primitive (HDL) #ifdef CABAL@@ -61,6 +65,8 @@ -- | Is '-fclash-aggresive-x-optimization-blackbox' set? newtype AggressiveXOptBB = AggressiveXOptBB Bool +-- | Is '-fclash-render-enums' set?+newtype RenderEnums = RenderEnums Bool -- | Kind of a HDL type. Used to determine whether types need conversions in -- order to cross top entity boundaries.@@ -75,16 +81,14 @@ -- ^ User defined type that's not interchangeable with any others, even if -- the underlying structures are the same. Similar to an ADT in Haskell. +type DomainMap = HashMap Text VDomainConfiguration++emptyDomainMap :: DomainMap+emptyDomainMap = empty+ class HasIdentifierSet state => Backend state where -- | Initial state for state monad- initBackend- :: Int- -> HdlSyn- -> Bool- -> PreserveCase- -> Maybe (Maybe Int)- -> AggressiveXOptBB- -> state+ initBackend :: ClashOpts -> state -- | What HDL is the backend generating hdlKind :: state -> HDL@@ -103,35 +107,35 @@ extractTypes :: state -> HashSet HWType -- | Generate HDL for a Netlist component- genHDL :: ModName -> SrcSpan -> IdentifierSet -> Component -> Mon (State state) ((String, Doc),[(String,Doc)])+ genHDL :: ModName -> SrcSpan -> IdentifierSet -> Component -> Ap (State state) ((String, Doc),[(String,Doc)]) -- | Generate a HDL package containing type definitions for the given HWTypes- mkTyPackage :: ModName -> [HWType] -> Mon (State state) [(String, Doc)]+ mkTyPackage :: ModName -> [HWType] -> Ap (State state) [(String, Doc)] -- | Convert a Netlist HWType to a target HDL type- hdlType :: Usage -> HWType -> Mon (State state) Doc+ hdlType :: Usage -> HWType -> Ap (State state) Doc -- | Query what kind of type a given HDL type is hdlHWTypeKind :: HWType -> State state HWKind -- | Convert a Netlist HWType to an HDL error value for that type- hdlTypeErrValue :: HWType -> Mon (State state) Doc+ hdlTypeErrValue :: HWType -> Ap (State state) Doc -- | Convert a Netlist HWType to the root of a target HDL type- hdlTypeMark :: HWType -> Mon (State state) Doc+ hdlTypeMark :: HWType -> Ap (State state) Doc -- | Create a record selector- hdlRecSel :: HWType -> Int -> Mon (State state) Doc+ hdlRecSel :: HWType -> Int -> Ap (State state) Doc -- | Create a signal declaration from an identifier (Text) and Netlist HWType- hdlSig :: LT.Text -> HWType -> Mon (State state) Doc+ hdlSig :: LT.Text -> HWType -> Ap (State state) Doc -- | Create a generative block statement marker genStmt :: Bool -> State state Doc -- | Turn a Netlist Declaration to a HDL concurrent block- inst :: Declaration -> Mon (State state) (Maybe Doc)+ inst :: Declaration -> Ap (State state) (Maybe Doc) -- | Turn a Netlist expression into a HDL expression expr :: Bool -- ^ Enclose in parentheses? -> Expr -- ^ Expr to convert- -> Mon (State state) Doc+ -> Ap (State state) Doc -- | Bit-width of Int,Word,Integer iwWidth :: State state Int -- | Convert to a bit-vector- toBV :: HWType -> LT.Text -> Mon (State state) Doc+ toBV :: HWType -> LT.Text -> Ap (State state) Doc -- | Convert from a bit-vector- fromBV :: HWType -> LT.Text -> Mon (State state) Doc+ fromBV :: HWType -> LT.Text -> Ap (State state) Doc -- | Synthesis tool we're generating HDL for hdlSyn :: State state HdlSyn -- | setModName@@ -141,7 +145,7 @@ -- | getSrcSpan getSrcSpan :: State state SrcSpan -- | Block of declarations- blockDecl :: Identifier -> [Declaration] -> Mon (State state) Doc+ blockDecl :: Identifier -> [Declaration] -> Ap (State state) Doc addIncludes :: [(String, Doc)] -> State state () addLibraries :: [LT.Text] -> State state () addImports :: [LT.Text] -> State state ()@@ -152,3 +156,9 @@ ifThenElseExpr :: state -> Bool -- | Whether -fclash-aggressive-x-optimization-blackboxes was set aggressiveXOptBB :: State state AggressiveXOptBB+ -- | Whether -fclash-no-render-enums was set+ renderEnums :: State state RenderEnums+ -- | All the domain configurations of design+ domainConfigurations :: State state DomainMap+ -- | Set the domain configurations+ setDomainConfigurations :: DomainMap -> state -> state
src/Clash/Backend/SystemVerilog.hs view
@@ -1,8 +1,9 @@ {-| Copyright : (C) 2015-2016, University of Twente,- 2017-2018, Google Inc.+ 2017-2018, Google Inc.,+ 2021-2022, QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Generate SystemVerilog for assorted Netlist datatypes -}@@ -20,7 +21,11 @@ import Control.Lens hiding (Indexed) import Control.Monad (forM,liftM,zipWithM) import Control.Monad.State (State)+import Data.Bifunctor (first) import Data.Bits (Bits, testBit)+import qualified Data.ByteString.Char8 as B8+import Data.Coerce (coerce)+import Data.Function (on) import Data.HashMap.Lazy (HashMap) import qualified Data.HashMap.Lazy as HashMap import Data.HashSet (HashSet)@@ -28,10 +33,8 @@ import Data.List (nub, nubBy) import Data.List.Extra ((<:>), zipEqual) import Data.Maybe (catMaybes,fromMaybe,mapMaybe)-#if !MIN_VERSION_base(4,11,0)-import Data.Monoid hiding (Sum, Product)-#endif-import Data.Semigroup.Monad+import Data.Monoid (Ap(Ap))+import Data.Monoid.Extra () import qualified Data.Text.Lazy as Text import qualified Data.Text as TextS import Data.Text.Prettyprint.Doc.Extra@@ -50,6 +53,8 @@ import Clash.Backend import Clash.Backend.Verilog (bits, bit_char, encodingNote, exprLit, include, noEmptyInit, uselibs)+import Clash.Driver.Types (ClashOpts(..))+import Clash.Explicit.BlockRam.Internal (unpackNats) import Clash.Netlist.BlackBox.Types (HdlSyn (..)) import Clash.Netlist.BlackBox.Util (extractLiterals, renderBlackBox, renderFilePath)@@ -58,7 +63,7 @@ import Clash.Netlist.Util import Clash.Signal.Internal (ActiveEdge (..)) import Clash.Util- (SrcSpan, noSrcSpan, curLoc, makeCached, first, on, indexNote)+ (SrcSpan, noSrcSpan, curLoc, makeCached, indexNote) import Clash.Util.Graph (reverseTopSort) -- | State for the 'Clash.Backend.SystemVerilog.SystemVerilogM' monad:@@ -85,6 +90,8 @@ , _hdlsyn :: HdlSyn , _undefValue :: Maybe (Maybe Int) , _aggressiveXOptBB_ :: AggressiveXOptBB+ , _renderEnums_ :: RenderEnums+ , _domainConfigurations_ :: DomainMap } makeLenses ''SystemVerilogState@@ -93,12 +100,12 @@ identifierSet = idSeen instance Backend SystemVerilogState where- initBackend w hdlsyn_ esc lw undefVal xOpt = SystemVerilogState {- _tyCache=HashSet.empty+ initBackend opts = SystemVerilogState+ { _tyCache=HashSet.empty , _nameCache=HashMap.empty , _genDepth=0 , _modNm=""- , _idSeen=Id.emptyIdentifierSet esc lw SystemVerilog+ , _idSeen=Id.emptyIdentifierSet (opt_escapedIds opts) (opt_lowerCaseBasicIds opts) SystemVerilog , _oports=[] , _srcSpan=noSrcSpan , _includes=[]@@ -107,10 +114,12 @@ , _dataFiles=[] , _memoryDataFiles=[] , _tyPkgCtx=False- , _intWidth=w- , _hdlsyn=hdlsyn_- , _undefValue=undefVal- , _aggressiveXOptBB_=xOpt+ , _intWidth=opt_intWidth opts+ , _hdlsyn=opt_hdlSyn opts+ , _undefValue=opt_forceUndefined opts+ , _aggressiveXOptBB_=coerce (opt_aggressiveXOptBB opts)+ , _renderEnums_=coerce (opt_renderEnums opts)+ , _domainConfigurations_=emptyDomainMap } hdlKind = const SystemVerilog primDirs = const $ do root <- primsRoot@@ -128,6 +137,7 @@ Vector {} -> pure UserType RTree {} -> pure UserType Product {} -> pure UserType+ MemBlob {} -> pure UserType BiDirectional _ ty -> hdlHWTypeKind ty Annotated _ ty -> hdlHWTypeKind ty _ -> pure PrimitiveType@@ -175,8 +185,11 @@ getMemoryDataFiles = use memoryDataFiles ifThenElseExpr _ = True aggressiveXOptBB = use aggressiveXOptBB_+ renderEnums = use renderEnums_+ domainConfigurations = use domainConfigurations_+ setDomainConfigurations confs s = s {_domainConfigurations_ = confs} -type SystemVerilogM a = Mon (State SystemVerilogState) a+type SystemVerilogM a = Ap (State SystemVerilogState) a -- | Generate SystemVerilog for a Netlist component genSystemVerilog@@ -191,11 +204,11 @@ -- -- TODO: Collect all type names up front, to prevent relatively costly union. -- TODO: Investigate whether type names / signal names collide in the first place- Mon $ idSeen %= Id.union seen+ Ap $ idSeen %= Id.union seen - Mon $ setSrcSpan sp+ Ap $ setSrcSpan sp v <- verilog- incs <- Mon $ use includes+ incs <- Ap $ use includes return ((TextS.unpack (Id.toText cName), v), incs) where cName = componentName c@@ -211,7 +224,7 @@ -- | Generate a SystemVerilog package containing type definitions for the given HWTypes mkTyPackage_ :: TextS.Text -> [HWType] -> SystemVerilogM [(String,Doc)] mkTyPackage_ modName hwtys = do- Mon (tyPkgCtx .= True)+ Ap (tyPkgCtx .= True) normTys <- nub <$> mapM (normaliseType) (hwtys ++ usedTys) let needsDec = nubBy eqReprTy $ normTys@@ -224,7 +237,7 @@ indent 2 packageDec <> line <> indent 2 funDecs <> line <> "endpackage" <+> colon <+> modNameD <> "_types"- Mon (tyPkgCtx .= False)+ Ap (tyPkgCtx .= False) return pkg where modNameD = stringS modName@@ -286,13 +299,14 @@ normaliseType :: HWType -> SystemVerilogM HWType normaliseType (Annotated _ ty) = normaliseType ty normaliseType (Vector n ty) = Vector n <$> (normaliseType ty)+normaliseType (MemBlob n m) = return (Vector n (BitVector m)) normaliseType (RTree d ty) = RTree d <$> (normaliseType ty) normaliseType (Product nm lbls tys) = Product nm lbls <$> (mapM normaliseType tys) normaliseType ty@(SP _ elTys) = do- Mon $ mapM_ ((tyCache %=) . HashSet.insert) (concatMap snd elTys)+ Ap $ mapM_ ((tyCache %=) . HashSet.insert) (concatMap snd elTys) return (BitVector (typeSize ty)) normaliseType (CustomSP _ _dataRepr size elTys) = do- Mon $ mapM_ ((tyCache %=) . HashSet.insert) [ty | (_, _, subTys) <- elTys, ty <- subTys]+ Ap $ mapM_ ((tyCache %=) . HashSet.insert) [ty | (_, _, subTys) <- elTys, ty <- subTys] return (BitVector size) normaliseType ty@(Index _) = return (Unsigned (typeSize ty)) normaliseType ty@(Sum _ _) = return (BitVector (typeSize ty))@@ -310,7 +324,7 @@ tyDec :: HWType -> SystemVerilogM (Maybe Doc) tyDec ty@(Vector n elTy) | typeSize ty > 0 = Just A.<$> do- syn <- Mon hdlSyn+ syn <- Ap hdlSyn case syn of Vivado -> case splitVecTy ty of Just ([Right n',Left n''],elTy') ->@@ -325,7 +339,7 @@ brackets (int 0 <> colon <> int (n' - 1)) <> semi _ -> error $ $(curLoc) ++ "impossible" tyDec ty@(RTree n elTy) | typeSize elTy > 0 = Just A.<$> do- syn <- Mon hdlSyn+ syn <- Ap hdlSyn case syn of Vivado -> case splitVecTy ty of Just ([Right n',Left n''],elTy') -> -- n' == 2^n@@ -382,14 +396,14 @@ lvType :: HWType -> SystemVerilogM (Maybe Doc) lvType ty@(Vector n elTy) | typeSize ty > 0 = Just A.<$> do- syn <- Mon hdlSyn+ syn <- Ap hdlSyn case syn of Vivado -> "logic" <+> brackets (int 0 <> colon <> int (n-1)) <> brackets (int (typeSize elTy - 1) <> colon <> int 0) _ -> case splitVecTy ty of Just (ns,elTy') -> elTy' <> hcat (mapM range ns) _ -> error $ $(curLoc) ++ "impossible" lvType ty@(RTree n elTy) | typeSize elTy > 0 = Just A.<$> do- syn <- Mon hdlSyn+ syn <- Ap hdlSyn case syn of Vivado -> "logic" <+> brackets (int 0 <> colon <> int (2^n-1)) <> brackets (int (typeSize elTy - 1) <> colon <> int 0) _ -> case splitVecTy ty of@@ -428,7 +442,7 @@ vecSigDecl :: SystemVerilogM Doc -> SystemVerilogM Doc vecSigDecl d = do- syn <- Mon hdlSyn+ syn <- Ap hdlSyn case syn of Vivado -> case splitVecTy ty of Just ([Right n',Left n''],elTy') ->@@ -467,7 +481,7 @@ where treeSigDecl :: SystemVerilogM Doc -> SystemVerilogM Doc treeSigDecl d = do- syn <- Mon hdlSyn+ syn <- Ap hdlSyn case syn of Vivado -> case splitVecTy (RTree (n-1) elTy) of Just ([Right n',Left n''],elTy') -> -- n' == 2 ^ (n-1)@@ -490,12 +504,12 @@ module_ :: Component -> SystemVerilogM Doc module_ c =- modVerilog <* Mon (imports .= [] >> oports .= [])+ modVerilog <* Ap (imports .= [] >> oports .= []) where modVerilog = do body <- modBody- imps <- Mon $ use imports- libs <- Mon $ use libraries+ imps <- Ap $ use imports+ libs <- Ap $ use libraries modHeader <> line <> modPorts <> line <> include (nub imps) <> uselibs (nub libs) <> pure body <> line <> modEnding modHeader = "module" <+> pretty (componentName c)@@ -542,11 +556,11 @@ verilogType :: HWType -> SystemVerilogM Doc verilogType t_ = do t <- normaliseType t_- Mon (tyCache %= HashSet.insert t)+ Ap (tyCache %= HashSet.insert t) let logicOrWire | isBiSignalIn t = "wire" | otherwise = "logic"- pkgCtx <- Mon $ use tyPkgCtx- nm <- Mon $ use modNm+ pkgCtx <- Ap $ use tyPkgCtx+ nm <- Ap $ use modNm let pvrType = if pkgCtx then tyName t else stringS nm <> "_types::" <> tyName t@@ -571,9 +585,9 @@ verilogTypeMark :: HWType -> SystemVerilogM Doc verilogTypeMark t_ = do t <- normaliseType t_- Mon (tyCache %= HashSet.insert t)- pkgCtx <- Mon $ use tyPkgCtx- nm <- Mon $ use modNm+ Ap (tyCache %= HashSet.insert t)+ pkgCtx <- Ap $ use tyPkgCtx+ nm <- Ap $ use modNm let pvrType = if pkgCtx then tyName t else stringS nm <> "_types::" <> tyName t@@ -587,6 +601,7 @@ tyName Bool = "logic" tyName Bit = "logic" tyName (Vector n elTy) = "array_of_" <> int n <> "_" <> tyName elTy+tyName (MemBlob n m) = tyName (Vector n (BitVector m)) tyName (RTree n elTy) = "tree_of_" <> int n <> "_" <> tyName elTy tyName (BitVector n) = "logic_vector_" <> int n tyName t@(Index _) = "logic_vector_" <> int (typeSize t)@@ -597,7 +612,7 @@ tyName t@(CustomSP _ _ _ _) = "logic_vector_" <> int (typeSize t) tyName t@(Product nm _ _) = do tN <- normaliseType t- PP.pretty =<< Mon (makeCached tN nameCache prodName)+ PP.pretty =<< Ap (makeCached tN nameCache prodName) where prodName :: State SystemVerilogState Identifier prodName = Id.makeBasicOr (last (TextS.splitOn "." nm)) "product"@@ -611,12 +626,12 @@ -- | Convert a Netlist HWType to an error SystemVerilog value for that type verilogTypeErrValue :: HWType -> SystemVerilogM Doc verilogTypeErrValue (Vector n elTy) = do- syn <- Mon hdlSyn+ syn <- Ap hdlSyn case syn of Vivado -> char '\'' <> braces (int n <+> braces (singularErrValue elTy)) _ -> char '\'' <> braces (int n <+> braces (verilogTypeErrValue elTy)) verilogTypeErrValue (RTree n elTy) = do- syn <- Mon hdlSyn+ syn <- Ap hdlSyn case syn of Vivado -> char '\'' <> braces (int (2^n) <+> braces (singularErrValue elTy)) _ -> char '\'' <> braces (int (2^n) <+> braces (verilogTypeErrValue elTy))@@ -625,7 +640,7 @@ singularErrValue :: HWType -> SystemVerilogM Doc singularErrValue ty = do- udf <- Mon (use undefValue)+ udf <- Ap (use undefValue) case udf of Nothing -> braces (int (typeSize ty) <+> braces "1'bx") Just Nothing -> int (typeSize ty) <> "'d0 /* undefined */"@@ -678,7 +693,8 @@ insts :: [Declaration] -> SystemVerilogM Doc insts [] = emptyDoc-insts (TickDecl id_:ds) = comment "//" id_ <> line <> insts ds+insts (TickDecl (Comment c):ds) = comment "//" c <> line <> insts ds+insts (TickDecl (Directive d):ds) = pretty d <> ";" <> line <> insts ds insts (d:ds) = do docM <- inst_ d case docM of@@ -761,8 +777,8 @@ "assign" <+> pretty id_ <+> equals <+> align (expr_ False e <> semi) inst_ (CondAssignment id_ ty scrut _ [(Just (BoolLit b), l),(_,r)]) = fmap Just $ do- { syn <- Mon hdlSyn- ; p <- Mon $ use oports+ { syn <- Ap hdlSyn+ ; p <- Ap $ use oports ; if syn == Vivado && id_ `elem` p then do { regId <- Id.suffix id_ "reg"@@ -795,8 +811,8 @@ inst_' id_ scrut scrutTy es inst_ (CondAssignment id_ ty scrut scrutTy es) = fmap Just $ do- { syn <- Mon hdlSyn- ; p <- Mon $ use oports+ { syn <- Ap hdlSyn+ ; p <- Ap $ use oports ; if syn == Vivado && id_ `elem` p then do { regId <- Id.suffix id_ "reg"@@ -839,12 +855,15 @@ | otherwise = addAttrs attrs line inst_ (BlackBoxD _ libs imps inc bs bbCtx) =- fmap Just (Mon (column (renderBlackBox libs imps inc bs bbCtx)))+ fmap Just (Ap (column (renderBlackBox libs imps inc bs bbCtx))) inst_ (Seq ds) = Just <$> seqs ds inst_ (NetDecl' {}) = return Nothing +inst_ (ConditionalDecl cond ds) = Just <$>+ "`ifdef" <+> pretty cond <> line <> indent 2 (insts ds) <> line <> "`endif"+ -- | Render a data constructor application for data constructors having a -- custom bit representation. customReprDataCon@@ -942,7 +961,8 @@ seqs :: [Seq] -> SystemVerilogM Doc seqs [] = emptyDoc-seqs (SeqDecl (TickDecl id_):ds) = "//" <+> pretty id_ <> line <> seqs ds+seqs (SeqDecl (TickDecl (Comment c)):ds) = comment "//" c <> line <> seqs ds+seqs (SeqDecl (TickDecl (Directive d)):ds) = pretty d <> ";" <> line <> seqs ds seqs (d:ds) = seq_ d <> line <> line <> seqs ds -- | Turn a Netlist expression into a SystemVerilog expression@@ -1036,8 +1056,8 @@ expr_ _ (Identifier id_ (Just m@Nested {})) = case modifier 0 [] m of Nothing -> pretty id_ Just (mods,resTy) -> do- nm <- Mon $ use modNm- pkgCtx <- Mon $ use tyPkgCtx+ nm <- Ap $ use modNm+ pkgCtx <- Ap $ use tyPkgCtx let prefix = if pkgCtx then emptyDoc else stringS nm <> "_types::" let e = pretty id_ <> hcat (mapM (either bracketNMod bracketNMod) (reverse mods)) case resTy of@@ -1046,13 +1066,13 @@ | Left (NRange {}):_ <- mods -> e | otherwise -> do- Mon (tyCache %= HashSet.insert resTy)+ Ap (tyCache %= HashSet.insert resTy) prefix <> tyName resTy <> "_from_lv" <> parens e RTree {} | Left (NRange {}):_ <- mods -> e | otherwise -> do- Mon (tyCache %= HashSet.insert resTy)+ Ap (tyCache %= HashSet.insert resTy) prefix <> tyName resTy <> "_from_lv" <> parens e _ -> e where@@ -1061,25 +1081,25 @@ -- See [Note] integer projection expr_ _ (Identifier id_ (Just (Indexed ((Signed w),_,_)))) = do- iw <- Mon $ use intWidth+ iw <- Ap $ use intWidth traceIf (iw < w) ($(curLoc) ++ "WARNING: result smaller than argument") $ pretty id_ -- See [Note] integer projection expr_ _ (Identifier id_ (Just (Indexed ((Unsigned w),_,_)))) = do- iw <- Mon $ use intWidth+ iw <- Ap $ use intWidth traceIf (iw < w) ($(curLoc) ++ "WARNING: result smaller than argument") $ pretty id_ -- See [Note] mask projection expr_ _ (Identifier _ (Just (Indexed ((BitVector _),_,0)))) = do- iw <- Mon $ use intWidth+ iw <- Ap $ use intWidth traceIf True ($(curLoc) ++ "WARNING: synthesizing bitvector mask to dontcare") $ verilogTypeErrValue (Signed iw) -- See [Note] bitvector projection expr_ _ (Identifier id_ (Just (Indexed ((BitVector w),_,1)))) = do- iw <- Mon $ use intWidth+ iw <- Ap $ use intWidth traceIf (iw < w) ($(curLoc) ++ "WARNING: result smaller than argument") $ pretty id_ @@ -1098,6 +1118,18 @@ Just es -> "'" <> listBraces (mapM (toSLV elTy) es) Nothing -> verilogTypeMark ty <> "_cons" <> parens (expr_ False e1 <> comma <+> expr_ False e2) +expr_ _ (DataCon (MemBlob n m) _ [n0, m0, _, runs, _, ends])+ | Literal _ (NumLit n1) <- n0+ , n == fromInteger n1+ , Literal _ (NumLit m1) <- m0+ , m == fromInteger m1+ , Literal Nothing (StringLit runs0) <- runs+ , Literal Nothing (StringLit ends0) <- ends+ , es <- unpackNats n m (B8.pack runs0) (B8.pack ends0) =+ let el val = exprLitSV (Just (BitVector m, m))+ (BitVecLit 0 $ toInteger val)+ in "'" <> listBraces (mapM el es)+ expr_ _ (DataCon (RTree 0 elTy) _ [e]) = "'" <> braces (toSLV elTy e) expr_ _ e@(DataCon ty@(RTree _ elTy) _ [e1,e2]) = case rtreeChain e of@@ -1164,18 +1196,18 @@ = exprLitSV (Just (Index (fromInteger n),fromInteger n)) i expr_ b (BlackBoxE _ libs imps inc bs bbCtx b') =- parenIf (b || b') (Mon (renderBlackBox libs imps inc bs bbCtx <*> pure 0))+ parenIf (b || b') (Ap (renderBlackBox libs imps inc bs bbCtx <*> pure 0)) expr_ _ (DataTag Bool (Left id_)) = pretty id_ <> brackets (int 0) expr_ _ (DataTag Bool (Right id_)) = do- iw <- Mon $ use intWidth+ iw <- Ap $ use intWidth "$unsigned" <> parens (listBraces (sequence [braces (int (iw-1) <+> braces "1'b0"),pretty id_])) expr_ _ (DataTag (Sum _ _) (Left id_)) = "$unsigned" <> parens (pretty id_) expr_ _ (DataTag (Sum _ _) (Right id_)) = "$unsigned" <> parens (pretty id_) expr_ _ (DataTag (Product {}) (Right _)) = do- iw <- Mon $ use intWidth+ iw <- Ap $ use intWidth int iw <> "'sd0" expr_ _ (DataTag hty@(SP _ _) (Right id_)) = "$unsigned" <> parens@@ -1186,45 +1218,45 @@ end = typeSize hty - conSize hty expr_ _ (DataTag (Vector 0 _) (Right _)) = do- iw <- Mon $ use intWidth+ iw <- Ap $ use intWidth int iw <> "'sd0" expr_ _ (DataTag (Vector _ _) (Right _)) = do- iw <- Mon $ use intWidth+ iw <- Ap $ use intWidth int iw <> "'sd1" expr_ _ (DataTag (RTree 0 _) (Right _)) = do- iw <- Mon $ use intWidth+ iw <- Ap $ use intWidth int iw <> "'sd0" expr_ _ (DataTag (RTree _ _) (Right _)) = do- iw <- Mon $ use intWidth+ iw <- Ap $ use intWidth int iw <> "'sd1" expr_ b (ToBv topM t e) = do- nm <- Mon $ use modNm- pkgCtx <- Mon $ use tyPkgCtx+ nm <- Ap $ use modNm+ pkgCtx <- Ap $ use tyPkgCtx let prefix = if pkgCtx then emptyDoc else stringS nm <> "_types::" case t of Vector {} -> do- Mon (tyCache %= HashSet.insert t)+ Ap (tyCache %= HashSet.insert t) maybe prefix ((<> "_types::") . pretty) topM <> tyName t <> "_to_lv" <> parens (expr_ False e) RTree {} -> do- Mon (tyCache %= HashSet.insert t)+ Ap (tyCache %= HashSet.insert t) maybe prefix ((<> "_types::") . pretty) topM <> tyName t <> "_to_lv" <> parens (expr_ False e) _ -> expr b e expr_ b (FromBv topM t e) = do- nm <- Mon $ use modNm- pkgCtx <- Mon $ use tyPkgCtx+ nm <- Ap $ use modNm+ pkgCtx <- Ap $ use tyPkgCtx let prefix = if pkgCtx then emptyDoc else stringS nm <> "_types::" case t of Vector {} -> do- Mon (tyCache %= HashSet.insert t)+ Ap (tyCache %= HashSet.insert t) maybe prefix ((<> "_types::") . pretty) topM <> tyName t <> "_from_lv" <> parens (expr_ False e) RTree {} -> do- Mon (tyCache %= HashSet.insert t)+ Ap (tyCache %= HashSet.insert t) maybe prefix ((<> "_types::") . pretty) topM <> tyName t <> "_from_lv" <> parens (expr_ False e) _ -> expr b e@@ -1258,18 +1290,21 @@ toSLV t e = case t of Vector _ _ -> braces (verilogTypeMark t <> "_to_lv" <> parens (expr_ False e)) RTree _ _ -> braces (verilogTypeMark t <> "_to_lv" <> parens (expr_ False e))+ MemBlob n m -> toSLV (Vector n (BitVector m)) e _ -> expr_ False e fromSLV :: HWType -> IdentifierText -> Int -> Int -> SystemVerilogM Doc fromSLV t@(Vector _ _) id_ start end = verilogTypeMark t <> "_from_lv" <> parens (pretty id_ <> brackets (int start <> colon <> int end)) fromSLV t@(RTree _ _) id_ start end = verilogTypeMark t <> "_from_lv" <> parens (pretty id_ <> brackets (int start <> colon <> int end)) fromSLV (Signed _) id_ start end = "$signed" <> parens (pretty id_ <> brackets (int start <> colon <> int end))+fromSLV (MemBlob n m) id_ start end = fromSLV (Vector n (BitVector m)) id_ start end fromSLV _ id_ start end = pretty id_ <> brackets (int start <> colon <> int end) simpleFromSLV :: HWType -> IdentifierText -> SystemVerilogM Doc simpleFromSLV t@(Vector _ _) id_ = verilogTypeMark t <> "_from_lv" <> parens (pretty id_) simpleFromSLV t@(RTree _ _) id_ = verilogTypeMark t <> "_from_lv" <> parens (pretty id_) simpleFromSLV (Signed _) id_ = "$signed" <> parens (pretty id_)+simpleFromSLV (MemBlob n m) id_ = simpleFromSLV (Vector n (BitVector m)) id_ simpleFromSLV _ id_ = pretty id_ expFromSLV :: HWType -> SystemVerilogM Doc -> SystemVerilogM Doc@@ -1288,7 +1323,7 @@ parenIf True = parens parenIf False = id -punctuate' :: Monad m => Mon m Doc -> Mon m [Doc] -> Mon m Doc+punctuate' :: Monad m => Ap m Doc -> Ap m [Doc] -> Ap m Doc punctuate' s d = vcat (punctuate s d) <> s
src/Clash/Backend/VHDL.hs view
@@ -1,8 +1,9 @@ {-| Copyright : (C) 2015-2016, University of Twente,- 2017-2018, Google Inc.+ 2017-2018, Google Inc.,+ 2021-2022, QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Generate VHDL for assorted Netlist datatypes -}@@ -23,7 +24,11 @@ import Control.Lens hiding (Indexed, Empty) import Control.Monad (forM,join,zipWithM) import Control.Monad.State (State, StateT)+import Data.Bifunctor (first) import Data.Bits (testBit, Bits)+import qualified Data.ByteString.Char8 as B8+import Data.Coerce (coerce)+import Data.Function (on) import Data.HashMap.Lazy (HashMap) import qualified Data.HashMap.Lazy as HashMap import qualified Data.HashMap.Strict as HashMapS@@ -33,12 +38,11 @@ (mapAccumL, nub, nubBy, intersperse, group, sort) import Data.List.Extra ((<:>), equalLength, zipEqual) import Data.Maybe (catMaybes,mapMaybe)-#if !MIN_VERSION_base(4,11,0)-import Data.Monoid hiding (Sum, Product)-#endif-import Data.Semigroup.Monad.Extra+import Data.Monoid (Ap(Ap))+import Data.Monoid.Extra () import qualified Data.Text.Lazy as T import qualified Data.Text as TextS+import Data.Text.Extra #if MIN_VERSION_prettyprinter(1,7,0) import qualified Prettyprinter as PP@@ -50,7 +54,6 @@ import GHC.Stack (HasCallStack) import qualified System.FilePath import Text.Printf-import TextShow (showt) import Clash.Annotations.Primitive (HDL (..)) import Clash.Annotations.BitRepresentation.Internal@@ -62,6 +65,8 @@ import Clash.Backend import Clash.Core.Var (Attr'(..),attrName) import Clash.Debug (traceIf)+import Clash.Driver.Types (ClashOpts(..))+import Clash.Explicit.BlockRam.Internal (unpackNats) import Clash.Netlist.BlackBox.Types (HdlSyn (..)) import Clash.Netlist.BlackBox.Util (extractLiterals, renderBlackBox, renderFilePath)@@ -69,11 +74,12 @@ import Clash.Netlist.Types hiding (_intWidth, intWidth) import Clash.Netlist.Util import Clash.Util- (SrcSpan, noSrcSpan, clogBase, curLoc, first, makeCached, on, indexNote)+ (SrcSpan, noSrcSpan, clogBase, curLoc, makeCached, indexNote) import qualified Clash.Util.Interpolate as I import Clash.Util.Graph (reverseTopSort) import Clash.Backend.Verilog (Range (..), continueWithRange)+import Debug.Trace (traceM) -- | State for the 'Clash.Netlist.VHDL.VHDLM' monad: data VHDLState =@@ -103,7 +109,11 @@ , _undefValue :: Maybe (Maybe Int) , _productFieldNameCache :: HashMap (Maybe [TextS.Text], [HWType]) [TextS.Text] -- ^ Caches output of 'productFieldNames'.+ , _enumNameCache :: HashMap HWType [TextS.Text]+ -- ^ Cache for enum variant names. , _aggressiveXOptBB_ :: AggressiveXOptBB+ , _renderEnums_ :: RenderEnums+ , _domainConfigurations_ :: DomainMap } makeLenses ''VHDLState@@ -112,7 +122,7 @@ identifierSet = idSeen instance Backend VHDLState where- initBackend w hdlsyn_ esc lw undefVal xOpt = VHDLState+ initBackend opts = VHDLState { _tyCache=mempty , _nameCache=mempty , _modNm=""@@ -122,13 +132,16 @@ , _includes=[] , _dataFiles=[] , _memoryDataFiles=[]- , _idSeen=Id.emptyIdentifierSet esc lw VHDL+ , _idSeen=Id.emptyIdentifierSet (opt_escapedIds opts) (opt_lowerCaseBasicIds opts) VHDL , _tyPkgCtx=False- , _intWidth=w- , _hdlsyn=hdlsyn_- , _undefValue=undefVal+ , _intWidth=opt_intWidth opts+ , _hdlsyn=opt_hdlSyn opts+ , _undefValue=opt_forceUndefined opts , _productFieldNameCache=mempty- , _aggressiveXOptBB_=xOpt+ , _enumNameCache=mempty+ , _aggressiveXOptBB_=coerce (opt_aggressiveXOptBB opts)+ , _renderEnums_=coerce (opt_renderEnums opts)+ , _domainConfigurations_=emptyDomainMap } hdlKind = const VHDL primDirs = const $ do root <- primsRoot@@ -145,14 +158,22 @@ Vector {} -> pure UserType RTree {} -> pure UserType Product {} -> pure UserType+ MemBlob {} -> pure UserType + Sum {} -> do+ -- If an enum is rendered, it is a user type. If not, an std_logic_vector+ -- is rendered, and it is a synonym.+ RenderEnums enums <- renderEnums+ if enums then pure UserType else pure SynonymType+ Clock {} -> pure SynonymType Reset {} -> pure SynonymType Enable {} -> pure SynonymType Index {} -> pure SynonymType CustomSP {} -> pure SynonymType SP {} -> pure SynonymType- Sum {} -> pure SynonymType+ -- TODO This could possibly be changed to a VHDL enum as well, provided the+ -- enum_encoding attribute behaves as desired in different tools CustomSum {} -> pure SynonymType CustomProduct {} -> pure SynonymType @@ -191,10 +212,11 @@ inst = inst_ expr = expr_ iwWidth = use intWidth- toBV t id_- | isBV t = pretty id_- | otherwise = do- nm <- Mon $ use modNm++ toBV t id_ = do+ enums <- Ap renderEnums+ if isBV enums t then pretty id_ else do+ nm <- Ap $ use modNm -- TODO: restore hack -- seen <- use seenIdentifiers -- This is a bit hacky, as id_ is just a rendered expression.@@ -204,10 +226,10 @@ -- | otherwise = let e = hdlTypeMark t <> squote <> parens (pretty id_) pretty nm <> "_types.toSLV" <> parens e- fromBV t id_- | isBV t = pretty id_- | otherwise = do- nm <- Mon $ use modNm+ fromBV t id_ = do+ enums <- Ap renderEnums+ if isBV enums t then pretty id_ else do+ nm <- Ap $ use modNm qualTyName t <> "'" <> parens (pretty nm <> "_types.fromSLV" <> parens (pretty id_)) hdlSyn = use hdlsyn setModName nm s = s {_modNm = nm}@@ -243,13 +265,16 @@ getMemoryDataFiles = use memoryDataFiles ifThenElseExpr _ = False aggressiveXOptBB = use aggressiveXOptBB_+ renderEnums = use renderEnums_+ domainConfigurations = use domainConfigurations_+ setDomainConfigurations confs s = s {_domainConfigurations_ = confs} -type VHDLM a = Mon (State VHDLState) a+type VHDLM a = Ap (State VHDLState) a -- Check if the underlying type is a BitVector-isBV :: HWType -> Bool-isBV (normaliseType -> BitVector _) = True-isBV _ = False+isBV :: RenderEnums -> HWType -> Bool+isBV e (normaliseType e -> BitVector _) = True+isBV _ _ = False -- | Generate unique (partial) names for product fields. Example: --@@ -327,6 +352,21 @@ selectProductField fieldLabels fieldTypes fieldIndex = "_sel" <> int fieldIndex <> "_" <> productFieldName fieldLabels fieldTypes fieldIndex +enumVariantName+ :: HasCallStack+ => HWType+ -> Int+ -> VHDLM Doc+enumVariantName ty@(Sum _ vs) i = do+ names <- makeCached ty enumNameCache (traverse variantName vs)+ pure (PP.pretty (names !! i))+ where+ -- Make a basic identifier from the last part of a qualified name+ variantName = fmap Id.toText . Id.makeBasic . snd . TextS.breakOnEnd "."++enumVariantName _ _ =+ error $ $(curLoc) ++ "enumVariantName called on non-enum type"+ -- | Generate VHDL for a Netlist component genVHDL :: ModName@@ -340,13 +380,13 @@ -- -- TODO: Collect all type names up front, to prevent relatively costly union. -- TODO: Investigate whether type names / signal names collide in the first place- Mon $ idSeen %= Id.union seen+ Ap $ idSeen %= Id.union seen - Mon $ setSrcSpan sp+ Ap $ setSrcSpan sp v <- vhdl- i <- Mon $ use includes- Mon $ libraries .= []- Mon $ packages .= []+ i <- Ap $ use includes+ Ap $ libraries .= []+ Ap $ packages .= [] return ((TextS.unpack (Id.toText cName), v), i) where cName = componentName c@@ -362,13 +402,14 @@ -- | Generate a VHDL package containing type definitions for the given HWTypes mkTyPackage_ :: ModName -> [HWType] -> VHDLM [(String,Doc)] mkTyPackage_ modName (map filterTransparent -> hwtys) = do- { Mon (tyPkgCtx .= True)- ; syn <- Mon hdlSyn+ { Ap (tyPkgCtx .= True)+ ; syn <- Ap hdlSyn+ ; enums <- Ap renderEnums ; let usedTys = concatMap mkUsedTys hwtys ; let normTys0 = nub (map mkVecZ (hwtys ++ usedTys)) ; let sortedTys0 = topSortHWTys normTys0 packageDec = vcat $ mapM tyDec (nubBy eqTypM sortedTys0)- (funDecs,funBodies) = unzip . mapMaybe (funDec syn) $ nubBy eqTypM (map normaliseType sortedTys0)+ (funDecs,funBodies) = unzip . mapMaybe (funDec enums syn) $ nubBy eqTypM (normaliseType enums <$> sortedTys0) ; pkg <- (:[]) <$> (TextS.unpack (modName `TextS.append` "_types"),) <$> "library IEEE;" <> line <>@@ -379,7 +420,7 @@ vcat (sequence funDecs) ) <> line <> "end" <> semi <> packageBodyDec funBodies- ; Mon (tyPkgCtx .= False)+ ; Ap (tyPkgCtx .= False) ; return pkg } where@@ -473,15 +514,18 @@ mkVecZ t = t typAliasDec :: HasCallStack => HWType -> VHDLM Doc-typAliasDec hwty =+typAliasDec hwty = do+ enums <- Ap renderEnums "subtype" <+> tyName hwty <+> "is"- <+> sizedTyName (normaliseType hwty)+ <+> sizedTyName (normaliseType enums hwty) <> semi tyDec :: HasCallStack => HWType -> VHDLM Doc tyDec hwty = do- syn <- Mon hdlSyn+ syn <- Ap hdlSyn+ RenderEnums enums <- Ap renderEnums+ case hwty of -- "Proper" custom types: Vector _ elTy ->@@ -520,14 +564,23 @@ indent 2 (vcat $ zipWithM (\x y -> x <+> colon <+> y <> semi) selNames selTys) <> line <> "end record" <> semi + Sum _ vs | enums ->+ let variantNames = traverse (enumVariantName hwty) [0..length vs - 1] in+ "type" <+> tyName hwty+ <+> "is"+ <+> parens (hsep (punctuate comma variantNames))+ <> semi++ MemBlob n m -> tyDec (Vector n (BitVector m))+ -- Type aliases: Clock _ -> typAliasDec hwty Reset _ -> typAliasDec hwty Enable _ -> typAliasDec hwty Index _ -> typAliasDec hwty CustomSP _ _ _ _ -> typAliasDec hwty- SP _ _ -> typAliasDec hwty Sum _ _ -> typAliasDec hwty+ SP _ _ -> typAliasDec hwty CustomSum _ _ _ _ -> typAliasDec hwty CustomProduct {} -> typAliasDec hwty @@ -556,8 +609,8 @@ -funDec :: HdlSyn -> HWType -> Maybe (VHDLM Doc,VHDLM Doc)-funDec _ Bool = Just+funDec :: RenderEnums -> HdlSyn -> HWType -> Maybe (VHDLM Doc,VHDLM Doc)+funDec _ _ Bool = Just ( "function" <+> "toSLV" <+> parens ("b" <+> colon <+> "in" <+> "boolean") <+> "return" <+> "std_logic_vector" <> semi <> line <> "function" <+> "fromSLV" <+> parens ("sl" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> "boolean" <> semi <> line <> "function" <+> "tagToEnum" <+> parens ("s" <+> colon <+> "in" <+> "signed") <+> "return" <+> "boolean" <> semi <> line <>@@ -582,7 +635,7 @@ "end" <> semi <> line <> "function" <+> "tagToEnum" <+> parens ("s" <+> colon <+> "in" <+> "signed") <+> "return" <+> "boolean" <+> "is" <> line <> "begin" <> line <>- indent 2 (vcat $ sequence ["if" <+> "s" <+> "=" <+> "to_signed" <> parens (int 0 <> comma <> (Mon (use intWidth) >>= int)) <+> "then"+ indent 2 (vcat $ sequence ["if" <+> "s" <+> "=" <+> "to_signed" <> parens (int 0 <> comma <> (Ap (use intWidth) >>= int)) <+> "then" , indent 2 ("return" <+> "false" <> semi) ,"else" , indent 2 ("return" <+> "true" <> semi)@@ -592,15 +645,15 @@ "function" <+> "dataToTag" <+> parens ("b" <+> colon <+> "in" <+> "boolean") <+> "return" <+> "signed" <+> "is" <> line <> "begin" <> line <> indent 2 (vcat $ sequence ["if" <+> "b" <+> "then"- , indent 2 ("return" <+> "to_signed" <> parens (int 1 <> comma <> (Mon (use intWidth) >>= int)) <> semi)+ , indent 2 ("return" <+> "to_signed" <> parens (int 1 <> comma <> (Ap (use intWidth) >>= int)) <> semi) ,"else"- , indent 2 ("return" <+> "to_signed" <> parens (int 0 <> comma <> (Mon (use intWidth) >>= int)) <> semi)+ , indent 2 ("return" <+> "to_signed" <> parens (int 0 <> comma <> (Ap (use intWidth) >>= int)) <> semi) ,"end" <+> "if" <> semi ]) <> line <> "end" <> semi ) -funDec _ bit@Bit = Just+funDec _ _ bit@Bit = Just ( "function" <+> "toSLV" <+> parens ("sl" <+> colon <+> "in" <+> tyName bit) <+> "return" <+> "std_logic_vector" <> semi <> line <> "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> tyName bit <> semi , "function" <+> "toSLV" <+> parens ("sl" <+> colon <+> "in" <+> tyName bit) <+> "return" <+> "std_logic_vector" <+> "is" <> line <>@@ -616,7 +669,7 @@ "end" <> semi ) -funDec _ (Signed _) = Just+funDec _ _ (Signed _) = Just ( "function" <+> "toSLV" <+> parens ("s" <+> colon <+> "in" <+> "signed") <+> "return" <+> "std_logic_vector" <> semi <> line <> "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> "signed" <> semi , "function" <+> "toSLV" <+> parens ("s" <+> colon <+> "in" <+> "signed") <+> "return" <+> "std_logic_vector" <+> "is" <> line <>@@ -630,7 +683,7 @@ "end" <> semi ) -funDec _ (Unsigned _) = Just+funDec _ _ (Unsigned _) = Just ( "function" <+> "toSLV" <+> parens ("u" <+> colon <+> "in" <+> "unsigned") <+> "return" <+> "std_logic_vector" <> semi <> line <> "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> "unsigned" <> semi , "function" <+> "toSLV" <+> parens ("u" <+> colon <+> "in" <+> "unsigned") <+> "return" <+> "std_logic_vector" <+> "is" <> line <>@@ -645,7 +698,7 @@ ) -funDec _ t@(Product _ labels elTys) = Just+funDec _ _ t@(Product _ labels elTys) = Just ( "function" <+> "toSLV" <+> parens ("p :" <+> sizedTyName t) <+> "return std_logic_vector" <> semi <> line <> "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> sizedTyName t <> semi , "function" <+> "toSLV" <+> parens ("p :" <+> sizedTyName t) <+> "return std_logic_vector" <+> "is" <> line <>@@ -671,7 +724,27 @@ (\(s,e) -> "fromSLV" <> parens ("islv" <> parens (int s <+> "to" <+> int e))) -funDec syn t@(Vector _ elTy) = Just+funDec (RenderEnums enums) _ t@(Sum _ _) | enums = Just+ ( "function" <+> "toSLV" <+> parens("value" <+> colon <+> "in" <+> qualTyName t) <+> "return std_logic_vector" <> semi <> line <>+ "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> qualTyName t <> semi+ , "function" <+> "toSLV" <+> parens ("value" <+> colon <+> "in" <+> qualTyName t) <+> "return std_logic_vector" <+> "is" <> line <>+ "begin" <> line <>+ indent 2+ ( "return" <+> "std_logic_vector" <>+ parens ("to_unsigned" <>+ parens (qualTyName t <> "'pos(value)" <> comma <+> int (typeSize t))+ )) <> semi <> line <>+ "end" <> semi <> line <>+ "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> qualTyName t <+> "is" <> line <>+ "begin" <> line <>+ indent 2+ ( "return" <+> qualTyName t <> "'val" <>+ parens ("to_integer" <>+ parens ("unsigned" <> parens "slv"))) <> semi <> line <>+ "end" <> semi+ )++funDec _ syn t@(Vector _ elTy) = Just ( "function" <+> "toSLV" <+> parens ("value : " <+> qualTyName t) <+> "return std_logic_vector" <> semi <> line <> "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> qualTyName t <> semi , "function" <+> "toSLV" <+> parens ("value : " <+> qualTyName t) <+> "return std_logic_vector" <+> "is" <> line <>@@ -717,7 +790,7 @@ eSz = int (typeSize elTy) getElem = "islv" <> parens ("i * " <> eSz <+> "to (i+1) * " <> eSz <+> "- 1") -funDec _ (BitVector _) = Just+funDec _ _ (BitVector _) = Just ( "function" <+> "toSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> "std_logic_vector" <> semi <> line <> "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> "std_logic_vector" <> semi , "function" <+> "toSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> "std_logic_vector" <+> "is" <> line <>@@ -730,7 +803,7 @@ "end" <> semi ) -funDec syn t@(RTree _ elTy) = Just+funDec _ syn t@(RTree _ elTy) = Just ( "function" <+> "toSLV" <+> parens ("value : " <+> qualTyName t) <+> "return std_logic_vector" <> semi <> line <> "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> qualTyName t <> semi , "function" <+> "toSLV" <+> parens ("value : " <+> qualTyName t) <+> "return std_logic_vector" <+> "is" <> line <>@@ -776,12 +849,12 @@ eSz = int (typeSize elTy) getElem = "islv" <> parens ("i * " <> eSz <+> "to (i+1) * " <> eSz <+> "- 1") -funDec _ _ = Nothing+funDec _ _ _ = Nothing tyImports :: ModName -> VHDLM Doc tyImports nm = do- libs <- Mon $ use libraries- packs <- Mon $ use packages+ libs <- Ap $ use libraries+ packs <- Ap $ use packages punctuate' semi $ sequence ([ "library IEEE" , "use IEEE.STD_LOGIC_1164.ALL"@@ -829,7 +902,7 @@ entity :: Component -> VHDLM Doc entity c = do- syn <- Mon hdlSyn+ syn <- Ap hdlSyn rec (p,ls) <- fmap unzip (ports (maximum ls)) "entity" <+> pretty (componentName c) <+> "is" <> line <> (case p of@@ -854,7 +927,7 @@ architecture :: Component -> VHDLM Doc architecture c = do {- ; syn <- Mon hdlSyn+ ; syn <- Ap hdlSyn ; let attrs = case syn of -- See: [Note] Hack entity attributes in architecture Other -> declAttrs@@ -980,6 +1053,7 @@ Unsigned n -> baseType <> parens (int (n-1) <+> "downto 0") Vector n _ -> baseType <> parens ("0 to" <+> int (n-1)) RTree d _ -> baseType <> parens ("0 to" <+> int ((2^d)-1))+ MemBlob n _ -> baseType <> parens ("0 to" <+> int (n-1)) Annotated _ elTy -> appendSize baseType elTy _ -> baseType @@ -1007,8 +1081,8 @@ -- Custom types: _ -> do- pkgCtx <- Mon (use tyPkgCtx)- modName <- Mon (use modNm)+ pkgCtx <- Ap (use tyPkgCtx)+ modName <- Ap (use modNm) if pkgCtx then tyName hwty@@ -1044,7 +1118,7 @@ -- ^ Type to name -> VHDLM TextS.Text tyName' rec0 (filterTransparent -> t) = do- Mon (tyCache %= HashSet.insert t)+ Ap (tyCache %= HashSet.insert t) case t of KnownDomain {} -> return (error ($(curLoc) ++ "Forced to print KnownDomain tyName"))@@ -1068,47 +1142,49 @@ let nm = TextS.concat [ "array_of_" , if rec0 then showt n `TextS.append` "_" else "" , elTy']- Mon $ makeCached (t, rec0) nameCache (return nm)+ Ap $ makeCached (t, rec0) nameCache (return nm) RTree n elTy -> do elTy' <- tyName' True elTy let nm = TextS.concat [ "tree_of_" , if rec0 then showt n `TextS.append` "_" else "" , elTy']- Mon $ makeCached (t, rec0) nameCache (return nm)+ Ap $ makeCached (t, rec0) nameCache (return nm) -- TODO: nice formatting for Index. I.e., 2000 = 2e3, 1024 = 2pow10 Index n -> return ("index_" `TextS.append` showt n) Clock nm0 -> let nm1 = "clk_" `TextS.append` nm0 in- Mon $ makeCached (t, False) nameCache (userTyName "clk" nm1 t)+ Ap $ makeCached (t, False) nameCache (userTyName "clk" nm1 t) Reset nm0 -> let nm1 = "rst_" `TextS.append` nm0 in- Mon $ makeCached (t, False) nameCache (userTyName "rst" nm1 t)+ Ap $ makeCached (t, False) nameCache (userTyName "rst" nm1 t) Enable nm0 -> let nm1 = "en_" `TextS.append` nm0 in- Mon $ makeCached (t, False) nameCache (userTyName "en" nm1 t)+ Ap $ makeCached (t, False) nameCache (userTyName "en" nm1 t) Sum nm _ ->- Mon $ makeCached (t, False) nameCache (userTyName "sum" nm t)+ Ap $ makeCached (t, False) nameCache (userTyName "sum" nm t) CustomSum nm _ _ _ ->- Mon $ makeCached (t, False) nameCache (userTyName "sum" nm t)+ Ap $ makeCached (t, False) nameCache (userTyName "sum" nm t) SP nm _ ->- Mon $ makeCached (t, False) nameCache (userTyName "sp" nm t)+ Ap $ makeCached (t, False) nameCache (userTyName "sp" nm t) CustomSP nm _ _ _ ->- Mon $ makeCached (t, False) nameCache (userTyName "sp" nm t)+ Ap $ makeCached (t, False) nameCache (userTyName "sp" nm t) Product nm _ _ ->- Mon $ makeCached (t, False) nameCache (userTyName "product" nm t)+ Ap $ makeCached (t, False) nameCache (userTyName "product" nm t) CustomProduct nm _ _ _ _ ->- Mon $ makeCached (t, False) nameCache (userTyName "product" nm t)+ Ap $ makeCached (t, False) nameCache (userTyName "product" nm t) Annotated _ hwTy -> tyName' rec0 hwTy BiDirectional _ hwTy -> tyName' rec0 hwTy FileType -> return "file"+ ty -> return (error ($(curLoc) ++ show ty +++ " not filtered by filterTransparent")) -- | Returns underlying type of given HWType. That is, the type by which it -- eventually will be represented in VHDL.-normaliseType :: HWType -> HWType-normaliseType hwty = case hwty of+normaliseType :: RenderEnums -> HWType -> HWType+normaliseType enums@(RenderEnums e) hwty = case hwty of Void {} -> hwty KnownDomain {} -> hwty @@ -1126,6 +1202,8 @@ Vector _ _ -> hwty RTree _ _ -> hwty Product _ _ _ -> hwty+ Sum _ _ -> if e then hwty else BitVector (typeSize hwty)+ MemBlob n m -> Vector n (BitVector m) -- Simple types, for which a subtype (without qualifiers) will be made in VHDL: Clock _ -> Bit@@ -1134,13 +1212,12 @@ Index _ -> Unsigned (typeSize hwty) CustomSP _ _ _ _ -> BitVector (typeSize hwty) SP _ _ -> BitVector (typeSize hwty)- Sum _ _ -> BitVector (typeSize hwty) CustomSum _ _ _ _ -> BitVector (typeSize hwty) CustomProduct {} -> BitVector (typeSize hwty) -- Transparent types:- Annotated _ elTy -> normaliseType elTy- BiDirectional _ elTy -> normaliseType elTy+ Annotated _ elTy -> normaliseType enums elTy+ BiDirectional _ elTy -> normaliseType enums elTy -- | Recursively remove transparent types from given type filterTransparent :: HWType -> HWType@@ -1160,6 +1237,8 @@ CustomSum _ _ _ _ -> hwty FileType -> hwty + MemBlob n m -> Vector n (BitVector m)+ Vector n elTy -> Vector n (filterTransparent elTy) RTree n elTy -> RTree n (filterTransparent elTy) Product nm labels elTys ->@@ -1200,20 +1279,20 @@ -- | Convert a Netlist HWType to an error VHDL value for that type sizedQualTyNameErrValue :: HWType -> VHDLM Doc sizedQualTyNameErrValue Bool = do- udf <- Mon (use undefValue)+ udf <- Ap (use undefValue) case udf of Just (Just 0) -> "false" _ -> "true" sizedQualTyNameErrValue Bit = singularErrValue sizedQualTyNameErrValue t@(Vector n elTy) = do- syn <-Mon hdlSyn+ syn <-Ap hdlSyn case syn of Vivado -> qualTyName t <> "'" <> parens (int 0 <+> "to" <+> int (n-1) <+> rarrow <+> "std_logic_vector'" <> parens (int 0 <+> "to" <+> int (typeSize elTy - 1) <+> rarrow <+> singularErrValue)) _ -> qualTyName t <> "'" <> parens (int 0 <+> "to" <+> int (n-1) <+> rarrow <+> sizedQualTyNameErrValue elTy) sizedQualTyNameErrValue t@(RTree n elTy) = do- syn <-Mon hdlSyn+ syn <-Ap hdlSyn case syn of Vivado -> qualTyName t <> "'" <> parens (int 0 <+> "to" <+> int (2^n - 1) <+> rarrow <+> "std_logic_vector'" <> parens (int 0 <+> "to" <+> int (typeSize elTy - 1) <+>@@ -1221,6 +1300,13 @@ _ -> qualTyName t <> "'" <> parens (int 0 <+> "to" <+> int (2^n - 1) <+> rarrow <+> sizedQualTyNameErrValue elTy) sizedQualTyNameErrValue t@(Product _ _ elTys) = qualTyName t <> "'" <> tupled (mapM sizedQualTyNameErrValue elTys)+sizedQualTyNameErrValue t@(Sum _ _) = do+ -- No undefined / don't care for enums, so just set it to the first value+ RenderEnums enums <- Ap renderEnums+ if enums then+ tyName t <> "'val" <> parens (int 0)+ else+ qualTyName t <> "'" <> parens (int 0 <+> "to" <+> int (typeSize t - 1) <+> rarrow <+> singularErrValue) sizedQualTyNameErrValue (Clock _) = singularErrValue sizedQualTyNameErrValue (Reset _) = singularErrValue sizedQualTyNameErrValue (Enable _) = singularErrValue@@ -1232,7 +1318,7 @@ singularErrValue :: VHDLM Doc singularErrValue = do- udf <- Mon (use undefValue)+ udf <- Ap (use undefValue) case udf of Nothing -> "'-'" Just Nothing -> "'0'"@@ -1342,7 +1428,8 @@ insts :: [Declaration] -> VHDLM Doc insts [] = emptyDoc-insts (TickDecl id_:ds) = comment "--" id_ <> line <> insts ds+insts (TickDecl (Comment c):ds) = comment "--" c <> line <> insts ds+insts (TickDecl (Directive d):ds) = pretty d <> ";" <> line <> insts ds insts (d:ds) = do d' <- inst_ d case d' of@@ -1409,7 +1496,7 @@ conds ((Just c ,e):es') = expr_ False e <+> "when" <+> patLit scrutTy c <:> conds es' inst_ (InstDecl entOrComp libM _ nm lbl gens pms0) = do- maybe (return ()) (\lib -> Mon (libraries %= (T.fromStrict lib:))) libM+ maybe (return ()) (\lib -> Ap (libraries %= (T.fromStrict lib:))) libM fmap Just $ nest 2 $ pretty lbl <+> colon <> entOrComp' <+> maybe emptyDoc ((<> ".") . pretty) libM <> pretty nm <> line <> gms <> pms2 <> semi@@ -1432,8 +1519,14 @@ entOrComp' = case entOrComp of { Entity -> " entity"; Comp -> " component"; Empty -> ""} inst_ (BlackBoxD _ libs imps inc bs bbCtx) =- fmap Just (Mon (column (renderBlackBox libs imps inc bs bbCtx)))+ fmap Just (Ap (column (renderBlackBox libs imps inc bs bbCtx))) +inst_ (ConditionalDecl cond _) = do+ traceM+ $ "WARNING: Conditional compilation is not supported in VHDL. Discarding code conditional on "+ <> TextS.unpack cond+ return Nothing+ inst_ _ = return Nothing -- | Render a data constructor application for data constructors having a@@ -1500,7 +1593,7 @@ expr_ _ (Identifier id_ Nothing) = pretty id_ expr_ _ (Identifier id_ (Just m)) = do- syn <- Mon hdlSyn+ syn <- Ap hdlSyn maybe (pretty id_) (foldr renderModifier (pretty id_)) (buildModifier syn [] m) expr_ b (DataCon _ (DC (Void {}, -1)) [e]) = expr_ b e@@ -1508,13 +1601,14 @@ expr_ _ (DataCon ty@(Vector 0 _) _ _) = sizedQualTyNameErrValue ty expr_ _ (DataCon ty@(Vector 1 elTy) _ [e]) = do- syn <- Mon hdlSyn+ syn <- Ap hdlSyn case syn of Vivado -> qualTyName ty <> "'" <> parens (int 0 <+> rarrow <+> toSLV elTy e) _ -> qualTyName ty <> "'" <> parens (int 0 <+> rarrow <+> expr_ False e) expr_ _ e@(DataCon ty@(Vector _ elTy) _ [e1,e2]) = do- syn <- Mon hdlSyn+ syn <- Ap hdlSyn case syn of+ -- When targeting Vivado, arrays must use std_logic_vector for elements. Vivado -> qualTyName ty <> "'" <> case vectorChain e of Just es -> align (tupled (mapM (toSLV elTy) es)) Nothing -> parens ("std_logic_vector'" <> parens (toSLV elTy e1) <+> "&" <+> expr_ False e2)@@ -1522,8 +1616,19 @@ Just es -> align (tupled (mapM (expr_ False) es)) Nothing -> parens (qualTyName elTy <> "'" <> parens (expr_ False e1) <+> "&" <+> expr_ False e2) +expr_ _ (DataCon ty@(MemBlob n m) _ [n0, m0, _, runs, _, ends])+ | Literal _ (NumLit n1) <- n0+ , n == fromInteger n1+ , Literal _ (NumLit m1) <- m0+ , m == fromInteger m1+ , Literal Nothing (StringLit runs0) <- runs+ , Literal Nothing (StringLit ends0) <- ends+ , es <- unpackNats n m (B8.pack runs0) (B8.pack ends0) =+ let el val = exprLit (Just (BitVector m, m)) (BitVecLit 0 $ toInteger val)+ in qualTyName ty <> "'" <> (align $ tupled $ mapM el es)+ expr_ _ (DataCon ty@(RTree 0 elTy) _ [e]) = do- syn <- Mon hdlSyn+ syn <- Ap hdlSyn case syn of Vivado -> qualTyName ty <> "'" <> parens (int 0 <+> rarrow <+> toSLV elTy e) _ -> qualTyName ty <> "'" <> parens (int 0 <+> rarrow <+> expr_ False e)@@ -1548,8 +1653,12 @@ n -> [bits (replicate n U)] assignExpr = "std_logic_vector'" <> parens (hcat $ punctuate " & " $ sequence (dcExpr:argExprs ++ extraArg)) -expr_ _ (DataCon ty@(Sum _ _) (DC (_,i)) []) =- expr_ False (dcToExpr ty i)+expr_ _ (DataCon ty@(Sum _ _) (DC (_,i)) []) = do+ RenderEnums enums <- Ap renderEnums+ if enums then+ tyName ty <> "'" <> parens (enumVariantName ty i)+ else+ expr_ False (dcToExpr ty i) expr_ _ (DataCon ty@(CustomSum _ _ _ tys) (DC (_,i)) []) = let (ConstrRepr' _ _ _ value _) = fst $ tys !! i in "std_logic_vector" <> parens ("to_unsigned" <> parens (int (fromIntegral value) <> comma <> int (typeSize ty)))@@ -1605,35 +1714,32 @@ , let k' = max 1 k = exprLit (Just (Unsigned k',k')) (NumLit (n-1)) -expr_ _ (BlackBoxE pNm _ _ _ _ bbCtx _)- | pNm == "GHC.Types.I#"- , [Literal _ (NumLit n)] <- extractLiterals bbCtx- = do iw <- Mon $ use intWidth- exprLit (Just (Signed iw,iw)) (NumLit n)--expr_ _ (BlackBoxE pNm _ _ _ _ bbCtx _)- | pNm == "GHC.Types.W#"- , [Literal _ (NumLit n)] <- extractLiterals bbCtx- = do iw <- Mon $ use intWidth- exprLit (Just (Unsigned iw,iw)) (NumLit n)- expr_ b (BlackBoxE _ libs imps inc bs bbCtx b') = do- parenIf (b || b') (Mon (renderBlackBox libs imps inc bs bbCtx <*> pure 0))+ parenIf (b || b') (Ap (renderBlackBox libs imps inc bs bbCtx <*> pure 0)) expr_ _ (DataTag Bool (Left id_)) = "tagToEnum" <> parens (pretty id_) expr_ _ (DataTag Bool (Right id_)) = "dataToTag" <> parens (pretty id_) -expr_ _ (DataTag hty@(Sum _ _) (Left id_)) =- "std_logic_vector" <> parens ("resize" <> parens ("unsigned" <> parens ("std_logic_vector" <> parens (pretty id_)) <> "," <> int (typeSize hty)))+expr_ _ (DataTag hty@(Sum _ _) (Left id_)) = do+ RenderEnums enums <- Ap renderEnums+ nm <- Ap $ use modNm++ let inner = "std_logic_vector" <> parens ("resize" <> parens ("unsigned" <> parens ("std_logic_vector" <> parens (pretty id_)) <> "," <> int (typeSize hty)))+ if enums then pretty nm <> "_types.fromSLV" <> parens inner else inner+ expr_ _ (DataTag (Sum _ _) (Right id_)) = do- iw <- Mon $ use intWidth- "signed" <> parens ("std_logic_vector" <> parens ("resize" <> parens ("unsigned" <> parens (pretty id_) <> "," <> int iw)))+ RenderEnums enums <- Ap renderEnums+ iw <- Ap $ use intWidth+ nm <- Ap $ use modNm + let inner = if enums then pretty nm <> "_types.toSLV" <> parens (pretty id_) else pretty id_+ "signed" <> parens ("std_logic_vector" <> parens ("resize" <> parens ("unsigned" <> parens inner <> "," <> int iw)))+ expr_ _ (DataTag (Product {}) (Right _)) = do- iw <- Mon $ use intWidth+ iw <- Ap $ use intWidth "to_signed" <> parens (int 0 <> "," <> int iw) expr_ _ (DataTag hty@(SP _ _) (Right id_)) = do {- ; iw <- Mon $ use intWidth+ ; iw <- Ap $ use intWidth ; "signed" <> parens ("std_logic_vector" <> parens ( "resize" <> parens ("unsigned" <> parens (pretty id_ <> parens (int start <+> "downto" <+> int end)) <> "," <> int iw)))@@ -1643,30 +1749,31 @@ end = typeSize hty - conSize hty expr_ _ (DataTag (Vector 0 _) (Right _)) = do- iw <- Mon $ use intWidth+ iw <- Ap $ use intWidth "to_signed" <> parens (int 0 <> "," <> int iw) expr_ _ (DataTag (Vector _ _) (Right _)) = do- iw <- Mon $ use intWidth+ iw <- Ap $ use intWidth "to_signed" <> parens (int 1 <> "," <> int iw) expr_ _ (DataTag (RTree 0 _) (Right _)) = do- iw <- Mon $ use intWidth+ iw <- Ap $ use intWidth "to_signed" <> parens (int 0 <> "," <> int iw) expr_ _ (DataTag (RTree _ _) (Right _)) = do- iw <- Mon $ use intWidth+ iw <- Ap $ use intWidth "to_signed" <> parens (int 1 <> "," <> int iw) expr_ _ (ToBv topM hwty e) = do- nm <- Mon $ use modNm+ nm <- Ap $ use modNm case topM of Nothing -> pretty nm <> "_types" <> dot <> "toSLV" <> parens (qualTyName hwty <> "'" <> parens (expr_ False e)) Just t -> pretty t <> dot <> pretty t <> "_types" <> dot <> "toSLV" <> parens (expr_ False e) -expr_ _ (FromBv topM _ e) = do- nm <- Mon $ use modNm- maybe (pretty nm <> "_types" ) (\t -> pretty t <> dot <> pretty t <> "_types") topM <> dot <>- "fromSLV" <> parens (expr_ False e)+expr_ _ (FromBv topM hwty e) = do+ nm <- Ap $ use modNm+ qualTyName hwty <> "'" <> parens+ (maybe (pretty nm <> "_types" ) (\t -> pretty t <> dot <> pretty t <> "_types") topM <>+ dot <> "fromSLV" <> parens (expr_ False e)) expr_ _ e = error $ $(curLoc) ++ (show e) -- empty @@ -1727,11 +1834,19 @@ patLit :: HWType -> Literal -> VHDLM Doc patLit Bit (NumLit i) = if i == 0 then "'0'" else "'1'"-patLit hwTy (NumLit i) =- let sz = conSize hwTy- in case sz `mod` 4 of- 0 -> hex (toHex sz i)- _ -> bits (toBits sz i)+patLit hwty (NumLit i) = do+ RenderEnums enums <- Ap renderEnums++ case hwty of+ Sum{} | enums ->+ tyName hwty <> "'" <> parens (enumVariantName hwty (fromInteger i))++ _ ->+ let sz = conSize hwty+ in case sz `mod` 4 of+ 0 -> hex (toHex sz i)+ _ -> bits (toBits sz i)+ patLit _ l = exprLit Nothing l patMod :: HWType -> Literal -> Literal@@ -1768,7 +1883,7 @@ bit_char H = char '1' bit_char L = char '0' bit_char U = do- udf <- Mon (use undefValue)+ udf <- Ap (use undefValue) case udf of Nothing -> char '-' Just Nothing -> char '0'@@ -1777,25 +1892,31 @@ toSLV :: HasCallStack => HWType -> Expr -> VHDLM Doc toSLV Bool e = do- nm <- Mon $ use modNm+ nm <- Ap $ use modNm pretty nm <> "_types.toSLV" <> parens (expr_ False e) toSLV Bit e = do- nm <- Mon $ use modNm+ nm <- Ap $ use modNm pretty nm <> "_types.toSLV" <> parens (expr_ False e) toSLV (Clock {}) e = do- nm <- Mon $ use modNm+ nm <- Ap $ use modNm pretty nm <> "_types.toSLV" <> parens (expr_ False e) toSLV (Reset {}) e = do- nm <- Mon $ use modNm+ nm <- Ap $ use modNm pretty (TextS.toLower nm) <> "_types.toSLV" <> parens (expr_ False e) toSLV (Enable _) e = do- nm <- Mon $ use modNm+ nm <- Ap $ use modNm pretty nm <> "_types.toSLV" <> parens (expr_ False e) toSLV (BitVector _) e = expr_ True e toSLV (Signed _) e = "std_logic_vector" <> parens (expr_ False e) toSLV (Unsigned _) e = "std_logic_vector" <> parens (expr_ False e) toSLV (Index _) e = "std_logic_vector" <> parens (expr_ False e)-toSLV (Sum _ _) e = expr_ False e+toSLV (Sum _ _) e = do+ RenderEnums enums <- Ap renderEnums+ if enums then do+ nm <- Ap $ use modNm+ pretty nm <> "_types.toSLV" <> parens (expr_ False e)+ else+ expr_ False e toSLV (CustomSum _ _dataRepr size reprs) (DataCon _ (DC (_,i)) _) = let (ConstrRepr' _ _ _ value _) = fst $ reprs !! i in let unsigned = "to_unsigned" <> parens (int (fromIntegral value) <> comma <> int size) in@@ -1816,7 +1937,7 @@ -- need to do anything. expr_ False e toSLV t@(Product _ _ _) e = do- nm <- Mon $ use modNm+ nm <- Ap $ use modNm pretty nm <> "_types.toSLV" <> parens (qualTyName t <> "'" <> parens (expr_ False e)) toSLV (SP _ _) e = expr_ False e toSLV (CustomSP _ _ _ _) e =@@ -1825,7 +1946,7 @@ expr_ False e toSLV (Vector n elTy) (Identifier id_ Nothing) = do selIds' <- sequence selIds- syn <- Mon hdlSyn+ syn <- Ap hdlSyn parens (vcat $ punctuate " & " (case syn of Vivado -> mapM (expr_ False) selIds'@@ -1835,15 +1956,15 @@ selIds = map (fmap (`Identifier` Nothing)) selNames -- Don't split up newtype wrappers, or void-filtered types toSLV (Vector _ _) e@(DataCon _ (DC (Void Nothing, -1)) _) = do- nm <- Mon $ use modNm+ nm <- Ap $ use modNm pretty nm <> "_types.toSLV" <> parens (expr_ False e) toSLV (Vector n elTy) (DataCon _ _ es) = "std_logic_vector'" <> (parens $ vcat $ punctuate " & " (zipWithM toSLV [elTy,Vector (n-1) elTy] es)) toSLV (Vector _ _) e = do- nm <- Mon $ use modNm+ nm <- Ap $ use modNm pretty nm <> "_types.toSLV" <> parens (expr_ False e) toSLV (RTree _ _) e = do- nm <- Mon (use modNm)+ nm <- Ap (use modNm) pretty (TextS.toLower nm) <> "_types.toSLV" <> parens (expr_ False e) toSLV hty e = error $ $(curLoc) ++ "toSLV:\n\nType: " ++ show hty ++ "\n\nExpression: " ++ show e @@ -1856,11 +1977,11 @@ rarrow :: VHDLM Doc rarrow = "=>" -parenIf :: Monad m => Bool -> Mon m Doc -> Mon m Doc+parenIf :: Monad m => Bool -> Ap m Doc -> Ap m Doc parenIf True = parens parenIf False = id -punctuate' :: Monad m => Mon m Doc -> Mon m [Doc] -> Mon m Doc+punctuate' :: Monad m => Ap m Doc -> Ap m [Doc] -> Ap m Doc punctuate' s d = vcat (punctuate s d) <> s encodingNote :: HWType -> VHDLM Doc@@ -2198,30 +2319,31 @@ renderModifier (Select sel,_) doc = doc <> sel -- See [Note] integer projection renderModifier (Resize,ty) doc = do- iw <- Mon (use intWidth)+ iw <- Ap (use intWidth) -- These integer projections always come last, so it's safe not to return a -- modified name, but an expression instead. traceIf (iw < typeSize ty) ($(curLoc) ++ "WARNING: result smaller than argument") $ "resize" <> parens (doc <> "," <> int iw) renderModifier (ResizeAndConvert,ty) doc = do- iw <- Mon (use intWidth)+ iw <- Ap (use intWidth) -- These natural projections always come last, so it's safe not to return a -- modified name, but an expression instead. traceIf (iw < typeSize ty) ($(curLoc) ++ "WARNING: result smaller than argument") $ "resize" <> parens ("unsigned" <> parens doc <> "," <> int iw) -- See [Note] mask projection renderModifier (DontCare,_) _ = do- iw <- Mon (use intWidth)+ iw <- Ap (use intWidth) -- These mask projections always come last, so it's safe not to return a -- modified name, but an expression instead. traceIf True ($(curLoc) ++ "WARNING: rendering bitvector mask as dontcare") $ sizedQualTyNameErrValue (Unsigned iw) renderModifier (Range r,t) doc = do- nm <- Mon (use modNm)+ nm <- Ap (use modNm)+ enums <- Ap renderEnums let doc1 = case r of Contiguous start end -> slice start end Split rs -> parens (hcat (punctuate " & " (mapM (\(s,e,_) -> slice s e) rs)))- case normaliseType t of+ case normaliseType enums t of BitVector _ -> doc1 -- See [Note] Continuing from an SLV slice _ ->
src/Clash/Backend/Verilog.hs view
@@ -1,8 +1,9 @@ {-| Copyright : (C) 2015-2016, University of Twente,- 2017-2018, Google Inc.+ 2017-2018, Google Inc.,+ 2021-2022, QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Generate Verilog for assorted Netlist datatypes -}@@ -34,19 +35,21 @@ import Control.Lens (Lens',(+=),(-=),(.=),(%=), makeLenses, use) import Control.Monad (forM) import Control.Monad.State (State)+import Data.Bifunctor (first, second) import Data.Bits (Bits, testBit)+import qualified Data.ByteString.Char8 as B8+import Data.Coerce (coerce)+import Data.Function (on) import Data.HashMap.Strict (HashMap) import qualified Data.HashMap.Strict as HashMap import Data.HashSet (HashSet) import qualified Data.HashSet as HashSet import Data.Maybe (catMaybes, fromMaybe)+import Data.Monoid (Ap(Ap))+import Data.Monoid.Extra () import Data.List (mapAccumL, mapAccumR, nubBy, foldl') import Data.List.Extra ((<:>))-#if !MIN_VERSION_base(4,11,0)-import Data.Monoid hiding (Product, Sum)-#endif-import Data.Semigroup.Monad.Extra import Data.Text.Lazy (pack) import qualified Data.Text.Lazy as Text import qualified Data.Text as TextS@@ -64,6 +67,8 @@ import Clash.Core.Var (Attr'(..)) import Clash.Backend import Clash.Debug (traceIf)+import Clash.Driver.Types (ClashOpts(..))+import Clash.Explicit.BlockRam.Internal (unpackNats) import Clash.Netlist.BlackBox.Types (HdlSyn) import Clash.Netlist.BlackBox.Util (extractLiterals, renderBlackBox, renderFilePath)@@ -72,7 +77,7 @@ import Clash.Netlist.Util import Clash.Signal.Internal (ActiveEdge (..)) import Clash.Util- (SrcSpan, noSrcSpan, curLoc, on, first, indexNote, makeCached, second)+ (SrcSpan, noSrcSpan, curLoc, indexNote, makeCached) -- | State for the 'Clash.Backend.Verilog.VerilogM' monad: data VerilogState =@@ -94,6 +99,7 @@ , _hdlsyn :: HdlSyn , _undefValue :: Maybe (Maybe Int) , _aggressiveXOptBB_ :: AggressiveXOptBB+ , _domainConfigurations_ :: DomainMap } makeLenses ''VerilogState@@ -102,9 +108,9 @@ identifierSet = idSeen instance Backend VerilogState where- initBackend iw hdlsyn_ esc lw undefVal xOpt = VerilogState+ initBackend opts = VerilogState { _genDepth=0- , _idSeen=Id.emptyIdentifierSet esc lw Verilog+ , _idSeen=Id.emptyIdentifierSet (opt_escapedIds opts) (opt_lowerCaseBasicIds opts) Verilog , _srcSpan=noSrcSpan , _includes=[] , _imports=HashSet.empty@@ -112,10 +118,11 @@ , _dataFiles=[] , _memoryDataFiles=[] , _customConstrs=HashMap.empty- , _intWidth=iw- , _hdlsyn=hdlsyn_- , _undefValue=undefVal- , _aggressiveXOptBB_=xOpt+ , _intWidth=opt_intWidth opts+ , _hdlsyn=opt_hdlSyn opts+ , _undefValue=opt_forceUndefined opts+ , _aggressiveXOptBB_=coerce (opt_aggressiveXOptBB opts)+ , _domainConfigurations_=emptyDomainMap } hdlKind = const Verilog primDirs = const $ do root <- primsRoot@@ -178,8 +185,11 @@ getMemoryDataFiles = use memoryDataFiles ifThenElseExpr _ = True aggressiveXOptBB = use aggressiveXOptBB_+ renderEnums = pure (RenderEnums False)+ domainConfigurations = use domainConfigurations_+ setDomainConfigurations confs s = s {_domainConfigurations_ = confs} -type VerilogM a = Mon (State VerilogState) a+type VerilogM a = Ap (State VerilogState) a -- | Generate Verilog for a Netlist component genVerilog@@ -193,11 +203,11 @@ -- -- TODO: Collect all type names up front, to prevent relatively costly union. -- TODO: Investigate whether type names / signal names collide in the first place- Mon $ idSeen %= Id.union seen+ Ap $ idSeen %= Id.union seen - Mon (setSrcSpan sp)+ Ap (setSrcSpan sp) v <- commentHeader <> line <> timescale <> line <> module_ c- incs <- Mon $ use includes+ incs <- Ap $ use includes return ((TextS.unpack (Id.toText cName), v), incs) where cName = componentName c@@ -226,12 +236,12 @@ module_ :: Component -> VerilogM Doc module_ c =- modVerilog <* Mon (imports .= HashSet.empty >> libraries .= HashSet.empty)+ modVerilog <* Ap (imports .= HashSet.empty >> libraries .= HashSet.empty) where modVerilog = do body <- modBody- imps <- Mon $ use imports- libs <- Mon $ use libraries+ imps <- Ap $ use imports+ libs <- Ap $ use libraries modHeader <> line <> modPorts <> line <> include (HashSet.toList imps) <> uselibs (HashSet.toList libs) <>@@ -264,13 +274,13 @@ <> (if null xs then emptyDoc else line <> vcat (forM xs commafy)) <> line <> rparen -include :: Monad m => [Text.Text] -> Mon m Doc+include :: Monad m => [Text.Text] -> Ap m Doc include [] = emptyDoc include xs = line <> indent 2 (vcat (mapM (\i -> string "`include" <+> dquotes (string i)) xs)) <> line <> line -uselibs :: Monad m => [Text.Text] -> Mon m Doc+uselibs :: Monad m => [Text.Text] -> Ap m Doc uselibs [] = emptyDoc uselibs xs = line <> -- NOTE: We must produce a single uselib directive as later ones overwrite earlier ones.@@ -304,7 +314,7 @@ -- | Convert a Netlist HWType to an error Verilog value for that type verilogTypeErrValue :: HWType -> VerilogM Doc verilogTypeErrValue ty = do- udf <- Mon (use undefValue)+ udf <- Ap (use undefValue) case udf of Nothing -> braces (int (typeSize ty) <+> braces "1'bx") Just Nothing -> int (typeSize ty) <> "'d0 /* undefined */"@@ -366,7 +376,8 @@ insts :: [Declaration] -> VerilogM Doc insts [] = emptyDoc-insts (TickDecl id_:ds) = comment "//" id_ <> line <> insts ds+insts (TickDecl (Comment c):ds) = comment "//" c <> line <> insts ds+insts (TickDecl (Directive d):ds) = pretty d <> ";" <> line <> insts ds insts (d:ds) = do docM <- inst_ d case docM of@@ -511,12 +522,15 @@ | otherwise = addAttrs attrs line inst_ (BlackBoxD _ libs imps inc bs bbCtx) =- fmap Just (Mon (column (renderBlackBox libs imps inc bs bbCtx)))+ fmap Just (Ap (column (renderBlackBox libs imps inc bs bbCtx))) inst_ (Seq ds) = Just <$> seqs ds inst_ (NetDecl' {}) = return Nothing +inst_ (ConditionalDecl cond ds) = Just <$>+ "`ifdef" <+> pretty cond <> line <> indent 2 (insts ds) <> line <> "`endif"+ seq_ :: Seq -> VerilogM Doc seq_ (AlwaysClocked edge clk ds) = "always @" <>@@ -570,7 +584,8 @@ seqs :: [Seq] -> VerilogM Doc seqs [] = emptyDoc-seqs (SeqDecl (TickDecl id_):ds) = "//" <+> stringS id_ <> line <> seqs ds+seqs (SeqDecl (TickDecl (Comment c)):ds) = comment "//" c <> line <> seqs ds+seqs (SeqDecl (TickDecl (Directive d)):ds) = pretty d <> ";" <> line <> seqs ds seqs (d:ds) = seq_ d <> line <> line <> seqs ds -- | Range slice, can be contiguous, or split into multiple sub-ranges@@ -851,12 +866,12 @@ _ -> error "internal error" customReprDataCon dataRepr constrRepr args = do funId <- mkConstrFunction- Mon (imports %= HashSet.insert (Text.pack (TextS.unpack (Id.toText funId) ++ ".inc")))+ Ap (imports %= HashSet.insert (Text.pack (TextS.unpack (Id.toText funId) ++ ".inc"))) pretty funId <> tupled (mapM (expr_ False . snd) nzArgs) where nzArgs = filter ((/=0) . typeSize . fst) args - mkConstrFunction :: Mon (State VerilogState) Identifier+ mkConstrFunction :: Ap (State VerilogState) Identifier mkConstrFunction = makeCached (crName constrRepr) customConstrs $ do let size = drSize dataRepr aTys = map fst args@@ -903,7 +918,7 @@ indent 2 (pretty fId <+> "=" <+> val <> semi) <> line <> "end" <> line <> "endfunction"- Mon (includes %= ((TextS.unpack (Id.toText fId) ++ ".inc",funDoc):))+ Ap (includes %= ((TextS.unpack (Id.toText fId) ++ ".inc",funDoc):)) return fId -- | Turn a Netlist expression into a Verilog expression@@ -937,25 +952,25 @@ -- See [Note] integer projection expr_ _ (Identifier id_ (Just (Indexed ((Signed w),_,_)))) = do- iw <- Mon $ use intWidth+ iw <- Ap $ use intWidth traceIf (iw < w) ($(curLoc) ++ "WARNING: result smaller than argument") $ pretty id_ -- See [Note] integer projection expr_ _ (Identifier id_ (Just (Indexed ((Unsigned w),_,_)))) = do- iw <- Mon $ use intWidth+ iw <- Ap $ use intWidth traceIf (iw < w) ($(curLoc) ++ "WARNING: result smaller than argument") $ pretty id_ -- See [Note] mask projection expr_ _ (Identifier _ (Just (Indexed ((BitVector _),_,0)))) = do- iw <- Mon $ use intWidth+ iw <- Ap $ use intWidth traceIf True ($(curLoc) ++ "WARNING: synthesizing bitvector mask to dontcare") $ verilogTypeErrValue (Signed iw) -- See [Note] bitvector projection expr_ _ (Identifier id_ (Just (Indexed ((BitVector w),_,1)))) = do- iw <- Mon $ use intWidth+ iw <- Ap $ use intWidth traceIf (iw < w) ($(curLoc) ++ "WARNING: result smaller than argument") $ pretty id_ @@ -981,6 +996,17 @@ expr_ _ e@(DataCon (Vector _ _) _ es@[_,_]) = listBraces $ mapM (expr_ False) $ fromMaybe es $ vectorChain e +expr_ _ (DataCon (MemBlob n m) _ [n0, m0, _, runs, _, ends])+ | Literal _ (NumLit n1) <- n0+ , n == fromInteger n1+ , Literal _ (NumLit m1) <- m0+ , m == fromInteger m1+ , Literal Nothing (StringLit runs0) <- runs+ , Literal Nothing (StringLit ends0) <- ends+ , es <- unpackNats n m (B8.pack runs0) (B8.pack ends0) =+ let el val = exprLitV (Just (BitVector m, m)) (BitVecLit 0 $ toInteger val)+ in listBraces $ mapM el es+ expr_ _ (DataCon (RTree 0 _) _ [e]) = expr_ False e expr_ _ e@(DataCon (RTree _ _) _ es@[_,_]) = listBraces $ mapM (expr_ False) $ fromMaybe es $ rtreeChain e@@ -1047,18 +1073,18 @@ = exprLit undefValue (Just (Index (fromInteger n),fromInteger n)) i expr_ b (BlackBoxE _ libs imps inc bs bbCtx b') = do- parenIf (b || b') (Mon (renderBlackBox libs imps inc bs bbCtx <*> pure 0))+ parenIf (b || b') (Ap (renderBlackBox libs imps inc bs bbCtx <*> pure 0)) expr_ _ (DataTag Bool (Left id_)) = pretty id_ <> brackets (int 0) expr_ _ (DataTag Bool (Right id_)) = do- iw <- Mon (use intWidth)+ iw <- Ap (use intWidth) "$unsigned" <> parens (listBraces (sequence [braces (int (iw-1) <+> braces "1'b0"),pretty id_])) expr_ _ (DataTag (Sum _ _) (Left id_)) = "$unsigned" <> parens (pretty id_) expr_ _ (DataTag (Sum _ _) (Right id_)) = "$unsigned" <> parens (pretty id_) expr_ _ (DataTag (Product {}) (Right _)) = do- iw <- Mon (use intWidth)+ iw <- Ap (use intWidth) int iw <> "'sd0" expr_ _ (DataTag hty@(SP _ _) (Right id_)) = "$unsigned" <> parens@@ -1069,17 +1095,17 @@ end = typeSize hty - conSize hty expr_ _ (DataTag (Vector 0 _) (Right _)) = do- iw <- Mon $ use intWidth+ iw <- Ap $ use intWidth int iw <> "'sd0" expr_ _ (DataTag (Vector _ _) (Right _)) = do- iw <- Mon $ use intWidth+ iw <- Ap $ use intWidth int iw <> "'sd1" expr_ _ (DataTag (RTree 0 _) (Right _)) = do- iw <- Mon $ use intWidth+ iw <- Ap $ use intWidth int iw <> "'sd0" expr_ _ (DataTag (RTree _ _) (Right _)) = do- iw <- Mon $ use intWidth+ iw <- Ap $ use intWidth int iw <> "'sd1" expr_ b (ToBv _ _ e) = expr_ b e@@ -1109,7 +1135,7 @@ exprLitV :: Maybe (HWType,Size) -> Literal -> VerilogM Doc exprLitV = exprLit undefValue -exprLit :: Lens' s (Maybe (Maybe Int)) -> Maybe (HWType,Size) -> Literal -> Mon (State s) Doc+exprLit :: Lens' s (Maybe (Maybe Int)) -> Maybe (HWType,Size) -> Literal -> Ap (State s) Doc exprLit _ Nothing (NumLit i) = integer i exprLit k (Just (hty,sz)) (NumLit i) = case hty of@@ -1148,7 +1174,7 @@ ( map (`mod` 2) $ iterate (`div` 2) val) -bits :: Lens' s (Maybe (Maybe Int)) -> [Bit] -> Mon (State s) Doc+bits :: Lens' s (Maybe (Maybe Int)) -> [Bit] -> Ap (State s) Doc bits k = hcat . traverse (bit_char k) bit_char' :: Bit -> Char@@ -1157,9 +1183,9 @@ bit_char' U = 'x' bit_char' Z = 'z' -bit_char :: Lens' s (Maybe (Maybe Int)) -> Bit -> Mon (State s) Doc+bit_char :: Lens' s (Maybe (Maybe Int)) -> Bit -> Ap (State s) Doc bit_char k b = do- udf <- Mon (use k)+ udf <- Ap (use k) case (udf,b) of (Just Nothing,U) -> char '0' (Just (Just i),U) -> "'" <> int i <> "'"@@ -1176,7 +1202,7 @@ parenIf True = parens parenIf False = id -punctuate' :: Monad m => Mon m Doc -> Mon m [Doc] -> Mon m Doc+punctuate' :: Monad m => Ap m Doc -> Ap m [Doc] -> Ap m Doc punctuate' s d = vcat (punctuate s d) <> s encodingNote :: Applicative m => HWType -> m Doc
src/Clash/Core/DataCon.hs view
@@ -1,8 +1,9 @@ {-| Copyright : (C) 2012-2016, University of Twente,- 2017, Google Inc.+ 2017, Google Inc.,+ 2021, QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Data Constructors in CoreHW -}@@ -11,17 +12,19 @@ {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TemplateHaskell #-} module Clash.Core.DataCon ( DataCon (..) , DcName , ConTag+ , DcStrictness(..) ) where import Control.DeepSeq (NFData(..)) import Data.Binary (Binary)+import Data.Function (on)+import Data.Hashable (Hashable) import qualified Data.Text as Text import GHC.Generics (Generic) @@ -29,7 +32,6 @@ import {-# SOURCE #-} Clash.Core.Type (Type) import Clash.Core.Var (TyVar) import Clash.Unique-import Clash.Util -- | Data Constructor data DataCon@@ -50,6 +52,8 @@ -- part of the result of the DataCon, but only of the arguments. , dcArgTys :: [Type] -- ^ Argument types+ , dcArgStrict :: [DcStrictness]+ -- ^ Argument strictness , dcFieldLabels :: [Text.Text] -- ^ Names of fields. Used when data constructor is referring to a record type. } deriving (Generic,NFData,Binary)@@ -72,3 +76,8 @@ type ConTag = Int -- | DataCon reference type DcName = Name DataCon++data DcStrictness+ = Strict+ | Lazy+ deriving (Generic, NFData, Eq, Hashable, Binary)
src/Clash/Core/EqSolver.hs view
@@ -130,26 +130,26 @@ lhsLit (LitTy (NumTy n)) y = Just (n, y) lhsLit _ _ = Nothing --- | Tests for unreachable alternative due to types being "absurd". See+-- | Tests for nonsencical patterns due to types being "absurd". See -- @isAbsurdEq@ for more info.-isAbsurdAlt+isAbsurdPat :: TyConMap- -> Alt+ -> Pat -> Bool #if MIN_VERSION_base(4,15,0)-isAbsurdAlt _tcm (DataPat dc _ _,_)- -- unsafeCoerce is not absurd in the way intended by /isAbsurdAlt/+isAbsurdPat _tcm (DataPat dc _ _)+ -- unsafeCoerce is not absurd in the way intended by /isAbsurdPat/ | dcUniq dc == getKey unsafeReflDataConKey = False #endif-isAbsurdAlt tcm alt =- any (isAbsurdEq tcm exts) (altEqs tcm alt)+isAbsurdPat tcm pat =+ any (isAbsurdEq tcm exts) (patEqs tcm pat) where- exts = case alt of- (DataPat _dc extNms _ids,_) -> mkVarSet extNms+ exts = case pat of+ DataPat _dc extNms _ids -> mkVarSet extNms _ -> emptyVarSet --- | Determines if an "equation" obtained through @altEqs@ or @typeEq@ is+-- | Determines if an "equation" obtained through @patEqs@ or @typeEq@ is -- absurd. That is, it tests if two types that are definitely not equal are -- asserted to be equal OR if the computation of the types yield some absurd -- (intermediate) result such as -1.@@ -164,11 +164,11 @@ lr -> any (==AbsurdSolution) (solveEq tcm exts lr) -- | Get constraint equations-altEqs+patEqs :: TyConMap- -> Alt+ -> Pat -> [(Type, Type)]-altEqs tcm (pat, _term) =+patEqs tcm pat = catMaybes (map (typeEq tcm . varType) (snd (patIds pat))) -- | If type is an equation, return LHS and RHS.
src/Clash/Core/Evaluator/Types.hs view
@@ -2,9 +2,9 @@ {-# LANGUAGE OverloadedStrings #-} {-|- Copyright : (C) 2020, QBayLogic B.V.+ Copyright : (C) 2020-2021, QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Types for the Partial Evaluator -}@@ -23,10 +23,10 @@ #endif import Clash.Core.DataCon (DataCon)+import Clash.Core.HasType import Clash.Core.Literal (Literal(CharLiteral)) import Clash.Core.Pretty (fromPpr, ppr, showPpr) import Clash.Core.Term (Term(..), PrimInfo(..), TickInfo, Alt)-import Clash.Core.TermInfo (termType) import Clash.Core.TyCon (TyConMap) import Clash.Core.Type (Type) import Clash.Core.Var (Id, IdScope(..), TyVar)@@ -62,7 +62,7 @@ whnf eval tcm isSubj m | isSubj = -- See [Note: empty case expressions]- let ty = termType tcm (mTerm m)+ let ty = inferCoreTypeOf tcm (mTerm m) in go (stackPush (Scrutinise ty []) m) | otherwise = go m where@@ -234,7 +234,7 @@ clashPretty (Apply i) = hsep ["Apply", fromPpr i] clashPretty (Instantiate t) = hsep ["Instantiate", fromPpr t] clashPretty (PrimApply p tys vs ts) =- hsep ["PrimApply", fromPretty (primName p), "::", fromPpr (primType p),+ hsep ["PrimApply", fromPretty (primName p), "::", fromPpr (coreTypeOf p), "; type args=", fromPpr tys, "; val args=", fromPpr (map valToTerm vs), "term args=", fromPpr ts]@@ -355,4 +355,3 @@ setTerm :: Term -> Machine -> Machine setTerm x m = m { mTerm = x }-
src/Clash/Core/FreeVars.hs view
@@ -1,7 +1,8 @@ {-| Copyright : (C) 2012-2016, University of Twente+ 2021, QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Free variable calculations -}@@ -17,16 +18,8 @@ , freeLocalIds , globalIds , termFreeTyVars- , tyFVsOfTypes- , localFVsOfTerms- , hasLocalFreeVars- -- * Fast- , noFreeVarsOfType -- * occurrence check- , localIdOccursIn , globalIdOccursIn- , localIdDoesNotOccurIn- , localIdsDoNotOccurIn , localVarsDoNotOccurIn , countFreeOccurances -- * Internal@@ -42,12 +35,12 @@ import qualified Data.IntSet as IntSet import Data.Monoid (All (..), Any (..)) -import Clash.Core.Term (Pat (..), Term (..), TickInfo (..))+import Clash.Core.Term (Pat (..), Term (..), TickInfo (..), Bind(..)) import Clash.Core.Type (Type (..)) import Clash.Core.Var (Id, IdScope (..), TyVar, Var (..), isLocalId) import Clash.Core.VarEnv- (VarEnv, VarSet, emptyVarEnv, unionVarEnvWith, unitVarSet, unitVarEnv)+ (VarEnv, emptyVarEnv, unionVarEnvWith, unitVarEnv) -- | Gives the free type-variables in a Type, implemented as a 'Fold' --@@ -116,21 +109,6 @@ goBndr inScope tv = (\t -> tv {varType = t}) <$> go inScope (varType tv) --- | Check whether an identifier does not occur free in a term-localIdDoesNotOccurIn- :: Id- -> Term- -> Bool-localIdDoesNotOccurIn v e = getAll (Lens.foldMapOf freeLocalIds (All . (/= v)) e)---- | Check whether a set of identifiers does not occur free in a term-localIdsDoNotOccurIn- :: [Id]- -> Term- -> Bool-localIdsDoNotOccurIn vs e =- getAll (Lens.foldMapOf freeLocalIds (All . (`notElem` vs)) e)- -- | Check whether a set of variables does not occur free in a term localVarsDoNotOccurIn :: [Var a]@@ -140,13 +118,6 @@ getAll (Lens.foldMapOf freeLocalVars (All . (`notElem` vs)) e) -- | Check whether a local identifier occurs free in a term-localIdOccursIn- :: Id- -> Term- -> Bool-localIdOccursIn v e = getAny (Lens.foldMapOf freeLocalIds (Any . (== v)) e)---- | Check whether a local identifier occurs free in a term globalIdOccursIn :: Id -> Term@@ -179,12 +150,6 @@ isGlobalId (Id {idScope = GlobalId}) = True isGlobalId _ = False --- | Determines if term has any locally free variables. That is, the free type--- variables and the free identifiers that are not bound in the global--- scope.-hasLocalFreeVars :: Term -> Bool-hasLocalFreeVars = Lens.notNullOf freeLocalVars- -- | Gives the free type-variables of a Term, implemented as a 'Fold' -- -- The 'Fold' is closed over the types of variables, so:@@ -259,12 +224,16 @@ TyApp <$> go inLocalScope l <*> typeFreeVars' interesting inLocalScope f r - Letrec bs e ->- Letrec <$> traverse (goBind inLocalScope') bs- <*> go inLocalScope' e- where- inLocalScope' = foldr IntSet.insert inLocalScope (map (varUniq.fst) bs)+ Let (NonRec i x) e ->+ Let <$> (NonRec <$> goBndr inLocalScope i <*> go inLocalScope x)+ <*> go (IntSet.insert (varUniq i) inLocalScope) e + Let (Rec bs) e ->+ Let <$> (Rec <$> traverse (goBind inLocalScope') bs)+ <*> go inLocalScope' e+ where+ inLocalScope' = foldr (IntSet.insert . varUniq . fst) inLocalScope bs+ Case subj ty alts -> Case <$> go inLocalScope subj <*> typeFreeVars' interesting inLocalScope f ty@@ -300,34 +269,6 @@ goTick inLocalScope = \case NameMod m ty -> NameMod m <$> typeFreeVars' interesting inLocalScope f ty tick -> pure tick---- | Determine whether a type has no free type variables.-noFreeVarsOfType- :: Type- -> Bool-noFreeVarsOfType ty = case ty of- VarTy {} -> False- ForAllTy {} -> getAll (Lens.foldMapOf typeFreeVars (const (All False)) ty)- AppTy l r -> noFreeVarsOfType l && noFreeVarsOfType r- _ -> True---- | Collect the free variables of a collection of type into a set-tyFVsOfTypes- :: Foldable f- => f Type- -> VarSet-tyFVsOfTypes = foldMap go- where- go = Lens.foldMapOf typeFreeVars unitVarSet---- | Collect the free variables of a collection of terms into a set-localFVsOfTerms- :: Foldable f- => f Term- -> VarSet-localFVsOfTerms = foldMap go- where- go = Lens.foldMapOf freeLocalVars unitVarSet -- | Get the free variables of an expression and count the number of occurrences countFreeOccurances
+ src/Clash/Core/HasFreeVars.hs view
@@ -0,0 +1,93 @@+{-|+Copyright : (C) 2021, QBayLogic B.V.+License : BSD2 (see the file LICENSE)+Maintainer : QBayLogic B.V. <devops@qbaylogic.com>++Utility class to extract free variables from data which has variables.+-}++{-# LANGUAGE FlexibleInstances #-}++module Clash.Core.HasFreeVars+ ( HasFreeVars(..)+ ) where++import Control.Lens as Lens (foldMapOf)+import Data.Monoid (All(..), Any(..))++import Clash.Core.FreeVars+import Clash.Core.Term (Term)+import Clash.Core.Type (Type(..))+import Clash.Core.Var (Var)+import Clash.Core.VarEnv++class HasFreeVars a where+ {-# MINIMAL freeVarsOf #-}++ freeVarsOf :: a -> VarSet++ {-# INLINE isClosed #-}+ -- | Something is closed if it has no free variables.+ -- This function may be replaced with a more efficient implementation.+ isClosed :: a -> Bool+ isClosed = nullVarSet . freeVarsOf++ {-# INLINE elemFreeVars #-}+ -- | Check if a variable is free in the given value.+ -- This function may be replaced with a more efficient implementation.+ elemFreeVars :: Var a -> a -> Bool+ elemFreeVars v = elemVarSet v . freeVarsOf++ {-# INLINE notElemFreeVars #-}+ -- | Check if a variable is not free in the given value.+ -- This function may be replaced with a more efficient implementation.+ notElemFreeVars :: Var a -> a -> Bool+ notElemFreeVars x = notElemVarSet x . freeVarsOf++ {-# INLINE subsetFreeVars #-}+ -- | Check if all variables in a set are free in the given value.+ -- This function may be replaced with a more efficient implementation.+ subsetFreeVars :: VarSet -> a -> Bool+ subsetFreeVars xs = subsetVarSet xs . freeVarsOf++ {-# INLINE disjointFreeVars #-}+ -- | Check if no variables in a set are free in the given value.+ -- This function may be replaced with a more efficient implementation.+ disjointFreeVars :: VarSet -> a -> Bool+ disjointFreeVars xs = disjointVarSet xs . freeVarsOf++instance HasFreeVars Term where+ {-# INLINE freeVarsOf #-}+ freeVarsOf =+ Lens.foldMapOf freeLocalVars unitVarSet++ elemFreeVars v e =+ getAny (Lens.foldMapOf freeLocalVars (Any . (== v)) e)++ notElemFreeVars v e =+ getAll (Lens.foldMapOf freeLocalVars (All . (/= v)) e)++ disjointFreeVars vs e =+ getAll (Lens.foldMapOf freeLocalVars (All . (`notElem` vs)) e)++instance HasFreeVars Type where+ {-# INLINE freeVarsOf #-}+ freeVarsOf =+ Lens.foldMapOf typeFreeVars unitVarSet++ isClosed ty =+ case ty of+ VarTy{} -> False+ ForAllTy{} -> getAll (Lens.foldMapOf typeFreeVars (const (All False)) ty)+ AppTy l r -> isClosed l && isClosed r+ _ -> True++ elemFreeVars v ty =+ getAny (Lens.foldMapOf typeFreeVars (Any . (== v)) ty)++ notElemFreeVars v ty =+ getAll (Lens.foldMapOf typeFreeVars (All . (/= v)) ty)++instance (Foldable f, HasFreeVars a) => HasFreeVars (f a) where+ {-# INLINE freeVarsOf #-}+ freeVarsOf = foldMap freeVarsOf
+ src/Clash/Core/HasType.hs view
@@ -0,0 +1,264 @@+{-|+Copyright : (C) 2021, QBayLogic B.V.+License : BSD2 (see the file LICENSE)+Maintainer : QBayLogic B.V. <devops@qbaylogic.com>++Utility class to extract type information from data which has a type.+-}++{-# LANGUAGE CPP #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TemplateHaskell #-}++module Clash.Core.HasType+ ( HasType(..)+ , coreKindOf+ , InferType(..)+ , inferCoreKindOf+ , applyTypeToArgs+ , piResultTy+ , piResultTys+ ) where++import qualified Data.Text as Text (isInfixOf)++#if MIN_VERSION_prettyprinter(1,7,0)+import Prettyprinter (line)+#else+import Data.Text.Prettyprint.Doc (line)+#endif++import GHC.Stack (HasCallStack)++import Clash.Core.DataCon (DataCon(dcType))+import Clash.Core.HasFreeVars+import Clash.Core.Literal (Literal(..))+import Clash.Core.Name (Name(nameOcc))+import Clash.Core.Pretty+import Clash.Core.Subst+import Clash.Core.Term (Term(..), IsMultiPrim(..), PrimInfo(..), collectArgs)+import Clash.Core.TyCon (TyCon(tyConKind), TyConMap)+import Clash.Core.Type+import Clash.Core.TysPrim+import Clash.Core.Var (Var(varType))+import Clash.Core.VarEnv+import Clash.Debug (debugIsOn)+import Clash.Unique (lookupUniqMap')+import Clash.Util (curLoc, pprPanic)+import qualified Clash.Util.Interpolate as I++class HasType a where+ coreTypeOf :: a -> Type++coreKindOf :: (HasType a) => a -> Kind+coreKindOf = coreTypeOf+{-# INLINE coreKindOf #-}++instance HasType DataCon where+ coreTypeOf = dcType++instance HasType Literal where+ coreTypeOf = \case+ IntegerLiteral _ -> integerPrimTy+ IntLiteral _ -> intPrimTy+ WordLiteral _ -> wordPrimTy+ StringLiteral _ -> stringPrimTy+ FloatLiteral _ -> floatPrimTy+ DoubleLiteral _ -> doublePrimTy+ CharLiteral _ -> charPrimTy+ Int64Literal _ -> int64PrimTy+ Word64Literal _ -> word64PrimTy+ NaturalLiteral _ -> naturalPrimTy+ ByteArrayLiteral _ -> byteArrayPrimTy++instance HasType PrimInfo where+ coreTypeOf pr =+ case primMultiResult pr of+ SingleResult -> primType pr++ -- See Note [MultiResult type] in Clash.Normalize.Transformations.MultiPrim+ MultiResult+ | let (primArgs, primResTy) = splitFunForallTy (primType pr)+ , TyConApp tupTcNm tupArgs <- tyView primResTy+ , Text.isInfixOf "GHC.Tuple.(" (nameOcc tupTcNm)+ -> mkPolyFunTy primResTy (primArgs <> fmap Right tupArgs)++ | otherwise+ -> error "PrimInfo.coreTypeOf: MultiResult primitive without tuple type"++instance HasType TyCon where+ coreTypeOf = tyConKind++instance HasType Type where+ coreTypeOf = id++instance HasType (Var a) where+ coreTypeOf = varType++class InferType a where+ inferCoreTypeOf :: TyConMap -> a -> Type++inferCoreKindOf :: (InferType a) => TyConMap -> a -> Kind+inferCoreKindOf = inferCoreTypeOf+{-# INLINE inferCoreKindOf #-}++instance InferType Type where+ inferCoreTypeOf tcm ty =+ case tyView ty of+ FunTy{} ->+ liftedTypeKind++ TyConApp tc args ->+ piResultTys tcm (tyConKind (lookupUniqMap' tcm tc)) args++ OtherType{} ->+ case ty of+ ConstTy c -> error $ $(curLoc) ++ "inferCoreTypeOf: naked ConstTy: " ++ show c+ VarTy k -> varType k+ ForAllTy _ a -> inferCoreTypeOf tcm a+ LitTy NumTy{} -> typeNatKind+ LitTy SymTy{} -> typeSymbolKind+ AnnType _ a -> inferCoreTypeOf tcm a+ AppTy a b -> go a [b]+ where+ go (AppTy c d) args = go c (d : args)+ go c args = piResultTys tcm (inferCoreTypeOf tcm c) args++instance InferType Term where+ inferCoreTypeOf tcm = go+ where+ go = \case+ Var i -> coreTypeOf i+ Data dc -> coreTypeOf dc+ Literal l -> coreTypeOf l+ Prim pr -> coreTypeOf pr+ Lam i x -> mkFunTy (coreTypeOf i) (go x)+ TyLam i x -> ForAllTy i (go x)++ x@App{} ->+ case collectArgs x of+ (fun, args) -> applyTypeToArgs x tcm (go fun) args++ x@TyApp{} ->+ case collectArgs x of+ (fun, args) -> applyTypeToArgs x tcm (go fun) args++ Let _ x -> go x+ Case _ ty _ -> ty+ Cast _ _ a -> a+ Tick _ x -> go x++-- | Get the result type of a polymorphic function given a list of arguments+applyTypeToArgs+ :: Term+ -- ^ The complete term, used for error messages.+ -> TyConMap+ -> Type+ -> [Either Term Type]+ -> Type+applyTypeToArgs e m opTy args = go opTy args+ where+ go opTy' [] = opTy'+ go opTy' (Right ty:args') = goTyArgs opTy' [ty] args'+ go opTy' (Left a:args') = case splitFunTy m opTy' of+ Just (_,resTy) -> go resTy args'+ _ -> error [I.i|+ Unexpected application. The term++ #{showPpr e}++ applied an argument++ #{showPpr a}++ to something with the non-function type++ #{showPpr opTy'}+ |]++ goTyArgs opTy' revTys (Right ty:args') = goTyArgs opTy' (ty:revTys) args'+ goTyArgs opTy' revTys args' = go (piResultTys m opTy' (reverse revTys)) args'++-- | Like 'piResultTys', but only applies a single type. If multiple types are+-- being applied use 'piResultTys', as it is more efficient to only substitute+-- once with many types.+piResultTy+ :: HasCallStack+ => TyConMap+ -> Type+ -> Type+ -> Type+piResultTy m ty arg =+ piResultTys m ty [arg]++-- | @(piResultTys f_ty [ty1, ..., tyn])@ gives the type of @(f ty1 .. tyn)@+-- where @f :: f_ty@+--+-- 'piResultTys' is interesting because:+--+-- 1. 'f_ty' may have more foralls than there are args+-- 2. Less obviously, it may have fewer foralls+--+-- Fore case 2. think of:+--+-- piResultTys (forall a . a) [forall b.b, Int]+--+-- This really can happen, such as situations involving 'undefined's type:+--+-- undefined :: forall a. a+--+-- undefined (forall b. b -> b) Int+--+-- This term should have the type @(Int -> Int)@, but notice that there are+-- more type args than foralls in 'undefined's type.+--+-- For efficiency reasons, when there are no foralls, we simply drop arrows from+-- a function type/kind.+piResultTys+ :: HasCallStack+ => TyConMap+ -> Type+ -> [Type]+ -> Type+piResultTys _ ty [] = ty+piResultTys m ty origArgs@(arg:args)+ | Just ty' <- coreView1 m ty+ = piResultTys m ty' origArgs+ | FunTy a res <- tyView ty+ -- TODO coreView is used here because the partial evaluator will sometimes+ -- encounter / not encounter a Signal as an argument unexpectedly. When PR+ -- #1064 is merged the coreView calls should be removed again.+ = if debugIsOn && not (aeqType (coreView m a) (coreView m arg)) then error [I.i|+ Unexpected application. A function with type:++ #{showPpr ty}++ Got applied to an argument of type:++ #{showPpr arg}+ |]+ else+ piResultTys m res args+ | ForAllTy tv res <- ty+ = go (extendVarEnv tv arg emptyVarEnv) res args+ | otherwise+ = pprPanic "piResultTys1" (ppr ty <> line <> ppr origArgs)+ where+ inScope = mkInScopeSet (freeVarsOf (ty:origArgs))++ go env ty' [] = substTy (mkTvSubst inScope env) ty'+ go env ty' allArgs@(arg':args')+ | Just ty'' <- coreView1 m ty'+ = go env ty'' allArgs+ | FunTy _ res <- tyView ty'+ = go env res args'+ | ForAllTy tv res <- ty'+ = go (extendVarEnv tv arg' env) res args'+ | VarTy tv <- ty'+ , Just ty'' <- lookupVarEnv tv env+ -- Deals with (piResultTys (forall a.a) [forall b.b, Int])+ = piResultTys m ty'' allArgs+ | otherwise+ = pprPanic "piResultTys2" (ppr ty' <> line <> ppr origArgs <> line <> ppr allArgs)
src/Clash/Core/Literal.hs view
@@ -1,9 +1,10 @@ {-| Copyright : (C) 2012-2016, University of Twente, 2016 , Myrtle Software Ltd,- 2017 , Google Inc.+ 2017 , Google Inc.,+ 2021 , QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Term Literal -}@@ -14,25 +15,34 @@ module Clash.Core.Literal ( Literal (..)- , literalType- )-where+ ) where import Control.DeepSeq (NFData (..)) import Data.Binary (Binary) import Data.Hashable (Hashable) import Data.Primitive.ByteArray (ByteArray) import Data.Primitive.ByteArray.Extra ()+import Data.Word (Word32, Word64) import GHC.Generics (Generic) -import {-# SOURCE #-} Clash.Core.Type (Type)-import Clash.Core.TysPrim (intPrimTy, integerPrimTy,- charPrimTy, stringPrimTy,- wordPrimTy,- int64PrimTy, word64PrimTy,- floatPrimTy, doublePrimTy,- naturalPrimTy, byteArrayPrimTy)+{-+Note [Storage of floating point in Literal]+------------------------------------------- +GHC stores literals of 'Float' and 'Double' as 'Rational'. However, unlike+GHC, we also need to store transfinite "literals". We need to preserve all+information there is in a specific code word representing a floating point+value.++Storing them as 'Float' and 'Double' here introduces issues with 'Eq' and+'Hashable'. 0.0 == -0.0, and NaN compares unequal to everything including+itself.++Also unlike GHC, we already assume that 'Float' is single-precision IEEE-754,+and 'Double' is double-precision IEEE-754. So we can store them as 'Word32'+and 'Word64' and get the 'Eq' and hashing properties we require.+-}+ -- | Term Literal data Literal = IntegerLiteral !Integer@@ -41,24 +51,9 @@ | Int64Literal !Integer | Word64Literal !Integer | StringLiteral !String- | FloatLiteral !Rational- | DoubleLiteral !Rational+ | FloatLiteral !Word32+ | DoubleLiteral !Word64 | CharLiteral !Char | NaturalLiteral !Integer | ByteArrayLiteral !ByteArray deriving (Eq,Ord,Show,Generic,NFData,Hashable,Binary)---- | Determines the Type of a Literal-literalType :: Literal- -> Type-literalType (IntegerLiteral _) = integerPrimTy-literalType (IntLiteral _) = intPrimTy-literalType (WordLiteral _) = wordPrimTy-literalType (StringLiteral _) = stringPrimTy-literalType (FloatLiteral _) = floatPrimTy-literalType (DoubleLiteral _) = doublePrimTy-literalType (CharLiteral _) = charPrimTy-literalType (Int64Literal _) = int64PrimTy-literalType (Word64Literal _) = word64PrimTy-literalType (NaturalLiteral _) = naturalPrimTy-literalType (ByteArrayLiteral _) = byteArrayPrimTy
src/Clash/Core/Name.hs view
@@ -11,7 +11,6 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-} module Clash.Core.Name ( module Clash.Core.Name
src/Clash/Core/PartialEval/AsTerm.hs view
@@ -1,5 +1,5 @@ {-|-Copyright : (C) 2020 QBayLogic B.V.+Copyright : (C) 2020-2021, QBayLogic B.V. License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> @@ -16,12 +16,10 @@ ) where import Data.Bifunctor (first, second)-import Data.Graph (SCC(..), flattenSCCs) -import Clash.Core.FreeVars (localFVsOfTerms)+import Clash.Core.HasFreeVars import Clash.Core.PartialEval.NormalForm-import Clash.Core.Term (Term(..), LetBinding, Pat, Alt, mkApps)-import Clash.Core.Util (sccLetBindings)+import Clash.Core.Term (Bind(..), Term(..), Pat, Alt, mkApps) import Clash.Core.VarEnv (elemVarSet) -- | Convert a term in some normal form back into a Term. This is important,@@ -37,24 +35,19 @@ NePrim pr args -> mkApps (Prim pr) (argsToTerms args) NeApp x y -> App (asTerm x) (asTerm y) NeTyApp x ty -> TyApp (asTerm x) ty- NeLetrec bs x ->- let bs' = fmap (second asTerm) bs- x' = asTerm x- in removeUnusedBindings bs' x'-+ NeLet bs x -> removeUnusedBindings (fmap asTerm bs) (asTerm x) NeCase x ty alts -> Case (asTerm x) ty (altsToTerms alts) -removeUnusedBindings :: [LetBinding] -> Term -> Term+removeUnusedBindings :: Bind Term -> Term -> Term removeUnusedBindings bs x- | null used = x- | otherwise = Letrec used x+ | isUsed bs = Let bs x+ | otherwise = x where- free = localFVsOfTerms [x]- used = flattenSCCs $ filter isUsed (sccLetBindings bs)+ free = freeVarsOf x isUsed = \case- AcyclicSCC y -> fst y `elemVarSet` free- CyclicSCC ys -> any (flip elemVarSet free . fst) ys+ NonRec i _ -> elemVarSet i free+ Rec xs -> any (flip elemVarSet free . fst) xs instance AsTerm Value where asTerm = \case
src/Clash/Core/PartialEval/Monad.hs view
@@ -1,5 +1,5 @@ {-|-Copyright : (C) 2020, QBayLogic B.V.+Copyright : (C) 2020-2021, QBayLogic B.V. License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> @@ -73,7 +73,7 @@ import qualified Data.IntMap.Strict as IntMap import qualified Data.Map.Strict as Map -import Clash.Core.FreeVars (localFVsOfTerms, tyFVsOfTypes)+import Clash.Core.HasFreeVars import Clash.Core.Name (OccName) import Clash.Core.PartialEval.AsTerm import Clash.Core.PartialEval.NormalForm@@ -174,7 +174,7 @@ modifyLocalEnv goLocal x where goGlobal env@GlobalEnv{genvInScope=inScope} =- let fvs = unitVarSet i `unionVarSet` tyFVsOfTypes [a]+ let fvs = unitVarSet i `unionVarSet` freeVarsOf a iss = mkInScopeSet fvs `unionInScope` inScope in env { genvInScope = iss } @@ -201,8 +201,8 @@ modifyLocalEnv goLocal x where goGlobal env@GlobalEnv{genvInScope=inScope} =- -- TODO Is it a hack to use asTerm here?- let fvs = unitVarSet i `unionVarSet` localFVsOfTerms [asTerm v]+ -- TODO Change this to use an instance HasFreeVars Value+ let fvs = unitVarSet i `unionVarSet` freeVarsOf (asTerm v) iss = mkInScopeSet fvs `unionInScope` inScope in env { genvInScope = iss }
src/Clash/Core/PartialEval/NormalForm.hs view
@@ -1,5 +1,5 @@ {-|-Copyright : (C) 2020, QBayLogic B.V.+Copyright : (C) 2020-2021, QBayLogic B.V. License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> @@ -13,6 +13,7 @@ {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TemplateHaskell #-} module Clash.Core.PartialEval.NormalForm ( Arg@@ -36,9 +37,10 @@ import Clash.Core.DataCon (DataCon) import Clash.Core.Literal-import Clash.Core.Term (Term(..), PrimInfo(primName), TickInfo, Pat)+import Clash.Core.Term (Bind, Term(..), PrimInfo(primName), TickInfo, Pat) import Clash.Core.TyCon (TyConMap) import Clash.Core.Type (Type, TyVar)+import Clash.Core.Util (undefinedPrims) import Clash.Core.Var (Id) import Clash.Core.VarEnv (VarEnv, InScopeSet) import Clash.Driver.Types (Binding(..))@@ -73,10 +75,13 @@ | NePrim !PrimInfo !(Args a) | NeApp !(Neutral a) !a | NeTyApp !(Neutral a) !Type- | NeLetrec ![(Id, a)] !a+ | NeLet !(Bind a) !a | NeCase !a !Type ![(Pat, a)] deriving (Show) +-- TODO Write an instance (InferType a) => InferType (Neutral a)+-- TODO Write an instance (HasFreeVars a) => HasFreeVars (Neutral a)+ -- | A term which has been potentially evaluated to WHNF. If evaluation has -- occurred, then there will be no redexes at the head of the Value, but -- sub-terms may still have redexes. Data constructors are only considered to@@ -99,6 +104,9 @@ | VThunk !Term !LocalEnv deriving (Show) +-- TODO Write an instance InferType Value+-- TODO Write an instance HasFreeVars Value+ mkValueTicks :: Value -> [TickInfo] -> Value mkValueTicks = foldl VTick @@ -115,14 +123,7 @@ isUndefined :: Value -> Bool isUndefined = \case VNeutral (NePrim pr _) ->- primName pr `elem`- [ "Control.Exception.Base.absentError"- , "Control.Exception.Base.patError"- , "EmptyCase"- , "GHC.Err.undefined"- , "Clash.Transformations.undefined"- , "Clash.XException.errorX"- ]+ primName pr `elem` undefinedPrims _ -> False
src/Clash/Core/Pretty.hs view
@@ -1,8 +1,9 @@ {-| Copyright : (C) 2012-2016, University of Twente,- 2016 , Myrtle Software Ltd+ 2016 , Myrtle Software Ltd,+ 2021 , QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> PrettyPrec printing class and instances for CoreHW -}@@ -34,6 +35,7 @@ import Data.Default (Default(..)) import Data.Text (Text) import Control.Monad.Identity+import Data.Binary.IEEE754 (wordToDouble, wordToFloat) import Data.List.Extra ((<:>)) import qualified Data.Text as T import Data.Maybe (fromMaybe)@@ -45,7 +47,7 @@ import Data.Text.Prettyprint.Doc.Internal #endif import GHC.Show (showMultiLineString)-import Numeric (fromRat)+import GHC.Stack (HasCallStack) #if MIN_VERSION_ghc(9,0,0) import qualified GHC.Utils.Outputable as GHC #else@@ -59,10 +61,10 @@ import Clash.Core.Literal (Literal (..)) import Clash.Core.Name (Name (..)) import Clash.Core.Term- (Pat (..), Term (..), TickInfo (..), NameMod (..), CoreContext (..), primArg, PrimInfo(primName))-import Clash.Core.TyCon (TyCon (..), TyConName, isTupleTyConLike)+ (Pat (..), Term (..), TickInfo (..), NameMod (..), CoreContext (..), primArg, PrimInfo(primName),Bind(..))+import Clash.Core.TyCon (TyCon (..), TyConName, isTupleTyConLike, AlgTyConRhs(..)) import Clash.Core.Type (ConstTy (..), Kind, LitTy (..),- Type (..), TypeView (..), tyView)+ Type (..), TypeView (..), tyView,mkTyConApp) import Clash.Core.Var (Id, TyVar, Var (..), IdScope(..)) import Clash.Debug (trace) import Clash.Util@@ -219,11 +221,14 @@ expr' <- pprM expr return $ bndr' <> line <> hang 2 (sep [(bndrName <+> equals), expr']) <> line -dcolon, rarrow, lam, tylam, at, cast, coerce, letrec, in_, case_, of_, forall_+dcolon, rarrow, lam, tylam, at, cast, coerce, let_, letrec, in_, case_, of_, forall_,+ data_,newtype_,type_,family_,instance_ :: ClashDoc-[dcolon, rarrow, lam, tylam, at, cast, coerce, letrec, in_, case_, of_, forall_]+[dcolon, rarrow, lam, tylam, at, cast, coerce, let_, letrec, in_, case_, of_, forall_,+ data_,newtype_,type_,family_,instance_] = annotate (AnnSyntax Keyword) <$>- ["::", "->", "λ", "Λ", "@", "▷", "~", "letrec", "in", "case", "of", "forall"]+ ["::", "->", "λ", "Λ", "@", "▷", "~", "let", "letrec", "in", "case", "of", "forall",+ "data","newtype","type","family","instance"] instance PrettyPrec Text where pprPrec _ = pure . pretty@@ -235,8 +240,54 @@ clashPretty = fromPpr instance PrettyPrec TyCon where- pprPrec _ t = pprM (tyConName t)+ pprPrec prec t = case t of+ AlgTyCon _ nm kn _ (DataTyCon dcs) _ -> do+ name <- pprPrec prec nm+ kind <- pprKind kn+ let decl = name <> annotate (AnnSyntax Type) (space <> dcolon <+> kind) + cons <- traverse pprDataCon dcs+ pure (vsep (data_ <+> decl : cons))+ where+ pprDataCon dc = do+ name <- pprPrec prec dc+ ty <- pprType (dcType dc)++ pure (name <+> dcolon <+> ty)++ AlgTyCon _ nm kn _ (NewTyCon dc _) _ -> do+ name <- pprPrec prec nm+ kind <- pprKind kn+ let decl = name <> annotate (AnnSyntax Type) (space <> dcolon <+> kind)++ conName <- pprPrec prec (dcName dc)+ conType <- pprType (dcType dc)++ pure (vsep [newtype_ <+> decl, conName <+> dcolon <+> conType])++ PromotedDataCon _ _ _ _ dc ->+ fmap ("promoted" <+>) (pprPrec prec dc)++ FunTyCon _ nm kn _ ss -> do+ name <- pprPrec prec nm+ kind <- pprKind kn+ let decl = name <> annotate (AnnSyntax Type) (space <> dcolon <+> kind)++ substs <- traverse pprSubst ss+ pure (vsep (type_ <+> family_ <+> decl : substs))+ where+ pprSubst (xs, y) = do+ lhs <- pprType (mkTyConApp (tyConName t) xs)+ rhs <- pprType y++ pure (type_ <+> instance_ <+> lhs <+> "=" <+> rhs)++ PrimTyCon _ nm kn _ -> do+ name <- pprPrec prec nm+ kind <- pprKind kn++ pure (name <> annotate (AnnSyntax Type) (space <> dcolon <+> kind))+ instance Pretty LitTy where pretty (NumTy i) = pretty i pretty (SymTy s) = dquotes $ pretty s@@ -260,7 +311,8 @@ App fun arg -> pprPrecApp prec fun arg TyApp e' ty -> annotate (AnnContext TyAppC) <$> pprPrecTyApp prec e' ty- Letrec xes e1 -> pprPrecLetrec prec xes e1+ Let (NonRec i x) e1 -> pprPrecLetrec prec False [(i,x)] e1+ Let (Rec xes) e1 -> pprPrecLetrec prec True xes e1 Case e' _ alts -> pprPrecCase prec e' alts Cast e' ty1 ty2 -> pprPrecCast prec e' ty1 ty2 Tick t e' -> do@@ -311,8 +363,8 @@ | otherwise -> pretty i WordLiteral w -> pretty w Word64Literal w -> pretty w- FloatLiteral r -> pretty (fromRat r :: Float)- DoubleLiteral r -> pretty (fromRat r :: Double)+ FloatLiteral w -> pretty $ wordToFloat w+ DoubleLiteral w -> pretty $ wordToDouble w CharLiteral c -> pretty c StringLiteral s -> vcat $ map pretty $ showMultiLineString s NaturalLiteral n -> pretty n@@ -379,8 +431,14 @@ e' <> annotate (AnnSyntax Type) (softline <> nest 2 (vsep [cast, ty1', coerce, ty2'])) -pprPrecLetrec :: Monad m => Rational -> [(Id, Term)] -> Term -> m ClashDoc-pprPrecLetrec prec xes body = do+-- TODO Since Clash now keeps non-recursive let expressions separately, the+-- result of normalization will contain more nested let expressions as the old+-- Letrec-based definitions are replaced by Let. As this happens, it may be a+-- good idea to change pprPrecLetrec to encourage more compact forms such as+-- printing the entire binding on one line if possible.++pprPrecLetrec :: Monad m => Rational -> Bool -> [(Id, Term)] -> Term -> m ClashDoc+pprPrecLetrec prec isRec xes body = do let bndrs = fst <$> xes body' <- annotate (AnnContext $ LetBody bndrs) <$> pprPrec noPrec body xes' <- mapM (\(x,e) -> do@@ -390,8 +448,9 @@ vsepHard [x', equals <+> e'] ) xes let xes'' = case xes' of { [] -> ["EmptyLetrec"]; _ -> xes' }+ let kw = if isRec then letrec else let_ return $ parensIf (prec > noPrec) $- vsepHard [hang 2 (vsepHard $ letrec : xes''), in_ <+> body']+ vsepHard [hang 2 (vsepHard $ kw : xes''), in_ <+> body'] pprPrecCase :: Monad m => Rational -> Term -> [(Pat,Term)] -> m ClashDoc pprPrecCase prec e alts = do
src/Clash/Core/Subst.hs view
@@ -1,8 +1,9 @@ {-| Copyright : (C) 2012-2016, University of Twente, 2017, Google Inc.+ 2021, QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Capture-free substitution function for CoreHW -}@@ -73,15 +74,15 @@ import qualified Data.List as List import qualified Data.List.Extra as List import Data.Ord (comparing)+import GHC.Stack (HasCallStack) import GHC.SrcLoc.Extra () import GHC.TypeLits (TypeError, ErrorMessage (Text, (:<>:))) -import Clash.Core.FreeVars- (noFreeVarsOfType, localFVsOfTerms, tyFVsOfTypes)+import Clash.Core.HasFreeVars import Clash.Core.Pretty (ppr, fromPpr) import Clash.Core.Term- (LetBinding, Pat (..), Term (..), TickInfo (..), PrimInfo(primName))+ (Bind(..), Pat (..), Term (..), TickInfo (..), PrimInfo(primName)) import Clash.Core.Type (Type (..)) import Clash.Core.VarEnv import Clash.Core.Var (Id, Var (..), TyVar, isGlobalId)@@ -263,7 +264,7 @@ , not (List.equalLength tvs tys) = pprTrace "zipTvSubst" (ppr tvs <> line <> ppr tys) emptySubst | otherwise- = Subst (mkInScopeSet (tyFVsOfTypes tys)) emptyVarEnv tenv emptyVarEnv+ = Subst (mkInScopeSet (freeVarsOf tys)) emptyVarEnv tenv emptyVarEnv where tenv = zipTyEnv tvs tys @@ -447,7 +448,7 @@ WARN( not (isValidSubst subst), "inScope" <+> clashPretty inScope <> line <> "tenv" <+> clashPretty tenv <> line <>- "tenvFVs" <+> clashPretty (tyFVsOfTypes tenv) <> line <>+ "tenvFVs" <+> clashPretty (freeVarsOf tenv) <> line <> "tys" <+> fromPpr tys) WARN( not tysFVsInSope, "inScope" <+> clashPretty inScope <> line <>@@ -457,7 +458,7 @@ a where needsInScope = foldrWithUnique (\k _ s -> delVarSetByKey k s)- (tyFVsOfTypes tys)+ (freeVarsOf tys) tenv tysFVsInSope = needsInScope `varSetInScope` inScope @@ -471,7 +472,7 @@ -> Bool isValidSubst (TvSubst inScope tenv) = tenvFVs `varSetInScope` inScope where- tenvFVs = tyFVsOfTypes tenv+ tenvFVs = freeVarsOf tenv -- | The work-horse of 'substTy' substTy'@@ -516,11 +517,11 @@ | otherwise = extendVarEnv oldVar (VarTy newVar) tenv -- Assertion that we're not capturing something in the substitution- no_capture = not (newVar `elemVarSet` tyFVsOfTypes tenv)+ no_capture = not (newVar `elemVarSet` freeVarsOf tenv) oldKi = varType oldVar -- verify that the kind is closed- noKindChange = noFreeVarsOfType oldKi+ noKindChange = isClosed oldKi -- noChange means that the new type variable is identical in all respects to -- the old type variable (same unique, same kind) -- See 'TvSubstEnv's Note [Extending the TvSubstEnv]@@ -566,8 +567,8 @@ (subst',v') -> TyLam v' (substTm doc subst' e) App l r -> App (go l) (go r) TyApp l r -> TyApp (go l) (substTy subst r)- Letrec bs e -> case substBind doc subst bs of- (subst',bs') -> Letrec bs' (substTm doc subst' e)+ Let bs e -> case substBind doc subst bs of+ (subst',bs') -> Let bs' (substTm doc subst' e) Case subj ty alts -> Case (go subj) (substTy subst ty) (map goAlt alts) Cast e t1 t2 -> Cast (go e) (substTy subst t1) (substTy subst t2) Tick tick e -> Tick (goTick tick) (go e)@@ -646,7 +647,7 @@ | otherwise = id1 {varType = substTy subst (varType id1)} oldTy = varType oldId- noTypeChange = nullVarEnv tenv || noFreeVarsOfType oldTy+ noTypeChange = nullVarEnv tenv || isClosed oldTy -- Extend the substitution if the unique has changed. --@@ -679,11 +680,17 @@ :: HasCallStack => Doc () -> Subst- -> [LetBinding]- -> (Subst,[LetBinding])-substBind doc subst xs =- (subst',zip bndrs' rhss')+ -> Bind Term+ -> (Subst, Bind Term)+substBind doc subst (NonRec i x) =+ (subst', NonRec i' x') where+ (subst', i') = substIdBndr subst i+ x' = substTm ("substBind" <+> doc) subst x++substBind doc subst (Rec xs) =+ (subst', Rec (zip bndrs' rhss'))+ where (bndrs,rhss) = unzip xs (subst',bndrs') = List.mapAccumL substIdBndr subst bndrs rhss' = map (substTm ("substBind" <+> doc) subst') rhss@@ -726,11 +733,11 @@ :: HasCallStack => InScopeSet -- ^ Current InScopeSet- -> [LetBinding]+ -> Bind Term -- ^ Bindings of the let-expression -> Term -- ^ The body of the let-expression- -> ([LetBinding],Term)+ -> (Bind Term, Term) -- ^ Deshadowed let-bindings, where let-bound expressions and the let-body -- properly reference the renamed variables deshadowLetExpr is bs e =@@ -761,9 +768,9 @@ (is2,r') -> (is2, App l' r') TyApp l r -> case go subst0 l of (is1,l') -> (is1, TyApp l' (substTy subst0 r))- Letrec bs e -> case goBind subst0 bs of+ Let bs e -> case goBind subst0 bs of (subst1,bs') -> case go subst1 e of- (is2,e') -> (is2,Letrec bs' e')+ (is2,e') -> (is2,Let bs' e') Case subj ty alts -> case go subst0 subj of (is1,subj') -> case List.mapAccumL (\isN -> goAlt subst0 {substInScope = isN}) is1 alts of (is2,alts') -> (is2, Case subj' (substTy subst0 ty) alts')@@ -773,13 +780,18 @@ (is1, e') -> (is1, Tick (goTick subst0 tick) e') tm -> (substInScope subst0, tm) - goBind subst0 xs =+ goBind subst0 (NonRec i x) =+ let (subst1, i') = substIdBndr subst0 i+ (is2, x') = go subst0 x+ in (subst1 { substInScope = extendInScopeSet is2 i' }, NonRec i' x')++ goBind subst0 (Rec xs) = let (bndrs,rhss) = unzip xs (subst1,bndrs') = List.mapAccumL substIdBndr subst0 bndrs (is2,rhss') = List.mapAccumL (\isN -> go subst1 {substInScope = isN}) (substInScope subst1) rhss- in (subst1 {substInScope = is2},zip bndrs' rhss')+ in (subst1 {substInScope = is2}, Rec $ zip bndrs' rhss') goAlt subst0 (pat,alt) = case pat of DataPat dc tvs ids -> case List.mapAccumL substTyVarBndr' subst0 tvs of@@ -801,7 +813,7 @@ -> Bool aeqType t1 t2 = acmpType' rnEnv t1 t2 == EQ where- rnEnv = mkRnEnv (mkInScopeSet (tyFVsOfTypes [t1,t2]))+ rnEnv = mkRnEnv (mkInScopeSet (freeVarsOf [t1,t2])) -- | Alpha comparison for types acmpType@@ -810,7 +822,7 @@ -> Ordering acmpType t1 t2 = acmpType' (mkRnEnv inScope) t1 t2 where- inScope = mkInScopeSet (tyFVsOfTypes [t1,t2])+ inScope = mkInScopeSet (freeVarsOf [t1,t2]) -- | Alpha comparison for types. Faster than 'acmpType' as it doesn't need to -- calculate the free variables to create the 'InScopeSet'@@ -863,7 +875,7 @@ -> Bool aeqTerm t1 t2 = aeqTerm' inScope t1 t2 where- inScope = mkInScopeSet (localFVsOfTerms [t1,t2])+ inScope = mkInScopeSet (freeVarsOf [t1,t2]) -- | Alpha equality for terms. Faster than 'aeqTerm' as it doesn't need to -- calculate the free variables to create the 'InScopeSet'@@ -882,7 +894,7 @@ -> Ordering acmpTerm t1 t2 = acmpTerm' inScope t1 t2 where- inScope = mkInScopeSet (localFVsOfTerms [t1,t2])+ inScope = mkInScopeSet (freeVarsOf [t1,t2]) -- | Alpha comparison for types. Faster than 'acmpTerm' as it doesn't need to -- calculate the free variables to create the 'InScopeSet'@@ -911,7 +923,9 @@ go env l1 l2 `thenCompare` go env r1 r2 go env (TyApp l1 r1) (TyApp l2 r2) = go env l1 l2 `thenCompare` acmpType' env r1 r2- go env (Letrec bs1 e1) (Letrec bs2 e2) =+ go env (Let (NonRec i1 x1) e1) (Let (NonRec i2 x2) e2) =+ go env x1 x2 `thenCompare` go (rnTmBndr env i1 i2) e1 e2+ go env (Let (Rec bs1) e1) (Let (Rec bs2) e2) = compare (length bs1) (length bs2) `thenCompare` foldr thenCmpTm EQ (zipWith (go env') rhs1 rhs2) `thenCompare` go env' e1 e2@@ -949,9 +963,10 @@ TyApp {} -> 6 Lam {} -> 7 TyLam {} -> 8- Letrec {} -> 9- Case {} -> 10- Tick {} -> 11+ Let NonRec{} _ -> 9+ Let Rec{} _ -> 10+ Case {} -> 11+ Tick {} -> 12 thenCompare :: Ordering -> Ordering -> Ordering thenCompare EQ rel = rel@@ -971,21 +986,29 @@ b1 == b2 && eqType (varType b1) (varType b2) && go e1 e2 go (App l1 r1) (App l2 r2) = go l1 l2 && go r1 r2 go (TyApp l1 r1) (TyApp l2 r2) = go l1 l2 && eqType r1 r2- go (Letrec bs1 e1) (Letrec bs2 e2) =+ go (Let bs1 e1) (Let bs2 e2) = go e1 e2 &&- List.all2 goBind bs1 bs2+ goBind bs1 bs2 where- goBind (b1,r1) (b2,r2) =- b1 == b2 &&- -- We need to check the types of Rec bindings, because:- --- -- letrec (x : Bool) = x in X- --- -- is not structurally equivalent to- --- -- letrec (x : Int) = x in x- eqType (varType b1) (varType b2) &&- go r1 r2+ goBind (NonRec b1 r1) (NonRec b2 r2) =+ -- No need to check types of NonRec bindings, when the RHSs match the+ -- types must be the same.+ b1 == b2 && go r1 r2+ goBind (Rec brs1) (Rec brs2) =+ List.all2+ (\(b1,r1) (b2,r2) ->+ b1 == b2 &&+ -- We need to check the types of Rec bindings, because:+ --+ -- letrec (x : Bool) = x in X+ --+ -- is not structurally equivalent to+ --+ -- letrec (x : Int) = x in x+ eqType (varType b1) (varType b2) &&+ go r1 r2)+ brs1 brs2+ goBind _ _ = False go (Case e1 _ a1) (Case e2 _ a2) = go e1 e2 && List.all2 goAlt a1 a2@@ -1013,7 +1036,6 @@ ':<>: 'Text "an issue report at https://github.com/clash-lang/clash-compiler/issues." ) => Hashable Term where hashWithSalt = error "Term.hashWithSalt: unreachable"- instance Ord Term where
src/Clash/Core/Term.hs view
@@ -1,8 +1,9 @@ {-| Copyright : (C) 2012-2016, University of Twente, 2017, Google Inc.+ 2021, QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Term representation in the CoreHW language: System F + LetRec + Case -}@@ -12,11 +13,12 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE UndecidableInstances #-} module Clash.Core.Term- ( Term (..)+ ( Term (.., Letrec) , mkAbstraction , mkTyLams , mkLams@@ -25,8 +27,8 @@ , mkTmApps , mkTicks , TmName- , idToVar , varToId+ , Bind(..) , LetBinding , Pat (..) , patIds@@ -38,6 +40,7 @@ , partitionTicks , NameMod (..) , PrimInfo (..)+ , PrimUnfolding (..) , IsMultiPrim (..) , MultiPrimInfo (..) , WorkInfo (..)@@ -78,8 +81,8 @@ import Clash.Core.Name (Name (..)) import {-# SOURCE #-} Clash.Core.Subst () -- instance Eq Type import {-# SOURCE #-} Clash.Core.Type (Type)-import Clash.Core.Var (Var(Id), Id, TyVar)-import Clash.Util (curLoc, second)+import Clash.Core.Var (Var, Id, TyVar)+import Clash.Util (curLoc) -- | Term representation in the CoreHW language: System F + LetRec + Case data Term@@ -91,13 +94,23 @@ | TyLam !TyVar Term -- ^ Type-abstraction | App !Term !Term -- ^ Application | TyApp !Term !Type -- ^ Type-application- | Letrec [LetBinding] Term -- ^ Recursive let-binding+ | Let !(Bind Term) Term -- ^ Recursive let-binding | Case !Term !Type [Alt] -- ^ Case-expression: subject, type of -- alternatives, list of alternatives | Cast !Term !Type !Type -- ^ Cast a term from one type to another | Tick !TickInfo !Term -- ^ Annotated term deriving (Show, Generic, NFData, Binary) +-- TODO When it is possible, remove this pattern.+pattern Letrec :: [LetBinding] -> Term -> Term+pattern Letrec bs x <- Let (bindToList -> bs) x+ where+ Letrec bs x = Let (Rec bs) x++bindToList :: Bind a -> [(Id, a)]+bindToList (NonRec i x) = [(i, x)]+bindToList (Rec xs) = xs+ data TickInfo = SrcSpan !SrcSpan -- ^ Source tick, will get added by GHC by running clash with `-g`@@ -139,8 +152,14 @@ -- the variables it should assign its results to. -- -- See: 'Clash.Normalize.Transformations.setupMultiResultPrim'+ , primUnfolding :: !PrimUnfolding } deriving (Show, Generic, NFData, Binary) +data PrimUnfolding+ = NoUnfolding+ | Unfolding !Id+ deriving (Show, Generic, NFData, Eq, Hashable, Binary)+ data MultiPrimInfo = MultiPrimInfo { mpi_primInfo :: PrimInfo , mpi_resultDc :: DataCon@@ -157,6 +176,10 @@ | WorkAlways -- ^ Performs work regardless of whether the variables are constant or -- variable; these are things like clock or reset generators+ | WorkIdentity Int [Int]+ -- ^ A more restrictive version of 'WorkNever', where the value is the+ -- argument at the given position if all arguments for the given list of+ -- positions are also 'WorkIdentity' deriving (Eq,Show,Generic,NFData,Hashable,Binary) -- | Term reference@@ -164,6 +187,12 @@ -- | Binding in a LetRec construct type LetBinding = (Id, Term) +data Bind a+ = NonRec Id a+ | Rec [(Id, a)]+ deriving (Eq, Show, Generic, NFData, Hashable, Binary, Functor)+ -- Structural equivalence instead of alpha equivalance+ -- | Patterns in the LHS of a case-decomposition data Pat = DataPat !DataCon [TyVar] [Id]@@ -293,12 +322,15 @@ go (TyLam i x) = TyLam i (go x) go (App f x) = App (go f) (go x) go (TyApp f a) = TyApp (go f) a- go (Letrec bs x) = Letrec (map (second go) bs) (go x)+ go (Let bs x) = Let (goBinds bs) (go x) go (Case x ty alts) = Case (go x) ty (fmap go <$> alts) go (Cast x a b) = Cast (go x) a b go (Tick _ x) = go x go x = x + goBinds (NonRec i x) = NonRec i (go x)+ goBinds (Rec ixs) = Rec (fmap go <$> ixs)+ -- | Split a (Type)Application in the applied term and it arguments collectArgs :: Term -> (Term, [Either Term Type]) collectArgs = go []@@ -366,7 +398,8 @@ TyLam _ t1 -> go t1 App t1 t2 -> go t1 <> go t2 TyApp t1 _ -> go t1- Letrec bndrs t1 -> go t1 <> mconcat (map (go . snd) bndrs)+ Let (NonRec _ x) t1 -> go t1 <> go x+ Let (Rec bndrs) t1 -> go t1 <> mconcat (map (go . snd) bndrs) Case t1 _ alts -> go t1 <> mconcat (map (go . snd) alts) Cast t1 _ _ -> go t1 Tick _ t1 -> go t1@@ -378,7 +411,8 @@ go :: Term -> [Id] go (Var i) = [i] go (Lam i _) = [i]- go (Letrec bndrs _) = map fst bndrs+ go (Let (NonRec i _) _) = [i]+ go (Let (Rec bndrs) _) = fmap fst bndrs go (Case _ _ alts) = concatMap (pat . fst) alts go (Data _) = [] go (Literal _) = []@@ -394,12 +428,10 @@ pat (LitPat _) = [] pat DefaultPat = [] --- | Make variable reference out of term variable-idToVar :: Id -> Term-idToVar i@(Id {}) = Var i-idToVar tv = error $ $(curLoc) ++ "idToVar: tyVar: " ++ show tv---- | Make a term variable out of a variable reference+-- | Make a term variable out of a variable reference or ticked variable+-- reference varToId :: Term -> Id-varToId (Var i) = i-varToId e = error $ $(curLoc) ++ "varToId: not a var: " ++ show e+varToId = \case+ Var i -> i+ Tick _ e -> varToId e+ e -> error $ $(curLoc) ++ "varToId: not a var: " ++ show e
src/Clash/Core/TermInfo.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-}@@ -7,29 +6,16 @@ module Clash.Core.TermInfo where import Data.Maybe (fromMaybe)--#if MIN_VERSION_prettyprinter(1,7,0)-import Prettyprinter (line)-#else-import Data.Text.Prettyprint.Doc (line)-#endif- import Data.Text (isInfixOf)+import GHC.Stack (HasCallStack) -import Clash.Core.DataCon-import Clash.Core.FreeVars-import Clash.Core.Literal+import Clash.Core.HasType import Clash.Core.Name-import Clash.Core.Pretty-import Clash.Core.Subst import Clash.Core.Term import Clash.Core.TyCon (tyConDataCons, TyConMap) import Clash.Core.Type import Clash.Core.Var-import Clash.Core.VarEnv-import Clash.Debug (debugIsOn) import Clash.Unique (lookupUniqMap)-import Clash.Util import Clash.Util.Interpolate as I termSize :: Term -> Word@@ -43,61 +29,16 @@ termSize (TyApp e _) = termSize e termSize (Cast e _ _) = termSize e termSize (Tick _ e) = termSize e-termSize (Letrec bndrs e) = sum (bodySz:bndrSzs)+termSize (Let (NonRec _ x) e) = termSize x + termSize e+termSize (Let (Rec xs) e) = sum (bodySz:bndrSzs) where- bndrSzs = map (termSize . snd) bndrs+ bndrSzs = map (termSize . snd) xs bodySz = termSize e termSize (Case subj _ alts) = sum (subjSz:altSzs) where subjSz = termSize subj altSzs = map (termSize . snd) alts --- | Determine the type of a term-termType :: TyConMap -> Term -> Type-termType m e = case e of- Var t -> varType t- Data dc -> dcType dc- Literal l -> literalType l- Prim p -> goPrimType p- Lam v e' -> mkFunTy (varType v) (termType m e')- TyLam tv e' -> ForAllTy tv (termType m e')- App _ _ -> case collectArgs e of- (fun, args) -> applyTypeToArgs e m (termType m fun) args- TyApp _ _ -> case collectArgs e of- (fun, args) -> applyTypeToArgs e m (termType m fun) args- Letrec _ e' -> termType m e'- Case _ ty _ -> ty- Cast _ _ ty2 -> ty2- Tick _ e' -> termType m e'- where- goPrimType = \case- PrimInfo{primMultiResult=SingleResult, primType} -> primType- p@PrimInfo{primMultiResult=MultiResult} -> multiPrimType p---- | Type of multi prim primitive belonging to given primitive. See--- 'Clash.Normalize.Transformations.setupMultiResultPrim' for more information.------ Example, given:------ @--- /\v1 -> t1 -> t2 -> (t3, t4)--- @------ produces:------ @--- /\v1 -> t1 -> t2 -> t3 -> t4 -> (t3, t4)--- @----multiPrimType :: PrimInfo -> Type-multiPrimType primInfo =- if "GHC.Tuple.(," `isInfixOf` nameOcc tupTcNm- then mkPolyFunTy primResTy (primArgs <> map Right tupEls)- else error (multPrimErr primInfo)- where- (primArgs, primResTy) = splitFunForallTy (primType primInfo)- TyConApp tupTcNm tupEls = tyView primResTy- multPrimErr :: PrimInfo -> String multPrimErr primInfo = [I.i| Internal error in multiPrimInfo': could not produce MultiPrimInfo. This@@ -138,158 +79,18 @@ , mpi_resultTypes = tupEls } multiPrimInfo _ _ = Nothing --- | Get the result type of a polymorphic function given a list of arguments-applyTypeToArgs- :: Term- -> TyConMap- -> Type- -> [Either Term Type]- -> Type-applyTypeToArgs e m opTy args = go opTy args- where- go opTy' [] = opTy'- go opTy' (Right ty:args') = goTyArgs opTy' [ty] args'- go opTy' (Left _:args') = case splitFunTy m opTy' of- Just (_,resTy) -> go resTy args'- _ -> error $ unlines ["applyTypeToArgs:"- ,"Expression: " ++ showPpr e- ,"Type: " ++ showPpr opTy- ,"Args: " ++ unlines (map (either showPpr showPpr) args)- ]-- goTyArgs opTy' revTys (Right ty:args') = goTyArgs opTy' (ty:revTys) args'- goTyArgs opTy' revTys args' = go (piResultTys m opTy' (reverse revTys)) args'---- | Like 'piResultTyMaybe', but errors out when a type application is not--- valid.------ Do not iterate 'piResultTy', because it's inefficient to substitute one--- variable at a time; instead use 'piResultTys'-piResultTy- :: HasCallStack- => TyConMap- -> Type- -> Type- -> Type-piResultTy m ty arg = case piResultTyMaybe m ty arg of- Just res -> res- Nothing -> pprPanic "piResultTy" (ppr ty <> line <> ppr arg)---- | Like 'piResultTys' but for a single argument.------ Do not iterate 'piResultTyMaybe', because it's inefficient to substitute one--- variable at a time; instead use 'piResultTys'-piResultTyMaybe- :: HasCallStack- => TyConMap- -> Type- -> Type- -> Maybe Type-piResultTyMaybe m ty arg- | Just ty' <- coreView1 m ty- = piResultTyMaybe m ty' arg- | FunTy a res <- tyView ty- = if debugIsOn && not (aeqType a arg) then error [I.i|- Unexpected application. A function with type:-- #{showPpr ty}-- Got applied to an argument of type:-- #{showPpr arg}- |]- else- Just res- | ForAllTy tv res <- ty- = let emptySubst = mkSubst (mkInScopeSet (tyFVsOfTypes [arg,res]))- in Just (substTy (extendTvSubst emptySubst tv arg) res)- | otherwise- = Nothing---- | @(piResultTys f_ty [ty1, ..., tyn])@ gives the type of @(f ty1 .. tyn)@--- where @f :: f_ty@------ 'piResultTys' is interesting because:------ 1. 'f_ty' may have more foralls than there are args--- 2. Less obviously, it may have fewer foralls------ Fore case 2. think of:------ piResultTys (forall a . a) [forall b.b, Int]------ This really can happen, such as situations involving 'undefined's type:------ undefined :: forall a. a------ undefined (forall b. b -> b) Int------ This term should have the type @(Int -> Int)@, but notice that there are--- more type args than foralls in 'undefined's type.------ For efficiency reasons, when there are no foralls, we simply drop arrows from--- a function type/kind.-piResultTys- :: HasCallStack- => TyConMap- -> Type- -> [Type]- -> Type-piResultTys _ ty [] = ty-piResultTys m ty origArgs@(arg:args)- | Just ty' <- coreView1 m ty- = piResultTys m ty' origArgs- | FunTy a res <- tyView ty- = if debugIsOn && not (aeqType a arg) then error [I.i|- Unexpected application. A function with type:-- #{showPpr ty}-- Got applied to an argument of type:-- #{showPpr arg}- |]- else- piResultTys m res args- | ForAllTy tv res <- ty- = go (extendVarEnv tv arg emptyVarEnv) res args- | otherwise- = pprPanic "piResultTys1" (ppr ty <> line <> ppr origArgs)- where- inScope = mkInScopeSet (tyFVsOfTypes (ty:origArgs))-- go env ty' [] = substTy (mkTvSubst inScope env) ty'- go env ty' allArgs@(arg':args')- | Just ty'' <- coreView1 m ty'- = go env ty'' allArgs- | FunTy _ res <- tyView ty'- = go env res args'- | ForAllTy tv res <- ty'- = go (extendVarEnv tv arg' env) res args'- | VarTy tv <- ty'- , Just ty'' <- lookupVarEnv tv env- -- Deals with (piResultTys (forall a.a) [forall b.b, Int])- = piResultTys m ty'' allArgs- | otherwise- = pprPanic "piResultTys2" (ppr ty' <> line <> ppr origArgs <> line <> ppr allArgs)- -- | Does a term have a function type? isFun :: TyConMap -> Term -> Bool-isFun m t = isFunTy m (termType m t)+isFun m t = isFunTy m (inferCoreTypeOf m t) -- | Does a term have a function or polymorphic type? isPolyFun :: TyConMap -> Term -> Bool-isPolyFun m t = isPolyFunCoreTy m (termType m t)---- | Is a term a term-abstraction?-isLam :: Term -> Bool-isLam (Lam {}) = True-isLam _ = False+isPolyFun m t = isPolyFunCoreTy m (inferCoreTypeOf m t) -- | Is a term a recursive let-binding? isLet :: Term -> Bool-isLet (Letrec {}) = True-isLet _ = False+isLet Let{} = True+isLet _ = False -- | Is a term a variable reference? isVar :: Term -> Bool@@ -309,6 +110,11 @@ isPrim :: Term -> Bool isPrim (Prim {}) = True isPrim _ = False++-- | Is a term a tick?+isTick :: Term -> Bool+isTick Tick{} = True+isTick _ = False -- | Is a term a cast? isCast :: Term -> Bool
src/Clash/Core/TermLiteral.hs view
@@ -1,7 +1,8 @@ {-|-Copyright : (C) 2019, Myrtle Software Ltd+Copyright : (C) 2019, Myrtle Software Ltd,+ 2021, QBayLogic B.V. License : BSD2 (see the file LICENSE)-Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Tools to convert a 'Term' into its "real" representation -}@@ -15,7 +16,6 @@ ( TermLiteral , termToData , termToDataError- , uncheckedTermToData ) where import Data.Bifunctor (bimap)@@ -122,8 +122,3 @@ #{typ} |]---- | Same as 'termToData', but errors hard if it can't translate a given term--- to data.-uncheckedTermToData :: TermLiteral a => Term -> a-uncheckedTermToData = either error id . termToDataError
− src/Clash/Core/Termination.hs
@@ -1,95 +0,0 @@-{-# LANGUAGE LambdaCase #-}--module Clash.Core.Termination- ( RecInfo- , mkRecInfo- , isRecursive- , recursiveGroup- ) where--import Control.Lens.Fold-import Data.Graph (SCC(..))-import qualified Data.Graph as Graph-import qualified Data.List as List--import Clash.Core.FreeVars-import Clash.Core.Var-import Clash.Core.VarEnv-import Clash.Driver.Types---- Quick lookup for whether a binding is recursive or non-recursive. If a--- binding is non-recursive, we can assume that it terminates and skip--- analysing it.----data RecInfo = RecInfo- { recBindings :: [VarSet]- -- ^ Recursive bindings, organized into groups of strongly connected- -- components.- , nonRecBindings :: VarSet- -- ^ Non-recursive bindings- }--instance Show RecInfo where- show (RecInfo rs ns) =- "recursive groups:\n" <> show (fmap eltsVarSet rs)- <> "\n\nnon-recursive:\n" <> show (eltsVarSet ns)--instance Semigroup RecInfo where- {-# INLINE (<>) #-}- RecInfo rX nX <> RecInfo rY nY =- RecInfo (rX <> rY) (nX <> nY)--instance Monoid RecInfo where- {-# INLINE mempty #-}- mempty = RecInfo mempty mempty-- {-# INLINE mappend #-}- mappend = (<>)---- | Given a map of top-level bindings, identify which terms are recursive and--- organize them into groups of mutually recursive bindings. For example,--- calling mkRecInfo on a BindingMap with the definitions------ f [] = []--- f (x:xs) = g x : h xs------ g x = x + 1------ h [] = []--- h (x:xs) = x : f xs------ i [] = []--- i (x:xs) = x * 2 : i xs------ would identify [f, g] and [i] as recursive groups, and g as non-recursive.----mkRecInfo :: BindingMap -> RecInfo-mkRecInfo =- mconcat . fmap asInfo . dependencies- where- -- Convert a SCC to RecInfo- asInfo = \case- AcyclicSCC x -> RecInfo [] (unitVarSet $ bindingId x)- CyclicSCC xs -> RecInfo [mkVarSet $ fmap bindingId xs] emptyVarSet-- -- Get the SCCs of the dependency graph of free variables.- dependencies =- Graph.stronglyConnComp . eltsVarEnv . fmap go- where- go x = let fvs = bindingTerm x ^.. freeIds- in (x, bindingId x, fvs)---- | Check if a global binder is recursive. To be conservative, binders which--- are not included in the RecInfo are assumed to be recursive.----isRecursive :: Id -> RecInfo -> Bool-isRecursive i- | isGlobalId i = not . elemVarSet i . nonRecBindings- | otherwise = error ("isRecursive: " <> show i <> " is not a global Id")---- | Return the recursive group that a global binder belongs to. If the--- binder is non-recursive or not included in the RecInfo, Nothing is returned.----recursiveGroup :: Id -> RecInfo -> Maybe VarSet-recursiveGroup i = List.find (elemVarSet i) . recBindings-
src/Clash/Core/TyCon.hs view
@@ -1,7 +1,8 @@ {-| Copyright : (C) 2012-2016, University of Twente+ 2021, QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Type Constructors in CoreHW -}@@ -18,7 +19,9 @@ , AlgTyConRhs (..) , mkKindTyCon , isTupleTyConLike+ , isPrimTc , isNewTypeTc+ , isPromotedDc , tyConDataCons ) where@@ -26,6 +29,7 @@ -- External Import import Control.DeepSeq import Data.Binary (Binary)+import Data.Function (on) import qualified Data.Text as T import GHC.Generics @@ -35,7 +39,6 @@ import {-# SOURCE #-} Clash.Core.Type (Kind, Type) import Clash.Core.Var (TyVar) import Clash.Unique-import Clash.Util -- | Type Constructor data TyCon@@ -48,6 +51,13 @@ , algTcRhs :: !AlgTyConRhs -- ^ DataCon definitions , isClassTc :: !Bool -- ^ Is this a class dictionary? }+ | PromotedDataCon+ { tyConUniq :: {-# UNPACK #-} !Unique -- invariant (same as dcUniq)+ , tyConName :: !TyConName -- ^ Name of the TyCon+ , tyConKind :: !Kind -- ^ Kind of the TyCon+ , tyConArity :: !Int -- ^ Number of type arguments+ , tyConData :: !DataCon -- ^ DataCon which is promoted+ } -- | Function TyCons (e.g. type families) | FunTyCon { tyConUniq :: {-# UNPACK #-} !Unique@@ -63,18 +73,14 @@ , tyConKind :: !Kind -- ^ Kind of the TyCon , tyConArity :: !Int -- ^ Number of type arguments }- -- | To close the loop on the type hierarchy- | SuperKindTyCon- { tyConUniq :: {-# UNPACK #-} !Unique- , tyConName :: !TyConName -- ^ Name of the TyCon- }- deriving (Generic,NFData,Binary)+ deriving (Show,Generic,NFData,Binary) +{- instance Show TyCon where show (AlgTyCon {tyConName = n}) = "AlgTyCon: " ++ show n show (FunTyCon {tyConName = n}) = "FunTyCon: " ++ show n show (PrimTyCon {tyConName = n}) = "PrimTyCon: " ++ show n- show (SuperKindTyCon {tyConName = n}) = "SuperKindTyCon: " ++ show n+-} instance Eq TyCon where (==) = (==) `on` tyConUniq@@ -126,8 +132,20 @@ tyConDataCons (AlgTyCon {algTcRhs = NewTyCon { dataCon = con }}) = [con] tyConDataCons _ = [] +isPrimTc+ :: TyCon+ -> Bool+isPrimTc PrimTyCon{} = True+isPrimTc _ = False+ isNewTypeTc :: TyCon -> Bool isNewTypeTc (AlgTyCon {algTcRhs = NewTyCon {}}) = True isNewTypeTc _ = False++isPromotedDc+ :: TyCon+ -> Bool+isPromotedDc PromotedDataCon{} = True+isPromotedDc _ = False
src/Clash/Core/Type.hs view
@@ -2,8 +2,9 @@ Copyright : (C) 2012-2016, University of Twente, 2016 , Myrtle Software Ltd, 2017 , Google Inc.+ 2021 , QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Types in CoreHW -}@@ -31,7 +32,6 @@ , tyView , coreView , coreView1- , typeKind , mkTyConTy , mkFunTy , mkPolyFunTy@@ -50,7 +50,6 @@ , applyFunTy , findFunSubst , reduceTypeFamily- , undefinedTy , isIntegerTy , normalizeType , varAttrs@@ -104,7 +103,6 @@ import Clash.Core.Name import {-# SOURCE #-} Clash.Core.Subst import Clash.Core.TyCon-import Clash.Core.TysPrim import Clash.Core.Var import Clash.Unique import Clash.Util@@ -172,6 +170,16 @@ -- | Reference to a Kind type KiName = Name Kind +-- TODO+--+-- tyView could be smarter about what it gives back. Since it traverses the+-- arguments to make a `TyConApp`, if the leftmost innermost type isn't a+-- TyCon it could still return a list of applied types to save a later call to+-- something like splitFunForallTy.+--+-- It could / should also look through annotations instead of just returning+-- the original type wrapped in OtherType.+ -- | An easier view on types -- -- Note [Arrow arguments]@@ -259,6 +267,7 @@ AlgTyCon {algTcRhs = (NewTyCon _ nt)} -> newTyConInstRhs nt args _ -> reduceTypeFamily tcMap ty+ OtherType (AnnType _ ty') -> coreView1 tcMap ty' _ -> Nothing -- | Instantiate and Apply the RHS/Original of a NewType with the given@@ -292,38 +301,6 @@ splitTyConAppM (tyView -> TyConApp tc args) = Just (tc,args) splitTyConAppM _ = Nothing --- | Is a type a Superkind?-isSuperKind :: TyConMap -> Type -> Bool-isSuperKind tcMap (ConstTy (TyCon ((tcMap `lookupUniqMap'`) -> SuperKindTyCon {}))) = True-isSuperKind _ _ = False---- | Determine the kind of a type-typeKind :: TyConMap -> Type -> Kind-typeKind _ (VarTy k) = varType k-typeKind m (ForAllTy _ ty) = typeKind m ty-typeKind _ (LitTy (NumTy _)) = typeNatKind-typeKind _ (LitTy (SymTy _)) = typeSymbolKind-typeKind m (AnnType _ann typ) = typeKind m typ-typeKind m (tyView -> FunTy _arg res)- | isSuperKind m k = k- | otherwise = liftedTypeKind- where k = typeKind m res--typeKind m (tyView -> TyConApp tc args) =- foldl' kindFunResult (tyConKind (m `lookupUniqMap'` tc)) args--typeKind m (AppTy fun arg) = kindFunResult (typeKind m fun) arg-typeKind _ (ConstTy ct) = error $ $(curLoc) ++ "typeKind: naked ConstTy: " ++ show ct--kindFunResult :: Kind -> KindOrType -> Kind-kindFunResult (tyView -> FunTy _ res) _ = res--kindFunResult (ForAllTy kv ki) arg =- substTyWith [kv] [arg] ki--kindFunResult k tys =- error $ $(curLoc) ++ "kindFunResult: " ++ show (k,tys)- -- | Is a type polymorphic? isPolyTy :: Type -> Bool isPolyTy (ForAllTy _ _) = True@@ -664,13 +641,6 @@ symLitView _ (LitTy (SymTy s)) = Just s symLitView m (reduceTypeFamily m -> Just ty') = symLitView m ty' symLitView _ _ = Nothing---- | The type @forall a . a@-undefinedTy ::Type-undefinedTy =- let aNm = mkUnsafeSystemName "a" 0- aTv = (TyVar aNm 0 liftedTypeKind)- in ForAllTy aTv (VarTy aTv) isIntegerTy :: Type -> Bool isIntegerTy (ConstTy (TyCon nm)) = nameUniq nm == getKey integerTyConKey
src/Clash/Core/TysPrim.hs view
@@ -1,8 +1,9 @@ {-| Copyright : (C) 2012-2016, University of Twente,- 2016 , Myrtle Software Ltd+ 2016 , Myrtle Software Ltd,+ 2021 , QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Builtin Type and Kind definitions -}@@ -26,6 +27,7 @@ , doublePrimTy , naturalPrimTy , byteArrayPrimTy+ , eqPrimTy , tysPrimMap ) where@@ -42,25 +44,23 @@ import Clash.Core.Name import Clash.Core.TyCon-import {-# SOURCE #-} Clash.Core.Type+import Clash.Core.Type+import Clash.Core.Var (mkTyVar) import Clash.Unique -- | Builtin Name-tySuperKindTyConName, liftedTypeKindTyConName, typeNatKindTyConName, typeSymbolKindTyConName :: TyConName-tySuperKindTyConName = mkUnsafeSystemName "tYPE" (getKey tYPETyConKey)-liftedTypeKindTyConName = mkUnsafeSystemName "*" (getKey liftedTypeKindTyConKey)+liftedTypeKindTyConName, typeNatKindTyConName, typeSymbolKindTyConName :: TyConName+liftedTypeKindTyConName = mkUnsafeSystemName "Type" (getKey liftedTypeKindTyConKey) typeNatKindTyConName = mkUnsafeSystemName "Nat" (getKey typeNatKindConNameKey) typeSymbolKindTyConName = mkUnsafeSystemName "Symbol" (getKey typeSymbolKindConNameKey) -- | Builtin Kind-liftedTypeKindTc, tySuperKindTc, typeNatKindTc, typeSymbolKindTc :: TyCon-tySuperKindTc = SuperKindTyCon (nameUniq tySuperKindTyConName) tySuperKindTyConName-liftedTypeKindTc = mkKindTyCon liftedTypeKindTyConName tySuperKind-typeNatKindTc = mkKindTyCon typeNatKindTyConName tySuperKind-typeSymbolKindTc = mkKindTyCon typeSymbolKindTyConName tySuperKind+liftedTypeKindTc, typeNatKindTc, typeSymbolKindTc :: TyCon+liftedTypeKindTc = mkKindTyCon liftedTypeKindTyConName liftedTypeKind+typeNatKindTc = mkKindTyCon typeNatKindTyConName liftedTypeKind+typeSymbolKindTc = mkKindTyCon typeSymbolKindTyConName liftedTypeKind -liftedTypeKind, tySuperKind, typeNatKind, typeSymbolKind :: Type-tySuperKind = mkTyConTy tySuperKindTyConName+liftedTypeKind, typeNatKind, typeSymbolKind :: Type liftedTypeKind = mkTyConTy liftedTypeKindTyConName typeNatKind = mkTyConTy typeNatKindTyConName typeSymbolKind = mkTyConTy typeSymbolKindTyConName@@ -68,7 +68,7 @@ intPrimTyConName, integerPrimTyConName, charPrimTyConName, stringPrimTyConName, voidPrimTyConName, wordPrimTyConName, int64PrimTyConName, word64PrimTyConName, floatPrimTyConName, doublePrimTyConName,- naturalPrimTyConName, byteArrayPrimTyConName :: TyConName+ naturalPrimTyConName, byteArrayPrimTyConName, eqPrimTyConName :: TyConName intPrimTyConName = mkUnsafeSystemName "GHC.Prim.Int#" (getKey intPrimTyConKey) #if MIN_VERSION_base(4,15,0)@@ -102,6 +102,8 @@ byteArrayPrimTyConName = mkUnsafeSystemName "GHC.Prim.ByteArray#" (getKey byteArrayPrimTyConKey) +eqPrimTyConName = mkUnsafeSystemName "GHC.Prim.~#" (getKey eqPrimTyConKey)+ liftedPrimTC :: TyConName -> TyCon liftedPrimTC name = PrimTyCon (nameUniq name) name liftedTypeKind 0@@ -123,9 +125,22 @@ naturalPrimTc = liftedPrimTC naturalPrimTyConName byteArrayPrimTc = liftedPrimTC byteArrayPrimTyConName +eqPrimTc :: TyCon+eqPrimTc = PrimTyCon (nameUniq eqPrimTyConName) eqPrimTyConName ty 4+ where+ -- forall (a :: Type). forall (b :: Type). a -> b -> Type+ --+ -- The "real" type for this in GHC has a codomain of `TYPE ('TupleRep '[])`+ -- instead of the `TYPE 'LiftedRep` used here.+ ty = mkPolyFunTy liftedTypeKind+ [Left aTv, Left bTv, Right (VarTy aTv), Right (VarTy bTv)]++ aTv = mkTyVar liftedTypeKind (mkUnsafeSystemName "a" 0)+ bTv = mkTyVar liftedTypeKind (mkUnsafeSystemName "b" 1)+ intPrimTy, integerPrimTy, charPrimTy, stringPrimTy, voidPrimTy, wordPrimTy, int64PrimTy, word64PrimTy, floatPrimTy, doublePrimTy, naturalPrimTy,- byteArrayPrimTy :: Type+ byteArrayPrimTy, eqPrimTy :: Type intPrimTy = mkTyConTy intPrimTyConName integerPrimTy = mkTyConTy integerPrimTyConName charPrimTy = mkTyConTy charPrimTyConName@@ -138,11 +153,11 @@ doublePrimTy = mkTyConTy doublePrimTyConName naturalPrimTy = mkTyConTy naturalPrimTyConName byteArrayPrimTy = mkTyConTy byteArrayPrimTyConName+eqPrimTy = mkTyConTy eqPrimTyConName tysPrimMap :: TyConMap tysPrimMap = List.foldl' (\s (k,x) -> extendUniqMap k x s) emptyUniqMap- [ (tySuperKindTyConName , tySuperKindTc)- , (liftedTypeKindTyConName , liftedTypeKindTc)+ [ (liftedTypeKindTyConName , liftedTypeKindTc) , (typeNatKindTyConName , typeNatKindTc) , (typeSymbolKindTyConName , typeSymbolKindTc) , (intPrimTyConName , intPrimTc)@@ -157,4 +172,5 @@ , (doublePrimTyConName , doublePrimTc) , (naturalPrimTyConName , naturalPrimTc) , (byteArrayPrimTyConName , byteArrayPrimTc)+ , (eqPrimTyConName , eqPrimTc) ]
src/Clash/Core/Util.hs view
@@ -1,7 +1,8 @@ {-|- Copyright : (C) 2012-2016, University of Twente+ Copyright : (C) 2012-2016, University of Twente,+ 2021 , QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Smart constructor and destructor functions for CoreHW -}@@ -17,20 +18,18 @@ module Clash.Core.Util where import Control.Concurrent.Supply (Supply, freshId)-import qualified Control.Lens as Lens import Control.Monad.Trans.Except (Except, throwE, runExcept)+import Data.Bifunctor (first) import qualified Data.HashSet as HashSet import qualified Data.Graph as Graph-import Data.List (foldl', mapAccumR)+import Data.List (mapAccumR) import Data.List.Extra (zipEqual) import Data.Maybe (fromJust, isJust, mapMaybe, catMaybes) import qualified Data.Set as Set import qualified Data.Set.Lens as Lens import qualified Data.Text as T-#if !MIN_VERSION_base(4,11,0)-import Data.Semigroup-#endif+import GHC.Stack (HasCallStack) #if MIN_VERSION_ghc(9,0,0) import GHC.Builtin.Names (ipClassKey)@@ -42,22 +41,48 @@ import Clash.Core.DataCon import Clash.Core.EqSolver-import Clash.Core.FreeVars (tyFVsOfTypes, typeFreeVars, freeLocalIds)+import Clash.Core.FreeVars (freeLocalIds)+import Clash.Core.HasFreeVars+import Clash.Core.HasType import Clash.Core.Name (Name (..), OccName, mkUnsafeInternalName, mkUnsafeSystemName) import Clash.Core.Pretty (showPpr) import Clash.Core.Subst import Clash.Core.Term-import Clash.Core.TermInfo (termType) import Clash.Core.TyCon (TyConMap, tyConDataCons) import Clash.Core.Type-import Clash.Core.TysPrim (typeNatKind)+import Clash.Core.TysPrim (liftedTypeKind, typeNatKind) import Clash.Core.Var (Id, Var(..), mkLocalId, mkTyVar) import Clash.Core.VarEnv import Clash.Debug (traceIf) import Clash.Unique import Clash.Util +-- | Rebuild a let expression / let expressions by taking the SCCs of a list+-- of bindings and remaking Let (NonRec ...) ... and Let (Rec ...) ...+--+listToLets :: [LetBinding] -> Term -> Term+listToLets xs body = foldr go body (sccLetBindings xs)+ where+ go (Graph.AcyclicSCC (i, x)) acc = Let (NonRec i x) acc+ go (Graph.CyclicSCC binds) acc = Let (Rec binds) acc++-- | The type @forall a . a@+undefinedTy ::Type+undefinedTy =+ let aNm = mkUnsafeSystemName "a" 0+ aTv = (TyVar aNm 0 liftedTypeKind)+ in ForAllTy aTv (VarTy aTv)++-- | The type @forall a. forall b. a -> b@+unsafeCoerceTy :: Type+unsafeCoerceTy =+ let aNm = mkUnsafeSystemName "a" 0+ aTv = TyVar aNm 0 liftedTypeKind+ bNm = mkUnsafeSystemName "b" 1+ bTv = TyVar bNm 1 liftedTypeKind+ in ForAllTy aTv (ForAllTy bTv (mkFunTy (VarTy aTv) (VarTy bTv)))+ -- | Create a vector of supplied elements mkVec :: DataCon -- ^ The Nil constructor -> DataCon -- ^ The Cons (:>) constructor@@ -126,12 +151,12 @@ -- ^ Length of the vector -> Term -- ^ The vector- -> (Supply, [(Term,[LetBinding])])+ -> (Supply, [(Term,[(Id, Term)])]) extractElems supply inScope consCon resTy s maxN vec = first fst (go maxN (supply,inScope) vec) where go :: Integer -> (Supply,InScopeSet) -> Term- -> ((Supply,InScopeSet),[(Term,[LetBinding])])+ -> ((Supply,InScopeSet),[(Term,[(Id, Term)])]) go 0 uniqs _ = (uniqs,[]) go n uniqs0 e = (uniqs3,(elNVar,[(elNId, lhs),(restNId, rhs)]):restVs)@@ -178,7 +203,7 @@ -- ^ Depth of the tree -> Term -- ^ The tree- -> (Supply,([Term],[LetBinding]))+ -> (Supply,([Term],[(Id, Term)])) extractTElems supply inScope lrCon brCon resTy s maxN tree = first fst (go maxN [0..(2^(maxN+1))-2] [0..(2^maxN - 1)] (supply,inScope) tree) where@@ -187,7 +212,7 @@ -> [Int] -> (Supply,InScopeSet) -> Term- -> ((Supply,InScopeSet),([Term],[LetBinding]))+ -> ((Supply,InScopeSet),([Term],[(Id, Term)])) go 0 _ ks uniqs0 e = (uniqs1,([elNVar],[(elNId, rhs)])) where tys = [LitTy (NumTy 0),resTy]@@ -287,7 +312,7 @@ go tcSeen (tyView -> TyConApp tcNm args) = case nameOcc tcNm of "Clash.Signal.Internal.Signal" -> True "Clash.Signal.BiSignal.BiSignalIn" -> True- "Clash.Signal.Internal.BiSignalOut" -> True+ "Clash.Signal.BiSignal.BiSignalOut" -> True _ | tcNm `HashSet.member` tcSeen -> False -- Do not follow rec types | otherwise -> case lookupUniqMap tcNm tcm of Just tc -> let dcs = tyConDataCons tc@@ -378,7 +403,7 @@ -- TODO: Check if all existentials were solved (they should be, or the wouldn't have -- TODO: been solved in the caseElemExistentials transformation) let is1 = extendInScopeSetList is0 dcExtTyVars- is2 = unionInScope is1 (mkInScopeSet (tyFVsOfTypes inst_tys))+ is2 = unionInScope is1 (mkInScopeSet (freeVarsOf inst_tys)) subst = extendTvSubstList (mkSubst is2) (zipEqual dcUnivTyVars inst_tys) go (substGlobalsInExistentials is0 dcExtTyVars (zipEqual dcUnivTyVars inst_tys))@@ -426,16 +451,34 @@ primCo :: Type -> Term-primCo ty = Prim (PrimInfo "_CO_" ty WorkNever SingleResult)+primCo ty = Prim (PrimInfo "_CO_" ty WorkNever SingleResult NoUnfolding) --- | Make an undefined term-undefinedTm- :: Type- -> Term-undefinedTm =- let undefinedNm = "Clash.Transformations.undefined" in- TyApp (Prim (PrimInfo undefinedNm undefinedTy WorkNever SingleResult))+-- | Make an unsafe coercion+primUCo :: Term+primUCo =+ Prim PrimInfo { primName = "GHC.Prim.unsafeCoerce#"+ , primType = unsafeCoerceTy+ , primWorkInfo = WorkNever+ , primMultiResult = SingleResult+ , primUnfolding = NoUnfolding+ } +undefinedPrims :: [T.Text]+undefinedPrims =+ [ "Clash.Normalize.Primitives.undefined"+ , "Clash.XException.errorX"+ , "Control.Exception.Base.absentError"+ , "Control.Exception.Base.patError"+ , "EmptyCase"+ , "GHC.Err.error"+ , "GHC.Err.errorWithoutStackTrace"+ , "GHC.Err.undefined"+ , "GHC.Real.divZeroError"+ , "GHC.Real.overflowError"+ , "GHC.Real.ratioZeroDenominatorError"+ , "GHC.Real.underflowError"+ ]+ substArgTys :: DataCon -> [Type]@@ -443,8 +486,7 @@ substArgTys dc args = let univTVs = dcUnivTyVars dc extTVs = dcExtTyVars dc- argsFVs = foldl' unionVarSet emptyVarSet- (map (Lens.foldMapOf typeFreeVars unitVarSet) args)+ argsFVs = freeVarsOf args is = mkInScopeSet (argsFVs `unionVarSet` mkVarSet extTVs) -- See Note [The substitution invariant] subst = extendTvSubstList (mkSubst is) (univTVs `zipEqual` args)@@ -643,8 +685,8 @@ -- | Group let-bindings into cyclic groups and acyclic individual bindings sccLetBindings :: HasCallStack- => [LetBinding]- -> [Graph.SCC LetBinding]+ => [(Id, Term)]+ -> [Graph.SCC (Id, Term)] sccLetBindings = Graph.stronglyConnComp . (map (\(i,e) -> let fvs = fmap varUniq@@ -663,7 +705,7 @@ -> Int -- ^ n'th DataCon -> Int -- ^ n'th field -> m Term-mkSelectorCase caller inScope tcm scrut dcI fieldI = go (termType tcm scrut)+mkSelectorCase caller inScope tcm scrut dcI fieldI = go (inferCoreTypeOf tcm scrut) where go (coreView1 tcm -> Just ty') = go ty' go scrutTy@(tyView -> TyConApp tc args) =
src/Clash/Core/Var.hs view
@@ -1,8 +1,9 @@ {-| Copyright : (C) 2012-2016, University of Twente, 2017-2018, Google Inc.+ 2021, QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Variables in CoreHW -}@@ -22,8 +23,6 @@ , mkLocalId , mkGlobalId , mkTyVar- , setVarUnique- , setVarType , setIdScope , modifyVarName , isGlobalId@@ -146,18 +145,6 @@ -> TmName -> Id mkGlobalId tmType tmName = Id tmName (nameUniq tmName) tmType GlobalId--setVarUnique- :: Var a- -> Unique- -> Var a-setVarUnique v u = v { varUniq = u, varName = (varName v) {nameUniq = u} }--setVarType- :: Var a- -> Type- -> Var a-setVarType v t = v { varType = t } isGlobalId :: Var a
src/Clash/Core/VarEnv.hs view
@@ -1,9 +1,7 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TypeSynonymInstances #-} module Clash.Core.VarEnv ( -- * Environment with variables as keys@@ -48,10 +46,14 @@ -- ** Modification , delVarSetByKey , unionVarSet+ , differenceVarSet -- ** Working with predicates+ , nullVarSet -- *** Searching , elemVarSet , notElemVarSet+ , subsetVarSet+ , disjointVarSet -- ** Conversions -- *** Lists , mkVarSet@@ -108,7 +110,8 @@ #endif import GHC.Exts (Any)-import GHC.Generics+import GHC.Generics (Generic)+import GHC.Stack (HasCallStack) import Clash.Core.Pretty () import Clash.Core.Var@@ -301,6 +304,13 @@ -> VarSet unionVarSet = unionUniqSet +-- | Take the difference of two sets+differenceVarSet+ :: VarSet+ -> VarSet+ -> VarSet+differenceVarSet = differenceUniqSet+ -- | Is the variable an element in the set elemVarSet :: Var a@@ -323,6 +333,19 @@ -- ^ Set of variables B -> Bool subsetVarSet = subsetUniqSet++-- | Are the sets of variables disjoint+disjointVarSet+ :: VarSet+ -> VarSet+ -> Bool+disjointVarSet = disjointUniqSet++-- | Check whether a varset is empty+nullVarSet+ :: VarSet+ -> Bool+nullVarSet = nullUniqSet -- | Look up a variable in the set, returns it if it exists lookupVarSet
src/Clash/Debug.hs view
@@ -3,8 +3,6 @@ module Clash.Debug ( debugIsOn , traceIf- , traceWith- , traceShowWith , module Debug.Trace ) where @@ -22,9 +20,3 @@ traceIf True msg = trace msg traceIf False _ = id {-# INLINE traceIf #-}--traceWith :: (a -> String) -> a -> a-traceWith f a = trace (f a) a--traceShowWith :: Show b => (a -> b) -> a -> a-traceShowWith f a = trace (show (f a)) a
src/Clash/Driver.hs view
@@ -2,7 +2,8 @@ Copyright : (C) 2012-2016, University of Twente, 2016-2017, Myrtle Software Ltd, 2017 , QBayLogic, Google Inc.- 2020 QBayLogic+ 2020-2022, QBayLogic,+ 2022 , Google Inc. License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com>@@ -20,6 +21,8 @@ module Clash.Driver where +import Control.Concurrent (MVar, modifyMVar, modifyMVar_, newMVar, withMVar)+import Control.Concurrent.Async (mapConcurrently_) import qualified Control.Concurrent.Supply as Supply import Control.DeepSeq import Control.Exception (throw)@@ -32,32 +35,37 @@ import Control.Monad.State.Strict (State) import qualified Control.Monad.State.Strict as State import qualified Crypto.Hash.SHA256 as Sha256+import Data.Bifunctor (first) import Data.ByteString (ByteString) import qualified Data.ByteString as ByteString import qualified Data.ByteString.Lazy as ByteStringLazy import qualified Data.ByteString.Lazy.Char8 as ByteStringLazyChar8 import Data.Char (isAscii, isAlphaNum)-import Data.Coerce (coerce) import Data.Default import Data.Hashable (hash) import Data.HashMap.Strict (HashMap) import qualified Data.HashMap.Strict as HashMap import qualified Data.HashSet as HashSet import Data.Proxy (Proxy(..))-import Data.IntMap (IntMap) import Data.List (intercalate) import Data.Maybe (fromMaybe, maybeToList, mapMaybe) import qualified Data.Map.Ordered as OMap import Data.Map.Ordered.Extra ()-import Data.Semigroup.Monad+import Data.Monoid (Ap(..)) import qualified Data.Text import Data.Text.Lazy (Text) import qualified Data.Text.Lazy as Text import Data.Text.Lazy.Encoding as Text import qualified Data.Text.Lazy.IO as Text+#if MIN_VERSION_prettyprinter(1,7,0)+import Prettyprinter (pretty)+#else+import Data.Text.Prettyprint.Doc (pretty)+#endif import Data.Text.Prettyprint.Doc.Extra (Doc, LayoutOptions (..), PageWidth (..) , layoutPretty, renderLazy) import qualified Data.Time.Clock as Clock+import GHC.Stack (HasCallStack) import qualified Language.Haskell.Interpreter as Hint import qualified Language.Haskell.Interpreter.Extension as Hint import qualified Language.Haskell.Interpreter.Unsafe as Hint@@ -95,26 +103,24 @@ (TopEntity (..), PortName(PortName, PortProduct)) import Clash.Annotations.TopEntity.Extra () import Clash.Backend--#if EXPERIMENTAL_EVALUATOR-import Clash.Core.PartialEval (Evaluator)-#else-import Clash.Core.Evaluator.Types (Evaluator)-#endif-+import Clash.Core.PartialEval as PE (Evaluator)+import Clash.Core.Evaluator.Types as WHNF (Evaluator)+import Clash.Core.HasType import Clash.Core.Name (Name (..)) import Clash.Core.Pretty (PrettyOptions(..), showPpr') import Clash.Core.Type (Type(ForAllTy, LitTy, AnnType), TypeView(..), tyView, mkFunTy, LitTy(SymTy))-import Clash.Core.TyCon (TyConMap, TyConName)+import Clash.Core.TyCon (TyConMap) import Clash.Core.Util (shouldSplit) import Clash.Core.Var (Id, varName, varUniq, varType) import Clash.Core.VarEnv- (elemVarEnv, emptyVarEnv, lookupVarEnv, lookupVarEnv', mkVarEnv, lookupVarEnvDirectly)+ (elemVarEnv, emptyVarEnv, lookupVarEnv, lookupVarEnv', mkVarEnv, lookupVarEnvDirectly, eltsVarEnv, VarEnv) import Clash.Debug (debugIsOn) import Clash.Driver.Types-import Clash.Driver.Manifest (Manifest(..), readFreshManifest, UnexpectedModification, pprintUnexpectedModifications, mkManifest, writeManifest, manifestFilename)+import Clash.Driver.Manifest+ (Manifest(..), readFreshManifest, UnexpectedModification, pprintUnexpectedModifications,+ mkManifest, writeManifest, manifestFilename) import Clash.Edalize.Edam import Clash.Netlist (genNetlist, genTopNames) import Clash.Netlist.BlackBox.Parser (runParse)@@ -126,6 +132,7 @@ import Clash.Normalize (checkNonRecursive, cleanupGraph, normalize, runNormalization) import Clash.Normalize.Util (callGraph, tvSubstWithTyEq)+import qualified Clash.Primitives.Sized.Signed as P import qualified Clash.Primitives.Sized.ToInteger as P import qualified Clash.Primitives.Sized.Vector as P import qualified Clash.Primitives.GHC.Int as P@@ -137,7 +144,7 @@ import Clash.Unique (Unique, getUnique) import Clash.Util.Interpolate (i) import Clash.Util- (ClashException(..), HasCallStack, first, reportTimeDiff,+ (ClashException(..), reportTimeDiff, wantedLanguageExtensions, unwantedLanguageExtensions, curLoc) import Clash.Util.Graph (reverseTopSort) import qualified Clash.Util.Interpolate as I@@ -227,8 +234,8 @@ -> TopEntityT splitTopEntityT tcm bindingsMap tt@(TopEntityT id_ (Just t@(Synthesize {})) _) = case lookupVarEnv id_ bindingsMap of- Just (Binding _id sp _ _ _) ->- tt{topAnnotation=Just (splitTopAnn tcm sp (varType id_) t)}+ Just (Binding _id sp _ _ _ _) ->+ tt{topAnnotation=Just (splitTopAnn tcm sp (coreTypeOf id_) t)} Nothing -> error "Internal error in 'splitTopEntityT'. Please report as a bug." splitTopEntityT _ _ t = t@@ -236,7 +243,7 @@ -- | Remove constraints such as 'a ~ 3'. removeForAll :: TopEntityT -> TopEntityT removeForAll (TopEntityT var annM isTb) =- TopEntityT var{varType=tvSubstWithTyEq (varType var)} annM isTb+ TopEntityT var{varType=tvSubstWithTyEq (coreTypeOf var)} annM isTb -- | Given a list of all found top entities and _maybe_ a top entity (+dependencies) -- passed in by '-main-is', return the list of top entities Clash needs to@@ -259,136 +266,169 @@ | c == a = b | otherwise = c +removeHistoryFile :: Maybe FilePath -> IO ()+removeHistoryFile =+ maybe (pure ()) removeHistory+ where+ removeHistory path =+ whenM (Directory.doesFileExist path) (Directory.removeFile path)++prefixModuleName+ :: HDL+ -> Maybe Data.Text.Text+ -> Maybe TopEntity+ -> String+ -> (String, Maybe String)+prefixModuleName hdl compPrefix annM modName =+ case compPrefix of+ Just (Data.Text.unpack -> p)+ | not (null p) -> case annM of+ Just ann ->+ let nm = p <> "_" <> t_name ann+ in (nm, Just nm)++ Nothing ->+ (p <> "_" <> modName, Just p)++ | Just ann <- annM -> case hdl of+ VHDL -> (t_name ann, Just modName)+ _ -> (t_name ann, Nothing)++ _ -> case annM of+ Just ann -> case hdl of+ VHDL -> (t_name ann, Just modName)+ _ -> (t_name ann, Just modName)+ _ -> (modName, Nothing)+ -- | Create a set of target HDL files for a set of functions generateHDL :: forall backend . Backend backend- => CustomReprs- -> HashMap Data.Text.Text VDomainConfiguration- -- ^ Known domains to configurations- -> BindingMap- -- ^ Set of functions+ => ClashEnv+ -> ClashDesign -> Maybe backend- -> CompiledPrimMap- -- ^ Primitive / BlackBox Definitions- -> TyConMap- -- ^ TyCon cache- -> IntMap TyConName- -- ^ Tuple TyCon cache -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -- ^ Hardcoded 'Type' -> 'HWType' translator- -> Evaluator+ -> PE.Evaluator -- ^ Hardcoded evaluator for partial evaluation- -> [TopEntityT]- -- ^ All topentities+ -> WHNF.Evaluator+ -- ^ Hardcoded evaluator for WHNF (old evaluator) -> Maybe (TopEntityT, [TopEntityT]) -- ^ Main top entity to compile. If Nothing, all top entities in previous -- argument will be compiled.- -> ClashOpts- -- ^ Debug information level for the normalization process- -> (Clock.UTCTime,Clock.UTCTime)+ -> Clock.UTCTime -> IO ()-generateHDL reprs domainConfs bindingsMap hdlState primMap tcm tupTcm typeTrans eval- topEntities0 mainTopEntity opts (startTime,prepTime) = do- case opt_dbgRewriteHistoryFile opts of- Nothing -> pure ()- Just histFile -> whenM (Directory.doesFileExist histFile) (Directory.removeFile histFile)- let (tes, deps) = sortTop bindingsMap topEntities1- in go prepTime initIs HashMap.empty deps tes- where- (compNames, initIs) = genTopNames topPrefixM escpIds lwIds hdl topEntities1- topEntityMap = mkVarEnv (fmap (\x -> (topId x, x)) topEntities1)- topPrefixM = opt_componentPrefix opts- hdl = hdlFromBackend (Proxy @backend)- escpIds = opt_escapedIds opts- lwIds = opt_lowerCaseBasicIds opts- topEntities1 =- map- (removeForAll . splitTopEntityT tcm bindingsMap)- (selectTopEntities topEntities0 mainTopEntity)+generateHDL env design hdlState typeTrans peEval eval mainTopEntity startTime = do+ let bindingsMap = designBindings design+ let tcm = envTyConMap env+ let topEntities0 = designEntities design+ let opts = envOpts env + removeHistoryFile (dbg_historyFile (opt_debug opts))++ unless (opt_cachehdl opts) $+ putStrLn "Clash: Ignoring previously made caches"++ let topEntities1 = fmap (removeForAll . splitTopEntityT tcm bindingsMap)+ (selectTopEntities topEntities0 mainTopEntity)+ hdl = hdlFromBackend (Proxy @backend)+ (compNames, initIs) = genTopNames opts hdl topEntities1+ (tes, deps) = sortTop bindingsMap topEntities1++ -- TODO This is here because of some minimal effort refactoring. At some+ -- point generateHDL should be better laid out so this can be closer to+ -- the few places it is needed.+ let topEntityMap = mkVarEnv (fmap (\x -> (topId x, x)) topEntities1)++ -- Data which is updated and used when updating the different top entities+ -- is kept in an MVar.+ idSet <- newMVar initIs+ edamFiles <- newMVar HashMap.empty+ ioLock <- newMVar ()++ mapConcurrently_ (go compNames idSet edamFiles ioLock deps topEntityMap) tes++ time <- Clock.getCurrentTime+ let diff = reportTimeDiff time startTime+ putStrLn $ "Clash: Total compilation took " ++ diff+ where go- :: Clock.UTCTime- -> Id.IdentifierSet- -> HashMap Unique [EdamFile]+ :: VarEnv Id.Identifier+ -> MVar Id.IdentifierSet+ -> MVar (HashMap Unique [EdamFile])+ -> MVar () -> HashMap Unique [Unique]- -> [TopEntityT]+ -> VarEnv TopEntityT+ -> TopEntityT -> IO ()- go prevTime _ _ _ [] =- putStrLn $ "Clash: Total compilation took " ++ reportTimeDiff prevTime startTime-- -- Process the next TopEntity- go prevTime seen0 edamFiles0 deps (TopEntityT topEntity annM isTb:topEntities') = do+ go compNames seenV edamFilesV ioLockV deps topEntityMap (TopEntityT topEntity annM isTb) = do+ let domainConfs = designDomains design+ let bindingsMap = designBindings design+ let primMap = envPrimitives env+ let topEntities0 = designEntities design+ let opts = envOpts env+ prevTime <- Clock.getCurrentTime let topEntityS = Data.Text.unpack (nameOcc (varName topEntity))- putStrLn $ "Clash: Compiling " ++ topEntityS - -- Some initial setup- let -- TODO: 'modName1' should be run through 'seen0'- modName1 = filter (\c -> isAscii c && (isAlphaNum c || c == '_')) (replaceChar '.' '_' topEntityS)- topNm = lookupVarEnv' compNames topEntity- (modNameS, fmap Data.Text.pack -> prefixM) = case topPrefixM of- Just (Data.Text.unpack -> p)- | not (null p) -> case annM of- -- Prefix top names with 'p', prefix other with 'p_tname'- Just ann ->- let nm = p <> "_" <> t_name ann in- (nm, Just nm)- -- Prefix top names with 'p', prefix other with 'p'- _ -> (p <> "_" <> modName1, Just p)- | Just ann <- annM -> case hdl of- -- Prefix other with 't_name'- VHDL -> (t_name ann, Just modNameS)- _ -> (t_name ann, Nothing)- _ -> case annM of- Just ann -> case hdlKind (undefined :: backend) of- VHDL -> (t_name ann, Nothing)- -- Prefix other with 't_name'- _ -> (t_name ann, Just modNameS)- _ -> (modName1, Nothing)+ withMVar ioLockV . const $+ putStrLn ("Clash: Compiling " ++ topEntityS)++ let modName1 = filter (\c -> isAscii c && (isAlphaNum c || c == '_')) (replaceChar '.' '_' topEntityS)++ modifyMVar_ seenV $ \seen ->+ pure $! State.execState (Id.addRaw (Data.Text.pack modName1)) seen++ let topNm = lookupVarEnv' compNames topEntity+ (modNameS, fmap Data.Text.pack -> prefixM) = prefixModuleName (hdlKind (undefined :: backend)) (opt_componentPrefix opts) annM modName1 modNameT = Data.Text.pack modNameS- iw = opt_intWidth opts- hdlsyn = opt_hdlSyn opts- forceUnd = opt_forceUndefined opts- xOpt = coerce (opt_aggressiveXOptBB opts)- hdlState' = setModName modNameT- $ fromMaybe (initBackend iw hdlsyn escpIds lwIds forceUnd xOpt :: backend) hdlState+ hdlState' = setDomainConfigurations domainConfs+ $ setModName modNameT+ $ fromMaybe (initBackend @backend opts) hdlState hdlDir = fromMaybe (Clash.Backend.name hdlState') (opt_hdlDir opts) </> topEntityS manPath = hdlDir </> manifestFilename ite = ifThenElseExpr hdlState' topNmT = Id.toText topNm - unless (opt_cachehdl opts) $ putStrLn "Clash: Ignoring previously made caches"- -- Get manifest file if cache is not stale and caching is enabled. This is used -- to prevent unnecessary recompilation. clashModDate <- getClashModificationDate (userModifications, maybeManifest, topHash) <- readFreshManifest topEntities0 (bindingsMap, topEntity) primMap opts clashModDate manPath - supplyN <- Supply.newSupply- let topEntityNames = map topId topEntities1+ let topEntityNames = map topId (eltsVarEnv topEntityMap) - (topTime, seen2, edamFiles2) <- case maybeManifest of+ case maybeManifest of Just manifest0@Manifest{fileNames} | Just [] <- userModifications -> do -- Found a 'manifest' files. Use it to extend "seen" set. Generate EDAM -- files if necessary.- putStrLn ("Clash: Using cached result for: " ++ topEntityS)- topTime <- Clock.getCurrentTime- let seen1 = State.execState (mapM_ Id.addRaw (componentNames manifest0)) seen0+ withMVar ioLockV . const $+ putStrLn ("Clash: Using cached result for: " ++ topEntityS) - (edamFiles1, fileNames1) <-+ modifyMVar_ seenV $ \seen ->+ pure $! State.execState (mapM_ Id.addRaw (componentNames manifest0)) seen++ fileNames1 <- modifyMVar edamFilesV $ \edamFiles -> if opt_edalize opts- then writeEdam hdlDir (topNm, varUniq topEntity) deps edamFiles0 fileNames- else pure (edamFiles0, fileNames)+ then writeEdam hdlDir (topNm, varUniq topEntity) deps edamFiles fileNames+ else pure (edamFiles, fileNames) - writeManifest manPath manifest0{fileNames=fileNames1}+ -- If we are generating (System)Verilog, we could potentially verilate+ -- the results. Clash can output a C++ shim for doing this automatically.+ fileNames2 <-+ case hdlFromBackend (Proxy @backend) of+ VHDL -> pure fileNames1+ _ -> writeVerilatorShim hdlDir topNm fileNames1 - return- ( topTime- , seen1- , edamFiles1- )+ writeManifest manPath manifest0{fileNames=fileNames2} + topTime <- Clock.getCurrentTime+ let topDiff = reportTimeDiff topTime prevTime++ withMVar ioLockV . const $+ putStrLn ("Clash: Compiling " ++ topEntityS ++ " took " ++ topDiff)++ return ()+ _ -> do -- 1. Prepare HDL directory --@@ -397,30 +437,37 @@ -- Already create the directory where the HDL ends up being generated, as -- we use directories relative to this final directory to find manifest -- files belonging to other top entities. Failing to do so leads to #463- () <- prepareDir hdlDir opts userModifications+ prepareDir hdlDir opts userModifications -- 2. Normalize topEntity- let transformedBindings = normalizeEntity reprs bindingsMap primMap tcm tupTcm- typeTrans eval topEntityNames opts supplyN- topEntity+ supplyN <- Supply.newSupply+ transformedBindings <- normalizeEntity env bindingsMap typeTrans peEval+ eval topEntityNames supplyN topEntity normTime <- transformedBindings `deepseq` Clock.getCurrentTime let prepNormDiff = reportTimeDiff normTime prevTime- putStrLn $ "Clash: Normalization took " ++ prepNormDiff + withMVar ioLockV . const $+ putStrLn ("Clash: Normalization took " ++ prepNormDiff)+ -- 3. Generate netlist for topEntity- (topComponent, netlist, seen2) <-- genNetlist isTb opts reprs transformedBindings topEntityMap compNames primMap- tcm typeTrans iw ite (SomeBackend hdlState') seen0 hdlDir prefixM topEntity+ (topComponent, netlist) <- modifyMVar seenV $ \seen -> do+ (topComponent, netlist, seen') <-+ -- TODO My word, this has far too many arguments.+ genNetlist env isTb transformedBindings topEntityMap compNames+ typeTrans ite (SomeBackend hdlState') seen hdlDir prefixM topEntity + pure (seen', (topComponent, netlist))+ netlistTime <- netlist `deepseq` Clock.getCurrentTime let normNetDiff = reportTimeDiff netlistTime normTime- putStrLn $ "Clash: Netlist generation took " ++ normNetDiff + withMVar ioLockV . const $+ putStrLn ("Clash: Netlist generation took " ++ normNetDiff)+ -- 4. Generate topEntity wrapper- let- (hdlDocs, dfiles, mfiles) =- createHDL hdlState' modNameT seen2 netlist domainConfs topComponent topNmT+ (hdlDocs, dfiles, mfiles) <- withMVar seenV $ \seen ->+ pure $! createHDL hdlState' modNameT seen netlist domainConfs topComponent topNmT -- TODO: Data files should go into their own directory -- FIXME: Files can silently overwrite each other@@ -435,11 +482,16 @@ <> zip (map fst dfiles) dataFilesDigests <> zip (map fst mfiles) memoryFilesDigests - (edamFiles1, filesAndDigests1) <-+ filesAndDigests1 <- modifyMVar edamFilesV $ \edamFiles -> if opt_edalize opts- then writeEdam hdlDir (topNm, varUniq topEntity) deps edamFiles0 filesAndDigests0- else pure (edamFiles0, filesAndDigests0)+ then writeEdam hdlDir (topNm, varUniq topEntity) deps edamFiles filesAndDigests0+ else pure (edamFiles, filesAndDigests0) + filesAndDigests2 <-+ case hdlFromBackend (Proxy @backend) of+ VHDL -> pure filesAndDigests1+ _ -> writeVerilatorShim hdlDir topNm filesAndDigests1+ let depUniques = fromMaybe [] (HashMap.lookup (getUnique topEntity) deps) depBindings = mapMaybe (flip lookupVarEnvDirectly bindingsMap) depUniques@@ -448,13 +500,14 @@ manifest = mkManifest hdlState' domainConfs opts topComponent components depIds- filesAndDigests1 topHash+ filesAndDigests2 topHash writeManifest manPath manifest topTime <- hdlDocs `seq` Clock.getCurrentTime- return (topTime, seen2, edamFiles1)+ let topDiff = reportTimeDiff topTime prevTime - go topTime seen2 edamFiles2 deps topEntities'+ withMVar ioLockV . const $+ putStrLn ("Clash: Compiling " ++ topEntityS ++ " took " ++ topDiff) -- | Interpret a specific function from a specific module. This action tries -- two things:@@ -542,6 +595,7 @@ , ('P.alteraPllQsysTF, P.alteraPllQsysTF) , ('P.alteraPllTF, P.alteraPllTF) , ('P.altpllTF, P.altpllTF)+ , ('P.fromIntegerTF, P.fromIntegerTF) ] -- | Compiles blackbox functions and parses blackbox templates.@@ -707,17 +761,17 @@ -> ([(String,Doc)],[(String,FilePath)],[(String,String)]) -- ^ The pretty-printed HDL documents -- + The data files that need to be copied-createHDL backend modName seen components domainConfs top topName = flip evalState backend $ getMon $ do+createHDL backend modName seen components domainConfs top topName = flip evalState backend $ getAp $ do let componentsL = map snd (OMap.assocs components) (hdlNmDocs,incs) <- fmap unzip $ forM componentsL $ \(ComponentMeta{cmLoc, cmScope}, comp) -> genHDL modName cmLoc (Id.union seen cmScope) comp - hwtys <- HashSet.toList <$> extractTypes <$> Mon get+ hwtys <- HashSet.toList <$> extractTypes <$> Ap get typesPkg <- mkTyPackage modName hwtys- dataFiles <- Mon getDataFiles- memFiles <- Mon getMemoryDataFiles+ dataFiles <- Ap getDataFiles+ memFiles <- Ap getMemoryDataFiles let hdl = map (first (<.> Clash.Backend.extension backend)) (typesPkg ++ hdlNmDocs) qincs = concat incs@@ -737,6 +791,48 @@ dom domainConfs +writeVerilatorShim+ :: FilePath+ -> Id.Identifier+ -> [(FilePath, ByteString)]+ -> IO [(FilePath, ByteString)]+writeVerilatorShim hdlDir topNm filesAndDigests = do+ let file = Data.Text.unpack (Id.toText topNm) <> "_shim" <.> "cpp"+ digest <- writeHDL hdlDir (file, pprVerilatorShim topNm)+ pure ((file, digest) : filesAndDigests)++-- | Create a shim for using verilator, which loads the entity and steps+-- through simulation until finished.+--+pprVerilatorShim :: Id.Identifier -> Doc+pprVerilatorShim (Id.toText -> topNm) =+ -- Extra newlines are aggressively inserted so the quasiquoter doesn't wrap+ -- the outlines lines in the file. It doesn't matter for code inside main,+ -- but is fatal for the #include directives.+ pretty $ Data.Text.pack [i|+ #include <cstdlib>++ #include <verilated.h>++ #include "V#{topNm}.h"++ int main(int argc, char **argv) {+ Verilated::commandArgs(argc, argv);++ V#{topNm} *top = new V#{topNm};++ while(!Verilated::gotFinish()) {+ top->eval();+ }++ top->final();++ delete top;++ return EXIT_SUCCESS;+ }+ |]+ writeEdam :: FilePath -> (Id.Identifier, Unique) ->@@ -956,38 +1052,31 @@ -- | Normalize a complete hierarchy normalizeEntity- :: CustomReprs+ :: ClashEnv -> BindingMap -- ^ All bindings- -> CompiledPrimMap- -- ^ BlackBox HDL templates- -> TyConMap- -- ^ TyCon cache- -> IntMap TyConName- -- ^ Tuple TyCon cache -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -- ^ Hardcoded 'Type' -> 'HWType' translator- -> Evaluator+ -> PE.Evaluator -- ^ Hardcoded evaluator for partial evaluation+ -> WHNF.Evaluator+ -- ^ Hardcoded evaluator for WHNF (old evaluator) -> [Id] -- ^ TopEntities- -> ClashOpts- -- ^ Debug information level for the normalization process -> Supply.Supply -- ^ Unique supply -> Id -- ^ root of the hierarchy- -> BindingMap-normalizeEntity reprs bindingsMap primMap tcm tupTcm typeTrans eval topEntities- opts supply tm = transformedBindings+ -> IO BindingMap+normalizeEntity env bindingsMap typeTrans peEval eval topEntities supply tm = transformedBindings where doNorm = do norm <- normalize [tm] let normChecked = checkNonRecursive norm cleaned <- cleanupGraph tm normChecked return cleaned- transformedBindings = runNormalization opts supply bindingsMap- typeTrans reprs tcm tupTcm eval primMap emptyVarEnv+ transformedBindings = runNormalization env supply bindingsMap+ typeTrans peEval eval emptyVarEnv topEntities doNorm -- | topologically sort the top entities
src/Clash/Driver/Manifest.hs view
@@ -1,4 +1,8 @@ {-|+Copyright : (C) 2021-2022, QBayLogic B.V.+License : BSD2 (see the file LICENSE)+Maintainer : QBayLogic B.V. <devops@qbaylogic.com>+ Functions to read, write, and handle manifest files. -} @@ -23,10 +27,15 @@ import qualified Data.ByteString.Base16 as Base16 import qualified Data.ByteString.Lazy as ByteStringLazy import Data.ByteString (ByteString)+import Data.Char (toLower)+#if MIN_VERSION_base16_bytestring(1,0,0)+import Data.Either (fromRight)+#endif import Data.Hashable (hash) import Data.HashMap.Strict (HashMap) import qualified Data.HashMap.Strict as HashMap import Data.Maybe (catMaybes)+import Data.Monoid (Ap(getAp)) import qualified Data.Text as Text import qualified Data.Text.Encoding as Text import qualified Data.Text.Lazy as LText@@ -35,8 +44,8 @@ import Data.Text.Prettyprint.Doc.Extra (renderOneLine) import Data.Time (UTCTime) import qualified Data.Set as Set-import Data.Semigroup.Monad (getMon) import Data.String (IsString)+import GHC.Generics (Generic) import System.IO.Error (isDoesNotExistError) import System.FilePath (takeDirectory, (</>)) import System.Directory (listDirectory, doesFileExist)@@ -63,11 +72,25 @@ import Util (OverridingBool(..)) #endif +data PortDirection+ = In | Out | InOut+ deriving (Generic, Eq, Read, Show)++instance ToJSON PortDirection where+ toJSON = Aeson.genericToJSON Aeson.defaultOptions+ { Aeson.constructorTagModifier = fmap toLower }++instance FromJSON PortDirection where+ parseJSON = Aeson.genericParseJSON Aeson.defaultOptions+ { Aeson.constructorTagModifier = fmap toLower }+ data ManifestPort = ManifestPort { mpName :: Text -- ^ Port name (as rendered in HDL) , mpTypeName :: Text -- ^ Type name (as rendered in HDL)+ , mpDirection :: PortDirection+ -- ^ Port direction (in / out / inout) , mpWidth :: Int -- ^ Port width in bits , mpIsClock :: Bool@@ -83,6 +106,7 @@ Aeson.object $ [ "name" .= mpName , "type_name" .= mpTypeName+ , "direction" .= mpDirection , "width" .= mpWidth , "is_clock" .= mpIsClock ] <>@@ -95,28 +119,29 @@ ManifestPort <$> v .: "name" <*> v .: "type_name"+ <*> v .: "direction" <*> v .: "width" <*> v .: "is_clock" <*> v .:? "domain" +-- | Just the 'fileNames' part of 'Manifest'+newtype FilesManifest = FilesManifest [(FilePath, ByteString)]++instance FromJSON FilesManifest where+ parseJSON = Aeson.withObject "FilesManifest" $ fmap FilesManifest . parseFiles+ -- | Information about the generated HDL between (sub)runs of the compiler data Manifest = Manifest- { manifestHash :: Int- -- ^ Hash of the TopEntity and all its dependencies.- --- -- TODO: This is currently calculated using 'hash', but this function wasn't- -- really designed to give any performance (in the collision / crypto- -- sense) guarantees. We should switch to a proper hashing algo like- -- SHA256.- , successFlags :: (Int,Int,Bool)+ { manifestHash :: ByteString+ -- ^ Hash digest of the TopEntity and all its dependencies.+ , successFlags :: (Int, Int) -- ^ Compiler flags used to achieve successful compilation: -- -- * opt_inlineLimit -- * opt_specLimit- -- * opt_floatSupport- , inPorts :: [ManifestPort]- , outPorts :: [ManifestPort]+ , ports :: [ManifestPort]+ -- ^ Ports in the generated @TopEntity@. , componentNames :: [Text] -- ^ Names of all the generated components for the @TopEntity@ (does not -- include the names of the components of the @TestBench@ accompanying@@ -141,20 +166,18 @@ toJSON (Manifest{..}) = Aeson.object [ "version" .= ("unstable" :: Text)- , "hash" .= manifestHash+ , "hash" .= toHexDigest manifestHash , "flags" .= successFlags -- TODO: add nested ports (i.e., how Clash split/filtered arguments) , "components" .= componentNames , "top_component" .= Aeson.object [ "name" .= topComponent- , "ports_flat" .= Aeson.object- [ "in" .= inPorts- , "out" .= outPorts ]+ , "ports_flat" .= ports ] , "files" .= [ Aeson.object [ "name" .= fName- , "sha256" .= Text.decodeUtf8 (Base16.encode fHash)+ , "sha256" .= toHexDigest fHash -- TODO: Add Edam like fields ] | (fName, fHash) <- fileNames]@@ -173,32 +196,50 @@ [ "transitive" .= transitiveDependencies ] ] +-- Note [Failed hex digest decodes]+--+-- 'unsafeFromHexDigest' may fail to decode a hex digest if it contains characters+-- outside of [a-fA-F0-9]. In this case, it will return a broken digest. Because+-- this module discards any data covered by the broken digest if it does not match+-- a freshly calculated one, this poses no problem.++-- | Decode a hex digest to a ByteString. Returns a broken digest if the decode+-- fails - hence it being marked as unsafe.+unsafeFromHexDigest :: Text -> ByteString+unsafeFromHexDigest =+#if MIN_VERSION_base16_bytestring(1,0,0)+ fromRight "failed decode" . Base16.decode . Text.encodeUtf8+#else+ fst . Base16.decode . Text.encodeUtf8+#endif++-- | Encode a ByteString to a hex digest.+toHexDigest :: ByteString -> Text+toHexDigest = Text.decodeUtf8 . Base16.encode++-- | Parse @files@ part of a Manifest file+parseFiles :: Aeson.Object -> Parser [(FilePath, ByteString)]+parseFiles v = do+ files <- v .: "files"+ forM files $ \obj -> do+ fName <- obj .: "name"+ sha256 <- obj .: "sha256"+ -- See Note [Failed hex digest decodes]+ pure (fName, unsafeFromHexDigest sha256)+ instance FromJSON Manifest where parseJSON = Aeson.withObject "Manifest" $ \v -> let topComponent = v .: "top_component"- portsFlat = topComponent >>= (.: "ports_flat") in Manifest- <$> v .: "hash"+ -- See Note [Failed hex digest decodes]+ <$> (unsafeFromHexDigest <$> v .: "hash") <*> v .: "flags"- <*> (portsFlat >>= (.: "in"))- <*> (portsFlat >>= (.: "out"))+ <*> (topComponent >>= (.: "ports_flat")) <*> v .: "components" <*> (topComponent >>= (.: "name"))- <*> do- files <- v .: "files"- forM files $ \obj -> do- fName <- obj .: "name"- sha256 <- obj .: "sha256"- -- Note that we don't particularly care about hash decode- -- failures. Realistically it shouldn't happen, and if it does- -- there's almost no chance it would result in accidental caching.-#if MIN_VERSION_base16_bytestring(1,0,0)- pure (fName, Base16.decodeLenient (Text.encodeUtf8 sha256))-#else- pure (fName, fst (Base16.decode (Text.encodeUtf8 sha256)))-#endif+ <*> parseFiles v <*> (v .: "domains" >>= HashMap.traverseWithKey parseDomain) <*> (v .: "dependencies" >>= (.: "transitive")) where@@ -235,14 +276,16 @@ Id.Identifier -> -- | Port type HWType ->+ PortDirection -> ManifestPort-mkManifestPort backend portId portType = ManifestPort{..}+mkManifestPort backend portId portType portDir = ManifestPort{..} where mpName = Id.toText portId mpWidth = typeSize portType+ mpDirection = portDir mpIsClock = case portType of {Clock _ -> True; _ -> False} mpDomain = hwTypeDomain portType- mpTypeName = flip evalState backend $ getMon $ do+ mpTypeName = flip evalState backend $ getAp $ do LText.toStrict . renderOneLine <$> hdlType (External mpName) portType -- | Filename manifest file should be written to and read from@@ -266,23 +309,31 @@ -- | Files and their hashes [(FilePath, ByteString)] -> -- | Hash returned by 'readFreshManifest'- Int ->+ ByteString -> -- | New manifest Manifest mkManifest backend domains ClashOpts{..} Component{..} components deps files topHash = Manifest { manifestHash = topHash- , inPorts = [mkManifestPort backend pName pType | (pName, pType) <- inputs]- , outPorts = [mkManifestPort backend pName pType | (_, (pName, pType), _) <- outputs]+ , ports = inPorts <> inOutPorts <> outPorts , componentNames = map Id.toText compNames , topComponent = Id.toText componentName , fileNames = files- , successFlags = (opt_inlineLimit, opt_specLimit, opt_floatSupport)+ , successFlags = (opt_inlineLimit, opt_specLimit) , domains = domains , transitiveDependencies = map (nameOcc . varName) deps } where compNames = map Netlist.componentName components + inPorts =+ [mkManifestPort backend pName pType In | p@(pName, pType) <- inputs, not (Netlist.isBiDirectional p)]++ inOutPorts =+ [mkManifestPort backend pName pType InOut | p@(pName, pType) <- inputs, Netlist.isBiDirectional p]++ outPorts =+ [mkManifestPort backend pName pType Out | (_, (pName, pType), _) <- outputs]+ -- | Pretty print an unexpected modification as a list item. pprintUnexpectedModification :: UnexpectedModification -> String pprintUnexpectedModification = \case@@ -327,11 +378,11 @@ FilePath -> -- | ( Nothing if no manifest file was found -- , Nothing on stale cache, disabled cache, or not manifest file found )- IO (Maybe [UnexpectedModification], Maybe Manifest, Int)+ IO (Maybe [UnexpectedModification], Maybe Manifest, ByteString) readFreshManifest tops (bindingsMap, topId) primMap opts@(ClashOpts{..}) clashModDate path = do- manifestM <- readManifest path- modificationsM <- traverse (isUserModified path) manifestM+ modificationsM <- traverse (isUserModified path) =<< readManifest path + manifestM <- readManifest path pure ( modificationsM , checkManifest =<< if opt_cachehdl then manifestM else Nothing@@ -343,9 +394,11 @@ -- Ignore the following settings, they don't affect the generated HDL: -- 1. Debug- opt_dbgLevel = DebugNone- , opt_dbgTransformations = Set.empty- , opt_dbgRewriteHistoryFile = Nothing+ opt_debug = opt_debug+ { dbg_invariants = False+ , dbg_transformations = Set.empty+ , dbg_historyFile = Nothing+ } -- 2. Caching , opt_cachehdl = True@@ -366,13 +419,10 @@ -- they could affect successful compilation, and use that information -- to decide whether to use caching or not (see: XXXX). --- -- 1. termination measures+ -- 5. termination measures , opt_inlineLimit = 20 , opt_specLimit = 20 - -- 2. Float support- , opt_floatSupport = False- -- Finally, also ignore the HDL dir setting, because when a user moves the -- entire dir with generated HDL, they probably still want to use that as -- a cache@@ -381,7 +431,7 @@ -- TODO: Binary encoding does not account for alpha equivalence (nor should -- it?), so the cache behaves more pessimisticly than it could.- topHash = hash $ Binary.encode+ topHash = Sha256.hashlazy $ Binary.encode ( tops , hashCompiledPrimMap primMap , show clashModDate@@ -390,16 +440,12 @@ ) checkManifest manifest@Manifest{manifestHash,successFlags}- | (cachedInline, cachedSpec, cachedFloat) <- successFlags+ | (cachedInline, cachedSpec) <- successFlags -- Higher limits shouldn't affect HDL , cachedInline <= opt_inlineLimit , cachedSpec <= opt_specLimit - -- /Enabling/ float support should compile more designs. Of course, keeping- -- the same value for float support shouldn't invalidate caches either.- , ((cachedFloat && not opt_floatSupport) || (cachedFloat == opt_floatSupport))- -- Callgraph hashes should correspond , manifestHash == topHash = Just manifest@@ -410,8 +456,8 @@ -- | Determines whether the HDL directory the given 'LocatedManifest' was found -- in contains any user made modifications. This is used by Clash to protect the -- user against lost work.-isUserModified :: FilePath -> Manifest -> IO [UnexpectedModification]-isUserModified (takeDirectory -> topDir) Manifest{fileNames} = do+isUserModified :: FilePath -> FilesManifest -> IO [UnexpectedModification]+isUserModified (takeDirectory -> topDir) (FilesManifest fileNames) = do let manifestFiles = Set.fromList (map fst fileNames) @@ -443,7 +489,7 @@ -- | Read a manifest file from disk. Returns 'Nothing' if file does not exist. -- Any other IO exception is re-raised.-readManifest :: FilePath -> IO (Maybe Manifest)+readManifest :: FromJSON a => FilePath -> IO (Maybe a) readManifest path = do contentsE <- tryJust (guard . isDoesNotExistError) (Aeson.decodeFileStrict path) pure (either (const Nothing) id contentsE)
src/Clash/Driver/Types.hs view
@@ -2,7 +2,7 @@ Copyright : (C) 2013-2016, University of Twente, 2016-2017, Myrtle Software Ltd, 2017 , QBayLogic, Google Inc.- 2020 , QBayLogic+ 2020-2022, QBayLogic License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> @@ -12,6 +12,7 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} @@ -20,10 +21,14 @@ -- For Int/Word size #include "MachDeps.h" -import Control.DeepSeq (NFData)+import Control.DeepSeq (NFData(rnf), deepseq) import Data.Binary (Binary) import Data.Fixed import Data.Hashable+import Data.HashMap.Strict (HashMap)+import Data.IntMap.Strict (IntMap)+import Data.Maybe (isJust)+import Data.Set (Set) import qualified Data.Set as Set import Data.Text (Text) @@ -45,14 +50,38 @@ import Util (OverridingBool(..)) #endif +import Clash.Annotations.BitRepresentation.Internal (CustomReprs) import Clash.Signal.Internal import Clash.Core.Term (Term)+import Clash.Core.TyCon (TyConMap, TyConName) import Clash.Core.Var (Id) import Clash.Core.VarEnv (VarEnv) import Clash.Netlist.BlackBox.Types (HdlSyn (..))-import {-# SOURCE #-} Clash.Netlist.Types (PreserveCase(..))+import {-# SOURCE #-} Clash.Netlist.Types (PreserveCase(..), TopEntityT)+import Clash.Primitives.Types (CompiledPrimMap) +data ClashEnv = ClashEnv+ { envOpts :: ClashOpts+ , envTyConMap :: TyConMap+ , envTupleTyCons :: IntMap TyConName+ , envPrimitives :: CompiledPrimMap+ , envCustomReprs :: CustomReprs+ } deriving (Generic, NFData)++data ClashDesign = ClashDesign+ { designEntities :: [TopEntityT]+ , designDomains :: DomainMap+ , designBindings :: BindingMap+ }++instance NFData ClashDesign where+ rnf design =+ designEntities design `seq`+ designDomains design `deepseq`+ designBindings design `deepseq`+ ()+ data IsPrim = IsPrim -- ^ The binding is the unfolding for a primitive.@@ -77,34 +106,193 @@ -- ^ The term representation for this binding. This is polymorphic so -- alternate representations can be used if more appropriate (i.e. in the -- evaluator this can be Value for evaluated bindings).+ , bindingRecursive :: Bool+ -- ^ Whether the binding is recursive.+ --+ -- TODO Ideally the BindingMap would store recursive and non-recursive+ -- bindings in a way similar to Let / Letrec. GHC also does this. } deriving (Binary, Functor, Generic, NFData, Show) -- | Global function binders -- -- Global functions cannot be mutually recursive, only self-recursive. type BindingMap = VarEnv (Binding Term)+type DomainMap = HashMap Text VDomainConfiguration --- | Debug Message Verbosity-data DebugLevel- = DebugNone- -- ^ Don't show debug messages- | DebugSilent- -- ^ Run invariant checks and err if violated (enabled by any debug flag)- | DebugFinal- -- ^ Show completely normalized expressions- | DebugName- -- ^ Show names of applied transformations- | DebugTry- -- ^ Show names of tried AND applied transformations- | DebugApplied- -- ^ Show sub-expressions after a successful rewrite- | DebugAll- -- ^ Show all sub-expressions on which a rewrite is attempted- deriving (Eq,Ord,Read,Enum,Generic,Hashable)+-- | Information to show about transformations during compilation.+--+-- __NB__: The @Ord@ instance compares by amount of information.+data TransformationInfo+ = None+ -- ^ Show no information about transformations.+ | FinalTerm+ -- ^ Show the final term after all applied transformations.+ | AppliedName+ -- ^ Show the name of every transformation that is applied.+ | AppliedTerm+ -- ^ Show the name and result of every transformation that is applied.+ | TryName+ -- ^ Show the name of every transformation that is attempted, and the result+ -- of every transformation that is applied.+ | TryTerm+ -- ^ Show the name and input to every transformation that is applied, and+ -- the result of every transformation that is applied.+ deriving (Eq, Generic, Hashable, Ord, Read, Show, NFData) +-- | Options related to debugging. See 'ClashOpts'+data DebugOpts = DebugOpts+ { dbg_invariants :: Bool+ -- ^ Check that the results of applied transformations do not violate the+ -- invariants for rewriting (e.g. no accidental shadowing, or type changes).+ --+ -- Command line flag: -fclash-debug-invariants+ , dbg_transformationInfo :: TransformationInfo+ -- ^ The information to show when debugging a transformation. See the+ -- 'TransformationInfo' type for different configurations.+ --+ -- Command line flag: -fclash-debug-info (None|FinalTerm|AppliedName|AppliedTerm|TryName|TryTerm)+ , dbg_transformations :: Set String+ -- ^ List the transformations that are being debugged. When the set is empty,+ -- all transformations are debugged.+ --+ -- Command line flag: -fclash-debug-transformations t1[,t2...]+ , dbg_countTransformations :: Bool+ -- ^ Count how many times transformations are applied and provide a summary+ -- at the end of normalization. This includes all transformations, not just+ -- those in 'dbg_transformations'.+ --+ -- Command line flag: -fclash-debug-count-transformations+ , dbg_transformationsFrom :: Maybe Word+ -- ^ Debug transformations applied after the nth transformation applied. This+ -- includes all transformations, not just those in 'dbg_transformations'.+ --+ -- Command line flag: -fclash-debug-transformations-from=N+ , dbg_transformationsLimit :: Maybe Word+ -- ^ Debug up to the nth applied transformation. If this limit is exceeded+ -- then Clash will error. This includes all transformations, not just those+ -- in 'dbg_transformations'.+ --+ -- Command line flag: -fclash-debug-transformations-limit=N+ , dbg_historyFile :: Maybe FilePath+ -- ^ Save information about all applied transformations to a history file+ -- for use with @clash-term@.+ --+ -- Command line flag: -fclash-debug-history[=FILE]+ } deriving (Generic, NFData, Show, Eq)++instance Hashable DebugOpts where+ hashWithSalt s DebugOpts{..} =+ s `hashWithSalt`+ dbg_invariants `hashWithSalt`+ dbg_transformationInfo `hashSet`+ dbg_transformations `hashWithSalt`+ dbg_countTransformations `hashWithSalt`+ dbg_transformationsFrom `hashWithSalt`+ dbg_transformationsLimit `hashWithSalt`+ dbg_historyFile+ where+ hashSet = Set.foldl' hashWithSalt+ infixl 0 `hashSet`++-- | Check whether the debugging options mean the compiler is debugging. This+-- is true only if at least one debugging feature is enabled, namely one of+--+-- * checking for invariants+-- * showing info for transformations+-- * counting applied transformations+-- * limiting the number of transformations+--+-- Other flags, such as writing to a history file or offsetting which applied+-- transformation to show information from do not affect the result, as it is+-- possible to enable these but still not perform any debugging checks in+-- functions like 'applyDebug'. If this is no longer the case, this function+-- will need to be changed.+isDebugging :: DebugOpts -> Bool+isDebugging opts = or+ [ dbg_invariants opts+ , dbg_transformationInfo opts > None+ , dbg_countTransformations opts+ , isJust (dbg_transformationsLimit opts)+ ]++-- | Check whether the requested information is available to the specified+-- transformation according to the options. e.g.+--+-- @+-- traceIf (hasDebugInfo AppliedName name opts) ("Trace something using: " <> show name)+-- @+--+-- This accounts for the set of transformations which are being debugged. For a+-- check which is agnostic to the a transformation, see 'hasTransformationInfo'.+hasDebugInfo :: TransformationInfo -> String -> DebugOpts -> Bool+hasDebugInfo info name opts =+ isDebugged name && hasTransformationInfo info opts+ where+ isDebugged n =+ let set = dbg_transformations opts+ in Set.null set || Set.member n set++-- | Check that the transformation info shown supports the requested info.+-- If the call-site is in the context of a particular transformation,+-- 'hasDebugInfo' should be used instead.+hasTransformationInfo :: TransformationInfo -> DebugOpts -> Bool+hasTransformationInfo info opts =+ info <= dbg_transformationInfo opts++-- NOTE [debugging options]+--+-- The preset debugging options here provide backwards compatibility with the+-- old style DebugLevel enum. However it is also possible to have finer-grained+-- control over debugging by using individual flags which did not previously+-- exist, e.g. -fclash-debug-invariants.++-- | -fclash-debug DebugNone+debugNone :: DebugOpts+debugNone = DebugOpts+ { dbg_invariants = False+ , dbg_transformationInfo = None+ , dbg_transformations = Set.empty+ , dbg_countTransformations = False+ , dbg_transformationsFrom = Nothing+ , dbg_transformationsLimit = Nothing+ , dbg_historyFile = Nothing+ }++-- | -fclash-debug DebugSilent+debugSilent :: DebugOpts+debugSilent = debugNone { dbg_invariants = True }++-- | -fclash-debug DebugFinal+debugFinal :: DebugOpts+debugFinal = debugSilent { dbg_transformationInfo = FinalTerm }++-- | -fclash-debug DebugCount+debugCount :: DebugOpts+debugCount = debugFinal { dbg_countTransformations = True }++-- | -fclash-debug DebugName+debugName :: DebugOpts+debugName = debugCount { dbg_transformationInfo = AppliedName }++-- | -fclash-debug DebugTry+debugTry :: DebugOpts+debugTry = debugName { dbg_transformationInfo = TryName }++-- | -fclash-debug DebugApplied+debugApplied :: DebugOpts+debugApplied = debugTry { dbg_transformationInfo = AppliedTerm }++-- | -fclash-debug DebugAll+debugAll :: DebugOpts+debugAll = debugApplied { dbg_transformationInfo = TryTerm }+ -- | Options passed to Clash compiler data ClashOpts = ClashOpts- { opt_inlineLimit :: Int+ { opt_werror :: Bool+ -- ^ Are warnings treated as errors.+ --+ -- Command line flag: -Werror+ , opt_inlineLimit :: Int -- ^ Change the number of times a function f can undergo inlining inside -- some other function g. This prevents the size of g growing dramatically. --@@ -128,30 +316,8 @@ -- of zero means no potentially non-terminating binding is unfolded. -- -- Command line flag: -fclash-evaluator-fuel-limit- , opt_dbgLevel :: DebugLevel- -- ^ Set the debugging mode for the compiler, exposing additional output. See- -- "DebugLevel" for the available options.- --- -- Command line flag: -fclash-debug- , opt_dbgTransformations :: Set.Set String- -- ^ List the transformations that are to be debugged.- --- -- Command line flag: -fclash-debug-transformations- , opt_dbgTransformationsFrom :: Int- -- ^ Only output debug information from (applied) transformation n- --- -- Command line flag: -fclash-debug-transformations-from- , opt_dbgTransformationsLimit :: Int- -- ^ Only output debug information for n (applied) transformations. If this- -- limit is exceeded, Clash will stop normalizing.- --- -- Command line flag: -fclash-debug-transformations-limit-- , opt_dbgRewriteHistoryFile :: Maybe FilePath- -- ^ Save all applied rewrites to a file- --- -- Command line flag: -fclash-debug-history-+ , opt_debug :: DebugOpts+ -- ^ Options which control debugging. See 'DebugOpts'. , opt_cachehdl :: Bool -- ^ Reuse previously generated output from Clash. Only caches topentities. --@@ -181,9 +347,6 @@ -- ^ Synthesis target. See "HdlSyn" for available options. , opt_errorExtra :: Bool -- ^ Show additional information in error messages- , opt_floatSupport :: Bool- -- ^ Treat floats as a BitVector. Note that operations on floating are still- -- not supported, use vendor primitives instead. , opt_importPaths :: [FilePath] -- ^ Paths where Clash should look for modules , opt_componentPrefix :: Maybe Text@@ -225,21 +388,89 @@ -- ^ At what size do we cache normalized work-free top-level binders. , opt_edalize :: Bool -- ^ Generate an EDAM file for use with Edalize.+ , opt_renderEnums :: Bool+ -- ^ Render sum types with all zero-width fields as enums where supported, as+ -- opposed to rendering them as bitvectors. }+ deriving (Show) +instance NFData ClashOpts where+ rnf o =+ opt_werror o `deepseq`+ opt_inlineLimit o `deepseq`+ opt_specLimit o `deepseq`+ opt_inlineFunctionLimit o `deepseq`+ opt_inlineConstantLimit o `deepseq`+ opt_evaluatorFuelLimit o `deepseq`+ opt_cachehdl o `deepseq`+ opt_clear o `deepseq`+ opt_primWarn o `deepseq`+ opt_color o `seq`+ opt_intWidth o `deepseq`+ opt_hdlDir o `deepseq`+ opt_hdlSyn o `deepseq`+ opt_errorExtra o `deepseq`+ opt_importPaths o `deepseq`+ opt_componentPrefix o `deepseq`+ opt_newInlineStrat o `deepseq`+ opt_escapedIds o `deepseq`+ opt_lowerCaseBasicIds o `deepseq`+ opt_ultra o `deepseq`+ opt_forceUndefined o `deepseq`+ opt_checkIDir o `deepseq`+ opt_aggressiveXOpt o `deepseq`+ opt_aggressiveXOptBB o `deepseq`+ opt_inlineWFCacheLimit o `deepseq`+ opt_edalize o `deepseq`+ opt_renderEnums o `deepseq`+ ()++instance Eq ClashOpts where+ s0 == s1 =+ opt_werror s0 == opt_werror s1 &&+ opt_inlineLimit s0 == opt_inlineLimit s1 &&+ opt_specLimit s0 == opt_specLimit s1 &&+ opt_inlineFunctionLimit s0 == opt_inlineFunctionLimit s1 &&+ opt_inlineConstantLimit s0 == opt_inlineConstantLimit s1 &&+ opt_evaluatorFuelLimit s0 == opt_evaluatorFuelLimit s1 &&+ opt_cachehdl s0 == opt_cachehdl s1 &&+ opt_clear s0 == opt_clear s1 &&+ opt_primWarn s0 == opt_primWarn s1 &&+ (opt_color s0 `eqOverridingBool` opt_color s1) &&+ opt_intWidth s0 == opt_intWidth s1 &&+ opt_hdlDir s0 == opt_hdlDir s1 &&+ opt_hdlSyn s0 == opt_hdlSyn s1 &&+ opt_errorExtra s0 == opt_errorExtra s1 &&+ opt_importPaths s0 == opt_importPaths s1 &&+ opt_componentPrefix s0 == opt_componentPrefix s1 &&+ opt_newInlineStrat s0 == opt_newInlineStrat s1 &&+ opt_escapedIds s0 == opt_escapedIds s1 &&+ opt_lowerCaseBasicIds s0 == opt_lowerCaseBasicIds s1 &&+ opt_ultra s0 == opt_ultra s1 &&+ opt_forceUndefined s0 == opt_forceUndefined s1 &&+ opt_checkIDir s0 == opt_checkIDir s1 &&+ opt_aggressiveXOpt s0 == opt_aggressiveXOpt s1 &&+ opt_aggressiveXOptBB s0 == opt_aggressiveXOptBB s1 &&+ opt_inlineWFCacheLimit s0 == opt_inlineWFCacheLimit s1 &&+ opt_edalize s0 == opt_edalize s1 &&+ opt_renderEnums s0 == opt_renderEnums s1++ where+ eqOverridingBool :: OverridingBool -> OverridingBool -> Bool+ eqOverridingBool Auto Auto = True+ eqOverridingBool Always Always = True+ eqOverridingBool Never Never = True+ eqOverridingBool _ _ = False+ instance Hashable ClashOpts where hashWithSalt s ClashOpts {..} = s `hashWithSalt`+ opt_werror `hashWithSalt` opt_inlineLimit `hashWithSalt` opt_specLimit `hashWithSalt` opt_inlineFunctionLimit `hashWithSalt` opt_inlineConstantLimit `hashWithSalt` opt_evaluatorFuelLimit `hashWithSalt`- opt_dbgLevel `hashSet`- opt_dbgTransformations `hashWithSalt`- opt_dbgTransformationsFrom `hashWithSalt`- opt_dbgTransformationsLimit `hashWithSalt`- opt_dbgRewriteHistoryFile `hashWithSalt` opt_cachehdl `hashWithSalt` opt_clear `hashWithSalt` opt_primWarn `hashOverridingBool`@@ -248,7 +479,6 @@ opt_hdlDir `hashWithSalt` opt_hdlSyn `hashWithSalt` opt_errorExtra `hashWithSalt`- opt_floatSupport `hashWithSalt` opt_importPaths `hashWithSalt` opt_componentPrefix `hashWithSalt` opt_newInlineStrat `hashWithSalt`@@ -260,7 +490,8 @@ opt_aggressiveXOpt `hashWithSalt` opt_aggressiveXOptBB `hashWithSalt` opt_inlineWFCacheLimit `hashWithSalt`- opt_edalize+ opt_edalize `hashWithSalt`+ opt_renderEnums where hashOverridingBool :: Int -> OverridingBool -> Int hashOverridingBool s1 Auto = hashWithSalt s1 (0 :: Int)@@ -268,23 +499,16 @@ hashOverridingBool s1 Never = hashWithSalt s1 (2 :: Int) infixl 0 `hashOverridingBool` - hashSet :: Hashable a => Int -> Set.Set a -> Int- hashSet = Set.foldl' hashWithSalt- infixl 0 `hashSet`- defClashOpts :: ClashOpts defClashOpts = ClashOpts- { opt_dbgLevel = DebugNone- , opt_dbgRewriteHistoryFile = Nothing- , opt_dbgTransformations = Set.empty- , opt_dbgTransformationsFrom = 0- , opt_dbgTransformationsLimit = maxBound+ { opt_werror = False , opt_inlineLimit = 20 , opt_specLimit = 20 , opt_inlineFunctionLimit = 15 , opt_inlineConstantLimit = 0 , opt_evaluatorFuelLimit = 20+ , opt_debug = debugNone , opt_cachehdl = True , opt_clear = False , opt_primWarn = True@@ -293,7 +517,6 @@ , opt_hdlDir = Nothing , opt_hdlSyn = Other , opt_errorExtra = False- , opt_floatSupport = False , opt_importPaths = [] , opt_componentPrefix = Nothing , opt_newInlineStrat = True@@ -306,6 +529,7 @@ , opt_aggressiveXOptBB = False , opt_inlineWFCacheLimit = 10 -- TODO: find "optimal" value , opt_edalize = False+ , opt_renderEnums = True } -- | Synopsys Design Constraint (SDC) information for a component.@@ -314,44 +538,6 @@ newtype SdcInfo = SdcInfo { sdcClock :: [(Text, VDomainConfiguration)] }- deriving (Show)---instance Eq ClashOpts where- s0 == s1 =- opt_inlineLimit s0 == opt_inlineLimit s1 &&- opt_specLimit s0 == opt_specLimit s1 &&- opt_inlineFunctionLimit s0 == opt_inlineFunctionLimit s1 &&- opt_inlineConstantLimit s0 == opt_inlineConstantLimit s1 &&- opt_evaluatorFuelLimit s0 == opt_evaluatorFuelLimit s1 &&- opt_cachehdl s0 == opt_cachehdl s1 &&- opt_clear s0 == opt_clear s1 &&- opt_primWarn s0 == opt_primWarn s1 &&- (opt_color s0 `eqOverridingBool` opt_color s1) &&- opt_intWidth s0 == opt_intWidth s1 &&- opt_hdlDir s0 == opt_hdlDir s1 &&- opt_hdlSyn s0 == opt_hdlSyn s1 &&- opt_errorExtra s0 == opt_errorExtra s1 &&- opt_floatSupport s0 == opt_floatSupport s1 &&- opt_importPaths s0 == opt_importPaths s1 &&- opt_componentPrefix s0 == opt_componentPrefix s1 &&- opt_newInlineStrat s0 == opt_newInlineStrat s1 &&- opt_escapedIds s0 == opt_escapedIds s1 &&- opt_lowerCaseBasicIds s0 == opt_lowerCaseBasicIds s1 &&- opt_ultra s0 == opt_ultra s1 &&- opt_forceUndefined s0 == opt_forceUndefined s1 &&- opt_checkIDir s0 == opt_checkIDir s1 &&- opt_aggressiveXOpt s0 == opt_aggressiveXOpt s1 &&- opt_aggressiveXOptBB s0 == opt_aggressiveXOptBB s1 &&- opt_inlineWFCacheLimit s0 == opt_inlineWFCacheLimit s1 &&- opt_edalize s0 == opt_edalize s1-- where- eqOverridingBool :: OverridingBool -> OverridingBool -> Bool- eqOverridingBool Auto Auto = True- eqOverridingBool Always Always = True- eqOverridingBool Never Never = True- eqOverridingBool _ _ = False -- | Render an SDC file from an SdcInfo. -- The clock periods, waveforms, and targets are all hardcoded.
src/Clash/Netlist.hs view
@@ -1,9 +1,10 @@ {-| Copyright : (C) 2012-2016, University of Twente, 2016-2017, Myrtle Software Ltd,- 2017-2018, Google Inc.+ 2017-2018, Google Inc.,+ 2021-2022, QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Create Netlists out of normalized CoreHW Terms -}@@ -26,7 +27,7 @@ import Control.Monad.Extra (concatMapM) import Control.Monad.Reader (runReaderT) import Control.Monad.State.Strict (State, runStateT, runState)-import Data.Binary.IEEE754 (floatToWord, doubleToWord)+import Data.Bifunctor (first, second) import Data.Char (ord) import Data.Either (partitionEithers, rights) import Data.Foldable (foldlM)@@ -39,6 +40,7 @@ import qualified Data.Set as Set import Data.Primitive.ByteArray (ByteArray (..)) import qualified Data.Text as StrictText+import GHC.Stack (HasCallStack) #if MIN_VERSION_base(4,15,0) import GHC.Num.Integer (Integer (..)) #else@@ -59,6 +61,7 @@ import Clash.Annotations.BitRepresentation.Internal (CustomReprs, DataRepr'(..), ConstrRepr'(..), getDataRepr, getConstrRepr) import Clash.Core.DataCon (DataCon (..))+import Clash.Core.HasType import Clash.Core.Literal (Literal (..)) import Clash.Core.Name (Name(..)) import Clash.Core.Pretty (showPpr)@@ -67,7 +70,7 @@ TickInfo (..), collectArgs, collectArgsTicks, collectTicks, mkApps, mkTicks, stripTicks) import qualified Clash.Core.Term as Core-import Clash.Core.TermInfo (multiPrimInfo', splitMultiPrimArgs, termType)+import Clash.Core.TermInfo (multiPrimInfo', splitMultiPrimArgs) import Clash.Core.Type (Type (..), coreView1, splitFunForallTy, splitCoreFunForallTy) import Clash.Core.TyCon (TyConMap)@@ -76,7 +79,7 @@ import Clash.Core.VarEnv (VarEnv, emptyInScopeSet, emptyVarEnv, extendVarEnv, lookupVarEnv, lookupVarEnv')-import Clash.Driver.Types (BindingMap, Binding(..), ClashOpts (..))+import Clash.Driver.Types (BindingMap, Binding(..), ClashEnv(..), ClashOpts (..)) import Clash.Netlist.BlackBox import qualified Clash.Netlist.Id as Id import Clash.Netlist.Types as HW@@ -88,27 +91,18 @@ -- | Generate a hierarchical netlist out of a set of global binders with -- @topEntity@ at the top. genNetlist- :: Bool+ :: ClashEnv+ -> Bool -- ^ Whether this we're compiling a testbench (suppresses certain warnings)- -> ClashOpts- -- ^ Options Clash was called with- -> CustomReprs- -- ^ Custom bit representations for certain types -> BindingMap -- ^ Global binders -> VarEnv TopEntityT -- ^ TopEntity annotations -> VarEnv Identifier -- ^ Top entity names- -> CompiledPrimMap- -- ^ Primitive definitions- -> TyConMap- -- ^ TyCon cache -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -- ^ Hardcoded Type -> HWType translator- -> Int- -- ^ Int/Word/Integer bit-width -> Bool -- ^ Whether the backend supports ifThenElse expressions -> SomeBackend@@ -122,14 +116,19 @@ -> Id -- ^ Name of the @topEntity@ -> IO (Component, ComponentMap, IdentifierSet)-genNetlist isTb opts reprs globals tops topNames primMap tcm typeTrans iw ite be seen0 env prefixM topEntity = do+genNetlist env isTb globals tops topNames typeTrans ite be seen0 dir prefixM topEntity = do+ let opts = envOpts env+ let reprs = envCustomReprs env+ let primMap = envPrimitives env+ let tcm = envTyConMap env+ let iw = opt_intWidth opts ((_meta, topComponent), s) <- runNetlistMonad isTb opts reprs globals tops primMap tcm typeTrans- iw ite be seen1 env componentNames_ $ genComponent topEntity+ iw ite be seen1 dir componentNames_ $ genComponent topEntity return (topComponent, _components s, seen1) where (componentNames_, seen1) =- genNames (opt_newInlineStrat opts) prefixM seen0 topNames globals+ genNames (opt_newInlineStrat (envOpts env)) prefixM seen0 topNames globals -- | Run a NetlistMonad action in a given environment runNetlistMonad@@ -221,23 +220,22 @@ -- | Generate names for top entities. Should be executed at the very start of -- the synthesis process and shared between all passes. genTopNames- :: Maybe StrictText.Text- -- ^ Prefix- -> Bool- -- ^ Allow escaped identifiers?- -> PreserveCase- -- ^ Lower case basic ids?+ :: ClashOpts -> HDL -- ^ HDL to generate identifiers for -> [TopEntityT] -> (VarEnv Identifier, IdentifierSet)-genTopNames prefixM esc lw hdl tops =+genTopNames opts hdl tops = -- TODO: Report error if fixed top entities have conflicting names flip runState (Id.emptyIdentifierSet esc lw hdl) $ do env0 <- foldlM goFixed emptyVarEnv fixedTops env1 <- foldlM goNonFixed env0 nonFixedTops pure env1 where+ prefixM = opt_componentPrefix opts+ esc = opt_escapedIds opts+ lw = opt_lowerCaseBasicIds opts+ fixedTops = [(topId, ann) | TopEntityT{topId, topAnnotation=Just ann} <- tops] nonFixedTops = [topId | TopEntityT{topId, topAnnotation=Nothing} <- tops] @@ -280,13 +278,13 @@ topEntityTM <- lookupVarEnv compName0 <$> Lens.use topEntityAnns let topAnnMM = topAnnotation <$> topEntityTM- topVarTypeM = snd . splitCoreFunForallTy tcm . varType . topId <$> topEntityTM+ topVarTypeM = snd . splitCoreFunForallTy tcm . coreTypeOf . topId <$> topEntityTM seenIds <~ Lens.use seenComps (wereVoids,compInps,argWrappers,compOutps,resUnwrappers,binders,resultM) <- case splitNormalized tcm componentExpr of Right (args, binds, res) -> do- let varType1 = fromMaybe (varType res) topVarTypeM+ let varType1 = fromMaybe (coreTypeOf res) topVarTypeM mkUniqueNormalized emptyInScopeSet topAnnMM@@ -328,7 +326,7 @@ mkNetDecl :: (Id, Term) -> NetlistMonad [Declaration] mkNetDecl (id_,tm) = preserveVarEnv $ do- hwTy <- unsafeCoreTypeToHWTypeM' $(curLoc) (varType id_)+ hwTy <- unsafeCoreTypeToHWTypeM' $(curLoc) (coreTypeOf id_) if | not (shouldRenderDecl hwTy tm) -> return [] | (Prim pInfo@PrimInfo{primMultiResult=MultiResult}, args) <- collectArgs tm ->@@ -379,7 +377,7 @@ termToWireOrReg :: Term -> NetlistMonad WireOrReg termToWireOrReg (stripTicks -> Case scrut _ alts0@(_:_:_)) = do tcm <- Lens.use tcCache- let scrutTy = termType tcm scrut+ let scrutTy = inferCoreTypeOf tcm scrut scrutHTy <- unsafeCoreTypeToHWTypeM' $(curLoc) scrutTy ite <- Lens.use backEndITE case iteAlts scrutHTy alts0 of@@ -516,7 +514,7 @@ mkSelection declType bndr scrut altTy alts0 tickDecls = do let dstId = netlistId1 id id2identifier bndr tcm <- Lens.use tcCache- let scrutTy = termType tcm scrut+ let scrutTy = inferCoreTypeOf tcm scrut scrutHTy <- unsafeCoreTypeToHWTypeM' $(curLoc) scrutTy scrutId <- Id.suffix dstId "selection" (_,sp) <- Lens.use curCompNm@@ -662,7 +660,7 @@ tcm <- Lens.use tcCache case (isGlobalId fun, lookupVarEnv fun topAnns) of (True, Just topEntity)- | let ty = varType (topId topEntity)+ | let ty = coreTypeOf (topId topEntity) , let (fArgTys0,fResTy) = splitFunForallTy ty -- Take into account that clocks and stuff are split off from any product -- types containing them@@ -706,15 +704,15 @@ -- Nothing -> error ("Internal error: could not find " <> show fun) -- Just (Left err) -> error ("Internal error: " <> show err) -- Just (Right (argIds, _binds, resId)) -> do- -- argTys <- mapM (unsafeCoreTypeToHWTypeM $(curLoc)) (map varType argIds)- -- resTy <- unsafeCoreTypeToHWTypeM $(curLoc) (varType resId)+ -- argTys <- mapM (unsafeCoreTypeToHWTypeM $(curLoc)) (map coreTypeOf argIds)+ -- resTy <- unsafeCoreTypeToHWTypeM $(curLoc) (coreTypeOf resId) -- is <- Lens.use seenIds -- let topAnnM = topAnnotation topEntity -- pure (expandTopEntityOrErr is (zip argIds argTys) (resId, resTy) topAnnM) -- Generate ExpandedTopEntity, see TODO^ is <- Lens.use seenIds- argTys <- mapM (unsafeCoreTypeToHWTypeM $(curLoc) . termType tcm) args+ argTys <- mapM (unsafeCoreTypeToHWTypeM $(curLoc) . inferCoreTypeOf tcm) args resTy <- unsafeCoreTypeToHWTypeM $(curLoc) fResTy let ettArgs = (Nothing,) <$> argTys@@ -740,7 +738,7 @@ |] Just (Binding{bindingTerm}) -> do (_, Component compName compInps co _) <- preserveVarEnv $ genComponent fun- let argTys = map (termType tcm) args+ let argTys = map (inferCoreTypeOf tcm) args argHWTys <- mapM coreTypeToHWTypeM' argTys (argExprs, concat -> argDecls) <- unzip <$>@@ -845,19 +843,15 @@ Int64Literal i -> return (HW.Literal (Just (Signed 64,64)) $ NumLit i, []) Word64Literal w -> return (HW.Literal (Just (Unsigned 64,64)) $ NumLit w, []) CharLiteral c -> return (HW.Literal (Just (Unsigned 21,21)) . NumLit . toInteger $ ord c, [])- FloatLiteral r -> let f = fromRational r :: Float- i = toInteger (floatToWord f)- in return (HW.Literal (Just (BitVector 32,32)) (NumLit i), [])- DoubleLiteral r -> let d = fromRational r :: Double- i = toInteger (doubleToWord d)- in return (HW.Literal (Just (BitVector 64,64)) (NumLit i), [])+ FloatLiteral w -> return (HW.Literal (Just (BitVector 32,32)) (NumLit $ toInteger w), [])+ DoubleLiteral w -> return (HW.Literal (Just (BitVector 64,64)) (NumLit $ toInteger w), []) NaturalLiteral n -> return (HW.Literal (Just (Unsigned iw,iw)) $ NumLit n, []) #if MIN_VERSION_base(4,15,0) ByteArrayLiteral (ByteArray ba) -> return (HW.Literal Nothing (NumLit (IP ba)),[]) #else ByteArrayLiteral (ByteArray ba) -> return (HW.Literal Nothing (NumLit (Jp# (BN# ba))),[]) #endif- _ -> error $ $(curLoc) ++ "not an integer or char literal"+ StringLiteral s -> return (HW.Literal Nothing $ StringLit s, []) mkExpr bbEasD declType bndr app = let (appF,args,ticks) = collectArgsTicks app@@ -891,7 +885,7 @@ Case scrut ty' [alt] -> mkProjection bbEasD bndr scrut ty' alt Case scrut tyA alts -> do tcm <- Lens.use tcCache- let scrutTy = termType tcm scrut+ let scrutTy = inferCoreTypeOf tcm scrut scrutHTy <- unsafeCoreTypeToHWTypeM' $(curLoc) scrutTy ite <- Lens.use backEndITE let wr = case iteAlts scrutHTy alts of@@ -929,7 +923,7 @@ -> NetlistMonad (Expr, [Declaration]) mkProjection mkDec bndr scrut altTy alt@(pat,v) = do tcm <- Lens.use tcCache- let scrutTy = termType tcm scrut+ let scrutTy = inferCoreTypeOf tcm scrut e = Case scrut scrutTy [alt] (_,sp) <- Lens.use curCompNm varTm <- case v of@@ -974,7 +968,7 @@ ++ showPpr e) Nothing) else tms- argHWTys <- mapM coreTypeToHWTypeM' (map varType tms)+ argHWTys <- mapM coreTypeToHWTypeM' (map coreTypeOf tms) let tmsBundled = zip argHWTys tms' tmsFiltered = filter (maybe False (not . isVoid) . fst) tmsBundled tmsFiltered' = map snd tmsFiltered@@ -1021,7 +1015,7 @@ mkDcApplication [dstHType] bndr dc args = do let dcNm = nameOcc (dcName dc) tcm <- Lens.use tcCache- let argTys = map (termType tcm) args+ let argTys = map (inferCoreTypeOf tcm) args argNm <- netlistId1 return (\b -> Id.suffix (id2identifier b) "_dc_arg") bndr argHWTys <- mapM coreTypeToHWTypeM' argTys @@ -1092,6 +1086,11 @@ Vector _ _ -> case argExprsFiltered of [e1,e2] -> return (HW.DataCon dstHType VecAppend [e1,e2]) _ -> error $ $(curLoc) ++ "Unexpected number of arguments for `Cons`: " ++ showPpr args+ MemBlob _ _ ->+ case compare 6 (length argExprsFiltered) of+ EQ -> return (HW.DataCon dstHType (DC (dstHType,0)) argExprsFiltered)+ LT -> error $ $(curLoc) ++ "Over-applied constructor"+ GT -> error $ $(curLoc) ++ "Under-applied constructor" RTree 0 _ -> case argExprsFiltered of [e] -> return (HW.DataCon dstHType RTreeAppend [e]) _ -> error $ $(curLoc) ++ "Unexpected number of arguments for `LR`: " ++ showPpr args@@ -1150,7 +1149,7 @@ -- Handle MultiId assignment mkDcApplication dstHTypes (MultiId argNms) _ args = do tcm <- Lens.use tcCache- let argTys = map (termType tcm) args+ let argTys = map (inferCoreTypeOf tcm) args argHWTys <- mapM coreTypeToHWTypeM' argTys -- Filter out the arguments of hwtype `Void` and only translate -- them to the intermediate HDL afterwards
src/Clash/Netlist/BlackBox.hs view
@@ -2,9 +2,10 @@ {-| Copyright : (C) 2012-2016, University of Twente, 2016-2017, Myrtle Software Ltd,- 2017 , Google Inc.+ 2017 , Google Inc.,+ 2021 , QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Functions to create BlackBox Contexts and fill in BlackBox templates -}@@ -13,6 +14,7 @@ {-# LANGUAGE LambdaCase #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TemplateHaskell #-}@@ -25,6 +27,7 @@ import Control.Monad (when, replicateM, zipWithM) import Control.Monad.Extra (concatMapM) import Control.Monad.IO.Class (liftIO)+import Data.Bifunctor (first, second) import Data.Char (ord) import Data.Either (lefts, partitionEithers) import qualified Data.HashMap.Lazy as HashMap@@ -32,21 +35,21 @@ import Data.List (elemIndex, partition) import Data.List.Extra (countEq, mapAccumLM) import Data.Maybe (listToMaybe, fromJust, fromMaybe)-import Data.Semigroup.Monad+import Data.Monoid (Ap(getAp)) import qualified Data.Set as Set import Data.Text.Lazy (fromStrict) import qualified Data.Text.Lazy as Text import Data.Text (unpack) import qualified Data.Text as TextS+import Data.Text.Extra import GHC.Stack- (callStack, prettyCallStack)+ (HasCallStack, callStack, prettyCallStack) import qualified System.Console.ANSI as ANSI import System.Console.ANSI- ( hSetSGR, SGR(SetConsoleIntensity, SetColor), Color(Magenta)+ ( hSetSGR, SGR(SetConsoleIntensity, SetColor), Color(Magenta, Red) , ConsoleIntensity(BoldIntensity), ConsoleLayer(Foreground), ColorIntensity(Vivid)) import System.IO (hPutStrLn, stderr, hFlush, hIsTerminalDevice)-import TextShow (showt) #if MIN_VERSION_ghc(9,0,0) import GHC.Utils.Misc (OverridingBool(..)) #else@@ -59,6 +62,7 @@ , extractPrim) import Clash.Core.DataCon as D (dcTag) import Clash.Core.FreeVars (freeIds)+import Clash.Core.HasType import Clash.Core.Literal as L (Literal (..)) import Clash.Core.Name (Name (..), mkUnsafeSystemName)@@ -67,7 +71,7 @@ import Clash.Core.Subst (extendIdSubst, mkSubst, substTm) import Clash.Core.Term as C (IsMultiPrim (..), PrimInfo (..), Term (..), WorkInfo (..), collectArgs,- collectArgsTicks, collectBndrs, mkApps)+ collectArgsTicks, collectBndrs, mkApps, PrimUnfolding(..)) import Clash.Core.TermInfo import Clash.Core.Type as C (Type (..), ConstTy (..), TypeView (..), mkFunTy, splitFunTys, tyView)@@ -84,11 +88,12 @@ import qualified Clash.Backend as Backend import Clash.Debug (debugIsOn) import Clash.Driver.Types- (opt_primWarn, opt_color, ClashOpts)+ (ClashOpts(opt_primWarn, opt_color, opt_werror)) import Clash.Netlist.BlackBox.Types as B import Clash.Netlist.BlackBox.Util as B import Clash.Netlist.Types as N import Clash.Netlist.Util as N+import Clash.Normalize.Primitives (removedArg) import Clash.Primitives.Types as P import qualified Clash.Primitives.Util as P import Clash.Signal.Internal (ActiveEdge (..))@@ -110,11 +115,18 @@ Auto -> hIsTerminalDevice stderr hSetSGR stderr [SetConsoleIntensity BoldIntensity]- when useColor $ hSetSGR stderr [SetColor Foreground Vivid Magenta]- hPutStrLn stderr $ "[WARNING] " ++ msg- hSetSGR stderr [ANSI.Reset]- hFlush stderr + case opt_werror opts of+ True -> do+ when useColor $ hSetSGR stderr [SetColor Foreground Vivid Red]+ throw (ClashException noSrcSpan msg Nothing)++ False -> do+ when useColor $ hSetSGR stderr [SetColor Foreground Vivid Magenta]+ hPutStrLn stderr $ "[WARNING] " ++ msg+ hSetSGR stderr [ANSI.Reset]+ hFlush stderr+ -- | Generate the context for a BlackBox instantiation. mkBlackBoxContext :: HasCallStack@@ -130,11 +142,11 @@ let resNms = map id2identifier resIds resNm = fromMaybe (error "mkBlackBoxContext: head") (listToMaybe resNms)- resTys <- mapM (unsafeCoreTypeToHWTypeM' $(curLoc) . V.varType) resIds+ resTys <- mapM (unsafeCoreTypeToHWTypeM' $(curLoc) . coreTypeOf) resIds (imps,impDecls) <- unzip <$> zipWithM (mkArgument bbName resNm) [0..] termArgs (funs,funDecls) <- mapAccumLM- (addFunction (map V.varType resIds))+ (addFunction (map coreTypeOf resIds)) IntMap.empty (zip termArgs [0..]) @@ -222,15 +234,15 @@ ) mkArgument bbName bndr nArg e = do tcm <- Lens.use tcCache- let ty = termType tcm e+ let ty = inferCoreTypeOf tcm e iw <- Lens.use intWidth hwTyM <- fmap stripFiltered <$> N.termHWTypeM e let eTyMsg = "(" ++ showPpr e ++ " :: " ++ showPpr ty ++ ")" ((e',t,l),d) <- case hwTyM of Nothing | (Prim p,_) <- collectArgs e- , primName p == "Clash.Transformations.removedArg"- -> return ((Identifier (Id.unsafeMake "Clash.Transformations.removedArg") Nothing, Void Nothing, False), [])+ , primName p == showt 'removedArg+ -> return ((Identifier (Id.unsafeMake (showt 'removedArg)) Nothing, Void Nothing, False), []) | otherwise -> return ((error ($(curLoc) ++ "Forced to evaluate untranslatable type: " ++ eTyMsg), Void Nothing, False), []) Just hwTy -> case collectArgsTicks e of@@ -263,7 +275,7 @@ (Case scrut ty' [alt],[],_) -> do (projection,decls) <- mkProjection False (NetlistId bndr ty) scrut ty' alt return ((projection,hwTy,False),decls)- (Letrec _bnds _term, [], _ticks) -> do+ (Let _bnds _term, [], _ticks) -> do (exprN, letDecls) <- mkExpr False Concurrent (NetlistId bndr ty) e return ((exprN,hwTy,False),letDecls) _ -> do@@ -488,7 +500,7 @@ return (exprN,dcDecls) [Right _, Left scrut] -> do tcm <- Lens.use tcCache- let scrutTy = termType tcm scrut+ let scrutTy = inferCoreTypeOf tcm scrut (scrutExpr,scrutDecls) <- mkExpr False Concurrent (NetlistId (Id.unsafeMake "c$tte_rhs") scrutTy) scrut case scrutExpr of@@ -506,7 +518,7 @@ return (N.Literal (Just (Signed iw,iw)) (NumLit $ toInteger $ dcTag dc - 1),[]) [Right _,Left scrut] -> do tcm <- Lens.use tcCache- let scrutTy = termType tcm scrut+ let scrutTy = inferCoreTypeOf tcm scrut scrutHTy <- unsafeCoreTypeToHWTypeM' $(curLoc) scrutTy (scrutExpr,scrutDecls) <- mkExpr False Concurrent (NetlistId (Id.unsafeMake "c$dtt_rhs") scrutTy) scrut@@ -539,7 +551,7 @@ [dstNm] -> return ( Identifier dstNm Nothing , dstDecl ++ decls ++ [Assignment dstNm expr])- _ -> error "internal error"+ _ -> error $ $(curLoc) ++ "bindSimIO: " ++ show resM _ -> return (Noop,decls) @@ -735,14 +747,14 @@ let u = case dst of CoreId u0 -> u0 _ -> uniqAway is0- (mkLocalId (termType tcm e)+ (mkLocalId (inferCoreTypeOf tcm e) (mkUnsafeSystemName "mealyres" 0)) in (bsN ++ [(u,e)], u) e -> let u = case dst of CoreId u0 -> u0 _ -> uniqAway is0- (mkLocalId (termType tcm e)+ (mkLocalId (inferCoreTypeOf tcm e) (mkUnsafeSystemName "mealyres" 0)) in ([(u,e)], u) #if __GLASGOW_HASKELL__ >= 900@@ -754,7 +766,7 @@ -- Take into account that the state argument is split over multiple -- binders because it contained types that are not allowed to occur in -- a HDL aggregate type- mealyInitLength = length (splitShouldSplit tcm [termType tcm mealyInit])+ mealyInitLength = length (splitShouldSplit tcm [inferCoreTypeOf tcm mealyInit]) (sArgs,iArgs) = splitAt mealyInitLength args1 -- Give all binders a unique name let sBindings = map (,mealyInit) sArgs ++ map (,mealyIn) iArgs ++ bs@@ -838,13 +850,13 @@ -- because we're basically clocked logic; so we need to have our outputs -- ready before the ambient system starts sampling them. The clockGen code -- ensures that the "opposite" edge always comes first.- kdTy <- unsafeCoreTypeToHWTypeM $(curLoc) (termType tcm kd)+ kdTy <- unsafeCoreTypeToHWTypeM $(curLoc) (inferCoreTypeOf tcm kd) let edge = case stripVoid (stripFiltered kdTy) of KnownDomain _ _ Rising _ _ _ -> Falling KnownDomain _ _ Falling _ _ _ -> Rising _ -> error "internal error" (clkExpr,clkDecls) <-- mkExpr False Concurrent (NetlistId (Id.unsafeMake "__MEALY_CLK__") (termType tcm clk)) clk+ mkExpr False Concurrent (NetlistId (Id.unsafeMake "__MEALY_CLK__") (inferCoreTypeOf tcm clk)) clk -- collect the declarations related to the input let netDeclsInp1 = netDeclsInp ++ inpDeclsMisc@@ -923,11 +935,11 @@ -- | Collect the sequential declarations for 'appIO' collectAppIO :: NetlistId -> [Term] -> [Term] -> NetlistMonad (Expr,[Declaration]) collectAppIO dst (fun1:arg1:_) rest = case collectArgs fun1 of- (Prim (PrimInfo "Clash.Explicit.SimIO.fmapSimIO#" _ _ _),(lefts -> (fun0:arg0:_))) -> do+ (Prim (PrimInfo "Clash.Explicit.SimIO.fmapSimIO#" _ _ _ _),(lefts -> (fun0:arg0:_))) -> do tcm <- Lens.use tcCache let argN = map (Left . unSimIO tcm) (arg0:arg1:rest) mkExpr False Sequential dst (mkApps fun0 argN)- (Prim (PrimInfo "Clash.Explicit.SimIO.apSimIO#" _ _ _),(lefts -> args)) -> do+ (Prim (PrimInfo "Clash.Explicit.SimIO.apSimIO#" _ _ _ _),(lefts -> args)) -> do collectAppIO dst args (arg1:rest) _ -> error ("internal error:\n" ++ showPpr (fun1:arg1:rest)) @@ -944,14 +956,15 @@ -> Term -> Term unSimIO tcm arg =- let argTy = termType tcm arg+ let argTy = inferCoreTypeOf tcm arg in case tyView argTy of TyConApp _ [tcArg] ->- mkApps (Prim ( PrimInfo- "Clash.Explicit.SimIO.unSimIO#"- (mkFunTy argTy tcArg)- WorkNever- SingleResult ))+ mkApps (Prim (PrimInfo+ "Clash.Explicit.SimIO.unSimIO#"+ (mkFunTy argTy tcArg)+ WorkNever+ SingleResult+ NoUnfolding)) [Left arg] _ -> error ("internal error:\n" ++ showPpr arg) @@ -1002,7 +1015,7 @@ P.BlackBoxHaskell{name=pName, functionName=fName, function=(_, func)} -> do -- Determine result type of this blackbox. If it's not a -- function, simply use its term type.- let (_, resTy) = splitFunTys tcm (termType tcm e)+ let (_, resTy) = splitFunTys tcm (inferCoreTypeOf tcm e) bbhRes <- func True pName args [resTy] case bbhRes of Left err ->@@ -1013,7 +1026,7 @@ Left ( bbKind, bbOutputReg, bbLibrary, bbImports , bbIncludes, pName, template) Data dc -> do- let eTy = termType tcm e+ let eTy = inferCoreTypeOf tcm e (_,resTy) = splitFunTys tcm eTy resHTyM0 <- coreTypeToHWTypeM resTy@@ -1139,7 +1152,7 @@ return ((Left l',if oreg then Reg else Wire,libs,imps,inc,bbCtx),dcls ++ templDecl) Left (TExpr,_,libs,imps,inc,nm,templ') -> do onBlackBox- (\t -> do t' <- getMon (prettyBlackBox t)+ (\t -> do t' <- getAp (prettyBlackBox t) let t'' = Id.unsafeMake (Text.toStrict t') assn = Assignment (Id.unsafeMake "~RESULT") (Identifier t'' Nothing) return ((Right (Id.unsafeMake "",[assn]),Wire,libs,imps,inc,bbCtx),dcls))@@ -1147,7 +1160,7 @@ let f' bbCtx' = do let assn = Assignment (Id.unsafeMake "~RESULT") (BlackBoxE nm libs imps inc templ' bbCtx' False)- p <- getMon (Backend.blockDecl (Id.unsafeMake "") [assn])+ p <- getAp (Backend.blockDecl (Id.unsafeMake "") [assn]) return p return ((Left (BBFunction bbName bbHash (TemplateFunction k g f')) ,Wire@@ -1165,7 +1178,7 @@ where goExpr app@(collectArgsTicks -> (C.Var fun,args@(_:_),ticks)) = do tcm <- Lens.use tcCache- resTy <- unsafeCoreTypeToHWTypeM' $(curLoc) (termType tcm app)+ resTy <- unsafeCoreTypeToHWTypeM' $(curLoc) (inferCoreTypeOf tcm app) let (tmArgs,tyArgs) = partitionEithers args if null tyArgs then@@ -1181,7 +1194,7 @@ throw (ClashException sp ($(curLoc) ++ "Not in normal form: Var-application with Type arguments:\n\n" ++ showPpr app) Nothing) goExpr e' = do tcm <- Lens.use tcCache- let eType = termType tcm e'+ let eType = inferCoreTypeOf tcm e' (appExpr,appDecls) <- mkExpr False Concurrent (NetlistId (Id.unsafeMake "c$bb_res") eType) e' let assn = Assignment (Id.unsafeMake "~RESULT") appExpr nm <- if null appDecls@@ -1205,7 +1218,7 @@ go _ _ (Case scrut ty [alt]) = do tcm <- Lens.use tcCache- let sTy = termType tcm scrut+ let sTy = inferCoreTypeOf tcm scrut (projection,decls) <- mkProjection False (NetlistId (Id.unsafeMake "c$bb_res") sTy) scrut ty alt let assn = Assignment (Id.unsafeMake "~RESULT") projection nm <- if null decls@@ -1215,7 +1228,7 @@ go _ _ (Case scrut ty alts@(_:_:_)) = do tcm <- Lens.use tcCache- let scrutTy = termType tcm scrut+ let scrutTy = inferCoreTypeOf tcm scrut scrutHTy <- unsafeCoreTypeToHWTypeM' $(curLoc) scrutTy ite <- Lens.use backEndITE let wr = case iteAlts scrutHTy alts of@@ -1233,7 +1246,7 @@ nm <- Id.makeBasic "selection" return (Right ((nm,assn++selectionDecls),Wire)) - go is0 _ e'@(Letrec {}) = do+ go is0 _ e'@(Let{}) = do tcm <- Lens.use tcCache let normE = splitNormalized tcm e' (_,[],[],_,[],binders,resultM) <- case normE of
src/Clash/Netlist/BlackBox/Parser.hs view
@@ -1,8 +1,9 @@ {-| Copyright : (C) 2012-2016, University of Twente,- 2017 , Myrtle Software Ltd+ 2017 , Myrtle Software Ltd,+ 2021 , QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Parser definitions for BlackBox templates -}@@ -16,7 +17,6 @@ import Control.Applicative ((<|>)) import Data.Text.Lazy (Text, pack, unpack) import qualified Data.Text.Lazy as Text-import Text.Parser.Combinators import Text.Trifecta hiding (Err) import Text.Trifecta.Delta @@ -129,6 +129,7 @@ <|> IsSync <$> (string "~ISSYNC" *> brackets' natural') <|> IsInitDefined <$> (string "~ISINITDEFINED" *> brackets' natural') <|> CtxName <$ string "~CTXNAME"+ <|> LongestPeriod <$ string "~LONGESTPERIOD" natural' :: TokenParsing m => m Int natural' = fmap fromInteger natural
src/Clash/Netlist/BlackBox/Types.hs view
@@ -1,18 +1,14 @@ {-| Copyright : (C) 2012-2016, University of Twente,- 2017 , Myrtle Software Ltd+ 2017 , Myrtle Software Ltd,+ 2021-2022, QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Types used in BlackBox modules -} -{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveAnyClass #-}--- since GHC 8.6 we can haddock individual contructor fields \o/-#if __GLASGOW_HASKELL__ >= 806-#define FIELD ^-#endif module Clash.Netlist.BlackBox.Types ( BlackBoxMeta(..)@@ -135,7 +131,7 @@ | Err !(Maybe Int) -- ^ Error value hole | TypElem !Element- -- ^ Select element type from a vector type+ -- ^ Select element type from a vector-like type | CompName -- ^ Hole for the name of the component in which the blackbox is instantiated | IncludeName !Int@@ -144,11 +140,11 @@ | Size !Element -- ^ Size of a type hole | Length !Element- -- ^ Length of a vector hole+ -- ^ Length of a vector-like hole | Depth !Element -- ^ Depth of a tree hole | MaxIndex !Element- -- ^ Max index into a vector+ -- ^ Max index into a vector-like type | FilePath !Element -- ^ Hole containing a filepath for a data file | Template [Element] [Element]@@ -175,6 +171,8 @@ -- ^ Tag of a domain. | Period !Int -- ^ Period of a domain.+ | LongestPeriod+ -- ^ Longest period of all known domains | ActiveEdge !Signal.ActiveEdge !Int -- ^ Test active edge of memory elements in a certain domain | IsSync !Int@@ -213,9 +211,9 @@ data Decl = Decl !Int- -- FIELD Argument position of the function to instantiate+ -- ^ Argument position of the function to instantiate !Int- -- FIELD Subposition of function: blackboxes can request multiple instances+ -- ^ Subposition of function: blackboxes can request multiple instances -- to be rendered of their given functions. This subposition indicates the -- nth function instance to be rendered (zero-indexed). --@@ -224,7 +222,7 @@ -- to indicate the subposition, and every ~INST will default its subposition -- to zero. Haskell blackboxes can use this data type. [(BlackBoxTemplate,BlackBoxTemplate)]- -- FIELD (name of signal, type of signal)+ -- ^ (name of signal, type of signal) deriving (Show, Generic, NFData, Binary, Eq, Hashable) data HdlSyn = Vivado | Quartus | Other
src/Clash/Netlist/BlackBox/Util.hs view
@@ -1,8 +1,9 @@ {-| Copyright : (C) 2012-2016, University of Twente, 2016-2017, Myrtle Software Ltd,+ 2021-2022, QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Utilties to verify blackbox contexts against templates and rendering filled in templates@@ -21,20 +22,19 @@ import Control.Exception (throw) import Control.Lens (use, (%=), _1, _2, element, (^?))-import Control.Monad (forM)+import Control.Monad (forM, (<=<)) import Control.Monad.State (State, StateT (..), lift)+import Data.Bitraversable (bitraverse) import Data.Bool (bool) import Data.Coerce (coerce) import Data.Foldable (foldrM) import Data.Hashable (Hashable (..))+import qualified Data.HashMap.Strict as HashMap import qualified Data.IntMap as IntMap import Data.List (nub) import Data.List.Extra (indexMaybe)-#if !MIN_VERSION_base(4,11,0)-import Data.Monoid-#endif import Data.Maybe (mapMaybe, maybeToList, fromJust)-import Data.Semigroup.Monad+import Data.Monoid (Ap(getAp)) import qualified Data.Text import Data.Text.Lazy (Text) import qualified Data.Text.Lazy as Text@@ -46,6 +46,7 @@ #endif import Data.Text.Prettyprint.Doc.Extra+import GHC.Stack (HasCallStack) import System.FilePath (replaceBaseName, takeBaseName, takeFileName, (<.>)) import Text.Printf@@ -63,7 +64,7 @@ import qualified Clash.Netlist.Types as N import Clash.Netlist.Util (typeSize, isVoid, stripVoid) import Clash.Signal.Internal- (ResetKind(..), ResetPolarity(..), InitBehavior(..))+ (ResetKind(..), ResetPolarity(..), InitBehavior(..), VDomainConfiguration (..)) import Clash.Util import qualified Clash.Util.Interpolate as I @@ -206,7 +207,7 @@ ++ " is already defined in BlackBox for: " ++ bbnm) Component (Decl n subN l') ->- Component <$> (Decl n subN <$> mapM (combineM (mapM setSym') (mapM setSym')) l')+ Component <$> (Decl n subN <$> mapM (bitraverse (mapM setSym') (mapM setSym')) l') IF c t f -> IF <$> pure c <*> mapM setSym' t <*> mapM setSym' f SigD e' m -> SigD <$> (mapM setSym' e') <*> pure m BV t e' m -> BV <$> pure t <*> mapM setSym' e' <*> pure m@@ -285,6 +286,14 @@ layout = LayoutOptions (AvailablePerLine 120 0.4) nms <- forM includes $ \((nm,_),inc) -> do+ case verifyBlackBoxContext bbCtx inc of+ Nothing -> return ()+ Just err0 -> do+ sp <- getSrcSpan+ let err1 = concat [ "Couldn't instantiate blackbox for "+ , Data.Text.unpack (bbName bbCtx), ". Verification "+ , "procedure reported:\n\n" ++ err0 ]+ throw (ClashException sp ($(curLoc) ++ err1) Nothing) let bbCtx' = bbCtx {bbQsysIncName = map Text.toStrict nms'} incForHash <- onBlackBox (renderTemplate bbCtx') (\_name _hash (N.TemplateFunction _ _ f) -> do@@ -331,8 +340,8 @@ -> Element -> State backend (Int -> Text) renderElem b (Component (Decl n subN (l:ls))) = do- (o,oTy,_) <- idToExpr <$> combineM (lineToIdentifier b) (return . lineToType b) l- is <- mapM (fmap idToExpr . combineM (lineToIdentifier b) (return . lineToType b)) ls+ (o,oTy,_) <- idToExpr <$> bitraverse (lineToIdentifier b) (return . lineToType b) l+ is <- mapM (fmap idToExpr . bitraverse (lineToIdentifier b) (return . lineToType b)) ls let func0 = IntMap.lookup n (bbFunctions b) errr = concat [ "renderElem: not enough functions rendered? Needed " , show (subN +1 ), " got only ", show (length (fromJust func0)) ]@@ -348,7 +357,7 @@ return t Right (nm0,ds) -> do nm1 <- Id.next nm0- block <- getMon (blockDecl nm1 ds)+ block <- getAp (blockDecl nm1 ds) return (render block) templ4 <-@@ -364,7 +373,7 @@ nm1 <- Id.toText <$> Id.makeBasic "bb" nm2 <- Id.makeBasic "bb" let bbD = BlackBoxD nm1 libs imps inc (N.BBTemplate templ3) b'- block <- getMon (blockDecl nm2 (templDecls ++ [bbD]))+ block <- getAp (blockDecl nm2 (templDecls ++ [bbD])) return (render block) case verifyBlackBoxContext b' templ4 of@@ -384,7 +393,7 @@ Nothing -> snd $ bbResult "~SIGD" b Just n -> let (_,ty',_) = bbInputs b !! n in ty'- t <- getMon (hdlSig e' ty)+ t <- getAp (hdlSig e' ty) return (const (renderOneLine t)) renderElem b (Period n) = do@@ -395,6 +404,11 @@ _ -> error $ $(curLoc) ++ "Period: Expected `KnownDomain` or `KnownConfiguration`, not: " ++ show ty +renderElem _ LongestPeriod = do+ doms <- domainConfigurations+ let longestPeriod = maximum [vPeriod v | v <- HashMap.elems doms]+ return (const (Text.pack (show longestPeriod)))+ renderElem b (Tag n) = do let (_, ty, _) = bbInputs b !! n case stripVoid ty of@@ -421,9 +435,11 @@ check xOpt iw syn c' = case c' of (Size e) -> typeSize (lineToType b [e]) (Length e) -> case lineToType b [e] of- (Vector n _) -> n- Void (Just (Vector n _)) -> n- _ -> 0 -- HACK: So we can test in splitAt if one of the+ (Vector n _) -> n+ Void (Just (Vector n _)) -> n+ (MemBlob n _) -> n+ Void (Just (MemBlob n _)) -> n+ _ -> 0 -- HACK: So we can test in splitAt if one of the -- vectors in the tuple had a zero length (Lit n) -> case bbInputs b !! n of (l,_,_)@@ -569,7 +585,8 @@ in ty lineToType b [(TypElem t)] = case lineToType b [t] of Vector _ elTy -> elTy- _ -> error $ $(curLoc) ++ "Element type selection of a non-vector type"+ MemBlob _ m -> BitVector m+ _ -> error $ $(curLoc) ++ "Element type selection of a non-vector-like type" lineToType b [(IndexType (Lit n))] = case bbInputs b !! n of (Literal _ (NumLit n'),_,_) -> Index (fromInteger n')@@ -585,37 +602,35 @@ -> State backend Text renderTag _ (Text t) = return t renderTag b (Result) = do- fmap renderOneLine . getMon . expr False . fst $ bbResult "~RESULT" b+ fmap renderOneLine . getAp . expr False . fst $ bbResult "~RESULT" b renderTag b (Arg n) = do let (e,_,_) = bbInputs b !! n- renderOneLine <$> getMon (expr False e)+ renderOneLine <$> getAp (expr False e) renderTag b (Const n) = do let (e,_,_) = bbInputs b !! n- renderOneLine <$> getMon (expr False e)+ renderOneLine <$> getAp (expr False e) renderTag b t@(ArgGen k n) | k == bbLevel b , let (e,_,_) = bbInputs b !! n- = renderOneLine <$> getMon (expr False e)+ = renderOneLine <$> getAp (expr False e) | otherwise- = getMon (prettyElem t)+ = getAp (prettyElem t) renderTag b (Lit n) =- renderOneLine <$> getMon (expr False (mkLit e))+ renderOneLine <$> getAp (expr False (mkLit e)) where (e,_,_) = bbInputs b !! n mkLit (Literal (Just (Signed _,_)) i) = Literal Nothing i -- Integer, Int# mkLit (Literal (Just (Unsigned _,_)) i) = Literal Nothing i -- KnownNat, Natural, Word# - -- TODO Remove the blackboxes for GHC.Types.I# and GHC.Types.W#.- -- Then we can use these two rules for Int and Word- -- mkLit (DataCon _ (DC (Void {}, _)) [Literal (Just (Signed _,_)) i]) = Literal Nothing i- mkLit (DataCon _ (DC (Void {}, _)) [Literal (Just (Unsigned _,_)) i]) = Literal Nothing i -- SNat+ mkLit (DataCon _ (DC (Void {}, _)) [Literal (Just (Signed _,_)) i]) = Literal Nothing i -- Int+ mkLit (DataCon _ (DC (Void {}, _)) [Literal (Just (Unsigned _,_)) i]) = Literal Nothing i -- SNat, Word - mkLit (BlackBoxE pNm _ _ _ _ bbCtx _) | pNm `elem` ["GHC.Types.I#","GHC.Int.I8#", "GHC.Int.I16#", "GHC.Int.I32#", "GHC.Int.I64#"- ,"GHC.Types.W#","GHC.Word.W8#","GHC.Word.W16#","GHC.Word.W32#","GHC.Word.W64#"+ mkLit (BlackBoxE pNm _ _ _ _ bbCtx _) | pNm `elem` ["GHC.Int.I8#", "GHC.Int.I16#", "GHC.Int.I32#", "GHC.Int.I64#"+ ,"GHC.Word.W8#","GHC.Word.W16#","GHC.Word.W32#","GHC.Word.W64#" ] , [Literal _ i] <- extractLiterals bbCtx = Literal Nothing i@@ -638,33 +653,35 @@ renderTag b (BV True es e) = do e' <- Text.concat <$> mapM (fmap ($ 0) . renderElem b) es let ty = lineToType b [e]- renderOneLine <$> getMon (toBV ty e')+ renderOneLine <$> getAp (toBV ty e') renderTag b (BV False es e) = do e' <- Text.concat <$> (mapM (fmap ($ 0) . renderElem b) es) let ty = lineToType b [e]- renderOneLine <$> getMon (fromBV ty e')+ renderOneLine <$> getAp (fromBV ty e') renderTag b (Sel e n) = let ty = lineToType b [e]- in renderOneLine <$> getMon (hdlRecSel ty n)+ in renderOneLine <$> getAp (hdlRecSel ty n) -renderTag b (Typ Nothing) = fmap renderOneLine . getMon . hdlType Internal . snd $ bbResult "~TYPO" b+renderTag b (Typ Nothing) = fmap renderOneLine . getAp . hdlType Internal . snd $ bbResult "~TYPO" b renderTag b (Typ (Just n)) = let (_,ty,_) = bbInputs b !! n- in renderOneLine <$> getMon (hdlType Internal ty)-renderTag b (TypM Nothing) = fmap renderOneLine . getMon . hdlTypeMark . snd $ bbResult "~TYPMO" b+ in renderOneLine <$> getAp (hdlType Internal ty)+renderTag b (TypM Nothing) = fmap renderOneLine . getAp . hdlTypeMark . snd $ bbResult "~TYPMO" b renderTag b (TypM (Just n)) = let (_,ty,_) = bbInputs b !! n- in renderOneLine <$> getMon (hdlTypeMark ty)-renderTag b (Err Nothing) = fmap renderOneLine . getMon . hdlTypeErrValue . snd $ bbResult "~ERRORO" b+ in renderOneLine <$> getAp (hdlTypeMark ty)+renderTag b (Err Nothing) = fmap renderOneLine . getAp . hdlTypeErrValue . snd $ bbResult "~ERRORO" b renderTag b (Err (Just n)) = let (_,ty,_) = bbInputs b !! n- in renderOneLine <$> getMon (hdlTypeErrValue ty)+ in renderOneLine <$> getAp (hdlTypeErrValue ty) renderTag b (Size e) = return . Text.pack . show . typeSize $ lineToType b [e] renderTag b (Length e) = return . Text.pack . show . vecLen $ lineToType b [e] where- vecLen (Vector n _) = n- vecLen (Void (Just (Vector n _))) = n+ vecLen (Vector n _) = n+ vecLen (Void (Just (Vector n _))) = n+ vecLen (MemBlob n _) = n+ vecLen (Void (Just (MemBlob n _))) = n vecLen thing =- error $ $(curLoc) ++ "vecLen of a non-vector type: " ++ show thing+ error $ $(curLoc) ++ "vecLen of a non-vector-like type: " ++ show thing renderTag b (Depth e) = return . Text.pack . show . treeDepth $ lineToType b [e] where@@ -675,12 +692,13 @@ renderTag b (MaxIndex e) = return . Text.pack . show . vecLen $ lineToType b [e] where- vecLen (Vector n _) = n-1+ vecLen (Vector n _) = n-1+ vecLen (MemBlob n _) = n-1 vecLen thing =- error $ $(curLoc) ++ "vecLen of a non-vector type: " ++ show thing+ error $ $(curLoc) ++ "vecLen of a non-vector-like type: " ++ show thing renderTag b e@(TypElem _) = let ty = lineToType b [e]- in renderOneLine <$> getMon (hdlType Internal ty)+ in renderOneLine <$> getAp (hdlType Internal ty) renderTag _ (Gen b) = renderOneLine <$> genStmt b renderTag _ (GenSym [Text t] _) = return t @@ -695,7 +713,7 @@ case bbInputs b !! n of (Literal _ (NumLit n'),_,_) -> let hty = Index (fromInteger n')- in fmap renderOneLine (getMon (hdlType Internal hty))+ in fmap renderOneLine (getAp (hdlType Internal hty)) x -> error $ $(curLoc) ++ "Index type not given a literal: " ++ show x renderTag b (FilePath e) = case e of Lit n -> do@@ -705,9 +723,9 @@ s' <- addAndSetData s return (Text.pack (show s')) _ -> do- e2 <- getMon (prettyElem e)+ e2 <- getAp (prettyElem e) error $ $(curLoc) ++ "argument of ~FILEPATH:" ++ show e2 ++ "does not reduce to a string"- _ -> do e' <- getMon (prettyElem e)+ _ -> do e' <- getAp (prettyElem e) error $ $(curLoc) ++ "~FILEPATH expects a ~LIT[N] argument, but got: " ++ show e' renderTag b (IncludeName n) = case indexMaybe (bbQsysIncName b) n of Just nm -> return (Text.fromStrict nm)@@ -763,7 +781,7 @@ _ -> error "internal error" -renderTag _ e = do e' <- getMon (prettyElem e)+renderTag _ e = do e' <- getAp (prettyElem e) error $ $(curLoc) ++ "Unable to evaluate: " ++ show e' -- | Compute string from a list of elements. Can interpret ~NAME string literals@@ -820,13 +838,13 @@ prettyBlackBox :: Monad m => BlackBoxTemplate- -> Mon m Text+ -> Ap m Text prettyBlackBox bbT = Text.concat <$> mapM prettyElem bbT prettyElem :: (HasCallStack, Monad m) => Element- -> Mon m Text+ -> Ap m Text prettyElem (Text t) = return t prettyElem (Component (Decl i 0 args)) = do args' <- mapM (\(a,b) -> (,) <$> prettyBlackBox a <*> prettyBlackBox b) args@@ -920,6 +938,7 @@ -- Domain attributes: prettyElem (Tag i) = renderOneLine <$> (string "~TAG" <> brackets (int i)) prettyElem (Period i) = renderOneLine <$> (string "~PERIOD" <> brackets (int i))+prettyElem LongestPeriod = return "~LONGESTPERIOD" prettyElem (ActiveEdge e i) = renderOneLine <$> (string "~ACTIVEEDGE" <> brackets (string (Text.pack (show e))) <> brackets (int i)) prettyElem (IsSync i) = renderOneLine <$> (string "~ISSYNC" <> brackets (int i)) prettyElem (IsInitDefined i) = renderOneLine <$> (string "~ISINITDEFINED" <> brackets (int i))@@ -1020,6 +1039,7 @@ IsVar _ -> [] Tag _ -> [] Period _ -> []+ LongestPeriod -> [] ActiveEdge _ _ -> [] IsSync _ -> [] IsInitDefined _ -> []@@ -1079,6 +1099,7 @@ ActiveEdge _ _ -> Nothing IsSync _ -> Nothing Period _ -> Nothing+ LongestPeriod -> Nothing Tag _ -> Nothing -- Others. Template tags only using types of arguments can be considered
src/Clash/Netlist/Id.hs view
@@ -7,13 +7,9 @@ -} {-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE MultiWayIf #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE QuasiQuotes #-} module Clash.Netlist.Id ( -- * Utilities to use IdentifierSet
src/Clash/Netlist/Id/Common.hs view
@@ -1,5 +1,5 @@ {-|- Copyright : (C) 2020, QBayLogic B.V.+ Copyright : (C) 2020-2021, QBayLogic B.V. License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com -}@@ -9,12 +9,11 @@ import Control.Arrow (first) import Control.Applicative ((<|>))-import Control.Applicative.Extra (orEmpty) import Data.Maybe (fromMaybe) import Data.Text (Text)+import Data.Text.Extra (showt) import qualified Data.Text as Text import qualified Data.Char as Char-import TextShow (showt) parseWhiteSpace :: Text -> Maybe Text parseWhiteSpace = parseSingle isWhiteSpace@@ -28,7 +27,7 @@ parseSingle :: (Char -> Bool) -> Text -> Maybe Text parseSingle predicate s = do (l, ls) <- Text.uncons s- orEmpty (predicate l) ls+ if predicate l then Just ls else Nothing parseMaybeSingle :: (Char -> Bool) -> Text -> Maybe Text parseMaybeSingle predicate s = Just (fromMaybe s (parseSingle predicate s))
src/Clash/Netlist/Id/Internal.hs view
@@ -26,9 +26,9 @@ import qualified Data.Text as Text import Data.Text (Text)+import Data.Text.Extra (showt) import qualified Data.Maybe as Maybe import Text.Read (readMaybe)-import TextShow (showt) import GHC.Stack import qualified Data.IntMap as IntMap
src/Clash/Netlist/Types.hs view
@@ -2,7 +2,7 @@ Copyright : (C) 2012-2016, University of Twente, 2017 , Myrtle Software Ltd, 2017-2018, Google Inc.- 2020 , QBayLogic+ 2020-2021, QBayLogic B.V. License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> @@ -21,13 +21,7 @@ {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TypeSynonymInstances #-} --- since GHC 8.6 we can haddock individual constructor fields \o/-#if __GLASGOW_HASKELL__ >= 806-#define FIELD ^-#endif- module Clash.Netlist.Types ( Declaration (..,NetDecl) , module Clash.Netlist.Types@@ -55,12 +49,12 @@ import Data.Map.Ordered (OMap) import Data.Map (Map) import Data.Maybe (mapMaybe)+import Data.Monoid (Ap(..)) import qualified Data.Set as Set import Data.Text (Text) import Data.Typeable (Typeable) import Data.Text.Prettyprint.Doc.Extra (Doc)-import Data.Semigroup.Monad (Mon(..)) import GHC.Generics (Generic) import GHC.Stack import Language.Haskell.TH.Syntax (Lift)@@ -75,8 +69,9 @@ import Clash.Annotations.Primitive (HDL(..)) import Clash.Annotations.TopEntity (TopEntity) import Clash.Backend (Backend)+import Clash.Core.HasType import Clash.Core.Type (Type)-import Clash.Core.Var (Attr', Id, varType)+import Clash.Core.Var (Attr', Id) import Clash.Core.TyCon (TyConMap) import Clash.Core.VarEnv (VarEnv) import Clash.Driver.Types (BindingMap, ClashOpts)@@ -85,7 +80,6 @@ import Clash.Signal.Internal (ResetPolarity, ActiveEdge, ResetKind, InitBehavior) import Clash.Unique (Unique)-import Clash.Util (makeLenses) import Clash.Annotations.BitRepresentation.Internal (CustomReprs, DataRepr', ConstrRepr')@@ -119,11 +113,11 @@ -- | Same as "PortProduct", but fully expanded | ExpandedPortProduct Text- -- FIELD Name hint. Can be used to create intermediate signal names.+ -- ^ Name hint. Can be used to create intermediate signal names. HWType- -- FIELD Type of product+ -- ^ Type of product [ExpandedPortName a]- -- FIELD Product fields+ -- ^ Product fields deriving (Show, Functor, Foldable, Traversable) -- | Monad that caches generated components (StateT) and remembers hidden inputs@@ -215,9 +209,9 @@ -- appear in the HDL exactly as the user specified. = RawIdentifier !Text- -- FIELD An identifier exactly as given by the user+ -- ^ An identifier exactly as given by the user (Maybe Identifier)- -- FIELD Parsed version of raw identifier. Will not be populated if this+ -- ^ Parsed version of raw identifier. Will not be populated if this -- identifier was created with an unsafe function. !CallStack -- ^ Stores where this identifier was generated. Tracking is only enabled@@ -366,7 +360,13 @@ SomeBackend :: Backend backend => backend -> SomeBackend type Comment = Text+type Directive = Text +data CommentOrDirective+ = Comment Comment+ | Directive Directive+ deriving Show+ -- | Component: base unit of a Netlist data Component = Component@@ -375,12 +375,13 @@ , outputs :: [(WireOrReg,(Identifier,HWType),Maybe Expr)] -- ^ Output ports , declarations :: [Declaration] -- ^ Internal declarations }- deriving Show+ deriving (Show, Generic, NFData) -instance NFData Component where- rnf c = case c of- Component nm inps outps decls -> rnf nm `seq` rnf inps `seq`- rnf outps `seq` rnf decls+-- | Check if an input port is really an inout port.+--+isBiDirectional :: (Identifier, HWType) -> Bool+isBiDirectional (_, BiDirectional _ _) = True+isBiDirectional _ = False -- | Find the name and domain name of each clock argument of a component. --@@ -430,6 +431,8 @@ -- ^ Unsigned integer of a specified size | Vector !Size !HWType -- ^ Vector type+ | MemBlob !Size !Size+ -- ^ MemBlob type | RTree !Size !HWType -- ^ RTree type | Sum !Text [Text]@@ -506,71 +509,80 @@ data Declaration -- | Signal assignment = Assignment- !Identifier -- FIELD Signal to assign- !Expr -- FIELD Assigned expression+ !Identifier -- ^ Signal to assign+ !Expr -- ^ Assigned expression -- | Conditional signal assignment: | CondAssignment- !Identifier -- FIELD Signal to assign- !HWType -- FIELD Type of the result/alternatives- !Expr -- FIELD Scrutinized expression- !HWType -- FIELD Type of the scrutinee- [(Maybe Literal,Expr)] -- FIELD List of: (Maybe expression scrutinized expression is compared with,RHS of alternative)+ !Identifier -- ^ Signal to assign+ !HWType -- ^ Type of the result/alternatives+ !Expr -- ^ Scrutinized expression+ !HWType -- ^ Type of the scrutinee+ [(Maybe Literal,Expr)] -- ^ List of: (Maybe expression scrutinized expression is compared with,RHS of alternative) -- | Instantiation of another component: | InstDecl- EntityOrComponent -- FIELD Whether it's an entity or a component- (Maybe Text) -- FIELD Library instance is defined in- [Attr'] -- FIELD Attributes to add to the generated code- !Identifier -- FIELD The component's (or entity's) name- !Identifier -- FIELD Instance label- [(Expr,HWType,Expr)] -- FIELD List of parameters for this component (param name, param type, param value)+ EntityOrComponent -- ^ Whether it's an entity or a component+ (Maybe Text) -- ^ Library instance is defined in+ [Attr'] -- ^ Attributes to add to the generated code+ !Identifier -- ^ The component's (or entity's) name+ !Identifier -- ^ Instance label+ [(Expr,HWType,Expr)] -- ^ List of parameters for this component (param name, param type, param value) PortMap -- | Instantiation of blackbox declaration | BlackBoxD- !Text -- FIELD Primitive name- [BlackBoxTemplate] -- FIELD VHDL only: add @library@ declarations- [BlackBoxTemplate] -- FIELD VHDL only: add @use@ declarations- [((Text,Text),BlackBox)] -- FIELD Intel Quartus only: create a @.qsys@ file from given template- !BlackBox -- FIELD Template tokens- BlackBoxContext -- FIELD Context in which tokens should be rendered+ !Text -- ^ Primitive name+ [BlackBoxTemplate] -- ^ VHDL only: add @library@ declarations+ [BlackBoxTemplate] -- ^ VHDL only: add @use@ declarations+ [((Text,Text),BlackBox)] -- ^ Intel Quartus only: create a @.qsys@ file from given template+ !BlackBox -- ^ Template tokens+ BlackBoxContext -- ^ Context in which tokens should be rendered -- | Signal declaration | NetDecl'- (Maybe Comment) -- FIELD Note; will be inserted as a comment in target hdl- WireOrReg -- FIELD Wire or register- !Identifier -- FIELD Name of signal- (Either IdentifierText HWType) -- FIELD Pointer to type of signal or type of signal- (Maybe Expr) -- FIELD Initial value+ (Maybe Comment) -- ^ Note; will be inserted as a comment in target hdl+ WireOrReg -- ^ Wire or register+ !Identifier -- ^ Name of signal+ (Either IdentifierText HWType) -- ^ Pointer to type of signal or type of signal+ (Maybe Expr) -- ^ Initial value -- ^ Signal declaration- | TickDecl Comment- -- ^ HDL tick corresponding to a Core tick++ -- | HDL tick corresponding to a Core tick+ | TickDecl CommentOrDirective+ -- | Sequential statement | Seq [Seq]++ -- | Compilation conditional on some preprocessor symbol, note that+ -- declarations here are ignored for VHDL. See here for a discussion+ -- https://github.com/clash-lang/clash-compiler/pull/1798#discussion_r648571862+ | ConditionalDecl+ !Text -- ^ condition text, for example @FORMAL@+ [Declaration] deriving Show -- | Sequential statements data Seq -- | Clocked sequential statements = AlwaysClocked- ActiveEdge -- FIELD Edge of the clock the statement should be executed- Expr -- FIELD Clock expression- [Seq] -- FIELD Statements to be executed on the active clock edge+ ActiveEdge -- ^ Edge of the clock the statement should be executed+ Expr -- ^ Clock expression+ [Seq] -- ^ Statements to be executed on the active clock edge -- | Statements running at simulator start | Initial- [Seq] -- FIELD Statements to run at simulator start+ [Seq] -- ^ Statements to run at simulator start -- | Statements to run always | AlwaysComb- [Seq] -- FIELD Statements to run always+ [Seq] -- ^ Statements to run always -- | Declaration in sequential form | SeqDecl- Declaration -- FIELD The declaration+ Declaration -- ^ The declaration -- | Branching statement | Branch- !Expr -- FIELD Scrutinized expresson- !HWType -- FIELD Type of the scrutinized expression- [(Maybe Literal,[Seq])] -- FIELD List of: (Maybe match, RHS of Alternative)+ !Expr -- ^ Scrutinized expresson+ !HWType -- ^ Type of the scrutinized expression+ [(Maybe Literal,[Seq])] -- ^ List of: (Maybe match, RHS of Alternative) deriving Show data EntityOrComponent = Entity | Comp | Empty@@ -618,25 +630,25 @@ -- | Instantiation of a BlackBox expression | BlackBoxE- !Text -- FIELD Primitive name- [BlackBoxTemplate] -- FIELD VHDL only: add @library@ declarations- [BlackBoxTemplate] -- FIELD VHDL only: add @use@ declarations:- [((Text,Text),BlackBox)] -- FIELD Intel/Quartus only: create a @.qsys@ file from given template.- !BlackBox -- FIELD Template tokens- !BlackBoxContext -- FIELD Context in which tokens should be rendered- !Bool -- FIELD Wrap in parentheses?+ !Text -- ^ Primitive name+ [BlackBoxTemplate] -- ^ VHDL only: add @library@ declarations+ [BlackBoxTemplate] -- ^ VHDL only: add @use@ declarations:+ [((Text,Text),BlackBox)] -- ^ Intel/Quartus only: create a @.qsys@ file from given template.+ !BlackBox -- ^ Template tokens+ !BlackBoxContext -- ^ Context in which tokens should be rendered+ !Bool -- ^ Wrap in parentheses? -- | Convert some type to a BitVector. | ToBv- (Maybe Identifier) -- FIELD Type prefix- HWType -- FIELD Type to convert _from_- Expr -- FIELD Expression to convert to BitVector+ (Maybe Identifier) -- ^ Type prefix+ HWType -- ^ Type to convert _from_+ Expr -- ^ Expression to convert to BitVector -- | Convert BitVector to some type. | FromBv- (Maybe Identifier) -- FIELD Type prefix- HWType -- FIELD Type to convert _to_- Expr -- FIELD BitVector to convert+ (Maybe Identifier) -- ^ Type prefix+ HWType -- ^ Type to convert _to_+ Expr -- ^ BitVector to convert | IfThenElse Expr Expr Expr -- | Do nothing@@ -719,12 +731,12 @@ data TemplateFunction where TemplateFunction :: [Int]- -- FIELD Used arguments+ -- ^ Used arguments -> (BlackBoxContext -> Bool)- -- FIELD Validation function. Should return 'False' if function can't render+ -- ^ Validation function. Should return 'False' if function can't render -- given a certain context. -> (forall s . Backend s => BlackBoxContext -> Lazy.State s Doc)- -- FIELD Render function+ -- ^ Render function -> TemplateFunction instance Show BlackBox where@@ -753,19 +765,6 @@ -- expressions of types that have to be split apart (e.g. tuples of Files) deriving Show --- | Eliminator for 'NetlistId'-netlistId- :: (Identifier -> r)- -- ^ Eliminator for Identifiers generated in the NetlistMonad- -> (Id -> r)- -- ^ Eliminator for original Core Identifiers- -> NetlistId- -> [r]-netlistId f g = \case- NetlistId i _ -> [f i]- CoreId i -> [g i]- MultiId is -> map g is- -- | Eliminator for 'NetlistId', fails on 'MultiId' netlistId1 :: HasCallStack@@ -787,8 +786,8 @@ -> [Type] netlistTypes = \case NetlistId _ t -> [t]- CoreId i -> [varType i]- MultiId is -> map varType is+ CoreId i -> [coreTypeOf i]+ MultiId is -> map coreTypeOf is -- | Return the type of a 'NetlistId', fails on 'MultiId' netlistTypes1@@ -797,7 +796,7 @@ -> Type netlistTypes1 = \case NetlistId _ t -> t- CoreId i -> varType i+ CoreId i -> coreTypeOf i m -> error ("netlistTypes1 MultiId: " ++ show m) -- | Type of declaration, concurrent or sequential@@ -820,8 +819,8 @@ , bbCtxName = Nothing } -makeLenses ''NetlistEnv-makeLenses ''NetlistState+Lens.makeLenses ''NetlistEnv+Lens.makeLenses ''NetlistState -- | Structures that hold an 'IdentifierSet' class HasIdentifierSet s where@@ -856,5 +855,5 @@ Lens.use identifierSet {-# INLINE identifierSetM #-} -instance IdentifierSetMonad m => IdentifierSetMonad (Mon m) where- identifierSetM = Mon . identifierSetM+instance IdentifierSetMonad m => IdentifierSetMonad (Ap m) where+ identifierSetM = Ap . identifierSetM
src/Clash/Netlist/Types.hs-boot view
@@ -1,13 +1,15 @@ {-|- Copyright : (C) 2018, Google Inc+ Copyright : (C) 2018, Google Inc,+ 2022, QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> -} {-# LANGUAGE RoleAnnotations #-} module Clash.Netlist.Types where +import Control.DeepSeq (NFData) import Control.Lens (Lens') import Data.Hashable @@ -19,7 +21,10 @@ data Component data Expr data BlackBox+data TopEntityT +instance NFData BlackBox+ class Monad m => IdentifierSetMonad m where identifierSetM :: (IdentifierSet -> IdentifierSet) -> m IdentifierSet @@ -32,3 +37,4 @@ instance Hashable PreserveCase instance Eq PreserveCase instance Show PreserveCase+instance NFData PreserveCase
src/Clash/Netlist/Util.hs view
@@ -2,8 +2,9 @@ Copyright : (C) 2012-2016, University of Twente, 2017 , Myrtle Software Ltd 2017-2018, Google Inc.+ 2021 , QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Utilities for converting Core Type/Term to Netlist datatypes -}@@ -24,7 +25,6 @@ module Clash.Netlist.Util where import Data.Coerce (coerce)-import Control.Error (hush) import Control.Exception (throw) import Control.Lens ((.=)) import qualified Control.Lens as Lens@@ -36,6 +36,7 @@ (State, evalState, get, modify, runState) import Control.Monad.Trans.Except (ExceptT (..), runExcept, runExceptT, throwE)+import Data.Bifunctor (second) import Data.Either (partitionEithers) import Data.Foldable (Foldable(toList)) import Data.Hashable (Hashable)@@ -50,14 +51,12 @@ import Data.Maybe (catMaybes, fromMaybe, isNothing, mapMaybe, isJust, listToMaybe, maybeToList) import Text.Printf (printf)-#if !(MIN_VERSION_base(4,11,0))-import Data.Semigroup ((<>))-#endif import Data.Text (Text) import qualified Data.Text as Text+import Data.Text.Extra (showt) import Data.Text.Lazy (toStrict) import Data.Text.Prettyprint.Doc.Extra-import TextShow (showt)+import GHC.Stack (HasCallStack) #if MIN_VERSION_ghc(9,0,0) import GHC.Utils.Monad (zipWith3M)@@ -77,7 +76,9 @@ import Clash.Backend (HWKind(..), hdlHWTypeKind) import Clash.Core.DataCon (DataCon (..)) import Clash.Core.EqSolver (typeEq)-import Clash.Core.FreeVars (localIdOccursIn, typeFreeVars, typeFreeVars')+import Clash.Core.FreeVars (typeFreeVars, typeFreeVars')+import Clash.Core.HasFreeVars (elemFreeVars)+import Clash.Core.HasType import qualified Clash.Core.Literal as C import Clash.Core.Name (Name (..), appendToName, nameOcc)@@ -161,6 +162,11 @@ isFilteredVoid :: FilteredHWType -> Bool isFilteredVoid = isVoid . stripFiltered +squashLets :: Term -> Term+squashLets (Letrec xs (Letrec ys e)) =+ squashLets (Letrec (xs <> ys) e)+squashLets e = e+ -- | Split a normalized term into: a list of arguments, a list of let-bindings, -- and a variable reference that is the body of the let-binding. Returns a -- String containing the error if the term was not in a normalized form.@@ -169,30 +175,16 @@ -> Term -> (Either String ([Id],[LetBinding],Id)) splitNormalized tcm expr = case collectBndrs expr of- (args, collectTicks -> (Letrec xes e, ticks))+ (args, collectTicks -> (squashLets -> Letrec xes e, ticks)) | (tmArgs,[]) <- partitionEithers args -> case stripTicks e of Var v -> Right (tmArgs, fmap (second (`mkTicks` ticks)) xes,v)- _ -> Left ($(curLoc) ++ "Not in normal form: res not simple var")+ t -> Left ($(curLoc) ++ "Not in normal form: res not simple var: " ++ showPpr t) | otherwise -> Left ($(curLoc) ++ "Not in normal form: tyArgs") _ -> Left ($(curLoc) ++ "Not in normal form: no Letrec:\n\n" ++ showPpr expr ++ "\n\nWhich has type:\n\n" ++ showPpr ty) where- ty = termType tcm expr---- | Same as @unsafeCoreTypeToHWType@, but discards void filter information-unsafeCoreTypeToHWType'- :: SrcSpan- -- ^ Approximate location in original source file- -> String- -> (CustomReprs -> TyConMap -> Type ->- State HWMap (Maybe (Either String FilteredHWType)))- -> CustomReprs- -> TyConMap- -> Type- -> State HWMap HWType-unsafeCoreTypeToHWType' sp loc builtInTranslation reprs m ty =- stripFiltered <$> (unsafeCoreTypeToHWType sp loc builtInTranslation reprs m ty)+ ty = inferCoreTypeOf tcm expr -- | Converts a Core type to a HWType given a function that translates certain -- builtin types. Errors if the Core type is not translatable.@@ -254,7 +246,7 @@ htm0 <- Lens.use htyCache let (hty,htm1) = runState (coreTypeToHWType tt reprs tcm ty) htm0 htyCache Lens..= htm1- return (hush hty)+ return (either (const Nothing) Just hty) -- | Constructs error message for unexpected projections out of a type annotated -- with a custom bit representation.@@ -691,6 +683,7 @@ typeSize (Signed i) = i typeSize (Unsigned i) = i typeSize (Vector n el) = n * typeSize el+typeSize (MemBlob n m) = n * m typeSize (RTree d el) = (2^d) * typeSize el typeSize t@(SP _ cons) = conSize t + maximum (map (sum . map typeSize . snd) cons)@@ -709,12 +702,6 @@ conSize (SP _ cons) = fromMaybe 0 . clogBase 2 . toInteger $ length cons conSize t = typeSize t --- | Gives the length of length-indexed types-typeLength :: HWType- -> Int-typeLength (Vector n _) = n-typeLength _ = 0- -- | Gives the HWType corresponding to a term. Returns an error if the term has -- a Core type that is not translatable to a HWType. termHWType :: String@@ -722,7 +709,7 @@ -> NetlistMonad HWType termHWType loc e = do m <- Lens.use tcCache- let ty = termType m e+ let ty = inferCoreTypeOf m e stripFiltered <$> unsafeCoreTypeToHWTypeM loc ty -- | Gives the HWType corresponding to a term. Returns 'Nothing' if the term has@@ -733,7 +720,7 @@ -> NetlistMonad (Maybe FilteredHWType) termHWTypeM e = do m <- Lens.use tcCache- let ty = termType m e+ let ty = inferCoreTypeOf m e coreTypeToHWTypeM ty isBiSignalIn :: HWType -> Bool@@ -779,8 +766,8 @@ ,Maybe Id) mkUniqueNormalized is0 topMM (args, binds, res) = do -- Generate port names and add them to set of seen identifiers- argHwtys <- mapM (unsafeCoreTypeToHWTypeM $(curLoc) . varType) args- resHwty <- unsafeCoreTypeToHWTypeM $(curLoc) (varType res)+ argHwtys <- mapM (unsafeCoreTypeToHWTypeM $(curLoc) . coreTypeOf) args+ resHwty <- unsafeCoreTypeToHWTypeM $(curLoc) (coreTypeOf res) etopM <- mapM (expandTopEntityOrErrM (zip (map Just args) argHwtys) (Just res, resHwty))@@ -808,7 +795,7 @@ -- we need to add a redirection as most synthesis tools don't allow reads -- from output ports. Note that if the result is renamed anyway, we don't -- have to do anything here.- resultRead = any (localIdOccursIn res) exprs+ resultRead = any (elemFreeVars res) exprs recResult = modifyVarName (`appendToName` "_rec") res resRenameM1 = resRenameM0 <|> orNothing resultRead (res, recResult) @@ -878,7 +865,7 @@ -- Routine for single result primitives (the default kind of primitive) goSingle :: PrimInfo -> CompiledPrimitive -> NetlistMonad [(Id, Id)] goSingle pInfo (BlackBoxHaskell{function=(_, function)}) = do- funRes <- preserveVarEnv (function False (primName pInfo) args [varType i])+ funRes <- preserveVarEnv (function False (primName pInfo) args [coreTypeOf i]) case either error fst funRes of BlackBoxMeta{bbResultNames=[bbResultName]} -> go (primName pInfo) [i] args [bbResultName]@@ -946,7 +933,7 @@ go (Just port) var = do (ports, decls, _, portI) <- mkTopInput port let portName = Id.toText portI- pId = mkLocalId (varType var) (setRepName portName (varName var))+ pId = mkLocalId (coreTypeOf var) (setRepName portName (varName var)) return (Just (ports, decls, (pId, (var, Var pId)))) @@ -970,12 +957,12 @@ pure Nothing mkUniqueResult subst0 (Just (ExpandedTopEntity{et_output=Just iPort})) res = do (_, sp) <- Lens.use curCompNm- (FilteredHWType hwty _) <- unsafeCoreTypeToHWTypeM $(curLoc) (varType res)+ (FilteredHWType hwty _) <- unsafeCoreTypeToHWTypeM $(curLoc) (coreTypeOf res) when (containsBiSignalIn hwty) (throw (ClashException sp ($(curLoc) ++ "BiSignalIn cannot be part of a function's result. Use 'readFromBiSignal'.") Nothing)) (ports, decls, portI) <- mkTopOutput iPort let pO = setRepName (Id.toText portI) (varName res)- pOId = mkLocalId (varType res) pO+ pOId = mkLocalId (coreTypeOf res) pO subst1 = extendInScopeId (extendIdSubst subst0 res (Var pOId)) pOId return (Just (ports, decls, pOId, subst1)) @@ -1007,14 +994,11 @@ idToPort :: Id -> NetlistMonad (Maybe (Identifier, HWType)) idToPort var = do- hwTy <- unsafeCoreTypeToHWTypeM' $(curLoc) (varType var)+ hwTy <- unsafeCoreTypeToHWTypeM' $(curLoc) (coreTypeOf var) if isVoid hwTy then return Nothing else return (Just (id2identifier var, hwTy)) -id2type :: Id -> Type-id2type = varType- id2identifier :: Id -> Identifier id2identifier = Id.unsafeMake . nameOcc . varName @@ -1622,7 +1606,7 @@ -> Bool bindsExistentials exts tms = any (`elem` freeVars) exts where- freeVars = concatMap (Lens.toListOf typeFreeVars) (map varType tms)+ freeVars = concatMap (Lens.toListOf typeFreeVars) (map coreTypeOf tms) iteAlts :: HWType -> [Alt] -> Maybe (Term,Term) iteAlts sHTy [(pat0,alt0),(pat1,alt1)] | validIteSTy sHTy = case pat0 of@@ -1672,7 +1656,7 @@ go decls (NoDeDup:ticks) = go decls ticks go decls (SrcSpan sp:ticks) =- go (TickDecl (Text.pack (showSDocUnsafe (ppr sp))):decls) ticks+ go (TickDecl (Comment (Text.pack (showSDocUnsafe (ppr sp)))):decls) ticks go decls (NameMod m nm0:ticks) = do tcm <- Lens.use tcCache
src/Clash/Normalize.hs view
@@ -1,9 +1,10 @@ {-| Copyright : (C) 2012-2016, University of Twente, 2016 , Myrtle Software Ltd,- 2017 , Google Inc.+ 2017 , Google Inc.,+ 2021-2022, QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Turn CoreHW terms into normalized CoreHW Terms -}@@ -23,7 +24,6 @@ import Data.Default (def) import Data.Either (lefts,partitionEithers) import qualified Data.IntMap as IntMap-import Data.IntMap.Strict (IntMap) import Data.List (intersect, mapAccumL) import qualified Data.Map as Map@@ -45,23 +45,19 @@ import Clash.Annotations.BitRepresentation.Internal (CustomReprs)--#if EXPERIMENTAL_EVALUATOR-import Clash.Core.PartialEval (Evaluator)-#else-import Clash.Core.Evaluator.Types (Evaluator)-#endif-+import Clash.Core.Evaluator.Types as WHNF (Evaluator) import Clash.Core.FreeVars- (freeLocalIds, globalIds, globalIdOccursIn, localIdDoesNotOccurIn)+ (freeLocalIds, globalIds)+import Clash.Core.HasFreeVars (notElemFreeVars)+import Clash.Core.HasType+import Clash.Core.PartialEval as PE (Evaluator) import Clash.Core.Pretty (PrettyOptions(..), showPpr, showPpr', ppr) import Clash.Core.Subst (extendGblSubstList, mkSubst, substTm) import Clash.Core.Term (Term (..), collectArgsTicks ,mkApps, mkTicks) import Clash.Core.Type (Type, splitCoreFunForallTy)-import Clash.Core.TyCon- (TyConMap, TyConName)+import Clash.Core.TyCon (TyConMap) import Clash.Core.Type (isPolyTy) import Clash.Core.Var (Id, varName, varType) import Clash.Core.VarEnv@@ -70,7 +66,7 @@ mkVarEnv, mkVarSet, notElemVarEnv, notElemVarSet, nullVarEnv, unionVarEnv) import Clash.Debug (traceIf) import Clash.Driver.Types- (BindingMap, Binding(..), ClashOpts (..), DebugLevel (..))+ (BindingMap, Binding(..), DebugOpts(..), ClashEnv(..)) import Clash.Netlist.Types (HWMap, FilteredHWType(..)) import Clash.Netlist.Util@@ -79,11 +75,10 @@ import Clash.Normalize.Transformations import Clash.Normalize.Types import Clash.Normalize.Util-import Clash.Primitives.Types (CompiledPrimMap) import Clash.Rewrite.Combinators ((>->),(!->),repeatR,topdownR) import Clash.Rewrite.Types- (RewriteEnv (..), RewriteState (..), bindings, dbgLevel, dbgRewriteHistoryFile, extra,- tcCache, topEntities)+ (RewriteEnv (..), RewriteState (..), bindings, debugOpts, extra,+ tcCache, topEntities, newInlineStrategy) import Clash.Rewrite.Util (apply, isUntranslatableType, runRewriteSession) import Clash.Util@@ -99,8 +94,7 @@ -- | Run a NormalizeSession in a given environment runNormalization- :: ClashOpts- -- ^ Level of debug messages to print+ :: ClashEnv -> Supply -- ^ UniqueSupply -> BindingMap@@ -108,52 +102,36 @@ -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -- ^ Hardcoded Type -> HWType translator- -> CustomReprs- -> TyConMap- -- ^ TyCon cache- -> IntMap TyConName- -- ^ Tuple TyCon cache- -> Evaluator+ -> PE.Evaluator -- ^ Hardcoded evaluator for partial evaluation- -> CompiledPrimMap- -- ^ Primitive Definitions+ -> WHNF.Evaluator+ -- ^ Hardcoded evaluator for WHNF (old evaluator) -> VarEnv Bool -- ^ Map telling whether a components is part of a recursive group -> [Id] -- ^ topEntities -> NormalizeSession a -- ^ NormalizeSession to run- -> a-runNormalization opts supply globals typeTrans reprs tcm tupTcm eval primMap rcsMap topEnts- = runRewriteSession rwEnv rwState+ -> IO a+runNormalization env supply globals typeTrans peEval eval rcsMap topEnts =+ runRewriteSession rwEnv rwState where+ -- TODO The RewriteEnv should just take ClashOpts. rwEnv = RewriteEnv- (opt_dbgLevel opts)- (opt_dbgTransformations opts)- (opt_dbgTransformationsFrom opts)- (opt_dbgTransformationsLimit opts)- (opt_dbgRewriteHistoryFile opts)- (opt_aggressiveXOpt opts)+ env typeTrans- tcm- tupTcm+ peEval eval (mkVarSet topEnts)- reprs- (opt_evaluatorFuelLimit opts) rwState = RewriteState 0+ mempty -- transformCounters Map globals supply (error $ $(curLoc) ++ "Report as bug: no curFun",noSrcSpan) 0-#if EXPERIMENTAL_EVALUATOR- IntMap.empty- 0-#else (IntMap.empty, 0)-#endif emptyVarEnv normState @@ -161,19 +139,10 @@ emptyVarEnv Map.empty emptyVarEnv- (opt_specLimit opts) emptyVarEnv- (opt_inlineLimit opts)- (opt_inlineFunctionLimit opts)- (opt_inlineConstantLimit opts)- primMap Map.empty rcsMap- (opt_newInlineStrat opts)- (opt_ultra opts)- (opt_inlineWFCacheLimit opts) - normalize :: [Id] -> NormalizeSession BindingMap@@ -188,11 +157,11 @@ exprM <- lookupVarEnv nm <$> Lens.use bindings let nmS = showPpr (varName nm) case exprM of- Just (Binding nm' sp inl pr tm) -> do+ Just (Binding nm' sp inl pr tm r) -> do tcm <- Lens.view tcCache topEnts <- Lens.view topEntities let isTop = nm `elemVarSet` topEnts- ty0 = varType nm'+ ty0 = coreTypeOf nm' ty1 = if isTop then tvSubstWithTyEq ty0 else ty0 -- check for polymorphic types@@ -215,11 +184,11 @@ resTyRep <- not <$> isUntranslatableType False resTy if resTyRep then do- tmNorm <- normalizeTopLvlBndr isTopEnt nm (Binding nm' sp inl pr tm)+ tmNorm <- normalizeTopLvlBndr isTopEnt nm (Binding nm' sp inl pr tm r) let usedBndrs = Lens.toListOf globalIds (bindingTerm tmNorm)- traceIf (nm `elem` usedBndrs)+ traceIf (bindingRecursive tmNorm) (concat [ $(curLoc),"Expr belonging to bndr: ",nmS ," (:: "- , showPpr (varType (bindingId tmNorm))+ , showPpr (coreTypeOf (bindingId tmNorm)) , ") remains recursive after normalization:\n" , showPpr (bindingTerm tmNorm) ]) (return ())@@ -242,13 +211,13 @@ -- for the ByteArray# inside of a Natural constant. -- (GHC-8.4 does this with tests/shouldwork/Numbers/Exp.hs) -- It will later be inlined by flattenCallTree.- lvl <- Lens.view dbgLevel- traceIf (lvl > DebugNone)+ opts <- Lens.view debugOpts+ traceIf (dbg_invariants opts) (concat [$(curLoc), "Expr belonging to bndr: ", nmS, " (:: "- , showPpr (varType nm')+ , showPpr (coreTypeOf nm') , ") has a non-representable return type." , " Not normalising:\n", showPpr tm] )- (return ([],(nm,(Binding nm' sp inl pr tm))))+ (return ([],(nm,(Binding nm' sp inl pr tm r)))) Nothing -> error $ $(curLoc) ++ "Expr belonging to bndr: " ++ nmS ++ " not found"@@ -266,11 +235,8 @@ | (a,b) <- eltsVarEnv rcs ]) where- go (Binding nm _ _ _ tm) =- if nm `globalIdOccursIn` tm- then Just (nm,tm)- else Nothing-+ go (Binding nm _ _ _ tm r) =+ if r then Just (nm,tm) else Nothing -- | Perform general \"clean up\" of the normalized (non-recursive) function -- hierarchy. This includes:@@ -332,8 +298,8 @@ flattenNode :: CallTree -> NormalizeSession (Either CallTree ((Id,Term),[CallTree]))-flattenNode c@(CLeaf (_,(Binding _ _ NoInline _ _))) = return (Left c)-flattenNode c@(CLeaf (nm,(Binding _ _ _ _ e))) = do+flattenNode c@(CLeaf (_,(Binding _ _ NoInline _ _ _))) = return (Left c)+flattenNode c@(CLeaf (nm,(Binding _ _ _ _ e _))) = do isTopEntity <- elemVarSet nm <$> Lens.view topEntities if isTopEntity then return (Left c) else do tcm <- Lens.view tcCache@@ -342,13 +308,13 @@ Right (ids,[(bId,bExpr)],_) -> do let (fun,args,ticks) = collectArgsTicks bExpr case stripArgs ids (reverse ids) (reverse args) of- Just remainder | bId `localIdDoesNotOccurIn` bExpr ->+ Just remainder | bId `notElemFreeVars` bExpr -> return (Right ((nm,mkApps (mkTicks fun ticks) (reverse remainder)),[])) _ -> return (Right ((nm,e),[])) _ -> return (Right ((nm,e),[]))-flattenNode b@(CBranch (_,(Binding _ _ NoInline _ _)) _) =+flattenNode b@(CBranch (_,(Binding _ _ NoInline _ _ _)) _) = return (Left b)-flattenNode b@(CBranch (nm,(Binding _ _ _ _ e)) us) = do+flattenNode b@(CBranch (nm,(Binding _ _ _ _ e _)) us) = do isTopEntity <- elemVarSet nm <$> Lens.view topEntities if isTopEntity then return (Left b) else do tcm <- Lens.view tcCache@@ -357,11 +323,11 @@ Right (ids,[(bId,bExpr)],_) -> do let (fun,args,ticks) = collectArgsTicks bExpr case stripArgs ids (reverse ids) (reverse args) of- Just remainder | bId `localIdDoesNotOccurIn` bExpr ->+ Just remainder | bId `notElemFreeVars` bExpr -> return (Right ((nm,mkApps (mkTicks fun ticks) (reverse remainder)),us)) _ -> return (Right ((nm,e),us)) _ -> do- newInlineStrat <- Lens.use (extra.newInlineStrategy)+ newInlineStrat <- Lens.view newInlineStrategy if newInlineStrat || isCheapFunction e then return (Right ((nm,e),us)) else return (Left b)@@ -370,7 +336,7 @@ :: CallTree -> NormalizeSession CallTree flattenCallTree c@(CLeaf _) = return c-flattenCallTree (CBranch (nm,(Binding nm' sp inl pr tm)) used) = do+flattenCallTree (CBranch (nm,(Binding nm' sp inl pr tm r)) used) = do flattenedUsed <- mapM flattenCallTree used (newUsed,il_ct) <- partitionEithers <$> mapM flattenNode flattenedUsed let (toInline,il_used) = unzip il_ct@@ -381,7 +347,8 @@ let tm1 = substTm "flattenCallTree.flattenExpr" subst tm -- NB: When -fclash-debug-history is on, emit binary data holding the recorded rewrite steps- rewriteHistFile <- Lens.view dbgRewriteHistoryFile+ opts <- Lens.view debugOpts+ let rewriteHistFile = dbg_historyFile opts when (Maybe.isJust rewriteHistFile) $ let !_ = unsafePerformIO $ BS.appendFile (Maybe.fromJust rewriteHistFile)@@ -406,27 +373,23 @@ (Maybe.catMaybes toInline') let tm1 = substTm "flattenCallTree.flattenCheap" subst' newExpr newExpr' <- rewriteExpr ("flattenCheap",flatten) (showPpr nm, tm1) (nm', sp)- return (CBranch (nm,(Binding nm' sp inl pr newExpr')) (concat allUsed'))- else return (CBranch (nm,(Binding nm' sp inl pr newExpr)) allUsed)+ return (CBranch (nm,(Binding nm' sp inl pr newExpr' r)) (concat allUsed'))+ else return (CBranch (nm,(Binding nm' sp inl pr newExpr r)) allUsed) where flatten =- repeatR (topdownR (apply "appPropFast" appPropFast >->+ repeatR (topdownR (apply "appProp" appProp >-> apply "bindConstantVar" bindConstantVar >-> apply "caseCon" caseCon >->-#if EXPERIMENTAL_EVALUATOR- apply "deadcode" deadCode >->-#else (apply "reduceConst" reduceConst !-> apply "deadcode" deadCode) >->-#endif apply "reduceNonRepPrim" reduceNonRepPrim >-> apply "removeUnusedExpr" removeUnusedExpr >-> apply "flattenLet" flattenLet)) !-> topdownSucR (apply "topLet" topLet) - goCheap c@(CLeaf (nm2,(Binding _ _ inl2 _ e)))+ goCheap c@(CLeaf (nm2,(Binding _ _ inl2 _ e _))) | inl2 == NoInline = (Nothing ,[c]) | otherwise = (Just (nm2,e),[])- goCheap c@(CBranch (nm2,(Binding _ _ inl2 _ e)) us)+ goCheap c@(CBranch (nm2,(Binding _ _ inl2 _ e _)) us) | inl2 == NoInline = (Nothing, [c]) | otherwise = (Just (nm2,e),us)
− src/Clash/Normalize/DEC.hs
@@ -1,662 +0,0 @@-{-|- Copyright : (C) 2015-2016, University of Twente- License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>-- Helper functions for the 'disjointExpressionConsolidation' transformation-- The 'disjointExpressionConsolidation' transformation lifts applications of- global binders out of alternatives of case-statements.-- e.g. It converts:-- > case x of- > A -> f 3 y- > B -> f x x- > C -> h x-- into:-- > let f_arg0 = case x of {A -> 3; B -> x}- > f_arg1 = case x of {A -> y; B -> x}- > f_out = f f_arg0 f_arg1- > in case x of- > A -> f_out- > B -> f_out- > C -> h x--}--{-# LANGUAGE CPP #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecursiveDo #-}-{-# LANGUAGE TemplateHaskell #-}--module Clash.Normalize.DEC- (collectGlobals- ,collectGlobalsArgs- ,isDisjoint- ,mkDisjointGroup- )-where---- external-import Control.Concurrent.Supply (splitSupply)-import qualified Control.Lens as Lens-import Data.Bits ((.&.),complement)-import Data.Coerce (coerce)-import qualified Data.Either as Either-import qualified Data.Foldable as Foldable-import qualified Data.Graph as Graph-import qualified Data.IntMap.Strict as IM-import qualified Data.IntSet as IntSet-import qualified Data.List as List-import qualified Data.List.Extra as List-import qualified Data.Map.Strict as Map-import qualified Data.Maybe as Maybe-import Data.Monoid (All (..))--#if MIN_VERSION_ghc(8,10,0)-import GHC.Hs.Utils (chunkify,mkChunkified)-#else-import HsUtils (chunkify,mkChunkified)-#endif--#if MIN_VERSION_ghc(9,0,0)-import GHC.Settings.Constants (mAX_TUPLE_SIZE)-#else-import Constants (mAX_TUPLE_SIZE)-#endif--#if EXPERIMENTAL_EVALUATOR-import System.IO.Unsafe-#endif---- internal-import Clash.Core.DataCon (DataCon)--#if EXPERIMENTAL_EVALUATOR-import Clash.Core.PartialEval-#else-import Clash.Core.Evaluator.Types (whnf')-#endif--import Clash.Core.FreeVars- (termFreeVars', typeFreeVars', localVarsDoNotOccurIn)-import Clash.Core.Literal (Literal (..))-import Clash.Core.Term- (LetBinding, Pat (..), PrimInfo (..), Term (..), TickInfo (..), collectArgs,- collectArgsTicks, mkApps, mkTicks, patIds)-import Clash.Core.TermInfo (termType)-import Clash.Core.TyCon (TyConMap, TyConName, tyConDataCons)-import Clash.Core.Type (Type, isPolyFunTy, mkTyConApp, splitFunForallTy)-import Clash.Core.Util (mkInternalVar, mkSelectorCase, sccLetBindings)-import Clash.Core.Var (isGlobalId, isLocalId)-import Clash.Core.VarEnv- (InScopeSet, elemInScopeSet, extendInScopeSetList, notElemInScopeSet, unionInScope)-import Clash.Normalize.Types (NormalizeState)-import Clash.Rewrite.Types-import Clash.Rewrite.Util (isUntranslatableType)-import Clash.Rewrite.WorkFree (isConstant)-import Clash.Unique (lookupUniqMap)-import Clash.Util--data CaseTree a- = Leaf a- | LB [LetBinding] (CaseTree a)- | Branch Term [(Pat,CaseTree a)]- deriving (Eq,Show,Functor,Foldable)---- | Test if a 'CaseTree' collected from an expression indicates that--- application of a global binder is disjoint: occur in separate branches of a--- case-expression.-isDisjoint :: CaseTree ([Either Term Type])- -> Bool-isDisjoint (Branch _ [_]) = False-isDisjoint ct = go ct- where- go (Leaf _) = False- go (LB _ ct') = go ct'- go (Branch _ []) = False- go (Branch _ [(_,x)]) = go x- go b@(Branch _ (_:_:_)) = allEqual (map Either.rights (Foldable.toList b))---- Remove empty branches from a 'CaseTree'-removeEmpty :: Eq a => CaseTree [a] -> CaseTree [a]-removeEmpty l@(Leaf _) = l-removeEmpty (LB lb ct) =- case removeEmpty ct of- Leaf [] -> Leaf []- ct' -> LB lb ct'-removeEmpty (Branch s bs) =- case filter ((/= (Leaf [])) . snd) (map (second removeEmpty) bs) of- [] -> Leaf []- bs' -> Branch s bs'---- | Test if all elements in a list are equal to each other.-allEqual :: Eq a => [a] -> Bool-allEqual [] = True-allEqual (x:xs) = all (== x) xs---- | Collect 'CaseTree's for (potentially) disjoint applications of globals out--- of an expression. Also substitute truly disjoint applications of globals by a--- reference to a lifted out application.-collectGlobals'- :: InScopeSet- -> [(Term,Term)]- -- ^ Substitution of (applications of) a global binder by a reference to a- -- lifted term.- -> [Term]- -- ^ List of already seen global binders- -> Term- -- ^ The expression- -> Bool- -- ^ Whether expression is constant- -> RewriteMonad- NormalizeState- (Term, InScopeSet, [(Term, ([Term], CaseTree [Either Term Type]))])-collectGlobals' is0 substitution seen (Case scrut ty alts) _eIsConstant = do- rec (alts1, isAlts, collectedAlts) <-- collectGlobalsAlts is0 substitution seen scrut1 alts- (scrut1, isScrut, collectedScrut) <-- collectGlobals is0 substitution (map fst collectedAlts ++ seen) scrut- return ( Case scrut1 ty alts1- , unionInScope isAlts isScrut- , collectedAlts ++ collectedScrut )--collectGlobals' is0 substitution seen e@(collectArgsTicks -> (fun, args@(_:_), ticks)) eIsconstant- | not eIsconstant = do- tcm <- Lens.view tcCache- bndrs <- Lens.use bindings- evaluate <- Lens.view evaluator- ids <- Lens.use uniqSupply- let (ids1,ids2) = splitSupply ids- uniqSupply Lens..= ids2-#if EXPERIMENTAL_EVALUATOR- (i,_) <- Lens.use curFun- heap <- Lens.use ioHeap- addr <- Lens.use ioAddr- fuel <- Lens.view fuelLimit- let genv = mkGlobalEnv bndrs tcm is0 ids1 fuel heap addr- let eval = fst . unsafePerformIO . nf evaluate genv False i-#else- gh <- Lens.use globalHeap- let eval = (Lens.view Lens._3) . whnf' evaluate bndrs tcm gh ids1 is0 False-#endif- let eTy = termType tcm e- untran <- isUntranslatableType False eTy- case untran of- -- Don't lift out non-representable values, because they cannot be let-bound- -- in our desired normal form.- False -> do- -- Look for, and substitute by, disjoint applications of globals in- -- the arguments first before considering the current term in function- -- position. Doing it in the other order (this term in function position- -- first, followed by arguments) resulted in issue #1322- (args1,isArgs,collectedArgs) <-- collectGlobalsArgs is0 substitution seen args- let seenInArgs = map fst collectedArgs ++ seen- isInteresting <- interestingToLift is0 eval fun args ticks- case isInteresting of- Just fun1 | fun1 `notElem` seenInArgs -> do- let e1 = Maybe.fromMaybe (mkApps fun1 args1) (List.lookup fun1 substitution)- -- This function is lifted out an environment with the currently 'seen'- -- binders. When we later apply substitution, we need to start with this- -- environment, otherwise we perform incorrect substitutions in the- -- arguments.- return (e1,isArgs,(fun1,(seen,Leaf args1)):collectedArgs)- _ -> return (mkApps (mkTicks fun ticks) args1, isArgs, collectedArgs)- _ -> return (e,is0,[])---- FIXME: This duplicates A LOT of let-bindings, where I just pray that after--- the ANF, CSE, and DeadCodeRemoval pass all duplicates are removed.------ I think we should be able to do better, but perhaps we cannot fix it here.-collectGlobals' is0 substitution seen (Letrec lbs body) _eIsConstant = do- let is1 = extendInScopeSetList is0 (map fst lbs)- (body1,isBody,collectedBody) <-- collectGlobals is1 substitution seen body- (lbs1,isBndrs,collectedBndrs) <-- collectGlobalsLbs is1 substitution (map fst collectedBody ++ seen) lbs- return ( Letrec lbs1 body1- , unionInScope isBody isBndrs- , map (second (second (LB lbs1))) (collectedBody ++ collectedBndrs)- )--collectGlobals' is0 substitution seen (Tick t e) eIsConstant = do- (e1,is1,collected) <- collectGlobals' is0 substitution seen e eIsConstant- return (Tick t e1, is1, collected)--collectGlobals' is0 _ _ e _ = return (e,is0,[])---- | Collect 'CaseTree's for (potentially) disjoint applications of globals out--- of an expression. Also substitute truly disjoint applications of globals by a--- reference to a lifted out application.-collectGlobals- :: InScopeSet- -> [(Term,Term)]- -- ^ Substitution of (applications of) a global binder by a reference to- -- a lifted term.- -> [Term]- -- ^ List of already seen global binders- -> Term- -- ^ The expression- -> RewriteMonad- NormalizeState- (Term, InScopeSet, [(Term, ([Term], CaseTree [Either Term Type]))])-collectGlobals inScope substitution seen e =- collectGlobals' inScope substitution seen e (isConstant e)---- | Collect 'CaseTree's for (potentially) disjoint applications of globals out--- of a list of application arguments. Also substitute truly disjoint--- applications of globals by a reference to a lifted out application.-collectGlobalsArgs ::- InScopeSet- -> [(Term,Term)] -- ^ Substitution of (applications of) a global- -- binder by a reference to a lifted term.- -> [Term] -- ^ List of already seen global binders- -> [Either Term Type] -- ^ The list of arguments- -> RewriteMonad NormalizeState- ([Either Term Type]- ,InScopeSet- ,[(Term,([Term],CaseTree [(Either Term Type)]))]- )-collectGlobalsArgs is0 substitution seen args = do- ((is1,_),(args',collected)) <- second unzip <$> List.mapAccumLM go (is0,seen) args- return (args',is1,concat collected)- where- go (isN0,s) (Left tm) = do- (tm',isN1,collected) <- collectGlobals isN0 substitution s tm- return ((isN1,map fst collected ++ s),(Left tm',collected))- go (isN,s) (Right ty) = return ((isN,s),(Right ty,[]))---- | Collect 'CaseTree's for (potentially) disjoint applications of globals out--- of a list of alternatives. Also substitute truly disjoint applications of--- globals by a reference to a lifted out application.-collectGlobalsAlts ::- InScopeSet- -> [(Term,Term)] -- ^ Substitution of (applications of) a global- -- binder by a reference to a lifted term.- -> [Term] -- ^ List of already seen global binders- -> Term -- ^ The subject term- -> [(Pat,Term)] -- ^ The list of alternatives- -> RewriteMonad NormalizeState- ([(Pat,Term)]- ,InScopeSet- ,[(Term,([Term],CaseTree [(Either Term Type)]))]- )-collectGlobalsAlts is0 substitution seen scrut alts = do- (is1,(alts',collected)) <- second unzip <$> List.mapAccumLM go is0 alts- let collectedM = map (Map.fromList . map (second (second (:[])))) collected- collectedUN = Map.unionsWith (\(l1,r1) (l2,r2) -> (List.nub (l1 ++ l2),r1 ++ r2)) collectedM- collected' = map (second (second (Branch scrut))) (Map.toList collectedUN)- return (alts',is1,collected')- where- go isN0 (p,e) = do- let isN1 = extendInScopeSetList isN0 (snd (patIds p))- (e',isN2,collected) <- collectGlobals isN1 substitution seen e- return (isN2,((p,e'),map (second (second (p,))) collected))---- | Collect 'CaseTree's for (potentially) disjoint applications of globals out--- of a list of let-bindings. Also substitute truly disjoint applications of--- globals by a reference to a lifted out application.-collectGlobalsLbs ::- InScopeSet- -> [(Term,Term)] -- ^ Substitution of (applications of) a global- -- binder by a reference to a lifted term.- -> [Term] -- ^ List of already seen global binders- -> [LetBinding] -- ^ The list let-bindings- -> RewriteMonad NormalizeState- ([LetBinding]- ,InScopeSet- ,[(Term,([Term],CaseTree [(Either Term Type)]))]- )-collectGlobalsLbs is0 substitution seen lbs = do- let lbsSCCs = sccLetBindings lbs- ((is1,_),(lbsSCCs1,collected)) <-- second unzip <$> List.mapAccumLM go (is0,seen) lbsSCCs- return (Graph.flattenSCCs lbsSCCs1,is1,concat collected)- where- go :: (InScopeSet,[Term]) -> Graph.SCC LetBinding- -> RewriteMonad NormalizeState- ((InScopeSet, [Term])- ,(Graph.SCC LetBinding- ,[(Term,([Term],CaseTree [(Either Term Type)]))]- )- )- go (isN0,s) (Graph.AcyclicSCC (id_, e)) = do- (e',isN1,collected) <- collectGlobals isN0 substitution s e- return ((isN1,map fst collected ++ s),(Graph.AcyclicSCC (id_,e'),collected))- -- TODO: This completely skips recursive let-bindings in the collection of- -- potentially disjoint applications of globals; and skips substituting truly- -- disjoint applications of globals by a reference to a lifted out application.- --- -- This is to prevent the creation of combinational loops that have occurred- -- "in the wild", but for which we have not been able to a create small- -- unit test that triggers this creation-of-combinational-loops bug.- -- Completely skipping recursive let-bindings is taking the hammer to- -- solving this bug, without knowing whether a scalpel even existed and what- -- it might look like. We should at some point think hard how traversing- -- recursive let-bindings can introduce combinational loops, and whether- -- there exists a solution that can traverse recursive let-bindings,- -- finding more opportunities for DEC, while not introducing combinational- -- loops.- go acc scc@(Graph.CyclicSCC {}) = return (acc,(scc,[]))---- | Given a case-tree corresponding to a disjoint interesting \"term-in-a---- function-position\", return a let-expression: where the let-binding holds--- a case-expression selecting between the distinct arguments of the case-tree,--- and the body is an application of the term applied to the shared arguments of--- the case tree, and projections of let-binding corresponding to the distinct--- argument positions.-mkDisjointGroup- :: InScopeSet- -- ^ Variables in scope at the very top of the case-tree, i.e., the original- -- expression- -> (Term,([Term],CaseTree [(Either Term Type)]))- -- ^ Case-tree of arguments belonging to the applied term.- -> RewriteMonad NormalizeState (Term,[Term])-mkDisjointGroup inScope (fun,(seen,cs)) = do- let argss = Foldable.toList cs- argssT = zip [0..] (List.transpose argss)- (sharedT,distinctT) = List.partition (areShared inScope . snd) argssT- shared = map (second head) sharedT- distinct = map (Either.lefts) (List.transpose (map snd distinctT))- cs' = fmap (zip [0..]) cs- cs'' = removeEmpty- $ fmap (Either.lefts . map snd)- (if null shared- then cs'- else fmap (filter (`notElem` shared)) cs')- tcm <- Lens.view tcCache- (distinctCaseM,distinctProjections) <- case distinct of- -- only shared arguments: do nothing.- [] -> return (Nothing,[])- -- Create selectors and projections- (uc:_) -> do- let argTys = map (termType tcm) uc- disJointSelProj inScope argTys cs''- let newArgs = mkDJArgs 0 shared distinctProjections- case distinctCaseM of- Just lb -> return (Letrec [lb] (mkApps fun newArgs), seen)- Nothing -> return (mkApps fun newArgs, seen)---- | Create a single selector for all the representable distinct arguments by--- selecting between tuples. This selector is only ('Just') created when the--- number of representable uncommmon arguments is larger than one, otherwise it--- is not ('Nothing').------ It also returns:------ * For all the non-representable distinct arguments: a selector--- * For all the representable distinct arguments: a projection out of the tuple--- created by the larger selector. If this larger selector does not exist, a--- single selector is created for the single representable distinct argument.-disJointSelProj- :: InScopeSet- -> [Type]- -- ^ Types of the arguments- -> CaseTree [Term]- -- The case-tree of arguments- -> RewriteMonad NormalizeState (Maybe LetBinding,[Term])-disJointSelProj _ _ (Leaf []) = return (Nothing,[])-disJointSelProj inScope argTys cs = do- tcm <- Lens.view tcCache- tupTcm <- Lens.view tupleTcCache- let maxIndex = length argTys - 1- css = map (\i -> fmap ((:[]) . (!!i)) cs) [0..maxIndex]- (untran,tran) <- List.partitionM (isUntranslatableType False . snd) (zip [0..] argTys)- let untranCs = map (css!!) (map fst untran)- untranSels = zipWith (\(_,ty) cs' -> genCase tcm tupTcm ty [ty] cs')- untran untranCs- (lbM,projs) <- case tran of- [] -> return (Nothing,[])- [(i,ty)] -> return (Nothing,[genCase tcm tupTcm ty [ty] (css!!i)])- tys -> do- let m = length tys- (tyIxs,tys') = unzip tys- tupTy = mkBigTupTy tcm tupTcm tys'- cs' = fmap (\es -> map (es !!) tyIxs) cs- djCase = genCase tcm tupTcm tupTy tys' cs'- scrutId <- mkInternalVar inScope "tupIn" tupTy- projections <- mapM (mkBigTupSelector inScope tcm tupTcm (Var scrutId) tys') [0..m-1]- return (Just (scrutId,djCase),projections)- let selProjs = tranOrUnTran 0 (zip (map fst untran) untranSels) projs-- return (lbM,selProjs)- where- tranOrUnTran _ [] projs = projs- tranOrUnTran _ sels [] = map snd sels- tranOrUnTran n ((ut,s):uts) (p:projs)- | n == ut = s : tranOrUnTran (n+1) uts (p:projs)- | otherwise = p : tranOrUnTran (n+1) ((ut,s):uts) projs---- | Arguments are shared between invocations if:------ * They contain _no_ references to locally-bound variables--- * Are all equal-areShared :: InScopeSet -> [Either Term Type] -> Bool-areShared _ [] = True-areShared inScope xs@(x:_) = noFV1 && allEqual xs- where- noFV1 = case x of- Right ty -> getAll (Lens.foldMapOf (typeFreeVars' isLocallyBound IntSet.empty)- (const (All False)) ty)- Left tm -> getAll (Lens.foldMapOf (termFreeVars' isLocallyBound)- (const (All False)) tm)-- isLocallyBound v = isLocalId v && v `notElemInScopeSet` inScope---- | Create a list of arguments given a map of positions to common arguments,--- and a list of arguments-mkDJArgs :: Int -- ^ Current position- -> [(Int,Either Term Type)] -- ^ map from position to common argument- -> [Term] -- ^ (projections for) distinct arguments- -> [Either Term Type]-mkDJArgs _ cms [] = map snd cms-mkDJArgs _ [] uncms = map Left uncms-mkDJArgs n ((m,x):cms) (y:uncms)- | n == m = x : mkDJArgs (n+1) cms (y:uncms)- | otherwise = Left y : mkDJArgs (n+1) ((m,x):cms) uncms---- | Create a case-expression that selects between the distinct arguments given--- a case-tree-genCase :: TyConMap- -> IM.IntMap TyConName- -> Type -- ^ Type of the alternatives- -> [Type] -- ^ Types of the arguments- -> CaseTree [Term] -- ^ CaseTree of arguments- -> Term-genCase tcm tupTcm ty argTys = go- where- go (Leaf tms) =- mkBigTupTm tcm tupTcm (List.zipEqual argTys tms)-- go (LB lb ct) =- Letrec lb (go ct)-- go (Branch scrut [(p,ct)]) =- let ct' = go ct- (ptvs,pids) = patIds p- in if (coerce ptvs ++ coerce pids) `localVarsDoNotOccurIn` ct'- then ct'- else Case scrut ty [(p,ct')]-- go (Branch scrut pats) =- Case scrut ty (map (second go) pats)---- | Lookup the TyConName and DataCon for a tuple of size n-findTup :: TyConMap -> IM.IntMap TyConName -> Int -> (TyConName,DataCon)-findTup tcm tupTcm n = (tupTcNm,tupDc)- where- tupTcNm = Maybe.fromMaybe (error $ $curLoc ++ "Can't find " ++ show n ++ "-tuple") $ IM.lookup n tupTcm- Just tupTc = lookupUniqMap tupTcNm tcm- [tupDc] = tyConDataCons tupTc--mkBigTupTm :: TyConMap -> IM.IntMap TyConName -> [(Type,Term)] -> Term-mkBigTupTm tcm tupTcm args = snd $ mkBigTup tcm tupTcm args--mkSmallTup,mkBigTup :: TyConMap -> IM.IntMap TyConName -> [(Type,Term)] -> (Type,Term)-mkSmallTup _ _ [] = error $ $curLoc ++ "mkSmallTup: Can't create 0-tuple"-mkSmallTup _ _ [(ty,tm)] = (ty,tm)-mkSmallTup tcm tupTcm args = (ty,tm)- where- (argTys,tms) = unzip args- (tupTcNm,tupDc) = findTup tcm tupTcm (length args)- tm = mkApps (Data tupDc) (map Right argTys ++ map Left tms)- ty = mkTyConApp tupTcNm argTys--mkBigTup tcm tupTcm = mkChunkified (mkSmallTup tcm tupTcm)--mkSmallTupTy,mkBigTupTy- :: TyConMap- -> IM.IntMap TyConName- -> [Type]- -> Type-mkSmallTupTy _ _ [] = error $ $curLoc ++ "mkSmallTupTy: Can't create 0-tuple"-mkSmallTupTy _ _ [ty] = ty-mkSmallTupTy tcm tupTcm tys = mkTyConApp tupTcNm tys- where- m = length tys- (tupTcNm,_) = findTup tcm tupTcm m--mkBigTupTy tcm tupTcm = mkChunkified (mkSmallTupTy tcm tupTcm)--mkSmallTupSelector,mkBigTupSelector- :: MonadUnique m- => InScopeSet- -> TyConMap- -> IM.IntMap TyConName- -> Term- -> [Type]- -> Int- -> m Term-mkSmallTupSelector _ _ _ scrut [_] 0 = return scrut-mkSmallTupSelector _ _ _ _ [_] n = error $ $curLoc ++ "mkSmallTupSelector called with one type, but to select " ++ show n-mkSmallTupSelector inScope tcm _ scrut _ n = mkSelectorCase ($curLoc ++ "mkSmallTupSelector") inScope tcm scrut 1 n--mkBigTupSelector inScope tcm tupTcm scrut tys n = go (chunkify tys)- where- go [_] = mkSmallTupSelector inScope tcm tupTcm scrut tys n- go tyss = do- let (nOuter,nInner) = divMod n mAX_TUPLE_SIZE- tyss' = map (mkSmallTupTy tcm tupTcm) tyss- outer <- mkSmallTupSelector inScope tcm tupTcm scrut tyss' nOuter- inner <- mkSmallTupSelector inScope tcm tupTcm outer (tyss List.!! nOuter) nInner- return inner----- | Determine if a term in a function position is interesting to lift out of--- of a case-expression.------ This holds for all global functions, and certain primitives. Currently those--- primitives are:------ * All non-power-of-two multiplications--- * All division-like operations with a non-power-of-two divisor-interestingToLift- :: InScopeSet- -- ^ in scope- -> (Term -> Term)- -- ^ Evaluator- -> Term- -- ^ Term in function position- -> [Either Term Type]- -- ^ Arguments- -> [TickInfo]- -- ^ Tick annoations- -> RewriteMonad extra (Maybe Term)-interestingToLift inScope _ e@(Var v) _ ticks =- if NoDeDup `notElem` ticks && (isGlobalId v || v `elemInScopeSet` inScope)- then pure (Just e)- else pure Nothing-interestingToLift inScope eval e@(Prim pInfo) args ticks- | NoDeDup `notElem` ticks = do- let anyArgNotConstant = any (not . isConstant) lArgs- case List.lookup (primName pInfo) interestingPrims of- Just t | t || anyArgNotConstant -> pure (Just e)- _ | DeDup `elem` ticks -> pure (Just e)- _ -> do- let isInteresting = (\(x, y, z) -> interestingToLift inScope eval x y z) . collectArgsTicks- if isHOTy (primType pInfo) then do- anyInteresting <- List.anyM (fmap Maybe.isJust . isInteresting) lArgs- if anyInteresting then pure (Just e) else pure Nothing- else- pure Nothing-- where- interestingPrims =- [("Clash.Sized.Internal.BitVector.*#",tailNonPow2)- ,("Clash.Sized.Internal.BitVector.times#",tailNonPow2)- ,("Clash.Sized.Internal.BitVector.quot#",lastNotPow2)- ,("Clash.Sized.Internal.BitVector.rem#",lastNotPow2)- ,("Clash.Sized.Internal.Index.*#",tailNonPow2)- ,("Clash.Sized.Internal.Index.quot#",lastNotPow2)- ,("Clash.Sized.Internal.Index.rem#",lastNotPow2)- ,("Clash.Sized.Internal.Signed.*#",tailNonPow2)- ,("Clash.Sized.Internal.Signed.times#",tailNonPow2)- ,("Clash.Sized.Internal.Signed.rem#",lastNotPow2)- ,("Clash.Sized.Internal.Signed.quot#",lastNotPow2)- ,("Clash.Sized.Internal.Signed.div#",lastNotPow2)- ,("Clash.Sized.Internal.Signed.mod#",lastNotPow2)- ,("Clash.Sized.Internal.Unsigned.*#",tailNonPow2)- ,("Clash.Sized.Internal.Unsigned.times#",tailNonPow2)- ,("Clash.Sized.Internal.Unsigned.quot#",lastNotPow2)- ,("Clash.Sized.Internal.Unsigned.rem#",lastNotPow2)- ,("GHC.Base.quotInt",lastNotPow2)- ,("GHC.Base.remInt",lastNotPow2)- ,("GHC.Base.divInt",lastNotPow2)- ,("GHC.Base.modInt",lastNotPow2)- ,("GHC.Classes.divInt#",lastNotPow2)- ,("GHC.Classes.modInt#",lastNotPow2)-#if MIN_VERSION_base(4,15,0)- ,("GHC.Num.Integer.integerMul",allNonPow2)- ,("GHC.Num.Integer.integerDiv",lastNotPow2)- ,("GHC.Num.Integer.integerMod",lastNotPow2)- ,("GHC.Num.Integer.integerQuot",lastNotPow2)- ,("GHC.Num.Integer.integerRem",lastNotPow2)-#else- ,("GHC.Integer.Type.timesInteger",allNonPow2)- ,("GHC.Integer.Type.divInteger",lastNotPow2)- ,("GHC.Integer.Type.modInteger",lastNotPow2)- ,("GHC.Integer.Type.quotInteger",lastNotPow2)- ,("GHC.Integer.Type.remInteger",lastNotPow2)-#endif- ,("GHC.Prim.*#",allNonPow2)- ,("GHC.Prim.quotInt#",lastNotPow2)- ,("GHC.Prim.remInt#",lastNotPow2)- ]-- lArgs = Either.lefts args-- allNonPow2 = all (not . termIsPow2) lArgs- tailNonPow2 = case lArgs of- [] -> True- _ -> all (not . termIsPow2) (tail lArgs)- lastNotPow2 = case lArgs of- [] -> True- _ -> not (termIsPow2 (last lArgs))-- termIsPow2 e' = case eval e' of- Literal (IntegerLiteral n) -> isPow2 n- a -> case collectArgs a of- (Prim p,[Right _,Left _,Left (Literal (IntegerLiteral n))])- | isFromInteger (primName p) -> isPow2 n- (Prim p,[Right _,Left _,Left _,Left (Literal (IntegerLiteral n))])- | primName p == "Clash.Sized.Internal.BitVector.fromInteger#" -> isPow2 n- (Prim p,[Right _, Left _,Left (Literal (IntegerLiteral n))])- | primName p == "Clash.Sized.Internal.BitVector.fromInteger##" -> isPow2 n-- _ -> False-- isPow2 x = x /= 0 && (x .&. (complement x + 1)) == x-- isFromInteger x = x `elem` ["Clash.Sized.Internal.BitVector.fromInteger#"- ,"Clash.Sized.Integer.Index.fromInteger"- ,"Clash.Sized.Internal.Signed.fromInteger#"- ,"Clash.Sized.Internal.Unsigned.fromInteger#"- ]-- isHOTy t = case splitFunForallTy t of- (args',_) -> any isPolyFunTy (Either.rights args')--interestingToLift _ _ _ _ _ = pure Nothing
src/Clash/Normalize/PrimitiveReductions.hs view
@@ -1,8 +1,9 @@ {-| Copyright : (C) 2015-2016, University of Twente,- 2016 , Myrtle Software Ltd+ 2016 , Myrtle Software Ltd,+ 2021 , QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Reductions of primitives @@ -39,10 +40,12 @@ import qualified Control.Lens as Lens import Control.Lens ((.=))+import Data.Bifunctor (second) import Data.List (mapAccumR) import Data.List.Extra (zipEqual) import qualified Data.Maybe as Maybe-import TextShow (showt)+import Data.Text.Extra (showt)+import GHC.Stack (HasCallStack) #if MIN_VERSION_ghc(9,0,0) import GHC.Builtin.Names@@ -59,14 +62,14 @@ #endif import Clash.Core.DataCon (DataCon)+import Clash.Core.HasType import Clash.Core.Literal (Literal (..)) import Clash.Core.Name (nameOcc, Name(..), NameSort(User), mkUnsafeSystemName) import Clash.Core.Pretty (showPpr) import Clash.Core.Term (IsMultiPrim (..), CoreContext (..), PrimInfo (..), Term (..), WorkInfo (..), Pat (..),- collectTermIds, mkApps)-import Clash.Core.TermInfo+ collectTermIds, mkApps, PrimUnfolding(..)) import Clash.Core.Type (LitTy (..), Type (..), TypeView (..), coreView1, mkFunTy, mkTyConApp,@@ -77,11 +80,11 @@ (integerPrimTy, typeNatKind, liftedTypeKind) import Clash.Core.Util (appendToVec, extractElems, extractTElems, mkRTree,- mkUniqInternalId, mkUniqSystemTyVar, mkVec, dataConInstArgTys,- primCo, undefinedTm)-import Clash.Core.Var (Var (..), mkTyVar, mkLocalId)+ mkUniqInternalId, mkUniqSystemTyVar, mkVec, dataConInstArgTys, primCo)+import Clash.Core.Var (mkTyVar, mkLocalId) import Clash.Core.VarEnv (InScopeSet, extendInScopeSetList)+import qualified Clash.Normalize.Primitives as NP (undefined) import {-# SOURCE #-} Clash.Normalize.Strategy import Clash.Normalize.Types import Clash.Rewrite.Types@@ -108,7 +111,7 @@ -> Term vecHeadPrim vecTcNm = -- head :: Vec (n+1) a -> a- Prim (PrimInfo "Clash.Sized.Vector.head" (vecHeadTy vecTcNm) WorkNever SingleResult)+ Prim (PrimInfo "Clash.Sized.Vector.head" (vecHeadTy vecTcNm) WorkNever SingleResult NoUnfolding) vecLastPrim :: TyConName@@ -118,7 +121,7 @@ -- last :: Vec (n+1) a -> a -- has the same type signature as head, hence we're reusing its type -- definition here.- Prim (PrimInfo "Clash.Sized.Vector.last" (vecHeadTy vecTcNm) WorkNever SingleResult)+ Prim (PrimInfo "Clash.Sized.Vector.last" (vecHeadTy vecTcNm) WorkNever SingleResult NoUnfolding) vecHeadTy :: TyConName@@ -140,7 +143,7 @@ -> Term vecTailPrim vecTcNm = -- tail :: Vec (n + 1) a -> Vec n a- Prim (PrimInfo "Clash.Sized.Vector.tail" (vecTailTy vecTcNm) WorkNever SingleResult)+ Prim (PrimInfo "Clash.Sized.Vector.tail" (vecTailTy vecTcNm) WorkNever SingleResult NoUnfolding) vecInitPrim :: TyConName@@ -150,7 +153,7 @@ -- init :: Vec (n + 1) a -> Vec n a -- has the same type signature as tail, hence we're reusing its type -- definition here.- Prim (PrimInfo "Clash.Sized.Vector.init" (vecTailTy vecTcNm) WorkNever SingleResult)+ Prim (PrimInfo "Clash.Sized.Vector.init" (vecTailTy vecTcNm) WorkNever SingleResult NoUnfolding) vecTailTy :: TyConName@@ -193,36 +196,6 @@ pat = DataPat consCon [mTV] [co, el, rest] --- Make case statement that projects the _head_ from a given vector-extractHead- :: DataCon- -- ^ The Cons (:>) constructor- -> Type- -- ^ Element type- -> Integer- -- ^ Length of the vector- -> Term- -- ^ Vector to extract head from- -> Term- -- ^ Head of vector-extractHead consCon elTy vLength vec =- fst (extractHeadTail consCon elTy vLength vec)---- Make case statement that projects the _tail_ from a given vector-extractTail- :: DataCon- -- ^ The Cons (:>) constructor- -> Type- -- ^ Element type- -> Integer- -- ^ Length of the vector- -> Term- -- ^ Vector to extract head from- -> Term- -- ^ Tail of vector-extractTail consCon elTy vLength vec =- snd (extractHeadTail consCon elTy vLength vec)- -- | Create a vector of supplied elements mkVecCons :: HasCallStack@@ -280,7 +253,7 @@ -> NormalizeSession Term reduceReverse inScope0 n elTy vArg = do tcm <- Lens.view tcCache- let ty = termType tcm vArg+ let ty = inferCoreTypeOf tcm vArg go tcm ty where go tcm (coreView1 tcm -> Just ty') = go tcm ty'@@ -314,7 +287,7 @@ -> NormalizeSession Term reduceZipWith _ctx zipWithPrimInfo n lhsElTy rhsElTy resElTy fun lhsArg rhsArg = do tcm <- Lens.view tcCache- changed (go tcm (termType tcm lhsArg))+ changed (go tcm (inferCoreTypeOf tcm lhsArg)) where go tcm (coreView1 tcm -> Just ty) = go tcm ty go tcm (tyView -> TyConApp vecTcNm _)@@ -358,7 +331,7 @@ -> NormalizeSession Term reduceMap _ctx mapPrimInfo n argElTy resElTy fun arg = do tcm <- Lens.view tcCache- let ty = termType tcm arg+ let ty = inferCoreTypeOf tcm arg changed (go tcm ty) where go tcm (coreView1 tcm -> Just ty') = go tcm ty'@@ -400,7 +373,7 @@ -> NormalizeSession Term reduceImap (TransformContext is0 ctx) n argElTy resElTy fun arg = do tcm <- Lens.view tcCache- let ty = termType tcm arg+ let ty = inferCoreTypeOf tcm arg go tcm ty where go tcm (coreView1 tcm -> Just ty') = go tcm ty'@@ -415,7 +388,7 @@ (uniqs1,nTv) = mkUniqSystemTyVar (uniqs0,is1) ("n",typeNatKind) (uniqs2,(vars,elems)) = second (second concat . unzip) $ uncurry extractElems uniqs1 consCon argElTy 'I' n arg- (Right idxTy:_,_) = splitFunForallTy (termType tcm fun)+ (Right idxTy:_,_) = splitFunForallTy (inferCoreTypeOf tcm fun) (TyConApp idxTcNm _) = tyView idxTy -- fromInteger# :: KnownNat n => Integer -> Index n idxFromIntegerTy = ForAllTy nTv@@ -423,7 +396,7 @@ (mkTyConApp idxTcNm [VarTy nTv]) [integerPrimTy,integerPrimTy])- idxFromInteger = Prim (PrimInfo "Clash.Sized.Internal.Index.fromInteger#" idxFromIntegerTy WorkNever SingleResult)+ idxFromInteger = Prim (PrimInfo "Clash.Sized.Internal.Index.fromInteger#" idxFromIntegerTy WorkNever SingleResult NoUnfolding) idxs = map (App (App (TyApp idxFromInteger (LitTy (NumTy n))) (Literal (IntegerLiteral (toInteger n)))) . Literal . IntegerLiteral . toInteger) [0..(n-1)]@@ -499,8 +472,8 @@ -> NormalizeSession Term reduceTraverse (TransformContext is0 ctx) n aTy fTy bTy dict fun arg = do tcm <- Lens.view tcCache- let (TyConApp apDictTcNm _) = tyView (termType tcm dict)- ty = termType tcm arg+ let (TyConApp apDictTcNm _) = tyView (inferCoreTypeOf tcm dict)+ ty = inferCoreTypeOf tcm arg go tcm apDictTcNm ty where go tcm apDictTcNm (coreView1 tcm -> Just ty') = go tcm apDictTcNm ty'@@ -532,20 +505,20 @@ fnPat = DataPat funcDictCon [] funcDicIds -- Extract the 'pure' function from the Applicative dictionary- pureTy = varType pureId+ pureTy = coreTypeOf pureId pureTm = Case dict pureTy [(apPat,Var pureId)] -- Extract the '<*>' function from the Applicative dictionary- apTy = varType apId+ apTy = coreTypeOf apId apTm = Case dict apTy [(apPat, Var apId)] -- Extract the Functor dictionary from the Applicative dictionary- funcTy = varType functorDictId+ funcTy = coreTypeOf functorDictId funcTm = Case dict funcTy [(apPat,Var functorDictId)] -- Extract the 'fmap' function from the Functor dictionary- fmapTy = varType fmapId+ fmapTy = coreTypeOf fmapId fmapTm = Case (Var functorDictId) fmapTy [(fnPat, Var fmapId)] @@ -636,7 +609,7 @@ reduceFoldr _ _ 0 _ _ start _ = changed start reduceFoldr _ctx foldrPrimInfo n aTy fun start arg = do tcm <- Lens.view tcCache- let ty = termType tcm arg+ let ty = inferCoreTypeOf tcm arg changed (go tcm ty) where go tcm (coreView1 tcm -> Just ty') = go tcm ty'@@ -647,7 +620,7 @@ = let (a, as) = extractHeadTail consCon aTy n arg b = mkApps (Prim foldrPrimInfo) [ Right aTy- , Right (termType tcm start)+ , Right (inferCoreTypeOf tcm start) , Right (LitTy (NumTy (n - 1))) , Left fun , Left start@@ -678,7 +651,7 @@ -> NormalizeSession Term reduceFold (TransformContext is0 ctx) n aTy fun arg = do tcm <- Lens.view tcCache- let ty = termType tcm arg+ let ty = inferCoreTypeOf tcm arg go tcm ty where go tcm (coreView1 tcm -> Just ty') = go tcm ty'@@ -723,7 +696,7 @@ reduceDFold _ 0 _ _ start _ = changed start reduceDFold is0 n aTy fun start arg = do tcm <- Lens.view tcCache- let ty = termType tcm arg+ let ty = inferCoreTypeOf tcm arg go tcm ty where go tcm (coreView1 tcm -> Just ty') = go tcm ty'@@ -738,7 +711,7 @@ -- TOOD: be used for every other function in this module. (uniqs1,(vars,elems)) = second (second concat . unzip) $ extractElems uniqs0 is1 consCon aTy 'D' n arg- (_ltv:Right snTy:_,_) = splitFunForallTy (termType tcm fun)+ (_ltv:Right snTy:_,_) = splitFunForallTy (inferCoreTypeOf tcm fun) (TyConApp snatTcNm _) = tyView snTy (Just snatTc) = lookupUniqMap snatTcNm tcm [snatDc] = tyConDataCons snatTc@@ -767,7 +740,7 @@ -> NormalizeSession Term reduceHead inScope n aTy vArg = do tcm <- Lens.view tcCache- let ty = termType tcm vArg+ let ty = inferCoreTypeOf tcm vArg go tcm ty where go tcm (coreView1 tcm -> Just ty') = go tcm ty'@@ -795,7 +768,7 @@ -> NormalizeSession Term reduceTail inScope n aTy vArg = do tcm <- Lens.view tcCache- let ty = termType tcm vArg+ let ty = inferCoreTypeOf tcm vArg go tcm ty where go tcm (coreView1 tcm -> Just ty') = go tcm ty'@@ -824,7 +797,7 @@ -> NormalizeSession Term reduceLast inScope n aTy vArg = do tcm <- Lens.view tcCache- let ty = termType tcm vArg+ let ty = inferCoreTypeOf tcm vArg go tcm ty where go tcm (coreView1 tcm -> Just ty') = go tcm ty'@@ -839,7 +812,7 @@ (tB,_) = head (last elems) uniqSupply Lens..= uniqs1 case n of- 0 -> changed (undefinedTm aTy)+ 0 -> changed (TyApp (Prim NP.undefined) aTy) _ -> changed (Letrec (init (concat elems)) (Var tB)) go _ ty = error $ $(curLoc) ++ "reduceLast: argument does not have a vector type: " ++ showPpr ty @@ -855,7 +828,7 @@ -> NormalizeSession Term reduceInit _inScope initPrimInfo n aTy vArg = do tcm <- Lens.view tcCache- let ty = termType tcm vArg+ let ty = inferCoreTypeOf tcm vArg changed (go tcm ty) where go tcm (coreView1 tcm -> Just ty') = go tcm ty'@@ -893,7 +866,7 @@ -> NormalizeSession Term reduceAppend inScope n m aTy lArg rArg = do tcm <- Lens.view tcCache- let ty = termType tcm lArg+ let ty = inferCoreTypeOf tcm lArg go tcm ty where go tcm (coreView1 tcm -> Just ty') = go tcm ty'@@ -924,7 +897,7 @@ -> NormalizeSession Term reduceUnconcat inScope unconcatPrimInfo n m aTy sm arg = do tcm <- Lens.view tcCache- let ty = termType tcm arg+ let ty = inferCoreTypeOf tcm arg go tcm ty where go tcm (coreView1 tcm -> Just ty') = go tcm ty'@@ -983,7 +956,7 @@ -> NormalizeSession Term reduceTranspose n 0 aTy arg = do tcm <- Lens.view tcCache- let ty = termType tcm arg+ let ty = inferCoreTypeOf tcm arg go tcm ty where go tcm (coreView1 tcm -> Just ty') = go tcm ty'@@ -1086,10 +1059,11 @@ -> Term eqIntPrim intTy boolTy = Prim (PrimInfo- "Clash.Transformations.eqInt"+ "GHC.Classes.eqInt" (mkFunTy intTy (mkFunTy intTy boolTy)) WorkVariable- SingleResult )+ SingleResult+ NoUnfolding) go tcm (coreView1 tcm -> Just ty') = go tcm ty' go tcm (tyView -> TyConApp vecTcNm _)@@ -1099,7 +1073,7 @@ = do -- Get data constructors of 'Int' uniqs0 <- Lens.use uniqSupply- let iTy = termType tcm i+ let iTy = inferCoreTypeOf tcm i (TyConApp iTcNm _) = tyView iTy (Just iTc) = lookupUniqMap iTcNm tcm [iDc] = tyConDataCons iTc@@ -1141,7 +1115,7 @@ -> NormalizeSession Term reduceIndex_int is0 n aTy v i = do tcm <- Lens.view tcCache- let vTy = termType tcm v+ let vTy = inferCoreTypeOf tcm v go tcm vTy where -- Basically creates:@@ -1190,10 +1164,11 @@ -> Term eqIntPrim intTy boolTy = Prim ( PrimInfo- "Clash.Transformations.eqInt"+ "GHC.Classes.eqInt" (mkFunTy intTy (mkFunTy intTy boolTy)) WorkVariable- SingleResult )+ SingleResult+ NoUnfolding) go tcm (coreView1 tcm -> Just ty') = go tcm ty' go tcm (tyView -> TyConApp vecTcNm _)@@ -1203,7 +1178,7 @@ = do -- Get data constructors of 'Int' uniqs0 <- Lens.use uniqSupply- let iTy = termType tcm i+ let iTy = inferCoreTypeOf tcm i (TyConApp iTcNm _) = tyView iTy (Just iTc) = lookupUniqMap iTcNm tcm [iDc] = tyConDataCons iTc@@ -1221,7 +1196,7 @@ -- Build a right-biased tree of case-expressions let indexed = foldr (index_intElement tcm iDc iTy)- (undefinedTm aTy)+ (TyApp (Prim NP.undefined) aTy) (zip vars [0..]) lb = Letrec (init elems) indexed uniqSupply Lens..= uniqs1@@ -1242,7 +1217,7 @@ -> NormalizeSession Term reduceDTFold inScope n aTy lrFun brFun arg = do tcm <- Lens.view tcCache- let ty = termType tcm arg+ let ty = inferCoreTypeOf tcm arg go tcm ty where go tcm (coreView1 tcm -> Just ty') = go tcm ty'@@ -1254,7 +1229,7 @@ let (uniqs1,(vars,elems)) = second (second concat . unzip) $ extractElems uniqs0 inScope consCon aTy 'T' (2^n) arg- (_ltv:Right snTy:_,_) = splitFunForallTy (termType tcm brFun)+ (_ltv:Right snTy:_,_) = splitFunForallTy (inferCoreTypeOf tcm brFun) (TyConApp snatTcNm _) = tyView snTy (Just snatTc) = lookupUniqMap snatTcNm tcm [snatDc] = tyConDataCons snatTc@@ -1290,7 +1265,7 @@ -> NormalizeSession Term reduceTFold inScope n aTy lrFun brFun arg = do tcm <- Lens.view tcCache- let ty = termType tcm arg+ let ty = inferCoreTypeOf tcm arg go tcm ty where go tcm (coreView1 tcm -> Just ty') = go tcm ty'@@ -1300,7 +1275,7 @@ , [lrCon,brCon] <- tyConDataCons treeTc = do uniqs0 <- Lens.use uniqSupply let (uniqs1,(vars,elems)) = extractTElems uniqs0 inScope lrCon brCon aTy 'T' n arg- (_ltv:Right snTy:_,_) = splitFunForallTy (termType tcm brFun)+ (_ltv:Right snTy:_,_) = splitFunForallTy (inferCoreTypeOf tcm brFun) (TyConApp snatTcNm _) = tyView snTy (Just snatTc) = lookupUniqMap snatTcNm tcm [snatDc] = tyConDataCons snatTc
+ src/Clash/Normalize/Primitives.hs view
@@ -0,0 +1,48 @@+{-|+Copyright : (C) 2021, QBayLogic B.V.+License : BSD2 (see the file LICENSE)+Maintainer : QBayLogic B.V. <devops@qbaylogic.com>++Special primitives created during the normalization process.+-}++{-# LANGUAGE TemplateHaskellQuotes #-}++module Clash.Normalize.Primitives+ ( removedArg+ , undefined+ ) where++import Prelude hiding (undefined)++import qualified Data.Text.Extra as Text++import Clash.Core.Term (IsMultiPrim(..), PrimInfo(..), PrimUnfolding(..), WorkInfo(..))+import Clash.Core.Util (undefinedTy)++-- | The removedArg primitive represents an argument which is computationally+-- irrelevant, and has been removed from the circuit (as removing it does not+-- change the behaviour of the circuit). Examples of such arguments are unused+-- arguments to blackboxes, as removing them does not affect the rendered HDL.+--+removedArg :: PrimInfo+removedArg = PrimInfo+ { primName = Text.showt 'removedArg+ , primType = undefinedTy+ , primWorkInfo = WorkNever+ , primMultiResult = SingleResult+ , primUnfolding = NoUnfolding+ }++-- | The undefined primitive represents an undefined value that was identified+-- during normalization. This includes undefined results to compile-time+-- evaluation, such as division by zero.+--+undefined :: PrimInfo+undefined = PrimInfo+ { primName = Text.showt 'undefined+ , primType = undefinedTy+ , primWorkInfo = WorkNever+ , primMultiResult = SingleResult+ , primUnfolding = NoUnfolding+ }
src/Clash/Normalize/Strategy.hs view
@@ -1,7 +1,8 @@ {-|- Copyright : (C) 2012-2016, University of Twente+ Copyright : (C) 2012-2016, University of Twente,+ (C) 2021, QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Transformation process for normalization -}@@ -33,9 +34,7 @@ normalization = rmDeadcode >-> multPrim >-> constantPropagation >-> rmUnusedExpr >-!-> anf >-!-> rmDeadcode >-> bindConst >-> letTL-#if !EXPERIMENTAL_EVALUATOR >-> evalConst-#endif >-!-> cse >-!-> cleanup >-> xOptim >-> rmDeadcode >-> cleanup >-> bindSimIO >-> recLetRec >-> splitArgs@@ -48,12 +47,12 @@ rmDeadcode = bottomupR (apply "deadcode" deadCode) bindConst = topdownR (apply "bindConstantVar" bindConstantVar) -- See [Note] bottomup traversal evalConst:-#if !EXPERIMENTAL_EVALUATOR evalConst = bottomupR (apply "evalConst" reduceConst)-#endif cse = topdownR (apply "CSE" simpleCSE) xOptim = bottomupR (apply "xOptimize" xOptimize) cleanup = topdownR (apply "etaExpandSyn" etaExpandSyn) >->+ -- See [Note] relation `collapseRHSNoops` and `inlineCleanup`+ topdownSucR (apply "collapseRHSNoops" collapseRHSNoops) >-> topdownSucR (apply "inlineCleanup" inlineCleanup) !-> innerMost (applyMany [("caseCon" , caseCon) ,("bindConstantVar", bindConstantVar)@@ -74,25 +73,23 @@ dec >-> conSpec where- etaTL = apply "etaTL" etaExpansionTL !-> topdownR (apply "applicationPropagation" appPropFast)+ etaTL = apply "etaTL" etaExpansionTL !-> topdownR (apply "applicationPropagation" appProp) inlineAndPropagate = repeatR (topdownR (applyMany transPropagateAndInline) >-> inlineNR) spec = bottomupR (applyMany specTransformations) caseFlattening = repeatR (topdownR (apply "caseFlat" caseFlat)) dec = repeatR (topdownR (apply "DEC" disjointExpressionConsolidation))- conSpec = bottomupR ((apply "appPropCS" appPropFast !->+ conSpec = bottomupR ((apply "appPropCS" appProp !-> bottomupR (apply "constantSpec" constantSpec)) >-! apply "constantSpec" constantSpec) transPropagateAndInline :: [(String,NormRewrite)] transPropagateAndInline =- [ ("applicationPropagation", appPropFast )+ [ ("applicationPropagation", appProp ) , ("bindConstantVar" , bindConstantVar ) , ("caseLet" , caseLet )-#if !EXPERIMENTAL_EVALUATOR , ("caseCase" , caseCase )-#endif , ("caseCon" , caseCon )- , ("elemExistentials" , elemExistentials )+ , ("elimExistentials" , elimExistentials ) , ("caseElemNonReachable" , caseElemNonReachable ) , ("removeUnusedExpr" , removeUnusedExpr ) -- These transformations can safely be applied in a top-down traversal as@@ -109,7 +106,7 @@ , ("splitCastWork" , splitCastWork) , ("argCastSpec" , argCastSpec) , ("inlineCast" , inlineCast)- , ("eliminateCastCast",eliminateCastCast)+ , ("elimCastCast" , elimCastCast) ] -- InlineNonRep cannot be applied in a top-down traversal, as the non-representable@@ -137,8 +134,53 @@ specTransformations = [ ("typeSpec" , typeSpec) , ("nonRepSpec" , nonRepSpec)+ , ("zeroWidthSpec", zeroWidthSpec)+ -- See Note [zeroWidthSpec enabling transformations] ] +{-+Note [zeroWidthSpec enabling transformations]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+When zeroWidthSpec fires, it can lead to better results in normalization, but+this is somewhat incidental. The extra transformations which fire are typically+from++ * calls to transformations like caseCon which occur after constantPropagation+ (e.g. caseCon run after ANF conversion).++ * flattening / inlining which happens late in normalization (after regular+ normalization has occurred)++ * normalizing another function due to being marked NOINLINE++If we consider the following:++ data AB = A | B++ ab :: KnownNat n => Index n -> AB -> AB+ ab n A = if n > 0 then A else B+ ab n B = if n == 0 then B else A+ {-# NOINLINE ab #-}++ topEntity = ab @1+ {-# NOINLINE topEntity #-}++The zeroWidthSpec transformation fires on the topEntity, giving a+post-normalization topEntity of++ \(x :: Index 1) ->+ \(y :: AB) ->+ letrec result :: AB = ab' y in result++where++ ab' = ab (fromInteger# 0)++The extra transformations which fire happen later when ab' is normalized.+Removing the NOINLINE from ab gives the same result, but the extra+transformations fire in flattening instead.+-}+ {- [Note] bottom-up traversal for liftNonRep We used to say: @@ -274,10 +316,6 @@ topdownSucR :: Rewrite extra -> Rewrite extra topdownSucR r = r >-! (allR (topdownSucR r)) {-# INLINE topdownSucR #-}--topdownRR :: Rewrite extra -> Rewrite extra-topdownRR r = repeatR (topdownR r)-{-# INLINE topdownRR #-} innerMost :: Rewrite extra -> Rewrite extra innerMost = let go r = bottomupR (r !-> innerMost r) in go
src/Clash/Normalize/Transformations.hs view
@@ -1,3274 +1,27 @@ {-| Copyright : (C) 2012-2016, University of Twente, 2016-2017, Myrtle Software Ltd,- 2017-2018, Google Inc.- License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>-- Transformations of the Normalization process--}--{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE MultiWayIf #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE TemplateHaskell #-}--module Clash.Normalize.Transformations- ( caseLet- , caseCon- , caseCase- , caseElemNonReachable- , elemExistentials- , inlineNonRep- , inlineOrLiftNonRep- , typeSpec- , nonRepSpec- , etaExpansionTL- , nonRepANF- , bindConstantVar- , constantSpec- , makeANF- , deadCode- , topLet- , recToLetRec- , inlineWorkFree- , inlineHO- , inlineSmall- , simpleCSE- , reduceConst- , reduceNonRepPrim- , caseFlat- , disjointExpressionConsolidation- , removeUnusedExpr- , inlineCleanup- , inlineBndrsCleanup- , flattenLet- , splitCastWork- , inlineCast- , caseCast- , letCast- , eliminateCastCast- , argCastSpec- , etaExpandSyn- , appPropFast- , separateArguments- , separateLambda- , xOptimize- , setupMultiResultPrim- , inlineSimIO- )-where--import Control.Exception (throw)-import Control.Lens ((^.),_1,_2)-import qualified Control.Lens as Lens-import qualified Control.Monad as Monad-import Control.Monad.Extra (orM)-import Control.Monad.State (StateT (..), modify)-import Control.Monad.State.Strict (evalState)-import Control.Monad.Writer (lift, listen)-import Control.Monad.Trans.Except (runExcept)-import Data.Coerce (coerce)-import Data.Default-import qualified Data.Either as Either-import qualified Data.HashMap.Lazy as HashMap-import Data.List ((\\))-import qualified Data.List as List-import qualified Data.List.Extra as List-import qualified Data.Maybe as Maybe-import qualified Data.Monoid as Monoid-import qualified Data.Primitive.ByteArray as BA-import qualified Data.Text as Text-#if MIN_VERSION_base(4,15,0)-import GHC.Num.Integer (Integer (..))-#else-import GHC.Integer.GMP.Internals (Integer (..), BigNat (..))-#endif-import TextShow (TextShow(showt))--#if MIN_VERSION_ghc(9,0,0)-import GHC.Types.Basic (InlineSpec (..))-#else-import BasicTypes (InlineSpec (..))-#endif--import Clash.Annotations.Primitive (extractPrim)-import Clash.Core.DataCon (DataCon (..))-import Clash.Core.EqSolver-import Clash.Core.Name- (mkUnsafeInternalName, Name (..), NameSort (..), mkUnsafeSystemName, nameOcc)-import Clash.Core.FreeVars- (localIdOccursIn, localIdsDoNotOccurIn, freeLocalIds, termFreeTyVars,- typeFreeVars, localVarsDoNotOccurIn, localIdDoesNotOccurIn,- countFreeOccurances)-import Clash.Core.Literal (Literal (..))-import Clash.Core.Pretty (PrettyOptions(..), showPpr, showPpr')-import Clash.Core.Subst-import Clash.Core.Term-import Clash.Core.TermInfo-import Clash.Core.Type (Type (..), TypeView (..), applyFunTy,- isPolyFunCoreTy, isClassTy,- normalizeType, splitFunForallTy,- splitFunTy,- tyView, mkPolyFunTy, coreView,- LitTy (..), coreView1, mkTyConApp)-import Clash.Core.TyCon (TyConMap, tyConDataCons)-import Clash.Core.Util- (Projections (..), isSignalType, mkVec, tyNatSize, undefinedTm,- shouldSplit, inverseTopSortLetBindings, mkInternalVar, mkSelectorCase)-import Clash.Core.Var- (Id, TyVar, Var (..), isGlobalId, isLocalId, mkLocalId)-import Clash.Core.VarEnv- (InScopeSet, VarEnv, VarSet, elemVarSet,- emptyVarEnv, extendInScopeSet, extendInScopeSetList, lookupVarEnv,- notElemVarSet, unionVarEnvWith, unionInScope, unitVarEnv,- unitVarSet, mkVarSet, mkInScopeSet, uniqAway, elemInScopeSet, elemVarEnv,- foldlWithUniqueVarEnv', lookupVarEnvDirectly, extendVarEnv, unionVarEnv,- eltsVarEnv, mkVarEnv, elemUniqInScopeSet)-import Clash.Debug-import Clash.Driver.Types (Binding(..), DebugLevel (..))-import Clash.Netlist.BlackBox.Types (Element(Err))-import Clash.Netlist.BlackBox.Util (getUsedArguments)-import Clash.Netlist.Types (BlackBox(..), HWType (..), FilteredHWType(..))-import Clash.Netlist.Util- (coreTypeToHWType, representableType, splitNormalized, bindsExistentials)-import Clash.Normalize.DEC-import Clash.Normalize.PrimitiveReductions-import Clash.Normalize.Types-import Clash.Normalize.Util-import Clash.Primitives.Types- (Primitive(..), TemplateKind(TExpr), CompiledPrimMap, UsedArguments(..))-import Clash.Rewrite.Combinators-import Clash.Rewrite.Types-import Clash.Rewrite.Util-import Clash.Unique-import Clash.Util-import qualified Clash.Util.Interpolate as I--inlineOrLiftNonRep :: HasCallStack => NormRewrite-inlineOrLiftNonRep ctx eLet@(Letrec _ body) =- inlineOrLiftBinders nonRepTest inlineTest ctx eLet- where- bodyFreeOccs = countFreeOccurances body-- nonRepTest :: (Id, Term) -> RewriteMonad extra Bool- nonRepTest (Id {varType = ty}, _)- = not <$> (representableType <$> Lens.view typeTranslator- <*> Lens.view customReprs- <*> pure False- <*> Lens.view tcCache- <*> pure ty)- nonRepTest _ = return False-- inlineTest :: Term -> (Id, Term) -> Bool- inlineTest e (id_, e') =- -- We do __NOT__ inline:- not $ or- [ -- 1. recursive let-binders- -- id_ `localIdOccursIn` e' -- <= already checked in inlineOrLiftBinders- -- 2. join points (which are not void-wrappers)- isJoinPointIn id_ e && not (isVoidWrapper e')- -- 3. binders that are used more than once in the body, because- -- it makes CSE a whole lot more difficult.- --- -- XXX: Check whether we can extend this to the binders as well- , maybe False (>1) (lookupVarEnv id_ bodyFreeOccs)- ]--inlineOrLiftNonRep _ e = return e-{-# SCC inlineOrLiftNonRep #-}--{- [Note] join points and void wrappers-Join points are functions that only occur in tail-call positions within an-expression, and only when they occur in a tail-call position more than once.--Normally bindNonRep binds/inlines all non-recursive local functions. However,-doing so for join points would significantly increase compilation time, so we-avoid it. The only exception to this rule are so-called void wrappers. Void-wrappers are functions of the form:--> \(w :: Void) -> f a b c--i.e. a wrapper around the function 'f' where the argument 'w' is not used. We-do bind/line these join-points because these void-wrappers interfere with the-'disjoint expression consolidation' (DEC) and 'common sub-expression elimination'-(CSE) transformation, sometimes resulting in circuits that are twice as big-as they'd need to be.--}---- | Specialize functions on their type-typeSpec :: HasCallStack => NormRewrite-typeSpec ctx e@(TyApp e1 ty)- | (Var {}, args) <- collectArgs e1- , null $ Lens.toListOf typeFreeVars ty- , (_, []) <- Either.partitionEithers args- = specializeNorm ctx e--typeSpec _ e = return e-{-# SCC typeSpec #-}---- | Specialize functions on their non-representable argument-nonRepSpec :: HasCallStack => NormRewrite-nonRepSpec ctx e@(App e1 e2)- | (Var {}, args) <- collectArgs e1- , (_, []) <- Either.partitionEithers args- , null $ Lens.toListOf termFreeTyVars e2- = do tcm <- Lens.view tcCache- let e2Ty = termType tcm e2- let localVar = isLocalVar e2- nonRepE2 <- not <$> (representableType <$> Lens.view typeTranslator- <*> Lens.view customReprs- <*> pure False- <*> Lens.view tcCache- <*> pure e2Ty)- if nonRepE2 && not localVar- then do- e2' <- inlineInternalSpecialisationArgument e2- specializeNorm ctx (App e1 e2')- else return e- where- -- | If the argument on which we're specialising ia an internal function,- -- one created by the compiler, then inline that function before we- -- specialise.- --- -- We need to do this because otherwise the specialisation history won't- -- recognize the new specialisation argument as something the function has- -- already been specialized on- inlineInternalSpecialisationArgument- :: Term- -> NormalizeSession Term- inlineInternalSpecialisationArgument app- | (Var f,fArgs,ticks) <- collectArgsTicks app- = do- fTmM <- lookupVarEnv f <$> Lens.use bindings- case fTmM of- Just b- | nameSort (varName (bindingId b)) == Internal- -> censor (const mempty)- (topdownR appPropFast ctx- (mkApps (mkTicks (bindingTerm b) ticks) fArgs))- _ -> return app- | otherwise = return app--nonRepSpec _ e = return e-{-# SCC nonRepSpec #-}---- | Lift the let-bindings out of the subject of a Case-decomposition-caseLet :: HasCallStack => NormRewrite-caseLet (TransformContext is0 _) (Case (collectTicks -> (Letrec xes e,ticks)) ty alts) = do- -- Note [CaseLet deshadow]- -- Imagine- --- -- @- -- case (let x = u in e) of {p -> a}- -- @- --- -- where `a` has a free variable named `x`.- --- -- Simply transforming the above to:- --- -- @- -- let x = u in case e of {p -> a}- -- @- --- -- would be very bad, because now the let-binding captures the free x variable- -- in a.- --- -- We must therefor rename `x` so that it doesn't capture the free variables- -- in the alternative:- --- -- @- -- let x1 = u[x:=x1] in case e[x:=x1] of {p -> a}- -- @- --- -- It is safe to over-approximate the free variables in `a` by simply taking- -- the current InScopeSet.- let (xes1,e1) = deshadowLetExpr is0 xes e- changed (Letrec (map (second (`mkTicks` ticks)) xes1)- (Case (mkTicks e1 ticks) ty alts))--caseLet _ e = return e-{-# SCC caseLet #-}---- | Remove non-reachable alternatives. For example, consider:------ data STy ty where--- SInt :: Int -> STy Int--- SBool :: Bool -> STy Bool------ f :: STy ty -> ty--- f (SInt b) = b + 1--- f (SBool True) = False--- f (SBool False) = True--- {-# NOINLINE f #-}------ g :: STy Int -> Int--- g = f------ @f@ is always specialized on @STy Int@. The SBool alternatives are therefore--- unreachable. Additional information can be found at:--- https://github.com/clash-lang/clash-compiler/pull/465-caseElemNonReachable :: HasCallStack => NormRewrite-caseElemNonReachable _ case0@(Case scrut altsTy alts0) = do- tcm <- Lens.view tcCache-- let (altsAbsurd, altsOther) = List.partition (isAbsurdAlt tcm) alts0- case altsAbsurd of- [] -> return case0- _ -> changed =<< caseOneAlt (Case scrut altsTy altsOther)--caseElemNonReachable _ e = return e-{-# SCC caseElemNonReachable #-}---- | Tries to eliminate existentials by using heuristics to determine what the--- existential should be. For example, consider Vec:------ data Vec :: Nat -> Type -> Type where--- Nil :: Vec 0 a--- Cons x xs :: a -> Vec n a -> Vec (n + 1) a------ Thus, 'null' (annotated with existentials) could look like:------ null :: forall n . Vec n Bool -> Bool--- null v =--- case v of--- Nil {n ~ 0} -> True--- Cons {n1:Nat} {n~n1+1} (x :: a) (xs :: Vec n1 a) -> False------ When it's applied to a vector of length 5, this becomes:------ null :: Vec 5 Bool -> Bool--- null v =--- case v of--- Nil {5 ~ 0} -> True--- Cons {n1:Nat} {5~n1+1} (x :: a) (xs :: Vec n1 a) -> False------ This function solves 'n1' and replaces every occurrence with its solution. A--- very limited number of solutions are currently recognized: only adds (such--- as in the example) will be solved.-elemExistentials :: HasCallStack => NormRewrite-elemExistentials (TransformContext is0 _) (Case scrut altsTy alts0) = do- tcm <- Lens.view tcCache-- alts1 <- mapM (go is0 tcm) alts0- caseOneAlt (Case scrut altsTy alts1)-- where- -- Eliminate free type variables if possible- go :: InScopeSet -> TyConMap -> (Pat, Term) -> NormalizeSession (Pat, Term)- go is2 tcm alt@(DataPat dc exts0 xs0, term0) =- case solveNonAbsurds tcm (mkVarSet exts0) (altEqs tcm alt) of- -- No equations solved:- [] -> return alt- -- One or more equations solved:- sols ->- changed =<< go is2 tcm (DataPat dc exts1 xs1, term1)- where- -- Substitute solution in existentials and applied types- is3 = extendInScopeSetList is2 exts0- xs1 = map (substTyInVar (extendTvSubstList (mkSubst is3) sols)) xs0- exts1 = substInExistentialsList is2 exts0 sols-- -- Substitute solution in term.- is4 = extendInScopeSetList is3 xs1- subst = extendTvSubstList (mkSubst is4) sols- term1 = substTm "Replacing tyVar due to solved eq" subst term0-- go _ _ alt = return alt--elemExistentials _ e = return e-{-# SCC elemExistentials #-}---- | Move a Case-decomposition from the subject of a Case-decomposition to the alternatives-caseCase :: HasCallStack => NormRewrite-caseCase (TransformContext is0 _) e@(Case (stripTicks -> Case scrut alts1Ty alts1) alts2Ty alts2)- = do- ty1Rep <- representableType <$> Lens.view typeTranslator- <*> Lens.view customReprs- <*> pure False- <*> Lens.view tcCache- <*> pure alts1Ty- if not ty1Rep- -- Deshadow to prevent accidental capture of free variables of inner- -- case. Imagine:- --- -- case (case a of {x -> x}) of {_ -> x}- --- -- 'x' is introduced the inner 'case' and used (as a free variable) in- -- the outer one. The goal of 'caseCase' is to rewrite cases such that- -- their subjects aren't cases. This is achieved by 'pushing' the outer- -- case to all the alternatives of the inner one. Naively doing so in- -- this example would cause an accidental capture:- --- -- case a of {x -> case x of {_ -> x}}- --- -- Suddenly, the 'x' in the alternative of the inner case statement- -- refers to the one introduced by the outer one, instead of being a- -- free variable. To prevent this, we deshadow the alternatives of the- -- original inner case. We now end up with:- --- -- case a of {x1 -> case x1 of {_ -> x}}- --- then let newAlts = map- (second (\altE -> Case altE alts2Ty alts2))- (map (deShadowAlt is0) alts1)- in changed $ Case scrut alts2Ty newAlts- else return e--caseCase _ e = return e-{-# SCC caseCase #-}---- | Inline function with a non-representable result if it's the subject--- of a Case-decomposition. It's a custom topdown traversal that -for efficiency--- reasons- does not explore alternative of cases whose subject triggered an--- 'inlineNonRepWorker'.-inlineNonRep :: HasCallStack => NormRewrite-inlineNonRep ctx0 e0@(Case {}) = do- r <- listen (inlineNonRepWorker e0)- case r of- (e1, Monoid.getAny -> True) ->- return e1- (~(Case subj0 typ alts), _) -> do- -- If a term _in_ the subject triggers 'inlineNonRepWorker', inline and- -- propagate might eliminate this case. We therefore don't explore the- -- alternatives. Note that this makes it substantially different from a- -- 'topdownSucR' transformation.- let- TransformContext inScope ctx1 = ctx0- ctx2 = TransformContext inScope (CaseScrut:ctx1)-- listen (inlineNonRep ctx2 subj0) >>= \case- (subj1, Monoid.getAny -> True) ->- return (Case subj1 typ alts)- (subj1, _) -> do- let (pats, rhss0) = unzip alts- rhss1 <- mapM (inlineNonRep ctx2) rhss0- pure (Case subj1 typ (zip pats rhss1))--inlineNonRep ctx e =- -- All non-case statements are simply traversed. TODO: are there other special- -- cases like 'Case' that would warrant an optimization like ^ ?- allR inlineNonRep ctx e-{-# SCC inlineNonRep #-}---- | Inline function with a non-representable result if it's the subject--- of a Case-decomposition. This worker function only tries the given term--- (i.e., it does not traverse it).------ It sets the changed flag in the NormalizeSession if it successfully inlines--- a binder.-inlineNonRepWorker :: HasCallStack => Term -> NormalizeSession Term-inlineNonRepWorker e@(Case scrut altsTy alts)- | (Var f, args,ticks) <- collectArgsTicks scrut- , isGlobalId f- = do- (cf,_) <- Lens.use curFun- isInlined <- zoomExtra (alreadyInlined f cf)- limit <- Lens.use (extra.inlineLimit)- tcm <- Lens.view tcCache- let- scrutTy = termType tcm scrut-- -- Constraint dictionary inlining always terminates, so we ignore the- -- usual inline safeguards.- notClassTy = not (isClassTy tcm scrutTy)- overLimit = notClassTy && (Maybe.fromMaybe 0 isInlined) > limit--- bodyMaybe <- lookupVarEnv f <$> Lens.use bindings- nonRepScrut <- not <$> (representableType <$> Lens.view typeTranslator- <*> Lens.view customReprs- <*> pure False- <*> Lens.view tcCache- <*> pure scrutTy)- case (nonRepScrut, bodyMaybe) of- (True, Just b) -> do- if overLimit then- trace ($(curLoc) ++ [I.i|- InlineNonRep: #{showPpr (varName f)} already inlined- #{limit} times in: #{showPpr (varName cf)}. The type of the subject- is:-- #{showPpr' def{displayTypes=True\} scrutTy}-- Function #{showPpr (varName cf)} will not reach a normal form and- compilation might fail.-- Run with '-fclash-inline-limit=N' to increase the inline limit to N.- |]) (return e)- else do- Monad.when notClassTy (zoomExtra (addNewInline f cf))-- let scrutBody0 = mkTicks (bindingTerm b) (mkInlineTick f : ticks)- let scrutBody1 = mkApps scrutBody0 args-- changed $ Case scrutBody1 altsTy alts- _ ->- return e--inlineNonRepWorker e = pure e-{-# SCC inlineNonRepWorker #-}---{--NOTE: caseOneAlt before caseCon'--When you put a bang on a signal argument:- f :: Signal d a -> _- f !x = ...-GHC generates a case like:- case x of- _ :- _ -> ...--When this f is inlined in an:- g = f (pure False)-And clash does its Signal d a ~ a thing we get:- g = case False of- _ :- _ -> ...-Because no pattern matches caseCon transforms this into- g = undefined--By trying caseOneAlt first clash can instead drop the case-and use the body of the single alternative.--}-caseCon :: HasCallStack => NormRewrite-caseCon = const caseOneAlt >-! caseCon'---- | Specialize a Case-decomposition (replace by the RHS of an alternative) if--- the subject is (an application of) a DataCon; or if there is only a single--- alternative that doesn't reference variables bound by the pattern.------ Note [CaseCon deshadow]------ Imagine:------ @--- case D (f a b) (g x y) of--- D a b -> h a--- @------ rewriting this to:------ @--- let a = f a b--- in h a--- @------ is very bad because the newly introduced let-binding now captures the free--- variable 'a' in 'f a b'.------ instead me must rewrite to:------ @--- let a1 = f a b--- in h a1--- @-caseCon' :: HasCallStack => NormRewrite-caseCon' ctx@(TransformContext is0 _) e@(Case subj ty alts) = do- tcm <- Lens.view tcCache- case collectArgsTicks subj of- -- The subject is an applied data constructor- (Data dc, args, ticks) -> case List.find (equalCon . fst) alts of- Just (DataPat _ tvs xs, altE) -> do- let- -- Create the substitution environment for all the existential- -- type variables.- exTysList = List.zipEqual tvs (drop (length (dcUnivTyVars dc)) (Either.rights args))- exTySubst = extendTvSubstList (mkSubst is0) exTysList- -- Apply the type-substitution in all the pattern variables, we need- -- to do this because we might use them as let-bindings later on,- -- and they should have the correct type.- xs1 = map (substTyInVar exTySubst) xs- -- Create an initial set of let-binders for all variables used in the- -- RHS of the alternative. We might later decide to substitute instead- -- of let-bind in case the RHS of the let-binder is work-free.- fvs = Lens.foldMapOf freeLocalIds unitVarSet altE- (binds,_) = List.partition ((`elemVarSet` fvs) . fst)- $ List.zipEqual xs1 (Either.lefts args)- binds1 = map (second (`mkTicks` ticks)) binds- altE1 <-- case binds1 of- [] ->- -- Apply the type-substitution for the existential type variables- pure (substTm "caseCon1" exTySubst altE)- _ -> do- -- See Note [CaseCon deshadow]- let- -- Only let-bind expression that perform work.- is1 = extendInScopeSetList (extendInScopeSetList is0 tvs) xs1- ((is3,substIds),binds2) <- List.mapAccumLM newBinder (is1,[]) binds1- let- -- Create a substitution for all the existential type variables- -- and the work-free expressions- subst = extendIdSubstList- (extendTvSubstList (mkSubst is3) exTysList)- substIds- body = substTm "caseCon1" subst altE- case Maybe.catMaybes binds2 of- [] -> pure body- binds3 -> pure (Letrec binds3 body)- changed altE1- _ -> case alts of- -- In Core, default patterns always come first, so we match against- -- that if there is one, and we couldn't match with any of the data- -- patterns.- ((DefaultPat,altE):_) -> changed altE- _ -> changed (undefinedTm ty)- where- -- Check whether the pattern matches the data constructor- equalCon (DataPat dcPat _ _) = dcTag dc == dcTag dcPat- equalCon _ = False-- -- Decide whether the applied arguments of the data constructor should- -- be let-bound, or substituted into the alternative. We decide this- -- based on the fact on whether the argument has the potential to make- -- the circuit larger than needed if we were to duplicate that argument.- newBinder (isN0, substN) (x, arg) = do- bndrs <- Lens.use bindings- isWorkFree workFreeBinders bndrs arg >>= \case- True -> pure ((isN0, (x, arg):substN), Nothing)- False ->- let- x' = uniqAway isN0 x- isN1 = extendInScopeSet isN0 x'- in- pure ((isN1, (x, Var x'):substN), Just (x', arg))--- -- The subject is a literal- (Literal l,_,_) -> case List.find (equalLit . fst) alts of- Just (LitPat _,altE) -> changed altE- _ -> matchLiteralContructor e l alts- where- equalLit (LitPat l') = l == l'- equalLit _ = False--- -- The subject is an applied primitive- (Prim _,_,_) ->- -- We try to reduce the applied primitive to WHNF- whnfRW True ctx subj $ \ctx1 subj1 -> case collectArgsTicks subj1 of- -- WHNF of subject is a literal, try `caseCon` with that- (Literal l,_,_) -> caseCon ctx1 (Case (Literal l) ty alts)- -- WHNF of subject is a data-constructor, try `caseCon` with that- (Data _,_,_) -> caseCon ctx1 (Case subj1 ty alts)-#if MIN_VERSION_ghc(8,2,2)- -- WHNF of subject is _|_, in the form of `absentError`: that means that- -- the entire case-expression is evaluates to _|_- (Prim pInfo,_:msgOrCallStack:_,ticks)- | primName pInfo == "Control.Exception.Base.absentError" ->- let e1 = mkApps (mkTicks (Prim pInfo) ticks)- [Right ty,msgOrCallStack]- in changed e1-#endif- -- WHNF of subject is _|_, in the form of `absentError`, `patError`,- -- or `undefined`: that means the entire case-expression is _|_- (Prim pInfo,repTy:_:msgOrCallStack:_,ticks)- | primName pInfo `elem` ["Control.Exception.Base.patError"-#if !MIN_VERSION_ghc(8,2,2)- ,"Control.Exception.Base.absentError"-#endif- ,"GHC.Err.undefined"] ->- let e1 = mkApps (mkTicks (Prim pInfo) ticks)- [repTy,Right ty,msgOrCallStack]- in changed e1- -- WHNF of subject is _|_, in the form of our internal _|_-values: that- -- means the entire case-expression is _|_- (Prim pInfo,[_],ticks)- | primName pInfo `elem` [ "Clash.Transformations.undefined"- , "Clash.GHC.Evaluator.undefined"- , "EmptyCase"] ->- let e1 = mkApps (mkTicks (Prim pInfo) ticks) [Right ty]- in changed e1- (Prim pInfo,_:callStack:msg:_,_)- | primName pInfo == "Clash.XException.errorX"- -> let e1 = mkApps (Prim pInfo) [Right ty,callStack,msg]- in changed e1- -- WHNF of subject is non of the above, so either a variable reference,- -- or a primitive for which the evaluator doesn't have any evaluation- -- rules.- _ -> do- let subjTy = termType tcm subj- tran <- Lens.view typeTranslator- reprs <- Lens.view customReprs- case (`evalState` mempty) (coreTypeToHWType tran reprs tcm subjTy) of- Right (FilteredHWType (Void (Just hty)) _areVoids)- | hty `elem` [BitVector 0, Unsigned 0, Signed 0, Index 1]- -- If we know that the type of the subject is zero-bits wide and- -- one of the Clash number types. Then the only valid alternative is- -- the one that can match on the literal "0", so try 'caseCon' with- -- that.- -> caseCon ctx1 (Case (Literal (IntegerLiteral 0)) ty alts)- _ -> do- let ret = caseOneAlt e- -- Otherwise check whether the entire case-expression has a single- -- alternative, and pick that one.- lvl <- Lens.view dbgLevel- if lvl > DebugNone then do- let subjIsConst = isConstant subj- -- In debug mode we always report missing evaluation rules for the- -- primitive evaluator- traceIf (lvl > DebugNone && subjIsConst)- ("Irreducible constant as case subject: " ++ showPpr subj ++- "\nCan be reduced to: " ++ showPpr subj1) ret- else- ret--- -- The subject is a variable- (Var v, [], _) | isNum0 (varType v) ->- -- If we know that the type of the subject is zero-bits wide and- -- one of the Clash number types. Then the only valid alternative is- -- the one that can match on the literal "0", so try 'caseCon' with- -- that.- caseCon ctx (Case (Literal (IntegerLiteral 0)) ty alts)- where- isNum0 (tyView -> TyConApp (nameOcc -> tcNm) [arg])- | tcNm `elem`- ["Clash.Sized.Internal.BitVector.BitVector"- ,"Clash.Sized.Internal.Unsigned.Unsigned"- ,"Clash.Sized.Internal.Signed.Signed"- ]- = isLitX 0 arg- | tcNm ==- "Clash.Sized.Internal.Index.Index"- = isLitX 1 arg- isNum0 (coreView1 tcm -> Just t) = isNum0 t- isNum0 _ = False-- isLitX n (LitTy (NumTy m)) = n == m- isLitX n (coreView1 tcm -> Just t) = isLitX n t- isLitX _ _ = False-- -- Otherwise check whether the entire case-expression has a single- -- alternative, and pick that one.- _ -> caseOneAlt e--caseCon' _ e = return e-{-# SCC caseCon' #-}--{- [Note: Name re-creation]-The names of heap bound variables are safely generate with mkUniqSystemId in Clash.Core.Evaluator.newLetBinding.-But only their uniqs end up in the heap, not the complete names.-So we use mkUnsafeSystemName to recreate the same Name.--}--matchLiteralContructor- :: Term- -> Literal- -> [(Pat,Term)]- -> NormalizeSession Term-matchLiteralContructor c (IntegerLiteral l) alts = go (reverse alts)- where- go [(DefaultPat,e)] = changed e- go ((DataPat dc [] xs,e):alts')- | dcTag dc == 1- , l >= ((-2)^(63::Int)) && l < 2^(63::Int)- = let fvs = Lens.foldMapOf freeLocalIds unitVarSet e- (binds,_) = List.partition ((`elemVarSet` fvs) . fst)- $ List.zipEqual xs [Literal (IntLiteral l)]- e' = case binds of- [] -> e- _ -> Letrec binds e- in changed e'- | dcTag dc == 2- , l >= 2^(63::Int)-#if MIN_VERSION_base(4,15,0)- = let !(IP ba) = l-#else- = let !(Jp# !(BN# ba)) = l-#endif- ba' = BA.ByteArray ba- fvs = Lens.foldMapOf freeLocalIds unitVarSet e- (binds,_) = List.partition ((`elemVarSet` fvs) . fst)- $ List.zipEqual xs [Literal (ByteArrayLiteral ba')]- e' = case binds of- [] -> e- _ -> Letrec binds e- in changed e'- | dcTag dc == 3- , l < ((-2)^(63::Int))-#if MIN_VERSION_base(4,15,0)- = let !(IN ba) = l-#else- = let !(Jn# !(BN# ba)) = l-#endif- ba' = BA.ByteArray ba- fvs = Lens.foldMapOf freeLocalIds unitVarSet e- (binds,_) = List.partition ((`elemVarSet` fvs) . fst)- $ List.zipEqual xs [Literal (ByteArrayLiteral ba')]- e' = case binds of- [] -> e- _ -> Letrec binds e- in changed e'- | otherwise- = go alts'- go ((LitPat l', e):alts')- | IntegerLiteral l == l'- = changed e- | otherwise- = go alts'- go _ = error $ $(curLoc) ++ "Report as bug: caseCon error: " ++ showPpr c--matchLiteralContructor c (NaturalLiteral l) alts = go (reverse alts)- where- go [(DefaultPat,e)] = changed e- go ((DataPat dc [] xs,e):alts')- | dcTag dc == 1- , l >= 0 && l < 2^(64::Int)- = let fvs = Lens.foldMapOf freeLocalIds unitVarSet e- (binds,_) = List.partition ((`elemVarSet` fvs) . fst)- $ List.zipEqual xs [Literal (WordLiteral l)]- e' = case binds of- [] -> e- _ -> Letrec binds e- in changed e'- | dcTag dc == 2- , l >= 2^(64::Int)-#if MIN_VERSION_base(4,15,0)- = let !(IP ba) = l-#else- = let !(Jp# !(BN# ba)) = l-#endif- ba' = BA.ByteArray ba- fvs = Lens.foldMapOf freeLocalIds unitVarSet e- (binds,_) = List.partition ((`elemVarSet` fvs) . fst)- $ List.zipEqual xs [Literal (ByteArrayLiteral ba')]- e' = case binds of- [] -> e- _ -> Letrec binds e- in changed e'- | otherwise- = go alts'- go ((LitPat l', e):alts')- | NaturalLiteral l == l'- = changed e- | otherwise- = go alts'- go _ = error $ $(curLoc) ++ "Report as bug: caseCon error: " ++ showPpr c--matchLiteralContructor _ _ ((DefaultPat,e):_) = changed e-matchLiteralContructor c _ _ =- error $ $(curLoc) ++ "Report as bug: caseCon error: " ++ showPpr c-{-# SCC matchLiteralContructor #-}--caseOneAlt :: Term -> RewriteMonad extra Term-caseOneAlt e@(Case _ _ [(pat,altE)]) = case pat of- DefaultPat -> changed altE- LitPat _ -> changed altE- DataPat _ tvs xs- | (coerce tvs ++ coerce xs) `localVarsDoNotOccurIn` altE- -> changed altE- | otherwise- -> return e--caseOneAlt (Case _ _ alts@((pat,alt):_:_))- | all ((== alt) . snd) (tail alts)- , (tvs,xs) <- patIds pat- , (coerce tvs ++ coerce xs) `localVarsDoNotOccurIn` alt- = changed alt--caseOneAlt e = return e-{-# SCC caseOneAlt #-}---- | Bring an application of a DataCon or Primitive in ANF, when the argument is--- is considered non-representable-nonRepANF :: HasCallStack => NormRewrite-nonRepANF ctx@(TransformContext is0 _) e@(App appConPrim arg)- | (conPrim, _) <- collectArgs e- , isCon conPrim || isPrim conPrim- = do- untranslatable <- isUntranslatable False arg- case (untranslatable,stripTicks arg) of- (True,Letrec binds body) ->- -- This is a situation similar to Note [CaseLet deshadow]- let (binds1,body1) = deshadowLetExpr is0 binds body- in changed (Letrec binds1 (App appConPrim body1))- (True,Case {}) -> specializeNorm ctx e- (True,Lam {}) -> specializeNorm ctx e- (True,TyLam {}) -> specializeNorm ctx e- _ -> return e--nonRepANF _ e = return e-{-# SCC nonRepANF #-}---- | Ensure that top-level lambda's eventually bind a let-expression of which--- the body is a variable-reference.-topLet :: HasCallStack => NormRewrite-topLet (TransformContext is0 ctx) e- | all (\c -> isLambdaBodyCtx c || isTickCtx c) ctx && not (isLet e) && not (isTick e)- = do- untranslatable <- isUntranslatable False e- if untranslatable- then return e- else do tcm <- Lens.view tcCache- argId <- mkTmBinderFor is0 tcm (mkUnsafeSystemName "result" 0) e- changed (Letrec [(argId, e)] (Var argId))- where- isTick Tick{} = True- isTick _ = False--topLet (TransformContext is0 ctx) e@(Letrec binds body)- | all (\c -> isLambdaBodyCtx c || isTickCtx c) ctx- = do- let localVar = isLocalVar body- untranslatable <- isUntranslatable False body- if localVar || untranslatable- then return e- else do- tcm <- Lens.view tcCache- let is2 = extendInScopeSetList is0 (map fst binds)- argId <- mkTmBinderFor is2 tcm (mkUnsafeSystemName "result" 0) body- changed (Letrec (binds ++ [(argId,body)]) (Var argId))--topLet _ e = return e-{-# SCC topLet #-}---- Misc rewrites---- | Remove unused let-bindings-deadCode :: HasCallStack => NormRewrite-deadCode _ e@(Letrec binds body) =- case removeUnusedBinders binds body of- Just t -> changed t- Nothing -> return e-deadCode _ e = return e-{-# SCC deadCode #-}--removeUnusedExpr :: HasCallStack => NormRewrite-removeUnusedExpr _ e@(collectArgsTicks -> (p@(Prim pInfo),args,ticks)) = do- bbM <- HashMap.lookup (primName pInfo) <$> Lens.use (extra.primitives)- let- usedArgs0 =- case Monad.join (extractPrim <$> bbM) of- Just (BlackBoxHaskell{usedArguments}) ->- case usedArguments of- UsedArguments used -> Just used- IgnoredArguments ignored -> Just ([0..length args - 1] \\ ignored)- Just (BlackBox pNm _ _ _ _ _ _ _ _ _ inc r ri templ) -> Just $- if | isFromInt pNm -> [0,1,2]- | primName pInfo `elem` [ "Clash.Annotations.BitRepresentation.Deriving.dontApplyInHDL"- , "Clash.Sized.Vector.splitAt"- ] -> [0,1]- | otherwise -> concat [ concatMap getUsedArguments r- , concatMap getUsedArguments ri- , getUsedArguments templ- , concatMap (getUsedArguments . snd) inc ]- _ ->- Nothing-- case usedArgs0 of- Nothing ->- return e- Just usedArgs1 -> do- tcm <- Lens.view tcCache- (args1, Monoid.getAny -> hasChanged) <- listen (go tcm 0 usedArgs1 args)- if hasChanged then- return (mkApps (mkTicks p ticks) args1)- else- return e-- where- arity = length . Either.rights . fst $ splitFunForallTy (primType pInfo)-- go _ _ _ [] = return []- go tcm !n used (Right ty:args') = do- args'' <- go tcm n used args'- return (Right ty : args'')- go tcm !n used (Left tm : args') = do- args'' <- go tcm (n+1) used args'- case tm of- TyApp (Prim p0) _- | primName p0 == "Clash.Transformations.removedArg"- -> return (Left tm : args'')- _ -> do- let ty = termType tcm tm- p' = removedTm ty- if n < arity && n `notElem` used- then changed (Left p' : args'')- else return (Left tm : args'')--removeUnusedExpr _ e@(Case _ _ [(DataPat _ [] xs,altExpr)]) =- if xs `localIdsDoNotOccurIn` altExpr- then changed altExpr- else return e---- Replace any expression that creates a Vector of size 0 within the application--- of the Cons constructor, by the Nil constructor.-removeUnusedExpr _ e@(collectArgsTicks -> (Data dc, [_,Right aTy,Right nTy,_,Left a,Left nil],ticks))- | nameOcc (dcName dc) == "Clash.Sized.Vector.Cons"- = do- tcm <- Lens.view tcCache- case runExcept (tyNatSize tcm nTy) of- Right 0- | (con, _) <- collectArgs nil- , not (isCon con)- -> let eTy = termType tcm e- (TyConApp vecTcNm _) = tyView eTy- (Just vecTc) = lookupUniqMap vecTcNm tcm- [nilCon,consCon] = tyConDataCons vecTc- v = mkTicks (mkVec nilCon consCon aTy 1 [a]) ticks- in changed v- _ -> return e--removeUnusedExpr _ e = return e-{-# SCC removeUnusedExpr #-}---- | Inline let-bindings when the RHS is either a local variable reference or--- is constant (except clock or reset generators)-bindConstantVar :: HasCallStack => NormRewrite-bindConstantVar = inlineBinders test- where- test _ (i,stripTicks -> e) = case isLocalVar e of- -- Don't inline `let x = x in x`, it throws us in an infinite loop- True -> return (i `localIdDoesNotOccurIn` e)- _ -> do- tcm <- Lens.view tcCache- case isWorkFreeIsh tcm e of- True -> Lens.use (extra.inlineConstantLimit) >>= \case- 0 -> return True- n -> return (termSize e <= n)- _ -> return False-{-# SCC bindConstantVar #-}---- | Push a cast over a case into it's alternatives.-caseCast :: HasCallStack => NormRewrite-caseCast _ (Cast (stripTicks -> Case subj ty alts) ty1 ty2) = do- let alts' = map (\(p,e) -> (p, Cast e ty1 ty2)) alts- changed (Case subj ty alts')-caseCast _ e = return e-{-# SCC caseCast #-}----- | Push a cast over a Letrec into it's body-letCast :: HasCallStack => NormRewrite-letCast _ (Cast (stripTicks -> Letrec binds body) ty1 ty2) =- changed $ Letrec binds (Cast body ty1 ty2)-letCast _ e = return e-{-# SCC letCast #-}----- | Push cast over an argument to a function into that function------ This is done by specializing on the casted argument.--- Example:--- @--- y = f (cast a)--- where f x = g x--- @--- transforms to:--- @--- y = f' a--- where f' x' = (\x -> g x) (cast x')--- @------ The reason d'etre for this transformation is that we hope to end up with--- and expression where two casts are "back-to-back" after which we can--- eliminate them in 'eliminateCastCast'.-argCastSpec :: HasCallStack => NormRewrite-argCastSpec ctx e@(App f (stripTicks -> Cast e' _ _))- -- Don't specialise when the arguments are casts-of-casts, these casts-of-casts- -- will be eliminated by 'eliminateCastCast' during the normalization of the- -- "current" function. We thus prevent the unnecessary introduction of a- -- specialized version of 'f'.- | not (isCast e')- -- We can only push casts into global binders- , (Var g, _) <- collectArgs f- , isGlobalId g = do- bndrs <- Lens.use bindings- isWorkFree workFreeBinders bndrs e' >>= \case- True -> go- False -> warn go- where- go = specializeNorm ctx e- warn = trace (unwords- [ "WARNING:", $(curLoc), "specializing a function on a non work-free"- , "cast. Generated HDL implementation might contain duplicate work."- , "Please report this as a bug.", "\n\nExpression where this occured:"- , "\n\n" ++ showPpr e- ])-argCastSpec _ e = return e-{-# SCC argCastSpec #-}---- | Only inline casts that just contain a 'Var', because these are guaranteed work-free.--- These are the result of the 'splitCastWork' transformation.-inlineCast :: HasCallStack => NormRewrite-inlineCast = inlineBinders test- where- test _ (_, (Cast (stripTicks -> Var {}) _ _)) = return True- test _ _ = return False-{-# SCC inlineCast #-}---- | Eliminate two back to back casts where the type going in and coming out are the same------ @--- (cast :: b -> a) $ (cast :: a -> b) x ==> x--- @-eliminateCastCast :: HasCallStack => NormRewrite-eliminateCastCast _ c@(Cast (stripTicks -> Cast e tyA tyB) tyB' tyC) = do- tcm <- Lens.view tcCache- let ntyA = normalizeType tcm tyA- ntyB = normalizeType tcm tyB- ntyB' = normalizeType tcm tyB'- ntyC = normalizeType tcm tyC- if ntyB == ntyB' && ntyA == ntyC then changed e- else throwError- where throwError = do- (nm,sp) <- Lens.use curFun- throw (ClashException sp ($(curLoc) ++ showPpr nm- ++ ": Found 2 nested casts whose types don't line up:\n"- ++ showPpr c)- Nothing)--eliminateCastCast _ e = return e-{-# SCC eliminateCastCast #-}---- | Make a cast work-free by splitting the work of to a separate binding------ @--- let x = cast (f a b)--- ==>--- let x = cast x'--- x' = f a b--- @-splitCastWork :: HasCallStack => NormRewrite-splitCastWork ctx@(TransformContext is0 _) unchanged@(Letrec vs e') = do- (vss', Monoid.getAny -> hasChanged) <- listen (mapM (splitCastLetBinding is0) vs)- let vs' = concat vss'- if hasChanged then changed (Letrec vs' e')- else return unchanged- where- splitCastLetBinding- :: InScopeSet- -> LetBinding- -> RewriteMonad extra [LetBinding]- splitCastLetBinding isN x@(nm, e) = case stripTicks e of- Cast (Var {}) _ _ -> return [x] -- already work-free- Cast (Cast {}) _ _ -> return [x] -- casts will be eliminated- Cast e0 ty1 ty2 -> do- tcm <- Lens.view tcCache- nm' <- mkTmBinderFor isN tcm (mkDerivedName ctx (nameOcc $ varName nm)) e0- changed [(nm',e0)- ,(nm, Cast (Var nm') ty1 ty2)- ]- _ -> return [x]--splitCastWork _ e = return e-{-# SCC splitCastWork #-}----- | Inline work-free functions, i.e. fully applied functions that evaluate to--- a constant-inlineWorkFree :: HasCallStack => NormRewrite-inlineWorkFree _ e@(collectArgsTicks -> (Var f,args@(_:_),ticks))- = do- tcm <- Lens.view tcCache- let eTy = termType tcm e- argsHaveWork <- or <$> mapM (either expressionHasWork- (const (pure False)))- args- untranslatable <- isUntranslatableType True eTy- topEnts <- Lens.view topEntities- let isSignal = isSignalType tcm eTy- let lv = isLocalId f- let isTopEnt = elemVarSet f topEnts- if untranslatable || isSignal || argsHaveWork || lv || isTopEnt- then return e- else do- bndrs <- Lens.use bindings- case lookupVarEnv f bndrs of- -- Don't inline recursive expressions- Just b -> do- isRecBndr <- isRecursiveBndr f- if isRecBndr- then return e- else do- let tm = mkTicks (bindingTerm b) (mkInlineTick f : ticks)- changed $ mkApps tm args-- _ -> return e- where- -- an expression is has work when it contains free local variables,- -- or has a Signal type, i.e. it does not evaluate to a work-free- -- constant.- expressionHasWork e' = do- let fvIds = Lens.toListOf freeLocalIds e'- tcm <- Lens.view tcCache- let e'Ty = termType tcm e'- isSignal = isSignalType tcm e'Ty- return (not (null fvIds) || isSignal)--inlineWorkFree _ e@(Var f) = do- tcm <- Lens.view tcCache- let fTy = varType f- closed = not (isPolyFunCoreTy tcm fTy)- isSignal = isSignalType tcm fTy- untranslatable <- isUntranslatableType True fTy- topEnts <- Lens.view topEntities- let gv = isGlobalId f- if closed && f `notElemVarSet` topEnts && not untranslatable && not isSignal && gv- then do- bndrs <- Lens.use bindings- case lookupVarEnv f bndrs of- -- Don't inline recursive expressions- Just top -> do- isRecBndr <- isRecursiveBndr f- if isRecBndr- then return e- else do- let topB = bindingTerm top- sizeLimit <- Lens.use (extra.inlineWFCacheLimit)- -- caching only worth it from a certain size onwards, otherwise- -- the caching mechanism itself brings more of an overhead.- if termSize topB < sizeLimit then- changed topB- else do- b <- normalizeTopLvlBndr False f top- changed (bindingTerm b)- _ -> return e- else return e--inlineWorkFree _ e = return e-{-# SCC inlineWorkFree #-}---- | Inline small functions-inlineSmall :: HasCallStack => NormRewrite-inlineSmall _ e@(collectArgsTicks -> (Var f,args,ticks)) = do- untranslatable <- isUntranslatable True e- topEnts <- Lens.view topEntities- let lv = isLocalId f- if untranslatable || f `elemVarSet` topEnts || lv- then return e- else do- bndrs <- Lens.use bindings- sizeLimit <- Lens.use (extra.inlineFunctionLimit)- case lookupVarEnv f bndrs of- -- Don't inline recursive expressions- Just b -> do- isRecBndr <- isRecursiveBndr f- if not isRecBndr && bindingSpec b /= NoInline && termSize (bindingTerm b) < sizeLimit- then do- let tm = mkTicks (bindingTerm b) (mkInlineTick f : ticks)- changed $ mkApps tm args- else return e-- _ -> return e--inlineSmall _ e = return e-{-# SCC inlineSmall #-}---- | Specialise functions on arguments which are constant, except when they--- are clock, reset generators.-constantSpec :: HasCallStack => NormRewrite-constantSpec ctx@(TransformContext is0 tfCtx) e@(App e1 e2)- | (Var {}, args) <- collectArgs e1- , (_, []) <- Either.partitionEithers args- , null $ Lens.toListOf termFreeTyVars e2- = do specInfo<- constantSpecInfo ctx e2- if csrFoundConstant specInfo then- let newBindings = csrNewBindings specInfo in- if null newBindings then- -- Whole of e2 is constant- specializeNorm ctx (App e1 e2)- else do- -- Parts of e2 are constant- let is1 = extendInScopeSetList is0 (fst <$> csrNewBindings specInfo)- (body, isSpec) <- listen $ specializeNorm- (TransformContext is1 tfCtx)- (App e1 (csrNewTerm specInfo))-- if Monoid.getAny isSpec- then changed (Letrec newBindings body)- else return e- else- -- e2 has no constant parts- return e-constantSpec _ e = return e-{-# SCC constantSpec #-}----- Experimental---- | Propagate arguments of application inwards; except for 'Lam' where the--- argument becomes let-bound. 'appPropFast' tries to propagate as many arguments--- as possible, down as many levels as possible; and should be called in a--- top-down traversal.------ The idea is that this reduces the number of traversals, which hopefully leads--- to shorter compile times.------ Note [AppProp no shadowing]------ Case 1.------ Imagine:------ @--- (case x of--- D a b -> h a) (f x y)--- @------ rewriting this to:------ @--- let b = f x y--- in case x of--- D a b -> h a b--- @------ is very bad because 'b' in 'h a b' is now bound by the pattern instead of the--- newly introduced let-binding------ instead me must deshadow w.r.t. the new variable and rewrite to:------ @--- let b = f x y--- in case x of--- D a b1 -> h a b--- @------ Case 2.------ Imagine------ @--- (\x -> e) u--- @------ where @u@ has a free variable named @x@, rewriting this to:------ @--- let x = u--- in e--- @------ would be very bad, because the let-binding suddenly captures the free--- variable in @u@. To prevent this from happening we over-approximate and check--- whether @x@ is in the current InScopeSet, and deshadow if that's the case,--- i.e. we then rewrite to:------ let x1 = u--- in e [x:=x1]------ Case 3.------ The same for:------ @--- (let x = w in e) u--- @------ where @u@ again has a free variable @x@, rewriting this to:------ @--- let x = w in (e u)--- @------ would be bad because the let-binding now captures the free variable in @u@.------ To prevent this from happening, we unconditionally deshadow the function part--- of the application w.r.t. the free variables in the argument part of the--- application. It is okay to over-approximate in this case and deshadow w.r.t--- the current InScopeSet.-appPropFast :: HasCallStack => NormRewrite-appPropFast ctx@(TransformContext is _) = \case- e@App {}- | let (fun,args,ticks) = collectArgsTicks e- -> do (eN,hasChanged) <- listen (go is (deShadowTerm is fun) args ticks)- if Monoid.getAny hasChanged then return eN else return e- e@TyApp {}- | let (fun,args,ticks) = collectArgsTicks e- -> do (eN,hasChanged) <- listen (go is (deShadowTerm is fun) args ticks)- if Monoid.getAny hasChanged then return eN else return e- e -> return e- where- go :: InScopeSet -> Term -> [Either Term Type] -> [TickInfo]- -> NormalizeSession Term- go is0 (collectArgsTicks -> (fun,args0@(_:_),ticks0)) args1 ticks1 =- go is0 fun (args0 ++ args1) (ticks0 ++ ticks1)-- go is0 (Lam v e) (Left arg:args) ticks = do- setChanged- bndrs <- Lens.use bindings- orM [pure (isVar arg), isWorkFree workFreeBinders bndrs arg] >>= \case- True ->- let subst = extendIdSubst (mkSubst is0) v arg in- (`mkTicks` ticks) <$> go is0 (substTm "appPropFast.AppLam" subst e) args []- False ->- let is1 = extendInScopeSet is0 v in- Letrec [(v, arg)] <$> go is1 (deShadowTerm is1 e) args ticks-- go is0 (Letrec vs e) args@(_:_) ticks = do- setChanged- let vbs = map fst vs- is1 = extendInScopeSetList is0 vbs- -- XXX: 'vs' should already be deshadowed w.r.t. 'is0'- Letrec vs <$> go is1 e args ticks-- go is0 (TyLam tv e) (Right t:args) ticks = do- setChanged- let subst = extendTvSubst (mkSubst is0) tv t- (`mkTicks` ticks) <$> go is0 (substTm "appPropFast.TyAppTyLam" subst e) args []-- go is0 (Case scrut ty0 alts) args0@(_:_) ticks = do- setChanged- let isA1 = unionInScope- is0- ((mkInScopeSet . mkVarSet . concatMap (patVars . fst)) alts)- (ty1,vs,args1) <- goCaseArg isA1 ty0 [] args0- case vs of- [] -> (`mkTicks` ticks) . Case scrut ty1 <$> mapM (goAlt is0 args1) alts- _ -> do- let vbs = map fst vs- is1 = extendInScopeSetList is0 vbs- alts1 = map (deShadowAlt is1) alts- Letrec vs . (`mkTicks` ticks) . Case scrut ty1 <$> mapM (goAlt is1 args1) alts1-- go is0 (Tick sp e) args ticks = do- setChanged- go is0 e args (sp:ticks)-- go _ fun args ticks = return (mkApps (mkTicks fun ticks) args)-- goAlt is0 args0 (p,e) = do- let (tvs,ids) = patIds p- is1 = extendInScopeSetList (extendInScopeSetList is0 tvs) ids- (p,) <$> go is1 e args0 []-- goCaseArg isA ty0 ls0 (Right t:args0) = do- tcm <- Lens.view tcCache- let ty1 = piResultTy tcm ty0 t- (ty2,ls1,args1) <- goCaseArg isA ty1 ls0 args0- return (ty2,ls1,Right t:args1)-- goCaseArg isA0 ty0 ls0 (Left arg:args0) = do- tcm <- Lens.view tcCache- bndrs <- Lens.use bindings- let argTy = termType tcm arg- ty1 = applyFunTy tcm ty0 argTy- orM [pure (isVar arg), isWorkFree workFreeBinders bndrs arg] >>= \case- True -> do- (ty2,ls1,args1) <- goCaseArg isA0 ty1 ls0 args0- return (ty2,ls1,Left arg:args1)- False -> do- boundArg <- mkTmBinderFor isA0 tcm (mkDerivedName ctx "app_arg") arg- let isA1 = extendInScopeSet isA0 boundArg- (ty2,ls1,args1) <- goCaseArg isA1 ty1 ls0 args0- return (ty2,(boundArg,arg):ls1,Left (Var boundArg):args1)-- goCaseArg _ ty ls [] = return (ty,ls,[])-{-# SCC appPropFast #-}---- | Flatten ridiculous case-statements generated by GHC------ For case-statements in haskell of the form:------ @--- f :: Unsigned 4 -> Unsigned 4--- f x = case x of--- 0 -> 3--- 1 -> 2--- 2 -> 1--- 3 -> 0--- @------ GHC generates Core that looks like:------ @--- f = \(x :: Unsigned 4) -> case x == fromInteger 3 of--- False -> case x == fromInteger 2 of--- False -> case x == fromInteger 1 of--- False -> case x == fromInteger 0 of--- False -> error "incomplete case"--- True -> fromInteger 3--- True -> fromInteger 2--- True -> fromInteger 1--- True -> fromInteger 0--- @------ Which would result in a priority decoder circuit where a normal decoder--- circuit was desired.------ This transformation transforms the above Core to the saner:------ @--- f = \(x :: Unsigned 4) -> case x of--- _ -> error "incomplete case"--- 0 -> fromInteger 3--- 1 -> fromInteger 2--- 2 -> fromInteger 1--- 3 -> fromInteger 0--- @-caseFlat :: HasCallStack => NormRewrite-caseFlat _ e@(Case (collectEqArgs -> Just (scrut',_)) ty _)- = do- case collectFlat scrut' e of- Just alts' -> changed (Case scrut' ty (last alts' : init alts'))- Nothing -> return e--caseFlat _ e = return e-{-# SCC caseFlat #-}--collectFlat :: Term -> Term -> Maybe [(Pat,Term)]-collectFlat scrut (Case (collectEqArgs -> Just (scrut', val)) _ty [lAlt,rAlt])- | scrut' == scrut- = case collectArgs val of- (Prim p,args') | isFromInt (primName p) ->- go (last args')- (Data dc,args') | nameOcc (dcName dc) == "GHC.Types.I#" ->- go (last args')- _ -> Nothing- where- go (Left (Literal i)) = case (lAlt,rAlt) of- ((pl,el),(pr,er))- | isFalseDcPat pl || isTrueDcPat pr ->- case collectFlat scrut el of- Just alts' -> Just ((LitPat i, er) : alts')- Nothing -> Just [(LitPat i, er)- ,(DefaultPat, el)- ]- | otherwise ->- case collectFlat scrut er of- Just alts' -> Just ((LitPat i, el) : alts')- Nothing -> Just [(LitPat i, el)- ,(DefaultPat, er)- ]- go _ = Nothing-- isFalseDcPat (DataPat p _ _)- = ((== "GHC.Types.False") . nameOcc . dcName) p- isFalseDcPat _ = False-- isTrueDcPat (DataPat p _ _)- = ((== "GHC.Types.True") . nameOcc . dcName) p- isTrueDcPat _ = False--collectFlat _ _ = Nothing-{-# SCC collectFlat #-}--collectEqArgs :: Term -> Maybe (Term,Term)-collectEqArgs (collectArgsTicks -> (Prim p, args, ticks))- | nm == "Clash.Sized.Internal.BitVector.eq#"- = let [_,_,Left scrut,Left val] = args- in Just (mkTicks scrut ticks,val)- | nm == "Clash.Sized.Internal.Index.eq#" ||- nm == "Clash.Sized.Internal.Signed.eq#" ||- nm == "Clash.Sized.Internal.Unsigned.eq#"- = let [_,Left scrut,Left val] = args- in Just (mkTicks scrut ticks,val)- | nm == "Clash.Transformations.eqInt"- = let [Left scrut,Left val] = args- in Just (mkTicks scrut ticks,val)- where- nm = primName p--collectEqArgs _ = Nothing--type NormRewriteW = Transform (StateT ([LetBinding],InScopeSet) (RewriteMonad NormalizeState))---- | See Note [ANF InScopeSet]-tellBinders :: Monad m => [LetBinding] -> StateT ([LetBinding],InScopeSet) m ()-tellBinders bs = modify ((bs ++) *** (`extendInScopeSetList` (map fst bs)))---- | See Note [ANF InScopeSet]; only extends the inscopeset-notifyBinders :: Monad m => [LetBinding] -> StateT ([LetBinding],InScopeSet) m ()-notifyBinders bs = modify (second (`extendInScopeSetList` (map fst bs)))---- | Is the given type IO-like-isSimIOTy- :: TyConMap- -> Type- -- ^ Type to check for IO-likeness- -> Bool-isSimIOTy tcm ty = case tyView (coreView tcm ty) of- TyConApp tcNm args- | nameOcc tcNm == "Clash.Explicit.SimIO.SimIO"- -> True- | nameOcc tcNm == "GHC.Prim.(#,#)"- , [_,_,st,_] <- args- -> isStateTokenTy tcm st- FunTy _ res -> isSimIOTy tcm res- _ -> False---- | Is the given type the state token-isStateTokenTy- :: TyConMap- -> Type- -- ^ Type to check for state tokenness- -> Bool-isStateTokenTy tcm ty = case tyView (coreView tcm ty) of- TyConApp tcNm _ -> nameOcc tcNm == "GHC.Prim.State#"- _ -> False---- | Turn an expression into a modified ANF-form. As opposed to standard ANF,--- constants do not become let-bound.-makeANF :: HasCallStack => NormRewrite-makeANF (TransformContext is0 ctx) (Lam bndr e) = do- e' <- makeANF (TransformContext (extendInScopeSet is0 bndr)- (LamBody bndr:ctx))- e- return (Lam bndr e')--makeANF _ e@(TyLam {}) = return e--makeANF ctx@(TransformContext is0 _) e0- = do- -- We need to freshen all binders in `e` because we're shuffling them around- -- into a single let-binder, because even when binders don't shadow, they- -- don't have to be unique within an expression. And so lifting them all- -- to a single let-binder will cause issues when they're not unique.- --- -- We cannot make freshening part of collectANF, because when we generate- -- new binders, we need to make sure those names do not conflict with _any_- -- of the existing binders in the expression.- --- -- See also Note [ANF InScopeSet]- let (is2,e1) = freshenTm is0 e0- ((e2,(bndrs,_)),Monoid.getAny -> hasChanged) <-- listen (runStateT (bottomupR collectANF ctx e1) ([],is2))- case bndrs of- [] -> if hasChanged then return e2 else return e0- _ -> do- let (e3,ticks) = collectTicks e2- (srcTicks,nmTicks) = partitionTicks ticks- -- Ensure that `AppendName` ticks still scope over the entire expression- changed (mkTicks (Letrec bndrs (mkTicks e3 srcTicks)) nmTicks)-{-# SCC makeANF #-}---- | Note [ANF InScopeSet]------ The InScopeSet contains:------ 1. All the free variables of the expression we are traversing------ 2. All the bound variables of the expression we are traversing------ 3. The newly created let-bindings as we recurse back up the traversal------ All of these are needed to created let-bindings that------ * Do not shadow--- * Are not shadowed--- * Nor conflict with each other (i.e. have the same unique)------ Initially we start with the local InScopeSet and add the global variables:------ @--- is1 <- unionInScope is0 <$> Lens.use globalInScope--- @------ Which will gives us the (superset of) free variables of the expression. Then--- we call 'freshenTm'------ @--- let (is2,e1) = freshenTm is1 e0--- @------ Which extends the InScopeSet with all the bound variables in 'e1', the--- version of 'e0' where all binders are unique (not just deshadowed).------ So we start out with an InScopeSet that satisfies points 1 and 2, now every--- time we create a new binder we must add it to the InScopeSet to satisfy--- point 3.------ Note [ANF no let-bind]------ | Do not let-bind:------ 1. Arguments with an untranslatable type: untranslatable expressions--- should be propagated down as far as possible------ 2. Local variables or constants: they don't add any work, so no reason--- to let-bind to enable sharing------ 3. IO actions, the translation of IO actions to sequential HDL constructs--- depends on IO actions to be propagated down as far as possible.-collectANF :: HasCallStack => NormRewriteW-collectANF ctx e@(App appf arg)- | (conVarPrim, _) <- collectArgs e- , isCon conVarPrim || isPrim conVarPrim || isVar conVarPrim- = do- tcm <- Lens.view tcCache- untranslatable <- lift (isUntranslatable False arg)- let localVar = isLocalVar arg- constantNoCR = isConstantNotClockReset tcm arg- -- See Note [ANF no let-bind]- case (untranslatable,localVar || constantNoCR, isSimBind conVarPrim,arg) of- (False,False,False,_) -> do- -- See Note [ANF InScopeSet]- is1 <- Lens.use _2- argId <- lift (mkTmBinderFor is1 tcm (mkDerivedName ctx "app_arg") arg)- -- See Note [ANF InScopeSet]- tellBinders [(argId,arg)]- return (App appf (Var argId))- (True,False,_,Letrec binds body) -> do- tellBinders binds- return (App appf body)- _ -> return e- where- isSimBind (Prim p) = primName p == "Clash.Explicit.SimIO.bindSimIO#"- isSimBind _ = False--collectANF _ (Letrec binds body) = do- tcm <- Lens.view tcCache- let isSimIO = isSimIOTy tcm (termType tcm body)- untranslatable <- lift (isUntranslatable False body)- let localVar = isLocalVar body- -- See Note [ANF no let-bind]- if localVar || untranslatable || isSimIO- then do- tellBinders binds- return body- else do- -- See Note [ANF InScopeSet]- is1 <- Lens.use _2- argId <- lift (mkTmBinderFor is1 tcm (mkUnsafeSystemName "result" 0) body)- -- See Note [ANF InScopeSet]- tellBinders [(argId,body)]- tellBinders binds- return (Var argId)---- TODO: The code below special-cases ANF for the ':-' constructor for the--- 'Signal' type. The 'Signal' type is essentially treated as a "transparent"--- type by the Clash compiler, so observing its constructor leads to all kinds--- of problems. In this case that "Clash.Rewrite.Util.mkSelectorCase" will--- try to project the LHS and RHS of the ':-' constructor, however,--- 'mkSelectorCase' uses 'coreView1' to find the "real" data-constructor.--- 'coreView1' however looks through the 'Signal' type, and hence 'mkSelector'--- finds the data constructors for the element type of Signal. This resulted in--- error #24 (https://github.com/christiaanb/clash2/issues/24), where we--- try to get the first field out of the 'Vec's 'Nil' constructor.------ Ultimately we should stop treating Signal as a "transparent" type and deal--- handling of the Signal type, and the involved co-recursive functions,--- properly. At the moment, Clash cannot deal with this recursive type and the--- recursive functions involved, hence the need for special-casing code. After--- everything is done properly, we should remove the two lines below.-collectANF _ e@(Case _ _ [(DataPat dc _ _,_)])- | nameOcc (dcName dc) == "Clash.Signal.Internal.:-" = return e--collectANF ctx (Case subj ty alts) = do- let localVar = isLocalVar subj- let isConstantSubj = isConstant subj-- (subj',subjBinders) <- if localVar || isConstantSubj- then return (subj,[])- else do- tcm <- Lens.view tcCache- -- See Note [ANF InScopeSet]- is1 <- Lens.use _2- argId <- lift (mkTmBinderFor is1 tcm (mkDerivedName ctx "case_scrut") subj)- -- See Note [ANF InScopeSet]- notifyBinders [(argId,subj)]- return (Var argId,[(argId,subj)])-- tcm <- Lens.view tcCache- let isSimIOAlt = isSimIOTy tcm ty-- alts' <- mapM (doAlt isSimIOAlt subj') alts- tellBinders subjBinders-- case alts' of- [(DataPat _ [] xs,altExpr)]- | xs `localIdsDoNotOccurIn` altExpr || isSimIOAlt- -> return altExpr- _ -> return (Case subj' ty alts')- where- doAlt- :: Bool -> Term -> (Pat,Term)- -> StateT ([LetBinding],InScopeSet) (RewriteMonad NormalizeState)- (Pat,Term)- doAlt isSimIOAlt subj' alt@(DataPat dc exts xs,altExpr) | not (bindsExistentials exts xs) = do- let lv = isLocalVar altExpr- patSels <- Monad.zipWithM (doPatBndr subj' dc) xs [0..]- let altExprIsConstant = isConstant altExpr- let usesXs (Var n) = any (== n) xs- usesXs _ = False- -- See [ANF no let-bind]- if or [isSimIOAlt, lv && (not (usesXs altExpr) || length alts == 1), altExprIsConstant]- then do- -- See Note [ANF InScopeSet]- tellBinders patSels- return alt- else do- tcm <- Lens.view tcCache- -- See Note [ANF InScopeSet]- is1 <- Lens.use _2- altId <- lift (mkTmBinderFor is1 tcm (mkDerivedName ctx "case_alt") altExpr)- -- See Note [ANF InScopeSet]- tellBinders (patSels ++ [(altId,altExpr)])- return (DataPat dc exts xs,Var altId)- doAlt _ _ alt@(DataPat {}, _) = return alt- doAlt isSimIOAlt _ alt@(pat,altExpr) = do- let lv = isLocalVar altExpr- let altExprIsConstant = isConstant altExpr- -- See [ANF no let-bind]- if isSimIOAlt || lv || altExprIsConstant- then return alt- else do- tcm <- Lens.view tcCache- -- See Note [ANF InScopeSet]- is1 <- Lens.use _2- altId <- lift (mkTmBinderFor is1 tcm (mkDerivedName ctx "case_alt") altExpr)- tellBinders [(altId,altExpr)]- return (pat,Var altId)-- doPatBndr- :: Term -> DataCon -> Id -> Int- -> StateT ([LetBinding],InScopeSet) (RewriteMonad NormalizeState)- LetBinding- doPatBndr subj' dc pId i- = do- tcm <- Lens.view tcCache- -- See Note [ANF InScopeSet]- is1 <- Lens.use _2- patExpr <- lift (mkSelectorCase ($(curLoc) ++ "doPatBndr") is1 tcm subj' (dcTag dc) i)- -- No need to 'tellBinders' here because 'pId' is already in the ANF- -- InScopeSet.- --- -- See also Note [ANF InScopeSet]- return (pId,patExpr)--collectANF _ e = return e-{-# SCC collectANF #-}---- | Eta-expand top-level lambda's (DON'T use in a traversal!)-etaExpansionTL :: HasCallStack => NormRewrite-etaExpansionTL (TransformContext is0 ctx) (Lam bndr e) = do- e' <- etaExpansionTL- (TransformContext (extendInScopeSet is0 bndr) (LamBody bndr:ctx))- e- return $ Lam bndr e'--etaExpansionTL (TransformContext is0 ctx) (Letrec xes e) = do- let bndrs = map fst xes- e' <- etaExpansionTL- (TransformContext (extendInScopeSetList is0 bndrs)- (LetBody bndrs:ctx))- e- case stripLambda e' of- (bs@(_:_),e2) -> do- let e3 = Letrec xes e2- changed (mkLams e3 bs)- _ -> return (Letrec xes e')- where- stripLambda :: Term -> ([Id],Term)- stripLambda (Lam bndr e0) =- let (bndrs,e1) = stripLambda e0- in (bndr:bndrs,e1)- stripLambda e' = ([],e')--etaExpansionTL (TransformContext is0 ctx) e- = do- tcm <- Lens.view tcCache- if isFun tcm e- then do- let argTy = ( fst- . Maybe.fromMaybe (error $ $(curLoc) ++ "etaExpansion splitFunTy")- . splitFunTy tcm- . termType tcm- ) e- newId <- mkInternalVar is0 "arg" argTy- e' <- etaExpansionTL (TransformContext (extendInScopeSet is0 newId)- (LamBody newId:ctx))- (App e (Var newId))- changed (Lam newId e')- else return e-{-# SCC etaExpansionTL #-}---- | Eta-expand functions with a Synthesize annotation, needed to allow such--- functions to appear as arguments to higher-order primitives.-etaExpandSyn :: HasCallStack => NormRewrite-etaExpandSyn (TransformContext is0 ctx) e@(collectArgs -> (Var f, _)) = do- topEnts <- Lens.view topEntities- tcm <- Lens.view tcCache- let isTopEnt = f `elemVarSet` topEnts- isAppFunCtx =- \case- AppFun:_ -> True- TickC _:c -> isAppFunCtx c- _ -> False- argTyM = fmap fst (splitFunTy tcm (termType tcm e))- case argTyM of- Just argTy | isTopEnt && not (isAppFunCtx ctx) -> do- newId <- mkInternalVar is0 "arg" argTy- changed (Lam newId (App e (Var newId)))- _ -> return e--etaExpandSyn _ e = return e-{-# SCC etaExpandSyn #-}--isClassConstraint :: Type -> Bool-isClassConstraint (tyView -> TyConApp nm0 _) =- if -- Constraint tuple:- | "GHC.Classes.(%" `Text.isInfixOf` nm1 -> True- -- Constraint class:- | "C:" `Text.isInfixOf` nm2 -> True- | otherwise -> False- where- nm1 = nameOcc nm0- nm2 = snd (Text.breakOnEnd "." nm1)--isClassConstraint _ = False----- | Turn a normalized recursive function, where the recursive calls only pass--- along the unchanged original arguments, into let-recursive function. This--- means that all recursive calls are replaced by the same variable reference as--- found in the body of the top-level let-expression.-recToLetRec :: HasCallStack => NormRewrite-recToLetRec (TransformContext is0 []) e = do- (fn,_) <- Lens.use curFun- tcm <- Lens.view tcCache- case splitNormalized tcm e of- Right (args,bndrs,res) -> do- let args' = map Var args- (toInline,others) = List.partition (eqApp tcm fn args' . snd) bndrs- resV = Var res- case (toInline,others) of- (_:_,_:_) -> do- let is1 = extendInScopeSetList is0 (args ++ map fst bndrs)- let substsInline = extendIdSubstList (mkSubst is1)- $ map (second (const resV)) toInline- others' = map (second (substTm "recToLetRec" substsInline))- others- changed $ mkLams (Letrec others' resV) args- _ -> return e- _ -> return e- where- -- This checks whether things are semantically equal. For example, say we- -- have:- --- -- x :: (a, (b, c))- --- -- and- --- -- y :: (a, (b, c))- --- -- If we can determine that 'y' is constructed solely using the- -- corresponding fields in 'x', then we can say they are semantically- -- equal. The algorithm below keeps track of what (sub)field it is- -- constructing, and checks if the field-expression projects the- -- corresponding (sub)field from the target variable.- --- -- TODO: See [Note: Breaks on constants and predetermined equality]- eqApp tcm v args (collectArgs . stripAllTicks -> (Var v',args'))- | isGlobalId v'- , v == v'- , let args2 = Either.lefts args'- , length args == length args2- = and (zipWith (eqArg tcm) args args2)- eqApp _ _ _ _ = False-- eqArg _ v1 v2@Var {}- = v1 == v2- eqArg tcm v1 v2@(collectArgs -> (Data _, args'))- | let t1 = normalizeType tcm (termType tcm v1)- , let t2 = normalizeType tcm (termType tcm v2)- , t1 == t2- = if isClassConstraint t1 then- -- Class constraints are equal if their types are equal, so we can- -- take a shortcut here.- True- else- -- Check whether all arguments to the data constructor are projections- --- and (zipWith (eqDat v1) (map pure [0..]) (Either.lefts args'))- eqArg _ _ _- = False-- -- Recursively check whether a term /e/ is semantically equal to some variable /v/.- -- Currently it can only assert equality when /e/ is syntactically equal- -- to /v/, or is constructed out of projections of /v/, importantly:- --- -- [Note: Breaks on constants and predetermined equality]- -- This function currently breaks if:- --- -- * One or more subfields are constants. Constants might have been- -- inlined for the construction, instead of being a projection of the- -- target variable.- --- -- * One or more subfields are determined to be equal and one is simply- -- swapped / replaced by the other. For example, say we have- -- `x :: (a, a)`. If GHC determines that both elements of the tuple will- -- always be the same, it might replace the (semantically equal to 'x')- -- construction of `y` with `(fst x, fst x)`.- --- eqDat :: Term -> [Int] -> Term -> Bool- eqDat v fTrace (collectArgs . stripTicks -> (Data _, args)) =- and (zipWith (eqDat v) (map (:fTrace) [0..]) (Either.lefts args))- eqDat v1 fTrace v2 =- case stripProjection (reverse fTrace) v1 v2 of- Just [] -> True- _ -> False-- stripProjection :: [Int] -> Term -> Term -> Maybe [Int]- stripProjection fTrace0 vTarget0 (Case v _ [(DataPat _ _ xs, r)]) = do- -- Get projection made in subject of case:- fTrace1 <- stripProjection fTrace0 vTarget0 v-- -- Extract projection of this case statement. Subsequent calls to- -- 'stripProjection' will check if new target is actually used.- (n, fTrace2) <- List.uncons fTrace1- vTarget1 <- List.indexMaybe xs n-- stripProjection fTrace2 (Var vTarget1) r-- stripProjection fTrace (Var sTarget) (Var s) =- if sTarget == s then Just fTrace else Nothing-- stripProjection _fTrace _vTarget _v =- Nothing--recToLetRec _ e = return e-{-# SCC recToLetRec #-}---- | Inline a function with functional arguments-inlineHO :: HasCallStack => NormRewrite-inlineHO _ e@(App _ _)- | (Var f, args, ticks) <- collectArgsTicks e- = do- tcm <- Lens.view tcCache- let hasPolyFunArgs = or (map (either (isPolyFun tcm) (const False)) args)- if hasPolyFunArgs- then do (cf,_) <- Lens.use curFun- isInlined <- zoomExtra (alreadyInlined f cf)- limit <- Lens.use (extra.inlineLimit)- if (Maybe.fromMaybe 0 isInlined) > limit- then do- lvl <- Lens.view dbgLevel- traceIf (lvl > DebugNone) ($(curLoc) ++ "InlineHO: " ++ show f ++ " already inlined " ++ show limit ++ " times in:" ++ show cf) (return e)- else do- bodyMaybe <- lookupVarEnv f <$> Lens.use bindings- case bodyMaybe of- Just b -> do- zoomExtra (addNewInline f cf)- changed (mkApps (mkTicks (bindingTerm b) ticks) args)- _ -> return e- else return e--inlineHO _ e = return e-{-# SCC inlineHO #-}---- | Simplified CSE, only works on let-bindings, does an inverse topological--- sort of the let-bindings and then works from top to bottom------ XXX: Check whether inverse top-sort followed by single traversal removes as--- many binders as the previous "apply-until-fixpoint" approach in the presence--- of recursive groups in the let-bindings. If not but just for checking whether--- changes to transformation affect the eventual size of the circuit, it would--- be really helpful if we tracked circuit size in the regression/test suite.--- On the two examples that were tested, Reducer and PipelinesViaFolds, this new--- version of CSE removed the same amount of let-binders.-simpleCSE :: HasCallStack => NormRewrite-simpleCSE (TransformContext is0 _) term@Letrec{} = do- let Letrec bndrs body = inverseTopSortLetBindings term- let is1 = extendInScopeSetList is0 (map fst bndrs)- ((subst,bndrs1), change) <- listen $ reduceBinders (mkSubst is1) [] bndrs- -- TODO: check whether a substitution over the body is enough, the reason I'm- -- doing a substitution over the the binders as well is that I don't know in- -- what order a recursive group shows up in a inverse topological sort.- -- Depending on the order and forgetting to apply the substitution over the- -- let-bindings might lead to the introduction of free variables.- --- -- NB: don't apply the substitution to the entire let-expression, and that- -- would rename the let-bindings because they've been added to the InScopeSet- -- of the substitution.- if Monoid.getAny change- then- let bndrs2 = map (second (substTm "simpleCSE.bndrs" subst)) bndrs1- body1 = substTm "simpleCSE.body" subst body- in changed (Letrec bndrs2 body1)- else- return term--simpleCSE _ e = return e-{-# SCC simpleCSE #-}---- | XXX: is given inverse topologically sorted binders, but returns--- topologically sorted binders------ TODO: check further speed improvements:------ 1. Store the processed binders in a `Map Expr LetBinding`:--- * Trades O(1) `cons` and O(n)*aeqTerm `find` for:--- * O(log n)*aeqTerm `insert` and O(log n)*aeqTerm `lookup`--- 2. Store the processed binders in a `AEQTrie Expr LetBinding`--- * Trades O(1) `cons` and O(n)*aeqTerm `find` for:--- * O(e) `insert` and O(e) `lookup`-reduceBinders- :: Subst- -> [LetBinding]- -> [LetBinding]- -> RewriteMonad NormalizeState (Subst, [LetBinding])-reduceBinders !subst processed [] = return (subst,processed)-reduceBinders !subst processed ((i,substTm "reduceBinders" subst -> e):rest)- | (_,_,ticks) <- collectArgsTicks e- , NoDeDup `notElem` ticks- , Just (i1,_) <- List.find ((== e) . snd) processed- = do- let subst1 = extendIdSubst subst i (Var i1)- setChanged- reduceBinders subst1 processed rest- | otherwise- = reduceBinders subst ((i,e):processed) rest-{-# SCC reduceBinders #-}--reduceConst :: HasCallStack => NormRewrite-reduceConst ctx e@(App _ _)- | (Prim p0, _) <- collectArgs e- = whnfRW False ctx e $ \_ctx1 e1 -> case e1 of- (collectArgs -> (Prim p1, _)) | primName p0 == primName p1 -> return e- _ -> changed e1--reduceConst _ e = return e-{-# SCC reduceConst #-}---- | Replace primitives by their "definition" if they would lead to let-bindings--- with a non-representable type when a function is in ANF. This happens for--- example when Clash.Size.Vector.map consumes or produces a vector of--- non-representable elements.------ Basically what this transformation does is replace a primitive the completely--- unrolled recursive definition that it represents. e.g.------ > zipWith ($) (xs :: Vec 2 (Int -> Int)) (ys :: Vec 2 Int)------ is replaced by:------ > let (x0 :: (Int -> Int)) = case xs of (:>) _ x xr -> x--- > (xr0 :: Vec 1 (Int -> Int)) = case xs of (:>) _ x xr -> xr--- > (x1 :: (Int -> Int)( = case xr0 of (:>) _ x xr -> x--- > (y0 :: Int) = case ys of (:>) _ y yr -> y--- > (yr0 :: Vec 1 Int) = case ys of (:>) _ y yr -> xr--- > (y1 :: Int = case yr0 of (:>) _ y yr -> y--- > in (($) x0 y0 :> ($) x1 y1 :> Nil)------ Currently, it only handles the following functions:------ * Clash.Sized.Vector.zipWith--- * Clash.Sized.Vector.map--- * Clash.Sized.Vector.traverse#--- * Clash.Sized.Vector.fold--- * Clash.Sized.Vector.foldr--- * Clash.Sized.Vector.dfold--- * Clash.Sized.Vector.(++)--- * Clash.Sized.Vector.head--- * Clash.Sized.Vector.tail--- * Clash.Sized.Vector.last--- * Clash.Sized.Vector.init--- * Clash.Sized.Vector.unconcat--- * Clash.Sized.Vector.transpose--- * Clash.Sized.Vector.replicate--- * Clash.Sized.Vector.replace_int--- * Clash.Sized.Vector.imap--- * Clash.Sized.Vector.dtfold--- * Clash.Sized.RTree.tdfold--- * Clash.Sized.RTree.treplicate--- * Clash.Sized.Internal.BitVector.split#--- * Clash.Sized.Internal.BitVector.eq#------ Note [Unroll shouldSplit types]--- 1. Certain higher-order functions over Vec, such as map, have specialized--- code-paths to turn them into generate-for loops in HDL, instead of having to--- having to unroll/inline their recursive definitions, e.g. Clash.Sized.Vector.map------ 2. Clash, in general, translates Haskell product types to VHDL records. This--- mostly works out fine, there is however one exception: certain synthesis--- tools, and some HDL simulation tools (like verilator), do not like it when--- the clock (and certain other global control signals) is contained in a--- record type; they want them to be separate inputs to the entity/module.--- And Clash actually does some transformations to try to ensure that values of--- type Clock do not end up in a VHDL record type.------ The problem is that the transformations in 2. never took into account the--- specialized code-paths in 1. Making the code-paths in 1. aware of the--- transformations in 2. is really not worth the effort for such a niche case.--- It's easier to just unroll the recursive definitions.------ See https://github.com/clash-lang/clash-compiler/issues/1606-reduceNonRepPrim :: HasCallStack => NormRewrite-reduceNonRepPrim c@(TransformContext is0 ctx) e@(App _ _) | (Prim p, args, ticks) <- collectArgsTicks e = do- tcm <- Lens.view tcCache- ultra <- Lens.use (extra.normalizeUltra)- let eTy = termType tcm e- case tyView eTy of- (TyConApp vecTcNm@(nameOcc -> "Clash.Sized.Vector.Vec")- [runExcept . tyNatSize tcm -> Right 0, aTy]) -> do- let (Just vecTc) = lookupUniqMap vecTcNm tcm- [nilCon,consCon] = tyConDataCons vecTc- nilE = mkVec nilCon consCon aTy 0 []- changed (mkTicks nilE ticks)- tv -> let argLen = length args in case primName p of- "Clash.Sized.Vector.zipWith" | argLen == 7 -> do- let [lhsElTy,rhsElty,resElTy,nTy] = Either.rights args- TyConApp vecTcNm _ = tv- lhsTy = mkTyConApp vecTcNm [nTy,lhsElTy]- rhsTy = mkTyConApp vecTcNm [nTy,rhsElty]- case runExcept (tyNatSize tcm nTy) of- Right n -> do- shouldReduce1 <- List.orM [ pure (ultra || n < 2)- , shouldReduce ctx- , List.anyM isUntranslatableType_not_poly- [lhsElTy,rhsElty,resElTy]- -- Note [Unroll shouldSplit types]- , pure (any (Maybe.isJust . shouldSplit tcm)- [lhsTy,rhsTy,eTy]) ]- if shouldReduce1- then let [fun,lhsArg,rhsArg] = Either.lefts args- in (`mkTicks` ticks) <$>- reduceZipWith c p n lhsElTy rhsElty resElTy fun lhsArg rhsArg- else return e- _ -> return e- "Clash.Sized.Vector.map" | argLen == 5 -> do- let [argElTy,resElTy,nTy] = Either.rights args- TyConApp vecTcNm _ = tv- argTy = mkTyConApp vecTcNm [nTy,argElTy]- case runExcept (tyNatSize tcm nTy) of- Right n -> do- shouldReduce1 <- List.orM [ pure (ultra || n < 2 )- , shouldReduce ctx- , List.anyM isUntranslatableType_not_poly- [argElTy,resElTy]- -- Note [Unroll shouldSplit types]- , pure (any (Maybe.isJust . shouldSplit tcm)- [argTy,eTy]) ]- if shouldReduce1- then let [fun,arg] = Either.lefts args- in (`mkTicks` ticks) <$> reduceMap c p n argElTy resElTy fun arg- else return e- _ -> return e- "Clash.Sized.Vector.traverse#" | argLen == 7 ->- let [aTy,fTy,bTy,nTy] = Either.rights args- in case runExcept (tyNatSize tcm nTy) of- Right n ->- let [dict,fun,arg] = Either.lefts args- in (`mkTicks` ticks) <$> reduceTraverse c n aTy fTy bTy dict fun arg- _ -> return e- "Clash.Sized.Vector.fold" | argLen == 4 -> do- let ([fun,arg],[nTy,aTy]) = Either.partitionEithers args- argTy = termType tcm arg- case runExcept (tyNatSize tcm nTy) of- Right n -> do- shouldReduce1 <- List.orM [ pure (ultra || n == 0)- , shouldReduce ctx- , isUntranslatableType_not_poly aTy- -- Note [Unroll shouldSplit types]- , pure (Maybe.isJust (shouldSplit tcm argTy))]- if shouldReduce1 then- (`mkTicks` ticks) <$> reduceFold c (n + 1) aTy fun arg- else return e- _ -> return e- "Clash.Sized.Vector.foldr" | argLen == 6 ->- let ([fun,start,arg],[aTy,bTy,nTy]) = Either.partitionEithers args- argTy = termType tcm arg- in case runExcept (tyNatSize tcm nTy) of- Right n -> do- shouldReduce1 <- List.orM [ pure ultra- , shouldReduce ctx- , List.anyM isUntranslatableType_not_poly [aTy,bTy]- -- Note [Unroll shouldSplit types]- , pure (Maybe.isJust (shouldSplit tcm argTy)) ]- if shouldReduce1- then (`mkTicks` ticks) <$> reduceFoldr c p n aTy fun start arg- else return e- _ -> return e- "Clash.Sized.Vector.dfold" | argLen == 8 ->- let ([_kn,_motive,fun,start,arg],[_mTy,nTy,aTy]) = Either.partitionEithers args- in case runExcept (tyNatSize tcm nTy) of- Right n -> (`mkTicks` ticks) <$> reduceDFold is0 n aTy fun start arg- _ -> return e- "Clash.Sized.Vector.++" | argLen == 5 ->- let [nTy,aTy,mTy] = Either.rights args- [lArg,rArg] = Either.lefts args- in case (runExcept (tyNatSize tcm nTy), runExcept (tyNatSize tcm mTy)) of- (Right n, Right m)- | n == 0 -> changed rArg- | m == 0 -> changed lArg- | otherwise -> do- shouldReduce1 <- List.orM [ shouldReduce ctx- , isUntranslatableType_not_poly aTy- -- Note [Unroll shouldSplit types]- , pure (Maybe.isJust (shouldSplit tcm eTy)) ]- if shouldReduce1- then (`mkTicks` ticks) <$> reduceAppend is0 n m aTy lArg rArg- else return e- _ -> return e- "Clash.Sized.Vector.head" | argLen == 3 -> do- let [nTy,aTy] = Either.rights args- [vArg] = Either.lefts args- argTy = termType tcm vArg- case runExcept (tyNatSize tcm nTy) of- Right n -> do- shouldReduce1 <- List.orM [ shouldReduce ctx- , isUntranslatableType_not_poly aTy- -- Note [Unroll shouldSplit types]- , pure (Maybe.isJust (shouldSplit tcm argTy)) ]- if shouldReduce1- then (`mkTicks` ticks) <$> reduceHead is0 (n+1) aTy vArg- else return e- _ -> return e- "Clash.Sized.Vector.tail" | argLen == 3 -> do- let [nTy,aTy] = Either.rights args- [vArg] = Either.lefts args- argTy = termType tcm vArg- case runExcept (tyNatSize tcm nTy) of- Right n -> do- shouldReduce1 <- List.orM [ shouldReduce ctx- , isUntranslatableType_not_poly aTy- -- Note [Unroll shouldSplit types]- , pure (Maybe.isJust (shouldSplit tcm argTy)) ]- if shouldReduce1- then (`mkTicks` ticks) <$> reduceTail is0 (n+1) aTy vArg- else return e- _ -> return e- "Clash.Sized.Vector.last" | argLen == 3 -> do- let [nTy,aTy] = Either.rights args- [vArg] = Either.lefts args- argTy = termType tcm vArg- case runExcept (tyNatSize tcm nTy) of- Right n -> do- shouldReduce1 <- List.orM [ shouldReduce ctx- , isUntranslatableType_not_poly aTy- -- Note [Unroll shouldSplit types]- , pure (Maybe.isJust (shouldSplit tcm argTy))- ]- if shouldReduce1- then (`mkTicks` ticks) <$> reduceLast is0 (n+1) aTy vArg- else return e- _ -> return e- "Clash.Sized.Vector.init" | argLen == 3 -> do- let [nTy,aTy] = Either.rights args- [vArg] = Either.lefts args- argTy = termType tcm vArg- case runExcept (tyNatSize tcm nTy) of- Right n -> do- shouldReduce1 <- List.orM [ shouldReduce ctx- , isUntranslatableType_not_poly aTy- -- Note [Unroll shouldSplit types]- , pure (Maybe.isJust (shouldSplit tcm argTy)) ]- if shouldReduce1- then (`mkTicks` ticks) <$> reduceInit is0 p n aTy vArg- else return e- _ -> return e- "Clash.Sized.Vector.unconcat" | argLen == 6 -> do- let ([_knN,sm,arg],[nTy,mTy,aTy]) = Either.partitionEithers args- argTy = termType tcm arg- case (runExcept (tyNatSize tcm nTy), runExcept (tyNatSize tcm mTy)) of- (Right n, Right m) -> do- shouldReduce1 <- List.orM [ pure (m==0)- , shouldReduce ctx- , isUntranslatableType_not_poly aTy- -- Note [Unroll shouldSplit types]- , pure (Maybe.isJust (shouldSplit tcm argTy))- ]- if shouldReduce1 then- (`mkTicks` ticks) <$> reduceUnconcat is0 p n m aTy sm arg- else- return e- _ -> return e- "Clash.Sized.Vector.transpose" | argLen == 5 -> do- let ([_knN,arg],[mTy,nTy,aTy]) = Either.partitionEithers args- case (runExcept (tyNatSize tcm nTy), runExcept (tyNatSize tcm mTy)) of- (Right n, Right 0) -> (`mkTicks` ticks) <$> reduceTranspose n 0 aTy arg- _ -> return e- "Clash.Sized.Vector.replicate" | argLen == 4 -> do- let ([_sArg,vArg],[nTy,aTy]) = Either.partitionEithers args- case runExcept (tyNatSize tcm nTy) of- Right n -> do- shouldReduce1 <- List.orM [ shouldReduce ctx- , isUntranslatableType_not_poly aTy- -- Note [Unroll shouldSplit types]- , pure (Maybe.isJust (shouldSplit tcm eTy))- ]- if shouldReduce1- then (`mkTicks` ticks) <$> reduceReplicate n aTy eTy vArg- else return e- _ -> return e- -- replace_int :: KnownNat n => Vec n a -> Int -> a -> Vec n a- "Clash.Sized.Vector.replace_int" | argLen == 6 -> do- let ([_knArg,vArg,iArg,aArg],[nTy,aTy]) = Either.partitionEithers args- case runExcept (tyNatSize tcm nTy) of- Right n -> do- shouldReduce1 <- List.orM [ pure ultra- , shouldReduce ctx- , isUntranslatableType_not_poly aTy- -- Note [Unroll shouldSplit types]- , pure (Maybe.isJust (shouldSplit tcm eTy))- ]- if shouldReduce1- then (`mkTicks` ticks) <$> reduceReplace_int is0 n aTy eTy vArg iArg aArg- else return e- _ -> return e-- "Clash.Sized.Vector.index_int" | argLen == 5 -> do- let ([_knArg,vArg,iArg],[nTy,aTy]) = Either.partitionEithers args- argTy = termType tcm vArg- case runExcept (tyNatSize tcm nTy) of- Right n -> do- shouldReduce1 <- List.orM [ pure ultra- , shouldReduce ctx- , isUntranslatableType_not_poly aTy- -- Note [Unroll shouldSplit types]- , pure (Maybe.isJust (shouldSplit tcm argTy)) ]- if shouldReduce1- then (`mkTicks` ticks) <$> reduceIndex_int is0 n aTy vArg iArg- else return e- _ -> return e-- "Clash.Sized.Vector.imap" | argLen == 6 -> do- let [nTy,argElTy,resElTy] = Either.rights args- TyConApp vecTcNm _ = tv- argTy = mkTyConApp vecTcNm [nTy,argElTy]- case runExcept (tyNatSize tcm nTy) of- Right n -> do- shouldReduce1 <- List.orM [ pure (ultra || n < 2)- , shouldReduce ctx- , List.anyM isUntranslatableType_not_poly [argElTy,resElTy]- -- Note [Unroll shouldSplit types]- , pure (any (Maybe.isJust . shouldSplit tcm)- [argTy,eTy]) ]- if shouldReduce1- then let [_,fun,arg] = Either.lefts args- in (`mkTicks` ticks) <$> reduceImap c n argElTy resElTy fun arg- else return e- _ -> return e- "Clash.Sized.Vector.iterateI" | argLen == 5 ->- let ([_kn,f,a],[nTy,aTy]) = Either.partitionEithers args in- case runExcept (tyNatSize tcm nTy) of- Right n -> do- shouldReduce1 <- List.orM- [ pure (ultra || n < 2)- , shouldReduce ctx- , isUntranslatableType_not_poly aTy- -- Note [Unroll shouldSplit types]- , pure (Maybe.isJust (shouldSplit tcm eTy)) ]-- if shouldReduce1 then- (`mkTicks` ticks) <$> reduceIterateI c n aTy eTy f a- else- return e- _ -> return e- "Clash.Sized.Vector.dtfold" | argLen == 8 ->- let ([_kn,_motive,lrFun,brFun,arg],[_mTy,nTy,aTy]) = Either.partitionEithers args- in case runExcept (tyNatSize tcm nTy) of- Right n -> (`mkTicks` ticks) <$> reduceDTFold is0 n aTy lrFun brFun arg- _ -> return e-- "Clash.Sized.Vector.reverse"- | ultra- , ([vArg],[nTy,aTy]) <- Either.partitionEithers args- , Right n <- runExcept (tyNatSize tcm nTy)- -> (`mkTicks` ticks) <$> reduceReverse is0 n aTy vArg-- "Clash.Sized.RTree.tdfold" | argLen == 8 ->- let ([_kn,_motive,lrFun,brFun,arg],[_mTy,nTy,aTy]) = Either.partitionEithers args- in case runExcept (tyNatSize tcm nTy) of- Right n -> (`mkTicks` ticks) <$> reduceTFold is0 n aTy lrFun brFun arg- _ -> return e- "Clash.Sized.RTree.treplicate" | argLen == 4 -> do- let ([_sArg,vArg],[nTy,aTy]) = Either.partitionEithers args- case runExcept (tyNatSize tcm nTy) of- Right n -> do- shouldReduce1 <- List.orM [ shouldReduce ctx- , isUntranslatableType False aTy ]- if shouldReduce1- then (`mkTicks` ticks) <$> reduceTReplicate n aTy eTy vArg- else return e- _ -> return e- "Clash.Sized.Internal.BitVector.split#" | argLen == 4 -> do- let ([_knArg,bvArg],[nTy,mTy]) = Either.partitionEithers args- case (runExcept (tyNatSize tcm nTy), runExcept (tyNatSize tcm mTy), tv) of- (Right n, Right m, TyConApp tupTcNm [lTy,rTy])- | n == 0 -> do- let (Just tupTc) = lookupUniqMap tupTcNm tcm- [tupDc] = tyConDataCons tupTc- tup = mkApps (Data tupDc)- [Right lTy- ,Right rTy- ,Left bvArg- ,Left (removedTm rTy)- ]-- changed (mkTicks tup ticks)- | m == 0 -> do- let (Just tupTc) = lookupUniqMap tupTcNm tcm- [tupDc] = tyConDataCons tupTc- tup = mkApps (Data tupDc)- [Right lTy- ,Right rTy- ,Left (removedTm lTy)- ,Left bvArg- ]-- changed (mkTicks tup ticks)- _ -> return e- "Clash.Sized.Internal.BitVector.eq#"- | ([_,_],[nTy]) <- Either.partitionEithers args- , Right 0 <- runExcept (tyNatSize tcm nTy)- , TyConApp boolTcNm [] <- tv- -> let (Just boolTc) = lookupUniqMap boolTcNm tcm- [_falseDc,trueDc] = tyConDataCons boolTc- in changed (mkTicks (Data trueDc) ticks)- _ -> return e- where- isUntranslatableType_not_poly t = do- u <- isUntranslatableType False t- if u- then return (null $ Lens.toListOf typeFreeVars t)- else return False--reduceNonRepPrim _ e = return e-{-# SCC reduceNonRepPrim #-}---- | This transformation lifts applications of global binders out of--- alternatives of case-statements.------ e.g. It converts:------ @--- case x of--- A -> f 3 y--- B -> f x x--- C -> h x--- @------ into:------ @--- let f_arg0 = case x of {A -> 3; B -> x}--- f_arg1 = case x of {A -> y; B -> x}--- f_out = f f_arg0 f_arg1--- in case x of--- A -> f_out--- B -> f_out--- C -> h x--- @-disjointExpressionConsolidation :: HasCallStack => NormRewrite-disjointExpressionConsolidation ctx@(TransformContext isCtx _) e@(Case _scrut _ty _alts@(_:_:_)) = do- -- Collect all (the applications of) global binders (and certain primitives)- -- that would be interesting to share out of the case-alternatives.- (_,isCollected,collected) <- collectGlobals isCtx [] [] e- -- Filter those that are used at most once in every (nested) branch.- let disJoint = filter (isDisjoint . snd . snd) collected- if null disJoint- then return e- else do- -- For every to-lift expression create (the generalization of):- --- -- let fargs = case x of {A -> (3,y); B -> (x,x)}- -- in f (fst fargs) (snd fargs)- --- -- the let-expression is not created when `f` has only one (selectable)- -- argument- --- -- NB: mkDisJointGroup needs the context InScopeSet, isCtx, to determine- -- whether expressions reference variables from the context, or- -- variables inside a let-expression inside one of the alternatives.- lifted <- mapM (mkDisjointGroup isCtx) disJoint- tcm <- Lens.view tcCache- -- Create let-binders for all of the lifted expressions- --- -- NB: Because we will be substituting under binders we use the collected- -- inScopeSet, isCollected, which also contains all the binders- -- created inside all of the alternatives. With this inScopeSet, we- -- ensure that the let-bindings we create here won't be accidentally- -- captured by binders inside the case-alternatives.- (_,funOutIds) <- List.mapAccumLM (mkFunOut tcm)- isCollected- (zip disJoint lifted)- -- Create "substitutions" of the form [f X Y := f_out]- let substitution = zip (map fst disJoint) (map Var funOutIds)- -- For all of the lifted expression: substitute occurrences of the- -- disjoint expressions (f X Y) by a variable reference to the lifted- -- expression (f_out)- let isCtx1 = extendInScopeSetList isCtx funOutIds- lifted1 <- substLifted isCtx1 substitution lifted- -- Do the same for the actual case expression- (e1,_,_) <- collectGlobals isCtx1 substitution [] e- -- Let-bind all the lifted function- let lb = Letrec (zip funOutIds lifted1) e1- -- Do an initial dead-code elimination pass, as `mkDisJoint` doesn't- -- clean-up unused let-binders.- lb1 <- bottomupR deadCode ctx lb- changed lb1- where- -- Make the let-binder for the lifted expressions- mkFunOut tcm isN ((fun,_),(eLifted,_)) = do- let ty = termType tcm eLifted- nm = case collectArgs fun of- (Var v,_) -> nameOcc (varName v)- (Prim p,_) -> primName p- _ -> "complex_expression_"- nm1 = last (Text.splitOn "." nm) `Text.append` "Out"- nm2 <- mkInternalVar isN nm1 ty- return (extendInScopeSet isN nm2,nm2)-- -- Substitute inside the lifted expressions- --- -- In case you are wondering why this function isn't simply- --- -- > mapM (\s (eL,seen) -> collectGlobal isN s seen eL) substitution lifted- --- -- then that's because we have e.g. the list of "substitutions":- --- -- [foo _ _ := foo_out; bar _ _ := bar_out]- --- -- and if we were to apply that to a lifted expression, which is going- -- to be of the form `foo (case ...) (case ...)` then we would end up- -- with let-bindings that are simply:- --- -- > let foo_out = foo_out ; bar_out = bar_out- --- -- instead of the desired- --- -- > let foo_out = foo ((case ...)[foo _ _ := foo_out; bar _ _ := bar_out])- -- > ((case ...)[foo _ _ := foo_out; bar _ _ := bar_out])- -- > bar_out = bar ((case ...)[foo _ _ := foo_out; bar _ _ := bar_out])- -- > ((case ...)[foo _ _ := foo_out; bar _ _ := bar_out])- --- -- So what we do is that for every lifted-expression we make sure that the- -- 'substitution' never contains the self-substitution, so we end up with:- --- -- > let foo_out = (foo (case ...) (case ...))[bar _ _ := bar_out]- -- bar_out = (bar (case ...) (case ...))[foo _ _ := foo_out]- --- -- We used to have a different approach, see commit- -- 73d237017c4a5fff0c49bb72c9c4d5f6c68faf69- --- -- But that lead to the generation of combinational loops. Now that we no- -- longer traverse into recursive groups of let-bindings, the issue #1316- -- that the above commit tried to solve, no longer shows up.- substLifted isN substitution lifted = do- -- remove the self-substitutions for the respective lifted expressions- let subsMatrix = l2m substitution- lifted1 <- Monad.zipWithM (\s (eL,seen) -> collectGlobals isN s seen eL)- subsMatrix- lifted- return (map (^. _1) lifted1)-- l2m = go []- where- go _ [] = []- go xs (y:ys) = (xs ++ ys) : go (xs ++ [y]) ys--disjointExpressionConsolidation _ e = return e-{-# SCC disjointExpressionConsolidation #-}---- | Given a function in the desired normal form, inline all the following--- let-bindings:------ Let-bindings with an internal name that is only used once, where it binds:--- * a primitive that will be translated to an HDL expression (as opposed to--- a HDL declaration)--- * a projection case-expression (1 alternative)--- * a data constructor--- * I/O actions-inlineCleanup :: HasCallStack => NormRewrite-inlineCleanup (TransformContext is0 _) (Letrec binds body) = do- prims <- Lens.use (extra.primitives)- -- For all let-bindings, count the number of times they are referenced.- -- We only inline let-bindings which are referenced only once, otherwise- -- we would lose sharing.- let is1 = extendInScopeSetList is0 (map fst binds)- bindsFvs = map (\(v,e) -> (v,((v,e),countFreeOccurances e))) binds- allOccs = List.foldl' (unionVarEnvWith (+)) emptyVarEnv- $ map (snd.snd) bindsFvs- bodyFVs = Lens.foldMapOf freeLocalIds unitVarSet body- (il,keep) = List.partition (isInteresting allOccs prims bodyFVs)- bindsFvs- keep' = inlineBndrsCleanup is1 (mkVarEnv il) emptyVarEnv- $ map snd keep-- if | null il -> return (Letrec binds body)- | null keep' -> changed body- | otherwise -> changed (Letrec keep' body)- where- -- Determine whether a let-binding is interesting to inline- isInteresting- :: VarEnv Int- -> CompiledPrimMap- -> VarSet- -> (Id,((Id, Term), VarEnv Int))- -> Bool- isInteresting allOccs prims bodyFVs (id_,((_,(fst.collectArgs) -> tm),_))- -- Try to keep user defined names, but inline names generated by GHC or- -- Clash. For example, if a user were to write:- --- -- x = 2 * y- --- -- Even if 'x' is only used once, we'd like to keep it around to produce- -- more readable HDL. In contrast, if a user were to write:- --- -- let x = f (2 * y)- --- -- ANF would transform that to:- --- -- let x = f f_arg; f_arg = 2 * y- --- -- In that case, there's no harm in inlining f_arg.- | nameSort (varName id_) /= User- , id_ `notElemVarSet` bodyFVs- = case tm of- Prim pInfo- | let nm = primName pInfo- , Just (extractPrim -> Just p@(BlackBox {})) <- HashMap.lookup nm prims- , TExpr <- kind p- , Just occ <- lookupVarEnv id_ allOccs- , occ < 2- -> True- | otherwise- -> primName pInfo `elem` ["Clash.Explicit.SimIO.bindSimIO#"]- Case _ _ [_] -> True- Data _ -> True- Case _ aTy (_:_:_)- | TyConApp (nameOcc -> "Clash.Explicit.SimIO.SimIO") _ <- tyView aTy- -> True- _ -> False- | id_ `notElemVarSet` bodyFVs- = case tm of- Prim pInfo- | primName pInfo `elem` [ "Clash.Explicit.SimIO.openFile"- , "Clash.Explicit.SimIO.fgetc"- , "Clash.Explicit.SimIO.feof"- ]- , Just occ <- lookupVarEnv id_ allOccs- , occ < 2- -> True- | otherwise- -> primName pInfo `elem` ["Clash.Explicit.SimIO.bindSimIO#"]- Case _ _ [(DataPat dcE _ _,_)]- -> let nm = (nameOcc (dcName dcE))- in -- Inlines WW projection that exposes internals of the BitVector types- nm == "Clash.Sized.Internal.BitVector.BV" ||- nm == "Clash.Sized.Internal.BitVector.Bit" ||- -- Inlines projections out of constraint-tuples (e.g. HiddenClockReset)- "GHC.Classes" `Text.isPrefixOf` nm- Case _ aTy (_:_:_)- | TyConApp (nameOcc -> "Clash.Explicit.SimIO.SimIO") _ <- tyView aTy- -> True- _ -> False-- isInteresting _ _ _ _ = False--inlineCleanup _ e = return e-{-# SCC inlineCleanup #-}---- | Mark to track progress of 'reduceBindersCleanup'-data Mark = Temp | Done | Rec---- | Used by 'inlineCleanup' to inline binders that we want to inline into the--- binders that we want to keep.-inlineBndrsCleanup- :: HasCallStack- => InScopeSet- -- ^ Current InScopeSet- -> VarEnv ((Id,Term),VarEnv Int)- -- ^ Original let-binders with their free variables (+ #occurrences), that we- -- want to inline- -> VarEnv ((Id,Term),VarEnv Int,Mark)- -- ^ Processed let-binders with their free variables and a tag to mark the- -- progress:- -- * Temp: Will eventually form a recursive cycle- -- * Done: Processed, non-recursive- -- * Rec: Processed, recursive- -> [((Id,Term),VarEnv Int)]- -- ^ The let-binders with their free variables (+ #occurrences), that we want- -- to keep- -> [(Id,Term)]-inlineBndrsCleanup isN origInl = go- where- go doneInl [] =- -- If some of the let-binders that we wanted to inline turn out to be- -- recursive, then we have to keep those around as well, as we weren't able- -- to inline them. Furthermore, for every recursive binder there might still- -- be non-inlined variables left, see #1337.- flip map [ (ve, eFvs) | (ve,eFvs,Rec) <- eltsVarEnv doneInl ] $ \((v, e), eFvs) ->- let- (substM, _, _) = foldlWithUniqueVarEnv'- (reduceBindersCleanup isN emptyVarEnv)- (Nothing, emptyVarEnv, doneInl)- eFvs- in (v, maybeSubstTm "inlineBndrsCleanup_0" substM e)- go !doneInl_0 (((v,e),eFVs):il) =- let (sM,_,doneInl_1) = foldlWithUniqueVarEnv'- (reduceBindersCleanup isN origInl)- (Nothing, emptyVarEnv, doneInl_0)- eFVs- e1 = maybeSubstTm "inlineBndrsCleanup_1" sM e- in (v,e1):go doneInl_1 il-{-# SCC inlineBndrsCleanup #-}---- | Used (transitively) by 'inlineCleanup' inline to-inline let-binders into--- the other to-inline let-binders.-reduceBindersCleanup- :: HasCallStack- => InScopeSet- -- ^ Current InScopeSet- -> VarEnv ((Id,Term),VarEnv Int)- -- ^ Original let-binders with their free variables (+ #occurrences)- -> (Maybe Subst,VarEnv Int,VarEnv ((Id,Term),VarEnv Int,Mark))- -- ^ Accumulated:- --- -- 1. (Maybe) the build up substitution so far- -- 2. The free variables of the range of the substitution- -- 3. Processed let-binders with their free variables and a tag to mark- -- the progress:- -- * Temp: Will eventually form a recursive cycle- -- * Done: Processed, non-recursive- -- * Rec: Processed, recursive- -> Unique- -- ^ The unique of the let-binding that we want to simplify- -> Int- -- ^ Ignore, artifact of 'foldlWithUniqueVarEnv'- -> (Maybe Subst,VarEnv Int,VarEnv ((Id,Term),VarEnv Int,Mark))- -- ^ Same as the third argument-reduceBindersCleanup isN origInl (!substM,!substFVs,!doneInl) u _ =- case lookupVarEnvDirectly u doneInl of- Nothing -> case lookupVarEnvDirectly u origInl of- Nothing ->- -- let-binding not found, cannot extend the substitution- if elemUniqInScopeSet u isN then- (substM,substFVs,doneInl)- else- error [I.i|- Internal error: 'reduceBindersCleanup' encountered a variable- reference that was neither in 'doneInl', 'origInl', or in the- transformation's in scope set. Unique was: '#{u}'.- |]- Just ((v,e),eFVs) ->- -- Simplify the transitive dependencies- let (sM,substFVsE,doneInl1) =- foldlWithUniqueVarEnv'- (reduceBindersCleanup isN origInl)- ( Nothing- -- It's okay/needed to over-approximate the free variables of- -- the range of the new substitution by including the free- -- variables of the original let-binder, because this set of- -- free variables is only used to check whether let-binding will- -- become self-recursive after applying the substitution.- --- -- That is, it was already self-recursive, or becomes- -- self-recursive after applying the substitution because it was- -- part of a recursive group. And we do not want to inline- -- recursive binders.- , eFVs- -- Temporarily extend the processing environment with the- -- let-binding so we don't end up in a loop in case there is a- -- recursive group.- , extendVarEnv v ((v,e),eFVs,Temp) doneInl)- eFVs-- e1 = maybeSubstTm "reduceBindersCleanup" sM e- in if v `elemVarEnv` substFVsE then- -- We cannot inline recursive let-bindings, so we do not extend- -- the substitution environment.- ( substM- , substFVs- -- And we explicitly mark the let-binding as recursive in the- -- processing environment. So that it will be kept around at the- -- end of 'inlineCleanup'- , extendVarEnv v ((v,e1),substFVsE,Rec) doneInl1- )- else- -- Extend the substitution- ( Just (extendIdSubst (Maybe.fromMaybe (mkSubst isN) substM) v e1)- , unionVarEnv substFVsE substFVs- -- Mark the let-binding a fully "reduced", so we don't repeat- -- this process when we encounter it again.- , extendVarEnv v ((v,e1),substFVsE,Done) doneInl1- )- -- It's already been processed, just extend the substitution environment- Just ((v,e),eFVs,Done) ->- ( Just (extendIdSubst (Maybe.fromMaybe (mkSubst isN) substM) v e)- , unionVarEnv eFVs substFVs- , doneInl- )-- -- It's either recursive (Rec), or part of a recursive group (Temp) where we- -- originally entered a different part of the cycle. Regardless, we do not- -- extend the substitution environment.- Just _ ->- ( substM- , substFVs- , doneInl- )-{-# SCC reduceBindersCleanup #-}---- | Flatten's letrecs after `inlineCleanup`------ `inlineCleanup` sometimes exposes additional possibilities for `caseCon`,--- which then introduces let-bindings in what should be ANF. This transformation--- flattens those nested let-bindings again.------ NB: must only be called in the cleaning up phase.-flattenLet :: HasCallStack => NormRewrite-flattenLet (TransformContext is0 _) (Letrec binds body) = do- let is1 = extendInScopeSetList is0 (map fst binds)- bodyOccs = Lens.foldMapByOf- freeLocalIds (unionVarEnvWith (+))- emptyVarEnv (`unitVarEnv` (1 :: Int))- body- (is2,binds1) <- second concat <$> List.mapAccumLM go is1 binds- bndrs <- Lens.use bindings- e1WorkFree <-- case binds1 of- [(_,e1)] -> isWorkFree workFreeBinders bndrs e1- _ -> pure (error "flattenLet: unreachable")- case binds1 of- -- inline binders into the body when there's only a single binder, and only- -- if that binder doesn't perform any work or is only used once in the body- [(id1,e1)] | Just occ <- lookupVarEnv id1 bodyOccs, e1WorkFree || occ < 2 ->- if id1 `localIdOccursIn` e1- -- Except when the binder is recursive!- then return (Letrec binds1 body)- else let subst = extendIdSubst (mkSubst is2) id1 e1- in changed (substTm "flattenLet" subst body)- _ -> return (Letrec binds1 body)- where- go :: InScopeSet -> LetBinding -> NormalizeSession (InScopeSet,[LetBinding])- go isN (id1,collectTicks -> (Letrec binds1 body1,ticks)) = do- let bs1 = map fst binds1- let (binds2,body2,isN1) =- -- We need to deshadow because we're merging nested let-expressions- -- into a single let-expression: and within a let-expression, the- -- bindings are not allowed to shadow each-other. Of course, we- -- only need to deshadow if any shadowing is happening in the- -- first place.- --- -- This is much better than blindly calling freshenTm, and saves- -- almost 30% run-time of the normalization phase on some examples.- if any (`elemInScopeSet` isN) bs1 then- let Letrec bindsN bodyN = deShadowTerm isN (Letrec binds1 body1)- in (bindsN,bodyN,extendInScopeSetList isN (map fst bindsN))- else- (binds1,body1,extendInScopeSetList isN bs1)- let bodyOccs = Lens.foldMapByOf- freeLocalIds (unionVarEnvWith (+))- emptyVarEnv (`unitVarEnv` (1 :: Int))- body2- (srcTicks,nmTicks) = partitionTicks ticks- bndrs <- Lens.use bindings- e2WorkFree <-- case binds2 of- [(_,e2)] -> isWorkFree workFreeBinders bndrs e2- _ -> pure (error "flattenLet: unreachable")- -- Distribute the name ticks of the let-expression over all the bindings- (isN1,) . map (second (`mkTicks` nmTicks)) <$> case binds2 of- -- inline binders into the body when there's only a single binder, and- -- only if that binder doesn't perform any work or is only used once in- -- the body- [(id2,e2)] | Just occ <- lookupVarEnv id2 bodyOccs, e2WorkFree || occ < 2 ->- if id2 `localIdOccursIn` e2- -- Except when the binder is recursive!- then changed ([(id2,e2),(id1, body2)])- else let subst = extendIdSubst (mkSubst isN1) id2 e2- in changed [(id1- -- Only apply srcTicks to the body- ,mkTicks (substTm "flattenLetGo" subst body2)- srcTicks)]- bs -> changed (bs ++ [(id1- -- Only apply srcTicks to the body- ,mkTicks body2 srcTicks)])- go isN b = return (isN,[b])--flattenLet _ e = return e-{-# SCC flattenLet #-}---- | Worker function of 'separateArguments'.-separateLambda- :: TyConMap- -> TransformContext- -> Id- -- ^ Lambda binder- -> Term- -- ^ Lambda body- -> Maybe Term- -- ^ If lambda is split up, this function returns a Just containing the new term-separateLambda tcm ctx@(TransformContext is0 _) b eb0 =- case shouldSplit tcm (varType b) of- Just (dc, _, argTys) ->- let- nm = mkDerivedName ctx (nameOcc (varName b))- bs0 = map (`mkLocalId` nm) argTys- (is1, bs1) = List.mapAccumL newBinder is0 bs0- subst = extendIdSubst (mkSubst is1) b (dc (map Var bs1))- eb1 = substTm "separateArguments" subst eb0- in- Just (mkLams eb1 bs1)- _ ->- Nothing- where- newBinder isN0 x =- let- x' = uniqAway isN0 x- isN1 = extendInScopeSet isN0 x'- in- (isN1, x')-{-# SCC separateLambda #-}---- | Split apart (global) function arguments that contain types that we--- want to separate off, e.g. Clocks. Works on both the definition side (i.e. the--- lambda), and the call site (i.e. the application of the global variable). e.g.--- turns------ > f :: (Clock System, Reset System) -> Signal System Int------ into------ > f :: Clock System -> Reset System -> Signal System Int-separateArguments :: HasCallStack => NormRewrite-separateArguments ctx e0@(Lam b eb) = do- tcm <- Lens.view tcCache- case separateLambda tcm ctx b eb of- Just e1 -> changed e1- Nothing -> return e0--separateArguments (TransformContext is0 _) e@(collectArgsTicks -> (Var g, args, ticks))- | isGlobalId g = do- -- We ensure that both the type of the global variable reference is updated- -- to take into account the changed arguments, and that we apply the global- -- function with the split apart arguments.- let (argTys0,resTy) = splitFunForallTy (varType g)- (concat -> args1, Monoid.getAny -> hasChanged)- <- listen (mapM (uncurry splitArg) (zip argTys0 args))- if hasChanged then- let (argTys1,args2) = unzip args1- gTy = mkPolyFunTy resTy argTys1- in return (mkApps (mkTicks (Var g {varType = gTy}) ticks) args2)- else- return e-- where- -- Split a single argument- splitArg- :: Either TyVar Type- -- The quantifier/function argument type of the global variable- -> Either Term Type- -- The applied type argument or term argument- -> NormalizeSession [(Either TyVar Type,Either Term Type)]- splitArg tv arg@(Right _) = return [(tv,arg)]- splitArg ty arg@(Left tmArg) = do- tcm <- Lens.view tcCache- let argTy = termType tcm tmArg- case shouldSplit tcm argTy of- Just (_,Projections projections,_) -> do- tmArgs <- projections is0 tmArg- changed (map ((ty,) . Left) tmArgs)- _ ->- return [(ty,arg)]--separateArguments _ e = return e-{-# SCC separateArguments #-}---- | Remove all undefined alternatives from case expressions, replacing them--- with the value of another defined alternative. If there is one defined--- alternative, the entire expression is replaced with that alternative. If--- there are no defined alternatives, the entire expression is replaced with--- a call to 'errorX'.------ e.g. It converts------ case x of--- D1 a -> f a--- D2 -> undefined--- D3 -> undefined------ to------ let subj = x--- a = case subj of--- D1 a -> field0--- in f a------ where fieldN is an internal variable referring to the nth argument of a--- data constructor.----xOptimize :: HasCallStack => NormRewrite-xOptimize (TransformContext is0 _) e@(Case subj ty alts) = do- runXOpt <- Lens.view aggressiveXOpt-- if runXOpt then do- defPart <- List.partitionM (isPrimError . snd) alts-- case defPart of- ([], _) -> return e- (_, []) -> changed (Prim (PrimInfo "Clash.XException.errorX" ty WorkConstant SingleResult))- (_, [alt]) -> xOptimizeSingle is0 subj alt- (_, defs) -> xOptimizeMany is0 subj ty defs- else- return e--xOptimize _ e = return e-{-# SCC xOptimize #-}---- Return an expression equivalent to the alternative given. When only one--- alternative is defined the result of this function is used to replace the--- case expression.----xOptimizeSingle :: InScopeSet -> Term -> Alt -> NormalizeSession Term-xOptimizeSingle is subj (DataPat dc tvs vars, expr) = do- tcm <- Lens.view tcCache- subjId <- mkInternalVar is "subj" (termType tcm subj)-- let fieldTys = fmap varType vars- lets <- Monad.zipWithM (mkFieldSelector is subjId dc tvs fieldTys) vars [0..]-- changed (Letrec ((subjId, subj) : lets) expr)--xOptimizeSingle _ _ (_, expr) = changed expr---- Given a list of alternatives which are defined, create a new case--- expression which only ever returns a defined value.----xOptimizeMany- :: HasCallStack- => InScopeSet- -> Term- -> Type- -> [Alt]- -> NormalizeSession Term-xOptimizeMany is subj ty defs@(d:ds)- | isAnyDefault defs = changed (Case subj ty defs)- | otherwise = do- newAlt <- xOptimizeSingle is subj d- changed (Case subj ty $ ds <> [(DefaultPat, newAlt)])- where- isAnyDefault :: [Alt] -> Bool- isAnyDefault = any ((== DefaultPat) . fst)--xOptimizeMany _ _ _ [] =- error $ $(curLoc) ++ "Report as bug: xOptimizeMany error: No defined alternatives"--mkFieldSelector- :: MonadUnique m- => InScopeSet- -> Id- -- ^ subject id- -> DataCon- -> [TyVar]- -> [Type]- -- ^ concrete types of fields- -> Id- -> Int- -> m LetBinding-mkFieldSelector is0 subj dc tvs fieldTys nm index = do- fields <- mapM (\ty -> mkInternalVar is0 "field" ty) fieldTys- let alt = (DataPat dc tvs fields, Var $ fields !! index)- return (nm, Case (Var subj) (fieldTys !! index) [alt])---- Check whether a term is really a black box primitive representing an error.--- Such values are undefined and are removed in X Optimization.----isPrimError :: Term -> NormalizeSession Bool-isPrimError (collectArgs -> (Prim pInfo, _)) = do- prim <- Lens.use (extra . primitives . Lens.at (primName pInfo))-- case prim >>= extractPrim of- Just p -> return (isErr p)- Nothing -> return False- where- isErr BlackBox{template=(BBTemplate [Err _])} = True- isErr _ = False--isPrimError _ = return False---- A multi result primitive assigns its results to multiple result variables--- instead of one. Besides producing nicer HDL it works around issues with--- synthesis tooling described in:------ https://github.com/clash-lang/clash-compiler/issues/1555------ This transformation rewrites primitives indicating they can assign their--- results to multiple signals, such that netlist can easily render it.------ Example:------ @--- prim :: forall a. a -> (a, a)--- @------ will be rewritten to:------ @--- \a0 -> let--- r = prim @t0 a0 r0 r1 -- With 'Clash.Core.Term.MultiPrim'--- r0 = multiPrimSelect r0 r--- r1 = multiPrimSelect r1 r--- in--- (x, y)--- @------ Netlist will not render any @multiPrimSelect@ primitives. Similar to--- primitives having a /void/ return type, /r/ is not rendered either.------ This transformation is currently hardcoded to recognize tuples as return--- types, not any product type. It will error if it sees a multi result primitive--- with a non-tuple return type.----setupMultiResultPrim :: HasCallStack => NormRewrite-setupMultiResultPrim _ctx e@(Prim pInfo@PrimInfo{primMultiResult=SingleResult}) = do- tcm <- Lens.view tcCache- prim <- Lens.use (extra . primitives . Lens.at (primName pInfo))-- case prim >>= extractPrim of- Just (BlackBoxHaskell{multiResult=True}) ->- changed (setupMultiResultPrim' tcm pInfo)- Just (BlackBox{multiResult=True}) ->- changed (setupMultiResultPrim' tcm pInfo)- _ ->- return e--setupMultiResultPrim _ e = return e--setupMultiResultPrim' :: HasCallStack => TyConMap -> PrimInfo -> Term-setupMultiResultPrim' tcm primInfo@PrimInfo{primType} =- mkAbstraction letTerm (map Right typeVars <> map Left argIds)- where- typeVars = Either.lefts pArgs-- internalNm prefix n = mkUnsafeInternalName (prefix <> showt n) n- internalId prefix typ n = mkLocalId typ (internalNm prefix n)-- nTermArgs = length (Either.rights pArgs)- argIds = zipWith (internalId "a") (Either.rights pArgs) [1..nTermArgs]- resIds = zipWith (internalId "r") resTypes [nTermArgs+1..nTermArgs+length resTypes]- resId = mkLocalId pResTy (mkUnsafeInternalName "r" (nTermArgs+length resTypes+1))-- (pArgs, pResTy) = splitFunForallTy primType- MultiPrimInfo{mpi_resultDc=tupTc, mpi_resultTypes=resTypes} =- multiPrimInfo' tcm primInfo-- multiPrimSelect r t = (r, mkTmApps (Prim (multiPrimSelectInfo t)) [Var r, Var resId])- multiPrimSelectBinds = zipWith multiPrimSelect resIds resTypes- multiPrimTermArgs = map (Left . Var) (argIds <> resIds)- multiPrimTypeArgs = map (Right . VarTy) typeVars- multiPrimBind =- mkApps- (Prim primInfo{primMultiResult=MultiResult})- (multiPrimTypeArgs <> multiPrimTermArgs)-- multiPrimSelectInfo t = PrimInfo- { primName = "c$multiPrimSelect"- , primType = mkPolyFunTy pResTy [Right pResTy, Right t]- , primWorkInfo = WorkAlways- , primMultiResult = SingleResult }-- letTerm =- Letrec- ((resId,multiPrimBind):multiPrimSelectBinds)- (mkTmApps (mkTyApps (Data tupTc) resTypes) (map Var resIds))---- | Inline anything of type `SimIO`: IO actions cannot be shared-inlineSimIO :: HasCallStack => NormRewrite-inlineSimIO = inlineBinders test- where- test _ (i,_) = case tyView (varType i) of- TyConApp tc _ -> return $! nameOcc tc == "Clash.Explicit.SimIO.SimIO"- _ -> return False-{-# SCC inlineSimIO #-}+ 2017-2018, Google Inc.,+ 2021 , QBayLogic B.V.+ License : BSD2 (see the file LICENSE)+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com>++ Transformations of the Normalization process+-}++module Clash.Normalize.Transformations+ ( module X+ ) where++import Clash.Normalize.Transformations.ANF as X+import Clash.Normalize.Transformations.Case as X+import Clash.Normalize.Transformations.Cast as X+import Clash.Normalize.Transformations.DEC as X+import Clash.Normalize.Transformations.EtaExpand as X+import Clash.Normalize.Transformations.Inline as X+import Clash.Normalize.Transformations.Letrec as X+import Clash.Normalize.Transformations.MultiPrim as X+import Clash.Normalize.Transformations.Reduce as X+import Clash.Normalize.Transformations.SeparateArgs as X+import Clash.Normalize.Transformations.Specialize as X+import Clash.Normalize.Transformations.XOptimize as X
+ src/Clash/Normalize/Transformations/ANF.hs view
@@ -0,0 +1,413 @@+{-|+ Copyright : (C) 2012-2016, University of Twente,+ 2016-2017, Myrtle Software Ltd,+ 2017-2018, Google Inc.,+ 2021, QBayLogic B.V.+ License : BSD2 (see the file LICENSE)+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com>++ Transformations for converting to A-Normal Form.+-}++{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++module Clash.Normalize.Transformations.ANF+ ( makeANF+ , nonRepANF+ ) where++import Control.Arrow ((***))+import Control.Lens (_2)+import qualified Control.Lens as Lens+import qualified Control.Monad as Monad+import Control.Monad.State (StateT, lift, modify, runStateT)+import Control.Monad.Writer (listen)+import Data.Bifunctor (second)+import qualified Data.Monoid as Monoid (Any(..))+import qualified Data.Text.Extra as Text (showt)+import GHC.Stack (HasCallStack)++import Clash.Signal.Internal (Signal(..))++import Clash.Core.DataCon (DataCon(..))+import Clash.Core.HasFreeVars (disjointFreeVars)+import Clash.Core.HasType+import Clash.Core.Name (mkUnsafeSystemName, nameOcc)+import Clash.Core.Subst (deshadowLetExpr, freshenTm)+import Clash.Core.Term+ ( Alt, CoreContext(..), LetBinding, Pat(..), PrimInfo(..), Term(..)+ , collectArgs, collectTicks, mkTicks, partitionTicks, stripTicks)+import Clash.Core.TermInfo (isCon, isLocalVar, isPrim, isVar)+import Clash.Core.TyCon (TyConMap)+import Clash.Core.Type (Type, TypeView(..), coreView, tyView)+import Clash.Core.Util (mkSelectorCase)+import Clash.Core.Var (Id)+import Clash.Core.VarEnv (InScopeSet, extendInScopeSet, extendInScopeSetList, mkVarSet)+import Clash.Netlist.Util (bindsExistentials)+import Clash.Normalize.Transformations.Specialize (specialize)+import Clash.Normalize.Types (NormRewrite, NormalizeSession)+import Clash.Rewrite.Combinators (bottomupR)+import Clash.Rewrite.Types+ (Transform, TransformContext(..), tcCache)+import Clash.Rewrite.Util+ (changed, isUntranslatable, mkDerivedName, mkTmBinderFor)+import Clash.Rewrite.WorkFree (isConstant, isConstantNotClockReset)+import Clash.Util (curLoc)++{- [Note: ANF in Clash]+ANF suitable for use in Clash can be described with the given types:++ data ATerm+ = ALam !Id ATerm+ | ATyLam !TyVar ATerm+ | ALetrec [(Id, CTerm)] !ITerm++ data CTerm+ = CApp !Id [Either ITerm Type]+ | CCase !ITerm !Type [(Pat, ITerm)]+ | CCast !ITerm !Type !Type+ | CPrim !PrimInfo [Either ITerm Type]+ | CTick !TickInfo CTerm++ data ITerm+ = IVar !Id+ | ILiteral !Literal+ | IData !DataCon [Either ITerm Type]+ | IPrim !PrimInfo [Either ITerm Type]+ | ITick !TickInfo ITerm++where ATerm is a term in A-normal form, CTerm is a compound term (i.e. one+which can only appear let-bound in ANF) and ITerm is an immediate term (i.e.+one which represents some simple term).++There are two constructors for primtiives, CPrim and IPrim. The difference+between these are whether the primitive performs work or not. Primitives which+perform work should be shared, but work-free primitives can be used directly.++These types help codify some invariants that must hold for the result of ANF:++ * terms start with (ty)lambdas, lambdas do not occur in let bindings or the+ the body of a letrec expression++ * there are no nested letrec expressions, only a single letrec which may+ occur after all lambdas++ * an ANF term may not have a letrec expression if the definition is already+ an immediate term, e.g. where there is no benefit in sharing the result++ * only compound terms are let-bound, as there is no benefit from let binding+ an immediate term (there is no benefit to sharing immediate terms)++ * arguments to functions / data constructors / primitives are not let bound+ if they correspond are immediate, but are if they are compound (to produce+ a variable which is an immediate term)++ * the leftmost innermost term in a function application is always an+ identifier, lambdas should have been removed by application propagation++ * the right-hand side of a case alternative is an immediate term++ * the body of the letrec expression is an immediate term++Some invariants are not captured by these types:++ * non-representable terms and terms in IO are not let-bound, instead they are+ pushed down as far as possible++ * if a let binding is created for the result, the name of the Id is "result"++TODO: The best way to enforce that Clash implements ANF compatible with these+types is to implement ANF using these types. However, as currently implemented+ANF is mostly defined using the bottom-up transformation 'collectANF'. This+would be some amount of effort to replace currently, perhaps it would be better+to convert the result of partial evaluation to these data types when it is+implemented more, then use these Anf types directly in the conversion to+netlist, i.e. Term -> Value -> Normal -> Anf -> Netlist.+-}++{- [Note: Name re-creation]+The names of heap bound variables are safely generate with mkUniqSystemId in+Clash.Core.Evaluator.newLetBinding. But only their uniqs end up in the heap,+not the complete names. So we use mkUnsafeSystemName to recreate the same Name.+-}++-- | Turn an expression into a modified ANF-form. As opposed to standard ANF,+-- constants do not become let-bound.+makeANF :: HasCallStack => NormRewrite+makeANF (TransformContext is0 ctx) (Lam bndr e) = do+ let ctx' = TransformContext (extendInScopeSet is0 bndr) (LamBody bndr : ctx)+ e' <- makeANF ctx' e+ return (Lam bndr e')++makeANF _ e@(TyLam {}) = return e++makeANF ctx@(TransformContext is0 _) e0 = do+ -- We need to freshen all binders in `e` because we're shuffling them around+ -- into a single let-binder, because even when binders don't shadow, they+ -- don't have to be unique within an expression. And so lifting them all+ -- to a single let-binder will cause issues when they're not unique.+ --+ -- We cannot make freshening part of collectANF, because when we generate+ -- new binders, we need to make sure those names do not conflict with _any_+ -- of the existing binders in the expression.+ --+ -- See also Note [ANF InScopeSet]+ let (is2,e1) = freshenTm is0 e0+ ((e2,(bndrs,_)),Monoid.getAny -> hasChanged) <-+ listen (runStateT (bottomupR collectANF ctx e1) ([],is2))+ case bndrs of+ [] -> if hasChanged then return e2 else return e0+ _ -> do+ let (e3,ticks) = collectTicks e2+ (srcTicks,nmTicks) = partitionTicks ticks+ -- Ensure that `AppendName` ticks still scope over the entire expression+ changed (mkTicks (Letrec bndrs (mkTicks e3 srcTicks)) nmTicks)+{-# SCC makeANF #-}++type NormRewriteW = Transform (StateT ([LetBinding],InScopeSet) NormalizeSession)++-- | See Note [ANF InScopeSet]+tellBinders :: [LetBinding] -> StateT ([LetBinding],InScopeSet) NormalizeSession ()+tellBinders bs = modify ((bs ++) *** (`extendInScopeSetList` (map fst bs)))++-- | See Note [ANF InScopeSet]; only extends the inscopeset+notifyBinders :: Monad m => [LetBinding] -> StateT ([LetBinding],InScopeSet) m ()+notifyBinders bs = modify (second (`extendInScopeSetList` (map fst bs)))++-- | Is the given type IO-like+isSimIOTy+ :: TyConMap+ -> Type+ -- ^ Type to check for IO-likeness+ -> Bool+isSimIOTy tcm ty = case tyView (coreView tcm ty) of+ TyConApp tcNm args+ | nameOcc tcNm == "Clash.Explicit.SimIO.SimIO"+ -> True+ | nameOcc tcNm == "GHC.Prim.(#,#)"+ , [_,_,st,_] <- args+ -> isStateTokenTy tcm st+ FunTy _ res -> isSimIOTy tcm res+ _ -> False++-- | Is the given type the state token+isStateTokenTy+ :: TyConMap+ -> Type+ -- ^ Type to check for state tokenness+ -> Bool+isStateTokenTy tcm ty = case tyView (coreView tcm ty) of+ TyConApp tcNm _ -> nameOcc tcNm == "GHC.Prim.State#"+ _ -> False++-- | Note [ANF InScopeSet]+--+-- The InScopeSet contains:+--+-- 1. All the free variables of the expression we are traversing+--+-- 2. All the bound variables of the expression we are traversing+--+-- 3. The newly created let-bindings as we recurse back up the traversal+--+-- All of these are needed to created let-bindings that+--+-- * Do not shadow+-- * Are not shadowed+-- * Nor conflict with each other (i.e. have the same unique)+--+-- Initially we start with the local InScopeSet and add the global variables:+--+-- @+-- is1 <- unionInScope is0 <$> Lens.use globalInScope+-- @+--+-- Which will gives us the (superset of) free variables of the expression. Then+-- we call 'freshenTm'+--+-- @+-- let (is2,e1) = freshenTm is1 e0+-- @+--+-- Which extends the InScopeSet with all the bound variables in 'e1', the+-- version of 'e0' where all binders are unique (not just deshadowed).+--+-- So we start out with an InScopeSet that satisfies points 1 and 2, now every+-- time we create a new binder we must add it to the InScopeSet to satisfy+-- point 3.+--+-- Note [ANF no let-bind]+--+-- | Do not let-bind:+--+-- 1. Arguments with an untranslatable type: untranslatable expressions+-- should be propagated down as far as possible+--+-- 2. Local variables or constants: they don't add any work, so no reason+-- to let-bind to enable sharing+--+-- 3. IO actions, the translation of IO actions to sequential HDL constructs+-- depends on IO actions to be propagated down as far as possible.+collectANF :: HasCallStack => NormRewriteW+collectANF ctx e@(App appf arg)+ | (conVarPrim, _) <- collectArgs e+ , isCon conVarPrim || isPrim conVarPrim || isVar conVarPrim+ = do+ tcm <- Lens.view tcCache+ untranslatable <- lift (isUntranslatable False arg)+ let localVar = isLocalVar arg+ constantNoCR = isConstantNotClockReset tcm arg+ -- See Note [ANF no let-bind]+ case (untranslatable,localVar || constantNoCR, isSimBind conVarPrim,arg) of+ (False,False,False,_) -> do+ -- See Note [ANF InScopeSet]+ is1 <- Lens.use _2+ argId <- lift (mkTmBinderFor is1 tcm (mkDerivedName ctx "app_arg") arg)+ -- See Note [ANF InScopeSet]+ tellBinders [(argId,arg)]+ return (App appf (Var argId))+ (True,False,_,Letrec binds body) -> do+ tellBinders binds+ return (App appf body)+ _ -> return e+ where+ isSimBind (Prim p) = primName p == "Clash.Explicit.SimIO.bindSimIO#"+ isSimBind _ = False++collectANF _ (Letrec binds body) = do+ tcm <- Lens.view tcCache+ let isSimIO = isSimIOTy tcm (inferCoreTypeOf tcm body)+ untranslatable <- lift (isUntranslatable False body)+ let localVar = isLocalVar body+ -- See Note [ANF no let-bind]+ if localVar || untranslatable || isSimIO+ then do+ tellBinders binds+ return body+ else do+ -- See Note [ANF InScopeSet]+ is1 <- Lens.use _2+ argId <- lift (mkTmBinderFor is1 tcm (mkUnsafeSystemName "result" 0) body)+ -- See Note [ANF InScopeSet]+ tellBinders [(argId,body)]+ tellBinders binds+ return (Var argId)++-- TODO: The code below special-cases ANF for the ':-' constructor for the+-- 'Signal' type. The 'Signal' type is essentially treated as a "transparent"+-- type by the Clash compiler, so observing its constructor leads to all kinds+-- of problems. In this case that "Clash.Rewrite.Util.mkSelectorCase" will+-- try to project the LHS and RHS of the ':-' constructor, however,+-- 'mkSelectorCase' uses 'coreView1' to find the "real" data-constructor.+-- 'coreView1' however looks through the 'Signal' type, and hence 'mkSelector'+-- finds the data constructors for the element type of Signal. This resulted in+-- error #24 (https://github.com/christiaanb/clash2/issues/24), where we+-- try to get the first field out of the 'Vec's 'Nil' constructor.+--+-- Ultimately we should stop treating Signal as a "transparent" type and deal+-- handling of the Signal type, and the involved co-recursive functions,+-- properly. At the moment, Clash cannot deal with this recursive type and the+-- recursive functions involved, hence the need for special-casing code. After+-- everything is done properly, we should remove the two lines below.+collectANF _ e@(Case _ _ [(DataPat dc _ _,_)])+ | nameOcc (dcName dc) == Text.showt '(:-) = return e++collectANF ctx (Case subj ty alts) = do+ let localVar = isLocalVar subj+ let isConstantSubj = isConstant subj++ (subj',subjBinders) <- if localVar || isConstantSubj+ then return (subj,[])+ else do+ tcm <- Lens.view tcCache+ -- See Note [ANF InScopeSet]+ is1 <- Lens.use _2+ argId <- lift (mkTmBinderFor is1 tcm (mkDerivedName ctx "case_scrut") subj)+ -- See Note [ANF InScopeSet]+ notifyBinders [(argId,subj)]+ return (Var argId,[(argId,subj)])++ tcm <- Lens.view tcCache+ let isSimIOAlt = isSimIOTy tcm ty++ alts' <- mapM (doAlt isSimIOAlt subj') alts+ tellBinders subjBinders++ case alts' of+ [(DataPat _ [] xs,altExpr)]+ | mkVarSet xs `disjointFreeVars` altExpr || isSimIOAlt+ -> return altExpr+ _ -> return (Case subj' ty alts')+ where+ doAlt :: Bool -> Term -> Alt -> StateT ([LetBinding],InScopeSet) NormalizeSession Alt+ doAlt isSimIOAlt subj' alt@(DataPat dc exts xs,altExpr) | not (bindsExistentials exts xs) = do+ let lv = isLocalVar altExpr+ patSels <- Monad.zipWithM (doPatBndr subj' dc) xs [0..]+ let altExprIsConstant = isConstant altExpr+ let usesXs (Var n) = any (== n) xs+ usesXs _ = False+ -- See [ANF no let-bind]+ if or [isSimIOAlt, lv && (not (usesXs altExpr) || length alts == 1), altExprIsConstant]+ then do+ -- See Note [ANF InScopeSet]+ tellBinders patSels+ return alt+ else do+ tcm <- Lens.view tcCache+ -- See Note [ANF InScopeSet]+ is1 <- Lens.use _2+ altId <- lift (mkTmBinderFor is1 tcm (mkDerivedName ctx "case_alt") altExpr)+ -- See Note [ANF InScopeSet]+ tellBinders (patSels ++ [(altId,altExpr)])+ return (DataPat dc exts xs,Var altId)+ doAlt _ _ alt@(DataPat {}, _) = return alt+ doAlt isSimIOAlt _ alt@(pat,altExpr) = do+ let lv = isLocalVar altExpr+ let altExprIsConstant = isConstant altExpr+ -- See [ANF no let-bind]+ if isSimIOAlt || lv || altExprIsConstant+ then return alt+ else do+ tcm <- Lens.view tcCache+ -- See Note [ANF InScopeSet]+ is1 <- Lens.use _2+ altId <- lift (mkTmBinderFor is1 tcm (mkDerivedName ctx "case_alt") altExpr)+ tellBinders [(altId,altExpr)]+ return (pat,Var altId)++ doPatBndr :: Term -> DataCon -> Id -> Int -> StateT ([LetBinding],InScopeSet) NormalizeSession LetBinding+ doPatBndr subj' dc pId i = do+ tcm <- Lens.view tcCache+ -- See Note [ANF InScopeSet]+ is1 <- Lens.use _2+ patExpr <- lift (mkSelectorCase ($(curLoc) ++ "doPatBndr") is1 tcm subj' (dcTag dc) i)+ -- No need to 'tellBinders' here because 'pId' is already in the ANF+ -- InScopeSet.+ --+ -- See also Note [ANF InScopeSet]+ return (pId,patExpr)++collectANF _ e = return e+{-# SCC collectANF #-}++-- | Bring an application of a DataCon or Primitive in ANF, when the argument is+-- is considered non-representable+nonRepANF :: HasCallStack => NormRewrite+nonRepANF ctx@(TransformContext is0 _) e@(App appConPrim arg)+ | (conPrim, _) <- collectArgs e+ , isCon conPrim || isPrim conPrim+ = do+ untranslatable <- isUntranslatable False arg+ case (untranslatable,stripTicks arg) of+ (True,Let binds body) ->+ -- This is a situation similar to Note [CaseLet deshadow]+ let (binds1,body1) = deshadowLetExpr is0 binds body+ in changed (Let binds1 (App appConPrim body1))+ (True,Case {}) -> specialize ctx e+ (True,Lam {}) -> specialize ctx e+ (True,TyLam {}) -> specialize ctx e+ _ -> return e++nonRepANF _ e = return e+{-# SCC nonRepANF #-}
+ src/Clash/Normalize/Transformations/Case.hs view
@@ -0,0 +1,702 @@+{-|+ Copyright : (C) 2012-2016, University of Twente,+ 2016-2017, Myrtle Software Ltd,+ 2017-2018, Google Inc.,+ 2021-2022, QBayLogic B.V.+ License : BSD2 (see the file LICENSE)+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com>+ Transformations on case-expressions+-}++{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++module Clash.Normalize.Transformations.Case+ ( caseCase+ , caseCon+ , caseElemNonReachable+ , caseFlat+ , caseLet+ , caseOneAlt+ , elimExistentials+ ) where++import qualified Control.Lens as Lens+import Control.Monad.State.Strict (evalState)+import Data.Bifunctor (second)+import Data.Coerce (coerce)+import qualified Data.Either as Either+import qualified Data.List as List+import qualified Data.List.Extra as List+import qualified Data.Maybe as Maybe+import qualified Data.Primitive.ByteArray as BA+import qualified Data.Text.Extra as Text (showt)+import GHC.Stack (HasCallStack)++#if MIN_VERSION_base(4,15,0)+import GHC.Num.Integer (Integer(..))+#else+import GHC.Integer.GMP.Internals (BigNat(..), Integer(..))+#endif++import Clash.Sized.Internal.BitVector as BV (BitVector, eq#)+import Clash.Sized.Internal.Index as I (Index, eq#)+import Clash.Sized.Internal.Signed as S (Signed, eq#)+import Clash.Sized.Internal.Unsigned as U (Unsigned, eq#)++import Clash.Core.DataCon (DataCon(..))+import Clash.Core.EqSolver+import Clash.Core.FreeVars (freeLocalIds, localVarsDoNotOccurIn)+import Clash.Core.HasType+import Clash.Core.Literal (Literal(..))+import Clash.Core.Name (nameOcc)+import Clash.Core.Pretty (showPpr)+import Clash.Core.Subst+import Clash.Core.Term+ ( Alt, Pat(..), PrimInfo(..), Term(..), collectArgs, collectArgsTicks+ , collectTicks, mkApps, mkTicks, patIds, stripTicks, Bind(..))+import Clash.Core.TyCon (TyConMap)+import Clash.Core.Type (LitTy(..), Type(..), TypeView(..), coreView1, tyView)+import Clash.Core.Util (listToLets, mkInternalVar)+import Clash.Core.VarEnv+ ( InScopeSet, elemVarSet, extendInScopeSet, extendInScopeSetList, mkVarSet+ , unitVarSet, uniqAway)+import Clash.Debug (traceIf)+import Clash.Driver.Types (DebugOpts(dbg_invariants))+import Clash.Netlist.Types (FilteredHWType(..), HWType(..))+import Clash.Netlist.Util (coreTypeToHWType, representableType)+import qualified Clash.Normalize.Primitives as NP (undefined)+import Clash.Normalize.Types (NormRewrite, NormalizeSession)+import Clash.Rewrite.Combinators ((>-!))+import Clash.Rewrite.Types+ ( TransformContext(..), bindings, customReprs, debugOpts, tcCache+ , typeTranslator, workFreeBinders)+import Clash.Rewrite.Util (changed, isFromInt, whnfRW)+import Clash.Rewrite.WorkFree+import Clash.Util (curLoc)++-- | Move a Case-decomposition from the subject of a Case-decomposition to the+-- alternatives+caseCase :: HasCallStack => NormRewrite+caseCase (TransformContext is0 _) e@(Case (stripTicks -> Case scrut alts1Ty alts1) alts2Ty alts2) = do+ ty1Rep <- representableType+ <$> Lens.view typeTranslator+ <*> Lens.view customReprs+ <*> pure False+ <*> Lens.view tcCache+ <*> pure alts1Ty++ -- This is only worth doing if the inner case-expression has a+ -- non-representable alternative type.+ if ty1Rep then return e else+ -- Deshadow to prevent accidental capture of free variables of inner+ -- case. Imagine:+ --+ -- case (case a of {x -> x}) of {_ -> x}+ --+ -- 'x' is introduced the inner 'case' and used (as a free variable) in+ -- the outer one. The goal of 'caseCase' is to rewrite cases such that+ -- their subjects aren't cases. This is achieved by 'pushing' the outer+ -- case to all the alternatives of the inner one. Naively doing so in+ -- this example would cause an accidental capture:+ --+ -- case a of {x -> case x of {_ -> x}}+ --+ -- Suddenly, the 'x' in the alternative of the inner case statement+ -- refers to the one introduced by the outer one, instead of being a+ -- free variable. To prevent this, we deshadow the alternatives of the+ -- original inner case. We now end up with:+ --+ -- case a of {x1 -> case x1 of {_ -> x}}+ --+ let newAlts = fmap (second (\altE -> Case altE alts2Ty alts2))+ (fmap (deShadowAlt is0) alts1)+ in changed $ Case scrut alts2Ty newAlts++caseCase _ e = return e+{-# SCC caseCase #-}++{-+NOTE: caseOneAlt before caseCon'++When you put a bang on a signal argument:+ f :: Signal d a -> _+ f !x = ...+GHC generates a case like:+ case x of+ _ :- _ -> ...++When this f is inlined in an:+ g = f (pure False)+And clash does its Signal d a ~ a thing we get:+ g = case False of+ _ :- _ -> ...+Because no pattern matches caseCon transforms this into+ g = undefined++By trying caseOneAlt first clash can instead drop the case+and use the body of the single alternative.+-}+caseCon :: HasCallStack => NormRewrite+caseCon = const caseOneAlt >-! caseCon'++-- | Specialize a Case-decomposition (replace by the RHS of an alternative) if+-- the subject is (an application of) a DataCon; or if there is only a single+-- alternative that doesn't reference variables bound by the pattern.+--+-- Note [CaseCon deshadow]+--+-- Imagine:+--+-- @+-- case D (f a b) (g x y) of+-- D a b -> h a+-- @+--+-- rewriting this to:+--+-- @+-- let a = f a b+-- in h a+-- @+--+-- is very bad because the newly introduced let-binding now captures the free+-- variable 'a' in 'f a b'.+--+-- instead me must rewrite to:+--+-- @+-- let a1 = f a b+-- in h a1+-- @+caseCon' :: HasCallStack => NormRewrite+caseCon' ctx@(TransformContext is0 _) e@(Case subj ty alts) = do+ tcm <- Lens.view tcCache+ case collectArgsTicks subj of+ -- The subject is an applied data constructor+ (Data dc, args, ticks) -> case List.find (equalCon . fst) alts of+ Just (DataPat _ tvs xs, altE) -> do+ let+ -- Create the substitution environment for all the existential+ -- type variables.+ exTysList = List.zipEqual tvs (drop (length (dcUnivTyVars dc)) (Either.rights args))+ exTySubst = extendTvSubstList (mkSubst is0) exTysList+ -- Apply the type-substitution in all the pattern variables, we need+ -- to do this because we might use them as let-bindings later on,+ -- and they should have the correct type.+ xs1 = fmap (substTyInVar exTySubst) xs+ -- Create an initial set of let-binders for all variables used in the+ -- RHS of the alternative. We might later decide to substitute instead+ -- of let-bind in case the RHS of the let-binder is work-free.+ fvs = Lens.foldMapOf freeLocalIds unitVarSet altE+ (binds,_) = List.partition ((`elemVarSet` fvs) . fst)+ $ List.zipEqual xs1 (Either.lefts args)+ binds1 = fmap (second (`mkTicks` ticks)) binds+ altE1 <-+ case binds1 of+ [] ->+ -- Apply the type-substitution for the existential type variables+ pure (substTm "caseCon'" exTySubst altE)+ _ -> do+ -- See Note [CaseCon deshadow]+ let+ -- Only let-bind expression that perform work.+ is1 = extendInScopeSetList (extendInScopeSetList is0 tvs) xs1+ ((is3,substIds),binds2) <- List.mapAccumLM newBinder (is1,[]) binds1+ let+ -- Create a substitution for all the existential type variables+ -- and the work-free expressions+ subst = mkSubst is3+ `extendTvSubstList` exTysList+ `extendIdSubstList` substIds+ body = substTm "caseCon'" subst altE+ case Maybe.catMaybes binds2 of+ [] -> pure body+ -- Use listToLets to create a series of non-recursive lets instead+ -- of a recursive group. We know these binders will not form a group.+ binds3 -> pure (listToLets binds3 body)+ changed altE1+ _ -> case alts of+ -- In Core, default patterns always come first, so we match against+ -- that if there is one, and we couldn't match with any of the data+ -- patterns.+ ((DefaultPat,altE):_) -> changed altE+ _ -> changed (TyApp (Prim NP.undefined) ty)+ where+ -- Check whether the pattern matches the data constructor+ equalCon (DataPat dcPat _ _) = dcTag dc == dcTag dcPat+ equalCon _ = False++ -- Decide whether the applied arguments of the data constructor should+ -- be let-bound, or substituted into the alternative. We decide this+ -- based on the fact on whether the argument has the potential to make+ -- the circuit larger than needed if we were to duplicate that argument.+ newBinder (isN0, substN) (x, arg) = do+ bndrs <- Lens.use bindings+ isWorkFree workFreeBinders bndrs arg >>= \case+ True -> pure ((isN0, (x, arg):substN), Nothing)+ False ->+ let+ x' = uniqAway isN0 x+ isN1 = extendInScopeSet isN0 x'+ in+ pure ((isN1, (x, Var x'):substN), Just (x', arg))++ -- The subject is a literal+ (Literal l,_,_) -> case List.find (equalLit . fst) alts of+ Just (LitPat _,altE) -> changed altE+ _ -> matchLiteralContructor e l alts+ where+ equalLit (LitPat l') = l == l'+ equalLit _ = False++ -- The subject is an applied primitive+ (Prim _,_,_) ->+ -- We try to reduce the applied primitive to WHNF+ whnfRW True ctx subj $ \ctx1 subj1 -> case collectArgsTicks subj1 of+ -- WHNF of subject is a literal, try `caseCon` with that+ (Literal l,_,_) -> caseCon ctx1 (Case (Literal l) ty alts)+ -- WHNF of subject is a data-constructor, try `caseCon` with that+ (Data _,_,_) -> caseCon ctx1 (Case subj1 ty alts)+ -- WHNF of subject is _|_, in the form of `absentError`: that means that+ -- the entire case-expression is evaluates to _|_+ (Prim pInfo,_:msgOrCallStack:_,ticks)+ | primName pInfo == "Control.Exception.Base.absentError" ->+ let e1 = mkApps (mkTicks (Prim pInfo) ticks)+ [Right ty,msgOrCallStack]+ in changed e1+ -- WHNF of subject is _|_, in the form of `absentError`, `patError`,+ -- or `undefined`: that means the entire case-expression is _|_+ (Prim pInfo,repTy:_:msgOrCallStack:_,ticks)+ | primName pInfo `elem` ["Control.Exception.Base.patError"+ ,"GHC.Err.undefined"] ->+ let e1 = mkApps (mkTicks (Prim pInfo) ticks)+ [repTy,Right ty,msgOrCallStack]+ in changed e1+ -- WHNF of subject is _|_, in the form of our internal _|_-values: that+ -- means the entire case-expression is _|_+ (Prim pInfo,[_],ticks)+ | primName pInfo `elem` [ Text.showt 'NP.undefined+ , "Clash.GHC.Evaluator.undefined"+ , "EmptyCase"] ->+ let e1 = mkApps (mkTicks (Prim pInfo) ticks) [Right ty]+ in changed e1+ (Prim pInfo,_:callStack:msg:_,_)+ | primName pInfo == "Clash.XException.errorX"+ -> let e1 = mkApps (Prim pInfo) [Right ty,callStack,msg]+ in changed e1+ -- WHNF of subject is non of the above, so either a variable reference,+ -- or a primitive for which the evaluator doesn't have any evaluation+ -- rules.+ _ -> do+ let subjTy = inferCoreTypeOf tcm subj+ tran <- Lens.view typeTranslator+ reprs <- Lens.view customReprs+ case (`evalState` mempty) (coreTypeToHWType tran reprs tcm subjTy) of+ Right (FilteredHWType (Void (Just hty)) _areVoids)+ | hty `elem` [BitVector 0, Unsigned 0, Signed 0, Index 1]+ -- If we know that the type of the subject is zero-bits wide and+ -- one of the Clash number types. Then the only valid alternative is+ -- the one that can match on the literal "0", so try 'caseCon' with+ -- that.+ -> caseCon ctx1 (Case (Literal (IntegerLiteral 0)) ty alts)+ _ -> do+ opts <- Lens.view debugOpts+ -- When invariants are being checked, report missing evaluation+ -- rules for the primitive evaluator.+ traceIf (dbg_invariants opts && isConstant subj)+ ("Unmatchable constant as case subject: " ++ showPpr subj +++ "\nWHNF is: " ++ showPpr subj1)+ -- Otherwise check whether the entire case-expression has a+ -- single alternative, and pick that one.+ (caseOneAlt e)++ -- The subject is a variable+ (Var v, [], _) | isNum0 (coreTypeOf v) ->+ -- If we know that the type of the subject is zero-bits wide and+ -- one of the Clash number types. Then the only valid alternative is+ -- the one that can match on the literal "0", so try 'caseCon' with+ -- that.+ caseCon ctx (Case (Literal (IntegerLiteral 0)) ty alts)+ where+ isNum0 (tyView -> TyConApp (nameOcc -> tcNm) [arg])+ | tcNm `elem`+ [ Text.showt ''BitVector+ , Text.showt ''Signed+ , Text.showt ''Unsigned+ ]+ = isLitX 0 arg+ | tcNm == Text.showt ''Index+ = isLitX 1 arg+ isNum0 (coreView1 tcm -> Just t) = isNum0 t+ isNum0 _ = False++ isLitX n (LitTy (NumTy m)) = n == m+ isLitX n (coreView1 tcm -> Just t) = isLitX n t+ isLitX _ _ = False++ -- Otherwise check whether the entire case-expression has a single+ -- alternative, and pick that one.+ _ -> caseOneAlt e++caseCon' _ e = return e+{-# SCC caseCon' #-}++{- [Note: Name re-creation]+The names of heap bound variables are safely generate with mkUniqSystemId in Clash.Core.Evaluator.newLetBinding.+But only their uniqs end up in the heap, not the complete names.+So we use mkUnsafeSystemName to recreate the same Name.+-}++matchLiteralContructor+ :: Term+ -> Literal+ -> [Alt]+ -> NormalizeSession Term+matchLiteralContructor c (IntegerLiteral l) alts = go (reverse alts)+ where+ go [(DefaultPat,e)] = changed e+ go ((DataPat dc [] [x],e):alts')+ | dcTag dc == 1+ , l >= ((-2)^(63::Int)) && l < 2^(63::Int)+ = let fvs = Lens.foldMapOf freeLocalIds unitVarSet e+ bind = NonRec x (Literal (IntLiteral l))+ in if x `elemVarSet` fvs+ then changed (Let bind e)+ else changed e+ | dcTag dc == 2+ , l >= 2^(63::Int)+#if MIN_VERSION_base(4,15,0)+ = let !(IP ba) = l+#else+ = let !(Jp# !(BN# ba)) = l+#endif+ ba' = BA.ByteArray ba+ fvs = Lens.foldMapOf freeLocalIds unitVarSet e+ bind = NonRec x (Literal (ByteArrayLiteral ba'))+ in if x `elemVarSet` fvs+ then changed (Let bind e)+ else changed e+ | dcTag dc == 3+ , l < ((-2)^(63::Int))+#if MIN_VERSION_base(4,15,0)+ = let !(IN ba) = l+#else+ = let !(Jn# !(BN# ba)) = l+#endif+ ba' = BA.ByteArray ba+ fvs = Lens.foldMapOf freeLocalIds unitVarSet e+ bind = NonRec x (Literal (ByteArrayLiteral ba'))+ in if x `elemVarSet` fvs+ then changed (Let bind e)+ else changed e+ | otherwise+ = go alts'+ go ((LitPat l', e):alts')+ | IntegerLiteral l == l'+ = changed e+ | otherwise+ = go alts'+ go _ = error $ $(curLoc) ++ "Report as bug: caseCon error: " ++ showPpr c++matchLiteralContructor c (NaturalLiteral l) alts = go (reverse alts)+ where+ go [(DefaultPat,e)] = changed e+ go ((DataPat dc [] [x],e):alts')+ | dcTag dc == 1+ , l >= 0 && l < 2^(64::Int)+ = let fvs = Lens.foldMapOf freeLocalIds unitVarSet e+ bind = NonRec x (Literal (WordLiteral l))+ in if x `elemVarSet` fvs+ then changed (Let bind e)+ else changed e+ | dcTag dc == 2+ , l >= 2^(64::Int)+#if MIN_VERSION_base(4,15,0)+ = let !(IP ba) = l+#else+ = let !(Jp# !(BN# ba)) = l+#endif+ ba' = BA.ByteArray ba+ fvs = Lens.foldMapOf freeLocalIds unitVarSet e+ bind = NonRec x (Literal (ByteArrayLiteral ba'))+ in if x `elemVarSet` fvs+ then changed (Let bind e)+ else changed e+ | otherwise+ = go alts'+ go ((LitPat l', e):alts')+ | NaturalLiteral l == l'+ = changed e+ | otherwise+ = go alts'+ go _ = error $ $(curLoc) ++ "Report as bug: caseCon error: " ++ showPpr c++matchLiteralContructor _ _ ((DefaultPat,e):_) = changed e+matchLiteralContructor c _ _ =+ error $ $(curLoc) ++ "Report as bug: caseCon error: " ++ showPpr c+{-# SCC matchLiteralContructor #-}++-- | Remove non-reachable alternatives. For example, consider:+--+-- data STy ty where+-- SInt :: Int -> STy Int+-- SBool :: Bool -> STy Bool+--+-- f :: STy ty -> ty+-- f (SInt b) = b + 1+-- f (SBool True) = False+-- f (SBool False) = True+-- {-# NOINLINE f #-}+--+-- g :: STy Int -> Int+-- g = f+--+-- @f@ is always specialized on @STy Int@. The SBool alternatives are therefore+-- unreachable. Additional information can be found at:+-- https://github.com/clash-lang/clash-compiler/pull/465+caseElemNonReachable :: HasCallStack => NormRewrite+caseElemNonReachable _ case0@(Case scrut altsTy alts0) = do+ tcm <- Lens.view tcCache++ let (altsAbsurd, altsOther) = List.partition (isAbsurdPat tcm . fst) alts0+ case altsAbsurd of+ [] -> return case0+ _ -> changed =<< caseOneAlt (Case scrut altsTy altsOther)++caseElemNonReachable _ e = return e+{-# SCC caseElemNonReachable #-}++-- | Flatten ridiculous case-statements generated by GHC+--+-- For case-statements in haskell of the form:+--+-- @+-- f :: Unsigned 4 -> Unsigned 4+-- f x = case x of+-- 0 -> 3+-- 1 -> 2+-- 2 -> 1+-- 3 -> 0+-- @+--+-- GHC generates Core that looks like:+--+-- @+-- f = \(x :: Unsigned 4) -> case x == fromInteger 3 of+-- False -> case x == fromInteger 2 of+-- False -> case x == fromInteger 1 of+-- False -> case x == fromInteger 0 of+-- False -> error "incomplete case"+-- True -> fromInteger 3+-- True -> fromInteger 2+-- True -> fromInteger 1+-- True -> fromInteger 0+-- @+--+-- Which would result in a priority decoder circuit where a normal decoder+-- circuit was desired.+--+-- This transformation transforms the above Core to the saner:+--+-- @+-- f = \(x :: Unsigned 4) -> case x of+-- _ -> error "incomplete case"+-- 0 -> fromInteger 3+-- 1 -> fromInteger 2+-- 2 -> fromInteger 1+-- 3 -> fromInteger 0+-- @+caseFlat :: HasCallStack => NormRewrite+caseFlat (TransformContext is0 _) e@(Case (collectEqArgs -> Just (scrut',val)) ty _) =+ case collectFlat scrut' e of+ Just alts' -> case collectArgs val of+ -- When we're pattern matching on `Int`, extract the `Int#` first before+ -- we do the Literal matching branches.+ (Data dc,_)+ | nameOcc (dcName dc) == "GHC.Types.I#"+ , [argTy] <- dcArgTys dc+ -> do+ wild <- mkInternalVar is0 "wild" argTy+ changed (Case scrut' ty+ [(DataPat dc [] [wild]+ ,Case (Var wild) ty (last alts' : init alts'))])+ _ -> changed (Case scrut' ty (last alts' : init alts'))+ Nothing -> return e++caseFlat _ e = return e+{-# SCC caseFlat #-}++collectFlat :: Term -> Term -> Maybe [Alt]+collectFlat scrut (Case (collectEqArgs -> Just (scrut', val)) _ty [lAlt,rAlt])+ | scrut' == scrut+ = case collectArgs val of+ (Prim p,args') | isFromInt (primName p) ->+ go (last args')+ (Data dc,args') | nameOcc (dcName dc) == "GHC.Types.I#" ->+ go (last args')+ _ -> Nothing+ where+ go (Left (Literal i)) = case (lAlt,rAlt) of+ ((pl,el),(pr,er))+ | isFalseDcPat pl || isTrueDcPat pr ->+ case collectFlat scrut el of+ Just alts' -> Just ((LitPat i, er) : alts')+ Nothing -> Just [(LitPat i, er)+ ,(DefaultPat, el)+ ]+ | otherwise ->+ case collectFlat scrut er of+ Just alts' -> Just ((LitPat i, el) : alts')+ Nothing -> Just [(LitPat i, el)+ ,(DefaultPat, er)+ ]+ go _ = Nothing++ isFalseDcPat (DataPat p _ _)+ = ((== "GHC.Types.False") . nameOcc . dcName) p+ isFalseDcPat _ = False++ isTrueDcPat (DataPat p _ _)+ = ((== "GHC.Types.True") . nameOcc . dcName) p+ isTrueDcPat _ = False++collectFlat _ _ = Nothing+{-# SCC collectFlat #-}++collectEqArgs :: Term -> Maybe (Term,Term)+collectEqArgs (collectArgsTicks -> (Prim p, args, ticks))+ | nm == Text.showt 'BV.eq#+ = let [_,_,Left scrut,Left val] = args+ in Just (mkTicks scrut ticks,val)+ | nm == Text.showt 'I.eq# ||+ nm == Text.showt 'S.eq# ||+ nm == Text.showt 'U.eq#+ = let [_,Left scrut,Left val] = args+ in Just (mkTicks scrut ticks,val)+ | nm == "GHC.Classes.eqInt"+ = let [Left scrut,Left val] = args+ in Just (mkTicks scrut ticks,val)+ where+ nm = primName p++collectEqArgs _ = Nothing++-- | Lift the let-bindings out of the subject of a Case-decomposition+caseLet :: HasCallStack => NormRewrite+caseLet (TransformContext is0 _) (Case (collectTicks -> (Let xes e,ticks)) ty alts) = do+ -- Note [CaseLet deshadow]+ -- Imagine+ --+ -- @+ -- case (let x = u in e) of {p -> a}+ -- @+ --+ -- where `a` has a free variable named `x`.+ --+ -- Simply transforming the above to:+ --+ -- @+ -- let x = u in case e of {p -> a}+ -- @+ --+ -- would be very bad, because now the let-binding captures the free x variable+ -- in a.+ --+ -- We must therefor rename `x` so that it doesn't capture the free variables+ -- in the alternative:+ --+ -- @+ -- let x1 = u[x:=x1] in case e[x:=x1] of {p -> a}+ -- @+ --+ -- It is safe to over-approximate the free variables in `a` by simply taking+ -- the current InScopeSet.+ let (xes1,e1) = deshadowLetExpr is0 xes e+ changed (Let (fmap (`mkTicks` ticks) xes1)+ (Case (mkTicks e1 ticks) ty alts))++caseLet _ e = return e+{-# SCC caseLet #-}++caseOneAlt :: Term -> NormalizeSession Term+caseOneAlt e@(Case _ _ [(pat,altE)]) =+ case pat of+ DefaultPat -> changed altE+ LitPat _ -> changed altE+ DataPat _ tvs xs+ | (coerce tvs ++ coerce xs) `localVarsDoNotOccurIn` altE+ -> changed altE+ | otherwise+ -> return e++caseOneAlt (Case _ _ alts@((pat,alt):_:_))+ | all ((== alt) . snd) (tail alts)+ , (tvs,xs) <- patIds pat+ , (coerce tvs ++ coerce xs) `localVarsDoNotOccurIn` alt+ = changed alt++caseOneAlt e = return e+{-# SCC caseOneAlt #-}++-- | Tries to eliminate existentials by using heuristics to determine what the+-- existential should be. For example, consider Vec:+--+-- data Vec :: Nat -> Type -> Type where+-- Nil :: Vec 0 a+-- Cons x xs :: a -> Vec n a -> Vec (n + 1) a+--+-- Thus, 'null' (annotated with existentials) could look like:+--+-- null :: forall n . Vec n Bool -> Bool+-- null v =+-- case v of+-- Nil {n ~ 0} -> True+-- Cons {n1:Nat} {n~n1+1} (x :: a) (xs :: Vec n1 a) -> False+--+-- When it's applied to a vector of length 5, this becomes:+--+-- null :: Vec 5 Bool -> Bool+-- null v =+-- case v of+-- Nil {5 ~ 0} -> True+-- Cons {n1:Nat} {5~n1+1} (x :: a) (xs :: Vec n1 a) -> False+--+-- This function solves 'n1' and replaces every occurrence with its solution. A+-- very limited number of solutions are currently recognized: only adds (such+-- as in the example) will be solved.+elimExistentials :: HasCallStack => NormRewrite+elimExistentials (TransformContext is0 _) (Case scrut altsTy alts0) = do+ tcm <- Lens.view tcCache+ alts1 <- traverse (go is0 tcm) alts0+ caseOneAlt (Case scrut altsTy alts1)+ where+ -- Eliminate free type variables if possible+ go :: InScopeSet -> TyConMap -> Alt -> NormalizeSession Alt+ go is2 tcm alt@(pat@(DataPat dc exts0 xs0), term0) =+ case solveNonAbsurds tcm (mkVarSet exts0) (patEqs tcm pat) of+ -- No equations solved:+ [] -> return alt+ -- One or more equations solved:+ sols ->+ changed =<< go is2 tcm (DataPat dc exts1 xs1, term1)+ where+ -- Substitute solution in existentials and applied types+ is3 = extendInScopeSetList is2 exts0+ xs1 = fmap (substTyInVar (extendTvSubstList (mkSubst is3) sols)) xs0+ exts1 = substInExistentialsList is2 exts0 sols++ -- Substitute solution in term.+ is4 = extendInScopeSetList is3 xs1+ subst = extendTvSubstList (mkSubst is4) sols+ term1 = substTm "Replacing tyVar due to solved eq" subst term0++ go _ _ alt = return alt++elimExistentials _ e = return e+{-# SCC elimExistentials #-}
+ src/Clash/Normalize/Transformations/Cast.hs view
@@ -0,0 +1,146 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE TemplateHaskell #-}++module Clash.Normalize.Transformations.Cast+ ( argCastSpec+ , caseCast+ , elimCastCast+ , letCast+ , splitCastWork+ ) where++import Control.Exception (throw)+import qualified Control.Lens as Lens+import Control.Monad.Writer (listen)+import qualified Data.Monoid as Monoid (Any(..))+import GHC.Stack (HasCallStack)++import Clash.Core.Name (nameOcc)+import Clash.Core.Pretty (showPpr)+import Clash.Core.Term (LetBinding, Term(..), collectArgs, stripTicks)+import Clash.Core.TermInfo (isCast)+import Clash.Core.Type (normalizeType)+import Clash.Core.Var (isGlobalId, varName)+import Clash.Core.VarEnv (InScopeSet)+import Clash.Debug (trace)+import Clash.Normalize.Transformations.Specialize (specialize)+import Clash.Normalize.Types (NormRewrite, NormalizeSession)+import Clash.Rewrite.Types+ (TransformContext(..), bindings, curFun, tcCache, workFreeBinders)+import Clash.Rewrite.Util (changed, mkDerivedName, mkTmBinderFor)+import Clash.Rewrite.WorkFree (isWorkFree)+import Clash.Util (ClashException(..), curLoc)++-- | Push cast over an argument to a function into that function+--+-- This is done by specializing on the casted argument.+-- Example:+-- @+-- y = f (cast a)+-- where f x = g x+-- @+-- transforms to:+-- @+-- y = f' a+-- where f' x' = (\x -> g x) (cast x')+-- @+--+-- The reason d'etre for this transformation is that we hope to end up with+-- and expression where two casts are "back-to-back" after which we can+-- eliminate them in 'eliminateCastCast'.+argCastSpec :: HasCallStack => NormRewrite+argCastSpec ctx e@(App f (stripTicks -> Cast e' _ _))+ -- Don't specialise when the arguments are casts-of-casts, these casts-of-casts+ -- will be eliminated by 'eliminateCastCast' during the normalization of the+ -- "current" function. We thus prevent the unnecessary introduction of a+ -- specialized version of 'f'.+ | not (isCast e')+ -- We can only push casts into global binders+ , (Var g, _) <- collectArgs f+ , isGlobalId g = do+ bndrs <- Lens.use bindings+ isWorkFree workFreeBinders bndrs e' >>= \case+ True -> go+ False -> warn go+ where+ go = specialize ctx e+ warn = trace (unwords+ [ "WARNING:", $(curLoc), "specializing a function on a non work-free"+ , "cast. Generated HDL implementation might contain duplicate work."+ , "Please report this as a bug.", "\n\nExpression where this occured:"+ , "\n\n" ++ showPpr e+ ])+argCastSpec _ e = return e+{-# SCC argCastSpec #-}++-- | Push a cast over a case into it's alternatives.+caseCast :: HasCallStack => NormRewrite+caseCast _ (Cast (stripTicks -> Case subj ty alts) ty1 ty2) = do+ let alts' = map (\(p,e) -> (p, Cast e ty1 ty2)) alts+ changed (Case subj ty alts')+caseCast _ e = return e+{-# SCC caseCast #-}++-- | Eliminate two back to back casts where the type going in and coming out are the same+--+-- @+-- (cast :: b -> a) $ (cast :: a -> b) x ==> x+-- @+elimCastCast :: HasCallStack => NormRewrite+elimCastCast _ c@(Cast (stripTicks -> Cast e tyA tyB) tyB' tyC) = do+ tcm <- Lens.view tcCache+ let ntyA = normalizeType tcm tyA+ ntyB = normalizeType tcm tyB+ ntyB' = normalizeType tcm tyB'+ ntyC = normalizeType tcm tyC+ if ntyB == ntyB' && ntyA == ntyC then changed e+ else throwError+ where throwError = do+ (nm,sp) <- Lens.use curFun+ throw (ClashException sp ($(curLoc) ++ showPpr nm+ ++ ": Found 2 nested casts whose types don't line up:\n"+ ++ showPpr c)+ Nothing)++elimCastCast _ e = return e+{-# SCC elimCastCast #-}++-- | Push a cast over a Let into it's body+letCast :: HasCallStack => NormRewrite+letCast _ (Cast (stripTicks -> Let binds body) ty1 ty2) =+ changed $ Let binds (Cast body ty1 ty2)+letCast _ e = return e+{-# SCC letCast #-}++-- | Make a cast work-free by splitting the work of to a separate binding+--+-- @+-- let x = cast (f a b)+-- ==>+-- let x = cast x'+-- x' = f a b+-- @+splitCastWork :: HasCallStack => NormRewrite+splitCastWork ctx@(TransformContext is0 _) unchanged@(Letrec vs e') = do+ (vss', Monoid.getAny -> hasChanged) <- listen (mapM (splitCastLetBinding is0) vs)+ let vs' = concat vss'+ if hasChanged then changed (Letrec vs' e')+ else return unchanged+ where+ splitCastLetBinding+ :: InScopeSet+ -> LetBinding+ -> NormalizeSession [LetBinding]+ splitCastLetBinding isN x@(nm, e) = case stripTicks e of+ Cast (Var {}) _ _ -> return [x] -- already work-free+ Cast (Cast {}) _ _ -> return [x] -- casts will be eliminated+ Cast e0 ty1 ty2 -> do+ tcm <- Lens.view tcCache+ nm' <- mkTmBinderFor isN tcm (mkDerivedName ctx (nameOcc $ varName nm)) e0+ changed [(nm',e0)+ ,(nm, Cast (Var nm') ty1 ty2)+ ]+ _ -> return [x]++splitCastWork _ e = return e+{-# SCC splitCastWork #-}
+ src/Clash/Normalize/Transformations/DEC.hs view
@@ -0,0 +1,777 @@+{-|+ Copyright : (C) 2015-2016, University of Twente,+ 2021, QBayLogic B.V.+ License : BSD2 (see the file LICENSE)+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com>++ The 'disjointExpressionConsolidation' transformation lifts applications of+ global binders out of alternatives of case-statements.++ e.g. It converts:++ > case x of+ > A -> f 3 y+ > B -> f x x+ > C -> h x++ into:++ > let f_arg0 = case x of {A -> 3; B -> x}+ > f_arg1 = case x of {A -> y; B -> x}+ > f_out = f f_arg0 f_arg1+ > in case x of+ > A -> f_out+ > B -> f_out+ > C -> h x+-}++{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecursiveDo #-}+{-# LANGUAGE TemplateHaskell #-}++module Clash.Normalize.Transformations.DEC+ ( disjointExpressionConsolidation+ ) where++import Control.Concurrent.Supply (splitSupply)+import Control.Lens ((^.), _1)+import qualified Control.Lens as Lens+import qualified Control.Monad as Monad+import Data.Bifunctor (second)+import Data.Bits ((.&.), complement)+import Data.Coerce (coerce)+import qualified Data.Either as Either+import qualified Data.Foldable as Foldable+import qualified Data.Graph as Graph+import Data.IntMap.Strict (IntMap)+import qualified Data.IntMap.Strict as IntMap+import qualified Data.IntSet as IntSet+import qualified Data.List as List+import qualified Data.List.Extra as List+import qualified Data.Map.Strict as Map+import qualified Data.Maybe as Maybe+import Data.Monoid (All(..))+import qualified Data.Text as Text+import GHC.Stack (HasCallStack)++#if MIN_VERSION_ghc(8,10,0)+import GHC.Hs.Utils (chunkify, mkChunkified)+#else+import HsUtils (chunkify, mkChunkified)+#endif++#if MIN_VERSION_ghc(9,0,0)+import GHC.Settings.Constants (mAX_TUPLE_SIZE)+#else+import Constants (mAX_TUPLE_SIZE)+#endif++-- internal+import Clash.Core.DataCon (DataCon)+import Clash.Core.Evaluator.Types (whnf')+import Clash.Core.FreeVars+ (termFreeVars', typeFreeVars', localVarsDoNotOccurIn)+import Clash.Core.HasType+import Clash.Core.Literal (Literal(..))+import Clash.Core.Name (nameOcc)+import Clash.Core.Term+ ( Alt, LetBinding, Pat(..), PrimInfo(..), Term(..), TickInfo(..)+ , collectArgs, collectArgsTicks, mkApps, mkTicks, patIds)+import Clash.Core.TyCon (TyConMap, TyConName, tyConDataCons)+import Clash.Core.Type (Type, isPolyFunTy, mkTyConApp, splitFunForallTy)+import Clash.Core.Util (mkInternalVar, mkSelectorCase, sccLetBindings)+import Clash.Core.Var (isGlobalId, isLocalId, varName)+import Clash.Core.VarEnv+ ( InScopeSet, elemInScopeSet, extendInScopeSet, extendInScopeSetList+ , notElemInScopeSet, unionInScope)+import Clash.Normalize.Transformations.Letrec (deadCode)+import Clash.Normalize.Types (NormRewrite, NormalizeSession)+import Clash.Rewrite.Combinators (bottomupR)+import Clash.Rewrite.Types+import Clash.Rewrite.Util (changed, isUntranslatableType)+import Clash.Rewrite.WorkFree (isConstant)+import Clash.Unique (lookupUniqMap)+import Clash.Util (MonadUnique, curLoc)++-- | This transformation lifts applications of global binders out of+-- alternatives of case-statements.+--+-- e.g. It converts:+--+-- @+-- case x of+-- A -> f 3 y+-- B -> f x x+-- C -> h x+-- @+--+-- into:+--+-- @+-- let f_arg0 = case x of {A -> 3; B -> x}+-- f_arg1 = case x of {A -> y; B -> x}+-- f_out = f f_arg0 f_arg1+-- in case x of+-- A -> f_out+-- B -> f_out+-- C -> h x+-- @+disjointExpressionConsolidation :: HasCallStack => NormRewrite+disjointExpressionConsolidation ctx@(TransformContext isCtx _) e@(Case _scrut _ty _alts@(_:_:_)) = do+ -- Collect all (the applications of) global binders (and certain primitives)+ -- that would be interesting to share out of the case-alternatives.+ (_,isCollected,collected) <- collectGlobals isCtx [] [] e+ -- Filter those that are used at most once in every (nested) branch.+ let disJoint = filter (isDisjoint . snd . snd) collected+ if null disJoint+ then return e+ else do+ -- For every to-lift expression create (the generalization of):+ --+ -- let fargs = case x of {A -> (3,y); B -> (x,x)}+ -- in f (fst fargs) (snd fargs)+ --+ -- the let-expression is not created when `f` has only one (selectable)+ -- argument+ --+ -- NB: mkDisJointGroup needs the context InScopeSet, isCtx, to determine+ -- whether expressions reference variables from the context, or+ -- variables inside a let-expression inside one of the alternatives.+ lifted <- mapM (mkDisjointGroup isCtx) disJoint+ tcm <- Lens.view tcCache+ -- Create let-binders for all of the lifted expressions+ --+ -- NB: Because we will be substituting under binders we use the collected+ -- inScopeSet, isCollected, which also contains all the binders+ -- created inside all of the alternatives. With this inScopeSet, we+ -- ensure that the let-bindings we create here won't be accidentally+ -- captured by binders inside the case-alternatives.+ (_,funOutIds) <- List.mapAccumLM (mkFunOut tcm)+ isCollected+ (zip disJoint lifted)+ -- Create "substitutions" of the form [f X Y := f_out]+ let substitution = zip (map fst disJoint) (map Var funOutIds)+ -- For all of the lifted expression: substitute occurrences of the+ -- disjoint expressions (f X Y) by a variable reference to the lifted+ -- expression (f_out)+ let isCtx1 = extendInScopeSetList isCtx funOutIds+ lifted1 <- substLifted isCtx1 substitution lifted+ -- Do the same for the actual case expression+ (e1,_,_) <- collectGlobals isCtx1 substitution [] e+ -- Let-bind all the lifted function+ let lb = Letrec (zip funOutIds lifted1) e1+ -- Do an initial dead-code elimination pass, as `mkDisJoint` doesn't+ -- clean-up unused let-binders.+ lb1 <- bottomupR deadCode ctx lb+ changed lb1+ where+ -- Make the let-binder for the lifted expressions+ mkFunOut tcm isN ((fun,_),(eLifted,_)) = do+ let ty = inferCoreTypeOf tcm eLifted+ nm = case collectArgs fun of+ (Var v,_) -> nameOcc (varName v)+ (Prim p,_) -> primName p+ _ -> "complex_expression_"+ nm1 = last (Text.splitOn "." nm) `Text.append` "Out"+ nm2 <- mkInternalVar isN nm1 ty+ return (extendInScopeSet isN nm2,nm2)++ -- Substitute inside the lifted expressions+ --+ -- In case you are wondering why this function isn't simply+ --+ -- > mapM (\s (eL,seen) -> collectGlobal isN s seen eL) substitution lifted+ --+ -- then that's because we have e.g. the list of "substitutions":+ --+ -- [foo _ _ := foo_out; bar _ _ := bar_out]+ --+ -- and if we were to apply that to a lifted expression, which is going+ -- to be of the form `foo (case ...) (case ...)` then we would end up+ -- with let-bindings that are simply:+ --+ -- > let foo_out = foo_out ; bar_out = bar_out+ --+ -- instead of the desired+ --+ -- > let foo_out = foo ((case ...)[foo _ _ := foo_out; bar _ _ := bar_out])+ -- > ((case ...)[foo _ _ := foo_out; bar _ _ := bar_out])+ -- > bar_out = bar ((case ...)[foo _ _ := foo_out; bar _ _ := bar_out])+ -- > ((case ...)[foo _ _ := foo_out; bar _ _ := bar_out])+ --+ -- So what we do is that for every lifted-expression we make sure that the+ -- 'substitution' never contains the self-substitution, so we end up with:+ --+ -- > let foo_out = (foo (case ...) (case ...))[bar _ _ := bar_out]+ -- bar_out = (bar (case ...) (case ...))[foo _ _ := foo_out]+ --+ -- We used to have a different approach, see commit+ -- 73d237017c4a5fff0c49bb72c9c4d5f6c68faf69+ --+ -- But that lead to the generation of combinational loops. Now that we no+ -- longer traverse into recursive groups of let-bindings, the issue #1316+ -- that the above commit tried to solve, no longer shows up.+ substLifted isN substitution lifted = do+ -- remove the self-substitutions for the respective lifted expressions+ let subsMatrix = l2m substitution+ lifted1 <- Monad.zipWithM (\s (eL,seen) -> collectGlobals isN s seen eL)+ subsMatrix+ lifted+ return (map (^. _1) lifted1)++ l2m = go []+ where+ go _ [] = []+ go xs (y:ys) = (xs ++ ys) : go (xs ++ [y]) ys++disjointExpressionConsolidation _ e = return e+{-# SCC disjointExpressionConsolidation #-}++data CaseTree a+ = Leaf a+ | LB [LetBinding] (CaseTree a)+ | Branch Term [(Pat,CaseTree a)]+ deriving (Eq,Show,Functor,Foldable)++-- | Test if a 'CaseTree' collected from an expression indicates that+-- application of a global binder is disjoint: occur in separate branches of a+-- case-expression.+isDisjoint :: CaseTree ([Either Term Type])+ -> Bool+isDisjoint (Branch _ [_]) = False+isDisjoint ct = go ct+ where+ go (Leaf _) = False+ go (LB _ ct') = go ct'+ go (Branch _ []) = False+ go (Branch _ [(_,x)]) = go x+ go b@(Branch _ (_:_:_)) = allEqual (map Either.rights (Foldable.toList b))++-- Remove empty branches from a 'CaseTree'+removeEmpty :: Eq a => CaseTree [a] -> CaseTree [a]+removeEmpty l@(Leaf _) = l+removeEmpty (LB lb ct) =+ case removeEmpty ct of+ Leaf [] -> Leaf []+ ct' -> LB lb ct'+removeEmpty (Branch s bs) =+ case filter ((/= (Leaf [])) . snd) (map (second removeEmpty) bs) of+ [] -> Leaf []+ bs' -> Branch s bs'++-- | Test if all elements in a list are equal to each other.+allEqual :: Eq a => [a] -> Bool+allEqual [] = True+allEqual (x:xs) = all (== x) xs++-- | Collect 'CaseTree's for (potentially) disjoint applications of globals out+-- of an expression. Also substitute truly disjoint applications of globals by a+-- reference to a lifted out application.+collectGlobals'+ :: InScopeSet+ -> [(Term,Term)]+ -- ^ Substitution of (applications of) a global binder by a reference to a+ -- lifted term.+ -> [Term]+ -- ^ List of already seen global binders+ -> Term+ -- ^ The expression+ -> Bool+ -- ^ Whether expression is constant+ -> NormalizeSession (Term, InScopeSet, [(Term, ([Term], CaseTree [Either Term Type]))])+collectGlobals' is0 substitution seen (Case scrut ty alts) _eIsConstant = do+ rec (alts1, isAlts, collectedAlts) <-+ collectGlobalsAlts is0 substitution seen scrut1 alts+ (scrut1, isScrut, collectedScrut) <-+ collectGlobals is0 substitution (map fst collectedAlts ++ seen) scrut+ return ( Case scrut1 ty alts1+ , unionInScope isAlts isScrut+ , collectedAlts ++ collectedScrut )++collectGlobals' is0 substitution seen e@(collectArgsTicks -> (fun, args@(_:_), ticks)) eIsconstant+ | not eIsconstant = do+ tcm <- Lens.view tcCache+ bndrs <- Lens.use bindings+ evaluate <- Lens.view evaluator+ ids <- Lens.use uniqSupply+ let (ids1,ids2) = splitSupply ids+ uniqSupply Lens..= ids2+ gh <- Lens.use globalHeap+ let eval = (Lens.view Lens._3) . whnf' evaluate bndrs tcm gh ids1 is0 False+ let eTy = inferCoreTypeOf tcm e+ untran <- isUntranslatableType False eTy+ case untran of+ -- Don't lift out non-representable values, because they cannot be let-bound+ -- in our desired normal form.+ False -> do+ -- Look for, and substitute by, disjoint applications of globals in+ -- the arguments first before considering the current term in function+ -- position. Doing it in the other order (this term in function position+ -- first, followed by arguments) resulted in issue #1322+ (args1,isArgs,collectedArgs) <-+ collectGlobalsArgs is0 substitution seen args+ let seenInArgs = map fst collectedArgs ++ seen+ isInteresting <- interestingToLift is0 eval fun args ticks+ case isInteresting of+ Just fun1 | fun1 `notElem` seenInArgs -> do+ let e1 = Maybe.fromMaybe (mkApps fun1 args1) (List.lookup fun1 substitution)+ -- This function is lifted out an environment with the currently 'seen'+ -- binders. When we later apply substitution, we need to start with this+ -- environment, otherwise we perform incorrect substitutions in the+ -- arguments.+ return (e1,isArgs,(fun1,(seen,Leaf args1)):collectedArgs)+ _ -> return (mkApps (mkTicks fun ticks) args1, isArgs, collectedArgs)+ _ -> return (e,is0,[])++-- FIXME: This duplicates A LOT of let-bindings, where I just pray that after+-- the ANF, CSE, and DeadCodeRemoval pass all duplicates are removed.+--+-- I think we should be able to do better, but perhaps we cannot fix it here.+collectGlobals' is0 substitution seen (Letrec lbs body) _eIsConstant = do+ let is1 = extendInScopeSetList is0 (map fst lbs)+ (body1,isBody,collectedBody) <-+ collectGlobals is1 substitution seen body+ (lbs1,isBndrs,collectedBndrs) <-+ collectGlobalsLbs is1 substitution (map fst collectedBody ++ seen) lbs+ return ( Letrec lbs1 body1+ , unionInScope isBody isBndrs+ , map (second (second (LB lbs1))) (collectedBody ++ collectedBndrs)+ )++collectGlobals' is0 substitution seen (Tick t e) eIsConstant = do+ (e1,is1,collected) <- collectGlobals' is0 substitution seen e eIsConstant+ return (Tick t e1, is1, collected)++collectGlobals' is0 _ _ e _ = return (e,is0,[])++-- | Collect 'CaseTree's for (potentially) disjoint applications of globals out+-- of an expression. Also substitute truly disjoint applications of globals by a+-- reference to a lifted out application.+collectGlobals+ :: InScopeSet+ -> [(Term,Term)]+ -- ^ Substitution of (applications of) a global binder by a reference to+ -- a lifted term.+ -> [Term]+ -- ^ List of already seen global binders+ -> Term+ -- ^ The expression+ -> NormalizeSession (Term, InScopeSet, [(Term, ([Term], CaseTree [Either Term Type]))])+collectGlobals inScope substitution seen e =+ collectGlobals' inScope substitution seen e (isConstant e)++-- | Collect 'CaseTree's for (potentially) disjoint applications of globals out+-- of a list of application arguments. Also substitute truly disjoint+-- applications of globals by a reference to a lifted out application.+collectGlobalsArgs+ :: InScopeSet+ -> [(Term,Term)] -- ^ Substitution of (applications of) a global+ -- binder by a reference to a lifted term.+ -> [Term] -- ^ List of already seen global binders+ -> [Either Term Type] -- ^ The list of arguments+ -> NormalizeSession+ ( [Either Term Type]+ , InScopeSet+ , [(Term, ([Term], CaseTree [(Either Term Type)]))]+ )+collectGlobalsArgs is0 substitution seen args = do+ ((is1,_),(args',collected)) <- second unzip <$> List.mapAccumLM go (is0,seen) args+ return (args',is1,concat collected)+ where+ go (isN0,s) (Left tm) = do+ (tm',isN1,collected) <- collectGlobals isN0 substitution s tm+ return ((isN1,map fst collected ++ s),(Left tm',collected))+ go (isN,s) (Right ty) = return ((isN,s),(Right ty,[]))++-- | Collect 'CaseTree's for (potentially) disjoint applications of globals out+-- of a list of alternatives. Also substitute truly disjoint applications of+-- globals by a reference to a lifted out application.+collectGlobalsAlts ::+ InScopeSet+ -> [(Term,Term)] -- ^ Substitution of (applications of) a global+ -- binder by a reference to a lifted term.+ -> [Term] -- ^ List of already seen global binders+ -> Term -- ^ The subject term+ -> [Alt] -- ^ The list of alternatives+ -> NormalizeSession+ ( [Alt]+ , InScopeSet+ , [(Term, ([Term], CaseTree [(Either Term Type)]))]+ )+collectGlobalsAlts is0 substitution seen scrut alts = do+ (is1,(alts',collected)) <- second unzip <$> List.mapAccumLM go is0 alts+ let collectedM = map (Map.fromList . map (second (second (:[])))) collected+ collectedUN = Map.unionsWith (\(l1,r1) (l2,r2) -> (List.nub (l1 ++ l2),r1 ++ r2)) collectedM+ collected' = map (second (second (Branch scrut))) (Map.toList collectedUN)+ return (alts',is1,collected')+ where+ go isN0 (p,e) = do+ let isN1 = extendInScopeSetList isN0 (snd (patIds p))+ (e',isN2,collected) <- collectGlobals isN1 substitution seen e+ return (isN2,((p,e'),map (second (second (p,))) collected))++-- | Collect 'CaseTree's for (potentially) disjoint applications of globals out+-- of a list of let-bindings. Also substitute truly disjoint applications of+-- globals by a reference to a lifted out application.+collectGlobalsLbs ::+ InScopeSet+ -> [(Term,Term)] -- ^ Substitution of (applications of) a global+ -- binder by a reference to a lifted term.+ -> [Term] -- ^ List of already seen global binders+ -> [LetBinding] -- ^ The list let-bindings+ -> NormalizeSession+ ( [LetBinding]+ , InScopeSet+ , [(Term, ([Term], CaseTree [(Either Term Type)]))]+ )+collectGlobalsLbs is0 substitution seen lbs = do+ let lbsSCCs = sccLetBindings lbs+ ((is1,_),(lbsSCCs1,collected)) <-+ second unzip <$> List.mapAccumLM go (is0,seen) lbsSCCs+ return (Graph.flattenSCCs lbsSCCs1,is1,concat collected)+ where+ go :: (InScopeSet,[Term]) -> Graph.SCC LetBinding+ -> NormalizeSession+ ( (InScopeSet, [Term])+ , ( Graph.SCC LetBinding+ , [(Term, ([Term], CaseTree [(Either Term Type)]))]+ )+ )+ go (isN0,s) (Graph.AcyclicSCC (id_, e)) = do+ (e',isN1,collected) <- collectGlobals isN0 substitution s e+ return ((isN1,map fst collected ++ s),(Graph.AcyclicSCC (id_,e'),collected))+ -- TODO: This completely skips recursive let-bindings in the collection of+ -- potentially disjoint applications of globals; and skips substituting truly+ -- disjoint applications of globals by a reference to a lifted out application.+ --+ -- This is to prevent the creation of combinational loops that have occurred+ -- "in the wild", but for which we have not been able to a create small+ -- unit test that triggers this creation-of-combinational-loops bug.+ -- Completely skipping recursive let-bindings is taking the hammer to+ -- solving this bug, without knowing whether a scalpel even existed and what+ -- it might look like. We should at some point think hard how traversing+ -- recursive let-bindings can introduce combinational loops, and whether+ -- there exists a solution that can traverse recursive let-bindings,+ -- finding more opportunities for DEC, while not introducing combinational+ -- loops.+ go acc scc@(Graph.CyclicSCC {}) = return (acc,(scc,[]))++-- | Given a case-tree corresponding to a disjoint interesting \"term-in-a-+-- function-position\", return a let-expression: where the let-binding holds+-- a case-expression selecting between the distinct arguments of the case-tree,+-- and the body is an application of the term applied to the shared arguments of+-- the case tree, and projections of let-binding corresponding to the distinct+-- argument positions.+mkDisjointGroup+ :: InScopeSet+ -- ^ Variables in scope at the very top of the case-tree, i.e., the original+ -- expression+ -> (Term,([Term],CaseTree [(Either Term Type)]))+ -- ^ Case-tree of arguments belonging to the applied term.+ -> NormalizeSession (Term,[Term])+mkDisjointGroup inScope (fun,(seen,cs)) = do+ let argss = Foldable.toList cs+ argssT = zip [0..] (List.transpose argss)+ (sharedT,distinctT) = List.partition (areShared inScope . snd) argssT+ shared = map (second head) sharedT+ distinct = map (Either.lefts) (List.transpose (map snd distinctT))+ cs' = fmap (zip [0..]) cs+ cs'' = removeEmpty+ $ fmap (Either.lefts . map snd)+ (if null shared+ then cs'+ else fmap (filter (`notElem` shared)) cs')+ tcm <- Lens.view tcCache+ (distinctCaseM,distinctProjections) <- case distinct of+ -- only shared arguments: do nothing.+ [] -> return (Nothing,[])+ -- Create selectors and projections+ (uc:_) -> do+ let argTys = map (inferCoreTypeOf tcm) uc+ disJointSelProj inScope argTys cs''+ let newArgs = mkDJArgs 0 shared distinctProjections+ case distinctCaseM of+ Just lb -> return (Letrec [lb] (mkApps fun newArgs), seen)+ Nothing -> return (mkApps fun newArgs, seen)++-- | Create a single selector for all the representable distinct arguments by+-- selecting between tuples. This selector is only ('Just') created when the+-- number of representable uncommmon arguments is larger than one, otherwise it+-- is not ('Nothing').+--+-- It also returns:+--+-- * For all the non-representable distinct arguments: a selector+-- * For all the representable distinct arguments: a projection out of the tuple+-- created by the larger selector. If this larger selector does not exist, a+-- single selector is created for the single representable distinct argument.+disJointSelProj+ :: InScopeSet+ -> [Type]+ -- ^ Types of the arguments+ -> CaseTree [Term]+ -- The case-tree of arguments+ -> NormalizeSession (Maybe LetBinding,[Term])+disJointSelProj _ _ (Leaf []) = return (Nothing,[])+disJointSelProj inScope argTys cs = do+ tcm <- Lens.view tcCache+ tupTcm <- Lens.view tupleTcCache+ let maxIndex = length argTys - 1+ css = map (\i -> fmap ((:[]) . (!!i)) cs) [0..maxIndex]+ (untran,tran) <- List.partitionM (isUntranslatableType False . snd) (zip [0..] argTys)+ let untranCs = map (css!!) (map fst untran)+ untranSels = zipWith (\(_,ty) cs' -> genCase tcm tupTcm ty [ty] cs')+ untran untranCs+ (lbM,projs) <- case tran of+ [] -> return (Nothing,[])+ [(i,ty)] -> return (Nothing,[genCase tcm tupTcm ty [ty] (css!!i)])+ tys -> do+ let m = length tys+ (tyIxs,tys') = unzip tys+ tupTy = mkBigTupTy tcm tupTcm tys'+ cs' = fmap (\es -> map (es !!) tyIxs) cs+ djCase = genCase tcm tupTcm tupTy tys' cs'+ scrutId <- mkInternalVar inScope "tupIn" tupTy+ projections <- mapM (mkBigTupSelector inScope tcm tupTcm (Var scrutId) tys') [0..m-1]+ return (Just (scrutId,djCase),projections)+ let selProjs = tranOrUnTran 0 (zip (map fst untran) untranSels) projs++ return (lbM,selProjs)+ where+ tranOrUnTran _ [] projs = projs+ tranOrUnTran _ sels [] = map snd sels+ tranOrUnTran n ((ut,s):uts) (p:projs)+ | n == ut = s : tranOrUnTran (n+1) uts (p:projs)+ | otherwise = p : tranOrUnTran (n+1) ((ut,s):uts) projs++-- | Arguments are shared between invocations if:+--+-- * They contain _no_ references to locally-bound variables+-- * Are all equal+areShared :: InScopeSet -> [Either Term Type] -> Bool+areShared _ [] = True+areShared inScope xs@(x:_) = noFV1 && allEqual xs+ where+ noFV1 = case x of+ Right ty -> getAll (Lens.foldMapOf (typeFreeVars' isLocallyBound IntSet.empty)+ (const (All False)) ty)+ Left tm -> getAll (Lens.foldMapOf (termFreeVars' isLocallyBound)+ (const (All False)) tm)++ isLocallyBound v = isLocalId v && v `notElemInScopeSet` inScope++-- | Create a list of arguments given a map of positions to common arguments,+-- and a list of arguments+mkDJArgs :: Int -- ^ Current position+ -> [(Int,Either Term Type)] -- ^ map from position to common argument+ -> [Term] -- ^ (projections for) distinct arguments+ -> [Either Term Type]+mkDJArgs _ cms [] = map snd cms+mkDJArgs _ [] uncms = map Left uncms+mkDJArgs n ((m,x):cms) (y:uncms)+ | n == m = x : mkDJArgs (n+1) cms (y:uncms)+ | otherwise = Left y : mkDJArgs (n+1) ((m,x):cms) uncms++-- | Create a case-expression that selects between the distinct arguments given+-- a case-tree+genCase :: TyConMap+ -> IntMap TyConName+ -> Type -- ^ Type of the alternatives+ -> [Type] -- ^ Types of the arguments+ -> CaseTree [Term] -- ^ CaseTree of arguments+ -> Term+genCase tcm tupTcm ty argTys = go+ where+ go (Leaf tms) =+ mkBigTupTm tcm tupTcm (List.zipEqual argTys tms)++ go (LB lb ct) =+ Letrec lb (go ct)++ go (Branch scrut [(p,ct)]) =+ let ct' = go ct+ (ptvs,pids) = patIds p+ in if (coerce ptvs ++ coerce pids) `localVarsDoNotOccurIn` ct'+ then ct'+ else Case scrut ty [(p,ct')]++ go (Branch scrut pats) =+ Case scrut ty (map (second go) pats)++-- | Lookup the TyConName and DataCon for a tuple of size n+findTup :: TyConMap -> IntMap TyConName -> Int -> (TyConName,DataCon)+findTup tcm tupTcm n = (tupTcNm,tupDc)+ where+ tupTcNm = Maybe.fromMaybe (error $ $curLoc ++ "Can't find " ++ show n ++ "-tuple") $ IntMap.lookup n tupTcm+ Just tupTc = lookupUniqMap tupTcNm tcm+ [tupDc] = tyConDataCons tupTc++mkBigTupTm :: TyConMap -> IntMap TyConName -> [(Type,Term)] -> Term+mkBigTupTm tcm tupTcm args = snd $ mkBigTup tcm tupTcm args++mkSmallTup,mkBigTup :: TyConMap -> IntMap TyConName -> [(Type,Term)] -> (Type,Term)+mkSmallTup _ _ [] = error $ $curLoc ++ "mkSmallTup: Can't create 0-tuple"+mkSmallTup _ _ [(ty,tm)] = (ty,tm)+mkSmallTup tcm tupTcm args = (ty,tm)+ where+ (argTys,tms) = unzip args+ (tupTcNm,tupDc) = findTup tcm tupTcm (length args)+ tm = mkApps (Data tupDc) (map Right argTys ++ map Left tms)+ ty = mkTyConApp tupTcNm argTys++mkBigTup tcm tupTcm = mkChunkified (mkSmallTup tcm tupTcm)++mkSmallTupTy,mkBigTupTy+ :: TyConMap+ -> IntMap TyConName+ -> [Type]+ -> Type+mkSmallTupTy _ _ [] = error $ $curLoc ++ "mkSmallTupTy: Can't create 0-tuple"+mkSmallTupTy _ _ [ty] = ty+mkSmallTupTy tcm tupTcm tys = mkTyConApp tupTcNm tys+ where+ m = length tys+ (tupTcNm,_) = findTup tcm tupTcm m++mkBigTupTy tcm tupTcm = mkChunkified (mkSmallTupTy tcm tupTcm)++mkSmallTupSelector,mkBigTupSelector+ :: MonadUnique m+ => InScopeSet+ -> TyConMap+ -> IntMap TyConName+ -> Term+ -> [Type]+ -> Int+ -> m Term+mkSmallTupSelector _ _ _ scrut [_] 0 = return scrut+mkSmallTupSelector _ _ _ _ [_] n = error $ $curLoc ++ "mkSmallTupSelector called with one type, but to select " ++ show n+mkSmallTupSelector inScope tcm _ scrut _ n = mkSelectorCase ($curLoc ++ "mkSmallTupSelector") inScope tcm scrut 1 n++mkBigTupSelector inScope tcm tupTcm scrut tys n = go (chunkify tys)+ where+ go [_] = mkSmallTupSelector inScope tcm tupTcm scrut tys n+ go tyss = do+ let (nOuter,nInner) = divMod n mAX_TUPLE_SIZE+ tyss' = map (mkSmallTupTy tcm tupTcm) tyss+ outer <- mkSmallTupSelector inScope tcm tupTcm scrut tyss' nOuter+ inner <- mkSmallTupSelector inScope tcm tupTcm outer (tyss List.!! nOuter) nInner+ return inner+++-- | Determine if a term in a function position is interesting to lift out of+-- of a case-expression.+--+-- This holds for all global functions, and certain primitives. Currently those+-- primitives are:+--+-- * All non-power-of-two multiplications+-- * All division-like operations with a non-power-of-two divisor+interestingToLift+ :: InScopeSet+ -- ^ in scope+ -> (Term -> Term)+ -- ^ Evaluator+ -> Term+ -- ^ Term in function position+ -> [Either Term Type]+ -- ^ Arguments+ -> [TickInfo]+ -- ^ Tick annoations+ -> RewriteMonad extra (Maybe Term)+interestingToLift inScope _ e@(Var v) _ ticks =+ if NoDeDup `notElem` ticks && (isGlobalId v || v `elemInScopeSet` inScope)+ then pure (Just e)+ else pure Nothing+interestingToLift inScope eval e@(Prim pInfo) args ticks+ | NoDeDup `notElem` ticks = do+ let anyArgNotConstant = any (not . isConstant) lArgs+ case List.lookup (primName pInfo) interestingPrims of+ Just t | t || anyArgNotConstant -> pure (Just e)+ _ | DeDup `elem` ticks -> pure (Just e)+ _ -> do+ let isInteresting = (\(x, y, z) -> interestingToLift inScope eval x y z) . collectArgsTicks+ if isHOTy (coreTypeOf pInfo) then do+ anyInteresting <- List.anyM (fmap Maybe.isJust . isInteresting) lArgs+ if anyInteresting then pure (Just e) else pure Nothing+ else+ pure Nothing++ where+ interestingPrims =+ [("Clash.Sized.Internal.BitVector.*#",tailNonPow2)+ ,("Clash.Sized.Internal.BitVector.times#",tailNonPow2)+ ,("Clash.Sized.Internal.BitVector.quot#",lastNotPow2)+ ,("Clash.Sized.Internal.BitVector.rem#",lastNotPow2)+ ,("Clash.Sized.Internal.Index.*#",tailNonPow2)+ ,("Clash.Sized.Internal.Index.quot#",lastNotPow2)+ ,("Clash.Sized.Internal.Index.rem#",lastNotPow2)+ ,("Clash.Sized.Internal.Signed.*#",tailNonPow2)+ ,("Clash.Sized.Internal.Signed.times#",tailNonPow2)+ ,("Clash.Sized.Internal.Signed.rem#",lastNotPow2)+ ,("Clash.Sized.Internal.Signed.quot#",lastNotPow2)+ ,("Clash.Sized.Internal.Signed.div#",lastNotPow2)+ ,("Clash.Sized.Internal.Signed.mod#",lastNotPow2)+ ,("Clash.Sized.Internal.Unsigned.*#",tailNonPow2)+ ,("Clash.Sized.Internal.Unsigned.times#",tailNonPow2)+ ,("Clash.Sized.Internal.Unsigned.quot#",lastNotPow2)+ ,("Clash.Sized.Internal.Unsigned.rem#",lastNotPow2)+ ,("GHC.Base.quotInt",lastNotPow2)+ ,("GHC.Base.remInt",lastNotPow2)+ ,("GHC.Base.divInt",lastNotPow2)+ ,("GHC.Base.modInt",lastNotPow2)+ ,("GHC.Classes.divInt#",lastNotPow2)+ ,("GHC.Classes.modInt#",lastNotPow2)+#if MIN_VERSION_base(4,15,0)+ ,("GHC.Num.Integer.integerMul",allNonPow2)+ ,("GHC.Num.Integer.integerDiv",lastNotPow2)+ ,("GHC.Num.Integer.integerMod",lastNotPow2)+ ,("GHC.Num.Integer.integerQuot",lastNotPow2)+ ,("GHC.Num.Integer.integerRem",lastNotPow2)+#else+ ,("GHC.Integer.Type.timesInteger",allNonPow2)+ ,("GHC.Integer.Type.divInteger",lastNotPow2)+ ,("GHC.Integer.Type.modInteger",lastNotPow2)+ ,("GHC.Integer.Type.quotInteger",lastNotPow2)+ ,("GHC.Integer.Type.remInteger",lastNotPow2)+#endif+ ,("GHC.Prim.*#",allNonPow2)+ ,("GHC.Prim.quotInt#",lastNotPow2)+ ,("GHC.Prim.remInt#",lastNotPow2)+ ]++ lArgs = Either.lefts args++ allNonPow2 = all (not . termIsPow2) lArgs+ tailNonPow2 = case lArgs of+ [] -> True+ _ -> all (not . termIsPow2) (tail lArgs)+ lastNotPow2 = case lArgs of+ [] -> True+ _ -> not (termIsPow2 (last lArgs))++ termIsPow2 e' = case eval e' of+ Literal (IntegerLiteral n) -> isPow2 n+ a -> case collectArgs a of+ (Prim p,[Right _,Left _,Left (Literal (IntegerLiteral n))])+ | isFromInteger (primName p) -> isPow2 n+ (Prim p,[Right _,Left _,Left _,Left (Literal (IntegerLiteral n))])+ | primName p == "Clash.Sized.Internal.BitVector.fromInteger#" -> isPow2 n+ (Prim p,[Right _, Left _,Left (Literal (IntegerLiteral n))])+ | primName p == "Clash.Sized.Internal.BitVector.fromInteger##" -> isPow2 n++ _ -> False++ isPow2 x = x /= 0 && (x .&. (complement x + 1)) == x++ isFromInteger x = x `elem` ["Clash.Sized.Internal.BitVector.fromInteger#"+ ,"Clash.Sized.Integer.Index.fromInteger"+ ,"Clash.Sized.Internal.Signed.fromInteger#"+ ,"Clash.Sized.Internal.Unsigned.fromInteger#"+ ]++ isHOTy t = case splitFunForallTy t of+ (args',_) -> any isPolyFunTy (Either.rights args')++interestingToLift _ _ _ _ _ = pure Nothing
+ src/Clash/Normalize/Transformations/EtaExpand.hs view
@@ -0,0 +1,107 @@+{-|+ Copyright : (C) 2012-2016, University of Twente,+ 2016-2017, Myrtle Software Ltd,+ 2017-2018, Google Inc.,+ 2021 , QBayLogic B.V.+ License : BSD2 (see the file LICENSE)+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com>++ The eta-expansion transformation.+-}++{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++module Clash.Normalize.Transformations.EtaExpand+ ( etaExpandSyn+ , etaExpansionTL+ ) where++import qualified Control.Lens as Lens+import qualified Data.Maybe as Maybe+import GHC.Stack (HasCallStack)++import Clash.Core.HasType+import Clash.Core.Term (Bind(..), CoreContext(..), Term(..), collectArgs, mkLams)+import Clash.Core.TermInfo (isFun)+import Clash.Core.Type (splitFunTy)+import Clash.Core.Util (mkInternalVar)+import Clash.Core.Var (Id)+import Clash.Core.VarEnv (elemVarSet, extendInScopeSet, extendInScopeSetList)+import Clash.Normalize.Types (NormRewrite)+import Clash.Rewrite.Types (TransformContext(..), tcCache, topEntities)+import Clash.Rewrite.Util (changed)+import Clash.Util (curLoc)++-- | Eta-expand functions with a Synthesize annotation, needed to allow such+-- functions to appear as arguments to higher-order primitives.+etaExpandSyn :: HasCallStack => NormRewrite+etaExpandSyn (TransformContext is0 ctx) e@(collectArgs -> (Var f, _)) = do+ topEnts <- Lens.view topEntities+ tcm <- Lens.view tcCache+ let isTopEnt = f `elemVarSet` topEnts+ isAppFunCtx =+ \case+ AppFun:_ -> True+ TickC _:c -> isAppFunCtx c+ _ -> False+ argTyM = fmap fst (splitFunTy tcm (inferCoreTypeOf tcm e))+ case argTyM of+ Just argTy | isTopEnt && not (isAppFunCtx ctx) -> do+ newId <- mkInternalVar is0 "arg" argTy+ changed (Lam newId (App e (Var newId)))+ _ -> return e++etaExpandSyn _ e = return e+{-# SCC etaExpandSyn #-}++stripLambda :: Term -> ([Id], Term)+stripLambda (Lam bndr e) =+ let (bndrs, e') = stripLambda e+ in (bndr : bndrs, e')++stripLambda e = ([], e)++-- | Eta-expand top-level lambda's (DON'T use in a traversal!)+etaExpansionTL :: HasCallStack => NormRewrite+etaExpansionTL (TransformContext is0 ctx) (Lam bndr e) = do+ let ctx' = TransformContext (extendInScopeSet is0 bndr) (LamBody bndr : ctx)+ e' <- etaExpansionTL ctx' e+ return $ Lam bndr e'++etaExpansionTL (TransformContext is0 ctx) (Let (NonRec i x) e) = do+ let ctx' = TransformContext (extendInScopeSet is0 i) (LetBody [i] : ctx)+ e' <- etaExpansionTL ctx' e+ case stripLambda e' of+ (bs@(_:_),e2) -> do+ let e3 = Let (NonRec i x) e2+ changed (mkLams e3 bs)+ _ -> return (Let (NonRec i x) e')++etaExpansionTL (TransformContext is0 ctx) (Let (Rec xes) e) = do+ let bndrs = map fst xes+ ctx' = TransformContext (extendInScopeSetList is0 bndrs) (LetBody bndrs : ctx)+ e' <- etaExpansionTL ctx' e+ case stripLambda e' of+ (bs@(_:_),e2) -> do+ let e3 = Let (Rec xes) e2+ changed (mkLams e3 bs)+ _ -> return (Let (Rec xes) e')++etaExpansionTL (TransformContext is0 ctx) e+ = do+ tcm <- Lens.view tcCache+ if isFun tcm e+ then do+ let argTy = ( fst+ . Maybe.fromMaybe (error $ $(curLoc) ++ "etaExpansion splitFunTy")+ . splitFunTy tcm+ . inferCoreTypeOf tcm+ ) e+ newId <- mkInternalVar is0 "arg" argTy+ let ctx' = TransformContext (extendInScopeSet is0 newId) (LamBody newId : ctx)+ e' <- etaExpansionTL ctx' (App e (Var newId))+ changed (Lam newId e')+ else return e+{-# SCC etaExpansionTL #-}
+ src/Clash/Normalize/Transformations/Inline.hs view
@@ -0,0 +1,664 @@+{-|+ Copyright : (C) 2012-2016, University of Twente,+ 2016-2017, Myrtle Software Ltd,+ 2017-2018, Google Inc.,+ 2021-2022, QBayLogic B.V.+ License : BSD2 (see the file LICENSE)+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com>++ Transformations for inlining+-}++{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TemplateHaskell #-}++module Clash.Normalize.Transformations.Inline+ ( bindConstantVar+ , inlineBndrsCleanup+ , inlineCast+ , inlineCleanup+ , collapseRHSNoops+ , inlineNonRep+ , inlineOrLiftNonRep+ , inlineSimIO+ , inlineSmall+ , inlineWorkFree+ ) where++import qualified Control.Lens as Lens+import qualified Control.Monad as Monad+import Control.Monad.Trans.Maybe (MaybeT(..))+import Control.Monad.Writer ((>=>),lift,listen)+import Data.Default (Default(..))+import Data.Either (lefts)+import qualified Data.HashMap.Lazy as HashMap+import qualified Data.List as List+import qualified Data.Maybe as Maybe+import qualified Data.Monoid as Monoid (Any(..))+import qualified Data.Text as Text+import qualified Data.Text.Extra as Text+import GHC.Stack (HasCallStack)++#if MIN_VERSION_ghc(9,0,0)+import GHC.Types.Basic (InlineSpec (..))+#else+import BasicTypes (InlineSpec (..))+#endif++import qualified Clash.Explicit.SimIO as SimIO+import qualified Clash.Sized.Internal.BitVector as BV (Bit(Bit), BitVector(BV))++import Clash.Annotations.Primitive (extractPrim)+import Clash.Core.DataCon (DataCon(..))+import Clash.Core.FreeVars+ (countFreeOccurances, freeLocalIds)+import Clash.Core.HasFreeVars+import Clash.Core.HasType+import Clash.Core.Name (Name(..), NameSort(..))+import Clash.Core.Pretty (PrettyOptions(..), showPpr, showPpr')+import Clash.Core.Subst+import Clash.Core.Term+ ( CoreContext(..), Pat(..), PrimInfo(..), Term(..), WorkInfo(..), collectArgs+ , collectArgsTicks, mkApps , mkTicks, stripTicks)+import Clash.Core.TermInfo (isLocalVar, termSize)+import Clash.Core.Type+ (TypeView(..), isClassTy, isPolyFunCoreTy, tyView)+import Clash.Core.Util (isSignalType, primUCo)+import Clash.Core.Var (Id, Var(..), isGlobalId, isLocalId)+import Clash.Core.VarEnv+ ( InScopeSet, VarEnv, VarSet, elemUniqInScopeSet, elemVarEnv, elemVarSet+ , eltsVarEnv, emptyVarEnv, extendInScopeSetList, extendVarEnv+ , foldlWithUniqueVarEnv', lookupVarEnv, lookupVarEnvDirectly, mkVarEnv+ , notElemVarSet, unionVarEnv, unionVarEnvWith, unitVarSet)+import Clash.Debug (trace)+import Clash.Driver.Types (Binding(..))+import Clash.Netlist.Util (representableType)+import Clash.Primitives.Types+ (CompiledPrimMap, Primitive(..), TemplateKind(..))+import Clash.Rewrite.Combinators (allR)+import Clash.Rewrite.Types+ ( TransformContext(..), bindings, curFun, customReprs, tcCache, topEntities+ , typeTranslator, inlineConstantLimit, inlineFunctionLimit, inlineLimit+ , inlineWFCacheLimit, primitives)+import Clash.Rewrite.Util+ ( changed, inlineBinders, inlineOrLiftBinders, isJoinPointIn+ , isUntranslatable, isUntranslatableType, isVoidWrapper, zoomExtra)+import Clash.Rewrite.WorkFree (isWorkFreeIsh)+import Clash.Normalize.Types ( NormRewrite, NormalizeSession)+import Clash.Normalize.Util+ ( addNewInline, alreadyInlined, isRecursiveBndr, mkInlineTick+ , normalizeTopLvlBndr)+import Clash.Unique (Unique)+import Clash.Util (curLoc)+import qualified Clash.Util.Interpolate as I++{- [Note] join points and void wrappers+Join points are functions that only occur in tail-call positions within an+expression, and only when they occur in a tail-call position more than once.+Normally bindNonRep binds/inlines all non-recursive local functions. However,+doing so for join points would significantly increase compilation time, so we+avoid it. The only exception to this rule are so-called void wrappers. Void+wrappers are functions of the form:+> \(w :: Void) -> f a b c+i.e. a wrapper around the function 'f' where the argument 'w' is not used. We+do bind/line these join-points because these void-wrappers interfere with the+'disjoint expression consolidation' (DEC) and 'common sub-expression elimination'+(CSE) transformation, sometimes resulting in circuits that are twice as big+as they'd need to be.+-}++-- | Inline let-bindings when the RHS is either a local variable reference or+-- is constant (except clock or reset generators)+bindConstantVar :: HasCallStack => NormRewrite+bindConstantVar = inlineBinders test+ where+ test _ (i,stripTicks -> e) = case isLocalVar e of+ -- Don't inline `let x = x in x`, it throws us in an infinite loop+ True -> return (i `notElemFreeVars` e)+ _ -> do+ tcm <- Lens.view tcCache+ case isWorkFreeIsh tcm e of+ True -> Lens.view inlineConstantLimit >>= \case+ 0 -> return True+ n -> return (termSize e <= n)+ _ -> return False+{-# SCC bindConstantVar #-}++-- | Mark to track progress of 'reduceBindersCleanup'+data Mark = Temp | Done | Rec++-- | Used (transitively) by 'inlineCleanup' inline to-inline let-binders into+-- the other to-inline let-binders.+reduceBindersCleanup+ :: HasCallStack+ => InScopeSet+ -- ^ Current InScopeSet+ -> VarEnv ((Id,Term),VarEnv Int)+ -- ^ Original let-binders with their free variables (+ #occurrences)+ -> (Maybe Subst,VarEnv Int,VarEnv ((Id,Term),VarEnv Int,Mark))+ -- ^ Accumulated:+ --+ -- 1. (Maybe) the build up substitution so far+ -- 2. The free variables of the range of the substitution+ -- 3. Processed let-binders with their free variables and a tag to mark+ -- the progress:+ -- * Temp: Will eventually form a recursive cycle+ -- * Done: Processed, non-recursive+ -- * Rec: Processed, recursive+ -> Unique+ -- ^ The unique of the let-binding that we want to simplify+ -> Int+ -- ^ Ignore, artifact of 'foldlWithUniqueVarEnv'+ -> (Maybe Subst,VarEnv Int,VarEnv ((Id,Term),VarEnv Int,Mark))+ -- ^ Same as the third argument+reduceBindersCleanup isN origInl (!substM,!substFVs,!doneInl) u _ =+ case lookupVarEnvDirectly u doneInl of+ Nothing -> case lookupVarEnvDirectly u origInl of+ Nothing ->+ -- let-binding not found, cannot extend the substitution+ if elemUniqInScopeSet u isN then+ (substM,substFVs,doneInl)+ else+ error [I.i|+ Internal error: 'reduceBindersCleanup' encountered a variable+ reference that was neither in 'doneInl', 'origInl', or in the+ transformation's in scope set. Unique was: '#{u}'.+ |]+ Just ((v,e),eFVs) ->+ -- Simplify the transitive dependencies+ let (sM,substFVsE,doneInl1) =+ foldlWithUniqueVarEnv'+ (reduceBindersCleanup isN origInl)+ ( Nothing+ -- It's okay/needed to over-approximate the free variables of+ -- the range of the new substitution by including the free+ -- variables of the original let-binder, because this set of+ -- free variables is only used to check whether let-binding will+ -- become self-recursive after applying the substitution.+ --+ -- That is, it was already self-recursive, or becomes+ -- self-recursive after applying the substitution because it was+ -- part of a recursive group. And we do not want to inline+ -- recursive binders.+ , eFVs+ -- Temporarily extend the processing environment with the+ -- let-binding so we don't end up in a loop in case there is a+ -- recursive group.+ , extendVarEnv v ((v,e),eFVs,Temp) doneInl)+ eFVs++ e1 = maybeSubstTm "reduceBindersCleanup" sM e+ in if v `elemVarEnv` substFVsE then+ -- We cannot inline recursive let-bindings, so we do not extend+ -- the substitution environment.+ ( substM+ , substFVs+ -- And we explicitly mark the let-binding as recursive in the+ -- processing environment. So that it will be kept around at the+ -- end of 'inlineCleanup'+ , extendVarEnv v ((v,e1),substFVsE,Rec) doneInl1+ )+ else+ -- Extend the substitution+ ( Just (extendIdSubst (Maybe.fromMaybe (mkSubst isN) substM) v e1)+ , unionVarEnv substFVsE substFVs+ -- Mark the let-binding a fully "reduced", so we don't repeat+ -- this process when we encounter it again.+ , extendVarEnv v ((v,e1),substFVsE,Done) doneInl1+ )+ -- It's already been processed, just extend the substitution environment+ Just ((v,e),eFVs,Done) ->+ ( Just (extendIdSubst (Maybe.fromMaybe (mkSubst isN) substM) v e)+ , unionVarEnv eFVs substFVs+ , doneInl+ )++ -- It's either recursive (Rec), or part of a recursive group (Temp) where we+ -- originally entered a different part of the cycle. Regardless, we do not+ -- extend the substitution environment.+ Just _ ->+ ( substM+ , substFVs+ , doneInl+ )+{-# SCC reduceBindersCleanup #-}++-- | Used by 'inlineCleanup' to inline binders that we want to inline into the+-- binders that we want to keep.+inlineBndrsCleanup+ :: HasCallStack+ => InScopeSet+ -- ^ Current InScopeSet+ -> VarEnv ((Id,Term),VarEnv Int)+ -- ^ Original let-binders with their free variables (+ #occurrences), that we+ -- want to inline+ -> VarEnv ((Id,Term),VarEnv Int,Mark)+ -- ^ Processed let-binders with their free variables and a tag to mark the+ -- progress:+ -- * Temp: Will eventually form a recursive cycle+ -- * Done: Processed, non-recursive+ -- * Rec: Processed, recursive+ -> [((Id,Term),VarEnv Int)]+ -- ^ The let-binders with their free variables (+ #occurrences), that we want+ -- to keep+ -> [(Id,Term)]+inlineBndrsCleanup isN origInl = go+ where+ go doneInl [] =+ -- If some of the let-binders that we wanted to inline turn out to be+ -- recursive, then we have to keep those around as well, as we weren't able+ -- to inline them. Furthermore, for every recursive binder there might still+ -- be non-inlined variables left, see #1337.+ flip map [ (ve, eFvs) | (ve,eFvs,Rec) <- eltsVarEnv doneInl ] $ \((v, e), eFvs) ->+ let+ (substM, _, _) = foldlWithUniqueVarEnv'+ (reduceBindersCleanup isN emptyVarEnv)+ (Nothing, emptyVarEnv, doneInl)+ eFvs+ in (v, maybeSubstTm "inlineBndrsCleanup_0" substM e)+ go !doneInl_0 (((v,e),eFVs):il) =+ let (sM,_,doneInl_1) = foldlWithUniqueVarEnv'+ (reduceBindersCleanup isN origInl)+ (Nothing, emptyVarEnv, doneInl_0)+ eFVs+ e1 = maybeSubstTm "inlineBndrsCleanup_1" sM e+ in (v,e1):go doneInl_1 il+{-# SCC inlineBndrsCleanup #-}++-- | Only inline casts that just contain a 'Var', because these are guaranteed work-free.+-- These are the result of the 'splitCastWork' transformation.+inlineCast :: HasCallStack => NormRewrite+inlineCast = inlineBinders test+ where+ test _ (_, (Cast (stripTicks -> Var {}) _ _)) = return True+ test _ _ = return False+{-# SCC inlineCast #-}++-- | Given a function in the desired normal form, inline all the following+-- let-bindings:+--+-- Let-bindings with an internal name that is only used once, where it binds:+-- * a primitive that will be translated to an HDL expression (as opposed to+-- a HDL declaration)+-- * a projection case-expression (1 alternative)+-- * a data constructor+-- * I/O actions+inlineCleanup :: HasCallStack => NormRewrite+inlineCleanup (TransformContext is0 _) (Letrec binds body) = do+ prims <- Lens.view primitives+ -- For all let-bindings, count the number of times they are referenced.+ -- We only inline let-bindings which are referenced only once, otherwise+ -- we would lose sharing.+ let is1 = extendInScopeSetList is0 (map fst binds)+ bindsFvs = map (\(v,e) -> (v,((v,e),countFreeOccurances e))) binds+ allOccs = List.foldl' (unionVarEnvWith (+)) emptyVarEnv+ $ map (snd.snd) bindsFvs+ bodyFVs = Lens.foldMapOf freeLocalIds unitVarSet body+ (il,keep) = List.partition (isInteresting allOccs prims bodyFVs)+ bindsFvs+ keep' = inlineBndrsCleanup is1 (mkVarEnv il) emptyVarEnv+ $ map snd keep++ if | null il -> return (Letrec binds body)+ | null keep' -> changed body+ | otherwise -> changed (Letrec keep' body)+ where+ -- Determine whether a let-binding is interesting to inline+ isInteresting+ :: VarEnv Int+ -> CompiledPrimMap+ -> VarSet+ -> (Id,((Id, Term), VarEnv Int))+ -> Bool+ isInteresting allOccs prims bodyFVs (id_,((_,(fst.collectArgs) -> tm),_))+ -- Try to keep user defined names, but inline names generated by GHC or+ -- Clash. For example, if a user were to write:+ --+ -- x = 2 * y+ --+ -- Even if 'x' is only used once, we'd like to keep it around to produce+ -- more readable HDL. In contrast, if a user were to write:+ --+ -- let x = f (2 * y)+ --+ -- ANF would transform that to:+ --+ -- let x = f f_arg; f_arg = 2 * y+ --+ -- In that case, there's no harm in inlining f_arg.+ | nameSort (varName id_) /= User+ , id_ `notElemVarSet` bodyFVs+ = case tm of+ Prim pInfo+ | let nm = primName pInfo+ , Just (extractPrim -> Just p@(BlackBox {})) <- HashMap.lookup nm prims+ , TExpr <- kind p+ , Just occ <- lookupVarEnv id_ allOccs+ , occ < 2+ -> True+ | otherwise+ -> primName pInfo `elem` ["Clash.Explicit.SimIO.bindSimIO#"]+ Case _ _ [_] -> True+ Data _ -> True+ Case _ aTy (_:_:_)+ | TyConApp nm _ <- tyView aTy+ , nameOcc nm == Text.showt ''SimIO.SimIO+ -> True+ _ -> False+ | id_ `notElemVarSet` bodyFVs+ = case tm of+ Prim pInfo+ | primName pInfo `elem`+ [ Text.showt 'SimIO.openFile+ , Text.showt 'SimIO.getChar+ , Text.showt 'SimIO.isEOF+ ]+ , Just occ <- lookupVarEnv id_ allOccs+ , occ < 2+ -> True+ | otherwise+ -> primName pInfo `elem` ["Clash.Explicit.SimIO.bindSimIO#"]+ Case _ _ [(DataPat dcE _ _,_)]+ -> let nm = (nameOcc (dcName dcE))+ in -- Inlines WW projection that exposes internals of the BitVector types+ nm == Text.showt 'BV.BV ||+ nm == Text.showt 'BV.Bit ||+ -- Inlines projections out of constraint-tuples (e.g. HiddenClockReset)+ "GHC.Classes" `Text.isPrefixOf` nm+ Case _ aTy (_:_:_)+ | TyConApp nm _ <- tyView aTy+ , nameOcc nm == Text.showt ''SimIO.SimIO+ -> True+ _ -> False++ isInteresting _ _ _ _ = False++inlineCleanup _ e = return e+{-# SCC inlineCleanup #-}++{- [Note] relation `collapseRHSNoops` and `inlineCleanup`+The `collapseRHSNoops` transformation replaces functions/primitives that are the identity+in HDL, but not in Haskell, by `unsafeCoerce`.+`inlineCleanup` subsequently inlines these `unsafeCoerce` calls.+The end result of all of this is that we get no/fewer assignments in HDL where the RHS is+simply a variable reference. See issue #779 -}++-- | Takes a binding and collapses its term if it is a noop+collapseRHSNoops :: HasCallStack => NormRewrite+collapseRHSNoops _ (Letrec binds body) = do+ binds1 <- mapM runCollapseNoop binds+ return $ Letrec binds1 body+ where+ runCollapseNoop orig =+ runMaybeT (collapseNoop orig) >>= Maybe.maybe (return orig) changed++ collapseNoop (iD,term) = do+ (Prim info,args) <- return $ collectArgs term+ identity <- getIdentity info $ lefts args+ collapsed <- collapseToIdentity iD identity+ return (iD,collapsed)++ collapseToIdentity iD identity = do+ tcm <- Lens.view tcCache+ let aTy = inferCoreTypeOf tcm identity+ bTy = coreTypeOf iD+ return $ primUCo `TyApp` aTy `TyApp` bTy `App` identity++ getIdentity primInfo termArgs = do+ WorkIdentity idIdx noopIdxs <- return $ primWorkInfo primInfo+ mapM_ (getTermArg termArgs >=> isNoop >=> Monad.guard) noopIdxs+ getTermArg termArgs idIdx++ getTermArg args i = do+ Monad.guard $ i <= length args - 1+ return $ args !! i++ isNoop (Var i) = do+ binding <- MaybeT $ lookupVarEnv i <$> Lens.use bindings+ isRecursive <- lift $ isRecursiveBndr $ bindingId binding+ Monad.guard $ not isRecursive+ isNoop $ bindingTerm binding+ isNoop (Prim PrimInfo{primWorkInfo=WorkIdentity _ []}) = return True+ isNoop _ = return False++collapseRHSNoops _ e = return e+{-# SCC collapseRHSNoops #-}++-- | Inline function with a non-representable result if it's the subject+-- of a Case-decomposition. It's a custom topdown traversal that -for efficiency+-- reasons- does not explore alternative of cases whose subject triggered an+-- 'inlineNonRepWorker'.+inlineNonRep :: HasCallStack => NormRewrite+inlineNonRep ctx0 e0@(Case {}) = do+ r <- listen (inlineNonRepWorker e0)+ case r of+ (e1, Monoid.getAny -> True) ->+ return e1+ (~(Case subj0 typ alts), _) -> do+ -- If a term _in_ the subject triggers 'inlineNonRepWorker', inline and+ -- propagate might eliminate this case. We therefore don't explore the+ -- alternatives. Note that this makes it substantially different from a+ -- 'topdownSucR' transformation.+ let+ TransformContext inScope ctx1 = ctx0+ ctx2 = TransformContext inScope (CaseScrut:ctx1)++ listen (inlineNonRep ctx2 subj0) >>= \case+ (subj1, Monoid.getAny -> True) ->+ return (Case subj1 typ alts)+ (subj1, _) -> do+ let (pats, rhss0) = unzip alts+ rhss1 <- mapM (inlineNonRep ctx2) rhss0+ pure (Case subj1 typ (zip pats rhss1))++inlineNonRep ctx e =+ -- All non-case statements are simply traversed. TODO: are there other special+ -- cases like 'Case' that would warrant an optimization like ^ ?+ allR inlineNonRep ctx e+{-# SCC inlineNonRep #-}++-- | Inline function with a non-representable result if it's the subject+-- of a Case-decomposition. This worker function only tries the given term+-- (i.e., it does not traverse it).+--+-- It sets the changed flag in the NormalizeSession if it successfully inlines+-- a binder.+inlineNonRepWorker :: HasCallStack => Term -> NormalizeSession Term+inlineNonRepWorker e@(Case scrut altsTy alts)+ | (Var f, args,ticks) <- collectArgsTicks scrut+ , isGlobalId f+ = do+ (cf,_) <- Lens.use curFun+ isInlined <- zoomExtra (alreadyInlined f cf)+ limit <- Lens.view inlineLimit+ tcm <- Lens.view tcCache+ let+ scrutTy = inferCoreTypeOf tcm scrut++ -- Constraint dictionary inlining always terminates, so we ignore the+ -- usual inline safeguards.+ notClassTy = not (isClassTy tcm scrutTy)+ overLimit = notClassTy && (Maybe.fromMaybe 0 isInlined) > limit+++ bodyMaybe <- lookupVarEnv f <$> Lens.use bindings+ nonRepScrut <- not <$> (representableType <$> Lens.view typeTranslator+ <*> Lens.view customReprs+ <*> pure False+ <*> Lens.view tcCache+ <*> pure scrutTy)+ case (nonRepScrut, bodyMaybe) of+ (True, Just b) -> do+ if overLimit then+ trace ($(curLoc) ++ [I.i|+ InlineNonRep: #{showPpr (varName f)} already inlined+ #{limit} times in: #{showPpr (varName cf)}. The type of the subject+ is:++ #{showPpr' def{displayTypes=True\} scrutTy}++ Function #{showPpr (varName cf)} will not reach a normal form and+ compilation might fail.++ Run with '-fclash-inline-limit=N' to increase the inline limit to N.+ |]) (return e)+ else do+ Monad.when notClassTy (zoomExtra (addNewInline f cf))++ let scrutBody0 = mkTicks (bindingTerm b) (mkInlineTick f : ticks)+ let scrutBody1 = mkApps scrutBody0 args++ changed $ Case scrutBody1 altsTy alts+ _ ->+ return e++inlineNonRepWorker e = pure e+{-# SCC inlineNonRepWorker #-}++inlineOrLiftNonRep :: HasCallStack => NormRewrite+inlineOrLiftNonRep ctx eLet@(Letrec _ body) =+ inlineOrLiftBinders nonRepTest inlineTest ctx eLet+ where+ bodyFreeOccs = countFreeOccurances body++ nonRepTest :: (Id, Term) -> NormalizeSession Bool+ nonRepTest (Id {varType = ty}, _)+ = not <$> (representableType <$> Lens.view typeTranslator+ <*> Lens.view customReprs+ <*> pure False+ <*> Lens.view tcCache+ <*> pure ty)+ nonRepTest _ = return False++ inlineTest :: Term -> (Id, Term) -> Bool+ inlineTest e (id_, e') =+ -- We do __NOT__ inline:+ not $ or+ [ -- 1. recursive let-binders+ -- id_ `elemFreeVars` e' -- <= already checked in inlineOrLiftBinders+ -- 2. join points (which are not void-wrappers)+ isJoinPointIn id_ e && not (isVoidWrapper e')+ -- 3. binders that are used more than once in the body, because+ -- it makes CSE a whole lot more difficult.+ --+ -- XXX: Check whether we can extend this to the binders as well+ , maybe False (>1) (lookupVarEnv id_ bodyFreeOccs)+ ]++inlineOrLiftNonRep _ e = return e+{-# SCC inlineOrLiftNonRep #-}++-- | Inline anything of type `SimIO`: IO actions cannot be shared+inlineSimIO :: HasCallStack => NormRewrite+inlineSimIO = inlineBinders test+ where+ test _ (i,_) = case tyView (coreTypeOf i) of+ TyConApp tc _ -> return $! nameOcc tc == Text.showt ''SimIO.SimIO+ _ -> return False+{-# SCC inlineSimIO #-}++-- | Inline small functions+inlineSmall :: HasCallStack => NormRewrite+inlineSmall _ e@(collectArgsTicks -> (Var f,args,ticks)) = do+ untranslatable <- isUntranslatable True e+ topEnts <- Lens.view topEntities+ let lv = isLocalId f+ if untranslatable || f `elemVarSet` topEnts || lv+ then return e+ else do+ bndrs <- Lens.use bindings+ sizeLimit <- Lens.view inlineFunctionLimit+ case lookupVarEnv f bndrs of+ -- Don't inline recursive expressions+ Just b -> do+ isRecBndr <- isRecursiveBndr f+ if not isRecBndr && bindingSpec b /= NoInline && termSize (bindingTerm b) < sizeLimit+ then do+ let tm = mkTicks (bindingTerm b) (mkInlineTick f : ticks)+ changed $ mkApps tm args+ else return e++ _ -> return e++inlineSmall _ e = return e+{-# SCC inlineSmall #-}++-- | Inline work-free functions, i.e. fully applied functions that evaluate to+-- a constant+inlineWorkFree :: HasCallStack => NormRewrite+inlineWorkFree _ e@(collectArgsTicks -> (Var f,args@(_:_),ticks))+ = do+ tcm <- Lens.view tcCache+ let eTy = inferCoreTypeOf tcm e+ argsHaveWork <- or <$> mapM (either expressionHasWork+ (const (pure False)))+ args+ untranslatable <- isUntranslatableType True eTy+ topEnts <- Lens.view topEntities+ let isSignal = isSignalType tcm eTy+ let lv = isLocalId f+ let isTopEnt = elemVarSet f topEnts+ if untranslatable || isSignal || argsHaveWork || lv || isTopEnt+ then return e+ else do+ bndrs <- Lens.use bindings+ case lookupVarEnv f bndrs of+ -- Don't inline recursive expressions+ Just b -> do+ isRecBndr <- isRecursiveBndr f+ if isRecBndr+ then return e+ else do+ let tm = mkTicks (bindingTerm b) (mkInlineTick f : ticks)+ changed $ mkApps tm args++ _ -> return e+ where+ -- an expression is has work when it contains free local variables,+ -- or has a Signal type, i.e. it does not evaluate to a work-free+ -- constant.+ expressionHasWork e' = do+ let fvIds = Lens.toListOf freeLocalIds e'+ tcm <- Lens.view tcCache+ let e'Ty = inferCoreTypeOf tcm e'+ isSignal = isSignalType tcm e'Ty+ return (not (null fvIds) || isSignal)++inlineWorkFree _ e@(Var f) = do+ tcm <- Lens.view tcCache+ let fTy = coreTypeOf f+ closed = not (isPolyFunCoreTy tcm fTy)+ isSignal = isSignalType tcm fTy+ untranslatable <- isUntranslatableType True fTy+ topEnts <- Lens.view topEntities+ let gv = isGlobalId f+ if closed && f `notElemVarSet` topEnts && not untranslatable && not isSignal && gv+ then do+ bndrs <- Lens.use bindings+ case lookupVarEnv f bndrs of+ -- Don't inline recursive expressions+ Just top -> do+ isRecBndr <- isRecursiveBndr f+ if isRecBndr+ then return e+ else do+ let topB = bindingTerm top+ sizeLimit <- Lens.view inlineWFCacheLimit+ -- caching only worth it from a certain size onwards, otherwise+ -- the caching mechanism itself brings more of an overhead.+ if termSize topB < sizeLimit then+ changed topB+ else do+ b <- normalizeTopLvlBndr False f top+ changed (bindingTerm b)+ _ -> return e+ else return e++inlineWorkFree _ e = return e+{-# SCC inlineWorkFree #-}
+ src/Clash/Normalize/Transformations/Letrec.hs view
@@ -0,0 +1,458 @@+{-|+ Copyright : (C) 2012-2016, University of Twente,+ 2016-2017, Myrtle Software Ltd,+ 2017-2018, Google Inc.,+ 2021-2022, QBayLogic B.V.+ License : BSD2 (see the file LICENSE)+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com>++ Transformations on letrec expressions.+-}++{-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskellQuotes #-}++module Clash.Normalize.Transformations.Letrec+ ( deadCode+ , flattenLet+ , recToLetRec+ , removeUnusedExpr+ , simpleCSE+ , topLet+ ) where++import qualified Control.Lens as Lens+import qualified Control.Monad as Monad+import Control.Monad.Trans.Except (runExcept)+import Control.Monad.Writer (listen)+import Data.Bifunctor (second)+import qualified Data.Either as Either+import qualified Data.HashMap.Lazy as HashMap+import Data.List ((\\))+import qualified Data.List as List+import qualified Data.List.Extra as List+import qualified Data.Monoid as Monoid (Any(..))+import qualified Data.Text as Text+import qualified Data.Text.Extra as Text+import GHC.Stack (HasCallStack)++import Clash.Annotations.BitRepresentation.Deriving (dontApplyInHDL)+import Clash.Sized.Vector as Vec (Vec(Cons), splitAt)++import Clash.Annotations.Primitive (extractPrim)+import Clash.Core.DataCon (DataCon(..))+import Clash.Core.FreeVars (freeLocalIds)+import Clash.Core.HasFreeVars+import Clash.Core.HasType+import Clash.Core.Name (mkUnsafeSystemName, nameOcc)+import Clash.Core.Subst+import Clash.Core.Term+ ( LetBinding, Pat(..), PrimInfo(..), Term(..), collectArgs, collectArgsTicks+ , collectTicks, isLambdaBodyCtx, isTickCtx, mkApps, mkLams, mkTicks, Bind(..)+ , partitionTicks, stripAllTicks)+import Clash.Core.TermInfo (isCon, isLet, isLocalVar, isTick)+import Clash.Core.TyCon (tyConDataCons)+import Clash.Core.Type+ (Type(..), TypeView(..), normalizeType+ , splitFunForallTy, tyView)+import Clash.Core.Util (inverseTopSortLetBindings, mkVec, tyNatSize)+import Clash.Core.Var (isGlobalId)+import Clash.Core.VarEnv+ ( InScopeSet, elemInScopeSet, emptyVarEnv, extendInScopeSetList, lookupVarEnv+ , unionVarEnvWith, unitVarEnv, mkVarSet)+import Clash.Netlist.BlackBox.Types ()+import Clash.Netlist.BlackBox.Util (getUsedArguments)+import Clash.Netlist.Util (splitNormalized)+import Clash.Normalize.Primitives (removedArg)+import Clash.Normalize.Transformations.Reduce (reduceBinders)+import Clash.Normalize.Types (NormRewrite, NormalizeSession)+import Clash.Primitives.Types (Primitive(..), UsedArguments(..))+import Clash.Rewrite.Types+ (TransformContext(..), bindings, curFun, tcCache, workFreeBinders, primitives)+import Clash.Rewrite.Util+ (changed, isFromInt, isUntranslatable, mkTmBinderFor, removeUnusedBinders, setChanged)+import Clash.Rewrite.WorkFree+import Clash.Unique (lookupUniqMap)++{- [Note: Name re-creation]+The names of heap bound variables are safely generate with mkUniqSystemId in+Clash.Core.Evaluator.newLetBinding. But only their uniqs end up in the heap,+not the complete names. So we use mkUnsafeSystemName to recreate the same Name.+-}++-- | Remove unused let-bindings+deadCode :: HasCallStack => NormRewrite+deadCode _ e@(Let binds body) =+ case removeUnusedBinders binds body of+ Just t -> changed t+ Nothing -> return e+deadCode _ e = return e+{-# SCC deadCode #-}++removeUnusedExpr :: HasCallStack => NormRewrite+removeUnusedExpr _ e@(collectArgsTicks -> (p@(Prim pInfo),args,ticks)) = do+ bbM <- HashMap.lookup (primName pInfo) <$> Lens.view primitives+ let+ usedArgs0 =+ case Monad.join (extractPrim <$> bbM) of+ Just (BlackBoxHaskell{usedArguments}) ->+ case usedArguments of+ UsedArguments used -> Just used+ IgnoredArguments ignored -> Just ([0..length args - 1] \\ ignored)+ Just (BlackBox pNm _ _ _ _ _ _ _ _ _ inc r ri templ) -> Just $+ if | isFromInt pNm -> [0,1,2]+ | primName pInfo `elem` [ Text.showt 'dontApplyInHDL+ , Text.showt 'Vec.splitAt+ ] -> [0,1]+ | otherwise -> concat [ concatMap getUsedArguments r+ , concatMap getUsedArguments ri+ , getUsedArguments templ+ , concatMap (getUsedArguments . snd) inc ]+ _ ->+ Nothing++ case usedArgs0 of+ Nothing ->+ return e+ Just usedArgs1 -> do+ tcm <- Lens.view tcCache+ (args1, Monoid.getAny -> hasChanged) <- listen (go tcm 0 usedArgs1 args)+ if hasChanged then+ return (mkApps (mkTicks p ticks) args1)+ else+ return e++ where+ arity = length . Either.rights . fst $ splitFunForallTy (coreTypeOf pInfo)++ go _ _ _ [] = return []+ go tcm !n used (Right ty:args') = do+ args'' <- go tcm n used args'+ return (Right ty : args'')+ go tcm !n used (Left tm : args') = do+ args'' <- go tcm (n+1) used args'+ case tm of+ TyApp (Prim p0) _+ | primName p0 == Text.showt 'removedArg+ -> return (Left tm : args'')+ _ -> do+ let ty = inferCoreTypeOf tcm tm+ p' = TyApp (Prim removedArg) ty+ if n < arity && n `notElem` used+ then changed (Left p' : args'')+ else return (Left tm : args'')++removeUnusedExpr _ e@(Case _ _ [(DataPat _ [] xs,altExpr)]) =+ if mkVarSet xs `disjointFreeVars` altExpr+ then changed altExpr+ else return e++-- Replace any expression that creates a Vector of size 0 within the application+-- of the Cons constructor, by the Nil constructor.+removeUnusedExpr _ e@(collectArgsTicks -> (Data dc, [_,Right aTy,Right nTy,_,Left a,Left nil],ticks))+ | nameOcc (dcName dc) == Text.showt 'Vec.Cons+ = do+ tcm <- Lens.view tcCache+ case runExcept (tyNatSize tcm nTy) of+ Right 0+ | (con, _) <- collectArgs nil+ , not (isCon con)+ -> let eTy = inferCoreTypeOf tcm e+ (TyConApp vecTcNm _) = tyView eTy+ (Just vecTc) = lookupUniqMap vecTcNm tcm+ [nilCon,consCon] = tyConDataCons vecTc+ v = mkTicks (mkVec nilCon consCon aTy 1 [a]) ticks+ in changed v+ _ -> return e++removeUnusedExpr _ e = return e+{-# SCC removeUnusedExpr #-}++-- | Flatten's letrecs after `inlineCleanup`+--+-- `inlineCleanup` sometimes exposes additional possibilities for `caseCon`,+-- which then introduces let-bindings in what should be ANF. This transformation+-- flattens those nested let-bindings again.+--+-- NB: must only be called in the cleaning up phase.+flattenLet :: HasCallStack => NormRewrite+flattenLet ctx@(TransformContext is0 _) (Letrec binds0 body0@Letrec{}) = do+ -- deshadow binds1, so binds0 and binds1 don't conflict when merged+ let is1 = extendInScopeSetList is0 (fmap fst binds0)+ Letrec binds1 body1 = deShadowTerm is1 body0++ setChanged+ flattenLet ctx{tfInScope=is1} (Letrec (binds0 <> binds1) body1)++flattenLet (TransformContext is0 _) (Letrec binds body) = do+ let is1 = extendInScopeSetList is0 (map fst binds)+ bodyOccs = Lens.foldMapByOf+ freeLocalIds (unionVarEnvWith (+))+ emptyVarEnv (`unitVarEnv` (1 :: Int))+ body+ (is2,binds1) <- second concat <$> List.mapAccumLM go is1 binds+ bndrs <- Lens.use bindings+ e1WorkFree <-+ case binds1 of+ [(_,e1)] -> isWorkFree workFreeBinders bndrs e1+ _ -> pure (error "flattenLet: unreachable")+ case binds1 of+ -- inline binders into the body when there's only a single binder, and only+ -- if that binder doesn't perform any work or is only used once in the body+ [(id1,e1)] | Just occ <- lookupVarEnv id1 bodyOccs, e1WorkFree || occ < 2 ->+ if id1 `elemFreeVars` e1+ -- Except when the binder is recursive!+ then return (Letrec binds1 body)+ else let subst = extendIdSubst (mkSubst is2) id1 e1+ in changed (substTm "flattenLet" subst body)+ _ -> return (Letrec binds1 body)+ where+ go :: InScopeSet -> LetBinding -> NormalizeSession (InScopeSet,[LetBinding])+ go isN (id1,collectTicks -> (Letrec binds1 body1,ticks)) = do+ let bs1 = map fst binds1+ let (binds2,body2,isN1) =+ -- We need to deshadow because we're merging nested let-expressions+ -- into a single let-expression: and within a let-expression, the+ -- bindings are not allowed to shadow each-other. Of course, we+ -- only need to deshadow if any shadowing is happening in the+ -- first place.+ --+ -- This is much better than blindly calling freshenTm, and saves+ -- almost 30% run-time of the normalization phase on some examples.+ if any (`elemInScopeSet` isN) bs1 then+ let Letrec bindsN bodyN = deShadowTerm isN (Letrec binds1 body1)+ in (bindsN,bodyN,extendInScopeSetList isN (map fst bindsN))+ else+ (binds1,body1,extendInScopeSetList isN bs1)+ let bodyOccs = Lens.foldMapByOf+ freeLocalIds (unionVarEnvWith (+))+ emptyVarEnv (`unitVarEnv` (1 :: Int))+ body2+ (srcTicks,nmTicks) = partitionTicks ticks+ bndrs <- Lens.use bindings+ e2WorkFree <-+ case binds2 of+ [(_,e2)] -> isWorkFree workFreeBinders bndrs e2+ _ -> pure (error "flattenLet: unreachable")+ -- Distribute the name ticks of the let-expression over all the bindings+ (isN1,) . map (second (`mkTicks` nmTicks)) <$> case binds2 of+ -- inline binders into the body when there's only a single binder, and+ -- only if that binder doesn't perform any work or is only used once in+ -- the body+ [(id2,e2)] | Just occ <- lookupVarEnv id2 bodyOccs, e2WorkFree || occ < 2 ->+ if id2 `elemFreeVars` e2+ -- Except when the binder is recursive!+ then changed ([(id2,e2),(id1, body2)])+ else let subst = extendIdSubst (mkSubst isN1) id2 e2+ in changed [(id1+ -- Only apply srcTicks to the body+ ,mkTicks (substTm "flattenLetGo" subst body2)+ srcTicks)]+ bs -> changed (bs ++ [(id1+ -- Only apply srcTicks to the body+ ,mkTicks body2 srcTicks)])+ go isN b = return (isN,[b])++flattenLet _ e = return e+{-# SCC flattenLet #-}++-- | Turn a normalized recursive function, where the recursive calls only pass+-- along the unchanged original arguments, into let-recursive function. This+-- means that all recursive calls are replaced by the same variable reference as+-- found in the body of the top-level let-expression.+recToLetRec :: HasCallStack => NormRewrite+recToLetRec (TransformContext is0 []) e = do+ (fn,_) <- Lens.use curFun+ tcm <- Lens.view tcCache+ case splitNormalized tcm e of+ Right (args,bndrs,res) -> do+ let args' = map Var args+ (toInline,others) = List.partition (eqApp tcm fn args' . snd) bndrs+ resV = Var res+ case (toInline,others) of+ (_:_,_:_) -> do+ let is1 = extendInScopeSetList is0 (args ++ map fst bndrs)+ let substsInline = extendIdSubstList (mkSubst is1)+ $ map (second (const resV)) toInline+ others' = map (second (substTm "recToLetRec" substsInline))+ others+ changed $ mkLams (Letrec others' resV) args+ _ -> return e+ _ -> return e+ where+ -- This checks whether things are semantically equal. For example, say we+ -- have:+ --+ -- x :: (a, (b, c))+ --+ -- and+ --+ -- y :: (a, (b, c))+ --+ -- If we can determine that 'y' is constructed solely using the+ -- corresponding fields in 'x', then we can say they are semantically+ -- equal. The algorithm below keeps track of what (sub)field it is+ -- constructing, and checks if the field-expression projects the+ -- corresponding (sub)field from the target variable.+ --+ -- TODO: See [Note: Breaks on constants and predetermined equality]+ --+ -- Since 'aeqTerm' now looks at ticks when determining equality, it is+ -- required that all ticks are removed with 'stripAllTicks' to keep the+ -- previous behaviour of this function. If we remove this, most terms will+ -- not be identified as equal.+ eqApp tcm v args (collectArgs . stripAllTicks -> (Var v',args'))+ | isGlobalId v'+ , v == v'+ , let args2 = Either.lefts args'+ , length args == length args2+ = and (zipWith (eqArg tcm) args args2)+ eqApp _ _ _ _ = False++ eqArg _ v1 v2@Var{}+ = v1 == v2+ eqArg tcm v1 v2@(collectArgs -> (Data _, args'))+ | let t1 = normalizeType tcm (inferCoreTypeOf tcm v1)+ , let t2 = normalizeType tcm (inferCoreTypeOf tcm v2)+ , t1 == t2+ = if isClassConstraint t1 then+ -- Class constraints are equal if their types are equal, so we can+ -- take a shortcut here.+ True+ else+ -- Check whether all arguments to the data constructor are projections+ --+ and (zipWith (eqDat v1) (map pure [0..]) (Either.lefts args'))+ eqArg _ _ _+ = False++ -- Recursively check whether a term /e/ is semantically equal to some variable /v/.+ -- Currently it can only assert equality when /e/ is syntactically equal+ -- to /v/, or is constructed out of projections of /v/, importantly:+ --+ -- [Note: Breaks on constants and predetermined equality]+ -- This function currently breaks if:+ --+ -- * One or more subfields are constants. Constants might have been+ -- inlined for the construction, instead of being a projection of the+ -- target variable.+ --+ -- * One or more subfields are determined to be equal and one is simply+ -- swapped / replaced by the other. For example, say we have+ -- `x :: (a, a)`. If GHC determines that both elements of the tuple will+ -- always be the same, it might replace the (semantically equal to 'x')+ -- construction of `y` with `(fst x, fst x)`.+ --+ eqDat :: Term -> [Int] -> Term -> Bool+ eqDat v fTrace (collectArgs -> (Data _, args)) =+ and (zipWith (eqDat v) (map (:fTrace) [0..]) (Either.lefts args))+ eqDat v1 fTrace v2 =+ case stripProjection (reverse fTrace) v1 v2 of+ Just [] -> True+ _ -> False++ stripProjection :: [Int] -> Term -> Term -> Maybe [Int]+ stripProjection fTrace0 vTarget0 (Case v _ [(DataPat _ _ xs, r)]) = do+ -- Get projection made in subject of case:+ fTrace1 <- stripProjection fTrace0 vTarget0 v++ -- Extract projection of this case statement. Subsequent calls to+ -- 'stripProjection' will check if new target is actually used.+ (n, fTrace2) <- List.uncons fTrace1+ vTarget1 <- List.indexMaybe xs n++ stripProjection fTrace2 (Var vTarget1) r++ stripProjection fTrace (Var sTarget) (Var s) =+ if sTarget == s then Just fTrace else Nothing++ stripProjection _fTrace _vTarget _v =+ Nothing++recToLetRec _ e = return e+{-# SCC recToLetRec #-}++isClassConstraint :: Type -> Bool+isClassConstraint (tyView -> TyConApp nm0 _) =+ if -- Constraint tuple:+ | "GHC.Classes.(%" `Text.isInfixOf` nm1 -> True+ -- Constraint class:+ | "C:" `Text.isInfixOf` nm2 -> True+ | otherwise -> False+ where+ nm1 = nameOcc nm0+ nm2 = snd (Text.breakOnEnd "." nm1)++isClassConstraint _ = False++-- | Simplified CSE, only works on let-bindings, does an inverse topological+-- sort of the let-bindings and then works from top to bottom+--+-- XXX: Check whether inverse top-sort followed by single traversal removes as+-- many binders as the previous "apply-until-fixpoint" approach in the presence+-- of recursive groups in the let-bindings. If not but just for checking whether+-- changes to transformation affect the eventual size of the circuit, it would+-- be really helpful if we tracked circuit size in the regression/test suite.+-- On the two examples that were tested, Reducer and PipelinesViaFolds, this new+-- version of CSE removed the same amount of let-binders.+simpleCSE :: HasCallStack => NormRewrite+simpleCSE (TransformContext is0 _) term@Letrec{} = do+ let Letrec bndrs body = inverseTopSortLetBindings term+ let is1 = extendInScopeSetList is0 (map fst bndrs)+ ((subst,bndrs1), change) <- listen $ reduceBinders (mkSubst is1) [] bndrs+ -- TODO: check whether a substitution over the body is enough, the reason I'm+ -- doing a substitution over the the binders as well is that I don't know in+ -- what order a recursive group shows up in a inverse topological sort.+ -- Depending on the order and forgetting to apply the substitution over the+ -- let-bindings might lead to the introduction of free variables.+ --+ -- NB: don't apply the substitution to the entire let-expression, and that+ -- would rename the let-bindings because they've been added to the InScopeSet+ -- of the substitution.+ if Monoid.getAny change+ then+ let bndrs2 = map (second (substTm "simpleCSE.bndrs" subst)) bndrs1+ body1 = substTm "simpleCSE.body" subst body+ in changed (Letrec bndrs2 body1)+ else+ return term++simpleCSE _ e = return e+{-# SCC simpleCSE #-}++-- | Ensure that top-level lambda's eventually bind a let-expression of which+-- the body is a variable-reference.+topLet :: HasCallStack => NormRewrite+topLet (TransformContext is0 ctx) e+ | all (\c -> isLambdaBodyCtx c || isTickCtx c) ctx && not (isLet e) && not (isTick e)+ = do+ untranslatable <- isUntranslatable False e+ if untranslatable+ then return e+ else do tcm <- Lens.view tcCache+ argId <- mkTmBinderFor is0 tcm (mkUnsafeSystemName "result" 0) e+ changed (Let (NonRec argId e) (Var argId))++topLet (TransformContext is0 ctx) e@(Letrec binds body)+ | all (\c -> isLambdaBodyCtx c || isTickCtx c) ctx+ = do+ let localVar = isLocalVar body+ untranslatable <- isUntranslatable False body+ if localVar || untranslatable+ then return e+ else do+ tcm <- Lens.view tcCache+ let is2 = extendInScopeSetList is0 (fmap fst binds)+ argId <- mkTmBinderFor is2 tcm (mkUnsafeSystemName "result" 0) body++ -- TODO We would like this to be+ --+ -- Let binds (Let (NonRec argId body) (Var argId))+ --+ -- but this makes tests/shouldwork/SimIO/Test00.hs fail.+ changed (Letrec (binds ++ [(argId, body)]) (Var argId))++topLet _ e = return e+{-# SCC topLet #-}
+ src/Clash/Normalize/Transformations/MultiPrim.hs view
@@ -0,0 +1,130 @@+{-|+ Copyright : (C) 2012-2016, University of Twente,+ 2016-2017, Myrtle Software Ltd,+ 2017-2018, Google Inc.+ 2022 , QBayLogic B.V.+ License : BSD2 (see the file LICENSE)+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com>++ Transformations on primitives with multiple results.+-}++{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}++module Clash.Normalize.Transformations.MultiPrim+ ( setupMultiResultPrim+ ) where++import qualified Control.Lens as Lens+import qualified Data.Either as Either+import Data.Text.Extra (showt)+import GHC.Stack (HasCallStack)++import Clash.Annotations.Primitive (extractPrim)+import Clash.Core.Name (mkUnsafeInternalName)+import Clash.Core.Term+ ( IsMultiPrim(..), MultiPrimInfo(..), PrimInfo(..), Term(..), WorkInfo(..)+ , mkAbstraction, mkApps, mkTmApps, mkTyApps, PrimUnfolding(..))+import Clash.Core.TermInfo (multiPrimInfo')+import Clash.Core.TyCon (TyConMap)+import Clash.Core.Type (Type(..), mkPolyFunTy, splitFunForallTy)+import Clash.Core.Util (listToLets)+import Clash.Core.Var (mkLocalId)+import Clash.Normalize.Types (NormRewrite)+import Clash.Primitives.Types (Primitive(..))+import Clash.Rewrite.Types (tcCache, primitives)+import Clash.Rewrite.Util (changed)++-- Note [MultiResult type]+--+-- A multi result primitive assigns its results to multiple result variables+-- instead of one. Besides producing nicer HDL it works around issues with+-- synthesis tooling described in:+--+-- https://github.com/clash-lang/clash-compiler/issues/1555+--+-- This transformation rewrites primitives indicating they can assign their+-- results to multiple signals, such that netlist can easily render it. This+-- involves inserting additional arguments for each of the result values, and+-- then using the c$multiPrimSelect primitive to select individual results.+--+-- Example:+--+-- @+-- prim :: forall a b c. a -> (b, c)+-- @+--+-- will be rewritten to:+--+-- @+-- \(x :: a) ->+-- let+-- r = prim @a @b @c x r0 r1 -- With 'Clash.Core.Term.MultiPrim'+-- r0 = c$multiPrimSelect r0 r+-- r1 = c$multiPrimSelect r1 r+-- in+-- (r0, r1)+-- @+--+-- Netlist will not render any @multiPrimSelect@ primitives. Similar to+-- primitives having a /void/ return type, /r/ is not rendered either.+--+-- This transformation is currently hardcoded to recognize tuples as return+-- types, not any product type. It will error if it sees a multi result primitive+-- with a non-tuple return type.+--+setupMultiResultPrim :: HasCallStack => NormRewrite+setupMultiResultPrim _ctx e@(Prim pInfo@PrimInfo{primMultiResult=SingleResult}) = do+ tcm <- Lens.view tcCache+ prim <- Lens.view (primitives . Lens.at (primName pInfo))++ case prim >>= extractPrim of+ Just (BlackBoxHaskell{multiResult=True}) ->+ changed (setupMultiResultPrim' tcm pInfo)+ Just (BlackBox{multiResult=True}) ->+ changed (setupMultiResultPrim' tcm pInfo)+ _ ->+ return e++setupMultiResultPrim _ e = return e++setupMultiResultPrim' :: HasCallStack => TyConMap -> PrimInfo -> Term+setupMultiResultPrim' tcm primInfo@PrimInfo{primType} =+ mkAbstraction letTerm (map Right typeVars <> map Left argIds)+ where+ typeVars = Either.lefts pArgs++ internalNm prefix n = mkUnsafeInternalName (prefix <> showt n) n+ internalId prefix typ n = mkLocalId typ (internalNm prefix n)++ nTermArgs = length (Either.rights pArgs)+ argIds = zipWith (internalId "a") (Either.rights pArgs) [1..nTermArgs]+ resIds = zipWith (internalId "r") resTypes [nTermArgs+1..nTermArgs+length resTypes]+ resId = mkLocalId pResTy (mkUnsafeInternalName "r" (nTermArgs+length resTypes+1))++ (pArgs, pResTy) = splitFunForallTy primType+ MultiPrimInfo{mpi_resultDc=tupTc, mpi_resultTypes=resTypes} =+ multiPrimInfo' tcm primInfo++ multiPrimSelect r t = (r, mkTmApps (Prim (multiPrimSelectInfo t)) [Var r, Var resId])+ multiPrimSelectBinds = zipWith multiPrimSelect resIds resTypes+ multiPrimTermArgs = map (Left . Var) (argIds <> resIds)+ multiPrimTypeArgs = map (Right . VarTy) typeVars+ multiPrimBind =+ mkApps+ (Prim primInfo{primMultiResult=MultiResult})+ (multiPrimTypeArgs <> multiPrimTermArgs)++ multiPrimSelectInfo t = PrimInfo+ { primName = "c$multiPrimSelect"+ , primType = mkPolyFunTy pResTy [Right pResTy, Right t]+ , primWorkInfo = WorkAlways+ , primMultiResult = SingleResult+ , primUnfolding = NoUnfolding+ }++ letTerm =+ listToLets+ ((resId,multiPrimBind):multiPrimSelectBinds)+ (mkTmApps (mkTyApps (Data tupTc) resTypes) (map Var resIds))
+ src/Clash/Normalize/Transformations/Reduce.hs view
@@ -0,0 +1,480 @@+{-|+ Copyright : (C) 2012-2016, University of Twente,+ 2016-2017, Myrtle Software Ltd,+ 2017-2018, Google Inc.,+ 2021-2022, QBayLogic B.V.+ License : BSD2 (see the file LICENSE)+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com>++ Transformations for compile-time reduction of expressions / primitives.+-}++{-# LANGUAGE OverloadedStrings #-}++module Clash.Normalize.Transformations.Reduce+ ( reduceBinders+ , reduceConst+ , reduceNonRepPrim+ ) where++import qualified Control.Lens as Lens+import Control.Monad.Trans.Except (runExcept)+import qualified Data.Either as Either+import qualified Data.List as List+import qualified Data.List.Extra as List+import qualified Data.Maybe as Maybe+import GHC.Stack (HasCallStack)++import Clash.Core.FreeVars (typeFreeVars)+import Clash.Core.HasType+import Clash.Core.Name (nameOcc)+import Clash.Core.Subst (Subst, extendIdSubst, substTm)+import Clash.Core.Term+ ( LetBinding, PrimInfo(..), Term(..), TickInfo(..), collectArgs+ , collectArgsTicks, mkApps, mkTicks)+import Clash.Core.TyCon (tyConDataCons)+import Clash.Core.Type (TypeView(..), mkTyConApp, tyView)+import Clash.Core.Util (mkVec, shouldSplit, tyNatSize)+import Clash.Normalize.PrimitiveReductions+import Clash.Normalize.Primitives (removedArg)+import Clash.Normalize.Types (NormRewrite, NormalizeSession)+import Clash.Normalize.Util (shouldReduce)+import Clash.Rewrite.Types (TransformContext(..), tcCache, normalizeUltra)+import Clash.Rewrite.Util (changed, isUntranslatableType, setChanged, whnfRW)+import Clash.Unique (lookupUniqMap)++-- | XXX: is given inverse topologically sorted binders, but returns+-- topologically sorted binders+--+-- TODO: check further speed improvements:+--+-- 1. Store the processed binders in a `Map Expr LetBinding`:+-- * Trades O(1) `cons` and O(n)*aeqTerm `find` for:+-- * O(log n)*aeqTerm `insert` and O(log n)*aeqTerm `lookup`+-- 2. Store the processed binders in a `AEQTrie Expr LetBinding`+-- * Trades O(1) `cons` and O(n)*aeqTerm `find` for:+-- * O(e) `insert` and O(e) `lookup`+reduceBinders+ :: Subst+ -> [LetBinding]+ -> [LetBinding]+ -> NormalizeSession (Subst, [LetBinding])+reduceBinders !subst processed [] = return (subst,processed)+reduceBinders !subst processed ((i,substTm "reduceBinders" subst -> e):rest)+ | (_,_,ticks) <- collectArgsTicks e+ , NoDeDup `notElem` ticks+ , Just (i1,_) <- List.find ((== e) . snd) processed+ = do+ let subst1 = extendIdSubst subst i (Var i1)+ setChanged+ reduceBinders subst1 processed rest+ | otherwise+ = reduceBinders subst ((i,e):processed) rest+{-# SCC reduceBinders #-}++reduceConst :: HasCallStack => NormRewrite+reduceConst ctx e@(App _ _)+ | (Prim p0, _) <- collectArgs e+ = whnfRW False ctx e $ \_ctx1 e1 -> case e1 of+ (collectArgs -> (Prim p1, _)) | primName p0 == primName p1 -> return e+ _ -> changed e1++reduceConst _ e = return e+{-# SCC reduceConst #-}++-- | Replace primitives by their "definition" if they would lead to let-bindings+-- with a non-representable type when a function is in ANF. This happens for+-- example when Clash.Size.Vector.map consumes or produces a vector of+-- non-representable elements.+--+-- Basically what this transformation does is replace a primitive the completely+-- unrolled recursive definition that it represents. e.g.+--+-- > zipWith ($) (xs :: Vec 2 (Int -> Int)) (ys :: Vec 2 Int)+--+-- is replaced by:+--+-- > let (x0 :: (Int -> Int)) = case xs of (:>) _ x xr -> x+-- > (xr0 :: Vec 1 (Int -> Int)) = case xs of (:>) _ x xr -> xr+-- > (x1 :: (Int -> Int)( = case xr0 of (:>) _ x xr -> x+-- > (y0 :: Int) = case ys of (:>) _ y yr -> y+-- > (yr0 :: Vec 1 Int) = case ys of (:>) _ y yr -> xr+-- > (y1 :: Int = case yr0 of (:>) _ y yr -> y+-- > in (($) x0 y0 :> ($) x1 y1 :> Nil)+--+-- Currently, it only handles the following functions:+--+-- * Clash.Sized.Vector.zipWith+-- * Clash.Sized.Vector.map+-- * Clash.Sized.Vector.traverse#+-- * Clash.Sized.Vector.fold+-- * Clash.Sized.Vector.foldr+-- * Clash.Sized.Vector.dfold+-- * Clash.Sized.Vector.(++)+-- * Clash.Sized.Vector.head+-- * Clash.Sized.Vector.tail+-- * Clash.Sized.Vector.last+-- * Clash.Sized.Vector.init+-- * Clash.Sized.Vector.unconcat+-- * Clash.Sized.Vector.transpose+-- * Clash.Sized.Vector.replicate+-- * Clash.Sized.Vector.replace_int+-- * Clash.Sized.Vector.imap+-- * Clash.Sized.Vector.dtfold+-- * Clash.Sized.RTree.tdfold+-- * Clash.Sized.RTree.treplicate+-- * Clash.Sized.Internal.BitVector.split#+-- * Clash.Sized.Internal.BitVector.eq#+--+-- Note [Unroll shouldSplit types]+-- 1. Certain higher-order functions over Vec, such as map, have specialized+-- code-paths to turn them into generate-for loops in HDL, instead of having to+-- having to unroll/inline their recursive definitions, e.g. Clash.Sized.Vector.map+--+-- 2. Clash, in general, translates Haskell product types to VHDL records. This+-- mostly works out fine, there is however one exception: certain synthesis+-- tools, and some HDL simulation tools (like verilator), do not like it when+-- the clock (and certain other global control signals) is contained in a+-- record type; they want them to be separate inputs to the entity/module.+-- And Clash actually does some transformations to try to ensure that values of+-- type Clock do not end up in a VHDL record type.+--+-- The problem is that the transformations in 2. never took into account the+-- specialized code-paths in 1. Making the code-paths in 1. aware of the+-- transformations in 2. is really not worth the effort for such a niche case.+-- It's easier to just unroll the recursive definitions.+--+-- See https://github.com/clash-lang/clash-compiler/issues/1606+reduceNonRepPrim :: HasCallStack => NormRewrite+reduceNonRepPrim c@(TransformContext is0 ctx) e@(App _ _) | (Prim p, args, ticks) <- collectArgsTicks e = do+ tcm <- Lens.view tcCache+ ultra <- Lens.view normalizeUltra+ let eTy = inferCoreTypeOf tcm e+ case tyView eTy of+ (TyConApp vecTcNm@(nameOcc -> "Clash.Sized.Vector.Vec")+ [runExcept . tyNatSize tcm -> Right 0, aTy]) -> do+ let (Just vecTc) = lookupUniqMap vecTcNm tcm+ [nilCon,consCon] = tyConDataCons vecTc+ nilE = mkVec nilCon consCon aTy 0 []+ changed (mkTicks nilE ticks)+ tv -> let argLen = length args in case primName p of+ "Clash.Sized.Vector.zipWith" | argLen == 7 -> do+ let [lhsElTy,rhsElty,resElTy,nTy] = Either.rights args+ TyConApp vecTcNm _ = tv+ lhsTy = mkTyConApp vecTcNm [nTy,lhsElTy]+ rhsTy = mkTyConApp vecTcNm [nTy,rhsElty]+ case runExcept (tyNatSize tcm nTy) of+ Right n -> do+ shouldReduce1 <- List.orM [ pure (ultra || n < 2)+ , shouldReduce ctx+ , List.anyM isUntranslatableType_not_poly+ [lhsElTy,rhsElty,resElTy]+ -- Note [Unroll shouldSplit types]+ , pure (any (Maybe.isJust . shouldSplit tcm)+ [lhsTy,rhsTy,eTy]) ]+ if shouldReduce1+ then let [fun,lhsArg,rhsArg] = Either.lefts args+ in (`mkTicks` ticks) <$>+ reduceZipWith c p n lhsElTy rhsElty resElTy fun lhsArg rhsArg+ else return e+ _ -> return e+ "Clash.Sized.Vector.map" | argLen == 5 -> do+ let [argElTy,resElTy,nTy] = Either.rights args+ TyConApp vecTcNm _ = tv+ argTy = mkTyConApp vecTcNm [nTy,argElTy]+ case runExcept (tyNatSize tcm nTy) of+ Right n -> do+ shouldReduce1 <- List.orM [ pure (ultra || n < 2 )+ , shouldReduce ctx+ , List.anyM isUntranslatableType_not_poly+ [argElTy,resElTy]+ -- Note [Unroll shouldSplit types]+ , pure (any (Maybe.isJust . shouldSplit tcm)+ [argTy,eTy]) ]+ if shouldReduce1+ then let [fun,arg] = Either.lefts args+ in (`mkTicks` ticks) <$> reduceMap c p n argElTy resElTy fun arg+ else return e+ _ -> return e+ "Clash.Sized.Vector.traverse#" | argLen == 7 ->+ let [aTy,fTy,bTy,nTy] = Either.rights args+ in case runExcept (tyNatSize tcm nTy) of+ Right n ->+ let [dict,fun,arg] = Either.lefts args+ in (`mkTicks` ticks) <$> reduceTraverse c n aTy fTy bTy dict fun arg+ _ -> return e+ "Clash.Sized.Vector.fold" | argLen == 4 -> do+ let ([fun,arg],[nTy,aTy]) = Either.partitionEithers args+ argTy = inferCoreTypeOf tcm arg+ case runExcept (tyNatSize tcm nTy) of+ Right n -> do+ shouldReduce1 <- List.orM [ pure (ultra || n == 0)+ , shouldReduce ctx+ , isUntranslatableType_not_poly aTy+ -- Note [Unroll shouldSplit types]+ , pure (Maybe.isJust (shouldSplit tcm argTy))]+ if shouldReduce1 then+ (`mkTicks` ticks) <$> reduceFold c (n + 1) aTy fun arg+ else return e+ _ -> return e+ "Clash.Sized.Vector.foldr" | argLen == 6 ->+ let ([fun,start,arg],[aTy,bTy,nTy]) = Either.partitionEithers args+ argTy = inferCoreTypeOf tcm arg+ in case runExcept (tyNatSize tcm nTy) of+ Right n -> do+ shouldReduce1 <- List.orM [ pure ultra+ , shouldReduce ctx+ , List.anyM isUntranslatableType_not_poly [aTy,bTy]+ -- Note [Unroll shouldSplit types]+ , pure (Maybe.isJust (shouldSplit tcm argTy)) ]+ if shouldReduce1+ then (`mkTicks` ticks) <$> reduceFoldr c p n aTy fun start arg+ else return e+ _ -> return e+ "Clash.Sized.Vector.dfold" | argLen == 8 ->+ let ([_kn,_motive,fun,start,arg],[_mTy,nTy,aTy]) = Either.partitionEithers args+ in case runExcept (tyNatSize tcm nTy) of+ Right n -> (`mkTicks` ticks) <$> reduceDFold is0 n aTy fun start arg+ _ -> return e+ "Clash.Sized.Vector.++" | argLen == 5 ->+ let [nTy,aTy,mTy] = Either.rights args+ [lArg,rArg] = Either.lefts args+ in case (runExcept (tyNatSize tcm nTy), runExcept (tyNatSize tcm mTy)) of+ (Right n, Right m)+ | n == 0 -> changed rArg+ | m == 0 -> changed lArg+ | otherwise -> do+ shouldReduce1 <- List.orM [ shouldReduce ctx+ , isUntranslatableType_not_poly aTy+ -- Note [Unroll shouldSplit types]+ , pure (Maybe.isJust (shouldSplit tcm eTy)) ]+ if shouldReduce1+ then (`mkTicks` ticks) <$> reduceAppend is0 n m aTy lArg rArg+ else return e+ _ -> return e+ "Clash.Sized.Vector.head" | argLen == 3 -> do+ let [nTy,aTy] = Either.rights args+ [vArg] = Either.lefts args+ argTy = inferCoreTypeOf tcm vArg+ case runExcept (tyNatSize tcm nTy) of+ Right n -> do+ shouldReduce1 <- List.orM [ shouldReduce ctx+ , isUntranslatableType_not_poly aTy+ -- Note [Unroll shouldSplit types]+ , pure (Maybe.isJust (shouldSplit tcm argTy)) ]+ if shouldReduce1+ then (`mkTicks` ticks) <$> reduceHead is0 (n+1) aTy vArg+ else return e+ _ -> return e+ "Clash.Sized.Vector.tail" | argLen == 3 -> do+ let [nTy,aTy] = Either.rights args+ [vArg] = Either.lefts args+ argTy = inferCoreTypeOf tcm vArg+ case runExcept (tyNatSize tcm nTy) of+ Right n -> do+ shouldReduce1 <- List.orM [ shouldReduce ctx+ , isUntranslatableType_not_poly aTy+ -- Note [Unroll shouldSplit types]+ , pure (Maybe.isJust (shouldSplit tcm argTy)) ]+ if shouldReduce1+ then (`mkTicks` ticks) <$> reduceTail is0 (n+1) aTy vArg+ else return e+ _ -> return e+ "Clash.Sized.Vector.last" | argLen == 3 -> do+ let [nTy,aTy] = Either.rights args+ [vArg] = Either.lefts args+ argTy = inferCoreTypeOf tcm vArg+ case runExcept (tyNatSize tcm nTy) of+ Right n -> do+ shouldReduce1 <- List.orM [ shouldReduce ctx+ , isUntranslatableType_not_poly aTy+ -- Note [Unroll shouldSplit types]+ , pure (Maybe.isJust (shouldSplit tcm argTy))+ ]+ if shouldReduce1+ then (`mkTicks` ticks) <$> reduceLast is0 (n+1) aTy vArg+ else return e+ _ -> return e+ "Clash.Sized.Vector.init" | argLen == 3 -> do+ let [nTy,aTy] = Either.rights args+ [vArg] = Either.lefts args+ argTy = inferCoreTypeOf tcm vArg+ case runExcept (tyNatSize tcm nTy) of+ Right n -> do+ shouldReduce1 <- List.orM [ shouldReduce ctx+ , isUntranslatableType_not_poly aTy+ -- Note [Unroll shouldSplit types]+ , pure (Maybe.isJust (shouldSplit tcm argTy)) ]+ if shouldReduce1+ then (`mkTicks` ticks) <$> reduceInit is0 p n aTy vArg+ else return e+ _ -> return e+ "Clash.Sized.Vector.unconcat" | argLen == 6 -> do+ let ([_knN,sm,arg],[nTy,mTy,aTy]) = Either.partitionEithers args+ argTy = inferCoreTypeOf tcm arg+ case (runExcept (tyNatSize tcm nTy), runExcept (tyNatSize tcm mTy)) of+ (Right n, Right m) -> do+ shouldReduce1 <- List.orM [ pure (m==0)+ , shouldReduce ctx+ , isUntranslatableType_not_poly aTy+ -- Note [Unroll shouldSplit types]+ , pure (Maybe.isJust (shouldSplit tcm argTy))+ ]+ if shouldReduce1 then+ (`mkTicks` ticks) <$> reduceUnconcat is0 p n m aTy sm arg+ else+ return e+ _ -> return e+ "Clash.Sized.Vector.transpose" | argLen == 5 -> do+ let ([_knN,arg],[mTy,nTy,aTy]) = Either.partitionEithers args+ case (runExcept (tyNatSize tcm nTy), runExcept (tyNatSize tcm mTy)) of+ (Right n, Right 0) -> (`mkTicks` ticks) <$> reduceTranspose n 0 aTy arg+ _ -> return e+ "Clash.Sized.Vector.replicate" | argLen == 4 -> do+ let ([_sArg,vArg],[nTy,aTy]) = Either.partitionEithers args+ case runExcept (tyNatSize tcm nTy) of+ Right n -> do+ shouldReduce1 <- List.orM [ shouldReduce ctx+ , isUntranslatableType_not_poly aTy+ -- Note [Unroll shouldSplit types]+ , pure (Maybe.isJust (shouldSplit tcm eTy))+ ]+ if shouldReduce1+ then (`mkTicks` ticks) <$> reduceReplicate n aTy eTy vArg+ else return e+ _ -> return e+ -- replace_int :: KnownNat n => Vec n a -> Int -> a -> Vec n a+ "Clash.Sized.Vector.replace_int" | argLen == 6 -> do+ let ([_knArg,vArg,iArg,aArg],[nTy,aTy]) = Either.partitionEithers args+ case runExcept (tyNatSize tcm nTy) of+ Right n -> do+ shouldReduce1 <- List.orM [ pure ultra+ , shouldReduce ctx+ , isUntranslatableType_not_poly aTy+ -- Note [Unroll shouldSplit types]+ , pure (Maybe.isJust (shouldSplit tcm eTy))+ ]+ if shouldReduce1+ then (`mkTicks` ticks) <$> reduceReplace_int is0 n aTy eTy vArg iArg aArg+ else return e+ _ -> return e++ "Clash.Sized.Vector.index_int" | argLen == 5 -> do+ let ([_knArg,vArg,iArg],[nTy,aTy]) = Either.partitionEithers args+ argTy = inferCoreTypeOf tcm vArg+ case runExcept (tyNatSize tcm nTy) of+ Right n -> do+ shouldReduce1 <- List.orM [ pure ultra+ , shouldReduce ctx+ , isUntranslatableType_not_poly aTy+ -- Note [Unroll shouldSplit types]+ , pure (Maybe.isJust (shouldSplit tcm argTy)) ]+ if shouldReduce1+ then (`mkTicks` ticks) <$> reduceIndex_int is0 n aTy vArg iArg+ else return e+ _ -> return e++ "Clash.Sized.Vector.imap" | argLen == 6 -> do+ let [nTy,argElTy,resElTy] = Either.rights args+ TyConApp vecTcNm _ = tv+ argTy = mkTyConApp vecTcNm [nTy,argElTy]+ case runExcept (tyNatSize tcm nTy) of+ Right n -> do+ shouldReduce1 <- List.orM [ pure (ultra || n < 2)+ , shouldReduce ctx+ , List.anyM isUntranslatableType_not_poly [argElTy,resElTy]+ -- Note [Unroll shouldSplit types]+ , pure (any (Maybe.isJust . shouldSplit tcm)+ [argTy,eTy]) ]+ if shouldReduce1+ then let [_,fun,arg] = Either.lefts args+ in (`mkTicks` ticks) <$> reduceImap c n argElTy resElTy fun arg+ else return e+ _ -> return e+ "Clash.Sized.Vector.iterateI" | argLen == 5 ->+ let ([_kn,f,a],[nTy,aTy]) = Either.partitionEithers args in+ case runExcept (tyNatSize tcm nTy) of+ Right n -> do+ shouldReduce1 <- List.orM+ [ pure (ultra || n < 2)+ , shouldReduce ctx+ , isUntranslatableType_not_poly aTy+ -- Note [Unroll shouldSplit types]+ , pure (Maybe.isJust (shouldSplit tcm eTy)) ]++ if shouldReduce1 then+ (`mkTicks` ticks) <$> reduceIterateI c n aTy eTy f a+ else+ return e+ _ -> return e+ "Clash.Sized.Vector.dtfold" | argLen == 8 ->+ let ([_kn,_motive,lrFun,brFun,arg],[_mTy,nTy,aTy]) = Either.partitionEithers args+ in case runExcept (tyNatSize tcm nTy) of+ Right n -> (`mkTicks` ticks) <$> reduceDTFold is0 n aTy lrFun brFun arg+ _ -> return e++ "Clash.Sized.Vector.reverse"+ | ultra+ , ([vArg],[nTy,aTy]) <- Either.partitionEithers args+ , Right n <- runExcept (tyNatSize tcm nTy)+ -> (`mkTicks` ticks) <$> reduceReverse is0 n aTy vArg++ "Clash.Sized.RTree.tdfold" | argLen == 8 ->+ let ([_kn,_motive,lrFun,brFun,arg],[_mTy,nTy,aTy]) = Either.partitionEithers args+ in case runExcept (tyNatSize tcm nTy) of+ Right n -> (`mkTicks` ticks) <$> reduceTFold is0 n aTy lrFun brFun arg+ _ -> return e+ "Clash.Sized.RTree.treplicate" | argLen == 4 -> do+ let ([_sArg,vArg],[nTy,aTy]) = Either.partitionEithers args+ case runExcept (tyNatSize tcm nTy) of+ Right n -> do+ shouldReduce1 <- List.orM [ shouldReduce ctx+ , isUntranslatableType False aTy ]+ if shouldReduce1+ then (`mkTicks` ticks) <$> reduceTReplicate n aTy eTy vArg+ else return e+ _ -> return e+ "Clash.Sized.Internal.BitVector.split#" | argLen == 4 -> do+ let ([_knArg,bvArg],[nTy,mTy]) = Either.partitionEithers args+ case (runExcept (tyNatSize tcm nTy), runExcept (tyNatSize tcm mTy), tv) of+ (Right n, Right m, TyConApp tupTcNm [lTy,rTy])+ | n == 0 -> do+ let (Just tupTc) = lookupUniqMap tupTcNm tcm+ [tupDc] = tyConDataCons tupTc+ tup = mkApps (Data tupDc)+ [Right lTy+ ,Right rTy+ ,Left bvArg+ ,Left (TyApp (Prim removedArg) rTy)+ ]++ changed (mkTicks tup ticks)+ | m == 0 -> do+ let (Just tupTc) = lookupUniqMap tupTcNm tcm+ [tupDc] = tyConDataCons tupTc+ tup = mkApps (Data tupDc)+ [Right lTy+ ,Right rTy+ ,Left (TyApp (Prim removedArg) lTy)+ ,Left bvArg+ ]++ changed (mkTicks tup ticks)+ _ -> return e+ "Clash.Sized.Internal.BitVector.eq#"+ | ([_,_],[nTy]) <- Either.partitionEithers args+ , Right 0 <- runExcept (tyNatSize tcm nTy)+ , TyConApp boolTcNm [] <- tv+ -> let (Just boolTc) = lookupUniqMap boolTcNm tcm+ [_falseDc,trueDc] = tyConDataCons boolTc+ in changed (mkTicks (Data trueDc) ticks)+ _ -> return e+ where+ isUntranslatableType_not_poly t = do+ u <- isUntranslatableType False t+ if u+ then return (null $ Lens.toListOf typeFreeVars t)+ else return False++reduceNonRepPrim _ e = return e+{-# SCC reduceNonRepPrim #-}
+ src/Clash/Normalize/Transformations/SeparateArgs.hs view
@@ -0,0 +1,120 @@+{-|+ Copyright : (C) 2012-2016, University of Twente,+ 2016-2017, Myrtle Software Ltd,+ 2017-2018, Google Inc.,+ 2021 , QBayLogic B.V.+ License : BSD2 (see the file LICENSE)+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com>+ The separating arguments transformation+-}++{-# LANGUAGE OverloadedStrings #-}++module Clash.Normalize.Transformations.SeparateArgs+ ( separateArguments+ ) where++import qualified Control.Lens as Lens+import Control.Monad.Writer (listen)+import qualified Data.List as List+import qualified Data.Monoid as Monoid+import GHC.Stack (HasCallStack)++import Clash.Core.HasType+import Clash.Core.Name (Name(..))+import Clash.Core.Subst (extendIdSubst, mkSubst, substTm)+import Clash.Core.Term (Term(..), collectArgsTicks, mkApps, mkLams, mkTicks)+import Clash.Core.Type (Type, mkPolyFunTy, splitFunForallTy)+import Clash.Core.TyCon (TyConMap)+import Clash.Core.Util (Projections (..), shouldSplit)+import Clash.Core.Var (Id, TyVar, Var (..), isGlobalId, mkLocalId)+import Clash.Core.VarEnv (extendInScopeSet, uniqAway)+import Clash.Normalize.Types (NormRewrite, NormalizeSession)+import Clash.Rewrite.Types (TransformContext(..), tcCache)+import Clash.Rewrite.Util (changed, mkDerivedName)++-- | Split apart (global) function arguments that contain types that we+-- want to separate off, e.g. Clocks. Works on both the definition side (i.e. the+-- lambda), and the call site (i.e. the application of the global variable). e.g.+-- turns+--+-- > f :: (Clock System, Reset System) -> Signal System Int+--+-- into+--+-- > f :: Clock System -> Reset System -> Signal System Int+separateArguments :: HasCallStack => NormRewrite+separateArguments ctx e0@(Lam b eb) = do+ tcm <- Lens.view tcCache+ case separateLambda tcm ctx b eb of+ Just e1 -> changed e1+ Nothing -> return e0++separateArguments (TransformContext is0 _) e@(collectArgsTicks -> (Var g, args, ticks))+ | isGlobalId g = do+ -- We ensure that both the type of the global variable reference is updated+ -- to take into account the changed arguments, and that we apply the global+ -- function with the split apart arguments.+ let (argTys0,resTy) = splitFunForallTy (coreTypeOf g)+ (concat -> args1, Monoid.getAny -> hasChanged)+ <- listen (mapM (uncurry splitArg) (zip argTys0 args))+ if hasChanged then+ let (argTys1,args2) = unzip args1+ gTy = mkPolyFunTy resTy argTys1+ in return (mkApps (mkTicks (Var g {varType = gTy}) ticks) args2)+ else+ return e++ where+ -- Split a single argument+ splitArg+ :: Either TyVar Type+ -- The quantifier/function argument type of the global variable+ -> Either Term Type+ -- The applied type argument or term argument+ -> NormalizeSession [(Either TyVar Type,Either Term Type)]+ splitArg tv arg@(Right _) = return [(tv,arg)]+ splitArg ty arg@(Left tmArg) = do+ tcm <- Lens.view tcCache+ let argTy = inferCoreTypeOf tcm tmArg+ case shouldSplit tcm argTy of+ Just (_,Projections projections,_) -> do+ tmArgs <- projections is0 tmArg+ changed (map ((ty,) . Left) tmArgs)+ _ ->+ return [(ty,arg)]++separateArguments _ e = return e+{-# SCC separateArguments #-}++-- | Worker function of 'separateArguments'.+separateLambda+ :: TyConMap+ -> TransformContext+ -> Id+ -- ^ Lambda binder+ -> Term+ -- ^ Lambda body+ -> Maybe Term+ -- ^ If lambda is split up, this function returns a Just containing the new term+separateLambda tcm ctx@(TransformContext is0 _) b eb0 =+ case shouldSplit tcm (coreTypeOf b) of+ Just (dc, _, argTys) ->+ let+ nm = mkDerivedName ctx (nameOcc (varName b))+ bs0 = map (`mkLocalId` nm) argTys+ (is1, bs1) = List.mapAccumL newBinder is0 bs0+ subst = extendIdSubst (mkSubst is1) b (dc (map Var bs1))+ eb1 = substTm "separateArguments" subst eb0+ in+ Just (mkLams eb1 bs1)+ _ ->+ Nothing+ where+ newBinder isN0 x =+ let+ x' = uniqAway isN0 x+ isN1 = extendInScopeSet isN0 x'+ in+ (isN1, x')+{-# SCC separateLambda #-}
+ src/Clash/Normalize/Transformations/Specialize.hs view
@@ -0,0 +1,699 @@+{-|+ Copyright : (C) 2012-2016, University of Twente,+ 2016-2017, Myrtle Software Ltd,+ 2017-2018, Google Inc.,+ 2021-2022, QBayLogic B.V.+ License : BSD2 (see the file LICENSE)+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com>++ Transformations for specialisation.+-}++{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE NondecreasingIndentation #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskellQuotes #-}++module Clash.Normalize.Transformations.Specialize+ ( appProp+ , constantSpec+ , specialize+ , nonRepSpec+ , typeSpec+ , zeroWidthSpec+ ) where++import Control.Arrow ((***), (&&&))+import Control.DeepSeq (deepseq)+import Control.Exception (throw)+import Control.Lens ((%=))+import qualified Control.Lens as Lens+import qualified Control.Monad as Monad+import Control.Monad.Extra (orM)+import qualified Control.Monad.Writer as Writer (listen)+import Data.Bifunctor (bimap)+import Data.Coerce (coerce)+import qualified Data.Either as Either+import Data.Functor.Const (Const(..))+import qualified Data.Map.Strict as Map+import qualified Data.Monoid as Monoid (getAny)+import qualified Data.Set.Ordered as OSet+import qualified Data.Set.Ordered.Extra as OSet+import qualified Data.Text as Text+import qualified Data.Text.Extra as Text+import GHC.Stack (HasCallStack)++#if MIN_VERSION_ghc(9,0,0)+import GHC.Types.Basic (InlineSpec (..))+#else+import BasicTypes (InlineSpec (..))+#endif++import qualified Clash.Sized.Internal.BitVector as BV (BitVector, fromInteger#)+import qualified Clash.Sized.Internal.Index as I (Index, fromInteger#)+import qualified Clash.Sized.Internal.Signed as S (Signed, fromInteger#)+import qualified Clash.Sized.Internal.Unsigned as U (Unsigned, fromInteger#)++import Clash.Core.DataCon (DataCon(dcArgTys))+import Clash.Core.FreeVars (freeLocalVars, termFreeTyVars, typeFreeVars)+import Clash.Core.HasType+import Clash.Core.Literal (Literal(..))+import Clash.Core.Name+ (NameSort(..), Name(..), appendToName, mkUnsafeInternalName, mkUnsafeSystemName)+import Clash.Core.Pretty (showPpr)+import Clash.Core.Subst+import Clash.Core.Term+ ( Term(..), TickInfo, collectArgs, collectArgsTicks, mkApps, mkTmApps, mkTicks, patIds, Bind(..)+ , patVars, mkAbstraction, PrimInfo(..), WorkInfo(..), IsMultiPrim(..), PrimUnfolding(..), stripAllTicks)+import Clash.Core.TermInfo (isLocalVar, isVar, isPolyFun)+import Clash.Core.TyCon (TyConMap, tyConDataCons)+import Clash.Core.Type+ (LitTy(NumTy), Type(LitTy,VarTy), applyFunTy, splitTyConAppM, normalizeType+ , mkPolyFunTy, mkTyConApp)+import Clash.Core.TysPrim+import Clash.Core.Util (listToLets)+import Clash.Core.Var (Var(..), Id, TyVar, mkTyVar)+import Clash.Core.VarEnv+ ( InScopeSet, extendInScopeSet, extendInScopeSetList, lookupVarEnv+ , mkInScopeSet, mkVarSet, unionInScope, elemVarSet)+import Clash.Debug (traceIf, traceM)+import Clash.Driver.Types (Binding(..), TransformationInfo(..), hasTransformationInfo)+import Clash.Netlist.Util (representableType)+import Clash.Rewrite.Combinators (topdownR)+import Clash.Rewrite.Types+ ( TransformContext(..), bindings, censor, curFun, customReprs, extra, tcCache+ , typeTranslator, workFreeBinders, debugOpts, topEntities, specializationLimit)+import Clash.Rewrite.Util+ ( mkBinderFor, mkDerivedName, mkFunction, mkTmBinderFor, setChanged, changed+ , normalizeTermTypes, normalizeId)+import Clash.Rewrite.WorkFree (isWorkFree)+import Clash.Normalize.Types+ ( NormRewrite, NormalizeSession, specialisationCache, specialisationHistory)+import Clash.Normalize.Util+ (constantSpecInfo, csrFoundConstant, csrNewBindings, csrNewTerm)+import Clash.Unique+ ( eltsUniqMap, eltsUniqSet, extendUniqMapWith, unitUniqSet, filterUniqMap+ , lookupUniqMap)+import Clash.Util (ClashException(..))++-- | Propagate arguments of application inwards; except for 'Lam' where the+-- argument becomes let-bound. 'appProp' tries to propagate as many arguments+-- as possible, down as many levels as possible; and should be called in a+-- top-down traversal.+--+-- The idea is that this reduces the number of traversals, which hopefully leads+-- to shorter compile times.+--+-- Note [AppProp no shadowing]+--+-- Case 1.+--+-- Imagine:+--+-- @+-- (case x of+-- D a b -> h a) (f x y)+-- @+--+-- rewriting this to:+--+-- @+-- let b = f x y+-- in case x of+-- D a b -> h a b+-- @+--+-- is very bad because 'b' in 'h a b' is now bound by the pattern instead of the+-- newly introduced let-binding+--+-- instead me must deshadow w.r.t. the new variable and rewrite to:+--+-- @+-- let b = f x y+-- in case x of+-- D a b1 -> h a b+-- @+--+-- Case 2.+--+-- Imagine+--+-- @+-- (\x -> e) u+-- @+--+-- where @u@ has a free variable named @x@, rewriting this to:+--+-- @+-- let x = u+-- in e+-- @+--+-- would be very bad, because the let-binding suddenly captures the free+-- variable in @u@. To prevent this from happening we over-approximate and check+-- whether @x@ is in the current InScopeSet, and deshadow if that's the case,+-- i.e. we then rewrite to:+--+-- let x1 = u+-- in e [x:=x1]+--+-- Case 3.+--+-- The same for:+--+-- @+-- (let x = w in e) u+-- @+--+-- where @u@ again has a free variable @x@, rewriting this to:+--+-- @+-- let x = w in (e u)+-- @+--+-- would be bad because the let-binding now captures the free variable in @u@.+--+-- To prevent this from happening, we unconditionally deshadow the function part+-- of the application w.r.t. the free variables in the argument part of the+-- application. It is okay to over-approximate in this case and deshadow w.r.t+-- the current InScopeSet.+appProp :: HasCallStack => NormRewrite+appProp ctx@(TransformContext is _) = \case+ e@App {}+ | let (fun,args,ticks) = collectArgsTicks e+ -> do (eN,hasChanged) <- Writer.listen (go is (deShadowTerm is fun) args ticks)+ if Monoid.getAny hasChanged+ then return eN+ else return e+ e@TyApp {}+ | let (fun,args,ticks) = collectArgsTicks e+ -> do (eN,hasChanged) <- Writer.listen (go is (deShadowTerm is fun) args ticks)+ if Monoid.getAny hasChanged+ then return eN+ else return e+ e -> return e+ where+ go :: InScopeSet -> Term -> [Either Term Type] -> [TickInfo] -> NormalizeSession Term+ go is0 (collectArgsTicks -> (fun,args0@(_:_),ticks0)) args1 ticks1 =+ go is0 fun (args0 ++ args1) (ticks0 ++ ticks1)++ go is0 (Lam v e) (Left arg:args) ticks = do+ setChanged+ bndrs <- Lens.use bindings+ orM [pure (isVar arg), isWorkFree workFreeBinders bndrs arg] >>= \case+ True ->+ let subst = extendIdSubst (mkSubst is0) v arg in+ (`mkTicks` ticks) <$> go is0 (substTm "appProp.AppLam" subst e) args []+ False ->+ let is1 = extendInScopeSet is0 v in+ Let (NonRec v arg) <$> go is1 (deShadowTerm is1 e) args ticks++ go is0 (Let (NonRec i x) e) args@(_:_) ticks = do+ setChanged+ let is1 = extendInScopeSet is0 i+ -- XXX: binding should already be deshadowed w.r.t. 'is0'+ Let (NonRec i x) <$> go is1 e args ticks++ go is0 (Let (Rec vs) e) args@(_:_) ticks = do+ setChanged+ let vbs = map fst vs+ is1 = extendInScopeSetList is0 vbs+ -- XXX: 'vs' should already be deshadowed w.r.t. 'is0'+ Let (Rec vs) <$> go is1 e args ticks++ go is0 (TyLam tv e) (Right t:args) ticks = do+ setChanged+ let subst = extendTvSubst (mkSubst is0) tv t+ (`mkTicks` ticks) <$> go is0 (substTm "appProp.TyAppTyLam" subst e) args []++ go is0 (Case scrut ty0 alts) args0@(_:_) ticks = do+ setChanged+ let isA1 = unionInScope+ is0+ ((mkInScopeSet . mkVarSet . concatMap (patVars . fst)) alts)+ (ty1,vs,args1) <- goCaseArg isA1 ty0 [] args0+ case vs of+ [] -> (`mkTicks` ticks) . Case scrut ty1 <$> mapM (goAlt is0 args1) alts+ _ -> do+ let vbs = map fst vs+ is1 = extendInScopeSetList is0 vbs+ alts1 = map (deShadowAlt is1) alts+ -- TODO I should have a mkNonRecLets :: [LetBinding] -> Term -> Term+ -- function which makes a chain of non-recursive let expressions without+ -- needing to first take the SCCs of all the binders.+ listToLets vs . (`mkTicks` ticks) . Case scrut ty1 <$> mapM (goAlt is1 args1) alts1++ go is0 (Tick sp e) args ticks = do+ setChanged+ go is0 e args (sp:ticks)++ go _ fun args ticks = return (mkApps (mkTicks fun ticks) args)++ goAlt is0 args0 (p,e) = do+ let (tvs,ids) = patIds p+ is1 = extendInScopeSetList (extendInScopeSetList is0 tvs) ids+ (p,) <$> go is1 e args0 []++ goCaseArg isA ty0 ls0 (Right t:args0) = do+ tcm <- Lens.view tcCache+ let ty1 = piResultTy tcm ty0 t+ (ty2,ls1,args1) <- goCaseArg isA ty1 ls0 args0+ return (ty2,ls1,Right t:args1)++ goCaseArg isA0 ty0 ls0 (Left arg:args0) = do+ tcm <- Lens.view tcCache+ bndrs <- Lens.use bindings+ let argTy = inferCoreTypeOf tcm arg+ ty1 = applyFunTy tcm ty0 argTy+ orM [pure (isVar arg), isWorkFree workFreeBinders bndrs arg] >>= \case+ True -> do+ (ty2,ls1,args1) <- goCaseArg isA0 ty1 ls0 args0+ return (ty2,ls1,Left arg:args1)+ False -> do+ boundArg <- mkTmBinderFor isA0 tcm (mkDerivedName ctx "app_arg") arg+ let isA1 = extendInScopeSet isA0 boundArg+ (ty2,ls1,args1) <- goCaseArg isA1 ty1 ls0 args0+ return (ty2,(boundArg,arg):ls1,Left (Var boundArg):args1)++ goCaseArg _ ty ls [] = return (ty,ls,[])+{-# SCC appProp #-}++-- | Specialise functions on arguments which are constant, except when they+-- are clock, reset generators.+constantSpec :: HasCallStack => NormRewrite+constantSpec ctx@(TransformContext is0 tfCtx) e@(App e1 e2)+ | (Var {}, args) <- collectArgs e1+ , (_, []) <- Either.partitionEithers args+ , null $ Lens.toListOf termFreeTyVars e2+ = do specInfo<- constantSpecInfo ctx e2+ if csrFoundConstant specInfo then+ let newBindings = csrNewBindings specInfo in+ if null newBindings then+ -- Whole of e2 is constant+ specialize ctx (App e1 e2)+ else do+ -- Parts of e2 are constant+ let is1 = extendInScopeSetList is0 (fst <$> csrNewBindings specInfo)+ (body, isSpec) <- Writer.listen $ specialize+ (TransformContext is1 tfCtx)+ (App e1 (csrNewTerm specInfo))++ if Monoid.getAny isSpec+ then changed (listToLets newBindings body)+ else return e+ else+ -- e2 has no constant parts+ return e+constantSpec _ e = return e+{-# SCC constantSpec #-}++-- | Specialize an application on its argument+specialize :: NormRewrite+specialize ctx e = case e of+ (TyApp e1 ty) -> specialize' ctx e (collectArgsTicks e1) (Right ty)+ (App e1 e2) -> specialize' ctx e (collectArgsTicks e1) (Left e2)+ _ -> return e++{-+Note [ticks and specialization]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+As Clash now distinguishes between ticks in expressions when comparing for+alpha equality, this has a knock-on effect when accessing the specialization+cache. Consider these applications which differ only by ticks:++ f[GlobalId] (\x -> ... x[LocalId])+ f[GlobalId] <tick>(\x -> ... x[LocalId])+ f[GlobalId] (\x -> ... <tick>x[LocalId])++If one of these had been specialized, the other two would hit that term in the+specialization cache, saving Clash from having to re-do work which is in effect+the same. To preserve this behaviour, we use 'stripAllTicks' on the keys for+the specialization cache.++TODO While this preserves the old behaviour, the old behaviour is likely not+quite what we want. Using a value from the specialization cache may change the+ticks present, which can affect naming / debugging information in generated HDL.+We may also not want to look at ticks, as then the specialization cache will+miss on virtually every lookup which could add to normalization time.+-}++-- | Specialize an application on its argument+specialize'+ :: TransformContext+ -- ^ Transformation context+ -> Term+ -- ^ Original term+ -> (Term, [Either Term Type], [TickInfo])+ -- ^ Function part of the term, split into root and applied arguments+ -> Either Term Type+ -- ^ Argument to specialize on+ -> NormalizeSession Term+specialize' (TransformContext is0 _) e (Var f, args, ticks) specArgIn = do+ opts <- Lens.view debugOpts+ tcm <- Lens.view tcCache++ -- Don't specialize TopEntities+ topEnts <- Lens.view topEntities+ if f `elemVarSet` topEnts+ then do+ case specArgIn of+ Left _ -> do+ traceM ("Not specializing TopEntity: " ++ showPpr (varName f))+ return e+ Right tyArg ->+ traceIf (hasTransformationInfo AppliedTerm opts) ("Dropping type application on TopEntity: " ++ showPpr (varName f) ++ "\ntype:\n" ++ showPpr tyArg) $+ -- TopEntities aren't allowed to be semantically polymorphic.+ -- But using type equality constraints they may be syntactically polymorphic.+ -- > topEntity :: forall dom . (dom ~ "System") => Signal dom Bool -> Signal dom Bool+ -- The TyLam's in the body will have been removed by 'Clash.Normalize.Util.substWithTyEq'.+ -- So we drop the TyApp ("specializing" on it) and change the varType to match.+ let newVarTy = piResultTy tcm (coreTypeOf f) tyArg+ in changed (mkApps (mkTicks (Var f{varType = newVarTy}) ticks) args)+ else do -- NondecreasingIndentation++ let specArg = bimap (normalizeTermTypes tcm) (normalizeType tcm) specArgIn+ -- Create binders and variable references for free variables in 'specArg'+ -- (specBndrsIn,specVars) :: ([Either Id TyVar], [Either Term Type])+ (specBndrsIn,specVars) = specArgBndrsAndVars specArg+ argLen = length args+ specBndrs :: [Either Id TyVar]+ specBndrs = map (Lens.over Lens._Left (normalizeId tcm)) specBndrsIn++ -- See Note [ticks and specialization]+ specAbs :: Either Term Type+ specAbs = either (Left . stripAllTicks . (`mkAbstraction` specBndrs)) (Right . id) specArg+ -- Determine if 'f' has already been specialized on (a type-normalized) 'specArg'+ specM <- Map.lookup (f,argLen,specAbs) <$> Lens.use (extra.specialisationCache)+ case specM of+ -- Use previously specialized function+ Just f' ->+ traceIf (hasTransformationInfo AppliedTerm opts)+ ("Using previous specialization of " ++ showPpr (varName f) ++ " on " +++ (either showPpr showPpr) specAbs ++ ": " ++ showPpr (varName f')) $+ changed $ mkApps (mkTicks (Var f') ticks) (args ++ specVars)+ -- Create new specialized function+ Nothing -> do+ -- Determine if we can specialize f+ bodyMaybe <- fmap (lookupUniqMap (varName f)) $ Lens.use bindings+ case bodyMaybe of+ Just (Binding _ sp inl _ bodyTm _) -> do+ -- Determine if we see a sequence of specializations on a growing argument+ specHistM <- lookupUniqMap f <$> Lens.use (extra.specialisationHistory)+ specLim <- Lens.view specializationLimit+ if maybe False (> specLim) specHistM+ then throw (ClashException+ sp+ (unlines [ "Hit specialization limit " ++ show specLim ++ " on function `" ++ showPpr (varName f) ++ "'.\n"+ , "The function `" ++ showPpr f ++ "' is most likely recursive, and looks like it is being indefinitely specialized on a growing argument.\n"+ , "Body of `" ++ showPpr f ++ "':\n" ++ showPpr bodyTm ++ "\n"+ , "Argument (in position: " ++ show argLen ++ ") that triggered termination:\n" ++ (either showPpr showPpr) specArg+ , "Run with '-fclash-spec-limit=N' to increase the specialization limit to N."+ ])+ Nothing)+ else do+ let existingNames = collectBndrsMinusApps bodyTm+ newNames = [ mkUnsafeInternalName ("pTS" `Text.append` Text.pack (show n)) n+ | n <- [(0::Int)..]+ ]+ -- Make new binders for existing arguments+ (boundArgs,argVars) <- fmap (unzip . map (either (Left &&& Left . Var) (Right &&& Right . VarTy))) $+ Monad.zipWithM+ (mkBinderFor is0 tcm)+ (existingNames ++ newNames)+ args+ -- Determine name the resulting specialized function, and the+ -- form of the specialized-on argument+ (fId,inl',specArg') <- case specArg of+ Left a@(collectArgsTicks -> (Var g,gArgs,_gTicks)) -> if isPolyFun tcm a+ then do+ -- In case we are specialising on an argument that is a+ -- global function then we use that function's name as the+ -- name of the specialized higher-order function.+ -- Additionally, we will return the body of the global+ -- function, instead of a variable reference to the+ -- global function.+ --+ -- This will turn things like @mealy g k@ into a new+ -- binding @g'@ where both the body of @mealy@ and @g@+ -- are inlined, meaning the state-transition-function+ -- and the memory element will be in a single function.+ gTmM <- fmap (lookupUniqMap (varName g)) $ Lens.use bindings+ return (g,maybe inl bindingSpec gTmM, maybe specArg (Left . (`mkApps` gArgs) . bindingTerm) gTmM)+ else return (f,inl,specArg)+ _ -> return (f,inl,specArg)+ -- Create specialized functions+ let newBody = mkAbstraction (mkApps bodyTm (argVars ++ [specArg'])) (boundArgs ++ specBndrs)+ newf <- mkFunction (varName fId) sp inl' newBody+ -- Remember specialization+ (extra.specialisationHistory) %= extendUniqMapWith f 1 (+)+ (extra.specialisationCache) %= Map.insert (f,argLen,specAbs) newf+ -- use specialized function+ let newExpr = mkApps (mkTicks (Var newf) ticks) (args ++ specVars)+ newf `deepseq` changed newExpr+ Nothing -> return e+ where+ collectBndrsMinusApps :: Term -> [Name a]+ collectBndrsMinusApps = reverse . go []+ where+ go bs (Lam v e') = go (coerce (varName v):bs) e'+ go bs (TyLam tv e') = go (coerce (varName tv):bs) e'+ go bs (App e' _) = case go [] e' of+ [] -> bs+ bs' -> init bs' ++ bs+ go bs (TyApp e' _) = case go [] e' of+ [] -> bs+ bs' -> init bs' ++ bs+ go bs _ = bs++-- Specialising non Var's is used by nonRepANF+specialize' _ctx _ (appE,args,ticks) (Left specArg) = do+ -- Create binders and variable references for free variables in 'specArg'+ let (specBndrs,specVars) = specArgBndrsAndVars (Left specArg)+ -- Create specialized function+ newBody = mkAbstraction specArg specBndrs+ -- See if there's an existing binder that's alpha-equivalent to the+ -- specialized function+ existing <- filterUniqMap ((`aeqTerm` newBody) . bindingTerm) <$> Lens.use bindings+ -- Create a new function if an alpha-equivalent binder doesn't exist+ newf <- case eltsUniqMap existing of+ [] -> do (cf,sp) <- Lens.use curFun+ mkFunction (appendToName (varName cf) "_specF") sp NoUserInline newBody+ (b:_) -> return (bindingId b)+ -- Create specialized argument+ let newArg = Left $ mkApps (Var newf) specVars+ -- Use specialized argument+ let newExpr = mkApps (mkTicks appE ticks) (args ++ [newArg])+ changed newExpr++specialize' _ e _ _ = return e++-- Note [Collect free-variables in an insertion-ordered set]+--+-- In order for the specialization cache to work, 'specArgBndrsAndVars' should+-- yield (alpha equivalent) results for the same specialization. While collecting+-- free variables in a given term or type it should therefore keep a stable+-- ordering based on the order in which it finds free vars. To see why,+-- consider the following two pseudo-code calls to 'specialise':+--+-- specialise {f ('a', x[123], y[456])}+-- specialise {f ('b', x[456], y[123])}+--+-- Collecting the binders in a VarSet would yield the following (unique ordered)+-- sets:+--+-- {x[123], y[456]}+-- {y[123], x[456]}+--+-- ..and therefore breaking specializing caching. We now track them in insert-+-- ordered sets, yielding:+--+-- {x[123], y[456]}+-- {x[456], y[123]}+--++-- | Create binders and variable references for free variables in 'specArg'+specArgBndrsAndVars+ :: Either Term Type+ -> ([Either Id TyVar], [Either Term Type])+specArgBndrsAndVars specArg =+ -- See Note [Collect free-variables in an insertion-ordered set]+ let unitFV :: Var a -> Const (OSet.OLSet TyVar, OSet.OLSet Id) (Var a)+ unitFV v@(Id {}) = Const (mempty, coerce (OSet.singleton (coerce v)))+ unitFV v@(TyVar {}) = Const (coerce (OSet.singleton (coerce v)), mempty)++ (specFTVs,specFVs) = case specArg of+ Left tm -> (OSet.toListL *** OSet.toListL) . getConst $+ Lens.foldMapOf freeLocalVars unitFV tm+ Right ty -> (eltsUniqSet (Lens.foldMapOf typeFreeVars unitUniqSet ty),[] :: [Id])++ specTyBndrs = map Right specFTVs+ specTmBndrs = map Left specFVs++ specTyVars = map (Right . VarTy) specFTVs+ specTmVars = map (Left . Var) specFVs++ in (specTyBndrs ++ specTmBndrs,specTyVars ++ specTmVars)++-- | Specialize functions on their non-representable argument+nonRepSpec :: HasCallStack => NormRewrite+nonRepSpec ctx e@(App e1 e2)+ | (Var {}, args) <- collectArgs e1+ , (_, []) <- Either.partitionEithers args+ , null $ Lens.toListOf termFreeTyVars e2+ = do tcm <- Lens.view tcCache+ let e2Ty = inferCoreTypeOf tcm e2+ let localVar = isLocalVar e2+ nonRepE2 <- not <$> (representableType <$> Lens.view typeTranslator+ <*> Lens.view customReprs+ <*> pure False+ <*> Lens.view tcCache+ <*> pure e2Ty)+ if nonRepE2 && not localVar+ then do+ e2' <- inlineInternalSpecialisationArgument e2+ specialize ctx (App e1 e2')+ else return e+ where+ -- | If the argument on which we're specialising ia an internal function,+ -- one created by the compiler, then inline that function before we+ -- specialise.+ --+ -- We need to do this because otherwise the specialisation history won't+ -- recognize the new specialisation argument as something the function has+ -- already been specialized on+ inlineInternalSpecialisationArgument+ :: Term+ -> NormalizeSession Term+ inlineInternalSpecialisationArgument app+ | (Var f,fArgs,ticks) <- collectArgsTicks app+ = do+ fTmM <- lookupVarEnv f <$> Lens.use bindings+ case fTmM of+ Just b+ | nameSort (varName (bindingId b)) == Internal+ -> censor (const mempty)+ (topdownR appProp ctx+ (mkApps (mkTicks (bindingTerm b) ticks) fArgs))+ _ -> return app+ | otherwise = return app++nonRepSpec _ e = return e+{-# SCC nonRepSpec #-}++-- | Specialize functions on their type+typeSpec :: HasCallStack => NormRewrite+typeSpec ctx e@(TyApp e1 ty)+ | (Var {}, args) <- collectArgs e1+ , null $ Lens.toListOf typeFreeVars ty+ , (_, []) <- Either.partitionEithers args+ = specialize ctx e++typeSpec _ e = return e+{-# SCC typeSpec #-}++-- | Specialize functions on arguments which are zero-width. These arguments+-- can have only one possible value, and specialising on this value may create+-- additional oppourtunities for transformations to fire.+--+-- As we can't remove zero-width arguements (as transformations cannot change+-- the type of a term), we instead substitute all occurances of a lambda-bound+-- variable with a zero-width type with the only value of that type.+--+zeroWidthSpec :: HasCallStack => NormRewrite+zeroWidthSpec (TransformContext is _) e@(Lam i x0) = do+ tcm <- Lens.view tcCache+ let bndrTy = normalizeType tcm (coreTypeOf i)++ case zeroWidthTypeElem tcm bndrTy of+ Just tm ->+ let subst = extendIdSubst (mkSubst is) i tm+ x1 = substTm "zeroWidthSpec" subst x0+ in changed (Lam i x1)++ Nothing ->+ return e++zeroWidthSpec _ e = return e+{-# SCC zeroWidthSpec #-}++-- Get the only element of a type, if it is zero-width.+--+zeroWidthTypeElem :: TyConMap -> Type -> Maybe Term+zeroWidthTypeElem tcm ty = do+ (tcNm, args) <- splitTyConAppM ty++ if | nameOcc tcNm == Text.showt ''BV.BitVector+ , [LitTy (NumTy 0)] <- args+ -> return (bitVectorZW tcNm args)++ | nameOcc tcNm == Text.showt ''I.Index+ , [LitTy (NumTy 1)] <- args+ -> return (indexZW tcNm args)++ | nameOcc tcNm == Text.showt ''S.Signed+ , [LitTy (NumTy 0)] <- args+ -> return (signedZW tcNm args)++ | nameOcc tcNm == Text.showt ''U.Unsigned+ , [LitTy (NumTy 0)] <- args+ -> return (unsignedZW tcNm args)++ -- Any other zero-width type should only have a single data constructor+ -- where all fields are also zero-width.+ | otherwise+ -> do+ tc <- lookupUniqMap tcNm tcm++ case tyConDataCons tc of+ [dc] -> do+ zwArgs <- traverse (zeroWidthTypeElem tcm) (dcArgTys dc)+ return (mkTmApps (Data dc) zwArgs)++ _ ->+ Nothing+ where+ nNm = mkUnsafeSystemName "n" 0+ nTv = mkTyVar typeNatKind nNm++ mkBitVector tcNm =+ let prTy = mkPolyFunTy (mkTyConApp tcNm [VarTy nTv])+ [Left nTv, Right naturalPrimTy, Right naturalPrimTy, Right integerPrimTy]+ in PrimInfo (Text.showt 'BV.fromInteger#) prTy WorkNever SingleResult NoUnfolding++ bitVectorZW tcNm tyArgs =+ let pr = mkBitVector tcNm+ in mkApps (Prim pr) $ fmap Right tyArgs <>+ [ Left (Literal (NaturalLiteral 0))+ , Left (Literal (NaturalLiteral 0))+ , Left (Literal (IntegerLiteral 0))+ ]++ mkSizedNum tcNm n =+ let prTy = mkPolyFunTy (mkTyConApp tcNm [VarTy nTv])+ [Left nTv, Right naturalPrimTy, Right integerPrimTy]+ in PrimInfo n prTy WorkNever SingleResult NoUnfolding++ indexZW tcNm tyArgs =+ let pr = mkSizedNum tcNm (Text.showt 'I.fromInteger#)+ in mkApps (Prim pr) $ fmap Right tyArgs <>+ [ Left (Literal (NaturalLiteral 1))+ , Left (Literal (IntegerLiteral 0))+ ]++ signedZW tcNm tyArgs =+ let pr = mkSizedNum tcNm (Text.showt 'S.fromInteger#)+ in mkApps (Prim pr) $ fmap Right tyArgs <>+ [ Left (Literal (NaturalLiteral 0))+ , Left (Literal (IntegerLiteral 0))+ ]++ unsignedZW tcNm tyArgs =+ let pr = mkSizedNum tcNm (Text.showt 'U.fromInteger#)+ in mkApps (Prim pr) $ fmap Right tyArgs <>+ [ Left (Literal (NaturalLiteral 0))+ , Left (Literal (IntegerLiteral 0))+ ]
+ src/Clash/Normalize/Transformations/XOptimize.hs view
@@ -0,0 +1,156 @@+{-|+ Copyright : (C) 2012-2016, University of Twente,+ 2016-2017, Myrtle Software Ltd,+ 2017-2018, Google Inc.,+ 2021-2022, QBayLogic B.V.+ License : BSD2 (see the file LICENSE)+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com>++ The X-optimization transformation.+-}++{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++module Clash.Normalize.Transformations.XOptimize+ ( xOptimize+ ) where++import qualified Control.Lens as Lens+import qualified Control.Monad as Monad+import qualified Data.List.Extra as List+import qualified Data.Text.Extra as Text (showt)+import GHC.Stack (HasCallStack)++import Clash.XException (errorX)++import Clash.Annotations.Primitive (extractPrim)+import Clash.Core.DataCon (DataCon)+import Clash.Core.HasType+import Clash.Core.Term+ ( Alt, IsMultiPrim(..), LetBinding, Pat(..), PrimInfo(..), Term(..)+ , WorkInfo(..), collectArgs, PrimUnfolding(..))+import Clash.Core.Type (TyVar, Type)+import Clash.Core.Util (mkInternalVar)+import Clash.Core.Var (Id)+import Clash.Core.VarEnv (InScopeSet)+import Clash.Netlist.BlackBox.Types (Element(Err))+import Clash.Netlist.Types (BlackBox(..))+import Clash.Normalize.Types (NormRewrite, NormalizeSession)+import Clash.Primitives.Types (Primitive(..))+import Clash.Rewrite.Types+ (TransformContext(..), aggressiveXOpt, tcCache, primitives)+import Clash.Rewrite.Util (changed)+import Clash.Util (MonadUnique, curLoc)++-- | Remove all undefined alternatives from case expressions, replacing them+-- with the value of another defined alternative. If there is one defined+-- alternative, the entire expression is replaced with that alternative. If+-- there are no defined alternatives, the entire expression is replaced with+-- a call to 'errorX'.+--+-- e.g. It converts+--+-- case x of+-- D1 a -> f a+-- D2 -> undefined+-- D3 -> undefined+--+-- to+--+-- let subj = x+-- a = case subj of+-- D1 a -> field0+-- in f a+--+-- where fieldN is an internal variable referring to the nth argument of a+-- data constructor.+--+xOptimize :: HasCallStack => NormRewrite+xOptimize (TransformContext is0 _) e@(Case subj ty alts) = do+ runXOpt <- Lens.view aggressiveXOpt++ if runXOpt then do+ defPart <- List.partitionM (isPrimError . snd) alts++ case defPart of+ ([], _) -> return e+ (_, []) -> changed (Prim (PrimInfo (Text.showt 'errorX) ty WorkConstant SingleResult NoUnfolding))+ (_, [alt]) -> xOptimizeSingle is0 subj alt+ (_, defs) -> xOptimizeMany is0 subj ty defs+ else+ return e++xOptimize _ e = return e+{-# SCC xOptimize #-}++-- Return an expression equivalent to the alternative given. When only one+-- alternative is defined the result of this function is used to replace the+-- case expression.+--+xOptimizeSingle :: InScopeSet -> Term -> Alt -> NormalizeSession Term+xOptimizeSingle is subj (DataPat dc tvs vars, expr) = do+ tcm <- Lens.view tcCache+ subjId <- mkInternalVar is "subj" (inferCoreTypeOf tcm subj)++ let fieldTys = fmap coreTypeOf vars+ lets <- Monad.zipWithM (mkFieldSelector is subjId dc tvs fieldTys) vars [0..]++ changed (Letrec ((subjId, subj) : lets) expr)++xOptimizeSingle _ _ (_, expr) = changed expr++-- Given a list of alternatives which are defined, create a new case+-- expression which only ever returns a defined value.+--+xOptimizeMany+ :: HasCallStack+ => InScopeSet+ -> Term+ -> Type+ -> [Alt]+ -> NormalizeSession Term+xOptimizeMany is subj ty defs@(d:ds)+ | isAnyDefault defs = changed (Case subj ty defs)+ | otherwise = do+ newAlt <- xOptimizeSingle is subj d+ changed (Case subj ty $ ds <> [(DefaultPat, newAlt)])+ where+ isAnyDefault :: [Alt] -> Bool+ isAnyDefault = any ((== DefaultPat) . fst)++xOptimizeMany _ _ _ [] =+ error $ $(curLoc) ++ "Report as bug: xOptimizeMany error: No defined alternatives"++mkFieldSelector+ :: MonadUnique m+ => InScopeSet+ -> Id+ -- ^ subject id+ -> DataCon+ -> [TyVar]+ -> [Type]+ -- ^ concrete types of fields+ -> Id+ -> Int+ -> m LetBinding+mkFieldSelector is0 subj dc tvs fieldTys nm index = do+ fields <- mapM (\ty -> mkInternalVar is0 "field" ty) fieldTys+ let alt = (DataPat dc tvs fields, Var $ fields !! index)+ return (nm, Case (Var subj) (fieldTys !! index) [alt])++-- Check whether a term is really a black box primitive representing an error.+-- Such values are undefined and are removed in X Optimization.+--+isPrimError :: Term -> NormalizeSession Bool+isPrimError (collectArgs -> (Prim pInfo, _)) = do+ prim <- Lens.view (primitives . Lens.at (primName pInfo))++ case prim >>= extractPrim of+ Just p -> return (isErr p)+ Nothing -> return False+ where+ isErr BlackBox{template=(BBTemplate [Err _])} = True+ isErr _ = False++isPrimError _ = return False
src/Clash/Normalize/Types.hs view
@@ -1,8 +1,9 @@ {-| Copyright : (C) 2012-2016, University of Twente, 2017, Google Inc.+ 2022, QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Types used in Normalize modules -}@@ -11,6 +12,7 @@ module Clash.Normalize.Types where +import qualified Control.Lens as Lens import Control.Monad.State.Strict (State) import Data.Map (Map) import Data.Set (Set)@@ -21,9 +23,7 @@ import Clash.Core.Var (Id) import Clash.Core.VarEnv (VarEnv) import Clash.Driver.Types (BindingMap)-import Clash.Primitives.Types (CompiledPrimMap) import Clash.Rewrite.Types (Rewrite, RewriteMonad)-import Clash.Util -- | State of the 'NormalizeMonad' data NormalizeState@@ -38,23 +38,12 @@ -- * Elem: (name of specialized function,type of specialized function) , _specialisationHistory :: VarEnv Int -- ^ Cache of how many times a function was specialized- , _specialisationLimit :: !Int- -- ^ Number of time a function 'f' can be specialized , _inlineHistory :: VarEnv (VarEnv Int) -- ^ Cache of function where inlining took place: -- -- * Key: function where inlining took place -- -- * Elem: (functions which were inlined, number of times inlined)- , _inlineLimit :: !Int- -- ^ Number of times a function 'f' can be inlined in a function 'g'- , _inlineFunctionLimit :: !Word- -- ^ Size of a function below which it is always inlined if it is not- -- recursive- , _inlineConstantLimit :: !Word- -- ^ Size of a constant below which it is always inlined; 0 = no limit- , _primitives :: CompiledPrimMap- -- ^ Primitive Definitions , _primitiveArgs :: Map Text (Set Int) -- ^ Cache for looking up constantness of blackbox arguments , _recursiveComponents :: VarEnv Bool@@ -62,18 +51,9 @@ -- -- NB: there are only no mutually-recursive component, only self-recursive -- ones.- , _newInlineStrategy :: Bool- -- ^ Flattening stage should use the new (no-)inlining strategy- , _normalizeUltra :: Bool- -- ^ High-effort normalization session, trading performance improvement for- -- potentially much longer compile times. Follows the 'Clash.Driver.opt_ultra'- -- flag.- , _inlineWFCacheLimit :: !Word- -- ^ At what size do we cache normalized work-free top-level binders. } -makeLenses ''NormalizeState-+Lens.makeLenses ''NormalizeState -- | State monad that stores specialisation and inlining information type NormalizeMonad = State NormalizeState@@ -95,4 +75,4 @@ } deriving Show -makeLenses ''TermClassification+Lens.makeLenses ''TermClassification
src/Clash/Normalize/Util.hs view
@@ -1,15 +1,16 @@ {-|- Copyright : (C) 2012-2016, University of Twente+ Copyright : (C) 2012-2016, University of Twente,+ 2021-2022, QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Utility functions used by the normalisation transformations -} {-# LANGUAGE CPP #-}-{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TemplateHaskellQuotes #-} module Clash.Normalize.Util ( ConstantSpecInfo(..)@@ -17,9 +18,7 @@ , shouldReduce , alreadyInlined , addNewInline- , specializeNorm , isRecursiveBndr- , isClosed , callGraph , collectCallGraphUniques , classifyFunction@@ -28,7 +27,6 @@ , constantSpecInfo , normalizeTopLvlBndr , rewriteExpr- , removedTm , mkInlineTick , substWithTyEq , tvSubstWithTyEq@@ -38,7 +36,7 @@ import Control.Lens ((&),(+~),(%=),(.=)) import qualified Control.Lens as Lens import Data.Bifunctor (bimap)-import Data.Either (lefts)+import Data.Either (lefts,rights) import qualified Data.List as List import qualified Data.List.Extra as List import qualified Data.Map as Map@@ -46,6 +44,7 @@ import qualified Data.HashSet as HashSet import Data.Text (Text) import qualified Data.Text as Text+import qualified Data.Text.Extra as Text #if MIN_VERSION_ghc(9,0,0) import GHC.Builtin.Names (eqTyConKey)@@ -57,34 +56,36 @@ import Clash.Annotations.Primitive (extractPrim) import Clash.Core.FreeVars- (globalIds, hasLocalFreeVars, globalIdOccursIn)+ (globalIds, globalIdOccursIn)+import Clash.Core.HasFreeVars (isClosed)+import Clash.Core.HasType import Clash.Core.Name (Name(nameOcc,nameUniq)) import Clash.Core.Pretty (showPpr) import Clash.Core.Subst- (deShadowTerm, extendTvSubst, extendTvSubstList, mkSubst, substTm, substTy,+ (deShadowTerm, extendTvSubst, mkSubst, substTm, substTy, substId, extendIdSubst) import Clash.Core.Term-import Clash.Core.TermInfo (isPolyFun, termType)-import Clash.Core.TyCon (TyConMap) import Clash.Core.Type- (Type(LitTy, VarTy), LitTy(SymTy), TypeView (..), tyView, undefinedTy,- splitFunForallTy, splitTyConAppM, mkPolyFunTy)+ (Type(ForAllTy,LitTy, VarTy), LitTy(SymTy), TypeView (..), tyView,+ splitTyConAppM, mkPolyFunTy) import Clash.Core.Util (isClockOrReset) import Clash.Core.Var (Id, TyVar, Var (..), isGlobalId) import Clash.Core.VarEnv (VarEnv, emptyInScopeSet, emptyVarEnv, extendVarEnv, extendVarEnvWith,- lookupVarEnv, unionVarEnvWith, unitVarEnv, extendInScopeSetList)+ lookupVarEnv, unionVarEnvWith, unitVarEnv, extendInScopeSetList, mkInScopeSet, mkVarSet) import Clash.Debug (traceIf)-import Clash.Driver.Types (BindingMap, Binding(..), DebugLevel (..))+import Clash.Driver.Types+ (BindingMap, Binding(..), TransformationInfo(FinalTerm), hasTransformationInfo)+import Clash.Normalize.Primitives (removedArg) import {-# SOURCE #-} Clash.Normalize.Strategy (normalization) import Clash.Normalize.Types import Clash.Primitives.Util (constantArgs) import Clash.Rewrite.Types- (RewriteMonad, TransformContext(..), bindings, curFun, dbgLevel, extra,- tcCache)+ (RewriteMonad, TransformContext(..), bindings, curFun, debugOpts, extra,+ tcCache, primitives) import Clash.Rewrite.Util- (runRewrite, specialise, mkTmBinderFor, mkDerivedName)+ (runRewrite, mkTmBinderFor, mkDerivedName) import Clash.Unique import Clash.Util (SrcSpan, makeCachedU) @@ -105,7 +106,7 @@ case Map.lookup nm argMap of Nothing -> do -- Constant args not yet calculated, or primitive does not exist- prims <- Lens.use (extra.primitives)+ prims <- Lens.view primitives case extractPrim =<< HashMapS.lookup nm prims of Nothing -> -- Primitive does not exist:@@ -156,16 +157,6 @@ (unitVarEnv f 1) (\_ hm -> extendVarEnvWith f 1 (+) hm) --- | Specialize under the Normalization Monad-specializeNorm :: NormRewrite-specializeNorm = specialise specialisationCache specialisationHistory specialisationLimit---- | Determine if a term is closed-isClosed :: TyConMap- -> Term- -> Bool-isClosed tcm = not . isPolyFun tcm- -- | Test whether a given term represents a non-recursive global variable isNonRecursiveGlobalVar :: Term@@ -306,10 +297,10 @@ -- -- I believe we can remove this special case in the future by looking at the -- primitive's workinfo.- if isClockOrReset tcm (termType tcm e) then+ if isClockOrReset tcm (inferCoreTypeOf tcm e) then case collectArgs e of (Prim p, _)- | primName p == "Clash.Transformations.removedArg" ->+ | primName p == Text.showt 'removedArg -> pure (constantCsr e) _ -> bindCsr ctx e else@@ -326,7 +317,7 @@ bindCsr ctx e (Lam _ _, _, _ticks) ->- if hasLocalFreeVars e then+ if not (isClosed e) then bindCsr ctx e else pure (constantCsr e)@@ -417,7 +408,7 @@ -> Id -> Binding Term -> NormalizeSession (Binding Term)-normalizeTopLvlBndr isTop nm (Binding nm' sp inl pr tm) = makeCachedU nm (extra.normalized) $ do+normalizeTopLvlBndr isTop nm (Binding nm' sp inl pr tm _) = makeCachedU nm (extra.normalized) $ do tcm <- Lens.view tcCache let nmS = showPpr (varName nm) -- We deshadow the term because sometimes GHC gives us@@ -430,8 +421,9 @@ old <- Lens.use curFun tm3 <- rewriteExpr ("normalization",normalization) (nmS,tm2) (nm',sp) curFun .= old- let ty' = termType tcm tm3- return (Binding nm'{varType = ty'} sp inl pr tm3)+ let ty' = inferCoreTypeOf tcm tm3+ let r' = nm' `globalIdOccursIn` tm3+ return (Binding nm'{varType = ty'} sp inl pr tm3 r') -- | Turn type equality constraints into substitutions and apply them. --@@ -447,30 +439,27 @@ substWithTyEq :: Term -> Term-substWithTyEq e0 = go [] False [] e0+substWithTyEq e0 = go [] False e0 where go- :: [TyVar]+ :: [Either Id TyVar] -> Bool- -> [Id] -> Term -> Term- go tvs changed ids_ (TyLam tv e) = go (tv:tvs) changed ids_ e- go tvs changed ids_ (Lam v e)- | TyConApp (nameUniq -> tcUniq) (tvFirst -> Just (tv, ty)) <- tyView (varType v)+ go args changed (TyLam tv e) = go (Right tv : args) changed e+ go args changed (Lam v e)+ | TyConApp (nameUniq -> tcUniq) (tvFirst -> Just (tv, ty)) <- tyView (coreTypeOf v) , tcUniq == getKey eqTyConKey- , tv `elem` tvs+ , Right tv `elem` args = let- subst0 = extendTvSubst (mkSubst emptyInScopeSet) tv ty- subst1 = extendIdSubst subst0 v (removedTm (varType v))- in go (tvs List.\\ [tv]) True (substId subst0 v : ids_) (substTm "substWithTyEq e" subst1 e)- | otherwise = go tvs changed (v:ids_) e- go tvs True ids_ e =- let- e1 = List.foldl' (flip TyLam) e tvs- e2 = List.foldl' (flip Lam) e1 ids_- in e2- go _ False _ _ = e0+ tvs = rights args+ subst0 = extendTvSubst (mkSubst $ mkInScopeSet $ mkVarSet tvs) tv ty+ removedTy = substTy subst0 $ coreTypeOf v+ subst1 = extendIdSubst subst0 v (TyApp (Prim removedArg) removedTy)+ in go (Left (substId subst0 v) : (args List.\\ [Right tv])) True (substTm "substWithTyEq e" subst1 e)+ | otherwise = go (Left v : args) changed e+ go args True e = mkAbstraction e (reverse args)+ go _ False _ = e0 -- Type equality (~) is symmetrical, so users could write: (dom ~ System) or (System ~ dom) tvFirst :: [Type] -> Maybe (TyVar, Type)@@ -482,25 +471,22 @@ tvSubstWithTyEq :: Type -> Type-tvSubstWithTyEq ty0 = go [] args0+tvSubstWithTyEq ty0 = go [] False ty0 where- (args0,tyRes) = splitFunForallTy ty0-- go :: [(TyVar,Type)] -> [Either TyVar Type] -> Type- go eqs (Right arg : args)+ go :: [Either TyVar Type] -> Bool -> Type -> Type+ go argsOut changed (ForAllTy tv ty)+ = go (Left tv:argsOut) changed ty+ go argsOut changed (tyView -> FunTy arg tyRes) | Just (tc,tcArgs) <- splitTyConAppM arg , nameUniq tc == getKey eqTyConKey- , Just eq <- tvFirst tcArgs- = go (eq:eqs) args- | otherwise = go eqs args- go eqs (Left _tv : args)- = go eqs args -- drop (ForAll) tv- go [] [] = ty0 -- no eq constraints, returning original type- go eqs [] = substTy subst ty2- where- subst = extendTvSubstList (mkSubst emptyInScopeSet) eqs- args2 = args0 List.\\ (map (Left . fst) eqs)- ty2 = mkPolyFunTy tyRes args2+ , Just (tv,ty) <- tvFirst tcArgs+ = let+ argsOut2 = Right arg : (argsOut List.\\ [Left tv])+ subst = extendTvSubst (mkSubst $ mkInScopeSet $ mkVarSet $ lefts argsOut2) tv ty+ in go argsOut2 True (substTy subst tyRes)+ | otherwise = go (Right arg : argsOut) changed tyRes+ go _ False _ = ty0 -- no eq constraints, returning original type+ go argsOut True tyRes = mkPolyFunTy tyRes (reverse argsOut) -- | Rewrite a term according to the provided transformation rewriteExpr :: (String,NormRewrite) -- ^ Transformation to apply@@ -509,23 +495,16 @@ -> NormalizeSession Term rewriteExpr (nrwS,nrw) (bndrS,expr) (nm, sp) = do curFun .= (nm, sp)- lvl <- Lens.view dbgLevel+ opts <- Lens.view debugOpts let before = showPpr expr- let expr' = traceIf (lvl >= DebugFinal)+ let expr' = traceIf (hasTransformationInfo FinalTerm opts) (bndrS ++ " before " ++ nrwS ++ ":\n\n" ++ before ++ "\n") expr rewritten <- runRewrite nrwS emptyInScopeSet nrw expr' let after = showPpr rewritten- traceIf (lvl >= DebugFinal)+ traceIf (hasTransformationInfo FinalTerm opts) (bndrS ++ " after " ++ nrwS ++ ":\n\n" ++ after ++ "\n") $ return rewritten--removedTm- :: Type- -> Term-removedTm =- let removedNm = "Clash.Transformations.removedArg" in- TyApp (Prim (PrimInfo removedNm undefinedTy WorkNever SingleResult)) -- | A tick to prefix an inlined expression with it's original name. -- For example, given
src/Clash/Primitives/DSL.hs view
@@ -77,7 +77,6 @@ , clog2 ) where -import Clash.Util (HasCallStack, clogBase) import Control.Lens hiding (Indexed, assign) import Control.Monad.State import Data.Default (Default(def))@@ -86,13 +85,14 @@ import Data.List (intersperse) import Data.List.Extra (zipEqual) import Data.Maybe (fromMaybe)+import Data.Monoid (Ap(getAp)) import Data.Semigroup hiding (Product)-import Data.Semigroup.Monad import Data.String import Data.Text (Text) import qualified Data.Text as Text+import Data.Text.Extra (showt) import Data.Text.Prettyprint.Doc.Extra-import TextShow (showt)+import GHC.Stack (HasCallStack) import Clash.Annotations.Primitive (HDL (..), Primitive (..)) import Clash.Backend hiding (fromBV, toBV)@@ -104,6 +104,7 @@ import qualified Clash.Netlist.Id as Id import Clash.Netlist.Types hiding (Component, toBit) import Clash.Netlist.Util+import Clash.Util (clogBase) import qualified Data.String.Interpolate as I import Data.String.Interpolate.Util (unindent) import Language.Haskell.TH (Name)@@ -223,7 +224,7 @@ BlockState decs _hoCalls backend1 = execState s initState put backend1 blockNameUnique <- Id.makeBasic blockName- getMon $ blockDecl blockNameUnique (reverse decs)+ getAp $ blockDecl blockNameUnique (reverse decs) -- | Add a declaration to the state. addDeclaration :: Declaration -> State (BlockState backend) ()
src/Clash/Primitives/GHC/Literal.hs view
@@ -20,8 +20,8 @@ import qualified Data.Text.Lazy as LT import Data.Text (Text, stripPrefix, stripSuffix, unpack)+import Data.Text.Extra (showtl) import Text.Read (readMaybe)-import TextShow (showtl) import Clash.Core.Term (Term) import Clash.Core.Type (Type)
src/Clash/Primitives/Intel/ClockGen.hs view
@@ -1,7 +1,8 @@ {-|- Copyright : (C) 2018, Google Inc.+ Copyright : (C) 2018, Google Inc.,+ 2021, QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Blackbox template functions for Clash.Intel.ClockGen.{alteraPll,altpll} -}@@ -19,13 +20,12 @@ import Clash.Netlist.Util import Control.Monad.State--import Data.Semigroup.Monad+import Data.Monoid (Ap(getAp)) import qualified Data.String.Interpolate.IsString as I import Data.Text.Prettyprint.Doc.Extra-import TextShow (showt) import qualified Data.Text as TextS+import Data.Text.Extra (showt) altpllTF :: TemplateFunction altpllTF = TemplateFunction used valid altpllTemplate@@ -88,7 +88,7 @@ let outclkPorts = map (\n -> instPort ("outclk_" <> showt n)) [(0 :: Int)..length clocks-1] - getMon $ blockDecl alteraPll $ concat+ getAp $ blockDecl alteraPll $ concat [[ NetDecl Nothing locked rstTy , NetDecl' Nothing Reg pllLock (Right Bool) Nothing] ,[ NetDecl Nothing clkNm ty | (clkNm,ty) <- zip clocks tys]@@ -127,7 +127,7 @@ -- TODO: bbQsysIncName into account when generating fresh ids let compName = Id.unsafeMake (head (bbQsysIncName bbCtx)) - getMon $ blockDecl alteraPll+ getAp $ blockDecl alteraPll [ NetDecl Nothing locked Bit , NetDecl' Nothing Reg pllLock (Right Bool) Nothing , NetDecl Nothing pllOut clkOutTy
+ src/Clash/Primitives/Sized/Signed.hs view
@@ -0,0 +1,43 @@+{-|+ Copyright : (C) 2021 QBayLogic+ License : BSD2 (see the file LICENSE)+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com>++ VHDL Blackbox implementations for "Clash.Sized.Internal.Signed.toInteger#".+-}++{-# LANGUAGE OverloadedStrings #-}+module Clash.Primitives.Sized.Signed (fromIntegerTF) where++import Control.Monad.State (State)+import Data.Monoid (Ap(getAp))+import Data.Text.Prettyprint.Doc.Extra (Doc, tupled)++import Clash.Backend (Backend, expr)+import Clash.Netlist.Types+ (BlackBoxContext (..), Expr (..), HWType (..), Literal (..), Modifier (..),+ TemplateFunction (..))++fromIntegerTF :: TemplateFunction+fromIntegerTF = TemplateFunction used valid fromIntegerTFTemplate+ where+ used = [0,1]+ valid bbCtx = case bbInputs bbCtx of+ [kn,_] -> case kn of+ (Literal _ (NumLit _),_,True) -> True+ _ -> False+ _ -> False++fromIntegerTFTemplate+ :: Backend s+ => BlackBoxContext+ -> State s Doc+fromIntegerTFTemplate bbCtx = getAp $ do+ let [(Literal _ (NumLit sz),_,_), (i@(Identifier iV m), Signed szI, _)] = bbInputs bbCtx+ case compare sz (toInteger szI) of+ LT -> let sl = Sliced (Signed szI,fromInteger sz-1,0)+ m1 = Just (maybe sl (`Nested` sl) m)+ in expr False (Identifier iV m1)+ EQ -> expr False i+ GT -> "resize" <> tupled (sequenceA [expr False i+ ,expr False (Literal Nothing (NumLit sz))])
src/Clash/Primitives/Sized/Vector.hs view
@@ -1,5 +1,5 @@ {-|- Copyright : (C) 2020 QBayLogic+ Copyright : (C) 2020-2021 QBayLogic License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> @@ -19,7 +19,8 @@ import qualified Data.IntMap as IntMap import Data.List.Extra (iterateNM) import Data.Maybe (fromMaybe)-import Data.Semigroup.Monad (getMon)+import Data.Monoid (Ap(getAp))+import Data.Text.Extra (showt) import Data.Text.Lazy (pack) import Data.Text.Prettyprint.Doc.Extra (Doc, string, renderLazy, layoutPretty, LayoutOptions(..),@@ -27,7 +28,7 @@ import Text.Trifecta.Result (Result(Success)) import qualified Data.String.Interpolate as I import qualified Data.String.Interpolate.Util as I-import TextShow (showt)+import GHC.Stack (HasCallStack) import Clash.Backend (Backend, hdlTypeErrValue, expr, blockDecl)@@ -42,9 +43,9 @@ Element(Component, Typ, TypElem, Text), Decl(Decl), emptyBlackBoxMeta) import Clash.Netlist.Types (Identifier, TemplateFunction, BlackBoxContext, HWType(Vector),- Declaration(..), Expr(BlackBoxE, Literal, Identifier), Literal(NumLit),+ Declaration(..), Expr(Literal, Identifier,DataCon), Literal(NumLit), BlackBox(BBTemplate, BBFunction), TemplateFunction(..), WireOrReg(Wire),- Modifier(Indexed, Nested), bbInputs, bbResults, emptyBBContext, tcCache,+ Modifier(Indexed, Nested, DC), HWType(..), bbInputs, bbResults, emptyBBContext, tcCache, bbFunctions) import qualified Clash.Netlist.Id as Id import Clash.Netlist.Util (typeSize)@@ -52,7 +53,7 @@ import Clash.Primitives.DSL (declarationReturn, instHO, tInputs, tExprToInteger) -import Clash.Util (HasCallStack, curLoc)+import Clash.Util (curLoc) -- | Blackbox function for 'Clash.Sized.Vector.iterateI' iterateBBF :: HasCallStack => BlackBoxFunction@@ -164,7 +165,7 @@ callDecls <- zipWithM callDecl [0..] fCalls foldNm <- Id.make "fold" - getMon $ blockDecl foldNm $+ getAp $ blockDecl foldNm $ resultAssign : vecAssign : vecDecl :@@ -286,7 +287,7 @@ :: Backend s => BlackBoxContext -> State s Doc-indexIntVerilogTemplate bbCtx = getMon $ case typeSize vTy of+indexIntVerilogTemplate bbCtx = getAp $ case typeSize vTy of 0 -> hdlTypeErrValue rTy _ -> case vec of Identifier i mM -> case mM of@@ -306,8 +307,8 @@ ixI ix0 = case ix0 of Literal _ (NumLit i) -> fromInteger i- BlackBoxE "GHC.Types.I#" _ _ _ _ ixCtx _ ->- let (ix1,_,_) = head (bbInputs ixCtx)- in ixI ix1+ DataCon (Signed _) (DC (Void{},_)) [Literal (Just (Signed _,_)) (NumLit i)] ->+ fromInteger i _ -> error ($(curLoc) ++ "Unexpected literal: " ++ show ix)+
src/Clash/Primitives/Types.hs view
@@ -12,7 +12,6 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE LambdaCase #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} @@ -52,6 +51,7 @@ import Data.Text.Lazy (Text) import GHC.Generics (Generic) import GHC.Stack (HasCallStack)+import Text.Read (readMaybe) #if MIN_VERSION_aeson(2,0,0) import qualified Data.Aeson.KeyMap as KeyMap@@ -306,7 +306,13 @@ parseWorkInfo (String "Never") = pure (Just WorkNever) parseWorkInfo (String "Variable") = pure (Just WorkVariable) parseWorkInfo (String "Always") = pure (Just WorkAlways)+ parseWorkInfo (parseWorkIdentity -> wi@Just{}) = pure wi parseWorkInfo c = fail ("[6] unexpected workInfo: " ++ show c)++ parseWorkIdentity arg = do+ String str <- return arg+ [iStr,xsStr] <- words . S.unpack <$> S.stripPrefix "Identity" str+ WorkIdentity <$> readMaybe iStr <*> readMaybe xsStr parseBBFN' = either fail return . parseBBFN
src/Clash/Primitives/Util.hs view
@@ -10,6 +10,7 @@ -} {-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE MultiWayIf #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} @@ -17,12 +18,14 @@ ( generatePrimMap , hashCompiledPrimMap , constantArgs- , decodeOrErr+ , decodeOrErrJson+ , decodeOrErrYaml , getFunctionPlurality ) where import Control.DeepSeq (force)-import Data.Aeson.Extra (decodeOrErr)+import Control.Monad (forM)+import Data.Aeson.Extra (decodeOrErrJson, decodeOrErrYaml) import qualified Data.ByteString.Lazy as LZ import qualified Data.HashMap.Lazy as HashMap import qualified Data.HashMap.Strict as HashMapStrict@@ -115,8 +118,13 @@ => FilePath -> IO [(TS.Text, GuardedResolvedPrimitive)] resolvePrimitive fileName = do- prims <- decodeOrErr fileName <$> LZ.readFile fileName+ prims <- decoder fileName <$> LZ.readFile fileName mapM (resolvePrimitive' fileName) prims+ where+ decoder+ | ".primitives.yaml" `isSuffixOf` fileName = decodeOrErrYaml+ | ".primitives" `isSuffixOf` fileName = decodeOrErrJson+ | otherwise = error ("Unexpected filename extension in: " <> fileName) addGuards :: ResolvedPrimMap@@ -161,17 +169,18 @@ -- ^ Directories to search for primitive definitions -> IO ResolvedPrimMap generatePrimMap unresolvedPrims primGuards filePaths = do- primitiveFiles <- fmap concat $ mapM- (\filePath -> do- fpExists <- Directory.doesDirectoryExist filePath- if fpExists- then- fmap ( map (FilePath.combine filePath)- . filter (isSuffixOf ".primitives")- ) (Directory.getDirectoryContents filePath)- else- return []- ) filePaths+ primitiveFiles <- fmap concat $ forM filePaths $ \filePath -> do+ fpExists <- Directory.doesDirectoryExist filePath+ if fpExists then do+ contents <- Directory.getDirectoryContents filePath+ let+ jsonPrims = filter (".primitives" `isSuffixOf`) contents+ yamlPrims = filter (".primitives.yaml" `isSuffixOf`) contents+ relPrims = jsonPrims <> yamlPrims+ absPrims = map (FilePath.combine filePath) relPrims+ return absPrims+ else+ return [] primitives0 <- concat <$> mapM resolvePrimitive primitiveFiles let metapaths = map (TS.unpack . name) unresolvedPrims
src/Clash/Primitives/Verification.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE OverloadedStrings #-} module Clash.Primitives.Verification (checkBBF) where@@ -8,33 +7,32 @@ import qualified Control.Lens as Lens import Control.Monad.State (State)+import Data.Monoid (Ap(getAp)) import Data.Text.Prettyprint.Doc.Extra (Doc) import qualified Data.Text as Text-import Data.Semigroup.Monad (getMon) import GHC.Stack (HasCallStack) import Clash.Annotations.Primitive (HDL(..)) import Clash.Backend (Backend, blockDecl, hdlKind)-import Clash.Core.Term (Term(Var))-import Clash.Core.TermInfo (termType)+import Clash.Core.HasType+import Clash.Core.Term (Term(Var), varToId) import Clash.Core.TermLiteral (termToDataError) import Clash.Util (indexNote) import Clash.Netlist (mkExpr)-import Clash.Netlist.Util (stripVoid)-import Clash.Netlist.Util (id2identifier)+import Clash.Netlist.Util (stripVoid, id2identifier) import qualified Clash.Netlist.Id as Id import Clash.Netlist.Types (BlackBox(BBFunction), TemplateFunction(..), BlackBoxContext, Identifier,- NetlistMonad, Declaration(Assignment, NetDecl', TickDecl),+ NetlistMonad, Declaration(Assignment, NetDecl'), HWType(Bool, KnownDomain), WireOrReg(Wire), NetlistId(..),- DeclarationType(Concurrent), tcCache, bbInputs)+ DeclarationType(Concurrent), tcCache, bbInputs, Expr(Identifier)) import Clash.Netlist.BlackBox.Types (BlackBoxFunction, BlackBoxMeta(..), TemplateKind(TDecl), RenderVoid(..), emptyBlackBoxMeta) import Clash.Verification.Internal-import Clash.Verification.PrettyPrinters+import Clash.Verification.Pretty checkBBF :: BlackBoxFunction checkBBF _isD _primName args _ty =@@ -44,12 +42,14 @@ cvProperty1 <- mapM (uncurry bindMaybe) cvProperty0 let decls = concatMap snd cvProperty1 cvProperty2 = fmap fst cvProperty1- pure (Right (meta, bb (checkTF decls clkId propName renderAs cvProperty2)))+ pure (Right (meta, bb (checkTF decls (clkExpr, clkId) propName renderAs cvProperty2))) where -- TODO: Improve error handling; currently errors don't indicate what -- TODO: blackbox generated them.- (Var (id2identifier -> clkId)) = indexNote "clk" (lefts args) 1- (Var (id2identifier -> _clkId)) = indexNote "rst" (lefts args) 2+ clk = indexNote "clk" (lefts args) 1+ clkExpr = Identifier clkId Nothing+ (id2identifier -> clkId) = varToId clk+ (id2identifier -> _clkId) = varToId (indexNote "rst" (lefts args) 2) litArgs = do propName <- termToDataError (indexNote "propName" (lefts args) 3)@@ -72,7 +72,7 @@ bindMaybe (Just nm) t = do tcm <- Lens.use tcCache newId <- Id.make (Text.pack nm)- (expr0, decls) <- mkExpr False Concurrent (NetlistId newId (termType tcm t)) t+ (expr0, decls) <- mkExpr False Concurrent (NetlistId newId (inferCoreTypeOf tcm t)) t pure ( newId , decls ++ [sigDecl Bool newId, Assignment newId expr0] )@@ -83,20 +83,20 @@ checkTF :: [Declaration]- -> Identifier+ -> (Expr, Identifier) -> Text.Text -> RenderAs -> Property' Identifier -> TemplateFunction-checkTF decls clkId propName renderAs prop =- TemplateFunction [] (const True) (checkTF' decls clkId propName renderAs prop)+checkTF decls clk propName renderAs prop =+ TemplateFunction [] (const True) (checkTF' decls clk propName renderAs prop) checkTF' :: forall s . (HasCallStack, Backend s) => [Declaration] -- ^ Extra decls needed- -> Identifier+ -> (Expr, Identifier) -- ^ Clock -> Text.Text -- ^ Prop name@@ -104,9 +104,9 @@ -> Property' Identifier -> BlackBoxContext -> State s Doc-checkTF' decls clkId propName renderAs prop bbCtx = do+checkTF' decls (clk, clkId) propName renderAs prop bbCtx = do blockName <- Id.makeBasic (propName <> "_block")- getMon (blockDecl blockName (TickDecl renderedPslProperty : decls))+ getAp (blockDecl blockName (renderedPslProperty : decls)) where hdl = hdlKind (undefined :: s)@@ -116,9 +116,17 @@ (_, stripVoid -> KnownDomain _nm _period e _rst _init _polarity, _) -> e _ -> error $ "Unexpected first argument: " ++ show (head (bbInputs bbCtx)) - renderedPslProperty- | renderAs == SVA || hdl == SystemVerilog = sva- | otherwise = psl+ renderedPslProperty = case renderAs of+ PSL -> psl+ SVA -> sva+ AutoRenderAs -> case hdl of+ SystemVerilog -> sva+ _ -> psl+ YosysFormal -> case hdl of+ VHDL -> psl+ _ -> ysva+ where sva = pprSvaProperty propName (Id.toText clkId) edge (fmap Id.toText prop)+ ysva = pprYosysSvaProperty propName clk edge (fmap Id.toText prop) psl = pprPslProperty hdl propName (Id.toText clkId) edge (fmap Id.toText prop)
src/Clash/Rewrite/Combinators.hs view
@@ -1,7 +1,8 @@ {-| Copyright : (C) 2012-2016, University of Twente+ 2021, QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Rewriting combinators and traversals -}@@ -15,11 +16,7 @@ , bottomupR , repeatR , topdownR-- , whenR- , bottomupWhenR- )- where+ ) where import Control.DeepSeq (deepseq) import Control.Monad ((>=>))@@ -149,25 +146,3 @@ repeatR :: Rewrite m -> Rewrite m repeatR = let go r = r !-> repeatR r in go {-# INLINE repeatR #-}--whenR :: Monad m- => (TransformContext -> Term -> m Bool)- -> Transform m- -> Transform m-whenR f r1 ctx expr = do- b <- f ctx expr- if b- then r1 ctx expr- else return expr---- | Only traverse downwards when the assertion evaluates to true-bottomupWhenR- :: Monad m- => (TransformContext -> Term -> m Bool)- -> Transform m- -> Transform m-bottomupWhenR f r ctx expr = do- b <- f ctx expr- if b- then (allR (bottomupWhenR f r) >-> r) ctx expr- else r ctx expr
src/Clash/Rewrite/Types.hs view
@@ -1,15 +1,17 @@ {-| Copyright : (C) 2012-2016, University of Twente, 2016 , Myrtle Software Ltd,- 2017 , Google Inc.+ 2017 , Google Inc.,+ 2021-2022, QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Type and instance definitions for Rewrite modules -} {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-}@@ -21,34 +23,37 @@ import Control.Concurrent.Supply (Supply, freshId) import Control.DeepSeq (NFData) import Control.Lens (Lens', use, (.=))-#if !MIN_VERSION_base(4,13,0)-import Control.Monad.Fail (MonadFail(fail))-#endif-import Control.Monad.Fix (MonadFix (..), fix)+import qualified Control.Lens as Lens+import Control.Monad.Fix (MonadFix)+import Control.Monad.State.Strict (State)+#if MIN_VERSION_transformers(0,5,6) import Control.Monad.Reader (MonadReader (..)) import Control.Monad.State (MonadState (..))-import Control.Monad.State.Strict (State)+import Control.Monad.Trans.RWS.CPS (RWST)+import qualified Control.Monad.Trans.RWS.CPS as RWS import Control.Monad.Writer (MonadWriter (..))+#else+import Control.Monad.Trans.RWS.Strict (RWST)+import qualified Control.Monad.Trans.RWS.Strict as RWS+#endif import Data.Binary (Binary)+import Data.HashMap.Strict (HashMap) import Data.IntMap.Strict (IntMap) import Data.Monoid (Any)-import qualified Data.Set as Set+import Data.Text (Text) import GHC.Generics -#if EXPERIMENTAL_EVALUATOR-import Clash.Core.PartialEval (Evaluator)-import Clash.Core.PartialEval.NormalForm (Value)-#else-import Clash.Core.Evaluator.Types (Evaluator, PrimHeap)-#endif+import Clash.Core.PartialEval as PE (Evaluator)+import Clash.Core.Evaluator.Types as WHNF (Evaluator, PrimHeap) import Clash.Core.Term (Term, Context) import Clash.Core.Type (Type)-import Clash.Core.TyCon (TyConName, TyConMap)+import Clash.Core.TyCon (TyConMap, TyConName) import Clash.Core.Var (Id) import Clash.Core.VarEnv (InScopeSet, VarSet, VarEnv)-import Clash.Driver.Types (BindingMap, DebugLevel)+import Clash.Driver.Types (ClashEnv(..), ClashOpts(..), BindingMap, DebugOpts) import Clash.Netlist.Types (FilteredHWType, HWMap)+import Clash.Primitives.Types (CompiledPrimMap) import Clash.Rewrite.WorkFree (isWorkFree) import Clash.Util @@ -72,8 +77,12 @@ -- | State of a rewriting session data RewriteState extra = RewriteState- { _transformCounter :: {-# UNPACK #-} !Int- -- ^ Number of applied transformations+ -- TODO Given we now keep transformCounters, this should just be 'fold'+ -- over that map, otherwise the two counts could fall out of sync.+ { _transformCounter :: {-# UNPACK #-} !Word+ -- ^ Total number of applied transformations+ , _transformCounters :: HashMap Text Word+ -- ^ Map that tracks how many times each transformation is applied , _bindings :: !BindingMap -- ^ Global binders , _uniqSupply :: !Supply@@ -82,140 +91,139 @@ -- ^ Function which is currently normalized , _nameCounter :: {-# UNPACK #-} !Int -- ^ Used for 'Fresh'-#if EXPERIMENTAL_EVALUATOR- , _ioHeap :: IntMap Value- -- ^ Used as a heap for compile-time evaluation of primitives that live in I/O- , _ioAddr :: Int- -- ^ Next address to use for heap insertion.-#else , _globalHeap :: PrimHeap -- ^ Used as a heap for compile-time evaluation of primitives that live in I/O-#endif , _workFreeBinders :: VarEnv Bool -- ^ Map telling whether a binder's definition is work-free , _extra :: !extra -- ^ Additional state } -makeLenses ''RewriteState+Lens.makeLenses ''RewriteState -- | Read-only environment of a rewriting session data RewriteEnv = RewriteEnv- { _dbgLevel :: DebugLevel- -- ^ Level at which we print debugging messages- , _dbgTransformations :: Set.Set String- -- ^ See ClashOpts.dbgTransformations- , _dbgTransformationsFrom :: Int- -- ^ See ClashOpts.opt_dbgTransformationsFrom- , _dbgTransformationsLimit :: Int- -- ^ See ClashOpts.opt_dbgTransformationsLimit- , _dbgRewriteHistoryFile :: Maybe FilePath- -- ^ See ClashOpts.opt_dbgRewriteHistory- , _aggressiveXOpt :: Bool- -- ^ Transformations to print debugging info for+ { _clashEnv :: ClashEnv+ -- ^ The global environment of the compiler , _typeTranslator :: CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType)) -- ^ Hardcode Type -> FilteredHWType translator- , _tcCache :: TyConMap- -- ^ TyCon cache- , _tupleTcCache :: IntMap TyConName- -- ^ Tuple TyCon cache- , _evaluator :: Evaluator+ , _peEvaluator :: PE.Evaluator -- ^ Hardcoded evaluator for partial evaluation+ , _evaluator :: WHNF.Evaluator+ -- ^ Hardcoded evaluator for WHNF (old evaluator) , _topEntities :: VarSet -- ^ Functions that are considered TopEntities- , _customReprs :: CustomReprs- -- ^ Custom bit representations- , _fuelLimit :: Word- -- ^ Maximum amount of fuel for the evaluator } -makeLenses ''RewriteEnv+Lens.makeLenses ''RewriteEnv +debugOpts :: Lens.Getter RewriteEnv DebugOpts+debugOpts = clashEnv . Lens.to (opt_debug . envOpts)++aggressiveXOpt :: Lens.Getter RewriteEnv Bool+aggressiveXOpt = clashEnv . Lens.to (opt_aggressiveXOpt . envOpts)++tcCache :: Lens.Getter RewriteEnv TyConMap+tcCache = clashEnv . Lens.to envTyConMap++tupleTcCache :: Lens.Getter RewriteEnv (IntMap TyConName)+tupleTcCache = clashEnv . Lens.to envTupleTyCons++customReprs :: Lens.Getter RewriteEnv CustomReprs+customReprs = clashEnv . Lens.to envCustomReprs++fuelLimit :: Lens.Getter RewriteEnv Word+fuelLimit = clashEnv . Lens.to (opt_evaluatorFuelLimit . envOpts)++primitives :: Lens.Getter RewriteEnv CompiledPrimMap+primitives = clashEnv . Lens.to envPrimitives++inlineLimit :: Lens.Getter RewriteEnv Int+inlineLimit = clashEnv . Lens.to (opt_inlineLimit . envOpts)++inlineFunctionLimit :: Lens.Getter RewriteEnv Word+inlineFunctionLimit = clashEnv . Lens.to (opt_inlineFunctionLimit . envOpts)++inlineConstantLimit :: Lens.Getter RewriteEnv Word+inlineConstantLimit = clashEnv . Lens.to (opt_inlineConstantLimit . envOpts)++inlineWFCacheLimit :: Lens.Getter RewriteEnv Word+inlineWFCacheLimit = clashEnv . Lens.to (opt_inlineWFCacheLimit . envOpts)++newInlineStrategy :: Lens.Getter RewriteEnv Bool+newInlineStrategy = clashEnv . Lens.to (opt_newInlineStrat . envOpts)++specializationLimit :: Lens.Getter RewriteEnv Int+specializationLimit = clashEnv . Lens.to (opt_specLimit . envOpts)++normalizeUltra :: Lens.Getter RewriteEnv Bool+normalizeUltra = clashEnv . Lens.to (opt_ultra . envOpts)+ -- | Monad that keeps track how many transformations have been applied and can -- generate fresh variables and unique identifiers. In addition, it keeps track -- if a transformation/rewrite has been successfully applied. newtype RewriteMonad extra a = R- { unR :: RewriteEnv -> RewriteState extra -> Any -> (a,RewriteState extra,Any) }+ { unR :: RWST RewriteEnv Any (RewriteState extra) IO a }+ deriving newtype+ ( Applicative+ , Functor+ , Monad+ , MonadFix+ ) -- | Run the computation in the RewriteMonad runR :: RewriteMonad extra a -> RewriteEnv -> RewriteState extra- -> (a, RewriteState extra, Any)-runR m r s = unR m r s mempty--instance MonadFail (RewriteMonad extra) where- fail err = error ("RewriteMonad.fail: " ++ err)--instance Functor (RewriteMonad extra) where- fmap f m = R $ \ r s w -> case unR m r s w of (a, s', w') -> (f a, s', w')- {-# INLINE fmap #-}--instance Applicative (RewriteMonad extra) where- pure a = R $ \ _ s w -> (a, s, w)- {-# INLINE pure #-}- R mf <*> R mx = R $ \ r s w -> case mf r s w of- (f,s',w') -> case mx r s' w' of- (x,s'',w'') -> (f x, s'', w'')- {-# INLINE (<*>) #-}--instance Monad (RewriteMonad extra) where- return a = R $ \ _ s w -> (a, s, w)- {-# INLINE return #-}- m >>= k =- R $ \ r s w -> case unR m r s w of- (a,s',w') -> unR (k a) r s' w'- {-# INLINE (>>=) #-}+ -> IO (a, RewriteState extra, Any)+runR m = RWS.runRWST (unR m) +#if MIN_VERSION_transformers(0,5,6) && !MIN_VERSION_mtl(2,3,0)+-- For Control.Monad.Trans.RWS.Strict these are already defined, however the+-- CPS version of RWS is not included in `mtl` yet. instance MonadState (RewriteState extra) (RewriteMonad extra) where- get = R $ \_ s w -> (s,s,w)+ get = R RWS.get {-# INLINE get #-}- put s = R $ \_ _ w -> ((),s,w)+ put = R . RWS.put {-# INLINE put #-}- state f = R $ \_ s w -> case f s of (a,s') -> (a,s',w)+ state = R . RWS.state {-# INLINE state #-} -instance MonadUnique (RewriteMonad extra) where- getUniqueM = do- sup <- use uniqSupply- let (a,sup') = freshId sup- uniqSupply .= sup'- a `seq` return a- instance MonadWriter Any (RewriteMonad extra) where- writer (a,w') = R $ \_ s w -> let wt = w `mappend` w' in wt `seq` (a,s,wt)+ writer = R . RWS.writer {-# INLINE writer #-}- tell w' = R $ \_ s w -> let wt = w `mappend` w' in wt `seq` ((),s,wt)+ tell = R . RWS.tell {-# INLINE tell #-}- listen m = R $ \r s w -> case runR m r s of- (a,s',w') -> let wt = w `mappend` w' in wt `seq` ((a,w'),s',wt)+ listen = R . RWS.listen . unR {-# INLINE listen #-}- pass m = R $ \r s w -> case runR m r s of- ((a,f),s',w') -> let wt = w `mappend` f w' in wt `seq` (a, s', wt)+ pass = R . RWS.pass . unR {-# INLINE pass #-} -censor :: (Any -> Any) -> RewriteMonad extra a -> RewriteMonad extra a-censor f m = R $ \r s w -> case runR m r s of- (a,s',w') -> let wt = w `mappend` f w' in wt `seq` (a, s', wt)-{-# INLINE censor #-}- instance MonadReader RewriteEnv (RewriteMonad extra) where- ask = R $ \r s w -> (r,s,w)+ ask = R RWS.ask {-# INLINE ask #-}- local f m = R $ \r s w -> unR m (f r) s w+ local f = R . RWS.local f . unR {-# INLINE local #-}- reader f = R $ \r s w -> (f r,s,w)+ reader = R . RWS.reader {-# INLINE reader #-}+#endif -instance MonadFix (RewriteMonad extra) where- mfix f = R $ \r s w -> fix $ \ ~(a,_,_) -> unR (f a) r s w- {-# INLINE mfix #-}+instance MonadUnique (RewriteMonad extra) where+ getUniqueM = do+ sup <- use uniqSupply+ let (a,sup') = freshId sup+ uniqSupply .= sup'+ a `seq` return a++censor :: (Any -> Any) -> RewriteMonad extra a -> RewriteMonad extra a+censor f = R . RWS.censor f . unR+{-# INLINE censor #-} data TransformContext = TransformContext
src/Clash/Rewrite/Util.hs view
@@ -1,9 +1,10 @@ {-| Copyright : (C) 2012-2016, University of Twente, 2016 , Myrtle Software Ltd,- 2017 , Google Inc.+ 2017 , Google Inc.,+ 2021-2022, QBayLogic B.V. License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com> Utilities for rewriting: e.g. inlining, specialisation, etc. -}@@ -26,35 +27,31 @@ import Control.Concurrent.Supply (splitSupply) import Control.DeepSeq import Control.Exception (throw)-import Control.Lens- (Lens', (%=), (+=), (^.), _Left)+import Control.Lens ((%=), (+=), (^.)) import qualified Control.Lens as Lens import qualified Control.Monad as Monad-#if !MIN_VERSION_base(4,13,0)-import Control.Monad.Fail (MonadFail)-#endif import qualified Control.Monad.State.Strict as State+#if MIN_VERSION_transformers(0,5,6)+import qualified Control.Monad.Trans.RWS.CPS as RWS+#else+import qualified Control.Monad.Trans.RWS.Strict as RWS+#endif import qualified Control.Monad.Writer as Writer-import Data.Bool (bool)-import Data.Bifunctor (bimap)+import Data.Bifunctor (second) import Data.Coerce (coerce) import Data.Functor.Const (Const (..))-import Data.List (group, partition, sort)+import qualified Data.HashMap.Strict as HashMap+import Data.List (group, partition, sort, sortOn) import qualified Data.List as List import qualified Data.List.Extra as List import Data.List.Extra (partitionM)-import qualified Data.Map as Map import Data.Maybe import qualified Data.Monoid as Monoid import qualified Data.Set as Set import qualified Data.Set.Lens as Lens-import qualified Data.Set.Ordered as OSet-import qualified Data.Set.Ordered.Extra as OSet import Data.Text (Text) import qualified Data.Text as Text- import System.IO.Unsafe (unsafePerformIO)- import Data.Binary (encode) import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as BL@@ -65,46 +62,42 @@ import BasicTypes (InlineSpec (..)) #endif -#if EXPERIMENTAL_EVALUATOR-import Clash.Core.PartialEval-import Clash.Core.PartialEval.NormalForm-#else import Clash.Core.Evaluator.Types (PureHeap, whnf')-#endif- import Clash.Core.FreeVars- (freeLocalVars, localIdDoesNotOccurIn, localIdOccursIn,- typeFreeVars, termFreeVars', freeLocalIds)+ (freeLocalVars, termFreeVars', freeLocalIds, globalIdOccursIn)+import Clash.Core.HasFreeVars (elemFreeVars, notElemFreeVars)+import Clash.Core.HasType import Clash.Core.Name import Clash.Core.Pretty (showPpr) import Clash.Core.Subst (substTmEnv, aeqTerm, aeqType, extendIdSubst, mkSubst, substTm, eqTerm) import Clash.Core.Term-import Clash.Core.TermInfo import Clash.Core.TyCon (TyConMap)-import Clash.Core.Type (Type (..), normalizeType, typeKind)+import Clash.Core.Type (Type (..), normalizeType) import Clash.Core.Var (Id, IdScope (..), TyVar, Var (..), mkGlobalId, mkLocalId, mkTyVar) import Clash.Core.VarEnv- (InScopeSet, VarEnv, elemVarSet, extendInScopeSetList, mkInScopeSet,+ (InScopeSet, extendInScopeSet, extendInScopeSetList, mkInScopeSet, uniqAway, uniqAway', mapVarEnv, eltsVarEnv, unitVarSet, emptyVarEnv,- mkVarEnv, eltsVarSet, elemVarEnv, lookupVarEnv, extendVarEnv)+ mkVarEnv, eltsVarSet, elemVarEnv, lookupVarEnv, extendVarEnv, elemVarSet) import Clash.Debug import Clash.Driver.Types- (DebugLevel (..), BindingMap, Binding(..), IsPrim(..))+ (TransformationInfo(..), DebugOpts(..), BindingMap, Binding(..), IsPrim(..),+ ClashEnv(..), ClashOpts(..), hasDebugInfo, isDebugging) import Clash.Netlist.Util (representableType) import Clash.Pretty (clashPretty, showDoc) import Clash.Rewrite.Types import Clash.Rewrite.WorkFree import Clash.Unique import Clash.Util+import Clash.Util.Eq (fastEqBy) import qualified Clash.Util.Interpolate as I -- | Lift an action working in the '_extra' state to the 'RewriteMonad'-zoomExtra :: State.State extra a- -> RewriteMonad extra a-zoomExtra m = R (\_ s w -> case State.runState m (s ^. extra) of- (a,s') -> (a,s {_extra = s'},w))+zoomExtra :: State.State extra a -> RewriteMonad extra a+zoomExtra m = R . RWS.rwsT $ \_ s ->+ let (a, st') = State.runState m (_extra s)+ in pure (a, s { _extra = st' }, mempty) -- | Some transformations might erroneously introduce shadowing. For example, -- a transformation might result in:@@ -132,8 +125,8 @@ Case t _ as -> concatMap (findInPat . fst) as ++ concatMap findAccidentialShadows (t : map snd as)- Letrec bs t ->- findDups (map fst bs) ++ findAccidentialShadows t+ Let NonRec{} t -> findAccidentialShadows t+ Let (Rec bs) t -> findDups (map fst bs) ++ findAccidentialShadows t where findInPat :: Pat -> [[Id]]@@ -153,19 +146,15 @@ -- ^ Transformation to be applied -> Rewrite extra apply = \s rewrite ctx expr0 -> do- lvl <- Lens.view dbgLevel- dbgTranss <- Lens.view dbgTransformations- let isTryLvl = lvl == DebugTry || lvl >= DebugAll- isRelevantTrans = s `Set.member` dbgTranss || Set.null dbgTranss- traceIf (isTryLvl && isRelevantTrans) ("Trying: " ++ s) (pure ())+ opts <- Lens.view debugOpts+ traceIf (hasDebugInfo TryName s opts) ("Trying: " <> s) (pure ()) - (expr1,anyChanged) <- Writer.listen (rewrite ctx expr0)+ (!expr1,anyChanged) <- Writer.listen (rewrite ctx expr0) let hasChanged = Monoid.getAny anyChanged- !expr2 = if hasChanged then expr1 else expr0 Monad.when hasChanged (transformCounter += 1) -- NB: When -fclash-debug-history is on, emit binary data holding the recorded rewrite steps- rewriteHistFile <- Lens.view dbgRewriteHistoryFile+ let rewriteHistFile = dbg_historyFile opts Monad.when (isJust rewriteHistFile && hasChanged) $ do (curBndr, _) <- Lens.use curFun let !_ = unsafePerformIO@@ -180,28 +169,13 @@ } return () - dbgFrom <- Lens.view dbgTransformationsFrom- dbgLimit <- Lens.view dbgTransformationsLimit- let fromLimit =- if (dbgFrom, dbgLimit) == (0, maxBound)- then Nothing- else Just (dbgFrom, dbgLimit)-- if lvl == DebugNone- then return expr2- else applyDebug lvl dbgTranss fromLimit s expr0 hasChanged expr2+ if isDebugging opts+ then applyDebug s expr0 hasChanged expr1+ else return expr1 {-# INLINE apply #-} applyDebug- :: DebugLevel- -- ^ The current debugging level- -> Set.Set String- -- ^ Transformations to debug- -> Maybe (Int, Int)- -- ^ Only print debug information for transformations [n, n+limit]. See flag- -- documentation of "-fclash-debug-transformations-from" and- -- "-fclash-debug-transformations-limit"- -> String+ :: String -- ^ Name of the transformation -> Term -- ^ Original expression@@ -210,79 +184,85 @@ -> Term -- ^ New expression -> RewriteMonad extra Term-applyDebug lvl transformations fromLimit name exprOld hasChanged exprNew- | Just (from, limit) <- fromLimit = do- nTrans <- Lens.use transformCounter- if | nTrans - from > limit ->- error "-fclash-debug-transformations-limit exceeded"- | nTrans > from ->- applyDebug lvl transformations Nothing name exprOld hasChanged exprNew- | otherwise ->- pure exprNew+applyDebug name exprOld hasChanged exprNew = do+ nTrans <- Lens.use transformCounter+ opts <- Lens.view debugOpts -applyDebug lvl transformations fromLimit name exprOld hasChanged exprNew- | not (Set.null transformations) =- let newLvl = bool DebugNone lvl (name `Set.member` transformations) in- applyDebug newLvl Set.empty fromLimit name exprOld hasChanged exprNew+ let from = fromMaybe 0 (dbg_transformationsFrom opts)+ let limit = fromMaybe maxBound (dbg_transformationsLimit opts) -applyDebug lvl _transformations _fromLimit name exprOld hasChanged exprNew =- traceIf (lvl >= DebugAll) ("Tried: " ++ name ++ " on:\n" ++ before) $ do- nTrans <- pred <$> Lens.use transformCounter- Monad.when (lvl > DebugNone && hasChanged) $ do- tcm <- Lens.view tcCache- let beforeTy = termType tcm exprOld- beforeFV = Lens.setOf freeLocalVars exprOld- afterTy = termType tcm exprNew- afterFV = Lens.setOf freeLocalVars exprNew- newFV = not (afterFV `Set.isSubsetOf` beforeFV)- accidentalShadows = findAccidentialShadows exprNew+ if | nTrans - from > limit ->+ error "-fclash-debug-transformations-limit exceeded"+ | nTrans <= from ->+ pure exprNew+ | otherwise ->+ go opts+ where+ go opts = traceIf (hasDebugInfo TryTerm name opts) ("Tried: " ++ name ++ " on:\n" ++ before) $ do+ nTrans <- pred <$> Lens.use transformCounter - Monad.when newFV $- error ( concat [ $(curLoc)- , "Error when applying rewrite ", name- , " to:\n" , before- , "\nResult:\n" ++ after ++ "\n"- , "It introduces free variables."- , "\nBefore: " ++ showPpr (Set.toList beforeFV)- , "\nAfter: " ++ showPpr (Set.toList afterFV)- ]- )- Monad.when (not (null accidentalShadows)) $- error ( concat [ $(curLoc)- , "Error when applying rewrite ", name- , " to:\n" , before- , "\nResult:\n" ++ after ++ "\n"- , "It accidentally creates shadowing let/case-bindings:\n"- , " ", showPpr accidentalShadows, "\n"- , "This usually means that a transformation did not extend "- , "or incorrectly extended its InScopeSet before applying a "- , "substitution."- ])+ Monad.when (dbg_countTransformations opts && hasChanged) $ do+ transformCounters %= HashMap.insertWith (const succ) (Text.pack name) 1 - traceIf (lvl >= DebugApplied && (not (normalizeType tcm beforeTy `aeqType` normalizeType tcm afterTy)))- ( concat [ $(curLoc)- , "Error when applying rewrite ", name- , " to:\n" , before- , "\nResult:\n" ++ after ++ "\n"- , "Changes type from:\n", showPpr beforeTy- , "\nto:\n", showPpr afterTy- ]- ) (return ())+ Monad.when (dbg_invariants opts && hasChanged) $ do+ tcm <- Lens.view tcCache+ let beforeTy = inferCoreTypeOf tcm exprOld+ beforeFV = Lens.setOf freeLocalVars exprOld+ afterTy = inferCoreTypeOf tcm exprNew+ afterFV = Lens.setOf freeLocalVars exprNew+ newFV = not (afterFV `Set.isSubsetOf` beforeFV)+ accidentalShadows = findAccidentialShadows exprNew - Monad.when (lvl >= DebugSilent && not hasChanged && not (exprOld `eqTerm` exprNew)) $- error $ $(curLoc) ++ "Expression changed without notice(" ++ name ++ "): before"- ++ before ++ "\nafter:\n" ++ after+ Monad.when newFV $+ error ( concat [ $(curLoc)+ , "Error when applying rewrite ", name+ , " to:\n" , before+ , "\nResult:\n" ++ after ++ "\n"+ , "It introduces free variables."+ , "\nBefore: " ++ showPpr (Set.toList beforeFV)+ , "\nAfter: " ++ showPpr (Set.toList afterFV)+ ]+ )+ Monad.when (not (null accidentalShadows)) $+ error ( concat [ $(curLoc)+ , "Error when applying rewrite ", name+ , " to:\n" , before+ , "\nResult:\n" ++ after ++ "\n"+ , "It accidentally creates shadowing let/case-bindings:\n"+ , " ", showPpr accidentalShadows, "\n"+ , "This usually means that a transformation did not extend "+ , "or incorrectly extended its InScopeSet before applying a "+ , "substitution."+ ]) - traceIf (lvl >= DebugName && hasChanged) (name <> " {" <> show nTrans <> "}") $- traceIf (lvl >= DebugApplied && hasChanged) ("Changes when applying rewrite to:\n"- ++ before ++ "\nResult:\n" ++ after ++ "\n") $- traceIf (lvl >= DebugAll && not hasChanged) ("No changes when applying rewrite "- ++ name ++ " to:\n" ++ after ++ "\n") $- return exprNew- where- before = showPpr exprOld- after = showPpr exprNew+ -- TODO This check should be an error instead of a trace, however this is+ -- currently very fragile as Clash doesn't keep casts in core. This should+ -- be changed when #1064 is merged.+ Monad.when (hasDebugInfo AppliedTerm name opts && not (normalizeType tcm beforeTy `aeqType` normalizeType tcm afterTy)) $+ traceM ( concat [ $(curLoc)+ , "Error when applying rewrite ", name+ , " to:\n" , before+ , "\nResult:\n" ++ after ++ "\n"+ , "Changes type from:\n", showPpr beforeTy+ , "\nto:\n", showPpr afterTy+ ]+ ) + let exprNotEqual = not (fastEqBy eqTerm exprOld exprNew)+ Monad.when (dbg_invariants opts && not hasChanged && exprNotEqual) $+ error $ $(curLoc) ++ "Expression changed without notice(" ++ name ++ "): before"+ ++ before ++ "\nafter:\n" ++ after++ traceIf (hasDebugInfo AppliedName name opts && hasChanged) (name <> " {" <> show nTrans <> "}") $+ traceIf (hasDebugInfo AppliedTerm name opts && hasChanged) ("Changes when applying rewrite to:\n"+ ++ before ++ "\nResult:\n" ++ after ++ "\n") $+ traceIf (hasDebugInfo TryTerm name opts && not hasChanged) ("No changes when applying rewrite "+ ++ name ++ " to:\n" ++ after ++ "\n") $+ return exprNew+ where+ before = showPpr exprOld+ after = showPpr exprNew+ -- | Perform a transformation on a Term runRewrite :: String@@ -299,13 +279,20 @@ runRewriteSession :: RewriteEnv -> RewriteState extra -> RewriteMonad extra a- -> a-runRewriteSession r s m =- traceIf (_dbgLevel r > DebugSilent)- ("Clash: Applied " ++ show (s' ^. transformCounter) ++ " transformations")- a+ -> IO a+runRewriteSession r s m = do+ (a, s', _) <- runR m r s+ traceIf (dbg_countTransformations (opt_debug (envOpts (_clashEnv r))))+ ("Clash: Transformations:\n" ++ Text.unpack (showCounters (s' ^. transformCounters))) $+ traceIf (None < dbg_transformationInfo (opt_debug (envOpts (_clashEnv r))))+ ("Clash: Applied " ++ show (s' ^. transformCounter) ++ " transformations")+ pure a where- (a,s',_) = runR m r s+ showCounters =+ Text.unlines+ . map (\(nm,cnt) -> nm <> ": " <> Text.pack (show cnt))+ . sortOn snd+ . HashMap.toList -- | Notify that a transformation has changed the expression setChanged :: RewriteMonad extra ()@@ -330,19 +317,19 @@ -- | Make a new binder and variable reference for a term mkTmBinderFor- :: (MonadUnique m, MonadFail m)+ :: (MonadUnique m) => InScopeSet -> TyConMap -- ^ TyCon cache -> Name a -- ^ Name of the new binder -> Term -- ^ Term to bind -> m Id-mkTmBinderFor is tcm name e = do- Left r <- mkBinderFor is tcm name (Left e)- return r+mkTmBinderFor is tcm name e =+ either id (error "mkTmBinderFor: Result is a TyVar")+ <$> mkBinderFor is tcm name (Left e) -- | Make a new binder and variable reference for either a term or a type mkBinderFor- :: (MonadUnique m, MonadFail m)+ :: (MonadUnique m) => InScopeSet -> TyConMap -- ^ TyCon cache -> Name a -- ^ Name of the new binder@@ -350,12 +337,12 @@ -> m (Either Id TyVar) mkBinderFor is tcm name (Left term) = do name' <- cloneNameWithInScopeSet is name- let ty = termType tcm term+ let ty = inferCoreTypeOf tcm term return (Left (mkLocalId ty (coerce name'))) mkBinderFor is tcm name (Right ty) = do name' <- cloneNameWithInScopeSet is name- let ki = typeKind tcm ty+ let ki = inferCoreKindOf tcm ty return (Right (mkTyVar ki (coerce name'))) -- | Inline the binders in a let-binding that have a certain property@@ -363,7 +350,17 @@ :: (Term -> LetBinding -> RewriteMonad extra Bool) -- ^ Property test -> Rewrite extra-inlineBinders condition (TransformContext inScope0 _) expr@(Letrec xes res) = do+inlineBinders condition (TransformContext inScope0 _) expr@(Let (NonRec i x) res) = do+ inline <- condition expr (i, x)++ if inline && elemFreeVars i res then+ let inScope1 = extendInScopeSet inScope0 i+ subst = extendIdSubst (mkSubst inScope1) i x+ in changed (substTm "inlineBinders" subst res)+ else+ return expr++inlineBinders condition (TransformContext inScope0 _) expr@(Let (Rec xes) res) = do (toInline,toKeep) <- partitionM (condition expr) xes case toInline of [] -> return expr@@ -432,7 +429,7 @@ -- introduced argument 'w' is not used by 'f' isVoidWrapper :: Term -> Bool isVoidWrapper (Lam bndr e@(collectArgs -> (Var _,_))) =- bndr `localIdDoesNotOccurIn` e+ bndr `notElemFreeVars` e isVoidWrapper _ = False -- | Inline the first set of binder into the second set of binders and into the@@ -463,7 +460,7 @@ subst1 = subst { substTmEnv = mapVarEnv (substTm "substSubst" substE) (substTmEnv subst)} subst2 = extendIdSubst subst1 x e1- in if x `localIdOccursIn` e1 then+ in if x `elemFreeVars` e1 then go subst ((x,e1):inlRec) toInl else go subst2 inlRec toInl@@ -494,7 +491,7 @@ subst1 = subst { substTmEnv = mapVarEnv (substTm "liftSubst" substE) (substTmEnv subst) } subst2 = extendIdSubst subst1 x e2- if x `localIdOccursIn` e2 then do+ if x `elemFreeVars` e2 then do (_,sp) <- Lens.use curFun throw (ClashException sp [I.i| Internal error: inlineOrLiftBInders failed on:@@ -573,7 +570,7 @@ -- Make a new global ID tcm <- Lens.view tcCache- let newBodyTy = termType tcm $ mkTyLams (mkLams e boundFVs) boundFTVs+ let newBodyTy = inferCoreTypeOf tcm $ mkTyLams (mkLams e boundFVs) boundFTVs (cf,sp) <- Lens.use curFun binders <- Lens.use bindings newBodyNm <-@@ -601,6 +598,7 @@ case aeqExisting of -- If it doesn't, create a new binder [] -> do -- Add the created function to the list of global bindings+ let r = newBodyId `globalIdOccursIn` newBody bindings %= extendUniqMap newBodyNm -- We mark this function as internal so that -- it can be inlined at the very end of@@ -610,16 +608,7 @@ -- function at this moment for a reason! -- (termination, CSE and DEC oppertunities, -- ,etc.)- (Binding- newBodyId- sp-#if MIN_VERSION_ghc(8,4,1)- NoUserInline-#else- EmptyInlineSpec-#endif- IsFun- newBody)+ (Binding newBodyId sp NoUserInline IsFun newBody r) -- Return the new binder return (var, newExpr) -- If it does, use the existing binder@@ -632,14 +621,6 @@ liftBinding _ = error $ $(curLoc) ++ "liftBinding: invalid core, expr bound to tyvar" --- | Ensure that the 'Unique' of a variable does not occur in the 'BindingMap'-uniqAwayBinder- :: BindingMap- -> Name a- -> Name a-uniqAwayBinder binders nm =- uniqAway' (`elemUniqMapDirectly` binders) (nameUniq nm) nm- -- | Make a global function for a name-term tuple mkFunction :: TmName@@ -652,7 +633,7 @@ -- ^ Name with a proper unique and the type of the function mkFunction bndrNm sp inl body = do tcm <- Lens.view tcCache- let bodyTy = termType tcm body+ let bodyTy = inferCoreTypeOf tcm body binders <- Lens.use bindings bodyNm <- cloneNameWithBindingMap binders bndrNm addGlobalBind bodyNm bodyTy sp inl body@@ -668,7 +649,8 @@ -> RewriteMonad extra () addGlobalBind vNm ty sp inl body = do let vId = mkGlobalId ty vNm- (ty,body) `deepseq` bindings %= extendUniqMap vNm (Binding vId sp inl IsFun body)+ r = vId `globalIdOccursIn` body+ (ty,body) `deepseq` bindings %= extendUniqMap vNm (Binding vId sp inl IsFun body r) -- | Create a new name out of the given name, but with another unique. Resulting -- unique is guaranteed to not be in the given InScopeSet.@@ -705,7 +687,7 @@ <*> Lens.view customReprs <*> pure stringRepresentable <*> pure tcm- <*> pure (termType tcm tm))+ <*> pure (inferCoreTypeOf tcm tm)) {-# INLINE isUntranslatableType #-} -- | Determine if a type cannot be represented in hardware@@ -721,166 +703,6 @@ <*> Lens.view tcCache <*> pure ty) --- | Specialise an application on its argument-specialise :: Lens' extra (Map.Map (Id, Int, Either Term Type) Id) -- ^ Lens into previous specialisations- -> Lens' extra (VarEnv Int) -- ^ Lens into the specialisation history- -> Lens' extra Int -- ^ Lens into the specialisation limit- -> Rewrite extra-specialise specMapLbl specHistLbl specLimitLbl ctx e = case e of- (TyApp e1 ty) -> specialise' specMapLbl specHistLbl specLimitLbl ctx e (collectArgsTicks e1) (Right ty)- (App e1 e2) -> specialise' specMapLbl specHistLbl specLimitLbl ctx e (collectArgsTicks e1) (Left e2)- _ -> return e---- | Specialise an application on its argument-specialise' :: Lens' extra (Map.Map (Id, Int, Either Term Type) Id) -- ^ Lens into previous specialisations- -> Lens' extra (VarEnv Int) -- ^ Lens into specialisation history- -> Lens' extra Int -- ^ Lens into the specialisation limit- -> TransformContext -- Transformation context- -> Term -- ^ Original term- -> (Term, [Either Term Type], [TickInfo]) -- ^ Function part of the term, split into root and applied arguments- -> Either Term Type -- ^ Argument to specialize on- -> RewriteMonad extra Term-specialise' specMapLbl specHistLbl specLimitLbl (TransformContext is0 _) e (Var f, args, ticks) specArgIn = do- lvl <- Lens.view dbgLevel- tcm <- Lens.view tcCache-- -- Don't specialise TopEntities- topEnts <- Lens.view topEntities- if f `elemVarSet` topEnts- then do- case specArgIn of- Left _ -> traceIf (lvl >= DebugNone) ("Not specializing TopEntity: " ++ showPpr (varName f)) (return e)- Right tyArg -> traceIf (lvl >= DebugApplied) ("Dropping type application on TopEntity: " ++ showPpr (varName f) ++ "\ntype:\n" ++ showPpr tyArg) $- -- TopEntities aren't allowed to be semantically polymorphic.- -- But using type equality constraints they may be syntactically polymorphic.- -- > topEntity :: forall dom . (dom ~ "System") => Signal dom Bool -> Signal dom Bool- -- The TyLam's in the body will have been removed by 'Clash.Normalize.Util.substWithTyEq'.- -- So we drop the TyApp ("specialising" on it) and change the varType to match.- let newVarTy = piResultTy tcm (varType f) tyArg- in changed (mkApps (mkTicks (Var f{varType = newVarTy}) ticks) args)- else do -- NondecreasingIndentation-- let specArg = bimap (normalizeTermTypes tcm) (normalizeType tcm) specArgIn- -- Create binders and variable references for free variables in 'specArg'- -- (specBndrsIn,specVars) :: ([Either Id TyVar], [Either Term Type])- (specBndrsIn,specVars) = specArgBndrsAndVars specArg- argLen = length args- specBndrs :: [Either Id TyVar]- specBndrs = map (Lens.over _Left (normalizeId tcm)) specBndrsIn- specAbs :: Either Term Type- specAbs = either (Left . stripAllTicks . (`mkAbstraction` specBndrs)) (Right . id) specArg- -- Determine if 'f' has already been specialized on (a type-normalized) 'specArg'- specM <- Map.lookup (f,argLen,specAbs) <$> Lens.use (extra.specMapLbl)- case specM of- -- Use previously specialized function- Just f' ->- traceIf (lvl >= DebugApplied)- ("Using previous specialization of " ++ showPpr (varName f) ++ " on " ++- (either showPpr showPpr) specAbs ++ ": " ++ showPpr (varName f')) $- changed $ mkApps (mkTicks (Var f') ticks) (args ++ specVars)- -- Create new specialized function- Nothing -> do- -- Determine if we can specialize f- bodyMaybe <- fmap (lookupUniqMap (varName f)) $ Lens.use bindings- case bodyMaybe of- Just (Binding _ sp inl _ bodyTm) -> do- -- Determine if we see a sequence of specialisations on a growing argument- specHistM <- lookupUniqMap f <$> Lens.use (extra.specHistLbl)- specLim <- Lens.use (extra . specLimitLbl)- if maybe False (> specLim) specHistM- then throw (ClashException- sp- (unlines [ "Hit specialisation limit " ++ show specLim ++ " on function `" ++ showPpr (varName f) ++ "'.\n"- , "The function `" ++ showPpr f ++ "' is most likely recursive, and looks like it is being indefinitely specialized on a growing argument.\n"- , "Body of `" ++ showPpr f ++ "':\n" ++ showPpr bodyTm ++ "\n"- , "Argument (in position: " ++ show argLen ++ ") that triggered termination:\n" ++ (either showPpr showPpr) specArg- , "Run with '-fclash-spec-limit=N' to increase the specialisation limit to N."- ])- Nothing)- else do- let existingNames = collectBndrsMinusApps bodyTm- newNames = [ mkUnsafeInternalName ("pTS" `Text.append` Text.pack (show n)) n- | n <- [(0::Int)..]- ]- -- Make new binders for existing arguments- (boundArgs,argVars) <- fmap (unzip . map (either (Left &&& Left . Var) (Right &&& Right . VarTy))) $- Monad.zipWithM- (mkBinderFor is0 tcm)- (existingNames ++ newNames)- args- -- Determine name the resulting specialized function, and the- -- form of the specialized-on argument- (fId,inl',specArg') <- case specArg of- Left a@(collectArgsTicks -> (Var g,gArgs,_gTicks)) -> if isPolyFun tcm a- then do- -- In case we are specialising on an argument that is a- -- global function then we use that function's name as the- -- name of the specialized higher-order function.- -- Additionally, we will return the body of the global- -- function, instead of a variable reference to the- -- global function.- --- -- This will turn things like @mealy g k@ into a new- -- binding @g'@ where both the body of @mealy@ and @g@- -- are inlined, meaning the state-transition-function- -- and the memory element will be in a single function.- gTmM <- fmap (lookupUniqMap (varName g)) $ Lens.use bindings- return (g,maybe inl bindingSpec gTmM, maybe specArg (Left . (`mkApps` gArgs) . bindingTerm) gTmM)- else return (f,inl,specArg)- _ -> return (f,inl,specArg)- -- Create specialized functions- let newBody = mkAbstraction (mkApps bodyTm (argVars ++ [specArg'])) (boundArgs ++ specBndrs)- newf <- mkFunction (varName fId) sp inl' newBody- -- Remember specialization- (extra.specHistLbl) %= extendUniqMapWith f 1 (+)- (extra.specMapLbl) %= Map.insert (f,argLen,specAbs) newf- -- use specialized function- let newExpr = mkApps (mkTicks (Var newf) ticks) (args ++ specVars)- newf `deepseq` changed newExpr- Nothing -> return e- where- collectBndrsMinusApps :: Term -> [Name a]- collectBndrsMinusApps = reverse . go []- where- go bs (Lam v e') = go (coerce (varName v):bs) e'- go bs (TyLam tv e') = go (coerce (varName tv):bs) e'- go bs (App e' _) = case go [] e' of- [] -> bs- bs' -> init bs' ++ bs- go bs (TyApp e' _) = case go [] e' of- [] -> bs- bs' -> init bs' ++ bs- go bs _ = bs---- Specialising non Var's is used by nonRepANF-specialise' _ _ _ _ctx _ (appE,args,ticks) (Left specArg) = do- -- Create binders and variable references for free variables in 'specArg'- let (specBndrs,specVars) = specArgBndrsAndVars (Left specArg)- -- Create specialized function- newBody = mkAbstraction specArg specBndrs- -- See if there's an existing binder that's alpha-equivalent to the- -- specialized function- existing <- filterUniqMap ((`aeqTerm` newBody) . bindingTerm) <$> Lens.use bindings- -- Create a new function if an alpha-equivalent binder doesn't exist- newf <- case eltsUniqMap existing of- [] -> do (cf,sp) <- Lens.use curFun- mkFunction (appendToName (varName cf) "_specF")- sp-#if MIN_VERSION_ghc(8,4,1)- NoUserInline-#else- EmptyInlineSpec-#endif- newBody- (b:_) -> return (bindingId b)- -- Create specialized argument- let newArg = Left $ mkApps (Var newf) specVars- -- Use specialized argument- let newExpr = mkApps (mkTicks appE ticks) (args ++ [newArg])- changed newExpr--specialise' _ _ _ _ e _ _ = return e- normalizeTermTypes :: TyConMap -> Term -> Term normalizeTermTypes tcm e = case e of Cast e' ty1 ty2 -> Cast (normalizeTermTypes tcm e') (normalizeType tcm ty1) (normalizeType tcm ty2)@@ -892,53 +714,6 @@ normalizeId tcm v@(Id {}) = v {varType = normalizeType tcm (varType v)} normalizeId _ tyvar = tyvar --- Note [Collect free-variables in an insertion-ordered set]------ In order for the specialization cache to work, 'specArgBndrsAndVars' should--- yield (alpha equivalent) results for the same specialization. While collecting--- free variables in a given term or type it should therefore keep a stable--- ordering based on the order in which it finds free vars. To see why,--- consider the following two pseudo-code calls to 'specialise':------ specialise {f ('a', x[123], y[456])}--- specialise {f ('b', x[456], y[123])}------ Collecting the binders in a VarSet would yield the following (unique ordered)--- sets:------ {x[123], y[456]}--- {y[123], x[456]}------ ..and therefore breaking specializing caching. We now track them in insert---- ordered sets, yielding:------ {x[123], y[456]}--- {x[456], y[123]}------- | Create binders and variable references for free variables in 'specArg'-specArgBndrsAndVars- :: Either Term Type- -> ([Either Id TyVar], [Either Term Type])-specArgBndrsAndVars specArg =- -- See Note [Collect free-variables in an insertion-ordered set]- let unitFV :: Var a -> Const (OSet.OLSet TyVar, OSet.OLSet Id) (Var a)- unitFV v@(Id {}) = Const (mempty, coerce (OSet.singleton (coerce v)))- unitFV v@(TyVar {}) = Const (coerce (OSet.singleton (coerce v)), mempty)-- (specFTVs,specFVs) = case specArg of- Left tm -> (OSet.toListL *** OSet.toListL) . getConst $- Lens.foldMapOf freeLocalVars unitFV tm- Right ty -> (eltsUniqSet (Lens.foldMapOf typeFreeVars unitUniqSet ty),[] :: [Id])-- specTyBndrs = map Right specFTVs- specTmBndrs = map Left specFVs-- specTyVars = map (Right . VarTy) specFTVs- specTmVars = map (Left . Var) specFVs-- in (specTyBndrs ++ specTmBndrs,specTyVars ++ specTmVars)- -- | Evaluate an expression to weak-head normal form (WHNF), and apply a -- transformation on the expression in WHNF. whnfRW@@ -956,32 +731,14 @@ ids <- Lens.use uniqSupply let (ids1,ids2) = splitSupply ids uniqSupply Lens..= ids2--#if EXPERIMENTAL_EVALUATOR- (i, _) <- Lens.use curFun- heap <- Lens.use ioHeap- addr <- Lens.use ioAddr- fuel <- Lens.view fuelLimit- let genv = mkGlobalEnv bndrs tcm is0 ids1 fuel heap addr-- case unsafePerformIO (nf eval genv isSubj i e) of- (!e', !genv') -> do- ioHeap Lens..= genvHeap genv'- ioAddr Lens..= genvAddr genv'-- -- TODO I remain unsure about this. Do I want to use bindPureHeap?- rw (ctx { tfInScope = genvInScope genv' }) e'-#else gh <- Lens.use globalHeap case whnf' eval bndrs tcm gh ids1 is0 isSubj e of (!gh1,ph,v) -> do globalHeap Lens..= gh1 bindPureHeap tcm ph rw ctx v-#endif {-# SCC whnfRW #-} -#if !EXPERIMENTAL_EVALUATOR -- | Binds variables on the PureHeap over the result of the rewrite -- -- To prevent unnecessary rewrites only do this when rewrite changed something.@@ -1019,7 +776,7 @@ -- ‡ https://www.microsoft.com/en-us/research/wp-content/uploads/2016/07/supercomp-by-eval.pdf bs <- Lens.use bindings inlineBinders (inlineTest bs) ctx0 (Letrec bndrs e1) >>= \case- e2@(Letrec bnders1 e3) ->+ e2@(Let bnders1 e3) -> pure (fromMaybe e2 (removeUnusedBinders bnders1 e3)) e2 -> pure e2@@ -1035,19 +792,22 @@ toLetBinding :: (Unique,Term) -> LetBinding toLetBinding (uniq,term) = (nm, term) where- ty = termType tcm term+ ty = inferCoreTypeOf tcm term nm = mkLocalId ty (mkUnsafeSystemName "x" uniq) -- See [Note: Name re-creation] inlineTest bs _ (_, stripTicks -> e_) = isWorkFree workFreeBinders bs e_-#endif -- | Remove unused binders in given let-binding. Returns /Nothing/ if no unused -- binders were found. removeUnusedBinders- :: [LetBinding]+ :: Bind Term -> Term -> Maybe Term-removeUnusedBinders binds body =+removeUnusedBinders (NonRec i _) body =+ let bodyFVs = Lens.foldMapOf freeLocalIds unitVarSet body+ in if i `elemVarSet` bodyFVs then Nothing else Just body++removeUnusedBinders (Rec binds) body = case eltsVarEnv used of [] -> Just body qqL | not (List.equalLength qqL binds)
src/Clash/Rewrite/WorkFree.hs view
@@ -1,5 +1,5 @@ {-|-Copyright : (C) 2020, QBayLogic B.V.+Copyright : (C) 2020-2021, QBayLogic B.V. License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qaylogic.com> @@ -10,6 +10,7 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TemplateHaskellQuotes #-} module Clash.Rewrite.WorkFree ( isWorkFree@@ -22,18 +23,21 @@ import Control.Lens (Lens') import Control.Monad.Extra (allM, andM, eitherM) import Control.Monad.State.Class (MonadState)+import qualified Data.Text.Extra as Text import GHC.Stack (HasCallStack) +import Clash.Core.HasFreeVars import Clash.Core.FreeVars+import Clash.Core.HasType import Clash.Core.Pretty (showPpr) import Clash.Core.Term-import Clash.Core.TermInfo import Clash.Core.TyCon (TyConMap) import Clash.Core.Type (isPolyFunTy) import Clash.Core.Util-import Clash.Core.Var (Id, Var(..), isLocalId)+import Clash.Core.Var (Id, isLocalId) import Clash.Core.VarEnv (VarEnv, lookupVarEnv) import Clash.Driver.Types (BindingMap, Binding(..))+import Clash.Normalize.Primitives (removedArg) import Clash.Util (makeCachedU) -- | Determines whether a global binder is work free. Errors if binder does@@ -86,7 +90,7 @@ -- isWorkFree with all the local FVs of the term being checked. PE -- would need to be changed to know the FVs of global binders first. --- | isPolyFunTy (varType i) ->+ | isPolyFunTy (coreTypeOf i) -> pure (isLocalId i && isOutermost && null args) | isLocalId i -> pure True@@ -101,12 +105,14 @@ -- regardless of their values. WorkConstant -> pure True WorkNever -> allM goArg args+ WorkIdentity _ _ -> allM goArg args WorkVariable -> pure (all isConstantArg args) WorkAlways -> pure False Lam _ e -> andM [go False e, allM goArg args] TyLam _ e -> andM [go False e, allM goArg args]- Letrec bs e -> andM [go False e, allM (go False . snd) bs, allM goArg args]+ Let (NonRec _ x) e -> andM [go False e, go False x, allM goArg args]+ Let (Rec bs) e -> andM [go False e, allM (go False . snd) bs, allM goArg args] Case s _ [(_, a)] -> andM [go False s, go False a, allM goArg args] Case e _ _ -> andM [go False e, allM goArg args] Cast e _ _ -> andM [go False e, allM goArg args]@@ -124,7 +130,7 @@ isConstant e = case collectArgs e of (Data _, args) -> all (either isConstant (const True)) args (Prim _, args) -> all (either isConstant (const True)) args- (Lam _ _, _) -> not (hasLocalFreeVars e)+ (Lam _ _, _) -> isClosed e (Literal _,_) -> True _ -> False @@ -132,12 +138,12 @@ isConstantNotClockReset tcm e | isClockOrReset tcm eTy = case fst (collectArgs e) of- Prim pr -> primName pr == "Clash.Transformations.removedArg"+ Prim pr -> primName pr == Text.showt 'removedArg _ -> False | otherwise = isConstant e where- eTy = termType tcm e+ eTy = inferCoreTypeOf tcm e -- TODO: Remove function after using WorkInfo in 'isWorkFreeIsh' isWorkFreeClockOrResetOrEnable@@ -145,10 +151,10 @@ -> Term -> Maybe Bool isWorkFreeClockOrResetOrEnable tcm e =- let eTy = termType tcm e in+ let eTy = inferCoreTypeOf tcm e in if isClockOrReset tcm eTy || isEnable tcm eTy then case collectArgs e of- (Prim p,_) -> Just (primName p == "Clash.Transformations.removedArg")+ (Prim p,_) -> Just (primName p == Text.showt 'removedArg) (Var _, []) -> Just True (Data _, [_dom, Left (stripTicks -> Data _)]) -> Just True -- For Enable True/False (Literal _,_) -> Just True@@ -184,7 +190,7 @@ WorkVariable -> all isConstantArg args _ -> all isWorkFreeIshArg args - (Lam _ _, _) -> not (hasLocalFreeVars e)+ (Lam _ _, _) -> isClosed e (Literal _,_) -> True _ -> False where
src/Clash/Unique.hs view
@@ -51,6 +51,8 @@ -- * UniqSet , UniqSet -- ** Accessors+ -- *** Size information+ , nullUniqSet -- *** Indexing , lookupUniqSet -- ** Construction@@ -67,6 +69,8 @@ , elemUniqSetDirectly -- *** Misc , subsetUniqSet+ , disjointUniqSet+ , differenceUniqSet -- ** Conversions -- *** Lists , mkUniqSet@@ -78,6 +82,11 @@ import Data.Binary (Binary) import Data.IntMap (IntMap) import qualified Data.IntMap as IntMap++#if !MIN_VERSION_containers(0,6,2)+import qualified Data.IntMap.Extra as IntMap+#endif+ import qualified Data.List as List #if MIN_VERSION_prettyprinter(1,7,0)@@ -86,10 +95,6 @@ import Data.Text.Prettyprint.Doc #endif -#if !MIN_VERSION_base(4,11,0)-import Data.Semigroup-#endif- import GHC.Stack import Clash.Pretty@@ -379,6 +384,12 @@ -> Bool elemUniqSetDirectly k (UniqSet m) = k `IntMap.member` m +-- | Check whether a set is empty+nullUniqSet+ :: UniqSet a+ -> Bool+nullUniqSet (UniqSet env) = IntMap.null env+ -- | Look up an element in the set, returns it if it exists lookupUniqSet :: Uniquable a@@ -421,3 +432,17 @@ -- ^ Set B -> Bool subsetUniqSet (UniqSet e1) (UniqSet e2) = IntMap.null (IntMap.difference e1 e2)++-- | Check whether A and B are disjoint+disjointUniqSet+ :: UniqSet a+ -> UniqSet a+ -> Bool+disjointUniqSet (UniqSet e1) (UniqSet e2) = IntMap.disjoint e1 e2++-- | Take the difference of two sets+differenceUniqSet+ :: UniqSet a+ -> UniqSet a+ -> UniqSet a+differenceUniqSet (UniqSet e1) (UniqSet e2) = UniqSet (IntMap.difference e1 e2)
src/Clash/Util.hs view
@@ -16,21 +16,15 @@ module Clash.Util ( module Clash.Util- , module X- , makeLenses , SrcSpan , noSrcSpan- , HasCallStack ) where -import Control.Arrow as X ((***),(&&&),first,second) import qualified Control.Exception as Exception import Control.Lens-import Control.Monad as X ((<=<),(>=>)) import Control.Monad.State (MonadState,StateT) import qualified Control.Monad.State as State-import Data.Function as X (on) import Data.Hashable (Hashable) import Data.HashMap.Lazy (HashMap) import qualified Data.HashMap.Lazy as HashMapL@@ -212,13 +206,6 @@ l %= (flip (OMap.|>)) (getUnique key, value) return value -combineM :: (Applicative f)- => (a -> f b)- -> (c -> f d)- -> (a,c)- -> f (b,d)-combineM f g (x,y) = (,) <$> f x <*> g y- -- | Same as 'indexNote' with last two arguments swapped indexNote' :: HasCallStack@@ -292,11 +279,6 @@ = "%-S%03Qs" -- | Left-biased choice on maybes-orElse :: Maybe a -> Maybe a -> Maybe a-orElse x@(Just _) _y = x-orElse _x y = y---- | Left-biased choice on maybes orElses :: [Maybe a] -> Maybe a orElses = listToMaybe . catMaybes @@ -323,6 +305,7 @@ , LangExt.KindSignatures , LangExt.MagicHash , LangExt.MonoLocalBinds+ , LangExt.NumericUnderscores , LangExt.QuasiQuotes , LangExt.ScopedTypeVariables , LangExt.TemplateHaskell@@ -330,17 +313,12 @@ , LangExt.TypeApplications , LangExt.TypeFamilies , LangExt.TypeOperators-#if !MIN_VERSION_ghc(8,6,0)- , LangExt.TypeInType-#endif ] unwantedLanguageExtensions :: [LangExt.Extension] unwantedLanguageExtensions = [ LangExt.ImplicitPrelude-#if MIN_VERSION_ghc(8,6,0) , LangExt.StarIsType-#endif , LangExt.Strict , LangExt.StrictData ]
+ src/Clash/Util/Eq.hs view
@@ -0,0 +1,46 @@+{-|+ Copyright : (C) 2021 , QBayLogic B.V.+ License : BSD2 (see the file LICENSE)+ Maintainer : QBayLogic B.V. <devops@qbaylogic.com>++ Utilities related to the 'Eq' type class.+-}+{-# LANGUAGE MagicHash #-}++module Clash.Util.Eq+ ( fastEq+ , fastEqBy+ ) where++import GHC.Exts (isTrue#, reallyUnsafePtrEquality#)++-- | Compare two values using pointer equality. If that fails, use 'Eq' to+-- determine equality. Note that this function will only shortcut for values+-- that are the same, but will always use 'Eq' for values that differ.+--+-- Values are evaluated to WHNF before comparison. This function can therefore+-- not be used if any of its arguments is expected to be bottom.+fastEq :: Eq a => a -> a -> Bool+fastEq = fastEqBy (==)++-- | Compare two values using pointer equality. If that fails, use given function+-- to determine equality. Note that this function will only shortcut for values+-- that are the same, but will always use the given function for values that+-- differ.+--+-- Values are evaluated to WHNF before comparison. This function can therefore+-- not be used if any of its arguments is expected to be bottom.+fastEqBy :: (a -> a -> Bool) -> a -> a -> Bool+fastEqBy f a1 a2+ | a1 `pointerEq` a2 = True+ | otherwise = f a1 a2++{-# NOINLINE pointerEq #-}+-- | Compares two values by comparing their positions on the heap. This function+-- will return 'True' if the values are the same object, 'False' otherwise. Note+-- that 'False' does *not* mean that the values are *not* the same. Values are+-- evaluated to WHNF before comparison.+--+-- Note: copied from @unordered-containers@.+pointerEq :: a -> a -> Bool+pointerEq !x !y = isTrue# (reallyUnsafePtrEquality# x y)
+ src/Clash/Verification/Pretty.hs view
@@ -0,0 +1,278 @@+{-|+Copyright : (C) 2019, Myrtle Software Ltd+License : BSD2 (see the file LICENSE)+Maintainer : QBayLogic B.V. <devops@qbaylogic.com>++Verification+-}++{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}++module Clash.Verification.Pretty+ ( pprPslProperty+ , pprSvaProperty+ , pprYosysSvaProperty++ -- * Debugging functions+ , pprProperty+ ) where++import Clash.Annotations.Primitive (HDL(..))+import Clash.Signal.Internal (ActiveEdge, ActiveEdge(..))+import Clash.Verification.Internal hiding (assertion)+import Clash.Netlist.Types (Declaration(..), Seq(..), Expr, CommentOrDirective(..))+import Data.Maybe (fromMaybe)+import Data.Text (Text)+import qualified Data.Text as Text (pack)++data Symbol+ = TImpliesOverlapping+ | TImplies+ | Implies+ | BiImplies+ | Not+ | And+ | Or+ | To+ | Equals+ -- + [] ?+ | Assign+ | Is++------------------------------------------+-- UTIL --+------------------------------------------+-- | Collapse constructs such as `next (next a)` down to `next[2] a`+squashBefore :: Assertion' a -> [Assertion' a]+squashBefore (CvBefore e1 e2) = e1s ++ e2s+ where+ e1s = case squashBefore e1 of {[] -> [e1]; es -> es}+ e2s = case squashBefore e2 of {[] -> [e2]; es -> es}+squashBefore _ = []++parensIf :: Bool -> Text -> Text+parensIf True s = "(" <> s <> ")"+parensIf False s = s++---------------------------------------+-- PSL --+---------------------------------------+pslBinOp+ :: HDL+ -> Bool+ -> Symbol+ -> Assertion' Text+ -> Assertion' Text+ -> Text+pslBinOp hdl parens op e1 e2 =+ parensIf parens (e1' <> symbol hdl op <> e2')+ where+ e1' = pprPslAssertion hdl True e1+ e2' = pprPslAssertion hdl True e2++pslEdge :: HDL -> ActiveEdge -> Text -> Text+pslEdge SystemVerilog activeEdge clkId = pslEdge Verilog activeEdge clkId+pslEdge Verilog Rising clkId = "posedge " <> clkId+pslEdge Verilog Falling clkId = "negedge " <> clkId+pslEdge VHDL Rising clkId = "rising_edge(" <> clkId <> ")"+pslEdge VHDL Falling clkId = "falling_edge(" <> clkId <> ")"++-- | Taken from IEEE Std 1850-2010a, Annex B.1, p149+symbol :: HDL -> Symbol -> Text+symbol SystemVerilog = symbol Verilog+symbol Verilog = \case+ TImpliesOverlapping -> "|->"+ TImplies -> "|=>"+ Implies -> "->"+ BiImplies -> "<->"+ Not -> "!"+ And -> "&&"+ Or -> "||"+ To -> ":"+ Assign -> "<="+ Is -> "="+ Equals -> "=="++symbol VHDL = \case+ TImpliesOverlapping -> "|->"+ TImplies -> "|=>"+ Implies -> " -> "+ BiImplies -> " <-> "+ Not -> "not"+ And -> " and "+ Or -> " or "+ To -> " to "+ Assign -> "<="+ Is -> "is"+ Equals -> "="++-- | Pretty print Property. Doesn't print valid HDL, but can be used for+-- debugging purposes.+pprProperty :: Property dom -> Declaration+pprProperty (Property prop0) =+ let prop1 = fromMaybe "__autogen__" . fst <$> prop0 in+ pprPslProperty VHDL "prop" "clk" Rising prop1++pprPslProperty+ :: HDL+ -- ^ HDL to generate PSL expression for+ -> Text+ -- ^ Property name+ -> Text+ -- ^ Clock name+ -> ActiveEdge+ -- ^ Edge property should be sensitive to+ -> Property' Text+ -- ^ Assertion / Cover statement+ -> Declaration+pprPslProperty hdl propName clkId edge assertion = TickDecl . Comment $+ "psl property " <> propName <> " " <> symbol hdl Is <> "\n" <>+ "(" <> prop <> ") @(" <> pslEdge hdl edge clkId <> ")" <>+ ";\n" <> "psl " <> coverOrAssert <> " " <>+ propName <> ";"+ where+ (coverOrAssert, prop) =+ case assertion of+ CvCover e -> ("cover", pprPslAssertion hdl False e)+ CvAssert e -> ("assert", pprPslAssertion hdl False e)+ CvAssume e -> ("assume", pprPslAssertion hdl False e)++pprPslAssertion :: HDL -> Bool -> Assertion' Text -> Text+pprPslAssertion hdl parens e =+ case e of+ (CvPure p) -> p++ -- ModelSim/QuastaSim doesn't support booleans in PSL. Anytime we want to+ -- use a boolean literal we use (0 == 0) or (0 == 1) instead.+ (CvLit False) -> parensIf parens ("0" <> symbol hdl Equals <> "1")+ (CvLit True) -> parensIf parens ("0" <> symbol hdl Equals <> "0")++ (CvNot e1) ->+ parensIf parens (symbol hdl Not <> " " <> pprPslAssertion hdl True e1)+ (CvAnd e1 e2) -> pslBinOp1 And e1 e2+ (CvOr e1 e2) -> pslBinOp1 Or e1 e2+ (CvImplies e1 e2) -> pslBinOp1 Implies e1 e2++ (CvToTemporal e1) -> "{" <> pprPslAssertion hdl False e1 <> "}"++ (CvNext 0 e1) -> pprPslAssertion hdl parens e1+ (CvNext 1 e1) -> " ## " <> pprPslAssertion hdl True e1+ (CvNext n e1) -> " ##" <> Text.pack (show n) <> " " <> pprPslAssertion hdl False e1++ (CvBefore _ _) -> "{" <> afters1 <> "}"+ where+ afters0 = map (pprPslAssertion hdl False) (squashBefore e)+ afters1 = foldl1 (\e1 e2 -> e1 <> "; " <> e2) afters0++ (CvTemporalImplies 0 e1 e2) -> pslBinOp1 TImpliesOverlapping e1 e2+ (CvTemporalImplies 1 e1 e2) -> pslBinOp1 TImplies e1 e2+ (CvTemporalImplies n e1 e2) -> pslBinOp1 TImplies e1 (CvNext n e2)++ (CvAlways e1) -> "always " <> pprPslAssertion hdl True e1+ (CvNever e1) -> "never " <> pprPslAssertion hdl True e1+ (CvEventually e1) -> "eventually! " <> pprPslAssertion hdl True e1+ where+ pslBinOp1 = pslBinOp hdl True+++---------------------------------------+-- SVA --+---------------------------------------+svaEdge :: ActiveEdge -> Text -> Text+svaEdge Rising clkId = "posedge " <> clkId+svaEdge Falling clkId = "negedge " <> clkId++svaBinOp+ :: Bool+ -> Symbol+ -> Assertion' Text+ -> Assertion' Text+ -> Text+svaBinOp parens op e1 e2 =+ parensIf parens (e1' <> symbol SystemVerilog op <> e2')+ where+ e1' = pprSvaAssertion True e1+ e2' = pprSvaAssertion True e2++pprSvaAssertion :: Bool -> Assertion' Text -> Text+pprSvaAssertion parens e =+ case e of+ (CvPure p) -> p+ (CvLit False) -> "false"+ (CvLit True) -> "true"++ (CvNot e1) ->+ parensIf parens (symbol' Not <> pprSvaAssertion True e1)+ (CvAnd e1 e2) -> svaBinOp1 And e1 e2+ (CvOr e1 e2) -> svaBinOp1 Or e1 e2+ (CvImplies e1 e2) -> svaBinOp1 Implies e1 e2++ (CvToTemporal e1) -> "{" <> pprSvaAssertion False e1 <> "}"++ (CvNext 0 e1) -> pprSvaAssertion parens e1+ (CvNext n e1) -> "nexttime[" <> Text.pack (show n) <> "] " <> pprSvaAssertion False e1++ (CvBefore _ _) -> "{" <> afters1 <> "}"+ where+ afters0 = map (pprSvaAssertion False) (squashBefore e)+ afters1 = foldl1 (\e1 e2 -> "(" <> e1 <> ") ##1 (" <> e2 <> ")") afters0++ (CvTemporalImplies 0 e1 e2) -> svaBinOp1 TImpliesOverlapping e1 e2+ (CvTemporalImplies 1 e1 e2) -> svaBinOp1 TImplies e1 e2+ (CvTemporalImplies n e1 e2) -> svaBinOp1 TImplies e1 (CvNext n e2)++ (CvAlways e1) -> "always (" <> pprSvaAssertion False e1 <> ")"+ (CvNever _e) -> error "'never' not supported in SVA"+ (CvEventually e1) -> "s_eventually (" <> pprSvaAssertion False e1 <> ")"+ where+ svaBinOp1 = svaBinOp parens+ symbol' = symbol SystemVerilog++pprSvaProperty+ :: Text+ -- ^ Property name+ -> Text+ -- ^ Clock name+ -> ActiveEdge+ -- ^ Edge property should be sensitive to+ -> Property' Text+ -- ^ Assertion / Cover statement+ -> Declaration+pprSvaProperty propName clkId edge assertion = TickDecl . Comment $+ propName <> ": " <> coverOrAssert <> " property (@(" <>+ svaEdge edge clkId <> ") " <> prop <> ");"+ where+ (coverOrAssert, prop) =+ case assertion of+ CvCover e -> ("cover", pprSvaAssertion False e)+ CvAssert e -> ("assert", pprSvaAssertion False e)+ CvAssume e -> ("assume", pprSvaAssertion False e)++---------------------------------------+-- Yosys Formal Extensions --+---------------------------------------++-- | Generate something like:+-- @always @(posedge clk_i) isOn: cover (result);@+pprYosysSvaProperty+ :: Text+ -- ^ Property name+ -> Expr+ -- ^ Clock expression+ -> ActiveEdge+ -- ^ Edge property should be sensitive to+ -> Property' Text+ -- ^ Assertion / Cover statement+ -> Declaration+pprYosysSvaProperty propName clk edge assertion = ConditionalDecl+ "FORMAL"+ [Seq [AlwaysClocked edge clk [SeqDecl (TickDecl directive)]]]+ where+ directive = Directive+ (propName <> ": " <> coverOrAssert <> " property (" <> prop <> ")")++ (coverOrAssert, prop) = case assertion of+ CvCover e -> ("cover", pprSvaAssertion False e)+ CvAssert e -> ("assert", pprSvaAssertion False e)+ CvAssume e -> ("assume", pprSvaAssertion False e)
− src/Control/Applicative/Extra.hs
@@ -1,18 +0,0 @@-{-|- Copyright : (C) 2020, QBayLogic B.V.- License : BSD2 (see the file LICENSE)- Maintainer : QBayLogic B.V. <devops@qbaylogic.com>--}--module Control.Applicative.Extra- ( orEmpty- , emptyIf- ) where--import Control.Applicative (Alternative, empty)--orEmpty :: Alternative f => Bool -> a -> f a-orEmpty b a = if b then pure a else empty--emptyIf :: Alternative f => a -> Bool -> f a-emptyIf a b = if b then empty else pure a
src/Data/Aeson/Extra.hs view
@@ -8,6 +8,8 @@ {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE OverloadedStrings #-} +{-# OPTIONS_HADDOCK hide #-}+ module Data.Aeson.Extra where import Control.Exception (throw)@@ -27,6 +29,7 @@ import Data.ByteString.Lazy (ByteString) import qualified Data.ByteString.Lazy as BS import qualified Data.ByteString.Lazy.Char8 as BSChar+import qualified Data.Yaml as Yaml import System.FilePath () import qualified Clash.Util.Interpolate as I@@ -130,14 +133,39 @@ -- | Parse a ByteString according to the given JSON template. Throws exception -- if it fails.-decodeOrErr+decodeOrErrYaml :: (HasCallStack, FromJSON a) => FilePath -- ^ Path read from (for error message) -> ByteString -- ^ Bytestring to parse -> a-decodeOrErr path contents0 =+decodeOrErrYaml path contents =+ case Yaml.decodeEither' (BS.toStrict contents) of+ Left (Yaml.prettyPrintParseException -> err) -> clashError [I.i|+ Failed to decode YAML:++ #{path}++ Decoder reported:++ #{err}+ |]+ Right a -> a+ where+ clashError msg = throw (ClashException loc msg Nothing)+ loc = mkGeneralSrcSpan (mkFastString path)++-- | Parse a ByteString according to the given JSON template. Throws exception+-- if it fails.+decodeOrErrJson+ :: (HasCallStack, FromJSON a)+ => FilePath+ -- ^ Path read from (for error message)+ -> ByteString+ -- ^ Bytestring to parse+ -> a+decodeOrErrJson path contents0 = case toSpecNewlines contents0 of Left (DecodeError err _) -> clashError [I.i| Failed to decode JSON file as UTF8:
+ src/Data/IntMap/Extra.hs view
@@ -0,0 +1,36 @@+{-# LANGUAGE CPP #-}++module Data.IntMap.Extra where++#if !MIN_VERSION_containers(0,6,2)+import Data.IntMap.Internal++-- TODO We can remove this when support for GHC 8.6 is dropped.++-- | /O(n+m)/. Check whether the key sets of two maps are disjoint+-- (i.e. their 'intersection' is empty).+--+-- > disjoint (fromList [(2,'a')]) (fromList [(1,()), (3,())]) == True+-- > disjoint (fromList [(2,'a')]) (fromList [(1,'a'), (2,'b')]) == False+-- > disjoint (fromList []) (fromList []) == True+--+-- > disjoint a b == null (intersection a b)+--+disjoint :: IntMap a -> IntMap b -> Bool+disjoint Nil _ = True+disjoint _ Nil = True+disjoint (Tip kx _) ys = notMember kx ys+disjoint xs (Tip ky _) = notMember ky xs+disjoint t1@(Bin p1 m1 l1 r1) t2@(Bin p2 m2 l2 r2)+ | shorter m1 m2 = disjoint1+ | shorter m2 m1 = disjoint2+ | p1 == p2 = disjoint l1 l2 && disjoint r1 r2+ | otherwise = True+ where+ disjoint1 | nomatch p2 p1 m1 = True+ | zero p2 m1 = disjoint l1 t2+ | otherwise = disjoint r1 t2+ disjoint2 | nomatch p1 p2 m2 = True+ | zero p1 m2 = disjoint t1 l2+ | otherwise = disjoint t1 r2+#endif
+ src/Data/Monoid/Extra.hs view
@@ -0,0 +1,16 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE UndecidableInstances #-}++{-# OPTIONS_GHC -Wno-orphans #-}++module Data.Monoid.Extra where++import Control.Monad.State (MonadState(..))+import Data.Monoid (Ap(Ap))++instance (MonadState s m) => MonadState s (Ap m) where+ get = Ap get+ put = Ap . put+ state = Ap . state+
− src/Data/Semigroup/Monad/Extra.hs
@@ -1,22 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE UndecidableInstances #-}--{-# OPTIONS_GHC -Wno-orphans #-}--module Data.Semigroup.Monad.Extra- (module Data.Semigroup.Monad- )-where--import Control.Monad.Fix-import Control.Monad.State-import Data.Semigroup.Monad--instance MonadFix f => MonadFix (Mon f) where- mfix f = Mon (mfix (getMon . f))--instance MonadState s m => MonadState s (Mon m) where- get = Mon get- put = Mon . put- state = Mon . state
src/Data/Set/Ordered/Extra.hs view
@@ -1,5 +1,5 @@ {-|- Copyright : (C) 2019, QBayLogic B.V+ Copyright : (C) 2019,2021, QBayLogic B.V License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V <devops@qbaylogic.com> @@ -9,11 +9,7 @@ module Data.Set.Ordered.Extra ( OLSet- , ORSet- , toSetL- , toSetR , toListL- , toListR ) where import Data.Coerce (coerce)@@ -21,16 +17,6 @@ import qualified Data.Set.Ordered as OSet type OLSet a = OSet.Bias OSet.L (OSet.OSet a)-type ORSet a = OSet.Bias OSet.R (OSet.OSet a) -toSetL :: Ord a => [a] -> OLSet a-toSetL = coerce . OSet.fromList--toSetR :: Ord a => [a] -> ORSet a-toSetR = coerce . OSet.fromList- toListL :: forall a. OLSet a -> [a] toListL = toList . coerce @(OLSet a) @(OSet.OSet a)--toListR :: forall a. ORSet a -> [a]-toListR = toList . coerce @(ORSet a) @(OSet.OSet a)
+ src/Data/Text/Extra.hs view
@@ -0,0 +1,13 @@+module Data.Text.Extra+ ( showt+ , showtl+ ) where++import qualified Data.Text as TS+import qualified Data.Text.Lazy as TL++showt :: (Show a) => a -> TS.Text+showt = TS.pack . show++showtl :: (Show a) => a -> TL.Text+showtl = TL.pack . show
src/GHC/SrcLoc/Extra.hs view
@@ -5,8 +5,6 @@ -} {-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveAnyClass #-}-{-# LANGUAGE TemplateHaskell #-} {-# OPTIONS_GHC -fno-warn-orphans #-}
tests/Clash/Tests/Driver/Manifest.hs view
@@ -1,10 +1,11 @@+{-# LANGUAGE NamedFieldPuns #-}+ module Clash.Tests.Driver.Manifest where import qualified Data.Aeson as Aeson import qualified Data.Aeson.Encode.Pretty as Aeson import Data.ByteString (ByteString) import qualified Data.ByteString.Base16 as Base16-import qualified Data.ByteString.Lazy as LazyByteString import Data.Coerce (coerce) import Data.Text (Text) import qualified Data.HashMap.Strict as HashMap@@ -19,15 +20,17 @@ import Clash.Driver.Manifest import Clash.Explicit.Signal -import Debug.Trace- newtype ArbitraryText = ArbitraryText Text deriving (Show)-newtype ArbitraryManifest = ArbitraryManifest Manifest deriving (Show) instance Q.Arbitrary ArbitraryText where arbitrary = coerce Q.genValidUtf8 shrink = coerce Q.shrinkValidUtf8 +newtype ArbitraryPortDirection = ArbitraryPortDirection PortDirection deriving (Show)++instance Q.Arbitrary ArbitraryPortDirection where+ arbitrary = ArbitraryPortDirection <$> Q.elements [In, Out, InOut]+ genDigest :: Q.Gen ByteString genDigest = Base16.encode . Text.encodeUtf8 . coerce @ArbitraryText <$> Q.arbitrary @@ -53,6 +56,7 @@ ManifestPort <$> coerce @(Q.Gen ArbitraryText) Q.arbitrary <*> coerce @(Q.Gen ArbitraryText) Q.arbitrary+ <*> coerce @(Q.Gen ArbitraryPortDirection) Q.arbitrary <*> (fromIntegral @Int . abs <$> Q.arbitraryBoundedIntegral) <*> Q.elements [False, True] <*> coerce @(Q.Gen (Maybe ArbitraryText)) Q.arbitrary@@ -60,10 +64,9 @@ genManifest :: Q.Gen Manifest genManifest = Manifest- <$> Q.arbitrary -- hash+ <$> genDigest -- hash <*> Q.arbitrary -- flags- <*> Q.listOf genPort -- in ports- <*> Q.listOf genPort -- out ports+ <*> Q.listOf genPort -- ports <*> coerce @(Q.Gen [ArbitraryText]) @(Q.Gen [Text]) Q.arbitrary -- comp names <*> coerce @(Q.Gen ArbitraryText) @(Q.Gen Text) Q.arbitrary -- top name <*> Q.listOf ((,) <$> genString <*> genDigest) -- files@@ -81,12 +84,12 @@ encoded = Aeson.encodePretty manifest decoded = Aeson.eitherDecode encoded - if decoded == Right manifest then- pure True- else do- !_ <- traceM "-------------------------"- !_ <- traceM (show manifest)- !_ <- traceM (Text.unpack (Text.decodeUtf8 (LazyByteString.toStrict encoded)))- !_ <- traceM (show decoded)- pure False+ pure (decoded Q.=== Right manifest)+ , Q.testProperty "FilesManifest can decode encoded Manifest" $ do+ manifest@Manifest{fileNames} <- genManifest+ let+ encoded = Aeson.encodePretty manifest+ Right (FilesManifest fileNamesDecoded) = Aeson.eitherDecode encoded++ pure (fileNamesDecoded Q.=== fileNames) ]
tests/Test/Clash/Rewrite.hs view
@@ -1,5 +1,5 @@ {-|- Copyright : (C) 2020 QBayLogic B.V.+ Copyright : (C) 2020,2022 QBayLogic B.V. License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. <devops@qbaylogic.com> @@ -22,7 +22,7 @@ import qualified Clash.Core.Type as C import qualified Clash.Core.Var as C import Clash.Core.VarEnv (InScopeSet, emptyVarSet, emptyVarEnv, emptyInScopeSet)-import Clash.Driver.Types (DebugLevel(DebugSilent))+import Clash.Driver.Types (ClashEnv(..), ClashOpts(..), defClashOpts, debugSilent) import Clash.Rewrite.Types import Clash.Rewrite.Util (runRewrite) import Clash.Normalize.Types@@ -44,7 +44,6 @@ import qualified Data.List as List import qualified Data.HashMap.Strict as HashMap import qualified Data.Map as Map-import qualified Data.Set as Set import qualified Data.IntMap as IntMap import qualified Data.Text as Text @@ -61,35 +60,29 @@ instance Default RewriteEnv where def = RewriteEnv- { _dbgLevel=DebugSilent- , _dbgTransformations=Set.empty- , _dbgTransformationsFrom=0- , _dbgTransformationsLimit=maxBound- , _dbgRewriteHistoryFile=Nothing- , _aggressiveXOpt=False+ { _clashEnv = ClashEnv+ { envOpts = defClashOpts { opt_debug = debugSilent }+ , envTyConMap = emptyUniqMap+ , envTupleTyCons = IntMap.empty+ , envPrimitives = HashMap.empty+ , envCustomReprs = buildCustomReprs []+ } , _typeTranslator=error "_typeTranslator: NYI"- , _tcCache=emptyUniqMap- , _tupleTcCache=IntMap.empty+ , _peEvaluator=error "_peEvaluator: NYI" , _evaluator=error "_evaluator: NYI" , _topEntities=emptyVarSet- , _customReprs=buildCustomReprs []- , _fuelLimit=10 } instance Default extra => Default (RewriteState extra) where def = RewriteState { _transformCounter=0+ , _transformCounters=mempty , _bindings=emptyVarEnv , _uniqSupply=unsafePerformIO newSupply , _curFun=error "_curFun: NYI" , _nameCounter=2 , _workFreeBinders=emptyVarEnv-#if EXPERIMENTAL_EVALUATOR- , _ioHeap=error "_ioHeap: NYI"- , _ioAddr=0-#else , _globalHeap=error "_globalHeap: NYI"-#endif , _extra=def } @@ -98,17 +91,9 @@ { _normalized=emptyVarEnv , _specialisationCache=Map.empty , _specialisationHistory=emptyVarEnv- , _specialisationLimit=20 , _inlineHistory=emptyVarEnv- , _inlineLimit=20- , _inlineFunctionLimit=15- , _inlineConstantLimit=0- , _primitives=HashMap.empty , _primitiveArgs=Map.empty , _recursiveComponents=emptyVarEnv- , _newInlineStrategy=True- , _normalizeUltra=False- , _inlineWFCacheLimit=10 } instance Default InScopeSet where@@ -126,9 +111,10 @@ -- ^ Transformation to perform -> C.Term -- ^ Term to transform- -> C.Term-runSingleTransformation rwEnv rwState is trans term = t- where (t, _, _) = runR (runRewrite "" is trans term) rwEnv rwState+ -> IO C.Term+runSingleTransformation rwEnv rwState is trans term = do+ (t, _, _) <- runR (runRewrite "" is trans term) rwEnv rwState+ pure t -- | Run a single transformation with an empty environment and empty -- InScopeSet. See Default instances ^ to inspect the precise definition of@@ -138,7 +124,7 @@ -- include a type translator, evaluator, current function, or global heap. Maps, -- like the primitive and tycon map, are also empty. If the transformation under -- test needs these definitions, you should add them manually.-runSingleTransformationDef :: Default extra => Rewrite extra -> C.Term -> C.Term+runSingleTransformationDef :: Default extra => Rewrite extra -> C.Term -> IO C.Term runSingleTransformationDef = runSingleTransformation def def def
+ tools/v16-upgrade-primitives.hs view
@@ -0,0 +1,125 @@+{- Utility executable to convert "old-style" JSON primitives to "new-style"+ YAML ones. See https://github.com/clash-lang/clash-compiler/pull/2009.+-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeApplications #-}++module Main where++#if MIN_VERSION_aeson(2,0,0)+import qualified Data.Aeson.KeyMap as Aeson+import Data.ByteString.Lazy.Search (replace)+import Data.String (IsString)+#endif++import qualified Data.Aeson.Extra as AesonExtra+import qualified Data.Aeson as Aeson+import qualified Data.Yaml as Yaml+import qualified Data.ByteString.Lazy as ByteString+import qualified Data.Set as Set++import Control.Monad (forM_, when)+import Data.ByteString.Lazy (ByteString)+import System.Directory (removeFile)+import System.Environment (getArgs)+import System.FilePath.Glob (glob)++help :: String+help = unlines+ [ "Convert JSON primitive files into YAML ones. YAML files will be written to "+ , "the original filename with '.yaml' appended."+ , ""+ , "Usage:"+ , " v16-upgrade-primitives [options]... <file>..."+ , ""+ , "Options:"+ , " --dry-run Do not write YAML files."+ , " --delete Delete JSON files after writing."+ , " --help | -h Show this screen."+ , ""+ , "Example:"+ , " v16-upgrade-primitives --dry-run prims/**/*.primitives"+ ]++-- | Same as 'glob', but errors on patterns matching no files.+globOrErr :: FilePath -> IO [FilePath]+globOrErr pattern = do+ files <- glob pattern+ when (null files) (error ("Pattern does not match any files: " <> pattern))+ pure files++-- | 'concatMap', but its monadic cousin+concatMapM :: Monad m => (a -> m [b]) -> [a] -> m [b]+concatMapM f = fmap concat . mapM f++-- | Read file and output YAML ByteString+jsonToYaml :: FilePath -> IO ByteString+jsonToYaml path = do+ contents <- ByteString.readFile path+ let decoded = AesonExtra.decodeOrErrJson path contents+ pure . removeTempKey . ByteString.fromStrict . Yaml.encode . customSortOutput $ decoded++{- NOTE [Sorting YAML object keys]++'Yaml.encode' encodes object with their keys in alphabetical order.+For readability we like `name` to be at the top, and `type` to be just above `template`.++We accomplice this here by renaming those keys to something there sorts where+we like them to be. And find-and-replace those temporary names back+in the resulting ByteString.+-}+#if MIN_VERSION_aeson(2,0,0)+keySortingRenames :: IsString str => [(str,str)]+keySortingRenames =+ [ ("name", "aaaa_really_should_be_name_but_renamed_to_get_the_sorting_we_like")+ , ("type", "really_should_be_type_but_renamed_to_get_the_sorting_we_like")+ ]++customSortOutput :: Aeson.Value -> Aeson.Value+customSortOutput x = case x of+ Aeson.Object o -> Aeson.Object $ fmap customSortOutput $ renameKeys $ o+ Aeson.Array xs -> Aeson.Array $ fmap customSortOutput xs+ _ -> x+ where+ renameKeys obj = foldl renameKey obj keySortingRenames+ renameKey obj (kOld,kNew) =+ case Aeson.lookup kOld obj of+ Nothing -> obj+ Just val -> Aeson.insert kNew val (Aeson.delete kOld obj)++removeTempKey :: ByteString -> ByteString+removeTempKey inp = foldl go inp keySortingRenames+ where+ go bs (orig,temp) = replace (ByteString.toStrict temp) orig bs+#else+-- < aeson-2.0 stores keys in HashMaps, whose order we can't possibly predict.+removeTempKey :: ByteString -> ByteString+removeTempKey = id++customSortOutput:: Aeson.Value -> Aeson.Value+customSortOutput = id+#endif+++main :: IO ()+main = do+ args0 <- Set.fromList <$> getArgs++ let+ doDryRun = Set.member "--dry-run" args0+ doWrite = not doDryRun+ doDelete = Set.member "--delete" args0 && doWrite+ doHelp = Set.member "-h" args0 || Set.member "--help" args0 || Set.null args1+ args1 = foldr Set.delete args0 ["--dry-run", "--delete", "--help", "-h"]++ if doHelp then+ putStrLn help+ else do+ files <- concatMapM globOrErr (Set.toList args1)+ forM_ files $ \path -> do+ let newPath = path <> ".yaml"+ putStrLn $ "Converting " <> path <> ".."+ decoded <- jsonToYaml path+ when doWrite $ ByteString.writeFile newPath decoded+ when doDelete $ removeFile path