clash-lib 0.99.3 → 1.0.0
raw patch · 210 files changed
+23219/−14064 lines, 210 filesdep +ansi-terminaldep +binarydep +exceptionsdep −fgldep −unbound-genericsdep ~basedep ~clash-preludedep ~ghcnew-uploaderPVP ok
version bump matches the API change (PVP)
Dependencies added: ansi-terminal, binary, exceptions, hint, interpolate, temporary, text-show, vector-binary-instances
Dependencies removed: fgl, unbound-generics
Dependency ranges changed: base, clash-prelude, ghc, hashable, lens, template-haskell, text, transformers, trifecta
API changes (from Hackage documentation)
- Clash.Backend: addInclude :: Backend state => (String, Doc) -> State state ()
- Clash.Backend: nestM :: Modifier -> Modifier -> Maybe Modifier
- Clash.Core.DataCon: dataConInstArgTys :: DataCon -> [Type] -> Maybe [Type]
- Clash.Core.DataCon: instance Unbound.Generics.LocallyNameless.Alpha.Alpha Clash.Core.DataCon.DataCon
- Clash.Core.DataCon: instance Unbound.Generics.LocallyNameless.Subst.Subst a Clash.Core.DataCon.DataCon
- Clash.Core.Evaluator: instance Clash.Core.Pretty.Pretty Clash.Core.Evaluator.StackFrame
- Clash.Core.Evaluator: instance GHC.Show.Show Clash.Core.Evaluator.Heap
- Clash.Core.Evaluator: matchLit :: DataCon -> Literal -> Bool
- Clash.Core.FreeVars: termFreeIds :: Fold Term TmOccName
- Clash.Core.Literal: instance Unbound.Generics.LocallyNameless.Alpha.Alpha Clash.Core.Literal.Literal
- Clash.Core.Literal: instance Unbound.Generics.LocallyNameless.Subst.Subst a Clash.Core.Literal.Literal
- Clash.Core.Name: coerceName :: Name a -> Name b
- Clash.Core.Name: instance Data.Typeable.Internal.Typeable a => Unbound.Generics.LocallyNameless.Alpha.Alpha (Clash.Core.Name.Name a)
- Clash.Core.Name: instance Unbound.Generics.LocallyNameless.Alpha.Alpha Clash.Core.Name.NameSort
- Clash.Core.Name: instance Unbound.Generics.LocallyNameless.Subst.Subst b (Clash.Core.Name.Name a)
- Clash.Core.Name: makeOccName :: String -> Integer -> OccName a
- Clash.Core.Name: makeSystemName :: String -> Integer -> Name a
- Clash.Core.Name: name2Integer :: Name a -> Integer
- Clash.Core.Name: name2String :: Name a -> String
- Clash.Core.Name: string2InternalName :: String -> Name a
- Clash.Core.Name: string2OccName :: String -> OccName a
- Clash.Core.Name: string2SystemName :: String -> Name a
- Clash.Core.Pretty: class Pretty p
- Clash.Core.Pretty: instance Clash.Core.Pretty.Pretty (Clash.Core.Name.Name a)
- Clash.Core.Pretty: instance Clash.Core.Pretty.Pretty (Clash.Core.Name.OccName a)
- Clash.Core.Pretty: instance Clash.Core.Pretty.Pretty (Clash.Core.Var.Id, Clash.Core.Term.Term)
- Clash.Core.Pretty: instance Clash.Core.Pretty.Pretty (Clash.Core.Var.Var Clash.Core.Term.Term)
- Clash.Core.Pretty: instance Clash.Core.Pretty.Pretty (Clash.Core.Var.Var Clash.Core.Type.Type)
- Clash.Core.Pretty: instance Clash.Core.Pretty.Pretty Clash.Core.DataCon.DataCon
- Clash.Core.Pretty: instance Clash.Core.Pretty.Pretty Clash.Core.Literal.Literal
- Clash.Core.Pretty: instance Clash.Core.Pretty.Pretty Clash.Core.Term.Pat
- Clash.Core.Pretty: instance Clash.Core.Pretty.Pretty Clash.Core.Term.Term
- Clash.Core.Pretty: instance Clash.Core.Pretty.Pretty Clash.Core.TyCon.TyCon
- Clash.Core.Pretty: instance Clash.Core.Pretty.Pretty Clash.Core.Type.LitTy
- Clash.Core.Pretty: instance Clash.Core.Pretty.Pretty Clash.Core.Type.Type
- Clash.Core.Pretty: instance Clash.Core.Pretty.Pretty Data.Text.Internal.Text
- Clash.Core.Pretty: instance Clash.Core.Pretty.Pretty a => Clash.Core.Pretty.Pretty [a]
- Clash.Core.Pretty: showDoc :: Pretty p => p -> String
- Clash.Core.Subst: substBndr :: TmOccName -> Term -> LetBinding -> LetBinding
- Clash.Core.Subst: substKindWith :: [(KiOccName, Kind)] -> Kind -> Kind
- Clash.Core.Subst: substTms :: [(TmOccName, Term)] -> Term -> Term
- Clash.Core.Subst: substTyInTm :: TyOccName -> Type -> Term -> Term
- Clash.Core.Subst: substTys :: [(TyOccName, Type)] -> Type -> Type
- Clash.Core.Subst: substTysinTm :: [(TyOccName, Type)] -> Term -> Term
- Clash.Core.Term: instance GHC.Classes.Eq Clash.Core.Term.Term
- Clash.Core.Term: instance GHC.Classes.Ord Clash.Core.Term.Term
- Clash.Core.Term: instance Unbound.Generics.LocallyNameless.Alpha.Alpha Clash.Core.Term.Pat
- Clash.Core.Term: instance Unbound.Generics.LocallyNameless.Alpha.Alpha Clash.Core.Term.Term
- Clash.Core.Term: instance Unbound.Generics.LocallyNameless.Subst.Subst Clash.Core.Term.Term Clash.Core.Term.Pat
- Clash.Core.Term: instance Unbound.Generics.LocallyNameless.Subst.Subst Clash.Core.Term.Term Clash.Core.Term.Term
- Clash.Core.Term: instance Unbound.Generics.LocallyNameless.Subst.Subst Clash.Core.Type.Type Clash.Core.Term.Pat
- Clash.Core.Term: instance Unbound.Generics.LocallyNameless.Subst.Subst Clash.Core.Type.Type Clash.Core.Term.Term
- Clash.Core.Term: type TmOccName = OccName Term
- Clash.Core.TyCon: instance GHC.Classes.Ord Clash.Core.TyCon.TyCon
- Clash.Core.TyCon: instance Unbound.Generics.LocallyNameless.Alpha.Alpha Clash.Core.TyCon.AlgTyConRhs
- Clash.Core.TyCon: instance Unbound.Generics.LocallyNameless.Alpha.Alpha Clash.Core.TyCon.TyCon
- Clash.Core.TyCon: type TyConOccName = OccName TyCon
- Clash.Core.Type: applyTy :: Fresh m => HashMap TyConOccName TyCon -> Type -> KindOrType -> m Type
- Clash.Core.Type: instance GHC.Classes.Eq Clash.Core.Type.Type
- Clash.Core.Type: instance GHC.Classes.Ord Clash.Core.Type.Type
- Clash.Core.Type: instance Unbound.Generics.LocallyNameless.Alpha.Alpha Clash.Core.Type.ConstTy
- Clash.Core.Type: instance Unbound.Generics.LocallyNameless.Alpha.Alpha Clash.Core.Type.LitTy
- Clash.Core.Type: instance Unbound.Generics.LocallyNameless.Alpha.Alpha Clash.Core.Type.Type
- Clash.Core.Type: instance Unbound.Generics.LocallyNameless.Subst.Subst Clash.Core.Term.Term Clash.Core.Type.Type
- Clash.Core.Type: instance Unbound.Generics.LocallyNameless.Subst.Subst Clash.Core.Type.Type Clash.Core.Type.Type
- Clash.Core.Type: instance Unbound.Generics.LocallyNameless.Subst.Subst a Clash.Core.Type.ConstTy
- Clash.Core.Type: instance Unbound.Generics.LocallyNameless.Subst.Subst a Clash.Core.Type.LitTy
- Clash.Core.Type: type KiOccName = OccName Kind
- Clash.Core.Type: type TyOccName = OccName Type
- Clash.Core.Util: collectArgs :: Term -> (Term, [Either Term Type])
- Clash.Core.Util: mkId :: Type -> TmName -> Id
- Clash.Core.Util: mkTyVar :: Kind -> TyName -> TyVar
- Clash.Core.Var: [varKind] :: Var a -> Embed Kind
- Clash.Core.Var: instance (Data.Typeable.Internal.Typeable a, Unbound.Generics.LocallyNameless.Alpha.Alpha a) => Unbound.Generics.LocallyNameless.Alpha.Alpha (Clash.Core.Var.Var a)
- Clash.Core.Var: instance GHC.Generics.Generic b => Unbound.Generics.LocallyNameless.Subst.Subst Clash.Core.Term.Term (Clash.Core.Var.Var b)
- Clash.Core.Var: instance GHC.Generics.Generic b => Unbound.Generics.LocallyNameless.Subst.Subst Clash.Core.Type.Type (Clash.Core.Var.Var b)
- Clash.Driver: parsePrimitive :: Primitive Text -> Primitive BlackBoxTemplate
- Clash.Driver.Types: ClashException :: SrcSpan -> String -> (Maybe String) -> ClashException
- Clash.Driver.Types: [opt_allowZero] :: ClashOpts -> Bool
- Clash.Driver.Types: data ClashException
- Clash.Driver.Types: data SrcSpan
- Clash.Driver.Types: instance GHC.Exception.Exception Clash.Driver.Types.ClashException
- Clash.Driver.Types: instance GHC.Show.Show Clash.Driver.Types.ClashException
- Clash.Driver.Types: noSrcSpan :: SrcSpan
- Clash.Netlist.BlackBox: collectFilePaths :: BlackBoxContext -> BlackBoxTemplate -> NetlistMonad BlackBoxTemplate
- Clash.Netlist.BlackBox: instantiateCompName :: BlackBoxTemplate -> NetlistMonad BlackBoxTemplate
- Clash.Netlist.BlackBox.Types: C :: !Text -> Element
- Clash.Netlist.BlackBox.Types: D :: !Decl -> Element
- Clash.Netlist.BlackBox.Types: I :: !Bool -> !Int -> Element
- Clash.Netlist.BlackBox.Types: IsGated :: !Int -> Element
- Clash.Netlist.BlackBox.Types: L :: !Int -> Element
- Clash.Netlist.BlackBox.Types: N :: !Int -> Element
- Clash.Netlist.BlackBox.Types: O :: !Bool -> Element
- Clash.Netlist.BlackBox.Util: exprToText :: Expr -> Maybe Text
- Clash.Netlist.BlackBox.Util: findAndSetDataFiles :: BlackBoxContext -> [(String, FilePath)] -> BlackBoxTemplate -> ([(String, FilePath)], BlackBoxTemplate)
- Clash.Netlist.BlackBox.Util: setCompName :: Identifier -> BlackBoxTemplate -> BlackBoxTemplate
- Clash.Netlist.BlackBox.Util: setSimpleVar :: BlackBoxContext -> BlackBoxTemplate -> BlackBoxTemplate
- Clash.Netlist.Types: [_dataFiles] :: NetlistState -> [(String, FilePath)]
- Clash.Netlist.Types: dataFiles :: Lens' NetlistState [(String, FilePath)]
- Clash.Netlist.Types: instance Data.Hashable.Class.Hashable Clash.Signal.Internal.ClockKind
- Clash.Netlist.Types: instance Data.Hashable.Class.Hashable Clash.Signal.Internal.ResetKind
- Clash.Netlist.Types: instance Unbound.Generics.LocallyNameless.Fresh.Fresh Clash.Netlist.Types.NetlistMonad
- Clash.Netlist.Util: appendNumber :: (Identifier, HWType) -> Int -> (Identifier, HWType)
- Clash.Netlist.Util: filterVoid :: HWType -> HWType
- Clash.Netlist.Util: synchronizedClk :: HashMap TyConOccName TyCon -> Type -> Maybe (Identifier, Integer)
- Clash.Normalize: clockResetErrors :: SrcSpan -> (HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType)) -> HashMap TyConOccName TyCon -> Type -> [String]
- Clash.Normalize: rewriteExpr :: (String, NormRewrite) -> (String, Term) -> NormalizeSession Term
- Clash.Normalize.Strategy: constantPropgation :: NormRewrite
- Clash.Normalize.Util: isConstant :: Term -> Bool
- Clash.Normalize.Util: isConstantNotClockReset :: Term -> NormalizeSession Bool
- Clash.Normalize.Util: type CallGraph = HashMap TmOccName (HashMap TmOccName Word)
- Clash.Primitives.Types: [include] :: Primitive a -> Maybe ((Text, Text), a)
- Clash.Primitives.Types: [library] :: Primitive a -> [a]
- Clash.Primitives.Types: [primType] :: Primitive a -> !Text
- Clash.Primitives.Types: instance Data.Aeson.Types.FromJSON.FromJSON (Clash.Primitives.Types.Primitive Data.Text.Internal.Lazy.Text)
- Clash.Primitives.Types: instance GHC.Show.Show a => GHC.Show.Show (Clash.Primitives.Types.Primitive a)
- Clash.Primitives.Util: parsePrimitive :: (FromJSON a) => FilePath -> IO [a]
- Clash.Rewrite.Combinators: unsafeBottomupR :: Fresh m => Transform m -> Transform m
- Clash.Rewrite.Combinators: unsafeTopdownR :: Rewrite m -> Rewrite m
- Clash.Rewrite.Types: AppArg :: CoreContext
- Clash.Rewrite.Types: AppFun :: CoreContext
- Clash.Rewrite.Types: CaseAlt :: [TyVar] -> [Id] -> CoreContext
- Clash.Rewrite.Types: CaseScrut :: CoreContext
- Clash.Rewrite.Types: CastBody :: CoreContext
- Clash.Rewrite.Types: LamBody :: Id -> CoreContext
- Clash.Rewrite.Types: LetBinding :: Id -> [Id] -> CoreContext
- Clash.Rewrite.Types: LetBody :: [Id] -> CoreContext
- Clash.Rewrite.Types: TyAppC :: CoreContext
- Clash.Rewrite.Types: TyLamBody :: TyVar -> CoreContext
- Clash.Rewrite.Types: [_allowZero] :: RewriteEnv -> Bool
- Clash.Rewrite.Types: [runR] :: RewriteMonad extra a -> RewriteEnv -> RewriteState extra -> (a, RewriteState extra, Any)
- Clash.Rewrite.Types: allowZero :: Lens' RewriteEnv Bool
- Clash.Rewrite.Types: data CoreContext
- Clash.Rewrite.Types: instance GHC.Classes.Eq Clash.Rewrite.Types.CoreContext
- Clash.Rewrite.Types: instance GHC.Show.Show Clash.Rewrite.Types.CoreContext
- Clash.Rewrite.Types: instance Unbound.Generics.LocallyNameless.Fresh.Fresh (Clash.Rewrite.Types.RewriteMonad extra)
- Clash.Rewrite.Util: cloneVar :: (Monad m, MonadUnique m) => Name a -> m (Name a)
- Clash.Rewrite.Util: contextEnv :: [CoreContext] -> (Gamma, Delta)
- Clash.Rewrite.Util: isLambdaBodyCtx :: CoreContext -> Bool
- Clash.Rewrite.Util: isLocalVar :: Term -> RewriteMonad extra Bool
- Clash.Rewrite.Util: localFreeIds :: (Applicative f, Contravariant f) => RewriteMonad extra ((TmOccName -> f TmOccName) -> Term -> f Term)
- Clash.Rewrite.Util: mkEnv :: [CoreContext] -> RewriteMonad extra (Gamma, Delta)
- Clash.Util: dot :: (c -> d) -> (a -> b -> c) -> a -> b -> d
- Clash.Util: makeCachedT3 :: (MonadTrans t2, MonadTrans t1, MonadTrans t, Eq k, Hashable k, MonadState s m, Monad (t2 m), Monad (t1 (t2 m)), Monad (t (t1 (t2 m)))) => k -> Lens' s (HashMap k v) -> (t (t1 (t2 m))) v -> (t (t1 (t2 m))) v
- Clash.Util: makeCachedT3S :: (MonadTrans t2, MonadTrans t1, MonadTrans t, Eq k, Hashable k, MonadState s m, Monad (t2 m), Monad (t1 (t2 m)), Monad (t (t1 (t2 m))), NFData v) => k -> Lens' s (HashMap k v) -> (t (t1 (t2 m))) v -> (t (t1 (t2 m))) v
+ Clash.Annotations.BitRepresentation.ClashLib: bitsToBits :: [Bit] -> [Bit]
+ Clash.Annotations.BitRepresentation.ClashLib: coreToType' :: Type -> Either String Type'
+ Clash.Backend: addAndSetData :: Backend state => FilePath -> State state String
+ Clash.Backend: addIncludes :: Backend state => [(String, Doc)] -> State state ()
+ Clash.Backend: addMemoryDataFile :: Backend state => (String, String) -> State state ()
+ Clash.Backend: getDataFiles :: Backend state => State state [(String, FilePath)]
+ Clash.Backend: getMemoryDataFiles :: Backend state => State state [(String, String)]
+ Clash.Backend: ifThenElseExpr :: Backend state => state -> Bool
+ Clash.Backend: mkUniqueIdentifier :: Backend s => IdType -> Identifier -> State s Identifier
+ Clash.Backend: preserveSeen :: Backend s => Mon (State s) a -> Mon (State s) a
+ Clash.Backend: seenIdentifiers :: Backend state => Lens' state (HashMap Identifier Word)
+ Clash.Backend.Verilog: bit_char :: Lens' s (Maybe (Maybe Int)) -> Bit -> Mon (State s) Doc
+ Clash.Backend.Verilog: bits :: Lens' s (Maybe (Maybe Int)) -> [Bit] -> Mon (State s) Doc
+ Clash.Backend.Verilog: encodingNote :: Applicative m => HWType -> m Doc
+ Clash.Backend.Verilog: exprLit :: Lens' s (Maybe (Maybe Int)) -> Maybe (HWType, Size) -> Literal -> Mon (State s) Doc
+ Clash.Backend.Verilog: uselibs :: Monad m => [Text] -> Mon m Doc
+ Clash.Core.DataCon: [dcFieldLabels] :: DataCon -> [Text]
+ Clash.Core.DataCon: [dcUniq] :: DataCon -> {-# UNPACK #-} !Unique
+ Clash.Core.DataCon: instance Clash.Unique.Uniquable Clash.Core.DataCon.DataCon
+ Clash.Core.DataCon: instance Data.Binary.Class.Binary Clash.Core.DataCon.DataCon
+ Clash.Core.Evaluator: GPureHeap :: PureHeap -> GPureHeap
+ Clash.Core.Evaluator: GUpdate :: Id -> StackFrame
+ Clash.Core.Evaluator: Suspend :: Term -> Value
+ Clash.Core.Evaluator: Tickish :: TickInfo -> StackFrame
+ Clash.Core.Evaluator: [unGPureHeap] :: GPureHeap -> PureHeap
+ Clash.Core.Evaluator: gupdate :: Heap -> Stack -> Id -> Value -> State
+ Clash.Core.Evaluator: instance Clash.Pretty.ClashPretty Clash.Core.Evaluator.StackFrame
+ Clash.Core.Evaluator: integerLiteral :: Value -> Maybe Integer
+ Clash.Core.Evaluator: mkTickish :: Stack -> [TickInfo] -> Stack
+ Clash.Core.Evaluator: naturalLiteral :: Value -> Maybe Integer
+ Clash.Core.Evaluator: newtype GPureHeap
+ Clash.Core.Evaluator: wrapSigned :: Integer -> Integer -> Integer
+ Clash.Core.Evaluator: wrapUnsigned :: Integer -> Integer -> Integer
+ Clash.Core.FreeVars: freeIds :: Fold Term Id
+ Clash.Core.FreeVars: freeLocalIds :: Fold Term Id
+ Clash.Core.FreeVars: freeLocalVars :: Fold Term (Var a)
+ Clash.Core.FreeVars: globalIdOccursIn :: Id -> Term -> Bool
+ Clash.Core.FreeVars: globalIds :: Fold Term Id
+ 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: localVarsDoNotOccurIn :: [Var a] -> Term -> Bool
+ Clash.Core.FreeVars: noFreeVarsOfType :: Type -> Bool
+ Clash.Core.FreeVars: termFreeVars' :: (Contravariant f, Applicative f) => (forall b. Var b -> Bool) -> (Var a -> f (Var a)) -> Term -> f Term
+ Clash.Core.FreeVars: termFreeVarsX :: Fold Term (Var a)
+ Clash.Core.FreeVars: tyFVsOfTypes :: Foldable f => f Type -> VarSet
+ Clash.Core.FreeVars: typeFreeVars' :: (Contravariant f, Applicative f) => (forall b. Var b -> Bool) -> IntSet -> (Var a -> f (Var a)) -> Type -> f Type
+ Clash.Core.Literal: instance Data.Binary.Class.Binary Clash.Core.Literal.Literal
+ Clash.Core.Name: [nameUniq] :: Name a -> {-# UNPACK #-} !Unique
+ Clash.Core.Name: instance Clash.Unique.Uniquable (Clash.Core.Name.Name a)
+ Clash.Core.Name: instance Data.Binary.Class.Binary (Clash.Core.Name.Name a)
+ Clash.Core.Name: instance Data.Binary.Class.Binary Clash.Core.Name.NameSort
+ Clash.Core.Name: mkUnsafeInternalName :: Text -> Unique -> Name a
+ Clash.Core.Name: mkUnsafeSystemName :: Text -> Unique -> Name a
+ Clash.Core.Pretty: AnnContext :: CoreContext -> ClashAnnotation
+ Clash.Core.Pretty: AnnSyntax :: SyntaxElement -> ClashAnnotation
+ Clash.Core.Pretty: Keyword :: SyntaxElement
+ Clash.Core.Pretty: LitS :: SyntaxElement
+ Clash.Core.Pretty: PrettyOptions :: Bool -> Bool -> Bool -> PrettyOptions
+ Clash.Core.Pretty: Qualifier :: SyntaxElement
+ Clash.Core.Pretty: Type :: SyntaxElement
+ Clash.Core.Pretty: Unique :: SyntaxElement
+ Clash.Core.Pretty: [displayQualifiers] :: PrettyOptions -> Bool
+ Clash.Core.Pretty: [displayTypes] :: PrettyOptions -> Bool
+ Clash.Core.Pretty: [displayUniques] :: PrettyOptions -> Bool
+ Clash.Core.Pretty: class PrettyPrec p
+ Clash.Core.Pretty: data ClashAnnotation
+ Clash.Core.Pretty: data PrettyOptions
+ Clash.Core.Pretty: data SyntaxElement
+ Clash.Core.Pretty: fromPpr :: PrettyPrec a => a -> Doc ()
+ Clash.Core.Pretty: instance Clash.Core.Pretty.PrettyPrec (Clash.Core.Name.Name a)
+ Clash.Core.Pretty: instance Clash.Core.Pretty.PrettyPrec (Clash.Core.Var.Id, Clash.Core.Term.Term)
+ Clash.Core.Pretty: instance Clash.Core.Pretty.PrettyPrec (Clash.Core.Var.Var a)
+ Clash.Core.Pretty: instance Clash.Core.Pretty.PrettyPrec Clash.Core.DataCon.DataCon
+ Clash.Core.Pretty: instance Clash.Core.Pretty.PrettyPrec Clash.Core.Literal.Literal
+ Clash.Core.Pretty: instance Clash.Core.Pretty.PrettyPrec Clash.Core.Term.Pat
+ Clash.Core.Pretty: instance Clash.Core.Pretty.PrettyPrec Clash.Core.Term.Term
+ Clash.Core.Pretty: instance Clash.Core.Pretty.PrettyPrec Clash.Core.Term.TickInfo
+ Clash.Core.Pretty: instance Clash.Core.Pretty.PrettyPrec Clash.Core.TyCon.TyCon
+ Clash.Core.Pretty: instance Clash.Core.Pretty.PrettyPrec Clash.Core.Type.LitTy
+ Clash.Core.Pretty: instance Clash.Core.Pretty.PrettyPrec Clash.Core.Type.Type
+ Clash.Core.Pretty: instance Clash.Core.Pretty.PrettyPrec Data.Text.Internal.Text
+ Clash.Core.Pretty: instance Clash.Core.Pretty.PrettyPrec SrcLoc.SrcSpan
+ Clash.Core.Pretty: instance Clash.Core.Pretty.PrettyPrec a => Clash.Core.Pretty.PrettyPrec [a]
+ Clash.Core.Pretty: instance Clash.Pretty.ClashPretty (Clash.Core.Name.Name a)
+ Clash.Core.Pretty: instance Clash.Pretty.ClashPretty (Clash.Core.Var.Var a)
+ Clash.Core.Pretty: instance Clash.Pretty.ClashPretty Clash.Core.Term.Term
+ Clash.Core.Pretty: instance Clash.Pretty.ClashPretty Clash.Core.Type.Type
+ Clash.Core.Pretty: instance Data.Text.Prettyprint.Doc.Internal.Pretty Clash.Core.Type.LitTy
+ Clash.Core.Pretty: instance GHC.Classes.Eq Clash.Core.Pretty.ClashAnnotation
+ Clash.Core.Pretty: instance GHC.Classes.Eq Clash.Core.Pretty.SyntaxElement
+ Clash.Core.Pretty: instance GHC.Show.Show Clash.Core.Pretty.SyntaxElement
+ Clash.Core.Pretty: ppr' :: PrettyPrec p => PrettyOptions -> p -> ClashDoc
+ Clash.Core.Pretty: pprPrec' :: (PrettyPrec p, Monad m) => PrettyOptions -> Rational -> p -> m ClashDoc
+ Clash.Core.Pretty: showPpr :: PrettyPrec p => p -> String
+ Clash.Core.Pretty: showPpr' :: PrettyPrec p => PrettyOptions -> p -> String
+ Clash.Core.Pretty: tracePpr :: PrettyPrec p => p -> a -> a
+ Clash.Core.Pretty: tracePprId :: PrettyPrec p => p -> p
+ Clash.Core.Pretty: type ClashDoc = Doc ClashAnnotation
+ Clash.Core.Subst: Subst :: InScopeSet -> IdSubstEnv -> TvSubstEnv -> IdSubstEnv -> Subst
+ Clash.Core.Subst: TvSubst :: InScopeSet -> TvSubstEnv -> TvSubst
+ Clash.Core.Subst: [substGblEnv] :: Subst -> IdSubstEnv
+ Clash.Core.Subst: [substInScope] :: Subst -> InScopeSet
+ Clash.Core.Subst: [substTmEnv] :: Subst -> IdSubstEnv
+ Clash.Core.Subst: [substTyEnv] :: Subst -> TvSubstEnv
+ Clash.Core.Subst: aeqTerm :: Term -> Term -> Bool
+ Clash.Core.Subst: aeqType :: Type -> Type -> Bool
+ Clash.Core.Subst: data Subst
+ Clash.Core.Subst: data TvSubst
+ Clash.Core.Subst: deShadowTerm :: HasCallStack => InScopeSet -> Term -> Term
+ Clash.Core.Subst: extendGblSubstList :: Subst -> [(Id, Term)] -> Subst
+ Clash.Core.Subst: extendIdSubst :: Subst -> Id -> Term -> Subst
+ Clash.Core.Subst: extendIdSubstList :: Subst -> [(Id, Term)] -> Subst
+ Clash.Core.Subst: extendInScopeId :: Subst -> Id -> Subst
+ Clash.Core.Subst: extendInScopeIdList :: Subst -> [Id] -> Subst
+ Clash.Core.Subst: extendTvSubst :: Subst -> TyVar -> Type -> Subst
+ Clash.Core.Subst: extendTvSubstList :: Subst -> [(TyVar, Type)] -> Subst
+ Clash.Core.Subst: freshenTm :: InScopeSet -> Term -> (InScopeSet, Term)
+ Clash.Core.Subst: instance Clash.Pretty.ClashPretty Clash.Core.Subst.TvSubst
+ Clash.Core.Subst: instance GHC.Classes.Eq Clash.Core.Term.Term
+ Clash.Core.Subst: instance GHC.Classes.Eq Clash.Core.Type.Type
+ Clash.Core.Subst: instance GHC.Classes.Ord Clash.Core.Term.Term
+ Clash.Core.Subst: instance GHC.Classes.Ord Clash.Core.Type.Type
+ Clash.Core.Subst: mkSubst :: InScopeSet -> Subst
+ Clash.Core.Subst: mkTvSubst :: InScopeSet -> VarEnv Type -> Subst
+ Clash.Core.Subst: substTyInVar :: HasCallStack => Subst -> Var a -> Var a
+ Clash.Core.Subst: substTyWith :: HasCallStack => [TyVar] -> [Type] -> Type -> Type
+ Clash.Core.Subst: type TvSubstEnv = VarEnv Type
+ Clash.Core.Term: AppArg :: Maybe (Text, Int, Int) -> CoreContext
+ Clash.Core.Term: AppFun :: CoreContext
+ Clash.Core.Term: CaseAlt :: Pat -> CoreContext
+ Clash.Core.Term: CaseScrut :: CoreContext
+ Clash.Core.Term: CastBody :: CoreContext
+ Clash.Core.Term: LamBody :: Id -> CoreContext
+ Clash.Core.Term: LetBinding :: Id -> [Id] -> CoreContext
+ Clash.Core.Term: LetBody :: [Id] -> CoreContext
+ Clash.Core.Term: NameMod :: !NameMod -> !Type -> TickInfo
+ Clash.Core.Term: PrefixName :: NameMod
+ Clash.Core.Term: PrimInfo :: !Type -> !WorkInfo -> PrimInfo
+ Clash.Core.Term: SetName :: NameMod
+ Clash.Core.Term: SrcSpan :: !SrcSpan -> TickInfo
+ Clash.Core.Term: SuffixName :: NameMod
+ Clash.Core.Term: Tick :: !TickInfo -> !Term -> Term
+ Clash.Core.Term: TickC :: TickInfo -> CoreContext
+ Clash.Core.Term: TyAppC :: CoreContext
+ Clash.Core.Term: TyLamBody :: TyVar -> CoreContext
+ Clash.Core.Term: WorkAlways :: WorkInfo
+ Clash.Core.Term: WorkConstant :: WorkInfo
+ Clash.Core.Term: WorkNever :: WorkInfo
+ Clash.Core.Term: WorkVariable :: WorkInfo
+ Clash.Core.Term: [primType] :: PrimInfo -> !Type
+ Clash.Core.Term: [primWorkInfo] :: PrimInfo -> !WorkInfo
+ Clash.Core.Term: collectArgs :: Term -> (Term, [Either Term Type])
+ Clash.Core.Term: collectArgsTicks :: Term -> (Term, [Either Term Type], [TickInfo])
+ Clash.Core.Term: collectTicks :: Term -> (Term, [TickInfo])
+ Clash.Core.Term: data CoreContext
+ Clash.Core.Term: data NameMod
+ Clash.Core.Term: data PrimInfo
+ Clash.Core.Term: data TickInfo
+ Clash.Core.Term: data WorkInfo
+ Clash.Core.Term: instance Control.DeepSeq.NFData Clash.Core.Term.CoreContext
+ Clash.Core.Term: instance Control.DeepSeq.NFData Clash.Core.Term.NameMod
+ Clash.Core.Term: instance Control.DeepSeq.NFData Clash.Core.Term.PrimInfo
+ Clash.Core.Term: instance Control.DeepSeq.NFData Clash.Core.Term.TickInfo
+ Clash.Core.Term: instance Control.DeepSeq.NFData Clash.Core.Term.WorkInfo
+ Clash.Core.Term: instance Data.Binary.Class.Binary Clash.Core.Term.CoreContext
+ Clash.Core.Term: instance Data.Binary.Class.Binary Clash.Core.Term.NameMod
+ Clash.Core.Term: instance Data.Binary.Class.Binary Clash.Core.Term.Pat
+ Clash.Core.Term: instance Data.Binary.Class.Binary Clash.Core.Term.PrimInfo
+ Clash.Core.Term: instance Data.Binary.Class.Binary Clash.Core.Term.Term
+ Clash.Core.Term: instance Data.Binary.Class.Binary Clash.Core.Term.TickInfo
+ Clash.Core.Term: instance Data.Binary.Class.Binary Clash.Core.Term.WorkInfo
+ Clash.Core.Term: instance Data.Hashable.Class.Hashable Clash.Core.Term.CoreContext
+ Clash.Core.Term: instance Data.Hashable.Class.Hashable Clash.Core.Term.NameMod
+ Clash.Core.Term: instance Data.Hashable.Class.Hashable Clash.Core.Term.PrimInfo
+ Clash.Core.Term: instance Data.Hashable.Class.Hashable Clash.Core.Term.TickInfo
+ Clash.Core.Term: instance Data.Hashable.Class.Hashable Clash.Core.Term.WorkInfo
+ Clash.Core.Term: instance GHC.Classes.Eq Clash.Core.Term.CoreContext
+ Clash.Core.Term: instance GHC.Classes.Eq Clash.Core.Term.NameMod
+ Clash.Core.Term: instance GHC.Classes.Eq Clash.Core.Term.TickInfo
+ Clash.Core.Term: instance GHC.Classes.Ord Clash.Core.Term.Pat
+ Clash.Core.Term: instance GHC.Generics.Generic Clash.Core.Term.CoreContext
+ Clash.Core.Term: instance GHC.Generics.Generic Clash.Core.Term.NameMod
+ Clash.Core.Term: instance GHC.Generics.Generic Clash.Core.Term.PrimInfo
+ Clash.Core.Term: instance GHC.Generics.Generic Clash.Core.Term.TickInfo
+ Clash.Core.Term: instance GHC.Generics.Generic Clash.Core.Term.WorkInfo
+ Clash.Core.Term: instance GHC.Show.Show Clash.Core.Term.CoreContext
+ Clash.Core.Term: instance GHC.Show.Show Clash.Core.Term.NameMod
+ Clash.Core.Term: instance GHC.Show.Show Clash.Core.Term.PrimInfo
+ Clash.Core.Term: instance GHC.Show.Show Clash.Core.Term.TickInfo
+ Clash.Core.Term: instance GHC.Show.Show Clash.Core.Term.WorkInfo
+ Clash.Core.Term: isLambdaBodyCtx :: CoreContext -> Bool
+ Clash.Core.Term: isTickCtx :: CoreContext -> Bool
+ Clash.Core.Term: partitionTicks :: [TickInfo] -> ([TickInfo], [TickInfo])
+ Clash.Core.Term: primArg :: Term -> Maybe (Text, Int, Int)
+ Clash.Core.Term: type Context = [CoreContext]
+ Clash.Core.TyCon: [isClassTc] :: TyCon -> !Bool
+ Clash.Core.TyCon: [tyConUniq] :: TyCon -> {-# UNPACK #-} !Unique
+ Clash.Core.TyCon: instance Clash.Unique.Uniquable Clash.Core.TyCon.TyCon
+ Clash.Core.TyCon: instance Data.Binary.Class.Binary Clash.Core.TyCon.AlgTyConRhs
+ Clash.Core.TyCon: instance Data.Binary.Class.Binary Clash.Core.TyCon.TyCon
+ Clash.Core.TyCon: isNewTypeTc :: TyCon -> Bool
+ Clash.Core.Type: AnnType :: [Attr'] -> !Type -> Type
+ Clash.Core.Type: coreView1 :: TyConMap -> Type -> Maybe Type
+ Clash.Core.Type: instance Data.Binary.Class.Binary Clash.Core.Type.ConstTy
+ Clash.Core.Type: instance Data.Binary.Class.Binary Clash.Core.Type.LitTy
+ Clash.Core.Type: instance Data.Binary.Class.Binary Clash.Core.Type.Type
+ Clash.Core.Type: instance GHC.Classes.Eq Clash.Core.Type.ConstTy
+ Clash.Core.Type: instance GHC.Classes.Eq Clash.Core.Type.LitTy
+ Clash.Core.Type: instance GHC.Classes.Ord Clash.Core.Type.ConstTy
+ Clash.Core.Type: instance GHC.Classes.Ord Clash.Core.Type.LitTy
+ Clash.Core.Type: isClassTy :: TyConMap -> Type -> Bool
+ Clash.Core.Type: isTypeFamilyApplication :: TyConMap -> Type -> Bool
+ Clash.Core.Type: typeAttrs :: Type -> [Attr']
+ Clash.Core.Type: varAttrs :: Var a -> [Attr']
+ Clash.Core.Util: AbsurdSolution :: TypeEqSolution
+ Clash.Core.Util: NoSolution :: TypeEqSolution
+ Clash.Core.Util: Solution :: (TyVar, Type) -> TypeEqSolution
+ Clash.Core.Util: altEqs :: TyConMap -> Alt -> [(Type, Type)]
+ Clash.Core.Util: availableUniques :: Term -> [Unique]
+ Clash.Core.Util: catSolutions :: [TypeEqSolution] -> [(TyVar, Type)]
+ Clash.Core.Util: data TypeEqSolution
+ Clash.Core.Util: dataConInstArgTys :: DataCon -> [Type] -> Maybe [Type]
+ Clash.Core.Util: dataConInstArgTysE :: HasCallStack => InScopeSet -> TyConMap -> DataCon -> [Type] -> Maybe [Type]
+ Clash.Core.Util: instance GHC.Classes.Eq Clash.Core.Util.TypeEqSolution
+ Clash.Core.Util: instance GHC.Show.Show Clash.Core.Util.TypeEqSolution
+ Clash.Core.Util: isAbsurdAlt :: TyConMap -> Alt -> Bool
+ Clash.Core.Util: isAbsurdEq :: TyConMap -> (Type, Type) -> Bool
+ Clash.Core.Util: isLocalVar :: Term -> Bool
+ Clash.Core.Util: mkTicks :: Term -> [TickInfo] -> Term
+ Clash.Core.Util: mkUniqInternalId :: (Supply, InScopeSet) -> (OccName, Type) -> ((Supply, InScopeSet), Id)
+ Clash.Core.Util: mkUniqSystemId :: (Supply, InScopeSet) -> (OccName, Type) -> ((Supply, InScopeSet), Id)
+ Clash.Core.Util: mkUniqSystemTyVar :: (Supply, InScopeSet) -> (OccName, Kind) -> ((Supply, InScopeSet), TyVar)
+ Clash.Core.Util: normalizeAdd :: (Type, Type) -> Maybe (Integer, Integer, Type)
+ Clash.Core.Util: patVars :: Pat -> [Var a]
+ Clash.Core.Util: piResultTy :: TyConMap -> Type -> Type -> Type
+ Clash.Core.Util: piResultTyMaybe :: TyConMap -> Type -> Type -> Maybe Type
+ Clash.Core.Util: piResultTys :: TyConMap -> Type -> [Type] -> Type
+ Clash.Core.Util: primCo :: Type -> Term
+ Clash.Core.Util: solveAdd :: (Type, Type) -> TypeEqSolution
+ Clash.Core.Util: solveEq :: TyConMap -> (Type, Type) -> [TypeEqSolution]
+ Clash.Core.Util: solveNonAbsurds :: TyConMap -> [(Type, Type)] -> [(TyVar, Type)]
+ Clash.Core.Util: stripTicks :: Term -> Term
+ Clash.Core.Util: substArgTys :: DataCon -> [Type] -> [Type]
+ Clash.Core.Util: substGlobalsInExistentials :: HasCallStack => InScopeSet -> [TyVar] -> [(TyVar, Type)] -> [TyVar]
+ Clash.Core.Util: substInExistentials :: HasCallStack => InScopeSet -> [TyVar] -> (TyVar, Type) -> [TyVar]
+ Clash.Core.Util: substInExistentialsList :: HasCallStack => InScopeSet -> [TyVar] -> [(TyVar, Type)] -> [TyVar]
+ Clash.Core.Util: tySym :: TyConMap -> Type -> Except String String
+ Clash.Core.Util: typeEq :: TyConMap -> Type -> Maybe (Type, Type)
+ Clash.Core.Util: undefinedTm :: Type -> Term
+ Clash.Core.Var: Attr' :: String -> Attr'
+ Clash.Core.Var: BoolAttr' :: String -> Bool -> Attr'
+ Clash.Core.Var: GlobalId :: IdScope
+ Clash.Core.Var: IntegerAttr' :: String -> Integer -> Attr'
+ Clash.Core.Var: LocalId :: IdScope
+ Clash.Core.Var: StringAttr' :: String -> String -> Attr'
+ Clash.Core.Var: [idScope] :: Var a -> IdScope
+ Clash.Core.Var: [varUniq] :: Var a -> {-# UNPACK #-} !Unique
+ Clash.Core.Var: attrName :: Attr' -> String
+ Clash.Core.Var: data Attr'
+ Clash.Core.Var: data IdScope
+ Clash.Core.Var: instance Clash.Unique.Uniquable (Clash.Core.Var.Var a)
+ Clash.Core.Var: instance Control.DeepSeq.NFData Clash.Core.Var.Attr'
+ Clash.Core.Var: instance Control.DeepSeq.NFData Clash.Core.Var.IdScope
+ Clash.Core.Var: instance Data.Binary.Class.Binary (Clash.Core.Var.Var a)
+ Clash.Core.Var: instance Data.Binary.Class.Binary Clash.Core.Var.Attr'
+ Clash.Core.Var: instance Data.Binary.Class.Binary Clash.Core.Var.IdScope
+ Clash.Core.Var: instance Data.Hashable.Class.Hashable Clash.Core.Var.Attr'
+ Clash.Core.Var: instance Data.Hashable.Class.Hashable Clash.Core.Var.IdScope
+ Clash.Core.Var: instance GHC.Classes.Eq Clash.Core.Var.Attr'
+ Clash.Core.Var: instance GHC.Classes.Ord (Clash.Core.Var.Var a)
+ Clash.Core.Var: instance GHC.Classes.Ord Clash.Core.Var.Attr'
+ Clash.Core.Var: instance GHC.Generics.Generic Clash.Core.Var.Attr'
+ Clash.Core.Var: instance GHC.Generics.Generic Clash.Core.Var.IdScope
+ Clash.Core.Var: instance GHC.Show.Show Clash.Core.Var.Attr'
+ Clash.Core.Var: instance GHC.Show.Show Clash.Core.Var.IdScope
+ Clash.Core.Var: isGlobalId :: Var a -> Bool
+ Clash.Core.Var: isLocalId :: Var a -> Bool
+ Clash.Core.Var: mkGlobalId :: Type -> TmName -> Id
+ Clash.Core.Var: mkId :: Type -> IdScope -> TmName -> Id
+ Clash.Core.Var: mkLocalId :: Type -> TmName -> Id
+ Clash.Core.Var: mkTyVar :: Kind -> TyName -> TyVar
+ Clash.Core.Var: setIdScope :: IdScope -> Var a -> Var a
+ Clash.Core.Var: setVarType :: Var a -> Type -> Var a
+ Clash.Core.Var: setVarUnique :: Var a -> Unique -> Var a
+ Clash.Core.VarEnv: data InScopeSet
+ Clash.Core.VarEnv: data RnEnv
+ Clash.Core.VarEnv: delVarEnv :: VarEnv a -> Var b -> VarEnv a
+ Clash.Core.VarEnv: delVarEnvList :: VarEnv a -> [Var b] -> VarEnv a
+ Clash.Core.VarEnv: delVarSetByKey :: Unique -> VarSet -> VarSet
+ Clash.Core.VarEnv: elemInScopeSet :: Var a -> InScopeSet -> Bool
+ Clash.Core.VarEnv: elemVarEnv :: Var a -> VarEnv b -> Bool
+ Clash.Core.VarEnv: elemVarSet :: Var a -> VarSet -> Bool
+ Clash.Core.VarEnv: eltsVarEnv :: VarEnv a -> [a]
+ Clash.Core.VarEnv: emptyInScopeSet :: InScopeSet
+ Clash.Core.VarEnv: emptyVarEnv :: VarEnv a
+ Clash.Core.VarEnv: emptyVarSet :: VarSet
+ Clash.Core.VarEnv: extendInScopeSet :: InScopeSet -> Var a -> InScopeSet
+ Clash.Core.VarEnv: extendInScopeSetList :: InScopeSet -> [Var a] -> InScopeSet
+ Clash.Core.VarEnv: extendVarEnv :: Var b -> a -> VarEnv a -> VarEnv a
+ Clash.Core.VarEnv: extendVarEnvList :: VarEnv a -> [(Var b, a)] -> VarEnv a
+ Clash.Core.VarEnv: extendVarEnvWith :: Var b -> a -> (a -> a -> a) -> VarEnv a -> VarEnv a
+ Clash.Core.VarEnv: instance Clash.Pretty.ClashPretty Clash.Core.VarEnv.InScopeSet
+ Clash.Core.VarEnv: instance Data.Binary.Class.Binary Clash.Core.VarEnv.InScopeSet
+ Clash.Core.VarEnv: instance GHC.Generics.Generic Clash.Core.VarEnv.InScopeSet
+ Clash.Core.VarEnv: lookupInScope :: InScopeSet -> Var a -> Maybe (Var Any)
+ Clash.Core.VarEnv: lookupVarEnv :: Var b -> VarEnv a -> Maybe a
+ Clash.Core.VarEnv: lookupVarEnv' :: VarEnv a -> Var b -> a
+ Clash.Core.VarEnv: mapMaybeVarEnv :: (a -> Maybe b) -> VarEnv a -> VarEnv b
+ Clash.Core.VarEnv: mapVarEnv :: (a -> b) -> VarEnv a -> VarEnv b
+ Clash.Core.VarEnv: mkInScopeSet :: VarSet -> InScopeSet
+ Clash.Core.VarEnv: mkRnEnv :: InScopeSet -> RnEnv
+ Clash.Core.VarEnv: mkVarEnv :: [(Var a, b)] -> VarEnv b
+ Clash.Core.VarEnv: mkVarSet :: [Var a] -> VarSet
+ Clash.Core.VarEnv: notElemInScopeSet :: Var a -> InScopeSet -> Bool
+ Clash.Core.VarEnv: notElemVarEnv :: Var a -> VarEnv b -> Bool
+ Clash.Core.VarEnv: notElemVarSet :: Var a -> VarSet -> Bool
+ Clash.Core.VarEnv: nullVarEnv :: VarEnv a -> Bool
+ Clash.Core.VarEnv: rnOccLId :: RnEnv -> Id -> Id
+ Clash.Core.VarEnv: rnOccLTy :: RnEnv -> TyVar -> TyVar
+ Clash.Core.VarEnv: rnOccRId :: RnEnv -> Id -> Id
+ Clash.Core.VarEnv: rnOccRTy :: RnEnv -> TyVar -> TyVar
+ Clash.Core.VarEnv: rnTmBndr :: RnEnv -> Id -> Id -> RnEnv
+ Clash.Core.VarEnv: rnTmBndrs :: RnEnv -> [Id] -> [Id] -> RnEnv
+ Clash.Core.VarEnv: rnTyBndr :: RnEnv -> TyVar -> TyVar -> RnEnv
+ Clash.Core.VarEnv: rnTyBndrs :: RnEnv -> [TyVar] -> [TyVar] -> RnEnv
+ Clash.Core.VarEnv: type VarEnv a = UniqMap a
+ Clash.Core.VarEnv: type VarSet = UniqSet (Var Any)
+ Clash.Core.VarEnv: unionInScope :: InScopeSet -> InScopeSet -> InScopeSet
+ Clash.Core.VarEnv: unionVarEnv :: VarEnv a -> VarEnv a -> VarEnv a
+ Clash.Core.VarEnv: unionVarEnvWith :: (a -> a -> a) -> VarEnv a -> VarEnv a -> VarEnv a
+ Clash.Core.VarEnv: unionVarSet :: VarSet -> VarSet -> VarSet
+ Clash.Core.VarEnv: uniqAway :: InScopeSet -> Var a -> Var a
+ Clash.Core.VarEnv: unitVarEnv :: Var b -> a -> VarEnv a
+ Clash.Core.VarEnv: unitVarSet :: Var a -> VarSet
+ Clash.Core.VarEnv: varSetInScope :: VarSet -> InScopeSet -> Bool
+ Clash.Driver: compilePrimitive :: [FilePath] -> [FilePath] -> FilePath -> ResolvedPrimitive -> IO CompiledPrimitive
+ Clash.Driver: getClashModificationDate :: IO UTCTime
+ Clash.Driver: loadImportAndInterpret :: (MonadIO m, MonadMask m) => [String] -> [String] -> String -> ModuleName -> String -> String -> m (Either InterpreterError a)
+ Clash.Driver: processHintError :: Monad m => String -> Text -> (t -> r) -> Either InterpreterError t -> m r
+ Clash.Driver: writeMemoryDataFiles :: FilePath -> [(String, String)] -> IO ()
+ Clash.Driver.Types: DebugSilent :: DebugLevel
+ Clash.Driver.Types: [opt_checkIDir] :: ClashOpts -> Bool
+ Clash.Driver.Types: [opt_color] :: ClashOpts -> OverridingBool
+ Clash.Driver.Types: [opt_componentPrefix] :: ClashOpts -> Maybe String
+ Clash.Driver.Types: [opt_escapedIds] :: ClashOpts -> Bool
+ Clash.Driver.Types: [opt_forceUndefined] :: ClashOpts -> Maybe (Maybe Int)
+ Clash.Driver.Types: [opt_newInlineStrat] :: ClashOpts -> Bool
+ Clash.Driver.Types: [opt_primWarn] :: ClashOpts -> Bool
+ Clash.Driver.Types: [opt_ultra] :: ClashOpts -> Bool
+ Clash.Driver.Types: defClashOpts :: ClashOpts
+ Clash.Netlist: isWriteToBiSignalPrimitive :: Term -> Bool
+ Clash.Netlist: patPos :: CustomReprs -> Pat -> Int
+ Clash.Netlist: reorderCustom :: TyConMap -> CustomReprs -> Type -> [(Pat, Term)] -> [(Pat, Term)]
+ Clash.Netlist: reorderDefault :: [(Pat, Term)] -> [(Pat, Term)]
+ Clash.Netlist.BlackBox: extractPrimWarnOrFail :: Text -> NetlistMonad CompiledPrimitive
+ Clash.Netlist.BlackBox: isLiteral :: Term -> Bool
+ Clash.Netlist.BlackBox: warn :: ClashOpts -> String -> IO ()
+ Clash.Netlist.BlackBox.Types: ActiveEdge :: !ActiveEdge -> !Int -> Element
+ Clash.Netlist.BlackBox.Types: ArgGen :: !Int -> !Int -> Element
+ Clash.Netlist.BlackBox.Types: BlackBoxMeta :: Bool -> TemplateKind -> [BlackBoxTemplate] -> [BlackBoxTemplate] -> [((Text, Text), BlackBox)] -> BlackBoxMeta
+ Clash.Netlist.BlackBox.Types: CmpLE :: !Element -> !Element -> Element
+ Clash.Netlist.BlackBox.Types: Component :: !Decl -> Element
+ Clash.Netlist.BlackBox.Types: Const :: !Int -> Element
+ Clash.Netlist.BlackBox.Types: DevNull :: [Element] -> Element
+ Clash.Netlist.BlackBox.Types: IsActiveEnable :: !Int -> Element
+ Clash.Netlist.BlackBox.Types: IsActiveHigh :: !Int -> Element
+ Clash.Netlist.BlackBox.Types: IsInitDefined :: !Int -> Element
+ Clash.Netlist.BlackBox.Types: Lit :: !Int -> Element
+ Clash.Netlist.BlackBox.Types: MaxIndex :: !Element -> Element
+ Clash.Netlist.BlackBox.Types: Name :: !Int -> Element
+ Clash.Netlist.BlackBox.Types: Period :: !Int -> Element
+ Clash.Netlist.BlackBox.Types: Quartus :: HdlSyn
+ Clash.Netlist.BlackBox.Types: Repeat :: [Element] -> [Element] -> Element
+ Clash.Netlist.BlackBox.Types: Result :: !Bool -> Element
+ Clash.Netlist.BlackBox.Types: TDecl :: TemplateKind
+ Clash.Netlist.BlackBox.Types: TExpr :: TemplateKind
+ Clash.Netlist.BlackBox.Types: Tag :: !Int -> Element
+ Clash.Netlist.BlackBox.Types: Template :: [Element] -> [Element] -> Element
+ Clash.Netlist.BlackBox.Types: Text :: !Text -> Element
+ Clash.Netlist.BlackBox.Types: [bbImports] :: BlackBoxMeta -> [BlackBoxTemplate]
+ Clash.Netlist.BlackBox.Types: [bbIncludes] :: BlackBoxMeta -> [((Text, Text), BlackBox)]
+ Clash.Netlist.BlackBox.Types: [bbKind] :: BlackBoxMeta -> TemplateKind
+ Clash.Netlist.BlackBox.Types: [bbLibrary] :: BlackBoxMeta -> [BlackBoxTemplate]
+ Clash.Netlist.BlackBox.Types: [bbOutputReg] :: BlackBoxMeta -> Bool
+ Clash.Netlist.BlackBox.Types: data BlackBoxMeta
+ Clash.Netlist.BlackBox.Types: data TemplateKind
+ Clash.Netlist.BlackBox.Types: emptyBlackBoxMeta :: BlackBoxMeta
+ Clash.Netlist.BlackBox.Types: instance Control.DeepSeq.NFData Clash.Netlist.BlackBox.Types.Decl
+ Clash.Netlist.BlackBox.Types: instance Control.DeepSeq.NFData Clash.Netlist.BlackBox.Types.Element
+ Clash.Netlist.BlackBox.Types: instance Control.DeepSeq.NFData Clash.Netlist.BlackBox.Types.HdlSyn
+ Clash.Netlist.BlackBox.Types: instance Control.DeepSeq.NFData Clash.Netlist.BlackBox.Types.TemplateKind
+ Clash.Netlist.BlackBox.Types: instance Data.Binary.Class.Binary Clash.Netlist.BlackBox.Types.Decl
+ Clash.Netlist.BlackBox.Types: instance Data.Binary.Class.Binary Clash.Netlist.BlackBox.Types.Element
+ Clash.Netlist.BlackBox.Types: instance Data.Binary.Class.Binary Clash.Netlist.BlackBox.Types.HdlSyn
+ Clash.Netlist.BlackBox.Types: instance Data.Binary.Class.Binary Clash.Netlist.BlackBox.Types.TemplateKind
+ Clash.Netlist.BlackBox.Types: instance Data.Hashable.Class.Hashable Clash.Netlist.BlackBox.Types.Decl
+ Clash.Netlist.BlackBox.Types: instance Data.Hashable.Class.Hashable Clash.Netlist.BlackBox.Types.Element
+ Clash.Netlist.BlackBox.Types: instance Data.Hashable.Class.Hashable Clash.Netlist.BlackBox.Types.HdlSyn
+ Clash.Netlist.BlackBox.Types: instance Data.Hashable.Class.Hashable Clash.Netlist.BlackBox.Types.TemplateKind
+ Clash.Netlist.BlackBox.Types: instance GHC.Classes.Eq Clash.Netlist.BlackBox.Types.TemplateKind
+ Clash.Netlist.BlackBox.Types: instance GHC.Generics.Generic Clash.Netlist.BlackBox.Types.Decl
+ Clash.Netlist.BlackBox.Types: instance GHC.Generics.Generic Clash.Netlist.BlackBox.Types.Element
+ Clash.Netlist.BlackBox.Types: instance GHC.Generics.Generic Clash.Netlist.BlackBox.Types.HdlSyn
+ Clash.Netlist.BlackBox.Types: instance GHC.Generics.Generic Clash.Netlist.BlackBox.Types.TemplateKind
+ Clash.Netlist.BlackBox.Types: instance GHC.Show.Show Clash.Netlist.BlackBox.Types.TemplateKind
+ Clash.Netlist.BlackBox.Types: type BlackBoxFunction = Bool " Indicates whether caller needs a declaration. If set, the function is still free to return an expression, but the caller will convert it to a declaration." -> Text " Name of primitive" -> [Either Term Type] " Arguments" -> Type " Result type" -> NetlistMonad (Either String (BlackBoxMeta, BlackBox))
+ Clash.Netlist.BlackBox.Util: elementToText :: BlackBoxContext -> Element -> Either String Text
+ Clash.Netlist.BlackBox.Util: elementsToText :: BlackBoxContext -> [Element] -> Either String Text
+ Clash.Netlist.BlackBox.Util: exprToString :: Expr -> Maybe String
+ Clash.Netlist.BlackBox.Util: inputHole :: Element -> Maybe Int
+ Clash.Netlist.BlackBox.Util: onBlackBox :: (BlackBoxTemplate -> r) -> (BBName -> BBHash -> TemplateFunction -> r) -> BlackBox -> r
+ Clash.Netlist.BlackBox.Util: selectNewName :: Foldable t => t String -> FilePath -> String
+ Clash.Netlist.BlackBox.Util: stripVoid :: HWType -> HWType
+ Clash.Netlist.BlackBox.Util: usedVariables :: Expr -> [Identifier]
+ Clash.Netlist.BlackBox.Util: walkElement :: (Element -> Maybe a) -> Element -> [a]
+ Clash.Netlist.Types: Annotated :: [Attr'] -> !HWType -> HWType
+ Clash.Netlist.Types: BBFunction :: BBName -> BBHash -> TemplateFunction -> BlackBox
+ Clash.Netlist.Types: BBTemplate :: BlackBoxTemplate -> BlackBox
+ Clash.Netlist.Types: BiDirectional :: !PortDirection -> !HWType -> HWType
+ Clash.Netlist.Types: BitVecLit :: !Integer -> !Integer -> Literal
+ Clash.Netlist.Types: Comp :: EntityOrComponent
+ Clash.Netlist.Types: CustomSP :: !Identifier -> !DataRepr' -> !Size -> [(ConstrRepr', Identifier, [HWType])] -> HWType
+ Clash.Netlist.Types: CustomSum :: !Identifier -> !DataRepr' -> !Size -> [(ConstrRepr', Identifier)] -> HWType
+ Clash.Netlist.Types: Empty :: EntityOrComponent
+ Clash.Netlist.Types: Entity :: EntityOrComponent
+ Clash.Netlist.Types: FilteredHWType :: HWType -> [[(IsVoid, FilteredHWType)]] -> FilteredHWType
+ Clash.Netlist.Types: IfThenElse :: Expr -> Expr -> Expr -> Expr
+ Clash.Netlist.Types: Integer :: HWType
+ Clash.Netlist.Types: KnownDomain :: !Identifier -> !Integer -> !ActiveEdge -> !ResetKind -> !InitBehavior -> !ResetPolarity -> HWType
+ Clash.Netlist.Types: NetlistEnv :: Identifier -> Identifier -> Maybe Identifier -> NetlistEnv
+ Clash.Netlist.Types: Sliced :: (HWType, Int, Int) -> Modifier
+ Clash.Netlist.Types: TickDecl :: Comment -> Declaration
+ Clash.Netlist.Types: [TemplateFunction] :: [Int] -> (BlackBoxContext -> Bool) -> (forall s. Backend s => BlackBoxContext -> State s Doc) -> TemplateFunction
+ Clash.Netlist.Types: [_backEndITE] :: NetlistState -> Bool
+ Clash.Netlist.Types: [_clashOpts] :: NetlistState -> ClashOpts
+ Clash.Netlist.Types: [_componentPrefix] :: NetlistState -> (Maybe Identifier, Maybe Identifier)
+ Clash.Netlist.Types: [_customReprs] :: NetlistState -> CustomReprs
+ Clash.Netlist.Types: [_htyCache] :: NetlistState -> HWMap
+ Clash.Netlist.Types: [_isTestBench] :: NetlistState -> Bool
+ Clash.Netlist.Types: [_prefixName] :: NetlistEnv -> Identifier
+ Clash.Netlist.Types: [_seenPrimitives] :: NetlistState -> Set Text
+ Clash.Netlist.Types: [_setName] :: NetlistEnv -> Maybe Identifier
+ Clash.Netlist.Types: [_suffixName] :: NetlistEnv -> Identifier
+ Clash.Netlist.Types: [bbCompName] :: BlackBoxContext -> Identifier
+ Clash.Netlist.Types: [bbName] :: BlackBoxContext -> Text
+ Clash.Netlist.Types: backEndITE :: Lens' NetlistState Bool
+ Clash.Netlist.Types: clashOpts :: Lens' NetlistState ClashOpts
+ Clash.Netlist.Types: componentPrefix :: Lens' NetlistState (Maybe Identifier, Maybe Identifier)
+ Clash.Netlist.Types: customReprs :: Lens' NetlistState CustomReprs
+ Clash.Netlist.Types: data BlackBox
+ Clash.Netlist.Types: data EntityOrComponent
+ Clash.Netlist.Types: data FilteredHWType
+ Clash.Netlist.Types: data NetlistEnv
+ Clash.Netlist.Types: data TemplateFunction
+ Clash.Netlist.Types: htyCache :: Lens' NetlistState HWMap
+ Clash.Netlist.Types: hwTypeAttrs :: HWType -> [Attr']
+ Clash.Netlist.Types: instance Control.DeepSeq.NFData Clash.Netlist.Types.BlackBox
+ Clash.Netlist.Types: instance Control.DeepSeq.NFData Clash.Netlist.Types.PortDirection
+ Clash.Netlist.Types: instance Control.DeepSeq.NFData Clash.Netlist.Types.TemplateFunction
+ Clash.Netlist.Types: instance Control.Monad.Fail.MonadFail Clash.Netlist.Types.NetlistMonad
+ Clash.Netlist.Types: instance Control.Monad.Reader.Class.MonadReader Clash.Netlist.Types.NetlistEnv Clash.Netlist.Types.NetlistMonad
+ Clash.Netlist.Types: instance Data.Binary.Class.Binary Clash.Netlist.Types.BlackBox
+ Clash.Netlist.Types: instance Data.Binary.Class.Binary Clash.Netlist.Types.TemplateFunction
+ Clash.Netlist.Types: instance Data.Hashable.Class.Hashable Clash.Netlist.Types.PortDirection
+ Clash.Netlist.Types: instance GHC.Classes.Eq Clash.Netlist.Types.FilteredHWType
+ Clash.Netlist.Types: instance GHC.Classes.Eq Clash.Netlist.Types.PortDirection
+ Clash.Netlist.Types: instance GHC.Classes.Ord Clash.Netlist.Types.PortDirection
+ Clash.Netlist.Types: instance GHC.Generics.Generic Clash.Netlist.Types.BlackBox
+ Clash.Netlist.Types: instance GHC.Generics.Generic Clash.Netlist.Types.PortDirection
+ Clash.Netlist.Types: instance GHC.Show.Show Clash.Netlist.Types.BlackBox
+ Clash.Netlist.Types: instance GHC.Show.Show Clash.Netlist.Types.EntityOrComponent
+ Clash.Netlist.Types: instance GHC.Show.Show Clash.Netlist.Types.FilteredHWType
+ Clash.Netlist.Types: instance Language.Haskell.TH.Syntax.Lift Clash.Netlist.Types.Bit
+ Clash.Netlist.Types: isTestBench :: Lens' NetlistState Bool
+ Clash.Netlist.Types: pattern NetDecl :: Maybe Comment -> Identifier -> HWType -> Declaration
+ Clash.Netlist.Types: prefixName :: Lens' NetlistEnv Identifier
+ Clash.Netlist.Types: seenPrimitives :: Lens' NetlistState (Set Text)
+ Clash.Netlist.Types: setName :: Lens' NetlistEnv (Maybe Identifier)
+ Clash.Netlist.Types: suffixName :: Lens' NetlistEnv Identifier
+ Clash.Netlist.Types: toBit :: Integer -> Integer -> Bit
+ Clash.Netlist.Types: type BBHash = Int
+ Clash.Netlist.Types: type BBName = String
+ Clash.Netlist.Types: type Comment = Text
+ Clash.Netlist.Types: type HWMap = HashMap Type (Either String FilteredHWType)
+ Clash.Netlist.Types: type IsVoid = Bool
+ Clash.Netlist.Util: affixName :: Identifier -> NetlistMonad Identifier
+ Clash.Netlist.Util: bindsExistentials :: [TyVar] -> [Var a] -> Bool
+ Clash.Netlist.Util: collectPortNames :: TopEntity -> [Identifier]
+ Clash.Netlist.Util: collectPortNames' :: [String] -> PortName -> [Identifier]
+ Clash.Netlist.Util: containsBiSignalIn :: HWType -> Bool
+ Clash.Netlist.Util: coreTypeToHWType' :: (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> CustomReprs -> TyConMap -> Type -> State HWMap (Either String HWType)
+ Clash.Netlist.Util: coreTypeToHWTypeM' :: Type -> NetlistMonad (Maybe HWType)
+ Clash.Netlist.Util: filterVoidPorts :: FilteredHWType -> PortName -> PortName
+ Clash.Netlist.Util: fixCustomRepr :: CustomReprs -> Type -> HWType -> HWType
+ Clash.Netlist.Util: flattenFiltered :: FilteredHWType -> [[Bool]]
+ Clash.Netlist.Util: genTopComponentName :: Bool -> (IdType -> Identifier -> Identifier) -> (Maybe Identifier, Maybe Identifier) -> Maybe TopEntity -> Id -> Identifier
+ Clash.Netlist.Util: id2identifier :: Id -> Identifier
+ Clash.Netlist.Util: id2type :: Id -> Type
+ Clash.Netlist.Util: idToInPort :: Id -> NetlistMonad (Maybe (Identifier, HWType))
+ Clash.Netlist.Util: idToOutPort :: Id -> NetlistMonad (Maybe (Identifier, HWType))
+ Clash.Netlist.Util: isBiSignalIn :: HWType -> Bool
+ Clash.Netlist.Util: isBiSignalOut :: HWType -> Bool
+ Clash.Netlist.Util: isFilteredVoid :: FilteredHWType -> Bool
+ Clash.Netlist.Util: iteAlts :: HWType -> [Alt] -> Maybe (Term, Term)
+ Clash.Netlist.Util: mkOutput' :: Maybe PortName -> (Identifier, HWType) -> NetlistMonad ([(Identifier, HWType)], [Declaration], Identifier)
+ Clash.Netlist.Util: mkTopOutput' :: Maybe Identifier -> [(Identifier, Identifier)] -> Maybe PortName -> (Identifier, HWType) -> NetlistMonad ([(Identifier, Identifier)], ([(Identifier, Identifier, HWType)], [Declaration], Either Identifier (Identifier, HWType)))
+ Clash.Netlist.Util: nestM :: Modifier -> Modifier -> Maybe Modifier
+ Clash.Netlist.Util: originalIndices :: [Bool] -> [Int]
+ Clash.Netlist.Util: packSP :: CustomReprs -> (Text, c) -> (ConstrRepr', Text, c)
+ Clash.Netlist.Util: packSum :: CustomReprs -> Text -> (ConstrRepr', Text)
+ Clash.Netlist.Util: prefixParent :: String -> PortName -> PortName
+ Clash.Netlist.Util: stripAttributes :: HWType -> ([Attr'], HWType)
+ Clash.Netlist.Util: stripFiltered :: FilteredHWType -> HWType
+ Clash.Netlist.Util: throwAnnotatedSplitError :: String -> String -> NetlistMonad a
+ Clash.Netlist.Util: unsafeCoreTypeToHWType' :: SrcSpan -> String -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> CustomReprs -> TyConMap -> Type -> State HWMap HWType
+ Clash.Netlist.Util: unsafeCoreTypeToHWTypeM' :: String -> Type -> NetlistMonad HWType
+ Clash.Netlist.Util: withTicks :: [TickInfo] -> ([Declaration] -> NetlistMonad a) -> NetlistMonad a
+ Clash.Normalize.PrimitiveReductions: reduceIndex_int :: InScopeSet -> Integer -> Type -> Term -> Term -> NormalizeSession Term
+ Clash.Normalize.PrimitiveReductions: reduceReplace_int :: InScopeSet -> Integer -> Type -> Type -> Term -> Term -> Term -> NormalizeSession Term
+ Clash.Normalize.PrimitiveReductions: reduceReverse :: InScopeSet -> Integer -> Type -> Term -> NormalizeSession Term
+ Clash.Normalize.Strategy: constantPropagation :: NormRewrite
+ Clash.Normalize.Strategy: topdownRR :: Rewrite extra -> Rewrite extra
+ Clash.Normalize.Transformations: appPropFast :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations: caseElemNonReachable :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations: elemExistentials :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations: etaExpandSyn :: HasCallStack => NormRewrite
+ Clash.Normalize.Types: [_newInlineStrategy] :: NormalizeState -> Bool
+ Clash.Normalize.Types: [_normalizeUltra] :: NormalizeState -> Bool
+ Clash.Normalize.Types: [_primitiveArgs] :: NormalizeState -> Map Text (Set Int)
+ Clash.Normalize.Types: newInlineStrategy :: Lens' NormalizeState Bool
+ Clash.Normalize.Types: normalizeUltra :: Lens' NormalizeState Bool
+ Clash.Normalize.Types: primitiveArgs :: Lens' NormalizeState (Map Text (Set Int))
+ Clash.Normalize.Util: canConstantSpec :: Term -> RewriteMonad NormalizeState Bool
+ Clash.Normalize.Util: isConstantArg :: Text -> Int -> RewriteMonad NormalizeState Bool
+ Clash.Normalize.Util: isNonRecursiveGlobalVar :: Term -> NormalizeSession Bool
+ Clash.Normalize.Util: normalizeTopLvlBndr :: Id -> (Id, SrcSpan, InlineSpec, Term) -> NormalizeSession (Id, SrcSpan, InlineSpec, Term)
+ Clash.Normalize.Util: removedTm :: Type -> Term
+ Clash.Normalize.Util: rewriteExpr :: (String, NormRewrite) -> (String, Term) -> (Id, SrcSpan) -> NormalizeSession Term
+ Clash.Normalize.Util: shouldReduce :: Context -> RewriteMonad NormalizeState Bool
+ Clash.Pretty: clashPretty :: ClashPretty a => a -> Doc ()
+ Clash.Pretty: class ClashPretty a
+ Clash.Pretty: fromPretty :: Pretty a => a -> Doc ()
+ Clash.Pretty: removeAnnotations :: Doc ann -> Doc ()
+ Clash.Pretty: showDoc :: Doc ann -> String
+ Clash.Primitives.GHC.Int: intTF :: BlackBoxFunction
+ Clash.Primitives.GHC.Literal: assign :: Element -> [Element] -> [Element]
+ Clash.Primitives.GHC.Literal: literalTF :: Text -> (Bool -> [Either Term Type] -> Int -> (BlackBoxMeta, BlackBox)) -> BlackBoxFunction
+ Clash.Primitives.GHC.Literal: signed :: Element -> [Element]
+ Clash.Primitives.GHC.Literal: signedLiteral :: Int -> Integer -> Element
+ Clash.Primitives.GHC.Literal: unsigned :: Element -> [Element]
+ Clash.Primitives.GHC.Literal: unsignedLiteral :: Int -> Integer -> Element
+ Clash.Primitives.GHC.Word: wordTF :: BlackBoxFunction
+ Clash.Primitives.Intel.ClockGen: alteraPllTF :: TemplateFunction
+ Clash.Primitives.Intel.ClockGen: alteraPllTemplate :: Backend s => BlackBoxContext -> State s Doc
+ Clash.Primitives.Intel.ClockGen: altpllTF :: TemplateFunction
+ Clash.Primitives.Intel.ClockGen: altpllTemplate :: Backend s => BlackBoxContext -> State s Doc
+ Clash.Primitives.Sized.Vector: indexIntVerilog :: BlackBoxFunction
+ Clash.Primitives.Sized.Vector: indexIntVerilogTF :: TemplateFunction
+ Clash.Primitives.Sized.Vector: indexIntVerilogTemplate :: Backend s => BlackBoxContext -> State s Doc
+ Clash.Primitives.Types: BlackBoxFunctionName :: [String] -> String -> BlackBoxFunctionName
+ Clash.Primitives.Types: BlackBoxHaskell :: !Text -> WorkInfo -> BlackBoxFunctionName -> d -> Primitive a b c d
+ Clash.Primitives.Types: TDecl :: TemplateKind
+ Clash.Primitives.Types: TExpr :: TemplateKind
+ Clash.Primitives.Types: TFile :: FilePath -> TemplateSource
+ Clash.Primitives.Types: THaskell :: TemplateFormat
+ Clash.Primitives.Types: TInline :: Text -> TemplateSource
+ Clash.Primitives.Types: TTemplate :: TemplateFormat
+ Clash.Primitives.Types: [functionName] :: Primitive a b c d -> BlackBoxFunctionName
+ Clash.Primitives.Types: [function] :: Primitive a b c d -> d
+ Clash.Primitives.Types: [includes] :: Primitive a b c d -> [((Text, Text), b)]
+ Clash.Primitives.Types: [kind] :: Primitive a b c d -> TemplateKind
+ Clash.Primitives.Types: [libraries] :: Primitive a b c d -> [a]
+ Clash.Primitives.Types: [primSort] :: Primitive a b c d -> !Text
+ Clash.Primitives.Types: [warning] :: Primitive a b c d -> c
+ Clash.Primitives.Types: [workInfo] :: Primitive a b c d -> WorkInfo
+ Clash.Primitives.Types: data BlackBoxFunctionName
+ Clash.Primitives.Types: data TemplateFormat
+ Clash.Primitives.Types: data TemplateKind
+ Clash.Primitives.Types: data TemplateSource
+ Clash.Primitives.Types: instance (Control.DeepSeq.NFData c, Control.DeepSeq.NFData a, Control.DeepSeq.NFData b, Control.DeepSeq.NFData d) => Control.DeepSeq.NFData (Clash.Primitives.Types.Primitive a b c d)
+ Clash.Primitives.Types: instance (Data.Binary.Class.Binary c, Data.Binary.Class.Binary a, Data.Binary.Class.Binary b, Data.Binary.Class.Binary d) => Data.Binary.Class.Binary (Clash.Primitives.Types.Primitive a b c d)
+ Clash.Primitives.Types: instance (Data.Hashable.Class.Hashable c, Data.Hashable.Class.Hashable a, Data.Hashable.Class.Hashable b, Data.Hashable.Class.Hashable d) => Data.Hashable.Class.Hashable (Clash.Primitives.Types.Primitive a b c d)
+ Clash.Primitives.Types: instance (GHC.Show.Show c, GHC.Show.Show a, GHC.Show.Show b, GHC.Show.Show d) => GHC.Show.Show (Clash.Primitives.Types.Primitive a b c d)
+ Clash.Primitives.Types: instance Control.DeepSeq.NFData Clash.Primitives.Types.BlackBoxFunctionName
+ Clash.Primitives.Types: instance Control.DeepSeq.NFData Clash.Primitives.Types.TemplateFormat
+ Clash.Primitives.Types: instance Control.DeepSeq.NFData Clash.Primitives.Types.TemplateSource
+ Clash.Primitives.Types: instance Data.Aeson.Types.FromJSON.FromJSON Clash.Primitives.Types.UnresolvedPrimitive
+ Clash.Primitives.Types: instance Data.Binary.Class.Binary Clash.Primitives.Types.BlackBoxFunctionName
+ Clash.Primitives.Types: instance Data.Hashable.Class.Hashable Clash.Primitives.Types.BlackBoxFunctionName
+ Clash.Primitives.Types: instance Data.Hashable.Class.Hashable Clash.Primitives.Types.TemplateFormat
+ Clash.Primitives.Types: instance GHC.Base.Functor (Clash.Primitives.Types.Primitive a b c)
+ Clash.Primitives.Types: instance GHC.Classes.Eq Clash.Primitives.Types.BlackBoxFunctionName
+ Clash.Primitives.Types: instance GHC.Classes.Eq Clash.Primitives.Types.TemplateSource
+ Clash.Primitives.Types: instance GHC.Generics.Generic (Clash.Primitives.Types.Primitive a b c d)
+ Clash.Primitives.Types: instance GHC.Generics.Generic Clash.Primitives.Types.BlackBoxFunctionName
+ Clash.Primitives.Types: instance GHC.Generics.Generic Clash.Primitives.Types.TemplateFormat
+ Clash.Primitives.Types: instance GHC.Generics.Generic Clash.Primitives.Types.TemplateSource
+ Clash.Primitives.Types: instance GHC.Show.Show Clash.Primitives.Types.BlackBoxFunctionName
+ Clash.Primitives.Types: instance GHC.Show.Show Clash.Primitives.Types.TemplateFormat
+ Clash.Primitives.Types: instance GHC.Show.Show Clash.Primitives.Types.TemplateSource
+ Clash.Primitives.Types: type CompiledPrimMap = PrimMap GuardedCompiledPrimitive
+ Clash.Primitives.Types: type CompiledPrimitive = Primitive BlackBoxTemplate BlackBox () (Int, BlackBoxFunction)
+ Clash.Primitives.Types: type GuardedCompiledPrimitive = PrimitiveGuard CompiledPrimitive
+ Clash.Primitives.Types: type GuardedResolvedPrimitive = PrimitiveGuard ResolvedPrimitive
+ Clash.Primitives.Types: type ResolvedPrimMap = PrimMap GuardedResolvedPrimitive
+ Clash.Primitives.Types: type ResolvedPrimitive = Primitive Text ((TemplateFormat, BlackBoxFunctionName), Maybe Text) () (Maybe Text)
+ Clash.Primitives.Types: type UnresolvedPrimitive = Primitive Text ((TemplateFormat, BlackBoxFunctionName), Maybe TemplateSource) (Maybe Text) (Maybe TemplateSource)
+ Clash.Primitives.Util: constantArgs :: Text -> CompiledPrimitive -> Set Int
+ Clash.Primitives.Util: decodeOrErr :: (HasCallStack, FromJSON a) => FilePath -> ByteString -> a
+ Clash.Primitives.Util: hashCompiledPrimMap :: CompiledPrimMap -> Int
+ Clash.Rewrite.Types: RewriteStep :: Context -> String -> String -> Term -> Term -> RewriteStep
+ Clash.Rewrite.Types: TransformContext :: !InScopeSet -> Context -> TransformContext
+ Clash.Rewrite.Types: [_customReprs] :: RewriteEnv -> CustomReprs
+ Clash.Rewrite.Types: [t_after] :: RewriteStep -> Term
+ Clash.Rewrite.Types: [t_before] :: RewriteStep -> Term
+ Clash.Rewrite.Types: [t_bndrS] :: RewriteStep -> String
+ Clash.Rewrite.Types: [t_ctx] :: RewriteStep -> Context
+ Clash.Rewrite.Types: [t_name] :: RewriteStep -> String
+ Clash.Rewrite.Types: [tfContext] :: TransformContext -> Context
+ Clash.Rewrite.Types: [tfInScope] :: TransformContext -> !InScopeSet
+ Clash.Rewrite.Types: [unR] :: RewriteMonad extra a -> RewriteEnv -> RewriteState extra -> Any -> (a, RewriteState extra, Any)
+ Clash.Rewrite.Types: censor :: (Any -> Any) -> RewriteMonad extra a -> RewriteMonad extra a
+ Clash.Rewrite.Types: customReprs :: Lens' RewriteEnv CustomReprs
+ Clash.Rewrite.Types: data RewriteStep
+ Clash.Rewrite.Types: data TransformContext
+ Clash.Rewrite.Types: instance Control.DeepSeq.NFData Clash.Rewrite.Types.RewriteStep
+ Clash.Rewrite.Types: instance Control.Monad.Fail.MonadFail (Clash.Rewrite.Types.RewriteMonad extra)
+ Clash.Rewrite.Types: instance Data.Binary.Class.Binary Clash.Rewrite.Types.RewriteStep
+ Clash.Rewrite.Types: instance Data.Hashable.Class.Hashable Clash.Rewrite.Types.RewriteStep
+ Clash.Rewrite.Types: instance GHC.Generics.Generic Clash.Rewrite.Types.RewriteStep
+ Clash.Rewrite.Types: instance GHC.Show.Show Clash.Rewrite.Types.RewriteStep
+ Clash.Rewrite.Types: runR :: RewriteMonad extra a -> RewriteEnv -> RewriteState extra -> (a, RewriteState extra, Any)
+ Clash.Rewrite.Util: applyDebug :: DebugLevel -> String -> Term -> Bool -> Term -> RewriteMonad extra Term
+ Clash.Rewrite.Util: cloneName :: (Monad m, MonadUnique m) => Name a -> m (Name a)
+ Clash.Rewrite.Util: findAccidentialShadows :: Term -> [[Id]]
+ Clash.Rewrite.Util: isConstant :: Term -> Bool
+ Clash.Rewrite.Util: isConstantNotClockReset :: Term -> RewriteMonad extra Bool
+ Clash.Rewrite.Util: isFromInt :: Text -> Bool
+ Clash.Rewrite.Util: isWorkFree :: Term -> Bool
+ Clash.Unique: class Uniquable a
+ Clash.Unique: data UniqMap a
+ Clash.Unique: data UniqSet a
+ Clash.Unique: delListUniqMap :: Uniquable a => UniqMap b -> [a] -> UniqMap b
+ Clash.Unique: delUniqMap :: Uniquable a => UniqMap b -> a -> UniqMap b
+ Clash.Unique: delUniqSetDirectly :: Unique -> UniqSet b -> UniqSet b
+ Clash.Unique: differenceUniqMap :: UniqMap a -> UniqMap a -> UniqMap a
+ Clash.Unique: elemUniqMap :: Uniquable a => a -> UniqMap b -> Bool
+ Clash.Unique: elemUniqSet :: Uniquable a => a -> UniqSet a -> Bool
+ Clash.Unique: elemUniqSetDirectly :: Unique -> UniqSet a -> Bool
+ Clash.Unique: eltsUniqMap :: UniqMap a -> [a]
+ Clash.Unique: eltsUniqSet :: UniqSet a -> [a]
+ Clash.Unique: emptyUniqMap :: UniqMap a
+ Clash.Unique: emptyUniqSet :: UniqSet a
+ Clash.Unique: extendListUniqMap :: Uniquable a => UniqMap b -> [(a, b)] -> UniqMap b
+ Clash.Unique: extendUniqMap :: Uniquable a => a -> b -> UniqMap b -> UniqMap b
+ Clash.Unique: extendUniqMapWith :: Uniquable a => a -> b -> (b -> b -> b) -> UniqMap b -> UniqMap b
+ Clash.Unique: extendUniqSet :: Uniquable a => UniqSet a -> a -> UniqSet a
+ Clash.Unique: filterUniqMap :: (b -> Bool) -> UniqMap b -> UniqMap b
+ Clash.Unique: foldrWithUnique :: (Unique -> a -> b -> b) -> b -> UniqMap a -> b
+ Clash.Unique: getUnique :: Uniquable a => a -> Unique
+ Clash.Unique: instance Clash.Pretty.ClashPretty a => Clash.Pretty.ClashPretty (Clash.Unique.UniqMap a)
+ Clash.Unique: instance Clash.Pretty.ClashPretty a => Clash.Pretty.ClashPretty (Clash.Unique.UniqSet a)
+ Clash.Unique: instance Clash.Pretty.ClashPretty a => GHC.Show.Show (Clash.Unique.UniqMap a)
+ Clash.Unique: instance Clash.Unique.Uniquable GHC.Types.Int
+ Clash.Unique: instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Clash.Unique.UniqMap a)
+ Clash.Unique: instance Data.Binary.Class.Binary a => Data.Binary.Class.Binary (Clash.Unique.UniqMap a)
+ Clash.Unique: instance Data.Binary.Class.Binary a => Data.Binary.Class.Binary (Clash.Unique.UniqSet a)
+ Clash.Unique: instance Data.Foldable.Foldable Clash.Unique.UniqMap
+ Clash.Unique: instance Data.Foldable.Foldable Clash.Unique.UniqSet
+ Clash.Unique: instance Data.Traversable.Traversable Clash.Unique.UniqMap
+ Clash.Unique: instance GHC.Base.Functor Clash.Unique.UniqMap
+ Clash.Unique: instance GHC.Base.Monoid (Clash.Unique.UniqMap a)
+ Clash.Unique: instance GHC.Base.Monoid (Clash.Unique.UniqSet a)
+ Clash.Unique: instance GHC.Base.Semigroup (Clash.Unique.UniqMap a)
+ Clash.Unique: instance GHC.Base.Semigroup (Clash.Unique.UniqSet a)
+ Clash.Unique: keysUniqMap :: UniqMap a -> [Unique]
+ Clash.Unique: listToUniqMap :: Uniquable a => [(a, b)] -> UniqMap b
+ Clash.Unique: lookupUniqMap :: Uniquable a => a -> UniqMap b -> Maybe b
+ Clash.Unique: lookupUniqMap' :: (HasCallStack, Uniquable a) => UniqMap b -> a -> b
+ Clash.Unique: lookupUniqSet :: Uniquable a => a -> UniqSet b -> Maybe b
+ Clash.Unique: mapMaybeUniqMap :: (a -> Maybe b) -> UniqMap a -> UniqMap b
+ Clash.Unique: mapUniqMap :: (a -> b) -> UniqMap a -> UniqMap b
+ Clash.Unique: mkUniqSet :: Uniquable a => [a] -> UniqSet a
+ Clash.Unique: notElemUniqMap :: Uniquable a => a -> UniqMap b -> Bool
+ Clash.Unique: notElemUniqSet :: Uniquable a => a -> UniqSet a -> Bool
+ Clash.Unique: nullUniqMap :: UniqMap a -> Bool
+ Clash.Unique: subsetUniqSet :: UniqSet a -> UniqSet a -> Bool
+ Clash.Unique: toListUniqMap :: UniqMap a -> [(Unique, a)]
+ Clash.Unique: type Unique = Int
+ Clash.Unique: unionUniqMap :: UniqMap a -> UniqMap a -> UniqMap a
+ Clash.Unique: unionUniqMapWith :: (a -> a -> a) -> UniqMap a -> UniqMap a -> UniqMap a
+ Clash.Unique: unionUniqSet :: UniqSet a -> UniqSet a -> UniqSet a
+ Clash.Unique: uniqMapToUniqSet :: UniqMap a -> UniqSet a
+ Clash.Unique: unitUniqMap :: Uniquable a => a -> b -> UniqMap b
+ Clash.Unique: unitUniqSet :: Uniquable a => a -> UniqSet a
+ Clash.Util: (&&&) :: Arrow a => a b c -> a b c' -> a b (c, c')
+ Clash.Util: ClashException :: SrcSpan -> String -> Maybe String -> ClashException
+ Clash.Util: anyM :: Monad m => (a -> m Bool) -> [a] -> m Bool
+ Clash.Util: assertPanic :: String -> Int -> a
+ Clash.Util: assertPprPanic :: HasCallStack => String -> Int -> Doc ann -> a
+ Clash.Util: callStackDoc :: HasCallStack => Doc ann
+ Clash.Util: countEq :: Eq a => a -> [a] -> Int
+ Clash.Util: data ClashException
+ Clash.Util: data SrcSpan
+ Clash.Util: debugIsOn :: Bool
+ Clash.Util: equalLength :: [a] -> [b] -> Bool
+ Clash.Util: headMaybe :: [a] -> Maybe a
+ Clash.Util: instance GHC.Exception.Type.Exception Clash.Util.ClashException
+ Clash.Util: instance GHC.Show.Show Clash.Util.ClashException
+ Clash.Util: makeCachedU :: (MonadState s m, Uniquable k) => k -> Lens' s (UniqMap v) -> m v -> m v
+ Clash.Util: neLength :: [a] -> [b] -> Bool
+ Clash.Util: noSrcSpan :: SrcSpan
+ Clash.Util: pkgIdFromTypeable :: Typeable a => a -> String
+ Clash.Util: pprDebugAndThen :: (String -> a) -> Doc ann -> Doc ann -> a
+ Clash.Util: pprPanic :: String -> Doc ann -> a
+ Clash.Util: pprTrace :: String -> Doc ann -> a -> a
+ Clash.Util: pprTraceDebug :: String -> Doc ann -> a -> a
+ Clash.Util: reportTimeDiff :: UTCTime -> UTCTime -> String
+ Clash.Util: tailMaybe :: [a] -> Maybe [a]
+ Clash.Util: type HasCallStack = ?callStack :: CallStack
+ Clash.Util: uncurry3 :: (a -> b -> c -> d) -> (a, b, c) -> d
+ Clash.Util: warnPprTrace :: HasCallStack => Bool -> String -> Int -> Doc ann -> a -> a
+ Clash.Util: zipEqual :: [a] -> [b] -> [(a, b)]
+ Clash.Util.Graph: reverseTopSort :: [(Int, a)] -> [(Int, Int)] -> Either String [a]
+ Clash.Util.Graph: topSort :: [(Int, a)] -> [(Int, Int)] -> Either String [a]
+ Data.Text.Prettyprint.Doc.Extra: (<+>) :: Applicative f => f Doc -> f Doc -> f Doc
+ Data.Text.Prettyprint.Doc.Extra: AvailablePerLine :: Int -> Double -> PageWidth
+ Data.Text.Prettyprint.Doc.Extra: LayoutOptions :: PageWidth -> LayoutOptions
+ Data.Text.Prettyprint.Doc.Extra: Unbounded :: PageWidth
+ Data.Text.Prettyprint.Doc.Extra: [layoutPageWidth] :: LayoutOptions -> PageWidth
+ Data.Text.Prettyprint.Doc.Extra: align :: Functor f => f Doc -> f Doc
+ Data.Text.Prettyprint.Doc.Extra: braces :: Functor f => f Doc -> f Doc
+ Data.Text.Prettyprint.Doc.Extra: brackets :: Functor f => f Doc -> f Doc
+ Data.Text.Prettyprint.Doc.Extra: char :: Applicative f => Char -> f Doc
+ Data.Text.Prettyprint.Doc.Extra: colon :: Applicative f => f Doc
+ Data.Text.Prettyprint.Doc.Extra: column :: Functor f => f (Int -> Doc) -> f Doc
+ Data.Text.Prettyprint.Doc.Extra: comma :: Applicative f => f Doc
+ Data.Text.Prettyprint.Doc.Extra: data PageWidth
+ Data.Text.Prettyprint.Doc.Extra: dot :: Applicative f => f Doc
+ Data.Text.Prettyprint.Doc.Extra: dquotes :: Functor f => f Doc -> f Doc
+ Data.Text.Prettyprint.Doc.Extra: emptyDoc :: Applicative f => f Doc
+ Data.Text.Prettyprint.Doc.Extra: encloseSep :: Applicative f => f Doc -> f Doc -> f Doc -> f [Doc] -> f Doc
+ Data.Text.Prettyprint.Doc.Extra: equals :: Applicative f => f Doc
+ Data.Text.Prettyprint.Doc.Extra: fill :: Applicative f => Int -> f Doc -> f Doc
+ Data.Text.Prettyprint.Doc.Extra: flatAlt :: Applicative f => f Doc -> f Doc -> f Doc
+ Data.Text.Prettyprint.Doc.Extra: hcat :: Functor f => f [Doc] -> f Doc
+ Data.Text.Prettyprint.Doc.Extra: hsep :: Functor f => f [Doc] -> f Doc
+ Data.Text.Prettyprint.Doc.Extra: indent :: Functor f => Int -> f Doc -> f Doc
+ Data.Text.Prettyprint.Doc.Extra: infixr 6 <+>
+ Data.Text.Prettyprint.Doc.Extra: instance GHC.Base.Applicative f => Data.String.IsString (f Data.Text.Prettyprint.Doc.Extra.Doc)
+ Data.Text.Prettyprint.Doc.Extra: int :: Applicative f => Int -> f Doc
+ Data.Text.Prettyprint.Doc.Extra: integer :: Applicative f => Integer -> f Doc
+ Data.Text.Prettyprint.Doc.Extra: isEmpty :: Doc -> Bool
+ Data.Text.Prettyprint.Doc.Extra: layoutCompact :: () => Doc ann -> SimpleDocStream ann
+ Data.Text.Prettyprint.Doc.Extra: layoutOneLine :: Doc ann -> SimpleDocStream ann
+ Data.Text.Prettyprint.Doc.Extra: layoutPretty :: () => LayoutOptions -> Doc ann -> SimpleDocStream ann
+ Data.Text.Prettyprint.Doc.Extra: lbrace :: Applicative f => f Doc
+ Data.Text.Prettyprint.Doc.Extra: line :: Applicative f => f Doc
+ Data.Text.Prettyprint.Doc.Extra: line' :: Applicative f => f Doc
+ Data.Text.Prettyprint.Doc.Extra: lparen :: Applicative f => f Doc
+ Data.Text.Prettyprint.Doc.Extra: nest :: Functor f => Int -> f Doc -> f Doc
+ Data.Text.Prettyprint.Doc.Extra: nesting :: Functor f => f (Int -> Doc) -> f Doc
+ Data.Text.Prettyprint.Doc.Extra: newtype LayoutOptions
+ Data.Text.Prettyprint.Doc.Extra: parens :: Functor f => f Doc -> f Doc
+ Data.Text.Prettyprint.Doc.Extra: pretty :: (Applicative f, Pretty a) => a -> f Doc
+ Data.Text.Prettyprint.Doc.Extra: punctuate :: Applicative f => f Doc -> f [Doc] -> f [Doc]
+ Data.Text.Prettyprint.Doc.Extra: rbrace :: Applicative f => f Doc
+ Data.Text.Prettyprint.Doc.Extra: renderLazy :: () => SimpleDocStream ann -> Text
+ Data.Text.Prettyprint.Doc.Extra: renderOneLine :: Doc ann -> Text
+ Data.Text.Prettyprint.Doc.Extra: rparen :: Applicative f => f Doc
+ Data.Text.Prettyprint.Doc.Extra: semi :: Applicative f => f Doc
+ Data.Text.Prettyprint.Doc.Extra: softline :: Applicative f => f Doc
+ Data.Text.Prettyprint.Doc.Extra: softline' :: Applicative f => f Doc
+ Data.Text.Prettyprint.Doc.Extra: space :: Applicative f => f Doc
+ Data.Text.Prettyprint.Doc.Extra: squotes :: Applicative f => f Doc -> f Doc
+ Data.Text.Prettyprint.Doc.Extra: string :: Applicative f => Text -> f Doc
+ Data.Text.Prettyprint.Doc.Extra: stringS :: Applicative f => Text -> f Doc
+ Data.Text.Prettyprint.Doc.Extra: tupled :: Functor f => f [Doc] -> f Doc
+ Data.Text.Prettyprint.Doc.Extra: type Doc = Doc ()
+ Data.Text.Prettyprint.Doc.Extra: vcat :: Functor f => f [Doc] -> f Doc
+ Data.Text.Prettyprint.Doc.Extra: vsep :: Functor f => f [Doc] -> f Doc
- Clash.Backend: genHDL :: Backend state => String -> SrcSpan -> Component -> Mon (State state) ((String, Doc), [(String, Doc)])
+ Clash.Backend: genHDL :: Backend state => Identifier -> SrcSpan -> HashMap Identifier Word -> Component -> Mon (State state) ((String, Doc), [(String, Doc)])
- Clash.Backend: initBackend :: Backend state => Int -> HdlSyn -> state
+ Clash.Backend: initBackend :: Backend state => Int -> HdlSyn -> Bool -> Maybe (Maybe Int) -> state
- Clash.Backend: mkTyPackage :: Backend state => String -> [HWType] -> Mon (State state) [(String, Doc)]
+ Clash.Backend: mkTyPackage :: Backend state => Identifier -> [HWType] -> Mon (State state) [(String, Doc)]
- Clash.Backend: type ModName = String
+ Clash.Backend: type ModName = Identifier
- Clash.Core.DataCon: MkData :: !DcName -> !ConTag -> !Type -> [TyName] -> [TyName] -> [Type] -> DataCon
+ Clash.Core.DataCon: MkData :: !DcName -> {-# UNPACK #-} !Unique -> !ConTag -> !Type -> [TyVar] -> [TyVar] -> [Type] -> [Text] -> DataCon
- Clash.Core.DataCon: [dcExtTyVars] :: DataCon -> [TyName]
+ Clash.Core.DataCon: [dcExtTyVars] :: DataCon -> [TyVar]
- Clash.Core.DataCon: [dcUnivTyVars] :: DataCon -> [TyName]
+ Clash.Core.DataCon: [dcUnivTyVars] :: DataCon -> [TyVar]
- Clash.Core.Evaluator: Heap :: GlobalHeap -> PureHeap -> Supply -> Heap
+ Clash.Core.Evaluator: Heap :: GlobalHeap -> GPureHeap -> PureHeap -> Supply -> InScopeSet -> Heap
- Clash.Core.Evaluator: Lambda :: (Bind Id Term) -> Value
+ Clash.Core.Evaluator: Lambda :: Id -> Term -> Value
- Clash.Core.Evaluator: PrimApply :: Text -> Type -> [Type] -> [Value] -> [Term] -> StackFrame
+ Clash.Core.Evaluator: PrimApply :: Text -> PrimInfo -> [Type] -> [Value] -> [Term] -> StackFrame
- Clash.Core.Evaluator: PrimVal :: Text -> Type -> [Type] -> [Value] -> Value
+ Clash.Core.Evaluator: PrimVal :: Text -> PrimInfo -> [Type] -> [Value] -> Value
- Clash.Core.Evaluator: TyLambda :: (Bind TyVar Term) -> Value
+ Clash.Core.Evaluator: TyLambda :: TyVar -> Term -> Value
- Clash.Core.Evaluator: allocate :: Heap -> Stack -> (Bind (Rec [LetBinding]) Term) -> State
+ Clash.Core.Evaluator: allocate :: Heap -> Stack -> [LetBinding] -> Term -> State
- Clash.Core.Evaluator: force :: BindingMap -> Heap -> Stack -> Id -> Maybe State
+ Clash.Core.Evaluator: force :: Heap -> Stack -> Id -> Maybe State
- Clash.Core.Evaluator: letSubst :: PureHeap -> Supply -> Id -> (Supply, (TmOccName, (TmOccName, Term)))
+ Clash.Core.Evaluator: letSubst :: PureHeap -> Supply -> Id -> (Supply, (Id, (Id, Term)))
- Clash.Core.Evaluator: primop :: PrimEvaluator -> BindingMap -> TyConMap -> Heap -> Stack -> Text -> Type -> [Type] -> [Value] -> Value -> [Term] -> Maybe State
+ Clash.Core.Evaluator: primop :: PrimEvaluator -> TyConMap -> Heap -> Stack -> Text -> PrimInfo -> [Type] -> [Value] -> Value -> [Term] -> Maybe State
- Clash.Core.Evaluator: step :: PrimEvaluator -> BindingMap -> TyConMap -> State -> Maybe State
+ Clash.Core.Evaluator: step :: PrimEvaluator -> TyConMap -> State -> Maybe State
- Clash.Core.Evaluator: substAlt :: DataCon -> Rebind [TyVar] [Id] -> [Either Term Type] -> Term -> Term
+ Clash.Core.Evaluator: substAlt :: DataCon -> [TyVar] -> [Id] -> [Either Term Type] -> Term -> Term
- Clash.Core.Evaluator: type PrimEvaluator = Bool -> BindingMap -> TyConMap -> Heap -> Stack -> Text -> Type -> [Type] -> [Value] -> Maybe State
+ Clash.Core.Evaluator: type PrimEvaluator = Bool -> TyConMap -> Heap -> Stack -> Text -> PrimInfo -> [Type] -> [Value] -> Maybe State
- Clash.Core.Evaluator: type PureHeap = Map TmOccName Term
+ Clash.Core.Evaluator: type PureHeap = VarEnv Term
- Clash.Core.Evaluator: uniqueInHeap :: PureHeap -> Supply -> TmOccName -> (Supply, TmName)
+ Clash.Core.Evaluator: uniqueInHeap :: PureHeap -> Supply -> Id -> (Supply, Id)
- Clash.Core.Evaluator: unwind :: PrimEvaluator -> BindingMap -> TyConMap -> Heap -> Stack -> Value -> Maybe State
+ Clash.Core.Evaluator: unwind :: PrimEvaluator -> TyConMap -> Heap -> Stack -> Value -> Maybe State
- Clash.Core.Evaluator: whnf :: PrimEvaluator -> BindingMap -> TyConMap -> Bool -> State -> State
+ Clash.Core.Evaluator: whnf :: PrimEvaluator -> TyConMap -> Bool -> State -> State
- Clash.Core.Evaluator: whnf' :: PrimEvaluator -> BindingMap -> TyConMap -> GlobalHeap -> Supply -> Bool -> Term -> (GlobalHeap, Term)
+ Clash.Core.Evaluator: whnf' :: PrimEvaluator -> BindingMap -> TyConMap -> GlobalHeap -> Supply -> InScopeSet -> Bool -> Term -> (GlobalHeap, PureHeap, Term)
- Clash.Core.FreeVars: termFreeTyVars :: Fold Term TyOccName
+ Clash.Core.FreeVars: termFreeTyVars :: Fold Term TyVar
- Clash.Core.FreeVars: typeFreeVars :: Fold Type TyOccName
+ Clash.Core.FreeVars: typeFreeVars :: Fold Type TyVar
- Clash.Core.Literal: ByteArrayLiteral :: !(Vector Word8) -> Literal
+ Clash.Core.Literal: ByteArrayLiteral :: !Vector Word8 -> Literal
- Clash.Core.Name: Name :: NameSort -> OccName a -> !SrcSpan -> Name a
+ Clash.Core.Name: Name :: NameSort -> !OccName -> {-# UNPACK #-} !Unique -> !SrcSpan -> Name a
- Clash.Core.Name: [nameOcc] :: Name a -> OccName a
+ Clash.Core.Name: [nameOcc] :: Name a -> !OccName
- Clash.Core.Name: appendToName :: Name a -> String -> Name a
+ Clash.Core.Name: appendToName :: Name a -> Text -> Name a
- Clash.Core.Name: type OccName a = Name a
+ Clash.Core.Name: type OccName = Text
- Clash.Core.Pretty: ppr :: (Pretty p, LFresh m) => p -> m Doc
+ Clash.Core.Pretty: ppr :: PrettyPrec p => p -> ClashDoc
- Clash.Core.Pretty: pprPrec :: (Pretty p, LFresh m) => Rational -> p -> m Doc
+ Clash.Core.Pretty: pprPrec :: (PrettyPrec p, Monad m) => Rational -> p -> m ClashDoc
- Clash.Core.Subst: substTm :: TmOccName -> Term -> Term -> Term
+ Clash.Core.Subst: substTm :: HasCallStack => Doc () -> Subst -> Term -> Term
- Clash.Core.Subst: substTy :: TyOccName -> Type -> Type -> Type
+ Clash.Core.Subst: substTy :: HasCallStack => Subst -> Type -> Type
- Clash.Core.Term: DataPat :: !(Embed DataCon) -> !(Rebind [TyVar] [Id]) -> Pat
+ Clash.Core.Term: DataPat :: !DataCon -> [TyVar] -> [Id] -> Pat
- Clash.Core.Term: Lam :: !(Bind Id Term) -> Term
+ Clash.Core.Term: Lam :: !Id -> Term -> Term
- Clash.Core.Term: Letrec :: !(Bind (Rec [LetBinding]) Term) -> Term
+ Clash.Core.Term: Letrec :: [LetBinding] -> Term -> Term
- Clash.Core.Term: LitPat :: !(Embed Literal) -> Pat
+ Clash.Core.Term: LitPat :: !Literal -> Pat
- Clash.Core.Term: Prim :: !Text -> !Type -> Term
+ Clash.Core.Term: Prim :: !Text -> !PrimInfo -> Term
- Clash.Core.Term: TyLam :: !(Bind TyVar Term) -> Term
+ Clash.Core.Term: TyLam :: !TyVar -> Term -> Term
- Clash.Core.Term: Var :: !Type -> !TmName -> Term
+ Clash.Core.Term: Var :: !Id -> Term
- Clash.Core.Term: type Alt = Bind Pat Term
+ Clash.Core.Term: type Alt = (Pat, Term)
- Clash.Core.Term: type LetBinding = (Id, Embed Term)
+ Clash.Core.Term: type LetBinding = (Id, Term)
- Clash.Core.TyCon: AlgTyCon :: !TyConName -> !Kind -> !Int -> !AlgTyConRhs -> TyCon
+ Clash.Core.TyCon: AlgTyCon :: {-# UNPACK #-} !Unique -> !TyConName -> !Kind -> !Int -> !AlgTyConRhs -> !Bool -> TyCon
- Clash.Core.TyCon: FunTyCon :: !TyConName -> !Kind -> !Int -> [([Type], Type)] -> TyCon
+ Clash.Core.TyCon: FunTyCon :: {-# UNPACK #-} !Unique -> !TyConName -> !Kind -> !Int -> [([Type], Type)] -> TyCon
- Clash.Core.TyCon: NewTyCon :: !DataCon -> ([TyName], Type) -> AlgTyConRhs
+ Clash.Core.TyCon: NewTyCon :: !DataCon -> ([TyVar], Type) -> AlgTyConRhs
- Clash.Core.TyCon: PrimTyCon :: !TyConName -> !Kind -> !Int -> TyCon
+ Clash.Core.TyCon: PrimTyCon :: {-# UNPACK #-} !Unique -> !TyConName -> !Kind -> !Int -> TyCon
- Clash.Core.TyCon: SuperKindTyCon :: !TyConName -> TyCon
+ Clash.Core.TyCon: SuperKindTyCon :: {-# UNPACK #-} !Unique -> !TyConName -> TyCon
- Clash.Core.TyCon: [ntEtadRhs] :: AlgTyConRhs -> ([TyName], Type)
+ Clash.Core.TyCon: [ntEtadRhs] :: AlgTyConRhs -> ([TyVar], Type)
- Clash.Core.TyCon: type TyConMap = HashMap TyConOccName TyCon
+ Clash.Core.TyCon: type TyConMap = UniqMap TyCon
- Clash.Core.Type: ForAllTy :: !(Bind TyVar Type) -> Type
+ Clash.Core.Type: ForAllTy :: !TyVar -> !Type -> Type
- Clash.Core.Type: VarTy :: !Kind -> !TyName -> Type
+ Clash.Core.Type: VarTy :: !TyVar -> Type
- Clash.Core.Type: applyFunTy :: HashMap TyConOccName TyCon -> Type -> Type -> Type
+ Clash.Core.Type: applyFunTy :: TyConMap -> Type -> Type -> Type
- Clash.Core.Type: coreView :: HashMap TyConOccName TyCon -> Type -> Maybe Type
+ Clash.Core.Type: coreView :: TyConMap -> Type -> Type
- Clash.Core.Type: findFunSubst :: HashMap TyConOccName TyCon -> [([Type], Type)] -> [Type] -> Maybe Type
+ Clash.Core.Type: findFunSubst :: TyConMap -> [([Type], Type)] -> [Type] -> Maybe Type
- Clash.Core.Type: isFunTy :: HashMap TyConOccName TyCon -> Type -> Bool
+ Clash.Core.Type: isFunTy :: TyConMap -> Type -> Bool
- Clash.Core.Type: isPolyFunCoreTy :: HashMap TyConOccName TyCon -> Type -> Bool
+ Clash.Core.Type: isPolyFunCoreTy :: TyConMap -> Type -> Bool
- Clash.Core.Type: normalizeType :: HashMap TyConOccName TyCon -> Type -> Type
+ Clash.Core.Type: normalizeType :: TyConMap -> Type -> Type
- Clash.Core.Type: reduceTypeFamily :: HashMap TyConOccName TyCon -> Type -> Maybe Type
+ Clash.Core.Type: reduceTypeFamily :: TyConMap -> Type -> Maybe Type
- Clash.Core.Type: splitCoreFunForallTy :: HashMap TyConOccName TyCon -> Type -> ([Either TyVar Type], Type)
+ Clash.Core.Type: splitCoreFunForallTy :: TyConMap -> Type -> ([Either TyVar Type], Type)
- Clash.Core.Type: splitFunTy :: HashMap TyConOccName TyCon -> Type -> Maybe (Type, Type)
+ Clash.Core.Type: splitFunTy :: TyConMap -> Type -> Maybe (Type, Type)
- Clash.Core.Type: splitFunTys :: HashMap TyConOccName TyCon -> Type -> ([Type], Type)
+ Clash.Core.Type: splitFunTys :: TyConMap -> Type -> ([Type], Type)
- Clash.Core.Type: typeKind :: HashMap TyConOccName TyCon -> Type -> Kind
+ Clash.Core.Type: typeKind :: TyConMap -> Type -> Kind
- Clash.Core.TysPrim: tysPrimMap :: HashMap TyConOccName TyCon
+ Clash.Core.TysPrim: tysPrimMap :: TyConMap
- Clash.Core.Util: applyTypeToArgs :: Fresh m => HashMap TyConOccName TyCon -> Type -> [Either Term Type] -> m Type
+ Clash.Core.Util: applyTypeToArgs :: Term -> TyConMap -> Type -> [Either Term Type] -> Type
- Clash.Core.Util: collectBndrs :: Fresh m => Term -> m ([Either Id TyVar], Term)
+ Clash.Core.Util: collectBndrs :: Term -> ([Either Id TyVar], Term)
- Clash.Core.Util: extractElems :: DataCon -> Type -> Char -> Integer -> Term -> [(Term, [LetBinding])]
+ Clash.Core.Util: extractElems :: Supply -> InScopeSet -> DataCon -> Type -> Char -> Integer -> Term -> (Supply, [(Term, [LetBinding])])
- Clash.Core.Util: extractTElems :: DataCon -> DataCon -> Type -> Char -> Integer -> Term -> ([Term], [LetBinding])
+ Clash.Core.Util: extractTElems :: Supply -> InScopeSet -> DataCon -> DataCon -> Type -> Char -> Integer -> Term -> (Supply, ([Term], [LetBinding]))
- Clash.Core.Util: isClockOrReset :: HashMap TyConOccName TyCon -> Type -> Bool
+ Clash.Core.Util: isClockOrReset :: TyConMap -> Type -> Bool
- Clash.Core.Util: isFun :: Fresh m => HashMap TyConOccName TyCon -> Term -> m Bool
+ Clash.Core.Util: isFun :: TyConMap -> Term -> Bool
- Clash.Core.Util: isPolyFun :: Fresh m => HashMap TyConOccName TyCon -> Term -> m Bool
+ Clash.Core.Util: isPolyFun :: TyConMap -> Term -> Bool
- Clash.Core.Util: isSignalType :: HashMap TyConOccName TyCon -> Type -> Bool
+ Clash.Core.Util: isSignalType :: TyConMap -> Type -> Bool
- Clash.Core.Util: termType :: Fresh m => HashMap TyConOccName TyCon -> Term -> m Type
+ Clash.Core.Util: termType :: TyConMap -> Term -> Type
- Clash.Core.Util: tyNatSize :: HashMap TyConOccName TyCon -> Type -> Except String Integer
+ Clash.Core.Util: tyNatSize :: TyConMap -> Type -> Except String Integer
- Clash.Core.Util: type Delta = HashMap TyOccName Kind
+ Clash.Core.Util: type Delta = VarEnv Kind
- Clash.Core.Util: type Gamma = HashMap TmOccName Type
+ Clash.Core.Util: type Gamma = VarEnv Type
- Clash.Core.Var: Id :: Name a -> Embed Type -> Var a
+ Clash.Core.Var: Id :: !Name a -> {-# UNPACK #-} !Unique -> Type -> IdScope -> Var a
- Clash.Core.Var: TyVar :: Name a -> Embed Kind -> Var a
+ Clash.Core.Var: TyVar :: !Name a -> {-# UNPACK #-} !Unique -> Kind -> Var a
- Clash.Core.Var: [varName] :: Var a -> Name a
+ Clash.Core.Var: [varName] :: Var a -> !Name a
- Clash.Core.Var: [varType] :: Var a -> Embed Type
+ Clash.Core.Var: [varType] :: Var a -> Type
- Clash.Driver: callGraphBindings :: BindingMap -> TmOccName -> [Term]
+ Clash.Driver: callGraphBindings :: BindingMap -> Id -> [Term]
- Clash.Driver: createHDL :: Backend backend => backend -> String -> [(SrcSpan, Component)] -> Component -> (String, Either Manifest Manifest) -> ([(String, Doc)], Manifest)
+ Clash.Driver: createHDL :: Backend backend => backend -> Identifier -> HashMap Identifier Word -> [([Bool], SrcSpan, HashMap Identifier Word, Component)] -> Component -> (Identifier, Either Manifest Manifest) -> ([(String, Doc)], Manifest, [(String, FilePath)], [(String, String)])
- Clash.Driver: generateHDL :: forall backend. Backend backend => BindingMap -> Maybe backend -> PrimMap (Text) -> HashMap TyConOccName TyCon -> IntMap TyConName -> (HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType)) -> PrimEvaluator -> [(TmName, Type, Maybe TopEntity, Maybe TmName)] -> ClashOpts -> (UTCTime, UTCTime) -> IO ()
+ Clash.Driver: generateHDL :: forall backend. Backend backend => CustomReprs -> BindingMap -> Maybe backend -> CompiledPrimMap -> TyConMap -> IntMap TyConName -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> PrimEvaluator -> [(Id, Maybe TopEntity, Maybe Id)] -> ClashOpts -> (UTCTime, UTCTime) -> IO ()
- Clash.Driver: normalizeEntity :: BindingMap -> PrimMap BlackBoxTemplate -> HashMap TyConOccName TyCon -> IntMap TyConName -> (HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType)) -> PrimEvaluator -> [TmOccName] -> ClashOpts -> Supply -> TmOccName -> BindingMap
+ Clash.Driver: normalizeEntity :: CustomReprs -> BindingMap -> CompiledPrimMap -> TyConMap -> IntMap TyConName -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> PrimEvaluator -> [Id] -> ClashOpts -> Supply -> Id -> BindingMap
- Clash.Driver.Types: ClashOpts :: Int -> Int -> Word -> Word -> DebugLevel -> Bool -> Bool -> Int -> Maybe String -> HdlSyn -> Bool -> Bool -> Bool -> [FilePath] -> ClashOpts
+ Clash.Driver.Types: ClashOpts :: Int -> Int -> Word -> Word -> DebugLevel -> Bool -> Bool -> Bool -> OverridingBool -> Int -> Maybe String -> HdlSyn -> Bool -> Bool -> [FilePath] -> Maybe String -> Bool -> Bool -> Bool -> Maybe (Maybe Int) -> Bool -> ClashOpts
- Clash.Driver.Types: type BindingMap = HashMap TmOccName (TmName, Type, SrcSpan, InlineSpec, Term)
+ Clash.Driver.Types: type BindingMap = VarEnv (Id, SrcSpan, InlineSpec, Term)
- Clash.Netlist: genComponent :: TmOccName -> NetlistMonad (SrcSpan, Component)
+ Clash.Netlist: genComponent :: HasCallStack => Id -> NetlistMonad ([Bool], SrcSpan, HashMap Identifier Word, Component)
- Clash.Netlist: genComponentT :: TmOccName -> Term -> NetlistMonad (SrcSpan, Component)
+ Clash.Netlist: genComponentT :: HasCallStack => Id -> Term -> NetlistMonad ([Bool], SrcSpan, HashMap Identifier Word, Component)
- Clash.Netlist: genNames :: (IdType -> Identifier -> Identifier) -> [Identifier] -> HashMap TmOccName Identifier -> [TmName] -> ([Identifier], HashMap TmOccName Identifier)
+ Clash.Netlist: genNames :: Bool -> (IdType -> Identifier -> Identifier) -> (Maybe Identifier, Maybe Identifier) -> HashMap Identifier Word -> VarEnv Identifier -> BindingMap -> (HashMap Identifier Word, VarEnv Identifier)
- Clash.Netlist: genNetlist :: BindingMap -> [(TmName, Type, Maybe TopEntity, Maybe TmName)] -> PrimMap BlackBoxTemplate -> HashMap TyConOccName TyCon -> (HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType)) -> [(String, FilePath)] -> Int -> (IdType -> Identifier -> Identifier) -> (IdType -> Identifier -> Identifier -> Identifier) -> [Identifier] -> FilePath -> TmOccName -> IO ([(SrcSpan, Component)], [(String, FilePath)], [Identifier])
+ Clash.Netlist: genNetlist :: Bool -> ClashOpts -> CustomReprs -> BindingMap -> [(Id, Maybe TopEntity, Maybe Id)] -> CompiledPrimMap -> TyConMap -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> Int -> (IdType -> Identifier -> Identifier) -> (IdType -> Identifier -> Identifier -> Identifier) -> Bool -> HashMap Identifier Word -> FilePath -> (Maybe Identifier, Maybe Identifier) -> Id -> IO ([([Bool], SrcSpan, HashMap Identifier Word, Component)], HashMap Identifier Word)
- Clash.Netlist: mkDcApplication :: HWType -> (Either Identifier Id) -> DataCon -> [Term] -> NetlistMonad (Expr, [Declaration])
+ Clash.Netlist: mkDcApplication :: HasCallStack => HWType -> Either Identifier Id -> DataCon -> [Term] -> NetlistMonad (Expr, [Declaration])
- Clash.Netlist: mkDeclarations :: Id -> Term -> NetlistMonad [Declaration]
+ Clash.Netlist: mkDeclarations :: HasCallStack => Id -> Term -> NetlistMonad [Declaration]
- Clash.Netlist: mkDeclarations' :: Id -> Term -> NetlistMonad [Declaration]
+ Clash.Netlist: mkDeclarations' :: HasCallStack => Id -> Term -> NetlistMonad [Declaration]
- Clash.Netlist: mkExpr :: Bool -> (Either Identifier Id) -> Type -> Term -> NetlistMonad (Expr, [Declaration])
+ Clash.Netlist: mkExpr :: HasCallStack => Bool -> Either Identifier Id -> Type -> Term -> NetlistMonad (Expr, [Declaration])
- Clash.Netlist: mkFunApp :: Id -> TmName -> [Term] -> NetlistMonad [Declaration]
+ Clash.Netlist: mkFunApp :: HasCallStack => Identifier -> Id -> [Term] -> [Declaration] -> NetlistMonad [Declaration]
- Clash.Netlist: mkNetDecl :: (Id, Embed Term) -> NetlistMonad (Maybe Declaration)
+ Clash.Netlist: mkNetDecl :: (Id, Term) -> NetlistMonad (Maybe Declaration)
- Clash.Netlist: mkSelection :: Id -> Term -> Type -> [Alt] -> NetlistMonad [Declaration]
+ Clash.Netlist: mkSelection :: Either Identifier Id -> Term -> Type -> [Alt] -> [Declaration] -> NetlistMonad [Declaration]
- Clash.Netlist: runNetlistMonad :: BindingMap -> HashMap TmOccName (Type, Maybe TopEntity) -> PrimMap BlackBoxTemplate -> HashMap TyConOccName TyCon -> (HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType)) -> [(String, FilePath)] -> Int -> (IdType -> Identifier -> Identifier) -> (IdType -> Identifier -> Identifier -> Identifier) -> [Identifier] -> FilePath -> NetlistMonad a -> IO (a, NetlistState)
+ Clash.Netlist: runNetlistMonad :: Bool -> ClashOpts -> CustomReprs -> BindingMap -> VarEnv (Type, Maybe TopEntity) -> CompiledPrimMap -> TyConMap -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> Int -> (IdType -> Identifier -> Identifier) -> (IdType -> Identifier -> Identifier -> Identifier) -> Bool -> HashMap Identifier Word -> FilePath -> (Maybe Identifier, Maybe Identifier) -> NetlistMonad a -> IO (a, NetlistState)
- Clash.Netlist: toSimpleVar :: Id -> (Expr, Type) -> NetlistMonad (Expr, [Declaration])
+ Clash.Netlist: toSimpleVar :: Identifier -> (Expr, Type) -> NetlistMonad (Expr, [Declaration])
- Clash.Netlist.BlackBox: mkBlackBoxContext :: Id -> [Term] -> NetlistMonad (BlackBoxContext, [Declaration])
+ Clash.Netlist.BlackBox: mkBlackBoxContext :: Text -> Id -> [Term] -> NetlistMonad (BlackBoxContext, [Declaration])
- Clash.Netlist.BlackBox: mkFunInput :: Id -> Term -> NetlistMonad ((Either BlackBoxTemplate (Identifier, [Declaration]), WireOrReg, [BlackBoxTemplate], [BlackBoxTemplate], Maybe ((Text, Text), BlackBoxTemplate), BlackBoxContext), [Declaration])
+ Clash.Netlist.BlackBox: mkFunInput :: HasCallStack => Id -> Term -> NetlistMonad ((Either BlackBox (Identifier, [Declaration]), WireOrReg, [BlackBoxTemplate], [BlackBoxTemplate], [((Text, Text), BlackBox)], BlackBoxContext), [Declaration])
- Clash.Netlist.BlackBox: mkPrimitive :: Bool -> Bool -> (Either Identifier Id) -> Text -> [Either Term Type] -> Type -> NetlistMonad (Expr, [Declaration])
+ Clash.Netlist.BlackBox: mkPrimitive :: Bool -> Bool -> Either Identifier Id -> Text -> [Either Term Type] -> Type -> [Declaration] -> NetlistMonad (Expr, [Declaration])
- Clash.Netlist.BlackBox: prepareBlackBox :: Text -> BlackBoxTemplate -> BlackBoxContext -> NetlistMonad (BlackBoxTemplate, [Declaration])
+ Clash.Netlist.BlackBox: prepareBlackBox :: Text -> BlackBox -> BlackBoxContext -> NetlistMonad (BlackBox, [Declaration])
- Clash.Netlist.BlackBox.Types: Arg :: !Int -> !Int -> Element
+ Clash.Netlist.BlackBox.Types: Arg :: !Bool -> !Int -> Element
- Clash.Netlist.BlackBox.Types: Err :: !(Maybe Int) -> Element
+ Clash.Netlist.BlackBox.Types: Err :: !Maybe Int -> Element
- Clash.Netlist.BlackBox.Types: IncludeName :: Element
+ Clash.Netlist.BlackBox.Types: IncludeName :: !Int -> Element
- Clash.Netlist.BlackBox.Types: SigD :: [Element] -> !(Maybe Int) -> Element
+ Clash.Netlist.BlackBox.Types: SigD :: [Element] -> !Maybe Int -> Element
- Clash.Netlist.BlackBox.Types: Typ :: !(Maybe Int) -> Element
+ Clash.Netlist.BlackBox.Types: Typ :: !Maybe Int -> Element
- Clash.Netlist.BlackBox.Types: TypM :: !(Maybe Int) -> Element
+ Clash.Netlist.BlackBox.Types: TypM :: !Maybe Int -> Element
- Clash.Netlist.BlackBox.Util: renderBlackBox :: Backend backend => [BlackBoxTemplate] -> [BlackBoxTemplate] -> Maybe ((Text, Text), BlackBoxTemplate) -> BlackBoxTemplate -> BlackBoxContext -> State backend (Int -> Doc)
+ Clash.Netlist.BlackBox.Util: renderBlackBox :: Backend backend => [BlackBoxTemplate] -> [BlackBoxTemplate] -> [((Text, Text), BlackBox)] -> BlackBox -> BlackBoxContext -> State backend (Int -> Doc)
- Clash.Netlist.BlackBox.Util: renderFilePath :: [(String, FilePath)] -> String -> ([(String, FilePath)], Element)
+ Clash.Netlist.BlackBox.Util: renderFilePath :: [(String, FilePath)] -> String -> ([(String, FilePath)], String)
- Clash.Netlist.BlackBox.Util: setSym :: BlackBoxContext -> BlackBoxTemplate -> NetlistMonad (BlackBoxTemplate, [Declaration])
+ Clash.Netlist.BlackBox.Util: setSym :: forall m. Monad m => (IdType -> Identifier -> m Identifier) -> BlackBoxContext -> BlackBoxTemplate -> m (BlackBoxTemplate, [Declaration])
- Clash.Netlist.BlackBox.Util: usedArguments :: BlackBoxTemplate -> [Int]
+ Clash.Netlist.BlackBox.Util: usedArguments :: BlackBox -> [Int]
- Clash.Netlist.BlackBox.Util: verifyBlackBoxContext :: BlackBoxContext -> BlackBoxTemplate -> Bool
+ Clash.Netlist.BlackBox.Util: verifyBlackBoxContext :: BlackBoxContext -> BlackBox -> Bool
- Clash.Netlist.Id: mkBasicId' :: Bool -> Text -> Text
+ Clash.Netlist.Id: mkBasicId' :: HDL -> Bool -> Text -> Text
- Clash.Netlist.Types: BlackBoxD :: !Text -> [BlackBoxTemplate] -> [BlackBoxTemplate] -> (Maybe ((Text, Text), BlackBoxTemplate)) -> !BlackBoxTemplate -> BlackBoxContext -> Declaration
+ Clash.Netlist.Types: BlackBoxD :: !Text -> [BlackBoxTemplate] -> [BlackBoxTemplate] -> [((Text, Text), BlackBox)] -> !BlackBox -> BlackBoxContext -> Declaration
- Clash.Netlist.Types: BlackBoxE :: !Text -> [BlackBoxTemplate] -> [BlackBoxTemplate] -> (Maybe ((Text, Text), BlackBoxTemplate)) -> !BlackBoxTemplate -> !BlackBoxContext -> !Bool -> Expr
+ Clash.Netlist.Types: BlackBoxE :: !Text -> [BlackBoxTemplate] -> [BlackBoxTemplate] -> [((Text, Text), BlackBox)] -> !BlackBox -> !BlackBoxContext -> !Bool -> Expr
- Clash.Netlist.Types: Clock :: !Identifier -> !Integer -> !ClockKind -> HWType
+ Clash.Netlist.Types: Clock :: !Identifier -> HWType
- Clash.Netlist.Types: Context :: (Expr, HWType) -> [(Expr, HWType, Bool)] -> IntMap (Either BlackBoxTemplate (Identifier, [Declaration]), WireOrReg, [BlackBoxTemplate], [BlackBoxTemplate], Maybe ((Text, Text), BlackBoxTemplate), BlackBoxContext) -> Maybe Identifier -> Int -> BlackBoxContext
+ Clash.Netlist.Types: Context :: Text -> (Expr, HWType) -> [(Expr, HWType, Bool)] -> IntMap (Either BlackBox (Identifier, [Declaration]), WireOrReg, [BlackBoxTemplate], [BlackBoxTemplate], [((Text, Text), BlackBox)], BlackBoxContext) -> [Identifier] -> Int -> Identifier -> BlackBoxContext
- Clash.Netlist.Types: ConvBV :: (Maybe Identifier) -> HWType -> Bool -> Expr -> Expr
+ Clash.Netlist.Types: ConvBV :: Maybe Identifier -> HWType -> Bool -> Expr -> Expr
- Clash.Netlist.Types: DataTag :: !HWType -> !(Either Identifier Identifier) -> Expr
+ Clash.Netlist.Types: DataTag :: !HWType -> !Either Identifier Identifier -> Expr
- Clash.Netlist.Types: Identifier :: !Identifier -> !(Maybe Modifier) -> Expr
+ Clash.Netlist.Types: Identifier :: !Identifier -> !Maybe Modifier -> Expr
- Clash.Netlist.Types: InstDecl :: (Maybe Identifier) -> !Identifier -> !Identifier -> [(Expr, PortDirection, HWType, Expr)] -> Declaration
+ Clash.Netlist.Types: InstDecl :: EntityOrComponent -> Maybe Comment -> !Identifier -> !Identifier -> [(Expr, HWType, Expr)] -> [(Expr, PortDirection, HWType, Expr)] -> Declaration
- Clash.Netlist.Types: Literal :: !(Maybe (HWType, Size)) -> !Literal -> Expr
+ Clash.Netlist.Types: Literal :: !Maybe (HWType, Size) -> !Literal -> Expr
- Clash.Netlist.Types: NetDecl' :: (Maybe Identifier) -> WireOrReg -> !Identifier -> (Either Identifier HWType) -> Declaration
+ Clash.Netlist.Types: NetDecl' :: Maybe Comment -> WireOrReg -> !Identifier -> Either Identifier HWType -> Declaration
- Clash.Netlist.Types: NetlistMonad :: StateT NetlistState (FreshMT IO) a -> NetlistMonad a
+ Clash.Netlist.Types: NetlistMonad :: StateT NetlistState (ReaderT NetlistEnv IO) a -> NetlistMonad a
- Clash.Netlist.Types: NetlistState :: BindingMap -> !Int -> HashMap TmOccName (SrcSpan, Component) -> PrimMap BlackBoxTemplate -> HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType) -> HashMap TyConOccName TyCon -> !(Identifier, SrcSpan) -> [(String, FilePath)] -> Int -> IdType -> Identifier -> Identifier -> IdType -> Identifier -> Identifier -> Identifier -> [Identifier] -> [Identifier] -> HashMap TmOccName Identifier -> HashMap TmOccName (Type, Maybe TopEntity) -> FilePath -> Int -> NetlistState
+ Clash.Netlist.Types: NetlistState :: BindingMap -> !Int -> VarEnv ([Bool], SrcSpan, HashMap Identifier Word, Component) -> CompiledPrimMap -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> TyConMap -> !(Identifier, SrcSpan) -> Int -> (IdType -> Identifier -> Identifier) -> (IdType -> Identifier -> Identifier -> Identifier) -> HashMap Identifier Word -> HashMap Identifier Word -> Set Text -> VarEnv Identifier -> VarEnv (Type, Maybe TopEntity) -> FilePath -> Int -> (Maybe Identifier, Maybe Identifier) -> CustomReprs -> ClashOpts -> Bool -> Bool -> HWMap -> NetlistState
- Clash.Netlist.Types: Product :: !Identifier -> [HWType] -> HWType
+ Clash.Netlist.Types: Product :: !Identifier -> Maybe [Text] -> [HWType] -> HWType
- Clash.Netlist.Types: Reset :: !Identifier -> !Integer -> !ResetKind -> HWType
+ Clash.Netlist.Types: Reset :: !Identifier -> HWType
- Clash.Netlist.Types: Void :: (Maybe HWType) -> HWType
+ Clash.Netlist.Types: Void :: Maybe HWType -> HWType
- Clash.Netlist.Types: [_componentNames] :: NetlistState -> HashMap TmOccName Identifier
+ Clash.Netlist.Types: [_componentNames] :: NetlistState -> VarEnv Identifier
- Clash.Netlist.Types: [_components] :: NetlistState -> HashMap TmOccName (SrcSpan, Component)
+ Clash.Netlist.Types: [_components] :: NetlistState -> VarEnv ([Bool], SrcSpan, HashMap Identifier Word, Component)
- Clash.Netlist.Types: [_primitives] :: NetlistState -> PrimMap BlackBoxTemplate
+ Clash.Netlist.Types: [_primitives] :: NetlistState -> CompiledPrimMap
- Clash.Netlist.Types: [_seenComps] :: NetlistState -> [Identifier]
+ Clash.Netlist.Types: [_seenComps] :: NetlistState -> HashMap Identifier Word
- Clash.Netlist.Types: [_seenIds] :: NetlistState -> [Identifier]
+ Clash.Netlist.Types: [_seenIds] :: NetlistState -> HashMap Identifier Word
- Clash.Netlist.Types: [_tcCache] :: NetlistState -> HashMap TyConOccName TyCon
+ Clash.Netlist.Types: [_tcCache] :: NetlistState -> TyConMap
- Clash.Netlist.Types: [_topEntityAnns] :: NetlistState -> HashMap TmOccName (Type, Maybe TopEntity)
+ Clash.Netlist.Types: [_topEntityAnns] :: NetlistState -> VarEnv (Type, Maybe TopEntity)
- Clash.Netlist.Types: [_typeTranslator] :: NetlistState -> HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType)
+ Clash.Netlist.Types: [_typeTranslator] :: NetlistState -> CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))
- Clash.Netlist.Types: [bbFunctions] :: BlackBoxContext -> IntMap (Either BlackBoxTemplate (Identifier, [Declaration]), WireOrReg, [BlackBoxTemplate], [BlackBoxTemplate], Maybe ((Text, Text), BlackBoxTemplate), BlackBoxContext)
+ Clash.Netlist.Types: [bbFunctions] :: BlackBoxContext -> IntMap (Either BlackBox (Identifier, [Declaration]), WireOrReg, [BlackBoxTemplate], [BlackBoxTemplate], [((Text, Text), BlackBox)], BlackBoxContext)
- Clash.Netlist.Types: [bbQsysIncName] :: BlackBoxContext -> Maybe Identifier
+ Clash.Netlist.Types: [bbQsysIncName] :: BlackBoxContext -> [Identifier]
- Clash.Netlist.Types: [runNetlist] :: NetlistMonad a -> StateT NetlistState (FreshMT IO) a
+ Clash.Netlist.Types: [runNetlist] :: NetlistMonad a -> StateT NetlistState (ReaderT NetlistEnv IO) a
- Clash.Netlist.Types: componentNames :: Lens' NetlistState (HashMap TmOccName Identifier)
+ Clash.Netlist.Types: componentNames :: Lens' NetlistState (VarEnv Identifier)
- Clash.Netlist.Types: components :: Lens' NetlistState (HashMap TmOccName (SrcSpan, Component))
+ Clash.Netlist.Types: components :: Lens' NetlistState (VarEnv ([Bool], SrcSpan, HashMap Identifier Word, Component))
- Clash.Netlist.Types: emptyBBContext :: BlackBoxContext
+ Clash.Netlist.Types: emptyBBContext :: Text -> BlackBoxContext
- Clash.Netlist.Types: primitives :: Lens' NetlistState (PrimMap BlackBoxTemplate)
+ Clash.Netlist.Types: primitives :: Lens' NetlistState CompiledPrimMap
- Clash.Netlist.Types: seenComps :: Lens' NetlistState [Identifier]
+ Clash.Netlist.Types: seenComps :: Lens' NetlistState (HashMap Identifier Word)
- Clash.Netlist.Types: seenIds :: Lens' NetlistState [Identifier]
+ Clash.Netlist.Types: seenIds :: Lens' NetlistState (HashMap Identifier Word)
- Clash.Netlist.Types: tcCache :: Lens' NetlistState (HashMap TyConOccName TyCon)
+ Clash.Netlist.Types: tcCache :: Lens' NetlistState TyConMap
- Clash.Netlist.Types: topEntityAnns :: Lens' NetlistState (HashMap TmOccName (Type, Maybe TopEntity))
+ Clash.Netlist.Types: topEntityAnns :: Lens' NetlistState (VarEnv (Type, Maybe TopEntity))
- Clash.Netlist.Types: typeTranslator :: Lens' NetlistState (HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType))
+ Clash.Netlist.Types: typeTranslator :: Lens' NetlistState (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType)))
- Clash.Netlist.Util: coreTypeToHWType :: (HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType)) -> HashMap TyConOccName TyCon -> Bool -> Type -> Either String HWType
+ Clash.Netlist.Util: coreTypeToHWType :: (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> CustomReprs -> TyConMap -> Type -> State HWMap (Either String FilteredHWType)
- Clash.Netlist.Util: coreTypeToHWTypeM :: Type -> NetlistMonad (Maybe HWType)
+ Clash.Netlist.Util: coreTypeToHWTypeM :: Type -> NetlistMonad (Maybe FilteredHWType)
- Clash.Netlist.Util: genComponentName :: [Identifier] -> (IdType -> Identifier -> Identifier) -> TmName -> Identifier
+ Clash.Netlist.Util: genComponentName :: Bool -> HashMap Identifier Word -> (IdType -> Identifier -> Identifier) -> (Maybe Identifier, Maybe Identifier) -> Id -> Identifier
- Clash.Netlist.Util: idToPort :: Id -> NetlistMonad (Identifier, HWType)
+ Clash.Netlist.Util: idToPort :: Id -> NetlistMonad (Maybe (Identifier, HWType))
- Clash.Netlist.Util: isRecursiveTy :: HashMap TyConOccName TyCon -> TyConName -> Bool
+ Clash.Netlist.Util: isRecursiveTy :: TyConMap -> TyConName -> Bool
- Clash.Netlist.Util: mkADT :: (HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType)) -> HashMap TyConOccName TyCon -> String -> Bool -> TyConName -> [Type] -> Either String HWType
+ Clash.Netlist.Util: mkADT :: (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> CustomReprs -> TyConMap -> String -> TyConName -> [Type] -> ExceptT String (State HWMap) FilteredHWType
- Clash.Netlist.Util: mkOutput :: Maybe PortName -> (Identifier, HWType) -> NetlistMonad ([(Identifier, HWType)], [Declaration], Identifier)
+ Clash.Netlist.Util: mkOutput :: Maybe PortName -> (Identifier, HWType) -> NetlistMonad (Maybe ([(Identifier, HWType)], [Declaration], Identifier))
- Clash.Netlist.Util: mkTopOutput :: Maybe Identifier -> [(Identifier, Identifier)] -> Maybe PortName -> (Identifier, HWType) -> NetlistMonad ([(Identifier, Identifier)], ([(Identifier, Identifier, HWType)], [Declaration], Either Identifier (Identifier, HWType)))
+ Clash.Netlist.Util: mkTopOutput :: Maybe Identifier -> [(Identifier, Identifier)] -> Maybe PortName -> (Identifier, HWType) -> NetlistMonad (Maybe ([(Identifier, Identifier)], ([(Identifier, Identifier, HWType)], [Declaration], Either Identifier (Identifier, HWType))))
- Clash.Netlist.Util: mkTopUnWrapper :: TmName -> Maybe TopEntity -> Manifest -> (Identifier, HWType) -> [(Expr, HWType)] -> NetlistMonad [Declaration]
+ Clash.Netlist.Util: mkTopUnWrapper :: Id -> Maybe TopEntity -> Manifest -> (Identifier, HWType) -> [(Expr, HWType)] -> [Declaration] -> NetlistMonad [Declaration]
- Clash.Netlist.Util: mkUnique :: [(TmOccName, Term)] -> [Id] -> NetlistMonad ([Id], [(TmOccName, Term)])
+ Clash.Netlist.Util: mkUnique :: Subst -> [Id] -> NetlistMonad ([Id], Subst)
- Clash.Netlist.Util: mkUniqueArguments :: Maybe (Maybe TopEntity) -> [Id] -> NetlistMonad ([(Identifier, HWType)], [Declaration], [(TmOccName, Term)])
+ Clash.Netlist.Util: mkUniqueArguments :: Subst -> Maybe (Maybe TopEntity) -> [Id] -> NetlistMonad ([Bool], [(Identifier, HWType)], [Declaration], Subst)
- Clash.Netlist.Util: mkUniqueNormalized :: Maybe (Maybe TopEntity) -> ([Id], [LetBinding], Id) -> NetlistMonad ([(Identifier, HWType)], [Declaration], [(Identifier, HWType)], [Declaration], [LetBinding], TmName)
+ Clash.Netlist.Util: mkUniqueNormalized :: InScopeSet -> Maybe (Maybe TopEntity) -> ([Id], [LetBinding], Id) -> NetlistMonad ([Bool], [(Identifier, HWType)], [Declaration], [(Identifier, HWType)], [Declaration], [LetBinding], Maybe Id)
- Clash.Netlist.Util: mkUniqueResult :: Maybe (Maybe TopEntity) -> Id -> NetlistMonad ([(Identifier, HWType)], [Declaration], Id, (TmOccName, Term))
+ Clash.Netlist.Util: mkUniqueResult :: Subst -> Maybe (Maybe TopEntity) -> Id -> NetlistMonad (Maybe ([(Identifier, HWType)], [Declaration], Id, Subst))
- Clash.Netlist.Util: repName :: String -> Name a -> Name a
+ Clash.Netlist.Util: repName :: Text -> Name a -> Name a
- Clash.Netlist.Util: representableType :: (HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType)) -> Bool -> Bool -> HashMap TyConOccName TyCon -> Type -> Bool
+ Clash.Netlist.Util: representableType :: (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> CustomReprs -> Bool -> TyConMap -> Type -> Bool
- Clash.Netlist.Util: splitNormalized :: Fresh m => HashMap TyConOccName TyCon -> Term -> m (Either String ([Id], [LetBinding], Id))
+ Clash.Netlist.Util: splitNormalized :: TyConMap -> Term -> Either String ([Id], [LetBinding], Id)
- Clash.Netlist.Util: termHWTypeM :: Term -> NetlistMonad (Maybe HWType)
+ Clash.Netlist.Util: termHWTypeM :: Term -> NetlistMonad (Maybe FilteredHWType)
- Clash.Netlist.Util: unsafeCoreTypeToHWType :: SrcSpan -> String -> (HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType)) -> HashMap TyConOccName TyCon -> Bool -> Type -> HWType
+ Clash.Netlist.Util: unsafeCoreTypeToHWType :: SrcSpan -> String -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> CustomReprs -> TyConMap -> Type -> State HWMap FilteredHWType
- Clash.Netlist.Util: unsafeCoreTypeToHWTypeM :: String -> Type -> NetlistMonad HWType
+ Clash.Netlist.Util: unsafeCoreTypeToHWTypeM :: String -> Type -> NetlistMonad FilteredHWType
- Clash.Normalize: CBranch :: (TmOccName, (TmName, Type, SrcSpan, InlineSpec, Term)) -> [CallTree] -> CallTree
+ Clash.Normalize: CBranch :: (Id, (Id, SrcSpan, InlineSpec, Term)) -> [CallTree] -> CallTree
- Clash.Normalize: CLeaf :: (TmOccName, (TmName, Type, SrcSpan, InlineSpec, Term)) -> CallTree
+ Clash.Normalize: CLeaf :: (Id, (Id, SrcSpan, InlineSpec, Term)) -> CallTree
- Clash.Normalize: callTreeToList :: [TmOccName] -> CallTree -> ([TmOccName], [(TmOccName, (TmName, Type, SrcSpan, InlineSpec, Term))])
+ Clash.Normalize: callTreeToList :: [Id] -> CallTree -> ([Id], [(Id, (Id, SrcSpan, InlineSpec, Term))])
- Clash.Normalize: cleanupGraph :: TmOccName -> BindingMap -> NormalizeSession BindingMap
+ Clash.Normalize: cleanupGraph :: Id -> BindingMap -> NormalizeSession BindingMap
- Clash.Normalize: flattenNode :: CallTree -> NormalizeSession (Either CallTree ((TmOccName, Term), [CallTree]))
+ Clash.Normalize: flattenNode :: CallTree -> NormalizeSession (Either CallTree ((Id, Term), [CallTree]))
- Clash.Normalize: mkCallTree :: [TmOccName] -> BindingMap -> TmOccName -> Maybe CallTree
+ Clash.Normalize: mkCallTree :: [Id] -> BindingMap -> Id -> Maybe CallTree
- Clash.Normalize: normalize :: [TmOccName] -> NormalizeSession BindingMap
+ Clash.Normalize: normalize :: [Id] -> NormalizeSession BindingMap
- Clash.Normalize: normalize' :: TmOccName -> NormalizeSession ([TmOccName], (TmOccName, (TmName, Type, SrcSpan, InlineSpec, Term)))
+ Clash.Normalize: normalize' :: Id -> NormalizeSession ([Id], (Id, (Id, SrcSpan, InlineSpec, Term)))
- Clash.Normalize: runNormalization :: ClashOpts -> Supply -> BindingMap -> (HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType)) -> HashMap TyConOccName TyCon -> IntMap TyConName -> PrimEvaluator -> PrimMap BlackBoxTemplate -> HashMap TmOccName Bool -> [TmOccName] -> NormalizeSession a -> a
+ Clash.Normalize: runNormalization :: ClashOpts -> Supply -> BindingMap -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> CustomReprs -> TyConMap -> IntMap TyConName -> PrimEvaluator -> CompiledPrimMap -> VarEnv Bool -> [Id] -> NormalizeSession a -> a
- Clash.Normalize: stripArgs :: [TmOccName] -> [Id] -> [Either Term Type] -> Maybe [Either Term Type]
+ Clash.Normalize: stripArgs :: [Id] -> [Id] -> [Either Term Type] -> Maybe [Either Term Type]
- Clash.Normalize.DEC: collectGlobals :: Set TmOccName -> [(Term, Term)] -> [Term] -> Term -> RewriteMonad NormalizeState (Term, [(Term, ([Term], CaseTree [(Either Term Type)]))])
+ Clash.Normalize.DEC: collectGlobals :: InScopeSet -> [(Term, Term)] -> [Term] -> Term -> RewriteMonad NormalizeState (Term, [(Term, ([Term], CaseTree [Either Term Type]))])
- Clash.Normalize.DEC: isDisjoint :: CaseTree ([Either Term Type]) -> Bool
+ Clash.Normalize.DEC: isDisjoint :: CaseTree [Either Term Type] -> Bool
- Clash.Normalize.DEC: mkDisjointGroup :: Set TmOccName -> (Term, ([Term], CaseTree [(Either Term Type)])) -> RewriteMonad NormalizeState (Term, [Term])
+ Clash.Normalize.DEC: mkDisjointGroup :: InScopeSet -> (Term, ([Term], CaseTree [Either Term Type])) -> RewriteMonad NormalizeState (Term, [Term])
- Clash.Normalize.PrimitiveReductions: reduceAppend :: Integer -> Integer -> Type -> Term -> Term -> NormalizeSession Term
+ Clash.Normalize.PrimitiveReductions: reduceAppend :: InScopeSet -> Integer -> Integer -> Type -> Term -> Term -> NormalizeSession Term
- Clash.Normalize.PrimitiveReductions: reduceDFold :: Integer -> Type -> Term -> Term -> Term -> NormalizeSession Term
+ Clash.Normalize.PrimitiveReductions: reduceDFold :: InScopeSet -> Integer -> Type -> Term -> Term -> Term -> NormalizeSession Term
- Clash.Normalize.PrimitiveReductions: reduceDTFold :: Integer -> Type -> Term -> Term -> Term -> NormalizeSession Term
+ Clash.Normalize.PrimitiveReductions: reduceDTFold :: InScopeSet -> Integer -> Type -> Term -> Term -> Term -> NormalizeSession Term
- Clash.Normalize.PrimitiveReductions: reduceFold :: Integer -> Type -> Term -> Term -> NormalizeSession Term
+ Clash.Normalize.PrimitiveReductions: reduceFold :: TransformContext -> Integer -> Type -> Term -> Term -> NormalizeSession Term
- Clash.Normalize.PrimitiveReductions: reduceFoldr :: Integer -> Type -> Term -> Term -> Term -> NormalizeSession Term
+ Clash.Normalize.PrimitiveReductions: reduceFoldr :: TransformContext -> Integer -> Type -> Term -> Term -> Term -> NormalizeSession Term
- Clash.Normalize.PrimitiveReductions: reduceHead :: Integer -> Type -> Term -> NormalizeSession Term
+ Clash.Normalize.PrimitiveReductions: reduceHead :: InScopeSet -> Integer -> Type -> Term -> NormalizeSession Term
- Clash.Normalize.PrimitiveReductions: reduceImap :: Integer -> Type -> Type -> Term -> Term -> NormalizeSession Term
+ Clash.Normalize.PrimitiveReductions: reduceImap :: TransformContext -> Integer -> Type -> Type -> Term -> Term -> NormalizeSession Term
- Clash.Normalize.PrimitiveReductions: reduceInit :: Integer -> Type -> Term -> NormalizeSession Term
+ Clash.Normalize.PrimitiveReductions: reduceInit :: InScopeSet -> Integer -> Type -> Term -> NormalizeSession Term
- Clash.Normalize.PrimitiveReductions: reduceLast :: Integer -> Type -> Term -> NormalizeSession Term
+ Clash.Normalize.PrimitiveReductions: reduceLast :: InScopeSet -> Integer -> Type -> Term -> NormalizeSession Term
- Clash.Normalize.PrimitiveReductions: reduceMap :: Integer -> Type -> Type -> Term -> Term -> NormalizeSession Term
+ Clash.Normalize.PrimitiveReductions: reduceMap :: TransformContext -> Integer -> Type -> Type -> Term -> Term -> NormalizeSession Term
- Clash.Normalize.PrimitiveReductions: reduceTFold :: Integer -> Type -> Term -> Term -> Term -> NormalizeSession Term
+ Clash.Normalize.PrimitiveReductions: reduceTFold :: InScopeSet -> Integer -> Type -> Term -> Term -> Term -> NormalizeSession Term
- Clash.Normalize.PrimitiveReductions: reduceTail :: Integer -> Type -> Term -> NormalizeSession Term
+ Clash.Normalize.PrimitiveReductions: reduceTail :: InScopeSet -> Integer -> Type -> Term -> NormalizeSession Term
- Clash.Normalize.PrimitiveReductions: reduceTraverse :: Integer -> Type -> Type -> Type -> Term -> Term -> Term -> NormalizeSession Term
+ Clash.Normalize.PrimitiveReductions: reduceTraverse :: TransformContext -> Integer -> Type -> Type -> Type -> Term -> Term -> Term -> NormalizeSession Term
- Clash.Normalize.PrimitiveReductions: reduceZipWith :: Integer -> Type -> Type -> Type -> Term -> Term -> Term -> NormalizeSession Term
+ Clash.Normalize.PrimitiveReductions: reduceZipWith :: TransformContext -> Integer -> Type -> Type -> Type -> Term -> Term -> Term -> NormalizeSession Term
- Clash.Normalize.Transformations: appProp :: NormRewrite
+ Clash.Normalize.Transformations: appProp :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: argCastSpec :: NormRewrite
+ Clash.Normalize.Transformations: argCastSpec :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: bindConstantVar :: NormRewrite
+ Clash.Normalize.Transformations: bindConstantVar :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: caseCase :: NormRewrite
+ Clash.Normalize.Transformations: caseCase :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: caseCast :: NormRewrite
+ Clash.Normalize.Transformations: caseCast :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: caseCon :: NormRewrite
+ Clash.Normalize.Transformations: caseCon :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: caseFlat :: NormRewrite
+ Clash.Normalize.Transformations: caseFlat :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: caseLet :: NormRewrite
+ Clash.Normalize.Transformations: caseLet :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: constantSpec :: NormRewrite
+ Clash.Normalize.Transformations: constantSpec :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: deadCode :: NormRewrite
+ Clash.Normalize.Transformations: deadCode :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: disjointExpressionConsolidation :: NormRewrite
+ Clash.Normalize.Transformations: disjointExpressionConsolidation :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: eliminateCastCast :: NormRewrite
+ Clash.Normalize.Transformations: eliminateCastCast :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: etaExpansionTL :: NormRewrite
+ Clash.Normalize.Transformations: etaExpansionTL :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: flattenLet :: NormRewrite
+ Clash.Normalize.Transformations: flattenLet :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: inlineCast :: NormRewrite
+ Clash.Normalize.Transformations: inlineCast :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: inlineCleanup :: NormRewrite
+ Clash.Normalize.Transformations: inlineCleanup :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: inlineHO :: NormRewrite
+ Clash.Normalize.Transformations: inlineHO :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: inlineNonRep :: NormRewrite
+ Clash.Normalize.Transformations: inlineNonRep :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: inlineOrLiftNonRep :: NormRewrite
+ Clash.Normalize.Transformations: inlineOrLiftNonRep :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: inlineSmall :: NormRewrite
+ Clash.Normalize.Transformations: inlineSmall :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: inlineWorkFree :: NormRewrite
+ Clash.Normalize.Transformations: inlineWorkFree :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: letCast :: NormRewrite
+ Clash.Normalize.Transformations: letCast :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: makeANF :: NormRewrite
+ Clash.Normalize.Transformations: makeANF :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: nonRepANF :: NormRewrite
+ Clash.Normalize.Transformations: nonRepANF :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: nonRepSpec :: NormRewrite
+ Clash.Normalize.Transformations: nonRepSpec :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: recToLetRec :: NormRewrite
+ Clash.Normalize.Transformations: recToLetRec :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: reduceConst :: NormRewrite
+ Clash.Normalize.Transformations: reduceConst :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: reduceNonRepPrim :: NormRewrite
+ Clash.Normalize.Transformations: reduceNonRepPrim :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: removeUnusedExpr :: NormRewrite
+ Clash.Normalize.Transformations: removeUnusedExpr :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: simpleCSE :: NormRewrite
+ Clash.Normalize.Transformations: simpleCSE :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: splitCastWork :: NormRewrite
+ Clash.Normalize.Transformations: splitCastWork :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: topLet :: NormRewrite
+ Clash.Normalize.Transformations: topLet :: HasCallStack => NormRewrite
- Clash.Normalize.Transformations: typeSpec :: NormRewrite
+ Clash.Normalize.Transformations: typeSpec :: HasCallStack => NormRewrite
- Clash.Normalize.Types: NormalizeState :: BindingMap -> Map (TmOccName, Int, Either Term Type) (TmName, Type) -> HashMap TmOccName Int -> !Int -> HashMap TmOccName (HashMap TmOccName Int) -> !Int -> !Word -> !Word -> PrimMap BlackBoxTemplate -> HashMap TmOccName Bool -> NormalizeState
+ 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 -> NormalizeState
- Clash.Normalize.Types: [_inlineHistory] :: NormalizeState -> HashMap TmOccName (HashMap TmOccName Int)
+ Clash.Normalize.Types: [_inlineHistory] :: NormalizeState -> VarEnv (VarEnv Int)
- Clash.Normalize.Types: [_primitives] :: NormalizeState -> PrimMap BlackBoxTemplate
+ Clash.Normalize.Types: [_primitives] :: NormalizeState -> CompiledPrimMap
- Clash.Normalize.Types: [_recursiveComponents] :: NormalizeState -> HashMap TmOccName Bool
+ Clash.Normalize.Types: [_recursiveComponents] :: NormalizeState -> VarEnv Bool
- Clash.Normalize.Types: [_specialisationCache] :: NormalizeState -> Map (TmOccName, Int, Either Term Type) (TmName, Type)
+ Clash.Normalize.Types: [_specialisationCache] :: NormalizeState -> Map (Id, Int, Either Term Type) Id
- Clash.Normalize.Types: [_specialisationHistory] :: NormalizeState -> HashMap TmOccName Int
+ Clash.Normalize.Types: [_specialisationHistory] :: NormalizeState -> VarEnv Int
- Clash.Normalize.Types: inlineHistory :: Lens' NormalizeState (HashMap TmOccName (HashMap TmOccName Int))
+ Clash.Normalize.Types: inlineHistory :: Lens' NormalizeState (VarEnv (VarEnv Int))
- Clash.Normalize.Types: primitives :: Lens' NormalizeState (PrimMap BlackBoxTemplate)
+ Clash.Normalize.Types: primitives :: Lens' NormalizeState CompiledPrimMap
- Clash.Normalize.Types: recursiveComponents :: Lens' NormalizeState (HashMap TmOccName Bool)
+ Clash.Normalize.Types: recursiveComponents :: Lens' NormalizeState (VarEnv Bool)
- Clash.Normalize.Types: specialisationCache :: Lens' NormalizeState (Map (TmOccName, Int, Either Term Type) (TmName, Type))
+ Clash.Normalize.Types: specialisationCache :: Lens' NormalizeState (Map (Id, Int, Either Term Type) Id)
- Clash.Normalize.Types: specialisationHistory :: Lens' NormalizeState (HashMap TmOccName Int)
+ Clash.Normalize.Types: specialisationHistory :: Lens' NormalizeState (VarEnv Int)
- Clash.Normalize.Util: addNewInline :: TmOccName -> TmOccName -> NormalizeMonad ()
+ Clash.Normalize.Util: addNewInline :: Id -> Id -> NormalizeMonad ()
- Clash.Normalize.Util: alreadyInlined :: TmOccName -> TmOccName -> NormalizeMonad (Maybe Int)
+ Clash.Normalize.Util: alreadyInlined :: Id -> Id -> NormalizeMonad (Maybe Int)
- Clash.Normalize.Util: callGraph :: BindingMap -> TmOccName -> CallGraph
+ Clash.Normalize.Util: callGraph :: BindingMap -> Id -> CallGraph
- Clash.Normalize.Util: isClosed :: Fresh m => HashMap TyConOccName TyCon -> Term -> m Bool
+ Clash.Normalize.Util: isClosed :: TyConMap -> Term -> Bool
- Clash.Normalize.Util: isRecursiveBndr :: TmOccName -> NormalizeSession Bool
+ Clash.Normalize.Util: isRecursiveBndr :: Id -> NormalizeSession Bool
- Clash.Primitives.Types: BlackBox :: !Text -> Bool -> [a] -> [a] -> Maybe ((Text, Text), a) -> !(Either a a) -> Primitive a
+ Clash.Primitives.Types: BlackBox :: !Text -> WorkInfo -> TemplateKind -> c -> Bool -> [a] -> [a] -> [((Text, Text), b)] -> b -> Primitive a b c d
- Clash.Primitives.Types: Primitive :: !Text -> !Text -> Primitive a
+ Clash.Primitives.Types: Primitive :: !Text -> WorkInfo -> !Text -> Primitive a b c d
- Clash.Primitives.Types: [imports] :: Primitive a -> [a]
+ Clash.Primitives.Types: [imports] :: Primitive a b c d -> [a]
- Clash.Primitives.Types: [name] :: Primitive a -> !Text
+ Clash.Primitives.Types: [name] :: Primitive a b c d -> !Text
- Clash.Primitives.Types: [outputReg] :: Primitive a -> Bool
+ Clash.Primitives.Types: [outputReg] :: Primitive a b c d -> Bool
- Clash.Primitives.Types: [template] :: Primitive a -> !(Either a a)
+ Clash.Primitives.Types: [template] :: Primitive a b c d -> b
- Clash.Primitives.Types: data Primitive a
+ Clash.Primitives.Types: data Primitive a b c d
- Clash.Primitives.Types: type PrimMap a = HashMap Text (Primitive a)
+ Clash.Primitives.Types: type PrimMap a = HashMap Text a
- Clash.Primitives.Util: generatePrimMap :: [FilePath] -> IO (PrimMap Text)
+ Clash.Primitives.Util: generatePrimMap :: HasCallStack => [UnresolvedPrimitive] -> [(Text, PrimitiveGuard ())] -> [FilePath] -> IO ResolvedPrimMap
- Clash.Rewrite.Combinators: allR :: forall m. (Monad m, Fresh m) => Bool -> Transform m -> Transform m
+ Clash.Rewrite.Combinators: allR :: forall m. Monad m => Transform m -> Transform m
- Clash.Rewrite.Combinators: bottomupR :: Fresh m => Transform m -> Transform m
+ Clash.Rewrite.Combinators: bottomupR :: Monad m => Transform m -> Transform m
- Clash.Rewrite.Combinators: bottomupWhenR :: Fresh m => ([CoreContext] -> Term -> m Bool) -> Transform m -> Transform m
+ Clash.Rewrite.Combinators: bottomupWhenR :: Monad m => (TransformContext -> Term -> m Bool) -> Transform m -> Transform m
- Clash.Rewrite.Combinators: infixr 6 >-!->
+ Clash.Rewrite.Combinators: infixr 6 >->
- Clash.Rewrite.Combinators: whenR :: Monad m => ([CoreContext] -> Term -> m Bool) -> Transform m -> Transform m
+ Clash.Rewrite.Combinators: whenR :: Monad m => (TransformContext -> Term -> m Bool) -> Transform m -> Transform m
- Clash.Rewrite.Types: R :: RewriteEnv -> RewriteState extra -> (a, RewriteState extra, Any) -> RewriteMonad extra a
+ Clash.Rewrite.Types: R :: (RewriteEnv -> RewriteState extra -> Any -> (a, RewriteState extra, Any)) -> RewriteMonad extra a
- Clash.Rewrite.Types: RewriteEnv :: DebugLevel -> HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType) -> HashMap TyConOccName TyCon -> IntMap TyConName -> PrimEvaluator -> Bool -> HashSet TmOccName -> RewriteEnv
+ Clash.Rewrite.Types: RewriteEnv :: DebugLevel -> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) -> TyConMap -> IntMap TyConName -> PrimEvaluator -> VarSet -> CustomReprs -> RewriteEnv
- Clash.Rewrite.Types: RewriteState :: {-# UNPACK #-} !Int -> !BindingMap -> !Supply -> (TmName, SrcSpan) -> {-# UNPACK #-} !Int -> GlobalHeap -> !extra -> RewriteState extra
+ Clash.Rewrite.Types: RewriteState :: {-# UNPACK #-} !Int -> !BindingMap -> !Supply -> (Id, SrcSpan) -> {-# UNPACK #-} !Int -> GlobalHeap -> !extra -> RewriteState extra
- Clash.Rewrite.Types: [_curFun] :: RewriteState extra -> (TmName, SrcSpan)
+ Clash.Rewrite.Types: [_curFun] :: RewriteState extra -> (Id, SrcSpan)
- Clash.Rewrite.Types: [_tcCache] :: RewriteEnv -> HashMap TyConOccName TyCon
+ Clash.Rewrite.Types: [_tcCache] :: RewriteEnv -> TyConMap
- Clash.Rewrite.Types: [_topEntities] :: RewriteEnv -> HashSet TmOccName
+ Clash.Rewrite.Types: [_topEntities] :: RewriteEnv -> VarSet
- Clash.Rewrite.Types: [_typeTranslator] :: RewriteEnv -> HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType)
+ Clash.Rewrite.Types: [_typeTranslator] :: RewriteEnv -> CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))
- Clash.Rewrite.Types: bindings :: forall extra_a47Db. Lens' (RewriteState extra_a47Db) BindingMap
+ Clash.Rewrite.Types: bindings :: forall extra_a2RTM. Lens' (RewriteState extra_a2RTM) BindingMap
- Clash.Rewrite.Types: curFun :: forall extra_a47Db. Lens' (RewriteState extra_a47Db) (TmName, SrcSpan)
+ Clash.Rewrite.Types: curFun :: forall extra_a2RTM. Lens' (RewriteState extra_a2RTM) (Id, SrcSpan)
- Clash.Rewrite.Types: extra :: forall extra_a47Db extra_a47Ib. Lens (RewriteState extra_a47Db) (RewriteState extra_a47Ib) extra_a47Db extra_a47Ib
+ Clash.Rewrite.Types: extra :: forall extra_a2RTM extra_a2S2f. Lens (RewriteState extra_a2RTM) (RewriteState extra_a2S2f) extra_a2RTM extra_a2S2f
- Clash.Rewrite.Types: globalHeap :: forall extra_a47Db. Lens' (RewriteState extra_a47Db) GlobalHeap
+ Clash.Rewrite.Types: globalHeap :: forall extra_a2RTM. Lens' (RewriteState extra_a2RTM) GlobalHeap
- Clash.Rewrite.Types: nameCounter :: forall extra_a47Db. Lens' (RewriteState extra_a47Db) Int
+ Clash.Rewrite.Types: nameCounter :: forall extra_a2RTM. Lens' (RewriteState extra_a2RTM) Int
- Clash.Rewrite.Types: tcCache :: Lens' RewriteEnv (HashMap TyConOccName TyCon)
+ Clash.Rewrite.Types: tcCache :: Lens' RewriteEnv TyConMap
- Clash.Rewrite.Types: topEntities :: Lens' RewriteEnv (HashSet TmOccName)
+ Clash.Rewrite.Types: topEntities :: Lens' RewriteEnv VarSet
- Clash.Rewrite.Types: transformCounter :: forall extra_a47Db. Lens' (RewriteState extra_a47Db) Int
+ Clash.Rewrite.Types: transformCounter :: forall extra_a2RTM. Lens' (RewriteState extra_a2RTM) Int
- Clash.Rewrite.Types: type Transform m = [CoreContext] -> Term -> m Term
+ Clash.Rewrite.Types: type Transform m = TransformContext -> Term -> m Term
- Clash.Rewrite.Types: typeTranslator :: Lens' RewriteEnv (HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType))
+ Clash.Rewrite.Types: typeTranslator :: Lens' RewriteEnv (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType)))
- Clash.Rewrite.Types: uniqSupply :: forall extra_a47Db. Lens' (RewriteState extra_a47Db) Supply
+ Clash.Rewrite.Types: uniqSupply :: forall extra_a2RTM. Lens' (RewriteState extra_a2RTM) Supply
- Clash.Rewrite.Util: closestLetBinder :: [CoreContext] -> Maybe Id
+ Clash.Rewrite.Util: closestLetBinder :: Context -> Maybe Id
- Clash.Rewrite.Util: liftBinding :: Gamma -> Delta -> LetBinding -> RewriteMonad extra LetBinding
+ Clash.Rewrite.Util: liftBinding :: LetBinding -> RewriteMonad extra LetBinding
- Clash.Rewrite.Util: mkBinderFor :: (Monad m, MonadUnique m, Fresh m) => HashMap TyConOccName TyCon -> Name a -> Either Term Type -> m (Either (Id, Term) (TyVar, Type))
+ Clash.Rewrite.Util: mkBinderFor :: (Monad m, MonadUnique m, MonadFail m) => InScopeSet -> TyConMap -> Name a -> Either Term Type -> m (Either Id TyVar)
- Clash.Rewrite.Util: mkDerivedName :: [CoreContext] -> String -> TmName
+ Clash.Rewrite.Util: mkDerivedName :: TransformContext -> OccName -> TmName
- Clash.Rewrite.Util: mkFunction :: TmName -> SrcSpan -> InlineSpec -> Term -> RewriteMonad extra (TmName, Type)
+ Clash.Rewrite.Util: mkFunction :: TmName -> SrcSpan -> InlineSpec -> Term -> RewriteMonad extra Id
- Clash.Rewrite.Util: mkInternalVar :: (Monad m, MonadUnique m) => TmName -> KindOrType -> m (Id, Term)
+ Clash.Rewrite.Util: mkInternalVar :: (Monad m, MonadUnique m) => InScopeSet -> OccName -> KindOrType -> m Id
- Clash.Rewrite.Util: mkSelectorCase :: (Functor m, Monad m, MonadUnique m, Fresh m) => String -> HashMap TyConOccName TyCon -> Term -> Int -> Int -> m Term
+ Clash.Rewrite.Util: mkSelectorCase :: HasCallStack => (Functor m, Monad m, MonadUnique m) => String -> InScopeSet -> TyConMap -> Term -> Int -> Int -> m Term
- Clash.Rewrite.Util: mkTmBinderFor :: (Fresh m, MonadUnique m) => HashMap TyConOccName TyCon -> Name a -> Term -> m (Id, Term)
+ Clash.Rewrite.Util: mkTmBinderFor :: (Monad m, MonadUnique m, MonadFail m) => InScopeSet -> TyConMap -> Name a -> Term -> m Id
- Clash.Rewrite.Util: mkWildValBinder :: (Monad m, MonadUnique m) => Type -> m Id
+ Clash.Rewrite.Util: mkWildValBinder :: (Monad m, MonadUnique m) => InScopeSet -> Type -> m Id
- Clash.Rewrite.Util: normalizeId :: HashMap TyConOccName TyCon -> Id -> Id
+ Clash.Rewrite.Util: normalizeId :: TyConMap -> Id -> Id
- Clash.Rewrite.Util: normalizeTermTypes :: HashMap TyConOccName TyCon -> Term -> Term
+ Clash.Rewrite.Util: normalizeTermTypes :: TyConMap -> Term -> Term
- Clash.Rewrite.Util: runRewrite :: String -> Rewrite extra -> Term -> RewriteMonad extra Term
+ Clash.Rewrite.Util: runRewrite :: String -> InScopeSet -> Rewrite extra -> Term -> RewriteMonad extra Term
- Clash.Rewrite.Util: specArgBndrsAndVars :: [CoreContext] -> Either Term Type -> RewriteMonad extra ([Either Id TyVar], [Either Term Type])
+ Clash.Rewrite.Util: specArgBndrsAndVars :: Either Term Type -> ([Either Id TyVar], [Either Term Type])
- Clash.Rewrite.Util: specialise :: Lens' extra (Map (TmOccName, Int, Either Term Type) (TmName, Type)) -> Lens' extra (HashMap TmOccName 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 -> Rewrite extra
- Clash.Rewrite.Util: specialise' :: Lens' extra (Map (TmOccName, Int, Either Term Type) (TmName, Type)) -> Lens' extra (HashMap TmOccName Int) -> Lens' extra Int -> [CoreContext] -> Term -> (Term, [Either Term Type]) -> Either Term Type -> RewriteMonad extra Term
+ 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: substituteBinders :: [LetBinding] -> [LetBinding] -> Term -> ([LetBinding], Term)
+ Clash.Rewrite.Util: substituteBinders :: InScopeSet -> [LetBinding] -> [LetBinding] -> Term -> ([LetBinding], Term)
- Clash.Util: (<$>) :: Functor f => a -> b -> f a -> f b
+ Clash.Util: (<$>) :: Functor f => (a -> b) -> f a -> f b
- Clash.Util: (<*>) :: Applicative f => f a -> b -> f a -> f b
+ Clash.Util: (<*>) :: Applicative f => f (a -> b) -> f a -> f b
- Clash.Util: (<=<) :: Monad m => b -> m c -> a -> m b -> a -> m 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: (>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
- Clash.Util: class Functor f => Applicative (f :: * -> *)
+ Clash.Util: class Functor f => Applicative (f :: Type -> Type)
- Clash.Util: combineM :: (Applicative f) => (a -> f b) -> (c -> f d) -> (a, c) -> f (b, d)
+ Clash.Util: combineM :: Applicative f => (a -> f b) -> (c -> f d) -> (a, c) -> f (b, d)
- Clash.Util: infixr 3 ***
+ Clash.Util: infixr 3 &&&
- Clash.Util: liftState :: (MonadState s m) => Lens' s s' -> State s' a -> m a
+ Clash.Util: liftState :: MonadState s m => Lens' s s' -> State s' a -> m a
- Clash.Util: mapAccumLM :: (Monad m) => (acc -> x -> m (acc, y)) -> acc -> [x] -> m (acc, [y])
+ Clash.Util: mapAccumLM :: Monad m => (acc -> x -> m (acc, y)) -> acc -> [x] -> m (acc, [y])
- Clash.Util: on :: () => b -> b -> c -> a -> b -> a -> a -> c
+ Clash.Util: on :: () => (b -> b -> c) -> (a -> b) -> a -> a -> c
Files
- CHANGELOG.md +126/−0
- LICENSE +1/−1
- README.md +6/−6
- clash-lib.cabal +61/−24
- prims/common/Clash_Annotations_BitRepresentation_Deriving.json +9/−0
- prims/common/Clash_Class_BitPack.json +12/−4
- prims/common/Clash_Explicit_Signal.json +8/−6
- prims/common/Clash_GHC_GHC2Core.json +5/−1
- prims/common/Clash_Intel_ClockGen.json +17/−0
- prims/common/Clash_Magic.json +16/−0
- prims/common/Clash_Promoted_Nat.json +9/−0
- prims/common/Clash_Promoted_Nat_Unsafe.json +3/−1
- prims/common/Clash_Promoted_Symbol.json +6/−2
- prims/common/Clash_Signal_BiSignal.json +30/−0
- prims/common/Clash_Signal_Bundle.json +1/−0
- prims/common/Clash_Signal_Internal.json +37/−0
- prims/common/Clash_Sized_Internal_BitVector.json +43/−0
- prims/common/Clash_Sized_Internal_Index.json +8/−0
- prims/common/Clash_Sized_Internal_Signed.json +22/−0
- prims/common/Clash_Sized_Internal_Unsigned.json +22/−0
- prims/common/Clash_Sized_RTree.json +7/−0
- prims/common/Clash_Sized_Vector.json +47/−0
- prims/common/Clash_Transformations.json +11/−1
- prims/common/Clash_XException.json +15/−3
- prims/common/Control_Exception_Base.json +56/−8
- prims/common/Debug_Trace.json +3/−1
- prims/common/GHC_Base.json +14/−0
- prims/common/GHC_CString.json +7/−2
- prims/common/GHC_Classes.json +29/−0
- prims/common/GHC_Err.json +9/−3
- prims/common/GHC_IO_Exception.json +3/−1
- prims/common/GHC_Integer_Type.json +50/−0
- prims/common/GHC_Magic.json +9/−0
- prims/common/GHC_Natural.json +32/−8
- prims/common/GHC_Prim.json +54/−4
- prims/common/GHC_Real.json +9/−3
- prims/common/GHC_TypeNats.json +3/−1
- prims/common/GHC_Typelits.json +3/−1
- prims/common/GHC_Types.json +31/−0
- prims/common/Unsafe_Coerce.json +3/−1
- prims/commonverilog/Clash_Class_Exp.json +29/−0
- prims/commonverilog/Clash_Intel_DDR.json +49/−0
- prims/commonverilog/Clash_Promoted_Nat.json +36/−33
- prims/commonverilog/Clash_Signal_Internal.json +27/−0
- prims/commonverilog/Clash_Sized_Internal_BitVector.json +281/−55
- prims/commonverilog/Clash_Sized_Internal_Index.json +45/−26
- prims/commonverilog/Clash_Sized_Internal_Signed.json +172/−7
- prims/commonverilog/Clash_Sized_Internal_Unsigned.json +155/−7
- prims/commonverilog/Clash_Sized_Vector.json +17/−0
- prims/commonverilog/Clash_Transformations.json +8/−0
- prims/commonverilog/Clash_Xilinx_ClockGen.json +47/−0
- prims/commonverilog/GHC_Base.json +8/−0
- prims/commonverilog/GHC_Classes.json +36/−0
- prims/commonverilog/GHC_Int.json +30/−0
- prims/commonverilog/GHC_Integer_Logarithms.json +11/−9
- prims/commonverilog/GHC_Integer_Type.json +189/−0
- prims/commonverilog/GHC_Natural.json +31/−0
- prims/commonverilog/GHC_Prim.json +398/−0
- prims/commonverilog/GHC_Word.json +30/−0
- prims/systemverilog/Clash_Explicit_BlockRam.json +122/−26
- prims/systemverilog/Clash_Explicit_BlockRam_File.json +31/−27
- prims/systemverilog/Clash_Explicit_DDR.json +60/−95
- prims/systemverilog/Clash_Explicit_RAM.json +19/−20
- prims/systemverilog/Clash_Explicit_ROM.json +18/−14
- prims/systemverilog/Clash_Explicit_ROM_File.json +17/−14
- prims/systemverilog/Clash_Explicit_Testbench.json +45/−12
- prims/systemverilog/Clash_Intel_ClockGen.json +0/−37
- prims/systemverilog/Clash_Intel_DDR.json +33/−74
- prims/systemverilog/Clash_Prelude_ROM.json +3/−2
- prims/systemverilog/Clash_Prelude_ROM_File.json +2/−1
- prims/systemverilog/Clash_Signal_BiSignal.json +34/−0
- prims/systemverilog/Clash_Signal_Internal.json +83/−145
- prims/systemverilog/Clash_Sized_Internal_BitVector.json +18/−180
- prims/systemverilog/Clash_Sized_Internal_Signed.json +14/−168
- prims/systemverilog/Clash_Sized_Internal_Unsigned.json +10/−140
- prims/systemverilog/Clash_Sized_RTree.json +9/−3
- prims/systemverilog/Clash_Sized_Vector.json +88/−59
- prims/systemverilog/Clash_Xilinx_ClockGen.json +0/−39
- prims/systemverilog/Clash_Xilinx_DDR.json +35/−35
- prims/systemverilog/GHC_Base.json +5/−20
- prims/systemverilog/GHC_Classes.json +4/−56
- prims/systemverilog/GHC_Int.json +0/−25
- prims/systemverilog/GHC_Integer_Type.json +4/−152
- prims/systemverilog/GHC_Prim.json +242/−597
- prims/systemverilog/GHC_Types.json +0/−24
- prims/systemverilog/GHC_Word.json +0/−25
- prims/verilog/Clash_Explicit_BlockRam.json +129/−28
- prims/verilog/Clash_Explicit_BlockRam_File.json +29/−25
- prims/verilog/Clash_Explicit_DDR.json +57/−100
- prims/verilog/Clash_Explicit_RAM.json +19/−21
- prims/verilog/Clash_Explicit_ROM.json +21/−17
- prims/verilog/Clash_Explicit_ROM_File.json +17/−14
- prims/verilog/Clash_Explicit_Testbench.json +45/−12
- prims/verilog/Clash_Intel_ClockGen.json +0/−37
- prims/verilog/Clash_Intel_DDR.json +33/−74
- prims/verilog/Clash_Prelude_ROM.json +3/−2
- prims/verilog/Clash_Prelude_ROM_File.json +2/−1
- prims/verilog/Clash_Signal_BiSignal.json +34/−0
- prims/verilog/Clash_Signal_Internal.json +83/−150
- prims/verilog/Clash_Sized_Internal_BitVector.json +17/−180
- prims/verilog/Clash_Sized_Internal_Signed.json +14/−168
- prims/verilog/Clash_Sized_Internal_Unsigned.json +10/−140
- prims/verilog/Clash_Sized_RTree.json +9/−3
- prims/verilog/Clash_Sized_Vector.json +101/−79
- prims/verilog/Clash_Xilinx_ClockGen.json +0/−39
- prims/verilog/Clash_Xilinx_DDR.json +37/−37
- prims/verilog/GHC_Base.json +5/−20
- prims/verilog/GHC_Classes.json +4/−56
- prims/verilog/GHC_Int.json +0/−25
- prims/verilog/GHC_Integer_Type.json +4/−152
- prims/verilog/GHC_Prim.json +257/−612
- prims/verilog/GHC_Types.json +0/−24
- prims/verilog/GHC_Word.json +0/−25
- prims/vhdl/Clash_Class_Exp.json +29/−0
- prims/vhdl/Clash_Explicit_BlockRam.json +160/−57
- prims/vhdl/Clash_Explicit_BlockRam_File.json +48/−48
- prims/vhdl/Clash_Explicit_DDR.json +86/−212
- prims/vhdl/Clash_Explicit_RAM.json +29/−38
- prims/vhdl/Clash_Explicit_ROM.json +20/−37
- prims/vhdl/Clash_Explicit_ROM_File.json +20/−20
- prims/vhdl/Clash_Explicit_Testbench.json +123/−22
- prims/vhdl/Clash_Intel_ClockGen.json +0/−59
- prims/vhdl/Clash_Intel_DDR.json +33/−37
- prims/vhdl/Clash_Prelude_ROM.json +3/−2
- prims/vhdl/Clash_Prelude_ROM_File.json +2/−1
- prims/vhdl/Clash_Promoted_Nat.json +9/−9
- prims/vhdl/Clash_Signal_BiSignal.json +34/−0
- prims/vhdl/Clash_Signal_Internal.json +147/−176
- prims/vhdl/Clash_Sized_Internal_BitVector.json +181/−111
- prims/vhdl/Clash_Sized_Internal_Index.json +45/−26
- prims/vhdl/Clash_Sized_Internal_Signed.json +73/−50
- prims/vhdl/Clash_Sized_Internal_Unsigned.json +65/−47
- prims/vhdl/Clash_Sized_RTree.json +9/−3
- prims/vhdl/Clash_Sized_Vector.json +86/−42
- prims/vhdl/Clash_Transformations.json +8/−0
- prims/vhdl/Clash_Xilinx_ClockGen.json +24/−16
- prims/vhdl/Clash_Xilinx_DDR.json +39/−45
- prims/vhdl/GHC_Base.json +7/−15
- prims/vhdl/GHC_Classes.json +14/−31
- prims/vhdl/GHC_Int.json +12/−4
- prims/vhdl/GHC_Integer_Logarithms.json +2/−1
- prims/vhdl/GHC_Integer_Type.json +108/−62
- prims/vhdl/GHC_Natural.json +32/−0
- prims/vhdl/GHC_Prim.json +154/−126
- prims/vhdl/GHC_Types.json +0/−24
- prims/vhdl/GHC_Word.json +12/−4
- src/Clash/Annotations/BitRepresentation/ClashLib.hs +55/−0
- src/Clash/Annotations/TopEntity/Extra.hs +22/−0
- src/Clash/Backend.hs +64/−60
- src/Clash/Backend/SystemVerilog.hs +544/−272
- src/Clash/Backend/VHDL.hs +2005/−1206
- src/Clash/Backend/Verilog.hs +439/−149
- src/Clash/Core/DataCon.hs +29/−76
- src/Clash/Core/Evaluator.hs +335/−184
- src/Clash/Core/FreeVars.hs +312/−13
- src/Clash/Core/Literal.hs +3/−10
- src/Clash/Core/Name.hs +35/−54
- src/Clash/Core/Pretty.hs +333/−234
- src/Clash/Core/Subst.hs +784/−46
- src/Clash/Core/Subst.hs-boot +21/−0
- src/Clash/Core/Term.hs +173/−33
- src/Clash/Core/Term.hs-boot +1/−0
- src/Clash/Core/TyCon.hs +34/−57
- src/Clash/Core/TyCon.hs-boot +1/−2
- src/Clash/Core/Type.hs +228/−180
- src/Clash/Core/Type.hs-boot +2/−8
- src/Clash/Core/TysPrim.hs +55/−62
- src/Clash/Core/Util.hs +715/−230
- src/Clash/Core/Var.hs +126/−19
- src/Clash/Core/VarEnv.hs +556/−0
- src/Clash/Driver.hs +370/−124
- src/Clash/Driver/Types.hs +77/−24
- src/Clash/Netlist.hs +507/−296
- src/Clash/Netlist.hs-boot +24/−8
- src/Clash/Netlist/BlackBox.hs +577/−283
- src/Clash/Netlist/BlackBox/Parser.hs +39/−19
- src/Clash/Netlist/BlackBox/Types.hs +166/−51
- src/Clash/Netlist/BlackBox/Util.hs +648/−269
- src/Clash/Netlist/Id.hs +39/−39
- src/Clash/Netlist/Types.hs +285/−91
- src/Clash/Netlist/Types.hs-boot +22/−0
- src/Clash/Netlist/Util.hs +1834/−1121
- src/Clash/Normalize.hs +185/−210
- src/Clash/Normalize/DEC.hs +164/−121
- src/Clash/Normalize/PrimitiveReductions.hs +650/−304
- src/Clash/Normalize/Strategy.hs +56/−38
- src/Clash/Normalize/Strategy.hs-boot +6/−0
- src/Clash/Normalize/Transformations.hs +2289/−1743
- src/Clash/Normalize/Types.hs +26/−14
- src/Clash/Normalize/Util.hs +213/−73
- src/Clash/Pretty.hs +20/−0
- src/Clash/Primitives/GHC/Int.hs +61/−0
- src/Clash/Primitives/GHC/Literal.hs +77/−0
- src/Clash/Primitives/GHC/Word.hs +49/−0
- src/Clash/Primitives/Intel/ClockGen.hs +119/−0
- src/Clash/Primitives/Sized/Vector.hs +92/−0
- src/Clash/Primitives/Types.hs +221/−38
- src/Clash/Primitives/Util.hs +171/−19
- src/Clash/Rewrite/Combinators.hs +79/−81
- src/Clash/Rewrite/Types.hs +106/−66
- src/Clash/Rewrite/Util.hs +500/−379
- src/Clash/Unique.hs +397/−0
- src/Clash/Util.hs +201/−41
- src/Clash/Util/Graph.hs +127/−0
- src/ClashDebug.h +5/−0
- src/Data/Aeson/Extra.hs +35/−17
- src/Data/Text/Prettyprint/Doc/Extra.hs +13/−3
- src/GHC/BasicTypes/Extra.hs +2/−0
- src/GHC/SrcLoc/Extra.hs +19/−7
- src/Unbound/Generics/LocallyNameless/Extra.hs +0/−115
CHANGELOG.md view
@@ -1,5 +1,131 @@ # Changelog for the [`clash-lib`](http://hackage.haskell.org/package/clash-lib) package +## 1.0.0 *September 3rd 2019*+* 10x - 50x faster compile times+* New features:+ * API changes: check the migration guide at the end of `Clash.Tutorial`+ * All memory elements now have an (implicit) enable line; "Gated" clocks have+ been removed as the clock wasn't actually gated, but implemented as an+ enable line.+ * Circuit domains are now configurable in:+ * (old) The clock period+ * (new) Clock edge on which memory elements latch their inputs+ (rising edge or falling edge)+ * (new) Whether the reset port of a memory element is level sensitive+ (asynchronous reset) or edge sensitive (synchronous reset)+ * (new) Whether the reset port of a memory element is active-high or+ active-low (negated reset)+ * (new) Whether memory element power on in a configurable/defined state+ (common on FPGAs) or in an undefined state (ASICs)++ * See the [blog post](https://clash-lang.org/blog/0005-synthesis-domain/) on this new feature+ * Data types can now be given custom bit-representations: http://hackage.haskell.org/package/clash-prelude/docs/Clash-Annotations-BitRepresentation.html+ * Annotate expressions with attributes that persist in the generated HDL,+ e.g. synthesis directives: http://hackage.haskell.org/package/clash-prelude/docs/Clash-Annotations-SynthesisAttributes.html+ * Control (System)Verilog module instance, and VHDL entity instantiation names+ in generated code: http://hackage.haskell.org/package/clash-prelude/docs/Clash-Magic.html+ * Much improved infrastructure for handling of unknown values: defined spine,+ but unknown leafs: http://hackage.haskell.org/package/clash-prelude/docs/Clash-XException.html#t:NFDataX+ * Experimental: Multiple hidden clocks. Can be enabled by compiling+ `clash-prelude` with `-fmultiple-hidden`+ * Experimental: Limited GADT support (pattern matching on vectors, or custom+ GADTs as longs as their usage can be statically removed; no support of+ recursive GADTs)+ * Experimental: Use regular Haskell functions to generate HDL black boxes for+ primitives (in an addition to existing string templates for HDL black boxes)+ See for example: http://hackage.haskell.org/package/clash-lib/docs/Clash-Primitives-Intel-ClockGen.html++* Fixes issues:+ * [#316](https://github.com/clash-lang/clash-prelude/issues/316)+ * [#319](https://github.com/clash-lang/clash-prelude/issues/319)+ * [#323](https://github.com/clash-lang/clash-prelude/issues/323)+ * [#324](https://github.com/clash-lang/clash-prelude/issues/324)+ * [#329](https://github.com/clash-lang/clash-prelude/issues/329)+ * [#331](https://github.com/clash-lang/clash-prelude/issues/331)+ * [#332](https://github.com/clash-lang/clash-prelude/issues/332)+ * [#335](https://github.com/clash-lang/clash-prelude/issues/335)+ * [#348](https://github.com/clash-lang/clash-prelude/issues/348)+ * [#349](https://github.com/clash-lang/clash-prelude/issues/349)+ * [#350](https://github.com/clash-lang/clash-prelude/issues/350)+ * [#351](https://github.com/clash-lang/clash-prelude/issues/351)+ * [#352](https://github.com/clash-lang/clash-prelude/issues/352)+ * [#353](https://github.com/clash-lang/clash-prelude/issues/353)+ * [#358](https://github.com/clash-lang/clash-prelude/issues/358)+ * [#359](https://github.com/clash-lang/clash-prelude/issues/359)+ * [#363](https://github.com/clash-lang/clash-prelude/issues/363)+ * [#364](https://github.com/clash-lang/clash-prelude/issues/364)+ * [#365](https://github.com/clash-lang/clash-prelude/issues/365)+ * [#371](https://github.com/clash-lang/clash-prelude/issues/371)+ * [#372](https://github.com/clash-lang/clash-prelude/issues/372)+ * [#373](https://github.com/clash-lang/clash-prelude/issues/373)+ * [#378](https://github.com/clash-lang/clash-prelude/issues/378)+ * [#380](https://github.com/clash-lang/clash-prelude/issues/380)+ * [#381](https://github.com/clash-lang/clash-prelude/issues/381)+ * [#382](https://github.com/clash-lang/clash-prelude/issues/382)+ * [#383](https://github.com/clash-lang/clash-prelude/issues/383)+ * [#387](https://github.com/clash-lang/clash-prelude/issues/387)+ * [#393](https://github.com/clash-lang/clash-prelude/issues/393)+ * [#396](https://github.com/clash-lang/clash-prelude/issues/396)+ * [#398](https://github.com/clash-lang/clash-prelude/issues/398)+ * [#399](https://github.com/clash-lang/clash-prelude/issues/399)+ * [#401](https://github.com/clash-lang/clash-prelude/issues/401)+ * [#403](https://github.com/clash-lang/clash-prelude/issues/403)+ * [#407](https://github.com/clash-lang/clash-prelude/issues/407)+ * [#412](https://github.com/clash-lang/clash-prelude/issues/412)+ * [#413](https://github.com/clash-lang/clash-prelude/issues/413)+ * [#420](https://github.com/clash-lang/clash-prelude/issues/420)+ * [#422](https://github.com/clash-lang/clash-prelude/issues/422)+ * [#423](https://github.com/clash-lang/clash-prelude/issues/423)+ * [#424](https://github.com/clash-lang/clash-prelude/issues/424)+ * [#438](https://github.com/clash-lang/clash-prelude/issues/438)+ * [#450](https://github.com/clash-lang/clash-prelude/issues/450)+ * [#452](https://github.com/clash-lang/clash-prelude/issues/452)+ * [#455](https://github.com/clash-lang/clash-prelude/issues/455)+ * [#460](https://github.com/clash-lang/clash-prelude/issues/460)+ * [#461](https://github.com/clash-lang/clash-prelude/issues/461)+ * [#463](https://github.com/clash-lang/clash-prelude/issues/463)+ * [#468](https://github.com/clash-lang/clash-prelude/issues/468)+ * [#475](https://github.com/clash-lang/clash-prelude/issues/475)+ * [#476](https://github.com/clash-lang/clash-prelude/issues/476)+ * [#500](https://github.com/clash-lang/clash-prelude/issues/500)+ * [#507](https://github.com/clash-lang/clash-prelude/issues/507)+ * [#512](https://github.com/clash-lang/clash-prelude/issues/512)+ * [#516](https://github.com/clash-lang/clash-prelude/issues/516)+ * [#517](https://github.com/clash-lang/clash-prelude/issues/517)+ * [#526](https://github.com/clash-lang/clash-prelude/issues/526)+ * [#556](https://github.com/clash-lang/clash-prelude/issues/556)+ * [#560](https://github.com/clash-lang/clash-prelude/issues/560)+ * [#566](https://github.com/clash-lang/clash-prelude/issues/566)+ * [#567](https://github.com/clash-lang/clash-prelude/issues/567)+ * [#569](https://github.com/clash-lang/clash-prelude/issues/569)+ * [#573](https://github.com/clash-lang/clash-prelude/issues/573)+ * [#575](https://github.com/clash-lang/clash-prelude/issues/575)+ * [#581](https://github.com/clash-lang/clash-prelude/issues/581)+ * [#582](https://github.com/clash-lang/clash-prelude/issues/582)+ * [#586](https://github.com/clash-lang/clash-prelude/issues/586)+ * [#588](https://github.com/clash-lang/clash-prelude/issues/588)+ * [#591](https://github.com/clash-lang/clash-prelude/issues/591)+ * [#596](https://github.com/clash-lang/clash-prelude/issues/596)+ * [#601](https://github.com/clash-lang/clash-prelude/issues/601)+ * [#607](https://github.com/clash-lang/clash-prelude/issues/607)+ * [#629](https://github.com/clash-lang/clash-prelude/issues/629)+ * [#637](https://github.com/clash-lang/clash-prelude/issues/637)+ * [#644](https://github.com/clash-lang/clash-prelude/issues/644)+ * [#647](https://github.com/clash-lang/clash-prelude/issues/647)+ * [#661](https://github.com/clash-lang/clash-prelude/issues/661)+ * [#668](https://github.com/clash-lang/clash-prelude/issues/668)+ * [#677](https://github.com/clash-lang/clash-prelude/issues/677)+ * [#678](https://github.com/clash-lang/clash-prelude/issues/678)+ * [#682](https://github.com/clash-lang/clash-prelude/issues/682)+ * [#691](https://github.com/clash-lang/clash-prelude/issues/691)+ * [#703](https://github.com/clash-lang/clash-prelude/issues/703)+ * [#713](https://github.com/clash-lang/clash-prelude/issues/713)+ * [#715](https://github.com/clash-lang/clash-prelude/issues/715)+ * [#727](https://github.com/clash-lang/clash-prelude/issues/727)+ * [#730](https://github.com/clash-lang/clash-prelude/issues/730)+ * [#736](https://github.com/clash-lang/clash-prelude/issues/736)+ * [#738](https://github.com/clash-lang/clash-prelude/issues/738)+ ## 0.99.3 *July 28th 2018* * Fixes bugs: * Evaluator recognizes `Bit` literals [#329](https://github.com/clash-lang/clash-compiler/issues/329)
LICENSE view
@@ -1,6 +1,6 @@ Copyright (c) 2012-2016, University of Twente, 2016-2017, Myrtle Software Ltd,- 2017 , QBayLogic, Google Inc.+ 2017-2019, QBayLogic B.V., Google Inc. All rights reserved. Redistribution and use in source and binary forms, with or without
README.md view
@@ -1,14 +1,14 @@-# `clash-lib` - CλaSH compiler, as a library+# `clash-lib` - Clash compiler, as a library * See the LICENSE file for license and copyright details -# CλaSH - A functional hardware description language-CλaSH (pronounced ‘clash’) is a functional hardware description language that-borrows both its syntax and semantics from the functional programming language-Haskell. The CλaSH compiler transforms these high-level descriptions to+# Clash - A functional hardware description language+Clash is a functional hardware description language that borrows both+its syntax and semantics from the functional programming language+Haskell. The Clash compiler transforms these high-level descriptions to low-level synthesizable VHDL, Verilog, or SystemVerilog. -Features of CλaSH:+Features of Clash: * Strongly typed (like VHDL), yet with a very high degree of type inference, enabling both safe and fast prototying using consise descriptions (like
clash-lib.cabal view
@@ -1,13 +1,13 @@ Name: clash-lib-Version: 0.99.3+Version: 1.0.0 Synopsis: CAES Language for Synchronous Hardware - As a Library Description:- CλaSH (pronounced ‘clash’) is a functional hardware description language that- borrows both its syntax and semantics from the functional programming language- Haskell. The CλaSH compiler transforms these high-level descriptions to- low-level synthesizable VHDL, Verilog, or SystemVerilog.+ Clash is a functional hardware description language that borrows both its+ syntax and semantics from the functional programming language Haskell. The+ Clash compiler transforms these high-level descriptions to low-level+ synthesizable VHDL, Verilog, or SystemVerilog. .- Features of CλaSH:+ Features of Clash: . * Strongly typed, but with a very high degree of type inference, enabling both safe and fast prototyping using concise descriptions.@@ -46,17 +46,18 @@ bug-reports: http://github.com/clash-lang/clash-compiler/issues License: BSD2 License-file: LICENSE-Author: Christiaan Baaij-Maintainer: Christiaan Baaij <christiaan.baaij@gmail.com>+Author: The Clash Authors+Maintainer: QBayLogic B.V. <devops@qbaylogic.com> Copyright: Copyright © 2012-2016, University of Twente,- 2016-2017, Myrtle Software Ltd,- 2017 , QBayLogic, Google Inc.+ 2016-2019, Myrtle Software Ltd,+ 2017-2019, QBayLogic B.V., Google Inc. Category: Hardware Build-type: Simple Extra-source-files: README.md, CHANGELOG.md+ src/ClashDebug.h Data-files: prims/common/*.json,@@ -71,6 +72,18 @@ type: git location: https://github.com/clash-lang/clash-compiler.git +flag debug+ description:+ Build a debug compiler+ default: False+ manual: True++flag history+ description:+ Emit rewrite history to disk+ default: False+ manual: True+ Library HS-Source-Dirs: src @@ -97,39 +110,47 @@ ViewPatterns Build-depends: aeson >= 0.6.2.0 && < 1.5,+ ansi-terminal >= 0.8.0.0 && < 0.10, ansi-wl-pprint >= 0.6.8.2 && < 1.0, attoparsec >= 0.10.4.0 && < 0.14,- base >= 4.8 && < 5,+ base >= 4.10 && < 5,+ binary >= 0.8.5 && < 0.11, bytestring >= 0.10.0.2 && < 0.11,- clash-prelude >= 0.11.1 && < 1.0,+ clash-prelude >= 1.0 && < 1.1, concurrent-supply >= 0.1.7 && < 0.2, containers >= 0.5.0.0 && < 0.7, data-binary-ieee754 >= 0.4.4 && < 0.6, deepseq >= 1.3.0.2 && < 1.5, directory >= 1.2.0.1 && < 1.4, errors >= 1.4.2 && < 2.4,- fgl >= 5.4.2.4 && < 5.7,+ exceptions >= 0.8.3 && < 0.11.0, filepath >= 1.3.0.1 && < 1.5,- ghc >= 8.0.2 && < 8.6,- hashable >= 1.2.1.0 && < 1.3,+ ghc >= 8.2.0 && < 8.9,+ hashable >= 1.2.1.0 && < 1.4,+ hint >= 0.7 && < 0.10, integer-gmp >= 1.0 && < 1.1,- lens >= 3.9.2 && < 4.18,+ interpolate >= 0.2.0 && < 1.0,+ lens >= 3.9.2 && < 4.19, mtl >= 2.1.2 && < 2.3, parsers >= 0.12.8 && < 1.0, prettyprinter >= 1.2.0.1 && < 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.14,- text >= 0.11.3.1 && < 1.3,+ template-haskell >= 2.8.0.0 && < 2.16,+ temporary >= 1.2.1 && < 1.4,+ text >= 1.2.2 && < 1.3,+ text-show >= 3.7 && < 3.9, time >= 1.4.0.1 && < 1.10,- transformers >= 0.3.0.0 && < 0.6,- trifecta >= 1.7.1.1 && < 2.0,+ transformers >= 0.5.2.0 && < 0.6,+ trifecta >= 1.7.1.1 && < 2.1, vector >= 0.11 && < 1.0,- unbound-generics >= 0.1 && < 0.4,+ vector-binary-instances >= 0.2.3.5 && < 0.3, unordered-containers >= 0.2.3.3 && < 0.3 - Exposed-modules: Clash.Backend+ Exposed-modules: Clash.Annotations.BitRepresentation.ClashLib++ Clash.Backend Clash.Backend.SystemVerilog Clash.Backend.Verilog Clash.Backend.VHDL@@ -147,6 +168,7 @@ Clash.Core.TysPrim Clash.Core.Util Clash.Core.Var+ Clash.Core.VarEnv Clash.Driver Clash.Driver.Types@@ -171,18 +193,33 @@ Clash.Primitives.Types Clash.Primitives.Util + Clash.Primitives.GHC.Int+ Clash.Primitives.GHC.Literal+ Clash.Primitives.GHC.Word+ Clash.Primitives.Intel.ClockGen+ Clash.Primitives.Sized.Vector+ Clash.Rewrite.Combinators Clash.Rewrite.Types Clash.Rewrite.Util + Clash.Unique Clash.Util+ Clash.Util.Graph+ Clash.Pretty + Data.Text.Prettyprint.Doc.Extra+ Other-Modules: Clash.Annotations.TopEntity.Extra Data.Aeson.Extra Data.Semigroup.Monad.Extra- Data.Text.Prettyprint.Doc.Extra Data.Vector.Primitive.Extra GHC.BasicTypes.Extra GHC.SrcLoc.Extra Paths_clash_lib- Unbound.Generics.LocallyNameless.Extra++ if flag(debug)+ cpp-options: -DDEBUG++ if flag(history)+ cpp-options: -DHISTORY
+ prims/common/Clash_Annotations_BitRepresentation_Deriving.json view
@@ -0,0 +1,9 @@+[ { "BlackBox" :+ { "name" : "Clash.Annotations.BitRepresentation.Deriving.dontApplyInHDL"+ , "workInfo" : "Never"+ , "kind" : "Expression"+ , "type" : "dontApplyInHDL :: (a -> b) -> a -> b"+ , "template" : "~ARG[1]"+ }+ }+]
prims/common/Clash_Class_BitPack.json view
@@ -1,29 +1,37 @@ [ { "BlackBox" : { "name" : "Clash.Class.BitPack.packFloat#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "packFloat# :: Float -> BitVector 32"- , "templateE" : "~ARG[0]"+ , "template" : "~ARG[0]" } } , { "BlackBox" : { "name" : "Clash.Class.BitPack.unpackFloat#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "packFloat# :: BitVector 32 -> Float"- , "templateE" : "~ARG[0]"+ , "template" : "~ARG[0]" } } , { "BlackBox" : { "name" : "Clash.Class.BitPack.packDouble#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "packFloat# :: Double -> BitVector 64"- , "templateE" : "~ARG[0]"+ , "template" : "~ARG[0]" } } , { "BlackBox" : { "name" : "Clash.Class.BitPack.unpackDouble#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "packFloat# :: BitVector 64 -> Double"- , "templateE" : "~ARG[0]"+ , "template" : "~ARG[0]" } } ]
prims/common/Clash_Explicit_Signal.json view
@@ -1,12 +1,14 @@ [ { "BlackBox" :- { "name" : "Clash.Explicit.Signal.unsafeSynchronizer"+ { "name" : "Clash.Explicit.Signal.veryUnsafeSynchronizer"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" :-"unsafeSynchronizer- :: Clock dom1 g1- -> Clock dom2 g2- -> Signal dom1 a -- ARG[2]+"veryUnsafeSynchronizer+ :: Int -- ARG[0]+ -> Int -- ARG[1]+ -> Signal dom1 a -- ARG[2] -> Signal dom2 a"- , "templateE" : "~ARG[2]"+ , "template" : "~ARG[2]" } } ]
prims/common/Clash_GHC_GHC2Core.json view
@@ -1,15 +1,19 @@ [ { "BlackBox" : { "name" : "EmptyCase"- , "templateE" : "~ERRORO"+ , "workInfo" : "Constant"+ , "kind" : "Expression"+ , "template" : "~ERRORO" } } , { "Primitive" : { "name" : "_CO_"+ , "workInfo" : "Constant" , "primType" : "Constructor" } } , { "Primitive" : { "name" : "_TY_"+ , "workInfo" : "Constant" , "primType" : "Constructor" } }
+ prims/common/Clash_Intel_ClockGen.json view
@@ -0,0 +1,17 @@+[ { "BlackBox" :+ { "name" : "Clash.Intel.ClockGen.altpll"+ , "workInfo" : "Always"+ , "kind" : "Declaration"+ , "format" : "Haskell"+ , "templateFunction" : "Clash.Primitives.Intel.ClockGen.altpllTF"+ }+ }+, { "BlackBox" :+ { "name" : "Clash.Intel.ClockGen.alteraPll"+ , "workInfo" : "Always"+ , "kind" : "Declaration"+ , "format" : "Haskell"+ , "templateFunction" : "Clash.Primitives.Intel.ClockGen.alteraPllTF"+ }+ }+]
+ prims/common/Clash_Magic.json view
@@ -0,0 +1,16 @@+[ { "Primitive" :+ { "name" : "Clash.Magic.prefixName"+ , "primType" : "Function"+ }+ }+, { "Primitive" :+ { "name" : "Clash.Magic.suffixName"+ , "primType" : "Function"+ }+ }+, { "Primitive" :+ { "name" : "Clash.Magic.setName"+ , "primType" : "Function"+ }+ }+]
+ prims/common/Clash_Promoted_Nat.json view
@@ -0,0 +1,9 @@+[ { "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_Unsafe.json view
@@ -1,7 +1,9 @@ [ { "BlackBox" : { "name" : "Clash.Promoted.Nat.Unsafe.unsafeSNat"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "Clash.Promoted.Nat.Unsafe.unsafeSNat :: Integer -> SNat k"- , "templateE" : "~LIT[0]"+ , "template" : "~LIT[0]" } } ]
prims/common/Clash_Promoted_Symbol.json view
@@ -1,13 +1,17 @@ [ { "BlackBox" : { "name" : "Clash.Promoted.Symbol.SSymbol"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "SSymbol :: KnownNat n => Proxy n -> SSymbol n"- , "templateE" : "~LIT[0]"+ , "template" : "~LIT[0]" } } , { "BlackBox" : { "name" : "Clash.Promoted.Symbol.symbolToString"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "symbolToString :: SSymbol n -> String"- , "templateE" : "~LIT[0]"+ , "template" : "~LIT[0]" } } ]
+ prims/common/Clash_Signal_BiSignal.json view
@@ -0,0 +1,30 @@+[ { "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_Bundle.json view
@@ -1,5 +1,6 @@ [ { "Primitive" : { "name" : "Clash.Signal.Bundle.vecBundle#"+ , "workInfo" : "Never" , "primType" : "Function" } }
+ prims/common/Clash_Signal_Internal.json view
@@ -0,0 +1,37 @@+[ { "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_Sized_Internal_BitVector.json view
@@ -0,0 +1,43 @@+[ { "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_Index.json view
@@ -0,0 +1,8 @@+[ { "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.json view
@@ -0,0 +1,22 @@+[ { "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_Unsigned.json view
@@ -0,0 +1,22 @@+[ { "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]"+ }+ }+]
+ prims/common/Clash_Sized_RTree.json view
@@ -0,0 +1,7 @@+[ { "Primitive" :+ { "name" : "Clash.Sized.RTree.tdfold"+ , "workInfo" : "Never"+ , "primType" : "Function"+ }+ }+]
+ prims/common/Clash_Sized_Vector.json view
@@ -0,0 +1,47 @@+[+ {+ "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_Transformations.json view
@@ -1,7 +1,17 @@ [ { "BlackBox" : { "name" : "Clash.Transformations.removedArg"+ , "workInfo" : "Constant"+ , "kind" : "Expression" , "type" : "removedArg :: a"- , "templateE" : "~ERRORO"+ , "template" : "~ERRORO"+ }+ }+, { "BlackBox" :+ { "name" : "Clash.Transformations.undefined"+ , "workInfo" : "Constant"+ , "kind" : "Expression"+ , "type" : "undefined :: forall a . a"+ , "template" : "~ERRORO" } } ]
prims/common/Clash_XException.json view
@@ -1,13 +1,25 @@ [ { "BlackBox" : { "name" : "Clash.XException.seqX"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "seqX :: a -> b -> b"- , "templateE" : "~ARG[1]"+ , "template" : "~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.XException.errorX"- , "type" : "errorX :: HasCallStack -> String -> a"- , "templateE" : "~ERRORO"+ , "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]"+ } } ]
prims/common/Control_Exception_Base.json view
@@ -1,25 +1,73 @@ [ { "BlackBox" :- { "name" : "Control.Exception.Base.patError"- , "type" : "patError :: Addr# -> a"- , "templateE" : "~ERRORO"+ { "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"- , "templateE" : "~ERRORO"+ , "template" : "~ERRORO" } } , { "BlackBox" :- { "name" : "Control.Exception.Base.recSelError"- , "type" : "recSelError :: Addr# -> a"- , "templateE" : "~ERRORO"+ { "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"- , "templateE" : "~ERRORO"+ , "template" : "~ERRORO"+ }+ }+, { "BlackBox" :+ { "name" : "Control.Exception.Base.typeError"+ , "workInfo" : "Constant"+ , "kind" : "Expression"+ , "type" : "typeError :: Addr# -> a"+ , "template" : "~ERRORO" } } ]
prims/common/Debug_Trace.json view
@@ -1,7 +1,9 @@ [ { "BlackBox" : { "name" : "Debug.Trace.trace"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "trace :: String -> a -> a"- , "templateE" : "~ARG[1]"+ , "template" : "~ARG[1]" } } ]
+ prims/common/GHC_Base.json view
@@ -0,0 +1,14 @@+[ { "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_CString.json view
@@ -1,15 +1,20 @@ [ { "BlackBox" : { "name" : "GHC.CString.unpackCString#"- , "templateE" : "~LIT[0]"+ , "workInfo" : "Never"+ , "kind" : "Expression"+ , "template" : "~LIT[0]" } } , { "BlackBox" : { "name" : "GHC.CString.unpackFoldrCString#"- , "templateE" : "~LIT[0]"+ , "workInfo" : "Never"+ , "kind" : "Expression"+ , "template" : "~LIT[0]" } } , { "Primitive" : { "name" : "GHC.CString.unpackCStringUtf8#"+ , "workInfo" : "Never" , "primType" : "Function" } }
+ prims/common/GHC_Classes.json view
@@ -0,0 +1,29 @@+[ { "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.json view
@@ -1,19 +1,25 @@ [ { "BlackBox" : { "name" : "GHC.Err.error"+ , "workInfo" : "Constant"+ , "kind" : "Expression" , "type" : "error :: [Char] -> a"- , "templateE" : "~ERRORO"+ , "template" : "~ERRORO" } } , { "BlackBox" : { "name" : "GHC.Err.errorWithoutStackTrace"+ , "workInfo" : "Constant"+ , "kind" : "Expression" , "type" : "errorWithoutStackTrace :: [Char] -> a"- , "templateE" : "~ERRORO"+ , "template" : "~ERRORO" } } , { "BlackBox" : { "name" : "GHC.Err.undefined"+ , "workInfo" : "Constant"+ , "kind" : "Expression" , "type" : "undefined :: a"- , "templateE" : "~ERRORO"+ , "template" : "~ERRORO" } } ]
prims/common/GHC_IO_Exception.json view
@@ -1,12 +1,14 @@ [ { "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"- , "templateE" : "~ARG[2]"+ , "template" : "~ARG[2]" } } ]
+ prims/common/GHC_Integer_Type.json view
@@ -0,0 +1,50 @@+[ { "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_Magic.json view
@@ -1,10 +1,19 @@ [ { "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_Natural.json view
@@ -1,12 +1,36 @@-[ { "Primitive" :- { "name" : "GHC.Natural.NatS#"- , "primType" : "Constructor"+[+ {+ "Primitive": {+ "name": "GHC.Natural.NatS#",+ "workInfo" : "Never",+ "primType": "Constructor" }- }-, { "BlackBox" :- { "name" : "GHC.Natural.underflowError"- , "type" : "underflowError :: a"- , "templateE" : "~ERRORO"+ },+ {+ "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." } } ]
prims/common/GHC_Prim.json view
@@ -1,11 +1,61 @@ [ { "Primitive" :- { "name" : "GHC.Prim.newByteArray#"- , "primType" : "Function"+ { "name" : "GHC.Prim.dataToTag#"+ , "primType" : "Function" } } , { "Primitive" :- { "name" : "GHC.Prim.realWorld#"- , "primType" : "Function"+ { "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_Real.json view
@@ -1,19 +1,25 @@ [ { "BlackBox" : { "name" : "GHC.Real.divZeroError"+ , "workInfo" : "Constant"+ , "kind" : "Expression" , "type" : "divZeroError :: a"- , "templateE" : "~ERRORO"+ , "template" : "~ERRORO" } } , { "BlackBox" : { "name" : "GHC.Real.ratioZeroDenominatorError"+ , "workInfo" : "Constant"+ , "kind" : "Expression" , "type" : "ratioZeroDenominatorError :: a"- , "templateE" : "~ERRORO"+ , "template" : "~ERRORO" } } , { "BlackBox" : { "name" : "GHC.Real.overflowError"+ , "workInfo" : "Constant"+ , "kind" : "Expression" , "type" : "overflowError :: a"- , "templateE" : "~ERRORO"+ , "template" : "~ERRORO" } } ]
prims/common/GHC_TypeNats.json view
@@ -1,7 +1,9 @@ [ { "BlackBox" : { "name" : "GHC.TypeNats.natVal"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "natVal :: forall n proxy. KnownNat n => proxy n -> Natural"- , "templateE" : "~ARG[0]"+ , "template" : "~ARG[0]" } } ]
prims/common/GHC_Typelits.json view
@@ -1,7 +1,9 @@ [ { "BlackBox" : { "name" : "GHC.TypeLits.natVal"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "natVal :: forall n proxy. KnownNat n => proxy n -> Integer"- , "templateE" : "~ARG[0]"+ , "template" : "~ARG[0]" } } ]
+ prims/common/GHC_Types.json view
@@ -0,0 +1,31 @@+[ { "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/Unsafe_Coerce.json view
@@ -1,7 +1,9 @@ [ { "BlackBox" : { "name" : "Unsafe.Coerce.unsafeCoerce"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "unsafeCoerce :: a -> b"- , "templateE" : "~ARG[0]"+ , "template" : "~ARG[0]" } } ]
+ prims/commonverilog/Clash_Class_Exp.json view
@@ -0,0 +1,29 @@+[+ {+ "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_Intel_DDR.json view
@@ -0,0 +1,49 @@+[ { "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_Promoted_Nat.json view
@@ -1,75 +1,78 @@ [ { "BlackBox" :- { "name" : "Clash.Promoted.Nat.powSNat"- , "type" : "Clash.Promoted.Nat.powSNat :: SNat a -> SNat b -> SNat (a^b)"- , "templateE" : "~LIT[0] ** ~LIT[1]"- }- }-, { "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.inc"]- , "include" :- { "name" : "flogBase"- , "extension" : "inc"- , "content" :+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "flogBase"+ , "extension" : "inc"+ , "template" : "// floor of logBase-function integer ~INCLUDENAME;+function integer ~INCLUDENAME[0]; input integer base, value; begin- for (~INCLUDENAME = 0; value >= base; ~INCLUDENAME=~INCLUDENAME+1)+ for (~INCLUDENAME[0] = 0; value >= base; ~INCLUDENAME[0]=~INCLUDENAME[0]+1) value = value / base; end endfunction"- }- , "templateE" : "~INCLUDENAME(~LIT[2],~LIT[3])"+ }+ ]+ , "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.inc"]- , "include" :- { "name" : "clogBase"- , "extension" : "inc"- , "content" :+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "clogBase"+ , "extension" : "inc"+ , "template" : "// ceiling of logBase-function integer ~INCLUDENAME;+function integer ~INCLUDENAME[0]; input integer base, value; begin- for (~INCLUDENAME = 0; base ** ~INCLUDENAME < value; ~~INCLUDENAME=~INCLUDENAME+1);+ for (~INCLUDENAME[0] = 0; base ** ~INCLUDENAME[0] < value; ~~INCLUDENAME[0]=~INCLUDENAME[0]+1); end endfunction"- }- , "templateE" : "~INCLUDENAME(~LIT[2],~LIT[3])"+ }+ ]+ , "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.inc"]- , "include" :- { "name" : "clogBase"- , "extension" : "inc"- , "content" :+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "clogBase"+ , "extension" : "inc"+ , "template" : "// logBaseSNat begin-function integer ~INCLUDENAME;+function integer ~INCLUDENAME[0]; input integer base, value; begin- for (~INCLUDENAME = 0; value >= base; ~INCLUDENAME=~INCLUDENAME+1)+ for (~INCLUDENAME[0] = 0; value >= base; ~INCLUDENAME[0]=~INCLUDENAME[0]+1) value = value / base; end endfunction"- }- , "templateE" : "~INCLUDENAME(~LIT[1],~LIT[2])"+ }+ ]+ , "template" : "~INCLUDENAME[0](~LIT[1],~LIT[2])" } } ]
+ prims/commonverilog/Clash_Signal_Internal.json view
@@ -0,0 +1,27 @@+[ { "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]"+ }+ }+, { "BlackBox" :+ { "name" : "Clash.Explicit.Testbench.tbEnableGen"+ , "workInfo" : "Always"+ , "kind" : "Declaration"+ , "type" : "tbEnableGen :: Enable dom"+ , "template" : "assign ~RESULT = 1'b1;"+ }+ }+]
prims/commonverilog/Clash_Sized_Internal_BitVector.json view
@@ -1,151 +1,377 @@ [ { "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"- , "templateE" : "1'b1"+ , "template" : "1'b1" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.low"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "low :: Bit"- , "templateE" : "1'b0"+ , "template" : "1'b0" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.pack#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "pack# :: Bit -> BitVector 1"- , "templateE" : "~ARG[0]"+ , "template" : "~ARG[0]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.unpack#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "unpack# :: BitVector 1 -> Bit"- , "templateE" : "~ARG[0]"+ , "template" : "~ARG[0]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.reduceAnd#"+ , "kind" : "Expression" , "type" : "reduceAnd# :: KnownNat n => BitVector n -> Bit"- , "templateE" : "& (~ARG[1])"+ , "template" : "~IF~SIZE[~TYP[1]]~THEN& (~ARG[1])~ELSE1'b1~FI" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.reduceOr#"- , "type" : "reduceOr# :: BitVector n -> Bit"- , "templateE" : "| (~ARG[0])"+ , "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#"- , "type" : "reduceXor# :: BitVector n -> Bit"- , "templateE" : "^ (~ARG[0])"+ , "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"- , "templateE" : "~ARG[0] == ~ARG[1]"+ , "template" : "~ARG[0] == ~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.neq##"+ , "kind" : "Expression" , "type" : "neq## :: Bit -> Bit -> Bool"- , "templateE" : "~ARG[0] != ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.lt##"- , "type" : "lt## :: Bit -> Bit -> Bool"- , "templateE" : "~ARG[0] < ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.ge##"- , "type" : "ge## :: Bit -> Bit -> Bool"- , "templateE" : "~ARG[0] >= ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.gt##"- , "type" : "gt## :: Bit -> Bit -> Bool"- , "templateE" : "~ARG[0] > ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.le##"- , "type" : "le## :: Bit -> Bit -> Bool"- , "templateE" : "~ARG[0] <= ~ARG[1]"+ , "template" : "~ARG[0] != ~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.fromInteger##"- , "type" : "fromInteger# :: Integer -> Bit"- , "templateE" : "~VAR[i][0][0]"+ , "workInfo" : "Never"+ , "kind" : "Expression"+ , "type" : "fromInteger## :: Integer -> Integer -> Bit"+ , "template" : "~ARG[0][0] ? 1'bx : ~ARG[1][0]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.and##"+ , "kind" : "Expression" , "type" : "and## :: Bit -> Bit -> Bit"- , "templateE" : "~ARG[0] & ~ARG[1]"+ , "template" : "~ARG[0] & ~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.or##"+ , "kind" : "Expression" , "type" : "or## :: Bit -> Bit -> Bit"- , "templateE" : "~ARG[0] | ~ARG[1]"+ , "template" : "~ARG[0] | ~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.xor##"+ , "kind" : "Expression" , "type" : "xor## :: Bit -> Bit -> Bit"- , "templateE" : "~ARG[0] ^ ~ARG[1]"+ , "template" : "~ARG[0] ^ ~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.complement##"+ , "kind" : "Expression" , "type" : "complement## :: Bit -> Bit"- , "templateE" : "~ ~ARG[0]"+ , "template" : "~ ~ARG[0]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.eq#"- , "type" : "eq# :: BitVector n -> BitVector n -> Bool"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] == ~ARG[1]~ELSE1'b1~FI"+ , "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#"- , "type" : "neq# :: BitVector n -> BitVector n -> Bool"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] != ~ARG[1]~ELSE1'b0~FI"+ , "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#"- , "type" : "lt# :: BitVector n -> BitVector n -> Bool"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] < ~ARG[1]~ELSE1'b0~FI"+ , "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#"- , "type" : "ge# :: BitVector n -> BitVector n -> Bool"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] >= ~ARG[1]~ELSE1'b1~FI"+ , "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#"- , "type" : "gt# :: BitVector n -> BitVector n -> Bool"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] > ~ARG[1]~ELSE1'b0~FI"+ , "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#"- , "type" : "le# :: BitVector n -> BitVector n -> Bool"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] <= ~ARG[1]~ELSE1'b1~FI"+ , "kind" : "Expression"+ , "type" : "le# :: 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.toInteger#"- , "type" : "toInteger# :: BitVector n -> Integer"- , "templateD" : "assign ~RESULT = ~IF~SIZE[~TYP[0]]~THEN$unsigned(~ARG[0])~ELSE64'sd0~FI;"+ , "workInfo" : "Never"+ , "kind" : "Expression"+ , "type" : "toInteger# :: KnownNat n => BitVector n -> Integer"+ , "template" : "~IF~SIZE[~TYP[1]]~THEN~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[1]]]~THEN$signed(~VAR[bv][1][0+:~SIZE[~TYPO]])~ELSE$signed({{(~SIZE[~TYPO]-~SIZE[~TYP[1]]) {1'b0}},~VAR[bv][1]})~FI~ELSE~SIZE[~TYPO]'sd0~FI"+ }+ }+, { "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# :: BitVector n -> BitVector n -> BitVector n"+ , "template" : "~ARG[0] & ~ARG[1]"+ }+ }+, { "BlackBox" :+ { "name" : "Clash.Sized.Internal.BitVector.or#"+ , "kind" : "Expression"+ , "type" : "or# :: BitVector n -> BitVector n -> BitVector n"+ , "template" : "~ARG[0] | ~ARG[1]"+ }+ }+, { "BlackBox" :+ { "name" : "Clash.Sized.Internal.BitVector.xor#"+ , "kind" : "Expression"+ , "type" : "xor# :: BitVector n -> BitVector n -> BitVector n"+ , "template" : "~ARG[0] ^ ~ARG[1]"+ }+ }+, { "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_Index.json view
@@ -1,121 +1,140 @@ [ { "BlackBox" : { "name" : "Clash.Sized.Internal.Index.pack#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "pack# :: Index n -> BitVector (CLog 2 n)"- , "templateE" : "~ARG[0]"+ , "template" : "~ARG[0]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Index.unpack#"- , "type" : "unpack# :: KnownNat n => BitVector (CLog 2 n) -> Index n"- , "templateE" : "~ARG[1]"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] == ~ARG[1]~ELSE1'b1~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] != ~ARG[1]~ELSE1'b0~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] < ~ARG[1]~ELSE1'b0~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] >= ~ARG[1]~ELSE1'b1~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] > ~ARG[1]~ELSE1'b0~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] <= ~ARG[1]~ELSE1'b1~FI"+ , "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"- , "templateE" : "~ARG[0]-~SIZE[~TYPO]'d1"+ , "template" : "~ARG[0]-~SIZE[~TYPO]'d1" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Index.+#"+ , "kind" : "Expression" , "type" : "(+#) :: KnownNat n => Index n -> Index n -> Index n"- , "templateE" : "~ARG[1] + ~ARG[2]"+ , "template" : "~ARG[1] + ~ARG[2]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Index.-#"+ , "kind" : "Expression" , "type" : "(-#) :: KnownNat n => Index n -> Index n -> Index n"- , "templateE" : "~ARG[1] - ~ARG[2]"+ , "template" : "~ARG[1] - ~ARG[2]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Index.*#"+ , "kind" : "Expression" , "type" : "(*#) :: KnownNat n => Index n -> Index n -> Index n"- , "templateE" : "~ARG[1] * ~ARG[2]"+ , "template" : "~ARG[1] * ~ARG[2]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Index.fromInteger#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "fromInteger# :: KnownNat n => Integer -> Index n"- , "templateE" : "$unsigned(~ARG[1][(~SIZE[~TYPO]-1):0])"+ , "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)"- , "templateD" : "assign ~RESULT = ~ARG[0] + ~ARG[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)"- , "templateD" : "assign ~RESULT = ~ARG[0] - ~ARG[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)"- , "templateD" : "assign ~RESULT = ~ARG[0] * ~ARG[1];"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.quot#"- , "type" : "quot# :: Index n -> Index n -> Index n"- , "templateE" : "~ARG[0] / ~ARG[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"- , "templateE" : "~ARG[0] % ~ARG[1]"+ , "template" : "~ARG[0] % ~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Index.toInteger#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "toInteger# :: Index n -> Integer"- , "templateD" : "assign ~RESULT = ~IF~SIZE[~TYP[0]]~THEN$unsigned(~ARG[0])~ELSE64'sd0~FI;"+ , "template" : "~IF~SIZE[~TYP[0]]~THEN~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[0]]]~THEN$signed(~VAR[i][0][0+:~SIZE[~TYPO]])~ELSE$signed({{(~SIZE[~TYPO]-~SIZE[~TYP[0]]) {1'b0}},~VAR[i][0]})~FI~ELSE~SIZE[~TYPO]'sd0~FI" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Index.resize#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "resize# :: KnownNat m => Index n -> Index m"- , "templateD" : "assign ~RESULT = $unsigned(~ARG[1]);"+ , "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_Signed.json view
@@ -1,43 +1,208 @@ [ { "BlackBox" : { "name" : "Clash.Sized.Internal.Signed.eq#"+ , "kind" : "Expression" , "type" : "eq# :: Signed n -> Signed n -> Bool"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] == ~ARG[1]~ELSE1'b1~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] != ~ARG[1]~ELSE1'b0~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] < ~ARG[1]~ELSE1'b0~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] >= ~ARG[1]~ELSE1'b1~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] > ~ARG[1]~ELSE1'b0~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] <= ~ARG[1]~ELSE1'b1~FI"+ , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] <= ~ARG[1]~ELSE1'b1~FI" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Signed.toInteger#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "toInteger# :: Signed n -> Integer"- , "templateD" : "assign ~RESULT = ~IF~SIZE[~TYP[0]]~THEN$unsigned(~ARG[0])~ELSE64'sd0~FI;"+ , "template" : "~IF~SIZE[~TYP[0]]~THEN~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[0]]]~THEN$signed(~VAR[i][0][0+:~SIZE[~TYPO]])~ELSE$signed({{(~SIZE[~TYPO]-~SIZE[~TYP[0]]) {1'b0}},~VAR[i][0]})~FI~ELSE~SIZE[~TYPO]'sd0~FI"+ }+ }+, { "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_Unsigned.json view
@@ -1,43 +1,191 @@ [ { "BlackBox" : { "name" : "Clash.Sized.Internal.Unsigned.eq#"+ , "kind" : "Expression" , "type" : "eq# :: Unsigned n -> Unsigned n -> Bool"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] == ~ARG[1]~ELSE1'b1~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] != ~ARG[1]~ELSE1'b0~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] < ~ARG[1]~ELSE1'b0~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] >= ~ARG[1]~ELSE1'b1~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] > ~ARG[1]~ELSE1'b0~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] <= ~ARG[1]~ELSE1'b1~FI"+ , "template" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] <= ~ARG[1]~ELSE1'b1~FI" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Unsigned.toInteger#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "toInteger# :: Unsigned n -> Integer"- , "templateD" : "assign ~RESULT = ~IF~SIZE[~TYP[0]]~THEN$unsigned(~ARG[0])~ELSE64'sd0~FI;"+ , "template" : "~IF~SIZE[~TYP[0]]~THEN~IF~CMPLE[~SIZE[~TYPO]][~SIZE[~TYP[0]]]~THEN$signed(~VAR[i][0][0+:~SIZE[~TYPO]])~ELSE$signed({{(~SIZE[~TYPO]-~SIZE[~TYP[0]]) {1'b0}},~VAR[i][0]})~FI~ELSE~SIZE[~TYPO]'sd0~FI"+ }+ }+, { "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_Vector.json view
@@ -0,0 +1,17 @@+[ { "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_Transformations.json view
@@ -0,0 +1,8 @@+[ { "BlackBox" :+ { "name" : "Clash.Transformations.eqInt"+ , "kind" : "Expression"+ , "type" : "eqInt :: Int -> Int -> Bool"+ , "template" : "~ARG[0] == ~ARG[1]"+ }+ }+]
+ prims/commonverilog/Clash_Xilinx_ClockGen.json view
@@ -0,0 +1,47 @@+[ { "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/GHC_Base.json view
@@ -0,0 +1,8 @@+[ { "BlackBox" :+ { "name" : "GHC.Base.remInt"+ , "kind" : "Expression"+ , "type" : "remInt :: Int -> Int -> Int"+ , "template" : "~ARG[0] % ~ARG[1]"+ }+ }+]
+ prims/commonverilog/GHC_Classes.json view
@@ -0,0 +1,36 @@+[ { "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.json view
@@ -0,0 +1,30 @@+[+ {+ "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_Integer_Logarithms.json view
@@ -1,21 +1,23 @@ [ { "BlackBox" : { "name" : "GHC.Integer.Logarithms.integerLogBase#"+ , "kind" : "Expression" , "type" : "integerLogBase# :: Integer -> Integer -> Int#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "integerLogBase"- , "extension" : "inc"- , "content" :+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "integerLogBase"+ , "extension" : "inc"+ , "template" : "// integer logBase-function integer ~INCLUDENAME;+function integer ~INCLUDENAME[0]; input integer base, value; begin- for (~INCLUDENAME = 0; value >= base; ~INCLUDENAME=~INCLUDENAME+1)+ for (~INCLUDENAME[0] = 0; value >= base; ~INCLUDENAME[0]=~INCLUDENAME[0]+1) value = value / base; end endfunction"- }- , "templateE" : "~INCLUDENAME(~ARG[0],~ARG[1])"+ }+ ]+ , "template" : "~INCLUDENAME[0](~ARG[0],~ARG[1])" } } ]
+ prims/commonverilog/GHC_Integer_Type.json view
@@ -0,0 +1,189 @@+[ { "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_Natural.json view
@@ -0,0 +1,31 @@+[+ {+ "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_Prim.json view
@@ -0,0 +1,398 @@+[ { "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"+ }+ }+]
+ prims/commonverilog/GHC_Word.json view
@@ -0,0 +1,30 @@+[+ {+ "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/systemverilog/Clash_Explicit_BlockRam.json view
@@ -1,44 +1,140 @@ [ { "BlackBox" : { "name" : "Clash.Explicit.BlockRam.blockRam#"+ , "kind" : "Declaration" , "type" : "blockRam#- :: HasCallStack -- ARG[0]- => Clock dom gated -- clk, ARG[1]- -> Vec n a -- init, ARG[2]- -> Signal dom Int -- rd, ARG[3]- -> Signal dom Bool -- wren, ARG[4]- -> Signal dom Int -- wr, ARG[5]- -> Signal dom a -- din, ARG[6]+ :: ( 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"- , "templateD" :+ , "template" : "// blockRam begin-~SIGD[~GENSYM[RAM][0]][2];-logic [~SIZE[~TYP[6]]-1:0] ~GENSYM[~RESULT_q][1];+~SIGD[~GENSYM[RAM][1]][5];+logic [~SIZE[~TYP[9]]-1:0] ~GENSYM[~RESULT_q][2]; initial begin- ~SYM[0] = ~LIT[2];-end~IF ~ISGATED[1] ~THEN-always @(posedge ~ARG[1][1]) begin : ~GENSYM[~COMPNAME_blockRam][2]~IF ~VIVADO ~THEN- if (~ARG[1][0]) begin- if (~ARG[4]) begin- ~SYM[0][~ARG[5]] <= ~TOBV[~ARG[6]][~TYP[6]];+ ~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[1] <= ~SYM[0][~ARG[3]];+ ~SYM[2] <= ~SYM[1][~ARG[6]]; end~ELSE- if (~ARG[4] & ~ARG[1][0]) begin- ~SYM[0][~ARG[5]] <= ~TOBV[~ARG[6]][~TYP[6]];+ if (~ARG[7] & ~ARG[4]) begin+ ~SYM[1][~ARG[8]] <= ~TOBV[~ARG[9]][~TYP[9]]; end- if (~ARG[1][0]) begin- ~SYM[1] <= ~SYM[0][~ARG[3]];+ if (~ARG[4]) begin+ ~SYM[2] <= ~SYM[1][~ARG[6]]; end~FI end~ELSE-always @(posedge ~ARG[1]) begin : ~SYM[2]- if (~ARG[4]) begin- ~SYM[0][~ARG[5]] <= ~TOBV[~ARG[6]][~TYP[6]];+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[1] <= ~SYM[0][~ARG[3]];+ ~SYM[2] <= ~SYM[1][~ARG[6]]; end~FI-assign ~RESULT = ~FROMBV[~SYM[1]][~TYP[6]];+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_File.json view
@@ -1,47 +1,51 @@ [ { "BlackBox" : { "name" : "Clash.Explicit.BlockRam.File.blockRamFile#"+ , "kind" : "Declaration" , "type" : "blockRamFile#- :: (KnownNat m, HasCallStack)-- (ARG[0],ARG[1])- => Clock dom gated -- clk, ARG[2]- -> SNat n -- sz, ARG[3]- -> FilePath -- file, ARG[4]- -> Signal dom Int -- rd, ARG[5]- -> Signal dom Bool -- wren, ARG[6]- -> Signal dom Int -- wr, ARG[7]- -> Signal dom (BitVector m) -- din, ARG[8]+ :: ( 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)"- , "templateD" :+ , "template" : "// blockRamFile begin-~SIGDO[~GENSYM[RAM][0]] [0:~LIT[3]-1];-~SIGD[~GENSYM[~RESULT_q][1]][8];+~SIGDO[~GENSYM[RAM][1]] [0:~LIT[5]-1];+~SIGD[~GENSYM[~RESULT_q][2]][10]; initial begin- $readmemb(~FILE[~LIT[4]],~SYM[0]);+ $readmemb(~FILE[~LIT[6]],~SYM[1]); end-~IF ~ISGATED[2] ~THEN-always @(posedge ~ARG[2][1]) begin : ~GENSYM[~COMPNAME_blockRamFile][2]~IF ~VIVADO ~THEN- if (~ARG[2][0]) begin- if (~ARG[6]) begin- ~SYM[0][~ARG[7]] <= ~ARG[8];+~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[1] <= ~SYM[0][~ARG[5]];+ ~SYM[2] <= ~SYM[1][~ARG[7]]; end~ELSE- if (~ARG[6] & ~ARG[2][0]) begin- ~SYM[0][~ARG[7]] <= ~ARG[8];+ if (~ARG[8] & ~ARG[4]) begin+ ~SYM[1][~ARG[9]] <= ~ARG[10]; end- if (~ARG[2][0] begin- ~SYM[1] <= ~SYM[0][~ARG[5]];+ if (~ARG[4]) begin+ ~SYM[2] <= ~SYM[1][~ARG[7]]; end~FI end~ELSE-always @(posedge ~ARG[2]) begin : ~SYM[2]- if (~ARG[6]) begin- ~SYM[0][~ARG[7]] <= ~ARG[8];+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[1] <= ~SYM[0][~ARG[5]];+ ~SYM[2] <= ~SYM[1][~ARG[7]]; end~FI -assign ~RESULT = ~SYM[1];+assign ~RESULT = ~SYM[2]; // blockRamFile end" } }
prims/systemverilog/Clash_Explicit_DDR.json view
@@ -1,67 +1,46 @@ [ { "BlackBox" : { "name" : "Clash.Explicit.DDR.ddrIn#"+ , "kind" : "Declaration" , "type" : "ddrIn# :: forall a slow fast n pFast gated synchronous.- ( HasCallStack -- ARG[0]- , fast ~ Dom n pFast -- ARG[1]- , slow ~ Dom n (2*pFast)) -- ARG[2]- => Clock slow gated -- ARG[3]- -> Reset slow synchronous -- ARG[4]- -> a -- ARG[5]- -> a -- ARG[6]- -> a -- ARG[7]- -> Signal fast a -- ARG[8]+ ( 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)"- , "templateD" :+ , "template" : "// ddrIn begin-~SIGD[~GENSYM[data_Pos][1]][8];-~SIGD[~GENSYM[data_Neg][2]][8];-~SIGD[~GENSYM[data_Neg_Latch][3]][8];-~IF ~ISGATED[3] ~THEN-always @(posedge ~ARG[3][1]~IF ~ISSYNC[4] ~THEN ~ELSE or posedge ~ARG[4]~FI) begin : ~GENSYM[~COMPNAME_ddrIn_pos][6]- if (~ARG[4]) begin- ~SYM[1] <= ~ARG[6];- end else if (~ARG[3][0]) begin- ~SYM[1] <= ~ARG[8];- end-end~ELSE-always @(posedge ~ARG[3]~IF ~ISSYNC[4] ~THEN ~ELSE or posedge ~ARG[4]~FI) begin : ~SYM[6]- if (~ARG[4]) begin- ~SYM[1] <= ~ARG[6];- end else 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-end~FI-~IF ~ISGATED[3] ~THEN-always @(negedge ~ARG[3][1]~IF ~ISSYNC[4] ~THEN ~ELSE or posedge ~ARG[4]~FI) begin : ~GENSYM[~COMPNAME_ddrIn_neg][7]- if (~ARG[4]) begin- ~SYM[2] <= ~ARG[7];- end else if (~ARG[3][0]) begin- ~SYM[2] <= ~ARG[8];- end-end~ELSE-always @(negedge ~ARG[3]~IF ~ISSYNC[4] ~THEN ~ELSE or posedge ~ARG[4]~FI) begin : ~SYM[7]- if (~ARG[4]) begin- ~SYM[2] <= ~ARG[7];- end else begin- ~SYM[2] <= ~ARG[8];+ end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin+ ~SYM[1] <= ~ARG[10]; end-end~FI-~IF ~ISGATED[3] ~THEN-always @(posedge ~ARG[3][1]~IF ~ISSYNC[4] ~THEN ~ELSE or posedge ~ARG[4]~FI) begin : ~GENSYM[~COMPNAME_ddrIn_neg_latch][8]- if (~ARG[4]) begin- ~SYM[3] <= ~ARG[5];- end else if (~ARG[3][0]) begin- ~SYM[3] <= ~SYM[2];+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~ELSE-always @(posedge ~ARG[3]~IF ~ISSYNC[4] ~THEN ~ELSE or posedge ~ARG[4]~FI) begin : ~SYM[8]- if (~ARG[4]) begin- ~SYM[3] <= ~ARG[5];- end else begin+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~FI+end assign ~RESULT = {~SYM[3], ~SYM[1]}; // ddrIn end"@@ -69,57 +48,43 @@ } , { "BlackBox" : { "name" : "Clash.Explicit.DDR.ddrOut#"+ , "kind" : "Declaration" , "type" : "ddrOut# :: ( HasCallStack -- ARG[0]- , fast ~ Dom n pFast -- ARG[1]- , slow ~ Dom n (2*pFast)) -- ARG[2]- => Clock slow gated -- ARG[3]- -> Reset slow synchronous -- ARG[4]- -> a -- ARG[5]- -> Signal slow a -- ARG[6]- -> Signal slow a -- ARG[7]+ , 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"- , "templateD" :+ , "template" : "// ddrOut begin-~SIGD[~GENSYM[data_Pos][1]][5];-~SIGD[~GENSYM[data_Neg][2]][5];-~IF ~ISGATED[3] ~THEN-always @(posedge ~ARG[3][1]~IF ~ISSYNC[4] ~THEN ~ELSE or posedge ~ARG[4]~FI) begin : ~GENSYM[~COMPNAME_ddrOut_pos][5]- if (~ARG[4]) begin- ~SYM[1] <= ~ARG[5];- end else if (~ARG[3][0]) begin- ~SYM[1] <= ~ARG[6];- end-end~ELSE-always @(posedge ~ARG[3]~IF ~ISSYNC[4] ~THEN ~ELSE or posedge ~ARG[4]~FI) begin : ~SYM[5]- if (~ARG[4]) begin- ~SYM[1] <= ~ARG[5];- end else begin- ~SYM[1] <= ~ARG[6];- end-end~FI-~IF ~ISGATED[3] ~THEN-always @(posedge ~ARG[3][1]~IF ~ISSYNC[4] ~THEN ~ELSE or posedge ~ARG[4]~FI) begin : ~GENSYM[~COMPNAME_ddrOut_neg][6]- if (~ARG[4]) begin- ~SYM[2] <= ~ARG[5];- end else if (~ARG[3][0]) begin- ~SYM[2] <= ~ARG[7];+~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~ELSE-always @(posedge ~ARG[3]~IF ~ISSYNC[4] ~THEN ~ELSE or posedge ~ARG[4]~FI) begin : ~SYM[6]- if (~ARG[4]) begin- ~SYM[2] <= ~ARG[5];- end else begin+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~FI+end -always @(*) begin ~IF ~ISGATED[3] ~THEN- if (~ARG[3][1]) begin~ELSE- if (~ARG[3]) begin~FI- ~RESULT = ~SYM[1];+always @(*) begin+ if (~ARG[4]) begin+ ~RESULT = ~IF~ACTIVEEDGE[Rising][2]~THEN~SYM[1]~ELSE~SYM[2]~FI; end else begin- ~RESULT = ~SYM[2];+ ~RESULT = ~IF~ACTIVEEDGE[Rising][2]~THEN~SYM[2]~ELSE~SYM[1]~FI; end end // ddrOut end"
prims/systemverilog/Clash_Explicit_RAM.json view
@@ -1,31 +1,30 @@ [ { "BlackBox" : { "name" : "Clash.Explicit.RAM.asyncRam#"+ , "kind" : "Declaration" , "type" : "asyncRam#- :: HasCallStack -- ARG[0]- => Clock wdom wgated -- ^ wclk, ARG[1]- -> Clock rdom rgated -- ^ rclk, ARG[2]- -> SNat n -- ^ sz, ARG[3]- -> Signal rdom Int -- ^ rd, ARG[4]- -> Signal wdom Bool -- ^ en, ARG[5]- -> Signal wdom Int -- ^ wr, ARG[6]- -> Signal wdom a -- ^ din, ARG[7]+ :: ( 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"- , "templateD" :+ , "template" : "// asyncRam begin-logic [~SIZE[~TYP[7]]-1:0] ~GENSYM[RAM][0] [0:~LIT[3]-1];~IF ~ISGATED[1] ~THEN-always @(posedge ~ARG[1][1]) begin : ~GENSYM[~COMPNAME_Ram][1]- if (~ARG[5] & ~ARG[1][0]) begin- ~SYM[0][~ARG[6]] <= ~TOBV[~ARG[7]][~TYP[7]];- end-end~ELSE-always @(posedge ~ARG[1]) begin : ~SYM[1]- if (~ARG[5]) begin- ~SYM[0][~ARG[6]] <= ~TOBV[~ARG[7]][~TYP[7]];+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~FI+end -assign ~RESULT = ~FROMBV[~SYM[0][\\~ARG[4]\\]][~TYPO];+assign ~RESULT = ~FROMBV[~SYM[0][\\~ARG[7]\\]][~TYPO]; // asyncRam end" } }
prims/systemverilog/Clash_Explicit_ROM.json view
@@ -1,27 +1,31 @@ [ { "BlackBox" : { "name" : "Clash.Explicit.ROM.rom#"+ , "kind" : "Declaration" , "type" :-"rom# :: KnownNat n -- ARG[0]- => Clock dom gated -- clk, ARG[1]- -> Vec n a -- init, ARG[2]- -> Signal dom Int -- rd, ARG[3]+"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"- , "templateD" :+ , "template" : "// rom begin-~SIGD[~GENSYM[ROM][0]][2];-assign ~SYM[0] = ~ARG[2];+~SIGD[~GENSYM[ROM][1]][5];+assign ~SYM[1] = ~LIT[5]; -logic [~SIZE[~TYPO]-1:0] ~GENSYM[~RESULT_q][1];~IF ~ISGATED[1] ~THEN-always @(posedge ~ARG[1][1]) begin : ~GENSYM[~COMPNAME_rom][2]- if (~ARG[1][0]) begin- ~SYM[1] <= ~SYM[0][~ARG[3]];+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 @(posedge ~ARG[1]) begin : ~SYM[2]- ~SYM[1] <= ~SYM[0][~ARG[3]];+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[1]][~TYPO];+assign ~RESULT = ~FROMBV[~SYM[2]][~TYPO]; // rom end" } }
prims/systemverilog/Clash_Explicit_ROM_File.json view
@@ -1,28 +1,31 @@ [ { "BlackBox" : { "name" : "Clash.Explicit.ROM.File.romFile#"+ , "kind" : "Declaration" , "type" :-"romFile# :: KnownNat m -- ARG[0]- => Clock clk gated -- clk, ARG[1]- -> SNat n -- sz, ARG[2]- -> FilePath -- file, ARG[3]- -> Signal dom Int -- rd, ARG[4]+"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)"- , "templateD" :+ , "template" : "// romFile begin-~SIGDO[~GENSYM[ROM][0]] [0:~LIT[2]-1];+~SIGDO[~GENSYM[ROM][0]] [0:~LIT[4]-1]; initial begin- $readmemb(~FILE[~LIT[3]],~SYM[0]);+ $readmemb(~FILE[~LIT[5]],~SYM[0]); end -~SIGDO[~GENSYM[~RESULT_q][1]];~IF ~ISGATED[1] ~THEN-always @(posedge ~ARG[1][1]) begin : ~GENSYM[~COMPNAME_romFile][2]- if (~ARG[1][0]) begin- ~SYM[1] <= ~SYM[0][~ARG[4]];+~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 @(posedge ~ARG[1]) begin : ~SYM[2]- ~SYM[1] <= ~SYM[0][~ARG[4]];+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];
prims/systemverilog/Clash_Explicit_Testbench.json view
@@ -1,27 +1,60 @@ [ { "BlackBox" : { "name" : "Clash.Explicit.Testbench.assert"+ , "kind" : "Declaration" , "type" : "assert- :: (Eq a,Show a) -- (ARG[0],ARG[1])- => Clock domain gated -- ARG[2]- -> Reset domain synchronous -- ARG[3]- -> String -- ARG[4]- -> Signal domain a -- Checked value (ARG[5])- -> Signal domain a -- Expected value (ARG[6])- -> Signal domain b -- Return valued (ARG[7])- -> Signal domain b"- , "templateD" :+ :: (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 @(posedge ~IF ~ISGATED[2] ~THEN ~ARG[2][1] ~ELSE ~ARG[2] ~FI~IF ~ISSYNC[3] ~THEN ~ELSE or negedge ~ARG[3]~FI) begin- if (~ARG[5] !== ~ARG[6]) begin+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];-// assert end"+// assertBitVector end" } } ]
− prims/systemverilog/Clash_Intel_ClockGen.json
@@ -1,37 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Intel.ClockGen.altpll"- , "type" :-"altpll- :: SSymbol name -- ARG[0]- -> Clock pllIn 'Source -- ARG[1]- -> Reset pllIn 'Asynchronous -- ARG[2]- -> (Clock pllOut 'Source, Signal pllOut Bool)"- , "templateD" :-"// altpll begin-~NAME[0] ~GENSYM[altpll_inst][2]-(.inclk0 (~ARG[1])-,.areset (~ARG[2])-,.c0 (~RESULT[1])-,.locked (~RESULT[0]));-// altpll end"- }- }-, { "BlackBox" :- { "name" : "Clash.Intel.ClockGen.alteraPll"- , "type" :-"alteraPll- :: SSymbol name -- ARG[0]- -> Clock pllIn 'Source -- ARG[1]- -> Reset pllIn 'Asynchronous -- ARG[2]- -> (Clock pllOut 'Source, Signal pllOut Bool)"- , "templateD" :-"// alteraPll begin-~NAME[0] ~GENSYM[alteraPll_inst][2]-(.refclk (~ARG[1])-,.rst (~ARG[2])-,.outclk_0 (~RESULT[1])-,.locked (~RESULT[0]));-// alteraPll end"- }- }-]
prims/systemverilog/Clash_Intel_DDR.json view
@@ -1,89 +1,48 @@ [ { "BlackBox" : { "name" : "Clash.Intel.DDR.altddioIn"+ , "kind" : "Declaration" , "type" : "altddioIn :: ( HasCallStack -- ARG[0]- , fast ~ Dom n pFast -- ARG[1]- , slow ~ Dom n (2*pFast) -- ARG[2]+ , KnownConfi~ fast domf -- ARG[1]+ , KnownConfi~ slow doms -- ARG[2] , KnownNat m ) -- ARG[3] => SSymbol deviceFamily -- ARG[4]- -> Clock slow gated -- ARG[5]- -> Reset slow synchronous -- ARG[6]- -> Signal fast (BitVector m) -- ARG[7]+ -> Clock slow -- ARG[5]+ -> Reset slow -- ARG[6]+ -> Enable slow -- ARG[7]+ -> Signal fast (BitVector m) -- ARG[8] -> Signal slow (BitVector m,BitVector m)"- , "templateD" :+ , "libraries" : ["altera_mf"]+ , "template" : "// altddioIn begin-~SIGD[~GENSYM[dataout_l][1]][7];-~SIGD[~GENSYM[dataout_h][2]][7];--altddio_in ~GENSYM[~COMPNAME_ALTDDIO_IN][7] (~IF ~ISSYNC[6] ~THEN- .sclr (~ARG[6]),- .aclr (1'b0),~ELSE- .aclr (~ARG[6]),- .sclr (1'b0),~FI- .datain (~ARG[7]),~IF ~ISGATED[5] ~THEN- .inclock (~ARG[5][1]),- .inclocken (~ARG[5][0]),~ELSE- .inclock (~ARG[5]),- .inclocken (1'b1),~FI- .dataout_h (~SYM[2]),- .dataout_l (~SYM[1]),- .aset (1'b0),- .sset (1'b0));-defparam- ~SYM[7].intended_device_family = ~LIT[4],- ~SYM[7].invert_input_clocks = \"OFF\",- ~SYM[7].lpm_hint = \"UNUSED\",- ~SYM[7].lpm_type = \"altddio_in\",- ~SYM[7].power_up_high = \"OFF\",- ~SYM[7].width = ~SIZE[~TYP[7]];+~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"- }- }-, { "BlackBox" :- { "name" : "Clash.Intel.DDR.altddioOut#"- , "type" :-"altddioOut#- :: ( HasCallStack -- ARG[0]- , fast ~ Dom n pFast -- ARG[1]- , slow ~ Dom n (2*pFast) -- ARG[2]- , KnownNat m ) -- ARG[3]- => SSymbol deviceFamily -- ARG[4]- -> Clock slow gated -- ARG[5]- -> Reset slow synchronous -- ARG[6]- -> Signal slow (BitVector m) -- ARG[7]- -> Signal slow (BitVector m) -- ARG[8]- -> Signal fast (BitVector m)"- , "templateD" :-"// altddioOut begin-altddio_out ~GENSYM[~COMPNAME_ALTDDIO_OUT][7] (~IF ~ISSYNC[6] ~THEN- .sclr (~ARG[6]),- .aclr (1'b0),~ELSE- .aclr (~ARG[6]),- .sclr (1'b0),~FI- .datain_h (~ARG[7]),- .datain_l (~ARG[8]),~IF ~ISGATED[5] ~THEN- .outclock (~ARG[5][1]),- .outclocken (~ARG[5][0]),~ELSE- .outclock (~ARG[5]),- .outclocken (1'b1),~FI- .dataout (~RESULT),- .aset (1'b0),- .sset (1'b0),- .oe (1'b1),- .oe_out ());-defparam- ~SYM[7].extend_oe_disable = \"OFF\",- ~SYM[7].intended_device_family = ~LIT[4],- ~SYM[7].invert_output = \"OFF\",- ~SYM[7].lpm_hint = \"UNUSED\",- ~SYM[7].lpm_type = \"altddio_out\",- ~SYM[7].oe_reg = \"UNREGISTERED\",- ~SYM[7].power_up_high = \"OFF\",- ~SYM[7].width = ~SIZE[~TYPO];-// altddioOut end" } } ]
prims/systemverilog/Clash_Prelude_ROM.json view
@@ -1,14 +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"- , "templateD" :+ , "template" : "// asyncRom begin ~SIGD[~GENSYM[ROM][0]][1];-assign ~SYM[0] = ~ARG[1];+assign ~SYM[0] = ~LIT[1]; assign ~RESULT = ~FROMBV[~SYM[0][\\~ARG[2]\\]][~TYPO]; // asyncRom end"
prims/systemverilog/Clash_Prelude_ROM_File.json view
@@ -1,12 +1,13 @@ [ { "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"- , "templateD" :+ , "template" : "// asyncRomFile begin ~SIGDO[~GENSYM[ROM][0]] [0:~LIT[1]-1];
+ prims/systemverilog/Clash_Signal_BiSignal.json view
@@ -0,0 +1,34 @@+[ { "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",+ "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_Internal.json view
@@ -1,108 +1,104 @@ [ { "BlackBox" : { "name" : "Clash.Signal.Internal.delay#"+ , "kind" : "Declaration" , "type" : "delay#- :: HasCallStack -- ARG[0]- => Clock domain gated -- ARG[1]- -> Signal clk a -- ARG[2]+ :: ( 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"- , "templateD" :-"// register begin~IF ~ISGATED[1] ~THEN-always_ff @(posedge ~ARG[1][1]) begin : ~GENSYM[~COMPNAME_delay][0]- if (~ARG[1][0]) begin- ~RESULT <= ~ARG[2];+ , "template" :+"// delay begin,+~TYPO ~GENSYM[~RESULT_reg][0] ~IF ~ISINITDEFINED[0] ~THEN = ~CONST[4] ~ELSE ~FI;~IF ~ISACTIVEENABLE[3] ~THEN+always_ff @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[2]) begin : ~GENSYM[~RESULT_delay][1]+ if (~ARG[3]) begin+ ~SYM[0] <= ~ARG[5]; end end~ELSE-always_ff @(posedge ~ARG[1]) begin : ~SYM[0]- ~RESULT <= ~ARG[2];+always_ff @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[2]) begin : ~SYM[1]+ ~SYM[0] <= ~ARG[5]; end~FI-// register end"+assign ~RESULT = ~SYM[0];+// delay end" } } , { "BlackBox" : { "name" : "Clash.Signal.Internal.register#"+ , "kind" : "Declaration" , "type" : "register#- :: HasCallStack -- ARG[0]- => Clock domain gated -- ARG[1]- -> Reset domain synchronous -- ARG[2]- -> a -- ARG[3]- -> Signal clk a -- ARG[4]+ :: ( 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"- , "templateD" :-"// register begin~IF ~ISGATED[1] ~THEN-always_ff @(posedge ~ARG[1][1]~IF ~ISSYNC[2] ~THEN ~ELSE or posedge ~ARG[2]~FI) begin : ~GENSYM[~COMPNAME_register][0]- if (~ARG[2]) begin- ~RESULT <= ~ARG[3];- end else if (~ARG[1][0]) begin- ~RESULT <= ~ARG[4];- end-end~ELSE-always_ff @(posedge ~ARG[1]~IF ~ISSYNC[2] ~THEN ~ELSE or posedge ~ARG[2]~FI) begin : ~SYM[0]- if (~ARG[2]) begin- ~RESULT <= ~ARG[3];- end else begin- ~RESULT <= ~ARG[4];+ , "template" :+"// register begin+~TYPO ~GENSYM[~RESULT_reg][0] ~IF ~ISINITDEFINED[0] ~THEN = ~CONST[5] ~ELSE ~FI;+always_ff @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[2]~IF ~ISSYNC[0] ~THEN ~ELSE or ~IF ~ISACTIVEHIGH[0] ~THEN posedge ~ELSE negedge ~FI ~ARG[3]~FI) begin : ~GENSYM[~RESULT_register][1]+ if (~IF ~ISACTIVEHIGH[0] ~THEN ~ELSE ! ~FI~ARG[3]) begin+ ~SYM[0] <= ~CONST[6];+ end else ~IF ~ISACTIVEENABLE[4] ~THEN if (~ARG[4]) ~ELSE ~FI begin+ ~SYM[0] <= ~ARG[7]; end-end~FI+end+assign ~RESULT = ~SYM[0]; // register end" } } , { "BlackBox" :- { "name" : "Clash.Signal.Internal.clockGate"- , "type" :-"clockGate- :: Clock domain gated -- ARG[0]- -> Signal domain Bool -- ARG[1]- -> Clcok domain 'Gated"- , "templateD" :-"// clockGate begin~IF ~ISGATED[0] ~THEN-assign ~RESULT = {~ARG[0][1],~ARG[0][0] & ~ARG[1]};~ELSE-assign ~RESULT = {~ARG[0],~ARG[1]};~FI-// clockGate end"- }- }-, { "BlackBox" : { "name" : "Clash.Signal.Internal.clockGen"+ , "workInfo" : "Always"+ , "kind" : "Declaration"+ , "warning" : "Clash.Signal.Internal.clockGen is not synthesizable!" , "type" : "clockGen- :: (domain ~ Dom nm period -- ARG[0]- ,KnownSymbol nm -- ARG[1]- ,KnownNat period) -- ARG[2]- => Clock domain Source"- , "templateD" :-"// pragma translate_off+ :: KnownDomain dom -- ARG[0]+ => Clock dom"+ , "template" :+"// clockGen begin+// pragma translate_off // 1 = 0.1ps-localparam ~GENSYM[half_period][0] = (~LIT[2]0 / 2);+localparam ~GENSYM[half_period][0] = (~PERIOD[0]0 / 2); always begin- ~RESULT = 0;- #3000 forever 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"+// pragma translate_on+// clockGen end" } } , { "BlackBox" :- { "name" : "Clash.Signal.Internal.tbClockGen"+ { "name" : "Clash.Explicit.Testbench.tbClockGen"+ , "workInfo" : "Always"+ , "kind" : "Declaration"+ , "warning" : "Clash.Signal.Internal.tbClockGen is not synthesizable!" , "type" : "tbClockGen- :: (domain ~ Dom nm period -- ARG[0]- ,KnownSymbol nm -- ARG[1]- ,KnownNat period) -- ARG[2]- => Signal domain Bool -- ARG[3]- -> Clock domain Source"- , "templateD" :-"// pragma translate_off+ :: 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] = (~LIT[2]0 / 2);+localparam ~GENSYM[half_period][0] = (~PERIOD[0]0 / 2); always begin- ~RESULT = 0;- #3000 forever begin- if (~ ~ARG[3]) begin+ ~RESULT = ~IF~ACTIVEEDGE[Rising][0]~THEN 0 ~ELSE 1 ~FI;+ #30000 forever begin+ if (~ ~ARG[1]) begin $finish; end ~RESULT = ~ ~RESULT;@@ -111,90 +107,32 @@ #~SYM[0]; end end-// pragma translate_on"+// pragma translate_on+// tbClockGen end" } } , { "BlackBox" :- { "name" : "Clash.Signal.Internal.asyncResetGen"- , "type" : "asyncResetGen :: Reset domain Asynchronous"- , "templateD" :-"// pragma translate_off+ { "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 = 1;- #1999 ~RESULT = 0;-end-// pragma translate_on"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.syncResetGen"- , "type" : "asyncResetGen :: Reset domain Synchronous"- , "templateD" :-"// pragma translate_off-localparam ~GENSYM[reset_period][1] = 2998 + ~LIT[1]0;+ #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 = 1;- #~SYM[1] ~RESULT = 0;+ #1 ~RESULT = ~IF ~ISACTIVEHIGH[0] ~THEN 1 ~ELSE 0 ~FI;+ #~SYM[1] ~RESULT = ~IF ~ISACTIVEHIGH[0] ~THEN 0 ~ELSE 1 ~FI; end-// pragma translate_on"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.unsafeFromAsyncReset"- , "type" :-"unsafeFromAsyncReset :: Reset domain Asynchronous -> Signal domain Bool"- , "templateE" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.unsafeToAsyncReset"- , "type" :-"unsafeToAsyncReset :: Signal domain Bool -> Reset domain Asynchronous"- , "templateE" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.fromSyncReset"- , "type" :-"fromSyncReset :: Reset domain Synchronous -> Signal domain Bool"- , "templateE" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.unsafeToSyncReset"- , "type" :-"unsafeToSyncReset :: Signal domain Bool -> Reset domain Synchronous"- , "templateE" : "~ARG[0]"- }- }-, { "Primitive" :- { "name" : "Clash.Signal.Internal.signal#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Signal.Internal.mapSignal#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Signal.Internal.appSignal#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Signal.Internal.foldr#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Signal.Internal.traverse#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Signal.Internal.joinSignal#"- , "primType" : "Function"+~FI+// pragma translate_on+// resetGen end" } } ]
prims/systemverilog/Clash_Sized_Internal_BitVector.json view
@@ -1,40 +1,13 @@ [ { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.size#"- , "type" : "size# :: KnownNat n => BitVector n -> Int"- , "templateE" : "~SIZE[~TYPO]'sd~LIT[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.maxIndex#"- , "type" : "maxIndex# :: KnownNat n => BitVector n -> Int"- , "templateE" : "~SIZE[~TYPO]'sd~LIT[0] - ~SIZE[~TYPO]'sd1"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.++#"- , "type" : "(++#) :: KnownNat m => BitVector n -> BitVector m -> BitVector (n + m)"- , "templateE" : "{~ARG[1],~ARG[2]}"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.index#"- , "type" :-"index# :: KnownNat n -- ARG[0]- => BitVector n -- ARG[1]- -> Int -- ARG[2]- -> Bit"- , "templateE" : "~VAR[bv][1][~ARG[2]]"- }- }-, { "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"- , "templateD" :+ , "template" : "// replaceBit start always_comb begin ~RESULT = ~ARG[1];@@ -45,13 +18,15 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.setSlice#"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "setSlice# :: BitVector (m + 1 + i) -- ARG[0] -> SNat m -- ARG[1] -> SNat n -- ARG[2] -> BitVector (m + 1 - n) -- ARG[3] -> BitVector (m + 1 + i)"- , "templateD" :+ , "template" : "// setSlice begin always_comb begin ~RESULT = ~ARG[0];@@ -61,22 +36,14 @@ } } , { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.slice#"- , "type" :-"slice# :: BitVector (m + 1 + i) -- ARG[0]- -> SNat m -- ARG[1]- -> SNat n -- ARG[2]- -> BitVector (m + 1 - n)"- , "templateE" : "~VAR[bv][0][~LIT[1] : ~LIT[2]]"- }- }-, { "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)"- , "templateD" :+ , "template" : "// split begin assign ~RESULT = { ~VAR[bv][1][$high(~VAR[bv][1]) : ~LIT[0]] , ~VAR[bv][1][(~LIT[0]-1) : 0]@@ -85,156 +52,27 @@ } } , { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.msb#"- , "type" :-"msb# :: KnownNat n -- ARG[0]- => BitVector n -- ARG[1]- -> Bit"- , "templateE" : "~IF ~LIT[0] ~THEN ~VAR[bv][1][~LIT[0]-1] ~ELSE 1'b0 ~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.lsb#"- , "type" :-"lsb# :: BitVector n -- ARG[0]- -> Bit"- , "templateE" : "~IF ~SIZE[~TYP[0]] ~THEN ~VAR[bv][0][0] ~ELSE 1'b0 ~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.minBound#"- , "type" : "minBound# :: BitVector n"- , "templateE" : "~SIZE[~TYPO]'d0"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.maxBound#"- , "type" : "maxBound# :: KnownNat n => BitVector n"- , "templateE" : "{~LIT[0] {1'b1}}"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.+#"- , "type" : "(+#) :: KnownNat n => BitVector n -> BitVector n -> BitVector n"- , "templateE" : "~ARG[1] + ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.-#"- , "type" : "(-#) :: KnownNat n => BitVector n -> BitVector n -> BitVector n"- , "templateE" : "~ARG[1] - ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.*#"- , "type" : "(*#) :: KnownNat n => BitVector n -> BitVector n -> BitVector n"- , "templateE" : "~ARG[1] * ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.negate#"- , "type" : "negate# :: KnownNat n => BitVector n -> BitVector n"- , "templateE" : "-~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.fromInteger#"- , "type" : "fromInteger# :: KnownNat n => Integer -> BitVector n"- , "templateE" : "$unsigned(~ARG[1][(~LIT[0]-1):0])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.plus#"- , "type" : "plus# :: BitVector m -> BitVector n -> BitVector (Max m n + 1)"- , "templateD" : "assign ~RESULT = ~ARG[0] + ~ARG[1];"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.minus#"- , "type" : "minus# :: (KnownNat m, KnownNat n) => BitVector m -> BitVector n -> BitVector (Max m n + 1)"- , "templateD" : "assign ~RESULT = ~ARG[2] - ~ARG[3];"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.times#"- , "type" : "times# :: KnownNat (m + n) => BitVector m -> BitVector n -> BitVector (m + n)"- , "templateD" : "assign ~RESULT = ~ARG[0] * ~ARG[1];"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.quot#"- , "type" : "quot# :: BitVector n -> BitVector n -> BitVector n"- , "templateE" : "~ARG[0] / ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.rem#"- , "type" : "rem# :: BitVector n -> BitVector n -> BitVector n"- , "templateE" : "~ARG[0] % ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.and#"- , "type" : "and# :: BitVector n -> BitVector n -> BitVector n"- , "templateE" : "~ARG[0] & ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.or#"- , "type" : "or# :: BitVector n -> BitVector n -> BitVector n"- , "templateE" : "~ARG[0] | ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.xor#"- , "type" : "xor# :: BitVector n -> BitVector n -> BitVector n"- , "templateE" : "~ARG[0] ^ ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.complement#"- , "type" : "complement# :: KnownNat n => BitVector n -> BitVector n"- , "templateE" : "~ ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.shiftL#"- , "type" : "shiftL# :: KnownNat n => BitVector n -> Int -> BitVector n"- , "templateE" : "~ARG[1] << ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.shiftR#"- , "type" : "shiftR# :: KnownNat n => BitVector n -> Int -> BitVector n"- , "templateE" : "~ARG[1] >> ~ARG[2]"- }- }-, { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.rotateL#"+ , "kind" : "Declaration" , "type" : "rotateL# :: KnownNat n => BitVector n -> Int -> BitVector n"- , "templateD" :+ , "template" : "// rotateL begin-logic [2*~LIT[0]-1:0] ~GENSYM[bv][0];-assign ~SYM[0] = {~ARG[1],~ARG[1]} << ~ARG[2];-assign ~RESULT = ~SYM[0][2*~LIT[0]-1 : ~LIT[0]];+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"- , "templateD" :+ , "template" : "// rotateR begin-logic [2*~LIT[0]-1:0] ~GENSYM[bv][0];-assign ~SYM[0] = {~ARG[1],~ARG[1]} >> ~ARG[2];-assign ~RESULT = ~SYM[0][~LIT[0]-1 : 0];+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"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.resize#"- , "type" : "resize# :: KnownNat m => BitVector n -> BitVector m"- , "templateD" : "assign ~RESULT = $unsigned(~ARG[1]);" } } ]
prims/systemverilog/Clash_Sized_Internal_Signed.json view
@@ -1,105 +1,8 @@ [ { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.size#"- , "type" : "size# :: KnownNat n => Signed n -> Int"- , "templateE" : "~SIZE[~TYPO]'sd~LIT[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.pack#"- , "type" : "pack# :: KnownNat n => Signed n -> BitVector n"- , "templateE" : "$unsigned(~ARG[1])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.unpack#"- , "type" : "unpack# :: KnownNat n => BitVector n -> Signed n"- , "templateE" : "$signed(~ARG[1])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.minBound#"- , "type" : "minBound# :: KnownNat n => Signed n"- , "comment" : "Generates incorrect SV for n=0"- , "templateE" : "$signed({1'b1, {(~LIT[0]-1) {1'b0}}})"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.maxBound#"- , "type" : "maxBound# :: KnownNat n => Signed n"- , "comment" : "Generates incorrect SV for n=0"- , "templateE" : "$signed({1'b0, {(~LIT[0]-1) {1'b1}}})"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.+#"- , "type" : "(+#) :: KnownNat n => Signed n -> Signed n -> Signed n"- , "templateE" : "~ARG[1] + ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.-#"- , "type" : "(-#) :: KnownNat n => Signed n -> Signed n -> Signed n"- , "templateE" : "~ARG[1] - ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.*#"- , "type" : "(*#) :: KnownNat n => Signed n -> Signed n -> Signed n"- , "templateE" : "~ARG[1] * ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.negate#"- , "type" : "negate# :: KnownNat n => Signed n -> Signed n"- , "templateE" : "-~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.abs#"- , "type" : "abs# :: KnownNat n => Signed n -> Signed n"- , "templateE" : "(~ARG[1] < ~LIT[0]'sd0) ? -~ARG[1] : ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.fromInteger#"- , "type" : "fromInteger# :: KnownNat n => Integer -> Signed (n :: Nat)"- , "templateE" : "$signed(~ARG[1][(~LIT[0]-1):0])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.plus#"- , "type" : "plus# :: Signed m -> Signed n -> Signed (1 + Max m n)"- , "templateD" : "assign ~RESULT = ~ARG[0] + ~ARG[1];"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.minus#"- , "type" : "minus# :: Signed m -> Signed n -> Signed (1 + Max m n)"- , "templateD" : "assign ~RESULT = ~ARG[0] - ~ARG[1];"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.times#"- , "type" : "times# :: Signed m -> Signed n -> Signed (m + n)"- , "templateD" : "assign ~RESULT = ~ARG[0] * ~ARG[1];"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.quot#"- , "type" : "quot# :: Signed n -> Signed n -> Signed n"- , "templateE" : "~ARG[0] / ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.rem#"- , "type" : "rem# :: Signed n -> Signed n -> Signed n"- , "templateE" : "~ARG[0] % ~ARG[1]"- }- }-, { "BlackBox" : { "name" : "Clash.Sized.Internal.Signed.div#"+ , "kind" : "Declaration" , "type" : "div# :: KnownNat n => Signed n -> Signed n -> Signed n"- , "templateD" :+ , "template" : "// divSigned begin // divide (rounds towards zero) ~SIGD[~GENSYM[quot_res][0]][1];@@ -112,8 +15,9 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Signed.mod#"+ , "kind" : "Declaration" , "type" : "mod# :: Signed n -> Signed n -> Signed n"- , "templateD" :+ , "template" : "// modSigned begin // remainder ~SIGD[~GENSYM[rem_res][0]][0];@@ -127,85 +31,27 @@ } } , { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.and#"- , "type" : "and# :: KnownNat n => Signed n -> Signed n -> Signed n"- , "templateE" : "~ARG[1] & ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.or#"- , "type" : "or# :: KnownNat n => Signed n -> Signed n -> Signed n"- , "templateE" : "~ARG[1] | ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.xor#"- , "type" : "xor# :: KnownNat n => Signed n -> Signed n -> Signed n"- , "templateE" : "~ARG[1] ^ ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.complement#"- , "type" : "complement# :: KnownNat n => Signed n -> Signed n"- , "templateE" : "~ ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.shiftL#"- , "type" : "shiftL# :: KnownNat n => Signed n -> Int -> Signed n"- , "templateE" : "~ARG[1] <<< ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.shiftR#"- , "type" : "shiftR# :: KnownNat n => Signed n -> Int -> Signed n"- , "templateE" : "~ARG[1] >>> ~ARG[2]"- }- }-, { "BlackBox" : { "name" : "Clash.Sized.Internal.Signed.rotateL#"+ , "kind" : "Declaration" , "type" : "rotateL# :: KnownNat n => Signed n -> Int -> Signed n"- , "templateD" :+ , "template" : "// rotateL begin-logic [2*~LIT[0]-1:0] ~GENSYM[s][0];-assign ~SYM[0] = {~ARG[1],~ARG[1]} << ~ARG[2];-assign ~RESULT = $signed(~SYM[0][~LIT[0]-1 : 0]);+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"- , "templateD" :+ , "template" : "// rotateR begin-logic [2*~LIT[0]-1:0] ~GENSYM[s][0];-assign ~SYM[0] = {~ARG[1],~ARG[1]} >> ~ARG[2];-assign ~RESULT = $signed(~SYM[0][~LIT[0]-1 : 0]);+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"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.resize#"- , "type" : "resize# :: (KnownNat n, KnownNat m) => Signed n -> Signed m"- , "comment" : "Back-end should only use this code when the result is smaller than the argument"- , "templateD" :-"// resize begin-~GENERATE- if (~LIT[1] < ~LIT[0]) begin- // truncate, sign preserving- assign ~RESULT = $signed({~VAR[s][2][~LIT[0]-1],~VAR[s][2][(~LIT[1]-2):0]});- end else begin- // sign-extend- assign ~RESULT = $signed(~VAR[s][2]);- end-~ENDGENERATE-// resize end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.truncateB#"- , "type" : "truncateB# :: KnownNat m => Signed (n + m) -> Signed m"- , "templateD" : "assign ~RESULT = $signed(~ARG[1]);" } } ]
prims/systemverilog/Clash_Sized_Internal_Unsigned.json view
@@ -1,155 +1,25 @@ [ { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.size#"- , "type" : "size# :: KnownNat n => Unsigned n -> Int"- , "templateE" : "~SIZE[~TYPO]'sd~LIT[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.pack#"- , "type" : "pack# :: Unsigned n -> BitVector n"- , "templateE" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.unpack#"- , "type" : "unpack# :: BitVector n -> Unsigned n"- , "templateE" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.minBound#"- , "type" : "minBound# :: Unsigned n"- , "templateE" : "~SIZE[~TYPO]'d0"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.maxBound#"- , "type" : "maxBound# :: KnownNat n => Unsigned n"- , "templateE" : "{~LIT[0] {1'b1}}"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.+#"- , "type" : "(+#) :: KnownNat n => Unsigned n -> Unsigned n -> Unsigned n"- , "templateE" : "~ARG[1] + ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.-#"- , "type" : "(-#) :: KnownNat n => Unsigned n -> Unsigned n -> Unsigned n"- , "templateE" : "~ARG[1] - ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.*#"- , "type" : "(*#) :: KnownNat n => Unsigned n -> Unsigned n -> Unsigned n"- , "templateE" : "~ARG[1] * ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.negate#"- , "type" : "negate# :: KnownNat n => Unsigned n -> Unsigned n"- , "templateE" : "- ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.fromInteger#"- , "type" : "fromInteger# :: KnownNat n => Integer -> Unsigned n"- , "templateE" : "$unsigned(~ARG[1][(~LIT[0]-1):0])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.plus#"- , "type" : "plus# :: Unsigned m -> Unsigned n -> Unsigned (1 + Max m n)"- , "templateD" : "assign ~RESULT = ~ARG[0] + ~ARG[1];"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.minus#"- , "type" : "minus# :: (KnownNat m, KnownNat n) => Unsigned m -> Unsigned n -> Unsigned (1 + Max m n)"- , "templateD" : "assign ~RESULT = ~ARG[2] - ~ARG[3];"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.times#"- , "type" : "times# :: Unsigned m -> Unsigned n -> Unsigned (m + n)"- , "templateD" : "assign ~RESULT = ~ARG[0] * ~ARG[1];"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.quot#"- , "type" : "quot# :: Unsigned n -> Unsigned n -> Unsigned n"- , "templateE" : "~ARG[0] / ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.rem#"- , "type" : "rem# :: Unsigned n -> Unsigned n -> Unsigned n"- , "templateE" : "~ARG[0] % ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.and#"- , "type" : "and# :: Unsigned n -> Unsigned n -> Unsigned n"- , "templateE" : "~ARG[0] & ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.or#"- , "type" : "or# :: Unsigned n -> Unsigned n -> Unsigned n"- , "templateE" : "~ARG[0] | ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.xor#"- , "type" : "xor# :: Unsigned n -> Unsigned n -> Unsigned n"- , "templateE" : "~ARG[0] ^ ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.complement#"- , "type" : "complement# :: KnownNat n => Unsigned n -> Unsigned n"- , "templateE" : "~ ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.shiftL#"- , "type" : "shiftL# :: KnownNat n => Unsigned n -> Int -> Unsigned n"- , "templateE" : "~ARG[1] << ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.shiftR#"- , "type" : "shiftR# :: KnownNat n => Unsigned n -> Int -> Unsigned n"- , "templateE" : "~ARG[1] >> ~ARG[2]"- }- }-, { "BlackBox" : { "name" : "Clash.Sized.Internal.Unsigned.rotateL#"+ , "kind" : "Declaration" , "type" : "rotateL# :: KnownNat n => Unsigned n -> Int -> Unsigned n"- , "templateD" :+ , "template" : "// rotateL begin-logic [2*~LIT[0]-1:0] ~GENSYM[u][0];-assign ~SYM[0] = {~ARG[1],~ARG[1]} << ~ARG[2];-assign ~RESULT = ~SYM[0][~LIT[0]-1 : 0];+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"- , "templateD" :+ , "template" : "// rotateR begin-logic [2*~LIT[0]-1:0] ~GENSYM[u][0];-assign ~SYM[0] = {~ARG[1],~ARG[1]} >> ~ARG[2];-assign ~RESULT = ~SYM[0][~LIT[0]-1 : 0];+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"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.resize#"- , "type" : "resize# :: KnownNat m => Unsigned n -> Unsigned m"- , "templateD" : "assign ~RESULT = $unsigned(~ARG[1]);" } } ]
prims/systemverilog/Clash_Sized_RTree.json view
@@ -1,19 +1,25 @@ [ { "BlackBox" : { "name" : "Clash.Sized.RTree.treplicate"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "replicate :: SNat d -> a -> RTree d a"- , "templateE" : "'{(2**~LIT[0]) {~TOBV[~ARG[1]][~TYP[1]]}}"+ , "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"- , "templateE" : "~FROMBV[~VAR[tree][0][\\0\\]][~TYPO]"+ , "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)"- , "templateE" : "~TOBV[~VAR[tree][0]][~TYP[0]]"+ , "template" : "~TOBV[~VAR[tree][0]][~TYP[0]]" } } ]
prims/systemverilog/Clash_Sized_Vector.json view
@@ -1,29 +1,39 @@ [ { "BlackBox" : { "name" : "Clash.Sized.Vector.head"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "head :: Vec (n + 1) a -> a"- , "templateE" : "~FROMBV[~VAR[vec][0][\\0\\]][~TYPO]"+ , "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"- , "templateE" : "~VAR[vec][0][1 : $high(~VAR[vec][0])]"+ , "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"- , "templateE" : "~FROMBV[~VAR[vec][0][\\$high(~VAR[vec][0])\\]][~TYPO]"+ , "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"- , "templateE" : "~VAR[vec][0][0 : $high(~VAR[vec][0]) - 1]"+ , "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]@@ -31,7 +41,7 @@ -> SNat n -- ARG[3] -> Vec i a -- ARG[4] -> Vec n a"- , "templateD" :+ , "template" : "// select begin genvar ~GENSYM[n][1]; ~GENERATE@@ -44,14 +54,18 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.++"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "(++) :: Vec n a -> Vec m a -> Vec (n + m) a"- , "templateE" : "~FROMBV[{~TOBV[~ARG[0]][~TYP[0]],~TOBV[~ARG[1]][~TYP[1]]}][~TYPO]"+ , "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"- , "templateD" :+ , "template" : "// concat begin genvar ~GENSYM[n][1]; ~GENERATE@@ -64,8 +78,10 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.splitAt"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "splitAt :: SNat m -> Vec (m + n) a -> (Vec m a, Vec n a)"- , "templateD" :+ , "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];@@ -84,13 +100,15 @@ } , { "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)"- , "templateD" :-"// unconcat begin+ , "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]@@ -102,8 +120,10 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.map"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "map :: (a -> b) -> Vec n a -> Vec n b"- , "templateD" :+ , "template" : "// map begin genvar ~GENSYM[n][1]; ~GENERATE@@ -123,14 +143,16 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.imap"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "imap :: KnownNat n => (Index n -> a -> b) -> Vec n a -> Vec n b"- , "templateD" :+ , "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] = ~LENGTH[~TYPO] - 1 - ~SYM[1];~IF~SIZE[~TYP[2]]~THEN+ 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];@@ -147,14 +169,16 @@ } , { "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"- , "templateD" :+ , "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] = ~LENGTH[~TYPO] - 1 - ~SYM[1] + ~ARG[0];~IF~SIZE[~TYP[2]]~THEN+ 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];@@ -171,8 +195,10 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.zipWith"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "zipWith :: (a -> b -> c) -> Vec n a -> Vec n b -> Vec n c"- , "templateD" :+ , "template" : "// zipWith begin genvar ~GENSYM[n][2]; ~GENERATE@@ -195,8 +221,10 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.foldr"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "foldr :: (a -> b -> b) -> b -> Vec n a -> b"- , "templateD" :+ , "template" : "// foldr start~IF ~LENGTH[~TYP[2]] ~THEN ~SIGDO[~GENSYM[intermediate][0]] [0:~LENGTH[~TYP[2]]]; assign ~SYM[0][~LENGTH[~TYP[2]]] = ~ARG[1];@@ -222,23 +250,26 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.fold"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "fold :: (a -> a -> a) -> Vec (n+1) a -> a" , "comment" : "THIS ONLY WORKS FOR POWER OF TWO LENGTH VECTORS"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "depth2Index"- , "extension" : "inc"- , "content" :+ , "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;+function integer ~INCLUDENAME[0]; input integer levels; input integer depth; - ~INCLUDENAME = (2 ** levels) - (2 ** depth);+ ~INCLUDENAME[0] = (2 ** levels) - (2 ** depth); endfunction"- }- , "templateD" :+ }+ ]+ , "template" : "// fold begin // put flat input array into the first half of the intermediate array ~SIGDO[~GENSYM[intermediate][0]] [0:(2*~LENGTH[~TYP[1]])-2];@@ -252,12 +283,12 @@ genvar ~GENSYM[i][6]; ~GENERATE if (~SYM[4] != 0) begin : ~GENSYM[make_tree][7]- for (~SYM[5] = (~SYM[4] - 1); ~SYM[5] >= 0; ~SYM[5]=~SYM[5]-1) begin : tree_depth- for (~SYM[6] = 0; ~SYM[6] < (2**~SYM[5]); ~SYM[6] = ~SYM[6]+1) begin : tree_depth_loop+ for (~SYM[5] = ~SYM[4]; ~SYM[5] > 0; ~SYM[5]=~SYM[5]-1) begin : tree_depth+ for (~SYM[6] = 0; ~SYM[6] < (2**(~SYM[5]-1)); ~SYM[6] = ~SYM[6]+1) begin : tree_depth_loop ~INST 0- ~OUTPUT <= ~SYM[0][~INCLUDENAME(~SYM[4]+1,~SYM[5]+1)+~SYM[6]]~ ~TYPO~- ~INPUT <= ~SYM[0][~INCLUDENAME(~SYM[4]+1,~SYM[5]+2)+(2*~SYM[6])]~ ~TYPO~- ~INPUT <= ~SYM[0][~INCLUDENAME(~SYM[4]+1,~SYM[5]+2)+(2*~SYM[6])+1]~ ~TYPO~+ ~OUTPUT <= ~SYM[0][~INCLUDENAME[0](~SYM[4]+1,~SYM[5])+~SYM[6]]~ ~TYPO~+ ~INPUT <= ~SYM[0][~INCLUDENAME[0](~SYM[4]+1,~SYM[5]+1)+(2*~SYM[6])]~ ~TYPO~+ ~INPUT <= ~SYM[0][~INCLUDENAME[0](~SYM[4]+1,~SYM[5]+1)+(2*~SYM[6])+1]~ ~TYPO~ ~INST end end@@ -271,14 +302,16 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.index_int"- , "type" : "index_integer :: KnownNat n => Vec n a -> Int -> a"- , "templateE" : "~FROMBV[~VAR[vec][1][\\~ARG[2]\\]][~TYPO]"+ , "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"- , "templateD" :+ , "template" : "// replaceVec start always_comb begin ~RESULT = ~ARG[1];@@ -288,27 +321,19 @@ } } , { "BlackBox" :- { "name" : "Clash.Sized.Vector.maxIndex"- , "type" : "maxIndex :: KnownNat n => Vec n a -> Int"- , "templateE" : "~SIZE[~TYPO]'sd~LIT[0] - ~SIZE[~TYPO]'sd1"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.length"- , "type" : "length :: KnownNat n => Vec n a -> Int"- , "templateE" : "~SIZE[~TYPO]'sd~LIT[0]"- }- }-, { "BlackBox" : { "name" : "Clash.Sized.Vector.replicate"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "replicate :: SNat n -> a -> Vec n a"- , "templateE" : "'{~LIT[0] {~TOBV[~ARG[1]][~TYP[1]]}}"+ , "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)"- , "templateD" :+ , "template" : "// transpose begin genvar ~GENSYM[row_index][1]; genvar ~GENSYM[col_index][2];@@ -325,8 +350,10 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.reverse"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "reverse :: Vec n a -> Vec n a"- , "templateD" :+ , "template" : "// reverse begin genvar ~GENSYM[n][1]; ~GENERATE@@ -338,33 +365,33 @@ } } , { "BlackBox" :- { "name" : "Clash.Sized.Vector.lazyV"- , "type" : "lazyV :: KnownNat n => Vec n a -> Vec n a"- , "templateE" : "~ARG[1]"- }- }-, { "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)"- , "templateE" : "~TOBV[~ARG[2]][~TYP[2]]"+ , "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)"- , "templateE" : "~FROMBV[~ARG[2]][~TYPO]"+ , "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"- , "templateD" :+ , "template" : "// rotateLeftS begin localparam ~GENSYM[shift_amount][2] = ~LIT[2] % ~LIT[0]; @@ -381,8 +408,10 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.rotateRightS"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "rotateRightS :: KnownNat n => Vec n a -> SNat d -> Vec n a"- , "templateD" :+ , "template" : "// rotateRightS begin localparam ~GENSYM[shift_amount][2] = ~LIT[2] % ~LIT[0];
− prims/systemverilog/Clash_Xilinx_ClockGen.json
@@ -1,39 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Xilinx.ClockGen.clockWizard"- , "type" :-"clockWizard- :: SSymbol name -- ARG[0]- -> Clock pllIn 'Source -- ARG[1]- -> Reset pllIn 'Asynchronous -- ARG[2]- -> (Clock pllOut 'Source, Signal pllOut Bool)"- , "templateD" :-"// clockWizard begin-~NAME[0] ~GENSYM[clockWizard_inst][2]-(.CLK_IN1 (~ARG[1])-,.RESET (~ARG[2])-,.CLK_OUT1 (~RESULT[1])-,.LOCKED (~RESULT[0]));-// clockWizard end"- }- }-, { "BlackBox" :- { "name" : "Clash.Xilinx.ClockGen.clockWizardDifferential"- , "type" :-"clockWizardDifferential- :: SSymbol name -- ARG[0]- -> Clock pllIn 'Source -- ARG[1]- -> Clock pllIn 'Source -- ARG[2]- -> Reset pllIn 'Asynchronous -- ARG[3]- -> (Clock pllOut 'Source, Signal pllOut Bool)"- , "templateD" :-"// clockWizardDifferential begin-~NAME[0] ~GENSYM[clockWizardDifferential_inst][2]-(.CLK_IN1_D_clk_n (~ARG[1])-,.CLK_IN1_D_clk_n (~ARG[2])-,.RESET (~ARG[3])-,.CLK_OUT1 (~RESULT[1])-,.LOCKED (~RESULT[0]));-// clockWizardDifferential end"- }- }-]
prims/systemverilog/Clash_Xilinx_DDR.json view
@@ -1,37 +1,37 @@ [ { "BlackBox" : { "name" : "Clash.Xilinx.DDR.iddr"+ , "kind" : "Declaration" , "type" : "iddr :: ( HasCallStack -- ARG[0]- , fast ~ Dom n pFast -- ARG[1]- , slow ~ Dom n (2*pFast) -- ARG[2]+ , KnownConfi~ fast domf -- ARG[1]+ , KnownConfi~ slow doms -- ARG[2] , KnownNat m ) -- ARG[3]- -> Clock slow gated -- ARG[4]- -> Reset slow synchronous -- ARG[5]- -> Signal fast (BitVector m) -- ARG[6]+ -> Clock slow -- ARG[4]+ -> Reset slow -- ARG[5]+ -> Enable slow -- ARG[6]+ -> Signal fast (BitVector m) -- ARG[7] -> Signal slow (BitVector m,BitVector m)"- , "templateD" :+ , "template" : "// iddr begin-~SIGD[~GENSYM[dataout_l][1]][6];-~SIGD[~GENSYM[dataout_h][2]][6];-~SIGD[~GENSYM[d][3]][6];-assign ~SYM[3] = ~ARG[6];+~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[6]]; ~SYM[8]=~SYM[8]+1) begin : ~GENSYM[ddri_array][7]+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[5] ~THEN \"SYNC\" ~ELSE \"ASYNC\" ~FI)+ .SRTYPE(~IF ~ISSYNC[2] ~THEN \"SYNC\" ~ELSE \"ASYNC\" ~FI) ) ~GENSYM[~COMPNAME_IDDR][9] ( .Q1(~SYM[1][~SYM[8]]),- .Q2(~SYM[2][~SYM[8]]),~IF ~ISGATED[6] ~THEN- .C(~ARG[4][1]),- .CE(~ARG[4][0]),~ELSE+ .Q2(~SYM[2][~SYM[8]]), .C(~ARG[4]),- .CE(1'b1),~FI+ .CE(~IF ~ISACTIVEENABLE[6] ~THEN ~ARG[6] ~ELSE 1'b1 ~FI), .D(~SYM[3][~SYM[8]]), .R(~ARG[5]), .S(1'b0)@@ -45,38 +45,38 @@ } , { "BlackBox" : { "name" : "Clash.Xilinx.DDR.oddr#"+ , "kind" : "Declaration" , "type" : "oddr#- :: ( slow ~ Dom n (2*pFast) -- ARG[0]- , fast ~ Dom n pFast -- ARG[1]- , KnownNat m ) -- ARG[2]- => Clock slow gated -- ARG[3]- -> Reset slow synchronous -- ARG[4]- -> Signal slow (BitVector m) -- ARG[5]- -> Signal slow (BitVector m) -- ARG[6]+ :: ( 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)"- , "templateD" :+ , "template" : "// oddr begin-~SIGD[~GENSYM[datain_l][1]][6];-~SIGD[~GENSYM[datain_h][2]][6];-~SIGD[~GENSYM[q][3]][6];+~SIGD[~GENSYM[datain_l][1]][7];+~SIGD[~GENSYM[datain_h][2]][7];+~SIGD[~GENSYM[q][3]][7]; -assign ~SYM[1] = ~ARG[5];-assign ~SYM[2] = ~ARG[6];+assign ~SYM[1] = ~ARG[6];+assign ~SYM[2] = ~ARG[7]; genvar ~GENSYM[i][8]; ~GENERATE-for (~SYM[8]=0; ~SYM[8] < ~SIZE[~TYP[6]]; ~SYM[8]=~SYM[8]+1) begin : ~GENSYM[ddro_array][7]+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[4] ~THEN \"SYNC\" ~ELSE \"ASYNC\" ~FI)+ .SRTYPE(~IF ~ISSYNC[2] ~THEN \"SYNC\" ~ELSE \"ASYNC\" ~FI) ) ~GENSYM[~COMPNAME_ODDR][9] (- .Q(~SYM[3][~SYM[8]]),~IF ~ISGATED[3] ~THEN- .C(~ARG[3][1]),- .CE(~ARG[3][0]),~ELSE+ .Q(~SYM[3][~SYM[8]]), .C(~ARG[3]),- .CE(1'b1),~FI+ .CE(~IF ~ISACTIVEENABLE[5] ~THEN ~ARG[5] ~ELSE 1'b1 ~FI), .D1(~SYM[1][~SYM[8]]), .D2(~SYM[2][~SYM[8]]), .R(~ARG[4]),
prims/systemverilog/GHC_Base.json view
@@ -1,24 +1,8 @@-[ { "Primitive" :- { "name" : "GHC.Base.$"- , "primType" : "Function"- }- }-, { "BlackBox" :- { "name" : "GHC.Base.quotInt"- , "type" : "quotInt :: Int -> Int -> Int"- , "templateE" : "~ARG[0] / ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Base.remInt"- , "type" : "remInt :: Int -> Int -> Int"- , "templateE" : "~ARG[0] % ~ARG[1]"- }- }-, { "BlackBox" :+[ { "BlackBox" : { "name" : "GHC.Base.divInt"+ , "kind" : "Declaration" , "type" : "divInt :: Int -> Int -> Int"- , "templateD" :+ , "template" : "// divInt begin // divide (rounds towards zero) ~SIGD[~GENSYM[quot_res][0]][0];@@ -31,8 +15,9 @@ } , { "BlackBox" : { "name" : "GHC.Base.modInt"+ , "kind" : "Declaration" , "type" : "modInt :: Int -> Int -> Int"- , "templateD" :+ , "template" : "// modInt begin // remainder ~SIGD[~GENSYM[rem_res][0]][0];
prims/systemverilog/GHC_Classes.json view
@@ -1,61 +1,8 @@ [ { "BlackBox" :- { "name" : "GHC.Classes.eqInt"- , "type" : "eqInt :: Int -> Int -> Bool"- , "templateE" : "~ARG[0] == ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.neInt"- , "type" : "neInt :: Int -> Int -> Bool"- , "templateE" : "~ARG[0] != ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.gtInt"- , "type" : "gtInt :: Int -> Int -> Bool"- , "templateE" : "~ARG[0] > ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.geInt"- , "type" : "geInt :: Int -> Int -> Bool"- , "templateE" : "~ARG[0] >= ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.ltInt"- , "type" : "ltInt :: Int -> Int -> Bool"- , "templateE" : "~ARG[0] < ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.leInt"- , "type" : "leInt :: Int -> Int -> Bool"- , "templateE" : "~ARG[0] <= ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.&&"- , "type" : "(&&) :: Bool -> Bool -> Bool"- , "templateE" : "~ARG[0] & ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.||"- , "type" : "(::) :: Bool -> Bool -> Bool"- , "templateE" : "~ARG[0] | ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.not"- , "type" : "not :: Bool -> Bool"- , "templateE" : "~ ~ARG[0]"- }- }-, { "BlackBox" : { "name" : "GHC.Classes.divInt#"+ , "kind" : "Declaration" , "type" : "divInt# :: Int# -> Int# -> Int#"- , "templateD" :+ , "template" : "// divInt# begin // divide (rounds towards zero) ~SIGD[~GENSYM[quot_res][0]][0];@@ -68,8 +15,9 @@ } , { "BlackBox" : { "name" : "GHC.Classes.modInt#"+ , "kind" : "Declaration" , "type" : "modInt# :: Int# -> Int# -> Int#"- , "templateD" :+ , "template" : "// modInt# begin // remainder ~SIGD[~GENSYM[rem_res][0]][0];
− prims/systemverilog/GHC_Int.json
@@ -1,25 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Int.I8#"- , "type" : "I8# :: Int# -> Int8"- , "templateD" : "assign ~RESULT = $signed(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Int.I16#"- , "type" : "I16# :: Int# -> Int16"- , "templateD" : "assign ~RESULT = $signed(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Int.I32#"- , "type" : "I32# :: Int# -> Int32"- , "templateD" : "assign ~RESULT = $signed(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Int.I64#"- , "type" : "I64# :: Int# -> Int64"- , "templateD" : "assign ~RESULT = $signed(~ARG[0]);"- }- }-]
prims/systemverilog/GHC_Integer_Type.json view
@@ -1,49 +1,8 @@ [ { "BlackBox" :- { "name" : "GHC.Integer.Type.smallInteger"- , "type" : "smallInteger :: Int# -> Integer"- , "templateD" : "assign ~RESULT = $signed(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.integerToInt"- , "type" : "integerToInt :: Integer -> Int#"- , "templateD" : "assign ~RESULT = $signed(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.plusInteger"- , "type" : "plusInteger :: Integer -> Integer -> Integer"- , "templateE" : "~ARG[0] + ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.minusInteger"- , "type" : "minusInteger :: Integer -> Integer -> Integer"- , "templateE" : "~ARG[0] - ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.timesInteger"- , "type" : "timesInteger :: Integer -> Integer -> Integer"- , "templateE" : "~ARG[0] * ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.negateInteger"- , "type" : "negateInteger :: Integer -> Integer"- , "templateE" : "-~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.absInteger"- , "type" : "absInteger :: Integer -> Integer"- , "templateE" : "(~ARG[0] < ~SIZE[~TYPO]'sd0) ? -~ARG[0] : ~ARG[0]"- }- }-, { "BlackBox" : { "name" : "GHC.Integer.Type.divInteger"+ , "kind" : "Declaration" , "type" : "divInteger :: Integer -> Integer -> Integer"- , "templateD" :+ , "template" : "// divInteger begin // divide (rounds towards zero) ~SIGD[~GENSYM[quot_res][0]][0];@@ -56,8 +15,9 @@ } , { "BlackBox" : { "name" : "GHC.Integer.Type.modInteger"+ , "kind" : "Declaration" , "type" : "modInteger :: Integer -> Integer -> Integer"- , "templateD" :+ , "template" : "// modInteger begin // remainder ~SIGD[~GENSYM[rem_res][0]][0];@@ -68,114 +28,6 @@ ~SYM[0] : ((~VAR[dividend][0] == ~SIZE[~TYPO]'sd0) ? ~SIZE[~TYPO]'sd0 : ~SYM[0] + ~VAR[divider][1]); // modInteger end"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.quotInteger"- , "type" : "quotInteger :: Integer -> Integer -> Integer"- , "templateE" : "~ARG[0] / ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.remInteger"- , "type" : "remInteger :: Integer -> Integer -> Integer"- , "templateE" : "~ARG[0] % ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.eqInteger"- , "type" : "eqInteger :: Integer -> Integer -> Bool"- , "templateE" : "~ARG[0] == ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.neqInteger"- , "type" : "neqInteger :: Integer -> Integer -> Bool"- , "templateE" : "~ARG[0] != ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.leInteger"- , "type" : "leInteger :: Integer -> Integer -> Bool"- , "templateE" : "~ARG[0] <= ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.gtInteger"- , "type" : "gtInteger :: Integer -> Integer -> Bool"- , "templateE" : "~ARG[0] > ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.ltInteger"- , "type" : "ltInteger :: Integer -> Integer -> Bool"- , "templateE" : "~ARG[0] < ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.geInteger"- , "type" : "geInteger :: Integer -> Integer -> Bool"- , "templateE" : "~ARG[0] >= ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.eqInteger#"- , "type" : "eqInteger :: Integer -> Integer -> Bool"- , "templateE" : "(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.neqInteger#"- , "type" : "neqInteger :: Integer -> Integer -> Bool"- , "templateE" : "(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.leInteger#"- , "type" : "leInteger :: Integer -> Integer -> Bool"- , "templateE" : "(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.gtInteger#"- , "type" : "gtInteger :: Integer -> Integer -> Bool"- , "templateE" : "(~ARG[0] > ~ARG[1] ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.ltInteger#"- , "type" : "ltInteger :: Integer -> Integer -> Bool"- , "templateE" : "(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.geInteger#"- , "type" : "geInteger :: Integer -> Integer -> Bool"- , "templateE" : "(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.shiftRInteger"- , "type" : "shiftRInteger :: Integer -> Int# -> Integer"- , "templateE" : "~ARG[0] >>> ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.shiftLInteger"- , "type" : "shiftLInteger :: Integer -> Int# -> Integer"- , "templateE" : "~ARG[0] <<< ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.wordToInteger"- , "type" : "wordToInteger :: Word# -> Integer"- , "templateD" : "assign ~RESULT = $signed(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.integerToWord"- , "type" : "integerToWord :: Integer -> Word#"- , "templateD" : "assign ~RESULT = $unsigned(~ARG[0]);" } } ]
prims/systemverilog/GHC_Prim.json view
@@ -1,79 +1,8 @@ [ { "BlackBox" :- { "name" : "GHC.Prim.gtChar#"- , "type" : "gtChar# :: Char# -> Char# -> Int#"- , "templateE" : "(~ARG[0] > ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.geChar#"- , "type" : "geChar# :: Char# -> Char# -> Int#"- , "templateE" : "(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.eqChar#"- , "type" : "eqChar# :: Char# -> Char# -> Int#"- , "templateE" : "(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.neChar#"- , "type" : "neChar# :: Char# -> Char# -> Int#"- , "templateE" : "(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ltChar#"- , "type" : "ltChar# :: Char# -> Char# -> Int#"- , "templateE" : "(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.leChar#"- , "type" : "leChar# :: Char# -> Char# -> Int#"- , "templateE" : "(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ord#"- , "type" : "ord :: Char# -> Int#"- , "templateD" : "assign ~RESULT = $unsigned(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.+#"- , "type" : "(+#) :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] + ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.-#"- , "type" : "(-#) :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] - ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.*#"- , "type" : "(*#) :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] * ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.quotInt#"- , "type" : "quotInt# :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] / ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.remInt#"- , "type" : "remInt# :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] % ~ARG[1]"- }- }-, { "BlackBox" : { "name" : "GHC.Prim.quotRemInt#"+ , "kind" : "Declaration" , "type" : "quotRemInt# :: Int# -> Int# -> (#Int#, Int##)"- , "templateD" :+ , "template" : "// quotRemInt begin ~SIGD[~GENSYM[quot_res][0]][0]; ~SIGD[~GENSYM[rem_res][1]][0];@@ -85,135 +14,10 @@ } } , { "BlackBox" :- { "name" : "GHC.Prim.andI#"- , "type" : "andI# :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] & ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.orI#"- , "type" : "orI# :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] | ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.xorI#"- , "type" : "xorI# :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] ^ ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.notI#"- , "type" : "notI# :: Int# -> Int#"- , "templateE" : "~ ~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.negateInt#"- , "type" : "negateInt# :: Int# -> Int#"- , "templateE" : "-(~ARG[0])"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.>#"- , "type" : "(>#) :: Int# -> Int# -> Int#"- , "templateE" : "(~ARG[0] > ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.>=#"- , "type" : "(>=#) :: Int# -> Int# -> Int#"- , "templateE" : "(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.==#"- , "type" : "(==) :: Int# -> Int# -> Int#"- , "templateE" : "(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim./=#"- , "type" : "(/=#) :: Int# -> Int# -> Int#"- , "templateE" : "(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.<#"- , "type" : "(<#) :: Int# -> Int# -> Int#"- , "templateE" : "(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.<=#"- , "type" : "(<=#) :: Int# -> Int# -> Int#"- , "templateE" : "(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.chr#"- , "type" : "ord :: Int# -> Char#"- , "templateD" : "assign ~RESULT = $unsigned(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.int2Word#"- , "type" : "int2Word# :: Int# -> Word#"- , "templateE" : "$unsigned(~ARG[0])"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.uncheckedIShiftL#"- , "type" : "uncheckedIShiftL# :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] <<< ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.uncheckedIShiftRA#"- , "type" : "uncheckedIShiftRA# :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] >>> ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.uncheckedIShiftRL#"- , "type" : "uncheckedIShiftRL# :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] >> ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.plusWord#"- , "type" : "plusWord# :: Word# -> Word# -> Word#"- , "templateE" : "~ARG[0] + ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.minusWord#"- , "type" : "minusWord# :: Word# -> Word# -> Word#"- , "templateE" : "~ARG[0] - ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.timesWord#"- , "type" : "timesWord# :: Word# -> Word# -> Word#"- , "templateE" : "~ARG[0] * ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.quotWord#"- , "type" : "quotWord# :: Word# -> Word# -> Word#"- , "templateE" : "~ARG[0] / ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.remWord#"- , "type" : "remWord# :: Word# -> Word# -> Word#"- , "templateE" : "~ARG[0] % ~ARG[1]"- }- }-, { "BlackBox" : { "name" : "GHC.Prim.quotRemWord#"+ , "kind" : "Declaration" , "type" : "quotRemWord# :: Word# -> Word# -> (#Word#, Word##)"- , "templateD" :+ , "template" : "// quotRemWord begin ~SIGD[~GENSYM[quot_res][0]][0]; ~SIGD[~GENSYM[rem_res][1]][0];@@ -225,101 +29,25 @@ } } , { "BlackBox" :- { "name" : "GHC.Prim.and#"- , "type" : "and# :: Word# -> Word# -> Word#"- , "templateE" : "~ARG[0] & ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.or#"- , "type" : "or# :: Word# -> Word# -> Word#"- , "templateE" : "~ARG[0] | ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.xor#"- , "type" : "xor# :: Word# -> Word# -> Word#"- , "templateE" : "~ARG[0] ^ ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.not#"- , "type" : "not# :: Word# -> Word#"- , "templateE" : "~ ~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.uncheckedShiftL#"- , "type" : "uncheckedShiftL# :: Word# -> Int# -> Word#"- , "templateE" : "~ARG[0] << ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.uncheckedShiftRL#"- , "type" : "uncheckedShiftRL# :: Word# -> Int# -> Word#"- , "templateE" : "~ARG[0] >> ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.word2Int#"- , "type" : "int2Word# :: Word# -> Int#"- , "templateE" : "$signed(~ARG[0])"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.gtWord#"- , "type" : "gtWord# :: Word# -> Word# -> Int#"- , "templateE" : "(~ARG[0] > ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.geWord#"- , "type" : "geWord# :: Word# -> Word# -> Int#"- , "templateE" : "(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.eqWord#"- , "type" : "eqWord# :: Word# -> Word# -> Int#"- , "templateE" : "(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.neWord#"- , "type" : "neWord# :: Word# -> Word# -> Int#"- , "templateE" : "(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ltWord#"- , "type" : "ltWord# :: Word# -> Word# -> Int#"- , "templateE" : "(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.leWord#"- , "type" : "leWord# :: Word# -> Word# -> Int#"- , "templateE" : "(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" : { "name" : "GHC.Prim.popCnt8#"+ , "kind" : "Declaration" , "type" : "popCnt8# :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "depth2Index"- , "extension" : "inc"- , "content" :+ , "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;+function integer ~INCLUDENAME[0]; input integer levels; input integer depth; - ~INCLUDENAME = (2 ** levels) - (2 ** depth);+ ~INCLUDENAME[0] = (2 ** levels) - (2 ** depth); endfunction"- }- , "templateD" :+ }+ ]+ , "template" : "// popCnt8 begin localparam ~GENSYM[width][0] = 8; @@ -332,7 +60,7 @@ 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(~ARG[0][~SYM[4]]);+ assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]); end ~ENDGENERATE @@ -341,11 +69,11 @@ genvar ~GENSYM[i][7]; ~GENERATE if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]- for (~SYM[6] = (~SYM[2] - 1); ~SYM[6] >= 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]- for (~SYM[7] = 0; ~SYM[7] < (2**~SYM[6]); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]- assign ~SYM[3][~INCLUDENAME(~SYM[2]+1,~SYM[6]+1)+~SYM[7]] =- ~SYM[3][~INCLUDENAME(~SYM[2]+1,~SYM[6]+2)+(2*~SYM[7])] +- ~SYM[3][~INCLUDENAME(~SYM[2]+1,~SYM[6]+2)+(2*~SYM[7])+1];+ 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@@ -358,22 +86,24 @@ } , { "BlackBox" : { "name" : "GHC.Prim.popCnt16#"+ , "kind" : "Declaration" , "type" : "popCnt16# :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "depth2Index"- , "extension" : "inc"- , "content" :+ , "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;+function integer ~INCLUDENAME[0]; input integer levels; input integer depth; - ~INCLUDENAME = (2 ** levels) - (2 ** depth);+ ~INCLUDENAME[0] = (2 ** levels) - (2 ** depth); endfunction"- }- , "templateD" :+ }+ ]+ , "template" : "// popCnt16 begin localparam ~GENSYM[width][0] = 16; @@ -386,7 +116,7 @@ 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(~ARG[0][~SYM[4]]);+ assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]); end ~ENDGENERATE @@ -395,11 +125,11 @@ genvar ~GENSYM[i][7]; ~GENERATE if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]- for (~SYM[6] = (~SYM[2] - 1); ~SYM[6] >= 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]- for (~SYM[7] = 0; ~SYM[7] < (2**~SYM[6]); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]- assign ~SYM[3][~INCLUDENAME(~SYM[2]+1,~SYM[6]+1)+~SYM[7]] =- ~SYM[3][~INCLUDENAME(~SYM[2]+1,~SYM[6]+2)+(2*~SYM[7])] +- ~SYM[3][~INCLUDENAME(~SYM[2]+1,~SYM[6]+2)+(2*~SYM[7])+1];+ 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@@ -412,22 +142,24 @@ } , { "BlackBox" : { "name" : "GHC.Prim.popCnt32#"+ , "kind" : "Declaration" , "type" : "popCnt32# :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "depth2Index"- , "extension" : "inc"- , "content" :+ , "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;+function integer ~INCLUDENAME[0]; input integer levels; input integer depth; - ~INCLUDENAME = (2 ** levels) - (2 ** depth);+ ~INCLUDENAME[0] = (2 ** levels) - (2 ** depth); endfunction"- }- , "templateD" :+ }+ ]+ , "template" : "// popCnt32 begin localparam ~GENSYM[width][0] = 32; @@ -440,7 +172,7 @@ 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(~ARG[0][~SYM[4]]);+ assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]); end ~ENDGENERATE @@ -449,11 +181,11 @@ genvar ~GENSYM[i][7]; ~GENERATE if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]- for (~SYM[6] = (~SYM[2] - 1); ~SYM[6] >= 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]- for (~SYM[7] = 0; ~SYM[7] < (2**~SYM[6]); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]- assign ~SYM[3][~INCLUDENAME(~SYM[2]+1,~SYM[6]+1)+~SYM[7]] =- ~SYM[3][~INCLUDENAME(~SYM[2]+1,~SYM[6]+2)+(2*~SYM[7])] +- ~SYM[3][~INCLUDENAME(~SYM[2]+1,~SYM[6]+2)+(2*~SYM[7])+1];+ 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@@ -466,22 +198,24 @@ } , { "BlackBox" : { "name" : "GHC.Prim.popCnt64#"+ , "kind" : "Declaration" , "type" : "popCnt64# :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "depth2Index"- , "extension" : "inc"- , "content" :+ , "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;+function integer ~INCLUDENAME[0]; input integer levels; input integer depth; - ~INCLUDENAME = (2 ** levels) - (2 ** depth);+ ~INCLUDENAME[0] = (2 ** levels) - (2 ** depth); endfunction"- }- , "templateD" :+ }+ ]+ , "template" : "// popCnt64 begin localparam ~GENSYM[width][0] = 64; @@ -494,7 +228,7 @@ 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(~ARG[0][~SYM[4]]);+ assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]); end ~ENDGENERATE @@ -503,11 +237,11 @@ genvar ~GENSYM[i][7]; ~GENERATE if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]- for (~SYM[6] = (~SYM[2] - 1); ~SYM[6] >= 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]- for (~SYM[7] = 0; ~SYM[7] < (2**~SYM[6]); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]- assign ~SYM[3][~INCLUDENAME(~SYM[2]+1,~SYM[6]+1)+~SYM[7]] =- ~SYM[3][~INCLUDENAME(~SYM[2]+1,~SYM[6]+2)+(2*~SYM[7])] +- ~SYM[3][~INCLUDENAME(~SYM[2]+1,~SYM[6]+2)+(2*~SYM[7])+1];+ 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@@ -520,22 +254,24 @@ } , { "BlackBox" : { "name" : "GHC.Prim.popCnt#"- , "type" : "popCnt8# :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "depth2Index"- , "extension" : "inc"- , "content" :+ , "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;+function integer ~INCLUDENAME[0]; input integer levels; input integer depth; - ~INCLUDENAME = (2 ** levels) - (2 ** depth);+ ~INCLUDENAME[0] = (2 ** levels) - (2 ** depth); endfunction"- }- , "templateD" :+ }+ ]+ , "template" : "// popCnt begin localparam ~GENSYM[width][0] = ~SIZE[~TYPO]; @@ -548,7 +284,7 @@ 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(~ARG[0][~SYM[4]]);+ assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]); end ~ENDGENERATE @@ -557,11 +293,11 @@ genvar ~GENSYM[i][7]; ~GENERATE if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]- for (~SYM[6] = (~SYM[2] - 1); ~SYM[6] >= 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]- for (~SYM[7] = 0; ~SYM[7] < (2**~SYM[6]); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]- assign ~SYM[3][~INCLUDENAME(~SYM[2]+1,~SYM[6]+1)+~SYM[7]] =- ~SYM[3][~INCLUDENAME(~SYM[2]+1,~SYM[6]+2)+(2*~SYM[7])] +- ~SYM[3][~INCLUDENAME(~SYM[2]+1,~SYM[6]+2)+(2*~SYM[7])+1];+ 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@@ -574,23 +310,25 @@ } , { "BlackBox" : { "name" : "GHC.Prim.clz8#"+ , "kind" : "Declaration" , "type" : "clz8 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "enc"- , "extension" : "inc"- , "content" :-"function [1:0] ~INCLUDENAME;+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "enc"+ , "extension" : "inc"+ , "template" :+"function [1:0] ~INCLUDENAME[0]; input [1:0] a; case (a)- 2'b00: ~INCLUDENAME = 2'b10;- 2'b01: ~INCLUDENAME = 2'b01;- 2'b10: ~INCLUDENAME = 2'b00;- default: ~INCLUDENAME = 2'b00;+ 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"- }- , "templateD" :+ }+ ]+ , "template" : "// clz8 begin logic [0:7] ~GENSYM[v][1]; assign ~SYM[1] = ~ARG[0][7:0];@@ -599,7 +337,7 @@ 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(~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]); end ~ENDGENERATE @@ -640,23 +378,25 @@ } , { "BlackBox" : { "name" : "GHC.Prim.clz16#"+ , "kind" : "Declaration" , "type" : "clz16 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "enc"- , "extension" : "inc"- , "content" :-"function [1:0] ~INCLUDENAME;+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "enc"+ , "extension" : "inc"+ , "template" :+"function [1:0] ~INCLUDENAME[0]; input [1:0] a; case (a)- 2'b00: ~INCLUDENAME = 2'b10;- 2'b01: ~INCLUDENAME = 2'b01;- 2'b10: ~INCLUDENAME = 2'b00;- default: ~INCLUDENAME = 2'b00;+ 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"- }- , "templateD" :+ }+ ]+ , "template" : "// clz16 begin logic [0:15] ~GENSYM[v][1]; assign ~SYM[1] = ~ARG[0][15:0];@@ -665,7 +405,7 @@ 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(~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]); end ~ENDGENERATE @@ -722,23 +462,25 @@ } , { "BlackBox" : { "name" : "GHC.Prim.clz32#"+ , "kind" : "Declaration" , "type" : "clz32 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "enc"- , "extension" : "inc"- , "content" :-"function [1:0] ~INCLUDENAME;+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "enc"+ , "extension" : "inc"+ , "template" :+"function [1:0] ~INCLUDENAME[0]; input [1:0] a; case (a)- 2'b00: ~INCLUDENAME = 2'b10;- 2'b01: ~INCLUDENAME = 2'b01;- 2'b10: ~INCLUDENAME = 2'b00;- default: ~INCLUDENAME = 2'b00;+ 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"- }- , "templateD" :+ }+ ]+ , "template" : "// clz32 begin logic [0:31] ~GENSYM[v][1]; assign ~SYM[1] = ~ARG[0][31:0];@@ -747,7 +489,7 @@ 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(~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]); end ~ENDGENERATE @@ -820,23 +562,25 @@ } , { "BlackBox" : { "name" : "GHC.Prim.clz64#"+ , "kind" : "Declaration" , "type" : "clz64 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "enc"- , "extension" : "inc"- , "content" :-"function [1:0] ~INCLUDENAME;+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "enc"+ , "extension" : "inc"+ , "template" :+"function [1:0] ~INCLUDENAME[0]; input [1:0] a; case (a)- 2'b00: ~INCLUDENAME = 2'b10;- 2'b01: ~INCLUDENAME = 2'b01;- 2'b10: ~INCLUDENAME = 2'b00;- default: ~INCLUDENAME = 2'b00;+ 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"- }- , "templateD" :+ }+ ]+ , "template" : "// clz64 begin logic [0:63] ~GENSYM[v][1]; assign ~SYM[1] = ~ARG[0][63:0];@@ -845,7 +589,7 @@ 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(~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]); end ~ENDGENERATE @@ -934,23 +678,25 @@ } , { "BlackBox" : { "name" : "GHC.Prim.clz#"+ , "kind" : "Declaration" , "type" : "clz :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "enc"- , "extension" : "inc"- , "content" :-"function [1:0] ~INCLUDENAME;+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "enc"+ , "extension" : "inc"+ , "template" :+"function [1:0] ~INCLUDENAME[0]; input [1:0] a; case (a)- 2'b00: ~INCLUDENAME = 2'b10;- 2'b01: ~INCLUDENAME = 2'b01;- 2'b10: ~INCLUDENAME = 2'b00;- default: ~INCLUDENAME = 2'b00;+ 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"- }- , "templateD" :+ }+ ]+ , "template" : "// clz begin ~IF ~IW64 ~THEN logic [0:63] ~GENSYM[v][1];@@ -960,7 +706,7 @@ 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(~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]); end ~ENDGENERATE @@ -1050,7 +796,7 @@ 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(~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]); end ~ENDGENERATE @@ -1123,23 +869,25 @@ } , { "BlackBox" : { "name" : "GHC.Prim.ctz8#"+ , "kind" : "Declaration" , "type" : "ctz8 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "enc"- , "extension" : "inc"- , "content" :-"function [1:0] ~INCLUDENAME;+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "enc"+ , "extension" : "inc"+ , "template" :+"function [1:0] ~INCLUDENAME[0]; input [1:0] a; case (a)- 2'b00: ~INCLUDENAME = 2'b10;- 2'b01: ~INCLUDENAME = 2'b01;- 2'b10: ~INCLUDENAME = 2'b00;- default: ~INCLUDENAME = 2'b00;+ 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"- }- , "templateD" :+ }+ ]+ , "template" : "// ctz8 begin logic [0:7] ~GENSYM[v][1]; genvar ~GENSYM[k][18];@@ -1153,7 +901,7 @@ 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(~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]); end ~ENDGENERATE @@ -1194,23 +942,25 @@ } , { "BlackBox" : { "name" : "GHC.Prim.ctz16#"+ , "kind" : "Declaration" , "type" : "ctz16 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "enc"- , "extension" : "inc"- , "content" :-"function [1:0] ~INCLUDENAME;+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "enc"+ , "extension" : "inc"+ , "template" :+"function [1:0] ~INCLUDENAME[0]; input [1:0] a; case (a)- 2'b00: ~INCLUDENAME = 2'b10;- 2'b01: ~INCLUDENAME = 2'b01;- 2'b10: ~INCLUDENAME = 2'b00;- default: ~INCLUDENAME = 2'b00;+ 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"- }- , "templateD" :+ }+ ]+ , "template" : "// ctz16 begin logic [0:15] ~GENSYM[v][1]; genvar ~GENSYM[k][18];@@ -1224,7 +974,7 @@ 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(~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]); end ~ENDGENERATE @@ -1281,23 +1031,25 @@ } , { "BlackBox" : { "name" : "GHC.Prim.ctz32#"+ , "kind" : "Declaration" , "type" : "ctz32 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "enc"- , "extension" : "inc"- , "content" :-"function [1:0] ~INCLUDENAME;+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "enc"+ , "extension" : "inc"+ , "template" :+"function [1:0] ~INCLUDENAME[0]; input [1:0] a; case (a)- 2'b00: ~INCLUDENAME = 2'b10;- 2'b01: ~INCLUDENAME = 2'b01;- 2'b10: ~INCLUDENAME = 2'b00;- default: ~INCLUDENAME = 2'b00;+ 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"- }- , "templateD" :+ }+ ]+ , "template" : "// ctz32 begin logic [0:31] ~GENSYM[v][1]; genvar ~GENSYM[k][18];@@ -1311,7 +1063,7 @@ 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(~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]); end ~ENDGENERATE @@ -1384,23 +1136,25 @@ } , { "BlackBox" : { "name" : "GHC.Prim.ctz64#"+ , "kind" : "Declaration" , "type" : "ctz64 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "enc"- , "extension" : "inc"- , "content" :-"function [1:0] ~INCLUDENAME;+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "enc"+ , "extension" : "inc"+ , "template" :+"function [1:0] ~INCLUDENAME[0]; input [1:0] a; case (a)- 2'b00: ~INCLUDENAME = 2'b10;- 2'b01: ~INCLUDENAME = 2'b01;- 2'b10: ~INCLUDENAME = 2'b00;- default: ~INCLUDENAME = 2'b00;+ 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"- }- , "templateD" :+ }+ ]+ , "template" : "// ctz64 begin logic [0:63] ~GENSYM[v][1]; genvar ~GENSYM[k][18];@@ -1414,7 +1168,7 @@ 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(~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]); end ~ENDGENERATE @@ -1503,23 +1257,25 @@ } , { "BlackBox" : { "name" : "GHC.Prim.ctz#"+ , "kind" : "Declaration" , "type" : "ctz :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "enc"- , "extension" : "inc"- , "content" :-"function [1:0] ~INCLUDENAME;+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "enc"+ , "extension" : "inc"+ , "template" :+"function [1:0] ~INCLUDENAME[0]; input [1:0] a; case (a)- 2'b00: ~INCLUDENAME = 2'b10;- 2'b01: ~INCLUDENAME = 2'b01;- 2'b10: ~INCLUDENAME = 2'b00;- default: ~INCLUDENAME = 2'b00;+ 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"- }- , "templateD" :+ }+ ]+ , "template" : "// ctz begin ~IF ~IW64 ~THEN logic [0:63] ~GENSYM[v][1];@@ -1534,7 +1290,7 @@ 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(~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]); end ~ENDGENERATE @@ -1629,7 +1385,7 @@ 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(~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]); end ~ENDGENERATE @@ -1698,117 +1454,6 @@ ~FI assign ~RESULT = $unsigned(~SYM[7]); // ctz end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.byteSwap16#"- , "type" : "byteSwap16# :: Word# -> Word#"- , "templateD" :-"// 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#"- , "type" : "byteSwap32# :: Word# -> Word#"- , "templateD" :-"// 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#"- , "type" : "byteSwap64# :: Word# -> Word#"- , "templateD" :-"// 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#"- , "type" : "byteSwap# :: Word# -> Word#"- , "templateD" :-"// 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#"- , "type" : "narrow8Int# :: Int# -> Int#"- , "templateD" :-"// narrow8Int begin-assign ~RESULT = $signed(~VAR[i][0][7:0]);-// narrow8Int end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.narrow16Int#"- , "type" : "narrow16Int# :: Int# -> Int#"- , "templateD" :-"// narrow16Int begin-assign ~RESULT = $signed(~VAR[i][0][15:0]);-// narrow16Int end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.narrow32Int#"- , "type" : "narrow32Int# :: Int# -> Int#"- , "templateD" :-"// narrow32Int begin-assign ~RESULT = $signed(~VAR[i][0][31:0]);-// narrow32Int end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.narrow8Word#"- , "type" : "narrow8Int# :: Word# -> Word#"- , "templateD" :-"// narrow8Word begin-assign ~RESULT = $unsigned(~VAR[w][0][7:0]);-// narrow8Word end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.narrow16Word#"- , "type" : "narrow16Word# :: Word# -> Word#"- , "templateD" :-"// narrow16Word begin-assign ~RESULT = $unsigned(~VAR[w][0][15:0]);-// narrow16Word end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.narrow32Word#"- , "type" : "narrow32Int# :: Word# -> Word#"- , "templateD" :-"// narrow32Word begin-assign ~RESULT = $unsigned(~VAR[w][0][31:0]);-// narrow32Word end"- }- }-, { "Primitive" :- { "name" : "GHC.Prim.dataToTag#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "GHC.Prim.tagToEnum#"- , "primType" : "Function"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.unsafeCoerce#"- , "type" : "unsafeCoerce# :: a -> b"- , "templateE" : "~ARG[0]" } } ]
− prims/systemverilog/GHC_Types.json
@@ -1,24 +0,0 @@-[ { "Primitive" :- { "name" : "GHC.Types.MkCoercible"- , "primType" : "Constructor"- }- }-, { "BlackBox" :- { "name" : "GHC.Types.C#"- , "type" : "I# :: Char# -> Char"- , "templateE" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Types.I#"- , "type" : "I# :: Int# -> Int"- , "templateE" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Types.W#"- , "type" : "W# :: Word# -> Word"- , "templateE" : "~ARG[0]"- }- }-]
− prims/systemverilog/GHC_Word.json
@@ -1,25 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Word.W8#"- , "type" : "W8# :: Word# -> Word8"- , "templateD" : "assign ~RESULT = $unsigned(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Word.W16#"- , "type" : "W16# :: Word# -> Word16"- , "templateD" : "assign ~RESULT = $unsigned(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Word.W32#"- , "type" : "W32# :: Word# -> Word32"- , "templateD" : "assign ~RESULT = $unsigned(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Word.W64#"- , "type" : "W64# :: Word# -> Word64"- , "templateD" : "assign ~RESULT = $unsigned(~ARG[0]);"- }- }-]
prims/verilog/Clash_Explicit_BlockRam.json view
@@ -1,50 +1,151 @@ [ { "BlackBox" : { "name" : "Clash.Explicit.BlockRam.blockRam#"+ , "kind" : "Declaration" , "type" : "blockRam#- :: HasCallStack -- ARG[0]- => Clock dom gated -- clk, ARG[1]- -> Vec n a -- init, ARG[2]- -> Signal dom Int -- rd, ARG[3]- -> Signal dom Bool -- wren, ARG[4]- -> Signal dom Int -- wr, ARG[5]- -> Signal dom a -- din, ARG[6]+ :: ( 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- , "templateD" :+ , "template" : "// blockRam begin-reg ~TYPO ~GENSYM[RAM][0] [0:~LENGTH[~TYP[2]]-1];+reg ~TYPO ~GENSYM[~RESULT_RAM][1] [0:~LENGTH[~TYP[5]]-1]; -reg ~TYP[2] ~GENSYM[ram_init][2];-integer ~GENSYM[i][3];+reg ~TYP[5] ~GENSYM[ram_init][3];+integer ~GENSYM[i][4]; initial begin- ~SYM[2] = ~ARG[2];- for (~SYM[3]=0; ~SYM[3] < ~LENGTH[~TYP[2]]; ~SYM[3] = ~SYM[3] + 1) begin- ~SYM[0][~LENGTH[~TYP[2]]-1-~SYM[3]] = ~SYM[2][~SYM[3]*~SIZE[~TYPO]+:~SIZE[~TYPO]];+ ~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 ~ISGATED[1] ~THEN-always @(posedge ~ARG[1][1]) begin : ~GENSYM[~COMPNAME_blockRam][4]~IF ~VIVADO ~THEN- if (~ARG[1][0]) begin- if (~ARG[4]) begin- ~SYM[0][~ARG[5]] <= ~ARG[6];+~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[0][~ARG[3]];+ ~RESULT <= ~SYM[1][~ARG[6]]; end~ELSE- if (~ARG[4] & ~ARG[1][0]) begin- ~SYM[0][~ARG[5]] <= ~ARG[6];+ if (~ARG[7] & ~ARG[4]) begin+ ~SYM[1][~ARG[8]] <= ~ARG[9]; end- if (~ARG[1][0]) begin- ~RESULT <= ~SYM[0][~ARG[3]];+ if (~ARG[4]) begin+ ~RESULT <= ~SYM[1][~ARG[6]]; end~FI end~ELSE-always @(posedge ~ARG[1]) begin : ~SYM[4]- if (~ARG[4]) begin- ~SYM[0][~ARG[5]] <= ~ARG[6];+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[0][~ARG[3]];+ ~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_File.json view
@@ -1,44 +1,48 @@ [ { "BlackBox" : { "name" : "Clash.Explicit.BlockRam.File.blockRamFile#"+ , "kind" : "Declaration" , "type" : "blockRamFile#- :: (KnownNat m, HasCallStack)-- (ARG[0],ARG[1])- => Clock dom gated -- clk, ARG[2]- -> SNat n -- sz, ARG[3]- -> FilePath -- file, ARG[4]- -> Signal dom Int -- rd, ARG[5]- -> Signal dom Bool -- wren, ARG[6]- -> Signal dom Int -- wr, ARG[7]- -> Signal dom (BitVector m) -- din, ARG[8]+ :: ( 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- , "templateD" :+ , "template" : "// blockRamFile begin-reg ~TYPO ~GENSYM[RAM][0] [0:~LIT[3]-1];+reg ~TYPO ~GENSYM[RAM][1] [0:~LIT[5]-1]; initial begin- $readmemb(~FILE[~LIT[4]],~SYM[0]);+ $readmemb(~FILE[~LIT[6]],~SYM[1]); end-~IF ~ISGATED[2] ~THEN-always @(posedge ~ARG[2][1]) begin : ~GENSYM[~COMPNAME_blockRamFile][2]~IF ~VIVADO ~THEN- if (~ARG[2][0]) begin- if (~ARG[6]) begin- ~SYM[0][~ARG[7]] <= ~ARG[8];+~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[0][~ARG[5]];+ ~RESULT <= ~SYM[1][~ARG[7]]; end~ELSE- if (~ARG[6] & ~ARG[2][0]) begin- ~SYM[0][~ARG[7]] <= ~ARG[8];+ if (~ARG[8] & ~ARG[4]) begin+ ~SYM[1][~ARG[9]] <= ~ARG[10]; end- if (~ARG[2][0]) begin- ~RESULT <= ~SYM[0][~ARG[5]];+ if (~ARG[4]) begin+ ~RESULT <= ~SYM[1][~ARG[7]]; end~FI end~ELSE-always @(posedge ~ARG[2]) begin : ~SYM[2]- if (~ARG[6]) begin- ~SYM[0][~ARG[7]] <= ~ARG[8];+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[0][~ARG[5]];+ ~RESULT <= ~SYM[1][~ARG[7]]; end~FI // blockRamFile end" }
prims/verilog/Clash_Explicit_DDR.json view
@@ -1,67 +1,46 @@ [ { "BlackBox" : { "name" : "Clash.Explicit.DDR.ddrIn#"+ , "kind" : "Declaration" , "type" : "ddrIn# :: forall a slow fast n pFast gated synchronous.- ( HasCallStack -- ARG[0]- , fast ~ Dom n pFast -- ARG[1]- , slow ~ Dom n (2*pFast)) -- ARG[2]- => Clock slow gated -- ARG[3]- -> Reset slow synchronous -- ARG[4]- -> a -- ARG[5]- -> a -- ARG[6]- -> a -- ARG[7]- -> Signal fast a -- ARG[8]+ ( 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)"- , "templateD" :+ , "template" : "// ddrIn begin-reg ~SIGD[~GENSYM[data_Pos][1]][8];-reg ~SIGD[~GENSYM[data_Neg][2]][8];-reg ~SIGD[~GENSYM[data_Neg_Latch][3]][8];-~IF ~ISGATED[3] ~THEN-always @(posedge ~ARG[3][1]~IF ~ISSYNC[4] ~THEN ~ELSE or posedge ~ARG[4]~FI) begin : ~GENSYM[~COMPNAME_ddrIn_pos][6]- if (~ARG[4]) begin- ~SYM[1] <= ~ARG[6];- end else if (~ARG[3][0]) begin- ~SYM[1] <= ~ARG[8];- end-end~ELSE-always @(posedge ~ARG[3]~IF ~ISSYNC[4] ~THEN ~ELSE or posedge ~ARG[4]~FI) begin : ~SYM[6]- if (~ARG[4]) begin- ~SYM[1] <= ~ARG[6];- end else 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-end~FI-~IF ~ISGATED[3] ~THEN-always @(negedge ~ARG[3][1]~IF ~ISSYNC[4] ~THEN ~ELSE or posedge ~ARG[4]~FI) begin : ~GENSYM[~COMPNAME_ddrIn_neg][7]- if (~ARG[4]) begin- ~SYM[2] <= ~ARG[7];- end else if (~ARG[3][0]) begin- ~SYM[2] <= ~ARG[8];- end-end~ELSE-always @(negedge ~ARG[3]~IF ~ISSYNC[4] ~THEN ~ELSE or posedge ~ARG[4]~FI) begin : ~SYM[7]- if (~ARG[4]) begin- ~SYM[2] <= ~ARG[7];- end else begin- ~SYM[2] <= ~ARG[8];+ end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin+ ~SYM[1] <= ~ARG[10]; end-end~FI-~IF ~ISGATED[3] ~THEN-always @(posedge ~ARG[3][1]~IF ~ISSYNC[4] ~THEN ~ELSE or posedge ~ARG[4]~FI) begin : ~GENSYM[~COMPNAME_ddrIn_neg_latch][8]- if (~ARG[4]) begin- ~SYM[3] <= ~ARG[5];- end else if (~ARG[3][0]) begin- ~SYM[3] <= ~SYM[2];+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~ELSE-always @(posedge ~ARG[3]~IF ~ISSYNC[4] ~THEN ~ELSE or posedge ~ARG[4]~FI) begin : ~SYM[8]- if (~ARG[4]) begin- ~SYM[3] <= ~ARG[5];- end else begin+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~FI+end assign ~RESULT = {~SYM[3], ~SYM[1]}; // ddrIn end"@@ -69,62 +48,40 @@ } , { "BlackBox" : { "name" : "Clash.Explicit.DDR.ddrOut#"+ , "kind" : "Declaration" , "type" : "ddrOut# :: ( HasCallStack -- ARG[0]- , fast ~ Dom n pFast -- ARG[1]- , slow ~ Dom n (2*pFast)) -- ARG[2]- => Clock slow gated -- ARG[3]- -> Reset slow synchronous -- ARG[4]- -> a -- ARG[5]- -> Signal slow a -- ARG[6]- -> Signal slow a -- ARG[7]+ , 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"- , "templateD" :+ , "template" : "// ddrOut begin-reg ~SIGD[~GENSYM[data_Pos][1]][5];-reg ~SIGD[~GENSYM[data_Neg][2]][5];-reg ~SIGD[~GENSYM[data_Out][3]][5];-~IF ~ISGATED[3] ~THEN-always @(posedge ~ARG[3][1]~IF ~ISSYNC[4] ~THEN ~ELSE or posedge ~ARG[4]~FI) begin : ~GENSYM[~COMPNAME_ddrOut_pos][5]- if (~ARG[4]) begin- ~SYM[1] <= ~ARG[5];- end else if (~ARG[3][0]) begin- ~SYM[1] <= ~ARG[6];- end-end~ELSE-always @(posedge ~ARG[3]~IF ~ISSYNC[4] ~THEN ~ELSE or posedge ~ARG[4]~FI) begin : ~SYM[5]- if (~ARG[4]) begin- ~SYM[1] <= ~ARG[5];- end else begin- ~SYM[1] <= ~ARG[6];- end-end~FI-~IF ~ISGATED[3] ~THEN-always @(posedge ~ARG[3][1]~IF ~ISSYNC[4] ~THEN ~ELSE or posedge ~ARG[4]~FI) begin : ~GENSYM[~COMPNAME_ddrOut_neg][6]- if (~ARG[4]) begin- ~SYM[2] <= ~ARG[5];- end else if (~ARG[3][0]) begin- ~SYM[2] <= ~ARG[7];+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~ELSE-always @(posedge ~ARG[3]~IF ~ISSYNC[4] ~THEN ~ELSE or posedge ~ARG[4]~FI) begin : ~SYM[6]- if (~ARG[4]) begin- ~SYM[2] <= ~ARG[5];- end else begin+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-end~FI--always @(*) begin ~IF ~ISGATED[3] ~THEN- if (~ARG[3][1]) begin~ELSE- if (~ARG[3]) begin~FI- ~SYM[3] = ~SYM[1];- end else begin- ~SYM[3] = ~SYM[2];+ end else ~IF ~ISACTIVEENABLE[6] ~THEN if (~ARG[6]) ~ELSE ~FI begin+ ~SYM[2] <= ~ARG[9]; end end -assign ~RESULT = ~SYM[3];+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.json view
@@ -1,32 +1,30 @@ [ { "BlackBox" : { "name" : "Clash.Explicit.RAM.asyncRam#"+ , "kind" : "Declaration" , "type" : "asyncRam#- :: HasCallStack -- ARG[0]- => Clock wdom wgated -- ^ wclk, ARG[1]- -> Clock rdom rgated -- ^ rclk, ARG[2]- -> SNat n -- ^ sz, ARG[3]- -> Signal rdom Int -- ^ rd, ARG[4]- -> Signal wdom Bool -- ^ en, ARG[5]- -> Signal wdom Int -- ^ wr, ARG[6]- -> Signal wdom a -- ^ din, ARG[7]+ :: ( 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"- , "templateD" :+ , "template" : "// asyncRam begin-reg ~TYPO ~GENSYM[RAM][0] [0:~LIT[3]-1];-~IF ~ISGATED[1] ~THEN-always @(posedge ~ARG[1][1]) begin : ~GENSYM[~COMPNAME_Ram][1]- if (~ARG[5] & ~ARG[1][0]) begin- ~SYM[0][~ARG[6]] <= ~ARG[7];- end-end~ELSE-always @(posedge ~ARG[1]) begin : ~SYM[1]- if (~ARG[5]) begin- ~SYM[0][~ARG[6]] <= ~ARG[7];+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~FI+end -assign ~RESULT = ~SYM[0][~ARG[4]];+assign ~RESULT = ~SYM[0][~ARG[7]]; // asyncRam end" } }
prims/verilog/Clash_Explicit_ROM.json view
@@ -1,32 +1,36 @@ [ { "BlackBox" : { "name" : "Clash.Explicit.ROM.rom#"+ , "kind" : "Declaration" , "type" :-"rom# :: KnownNat n -- ARG[0]- => Clock dom gated -- clk, ARG[1]- -> Vec n a -- init, ARG[2]- -> Signal dom Int -- rd, ARG[3]+"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- , "templateD" :+ , "template" : "// rom begin-reg ~TYPO ~GENSYM[ROM][0] [0:~LIT[0]-1];+reg ~TYPO ~GENSYM[ROM][1] [0:~LIT[1]-1]; -reg ~TYP[2] ~GENSYM[rom_init][2];-integer ~GENSYM[i][3];+reg ~TYP[5] ~GENSYM[rom_init][3];+integer ~GENSYM[i][4]; initial begin- ~SYM[2] = ~ARG[2];- for (~SYM[3]=0; ~SYM[3] < ~LIT[0]; ~SYM[3] = ~SYM[3] + 1) begin- ~SYM[0][~LIT[0]-1-~SYM[3]] = ~SYM[2][~SYM[3]*~SIZE[~TYPO]+:~SIZE[~TYPO]];+ ~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 ~ISGATED[1] ~THEN-always @(posedge ~ARG[1][1]) begin : ~GENSYM[~COMPNAME_rom][4]- if (~ARG[1][0]) begin- ~RESULT <= ~SYM[0][~ARG[3]];+~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 @(posedge ~ARG[1]) begin : ~SYM[4]- ~RESULT <= ~SYM[0][~ARG[3]];+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_File.json view
@@ -1,28 +1,31 @@ [ { "BlackBox" : { "name" : "Clash.Explicit.ROM.File.romFile#"+ , "kind" : "Declaration" , "type" :-"romFile# :: KnownNat m -- ARG[0]- => Clock dom gated -- clk, ARG[1]- -> SNat n -- sz, ARG[2]- -> FilePath -- file, ARG[3]- -> Signal dom Int -- rd, ARG[4]+"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- , "templateD" :+ , "template" : "// romFile begin-reg ~TYPO ~GENSYM[ROM][0] [0:~LIT[2]-1];+reg ~TYPO ~GENSYM[ROM][0] [0:~LIT[4]-1]; initial begin- $readmemb(~FILE[~LIT[3]],~SYM[0]);+ $readmemb(~FILE[~LIT[5]],~SYM[0]); end-~IF ~ISGATED[1] ~THEN-always @(posedge ~ARG[1][1]) begin : ~GENSYM[~COMPNAME_romFile][2]- if (~ARG[1][0]) begin- ~RESULT <= ~SYM[0][~ARG[4]];+~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 @(posedge ~ARG[1]) begin : ~SYM[2]- ~RESULT <= ~SYM[0][~ARG[4]];+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.json view
@@ -1,27 +1,60 @@ [ { "BlackBox" : { "name" : "Clash.Explicit.Testbench.assert"+ , "kind" : "Declaration" , "type" : "assert- :: (Eq a,ShowX a) -- (ARG[0],ARG[1])- => Clock domain gated -- ARG[2]- -> Reset domain synchronous -- ARG[3]- -> String -- ARG[4]- -> Signal domain a -- Checked value (ARG[5])- -> Signal domain a -- Expected value (ARG[6])- -> Signal domain b -- Return valued (ARG[7])- -> Signal domain b"- , "templateD" :+ :: (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 @(posedge ~IF ~ISGATED[2] ~THEN ~ARG[2][1] ~ELSE ~ARG[2] ~FI~IF ~ISSYNC[3] ~THEN ~ELSE or negedge ~ARG[3]~FI) begin- if (~ARG[5] !== ~ARG[6]) begin+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];-// assert end"+// assertBitVector end" } } ]
− prims/verilog/Clash_Intel_ClockGen.json
@@ -1,37 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Intel.ClockGen.altpll"- , "type" :-"altpll- :: SSymbol name -- ARG[0]- -> Clock pllIn 'Source -- ARG[1]- -> Reset pllIn 'Asynchronous -- ARG[2]- -> (Clock pllOut 'Source, Signal pllOut Bool)"- , "templateD" :-"// altpll begin-~NAME[0] ~GENSYM[altpll_inst][2]-(.inclk0 (~ARG[1])-,.areset (~ARG[2])-,.c0 (~RESULT[1])-,.locked (~RESULT[0]));-// altpll end"- }- }-, { "BlackBox" :- { "name" : "Clash.Intel.ClockGen.alteraPll"- , "type" :-"alteraPll- :: SSymbol name -- ARG[0]- -> Clock pllIn 'Source -- ARG[1]- -> Reset pllIn 'Asynchronous -- ARG[2]- -> (Clock pllOut 'Source, Signal pllOut Bool)"- , "templateD" :-"// alteraPll begin-~NAME[0] ~GENSYM[alteraPll_inst][2]-(.refclk (~ARG[1])-,.rst (~ARG[2])-,.outclk_0 (~RESULT[1])-,.locked (~RESULT[0]));-// alteraPll end"- }- }-]
prims/verilog/Clash_Intel_DDR.json view
@@ -1,89 +1,48 @@ [ { "BlackBox" : { "name" : "Clash.Intel.DDR.altddioIn"+ , "kind" : "Declaration" , "type" : "altddioIn :: ( HasCallStack -- ARG[0]- , fast ~ Dom n pFast -- ARG[1]- , slow ~ Dom n (2*pFast) -- ARG[2]+ , KnownConfi~ fast domf -- ARG[1]+ , KnownConfi~ slow doms -- ARG[2] , KnownNat m ) -- ARG[3] => SSymbol deviceFamily -- ARG[4]- -> Clock slow gated -- ARG[5]- -> Reset slow synchronous -- ARG[6]- -> Signal fast (BitVector m) -- ARG[7]+ -> Clock slow -- ARG[5]+ -> Reset slow -- ARG[6]+ -> Enable slow -- ARG[7]+ -> Signal fast (BitVector m) -- ARG[8] -> Signal slow (BitVector m,BitVector m)"- , "templateD" :+ , "libraries" : ["altera_mf"]+ , "template" : "// altddioIn begin-wire ~SIGD[~GENSYM[dataout_l][1]][7];-wire ~SIGD[~GENSYM[dataout_h][2]][7];--altddio_in ~GENSYM[~COMPNAME_ALTDDIO_IN][7] (~IF ~ISSYNC[6] ~THEN- .sclr (~ARG[6]),- .aclr (1'b0),~ELSE- .aclr (~ARG[6]),- .sclr (1'b0),~FI- .datain (~ARG[7]),~IF ~ISGATED[5] ~THEN- .inclock (~ARG[5][1]),- .inclocken (~ARG[5][0]),~ELSE- .inclock (~ARG[5]),- .inclocken (1'b1),~FI- .dataout_h (~SYM[2]),- .dataout_l (~SYM[1]),- .aset (1'b0),- .sset (1'b0));-defparam- ~SYM[7].intended_device_family = ~LIT[4],- ~SYM[7].invert_input_clocks = \"OFF\",- ~SYM[7].lpm_hint = \"UNUSED\",- ~SYM[7].lpm_type = \"altddio_in\",- ~SYM[7].power_up_high = \"OFF\",- ~SYM[7].width = ~SIZE[~TYP[7]];+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"- }- }-, { "BlackBox" :- { "name" : "Clash.Intel.DDR.altddioOut#"- , "type" :-"altddioOut#- :: ( HasCallStack -- ARG[0]- , fast ~ Dom n pFast -- ARG[1]- , slow ~ Dom n (2*pFast) -- ARG[2]- , KnownNat m ) -- ARG[3]- => SSymbol deviceFamily -- ARG[4]- -> Clock slow gated -- ARG[5]- -> Reset slow synchronous -- ARG[6]- -> Signal slow (BitVector m) -- ARG[7]- -> Signal slow (BitVector m) -- ARG[8]- -> Signal fast (BitVector m)"- , "templateD" :-"// altddioOut begin-altddio_out ~GENSYM[~COMPNAME_ALTDDIO_OUT][7] (~IF ~ISSYNC[6] ~THEN- .sclr (~ARG[6]),- .aclr (1'b0),~ELSE- .aclr (~ARG[6]),- .sclr (1'b0),~FI- .datain_h (~ARG[7]),- .datain_l (~ARG[8]),~IF ~ISGATED[5] ~THEN- .outclock (~ARG[5][1]),- .outclocken (~ARG[5][0]),~ELSE- .outclock (~ARG[5]),- .outclocken (1'b1),~FI- .dataout (~RESULT),- .aset (1'b0),- .sset (1'b0),- .oe (1'b1),- .oe_out ());-defparam- ~SYM[7].extend_oe_disable = \"OFF\",- ~SYM[7].intended_device_family = ~LIT[4],- ~SYM[7].invert_output = \"OFF\",- ~SYM[7].lpm_hint = \"UNUSED\",- ~SYM[7].lpm_type = \"altddio_out\",- ~SYM[7].oe_reg = \"UNREGISTERED\",- ~SYM[7].power_up_high = \"OFF\",- ~SYM[7].width = ~SIZE[~TYPO];-// altddioOut end" } } ]
prims/verilog/Clash_Prelude_ROM.json view
@@ -1,16 +1,17 @@ [ { "BlackBox" : { "name" : "Clash.Prelude.ROM.asyncRom#"+ , "kind" : "Declaration" , "type" : "asyncRom# :: KnownNat n -- ^ ARG[0] => Vec n a -- ^ ARG[1] -> Int -- ^ ARG[2] -> a"- , "templateD" :+ , "template" : "// asyncRom begin wire ~TYPO ~GENSYM[ROM][0] [0:~LIT[0]-1]; wire ~TYP[1] ~GENSYM[romflat][1];-assign ~SYM[1] = ~ARG[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]
prims/verilog/Clash_Prelude_ROM_File.json view
@@ -1,12 +1,13 @@ [ { "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"- , "templateD" :+ , "template" : "// asyncRomFile begin reg ~TYPO ~GENSYM[ROM][0] [0:~LIT[1]-1];
+ prims/verilog/Clash_Signal_BiSignal.json view
@@ -0,0 +1,34 @@+[ { "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",+ "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_Internal.json view
@@ -1,85 +1,76 @@ [ { "BlackBox" : { "name" : "Clash.Signal.Internal.delay#"+ , "kind" : "Declaration" , "type" : "delay#- :: HasCallStack -- ARG[0]- => Clock domain gated -- ARG[1]- -> Signal clk a -- ARG[2]+ :: ( 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- , "templateD" :-"// delay begin~IF ~ISGATED[1] ~THEN-always @(posedge ~ARG[1][1]) begin : ~GENSYM[~COMPNAME_delay][1]- if (~ARG[1][0]) begin- ~RESULT <= ~ARG[2];+ , "template" :+"// delay begin,+reg ~TYPO ~GENSYM[~RESULT_reg][0] ~IF ~ISINITDEFINED[0] ~THEN = ~CONST[4] ~ELSE ~FI;~IF ~ISACTIVEENABLE[3] ~THEN+always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[2]) begin : ~GENSYM[~RESULT_delay][1]+ if (~ARG[3]) begin+ ~SYM[0] <= ~ARG[5]; end end~ELSE-always @(posedge ~ARG[1]) begin : ~SYM[1]- ~RESULT <= ~ARG[2];+always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[2]) begin : ~SYM[1]+ ~SYM[0] <= ~ARG[5]; end~FI+assign ~RESULT = ~SYM[0]; // delay end" } } , { "BlackBox" : { "name" : "Clash.Signal.Internal.register#"+ , "kind" : "Declaration" , "type" : "register#- :: HasCallStack -- ARG[0]- => Clock domain gated -- ARG[1]- -> Reset domain synchronous -- ARG[2]- -> a -- ARG[3]- -> Signal clk a -- ARG[4]+ :: ( 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- , "templateD" :-"// register begin~IF ~ISGATED[1] ~THEN-always @(posedge ~ARG[1][1]~IF ~ISSYNC[2] ~THEN ~ELSE or posedge ~ARG[2]~FI) begin : ~GENSYM[~COMPNAME_register][1]- if (~ARG[2]) begin- ~RESULT <= ~ARG[3];- end else if (~ARG[1][0]) begin- ~RESULT <= ~ARG[4];- end-end~ELSE-always @(posedge ~ARG[1]~IF ~ISSYNC[2] ~THEN ~ELSE or posedge ~ARG[2]~FI) begin : ~SYM[1]- if (~ARG[2]) begin- ~RESULT <= ~ARG[3];- end else begin- ~RESULT <= ~ARG[4];+ , "template" :+"// register begin+reg ~TYPO ~GENSYM[~RESULT_reg][0] ~IF ~ISINITDEFINED[0] ~THEN = ~CONST[5] ~ELSE ~FI;+always @(~IF~ACTIVEEDGE[Rising][0]~THENposedge~ELSEnegedge~FI ~ARG[2]~IF ~ISSYNC[0] ~THEN ~ELSE or ~IF ~ISACTIVEHIGH[0] ~THEN posedge ~ELSE negedge ~FI ~ARG[3]~FI) begin : ~GENSYM[~RESULT_register][1]+ if (~IF ~ISACTIVEHIGH[0] ~THEN ~ELSE ! ~FI~ARG[3]) begin+ ~SYM[0] <= ~CONST[6];+ end else ~IF ~ISACTIVEENABLE[4] ~THEN if (~ARG[4]) ~ELSE ~FI begin+ ~SYM[0] <= ~ARG[7]; end-end~FI+end+assign ~RESULT = ~SYM[0]; // register end" } } , { "BlackBox" :- { "name" : "Clash.Signal.Internal.clockGate"- , "type" :-"clockGate- :: Clock domain gated -- ARG[0]- -> Signal domain Bool -- ARG[1]- -> Clcok domain 'Gated"- , "templateD" :-"// clockGate begin ~IF ~ISGATED[0] ~THEN-assign ~RESULT = {~ARG[0][1],~ARG[0][0] & ~ARG[1]};~ELSE-assign ~RESULT = {~ARG[0],~ARG[1]};~FI-// clockGate end"- }- }-, { "BlackBox" : { "name" : "Clash.Signal.Internal.clockGen"+ , "workInfo" : "Always"+ , "kind" : "Declaration"+ , "warning" : "Clash.Signal.Internal.clockGen is not synthesizable!" , "type" : "clockGen- :: (domain ~ Dom nm period -- ARG[0]- ,KnownSymbol nm -- ARG[1]- ,KnownNat period) -- ARG[2]- => Clock domain Source"- , "templateD" :-"// pragma translate_off+ :: 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] = (~LIT[2]0 / 2);+localparam ~GENSYM[half_period][1] = (~PERIOD[0]0 / 2); always begin- ~SYM[0] = 0;- #3000 forever begin+ ~SYM[0] = ~IF~ACTIVEEDGE[Rising][0]~THEN 0 ~ELSE 1 ~FI;+ #30000 forever begin ~SYM[0] = ~ ~SYM[0]; #~SYM[1]; ~SYM[0] = ~ ~SYM[0];@@ -87,27 +78,30 @@ end end assign ~RESULT = ~SYM[0];-// pragma translate_on"+// pragma translate_on+// clockGen end" } } , { "BlackBox" :- { "name" : "Clash.Signal.Internal.tbClockGen"+ { "name" : "Clash.Explicit.Testbench.tbClockGen"+ , "workInfo" : "Always"+ , "kind" : "Declaration"+ , "warning" : "Clash.Signal.Internal.tbClockGen is not synthesizable!" , "type" : "tbClockGen- :: (domain ~ Dom nm period -- ARG[0]- ,KnownSymbol nm -- ARG[1]- ,KnownNat period) -- ARG[2]- => Signal domain Bool -- ARG[3]- -> Clock domain Source"- , "templateD" :-"// pragma translate_off+ :: 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] = (~LIT[2]0 / 2);+localparam ~GENSYM[half_period][1] = (~PERIOD[0]0 / 2); always begin- ~SYM[0] = 0;- #3000 forever begin- if (~ ~ARG[3]) begin+ ~SYM[0] = ~IF~ACTIVEEDGE[Rising][0]~THEN 0 ~ELSE 1 ~FI;+ #30000 forever begin+ if (~ ~ARG[1]) begin $finish; end ~SYM[0] = ~ ~SYM[0];@@ -117,96 +111,35 @@ end end assign ~RESULT = ~SYM[0];-// pragma translate_on"+// pragma translate_on+// tbClockGen end" } } , { "BlackBox" :- { "name" : "Clash.Signal.Internal.asyncResetGen"- , "type" :-"asyncResetGen :: Reset domain 'Asynchronous"- , "templateD" :-"// pragma translate_off+ { "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] = 1;- #1999 ~SYM[0] = 0;+ #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];-// pragma translate_on"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.syncResetGen"- , "type" :-"asyncResetGen :: Reset domain 'Synchronous"- , "templateD" :-"// pragma translate_off-reg ~TYPO ~GENSYM[rst][0];-localparam ~GENSYM[reset_period][1] = 2998 + ~LIT[1]0;+assign ~RESULT = ~SYM[0];~ELSE+reg ~TYPO ~SYM[0];+localparam ~SYM[1] = 30001 + ((~LIT[2] - 1) * ~PERIOD[0]0); initial begin- #1 ~SYM[0] = 1;- #~SYM[1] ~SYM[0] = 0;+ #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];-// pragma translate_on"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.unsafeFromAsyncReset"- , "type" :-"unsafeFromAsyncReset :: Reset domain Asynchronous -> Signal domain Bool"- , "templateE" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.unsafeToAsyncReset"- , "type" :-"unsafeToAsyncReset :: Signal domain Bool -> Reset domain Asynchronous"- , "templateE" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.fromSyncReset"- , "type" :-"fromSyncReset :: Reset domain Synchronous -> Signal domain Bool"- , "templateE" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.unsafeToSyncReset"- , "type" :-"unsafeToSyncReset :: Signal domain Bool -> Reset domain Synchronous"- , "templateE" : "~ARG[0]"- }- }-, { "Primitive" :- { "name" : "Clash.Signal.Internal.signal#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Signal.Internal.mapSignal#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Signal.Internal.appSignal#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Signal.Internal.foldr#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Signal.Internal.traverse#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Signal.Internal.joinSignal#"- , "primType" : "Function"+assign ~RESULT = ~SYM[0]; ~FI+// pragma translate_on+// resetGen end" } } ]
prims/verilog/Clash_Sized_Internal_BitVector.json view
@@ -1,33 +1,6 @@ [ { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.size#"- , "type" : "size# :: KnownNat n => BitVector n -> Int"- , "templateE" : "~SIZE[~TYPO]'sd~LIT[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.maxIndex#"- , "type" : "maxIndex# :: KnownNat n => BitVector n -> Int"- , "templateE" : "~SIZE[~TYPO]'sd~LIT[0] - ~SIZE[~TYPO]'sd1"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.++#"- , "type" : "(++#) :: KnownNat m => BitVector n -> BitVector m -> BitVector (n + m)"- , "templateE" : "{~ARG[1],~ARG[2]}"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.index#"- , "type" :-"index# :: KnownNat n -- ARG[0]- => BitVector n -- ARG[1]- -> Int -- ARG[2]- -> Bit"- , "templateE" : "~VAR[bv][1][~ARG[2]]"- }- }-, { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.replaceBit#"+ , "kind" : "Declaration" , "type" : "replaceBit# :: KnownNat n -- ARG[0] => BitVector n -- ARG[1]@@ -35,7 +8,7 @@ -> Bit -- ARG[3] -> BitVector n" , "outputReg" : true- , "templateD" :+ , "template" : "// replaceBit start always @(*) begin ~RESULT = ~ARG[1];@@ -46,6 +19,8 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.setSlice#"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "setSlice# :: BitVector (m + 1 + i) -- ARG[0] -> SNat m -- ARG[1]@@ -53,7 +28,7 @@ -> BitVector (m + 1 - n) -- ARG[3] -> BitVector (m + 1 + i)" , "outputReg" : true- , "templateD" :+ , "template" : "// setSlice begin always @(*) begin ~RESULT = ~ARG[0];@@ -63,175 +38,37 @@ } } , { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.slice#"- , "type" :-"slice# :: BitVector (m + 1 + i) -- ARG[0]- -> SNat m -- ARG[1]- -> SNat n -- ARG[2]- -> BitVector (m + 1 - n)"- , "templateE" : "~VAR[bv][0][~LIT[1] : ~LIT[2]]"- }- }-, { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.split#"+ , "kind" : "Expression" , "type" : "split# :: KnownNat n -- ARG[0] => BitVector (m + n) -- ARG[1] -> (BitVector m, BitVector n)"- , "templateE" : "~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.msb#"- , "type" :-"msb# :: KnownNat n -- ARG[0]- => BitVector n -- ARG[1]- -> Bit"- , "templateE" : "~IF ~LIT[0] ~THEN ~VAR[bv][1][~LIT[0]-1] ~ELSE 1'b0 ~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.lsb#"- , "type" :-"lsb# :: BitVector n -- ARG[0]- -> Bit"- , "templateE" : "~IF ~SIZE[~TYP[0]] ~THEN ~VAR[bv][0][0] ~ELSE 1'b0 ~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.minBound#"- , "type" : "minBound# :: BitVector n"- , "templateE" : "~SIZE[~TYPO]'d0"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.maxBound#"- , "type" : "maxBound# :: KnownNat n => BitVector n"- , "templateE" : "{~LIT[0] {1'b1}}"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.+#"- , "type" : "(+#) :: KnownNat n => BitVector n -> BitVector n -> BitVector n"- , "templateE" : "~ARG[1] + ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.-#"- , "type" : "(-#) :: KnownNat n => BitVector n -> BitVector n -> BitVector n"- , "templateE" : "~ARG[1] - ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.*#"- , "type" : "(*#) :: KnownNat n => BitVector n -> BitVector n -> BitVector n"- , "templateE" : "~ARG[1] * ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.negate#"- , "type" : "negate# :: KnownNat n => BitVector n -> BitVector n"- , "templateE" : "-~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.fromInteger#"- , "type" : "fromInteger# :: KnownNat n => Integer -> BitVector n"- , "templateE" : "$unsigned(~ARG[1][(~LIT[0]-1):0])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.plus#"- , "type" : "plus# :: BitVector m -> BitVector n -> BitVector (Max m n + 1)"- , "templateD" : "assign ~RESULT = ~ARG[0] + ~ARG[1];"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.minus#"- , "type" : "minus# :: (KnownNat m, KnownNat n) => BitVector m -> BitVector n -> BitVector (Max m n + 1)"- , "templateD" : "assign ~RESULT = ~ARG[2] - ~ARG[3];"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.times#"- , "type" : "times# :: KnownNat (m + n) => BitVector m -> BitVector n -> BitVector (m + n)"- , "templateD" : "assign ~RESULT = ~ARG[0] * ~ARG[1];"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.quot#"- , "type" : "quot# :: BitVector n -> BitVector n -> BitVector n"- , "templateE" : "~ARG[0] / ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.rem#"- , "type" : "rem# :: BitVector n -> BitVector n -> BitVector n"- , "templateE" : "~ARG[0] % ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.and#"- , "type" : "and# :: BitVector n -> BitVector n -> BitVector n"- , "templateE" : "~ARG[0] & ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.or#"- , "type" : "or# :: BitVector n -> BitVector n -> BitVector n"- , "templateE" : "~ARG[0] | ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.xor#"- , "type" : "xor# :: BitVector n -> BitVector n -> BitVector n"- , "templateE" : "~ARG[0] ^ ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.complement#"- , "type" : "complement# :: KnownNat n => BitVector n -> BitVector n"- , "templateE" : "~ ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.shiftL#"- , "type" : "shiftL# :: KnownNat n => BitVector n -> Int -> BitVector n"- , "templateE" : "~ARG[1] << ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.shiftR#"- , "type" : "shiftR# :: KnownNat n => BitVector n -> Int -> BitVector n"- , "templateE" : "~ARG[1] >> ~ARG[2]"+ , "template" : "~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.rotateL#"+ , "kind" : "Declaration" , "type" : "rotateL# :: KnownNat n => BitVector n -> Int -> BitVector n"- , "templateD" :+ , "template" : "// rotateL begin-wire [2*~LIT[0]-1:0] ~SYM[0];-assign ~SYM[0] = {~ARG[1],~ARG[1]} << ~ARG[2];-assign ~RESULT = ~SYM[0][2*~LIT[0]-1 : ~LIT[0]];+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"- , "templateD" :+ , "template" : "// rotateR begin-wire [2*~LIT[0]-1:0] ~GENSYM[bv][0];-assign ~SYM[0] = {~ARG[1],~ARG[1]} >> ~ARG[2];-assign ~RESULT = ~SYM[0][~LIT[0]-1 : 0];+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"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.resize#"- , "type" : "resize# :: KnownNat m => BitVector n -> BitVector m"- , "templateD" : "assign ~RESULT = $unsigned(~ARG[1]);" } } ]
prims/verilog/Clash_Sized_Internal_Signed.json view
@@ -1,105 +1,8 @@ [ { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.size#"- , "type" : "size# :: KnownNat n => Signed n -> Int"- , "templateE" : "~SIZE[~TYPO]'sd~LIT[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.pack#"- , "type" : "pack# :: KnownNat n => Signed n -> BitVector n"- , "templateE" : "$unsigned(~ARG[1])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.unpack#"- , "type" : "unpack# :: KnownNat n => BitVector n -> Signed n"- , "templateE" : "$signed(~ARG[1])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.minBound#"- , "type" : "minBound# :: KnownNat n => Signed n"- , "comment" : "Generates incorrect SV for n=0"- , "templateE" : "$signed({1'b1, {(~LIT[0]-1) {1'b0}}})"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.maxBound#"- , "type" : "maxBound# :: KnownNat n => Signed n"- , "comment" : "Generates incorrect SV for n=0"- , "templateE" : "$signed({1'b0, {(~LIT[0]-1) {1'b1}}})"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.+#"- , "type" : "(+#) :: KnownNat n => Signed n -> Signed n -> Signed n"- , "templateE" : "~ARG[1] + ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.-#"- , "type" : "(-#) :: KnownNat n => Signed n -> Signed n -> Signed n"- , "templateE" : "~ARG[1] - ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.*#"- , "type" : "(*#) :: KnownNat n => Signed n -> Signed n -> Signed n"- , "templateE" : "~ARG[1] * ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.negate#"- , "type" : "negate# :: KnownNat n => Signed n -> Signed n"- , "templateE" : "-~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.abs#"- , "type" : "abs# :: KnownNat n => Signed n -> Signed n"- , "templateE" : "(~ARG[1] < ~LIT[0]'sd0) ? -~ARG[1] : ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.fromInteger#"- , "type" : "fromInteger# :: KnownNat n => Integer -> Signed (n :: Nat)"- , "templateE" : "$signed(~ARG[1][(~LIT[0]-1):0])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.plus#"- , "type" : "plus# :: Signed m -> Signed n -> Signed (1 + Max m n)"- , "templateD" : "assign ~RESULT = ~ARG[0] + ~ARG[1];"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.minus#"- , "type" : "minus# :: Signed m -> Signed n -> Signed (1 + Max m n)"- , "templateD" : "assign ~RESULT = ~ARG[0] - ~ARG[1];"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.times#"- , "type" : "times# :: Signed m -> Signed n -> Signed (m + n)"- , "templateD" : "assign ~RESULT = ~ARG[0] * ~ARG[1];"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.quot#"- , "type" : "quot# :: Signed n -> Signed n -> Signed n"- , "templateE" : "~ARG[0] / ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.rem#"- , "type" : "rem# :: Signed n -> Signed n -> Signed n"- , "templateE" : "~ARG[0] % ~ARG[1]"- }- }-, { "BlackBox" : { "name" : "Clash.Sized.Internal.Signed.div#"+ , "kind" : "Declaration" , "type" : "div# :: Signed n -> Signed n -> Signed n"- , "templateD" :+ , "template" : "// divSigned begin // divide (rounds towards zero) wire ~SIGD[~GENSYM[quot_res][0]][1];@@ -112,8 +15,9 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Signed.mod#"+ , "kind" : "Declaration" , "type" : "mod# :: Signed n -> Signed n -> Signed n"- , "templateD" :+ , "template" : "// modSigned begin // remainder ~SIGD[~GENSYM[rem_res][0]][0];@@ -127,85 +31,27 @@ } } , { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.and#"- , "type" : "and# :: KnownNat n => Signed n -> Signed n -> Signed n"- , "templateE" : "~ARG[1] & ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.or#"- , "type" : "or# :: KnownNat n => Signed n -> Signed n -> Signed n"- , "templateE" : "~ARG[1] | ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.xor#"- , "type" : "xor# :: KnownNat n => Signed n -> Signed n -> Signed n"- , "templateE" : "~ARG[1] ^ ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.complement#"- , "type" : "complement# :: KnownNat n => Signed n -> Signed n"- , "templateE" : "~ ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.shiftL#"- , "type" : "shiftL# :: KnownNat n => Signed n -> Int -> Signed n"- , "templateE" : "~ARG[1] <<< ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.shiftR#"- , "type" : "shiftR# :: KnownNat n => Signed n -> Int -> Signed n"- , "templateE" : "~ARG[1] >>> ~ARG[2]"- }- }-, { "BlackBox" : { "name" : "Clash.Sized.Internal.Signed.rotateL#"+ , "kind" : "Declaration" , "type" : "rotateL# :: KnownNat n => Signed n -> Int -> Signed n"- , "templateD" :+ , "template" : "// rotateL begin-wire [2*~LIT[0]-1:0] ~SYM[0];-assign ~SYM[0] = {~ARG[1],~ARG[1]} << ~ARG[2];-assign ~RESULT = $signed(~SYM[0][~LIT[0]-1 : 0]);+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"- , "templateD" :+ , "template" : "// rotateR begin-wire [2*~LIT[0]-1:0] ~GENSYM[s][0];-assign ~SYM[0] = {~ARG[1],~ARG[1]} >> ~ARG[2];-assign ~RESULT = $signed(~SYM[0][~LIT[0]-1 : 0]);+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"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.resize#"- , "type" : "resize# :: (KnownNat n, KnownNat m) => Signed n -> Signed m"- , "comment" : "Back-end should only use this code when the result is smaller than the argument"- , "templateD" :-"// resize begin-~GENERATE- if (~LIT[1] < ~LIT[0]) begin- // truncate, sign preserving- assign ~RESULT = $signed({~VAR[s][2][~LIT[0]-1],~VAR[s][2][(~LIT[1]-2):0]});- end else begin- // sign-extend- assign ~RESULT = $signed(~VAR[s][2]);- end-~ENDGENERATE-// resize end"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.truncateB#"- , "type" : "truncateB# :: KnownNat m => Signed (n + m) -> Signed m"- , "templateD" : "assign ~RESULT = $signed(~ARG[1]);" } } ]
prims/verilog/Clash_Sized_Internal_Unsigned.json view
@@ -1,155 +1,25 @@ [ { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.size#"- , "type" : "size# :: KnownNat n => Unsigned n -> Int"- , "templateE" : "~SIZE[~TYPO]'sd~LIT[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.pack#"- , "type" : "pack# :: Unsigned n -> BitVector n"- , "templateE" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.unpack#"- , "type" : "unpack# :: BitVector n -> Unsigned n"- , "templateE" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.minBound#"- , "type" : "minBound# :: Unsigned n"- , "templateE" : "~SIZE[~TYPO]'d0"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.maxBound#"- , "type" : "maxBound# :: KnownNat n => Unsigned n"- , "templateE" : "{~LIT[0] {1'b1}}"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.+#"- , "type" : "(+#) :: KnownNat n => Unsigned n -> Unsigned n -> Unsigned n"- , "templateE" : "~ARG[1] + ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.-#"- , "type" : "(-#) :: KnownNat n => Unsigned n -> Unsigned n -> Unsigned n"- , "templateE" : "~ARG[1] - ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.*#"- , "type" : "(*#) :: KnownNat n => Unsigned n -> Unsigned n -> Unsigned n"- , "templateE" : "~ARG[1] * ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.negate#"- , "type" : "negate# :: KnownNat n => Unsigned n -> Unsigned n"- , "templateE" : "- ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.fromInteger#"- , "type" : "fromInteger# :: KnownNat n => Integer -> Unsigned n"- , "templateE" : "$unsigned(~ARG[1][(~LIT[0]-1):0])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.plus#"- , "type" : "plus# :: Unsigned m -> Unsigned n -> Unsigned (1 + Max m n)"- , "templateD" : "assign ~RESULT = ~ARG[0] + ~ARG[1];"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.minus#"- , "type" : "minus# :: (KnownNat m, KnownNat n) => Unsigned m -> Unsigned n -> Unsigned (1 + Max m n)"- , "templateD" : "assign ~RESULT = ~ARG[2] - ~ARG[3];"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.times#"- , "type" : "times# :: Unsigned m -> Unsigned n -> Unsigned (m + n)"- , "templateD" : "assign ~RESULT = ~ARG[0] * ~ARG[1];"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.quot#"- , "type" : "quot# :: Unsigned n -> Unsigned n -> Unsigned n"- , "templateE" : "~ARG[0] / ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.rem#"- , "type" : "rem# :: Unsigned n -> Unsigned n -> Unsigned n"- , "templateE" : "~ARG[0] % ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.and#"- , "type" : "and# :: Unsigned n -> Unsigned n -> Unsigned n"- , "templateE" : "~ARG[0] & ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.or#"- , "type" : "or# :: Unsigned n -> Unsigned n -> Unsigned n"- , "templateE" : "~ARG[0] | ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.xor#"- , "type" : "xor# :: Unsigned n -> Unsigned n -> Unsigned n"- , "templateE" : "~ARG[0] ^ ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.complement#"- , "type" : "complement# :: KnownNat n => Unsigned n -> Unsigned n"- , "templateE" : "~ ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.shiftL#"- , "type" : "shiftL# :: KnownNat n => Unsigned n -> Int -> Unsigned n"- , "templateE" : "~ARG[1] << ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.shiftR#"- , "type" : "shiftR# :: KnownNat n => Unsigned n -> Int -> Unsigned n"- , "templateE" : "~ARG[1] >> ~ARG[2]"- }- }-, { "BlackBox" : { "name" : "Clash.Sized.Internal.Unsigned.rotateL#"+ , "kind" : "Declaration" , "type" : "rotateL# :: KnownNat n => Unsigned n -> Int -> Unsigned n"- , "templateD" :+ , "template" : "// rotateL begin-wire [2*~LIT[0]-1:0] ~GENSYM[u][0];-assign ~SYM[0] = {~ARG[1],~ARG[1]} << ~ARG[2];-assign ~RESULT = ~SYM[0][~LIT[0]-1 : 0];+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"- , "templateD" :+ , "template" : "// rotateR begin-wire [2*~LIT[0]-1:0] ~GENSYM[u][0];-assign ~SYM[0] = {~ARG[1],~ARG[1]} >> ~ARG[2];-assign ~RESULT = ~SYM[0][~LIT[0]-1 : 0];+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"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.resize#"- , "type" : "resize# :: KnownNat m => Unsigned n -> Unsigned m"- , "templateD" : "assign ~RESULT = $unsigned(~ARG[1]);" } } ]
prims/verilog/Clash_Sized_RTree.json view
@@ -1,19 +1,25 @@ [ { "BlackBox" : { "name" : "Clash.Sized.RTree.treplicate"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "replicate :: SNat d -> a -> RTree d a"- , "templateE" : "'{(2**~LIT[0]) {~ARG[1]}}"+ , "template" : "{(2**~LIT[0]) {~ARG[1]}}" } } , { "BlackBox" : { "name" : "Clash.Sized.RTree.textract"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "textract :: RTree 0 a -> a"- , "templateE" : "~VAR[tree][0][~SIZE[~TYP[0]]-1 -: ~SIZE[~TYPO]]"+ , "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)"- , "templateE" : "~ARG[0]"+ , "template" : "~ARG[0]" } } ]
prims/verilog/Clash_Sized_Vector.json view
@@ -1,29 +1,39 @@ [ { "BlackBox" : { "name" : "Clash.Sized.Vector.head"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "head :: Vec (n + 1) a -> a"- , "templateE" : "~VAR[vec][0][~SIZE[~TYP[0]]-1 -: ~SIZE[~TYPO]]"+ , "template" : "~VAR[vec][0][~SIZE[~TYP[0]]-1 -: ~SIZE[~TYPO]]" } } , { "BlackBox" : { "name" : "Clash.Sized.Vector.tail"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "tail :: Vec (n + 1) a -> Vec n a"- , "templateE" : "~VAR[vec][0][~SIZE[~TYPO]-1 : 0]"+ , "template" : "~VAR[vec][0][~SIZE[~TYPO]-1 : 0]" } } , { "BlackBox" : { "name" : "Clash.Sized.Vector.last"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "Vec (n + 1) a -> a"- , "templateE" : "~VAR[vec][0][~SIZE[~TYPO]-1:0]"+ , "template" : "~VAR[vec][0][~SIZE[~TYPO]-1:0]" } } , { "BlackBox" : { "name" : "Clash.Sized.Vector.init"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "Vec (n + 1) a -> Vec n a"- , "templateE" : "~VAR[vec][0][~SIZE[~TYP[0]]-1 : ~SIZE[~TYPEL[~TYP[0]]]]"+ , "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]@@ -31,7 +41,7 @@ -> SNat n -- ARG[3] -> Vec i a -- ARG[4] -> Vec n a"- , "templateD" :+ , "template" : "// select begin wire ~TYPEL[~TYPO] ~SYM[1] [0:~LENGTH[~TYP[4]]-1]; genvar ~GENSYM[i][2];@@ -52,36 +62,46 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.++"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "(++) :: Vec n a -> Vec m a -> Vec (n + m) a"- , "templateE" : "{~ARG[0],~ARG[1]}"+ , "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"- , "templateE" : "~ARG[0]"+ , "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)"- , "templateE" : "~ARG[1]"+ , "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)"- , "templateE" : "~ARG[2]"+ , "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"- , "templateD" :+ , "template" : "// map begin genvar ~GENSYM[i][1]; ~GENERATE@@ -101,8 +121,10 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.imap"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "imap :: KnownNat n => (Index n -> a -> b) -> Vec n a -> Vec n b"- , "templateD" :+ , "template" : "// imap begin genvar ~GENSYM[i][1]; ~GENERATE@@ -112,7 +134,7 @@ 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] = ~LENGTH[~TYPO] - 1 - ~SYM[1];+ 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]]~@@ -126,8 +148,10 @@ } , { "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"- , "templateD" :+ , "template" : "// imap begin genvar ~GENSYM[i][1]; ~GENERATE@@ -137,7 +161,7 @@ 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] = ~LENGTH[~TYPO] - 1 - ~SYM[1] + ~ARG[0];+ 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]~@@ -151,8 +175,10 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.zipWith"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "zipWith :: (a -> b -> c) -> Vec n a -> Vec n b -> Vec n c"- , "templateD" :+ , "template" : "// zipWith start genvar ~GENSYM[i][2]; ~GENERATE@@ -175,8 +201,10 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.foldr"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "foldr :: (a -> b -> b) -> b -> Vec n a -> b"- , "templateD" :+ , "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];@@ -207,33 +235,36 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.fold"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "fold :: (a -> a -> a) -> Vec (n+1) a -> a" , "comment" : "THIS ONLY WORKS FOR POWER OF TWO LENGTH VECTORS"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "fold"- , "extension" : "inc"- , "content" :+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "fold"+ , "extension" : "inc"+ , "template" : "// ceiling of log2-function integer ~INCLUDENAME_clog2;+function integer ~INCLUDENAME[0]_clog2; input integer value; begin value = value-1;- for (~INCLUDENAME_clog2=0; value>0; ~INCLUDENAME_clog2=~INCLUDENAME_clog2+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_depth2Index;+function integer ~INCLUDENAME[0]_depth2Index; input integer levels; input integer depth; - ~INCLUDENAME_depth2Index = (2 ** levels) - (2 ** depth);+ ~INCLUDENAME[0]_depth2Index = (2 ** levels) - (2 ** depth); endfunction"- }- , "templateD" :+ }+ ]+ , "template" : "// fold begin // put flat input array into the first half of the intermediate array wire ~TYPO ~GENSYM[intermediate][0] [0:(2*~LENGTH[~TYP[1]])-2];@@ -246,27 +277,27 @@ ~ENDGENERATE // calculate the depth of the tree-localparam ~GENSYM[levels][4] = ~INCLUDENAME_clog2(~LENGTH[~TYP[1]]);+localparam ~GENSYM[levels][4] = ~INCLUDENAME[0]_clog2(~LENGTH[~TYP[1]]); // Create the tree of instantiated components genvar ~GENSYM[d][5]; genvar ~GENSYM[i][6]; ~GENERATE if (~SYM[4] != 0) begin : ~GENSYM[make_tree][7]- for (~SYM[5] = (~SYM[4] - 1); ~SYM[5] >= 0; ~SYM[5]=~SYM[5]-1) begin : ~GENSYM[tree_depth][11]- for (~SYM[6] = 0; ~SYM[6] < (2**~SYM[5]); ~SYM[6] = ~SYM[6]+1) begin : ~GENSYM[tree_depth_loop][12]+ for (~SYM[5] = ~SYM[4]; ~SYM[5] > 0; ~SYM[5]=~SYM[5]-1) begin : ~GENSYM[tree_depth][11]+ for (~SYM[6] = 0; ~SYM[6] < (2**(~SYM[5]-1)); ~SYM[6] = ~SYM[6]+1) begin : ~GENSYM[tree_depth_loop][12] wire ~TYPO ~GENSYM[fold_in1][8]; wire ~TYPO ~GENSYM[fold_in2][9]; ~OUTPUTWIREREG[0] ~TYPO ~GENSYM[fold_out][10]; - assign ~SYM[8] = ~SYM[0][~INCLUDENAME_depth2Index(~SYM[4]+1,~SYM[5]+2)+(2*~SYM[6])];- assign ~SYM[9] = ~SYM[0][~INCLUDENAME_depth2Index(~SYM[4]+1,~SYM[5]+2)+(2*~SYM[6])+1];+ assign ~SYM[8] = ~SYM[0][~INCLUDENAME[0]_depth2Index(~SYM[4]+1,~SYM[5]+1)+(2*~SYM[6])];+ assign ~SYM[9] = ~SYM[0][~INCLUDENAME[0]_depth2Index(~SYM[4]+1,~SYM[5]+1)+(2*~SYM[6])+1]; ~INST 0 ~OUTPUT <= ~SYM[10]~ ~TYPO~ ~INPUT <= ~SYM[8]~ ~TYPO~ ~INPUT <= ~SYM[9]~ ~TYPO~ ~INST- assign ~SYM[0][~INCLUDENAME_depth2Index(~SYM[4]+1,~SYM[5]+1)+~SYM[6]] = ~SYM[10];+ assign ~SYM[0][~INCLUDENAME[0]_depth2Index(~SYM[4]+1,~SYM[5])+~SYM[6]] = ~SYM[10]; end end end@@ -277,69 +308,56 @@ // fold end" } }-, { "BlackBox" :- { "name" : "Clash.Sized.Vector.index_int"- , "type" : "index_integer :: KnownNat n => Vec n a -> Int -> a"- , "templateD" :-"// indexVec begin-wire ~TYPO ~GENSYM[vec][0] [0:~LIT[0]-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]] = ~VAR[vecflat][1][~SYM[2]*~SIZE[~TYPO]+:~SIZE[~TYPO]];-end-~ENDGENERATE--assign ~RESULT = ~SYM[0][~ARG[2]];-// indexVec 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"- , "templateD" :-"// replaceVec start-reg ~TYP[3] ~GENSYM[vec][1] [0:~LIT[0]-1];-integer ~GENSYM[i][2];-always @(*) begin- for (~SYM[2]=0;~SYM[2]<~LIT[0];~SYM[2]=~SYM[2]+1) begin- ~SYM[1][~LIT[0]-1-~SYM[2]] = ~VAR[vecflat][1][~SYM[2]*~SIZE[~TYP[3]]+:~SIZE[~TYP[3]]];- end- ~SYM[1][~ARG[2]] = ~ARG[3];-end--genvar ~GENSYM[i][3];+ , "template" :+"// vector replace begin+genvar ~GENSYM[i][0]; ~GENERATE-for (~SYM[3]=0;~SYM[3]<~LIT[0];~SYM[3]=~SYM[3]+1) begin : ~GENSYM[mk_vec][4]- assign ~RESULT[~SYM[3]*~SIZE[~TYP[3]]+:~SIZE[~TYP[3]]] = ~SYM[1][(~LIT[0]-1)-~SYM[3]];+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-// replaceVec end"+// vector replace end" } } , { "BlackBox" : { "name" : "Clash.Sized.Vector.maxIndex"+ , "workInfo" : "Constant"+ , "kind" : "Expression" , "type" : "maxIndex :: KnownNat n => Vec n a -> Int"- , "templateE" : "~SIZE[~TYPO]'sd~LIT[0] - ~SIZE[~TYPO]'d1"+ , "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"- , "templateE" : "~SIZE[~TYPO]'sd~LIT[0]"+ , "template" : "~SIZE[~TYPO]'sd~LIT[0]" } } , { "BlackBox" : { "name" : "Clash.Sized.Vector.replicate"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "replicate :: SNat n -> a -> Vec n a"- , "templateE" : "{~LIT[0] {~ARG[1]}}"+ , "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)"- , "templateD" :+ , "template" : "// transpose begin genvar ~GENSYM[row_index][1]; genvar ~GENSYM[col_index][2];@@ -355,8 +373,10 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.reverse"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "reverse :: Vec n a -> Vec n a"- , "templateD" :+ , "template" : "// reverse begin genvar ~GENSYM[i][1]; ~GENERATE@@ -368,33 +388,33 @@ } } , { "BlackBox" :- { "name" : "Clash.Sized.Vector.lazyV"- , "type" : "lazyV :: KnownNat n => Vec n a -> Vec n a"- , "templateE" : "~ARG[1]"- }- }-, { "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)"- , "templateE" : "~ARG[2]"+ , "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)"- , "templateE" : "~ARG[2]"+ , "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"- , "templateD" :+ , "template" : "// rotateLeftS begin localparam ~GENSYM[shift_amount][2] = ~LIT[2] % ~LIT[0]; @@ -412,8 +432,10 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.rotateRightS"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "rotateRightS :: KnownNat n => Vec n a -> SNat d -> Vec n a"- , "templateD" :+ , "template" : "// rotateRightS begin localparam ~GENSYM[shift_amount][2] = ~LIT[2] % ~LIT[0];
− prims/verilog/Clash_Xilinx_ClockGen.json
@@ -1,39 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Xilinx.ClockGen.clockWizard"- , "type" :-"clockWizard- :: SSymbol name -- ARG[0]- -> Clock pllIn 'Source -- ARG[1]- -> Reset pllIn 'Asynchronous -- ARG[2]- -> (Clock pllOut 'Source, Signal pllOut Bool)"- , "templateD" :-"// clockWizard begin-~NAME[0] ~GENSYM[clockWizard_inst][2]-(.CLK_IN1 (~ARG[1])-,.RESET (~ARG[2])-,.CLK_OUT1 (~RESULT[1])-,.LOCKED (~RESULT[0]));-// clockWizard end"- }- }-, { "BlackBox" :- { "name" : "Clash.Xilinx.ClockGen.clockWizardDifferential"- , "type" :-"clockWizardDifferential- :: SSymbol name -- ARG[0]- -> Clock pllIn 'Source -- ARG[1]- -> Clock pllIn 'Source -- ARG[2]- -> Reset pllIn 'Asynchronous -- ARG[3]- -> (Clock pllOut 'Source, Signal pllOut Bool)"- , "templateD" :-"// clockWizardDifferential begin-~NAME[0] ~GENSYM[clockWizardDifferential_inst][2]-(.CLK_IN1_D_clk_n (~ARG[1])-,.CLK_IN1_D_clk_n (~ARG[2])-,.RESET (~ARG[3])-,.CLK_OUT1 (~RESULT[1])-,.LOCKED (~RESULT[0]));-// clockWizardDifferential end"- }- }-]
prims/verilog/Clash_Xilinx_DDR.json view
@@ -1,37 +1,37 @@ [ { "BlackBox" : { "name" : "Clash.Xilinx.DDR.iddr"+ , "kind" : "Declaration" , "type" : "iddr- :: ( HasCallStack -- ARG[0]- , fast ~ Dom n pFast -- ARG[1]- , slow ~ Dom n (2*pFast) -- ARG[2]- , KnownNat m ) -- ARG[3]- -> Clock slow gated -- ARG[4]- -> Reset slow synchronous -- ARG[5]- -> Signal fast (BitVector m) -- ARG[6]+ :: ( 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)"- , "templateD" :+ , "template" : "// iddr begin-wire ~SIGD[~GENSYM[dataout_l][1]][6];-wire ~SIGD[~GENSYM[dataout_h][2]][6];-wire ~SIGD[~GENSYM[d][3]][6];-assign ~SYM[3] = ~ARG[6];+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[6]]; ~SYM[8]=~SYM[8]+1) begin : ~GENSYM[ddri_array][7]+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[5] ~THEN \"SYNC\" ~ELSE \"ASYNC\" ~FI)+ .SRTYPE(~IF ~ISSYNC[2] ~THEN \"SYNC\" ~ELSE \"ASYNC\" ~FI) ) ~GENSYM[~COMPNAME_IDDR][9] ( .Q1(~SYM[1][~SYM[8]]),- .Q2(~SYM[2][~SYM[8]]),~IF ~ISGATED[6] ~THEN- .C(~ARG[4][1]),- .CE(~ARG[4][0]),~ELSE+ .Q2(~SYM[2][~SYM[8]]), .C(~ARG[4]),- .CE(1'b1),~FI+ .CE(~IF ~ISACTIVEENABLE[6] ~THEN ~ARG[6] ~ELSE 1'b1 ~FI), .D(~SYM[3][~SYM[8]]), .R(~ARG[5]), .S(1'b0)@@ -45,38 +45,38 @@ } , { "BlackBox" : { "name" : "Clash.Xilinx.DDR.oddr#"+ , "kind" : "Declaration" , "type" : "oddr#- :: ( slow ~ Dom n (2*pFast) -- ARG[0]- , fast ~ Dom n pFast -- ARG[1]- , KnownNat m ) -- ARG[2]- => Clock slow gated -- ARG[3]- -> Reset slow synchronous -- ARG[4]- -> Signal slow (BitVector m) -- ARG[5]- -> Signal slow (BitVector m) -- ARG[6]+ :: ( 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)"- , "templateD" :+ , "template" : "// oddr begin-wire ~SIGD[~GENSYM[datain_l][1]][6];-wire ~SIGD[~GENSYM[datain_h][2]][6];-wire ~SIGD[~GENSYM[q][3]][6];+wire ~SIGD[~GENSYM[datain_l][1]][7];+wire ~SIGD[~GENSYM[datain_h][2]][7];+wire ~SIGD[~GENSYM[q][3]][7]; -assign ~SYM[1] = ~ARG[5];-assign ~SYM[2] = ~ARG[6];+assign ~SYM[1] = ~ARG[6];+assign ~SYM[2] = ~ARG[7]; genvar ~GENSYM[i][8]; ~GENERATE-for (~SYM[8]=0; ~SYM[8] < ~SIZE[~TYP[6]]; ~SYM[8]=~SYM[8]+1) begin : ~GENSYM[ddro_array][7]+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[4] ~THEN \"SYNC\" ~ELSE \"ASYNC\" ~FI)+ .SRTYPE(~IF ~ISSYNC[1] ~THEN \"SYNC\" ~ELSE \"ASYNC\" ~FI) ) ~GENSYM[~COMPNAME_ODDR][9] (- .Q(~SYM[3][~SYM[8]]),~IF ~ISGATED[3] ~THEN- .C(~ARG[3][1]),- .CE(~ARG[3][0]),~ELSE+ .Q(~SYM[3][~SYM[8]]), .C(~ARG[3]),- .CE(1'b1),~FI+ .CE(~IF ~ISACTIVEENABLE[5] ~THEN ~ARG[5] ~ELSE 1'b1 ~FI), .D1(~SYM[1][~SYM[8]]), .D2(~SYM[2][~SYM[8]]), .R(~ARG[4]),
prims/verilog/GHC_Base.json view
@@ -1,24 +1,8 @@-[ { "Primitive" :- { "name" : "GHC.Base.$"- , "primType" : "Function"- }- }-, { "BlackBox" :- { "name" : "GHC.Base.quotInt"- , "type" : "quotInt :: Int -> Int -> Int"- , "templateE" : "~ARG[0] / ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Base.remInt"- , "type" : "remInt :: Int -> Int -> Int"- , "templateE" : "~ARG[0] % ~ARG[1]"- }- }-, { "BlackBox" :+[ { "BlackBox" : { "name" : "GHC.Base.divInt"+ , "kind" : "Declaration" , "type" : "divInt :: Int -> Int -> Int"- , "templateD" :+ , "template" : "// divInt begin // divide (rounds towards zero) wire ~SIGD[~GENSYM[quot_res][0]][0];@@ -31,8 +15,9 @@ } , { "BlackBox" : { "name" : "GHC.Base.modInt"+ , "kind" : "Declaration" , "type" : "modInt :: Int -> Int -> Int"- , "templateD" :+ , "template" : "// modInt begin // remainder wire ~SIGD[~GENSYM[rem_res][0]][0];
prims/verilog/GHC_Classes.json view
@@ -1,61 +1,8 @@ [ { "BlackBox" :- { "name" : "GHC.Classes.eqInt"- , "type" : "eqInt :: Int -> Int -> Bool"- , "templateE" : "~ARG[0] == ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.neInt"- , "type" : "neInt :: Int -> Int -> Bool"- , "templateE" : "~ARG[0] != ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.gtInt"- , "type" : "gtInt :: Int -> Int -> Bool"- , "templateE" : "~ARG[0] > ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.geInt"- , "type" : "geInt :: Int -> Int -> Bool"- , "templateE" : "~ARG[0] >= ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.ltInt"- , "type" : "ltInt :: Int -> Int -> Bool"- , "templateE" : "~ARG[0] < ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.leInt"- , "type" : "leInt :: Int -> Int -> Bool"- , "templateE" : "~ARG[0] <= ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.&&"- , "type" : "(&&) :: Bool -> Bool -> Bool"- , "templateE" : "~ARG[0] & ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.||"- , "type" : "(::) :: Bool -> Bool -> Bool"- , "templateE" : "~ARG[0] | ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.not"- , "type" : "not :: Bool -> Bool"- , "templateE" : "~ ~ARG[0]"- }- }-, { "BlackBox" : { "name" : "GHC.Classes.divInt#"+ , "kind" : "Declaration" , "type" : "divInt# :: Int# -> Int# -> Int#"- , "templateD" :+ , "template" : "// divInt# begin // divide (rounds towards zero) wire ~SIGD[~GENSYM[quot_res][0]][0];@@ -68,8 +15,9 @@ } , { "BlackBox" : { "name" : "GHC.Classes.modInt#"+ , "kind" : "Declaration" , "type" : "modInt# :: Int# -> Int# -> Int#"- , "templateD" :+ , "template" : "// modInt# begin // remainder wire ~SIGD[~GENSYM[rem_res][0]][0];
− prims/verilog/GHC_Int.json
@@ -1,25 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Int.I8#"- , "type" : "I8# :: Int# -> Int8"- , "templateD" : "assign ~RESULT = $signed(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Int.I16#"- , "type" : "I16# :: Int# -> Int16"- , "templateD" : "assign ~RESULT = $signed(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Int.I32#"- , "type" : "I32# :: Int# -> Int32"- , "templateD" : "assign ~RESULT = $signed(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Int.I64#"- , "type" : "I64# :: Int# -> Int64"- , "templateD" : "assign ~RESULT = $signed(~ARG[0]);"- }- }-]
prims/verilog/GHC_Integer_Type.json view
@@ -1,49 +1,8 @@ [ { "BlackBox" :- { "name" : "GHC.Integer.Type.smallInteger"- , "type" : "smallInteger :: Int# -> Integer"- , "templateD" : "assign ~RESULT = $signed(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.integerToInt"- , "type" : "integerToInt :: Integer -> Int#"- , "templateD" : "assign ~RESULT = $signed(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.plusInteger"- , "type" : "plusInteger :: Integer -> Integer -> Integer"- , "templateE" : "~ARG[0] + ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.minusInteger"- , "type" : "minusInteger :: Integer -> Integer -> Integer"- , "templateE" : "~ARG[0] - ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.timesInteger"- , "type" : "timesInteger :: Integer -> Integer -> Integer"- , "templateE" : "~ARG[0] * ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.negateInteger"- , "type" : "negateInteger :: Integer -> Integer"- , "templateE" : "-~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.absInteger"- , "type" : "absInteger :: Integer -> Integer"- , "templateE" : "(~ARG[0] < ~SIZE[~TYPO]'sd0) ? -~ARG[0] : ~ARG[0]"- }- }-, { "BlackBox" : { "name" : "GHC.Integer.Type.divInteger"+ , "kind" : "Declaration" , "type" : "divInteger :: Integer -> Integer -> Integer"- , "templateD" :+ , "template" : "// divInteger begin // divide (rounds towards zero) wire ~SIGD[~GENSYM[quot_res][0]][0];@@ -56,8 +15,9 @@ } , { "BlackBox" : { "name" : "GHC.Integer.Type.modInteger"+ , "kind" : "Declaration" , "type" : "modInteger :: Integer -> Integer -> Integer"- , "templateD" :+ , "template" : "// modInteger begin // remainder wire ~SIGD[~GENSYM[rem_res][0]][0];@@ -68,114 +28,6 @@ ~SYM[0] : ((~VAR[dividend][0] == ~SIZE[~TYPO]'sd0) ? ~SIZE[~TYPO]'sd0 : ~SYM[0] + ~VAR[divider][1]); // modInteger end"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.quotInteger"- , "type" : "quotInteger :: Integer -> Integer -> Integer"- , "templateE" : "~ARG[0] / ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.remInteger"- , "type" : "remInteger :: Integer -> Integer -> Integer"- , "templateE" : "~ARG[0] % ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.eqInteger"- , "type" : "eqInteger :: Integer -> Integer -> Bool"- , "templateE" : "~ARG[0] == ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.neqInteger"- , "type" : "neqInteger :: Integer -> Integer -> Bool"- , "templateE" : "~ARG[0] != ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.leInteger"- , "type" : "leInteger :: Integer -> Integer -> Bool"- , "templateE" : "~ARG[0] <= ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.gtInteger"- , "type" : "gtInteger :: Integer -> Integer -> Bool"- , "templateE" : "~ARG[0] > ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.ltInteger"- , "type" : "ltInteger :: Integer -> Integer -> Bool"- , "templateE" : "~ARG[0] < ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.geInteger"- , "type" : "geInteger :: Integer -> Integer -> Bool"- , "templateE" : "~ARG[0] >= ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.eqInteger#"- , "type" : "eqInteger :: Integer -> Integer -> Int#"- , "templateE" : "(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.neqInteger#"- , "type" : "neqInteger :: Integer -> Integer -> Int#"- , "templateE" : "(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.leInteger#"- , "type" : "leInteger :: Integer -> Integer -> Int#"- , "templateE" : "(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.gtInteger#"- , "type" : "gtInteger :: Integer -> Integer -> Int#"- , "templateE" : "(~ARG[0] > ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.ltInteger#"- , "type" : "ltInteger :: Integer -> Integer -> Int#"- , "templateE" : "(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.geInteger#"- , "type" : "geInteger :: Integer -> Integer -> Int#"- , "templateE" : "(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.shiftRInteger"- , "type" : "shiftRInteger :: Integer -> Int# -> Integer"- , "templateE" : "~ARG[0] >>> ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.shiftLInteger"- , "type" : "shiftLInteger :: Integer -> Int# -> Integer"- , "templateE" : "~ARG[0] <<< ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.wordToInteger"- , "type" : "wordToInteger :: Word# -> Integer"- , "templateD" : "assign ~RESULT = $signed(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.integerToWord"- , "type" : "integerToWord :: Integer -> Word#"- , "templateD" : "assign ~RESULT = $unsigned(~ARG[0]);" } } ]
prims/verilog/GHC_Prim.json view
@@ -1,79 +1,8 @@ [ { "BlackBox" :- { "name" : "GHC.Prim.gtChar#"- , "type" : "gtChar# :: Char# -> Char# -> Int#"- , "templateE" : "(~ARG[0] > ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.geChar#"- , "type" : "geChar# :: Char# -> Char# -> Int#"- , "templateE" : "(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.eqChar#"- , "type" : "eqChar# :: Char# -> Char# -> Int#"- , "templateE" : "(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.neChar#"- , "type" : "neChar# :: Char# -> Char# -> Int#"- , "templateE" : "(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ltChar#"- , "type" : "ltChar# :: Char# -> Char# -> Int#"- , "templateE" : "(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.leChar#"- , "type" : "leChar# :: Char# -> Char# -> Int#"- , "templateE" : "(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ord#"- , "type" : "ord :: Char# -> Int#"- , "templateD" : "assign ~RESULT = $unsigned(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.+#"- , "type" : "(+#) :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] + ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.-#"- , "type" : "(-#) :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] - ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.*#"- , "type" : "(*#) :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] * ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.quotInt#"- , "type" : "quotInt# :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] / ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.remInt#"- , "type" : "remInt# :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] % ~ARG[1]"- }- }-, { "BlackBox" : { "name" : "GHC.Prim.quotRemInt#"+ , "kind" : "Declaration" , "type" : "quotRemInt# :: Int# -> Int# -> (#Int#, Int##)"- , "templateD" :+ , "template" : "// quotRemInt begin wire ~SIGD[~GENSYM[quot_res][0]][0]; wire ~SIGD[~GENSYM[rem_res][1]][0];@@ -85,135 +14,10 @@ } } , { "BlackBox" :- { "name" : "GHC.Prim.andI#"- , "type" : "andI# :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] & ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.orI#"- , "type" : "orI# :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] | ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.xorI#"- , "type" : "xorI# :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] ^ ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.notI#"- , "type" : "notI# :: Int# -> Int#"- , "templateE" : "~ ~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.negateInt#"- , "type" : "negateInt# :: Int# -> Int#"- , "templateE" : "-(~ARG[0])"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.>#"- , "type" : "(>#) :: Int# -> Int# -> Int#"- , "templateE" : "(~ARG[0] > ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.>=#"- , "type" : "(>=#) :: Int# -> Int# -> Int#"- , "templateE" : "(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.==#"- , "type" : "(==) :: Int# -> Int# -> Int#"- , "templateE" : "(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim./=#"- , "type" : "(/=#) :: Int# -> Int# -> Int#"- , "templateE" : "(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.<#"- , "type" : "(<#) :: Int# -> Int# -> Int#"- , "templateE" : "(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.<=#"- , "type" : "(<=#) :: Int# -> Int# -> Int#"- , "templateE" : "(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.chr#"- , "type" : "ord :: Int# -> Char#"- , "templateD" : "assign ~RESULT = $unsigned(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.int2Word#"- , "type" : "int2Word# :: Int# -> Word#"- , "templateE" : "$unsigned(~ARG[0])"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.uncheckedIShiftL#"- , "type" : "uncheckedIShiftL# :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] <<< ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.uncheckedIShiftRA#"- , "type" : "uncheckedIShiftRA# :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] >>> ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.uncheckedIShiftRL#"- , "type" : "uncheckedIShiftRL# :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] >> ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.plusWord#"- , "type" : "plusWord# :: Word# -> Word# -> Word#"- , "templateE" : "~ARG[0] + ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.minusWord#"- , "type" : "minusWord# :: Word# -> Word# -> Word#"- , "templateE" : "~ARG[0] - ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.timesWord#"- , "type" : "timesWord# :: Word# -> Word# -> Word#"- , "templateE" : "~ARG[0] * ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.quotWord#"- , "type" : "quotWord# :: Word# -> Word# -> Word#"- , "templateE" : "~ARG[0] / ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.remWord#"- , "type" : "remWord# :: Word# -> Word# -> Word#"- , "templateE" : "~ARG[0] % ~ARG[1]"- }- }-, { "BlackBox" : { "name" : "GHC.Prim.quotRemWord#"+ , "kind" : "Declaration" , "type" : "quotRemWord# :: Word# -> Word# -> (#Word#, Word##)"- , "templateD" :+ , "template" : "// quotRemWord begin wire ~SIGD[~GENSYM[quot_res][0]][0]; wire ~SIGD[~GENSYM[rem_res][1]][0];@@ -225,116 +29,40 @@ } } , { "BlackBox" :- { "name" : "GHC.Prim.and#"- , "type" : "and# :: Word# -> Word# -> Word#"- , "templateE" : "~ARG[0] & ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.or#"- , "type" : "or# :: Word# -> Word# -> Word#"- , "templateE" : "~ARG[0] | ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.xor#"- , "type" : "xor# :: Word# -> Word# -> Word#"- , "templateE" : "~ARG[0] ^ ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.not#"- , "type" : "not# :: Word# -> Word#"- , "templateE" : "~ ~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.uncheckedShiftL#"- , "type" : "uncheckedShiftL# :: Word# -> Int# -> Word#"- , "templateE" : "~ARG[0] << ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.uncheckedShiftRL#"- , "type" : "uncheckedShiftRL# :: Word# -> Int# -> Word#"- , "templateE" : "~ARG[0] >> ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.word2Int#"- , "type" : "int2Word# :: Word# -> Int#"- , "templateE" : "$signed(~ARG[0])"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.gtWord#"- , "type" : "gtWord# :: Word# -> Word# -> Int#"- , "templateE" : "(~ARG[0] > ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.geWord#"- , "type" : "geWord# :: Word# -> Word# -> Int#"- , "templateE" : "(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.eqWord#"- , "type" : "eqWord# :: Word# -> Word# -> Int#"- , "templateE" : "(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.neWord#"- , "type" : "neWord# :: Word# -> Word# -> Int#"- , "templateE" : "(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.ltWord#"- , "type" : "ltWord# :: Word# -> Word# -> Int#"- , "templateE" : "(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.leWord#"- , "type" : "leWord# :: Word# -> Word# -> Int#"- , "templateE" : "(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"- }- }-, { "BlackBox" : { "name" : "GHC.Prim.popCnt8#"+ , "kind" : "Declaration" , "type" : "popCnt8# :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "popCnt8"- , "extension" : "inc"- , "content" :+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "popCnt8"+ , "extension" : "inc"+ , "template" : "// ceiling of log2-function integer ~INCLUDENAME_clog2;+function integer ~INCLUDENAME[0]_clog2; input integer value; begin value = value-1;- for (~INCLUDENAME_clog2=0; value>0; ~INCLUDENAME_clog2=~INCLUDENAME_clog2+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_depth2Index;+function integer ~INCLUDENAME[0]_depth2Index; input integer levels; input integer depth; - ~INCLUDENAME_depth2Index = (2 ** levels) - (2 ** depth);+ ~INCLUDENAME[0]_depth2Index = (2 ** levels) - (2 ** depth); endfunction"- }- , "templateD" :+ }+ ]+ , "template" : "// popCnt8 begin localparam ~GENSYM[width][0] = 8; // depth of the tree-localparam ~GENSYM[levels][2] = ~INCLUDENAME_clog2(~SYM[0]);+localparam ~GENSYM[levels][2] = ~INCLUDENAME[0]_clog2(~SYM[0]); wire [~SYM[2]:0] ~GENSYM[intermediate][3] [0:(2*~SYM[0])-2]; @@ -342,7 +70,7 @@ 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(~ARG[0][~SYM[4]]);+ assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]); end ~ENDGENERATE @@ -351,11 +79,11 @@ genvar ~GENSYM[i][7]; ~GENERATE if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]- for (~SYM[6] = (~SYM[2] - 1); ~SYM[6] >= 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]- for (~SYM[7] = 0; ~SYM[7] < (2**~SYM[6]); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]- assign ~SYM[3][~INCLUDENAME_depth2Index(~SYM[2]+1,~SYM[6]+1)+~SYM[7]] =- ~SYM[3][~INCLUDENAME_depth2Index(~SYM[2]+1,~SYM[6]+2)+(2*~SYM[7])] +- ~SYM[3][~INCLUDENAME_depth2Index(~SYM[2]+1,~SYM[6]+2)+(2*~SYM[7])+1];+ 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@@ -368,37 +96,39 @@ } , { "BlackBox" : { "name" : "GHC.Prim.popCnt16#"+ , "kind" : "Declaration" , "type" : "popCnt16# :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "popCnt16"- , "extension" : "inc"- , "content" :+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "popCnt16"+ , "extension" : "inc"+ , "template" : "// ceiling of log2-function integer ~INCLUDENAME_clog2;+function integer ~INCLUDENAME[0]_clog2; input integer value; begin value = value-1;- for (~INCLUDENAME_clog2=0; value>0; ~INCLUDENAME_clog2=~INCLUDENAME_clog2+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_depth2Index;+function integer ~INCLUDENAME[0]_depth2Index; input integer levels; input integer depth; - ~INCLUDENAME_depth2Index = (2 ** levels) - (2 ** depth);+ ~INCLUDENAME[0]_depth2Index = (2 ** levels) - (2 ** depth); endfunction"- }- , "templateD" :+ }+ ]+ , "template" : "// popCnt16 begin localparam ~GENSYM[width][0] = 16; // depth of the tree-localparam ~GENSYM[levels][2] = ~INCLUDENAME_clog2(~SYM[0]);+localparam ~GENSYM[levels][2] = ~INCLUDENAME[0]_clog2(~SYM[0]); wire [~SYM[2]:0] ~GENSYM[intermediate][3] [0:(2*~SYM[0])-2]; @@ -406,7 +136,7 @@ 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(~ARG[0][~SYM[4]]);+ assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]); end ~ENDGENERATE @@ -415,11 +145,11 @@ genvar ~GENSYM[i][7]; ~GENERATE if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]- for (~SYM[6] = (~SYM[2] - 1); ~SYM[6] >= 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]- for (~SYM[7] = 0; ~SYM[7] < (2**~SYM[6]); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]- assign ~SYM[3][~INCLUDENAME_depth2Index(~SYM[2]+1,~SYM[6]+1)+~SYM[7]] =- ~SYM[3][~INCLUDENAME_depth2Index(~SYM[2]+1,~SYM[6]+2)+(2*~SYM[7])] +- ~SYM[3][~INCLUDENAME_depth2Index(~SYM[2]+1,~SYM[6]+2)+(2*~SYM[7])+1];+ 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@@ -432,37 +162,39 @@ } , { "BlackBox" : { "name" : "GHC.Prim.popCnt32#"+ , "kind" : "Declaration" , "type" : "popCnt32# :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "popCnt32"- , "extension" : "inc"- , "content" :+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "popCnt32"+ , "extension" : "inc"+ , "template" : "// ceiling of log2-function integer ~INCLUDENAME_clog2;+function integer ~INCLUDENAME[0]_clog2; input integer value; begin value = value-1;- for (~INCLUDENAME_clog2=0; value>0; ~INCLUDENAME_clog2=~INCLUDENAME_clog2+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_depth2Index;+function integer ~INCLUDENAME[0]_depth2Index; input integer levels; input integer depth; - ~INCLUDENAME_depth2Index = (2 ** levels) - (2 ** depth);+ ~INCLUDENAME[0]_depth2Index = (2 ** levels) - (2 ** depth); endfunction"- }- , "templateD" :+ }+ ]+ , "template" : "// popCnt32 begin localparam ~GENSYM[width][0] = 32; // depth of the tree-localparam ~GENSYM[levels][2] = ~INCLUDENAME_clog2(~SYM[0]);+localparam ~GENSYM[levels][2] = ~INCLUDENAME[0]_clog2(~SYM[0]); wire [~SYM[2]:0] ~GENSYM[intermediate][3] [0:(2*~SYM[0])-2]; @@ -470,7 +202,7 @@ 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(~ARG[0][~SYM[4]]);+ assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]); end ~ENDGENERATE @@ -479,11 +211,11 @@ genvar ~GENSYM[i][7]; ~GENERATE if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]- for (~SYM[6] = (~SYM[2] - 1); ~SYM[6] >= 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]- for (~SYM[7] = 0; ~SYM[7] < (2**~SYM[6]); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]- assign ~SYM[3][~INCLUDENAME_depth2Index(~SYM[2]+1,~SYM[6]+1)+~SYM[7]] =- ~SYM[3][~INCLUDENAME_depth2Index(~SYM[2]+1,~SYM[6]+2)+(2*~SYM[7])] +- ~SYM[3][~INCLUDENAME_depth2Index(~SYM[2]+1,~SYM[6]+2)+(2*~SYM[7])+1];+ 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@@ -496,37 +228,39 @@ } , { "BlackBox" : { "name" : "GHC.Prim.popCnt64#"+ , "kind" : "Declaration" , "type" : "popCnt64# :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "popCnt64"- , "extension" : "inc"- , "content" :+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "popCnt64"+ , "extension" : "inc"+ , "template" : "// ceiling of log2-function integer ~INCLUDENAME_clog2;+function integer ~INCLUDENAME[0]_clog2; input integer value; begin value = value-1;- for (~INCLUDENAME_clog2=0; value>0; ~INCLUDENAME_clog2=~INCLUDENAME_clog2+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_depth2Index;+function integer ~INCLUDENAME[0]_depth2Index; input integer levels; input integer depth; - ~INCLUDENAME_depth2Index = (2 ** levels) - (2 ** depth);+ ~INCLUDENAME[0]_depth2Index = (2 ** levels) - (2 ** depth); endfunction"- }- , "templateD" :+ }+ ]+ , "template" : "// popCnt64 begin localparam ~GENSYM[width][0] = 64; // depth of the tree-localparam ~GENSYM[levels][2] = ~INCLUDENAME_clog2(~SYM[0]);+localparam ~GENSYM[levels][2] = ~INCLUDENAME[0]_clog2(~SYM[0]); wire [~SYM[2]:0] ~GENSYM[intermediate][3] [0:(2*~SYM[0])-2]; @@ -534,7 +268,7 @@ 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(~ARG[0][~SYM[4]]);+ assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]); end ~ENDGENERATE @@ -543,11 +277,11 @@ genvar ~GENSYM[i][7]; ~GENERATE if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]- for (~SYM[6] = (~SYM[2] - 1); ~SYM[6] >= 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]- for (~SYM[7] = 0; ~SYM[7] < (2**~SYM[6]); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]- assign ~SYM[3][~INCLUDENAME_depth2Index(~SYM[2]+1,~SYM[6]+1)+~SYM[7]] =- ~SYM[3][~INCLUDENAME_depth2Index(~SYM[2]+1,~SYM[6]+2)+(2*~SYM[7])] +- ~SYM[3][~INCLUDENAME_depth2Index(~SYM[2]+1,~SYM[6]+2)+(2*~SYM[7])+1];+ 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@@ -560,37 +294,39 @@ } , { "BlackBox" : { "name" : "GHC.Prim.popCnt#"- , "type" : "popCnt8# :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "popCnt"- , "extension" : "inc"- , "content" :+ , "kind" : "Declaration"+ , "type" : "popCnt# :: Word# -> Word#"+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "popCnt"+ , "extension" : "inc"+ , "template" : "// ceiling of log2-function integer ~INCLUDENAME_clog2;+function integer ~INCLUDENAME[0]_clog2; input integer value; begin value = value-1;- for (~INCLUDENAME_clog2=0; value>0; ~INCLUDENAME_clog2=~INCLUDENAME_clog2+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_depth2Index;+function integer ~INCLUDENAME[0]_depth2Index; input integer levels; input integer depth; - ~INCLUDENAME_depth2Index = (2 ** levels) - (2 ** depth);+ ~INCLUDENAME[0]_depth2Index = (2 ** levels) - (2 ** depth); endfunction"- }- , "templateD" :+ }+ ]+ , "template" : "// popCnt begin localparam ~GENSYM[width][0] = ~SIZE[~TYPO]; // depth of the tree-localparam ~GENSYM[levels][2] = ~INCLUDENAME_clog2(~SYM[0]);+localparam ~GENSYM[levels][2] = ~INCLUDENAME[0]_clog2(~SYM[0]); wire [~SYM[2]:0] ~GENSYM[intermediate][3] [0:(2*~SYM[0])-2]; @@ -598,7 +334,7 @@ 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(~ARG[0][~SYM[4]]);+ assign ~SYM[3][~SYM[4]] = $unsigned(~VAR[input][0][~SYM[4]]); end ~ENDGENERATE @@ -607,11 +343,11 @@ genvar ~GENSYM[i][7]; ~GENERATE if (~SYM[2] != 0) begin : ~GENSYM[make_tree][8]- for (~SYM[6] = (~SYM[2] - 1); ~SYM[6] >= 0; ~SYM[6]=~SYM[6]-1) begin : ~GENSYM[tree_depth][9]- for (~SYM[7] = 0; ~SYM[7] < (2**~SYM[6]); ~SYM[7] = ~SYM[7]+1) begin : ~GENSYM[tree_depth_loop][10]- assign ~SYM[3][~INCLUDENAME_depth2Index(~SYM[2]+1,~SYM[6]+1)+~SYM[7]] =- ~SYM[3][~INCLUDENAME_depth2Index(~SYM[2]+1,~SYM[6]+2)+(2*~SYM[7])] +- ~SYM[3][~INCLUDENAME_depth2Index(~SYM[2]+1,~SYM[6]+2)+(2*~SYM[7])+1];+ 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@@ -624,23 +360,25 @@ } , { "BlackBox" : { "name" : "GHC.Prim.clz8#"+ , "kind" : "Declaration" , "type" : "clz8 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "enc"- , "extension" : "inc"- , "content" :-"function [1:0] ~INCLUDENAME;+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "enc"+ , "extension" : "inc"+ , "template" :+"function [1:0] ~INCLUDENAME[0]; input [1:0] a; case (a)- 2'b00: ~INCLUDENAME = 2'b10;- 2'b01: ~INCLUDENAME = 2'b01;- 2'b10: ~INCLUDENAME = 2'b00;- default: ~INCLUDENAME = 2'b00;+ 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"- }- , "templateD" :+ }+ ]+ , "template" : "// clz8 begin wire [0:7] ~GENSYM[v][1]; assign ~SYM[1] = ~ARG[0][7:0];@@ -649,7 +387,7 @@ 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(~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]); end ~ENDGENERATE @@ -690,23 +428,25 @@ } , { "BlackBox" : { "name" : "GHC.Prim.clz16#"+ , "kind" : "Declaration" , "type" : "clz16 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "enc"- , "extension" : "inc"- , "content" :-"function [1:0] ~INCLUDENAME;+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "enc"+ , "extension" : "inc"+ , "template" :+"function [1:0] ~INCLUDENAME[0]; input [1:0] a; case (a)- 2'b00: ~INCLUDENAME = 2'b10;- 2'b01: ~INCLUDENAME = 2'b01;- 2'b10: ~INCLUDENAME = 2'b00;- default: ~INCLUDENAME = 2'b00;+ 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"- }- , "templateD" :+ }+ ]+ , "template" : "// clz16 begin wire [0:15] ~GENSYM[v][1]; assign ~SYM[1] = ~ARG[0][15:0];@@ -715,7 +455,7 @@ 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(~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]); end ~ENDGENERATE @@ -772,23 +512,25 @@ } , { "BlackBox" : { "name" : "GHC.Prim.clz32#"+ , "kind" : "Declaration" , "type" : "clz32 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "enc"- , "extension" : "inc"- , "content" :-"function [1:0] ~INCLUDENAME;+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "enc"+ , "extension" : "inc"+ , "template" :+"function [1:0] ~INCLUDENAME[0]; input [1:0] a; case (a)- 2'b00: ~INCLUDENAME = 2'b10;- 2'b01: ~INCLUDENAME = 2'b01;- 2'b10: ~INCLUDENAME = 2'b00;- default: ~INCLUDENAME = 2'b00;+ 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"- }- , "templateD" :+ }+ ]+ , "template" : "// clz32 begin wire [0:31] ~GENSYM[v][1]; assign ~SYM[1] = ~ARG[0][31:0];@@ -797,7 +539,7 @@ 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(~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]); end ~ENDGENERATE @@ -870,23 +612,25 @@ } , { "BlackBox" : { "name" : "GHC.Prim.clz64#"+ , "kind" : "Declaration" , "type" : "clz64 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "enc"- , "extension" : "inc"- , "content" :-"function [1:0] ~INCLUDENAME;+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "enc"+ , "extension" : "inc"+ , "template" :+"function [1:0] ~INCLUDENAME[0]; input [1:0] a; case (a)- 2'b00: ~INCLUDENAME = 2'b10;- 2'b01: ~INCLUDENAME = 2'b01;- 2'b10: ~INCLUDENAME = 2'b00;- default: ~INCLUDENAME = 2'b00;+ 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"- }- , "templateD" :+ }+ ]+ , "template" : "// clz64 begin wire [0:63] ~GENSYM[v][1]; assign ~SYM[1] = ~ARG[0][63:0];@@ -895,7 +639,7 @@ 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(~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]); end ~ENDGENERATE @@ -984,23 +728,25 @@ } , { "BlackBox" : { "name" : "GHC.Prim.clz#"+ , "kind" : "Declaration" , "type" : "clz :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "enc"- , "extension" : "inc"- , "content" :-"function [1:0] ~INCLUDENAME;+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "enc"+ , "extension" : "inc"+ , "template" :+"function [1:0] ~INCLUDENAME[0]; input [1:0] a; case (a)- 2'b00: ~INCLUDENAME = 2'b10;- 2'b01: ~INCLUDENAME = 2'b01;- 2'b10: ~INCLUDENAME = 2'b00;- default: ~INCLUDENAME = 2'b00;+ 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"- }- , "templateD" :+ }+ ]+ , "template" : "// clz begin~IF ~IW64 ~THEN wire [0:63] ~GENSYM[v][1]; assign ~SYM[1] = ~ARG[0][63:0];@@ -1009,7 +755,7 @@ 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(~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]); end ~ENDGENERATE @@ -1099,7 +845,7 @@ 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(~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]); end ~ENDGENERATE @@ -1172,23 +918,25 @@ } , { "BlackBox" : { "name" : "GHC.Prim.ctz8#"+ , "kind" : "Declaration" , "type" : "ctz8 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "enc"- , "extension" : "inc"- , "content" :-"function [1:0] ~INCLUDENAME;+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "enc"+ , "extension" : "inc"+ , "template" :+"function [1:0] ~INCLUDENAME[0]; input [1:0] a; case (a)- 2'b00: ~INCLUDENAME = 2'b10;- 2'b01: ~INCLUDENAME = 2'b01;- 2'b10: ~INCLUDENAME = 2'b00;- default: ~INCLUDENAME = 2'b00;+ 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"- }- , "templateD" :+ }+ ]+ , "template" : "// ctz8 begin wire [0:7] ~GENSYM[v][1]; genvar ~GENSYM[k][18];@@ -1202,7 +950,7 @@ 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(~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]); end ~ENDGENERATE @@ -1243,23 +991,25 @@ } , { "BlackBox" : { "name" : "GHC.Prim.ctz16#"+ , "kind" : "Declaration" , "type" : "ctz16 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "enc"- , "extension" : "inc"- , "content" :-"function [1:0] ~INCLUDENAME;+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "enc"+ , "extension" : "inc"+ , "template" :+"function [1:0] ~INCLUDENAME[0]; input [1:0] a; case (a)- 2'b00: ~INCLUDENAME = 2'b10;- 2'b01: ~INCLUDENAME = 2'b01;- 2'b10: ~INCLUDENAME = 2'b00;- default: ~INCLUDENAME = 2'b00;+ 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"- }- , "templateD" :+ }+ ]+ , "template" : "// ctz16 begin wire [0:15] ~GENSYM[v][1]; genvar ~GENSYM[k][18];@@ -1273,7 +1023,7 @@ 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(~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]); end ~ENDGENERATE @@ -1330,23 +1080,25 @@ } , { "BlackBox" : { "name" : "GHC.Prim.ctz32#"+ , "kind" : "Declaration" , "type" : "ctz32 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "enc"- , "extension" : "inc"- , "content" :-"function [1:0] ~INCLUDENAME;+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "enc"+ , "extension" : "inc"+ , "template" :+"function [1:0] ~INCLUDENAME[0]; input [1:0] a; case (a)- 2'b00: ~INCLUDENAME = 2'b10;- 2'b01: ~INCLUDENAME = 2'b01;- 2'b10: ~INCLUDENAME = 2'b00;- default: ~INCLUDENAME = 2'b00;+ 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"- }- , "templateD" :+ }+ ]+ , "template" : "// ctz32 begin wire [0:31] ~GENSYM[v][1]; genvar ~GENSYM[k][18];@@ -1360,7 +1112,7 @@ 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(~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]); end ~ENDGENERATE @@ -1433,23 +1185,25 @@ } , { "BlackBox" : { "name" : "GHC.Prim.ctz64#"+ , "kind" : "Declaration" , "type" : "ctz64 :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "enc"- , "extension" : "inc"- , "content" :-"function [1:0] ~INCLUDENAME;+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "enc"+ , "extension" : "inc"+ , "template" :+"function [1:0] ~INCLUDENAME[0]; input [1:0] a; case (a)- 2'b00: ~INCLUDENAME = 2'b10;- 2'b01: ~INCLUDENAME = 2'b01;- 2'b10: ~INCLUDENAME = 2'b00;- default: ~INCLUDENAME = 2'b00;+ 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"- }- , "templateD" :+ }+ ]+ , "template" : "// ctz64 begin wire [0:63] ~GENSYM[v][1]; genvar ~GENSYM[k][18];@@ -1463,7 +1217,7 @@ 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(~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]); end ~ENDGENERATE @@ -1552,23 +1306,25 @@ } , { "BlackBox" : { "name" : "GHC.Prim.ctz#"+ , "kind" : "Declaration" , "type" : "ctz :: Word# -> Word#"- , "imports" : ["~INCLUDENAME.inc"]- , "include" :- { "name" : "enc"- , "extension" : "inc"- , "content" :-"function [1:0] ~INCLUDENAME;+ , "imports" : ["~INCLUDENAME[0].inc"]+ , "includes" :+ [ { "name" : "enc"+ , "extension" : "inc"+ , "template" :+"function [1:0] ~INCLUDENAME[0]; input [1:0] a; case (a)- 2'b00: ~INCLUDENAME = 2'b10;- 2'b01: ~INCLUDENAME = 2'b01;- 2'b10: ~INCLUDENAME = 2'b00;- default: ~INCLUDENAME = 2'b00;+ 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"- }- , "templateD" :+ }+ ]+ , "template" : "// ctz begin~IF ~IW64 ~THEN wire [0:63] ~GENSYM[v][1]; genvar ~GENSYM[k][18];@@ -1582,7 +1338,7 @@ 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(~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]); end ~ENDGENERATE @@ -1677,7 +1433,7 @@ 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(~SYM[1][~SYM[3]*2:~SYM[3]*2+1]);+ assign ~SYM[2][~SYM[3]*2:~SYM[3]*2+1] = ~INCLUDENAME[0](~SYM[1][~SYM[3]*2:~SYM[3]*2+1]); end ~ENDGENERATE @@ -1746,117 +1502,6 @@ ~FI assign ~RESULT = $unsigned(~SYM[7]); // ctz end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.byteSwap16#"- , "type" : "byteSwap16# :: Word# -> Word#"- , "templateD" :-"// 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#"- , "type" : "byteSwap32# :: Word# -> Word#"- , "templateD" :-"// 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#"- , "type" : "byteSwap64# :: Word# -> Word#"- , "templateD" :-"// 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#"- , "type" : "byteSwap# :: Word# -> Word#"- , "templateD" :-"// 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#"- , "type" : "narrow8Int# :: Int# -> Int#"- , "templateD" :-"// narrow8Int begin-assign ~RESULT = $signed(~VAR[i][0][7:0]);-// narrow8Int end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.narrow16Int#"- , "type" : "narrow16Int# :: Int# -> Int#"- , "templateD" :-"// narrow16Int begin-assign ~RESULT = $signed(~VAR[i][0][15:0]);-// narrow16Int end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.narrow32Int#"- , "type" : "narrow32Int# :: Int# -> Int#"- , "templateD" :-"// narrow32Int begin-assign ~RESULT = $signed(~VAR[i][0][31:0]);-// narrow32Int end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.narrow8Word#"- , "type" : "narrow8Int# :: Word# -> Word#"- , "templateD" :-"// narrow8Word begin-assign ~RESULT = $unsigned(~VAR[w][0][7:0]);-// narrow8Word end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.narrow16Word#"- , "type" : "narrow16Word# :: Word# -> Word#"- , "templateD" :-"// narrow16Word begin-assign ~RESULT = $unsigned(~VAR[w][0][15:0]);-// narrow16Word end"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.narrow32Word#"- , "type" : "narrow32Int# :: Word# -> Word#"- , "templateD" :-"// narrow32Word begin-assign ~RESULT = $unsigned(~VAR[w][0][31:0]);-// narrow32Word end"- }- }-, { "Primitive" :- { "name" : "GHC.Prim.dataToTag#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "GHC.Prim.tagToEnum#"- , "primType" : "Function"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.unsafeCoerce#"- , "type" : "unsafeCoerce# :: a -> b"- , "templateE" : "~ARG[0]" } } ]
− prims/verilog/GHC_Types.json
@@ -1,24 +0,0 @@-[ { "Primitive" :- { "name" : "GHC.Types.MkCoercible"- , "primType" : "Constructor"- }- }-, { "BlackBox" :- { "name" : "GHC.Types.C#"- , "type" : "I# :: Char# -> Char"- , "templateE" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Types.I#"- , "type" : "I# :: Int# -> Int"- , "templateE" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Types.W#"- , "type" : "W# :: Word# -> Word"- , "templateE" : "~ARG[0]"- }- }-]
− prims/verilog/GHC_Word.json
@@ -1,25 +0,0 @@-[ { "BlackBox" :- { "name" : "GHC.Word.W8#"- , "type" : "W8# :: Word# -> Word8"- , "templateD" : "assign ~RESULT = $unsigned(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Word.W16#"- , "type" : "W16# :: Word# -> Word16"- , "templateD" : "assign ~RESULT = $unsigned(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Word.W32#"- , "type" : "W32# :: Word# -> Word32"- , "templateD" : "assign ~RESULT = $unsigned(~ARG[0]);"- }- }-, { "BlackBox" :- { "name" : "GHC.Word.W64#"- , "type" : "W64# :: Word# -> Word64"- , "templateD" : "assign ~RESULT = $unsigned(~ARG[0]);"- }- }-]
+ prims/vhdl/Clash_Class_Exp.json view
@@ -0,0 +1,29 @@+[+ {+ "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.json view
@@ -1,96 +1,199 @@ [ { "BlackBox" : { "name" : "Clash.Explicit.BlockRam.blockRam#"+ , "kind" : "Declaration" , "type" : "blockRam#- :: HasCallStack -- ARG[0]- => Clock dom gated -- clk, ARG[1]- -> Vec n a -- init, ARG[2]- -> Signal dom Int -- rd, ARG[3]- -> Signal dom Bool -- wren, ARG[4]- -> Signal dom Int -- wr, ARG[5]- -> Signal dom a -- din, ARG[6]+ :: ( 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"- , "templateD" :+ , "template" : "-- blockRam begin-~GENSYM[~COMPNAME_blockRam][0] : block- signal ~GENSYM[RAM][1] : ~TYP[2] := ~LIT[2];- signal ~GENSYM[rd][3] : integer range 0 to ~LENGTH[~TYP[2]] - 1;- signal ~GENSYM[wr][4] : integer range 0 to ~LENGTH[~TYP[2]] - 1;~IF ~ISGATED[1] ~THEN- signal ~GENSYM[clk][5] : std_logic;- signal ~GENSYM[ce][6] : boolean;~ELSE ~FI+~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[3] <= to_integer(~ARG[3])+ ~SYM[4] <= to_integer(~ARG[6]) -- pragma translate_off- mod ~LENGTH[~TYP[2]]+ mod ~LENGTH[~TYP[5]] -- pragma translate_on ; - ~SYM[4] <= to_integer(~ARG[5])+ ~SYM[5] <= to_integer(~ARG[8]) -- pragma translate_off- mod ~LENGTH[~TYP[2]]+ mod ~LENGTH[~TYP[5]] -- pragma translate_on ;-~IF ~VIVADO ~THEN ~IF ~ISGATED[1] ~THEN- (~SYM[5],~SYM[6]) <= ~ARG[1];- ~GENSYM[blockRam_sync][7] : process(~SYM[5])+~IF ~VIVADO ~THEN+ ~SYM[6] : process(~ARG[3]) begin- if rising_edge(~SYM[5]) then- if ~SYM[6] then- if ~ARG[4] then- ~SYM[1](~SYM[4]) <= ~TOBV[~ARG[6]][~TYP[6]];- end if;- ~RESULT <= fromSLV(~SYM[1](~SYM[3]))- -- pragma translate_off- after 1 ps- -- pragma translate_on- ;+ 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]))+ -- pragma translate_off+ after 1 ps+ -- pragma translate_on+ ; end if;- end process;~ELSE- ~SYM[7] : process(~ARG[1])+ end process; ~ELSE+ ~SYM[6] : process(~ARG[3]) begin- if rising_edge(~ARG[1]) then- if ~ARG[4] then- ~SYM[1](~SYM[4]) <= ~TOBV[~ARG[6]][~TYP[6]];+ 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 <= fromSLV(~SYM[1](~SYM[3]))+ ~RESULT <= ~SYM[2](~SYM[4]) -- pragma translate_off after 1 ps -- pragma translate_on ; end if;- end process;~FI ~ELSE ~IF ~ISGATED[1] ~THEN- (~SYM[5],~SYM[6]) <= ~ARG[1];- ~SYM[7] : process(~SYM[5])+ 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+ type ~GENSYM[ram_t][8] is array (0 to integer'(~LIT[5])-1) of ~TYP[9];+ 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 rising_edge(~SYM[5]) then- if ~ARG[4] and ~SYM[6] then- ~SYM[1](~SYM[4]) <= ~ARG[6];+ 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;- if ~SYM[6] then- ~RESULT <= ~SYM[1](~SYM[3])- -- pragma translate_off- after 1 ps- -- pragma translate_on- ;+ ~RESULT <= fromSLV(~SYM[2](~SYM[4]))+ -- pragma translate_off+ after 1 ps+ -- pragma translate_on+ ;+ 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])+ -- pragma translate_off+ after 1 ps+ -- pragma translate_on+ ; end if;- end process;~ELSE- ~SYM[7] : process(~ARG[1])+ 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+ type ~GENSYM[ram_t][8] is array (0 to integer'(~LIT[5])-1) of ~TYP[6];+ signal ~GENSYM[~RESULT_RAM][2] : ~SYM[8] := (others => ~CONST[6]);+ 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 rising_edge(~ARG[1]) then- if ~ARG[4] then- ~SYM[1](~SYM[4]) <= ~ARG[6];+ 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 <= ~SYM[1](~SYM[3])+ ~RESULT <= fromSLV(~SYM[2](~SYM[4])) -- pragma translate_off after 1 ps -- pragma translate_on ; end if;- end process;~FI ~FI+ 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])+ -- pragma translate_off+ after 1 ps+ -- pragma translate_on+ ;+ end if;+ end process; ~FI end block;---end blockRam"+--end blockRam1" } } ]
prims/vhdl/Clash_Explicit_BlockRam_File.json view
@@ -1,25 +1,29 @@ [ { "BlackBox" : { "name" : "Clash.Explicit.BlockRam.File.blockRamFile#"+ , "kind" : "Declaration" , "type" : "blockRamFile#- :: (KnownNat m, HasCallStack)-- (ARG[0],ARG]1)- => Clock dom gated -- clk, ARG[2]- -> SNat n -- sz, ARG[3]- -> FilePath -- file, ARG[4]- -> Signal dom Int -- rd, ARG[5]- -> Signal dom Bool -- wren, ARG[6]- -> Signal dom Int -- wr, ARG[7]- -> Signal dom (BitVector m) -- din, ARG[8]+ :: ( 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)"- , "templateD" :+ , "template" : "-- blockRamFile begin-~GENSYM[~COMPNAME_blockRamFile][0] : block- type ~GENSYM[RamType][6] is array(natural range <>) of bit_vector(~LIT[0]-1 downto 0);+~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][1] (RamFileName : in string) return ~SYM[6] is+ 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[6](0 to ~LIT[3]-1);+ variable RAM : ~SYM[7](0 to ~LIT[5]-1); begin for i in RAM'range loop readline(RamFile,RamFileLine);@@ -28,33 +32,30 @@ return RAM; end function; - signal ~GENSYM[RAM][2] : ~SYM[6](0 to ~LIT[3]-1) := ~SYM[1](~FILE[~LIT[4]]);- signal ~GENSYM[rd][4] : integer range 0 to ~LIT[3]-1;- signal ~GENSYM[wr][5] : integer range 0 to ~LIT[3]-1;~IF ~ISGATED[2] ~THEN- signal ~GENSYM[clk][7] : std_logic;- signal ~GENSYM[ce][8] : boolean;~ELSE ~FI+ 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[4] <= to_integer(~ARG[5])+ ~SYM[5] <= to_integer(~ARG[7]) -- pragma translate_off- mod ~LIT[3]+ mod ~LIT[5] -- pragma translate_on ; - ~SYM[5] <= to_integer(~ARG[7])+ ~SYM[6] <= to_integer(~ARG[9]) -- pragma translate_off- mod ~LIT[3]+ mod ~LIT[5] -- pragma translate_on ;- ~IF ~VIVADO ~THEN ~IF ~ISGATED[2] ~THEN- (~SYM[7],~SYM[8]) <= ~ARG[2];- ~GENSYM[blockRamFile_sync][9] : process(~SYM[7])+ ~IF ~VIVADO ~THEN ~IF ~ISACTIVEENABLE[4] ~THEN+ ~GENSYM[blockRamFile_sync][10] : process(~ARG[3]) begin- if rising_edge(~SYM[7]) then- if ~SYM[8] then- if ~ARG[6] then- ~SYM[2](~SYM[5]) <= to_bitvector(~ARG[8]);+ 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[2](~SYM[4]))+ ~RESULT <= to_stdlogicvector(~SYM[3](~SYM[5])) -- pragma translate_off after 1 ps -- pragma translate_on@@ -62,28 +63,27 @@ end if; end if; end process;~ELSE- ~SYM[9] : process(~ARG[2])+ ~SYM[10] : process(~ARG[3]) begin- if rising_edge(~ARG[2]) then- if ~ARG[6] then- ~SYM[2](~SYM[5]) <= to_bitvector(~ARG[8]);+ 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[2](~SYM[4]))+ ~RESULT <= to_stdlogicvector(~SYM[3](~SYM[5])) -- pragma translate_off after 1 ps -- pragma translate_on ; end if;- end process;~FI ~ELSE ~IF ~ISGATED[2] ~THEN- (~SYM[7],~SYM[8]) <= ~ARG[2];- ~SYM[9] : process(~SYM[7])+ end process;~FI ~ELSE ~IF ~ISACTIVEENABLE[4] ~THEN+ ~SYM[10] : process(~ARG[3]) begin- if rising_edge(~SYM[7]) then- if ~ARG[6] and ~SYM[8] then- ~SYM[2](~SYM[5]) <= to_bitvector(~ARG[8]);+ 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 ~SYM[8] then- ~RESULT <= to_stdlogicvector(~SYM[2](~SYM[4]))+ if ~ARG[4] then+ ~RESULT <= to_stdlogicvector(~SYM[3](~SYM[5])) -- pragma translate_off after 1 ps -- pragma translate_on@@ -91,13 +91,13 @@ end if; end if; end process;~ELSE- ~SYM[9] : process(~ARG[2])+ ~SYM[10] : process(~ARG[3]) begin- if rising_edge(~ARG[2]) then- if ~ARG[6] then- ~SYM[2](~SYM[5]) <= to_bitvector(~ARG[8]);+ 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[2](~SYM[4]))+ ~RESULT <= to_stdlogicvector(~SYM[3](~SYM[5])) -- pragma translate_off after 1 ps -- pragma translate_on
prims/vhdl/Clash_Explicit_DDR.json view
@@ -1,290 +1,164 @@ [ { "BlackBox" : { "name" : "Clash.Explicit.DDR.ddrIn#"+ , "kind" : "Declaration" , "type" :-"ddrIn# :: forall a slow fast n pFast gated synchronous.- ( HasCallStack -- ARG[0]- , fast ~ Dom n pFast -- ARG[1]- , slow ~ Dom n (2*pFast)) -- ARG[2]- => Clock slow gated -- ARG[3]- -> Reset slow synchronous -- ARG[4]- -> a -- ARG[5]- -> a -- ARG[6]- -> a -- ARG[7]- -> Signal fast a -- ARG[8]+"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)"- , "templateD" :+ , "template" : "-- ddrIn begin ~GENSYM[~COMPNAME_ddrIn][0] : block- signal ~GENSYM[data_Pos][1] : ~TYP[8];- signal ~GENSYM[data_Neg][2] : ~TYP[8];- signal ~GENSYM[data_Neg_Latch][3] : ~TYP[8];-~IF ~ISGATED[3] ~THEN- signal ~GENSYM[clk][4] : std_logic;- signal ~GENSYM[ce][5] : boolean;-~ELSE ~FI+ signal ~GENSYM[data_Pos][1] : ~TYP[9];+ signal ~GENSYM[data_Neg][2] : ~TYP[9];+ signal ~GENSYM[data_Neg_Latch][3] : ~TYP[9]; begin-~IF ~ISGATED[3] ~THEN- ~IF ~ISSYNC[4] ~THEN- -- gated sync+ ~IF ~ISSYNC[3] ~THEN+ -- sync -------------- ~GENSYM[~COMPNAME_ddrIn_pos][6] : process(~SYM[4])+ ~GENSYM[~COMPNAME_ddrIn_pos][6] : process(~ARG[4]) begin- if rising_edge(~SYM[4]) then- if ~ARG[4] = '1' then- ~SYM[1] <= ~ARG[6];- elsif ~SYM[5] then+ 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(~SYM[4])+ ~GENSYM[~COMPNAME_ddrIn_neg][7] : process(~ARG[4]) begin- if falling_edge(~SYM[4]) then- if ~ARG[4] = '1' then- ~SYM[2] <= ~ARG[7];- elsif ~SYM[5] then- ~SYM[2] <= ~ARG[8];+ 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(~SYM[4])+ ~GENSYM[~COMPNAME_ddrIn_neg_latch][8] : process(~ARG[4]) begin- if rising_edge(~SYM[4]) then- if ~ARG[4] = '1' then- ~SYM[3] <= ~ARG[5];- elsif ~SYM[5] then+ 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- -- gated async+ -- async --------------- ~SYM[6] : process(~SYM[4],~ARG[4]~VARS[8])- begin- if ~ARG[4] = '1' then- ~SYM[1] <= ~ARG[6];- elsif ~SYM[5] and rising_edge(~SYM[4]) then- ~SYM[1] <= ~ARG[8];- end if;- end process;-- ~SYM[7] : process(~SYM[4],~ARG[4]~VARS[8])- begin- if ~ARG[4] = '1' then- ~SYM[2] <= ~ARG[7];- elsif ~SYM[5] and falling_edge(~SYM[4]) then- ~SYM[2] <= ~ARG[8];- end if;- end process;-- ~SYM[8] : process(~SYM[4],~ARG[4],~SYM[2])- begin- if ~ARG[4] = '1' then- ~SYM[3] <= ~ARG[5];- elsif ~SYM[5] and rising_edge(~SYM[4]) then- ~SYM[3] <= ~SYM[2];- end if;- end process;- ~FI-~ELSE- ~IF ~ISSYNC[4] ~THEN- -- ungated sync- ---------------- ~SYM[6] : process(~ARG[3])- begin- if rising_edge(~ARG[3]) then- if ~ARG[4] = '1' then- ~SYM[1] <= ~ARG[6];- else- ~SYM[1] <= ~ARG[8];- end if;- end if;- end process;-- ~SYM[7] : process(~ARG[3])- begin- if falling_edge(~ARG[3]) then- if ~ARG[4] = '1' then- ~SYM[2] <= ~ARG[7];- else- ~SYM[2] <= ~ARG[8];- end if;- end if;- end process;-- ~SYM[8] : process(~ARG[3])- begin- if rising_edge(~ARG[3]) then- if ~ARG[4] = '1' then- ~SYM[3] <= ~ARG[5];- else- ~SYM[3] <= ~SYM[2];- end if;- end if;- end process;- ~ELSE- -- ungated async- ----------------- ~SYM[6] : process(~ARG[3],~ARG[4]~VARS[8])+ ~SYM[6] : process(~ARG[4],~ARG[5]~VARS[9]) begin- if ~ARG[4] = '1' then- ~SYM[1] <= ~ARG[6];- elsif rising_edge(~ARG[3]) then+ 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[3],~ARG[4]~VARS[8])+ ~SYM[7] : process(~ARG[4],~ARG[5]~VARS[9]) begin- if ~ARG[4] = '1' then- ~SYM[2] <= ~ARG[7];- elsif falling_edge(~ARG[3]) then- ~SYM[2] <= ~ARG[8];+ 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[3],~ARG[4],~SYM[2])+ ~SYM[8] : process(~ARG[4],~ARG[5],~SYM[2]) begin- if ~ARG[4] = '1' then- ~SYM[3] <= ~ARG[5];- elsif rising_edge(~ARG[3]) then+ 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-~FI ~RESULT <= (~SYM[3], ~SYM[1]);-~IF ~ISGATED[3] ~THEN- (~SYM[4],~SYM[5]) <= ~ARG[3];-~ELSE ~FI end block; -- ddrIn end" } } , { "BlackBox" : { "name" : "Clash.Explicit.DDR.ddrOut#"+ , "kind" : "Declaration" , "type" : "ddrOut# :: ( HasCallStack -- ARG[0]- , fast ~ Dom n pFast -- ARG[1]- , slow ~ Dom n (2*pFast)) -- ARG[2]- => Clock slow gated -- ARG[3]- -> Reset slow synchronous -- ARG[4]- -> a -- ARG[5]- -> Signal slow a -- ARG[6]- -> Signal slow a -- ARG[7]+ , 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"- , "templateD" :+ , "template" : "-- ddrOut begin ~GENSYM[~COMPNAME_ddrIn][0] : block- signal ~GENSYM[data_Pos][1] : ~TYP[5];- signal ~GENSYM[data_Neg][2] : ~TYP[5];-~IF ~ISGATED[3] ~THEN- signal ~GENSYM[clk][3] : std_logic;- signal ~GENSYM[ce][4] : boolean;-~ELSE ~FI+ signal ~GENSYM[data_Pos][1] : ~TYP[7];+ signal ~GENSYM[data_Neg][2] : ~TYP[7]; begin-~IF ~ISGATED[3] ~THEN- ~IF ~ISSYNC[4] ~THEN- -- gated sync+ ~IF ~ISSYNC[3] ~THEN+ -- sync -------------- ~GENSYM[~COMPNAME_ddrOut_pos][5] : process(~SYM[3])+ ~GENSYM[~COMPNAME_ddrOut_pos][5] : process(~ARG[4]) begin- if rising_edge(~SYM[3]) then- if ~ARG[4] = '1' then- ~SYM[1] <= ~ARG[5];- elsif ~SYM[4] then- ~SYM[1] <= ~ARG[6];+ 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(~SYM[3])+ ~GENSYM[~COMPNAME_ddrOut_neg][6] : process(~ARG[4]) begin- if rising_edge(~SYM[3]) then- if ~ARG[4] = '1' then- ~SYM[2] <= ~ARG[5];- elsif ~SYM[4] then+ 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- -- gated async+ -- async --------------- ~SYM[5] : process(~SYM[3],~ARG[4]~VARS[6])- begin- if ~ARG[4] = '1' then- ~SYM[1] <= ~ARG[5];- elsif rising_edge(~SYM[3]) then- ~SYM[1] <= ~ARG[6];- end if;- end process;-- ~SYM[6] : process(~SYM[3],~ARG[4]~VARS[7])- begin- if ~ARG[4] = '1' then- ~SYM[2] <= ~ARG[5];- elsif rising_edge(~SYM[3]) then- ~SYM[2] <= ~ARG[7];- end if;- end process;- ~FI-~ELSE- ~IF ~ISSYNC[4] ~THEN- -- ungated sync- ---------------- ~SYM[5] : process(~ARG[3])- begin- if rising_edge(~ARG[3]) then- if ~ARG[4] = '1' then- ~SYM[1] <= ~ARG[5];- else- ~SYM[1] <= ~ARG[6];- end if;- end if;- end process;-- ~SYM[6] : process(~ARG[3])- begin- if rising_edge(~ARG[3]) then- if ~ARG[4] = '1' then- ~SYM[2] <= ~ARG[5];- else- ~SYM[2] <= ~ARG[7];- end if;- end if;- end process;- ~ELSE- -- ungated async- ----------------- ~SYM[5] : process(~ARG[3],~ARG[4]~VARS[6])+ ~SYM[5] : process(~ARG[4],~ARG[5]~VARS[8]) begin- if ~ARG[4] = '1' then- ~SYM[1] <= ~ARG[5];- elsif rising_edge(~ARG[3]) then- ~SYM[1] <= ~ARG[6];+ 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[3],~ARG[4]~VARS[7])+ ~SYM[6] : process(~ARG[4],~ARG[5]~VARS[9]) begin- if ~ARG[4] = '1' then- ~SYM[2] <= ~ARG[5];- elsif rising_edge(~ARG[3]) then+ 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-~FI-~IF ~ISGATED[3] ~THEN- (~SYM[3],~SYM[4]) <= ~ARG[3];- ~RESULT <= ~SYM[1] when (~SYM[3] = '1' and ~SYM[4]) else ~SYM[2];-~ELSE- ~RESULT <= ~SYM[1] when (~ARG[3] = '1') else ~SYM[2];-~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.json view
@@ -1,60 +1,51 @@ [ { "BlackBox" : { "name" : "Clash.Explicit.RAM.asyncRam#"+ , "kind" : "Declaration" , "type" : "asyncRam#- :: HasCallStack -- ARG[0]- => Clock wdom wgated -- ^ wclk, ARG[1]- -> Clock rdom rgated -- ^ rclk, ARG[2]- -> SNat n -- ^ sz, ARG[3]- -> Signal rdom Int -- ^ rd, ARG[4]- -> Signal wdom Bool -- ^ en, ARG[5]- -> Signal wdom Int -- ^ wr, ARG[6]- -> Signal wdom a -- ^ din, ARG[7]+ :: ( 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"- , "templateD" :+ , "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[7]]-1 downto 0);~ELSE- type ~SYM[4] is array(natural range <>) of ~TYP[7];~FI- signal ~GENSYM[RAM][1] : ~SYM[4](0 to ~LIT[3]-1);- signal ~GENSYM[rd][2] : integer range 0 to ~LIT[3] - 1;- signal ~GENSYM[wr][3] : integer range 0 to ~LIT[3] - 1;~IF ~ISGATED[1] ~THEN- signal ~GENSYM[clk][5] : std_logic;- signal ~GENSYM[ce][6] : boolean;~ELSE ~FI+ 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[4])+ ~SYM[2] <= to_integer(~ARG[7]) -- pragma translate_off- mod ~LIT[3]+ mod ~LIT[6] -- pragma translate_on ; - ~SYM[3] <= to_integer(~ARG[6])+ ~SYM[3] <= to_integer(~ARG[9]) -- pragma translate_off- mod ~LIT[3]+ mod ~LIT[6] -- pragma translate_on ;- ~IF ~ISGATED[1] ~THEN- (~SYM[5],~SYM[6]) <= ~ARG[1];- ~GENSYM[asyncRam_sync][7] : process(~SYM[5])- begin- if rising_edge(~SYM[5]) then- if (~ARG[5] and ~SYM[6]) then~IF ~VIVADO ~THEN- ~SYM[1](~SYM[3]) <= ~TOBV[~ARG[7]][~TYP[7]];~ELSE- ~SYM[1](~SYM[3]) <= ~ARG[7];~FI- end if;- end if;- end process;~ELSE- ~SYM[7] : process(~ARG[1])+ ~GENSYM[asyncRam_sync][7] : process(~ARG[3]) begin- if rising_edge(~ARG[1]) then- if ~ARG[5] then~IF ~VIVADO ~THEN- ~SYM[1](~SYM[3]) <= ~TOBV[~ARG[7]][~TYP[7]];~ELSE- ~SYM[1](~SYM[3]) <= ~ARG[7];~FI+ 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;~FI+ end process; ~IF ~VIVADO ~THEN- ~RESULT <= ~FROMBV[~SYM[1](~SYM[2])][~TYP[7]];~ELSE+ ~RESULT <= ~FROMBV[~SYM[1](~SYM[2])][~TYP[10]];~ELSE ~RESULT <= ~SYM[1](~SYM[2]);~FI end block; -- asyncRam end"
prims/vhdl/Clash_Explicit_ROM.json view
@@ -1,60 +1,43 @@ [ { "BlackBox" : { "name" : "Clash.Explicit.ROM.rom#"+ , "kind" : "Declaration" , "type" :-"rom# :: KnownNat n -- ARG[0]- => Clock dom gated -- clk, ARG[1]- -> Vec n a -- init, ARG[2]- -> Signal dom Int -- rd, ARG[3]+"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"- , "templateD" :+ , "template" : "-- rom begin-~GENSYM[~COMPNAME_rom][0] : block- signal ~GENSYM[ROM][1] : ~TYP[2];- signal ~GENSYM[rd][2] : integer range 0 to ~LIT[0]-1;~IF ~ISGATED[1] ~THEN- signal ~GENSYM[clk][3] : std_logic;- signal ~GENSYM[ce][4] : boolean;~ELSE ~FI+~GENSYM[~COMPNAME_rom][1] : block+ signal ~GENSYM[ROM][2] : ~TYP[5];+ signal ~GENSYM[rd][3] : integer range 0 to ~LIT[1]-1; begin- ~SYM[1] <= ~ARG[2];+ ~SYM[2] <= ~LIT[5]; - ~SYM[2] <= to_integer(~ARG[3])+ ~SYM[3] <= to_integer(~ARG[6]) -- pragma translate_off- mod ~LIT[0]+ mod ~LIT[1] -- pragma translate_on ;- ~IF ~ISGATED[1] ~THEN- (~SYM[3],~SYM[4]) <= ~ARG[1];- ~GENSYM[romSync][5] : process (~SYM[3])- begin- if (rising_edge(~SYM[3])) then- if ~SYM[4] then~IF ~VIVADO ~THEN- ~RESULT <= ~FROMBV[~SYM[1](~SYM[2])][~TYPO]- -- pragma translate_off- after 1 ps- -- pragma translate_on- ;~ELSE- ~RESULT <= ~SYM[1](~SYM[2])- -- pragma translate_off- after 1 ps- -- pragma translate_on- ;~FI- end if;- end if;- end process;~ELSE- ~SYM[5] : process (~ARG[1])+ ~GENSYM[romSync][6] : process (~ARG[3]) begin- if (rising_edge(~ARG[1])) then~IF ~VIVADO ~THEN- ~RESULT <= ~FROMBV[~SYM[1](~SYM[2])][~TYPO]+ 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] -- pragma translate_off after 1 ps -- pragma translate_on ;~ELSE- ~RESULT <= ~SYM[1](~SYM[2])+ ~RESULT <= ~SYM[2](~SYM[3]) -- pragma translate_off after 1 ps -- pragma translate_on ;~FI end if;- end process;~FI+ end process; end block; -- rom end" }
prims/vhdl/Clash_Explicit_ROM_File.json view
@@ -1,13 +1,16 @@ [ { "BlackBox" : { "name" : "Clash.Explicit.ROM.File.romFile#"+ , "kind" : "Declaration" , "type" :-"romFile# :: KnownNat m -- ARG[0]- => Clock dom gated -- clk, ARG[1]- -> SNat n -- sz, ARG[2]- -> FilePath -- file, ARG[3]- -> Signal dom Int -- rd, ARG[4]+"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)"- , "templateD" :+ , "template" : "-- romFile begin ~GENSYM[~COMPNAME_romFile][0] : block type ~GENSYM[RomType][4] is array(natural range <>) of bit_vector(~LIT[0]-1 downto 0);@@ -15,7 +18,7 @@ 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[2]-1);+ variable ROM : ~SYM[4](0 to ~LIT[4]-1); begin for i in ROM'range loop readline(RomFile,RomFileLine);@@ -24,22 +27,19 @@ return ROM; end function; - signal ~GENSYM[ROM][2] : ~SYM[4](0 to ~LIT[2]-1) := ~SYM[1](~FILE[~LIT[3]]);- signal ~GENSYM[rd][3] : integer range 0 to ~LIT[2]-1;~IF ~ISGATED[1] ~THEN- signal ~GENSYM[clk][5] : std_logic;- signal ~GENSYM[ce][6] : boolean; ~ELSE ~FI+ 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[4])+ ~SYM[3] <= to_integer(~ARG[6]) -- pragma translate_off- mod ~LIT[2]+ mod ~LIT[4] -- pragma translate_on ;- ~IF ~ISGATED[1] ~THEN- (~SYM[5],~SYM[6]) <= ~ARG[1];- ~GENSYM[romFileSync][7] : process (~SYM[5])+ ~IF ~ISACTIVEENABLE[3] ~THEN+ ~GENSYM[romFileSync][7] : process (~ARG[2]) begin- if (rising_edge(~SYM[5])) then- if ~SYM[6] then+ if (~IF~ACTIVEEDGE[Rising][1]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2])) then+ if ~ARG[3] then ~RESULT <= to_stdlogicvector(~SYM[2](~SYM[3])) -- pragma translate_off after 1 ps@@ -48,9 +48,9 @@ end if; end if; end process;~ELSE- ~SYM[7] : process (~ARG[1])+ ~SYM[7] : process (~ARG[2]) begin- if (rising_edge(~ARG[1])) then+ if (~IF~ACTIVEEDGE[Rising][1]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2])) then ~RESULT <= to_stdlogicvector(~SYM[2](~SYM[3])) -- pragma translate_off after 1 ps
prims/vhdl/Clash_Explicit_Testbench.json view
@@ -1,20 +1,120 @@ [ { "BlackBox" : { "name" : "Clash.Explicit.Testbench.assert"+ , "kind" : "Declaration" , "type" : "assert- :: (Eq a,Show a) -- (ARG[0],ARG[1])- => Clock domain gated -- ARG[2]- -> Reset domain synchronous -- ARG[3]- -> String -- ARG[4]- -> Signal domain a -- Checked value (ARG[5])- -> Signal domain a -- Expected value (ARG[6])- -> Signal domain b -- Return valued (ARG[7])- -> Signal domain b"- , "templateD" :+ :: (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- function ~GENSYM[slv2string][1] (slv : std_logic_vector) return STRING is+ 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;@@ -26,31 +126,32 @@ r := r + 1; end loop; return result;- end;+ 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];-~IF ~ISGATED[2] ~THEN- signal ~GENSYM[clk][4] : std_logic;- signal ~GENSYM[ce][5] : boolean;-~ELSE ~FI -- pragma translate_on begin -- pragma translate_off ~SYM[2] <= ~ARG[5]; ~SYM[3] <= ~ARG[6];- process(~IF ~ISGATED[2] ~THEN~SYM[4]~ELSE~ARG[2]~FI~IF ~ISSYNC[3] ~THEN ~ELSE,~ARG[3]~FI) is+ process(~ARG[2]) is begin- if (rising_edge(~IF ~ISGATED[2] ~THEN~SYM[4]~ELSE~ARG[2]~FI)~IF ~ISSYNC[3] ~THEN ~ELSE or falling_edge(~ARG[3])~FI) then- assert (std_match(toSLV(~SYM[2]),toSLV(~SYM[3]))) report (~LIT[4] & \", expected: \" & ~SYM[1](toSLV(~SYM[3])) & \", actual: \" & ~SYM[1](toSLV(~SYM[2]))) severity error;+ 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-~IF ~ISGATED[2] ~THEN- (~SYM[4],~SYM[5]) <= ~ARG[2];-~ELSE ~FI ~RESULT <= ~ARG[7]; end block;--- assert end"+-- assertBitVector end" } } ]
− prims/vhdl/Clash_Intel_ClockGen.json
@@ -1,59 +0,0 @@-[ { "BlackBox" :- { "name" : "Clash.Intel.ClockGen.altpll"- , "type" :-"altpll- :: SSymbol name -- ARG[0]- -> Clock pllIn 'Source -- ARG[1]- -> Reset pllIn 'Asynchronous -- ARG[2]- -> (Clock pllOut 'Source, Signal pllOut Bool)"- , "templateD" :-"-- altpll begin-~GENSYM[altpll][0] : block- signal ~GENSYM[pllOut][1] : std_logic;- signal ~GENSYM[locked][2] : std_logic;- signal ~GENSYM[pllLock][3] : boolean;-- component ~NAME[0]- port (inclk0 : in std_logic;- areset : in std_logic;- c0 : out std_logic;- locked : out std_logic);- end component;-begin- ~GENSYM[altpll_inst][4] : component ~NAME[0] port map (~ARG[1],~ARG[2],~SYM[1],~SYM[2]);- ~SYM[3] <= true when ~SYM[2] = '1' else false;- ~RESULT <= (~SYM[1],~SYM[3]);-end block;--- altpll end"- }- }-, { "BlackBox" :- { "name" : "Clash.Intel.ClockGen.alteraPll"- , "type" :-"alteraPll- :: SSymbol name -- ARG[0]- -> Clock pllIn 'Source -- ARG[1]- -> Reset pllIn 'Asynchronous -- ARG[2]- -> (Clock pllOut 'Source, Signal pllOut Bool)"- , "templateD" :-"-- alteraPll begin-~GENSYM[alteraPll][0] : block- signal ~GENSYM[pllOut][1] : std_logic;- signal ~GENSYM[locked][2] : std_logic;- signal ~GENSYM[pllLock][3] : boolean;-- component ~NAME[0]- port (refclk : in std_logic;- rst : in std_logic;- outclk_0 : out std_logic;- locked : out std_logic);- end component;-begin- ~GENSYM[alteraPll_inst][4] : component ~NAME[0] port map (~ARG[1],~ARG[2],~SYM[1],~SYM[2]);- ~SYM[3] <= true when ~SYM[2] = '1' else false;- ~RESULT <= (~SYM[1],~SYM[3]);-end block;--- alteraPll end"- }- }-]
prims/vhdl/Clash_Intel_DDR.json view
@@ -1,29 +1,28 @@ [ { "BlackBox" : { "name" : "Clash.Intel.DDR.altddioIn"+ , "kind" : "Declaration" , "type" : "altddioIn :: ( HasCallStack -- ARG[0]- , fast ~ Dom n pFast -- ARG[1]- , slow ~ Dom n (2*pFast) -- ARG[2]+ , KnownConfi~ fast domf -- ARG[1]+ , KnownConfi~ slow doms -- ARG[2] , KnownNat m ) -- ARG[3] => SSymbol deviceFamily -- ARG[4]- -> Clock slow gated -- ARG[5]- -> Reset slow synchronous -- ARG[6]- -> Signal fast (BitVector m) -- ARG[7]+ -> 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"]- , "templateD" :+ , "template" : "-- altddioIn begin ~GENSYM[~COMPNAME_ALTDDIO_IN][0] : block- signal ~GENSYM[dataout_l][1] : ~TYP[7];- signal ~GENSYM[dataout_h][2] : ~TYP[7];~IF ~ISGATED[5] ~THEN- signal ~GENSYM[clk][4] : std_logic;- signal ~GENSYM[ce][5] : boolean;- signal ~GENSYM[ce_logic][6]: std_logic;~ELSE ~FI-begin~IF ~ISGATED[5] ~THEN- (~SYM[4],~SYM[5]) <= ~ARG[5];- ~SYM[6] <= '1' when (~SYM[5]) else '0';~ELSE ~FI+ 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],@@ -31,15 +30,14 @@ lpm_hint => \"UNUSED\", lpm_type => \"altddio_in\", power_up_high => \"OFF\",- width => ~SIZE[~TYP[7]]+ width => ~SIZE[~TYP[8]] ) PORT MAP (~IF ~ISSYNC[6] ~THEN sclr => ~ARG[6],~ELSE aclr => ~ARG[6],~FI- datain => ~ARG[7],~IF ~ISGATED[5] ~THEN- inclock => ~SYM[4],- inclocken => ~SYM[6],~ELSE- inclock => ~ARG[5],~FI+ datain => ~ARG[8],~IF ~ISACTIVEENABLE[5] ~THEN+ inclocken => ~SYM[4],~ELSE ~FI+ inclock => ~ARG[5], dataout_h => ~SYM[2], dataout_l => ~SYM[1] );@@ -50,29 +48,28 @@ } , { "BlackBox" : { "name" : "Clash.Intel.DDR.altddioOut#"+ , "kind" : "Declaration" , "type" : "altddioOut# :: ( HasCallStack -- ARG[0]- , fast ~ Dom n pFast -- ARG[1]- , slow ~ Dom n (2*pFast) -- ARG[2]+ , KnownConfi~ fast domf -- ARG[1]+ , KnownConfi~ slow doms -- ARG[2] , KnownNat m ) -- ARG[3] => SSymbol deviceFamily -- ARG[4]- -> Clock slow gated -- ARG[5]- -> Reset slow synchronous -- ARG[6]- -> Signal slow (BitVector m) -- ARG[7]+ -> 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"]- , "templateD" :+ , "template" : "-- altddioOut begin-~GENSYM[~COMPNAME_ALTDDIO_OUT][0] : block ~IF ~ISGATED[5] ~THEN- signal ~GENSYM[clk][1] : std_logic;- signal ~GENSYM[ce][2] : boolean;- signal ~GENSYM[ce_logic][3] : std_logic; ~ELSE ~FI-begin~IF ~ISGATED[5] ~THEN- (~SYM[1],~SYM[2]) <= ~ARG[5];- ~SYM[3] <= '1' when (~SYM[2]) else '0'; ~ELSE ~FI+~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\",@@ -84,12 +81,11 @@ power_up_high => \"OFF\", width => ~SIZE[~TYPO] )- PORT MAP (~IF ~ISSYNC[6] ~THEN+ PORT MAP (~IF ~ISSYNC[2] ~THEN sclr => ~ARG[6],~ELSE- aclr => ~ARG[6],~FI ~IF ~ISGATED[5] ~THEN- outclock => ~SYM[1],- outclocken => ~SYM[3],~ELSE- outclock => ~ARG[5],~FI+ 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
prims/vhdl/Clash_Prelude_ROM.json view
@@ -1,17 +1,18 @@ [ { "BlackBox" : { "name" : "Clash.Prelude.ROM.asyncRom#"+ , "kind" : "Declaration" , "type" : "asyncRom# :: KnownNat n -- ^ ARG[0] => Vec n a -- ^ ARG[1] -> Int -- ^ ARG[2] -> a"- , "templateD" :+ , "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] <= ~ARG[1];+ ~SYM[1] <= ~LIT[1]; ~SYM[2] <= to_integer(~ARG[2]) -- pragma translate_off
prims/vhdl/Clash_Prelude_ROM_File.json view
@@ -1,12 +1,13 @@ [ { "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"- , "templateD" :+ , "template" : "-- asyncRomFile begin ~GENSYM[asyncROMFile][0] : block type ~GENSYM[RomType][4] is array(natural range <>) of bit_vector(~LIT[0]-1 downto 0);
prims/vhdl/Clash_Promoted_Nat.json view
@@ -1,34 +1,34 @@ [ { "BlackBox" :- { "name" : "Clash.Promoted.Nat.powSNat"- , "type" : "Clash.Promoted.Nat.powSNat :: SNat a -> SNat b -> SNat (a^b)"- , "templateE" : "~LIT[0] ** ~LIT[1]"- }- }-, { "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)"- , "templateE" : "integer(floor(log(real(~LIT[3]),real(~LIT[2]))))"+ , "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)"- , "templateE" : "integer(ceiling(log(real(~LIT[3]),real(~LIT[2]))))"+ , "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)"- , "templateE" : "integer(ceiling(log(real(~LIT[2]),real(~LIT[1]))))"+ , "template" : "integer(ceiling(log(real(~LIT[2]),real(~LIT[1]))))" } } ]
+ prims/vhdl/Clash_Signal_BiSignal.json view
@@ -0,0 +1,34 @@+[ { "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",+ "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_Internal.json view
@@ -1,23 +1,26 @@ [ { "BlackBox" : { "name" : "Clash.Signal.Internal.delay#"+ , "kind" : "Declaration" , "type" :-"register#- :: HasCallStack -- ARG[0]- => Clock domain gated -- ARG[1]- -> Signal clk a -- ARG[2]+"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"- , "templateD" :-"-- register begin~IF ~ISGATED[1] ~THEN-~GENSYM[~COMPNAME_delay][0] : block- signal ~GENSYM[clk][1] : std_logic;- signal ~GENSYM[ce][2] : boolean;+ , "template" :+"-- delay begin~IF ~ISACTIVEENABLE[3] ~THEN+~GENSYM[~RESULT_delay][0] : block+ signal ~GENSYM[~RESULT_reg][1] : ~TYPO ~IF ~ISINITDEFINED[0] ~THEN := ~CONST[4] ~ELSE ~FI; begin- (~SYM[1],~SYM[2]) <= ~ARG[1];- ~GENSYM[~COMPNAME_dly][3] : process(~SYM[1])+ ~RESULT <= ~SYM[1];+ ~GENSYM[~RESULT_dly][4] : process(~ARG[2]) begin- if rising_edge(~SYM[1]) then- if ~SYM[2] then- ~RESULT <= ~ARG[2]+ if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2]) then+ if ~ARG[3] then+ ~SYM[1] <= ~ARG[5] -- pragma translate_off after 1 ps -- pragma translate_on@@ -26,47 +29,55 @@ end if; end process; end block;~ELSE-~SYM[0] : process(~ARG[1])+~SYM[0] : block+ signal ~SYM[1] : ~TYPO := ~CONST[4]; begin- if rising_edge(~ARG[1]) then- ~RESULT <= ~ARG[2]- -- pragma translate_off- after 1 ps- -- pragma translate_on- ;- end if;-end process;~FI--- register end"+ ~RESULT <= ~SYM[1];+ ~SYM[4] : process(~ARG[2])+ begin+ if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2]) then+ ~SYM[1] <= ~ARG[5]+ -- pragma translate_off+ after 1 ps+ -- pragma translate_on+ ;+ end if;+ end process;+end block;~FI+-- delay end" } } , { "BlackBox" : { "name" : "Clash.Signal.Internal.register#"+ , "kind" : "Declaration" , "type" : "register#- :: HasCallStack -- ARG[0]- => Clock domain gated -- ARG[1]- -> Reset domain synchronous -- ARG[2]- -> a -- ARG[3]- -> Signal clk a -- ARG[4]+ :: ( 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"- , "templateD" :-"-- register begin~IF ~ISGATED[1] ~THEN+ , "template" :+"-- register begin~IF ~ISACTIVEENABLE[4] ~THEN ~GENSYM[~COMPNAME_register][0] : block- signal ~GENSYM[clk][1] : std_logic;- signal ~GENSYM[ce][2] : boolean;+ signal ~GENSYM[~RESULT_reg][1] : ~TYPO ~IF ~ISINITDEFINED[0] ~THEN := ~CONST[5] ~ELSE ~FI; begin- (~SYM[1],~SYM[2]) <= ~ARG[1];~IF ~ISSYNC[2] ~THEN- ~GENSYM[~COMPNAME_reg][3] : process(~SYM[1])+ ~RESULT <= ~SYM[1]; ~IF ~ISSYNC[0] ~THEN+ ~GENSYM[~RESULT_r][2] : process(~ARG[2]) begin- if rising_edge(~SYM[1]) then- if ~ARG[2] = '1' then- ~RESULT <= ~ARG[3]+ if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2]) then+ if ~ARG[3] = ~IF ~ISACTIVEHIGH[0] ~THEN '1' ~ELSE '0' ~FI then+ ~SYM[1] <= ~CONST[6] -- pragma translate_off after 1 ps -- pragma translate_on ;- elsif ~SYM[2] then- ~RESULT <= ~ARG[4]+ elsif ~ARG[4] then+ ~SYM[1] <= ~ARG[7] -- pragma translate_off after 1 ps -- pragma translate_on@@ -74,13 +85,13 @@ end if; end if; end process;~ELSE- ~SYM[3] : process(~SYM[1],~ARG[2]~VARS[3])+ ~SYM[2] : process(~ARG[2],~ARG[3]) begin- if ~ARG[2] = '1' then- ~RESULT <= ~ARG[3];- elsif rising_edge(~SYM[1]) then- if ~SYM[2] then- ~RESULT <= ~ARG[4]+ if ~ARG[3] = ~IF ~ISACTIVEHIGH[0] ~THEN '1' ~ELSE '0' ~FI then+ ~SYM[1] <= ~CONST[6];+ elsif ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2]) then+ if ~ARG[4] then+ ~SYM[1] <= ~ARG[7] -- pragma translate_off after 1 ps -- pragma translate_on@@ -88,191 +99,151 @@ end if; end if; end process;~FI-end block;~ELSE ~IF ~ISSYNC[2] ~THEN-~SYM[0] : process(~ARG[1])+end block;~ELSE+~SYM[0] : block+ signal ~SYM[1] : ~TYPO := ~CONST[5]; begin- if rising_edge(~ARG[1]) then- if ~ARG[2] = '1' then- ~RESULT <= ~ARG[3]+ ~RESULT <= ~SYM[1]; ~IF ~ISSYNC[0] ~THEN+ ~SYM[2] : process(~ARG[2])+ begin+ if ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2]) then+ if ~ARG[3] = ~IF ~ISACTIVEHIGH[0] ~THEN '1' ~ELSE '0' ~FI then+ ~SYM[1] <= ~CONST[6]+ -- pragma translate_off+ after 1 ps+ -- pragma translate_on+ ;+ else+ ~SYM[1] <= ~ARG[7]+ -- pragma translate_off+ after 1 ps+ -- pragma translate_on+ ;+ end if;+ end if;+ end process;~ELSE+ ~SYM[2] : process(~ARG[2],~ARG[3])+ begin+ if ~ARG[3] = ~IF ~ISACTIVEHIGH[0] ~THEN '1' ~ELSE '0' ~FI then+ ~SYM[1] <= ~CONST[6] -- pragma translate_off after 1 ps -- pragma translate_on ;- else- ~RESULT <= ~ARG[4]+ elsif ~IF~ACTIVEEDGE[Rising][0]~THENrising_edge~ELSEfalling_edge~FI(~ARG[2]) then+ ~SYM[1] <= ~ARG[7] -- pragma translate_off after 1 ps -- pragma translate_on ; end if;- end if;-end process;~ELSE-~SYM[0] : process(~ARG[1],~ARG[2]~VARS[3])-begin- if ~ARG[2] = '1' then- ~RESULT <= ~ARG[3]- -- pragma translate_off- after 1 ps- -- pragma translate_on- ;- elsif rising_edge(~ARG[1]) then- ~RESULT <= ~ARG[4]- -- pragma translate_off- after 1 ps- -- pragma translate_on- ;- end if;-end process;~FI~FI+ end process;~FI+end block;~FI -- register end" } } , { "BlackBox" :- { "name" : "Clash.Signal.Internal.clockGate"- , "type" :-"clockGate- :: Clock domain gated -- ARG[0]- -> Signal domain Bool -- ARG[1]- -> Clcok domain 'Gated"- , "templateD" :-"-- clockGate begin~IF ~ISGATED[0] ~THEN-~RESULT <= (~ARG[0].~TYPM[0]_sel0,~ARG[0].~TYPM[0]_sel1 and ~ARG[1]);~ELSE-~RESULT <= (~ARG[0],~ARG[1]);~FI--- clockGate end"- }- }-, { "BlackBox" : { "name" : "Clash.Signal.Internal.clockGen"+ , "workInfo" : "Always"+ , "kind" : "Declaration"+ , "warning" : "Clash.Signal.Internal.clockGen is not synthesizable!" , "type" : "clockGen- :: (domain ~ Dom nm period -- ARG[0]- ,KnownSymbol nm -- ARG[1]- ,KnownNat period) -- ARG[2]- => Clock domain Source"- , "templateD" :-"-- pragma translate_off+ :: 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_period][1] : time := ~LIT[2]0 ps / 2;+ 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 <= '0';+ ~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[1];+ wait for ~SYM[2]; end loop; wait; end process;--- pragma translate_on"+-- pragma translate_on+-- clockGen end" } } , { "BlackBox" :- { "name" : "Clash.Signal.Internal.tbClockGen"+ { "name" : "Clash.Explicit.Testbench.tbClockGen"+ , "workInfo" : "Always"+ , "kind" : "Declaration"+ , "warning" : "Clash.Signal.Internal.tbClockGen is not synthesizable!" , "type" : "tbClockGen- :: (domain ~ Dom nm period -- ARG[0]- ,KnownSymbol nm -- ARG[1]- ,KnownNat period) -- ARG[2]- => Signal domain Bool -- ARG[3]- -> Clock domain Source"- , "templateD" :-"-- pragma translate_off+ :: 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_period][1] : time := ~LIT[2]0 ps / 2;+ 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 <= '0';+ ~RESULT <= ~IF~ACTIVEEDGE[Rising][0]~THEN'0'~ELSE'1'~FI; wait for 3000 ps;- while ~ARG[3] loop+ while ~ARG[1] loop ~RESULT <= not ~RESULT; wait for ~SYM[1]; ~RESULT <= not ~RESULT;- wait for ~SYM[1];+ wait for ~SYM[2]; end loop; wait; end process;--- pragma translate_on"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.asyncResetGen"- , "type" :-"asyncResetGen :: Reset domain 'Asynchronous"- , "templateD" :-"-- pragma translate_off-~RESULT <= '1',- '0' after 2000 ps;--- pragma translate_on"- }- }-, { "BlackBox" :- { "name" : "Clash.Signal.Internal.syncResetGen"- , "type" :-"syncResetGen :: ( domain ~ 'Dom n clkPeriod- , KnownNat clkPeriod )- => Reset domain 'Synchronous"- , "templateD" :-"-- pragma translate_off-~RESULT <= '1',- '0' after (2999 ps + ~LIT[1]0 ps);--- pragma translate_on"+-- pragma translate_on+-- tbClockGen end" } } , { "BlackBox" :- { "name" : "Clash.Signal.Internal.unsafeFromAsyncReset"- , "type" :-"unsafeFromAsyncReset :: Reset domain Asynchronous -> Signal domain Bool"- , "templateD" : "~RESULT <= true when ~ARG[0] = '1' else false;"+ { "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.unsafeToAsyncReset"+ { "name" : "Clash.Signal.Internal.unsafeFromReset"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" :-"unsafeToAsyncReset :: Signal domain Bool -> Reset domain Asynchronous"- , "templateD" : "~RESULT <= '1' when ~ARG[0] else '0';"+"unsafeFromReset :: Reset dom -> Signal dom Bool"+ , "template" : "~RESULT <= true when ~ARG[0] = '1' else false;" } } , { "BlackBox" :- { "name" : "Clash.Signal.Internal.fromSyncReset"+ { "name" : "Clash.Signal.Internal.unsafeToReset"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" :-"fromSyncReset :: Reset domain Synchronous -> Signal domain Bool"- , "templateD" : "~RESULT <= true when ~ARG[0] = '1' else false;"+"unsafeToReset :: Signal dom Bool -> Reset dom"+ , "template" : "~RESULT <= '1' when ~ARG[0] = true else '0';" } } , { "BlackBox" :- { "name" : "Clash.Signal.Internal.unsafeToSyncReset"- , "type" :-"unsafeToSyncReset :: Signal domain Bool -> Reset domain Synchronous"- , "templateD" : "~RESULT <= '1' when ~ARG[0] else '0';"- }- }-, { "Primitive" :- { "name" : "Clash.Signal.Internal.signal#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Signal.Internal.mapSignal#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Signal.Internal.appSignal#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Signal.Internal.foldr#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Signal.Internal.traverse#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "Clash.Signal.Internal.joinSignal#"- , "primType" : "Function"+ { "name" : "Clash.Explicit.Testbench.tbEnableGen"+ , "workInfo" : "Always"+ , "kind" : "Declaration"+ , "type" : "tbEnableGen :: Enable dom"+ , "template" : "~RESULT <= true;" } } ]
prims/vhdl/Clash_Sized_Internal_BitVector.json view
@@ -1,116 +1,134 @@ [ { "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"- , "templateE" : "to_signed(~LIT[0],~SIZE[~TYPO])"+ , "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"- , "templateE" : "to_signed(~LIT[0] - 1,~SIZE[~TYPO])"+ , "template" : "to_signed(~SIZE[~TYP[1]] - 1,~SIZE[~TYPO])" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.high"+ , "workInfo" : "Constant"+ , "kind" : "Expression" , "type" : "high :: Bit"- , "templateE" : "'1'"+ , "template" : "'1'" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.low"+ , "workInfo" : "Constant"+ , "kind" : "Expression" , "type" : "low :: Bit"- , "templateE" : "'0'"+ , "template" : "'0'" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.pack#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "pack# :: Bit -> BitVector 1"- , "templateE" : "std_logic_vector'(0 => ~ARG[0])"+ , "template" : "std_logic_vector'(0 => ~ARG[0])" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.unpack#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "unpack# :: BitVector 1 -> Bit"- , "templateE" : "~VAR[bv][0](0)"+ , "template" : "~VAR[bv][0](0)" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.eq##"+ , "kind" : "Expression" , "type" : "eq## :: Bit -> Bit -> Bool"- , "templateE" : "~ARG[0] = ~ARG[1]"+ , "template" : "~ARG[0] = ~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.neq##"+ , "kind" : "Expression" , "type" : "neq## :: Bit -> Bit -> Bool"- , "templateE" : "~ARG[0] /= ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.lt##"- , "type" : "lt## :: Bit -> Bit -> Bool"- , "templateE" : "~ARG[0] < ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.ge##"- , "type" : "ge## :: Bit -> Bit -> Bool"- , "templateE" : "~ARG[0] >= ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.gt##"- , "type" : "gt## :: Bit -> Bit -> Bool"- , "templateE" : "~ARG[0] > ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.le##"- , "type" : "le## :: Bit -> Bit -> Bool"- , "templateE" : "~ARG[0] <= ~ARG[1]"+ , "template" : "~ARG[0] /= ~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.fromInteger##"- , "type" : "fromInteger# :: Integer -> Bit"- , "templateE" : "~VAR[i][0](0)"+ , "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"- , "templateE" : "~ARG[0] and ~ARG[1]"+ , "template" : "~ARG[0] and ~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.or##"+ , "kind" : "Expression" , "type" : "or## :: Bit -> Bit -> Bit"- , "templateE" : "~ARG[0] or ~ARG[1]"+ , "template" : "~ARG[0] or ~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.xor##"+ , "kind" : "Expression" , "type" : "xor## :: Bit -> Bit -> Bit"- , "templateE" : "~ARG[0] xor ~ARG[1]"+ , "template" : "~ARG[0] xor ~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.complement##"+ , "kind" : "Expression" , "type" : "complement## :: Bit -> Bit"- , "templateE" : "not ~ARG[0]"+ , "template" : "not ~ARG[0]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.++#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "(++#) :: KnownNat m => BitVector n -> BitVector m -> BitVector (n + m)"- , "templateE" : "std_logic_vector'(std_logic_vector'(~ARG[1]) & std_logic_vector'(~ARG[2]))"+ , "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"- , "templateD" :-"-- reduceAnd begin+ , "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;@@ -135,15 +153,17 @@ end; begin ~RESULT <= and_reduce(~ARG[1]);-end block;+end block;~ELSE+~RESULT <= '1';~FI -- reduceAnd end" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.reduceOr#"- , "type" : "reduceOr# :: BitVector n -> Bit"- , "templateD" :-"-- reduceOr begin+ , "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;@@ -167,16 +187,18 @@ return result; end; begin- ~RESULT <= or_reduce(~ARG[0]);-end block;+ ~RESULT <= or_reduce(~ARG[1]);+end block;~ELSE+~RESULT <= '0'; ~FI -- reduceOr end" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.reduceXor#"- , "type" : "reduceXor# :: BitVector n -> Bit"- , "templateD" :-"-- reduceXor begin+ , "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;@@ -200,61 +222,65 @@ return result; end; begin- ~RESULT <= xor_reduce(~ARG[0]);-end block;+ ~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"- , "templateD" :-"-- indexBitVector begin~IF ~ISVAR[1] ~THEN+ , "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 ~LIT[0]-1;+ signal ~GENSYM[vec_index][1] : integer range 0 to ~SIZE[~TYP[1]]-1; begin ~SYM[1] <= to_integer(~ARG[2]) -- pragma translate_off- mod ~LIT[0]+ 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 ~LIT[0]-1;+ signal ~SYM[1] : integer range 0 to ~SIZE[~TYP[1]]-1; begin ~SYM[1] <= to_integer(~ARG[2]) -- pragma translate_off- mod ~LIT[0]+ mod ~SIZE[~TYP[1]] -- pragma translate_on ; ~RESULT <= ~VAR[bv][1](~SYM[1]);-end block;~FI+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"- , "templateD" :-"-- replaceBit begin+ , "template" :+"-- replaceBit begin ~IF~SIZE[~TYP[1]]~THEN ~GENSYM[replaceBit][0] : block- signal ~GENSYM[vec_index][1] : integer range 0 to ~LIT[0]-1;+ signal ~GENSYM[vec_index][1] : integer range 0 to ~SIZE[~TYP[1]]-1; begin ~SYM[1] <= to_integer(~ARG[2]) -- pragma translate_off- mod ~LIT[0]+ mod ~SIZE[~TYP[1]] -- pragma translate_on ; @@ -265,19 +291,22 @@ ~SYM[2](~SYM[1]) := ~ARG[3]; ~RESULT <= ~SYM[2]; end process;-end block;+end block; ~ELSE+~RESULT <= ~ERRORO;~FI -- replaceBit end" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.setSlice#"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "setSlice# :: BitVector (m + 1 + i) -- ARG[0] -> SNat m -- ARG[1] -> SNat n -- ARG[2] -> BitVector (m + 1 - n) -- ARG[3] -> BitVector (m + 1 + i)"- , "templateD" :+ , "template" : "-- setSlice begin ~GENSYM[setSlice][0] : process(~VAR[bv][0]~VARS[3]) variable ~GENSYM[ivec][1] : ~TYP[0];@@ -291,206 +320,247 @@ } , { "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)"- , "templateE" : "~VAR[bv][0](~LIT[1] downto ~LIT[2])"+ , "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)"- , "templateE" : "(~VAR[bv][1](~VAR[bv][1]'high downto ~LIT[0]),~VAR[bv][1](~LIT[0]-1 downto 0))"+ , "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"- , "templateE" : "~IF ~LIT[0] ~THEN ~VAR[bv][1](~VAR[bv][1]'high) ~ELSE \"0\" ~FI"+ , "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"- , "templateE" : "~IF ~SIZE[~TYP[0]] ~THEN ~VAR[bv][0](0) ~ELSE \"0\" ~FI"+ , "template" : "~IF ~SIZE[~TYP[0]] ~THEN ~VAR[bv][0](0) ~ELSE \"0\" ~FI" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.eq#"- , "type" : "eq# :: BitVector n -> BitVector n -> Bool"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] = ~ARG[1]~ELSEtrue~FI"+ , "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#"- , "type" : "neq# :: BitVector n -> BitVector n -> Bool"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] /= ~ARG[1]~ELSEfalse~FI"+ , "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#"- , "type" : "lt# :: BitVector n -> BitVector n -> Bool"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] < ~ARG[1]~ELSEfalse~FI"+ , "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#"- , "type" : "ge# :: BitVector n -> BitVector n -> Bool"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] >= ~ARG[1]~ELSEtrue~FI"+ , "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#"- , "type" : "gt# :: BitVector n -> BitVector n -> Bool"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] > ~ARG[1]~ELSEfalse~FI"+ , "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#"- , "type" : "le# :: BitVector n -> BitVector n -> Bool"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] <= ~ARG[1]~ELSEtrue~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYPO]~THENstd_logic_vector'(~SIZE[~TYPO]-1 downto 0 => '0')~ELSEstd_logic_vector'(0 downto 1 => '0')~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYPO]~THENstd_logic_vector'(~SIZE[~TYPO]-1 downto 0 => '1')~ELSEstd_logic_vector'(0 downto 1 => '1')~FI"+ , "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"- , "templateE" : "std_logic_vector(unsigned(~ARG[1]) + unsigned(~ARG[2]))"+ , "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"- , "templateE" : "std_logic_vector(unsigned(~ARG[1]) - unsigned(~ARG[2]))"+ , "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"- , "templateE" : "std_logic_vector(resize(unsigned(~ARG[1]) * unsigned(~ARG[2]), ~LIT[0]))"+ , "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"- , "templateE" : "std_logic_vector(-(signed(~ARG[1])))"+ , "template" : "std_logic_vector(-(signed(~ARG[1])))" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.fromInteger#"- , "type" : "fromInteger# :: KnownNat n => Integer -> BitVector n"- , "templateE" : "std_logic_vector(resize(unsigned(std_logic_vector(~ARG[1])),~LIT[0]))"+ , "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#"- , "type" : "plus# :: BitVector m -> BitVector n -> BitVector (Max m n + 1)"- , "templateE" : "std_logic_vector(resize(unsigned(~ARG[0]),~SIZE[~TYPO]) + resize(unsigned(~ARG[1]),~SIZE[~TYPO]))"+ , "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)"- , "templateE" : "std_logic_vector(resize(unsigned(~ARG[2]),~SIZE[~TYPO]) - resize(unsigned(~ARG[3]),~SIZE[~TYPO]))"+ , "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#"- , "type" : "times# :: BitVector m -> BitVector n -> BitVector (m + n)"- , "templateE" : "std_logic_vector(unsigned(~ARG[0]) * unsigned(~ARG[1]))"+ , "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#"- , "type" : "quot# :: BitVector n -> BitVector n -> BitVector n"- , "templateE" : "std_logic_vector(unsigned(~ARG[0]) / unsigned(~ARG[1]))"+ , "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#"- , "type" : "rem# :: BitVector n -> BitVector n -> BitVector n"- , "templateE" : "std_logic_vector(unsigned(~ARG[0]) rem unsigned(~ARG[1]))"+ , "kind" : "Expression"+ , "type" : "rem# :: KnownNat n => BitVector n -> BitVector n -> BitVector n"+ , "template" : "std_logic_vector(unsigned(~ARG[1]) rem unsigned(~ARG[2]))" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.toInteger#"- , "type" : "toInteger# :: BitVector n -> Integer"- , "templateE" : "~IF~SIZE[~TYP[0]]~THENsigned(std_logic_vector(resize(unsigned(~ARG[0]),~SIZE[~TYPO])))~ELSEto_signed(0,64)~FI"+ , "workInfo" : "Never"+ , "kind" : "Expression"+ , "type" : "toInteger# :: KnownNat n => BitVector n -> Integer"+ , "template" : "~IF~SIZE[~TYP[1]]~THENsigned(std_logic_vector(resize(unsigned(~ARG[1]),~SIZE[~TYPO])))~ELSEto_signed(0,64)~FI" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.and#"+ , "kind" : "Expression" , "type" : "and# :: BitVector n -> BitVector n -> BitVector n"- , "templateE" : "~ARG[0] and ~ARG[1]"+ , "template" : "~ARG[0] and ~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.or#"+ , "kind" : "Expression" , "type" : "or# :: BitVector n -> BitVector n -> BitVector n"- , "templateE" : "~ARG[0] or ~ARG[1]"+ , "template" : "~ARG[0] or ~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.xor#"+ , "kind" : "Expression" , "type" : "xor# :: BitVector n -> BitVector n -> BitVector n"- , "templateE" : "~ARG[0] xor ~ARG[1]"+ , "template" : "~ARG[0] xor ~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.complement#"+ , "kind" : "Expression" , "type" : "complement# :: KnownNat n => BitVector n -> BitVector n"- , "templateE" : "not ~ARG[1]"+ , "template" : "not ~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.shiftL#"+ , "kind" : "Expression" , "type" : "shiftL# :: KnownNat n => BitVector n -> Int -> BitVector n"- , "templateE" : "std_logic_vector(shift_left(unsigned(~ARG[1]),to_integer(~ARG[2])))"+ , "template" : "std_logic_vector(shift_left(unsigned(~ARG[1]),to_integer(~ARG[2])))" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.shiftR#"+ , "kind" : "Expression" , "type" : "shiftR# :: KnownNat n => BitVector n -> Int -> BitVector n"- , "templateE" : "std_logic_vector(shift_right(unsigned(~ARG[1]),to_integer(~ARG[2])))"+ , "template" : "std_logic_vector(shift_right(unsigned(~ARG[1]),to_integer(~ARG[2])))" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.rotateL#"+ , "kind" : "Expression" , "type" : "rotateL# :: KnownNat n => BitVector n -> Int -> BitVector n"- , "templateE" : "std_logic_vector(rotate_left(unsigned(~ARG[1]),to_integer(~ARG[2])))"+ , "template" : "std_logic_vector(rotate_left(unsigned(~ARG[1]),to_integer(~ARG[2])))" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.BitVector.rotateR#"+ , "kind" : "Expression" , "type" : "rotateR# :: KnownNat n => BitVector n -> Int -> BitVector n"- , "templateE" : "std_logic_vector(rotate_right(unsigned(~ARG[1]),to_integer(~ARG[2])))"+ , "template" : "std_logic_vector(rotate_right(unsigned(~ARG[1]),to_integer(~ARG[2])))" } } , { "BlackBox" :- { "name" : "Clash.Sized.Internal.BitVector.resize#"- , "type" : "resize# :: KnownNat m => BitVector n -> BitVector m"- , "templateE" : "std_logic_vector(resize(unsigned(~ARG[1]),~LIT[0]))"+ { "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_Index.json view
@@ -1,121 +1,140 @@ [ { "BlackBox" : { "name" : "Clash.Sized.Internal.Index.pack#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "pack# :: Index n -> BitVector (CLog 2 n)"- , "templateE" : "std_logic_vector(~ARG[0])"+ , "template" : "std_logic_vector(~ARG[0])" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Index.unpack#"- , "type" : "unpack# :: KnownNat n => BitVector (CLog 2 n) -> Index n"- , "templateE" : "unsigned(~ARG[1])"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] = ~ARG[1]~ELSEtrue~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] /= ~ARG[1]~ELSEfalse~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] < ~ARG[1]~ELSEfalse~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] >= ~ARG[1]~ELSEtrue~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] > ~ARG[1]~ELSEfalse~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] <= ~ARG[1]~ELSEtrue~FI"+ , "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"- , "templateE" : "to_unsigned(~LIT[0]-1,~SIZE[~TYPO])"+ , "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"- , "templateE" : "~ARG[1] + ~ARG[2]"+ , "template" : "~ARG[1] + ~ARG[2]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Index.-#"+ , "kind" : "Expression" , "type" : "(-#) :: KnownNat n => Index n -> Index n -> Index n"- , "templateE" : "~ARG[1] - ~ARG[2]"+ , "template" : "~ARG[1] - ~ARG[2]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Index.*#"+ , "kind" : "Expression" , "type" : "(*#) :: KnownNat n => Index n -> Index n -> Index n"- , "templateE" : "resize(~ARG[1] * ~ARG[2], ~SIZE[~TYPO])"+ , "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"- , "templateE" : "resize(unsigned(std_logic_vector(~ARG[1])),~SIZE[~TYPO])"+ , "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)"- , "templateE" : "resize(~ARG[0],~SIZE[~TYPO]) + resize(~ARG[1],~SIZE[~TYPO])"+ , "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)"- , "templateE" : "resize(~ARG[0],~SIZE[~TYPO]) - resize(~ARG[1],~SIZE[~TYPO])"+ , "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)"- , "templateE" : "resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO])"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Index.quot#"- , "type" : "quot# :: Index n -> Index n -> Index n"- , "templateE" : "~ARG[0] / ~ARG[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"- , "templateE" : "~ARG[0] rem ~ARG[1]"+ , "template" : "~ARG[0] rem ~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Index.toInteger#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "toInteger# :: Index n -> Integer"- , "templateE" : "~IF~SIZE[~TYP[0]]~THENsigned(std_logic_vector(resize(~ARG[0],~SIZE[~TYPO])))~ELSEto_signed(0,64)~FI"+ , "template" : "~IF~SIZE[~TYP[0]]~THENsigned(std_logic_vector(resize(~ARG[0],~SIZE[~TYPO])))~ELSEto_signed(0,64)~FI" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Index.resize#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "resize# :: KnownNat m => Index n -> Index m"- , "templateE" : "resize(~ARG[1],~SIZE[~TYPO])"+ , "template" : "~IF~SIZE[~TYP[1]]~THENresize(~ARG[1],~SIZE[~TYPO])~ELSEunsigned'(~SIZE[~TYPO]-1 downto 0 => '0')~FI" } } ]
prims/vhdl/Clash_Sized_Internal_Signed.json view
@@ -1,141 +1,149 @@ [ { "BlackBox" : { "name" : "Clash.Sized.Internal.Signed.size#"+ , "workInfo" : "Constant"+ , "kind" : "Expression" , "type" : "size# :: KnownNat n => Signed n -> Int"- , "templateE" : "to_signed(~LIT[0],~SIZE[~TYPO])"+ , "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"- , "templateE" : "std_logic_vector(~ARG[1])"+ , "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"- , "templateE" : "signed(~ARG[1])"+ , "template" : "signed(~ARG[1])" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Signed.eq#"+ , "kind" : "Expression" , "type" : "eq# :: Signed n -> Signed n -> Bool"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] = ~ARG[1]~ELSEtrue~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] /= ~ARG[1]~ELSEfalse~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] < ~ARG[1]~ELSEfalse~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] >= ~ARG[1]~ELSEtrue~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] > ~ARG[1]~ELSEfalse~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] <= ~ARG[1]~ELSEtrue~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYPO]~THENsigned'(0 => '1', 1 to ~LIT[0]-1 => '0')~ELSEsigned'(1 downto 0 => '0')~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYPO]~THENsigned'(0 => '0', 1 to ~LIT[0]-1 => '1')~ELSEsigned'(1 downto 0 => '0')~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.+#"- , "type" : "(+#) :: KnownNat n => Signed n -> Signed n -> Signed n"- , "templateE" : "~ARG[1] + ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.-#"- , "type" : "(-#) :: KnownNat n => Signed n -> Signed n -> Signed n"- , "templateE" : "~ARG[1] - ~ARG[2]"+ , "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"- , "templateE" : "resize(~ARG[1] * ~ARG[2], ~LIT[0])"+ , "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"- , "templateE" : "-~ARG[1]"+ , "template" : "-~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Signed.abs#"+ , "kind" : "Expression" , "type" : "abs# :: KnownNat n => Signed n -> Signed n"- , "templateE" : "abs ~ARG[1]"+ , "template" : "abs ~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Signed.fromInteger#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "fromInteger# :: KnownNat n => Integer -> Signed (n :: Nat)"- , "templateE" : "resize(~ARG[1],~LIT[0])"+ , "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)"- , "templateE" : "resize(~ARG[0],~SIZE[~TYPO]) + resize(~ARG[1],~SIZE[~TYPO])"+ , "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)"- , "templateE" : "resize(~ARG[0],~SIZE[~TYPO]) - resize(~ARG[1],~SIZE[~TYPO])"+ , "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)"- , "templateE" : "~ARG[0] * ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Signed.quot#"- , "type" : "quot# :: Signed n -> Signed n -> Signed n"- , "templateE" : "~ARG[0] / ~ARG[1]"+ , "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"- , "templateE" : "~ARG[0] rem ~ARG[1]"+ , "template" : "~ARG[0] rem ~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Signed.div#"+ , "kind" : "Declaration" , "type" : "div# :: Signed n -> Signed n -> Signed n"- , "templateD" :+ , "template" : "-- divSigned begin ~GENSYM[divSigned][0] : block signal ~GENSYM[quot_res][3] : ~TYP[0];@@ -149,74 +157,89 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Signed.mod#"+ , "kind" : "Expression" , "type" : "mod# :: Signed n -> Signed n -> Signed n"- , "templateE" : "~ARG[0] mod ~ARG[1]"+ , "template" : "~ARG[0] mod ~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Signed.toInteger#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "toInteger# :: Signed n -> Integer"- , "templateE" : "~IF~SIZE[~TYP[0]]~THENresize(~ARG[0],~SIZE[~TYPO])~ELSEto_signed(0,64)~FI"+ , "template" : "~IF~SIZE[~TYP[0]]~THENresize(~ARG[0],~SIZE[~TYPO])~ELSEto_signed(0,64)~FI" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Signed.and#"+ , "kind" : "Expression" , "type" : "and# :: KnownNat n => Signed n -> Signed n -> Signed n"- , "templateE" : "~ARG[1] and ~ARG[2]"+ , "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"- , "templateE" : "~ARG[1] or ~ARG[2]"+ , "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"- , "templateE" : "~ARG[1] xor ~ARG[2]"+ , "template" : "~ARG[1] xor ~ARG[2]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Signed.complement#"+ , "kind" : "Expression" , "type" : "complement# :: KnownNat n => Signed n -> Signed n"- , "templateE" : "not ~ARG[1]"+ , "template" : "not ~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Signed.shiftL#"+ , "kind" : "Expression" , "type" : "shiftL# :: KnownNat n => Signed n -> Int -> Signed n"- , "templateE" : "shift_left(~ARG[1],to_integer(~ARG[2]))"+ , "template" : "shift_left(~ARG[1],to_integer(~ARG[2]))" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Signed.shiftR#"+ , "kind" : "Expression" , "type" : "shiftR# :: KnownNat n => Signed n -> Int -> Signed n"- , "templateE" : "shift_right(~ARG[1],to_integer(~ARG[2]))"+ , "template" : "shift_right(~ARG[1],to_integer(~ARG[2]))" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Signed.rotateL#"+ , "kind" : "Expression" , "type" : "rotateL# :: KnownNat n => Signed n -> Int -> Signed n"- , "templateE" : "rotate_left(~ARG[1],to_integer(~ARG[2]))"+ , "template" : "rotate_left(~ARG[1],to_integer(~ARG[2]))" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Signed.rotateR#"+ , "kind" : "Expression" , "type" : "rotateR# :: KnownNat n => Signed n -> Int -> Signed n"- , "templateE" : "rotate_right(~ARG[1],to_integer(~ARG[2]))"+ , "template" : "rotate_right(~ARG[1],to_integer(~ARG[2]))" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Signed.resize#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "resize# :: (KnownNat n, KnownNat m) => Signed n -> Signed m"- , "templateE" : "resize(~ARG[2],~LIT[1])"+ , "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"- , "templateE" : "~IF~SIZE[~TYPO]~THEN~VAR[s][1](~LIT[0]-1 downto 0)~ELSEsigned'(0 downto 1 => '0')~FI"+ , "template" : "~IF~SIZE[~TYPO]~THEN~VAR[s][1](~LIT[0]-1 downto 0)~ELSEsigned'(0 downto 1 => '0')~FI" } } ]
prims/vhdl/Clash_Sized_Internal_Unsigned.json view
@@ -1,187 +1,205 @@ [ { "BlackBox" : { "name" : "Clash.Sized.Internal.Unsigned.size#"+ , "workInfo" : "Constant"+ , "kind" : "Expression" , "type" : "size# :: KnownNat n => Unsigned n -> Int"- , "templateE" : "to_signed(~LIT[0],~SIZE[~TYPO])"+ , "template" : "to_signed(~LIT[0],~SIZE[~TYPO])" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Unsigned.pack#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "pack# :: Unsigned n -> BitVector n"- , "templateE" : "std_logic_vector(~ARG[0])"+ , "template" : "std_logic_vector(~ARG[0])" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Unsigned.unpack#"- , "type" : "unpack# :: BitVector n -> Unsigned n"- , "templateE" : "unsigned(~ARG[0])"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] = ~ARG[1]~ELSEtrue~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] /= ~ARG[1]~ELSEfalse~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] < ~ARG[1]~ELSEfalse~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] >= ~ARG[1]~ELSEtrue~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] > ~ARG[1]~ELSEfalse~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYP[0]]~THEN~ARG[0] <= ~ARG[1]~ELSEtrue~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYPO]~THENunsigned'(~SIZE[~TYPO]-1 downto 0 => '0')~ELSEunsigned'(0 downto 1 => '0')~FI"+ , "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"- , "templateE" : "~IF~SIZE[~TYPO]~THENunsigned'(~LIT[0]-1 downto 0 => '1')~ELSEunsigned'(0 downto 1 => '1')~FI"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.+#"- , "type" : "(+#) :: KnownNat n => Unsigned n -> Unsigned n -> Unsigned n"- , "templateE" : "~ARG[1] + ~ARG[2]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.-#"- , "type" : "(-#) :: KnownNat n => Unsigned n -> Unsigned n -> Unsigned n"- , "templateE" : "~ARG[1] - ~ARG[2]"+ , "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"- , "templateE" : "resize(~ARG[1] * ~ARG[2], ~LIT[0])"+ , "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"- , "templateE" : "unsigned(std_logic_vector(-(signed(std_logic_vector(~ARG[1])))))"+ , "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"- , "templateE" : "resize(unsigned(std_logic_vector(~ARG[1])),~LIT[0])"+ , "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)"- , "templateE" : "resize(~ARG[0],~SIZE[~TYPO]) + resize(~ARG[1],~SIZE[~TYPO])"+ , "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)"- , "templateE" : "resize(~ARG[2],~SIZE[~TYPO]) - resize(~ARG[3],~SIZE[~TYPO])"+ , "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)"- , "templateE" : "~ARG[0] * ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "Clash.Sized.Internal.Unsigned.quot#"- , "type" : "quot# :: Unsigned n -> Unsigned n -> Unsigned n"- , "templateE" : "~ARG[0] / ~ARG[1]"+ , "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"- , "templateE" : "~ARG[0] rem ~ARG[1]"+ , "template" : "~ARG[0] rem ~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Unsigned.toInteger#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "toInteger# :: Unsigned n -> Integer"- , "templateE" : "~IF~SIZE[~TYP[0]]~THENsigned(std_logic_vector(resize(~ARG[0],~SIZE[~TYPO])))~ELSEto_signed(0,64)~FI"+ , "template" : "~IF~SIZE[~TYP[0]]~THENsigned(std_logic_vector(resize(~ARG[0],~SIZE[~TYPO])))~ELSEto_signed(0,64)~FI" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Unsigned.and#"+ , "kind" : "Expression" , "type" : "and# :: Unsigned n -> Unsigned n -> Unsigned n"- , "templateE" : "~ARG[0] and ~ARG[1]"+ , "template" : "~ARG[0] and ~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Unsigned.or#"+ , "kind" : "Expression" , "type" : "or# :: Unsigned n -> Unsigned n -> Unsigned n"- , "templateE" : "~ARG[0] or ~ARG[1]"+ , "template" : "~ARG[0] or ~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Unsigned.xor#"+ , "kind" : "Expression" , "type" : "xor# :: Unsigned n -> Unsigned n -> Unsigned n"- , "templateE" : "~ARG[0] xor ~ARG[1]"+ , "template" : "~ARG[0] xor ~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Unsigned.complement#"+ , "kind" : "Expression" , "type" : "complement# :: KnownNat n => Unsigned n -> Unsigned n"- , "templateE" : "not ~ARG[1]"+ , "template" : "not ~ARG[1]" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Unsigned.shiftL#"+ , "kind" : "Expression" , "type" : "shiftL# :: KnownNat n => Unsigned n -> Int -> Unsigned n"- , "templateE" : "shift_left(~ARG[1],to_integer(~ARG[2]))"+ , "template" : "shift_left(~ARG[1],to_integer(~ARG[2]))" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Unsigned.shiftR#"+ , "kind" : "Expression" , "type" : "shiftR# :: KnownNat n => Unsigned n -> Int -> Unsigned n"- , "templateE" : "shift_right(~ARG[1],to_integer(~ARG[2]))"+ , "template" : "shift_right(~ARG[1],to_integer(~ARG[2]))" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Unsigned.rotateL#"+ , "kind" : "Expression" , "type" : "rotateL# :: KnownNat n => Unsigned n -> Int -> Unsigned n"- , "templateE" : "rotate_left(~ARG[1],to_integer(~ARG[2]))"+ , "template" : "rotate_left(~ARG[1],to_integer(~ARG[2]))" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Unsigned.rotateR#"+ , "kind" : "Expression" , "type" : "rotateR# :: KnownNat n => Unsigned n -> Int -> Unsigned n"- , "templateE" : "rotate_right(~ARG[1],to_integer(~ARG[2]))"+ , "template" : "rotate_right(~ARG[1],to_integer(~ARG[2]))" } } , { "BlackBox" : { "name" : "Clash.Sized.Internal.Unsigned.resize#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "resize# :: KnownNat m => Unsigned n -> Unsigned m"- , "templateE" : "resize(~ARG[1],~LIT[0])"+ , "template" : "~IF~SIZE[~TYP[1]]~THENresize(~ARG[1],~LIT[0])~ELSEunsigned'(~SIZE[~TYPO]-1 downto 0 => '0')~FI" } } ]
prims/vhdl/Clash_Sized_RTree.json view
@@ -1,19 +1,25 @@ [ { "BlackBox" : { "name" : "Clash.Sized.RTree.treplicate"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "replicate :: SNat n -> a -> RTree d a"- , "templateE" : "~TYPMO'(0 to (2**~LIT[0])-1 => ~ARG[1])"+ , "template" : "~TYPMO'(0 to (2**~LIT[0])-1 => ~ARG[1])" } } , { "BlackBox" : { "name" : "Clash.Sized.RTree.textract"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "textract :: RTree 0 a -> a"- , "templateE" : "~IF ~VIVADO ~THEN ~FROMBV[~VAR[t][0]][~TYPO] ~ELSE ~VAR[t][0](0) ~FI"+ , "template" : "~IF ~VIVADO ~THEN ~FROMBV[~VAR[t][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)"- , "templateE" : "(~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))"+ , "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_Vector.json view
@@ -1,29 +1,39 @@ [ { "BlackBox" : { "name" : "Clash.Sized.Vector.head"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "head :: Vec (n + 1) a -> a"- , "templateE" : "~IF ~VIVADO ~THEN ~TYPMO'(fromSLV(~VAR[vec][0](0))) ~ELSE ~VAR[vec][0](0) ~FI"+ , "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"- , "templateE" : "~VAR[vec][0](1 to ~VAR[vec][0]'high)"+ , "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"- , "templateE" : "~IF ~VIVADO ~THEN ~TYPMO'(fromSLV(~VAR[vec][0](~VAR[vec][0]'high))) ~ELSE ~VAR[vec][0](~VAR[vec][0]'high) ~FI"+ , "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"- , "templateE" : "~VAR[vec][0](0 to ~VAR[vec][0]'high - 1)"+ , "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]@@ -31,7 +41,7 @@ -> SNat n -- ARG[3] -> Vec i a -- ARG[4] -> Vec n a"- , "templateD" :+ , "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]));@@ -41,16 +51,20 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.++"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "(++) :: Vec n a -> Vec m a -> Vec (n + m) a"- , "templateE" : "~TYPMO'(~TYPM[0]'(~ARG[0]) & ~TYPM[1]'(~ARG[1]))"+ , "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"- , "templateD" :+ , "template" : "-- concat begin-~GENSYM[concat][0] : for ~GENSYM[i][1] in ~VAR[vec][0]'range generate+~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@@ -60,19 +74,23 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.splitAt"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "splitAt :: SNat m -> Vec (m + n) a -> (Vec m a, Vec n a)"- , "templateE" : "~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"+ , "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)"- , "templateD" :-"-- unconcat begin+ , "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@@ -83,8 +101,10 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.map"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "map :: (a -> b) -> Vec n a -> Vec n b"- , "templateD" :+ , "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@@ -108,8 +128,10 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.imap"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "imap :: KnownNat n => (Index n -> a -> b) -> Vec n a -> Vec n b"- , "templateD" :+ , "template" : "-- imap begin ~GENSYM[imap][0] : block function ~GENSYM[max][6] (l,r : in natural) return natural is@@ -144,8 +166,10 @@ } , { "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"- , "templateD" :+ , "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@@ -175,8 +199,10 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.zipWith"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "zipWith :: (a -> b -> c) -> Vec n a -> Vec n b -> Vec n c"- , "templateD" :+ , "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@@ -204,8 +230,10 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.foldr"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "foldr :: (a -> b -> b) -> b -> Vec n a -> b"- , "templateD" :+ , "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];@@ -213,7 +241,7 @@ begin ~SYM[2](~LENGTH[~TYP[2]]) <= ~ARG[1]; - foldr_loop : for ~GENSYM[i][3] in ~VAR[vec][2]'range generate~IF ~VIVADO ~THEN~IF~SIZE[~TYP[2]]~THEN+ 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@@ -239,9 +267,11 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.fold"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "fold :: (a -> a -> a) -> Vec (n+1) a -> a" , "comment" : "THIS ONLY WORKS FOR POWER OF TWO LENGTH VECTORS"- , "templateD" :+ , "template" : "-- fold begin ~GENSYM[fold][0] : block -- given a level and a depth, calculate the corresponding index into the@@ -257,7 +287,7 @@ constant ~GENSYM[levels][5] : natural := natural (ceil (log2 (real (~LENGTH[~TYP[1]])))); begin -- put input array into the first half of the intermediate array~IF ~VIVADO ~THEN- ~SYM[6] : for ~SYM[7] in ~VAR[vec][1]'range generate+ ~SYM[6] : for ~SYM[7] in 0 to (~LENGTH[~TYP[1]] - 1) generate ~SYM[3](~SYM[7]) <= fromSLV(~VAR[vec][1](~SYM[7])); end generate;~ELSE ~SYM[3](0 to ~LENGTH[~TYP[1]]-1) <= ~VAR[vec][1];~FI@@ -283,10 +313,11 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.index_int"+ , "kind" : "Declaration" , "type" : "index_int :: KnownNat n => Vec n a -> Int -> a"- , "templateD" :+ , "template" : "-- index begin-~GENSYM[indexVec][0] : block+~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])@@ -296,14 +327,15 @@ ;~IF ~VIVADO ~THEN ~RESULT <= fromSLV(~VAR[vec][1](~SYM[1]));~ELSE ~RESULT <= ~VAR[vec][1](~SYM[1]);~FI-end block;+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"- , "templateD" :+ , "template" : "-- replace begin ~GENSYM[replaceVec][0] : block signal ~GENSYM[vec_index][1] : integer range 0 to ~LIT[0]-1;@@ -328,30 +360,38 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.maxIndex"+ , "workInfo" : "Constant"+ , "kind" : "Expression" , "type" : "maxIndex :: KnownNat n => Vec n a -> Int"- , "templateE" : "to_signed(~LIT[0] - 1,~SIZE[~TYPO])"+ , "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"- , "templateE" : "to_signed(~LIT[0],~SIZE[~TYPO])"+ , "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"- , "templateE" : "~TYPMO'(0 to ~LIT[0]-1 => ~IF ~VIVADO ~THEN ~TOBV[~TYPM[1]'(~ARG[1])][~TYP[1]] ~ELSE ~ARG[1] ~FI)"+ , "template" : "~TYPMO'(0 to ~LIT[0]-1 => ~IF ~VIVADO ~THEN ~TOBV[~TYPM[1]'(~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)"- , "templateD" :+ , "template" : "-- transpose begin-~GENSYM[transpose_outer][2] : for ~GENSYM[row_index][3] in ~VAR[matrix][1]'range generate+~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])((~VAR[matrix][1]'length-~SYM[3])*~SIZE[~TYPEL[~TYPEL[~TYPO]]]-1 downto (~VAR[matrix][1]'length-~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])((~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;@@ -360,30 +400,28 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.reverse"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "reverse :: Vec n a -> Vec n a"- , "templateD" :+ , "template" : "-- reverse begin-~GENSYM[reverse_loop][2] : for ~GENSYM[i][3] in ~VAR[vec][0]'range generate+~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.lazyV"- , "type" : "lazyV :: KnownNat n => Vec n a -> Vec n a"- , "templateE" : "~ARG[1]"- }- }-, { "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)"- , "templateD" :+ , "template" : "-- concatBitVector begin-~GENSYM[concatBitVectorIter_loop][2] : for ~GENSYM[i][3] in ~VAR[vec][2]'range generate+~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"@@ -391,11 +429,13 @@ } , { "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)"- , "templateD" :+ , "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]));@@ -405,8 +445,10 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.rotateLeftS"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "rotateLeftS :: KnownNat n => Vec n a -> SNat d -> Vec n a"- , "templateD" :+ , "template" : "-- rotateLeftS begin ~GENSYM[rotateLeftS][0] : block constant ~GENSYM[shift_amount][2] : natural := ~LIT[2] mod ~LIT[0];@@ -425,8 +467,10 @@ } , { "BlackBox" : { "name" : "Clash.Sized.Vector.rotateRightS"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "rotateRightS :: KnownNat n => Vec n a -> SNat d -> Vec n a"- , "templateD" :+ , "template" : "-- rotateRightS begin ~GENSYM[rotateLeftS][0] : block constant ~GENSYM[shift_amount][2] : natural := ~LIT[2] mod ~LIT[0];
+ prims/vhdl/Clash_Transformations.json view
@@ -0,0 +1,8 @@+[ { "BlackBox" :+ { "name" : "Clash.Transformations.eqInt"+ , "kind" : "Expression"+ , "type" : "eqInt :: Int -> Int -> Bool"+ , "template" : "~ARG[0] = ~ARG[1]"+ }+ }+]
prims/vhdl/Clash_Xilinx_ClockGen.json view
@@ -1,26 +1,30 @@ [ { "BlackBox" : { "name" : "Clash.Xilinx.ClockGen.clockWizard"+ , "workInfo" : "Always"+ , "kind" : "Declaration" , "type" : "clockWizard- :: SSymbol name -- ARG[0]- -> Clock pllIn 'Source -- ARG[1]- -> Reset pllIn 'Asynchronous -- ARG[2]- -> (Clock pllOut 'Source, Signal pllOut Bool)"- , "templateD" :+ :: ( 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[0]+ 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[0] port map (~ARG[1],~ARG[2],~SYM[1],~SYM[2]);+ ~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;@@ -29,21 +33,25 @@ } , { "BlackBox" : { "name" : "Clash.Xilinx.ClockGen.clockWizardDifferential"+ , "workInfo" : "Always"+ , "kind" : "Declaration" , "type" : "clockWizardDifferential- :: SSymbol name -- ARG[0]- -> Clock pllIn 'Source -- ARG[1]- -> Clock pllIn 'Source -- ARG[2]- -> Reset pllIn 'Asynchronous -- ARG[3]- -> (Clock pllOut 'Source, Signal pllOut Bool)"- , "templateD" :+ :: ( 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[0]+ component ~NAME[2] port (CLK_IN1_D_clk_n : in std_logic; CLK_IN1_D_clk_p : in std_logic; RESET : in std_logic;@@ -51,8 +59,8 @@ LOCKED : out std_logic); end component; begin- ~GENSYM[clockWizardDifferential_inst][4] : component ~NAME[0]- port map (~ARG[1],~ARG[2],~ARG[3],~SYM[1],~SYM[2]);+ ~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;
prims/vhdl/Clash_Xilinx_DDR.json view
@@ -1,30 +1,29 @@ [ { "BlackBox" : { "name" : "Clash.Xilinx.DDR.iddr"+ , "kind" : "Declaration" , "type" : "iddr- :: ( HasCallStack -- ARG[0]- , fast ~ Dom n pFast -- ARG[1]- , slow ~ Dom n (2*pFast) -- ARG[2]- , KnownNat m ) -- ARG[3]- -> Clock slow gated -- ARG[4]- -> Reset slow synchronous -- ARG[5]- -> Signal fast (BitVector m) -- ARG[6]+ :: ( 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"]- , "templateD" :+ , "template" : "-- iddr begin ~GENSYM[~COMPNAME_IDDR][0] : block- signal ~GENSYM[dataout_l][1] : ~TYP[6];- signal ~GENSYM[dataout_h][2] : ~TYP[6];- signal ~GENSYM[d][3] : ~TYP[6];~IF ~ISGATED[4] ~THEN- signal ~GENSYM[clk][4] : std_logic;- signal ~GENSYM[ce][5] : boolean;- signal ~GENSYM[ce_logic][6]: std_logic;~ELSE ~FI-begin~IF ~ISGATED[4] ~THEN- (~SYM[4],~SYM[5]) <= ~ARG[4];- ~SYM[6] <= '1' when (~SYM[5]) else '0';~ELSE ~FI- ~SYM[3] <= ~ARG[6];+ 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@@ -33,14 +32,12 @@ DDR_CLK_EDGE => \"SAME_EDGE\", INIT_Q1 => '0', INIT_Q2 => '0',- SRTYPE => ~IF ~ISSYNC[5] ~THEN \"SYNC\" ~ELSE \"ASYNC\" ~FI)+ 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~IF ~ISGATED[4] ~THEN- C => ~SYM[4], -- 1-bit clock input- CE => ~SYM[6], -- 1-bit clock enable input~ELSE+ Q2 => ~SYM[2](~SYM[8]), -- 1-bit output for negative edge of clock C => ~ARG[4], -- 1-bit clock input- CE => '1', -- 1-bit clock enable input~FI+ 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@@ -54,32 +51,31 @@ } , { "BlackBox" : { "name" : "Clash.Xilinx.DDR.oddr#"+ , "kind" : "Declaration" , "type" : "oddr#- :: ( slow ~ Dom n (2*pFast) -- ARG[0]- , fast ~ Dom n pFast -- ARG[1]- , KnownNat m ) -- ARG[2]- => Clock slow gated -- ARG[3]- -> Reset slow synchronous -- ARG[4]- -> Signal slow (BitVector m) -- ARG[5]- -> Signal slow (BitVector m) -- ARG[6]+ :: ( 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"]- , "templateD" :+ , "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 ~ISGATED[3] ~THEN- signal ~GENSYM[clk][4] : std_logic;- signal ~GENSYM[ce][5] : boolean;- signal ~GENSYM[ce_logic][6] : std_logic;~ELSE ~FI-begin~IF ~ISGATED[3] ~THEN- (~SYM[4],~SYM[5]) <= ~ARG[3];- ~SYM[6] <= '1' when (~SYM[5]) else '0';~ELSE ~FI- ~SYM[1] <= ~ARG[5];- ~SYM[2] <= ~ARG[6];+ 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@@ -87,13 +83,11 @@ generic map( DDR_CLK_EDGE => \"SAME_EDGE\", INIT => '0',- SRTYPE => ~IF ~ISSYNC[4] ~THEN \"SYNC\" ~ELSE \"ASYNC\" ~FI)+ SRTYPE => ~IF ~ISSYNC[2] ~THEN \"SYNC\" ~ELSE \"ASYNC\" ~FI) port map (- Q => ~SYM[3](~SYM[8]), -- 1-bit DDR output~IF ~ISGATED[3] ~THEN- C => ~SYM[4], -- 1-bit clock input- CE => ~SYM[6], -- 1-bit clock enable input~ELSE+ Q => ~SYM[3](~SYM[8]), -- 1-bit DDR output C => ~ARG[3], -- 1-bit clock input- CE => '1', -- 1-bit clock enable input~FI+ 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
prims/vhdl/GHC_Base.json view
@@ -1,24 +1,15 @@-[ { "Primitive" :- { "name" : "GHC.Base.$"- , "primType" : "Function"- }- }-, { "BlackBox" :- { "name" : "GHC.Base.quotInt"- , "type" : "quotInt :: Int -> Int -> Int"- , "templateE" : "~ARG[0] / ~ARG[1]"- }- }-, { "BlackBox" :+[ { "BlackBox" : { "name" : "GHC.Base.remInt"+ , "kind" : "Expression" , "type" : "remInt :: Int -> Int -> Int"- , "templateE" : "~ARG[0] rem ~ARG[1]"+ , "template" : "~ARG[0] rem ~ARG[1]" } } , { "BlackBox" : { "name" : "GHC.Base.divInt"+ , "kind" : "Declaration" , "type" : "divInt :: Int -> Int -> Int"- , "templateD" :+ , "template" : "-- divInt begin ~GENSYM[divInt][0] : block signal ~GENSYM[quot_res][1] : ~TYP[1];@@ -32,8 +23,9 @@ } , { "BlackBox" : { "name" : "GHC.Base.modInt"+ , "kind" : "Expression" , "type" : "modInt :: Int -> Int -> Int"- , "templateE" : "~ARG[0] mod ~ARG[1]"+ , "template" : "~ARG[0] mod ~ARG[1]" } } ]
prims/vhdl/GHC_Classes.json view
@@ -1,61 +1,43 @@ [ { "BlackBox" : { "name" : "GHC.Classes.eqInt"+ , "kind" : "Expression" , "type" : "eqInt :: Int -> Int -> Bool"- , "templateE" : "~ARG[0] = ~ARG[1]"+ , "template" : "~ARG[0] = ~ARG[1]" } } , { "BlackBox" : { "name" : "GHC.Classes.neInt"+ , "kind" : "Expression" , "type" : "neInt :: Int -> Int -> Bool"- , "templateE" : "~ARG[0] /= ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.gtInt"- , "type" : "gtInt :: Int -> Int -> Bool"- , "templateE" : "~ARG[0] > ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.geInt"- , "type" : "geInt :: Int -> Int -> Bool"- , "templateE" : "~ARG[0] >= ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.ltInt"- , "type" : "ltInt :: Int -> Int -> Bool"- , "templateE" : "~ARG[0] < ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Classes.leInt"- , "type" : "leInt :: Int -> Int -> Bool"- , "templateE" : "~ARG[0] <= ~ARG[1]"+ , "template" : "~ARG[0] /= ~ARG[1]" } } , { "BlackBox" : { "name" : "GHC.Classes.&&"+ , "kind" : "Expression" , "type" : "(&&) :: Bool -> Bool -> Bool"- , "templateE" : "~ARG[0] and ~ARG[1]"+ , "template" : "~ARG[0] and ~ARG[1]" } } , { "BlackBox" : { "name" : "GHC.Classes.||"+ , "kind" : "Expression" , "type" : "(::) :: Bool -> Bool -> Bool"- , "templateE" : "~ARG[0] or ~ARG[1]"+ , "template" : "~ARG[0] or ~ARG[1]" } } , { "BlackBox" : { "name" : "GHC.Classes.not"+ , "kind" : "Expression" , "type" : "not :: Bool -> Bool"- , "templateE" : "not ~ARG[0]"+ , "template" : "not ~ARG[0]" } } , { "BlackBox" : { "name" : "GHC.Classes.divInt#"+ , "kind" : "Declaration" , "type" : "divInt# :: Int# -> Int# -> Int#"- , "templateD" :+ , "template" : "-- divInt begin ~GENSYM[divInt][0] : block signal ~GENSYM[quot_res][1] : ~TYP[1];@@ -69,8 +51,9 @@ } , { "BlackBox" : { "name" : "GHC.Classes.modInt#"+ , "kind" : "Expression" , "type" : "modInt# :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] mod ~ARG[1]"+ , "template" : "~ARG[0] mod ~ARG[1]" } } ]
prims/vhdl/GHC_Int.json view
@@ -1,25 +1,33 @@ [ { "BlackBox" : { "name" : "GHC.Int.I8#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "I8# :: Int# -> Int8"- , "templateE" : "resize(~ARG[0],8)"+ , "template" : "resize(~ARG[0],8)" } } , { "BlackBox" : { "name" : "GHC.Int.I16#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "I16# :: Int# -> Int16"- , "templateE" : "resize(~ARG[0],16)"+ , "template" : "resize(~ARG[0],16)" } } , { "BlackBox" : { "name" : "GHC.Int.I32#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "I32# :: Int# -> Int32"- , "templateE" : "resize(~ARG[0],32)"+ , "template" : "resize(~ARG[0],32)" } } , { "BlackBox" : { "name" : "GHC.Int.I64#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "I64# :: Int# -> Int64"- , "templateE" : "resize(~ARG[0],64)"+ , "template" : "resize(~ARG[0],64)" } } ]
prims/vhdl/GHC_Integer_Logarithms.json view
@@ -1,7 +1,8 @@ [ { "BlackBox" : { "name" : "GHC.Integer.Logarithms.integerLogBase#"+ , "kind" : "Expression" , "type" : "integerLogBase# :: Integer -> Integer -> Int#"- , "templateE" : "integer(floor(log(real(~ARG[1]),real(~ARG[0]))))"+ , "template" : "integer(floor(log(real(~ARG[1]),real(~ARG[0]))))" } } ]
prims/vhdl/GHC_Integer_Type.json view
@@ -1,49 +1,45 @@ [ { "BlackBox" : { "name" : "GHC.Integer.Type.smallInteger"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "smallInteger :: Int# -> Integer"- , "templateE" : "~ARG[0]"+ , "template" : "~ARG[0]" } } , { "BlackBox" : { "name" : "GHC.Integer.Type.integerToInt"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "integerToInt :: Integer -> Int#"- , "templateE" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.plusInteger"- , "type" : "plusInteger :: Integer -> Integer -> Integer"- , "templateE" : "~ARG[0] + ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.minusInteger"- , "type" : "minusInteger :: Integer -> Integer -> Integer"- , "templateE" : "~ARG[0] - ~ARG[1]"+ , "template" : "~ARG[0]" } } , { "BlackBox" : { "name" : "GHC.Integer.Type.timesInteger"+ , "kind" : "Expression" , "type" : "timesInteger :: Integer -> Integer -> Integer"- , "templateE" : "resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO])"+ , "template" : "resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO])" } } , { "BlackBox" : { "name" : "GHC.Integer.Type.negateInteger"+ , "kind" : "Expression" , "type" : "negateInteger :: Integer -> Integer"- , "templateE" : "-~ARG[0]"+ , "template" : "-~ARG[0]" } } , { "BlackBox" : { "name" : "GHC.Integer.Type.absInteger"+ , "kind" : "Expression" , "type" : "absInteger :: Integer -> Integer"- , "templateE" : "abs ~ARG[0]"+ , "template" : "abs ~ARG[0]" } } , { "BlackBox" : { "name" : "GHC.Integer.Type.divInteger"+ , "kind" : "Declaration" , "type" : "divInteger :: Integer -> Integer -> Integer"- , "templateD" :+ , "template" : "-- divInteger begin ~GENSYM[divInteger][0] : block signal ~GENSYM[quot_res][1] : ~TYP[1];@@ -57,116 +53,166 @@ } , { "BlackBox" : { "name" : "GHC.Integer.Type.modInteger"+ , "kind" : "Expression" , "type" : "modInteger :: Integer -> Integer -> Integer"- , "templateE" : "~ARG[0] mod ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.quotInteger"- , "type" : "quotInteger :: Integer -> Integer -> Integer"- , "templateE" : "~ARG[0] / ~ARG[1]"+ , "template" : "~ARG[0] mod ~ARG[1]" } } , { "BlackBox" : { "name" : "GHC.Integer.Type.remInteger"+ , "kind" : "Expression" , "type" : "remInteger :: Integer -> Integer -> Integer"- , "templateE" : "~ARG[0] rem ~ARG[1]"+ , "template" : "~ARG[0] rem ~ARG[1]" } } , { "BlackBox" : { "name" : "GHC.Integer.Type.eqInteger"+ , "kind" : "Expression" , "type" : "eqInteger :: Integer -> Integer -> Bool"- , "templateE" : "~ARG[0] = ~ARG[1]"+ , "template" : "~ARG[0] = ~ARG[1]" } } , { "BlackBox" : { "name" : "GHC.Integer.Type.neqInteger"+ , "kind" : "Expression" , "type" : "neqInteger :: Integer -> Integer -> Bool"- , "templateE" : "~ARG[0] /= ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.leInteger"- , "type" : "leInteger :: Integer -> Integer -> Bool"- , "templateE" : "~ARG[0] <= ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.gtInteger"- , "type" : "gtInteger :: Integer -> Integer -> Bool"- , "templateE" : "~ARG[0] > ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.ltInteger"- , "type" : "ltInteger :: Integer -> Integer -> Bool"- , "templateE" : "~ARG[0] < ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Integer.Type.geInteger"- , "type" : "geInteger :: Integer -> Integer -> Bool"- , "templateE" : "~ARG[0] >= ~ARG[1]"+ , "template" : "~ARG[0] /= ~ARG[1]" } } , { "BlackBox" : { "name" : "GHC.Integer.Type.eqInteger#"+ , "kind" : "Declaration" , "type" : "eqInteger# :: Integer -> Integer -> Int#"- , "templateD" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"+ , "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#"- , "templateD" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"+ , "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#"- , "templateD" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"+ , "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#"- , "templateD" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"+ , "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#"- , "templateD" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"+ , "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#"- , "templateD" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"+ , "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" : "Expression" , "type" : "shiftRInteger :: Integer -> Int# -> Integer"- , "templateE" : "shift_right(~ARG[0],to_integer(~ARG[1]))"+ , "template" : "shift_right(~ARG[0],to_integer(~ARG[1]))" } } , { "BlackBox" : { "name" : "GHC.Integer.Type.shiftLInteger"+ , "kind" : "Expression" , "type" : "shiftLInteger :: Integer -> Int# -> Integer"- , "templateE" : "shift_left(~ARG[0],to_integer(~ARG[1]))"+ , "template" : "shift_left(~ARG[0],to_integer(~ARG[1]))" } } , { "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"- , "templateE" : "signed(std_logic_vector(~ARG[0]))"+ , "template" : "signed(std_logic_vector(~ARG[0]))" } } , { "BlackBox" : { "name" : "GHC.Integer.Type.integerToWord"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "integerToWord :: Integer -> Word#"- , "templateE" : "unsigned(std_logic_vector(~ARG[0]))"+ , "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_Natural.json view
@@ -0,0 +1,32 @@+[+ {+ "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_Prim.json view
@@ -1,295 +1,305 @@ [ { "BlackBox" : { "name" : "GHC.Prim.gtChar#"+ , "kind" : "Declaration" , "type" : "gtChar# :: Char# -> Char# -> Int#"- , "templateD" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"+ , "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#"- , "templateD" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"+ , "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#"- , "templateD" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"+ , "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#"- , "templateD" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"+ , "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#"- , "templateD" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"+ , "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#"- , "templateD" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"+ , "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#"- , "templateE" : "signed(std_logic_vector(resize(~ARG[0],~SIZE[~TYPO])))"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.+#"- , "type" : "(+#) :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] + ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.-#"- , "type" : "(-#) :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] - ~ARG[1]"+ , "template" : "signed(std_logic_vector(resize(~ARG[0],~SIZE[~TYPO])))" } } , { "BlackBox" : { "name" : "GHC.Prim.*#"+ , "kind" : "Expression" , "type" : "(*#) :: Int# -> Int# -> Int#"- , "templateE" : "resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO])"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.quotInt#"- , "type" : "quotInt# :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] / ~ARG[1]"+ , "template" : "resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO])" } } , { "BlackBox" : { "name" : "GHC.Prim.remInt#"+ , "kind" : "Expression" , "type" : "remInt# :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] rem ~ARG[1]"+ , "template" : "~ARG[0] rem ~ARG[1]" } } , { "BlackBox" : { "name" : "GHC.Prim.quotRemInt#"+ , "kind" : "Expression" , "type" : "quotRemInt# :: Int# -> Int# -> (#Int#, Int##)"- , "templateE" : "(~ARG[0] / ~ARG[1], ~ARG[0] rem ~ARG[1])"+ , "template" : "(~ARG[0] / ~ARG[1], ~ARG[0] rem ~ARG[1])" } } , { "BlackBox" : { "name" : "GHC.Prim.andI#"+ , "kind" : "Expression" , "type" : "and# :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] and ~ARG[1]"+ , "template" : "~ARG[0] and ~ARG[1]" } } , { "BlackBox" : { "name" : "GHC.Prim.orI#"+ , "kind" : "Expression" , "type" : "or# :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] or ~ARG[1]"+ , "template" : "~ARG[0] or ~ARG[1]" } } , { "BlackBox" : { "name" : "GHC.Prim.xorI#"+ , "kind" : "Expression" , "type" : "xor# :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] xor ~ARG[1]"+ , "template" : "~ARG[0] xor ~ARG[1]" } } , { "BlackBox" : { "name" : "GHC.Prim.notI#"+ , "kind" : "Expression" , "type" : "not# :: Int# -> Int#"- , "templateE" : "not ~ARG[0]"+ , "template" : "not ~ARG[0]" } } , { "BlackBox" : { "name" : "GHC.Prim.negateInt#"+ , "kind" : "Expression" , "type" : "negateInt# :: Int# -> Int#"- , "templateE" : "-~ARG[0]"+ , "template" : "-~ARG[0]" } } , { "BlackBox" : { "name" : "GHC.Prim.>#"+ , "kind" : "Declaration" , "type" : "(>#) :: Int# -> Int# -> Int#"- , "templateD" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"+ , "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#"- , "templateD" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"+ , "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#"- , "templateD" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"+ , "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#"- , "templateD" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"+ , "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#"- , "templateD" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"+ , "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#"- , "templateD" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"+ , "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#"- , "templateE" : "resize(unsigned(std_logic_vector(~ARG[0])),21)"+ , "template" : "resize(unsigned(std_logic_vector(~ARG[0])),21)" } } , { "BlackBox" : { "name" : "GHC.Prim.int2Word#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "word2Int# :: Int# -> Word#"- , "templateE" : "unsigned(std_logic_vector(~ARG[0]))"+ , "template" : "unsigned(std_logic_vector(~ARG[0]))" } } , { "BlackBox" : { "name" : "GHC.Prim.uncheckedIShiftL#"+ , "kind" : "Expression" , "type" : "uncheckedIShiftL# :: Int# -> Int# -> Int#"- , "templateE" : "shift_left(~ARG[0],to_integer(~ARG[1]))"+ , "template" : "shift_left(~ARG[0],to_integer(~ARG[1]))" } } , { "BlackBox" : { "name" : "GHC.Prim.uncheckedIShiftRA#"+ , "kind" : "Expression" , "type" : "uncheckedIShiftRA# :: Int# -> Int# -> Int#"- , "templateE" : "shift_right(~ARG[0],to_integer(~ARG[1]))"+ , "template" : "shift_right(~ARG[0],to_integer(~ARG[1]))" } } , { "BlackBox" : { "name" : "GHC.Prim.uncheckedIShiftRL#"+ , "kind" : "Expression" , "type" : "uncheckedIShiftRL# :: Int# -> Int# -> Int#"- , "templateE" : "~ARG[0] srl to_integer(~ARG[1])"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.plusWord#"- , "type" : "plusWord# :: Word# -> Word# -> Word#"- , "templateE" : "~ARG[0] + ~ARG[1]"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.minusWord#"- , "type" : "minusWord# :: Word# -> Word# -> Word#"- , "templateE" : "~ARG[0] - ~ARG[1]"+ , "template" : "~ARG[0] srl to_integer(~ARG[1])" } } , { "BlackBox" : { "name" : "GHC.Prim.timesWord#"+ , "kind" : "Expression" , "type" : "timesWord# :: Word# -> Word# -> Word#"- , "templateE" : "resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO])"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.quotWord#"- , "type" : "quotWord# :: Word# -> Word# -> Word#"- , "templateE" : "~ARG[0] / ~ARG[1]"+ , "template" : "resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO])" } } , { "BlackBox" : { "name" : "GHC.Prim.remWord#"+ , "kind" : "Expression" , "type" : "remWord# :: Word# -> Word# -> Word#"- , "templateE" : "~ARG[0] rem ~ARG[1]"+ , "template" : "~ARG[0] rem ~ARG[1]" } } , { "BlackBox" : { "name" : "GHC.Prim.quotRemWord#"+ , "kind" : "Expression" , "type" : "quotRemWord# :: Word# -> Word# -> (#Word#, Word##)"- , "templateE" : "(~ARG[0] / ~ARG[1], ~ARG[0] rem ~ARG[1])"+ , "template" : "(~ARG[0] / ~ARG[1], ~ARG[0] rem ~ARG[1])" } } , { "BlackBox" : { "name" : "GHC.Prim.and#"+ , "kind" : "Expression" , "type" : "and# :: Word# -> Word# -> Word#"- , "templateE" : "~ARG[0] and ~ARG[1]"+ , "template" : "~ARG[0] and ~ARG[1]" } } , { "BlackBox" : { "name" : "GHC.Prim.or#"+ , "kind" : "Expression" , "type" : "or# :: Word# -> Word# -> Word#"- , "templateE" : "~ARG[0] or ~ARG[1]"+ , "template" : "~ARG[0] or ~ARG[1]" } } , { "BlackBox" : { "name" : "GHC.Prim.xor#"+ , "kind" : "Expression" , "type" : "xor# :: Word# -> Word# -> Word#"- , "templateE" : "~ARG[0] xor ~ARG[1]"+ , "template" : "~ARG[0] xor ~ARG[1]" } } , { "BlackBox" : { "name" : "GHC.Prim.not#"+ , "kind" : "Expression" , "type" : "not# :: Word# -> Word#"- , "templateE" : "not ~ARG[0]"+ , "template" : "not ~ARG[0]" } } , { "BlackBox" : { "name" : "GHC.Prim.uncheckedShiftL#"+ , "kind" : "Expression" , "type" : "uncheckedShiftL# :: Word# -> Int# -> Word#"- , "templateE" : "shift_left(~ARG[0],to_integer(~ARG[1]))"+ , "template" : "shift_left(~ARG[0],to_integer(~ARG[1]))" } } , { "BlackBox" : { "name" : "GHC.Prim.uncheckedShiftRL#"+ , "kind" : "Expression" , "type" : "uncheckedShiftR# :: Word# -> Int# -> Word#"- , "templateE" : "shift_right(~ARG[0],to_integer(~ARG[1]))"+ , "template" : "shift_right(~ARG[0],to_integer(~ARG[1]))" } } , { "BlackBox" : { "name" : "GHC.Prim.word2Int#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "word2Int# :: word# -> Int#"- , "templateE" : "signed(std_logic_vector(~ARG[0]))"+ , "template" : "signed(std_logic_vector(~ARG[0]))" } } , { "BlackBox" : { "name" : "GHC.Prim.gtWord#"+ , "kind" : "Declaration" , "type" : "gtWord# :: Word# -> Word# -> Int#"- , "templateD" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"+ , "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#"- , "templateD" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"+ , "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#"- , "templateD" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"+ , "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#"- , "templateD" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"+ , "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#"- , "templateD" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"+ , "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#"- , "templateD" : "~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);"+ , "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#"- , "templateD" :+ , "template" : "-- popCnt8 begin ~GENSYM[popCnt8][0] : block -- given a level and a depth, calculate the corresponding index into the@@ -306,7 +316,7 @@ 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](i) <= resize(~ARG[0](~SYM[7] downto ~SYM[7]),~SYM[3]+1);+ ~SYM[5](~SYM[7]) <= resize(~VAR[input][0](~SYM[7] downto ~SYM[7]),~SYM[3]+1); end generate; -- Create the tree of adders@@ -328,8 +338,9 @@ } , { "BlackBox" : { "name" : "GHC.Prim.popCnt16#"+ , "kind" : "Declaration" , "type" : "popCnt16 :: Word# -> Word#"- , "templateD" :+ , "template" : "-- popCnt16 begin ~GENSYM[popCnt16][0] : block -- given a level and a depth, calculate the corresponding index into the@@ -346,7 +357,7 @@ 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](i) <= resize(~ARG[0](~SYM[7] downto ~SYM[7]),~SYM[3]+1);+ ~SYM[5](~SYM[7]) <= resize(~VAR[input][0](~SYM[7] downto ~SYM[7]),~SYM[3]+1); end generate; -- Create the tree of adders@@ -368,8 +379,9 @@ } , { "BlackBox" : { "name" : "GHC.Prim.popCnt32#"- , "type" : "popCnt16 :: Word# -> Word#"- , "templateD" :+ , "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@@ -386,7 +398,7 @@ 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](i) <= resize(~ARG[0](~SYM[7] downto ~SYM[7]),~SYM[3]+1);+ ~SYM[5](~SYM[7]) <= resize(~VAR[input][0](~SYM[7] downto ~SYM[7]),~SYM[3]+1); end generate; -- Create the tree of adders@@ -408,8 +420,9 @@ } , { "BlackBox" : { "name" : "GHC.Prim.popCnt64#"- , "type" : "popCnt16 :: Word# -> Word#"- , "templateD" :+ , "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@@ -426,7 +439,7 @@ 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](i) <= resize(~ARG[0](~SYM[7] downto ~SYM[7]),~SYM[3]+1);+ ~SYM[5](~SYM[7]) <= resize(~VAR[input][0](~SYM[7] downto ~SYM[7]),~SYM[3]+1); end generate; -- Create the tree of adders@@ -448,8 +461,9 @@ } , { "BlackBox" : { "name" : "GHC.Prim.popCnt#"+ , "kind" : "Declaration" , "type" : "popCnt :: Word# -> Word#"- , "templateD" :+ , "template" : "-- popCnt begin ~GENSYM[popCnt][0] : block -- given a level and a depth, calculate the corresponding index into the@@ -466,7 +480,7 @@ 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](i) <= resize(~ARG[0](~SYM[7] downto ~SYM[7]),~SYM[3]+1);+ ~SYM[5](~SYM[7]) <= resize(~VAR[input][0](~SYM[7] downto ~SYM[7]),~SYM[3]+1); end generate; -- Create the tree of adders@@ -488,8 +502,9 @@ } , { "BlackBox" : { "name" : "GHC.Prim.clz8#"+ , "kind" : "Declaration" , "type" : "clz8 :: Word# -> Word#"- , "templateD" :+ , "template" : "-- clz8 begin ~GENSYM[clz8][0] : block function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is@@ -530,8 +545,9 @@ } , { "BlackBox" : { "name" : "GHC.Prim.clz16#"+ , "kind" : "Declaration" , "type" : "clz16 :: Word# -> Word#"- , "templateD" :+ , "template" : "-- clz16 begin clz16~SYM[0] : block function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is@@ -574,8 +590,9 @@ } , { "BlackBox" : { "name" : "GHC.Prim.clz32#"+ , "kind" : "Declaration" , "type" : "clz32 :: Word# -> Word#"- , "templateD" :+ , "template" : "-- clz32 begin clz32~SYM[0] : block function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is@@ -620,8 +637,9 @@ } , { "BlackBox" : { "name" : "GHC.Prim.clz64#"+ , "kind" : "Declaration" , "type" : "clz64 :: Word# -> Word#"- , "templateD" :+ , "template" : "-- clz64 begin clz64~SYM[0] : block function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is@@ -668,8 +686,9 @@ } , { "BlackBox" : { "name" : "GHC.Prim.clz#"+ , "kind" : "Declaration" , "type" : "clz :: Word# -> Word#"- , "templateD" :+ , "template" : "-- clz begin clz~SYM[0] : block function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is@@ -734,8 +753,9 @@ } , { "BlackBox" : { "name" : "GHC.Prim.ctz8#"+ , "kind" : "Declaration" , "type" : "ctz8 :: Word# -> Word#"- , "templateD" :+ , "template" : "-- ctz8 begin ~GENSYM[ctz8][0] : block function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is@@ -785,8 +805,9 @@ } , { "BlackBox" : { "name" : "GHC.Prim.ctz16#"+ , "kind" : "Declaration" , "type" : "ctz16 :: Word# -> Word#"- , "templateD" :+ , "template" : "-- ctz16 begin ~GENSYM[ctz16][0] : block function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is@@ -838,8 +859,9 @@ } , { "BlackBox" : { "name" : "GHC.Prim.ctz32#"+ , "kind" : "Declaration" , "type" : "ctz32 :: Word# -> Word#"- , "templateD" :+ , "template" : "-- ctz32 begin ~GENSYM[ctz32][0] : block function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is@@ -893,8 +915,9 @@ } , { "BlackBox" : { "name" : "GHC.Prim.ctz64#"+ , "kind" : "Declaration" , "type" : "ctz64 :: Word# -> Word#"- , "templateD" :+ , "template" : "-- ctz64 begin ~GENSYM[ctz64][0] : block function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is@@ -947,8 +970,9 @@ } , { "BlackBox" : { "name" : "GHC.Prim.ctz#"+ , "kind" : "Declaration" , "type" : "ctz :: Word# -> Word#"- , "templateD" :+ , "template" : "-- ctz begin ~GENSYM[ctz][0] : block function ~GENSYM[enc][1] (constant a : unsigned(1 downto 0)) return unsigned is@@ -1019,8 +1043,10 @@ } , { "BlackBox" : { "name" : "GHC.Prim.byteSwap16#"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "byteSwap16# :: Word# -> Word#"- , "templateD" :+ , "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@@ -1029,8 +1055,10 @@ } , { "BlackBox" : { "name" : "GHC.Prim.byteSwap32#"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "byteSwap32# :: Word# -> Word#"- , "templateD" :+ , "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@@ -1041,8 +1069,10 @@ } , { "BlackBox" : { "name" : "GHC.Prim.byteSwap64#"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "byteSwap64# :: Word# -> Word#"- , "templateD" :+ , "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)@@ -1053,8 +1083,10 @@ } , { "BlackBox" : { "name" : "GHC.Prim.byteSwap#"+ , "workInfo" : "Never"+ , "kind" : "Declaration" , "type" : "byteSwap# :: Word# -> Word#"- , "templateD" :+ , "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)@@ -1067,54 +1099,50 @@ } , { "BlackBox" : { "name" : "GHC.Prim.narrow8Int#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "narrow8Int# :: Int# -> Int#"- , "templateE" : "resize(~VAR[i][0](7 downto 0),~SIZE[~TYPO])"+ , "template" : "resize(~VAR[i][0](7 downto 0),~SIZE[~TYPO])" } } , { "BlackBox" : { "name" : "GHC.Prim.narrow16Int#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "narrow16Int# :: Int# -> Int#"- , "templateE" : "resize(~VAR[i][0](15 downto 0),~SIZE[~TYPO])"+ , "template" : "resize(~VAR[i][0](15 downto 0),~SIZE[~TYPO])" } } , { "BlackBox" : { "name" : "GHC.Prim.narrow32Int#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "narrow32Int# :: Int# -> Int#"- , "templateE" : "resize(~VAR[i][0](31 downto 0),~SIZE[~TYPO])"+ , "template" : "resize(~VAR[i][0](31 downto 0),~SIZE[~TYPO])" } } , { "BlackBox" : { "name" : "GHC.Prim.narrow8Word#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "narrow8Word# :: Word# -> Word#"- , "templateE" : "resize(~VAR[w][0](7 downto 0),~SIZE[~TYPO])"+ , "template" : "resize(~VAR[w][0](7 downto 0),~SIZE[~TYPO])" } } , { "BlackBox" : { "name" : "GHC.Prim.narrow16Word#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "narrow16Word# :: Word# -> Word#"- , "templateE" : "resize(~VAR[w][0](15 downto 0),~SIZE[~TYPO])"+ , "template" : "resize(~VAR[w][0](15 downto 0),~SIZE[~TYPO])" } } , { "BlackBox" : { "name" : "GHC.Prim.narrow32Word#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "narrow32Word# :: Word# -> Word#"- , "templateE" : "resize(~VAR[w][0](31 downto 0),~SIZE[~TYPO])"- }- }-, { "Primitive" :- { "name" : "GHC.Prim.dataToTag#"- , "primType" : "Function"- }- }-, { "Primitive" :- { "name" : "GHC.Prim.tagToEnum#"- , "primType" : "Function"- }- }-, { "BlackBox" :- { "name" : "GHC.Prim.unsafeCoerce#"- , "type" : "unsafeCoerce# :: a -> b"- , "templateE" : "~ARG[0]"+ , "template" : "resize(~VAR[w][0](31 downto 0),~SIZE[~TYPO])" } } ]
− prims/vhdl/GHC_Types.json
@@ -1,24 +0,0 @@-[ { "Primitive" :- { "name" : "GHC.Types.MkCoercible"- , "primType" : "Constructor"- }- }-, { "BlackBox" :- { "name" : "GHC.Types.C#"- , "type" : "C# :: Char# -> Char"- , "templateE" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Types.I#"- , "type" : "I# :: Int# -> Int"- , "templateE" : "~ARG[0]"- }- }-, { "BlackBox" :- { "name" : "GHC.Types.W#"- , "type" : "W# :: Word# -> Word"- , "templateE" : "~ARG[0]"- }- }-]
prims/vhdl/GHC_Word.json view
@@ -1,25 +1,33 @@ [ { "BlackBox" : { "name" : "GHC.Word.W8#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "W8# :: Word# -> Word8"- , "templateE" : "resize(~ARG[0],8)"+ , "template" : "resize(~ARG[0],8)" } } , { "BlackBox" : { "name" : "GHC.Word.W16#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "W16# :: Word# -> Word16"- , "templateE" : "resize(~ARG[0],16)"+ , "template" : "resize(~ARG[0],16)" } } , { "BlackBox" : { "name" : "GHC.Word.W32#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "W32# :: Word# -> Word32"- , "templateE" : "resize(~ARG[0],32)"+ , "template" : "resize(~ARG[0],32)" } } , { "BlackBox" : { "name" : "GHC.Word.W64#"+ , "workInfo" : "Never"+ , "kind" : "Expression" , "type" : "W64# :: Word# -> Word64"- , "templateE" : "resize(~ARG[0],64)"+ , "template" : "resize(~ARG[0],64)" } } ]
+ src/Clash/Annotations/BitRepresentation/ClashLib.hs view
@@ -0,0 +1,55 @@+{-|+Copyright : (C) 2018, Google Inc.+License : BSD2 (see the file LICENSE)+Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>++Houses internal BitRepresentation code which cannot be housed in clash-prelude+due to its dependencies.+-}++{-# LANGUAGE TemplateHaskell #-}++module Clash.Annotations.BitRepresentation.ClashLib+ ( coreToType'+ , bitsToBits+ ) where++import Clash.Annotations.BitRepresentation.Internal+ (Type'(AppTy',ConstTy',LitTy'))+import qualified Clash.Annotations.BitRepresentation.Util as BitRepresentation+import qualified Clash.Core.Type as C+import Clash.Core.Name (nameOcc)+import qualified Clash.Netlist.Types as Netlist+import Clash.Util (curLoc)++-- Convert Core type to BitRepresentation type+coreToType'+ :: C.Type+ -- ^ Type to convert to bit representation type+ -> Either+ String+ -- Error message+ Type'+ -- Bit representation type+coreToType' (C.AppTy t1 t2) =+ AppTy' <$> coreToType' t1 <*> coreToType' t2+coreToType' (C.ConstTy (C.TyCon name)) =+ return $ ConstTy' (nameOcc name)+coreToType' (C.LitTy (C.NumTy n)) =+ return $ LitTy' n+coreToType' e =+ Left $ $(curLoc) ++ "Unexpected type: " ++ show e+++bitToBit+ :: BitRepresentation.Bit+ -> Netlist.Bit+bitToBit BitRepresentation.H = Netlist.H+bitToBit BitRepresentation.L = Netlist.L+bitToBit BitRepresentation.U = Netlist.U++-- | Converts a list of /BitRepresentation.Bit/s to their Netlist counterpart.+bitsToBits+ :: [BitRepresentation.Bit]+ -> [Netlist.Bit]+bitsToBits = map bitToBit
src/Clash/Annotations/TopEntity/Extra.hs view
@@ -11,8 +11,20 @@ import Clash.Annotations.TopEntity (TopEntity, PortName) import Language.Haskell.TH.Syntax (ModName, Name, NameFlavour, NameSpace, PkgName, OccName)+import Data.Binary (Binary) import Data.Hashable (Hashable)+import Control.DeepSeq (NFData) +instance Binary TopEntity+instance Binary PortName++instance Binary Name+instance Binary OccName+instance Binary NameFlavour+instance Binary ModName+instance Binary NameSpace+instance Binary PkgName+ instance Hashable TopEntity instance Hashable PortName @@ -22,3 +34,13 @@ instance Hashable NameSpace instance Hashable PkgName instance Hashable OccName++instance NFData TopEntity+instance NFData PortName++instance NFData ModName+instance NFData Name+instance NFData NameFlavour+instance NFData NameSpace+instance NFData PkgName+instance NFData OccName
src/Clash/Backend.hs view
@@ -5,28 +5,32 @@ Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com> -} -{-# LANGUAGE MultiWayIf #-} {-# LANGUAGE OverloadedStrings #-} module Clash.Backend where +import Control.Lens (Lens')+import qualified Control.Lens as Lens+import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HashMap import Data.HashSet (HashSet) import Data.Maybe (fromMaybe)-import Data.Semigroup.Monad (Mon)-import qualified Data.Text.Lazy as T-import Data.Text.Lazy (Text)+import Data.Semigroup.Monad (Mon (..))+import qualified Data.Text as T+import Data.Text (Text)+import qualified Data.Text.Lazy as LT import Control.Monad.State (State) import Data.Text.Prettyprint.Doc.Extra (Doc) import SrcLoc (SrcSpan) import Clash.Netlist.Id-import Clash.Netlist.Types+import {-# SOURCE #-} Clash.Netlist.Types import Clash.Netlist.BlackBox.Types import Clash.Annotations.Primitive (HDL) -type ModName = String+type ModName = Identifier -- | Is a type used for internal or external use data Usage@@ -37,7 +41,7 @@ class Backend state where -- | Initial state for state monad- initBackend :: Int -> HdlSyn -> state+ initBackend :: Int -> HdlSyn -> Bool -> Maybe (Maybe Int) -> state -- | What HDL is the backend generating hdlKind :: state -> HDL@@ -46,7 +50,7 @@ primDirs :: state -> IO [FilePath] -- | Name of backend, used for directory to put output files in. Should be- -- | constant function / ignore argument.+ -- constant function / ignore argument. name :: state -> String -- | File extension for target langauge@@ -56,9 +60,9 @@ extractTypes :: state -> HashSet HWType -- | Generate HDL for a Netlist component- genHDL :: String -> SrcSpan -> Component -> Mon (State state) ((String, Doc),[(String,Doc)])+ genHDL :: Identifier -> SrcSpan -> HashMap Identifier Word -> Component -> Mon (State state) ((String, Doc),[(String,Doc)]) -- | Generate a HDL package containing type definitions for the given HWTypes- mkTyPackage :: String -> [HWType] -> Mon (State state) [(String, Doc)]+ mkTyPackage :: Identifier -> [HWType] -> Mon (State state) [(String, Doc)] -- | Convert a Netlist HWType to a target HDL type hdlType :: Usage -> HWType -> Mon (State state) Doc -- | Convert a Netlist HWType to an HDL error value for that type@@ -68,19 +72,21 @@ -- | Create a record selector hdlRecSel :: HWType -> Int -> Mon (State state) Doc -- | Create a signal declaration from an identifier (Text) and Netlist HWType- hdlSig :: Text -> HWType -> Mon (State state) Doc+ hdlSig :: LT.Text -> HWType -> Mon (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) -- | Turn a Netlist expression into a HDL expression- expr :: Bool -> Expr -> Mon (State state) Doc- -- | Bit-width of Int/Word/Integer+ expr :: Bool -- ^ Enclose in parentheses?+ -> Expr -- ^ Expr to convert+ -> Mon (State state) Doc+ -- | Bit-width of Int,Word,Integer iwWidth :: State state Int -- | Convert to a bit-vector- toBV :: HWType -> Text -> Mon (State state) Doc+ toBV :: HWType -> LT.Text -> Mon (State state) Doc -- | Convert from a bit-vector- fromBV :: HWType -> Text -> Mon (State state) Doc+ fromBV :: HWType -> LT.Text -> Mon (State state) Doc -- | Synthesis tool we're generating HDL for hdlSyn :: State state HdlSyn -- | mkIdentifier@@ -97,51 +103,15 @@ blockDecl :: Text -> [Declaration] -> Mon (State state) Doc -- | unextend/unescape identifier unextend :: State state (Identifier -> Identifier)- addInclude :: (String, Doc) -> State state ()- addLibraries :: [Text] -> State state ()- addImports :: [Text] -> State state ()---- | Try to merge nested modifiers into a single modifier, needed by the VHDL--- and SystemVerilog backend.-nestM :: Modifier -> Modifier -> Maybe Modifier-nestM (Nested a b) m2- | Just m1 <- nestM a b = maybe (Just (Nested m1 m2)) Just (nestM m1 m2)- | Just m2' <- nestM b m2 = maybe (Just (Nested a m2')) Just (nestM a m2')--nestM (Indexed (Vector n t1,1,1)) (Indexed (Vector _ t2,1,0))- | t1 == t2 = Just (Indexed (Vector n t1,10,1))--nestM (Indexed (Vector n t1,1,1)) (Indexed (Vector _ t2,10,k))- | t1 == t2 = Just (Indexed (Vector n t1,10,k+1))--nestM (Indexed (RTree d1 t1,1,n)) (Indexed (RTree d2 t2,0,0))- | t1 == t2- , d1 >= 0- , d2 >= 0- = Just (Indexed (RTree d1 t1,10,n))--nestM (Indexed (RTree d1 t1,1,n)) (Indexed (RTree d2 t2,1,m))- | t1 == t2- , d1 >= 0- , d2 >= 0- = if | n == 1 && m == 1 -> let r = 2 ^ d1- l = r - (2 ^ (d1-1) `div` 2)- in Just (Indexed (RTree (-1) t1, l, r))- | n == 1 && m == 0 -> let l = 2 ^ (d1-1)- r = l + (l `div` 2)- in Just (Indexed (RTree (-1) t1, l, r))- | n == 0 && m == 1 -> let l = (2 ^ (d1-1)) `div` 2- r = 2 ^ (d1-1)- in Just (Indexed (RTree (-1) t1, l, r))- | n == 0 && m == 0 -> let l = 0- r = (2 ^ (d1-1)) `div` 2- in Just (Indexed (RTree (-1) t1, l, r))-nestM (Indexed (RTree (-1) t1,l,_)) (Indexed (RTree d t2,10,k))- | t1 == t2- , d >= 0- = Just (Indexed (RTree d t1,10,l+k))--nestM _ _ = Nothing+ addIncludes :: [(String, Doc)] -> State state ()+ addLibraries :: [LT.Text] -> State state ()+ addImports :: [LT.Text] -> State state ()+ addAndSetData :: FilePath -> State state String+ getDataFiles :: State state [(String,FilePath)]+ addMemoryDataFile :: (String,String) -> State state ()+ getMemoryDataFiles :: State state [(String,String)]+ seenIdentifiers :: Lens' state (HashMap Identifier Word)+ ifThenElseExpr :: state -> Bool -- | Replace a normal HDL template placeholder with an unescaped/unextended -- template placeholder.@@ -155,3 +125,37 @@ t1 <- T.stripPrefix "~ARG[" t n <- T.stripSuffix "]" t1 pure (T.concat ["~EARG[",n,"]"])++mkUniqueIdentifier+ :: Backend s+ => IdType+ -> Identifier+ -> State s Identifier+mkUniqueIdentifier typ nm = do+ mkId <- mkIdentifier+ extendId <- extendIdentifier+ seen <- Lens.use seenIdentifiers+ let i = mkId typ nm+ case HashMap.lookup i seen of+ Just n -> go extendId n seen i+ Nothing -> do+ seenIdentifiers Lens.%= (HashMap.insert i 0)+ return i+ where+ go extendId n seen i = do+ let i' = extendId typ i (T.pack ('_':show n))+ case HashMap.lookup i' seen of+ Just _ -> go extendId (n+1) seen i+ Nothing -> do+ seenIdentifiers Lens.%= (HashMap.insert i' (n+1))+ return i'++preserveSeen+ :: Backend s+ => Mon (State s) a+ -> Mon (State s) a+preserveSeen m = do+ s <- Mon (Lens.use seenIdentifiers)+ a <- m+ Mon (seenIdentifiers Lens..= s)+ return a
src/Clash/Backend/SystemVerilog.hs view
@@ -1,6 +1,6 @@ {-| Copyright : (C) 2015-2016, University of Twente,- 2017, Google Inc.+ 2017-2018, Google Inc. License : BSD2 (see the file LICENSE) Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com> @@ -9,6 +9,7 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiWayIf #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecursiveDo #-} {-# LANGUAGE TemplateHaskell #-}@@ -21,9 +22,10 @@ import Control.Lens hiding (Indexed) import Control.Monad (forM,liftM,zipWithM) import Control.Monad.State (State)-import Data.Graph.Inductive (Gr, mkGraph, topsort')+import Data.Bits (Bits, testBit) import Data.HashMap.Lazy (HashMap) import qualified Data.HashMap.Lazy as HashMap+import qualified Data.HashMap.Strict as HashMapS import Data.HashSet (HashSet) import qualified Data.HashSet as HashSet import Data.List (nub, nubBy)@@ -32,8 +34,8 @@ import Data.Monoid hiding (Sum, Product) #endif import Data.Semigroup.Monad-import Data.Text.Lazy (pack,unpack) import qualified Data.Text.Lazy as Text+import qualified Data.Text as TextS import Data.Text.Prettyprint.Doc.Extra #ifdef CABAL import qualified Data.Version@@ -41,16 +43,24 @@ import qualified System.FilePath import Clash.Annotations.Primitive (HDL (..))+import Clash.Annotations.BitRepresentation.Internal+ (ConstrRepr'(..))+import Clash.Annotations.BitRepresentation.ClashLib+ (bitsToBits)+import Clash.Annotations.BitRepresentation.Util+ (BitOrigin(Lit, Field), bitOrigins, bitRanges)+import Clash.Core.Var (Attr'(..)) import Clash.Backend-import Clash.Backend.Verilog (include)-import Clash.Driver.Types (SrcSpan, noSrcSpan)+import Clash.Backend.Verilog (bits, bit_char, encodingNote, exprLit, include, uselibs) import Clash.Netlist.BlackBox.Types (HdlSyn (..))-import Clash.Netlist.BlackBox.Util (extractLiterals, renderBlackBox)+import Clash.Netlist.BlackBox.Util+ (extractLiterals, renderBlackBox, renderFilePath) import Clash.Netlist.Id (IdType (..), mkBasicId') import Clash.Netlist.Types hiding (_intWidth, intWidth) import Clash.Netlist.Util hiding (mkIdentifier, extendIdentifier)-import Clash.Signal.Internal (ClockKind (..))-import Clash.Util (curLoc, makeCached, (<:>))+import Clash.Util+ (SrcSpan, noSrcSpan, curLoc, makeCached, (<:>), first, on, traceIf)+import Clash.Util.Graph (reverseTopSort) #ifdef CABAL import qualified Paths_clash_lib@@ -60,21 +70,34 @@ data SystemVerilogState = SystemVerilogState { _tyCache :: HashSet HWType -- ^ Previously encountered HWTypes- , _tySeen :: [Identifier] -- ^ Product type counter+ , _tySeen :: HashMapS.HashMap Identifier Word -- ^ Product type counter , _nameCache :: HashMap HWType Doc -- ^ Cache for previously generated product type names , _genDepth :: Int -- ^ Depth of current generative block- , _modNm :: String- , _idSeen :: [Identifier]+ , _modNm :: Identifier+ , _idSeen :: HashMapS.HashMap Identifier Word , _oports :: [Identifier] , _srcSpan :: SrcSpan , _includes :: [(String,Doc)] , _imports :: [Text.Text]+ , _libraries :: [Text.Text]+ , _dataFiles :: [(String,FilePath)]+ -- ^ Files to be copied: (filename, old path)+ , _memoryDataFiles:: [(String,String)]+ -- ^ Files to be stored: (filename, contents). These files are generated+ -- during the execution of 'genNetlist'.+ , _tyPkgCtx :: Bool+ -- ^ Are we in the context of generating the @_types@ package? , _intWidth :: Int -- ^ Int/Word/Integer bit-width , _hdlsyn :: HdlSyn+ , _escapedIds :: Bool+ , _undefValue :: Maybe (Maybe Int) } makeLenses ''SystemVerilogState +squote :: Mon (State SystemVerilogState) Doc+squote = string "'"+ primsRoot :: IO FilePath #ifdef CABAL primsRoot = Paths_clash_lib.getDataFileName "prims"@@ -83,7 +106,9 @@ #endif instance Backend SystemVerilogState where- initBackend = SystemVerilogState HashSet.empty [] HashMap.empty 0 "" [] [] noSrcSpan [] []+ initBackend = SystemVerilogState HashSet.empty HashMapS.empty HashMap.empty+ 0 "" HashMapS.empty [] noSrcSpan [] [] []+ [] [] False hdlKind = const SystemVerilog primDirs = const $ do root <- primsRoot return [ root System.FilePath.</> "common"@@ -114,25 +139,34 @@ inst = inst_ expr = expr_ iwWidth = use intWidth- toBV hty id_ = toSLV hty (Identifier id_ Nothing)- fromBV hty id_ = simpleFromSLV hty id_+ toBV hty id_ = toSLV hty (Identifier (Text.toStrict id_) Nothing)+ fromBV hty id_ = simpleFromSLV hty (Text.toStrict id_) hdlSyn = use hdlsyn- mkIdentifier = return go+ mkIdentifier = do+ allowEscaped <- use escapedIds+ return (go allowEscaped) where- go Basic nm = filterReserved (mkBasicId' True nm)- go Extended (rmSlash . escapeTemplate -> nm) = case go Basic nm of- nm' | nm /= nm' -> Text.concat ["\\",nm," "]- |otherwise -> nm'- extendIdentifier = return go+ go _ Basic nm = case (TextS.take 1024 . filterReserved) (mkBasicId' SystemVerilog True nm) of+ nm' | TextS.null nm' -> "_clash_internal"+ | otherwise -> nm'+ go esc Extended (rmSlash . escapeTemplate -> nm) = case go esc Basic nm of+ nm' | esc && nm /= nm' -> TextS.concat ["\\",nm," "]+ | otherwise -> nm'+ extendIdentifier = do+ allowEscaped <- use escapedIds+ return (go allowEscaped) where- go Basic nm ext = filterReserved (mkBasicId' True (nm `Text.append` ext))- go Extended (rmSlash -> nm) ext =- let nmExt = nm `Text.append` ext- in case go Basic nm ext of- nm' | nm' /= nmExt -> case Text.head nmExt of- '#' -> Text.concat ["\\",nmExt," "]- _ -> Text.concat ["\\#",nmExt," "]- | otherwise -> nm'+ go _ Basic nm ext =+ case (TextS.take 1024 . filterReserved) (mkBasicId' SystemVerilog True (nm `TextS.append` ext)) of+ nm' | TextS.null nm' -> "_clash_internal"+ | otherwise -> nm'+ go esc Extended (rmSlash -> nm) ext =+ let nmExt = nm `TextS.append` ext+ in case go esc Basic nm ext of+ nm' | esc && nm' /= nmExt -> case TextS.isPrefixOf "c$" nmExt of+ True -> TextS.concat ["\\",nmExt," "]+ _ -> TextS.concat ["\\c$",nmExt," "]+ | otherwise -> nm' setModName nm s = s {_modNm = nm} setSrcSpan = (srcSpan .=)@@ -140,19 +174,29 @@ blockDecl _ ds = do decs <- decls ds if isEmpty decs- then insts ds+ then indent 2 (insts ds) else pure decs <> line <>- insts ds+ indent 2 (insts ds) unextend = return rmSlash- addInclude inc = includes %= (inc:)- addLibraries _ = return ()+ addIncludes inc = includes %= (inc++)+ addLibraries libs = libraries %= (libs ++) addImports inps = imports %= (inps ++)+ addAndSetData f = do+ fs <- use dataFiles+ let (fs',f') = renderFilePath fs f+ dataFiles .= fs'+ return f'+ getDataFiles = use dataFiles+ addMemoryDataFile f = memoryDataFiles %= (f:)+ getMemoryDataFiles = use memoryDataFiles+ seenIdentifiers = idSeen+ ifThenElseExpr _ = True rmSlash :: Identifier -> Identifier rmSlash nm = fromMaybe nm $ do- nm1 <- Text.stripPrefix "\\" nm- pure (Text.filter (not . (== ' ')) nm1)+ nm1 <- TextS.stripPrefix "\\" nm+ pure (TextS.filter (not . (== ' ')) nm1) type SystemVerilogM a = Mon (State SystemVerilogState) a @@ -194,19 +238,23 @@ filterReserved :: Identifier -> Identifier filterReserved s = if s `elem` reservedWords- then s `Text.append` "_r"+ then s `TextS.append` "_r" else s --- | Generate VHDL for a Netlist component-genVerilog :: String -> SrcSpan -> Component -> SystemVerilogM ((String,Doc),[(String,Doc)])-genVerilog _ sp c = do+-- | Generate SystemVerilog for a Netlist component+genVerilog :: Identifier -> SrcSpan -> HashMapS.HashMap Identifier Word -> Component -> SystemVerilogM ((String,Doc),[(String,Doc)])+genVerilog _ sp seen c = preserveSeen $ do+ Mon $ idSeen .= seen+ -- Don't have type names conflict with module names+ Mon $ tySeen %= HashMapS.unionWith max seen Mon $ setSrcSpan sp v <- verilog incs <- Mon $ use includes- return ((unpack cName,v),incs)+ return ((TextS.unpack cName,v),incs) where cName = componentName c verilog = commentHeader <> line <>+ timescale <> line <> module_ c #ifdef CABAL clashVer = Data.Version.showVersion Paths_clash_lib.version@@ -217,24 +265,31 @@ = "/* AUTOMATICALLY GENERATED SYSTEMVERILOG-2005 SOURCE CODE." <> line <> "** GENERATED BY CLASH " <> string (Text.pack clashVer) <> ". DO NOT MODIFY." <> line <> "*/"+ timescale = "`timescale 100fs/100fs" -- | Generate a SystemVerilog package containing type definitions for the given HWTypes-mkTyPackage_ :: String+mkTyPackage_ :: Identifier -> [HWType] -> SystemVerilogM [(String,Doc)]-mkTyPackage_ modName hwtys =- (:[]) A.<$> (modName ++ "_types",) A.<$>+mkTyPackage_ modName hwtys = do+ Mon (tyPkgCtx .= True)+ normTys <- nub <$> mapM (normaliseType) (hwtys ++ usedTys)+ let+ needsDec = nubBy eqReprTy $ normTys+ hwTysSorted = topSortHWTys needsDec+ packageDec = vcat $ fmap catMaybes $ mapM tyDec hwTysSorted+ funDecs = vcat $ fmap catMaybes $ mapM funDec hwTysSorted++ pkg <- (:[]) A.<$> (TextS.unpack modName ++ "_types",) A.<$> "package" <+> modNameD <> "_types" <> semi <> line <> indent 2 packageDec <> line <> indent 2 funDecs <> line <> "endpackage" <+> colon <+> modNameD <> "_types"+ Mon (tyPkgCtx .= False)+ return pkg where- modNameD = string (pack modName)+ modNameD = stringS modName usedTys = concatMap mkUsedTys hwtys- needsDec = nubBy eqReprTy $ (hwtys ++ usedTys)- hwTysSorted = topSortHWTys needsDec- packageDec = vcat $ fmap catMaybes $ mapM tyDec hwTysSorted- funDecs = vcat $ fmap catMaybes $ mapM funDec hwTysSorted eqReprTy :: HWType -> HWType -> Bool eqReprTy (Vector n ty1) (Vector m ty2)@@ -250,21 +305,22 @@ | otherwise = ty1 == ty2 isUnsigned :: HWType -> Bool- isUnsigned (Unsigned _) = True- isUnsigned (BitVector _) = True- isUnsigned (Index _) = True- isUnsigned (Sum _ _) = True- isUnsigned (SP _ _) = True- isUnsigned _ = False+ isUnsigned (Unsigned _) = True+ isUnsigned (BitVector _) = True+ isUnsigned (Index _) = True+ isUnsigned (Sum _ _) = True+ isUnsigned (CustomSum _ _ _ _) = True+ isUnsigned (SP _ _) = True+ isUnsigned (CustomSP _ _ _ _) = True+ isUnsigned _ = False mkUsedTys :: HWType -> [HWType]-mkUsedTys v@(Vector _ elTy) = v : mkUsedTys elTy-mkUsedTys t@(RTree _ elTy) = t : mkUsedTys elTy-mkUsedTys p@(Product _ elTys) = p : concatMap mkUsedTys elTys-mkUsedTys sp@(SP _ elTys) = sp : concatMap mkUsedTys (concatMap snd elTys)-mkUsedTys c@(Clock _ _ Gated) = [c,Bit,Bool]-mkUsedTys t = [t]+mkUsedTys v@(Vector _ elTy) = v : mkUsedTys elTy+mkUsedTys t@(RTree _ elTy) = t : mkUsedTys elTy+mkUsedTys p@(Product _ _ elTys) = p : concatMap mkUsedTys elTys+mkUsedTys sp@(SP _ elTys) = sp : concatMap mkUsedTys (concatMap snd elTys)+mkUsedTys t = [t] topSortHWTys :: [HWType] -> [HWType]@@ -273,19 +329,41 @@ nodes = zip [0..] hwtys nodesI = HashMap.fromList (zip hwtys [0..]) edges = concatMap edge hwtys- graph = mkGraph nodes edges :: Gr HWType ()- sorted = reverse $ topsort' graph+ sorted =+ case reverseTopSort nodes edges of+ Left err -> error ("[BUG IN CLASH] topSortHWTys: " ++ err)+ Right ns -> ns - edge t@(Vector _ elTy) = maybe [] ((:[]) . (HashMap.lookupDefault (error $ $(curLoc) ++ "Vector") t nodesI,,()))+ edge t@(Vector _ elTy) = maybe [] ((:[]) . (HashMap.lookupDefault (error $ $(curLoc) ++ "Vector") t nodesI,)) (HashMap.lookup elTy nodesI)- edge t@(RTree _ elTy) = maybe [] ((:[]) . (HashMap.lookupDefault (error $ $(curLoc) ++ "RTree") t nodesI,,()))+ edge t@(RTree _ elTy) = maybe [] ((:[]) . (HashMap.lookupDefault (error $ $(curLoc) ++ "RTree") t nodesI,)) (HashMap.lookup elTy nodesI)- edge t@(Product _ tys) = let ti = HashMap.lookupDefault (error $ $(curLoc) ++ "Product") t nodesI- in mapMaybe (\ty -> liftM (ti,,()) (HashMap.lookup ty nodesI)) tys+ edge t@(Product _ _ tys) = let ti = HashMap.lookupDefault (error $ $(curLoc) ++ "Product") t nodesI+ in mapMaybe (\ty -> liftM (ti,) (HashMap.lookup ty nodesI)) tys edge t@(SP _ ctys) = let ti = HashMap.lookupDefault (error $ $(curLoc) ++ "SP") t nodesI- in concatMap (\(_,tys) -> mapMaybe (\ty -> liftM (ti,,()) (HashMap.lookup ty nodesI)) tys) ctys+ in concatMap (\(_,tys) -> mapMaybe (\ty -> liftM (ti,) (HashMap.lookup ty nodesI)) tys) ctys edge _ = [] +normaliseType :: HWType -> SystemVerilogM HWType+normaliseType (Annotated _ ty) = normaliseType ty+normaliseType (Vector n ty) = Vector n <$> (normaliseType ty)+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)+ return (BitVector (typeSize ty))+normaliseType (CustomSP _ _dataRepr size elTys) = do+ Mon $ 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))+normaliseType ty@(CustomSum _ _ _ _) = return (BitVector (typeSize ty))+normaliseType (Clock _) = return Bit+normaliseType (Reset {}) = return Bit+normaliseType (BiDirectional dir ty) = BiDirectional dir <$> normaliseType ty+normaliseType ty = return ty++ range :: Either Int Int -> SystemVerilogM Doc range (Left n) = brackets (int (n-1) <> colon <> int 0) range (Right n) = brackets (int 0 <> colon <> int (n-1))@@ -321,7 +399,7 @@ "typedef" <+> elTy' <+> hcat (mapM range ns) <+> tyName ty <+> brackets (int 0 <> colon <> int (n' - 1)) <> semi _ -> error $ $(curLoc) ++ "impossible"-tyDec ty@(Product _ tys) | typeSize ty > 0 = Just A.<$> prodDec+tyDec ty@(Product _ _ tys) | typeSize ty > 0 = Just A.<$> prodDec where prodDec = "typedef struct packed {" <> line <> indent 2 (vcat $ fmap catMaybes $ zipWithM combineM selNames tys) <> line <>@@ -337,24 +415,19 @@ tyDec _ = pure Nothing -gatedClockType :: HWType -> HWType-gatedClockType (Clock nm rt Gated) = Product ("GatedClock" `Text.append` (pack (show (nm,rt)))) [Bit,Bool]-gatedClockType ty = ty-{-# INLINE gatedClockType #-}- splitVecTy :: HWType -> Maybe ([Either Int Int],SystemVerilogM Doc) splitVecTy = fmap splitElemTy . go where splitElemTy (ns,t) = case t of- Product _ _ -> (ns, verilogType t)- Vector _ _ -> error $ $(curLoc) ++ "impossible"- Clock {} -> (ns, verilogType t)- Reset {} -> (ns, "logic")- Bool -> (ns, "logic")- Bit -> (ns, "logic")- String -> (ns, "string")- Signed n -> (ns ++ [Left n],"logic signed")- _ -> (ns ++ [Left (typeSize t)], "logic")+ Product {} -> (ns, verilogType t)+ Vector {} -> error $ $(curLoc) ++ "impossible"+ Clock {} -> (ns, verilogType t)+ Reset {} -> (ns, "logic")+ Bool -> (ns, "logic")+ Bit -> (ns, "logic")+ String -> (ns, "string")+ Signed n -> (ns ++ [Left n],"logic signed")+ _ -> (ns ++ [Left (typeSize t)], "logic") go (Vector n elTy) = case go elTy of Just (ns,elTy') -> Just (Right n:ns,elTy')@@ -386,24 +459,24 @@ funDec :: HWType -> SystemVerilogM (Maybe Doc) funDec ty@(Vector n elTy) | typeSize ty > 0 = Just A.<$>- "function" <+> "logic" <+> ranges <+> tName <> "_to_lv" <> parens (sigDecl "i" ty) <> semi <> line <>+ "function" <+> "automatic" <+> "logic" <+> ranges <+> tName <> "_to_lv" <> parens (sigDecl "i" ty) <> semi <> line <> indent 2 ("for" <+> parens ("int n = 0" <> semi <+> "n <" <+> int n <> semi <+> "n=n+1") <> line <> indent 2 (tName <> "_to_lv" <> brackets "n" <+> "=" <+> "i[n]" <> semi)) <> line <> "endfunction" <> line <>- "function" <+> tName <+> tName <> "_from_lv" <> parens ("logic" <+> ranges <+> "i") <> semi <> line <>+ "function" <+> "automatic" <+> tName <+> tName <> "_from_lv" <> parens ("logic" <+> ranges <+> "i") <> semi <> line <> indent 2 ("for" <+> parens ("int n = 0" <> semi <+> "n <" <+> int n <> semi <+> "n=n+1") <> line <> indent 2 (tName <> "_from_lv" <> brackets "n" <+> "=" <+> "i[n]" <> semi)) <> line <> "endfunction" <> line <> if n > 1 then- "function" <+> tName <+> tName <> "_cons" <> parens (sigDecl "x" elTy <> comma <> vecSigDecl "xs") <> semi <> line <>+ "function" <+> "automatic" <+> tName <+> tName <> "_cons" <> parens (sigDecl "x" elTy <> comma <> vecSigDecl "xs") <> semi <> line <> indent 2 (tName <> "_cons" <> brackets (int 0) <+> "=" <+> (toSLV elTy (Identifier "x" Nothing)) <> semi <> line <> tName <> "_cons" <> brackets (int 1 <> colon <> int (n-1)) <+> "=" <+> "xs" <> semi) <> line <> "endfunction" else- "function" <+> tName <+> tName <> "_cons" <> parens (sigDecl "x" elTy) <> semi <> line <>+ "function" <+> "automatic" <+> tName <+> tName <> "_cons" <> parens (sigDecl "x" elTy) <> semi <> line <> indent 2 (tName <> "_cons" <> brackets (int 0) <+> "=" <+> (toSLV elTy (Identifier "x" Nothing)) <> semi) <> line <> "endfunction"@@ -431,19 +504,19 @@ funDec ty@(RTree n elTy) | typeSize elTy > 0 = Just A.<$>- "function" <+> "logic" <+> ranges <+> tName <> "_to_lv" <> parens (sigDecl "i" ty) <> semi <> line <>+ "function" <+> "automatic" <+> "logic" <+> ranges <+> tName <> "_to_lv" <> parens (sigDecl "i" ty) <> semi <> line <> indent 2 ("for" <+> parens ("int n = 0" <> semi <+> "n <" <+> int (2^n) <> semi <+> "n=n+1") <> line <> indent 2 (tName <> "_to_lv" <> brackets "n" <+> "=" <+> "i[n]" <> semi)) <> line <> "endfunction" <> line <>- "function" <+> tName <+> tName <> "_from_lv" <> parens ("logic" <+> ranges <+> "i") <> semi <> line <>+ "function" <+> "automatic" <+> tName <+> tName <> "_from_lv" <> parens ("logic" <+> ranges <+> "i") <> semi <> line <> indent 2 ("for" <+> parens ("int n = 0" <> semi <+> "n <" <+> int (2^n) <> semi <+> "n=n+1") <> line <> indent 2 (tName <> "_from_lv" <> brackets "n" <+> "=" <+> "i[n]" <> semi)) <> line <> "endfunction" <> line <> (if n > 0 then- "function" <+> tName <+> tName <> "_br" <> parens (treeSigDecl "l" <> comma <> treeSigDecl "r") <> semi <> line <>+ "function" <+> "automatic" <+> tName <+> tName <> "_br" <> parens (treeSigDecl "l" <> comma <> treeSigDecl "r") <> semi <> line <> indent 2 (tName <> "_br" <> brackets (int 0 <> colon <> int (2^(n-1)-1)) <+> "=" <+> "l" <> semi <> line <> tName <> "_br" <> brackets (int (2^(n-1)) <> colon <> int (2^n-1)) <+> "=" <+> "r" <> semi) <> line <>@@ -476,28 +549,34 @@ module_ :: Component -> SystemVerilogM Doc module_ c =- addSeen c *> modVerilog <* Mon (idSeen .= [] >> imports .= [] >> oports .= [])+ addSeen c *> modVerilog <* Mon (imports .= [] >> oports .= []) where modVerilog = do body <- modBody imps <- Mon $ use imports- modHeader <> line <> modPorts <> line <> include (nub imps) <> pure body <> line <> modEnding+ libs <- Mon $ use libraries+ modHeader <> line <> modPorts <> line <> include (nub imps) <> uselibs (nub libs) <> pure body <> line <> modEnding - modHeader = "module" <+> string (componentName c)+ modHeader = "module" <+> stringS (componentName c) modPorts = indent 4 (tupleInputs inPorts <> line <> tupleOutputs outPorts <> semi)- modBody = indent 2 (decls (declarations c)) <> line <> line <> insts (declarations c)+ modBody = indent 2 (decls (declarations c)) <> line <> line <> indent 2 (insts (declarations c)) modEnding = "endmodule" - inPorts = sequence [ sigPort Nothing p | p <- inputs c ]- outPorts = sequence [ sigPort (Just wr) p | (wr, p) <- outputs c ]+ inPorts = sequence [ sigPort (Nothing,isBiSignalIn ty) (i,ty) | (i,ty) <- inputs c ]+ outPorts = sequence [ sigPort (Just wr,False) p | (wr, p) <- outputs c ] - wr2ty Nothing = "input"- wr2ty (Just Wire) = "output"- wr2ty (Just Reg) = "output"+ wr2ty (Nothing,isBidirectional)+ | isBidirectional+ = "inout"+ | otherwise+ = "input"+ wr2ty (Just _,_)+ = "output" -- map a port to its verilog type, port name, and any encoding notes sigPort (wr2ty -> portTy) (nm, hwTy)- = portTy <+> sigDecl (string nm) hwTy <+> encodingNote hwTy+ = addAttrs (hwTypeAttrs hwTy)+ (portTy <+> sigDecl (stringS nm) hwTy <+> encodingNote hwTy) -- slightly more readable than 'tupled', makes the output Haskell-y-er commafy v = (comma <> space) <> pure v @@ -519,10 +598,10 @@ addSeen :: Component -> SystemVerilogM () addSeen c = do- let iport = map fst $ inputs c+ let iport = map fst (inputs c) oport = map (fst.snd) $ outputs c nets = mapMaybe (\case {NetDecl' _ _ i _ -> Just i; _ -> Nothing}) $ declarations c- Mon (idSeen .= concat [iport,oport,nets])+ Mon (idSeen %= (HashMapS.unionWith max (HashMapS.fromList (concatMap (map (,0)) [iport,oport,nets])))) Mon (oports .= oport) mkUniqueId :: Identifier -> SystemVerilogM Identifier@@ -530,108 +609,124 @@ mkId <- Mon (mkIdentifier <*> pure Extended) seen <- Mon $ use idSeen let i' = mkId i- case i `elem` seen of- True -> go mkId seen i' 0- False -> do Mon (idSeen %= (i':))- return i'+ case HashMapS.lookup i seen of+ Just n -> go mkId seen i' n+ Nothing -> do Mon (idSeen %= (HashMapS.insert i' 0))+ return i' where- go :: (Identifier -> Identifier) -> [Identifier] -> Identifier- -> Int -> SystemVerilogM Identifier+ go :: (Identifier -> Identifier) -> HashMapS.HashMap Identifier Word -> Identifier+ -> Word -> SystemVerilogM Identifier go mkId seen i' n = do- let i'' = mkId (Text.append i' (Text.pack ('_':show n)))- case i'' `elem` seen of- True -> go mkId seen i' (n+1)- False -> do Mon (idSeen %= (i'':))- return i''+ let i'' = mkId (TextS.append i' (TextS.pack ('_':show n)))+ case HashMapS.lookup i'' seen of+ Just _ -> go mkId seen i' (n+1)+ Nothing -> do Mon (idSeen %= (HashMapS.insert i'' (n+1)))+ return i'' verilogType :: HWType -> SystemVerilogM Doc-verilogType t = do+verilogType t_ = do+ t <- normaliseType t_ Mon (tyCache %= HashSet.insert t)+ let logicOrWire | isBiSignalIn t = "wire"+ | otherwise = "logic"+ pkgCtx <- Mon $ use tyPkgCtx+ nm <- Mon $ use modNm+ let pvrType = if pkgCtx+ then tyName t+ else stringS nm <> "_types::" <> tyName t case t of- Product _ _ -> do- nm <- Mon $ use modNm- string (pack nm) <> "_types::" <> tyName t- Vector _ _ -> do- nm <- Mon $ use modNm- string (pack nm) <> "_types::" <> tyName t- RTree _ _ -> do- nm <- Mon $ use modNm- string (pack nm) <> "_types::" <> tyName t- Signed n -> "logic signed" <+> brackets (int (n-1) <> colon <> int 0)- Clock _ _ Gated -> verilogType (gatedClockType t)- Clock {} -> "logic"+ Product {} -> pvrType+ Vector {} -> pvrType+ RTree {} -> pvrType+ Signed n -> logicOrWire <+> "signed" <+> brackets (int (n-1) <> colon <> int 0)+ Clock _ -> "logic" Reset {} -> "logic" Bit -> "logic" Bool -> "logic" String -> "string"- _ -> "logic" <+> brackets (int (typeSize t -1) <> colon <> int 0)+ _ -> logicOrWire <+> brackets (int (typeSize t -1) <> colon <> int 0) sigDecl :: SystemVerilogM Doc -> HWType -> SystemVerilogM Doc sigDecl d t = verilogType t <+> d -- | Convert a Netlist HWType to the root of a Verilog type verilogTypeMark :: HWType -> SystemVerilogM Doc-verilogTypeMark t = do+verilogTypeMark t_ = do+ t <- normaliseType t_ Mon (tyCache %= HashSet.insert t)+ pkgCtx <- Mon $ use tyPkgCtx nm <- Mon $ use modNm- let m = tyName t+ let pvrType = if pkgCtx+ then tyName t+ else stringS nm <> "_types::" <> tyName t case t of- Product _ _ -> string (pack nm) <> "_types::" <> m- Vector _ _ -> string (pack nm) <> "_types::" <> m- RTree _ _ -> string (pack nm) <> "_types::" <> m+ Product {} -> pvrType+ Vector {} -> pvrType+ RTree {} -> pvrType _ -> emptyDoc tyName :: HWType -> SystemVerilogM Doc-tyName Bool = "logic"-tyName Bit = "logic"-tyName (Vector n elTy) = "array_of_" <> int n <> "_" <> tyName elTy-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)-tyName (Signed n) = "signed_" <> int n-tyName (Unsigned n) = "logic_vector_" <> int n-tyName t@(Sum _ _) = "logic_vector_" <> int (typeSize t)-tyName t@(Product nm _) = Mon (makeCached t nameCache prodName)+tyName Bool = "logic"+tyName Bit = "logic"+tyName (Vector n elTy) = "array_of_" <> int n <> "_" <> tyName elTy+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)+tyName (Signed n) = "signed_" <> int n+tyName (Unsigned n) = "logic_vector_" <> int n+tyName t@(Sum _ _) = "logic_vector_" <> int (typeSize t)+tyName t@(CustomSum _ _ _ _) = "logic_vector_" <> int (typeSize t)+tyName t@(CustomSP _ _ _ _) = "logic_vector_" <> int (typeSize t)+tyName t@(Product nm _ _) = do+ tN <- normaliseType t+ Mon (makeCached tN nameCache prodName) where prodName = do seen <- use tySeen mkId <- mkIdentifier <*> pure Basic- let nm' = (mkId . last . Text.splitOn ".") nm- nm'' = if Text.null nm'+ let nm' = (mkId . last . TextS.splitOn ".") nm+ nm'' = if TextS.null nm' then "product" else nm'- nm3 = if nm'' `elem` seen- then go mkId seen (0::Integer) nm''- else nm''- tySeen %= (nm3:)- string nm3+ (nm3,count) = case HashMapS.lookup nm'' seen of+ Just cnt -> go mkId seen cnt nm''+ Nothing -> (nm'',0)+ tySeen %= HashMap.insert nm3 count+ stringS nm3 go mkId s i n =- let n' = n `Text.append` Text.pack ('_':show i)- in if n' `elem` s- then go mkId s (i+1) n- else n'-tyName t@(SP _ _) = "logic_vector_" <> int (typeSize t)-tyName t@(Clock _ _ Gated) = tyName (gatedClockType t)-tyName (Clock {}) = "logic"-tyName (Reset {}) = "logic"+ let n' = n `TextS.append` TextS.pack ('_':show i)+ in case HashMapS.lookup n' s of+ Just _ -> go mkId s (i+1) n+ Nothing -> (n',i+1)+tyName t@(SP _ _) = "logic_vector_" <> int (typeSize t)+tyName (Clock _) = "logic"+tyName (Reset {}) = "logic" tyName t = error $ $(curLoc) ++ "tyName: " ++ show t --- | Convert a Netlist HWType to an error VHDL value for that type+-- | Convert a Netlist HWType to an error SystemVerilog value for that type verilogTypeErrValue :: HWType -> SystemVerilogM Doc verilogTypeErrValue (Vector n elTy) = do syn <- Mon hdlSyn case syn of- Vivado -> char '\'' <> braces (int n <+> braces (braces (int (typeSize elTy) <+> braces "1'bx")))+ Vivado -> char '\'' <> braces (int n <+> braces (singularErrValue elTy)) _ -> char '\'' <> braces (int n <+> braces (verilogTypeErrValue elTy)) verilogTypeErrValue (RTree n elTy) = do syn <- Mon hdlSyn case syn of- Vivado -> char '\'' <> braces (int (2^n) <+> braces (braces (int (typeSize elTy) <+> braces "1'bx")))+ Vivado -> char '\'' <> braces (int (2^n) <+> braces (singularErrValue elTy)) _ -> char '\'' <> braces (int (2^n) <+> braces (verilogTypeErrValue elTy)) verilogTypeErrValue String = "\"ERROR\""-verilogTypeErrValue ty = braces (int (typeSize ty) <+> braces "1'bx")+verilogTypeErrValue ty = singularErrValue ty +singularErrValue :: HWType -> SystemVerilogM Doc+singularErrValue ty = do+ udf <- Mon (use undefValue)+ case udf of+ Nothing -> braces (int (typeSize ty) <+> braces "1'bx")+ Just Nothing -> int (typeSize ty) <> "'d0 /* undefined */"+ Just (Just x) -> braces (int (typeSize ty) <+> braces ("1'b" <> int x)) <+> "/* undefined */"+ verilogRecSel :: HWType -> Int@@ -648,22 +743,117 @@ decl :: Declaration -> SystemVerilogM (Maybe Doc) decl (NetDecl' noteM _ id_ tyE) =- Just A.<$> maybe id addNote noteM (typ tyE)+ Just A.<$> maybe id addNote noteM (addAttrs attrs (typ tyE)) where- typ (Left ty) = string ty <+> string id_- typ (Right ty) = sigDecl (string id_) ty- addNote n = mappend ("//" <+> string n <> line)+ typ (Left ty) = stringS ty <+> stringS id_+ typ (Right ty) = sigDecl (stringS id_) ty+ addNote n = mappend ("//" <+> stringS n <> line)+ attrs = fromMaybe [] (hwTypeAttrs A.<$> either (const Nothing) Just tyE) decl _ = return Nothing +-- | Convert single attribute to systemverilog syntax+renderAttr :: Attr' -> Text.Text+renderAttr (StringAttr' key value) = Text.pack $ concat [key, " = ", show value]+renderAttr (IntegerAttr' key value) = Text.pack $ concat [key, " = ", show value]+renderAttr (BoolAttr' key True ) = Text.pack $ concat [key, " = ", "1"]+renderAttr (BoolAttr' key False) = Text.pack $ concat [key, " = ", "0"]+renderAttr (Attr' key ) = Text.pack $ key++-- | Add attribute notation to given declaration+addAttrs+ :: [Attr']+ -> SystemVerilogM Doc+ -> SystemVerilogM Doc+addAttrs [] t = t+addAttrs attrs' t =+ "(*" <+> attrs'' <+> "*)" <+> t+ where+ attrs'' = string $ Text.intercalate ", " (map renderAttr attrs')+ insts :: [Declaration] -> SystemVerilogM Doc insts [] = emptyDoc-insts is = indent 2 . vcat . punctuate line . fmap catMaybes $ mapM inst_ is+insts (TickDecl id_:ds) = "//" <+> stringS id_ <> line <> insts ds+insts (d:ds) = do+ docM <- inst_ d+ case docM of+ Nothing -> insts ds+ Just doc -> pure doc <> line <> line <> insts ds +stdMatch+ :: Bits a+ => Int+ -> a+ -> a+ -> String+stdMatch 0 _mask _value = []+stdMatch size mask value =+ symbol : stdMatch (size - 1) mask value+ where+ symbol =+ if testBit mask (size - 1) then+ if testBit value (size - 1) then+ '1'+ else+ '0'+ else+ '?'++patLitCustom'+ :: Int+ -> ConstrRepr'+ -> SystemVerilogM Doc+patLitCustom' size (ConstrRepr' _name _n mask value _anns) =+ int size <> squote <> "b" <> (string $ Text.pack $ stdMatch size mask value)++patLitCustom+ :: HWType+ -> Literal+ -> SystemVerilogM Doc+patLitCustom (CustomSum _name _dataRepr size reprs) (NumLit (fromIntegral -> i)) =+ patLitCustom' size (fst $ reprs !! i)++patLitCustom (CustomSP _name _dataRepr size reprs) (NumLit (fromIntegral -> i)) =+ let (cRepr, _id, _tys) = reprs !! i in+ patLitCustom' size cRepr++patLitCustom x y = error $ $(curLoc) ++ unwords+ [ "You can only pass CustomSP / CustomSum and a NumLit to this function,"+ , "not", show x, "and", show y]++patMod :: HWType -> Literal -> Literal+patMod hwTy (NumLit i) = NumLit (i `mod` (2 ^ typeSize hwTy))+patMod _ l = l++-- | Helper function for inst_, handling CustomSP and CustomSum+inst_' :: TextS.Text -> Expr -> HWType -> [(Maybe Literal, Expr)] -> SystemVerilogM (Maybe Doc)+inst_' id_ scrut scrutTy es = fmap Just $+ "always_comb begin" <> line <> indent 2 casez <> line <> "end"+ where+ casez =+ "casez" <+> parens var <> line <>+ indent 2 (conds esNub) <> line <>+ "endcase"++ esMod = map (first (fmap (patMod scrutTy))) es+ esNub = nubBy ((==) `on` fst) esMod+ var = expr_ True scrut++ conds :: [(Maybe Literal,Expr)] -> SystemVerilogM Doc+ conds [] = error $ $(curLoc) ++ "Empty list of conditions invalid."+ conds [(_,e)] = "default" <+> ":" <+> stringS id_ <+> "=" <+> expr_ False e <> ";"+ conds ((Nothing,e):_) = "default" <+> ":" <+> stringS id_ <+> "=" <+> expr_ False e <> ";"+ conds ((Just c ,e):es') =+ mask' <+> ":" <+> stringS id_ <+> "=" <+> expr_ False e <> ";" <> line <> conds es'+ where+ mask' = patLitCustom scrutTy c+ -- | Turn a Netlist Declaration to a SystemVerilog concurrent block inst_ :: Declaration -> SystemVerilogM (Maybe Doc)+inst_ (TickDecl {}) = return Nothing+ inst_ (Assignment id_ e) = fmap Just $- "assign" <+> string id_ <+> equals <+> align (expr_ False e <> semi)+ "assign" <+> stringS id_ <+> equals <+> align (expr_ False e <> semi) inst_ (CondAssignment id_ ty scrut _ [(Just (BoolLit b), l),(_,r)]) = fmap Just $ do { syn <- Mon hdlSyn@@ -671,38 +861,44 @@ ; if syn == Vivado && id_ `elem` p then do { regId <- mkUniqueId =<< Mon (extendIdentifier <*> pure Extended <*> pure id_ <*> pure "_reg")- ; verilogType ty <+> string regId <> semi <> line <>+ ; verilogType ty <+> stringS regId <> semi <> line <> "always_comb begin" <> line <> indent 2 ("if" <> parens (expr_ True scrut) <> line <>- (indent 2 $ string regId <+> equals <+> expr_ False t <> semi) <> line <>+ (indent 2 $ stringS regId <+> equals <+> expr_ False t <> semi) <> line <> "else" <> line <>- (indent 2 $ string regId <+> equals <+> expr_ False f <> semi)) <> line <>+ (indent 2 $ stringS regId <+> equals <+> expr_ False f <> semi)) <> line <> "end" <> line <>- "assign" <+> string id_ <+> equals <+> string regId <> semi+ "assign" <+> stringS id_ <+> equals <+> stringS regId <> semi } else "always_comb begin" <> line <> indent 2 ("if" <> parens (expr_ True scrut) <> line <>- (indent 2 $ string id_ <+> equals <+> expr_ False t <> semi) <> line <>+ (indent 2 $ stringS id_ <+> equals <+> expr_ False t <> semi) <> line <> "else" <> line <>- (indent 2 $ string id_ <+> equals <+> expr_ False f <> semi)) <> line <>+ (indent 2 $ stringS id_ <+> equals <+> expr_ False f <> semi)) <> line <> "end" } where (t,f) = if b then (l,r) else (r,l) +inst_ (CondAssignment id_ _ scrut scrutTy@(CustomSP _ _ _ _) es) =+ inst_' id_ scrut scrutTy es++inst_ (CondAssignment id_ _ scrut scrutTy@(CustomSum _ _ _ _) es) =+ inst_' id_ scrut scrutTy es+ inst_ (CondAssignment id_ ty scrut scrutTy es) = fmap Just $ do { syn <- Mon hdlSyn ; p <- Mon $ use oports ; if syn == Vivado && id_ `elem` p then do { regId <- mkUniqueId =<< Mon (extendIdentifier <*> pure Extended <*> pure id_ <*> pure "_reg")- ; verilogType ty <+> string regId <> semi <> line <>+ ; verilogType ty <+> stringS regId <> semi <> line <> "always_comb begin" <> line <> indent 2 ("case" <> parens (expr_ True scrut) <> line <> (indent 2 $ vcat $ punctuate semi (conds regId es)) <> semi <> line <> "endcase") <> line <> "end" <> line <>- "assign" <+> string id_ <+> equals <+> string regId <> semi+ "assign" <+> stringS id_ <+> equals <+> stringS regId <> semi } else "always_comb begin" <> line <> indent 2 ("case" <> parens (expr_ True scrut) <> line <>@@ -713,14 +909,17 @@ where conds :: Identifier -> [(Maybe Literal,Expr)] -> SystemVerilogM [Doc] conds _ [] = return []- conds i [(_,e)] = ("default" <+> colon <+> string i <+> equals <+> expr_ False e) <:> return []- conds i ((Nothing,e):_) = ("default" <+> colon <+> string i <+> equals <+> expr_ False e) <:> return []- conds i ((Just c ,e):es') = (exprLit (Just (scrutTy,conSize scrutTy)) c <+> colon <+> string i <+> equals <+> expr_ False e) <:> conds i es'+ conds i [(_,e)] = ("default" <+> colon <+> stringS i <+> equals <+> expr_ False e) <:> return []+ conds i ((Nothing,e):_) = ("default" <+> colon <+> stringS i <+> equals <+> expr_ False e) <:> return []+ conds i ((Just c ,e):es') = (exprLitSV (Just (scrutTy,conSize scrutTy)) c <+> colon <+> stringS i <+> equals <+> expr_ False e) <:> conds i es' -inst_ (InstDecl _ nm lbl pms) = fmap Just $- nest 2 (string nm <+> string lbl <> line <> pms' <> semi)+inst_ (InstDecl _ _ nm lbl ps pms) = fmap Just $+ nest 2 (stringS nm <> params <> stringS lbl <> line <> pms' <> semi) where pms' = tupled $ sequence [dot <> expr_ False i <+> parens (expr_ False e) | (i,_,_,e) <- pms]+ params+ | null ps = space+ | otherwise = line <> "#" <> tupled (sequence [dot <> expr_ False i <+> parens (expr_ False e) | (i,_,e) <- ps]) <> line inst_ (BlackBoxD _ libs imps inc bs bbCtx) = fmap Just (Mon (column (renderBlackBox libs imps inc bs bbCtx)))@@ -728,11 +927,18 @@ inst_ (NetDecl' _ _ _ _) = return Nothing -- | Turn a Netlist expression into a SystemVerilog expression-expr_ :: Bool -- ^ Enclose in parenthesis?+expr_ :: Bool -- ^ Enclose in parentheses? -> Expr -- ^ Expr to convert -> SystemVerilogM Doc-expr_ _ (Literal sizeM lit) = exprLit sizeM lit-expr_ _ (Identifier id_ Nothing) = string id_+expr_ _ (Literal sizeM lit) = exprLitSV sizeM lit+expr_ _ (Identifier id_ Nothing) = stringS id_+expr_ _ (Identifier id_ (Just (Indexed (CustomSP _id _dataRepr _size args,dcI,fI)))) =+ expFromSLV resultType (braces $ hcat $ punctuate ", " $ sequence ranges)+ where+ (ConstrRepr' _name _n _mask _value anns, _, argTys) = args !! dcI+ resultType = argTys !! fI+ ranges = map range' $ bitRanges (anns !! fI)+ range' (start, end) = stringS id_ <> brackets (int start <> ":" <> int end) expr_ _ (Identifier id_ (Just (Indexed (ty@(SP _ args),dcI,fI)))) = fromSLV argTy id_ start end where argTys = snd $ args !! dcI@@ -742,68 +948,118 @@ start = typeSize ty - 1 - conSize ty - other end = start - argSize + 1 -expr_ _ (Identifier id_ (Just (Indexed (ty@(Product _ tys),_,fI)))) = do- id'<- fmap renderOneLine (string id_ <> dot <> tyName ty <> "_sel" <> int fI)- simpleFromSLV (tys !! fI) id'--expr_ _ (Identifier id_ (Just (Indexed (ty@(Clock _ _ Gated),_,fI)))) = do- let tys = [Bit, Bool]- ty' = gatedClockType ty- id'<- fmap renderOneLine (string id_ <> dot <> tyName ty' <> "_sel" <> int fI)+expr_ _ (Identifier id_ (Just (Indexed (ty@(Product _ _ tys),_,fI)))) = do+ id'<- fmap (Text.toStrict . renderOneLine) (stringS id_ <> dot <> tyName ty <> "_sel" <> int fI) simpleFromSLV (tys !! fI) id' expr_ _ (Identifier id_ (Just (Indexed ((Vector _ elTy),1,0)))) = do- id' <- fmap renderOneLine (string id_ <> brackets (int 0))+ id' <- fmap (Text.toStrict . renderOneLine) (stringS id_ <> brackets (int 0)) simpleFromSLV elTy id' -expr_ _ (Identifier id_ (Just (Indexed ((Vector n _),1,1)))) = string id_ <> brackets (int 1 <> colon <> int (n-1))+expr_ _ (Identifier id_ (Just (Indexed ((Vector n _),1,1)))) = stringS id_ <> brackets (int 1 <> colon <> int (n-1)) -- This is a "Hack", we cannot construct trees with a negative depth. This is -- here so that we can recognise merged RTree modifiers. See the code in -- @Clash.Backend.nestM@ which construct these tree modifiers. expr_ _ (Identifier id_ (Just (Indexed (RTree (-1) _,l,r)))) =- string id_ <> brackets (int l <> colon <> int (r-1))+ stringS id_ <> brackets (int l <> colon <> int (r-1)) expr_ _ (Identifier id_ (Just (Indexed ((RTree 0 elTy),0,0)))) = do- id' <- fmap renderOneLine (string id_ <> brackets (int 0))+ id' <- fmap (Text.toStrict . renderOneLine) (stringS id_ <> brackets (int 0)) simpleFromSLV elTy id' expr_ _ (Identifier id_ (Just (Indexed ((RTree n _),1,0)))) = let z = 2^(n-1)- in string id_ <> brackets (int 0 <> colon <> int (z-1))+ in stringS id_ <> brackets (int 0 <> colon <> int (z-1)) expr_ _ (Identifier id_ (Just (Indexed ((RTree n _),1,1)))) = let z = 2^(n-1) z' = 2^n- in string id_ <> brackets (int z <> colon <> int (z'-1))+ in stringS id_ <> brackets (int z <> colon <> int (z'-1)) -- This is a HACK for Clash.Driver.TopWrapper.mkOutput -- Vector's don't have a 10'th constructor, this is just so that we can -- recognize the particular case expr_ _ (Identifier id_ (Just (Indexed ((Vector _ elTy),10,fI)))) = do- id' <- fmap renderOneLine (string id_ <> brackets (int fI))+ id' <- fmap (Text.toStrict . renderOneLine) (stringS id_ <> brackets (int fI)) simpleFromSLV elTy id' -- This is a HACK for Clash.Driver.TopWrapper.mkOutput -- RTree's don't have a 10'th constructor, this is just so that we can -- recognize the particular case expr_ _ (Identifier id_ (Just (Indexed ((RTree _ elTy),10,fI)))) = do- id' <- fmap renderOneLine (string id_ <> brackets (int fI))+ id' <- fmap (Text.toStrict . renderOneLine) (stringS id_ <> brackets (int fI)) simpleFromSLV elTy id' -expr_ _ (Identifier id_ (Just (DC (ty@(SP _ _),_)))) = string id_ <> brackets (int start <> colon <> int end)+expr_ _ (Identifier id_ (Just (DC (ty@(SP _ _),_)))) = stringS id_ <> brackets (int start <> colon <> int end) where start = typeSize ty - 1 end = typeSize ty - conSize ty expr_ b (Identifier id_ (Just (Nested m1 m2))) = case nestM m1 m2 of Just m3 -> expr_ b (Identifier id_ (Just m3))- _ -> do- k <- expr_ b (Identifier id_ (Just m1))- expr_ b (Identifier (renderOneLine k) (Just m2))+ _ -> case nestSP 0 m1 m2 of+ Just (argTy,start,end) -> fromSLV argTy id_ start end+ _ -> do+ k <- expr_ b (Identifier id_ (Just m1))+ expr_ b (Identifier (Text.toStrict (renderOneLine k)) (Just m2))+ where+ nestSP offset k1 k2 = case goSP offset k1 of+ Just (_,_,e) -> goSP e k2+ _ -> Nothing -expr_ _ (Identifier id_ (Just _)) = string id_+ goSP offset (Indexed (ty@(SP _ args),dcI,fI)) = Just (argTy,start+offset,end+offset)+ where+ argTys = snd $ args !! dcI+ argTy = argTys !! fI+ argSize = typeSize argTy+ other = otherSize argTys (fI-1)+ start = typeSize ty - 1 - conSize ty - other+ end = start - argSize + 1 ++ goSP offset (Indexed (CustomSP _id _dataRepr _size args,dcI,fI)) =+ case bitRanges (anns !! fI) of+ [(start,end)] -> Just (argTy,start+offset,end+offset)+ _ -> Nothing++ where+ (ConstrRepr' _name _n _mask _value anns, _, argTys) = args !! dcI+ argTy = argTys !! fI++ goSP offset (Nested k1 k2) = nestSP offset k1 k2++ goSP _ _ = Nothing++-- See [Note] integer projection+expr_ _ (Identifier id_ (Just (Indexed ((Signed w),_,_)))) = do+ iw <- Mon $ use intWidth+ traceIf (iw < w) ($(curLoc) ++ "WARNING: result smaller than argument") $+ stringS id_++-- See [Note] integer projection+expr_ _ (Identifier id_ (Just (Indexed ((Unsigned w),_,_)))) = do+ iw <- Mon $ use intWidth+ traceIf (iw < w) ($(curLoc) ++ "WARNING: result smaller than argument") $+ stringS id_++-- See [Note] mask projection+expr_ _ (Identifier _ (Just (Indexed ((BitVector _),_,0)))) = do+ iw <- Mon $ 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+ traceIf (iw < w) ($(curLoc) ++ "WARNING: result smaller than argument") $+ stringS id_++expr_ _ (Identifier id_ (Just (Sliced ((BitVector _,start,end))))) =+ stringS id_ <> brackets (int start <> ":" <> int end)++expr_ _ (Identifier id_ (Just _)) = stringS id_+ expr_ b (DataCon _ (DC (Void {}, -1)) [e]) = expr_ b e expr_ _ (DataCon ty@(Vector 0 _) _ _) = verilogTypeErrValue ty@@ -820,6 +1076,11 @@ Just es -> "'" <> listBraces (mapM (toSLV elTy) es) Nothing -> verilogTypeMark ty <> "_br" <> parens (expr_ False e1 <> comma <+> expr_ False e2) +expr_ _ (DataCon (SP {}) (DC (BitVector _,_)) es) = assignExpr+ where+ argExprs = map (expr_ False) es+ assignExpr = braces (hcat $ punctuate comma $ sequence argExprs)+ expr_ _ (DataCon ty@(SP _ args) (DC (_,i)) es) = assignExpr where argTys = snd $ args !! i@@ -828,56 +1089,92 @@ argExprs = zipWith toSLV argTys es extraArg = case typeSize ty - dcSize of 0 -> []- n -> [int n <> "'b" <> bits (replicate n U)]+ n -> [int n <> "'b" <> bits undefValue (replicate n U)] assignExpr = braces (hcat $ punctuate comma $ sequence (dcExpr:argExprs ++ extraArg)) expr_ _ (DataCon ty@(Sum _ _) (DC (_,i)) []) = int (typeSize ty) <> "'d" <> int i-expr_ _ (DataCon (Product _ tys) _ es) = listBraces (zipWithM toSLV tys es)-expr_ _ (DataCon (Clock nm rt Gated) _ es) =- listBraces (zipWithM toSLV [Clock nm rt Source,Bool] es)+expr_ _ (DataCon ty@(CustomSum _ _ _ tys) (DC (_,i)) []) =+ let (ConstrRepr' _ _ _ value _) = fst $ tys !! i in+ int (typeSize ty) <> squote <> "d" <> int (fromIntegral value)+expr_ _ (DataCon (CustomSP _ dataRepr size args) (DC (_,i)) es) =+ braces $ hcat $ punctuate ", " $ mapM range' origins+ where+ (cRepr, _, argTys) = args !! i + -- Build bit representations for all constructor arguments+ argExprs = zipWith toSLV argTys es :: [SystemVerilogM Doc]++ -- Spread bits of constructor arguments using masks+ origins = bitOrigins dataRepr cRepr :: [BitOrigin]++ range'+ :: BitOrigin+ -> SystemVerilogM Doc+ range' (Lit (bitsToBits -> ns)) =+ int (length ns) <> squote <> "b" <> hcat (mapM (bit_char undefValue) ns)+ range' (Field n start end) =+ -- We want to select the bits starting from 'start' downto and including+ -- 'end'. We cannot use slice notation in Verilog, as the preceding+ -- expression might not be an identifier.+ let fsize = start - end + 1 in+ let expr' = argExprs !! n in++ if | fsize == size ->+ -- If sizes are equal, rotating / resizing amounts to doing nothing+ expr'+ | end == 0 ->+ -- Rotating is not necessary if relevant bits are already at the end+ int fsize <> squote <> parens expr'+ | otherwise ->+ -- Select bits 'start' downto and including 'end'+ let rotated = parens expr' <+> ">>" <+> int end in+ int fsize <> squote <> parens rotated+expr_ _ (DataCon (Product _ _ tys) _ es) = listBraces (zipWithM toSLV tys es)+ expr_ _ (BlackBoxE pNm _ _ _ _ bbCtx _) | pNm == "Clash.Sized.Internal.Signed.fromInteger#" , [Literal _ (NumLit n), Literal _ i] <- extractLiterals bbCtx- = exprLit (Just (Signed (fromInteger n),fromInteger n)) i+ = exprLitSV (Just (Signed (fromInteger n),fromInteger n)) i expr_ _ (BlackBoxE pNm _ _ _ _ bbCtx _) | pNm == "Clash.Sized.Internal.Unsigned.fromInteger#" , [Literal _ (NumLit n), Literal _ i] <- extractLiterals bbCtx- = exprLit (Just (Unsigned (fromInteger n),fromInteger n)) i+ = exprLitSV (Just (Unsigned (fromInteger n),fromInteger n)) i expr_ _ (BlackBoxE pNm _ _ _ _ bbCtx _) | pNm == "Clash.Sized.Internal.BitVector.fromInteger#"- , [Literal _ (NumLit n), Literal _ i] <- extractLiterals bbCtx- = exprLit (Just (BitVector (fromInteger n),fromInteger n)) i+ , [Literal _ (NumLit n), Literal _ (NumLit m), Literal _ (NumLit i)] <- extractLiterals bbCtx+ = exprLitSV (Just (BitVector (fromInteger n),fromInteger n)) (BitVecLit m i) expr_ _ (BlackBoxE pNm _ _ _ _ bbCtx _) | pNm == "Clash.Sized.Internal.BitVector.fromInteger##"- , [Literal _ i] <- extractLiterals bbCtx- = exprLit (Just (Bit,1)) i+ , [Literal _ m, Literal _ i] <- extractLiterals bbCtx+ = let NumLit m' = m+ NumLit i' = i+ in exprLitSV (Just (Bit,1)) (BitLit $ toBit m' i') expr_ _ (BlackBoxE pNm _ _ _ _ bbCtx _) | pNm == "Clash.Sized.Internal.Index.fromInteger#" , [Literal _ (NumLit n), Literal _ i] <- extractLiterals bbCtx- = exprLit (Just (Index (fromInteger n),fromInteger n)) i+ = 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)) -expr_ _ (DataTag Bool (Left id_)) = string id_ <> brackets (int 0)+expr_ _ (DataTag Bool (Left id_)) = stringS id_ <> brackets (int 0) expr_ _ (DataTag Bool (Right id_)) = do iw <- Mon $ use intWidth- "$unsigned" <> parens (listBraces (sequence [braces (int (iw-1) <+> braces "1'b0"),string id_]))+ "$unsigned" <> parens (listBraces (sequence [braces (int (iw-1) <+> braces "1'b0"),stringS id_])) -expr_ _ (DataTag (Sum _ _) (Left id_)) = "$unsigned" <> parens (string id_)-expr_ _ (DataTag (Sum _ _) (Right id_)) = "$unsigned" <> parens (string id_)+expr_ _ (DataTag (Sum _ _) (Left id_)) = "$unsigned" <> parens (stringS id_)+expr_ _ (DataTag (Sum _ _) (Right id_)) = "$unsigned" <> parens (stringS id_) -expr_ _ (DataTag (Product _ _) (Right _)) = do+expr_ _ (DataTag (Product {}) (Right _)) = do iw <- Mon $ use intWidth int iw <> "'sd0" expr_ _ (DataTag hty@(SP _ _) (Right id_)) = "$unsigned" <> parens- (string id_ <> brackets+ (stringS id_ <> brackets (int start <> colon <> int end)) where start = typeSize hty - 1@@ -899,34 +1196,42 @@ expr_ b (ConvBV topM t True e) = do nm <- Mon $ use modNm- let nm' = string (pack nm)+ pkgCtx <- Mon $ use tyPkgCtx+ let prefix = if pkgCtx then stringS nm <> "_types::" else emptyDoc case t of Vector {} -> do Mon (tyCache %= HashSet.insert t)- maybe (nm' <> "_types::" ) ((<> "_types::") . string) topM <>+ maybe prefix ((<> "_types::") . stringS) topM <> tyName t <> "_to_lv" <> parens (expr_ False e) RTree {} -> do Mon (tyCache %= HashSet.insert t)- maybe (nm' <> "_types::" ) ((<> "_types::") . string) topM <>+ maybe prefix ((<> "_types::") . stringS) topM <> tyName t <> "_to_lv" <> parens (expr_ False e) _ -> expr b e expr_ b (ConvBV topM t False e) = do nm <- Mon $ use modNm- let nm' = string (pack nm)+ pkgCtx <- Mon $ use tyPkgCtx+ let prefix = if pkgCtx then stringS nm <> "_types::" else emptyDoc case t of Vector {} -> do Mon (tyCache %= HashSet.insert t)- maybe (nm' <> "_types::" ) ((<> "_types::") . string) topM <>+ maybe prefix ((<> "_types::") . stringS) topM <> tyName t <> "_from_lv" <> parens (expr_ False e) RTree {} -> do Mon (tyCache %= HashSet.insert t)- maybe (nm' <> "_types::" ) ((<> "_types::") . string) topM <>+ maybe prefix ((<> "_types::") . stringS) topM <> tyName t <> "_from_lv" <> parens (expr_ False e) _ -> expr b e +expr_ b (IfThenElse c t e) =+ parenIf b (expr_ True c <+> "?" <+> expr_ True t <+> ":" <+> expr_ True e)+ expr_ _ e = error $ $(curLoc) ++ (show e) -- empty +exprLitSV :: Maybe (HWType,Size) -> Literal -> SystemVerilogM Doc+exprLitSV = exprLit undefValue+ otherSize :: [HWType] -> Int -> Int otherSize _ n | n < 0 = 0 otherSize [] _ = 0@@ -944,39 +1249,6 @@ (rtreeChain e2) rtreeChain _ = Nothing -exprLit :: Maybe (HWType,Size) -> Literal -> SystemVerilogM Doc-exprLit Nothing (NumLit i) = integer i--exprLit (Just (hty,sz)) (NumLit i) = case hty of- Unsigned _ -> int sz <> "'d" <> integer i- Index _ -> int (typeSize hty) <> "'d" <> integer i- Signed _- | i < 0 -> "-" <> int sz <> "'sd" <> integer (abs i)- | otherwise -> int sz <> "'sd" <> integer i- _ -> int sz <> "'b" <> blit- where- blit = bits (toBits sz i)-exprLit _ (BoolLit t) = if t then "1'b1" else "1'b0"-exprLit _ (BitLit b) = "1'b" <> bit_char b-exprLit _ (StringLit s) = string . pack $ show s-exprLit _ l = error $ $(curLoc) ++ "exprLit: " ++ show l--toBits :: Integral a => Int -> a -> [Bit]-toBits size val = map (\x -> if odd x then H else L)- $ reverse- $ take size- $ map (`mod` 2)- $ iterate (`div` 2) val--bits :: [Bit] -> SystemVerilogM Doc-bits = hcat . mapM bit_char--bit_char :: Bit -> SystemVerilogM Doc-bit_char H = char '1'-bit_char L = char '0'-bit_char U = char 'x'-bit_char Z = char 'z'- toSLV :: HWType -> Expr -> SystemVerilogM Doc toSLV t e = case t of Vector _ _ -> braces (verilogTypeMark t <> "_to_lv" <> parens (expr_ False e))@@ -984,17 +1256,23 @@ _ -> expr_ False e fromSLV :: HWType -> Identifier -> Int -> Int -> SystemVerilogM Doc-fromSLV t@(Vector _ _) id_ start end = verilogTypeMark t <> "_from_lv" <> parens (string id_ <> brackets (int start <> colon <> int end))-fromSLV t@(RTree _ _) id_ start end = verilogTypeMark t <> "_from_lv" <> parens (string id_ <> brackets (int start <> colon <> int end))-fromSLV (Signed _) id_ start end = "$signed" <> parens (string id_ <> brackets (int start <> colon <> int end))-fromSLV _ id_ start end = string id_ <> brackets (int start <> colon <> int end)+fromSLV t@(Vector _ _) id_ start end = verilogTypeMark t <> "_from_lv" <> parens (stringS id_ <> brackets (int start <> colon <> int end))+fromSLV t@(RTree _ _) id_ start end = verilogTypeMark t <> "_from_lv" <> parens (stringS id_ <> brackets (int start <> colon <> int end))+fromSLV (Signed _) id_ start end = "$signed" <> parens (stringS id_ <> brackets (int start <> colon <> int end))+fromSLV _ id_ start end = stringS id_ <> brackets (int start <> colon <> int end) simpleFromSLV :: HWType -> Identifier -> SystemVerilogM Doc-simpleFromSLV t@(Vector _ _) id_ = verilogTypeMark t <> "_from_lv" <> parens (string id_)-simpleFromSLV t@(RTree _ _) id_ = verilogTypeMark t <> "_from_lv" <> parens (string id_)-simpleFromSLV (Signed _) id_ = "$signed" <> parens (string id_)-simpleFromSLV _ id_ = string id_+simpleFromSLV t@(Vector _ _) id_ = verilogTypeMark t <> "_from_lv" <> parens (stringS id_)+simpleFromSLV t@(RTree _ _) id_ = verilogTypeMark t <> "_from_lv" <> parens (stringS id_)+simpleFromSLV (Signed _) id_ = "$signed" <> parens (stringS id_)+simpleFromSLV _ id_ = stringS id_ +expFromSLV :: HWType -> SystemVerilogM Doc -> SystemVerilogM Doc+expFromSLV t@(Vector _ _) exp_ = verilogTypeMark t <> "_from_lv" <> parens exp_+expFromSLV t@(RTree _ _) exp_ = verilogTypeMark t <> "_from_lv" <> parens exp_+expFromSLV (Signed _) exp_ = "$signed" <> parens exp_+expFromSLV _ exp_ = exp_+ dcToExpr :: HWType -> Int -> Expr dcToExpr ty i = Literal (Just (ty,conSize ty)) (NumLit (toInteger i)) @@ -1007,9 +1285,3 @@ punctuate' :: Monad m => Mon m Doc -> Mon m [Doc] -> Mon m Doc punctuate' s d = vcat (punctuate s d) <> s--encodingNote :: HWType -> SystemVerilogM Doc-encodingNote (Clock _ _ Gated) = "// gated clock"-encodingNote (Clock {}) = "// clock"-encodingNote (Reset {}) = "// asynchronous reset: active high"-encodingNote _ = emptyDoc
src/Clash/Backend/VHDL.hs view
@@ -1,1208 +1,2007 @@ {-| Copyright : (C) 2015-2016, University of Twente,- 2017, Google Inc.- License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>-- Generate VHDL for assorted Netlist datatypes--}--{-# LANGUAGE CPP #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecursiveDo #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE ViewPatterns #-}--module Clash.Backend.VHDL (VHDLState) where--import Control.Applicative (liftA2)-import Control.Lens hiding (Indexed)-import Control.Monad (forM,join,liftM,zipWithM)-import Control.Monad.State (State)-import Data.Graph.Inductive (Gr, mkGraph, topsort')-import Data.HashMap.Lazy (HashMap)-import qualified Data.HashMap.Lazy as HashMap-import Data.HashSet (HashSet)-import qualified Data.HashSet as HashSet-import Data.List (mapAccumL,nub,nubBy)-import Data.Maybe (catMaybes,fromMaybe,mapMaybe)-#if !MIN_VERSION_base(4,11,0)-import Data.Monoid hiding (Sum, Product)-#endif-import Data.Semigroup.Monad.Extra-import Data.Text.Lazy (unpack)-import qualified Data.Text.Lazy as T-import Data.Text.Prettyprint.Doc.Extra-import qualified System.FilePath-import Text.Printf--import Clash.Annotations.Primitive (HDL (..))-import Clash.Backend-import Clash.Driver.Types (SrcSpan, noSrcSpan)-import Clash.Netlist.BlackBox.Types (HdlSyn (..))-import Clash.Netlist.BlackBox.Util (extractLiterals, renderBlackBox)-import Clash.Netlist.Id (IdType (..), mkBasicId')-import Clash.Netlist.Types hiding (_intWidth, intWidth)-import Clash.Netlist.Util hiding (mkIdentifier)-import Clash.Signal.Internal (ClockKind (..))-import Clash.Util (clogBase, curLoc, first, makeCached, on, (<:>))--#ifdef CABAL-import qualified Paths_clash_lib-#endif---- | State for the 'Clash.Netlist.VHDL.VHDLM' monad:-data VHDLState =- VHDLState- { _tyCache :: (HashSet HWType) -- ^ Previously encountered HWTypes- , _tySeen :: [Identifier] -- ^ Generated product types- , _nameCache :: (HashMap HWType Doc) -- ^ Cache for previously generated product type names- , _modNm :: String- , _srcSpan :: SrcSpan- , _libraries :: [T.Text]- , _packages :: [T.Text]- , _includes :: [(String,Doc)]- , _intWidth :: Int -- ^ Int/Word/Integer bit-width- , _hdlsyn :: HdlSyn -- ^ For which HDL synthesis tool are we generating VHDL- }--makeLenses ''VHDLState--primsRoot :: IO FilePath-#ifdef CABAL-primsRoot = Paths_clash_lib.getDataFileName "prims"-#else-primsRoot = return ("clash-lib" System.FilePath.</> "prims")-#endif--instance Backend VHDLState where- initBackend = VHDLState HashSet.empty [] HashMap.empty "" noSrcSpan [] [] []- hdlKind = const VHDL- primDirs = const $ do root <- primsRoot- return [ root System.FilePath.</> "common"- , root System.FilePath.</> "vhdl"- ]- extractTypes = _tyCache- name = const "vhdl"- extension = const ".vhdl"-- genHDL = genVHDL- mkTyPackage = mkTyPackage_- hdlType Internal ty = vhdlType ty- hdlType (External nm) ty = case ty of- Vector _ _ -> pretty nm <> dot <> vhdlType ty- RTree _ _ -> pretty nm <> dot <> vhdlType ty- Product _ _ -> pretty nm <> dot <> vhdlType ty- _ -> vhdlType ty- hdlTypeErrValue = vhdlTypeErrValue- hdlTypeMark = vhdlTypeMark- hdlRecSel = vhdlRecSel- hdlSig t ty = sigDecl (pretty t) ty- genStmt = const emptyDoc- inst = inst_- expr = expr_- iwWidth = use intWidth- toBV _ id_ = do- nm <- Mon $ use modNm- pretty (T.toLower $ T.pack nm) <> "_types.toSLV" <> parens (pretty id_)- fromBV _ id_ = do- nm <- Mon $ use modNm- pretty (T.toLower $ T.pack nm) <> "_types.fromSLV" <> parens (pretty id_)- hdlSyn = use hdlsyn- mkIdentifier = return go- where- go Basic nm = filterReserved (T.toLower (mkBasicId' True nm))- go Extended (rmSlash -> nm) = case go Basic nm of- nm' | nm /= nm' -> T.concat ["\\",nm,"\\"]- |otherwise -> nm'- extendIdentifier = return go- where- go Basic nm ext = filterReserved (T.toLower (mkBasicId' True (nm `T.append` ext)))- go Extended ((rmSlash . escapeTemplate) -> nm) ext =- let nmExt = nm `T.append` ext- in case go Basic nm ext of- nm' | nm' /= nmExt -> case T.head nmExt of- '#' -> T.concat ["\\",nmExt,"\\"]- _ -> T.concat ["\\#",nmExt,"\\"]- | otherwise -> nm'-- setModName nm s = s {_modNm = nm}- setSrcSpan = (srcSpan .=)- getSrcSpan = use srcSpan- blockDecl nm ds = do- decs <- decls ds- if isEmpty decs- then insts ds- else nest 2- (pretty nm <+> colon <+> "block" <> line <>- pure decs) <> line <>- nest 2- ("begin" <> line <>- insts ds) <> line <>- "end block" <> semi- unextend = return rmSlash- addInclude inc = includes %= (inc:)- addLibraries libs = libraries %= (libs ++)- addImports imps = packages %= (imps ++)--rmSlash :: Identifier -> Identifier-rmSlash nm = fromMaybe nm $ do- nm1 <- T.stripPrefix "\\" nm- pure (T.filter (not . (== '\\')) nm1)--type VHDLM a = Mon (State VHDLState) a---- List of reserved VHDL-2008 keywords--- + used internal names: toslv, fromslv, tagtoenum, datatotag--- + used IEEE library names: integer, boolean, std_logic, std_logic_vector,--- signed, unsigned, to_integer, to_signed, to_unsigned, string-reservedWords :: [Identifier]-reservedWords = ["abs","access","after","alias","all","and","architecture"- ,"array","assert","assume","assume_guarantee","attribute","begin","block"- ,"body","buffer","bus","case","component","configuration","constant","context"- ,"cover","default","disconnect","downto","else","elsif","end","entity","exit"- ,"fairness","file","for","force","function","generate","generic","group"- ,"guarded","if","impure","in","inertial","inout","is","label","library"- ,"linkage","literal","loop","map","mod","nand","new","next","nor","not","null"- ,"of","on","open","or","others","out","package","parameter","port","postponed"- ,"procedure","process","property","protected","pure","range","record"- ,"register","reject","release","rem","report","restrict","restrict_guarantee"- ,"return","rol","ror","select","sequence","severity","signal","shared","sla"- ,"sll","sra","srl","strong","subtype","then","to","transport","type"- ,"unaffected","units","until","use","variable","vmode","vprop","vunit","wait"- ,"when","while","with","xnor","xor","toslv","fromslv","tagtoenum","datatotag"- ,"integer", "boolean", "std_logic", "std_logic_vector", "signed", "unsigned"- ,"to_integer", "to_signed", "to_unsigned", "string"]--filterReserved :: Identifier -> Identifier-filterReserved s = if s `elem` reservedWords- then s `T.append` "_r"- else s---- | Generate VHDL for a Netlist component-genVHDL :: String -> SrcSpan -> Component -> VHDLM ((String,Doc),[(String,Doc)])-genVHDL nm sp c = do- Mon $ setSrcSpan sp- v <- vhdl- i <- Mon $ use includes- Mon $ libraries .= []- Mon $ packages .= []- return ((unpack cName,v),i)- where- cName = componentName c- vhdl = do- ent <- entity c- arch <- architecture c- imps <- tyImports nm- ("-- Automatically generated VHDL-93" <> line <>- pure imps <> line <> line <>- pure ent <> line <> line <>- pure arch)---- | Generate a VHDL package containing type definitions for the given HWTypes-mkTyPackage_ :: String- -> [HWType]- -> VHDLM [(String,Doc)]-mkTyPackage_ modName hwtys = do- { syn <- Mon hdlSyn- ; mkId <- Mon (mkIdentifier <*> pure Basic)- ; let usedTys = concatMap mkUsedTys hwtys- ; normTys <- nub <$> mapM (fmap mkVecZ . normaliseType) (hwtys ++ usedTys)- ; let sortedTys = topSortHWTys normTys- packageDec = vcat $ mapM tyDec sortedTys- (funDecs,funBodies) = unzip . mapMaybe (funDec syn) $ nubBy eqTypM sortedTys-- ; (:[]) <$> (unpack $ mkId (T.pack modName `T.append` "_types"),) <$>- "library IEEE;" <> line <>- "use IEEE.STD_LOGIC_1164.ALL;" <> line <>- "use IEEE.NUMERIC_STD.ALL;" <> line <> line <>- "package" <+> pretty (mkId (T.pack modName `T.append` "_types")) <+> "is" <> line <>- indent 2 ( packageDec <> line <>- vcat (sequence funDecs)- ) <> line <>- "end" <> semi <> packageBodyDec funBodies- }- where- packageBodyDec :: [VHDLM Doc] -> VHDLM Doc- packageBodyDec funBodies = case funBodies of- [] -> emptyDoc- _ -> do- { mkId <- Mon (mkIdentifier <*> pure Basic)- ; line <> line <>- "package" <+> "body" <+> pretty (mkId (T.pack modName `T.append` "_types")) <+> "is" <> line <>- indent 2 (vcat (sequence funBodies)) <> line <>- "end" <> semi- }-- eqTypM :: HWType -> HWType -> Bool- eqTypM (Signed _) (Signed _) = True- eqTypM (Unsigned _) (Unsigned _) = True- eqTypM (BitVector _) (BitVector _) = True- eqTypM (Clock _ _ g) (Clock _ _ g') = g == g'- eqTypM ty1 ty2 = ty1 == ty2--mkUsedTys :: HWType- -> [HWType]-mkUsedTys v@(Vector _ elTy) = v : mkUsedTys elTy-mkUsedTys v@(RTree _ elTy) = v : mkUsedTys elTy-mkUsedTys p@(Product _ elTys) = p : concatMap mkUsedTys elTys-mkUsedTys sp@(SP _ elTys) = sp : concatMap mkUsedTys (concatMap snd elTys)-mkUsedTys t = [t]--topSortHWTys :: [HWType]- -> [HWType]-topSortHWTys hwtys = sorted- where- nodes = zip [0..] hwtys- nodesI = HashMap.fromList (zip hwtys [0..])- edges = concatMap edge hwtys- graph = mkGraph nodes edges :: Gr HWType ()- sorted = reverse $ topsort' graph-- edge t@(Vector _ elTy) = maybe [] ((:[]) . (HashMap.lookupDefault (error $ $(curLoc) ++ "Vector") t nodesI,,()))- (HashMap.lookup (mkVecZ elTy) nodesI)- edge t@(RTree _ elTy) = maybe [] ((:[]) . (HashMap.lookupDefault (error $ $(curLoc) ++ "RTree") t nodesI,,()))- (HashMap.lookup (mkVecZ elTy) nodesI)- edge t@(Product _ tys) = let ti = HashMap.lookupDefault (error $ $(curLoc) ++ "Product") t nodesI- in mapMaybe (\ty -> liftM (ti,,()) (HashMap.lookup (mkVecZ ty) nodesI)) tys- edge _ = []--normaliseType :: HWType -> VHDLM HWType-normaliseType (Vector n ty) = Vector n <$> (normaliseType ty)-normaliseType (RTree d ty) = RTree d <$> (normaliseType ty)-normaliseType (Product nm tys) = Product nm <$> (mapM normaliseType tys)-normaliseType ty@(SP _ elTys) = do- Mon $ mapM_ ((tyCache %=) . HashSet.insert) (concatMap snd elTys)- return (BitVector (typeSize ty))-normaliseType ty@(Index _) = return (Unsigned (typeSize ty))-normaliseType ty@(Sum _ _) = return (BitVector (typeSize ty))-normaliseType (Clock _ _ Gated) =- return (Product "GatedClock" [Bit,Bool])-normaliseType (Clock {}) = return Bit-normaliseType (Reset {}) = return Bit-normaliseType ty = return ty--mkVecZ :: HWType -> HWType-mkVecZ (Vector _ elTy) = Vector 0 elTy-mkVecZ (RTree _ elTy) = RTree 0 elTy-mkVecZ t = t--tyDec :: HWType -> VHDLM Doc-tyDec (Vector _ elTy) = do- syn <- Mon hdlSyn- case syn of- Vivado -> "type" <+> "array_of_" <> tyName elTy <+> "is array (integer range <>) of"- <+> "std_logic_vector" <> parens (int (typeSize elTy - 1) <+> "downto 0") <> semi- _ -> "type" <+> "array_of_" <> tyName elTy <+> "is array (integer range <>) of"- <+> vhdlType elTy <> semi--tyDec (RTree _ elTy) = do- syn <- Mon hdlSyn- case syn of- Vivado -> "type" <+> "tree_of_" <> tyName elTy <+> "is array (integer range <>) of"- <+> "std_logic_vector" <> parens (int (typeSize elTy - 1) <+> "downto 0") <> semi- _ -> "type" <+> "tree_of_" <> tyName elTy <+> "is array (integer range <>) of" <+> vhdlType elTy <> semi--tyDec ty@(Product _ tys@(_:_:_)) = prodDec- where- prodDec = "type" <+> tName <+> "is record" <> line <>- indent 2 (vcat $ zipWithM (\x y -> x <+> colon <+> y <> semi) selNames selTys) <> line <>- "end record" <> semi-- tName = tyName ty- selNames = map (\i -> tName <> "_sel" <> int i) [0..]- selTys = map vhdlType tys--tyDec _ = emptyDoc---funDec :: 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 <>- "function" <+> "dataToTag" <+> parens ("b" <+> colon <+> "in" <+> "boolean") <+> "return" <+> "signed" <> semi- , "function" <+> "toSLV" <+> parens ("b" <+> colon <+> "in" <+> "boolean") <+> "return" <+> "std_logic_vector" <+> "is" <> line <>- "begin" <> line <>- indent 2 (vcat $ sequence ["if" <+> "b" <+> "then"- , indent 2 ("return" <+> dquotes (int 1) <> semi)- ,"else"- , indent 2 ("return" <+> dquotes (int 0) <> semi)- ,"end" <+> "if" <> semi- ]) <> line <>- "end" <> semi <> line <>- "function" <+> "fromSLV" <+> parens ("sl" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> "boolean" <+> "is" <> line <>- "begin" <> line <>- indent 2 (vcat $ sequence ["if" <+> "sl" <+> "=" <+> dquotes (int 1) <+> "then"- , indent 2 ("return" <+> "true" <> semi)- ,"else"- , indent 2 ("return" <+> "false" <> semi)- ,"end" <+> "if" <> semi- ]) <> line <>- "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 ("return" <+> "false" <> semi)- ,"else"- , indent 2 ("return" <+> "true" <> semi)- ,"end" <+> "if" <> semi- ]) <> line <>- "end" <> semi <> line <>- "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)- ,"else"- , indent 2 ("return" <+> "to_signed" <> parens (int 0 <> comma <> (Mon (use intWidth) >>= int)) <> semi)- ,"end" <+> "if" <> semi- ]) <> line <>- "end" <> semi- )--funDec _ Bit = Just- ( "function" <+> "toSLV" <+> parens ("sl" <+> colon <+> "in" <+> "std_logic") <+> "return" <+> "std_logic_vector" <> semi <> line <>- "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> "std_logic" <> semi- , "function" <+> "toSLV" <+> parens ("sl" <+> colon <+> "in" <+> "std_logic") <+> "return" <+> "std_logic_vector" <+> "is" <> line <>- "begin" <> line <>- indent 2 ("return" <+> "std_logic_vector'" <> parens (int 0 <+> rarrow <+> "sl") <> semi) <> line <>- "end" <> semi <> line <>- "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> "std_logic" <+> "is" <> line <>- indent 2- ( "alias islv : std_logic_vector (0 to slv'length - 1) is slv;"- ) <> line <>- "begin" <> line <>- indent 2 ("return" <+> "islv" <> parens (int 0) <> semi) <> line <>- "end" <> semi- )--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 <>- "begin" <> line <>- indent 2 ("return" <+> "std_logic_vector" <> parens ("s") <> semi) <> line <>- "end" <> semi <> line <>- "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> "signed" <+> "is" <> line <>- "begin" <> line <>- indent 2 ("return" <+> "signed" <> parens ("slv") <> semi) <> line <>- "end" <> semi- )--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 <>- "begin" <> line <>- indent 2 ("return" <+> "std_logic_vector" <> parens ("u") <> semi) <> line <>- "end" <> semi <> line <>- "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> "unsigned" <+> "is" <> line <>- "begin" <> line <>- indent 2 ("return" <+> "unsigned" <> parens ("slv") <> semi) <> line <>- "end" <> semi-- )--funDec _ t@(Product _ elTys) = Just- ( "function" <+> "toSLV" <+> parens ("p :" <+> vhdlType t) <+> "return std_logic_vector" <> semi <> line <>- "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> vhdlType t <> semi- , "function" <+> "toSLV" <+> parens ("p :" <+> vhdlType t) <+> "return std_logic_vector" <+> "is" <> line <>- "begin" <> line <>- indent 2 ("return" <+> parens (hcat (punctuate " & " elTyToSLV)) <> semi) <> line <>- "end" <> semi <> line <>- "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> vhdlType t <+> "is" <> line <>- "alias islv : std_logic_vector(0 to slv'length - 1) is slv;" <> line <>- "begin" <> line <>- indent 2 ("return" <+> parens (hcat (punctuate "," elTyFromSLV)) <> semi) <> line <>- "end" <> semi- )- where- elTyToSLV = forM [0..(length elTys - 1)]- (\i -> "toSLV" <>- parens ("p." <> tyName t <> "_sel" <> int i))-- argLengths = map typeSize elTys- starts = 0 : snd (mapAccumL ((join (,) .) . (+)) 0 argLengths)- ends = map (subtract 1) (tail starts)-- elTyFromSLV = forM (zip starts ends)- (\(s,e) -> "fromSLV" <>- parens ("islv" <> parens (int s <+> "to" <+> int e)))--funDec syn t@(Vector _ elTy) = Just- ( "function" <+> "toSLV" <+> parens ("value : " <+> vhdlTypeMark t) <+> "return std_logic_vector" <> semi <> line <>- "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> vhdlTypeMark t <> semi- , "function" <+> "toSLV" <+> parens ("value : " <+> vhdlTypeMark t) <+> "return std_logic_vector" <+> "is" <> line <>- indent 2- ( "alias ivalue :" <+> vhdlTypeMark t <> "(1 to value'length) is value;" <> line <>- "variable result :" <+> "std_logic_vector" <> parens ("1 to value'length * " <> int (typeSize elTy)) <> semi- ) <> line <>- "begin" <> line <>- indent 2- ("for i in ivalue'range loop" <> line <>- indent 2- ( "result" <> parens (parens ("(i - 1) * " <> int (typeSize elTy)) <+> "+ 1" <+>- "to i*" <> int (typeSize elTy)) <+>- ":=" <+> (case syn of- Vivado -> "ivalue" <> parens ("i")- _ -> "toSLV" <> parens ("ivalue" <> parens ("i"))) <> semi- ) <> line <>- "end" <+> "loop" <> semi <> line <>- "return" <+> "result" <> semi- ) <> line <>- "end" <> semi <> line <>- "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> vhdlTypeMark t <+> "is" <> line <>- indent 2- ( "alias islv :" <+> "std_logic_vector" <> "(0 to slv'length - 1) is slv;" <> line <>- "variable result :" <+> vhdlTypeMark t <> parens ("0 to slv'length / " <> eSz <+> "- 1") <> semi- ) <> line <>- "begin" <> line <>- indent 2- ("for i in result'range loop" <> line <>- indent 2- ( "result" <> parens "i" <+> ":=" <+> case syn of- Vivado -> getElem <> semi- _ | BitVector _ <- elTy -> getElem <> semi- | otherwise -> "fromSLV" <> parens getElem <> semi-- ) <> line <>- "end" <+> "loop" <> semi <> line <>- "return" <+> "result" <> semi- ) <> line <>- "end" <> semi- )- where- eSz = int (typeSize elTy)- getElem = "islv" <> parens ("i * " <> eSz <+> "to (i+1) * " <> eSz <+> "- 1")--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 <>- "begin" <> line <>- indent 2 ("return" <+> "slv" <> semi) <> line <>- "end" <> semi <> line <>- "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> "std_logic_vector" <+> "is" <> line <>- "begin" <> line <>- indent 2 ("return" <+> "slv" <> semi) <> line <>- "end" <> semi- )--funDec syn t@(RTree _ elTy) = Just- ( "function" <+> "toSLV" <+> parens ("value : " <+> vhdlTypeMark t) <+> "return std_logic_vector" <> semi <> line <>- "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> vhdlTypeMark t <> semi- , "function" <+> "toSLV" <+> parens ("value : " <+> vhdlTypeMark t) <+> "return std_logic_vector" <+> "is" <> line <>- indent 2- ( "alias ivalue :" <+> vhdlTypeMark t <> "(1 to value'length) is value;" <> line <>- "variable result :" <+> "std_logic_vector" <> parens ("1 to value'length * " <> int (typeSize elTy)) <> semi- ) <> line <>- "begin" <> line <>- indent 2- ("for i in ivalue'range loop" <> line <>- indent 2- ( "result" <> parens (parens ("(i - 1) * " <> int (typeSize elTy)) <+> "+ 1" <+>- "to i*" <> int (typeSize elTy)) <+>- ":=" <+> (case syn of- Vivado -> "ivalue" <> parens ("i")- _ -> "toSLV" <> parens ("ivalue" <> parens ("i"))) <> semi- ) <> line <>- "end" <+> "loop" <> semi <> line <>- "return" <+> "result" <> semi- ) <> line <>- "end" <> semi <> line <>- "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> vhdlTypeMark t <+> "is" <> line <>- indent 2- ( "alias islv :" <+> "std_logic_vector" <> "(0 to slv'length - 1) is slv;" <> line <>- "variable result :" <+> vhdlTypeMark t <> parens ("0 to slv'length / " <> eSz <+> "- 1") <> semi- ) <> line <>- "begin" <> line <>- indent 2- ("for i in result'range loop" <> line <>- indent 2- ( "result" <> parens "i" <+> ":=" <+> case syn of- Vivado -> getElem <> semi- _ | BitVector _ <- elTy -> getElem <> semi- | otherwise -> "fromSLV" <> parens getElem <> semi-- ) <> line <>- "end" <+> "loop" <> semi <> line <>- "return" <+> "result" <> semi- ) <> line <>- "end" <> semi- )- where- eSz = int (typeSize elTy)- getElem = "islv" <> parens ("i * " <> eSz <+> "to (i+1) * " <> eSz <+> "- 1")--funDec _ _ = Nothing--tyImports :: String -> VHDLM Doc-tyImports nm = do- mkId <- Mon (mkIdentifier <*> pure Basic)- libs <- Mon $ use libraries- packs <- Mon $ use packages- punctuate' semi $ sequence- ([ "library IEEE"- , "use IEEE.STD_LOGIC_1164.ALL"- , "use IEEE.NUMERIC_STD.ALL"- , "use IEEE.MATH_REAL.ALL"- , "use std.textio.all"- , "use work.all"- , "use work." <> pretty (mkId (T.pack nm `T.append` "_types")) <> ".all"- ] ++ (map (("library" <+>) . pretty) (nub libs))- ++ (map (("use" <+>) . pretty) (nub packs)))--entity :: Component -> VHDLM Doc-entity c = do- rec (p,ls) <- fmap unzip (ports (maximum ls))- "entity" <+> pretty (componentName c) <+> "is" <> line <>- (case p of- [] -> emptyDoc- _ -> indent 2 ("port" <>- parens (align $ vcat $ punctuate semi (pure p)) <>- semi)- ) <> line <>- "end" <> semi- where- ports l = sequence- $ [ (,fromIntegral $ T.length i) <$> (encodingNote ty <> fill l (pretty i) <+> colon <+> "in" <+> vhdlType ty)- | (i,ty) <- inputs c ] ++- [ (,fromIntegral $ T.length i) <$> (encodingNote ty <> fill l (pretty i) <+> colon <+> "out" <+> vhdlType ty)- | (_,(i,ty)) <- outputs c ]--architecture :: Component -> VHDLM Doc-architecture c =- nest 2- ("architecture structural of" <+> pretty (componentName c) <+> "is" <> line <>- decls (declarations c)) <> line <>- nest 2- ("begin" <> line <>- insts (declarations c)) <> line <>- "end" <> semi---- | Convert a Netlist HWType to a VHDL type-vhdlType :: HWType -> VHDLM Doc-vhdlType hwty = do- hwty' <- normaliseType hwty- Mon (tyCache %= HashSet.insert hwty')- go hwty'- where- go :: HWType -> VHDLM Doc- go Bool = "boolean"- go Bit = "std_logic"- go (Clock {}) = "std_logic"- go (Reset {}) = "std_logic"- go (BitVector n) = case n of- 0 -> "std_logic_vector (0 downto 1)"- _ -> "std_logic_vector" <> parens (int (n-1) <+> "downto 0")- go (Signed n) = case n of- 0 -> "signed (0 downto 1)"- _ -> "signed" <> parens (int (n-1) <+> "downto 0")- go (Unsigned n) = case n of- 0 -> "unsigned (0 downto 1)"- _ -> "unsigned" <> parens ( int (n-1) <+> "downto 0")- go (Vector n elTy) = do- nm <- Mon $ use modNm- pretty (T.toLower $ T.pack nm) <> "_types.array_of_" <> tyName elTy <> parens ("0 to " <> int (n-1))- go (RTree d elTy) = do- nm <- Mon $ use modNm- pretty (T.toLower $ T.pack nm) <> "_types.tree_of_" <> tyName elTy <> parens ("0 to " <> int ((2^d)-1))- go t@(Product _ _) = do- nm <- Mon $ use modNm- pretty (T.toLower $ T.pack nm) <> "_types." <> tyName t- go (Void {}) = "std_logic_vector (0 downto 1)"- go String = "string"- go ty = error $ $(curLoc) ++ "vhdlType: type is not normalised: " ++ show ty--sigDecl :: VHDLM Doc -> HWType -> VHDLM Doc-sigDecl d t = d <+> colon <+> vhdlType t---- | Convert a Netlist HWType to the root of a VHDL type-vhdlTypeMark :: HWType -> VHDLM Doc-vhdlTypeMark hwty = do- hwty' <- normaliseType hwty- Mon (tyCache %= HashSet.insert hwty')- go hwty'- where- go Bool = "boolean"- go Bit = "std_logic"- go (Clock {}) = "std_logic"- go (Reset {}) = "std_logic"- go (BitVector _) = "std_logic_vector"- go (Signed _) = "signed"- go (Unsigned _) = "unsigned"- go (Vector _ elTy) = do- nm <- Mon $ use modNm- pretty (T.toLower $ T.pack nm) <> "_types.array_of_" <> tyName elTy- go (RTree _ elTy) = do- nm <- Mon $ use modNm- pretty (T.toLower $ T.pack nm) <> "_types.tree_of_" <> tyName elTy- go t@(Product _ _) = do- nm <- Mon $ use modNm- pretty (T.toLower $ T.pack nm) <> "_types." <> tyName t- go t = error $ $(curLoc) ++ "vhdlTypeMark: " ++ show t--tyName :: HWType -> VHDLM Doc-tyName Bool = "boolean"-tyName Bit = "std_logic"-tyName (Clock {}) = "std_logic"-tyName (Reset {}) = "std_logic"-tyName (Vector n elTy) = "array_of_" <> int n <> "_" <> tyName elTy-tyName (RTree n elTy) = "tree_of_" <> int n <> "_" <> tyName elTy-tyName (BitVector n) = "std_logic_vector_" <> int n-tyName t@(Index _) = "unsigned_" <> int (typeSize t)-tyName (Signed n) = "signed_" <> int n-tyName (Unsigned n) = "unsigned_" <> int n-tyName t@(Sum _ _) = "std_logic_vector_" <> int (typeSize t)-tyName t@(Product nm _) = do- tN <- normaliseType t- Mon $ makeCached tN nameCache prodName- where- prodName = do- tyCache %= HashSet.insert t- seen <- use tySeen- mkId <- mkIdentifier <*> pure Basic- let nm' = (mkId . last . T.splitOn ".") nm- nm'' = if T.null nm'- then "product"- else nm'- nm3 = if nm'' `elem` seen- then go mkId seen (0::Integer) nm''- else nm''- tySeen %= (nm3:)- pretty nm3-- go mkId s i n =- let n' = n `T.append` T.pack ('_':show i)- in if n' `elem` s- then go mkId s (i+1) n- else n'-tyName t@(SP _ _) = "std_logic_vector_" <> int (typeSize t)-tyName _ = emptyDoc---- | Convert a Netlist HWType to an error VHDL value for that type-vhdlTypeErrValue :: HWType -> VHDLM Doc-vhdlTypeErrValue Bool = "true"-vhdlTypeErrValue Bit = "'-'"-vhdlTypeErrValue t@(Vector n elTy) = do- syn <-Mon hdlSyn- case syn of- Vivado -> vhdlTypeMark t <> "'" <> parens (int 0 <+> "to" <+> int (n-1) <+> rarrow <+>- "std_logic_vector'" <> parens (int 0 <+> "to" <+> int (typeSize elTy - 1) <+>- rarrow <+> "'-'"))- _ -> vhdlTypeMark t <> "'" <> parens (int 0 <+> "to" <+> int (n-1) <+> rarrow <+> vhdlTypeErrValue elTy)-vhdlTypeErrValue t@(RTree n elTy) = do- syn <-Mon hdlSyn- case syn of- Vivado -> vhdlTypeMark t <> "'" <> parens (int 0 <+> "to" <+> int (2^n - 1) <+> rarrow <+>- "std_logic_vector'" <> parens (int 0 <+> "to" <+> int (typeSize elTy - 1) <+>- rarrow <+> "'-'"))- _ -> vhdlTypeMark t <> "'" <> parens (int 0 <+> "to" <+> int (2^n - 1) <+> rarrow <+> vhdlTypeErrValue elTy)-vhdlTypeErrValue t@(Product _ elTys) = vhdlTypeMark t <> "'" <> tupled (mapM vhdlTypeErrValue elTys)-vhdlTypeErrValue (Reset {}) = "'-'"-vhdlTypeErrValue (Clock _ _ Source) = "'-'"-vhdlTypeErrValue (Clock _ _ Gated) = "('-',false)"-vhdlTypeErrValue (Void {}) = "std_logic_vector'(0 downto 1 => '-')"-vhdlTypeErrValue String = "\"ERROR\""-vhdlTypeErrValue t = vhdlTypeMark t <> "'" <> parens (int 0 <+> "to" <+> int (typeSize t - 1) <+> rarrow <+> "'-'")--vhdlRecSel- :: HWType- -> Int- -> VHDLM Doc-vhdlRecSel ty i = tyName ty <> "_sel" <> int i--decls :: [Declaration] -> VHDLM Doc-decls [] = emptyDoc-decls ds = do- rec (dsDoc,ls) <- fmap (unzip . catMaybes) $ mapM (decl (maximum ls)) ds- case dsDoc of- [] -> emptyDoc- _ -> punctuate' semi (pure dsDoc)--decl :: Int -> Declaration -> VHDLM (Maybe (Doc,Int))-decl l (NetDecl' noteM _ id_ ty) = Just <$> (,fromIntegral (T.length id_)) <$>- maybe id addNote noteM ("signal" <+> fill l (pretty id_) <+> colon <+> either pretty vhdlType ty)- where- addNote n = mappend ("--" <+> pretty n <> line)--decl _ _ = return Nothing--insts :: [Declaration] -> VHDLM Doc-insts [] = emptyDoc-insts is = vcat . punctuate line . fmap catMaybes $ mapM inst_ is---- | Turn a Netlist Declaration to a VHDL concurrent block-inst_ :: Declaration -> VHDLM (Maybe Doc)-inst_ (Assignment id_ e) = fmap Just $- pretty id_ <+> larrow <+> align (expr_ False e) <> semi--inst_ (CondAssignment id_ _ scrut _ [(Just (BoolLit b), l),(_,r)]) = fmap Just $- pretty id_ <+> larrow- <+> align (vsep (sequence [expr_ False t <+> "when" <+>- expr_ False scrut <+> "else"- ,expr_ False f <> semi- ]))- where- (t,f) = if b then (l,r) else (r,l)--inst_ (CondAssignment id_ _ scrut scrutTy es) = fmap Just $- "with" <+> parens (expr_ True scrut) <+> "select" <> line <>- indent 2 (pretty id_ <+> larrow <+> align (vcat (punctuate comma (conds esNub)) <> semi))- where- esMod = map (first (fmap (patMod scrutTy))) es- esNub = nubBy ((==) `on` fst) esMod-- conds :: [(Maybe Literal,Expr)] -> VHDLM [Doc]- conds [] = return []- conds [(_,e)] = expr_ False e <+> "when" <+> "others" <:> return []- conds ((Nothing,e):_) = expr_ False e <+> "when" <+> "others" <:> return []- conds ((Just c ,e):es') = expr_ False e <+> "when" <+> patLit scrutTy c <:> conds es'--inst_ (InstDecl libM nm lbl pms) = do- maybe (return ()) (\lib -> Mon (libraries %= (lib:))) libM- fmap Just $- nest 2 $ pretty lbl <+> colon <+> "entity"- <+> maybe emptyDoc ((<> ".") . pretty) libM <> pretty nm <> line <> pms' <> semi- where- pms' = do- rec (p,ls) <- fmap unzip $ sequence [ (,formalLength i) <$> fill (maximum ls) (expr_ False i) <+> "=>" <+> expr_ False e | (i,_,_,e) <- pms]- nest 2 $ "port map" <> line <> tupled (pure p)- formalLength (Identifier i _) = fromIntegral (T.length i)- formalLength _ = 0--inst_ (BlackBoxD _ libs imps inc bs bbCtx) =- fmap Just (Mon (column (renderBlackBox libs imps inc bs bbCtx)))--inst_ _ = return Nothing---- | Turn a Netlist expression into a VHDL expression-expr_ :: Bool -- ^ Enclose in parenthesis?- -> Expr -- ^ Expr to convert- -> VHDLM Doc-expr_ _ (Literal sizeM lit) = exprLit sizeM lit-expr_ _ (Identifier id_ Nothing) = pretty id_-expr_ _ (Identifier id_ (Just (Indexed (ty@(SP _ args),dcI,fI)))) = fromSLV argTy id_ start end- where- argTys = snd $ args !! dcI- argTy = argTys !! fI- argSize = typeSize argTy- other = otherSize argTys (fI-1)- start = typeSize ty - 1 - conSize ty - other- end = start - argSize + 1--expr_ _ (Identifier id_ (Just (Indexed (ty@(Product _ _),_,fI)))) =- pretty id_ <> dot <> tyName ty <> "_sel" <> int fI--expr_ _ (Identifier id_ (Just (Indexed (ty@(Clock _ _ Gated),_,fI)))) = do- ty' <- normaliseType ty- pretty id_ <> dot <> tyName ty' <> "_sel" <> int fI--expr_ _ (Identifier id_ (Just (Indexed ((Vector _ elTy),1,0)))) = do- syn <- Mon hdlSyn- case syn of- Vivado -> do- id' <- fmap renderOneLine (pretty id_ <> parens (int 0))- fromSLV elTy id' (typeSize elTy - 1) 0- _ -> pretty id_ <> parens (int 0)-expr_ _ (Identifier id_ (Just (Indexed ((Vector n _),1,1)))) = pretty id_ <> parens (int 1 <+> "to" <+> int (n-1))---- This is a "Hack", we cannot construct trees with a negative depth. This is--- here so that we can recognise merged RTree modifiers. See the code in--- @Clash.Backend.nestM@ which construct these tree modifiers.-expr_ _ (Identifier id_ (Just (Indexed (RTree (-1) _,l,r)))) =- pretty id_ <> parens (int l <+> "to" <+> int (r-1))--expr_ _ (Identifier id_ (Just (Indexed ((RTree 0 elTy),0,0)))) = do- syn <- Mon hdlSyn- case syn of- Vivado -> do- id' <- fmap renderOneLine (pretty id_ <> parens (int 0))- fromSLV elTy id' (typeSize elTy - 1) 0- _ -> pretty id_ <> parens (int 0)-expr_ _ (Identifier id_ (Just (Indexed ((RTree n _),1,0)))) =- let z = 2^(n-1)- in pretty id_ <> parens (int 0 <+> "to" <+> int (z-1))-expr_ _ (Identifier id_ (Just (Indexed ((RTree n _),1,1)))) =- let z = 2^(n-1)- z' = 2^n- in pretty id_ <> parens (int z <+> "to" <+> int (z'-1))---- This is a HACK for Clash.Driver.TopWrapper.mkOutput--- Vector's don't have a 10'th constructor, this is just so that we can--- recognize the particular case-expr_ _ (Identifier id_ (Just (Indexed ((Vector _ elTy),10,fI)))) = do- syn <- Mon hdlSyn- case syn of- Vivado -> do- id' <- fmap renderOneLine (pretty id_ <> parens (int fI))- fromSLV elTy id' (typeSize elTy - 1) 0- _ -> pretty id_ <> parens (int fI)---- This is a HACK for Clash.Driver.TopWrapper.mkOutput--- RTree's don't have a 10'th constructor, this is just so that we can--- recognize the particular case-expr_ _ (Identifier id_ (Just (Indexed ((RTree _ elTy),10,fI)))) = do- syn <- Mon hdlSyn- case syn of- Vivado -> do- id' <- fmap renderOneLine (pretty id_ <> parens (int fI))- fromSLV elTy id' (typeSize elTy - 1) 0- _ -> pretty id_ <> parens (int fI)--expr_ _ (Identifier id_ (Just (DC (ty@(SP _ _),_)))) = pretty id_ <> parens (int start <+> "downto" <+> int end)- where- start = typeSize ty - 1- end = typeSize ty - conSize ty--expr_ _ (Identifier id_ (Just (Indexed ((Signed _ ),_,_)))) = do- iw <- Mon $ use intWidth- "resize" <> parens (pretty id_ <> "," <> int iw)-expr_ _ (Identifier id_ (Just (Indexed ((Unsigned _),_,_)))) = do- iw <- Mon $ use intWidth- "resize" <> parens (pretty id_ <> "," <> int iw)--expr_ b (Identifier id_ (Just (Nested m1 m2))) = case nestM m1 m2 of- Just m3 -> expr_ b (Identifier id_ (Just m3))- _ -> do- k <- expr_ b (Identifier id_ (Just m1))- expr_ b (Identifier (renderOneLine k) (Just m2))--expr_ _ (Identifier id_ (Just _)) = pretty id_--expr_ b (DataCon _ (DC (Void {}, -1)) [e]) = expr_ b e--expr_ _ (DataCon ty@(Vector 0 _) _ _) = vhdlTypeErrValue ty--expr_ _ (DataCon ty@(Vector 1 elTy) _ [e]) = do- syn <- Mon hdlSyn- case syn of- Vivado -> vhdlTypeMark ty <> "'" <> parens (int 0 <+> rarrow <+> toSLV elTy e)- _ -> vhdlTypeMark ty <> "'" <> parens (int 0 <+> rarrow <+> expr_ False e)-expr_ _ e@(DataCon ty@(Vector _ elTy) _ [e1,e2]) = do- syn <- Mon hdlSyn- case syn of- Vivado -> vhdlTypeMark 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)- _ -> vhdlTypeMark ty <> "'" <> case vectorChain e of- Just es -> align (tupled (mapM (expr_ False) es))- Nothing -> parens (vhdlTypeMark elTy <> "'" <> parens (expr_ False e1) <+> "&" <+> expr_ False e2)--expr_ _ (DataCon ty@(RTree 0 elTy) _ [e]) = do- syn <- Mon hdlSyn- case syn of- Vivado -> vhdlTypeMark ty <> "'" <> parens (int 0 <+> rarrow <+> toSLV elTy e)- _ -> vhdlTypeMark ty <> "'" <> parens (int 0 <+> rarrow <+> expr_ False e)-expr_ _ e@(DataCon ty@(RTree d elTy) _ [e1,e2]) = vhdlTypeMark ty <> "'" <> case rtreeChain e of- Just es -> tupled (mapM (expr_ False) es)- Nothing -> parens (vhdlTypeMark (RTree (d-1) elTy) <> "'" <> parens (expr_ False e1) <+>- "&" <+> expr_ False e2)--expr_ _ (DataCon ty@(SP _ args) (DC (_,i)) es) = assignExpr- where- argTys = snd $ args !! i- dcSize = conSize ty + sum (map typeSize argTys)- dcExpr = expr_ False (dcToExpr ty i)- argExprs = map parens (zipWith toSLV argTys es)- extraArg = case typeSize ty - dcSize of- 0 -> []- 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@(Product _ _) _ es) =- tupled $ zipWithM (\i e' -> tyName ty <> "_sel" <> int i <+> rarrow <+> expr_ False e') [0..] es--expr_ _ (DataCon ty@(Clock _ _ Gated) _ es) = do- ty' <- normaliseType ty- tupled $ zipWithM (\i e' -> tyName ty' <> "_sel" <> int i <+> rarrow <+> expr_ False e') [0..] es--expr_ _ (BlackBoxE pNm _ _ _ _ bbCtx _)- | pNm == "Clash.Sized.Internal.Signed.fromInteger#"- , [Literal _ (NumLit n), Literal _ i] <- extractLiterals bbCtx- = exprLit (Just (Signed (fromInteger n),fromInteger n)) i--expr_ _ (BlackBoxE pNm _ _ _ _ bbCtx _)- | pNm == "Clash.Sized.Internal.Unsigned.fromInteger#"- , [Literal _ (NumLit n), Literal _ i] <- extractLiterals bbCtx- = exprLit (Just (Unsigned (fromInteger n),fromInteger n)) i--expr_ _ (BlackBoxE pNm _ _ _ _ bbCtx _)- | pNm == "Clash.Sized.Internal.BitVector.fromInteger#"- , [Literal _ (NumLit n), Literal _ i] <- extractLiterals bbCtx- = exprLit (Just (BitVector (fromInteger n),fromInteger n)) i--expr_ _ (BlackBoxE pNm _ _ _ _ bbCtx _)- | pNm == "Clash.Sized.Internal.BitVector.fromInteger##"- , [Literal _ i] <- extractLiterals bbCtx- = exprLit (Just (Bit,1)) i--expr_ _ (BlackBoxE pNm _ _ _ _ bbCtx _)- | pNm == "Clash.Sized.Internal.Index.fromInteger#"- , [Literal _ (NumLit n), Literal _ i] <- extractLiterals bbCtx- , Just k <- clogBase 2 n- , let k' = max 1 k- = exprLit (Just (Unsigned k',k')) i--expr_ _ (BlackBoxE pNm _ _ _ _ bbCtx _)- | pNm == "Clash.Sized.Internal.Index.maxBound#"- , [Literal _ (NumLit n)] <- extractLiterals bbCtx- , n > 0- , Just k <- clogBase 2 n- , 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))--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 (Sum _ _) (Right id_)) = do- iw <- Mon $ use intWidth- "signed" <> parens ("std_logic_vector" <> parens ("resize" <> parens ("unsigned" <> parens (pretty id_) <> "," <> int iw)))--expr_ _ (DataTag (Product _ _) (Right _)) = do- iw <- Mon $ use intWidth- "to_signed" <> parens (int 0 <> "," <> int iw)-expr_ _ (DataTag hty@(SP _ _) (Right id_)) = do {- ; iw <- Mon $ use intWidth- ; "signed" <> parens ("std_logic_vector" <> parens (- "resize" <> parens ("unsigned" <> parens (pretty id_ <> parens (int start <+> "downto" <+> int end))- <> "," <> int iw)))- }- where- start = typeSize hty - 1- end = typeSize hty - conSize hty--expr_ _ (DataTag (Vector 0 _) (Right _)) = do- iw <- Mon $ use intWidth- "to_signed" <> parens (int 0 <> "," <> int iw)-expr_ _ (DataTag (Vector _ _) (Right _)) = do- iw <- Mon $ use intWidth- "to_signed" <> parens (int 1 <> "," <> int iw)--expr_ _ (DataTag (RTree 0 _) (Right _)) = do- iw <- Mon $ use intWidth- "to_signed" <> parens (int 0 <> "," <> int iw)-expr_ _ (DataTag (RTree _ _) (Right _)) = do- iw <- Mon $ use intWidth- "to_signed" <> parens (int 1 <> "," <> int iw)--expr_ _ (ConvBV topM hwty True e) = do- nm <- Mon $ use modNm- case topM of- Nothing -> pretty (T.pack nm) <> "_types" <> dot <> "toSLV" <>- parens (vhdlTypeMark hwty <> "'" <> parens (expr_ False e))- Just t -> pretty t <> dot <> pretty t <> "_types" <> dot <> "toSLV" <> parens (expr_ False e)--expr_ _ (ConvBV topM _ False e) = do- nm <- Mon $ use modNm- maybe (pretty (T.pack nm) <> "_types" ) (\t -> pretty t <> dot <> pretty t <> "_types") topM <> dot <>- "fromSLV" <> parens (expr_ False e)--expr_ _ e = error $ $(curLoc) ++ (show e) -- empty--otherSize :: [HWType] -> Int -> Int-otherSize _ n | n < 0 = 0-otherSize [] _ = 0-otherSize (a:as) n = typeSize a + otherSize as (n-1)--vectorChain :: Expr -> Maybe [Expr]-vectorChain (DataCon (Vector 0 _) _ _) = Just []-vectorChain (DataCon (Vector 1 _) _ [e]) = Just [e]-vectorChain (DataCon (Vector _ _) _ [e1,e2]) = Just e1 <:> vectorChain e2-vectorChain _ = Nothing--rtreeChain :: Expr -> Maybe [Expr]-rtreeChain (DataCon (RTree 1 _) _ [e]) = Just [e]-rtreeChain (DataCon (RTree _ _) _ [e1,e2]) = liftA2 (++) (rtreeChain e1) (rtreeChain e2)-rtreeChain _ = Nothing--exprLit :: Maybe (HWType,Size) -> Literal -> VHDLM Doc-exprLit Nothing (NumLit i) = integer i--exprLit (Just (hty,sz)) (NumLit i) = case hty of- Unsigned n- | i < 2^(31 :: Integer) -> "to_unsigned" <> parens (integer i <> "," <> int n)- | otherwise -> "unsigned'" <> parens lit- Signed n- | i < 2^(31 :: Integer) && i > (-2^(31 :: Integer)) -> "to_signed" <> parens (integer i <> "," <> int n)- | otherwise -> "signed'" <> parens lit- BitVector _ -> "std_logic_vector'" <> parens lit- Bit -> squotes (int (fromInteger i `mod` 2))- _ -> blit-- where- validHexLit = sz `mod` 4 == 0 && sz /= 0- lit = if validHexLit then hlit else blit- blit = bits (toBits sz i)- i' = case hty of- Signed _ -> let mask = 2^(sz-1) in case divMod i mask of- (s,i'') | even s -> i''- | otherwise -> i'' - mask- _ -> i `mod` 2^sz- hlit = (if i' < 0 then "-" else emptyDoc) <> hex (toHex sz i')-exprLit _ (BoolLit t) = if t then "true" else "false"-exprLit _ (BitLit b) = squotes $ bit_char b-exprLit _ (StringLit s) = pretty . T.pack $ show s-exprLit _ l = error $ $(curLoc) ++ "exprLit: " ++ show l--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 _ l = exprLit Nothing l--patMod :: HWType -> Literal -> Literal-patMod hwTy (NumLit i) = NumLit (i `mod` (2 ^ typeSize hwTy))-patMod _ l = l--toBits :: Integral a => Int -> a -> [Bit]-toBits size val = map (\x -> if odd x then H else L)- $ reverse- $ take size- $ map (`mod` 2)- $ iterate (`div` 2) val--bits :: [Bit] -> VHDLM Doc-bits = dquotes . hcat . mapM bit_char--toHex :: Int -> Integer -> String-toHex sz i =- let Just d = clogBase 16 (2^sz)- in printf ("%0" ++ show d ++ "X") (abs i)--hex :: String -> VHDLM Doc-hex s = char 'x' <> dquotes (pretty (T.pack s))--bit_char :: Bit -> VHDLM Doc-bit_char H = char '1'-bit_char L = char '0'-bit_char U = char '-'-bit_char Z = char 'Z'--toSLV :: HWType -> Expr -> VHDLM Doc-toSLV Bool e = do- nm <- Mon $ use modNm- pretty (T.toLower $ T.pack nm) <> "_types.toSLV" <> parens (expr_ False e)-toSLV Bit e = do- nm <- Mon $ use modNm- pretty (T.toLower $ T.pack nm) <> "_types.toSLV" <> parens (expr_ False e)-toSLV (Clock {}) e = do- nm <- Mon $ use modNm- pretty (T.toLower $ T.pack nm) <> "_types.toSLV" <> parens (expr_ False e)-toSLV (Reset {}) e = do- nm <- Mon $ use modNm- pretty (T.toLower $ T.pack nm) <> "_types.toSLV" <> parens (expr_ False e)-toSLV (BitVector _) e = expr_ False 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 t@(Product _ tys) (Identifier id_ Nothing) = do- selIds' <- sequence selIds- encloseSep lparen rparen " & " (zipWithM toSLV tys selIds')- where- tName = tyName t- selNames = map (fmap renderOneLine ) [pretty id_ <> dot <> tName <> "_sel" <> int i | i <- [0..(length tys)-1]]- selIds = map (fmap (\n -> Identifier n Nothing)) selNames-toSLV (Product _ tys) (DataCon _ _ es) = do- encloseSep lparen rparen " & " (zipWithM toSLV tys es)-toSLV (Product _ _) e = do- nm <- Mon $ use modNm- pretty (T.toLower $ T.pack nm) <> "_types.toSLV" <> parens (expr_ False e)-toSLV (SP _ _) e = expr_ False e-toSLV (Vector n elTy) (Identifier id_ Nothing) = do- selIds' <- sequence selIds- syn <- Mon hdlSyn- parens (vcat $ punctuate " & "- (case syn of- Vivado -> mapM (expr_ False) selIds'- _ -> mapM (toSLV elTy) selIds'))- where- selNames = map (fmap renderOneLine ) $ [pretty id_ <> parens (int i) | i <- [0 .. (n-1)]]- selIds = map (fmap (`Identifier` Nothing)) selNames-toSLV (Vector n elTy) (DataCon _ _ es) = parens $ vcat $ punctuate " & " (zipWithM toSLV [elTy,Vector (n-1) elTy] es)-toSLV (Vector _ _) e = do- nm <- Mon $ use modNm- pretty (T.toLower $ T.pack nm) <> "_types.toSLV" <> parens (expr_ False e)-toSLV hty e = error $ $(curLoc) ++ "toSLV: ty:" ++ show hty ++ "\n expr: " ++ show e--fromSLV :: HWType -> Identifier -> Int -> Int -> VHDLM Doc-fromSLV Bool id_ start _ = do- nm <- Mon $ use modNm- pretty (T.toLower $ T.pack nm) <> "_types.fromSLV" <> parens (pretty id_ <> parens (int start <+> "downto" <+> int start))-fromSLV Bit id_ start _ = pretty id_ <> parens (int start)-fromSLV (BitVector _) id_ start end = pretty id_ <> parens (int start <+> "downto" <+> int end)-fromSLV (Index _) id_ start end = "unsigned" <> parens (pretty id_ <> parens (int start <+> "downto" <+> int end))-fromSLV (Signed _) id_ start end = "signed" <> parens (pretty id_ <> parens (int start <+> "downto" <+> int end))-fromSLV (Unsigned _) id_ start end = "unsigned" <> parens (pretty id_ <> parens (int start <+> "downto" <+> int end))-fromSLV (Sum _ _) id_ start end = pretty id_ <> parens (int start <+> "downto" <+> int end)-fromSLV t@(Product _ tys) id_ start _ = do- tupled $ zipWithM (\s e -> s <+> rarrow <+> e) selNames args- where- tName = tyName t- selNames = [tName <> "_sel" <> int i | i <- [0..]]- argLengths = map typeSize tys- starts = start : snd (mapAccumL ((join (,) .) . (-)) start argLengths)- ends = map (+1) (tail starts)- args = zipWith3 (`fromSLV` id_) tys starts ends--fromSLV (SP _ _) id_ start end = pretty id_ <> parens (int start <+> "downto" <+> int end)-fromSLV (Vector n elTy) id_ start _ =- if n > 1 then tupled args- else parens (int 0 <+> rarrow <+> fmap head args)- where- argLength = typeSize elTy- starts = take (n + 1) $ iterate (subtract argLength) start- ends = map (+1) (tail starts)- args = do syn <- Mon hdlSyn- let elTy' = case syn of- Vivado -> BitVector (argLength - 1)- _ -> elTy- zipWithM (fromSLV elTy' id_) starts ends-fromSLV (Clock {}) id_ start _ = pretty id_ <> parens (int start)-fromSLV (Reset {}) id_ start _ = pretty id_ <> parens (int start)-fromSLV hty _ _ _ = error $ $(curLoc) ++ "fromSLV: " ++ show hty--dcToExpr :: HWType -> Int -> Expr-dcToExpr ty i = Literal (Just (ty,conSize ty)) (NumLit (toInteger i))--larrow :: VHDLM Doc-larrow = "<="--rarrow :: VHDLM Doc-rarrow = "=>"--parenIf :: Monad m => Bool -> Mon m Doc -> Mon m Doc-parenIf True = parens-parenIf False = id--punctuate' :: Monad m => Mon m Doc -> Mon m [Doc] -> Mon m Doc-punctuate' s d = vcat (punctuate s d) <> s--encodingNote :: HWType -> VHDLM Doc-encodingNote (Clock _ _ Gated) = "-- gated clock" <> line-encodingNote (Clock {}) = "-- clock" <> line-encodingNote (Reset {}) = "-- asynchronous reset: active high" <> line-encodingNote _ = emptyDoc+ 2017-2018, Google Inc.+ License : BSD2 (see the file LICENSE)+ Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>++ Generate VHDL for assorted Netlist datatypes+-}++{-# LANGUAGE CPP #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecursiveDo #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ViewPatterns #-}++module Clash.Backend.VHDL (VHDLState) where++import Control.Applicative (liftA2)+import Control.Lens hiding (Indexed, Empty)+import Control.Monad (forM,join,zipWithM)+import Control.Monad.State (State, StateT)+import Data.Bits (testBit, Bits)+import Data.Hashable (Hashable)+import Data.HashMap.Lazy (HashMap)+import qualified Data.HashMap.Lazy as HashMap+import qualified Data.HashMap.Strict as HashMapS+import Data.HashSet (HashSet)+import qualified Data.HashSet as HashSet+import Data.List+ (mapAccumL, nub, nubBy, intersperse, group, sort)+import Data.Maybe (catMaybes,fromMaybe,mapMaybe)+#if !MIN_VERSION_base(4,11,0)+import Data.Monoid hiding (Sum, Product)+#endif+import Data.Semigroup.Monad.Extra+import qualified Data.Text.Lazy as T+import qualified Data.Text as TextS+import qualified Data.Text.Prettyprint.Doc as PP+import Data.Text.Prettyprint.Doc.Extra+import GHC.Stack (HasCallStack)+import qualified System.FilePath+import Text.Printf+import TextShow (showt)++import Clash.Annotations.Primitive (HDL (..))+import Clash.Annotations.BitRepresentation.Internal+ (ConstrRepr'(..))+import Clash.Annotations.BitRepresentation.ClashLib+ (bitsToBits)+import Clash.Annotations.BitRepresentation.Util+ (BitOrigin(Lit, Field), bitOrigins, bitRanges)+import Clash.Backend+import Clash.Core.Var (Attr'(..),attrName)+import Clash.Netlist.BlackBox.Types (HdlSyn (..))+import Clash.Netlist.BlackBox.Util+ (extractLiterals, renderBlackBox, renderFilePath)+import Clash.Netlist.Id (IdType (..), mkBasicId')+import Clash.Netlist.Types hiding (_intWidth, intWidth)+import Clash.Netlist.Util hiding (mkIdentifier)+import Clash.Util+ (SrcSpan, noSrcSpan, clogBase, curLoc, first, makeCached, on, traceIf, (<:>))+import Clash.Util.Graph (reverseTopSort)++#ifdef CABAL+import qualified Paths_clash_lib+#endif++-- | State for the 'Clash.Netlist.VHDL.VHDLM' monad:+data VHDLState =+ VHDLState+ { _tyCache :: (HashSet HWType)+ -- ^ Previously encountered HWTypes+ , _tySeen :: HashMap Identifier Word+ -- ^ Generated product types+ , _nameCache :: (HashMap (HWType, Bool) TextS.Text)+ -- ^ Cache for type names. Bool indicates whether this name includes length+ -- information in its first "part". See `tyName'` for more information.+ , _modNm :: Identifier+ , _srcSpan :: SrcSpan+ , _libraries :: [T.Text]+ , _packages :: [T.Text]+ , _includes :: [(String,Doc)]+ , _dataFiles :: [(String,FilePath)]+ -- ^ Files to be copied: (filename, old path)+ , _memoryDataFiles:: [(String,String)]+ -- ^ Files to be stored: (filename, contents). These files are generated+ -- during the execution of 'genNetlist'.+ , _idSeen :: HashMapS.HashMap Identifier Word+ , _intWidth :: Int+ -- ^ Int/Word/Integer bit-width+ , _hdlsyn :: HdlSyn+ -- ^ For which HDL synthesis tool are we generating VHDL+ , _extendedIds :: Bool+ , _undefValue :: Maybe (Maybe Int)+ }++makeLenses ''VHDLState++squote :: Mon (State VHDLState) Doc+squote = string "'"++primsRoot :: IO FilePath+#ifdef CABAL+primsRoot = Paths_clash_lib.getDataFileName "prims"+#else+primsRoot = return ("clash-lib" System.FilePath.</> "prims")+#endif++instance Backend VHDLState where+ initBackend = VHDLState HashSet.empty HashMap.empty HashMap.empty ""+ noSrcSpan [] [] [] [] [] HashMapS.empty+ hdlKind = const VHDL+ primDirs = const $ do root <- primsRoot+ return [ root System.FilePath.</> "common"+ , root System.FilePath.</> "vhdl"+ ]+ extractTypes = _tyCache+ name = const "vhdl"+ extension = const ".vhdl"++ genHDL = genVHDL+ mkTyPackage = mkTyPackage_+ hdlType Internal (filterTransparent -> ty) = sizedQualTyName ty+ hdlType (External nm) (filterTransparent -> ty) =+ let sized = sizedQualTyName ty in+ case ty of+ Bit -> sized+ Bool -> sized+ Signed _ -> sized+ Unsigned _ -> sized+ BitVector _ -> sized+ _ -> pretty nm <> dot <> sized+ hdlTypeErrValue = sizedQualTyNameErrValue+ hdlTypeMark = qualTyName+ hdlRecSel = vhdlRecSel+ hdlSig t ty = sigDecl (pretty t) ty+ genStmt = const emptyDoc+ inst = inst_+ expr = expr_+ iwWidth = use intWidth+ toBV _ id_ = do+ nm <- Mon $ use modNm+ pretty (TextS.toLower nm) <> "_types.toSLV" <> parens (pretty id_)+ fromBV _ id_ = do+ nm <- Mon $ use modNm+ pretty (TextS.toLower nm) <> "_types.fromSLV" <> parens (pretty id_)+ hdlSyn = use hdlsyn+ mkIdentifier = do+ allowExtended <- use extendedIds+ return (go allowExtended)+ where+ go _ Basic nm =+ case (stripTrailingUnderscore . filterReserved) (TextS.toLower (mkBasicId' VHDL True nm)) of+ nm' | TextS.null nm' -> "clash_internal"+ | otherwise -> nm'+ go esc Extended (rmSlash -> nm) = case go esc Basic nm of+ nm' | esc && nm /= nm' -> TextS.concat ["\\",nm,"\\"]+ | otherwise -> nm'+ extendIdentifier = do+ allowExtended <- use extendedIds+ return (go allowExtended)+ where+ go _ Basic nm ext =+ case (stripTrailingUnderscore . filterReserved) (TextS.toLower (mkBasicId' VHDL True (nm `TextS.append` ext))) of+ nm' | TextS.null nm' -> "clash_internal"+ | otherwise -> nm'+ go esc Extended ((rmSlash . escapeTemplate) -> nm) ext =+ let nmExt = nm `TextS.append` ext+ in case go esc Basic nm ext of+ nm' | esc && nm' /= nmExt -> case TextS.isPrefixOf "c$" nmExt of+ True -> TextS.concat ["\\",nmExt,"\\"]+ _ -> TextS.concat ["\\c$",nmExt,"\\"]+ | otherwise -> nm'++ setModName nm s = s {_modNm = nm}+ setSrcSpan = (srcSpan .=)+ getSrcSpan = use srcSpan+ blockDecl nm ds = do+ decs <- decls ds+ let attrs = [ (id_, attr)+ | NetDecl' _ _ id_ (Right hwtype) <- ds+ , attr <- hwTypeAttrs hwtype]+ if isEmpty decs+ then insts ds+ else nest 2+ (pretty nm <+> colon <+> "block" <> line <>+ pure decs <>+ if null attrs+ then emptyDoc+ else line <> line <> renderAttrs attrs) <> line <>+ nest 2+ ("begin" <> line <>+ insts ds) <> line <>+ "end block" <> semi+ unextend = return rmSlash+ addIncludes inc = includes %= (inc++)+ addLibraries libs = libraries %= (libs ++)+ addImports imps = packages %= (imps ++)+ addAndSetData f = do+ fs <- use dataFiles+ let (fs',f') = renderFilePath fs f+ dataFiles .= fs'+ return f'+ getDataFiles = use dataFiles+ addMemoryDataFile f = memoryDataFiles %= (f:)+ getMemoryDataFiles = use memoryDataFiles+ seenIdentifiers = idSeen+ ifThenElseExpr _ = False++rmSlash :: Identifier -> Identifier+rmSlash nm = fromMaybe nm $ do+ nm1 <- TextS.stripPrefix "\\" nm+ pure (TextS.filter (not . (== '\\')) nm1)++type VHDLM a = Mon (State VHDLState) a++-- | Time units: are added to 'reservedWords' as simulators trip over signals+-- named after them.+timeUnits :: [Identifier]+timeUnits = ["fs", "ps", "ns", "us", "ms", "sec", "min", "hr"]++-- List of reserved VHDL-2008 keywords+-- + used internal names: toslv, fromslv, tagtoenum, datatotag+-- + used IEEE library names: integer, boolean, std_logic, std_logic_vector,+-- signed, unsigned, to_integer, to_signed, to_unsigned, string+reservedWords :: [Identifier]+reservedWords = ["abs","access","after","alias","all","and","architecture"+ ,"array","assert","assume","assume_guarantee","attribute","begin","block"+ ,"body","buffer","bus","case","component","configuration","constant","context"+ ,"cover","default","disconnect","downto","else","elsif","end","entity","exit"+ ,"fairness","file","for","force","function","generate","generic","group"+ ,"guarded","if","impure","in","inertial","inout","is","label","library"+ ,"linkage","literal","loop","map","mod","nand","new","next","nor","not","null"+ ,"of","on","open","or","others","out","package","parameter","port","postponed"+ ,"procedure","process","property","protected","pure","range","record"+ ,"register","reject","release","rem","report","restrict","restrict_guarantee"+ ,"return","rol","ror","select","sequence","severity","signal","shared","sla"+ ,"sll","sra","srl","strong","subtype","then","to","transport","type"+ ,"unaffected","units","until","use","variable","vmode","vprop","vunit","wait"+ ,"when","while","with","xnor","xor","toslv","fromslv","tagtoenum","datatotag"+ ,"integer", "boolean", "std_logic", "std_logic_vector", "signed", "unsigned"+ ,"to_integer", "to_signed", "to_unsigned", "string","log"] ++ timeUnits++filterReserved :: Identifier -> Identifier+filterReserved s = if s `elem` reservedWords+ then s `TextS.append` "_r"+ else s++stripTrailingUnderscore :: Identifier -> Identifier+stripTrailingUnderscore = TextS.dropWhileEnd (== '_')++-- | Generate unique (partial) names for product fields. Example:+--+-- >>> productFieldNames [Unsigned 6, Unsigned 6, Bit, Bool]+-- ["unsigned6_0", "unsigned6_1", "bit", "boolean"]+productFieldNames+ :: HasCallStack+ => Maybe [TextS.Text]+ -- ^ Label hints. From user records, for example.+ -> [HWType]+ -- ^ Field types+ -> VHDLM [TextS.Text]+productFieldNames labels0 fields = do+ let labels1 = sequence labels0 ++ repeat Nothing+ hFields <- zipWithM hName labels1 fields++ let grouped = group $ sort $ hFields+ counted = HashMapS.fromList (map (\(g:gs) -> (g, succ (length gs))) grouped)+ names = snd $ mapAccumL (name' counted) HashMapS.empty hFields++ return names+ where+ hName+ :: Maybe Identifier+ -> HWType+ -> VHDLM Identifier+ hName Nothing field =+ tyName' False field+ hName (Just label) _field = do+ Mon (mkIdentifier <*> pure Basic <*> pure label)++ name'+ :: HashMap TextS.Text Int+ -> HashMap TextS.Text Int+ -> TextS.Text+ -> (HashMap TextS.Text Int, TextS.Text)+ name' counted countMap fieldName+ | counted HashMapS.! fieldName > 1 =+ -- Seen this fieldname more than once, so we need to add a number+ -- as a postfix:+ let succ' n = Just (maybe (0 :: Int) (+1) n) in+ let countMap' = HashMapS.alter succ' fieldName countMap in+ -- Each field will get a distinct number:+ let count = countMap' HashMapS.! fieldName in+ (countMap', TextS.concat [fieldName, "_", showt count])+ | otherwise =+ -- This fieldname has only been seen once, so we don't need to add+ -- a number as a postfix:+ (countMap, fieldName)++productFieldName+ :: HasCallStack+ => Maybe [TextS.Text]+ -- ^ Label hints. From user records, for example.+ -> [HWType]+ -- ^ Field types+ -> Int+ -- ^ Index of field+ -> VHDLM Doc+productFieldName labels fields fieldIndex = do+ -- TODO: cache+ names <- productFieldNames labels fields+ return (PP.pretty (names !! fieldIndex))++selectProductField+ :: HasCallStack+ => Maybe [TextS.Text]+ -- ^ Label hints. From user records, for example.+ -> [HWType]+ -- ^ Field types+ -> Int+ -- ^ Index of field+ -> VHDLM Doc+selectProductField fieldLabels fieldTypes fieldIndex =+ "_sel" <> int fieldIndex <> "_" <> productFieldName fieldLabels fieldTypes fieldIndex++-- | Generate VHDL for a Netlist component+genVHDL :: Identifier -> SrcSpan -> HashMapS.HashMap Identifier Word -> Component -> VHDLM ((String,Doc),[(String,Doc)])+genVHDL nm sp seen c = preserveSeen $ do+ Mon $ idSeen .= seen+ -- Don't have type names conflict with component names+ Mon $ tySeen %= HashMap.unionWith max seen+ Mon $ setSrcSpan sp+ v <- vhdl+ i <- Mon $ use includes+ Mon $ libraries .= []+ Mon $ packages .= []+ return ((TextS.unpack cName,v),i)+ where+ cName = componentName c+ vhdl = do+ ent <- entity c+ arch <- architecture c+ imps <- tyImports nm+ ("-- Automatically generated VHDL-93" <> line <>+ pure imps <> line <> line <>+ pure ent <> line <> line <>+ pure arch)++-- | Generate a VHDL package containing type definitions for the given HWTypes+mkTyPackage_ :: Identifier+ -> [HWType]+ -> VHDLM [(String,Doc)]+mkTyPackage_ modName (map filterTransparent -> hwtys) = do+ { syn <- Mon hdlSyn+ ; mkId <- Mon (mkIdentifier <*> pure Basic)+ ; 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)++ ; (:[]) <$> (TextS.unpack $ mkId (modName `TextS.append` "_types"),) <$>+ "library IEEE;" <> line <>+ "use IEEE.STD_LOGIC_1164.ALL;" <> line <>+ "use IEEE.NUMERIC_STD.ALL;" <> line <> line <>+ "package" <+> pretty (mkId (modName `TextS.append` "_types")) <+> "is" <> line <>+ indent 2 ( packageDec <> line <>+ vcat (sequence funDecs)+ ) <> line <>+ "end" <> semi <> packageBodyDec funBodies+ }+ where+ packageBodyDec :: [VHDLM Doc] -> VHDLM Doc+ packageBodyDec funBodies = case funBodies of+ [] -> emptyDoc+ _ -> do+ { mkId <- Mon (mkIdentifier <*> pure Basic)+ ; line <> line <>+ "package" <+> "body" <+> pretty (mkId (modName `TextS.append` "_types")) <+> "is" <> line <>+ indent 2 (vcat (sequence funBodies)) <> line <>+ "end" <> semi+ }++ eqTypM :: HWType -> HWType -> Bool+ eqTypM (Signed _) (Signed _) = True+ eqTypM (Unsigned _) (Unsigned _) = True+ eqTypM (BitVector _) (BitVector _) = True+ eqTypM ty1 ty2 = ty1 == ty2++mkUsedTys :: HWType -> [HWType]+mkUsedTys hwty = hwty : case hwty of+ Vector _ elTy -> mkUsedTys elTy+ RTree _ elTy -> mkUsedTys elTy+ Product _ _ elTys -> concatMap mkUsedTys elTys+ SP _ elTys -> concatMap mkUsedTys (concatMap snd elTys)+ BiDirectional _ elTy -> mkUsedTys elTy+ Annotated _ elTy -> mkUsedTys elTy+ CustomSP _ _ _ tys0 ->+ let tys1 = concat [tys | (_repr, _id, tys) <- tys0] in+ concatMap mkUsedTys tys1+ _ ->+ []++topSortHWTys+ :: [HWType]+ -> [HWType]+topSortHWTys hwtys = sorted+ where+ nodes = zip [0..] hwtys+ nodesI = HashMap.fromList (zip hwtys [0..])+ edges = concatMap edge hwtys++ sorted =+ case reverseTopSort nodes edges of+ Left err -> error $ $(curLoc) ++ "[BUG IN CLASH] topSortHWTys: " ++ err+ Right ns -> ns++ -- `elTy` needs to be rendered before `t`+ edge t@(Vector _ elTy) =+ case HashMap.lookup (mkVecZ elTy) nodesI of+ Just node ->+ [(nodesI HashMap.! t, node)]+ Nothing ->+ []++ -- `elTy` needs to be rendered before `t`+ edge t@(RTree _ elTy) =+ let vecZ = mkVecZ elTy in+ case HashMap.lookup vecZ nodesI of+ Just node ->+ [(nodesI HashMap.! t, node)] ++ edge elTy+ Nothing ->+ []++ -- `tys` need to be rendered before `t`+ edge t@(Product _ _ tys0) =+ let tys1 = [HashMap.lookup (mkVecZ ty) nodesI | ty <- tys0] in+ map (nodesI HashMap.! t,) (catMaybes tys1)++ edge t@(SP _ tys0) =+ let tys1 = concat (map snd tys0) in+ let tys2 = [HashMap.lookup (mkVecZ ty) nodesI | ty <- tys1] in+ map (nodesI HashMap.! t,) (catMaybes tys2)++ edge t@(CustomSP _ _ _ tys0) =+ let tys1 = concat [tys | (_repr, _id, tys) <- tys0] in+ let tys2 = [HashMap.lookup (mkVecZ ty) nodesI | ty <- tys1] in+ map (nodesI HashMap.! t,) (catMaybes tys2)++ edge _ = []++mkVecZ :: HWType -> HWType+mkVecZ (Vector _ elTy) = Vector 0 elTy+mkVecZ (RTree _ elTy) = RTree 0 elTy+mkVecZ t = t++typAliasDec :: HasCallStack => HWType -> VHDLM Doc+typAliasDec hwty =+ "subtype" <+> tyName hwty+ <+> "is"+ <+> sizedTyName (normaliseType hwty)+ <> semi++tyDec :: HasCallStack => HWType -> VHDLM Doc+tyDec hwty = do+ syn <- Mon hdlSyn+ case hwty of+ -- "Proper" custom types:+ Vector _ elTy ->+ case syn of+ Vivado ->+ "type" <+> tyName hwty+ <+> "is array (integer range <>) of std_logic_vector"+ <> parens (int (typeSize elTy - 1) <+> "downto 0")+ <> semi++ _ ->+ "type" <+> tyName hwty+ <+> "is array (integer range <>) of"+ <+> sizedQualTyName elTy+ <> semi++ RTree _ elTy ->+ case syn of+ Vivado ->+ "type" <+> tyName hwty+ <+> "is array (integer range <>) of"+ <+> "std_logic_vector"+ <> parens (int (typeSize elTy - 1) <+> "downto 0")+ <> semi++ _ ->+ "type" <+> tyName hwty+ <+> "is array (integer range <>) of"+ <+> sizedQualTyName elTy+ <> semi++ Product _ labels tys@(_:_:_) ->+ let selNames = map (\i -> tyName hwty <> selectProductField labels tys i) [0..] in+ let selTys = map sizedQualTyName tys in+ "type" <+> tyName hwty <+> "is record" <> line <>+ indent 2 (vcat $ zipWithM (\x y -> x <+> colon <+> y <> semi) selNames selTys) <> line <>+ "end record" <> semi++ -- Type aliases:+ Clock _ -> typAliasDec hwty+ Reset _ -> typAliasDec hwty+ Index _ -> typAliasDec hwty+ CustomSP _ _ _ _ -> typAliasDec hwty+ SP _ _ -> typAliasDec hwty+ Sum _ _ -> typAliasDec hwty+ CustomSum _ _ _ _ -> typAliasDec hwty++ -- VHDL builtin types:+ BitVector _ -> emptyDoc+ Bool -> emptyDoc+ Bit -> emptyDoc+ Unsigned _ -> emptyDoc+ Signed _ -> emptyDoc+ String -> emptyDoc+ Integer -> emptyDoc++ -- Transparent types:+ BiDirectional _ ty -> tyDec ty+ Annotated _ ty -> tyDec ty++ Void {} -> emptyDoc+ KnownDomain {} -> emptyDoc++ _ -> error $ $(curLoc) ++ show hwty+++++funDec :: 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 <>+ "function" <+> "dataToTag" <+> parens ("b" <+> colon <+> "in" <+> "boolean") <+> "return" <+> "signed" <> semi+ , "function" <+> "toSLV" <+> parens ("b" <+> colon <+> "in" <+> "boolean") <+> "return" <+> "std_logic_vector" <+> "is" <> line <>+ "begin" <> line <>+ indent 2 (vcat $ sequence ["if" <+> "b" <+> "then"+ , indent 2 ("return" <+> dquotes (int 1) <> semi)+ ,"else"+ , indent 2 ("return" <+> dquotes (int 0) <> semi)+ ,"end" <+> "if" <> semi+ ]) <> line <>+ "end" <> semi <> line <>+ "function" <+> "fromSLV" <+> parens ("sl" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> "boolean" <+> "is" <> line <>+ "begin" <> line <>+ indent 2 (vcat $ sequence ["if" <+> "sl" <+> "=" <+> dquotes (int 1) <+> "then"+ , indent 2 ("return" <+> "true" <> semi)+ ,"else"+ , indent 2 ("return" <+> "false" <> semi)+ ,"end" <+> "if" <> semi+ ]) <> line <>+ "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 ("return" <+> "false" <> semi)+ ,"else"+ , indent 2 ("return" <+> "true" <> semi)+ ,"end" <+> "if" <> semi+ ]) <> line <>+ "end" <> semi <> line <>+ "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)+ ,"else"+ , indent 2 ("return" <+> "to_signed" <> parens (int 0 <> comma <> (Mon (use intWidth) >>= int)) <> semi)+ ,"end" <+> "if" <> semi+ ]) <> line <>+ "end" <> semi+ )++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 <>+ "begin" <> line <>+ indent 2 ("return" <+> "std_logic_vector'" <> parens (int 0 <+> rarrow <+> "sl") <> semi) <> line <>+ "end" <> semi <> line <>+ "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> tyName bit <+> "is" <> line <>+ indent 2+ ( "alias islv : std_logic_vector (0 to slv'length - 1) is slv;"+ ) <> line <>+ "begin" <> line <>+ indent 2 ("return" <+> "islv" <> parens (int 0) <> semi) <> line <>+ "end" <> semi+ )++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 <>+ "begin" <> line <>+ indent 2 ("return" <+> "std_logic_vector" <> parens ("s") <> semi) <> line <>+ "end" <> semi <> line <>+ "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> "signed" <+> "is" <> line <>+ "begin" <> line <>+ indent 2 ("return" <+> "signed" <> parens ("slv") <> semi) <> line <>+ "end" <> semi+ )++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 <>+ "begin" <> line <>+ indent 2 ("return" <+> "std_logic_vector" <> parens ("u") <> semi) <> line <>+ "end" <> semi <> line <>+ "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> "unsigned" <+> "is" <> line <>+ "begin" <> line <>+ indent 2 ("return" <+> "unsigned" <> parens ("slv") <> semi) <> line <>+ "end" <> semi++ )++funDec _ t@(Product _ labels elTys) = Just+ ( "function" <+> "toSLV" <+> parens ("p :" <+> sizedQualTyName t) <+> "return std_logic_vector" <> semi <> line <>+ "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> sizedQualTyName t <> semi+ , "function" <+> "toSLV" <+> parens ("p :" <+> sizedQualTyName t) <+> "return std_logic_vector" <+> "is" <> line <>+ "begin" <> line <>+ indent 2 ("return" <+> parens (hcat (punctuate " & " elTyToSLV)) <> semi) <> line <>+ "end" <> semi <> line <>+ "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> sizedQualTyName t <+> "is" <> line <>+ "alias islv : std_logic_vector(0 to slv'length - 1) is slv;" <> line <>+ "begin" <> line <>+ indent 2 ("return" <+> parens (hcat (punctuate "," elTyFromSLV)) <> semi) <> line <>+ "end" <> semi+ )+ where+ elTyToSLV = forM [0..(length elTys - 1)]+ (\i -> "toSLV" <>+ parens ("p." <> tyName t <> selectProductField labels elTys i))++ argLengths = map typeSize elTys+ starts = 0 : snd (mapAccumL ((join (,) .) . (+)) 0 argLengths)+ ends = map (subtract 1) (tail starts)++ elTyFromSLV = forM (zip starts ends)+ (\(s,e) -> "fromSLV" <>+ parens ("islv" <> parens (int s <+> "to" <+> int e)))++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 <>+ indent 2+ ( "alias ivalue :" <+> qualTyName t <> "(1 to value'length) is value;" <> line <>+ "variable result :" <+> "std_logic_vector" <> parens ("1 to value'length * " <> int (typeSize elTy)) <> semi+ ) <> line <>+ "begin" <> line <>+ indent 2+ ("for i in ivalue'range loop" <> line <>+ indent 2+ ( "result" <> parens (parens ("(i - 1) * " <> int (typeSize elTy)) <+> "+ 1" <+>+ "to i*" <> int (typeSize elTy)) <+>+ ":=" <+> (case syn of+ Vivado -> "ivalue" <> parens ("i")+ _ -> "toSLV" <> parens ("ivalue" <> parens ("i"))) <> semi+ ) <> line <>+ "end" <+> "loop" <> semi <> line <>+ "return" <+> "result" <> semi+ ) <> line <>+ "end" <> semi <> line <>+ "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> qualTyName t <+> "is" <> line <>+ indent 2+ ( "alias islv :" <+> "std_logic_vector" <> "(0 to slv'length - 1) is slv;" <> line <>+ "variable result :" <+> qualTyName t <> parens ("0 to slv'length / " <> eSz <+> "- 1") <> semi+ ) <> line <>+ "begin" <> line <>+ indent 2+ ("for i in result'range loop" <> line <>+ indent 2+ ( "result" <> parens "i" <+> ":=" <+> case syn of+ Vivado -> getElem <> semi+ _ | BitVector _ <- elTy -> getElem <> semi+ | otherwise -> "fromSLV" <> parens getElem <> semi++ ) <> line <>+ "end" <+> "loop" <> semi <> line <>+ "return" <+> "result" <> semi+ ) <> line <>+ "end" <> semi+ )+ where+ eSz = int (typeSize elTy)+ getElem = "islv" <> parens ("i * " <> eSz <+> "to (i+1) * " <> eSz <+> "- 1")++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 <>+ "begin" <> line <>+ indent 2 ("return" <+> "slv" <> semi) <> line <>+ "end" <> semi <> line <>+ "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> "std_logic_vector" <+> "is" <> line <>+ "begin" <> line <>+ indent 2 ("return" <+> "slv" <> semi) <> line <>+ "end" <> semi+ )++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 <>+ indent 2+ ( "alias ivalue :" <+> qualTyName t <> "(1 to value'length) is value;" <> line <>+ "variable result :" <+> "std_logic_vector" <> parens ("1 to value'length * " <> int (typeSize elTy)) <> semi+ ) <> line <>+ "begin" <> line <>+ indent 2+ ("for i in ivalue'range loop" <> line <>+ indent 2+ ( "result" <> parens (parens ("(i - 1) * " <> int (typeSize elTy)) <+> "+ 1" <+>+ "to i*" <> int (typeSize elTy)) <+>+ ":=" <+> (case syn of+ Vivado -> "ivalue" <> parens ("i")+ _ -> "toSLV" <> parens ("ivalue" <> parens ("i"))) <> semi+ ) <> line <>+ "end" <+> "loop" <> semi <> line <>+ "return" <+> "result" <> semi+ ) <> line <>+ "end" <> semi <> line <>+ "function" <+> "fromSLV" <+> parens ("slv" <+> colon <+> "in" <+> "std_logic_vector") <+> "return" <+> qualTyName t <+> "is" <> line <>+ indent 2+ ( "alias islv :" <+> "std_logic_vector" <> "(0 to slv'length - 1) is slv;" <> line <>+ "variable result :" <+> qualTyName t <> parens ("0 to slv'length / " <> eSz <+> "- 1") <> semi+ ) <> line <>+ "begin" <> line <>+ indent 2+ ("for i in result'range loop" <> line <>+ indent 2+ ( "result" <> parens "i" <+> ":=" <+> case syn of+ Vivado -> getElem <> semi+ _ | BitVector _ <- elTy -> getElem <> semi+ | otherwise -> "fromSLV" <> parens getElem <> semi++ ) <> line <>+ "end" <+> "loop" <> semi <> line <>+ "return" <+> "result" <> semi+ ) <> line <>+ "end" <> semi+ )+ where+ eSz = int (typeSize elTy)+ getElem = "islv" <> parens ("i * " <> eSz <+> "to (i+1) * " <> eSz <+> "- 1")++funDec _ _ = Nothing++tyImports :: Identifier -> VHDLM Doc+tyImports nm = do+ mkId <- Mon (mkIdentifier <*> pure Basic)+ libs <- Mon $ use libraries+ packs <- Mon $ use packages+ punctuate' semi $ sequence+ ([ "library IEEE"+ , "use IEEE.STD_LOGIC_1164.ALL"+ , "use IEEE.NUMERIC_STD.ALL"+ , "use IEEE.MATH_REAL.ALL"+ , "use std.textio.all"+ , "use work.all"+ , "use work." <> pretty (mkId (nm `TextS.append` "_types")) <> ".all"+ ] ++ (map (("library" <+>) . pretty) (nub libs))+ ++ (map (("use" <+>) . pretty) (nub packs)))+++-- TODO: Way too much happening on a single line+port :: Num t+ => TextS.Text+ -> HWType+ -> VHDLM Doc+ -> Int+ -> VHDLM (Doc, t)+port elName hwType portDirection fillToN =+ (,fromIntegral $ TextS.length elName) <$> (encodingNote hwType <> fill fillToN (pretty elName) <+> colon <+> direction <+> sizedQualTyName hwType)+ where+ direction | isBiSignalIn hwType = "inout"+ | otherwise = portDirection+++-- [Note] Hack entity attributes in architecture+--+-- By default we print attributes inside the entity block. This conforms+-- to the VHDL standard (IEEE Std 1076-1993, 5.1 Attribute specification,+-- paragraph 9), and is subsequently implemented in this way by open-source+-- simulators such as GHDL.+---+-- Intel and Xilinx use their own annotation schemes unfortunately, which+-- require attributes in the architecture.+--+-- References:+-- * https://www.mail-archive.com/ghdl-discuss@gna.org/msg03175.html+-- * https://forums.xilinx.com/t5/Simulation-and-Verification/wrong-attribute-decorations-of-port-signals-generated-by-write/m-p/704905#M16265+-- * http://quartushelp.altera.com/15.0/mergedProjects/hdl/vhdl/vhdl_file_dir_chip.htm++entity :: Component -> VHDLM Doc+entity c = do+ syn <- Mon hdlSyn+ rec (p,ls) <- fmap unzip (ports (maximum ls))+ "entity" <+> pretty (componentName c) <+> "is" <> line <>+ (case p of+ [] -> emptyDoc+ _ -> case syn of+ -- See: [Note] Hack entity attributes in architecture+ Other -> indent 2 (rports p <> if null attrs then emptyDoc else+ line <> line <> rattrs) <> line <> "end" <> semi+ _ -> indent 2 (rports p) <> "end" <> semi+ )+ where+ ports l = sequence $ [port iName hwType "in" l | (iName, hwType) <- inputs c]+ ++ [port oName hwType "out" l | (_, (oName, hwType)) <- outputs c]++ rports p = "port" <> (parens (align (vcat (punctuate semi (pure p))))) <> semi++ rattrs = renderAttrs attrs+ attrs = inputAttrs ++ outputAttrs+ inputAttrs = [(id_, attr) | (id_, hwtype) <- inputs c, attr <- hwTypeAttrs hwtype]+ outputAttrs = [(id_, attr) | (_wireOrReg, (id_, hwtype)) <- outputs c, attr <- hwTypeAttrs hwtype]+++architecture :: Component -> VHDLM Doc+architecture c = do {+ ; syn <- Mon hdlSyn+ ; let attrs = case syn of+ -- See: [Note] Hack entity attributes in architecture+ Other -> declAttrs+ _ -> inputAttrs ++ outputAttrs ++ declAttrs+ ; nest 2+ (("architecture structural of" <+> pretty (componentName c) <+> "is" <> line <>+ decls (declarations c)) <> line <>+ if null attrs then emptyDoc else line <> line <> renderAttrs attrs) <> line <>+ nest 2+ ("begin" <> line <>+ insts (declarations c)) <> line <>+ "end" <> semi+ }+ where+ netdecls = filter isNetDecl (declarations c)+ declAttrs = [(id_, attr) | NetDecl' _ _ id_ (Right hwtype) <- netdecls, attr <- hwTypeAttrs hwtype]+ inputAttrs = [(id_, attr) | (id_, hwtype) <- inputs c, attr <- hwTypeAttrs hwtype]+ outputAttrs = [(id_, attr) | (_wireOrReg, (id_, hwtype)) <- outputs c, attr <- hwTypeAttrs hwtype]++ isNetDecl :: Declaration -> Bool+ isNetDecl (NetDecl' _ _ _ (Right _)) = True+ isNetDecl _ = False++attrType+ :: t ~ HashMap T.Text T.Text+ => t+ -> Attr'+ -> t+attrType types attr =+ case HashMap.lookup name' types of+ Nothing -> HashMap.insert name' type' types+ Just type'' | type'' == type' -> types+ | otherwise -> error $+ $(curLoc) ++ unwords [ T.unpack name', "already assigned"+ , T.unpack type'', "while we tried to"+ , "add", T.unpack type' ]+ where+ name' = T.pack $ attrName attr+ type' = T.pack $ case attr of+ BoolAttr' _ _ -> "boolean"+ IntegerAttr' _ _ -> "integer"+ StringAttr' _ _ -> "string"+ Attr' _ -> "bool"++-- | Create 'attrname -> type' mapping for given attributes. Will err if multiple+-- types are assigned to the same name.+attrTypes :: [Attr'] -> HashMap T.Text T.Text+attrTypes = foldl attrType HashMap.empty++-- | Create a 'attrname -> (type, [(signalname, value)]). Will err if multiple+-- types are assigned to the same name.+attrMap+ :: forall t+ . t ~ HashMap T.Text (T.Text, [(TextS.Text, T.Text)])+ => [(TextS.Text, Attr')]+ -> t+attrMap attrs = foldl go empty' attrs+ where+ empty' = HashMap.fromList+ [(k, (types HashMap.! k, [])) | k <- HashMap.keys types]+ types = attrTypes (map snd attrs)++ go :: t -> (TextS.Text, Attr') -> t+ go map' attr = HashMap.adjust+ (go' attr)+ (T.pack $ attrName $ snd attr)+ map'++ go'+ :: (TextS.Text, Attr')+ -> (T.Text, [(TextS.Text, T.Text)])+ -> (T.Text, [(TextS.Text, T.Text)])+ go' (signalName, attr) (typ, elems) =+ (typ, (signalName, renderAttr attr) : elems)++renderAttrs+ :: [(TextS.Text, Attr')]+ -> VHDLM Doc+renderAttrs (attrMap -> attrs) =+ vcat $ sequence $ intersperse " " $ map renderAttrGroup (assocs attrs)+ where+ renderAttrGroup+ :: (T.Text, (T.Text, [(TextS.Text, T.Text)]))+ -> VHDLM Doc+ renderAttrGroup (attrname, (typ, elems)) =+ ("attribute" <+> string attrname <+> colon <+> string typ <> semi)+ <> line <>+ (vcat $ sequence $ map (renderAttrDecl attrname) elems)++ renderAttrDecl+ :: T.Text+ -> (TextS.Text, T.Text)+ -> VHDLM Doc+ renderAttrDecl attrname (signalName, value) =+ "attribute"+ <+> string attrname+ <+> "of"+ <+> stringS signalName+ <+> colon+ <+> "signal is"+ <+> string value+ <> semi++-- | Return all key/value pairs in the map in arbitrary key order.+assocs :: Eq a => Hashable a => HashMap a b -> [(a,b)]+assocs m = zip keys (map (m HashMap.!) keys)+ where+ keys = (HashMap.keys m)++-- | Convert single attribute to VHDL syntax+renderAttr :: Attr' -> T.Text+renderAttr (StringAttr' _key value) = T.pack $ show value+renderAttr (IntegerAttr' _key value) = T.pack $ show value+renderAttr (BoolAttr' _key True ) = T.pack $ "true"+renderAttr (BoolAttr' _key False) = T.pack $ "false"+renderAttr (Attr' _key ) = T.pack $ "true"++sigDecl :: VHDLM Doc -> HWType -> VHDLM Doc+sigDecl d t = d <+> colon <+> sizedQualTyName t++-- | Append size information to given type string+appendSize :: VHDLM Doc -> HWType -> VHDLM Doc+appendSize baseType sizedType = case sizedType of+ BitVector n -> baseType <> parens (int (n-1) <+> "downto 0")+ Signed n -> baseType <> parens (int (n-1) <+> "downto 0")+ 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))+ _ -> baseType++-- | Same as @qualTyName@, but instantiate generic types with their size.+sizedQualTyName :: HWType -> VHDLM Doc+sizedQualTyName (filterTransparent -> hwty) = appendSize (qualTyName hwty) hwty++-- | Same as @tyName@, but instantiate generic types with their size.+sizedTyName :: HWType -> VHDLM Doc+sizedTyName (filterTransparent -> hwty) = appendSize (tyName hwty) hwty++-- | Same as @tyName@, but return fully qualified name (name, including module)+qualTyName :: HWType -> VHDLM Doc+qualTyName (filterTransparent -> hwty) = case hwty of+ -- Builtin types:+ Bit -> tyName hwty+ Bool -> tyName hwty+ Signed _ -> tyName hwty+ Unsigned _ -> tyName hwty+ BitVector _ -> tyName hwty++ -- Transparent types:+ BiDirectional _ elTy -> qualTyName elTy+ Annotated _ elTy -> qualTyName elTy++ -- Custom types:+ _ -> do+ modName <- Mon (use modNm)+ pretty (TextS.toLower modName) <> "_types." <> tyName hwty++-- | Generates a unique name for a given type. This action will cache its+-- results, thus returning the same answer for the same @HWType@ argument.+-- Some type names do not have specific names, but are instead basic types+-- in VHDL.+tyName+ :: HWType+ -- ^ Type to name+ -> VHDLM Doc+tyName t = do+ nm <- tyName' False t+ pretty nm++-- | Generates a unique name for a given type. This action will cache its+-- results, thus returning the same answer for the same @HWType@ argument.+-- Some type names do not have specific names, but are instead basic types+-- in VHDL.+tyName'+ :: Bool+ -- ^ Include length information in first part of name. For example, say we+ -- want to generate a name for a vector<signed>, where the vector is of length+ -- 5, and signed has 64 bits. When given `True`, this function would+ -- generate `array_of_5_signed_64`. When given `False` it would generate+ -- `array_of_signed_64`. Note that parts other than the first part will always+ -- have length information. This option is useful for generating names in+ -- VHDL, where the `False` case is needed to create generic types.+ -> HWType+ -- ^ Type to name+ -> VHDLM TextS.Text+tyName' rec0 (filterTransparent -> t) = do+ Mon (tyCache %= HashSet.insert t)+ case t of+ KnownDomain {} ->+ return (error ($(curLoc) ++ "Forced to print KnownDomain tyName"))+ Void _ ->+ return (error ($(curLoc) ++ "Forced to print Void tyName"))+ Bool -> return "boolean"+ Signed n ->+ let app = if rec0 then ["_", showt n] else [] in+ return $ TextS.concat $ "signed" : app+ Unsigned n ->+ let app = if rec0 then ["_", showt n] else [] in+ return $ TextS.concat $ "unsigned" : app+ BitVector n ->+ let app = if rec0 then ["_", showt n] else [] in+ return $ TextS.concat $ "std_logic_vector" : app+ String -> return "string"+ Integer -> return "integer"+ Bit -> return "std_logic"+ Vector n elTy -> do+ elTy' <- tyName' True elTy+ let nm = TextS.concat [ "array_of_"+ , if rec0 then showt n `TextS.append` "_" else ""+ , elTy']+ Mon $ 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)+ -- 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)+ Reset nm0 ->+ let nm1 = "rst_" `TextS.append` nm0 in+ Mon $ makeCached (t, False) nameCache (userTyName "rst" nm1 t)+ Sum nm _ ->+ Mon $ makeCached (t, False) nameCache (userTyName "sum" nm t)+ CustomSum nm _ _ _ ->+ Mon $ makeCached (t, False) nameCache (userTyName "sum" nm t)+ SP nm _ ->+ Mon $ makeCached (t, False) nameCache (userTyName "sp" nm t)+ CustomSP nm _ _ _ ->+ Mon $ makeCached (t, False) nameCache (userTyName "sp" nm t)+ Product nm _ _ ->+ Mon $ makeCached (t, False) nameCache (userTyName "product" nm t)+ Annotated _ hwTy ->+ tyName' rec0 hwTy+ BiDirectional _ hwTy ->+ tyName' rec0 hwTy++-- | 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+ Void {} -> hwty+ KnownDomain {} -> hwty++ -- Base types:+ Bool -> hwty+ Signed _ -> hwty+ Unsigned _ -> hwty+ BitVector _ -> hwty+ String -> hwty+ Integer -> hwty+ Bit -> hwty++ -- Complex types, for which a user defined type is made in VHDL:+ Vector _ _ -> hwty+ RTree _ _ -> hwty+ Product _ _ _ -> hwty++ -- Simple types, for which a subtype (without qualifiers) will be made in VHDL:+ Clock _ -> Bit+ Reset _ -> Bit+ Index _ -> Unsigned (typeSize hwty)+ CustomSP _ _ _ _ -> BitVector (typeSize hwty)+ SP _ _ -> BitVector (typeSize hwty)+ Sum _ _ -> BitVector (typeSize hwty)+ CustomSum _ _ _ _ -> BitVector (typeSize hwty)++ -- Transparent types:+ Annotated _ elTy -> normaliseType elTy+ BiDirectional _ elTy -> normaliseType elTy++-- | Recursively remove transparent types from given type+filterTransparent :: HWType -> HWType+filterTransparent hwty = case hwty of+ Bool -> hwty+ Signed _ -> hwty+ Unsigned _ -> hwty+ BitVector _ -> hwty+ String -> hwty+ Integer -> hwty+ Bit -> hwty+ Clock _ -> hwty+ Reset _ -> hwty+ Index _ -> hwty+ Sum _ _ -> hwty+ CustomSum _ _ _ _ -> hwty++ Vector n elTy -> Vector n (filterTransparent elTy)+ RTree n elTy -> RTree n (filterTransparent elTy)+ Product nm labels elTys ->+ Product nm labels (map filterTransparent elTys)++ SP nm0 constrs ->+ SP nm0+ (map (\(nm1, tys) -> (nm1, map filterTransparent tys)) constrs)++ CustomSP nm0 drepr size constrs ->+ CustomSP nm0 drepr size+ (map (\(repr, nm1, tys) -> (repr, nm1, map filterTransparent tys)) constrs)++ -- Transparent types:+ Annotated _ elTy -> elTy+ BiDirectional _ elTy -> elTy++ Void {} -> hwty+ KnownDomain {} -> hwty++-- | Create a unique type name for user defined types+userTyName+ :: Identifier+ -- ^ Default name+ -> Identifier+ -- ^ Identifier stored in @hwTy@+ -> HWType+ -- ^ Type to give a (unique) name+ -> StateT VHDLState Identity TextS.Text+userTyName dflt nm0 hwTy = do+ tyCache %= HashSet.insert hwTy+ seen <- use tySeen+ mkId <- mkIdentifier <*> pure Basic+ let nm1 = (mkId . last . TextS.splitOn ".") nm0+ nm2 = if TextS.null nm1 then dflt else nm1+ (nm3,count) = case HashMap.lookup nm2 seen of+ Just cnt -> go mkId seen cnt nm2+ Nothing -> (nm2,0)+ tySeen %= HashMap.insert nm3 count+ return nm3+ where+ go mkId seen count nm0' =+ let nm1' = nm0' `TextS.append` TextS.pack ('_':show count) in+ case HashMap.lookup nm1' seen of+ Just _ -> go mkId seen (count+1) nm0'+ Nothing -> (nm1',count+1)+++-- | Convert a Netlist HWType to an error VHDL value for that type+sizedQualTyNameErrValue :: HWType -> VHDLM Doc+sizedQualTyNameErrValue Bool = "true"+sizedQualTyNameErrValue Bit = singularErrValue+sizedQualTyNameErrValue t@(Vector n elTy) = do+ syn <-Mon 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+ 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) <+>+ rarrow <+> singularErrValue))+ _ -> qualTyName t <> "'" <> parens (int 0 <+> "to" <+> int (2^n - 1) <+> rarrow <+> sizedQualTyNameErrValue elTy)+sizedQualTyNameErrValue t@(Product _ _ elTys) =+ qualTyName t <> "'" <> tupled (mapM sizedQualTyNameErrValue elTys)+sizedQualTyNameErrValue (Reset {}) = singularErrValue+sizedQualTyNameErrValue (Clock _) = singularErrValue+sizedQualTyNameErrValue (Void {}) =+ return (error ($(curLoc) ++ "[CLASH BUG] Forced to print Void error value"))+sizedQualTyNameErrValue String = "\"ERROR\""+sizedQualTyNameErrValue t =+ qualTyName t <> "'" <> parens (int 0 <+> "to" <+> int (typeSize t - 1) <+> rarrow <+> singularErrValue)++singularErrValue :: VHDLM Doc+singularErrValue = do+ udf <- Mon (use undefValue)+ case udf of+ Nothing -> "'-'"+ Just Nothing -> "'0'"+ Just (Just x) -> "'" <> int x <> "'"++vhdlRecSel+ :: HWType+ -> Int+ -> VHDLM Doc+vhdlRecSel p@(Product _ labels tys) i =+ tyName p <> selectProductField labels tys i+vhdlRecSel ty i =+ tyName ty <> "_sel" <> int i++decls :: [Declaration] -> VHDLM Doc+decls [] = emptyDoc+decls ds = do+ rec (dsDoc,ls) <- fmap (unzip . catMaybes) $ mapM (decl (maximum ls)) ds+ case dsDoc of+ [] -> emptyDoc+ _ -> punctuate' semi (pure dsDoc)++decl :: Int -> Declaration -> VHDLM (Maybe (Doc,Int))+decl l (NetDecl' noteM _ id_ ty) = Just <$> (,fromIntegral (TextS.length id_)) <$>+ maybe id addNote noteM ("signal" <+> fill l (pretty id_) <+> colon <+> either pretty sizedQualTyName ty)+ where+ addNote n = mappend ("--" <+> pretty n <> line)++decl _ (InstDecl Comp _ nm _ gens pms) = fmap (Just . (,0)) $ do+ { rec (p,ls) <- fmap unzip $ sequence [ (,formalLength i) <$> fill (maximum ls) (expr_ False i) <+> colon <+> portDir dir <+> sizedQualTyName ty | (i,dir,ty,_) <- pms ]+ ; rec (g,lsg) <- fmap unzip $ sequence [ (,formalLength i) <$> fill (maximum lsg) (expr_ False i) <+> colon <+> tyName ty | (i,ty,_) <- gens]+ ; "component" <+> pretty nm <> line <>+ ( if null g then emptyDoc+ else indent 2 ("generic" <> line <> tupledSemi (pure g) <> semi) <> line+ )+ <> indent 2 ("port" <+> tupledSemi (pure p) <> semi) <> line <>+ "end component"+ }+ where+ formalLength (Identifier i _) = fromIntegral (TextS.length i)+ formalLength _ = 0++ portDir In = "in"+ portDir Out = "out"++decl _ _ = return Nothing++stdMatch+ :: Bits a+ => Int+ -> a+ -> a+ -> String+stdMatch 0 _mask _value = []+stdMatch size mask value =+ symbol : stdMatch (size - 1) mask value+ where+ symbol =+ if testBit mask (size - 1) then+ if testBit value (size - 1) then+ '1'+ else+ '0'+ else+ '-'++patLitCustom'+ :: Bits a+ => VHDLM Doc+ -> Int+ -> a+ -> a+ -> VHDLM Doc+patLitCustom' var size mask value =+ let mask' = string $ T.pack $ stdMatch size mask value in+ "std_match" <> parens (dquotes mask' <> comma <+> var)++patLitCustom+ :: VHDLM Doc+ -> HWType+ -> Literal+ -> VHDLM Doc+patLitCustom var (CustomSum _name _dataRepr size reprs) (NumLit (fromIntegral -> i)) =+ patLitCustom' var size mask value+ where+ ((ConstrRepr' _name _n mask value _anns), _id) = reprs !! i++patLitCustom var (CustomSP _name _dataRepr size reprs) (NumLit (fromIntegral -> i)) =+ patLitCustom' var size mask value+ where+ ((ConstrRepr' _name _n mask value _anns), _id, _tys) = reprs !! i++patLitCustom _ x y = error $ $(curLoc) ++ unwords+ [ "You can only pass CustomSP / CustomSum and a NumLit to this function,"+ , "not", show x, "and", show y]++insts :: [Declaration] -> VHDLM Doc+insts [] = emptyDoc+insts (TickDecl id_:ds) = "--" <+> stringS id_ <> line <> insts ds+insts (d:ds) = do+ d' <- inst_ d+ case d' of+ Just doc -> pure doc <> line <> line <> insts ds+ _ -> insts ds++-- | Helper function for inst_, handling CustomSP and CustomSum+inst_' :: TextS.Text -> Expr -> HWType -> [(Maybe Literal, Expr)] -> VHDLM (Maybe Doc)+inst_' id_ scrut scrutTy es = fmap Just $+ (pretty id_ <+> larrow <+> align (vcat (conds esNub) <> semi))+ where+ esMod = map (first (fmap (patMod scrutTy))) es+ esNub = nubBy ((==) `on` fst) esMod+ var = expr_ True scrut++ conds :: [(Maybe Literal,Expr)] -> VHDLM [Doc]+ conds [] = return []+ conds [(_,e)] = expr_ False e <:> return []+ conds ((Nothing,e):_) = expr_ False e <:> return []+ conds ((Just c ,e):es') = expr_ False e <+> "when"+ <+> patLitCustom var scrutTy c+ <+> "else"+ <:> conds es'+++-- | Turn a Netlist Declaration to a VHDL concurrent block+inst_ :: Declaration -> VHDLM (Maybe Doc)+inst_ (Assignment id_ e) = fmap Just $+ pretty id_ <+> larrow <+> align (expr_ False e) <> semi++inst_ (CondAssignment id_ _ scrut _ [(Just (BoolLit b), l),(_,r)]) = fmap Just $+ pretty id_ <+> larrow+ <+> align (vsep (sequence [expr_ False t <+> "when" <+>+ expr_ False scrut <+> "else"+ ,expr_ False f <> semi+ ]))+ where+ (t,f) = if b then (l,r) else (r,l)++inst_ (CondAssignment id_ _ scrut scrutTy@(CustomSP _ _ _ _) es) =+ inst_' id_ scrut scrutTy es++inst_ (CondAssignment id_ _ scrut scrutTy@(CustomSum _ _ _ _) es) =+ inst_' id_ scrut scrutTy es++inst_ (CondAssignment id_ _sig scrut scrutTy es) = fmap Just $+ "with" <+> parens (expr_ True scrut) <+> "select" <> line <>+ indent 2 (pretty id_ <+> larrow <+> align (vcat (punctuate comma (conds esNub)) <> semi))+ where+ esMod = map (first (fmap (patMod scrutTy))) es+ esNub = nubBy ((==) `on` fst) esMod++ conds :: [(Maybe Literal,Expr)] -> VHDLM [Doc]+ conds [] = return []+ conds [(_,e)] = expr_ False e <+> "when" <+> "others" <:> return []+ conds ((Nothing,e):_) = expr_ False e <+> "when" <+> "others" <:> return []+ conds ((Just c ,e):es') = expr_ False e <+> "when" <+> patLit scrutTy c <:> conds es'++inst_ (InstDecl entOrComp libM nm lbl gens pms) = do+ maybe (return ()) (\lib -> Mon (libraries %= (T.fromStrict lib:))) libM+ fmap Just $+ nest 2 $ pretty lbl <+> colon <> entOrComp'+ <+> maybe emptyDoc ((<> ".") . pretty) libM <> pretty nm <> line <> gms <> pms' <> semi+ where+ gms | [] <- gens = emptyDoc+ | otherwise = do+ rec (p,ls) <- fmap unzip $ sequence [ (,formalLength i) <$> fill (maximum ls) (expr_ False i) <+> "=>" <+> expr_ False e | (i,_,e) <- gens]+ nest 2 ("generic map" <> line <> tupled (pure p)) <> line+ pms' = do+ rec (p,ls) <- fmap unzip $ sequence [ (,formalLength i) <$> fill (maximum ls) (expr_ False i) <+> "=>" <+> expr_ False e | (i,_,_,e) <- pms]+ nest 2 $ "port map" <> line <> tupled (pure p)+ formalLength (Identifier i _) = fromIntegral (TextS.length i)+ formalLength _ = 0+ 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)))++inst_ _ = return Nothing++-- | Turn a Netlist expression into a VHDL expression+expr_ :: Bool -- ^ Enclose in parentheses?+ -> Expr -- ^ Expr to convert+ -> VHDLM Doc+expr_ _ (Literal sizeM lit) = exprLit sizeM lit+expr_ _ (Identifier id_ Nothing) = pretty id_+expr_ _ (Identifier id_ (Just (Indexed (CustomSP _id _dataRepr _size args,dcI,fI)))) = do+ nm <- Mon $ use modNm+ let cast = qualTyName resultType <> squote+ let fSLV = stringS (TextS.toLower nm) <> "_types.fromSLV"+ cast <> parens (fSLV <> parens (hcat $ punctuate " & " $ ranges))+ where+ resultType = fieldTypes !! fI+ (ConstrRepr' _name _n _mask _value anns, _, fieldTypes) = args !! dcI++ ranges =+ mapM range $ bitRanges (anns !! fI)++ range (start, end) =+ pretty id_ <> parens (int start <+> "downto" <+> int end)++expr_ b (Identifier id_ (Just (Indexed (ty@(SP _ args),dcI,fI)))) = do+ nm <- Mon $ use modNm+ case b of+ True ->+ (case normaliseType argTy of+ BitVector {} -> id+ _ -> (\x -> pretty (TextS.toLower nm) <> "_types.fromSLV" <> parens x))+ (pretty id_ <> parens (int start <+> "downto" <+> int end))+ _ -> fromSLV argTy id_ start end+ where+ argTys = snd $ args !! dcI+ argTy = argTys !! fI+ argSize = typeSize argTy+ other = otherSize argTys (fI-1)+ start = typeSize ty - 1 - conSize ty - other+ end = start - argSize + 1++expr_ _ (Identifier id_ (Just (Indexed (ty@(Product _ labels tys),_,fI)))) =+ pretty id_ <> dot <> tyName ty <> selectProductField labels tys fI++expr_ _ (Identifier id_ (Just (Indexed ((Vector _ elTy),1,0)))) = do+ syn <- Mon hdlSyn+ case syn of+ Vivado -> do+ id' <- fmap (T.toStrict . renderOneLine) (pretty id_ <> parens (int 0))+ fromSLV elTy id' (typeSize elTy - 1) 0+ _ -> pretty id_ <> parens (int 0)+expr_ _ (Identifier id_ (Just (Indexed ((Vector n _),1,1)))) = pretty id_ <> parens (int 1 <+> "to" <+> int (n-1))++-- This is a "Hack", we cannot construct trees with a negative depth. This is+-- here so that we can recognise merged RTree modifiers. See the code in+-- @Clash.Backend.nestM@ which construct these tree modifiers.+expr_ _ (Identifier id_ (Just (Indexed (RTree (-1) _,l,r)))) =+ pretty id_ <> parens (int l <+> "to" <+> int (r-1))++expr_ _ (Identifier id_ (Just (Indexed ((RTree 0 elTy),0,0)))) = do+ syn <- Mon hdlSyn+ case syn of+ Vivado -> do+ id' <- fmap (T.toStrict . renderOneLine) (pretty id_ <> parens (int 0))+ fromSLV elTy id' (typeSize elTy - 1) 0+ _ -> pretty id_ <> parens (int 0)+expr_ _ (Identifier id_ (Just (Indexed ((RTree n _),1,0)))) =+ let z = 2^(n-1)+ in pretty id_ <> parens (int 0 <+> "to" <+> int (z-1))+expr_ _ (Identifier id_ (Just (Indexed ((RTree n _),1,1)))) =+ let z = 2^(n-1)+ z' = 2^n+ in pretty id_ <> parens (int z <+> "to" <+> int (z'-1))++-- This is a HACK for Clash.Driver.TopWrapper.mkOutput+-- Vector's don't have a 10'th constructor, this is just so that we can+-- recognize the particular case+expr_ _ (Identifier id_ (Just (Indexed ((Vector _ elTy),10,fI)))) = do+ syn <- Mon hdlSyn+ case syn of+ Vivado -> do+ id' <- fmap (T.toStrict . renderOneLine) (pretty id_ <> parens (int fI))+ fromSLV elTy id' (typeSize elTy - 1) 0+ _ -> pretty id_ <> parens (int fI)++-- This is a HACK for Clash.Driver.TopWrapper.mkOutput+-- RTree's don't have a 10'th constructor, this is just so that we can+-- recognize the particular case+expr_ _ (Identifier id_ (Just (Indexed ((RTree _ elTy),10,fI)))) = do+ syn <- Mon hdlSyn+ case syn of+ Vivado -> do+ id' <- fmap (T.toStrict . renderOneLine) (pretty id_ <> parens (int fI))+ fromSLV elTy id' (typeSize elTy - 1) 0+ _ -> pretty id_ <> parens (int fI)++expr_ _ (Identifier id_ (Just (DC (ty@(SP _ _),_)))) = pretty id_ <> parens (int start <+> "downto" <+> int end)+ where+ start = typeSize ty - 1+ end = typeSize ty - conSize ty++-- [Note] integer projection+--+-- The idea behind these expressions is to translate cases like:+--+-- > :: Int8 -> Int#+-- > \case I8# i -> i+--+-- Which is fine, because no bits are lost. However, these expression might+-- also be the result of the W/W transformation (or uses of unsafeToInteger)+-- for:+--+-- > :: Signed 128 -> Integer+-- > \case S i -> i+--+-- which is very bad because `Integer` is represented by 64 bits meaning we+-- we lose the top 64 bits in the above translation.+--+-- Just as bad is that+--+-- > :: Word8 -> Word#+-- > \case W8# w -> w+--+-- > :: Unsigned 8 -> Integer+-- > \case U i -> i+--+-- result in the same expression... even though their resulting types are+-- different. TODO: this needs to be fixed!+expr_ _ (Identifier id_ (Just (Indexed ((Signed w),_,_)))) = do+ iw <- Mon $ use intWidth+ traceIf (iw < w) ($(curLoc) ++ "WARNING: result smaller than argument") $+ "resize" <> parens (pretty id_ <> "," <> int iw)+expr_ _ (Identifier id_ (Just (Indexed ((Unsigned w),_,_)))) = do+ iw <- Mon $ use intWidth+ traceIf (iw < w) ($(curLoc) ++ "WARNING: result smaller than argument") $+ "resize" <> parens (pretty id_ <> "," <> int iw)++-- [Note] mask projection+--+-- This covers the case of either:+--+-- `Clash.Sized.Internal.BitVector.unsafeToMask` or+--+-- > :: BitVector 8 -> Integer+-- > \case BV m wild -> m+--+-- introduced by the W/W transformation. Both of which we prefer not to see+-- but will allow. Since the mask is pretty much a simulation artifact we+-- emit don't cares so stuff gets optimised away.+expr_ _ (Identifier _ (Just (Indexed ((BitVector _),_,0)))) = do+ iw <- Mon $ use intWidth+ traceIf True ($(curLoc) ++ "WARNING: synthesizing bitvector mask to dontcare") $+ sizedQualTyNameErrValue (Signed iw)++-- [Note] bitvector projection+--+-- This covers the case of either:+--+-- `Clash.Sized.Internal.BitVector.unsafeToInteger` or+--+-- > :: BitVector 8 -> Integer+-- > \case BV wild i -> i+--+-- introduced by the+expr_ _ (Identifier id_ (Just (Indexed ((BitVector w),_,1)))) = do+ iw <- Mon $ use intWidth+ traceIf (iw < w) ($(curLoc) ++ "WARNING: result smaller than argument") $+ "signed" <> parens ("std_logic_vector" <> parens ("resize" <>+ parens ("unsigned" <> parens (pretty id_) <> "," <> int iw)))++expr_ _ (Identifier id_ (Just (Sliced (BitVector _,start,end)))) =+ pretty id_ <> parens (int start <+> "downto" <+> int end)++expr_ b (Identifier id_ (Just (Nested (Indexed ((Vector n elTy),1,1)) m0))) = go 1 m0+ where+ go s (Nested (Indexed ((Vector {}),1,1)) m1) = go (s+1) m1+ go s (Indexed (Vector {},1,1)) = pretty id_ <> parens (int (s+1) <+> "to" <+> int (n-1))+ go s (Indexed (Vector {},1,0)) = do+ syn <- Mon hdlSyn+ case syn of+ Vivado -> do+ id' <- fmap (T.toStrict . renderOneLine) (pretty id_ <> parens (int s))+ fromSLV elTy id' (typeSize elTy - 1) 0+ _ -> pretty id_ <> parens (int s)+ -- This is a HACK for Clash.Driver.TopWrapper.mkOutput+-- Vector's don't have a 10'th constructor, this is just so that we can+-- recognize the particular case+ go s (Indexed (Vector {},10,fI)) = do+ syn <- Mon hdlSyn+ case syn of+ Vivado -> do+ id' <- fmap (T.toStrict . renderOneLine) (pretty id_ <> parens (int (s+fI)))+ fromSLV elTy id' (typeSize elTy - 1) 0+ _ -> pretty id_ <> parens (int (s+fI))+ go s m1 = do+ k <- pretty id_ <> parens (int s <+> "to" <+> int (n-1))+ expr b (Identifier (T.toStrict $ renderOneLine k) (Just m1))++expr_ b (Identifier id_ (Just (Nested m1 m2))) = case nestM m1 m2 of+ Just m3 -> expr_ b (Identifier id_ (Just m3))+ _ -> do+ k <- expr_ True (Identifier id_ (Just m1))+ expr_ b (Identifier (T.toStrict $ renderOneLine k) (Just m2))++expr_ _ (Identifier id_ (Just _)) = pretty id_++expr_ b (DataCon _ (DC (Void {}, -1)) [e]) = expr_ b e++expr_ _ (DataCon ty@(Vector 0 _) _ _) = sizedQualTyNameErrValue ty++expr_ _ (DataCon ty@(Vector 1 elTy) _ [e]) = do+ syn <- Mon 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+ case syn of+ 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)+ _ -> qualTyName ty <> "'" <> case vectorChain e of+ Just es -> align (tupled (mapM (expr_ False) es))+ Nothing -> parens (qualTyName elTy <> "'" <> parens (expr_ False e1) <+> "&" <+> expr_ False e2)++expr_ _ (DataCon ty@(RTree 0 elTy) _ [e]) = do+ syn <- Mon 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@(RTree d elTy) _ [e1,e2]) = qualTyName ty <> "'" <> case rtreeChain e of+ Just es -> tupled (mapM (expr_ False) es)+ Nothing -> parens (qualTyName (RTree (d-1) elTy) <> "'" <> parens (expr_ False e1) <+>+ "&" <+> expr_ False e2)++expr_ _ (DataCon (SP {}) (DC (BitVector _,_)) es) = assignExpr+ where+ argExprs = map (parens . expr_ False) es+ assignExpr = "std_logic_vector'" <> parens (hcat $ punctuate " & " $ sequence argExprs)++expr_ _ (DataCon ty@(SP _ args) (DC (_,i)) es) = assignExpr+ where+ argTys = snd $ args !! i+ dcSize = conSize ty + sum (map typeSize argTys)+ dcExpr = expr_ False (dcToExpr ty i)+ argExprs = map parens (zipWith toSLV argTys es)+ extraArg = case typeSize ty - dcSize of+ 0 -> []+ 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@(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)))+expr_ _ (DataCon (CustomSP _ dataRepr size args) (DC (_,i)) es) =+ "std_logic_vector'" <> parens (hcat $ punctuate " & " $ mapM range origins)+ where+ (cRepr, _, argTys) = args !! i++ -- Build bit representations for all constructor arguments+ argExprs = zipWith toSLV argTys es :: [VHDLM Doc]++ -- Spread bits of constructor arguments using masks+ origins = bitOrigins dataRepr cRepr :: [BitOrigin]++ range+ :: BitOrigin+ -> VHDLM Doc+ range (Lit (bitsToBits -> ns)) =+ dquotes $ hcat $ mapM bit_char ns+ range (Field n start end) =+ -- We want to select the bits starting from 'start' downto and including+ -- 'end'. We cannot use "(start downto end)" in VHDL, as the preceeding+ -- expression might be anything. This notation only works on identifiers+ -- unfortunately.+ let fsize = start - end + 1 in+ let expr' = argExprs !! n in++ -- HACK: While expr' is a std_logic_vector (see call `toSLV`), it cannot+ -- be cast to unsigned in case of literals. This is fixed by explicitly+ -- casting it to std_logic_vector.+ let unsigned = "unsigned" <> parens ("std_logic_vector'" <> parens expr') in++ if | fsize == size ->+ -- If sizes are equal, rotating / resizing amounts to doing nothing+ expr'+ | end == 0 ->+ -- Rotating is not necessary if relevant bits are already at the end+ let resized = "resize" <> parens (unsigned <> comma <> int fsize) in+ "std_logic_vector" <> parens resized+ | otherwise ->+ -- Select bits 'start' downto and including 'end'+ let rotated = unsigned <+> "srl" <+> int end in+ let resized = "resize" <> parens (rotated <> comma <> int fsize) in+ "std_logic_vector" <> parens resized++expr_ _ (DataCon ty@(Product _ labels tys) _ es) =+ tupled $ zipWithM (\i e' -> tyName ty <> selectProductField labels tys i <+> rarrow <+> expr_ False e') [0..] es++expr_ _ (BlackBoxE pNm _ _ _ _ bbCtx _)+ | pNm == "Clash.Sized.Internal.Signed.fromInteger#"+ , [Literal _ (NumLit n), Literal _ i] <- extractLiterals bbCtx+ = exprLit (Just (Signed (fromInteger n),fromInteger n)) i++expr_ _ (BlackBoxE pNm _ _ _ _ bbCtx _)+ | pNm == "Clash.Sized.Internal.Unsigned.fromInteger#"+ , [Literal _ (NumLit n), Literal _ i] <- extractLiterals bbCtx+ = exprLit (Just (Unsigned (fromInteger n),fromInteger n)) i++expr_ _ (BlackBoxE pNm _ _ _ _ bbCtx _)+ | pNm == "Clash.Sized.Internal.BitVector.fromInteger#"+ , [Literal _ (NumLit n), Literal _ m, Literal _ i] <- extractLiterals bbCtx+ = let NumLit m' = m+ NumLit i' = i+ in exprLit (Just (BitVector (fromInteger n),fromInteger n)) (BitVecLit m' i')++expr_ _ (BlackBoxE pNm _ _ _ _ bbCtx _)+ | pNm == "Clash.Sized.Internal.BitVector.fromInteger##"+ , [Literal _ m, Literal _ i] <- extractLiterals bbCtx+ = let NumLit m' = m+ NumLit i' = i+ in exprLit (Just (Bit,1)) (BitLit $ toBit m' i')++expr_ _ (BlackBoxE pNm _ _ _ _ bbCtx _)+ | pNm == "Clash.Sized.Internal.Index.fromInteger#"+ , [Literal _ (NumLit n), Literal _ i] <- extractLiterals bbCtx+ , Just k <- clogBase 2 n+ , let k' = max 1 k+ = exprLit (Just (Unsigned k',k')) i++expr_ _ (BlackBoxE pNm _ _ _ _ bbCtx _)+ | pNm == "Clash.Sized.Internal.Index.maxBound#"+ , [Literal _ (NumLit n)] <- extractLiterals bbCtx+ , n > 0+ , Just k <- clogBase 2 n+ , 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))++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 (Sum _ _) (Right id_)) = do+ iw <- Mon $ use intWidth+ "signed" <> parens ("std_logic_vector" <> parens ("resize" <> parens ("unsigned" <> parens (pretty id_) <> "," <> int iw)))++expr_ _ (DataTag (Product {}) (Right _)) = do+ iw <- Mon $ use intWidth+ "to_signed" <> parens (int 0 <> "," <> int iw)+expr_ _ (DataTag hty@(SP _ _) (Right id_)) = do {+ ; iw <- Mon $ use intWidth+ ; "signed" <> parens ("std_logic_vector" <> parens (+ "resize" <> parens ("unsigned" <> parens (pretty id_ <> parens (int start <+> "downto" <+> int end))+ <> "," <> int iw)))+ }+ where+ start = typeSize hty - 1+ end = typeSize hty - conSize hty++expr_ _ (DataTag (Vector 0 _) (Right _)) = do+ iw <- Mon $ use intWidth+ "to_signed" <> parens (int 0 <> "," <> int iw)+expr_ _ (DataTag (Vector _ _) (Right _)) = do+ iw <- Mon $ use intWidth+ "to_signed" <> parens (int 1 <> "," <> int iw)++expr_ _ (DataTag (RTree 0 _) (Right _)) = do+ iw <- Mon $ use intWidth+ "to_signed" <> parens (int 0 <> "," <> int iw)+expr_ _ (DataTag (RTree _ _) (Right _)) = do+ iw <- Mon $ use intWidth+ "to_signed" <> parens (int 1 <> "," <> int iw)++expr_ _ (ConvBV topM hwty True e) = do+ nm <- Mon $ 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_ _ (ConvBV topM _ False 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_ _ e = error $ $(curLoc) ++ (show e) -- empty++otherSize :: [HWType] -> Int -> Int+otherSize _ n | n < 0 = 0+otherSize [] _ = 0+otherSize (a:as) n = typeSize a + otherSize as (n-1)++vectorChain :: Expr -> Maybe [Expr]+vectorChain (DataCon (Vector 0 _) _ _) = Just []+vectorChain (DataCon (Vector 1 _) _ [e]) = Just [e]+vectorChain (DataCon (Vector _ _) _ [e1,e2]) = Just e1 <:> vectorChain e2+vectorChain _ = Nothing++rtreeChain :: Expr -> Maybe [Expr]+rtreeChain (DataCon (RTree 1 _) _ [e]) = Just [e]+rtreeChain (DataCon (RTree _ _) _ [e1,e2]) = liftA2 (++) (rtreeChain e1) (rtreeChain e2)+rtreeChain _ = Nothing++exprLit :: Maybe (HWType,Size) -> Literal -> VHDLM Doc+exprLit Nothing (NumLit i) = integer i++exprLit (Just (hty,sz)) (NumLit i) = case hty of+ Unsigned n+ | i < (-2^(31 :: Integer)) -> "unsigned" <> parens ("std_logic_vector" <> parens ("signed'" <> parens lit))+ | i < 0 -> "unsigned" <> parens ("std_logic_vector" <> parens ("to_signed" <> parens(integer i <> "," <> int n)))+ | i < 2^(31 :: Integer) -> "to_unsigned" <> parens (integer i <> "," <> int n)+ | otherwise -> "unsigned'" <> parens lit+ Signed n+ | i < 2^(31 :: Integer) && i > (-2^(31 :: Integer)) -> "to_signed" <> parens (integer i <> "," <> int n)+ | otherwise -> "signed'" <> parens lit+ BitVector _ -> "std_logic_vector'" <> parens lit+ Bit -> squotes (int (fromInteger i `mod` 2))+ _ -> blit++ where+ validHexLit = sz `mod` 4 == 0 && sz /= 0+ lit = if validHexLit then hlit else blit+ blit = bits (toBits sz i)+ i' = case hty of+ Signed _ -> let mask = 2^(sz-1) in case divMod i mask of+ (s,i'') | even s -> i''+ | otherwise -> i'' - mask+ _ -> i `mod` 2^sz+ hlit = (if i' < 0 then "-" else emptyDoc) <> hex (toHex sz i')++exprLit (Just (hty,sz)) (BitVecLit m i) = case m of+ 0 -> exprLit (Just (hty,sz)) (NumLit i)+ _ -> "std_logic_vector'" <> parens bvlit+ where+ bvlit = bits (toBits' sz m i)+++exprLit _ (BoolLit t) = if t then "true" else "false"+exprLit _ (BitLit b) = squotes $ bit_char b+exprLit _ (StringLit s) = pretty . T.pack $ show s+exprLit _ l = error $ $(curLoc) ++ "exprLit: " ++ show l++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 _ l = exprLit Nothing l++patMod :: HWType -> Literal -> Literal+patMod hwTy (NumLit i) = NumLit (i `mod` (2 ^ typeSize hwTy))+patMod _ l = l++toBits :: Integral a => Int -> a -> [Bit]+toBits size val = map (\x -> if odd x then H else L)+ $ reverse+ $ take size+ $ map (`mod` 2)+ $ iterate (`div` 2) val++toBits' :: Integral a => Int -> a -> a -> [Bit]+toBits' size msk val = map (\(m,i) -> if odd m then U else (if odd i then H else L))+ $+ ( reverse . take size)+ $ zip+ ( map (`mod` 2) $ iterate (`div` 2) msk)+ ( map (`mod` 2) $ iterate (`div` 2) val)++bits :: [Bit] -> VHDLM Doc+bits = dquotes . hcat . mapM bit_char++toHex :: Int -> Integer -> String+toHex sz i =+ let Just d = clogBase 16 (2^sz)+ in printf ("%0" ++ show d ++ "X") (abs i)++hex :: String -> VHDLM Doc+hex s = char 'x' <> dquotes (pretty (T.pack s))++bit_char :: Bit -> VHDLM Doc+bit_char H = char '1'+bit_char L = char '0'+bit_char U = do+ udf <- Mon (use undefValue)+ case udf of+ Nothing -> char '-'+ Just Nothing -> char '0'+ Just (Just i) -> "'" <> int i <> "'"+bit_char Z = char 'Z'++toSLV :: HWType -> Expr -> VHDLM Doc+toSLV Bool e = do+ nm <- Mon $ use modNm+ pretty (TextS.toLower nm) <> "_types.toSLV" <> parens (expr_ False e)+toSLV Bit e = do+ nm <- Mon $ use modNm+ pretty (TextS.toLower nm) <> "_types.toSLV" <> parens (expr_ False e)+toSLV (Clock {}) e = do+ nm <- Mon $ use modNm+ pretty (TextS.toLower nm) <> "_types.toSLV" <> parens (expr_ False e)+toSLV (Reset {}) e = do+ nm <- Mon $ use modNm+ pretty (TextS.toLower 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 (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+ "std_logic_vector" <> parens unsigned+toSLV t@(Product _ labels tys) (Identifier id_ Nothing) = do+ selIds' <- sequence selIds+ encloseSep lparen rparen " & " (zipWithM toSLV tys selIds')+ where+ tName = tyName t+ selNames = map (fmap (T.toStrict . renderOneLine) ) [pretty id_ <> dot <> tName <> selectProductField labels tys i | i <- [0..(length tys)-1]]+ selIds = map (fmap (\n -> Identifier n Nothing)) selNames+toSLV (Product _ _ tys) (DataCon _ _ es) = do+ encloseSep lparen rparen " & " (zipWithM toSLV tys es)+toSLV (Product _ _ _) e = do+ nm <- Mon $ use modNm+ pretty (TextS.toLower nm) <> "_types.toSLV" <> parens (expr_ False e)+toSLV (SP _ _) e = expr_ False e+toSLV (CustomSP _ _ _ _) e = expr_ False e+toSLV (Vector n elTy) (Identifier id_ Nothing) = do+ selIds' <- sequence selIds+ syn <- Mon hdlSyn+ parens (vcat $ punctuate " & "+ (case syn of+ Vivado -> mapM (expr_ False) selIds'+ _ -> mapM (toSLV elTy) selIds'))+ where+ selNames = map (fmap (T.toStrict . renderOneLine) ) $ [pretty id_ <> parens (int i) | i <- [0 .. (n-1)]]+ selIds = map (fmap (`Identifier` Nothing)) selNames+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+ pretty (TextS.toLower nm) <> "_types.toSLV" <> parens (expr_ False e)+toSLV hty e = error $ $(curLoc) ++ "toSLV:\n\nType: " ++ show hty ++ "\n\nExpression: " ++ show e++fromSLV :: HasCallStack => HWType -> Identifier -> Int -> Int -> VHDLM Doc+fromSLV Bool id_ start _ = do+ nm <- Mon $ use modNm+ pretty (TextS.toLower nm) <> "_types.fromSLV" <> parens (pretty id_ <> parens (int start <+> "downto" <+> int start))+fromSLV Bit id_ start _ = pretty id_ <> parens (int start)+fromSLV (BitVector _) id_ start end = pretty id_ <> parens (int start <+> "downto" <+> int end)+fromSLV (Index _) id_ start end = "unsigned" <> parens (pretty id_ <> parens (int start <+> "downto" <+> int end))+fromSLV (Signed _) id_ start end = "signed" <> parens (pretty id_ <> parens (int start <+> "downto" <+> int end))+fromSLV (Unsigned _) id_ start end = "unsigned" <> parens (pretty id_ <> parens (int start <+> "downto" <+> int end))+fromSLV (Sum _ _) id_ start end = pretty id_ <> parens (int start <+> "downto" <+> int end)+fromSLV (CustomSum _ _ _ _) id_ start end = pretty id_ <> parens (int start <+> "downto" <+> int end)+fromSLV t@(Product _ labels tys) id_ start _ = do+ tupled $ zipWithM (\s e -> s <+> rarrow <+> e) selNames args+ where+ tName = tyName t+ selNames = [tName <> selectProductField labels tys i | i <- [0..]]+ argLengths = map typeSize tys+ starts = start : snd (mapAccumL ((join (,) .) . (-)) start argLengths)+ ends = map (+1) (tail starts)+ args = zipWith3 (`fromSLV` id_) tys starts ends++fromSLV (CustomSP _ _ _ _) id_ start end = pretty id_ <> parens (int start <+> "downto" <+> int end)+fromSLV (SP _ _) id_ start end = pretty id_ <> parens (int start <+> "downto" <+> int end)+fromSLV (Vector n elTy) id_ start _ =+ if n > 1 then tupled args+ else parens (int 0 <+> rarrow <+> fmap head args)+ where+ argLength = typeSize elTy+ starts = take (n + 1) $ iterate (subtract argLength) start+ ends = map (+1) (tail starts)+ args = do syn <- Mon hdlSyn+ let elTy' = case syn of+ Vivado -> BitVector (argLength - 1)+ _ -> elTy+ zipWithM (fromSLV elTy' id_) starts ends+fromSLV (Clock {}) id_ start _ = pretty id_ <> parens (int start)+fromSLV (Reset {}) id_ start _ = pretty id_ <> parens (int start)+fromSLV hty _ _ _ = error $ $(curLoc) ++ "fromSLV: " ++ show hty++dcToExpr :: HWType -> Int -> Expr+dcToExpr ty i = Literal (Just (ty,conSize ty)) (NumLit (toInteger i))++larrow :: VHDLM Doc+larrow = "<="++rarrow :: VHDLM Doc+rarrow = "=>"++parenIf :: Monad m => Bool -> Mon m Doc -> Mon m Doc+parenIf True = parens+parenIf False = id++punctuate' :: Monad m => Mon m Doc -> Mon m [Doc] -> Mon m Doc+punctuate' s d = vcat (punctuate s d) <> s++encodingNote :: HWType -> VHDLM Doc+encodingNote (Clock _) = "-- clock" <> line+encodingNote (Reset _ ) = "-- reset" <> line+encodingNote _ = emptyDoc++tupledSemi :: Applicative f => f [Doc] -> f Doc+tupledSemi = align . encloseSep (flatAlt (lparen <+> emptyDoc) lparen)+ (flatAlt (emptyDoc <+> rparen) rparen)+ (semi <+> emptyDoc)
src/Clash/Backend/Verilog.hs view
@@ -1,6 +1,6 @@ {-| Copyright : (C) 2015-2016, University of Twente,- 2017, Google Inc.+ 2017-2018, Google Inc. License : BSD2 (see the file LICENSE) Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com> @@ -9,28 +9,42 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiWayIf #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-} {-# LANGUAGE RecursiveDo #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TupleSections #-} {-# LANGUAGE ViewPatterns #-} -module Clash.Backend.Verilog (VerilogState, include) where+module Clash.Backend.Verilog+ ( VerilogState+ , include+ , uselibs+ , encodingNote+ , exprLit+ , bits+ , bit_char+ )+where -import Control.Applicative ((<*), (*>)) import qualified Control.Applicative as A-import Control.Lens ((+=),(-=),(.=),(%=), makeLenses, use)+import Control.Lens (Lens',(+=),(-=),(.=),(%=), makeLenses, use) import Control.Monad (forM) import Control.Monad.State (State)+import Data.Bits (Bits, testBit)+import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HashMap import qualified Data.HashSet as HashSet import Data.Maybe (catMaybes,fromMaybe,mapMaybe)-import Data.List (nub)+import Data.List (nub, nubBy) #if !MIN_VERSION_base(4,11,0) import Data.Monoid hiding (Product, Sum) #endif import Data.Semigroup.Monad-import Data.Text.Lazy (pack, unpack)+import Data.Text.Lazy (pack) import qualified Data.Text.Lazy as Text+import qualified Data.Text as TextS import Data.Text.Prettyprint.Doc.Extra #ifdef CABAL import qualified Data.Version@@ -38,16 +52,27 @@ import qualified System.FilePath import Clash.Annotations.Primitive (HDL (..))+import Clash.Annotations.BitRepresentation (BitMask)+import Clash.Annotations.BitRepresentation.ClashLib+ (bitsToBits)+import Clash.Annotations.BitRepresentation.Internal+ (ConstrRepr'(..))+import Clash.Annotations.BitRepresentation.Util+ (BitOrigin(Lit, Field), bitOrigins, bitRanges, isContinuousMask)+import Clash.Core.Var (Attr'(..)) import Clash.Backend-import Clash.Driver.Types (SrcSpan, noSrcSpan) import Clash.Netlist.BlackBox.Types (HdlSyn)-import Clash.Netlist.BlackBox.Util (extractLiterals, renderBlackBox)+import Clash.Netlist.BlackBox.Util+ (extractLiterals, renderBlackBox, renderFilePath) import Clash.Netlist.Id (IdType (..), mkBasicId') import Clash.Netlist.Types hiding (_intWidth, intWidth) import Clash.Netlist.Util hiding (mkIdentifier, extendIdentifier)-import Clash.Signal.Internal (ClockKind (..))-import Clash.Util (curLoc, (<:>))+import Clash.Util+ (SrcSpan, noSrcSpan, curLoc, traceIf, (<:>),on,first) +++ #ifdef CABAL import qualified Paths_clash_lib #endif@@ -56,16 +81,27 @@ data VerilogState = VerilogState { _genDepth :: Int -- ^ Depth of current generative block- , _idSeen :: [Identifier]+ , _idSeen :: HashMap Identifier Word , _srcSpan :: SrcSpan , _includes :: [(String,Doc)] , _imports :: [Text.Text]+ , _libraries :: [Text.Text]+ , _dataFiles :: [(String,FilePath)]+ -- ^ Files to be copied: (filename, old path)+ , _memoryDataFiles:: [(String,String)]+ -- ^ Files to be stored: (filename, contents). These files are generated+ -- during the execution of 'genNetlist'. , _intWidth :: Int -- ^ Int/Word/Integer bit-width , _hdlsyn :: HdlSyn+ , _escapedIds :: Bool+ , _undefValue :: Maybe (Maybe Int) } makeLenses ''VerilogState +squote :: Mon (State VerilogState) Doc+squote = string "'"+ primsRoot :: IO FilePath #ifdef CABAL primsRoot = Paths_clash_lib.getDataFileName "prims"@@ -74,7 +110,7 @@ #endif instance Backend VerilogState where- initBackend = VerilogState 0 [] noSrcSpan [] []+ initBackend = VerilogState 0 HashMap.empty noSrcSpan [] [] [] [] [] hdlKind = const Verilog primDirs = const $ do root <- primsRoot return [ root System.FilePath.</> "common"@@ -108,22 +144,31 @@ toBV _ = string fromBV _ = string hdlSyn = use hdlsyn- mkIdentifier = return go+ mkIdentifier = do+ allowEscaped <- use escapedIds+ return (go allowEscaped) where- go Basic nm = filterReserved (mkBasicId' True nm)- go Extended (rmSlash -> nm) = case go Basic nm of- nm' | nm /= nm' -> Text.concat ["\\",nm," "]- |otherwise -> nm'- extendIdentifier = return go+ go _ Basic nm = case (TextS.take 1024 . filterReserved) (mkBasicId' Verilog True nm) of+ nm' | TextS.null nm' -> "_clash_internal"+ | otherwise -> nm'+ go esc Extended (rmSlash -> nm) = case go esc Basic nm of+ nm' | esc && nm /= nm' -> TextS.concat ["\\",nm," "]+ | otherwise -> nm'+ extendIdentifier = do+ allowEscaped <- use escapedIds+ return (go allowEscaped) where- go Basic nm ext = filterReserved (mkBasicId' True (nm `Text.append` ext))- go Extended (rmSlash . escapeTemplate -> nm) ext =- let nmExt = nm `Text.append` ext- in case go Basic nm ext of- nm' | nm' /= nmExt -> case Text.head nmExt of- '#' -> Text.concat ["\\",nmExt," "]- _ -> Text.concat ["\\#",nmExt," "]- | otherwise -> nm'+ go _ Basic nm ext =+ case (TextS.take 1024 . filterReserved) (mkBasicId' Verilog True (nm `TextS.append` ext)) of+ nm' | TextS.null nm' -> "_clash_internal"+ | otherwise -> nm'+ go esc Extended (rmSlash . escapeTemplate -> nm) ext =+ let nmExt = nm `TextS.append` ext+ in case go esc Basic nm ext of+ nm' | esc && nm' /= nmExt -> case TextS.isPrefixOf "c$" nmExt of+ True -> TextS.concat ["\\",nmExt," "]+ _ -> TextS.concat ["\\c$",nmExt," "]+ | otherwise -> nm' setModName _ = id setSrcSpan = (srcSpan .=)@@ -131,19 +176,29 @@ blockDecl _ ds = do decs <- decls ds if isEmpty decs- then insts ds+ then indent 2 (insts ds) else pure decs <> line <>- insts ds+ indent 2 (insts ds) unextend = return rmSlash- addInclude inc = includes %= (inc:)- addLibraries _ = return ()+ addIncludes inc = includes %= (inc++)+ addLibraries libs = libraries %= (libs ++) addImports inps = imports %= (inps ++)+ addAndSetData f = do+ fs <- use dataFiles+ let (fs',f') = renderFilePath fs f+ dataFiles .= fs'+ return f'+ getDataFiles = use dataFiles+ addMemoryDataFile f = memoryDataFiles %= (f:)+ getMemoryDataFiles = use memoryDataFiles+ seenIdentifiers = idSeen+ ifThenElseExpr _ = True rmSlash :: Identifier -> Identifier rmSlash nm = fromMaybe nm $ do- nm1 <- Text.stripPrefix "\\" nm- pure (Text.filter (not . (== ' ')) nm1)+ nm1 <- TextS.stripPrefix "\\" nm+ pure (TextS.filter (not . (== ' ')) nm1) type VerilogM a = Mon (State VerilogState) a @@ -168,16 +223,17 @@ filterReserved :: Identifier -> Identifier filterReserved s = if s `elem` reservedWords- then s `Text.append` "_r"+ then s `TextS.append` "_r" else s -- | Generate VHDL for a Netlist component-genVerilog :: SrcSpan -> Component -> VerilogM ((String,Doc),[(String,Doc)])-genVerilog sp c = do+genVerilog :: SrcSpan -> HashMap Identifier Word -> Component -> VerilogM ((String,Doc),[(String,Doc)])+genVerilog sp seen c = preserveSeen $ do+ Mon (idSeen .= seen) Mon (setSrcSpan sp)- v <- commentHeader <> line <> module_ c+ v <- commentHeader <> line <> timescale <> line <> module_ c incs <- Mon $ use includes- return ((unpack cName,v),incs)+ return ((TextS.unpack cName,v),incs) where #ifdef CABAL clashVer = Data.Version.showVersion Paths_clash_lib.version@@ -189,30 +245,37 @@ = "/* AUTOMATICALLY GENERATED VERILOG-2001 SOURCE CODE." <> line <> "** GENERATED BY CLASH " <> string (Text.pack clashVer) <> ". DO NOT MODIFY." <> line <> "*/"+ timescale = "`timescale 100fs/100fs" +sigPort :: Maybe WireOrReg+ -> TextS.Text+ -> HWType+ -> VerilogM Doc+sigPort wor pName hwType =+ addAttrs (hwTypeAttrs hwType)+ (portType <+> verilogType' True hwType <+> stringS pName <> encodingNote hwType)+ where+ portType = case wor of+ Nothing -> if isBiSignalIn hwType then "inout" else "input"+ Just Wire -> "output" <+> "wire"+ Just Reg -> "output" <+> "reg"+ module_ :: Component -> VerilogM Doc-module_ c = addSeen c *> modVerilog <* Mon (idSeen .= [] >> imports .= [])+module_ c = addSeen c *> modVerilog <* Mon (imports .= []) where modVerilog = do body <- modBody imps <- Mon $ use imports- modHeader <> line <> modPorts <> line <> include (nub imps) <> pure body <> line <> modEnding+ libs <- Mon $ use libraries+ modHeader <> line <> modPorts <> line <> include (nub imps) <> uselibs (nub libs) <> pure body <> line <> modEnding - modHeader = "module" <+> string (componentName c)+ modHeader = "module" <+> stringS (componentName c) modPorts = indent 4 (tupleInputs inPorts <> line <> tupleOutputs outPorts <> semi)- modBody = indent 2 (decls (declarations c)) <> line <> line <> insts (declarations c)+ modBody = indent 2 (decls (declarations c)) <> line <> line <> indent 2 (insts (declarations c)) modEnding = "endmodule" - inPorts = sequence [ sigPort Nothing p | p <- inputs c ]- outPorts = sequence [ sigPort (Just wr) p | (wr, p) <- outputs c ]-- wr2ty Nothing = "input"- wr2ty (Just Wire) = "output" <+> "wire"- wr2ty (Just Reg) = "output" <+> "reg"-- -- map a port to its verilog type, port name, and any encoding notes- sigPort (wr2ty -> portTy) (nm, hwTy)- = portTy <+> verilogType' True hwTy <+> string nm <+> encodingNote hwTy+ inPorts = sequence [ sigPort Nothing id_ hwType | (id_, hwType) <- inputs c ]+ outPorts = sequence [ sigPort (Just wireOrReg) id_ hwType | (wireOrReg, (id_, hwType)) <- outputs c ] -- slightly more readable than 'tupled', makes the output Haskell-y-er commafy v = (comma <> space) <> pure v@@ -239,16 +302,23 @@ indent 2 (vcat (mapM (\i -> string "`include" <+> dquotes (string i)) xs)) <> line <> line -wireOrReg :: WireOrReg -> VerilogM Doc-wireOrReg Wire = "wire"-wireOrReg Reg = "reg"+uselibs :: Monad m => [Text.Text] -> Mon m Doc+uselibs [] = emptyDoc+uselibs xs = line <>+ -- NOTE: We must produce a single uselib directive as later ones overwrite earlier ones.+ indent 2 (string "`uselib" <+> (hsep (mapM (\l -> ("lib=" <> string l)) xs)))+ <> line <> line +wireOrRegDoc :: WireOrReg -> VerilogM Doc+wireOrRegDoc Wire = "wire"+wireOrRegDoc Reg = "reg"+ addSeen :: Component -> VerilogM () addSeen c = do- let iport = map fst $ inputs c- oport = map (fst.snd) $ outputs c+ let iport = [iName | (iName, _) <- inputs c]+ oport = [oName | (_, (oName, _)) <- outputs c] nets = mapMaybe (\case {NetDecl' _ _ i _ -> Just i; _ -> Nothing}) $ declarations c- Mon $ idSeen .= concat [iport,oport,nets]+ Mon $ idSeen %= (HashMap.unionWith max (HashMap.fromList (concatMap (map (,0)) [iport,oport,nets]))) -- render a type; by default, removing zero-sizes is an aesthetic operation -- and is only valid for decls (e.g. when rendering module ports), so don't@@ -271,7 +341,6 @@ in case t of -- special case: Bit, Bool, clocks and resets- Clock _ _ Gated -> verilogType' isDecl (gatedClockType t) Clock {} -> emptyDoc Reset {} -> emptyDoc Bit -> emptyDoc@@ -281,11 +350,6 @@ ty | (prefix, sz) <- getVerilogTy ty -> prefix <> renderVerilogTySize (sz-1) -gatedClockType :: HWType -> HWType-gatedClockType (Clock _ _ Gated) = Product "GatedClock" [Bit,Bool]-gatedClockType ty = ty-{-# INLINE gatedClockType #-}- sigDecl :: VerilogM Doc -> HWType -> VerilogM Doc sigDecl d t = verilogType t <+> d @@ -293,16 +357,21 @@ verilogTypeMark :: HWType -> VerilogM Doc verilogTypeMark = const emptyDoc --- | Convert a Netlist HWType to an error VHDL value for that type+-- | Convert a Netlist HWType to an error Verilog value for that type verilogTypeErrValue :: HWType -> VerilogM Doc-verilogTypeErrValue ty = braces (int (typeSize ty) <+> braces "1'bx")+verilogTypeErrValue ty = do+ udf <- Mon (use undefValue)+ case udf of+ Nothing -> braces (int (typeSize ty) <+> braces "1'bx")+ Just Nothing -> int (typeSize ty) <> "'d0 /* undefined */"+ Just (Just x) -> braces (int (typeSize ty) <+> braces ("1'b" <> int x)) <+> "/* undefined */" verilogRecSel :: HWType -> Int -> VerilogM Doc verilogRecSel ty i = case modifier 0 (Indexed (ty,0,i)) of- Just (start,end) -> brackets (int start <> colon <> int end)+ Just (start,end,_resTy) -> brackets (int start <> colon <> int end) _ -> error "Can't make a record selector" decls :: [Declaration] -> VerilogM Doc@@ -313,36 +382,142 @@ [] -> emptyDoc _ -> punctuate' semi (A.pure dsDoc) +-- | Add attribute notation to given declaration+addAttrs+ :: [Attr']+ -> VerilogM Doc+ -> VerilogM Doc+addAttrs [] t = t+addAttrs attrs' t =+ "(*" <+> attrs'' <+> "*)" <+> t+ where+ attrs'' = string $ Text.intercalate ", " (map renderAttr attrs')++-- | Convert single attribute to verilog syntax+renderAttr :: Attr' -> Text.Text+renderAttr (StringAttr' key value) = pack $ concat [key, " = ", show value]+renderAttr (IntegerAttr' key value) = pack $ concat [key, " = ", show value]+renderAttr (BoolAttr' key True ) = pack $ concat [key, " = ", "1"]+renderAttr (BoolAttr' key False) = pack $ concat [key, " = ", "0"]+renderAttr (Attr' key ) = pack $ key+ decl :: Declaration -> VerilogM (Maybe Doc) decl (NetDecl' noteM wr id_ tyE) =- Just <$> maybe id addNote noteM (wireOrReg wr <+> tyDec tyE)+ Just A.<$> maybe id addNote noteM (addAttrs attrs (wireOrRegDoc wr <+> tyDec tyE)) where- tyDec (Left ty) = string ty <+> string id_- tyDec (Right ty) = sigDecl (string id_) ty- addNote n = mappend ("//" <+> string n <> line)+ tyDec (Left ty) = stringS ty <+> stringS id_+ tyDec (Right ty) = sigDecl (stringS id_) ty+ addNote n = mappend ("//" <+> stringS n <> line)+ attrs = fromMaybe [] (hwTypeAttrs A.<$> either (const Nothing) Just tyE) decl _ = return Nothing insts :: [Declaration] -> VerilogM Doc insts [] = emptyDoc-insts is = indent 2 . vcat . punctuate line . fmap catMaybes $ mapM inst_ is+insts (TickDecl id_:ds) = "//" <+> stringS id_ <> line <> insts ds+insts (d:ds) = do+ docM <- inst_ d+ case docM of+ Nothing -> insts ds+ Just doc -> pure doc <> line <> line <> insts ds --- | Turn a Netlist Declaration to a SystemVerilog concurrent block+stdMatch+ :: Bits a+ => Int+ -> a+ -> a+ -> String+stdMatch 0 _mask _value = []+stdMatch size mask value =+ symbol : stdMatch (size - 1) mask value+ where+ symbol =+ if testBit mask (size - 1) then+ if testBit value (size - 1) then+ '1'+ else+ '0'+ else+ '?'++patLitCustom'+ :: Int+ -> ConstrRepr'+ -> VerilogM Doc+patLitCustom' size (ConstrRepr' _name _n mask value _anns) =+ int size <> squote <> "b" <> (string $ Text.pack $ stdMatch size mask value)++patLitCustom+ :: HWType+ -> Literal+ -> VerilogM Doc+patLitCustom (CustomSum _name _dataRepr size reprs) (NumLit (fromIntegral -> i)) =+ patLitCustom' size (fst $ reprs !! i)++patLitCustom (CustomSP _name _dataRepr size reprs) (NumLit (fromIntegral -> i)) =+ let (cRepr, _id, _tys) = reprs !! i in+ patLitCustom' size cRepr++patLitCustom x y = error $ $(curLoc) ++ unwords+ [ "You can only pass CustomSP / CustomSum and a NumLit to this function,"+ , "not", show x, "and", show y]++patMod :: HWType -> Literal -> Literal+patMod hwTy (NumLit i) = NumLit (i `mod` (2 ^ typeSize hwTy))+patMod _ l = l++-- | Helper function for inst_, handling CustomSP and CustomSum+inst_'+ :: TextS.Text+ -> Expr+ -> HWType+ -> [(Maybe Literal, Expr)]+ -> VerilogM (Maybe Doc)+inst_' id_ scrut scrutTy es = fmap Just $+ "always @(*) begin" <> line <>+ indent 2 casez <> line <>+ "end"+ where+ casez =+ "casez" <+> parens var <> line <>+ indent 2 (conds esNub) <> line <>+ "endcase"++ esMod = map (first (fmap (patMod scrutTy))) es+ esNub = nubBy ((==) `on` fst) esMod+ var = expr_ True scrut++ conds :: [(Maybe Literal,Expr)] -> VerilogM Doc+ conds [] = error $ $(curLoc) ++ "Empty list of conditions invalid."+ conds [(_,e)] = "default" <+> ":" <+> stringS id_ <+> "=" <+> expr_ False e <> ";"+ conds ((Nothing,e):_) = "default" <+> ":" <+> stringS id_ <+> "=" <+> expr_ False e <> ";"+ conds ((Just c ,e):es') =+ mask' <+> ":" <+> stringS id_ <+> "=" <+> expr_ False e <> ";" <> line <> conds es'+ where+ mask' = patLitCustom scrutTy c++-- | Turn a Netlist Declaration to a Verilog concurrent block inst_ :: Declaration -> VerilogM (Maybe Doc)+inst_ (TickDecl {}) = return Nothing inst_ (Assignment id_ e) = fmap Just $- "assign" <+> string id_ <+> equals <+> expr_ False e <> semi+ "assign" <+> stringS id_ <+> equals <+> expr_ False e <> semi inst_ (CondAssignment id_ _ scrut _ [(Just (BoolLit b), l),(_,r)]) = fmap Just $ "always @(*) begin" <> line <> indent 2 ("if" <> parens (expr_ True scrut) <> line <>- (indent 2 $ string id_ <+> equals <+> expr_ False t <> semi) <> line <>+ (indent 2 $ stringS id_ <+> equals <+> expr_ False t <> semi) <> line <> "else" <> line <>- (indent 2 $ string id_ <+> equals <+> expr_ False f <> semi)) <> line <>+ (indent 2 $ stringS id_ <+> equals <+> expr_ False f <> semi)) <> line <> "end" where (t,f) = if b then (l,r) else (r,l) +inst_ (CondAssignment id_ _ scrut scrutTy@(CustomSP _ _ _ _) es) =+ inst_' id_ scrut scrutTy es +inst_ (CondAssignment id_ _ scrut scrutTy@(CustomSum _ _ _ _) es) =+ inst_' id_ scrut scrutTy es+ inst_ (CondAssignment id_ _ scrut scrutTy es) = fmap Just $ "always @(*) begin" <> line <> indent 2 ("case" <> parens (expr_ True scrut) <> line <>@@ -352,14 +527,17 @@ where conds :: Identifier -> [(Maybe Literal,Expr)] -> VerilogM [Doc] conds _ [] = return []- conds i [(_,e)] = ("default" <+> colon <+> string i <+> equals <+> expr_ False e) <:> return []- conds i ((Nothing,e):_) = ("default" <+> colon <+> string i <+> equals <+> expr_ False e) <:> return []- conds i ((Just c ,e):es') = (exprLit (Just (scrutTy,conSize scrutTy)) c <+> colon <+> string i <+> equals <+> expr_ False e) <:> conds i es'+ conds i [(_,e)] = ("default" <+> colon <+> stringS i <+> equals <+> expr_ False e) <:> return []+ conds i ((Nothing,e):_) = ("default" <+> colon <+> stringS i <+> equals <+> expr_ False e) <:> return []+ conds i ((Just c ,e):es') = (exprLitV (Just (scrutTy,conSize scrutTy)) c <+> colon <+> stringS i <+> equals <+> expr_ False e) <:> conds i es' -inst_ (InstDecl _ nm lbl pms) = fmap Just $- nest 2 (string nm <+> string lbl <> line <> pms' <> semi)+inst_ (InstDecl _ _ nm lbl ps pms) = fmap Just $+ nest 2 (stringS nm <> params <> stringS lbl <> line <> pms' <> semi) where pms' = tupled $ sequence [dot <> expr_ False i <+> parens (expr_ False e) | (i,_,_,e) <- pms]+ params+ | null ps = space+ | otherwise = line <> "#" <> tupled (sequence [dot <> expr_ False i <+> parens (expr_ False e) | (i,_,e) <- ps]) <> line inst_ (BlackBoxD _ libs imps inc bs bbCtx) = fmap Just (Mon (column (renderBlackBox libs imps inc bs bbCtx)))@@ -368,12 +546,15 @@ -- | Calculate the beginning and end index into a variable, to get the -- desired field.+-- Also returns the HWType of the result. modifier :: Int -- ^ Offset, only used when we have nested modifiers -> Modifier- -> Maybe (Int,Int)-modifier offset (Indexed (ty@(SP _ args),dcI,fI)) = Just (start+offset,end+offset)+ -> Maybe (Int,Int,HWType)+modifier offset (Sliced (BitVector _,start,end)) = Just (start+offset,end+offset, BitVector (start-end+1))++modifier offset (Indexed (ty@(SP _ args),dcI,fI)) = Just (start+offset,end+offset, argTy) where argTys = snd $ args !! dcI argTy = argTys !! fI@@ -382,7 +563,7 @@ start = typeSize ty - 1 - conSize ty - other end = start - argSize + 1 -modifier offset (Indexed (ty@(Product _ argTys),_,fI)) = Just (start+offset,end+offset)+modifier offset (Indexed (ty@(Product _ _ argTys),_,fI)) = Just (start+offset,end+offset, argTy) where argTy = argTys !! fI argSize = typeSize argTy@@ -390,43 +571,34 @@ start = typeSize ty - 1 - otherSz end = start - argSize + 1 -modifier offset (Indexed (ty@(Clock _ _ Gated),_,fI)) = Just (start+offset,end+offset)- where- argTys = [Bit, Bool]- argTy = argTys !! fI- argSize = typeSize argTy- otherSz = otherSize argTys (fI - 1)- start = typeSize ty - 1 - otherSz- end = start - argSize + 1--modifier offset (Indexed (ty@(Vector _ argTy),1,0)) = Just (start+offset,end+offset)+modifier offset (Indexed (ty@(Vector _ argTy),1,0)) = Just (start+offset,end+offset, argTy) where argSize = typeSize argTy start = typeSize ty - 1 end = start - argSize + 1 -modifier offset (Indexed (ty@(Vector _ argTy),1,1)) = Just (start+offset,offset)+modifier offset (Indexed (ty@(Vector _ argTy),1,1)) = Just (start+offset,offset, argTy) where argSize = typeSize argTy start = typeSize ty - argSize - 1 -modifier offset (Indexed (ty@(RTree 0 _),0,0)) = Just (start+offset,offset)+modifier offset (Indexed (ty@(RTree 0 argTy),0,0)) = Just (start+offset,offset, argTy) where start = typeSize ty - 1 -modifier offset (Indexed (ty@(RTree _ _),1,0)) = Just (start+offset,end+offset)+modifier offset (Indexed (ty@(RTree _ argTy),1,0)) = Just (start+offset,end+offset, argTy) where start = typeSize ty - 1 end = typeSize ty `div` 2 -modifier offset (Indexed (ty@(RTree _ _),1,1)) = Just (start+offset,offset)+modifier offset (Indexed (ty@(RTree _ argTy),1,1)) = Just (start+offset,offset, argTy) where start = (typeSize ty `div` 2) - 1 -- This is a HACK for Clash.Driver.TopWrapper.mkOutput -- Vector's don't have a 10'th constructor, this is just so that we can -- recognize the particular case-modifier offset (Indexed (ty@(Vector _ argTy),10,fI)) = Just (start+offset,end+offset)+modifier offset (Indexed (ty@(Vector _ argTy),10,fI)) = Just (start+offset,end+offset, argTy) where argSize = typeSize argTy start = typeSize ty - (fI * argSize) - 1@@ -435,13 +607,21 @@ -- This is a HACK for Clash.Driver.TopWrapper.mkOutput -- RTree's don't have a 10'th constructor, this is just so that we can -- recognize the particular case-modifier offset (Indexed (ty@(RTree _ argTy),10,fI)) = Just (start+offset,end+offset)+modifier offset (Indexed (ty@(RTree _ argTy),10,fI)) = Just (start+offset,end+offset, argTy) where argSize = typeSize argTy start = typeSize ty - (fI * argSize) - 1 end = start - argSize + 1 -modifier offset (DC (ty@(SP _ _),_)) = Just (start+offset,end+offset)+modifier offset (Indexed (CustomSP _id _dataRepr _size args,dcI,fI)) =+ case bitRanges (anns !! fI) of+ [(start,end)] -> Just (start+offset,end+offset, argTy)+ _ -> error ($(curLoc) ++ "Cannot handle projection out of a non-contiguously encoded field")+ where+ (ConstrRepr' _name _n _mask _value anns, _, argTys) = args !! dcI+ argTy = argTys !! fI++modifier offset (DC (ty@(SP _ _),_)) = Just (start+offset,end+offset, ty) where start = typeSize ty - 1 end = typeSize ty - conSize ty@@ -449,25 +629,58 @@ modifier offset (Nested m1 m2) = do case modifier offset m1 of Nothing -> modifier offset m2- Just (s,e) -> case modifier e m2 of+ Just (s,e,argTy) -> case modifier e m2 of -- In case the second modifier is `Nothing` that means we want the entire -- thing calculated by the first modifier- Nothing -> Just (s,e)+ Nothing -> Just (s,e,argTy) m -> m modifier _ _ = Nothing --- | Turn a Netlist expression into a SystemVerilog expression-expr_ :: Bool -- ^ Enclose in parenthesis?+-- | Turn a Netlist expression into a Verilog expression+expr_ :: Bool -- ^ Enclose in parentheses? -> Expr -- ^ Expr to convert -> VerilogM Doc-expr_ _ (Literal sizeM lit) = exprLit sizeM lit+expr_ _ (Literal sizeM lit) = exprLitV sizeM lit -expr_ _ (Identifier id_ Nothing) = string id_+expr_ _ (Identifier id_ Nothing) = stringS id_ +expr_ _ (Identifier id_ (Just (Indexed (CustomSP _id _dataRepr _size args,dcI,fI)))) =+ braces $ hcat $ punctuate ", " $ sequence ranges+ where+ (ConstrRepr' _name _n _mask _value anns, _, _argTys) = args !! dcI+ ranges = map range' $ bitRanges (anns !! fI)+ range' (start, end) = stringS id_ <> brackets (int start <> ":" <> int end)++-- See [Note] integer projection+expr_ _ (Identifier id_ (Just (Indexed ((Signed w),_,_)))) = do+ iw <- Mon $ use intWidth+ traceIf (iw < w) ($(curLoc) ++ "WARNING: result smaller than argument") $+ stringS id_++-- See [Note] integer projection+expr_ _ (Identifier id_ (Just (Indexed ((Unsigned w),_,_)))) = do+ iw <- Mon $ use intWidth+ traceIf (iw < w) ($(curLoc) ++ "WARNING: result smaller than argument") $+ stringS id_++-- See [Note] mask projection+expr_ _ (Identifier _ (Just (Indexed ((BitVector _),_,0)))) = do+ iw <- Mon $ 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+ traceIf (iw < w) ($(curLoc) ++ "WARNING: result smaller than argument") $+ stringS id_+ expr_ _ (Identifier id_ (Just m)) = case modifier 0 m of- Nothing -> string id_- Just (start,end) -> string id_ <> brackets (int start <> colon <> int end)+ Nothing -> stringS id_+ Just (start,end,resTy) -> case resTy of+ Signed _ -> "$signed" <> parens (stringS id_ <> brackets (int start <> colon <> int end))+ _ -> stringS id_ <> brackets (int start <> colon <> int end) expr_ b (DataCon _ (DC (Void {}, -1)) [e]) = expr_ b e @@ -485,6 +698,11 @@ Just es' -> listBraces (mapM (expr_ False) es') Nothing -> listBraces (mapM (expr_ False) es) +expr_ _ (DataCon (SP {}) (DC (BitVector _,_)) es) = assignExpr+ where+ argExprs = map (expr_ False) es+ assignExpr = braces (hcat $ punctuate comma $ sequence argExprs)+ expr_ _ (DataCon ty@(SP _ args) (DC (_,i)) es) = assignExpr where argTys = snd $ args !! i@@ -493,57 +711,100 @@ argExprs = map (expr_ False) es extraArg = case typeSize ty - dcSize of 0 -> []- n -> [int n <> "'b" <> bits (replicate n U)]+ n -> [int n <> "'b" <> bits undefValue (replicate n U)] assignExpr = braces (hcat $ punctuate comma $ sequence (dcExpr:argExprs ++ extraArg)) expr_ _ (DataCon ty@(Sum _ _) (DC (_,i)) []) = int (typeSize ty) <> "'d" <> int i -expr_ _ (DataCon (Product _ _) _ es) = listBraces (mapM (expr_ False) es)+expr_ _ (DataCon ty@(CustomSum _ _ _ tys) (DC (_,i)) []) =+ let (ConstrRepr' _ _ _ value _) = fst $ tys !! i in+ int (typeSize ty) <> squote <> "d" <> int (fromIntegral value)+expr_ _ (DataCon (CustomSP name' dataRepr size args) (DC (_,constrNr)) es) =+ (flip fromMaybe) (errOnNonContinuous 0 anns) $+ braces $ hcat $ punctuate ", " $ mapM range' origins+ where+ (cRepr, _, _) = args !! constrNr+ (ConstrRepr' _name _n _mask _value anns) = cRepr -expr_ _ (DataCon (Clock _ _ Gated) _ es) = listBraces (mapM (expr_ False) es)+ errOnNonContinuous :: Int -> [BitMask] -> Maybe a+ errOnNonContinuous _ [] = Nothing+ errOnNonContinuous fieldnr (ann:anns') =+ if isContinuousMask ann then+ errOnNonContinuous (fieldnr + 1) anns'+ else+ error $ $(curLoc) ++ unlines [+ "Error while processing custom bit representation:\n"+ , unwords ["Field", show fieldnr, "of constructor", show constrNr, "of type\n"]+ , " " ++ show name' ++ "\n"+ , "has a non-continuous fieldmask:\n"+ , " " ++ (map bit_char' $ toBits size ann) ++ "\n"+ , unwords [ "This is not supported in Verilog. Change the mask to a"+ , "continuous one, or render using VHDL or SystemVerilog."+ ]+ ] + -- Build bit representations for all constructor arguments+ argExprs = map (expr_ False) es :: [VerilogM Doc]++ -- Spread bits of constructor arguments using masks+ origins = bitOrigins dataRepr cRepr :: [BitOrigin]++ range'+ :: BitOrigin+ -> VerilogM Doc+ range' (Lit (bitsToBits -> ns)) =+ int (length ns) <> squote <> "b" <> hcat (mapM (bit_char undefValue) ns)+ range' (Field n _start _end) =+ argExprs !! n++expr_ _ (DataCon (Product {}) _ es) = listBraces (mapM (expr_ False) es)+ expr_ _ (BlackBoxE pNm _ _ _ _ bbCtx _) | pNm == "Clash.Sized.Internal.Signed.fromInteger#" , [Literal _ (NumLit n), Literal _ i] <- extractLiterals bbCtx- = exprLit (Just (Signed (fromInteger n),fromInteger n)) i+ = exprLitV (Just (Signed (fromInteger n),fromInteger n)) i expr_ _ (BlackBoxE pNm _ _ _ _ bbCtx _) | pNm == "Clash.Sized.Internal.Unsigned.fromInteger#" , [Literal _ (NumLit n), Literal _ i] <- extractLiterals bbCtx- = exprLit (Just (Unsigned (fromInteger n),fromInteger n)) i+ = exprLitV (Just (Unsigned (fromInteger n),fromInteger n)) i expr_ _ (BlackBoxE pNm _ _ _ _ bbCtx _) | pNm == "Clash.Sized.Internal.BitVector.fromInteger#"- , [Literal _ (NumLit n), Literal _ i] <- extractLiterals bbCtx- = exprLit (Just (BitVector (fromInteger n),fromInteger n)) i+ , [Literal _ (NumLit n), Literal _ m, Literal _ i] <- extractLiterals bbCtx+ = let NumLit m' = m+ NumLit i' = i+ in exprLitV (Just (BitVector (fromInteger n),fromInteger n)) (BitVecLit m' i') expr_ _ (BlackBoxE pNm _ _ _ _ bbCtx _) | pNm == "Clash.Sized.Internal.BitVector.fromInteger##"- , [Literal _ i] <- extractLiterals bbCtx- = exprLit (Just (Bit,1)) i+ , [Literal _ m, Literal _ i] <- extractLiterals bbCtx+ = let NumLit m' = m+ NumLit i' = i+ in exprLitV (Just (Bit,1)) (BitLit $ toBit m' i') expr_ _ (BlackBoxE pNm _ _ _ _ bbCtx _) | pNm == "Clash.Sized.Internal.Index.fromInteger#" , [Literal _ (NumLit n), Literal _ i] <- extractLiterals bbCtx- = exprLit (Just (Index (fromInteger n),fromInteger n)) i+ = 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)) -expr_ _ (DataTag Bool (Left id_)) = string id_ <> brackets (int 0)+expr_ _ (DataTag Bool (Left id_)) = stringS id_ <> brackets (int 0) expr_ _ (DataTag Bool (Right id_)) = do iw <- Mon (use intWidth)- "$unsigned" <> parens (listBraces (sequence [braces (int (iw-1) <+> braces "1'b0"),string id_]))+ "$unsigned" <> parens (listBraces (sequence [braces (int (iw-1) <+> braces "1'b0"),stringS id_])) -expr_ _ (DataTag (Sum _ _) (Left id_)) = "$unsigned" <> parens (string id_)-expr_ _ (DataTag (Sum _ _) (Right id_)) = "$unsigned" <> parens (string id_)+expr_ _ (DataTag (Sum _ _) (Left id_)) = "$unsigned" <> parens (stringS id_)+expr_ _ (DataTag (Sum _ _) (Right id_)) = "$unsigned" <> parens (stringS id_) -expr_ _ (DataTag (Product _ _) (Right _)) = do+expr_ _ (DataTag (Product {}) (Right _)) = do iw <- Mon (use intWidth) int iw <> "'sd0" expr_ _ (DataTag hty@(SP _ _) (Right id_)) = "$unsigned" <> parens- (string id_ <> brackets+ (stringS id_ <> brackets (int start <> colon <> int end)) where start = typeSize hty - 1@@ -565,6 +826,9 @@ expr_ b (ConvBV _ _ _ e) = expr_ b e +expr_ b (IfThenElse c t e) =+ parenIf b (expr_ True c <+> "?" <+> expr_ True t <+> ":" <+> expr_ True e)+ expr_ _ e = error $ $(curLoc) ++ (show e) -- empty otherSize :: [HWType] -> Int -> Int@@ -583,23 +847,32 @@ rtreeChain (DataCon (RTree _ _) _ [e1,e2]) = Just e1 <:> rtreeChain e2 rtreeChain _ = Nothing -exprLit :: Maybe (HWType,Size) -> Literal -> VerilogM Doc-exprLit Nothing (NumLit i) = integer i+exprLitV :: Maybe (HWType,Size) -> Literal -> VerilogM Doc+exprLitV = exprLit undefValue -exprLit (Just (hty,sz)) (NumLit i) = case hty of- Unsigned _ -> int sz <> "'d" <> integer i- Index _ -> int (typeSize hty) <> "'d" <> integer i+exprLit :: Lens' s (Maybe (Maybe Int)) -> Maybe (HWType,Size) -> Literal -> Mon (State s) Doc+exprLit _ Nothing (NumLit i) = integer i++exprLit k (Just (hty,sz)) (NumLit i) = case hty of+ Unsigned _+ | i < 0 -> string "-" <> int sz <> string "'d" <> integer (abs i)+ | otherwise -> int sz <> string "'d" <> integer i+ Index _ -> int (typeSize hty) <> string "'d" <> integer i Signed _- | i < 0 -> "-" <> int sz <> "'sd" <> integer (abs i)- | otherwise -> int sz <> "'sd" <> integer i- _ -> int sz <> "'b" <> blit+ | i < 0 -> string "-" <> int sz <> string "'sd" <> integer (abs i)+ | otherwise -> int sz <> string "'sd" <> integer i+ _ -> int sz <> string "'b" <> blit where- blit = bits (toBits sz i)-exprLit _ (BoolLit t) = if t then "1'b1" else "1'b0"-exprLit _ (BitLit b) = "1'b" <> bit_char b-exprLit _ (StringLit s) = string . pack $ show s-exprLit _ l = error $ $(curLoc) ++ "exprLit: " ++ show l+ blit = bits k (toBits sz i)+exprLit k (Just (_,sz)) (BitVecLit m i) = int sz <> string "'b" <> bvlit+ where+ bvlit = bits k (toBits' sz m i) +exprLit _ _ (BoolLit t) = string $ if t then "1'b1" else "1'b0"+exprLit k _ (BitLit b) = string "1'b" <> bit_char k b+exprLit _ _ (StringLit s) = string . pack $ show s+exprLit _ _ l = error $ $(curLoc) ++ "exprLit: " ++ show l+ toBits :: Integral a => Int -> a -> [Bit] toBits size val = map (\x -> if odd x then H else L) $ reverse@@ -607,15 +880,33 @@ $ map (`mod` 2) $ iterate (`div` 2) val -bits :: [Bit] -> VerilogM Doc-bits = hcat . mapM bit_char+toBits' :: Integral a => Int -> a -> a -> [Bit]+toBits' size msk val = map (\(m,i) -> if odd m then U else (if odd i then H else L))+ $+ ( reverse . take size)+ $ zip+ ( map (`mod` 2) $ iterate (`div` 2) msk)+ ( map (`mod` 2) $ iterate (`div` 2) val) -bit_char :: Bit -> VerilogM Doc-bit_char H = char '1'-bit_char L = char '0'-bit_char U = char 'x'-bit_char Z = char 'z' +bits :: Lens' s (Maybe (Maybe Int)) -> [Bit] -> Mon (State s) Doc+bits k = hcat . traverse (bit_char k)++bit_char' :: Bit -> Char+bit_char' H = '1'+bit_char' L = '0'+bit_char' U = 'x'+bit_char' Z = 'z'++bit_char :: Lens' s (Maybe (Maybe Int)) -> Bit -> Mon (State s) Doc+bit_char k b = do+ udf <- Mon (use k)+ case (udf,b) of+ (Just Nothing,U) -> char '0'+ (Just (Just i),U) -> "'" <> int i <> "'"+ _ -> char (bit_char' b)++ dcToExpr :: HWType -> Int -> Expr dcToExpr ty i = Literal (Just (ty,conSize ty)) (NumLit (toInteger i)) @@ -629,8 +920,7 @@ punctuate' :: Monad m => Mon m Doc -> Mon m [Doc] -> Mon m Doc punctuate' s d = vcat (punctuate s d) <> s -encodingNote :: HWType -> VerilogM Doc-encodingNote (Clock _ _ Gated) = "// gated clock"-encodingNote (Clock {}) = "// clock"-encodingNote (Reset {}) = "// asynchronous reset: active high"-encodingNote _ = emptyDoc+encodingNote :: Applicative m => HWType -> m Doc+encodingNote (Clock _) = string " // clock"+encodingNote (Reset _) = string " // reset"+encodingNote _ = emptyDoc
src/Clash/Core/DataCon.hs view
@@ -18,104 +18,57 @@ ( DataCon (..) , DcName , ConTag- , dataConInstArgTys ) where -#ifndef MIN_VERSION_unbound_generics-#define MIN_VERSION_unbound_generics(x,y,z)(1)-#endif- import Control.DeepSeq (NFData(..))+import Data.Binary (Binary) import Data.Hashable (Hashable)+import qualified Data.Text as Text import GHC.Generics (Generic)-import Unbound.Generics.LocallyNameless (Alpha(..),Subst(..))-import Unbound.Generics.LocallyNameless.Extra ()-#if MIN_VERSION_unbound_generics(0,3,0)-import Data.Monoid (All (..))-import Unbound.Generics.LocallyNameless (NthPatFind (..),- NamePatFind (..))-#endif import Clash.Core.Name (Name (..))-import {-# SOURCE #-} Clash.Core.Type (TyName, Type)+import {-# SOURCE #-} Clash.Core.Type (Type)+import Clash.Core.Var (TyVar)+import Clash.Unique import Clash.Util -- | Data Constructor data DataCon = MkData- { dcName :: !DcName -- ^ Name of the DataCon- , dcTag :: !ConTag -- ^ Syntactical position in the type definition- , dcType :: !Type -- ^ Type of the 'DataCon- , dcUnivTyVars :: [TyName] -- ^ Universally quantified type-variables,- -- these type variables are also part of the- -- result type of the DataCon- , dcExtTyVars :: [TyName] -- ^ Existentially quantified type-variables,- -- these type variables are not part of the result- -- of the DataCon, but only of the arguments.- , dcArgTys :: [Type] -- ^ Argument types- } deriving (Generic,NFData,Hashable)+ { dcName :: !DcName+ -- ^ Name of the DataCon+ , dcUniq :: {-# UNPACK #-} !Unique+ , dcTag :: !ConTag+ -- ^ Syntactical position in the type definition+ , dcType :: !Type+ -- ^ Type of the 'DataCon+ , dcUnivTyVars :: [TyVar]+ -- ^ Universally quantified type-variables, these type variables are also part+ -- of the result type of the DataCon+ , dcExtTyVars :: [TyVar]+ -- ^ Existentially quantified type-variables, these type variables are not+ -- part of the result of the DataCon, but only of the arguments.+ , dcArgTys :: [Type]+ -- ^ Argument types+ , dcFieldLabels :: [Text.Text]+ -- ^ Names of fields. Used when data constructor is referring to a record type.+ } deriving (Generic,NFData,Hashable,Binary) instance Show DataCon where show = show . dcName instance Eq DataCon where- (==) = (==) `on` dcName+ (==) = (==) `on` dcUniq+ (/=) = (/=) `on` dcUniq instance Ord DataCon where- compare = compare `on` dcName+ compare = compare `on` dcUniq +instance Uniquable DataCon where+ getUnique = dcUniq+ -- | Syntactical position of the DataCon in the type definition type ConTag = Int -- | DataCon reference type DcName = Name DataCon--instance Alpha DataCon where- aeq' c dc1 dc2 = aeq' c (dcName dc1) (dcName dc2)-- fvAny' _ _ dc = pure dc-- close _ _ dc = dc- open _ _ dc = dc-- isPat _ = mempty--#if MIN_VERSION_unbound_generics(0,3,0)- isTerm _ = All True- nthPatFind _ = NthPatFind Left- namePatFind _ = NamePatFind (const (Left 0))-#else- isTerm _ = True- nthPatFind _ = Left- namePatFind _ _ = Left 0-#endif-- swaps' _ _ dc = dc- lfreshen' _ dc cont = cont dc mempty- freshen' _ dc = return (dc,mempty)-- acompare' c dc1 dc2 = acompare' c (dcName dc1) (dcName dc2)--instance Subst a DataCon where- subst _ _ dc = dc- substs _ dc = dc---- | Given a DataCon and a list of types, the type variables of the DataCon--- type are substituted for the list of types. The argument types are returned.------ The list of types should be equal to the number of type variables, otherwise--- @Nothing@ is returned.-dataConInstArgTys :: DataCon -> [Type] -> Maybe [Type]-dataConInstArgTys (MkData { dcArgTys = arg_tys- , dcUnivTyVars = univ_tvs- , dcExtTyVars = ex_tvs- })- inst_tys- | length tyvars == length inst_tys- = Just (map (substs (zip tyvars inst_tys)) arg_tys)-- | otherwise- = Nothing-- where- tyvars = map nameOcc (univ_tvs ++ ex_tvs)
src/Clash/Core/Evaluator.hs view
@@ -10,6 +10,9 @@ -} +{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MagicHash #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE ViewPatterns #-}@@ -18,18 +21,21 @@ import Control.Arrow (second) import Control.Concurrent.Supply (Supply, freshId)+import Control.Lens (view, _4)+import Data.Bits (shiftL) import Data.Either (lefts,rights)-import qualified Data.HashMap.Lazy as HM import Data.List (foldl',mapAccumL,uncons) import Data.IntMap (IntMap)-import Data.Map- (Map,delete,fromList,insert,lookup,union)-import qualified Data.Map as M+import qualified Data.Primitive.ByteArray as BA+import qualified Data.Vector.Primitive as PV import Data.Text (Text)-import Data.Text.Prettyprint.Doc (hsep)+import Data.Text.Prettyprint.Doc import Debug.Trace (trace)+import GHC.Integer.GMP.Internals+ (Integer (..), BigNat (..)) import Clash.Core.DataCon+import Clash.Core.FreeVars import Clash.Core.Literal import Clash.Core.Name import Clash.Core.Pretty@@ -39,70 +45,72 @@ import Clash.Core.Type import Clash.Core.Util import Clash.Core.Var+import Clash.Core.VarEnv import Clash.Driver.Types (BindingMap) import Prelude hiding (lookup)+import Clash.Unique import Clash.Util (curLoc)-import Unbound.Generics.LocallyNameless as Unbound-import Unbound.Generics.LocallyNameless.Unsafe+import Clash.Pretty -- | The heap-data Heap = Heap GlobalHeap PureHeap Supply- deriving (Show)+data Heap = Heap GlobalHeap GPureHeap PureHeap Supply InScopeSet -type PureHeap = Map TmOccName Term+type PureHeap = VarEnv Term+newtype GPureHeap = GPureHeap { unGPureHeap :: PureHeap } -- | Global heap type GlobalHeap = (IntMap Term, Int) -- | The stack-type Stack = [StackFrame]+type Stack = [StackFrame] data StackFrame = Update Id+ | GUpdate Id | Apply Id | Instantiate Type- | PrimApply Text Type [Type] [Value] [Term]+ | PrimApply Text PrimInfo [Type] [Value] [Term] | Scrutinise Type [Alt]+ | Tickish TickInfo deriving Show -instance Pretty StackFrame where- pprPrec _ (Update i) = do- i' <- ppr i- pure (hsep ["Update", i'])- pprPrec _ (Apply i) = do- i' <- ppr i- pure (hsep ["Apply", i'])- pprPrec _ (Instantiate t) = do- t' <- ppr t- pure (hsep ["Instantiate", t'])- pprPrec _ (PrimApply a b c d e) = do- a' <- ppr a- b' <- ppr b- c' <- ppr c- d' <- ppr (map valToTerm d)- e' <- ppr e- pure $ hsep ["PrimApply", a', "::", b',- "; type args=", c',- "; val args=", d',- "term args=", e']- pprPrec _ (Scrutinise a b) = do- a' <- ppr a- b' <- ppr (Case (Literal (CharLiteral '_')) a b)- pure $ hsep ["Scrutinise ", a', b']+instance ClashPretty StackFrame where+ clashPretty (Update i) = hsep ["Update", fromPpr i]+ clashPretty (GUpdate i) = hsep ["GUpdate", fromPpr i]+ clashPretty (Apply i) = hsep ["Apply", fromPpr i]+ clashPretty (Instantiate t) = hsep ["Instantiate", fromPpr t]+ clashPretty (PrimApply a b c d e) = do+ hsep ["PrimApply", fromPretty a, "::", fromPpr (primType b),+ "; type args=", fromPpr c,+ "; val args=", fromPpr (map valToTerm d),+ "term args=", fromPpr e]+ clashPretty (Scrutinise a b) =+ hsep ["Scrutinise ", fromPpr a,+ fromPpr (Case (Literal (CharLiteral '_')) a b)]+ clashPretty (Tickish sp) =+ hsep ["Tick", fromPpr sp] +mkTickish+ :: Stack+ -> [TickInfo]+ -> Stack+mkTickish s sps = map Tickish sps ++ s+ -- Values data Value- = Lambda (Bind Id Term)+ = Lambda Id Term -- ^ Functions- | TyLambda (Bind TyVar Term)+ | TyLambda TyVar Term -- ^ Type abstractions | DC DataCon [Either Term Type] -- ^ Data constructors | Lit Literal -- ^ Literals- | PrimVal Text Type [Type] [Value]+ | PrimVal Text PrimInfo [Type] [Value] -- ^ Clash's number types are represented by their "fromInteger#" primitive -- function. So some primitives are values.+ | Suspend Term+ -- ^ Used by lazy primitives deriving Show -- | State of the evaluator@@ -111,12 +119,11 @@ -- | Function that can evaluator primitives, i.e., perform delta-reduction type PrimEvaluator = Bool -> -- Force special primitives? See [Note: forcing special primitives]- BindingMap -> -- Global binders TyConMap -> -- Type constructors Heap -> Stack -> Text -> -- Name of the primitive- Type -> -- Type of the primitive+ PrimInfo -> -- Type of the primitive [Type] -> -- Type arguments of the primitive [Value] -> -- Value arguments of the primitive Maybe State -- Delta-reduction can get stuck, so Nothing is an option@@ -128,35 +135,37 @@ -> TyConMap -> GlobalHeap -> Supply+ -> InScopeSet -> Bool -> Term- -> (GlobalHeap, Term)-whnf' eval gbl tcm gh ids isSubj e- = case whnf eval gbl tcm isSubj (Heap gh (fromList []) ids,[],e) of- (Heap gh' _ _,_,e') -> (gh',e')+ -> (GlobalHeap, PureHeap, Term)+whnf' eval gbl0 tcm gh ids is isSubj e+ = case whnf eval tcm isSubj (Heap gh gbl1 emptyVarEnv ids is,[],e) of+ (Heap gh' _ ph' _ _,_,e') -> (gh',ph',e')+ where+ gbl1 = GPureHeap (mapVarEnv (view _4) gbl0) -- | Evaluate to WHNF given an existing Heap and Stack whnf :: PrimEvaluator- -> BindingMap -> TyConMap -> Bool -> State -> State-whnf eval gbl tcm isSubj (h,k,e) =+whnf eval tcm isSubj (h,k,e) = if isSubj then go (h,Scrutinise ty []:k,e) -- See [Note: empty case expressions] else go (h,k,e) where- ty = runFreshM $ termType tcm e+ ty = termType tcm e - go s = case step eval gbl tcm s of+ go s = case step eval tcm s of Just s' -> go s' Nothing | Just e' <- unwindStack s -> e' | otherwise- -> error $ showDoc e+ -> error $ showDoc $ ppr e -- | Are we in a context where special primitives must be forced. --@@ -164,12 +173,13 @@ isScrut :: Stack -> Bool isScrut (Scrutinise {}:_) = True isScrut (PrimApply {} :_) = True+isScrut (Tickish {}:k) = isScrut k isScrut _ = False -- | Completely unwind the stack to get back the complete term unwindStack :: State -> Maybe State unwindStack s@(_,[],_) = Just s-unwindStack (h@(Heap _ h' _),(kf:k'),e) = case kf of+unwindStack (h@(Heap gh gbl h' ids is),(kf:k'),e) = case kf of PrimApply nm ty tys vs tms -> unwindStack (h,k'@@ -179,28 +189,30 @@ Instantiate ty -> unwindStack (h,k',TyApp e ty) Apply id_ -> do- case lookup (nameOcc (varName id_)) h' of+ case lookupVarEnv id_ h' of Just e' -> unwindStack (h,k',App e e') Nothing -> error $ unlines $ [ "Clash.Core.Evaluator.unwindStack:" , "Stack:" ] ++- [ " "++showDoc frame | frame <- kf:k'] +++ [ " "++ showDoc (clashPretty frame) | frame <- kf:k'] ++ [ "" , "Expression:"- , showDoc e+ , showPpr e , "" , "Heap:"- ] ++- [ " "++show name ++ " === " ++ showDoc value- | (name,value) <- M.toList h'+ , showDoc (clashPretty h') ] Scrutinise _ [] -> unwindStack (h,k',e) Scrutinise ty alts -> unwindStack (h,k',Case e ty alts)- Update _ ->+ Update x ->+ unwindStack (Heap gh gbl (extendVarEnv x e h') ids is,k',e)+ GUpdate _ -> unwindStack (h,k',e)+ Tickish sp ->+ unwindStack (h,k',Tick sp e) {- [Note: forcing special primitives] Clash uses the `whnf` function in two places (for now):@@ -230,64 +242,74 @@ -- | Small-step operational semantics. step :: PrimEvaluator- -> BindingMap -> TyConMap -> State -> Maybe State-step eval gbl tcm (h, k, e) = case e of- Var ty nm -> force gbl h k (Id nm (embed ty))- (Lam b) -> unwind eval gbl tcm h k (Lambda b)- (TyLam b) -> unwind eval gbl tcm h k (TyLambda b)- (Literal l) -> unwind eval gbl tcm h k (Lit l)+step eval tcm (h, k, e) = case e of+ Var v -> force h k v+ (Lam x e') -> unwind eval tcm h k (Lambda x e')+ (TyLam x e') -> unwind eval tcm h k (TyLambda x e')+ (Literal l) -> unwind eval tcm h k (Lit l) (App e1 e2)- | (Data dc,args) <- collectArgs e+ | (Data dc,args,_ticks) <- collectArgsTicks e , (tys,_) <- splitFunForallTy (dcType dc) -> case compare (length args) (length tys) of- EQ -> unwind eval gbl tcm h k (DC dc args)- LT -> let (h2,e') = mkAbstr (h,e) (drop (length args) tys)- in step eval gbl tcm (h2,k,e')+ EQ -> unwind eval tcm h k (DC dc args)+ LT -> let (tys',_) = splitFunForallTy (termType tcm e)+ (h2,e') = mkAbstr (h,e) tys'+ in step eval tcm (h2,k,e') GT -> error "Overapplied DC"- | (Prim nm ty,args) <- collectArgs e+ | (Prim nm pInfo,args,_ticks) <- collectArgsTicks e+ , let ty = primType pInfo , (tys,_) <- splitFunForallTy ty -> case compare (length args) (length tys) of EQ -> let (e':es) = lefts args- in Just (h,PrimApply nm ty (rights args) [] es:k,e')- LT -> let (h2,e') = mkAbstr (h,e) (drop (length args) tys)- in step eval gbl tcm (h2,k,e')+ in Just (h,PrimApply nm pInfo (rights args) [] es:k,e')+ LT -> let (tys',_) = splitFunForallTy (termType tcm e)+ (h2,e') = mkAbstr (h,e) tys'+ in step eval tcm (h2,k,e') GT -> let (h2,id_) = newLetBinding tcm h e2 in Just (h2,Apply id_:k,e1) (TyApp e1 ty)- | (Data dc,args) <- collectArgs e+ | (Data dc,args,_ticks) <- collectArgsTicks e , (tys,_) <- splitFunForallTy (dcType dc) -> case compare (length args) (length tys) of- EQ -> unwind eval gbl tcm h k (DC dc args)- LT -> let (h2,e') = mkAbstr (h,e) (drop (length args) tys)- in step eval gbl tcm (h2,k,e')+ EQ -> unwind eval tcm h k (DC dc args)+ LT -> let (tys',_) = splitFunForallTy (termType tcm e)+ (h2,e') = mkAbstr (h,e) tys'+ in step eval tcm (h2,k,e') GT -> error "Overapplied DC"- | (Prim nm ty',args) <- collectArgs e+ | (Prim nm pInfo,args,_ticks) <- collectArgsTicks e+ , let ty' = primType pInfo , (tys,_) <- splitFunForallTy ty' -> case compare (length args) (length tys) of EQ -> case lefts args of [] | nm `elem` ["Clash.Transformations.removedArg"] -- The above primitives are actually values, and not operations.- -> unwind eval gbl tcm h k (PrimVal nm ty' (rights args) [])+ -> unwind eval tcm h k (PrimVal nm pInfo (rights args) []) | otherwise- -> eval (isScrut k) gbl tcm h k nm ty' (rights args) []- (e':es) -> Just (h,PrimApply nm ty' (rights args) [] es:k,e')- LT -> let (h2,e') = mkAbstr (h,e) (drop (length args) tys)- in step eval gbl tcm (h2,k,e')+ -> eval (isScrut k) tcm h k nm pInfo (rights args) []+ (e':es) -> Just (h,PrimApply nm pInfo (rights args) [] es:k,e')+ LT -> let (tys',_) = splitFunForallTy (termType tcm e)+ (h2,e') = mkAbstr (h,e) tys'+ in step eval tcm (h2,k,e') GT -> Just (h,Instantiate ty:k,e1)- (Data dc) -> unwind eval gbl tcm h k (DC dc [])- (Prim nm ty')+ (Data dc) -> unwind eval tcm h k (DC dc [])+ (Prim nm pInfo) | nm `elem` ["GHC.Prim.realWorld#"]- -> unwind eval gbl tcm h k (PrimVal nm ty' [] [])+ -> unwind eval tcm h k (PrimVal nm pInfo [] []) | otherwise- -> eval (isScrut k) gbl tcm h k nm ty' [] []+ , let ty' = primType pInfo+ -> case fst (splitFunForallTy ty') of+ [] -> eval (isScrut k) tcm h k nm pInfo [] []+ tys -> let (h2,e') = mkAbstr (h,e) tys+ in step eval tcm (h2,k,e') (App e1 e2) -> let (h2,id_) = newLetBinding tcm h e2 in Just (h2,Apply id_:k,e1) (TyApp e1 ty) -> Just (h,Instantiate ty:k,e1) (Case scrut ty alts) -> Just (h,Scrutinise ty alts:k,scrut)- (Letrec bs) -> Just (allocate h k bs)+ (Letrec bs e') -> Just (allocate h k bs e')+ Tick sp e' -> Just (h,Tickish sp:k,e') Cast _ _ _ -> trace (unlines ["WARNING: " ++ $(curLoc) ++ "Clash currently can't symbolically evaluate casts" ,"If you have testcase that produces this message, please open an issue about it."]) Nothing @@ -296,16 +318,15 @@ -> Heap -> Term -> (Heap,Id)-newLetBinding tcm h@(Heap gh h' ids) e- | Var ty' nm' <- e- , Just _ <- lookup (nameOcc nm') h'- = (h, Id nm' (embed ty'))+newLetBinding tcm h@(Heap gh gbl h' ids is0) e+ | Var v <- e+ , Just _ <- lookupVarEnv v h'+ = (h, v) | otherwise- = (Heap gh (insert (nameOcc nm) e h') ids',Id nm (embed ty))+ = (Heap gh gbl (extendVarEnv id_ e h') ids' is1,id_) where- (i,ids') = freshId ids- nm = makeSystemName "x" (toInteger i)- ty = runFreshM (termType tcm e)+ ty = termType tcm e+ ((ids',is1),id_) = mkUniqSystemId (ids,is0) ("x",ty) newLetBindings' :: TyConMap@@ -325,88 +346,121 @@ mkAbstr = foldr go where go (Left tv) (h,e) =- (h,TyLam (bind tv (TyApp e (VarTy (unembed (varKind tv)) (varName tv)))))- go (Right ty) (Heap gh h ids,e) =- let (i,ids') = freshId ids- nm = makeSystemName "x" (toInteger i)- id_ = Id nm (embed ty)- in (Heap gh h ids',Lam (bind id_ (App e (Var ty nm))))+ (h,TyLam tv (TyApp e (VarTy tv)))+ go (Right ty) (Heap gh gbl h ids is,e) =+ let ((ids',_),id_) = mkUniqSystemId (ids,is) ("x",ty)+ in (Heap gh gbl h ids' is,Lam id_ (App e (Var id_))) -- | Force the evaluation of a variable.-force :: BindingMap -> Heap -> Stack -> Id -> Maybe State-force gbl (Heap gh h ids) k x' = case lookup nm h of- Nothing -> case HM.lookup nm gbl of- Nothing -> Nothing- Just (_,_,_,_,e) -> Just (Heap gh h ids,k,e)- Just e -> Just (Heap gh (delete nm h) ids,Update x':k,e)+force :: Heap -> Stack -> Id -> Maybe State+force (Heap gh g@(GPureHeap gbl) h ids is) k x' = case lookupVarEnv x' h of+ Nothing -> case lookupVarEnv x' gbl of+ Just e | isGlobalId x'+ -> Just (Heap gh (GPureHeap (delVarEnv gbl x')) h ids is,GUpdate x':k,e)+ _ -> Nothing+ Just e -> Just (Heap gh g (delVarEnv h x') ids is,Update x':k,e) -- Removing the heap-bound value on a force ensures we do not get stuck on -- expressions such as: "let x = x in x"- where- nm = nameOcc (varName x') -- | Unwind the stack by 1 unwind :: PrimEvaluator- -> BindingMap -> TyConMap -> Heap -> Stack -> Value -> Maybe State-unwind eval gbl tcm h k v = do+unwind eval tcm h k v = do (kf,k') <- uncons k case kf of Update x -> return (update h k' x v)+ GUpdate x -> return (gupdate h k' x v) Apply x -> return (apply h k' v x) Instantiate ty -> return (instantiate h k' v ty)- PrimApply nm ty tys vals tms -> primop eval gbl tcm h k' nm ty tys vals v tms+ PrimApply nm ty tys vals tms -> primop eval tcm h k' nm ty tys vals v tms Scrutinise _ alts -> return (scrutinise h k' v alts)+ -- Adding back the Tick constructor will make the evaluator loop+ Tickish _ -> return (h,k',valToTerm v) -- | Update the Heap with the evaluated term update :: Heap -> Stack -> Id -> Value -> State-update (Heap gh h ids) k x v = (Heap gh (insert (nameOcc (varName x)) v' h) ids,k,v')+update (Heap gh gbl h ids is) k x v = (Heap gh gbl (extendVarEnv x v' h) ids is,k,v') where v' = valToTerm v +-- | Update the Globals with the evaluated term+gupdate :: Heap -> Stack -> Id -> Value -> State+gupdate (Heap gh (GPureHeap gbl) h ids is) k x v =+ (Heap gh (GPureHeap (extendVarEnv x v' gbl)) h ids is,k,v')+ where+ v' = valToTerm v+ valToTerm :: Value -> Term valToTerm v = case v of- Lambda b -> Lam b- TyLambda b -> TyLam b+ Lambda x e -> Lam x e+ TyLambda x e -> TyLam x e DC dc pxs -> foldl' (\e a -> either (App e) (TyApp e) a) (Data dc) pxs Lit l -> Literal l PrimVal nm ty tys vs -> foldl' App (foldl' TyApp (Prim nm ty) tys) (map valToTerm vs)+ Suspend e -> e toVar :: Id -> Term-toVar x = Var (unembed (varType x)) (varName x)+toVar x = Var x toType :: TyVar -> Type-toType x = VarTy (unembed (varKind x)) (varName x)+toType x = VarTy x -- | Apply a value to a function apply :: Heap -> Stack -> Value -> Id -> State-apply h k (Lambda b) x = (h,k,subst nm (toVar x) e)- where- (x',e) = unsafeUnbind b- nm = nameOcc (varName x')+apply h@(Heap _ _ _ _ is0) k (Lambda x' e) x = (h,k,substTm "Evaluator.apply" subst e)+ where+ subst = extendIdSubst subst0 x' (Var x)+ subst0 = mkSubst (extendInScopeSet is0 x) apply _ _ _ _ = error "not a lambda" -- | Instantiate a type-abstraction instantiate :: Heap -> Stack -> Value -> Type -> State-instantiate h k (TyLambda b) ty = (h,k,subst nm ty e)- where- (x,e) = unsafeUnbind b- nm = nameOcc (varName x)+instantiate h k (TyLambda x e) ty = (h,k,substTm "Evaluator.instantiate" subst e)+ where+ subst = extendTvSubst subst0 x ty+ subst0 = mkSubst is0+ is0 = mkInScopeSet (localFVsOfTerms [e] `unionUniqSet` tyFVsOfTypes [ty]) instantiate _ _ _ _ = error "not a ty lambda" +naturalLiteral :: Value -> Maybe Integer+naturalLiteral v =+ case v of+ Lit (NaturalLiteral i) -> Just i+ DC dc [Left (Literal (WordLiteral i))]+ | dcTag dc == 1+ -> Just i+ DC dc [Left (Literal (ByteArrayLiteral (PV.Vector _ _ (BA.ByteArray ba))))]+ | dcTag dc == 2+ -> Just (Jp# (BN# ba))+ _ -> Nothing++integerLiteral :: Value -> Maybe Integer+integerLiteral v =+ case v of+ Lit (IntegerLiteral i) -> Just i+ DC dc [Left (Literal (IntLiteral i))]+ | dcTag dc == 1+ -> Just i+ DC dc [Left (Literal (ByteArrayLiteral (PV.Vector _ _ (BA.ByteArray ba))))]+ | dcTag dc == 2+ -> Just (Jp# (BN# ba))+ | dcTag dc == 3+ -> Just (Jn# (BN# ba))+ _ -> Nothing+ -- | Evaluation of primitive operations primop :: PrimEvaluator- -> BindingMap -> TyConMap -> Heap -> Stack -> Text -- ^ Name of the primitive- -> Type+ -> PrimInfo -- ^ Type of the primitive -> [Type] -- ^ Applied types@@ -417,35 +471,52 @@ -> [Term] -- ^ The remaining terms which must be evaluated to a value -> Maybe State-primop eval gbl tcm h k nm ty tys vs v []- | nm `elem` ["Clash.Sized.Internal.BitVector.fromInteger#"- ,"Clash.Sized.Internal.BitVector.fromInteger##"- ,"Clash.Sized.Internal.Index.fromInteger#"- ,"Clash.Sized.Internal.Signed.fromInteger#"- ,"Clash.Sized.Internal.Unsigned.fromInteger#"+primop eval tcm h k nm ty tys vs v []+ | nm `elem` ["Clash.Sized.Internal.Index.fromInteger#" ,"GHC.CString.unpackCString#" ,"Clash.Transformations.removedArg" ,"GHC.Prim.MutableByteArray#" ] -- The above primitives are actually values, and not operations.- = unwind eval gbl tcm h k (PrimVal nm ty tys (vs ++ [v]))- | otherwise = eval (isScrut k) gbl tcm h k nm ty tys (vs ++ [v])-primop _ _ _ h k nm ty tys vs v (e:es) =+ = unwind eval tcm h k (PrimVal nm ty tys (vs ++ [v]))+ | nm == "Clash.Sized.Internal.BitVector.fromInteger#"+ = case (vs,v) of+ ([naturalLiteral -> Just n,mask], integerLiteral -> Just i) ->+ unwind eval tcm h k (PrimVal nm ty tys [Lit (NaturalLiteral n)+ ,mask+ ,Lit (IntegerLiteral (wrapUnsigned n i))])+ _ -> error ($(curLoc) ++ "Internal error" ++ show (vs,v))+ | nm == "Clash.Sized.Internal.BitVector.fromInteger##"+ = case (vs,v) of+ ([mask], integerLiteral -> Just i) ->+ unwind eval tcm h k (PrimVal nm ty tys [mask+ ,Lit (IntegerLiteral (wrapUnsigned 1 i))])+ _ -> error ($(curLoc) ++ "Internal error" ++ show (vs,v))+ | nm == "Clash.Sized.Internal.Signed.fromInteger#"+ = case (vs,v) of+ ([naturalLiteral -> Just n],integerLiteral -> Just i) ->+ unwind eval tcm h k (PrimVal nm ty tys [Lit (NaturalLiteral n)+ ,Lit (IntegerLiteral (wrapSigned n i))])+ _ -> error ($(curLoc) ++ "Internal error" ++ show (vs,v))+ | nm == "Clash.Sized.Internal.Unsigned.fromInteger#"+ = case (vs,v) of+ ([naturalLiteral -> Just n],integerLiteral -> Just i) ->+ unwind eval tcm h k (PrimVal nm ty tys [Lit (NaturalLiteral n)+ ,Lit (IntegerLiteral (wrapUnsigned n i))])+ _ -> error ($(curLoc) ++ "Internal error" ++ show (vs,v))+ | otherwise = eval (isScrut k) tcm h k nm ty tys (vs ++ [v])+primop eval tcm h0 k nm ty tys vs v [e]+ | nm `elem` [ "Clash.Sized.Vector.lazyV"+ , "Clash.Sized.Vector.replicate"+ , "Clash.Sized.Vector.replace_int"+ ]+ = let (h1,i) = newLetBinding tcm h0 e+ in eval (isScrut k) tcm h1 k nm ty tys (vs ++ [v,Suspend (Var i)])+primop _ _ h k nm ty tys vs v (e:es) = Just (h,PrimApply nm ty tys (vs ++ [v]) es:k,e) -- | Evaluate a case-expression scrutinise :: Heap -> Stack -> Value -> [Alt] -> State-scrutinise h k (Lit l) (map unsafeUnbind -> alts)- | altE:_ <-- [altE | (LitPat (unembed -> altL),altE) <- alts, altL == l ] ++- [altE | (DataPat (unembed -> altDc) _,altE) <- alts, matchLit altDc l ] ++- [altE | (DefaultPat,altE) <- alts ]- = (h,k,altE)-scrutinise h k (DC dc xs) (map unsafeUnbind -> alts)- | altE:_ <- [substAlt altDc pxs xs altE- | (DataPat (unembed -> altDc) pxs,altE) <- alts, altDc == dc ] ++- [altE | (DefaultPat,altE) <- alts ]- = (h,k,altE) scrutinise h k v [] = (h,k,valToTerm v) -- [Note: empty case expressions] --@@ -453,36 +524,104 @@ -- are used to indicate that the `whnf` function was called the context of a -- case-expression, which means certain special primitives must be forced. -- See also [Note: forcing special primitives]-scrutinise _ _ _ _ = error "scrutinise"+scrutinise h k (Lit l) alts = case alts of+ (DefaultPat,altE):alts1 -> (h,k,go altE alts1)+ _ -> (h,k,go (error ("scrutinise: no match " +++ showPpr (Case (valToTerm (Lit l)) (ConstTy Arrow) alts))) alts)+ where+ go def [] = def+ go _ ((LitPat l1,altE):_) | l1 == l = altE+ go _ ((DataPat dc [] [x],altE):_)+ | IntegerLiteral l1 <- l+ , Just patE <- case dcTag dc of+ 1 | l1 >= ((-2)^(63::Int)) && l1 < 2^(63::Int) ->+ Just (IntLiteral l1)+ 2 | l1 >= (2^(63::Int)) ->+ let !(Jp# !(BN# ba0)) = l1+ ba1 = BA.ByteArray ba0+ bv = PV.Vector 0 (BA.sizeofByteArray ba1) ba1+ in Just (ByteArrayLiteral bv)+ 3 | l1 < ((-2)^(63::Int)) ->+ let !(Jn# !(BN# ba0)) = l1+ ba1 = BA.ByteArray ba0+ bv = PV.Vector 0 (BA.sizeofByteArray ba1) ba1+ in Just (ByteArrayLiteral bv)+ _ -> Nothing+ = let inScope = localFVsOfTerms [altE]+ subst0 = mkSubst (mkInScopeSet inScope)+ subst1 = extendIdSubst subst0 x (Literal patE)+ in substTm "Evaluator.scrutinise" subst1 altE+ | NaturalLiteral l1 <- l+ , Just patE <- case dcTag dc of+ 1 | l1 >= 0 && l1 < 2^(64::Int) ->+ Just (WordLiteral l1)+ 2 | l1 >= (2^(64::Int)) ->+ let !(Jp# !(BN# ba0)) = l1+ ba1 = BA.ByteArray ba0+ bv = PV.Vector 0 (BA.sizeofByteArray ba1) ba1+ in Just (ByteArrayLiteral bv)+ _ -> Nothing+ = let inScope = localFVsOfTerms [altE]+ subst0 = mkSubst (mkInScopeSet inScope)+ subst1 = extendIdSubst subst0 x (Literal patE)+ in substTm "Evaluator.scrutinise" subst1 altE+ go def (_:alts1) = go def alts1 -matchLit :: DataCon -> Literal -> Bool-matchLit dc (IntegerLiteral l)- | dcTag dc == 1- = l < 2^(63::Int)-matchLit dc (NaturalLiteral l)- | dcTag dc == 1- = l < 2^(64::Int)-matchLit _ _ = False+scrutinise h k (DC dc xs) alts+ | altE:_ <- [substAlt altDc tvs pxs xs altE+ | (DataPat altDc tvs pxs,altE) <- alts, altDc == dc ] +++ [altE | (DefaultPat,altE) <- alts ]+ = (h,k,altE) -substAlt :: DataCon -> Rebind [TyVar] [Id] -> [Either Term Type] -> Term -> Term-substAlt dc pxs args e =- let (tvs,xs) = unrebind pxs- substTyMap = zip (map (nameOcc.varName) tvs)- (drop (length (dcUnivTyVars dc)) (rights args))- substTmMap = zip (map (nameOcc.varName) xs) (lefts args)- in substTysinTm substTyMap (substTms substTmMap e)+scrutinise h k v@(PrimVal nm _ _ vs) alts+ | any (\case {(LitPat {},_) -> True; _ -> False}) alts+ = case alts of+ ((DefaultPat,altE):alts1) -> (h,k,go altE alts1)+ _ -> (h,k,go (error ("scrutinise: no match " +++ showPpr (Case (valToTerm v) (ConstTy Arrow) alts))) alts)+ where+ go def [] = def+ go _ ((LitPat l1,altE):_) | l1 == l = altE+ go def (_:alts1) = go def alts1 + l = case nm of+ "Clash.Sized.Internal.BitVector.fromInteger#"+ | [_,Lit (IntegerLiteral 0),Lit l0] <- vs -> l0+ "Clash.Sized.Internal.Index.fromInteger#"+ | [_,Lit l0] <- vs -> l0+ "Clash.Sized.Internal.Signed.fromInteger#"+ | [_,Lit l0] <- vs -> l0+ "Clash.Sized.Internal.Unsigned.fromInteger#"+ | [_,Lit l0] <- vs -> l0+ _ -> error ("scrutinise: " ++ showPpr (Case (valToTerm v) (ConstTy Arrow) alts))++scrutinise _ _ v alts = error ("scrutinise: " ++ showPpr (Case (valToTerm v) (ConstTy Arrow) alts))++substAlt :: DataCon -> [TyVar] -> [Id] -> [Either Term Type] -> Term -> Term+substAlt dc tvs xs args e = substTm "Evaluator.substAlt" subst e+ where+ tys = rights args+ tms = lefts args+ substTyMap = zip tvs (drop (length (dcUnivTyVars dc)) tys)+ substTmMap = zip xs tms+ inScope = tyFVsOfTypes tys `unionVarSet` localFVsOfTerms (e:tms)+ subst = extendTvSubstList (extendIdSubstList subst0 substTmMap) substTyMap+ subst0 = mkSubst (mkInScopeSet inScope)+ -- | Allocate let-bindings on the heap-allocate :: Heap -> Stack -> (Bind (Rec [LetBinding]) Term) -> State-allocate (Heap gh h ids) k b =- (Heap gh (h `union` fromList xes') ids',k,e')+allocate :: Heap -> Stack -> [LetBinding] -> Term -> State+allocate (Heap gh gbl h ids is0) k xes e =+ (Heap gh gbl (h `extendVarEnvList` xes') ids' isN,k,e') where- (xesR,e) = unsafeUnbind b- xes = unrec xesR- (ids',s) = mapAccumL (letSubst h) ids (map fst xes)+ xNms = map fst xes+ is1 = extendInScopeSetList is0 xNms+ (ids',s) = mapAccumL (letSubst h) ids xNms (nms,s') = unzip s- xes' = zip nms (map (substTms s' . unembed . snd) xes)- e' = substTms s' e+ isN = extendInScopeSetList is1 nms+ subst = extendIdSubstList subst0 s'+ subst0 = mkSubst (foldl' extendInScopeSet is1 nms)+ xes' = zip nms (map (substTm "Evaluator.allocate0" subst . snd) xes)+ e' = substTm "Evaluator.allocate1" subst e -- | Create a unique name and substitution for a let-binder letSubst@@ -490,21 +629,33 @@ -> Supply -> Id -> ( Supply- , (TmOccName,(TmOccName,Term)))-letSubst h acc id_ =- let nm = nameOcc (varName id_)- (acc',nm') = uniqueInHeap h acc nm- in (acc',(nameOcc nm',(nm,Var (unembed (varType id_)) nm')))+ , (Id,(Id,Term)))+letSubst h acc id0 =+ let (acc',id1) = uniqueInHeap h acc id0+ in (acc',(id1,(id0,Var id1))) -- | Create a name that's unique in the heap uniqueInHeap :: PureHeap -> Supply- -> TmOccName- -> (Supply, TmName)-uniqueInHeap h ids nm =- let (i,ids') = freshId ids- nm' = makeSystemName (Unbound.name2String nm) (toInteger i)- in case nameOcc nm' `M.member` h of- True -> uniqueInHeap h ids' nm- _ -> (ids',nm')+ -> Id+ -> (Supply, Id)+uniqueInHeap h ids x = case lookupVarEnv x' h of+ Just _ -> uniqueInHeap h ids' x+ _ -> (ids',x')+ where+ (i,ids') = freshId ids+ x' = modifyVarName (\nm -> nm {nameUniq = i}) x++wrapUnsigned :: Integer -> Integer -> Integer+wrapUnsigned n i = i `mod` sz+ where+ sz = 1 `shiftL` fromInteger n++wrapSigned :: Integer -> Integer -> Integer+wrapSigned n i = if mask == 0 then 0 else res+ where+ mask = 1 `shiftL` fromInteger (n - 1)+ res = case divMod i mask of+ (s,i1) | even s -> i1+ | otherwise -> i1 - mask
src/Clash/Core/FreeVars.hs view
@@ -6,22 +6,321 @@ Free variable calculations -} -module Clash.Core.FreeVars where+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ViewPatterns #-} +module Clash.Core.FreeVars+ (-- * Free variable calculation+ typeFreeVars+ , termFreeVarsX+ , freeIds+ , freeLocalVars+ , freeLocalIds+ , globalIds+ , termFreeTyVars+ , tyFVsOfTypes+ , localFVsOfTerms+ , hasLocalFreeVars+ -- * Fast+ , noFreeVarsOfType+ -- * occurrence check+ , localIdOccursIn+ , globalIdOccursIn+ , localIdDoesNotOccurIn+ , localIdsDoNotOccurIn+ , localVarsDoNotOccurIn+ -- * Internal+ , typeFreeVars'+ , termFreeVars'+ )+where++import qualified Control.Lens as Lens import Control.Lens.Fold (Fold)-import Unbound.Generics.LocallyNameless (fv)+import Control.Lens.Getter (Contravariant)+import Data.Coerce+import qualified Data.IntSet as IntSet+import Data.Monoid (All (..), Any (..)) -import Clash.Core.Term (Term, TmOccName)-import Clash.Core.Type (TyOccName, Type)+import Clash.Core.Term (Pat (..), Term (..), TickInfo (..))+import Clash.Core.Type (Type (..))+import Clash.Core.Var (Id, IdScope (..), TyVar, Var (..))+import Clash.Core.VarEnv (VarSet, unitVarSet) --- | Gives the free type-variables in a Type-typeFreeVars :: Fold Type TyOccName-typeFreeVars = fv+-- | Gives the free type-variables in a Type, implemented as a 'Fold'+--+-- The 'Fold' is closed over the types of its variables, so:+--+-- @+-- foldMapOf typeFreeVars unitVarSet ((a:* -> k) Int) = {a, k}+-- @+typeFreeVars :: Fold Type TyVar+typeFreeVars = typeFreeVars' (const True) IntSet.empty --- | Gives the free term-variables of a Term-termFreeIds :: Fold Term TmOccName-termFreeIds = fv+-- | Gives the "interesting" free variables in a Type, implemented as a 'Fold'+--+-- The 'Fold' is closed over the types of variables, so:+--+-- @+-- foldMapOf (typeFreeVars' (const True) IntSet.empty) unitVarSet ((a:* -> k) Int) = {a, k}+-- @+--+-- Note [Closing over kind variables]+--+-- Consider the type+--+-- > forall k . b -> k+--+-- where+--+-- > b :: k -> Type+--+-- When we close over the free variables of @forall k . b -> k@, i.e. @b@, then+-- the @k@ in @b :: k -> Type@ is most definitely /not/ the @k@ in+-- @forall k . b -> k@. So when a type variable is free, i.e. not in the inScope+-- set, its kind variables also aren´t; so in order to prevent collisions due to+-- shadowing we close using an empty inScope set.+--+-- See also: https://git.haskell.org/ghc.git/commitdiff/503514b94f8dc7bd9eab5392206649aee45f140b+typeFreeVars'+ :: (Contravariant f, Applicative f)+ => (forall b . Var b -> Bool)+ -- ^ Predicate telling whether a variable is interesting+ -> IntSet.IntSet+ -- ^ Uniques of the variables in scope, used by 'termFreeVars''+ -> (Var a -> f (Var a))+ -> Type+ -> f Type+typeFreeVars' interesting is f = go is where+ go inScope = \case+ VarTy tv -> tv1 <* go inScope1 (varType tv)+ where+ isInteresting = interesting tv+ tvInScope = varUniq tv `IntSet.member` inScope+ inScope1+ | tvInScope = inScope+ | otherwise = IntSet.empty -- See Note [Closing over type variables] --- | Gives the free type-variables of a Term-termFreeTyVars :: Fold Term TyOccName-termFreeTyVars = fv+ tv1 | isInteresting+ , not tvInScope+ = VarTy . coerce <$> f (coerce tv)+ | otherwise+ = pure (VarTy tv)++ ForAllTy tv ty -> ForAllTy <$> goBndr inScope tv+ <*> go (IntSet.insert (varUniq tv) inScope) ty+ AppTy l r -> AppTy <$> go inScope l <*> go inScope r+ ty -> pure ty++ 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]+ -> Term+ -> Bool+localVarsDoNotOccurIn vs e =+ 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+ -> Bool+globalIdOccursIn v e = getAny (Lens.foldMapOf globalIds (Any . (== v)) e)++-- | Calculate the /local/ free variable of an expression: the free type+-- variables and the free identifiers that are not bound in the global+-- environment.+freeLocalVars :: Fold Term (Var a)+freeLocalVars = termFreeVars' isLocalVar where+ isLocalVar (Id {idScope = GlobalId}) = False+ isLocalVar _ = True++-- | Gives the free identifiers of a Term, implemented as a 'Fold'+freeIds :: Fold Term Id+freeIds = termFreeVars' isId where+ isId (Id {}) = True+ isId _ = False++-- | Calculate the /local/ free identifiers of an expression: the free+-- identifiers that are not bound in the global environment.+freeLocalIds :: Fold Term Id+freeLocalIds = termFreeVars' isLocalId where+ isLocalId (Id {idScope = LocalId}) = True+ isLocalId _ = False++-- | Calculate the /global/ free identifiers of an expression: the free+-- identifiers that are bound in the global environment.+globalIds :: Fold Term Id+globalIds = termFreeVars' isGlobalId where+ 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:+--+-- @+-- foldMapOf termFreeTyVars unitVarSet (case (x : (a:* -> k) Int)) of {}) = {a, k}+-- @+termFreeTyVars :: Fold Term TyVar+termFreeTyVars = termFreeVars' isTV where+ isTV (TyVar {}) = True+ isTV _ = False++-- | Gives the free variables of a Term, implemented as a 'Fold'+--+-- The 'Fold' is closed over the types of variables, so:+--+-- @+-- foldMapOf termFreeVars unitVarSet (case (x : (a:* -> k) Int)) of {}) = {x, a, k}+-- @+--+-- __NB__ this collects both global and local IDs, and you almost __NEVER__ want+-- to use this. Use one of the other FV calculations instead+termFreeVarsX :: Fold Term (Var a)+termFreeVarsX = termFreeVars' (const True)++-- | Gives the "interesting" free variables in a Term, implemented as a 'Fold'+--+-- The 'Fold' is closed over the types of variables, so:+--+-- @+-- foldMapOf (termFreeVars' (const True)) unitVarSet (case (x : (a:* -> k) Int)) of {}) = {x, a, k}+-- @+--+-- Note [Closing over type variables]+--+-- Consider the term+--+-- > /\(k :: Type) -> \(b :: k) -> a+--+-- where+--+-- > a :: k+--+-- When we close over the free variables of @/\k -> \(b :: k) -> (a :: k)@, i.e.+-- @a@, then the @k@ in @a :: k@ is most definitely /not/ the @k@ in introduced+-- by the @/\k ->@. So when a term variable is free, i.e. not in the inScope+-- set, its type variables also aren´t; so in order to prevent collisions due to+-- shadowing we close using an empty inScope set.+--+-- See also: https://git.haskell.org/ghc.git/commitdiff/503514b94f8dc7bd9eab5392206649aee45f140b+termFreeVars'+ :: (Contravariant f, Applicative f)+ => (forall b . Var b -> Bool)+ -- ^ Predicate telling whether a variable is interesting+ -> (Var a -> f (Var a))+ -> Term+ -> f Term+termFreeVars' interesting f = go IntSet.empty where+ go inScope = \case+ Var v -> v1 <* typeFreeVars' interesting inScope1 f (varType v)+ where+ isInteresting = interesting v+ vInScope = varUniq v `IntSet.member` inScope+ inScope1+ | vInScope = inScope+ | otherwise = IntSet.empty -- See Note [Closing over type variables]++ v1 | isInteresting+ , not vInScope+ = Var . coerce <$> f (coerce v)+ | otherwise+ = pure (Var v)++ Lam id_ tm -> Lam <$> goBndr inScope id_+ <*> go (IntSet.insert (varUniq id_) inScope) tm+ TyLam tv tm -> TyLam <$> goBndr inScope tv+ <*> go (IntSet.insert (varUniq tv) inScope) tm+ App l r -> App <$> go inScope l <*> go inScope r+ TyApp l r -> TyApp <$> go inScope l+ <*> typeFreeVars' interesting inScope f r+ Letrec bs e -> Letrec <$> traverse (goBind inScope') bs <*> go inScope' e+ where inScope' = foldr IntSet.insert inScope (map (varUniq.fst) bs)+ Case subj ty alts -> Case <$> go inScope subj+ <*> typeFreeVars' interesting inScope f ty+ <*> traverse (goAlt inScope) alts+ Cast tm t1 t2 -> Cast <$> go inScope tm+ <*> typeFreeVars' interesting inScope f t1+ <*> typeFreeVars' interesting inScope f t2+ Tick tick tm -> Tick <$> goTick inScope tick <*> go inScope tm+ tm -> pure tm++ goBndr inScope v =+ (\t -> v {varType = t}) <$> typeFreeVars' interesting inScope f (varType v)++ goBind inScope (l,r) = (,) <$> goBndr inScope l <*> go inScope r++ goAlt inScope (pat,alt) = case pat of+ DataPat dc tvs ids -> (,) <$> (DataPat <$> pure dc+ <*> traverse (goBndr inScope') tvs+ <*> traverse (goBndr inScope') ids)+ <*> go inScope' alt+ where+ inScope' = foldr IntSet.insert+ (foldr IntSet.insert inScope (map varUniq tvs))+ (map varUniq ids)+ _ -> (,) <$> pure pat <*> go inScope alt++ goTick inScope = \case+ NameMod m ty -> NameMod m <$> typeFreeVars' interesting inScope 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
src/Clash/Core/Literal.hs view
@@ -20,12 +20,12 @@ where import Control.DeepSeq (NFData (..))+import Data.Binary (Binary)+import Data.Vector.Binary () import Data.Hashable (Hashable) import Data.Vector.Primitive.Extra (Vector) import Data.Word (Word8) import GHC.Generics (Generic)-import Unbound.Generics.LocallyNameless.Extra ()-import Unbound.Generics.LocallyNameless (Alpha (..), Subst (..)) import {-# SOURCE #-} Clash.Core.Type (Type) import Clash.Core.TysPrim (intPrimTy, integerPrimTy,@@ -48,14 +48,7 @@ | CharLiteral !Char | NaturalLiteral !Integer | ByteArrayLiteral !(Vector Word8)- deriving (Eq,Ord,Show,Generic,NFData,Hashable)--instance Alpha Literal where- fvAny' _ _ l = pure l--instance Subst a Literal where- subst _ _ l = l- substs _ l = l+ deriving (Eq,Ord,Show,Generic,NFData,Hashable,Binary) -- | Determines the Type of a Literal literalType :: Literal
src/Clash/Core/Name.hs view
@@ -10,6 +10,7 @@ {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-} module Clash.Core.Name@@ -19,81 +20,61 @@ where import Control.DeepSeq (NFData)+import Data.Binary (Binary) import Data.Function (on)-import Data.Hashable (Hashable)-import Data.Typeable (Typeable)+import Data.Hashable (Hashable (..))+import Data.Text (Text, append)+import GHC.BasicTypes.Extra () import GHC.Generics (Generic) import GHC.SrcLoc.Extra ()-import Unbound.Generics.LocallyNameless hiding- (Name, name2String, string2Name)-import qualified Unbound.Generics.LocallyNameless as Unbound-import qualified Unbound.Generics.LocallyNameless.Name as Unbound-import Unbound.Generics.LocallyNameless.TH-import Unbound.Generics.LocallyNameless.Extra () import SrcLoc (SrcSpan, noSrcSpan) +import Clash.Unique+ data Name a = Name { nameSort :: NameSort- , nameOcc :: OccName a+ , nameOcc :: !OccName+ , nameUniq :: {-# UNPACK #-} !Unique , nameLoc :: !SrcSpan }- deriving (Show,Generic,NFData,Hashable)+ deriving (Show,Generic,NFData,Binary) instance Eq (Name a) where- (==) = (==) `on` nameOcc+ (==) = (==) `on` nameUniq+ (/=) = (/=) `on` nameUniq instance Ord (Name a) where- compare = compare `on` nameOcc+ compare = compare `on` nameUniq -type OccName a = Unbound.Name a+instance Hashable (Name a) where+ hashWithSalt salt nm = hashWithSalt salt (nameUniq nm) +instance Uniquable (Name a) where+ getUnique = nameUniq++type OccName = Text+ data NameSort = User | System | Internal- deriving (Eq,Ord,Show,Generic,NFData,Hashable)--instance Typeable a => Alpha (Name a) where- aeq' ctx (Name _ nm1 _) (Name _ nm2 _) = aeq' ctx nm1 nm2- acompare' ctx (Name _ nm1 _) (Name _ nm2 _) = acompare' ctx nm1 nm2--makeClosedAlpha ''NameSort--instance Subst b (Name a) where subst _ _ = id; substs _ = id--name2String :: Name a -> String-name2String = Unbound.name2String . nameOcc-{-# INLINE name2String #-}--name2Integer :: Name a -> Integer-name2Integer = Unbound.name2Integer . nameOcc--string2OccName :: String -> OccName a-string2OccName = Unbound.string2Name-{-# INLINE string2OccName #-}--string2SystemName :: String -> Name a-string2SystemName nm = Name System (string2OccName nm) noSrcSpan--string2InternalName :: String -> Name a-string2InternalName nm = Name Internal (string2OccName ('#':nm)) noSrcSpan--makeOccName :: String -> Integer -> OccName a-makeOccName = Unbound.makeName+ deriving (Eq,Ord,Show,Generic,NFData,Hashable,Binary) -makeSystemName :: String -> Integer -> Name a-makeSystemName s i = Name System (makeOccName s i) noSrcSpan+mkUnsafeSystemName+ :: Text+ -> Unique+ -> Name a+mkUnsafeSystemName s i = Name System s i noSrcSpan -coerceName :: Name a -> Name b-coerceName nm = nm {nameOcc = go (nameOcc nm)}- where- go (Unbound.Fn s i) = Unbound.Fn s i- go _ = error "Trying to coerce bound name"+mkUnsafeInternalName+ :: Text+ -> Unique+ -> Name a+mkUnsafeInternalName s i = Name Internal ("c$" `append` s) i noSrcSpan -appendToName :: Name a -> String -> Name a-appendToName (Name sort nm loc) s = Name Internal nm' loc+appendToName :: Name a -> Text -> Name a+appendToName (Name sort nm uniq loc) s = Name Internal nm2 uniq loc where- n = Unbound.name2String nm- n' = case sort of {Internal -> n; _ -> '#':n}- nm' = Unbound.makeName (n' ++ s) (Unbound.name2Integer nm)+ nm1 = case sort of {Internal -> nm; _ -> "c$" `append` nm}+ nm2 = nm1 `append` s
src/Clash/Core/Pretty.hs view
@@ -4,369 +4,467 @@ License : BSD2 (see the file LICENSE) Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com> - Pretty printing class and instances for CoreHW+ PrettyPrec printing class and instances for CoreHW -} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE LambdaCase #-} +{-# OPTIONS_GHC -fno-warn-orphans #-}+ module Clash.Core.Pretty- ( Pretty (..)- , showDoc+ ( PrettyPrec (..)+ , PrettyOptions (..)+ , ClashDoc+ , ClashAnnotation (..)+ , SyntaxElement (..)+ , ppr, ppr'+ , showPpr, showPpr'+ , tracePprId+ , tracePpr+ , fromPpr ) where import Data.Char (isSymbol, isUpper, ord) import Data.Text (Text)-import Data.Text.Prettyprint.Doc hiding (Doc, Pretty)-import qualified Data.Text.Prettyprint.Doc as PP-import Data.Text.Prettyprint.Doc.Render.String+import Control.Monad.Identity+import qualified Data.Text as T+import Data.Text.Prettyprint.Doc+import Data.Text.Prettyprint.Doc.Internal+import Debug.Trace (trace) import GHC.Show (showMultiLineString) import Numeric (fromRat)-import Unbound.Generics.LocallyNameless- (Embed (..), LFresh, lunbind, runLFreshM, unembed, unrebind, unrec)+import qualified Outputable as GHC import Clash.Core.DataCon (DataCon (..)) import Clash.Core.Literal (Literal (..))-import Clash.Core.Name (Name (..), OccName, name2String)-import Clash.Core.Term (Pat (..), Term (..))+import Clash.Core.Name (Name (..))+import Clash.Core.Term+ (Pat (..), Term (..), TickInfo (..), NameMod (..), CoreContext (..), primArg) import Clash.Core.TyCon (TyCon (..), TyConName, isTupleTyConLike) import Clash.Core.Type (ConstTy (..), Kind, LitTy (..), Type (..), TypeView (..), tyView)-import Clash.Core.Var (Id, TyVar, Var, varKind, varName,- varType)+import Clash.Core.Var (Id, TyVar, Var (..)) import Clash.Util+import Clash.Pretty -type Doc = PP.Doc ()+-- | Options for the pretty-printer, controlling which elements to hide.+data PrettyOptions = PrettyOptions+ { displayUniques :: Bool+ -- ^ whether to display unique identifiers+ , displayTypes :: Bool+ -- ^ whether to display type information+ , displayQualifiers :: Bool+ -- ^ whether to display module qualifiers+ } --- | Pretty printing Show-like typeclass-class Pretty p where- ppr :: LFresh m => p -> m Doc- ppr = pprPrec 0+-- | Annotations carried on pretty-printed code.+data ClashAnnotation+ = AnnContext CoreContext+ -- ^ marking navigation to a different context+ | AnnSyntax SyntaxElement+ -- ^ marking a specific sort of syntax+ deriving Eq - pprPrec :: LFresh m => Rational -> p -> m Doc+-- | Specific places in the program syntax.+data SyntaxElement = Keyword | LitS | Type | Unique | Qualifier+ deriving (Eq, Show) +-- | Clash's specialized @Doc@ type holds metadata of type @ClashAnnotation@.+type ClashDoc = Doc ClashAnnotation++-- | PrettyPrec printing Show-like typeclass+class PrettyPrec p where++ -- default pretty-printing without hiding+ pprPrec :: Monad m => Rational -> p -> m ClashDoc++ -- pretty-printing with hiding options+ -- NB: we utilise the syntax annotations to hide the requested parts of syntax+ pprPrec' :: Monad m => PrettyOptions -> Rational -> p -> m ClashDoc+ pprPrec' opts p = fmap hide . pprPrec p+ where+ hide = \case+ FlatAlt d d' -> FlatAlt (hide d) (hide d')+ Cat d d' -> Cat (hide d) (hide d')+ Nest i d -> Nest i (hide d)+ Union d d' -> Union (hide d) (hide d')+ Column f -> Column (hide . f)+ WithPageWidth f -> WithPageWidth (hide . f)+ Nesting f -> Nesting (hide . f)+ Annotated ann d' ->+ if not (displayTypes opts) && ann == AnnSyntax Type+ || not (displayUniques opts) && ann == AnnSyntax Unique+ || not (displayQualifiers opts) && ann == AnnSyntax Qualifier+ then Empty+ else Annotated ann (hide d')+ d -> d++pprM :: (Monad m, PrettyPrec p) => p -> m ClashDoc+pprM = pprPrec 0++pprM' :: (Monad m, PrettyPrec p) => PrettyOptions -> p -> m ClashDoc+pprM' opts = pprPrec' opts 0++ppr :: PrettyPrec p => p -> ClashDoc+ppr = runIdentity . pprM++ppr' :: PrettyPrec p => PrettyOptions -> p -> ClashDoc+ppr' opts = runIdentity . pprM' opts++fromPpr :: PrettyPrec a => a -> Doc ()+fromPpr = removeAnnotations . ppr+ noPrec, opPrec, appPrec :: Num a => a noPrec = 0 opPrec = 1 appPrec = 2 --- | Print a Pretty thing to a String-showDoc :: Pretty p => p -> String-showDoc = renderString . layoutPretty (LayoutOptions (AvailablePerLine 80 0.6)) . runLFreshM . ppr+-- | Print a PrettyPrec thing to a String+showPpr :: PrettyPrec p => p -> String+showPpr = showDoc . ppr -prettyParen :: Bool -> Doc -> Doc-prettyParen False = id-prettyParen True = parens+showPpr' :: PrettyPrec p => PrettyOptions -> p -> String+showPpr' opts = showDoc . ppr' opts -instance Pretty (OccName a) where- pprPrec _ = return . PP.pretty . show+tracePprId :: PrettyPrec p => p -> p+tracePprId p = trace (showPpr p) p -instance Pretty (Name a) where- pprPrec p = pprPrec p . nameOcc+tracePpr :: PrettyPrec p => p -> a -> a+tracePpr p a = trace (showPpr p) a -instance Pretty a => Pretty [a] where- pprPrec prec xs = do- xs' <- mapM (pprPrec prec) xs- return $ vcat xs'+parensIf :: Bool -> ClashDoc -> ClashDoc+parensIf False = id+parensIf True = parens -instance Pretty (Id, Term) where+tyParens :: ClashDoc -> ClashDoc+tyParens = enclose (annotate (AnnSyntax Type) lparen)+ (annotate (AnnSyntax Type) rparen)++tyParensIf :: Bool -> ClashDoc -> ClashDoc+tyParensIf False = id+tyParensIf True = tyParens++vsepHard :: [ClashDoc] -> ClashDoc+vsepHard = concatWith (\x y -> x <> hardline <> y)++viewName :: Name a -> (Text, Text, Text)+viewName n = (qual, occ, T.pack $ show $ nameUniq n)+ where (qual, occ) = T.breakOnEnd "." $ nameOcc n++instance PrettyPrec (Name a) where+ pprPrec p (viewName -> (qual, occ, uniq)) = do+ qual' <- annotate (AnnSyntax Qualifier) <$> pprPrec p qual+ occ' <- pprPrec p occ+ uniq' <- annotate (AnnSyntax Unique) <$> pprPrec p uniq+ return $ qual' <> occ' <> uniq'++instance ClashPretty (Name a) where+ clashPretty = fromPpr++instance PrettyPrec a => PrettyPrec [a] where+ pprPrec prec = fmap vcat . mapM (pprPrec prec)++instance PrettyPrec (Id, Term) where pprPrec _ = pprTopLevelBndr -pprTopLevelBndr :: LFresh m => (Id,Term) -> m Doc+pprTopLevelBndr :: Monad m => (Id,Term) -> m ClashDoc pprTopLevelBndr (bndr,expr) = do- bndr' <- ppr bndr- bndrName <- ppr (varName bndr)- expr' <- ppr expr+ bndr' <- pprM bndr+ bndrName <- pprM (varName bndr)+ expr' <- pprM expr return $ bndr' <> line <> hang 2 (sep [(bndrName <+> equals), expr']) <> line -dcolon :: Doc-dcolon = PP.pretty "::"--rarrow :: Doc-rarrow = PP.pretty "->"+dcolon, rarrow, lam, tylam, at, cast, coerce, letrec, in_, case_, of_, forall_+ :: ClashDoc+[dcolon, rarrow, lam, tylam, at, cast, coerce, letrec, in_, case_, of_, forall_]+ = annotate (AnnSyntax Keyword) <$>+ ["::", "->", "λ", "Λ", "@", "▷", "~", "letrec", "in", "case", "of", "forall"] -instance Pretty Text where- pprPrec _ = pure . PP.pretty+instance PrettyPrec Text where+ pprPrec _ = pure . pretty -instance Pretty Type where- pprPrec _ = pprType+instance PrettyPrec Type where+ pprPrec _ t = annotate (AnnSyntax Type) <$> pprType t -instance Pretty (Var Type) where- pprPrec _ v = ppr $ varName v+instance ClashPretty Type where+ clashPretty = fromPpr -instance Pretty TyCon where- pprPrec _ tc = return . PP.pretty . name2String $ tyConName tc+instance PrettyPrec TyCon where+ pprPrec _ t = pprM (tyConName t) instance Pretty LitTy where- pprPrec _ (NumTy i) = return $ PP.pretty i- pprPrec _ (SymTy s) = return $ PP.pretty s+ pretty (NumTy i) = pretty i+ pretty (SymTy s) = dquotes $ pretty s -instance Pretty Term where+instance PrettyPrec LitTy where+ pprPrec _ = return . annotate (AnnSyntax LitS) . pretty++instance PrettyPrec Term where pprPrec prec e = case e of- Var _ x -> pprPrec prec x- Data dc -> pprPrec prec dc- Literal l -> pprPrec prec l- Prim nm _ -> return $ PP.pretty nm- Lam b -> lunbind b $ \(v,e') -> pprPrecLam prec [v] e'- TyLam b -> lunbind b $ \(tv,e') -> pprPrecTyLam prec [tv] e'- App fun arg -> pprPrecApp prec fun arg- TyApp e' ty -> pprPrecTyApp prec e' ty- Letrec b -> lunbind b $ \(xes,e') -> pprPrecLetrec prec (unrec xes) e'- Case e' _ alts -> pprPrecCase prec e' =<< mapM (`lunbind` return) alts- Cast e' ty1 ty2-> pprPrecCast prec e' ty1 ty2+ Var x -> pprPrec prec (varName x)+ Data dc -> pprPrec prec dc+ Literal l -> pprPrec prec l+ Prim nm _ -> pprPrecPrim prec nm+ Lam v e1 -> annotate (AnnContext $ LamBody v) <$>+ pprPrecLam prec [v] e1+ TyLam tv e1 -> annotate (AnnContext $ TyLamBody tv) <$>+ pprPrecTyLam prec [tv] e1+ App fun arg -> pprPrecApp prec fun arg+ TyApp e' ty -> annotate (AnnContext TyAppC) <$>+ pprPrecTyApp prec e' ty+ Letrec xes e1 -> pprPrecLetrec prec xes e1+ Case e' _ alts -> pprPrecCase prec e' alts+ Cast e' ty1 ty2 -> pprPrecCast prec e' ty1 ty2+ Tick t e' -> do+ tDoc <- pprPrec prec t+ eDoc <- pprPrec prec e'+ return (tDoc <> line' <> eDoc) -data BindingSite- = LambdaBind- | CaseBind- | LetBind+instance PrettyPrec TickInfo where+ pprPrec prec (SrcSpan sp) = pprPrec prec sp+ pprPrec prec (NameMod PrefixName t) = ("<prefixName>" <>) <$> pprPrec prec t+ pprPrec prec (NameMod SuffixName t) = ("<suffixName>" <>) <$> pprPrec prec t+ pprPrec prec (NameMod SetName t) = ("<setName>" <>) <$> pprPrec prec t -instance Pretty (Var Term) where- pprPrec _ v = do- v' <- ppr (varName v)- ty' <- ppr (unembed $ varType v)- return $ v' <+> dcolon <+> ty'+instance PrettyPrec SrcSpan where+ pprPrec _ sp = return ("<src>"<>pretty (GHC.showSDocUnsafe (GHC.ppr sp))) -instance Pretty DataCon where- pprPrec _ dc = return . PP.pretty . name2String $ dcName dc+instance ClashPretty Term where+ clashPretty = fromPpr -instance Pretty Literal where- pprPrec _ l = case l of+data BindingSite = LambdaBind | CaseBind | LetBind++instance PrettyPrec (Var a) where+ pprPrec _ v@(TyVar {}) = pprM $ varName v+ pprPrec _ v@(Id {}) = do+ v' <- pprM (varName v)+ ty' <- pprM (varType v)+ return $ v' <> (annotate (AnnSyntax Type) $ align (space <> dcolon <+> ty'))++instance ClashPretty (Var a) where+ clashPretty = fromPpr++instance PrettyPrec DataCon where+ pprPrec _ = pprM . dcName++instance PrettyPrec Literal where+ pprPrec _ l = return $ annotate (AnnSyntax LitS) $ case l of IntegerLiteral i- | i < 0 -> return $ parens (PP.pretty i)- | otherwise -> return $ PP.pretty i+ | i < 0 -> parens (pretty i)+ | otherwise -> pretty i IntLiteral i- | i < 0 -> return $ parens (PP.pretty i)- | otherwise -> return $ PP.pretty i+ | i < 0 -> parens (pretty i)+ | otherwise -> pretty i Int64Literal i- | i < 0 -> return $ parens (PP.pretty i)- | otherwise -> return $ PP.pretty i- WordLiteral w -> return $ PP.pretty w- Word64Literal w -> return $ PP.pretty w- FloatLiteral r -> return $ PP.pretty (fromRat r :: Float)- DoubleLiteral r -> return $ PP.pretty (fromRat r :: Double)- CharLiteral c -> return $ PP.pretty c- StringLiteral s -> return $ vcat $ map PP.pretty $ showMultiLineString s- NaturalLiteral n -> return $ PP.pretty n- ByteArrayLiteral s -> return $ PP.pretty $ show s+ | i < 0 -> parens (pretty i)+ | otherwise -> pretty i+ WordLiteral w -> pretty w+ Word64Literal w -> pretty w+ FloatLiteral r -> pretty (fromRat r :: Float)+ DoubleLiteral r -> pretty (fromRat r :: Double)+ CharLiteral c -> pretty c+ StringLiteral s -> vcat $ map pretty $ showMultiLineString s+ NaturalLiteral n -> pretty n+ ByteArrayLiteral s -> pretty $ show s -instance Pretty Pat where+instance PrettyPrec Pat where pprPrec prec pat = case pat of- DataPat dc pxs -> do- let (txs,xs) = unrebind pxs- dc' <- ppr (unembed dc)+ DataPat dc txs xs -> do+ dc' <- pprM dc txs' <- mapM (pprBndr LetBind) txs xs' <- mapM (pprBndr CaseBind) xs- return $ prettyParen (prec >= appPrec) $ dc' <+> hsep txs' <> softline <> (nest 2 (vcat xs'))- LitPat l -> ppr (unembed l)- DefaultPat -> return $ PP.pretty '_'+ return $ parensIf (prec >= appPrec) $+ sep [ hsep (dc':txs')+ , nest 2 (sep xs') ]+ LitPat l -> pprM l+ DefaultPat -> return "_" -pprPrecLam :: LFresh m => Rational -> [Id] -> Term -> m Doc+pprPrecPrim :: Monad m => Rational -> Text -> m ClashDoc+pprPrecPrim prec nm =+ (<>) <$> (annotate (AnnSyntax Qualifier) <$> pprPrec prec qual)+ <*> pprPrec prec occ+ where (qual, occ) = T.breakOnEnd "." nm++pprPrecLam :: Monad m => Rational -> [Id] -> Term -> m ClashDoc pprPrecLam prec xs e = do xs' <- mapM (pprBndr LambdaBind) xs e' <- pprPrec noPrec e- return $ prettyParen (prec > noPrec) $- PP.pretty 'λ' <> hsep xs' <+> rarrow <> line <> e'+ return $ parensIf (prec > noPrec) $+ lam <> hsep xs' <+> rarrow <> line <> e' -pprPrecTyLam :: LFresh m => Rational -> [TyVar] -> Term -> m Doc+pprPrecTyLam :: Monad m => Rational -> [TyVar] -> Term -> m ClashDoc pprPrecTyLam prec tvs e = do- tvs' <- mapM ppr tvs+ tvs' <- mapM pprM tvs e' <- pprPrec noPrec e- return $ prettyParen (prec > noPrec) $- PP.pretty 'Λ' <> hsep tvs' <+> rarrow <> line <> e'+ return $ tyParensIf (prec > noPrec) $+ annotate (AnnSyntax Type) (tylam <> hsep tvs' <+> rarrow <> line) <> e' -pprPrecApp :: LFresh m => Rational -> Term -> Term -> m Doc+pprPrecApp :: Monad m => Rational -> Term -> Term -> m ClashDoc pprPrecApp prec e1 e2 = do- e1' <- pprPrec opPrec e1- e2' <- pprPrec appPrec e2- return $ prettyParen (prec >= appPrec) $- hang 2 (vsep [e1',e2'])+ e1' <- annotate (AnnContext AppFun) <$> pprPrec opPrec e1+ e2' <- annotate (AnnContext $ AppArg $ primArg e2) <$> pprPrec appPrec e2+ return $ parensIf (prec >= appPrec) $+ hang 2 (sep [e1',e2']) -pprPrecTyApp :: LFresh m => Rational -> Term -> Type -> m Doc+pprPrecTyApp :: Monad m => Rational -> Term -> Type -> m ClashDoc pprPrecTyApp prec e ty = do- e' <- pprPrec opPrec e+ e' <- pprPrec opPrec e ty' <- pprParendType ty- return $ prettyParen (prec >= appPrec) $- hang 2 (sep [e', (PP.pretty '@' <> ty')])+ return $ tyParensIf (prec >= appPrec) $+ hang 2 $ group $+ e' <> annotate (AnnSyntax Type) (line <> at <> ty') --- TODO use more conventional cast operator (|> or ▷) ?-pprPrecCast :: LFresh m => Rational -> Term -> Type -> Type -> m Doc+pprPrecCast :: Monad m => Rational -> Term -> Type -> Type -> m ClashDoc pprPrecCast prec e ty1 ty2 = do- e' <- pprPrec appPrec e+ e' <- annotate (AnnContext CastBody) <$> pprPrec appPrec e ty1' <- pprType ty1 ty2' <- pprType ty2- return $ prettyParen (prec >= appPrec) $- parens (PP.pretty "cast" <> softline <> nest 5 (vcat [dcolon <+> ty1', rarrow <+> ty2']))- <> softline <> nest 2 e'+ return $ tyParensIf (prec >= appPrec) $+ e' <> annotate (AnnSyntax Type)+ (softline <> nest 2 (vsep [cast, ty1', coerce, ty2'])) -pprPrecLetrec :: LFresh m => Rational -> [(Id, Embed Term)] -> Term -> m Doc+pprPrecLetrec :: Monad m => Rational -> [(Id, Term)] -> Term -> m ClashDoc pprPrecLetrec prec xes body = do- body' <- pprPrec noPrec body+ let bndrs = fst <$> xes+ body' <- annotate (AnnContext $ LetBody bndrs) <$> pprPrec noPrec body xes' <- mapM (\(x,e) -> do x' <- pprBndr LetBind x- e' <- pprPrec noPrec (unembed e)- return $ x' <> line <> equals <+> e'+ e' <- pprPrec noPrec e+ return $ annotate (AnnContext $ LetBinding x bndrs) $+ vsepHard [x', equals <+> e'] ) xes- let xes'' = case xes' of- [] -> [PP.pretty "EmptyLetrec"]- _ -> xes'- return $ prettyParen (prec > noPrec) $- hang 2 (vcat ((PP.pretty "letrec"):xes'')) <> line <> PP.pretty "in" <+> body'+ let xes'' = case xes' of { [] -> ["EmptyLetrec"]; _ -> xes' }+ return $ parensIf (prec > noPrec) $+ vsepHard [hang 2 (vsepHard $ letrec : xes''), in_ <+> body'] -pprPrecCase :: LFresh m => Rational -> Term -> [(Pat,Term)] -> m Doc+pprPrecCase :: Monad m => Rational -> Term -> [(Pat,Term)] -> m ClashDoc pprPrecCase prec e alts = do- e' <- pprPrec prec e+ e' <- annotate (AnnContext CaseScrut) <$> pprPrec prec e alts' <- mapM (pprPrecAlt noPrec) alts- return $ prettyParen (prec > noPrec) $- hang 2 (vcat ((PP.pretty "case" <+> e' <+> PP.pretty "of"):alts'))+ return $ parensIf (prec > noPrec) $+ hang 2 $ vsepHard $ (case_ <+> e' <+> of_) : alts' -pprPrecAlt :: LFresh m => Rational -> (Pat,Term) -> m Doc+pprPrecAlt :: Monad m => Rational -> (Pat,Term) -> m ClashDoc pprPrecAlt _ (altPat, altE) = do altPat' <- pprPrec noPrec altPat altE' <- pprPrec noPrec altE- return $ hang 2 (vcat [(altPat' <+> rarrow), altE'])+ return $ annotate (AnnContext $ CaseAlt altPat) $+ hang 2 $ vsepHard [(altPat' <+> rarrow), altE'] -pprBndr :: (LFresh m, Pretty a) => BindingSite -> a -> m Doc-pprBndr bs x = prettyParen needsParen <$> ppr x- where- needsParen = case bs of- LambdaBind -> True- CaseBind -> True- LetBind -> False+pprBndr :: (Monad m, PrettyPrec a) => BindingSite -> a -> m ClashDoc+pprBndr LetBind = pprM+pprBndr _ = fmap tyParens . pprM -data TypePrec- = TopPrec- | FunPrec- | TyConPrec- deriving (Eq,Ord)+data TypePrec = TopPrec | FunPrec | TyConPrec deriving (Eq,Ord) -maybeParen :: TypePrec -> TypePrec -> Doc -> Doc-maybeParen ctxt_prec inner_prec = prettyParen (ctxt_prec >= inner_prec)+maybeParen :: TypePrec -> TypePrec -> ClashDoc -> ClashDoc+maybeParen ctxt_prec inner_prec = parensIf (ctxt_prec >= inner_prec) -pprType :: LFresh m => Type -> m Doc+pprType :: Monad m => Type -> m ClashDoc pprType = ppr_type TopPrec -pprParendType :: LFresh m => Type -> m Doc+pprParendType :: Monad m => Type -> m ClashDoc pprParendType = ppr_type TyConPrec -ppr_type :: LFresh m => TypePrec -> Type -> m Doc-ppr_type _ (VarTy _ tv) = ppr tv-ppr_type _ (LitTy tyLit) = ppr tyLit-ppr_type p ty@(ForAllTy _) = pprForAllType p ty+ppr_type :: Monad m => TypePrec -> Type -> m ClashDoc+ppr_type _ (VarTy tv) = pprM tv+ppr_type _ (LitTy tyLit) = pprM tyLit+ppr_type p ty@(ForAllTy {}) = pprForAllType p ty ppr_type p (ConstTy (TyCon tc)) = pprTcApp p ppr_type tc []+ppr_type p (AnnType _ann typ) = ppr_type p typ ppr_type p (tyView -> TyConApp tc args) = pprTcApp p ppr_type tc args-ppr_type p (tyView -> FunTy ty1 ty2) = pprArrowChain p <$> ppr_type FunPrec ty1 <:> pprFunTail ty2+ppr_type p (tyView -> FunTy ty1 ty2)+ = pprArrowChain <$> ppr_type FunPrec ty1 <:> pprFunTail ty2 where- pprFunTail (tyView -> FunTy ty1' ty2') = ppr_type FunPrec ty1' <:> pprFunTail ty2'- pprFunTail otherTy = ppr_type TopPrec otherTy <:> pure []+ pprFunTail (tyView -> FunTy ty1' ty2')+ = ppr_type FunPrec ty1' <:> pprFunTail ty2'+ pprFunTail otherTy+ = ppr_type TopPrec otherTy <:> pure [] -ppr_type p (AppTy ty1 ty2) = maybeParen p TyConPrec <$> ((<+>) <$> pprType ty1 <*> ppr_type TyConPrec ty2)+ pprArrowChain []+ = emptyDoc+ pprArrowChain (arg:args)+ = maybeParen p FunPrec $ sep [arg, sep (map (rarrow <+>) args)]++ppr_type p (AppTy ty1 ty2) = maybeParen p TyConPrec <$> ((<+>) <$> pprType ty1+ <*> ppr_type TyConPrec ty2) ppr_type _ (ConstTy Arrow) = return (parens rarrow) -pprForAllType :: LFresh m => TypePrec -> Type -> m Doc+pprForAllType :: Monad m => TypePrec -> Type -> m ClashDoc pprForAllType p ty = maybeParen p FunPrec <$> pprSigmaType True ty -pprSigmaType :: LFresh m => Bool -> Type -> m Doc+pprSigmaType :: Monad m => Bool -> Type -> m ClashDoc pprSigmaType showForalls ty = do (tvs, rho) <- split1 [] ty sep <$> sequenceA [ if showForalls then pprForAll tvs else pure emptyDoc , pprType rho ] where- split1 tvs (ForAllTy b) =- lunbind b $ \(tv,resTy) -> split1 (tv:tvs) resTy- split1 tvs resTy = return (reverse tvs,resTy)+ split1 tvs (ForAllTy tv resTy) = split1 (tv:tvs) resTy+ split1 tvs resTy = return (reverse tvs,resTy) -pprForAll :: LFresh m => [TyVar] -> m Doc-pprForAll [] = return emptyDoc+pprForAll :: Monad m => [TyVar] -> m ClashDoc+pprForAll [] = return emptyDoc pprForAll tvs = do tvs' <- mapM pprTvBndr tvs- return $ PP.pretty '∀' <+> sep tvs' <> PP.dot+ return $ forall_ <+> sep tvs' <> dot -pprTvBndr :: LFresh m => TyVar -> m Doc-pprTvBndr tv- = do- tv' <- ppr tv- kind' <- pprKind kind- return $ parens (tv' <+> dcolon <+> kind')- where- kind = unembed $ varKind tv+pprTvBndr :: Monad m => TyVar -> m ClashDoc+pprTvBndr tv = do+ tv' <- pprM tv+ kind' <- pprKind (varType tv)+ return $ tyParens $ tv' <> (annotate (AnnSyntax Type) $ space <> dcolon <+> kind') -pprKind :: LFresh m => Kind -> m Doc+pprKind :: Monad m => Kind -> m ClashDoc pprKind = pprType -pprTcApp :: LFresh m => TypePrec -> (TypePrec -> Type -> m Doc)- -> TyConName -> [Type] -> m Doc-pprTcApp _ _ tc []- = return . PP.pretty $ name2String tc-+pprTcApp :: Monad m => TypePrec -> (TypePrec -> Type -> m ClashDoc)+ -> TyConName -> [Type] -> m ClashDoc pprTcApp p pp tc tys- | isTupleTyConLike tc- = do- tys' <- mapM (pp TopPrec) tys- return $ parens $ sep $ punctuate comma tys'+ | null tys+ = pprM tc - | otherwise- = pprTypeNameApp p pp tc tys+ | isTupleTyConLike tc+ = do tys' <- mapM (pp TopPrec) tys+ return $ parens $ sep $ punctuate comma tys' -pprTypeNameApp :: LFresh m => TypePrec -> (TypePrec -> Type -> m Doc)- -> Name a -> [Type] -> m Doc-pprTypeNameApp p pp name tys | isSym- , [ty1,ty2] <- tys- = pprInfixApp p pp name ty1 ty2- | otherwise- = do- tys' <- mapM (pp TyConPrec) tys- let name' = PP.pretty $ name2String name- return $ pprPrefixApp p (pprPrefixVar isSym name') tys'- where- isSym = isSymName name--pprInfixApp :: LFresh m => TypePrec -> (TypePrec -> Type -> m Doc)- -> Name a -> Type -> Type -> m Doc-pprInfixApp p pp name ty1 ty2 = do- ty1' <- pp FunPrec ty1- ty2' <- pp FunPrec ty2- let name' = PP.pretty $ name2String name- return $ maybeParen p FunPrec $ sep [ty1', pprInfixVar True name' <+> ty2']--pprPrefixApp :: TypePrec -> Doc -> [Doc] -> Doc-pprPrefixApp p pp_fun pp_tys = maybeParen p TyConPrec $- hang 2 (sep (pp_fun:pp_tys))--pprPrefixVar :: Bool -> Doc -> Doc-pprPrefixVar is_operator pp_v- | is_operator = parens pp_v- | otherwise = pp_v+ , [ty1, ty2] <- tys+ = do ty1' <- pp FunPrec ty1+ ty2' <- pp FunPrec ty2+ tc' <- pprM tc+ return $ maybeParen p FunPrec $+ sep [ty1', enclose "`" "`" tc' <+> ty2'] -pprInfixVar :: Bool -> Doc -> Doc-pprInfixVar is_operator pp_v- | is_operator = pp_v- | otherwise = PP.pretty '`' <> pp_v <> PP.pretty '`'+ | otherwise+ = do tys' <- mapM (pp TyConPrec) tys+ tc' <- parensIf isSym <$> pprM tc+ return $ maybeParen p TyConPrec $+ hang 2 $ sep (tc':tys') -pprArrowChain :: TypePrec -> [Doc] -> Doc-pprArrowChain _ [] = emptyDoc-pprArrowChain p (arg:args) = maybeParen p FunPrec $- sep [arg, sep (map (rarrow <+>) args)]+ where isSym = isSymName tc isSymName :: Name a -> Bool-isSymName n = go (name2String n)+isSymName n = go (nameOcc n) where- go s | null s = False- | isUpper $ head s = isLexConSym s- | otherwise = isLexSym s+ go s | T.null s = False+ | isUpper $ T.head s = isLexConSym s+ | otherwise = isLexSym s -isLexSym :: String -> Bool+isLexSym :: Text -> Bool isLexSym cs = isLexConSym cs || isLexVarSym cs -isLexConSym :: String -> Bool+isLexConSym :: Text -> Bool isLexConSym "->" = True-isLexConSym cs = startsConSym (head cs)+isLexConSym cs = startsConSym (T.head cs) -isLexVarSym :: String -> Bool-isLexVarSym cs = startsVarSym (head cs)+isLexVarSym :: Text -> Bool+isLexVarSym cs = startsVarSym (T.head cs) startsConSym :: Char -> Bool startsConSym c = c == ':'@@ -375,4 +473,5 @@ startsVarSym c = isSymbolASCII c || (ord c > 0x7f && isSymbol c) isSymbolASCII :: Char -> Bool-isSymbolASCII c = c `elem` "!#$%&*+./<=>?@\\^|~-"+isSymbolASCII c = c `elem` ("!#$%&*+./<=>?@\\^|~-" :: String)+
src/Clash/Core/Subst.hs view
@@ -7,60 +7,798 @@ Capture-free substitution function for CoreHW -} -{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ViewPatterns #-} -module Clash.Core.Subst where+{-# OPTIONS_GHC -fno-warn-orphans #-} -import Unbound.Generics.LocallyNameless (embed, subst, substs, unembed)+#include "../../ClashDebug.h" -import Clash.Core.Term (LetBinding, Term, TmOccName)-import {-# SOURCE #-} Clash.Core.Type (KiOccName, Kind, TyOccName, Type)+module Clash.Core.Subst+ ( -- * Substitution into types+ -- ** Substitution environments+ TvSubst (..)+ , TvSubstEnv+ -- , mkTvSubst+ , extendTvSubst+ , extendTvSubstList+ -- ** Applying substitutions+ , substTy+ , substTyWith+ , substTyInVar+ -- * Substitution into terms+ -- ** Substitution environments+ , Subst (..)+ , mkSubst+ , mkTvSubst+ , extendInScopeId+ , extendInScopeIdList+ , extendIdSubst+ , extendIdSubstList+ , extendGblSubstList+ -- ** Applying substitutions+ , substTm+ -- * Variable renaming+ , deShadowTerm+ , freshenTm+ -- * Alpha equivalence+ , aeqType+ , aeqTerm+ )+where --- | Substitutes types in a type-substTys :: [(TyOccName,Type)]- -> Type- -> Type-substTys = substs+import Data.Coerce (coerce)+import Data.Text.Prettyprint.Doc+import qualified Data.List as List --- | Substitutes a type in a type-substTy :: TyOccName- -> Type- -> Type- -> Type-substTy = subst+import Clash.Core.FreeVars+ (noFreeVarsOfType, localFVsOfTerms, tyFVsOfTypes)+import Clash.Core.Pretty (ppr, fromPpr)+import Clash.Core.Term+ (LetBinding, Pat (..), Term (..), TickInfo (..))+import Clash.Core.Type (Type (..))+import Clash.Core.VarEnv+import Clash.Core.Var (Id, Var (..), TyVar, isGlobalId)+import Clash.Unique+import Clash.Util+import Clash.Pretty --- | Substitutes kinds in a kind-substKindWith :: [(KiOccName,Kind)]- -> Kind- -> Kind-substKindWith = substs+-- * Subst --- | Substitutes a type in a term-substTyInTm :: TyOccName- -> Type- -> Term- -> Term-substTyInTm = subst+-- | A substitution of 'Type's for 'TyVar's+--+-- Note [Extending the TvSubstEnv]+-- See 'TvSubst' for the invariants that must hold+--+-- This invariant allows a short-cut when the subst env is empty: if the+-- TvSubstEnv is empty, i.e. @nullVarEnv TvSubstEnv@ holds, then+-- (substTy subst ty) does nothing.+--+-- For example, consider:+--+-- (/\a -> /\b(a ~ Int) -> ... b ...) Int+--+-- We substitute Int for 'a'. The Unique of 'b' does not change, but+-- nevertheless we add 'b' to the 'TvSubstEnv' because b's kind does change+--+-- This invariant has several consequences:+--+-- * In 'substTyVarBndr', we extend TvSubstEnv if the unique has changed, or+-- if the kind has changed+--+-- * In 'substTyVar', we do not need to consult the 'InScopeSet'; the+-- TvSubstEnv is enough+--+-- * In 'substTy', we can short-circuit when TvSubstEnv is empty+type TvSubstEnv = VarEnv Type --- | Substitutes types in a term-substTysinTm :: [(TyOccName,Type)]- -> Term- -> Term-substTysinTm = substs+-- | Type substitution+--+-- The following invariants must hold:+--+-- 1. The 'InScopeSet' is needed only to guide the generation of fresh uniques+--+-- 2. In particular, the kind of the type variables in the 'InScopeSet' is not+-- relevant.+--+-- 3. The substitution is only applied once+--+-- Note [Apply Once]+--+-- We might instantiate @forall a b. ty@ with the types @[a, b]@ or @[b, a]@.+-- So the substitution might go like @[a -> b, b -> a]@. A similar situation+-- arises in terms when we find a redex like @(/\a -> /\b -> e) b a@. Then we+-- also end up with a substitution that permutes variables. Other variations+-- happen to; for example @[a -> (a,b)]@.+--+-- SO A TvSubst MUST BE APPLIED PRECISELY ONCE, OR THINGS MIGHT LOOP+--+-- Note [The substitution invariant]+--+-- When calling (substTy subst ty) it should be the case that the 'InScopeSet'+-- is a superset of both:+--+-- * The free variables of the range of the substitution+--+-- * The free variables of /ty/ minus the domain of the substitution+data TvSubst+ = TvSubst InScopeSet -- Variable in scope /after/ substitution+ TvSubstEnv -- Substitution for types --- | Substitutes a term in a term-substTm :: TmOccName- -> Term- -> Term- -> Term-substTm = subst+instance ClashPretty TvSubst where+ clashPretty (TvSubst ins tenv) =+ brackets $ sep [ "TvSubst"+ , nest 2 ("In scope:" <+> clashPretty ins)+ , nest 2 ("Type env:" <+> clashPretty tenv)] --- | Substitutes terms in a term-substTms :: [(TmOccName,Term)]- -> Term- -> Term-substTms = substs+-- | A substitution of 'Term's for 'Id's+--+-- Note [Extending the Subst]+--+-- For a term 'Subst', which binds 'Id's as well, we make a different choice for+-- Ids than we do for TyVars.+--+-- For TyVars see 'TvSubstEnv's Note [Extending the TvSubstEnv]+--+-- For Ids, we have a different invariant:+--+-- The IdSubstEnv is extended only when the Unique on an Id changes.+-- Otherwise, we just extend the InScopeSet+--+-- In consequence:+--+-- * If all subst envs are empty, substsTm would be a no-op+--+-- However, substTm still goes ahead and substitutes. Reason: we may want+-- to replace existing Ids with new ones from the in-scope set, to avoid+-- space leaks.+--+-- * In substIdBndr, we extend the 'IdSubstEnv' only when the unique changes+--+-- * If TvSubstEnv and IdSubstEnv are all empty, substExpr does nothing+-- (Note that the above rule for 'substIdBndr' maintains this property.)+--+-- * In 'lookupIdSubst', we must look up the Id in the in-scope set, because+-- it may contain non-trivial changes. Exmaple:+--+-- (/\a -> \x:a. ... x ...) Int+--+-- We extend the 'TvSubstEnv' with a @[a |-> Int]@; but x's unique does not+-- change so we only extend the in-scope set. Then we must look up in the+-- in-scope set when we find the occurrence of x.+--+-- * The requirement to look up the Id in the in-scope set means that we+-- must not take no-op short cut when the 'IdSubstEnv' is empty. We must+-- still look up ever Id in the in-scope set.+--+-- * (However, we don't need to do so for the expression found in the+-- IdSubstEnv, whose range is assumed to be correct wrt the in-scope set)+type IdSubstEnv = VarEnv Term --- | Substitutes a term in a let-binding-substBndr :: TmOccName -> Term -> LetBinding -> LetBinding-substBndr nm tm (id_,unembed -> tm') = (id_,embed (substTm nm tm tm'))+-- | A substitution environment containing containing both 'Id' and 'TyVar'+-- substitutions.+--+-- Some invariants apply to how you use the substitution:+--+-- 1. The 'InScopeSet' contains at least those 'Id's and 'TyVar's that will+-- be in scope /after/ applying the substitution to a term. Precisely,+-- the in-scope set must be a superset of the free variables of the+-- substitution range that might possibly clash with locally-bound+-- variables in the thing being substituted in.+--+-- 2. You may only apply the substitution once. See 'TvSubst'+--+-- There are various ways of setting up the in-scope set such that the first of+-- of these invariants holds:+--+-- * Arrange that the in-scope set really is all the things in scope+--+-- * Arrange that it's the free vars of the range of the substitution+--+-- * Make it empty, if you know that all the free variables of the+-- substitution are fresh, and hence can´t possibly clash+data Subst+ = Subst+ { substInScope :: InScopeSet -- Variables in scope /after/ substitution+ , substTmEnv :: IdSubstEnv -- Substitution for terms+ , substTyEnv :: TvSubstEnv -- Substitution for types+ , substGblEnv :: IdSubstEnv -- Substitution of globals (in terms)+ }++emptySubst+ :: Subst+emptySubst = Subst emptyInScopeSet emptyVarEnv emptyVarEnv emptyVarEnv++-- | An empty substitution, starting the variables currently in scope+mkSubst+ :: InScopeSet+ -> Subst+mkSubst is = Subst is emptyVarEnv emptyVarEnv emptyVarEnv++-- | Create a type substitution+mkTvSubst+ :: InScopeSet+ -> VarEnv Type+ -> Subst+mkTvSubst is env = Subst is emptyVarEnv env emptyVarEnv++-- | Generates the in-scope set for the 'Subst' from the types in the incoming+-- environment.+--+-- Should only be used the type we're substituting into has no free variables+-- outside of the domain of substitution+zipTvSubst+ :: [TyVar]+ -> [Type]+ -> Subst+zipTvSubst tvs tys+ | debugIsOn+ , neLength tvs tys+ = pprTrace "zipTvSubst" (ppr tvs <> line <> ppr tys) emptySubst+ | otherwise+ = Subst (mkInScopeSet (tyFVsOfTypes tys)) emptyVarEnv tenv emptyVarEnv+ where+ tenv = zipTyEnv tvs tys++zipTyEnv+ :: [TyVar]+ -> [Type]+ -> VarEnv Type+zipTyEnv tvs tys = mkVarEnv (zipEqual tvs tys)++-- | Extend the substitution environment with a new 'Id' substitution+extendIdSubst+ :: Subst+ -> Id+ -> Term+ -> Subst+extendIdSubst (Subst is env tenv genv) i e =+ Subst is (extendVarEnv i e env) tenv genv++-- | Extend the substitution environment with a list of 'Id' substitutions+extendIdSubstList+ :: Subst+ -> [(Id,Term)]+ -> Subst+extendIdSubstList (Subst is env tenv genv) es =+ Subst is (extendVarEnvList env es) tenv genv++-- | Extend the substitution environment with a list of global 'Id' substitutions+extendGblSubstList+ :: Subst+ -> [(Id,Term)]+ -> Subst+extendGblSubstList (Subst is env tenv genv) es =+ Subst is env tenv (extendVarEnvList genv es)++-- | Extend the substitution environment with a new 'TyVar' substitution+extendTvSubst+ :: Subst+ -> TyVar+ -> Type+ -> Subst+extendTvSubst (Subst is env tenv genv) tv t =+ Subst is env (extendVarEnv tv t tenv) genv++-- | Extend the substitution environment with a list of 'TyVar' substitutions+extendTvSubstList+ :: Subst+ -> [(TyVar, Type)]+ -> Subst+extendTvSubstList (Subst is env tenv genv) ts =+ Subst is env (extendVarEnvList tenv ts) genv++-- | Add an 'Id' to the in-scope set: as a side effect, remove any existing+-- substitutions for it.+extendInScopeId+ :: Subst+ -> Id+ -> Subst+extendInScopeId (Subst inScope env tenv genv) id' =+ Subst inScope' env' tenv genv+ where+ inScope' = extendInScopeSet inScope id'+ env' = delVarEnv env id'++-- | Add 'Id's to the in-scope set. See also 'extendInScopeId'+extendInScopeIdList+ :: Subst+ -> [Id]+ -> Subst+extendInScopeIdList (Subst inScope env tenv genv) ids =+ Subst inScope' env' tenv genv+ where+ inScope' = extendInScopeSetList inScope ids+ env' = delVarEnvList env ids++-- | Substitute within a 'Type'+--+-- The substitution has to satisfy the invariant described in+-- 'TvSubst's Note [The substitution environment]+substTy+ :: HasCallStack+ => Subst+ -> Type+ -> Type+substTy (Subst inScope _ tvS _) ty+ | nullVarEnv tvS+ = ty+ | otherwise+ = checkValidSubst s' [ty] (substTy' s' ty)+ where+ s' = TvSubst inScope tvS++-- | Substitute within a 'TyVar'. See 'substTy'.+substTyInVar+ :: HasCallStack+ => Subst+ -> Var a+ -> Var a+substTyInVar subst tyVar =+ tyVar { varType = (substTy subst (varType tyVar)) }++-- | Like 'substTy', but skips the checks for the invariants described in+-- 'TvSubts' Note [The substitution environment]. Should be used inside this+-- module only.+substTyUnchecked+ :: HasCallStack+ => TvSubst+ -> Type+ -> Type+substTyUnchecked subst@(TvSubst _ tvS) ty+ | nullVarEnv tvS+ = ty+ | otherwise+ = substTy' subst ty++-- | This checks if the substitution satisfies the invariant from 'TvSbust's+-- Note [The substitution invariant].+checkValidSubst+ :: HasCallStack+ => TvSubst+ -> [Type]+ -> a+ -> a+checkValidSubst subst@(TvSubst inScope tenv) tys a =+ WARN( not (isValidSubst subst),+ "inScope" <+> clashPretty inScope <> line <>+ "tenv" <+> clashPretty tenv <> line <>+ "tenvFVs" <+> clashPretty (tyFVsOfTypes tenv) <> line <>+ "tys" <+> fromPpr tys)+ WARN( not tysFVsInSope,+ "inScope" <+> clashPretty inScope <> line <>+ "tenv" <+> clashPretty tenv <> line <>+ "tys" <+> fromPpr tys <> line <>+ "needsInScope" <+> clashPretty needsInScope)+ a+ where+ needsInScope = foldrWithUnique (\k _ s -> delVarSetByKey k s)+ (tyFVsOfTypes tys)+ tenv+ tysFVsInSope = needsInScope `varSetInScope` inScope++-- | When calling 'substTy' it should be the case that the in-scope set in the+-- substitution is a superset of the free variables of the range of the+-- substitution.+--+-- See also 'TvSubst's Note [The substitution invariant].+isValidSubst+ :: TvSubst+ -> Bool+isValidSubst (TvSubst inScope tenv) = tenvFVs `varSetInScope` inScope+ where+ tenvFVs = tyFVsOfTypes tenv++-- | The work-horse of 'substTy'+substTy'+ :: HasCallStack+ => TvSubst+ -> Type+ -> Type+substTy' subst = go where+ go = \case+ VarTy tv -> substTyVar subst tv+ ForAllTy tv ty -> case substTyVarBndr subst tv of+ (subst', tv') -> ForAllTy tv' (substTy' subst' ty)+ AppTy fun arg -> AppTy (go fun) (go arg)+ ty -> ty++-- | Substitute a variable with a type if it's within the substitution's domain.+--+-- Does not substitute within the kind of free variables.+substTyVar+ :: TvSubst+ -> TyVar+ -> Type+substTyVar (TvSubst _ tenv) tv = case lookupVarEnv tv tenv of+ Just ty -> ty+ _ -> VarTy tv++-- | Substitute a type variable in a binding position, returning an extended+-- substitution environment and a new type variable.+--+-- Substitutes within the kind of the type variable+substTyVarBndr+ :: TvSubst+ -> TyVar+ -> (TvSubst, TyVar)+substTyVarBndr subst@(TvSubst inScope tenv) oldVar =+ ASSERT2( no_capture, clashPretty oldVar <> line+ <> clashPretty newVar <> line+ <> clashPretty subst )+ (TvSubst (inScope `extendInScopeSet` newVar) newEnv, newVar)+ where+ newEnv | noChange = delVarEnv tenv oldVar+ | otherwise = extendVarEnv oldVar (VarTy newVar) tenv++ -- Assertion that we're not capturing something in the substitution+ no_capture = not (newVar `elemVarSet` tyFVsOfTypes tenv)++ oldKi = varType oldVar+ -- verify that the kind is closed+ noKindChange = noFreeVarsOfType 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]+ --+ -- In that case we don't need to extend the substitution to map old to new.+ -- But instead we must zap any current substitution for the variable. For+ -- example+ --+ -- (\x.e) with subst = [x | -> e']+ --+ -- Here we must simply zap the substitution for x+ noChange = noKindChange && (newVar == oldVar)++ -- uniqAway ensures that the new variable is not already in scope+ newVar | noKindChange = uniqAway inScope oldVar+ | otherwise = uniqAway inScope+ (oldVar {varType = substTyUnchecked subst oldKi})++-- | Substitute within a 'Type'+substTm+ :: HasCallStack+ => Doc ()+ -> Subst+ -> Term+ -> Term+substTm doc subst = go where+ go = \case+ Var v -> lookupIdSubst (doc <> line <> "subsTm") subst v+ Lam v e -> case substIdBndr subst v of+ (subst',v') -> Lam v' (substTm doc subst' e)+ TyLam v e -> case substTyVarBndr' subst v of+ (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)+ 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)+ tm -> tm++ goAlt (pat,alt) = case pat of+ DataPat dc tvs ids -> case List.mapAccumL substTyVarBndr' subst tvs of+ (subst1,tvs') -> case List.mapAccumL substIdBndr subst1 ids of+ (subst2,ids') -> (DataPat dc tvs' ids',substTm doc subst2 alt)+ _ -> (pat,go alt)++ goTick t@(SrcSpan _) = t+ goTick (NameMod m ty) = NameMod m (substTy subst ty)++-- | Find the substitution for an 'Id' in the 'Subst'+lookupIdSubst+ :: HasCallStack+ => Doc ()+ -> Subst+ -> Id+ -> Term+lookupIdSubst doc (Subst inScope tmS _ genv) v+ | isGlobalId v = case lookupVarEnv v genv of+ Just e -> e+ _ -> Var v+ | Just e <- lookupVarEnv v tmS = e+ -- Vital! See 'IdSubstEnv' Note [Extending the Subst]+ | Just v' <- lookupInScope inScope v = Var (coerce v')+ | otherwise = WARN(True, "Subst.lookupIdSubst" <+> doc <+> fromPpr v)+ Var v++-- | Substitute an 'Id' for another one according to the 'Subst' given,+-- returning the result and an update 'Subst' that should be used in subsequent+-- substitutions.+substIdBndr+ :: HasCallStack+ => Subst+ -> Id+ -> (Subst,Id)+substIdBndr subst@(Subst inScope env tenv genv) oldId =+ (Subst (inScope `extendInScopeSet` newId) newEnv tenv genv, newId)+ where+ id1 = uniqAway inScope oldId+ newId | noTypeChange = id1+ | otherwise = id1 {varType = substTy subst (varType id1)}++ oldTy = varType oldId+ noTypeChange = nullVarEnv tenv || noFreeVarsOfType oldTy++ -- Extend the substitution if the unique has changed.+ --+ -- In case it hasn't changed we don't need to extend the substitution to map+ -- old to new. But instead we must zap any current substitution for the+ -- variable. For example+ --+ -- (\x.e) with subst = [x | -> e']+ --+ -- Here we must simply zap the substitution for x+ newEnv | noChange = delVarEnv env oldId+ | otherwise = extendVarEnv oldId (Var newId) env++ -- See Note [Extending the Subst] why it's not necessary to check noTypeChange+ noChange = id1 == oldId++-- | Like 'substTyVarBndr' but takes a 'Subst' instead of a 'TvSubst'+substTyVarBndr'+ :: HasCallStack+ => Subst+ -> TyVar+ -> (Subst,TyVar)+substTyVarBndr' (Subst inScope tmS tyS tgS) tv =+ case substTyVarBndr (TvSubst inScope tyS) tv of+ (TvSubst inScope' tyS',tv') -> (Subst inScope' tmS tyS' tgS, tv')++-- | Apply a substitution to an entire set of let-bindings, additionally+-- returning an updated 'Subst' that should be used by subsequent substitutions.+substBind+ :: HasCallStack+ => Doc ()+ -> Subst+ -> [LetBinding]+ -> (Subst,[LetBinding])+substBind doc subst xs =+ (subst',zip bndrs' rhss')+ where+ (bndrs,rhss) = unzip xs+ (subst',bndrs') = List.mapAccumL substIdBndr subst bndrs+ rhss' = map (substTm ("substBind" <+> doc) subst') rhss++-- | Type substitution, see 'zipTvSubst'+--+-- Works only if the domain of the substitution is superset of the type being+-- substituted into+substTyWith+ :: HasCallStack+ => [TyVar]+ -> [Type]+ -> Type+ -> Type+substTyWith tvs tys =+ ASSERT( tvs `equalLength` tys )+ substTy (zipTvSubst tvs tys)++-- | Ensure that non of the binders in an expression shadow each-other, nor+-- conflict with he in-scope set+deShadowTerm+ :: HasCallStack+ => InScopeSet+ -> Term+ -> Term+deShadowTerm is e = substTm "deShadowTerm" (mkSubst is) e++-- | A much stronger variant of `deShadowTerm` that ensures that all bound+-- variables are unique.+--+-- Also returns an extended 'InScopeSet' additionally containing the (renamed)+-- unique bound variables of the term.+freshenTm+ :: InScopeSet+ -- ^ Current set of variables in scope+ -> Term+ -> (InScopeSet, Term)+freshenTm is0 = go (mkSubst is0) where+ go subst0 = \case+ Var v -> (substInScope subst0, lookupIdSubst "freshenTm" subst0 v)+ Lam v e -> case substIdBndr subst0 v of+ (subst1,v') -> case go subst1 e of+ (is2,e') -> (is2, Lam v' e')+ TyLam v e -> case substTyVarBndr' subst0 v of+ (subst1,v') -> case go subst1 e of+ (is2,e') -> (is2,TyLam v' e')+ App l r -> case go subst0 l of+ (is1,l') -> case go subst0 {substInScope = is1} r of+ (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+ (subst1,bs') -> case go subst1 e of+ (is2,e') -> (is2,Letrec 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')+ Cast e t1 t2 -> case go subst0 e of+ (is1, e') -> (is1, Cast e' (substTy subst0 t1) (substTy subst0 t2))+ Tick tick e -> case go subst0 e of+ (is1, e') -> (is1, Tick (goTick subst0 tick) e')+ tm -> (substInScope subst0, tm)++ goBind subst0 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')++ goAlt subst0 (pat,alt) = case pat of+ DataPat dc tvs ids -> case List.mapAccumL substTyVarBndr' subst0 tvs of+ (subst1,tvs') -> case List.mapAccumL substIdBndr subst1 ids of+ (subst2,ids') -> case go subst2 alt of+ (is3,alt') -> (is3,(DataPat dc tvs' ids',alt'))+ _ -> case go subst0 alt of+ (is1,alt') -> (is1,(pat,alt'))++ goTick subst0 (NameMod m ty) = NameMod m (substTy subst0 ty)+ goTick _ tick = tick++-- * AEQ++-- | Alpha equality for types+aeqType+ :: Type+ -> Type+ -> Bool+aeqType t1 t2 = acmpType' rnEnv t1 t2 == EQ+ where+ rnEnv = mkRnEnv (mkInScopeSet (tyFVsOfTypes [t1,t2]))++-- | Alpha comparison for types+acmpType+ :: Type+ -> Type+ -> Ordering+acmpType t1 t2 = acmpType' (mkRnEnv inScope) t1 t2+ where+ inScope = mkInScopeSet (tyFVsOfTypes [t1,t2])++-- | Alpha comparison for types. Faster than 'acmpType' as it doesn't need to+-- calculate the free variables to create the 'InScopeSet'+acmpType'+ :: RnEnv+ -> Type+ -> Type+ -> Ordering+acmpType' = go+ where+ go env (VarTy tv1) (VarTy tv2) = compare (rnOccLTy env tv1) (rnOccRTy env tv2)+ go _ (ConstTy c1) (ConstTy c2) = compare c1 c2+ go env (ForAllTy tv1 t1) (ForAllTy tv2 t2) =+ go env (varType tv1) (varType tv2) `thenCompare` go (rnTyBndr env tv1 tv2) t1 t2+ go env (AppTy s1 t1) (AppTy s2 t2) =+ go env s1 s2 `thenCompare` go env t1 t2+ go _ (LitTy l1) (LitTy l2) = compare l1 l2+ go _ t1 t2 = compare (getRank t1) (getRank t2)++ getRank :: Type -> Word+ getRank (VarTy {}) = 0+ getRank (LitTy {}) = 1+ getRank (ConstTy {}) = 2+ getRank (AnnType {}) = 3+ getRank (AppTy {}) = 4+ getRank (ForAllTy {}) = 5++-- | Alpha equality for terms+aeqTerm+ :: Term+ -> Term+ -> Bool+aeqTerm t1 t2 = aeqTerm' inScope t1 t2+ where+ inScope = mkInScopeSet (localFVsOfTerms [t1,t2])++-- | Alpha equality for terms. Faster than 'aeqTerm' as it doesn't need to+-- calculate the free variables to create the 'InScopeSet'+aeqTerm'+ :: InScopeSet+ -- ^ Superset of variables in scope of the left and right term+ -> Term+ -> Term+ -> Bool+aeqTerm' inScope t1 t2 = acmpTerm' inScope t1 t2 == EQ++-- | Alpha comparison for types+acmpTerm+ :: Term+ -> Term+ -> Ordering+acmpTerm t1 t2 = acmpTerm' inScope t1 t2+ where+ inScope = mkInScopeSet (localFVsOfTerms [t1,t2])++-- | Alpha comparison for types. Faster than 'acmpTerm' as it doesn't need to+-- calculate the free variables to create the 'InScopeSet'+acmpTerm'+ :: InScopeSet+ -- ^ Superset of variables in scope of the left and right term+ -> Term+ -> Term+ -> Ordering+acmpTerm' inScope = go (mkRnEnv inScope)+ where+ thenCmpTm EQ rel = rel+ thenCmpTm rel _ = rel++ go env (Var id1) (Var id2) = compare (rnOccLId env id1) (rnOccRId env id2)+ go _ (Data dc1) (Data dc2) = compare dc1 dc2+ go _ (Literal l1) (Literal l2) = compare l1 l2+ go _ (Prim p1 _) (Prim p2 _) = compare p1 p2+ go env (Lam b1 e1) (Lam b2 e2) =+ acmpType' env (varType b1) (varType b2) `thenCompare`+ go (rnTmBndr env b1 b2) e1 e2+ go env (TyLam b1 e1) (TyLam b2 e2) =+ acmpType' env (varType b1) (varType b2) `thenCompare`+ go (rnTyBndr env b1 b2) e1 e2+ go env (App l1 r1) (App l2 r2) =+ 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) =+ compare (length bs1) (length bs2) `thenCompare`+ foldr thenCmpTm EQ (zipWith (go env') rhs1 rhs2) `thenCompare`+ go env' e1 e2+ where+ (ids1,rhs1) = unzip bs1+ (ids2,rhs2) = unzip bs2+ env' = rnTmBndrs env ids1 ids2+ go env (Case e1 _ a1) (Case e2 _ a2) =+ compare (length a1) (length a2) `thenCompare`+ go env e1 e2 `thenCompare`+ foldr thenCmpTm EQ (zipWith (goAlt env) a1 a2)+ go env (Cast e1 l1 r1) (Cast e2 l2 r2) =+ go env e1 e2 `thenCompare`+ acmpType' env l1 l2 `thenCompare`+ acmpType' env r1 r2+ -- Look through ticks for aeq+ go env (Tick _ e1) e2 = go env e1 e2+ go env e1 (Tick _ e2) = go env e1 e2++ go _ e1 e2 = compare (getRank e1) (getRank e2)++ goAlt env (DataPat c1 tvs1 ids1,e1) (DataPat c2 tvs2 ids2,e2) =+ compare c1 c2 `thenCompare` go env' e1 e2+ where+ env' = rnTmBndrs (rnTyBndrs env tvs1 tvs2) ids1 ids2+ goAlt env (c1,e1) (c2,e2) =+ compare c1 c2 `thenCompare` go env e1 e2++ getRank :: Term -> Word+ getRank = \case+ Var {} -> 0+ Data {} -> 1+ Literal {} -> 2+ Prim {} -> 3+ Cast {} -> 4+ App {} -> 5+ TyApp {} -> 6+ Lam {} -> 7+ TyLam {} -> 8+ Letrec {} -> 9+ Case {} -> 10+ Tick {} -> 11++thenCompare :: Ordering -> Ordering -> Ordering+thenCompare EQ rel = rel+thenCompare rel _ = rel++instance Eq Type where+ (==) = aeqType++instance Ord Type where+ compare = acmpType++instance Eq Term where+ (==) = aeqTerm++instance Ord Term where+ compare = acmpTerm
+ src/Clash/Core/Subst.hs-boot view
@@ -0,0 +1,21 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}++module Clash.Core.Subst where++import GHC.Stack (HasCallStack)+import {-# SOURCE #-} Clash.Core.Type (Type)+import Clash.Core.Var (TyVar)++substTyWith+ :: HasCallStack+ => [TyVar]+ -> [Type]+ -> Type+ -> Type++aeqType+ :: Type+ -> Type+ -> Bool++instance Eq Type
src/Clash/Core/Term.hs view
@@ -10,89 +10,229 @@ {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE ViewPatterns #-} module Clash.Core.Term ( Term (..) , TmName- , TmOccName , LetBinding , Pat (..) , Alt+ , TickInfo (..), NameMod (..)+ , PrimInfo (..)+ , WorkInfo (..)+ , CoreContext (..), Context, isLambdaBodyCtx, isTickCtx+ , collectArgs, collectArgsTicks, collectTicks, primArg+ , partitionTicks ) where -- External Modules import Control.DeepSeq+import Data.Binary (Binary)+import Data.Either (lefts, rights) import Data.Hashable (Hashable)+import Data.List (partition) import Data.Text (Text) import GHC.Generics-import Unbound.Generics.LocallyNameless hiding (Name)-import Unbound.Generics.LocallyNameless.Extra ()+import SrcLoc (SrcSpan) -- Internal Modules import Clash.Core.DataCon (DataCon) import Clash.Core.Literal (Literal)-import Clash.Core.Name (Name (..), OccName)+import Clash.Core.Name (Name (..))+import {-# SOURCE #-} Clash.Core.Subst () -- instance Eq Type import {-# SOURCE #-} Clash.Core.Type (Type) import Clash.Core.Var (Id, TyVar) -- | Term representation in the CoreHW language: System F + LetRec + Case data Term- = Var !Type !TmName -- ^ Variable reference+ = Var !Id -- ^ Variable reference | Data !DataCon -- ^ Datatype constructor | Literal !Literal -- ^ Literal- | Prim !Text !Type -- ^ Primitive- | Lam !(Bind Id Term) -- ^ Term-abstraction- | TyLam !(Bind TyVar Term) -- ^ Type-abstraction+ | Prim !Text !PrimInfo -- ^ Primitive+ | Lam !Id Term -- ^ Term-abstraction+ | TyLam !TyVar Term -- ^ Type-abstraction | App !Term !Term -- ^ Application | TyApp !Term !Type -- ^ Type-application- | Letrec !(Bind (Rec [LetBinding]) Term) -- ^ Recursive let-binding+ | Letrec [LetBinding] 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- deriving (Show,Generic,NFData,Hashable)+ | Tick !TickInfo !Term -- ^ Annotated term+ deriving (Show,Generic,NFData,Hashable,Binary) +data TickInfo+ = SrcSpan !SrcSpan+ -- ^ Source tick, will get added by GHC by running clash with `-g`+ | NameMod !NameMod !Type+ -- ^ Modifier for naming module instantiations and registers, are added by+ -- the user by using the functions @Clash.Magic.[prefixName,suffixName,setName]@+ deriving (Eq,Show,Generic,NFData,Hashable,Binary)++-- | Tag to indicate which instance/register name modifier was used+data NameMod+ = PrefixName+ -- ^ @Clash.Magic.prefixName@+ | SuffixName+ -- ^ @Clash.Magic.suffixName@+ | SetName+ -- ^ @Clash.Magic.setName@+ deriving (Eq,Show,Generic,NFData,Hashable,Binary)++data PrimInfo+ = PrimInfo+ { primType :: !Type+ , primWorkInfo :: !WorkInfo+ }+ deriving (Show,Generic,NFData,Hashable,Binary)++data WorkInfo+ = WorkConstant+ -- ^ Ignores its arguments, and outputs a constant+ | WorkNever+ -- ^ Never adds any work+ | WorkVariable+ -- ^ Does work when the arguments are variable+ | WorkAlways+ -- ^ Performs work regardless of whether the variables are constant or+ -- variable; these are things like clock or reset generators+ deriving (Show,Generic,NFData,Hashable,Binary)+ -- | Term reference type TmName = Name Term-type TmOccName = OccName Term -- | Binding in a LetRec construct-type LetBinding = (Id, Embed Term)+type LetBinding = (Id, Term) -- | Patterns in the LHS of a case-decomposition data Pat- = DataPat !(Embed DataCon) !(Rebind [TyVar] [Id])+ = DataPat !DataCon [TyVar] [Id] -- ^ Datatype pattern, '[TyVar]' bind existentially-quantified -- type-variables of a DataCon- | LitPat !(Embed Literal)+ | LitPat !Literal -- ^ Literal pattern | DefaultPat -- ^ Default pattern- deriving (Eq,Show,Generic,NFData,Alpha,Hashable)+ deriving (Eq,Ord,Show,Generic,NFData,Hashable,Binary) -type Alt = Bind Pat Term+type Alt = (Pat,Term) -instance Eq Term where- (==) = aeq+-- | Context in which a term appears+data CoreContext+ = AppFun+ -- ^ Function position of an application+ | AppArg (Maybe (Text, Int, Int))+ -- ^ Argument position of an application. If this is an argument applied to+ -- a primitive, a tuple is defined containing (name of the primitive, #type+ -- args, #term args)+ | TyAppC+ -- ^ Function position of a type application+ | LetBinding Id [Id]+ -- ^ RHS of a Let-binder with the sibling LHS'+ | LetBody [Id]+ -- ^ Body of a Let-binding with the bound LHS'+ | LamBody Id+ -- ^ Body of a lambda-term with the abstracted variable+ | TyLamBody TyVar+ -- ^ Body of a TyLambda-term with the abstracted type-variable+ | CaseAlt Pat+ -- ^ RHS of a case-alternative with the bound pattern on the LHS+ | CaseScrut+ -- ^ Subject of a case-decomposition+ | CastBody+ -- ^ Body of a Cast+ | TickC TickInfo+ -- ^ Body of a Tick+ deriving (Show, Generic, NFData, Hashable, Binary) -instance Ord Term where- compare = acompare+-- | A list of @CoreContext@ describes the complete navigation path from the+-- top-level to a specific sub-expression.+type Context = [CoreContext] -instance Alpha Term where- aeq' c (Var _ n) (Var _ m) = aeq' c n m- aeq' _ (Prim t1 _) (Prim t2 _) = t1 == t2- aeq' c t1 t2 = gaeq c (from t1) (from t2)+-- [Note] Custom @Eq@ instance for @CoreContext@+--+-- We need a manual equality instance here, due to the argument of `AppArg`.+-- Specifically, it is the only piece of information kept in `CoreContext`,+-- which references information about its children, breaking the invariant+-- that contexts represent a navigation to a specific sub-expression.+--+-- One would expect equal contexts to navigate to the same place, but if+-- these navigate to an argument position that contains different children,+-- we will get inequality from the derived `Eq`.+instance Eq CoreContext where+ c == c' = case (c, c') of+ (AppFun, AppFun) -> True+ (AppArg _, AppArg _) -> True+ -- NB: we do not see inside the argument here+ (TyAppC, TyAppC) -> True+ (LetBinding i is, LetBinding i' is') -> i == i' && is == is'+ (LetBody is, LetBody is') -> is == is'+ (LamBody i, LamBody i') -> i == i'+ (TyLamBody tv, TyLamBody tv') -> tv == tv'+ (CaseAlt p, CaseAlt p') -> p == p'+ (CaseScrut, CaseScrut) -> True+ (CastBody, CastBody) -> True+ (TickC sp, TickC sp') -> sp == sp'+ (_, _) -> False - acompare' c (Var _ n) (Var _ m) = acompare' c n m- acompare' _ (Prim t1 _) (Prim t2 _) = compare t1 t2- acompare' c t1 t2 = gacompare c (from t1) (from t2)+-- | Is the Context a Lambda/Term-abstraction context?+isLambdaBodyCtx :: CoreContext -> Bool+isLambdaBodyCtx (LamBody _) = True+isLambdaBodyCtx _ = False -instance Subst Type Pat-instance Subst Term Pat+-- | Is the Context a Tick context?+isTickCtx :: CoreContext -> Bool+isTickCtx (TickC _) = True+isTickCtx _ = False -instance Subst Term Term where- isvar (Var _ x) = Just (SubstName (nameOcc x))- isvar _ = Nothing+-- | Split a (Type)Application in the applied term and it arguments+collectArgs :: Term+ -> (Term, [Either Term Type])+collectArgs = go []+ where+ go args (App e1 e2) = go (Left e2:args) e1+ go args (TyApp e t) = go (Right t:args) e+ go args (Tick _ e) = go args e+ go args e = (e, args) -instance Subst Type Term+collectTicks+ :: Term+ -> (Term, [TickInfo])+collectTicks = go []+ where+ go ticks (Tick s e) = go (s:ticks) e+ go ticks e = (e,ticks)++collectArgsTicks+ :: Term+ -> (Term, [Either Term Type], [TickInfo])+collectArgsTicks = go [] []+ where+ go args ticks (App e1 e2) = go (Left e2:args) ticks e1+ go args ticks (TyApp e t) = go (Right t:args) ticks e+ go args ticks (Tick s e) = go args (s:ticks) e+ go args ticks e = (e, args, ticks)++-- | Given a function application, find the primitive it's applied. Yields+-- Nothing if given term is not an application or if it is not a primitive.+primArg+ :: Term+ -- ^ Function application+ -> Maybe (Text, Int, Int)+ -- ^ If @Term@ was a primitive: (name of primitive, #type args, #term args)+primArg (collectArgs -> t) =+ case t of+ (Prim nm _, args) ->+ Just (nm, length (rights args), length (lefts args))+ _ ->+ Nothing++-- | Partition ticks in source ticks and nameMod ticks+partitionTicks+ :: [TickInfo]+ -> ([TickInfo], [TickInfo])+ -- ^ (source ticks, nameMod ticks)+partitionTicks = partition (\case {SrcSpan {} -> True; _ -> False})
src/Clash/Core/Term.hs-boot view
@@ -12,6 +12,7 @@ import Clash.Core.Name (Name) data Term+ type TmName = Name Term instance Generic Term
src/Clash/Core/TyCon.hs view
@@ -15,64 +15,61 @@ module Clash.Core.TyCon ( TyCon (..) , TyConName- , TyConOccName , TyConMap , AlgTyConRhs (..) , mkKindTyCon , isTupleTyConLike+ , isNewTypeTc , tyConDataCons ) where -#ifndef MIN_VERSION_unbound_generics-#define MIN_VERSION_unbound_generics(x,y,z)(1)-#endif- -- External Import import Control.DeepSeq-import Data.HashMap.Lazy (HashMap)+import Data.Binary (Binary)+import qualified Data.Text as T import GHC.Generics-import Unbound.Generics.LocallyNameless (Alpha(..))-import Unbound.Generics.LocallyNameless.Extra ()-#if MIN_VERSION_unbound_generics(0,3,0)-import Data.Monoid (All (..))-import Unbound.Generics.LocallyNameless (NthPatFind (..),- NamePatFind (..))-#endif -- Internal Imports import Clash.Core.DataCon (DataCon) import Clash.Core.Name-import {-# SOURCE #-} Clash.Core.Type (Kind, TyName, Type)+import {-# SOURCE #-} Clash.Core.Type (Kind, Type)+import Clash.Core.Var (TyVar)+import Clash.Unique import Clash.Util -- | Type Constructor data TyCon -- | Algorithmic DataCons = AlgTyCon- { tyConName :: !TyConName -- ^ Name of the TyCon+ { tyConUniq :: {-# UNPACK #-} !Unique+ , tyConName :: !TyConName -- ^ Name of the TyCon , tyConKind :: !Kind -- ^ Kind of the TyCon , tyConArity :: !Int -- ^ Number of type arguments , algTcRhs :: !AlgTyConRhs -- ^ DataCon definitions+ , isClassTc :: !Bool -- ^ Is this a class dictionary? } -- | Function TyCons (e.g. type families) | FunTyCon- { tyConName :: !TyConName -- ^ Name of the TyCon+ { tyConUniq :: {-# UNPACK #-} !Unique+ , tyConName :: !TyConName -- ^ Name of the TyCon , tyConKind :: !Kind -- ^ Kind of the TyCon , tyConArity :: !Int -- ^ Number of type arguments , tyConSubst :: [([Type],Type)] -- ^ List of: ([LHS match types], RHS type) } -- | Primitive TyCons | PrimTyCon- { tyConName :: !TyConName -- ^ Name of the TyCon+ { tyConUniq :: {-# UNPACK #-} !Unique+ , tyConName :: !TyConName -- ^ Name of the TyCon , tyConKind :: !Kind -- ^ Kind of the TyCon , tyConArity :: !Int -- ^ Number of type arguments } -- | To close the loop on the type hierarchy | SuperKindTyCon- { tyConName :: !TyConName -- ^ Name of the TyCon+ { tyConUniq :: {-# UNPACK #-} !Unique+ , tyConName :: !TyConName -- ^ Name of the TyCon }- deriving (Generic,NFData)+ deriving (Generic,NFData,Binary) instance Show TyCon where show (AlgTyCon {tyConName = n}) = "AlgTyCon: " ++ show n@@ -81,15 +78,15 @@ show (SuperKindTyCon {tyConName = n}) = "SuperKindTyCon: " ++ show n instance Eq TyCon where- (==) = (==) `on` tyConName+ (==) = (==) `on` tyConUniq+ (/=) = (/=) `on` tyConUniq -instance Ord TyCon where- compare = compare `on` tyConName+instance Uniquable TyCon where+ getUnique = tyConUniq -- | TyCon reference type TyConName = Name TyCon-type TyConOccName = OccName TyCon-type TyConMap = HashMap TyConOccName TyCon+type TyConMap = UniqMap TyCon -- | The RHS of an Algebraic Datatype data AlgTyConRhs@@ -98,55 +95,29 @@ } | NewTyCon { dataCon :: !DataCon -- ^ The newtype DataCon- , ntEtadRhs :: ([TyName],Type) -- ^ The argument type of the newtype+ , ntEtadRhs :: ([TyVar],Type) -- ^ The argument type of the newtype -- DataCon in eta-reduced form, which is -- just the representation of the TyCon. -- The TyName's are the type-variables from -- the corresponding TyCon. }- deriving (Show,Generic,NFData,Alpha)--instance Alpha TyCon where- aeq' c tc1 tc2 = aeq' c (tyConName tc1) (tyConName tc2)-- fvAny' _ _ tc = pure tc-- close _ _ tc = tc- open _ _ tc = tc-- isPat _ = mempty--#if MIN_VERSION_unbound_generics(0,3,0)- isTerm _ = All True- nthPatFind _ = NthPatFind Left- namePatFind _ = NamePatFind (const (Left 0))-#else- isTerm _ = True- nthPatFind _ = Left- namePatFind _ _ = Left 0-#endif-- swaps' _ _ tc = tc- lfreshen' _ tc cont = cont tc mempty- freshen' _ tc = return (tc,mempty)-- acompare' c tc1 tc2 = acompare' c (tyConName tc1) (tyConName tc2)+ deriving (Show,Generic,NFData,Binary) -- | Create a Kind out of a TyConName mkKindTyCon :: TyConName -> Kind -> TyCon mkKindTyCon name kind- = PrimTyCon name kind 0+ = PrimTyCon (nameUniq name) name kind 0 -- | Does the TyCon look like a tuple TyCon isTupleTyConLike :: TyConName -> Bool-isTupleTyConLike nm = tupleName (name2String nm)+isTupleTyConLike nm = tupleName (nameOcc nm) where tupleName nm'- | '(' <- head nm'- , ')' <- last nm'- = all (== ',') (init $ tail nm')+ | '(' <- T.head nm'+ , ')' <- T.last nm'+ = T.all (== ',') (T.init $ T.tail nm') tupleName _ = False -- | Get the DataCons belonging to a TyCon@@ -154,3 +125,9 @@ tyConDataCons (AlgTyCon {algTcRhs = DataTyCon { dataCons = cons}}) = cons tyConDataCons (AlgTyCon {algTcRhs = NewTyCon { dataCon = con }}) = [con] tyConDataCons _ = []++isNewTypeTc+ :: TyCon+ -> Bool+isNewTypeTc (AlgTyCon {algTcRhs = NewTyCon {}}) = True+isNewTypeTc _ = False
src/Clash/Core/TyCon.hs-boot view
@@ -6,8 +6,7 @@ module Clash.Core.TyCon where -import Clash.Core.Name (Name, OccName)+import Clash.Core.Name (Name) data TyCon type TyConName = Name TyCon-type TyConOccName = OccName TyCon
src/Clash/Core/Type.hs view
@@ -14,6 +14,8 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE ViewPatterns #-} @@ -25,12 +27,11 @@ , Kind , KindOrType , KiName- , KiOccName , TyName- , TyOccName , TyVar , tyView , coreView+ , coreView1 , typeKind , mkTyConTy , mkFunTy@@ -43,54 +44,84 @@ , isPolyFunTy , isPolyFunCoreTy , isPolyTy+ , isTypeFamilyApplication , isFunTy+ , isClassTy , applyFunTy- , applyTy , findFunSubst , reduceTypeFamily , undefinedTy , isIntegerTy , normalizeType+ , varAttrs+ , typeAttrs ) where -- External import-import Control.DeepSeq as DS-import Data.Hashable (Hashable)-import Data.HashMap.Strict (HashMap)-import qualified Data.HashMap.Strict as HashMap-import Data.List (foldl',isPrefixOf)-import Data.Maybe (isJust, mapMaybe)-import GHC.Base (isTrue#,(==#))-import GHC.Generics (Generic(..))-import GHC.Integer (smallInteger)-import GHC.Integer.Logarithms (integerLogBase#)-import Unbound.Generics.LocallyNameless (Alpha(..),Bind,Fresh,- Subst(..),SubstName(..),- acompare,aeq,bind,embed,- gacompare,gaeq,gfvAny,- runFreshM,unbind)-import Unbound.Generics.LocallyNameless.Extra ()-import Unbound.Generics.LocallyNameless.Unsafe (unsafeUnbind)+import Control.DeepSeq as DS+import Data.Binary (Binary)+import Data.Coerce (coerce)+import Data.Hashable (Hashable)+import Data.List (foldl')+import Data.Maybe (isJust, mapMaybe)+import GHC.Base (isTrue#,(==#))+import GHC.Generics (Generic(..))+import GHC.Integer (smallInteger)+import GHC.Integer.Logarithms (integerLogBase#) +-- GHC API+#if __GLASGOW_HASKELL__ >= 808+import PrelNames+ (ordLTDataConKey, ordEQDataConKey, ordGTDataConKey)+#else+import Unique (Unique)+import PrelNames+ (ltDataConKey, eqDataConKey, gtDataConKey)+#endif+import PrelNames+ (integerTyConKey, typeNatAddTyFamNameKey, typeNatExpTyFamNameKey,+ typeNatLeqTyFamNameKey, typeNatMulTyFamNameKey, typeNatSubTyFamNameKey,+ typeNatCmpTyFamNameKey)+import SrcLoc (wiredInSrcSpan)+import Unique (getKey)+ -- Local imports import Clash.Core.DataCon import Clash.Core.Name-import Clash.Core.Subst-import {-# SOURCE #-} Clash.Core.Term+import {-# SOURCE #-} Clash.Core.Subst import Clash.Core.TyCon import Clash.Core.TysPrim import Clash.Core.Var+import Clash.Unique import Clash.Util +#if __GLASGOW_HASKELL__ <= 806+ordLTDataConKey, ordEQDataConKey, ordGTDataConKey :: Unique.Unique+ordLTDataConKey = ltDataConKey+ordEQDataConKey = eqDataConKey+ordGTDataConKey = gtDataConKey+#endif++varAttrs :: Var a -> [Attr']+varAttrs t@(TyVar {}) =+ error $ $(curLoc) ++ "Unexpected argument: " ++ show t++varAttrs (Id _ _ ty _) =+ case ty of+ AnnType attrs _typ -> attrs+ _ -> []++ -- | Types in CoreHW: function and polymorphic types data Type- = VarTy !Kind !TyName -- ^ Type variable+ = VarTy !TyVar -- ^ Type variable | ConstTy !ConstTy -- ^ Type constant- | ForAllTy !(Bind TyVar Type) -- ^ Polymorphic Type+ | ForAllTy !TyVar !Type -- ^ Polymorphic Type | AppTy !Type !Type -- ^ Type Application | LitTy !LitTy -- ^ Type literal- deriving (Show,Generic,NFData,Hashable)+ | AnnType [Attr'] !Type -- ^ Annotated type, see Clash.Annotations.SynthesisAttributes+ deriving (Show,Generic,NFData,Hashable,Binary) -- | An easier view on types data TypeView@@ -103,13 +134,13 @@ data ConstTy = TyCon !TyConName -- ^ TyCon type | Arrow -- ^ Function type- deriving (Show,Generic,NFData,Alpha,Hashable)+ deriving (Eq,Ord,Show,Generic,NFData,Hashable,Binary) -- | Literal Types data LitTy = NumTy !Integer | SymTy !String- deriving (Show,Generic,NFData,Alpha,Hashable)+ deriving (Eq,Ord,Show,Generic,NFData,Hashable,Binary) -- | The level above types type Kind = Type@@ -118,44 +149,25 @@ -- | Reference to a Type type TyName = Name Type-type TyOccName = OccName Type -- | Reference to a Kind type KiName = Name Kind-type KiOccName = OccName Kind -instance Alpha Type where- fvAny' c nfn (VarTy t n) = fmap (VarTy t) $ fvAny' c nfn n- fvAny' c nfn t = fmap to . gfvAny c nfn $ from t-- aeq' c (VarTy _ n) (VarTy _ m) = aeq' c n m- aeq' c t1 t2 = gaeq c (from t1) (from t2)-- acompare' c (VarTy _ n) (VarTy _ m) = acompare' c n m- acompare' c t1 t2 = gacompare c (from t1) (from t2)--instance Subst a LitTy where- subst _ _ lt = lt- substs _ lt = lt--instance Subst a ConstTy where- subst _ _ ct = ct- substs _ ct = ct--instance Subst Term Type-instance Subst Type Type where- isvar (VarTy _ v) = Just (SubstName (nameOcc v))- isvar _ = Nothing--instance Eq Type where- (==) = aeq--instance Ord Type where- compare = acompare- -- | An easier view on types+--+-- Note [Arrow arguments]+--+-- Clash' Arrow type can either have 2 or 4 arguments, depending on who created it.+-- By default it has two arguments: the argument type of a function, and the result+-- type of a function.+--+-- So when do we have 4 arguments? When in Haskell/GHC land the arrow was+-- unsaturated. This can happen in instance heads, or in the eta-reduced+-- representation of newtypes. So what are those additional 2 arguments compared to+-- the "normal" function type? They're the kinds of argument and result type. tyView :: Type -> TypeView tyView ty@(AppTy _ _) = case splitTyAppM ty of Just (ConstTy Arrow, [ty1,ty2]) -> FunTy ty1 ty2+ Just (ConstTy Arrow, [_,_,ty1,ty2]) -> FunTy ty1 ty2 -- See Note [Arrow arguments] Just (ConstTy (TyCon tc), args) -> TyConApp tc args _ -> OtherType ty tyView (ConstTy (TyCon tc)) = TyConApp tc []@@ -164,15 +176,31 @@ -- | A view on types in which newtypes are transparent, the Signal type is -- transparent, and type functions are evaluated to WHNF (when possible). --+-- Strips away ALL layers. If no layers are found it returns the given type.+coreView :: TyConMap -> Type -> Type+coreView tcm ty =+ case coreView1 tcm ty of+ Nothing -> ty+ Just ty' -> coreView tcm ty'++-- | A view on types in which newtypes are transparent, the Signal type is+-- transparent, and type functions are evaluated to WHNF (when possible).+-- -- Only strips away one "layer".-coreView :: HashMap TyConOccName TyCon -> Type -> Maybe Type-coreView tcMap ty = case tyView ty of+coreView1 :: TyConMap -> Type -> Maybe Type+coreView1 tcMap ty = case tyView ty of TyConApp tcNm args- | name2String tcNm == "Clash.Signal.Internal.Signal"+ | nameOcc tcNm == "Clash.Signal.BiSignal.BiSignalIn"+ , [_,_,_,elTy] <- args+ -> Just elTy+ | nameOcc tcNm == "Clash.Signal.BiSignal.BiSignalOut"+ , [_,_,_,elTy] <- args+ -> Just elTy+ | nameOcc tcNm == "Clash.Signal.Internal.Signal" , [_,elTy] <- args -> Just elTy | otherwise- -> case tcMap HashMap.! nameOcc tcNm of+ -> case tcMap `lookupUniqMap'` tcNm of AlgTyCon {algTcRhs = (NewTyCon _ nt)} -> newTyConInstRhs nt args _ -> reduceTypeFamily tcMap ty@@ -182,15 +210,14 @@ -- list of argument types -- -- Returns /Nothing/ when under-applied-newTyConInstRhs :: ([TyName],Type) -> [Type] -> Maybe Type+newTyConInstRhs :: ([TyVar],Type) -> [Type] -> Maybe Type newTyConInstRhs (tvs,ty) tys | length tvs <= length tys- = Just (foldl AppTy (substTys (zip tvs' tys1) ty) tys2)+ = Just (foldl' AppTy (substTyWith tvs tys1 ty) tys2) | otherwise = Nothing where (tys1, tys2) = splitAtList tvs tys- tvs' = map nameOcc tvs -- | Make a function type of an argument and result type mkFunTy :: Type -> Type -> Type@@ -211,23 +238,24 @@ splitTyConAppM _ = Nothing -- | Is a type a Superkind?-isSuperKind :: HashMap TyConOccName TyCon -> Type -> Bool-isSuperKind tcMap (ConstTy (TyCon (((tcMap HashMap.!) . nameOcc) -> SuperKindTyCon {}))) = True+isSuperKind :: TyConMap -> Type -> Bool+isSuperKind tcMap (ConstTy (TyCon ((tcMap `lookupUniqMap'`) -> SuperKindTyCon {}))) = True isSuperKind _ _ = False -- | Determine the kind of a type-typeKind :: HashMap TyConOccName TyCon -> Type -> Kind-typeKind _ (VarTy k _) = k-typeKind m (ForAllTy b) = let (_,ty) = runFreshM $ unbind b- in typeKind m ty+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 HashMap.! nameOcc tc)) args+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@@ -235,33 +263,32 @@ kindFunResult :: Kind -> KindOrType -> Kind kindFunResult (tyView -> FunTy _ res) _ = res -kindFunResult (ForAllTy b) arg =- let (kv,ki) = runFreshM . unbind $ b- in substKindWith (zip [nameOcc (varName kv)] [arg]) ki+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+isPolyTy (ForAllTy _ _) = True isPolyTy (tyView -> FunTy _ res) = isPolyTy res isPolyTy _ = False -- | Split a function type in an argument and result type-splitFunTy :: HashMap TyConOccName TyCon+splitFunTy :: TyConMap -> Type -> Maybe (Type, Type)-splitFunTy m (coreView m -> Just ty) = splitFunTy m ty+splitFunTy m (coreView1 m -> Just ty) = splitFunTy m ty splitFunTy _ (tyView -> FunTy arg res) = Just (arg,res) splitFunTy _ _ = Nothing -splitFunTys :: HashMap TyConOccName TyCon+splitFunTys :: TyConMap -> Type -> ([Type],Type) splitFunTys m ty = go [] ty ty where- go args orig_ty (coreView m -> Just ty') = go args orig_ty ty'+ go args orig_ty (coreView1 m -> Just ty') = go args orig_ty ty' go args _ (tyView -> FunTy arg res) = go (arg:args) res res go args orig_ty _ = (reverse args, orig_ty) @@ -271,66 +298,60 @@ -> ([Either TyVar Type],Type) splitFunForallTy = go [] where- go args (ForAllTy b) = let (tv,ty) = runFreshM $ unbind b- in go (Left tv:args) ty+ go args (ForAllTy tv ty) = go (Left tv:args) ty go args (tyView -> FunTy arg res) = go (Right arg:args) res go args ty = (reverse args,ty) -- | Split a poly-function type in a: list of type-binders and argument types, -- and the result type. Looks through 'Signal' and type functions.-splitCoreFunForallTy :: HashMap TyConOccName TyCon+splitCoreFunForallTy :: TyConMap -> Type -> ([Either TyVar Type], Type) splitCoreFunForallTy tcm ty = go [] ty ty where- go args orig_ty (coreView tcm -> Just ty') = go args orig_ty ty'- go args _ (ForAllTy b) = let (tv,res) = runFreshM $ unbind b- in go (Left tv:args) res res- go args _ (tyView -> FunTy arg res) = go (Right arg:args) res res- go args orig_ty _ = (reverse args,orig_ty)+ go args orig_ty (coreView1 tcm -> Just ty') = go args orig_ty ty'+ go args _ (ForAllTy tv res) = go (Left tv:args) res res+ go args _ (tyView -> FunTy arg res) = go (Right arg:args) res res+ go args orig_ty _ = (reverse args,orig_ty) -- | Is a type a polymorphic or function type? isPolyFunTy :: Type -> Bool isPolyFunTy = not . null . fst . splitFunForallTy --- | Is a type a polymorphic or function type under 'coreView'?-isPolyFunCoreTy :: HashMap TyConOccName TyCon+-- | Is a type a polymorphic or function type under 'coreView1'?+isPolyFunCoreTy :: TyConMap -> Type -> Bool-isPolyFunCoreTy m (coreView m -> Just ty) = isPolyFunCoreTy m ty+isPolyFunCoreTy m (coreView1 m -> Just ty) = isPolyFunCoreTy m ty isPolyFunCoreTy _ ty = case tyView ty of FunTy _ _ -> True- OtherType (ForAllTy _) -> True+ OtherType (ForAllTy _ _) -> True _ -> False +-- | Extract attributes from type. Will return an empty list if this is an+-- AnnType with an empty list AND if this is not an AnnType at all.+typeAttrs+ :: Type+ -> [Attr']+typeAttrs (AnnType attrs _typ) = attrs+typeAttrs _ = []+ -- | Is a type a function type?-isFunTy :: HashMap TyConOccName TyCon+isFunTy :: TyConMap -> Type -> Bool isFunTy m = isJust . splitFunTy m -- | Apply a function type to an argument type and get the result type-applyFunTy :: HashMap TyConOccName TyCon+applyFunTy :: TyConMap -> Type -> Type -> Type-applyFunTy m (coreView m -> Just ty) arg = applyFunTy m ty arg-applyFunTy _ (tyView -> FunTy _ resTy) _ = resTy+applyFunTy m (coreView1 m -> Just ty) arg = applyFunTy m ty arg+applyFunTy _ (tyView -> FunTy _ resTy) _ = resTy applyFunTy _ _ _ = error $ $(curLoc) ++ "Report as bug: not a FunTy" --- | Substitute the type variable of a type ('ForAllTy') with another type-applyTy :: Fresh m- => HashMap TyConOccName TyCon- -> Type- -> KindOrType- -> m Type-applyTy tcm (coreView tcm -> Just ty) arg = applyTy tcm ty arg-applyTy _ (ForAllTy b) arg = do- (tv,ty) <- unbind b- return (substTy (nameOcc (varName tv)) arg ty)-applyTy _ ty arg = error ($(curLoc) ++ "applyTy: not a forall type:\n" ++ show ty ++ "\nArg:\n" ++ show arg)- -- | Split a type application in the applied type and the argument types splitTyAppM :: Type -> Maybe (Type, [Type])@@ -346,7 +367,7 @@ -- Given a set of type functions, and list of argument types, get the first -- type function that matches, and return its substituted RHS type.-findFunSubst :: HashMap TyConOccName TyCon -> [([Type],Type)] -> [Type] -> Maybe Type+findFunSubst :: TyConMap -> [([Type],Type)] -> [Type] -> Maybe Type findFunSubst _ [] _ = Nothing findFunSubst tcm (tcSubst:rest) args = case funSubsts tcm tcSubst args of Just ty -> Just ty@@ -355,10 +376,10 @@ -- Given a ([LHS match type], RHS type) representing a type function, and -- a set of applied types. Match LHS with args, and when successful, return -- a substituted RHS-funSubsts :: HashMap TyConOccName TyCon -> ([Type],Type) -> [Type] -> Maybe Type+funSubsts :: TyConMap -> ([Type],Type) -> [Type] -> Maybe Type funSubsts tcm (tcSubstLhs,tcSubstRhs) args = do tySubts <- foldl' (funSubst tcm) (Just []) (zip tcSubstLhs args)- let tyRhs = substTys tySubts tcSubstRhs+ let tyRhs = uncurry substTyWith (unzip tySubts) tcSubstRhs -- Type functions can return higher-kinded types case drop (length tcSubstLhs) args of [] -> return tyRhs@@ -372,14 +393,14 @@ -- are a match. If they do match, and the LHS is a variable, return a -- substitution funSubst- :: HashMap TyConOccName TyCon- -> Maybe [(TyOccName,Type)]+ :: TyConMap+ -> Maybe [(TyVar,Type)] -> (Type,Type)- -> Maybe [(TyOccName,Type)]+ -> Maybe [(TyVar,Type)] funSubst _ Nothing = const Nothing funSubst tcm (Just s) = uncurry go where- go (VarTy _ (nameOcc -> nmF)) ty = case lookup nmF s of+ go (VarTy nmF) ty = case lookup nmF s of Nothing -> Just ((nmF,ty):s) -- Given, for example, the type family definition: --@@ -394,13 +415,33 @@ -- So this is why, whenever we match against a type variable, we first -- check if there is already a substitution defined for this type variable, -- and if so, the applied type, and the type in the substitution should match.- Just ty' | ty' == ty -> Just s+ Just ty' | ty' `aeqType` ty -> Just s _ -> Nothing go ty1 (reduceTypeFamily tcm -> Just ty2) = go ty1 ty2 -- See [Note: lazy type families]- go ty1@(LitTy _) ty2 = if ty1 == ty2 then Just s else Nothing+ go ty1@(LitTy _) ty2 = if ty1 `aeqType` ty2 then Just s else Nothing go (tyView -> TyConApp tc argTys) (tyView -> TyConApp tc' argTys') | tc == tc' = foldl' (funSubst tcm) (Just s) (zip argTys argTys')+ -- Whenever type classes have associated types whose instances 'map' to+ -- functions, we try to find substitutions in the LHS and RHS of these+ -- (type-level) functions. Because we use @funSubst@ recursively, we+ -- implicitly check if these functions are of the same arity and match+ -- in the first place. An example of such a construct:+ --+ -- class Example p where+ -- type AB p+ --+ -- instance Example (a -> a) where+ -- type AB (a -> a) = a+ --+ -- In the given example, we would find two substitutions. For example, when+ -- matching against `Char -> Char` we'd find a duplicate `a -> Char`. We+ -- can't think of any (type-checking) cases where these mappings would map+ -- to different types, so this is OK for our purposes.+ go (tyView -> FunTy a b) (tyView -> FunTy a' b') =+ (++) <$> funSubst tcm (Just s) (a, a')+ <*> funSubst tcm (Just s) (b, b')+ go _ _ = Nothing {- [Note: lazy type families]@@ -412,65 +453,55 @@ to (WH)NF when the formal parameter is _not_ a type variable. -} -reduceTypeFamily :: HashMap TyConOccName TyCon -> Type -> Maybe Type+reduceTypeFamily :: TyConMap -> Type -> Maybe Type reduceTypeFamily tcm (tyView -> TyConApp tc tys)-#if MIN_VERSION_ghc(8,2,0)- | name2String tc == "GHC.TypeNats.+"-#else- | name2String tc == "GHC.TypeLits.+"-#endif+ | nameUniq tc == getKey typeNatAddTyFamNameKey , [i1, i2] <- mapMaybe (litView tcm) tys = Just (LitTy (NumTy (i1 + i2))) -#if MIN_VERSION_ghc(8,2,0)- | name2String tc == "GHC.TypeNats.*"-#else- | name2String tc == "GHC.TypeLits.*"-#endif+ | nameUniq tc == getKey typeNatMulTyFamNameKey , [i1, i2] <- mapMaybe (litView tcm) tys = Just (LitTy (NumTy (i1 * i2))) -#if MIN_VERSION_ghc(8,2,0)- | name2String tc == "GHC.TypeNats.^"-#else- | name2String tc == "GHC.TypeLits.^"-#endif+ | nameUniq tc == getKey typeNatExpTyFamNameKey , [i1, i2] <- mapMaybe (litView tcm) tys = Just (LitTy (NumTy (i1 ^ i2))) -#if MIN_VERSION_ghc(8,2,0)- | name2String tc == "GHC.TypeNats.-"-#else- | name2String tc == "GHC.TypeLits.-"-#endif+ | nameUniq tc == getKey typeNatSubTyFamNameKey , [i1, i2] <- mapMaybe (litView tcm) tys- = Just (LitTy (NumTy (i1 - i2)))+ , let z = i1 - i2+ , z >= 0+ = Just (LitTy (NumTy z)) -#if MIN_VERSION_ghc(8,2,0)- | name2String tc == "GHC.TypeNats.<=?"-#else- | name2String tc == "GHC.TypeLits.<=?"-#endif+ | nameUniq tc == getKey typeNatLeqTyFamNameKey , [i1, i2] <- mapMaybe (litView tcm) tys- , Just (FunTyCon {tyConKind = tck}) <- HashMap.lookup (nameOcc tc) tcm+ , Just (FunTyCon {tyConKind = tck}) <- lookupUniqMap tc tcm , (_,tyView -> TyConApp boolTcNm []) <- splitFunTys tcm tck- , Just boolTc <- HashMap.lookup (nameOcc boolTcNm) tcm- = let [falseTc,trueTc] = map (coerceName . dcName) (tyConDataCons boolTc)+ , Just boolTc <- lookupUniqMap boolTcNm tcm+ = let [falseTc,trueTc] = map (coerce . dcName) (tyConDataCons boolTc) in if i1 <= i2 then Just (mkTyConApp trueTc [] ) else Just (mkTyConApp falseTc []) - | name2String tc == "GHC.TypeLits.Extra.FLog"+ | nameUniq tc == getKey typeNatCmpTyFamNameKey -- "GHC.TypeNats.CmpNat" , [i1, i2] <- mapMaybe (litView tcm) tys+ = Just $ ConstTy $ TyCon $+ case compare i1 i2 of+ LT -> Name User "GHC.Types.LT" (getKey ordLTDataConKey) wiredInSrcSpan+ EQ -> Name User "GHC.Types.EQ" (getKey ordEQDataConKey) wiredInSrcSpan+ GT -> Name User "GHC.Types.GT" (getKey ordGTDataConKey) wiredInSrcSpan++ | nameOcc tc `elem` ["GHC.TypeLits.Extra.FLog", "GHC.TypeNats.FLog"]+ , [i1, i2] <- mapMaybe (litView tcm) tys , i1 > 1 , i2 > 0 = Just (LitTy (NumTy (smallInteger (integerLogBase# i1 i2)))) - | name2String tc == "GHC.TypeLits.Extra.CLog"+ | nameOcc tc `elem` ["GHC.TypeLits.Extra.CLog", "GHC.TypeNats.CLog"] , [i1, i2] <- mapMaybe (litView tcm) tys , Just k <- clogBase i1 i2 = Just (LitTy (NumTy (toInteger k))) - | name2String tc == "GHC.TypeLits.Extra.Log"+ | nameOcc tc `elem` ["GHC.TypeLits.Extra.Log", "GHC.TypeNats.Log"] , [i1, i2] <- mapMaybe (litView tcm) tys , i1 > 1 , i2 > 0@@ -483,76 +514,93 @@ else Just (LitTy (NumTy (smallInteger z1))) - | name2String tc == "GHC.TypeLits.Extra.GCD"+ | nameOcc tc `elem` ["GHC.TypeLits.Extra.GCD", "GHC.TypeNats.GCD"] , [i1, i2] <- mapMaybe (litView tcm) tys = Just (LitTy (NumTy (i1 `gcd` i2))) - | name2String tc == "GHC.TypeLits.Extra.LCM"+ | nameOcc tc `elem` ["GHC.TypeLits.Extra.LCM", "GHC.TypeNats.LCM"] , [i1, i2] <- mapMaybe (litView tcm) tys = Just (LitTy (NumTy (i1 `lcm` i2))) - | name2String tc == "GHC.TypeLits.Extra.Div"+ | nameOcc tc `elem` ["GHC.TypeLits.Extra.Div", "GHC.TypeNats.Div"] , [i1, i2] <- mapMaybe (litView tcm) tys , i2 > 0 = Just (LitTy (NumTy (i1 `div` i2))) - | name2String tc == "GHC.TypeLits.Extra.Mod"+ | nameOcc tc `elem` ["GHC.TypeLits.Extra.Mod", "GHC.TypeNats.Mod"] , [i1, i2] <- mapMaybe (litView tcm) tys , i2 > 0 = Just (LitTy (NumTy (i1 `mod` i2))) - | Just (FunTyCon {tyConSubst = tcSubst}) <- HashMap.lookup (nameOcc tc) tcm+ | Just (FunTyCon {tyConSubst = tcSubst}) <- lookupUniqMap tc tcm = findFunSubst tcm tcSubst tys reduceTypeFamily _ _ = Nothing -litView :: HashMap TyConOccName TyCon -> Type -> Maybe Integer+-- |+isTypeFamilyApplication :: TyConMap -> Type -> Bool+isTypeFamilyApplication tcm (tyView -> TyConApp tcNm _args)+ | Just (FunTyCon {}) <- lookupUniqMap tcNm tcm = True+isTypeFamilyApplication _tcm _type = False++litView :: TyConMap -> Type -> Maybe Integer litView _ (LitTy (NumTy i)) = Just i litView m (reduceTypeFamily m -> Just ty') = litView m ty' litView _ _ = Nothing --- | The type of GHC.Err.undefined :: forall a . a-undefinedTy :: Type+-- | The type @forall a . a@+undefinedTy ::Type undefinedTy =- let aNm = string2SystemName "a"- in ForAllTy (bind (TyVar aNm (embed liftedTypeKind)) (VarTy liftedTypeKind aNm))+ let aNm = mkUnsafeSystemName "a" 0+ aTv = (TyVar aNm 0 liftedTypeKind)+ in ForAllTy aTv (VarTy aTv) isIntegerTy :: Type -> Bool-isIntegerTy (ConstTy (TyCon (nm)))- | "GHC.Integer.Type.Integer" `isPrefixOf` (name2String nm) = True+isIntegerTy (ConstTy (TyCon nm)) = nameUniq nm == getKey integerTyConKey isIntegerTy _ = False --- Normalize a type, looking through Signals and newtypes+-- | Normalize a type, looking through Signals and newtypes ----- For example: Vec (6-1) (Unsigned (3+1)) normalizes to Vec 5 (Unsigned 4)-normalizeType :: HashMap TyConOccName TyCon -> Type -> Type+-- For example: @Signal a (Vec (6-1) (Unsigned (3+1)))@ normalizes to @Vec 5 (Unsigned 4)@+normalizeType :: TyConMap -> Type -> Type normalizeType tcMap = go where go ty = case tyView ty of TyConApp tcNm args- | name2String tcNm == "Clash.Signal.Internal.Signal"+ | nameOcc tcNm == "Clash.Signal.Internal.Signal" , [_,elTy] <- args -> go elTy -- These Clash types are implemented with newtypes. -- We need to keep these newtypes because they define the width of the numbers.- | name2String tcNm == "Clash.Sized.Internal.BitVector.Bit" ||- name2String tcNm == "Clash.Sized.Internal.BitVector.BitVector" ||- name2String tcNm == "Clash.Sized.Internal.Index.Index" ||- name2String tcNm == "Clash.Sized.Internal.Signed.Signed" ||- name2String tcNm == "Clash.Sized.Internal.Unsigned.Unsigned"+ | nameOcc tcNm == "Clash.Sized.Internal.BitVector.Bit" ||+ nameOcc tcNm == "Clash.Sized.Internal.BitVector.BitVector" ||+ nameOcc tcNm == "Clash.Sized.Internal.Index.Index" ||+ nameOcc tcNm == "Clash.Sized.Internal.Signed.Signed" ||+ nameOcc tcNm == "Clash.Sized.Internal.Unsigned.Unsigned" -> mkTyConApp tcNm (map go args) | otherwise- -> case tcMap HashMap.! nameOcc tcNm of- AlgTyCon {algTcRhs = (NewTyCon _ nt)}+ -> case lookupUniqMap' tcMap tcNm of+ AlgTyCon {algTcRhs = (NewTyCon _ nt)} -> case newTyConInstRhs nt args of Just ty' -> go ty' Nothing -> ty- _ -> let args' = map go args- ty' = mkTyConApp tcNm args'- in case reduceTypeFamily tcMap ty' of- Just ty'' -> ty''- Nothing -> ty'+ _ ->+ let args' = map go args+ ty' = mkTyConApp tcNm args'+ in case reduceTypeFamily tcMap ty' of+ Just ty'' -> ty''+ Nothing -> ty' FunTy ty1 ty2 -> mkFunTy (go ty1) (go ty2)- (OtherType (ForAllTy (unsafeUnbind -> (tyvar,ty'))))- -> ForAllTy (bind tyvar (go ty'))+ OtherType (ForAllTy tyvar ty')+ -> ForAllTy tyvar (go ty') _ -> ty++isClassTy+ :: TyConMap+ -> Type+ -> Bool+isClassTy tcm (tyView -> TyConApp tcNm _) =+ case lookupUniqMap tcNm tcm of+ Just (AlgTyCon {isClassTc}) -> isClassTc+ _ -> False+isClassTy _ _ = False
src/Clash/Core/Type.hs-boot view
@@ -12,29 +12,23 @@ module Clash.Core.Type where import Control.DeepSeq (NFData)+import Data.Binary (Binary) import Data.Hashable (Hashable) import GHC.Generics (Generic)-import Unbound.Generics.LocallyNameless (Alpha,Subst) import Clash.Core.Name-import {-# SOURCE #-} Clash.Core.Term import {-# SOURCE #-} Clash.Core.TyCon data Type type Kind = Type type TyName = Name Type-type TyOccName = OccName Type type KiName = Name Kind-type KiOccName = OccName Kind -instance Eq Type instance Generic Type instance Show Type-instance Alpha Type-instance Subst Type Type-instance Subst Term Type instance NFData Type instance Hashable Type+instance Binary Type mkTyConTy :: TyConName -> Type
src/Clash/Core/TysPrim.hs view
@@ -7,7 +7,8 @@ Builtin Type and Kind definitions -} -{-# LANGUAGE CPP #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-} module Clash.Core.TysPrim ( liftedTypeKind@@ -29,30 +30,29 @@ ) where -import Control.Arrow (first)-import Data.HashMap.Strict (HashMap)-import qualified Data.HashMap.Strict as HashMap+import qualified Data.List as List import PrelNames-import Unique (Unique, getKey)+import Unique (getKey) import Clash.Core.Name import Clash.Core.TyCon import {-# SOURCE #-} Clash.Core.Type+import Clash.Unique -- | Builtin Name tySuperKindTyConName, liftedTypeKindTyConName, typeNatKindTyConName, typeSymbolKindTyConName :: TyConName-tySuperKindTyConName = string2SystemName "BOX"-liftedTypeKindTyConName = string2SystemName "*"-typeNatKindTyConName = string2SystemName "Nat"-typeSymbolKindTyConName = string2SystemName "Symbol"+tySuperKindTyConName = mkUnsafeSystemName "tYPE" (getKey tYPETyConKey)+liftedTypeKindTyConName = mkUnsafeSystemName "*" (getKey liftedTypeKindTyConKey)+typeNatKindTyConName = mkUnsafeSystemName "Nat" (getKey typeNatKindConNameKey)+typeSymbolKindTyConName = mkUnsafeSystemName "Symbol" (getKey typeSymbolKindConNameKey) -- | Builtin Kind-liftedTypeKindtc, tySuperKindtc, typeNatKindtc, typeSymbolKindtc :: TyCon-tySuperKindtc = SuperKindTyCon tySuperKindTyConName-liftedTypeKindtc = mkKindTyCon liftedTypeKindTyConName tySuperKind-typeNatKindtc = mkKindTyCon typeNatKindTyConName tySuperKind-typeSymbolKindtc = mkKindTyCon typeSymbolKindTyConName tySuperKind+liftedTypeKindTc, tySuperKindTc, typeNatKindTc, typeSymbolKindTc :: TyCon+tySuperKindTc = SuperKindTyCon (nameUniq tySuperKindTyConName) tySuperKindTyConName+liftedTypeKindTc = mkKindTyCon liftedTypeKindTyConName tySuperKind+typeNatKindTc = mkKindTyCon typeNatKindTyConName tySuperKind+typeSymbolKindTc = mkKindTyCon typeSymbolKindTyConName tySuperKind liftedTypeKind, tySuperKind, typeNatKind, typeSymbolKind :: Type tySuperKind = mkTyConTy tySuperKindTyConName@@ -60,43 +60,36 @@ typeNatKind = mkTyConTy typeNatKindTyConName typeSymbolKind = mkTyConTy typeSymbolKindTyConName -uniqueToInteger :: Unique -> Integer-uniqueToInteger = toInteger . getKey- intPrimTyConName, integerPrimTyConName, charPrimTyConName, stringPrimTyConName, voidPrimTyConName, wordPrimTyConName, int64PrimTyConName, word64PrimTyConName, floatPrimTyConName, doublePrimTyConName, naturalPrimTyConName, byteArrayPrimTyConName :: TyConName-intPrimTyConName = makeSystemName "GHC.Prim.Int#"- (uniqueToInteger intPrimTyConKey)-integerPrimTyConName = makeSystemName "GHC.Integer.Type.Integer"- (uniqueToInteger integerTyConKey)-stringPrimTyConName = string2SystemName "String"-charPrimTyConName = makeSystemName "GHC.Prim.Char#"- (uniqueToInteger charPrimTyConKey)-voidPrimTyConName = string2SystemName "VOID"-wordPrimTyConName = makeSystemName "GHC.Prim.Word#"- (uniqueToInteger wordPrimTyConKey)-int64PrimTyConName = makeSystemName "GHC.Prim.Int64#"- (uniqueToInteger int64PrimTyConKey)-word64PrimTyConName = makeSystemName "GHC.Prim.Word64#"- (uniqueToInteger word64PrimTyConKey)-floatPrimTyConName = makeSystemName "GHC.Prim.Float#"- (uniqueToInteger floatPrimTyConKey)-doublePrimTyConName = makeSystemName "GHC.Prim.Double#"- (uniqueToInteger doublePrimTyConKey)-#if MIN_VERSION_ghc(8,2,0)-naturalPrimTyConName = makeSystemName "GHC.Natural.Natural"- (uniqueToInteger naturalTyConKey)-#else-naturalPrimTyConName = string2SystemName "GHC.Natural.Natural"-#endif-byteArrayPrimTyConName = makeSystemName "GHC.Prim.ByteArray#"- (uniqueToInteger byteArrayPrimTyConKey)+intPrimTyConName = mkUnsafeSystemName "GHC.Prim.Int#"+ (getKey intPrimTyConKey)+integerPrimTyConName = mkUnsafeSystemName "GHC.Integer.Type.Integer"+ (getKey integerTyConKey)+stringPrimTyConName = mkUnsafeSystemName "GHC.Prim.Addr#" (getKey addrPrimTyConKey)+charPrimTyConName = mkUnsafeSystemName "GHC.Prim.Char#"+ (getKey charPrimTyConKey)+voidPrimTyConName = mkUnsafeSystemName "Void#" (getKey voidPrimTyConKey)+wordPrimTyConName = mkUnsafeSystemName "GHC.Prim.Word#"+ (getKey wordPrimTyConKey)+int64PrimTyConName = mkUnsafeSystemName "GHC.Prim.Int64#"+ (getKey int64PrimTyConKey)+word64PrimTyConName = mkUnsafeSystemName "GHC.Prim.Word64#"+ (getKey word64PrimTyConKey)+floatPrimTyConName = mkUnsafeSystemName "GHC.Prim.Float#"+ (getKey floatPrimTyConKey)+doublePrimTyConName = mkUnsafeSystemName "GHC.Prim.Double#"+ (getKey doublePrimTyConKey)+naturalPrimTyConName = mkUnsafeSystemName "GHC.Natural.Natural"+ (getKey naturalTyConKey)+byteArrayPrimTyConName = mkUnsafeSystemName "GHC.Prim.ByteArray#"+ (getKey byteArrayPrimTyConKey) liftedPrimTC :: TyConName -> TyCon-liftedPrimTC name = PrimTyCon name liftedTypeKind 0+liftedPrimTC name = PrimTyCon (nameUniq name) name liftedTypeKind 0 -- | Builtin Type intPrimTc, integerPrimTc, charPrimTc, stringPrimTc, voidPrimTc, wordPrimTc,@@ -131,22 +124,22 @@ naturalPrimTy = mkTyConTy naturalPrimTyConName byteArrayPrimTy = mkTyConTy byteArrayPrimTyConName -tysPrimMap :: HashMap TyConOccName TyCon-tysPrimMap = HashMap.fromList $ map (first nameOcc)- [ (tySuperKindTyConName,tySuperKindtc)- , (liftedTypeKindTyConName,liftedTypeKindtc)- , (typeNatKindTyConName,typeNatKindtc)- , (typeSymbolKindTyConName,typeSymbolKindtc)- , (intPrimTyConName,intPrimTc)- , (integerPrimTyConName,integerPrimTc)- , (charPrimTyConName,charPrimTc)- , (stringPrimTyConName,stringPrimTc)- , (voidPrimTyConName,voidPrimTc)- , (wordPrimTyConName,wordPrimTc)- , (int64PrimTyConName,int64PrimTc)- , (word64PrimTyConName,word64PrimTc)- , (floatPrimTyConName,floatPrimTc)- , (doublePrimTyConName,doublePrimTc)- , (naturalPrimTyConName,naturalPrimTc)- , (byteArrayPrimTyConName,byteArrayPrimTc)+tysPrimMap :: TyConMap+tysPrimMap = List.foldl' (\s (k,x) -> extendUniqMap k x s) emptyUniqMap+ [ (tySuperKindTyConName , tySuperKindTc)+ , (liftedTypeKindTyConName , liftedTypeKindTc)+ , (typeNatKindTyConName , typeNatKindTc)+ , (typeSymbolKindTyConName , typeSymbolKindTc)+ , (intPrimTyConName , intPrimTc)+ , (integerPrimTyConName , integerPrimTc)+ , (charPrimTyConName , charPrimTc)+ , (stringPrimTyConName , stringPrimTc)+ , (voidPrimTyConName , voidPrimTc)+ , (wordPrimTyConName , wordPrimTc)+ , (int64PrimTyConName , int64PrimTc)+ , (word64PrimTyConName , word64PrimTc)+ , (floatPrimTyConName , floatPrimTc)+ , (doublePrimTyConName , doublePrimTc)+ , (naturalPrimTyConName , naturalPrimTc)+ , (byteArrayPrimTyConName , byteArrayPrimTc) ]
src/Clash/Core/Util.hs view
@@ -6,133 +6,424 @@ Smart constructor and destructor functions for CoreHW -} +{-# LANGUAGE CPP #-}+{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE ViewPatterns #-} module Clash.Core.Util where +import Control.Concurrent.Supply (Supply, freshId)+import qualified Control.Lens as Lens import Control.Monad.Trans.Except (Except, throwE)-import qualified Data.HashMap.Strict as HMS-import qualified Data.HashMap.Lazy as HashMap-import Data.HashMap.Lazy (HashMap)+import Data.Coerce (coerce)+import qualified Data.IntSet as IntSet import qualified Data.HashSet as HashSet-import Data.Maybe (fromJust, mapMaybe)-import Unbound.Generics.LocallyNameless- (Fresh, bind, embed, rebind, unbind, unembed, unrebind, unrec)-import Unbound.Generics.LocallyNameless.Unsafe (unsafeUnbind)+import Data.List+ (foldl', mapAccumR, elemIndices, nub)+import Data.Maybe (fromJust, mapMaybe, catMaybes)+import qualified Data.Text as T+import Data.Text.Prettyprint.Doc (line)+#if !MIN_VERSION_base(4,11,0)+import Data.Semigroup+#endif -import Clash.Core.DataCon (DataCon, dcType, dataConInstArgTys)+import Clash.Core.DataCon+ (DataCon (MkData), dcType, dcUnivTyVars, dcExtTyVars, dcArgTys)+import Clash.Core.FreeVars+ (termFreeVarsX, tyFVsOfTypes, typeFreeVars) import Clash.Core.Literal (literalType) import Clash.Core.Name- (Name (..), name2String, string2SystemName)-import Clash.Core.Pretty (showDoc)+ (Name (..), OccName, mkUnsafeInternalName, mkUnsafeSystemName)+import Clash.Core.Pretty (ppr, showPpr)+import Clash.Core.Subst+ (extendTvSubst, mkSubst, mkTvSubst, substTy, substTyWith,+ substTyInVar, extendTvSubstList) import Clash.Core.Term- (LetBinding, Pat (..), Term (..), TmName, TmOccName)+ (LetBinding, Pat (..), PrimInfo (..), Term (..), Alt, WorkInfo (..),+ TickInfo (..), collectArgs) import Clash.Core.Type- (Kind, LitTy (..), TyName, TyOccName, Type (..), TypeView (..), applyTy,- coreView, isFunTy, isPolyFunCoreTy, mkFunTy, splitFunTy, tyView)+ (Kind, LitTy (..), Type (..), TypeView (..),+ coreView, coreView1, isFunTy, isPolyFunCoreTy, mkFunTy, splitFunTy, tyView,+ undefinedTy, isTypeFamilyApplication) import Clash.Core.TyCon- (TyCon (..), TyConOccName, tyConDataCons)+ (TyConMap, tyConDataCons) import Clash.Core.TysPrim (typeNatKind)-import Clash.Core.Var (Id, TyVar, Var (..), varType)+import Clash.Core.Var+ (Id, TyVar, Var (..), isLocalId, mkLocalId, mkTyVar)+import Clash.Core.VarEnv+ (InScopeSet, VarEnv, emptyVarEnv, extendInScopeSet, extendVarEnv,+ lookupVarEnv, mkInScopeSet, uniqAway, extendInScopeSetList, unionInScope,+ mkVarSet, unionVarSet, unitVarSet, emptyVarSet)+import Clash.Unique import Clash.Util -- | Type environment/context-type Gamma = HashMap TmOccName Type+type Gamma = VarEnv Type -- | Kind environment/context-type Delta = HashMap TyOccName Kind+type Delta = VarEnv Kind +-- | Given the left and right side of an equation, normalize it such that+-- equations of the following forms:+--+-- * 5 ~ n + 2+-- * 5 ~ 2 + n+-- * n + 2 ~ 5+-- * 2 + n ~ 5+--+-- are returned as (5, 2, n)+normalizeAdd+ :: (Type, Type)+ -> Maybe (Integer, Integer, Type)+normalizeAdd (a, b) = do+ (n, rhs) <- lhsLit a b+ case tyView rhs of+ TyConApp (nameOcc -> "GHC.TypeNats.+") [left, right] -> do+ (m, o) <- lhsLit left right+ return (n, m, o)+ _ ->+ Nothing+ where+ lhsLit x (LitTy (NumTy n)) = Just (n, x)+ lhsLit (LitTy (NumTy n)) y = Just (n, y)+ lhsLit _ _ = Nothing++-- | Data type that indicates what kind of solution (if any) was found+data TypeEqSolution+ = Solution (TyVar, Type)+ -- ^ Solution was found. Variable equals some integer.+ | AbsurdSolution+ -- ^ A solution was found, but it involved negative naturals.+ | NoSolution+ -- ^ Given type wasn't an equation, or it was unsolvable.+ deriving (Show, Eq)++catSolutions :: [TypeEqSolution] -> [(TyVar, Type)]+catSolutions = mapMaybe getSol+ where+ getSol (Solution s) = Just s+ getSol _ = Nothing++-- | Solve given equations and return all non-absurd solutions+solveNonAbsurds :: TyConMap -> [(Type, Type)] -> [(TyVar, Type)]+solveNonAbsurds _tcm [] = []+solveNonAbsurds tcm (eq:eqs) =+ solved ++ solveNonAbsurds tcm eqs+ where+ solvers = [pure . solveAdd, solveEq tcm]+ solved = catSolutions (concat [s eq | s <- solvers])++-- | Solve simple equalities such as:+--+-- * a ~ 3+-- * 3 ~ a+-- * SomeType a b ~ SomeType 3 5+-- * SomeType 3 5 ~ SomeType a b+-- * SomeType a 5 ~ SomeType 3 b+--+solveEq :: TyConMap -> (Type, Type) -> [TypeEqSolution]+solveEq tcm (coreView tcm -> left, coreView tcm -> right) =+ case (left, right) of+ (VarTy tyVar, ConstTy {}) ->+ -- a ~ 3+ [Solution (tyVar, right)]+ (ConstTy {}, VarTy tyVar) ->+ -- 3 ~ a+ [Solution (tyVar, left)]+ (ConstTy {}, ConstTy {}) ->+ -- Int /= Char+ if left /= right then [AbsurdSolution] else []+ (LitTy {}, LitTy {}) ->+ -- 3 /= 5+ if left /= right then [AbsurdSolution] else []+ _ ->+ -- The call to 'coreView' at the start of 'solveEq' should have reduced+ -- all solvable type families. If we encounter one here that means the+ -- type family is stuck (and that we shouldn't compare it to anything!).+ if any (isTypeFamilyApplication tcm) [left, right] then+ []+ else+ case (tyView left, tyView right) of+ (TyConApp leftNm leftTys, TyConApp rightNm rightTys) ->+ -- SomeType a b ~ SomeType 3 5 (or other way around)+ if leftNm == rightNm then+ concat (map (solveEq tcm) (zip leftTys rightTys))+ else+ [AbsurdSolution]+ _ ->+ []++-- | Solve equations supported by @normalizeAdd@. See documentation of+-- @TypeEqSolution@ to understand the return value.+solveAdd+ :: (Type, Type)+ -> TypeEqSolution+solveAdd ab =+ case normalizeAdd ab of+ Just (n, m, VarTy tyVar) ->+ if n >= 0 && m >= 0 && n - m >= 0 then+ Solution (tyVar, (LitTy (NumTy (n - m))))+ else+ AbsurdSolution+ _ ->+ NoSolution++-- | If type is an equation, return LHS and RHS.+typeEq+ :: TyConMap+ -> Type+ -> Maybe (Type, Type)+typeEq tcm ty =+ case tyView (coreView tcm ty) of+ TyConApp (nameOcc -> "GHC.Prim.~#") [_, _, left, right] ->+ Just (coreView tcm left, coreView tcm right)+ _ ->+ Nothing++-- | Get constraint equations+altEqs+ :: TyConMap+ -> Alt+ -> [(Type, Type)]+altEqs tcm (pat, _term) =+ catMaybes (map (typeEq tcm . varType) (snd (patIds pat)))++-- | Tests for unreachable alternative due to types being "absurd". See+-- @isAbsurdEq@ for more info.+isAbsurdAlt+ :: TyConMap+ -> Alt+ -> Bool+isAbsurdAlt tcm alt =+ any (isAbsurdEq tcm) (altEqs tcm alt)++-- | Determines if an "equation" obtained through @altEqs@ 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.+isAbsurdEq+ :: TyConMap+ -> (Type, Type)+ -> Bool+isAbsurdEq tcm ((left0, right0)) =+ case (coreView tcm left0, coreView tcm right0) of+ (solveAdd -> AbsurdSolution) -> True+ lr -> any (==AbsurdSolution) (solveEq tcm lr)++-- Safely substitute global type variables in a list of potentially+-- shadowing type variables.+substGlobalsInExistentials+ :: HasCallStack+ => InScopeSet+ -- ^ Variables in scope+ -> [TyVar]+ -- ^ List of existentials to apply the substitution for+ -> [(TyVar, Type)]+ -- ^ Substitutions+ -> [TyVar]+substGlobalsInExistentials is exts substs0 = result+ -- TODO: Is is actually possible that existentials shadow each other? If they+ -- TODO: can't, we can remove this function+ where+ iss = scanl extendInScopeSet is exts+ substs1 = map (\is_ -> extendTvSubstList (mkSubst is_) substs0) iss+ result = zipWith substTyInVar substs1 exts++-- | Safely substitute type variables in a list of existentials. This function+-- will account for cases where existentials shadow each other.+substInExistentialsList+ :: HasCallStack+ => InScopeSet+ -- ^ Variables in scope+ -> [TyVar]+ -- ^ List of existentials to apply the substitution for+ -> [(TyVar, Type)]+ -- ^ Substitutions+ -> [TyVar]+substInExistentialsList is exts substs =+ foldl (substInExistentials is) exts substs++-- | Safely substitute a type variable in a list of existentials. This function+-- will account for cases where existentials shadow each other.+substInExistentials+ :: HasCallStack+ => InScopeSet+ -- ^ Variables in scope+ -> [TyVar]+ -- ^ List of existentials to apply the substitution for+ -> (TyVar, Type)+ -- ^ Substitution+ -> [TyVar]+substInExistentials is exts subst@(typeVar, _type) =+ -- TODO: Is is actually possible that existentials shadow each other? If they+ -- TODO: can't, we can remove this function+ case elemIndices typeVar exts of+ [] ->+ -- We're not replacing any of the existentials, but a global variable+ substGlobalsInExistentials is exts [subst]+ (last -> i) ->+ -- We're replacing an existential. That means we're not touching any+ -- variables that were introduced before it. For all variables after it,+ -- it is as we would replace global variables in them.+ take (i+1) exts ++ substGlobalsInExistentials is (drop (i+1) exts) [subst]+ -- | Determine the type of a term-termType :: Fresh m- => HashMap TyConOccName TyCon- -> Term- -> m Type+termType+ :: TyConMap+ -> Term+ -> Type termType m e = case e of- Var t _ -> return t- Data dc -> return $ dcType dc- Literal l -> return $ literalType l- Prim _ t -> return t- Lam b -> do (v,e') <- unbind b- mkFunTy (unembed $ varType v) <$> termType m e'- TyLam b -> do (tv,e') <- unbind b- ForAllTy <$> bind tv <$> termType m e'+ Var t -> varType t+ Data dc -> dcType dc+ Literal l -> literalType l+ Prim _ t -> primType t+ Lam v e' -> mkFunTy (varType v) (termType m e')+ TyLam tv e' -> ForAllTy tv (termType m e') App _ _ -> case collectArgs e of- (fun, args) -> termType m fun >>=- (flip (applyTypeToArgs m) args)- TyApp e' ty -> termType m e' >>= (\f -> applyTy m f ty)- Letrec b -> do (_,e') <- unbind b- termType m e'- Case _ ty _ -> return ty- Cast _ _ ty2 -> return ty2---- | Split a (Type)Application in the applied term and it arguments-collectArgs :: Term- -> (Term, [Either Term Type])-collectArgs = go []- where- go args (App e1 e2) = go (Left e2:args) e1- go args (TyApp e t) = go (Right t:args) e- go args e = (e, args)+ (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' -- | Split a (Type)Abstraction in the bound variables and the abstracted term-collectBndrs :: Fresh m- => Term- -> m ([Either Id TyVar], Term)+collectBndrs :: Term+ -> ([Either Id TyVar], Term) collectBndrs = go [] where- go bs (Lam b) = do- (v,e') <- unbind b- go (Left v:bs) e'- go bs (TyLam b) = do- (tv,e') <- unbind b- go (Right tv:bs) e'- go bs e' = return (reverse bs,e')+ go bs (Lam v e') = go (Left v:bs) e'+ go bs (TyLam tv e') = go (Right tv:bs) e'+ go bs e' = (reverse bs,e') -- | Get the result type of a polymorphic function given a list of arguments-applyTypeToArgs :: Fresh m- => HashMap TyConOccName TyCon- -> Type- -> [Either Term Type]- -> m Type-applyTypeToArgs _ opTy [] = return opTy-applyTypeToArgs m opTy (Right ty:args) = applyTy m opTy ty >>=- (flip (applyTypeToArgs m) args)-applyTypeToArgs m opTy (Left e:args) = case splitFunTy m opTy of- Just (_,resTy) -> applyTypeToArgs m resTy args- Nothing -> error $- concat [ $(curLoc)- , "applyTypeToArgs splitFunTy: not a funTy:\n"- , "opTy: "- , showDoc opTy- , "\nTerm: "- , showDoc e- , "\nOtherArgs: "- , unlines (map (either showDoc showDoc) args)- ]+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+ :: 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+ :: TyConMap+ -> Type+ -> Type+ -> Maybe Type+piResultTyMaybe m ty arg+ | Just ty' <- coreView1 m ty+ = piResultTyMaybe m ty' arg+ | FunTy _ res <- tyView ty+ = 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])@ give sthe 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+ :: TyConMap+ -> Type+ -> [Type]+ -> Type+piResultTys _ ty [] = ty+piResultTys m ty origArgs@(arg:args)+ | Just ty' <- coreView1 m ty+ = piResultTys m ty' origArgs+ | FunTy _ res <- tyView ty+ = 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)+ -- | Get the list of term-binders out of a DataType pattern patIds :: Pat -> ([TyVar],[Id])-patIds (DataPat _ ids) = unrebind ids-patIds _ = ([],[])---- | Make a type variable-mkTyVar :: Kind- -> TyName- -> TyVar-mkTyVar tyKind tyName = TyVar tyName (embed tyKind)+patIds (DataPat _ tvs ids) = (tvs,ids)+patIds _ = ([],[]) --- | Make a term variable-mkId :: Type- -> TmName- -> Id-mkId tmType tmName = Id tmName (embed tmType)+patVars :: Pat -> [Var a]+patVars (DataPat _ tvs ids) = coerce tvs ++ coerce ids+patVars _ = [] -- | Abstract a term over a list of term and type variables mkAbstraction :: Term -> [Either Id TyVar] -> Term-mkAbstraction = foldr (either (Lam `dot` bind) (TyLam `dot` bind))+mkAbstraction = foldr (either Lam TyLam) -- | Abstract a term over a list of term variables mkTyLams :: Term@@ -150,96 +441,106 @@ mkApps :: Term -> [Either Term Type] -> Term-mkApps = foldl (\e a -> either (App e) (TyApp e) a)+mkApps = foldl' (\e a -> either (App e) (TyApp e) a) -- | Apply a list of terms to a term mkTmApps :: Term -> [Term] -> Term-mkTmApps = foldl App+mkTmApps = foldl' App -- | Apply a list of types to a term mkTyApps :: Term -> [Type] -> Term-mkTyApps = foldl TyApp+mkTyApps = foldl' TyApp +mkTicks+ :: Term+ -> [TickInfo]+ -> Term+mkTicks tm ticks = foldl' (\e s -> Tick s e) tm (nub ticks)+ -- | Does a term have a function type?-isFun :: Fresh m- => HashMap TyConOccName TyCon+isFun :: TyConMap -> Term- -> m Bool-isFun m t = fmap (isFunTy m) $ (termType m) t+ -> Bool+isFun m t = isFunTy m (termType m t) -- | Does a term have a function or polymorphic type?-isPolyFun :: Fresh m- => HashMap TyConOccName TyCon+isPolyFun :: TyConMap -> Term- -> m Bool-isPolyFun m t = isPolyFunCoreTy m <$> termType m t+ -> Bool+isPolyFun m t = isPolyFunCoreTy m (termType m t) -- | Is a term a term-abstraction? isLam :: Term -> Bool-isLam (Lam _) = True-isLam _ = False+isLam (Lam {}) = True+isLam _ = False -- | Is a term a recursive let-binding? isLet :: Term -> Bool-isLet (Letrec _) = True-isLet _ = False+isLet (Letrec {}) = True+isLet _ = False -- | Is a term a variable reference? isVar :: Term -> Bool-isVar (Var _ _) = True-isVar _ = False+isVar (Var {}) = True+isVar _ = False +isLocalVar+ :: Term+ -> Bool+isLocalVar (Var v) = isLocalId v+isLocalVar _ = False+ -- | Is a term a datatype constructor? isCon :: Term -> Bool-isCon (Data _) = True-isCon _ = False+isCon (Data {}) = True+isCon _ = False -- | Is a term a primitive? isPrim :: Term -> Bool-isPrim (Prim _ _) = True-isPrim _ = False+isPrim (Prim {}) = True+isPrim _ = False -- | Make variable reference out of term variable idToVar :: Id -> Term-idToVar (Id nm tyE) = Var (unembed tyE) nm-idToVar tv = error $ $(curLoc) ++ "idToVar: tyVar: " ++ showDoc tv+idToVar i@(Id {}) = Var i+idToVar tv = error $ $(curLoc) ++ "idToVar: tyVar: " ++ showPpr tv -- | Make a term variable out of a variable reference varToId :: Term -> Id-varToId (Var ty nm) = Id nm (embed ty)-varToId e = error $ $(curLoc) ++ "varToId: not a var: " ++ showDoc e+varToId (Var i) = i+varToId e = error $ $(curLoc) ++ "varToId: not a var: " ++ showPpr e termSize :: Term -> Word-termSize (Var _ _) = 1-termSize (Data _) = 1-termSize (Literal _) = 1-termSize (Prim _ _) = 1-termSize (Lam b) = let (_,e) = unsafeUnbind b- in termSize e + 1-termSize (TyLam b) = let (_,e) = unsafeUnbind b- in termSize e-termSize (App e1 e2) = termSize e1 + termSize e2-termSize (TyApp e _) = termSize e-termSize (Cast e _ _)= termSize e-termSize (Letrec b) = let (bndrsR,body) = unsafeUnbind b- bndrSzs = map (termSize . unembed . snd) (unrec bndrsR)- bodySz = termSize body- in sum (bodySz:bndrSzs)-termSize (Case subj _ alts) = let subjSz = termSize subj- altSzs = map (termSize . snd . unsafeUnbind) alts- in sum (subjSz:altSzs)+termSize (Var {}) = 1+termSize (Data {}) = 1+termSize (Literal {}) = 1+termSize (Prim {}) = 1+termSize (Lam _ e) = termSize e + 1+termSize (TyLam _ e) = termSize e+termSize (App e1 e2) = termSize e1 + termSize e2+termSize (TyApp e _) = termSize e+termSize (Cast e _ _) = termSize e+termSize (Tick _ e) = termSize e+termSize (Letrec bndrs e) = sum (bodySz:bndrSzs)+ where+ bndrSzs = map (termSize . snd) bndrs+ bodySz = termSize e+termSize (Case subj _ alts) = sum (subjSz:altSzs)+ where+ subjSz = termSize subj+ altSzs = map (termSize . snd) alts -- | Create a vector of supplied elements mkVec :: DataCon -- ^ The Nil constructor@@ -252,13 +553,13 @@ where go _ [] = mkApps (Data nilCon) [Right (LitTy (NumTy 0)) ,Right resTy- ,Left (Prim "_CO_" nilCoTy)+ ,Left (primCo nilCoTy) ] go n (x:xs) = mkApps (Data consCon) [Right (LitTy (NumTy n)) ,Right resTy ,Right (LitTy (NumTy (n-1)))- ,Left (Prim "_CO_" (consCoTy n))+ ,Left (primCo (consCoTy n)) ,Left x ,Left (go (n-1) xs)] @@ -282,7 +583,7 @@ go n (x:xs) = mkApps (Data consCon) [Right (LitTy (NumTy n)) ,Right resTy ,Right (LitTy (NumTy (n-1)))- ,Left (Prim "_CO_" (consCoTy n))+ ,Left (primCo (consCoTy n)) ,Left x ,Left (go (n-1) xs)] @@ -291,97 +592,141 @@ ,resTy ,(LitTy (NumTy (n-1)))]) ++availableUniques+ :: Term+ -> [Unique]+availableUniques t = [ n | n <- [0..] , n `IntSet.notMember` avoid ]+ where+ avoid = Lens.foldMapOf termFreeVarsX (\a i -> IntSet.insert (varUniq a) i) t+ IntSet.empty+ -- | Create let-bindings with case-statements that select elements out of a -- vector. Returns both the variables to which element-selections are bound -- and the let-bindings-extractElems :: DataCon -- ^ The Cons (:>) constructor- -> Type -- ^ The element type- -> Char -- ^ Char to append to the bound variable names- -> Integer -- ^ Length of the vector- -> Term -- ^ The vector- -> [(Term,[LetBinding])]-extractElems consCon resTy s maxN = go maxN- where- go :: Integer -> Term -> [(Term,[LetBinding])]- go 0 _ = []- go n e = (elVar- ,[(Id elBNm (embed resTy) ,embed lhs)- ,(Id restBNm (embed restTy),embed rhs)- ]- ) :- go (n-1) (Var restTy restBNm)+extractElems+ :: Supply+ -- ^ Unique supply+ -> InScopeSet+ -- ^ (Superset of) in scope variables+ -> DataCon+ -- ^ The Cons (:>) constructor+ -> Type+ -- ^ The element type+ -> Char+ -- ^ Char to append to the bound variable names+ -> Integer+ -- ^ Length of the vector+ -> Term+ -- ^ The vector+ -> (Supply, [(Term,[LetBinding])])+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])])+ go 0 uniqs _ = (uniqs,[])+ go n uniqs0 e =+ (uniqs3,(elNVar,[(elNId, lhs),(restNId, rhs)]):restVs)+ where+ tys = [(LitTy (NumTy n)),resTy,(LitTy (NumTy (n-1)))]+ (Just idTys) = dataConInstArgTys consCon tys+ restTy = last idTys - where- elBNm = string2SystemName ("el" ++ s:show (maxN-n))- restBNm = string2SystemName ("rest" ++ s:show (maxN-n))- elVar = Var resTy elBNm- pat = DataPat (embed consCon) (rebind [mTV] [co,el,rest])- elPatNm = string2SystemName "el"- restPatNm = string2SystemName "rest"- lhs = Case e resTy [bind pat (Var resTy elPatNm)]- rhs = Case e restTy [bind pat (Var restTy restPatNm)]+ (uniqs1,mTV) = mkUniqSystemTyVar uniqs0 ("m",typeNatKind)+ (uniqs2,[elNId,restNId,co,el,rest]) =+ mapAccumR mkUniqSystemId uniqs1 $ zip+ ["el" `T.append` (s `T.cons` T.pack (show (maxN-n)))+ ,"rest" `T.append` (s `T.cons` T.pack (show (maxN-n)))+ ,"_co_"+ ,"el"+ ,"rest"+ ]+ (resTy:restTy:idTys) - mName = string2SystemName "m"- mTV = TyVar mName (embed typeNatKind)- tys = [(LitTy (NumTy n)),resTy,(LitTy (NumTy (n-1)))]- (Just idTys) = dataConInstArgTys consCon tys- [co,el,rest] = zipWith Id [string2SystemName "_co_",elPatNm, restPatNm]- (map embed idTys)- restTy = last (fromJust (dataConInstArgTys consCon tys))+ elNVar = Var elNId+ pat = DataPat consCon [mTV] [co,el,rest]+ lhs = Case e resTy [(pat,Var el)]+ rhs = Case e restTy [(pat,Var rest)] + (uniqs3,restVs) = go (n-1) uniqs2 (Var restNId) -- | Create let-bindings with case-statements that select elements out of a -- tree. Returns both the variables to which element-selections are bound -- and the let-bindings-extractTElems :: DataCon -- ^ The 'LR' constructor- -> DataCon -- ^ The 'BR' constructor- -> Type -- ^ The element type- -> Char -- ^ Char to append to the bound variable names- -> Integer -- ^ Depth of the tree- -> Term -- ^ The tree- -> ([Term],[LetBinding])-extractTElems lrCon brCon resTy s maxN = go maxN [0..(2^(maxN+1))-2] [0..(2^maxN - 1)]- where- go :: Integer -> [Int] -> [Int] -> Term -> ([Term],[LetBinding])- go 0 _ ks e = ([elVar],[(Id elBNm (embed resTy), embed lhs)])- where- elBNm = string2SystemName ("el" ++ s:show (head ks))- elVar = Var resTy elBNm- pat = DataPat (embed lrCon) (rebind [] [co,el])- elPatNm = string2SystemName "el"- lhs = Case e resTy [bind pat (Var resTy elPatNm)]+extractTElems+ :: Supply+ -- ^ Unique supply+ -> InScopeSet+ -- ^ (Superset of) in scope variables+ -> DataCon+ -- ^ The 'LR' constructor+ -> DataCon+ -- ^ The 'BR' constructor+ -> Type+ -- ^ The element type+ -> Char+ -- ^ Char to append to the bound variable names+ -> Integer+ -- ^ Depth of the tree+ -> Term+ -- ^ The tree+ -> (Supply,([Term],[LetBinding]))+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+ go :: Integer+ -> [Int]+ -> [Int]+ -> (Supply,InScopeSet)+ -> Term+ -> ((Supply,InScopeSet),([Term],[LetBinding]))+ go 0 _ ks uniqs0 e = (uniqs1,([elNVar],[(elNId, rhs)]))+ where+ tys = [LitTy (NumTy 0),resTy]+ (Just idTys) = dataConInstArgTys lrCon tys - tys = [LitTy (NumTy 0),resTy]- (Just idTys) = dataConInstArgTys lrCon tys- [co,el] = zipWith Id [string2SystemName "_co_",elPatNm]- (map embed idTys)+ (uniqs1,[elNId,co,el]) =+ mapAccumR mkUniqSystemId uniqs0 $ zip+ [ "el" `T.append` (s `T.cons` T.pack (show (head ks)))+ , "_co_"+ , "el"+ ]+ (resTy:idTys)+ elNVar = Var elNId+ pat = DataPat lrCon [] [co,el]+ rhs = Case e resTy [(pat,Var el)] - go n bs ks e = (lVars ++ rVars,(Id ltBNm (embed brTy),embed ltLhs):- (Id rtBNm (embed brTy),embed rtLhs):- (lBinds ++ rBinds))- where- ltBNm = string2SystemName ("lt" ++ s:show b0)- rtBNm = string2SystemName ("rt" ++ s:show b1)- ltVar = Var brTy ltBNm- rtVar = Var brTy rtBNm- pat = DataPat (embed brCon) (rebind [mTV] [co,lt,rt])- ltPatNm = string2SystemName "lt"- rtPatNm = string2SystemName "rt"- ltLhs = Case e brTy [bind pat (Var brTy ltPatNm)]- rtLhs = Case e brTy [bind pat (Var brTy rtPatNm)]+ go n bs ks uniqs0 e =+ (uniqs4+ ,(lVars ++ rVars,(ltNId, ltRhs):+ (rtNId, rtRhs):+ (lBinds ++ rBinds)))+ where+ tys = [LitTy (NumTy n),resTy,LitTy (NumTy (n-1))]+ (Just idTys) = dataConInstArgTys brCon tys - mName = string2SystemName "m"- mTV = TyVar mName (embed typeNatKind)- tys = [LitTy (NumTy n),resTy,LitTy (NumTy (n-1))]- (Just idTys) = dataConInstArgTys brCon tys- [co,lt,rt] = zipWith Id [string2SystemName "_co_",ltPatNm,rtPatNm]- (map embed idTys)- brTy = last idTys- (kL,kR) = splitAt (length ks `div` 2) ks- (b0:bL,b1:bR) = splitAt (length bs `div` 2) bs+ (uniqs1,mTV) = mkUniqSystemTyVar uniqs0 ("m",typeNatKind)+ (b0:bL,b1:bR) = splitAt (length bs `div` 2) bs+ brTy = last idTys+ (uniqs2,[ltNId,rtNId,co,lt,rt]) =+ mapAccumR mkUniqSystemId uniqs1 $ zip+ ["lt" `T.append` (s `T.cons` T.pack (show b0))+ ,"rt" `T.append` (s `T.cons` T.pack (show b1))+ ,"_co_"+ ,"lt"+ ,"rt"+ ]+ (brTy:brTy:idTys)+ ltVar = Var ltNId+ rtVar = Var rtNId+ pat = DataPat brCon [mTV] [co,lt,rt]+ ltRhs = Case e brTy [(pat,Var lt)]+ rtRhs = Case e brTy [(pat,Var rt)] - (lVars,lBinds) = go (n-1) bL kL ltVar- (rVars,rBinds) = go (n-1) bR kR rtVar+ (kL,kR) = splitAt (length ks `div` 2) ks+ (uniqs3,(lVars,lBinds)) = go (n-1) bL kL uniqs2 ltVar+ (uniqs4,(rVars,rBinds)) = go (n-1) bR kR uniqs3 rtVar -- | Create a vector of supplied elements mkRTree :: DataCon -- ^ The LR constructor@@ -394,7 +739,7 @@ where go _ [x] = mkApps (Data lrCon) [Right (LitTy (NumTy 0)) ,Right resTy- ,Left (Prim "_CO_" lrCoTy)+ ,Left (primCo lrCoTy) ,Left x ] @@ -403,7 +748,7 @@ in mkApps (Data brCon) [Right (LitTy (NumTy n)) ,Right resTy ,Right (LitTy (NumTy (n-1)))- ,Left (Prim "_CO_" (brCoTy n))+ ,Left (primCo (brCoTy n)) ,Left (go (n-1) xsL) ,Left (go (n-1) xsR)] @@ -414,22 +759,30 @@ ,resTy ,(LitTy (NumTy (n-1)))]) --- | Determine whether a type is isomorphic to "Clash.Signal.Internal.Signal'"+-- | Determine whether a type is isomorphic to "Clash.Signal.Internal.Signal" -- -- It is i.e.: ----- * Signal' clk a--- * (Signal' clk a, Signal' clk b)--- * Vec n (Signal' clk a)+-- * Signal clk a+-- * (Signal clk a, Signal clk b)+-- * Vec n (Signal clk a) -- * data Wrap = W (Signal clk' Int) -- * etc.-isSignalType :: HashMap TyConOccName TyCon -> Type -> Bool+--+-- This also includes BiSignals, i.e.:+--+-- * BiSignalIn High System Int+-- * etc.+--+isSignalType :: TyConMap -> Type -> Bool isSignalType tcm ty = go HashSet.empty ty where- go tcSeen (tyView -> TyConApp tcNm args) = case name2String tcNm of- "Clash.Signal.Internal.Signal" -> True- _ | tcNm `HashSet.member` tcSeen -> False -- Do not follow rec types- | otherwise -> case HashMap.lookup (nameOcc tcNm) tcm of+ 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+ _ | tcNm `HashSet.member` tcSeen -> False -- Do not follow rec types+ | otherwise -> case lookupUniqMap tcNm tcm of Just tc -> let dcs = tyConDataCons tc dcInsArgTys = concat $ mapMaybe (`dataConInstArgTys` args) dcs@@ -441,19 +794,151 @@ go _ _ = False isClockOrReset- :: HashMap TyConOccName TyCon+ :: TyConMap -> Type -> Bool-isClockOrReset m (coreView m -> Just ty) = isClockOrReset m ty-isClockOrReset _ (tyView -> TyConApp tcNm _) = case name2String tcNm of+isClockOrReset m (coreView1 m -> Just ty) = isClockOrReset m ty+isClockOrReset _ (tyView -> TyConApp tcNm _) = case nameOcc tcNm of "Clash.Signal.Internal.Clock" -> True "Clash.Signal.Internal.Reset" -> True _ -> False isClockOrReset _ _ = False -tyNatSize :: HMS.HashMap TyConOccName TyCon+tyNatSize :: TyConMap -> Type -> Except String Integer-tyNatSize m (coreView m -> Just ty) = tyNatSize m ty-tyNatSize _ (LitTy (NumTy i)) = return i-tyNatSize _ ty = throwE $ $(curLoc) ++ "Cannot reduce an integer: " ++ show ty+tyNatSize m (coreView1 m -> Just ty) = tyNatSize m ty+tyNatSize _ (LitTy (NumTy i)) = return i+tyNatSize _ ty = throwE $ $(curLoc) ++ "Cannot reduce to an integer:\n" ++ showPpr ty+++mkUniqSystemTyVar+ :: (Supply, InScopeSet)+ -> (OccName, Kind)+ -> ((Supply, InScopeSet), TyVar)+mkUniqSystemTyVar (supply,inScope) (nm, ki) =+ ((supply',extendInScopeSet inScope v'), v')+ where+ (u,supply') = freshId supply+ v = mkTyVar ki (mkUnsafeSystemName nm u)+ v' = uniqAway inScope v++mkUniqSystemId+ :: (Supply, InScopeSet)+ -> (OccName, Type)+ -> ((Supply,InScopeSet), Id)+mkUniqSystemId (supply,inScope) (nm, ty) =+ ((supply',extendInScopeSet inScope v'), v')+ where+ (u,supply') = freshId supply+ v = mkLocalId ty (mkUnsafeSystemName nm u)+ v' = uniqAway inScope v++mkUniqInternalId+ :: (Supply, InScopeSet)+ -> (OccName, Type)+ -> ((Supply,InScopeSet), Id)+mkUniqInternalId (supply,inScope) (nm, ty) =+ ((supply',extendInScopeSet inScope v'), v')+ where+ (u,supply') = freshId supply+ v = mkLocalId ty (mkUnsafeInternalName nm u)+ v' = uniqAway inScope v+++-- | Same as @dataConInstArgTys@, but it tries to compute existentials too,+-- hence the extra argument @TyConMap@. WARNING: It will return the types+-- of non-existentials only+dataConInstArgTysE+ :: HasCallStack+ => InScopeSet+ -> TyConMap+ -> DataCon+ -> [Type]+ -> Maybe [Type]+dataConInstArgTysE is0 tcm (MkData { dcArgTys, dcExtTyVars, dcUnivTyVars }) inst_tys = do+ -- 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))+ subst = extendTvSubstList (mkSubst is2) (zip dcUnivTyVars inst_tys)+ go+ (substGlobalsInExistentials is0 dcExtTyVars (zip dcUnivTyVars inst_tys))+ (map (substTy subst) dcArgTys)++ where+ go+ :: [TyVar]+ -- ^ Existentials+ -> [Type]+ -- ^ Type arguments+ -> Maybe [Type]+ -- ^ Maybe ([type of non-existential])+ go exts0 args0 =+ let eqs = catMaybes (map (typeEq tcm) args0) in+ case solveNonAbsurds tcm eqs of+ [] ->+ Just args0+ sols ->+ go exts1 args1+ where+ exts1 = substInExistentialsList is0 exts0 sols+ is2 = extendInScopeSetList is0 exts1+ subst = extendTvSubstList (mkSubst is2) sols+ args1 = map (substTy subst) args0+++-- | Given a DataCon and a list of types, the type variables of the DataCon+-- type are substituted for the list of types. The argument types are returned.+--+-- The list of types should be equal to the number of type variables, otherwise+-- @Nothing@ is returned.+dataConInstArgTys :: DataCon -> [Type] -> Maybe [Type]+dataConInstArgTys (MkData { dcArgTys, dcUnivTyVars, dcExtTyVars }) inst_tys =+ -- TODO: Check if inst_tys do not contain any free variables on call sites. If+ -- TODO: they do, this function is unsafe to use.+ let tyvars = dcUnivTyVars ++ dcExtTyVars in+ if length tyvars == length inst_tys then+ Just (map (substTyWith tyvars inst_tys) dcArgTys)+ else+ Nothing++-- | Make a coercion+primCo+ :: Type+ -> Term+primCo ty = Prim "_CO_" (PrimInfo ty WorkNever)++-- | Make an undefined term+undefinedTm+ :: Type+ -> Term+undefinedTm = TyApp (Prim "Clash.Transformations.undefined" (PrimInfo undefinedTy WorkNever))++substArgTys+ :: DataCon+ -> [Type]+ -> [Type]+substArgTys dc args =+ let univTVs = dcUnivTyVars dc+ extTVs = dcExtTyVars dc+ argsFVs = foldl' unionVarSet emptyVarSet+ (map (Lens.foldMapOf typeFreeVars unitVarSet) args)+ is = mkInScopeSet (argsFVs `unionVarSet` mkVarSet extTVs)+ -- See Note [The substitution invariant]+ subst = extendTvSubstList (mkSubst is) (univTVs `zipEqual` args)+ in map (substTy subst) (dcArgTys dc)++stripTicks :: Term -> Term+stripTicks (Tick _ e) = stripTicks e+stripTicks e = e++-- | Try to reduce an arbitrary type to a Symbol, and subsequently extract its+-- String representation+tySym+ :: TyConMap+ -> Type+ -> Except String String+tySym m (coreView1 m -> Just ty) = tySym m ty+tySym _ (LitTy (SymTy s)) = return s+tySym _ ty = throwE $ $(curLoc) ++ "Cannot reduce to a string:\n" ++ showPpr ty
src/Clash/Core/Var.hs view
@@ -1,6 +1,6 @@ {-| Copyright : (C) 2012-2016, University of Twente,- 2017, Google Inc.+ 2017-2018, Google Inc. License : BSD2 (see the file LICENSE) Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com> @@ -9,53 +9,160 @@ {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ExplicitForAll #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE RankNTypes #-} module Clash.Core.Var- ( Var (..)+ ( Attr' (..)+ , Var (..)+ , IdScope (..) , Id , TyVar+ , mkId+ , mkLocalId+ , mkGlobalId+ , mkTyVar+ , setVarUnique+ , setVarType+ , setIdScope , modifyVarName+ , isGlobalId+ , isLocalId+ , attrName ) where + import Control.DeepSeq (NFData (..))+import Data.Binary (Binary)+import Data.Function (on) import Data.Hashable (Hashable)-import Data.Typeable (Typeable) import GHC.Generics (Generic)-import Unbound.Generics.LocallyNameless (Alpha,Embed,Subst(..))+import Clash.Core.Name (Name (..))+import {-# SOURCE #-} Clash.Core.Term (Term, TmName)+import {-# SOURCE #-} Clash.Core.Type (Kind, Type, TyName)+import Clash.Unique -import Clash.Core.Name (Name)-import {-# SOURCE #-} Clash.Core.Term (Term)-import {-# SOURCE #-} Clash.Core.Type (Kind, Type) +-- | Interal version of Clash.Annotations.SynthesisAttributes.Attr.+--+-- Needed because Clash.Annotations.SynthesisAttributes.Attr uses the Symbol+-- kind for names, which do not have a term-level representation+data Attr'+ = BoolAttr' String Bool+ | IntegerAttr' String Integer+ | StringAttr' String String+ | Attr' String+ deriving (Eq, Show, NFData, Generic, Hashable, Ord, Binary)++attrName :: Attr' -> String+attrName (BoolAttr' n _) = n+attrName (IntegerAttr' n _) = n+attrName (StringAttr' n _) = n+attrName (Attr' n) = n+ -- | Variables in CoreHW data Var a -- | Constructor for type variables = TyVar- { varName :: Name a- , varKind :: Embed Kind+ { varName :: !(Name a)+ , varUniq :: {-# UNPACK #-} !Unique+ , varType :: Kind } -- | Constructor for term variables | Id- { varName :: Name a- , varType :: Embed Type+ { varName :: !(Name a)+ , varUniq :: {-# UNPACK #-} !Unique+ , varType :: Type+ , idScope :: IdScope }- deriving (Eq,Show,Generic,NFData,Hashable)+ deriving (Show,Generic,NFData,Hashable,Binary) +instance Eq (Var a) where+ (==) = (==) `on` varUniq+ (/=) = (/=) `on` varUniq++instance Ord (Var a) where+ compare = compare `on` varUniq++instance Uniquable (Var a) where+ getUnique = varUniq++data IdScope = GlobalId | LocalId+ deriving (Show,Generic,NFData,Hashable,Binary)+ -- | Term variable type Id = Var Term -- | Type variable type TyVar = Var Type -instance (Typeable a, Alpha a) => Alpha (Var a)-instance Generic b => Subst Term (Var b)-instance Generic b => Subst Type (Var b)- -- | Change the name of a variable modifyVarName :: (Name a -> Name a) -> Var a -> Var a-modifyVarName f (TyVar n k) = TyVar (f n) k-modifyVarName f (Id n t) = Id (f n) t+modifyVarName f (TyVar n _ k) =+ let n' = f n+ in TyVar n' (nameUniq n') k+modifyVarName f (Id n _ t s) =+ let n' = f n+ in Id n' (nameUniq n') t s++-- | Make a type variable+mkTyVar+ :: Kind+ -> TyName+ -> TyVar+mkTyVar tyKind tyName = TyVar tyName (nameUniq tyName) tyKind++-- | Make a term variable+mkId+ :: Type+ -> IdScope+ -> TmName+ -> Id+mkId tmType scope tmName = Id tmName (nameUniq tmName) tmType scope++mkLocalId+ :: Type+ -> TmName+ -> Id+mkLocalId tmType tmName = Id tmName (nameUniq tmName) tmType LocalId++mkGlobalId+ :: Type+ -> 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+ -> Bool+isGlobalId (Id {idScope = GlobalId}) = True+isGlobalId _ = False++isLocalId+ :: Var a+ -> Bool+isLocalId (Id {idScope = LocalId}) = True+isLocalId _ = False++setIdScope+ :: IdScope+ -> Var a+ -> Var a+setIdScope s (Id nm u t _) = Id nm u t s+setIdScope _ v = v
+ src/Clash/Core/VarEnv.hs view
@@ -0,0 +1,556 @@+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeSynonymInstances #-}++module Clash.Core.VarEnv+ ( -- * Environment with variables as keys+ VarEnv+ -- ** Accessors+ -- *** Size information+ , nullVarEnv+ -- ** Indexing+ , lookupVarEnv+ , lookupVarEnv'+ -- ** Construction+ , emptyVarEnv+ , unitVarEnv+ , mkVarEnv+ -- ** Modification+ , extendVarEnv+ , extendVarEnvList+ , extendVarEnvWith+ , delVarEnv+ , delVarEnvList+ , unionVarEnv+ , unionVarEnvWith+ -- ** Element-wise operations+ -- *** Mapping+ , mapVarEnv+ , mapMaybeVarEnv+ -- ** Working with predicates+ -- *** Searching+ , elemVarEnv+ , notElemVarEnv+ -- ** Conversions+ -- *** Lists+ , eltsVarEnv+ -- * Sets of variables+ , VarSet+ -- ** Construction+ , emptyVarSet+ , unitVarSet+ -- ** Modification+ , delVarSetByKey+ , unionVarSet+ -- ** Working with predicates+ -- *** Searching+ , elemVarSet+ , notElemVarSet+ -- ** Conversions+ -- *** Lists+ , mkVarSet+ -- * In-scope sets+ , InScopeSet+ -- ** Accessors+ -- *** Size information+ , emptyInScopeSet+ -- *** Indexing+ , lookupInScope+ -- ** Construction+ , mkInScopeSet+ -- ** Modification+ , extendInScopeSet+ , extendInScopeSetList+ , unionInScope+ -- ** Working with predicates+ -- *** Searching+ , elemInScopeSet+ , notElemInScopeSet+ , varSetInScope+ -- ** Unique generation+ , uniqAway+ -- * Dual renaming+ , RnEnv+ -- ** Construction+ , mkRnEnv+ -- ** Renaming+ , rnTmBndr+ , rnTyBndr+ , rnTmBndrs+ , rnTyBndrs+ , rnOccLId+ , rnOccRId+ , rnOccLTy+ , rnOccRTy+ )+where++import Data.Binary (Binary)+import Data.Coerce (coerce)+import qualified Data.List as List+import Data.Maybe (fromMaybe)+import Data.Text.Prettyprint.Doc+import GHC.Exts (Any)+import GHC.Generics++import Clash.Core.Pretty ()+import Clash.Core.Var+import Clash.Unique+import Clash.Util+import Clash.Pretty++-- * VarEnv++-- | Map indexed by variables+type VarEnv a = UniqMap a++-- | Empty map+emptyVarEnv+ :: VarEnv a+emptyVarEnv = emptyUniqMap++-- | Environment containing a single variable-value pair+unitVarEnv+ :: Var b+ -> a+ -> VarEnv a+unitVarEnv = unitUniqMap++-- | Look up a value based on the variable+lookupVarEnv+ :: Var b+ -> VarEnv a+ -> Maybe a+lookupVarEnv = lookupUniqMap++-- | Lookup a value based on the variable+--+-- Errors out when the variable is not present+lookupVarEnv'+ :: VarEnv a+ -> Var b+ -> a+lookupVarEnv' = lookupUniqMap'++-- | Remove a variable-value pair from the environment+delVarEnv+ :: VarEnv a+ -> Var b+ -> VarEnv a+delVarEnv = delUniqMap++-- | Remove a list of variable-value pairs from the environment+delVarEnvList+ :: VarEnv a+ -> [Var b]+ -> VarEnv a+delVarEnvList = delListUniqMap++-- | Add a variable-value pair to the environment; overwrites the value if the+-- variable already exists+extendVarEnv+ :: Var b+ -> a+ -> VarEnv a+ -> VarEnv a+extendVarEnv = extendUniqMap++-- | Add a variable-value pair to the environment; if the variable already+-- exists, the two values are merged with the given function+extendVarEnvWith+ :: Var b+ -> a+ -> (a -> a -> a)+ -> VarEnv a+ -> VarEnv a+extendVarEnvWith = extendUniqMapWith++-- | Add a list of variable-value pairs; the values of existing keys will be+-- overwritten+extendVarEnvList+ :: VarEnv a+ -> [(Var b, a)]+ -> VarEnv a+extendVarEnvList = extendListUniqMap++-- | Is the environment empty+nullVarEnv+ :: VarEnv a+ -> Bool+nullVarEnv = nullUniqMap++-- | Get the (left-biased) union of two environments+unionVarEnv+ :: VarEnv a+ -> VarEnv a+ -> VarEnv a+unionVarEnv = unionUniqMap++-- | Get the union of two environments, mapped values existing in both+-- environments will be merged with the given function.+unionVarEnvWith+ :: (a -> a -> a)+ -> VarEnv a+ -> VarEnv a+ -> VarEnv a+unionVarEnvWith = unionUniqMapWith++-- | Create an environment given a list of var-value pairs+mkVarEnv+ :: [(Var a,b)]+ -> VarEnv b+mkVarEnv = listToUniqMap++-- | Apply a function to every element in the environment+mapVarEnv+ :: (a -> b)+ -> VarEnv a+ -> VarEnv b+mapVarEnv = mapUniqMap++-- | Apply a function to every element in the environment; values for which the+-- function returns 'Nothing' are removed from the environment+mapMaybeVarEnv+ :: (a -> Maybe b)+ -> VarEnv a+ -> VarEnv b+mapMaybeVarEnv = mapMaybeUniqMap++-- | Extract the elements+eltsVarEnv+ :: VarEnv a+ -> [a]+eltsVarEnv = eltsUniqMap++-- | Does the variable exist in the environment+elemVarEnv+ :: Var a+ -> VarEnv b+ -> Bool+elemVarEnv = elemUniqMap++-- | Does the variable not exist in the environment+notElemVarEnv+ :: Var a+ -> VarEnv b+ -> Bool+notElemVarEnv = notElemUniqMap++-- * VarSet++-- | Set of variables+type VarSet = UniqSet (Var Any)++-- | The empty set+emptyVarSet+ :: VarSet+emptyVarSet = emptyUniqSet++-- | The set of a single variable+unitVarSet+ :: Var a+ -> VarSet+unitVarSet v = unitUniqSet (coerce v)++-- | Add a variable to the set+extendVarSet+ :: VarSet+ -> Var a+ -> VarSet+extendVarSet env v = extendUniqSet env (coerce v)++-- | Union two sets+unionVarSet+ :: VarSet+ -> VarSet+ -> VarSet+unionVarSet = unionUniqSet++-- | Is the variable an element in the set+elemVarSet+ :: Var a+ -> VarSet+ -> Bool+elemVarSet v = elemUniqSet (coerce v)++-- | Is the variable not an element in the set+notElemVarSet+ :: Var a+ -> VarSet+ -> Bool+notElemVarSet v = notElemUniqSet (coerce v)++-- | Is the set of variables A a subset of the variables B+subsetVarSet+ :: VarSet+ -- ^ Set of variables A+ -> VarSet+ -- ^ Set of variables B+ -> Bool+subsetVarSet = subsetUniqSet++-- | Look up a variable in the set, returns it if it exists+lookupVarSet+ :: Var a+ -> VarSet+ -> Maybe (Var Any)+lookupVarSet = lookupUniqSet++-- | Remove a variable from the set based on its 'Unique'+delVarSetByKey+ :: Unique+ -> VarSet+ -> VarSet+delVarSetByKey = delUniqSetDirectly++-- | Create a set from a list of variables+mkVarSet+ :: [Var a]+ -> VarSet+mkVarSet xs = mkUniqSet (coerce xs)++-- * InScopeSet++-- | Set of variables that is in scope at some point+--+-- The 'Int' is a kind of hash-value used to generate new uniques. It should+-- never be zero+--+-- See "Secrets of the Glasgow Haskell Compiler inliner" Section 3.2 for the+-- motivation+data InScopeSet = InScopeSet VarSet {-# UNPACK #-} !Int+ deriving (Generic, Binary)++instance ClashPretty InScopeSet where+ clashPretty (InScopeSet s _) = clashPretty s++-- | The empty set+extendInScopeSet+ :: InScopeSet+ -> Var a+ -> InScopeSet+extendInScopeSet (InScopeSet inScope n) v =+ InScopeSet (extendVarSet inScope v) (n + 1)++-- | Add a list of variables in scope+extendInScopeSetList+ :: InScopeSet+ -> [Var a]+ -> InScopeSet+extendInScopeSetList (InScopeSet inScope n) vs =+ InScopeSet (List.foldl' extendVarSet inScope vs) (n + length vs)++-- | Union two sets of in scope variables+unionInScope+ :: InScopeSet+ -> InScopeSet+ -> InScopeSet+unionInScope (InScopeSet s1 _) (InScopeSet s2 n2)+ = InScopeSet (s1 `unionVarSet` s2) n2++-- | Is the set of variables in scope+varSetInScope+ :: VarSet+ -> InScopeSet+ -> Bool+varSetInScope vars (InScopeSet s1 _)+ = vars `subsetVarSet` s1++-- | Look up a variable in the 'InScopeSet'. This gives you the canonical+-- version of the variable+lookupInScope+ :: InScopeSet+ -> Var a+ -> Maybe (Var Any)+lookupInScope (InScopeSet s _) v = lookupVarSet v s++-- | Is the variable in scope+elemInScopeSet+ :: Var a+ -> InScopeSet+ -> Bool+elemInScopeSet v (InScopeSet s _) = elemVarSet v s++-- | Is the variable not in scope+notElemInScopeSet+ :: Var a+ -> InScopeSet+ -> Bool+notElemInScopeSet v (InScopeSet s _) = notElemVarSet v s++-- | Create a set of variables in scope+mkInScopeSet+ :: VarSet+ -> InScopeSet+mkInScopeSet is = InScopeSet is 1++-- | The empty set+emptyInScopeSet+ :: InScopeSet+emptyInScopeSet = mkInScopeSet emptyVarSet++-- | Ensure that the 'Unique' of a variable does not occur in the 'InScopeSet'+uniqAway+ :: InScopeSet+ -> Var a+ -> Var a+uniqAway inScopeSet var+ | var `elemInScopeSet` inScopeSet -- make a new one+ = uniqAway' inScopeSet var+ | otherwise -- Nothing to do+ = var++uniqAway'+ :: InScopeSet+ -> Var a+ -> Var a+uniqAway' (InScopeSet set n) var = try 1 where+ origUniq = varUniq var+ try k+ | debugIsOn && k > 1000+ = pprPanic "uniqAway loop:" msg+ | uniq `elemUniqSetDirectly` set+ = try (k + 1)+ | k > 3+ = pprTraceDebug "uniqAway:" msg (setVarUnique var uniq)+ | otherwise+ = setVarUnique var uniq+ where+ msg = fromPretty k <+> "tries" <+> clashPretty (varName var) <+> fromPretty n+ uniq = deriveUnique origUniq (n * k)++deriveUnique+ :: Unique+ -> Int+ -> Unique+deriveUnique i delta = i + delta++-- * RnEnv++-- | Rename environment for e.g. alpha equivalence+--+-- When going under binders for e.g.+--+-- @+-- \x -> e1 `aeq` \y -> e2+-- @+--+-- We want to rename @[x -> y]@ or @[y -> x]@, but we have to pick a binder+-- that is neither free in @e1@ nor @e2@ or we risk accidental capture.+--+-- So we must maintain:+--+-- 1. A renaming for the left term+--+-- 2. A renaming for the right term+--+-- 3. A set of in scope variables+data RnEnv+ = RnEnv+ { rn_envLTy :: VarEnv TyVar+ -- ^ Type renaming for the left term+ , rn_envLTm :: VarEnv Id+ -- ^ Term renaming for the left term+ , rn_envRTy :: VarEnv TyVar+ -- ^ Type renaming for the right term+ , rn_envRTm :: VarEnv Id+ -- ^ Term renaming for the right term+ , rn_inScope :: InScopeSet+ -- ^ In scope in left or right terms+ }++-- | Create an empty renaming environment+mkRnEnv+ :: InScopeSet -> RnEnv+mkRnEnv vars+ = RnEnv+ { rn_envLTy = emptyVarEnv+ , rn_envLTm = emptyVarEnv+ , rn_envRTy = emptyVarEnv+ , rn_envRTm = emptyVarEnv+ , rn_inScope = vars+ }++-- | Look up the renaming of an type-variable occurrence in the left term+rnOccLTy+ :: RnEnv -> TyVar -> TyVar+rnOccLTy rn v = fromMaybe v (lookupVarEnv v (rn_envLTy rn))++-- | Look up the renaming of an type-variable occurrence in the right term+rnOccRTy+ :: RnEnv -> TyVar -> TyVar+rnOccRTy rn v = fromMaybe v (lookupVarEnv v (rn_envRTy rn))++-- | Simultaneously go under the type-variable binder /bTvL/ and type-variable+-- binder /bTvR/, finds a new binder /newTvB/, and return an environment mapping+-- @[bTvL -> newB]@ and @[bTvR -> newB]@+rnTyBndr+ :: RnEnv -> TyVar -> TyVar -> RnEnv+rnTyBndr rv@(RnEnv {rn_envLTy = lenv, rn_envRTy = renv, rn_inScope = inScope}) bL bR =+ rv { rn_envLTy = extendVarEnv bL newB lenv -- See Note [Rebinding and shadowing]+ , rn_envRTy = extendVarEnv bR newB renv+ , rn_inScope = extendInScopeSet inScope newB }+ where+ -- Find a new type-binder not in scope in either term+ newB | not (bL `elemInScopeSet` inScope) = bL+ | not (bR `elemInScopeSet` inScope) = bR+ | otherwise = uniqAway' inScope bL++{- Note [Rebinding and shadowing]+Imagine:++@+\x -> \x -> e1 `aeq` \y -> \x -> e2+@++Then inside++@+\x \y { [x->p] [y->p] {p} }+\x \z { [x->q] [y->p, z->q] {p,q} }+@++i.e. if the new var is the same as the old var, the renaming is deleted by+'extendVarEnv'+-}++-- | Applies 'rnTyBndr' to several variables: the two variable lists must be of+-- equal length.+rnTyBndrs+ :: RnEnv -> [TyVar] -> [TyVar] -> RnEnv+rnTyBndrs env tvs1 tvs2 =+ List.foldl' (\s (l,r) -> rnTyBndr s l r) env (zipEqual tvs1 tvs2)++-- | Look up the renaming of an occurrence in the left term+rnOccLId+ :: RnEnv -> Id -> Id+rnOccLId rn v = fromMaybe v (lookupVarEnv v (rn_envLTm rn))++-- | Look up the renaming of an occurrence in the left term+rnOccRId+ :: RnEnv -> Id -> Id+rnOccRId rn v = fromMaybe v (lookupVarEnv v (rn_envRTm rn))++-- | Simultaneously go under the binder /bL/ and binder /bR/, finds a new binder+-- /newTvB/, and return an environment mapping @[bL -> newB]@ and @[bR -> newB]@+rnTmBndr+ :: RnEnv -> Id -> Id -> RnEnv+rnTmBndr rv@(RnEnv {rn_envLTm = lenv, rn_envRTm = renv, rn_inScope = inScope}) bL bR =+ rv { rn_envLTm = extendVarEnv bL newB lenv -- See Note [Rebinding and shadowing]+ , rn_envRTm = extendVarEnv bR newB renv+ , rn_inScope = extendInScopeSet inScope newB }+ where+ -- Find a new type-binder not in scope in either term+ newB | not (bL `elemInScopeSet` inScope) = bL+ | not (bR `elemInScopeSet` inScope) = bR+ | otherwise = uniqAway' inScope bL++-- | Applies 'rnTmBndr' to several variables: the two variable lists must be of+-- equal length.+rnTmBndrs+ :: RnEnv -> [Id] -> [Id] -> RnEnv+rnTmBndrs env ids1 ids2 =+ List.foldl' (\s (l,r) -> rnTmBndr s l r) env (zipEqual ids1 ids2)
src/Clash/Driver.hs view
@@ -10,7 +10,6 @@ {-# LANGUAGE NondecreasingIndentation #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TupleSections #-} module Clash.Driver where@@ -18,17 +17,21 @@ import qualified Control.Concurrent.Supply as Supply import Control.DeepSeq import Control.Exception (tryJust, bracket)-import Control.Lens ((^.), _5)-import Control.Monad (guard, when, unless)+import Control.Lens (view, (^.), _4)+import Control.Monad (guard, when, unless, foldM)+import Control.Monad.Catch (MonadMask)+import Control.Monad.IO.Class (MonadIO) import Control.Monad.State (evalState, get)+import Control.Monad.State.Strict (State) import Data.Hashable (hash)-import qualified Data.HashMap.Lazy as HML import Data.HashMap.Strict (HashMap)-import qualified Data.HashMap.Strict as HM+import qualified Data.HashMap.Strict as HashMap import qualified Data.HashSet as HashSet import Data.IntMap (IntMap)+import Data.List (intercalate) import Data.Maybe (fromMaybe) import Data.Semigroup.Monad+import qualified Data.Text import Data.Text.Lazy (Text) import qualified Data.Text.Lazy as Text import qualified Data.Text.Lazy.IO as Text@@ -37,57 +40,77 @@ (Doc, LayoutOptions (..), PageWidth (..) , layoutPretty, renderLazy, renderOneLine) import qualified Data.Time.Clock as Clock+import qualified Language.Haskell.Interpreter as Hint+import qualified Language.Haskell.Interpreter.Unsafe as Hint import qualified System.Directory as Directory+import System.Environment (getExecutablePath) import System.FilePath ((</>), (<.>)) import qualified System.FilePath as FilePath import qualified System.IO as IO import System.IO.Error (isDoesNotExistError)+import System.IO.Temp+ (getCanonicalTemporaryDirectory, withTempDirectory) import qualified Text.PrettyPrint.ANSI.Leijen as ANSI import Text.Trifecta.Result+ (Result(Success, Failure), _errDoc) import Text.Read (readMaybe)-+import SrcLoc (SrcSpan) import GHC.BasicTypes.Extra () +import Clash.Annotations.Primitive+ (HDL (..))+import Clash.Annotations.BitRepresentation.Internal+ (CustomReprs) import Clash.Annotations.TopEntity (TopEntity (..)) import Clash.Annotations.TopEntity.Extra () import Clash.Backend import Clash.Core.Evaluator (PrimEvaluator)-import Clash.Core.Name (Name (..), name2String)-import Clash.Core.Term (Term, TmName, TmOccName)+import Clash.Core.Name (Name (..))+import Clash.Core.Term (Term) import Clash.Core.Type (Type)-import Clash.Core.TyCon (TyCon, TyConName, TyConOccName)+import Clash.Core.TyCon (TyConMap, TyConName)+import Clash.Core.Var (Id, varName)+import Clash.Core.VarEnv (emptyVarEnv) import Clash.Driver.Types import Clash.Netlist (genNetlist)-import Clash.Netlist.Util (genComponentName)+import Clash.Netlist.Util (genComponentName, genTopComponentName) import Clash.Netlist.BlackBox.Parser (runParse)-import Clash.Netlist.BlackBox.Types (BlackBoxTemplate)-import Clash.Netlist.Types (Component (..), HWType)+import Clash.Netlist.BlackBox.Types (BlackBoxTemplate, BlackBoxFunction)+import Clash.Netlist.Types+ (BlackBox (..), Component (..), Identifier, FilteredHWType, HWMap) import Clash.Normalize (checkNonRecursive, cleanupGraph, normalize, runNormalization) import Clash.Normalize.Util (callGraph) import Clash.Primitives.Types-import Clash.Util (first, second)+import Clash.Primitives.Util (hashCompiledPrimMap)+import Clash.Unique (keysUniqMap, lookupUniqMap')+import Clash.Util (first, reportTimeDiff) +-- | Get modification data of current clash binary.+getClashModificationDate :: IO Clock.UTCTime+getClashModificationDate = Directory.getModificationTime =<< getExecutablePath+ -- | Create a set of target HDL files for a set of functions generateHDL :: forall backend . Backend backend- => BindingMap+ => CustomReprs+ -> BindingMap -- ^ Set of functions -> Maybe backend- -> PrimMap (Text.Text)+ -> CompiledPrimMap -- ^ Primitive / BlackBox Definitions- -> HashMap TyConOccName TyCon+ -> TyConMap -- ^ TyCon cache -> IntMap TyConName -- ^ Tuple TyCon cache- -> (HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType))+ -> (CustomReprs -> TyConMap -> Type ->+ State HWMap (Maybe (Either String FilteredHWType))) -- ^ Hardcoded 'Type' -> 'HWType' translator -> PrimEvaluator -- ^ Hardcoded evaluator (delta-reduction)- -> [( TmName- , Type+ -> [( Id , Maybe TopEntity- , Maybe TmName+ , Maybe Id )] -- ^ topEntity bndr -- + (maybe) TopEntity annotation@@ -96,46 +119,86 @@ -- ^ Debug information level for the normalization process -> (Clock.UTCTime,Clock.UTCTime) -> IO ()-generateHDL bindingsMap hdlState primMap tcm tupTcm typeTrans eval topEntities- opts (startTime,prepTime) = go prepTime [] topEntities where-- primMap' = HM.map parsePrimitive primMap+generateHDL reprs bindingsMap hdlState primMap tcm tupTcm typeTrans eval+ topEntities opts (startTime,prepTime) = go prepTime HashMap.empty topEntities where - -- No more TopEntities to process- go prevTime _ [] = putStrLn $ "Total compilation took " ++- show (Clock.diffUTCTime prevTime startTime)+ go prevTime _ [] = putStrLn $ "Clash: Total compilation took " +++ reportTimeDiff prevTime startTime -- Process the next TopEntity- go prevTime seen ((topEntity,_,annM,benchM):topEntities') = do- putStrLn $ "Compiling: " ++ name2String topEntity+ go prevTime seen ((topEntity,annM,benchM):topEntities') = do+ let topEntityS = Data.Text.unpack (nameOcc (varName topEntity))+ putStrLn $ "Clash: Compiling " ++ topEntityS -- Some initial setup- let modName = maybe (takeWhile (/= '.') (name2String topEntity)) t_name annM+ let modName1 = takeWhile (/= '.') topEntityS+ (modName,prefixM) = case opt_componentPrefix opts of+ Just 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 (Data.Text.pack p),Just (Data.Text.pack nm)))+ -- Prefix top names with 'p', prefix other with 'p'+ _ -> (p ++ '_':modName1,(Just (Data.Text.pack p),Just (Data.Text.pack p)))+ | Just ann <- annM -> case hdlKind (undefined :: backend) of+ -- Prefix other with 't_name'+ VHDL -> (t_name ann,(Nothing,Just (Data.Text.pack (t_name ann))))+ _ -> (t_name ann,(Nothing,Nothing))+ _ -> case annM of+ Just ann -> case hdlKind (undefined :: backend) of+ VHDL -> (t_name ann, (Nothing,Nothing))+ -- Prefix other with 't_name'+ _ -> (t_name ann, (Nothing,Just (Data.Text.pack (t_name ann))))+ _ -> (modName1, (Nothing,Nothing)) iw = opt_intWidth opts hdlsyn = opt_hdlSyn opts- hdlState' = setModName modName- $ fromMaybe (initBackend iw hdlsyn :: backend) hdlState+ escpIds = opt_escapedIds opts+ forceUnd = opt_forceUndefined opts+ hdlState' = setModName (Data.Text.pack modName)+ $ fromMaybe (initBackend iw hdlsyn escpIds forceUnd :: backend) hdlState hdlDir = fromMaybe "." (opt_hdlDir opts) </> Clash.Backend.name hdlState' </>- takeWhile (/= '.') (name2String topEntity)+ takeWhile (/= '.') topEntityS mkId = evalState mkIdentifier hdlState' extId = evalState extendIdentifier hdlState'- topName = genComponentName [] mkId topEntity- topNm = maybe topName- (Text.pack . t_name)- annM+ ite = ifThenElseExpr hdlState'+ topNm = genTopComponentName (opt_newInlineStrat opts) mkId prefixM+ annM topEntity+ topNmU = Data.Text.unpack topNm - unless (opt_cachehdl opts) $ putStrLn "Ignoring .manifest files"+ unless (opt_cachehdl opts) $ putStrLn "Clash: Ignoring .manifest files" -- Calculate the hash over the callgraph and the topEntity annotation (sameTopHash,sameBenchHash,manifest) <- do- let topHash = hash (annM,callGraphBindings bindingsMap (nameOcc topEntity))- benchHashM = fmap (hash . (annM,) . callGraphBindings bindingsMap . nameOcc) benchM- manifestI = Manifest (topHash,benchHashM) [] [] [] [] []+ clashModDate <- getClashModificationDate - manFile = maybe (hdlDir </> Text.unpack topNm <.> "manifest")- (\ann -> hdlDir </> t_name ann </> t_name ann <.> "manifest")- annM+ let primMapHash = hashCompiledPrimMap primMap++ let+ topHash =+ hash ( annM+ , primMapHash+ , show clashModDate+ , callGraphBindings bindingsMap topEntity+ )++ let+ benchHashM =+ case benchM of+ Nothing -> Nothing+ Just bench ->+ let terms = callGraphBindings bindingsMap bench in+ Just (hash (annM, primMapHash, show clashModDate, terms))++ let manifestI = Manifest (topHash,benchHashM) [] [] [] [] []++ let+ manFile =+ case annM of+ Nothing -> hdlDir </> topNmU <.> "manifest"+ _ -> hdlDir </> topNmU </> topNmU <.> "manifest"+ manM <- if not (opt_cachehdl opts) then return Nothing -- ignore manifest file because -fclash-nocache else (>>= readMaybe) . either (const Nothing) Just <$>@@ -151,147 +214,311 @@ . snd . Supply.freshId <$> Supply.newSupply- let topEntityNames = map (\(x,_,_,_) -> nameOcc x) topEntities+ let topEntityNames = map (\(x,_,_) -> x) topEntities (topTime,manifest',seen') <- if sameTopHash then do- putStrLn ("Using cached result for: " ++ name2String topEntity)+ putStrLn ("Clash: Using cached result for: " ++ Data.Text.unpack (nameOcc (varName topEntity))) topTime <- Clock.getCurrentTime- return (topTime,manifest,componentNames manifest ++ seen)+ return (topTime,manifest,HashMap.unionWith max (HashMap.fromList (map (,0) (componentNames manifest))) seen) else do -- 1. Normalise topEntity- let transformedBindings = normalizeEntity bindingsMap primMap' tcm tupTcm+ let transformedBindings = normalizeEntity reprs bindingsMap primMap tcm tupTcm typeTrans eval topEntityNames opts supplyN- (nameOcc topEntity)+ topEntity normTime <- transformedBindings `deepseq` Clock.getCurrentTime- let prepNormDiff = Clock.diffUTCTime normTime prevTime- putStrLn $ "Normalisation took " ++ show prepNormDiff+ let prepNormDiff = reportTimeDiff normTime prevTime+ putStrLn $ "Clash: Normalisation took " ++ prepNormDiff -- 2. Generate netlist for topEntity- (netlist,dfiles,seen') <- genNetlist transformedBindings topEntities primMap'- tcm typeTrans [] iw mkId extId seen- hdlDir (nameOcc topEntity) + -- [Note] Create HDL dir before netlist generation+ --+ -- 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+ let dir = hdlDir </> maybe "" (const modName) annM+ prepareDir (opt_cleanhdl opts) (extension hdlState') dir+ -- Now start the netlist generation+ (netlist,seen') <-+ genNetlist False opts reprs transformedBindings topEntities primMap+ tcm typeTrans iw mkId extId ite seen hdlDir prefixM topEntity+ netlistTime <- netlist `deepseq` Clock.getCurrentTime- let normNetDiff = Clock.diffUTCTime netlistTime normTime- putStrLn $ "Netlist generation took " ++ show normNetDiff+ let normNetDiff = reportTimeDiff netlistTime normTime+ putStrLn $ "Clash: Netlist generation took " ++ normNetDiff -- 3. Generate topEntity wrapper- let topComponent = snd . head $- filter (\(_,Component cName _ _ _) -> maybe- (Text.isSuffixOf (genComponentName [] mkId topEntity))- (\te n -> n == Text.pack (t_name te)) annM- cName)- netlist- (hdlDocs,manifest') = createHDL hdlState' modName netlist topComponent- (Text.unpack topNm, Right manifest)- dir = hdlDir </> maybe "" t_name annM- prepareDir (opt_cleanhdl opts) (extension hdlState') dir+ let topComponent = view _4 . head $ filter (Data.Text.isSuffixOf topNm . componentName . view _4) netlist+ (hdlDocs,manifest',dfiles,mfiles) = createHDL hdlState' (Data.Text.pack modName) seen' netlist topComponent+ (topNm, Right manifest) mapM_ (writeHDL dir) hdlDocs copyDataFiles (opt_importPaths opts) dir dfiles+ writeMemoryDataFiles dir mfiles topTime <- hdlDocs `seq` Clock.getCurrentTime return (topTime,manifest',seen') benchTime <- case benchM of Just tb | not sameBenchHash -> do- putStrLn $ "Compiling: " ++ name2String tb+ putStrLn $ "Clash: Compiling " ++ Data.Text.unpack (nameOcc (varName tb)) - let modName' = Text.unpack (genComponentName [] mkId tb)+ let modName' = genComponentName (opt_newInlineStrat opts) HashMap.empty+ mkId prefixM tb hdlState2 = setModName modName' hdlState' -- 1. Normalise testBench- let transformedBindings = normalizeEntity bindingsMap primMap' tcm tupTcm- typeTrans eval topEntityNames opts supplyTB (nameOcc tb)+ let transformedBindings = normalizeEntity reprs bindingsMap primMap tcm tupTcm+ typeTrans eval topEntityNames opts supplyTB tb normTime <- transformedBindings `deepseq` Clock.getCurrentTime- let prepNormDiff = Clock.diffUTCTime normTime topTime- putStrLn $ "Testbench normalisation took " ++ show prepNormDiff+ let prepNormDiff = reportTimeDiff normTime topTime+ putStrLn $ "Clash: Testbench normalisation took " ++ prepNormDiff -- 2. Generate netlist for topEntity- (netlist,dfiles,_) <- genNetlist transformedBindings topEntities primMap'- tcm typeTrans [] iw mkId extId seen'- hdlDir (nameOcc tb) + -- See [Note] Create HDL dir before netlist generation+ let dir = hdlDir </> maybe "" t_name annM </> Data.Text.unpack modName'+ prepareDir (opt_cleanhdl opts) (extension hdlState2) dir+ -- Now start the netlist generation+ (netlist,seen'') <-+ genNetlist True opts reprs transformedBindings topEntities primMap+ tcm typeTrans iw mkId extId ite seen' hdlDir prefixM tb+ netlistTime <- netlist `deepseq` Clock.getCurrentTime- let normNetDiff = Clock.diffUTCTime netlistTime normTime- putStrLn $ "Testbench netlist generation took " ++ show normNetDiff+ let normNetDiff = reportTimeDiff netlistTime normTime+ putStrLn $ "Clash: Testbench netlist generation took " ++ normNetDiff -- 3. Write HDL- let (hdlDocs,_) = createHDL hdlState2 modName' netlist undefined- (Text.unpack topNm, Left manifest')- dir = hdlDir </> maybe "" t_name annM </> modName'- prepareDir (opt_cleanhdl opts) (extension hdlState2) dir+ let (hdlDocs,_,dfiles,mfiles) = createHDL hdlState2 modName' seen'' netlist undefined+ (topNm, Left manifest') writeHDL (hdlDir </> maybe "" t_name annM) (head hdlDocs) mapM_ (writeHDL dir) (tail hdlDocs) copyDataFiles (opt_importPaths opts) dir dfiles+ writeMemoryDataFiles dir mfiles hdlDocs `seq` Clock.getCurrentTime Just tb -> do- let tb' = name2String tb- putStrLn ("Compiling: " ++ tb')- putStrLn ("Using cached result for: " ++ tb')+ let tb' = Data.Text.unpack (nameOcc (varName tb))+ putStrLn ("Clash: Compiling: " ++ tb')+ putStrLn ("Clash: Using cached result for: " ++ tb') return topTime Nothing -> return topTime go benchTime seen' topEntities' -parsePrimitive :: Primitive Text -> Primitive BlackBoxTemplate-parsePrimitive (BlackBox pNm oReg libM imps inc templT) =- case either (fmap Left . runParse) (fmap Right . runParse) templT of- Failure errInfo- -> error (ANSI.displayS (ANSI.renderCompact (_errDoc errInfo)) "")- Success templ- -> BlackBox pNm oReg (map parseBB libM) (map parseBB imps) inc' templ+-- | Interpret a specific function from a specific module. This action tries+-- two things:+--+-- 1. Interpret without explicitly loading the module. This will succeed if+-- the module was already loaded through a package database (set using+-- 'interpreterArgs').+--+-- 2. If (1) fails, it does try to load it explicitly. If this also fails,+-- an error is returned.+--+loadImportAndInterpret+ :: (MonadIO m, MonadMask m)+ => [String]+ -- ^ Extra search path (usually passed as -i)+ -> [String]+ -- ^ Interpreter args+ -> String+ -- ^ The folder in which the GHC bootstrap libraries (base, containers, etc.)+ -- can be found+ -> Hint.ModuleName+ -- ^ Module function lives in+ -> String+ -- ^ Function name+ -> String+ -- ^ Type name ("BlackBoxFunction" or "TemplateFunction")+ -> m (Either Hint.InterpreterError a)+loadImportAndInterpret iPaths0 interpreterArgs topDir qualMod funcName typ = do+ -- Try to interpret function *without* loading module explicitly. If this+ -- succeeds, the module was already in the global package database(s).+ bbfE <- Hint.unsafeRunInterpreterWithArgsLibdir interpreterArgs topDir $ do+ iPaths1 <- (++iPaths0) <$> Hint.get Hint.searchPath+ Hint.set [Hint.searchPath Hint.:= iPaths1]+ Hint.setImports [ "Clash.Netlist.Types", "Clash.Netlist.BlackBox.Types", qualMod]+ Hint.unsafeInterpret funcName typ++ case bbfE of+ Left _ -> do+ -- Try to interpret module as a local module, not yet present in the+ -- global package database(s).+ Hint.unsafeRunInterpreterWithArgsLibdir interpreterArgs topDir $ do+ Hint.reset+ iPaths1 <- (iPaths0++) <$> Hint.get Hint.searchPath+ Hint.set [Hint.searchPath Hint.:= iPaths1]+ Hint.loadModules [qualMod]+ Hint.setImports [ "Clash.Netlist.BlackBox.Types", "Clash.Netlist.Types", qualMod]+ Hint.unsafeInterpret funcName typ+ Right _ -> do+ return bbfE++-- | Compiles blackbox functions and parses blackbox templates.+compilePrimitive+ :: [FilePath]+ -- ^ Import directories (-i flag)+ -> [FilePath]+ -- ^ Package databases+ -> FilePath+ -- ^ The folder in which the GHC bootstrap libraries (base, containers, etc.)+ -- can be found+ -> ResolvedPrimitive+ -- ^ Primitive to compile+ -> IO CompiledPrimitive+compilePrimitive idirs pkgDbs topDir (BlackBoxHaskell bbName wf bbGenName source) = do+ let interpreterArgs = concatMap (("-package-db":) . (:[])) pkgDbs+ -- Compile a blackbox template function or fetch it from an already compiled file.+ r <- go interpreterArgs source+ processHintError+ (show bbGenName)+ bbName+ (\bbFunc -> BlackBoxHaskell bbName wf bbGenName (hash source, bbFunc))+ r+ where+ qualMod = intercalate "." modNames+ BlackBoxFunctionName modNames funcName = bbGenName++ -- | Create directory based on base name and directory. Return path+ -- of directory just created.+ createDirectory'+ :: FilePath+ -> FilePath+ -> IO FilePath+ createDirectory' base sub =+ let new = base </> sub in+ Directory.createDirectory new >> return new++ go+ :: [String]+ -> Maybe Text+ -> IO (Either Hint.InterpreterError BlackBoxFunction)+ go args (Just source') = do+ -- Create a temporary directory with user module in it, add it to the+ -- list of import direcotries, and run as if it were a "normal" compiled+ -- module.+ tmpDir0 <- getCanonicalTemporaryDirectory+ withTempDirectory tmpDir0 "clash-prim-compile" $ \tmpDir1 -> do+ modDir <- foldM createDirectory' tmpDir1 (init modNames)+ Text.writeFile (modDir </> (last modNames ++ ".hs")) source'+ loadImportAndInterpret (tmpDir1:idirs) args topDir qualMod funcName "BlackBoxFunction"++ go args Nothing = do+ loadImportAndInterpret idirs args topDir qualMod funcName "BlackBoxFunction"++compilePrimitive idirs pkgDbs topDir (BlackBox pNm wf tkind () oReg libM imps incs templ) = do+ libM' <- mapM parseTempl libM+ imps' <- mapM parseTempl imps+ incs' <- mapM (traverse parseBB) incs+ templ' <- parseBB templ+ return (BlackBox pNm wf tkind () oReg libM' imps' incs' templ') where- inc' = case fmap (second runParse) inc of- Just (x,Success t) -> Just (x,t)- _ -> Nothing+ iArgs = concatMap (("-package-db":) . (:[])) pkgDbs - parseBB :: Text -> BlackBoxTemplate- parseBB t = case runParse t of+ parseTempl+ :: Applicative m+ => Text+ -> m BlackBoxTemplate+ parseTempl t = case runParse t of Failure errInfo -> error (ANSI.displayS (ANSI.renderCompact (_errDoc errInfo)) "")- Success templ- -> templ+ Success t'+ -> pure t' -parsePrimitive (Primitive pNm typ) = Primitive pNm typ+ parseBB+ :: ((TemplateFormat,BlackBoxFunctionName), Maybe Text)+ -> IO BlackBox+ parseBB ((TTemplate,_),Just t) = BBTemplate <$> parseTempl t+ parseBB ((TTemplate,_),Nothing) =+ error ("No template specified for blackbox: " ++ show pNm)+ parseBB ((THaskell,bbGenName),Just source) = do+ let BlackBoxFunctionName modNames funcName = bbGenName+ qualMod = intercalate "." modNames+ tmpDir <- getCanonicalTemporaryDirectory+ r <- withTempDirectory tmpDir "clash-prim-compile" $ \tmpDir' -> do+ let modDir = foldl (</>) tmpDir' (init modNames)+ Directory.createDirectoryIfMissing True modDir+ Text.writeFile (modDir </> last modNames <.> "hs") source+ loadImportAndInterpret (tmpDir':idirs) iArgs topDir qualMod funcName "TemplateFunction"+ let hsh = hash (qualMod, source)+ processHintError (show bbGenName) pNm (BBFunction (Data.Text.unpack pNm) hsh) r+ parseBB ((THaskell,bbGenName),Nothing) = do+ let BlackBoxFunctionName modNames funcName = bbGenName+ qualMod = intercalate "." modNames+ hsh = hash qualMod+ r <- loadImportAndInterpret idirs iArgs topDir qualMod funcName "TemplateFunction"+ processHintError (show bbGenName) pNm (BBFunction (Data.Text.unpack pNm) hsh) r +compilePrimitive _ _ _ (Primitive pNm wf typ) =+ return (Primitive pNm wf typ)++processHintError+ :: Monad m+ => String+ -> Data.Text.Text+ -> (t -> r)+ -> Either Hint.InterpreterError t+ -> m r+processHintError fun bb go r = case r of+ Left (Hint.GhcException err) ->+ error' "GHC Exception" err+ Left (Hint.NotAllowed err) ->+ error' "NotAllowed error" err+ Left (Hint.UnknownError err) ->+ error' "an unknown error" err+ Left (Hint.WontCompile ghcErrs) ->+ error' "compilation errors" (intercalate "\n\n" $ map Hint.errMsg ghcErrs)+ Right f ->+ return $ go f+ where+ error' errType report =+ error $ unwords [ "Encountered", errType, "while compiling blackbox template"+ , "function", show fun, "for function", show bb ++ "."+ , "Compilation reported: \n\n" ++ report ]+ -- | Pretty print Components to HDL Documents createHDL :: Backend backend => backend -- ^ Backend- -> String+ -> Identifier -- ^ Module hierarchy root- -> [(SrcSpan,Component)]+ -> HashMap Identifier Word+ -- ^ Component names+ -> [([Bool],SrcSpan,HashMap Identifier Word,Component)] -- ^ List of components -> Component -- ^ Top component- -> (String, Either Manifest Manifest)+ -> (Identifier, Either Manifest Manifest) -- ^ Name of the manifest file -- + Either: -- * Left manifest: Only write/update the hashes of the @manifest@ -- * Right manifest: Update all fields of the @manifest@- -> ([(String,Doc)],Manifest)+ -> ([(String,Doc)],Manifest,[(String,FilePath)],[(String,String)]) -- ^ The pretty-printed HDL documents -- + The update manifest file-createHDL backend modName components top (topName,manifestE) = flip evalState backend $ getMon $ do- (hdlNmDocs,incs) <- unzip <$> mapM (uncurry (genHDL modName)) components+ -- + The data files that need to be copied+createHDL backend modName seen components top (topName,manifestE) = flip evalState backend $ getMon $ do+ (hdlNmDocs,incs) <- unzip <$> mapM (\(_wereVoids,sp,ids,comp) -> genHDL modName sp (HashMap.unionWith max seen ids) comp) components hwtys <- HashSet.toList <$> extractTypes <$> Mon get typesPkg <- mkTyPackage modName hwtys+ dataFiles <- Mon getDataFiles+ memFiles <- Mon getMemoryDataFiles let hdl = map (first (<.> Clash.Backend.extension backend)) (typesPkg ++ hdlNmDocs) qincs = concat incs topFiles = hdl ++ qincs manifest <- either return (\m -> do- let topName' = Text.pack topName- let topInNames = map fst (inputs top)- topInTypes <- mapM (fmap renderOneLine . hdlType (External topName') . snd) (inputs top)+ let topInNames = map fst (inputs top)+ topInTypes <- mapM (fmap (Text.toStrict . renderOneLine) .+ hdlType (External topName) . snd) (inputs top) let topOutNames = map (fst . snd) (outputs top)- topOutTypes <- mapM (fmap renderOneLine . hdlType (External topName') . snd . snd) (outputs top)- let compNames = map (componentName.snd) components+ topOutTypes <- mapM (fmap (Text.toStrict . renderOneLine) .+ hdlType (External topName) . snd . snd) (outputs top)+ let compNames = map (componentName . view _4) components return (m { portInNames = topInNames , portInTypes = topInTypes , portOutNames = topOutNames@@ -299,9 +526,9 @@ , componentNames = compNames }) ) manifestE- let manDoc = ( topName <.> "manifest"+ let manDoc = ( Data.Text.unpack topName <.> "manifest" , pretty (Text.pack (show manifest)))- return (manDoc:topFiles,manifest)+ return (manDoc:topFiles,manifest,dataFiles,memFiles) -- | Prepares the directory for writing HDL files. This means creating the -- dir if it does not exist and removing all existing .hdl files from it.@@ -334,7 +561,23 @@ Text.hPutStr h (clean rendered) Text.hPutStr h (Text.pack "\n") -copyDataFiles :: [FilePath] -> FilePath -> [(String,FilePath)] -> IO ()+-- | Copy given files+writeMemoryDataFiles+ :: FilePath+ -- ^ Directory to copy files to+ -> [(String, String)]+ -- ^ (filename, content)+ -> IO ()+writeMemoryDataFiles dir files =+ mapM_+ (uncurry writeFile)+ [(dir </> fname, content) | (fname, content) <- files]++copyDataFiles+ :: [FilePath]+ -> FilePath+ -> [(String,FilePath)]+ -> IO () copyDataFiles idirs dir = mapM_ (copyFile' idirs) where copyFile' dirs (nm,old) = do@@ -361,43 +604,46 @@ callGraphBindings :: BindingMap -- ^ All bindings- -> TmOccName+ -> Id -- ^ Root of the call graph -> [Term] callGraphBindings bindingsMap tm =- map ((^. _5) . (bindingsMap HM.!)) (HM.keys cg)+ map ((^. _4) . (bindingsMap `lookupUniqMap'`)) (keysUniqMap cg) where cg = callGraph bindingsMap tm -- | Normalize a complete hierarchy normalizeEntity- :: BindingMap+ :: CustomReprs+ -> BindingMap -- ^ All bindings- -> PrimMap BlackBoxTemplate+ -> CompiledPrimMap -- ^ BlackBox HDL templates- -> HashMap TyConOccName TyCon+ -> TyConMap -- ^ TyCon cache -> IntMap TyConName -- ^ Tuple TyCon cache- -> (HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType))+ -> (CustomReprs -> TyConMap -> Type ->+ State HWMap (Maybe (Either String FilteredHWType))) -- ^ Hardcoded 'Type' -> 'HWType' translator -> PrimEvaluator -- ^ Hardcoded evaluator (delta-reduction)- -> [TmOccName]+ -> [Id] -- ^ TopEntities -> ClashOpts -- ^ Debug information level for the normalization process -> Supply.Supply -- ^ Unique supply- -> TmOccName+ -> Id -- ^ root of the hierarchy -> BindingMap-normalizeEntity bindingsMap primMap tcm tupTcm typeTrans eval topEntities+normalizeEntity reprs bindingsMap primMap tcm tupTcm typeTrans eval topEntities opts supply tm = transformedBindings where doNorm = do norm <- normalize [tm] let normChecked = checkNonRecursive norm- cleanupGraph tm normChecked+ cleaned <- cleanupGraph tm normChecked+ return cleaned transformedBindings = runNormalization opts supply bindingsMap- typeTrans tcm tupTcm eval primMap HML.empty+ typeTrans reprs tcm tupTcm eval primMap emptyVarEnv topEntities doNorm
src/Clash/Driver/Types.hs view
@@ -8,36 +8,45 @@ Type definitions used by the Driver module -} -module Clash.Driver.Types- (module Clash.Driver.Types- ,SrcSpan, noSrcSpan- )-where+{-# LANGUAGE CPP #-} -import Control.Exception (Exception)-import Data.HashMap.Lazy (HashMap)-import Data.Text.Lazy (Text)+module Clash.Driver.Types where +-- For Int/Word size+#include "MachDeps.h"++import Data.Text (Text)+ import BasicTypes (InlineSpec)-import SrcLoc (SrcSpan, noSrcSpan)+import SrcLoc (SrcSpan) -import Clash.Core.Term (Term,TmName,TmOccName)-import Clash.Core.Type (Type)+import Clash.Core.Term (Term)+import Clash.Core.Var (Id)+import Clash.Core.VarEnv (VarEnv) -import Clash.Netlist.BlackBox.Types (HdlSyn)+import Clash.Netlist.BlackBox.Types (HdlSyn (..)) +import Util (OverridingBool(..))+ -- | Global function binders -- -- Global functions cannot be mutually recursive, only self-recursive-type BindingMap = HashMap TmOccName (TmName,Type,SrcSpan,InlineSpec,Term)+type BindingMap = VarEnv (Id,SrcSpan,InlineSpec,Term) -- | Debug Message Verbosity data DebugLevel- = DebugNone -- ^ Don't show debug messages- | DebugFinal -- ^ Show completely normalized expressions- | DebugName -- ^ Names of applied transformations- | DebugApplied -- ^ Show sub-expressions after a successful rewrite- | DebugAll -- ^ Show all sub-expressions on which a rewrite is attempted+ = 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+ -- ^ Names of 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) data ClashOpts = ClashOpts { opt_inlineLimit :: Int@@ -47,21 +56,65 @@ , opt_dbgLevel :: DebugLevel , opt_cachehdl :: Bool , opt_cleanhdl :: Bool+ , opt_primWarn :: Bool+ , opt_color :: OverridingBool , opt_intWidth :: Int , opt_hdlDir :: Maybe String+ -- ^ Directory to store temporary files in. Will be+ -- cleaned after Clash has finished executing. , opt_hdlSyn :: HdlSyn , opt_errorExtra :: Bool , opt_floatSupport :: Bool- , opt_allowZero :: Bool , opt_importPaths :: [FilePath]+ , opt_componentPrefix :: Maybe String+ , opt_newInlineStrat :: Bool+ , opt_escapedIds :: Bool+ , opt_ultra :: Bool+ -- ^ Perform a high-effort compile, trading improved+ -- performance for potentially much longer compile+ -- times.+ --+ -- Name inspired by Design Compiler's /compile_ultra/+ -- flag.+ , opt_forceUndefined :: Maybe (Maybe Int)+ -- ^+ -- * /Nothing/: generate undefined's in the HDL+ --+ -- * /Just Nothing/: replace undefined's by a+ -- constant in the HDL; the compiler decides what's+ -- best+ --+ -- * /Just (Just x)/: replace undefined's by /x/ in+ -- the HDL+ , opt_checkIDir :: Bool } -data ClashException = ClashException SrcSpan String (Maybe String) -instance Show ClashException where- show (ClashException _ s eM) = s ++ "\n" ++ maybe "" id eM--instance Exception ClashException+defClashOpts :: ClashOpts+defClashOpts+ = ClashOpts+ { opt_dbgLevel = DebugNone+ , opt_inlineLimit = 20+ , opt_specLimit = 20+ , opt_inlineFunctionLimit = 15+ , opt_inlineConstantLimit = 0+ , opt_cachehdl = True+ , opt_cleanhdl = True+ , opt_primWarn = True+ , opt_color = Auto+ , opt_intWidth = WORD_SIZE_IN_BITS+ , opt_hdlDir = Nothing+ , opt_hdlSyn = Other+ , opt_errorExtra = False+ , opt_floatSupport = False+ , opt_importPaths = []+ , opt_componentPrefix = Nothing+ , opt_newInlineStrat = True+ , opt_escapedIds = True+ , opt_ultra = False+ , opt_forceUndefined = Nothing+ , opt_checkIDir = True+ } -- | Information about the generated HDL between (sub)runs of the compiler data Manifest
src/Clash/Netlist.hs view
@@ -1,7 +1,7 @@ {-| Copyright : (C) 2012-2016, University of Twente, 2016-2017, Myrtle Software Ltd,- 2017 , Google Inc.+ 2017-2018, Google Inc. License : BSD2 (see the file LICENSE) Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com> @@ -9,6 +9,7 @@ -} {-# LANGUAGE MagicHash #-}+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TupleSections #-}@@ -17,184 +18,236 @@ module Clash.Netlist where import Control.Exception (throw)-import Control.Lens ((.=),(^.),_1,_3)+import Control.Lens ((.=),(^.),_2) import qualified Control.Lens as Lens+import Control.Monad (join) import Control.Monad.IO.Class (liftIO)-import Control.Monad.State.Strict (runStateT)+import Control.Monad.Reader (runReaderT)+import Control.Monad.State.Strict (State, runStateT) import Data.Binary.IEEE754 (floatToWord, doubleToWord) import Data.Char (ord)-import Data.Either (lefts,partitionEithers)-import Data.HashMap.Lazy (HashMap)+import Data.Either (partitionEithers)+import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HashMapS import qualified Data.HashMap.Lazy as HashMap-import Data.List (elemIndex)-import Data.Maybe (catMaybes)+import Data.List (elemIndex, sortOn)+import Data.Maybe (catMaybes, listToMaybe, fromMaybe)+import qualified Data.Set as Set import Data.Primitive.ByteArray (ByteArray (..))-import qualified Data.Text.Lazy as Text+import qualified Data.Text as StrictText import qualified Data.Vector.Primitive as PV import GHC.Integer.GMP.Internals (Integer (..), BigNat (..)) import System.FilePath ((</>), (<.>)) import Text.Read (readMaybe)-import Unbound.Generics.LocallyNameless- (Embed (..), runFreshMT, unbind, unembed, unrebind) import Outputable (ppr, showSDocUnsafe)-import SrcLoc (SrcSpan,isGoodSrcSpan,noSrcSpan)+import SrcLoc (isGoodSrcSpan) +import Clash.Annotations.Primitive (extractPrim)+import Clash.Annotations.BitRepresentation.ClashLib+ (coreToType')+import Clash.Annotations.BitRepresentation.Internal+ (CustomReprs, DataRepr'(..), ConstrRepr'(..), getDataRepr, getConstrRepr) import Clash.Annotations.TopEntity (TopEntity (..)) import Clash.Core.DataCon (DataCon (..))-import Clash.Core.FreeVars (typeFreeVars) import Clash.Core.Literal (Literal (..))-import Clash.Core.Name (Name(..), name2String)-import Clash.Core.Pretty (showDoc)+import Clash.Core.Name (Name(..))+import Clash.Core.Pretty (showPpr) import Clash.Core.Term- (Alt, Pat (..), Term (..), TmName, TmOccName)+ (Alt, Pat (..), Term (..), TickInfo (..), collectArgs, collectArgsTicks, collectTicks) import qualified Clash.Core.Term as Core-import Clash.Core.Type (Type (..), splitFunTys)-import Clash.Core.TyCon- (TyCon, TyConOccName)-import Clash.Core.Util (collectArgs, termType)+import Clash.Core.Type+ (Type (..), coreView1, splitFunTys, splitCoreFunForallTy)+import Clash.Core.TyCon (TyConMap)+import Clash.Core.Util+ (mkApps, mkTicks, stripTicks, termType) import Clash.Core.Var (Id, Var (..))-import Clash.Driver.Types- (BindingMap, ClashException (..))+import Clash.Core.VarEnv+ (VarEnv, eltsVarEnv, emptyInScopeSet, emptyVarEnv, extendVarEnv, lookupVarEnv,+ lookupVarEnv', mkVarEnv)+import Clash.Driver.Types (BindingMap, ClashOpts (..)) import Clash.Netlist.BlackBox-import Clash.Netlist.BlackBox.Types (BlackBoxTemplate) import Clash.Netlist.Id import Clash.Netlist.Types as HW import Clash.Netlist.Util import Clash.Primitives.Types as P import Clash.Util + -- | Generate a hierarchical netlist out of a set of global binders with -- @topEntity@ at the top.-genNetlist :: BindingMap- -- ^ Global binders- -> [(TmName,Type,Maybe TopEntity,Maybe TmName)]- -- ^ All the TopEntities- -> PrimMap BlackBoxTemplate- -- ^ Primitive definitions- -> HashMap TyConOccName TyCon- -- ^ TyCon cache- -> (HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType))- -- ^ Hardcoded Type -> HWType translator- -> [(String,FilePath)]- -- ^ Set of collected data-files- -> Int- -- ^ Int/Word/Integer bit-width- -> (IdType -> Identifier -> Identifier)- -- ^ valid identifiers- -> (IdType -> Identifier -> Identifier -> Identifier)- -- ^ extend valid identifiers- -> [Identifier]- -- ^ Seen components- -> FilePath- -- ^ HDL dir- -> TmOccName- -- ^ Name of the @topEntity@- -> IO ([(SrcSpan,Component)],[(String,FilePath)],[Identifier])-genNetlist globals tops primMap tcm typeTrans dfiles iw mkId extId seen env topEntity = do- (_,s) <- runNetlistMonad globals (mkTopEntityMap tops) primMap tcm typeTrans- dfiles iw mkId extId seen env $ genComponent topEntity- return (HashMap.elems $ _components s, _dataFiles s, _seenComps s)+genNetlist+ :: 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+ -> [(Id,Maybe TopEntity,Maybe Id)]+ -- ^ All the TopEntities+ -> 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+ -> (IdType -> Identifier -> Identifier)+ -- ^ valid identifiers+ -> (IdType -> Identifier -> Identifier -> Identifier)+ -- ^ extend valid identifiers+ -> Bool+ -- ^ Whether the backend supports ifThenElse expressions+ -> HashMap Identifier Word+ -- ^ Seen components+ -> FilePath+ -- ^ HDL dir+ -> (Maybe Identifier,Maybe Identifier)+ -- ^ Component name prefix+ -> Id+ -- ^ Name of the @topEntity@+ -> IO ([([Bool],SrcSpan,HashMap Identifier Word,Component)],HashMap Identifier Word)+genNetlist isTb opts reprs globals tops primMap tcm typeTrans iw mkId extId ite seen env prefixM topEntity = do+ (_,s) <- runNetlistMonad isTb opts reprs globals (mkTopEntityMap tops)+ primMap tcm typeTrans iw mkId extId ite seen env prefixM $+ genComponent topEntity+ return ( eltsVarEnv $ _components s+ , _seenComps s+ ) where mkTopEntityMap- :: [(TmName,Type,Maybe TopEntity,Maybe TmName)]- -> HashMap TmOccName (Type, Maybe TopEntity)- mkTopEntityMap = HashMap.fromList . map (\(a,b,c,_) -> (nameOcc a,(b,c)))+ :: [(Id,Maybe TopEntity,Maybe Id)]+ -> VarEnv (Type,Maybe TopEntity)+ mkTopEntityMap = mkVarEnv . map (\(a,b,_) -> (a,(varType a,b))) -- | Run a NetlistMonad action in a given environment-runNetlistMonad :: BindingMap- -- ^ Global binders- -> HashMap TmOccName (Type, Maybe TopEntity)- -- ^ TopEntity annotations- -> PrimMap BlackBoxTemplate- -- ^ Primitive Definitions- -> HashMap TyConOccName TyCon- -- ^ TyCon cache- -> (HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType))- -- ^ Hardcode Type -> HWType translator- -> [(String,FilePath)]- -- ^ Set of collected data-files- -> Int- -- ^ Int/Word/Integer bit-width- -> (IdType -> Identifier -> Identifier)- -- ^ valid identifiers- -> (IdType -> Identifier -> Identifier -> Identifier)- -- ^ extend valid identifiers- -> [Identifier]- -- ^ Seen components- -> FilePath- -- ^ HDL dir- -> NetlistMonad a- -- ^ Action to run- -> IO (a, NetlistState)-runNetlistMonad s tops p tcm typeTrans dfiles iw mkId extId seenIds_ env- = runFreshMT+runNetlistMonad+ :: 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 (Type, Maybe TopEntity)+ -- ^ TopEntity annotations+ -> CompiledPrimMap+ -- ^ Primitive Definitions+ -> TyConMap+ -- ^ TyCon cache+ -> (CustomReprs -> TyConMap -> Type ->+ State HWMap (Maybe (Either String FilteredHWType)))+ -- ^ Hardcode Type -> HWType translator+ -> Int+ -- ^ Int/Word/Integer bit-width+ -> (IdType -> Identifier -> Identifier)+ -- ^ valid identifiers+ -> (IdType -> Identifier -> Identifier -> Identifier)+ -- ^ extend valid identifiers+ -> Bool+ -- ^ Whether the backend supports ifThenElse expressions+ -> HashMap Identifier Word+ -- ^ Seen components+ -> FilePath+ -- ^ HDL dir+ -> (Maybe Identifier,Maybe Identifier)+ -- ^ Component name prefix+ -> NetlistMonad a+ -- ^ Action to run+ -> IO (a, NetlistState)+runNetlistMonad isTb opts reprs s tops p tcm typeTrans iw mkId extId ite seenIds_ env prefixM+ = flip runReaderT (NetlistEnv "" "" Nothing) . flip runStateT s' . runNetlist where- s' = NetlistState s 0 HashMap.empty p typeTrans tcm (Text.empty,noSrcSpan) dfiles iw mkId extId [] seenIds' names tops env 0- (seenIds',names) = genNames mkId seenIds_ HashMap.empty (HashMap.elems (HashMap.map (^. _1) s))+ s' =+ NetlistState+ s 0 emptyVarEnv p typeTrans tcm (StrictText.empty,noSrcSpan) iw mkId+ extId HashMapS.empty seenIds' Set.empty names tops env 0 prefixM reprs opts isTb ite+ HashMapS.empty -genNames :: (IdType -> Identifier -> Identifier)- -> [Identifier]- -> HashMap TmOccName Identifier- -> [TmName]- -> ([Identifier], HashMap TmOccName Identifier)-genNames mkId = go+ (seenIds',names) = genNames (opt_newInlineStrat opts) mkId prefixM seenIds_+ emptyVarEnv s++genNames :: Bool+ -> (IdType -> Identifier -> Identifier)+ -> (Maybe Identifier,Maybe Identifier)+ -> HashMap Identifier Word+ -> VarEnv Identifier+ -> BindingMap+ -> (HashMap Identifier Word, VarEnv Identifier)+genNames newInlineStrat mkId prefixM s0 m0 = foldr go (s0,m0) where- go s m [] = (s,m)- go s m (nm:nms) = let nm' = genComponentName s mkId nm- s' = nm':s- m' = HashMap.insert (nameOcc nm) nm' m- in go s' m' nms+ go (v,_,_,_) (s,m) =+ let nm' = genComponentName newInlineStrat s mkId prefixM v+ s' = HashMapS.insert nm' 0 s+ m' = extendVarEnv v nm' m+ in (s', m') -- | Generate a component for a given function (caching) genComponent- :: TmOccName+ :: HasCallStack+ => Id -- ^ Name of the function- -> NetlistMonad (SrcSpan,Component)+ -> NetlistMonad ([Bool],SrcSpan,HashMap Identifier Word,Component) genComponent compName = do- compExprM <- fmap (HashMap.lookup compName) $ Lens.use bindings+ compExprM <- lookupVarEnv compName <$> Lens.use bindings case compExprM of Nothing -> do (_,sp) <- Lens.use curCompNm throw (ClashException sp ($(curLoc) ++ "No normalized expression found for: " ++ show compName) Nothing)- Just (_,_,_,_,expr_) -> do- makeCached compName components $ genComponentT compName expr_+ Just (_,_,_,expr_) -> do+ makeCachedU compName components $ genComponentT compName expr_ -- | Generate a component for a given function genComponentT- :: TmOccName+ :: HasCallStack+ => Id -- ^ Name of the function -> Term -- ^ Corresponding term- -> NetlistMonad (SrcSpan,Component)+ -> NetlistMonad ([Bool],SrcSpan,HashMap Identifier Word,Component) genComponentT compName componentExpr = do varCount .= 0- componentName1 <- (HashMap.! compName) <$> Lens.use componentNames- topEntMM <- fmap snd . HashMap.lookup compName <$> Lens.use topEntityAnns- let componentName2 = maybe componentName1- (maybe componentName1 (Text.pack . t_name))- topEntMM- sp <- ((^. _3) . (HashMap.! compName)) <$> Lens.use bindings+ componentName1 <- (`lookupVarEnv'` compName) <$> Lens.use componentNames+ topEntMM <- fmap snd . lookupVarEnv compName <$> Lens.use topEntityAnns+ prefixM <- Lens.use componentPrefix+ let componentName2 = case (prefixM,join topEntMM) of+ ((Just p,_),Just ann) -> p `StrictText.append` StrictText.pack ('_':t_name ann)+ (_,Just ann) -> StrictText.pack (t_name ann)+ _ -> componentName1+ sp <- ((^. _2) . (`lookupVarEnv'` compName)) <$> Lens.use bindings curCompNm .= (componentName2,sp) tcm <- Lens.use tcCache - seenIds .= []- (compInps,argWrappers,compOutps,resUnwrappers,binders,result) <- do- normalizedM <- splitNormalized tcm componentExpr- case normalizedM of- Right normalized -> mkUniqueNormalized topEntMM normalized- Left err -> throw (ClashException sp err Nothing)+ -- HACK: Determine resulttype of this function by looking at its definition+ -- in topEntityAnns, instead of looking at its last binder (which obscure+ -- any attributes [see: Clash.Annotations.SynthesisAttributes]).+ topEntityTypeM <- lookupVarEnv compName <$> Lens.use topEntityAnns+ let topEntityTypeM' = snd . splitCoreFunForallTy tcm . fst <$> topEntityTypeM - netDecls <- fmap catMaybes . mapM mkNetDecl $ filter ((/= result) . varName . fst) binders- decls <- concat <$> mapM (uncurry mkDeclarations . second unembed) binders+ seenIds .= HashMapS.empty+ (wereVoids,compInps,argWrappers,compOutps,resUnwrappers,binders,resultM) <-+ case splitNormalized tcm componentExpr of+ Right (args, binds, res) -> do+ let varType' = fromMaybe (varType res) topEntityTypeM'+ mkUniqueNormalized emptyInScopeSet topEntMM ((args, binds, res{varType=varType'}))+ Left err ->+ throw (ClashException sp err Nothing) - resDecl <- mkNetDecl . head $ filter ((==result) . varName . fst) binders+ netDecls <- fmap catMaybes . mapM mkNetDecl $ filter (maybe (const True) (/=) resultM . fst) binders+ decls <- concat <$> mapM (uncurry mkDeclarations) binders - case resDecl of- Just (NetDecl' _ rw _ _) -> do+ case resultM of+ Just result -> do+ Just (NetDecl' _ rw _ _) <- mkNetDecl . head $ filter ((==result) . fst) binders+ let (compOutps',resUnwrappers') = case compOutps of [oport] -> ([(rw,oport)],resUnwrappers) _ -> let NetDecl n res resTy = head resUnwrappers@@ -203,161 +256,257 @@ ) component = Component componentName2 compInps compOutps' (netDecls ++ argWrappers ++ decls ++ resUnwrappers')- return (sp,component)+ ids <- Lens.use seenIds+ return (wereVoids, sp, ids, component) -- No result declaration means that the result is empty, this only happens -- when the TopEntity has an empty result. We just create an empty component -- in this case.- _ -> do- let component = Component componentName2 compInps [] []- return (sp, component)+ Nothing -> do+ let component = Component componentName2 compInps [] (netDecls ++ argWrappers ++ decls)+ ids <- Lens.use seenIds+ return (wereVoids, sp, ids, component) -mkNetDecl :: (Id, Embed Term) -> NetlistMonad (Maybe Declaration)+mkNetDecl :: (Id, Term) -> NetlistMonad (Maybe Declaration) mkNetDecl (id_,tm) = do- hwTy <- unsafeCoreTypeToHWTypeM $(curLoc) (unembed (varType id_))- wr <- wireOrReg (unembed tm)+ let typ = varType id_+ hwTy <- unsafeCoreTypeToHWTypeM' $(curLoc) typ+ wr <- termToWireOrReg tm if isVoid hwTy then return Nothing- else return . Just $ NetDecl' (addSrcNote (nameLoc nm))+ else return . Just $ NetDecl' (addSrcNote sp) wr- (Text.pack (name2String nm))+ (id2identifier id_) (Right hwTy) where nm = varName id_+ sp = case tm of {Tick (SrcSpan s) _ -> s; _ -> nameLoc nm} - wireOrReg :: Term -> NetlistMonad WireOrReg- wireOrReg (Case _ _ (_:_:_)) = return Reg- wireOrReg (collectArgs -> (Prim nm' _,_)) = do+ termToWireOrReg :: Term -> NetlistMonad WireOrReg+ termToWireOrReg (stripTicks -> Case scrut _ alts0@(_:_:_)) = do+ tcm <- Lens.use tcCache+ let scrutTy = termType tcm scrut+ scrutHTy <- unsafeCoreTypeToHWTypeM' $(curLoc) scrutTy+ ite <- Lens.use backEndITE+ case iteAlts scrutHTy alts0 of+ Just _ | ite -> return Wire+ _ -> return Reg+ termToWireOrReg (collectArgs -> (Prim nm' _,_)) = do bbM <- HashMap.lookup nm' <$> Lens.use primitives case bbM of- Just (BlackBox {..}) | outputReg -> return Reg+ Just (extractPrim -> Just BlackBox {..}) | outputReg -> return Reg _ -> return Wire- wireOrReg _ = return Wire+ termToWireOrReg _ = return Wire addSrcNote loc = if isGoodSrcSpan loc- then Just (Text.pack (showSDocUnsafe (ppr loc)))+ then Just (StrictText.pack (showSDocUnsafe (ppr loc))) else Nothing ++isWriteToBiSignalPrimitive :: Term -> Bool+isWriteToBiSignalPrimitive e = case collectArgs e of+ (Prim nm _,_) -> nm == StrictText.pack "Clash.Signal.BiSignal.writeToBiSignal#"+ _ -> False+ -- | Generate a list of Declarations for a let-binder, return an empty list -- if the bound expression is represented by 0 bits mkDeclarations- :: Id+ :: HasCallStack+ => Id -- ^ LHS of the let-binder -> Term -- ^ RHS of the let-binder -> NetlistMonad [Declaration] mkDeclarations bndr e = do- hty <- unsafeCoreTypeToHWTypeM $(curLoc) (unembed (varType bndr))- case hty of- Void {} -> return []- _ -> mkDeclarations' bndr e+ hty <- unsafeCoreTypeToHWTypeM' $(curLoc) (varType bndr)+ if isVoid hty && not (isBiSignalOut hty)+ then return []+ else mkDeclarations' bndr e -- | Generate a list of Declarations for a let-binder mkDeclarations'- :: Id+ :: HasCallStack+ => Id -- ^ LHS of the let-binder -> Term -- ^ RHS of the let-binder -> NetlistMonad [Declaration]-mkDeclarations' bndr (Var _ v) = mkFunApp bndr v []+mkDeclarations' bndr (collectTicks -> (Var v,ticks)) =+ withTicks ticks $ \tickDecls -> do+ mkFunApp (id2identifier bndr) v [] tickDecls -mkDeclarations' _ e@(Case _ _ []) = do+mkDeclarations' _ e@(collectTicks -> (Case _ _ [],_)) = do (_,sp) <- Lens.use curCompNm- throw (ClashException sp ($(curLoc) ++ "Not in normal form: Case-decompositions with an empty list of alternatives not supported:\n\n" ++ showDoc e) Nothing)+ throw $ ClashException+ sp+ ( unwords [ $(curLoc)+ , "Not in normal form: Case-decompositions with an"+ , "empty list of alternatives not supported:\n\n"+ , showPpr e+ ])+ Nothing -mkDeclarations' bndr (Case scrut altTy alts@(_:_:_)) =- mkSelection bndr scrut altTy alts+mkDeclarations' bndr (collectTicks -> (Case scrut altTy alts@(_:_:_),ticks)) =+ withTicks ticks $ \tickDecls -> do+ mkSelection (Right bndr) scrut altTy alts tickDecls mkDeclarations' bndr app =- let (appF,(args,tyArgs)) = second partitionEithers $ collectArgs app- in case appF of- Var _ f- | null tyArgs -> mkFunApp bndr f args+ let (appF,args0,ticks) = collectArgsTicks app+ (args,tyArgs) = partitionEithers args0+ in withTicks ticks $ \tickDecls -> do+ case appF of+ Var f+ | null tyArgs -> mkFunApp (id2identifier bndr) f args tickDecls | otherwise -> do (_,sp) <- Lens.use curCompNm- throw (ClashException sp ($(curLoc) ++ "Not in normal form: Var-application with Type arguments:\n\n" ++ showDoc app) Nothing)+ throw (ClashException sp ($(curLoc) ++ "Not in normal form: Var-application with Type arguments:\n\n" ++ showPpr app) Nothing)+ -- Do not generate any assignments writing to a BiSignalOut, as these+ -- do not have any significance in a HDL. The single exception occurs+ -- when writing to a BiSignal using the primitive 'writeToBiSignal'. In+ -- the generate HDL it will write to an inout port, NOT the variable+ -- having the actual type BiSignalOut.+ -- _ | isBiSignalOut (id2type bndr) && (not $ isWriteToBiSignalPrimitive app) ->+ -- return [] _ -> do- (exprApp,declsApp) <- mkExpr False (Right bndr) (unembed $ varType bndr) app- let dstId = Text.pack . name2String $ varName bndr- assn = case exprApp of- Identifier _ Nothing -> []- _ -> [Assignment dstId exprApp]- return (declsApp ++ assn)+ hwTy <- unsafeCoreTypeToHWTypeM' $(curLoc) (id2type bndr)+ if isBiSignalOut hwTy && not (isWriteToBiSignalPrimitive app)+ then return []+ else do+ (exprApp,declsApp0) <- mkExpr False (Right bndr) (varType bndr) app+ let dstId = id2identifier bndr+ assn = case exprApp of+ Identifier _ Nothing -> []+ _ -> [Assignment dstId exprApp]+ declsApp1 = if null declsApp0 then tickDecls else declsApp0+ return (declsApp1 ++ assn) -- | Generate a declaration that selects an alternative based on the value of -- the scrutinee mkSelection- :: Id+ :: (Either Identifier Id) -> Term -> Type -> [Alt]+ -> [Declaration] -> NetlistMonad [Declaration]-mkSelection bndr scrut altTy alts = do- alts' <- reorderPats <$> mapM unbind alts- tcm <- Lens.use tcCache- scrutTy <- termType tcm scrut- scrutHTy <- unsafeCoreTypeToHWTypeM $(curLoc) scrutTy- altHTy <- unsafeCoreTypeToHWTypeM $(curLoc) altTy- scrutId <- extendIdentifier Extended- (Text.pack (name2String (varName bndr)))- (Text.pack "_selection")+mkSelection bndr scrut altTy alts0 tickDecls = do+ let dstId = either id id2identifier bndr+ tcm <- Lens.use tcCache+ let scrutTy = termType tcm scrut+ scrutHTy <- unsafeCoreTypeToHWTypeM' $(curLoc) scrutTy+ scrutId <- extendIdentifier Extended dstId "_selection" (_,sp) <- Lens.use curCompNm- (scrutExpr,scrutDecls) <- first (mkScrutExpr sp scrutHTy (fst (head alts'))) <$> mkExpr True (Left scrutId) scrutTy scrut- (exprs,altsDecls) <- (second concat . unzip) <$> mapM (mkCondExpr scrutHTy) alts'+ ite <- Lens.use backEndITE+ case iteAlts scrutHTy alts0 of+ Just (altT,altF)+ | ite+ -> do+ (scrutExpr,scrutDecls) <- case scrutHTy of+ SP {} -> first (mkScrutExpr sp scrutHTy (fst (last alts0))) <$>+ mkExpr True (Left scrutId) scrutTy scrut+ _ -> mkExpr False (Left scrutId) scrutTy scrut+ altTId <- extendIdentifier Extended dstId "_sel_alt_t"+ altFId <- extendIdentifier Extended dstId "_sel_alt_f"+ (altTExpr,altTDecls) <- mkExpr False (Left altTId) altTy altT+ (altFExpr,altFDecls) <- mkExpr False (Left altFId) altTy altF+ return $! scrutDecls ++ altTDecls ++ altFDecls ++ tickDecls +++ [Assignment dstId (IfThenElse scrutExpr altTExpr altFExpr)]+ _ -> do+ reprs <- Lens.use customReprs+ let alts1 = (reorderDefault . reorderCustom tcm reprs scrutTy) alts0+ altHTy <- unsafeCoreTypeToHWTypeM' $(curLoc) altTy+ (scrutExpr,scrutDecls) <- first (mkScrutExpr sp scrutHTy (fst (head alts1))) <$>+ mkExpr True (Left scrutId) scrutTy scrut+ (exprs,altsDecls) <- (second concat . unzip) <$> mapM (mkCondExpr scrutHTy) alts1+ return $! scrutDecls ++ altsDecls ++ tickDecls ++ [CondAssignment dstId altHTy scrutExpr scrutHTy exprs]+ where+ mkCondExpr :: HWType -> (Pat,Term) -> NetlistMonad ((Maybe HW.Literal,Expr),[Declaration])+ mkCondExpr scrutHTy (pat,alt) = do+ altId <- extendIdentifier Extended+ (either id id2identifier bndr)+ "_sel_alt"+ (altExpr,altDecls) <- mkExpr False (Left altId) altTy alt+ (,altDecls) <$> case pat of+ DefaultPat -> return (Nothing,altExpr)+ DataPat dc _ _ -> return (Just (dcToLiteral scrutHTy (dcTag dc)),altExpr)+ LitPat (IntegerLiteral i) -> return (Just (NumLit i),altExpr)+ LitPat (IntLiteral i) -> return (Just (NumLit i), altExpr)+ LitPat (WordLiteral w) -> return (Just (NumLit w), altExpr)+ LitPat (CharLiteral c) -> return (Just (NumLit . toInteger $ ord c), altExpr)+ LitPat (Int64Literal i) -> return (Just (NumLit i), altExpr)+ LitPat (Word64Literal w) -> return (Just (NumLit w), altExpr)+ LitPat (NaturalLiteral n) -> return (Just (NumLit n), altExpr)+ _ -> do+ (_,sp) <- Lens.use curCompNm+ throw (ClashException sp ($(curLoc) ++ "Not an integer literal in LitPat:\n\n" ++ showPpr pat) Nothing) - let dstId = Text.pack . name2String $ varName bndr- return $! scrutDecls ++ altsDecls ++ [CondAssignment dstId altHTy scrutExpr scrutHTy exprs]- where- mkCondExpr :: HWType -> (Pat,Term) -> NetlistMonad ((Maybe HW.Literal,Expr),[Declaration])- mkCondExpr scrutHTy (pat,alt) = do- altId <- extendIdentifier Extended- (Text.pack (name2String (varName bndr)))- (Text.pack "_sel_alt")- (altExpr,altDecls) <- mkExpr False (Left altId) altTy alt- (,altDecls) <$> case pat of- DefaultPat -> return (Nothing,altExpr)- DataPat (Embed dc) _ -> return (Just (dcToLiteral scrutHTy (dcTag dc)),altExpr)- LitPat (Embed (IntegerLiteral i)) -> return (Just (NumLit i),altExpr)- LitPat (Embed (IntLiteral i)) -> return (Just (NumLit i), altExpr)- LitPat (Embed (WordLiteral w)) -> return (Just (NumLit w), altExpr)- LitPat (Embed (CharLiteral c)) -> return (Just (NumLit . toInteger $ ord c), altExpr)- LitPat (Embed (Int64Literal i)) -> return (Just (NumLit i), altExpr)- LitPat (Embed (Word64Literal w)) -> return (Just (NumLit w), altExpr)- LitPat (Embed (NaturalLiteral n)) -> return (Just (NumLit n), altExpr)- _ -> do- (_,sp) <- Lens.use curCompNm- throw (ClashException sp ($(curLoc) ++ "Not an integer literal in LitPat:\n\n" ++ showDoc pat) Nothing)+ mkScrutExpr :: SrcSpan -> HWType -> Pat -> Expr -> Expr+ mkScrutExpr sp scrutHTy pat scrutE = case pat of+ DataPat dc _ _ -> let modifier = Just (DC (scrutHTy,dcTag dc - 1))+ in case scrutE of+ Identifier scrutId Nothing -> Identifier scrutId modifier+ _ -> throw (ClashException sp ($(curLoc) ++ "Not in normal form: Not a variable reference or primitive as subject of a case-statement:\n\n" ++ show scrutE) Nothing)+ _ -> scrutE - mkScrutExpr :: SrcSpan -> HWType -> Pat -> Expr -> Expr- mkScrutExpr sp scrutHTy pat scrutE = case pat of- DataPat (Embed dc) _ -> let modifier = Just (DC (scrutHTy,dcTag dc - 1))- in case scrutE of- Identifier scrutId Nothing -> Identifier scrutId modifier- _ -> throw (ClashException sp ($(curLoc) ++ "Not in normal form: Not a variable reference or primitive as subject of a case-statement:\n\n" ++ show scrutE) Nothing)- _ -> scrutE+-- GHC puts default patterns in the first position, we want them in the+-- last position.+reorderDefault+ :: [(Pat, Term)]+ -> [(Pat, Term)]+reorderDefault ((DefaultPat,e):alts') = alts' ++ [(DefaultPat,e)]+reorderDefault alts' = alts' - -- GHC puts default patterns in the first position, we want them in the- -- last position.- reorderPats :: [(Pat,Term)] -> [(Pat,Term)]- reorderPats ((DefaultPat,e):alts') = alts' ++ [(DefaultPat,e)]- reorderPats alts' = alts'+reorderCustom+ :: TyConMap+ -> CustomReprs+ -> Type+ -> [(Pat, Term)]+ -> [(Pat, Term)]+reorderCustom tcm reprs (coreView1 tcm -> Just ty) alts =+ reorderCustom tcm reprs ty alts+reorderCustom _tcm reprs (coreToType' -> Right typeName) alts =+ case getDataRepr typeName reprs of+ Just (DataRepr' _name _size _constrReprs) ->+ sortOn (patPos reprs . fst) alts+ Nothing ->+ alts+reorderCustom _tcm _reprs _type alts =+ alts +patPos+ :: CustomReprs+ -> Pat+ -> Int+patPos _reprs DefaultPat = -1+patPos _reprs (LitPat _) = 0+patPos reprs pat@(DataPat dataCon _ _) =+ -- We sort data patterns by their syntactical order+ let name = nameOcc $ dcName dataCon in+ case getConstrRepr name reprs of+ Nothing ->+ -- TODO: err+ error $ $(curLoc) ++ (show pat)+ Just (ConstrRepr' _name n _mask _value _anns) ->+ n++ -- | Generate a list of Declarations for a let-binder where the RHS is a function application mkFunApp- :: Id -- ^ LHS of the let-binder- -> TmName -- ^ Name of the applied function+ :: HasCallStack+ => Identifier -- ^ LHS of the let-binder+ -> Id -- ^ Name of the applied function -> [Term] -- ^ Function arguments+ -> [Declaration] -- ^ Tick declarations -> NetlistMonad [Declaration]-mkFunApp dst fun args = do+mkFunApp dstId fun args tickDecls = do topAnns <- Lens.use topEntityAnns tcm <- Lens.use tcCache- case HashMap.lookup (nameOcc fun) topAnns of+ case lookupVarEnv fun topAnns of Just (ty,annM) | let (fArgTys,fResTy) = splitFunTys tcm ty , length fArgTys == length args -> do- let dstId = Text.pack . name2String $ varName dst- argHWTys <- mapM (unsafeCoreTypeToHWTypeM $(curLoc)) fArgTys+ argHWTys <- mapM (unsafeCoreTypeToHWTypeM' $(curLoc)) fArgTys -- Filter out the arguments of hwtype `Void` and only translate them -- to the intermediate HDL afterwards let argsBundled = zip argHWTys (zip args fArgTys)@@ -367,71 +516,80 @@ (argExprs,argDecls) <- second concat . unzip <$> mapM (\(e,t) -> mkExpr False (Left dstId) t e) argsFiltered'- dstHWty <- unsafeCoreTypeToHWTypeM $(curLoc) fResTy+ dstHWty <- unsafeCoreTypeToHWTypeM' $(curLoc) fResTy env <- Lens.use hdlDir+ mkId <- Lens.use mkIdentifierFn+ prefixM <- Lens.use componentPrefix+ newInlineStrat <- opt_newInlineStrat <$> Lens.use clashOpts+ let topName = StrictText.unpack+ (genTopComponentName newInlineStrat mkId prefixM annM fun)+ modName = takeWhile (/= '.')+ (StrictText.unpack (nameOcc (varName fun))) manFile <- case annM of- Just ann -> return (env </> t_name ann </> t_name ann <.> "manifest")- Nothing -> do- mkId <- Lens.use mkIdentifierFn- let topName = genComponentName [] mkId fun- return (env </> (Text.unpack topName) <.> "manifest")+ Just _ -> return (env </> ".." </> modName </> topName </> topName <.> "manifest")+ Nothing -> return (env </> topName <.> "manifest") Just man <- readMaybe <$> liftIO (readFile manFile) instDecls <- mkTopUnWrapper fun annM man (dstId,dstHWty) (zip argExprs hWTysFiltered)+ tickDecls return (argDecls ++ instDecls) | otherwise -> error $ $(curLoc) ++ "under-applied TopEntity" _ -> do normalized <- Lens.use bindings- case HashMap.lookup (nameOcc fun) normalized of+ case lookupVarEnv fun normalized of Just _ -> do- (_,Component compName compInps [snd -> compOutp] _) <- preserveVarEnv $ genComponent (nameOcc fun)- if length args == length compInps+ (_,_,_,Component compName compInps co _) <- preserveVarEnv $ genComponent fun+ let argTys = map (termType tcm) args+ argHWTys <- mapM coreTypeToHWTypeM' argTys+ -- Filter out the arguments of hwtype `Void` and only translate+ -- them to the intermediate HDL afterwards+ let argsBundled = zip argHWTys (zip args argTys)+ argsFiltered = filter (maybe True (not . isVoid) . fst) argsBundled+ argsFiltered' = map snd argsFiltered+ tysFiltered = map snd argsFiltered'+ compOutp = snd <$> listToMaybe co+ if length tysFiltered == length compInps then do- argTys <- mapM (termType tcm) args- argHWTys <- mapM coreTypeToHWTypeM argTys- -- Filter out the arguments of hwtype `Void` and only translate- -- them to the intermediate HDL afterwards- let argsBundled = zip argHWTys (zip args argTys)- argsFiltered = filter (maybe True (not . isVoid) . fst) argsBundled- argsFiltered' = map snd argsFiltered- tysFiltered = map snd argsFiltered'- let dstId = Text.pack . name2String $ varName dst (argExprs,argDecls) <- fmap (second concat . unzip) $! mapM (\(e,t) -> mkExpr False (Left dstId) t e) argsFiltered'- (argExprs',argDecls') <- (second concat . unzip) <$> mapM (toSimpleVar dst) (zip argExprs tysFiltered)+ (argExprs',argDecls') <- (second concat . unzip) <$> mapM (toSimpleVar dstId) (zip argExprs tysFiltered) let inpAssigns = zipWith (\(i,t) e -> (Identifier i Nothing,In,t,e)) compInps argExprs'- outpAssign = (Identifier (fst compOutp) Nothing,Out,snd compOutp,Identifier dstId Nothing)- instLabel <- extendIdentifier Basic compName (Text.pack "_" `Text.append` dstId)- let instDecl = InstDecl Nothing compName instLabel (outpAssign:inpAssigns)- return (argDecls ++ argDecls' ++ [instDecl])+ outpAssign = case compOutp of+ Nothing -> []+ Just (id_,hwtype) -> [(Identifier id_ Nothing,Out,hwtype,Identifier dstId Nothing)]+ instLabel0 <- extendIdentifier Basic compName (StrictText.pack "_" `StrictText.append` dstId)+ instLabel1 <- fromMaybe instLabel0 <$> Lens.view setName+ instLabel2 <- affixName instLabel1+ instLabel3 <- mkUniqueIdentifier Basic instLabel2+ let instDecl = InstDecl Entity Nothing compName instLabel3 [] (outpAssign ++ inpAssigns)+ return (argDecls ++ argDecls' ++ tickDecls ++ [instDecl]) else error $ $(curLoc) ++ "under-applied normalized function" Nothing -> case args of- [] -> do- let dstId = Text.pack . name2String $ varName dst- return [Assignment dstId (Identifier (Text.pack $ name2String fun) Nothing)]- _ -> error $ $(curLoc) ++ "Unknown function: " ++ showDoc fun+ [] -> return [Assignment dstId (Identifier (nameOcc $ varName fun) Nothing)]+ _ -> error $ $(curLoc) ++ "Unknown function: " ++ showPpr fun -toSimpleVar :: Id+toSimpleVar :: Identifier -> (Expr,Type) -> NetlistMonad (Expr,[Declaration]) toSimpleVar _ (e@(Identifier _ _),_) = return (e,[])-toSimpleVar dst (e,ty) = do+toSimpleVar dstId (e,ty) = do argNm <- extendIdentifier Extended- (Text.pack (name2String (varName dst)))- (Text.pack "_fun_arg")+ dstId+ "_fun_arg" argNm' <- mkUniqueIdentifier Extended argNm- hTy <- unsafeCoreTypeToHWTypeM $(curLoc) ty- let argDecl = NetDecl Nothing argNm' hTy- argAssn = Assignment argNm' e+ hTy <- unsafeCoreTypeToHWTypeM' $(curLoc) ty+ let argDecl = NetDecl Nothing argNm' hTy+ argAssn = Assignment argNm' e return (Identifier argNm' Nothing,[argDecl,argAssn]) -- | Generate an expression for a term occurring on the RHS of a let-binder-mkExpr :: Bool -- ^ Treat BlackBox expression as declaration+mkExpr :: HasCallStack+ => Bool -- ^ Treat BlackBox expression as declaration -> (Either Identifier Id) -- ^ Id to assign the result to -> Type -- ^ Type of the LHS of the let-binder -> Term -- ^ Term to convert to an expression -> NetlistMonad (Expr,[Declaration]) -- ^ Returned expression and a list of generate BlackBox declarations-mkExpr _ _ _ (Core.Literal l) = do+mkExpr _ _ _ (stripTicks -> Core.Literal l) = do iw <- Lens.use intWidth case l of IntegerLiteral i -> return (HW.Literal (Just (Signed iw,iw)) $ NumLit i, [])@@ -450,20 +608,45 @@ ByteArrayLiteral (PV.Vector _ _ (ByteArray ba)) -> return (HW.Literal Nothing (NumLit (Jp# (BN# ba))),[]) _ -> error $ $(curLoc) ++ "not an integer or char literal" -mkExpr bbEasD bndr ty app = do- let (appF,args) = collectArgs app- tmArgs = lefts args- hwTy <- unsafeCoreTypeToHWTypeM $(curLoc) ty+mkExpr bbEasD bndr ty app =+ let (appF,args,ticks) = collectArgsTicks app+ (tmArgs,tyArgs) = partitionEithers args+ in withTicks ticks $ \tickDecls -> do+ hwTy <- unsafeCoreTypeToHWTypeM' $(curLoc) ty (_,sp) <- Lens.use curCompNm case appF of Data dc -> mkDcApplication hwTy bndr dc tmArgs- Prim nm _ -> mkPrimitive False bbEasD bndr nm args ty- Var _ f- | null tmArgs -> return (Identifier (Text.pack $ name2String f) Nothing,[])- | otherwise ->- throw (ClashException sp ($(curLoc) ++ "Not in normal form: top-level binder in argument position:\n\n" ++ showDoc app) Nothing)+ Prim nm _ -> mkPrimitive False bbEasD bndr nm args ty tickDecls+ Var f+ | null tmArgs -> return (Identifier (nameOcc $ varName f) Nothing,[])+ | not (null tyArgs) ->+ throw (ClashException sp ($(curLoc) ++ "Not in normal form: Var-application with Type arguments:\n\n" ++ showPpr app) Nothing)+ | otherwise -> do+ argNm0 <- extendIdentifier Extended (either id id2identifier bndr) "_fun_arg"+ argNm1 <- mkUniqueIdentifier Extended argNm0+ hwTyA <- unsafeCoreTypeToHWTypeM' $(curLoc) ty+ decls <- mkFunApp argNm1 f tmArgs tickDecls+ return (Identifier argNm1 Nothing, NetDecl' Nothing Wire argNm1 (Right hwTyA):decls) Case scrut ty' [alt] -> mkProjection bbEasD bndr scrut ty' alt- _ -> throw (ClashException sp ($(curLoc) ++ "Not in normal form: application of a Let/Lam/Case:\n\n" ++ showDoc app) Nothing)+ Case scrut tyA alts -> do+ tcm <- Lens.use tcCache+ let scrutTy = termType tcm scrut+ scrutHTy <- unsafeCoreTypeToHWTypeM' $(curLoc) scrutTy+ ite <- Lens.use backEndITE+ let wr = case iteAlts scrutHTy alts of+ Just _ | ite -> Wire+ _ -> Reg+ argNm0 <- extendIdentifier Extended (either id id2identifier bndr) "_sel_arg"+ argNm1 <- mkUniqueIdentifier Extended argNm0+ hwTyA <- unsafeCoreTypeToHWTypeM' $(curLoc) tyA+ decls <- mkSelection (Left argNm1) scrut tyA alts tickDecls+ return (Identifier argNm1 Nothing, NetDecl' Nothing wr argNm1 (Right hwTyA):decls)+ Letrec binders body -> do+ netDecls <- fmap catMaybes $ mapM mkNetDecl binders+ decls <- concat <$> mapM (uncurry mkDeclarations) binders+ (bodyE,bodyDecls) <- mkExpr bbEasD bndr ty (mkApps (mkTicks body ticks) args)+ return (bodyE,netDecls ++ decls ++ bodyDecls)+ _ -> throw (ClashException sp ($(curLoc) ++ "Not in normal form: application of a Lambda-expression\n\n" ++ showPpr app) Nothing) -- | Generate an expression that projects a field out of a data-constructor. --@@ -480,24 +663,23 @@ -> Alt -- ^ The field to be projected -> NetlistMonad (Expr, [Declaration])-mkProjection mkDec bndr scrut altTy alt = do+mkProjection mkDec bndr scrut altTy alt@(pat,v) = do tcm <- Lens.use tcCache- scrutTy <- termType tcm scrut- let e = Case scrut scrutTy [alt]- (pat,v) <- unbind alt+ let scrutTy = termType tcm scrut+ e = Case scrut scrutTy [alt] (_,sp) <- Lens.use curCompNm varTm <- case v of- (Var _ n) -> return n+ (Var n) -> return n _ -> throw (ClashException sp ($(curLoc) ++ "Not in normal form: RHS of case-projection is not a variable:\n\n"- ++ showDoc e) Nothing)- sHwTy <- unsafeCoreTypeToHWTypeM $(curLoc) scrutTy- vHwTy <- unsafeCoreTypeToHWTypeM $(curLoc) altTy+ ++ showPpr e) Nothing)+ sHwTy <- unsafeCoreTypeToHWTypeM' $(curLoc) scrutTy+ vHwTy <- unsafeCoreTypeToHWTypeM' $(curLoc) altTy (selId,modM,decls) <- do scrutNm <- either return (\b -> extendIdentifier Extended- (Text.pack (name2String (varName b)))- (Text.pack ("_projection")))+ (id2identifier b)+ "_projection") bndr (scrutExpr,newDecls) <- mkExpr False (Left scrutNm) scrutTy scrut case scrutExpr of@@ -508,28 +690,24 @@ scrutAssn = Assignment scrutNm' scrutExpr return (scrutNm',Nothing,newDecls ++ [scrutDecl,scrutAssn]) - let altVarId = Text.pack $ name2String varTm+ let altVarId = nameOcc (varName varTm) modifier <- case pat of- DataPat (Embed dc) ids -> do- let (exts,tms) = unrebind ids- tmsTys = map (unembed . varType) tms- tmsFVs = concatMap (Lens.toListOf typeFreeVars) tmsTys- extNms = map (nameOcc.varName) exts- tms' = if any (`elem` tmsFVs) extNms- then throw (ClashException sp ($(curLoc) ++ "Not in normal form: Pattern binds existential variables:\n\n" ++ showDoc e) Nothing)- else tms- argHWTys <- mapM coreTypeToHWTypeM tmsTys+ DataPat dc exts tms -> do+ let tms' = if bindsExistentials exts tms+ then throw (ClashException sp ($(curLoc) ++ "Not in normal form: Pattern binds existential variables:\n\n" ++ showPpr e) Nothing)+ else tms+ argHWTys <- mapM coreTypeToHWTypeM' (map varType tms) let tmsBundled = zip argHWTys tms' tmsFiltered = filter (maybe False (not . isVoid) . fst) tmsBundled tmsFiltered' = map snd tmsFiltered- case elemIndex (Id varTm (Embed altTy)) tmsFiltered' of+ case elemIndex varTm {varType = altTy} tmsFiltered' of Nothing -> pure Nothing Just fI | sHwTy /= vHwTy -> pure $ nestModifier modM (Just (Indexed (sHwTy,dcTag dc - 1,fI))) -- When element and subject have the same HW-type, -- then the projections is just the identity | otherwise -> pure $ nestModifier modM (Just (DC (Void Nothing,0)))- _ -> throw (ClashException sp ($(curLoc) ++ "Not in normal form: Unexpected pattern in case-projection:\n\n" ++ showDoc e) Nothing)+ _ -> throw (ClashException sp ($(curLoc) ++ "Not in normal form: Unexpected pattern in case-projection:\n\n" ++ showPpr e) Nothing) let extractExpr = Identifier (maybe altVarId (const selId) modifier) modifier case bndr of Left scrutNm | mkDec -> do@@ -545,24 +723,30 @@ -- | Generate an expression for a DataCon application occurring on the RHS of a let-binder-mkDcApplication :: HWType -- ^ HWType of the LHS of the let-binder- -> (Either Identifier Id) -- ^ Id to assign the result to- -> DataCon -- ^ Applied DataCon- -> [Term] -- ^ DataCon Arguments- -> NetlistMonad (Expr,[Declaration]) -- ^ Returned expression and a list of generate BlackBox declarations+mkDcApplication+ :: HasCallStack+ => HWType+ -- ^ HWType of the LHS of the let-binder+ -> (Either Identifier Id)+ -- ^ Id to assign the result to+ -> DataCon+ -- ^ Applied DataCon+ -> [Term]+ -- ^ DataCon Arguments+ -> NetlistMonad (Expr,[Declaration])+ -- ^ Returned expression and a list of generate BlackBox declarations mkDcApplication dstHType bndr dc args = do- let dcNm = name2String (dcName dc)+ let dcNm = nameOcc (dcName dc) tcm <- Lens.use tcCache- argTys <- mapM (termType tcm) args- argNm <- either return (\b -> extendIdentifier Extended (Text.pack (name2String (varName b))) (Text.pack "_dc_arg")) bndr- argHWTys <- mapM coreTypeToHWTypeM argTys+ let argTys = map (termType tcm) args+ argNm <- either return (\b -> extendIdentifier Extended (nameOcc (varName b)) "_dc_arg") bndr+ argHWTys <- mapM coreTypeToHWTypeM' argTys -- Filter out the arguments of hwtype `Void` and only translate -- them to the intermediate HDL afterwards let argsBundled = zip argHWTys (zip args argTys)- argsFiltered = filter (maybe True (not . isVoid) . fst) argsBundled- argsFiltered' = map snd argsFiltered- hWTysFiltered = filter (maybe True (not . isVoid)) argHWTys- (argExprs,argDecls) <- fmap (second concat . unzip) $! mapM (\(e,t) -> mkExpr False (Left argNm) t e) argsFiltered'+ (hWTysFiltered,argsFiltered) = unzip+ (filter (maybe True (not . isVoid) . fst) argsBundled)+ (argExprs,argDecls) <- fmap (second concat . unzip) $! mapM (\(e,t) -> mkExpr False (Left argNm) t e) argsFiltered fmap (,argDecls) $! case (hWTysFiltered,argExprs) of -- Is the DC just a newtype wrapper? ([Just argHwTy],[argExpr]) | argHwTy == dstHType ->@@ -575,38 +759,52 @@ EQ -> return (HW.DataCon dstHType (DC (dstHType,dcI)) argExprs) LT -> error $ $(curLoc) ++ "Over-applied constructor" GT -> error $ $(curLoc) ++ "Under-applied constructor"- Product _ dcArgs ->+ Product _ _ dcArgs -> case compare (length dcArgs) (length argExprs) of EQ -> return (HW.DataCon dstHType (DC (dstHType,0)) argExprs) LT -> error $ $(curLoc) ++ "Over-applied constructor" GT -> error $ $(curLoc) ++ "Under-applied constructor" Sum _ _ -> return (HW.DataCon dstHType (DC (dstHType,dcTag dc - 1)) [])+ CustomSP _ _ _ dcArgsTups -> do+ -- Safely get item from list, or err with note+ let dcI = dcTag dc - 1+ let note = $(curLoc) ++ "No DC with tag: " ++ show dcI+ let argTup = indexNote note dcArgsTups dcI+ let (_, _, dcArgs) = argTup++ case compare (length dcArgs) (length argExprs) of+ EQ -> return (HW.DataCon dstHType (DC (dstHType, dcI)) argExprs)+ LT -> error $ $(curLoc) ++ "Over-applied constructor"+ GT -> error $ $(curLoc) ++ "Under-applied constructor"++ CustomSum _ _ _ _ ->+ return (HW.DataCon dstHType (DC (dstHType, dcTag dc - 1)) []) Bool -> let dc' = case dcTag dc of 1 -> HW.Literal Nothing (BoolLit False) 2 -> HW.Literal Nothing (BoolLit True)- tg -> error $ $(curLoc) ++ "unknown bool literal: " ++ showDoc dc ++ "(tag: " ++ show tg ++ ")"+ tg -> error $ $(curLoc) ++ "unknown bool literal: " ++ showPpr dc ++ "(tag: " ++ show tg ++ ")" in return dc' Vector 0 _ -> return (HW.DataCon dstHType VecAppend []) Vector 1 _ -> case argExprs of [e] -> return (HW.DataCon dstHType VecAppend [e])- _ -> error $ $(curLoc) ++ "Unexpected number of arguments for `Cons`: " ++ showDoc args+ _ -> error $ $(curLoc) ++ "Unexpected number of arguments for `Cons`: " ++ showPpr args Vector _ _ -> case argExprs of [e1,e2] -> return (HW.DataCon dstHType VecAppend [e1,e2])- _ -> error $ $(curLoc) ++ "Unexpected number of arguments for `Cons`: " ++ showDoc args+ _ -> error $ $(curLoc) ++ "Unexpected number of arguments for `Cons`: " ++ showPpr args RTree 0 _ -> case argExprs of [e] -> return (HW.DataCon dstHType RTreeAppend [e])- _ -> error $ $(curLoc) ++ "Unexpected number of arguments for `LR`: " ++ showDoc args+ _ -> error $ $(curLoc) ++ "Unexpected number of arguments for `LR`: " ++ showPpr args RTree _ _ -> case argExprs of [e1,e2] -> return (HW.DataCon dstHType RTreeAppend [e1,e2])- _ -> error $ $(curLoc) ++ "Unexpected number of arguments for `BR`: " ++ showDoc args+ _ -> error $ $(curLoc) ++ "Unexpected number of arguments for `BR`: " ++ showPpr args String -> let dc' = case dcTag dc of 1 -> HW.Literal Nothing (StringLit "") _ -> error $ $(curLoc) ++ "mkDcApplication undefined for: " ++ show (dstHType,dc,dcTag dc,args,argHWTys) in return dc'- Void {} -> return (Identifier (Text.pack "__VOID__") Nothing)+ Void {} -> return (Identifier "__VOID__" Nothing) Signed _ | dcNm == "GHC.Integer.Type.S#" -> pure (head argExprs)@@ -620,4 +818,17 @@ -> pure (head argExprs) | dcNm == "GHC.Natural.NatJ#" -> pure (head argExprs)- _ -> error $ $(curLoc) ++ "mkDcApplication undefined for: " ++ show (dstHType,dc,args,argHWTys)+-- KnownDomain {} ->+-- return (Identifier "__KNOWNDOMAIN__" Nothing)+-- pure $+-- error $ $(curLoc) ++ "mkDcApplication undefined for KnownDomain. "+-- ++ "Did a blackbox definition try to render it? "+-- ++ "Context: \n\n"+-- ++ "dstHType: " ++ show dstHType ++ "\n\n"+-- ++ "dc: " ++ show dc ++ "\n\n"+-- ++ "args: " ++ show args ++ "\n\n"+-- ++ "argHWTys: " ++ show argHWTys ++ "\n\n"+-- ++ "Callstack: "+-- ++ prettyCallStack callStack+ _ ->+ error $ $(curLoc) ++ "mkDcApplication undefined for: " ++ show (dstHType,dc,args,argHWTys)
src/Clash/Netlist.hs-boot view
@@ -12,26 +12,33 @@ ,mkNetDecl ,mkProjection ,mkSelection+ ,mkFunApp ) where +import Data.HashMap.Strict (HashMap) import Clash.Core.DataCon (DataCon)-import Clash.Core.Term (Alt,LetBinding,Term,TmOccName)+import Clash.Core.Term (Alt,LetBinding,Term) import Clash.Core.Type (Type) import Clash.Core.Var (Id)-import Clash.Driver.Types (SrcSpan) import Clash.Netlist.Types (Expr, HWType, Identifier, NetlistMonad, Component, Declaration)+import SrcLoc (SrcSpan) -genComponent :: TmOccName- -> NetlistMonad (SrcSpan,Component)+import GHC.Stack (HasCallStack) -mkExpr :: Bool+genComponent :: HasCallStack+ => Id+ -> NetlistMonad ([Bool],SrcSpan,HashMap Identifier Word,Component)++mkExpr :: HasCallStack+ => Bool -> Either Identifier Id -> Type -> Term -> NetlistMonad (Expr,[Declaration]) -mkDcApplication :: HWType+mkDcApplication :: HasCallStack+ => HWType -> Either Identifier Id -> DataCon -> [Term]@@ -46,12 +53,21 @@ -> NetlistMonad (Expr, [Declaration]) mkSelection- :: Id+ :: Either Identifier Id -> Term -> Type -> [Alt]+ -> [Declaration] -> NetlistMonad [Declaration] mkNetDecl :: LetBinding -> NetlistMonad (Maybe Declaration) -mkDeclarations :: Id -> Term -> NetlistMonad [Declaration]+mkDeclarations :: HasCallStack => Id -> Term -> NetlistMonad [Declaration]++mkFunApp+ :: HasCallStack+ => Identifier -- ^ LHS of the let-binder+ -> Id -- ^ Name of the applied function+ -> [Term] -- ^ Function arguments+ -> [Declaration] -- ^ Tick declarations+ -> NetlistMonad [Declaration]
src/Clash/Netlist/BlackBox.hs view
@@ -8,6 +8,7 @@ Functions to create BlackBox Contexts and fill in BlackBox templates -} +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TemplateHaskell #-}@@ -17,129 +18,197 @@ module Clash.Netlist.BlackBox where import Control.Exception (throw)-import Control.Lens ((.=),(<<%=))+import Control.Lens ((<<%=),(%=)) import qualified Control.Lens as Lens+import Control.Monad (when)+import Control.Monad.IO.Class (liftIO) import Data.Char (ord)-import Data.Either (lefts)+import Data.Either (lefts, partitionEithers) import qualified Data.HashMap.Lazy as HashMap import qualified Data.IntMap as IntMap-import Data.Maybe (catMaybes)+import Data.List (elemIndex)+import Data.Maybe (catMaybes, fromJust) import Data.Semigroup.Monad-import Data.Text.Lazy (fromStrict, pack)+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 Unbound.Generics.LocallyNameless (embed, unbind, unembed)+import qualified System.Console.ANSI as ANSI+import System.Console.ANSI+ ( hSetSGR, SGR(SetConsoleIntensity, SetColor), Color(Magenta)+ , ConsoleIntensity(BoldIntensity), ConsoleLayer(Foreground), ColorIntensity(Vivid))+import System.IO+ (hPutStrLn, stderr, hFlush, hIsTerminalDevice)+import TextShow (showt)+import Util (OverridingBool(..)) --- import Clash.Backend as N+import Clash.Annotations.Primitive+ (PrimitiveGuard(HasBlackBox, WarnNonSynthesizable, WarnAlways, DontTranslate)) import Clash.Core.DataCon as D (dcTag)+import Clash.Core.FreeVars (freeIds) import Clash.Core.Literal as L (Literal (..)) import Clash.Core.Name- (Name (..), NameSort (..), name2String, string2SystemName)-import Clash.Core.Pretty (showDoc)-import Clash.Core.Subst (substTm)-import Clash.Core.Term as C (Term (..))+ (Name (..), mkUnsafeSystemName)+import Clash.Core.Pretty (showPpr)+import Clash.Core.Subst (extendIdSubst, mkSubst, substTm)+import Clash.Core.Term as C+ (Term (..), collectArgs, collectArgsTicks) import Clash.Core.Type as C (Type (..), ConstTy (..),- splitFunTys)+ splitFunTys, splitFunTy) import Clash.Core.TyCon as C (tyConDataCons)-import Clash.Core.Util (collectArgs, isFun, termType)-import Clash.Core.Var as V (Id, Var (..))-import Clash.Driver.Types (ClashException (..))+import Clash.Core.Util (isFun, termType)+import Clash.Core.Var as V+ (Id, Var (..), mkLocalId, modifyVarName)+import Clash.Core.VarEnv+ (extendInScopeSet, mkInScopeSet, lookupVarEnv, uniqAway, unitVarSet) import {-# SOURCE #-} Clash.Netlist (genComponent, mkDcApplication, mkDeclarations, mkExpr, mkNetDecl,- mkProjection, mkSelection)+ mkProjection, mkSelection, mkFunApp)+import qualified Clash.Backend as Backend+import Clash.Driver.Types+ (opt_primWarn, opt_color, ClashOpts) import Clash.Netlist.BlackBox.Types as B import Clash.Netlist.BlackBox.Util as B import Clash.Netlist.Id (IdType (..)) import Clash.Netlist.Types as N import Clash.Netlist.Util as N-import Clash.Normalize.Util (isConstant) import Clash.Primitives.Types as P+import Clash.Unique (lookupUniqMap') import Clash.Util +-- | Emits (colorized) warning to stderr+warn+ :: ClashOpts+ -> String+ -> IO ()+warn opts msg = do+ -- TODO: Put in appropriate module+ useColor <-+ case opt_color opts of+ Always -> return True+ Never -> return False+ 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+ -- | Generate the context for a BlackBox instantiation.-mkBlackBoxContext :: Id -- ^ Identifier binding the primitive/blackbox application- -> [Term] -- ^ Arguments of the primitive/blackbox application- -> NetlistMonad (BlackBoxContext,[Declaration])-mkBlackBoxContext resId args = do+mkBlackBoxContext+ :: TextS.Text+ -- ^ Blackbox function name+ -> Id+ -- ^ Identifier binding the primitive/blackbox application+ -> [Term]+ -- ^ Arguments of the primitive/blackbox application+ -> NetlistMonad (BlackBoxContext,[Declaration])+mkBlackBoxContext bbName resId args = do -- Make context inputs tcm <- Lens.use tcCache- let resNm = Text.pack . name2String $ varName resId+ let resNm = nameOcc (varName resId) (imps,impDecls) <- unzip <$> mapM (mkArgument resNm) args (funs,funDecls) <- mapAccumLM (addFunction tcm) IntMap.empty (zip args [0..]) -- Make context result let res = Identifier resNm Nothing- resTy <- unsafeCoreTypeToHWTypeM $(curLoc) (unembed $ V.varType resId)+ resTy <- unsafeCoreTypeToHWTypeM' $(curLoc) (V.varType resId) lvl <- Lens.use curBBlvl+ (nm,_) <- Lens.use curCompNm - return ( Context (res,resTy) imps funs Nothing lvl+ return ( Context bbName (res,resTy) imps funs [] lvl nm , concat impDecls ++ concat funDecls ) where- addFunction tcm im (arg,i) = do- isF <- isFun tcm arg- if isF- then do curBBlvl Lens.+= 1- (f,d) <- mkFunInput resId arg- curBBlvl Lens.-= 1- let im' = IntMap.insert i f im- return (im',d)- else return (im,[])+ addFunction tcm im (arg,i) = if isFun tcm arg+ then do curBBlvl Lens.+= 1+ (f,d) <- mkFunInput resId arg+ curBBlvl Lens.-= 1+ let im' = IntMap.insert i f im+ return (im',d)+ else return (im,[]) -prepareBlackBox :: TextS.Text- -> BlackBoxTemplate- -> BlackBoxContext- -> NetlistMonad (BlackBoxTemplate,[Declaration])+prepareBlackBox+ :: TextS.Text+ -> BlackBox+ -> BlackBoxContext+ -> NetlistMonad (BlackBox,[Declaration]) prepareBlackBox pNm templ bbCtx = if verifyBlackBoxContext bbCtx templ then do- t1 <- instantiateCompName templ- (t2,decls) <- setSym bbCtx t1- t3 <- collectFilePaths bbCtx t2- return (t3,decls)+ (t2,decls) <-+ onBlackBox+ (fmap (first BBTemplate) . setSym mkUniqueIdentifier bbCtx)+ (\bbName bbHash bbFunc -> pure (BBFunction bbName bbHash bbFunc, []))+ templ+ return (t2,decls) else do (_,sp) <- Lens.use curCompNm- templ' <- getMon (prettyBlackBox templ)+ templ' <- onBlackBox (getMon . prettyBlackBox)+ (\n h f -> return $ Text.pack $ show (BBFunction n h f))+ templ let msg = $(curLoc) ++ "Can't match template for " ++ show pNm ++ " :\n\n" ++ Text.unpack templ' ++ "\n\nwith context:\n\n" ++ show bbCtx throw (ClashException sp msg Nothing) -mkArgument :: Identifier -- ^ LHS of the original let-binder- -> Term- -> NetlistMonad ( (Expr,HWType,Bool)- , [Declaration]- )+-- | Determine if a term represents a literal+isLiteral :: Term -> Bool+isLiteral e = case collectArgs e of+ (Data _, args) -> all (either isLiteral (const True)) args+ (Prim _ _, args) -> all (either isLiteral (const True)) args+ (C.Literal _,_) -> True+ _ -> False++mkArgument+ :: Identifier+ -- ^ LHS of the original let-binder+ -> Term+ -> NetlistMonad ( (Expr,HWType,Bool)+ , [Declaration]+ ) mkArgument bndr e = do tcm <- Lens.use tcCache- ty <- termType tcm e+ let ty = termType tcm e iw <- Lens.use intWidth- hwTyM <- N.termHWTypeM e- let eTyMsg = "(" ++ showDoc e ++ " :: " ++ showDoc ty ++ ")"+ hwTyM <- fmap stripFiltered <$> N.termHWTypeM e+ let eTyMsg = "(" ++ showPpr e ++ " :: " ++ showPpr ty ++ ")" ((e',t,l),d) <- case hwTyM of- Nothing ->- return ((Identifier (error ($(curLoc) ++ "Forced to evaluate untranslatable type: " ++ eTyMsg)) Nothing- ,Void Nothing,False),[])- Just hwTy -> case collectArgs e of- (C.Var _ v,[]) -> return ((Identifier (pack (name2String v)) Nothing,hwTy,False),[])- (C.Literal (IntegerLiteral i),[]) -> return ((N.Literal (Just (Signed iw,iw)) (N.NumLit i),hwTy,True),[])- (C.Literal (IntLiteral i), []) -> return ((N.Literal (Just (Signed iw,iw)) (N.NumLit i),hwTy,True),[])- (C.Literal (WordLiteral w), []) -> return ((N.Literal (Just (Unsigned iw,iw)) (N.NumLit w),hwTy,True),[])- (C.Literal (CharLiteral c), []) -> return ((N.Literal (Just (Unsigned 21,21)) (N.NumLit . toInteger $ ord c),hwTy,True),[])- (C.Literal (StringLiteral s),[]) -> return ((N.Literal Nothing (N.StringLit s),hwTy,True),[])- (C.Literal (Int64Literal i), []) -> return ((N.Literal (Just (Signed 64,64)) (N.NumLit i),hwTy,True),[])- (C.Literal (Word64Literal i), []) -> return ((N.Literal (Just (Unsigned 64,64)) (N.NumLit i),hwTy,True),[])- (C.Literal (NaturalLiteral n), []) -> return ((N.Literal (Just (Unsigned iw,iw)) (N.NumLit n),hwTy,True),[])- (Prim f _,args) -> do- (e',d) <- mkPrimitive True False (Left bndr) f args ty+ Nothing+ | (Prim nm _,_) <- collectArgs e+ , nm == "Clash.Transformations.removedArg"+ -> return ((Identifier nm Nothing, Void Nothing, False),[])+ | otherwise+ -> return ((error ($(curLoc) ++ "Forced to evaluate untranslatable type: " ++ eTyMsg), Void Nothing, False), [])+ Just hwTy -> case collectArgsTicks e of+ (C.Var v,[],_) -> return ((Identifier (nameOcc (varName v)) Nothing,hwTy,False),[])+ (C.Literal (IntegerLiteral i),[],_) ->+ return ((N.Literal (Just (Signed iw,iw)) (N.NumLit i),hwTy,True),[])+ (C.Literal (IntLiteral i), [],_) ->+ return ((N.Literal (Just (Signed iw,iw)) (N.NumLit i),hwTy,True),[])+ (C.Literal (WordLiteral w), [],_) ->+ return ((N.Literal (Just (Unsigned iw,iw)) (N.NumLit w),hwTy,True),[])+ (C.Literal (CharLiteral c), [],_) ->+ return ((N.Literal (Just (Unsigned 21,21)) (N.NumLit . toInteger $ ord c),hwTy,True),[])+ (C.Literal (StringLiteral s),[],_) ->+ return ((N.Literal Nothing (N.StringLit s),hwTy,True),[])+ (C.Literal (Int64Literal i), [],_) ->+ return ((N.Literal (Just (Signed 64,64)) (N.NumLit i),hwTy,True),[])+ (C.Literal (Word64Literal i), [],_) ->+ return ((N.Literal (Just (Unsigned 64,64)) (N.NumLit i),hwTy,True),[])+ (C.Literal (NaturalLiteral n), [],_) ->+ return ((N.Literal (Just (Unsigned iw,iw)) (N.NumLit n),hwTy,True),[])+ (Prim f _,args,ticks) -> withTicks ticks $ \tickDecls -> do+ (e',d) <- mkPrimitive True False (Left bndr) f args ty tickDecls case e' of (Identifier _ _) -> return ((e',hwTy,False), d)- _ -> return ((e',hwTy,isConstant e), d)- (Data dc, args) -> do+ _ -> return ((e',hwTy,isLiteral e), d)+ (Data dc, args,_) -> do (exprN,dcDecls) <- mkDcApplication hwTy (Left bndr) dc (lefts args)- return ((exprN,hwTy,isConstant e),dcDecls)- (Case scrut ty' [alt],[]) -> do+ return ((exprN,hwTy,isLiteral e),dcDecls)+ (Case scrut ty' [alt],[],_) -> do (projection,decls) <- mkProjection False (Left bndr) scrut ty' alt return ((projection,hwTy,False),decls) _ ->@@ -147,98 +216,198 @@ ,hwTy,False),[]) return ((e',t,l),d) -mkPrimitive :: Bool -- ^ Put BlackBox expression in parenthesis- -> Bool -- ^ Treat BlackBox expression as declaration- -> (Either Identifier Id) -- ^ Id to assign the result to- -> TextS.Text- -> [Either Term Type]- -> Type- -> NetlistMonad (Expr,[Declaration])-mkPrimitive bbEParen bbEasD dst nm args ty = do- bbM <- HashMap.lookup nm <$> Lens.use primitives- case bbM of- Just p@(P.BlackBox {outputReg = wr}) -> do- case template p of- (Left tempD) -> do- let pNm = name p- wr' = if wr then Reg else Wire- resM <- resBndr True wr' dst- case resM of- Just (dst',dstNm,dstDecl) -> do- (bbCtx,ctxDcls) <- mkBlackBoxContext dst' (lefts args)- (templ,templDecl) <- prepareBlackBox pNm tempD bbCtx- let bbDecl = N.BlackBoxD pNm (library p) (imports p)- (include p) templ bbCtx- return (Identifier dstNm Nothing,dstDecl ++ ctxDcls ++ templDecl ++ [bbDecl])- Nothing -> return (Identifier "__VOID__" Nothing,[])- (Right tempE) -> do- let pNm = name p- if bbEasD- then do- resM <- resBndr True Wire dst+-- | Extract a compiled primitive from a guarded primitive. Emit a warning if+-- the guard wants to, or fail entirely.+extractPrimWarnOrFail+ :: TextS.Text+ -- ^ Name of primitive+ -> NetlistMonad CompiledPrimitive+extractPrimWarnOrFail nm = do+ prim <- HashMap.lookup nm <$> Lens.use primitives+ case prim of+ Just guardedPrim ->+ -- See if we need to warn the user, or error because we encountered+ -- a primitive the user explicitly requested not to translate+ go guardedPrim+ Nothing -> do+ -- Blackbox requested, but no blackbox found at all!+ (_,sp) <- Lens.use curCompNm+ let msg = $(curLoc) ++ "No blackbox found for: " ++ unpack nm+ ++ ". Did you forget to include directories containing "+ ++ "primitives? You can use '-i/my/prim/dir' to achieve this."+ throw (ClashException sp msg Nothing)+ where+ go+ :: GuardedCompiledPrimitive+ -> NetlistMonad CompiledPrimitive+ go (HasBlackBox cp) =+ return cp++ go DontTranslate = do+ (_,sp) <- Lens.use curCompNm+ let msg = $(curLoc) ++ "Clash was forced to translate '" ++ unpack nm+ ++ "', but this value was marked with DontTranslate. Did you forget"+ ++ " to include a blackbox for one of the constructs using this?"+ throw (ClashException sp msg Nothing)++ go (WarnAlways warning cp) = do+ primWarn <- opt_primWarn <$> Lens.use clashOpts+ seen <- Set.member nm <$> Lens.use seenPrimitives+ opts <- Lens.use clashOpts++ when (primWarn && not seen)+ $ liftIO+ $ warn opts+ $ "Dubious primitive instantiation for "+ ++ unpack nm+ ++ ": "+ ++ warning+ ++ " (disable with -fclash-no-prim-warn)"++ seenPrimitives %= Set.insert nm++ return cp++ go (WarnNonSynthesizable warning cp) = do+ isTB <- Lens.use isTestBench+ if isTB then return cp else go (WarnAlways warning cp)+++mkPrimitive+ :: Bool+ -- ^ Put BlackBox expression in parenthesis+ -> Bool+ -- ^ Treat BlackBox expression as declaration+ -> Either Identifier Id+ -- ^ Id to assign the result to+ -> TextS.Text+ -- ^ Name of primitive+ -> [Either Term Type]+ -- ^ Arguments+ -> Type+ -- ^ Result type+ -> [Declaration]+ -- ^ Tick declarations+ -> NetlistMonad (Expr,[Declaration])+mkPrimitive bbEParen bbEasD dst nm args ty tickDecls =+ go =<< extractPrimWarnOrFail nm+ where+ go+ :: CompiledPrimitive+ -> NetlistMonad (Expr, [Declaration])+ go =+ \case+ P.BlackBoxHaskell bbName wf funcName (_fHash, func) -> do+ bbFunRes <- func bbEasD nm args ty+ case bbFunRes of+ Left err -> do+ -- Blackbox template function returned an error:+ let err' = unwords [ $(curLoc) ++ "Could not create blackbox"+ , "template using", show funcName, "for"+ , show bbName ++ ".", "Function reported: \n\n"+ , err ]+ (_,sp) <- Lens.use curCompNm+ throw (ClashException sp err' Nothing)+ Right (BlackBoxMeta {..}, bbTemplate) ->+ -- Blackbox template generation succesful. Rerun 'go', but this time+ -- around with a 'normal' @BlackBox@+ go (P.BlackBox bbName wf bbKind () bbOutputReg bbLibrary bbImports bbIncludes bbTemplate)+ p@P.BlackBox {outputReg = wr} ->+ case kind p of+ TDecl -> do+ let tempD = template p+ pNm = name p+ wr' = if wr then Reg else Wire+ resM <- resBndr True wr' dst case resM of Just (dst',dstNm,dstDecl) -> do- (bbCtx,ctxDcls) <- mkBlackBoxContext dst' (lefts args)- (bbTempl,templDecl) <- prepareBlackBox pNm tempE bbCtx- let tmpAssgn = Assignment dstNm- (BlackBoxE pNm (library p) (imports p)- (include p) bbTempl bbCtx- bbEParen)- return (Identifier dstNm Nothing, dstDecl ++ ctxDcls ++ templDecl ++ [tmpAssgn])- Nothing -> return (Identifier "__VOID__" Nothing,[])- else do- resM <- resBndr False Wire dst- case resM of- Just (dst',_,_) -> do- (bbCtx,ctxDcls) <- mkBlackBoxContext dst' (lefts args)- (bbTempl,templDecl) <- prepareBlackBox pNm tempE bbCtx- return (BlackBoxE pNm (library p) (imports p) (include p) bbTempl bbCtx bbEParen,ctxDcls ++ templDecl)+ (bbCtx,ctxDcls) <- mkBlackBoxContext nm dst' (lefts args)+ (templ,templDecl) <- prepareBlackBox pNm tempD bbCtx+ let bbDecl = N.BlackBoxD pNm (libraries p) (imports p)+ (includes p) templ bbCtx+ return (Identifier dstNm Nothing,dstDecl ++ ctxDcls ++ templDecl ++ tickDecls ++ [bbDecl]) Nothing -> return (Identifier "__VOID__" Nothing,[])- Just (P.Primitive pNm _)- | pNm == "GHC.Prim.tagToEnum#" -> do- hwTy <- N.unsafeCoreTypeToHWTypeM $(curLoc) ty- case args of- [Right (ConstTy (TyCon tcN)), Left (C.Literal (IntLiteral i))] -> do- tcm <- Lens.use tcCache- let dcs = tyConDataCons (tcm HashMap.! nameOcc tcN)- dc = dcs !! fromInteger i- (exprN,dcDecls) <- mkDcApplication hwTy dst dc []- return (exprN,dcDecls)- [Right _, Left scrut] -> do- tcm <- Lens.use tcCache- scrutTy <- termType tcm scrut- (scrutExpr,scrutDecls) <- mkExpr False (Left "#tte_rhs") scrutTy scrut- case scrutExpr of- Identifier id_ Nothing -> return (DataTag hwTy (Left id_),scrutDecls)- _ -> do- scrutHTy <- unsafeCoreTypeToHWTypeM $(curLoc) scrutTy- tmpRhs <- mkUniqueIdentifier Extended (pack "#tte_rhs")- let netDeclRhs = NetDecl Nothing tmpRhs scrutHTy- netAssignRhs = Assignment tmpRhs scrutExpr- return (DataTag hwTy (Left tmpRhs),[netDeclRhs,netAssignRhs] ++ scrutDecls)- _ -> error $ $(curLoc) ++ "tagToEnum: " ++ show (map (either showDoc showDoc) args)- | pNm == "GHC.Prim.dataToTag#" -> case args of- [Right _,Left (Data dc)] -> do- iw <- Lens.use intWidth- return (N.Literal (Just (Signed iw,iw)) (NumLit $ toInteger $ dcTag dc - 1),[])- [Right _,Left scrut] -> do- tcm <- Lens.use tcCache- scrutTy <- termType tcm scrut- scrutHTy <- unsafeCoreTypeToHWTypeM $(curLoc) scrutTy- (scrutExpr,scrutDecls) <- mkExpr False (Left "#dtt_rhs") scrutTy scrut- case scrutExpr of- Identifier id_ Nothing -> return (DataTag scrutHTy (Right id_),scrutDecls)- _ -> do- tmpRhs <- mkUniqueIdentifier Extended "#dtt_rhs"- let netDeclRhs = NetDecl Nothing tmpRhs scrutHTy- netAssignRhs = Assignment tmpRhs scrutExpr- return (DataTag scrutHTy (Right tmpRhs),[netDeclRhs,netAssignRhs] ++ scrutDecls)- _ -> error $ $(curLoc) ++ "dataToTag: " ++ show (map (either showDoc showDoc) args)- | otherwise -> return (BlackBoxE "" [] [] Nothing [C $ mconcat ["NO_TRANSLATION_FOR:",fromStrict pNm]] emptyBBContext False,[])- _ -> do- (_,sp) <- Lens.use curCompNm- throw (ClashException sp ($(curLoc) ++ "No blackbox found for: " ++ unpack nm) Nothing)- where+ TExpr -> do+ let tempE = template p+ pNm = name p+ if bbEasD+ then do+ resM <- resBndr True Wire dst+ case resM of+ Just (dst',dstNm,dstDecl) -> do+ (bbCtx,ctxDcls) <- mkBlackBoxContext nm dst' (lefts args)+ (bbTempl,templDecl) <- prepareBlackBox pNm tempE bbCtx+ let tmpAssgn = Assignment dstNm+ (BlackBoxE pNm (libraries p) (imports p)+ (includes p) bbTempl bbCtx+ bbEParen)+ return (Identifier dstNm Nothing, dstDecl ++ ctxDcls ++ templDecl ++ [tmpAssgn])+ Nothing -> return (Identifier "__VOID__" Nothing,[])+ else do+ resM <- resBndr False Wire dst+ case resM of+ Just (dst',_,_) -> do+ (bbCtx,ctxDcls) <- mkBlackBoxContext nm dst' (lefts args)+ (bbTempl,templDecl0) <- prepareBlackBox pNm tempE bbCtx+ let templDecl1 = case nm of+ "Clash.Sized.Internal.BitVector.fromInteger#"+ | [N.Literal _ (NumLit _), N.Literal _ _, N.Literal _ _] <- extractLiterals bbCtx -> []+ "Clash.Sized.Internal.BitVector.fromInteger##"+ | [N.Literal _ _, N.Literal _ _] <- extractLiterals bbCtx -> []+ "Clash.Sized.Internal.Index.fromInteger#"+ | [N.Literal _ (NumLit _), N.Literal _ _] <- extractLiterals bbCtx -> []+ "Clash.Sized.Internal.Signed.fromInteger#"+ | [N.Literal _ (NumLit _), N.Literal _ _] <- extractLiterals bbCtx -> []+ "Clash.Sized.Internal.Unsigned.fromInteger#"+ | [N.Literal _ (NumLit _), N.Literal _ _] <- extractLiterals bbCtx -> []+ _ -> templDecl0+ return (BlackBoxE pNm (libraries p) (imports p) (includes p) bbTempl bbCtx bbEParen,ctxDcls ++ templDecl1)+ Nothing -> return (Identifier "__VOID__" Nothing,[])+ P.Primitive pNm _ _+ | pNm == "GHC.Prim.tagToEnum#" -> do+ hwTy <- N.unsafeCoreTypeToHWTypeM' $(curLoc) ty+ case args of+ [Right (ConstTy (TyCon tcN)), Left (C.Literal (IntLiteral i))] -> do+ tcm <- Lens.use tcCache+ let dcs = tyConDataCons (tcm `lookupUniqMap'` tcN)+ dc = dcs !! fromInteger i+ (exprN,dcDecls) <- mkDcApplication hwTy dst dc []+ return (exprN,dcDecls)+ [Right _, Left scrut] -> do+ tcm <- Lens.use tcCache+ let scrutTy = termType tcm scrut+ (scrutExpr,scrutDecls) <- mkExpr False (Left "c$tte_rhs") scrutTy scrut+ case scrutExpr of+ Identifier id_ Nothing -> return (DataTag hwTy (Left id_),scrutDecls)+ _ -> do+ scrutHTy <- unsafeCoreTypeToHWTypeM' $(curLoc) scrutTy+ tmpRhs <- mkUniqueIdentifier Extended "c$tte_rhs"+ let netDeclRhs = NetDecl Nothing tmpRhs scrutHTy+ netAssignRhs = Assignment tmpRhs scrutExpr+ return (DataTag hwTy (Left tmpRhs),[netDeclRhs,netAssignRhs] ++ scrutDecls)+ _ -> error $ $(curLoc) ++ "tagToEnum: " ++ show (map (either showPpr showPpr) args)+ | pNm == "GHC.Prim.dataToTag#" -> case args of+ [Right _,Left (Data dc)] -> do+ iw <- Lens.use intWidth+ 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+ scrutHTy <- unsafeCoreTypeToHWTypeM' $(curLoc) scrutTy+ (scrutExpr,scrutDecls) <- mkExpr False (Left "c$dtt_rhs") scrutTy scrut+ case scrutExpr of+ Identifier id_ Nothing -> return (DataTag scrutHTy (Right id_),scrutDecls)+ _ -> do+ tmpRhs <- mkUniqueIdentifier Extended "c$dtt_rhs"+ let netDeclRhs = NetDecl Nothing tmpRhs scrutHTy+ netAssignRhs = Assignment tmpRhs scrutExpr+ return (DataTag scrutHTy (Right tmpRhs),[netDeclRhs,netAssignRhs] ++ scrutDecls)+ _ -> error $ $(curLoc) ++ "dataToTag: " ++ show (map (either showPpr showPpr) args)+ | otherwise ->+ return (BlackBoxE "" [] [] []+ (BBTemplate [Text $ mconcat ["NO_TRANSLATION_FOR:",fromStrict pNm]])+ (emptyBBContext pNm) False,[])+ resBndr :: Bool -> WireOrReg@@ -248,178 +417,303 @@ resBndr mkDec wr dst' = case dst' of Left dstL -> case mkDec of False -> do- let nm' = Text.unpack dstL- id_ = Id (string2SystemName nm') (embed ty)+ -- TODO: check that it's okay to use `mkUnsafeSystemName`+ let nm' = mkUnsafeSystemName dstL 0+ id_ = mkLocalId ty nm' return (Just (id_,dstL,[])) True -> do nm' <- extendIdentifier Extended dstL "_res" nm'' <- mkUniqueIdentifier Extended nm'- let nm3 = (string2SystemName (Text.unpack nm'')) { nameSort = Internal }- hwTy <- N.unsafeCoreTypeToHWTypeM $(curLoc) ty- let id_ = Id nm3 (embed ty)+ -- TODO: check that it's okay to use `mkUnsafeInternalName`+ let nm3 = mkUnsafeSystemName nm'' 0+ hwTy <- N.unsafeCoreTypeToHWTypeM' $(curLoc) ty+ let id_ = mkLocalId ty nm3 idDecl = NetDecl' Nothing wr nm'' (Right hwTy) case hwTy of Void {} -> return Nothing _ -> return (Just (id_,nm'',[idDecl]))- Right dstR -> return (Just (dstR,Text.pack . name2String . varName $ dstR,[]))+ Right dstR -> return (Just (dstR,nameOcc . varName $ dstR,[])) -- | Create an template instantiation text and a partial blackbox content for an -- argument term, given that the term is a function. Errors if the term is not -- a function mkFunInput- :: Id+ :: HasCallStack+ => Id -- ^ Identifier binding the encompassing primitive/blackbox application -> Term -- ^ The function argument term -> NetlistMonad- ((Either BlackBoxTemplate (Identifier,[Declaration])+ ((Either BlackBox (Identifier,[Declaration]) ,WireOrReg ,[BlackBoxTemplate] ,[BlackBoxTemplate]- ,Maybe ((TextS.Text,TextS.Text),BlackBoxTemplate)+ ,[((TextS.Text,TextS.Text),BlackBox)] ,BlackBoxContext) ,[Declaration])-mkFunInput resId e = do- let (appE,args) = collectArgs e- (bbCtx,dcls) <- mkBlackBoxContext resId (lefts args)+mkFunInput resId e =+ let (appE,args,ticks) = collectArgsTicks e+ in withTicks ticks $ \tickDecls -> do+ tcm <- Lens.use tcCache+ -- TODO: Rewrite this function to use blackbox functions. Right now it+ -- TODO: generates strings that are later parsed/interpreted again. Silly!+ (bbCtx,dcls) <- mkBlackBoxContext "__INTERNAL__" resId (lefts args) templ <- case appE of Prim nm _ -> do- bbM <- fmap (HashMap.lookup nm) $ Lens.use primitives- (_,sp) <- Lens.use curCompNm- let templ = case bbM of- Just (P.BlackBox {..}) -> Left (outputReg,library,imports,include,template)- _ -> throw (ClashException sp ($(curLoc) ++ "No blackbox found for: " ++ unpack nm) Nothing)- return templ+ bb <- extractPrimWarnOrFail nm+ case bb of+ P.BlackBox {..} ->+ pure (Left (kind,outputReg,libraries,imports,includes,nm,template))+ P.Primitive pn _ pt ->+ error $ $(curLoc) ++ "Unexpected blackbox type: "+ ++ "Primitive " ++ show pn+ ++ " " ++ show pt+ P.BlackBoxHaskell pName _workInfo fName (_, func) -> do+ -- Determine result type of this blackbox. If it's not a+ -- function, simply use its term type.+ let+ resTy0 = termType tcm e+ resTy1 =+ case splitFunTy tcm resTy0 of+ Just (_, t) -> t+ Nothing -> resTy0++ bbhRes <- func True pName args resTy1+ case bbhRes of+ Left err ->+ error $ $(curLoc) ++ show fName ++ " yielded an error: "+ ++ err+ Right (BlackBoxMeta{..}, template) ->+ pure $+ Left ( bbKind, bbOutputReg, bbLibrary, bbImports+ , bbIncludes, pName, template) Data dc -> do- tcm <- Lens.use tcCache- eTy <- termType tcm e- let (_,resTy) = splitFunTys tcm eTy- resHTyM <- coreTypeToHWTypeM resTy- case resHTyM of- Just resHTy@(SP _ dcArgPairs) -> do- let dcI = dcTag dc - 1- dcArgs = snd $ indexNote ($(curLoc) ++ "No DC with tag: " ++ show dcI) dcArgPairs dcI- dcInps = [ Identifier (pack ("~ARG[" ++ show x ++ "]")) Nothing | x <- [(0::Int)..(length dcArgs - 1)]]- dcApp = DataCon resHTy (DC (resHTy,dcI)) dcInps- dcAss = Assignment (pack "~RESULT") dcApp- return (Right (("",[dcAss]),Wire))- Just resHTy@(Product _ dcArgs) -> do- let dcInps = [ Identifier (pack ("~ARG[" ++ show x ++ "]")) Nothing | x <- [(0::Int)..(length dcArgs - 1)]]- dcApp = DataCon resHTy (DC (resHTy,0)) dcInps- dcAss = Assignment (pack "~RESULT") dcApp- return (Right (("",[dcAss]),Wire))- Just resHTy@(Vector _ _) -> do- let dcInps = [ Identifier (pack ("~ARG[" ++ show x ++ "]")) Nothing | x <- [(1::Int)..2] ]+ let eTy = termType tcm e+ (_,resTy) = splitFunTys tcm eTy++ resHTyM0 <- coreTypeToHWTypeM resTy+ let resHTyM1 = (\fHwty -> (stripFiltered fHwty, flattenFiltered fHwty)) <$> resHTyM0++ case resHTyM1 of+ -- Special case where coreTypeToHWTypeM determined a type to+ -- be completely transparent.+ Just (_resHTy, areVoids@[countEq False -> 1]) -> do+ let nonVoidArgI = fromJust (elemIndex False (head areVoids))+ let arg = TextS.concat ["~ARG[", showt nonVoidArgI, "]"]+ let assign = Assignment "~RESULT" (Identifier arg Nothing)+ return (Right (("", tickDecls ++ [assign]), Wire))++ -- Because we filter void constructs, the argument indices and+ -- the field indices don't necessarily correspond anymore. We+ -- use the result of coreTypeToHWTypeM to figure out what the+ -- original indices are. Please see the documentation in+ -- Clash.Netlist.Util.mkADT for more information.+ Just (resHTy@(SP _ _), areVoids0) -> do+ let+ dcI = dcTag dc - 1+ areVoids1 = indexNote ($(curLoc) ++ "No areVoids with index: " ++ show dcI) areVoids0 dcI+ dcInps = [Identifier (TextS.pack ("~ARG[" ++ show x ++ "]")) Nothing | x <- originalIndices areVoids1]+ dcApp = DataCon resHTy (DC (resHTy,dcI)) dcInps+ dcAss = Assignment "~RESULT" dcApp+ return (Right (("",tickDecls ++ [dcAss]),Wire))++ -- CustomSP the same as SP, but with a user-defined bit+ -- level representation+ Just (resHTy@(CustomSP {}), areVoids0) -> do+ let+ dcI = dcTag dc - 1+ areVoids1 = indexNote ($(curLoc) ++ "No areVoids with index: " ++ show dcI) areVoids0 dcI+ dcInps = [Identifier (TextS.pack ("~ARG[" ++ show x ++ "]")) Nothing | x <- originalIndices areVoids1]+ dcApp = DataCon resHTy (DC (resHTy,dcI)) dcInps+ dcAss = Assignment "~RESULT" dcApp+ return (Right (("",tickDecls ++ [dcAss]),Wire))++ -- Like SP, we have to retrieve the index BEFORE filtering voids+ Just (resHTy@(Product _ _ _), areVoids0) -> do+ let areVoids1 = head areVoids0+ dcInps = [ Identifier (TextS.pack ("~ARG[" ++ show x ++ "]")) Nothing | x <- originalIndices areVoids1]+ dcApp = DataCon resHTy (DC (resHTy,0)) dcInps+ dcAss = Assignment "~RESULT" dcApp+ return (Right (("",tickDecls ++ [dcAss]),Wire))++ -- Vectors never have defined areVoids (or all set to False), as+ -- it would be converted to Void otherwise. We can therefore+ -- safely ignore it:+ Just (resHTy@(Vector _ _), _areVoids) -> do+ let dcInps = [ Identifier (TextS.pack ("~ARG[" ++ show x ++ "]")) Nothing | x <- [(1::Int)..2] ] dcApp = DataCon resHTy (DC (resHTy,1)) dcInps- dcAss = Assignment (pack "~RESULT") dcApp- return (Right (("",[dcAss]),Wire))- -- The following happens for things like `Maybe ()`- Just resHTy@(Sum _ _) -> do+ dcAss = Assignment "~RESULT" dcApp+ return (Right (("",tickDecls ++ [dcAss]),Wire))++ -- Sum types OR a Sum type after filtering empty types:+ Just (resHTy@(Sum _ _), _areVoids) -> do let dcI = dcTag dc - 1 dcApp = DataCon resHTy (DC (resHTy,dcI)) []- dcAss = Assignment (pack "~RESULT") dcApp- return (Right (("",[dcAss]),Wire))- -- The following happens for things like `(1,())`- Just _ -> do- let inp = Identifier (pack ("~ARG[0]")) Nothing- assgn = Assignment (pack "~RESULT") inp- return (Right (("",[assgn]),Wire))- _ -> error $ $(curLoc) ++ "Cannot make function input for: " ++ showDoc e- C.Var _ (nameOcc -> fun) -> do- normalized <- Lens.use bindings- case HashMap.lookup fun normalized of- Just _ -> do- (_,Component compName compInps [snd -> compOutp] _) <- preserveVarEnv $ genComponent fun- let inpAssigns = zipWith (\(i,t) e' -> (Identifier i Nothing,In,t,e')) compInps [ Identifier (pack ("~ARG[" ++ show x ++ "]")) Nothing | x <- [(0::Int)..] ]- outpAssign = (Identifier (fst compOutp) Nothing,Out,snd compOutp,Identifier (pack "~RESULT") Nothing)- i <- varCount <<%= (+1)- let instLabel = Text.concat [compName,pack ("_" ++ show i)]- instDecl = InstDecl Nothing compName instLabel (outpAssign:inpAssigns)- return (Right (("",[instDecl]),Wire))- Nothing -> error $ $(curLoc) ++ "Cannot make function input for: " ++ showDoc e- C.Lam _ -> go 0 appE- _ -> error $ $(curLoc) ++ "Cannot make function input for: " ++ showDoc e+ dcAss = Assignment "~RESULT" dcApp+ return (Right (("",tickDecls ++ [dcAss]),Wire))++ -- Same as Sum, but with user defined bit level representation+ Just (resHTy@(CustomSum {}), _areVoids) -> do+ let dcI = dcTag dc - 1+ dcApp = DataCon resHTy (DC (resHTy,dcI)) []+ dcAss = Assignment "~RESULT" dcApp+ return (Right (("",tickDecls ++ [dcAss]),Wire))++ Just (Void {}, _areVoids) ->+ return (error $ $(curLoc) ++ "Encountered Void in mkFunInput."+ ++ " This is a bug in Clash.")++ _ -> error $ $(curLoc) ++ "Cannot make function input for: " ++ showPpr e+ C.Var fun -> do+ topAnns <- Lens.use topEntityAnns+ case lookupVarEnv fun topAnns of+ Just _ ->+ error $ $(curLoc) ++ "Cannot make function input for partially applied Synthesize-annotated: " ++ showPpr e+ _ -> do+ normalized <- Lens.use bindings+ case lookupVarEnv fun normalized of+ Just _ -> do+ (wereVoids,_,_,N.Component compName compInps [snd -> compOutp] _) <-+ preserveVarEnv $ genComponent fun++ let inpAssign (i, t) e' = (Identifier i Nothing, In, t, e')+ inpVar i = TextS.pack ("~VAR[arg" ++ show i ++ "][" ++ show i ++ "]")+ inpVars = [Identifier (inpVar i) Nothing | i <- originalIndices wereVoids]+ inpAssigns = zipWith inpAssign compInps inpVars+ outpAssign = ( Identifier (fst compOutp) Nothing+ , Out+ , snd compOutp+ , Identifier "~RESULT" Nothing )+ i <- varCount <<%= (+1)+ let instLabel = TextS.concat [compName,TextS.pack ("_" ++ show i)]+ instDecl = InstDecl Entity Nothing compName instLabel [] (outpAssign:inpAssigns)+ return (Right (("",tickDecls ++ [instDecl]),Wire))+ Nothing -> error $ $(curLoc) ++ "Cannot make function input for: " ++ showPpr e+ C.Lam {} -> do+ let is0 = mkInScopeSet (Lens.foldMapOf freeIds unitVarSet appE)+ either Left (Right . first (second (tickDecls ++))) <$> go is0 0 appE+ _ -> error $ $(curLoc) ++ "Cannot make function input for: " ++ showPpr e case templ of- Left (oreg,libs,imps,incM,Left templ') -> do- l <- instantiateCompName templ'- (l',templDecl) <- setSym bbCtx l- l'' <- collectFilePaths bbCtx l'- return ((Left l'',if oreg then Reg else Wire,libs,imps,incM,bbCtx),dcls ++ templDecl)- Left (_,libs,imps,incM,Right templ') -> do- templ'' <- getMon $ prettyBlackBox templ'- let ass = Assignment (pack "~RESULT") (Identifier templ'' Nothing)- return ((Right ("",[ass]),Wire,libs,imps,incM,bbCtx),dcls)+ Left (TDecl,oreg,libs,imps,inc,_,templ') -> do+ (l',templDecl)+ <- onBlackBox+ (fmap (first BBTemplate) . setSym mkUniqueIdentifier bbCtx)+ (\bbName bbHash bbFunc -> pure $ (BBFunction bbName bbHash bbFunc, []))+ templ'+ 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)+ let assn = Assignment "~RESULT" (Identifier (Text.toStrict t') Nothing)+ return ((Right ("",[assn]),Wire,libs,imps,inc,bbCtx),dcls))+ (\bbName bbHash (TemplateFunction k g _) -> do+ let f' bbCtx' = do+ let assn = Assignment "~RESULT"+ (BlackBoxE nm libs imps inc templ' bbCtx' False)+ p <- getMon (Backend.blockDecl "" [assn])+ return p+ return ((Left (BBFunction bbName bbHash (TemplateFunction k g f'))+ ,Wire+ ,[]+ ,[]+ ,[]+ ,bbCtx+ )+ ,dcls+ )+ )+ templ' Right (decl,wr) ->- return ((Right decl,wr,[],[],Nothing,bbCtx),dcls)+ return ((Right decl,wr,[],[],[],bbCtx),dcls) where- go n (Lam b) = do- (id_,e') <- unbind b- lvl <- Lens.use curBBlvl- let nm = varName id_- e'' = substTm (nameOcc nm)- (C.Var (unembed (varType id_))- (string2SystemName ("~ARGN[" ++ show lvl ++ "][" ++ show n ++ "]")))- e'- go (n+(1::Int)) e''+ goExpr app@(collectArgsTicks -> (C.Var fun,args@(_:_),ticks)) = do+ let (tmArgs,tyArgs) = partitionEithers args+ if null tyArgs+ then+ withTicks ticks $ \tickDecls -> do+ appDecls <- mkFunApp "~RESULT" fun tmArgs tickDecls+ nm <- mkUniqueIdentifier Basic "block"+ return (Right ((nm,appDecls),Wire))+ else do+ (_,sp) <- Lens.use curCompNm+ 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'+ (appExpr,appDecls) <- mkExpr False (Left "c$bb_res") eType e'+ let assn = Assignment "~RESULT" appExpr+ nm <- if null appDecls+ then return ""+ else mkUniqueIdentifier Basic "block"+ return (Right ((nm,appDecls ++ [assn]),Wire)) - go _ (C.Var _ nm) = do- let assn = Assignment (pack "~RESULT") (Identifier (pack (name2String nm)) Nothing)+ go is0 n (Lam id_ e') = do+ lvl <- Lens.use curBBlvl+ let nm = TextS.concat+ ["~ARGN[",TextS.pack (show lvl),"][",TextS.pack (show n),"]"]+ v' = uniqAway is0 (modifyVarName (\v -> v {nameOcc = nm}) id_)+ subst = extendIdSubst (mkSubst is0) id_ (C.Var v')+ e'' = substTm "mkFunInput.goLam" subst e'+ is1 = extendInScopeSet is0 v'+ go is1 (n+(1::Int)) e''++ go _ _ (C.Var v) = do+ let assn = Assignment "~RESULT" (Identifier (nameOcc (varName v)) Nothing) return (Right (("",[assn]),Wire)) - go _ (Case scrut ty [alt]) = do- (projection,decls) <- mkProjection False (Left "#bb_res") scrut ty alt- let assn = Assignment (pack "~RESULT") projection+ go _ _ (Case scrut ty [alt]) = do+ (projection,decls) <- mkProjection False (Left "c$bb_res") scrut ty alt+ let assn = Assignment "~RESULT" projection nm <- if null decls then return "" else mkUniqueIdentifier Basic "projection" return (Right ((nm,decls ++ [assn]),Wire)) - go _ (Case scrut ty alts@(_:_:_)) = do- let resId' = resId {varName = string2SystemName "~RESULT"}- selectionDecls <- mkSelection resId' scrut ty alts+ go _ _ (Case scrut ty alts@(_:_:_)) = do+ -- TODO: check that it's okay to use `mkUnsafeSystemName`+ let resId' = resId {varName = mkUnsafeSystemName "~RESULT" 0}+ selectionDecls <- mkSelection (Right resId') scrut ty alts [] nm <- mkUniqueIdentifier Basic "selection"- return (Right ((nm,selectionDecls),Reg))-- go _ e'@(App _ _) = do tcm <- Lens.use tcCache- eType <- termType tcm e'- (appExpr,appDecls) <- mkExpr False (Left "#bb_res") eType e'- let assn = Assignment (pack "~RESULT") appExpr- nm <- if null appDecls- then return ""- else mkUniqueIdentifier Basic "block"- return (Right ((nm,appDecls ++ [assn]),Wire))+ let scrutTy = termType tcm scrut+ scrutHTy <- unsafeCoreTypeToHWTypeM' $(curLoc) scrutTy+ ite <- Lens.use backEndITE+ let wr = case iteAlts scrutHTy alts of+ Just _ | ite -> Wire+ _ -> Reg+ return (Right ((nm,selectionDecls),wr)) - go _ e'@(Letrec _) = do+ go is0 _ e'@(Letrec {}) = do tcm <- Lens.use tcCache- normE <- splitNormalized tcm e'- ([],[],_,[],binders,result) <- case normE of- Right norm -> mkUniqueNormalized Nothing norm+ let normE = splitNormalized tcm e'+ (_,[],[],_,[],binders,resultM) <- case normE of+ Right norm -> mkUniqueNormalized is0 Nothing norm Left err -> error err- let binders' = map (\(id_,tm) -> (goR result id_,tm)) binders- netDecls <- fmap catMaybes . mapM mkNetDecl $ filter ((/= result) . varName . fst) binders- decls <- concat <$> mapM (uncurry mkDeclarations . second unembed) binders'- Just (NetDecl' _ rw _ _) <- mkNetDecl . head $ filter ((==result) . varName . fst) binders- nm <- mkUniqueIdentifier Basic "fun"- return (Right ((nm,netDecls ++ decls),rw))+ case resultM of+ Just result -> do+ let binders' = map (\(id_,tm) -> (goR result id_,tm)) binders+ netDecls <- fmap catMaybes . mapM mkNetDecl $ filter ((/= result) . fst) binders+ decls <- concat <$> mapM (uncurry mkDeclarations) binders'+ Just (NetDecl' _ rw _ _) <- mkNetDecl . head $ filter ((==result) . fst) binders+ nm <- mkUniqueIdentifier Basic "fun"+ return (Right ((nm,netDecls ++ decls),rw))+ Nothing -> return (Right (("",[]),Wire)) where- goR r id_ | varName id_ == r = id_ {varName = string2SystemName "~RESULT"}- | otherwise = id_+ -- TODO: check that it's okay to use `mkUnsafeSystemName`+ goR r id_ | id_ == r = id_ {varName = mkUnsafeSystemName "~RESULT" 0}+ | otherwise = id_ - go _ e' = error $ $(curLoc) ++ "Cannot make function input for: " ++ showDoc e'+ go is0 n (Tick _ e') = go is0 n e' + go _ _ e'@(App {}) = goExpr e'+ go _ _ e'@(C.Data {}) = goExpr e'+ go _ _ e'@(C.Literal {}) = goExpr e'+ go _ _ e'@(Cast {}) = goExpr e'+ go _ _ e'@(Prim {}) = goExpr e'+ go _ _ e'@(TyApp {}) = goExpr e' -instantiateCompName :: BlackBoxTemplate- -> NetlistMonad BlackBoxTemplate-instantiateCompName l = do- (nm,_) <- Lens.use curCompNm- return (setCompName nm l)+ go _ _ e'@(Case _ _ []) =+ error $ $(curLoc) ++ "Cannot make function input for case without alternatives: " ++ show e' -collectFilePaths :: BlackBoxContext- -> BlackBoxTemplate- -> NetlistMonad BlackBoxTemplate-collectFilePaths bbCtx l = do- fs <- Lens.use dataFiles- let (fs',l') = findAndSetDataFiles bbCtx fs l- dataFiles .= fs'- return l'+ go _ _ e'@(TyLam {}) =+ error $ $(curLoc) ++ "Cannot make function input for TyLam: " ++ show e'
src/Clash/Netlist/BlackBox/Parser.hs view
@@ -13,13 +13,14 @@ (runParse) where -import Control.Applicative+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 +import qualified Clash.Signal.Internal as Signal import Clash.Netlist.BlackBox.Types -- | Parse a text as a BlackBoxTemplate, returns a list of errors in case@@ -37,19 +38,25 @@ -- | Parse a single Template Element pElement :: Parser Element pElement = pTagD- <|> C <$> pText- <|> C <$> (pack <$> string "~ ")+ <|> Text <$> pText+ <|> Text <$> (pack <$> string "~ ") -- | Parse the Text part of a Template pText :: Parser Text pText = pack <$> some (satisfyRange '\000' '\125') +pEdge :: Parser Signal.ActiveEdge+pEdge =+ (pure Signal.Rising <* symbol "Rising") <|>+ (pure Signal.Falling <* symbol "Falling")++ -- | Parse a Declaration or Expression element pTagD :: Parser Element pTagD = IF <$> (symbol "~IF" *> pTagE) <*> (spaces *> (string "~THEN" *> pBlackBoxD)) <*> (string "~ELSE" *> pBlackBoxD <* string "~FI")- <|> D <$> pDecl+ <|> Component <$> pDecl <|> pTagE -- | Parse a Declaration@@ -67,13 +74,14 @@ -- | Parse an Expression element pTagE :: Parser Element-pTagE = O True <$ string "~ERESULT"- <|> O False <$ string "~RESULT"- <|> I True <$> (string "~EARG" *> brackets' natural')- <|> Arg <$> (string "~ARGN" *> brackets' natural') <*> brackets' natural'- <|> I False <$> (string "~ARG" *> brackets' natural')- <|> L <$> (string "~LIT" *> brackets' natural')- <|> N <$> (string "~NAME" *> brackets' natural')+pTagE = Result True <$ string "~ERESULT"+ <|> Result False <$ string "~RESULT"+ <|> ArgGen <$> (string "~ARGN" *> brackets' natural') <*> brackets' natural'+ <|> Arg True <$> (string "~EARG" *> brackets' natural')+ <|> Arg False <$> (string "~ARG" *> brackets' natural')+ <|> Const <$> (string "~CONST" *> brackets' natural')+ <|> Lit <$> (string "~LIT" *> brackets' natural')+ <|> Name <$> (string "~NAME" *> brackets' natural') <|> Var <$> try (string "~VAR" *> brackets' pSigD) <*> brackets' natural' <|> (Sym Text.empty) <$> (string "~SYM" *> brackets' natural') <|> Typ Nothing <$ string "~TYPO"@@ -85,16 +93,18 @@ <|> TypElem <$> (string "~TYPEL" *> brackets' pTagE) <|> IndexType <$> (string "~INDEXTYPE" *> brackets' pTagE) <|> CompName <$ string "~COMPNAME"- <|> IncludeName <$ string "~INCLUDENAME"+ <|> IncludeName <$> (string "~INCLUDENAME" *> brackets' natural') <|> Size <$> (string "~SIZE" *> brackets' pTagE) <|> Length <$> (string "~LENGTH" *> brackets' pTagE) <|> Depth <$> (string "~DEPTH" *> brackets' pTagE)+ <|> MaxIndex <$> (string "~MAXINDEX" *> brackets' pTagE) <|> FilePath <$> (string "~FILE" *> brackets' pTagE) <|> Gen <$> (True <$ string "~GENERATE") <|> Gen <$> (False <$ string "~ENDGENERATE") <|> (`SigD` Nothing) <$> (string "~SIGDO" *> brackets' pSigD) <|> SigD <$> (string "~SIGD" *> brackets' pSigD) <*> (Just <$> (brackets' natural')) <|> IW64 <$ string "~IW64"+ <|> CmpLE <$> try (string "~CMPLE" *> brackets' pTagE) <*> brackets' pTagE <|> (HdlSyn Vivado) <$ string "~VIVADO" <|> (HdlSyn Other) <$ string "~OTHERSYN" <|> (BV True) <$> (string "~TOBV" *> brackets' pSigD) <*> brackets' pTagE@@ -102,14 +112,24 @@ <|> Sel <$> (string "~SEL" *> brackets' pTagE) <*> brackets' natural' <|> IsLit <$> (string "~ISLIT" *> brackets' natural') <|> IsVar <$> (string "~ISVAR" *> brackets' natural')- <|> IsGated <$> (string "~ISGATED" *> brackets' natural')- <|> IsSync <$> (string "~ISSYNC" *> brackets' natural')+ <|> IsActiveHigh <$> (string "~ISACTIVEHIGH" *> brackets' natural')+ <|> IsActiveEnable <$> (string "~ISACTIVEENABLE" *> brackets' natural') <|> StrCmp <$> (string "~STRCMP" *> brackets' pSigD) <*> brackets' natural' <|> OutputWireReg <$> (string "~OUTPUTWIREREG" *> brackets' natural') <|> GenSym <$> (string "~GENSYM" *> brackets' pSigD) <*> brackets' natural'+ <|> Template <$> (string "~TEMPLATE" *> brackets' pSigD) <*> brackets' pSigD+ <|> Repeat <$> (string "~REPEAT" *> brackets' pSigD) <*> brackets' pSigD+ <|> DevNull <$> (string "~DEVNULL" *> brackets' pSigD) <|> And <$> (string "~AND" *> brackets' (commaSep pTagE)) <|> Vars <$> (string "~VARS" *> brackets' natural') + -- Domain attributes:+ <|> Tag <$> (string "~TAG" *> brackets' natural')+ <|> Period <$> (string "~PERIOD" *> brackets' natural')+ <|> ActiveEdge <$> (string "~ACTIVEEDGE" *> brackets pEdge) <*> brackets' natural'+ <|> IsSync <$> (string "~ISSYNC" *> brackets' natural')+ <|> IsInitDefined <$> (string "~ISINITDEFINED" *> brackets' natural')+ natural' :: TokenParsing m => m Int natural' = fmap fromInteger natural @@ -124,11 +144,11 @@ -- | Parse an Expression or Text pElemE :: Parser Element pElemE = pTagE- <|> C <$> pText+ <|> Text <$> pText -- | Parse SigD pSigD :: Parser [Element]-pSigD = some (pTagE <|> (C (pack "[") <$ (pack <$> string "[\\"))- <|> (C (pack "]") <$ (pack <$> string "\\]"))- <|> (C <$> (pack <$> some (satisfyRange '\000' '\90')))- <|> (C <$> (pack <$> some (satisfyRange '\94' '\125'))))+pSigD = some (pTagE <|> (Text (pack "[") <$ (pack <$> string "[\\"))+ <|> (Text (pack "]") <$ (pack <$> string "\\]"))+ <|> (Text <$> (pack <$> some (satisfyRange '\000' '\90')))+ <|> (Text <$> (pack <$> some (satisfyRange '\94' '\125'))))
src/Clash/Netlist/BlackBox/Types.hs view
@@ -7,59 +7,174 @@ Types used in BlackBox modules -} -module Clash.Netlist.BlackBox.Types where+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-} -import Data.Text.Lazy (Text)+module Clash.Netlist.BlackBox.Types+ ( BlackBoxMeta(..)+ , emptyBlackBoxMeta+ , BlackBoxFunction+ , BlackBoxTemplate+ , TemplateKind (..)+ , Element(..)+ , Decl(..)+ , HdlSyn(..)+ ) where +import Control.DeepSeq (NFData)+import Data.Binary (Binary)+import Data.Hashable (Hashable)+import Data.Text.Lazy (Text)+import qualified Data.Text as S+import GHC.Generics (Generic)++import Clash.Core.Term (Term)+import Clash.Core.Type (Type)+import {-# SOURCE #-} Clash.Netlist.Types+ (BlackBox, NetlistMonad)++import qualified Clash.Signal.Internal as Signal++data TemplateKind+ = TDecl+ | TExpr+ deriving (Show, Eq, Generic, NFData, Binary, Hashable)++-- | See @Clash.Primitives.Types.BlackBox@ for documentation on this record's+-- fields. (They are intentionally renamed to prevent name clashes.)+data BlackBoxMeta =+ BlackBoxMeta { bbOutputReg :: Bool+ , bbKind :: TemplateKind+ , bbLibrary :: [BlackBoxTemplate]+ , bbImports :: [BlackBoxTemplate]+ , bbIncludes :: [((S.Text, S.Text), BlackBox)]+ }++-- | Use this value in your blackbox template function if you do want to+-- accept the defaults as documented in @Clash.Primitives.Types.BlackBox@.+emptyBlackBoxMeta :: BlackBoxMeta+emptyBlackBoxMeta = BlackBoxMeta False TExpr [] [] []++-- | A BlackBox function generates a blackbox template, given the inputs and+-- result type of the function it should provide a blackbox for. This is useful+-- when having a need for blackbox functions, ... TODO: docs+type BlackBoxFunction+ = Bool+ -- ^ Indicates whether caller needs a declaration. If set, the function is+ -- still free to return an expression, but the caller will convert it to a+ -- declaration.+ -> S.Text+ -- ^ Name of primitive+ -> [Either Term Type]+ -- ^ Arguments+ -> Type+ -- ^ Result type+ -> NetlistMonad (Either String (BlackBoxMeta, BlackBox))+ -- | A BlackBox Template is a List of Elements+-- TODO: Add name of function for better error messages type BlackBoxTemplate = [Element] --- | Elements of a blackbox context-data Element = C !Text -- ^ Constant- | D !Decl -- ^ Component instantiation hole- | O !Bool- -- ^ Output hole; @Bool@ asserts escape marker stripping- | I !Bool !Int- -- ^ Input hole; @Bool@ asserts escape marker stripping- | Arg !Int !Int- -- ^ Generated input hole, first argument is the scoping level- | N !Int -- ^ Name hole- | L !Int -- ^ Literal hole- | Var [Element] !Int --- | Sym !Text !Int -- ^ Symbol hole- | Typ !(Maybe Int) -- ^ Type declaration hole- | TypM !(Maybe Int) -- ^ Type root hole- | Err !(Maybe Int) -- ^ Error value hole- | TypElem !Element -- ^ Select element type from a vector type- | CompName -- ^ Hole for the name of the component in which- -- the blackbox is instantiated- | IncludeName- | IndexType !Element -- ^ Index data type hole, the field is the- -- (exclusive) maximum index- | Size !Element -- ^ Size of a type hole- | Length !Element -- ^ Length of a vector hole- | Depth !Element -- ^ Depth of a tree hole- | FilePath !Element -- ^ Hole containing a filepath for a data file- | Gen !Bool -- ^ Hole marking beginning (True) or end (False)- -- of a generative construct- | IF !Element [Element] [Element]- | And [Element]- | IW64 -- ^ Hole indicating whether Int/Word/Integer- -- are 64-Bit- | HdlSyn HdlSyn -- ^ Hole indicating which synthesis tool we're- -- generating HDL for- | BV !Bool [Element] !Element -- ^ Convert to (True)/from(False) a bit-vector- | Sel !Element !Int -- ^ Record selector of a type- | IsLit !Int- | IsVar !Int- | IsGated !Int- | IsSync !Int- | StrCmp [Element] !Int- | OutputWireReg !Int- | Vars !Int- | GenSym [Element] !Int- | SigD [Element] !(Maybe Int)- deriving Show+-- | Elements of a blackbox context. If you extend this list, make sure to+-- update the following functions:+--+-- - Clash.Netlist.BlackBox.Types.prettyElem+-- - Clash.Netlist.BlackBox.Types.renderElem+-- - Clash.Netlist.BlackBox.Types.renderTag+-- - Clash.Netlist.BlackBox.Types.setSym+-- - Clash.Netlist.BlackBox.Types.usedArguments+-- - Clash.Netlist.BlackBox.Types.usedVariables+-- - Clash.Netlist.BlackBox.Types.verifyBlackBoxContext+-- - Clash.Netlist.BlackBox.Types.walkElement+data Element+ = Text !Text+ -- ^ Dumps given text without processing in HDL+ | Component !Decl+ -- ^ Component instantiation hole+ | Result !Bool+ -- ^ Output hole; @Bool@ asserts escape marker stripping+ | Arg !Bool !Int+ -- ^ Input hole; @Bool@ asserts escape marker stripping+ | ArgGen !Int !Int+ -- ^ Like Arg, but its first argument is the scoping level. For use in+ -- in generated code only.+ | Const !Int+ -- ^ Like Arg, but input hole must be a constant.+ | Lit !Int+ -- ^ Like Arg, but input hole must be a literal+ | Name !Int+ -- ^ Name hole+ | Var [Element] !Int+ -- ^ Like Arg but only insert variable reference (creating an assignment+ -- elsewhere if necessary).+ | Sym !Text !Int+ -- ^ Symbol hole+ | Typ !(Maybe Int)+ -- ^ Type declaration hole+ | TypM !(Maybe Int)+ -- ^ Type root hole+ | Err !(Maybe Int)+ -- ^ Error value hole+ | TypElem !Element+ -- ^ Select element type from a vector type+ | CompName+ -- ^ Hole for the name of the component in which the blackbox is instantiated+ | IncludeName !Int+ | IndexType !Element+ -- ^ Index data type hole, the field is the (exclusive) maximum index+ | Size !Element+ -- ^ Size of a type hole+ | Length !Element+ -- ^ Length of a vector hole+ | Depth !Element+ -- ^ Depth of a tree hole+ | MaxIndex !Element+ -- ^ Max index into a vector+ | FilePath !Element+ -- ^ Hole containing a filepath for a data file+ | Template [Element] [Element]+ -- ^ Create data file <HOLE0> with contents <HOLE1>+ | Gen !Bool+ -- ^ Hole marking beginning (True) or end (False) of a generative construct+ | IF !Element [Element] [Element]+ | And [Element]+ | IW64+ -- ^ Hole indicating whether Int/Word/Integer are 64-Bit+ | CmpLE !Element !Element+ -- ^ Compare less-or-equal+ | HdlSyn HdlSyn+ -- ^ Hole indicating which synthesis tool we're generating HDL for+ | BV !Bool [Element] !Element+ -- ^ Convert to (True)/from(False) a bit-vector+ | Sel !Element !Int+ -- ^ Record selector of a type+ | IsLit !Int+ | IsVar !Int+ | IsActiveHigh !Int+ -- ^ Whether a domain's reset lines are synchronous.+ | Tag !Int+ -- ^ Tag of a domain.+ | Period !Int+ -- ^ Period of a domain.+ | ActiveEdge !Signal.ActiveEdge !Int+ -- ^ Test active edge of memory elements in a certain domain+ | IsSync !Int+ -- ^ Whether a domain's reset lines are synchronous. Errors if not applied to+ -- a KnownDomain.+ | IsInitDefined !Int+ | IsActiveEnable !Int+ -- ^ Whether given enable line is active. More specifically, whether the+ -- enable line is NOT set to a constant 'True'.+ | StrCmp [Element] !Int+ | OutputWireReg !Int+ | Vars !Int+ | GenSym [Element] !Int+ | Repeat [Element] [Element]+ -- ^ Repeat <hole> n times+ | DevNull [Element]+ -- ^ Evaluate <hole> but swallow output+ | SigD [Element] !(Maybe Int)+ deriving (Show, Generic, NFData, Binary, Hashable) -- | Component instantiation hole. First argument indicates which function argument -- to instantiate. Second argument corresponds to output and input assignments,@@ -69,7 +184,7 @@ -- The LHS of the tuple is the name of the signal, while the RHS of the tuple -- is the type of the signal data Decl = Decl !Int [(BlackBoxTemplate,BlackBoxTemplate)]- deriving Show+ deriving (Show, Generic, NFData, Binary, Hashable) -data HdlSyn = Vivado | Other- deriving (Eq,Show,Read)+data HdlSyn = Vivado | Quartus | Other+ deriving (Eq, Show, Read, Generic, NFData, Binary, Hashable)
src/Clash/Netlist/BlackBox/Util.hs view
@@ -8,74 +8,113 @@ in templates -} -{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-} module Clash.Netlist.BlackBox.Util where -import Control.Exception (throw)-import Control.Lens (_1,_2,(%=),use)-import Control.Monad.State (State, StateT (..), lift)-import Data.Bool (bool)-import Data.Foldable (foldrM)-import Data.Hashable (Hashable (..))-import qualified Data.IntMap as IntMap-import Data.List (mapAccumL, nub)+import Control.Exception (throw)+import Control.Lens+ (use, (%=), _1, _2, element, (^?))+import Control.Monad (forM)+import Control.Monad.State (State, StateT (..), lift)+import Data.Bool (bool)+import Data.Foldable (foldrM)+import Data.Hashable (Hashable (..))+import qualified Data.IntMap as IntMap+import Data.List (nub) #if !MIN_VERSION_base(4,11,0) import Data.Monoid #endif+import Data.Maybe (mapMaybe, maybeToList) import Data.Semigroup.Monad import qualified Data.Text-import qualified Data.Text.Prettyprint.Doc as PP+import Data.Text.Lazy (Text)+import qualified Data.Text.Lazy as Text+import qualified Data.Text.Prettyprint.Doc as PP import Data.Text.Prettyprint.Doc.Extra-import Data.Text.Lazy (Text)-import qualified Data.Text.Lazy as Text-import System.FilePath (replaceBaseName,- takeBaseName,- takeFileName,- (<.>))-import qualified Text.PrettyPrint.ANSI.Leijen as ANSI+import System.FilePath (replaceBaseName, takeBaseName,+ takeFileName, (<.>))+import qualified Text.PrettyPrint.ANSI.Leijen as ANSI import Text.Printf-import Text.Trifecta.Result hiding (Err)+import Text.Read (readEither)+import Text.Trifecta.Result hiding (Err) -import Clash.Backend (Backend (..), Usage (..))-import Clash.Driver.Types (ClashException (..))+import Clash.Backend (Backend (..), Usage (..))+import qualified Clash.Backend as Backend import Clash.Netlist.BlackBox.Parser import Clash.Netlist.BlackBox.Types-import Clash.Netlist.Id (IdType (..))-import Clash.Netlist.Types- (HWType (..), Identifier, BlackBoxContext (..), Expr (..), Literal (..),- NetlistMonad, Modifier (..))-import qualified Clash.Netlist.Types as N-import Clash.Netlist.Util (mkUniqueIdentifier,typeSize)+import Clash.Netlist.Id (IdType (..))+import Clash.Netlist.Types (BlackBoxContext (..),+ Expr (..), HWType (..),+ Identifier, Literal (..),+ Modifier (..),+ Declaration(BlackBoxD))+import qualified Clash.Netlist.Types as N+import Clash.Netlist.Util (typeSize) import Clash.Signal.Internal- (ClockKind (Gated), ResetKind (Synchronous))+ (ResetKind(..), ResetPolarity(..), InitBehavior(..)) import Clash.Util +-- | Strip as many "Void" layers as possible. Might still return a Void if the+-- void doesn't contain a hwtype.+stripVoid :: HWType -> HWType+stripVoid (Void (Just e)) = stripVoid e+stripVoid e = e++inputHole :: Element -> Maybe Int+inputHole = \case+ Arg _ n -> pure n+ Lit n -> pure n+ Const n -> pure n+ Name n -> pure n+ Typ (Just n) -> pure n+ TypM (Just n) -> pure n+ Err (Just n) -> pure n+ _ -> Nothing+ -- | Determine if the number of normal/literal/function inputs of a blackbox -- context at least matches the number of argument that is expected by the -- template.-verifyBlackBoxContext :: BlackBoxContext -- ^ Blackbox to verify- -> BlackBoxTemplate -- ^ Template to check against- -> Bool-verifyBlackBoxContext bbCtx = all verify'+verifyBlackBoxContext+ :: BlackBoxContext+ -- ^ Blackbox to verify+ -> N.BlackBox+ -- ^ Template to check against+ -> Bool+verifyBlackBoxContext bbCtx (N.BBFunction _ _ (N.TemplateFunction _ f _)) = f bbCtx+verifyBlackBoxContext bbCtx (N.BBTemplate t) = and (concatMap (walkElement verify') t) where- verify' (I _ n) = n < length (bbInputs bbCtx)- verify' (L n) = case indexMaybe (bbInputs bbCtx) n of- Just (_,_,b) -> b- _ -> False- verify' (Typ (Just n)) = n < length (bbInputs bbCtx)- verify' (TypM (Just n)) = n < length (bbInputs bbCtx)- verify' (Err (Just n)) = n < length (bbInputs bbCtx)- verify' (D (Decl n l')) = case IntMap.lookup n (bbFunctions bbCtx) of- Just _ -> all (\(x,y) -> verifyBlackBoxContext bbCtx x &&- verifyBlackBoxContext bbCtx y) l'- _ -> False- verify' _ = True+ verify' e =+ Just $+ case e of+ Lit n ->+ case indexMaybe (bbInputs bbCtx) n of+ Just (_, _, b) -> b+ _ -> False+ Const n ->+ case indexMaybe (bbInputs bbCtx) n of+ Just (_, _, b) -> b+ _ -> False+ Component (Decl n l') ->+ case IntMap.lookup n (bbFunctions bbCtx) of+ Just _ ->+ all (\(x,y) ->+ verifyBlackBoxContext bbCtx (N.BBTemplate x) &&+ verifyBlackBoxContext bbCtx (N.BBTemplate y)) l'+ Nothing ->+ False+ _ ->+ case inputHole e of+ Nothing ->+ True+ Just n ->+ n < length (bbInputs bbCtx) extractLiterals :: BlackBoxContext -> [Expr]@@ -86,51 +125,58 @@ -- | Update all the symbol references in a template, and increment the symbol -- counter for every newly encountered symbol. setSym- :: BlackBoxContext+ :: forall m+ . Monad m+ => (IdType -> Identifier -> m Identifier)+ -> BlackBoxContext -> BlackBoxTemplate- -> NetlistMonad (BlackBoxTemplate,[N.Declaration])-setSym bbCtx l = do+ -> m (BlackBoxTemplate,[N.Declaration])+setSym mkUniqueIdentifierM bbCtx l = do (a,(_,decls)) <- runStateT (mapM setSym' l) (IntMap.empty,IntMap.empty) return (a,concatMap snd (IntMap.elems decls)) where- setSym' :: Element- -> StateT ( IntMap.IntMap Identifier- , IntMap.IntMap (Identifier,[N.Declaration]))- NetlistMonad- Element+ setSym'+ :: Element+ -> StateT ( IntMap.IntMap Identifier+ , IntMap.IntMap (Identifier,[N.Declaration]))+ m+ Element setSym' e = case e of Var nm i | i < length (bbInputs bbCtx) -> case bbInputs bbCtx !! i of- (Identifier nm' Nothing,_,_) -> return (Var [C nm'] i)+ (Identifier nm' Nothing,_,_) ->+ return (Var [Text (Text.fromStrict nm')] i)+ (e',hwTy,_) -> do varM <- IntMap.lookup i <$> use _2 case varM of Nothing -> do- nm' <- lift (mkUniqueIdentifier Extended (concatT (C "#":nm)))+ nm' <- lift (mkUniqueIdentifierM Extended (Text.toStrict (concatT (Text "c$":nm)))) let decls = case typeSize hwTy of 0 -> [] _ -> [N.NetDecl Nothing nm' hwTy ,N.Assignment nm' e' ] _2 %= (IntMap.insert i (nm',decls))- return (Var [C nm'] i)- Just (nm',_) -> return (Var [C nm'] i)+ return (Var [Text (Text.fromStrict nm')] i)+ Just (nm',_) -> return (Var [Text (Text.fromStrict nm')] i) Sym _ i -> do symM <- IntMap.lookup i <$> use _1 case symM of Nothing -> do- t <- lift (mkUniqueIdentifier Extended (Text.pack "#n"))+ t <- lift (mkUniqueIdentifierM Extended "c$n") _1 %= (IntMap.insert i t)- return (Sym t i)- Just t -> return (Sym t i)+ return (Sym (Text.fromStrict t) i)+ Just t -> return (Sym (Text.fromStrict t) i) GenSym t i -> do symM <- IntMap.lookup i <$> use _1 case symM of Nothing -> do- t' <- lift (mkUniqueIdentifier Basic (concatT t))+ t' <- lift (mkUniqueIdentifierM Basic (Text.toStrict (concatT t))) _1 %= (IntMap.insert i t')- return (GenSym [C t'] i)+ return (GenSym [Text (Text.fromStrict t')] i) Just _ -> error ("Symbol #" ++ show (t,i) ++ " is already defined")- D (Decl n l') -> D <$> (Decl n <$> mapM (combineM (mapM setSym') (mapM setSym')) l')+ Component (Decl n l') ->+ Component <$> (Decl n <$> mapM (combineM (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@@ -138,49 +184,36 @@ concatT :: [Element] -> Text concatT = Text.concat- . map (\case { C t -> t- ; O _ | Identifier t _ <- fst (bbResult bbCtx)- -> t- ; N n | let (e,_,_) = bbInputs bbCtx !! n- , Just t <- exprToText e- -> t+ . map (\case { Text t -> t+ ; Name i -> case elementToText bbCtx (Name i) of+ Right t ->+ t+ Left msg ->+ error $ $(curLoc) ++ "Could not convert "+ ++ "~NAME[" ++ show i ++ "]"+ ++ " to string:" ++ msg+ ; Result _ | Identifier t _ <- fst (bbResult bbCtx)+ -> Text.fromStrict t+ ; CompName -> Text.fromStrict (bbCompName bbCtx) ; _ -> error "unexpected element in GENSYM"}) -setCompName :: Identifier -> BlackBoxTemplate -> BlackBoxTemplate-setCompName nm = map setCompName'- where- setCompName' CompName = C nm- setCompName' (D (Decl n l)) = D (Decl n (map (setCompName nm *** setCompName nm) l))- setCompName' (IF c t f) = IF c (setCompName nm t) (setCompName nm f)- setCompName' (GenSym es i) = GenSym (setCompName nm es) i- setCompName' (BV t e m) = BV t (setCompName nm e) (setCompName' m)- setCompName' e = e--findAndSetDataFiles :: BlackBoxContext -> [(String,FilePath)] -> BlackBoxTemplate -> ([(String,FilePath)],BlackBoxTemplate)-findAndSetDataFiles bbCtx fs = mapAccumL findAndSet fs- where- findAndSet fs' (FilePath e) = case e of- (L n) ->- let (e',_,_) = bbInputs bbCtx !! n- in case e' of- BlackBoxE "GHC.CString.unpackCString#" _ _ _ _ bbCtx' _ -> case bbInputs bbCtx' of- [(Literal Nothing (StringLit s'),_,_)] -> renderFilePath fs s'- _ -> (fs',FilePath e)- Literal Nothing (StringLit s') -> renderFilePath fs s'- _ -> (fs',FilePath e)- _ -> (fs',FilePath e)- findAndSet fs' l = (fs',l)+selectNewName+ :: Foldable t+ => t String+ -- ^ Set of existing names+ -> FilePath+ -- ^ Name for new file (+ -> String+selectNewName as a+ | elem a as = selectNewName as (replaceBaseName a (takeBaseName a ++ "_"))+ | otherwise = a -renderFilePath :: [(String,FilePath)] -> String -> ([(String,FilePath)],Element)-renderFilePath fs f = ((f'',f):fs,C (Text.pack $ show f''))+renderFilePath :: [(String,FilePath)] -> String -> ([(String,FilePath)],String)+renderFilePath fs f = ((f'',f):fs, f'') where f' = takeFileName f f'' = selectNewName (map fst fs) f' - selectNewName as a- | elem a as = selectNewName as (replaceBaseName a (takeBaseName a ++ "_"))- | otherwise = a- -- | Render a blackbox given a certain context. Returns a filled out template -- and a list of 'hidden' inputs that must be added to the encompassing component. renderTemplate@@ -196,87 +229,103 @@ :: Backend backend => [BlackBoxTemplate] -> [BlackBoxTemplate]- -> Maybe ((Data.Text.Text,Data.Text.Text), BlackBoxTemplate)- -> BlackBoxTemplate+ -> [((Data.Text.Text,Data.Text.Text), N.BlackBox)]+ -> N.BlackBox -> BlackBoxContext -> State backend (Int -> Doc)-renderBlackBox libs imps Nothing bs bbCtx = do- libs' <- mapM (fmap ($ 0) . renderTemplate bbCtx) libs- imps' <- mapM (fmap ($ 0) . renderTemplate bbCtx) imps- addLibraries libs'- addImports imps'- t <- renderTemplate bbCtx bs- return (\col -> PP.nest (col-2) (PP.pretty (t (col+2))))+renderBlackBox libs imps includes bb bbCtx = do+ let nms' = zipWith (\_ i -> "~INCLUDENAME[" <> Text.pack (show i) <> "]")+ includes+ [(0 :: Int)..]+ layout = LayoutOptions (AvailablePerLine 120 0.4)+ nms <-+ forM includes $ \((nm,_),inc) -> do+ let bbCtx' = bbCtx {bbQsysIncName = map Text.toStrict nms'}+ incForHash <- onBlackBox (renderTemplate bbCtx')+ (\_name _hash (N.TemplateFunction _ _ f) -> do+ t <- f bbCtx'+ let t' = renderLazy (layoutPretty layout t)+ return (const t'))+ inc+ iw <- iwWidth+ let incHash = hash (incForHash 0)+ nm' = Text.concat+ [ Text.fromStrict nm+ , Text.pack (printf ("%0" ++ show (iw `div` 4) ++ "X") incHash)+ ]+ pure nm' -renderBlackBox libs imps (Just ((nm,ext),inc)) bs bbCtx = do- incForHash <- renderTemplate (bbCtx {bbQsysIncName = Just "~INCLUDENAME"}) inc- iw <- iwWidth- let incHash = hash (incForHash 0)- nm' = Text.concat- [ Text.fromStrict nm- , Text.pack (printf ("%0" ++ show (iw `div` 4) ++ "X") incHash)- ]- bbNamedCtx = bbCtx {bbQsysIncName = Just nm'}+ let bbNamedCtx = bbCtx {bbQsysIncName = map Text.toStrict nms}+ incs = snd <$> includes+ bb' <- case bb of+ N.BBTemplate bt -> do+ t <- renderTemplate bbNamedCtx bt+ return (\col -> PP.nest (col-2) (PP.pretty (t (col + 2))))+ N.BBFunction _ _ (N.TemplateFunction _ _ bf) -> do+ t <- bf bbNamedCtx+ return (\_ -> t) - inc' <-renderTemplate bbNamedCtx inc- t <- renderTemplate bbNamedCtx bs- inc'' <- pretty (inc' 0)- addInclude (Text.unpack nm' <.> Data.Text.unpack ext, inc'')+ incs' <- mapM (onBlackBox (fmap (PP.pretty . ($ 0)) . renderTemplate bbNamedCtx)+ (\_name _hash (N.TemplateFunction _ _ f) -> f bbNamedCtx))+ incs libs' <- mapM (fmap ($ 0) . renderTemplate bbNamedCtx) libs imps' <- mapM (fmap ($ 0) . renderTemplate bbNamedCtx) imps+ addIncludes $ zipWith3 (\nm' ((_, ext), _) inc -> (Text.unpack nm' <.> Data.Text.unpack ext, inc)) nms includes incs' addLibraries libs' addImports imps'- return (\col -> PP.nest (col-2) (PP.pretty (t (col+2))))---- | Assign @Var@ holes in the context of a primitive HDL template that is--- passed as an argument of a higher-order HDL template. For the general case,--- use 'setSym'------ This functions errors when the @Var@ hole cannot be filled with a variable,--- as it is (currently) impossible to create unique names this late in the--- pipeline.-setSimpleVar- :: BlackBoxContext- -> BlackBoxTemplate- -> BlackBoxTemplate-setSimpleVar bbCtx = map go- where- go e = case e of- Var _ i- | i < length (bbInputs bbCtx)- , (Identifier nm' Nothing,_,_) <- bbInputs bbCtx !! i- -> Var [C nm'] i- | otherwise- -> error $ $(curLoc) ++ "You can only pass variables to function arguments in a higher-order primitive"- D (Decl n l') -> D (Decl n (map (map go *** map go) l'))- IF c t f -> IF c (map go t) (map go f)- SigD e' m -> SigD (map go e') m- BV t e' m -> BV t (map go e') m- _ -> e+ return bb' -- | Render a single template element renderElem :: Backend backend => BlackBoxContext -> Element -> State backend (Int -> Text)-renderElem b (D (Decl n (l:ls))) = do+renderElem b (Component (Decl n (l:ls))) = do (o,oTy,_) <- idToExpr <$> combineM (lineToIdentifier b) (return . lineToType b) l is <- mapM (fmap idToExpr . combineM (lineToIdentifier b) (return . lineToType b)) ls- -- let Just (templ,libs,imps,incM,pCtx)- let Just (templ,_,libs,imps,incM,pCtx) = IntMap.lookup n (bbFunctions b)+ let Just (templ0,_,libs,imps,inc,pCtx) = IntMap.lookup n (bbFunctions b) b' = pCtx { bbResult = (o,oTy), bbInputs = bbInputs pCtx ++ is }- templ' <- case templ of- Left t -> return t- Right (nm,ds) -> do block <- getMon $ blockDecl nm ds- return . parseFail . renderLazy $ (layoutPretty (LayoutOptions (AvailablePerLine 120 0.4)) block)- let t2 = setSimpleVar b' templ'- if verifyBlackBoxContext b' t2+ layoutOptions = LayoutOptions (AvailablePerLine 120 0.4)++ templ1 <-+ case templ0 of+ Left t ->+ return t+ Right (nm,ds) -> do+ block <- getMon (blockDecl nm ds)+ return $ N.BBTemplate+ $ parseFail+ $ renderLazy+ $ layoutPretty layoutOptions block++ templ4 <-+ case templ1 of+ N.BBFunction {} ->+ return templ1+ N.BBTemplate templ2 -> do+ (templ3, templDecls) <- setSym Backend.mkUniqueIdentifier b' templ2+ case templDecls of+ [] ->+ return (N.BBTemplate templ3)+ _ -> do+ nm1 <- Backend.mkUniqueIdentifier Basic "bb"+ nm2 <- Backend.mkUniqueIdentifier Basic "bb"+ let bbD = BlackBoxD nm1 libs imps inc (N.BBTemplate templ3) b'+ block <- getMon (blockDecl nm2 (templDecls ++ [bbD]))+ return $ N.BBTemplate+ $ parseFail+ $ renderLazy+ $ layoutPretty layoutOptions block++ if verifyBlackBoxContext b' templ4 then do- bb <- renderBlackBox libs imps incM t2 b'- return (renderLazy . layoutPretty (LayoutOptions (AvailablePerLine 120 0.4)) . bb)+ bb <- renderBlackBox libs imps inc templ4 b'+ return (renderLazy . layoutPretty layoutOptions . bb) else do sp <- getSrcSpan- throw (ClashException sp ($(curLoc) ++ "\nCan't match context:\n" ++ show b' ++ "\nwith template:\n" ++ show templ) Nothing)+ throw (ClashException sp ($(curLoc) ++ "\nCan't match context:\n"+ ++ show b' ++ "\nwith template:\n"+ ++ show templ0) Nothing) renderElem b (SigD e m) = do e' <- Text.concat <$> mapM (fmap ($ 0) . renderElem b) e@@ -287,6 +336,27 @@ t <- getMon (hdlSig e' ty) return (const (renderOneLine t)) +renderElem b (Period n) = do+ let (_, ty, _) = bbInputs b !! n+ case stripVoid ty of+ KnownDomain _ period _ _ _ _ ->+ return $ const $ Text.pack $ show period+ _ ->+ error $ $(curLoc) ++ "Period: Expected `KnownDomain` or `KnownConfiguration`, not: " ++ show ty++renderElem b (Tag n) = do+ let (_, ty, _) = bbInputs b !! n+ case stripVoid ty of+ KnownDomain dom _ _ _ _ _ ->+ return (const (Text.pack (Data.Text.unpack dom)))+ Reset dom ->+ return (const (Text.pack (Data.Text.unpack dom)))+ Clock dom ->+ return (const (Text.pack (Data.Text.unpack dom)))+ _ ->+ error $ $(curLoc) ++ "Tag: Expected `KnownDomain` or `KnownConfiguration`, not: " ++ show ty++ renderElem b (IF c t f) = do iw <- iwWidth syn <- hdlSyn@@ -296,11 +366,11 @@ check iw syn c' = case c' of (Size e) -> typeSize (lineToType b [e]) (Length e) -> case lineToType b [e] of- (Vector n _) -> n+ (Vector n _) -> n Void (Just (Vector n _)) -> n- _ -> 0 -- HACK: So we can test in splitAt if one of the+ _ -> 0 -- HACK: So we can test in splitAt if one of the -- vectors in the tuple had a zero length- (L n) -> case bbInputs b !! n of+ (Lit n) -> case bbInputs b !! n of (l,_,_) | Literal _ l' <- l -> case l' of@@ -324,31 +394,68 @@ (IsVar n) -> let (e,_,_) = bbInputs b !! n in case e of Identifier _ Nothing -> 1- _ -> 0+ _ -> 0 (IsLit n) -> let (e,_,_) = bbInputs b !! n in case e of- DataCon {} -> 1- Literal {} -> 1+ DataCon {} -> 1+ Literal {} -> 1 BlackBoxE {} -> 1- _ -> 0- (IsGated n) -> let (_,ty,_) = bbInputs b !! n- in case ty of- Clock _ _ Gated -> 1- _ -> 0- (IsSync n) -> let (_,ty,_) = bbInputs b !! n- in case ty of- Reset _ _ Synchronous -> 1- _ -> 0- (StrCmp [C t1] n) ->+ _ -> 0++ (IsActiveEnable n) ->+ let (e, ty, _) = bbInputs b !! n in+ case (e, ty) of+ (Literal Nothing (BoolLit True), Bool) -> 0+ -- TODO: Emit warning? If enable signal is inferred as always False,+ -- TODO: the component will never be enabled. This is probably not the+ -- TODO: user's intention.+ (Literal Nothing (BoolLit False), Bool) -> 1+ (_, Bool) -> 1+ _ ->+ error $ $(curLoc) ++ "IsActiveEnable: Expected Bool, not: " ++ show ty++ (ActiveEdge edgeRequested n) ->+ let (_, ty, _) = bbInputs b !! n in+ case stripVoid ty of+ KnownDomain _ _ edgeActual _ _ _ ->+ if edgeRequested == edgeActual then 1 else 0+ _ ->+ error $ $(curLoc) ++ "ActiveEdge: Expected `KnownDomain` or `KnownConfiguration`, not: " ++ show ty++ (IsSync n) ->+ let (_, ty, _) = bbInputs b !! n in+ case stripVoid ty of+ KnownDomain _ _ _ Synchronous _ _ -> 1+ KnownDomain _ _ _ Asynchronous _ _ -> 0+ _ -> error $ $(curLoc) ++ "IsSync: Expected `KnownDomain` or `KnownConfiguration`, not: " ++ show ty++ (IsInitDefined n) ->+ let (_, ty, _) = bbInputs b !! n in+ case stripVoid ty of+ KnownDomain _ _ _ _ Defined _ -> 1+ KnownDomain _ _ _ _ Unknown _ -> 0+ _ -> error $ $(curLoc) ++ "IsInitDefined: Expected `KnownDomain` or `KnownConfiguration`, not: " ++ show ty++ (IsActiveHigh n) ->+ let (_, ty, _) = bbInputs b !! n in+ case stripVoid ty of+ KnownDomain _ _ _ _ _ ActiveHigh -> 1+ KnownDomain _ _ _ _ _ ActiveLow -> 0+ _ -> error $ $(curLoc) ++ "IsActiveHigh: Expected `KnownDomain` or `KnownConfiguration`, not: " ++ show ty++ (StrCmp [Text t1] n) -> let (e,_,_) = bbInputs b !! n- in case exprToText e of+ in case exprToString e of Just t2- | t1 == t2 -> 1+ | t1 == Text.pack t2 -> 1 | otherwise -> 0 Nothing -> error $ $(curLoc) ++ "Expected a string literal: " ++ show e- (And es) -> if all (==1) (map (check iw syn) es)+ (And es) -> if all (/=0) (map (check iw syn) es) then 1 else 0+ CmpLE e1 e2 -> if check iw syn e1 <= check iw syn e2+ then 1+ else 0 _ -> error $ $(curLoc) ++ "IF: condition must be: SIZE, LENGTH, IW64, LIT, ISLIT, or ISARG" renderElem b e = fmap const (renderTag b e)@@ -362,7 +469,7 @@ idToExpr :: (Text,HWType) -> (Expr,HWType,Bool)-idToExpr (t,ty) = (Identifier t Nothing,ty,False)+idToExpr (t,ty) = (Identifier (Text.toStrict t) Nothing,ty,False) -- | Fill out the template corresponding to an output/input assignment of a -- component instantiation, and turn it into a single identifier so it can@@ -385,7 +492,7 @@ lineToType b [(TypElem t)] = case lineToType b [t] of Vector _ elTy -> elTy _ -> error $ $(curLoc) ++ "Element type selection of a non-vector type"-lineToType b [(IndexType (L n))] =+lineToType b [(IndexType (Lit n))] = case bbInputs b !! n of (Literal _ (NumLit n'),_,_) -> Index (fromInteger n') x -> error $ $(curLoc) ++ "Index type not given a literal: " ++ show x@@ -398,37 +505,44 @@ => BlackBoxContext -> Element -> State backend Text-renderTag _ (C t) = return t-renderTag b (O esc) = do+renderTag _ (Text t) = return t+renderTag b (Result esc) = do escape <- if esc then unextend else pure id- fmap (escape . renderOneLine) . getMon . expr False . fst $ bbResult b-renderTag b (I esc n) = do+ fmap (Text.fromStrict . escape . Text.toStrict . renderOneLine) . getMon . expr False . fst $ bbResult b+renderTag b (Arg esc n) = do let (e,_,_) = bbInputs b !! n escape <- if esc then unextend else pure id- (escape . renderOneLine) <$> getMon (expr False e)+ (Text.fromStrict . escape . Text.toStrict . renderOneLine) <$> getMon (expr False e) -renderTag b t@(Arg k n)+renderTag b (Const n) = do+ let (e,_,_) = bbInputs b !! n+ renderOneLine <$> getMon (expr False e)++renderTag b t@(ArgGen k n) | k == bbLevel b , let (e,_,_) = bbInputs b !! n = renderOneLine <$> getMon (expr False e) | otherwise = getMon (prettyElem t) -renderTag b (N n) = let (e,_,_) = bbInputs b !! n- in case exprToText e of- Just t -> return t- _ -> error $ $(curLoc) ++ "Expected a string literal: " ++ show e+renderTag b (Lit n) =+ renderOneLine <$> getMon (expr False (mkLit e))+ where+ (e,_,_) = bbInputs b !! n -renderTag b (L n) = let (e,_,_) = bbInputs b !! n- in renderOneLine <$> getMon (expr False (mkLit e))- where- mkLit (Literal (Just (Signed _,_)) i) = Literal Nothing i- mkLit (Literal (Just (Unsigned _,_)) i) = Literal Nothing i- mkLit (DataCon _ (DC (Void {}, _)) [Literal (Just (Signed _,_)) i]) = Literal Nothing i- mkLit (DataCon _ (DC (Void {}, _)) [Literal (Just (Unsigned _,_)) i]) = Literal Nothing i- mkLit i = i+ mkLit (Literal (Just (Signed _,_)) i) = Literal Nothing i+ mkLit (Literal (Just (Unsigned _,_)) i) = Literal Nothing i+ mkLit (DataCon _ (DC (Void {}, _)) [Literal (Just (Signed _,_)) i]) = Literal Nothing i+ mkLit (DataCon _ (DC (Void {}, _)) [Literal (Just (Unsigned _,_)) i]) = Literal Nothing i+ mkLit i = i -renderTag _ (Var [C t] _) = return t+renderTag b e@(Name _i) =+ case elementToText b e of+ Right s -> return s+ Left msg -> error $ $(curLoc) ++ unwords [ "Error when reducing to string"+ , "in ~NAME construct:", msg ]++renderTag _ (Var [Text t] _) = return t renderTag _ (Sym t _) = return t renderTag b (BV True es e) = do@@ -454,67 +568,155 @@ renderTag b (Err (Just n)) = let (_,ty,_) = bbInputs b !! n in renderOneLine <$> getMon (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]++renderTag b (Length e) = return . Text.pack . show . vecLen $ lineToType b [e] where- vecLen (Vector n _) = n- vecLen _ = error $ $(curLoc) ++ "vecLen of a non-vector type"-renderTag b (Depth e) = return . Text.pack . show . treeDepth $ lineToType b [e]+ vecLen (Vector n _) = n+ vecLen (Void (Just (Vector n _))) = n+ vecLen thing =+ error $ $(curLoc) ++ "vecLen of a non-vector type: " ++ show thing++renderTag b (Depth e) = return . Text.pack . show . treeDepth $ lineToType b [e] where- treeDepth (RTree n _) = n- treeDepth _ = error $ $(curLoc) ++ "treeDepth of a non-tree type"+ treeDepth (RTree n _) = n+ treeDepth (Void (Just (RTree n _))) = n+ treeDepth thing =+ error $ $(curLoc) ++ "treeDepth of a non-tree type: " ++ show thing++renderTag b (MaxIndex e) = return . Text.pack . show . vecLen $ lineToType b [e]+ where+ vecLen (Vector n _) = n-1+ vecLen thing =+ error $ $(curLoc) ++ "vecLen of a non-vector type: " ++ show thing+ renderTag b e@(TypElem _) = let ty = lineToType b [e] in renderOneLine <$> getMon (hdlType Internal ty) renderTag _ (Gen b) = renderOneLine <$> genStmt b-renderTag _ (GenSym [C t] _) = return t-renderTag b (Vars n) =- let (e,_,_) = bbInputs b !! n+renderTag _ (GenSym [Text t] _) = return t - go (Identifier i _) = [i]- go (DataCon _ _ es) = concatMap go es- go (DataTag _ e') = [either id id e']- go _ = []+-- Determine variables used in argument /n/.+renderTag b (Vars n) = return $ vars'+ where+ (e, _, _) = bbInputs b !! n+ vars = map Text.fromStrict (usedVariables e)+ vars' = Text.concat (map (Text.cons ',') vars) - vars = go e- in case vars of- [] -> return Text.empty- _ -> return (Text.concat $ map (Text.cons ',') vars)-renderTag b (IndexType (L n)) =+renderTag b (IndexType (Lit n)) = case bbInputs b !! n of (Literal _ (NumLit n'),_,_) -> let hty = Index (fromInteger n') in fmap renderOneLine (getMon (hdlType Internal hty)) x -> error $ $(curLoc) ++ "Index type not given a literal: " ++ show x renderTag b (FilePath e) = case e of- L n -> do+ Lit n -> do let (e',_,_) = bbInputs b !! n- e2 <- getMon (prettyElem e)- case e' of- BlackBoxE "GHC.CString.unpackCString#" _ _ _ _ bbCtx' _ -> case bbInputs bbCtx' of- [(Literal Nothing (StringLit _),_,_)] -> error $ $(curLoc) ++ "argument of ~FILEPATH:" ++ show e2 ++ "does not reduce to a string"- _ -> error $ $(curLoc) ++ "argument of ~FILEPATH:" ++ show e2 ++ "does not reduce to a string"- _ -> error $ $(curLoc) ++ "argument of ~FILEPATH:" ++ show e2 ++ "does not reduce to a string"+ case exprToString e' of+ Just s -> do+ s' <- addAndSetData s+ return (Text.pack (show s'))+ _ -> do+ e2 <- getMon (prettyElem e)+ error $ $(curLoc) ++ "argument of ~FILEPATH:" ++ show e2 ++ "does not reduce to a string" _ -> do e' <- getMon (prettyElem e) error $ $(curLoc) ++ "~FILEPATH expects a ~LIT[N] argument, but got: " ++ show e'-renderTag b IncludeName = case bbQsysIncName b of- Just nm -> return nm- _ -> error $ $(curLoc) ++ "~INCLUDENAME used where no 'qysInclude' was specified in the primitive definition"+renderTag b (IncludeName n) = case indexMaybe (bbQsysIncName b) n of+ Just nm -> return (Text.fromStrict nm)+ _ -> error $ $(curLoc) ++ "~INCLUDENAME[" ++ show n ++ "] does not correspond to any index of the 'includes' field that is specified in the primitive definition" renderTag b (OutputWireReg n) = case IntMap.lookup n (bbFunctions b) of Just (_,rw,_,_,_,_) -> case rw of {N.Wire -> return "wire"; N.Reg -> return "reg"} _ -> error $ $(curLoc) ++ "~OUTPUTWIREREG[" ++ show n ++ "] used where argument " ++ show n ++ " is not a function"+renderTag b (Repeat [es] [i]) = do+ i' <- Text.unpack <$> renderTag b i+ es' <- renderTag b es+ let i'' = case (readEither i' :: Either String Int) of+ Left msg -> error $ $(curLoc) ++ "Could not parse " ++ show i' ++ ". read reported: " ++ msg ++ "."+ Right n -> n+ return $ Text.concat $ take i'' $ repeat es'++renderTag b (DevNull es) = do+ _ <- mapM (renderElem b) es+ return $ Text.empty++renderTag b (Template filenameL sourceL) = case file of+ Left msg ->+ error $ $(curLoc) ++ unwords [ "Name or source in ~TEMPLATE construct"+ , "did not reduce to a string."+ , "'elementToText' reported:"+ , msg ]+ Right fstup@(filename, _source) -> do+ fs <- getMemoryDataFiles+ if elem filename (map fst fs)+ then if not (elem fstup fs)+ then error $ $(curLoc) ++ unwords [ "Multiple ~TEMPLATE constructs"+ , "specifiy the same filename"+ , "but different contents. Make"+ , "sure these names are unique." ]+ -- We replace the Template element with an empty constant, so nothing+ -- ends up in the generated HDL.+ else return (Text.pack "")+ else do+ addMemoryDataFile fstup+ return (Text.pack "")++ where+ file = do+ filename <- elementsToText b filenameL+ source <- elementsToText b sourceL+ return (Text.unpack filename, Text.unpack source)++renderTag b CompName = pure (Text.fromStrict (bbCompName b))+ renderTag _ e = do e' <- getMon (prettyElem e) error $ $(curLoc) ++ "Unable to evaluate: " ++ show e' -exprToText+-- | Compute string from a list of elements. Can interpret ~NAME string literals+-- on template level (constants).+elementsToText+ :: BlackBoxContext+ -> [Element]+ -> Either String Text+elementsToText bbCtx elements =+ foldl (\txt el -> case txt of+ -- Append new string (if no error) to string so far+ Right s -> (Text.append s) <$> elementToText bbCtx el+ -- If previous iteration resulted in an error: stop.+ msg -> msg) (Right $ Text.pack "") elements++elementToText+ :: BlackBoxContext+ -> Element+ -> Either String Text+elementToText bbCtx (Name n) = elementToText bbCtx (Lit n)+elementToText _bbCtx (Text t) = return $ t+elementToText bbCtx (Lit n) =+ case bbInputs bbCtx ^? element n of+ Just (e,_,_) ->+ case exprToString e of+ Just t ->+ Right $ Text.pack t+ Nothing ->+ Left $ $(curLoc) ++ unwords [ "Could not extract string from"+ , show e, "referred to by"+ , show (Lit n) ]+ Nothing ->+ Left $ $(curLoc) ++ unwords [ "Invalid literal", show (Lit n)+ , "used in blackbox with context:"+ , show bbCtx, "." ]++elementToText _bbCtx e = error $ "Unexpected string like: " ++ show e++-- | Extracts string from SSymbol or string literals+exprToString :: Expr- -> Maybe Text-exprToText (Literal _ (StringLit l)) = Just (Text.pack l)-exprToText (BlackBoxE "Clash.Promoted.Symbol.SSymbol" _ _ _ _ ctx _) =+ -> Maybe String+exprToString (Literal _ (StringLit l)) = Just l+exprToString (BlackBoxE "Clash.Promoted.Symbol.SSymbol" _ _ _ _ ctx _) = let (e',_,_) = head (bbInputs ctx)- in exprToText e'-exprToText (BlackBoxE "GHC.CString.unpackCString#" _ _ _ _ ctx _) =+ in exprToString e'+exprToString (BlackBoxE "GHC.CString.unpackCString#" _ _ _ _ ctx _) = let (e',_,_) = head (bbInputs ctx)- in exprToText e'-exprToText _ = Nothing+ in exprToString e'+exprToString _ = Nothing prettyBlackBox :: Monad m => BlackBoxTemplate@@ -524,18 +726,19 @@ prettyElem :: Monad m => Element -> Mon m Text-prettyElem (C t) = return t-prettyElem (D (Decl i args)) = do+prettyElem (Text t) = return t+prettyElem (Component (Decl i args)) = do args' <- mapM (\(a,b) -> (,) <$> prettyBlackBox a <*> prettyBlackBox b) args renderOneLine <$> (nest 2 (string "~INST" <+> int i <> line <> string "~OUTPUT" <+> string "=>" <+> string (fst (head args')) <+> string (snd (head args')) <+> string "~" <> line <> vcat (mapM (\(a,b) -> string "~INPUT" <+> string "=>" <+> string a <+> string b <+> string "~") (tail args'))) <> line <> string "~INST")-prettyElem (O b) = if b then return "~ERESULT" else return "~RESULT"-prettyElem (I b i) = renderOneLine <$> (if b then string "~EARG" else string "~ARG" <> brackets (int i))-prettyElem (L i) = renderOneLine <$> (string "~LIT" <> brackets (int i))-prettyElem (N i) = renderOneLine <$> (string "~NAME" <> brackets (int i))+prettyElem (Result b) = if b then return "~ERESULT" else return "~RESULT"+prettyElem (Arg b i) = renderOneLine <$> (if b then string "~EARG" else string "~ARG" <> brackets (int i))+prettyElem (Lit i) = renderOneLine <$> (string "~LIT" <> brackets (int i))+prettyElem (Const i) = renderOneLine <$> (string "~CONST" <> brackets (int i))+prettyElem (Name i) = renderOneLine <$> (string "~NAME" <> brackets (int i)) prettyElem (Var es i) = do es' <- prettyBlackBox es renderOneLine <$> (string "~VAR" <> brackets (string es') <> brackets (int i))@@ -550,7 +753,7 @@ e' <- prettyElem e renderOneLine <$> (string "~TYPEL" <> brackets (string e')) prettyElem CompName = return "~COMPNAME"-prettyElem IncludeName = return "~INCLUDENAME"+prettyElem (IncludeName i) = renderOneLine <$> ("~INCLUDENAME" <> brackets (int i)) prettyElem (IndexType e) = do e' <- prettyElem e renderOneLine <$> (string "~INDEXTYPE" <> brackets (string e'))@@ -563,6 +766,9 @@ prettyElem (Depth e) = do e' <- prettyElem e renderOneLine <$> (string "~DEPTH" <> brackets (string e'))+prettyElem (MaxIndex e) = do+ e' <- prettyElem e+ renderOneLine <$> (string "~MAXINDEX" <> brackets (string e')) prettyElem (FilePath e) = do e' <- prettyElem e renderOneLine <$> (string "~FILE" <> brackets (string e'))@@ -577,13 +783,18 @@ string "~ELSE" <> string esF' <> string "~FI")-prettyElem (And es) =- (renderLazy . layoutCompact) <$>- (brackets (tupled $ mapM (string <=< prettyElem) es))+prettyElem (And es) = renderOneLine <$>+ (string "~AND" <>+ (brackets (hcat (punctuate comma (mapM (string <=< prettyElem) es)))))+prettyElem (CmpLE e1 e2) = do+ e1' <- prettyElem e1+ e2' <- prettyElem e2+ renderOneLine <$> (string "~CMPLE" <> brackets (string e1')+ <> brackets (string e2')) prettyElem IW64 = return "~IW64" prettyElem (HdlSyn s) = case s of Vivado -> return "~VIVADO"- _ -> return "~OTHERSYN"+ _ -> return "~OTHERSYN" prettyElem (BV b es e) = do es' <- prettyBlackBox es e' <- prettyBlackBox [e]@@ -596,14 +807,39 @@ renderOneLine <$> (string "~SEL" <> brackets (string e') <> brackets (int i)) prettyElem (IsLit i) = renderOneLine <$> (string "~ISLIT" <> brackets (int i)) prettyElem (IsVar i) = renderOneLine <$> (string "~ISVAR" <> brackets (int i))-prettyElem (IsGated i) = renderOneLine <$> (string "~ISGATED" <> brackets (int i))+prettyElem (IsActiveHigh i) = renderOneLine <$> (string "~ISACTIVEHIGH" <> brackets (int i))+prettyElem (IsActiveEnable i) = renderOneLine <$> (string "~ISACTIVEENABLE" <> brackets (int i))++-- Domain attributes:+prettyElem (Tag i) = renderOneLine <$> (string "~TAG" <> brackets (int i))+prettyElem (Period i) = renderOneLine <$> (string "~PERIOD" <> brackets (int i))+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))+ prettyElem (StrCmp es i) = do es' <- prettyBlackBox es renderOneLine <$> (string "~STRCMP" <> brackets (string es') <> brackets (int i)) prettyElem (GenSym es i) = do es' <- prettyBlackBox es renderOneLine <$> (string "~GENSYM" <> brackets (string es') <> brackets (int i))+prettyElem (Repeat [es] [i]) = do+ es' <- prettyElem es+ i' <- prettyElem i+ renderOneLine+ <$> string "~REPEAT"+ <> brackets (string es')+ <> brackets (string i')+prettyElem (Repeat es i) = error $ $(curLoc)+ ++ "Unexpected number of arguments in either "+ ++ show es+ ++ " or "+ ++ show i+ ++ ". Both lists are expected to have a single element."+prettyElem (DevNull es) = do+ es' <- mapM prettyElem es+ renderOneLine <$> (string "~DEVNULL" <> brackets (string $ Text.concat es'))+ prettyElem (SigD es mI) = do es' <- prettyBlackBox es renderOneLine <$>@@ -612,24 +848,167 @@ mI) prettyElem (Vars i) = renderOneLine <$> (string "~VARS" <> brackets (int i)) prettyElem (OutputWireReg i) = renderOneLine <$> (string "~RESULTWIREREG" <> brackets (int i))-prettyElem (Arg n x) =+prettyElem (ArgGen n x) = renderOneLine <$> (string "~ARGN" <> brackets (int n) <> brackets (int x))+prettyElem (Template bbname source) = do+ bbname' <- mapM prettyElem bbname+ source' <- mapM prettyElem source+ renderOneLine <$> (string "~TEMPLATE"+ <> brackets (string $ Text.concat bbname')+ <> brackets (string $ Text.concat source')) -usedArguments :: BlackBoxTemplate- -> [Int]-usedArguments = nub . concatMap go+-- | Recursively walk @Element@, applying @f@ to each element in the tree.+walkElement+ :: (Element -> Maybe a)+ -> Element+ -> [a]+walkElement f el = maybeToList (f el) ++ walked where- go x = case x of- D (Decl i args) -> i : concatMap (\(a,b) -> usedArguments a ++ usedArguments b) args- I _ i -> [i]- L i -> [i]- N i -> [i]- Var _ i -> [i]- IndexType e -> go e- FilePath e -> go e- IF b esT esF -> go b ++ usedArguments esT ++ usedArguments esF- SigD es _ -> usedArguments es- BV _ es _ -> usedArguments es- StrCmp _ i -> [i]- GenSym es _ -> usedArguments es- _ -> []+ go = walkElement f+ walked =+ -- TODO: alternatives are purposely explicitly listed in case @Element@+ -- TODO: gets extended. This way, GHC will complain about missing+ -- TODO: alternatives. It would probably be better to replace it by Lens+ -- TODO: logic?+ case el of+ Component (Decl _ args) ->+ concatMap (\(a,b) -> concatMap go a ++ concatMap go b) args+ IndexType e -> go e+ FilePath e -> go e+ Template bbname source ->+ concatMap go bbname ++ concatMap go source+ IF b esT esF ->+ go b ++ concatMap go esT ++ concatMap go esF+ SigD es _ -> concatMap go es+ BV _ es _ -> concatMap go es+ GenSym es _ -> concatMap go es+ DevNull es -> concatMap go es+ Text _ -> []+ Result _ -> []+ Arg _ _ -> []+ ArgGen _ _ -> []+ Const _ -> []+ Lit _ -> []+ Name _ -> []+ Var es _ -> concatMap go es+ Sym _ _ -> []+ Typ _ -> []+ TypM _ -> []+ Err _ -> []+ TypElem e -> go e+ CompName -> []+ IncludeName _ -> []+ Size e -> go e+ Length e -> go e+ Depth e -> go e+ MaxIndex e -> go e+ Gen _ -> []+ And es -> concatMap go es+ CmpLE e1 e2 -> go e1 ++ go e2+ IW64 -> []+ HdlSyn _ -> []+ Sel e _ -> go e+ IsLit _ -> []+ IsVar _ -> []+ Tag _ -> []+ Period _ -> []+ ActiveEdge _ _ -> []+ IsSync _ -> []+ IsInitDefined _ -> []+ IsActiveHigh _ -> []+ IsActiveEnable _ -> []+ StrCmp es _ -> concatMap go es+ OutputWireReg _ -> []+ Vars _ -> []+ Repeat es1 es2 ->+ concatMap go es1 ++ concatMap go es2++-- | Determine variables used in an expression. Used for VHDL sensitivity list.+-- Also see: https://github.com/clash-lang/clash-compiler/issues/365+usedVariables :: Expr -> [Identifier]+usedVariables (Identifier i _) = [i]+usedVariables (DataCon _ _ es) = concatMap usedVariables es+usedVariables (DataTag _ e') = [either id id e']+usedVariables (Literal {}) = []+usedVariables (ConvBV _ _ _ e') = usedVariables e'+usedVariables (IfThenElse e1 e2 e3) = concatMap usedVariables [e1,e2,e3]+usedVariables (BlackBoxE _ _ _ _ t bb _) = nub (sList ++ sList')+ where+ matchArg (Arg _ i) = Just i+ matchArg _ = Nothing++ matchVar (Var [Text v] _) = Just (Text.toStrict v)+ matchVar _ = Nothing++ t' = onBlackBox id (\_ _ _ -> []) t+ usedIs = mapMaybe (indexMaybe (bbInputs bb)) (concatMap (walkElement matchArg) t')+ sList = concatMap (\(e,_,_) -> usedVariables e) usedIs+ sList' = concatMap (walkElement matchVar) t'++-- | Collect arguments (e.g., ~ARG, ~LIT) used in this blackbox+usedArguments :: N.BlackBox -> [Int]+usedArguments (N.BBFunction _nm _hsh (N.TemplateFunction k _ _)) = k+usedArguments (N.BBTemplate t) = nub (concatMap (walkElement matchArg) t)+ where+ matchArg =+ \case+ Arg _ i -> Just i+ Component (Decl i _) -> Just i+ Const i -> Just i+ IsLit i -> Just i+ IsActiveEnable i -> Just i+ Lit i -> Just i+ Name i -> Just i+ Var _ i -> Just i++ -- Domain properties (only need type):+ IsInitDefined _ -> Nothing+ ActiveEdge _ _ -> Nothing+ IsSync _ -> Nothing+ Period _ -> Nothing+ Tag _ -> Nothing++ -- Others. Template tags only using types of arguments can be considered+ -- "not used".+ And _ -> Nothing+ ArgGen _ _ -> Nothing+ BV _ _ _ -> Nothing+ CmpLE _ _ -> Nothing+ CompName -> Nothing+ Depth _ -> Nothing+ DevNull _ -> Nothing+ Err _ -> Nothing+ FilePath _ -> Nothing+ Gen _ -> Nothing+ GenSym _ _ -> Nothing+ HdlSyn _ -> Nothing+ IF _ _ _ -> Nothing+ IncludeName _ -> Nothing+ IndexType _ -> Nothing+ IsActiveHigh _ -> Nothing+ IsVar _ -> Nothing+ IW64 -> Nothing+ Length _ -> Nothing+ MaxIndex _ -> Nothing+ OutputWireReg _ -> Nothing+ Repeat _ _ -> Nothing+ Result _ -> Nothing+ Sel _ _ -> Nothing+ SigD _ _ -> Nothing+ Size _ -> Nothing+ StrCmp _ _ -> Nothing+ Sym _ _ -> Nothing+ Template _ _ -> Nothing+ Text _ -> Nothing+ Typ _ -> Nothing+ TypElem _ -> Nothing+ TypM _ -> Nothing+ Vars _ -> Nothing++onBlackBox+ :: (BlackBoxTemplate -> r)+ -> (N.BBName -> N.BBHash -> N.TemplateFunction -> r)+ -> N.BlackBox+ -> r+onBlackBox f _ (N.BBTemplate t) = f t+onBlackBox _ g (N.BBFunction n h t) = g n h t
src/Clash/Netlist/Id.hs view
@@ -17,27 +17,29 @@ ) where -#ifndef MIN_VERSION_text-#error MIN_VERSION_text undefined-#endif--import Data.Char (isAsciiLower,isAsciiUpper,isDigit)-import Data.Text.Lazy as Text+import Clash.Annotations.Primitive (HDL (..))+import Data.Char (isAsciiLower,isAsciiUpper,isDigit)+import Data.Text as Text data IdType = Basic | Extended -mkBasicId' :: Bool- -> Text- -> Text-mkBasicId' tupEncode = stripMultiscore . stripLeading . zEncode tupEncode+mkBasicId'+ :: HDL+ -> Bool+ -> Text+ -> Text+mkBasicId' hdl tupEncode = stripMultiscore hdl . stripLeading hdl . zEncode hdl tupEncode where- stripLeading = Text.dropWhile (`elem` ('_':['0'..'9']))- stripMultiscore = Text.concat- . Prelude.map (\cs -> case Text.head cs of- '_' -> "_"- _ -> cs- )- . Text.group+ stripLeading VHDL = Text.dropWhile (`elem` ('_':['0'..'9']))+ stripLeading _ = Text.dropWhile (`elem` ('$':['0'..'9']))+ stripMultiscore VHDL+ = Text.concat+ . Prelude.map (\cs -> case Text.head cs of+ '_' -> "_"+ _ -> cs+ )+ . Text.group+ stripMultiscore _ = id stripDollarPrefixes :: Text -> Text stripDollarPrefixes = stripWorkerPrefix . stripSpecPrefix . stripConPrefix@@ -47,10 +49,6 @@ Just k -> takeWhileEnd (/= '_') k Nothing -> t -#if !MIN_VERSION_text(1,2,2)- takeWhileEnd p = Text.reverse . Text.takeWhile p . Text.reverse-#endif- stripWorkerPrefix t = case Text.stripPrefix "$w" t of Just k -> k Nothing -> t@@ -67,38 +65,40 @@ type UserString = Text -- As the user typed it type EncodedString = Text -- Encoded form -zEncode :: Bool -> UserString -> EncodedString-zEncode False cs = go (uncons cs)+zEncode :: HDL -> Bool -> UserString -> EncodedString+zEncode hdl False cs = go (uncons cs) where go Nothing = empty- go (Just (c,cs')) = append (encodeDigitCh c) (go' $ uncons cs')+ go (Just (c,cs')) = append (encodeDigitCh hdl c) (go' $ uncons cs') go' Nothing = empty- go' (Just (c,cs')) = append (encodeCh c) (go' $ uncons cs')+ go' (Just (c,cs')) = append (encodeCh hdl c) (go' $ uncons cs') -zEncode True cs = case maybeTuple cs of+zEncode hdl True cs = case maybeTuple cs of Just (n,cs') -> append n (go' (uncons cs')) Nothing -> go (uncons cs) where go Nothing = empty- go (Just (c,cs')) = append (encodeDigitCh c) (go' $ uncons cs')+ go (Just (c,cs')) = append (encodeDigitCh hdl c) (go' $ uncons cs') go' Nothing = empty go' (Just (c,cs')) = case maybeTuple (cons c cs') of Just (n,cs2) -> append n (go' $ uncons cs2)- Nothing -> append (encodeCh c) (go' $ uncons cs')+ Nothing -> append (encodeCh hdl c) (go' $ uncons cs') -encodeDigitCh :: Char -> EncodedString-encodeDigitCh c | isDigit c = Text.empty -- encodeAsUnicodeChar c-encodeDigitCh c = encodeCh c+encodeDigitCh :: HDL -> Char -> EncodedString+encodeDigitCh _ c | isDigit c = Text.empty -- encodeAsUnicodeChar c+encodeDigitCh hdl c = encodeCh hdl c -encodeCh :: Char -> EncodedString-encodeCh c | unencodedChar c = singleton c -- Common case first- | otherwise = Text.empty+encodeCh :: HDL -> Char -> EncodedString+encodeCh hdl c | unencodedChar hdl c = singleton c -- Common case first+ | otherwise = Text.empty -unencodedChar :: Char -> Bool -- True for chars that don't need encoding-unencodedChar c = or [ isAsciiLower c- , isAsciiUpper c- , isDigit c- , c == '_']+unencodedChar :: HDL -> Char -> Bool -- True for chars that don't need encoding+unencodedChar hdl c =+ or [ isAsciiLower c+ , isAsciiUpper c+ , isDigit c+ , if hdl == VHDL then c == '_' else c `elem` ['_','$']+ ] maybeTuple :: UserString -> Maybe (EncodedString,UserString) maybeTuple "(# #)" = Just ("Unit",empty)
src/Clash/Netlist/Types.hs view
@@ -1,79 +1,143 @@ {-| Copyright : (C) 2012-2016, University of Twente,- 2017 , Myrtle Software Ltd, Google Inc.+ 2017 , Myrtle Software Ltd,+ 2017-2018, Google Inc. License : BSD2 (see the file LICENSE) Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com> Type and instance definitions for Netlist modules -} +{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE DeriveLift #-}+{-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE RankNTypes #-} {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE DeriveDataTypeable #-} -{-# OPTIONS_GHC -Wno-orphans #-}+-- since GHC 8.6 we can haddock individual contructor fields \o/+#if __GLASGOW_HASKELL__ >= 806+#define FIELD ^+#endif module Clash.Netlist.Types- (Declaration (..,NetDecl), module Clash.Netlist.Types)+ ( Declaration (..,NetDecl)+ , module Clash.Netlist.Types+ ) where import Control.DeepSeq-import Control.Monad.State.Strict (MonadIO, MonadState, StateT)-import Data.Hashable-import Data.HashMap.Lazy (HashMap)-import Data.IntMap.Lazy (IntMap, empty)-import qualified Data.Text as S-import Data.Text.Lazy (Text, pack)+#if !MIN_VERSION_base(4,13,0)+import Control.Monad.Fail (MonadFail)+#endif+import Control.Monad.Reader (ReaderT, MonadReader)+import Control.Monad.State as Lazy (State)+import Control.Monad.State.Strict as Strict+ (State,MonadIO, MonadState, StateT)+import Data.Bits (testBit)+import Data.Binary (Binary(..))+import Data.Hashable (Hashable)+import Data.HashMap.Strict (HashMap)+import Data.IntMap (IntMap, empty)+import qualified Data.Set as Set+import Data.Text (Text, pack)+import Data.Typeable (Typeable)+import Data.Text.Prettyprint.Doc.Extra (Doc) import GHC.Generics (Generic)-import Unbound.Generics.LocallyNameless (Fresh, FreshMT)+import Language.Haskell.TH.Syntax (Lift) import SrcLoc (SrcSpan) import Clash.Annotations.TopEntity (TopEntity)-import Clash.Core.Term (TmOccName)+import Clash.Backend (Backend) import Clash.Core.Type (Type)-import Clash.Core.TyCon (TyCon, TyConOccName)-import Clash.Driver.Types (BindingMap)-import Clash.Netlist.BlackBox.Types+import Clash.Core.Var (Attr')+import Clash.Core.TyCon (TyConMap)+import Clash.Core.VarEnv (VarEnv)+import Clash.Driver.Types (BindingMap, ClashOpts)+import Clash.Netlist.BlackBox.Types (BlackBoxTemplate) import Clash.Netlist.Id (IdType)-import Clash.Primitives.Types (PrimMap)-import Clash.Signal.Internal (ClockKind, ResetKind)-import Clash.Util+import Clash.Primitives.Types (CompiledPrimMap)+import Clash.Signal.Internal+ (ResetPolarity, ActiveEdge, ResetKind, InitBehavior)+import Clash.Util (makeLenses) +import Clash.Annotations.BitRepresentation.Internal+ (CustomReprs, DataRepr', ConstrRepr')+ -- | Monad that caches generated components (StateT) and remembers hidden inputs -- of components that are being generated (WriterT) newtype NetlistMonad a =- NetlistMonad { runNetlist :: StateT NetlistState (FreshMT IO) a }- deriving (Functor, Monad, Applicative, MonadState NetlistState, Fresh, MonadIO)+ NetlistMonad { runNetlist :: StateT NetlistState (ReaderT NetlistEnv IO) a }+ deriving newtype (Functor, Monad, Applicative, MonadReader NetlistEnv,+ MonadState NetlistState, MonadIO, MonadFail) +type HWMap = HashMap Type (Either String FilteredHWType)++-- | Environment of the NetlistMonad+data NetlistEnv+ = NetlistEnv+ { _prefixName :: Identifier+ -- ^ Prefix for instance/register names+ , _suffixName :: Identifier+ -- ^ Postfix for instance/register names+ , _setName :: Maybe Identifier+ -- ^ (Maybe) user given instance/register name+ }+ -- | State of the NetlistMonad data NetlistState = NetlistState- { _bindings :: BindingMap -- ^ Global binders- , _varCount :: !Int -- ^ Number of signal declarations- , _components :: HashMap TmOccName (SrcSpan,Component) -- ^ Cached components- , _primitives :: PrimMap BlackBoxTemplate -- ^ Primitive Definitions- , _typeTranslator :: HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType)+ { _bindings :: BindingMap+ -- ^ Global binders+ , _varCount :: !Int+ -- ^ Number of signal declarations+ , _components :: VarEnv ([Bool],SrcSpan,HashMap Identifier Word,Component)+ -- ^ Cached components+ , _primitives :: CompiledPrimMap+ -- ^ Primitive Definitions+ , _typeTranslator :: CustomReprs -> TyConMap -> Type+ -> Strict.State HWMap (Maybe (Either String FilteredHWType)) -- ^ Hardcoded Type -> HWType translator- , _tcCache :: HashMap TyConOccName TyCon -- ^ TyCon cache+ , _tcCache :: TyConMap+ -- ^ TyCon cache , _curCompNm :: !(Identifier,SrcSpan)- , _dataFiles :: [(String,FilePath)] , _intWidth :: Int , _mkIdentifierFn :: IdType -> Identifier -> Identifier , _extendIdentifierFn :: IdType -> Identifier -> Identifier -> Identifier- , _seenIds :: [Identifier]- , _seenComps :: [Identifier]- , _componentNames :: HashMap TmOccName Identifier- , _topEntityAnns :: HashMap TmOccName (Type, Maybe TopEntity)+ , _seenIds :: HashMap Identifier Word+ , _seenComps :: HashMap Identifier Word+ , _seenPrimitives :: Set.Set Text+ -- ^ Keeps track of invocations of ´mkPrimitive´. It is currently used to+ -- filter duplicate warning invocations for dubious blackbox instantiations,+ -- see GitHub pull request #286.+ , _componentNames :: VarEnv Identifier+ , _topEntityAnns :: VarEnv (Type, Maybe TopEntity) , _hdlDir :: FilePath , _curBBlvl :: Int -- ^ The current scoping level assigned to black box contexts+ , _componentPrefix :: (Maybe Identifier,Maybe Identifier)+ -- ^ Prefix for top-level components, and prefix for all other components+ , _customReprs :: CustomReprs+ , _clashOpts :: ClashOpts+ -- ^ Settings Clash was called with+ , _isTestBench :: Bool+ -- ^ Whether we're compiling a testbench (suppresses some warnings)+ , _backEndITE :: Bool+ -- ^ Whether the backend supports ifThenElse expressions+ , _htyCache :: HWMap } -- | Signal reference type Identifier = Text +type Comment = Text+ -- | Component: base unit of a Netlist data Component = Component@@ -92,71 +156,138 @@ -- | Size indication of a type (e.g. bit-size or number of elements) type Size = Int +type IsVoid = Bool++-- | Tree structure indicating which constructor fields were filtered from+-- a type due to them being void. We need this information to generate stable+-- and/or user-defined port mappings.+data FilteredHWType =+ FilteredHWType HWType [[(IsVoid, FilteredHWType)]]+ deriving (Eq, Show)+ -- | Representable hardware types data HWType = Void (Maybe HWType) -- ^ Empty type. @Just Size@ for "empty" Vectors so we can still have- -- primitives that can traverse e.g. Vectors of unit and know the lenght of+ -- primitives that can traverse e.g. Vectors of unit and know the length of -- that vector.- | String -- ^ String type- | Bool -- ^ Boolean type- | Bit -- ^ Bit type- | BitVector !Size -- ^ BitVector of a specified size- | Index !Integer -- ^ Unsigned integer with specified (exclusive) upper bounder- | Signed !Size -- ^ Signed integer of a specified size- | Unsigned !Size -- ^ Unsigned integer of a specified size- | Vector !Size !HWType -- ^ Vector type- | RTree !Size !HWType -- ^ RTree type- | Sum !Identifier [Identifier] -- ^ Sum type: Name and Constructor names- | Product !Identifier [HWType] -- ^ Product type: Name and field types- | SP !Identifier [(Identifier,[HWType])] -- ^ Sum-of-Product type: Name and Constructor names + field types- | Clock !Identifier !Integer !ClockKind -- ^ Clock type with specified name and period- | Reset !Identifier !Integer !ResetKind -- ^ Reset type corresponding to clock with a specified name and period- deriving (Eq,Ord,Show,Generic)--instance Hashable ClockKind-instance Hashable ResetKind+ | String+ -- ^ String type+ | Integer+ -- ^ Integer type (for parameters only)+ | Bool+ -- ^ Boolean type+ | Bit+ -- ^ Bit type+ | BitVector !Size+ -- ^ BitVector of a specified size+ | Index !Integer+ -- ^ Unsigned integer with specified (exclusive) upper bounder+ | Signed !Size+ -- ^ Signed integer of a specified size+ | Unsigned !Size+ -- ^ Unsigned integer of a specified size+ | Vector !Size !HWType+ -- ^ Vector type+ | RTree !Size !HWType+ -- ^ RTree type+ | Sum !Identifier [Identifier]+ -- ^ Sum type: Name and Constructor names+ | Product !Identifier (Maybe [Text]) [HWType]+ -- ^ Product type: Name, field names, and field types. Field names will be+ -- populated when using records.+ | SP !Identifier [(Identifier,[HWType])]+ -- ^ Sum-of-Product type: Name and Constructor names + field types+ | Clock !Identifier+ -- ^ Clock type corresponding to domain /Identifier/+ | Reset !Identifier+ -- ^ Reset type corresponding to domain /Identifier/+ | BiDirectional !PortDirection !HWType+ -- ^ Tagging type indicating a bidirectional (inout) port+ | CustomSP !Identifier !DataRepr' !Size [(ConstrRepr', Identifier, [HWType])]+ -- ^ Same as Sum-Of-Product, but with a user specified bit representation. For+ -- more info, see: Clash.Annotations.BitRepresentations.+ | CustomSum !Identifier !DataRepr' !Size [(ConstrRepr', Identifier)]+ -- ^ Same as Sum, but with a user specified bit representation. For more info,+ -- see: Clash.Annotations.BitRepresentations.+ | Annotated [Attr'] !HWType+ -- ^ Annotated with HDL attributes+ | KnownDomain !Identifier !Integer !ActiveEdge !ResetKind !InitBehavior !ResetPolarity+ -- ^ Domain name, period, active edge, reset kind, initial value behavior+ deriving (Eq, Ord, Show, Generic, NFData, Hashable) -instance Hashable HWType-instance NFData HWType+-- | Extract hardware attributes from Annotated. Returns an empty list if+-- non-Annotated given or if Annotated has an empty list of attributes.+hwTypeAttrs :: HWType -> [Attr']+hwTypeAttrs (Annotated attrs _type) = attrs+hwTypeAttrs _ = [] -- | Internals of a Component data Declaration- = Assignment !Identifier !Expr- -- ^ Signal assignment:- --- -- * Signal to assign- --- -- * Assigned expression- | CondAssignment !Identifier !HWType !Expr !HWType [(Maybe Literal,Expr)]- -- ^ Conditional signal assignment:- --- -- * Signal to assign- --- -- * Type of the result/alternatives- --- -- * Scrutinized expression- --- -- * Type of the scrutinee- --- -- * List of: (Maybe expression scrutinized expression is compared with,RHS of alternative)- | InstDecl (Maybe Identifier) !Identifier !Identifier [(Expr,PortDirection,HWType,Expr)] -- ^ Instantiation of another component- | BlackBoxD !S.Text [BlackBoxTemplate] [BlackBoxTemplate] (Maybe ((S.Text,S.Text),BlackBoxTemplate)) !BlackBoxTemplate BlackBoxContext -- ^ Instantiation of blackbox declaration- | NetDecl' (Maybe Identifier) WireOrReg !Identifier (Either Identifier HWType) -- ^ Signal declaration+ -- | Signal assignment+ = Assignment+ !Identifier -- FIELD Signal to assign+ !Expr -- FIELD 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)++ -- | Instantiation of another component:+ | InstDecl+ EntityOrComponent -- FIELD Whether it's an entity or a component+ (Maybe Comment) -- FIELD Comment 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)+ [(Expr,PortDirection,HWType,Expr)] -- FIELD Ports (port name, port direction, type, assignment)++ -- | 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++ -- | 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 Identifier HWType) -- FIELD Pointer to type of signal or type of signal+ -- ^ Signal declaration+ | TickDecl Comment+ -- ^ HDL tick corresponding to a Core tick deriving Show +data EntityOrComponent = Entity | Comp | Empty+ deriving Show+ data WireOrReg = Wire | Reg deriving (Show,Generic) instance NFData WireOrReg -pattern NetDecl :: Maybe Identifier -> Identifier -> HWType -> Declaration+pattern NetDecl+ :: Maybe Comment+ -- ^ Note; will be inserted as a comment in target hdl+ -> Identifier+ -- ^ Name of signal+ -> HWType+ -- ^ Type of signal+ -> Declaration pattern NetDecl note d ty <- NetDecl' note Wire d (Right ty) where NetDecl note d ty = NetDecl' note Wire d (Right ty) data PortDirection = In | Out- deriving Show+ deriving (Eq,Ord,Show,Generic,NFData,Hashable) instance NFData Declaration where rnf a = a `seq` ()@@ -164,9 +295,10 @@ -- | Expression Modifier data Modifier = Indexed (HWType,Int,Int) -- ^ Index the expression: (Type of expression,DataCon tag,Field Tag)- | DC (HWType,Int) -- ^ See expression in a DataCon context: (Type of the expression, DataCon tag)- | VecAppend -- ^ See the expression in the context of a Vector append operation- | RTreeAppend -- ^ See the expression in the context of a Tree append operation+ | DC (HWType,Int) -- ^ See expression in a DataCon context: (Type of the expression, DataCon tag)+ | VecAppend -- ^ See the expression in the context of a Vector append operation+ | RTreeAppend -- ^ See the expression in the context of a Tree append operation+ | Sliced (HWType,Int,Int) -- ^ Slice the identifier of the given type from start to end | Nested Modifier Modifier deriving Show @@ -175,18 +307,29 @@ = Literal !(Maybe (HWType,Size)) !Literal -- ^ Literal expression | DataCon !HWType !Modifier [Expr] -- ^ DataCon application | Identifier !Identifier !(Maybe Modifier) -- ^ Signal reference- | DataTag !HWType !(Either Identifier Identifier) -- ^ @Left e@: tagToEnum#, @Right e@: dataToTag#- | BlackBoxE !S.Text [BlackBoxTemplate] [BlackBoxTemplate] (Maybe ((S.Text,S.Text),BlackBoxTemplate)) !BlackBoxTemplate !BlackBoxContext !Bool -- ^ Instantiation of a BlackBox expression+ | DataTag !HWType !(Either Identifier Identifier) -- ^ @Left e@: tagToEnum\#, @Right e@: dataToTag\#++ -- | 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 paretheses? | ConvBV (Maybe Identifier) HWType Bool Expr+ | IfThenElse Expr Expr Expr deriving Show -- | Literals used in an expression data Literal- = NumLit !Integer -- ^ Number literal- | BitLit !Bit -- ^ Bit literal- | BoolLit !Bool -- ^ Boolean literal- | VecLit [Literal] -- ^ Vector literal- | StringLit !String -- ^ String literal+ = NumLit !Integer -- ^ Number literal+ | BitLit !Bit -- ^ Bit literal+ | BitVecLit !Integer !Integer -- ^ BitVector literal+ | BoolLit !Bool -- ^ Boolean literal+ | VecLit [Literal] -- ^ Vector literal+ | StringLit !String -- ^ String literal deriving (Eq,Show) -- | Bit literal@@ -195,33 +338,84 @@ | L -- ^ Low | U -- ^ Undefined | Z -- ^ High-impedance- deriving (Eq,Show)+ deriving (Eq,Show,Typeable,Lift) ++toBit :: Integer -- ^ mask+ -> Integer -- ^ value+ -> Bit+toBit m i = if testBit m 0+ then U+ else if testBit i 0 then H else L+ -- | Context used to fill in the holes of a BlackBox template data BlackBoxContext = Context- { bbResult :: (Expr,HWType) -- ^ Result name and type+ { bbName :: Text -- ^ Blackbox function name (for error reporting)+ , bbResult :: (Expr,HWType) -- ^ Result name and type , bbInputs :: [(Expr,HWType,Bool)] -- ^ Argument names, types, and whether it is a literal- , bbFunctions :: IntMap (Either BlackBoxTemplate (Identifier,[Declaration])+ , bbFunctions :: IntMap (Either BlackBox (Identifier,[Declaration]) ,WireOrReg ,[BlackBoxTemplate] ,[BlackBoxTemplate]- ,Maybe ((S.Text,S.Text),BlackBoxTemplate),BlackBoxContext)+ ,[((Text,Text),BlackBox)]+ ,BlackBoxContext) -- ^ Function arguments (subset of inputs): -- -- * ( Blackbox Template -- , Whether the result should be /reg/ or a /wire/ (Verilog only) -- , Partial Blackbox Context -- )- , bbQsysIncName :: Maybe Identifier+ , bbQsysIncName :: [Identifier] , bbLevel :: Int -- ^ The scoping level this context is associated with, ensures that -- @~ARGN[k][n]@ holes are only filled with values from this context if @k@ -- is equal to the scoping level of this context.+ , bbCompName :: Identifier+ -- ^ The component the BlackBox is instantiated in } deriving Show -emptyBBContext :: BlackBoxContext-emptyBBContext = Context (Identifier (pack "__EMPTY__") Nothing, Void Nothing) [] empty Nothing (-1)+type BBName = String+type BBHash = Int +data BlackBox+ = BBTemplate BlackBoxTemplate+ | BBFunction BBName BBHash TemplateFunction+ deriving (Generic, NFData, Binary)++data TemplateFunction where+ TemplateFunction+ :: [Int]+ -> (BlackBoxContext -> Bool)+ -> (forall s . Backend s => BlackBoxContext -> Lazy.State s Doc)+ -> TemplateFunction++instance Show BlackBox where+ show (BBTemplate t) = show t+ show (BBFunction nm hsh _) =+ "<TemplateFunction(nm=" ++ show nm ++ ", hash=" ++ show hsh ++ ")>"++instance NFData TemplateFunction where+ rnf (TemplateFunction is f _) = rnf is `seq` f `seq` ()++-- | __NB__: serialisation doesn't preserve the embedded function+instance Binary TemplateFunction where+ put (TemplateFunction is _ _ ) = put is+ get = (\is -> TemplateFunction is err err) <$> get+ where err = const $ error "TemplateFunction functions can't be preserved by serialisation"++emptyBBContext :: Text -> BlackBoxContext+emptyBBContext n+ = Context+ { bbName = n+ , bbResult = (Identifier (pack "__EMPTY__") Nothing, Void Nothing)+ , bbInputs = []+ , bbFunctions = empty+ , bbQsysIncName = []+ , bbLevel = (-1)+ , bbCompName = pack "__NOCOMPNAME__"+ }++makeLenses ''NetlistEnv makeLenses ''NetlistState
+ src/Clash/Netlist/Types.hs-boot view
@@ -0,0 +1,22 @@+{-|+ Copyright : (C) 2018, Google Inc+ License : BSD2 (see the file LICENSE)+ Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>+-}++{-# LANGUAGE RoleAnnotations #-}++module Clash.Netlist.Types where++import Data.Text (Text)++type Identifier = Text++data HWType+data Declaration+data Component+data Expr+data BlackBox++type role NetlistMonad nominal+data NetlistMonad a
src/Clash/Netlist/Util.hs view
@@ -1,1123 +1,1836 @@ {-| Copyright : (C) 2012-2016, University of Twente,- 2017 , Google Inc., Myrtle Software Ltd- License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>-- Utilities for converting Core Type/Term to Netlist datatypes--}--{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE ViewPatterns #-}--module Clash.Netlist.Util where--import Control.Error (hush)-import Control.Exception (throw)-import Control.Lens ((.=),(%=))-import qualified Control.Lens as Lens-import Control.Monad (zipWithM)-import Control.Monad.Trans.Except (runExcept)-import Data.Either (partitionEithers)-import Data.HashMap.Strict (HashMap)-import qualified Data.HashMap.Strict as HashMap-import Data.List (intersperse, unzip4)-import Data.Maybe (catMaybes,fromMaybe)-import Data.Text.Lazy (append,pack,unpack)-import qualified Data.Text.Lazy as Text-import Unbound.Generics.LocallyNameless- (Embed, Fresh, embed, unbind, unembed, unrec)-import qualified Unbound.Generics.LocallyNameless as Unbound--import Clash.Annotations.TopEntity (PortName (..), TopEntity (..))-import Clash.Driver.Types- (ClashException (..), Manifest (..), SrcSpan)-import Clash.Core.DataCon (DataCon (..))-import Clash.Core.FreeVars (termFreeIds, typeFreeVars)-import Clash.Core.Name (Name (..), appendToName, name2String)-import Clash.Core.Pretty (showDoc)-import Clash.Core.Subst (substTms, substTys)-import Clash.Core.Term (LetBinding, Term (..), TmName, TmOccName)-import Clash.Core.TyCon- (TyCon (..), TyConName, TyConOccName, tyConDataCons)-import Clash.Core.Type (Type (..), TypeView (..), LitTy (..),- coreView, splitTyConAppM, tyView)-import Clash.Core.Util (collectBndrs, termType, tyNatSize)-import Clash.Core.Var (Id, Var (..), modifyVarName)-import Clash.Netlist.Id (IdType (..), stripDollarPrefixes)-import Clash.Netlist.Types as HW-import Clash.Signal.Internal (ClockKind (..))-import Clash.Util--isVoid :: HWType -> Bool-isVoid (Void {}) = True-isVoid _ = False--mkIdentifier :: IdType -> Identifier -> NetlistMonad Identifier-mkIdentifier typ nm = Lens.use mkIdentifierFn <*> pure typ <*> pure nm--extendIdentifier- :: IdType- -> Identifier- -> Identifier- -> NetlistMonad Identifier-extendIdentifier typ nm ext =- Lens.use extendIdentifierFn <*> pure typ <*> pure nm <*> pure ext---- | 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 is the term was not in a normalized form.-splitNormalized :: Fresh m- => HashMap TyConOccName TyCon- -> Term- -> m (Either String ([Id],[LetBinding],Id))-splitNormalized tcm expr = do- (args,letExpr) <- fmap (first partitionEithers) $ collectBndrs expr- case letExpr of- Letrec b- | (tmArgs,[]) <- args -> do- (xes,e) <- unbind b- case e of- Var t v -> return $! Right (tmArgs,unrec xes,Id v (embed t))- _ -> return $! Left ($(curLoc) ++ "Not in normal form: res not simple var")- | otherwise -> return $! Left ($(curLoc) ++ "Not in normal form: tyArgs")- _ -> do- ty <- termType tcm expr- return $! Left ($(curLoc) ++ "Not in normal form: no Letrec:\n\n" ++ showDoc expr ++ "\n\nWhich has type:\n\n" ++ showDoc ty)---- | Converts a Core type to a HWType given a function that translates certain--- builtin types. Errors if the Core type is not translatable.-unsafeCoreTypeToHWType- :: SrcSpan- -> String- -> (HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType))- -> HashMap TyConOccName TyCon- -> Bool- -> Type- -> HWType-unsafeCoreTypeToHWType sp loc builtInTranslation m keepVoid =- either (\msg -> throw (ClashException sp (loc ++ msg) Nothing)) id .- coreTypeToHWType builtInTranslation m keepVoid---- | Converts a Core type to a HWType within the NetlistMonad; errors on failure-unsafeCoreTypeToHWTypeM- :: String- -> Type- -> NetlistMonad HWType-unsafeCoreTypeToHWTypeM loc ty =- unsafeCoreTypeToHWType- <$> (snd <$> Lens.use curCompNm)- <*> pure loc- <*> Lens.use typeTranslator- <*> Lens.use tcCache- <*> pure False- <*> pure ty---- | Converts a Core type to a HWType within the NetlistMonad; 'Nothing' on failure-coreTypeToHWTypeM- :: Type- -> NetlistMonad (Maybe HWType)-coreTypeToHWTypeM ty = hush <$> (coreTypeToHWType <$> Lens.use typeTranslator <*> Lens.use tcCache <*> pure False <*> pure ty)---- | Returns the name and period of the clock corresponding to a type-synchronizedClk :: HashMap TyConOccName TyCon -- ^ TyCon cache- -> Type- -> Maybe (Identifier,Integer)-synchronizedClk tcm ty- | not . null . Lens.toListOf typeFreeVars $ ty = Nothing- | Just (tyCon,args) <- splitTyConAppM ty- = case name2String tyCon of- "Clash.Sized.Vector.Vec" -> synchronizedClk tcm (args!!1)- "Clash.Signal.Internal.SClock" -> case splitTyConAppM (head args) of- Just (_,[LitTy (SymTy s),litTy])- | Right i <- runExcept (tyNatSize tcm litTy) -> Just (pack s,i)- _ -> error $ $(curLoc) ++ "Clock period not a simple literal: " ++ showDoc ty- "Clash.Signal.Internal.Signal" -> case splitTyConAppM (head args) of- Just (_,[LitTy (SymTy s),litTy])- | Right i <- runExcept (tyNatSize tcm litTy) -> Just (pack s,i)- _ -> error $ $(curLoc) ++ "Clock period not a simple literal: " ++ showDoc ty- _ -> case tyConDataCons (tcm HashMap.! nameOcc tyCon) of- [dc] -> let argTys = dcArgTys dc- argTVs = map nameOcc (dcUnivTyVars dc)- argSubts = zip argTVs args- args' = map (substTys argSubts) argTys- in case args' of- (arg:_) -> synchronizedClk tcm arg- _ -> Nothing- _ -> Nothing- | otherwise- = Nothing---- | Converts a Core type to a HWType given a function that translates certain--- builtin types. Returns a string containing the error message when the Core--- type is not translatable.-coreTypeToHWType- :: (HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType))- -> HashMap TyConOccName TyCon- -> Bool- -> Type- -> Either String HWType-coreTypeToHWType builtInTranslation m keepVoid (builtInTranslation m keepVoid -> Just hty) =- hty-coreTypeToHWType builtInTranslation m keepVoid (coreView m -> Just ty) =- coreTypeToHWType builtInTranslation m keepVoid ty-coreTypeToHWType builtInTranslation m keepVoid ty@(tyView -> TyConApp tc args) =- mkADT builtInTranslation m (showDoc ty) keepVoid tc args-coreTypeToHWType _ _ _ ty = Left $ "Can't translate non-tycon type: " ++ showDoc ty---- | Converts an algebraic Core type (split into a TyCon and its argument) to a HWType.-mkADT- :: (HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType))- -- ^ Hardcoded Type -> HWType translator- -> HashMap TyConOccName TyCon- -- ^ TyCon cache- -> String- -- ^ String representation of the Core type for error messages- -> Bool- -- ^ Keep Void- -> TyConName- -- ^ The TyCon- -> [Type]- -- ^ Its applied arguments- -> Either String HWType-mkADT _ m tyString _ tc _- | isRecursiveTy m tc- = Left $ $(curLoc) ++ "Can't translate recursive type: " ++ tyString--mkADT builtInTranslation m _tyString keepVoid tc args = case tyConDataCons (m HashMap.! nameOcc tc) of- [] -> return (Void Nothing) -- Left $ $(curLoc) ++ "Can't translate empty type: " ++ tyString- dcs -> do- let tcName = pack $ name2String tc- argTyss = map dcArgTys dcs- argTVss = map dcUnivTyVars dcs- argSubts = map ((`zip` args) . map nameOcc) argTVss- substArgTyss = zipWith (\s tys -> map (substTys s) tys) argSubts argTyss- argHTyss <- mapM (mapM (coreTypeToHWType builtInTranslation m keepVoid)) substArgTyss- let argHTyss' = if keepVoid- then argHTyss- else map (filter (not . isVoid)) argHTyss- case (dcs,argHTyss') of- (_:[],[[elemTy]]) -> return elemTy- (_:[],[elemTys@(_:_)]) -> return $ Product tcName elemTys- (_ ,concat -> [])- | length dcs < 2 -> return (Void Nothing)- | otherwise -> return $ Sum tcName $ map (pack . name2String . dcName) dcs- (_ ,elemHTys) -> return $ SP tcName- $ zipWith (\dc tys ->- ( pack . name2String $ dcName dc- , tys- )- ) dcs elemHTys---- | Simple check if a TyCon is recursively defined.-isRecursiveTy :: HashMap TyConOccName TyCon -> TyConName -> Bool-isRecursiveTy m tc = case tyConDataCons (m HashMap.! nameOcc tc) of- [] -> False- dcs -> let argTyss = map dcArgTys dcs- argTycons = (map fst . catMaybes) $ (concatMap . map) splitTyConAppM argTyss- in tc `elem` argTycons---- | Determines if a Core type is translatable to a HWType given a function that--- translates certain builtin types.-representableType- :: (HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType))- -> Bool- -- ^ Allow zero-bit things- -> Bool- -- ^ String considered representable- -> HashMap TyConOccName TyCon- -> Type- -> Bool-representableType builtInTranslation _allowZero stringRepresentable m =- either (const False) isRepresentable . coreTypeToHWType builtInTranslation m False- where- isRepresentable hty = case hty of- String -> stringRepresentable- Vector _ elTy -> isRepresentable elTy- RTree _ elTy -> isRepresentable elTy- Product _ elTys -> all isRepresentable elTys- SP _ elTyss -> all (all isRepresentable . snd) elTyss- _ -> True---- | Determines the bitsize of a type-typeSize :: HWType- -> Int-typeSize (Void {}) = 0-typeSize String = 1-typeSize Bool = 1-typeSize Bit = 1-typeSize (Clock {}) = 1-typeSize (Reset {}) = 1-typeSize (BitVector i) = i-typeSize (Index 0) = 0-typeSize (Index 1) = 1-typeSize (Index u) = fromMaybe 0 (clogBase 2 u)-typeSize (Signed i) = i-typeSize (Unsigned i) = i-typeSize (Vector n el) = n * typeSize el-typeSize (RTree d el) = (2^d) * typeSize el-typeSize t@(SP _ cons) = conSize t +- maximum (map (sum . map typeSize . snd) cons)-typeSize (Sum _ dcs) = fromMaybe 0 . clogBase 2 . toInteger $ length dcs-typeSize (Product _ tys) = sum $ map typeSize tys---- | Determines the bitsize of the constructor of a type-conSize :: HWType- -> Int-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- -> Term- -> NetlistMonad HWType-termHWType loc e = do- m <- Lens.use tcCache- ty <- termType m e- unsafeCoreTypeToHWTypeM loc ty---- | Gives the HWType corresponding to a term. Returns 'Nothing' if the term has--- a Core type that is not translatable to a HWType.-termHWTypeM :: Term- -> NetlistMonad (Maybe HWType)-termHWTypeM e = do- m <- Lens.use tcCache- ty <- termType m e- coreTypeToHWTypeM ty---- | Uniquely rename all the variables and their references in a normalized--- term-mkUniqueNormalized- :: Maybe (Maybe TopEntity)- -> ([Id],[LetBinding],Id)- -> NetlistMonad- ([(Identifier,HWType)]- ,[Declaration]- ,[(Identifier,HWType)]- ,[Declaration]- ,[LetBinding]- ,TmName)-mkUniqueNormalized topMM (args,binds,res) = do- -- Make arguments unique- (iports,iwrappers,substArgs) <- mkUniqueArguments topMM args- -- Make result unique- (oports,owrappers,res1,substRes) <- mkUniqueResult topMM res- let subst' = substRes:substArgs- bndrs = map fst binds- exprs = map (unembed . snd) binds- usesOutput = concatMap (filter ( == (nameOcc . varName) res)- . Lens.toListOf termFreeIds- ) exprs- -- If the let-binder carrying the result is used in a feedback loop- -- rename the let-binder to "<X>_rec", and assign the "<X>_rec" to- -- "<X>". We do this because output ports in most HDLs cannot be read.- (res2,subst'',extraBndr) <- case usesOutput of- [] -> return (varName res1- ,(nameOcc $ varName res, Var (unembed $ varType res1) (varName res1)):subst'- ,[] :: [(Id, Embed Term)])- _ -> do- ([res3],_) <- mkUnique [] [modifyVarName (`appendToName` "_rec") res]- return (varName res3,(nameOcc $ varName res,Var (unembed $ varType res3) (varName res3)):subst'- ,[(res1,embed $ Var (unembed $ varType res) (varName res3))])- -- Replace occurences of "<X>" by "<X>_rec"- let resN = varName res- bndrs' = map (\i -> if varName i == resN then modifyVarName (const res2) i else i) bndrs- (bndrsL,r:bndrsR) = break ((== res2).varName) bndrs'- -- Make let-binders unique- (bndrsL',substL) <- mkUnique subst'' bndrsL- (bndrsR',substR) <- mkUnique substL bndrsR- -- Replace old IDs by updated unique IDs in the RHSs of the let-binders- let exprs' = map (embed . substTms substR) exprs- -- Return the uniquely named arguments, let-binders, and result- return (iports,iwrappers,oports,owrappers,zip (bndrsL' ++ r:bndrsR') exprs' ++ extraBndr,varName res1)--mkUniqueArguments- :: Maybe (Maybe TopEntity)- -> [Id]- -> NetlistMonad- ([(Identifier,HWType)]- ,[Declaration]- ,[(TmOccName,Term)]- )-mkUniqueArguments Nothing args = do- (args',subst) <- mkUnique [] args- ports <- mapM idToPort args'- return (ports,[],subst)--mkUniqueArguments (Just teM) args = do- let iPortSupply = maybe (repeat Nothing) (extendPorts . t_inputs) teM- (ports,decls,subst) <- unzip3 . catMaybes <$> zipWithM go iPortSupply args- let ports' = concat ports- return (ports', concat decls, subst)- where- go pM var = do- tcm <- Lens.use tcCache- typeTrans <- Lens.use typeTranslator- (_,sp) <- Lens.use curCompNm- let i = varName var- i' = pack (name2String i)- ty = unembed (varType var)- hwty = unsafeCoreTypeToHWType sp $(curLoc) typeTrans tcm True ty- (ports,decls,_,pN) <- mkInput pM (i',hwty)- if isVoid hwty- then return Nothing- else return (Just (ports,decls,(nameOcc i, Var ty (repName (unpack pN) i))))--mkUniqueResult- :: Maybe (Maybe TopEntity)- -> Id- -> NetlistMonad ([(Identifier,HWType)],[Declaration],Id,(TmOccName,Term))-mkUniqueResult Nothing res = do- ([res'],[subst]) <- mkUnique [] [res]- port <- idToPort res'- return ([port],[],res',subst)--mkUniqueResult (Just teM) res = do- tcm <- Lens.use tcCache- typeTrans <- Lens.use typeTranslator- (_,sp) <- Lens.use curCompNm- let o = varName res- o' = pack (name2String o)- ty = unembed (varType res)- hwty = unsafeCoreTypeToHWType sp $(curLoc) typeTrans tcm True ty- oPortSupply = fmap t_output teM- (ports,decls,pN) <- mkOutput oPortSupply (o',hwty)- let pO = repName (unpack pN) o- return (ports,decls,Id pO (embed ty),(nameOcc o,Var ty pO))--idToPort :: Id -> NetlistMonad (Identifier,HWType)-idToPort var = do- tcm <- Lens.use tcCache- typeTrans <- Lens.use typeTranslator- (_,sp) <- Lens.use curCompNm- let i = varName var- ty = unembed (varType var)- return- ( pack $ name2String i- , unsafeCoreTypeToHWType sp $(curLoc) typeTrans tcm False ty- )--repName :: String -> Name a -> Name a-repName s (Name sort _ loc) = Name sort (Unbound.string2Name s) loc---- | Make a set of IDs unique; also returns a substitution from old ID to new--- updated unique ID.-mkUnique- :: [(TmOccName,Term)]- -- ^ Existing substitution- -> [Id]- -- ^ IDs to make unique- -> NetlistMonad ([Id],[(TmOccName,Term)])- -- ^ (Unique IDs, update substitution)-mkUnique = go []- where- go :: [Id] -> [(TmOccName,Term)] -> [Id] -> NetlistMonad ([Id],[(TmOccName,Term)])- go processed subst [] = return (reverse processed,subst)- go processed subst (i:is) = do- iN <- mkUniqueIdentifier Extended . pack . name2String $ varName i- let iN_unpacked = unpack iN- i' = modifyVarName (repName iN_unpacked) i- go (i':processed)- ((nameOcc . varName $ i,Var (unembed $ varType i') (varName i')):subst)- is--mkUniqueIdentifier- :: IdType- -> Identifier- -> NetlistMonad Identifier-mkUniqueIdentifier typ nm = do- seen <- Lens.use seenIds- seenC <- Lens.use seenComps- i <- mkIdentifier typ nm- let s = seenC ++ seen- if i `elem` s- then go 0 s i- else do- seenIds %= (i:)- return i- where- go :: Integer -> [Identifier] -> Identifier -> NetlistMonad Identifier- go n s i = do- i' <- extendIdentifier typ i (pack ('_':show n))- if i' `elem` s- then go (n+1) s i- else do- seenIds %= (i':)- return i'---- | Preserve the Netlist '_varEnv' and '_varCount' when executing a monadic action-preserveVarEnv :: NetlistMonad a- -> NetlistMonad a-preserveVarEnv action = do- -- store state- vCnt <- Lens.use varCount- vComp <- Lens.use curCompNm- vSeen <- Lens.use seenIds- -- perform action- val <- action- -- restore state- varCount .= vCnt- curCompNm .= vComp- seenIds .= vSeen- return val--dcToLiteral :: HWType -> Int -> Literal-dcToLiteral Bool 1 = BoolLit False-dcToLiteral Bool 2 = BoolLit True-dcToLiteral _ i = NumLit (toInteger i-1)---- * TopEntity Annotations--extendPorts :: [PortName] -> [Maybe PortName]-extendPorts ps = map Just ps ++ repeat Nothing--appendNumber- :: (Identifier,HWType)- -> Int- -> (Identifier,HWType)-appendNumber (nm,hwty) i =- (nm `append` "_" `append` pack (show i),hwty)--portName- :: String- -> Identifier- -> Identifier-portName [] i = i-portName x _ = pack x--appendIdentifier- :: (Identifier,HWType)- -> Int- -> NetlistMonad (Identifier,HWType)-appendIdentifier (nm,hwty) i =- (,hwty) <$> extendIdentifier Extended nm (pack ('_':show i))--uniquePortName- :: String- -> Identifier- -> NetlistMonad Identifier-uniquePortName [] i = mkUniqueIdentifier Extended i-uniquePortName x _ = do- let x' = pack x- seenIds %= (x':)- return x'--mkInput- :: Maybe PortName- -> (Identifier,HWType)- -> NetlistMonad ([(Identifier,HWType)],[Declaration],Expr,Identifier)-mkInput pM = case pM of- Nothing -> go- Just p -> go' p- where- go (i,hwty) = do- i' <- mkUniqueIdentifier Extended i- case hwty of- Vector sz hwty' -> do- arguments <- mapM (appendIdentifier (i',hwty')) [0..sz-1]- (ports,_,exprs,_) <- unzip4 <$> mapM (mkInput Nothing) arguments- let hwty2 = filterVoid hwty'- netdecl = NetDecl Nothing i' (Vector sz hwty2)- vecExpr = mkVectorChain sz hwty2 exprs- netassgn = Assignment i' vecExpr- return (concat ports,[netdecl,netassgn],vecExpr,i')-- RTree d hwty' -> do- arguments <- mapM (appendIdentifier (i',hwty')) [0..2^d-1]- (ports,_,exprs,_) <- unzip4 <$> mapM (mkInput Nothing) arguments- let hwty2 = filterVoid hwty'- netdecl = NetDecl Nothing i' (RTree d hwty2)- trExpr = mkRTreeChain d hwty2 exprs- netassgn = Assignment i' trExpr- return (concat ports,[netdecl,netassgn],trExpr,i')-- Product _ hwtys -> do- arguments <- zipWithM appendIdentifier (map (i',) hwtys) [0..]- let argumentsBundled = zip hwtys arguments- argumentsFiltered = filter (not . isVoid . fst) argumentsBundled- argumentsFiltered' = map snd argumentsFiltered- (ports,_,exprs,_) <- unzip4 <$> mapM (mkInput Nothing) argumentsFiltered'- case exprs of- [expr] ->- let hwty' = filterVoid hwty- netdecl = NetDecl Nothing i' hwty'- dcExpr = expr- netassgn = Assignment i' expr- in return (concat ports,[netdecl,netassgn],dcExpr,i')- _ ->- let hwty' = filterVoid hwty- netdecl = NetDecl Nothing i' hwty'- dcExpr = DataCon hwty' (DC (hwty',0)) exprs- netassgn = Assignment i' dcExpr- in return (concat ports,[netdecl,netassgn],dcExpr,i')-- Clock nm rt Gated -> do- let hwtys = [Clock nm rt Source,Bool]- arguments <- zipWithM appendIdentifier (map (i',) hwtys) [0..]- (ports,_,exprs,_) <- unzip4 <$> mapM (mkInput Nothing) arguments- let netdecl = NetDecl Nothing i' hwty- dcExpr = DataCon hwty (DC (hwty,0)) exprs- netassgn = Assignment i' dcExpr- return (concat ports,[netdecl,netassgn],dcExpr,i')-- _ -> return ([(i',hwty)],[],Identifier i' Nothing,i')--- go' (PortName p) (i,hwty) = do- pN <- uniquePortName p i- return ([(pN,hwty)],[],Identifier pN Nothing,pN)-- go' (PortProduct p ps) (i,hwty) = do- pN <- uniquePortName p i- case hwty of- Vector sz hwty' -> do- arguments <- mapM (appendIdentifier (pN,hwty')) [0..sz-1]- (ports,_,exprs,_) <- unzip4 <$> zipWithM mkInput (extendPorts ps) arguments- let hwty2 = filterVoid hwty'- netdecl = NetDecl Nothing pN (Vector sz hwty2)- vecExpr = mkVectorChain sz hwty2 exprs- netassgn = Assignment pN vecExpr- return (concat ports,[netdecl,netassgn],vecExpr,pN)-- RTree d hwty' -> do- arguments <- mapM (appendIdentifier (pN,hwty')) [0..2^d-1]- (ports,_,exprs,_) <- unzip4 <$> zipWithM mkInput (extendPorts ps) arguments- let hwty2 = filterVoid hwty'- netdecl = NetDecl Nothing pN (RTree d hwty2)- trExpr = mkRTreeChain d hwty2 exprs- netassgn = Assignment pN trExpr- return (concat ports,[netdecl,netassgn],trExpr,pN)-- Product _ hwtys -> do- arguments <- zipWithM appendIdentifier (map (pN,) hwtys) [0..]- let argumentsBundled = zip hwtys (zip (extendPorts ps) arguments)- argumentsFiltered = filter (not . isVoid . fst) argumentsBundled- argumentsFiltered' = unzip (map snd argumentsFiltered)- (ports,_,exprs,_) <- unzip4 <$> uncurry (zipWithM mkInput) argumentsFiltered'- case exprs of- [expr] ->- let hwty' = filterVoid hwty- netdecl = NetDecl Nothing pN hwty'- dcExpr = expr- netassgn = Assignment pN expr- in return (concat ports,[netdecl,netassgn],dcExpr,pN)- _ -> let hwty' = filterVoid hwty- netdecl = NetDecl Nothing pN hwty'- dcExpr = DataCon hwty' (DC (hwty',0)) exprs- netassgn = Assignment pN dcExpr- in return (concat ports,[netdecl,netassgn],dcExpr,pN)-- Clock nm rt Gated -> do- let hwtys = [Clock nm rt Source, Bool]- arguments <- zipWithM appendIdentifier (map (pN,) hwtys) [0..]- (ports,_,exprs,_) <- unzip4 <$> zipWithM mkInput (extendPorts ps) arguments- let netdecl = NetDecl Nothing pN hwty- dcExpr = DataCon hwty (DC (hwty,0)) exprs- netassgn = Assignment pN dcExpr- return (concat ports,[netdecl,netassgn],dcExpr,pN)-- _ -> return ([(pN,hwty)],[],Identifier pN Nothing,pN)--filterVoid- :: HWType- -> HWType-filterVoid t = case t of- Product nm hwtys- | null hwtys' -> Void Nothing- | length hwtys' == 1 -> head hwtys'- | otherwise -> Product nm hwtys'- where- hwtys' = filter (not . isVoid) (map filterVoid hwtys)- _ -> t---- | Create a Vector chain for a list of 'Identifier's-mkVectorChain :: Int- -> HWType- -> [Expr]- -> Expr-mkVectorChain _ elTy [] = DataCon (Vector 0 elTy) VecAppend []-mkVectorChain _ elTy [e] = DataCon (Vector 1 elTy) VecAppend- [e]-mkVectorChain sz elTy (e:es) = DataCon (Vector sz elTy) VecAppend- [ e- , mkVectorChain (sz-1) elTy es- ]---- | Create a RTree chain for a list of 'Identifier's-mkRTreeChain :: Int- -> HWType- -> [Expr]- -> Expr-mkRTreeChain _ elTy [e] = DataCon (RTree 0 elTy) RTreeAppend- [e]-mkRTreeChain d elTy es =- let (esL,esR) = splitAt (length es `div` 2) es- in DataCon (RTree d elTy) RTreeAppend- [ mkRTreeChain (d-1) elTy esL- , mkRTreeChain (d-1) elTy esR- ]--genComponentName :: [Identifier] -> (IdType -> Identifier -> Identifier) -> TmName -> Identifier-genComponentName seen mkId nm =- let nm' = Text.splitOn (Text.pack ".") (Text.pack (name2String nm))- fn = mkId Basic (stripDollarPrefixes (last nm'))- fn' = if Text.null fn then Text.pack "Component" else fn- nm2 = Text.concat (intersperse (Text.pack "_") (init nm' ++ [fn']))- nm3 = mkId Basic nm2- in if nm3 `elem` seen then go 0 nm3 else nm3- where- go :: Integer -> Identifier -> Identifier- go n i =- let i' = mkId Basic (i `Text.append` Text.pack ('_':show n))- in if i' `elem` seen- then go (n+1) i- else i'---- | Generate output port mappings-mkOutput- :: Maybe PortName- -> (Identifier,HWType)- -> NetlistMonad ([(Identifier,HWType)],[Declaration],Identifier)-mkOutput pM = case pM of- Nothing -> go- Just p -> go' p- where- go (o,hwty) = do- o' <- mkUniqueIdentifier Extended o- case hwty of- Vector sz hwty' -> do- results <- mapM (appendIdentifier (o',hwty')) [0..sz-1]- (ports,decls,ids) <- unzip3 <$> mapM (mkOutput Nothing) results- let hwty2 = Vector sz (filterVoid hwty')- netdecl = NetDecl Nothing o' hwty2- assigns = zipWith (assignId o' hwty2 10) ids [0..]- return (concat ports,netdecl:assigns ++ concat decls,o')-- RTree d hwty' -> do- results <- mapM (appendIdentifier (o',hwty')) [0..2^d-1]- (ports,decls,ids) <- unzip3 <$> mapM (mkOutput Nothing) results- let hwty2 = RTree d (filterVoid hwty')- netdecl = NetDecl Nothing o' hwty2- assigns = zipWith (assignId o' hwty2 10) ids [0..]- return (concat ports,netdecl:assigns ++ concat decls,o')-- Product _ hwtys -> do- results <- zipWithM appendIdentifier (map (o,) hwtys) [0..]- let resultsBundled = zip hwtys results- resultsFiltered = filter (not . isVoid . fst) resultsBundled- resultsFiltered' = map snd resultsFiltered- (ports,decls,ids) <- unzip3 <$> mapM (mkOutput Nothing) resultsFiltered'- case ids of- [i] ->- let hwty' = filterVoid hwty- netdecl = NetDecl Nothing o' hwty'- assign = Assignment i (Identifier o' Nothing)- in return (concat ports,netdecl:assign:concat decls,o')- _ ->- let hwty' = filterVoid hwty- netdecl = NetDecl Nothing o' hwty'- assigns = zipWith (assignId o' hwty' 0) ids [0..]- in return (concat ports,netdecl:assigns ++ concat decls,o')-- _ -> return ([(o',hwty)],[],o')-- go' (PortName p) (o,hwty) = do- pN <- uniquePortName p o- return ([(pN,hwty)],[],pN)-- go' (PortProduct p ps) (o,hwty) = do- pN <- uniquePortName p o- case hwty of- Vector sz hwty' -> do- results <- mapM (appendIdentifier (pN,hwty')) [0..sz-1]- (ports,decls,ids) <- unzip3 <$> zipWithM mkOutput (extendPorts ps) results- let hwty2 = Vector sz (filterVoid hwty')- netdecl = NetDecl Nothing pN hwty2- assigns = zipWith (assignId pN hwty2 10) ids [0..]- return (concat ports,netdecl:assigns ++ concat decls,pN)-- RTree d hwty' -> do- results <- mapM (appendIdentifier (pN,hwty')) [0..2^d-1]- (ports,decls,ids) <- unzip3 <$> zipWithM mkOutput (extendPorts ps) results- let hwty2 = RTree d (filterVoid hwty')- netdecl = NetDecl Nothing pN hwty2- assigns = zipWith (assignId pN hwty2 10) ids [0..]- return (concat ports,netdecl:assigns ++ concat decls,pN)-- Product _ hwtys -> do- results <- zipWithM appendIdentifier (map (pN,) hwtys) [0..]- let resultsBundled = zip hwtys (zip (extendPorts ps) results)- resultsFiltered = filter (not . isVoid . fst) resultsBundled- resultsFiltered' = unzip (map snd resultsFiltered)- (ports,decls,ids) <- unzip3 <$> uncurry (zipWithM mkOutput) resultsFiltered'- case ids of- [i] -> let hwty' = filterVoid hwty- netdecl = NetDecl Nothing pN hwty'- assign = Assignment i (Identifier pN Nothing)- in return (concat ports,netdecl:assign:concat decls,pN)- _ -> let hwty' = filterVoid hwty- netdecl = NetDecl Nothing pN hwty'- assigns = zipWith (assignId pN hwty' 0) ids [0..]- in return (concat ports,netdecl:assigns ++ concat decls,pN)-- _ -> return ([(pN,hwty)],[],pN)-- assignId p hwty con i n =- Assignment i (Identifier p (Just (Indexed (hwty,con,n))))---- | Instantiate a TopEntity, and add the proper type-conversions where needed-mkTopUnWrapper- :: TmName- -- ^ Name of the TopEntity component- -> Maybe TopEntity- -- ^ (maybe) a corresponding @TopEntity@ annotation- -> Manifest- -- ^ a corresponding @Manifest@- -> (Identifier,HWType)- -- ^ The name and type of the signal to which to assign the result- -> [(Expr,HWType)]- -- ^ The arguments- -> NetlistMonad [Declaration]-mkTopUnWrapper topEntity annM man dstId args = do- let inTys = portInTypes man- outTys = portOutTypes man- inNames = portInNames man- outNames = portOutNames man-- -- component name- mkId <- Lens.use mkIdentifierFn- let topName = genComponentName [] mkId topEntity- topName' = maybe topName (pack . t_name) annM- topM = fmap (const topName') annM-- -- inputs- let iPortSupply = maybe (repeat Nothing)- (extendPorts . t_inputs)- annM- arguments <- zipWithM appendIdentifier (map (first (const "input")) args) [0..]- (_,arguments1) <- mapAccumLM (\acc (p,i) -> mkTopInput topM acc p i)- (zip inNames inTys)- (zip iPortSupply arguments)- let (iports,wrappers,idsI) = unzip3 arguments1- inpAssigns = zipWith (argBV topM) idsI (map fst args)-- -- output- let oPortSupply = maybe (repeat Nothing)- (extendPorts . (:[]) . t_output)- annM-- result = ("result",snd dstId)- (_,(oports,unwrappers,idsO)) <- mkTopOutput topM (zip outNames outTys)- (head oPortSupply) result- let outpAssign = Assignment (fst dstId) (resBV topM idsO)-- instLabel <- extendIdentifier Basic topName' ("_" `append` fst dstId)- let topCompDecl =- InstDecl- (Just topName')- topName'- instLabel- (map (\(p,i,t) -> (Identifier p Nothing,In, t,Identifier i Nothing)) (concat iports) ++- map (\(p,o,t) -> (Identifier p Nothing,Out,t,Identifier o Nothing)) oports)--- return (inpAssigns ++ concat wrappers ++ (topCompDecl:unwrappers) ++ [outpAssign])---- | Convert between BitVector for an argument-argBV- :: Maybe Identifier- -- ^ (maybe) Name of the _TopEntity_- -> Either Identifier (Identifier, HWType)- -- ^ Either:- -- * A /normal/ argument- -- * An argument with a @PortName@- -> Expr- -> Declaration-argBV _ (Left i) e = Assignment i e-argBV topM (Right (i,t)) e = Assignment i- . doConv t (fmap Just topM) False- $ doConv t (fmap (const Nothing) topM) True e---- | Convert between BitVector for the result-resBV- :: Maybe Identifier- -- ^ (mabye) Name of the _TopEntity_- -> Either Identifier (Identifier, HWType)- -- ^ Either:- -- * A /normal/ result- -- * A result with a @PortName@- -> Expr-resBV _ (Left i) = Identifier i Nothing-resBV topM (Right (i,t)) = doConv t (fmap (const Nothing) topM) False- . doConv t (fmap Just topM) True- $ Identifier i Nothing----- | Add to/from-BitVector conversion logic-doConv- :: HWType- -- ^ We only need it for certain types- -> Maybe (Maybe Identifier)- -- ^- -- * Nothing: No _given_ TopEntity, no need for conversion, this- -- happens when we have a _TestBench_, but no- -- _TopEntity_ annotation.- -- * Just Nothing: Converting to/from a BitVector for one of the- -- internally defined types.- -- * Just (Just top): Converting to/from a BitVector for one of the- -- types defined by @top@.- -> Bool- -- ^- -- * True: convert to a BitVector- -- * False: convert from a BitVector- -> Expr- -- ^ The expression on top of which we have to add conversion logic- -> Expr-doConv _ Nothing _ e = e-doConv hwty (Just topM) b e = case hwty of- Vector {} -> ConvBV topM hwty b e- RTree {} -> ConvBV topM hwty b e- Product {} -> ConvBV topM hwty b e- Clock _ _ Gated -> ConvBV topM hwty b e- _ -> e---- | Generate input port mappings for the TopEntity-mkTopInput- :: Maybe Identifier- -- ^ (maybe) Name of the _TopEntity_- -> [(Identifier,Identifier)]- -- ^ /Rendered/ input port names and types- -> Maybe PortName- -- ^ (maybe) The @PortName@ of a _TopEntity_ annotation for this input- -> (Identifier,HWType)- -> NetlistMonad ([(Identifier,Identifier)]- ,([(Identifier,Identifier,HWType)]- ,[Declaration]- ,Either Identifier (Identifier,HWType)))-mkTopInput topM inps pM = case pM of- Nothing -> go inps- Just p -> go' p inps- where- -- No @PortName@- go inps'@((iN,_):rest) (i,hwty) = do- i' <- mkUniqueIdentifier Basic i- let iDecl = NetDecl Nothing i' hwty- case hwty of- Vector sz hwty' -> do- arguments <- mapM (appendIdentifier (i',hwty')) [0..sz-1]- (inps'',arguments1) <- mapAccumLM go inps' arguments- let (ports,decls,ids) = unzip3 arguments1- assigns = zipWith (argBV topM) ids- [ Identifier i' (Just (Indexed (hwty,10,n)))- | n <- [0..]]- return (inps'',(concat ports,iDecl:assigns++concat decls,Left i'))-- RTree d hwty' -> do- arguments <- mapM (appendIdentifier (i',hwty')) [0..2^d-1]- (inps'',arguments1) <- mapAccumLM go inps' arguments- let (ports,decls,ids) = unzip3 arguments1- assigns = zipWith (argBV topM) ids- [ Identifier i' (Just (Indexed (hwty,10,n)))- | n <- [0..]]- return (inps'',(concat ports,iDecl:assigns++concat decls,Left i'))-- Product _ hwtys -> do- arguments <- zipWithM appendIdentifier (map (i,) hwtys) [0..]- (inps'',arguments1) <- mapAccumLM go inps' arguments- let (ports,decls,ids) = unzip3 arguments1- assigns = zipWith (argBV topM) ids- [ Identifier i' (Just (Indexed (hwty,0,n)))- | n <- [0..]]- return (inps'',(concat ports,iDecl:assigns++concat decls,Left i'))-- Clock nm rt Gated -> do- let hwtys = [Clock nm rt Source,Bool]- arguments <- zipWithM appendIdentifier (map (i,) hwtys) [0..]- (inps'',arguments1) <- mapAccumLM go inps' arguments- let (ports,decls,ids) = unzip3 arguments1- assigns = zipWith (argBV topM) ids- [ Identifier i' (Just (Indexed (hwty,0,n)))- | n <- [0..]]- return (inps'',(concat ports,iDecl:assigns++concat decls,Left i'))-- _ -> return (rest,([(iN,i',hwty)],[iDecl],Left i'))-- go [] _ = error "This shouldn't happen"-- -- With a @PortName@- go' (PortName _) ((iN,iTy):inps') (_,hwty) = do- iN' <- mkUniqueIdentifier Extended iN- return (inps',([(iN,iN',hwty)]- ,[NetDecl' Nothing Wire iN' (Left iTy)]- ,Right (iN',hwty)))-- go' (PortName _) [] _ = error "This shouldnt happen"-- go' (PortProduct p ps) inps' (i,hwty) = do- let pN = portName p i- pN' <- mkUniqueIdentifier Extended pN- let pDecl = NetDecl Nothing pN' hwty- case hwty of- Vector sz hwty' -> do- arguments <- mapM (appendIdentifier (pN',hwty')) [0..sz-1]- (inps'',arguments1) <-- mapAccumLM (\acc (p',o') -> mkTopInput topM acc p' o') inps'- (zip (extendPorts ps) arguments)- let (ports,decls,ids) = unzip3 arguments1- assigns = zipWith (argBV topM) ids- [ Identifier pN' (Just (Indexed (hwty,10,n)))- | n <- [0..]]- return (inps'',(concat ports,pDecl:assigns ++ concat decls,Left pN'))-- RTree d hwty' -> do- arguments <- mapM (appendIdentifier (pN',hwty')) [0..2^d-1]- (inps'',arguments1) <-- mapAccumLM (\acc (p',o') -> mkTopInput topM acc p' o') inps'- (zip (extendPorts ps) arguments)- let (ports,decls,ids) = unzip3 arguments1- assigns = zipWith (argBV topM) ids- [ Identifier pN' (Just (Indexed (hwty,10,n)))- | n <- [0..]]- return (inps'',(concat ports,pDecl:assigns ++ concat decls,Left pN'))-- Product _ hwtys -> do- arguments <- zipWithM appendIdentifier (map (pN',) hwtys) [0..]- (inps'',arguments1) <-- mapAccumLM (\acc (p',o') -> mkTopInput topM acc p' o') inps'- (zip (extendPorts ps) arguments)- let (ports,decls,ids) = unzip3 arguments1- assigns = zipWith (argBV topM) ids- [ Identifier pN' (Just (Indexed (hwty,0,n)))- | n <- [0..]]- return (inps'',(concat ports,pDecl:assigns ++ concat decls,Left pN'))-- Clock nm rt Gated -> do- let hwtys = [Clock nm rt Source,Bool]- arguments <- zipWithM appendIdentifier (map (pN',) hwtys) [0..]- (inps'',arguments1) <-- mapAccumLM (\acc (p',o') -> mkTopInput topM acc p' o') inps'- (zip (extendPorts ps) arguments)- let (ports,decls,ids) = unzip3 arguments1- assigns = zipWith (argBV topM) ids- [ Identifier pN' (Just (Indexed (hwty,0,n)))- | n <- [0..]]- return (inps'',(concat ports,pDecl:assigns ++ concat decls,Left pN'))-- _ -> return (tail inps',([(pN,pN',hwty)],[pDecl],Left pN'))---- | Generate output port mappings for the TopEntity-mkTopOutput- :: Maybe Identifier- -- ^ (maybe) Name of the _TopEntity_- -> [(Identifier,Identifier)]- -- ^ /Rendered/ output port names and types- -> Maybe PortName- -- ^ (maybe) The @PortName@ of a _TopEntity_ annotation for this output- -> (Identifier,HWType)- -> NetlistMonad ([(Identifier,Identifier)]- ,([(Identifier,Identifier,HWType)]- ,[Declaration]- ,Either Identifier (Identifier,HWType))- )-mkTopOutput topM outps pM = case pM of- Nothing -> go outps- Just p -> go' p outps- where- -- No @PortName@- go outps'@((oN,_):rest) (o,hwty) = do- o' <- mkUniqueIdentifier Extended o- let oDecl = NetDecl Nothing o' hwty- case hwty of- Vector sz hwty' -> do- results <- mapM (appendIdentifier (o',hwty')) [0..sz-1]- (outps'',results1) <- mapAccumLM go outps' results- let (ports,decls,ids) = unzip3 results1- ids' = map (resBV topM) ids- netassgn = Assignment o' (mkVectorChain sz hwty' ids')- return (outps'',(concat ports,oDecl:netassgn:concat decls,Left o'))-- RTree d hwty' -> do- results <- mapM (appendIdentifier (o',hwty')) [0..2^d-1]- (outps'',results1) <- mapAccumLM go outps' results- let (ports,decls,ids) = unzip3 results1- ids' = map (resBV topM) ids- netassgn = Assignment o' (mkRTreeChain d hwty' ids')- return (outps'',(concat ports,oDecl:netassgn:concat decls,Left o'))-- Product _ hwtys -> do- results <- zipWithM appendIdentifier (map (o',) hwtys) [0..]- (outps'',results1) <- mapAccumLM go outps' results- let (ports,decls,ids) = unzip3 results1- ids' = map (resBV topM) ids- netassgn = Assignment o' (DataCon hwty (DC (hwty,0)) ids')- return (outps'',(concat ports,oDecl:netassgn:concat decls,Left o'))-- _ -> return (rest,([(oN,o',hwty)],[oDecl],Left o'))-- go [] _ = error "This shouldn't happen"-- -- With a @PortName@- go' (PortName _) ((oN,oTy):outps') (_,hwty) = do- oN' <- mkUniqueIdentifier Extended oN- return (outps',([(oN,oN',hwty)]- ,[NetDecl' Nothing Wire oN' (Left oTy)]- ,Right (oN',hwty)))-- go' (PortName _) [] _ = error "This shouldnt happen"-- go' (PortProduct p ps) outps' (o,hwty) = do- let pN = portName p o- pN' <- mkUniqueIdentifier Extended pN- let pDecl = NetDecl Nothing pN' hwty- case hwty of- Vector sz hwty' -> do- results <- mapM (appendIdentifier (pN',hwty')) [0..sz-1]- (outps'',results1) <-- mapAccumLM (\acc (p',o') -> mkTopOutput topM acc p' o') outps'- (zip (extendPorts ps) results)- let (ports,decls,ids) = unzip3 results1- ids' = map (resBV topM) ids- netassgn = Assignment pN' (mkVectorChain sz hwty' ids')- return (outps'',(concat ports,pDecl:netassgn:concat decls,Left pN'))-- RTree d hwty' -> do- results <- mapM (appendIdentifier (pN',hwty')) [0..2^d-1]- (outps'',results1) <-- mapAccumLM (\acc (p',o') -> mkTopOutput topM acc p' o') outps'- (zip (extendPorts ps) results)- let (ports,decls,ids) = unzip3 results1- ids' = map (resBV topM) ids- netassgn = Assignment pN' (mkRTreeChain d hwty' ids')- return (outps'',(concat ports,pDecl:netassgn:concat decls,Left pN'))-- Product _ hwtys -> do- results <- zipWithM appendIdentifier (map (pN',) hwtys) [0..]- (outps'',results1) <-- mapAccumLM (\acc (p',o') -> mkTopOutput topM acc p' o') outps'- (zip (extendPorts ps) results)- let (ports,decls,ids) = unzip3 results1- ids' = map (resBV topM) ids- netassgn = Assignment pN' (DataCon hwty (DC (hwty,0)) ids')- return (outps'',(concat ports,pDecl:netassgn:concat decls,Left pN'))-- _ -> return (tail outps',([(pN,pN',hwty)],[pDecl],Left pN'))--concatPortDecls3- :: [([(Identifier,Identifier,HWType)]- ,[Declaration]- ,Either Identifier (Identifier,HWType))]- -> ([(Identifier,Identifier,HWType)]- ,[Declaration]- ,[Either Identifier (Identifier,HWType)])-concatPortDecls3 portDecls = case unzip3 portDecls of- (ps,decls,ids) -> (concat ps, concat decls, ids)+ 2017 , Myrtle Software Ltd+ 2017-2018, Google Inc.+ License : BSD2 (see the file LICENSE)+ Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>++ Utilities for converting Core Type/Term to Netlist datatypes+-}++{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+#if !MIN_VERSION_ghc(8,8,0)+{-# LANGUAGE MonadFailDesugaring #-}+#endif+{-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE ViewPatterns #-}++module Clash.Netlist.Util where++import Control.Error (hush)+import Control.Exception (throw)+import Control.Lens ((.=),(%=))+import qualified Control.Lens as Lens+import Control.Monad (unless, when, zipWithM, join)+import Control.Monad.Reader (ask, local)+import Control.Monad.State.Strict+ (State, evalState, get, modify, runState)+import Control.Monad.Trans.Except+ (ExceptT (..), runExcept, runExceptT, throwE)+import Data.Either (partitionEithers)+import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HashMap+import Data.String (fromString)+import Data.List (intersperse, unzip4, sort, intercalate)+import qualified Data.List as List+import Data.Maybe (catMaybes,fromMaybe,isNothing)+import Data.Monoid (First (..))+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.Prettyprint.Doc (Doc)++import Outputable (ppr, showSDocUnsafe)++import Clash.Annotations.BitRepresentation.ClashLib+ (coreToType')+import Clash.Annotations.BitRepresentation.Internal+ (CustomReprs, ConstrRepr'(..), DataRepr'(..), getDataRepr, getConstrRepr)+import Clash.Annotations.TopEntity (PortName (..), TopEntity (..))+import Clash.Driver.Types (Manifest (..), ClashOpts (..))+import Clash.Core.DataCon (DataCon (..))+import Clash.Core.FreeVars (freeLocalIds, typeFreeVars)+import qualified Clash.Core.Literal as C+import Clash.Core.Name+ (Name (..), appendToName, nameOcc)+import Clash.Core.Pretty (showPpr)+import Clash.Core.Subst+ (Subst (..), extendIdSubst, extendIdSubstList, extendInScopeId,+ extendInScopeIdList, mkSubst, substTm)+import Clash.Core.Term+ (Alt, LetBinding, Pat (..), Term (..), TickInfo (..), NameMod (..))+import Clash.Core.TyCon+ (TyConName, TyConMap, tyConDataCons)+import Clash.Core.Type (Type (..), TypeView (..),+ coreView1, splitTyConAppM, tyView, TyVar)+import Clash.Core.Util+ (collectBndrs, stripTicks, substArgTys, termType, tySym)+import Clash.Core.Var+ (Id, Var (..), mkLocalId, modifyVarName, Attr')+import Clash.Core.VarEnv+ (InScopeSet, extendInScopeSetList, uniqAway)+import Clash.Netlist.Id (IdType (..), stripDollarPrefixes)+import Clash.Netlist.Types as HW+import Clash.Unique+import Clash.Util++-- | Throw away information indicating which constructor fields were filtered+-- due to being void.+stripFiltered :: FilteredHWType -> HWType+stripFiltered (FilteredHWType hwty _filtered) = hwty++flattenFiltered :: FilteredHWType -> [[Bool]]+flattenFiltered (FilteredHWType _hwty filtered) = map (map fst) filtered++-- | Determines if type is a zero-width construct ("void")+isVoid :: HWType -> Bool+isVoid Void {} = True+isVoid _ = False++-- | Same as @isVoid@, but on @FilteredHWType@ instead of @HWType@+isFilteredVoid :: FilteredHWType -> Bool+isFilteredVoid = isVoid . stripFiltered++isBiSignalOut :: HWType -> Bool+isBiSignalOut (Void (Just (BiDirectional Out _))) = True+isBiSignalOut (Vector n ty) | n /= 0 = isBiSignalOut ty+isBiSignalOut (RTree _ ty) = isBiSignalOut ty+isBiSignalOut _ = False++mkIdentifier :: IdType -> Identifier -> NetlistMonad Identifier+mkIdentifier typ nm = Lens.use mkIdentifierFn <*> pure typ <*> pure nm++extendIdentifier+ :: IdType+ -> Identifier+ -> Identifier+ -> NetlistMonad Identifier+extendIdentifier typ nm ext =+ Lens.use extendIdentifierFn <*> pure typ <*> pure nm <*> pure ext++-- | 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.+splitNormalized+ :: TyConMap+ -> Term+ -> (Either String ([Id],[LetBinding],Id))+splitNormalized tcm expr = case collectBndrs expr of+ (args,Letrec xes e)+ | (tmArgs,[]) <- partitionEithers args -> case stripTicks e of+ Var v -> Right (tmArgs,xes,v)+ _ -> Left ($(curLoc) ++ "Not in normal form: res not simple var")+ | 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)++-- | Converts a Core type to a HWType given a function that translates certain+-- builtin types. Errors if the Core type is not translatable.+unsafeCoreTypeToHWType+ :: SrcSpan+ -- ^ Approximate location in original source file+ -> String+ -> (CustomReprs -> TyConMap -> Type ->+ State HWMap (Maybe (Either String FilteredHWType)))+ -> CustomReprs+ -> TyConMap+ -> Type+ -> State HWMap FilteredHWType+unsafeCoreTypeToHWType sp loc builtInTranslation reprs m ty =+ either (\msg -> throw (ClashException sp (loc ++ msg) Nothing)) id <$>+ coreTypeToHWType builtInTranslation reprs m ty++-- | Same as @unsafeCoreTypeToHWTypeM@, but discards void filter information+unsafeCoreTypeToHWTypeM'+ :: String+ -> Type+ -> NetlistMonad HWType+unsafeCoreTypeToHWTypeM' loc ty =+ stripFiltered <$> unsafeCoreTypeToHWTypeM loc ty++-- | Converts a Core type to a HWType within the NetlistMonad; errors on failure+unsafeCoreTypeToHWTypeM+ :: String+ -> Type+ -> NetlistMonad FilteredHWType+unsafeCoreTypeToHWTypeM loc ty = do+ (_,cmpNm) <- Lens.use curCompNm+ tt <- Lens.use typeTranslator+ reprs <- Lens.use customReprs+ tcm <- Lens.use tcCache+ htm0 <- Lens.use htyCache+ let (hty,htm1) = runState (unsafeCoreTypeToHWType cmpNm loc tt reprs tcm ty) htm0+ htyCache Lens..= htm1+ return hty++-- | Same as @coreTypeToHWTypeM@, but discards void filter information+coreTypeToHWTypeM'+ :: Type+ -- ^ Type to convert to HWType+ -> NetlistMonad (Maybe HWType)+coreTypeToHWTypeM' ty =+ fmap stripFiltered <$> coreTypeToHWTypeM ty+++-- | Converts a Core type to a HWType within the NetlistMonad; 'Nothing' on failure+coreTypeToHWTypeM+ :: Type+ -- ^ Type to convert to HWType+ -> NetlistMonad (Maybe FilteredHWType)+coreTypeToHWTypeM ty = do+ tt <- Lens.use typeTranslator+ reprs <- Lens.use customReprs+ tcm <- Lens.use tcCache+ htm0 <- Lens.use htyCache+ let (hty,htm1) = runState (coreTypeToHWType tt reprs tcm ty) htm0+ htyCache Lens..= htm1+ return (hush hty)++packSP+ :: CustomReprs+ -> (Text, c)+ -> (ConstrRepr', Text, c)+packSP reprs (name, tys) =+ case getConstrRepr name reprs of+ Just repr -> (repr, name, tys)+ Nothing -> error $ $(curLoc) ++ unwords+ [ "Could not find custom representation for", Text.unpack name ]++packSum+ :: CustomReprs+ -> Text+ -> (ConstrRepr', Text)+packSum reprs name =+ case getConstrRepr name reprs of+ Just repr -> (repr, name)+ Nothing -> error $ $(curLoc) ++ unwords+ [ "Could not find custom representation for", Text.unpack name ]++fixCustomRepr+ :: CustomReprs+ -> Type+ -> HWType+ -> HWType+fixCustomRepr reprs (coreToType' -> Right tyName) sum_@(Sum name subtys) =+ case getDataRepr tyName reprs of+ Just dRepr@(DataRepr' name' size constrs) ->+ if length constrs == length subtys then+ CustomSum+ name+ dRepr+ (fromIntegral size)+ [packSum reprs ty | ty <- subtys]+ else+ error $ $(curLoc) ++ (Text.unpack $ Text.unwords+ [ "Type "+ , Text.pack $ show name'+ , "has"+ , Text.pack $ show $ length subtys+ , "constructors: \n\n"+ , Text.intercalate "\n" $ sort [Text.append " * " id_ | id_ <- subtys]+ , "\n\nBut the custom bit representation only specified"+ , Text.pack $ show $ length constrs+ , "constructors:\n\n"+ , Text.intercalate "\n" $ sort [Text.append " * " id_ | (ConstrRepr' id_ _ _ _ _) <- constrs]+ ])+ Nothing ->+ -- No custom representation found+ sum_++fixCustomRepr reprs (coreToType' -> Right tyName) sp@(SP name subtys) =+ case getDataRepr tyName reprs of+ Just dRepr@(DataRepr' name' size constrs) ->+ if length constrs == length subtys then+ CustomSP+ name+ dRepr+ (fromIntegral size)+ [packSP reprs ty | ty <- subtys]+ else+ error $ $(curLoc) ++ (Text.unpack $ Text.unwords+ [ "Type "+ , Text.pack $ show $ name'+ , "has"+ , Text.pack $ show $ length subtys+ , "constructors: \n\n"+ , Text.intercalate "\n" $ sort [Text.append " * " id_ | (id_, _) <- subtys]+ , "\n\nBut the custom bit representation only specified"+ , Text.pack $ show $ length constrs, "constructors:\n\n"+ , Text.intercalate "\n" $ sort [Text.append " * " id_ | (ConstrRepr' id_ _ _ _ _) <- constrs]+ ])+ Nothing ->+ -- No custom representation found+ sp++fixCustomRepr _ _ typ = typ++-- | Same as @coreTypeToHWType@, but discards void filter information+coreTypeToHWType'+ :: (CustomReprs -> TyConMap -> Type ->+ State HWMap (Maybe (Either String FilteredHWType)))+ -> CustomReprs+ -> TyConMap+ -> Type+ -- ^ Type to convert to HWType+ -> State HWMap (Either String HWType)+coreTypeToHWType' builtInTranslation reprs m ty =+ fmap stripFiltered <$> coreTypeToHWType builtInTranslation reprs m ty+++-- | Converts a Core type to a HWType given a function that translates certain+-- builtin types. Returns a string containing the error message when the Core+-- type is not translatable.+coreTypeToHWType+ :: (CustomReprs -> TyConMap -> Type ->+ State HWMap (Maybe (Either String FilteredHWType)))+ -> CustomReprs+ -> TyConMap+ -> Type+ -- ^ Type to convert to HWType+ -> State HWMap (Either String FilteredHWType)+coreTypeToHWType builtInTranslation reprs m ty = do+ htyM <- HashMap.lookup ty <$> get+ case htyM of+ Just hty -> return hty+ _ -> do+ hty0M <- builtInTranslation reprs m ty+ hty1 <- go hty0M ty+ modify (HashMap.insert ty hty1)+ return hty1+ where+ -- Try builtin translation; for now this is hardcoded to be the one in ghcTypeToHWType+ go :: Maybe (Either String FilteredHWType)+ -> Type+ -> State (HashMap Type (Either String FilteredHWType))+ (Either String FilteredHWType)+ go (Just hwtyE) _ = pure $+ (\(FilteredHWType hwty filtered) ->+ (FilteredHWType (fixCustomRepr reprs ty hwty) filtered)) <$> hwtyE+ -- Strip transparant types:+ go _ (coreView1 m -> Just ty') =+ coreTypeToHWType builtInTranslation reprs m ty'+ -- Try to create hwtype based on AST:+ go _ (tyView -> TyConApp tc args) = runExceptT $ do+ FilteredHWType hwty filtered <- mkADT builtInTranslation reprs m (showPpr ty) tc args+ return (FilteredHWType (fixCustomRepr reprs ty hwty) filtered)+ -- All methods failed:+ go _ _ = return $ Left $ "Can't translate non-tycon type: " ++ showPpr ty++-- | Generates original indices in list before filtering, given a list of+-- removed indices.+--+-- >>> originalIndices [False, False, True, False]+-- [0,1,3]+originalIndices+ :: [Bool]+ -- ^ Were voids. Length must be less than or equal to n.+ -> [Int]+ -- ^ Original indices+originalIndices wereVoids =+ [i | (i, void) <- zip [0..] wereVoids, not void]++-- | Converts an algebraic Core type (split into a TyCon and its argument) to a HWType.+mkADT+ :: (CustomReprs -> TyConMap -> Type ->+ State HWMap (Maybe (Either String FilteredHWType)))+ -- ^ Hardcoded Type -> HWType translator+ -> CustomReprs+ -> TyConMap+ -- ^ TyCon cache+ -> String+ -- ^ String representation of the Core type for error messages+ -> TyConName+ -- ^ The TyCon+ -> [Type]+ -- ^ Its applied arguments+ -> ExceptT String (State HWMap) FilteredHWType+ -- ^ An error string or a tuple with the type and possibly a list of+ -- removed arguments.+mkADT _ _ m tyString tc _+ | isRecursiveTy m tc+ = throwE $ $(curLoc) ++ "Can't translate recursive type: " ++ tyString++mkADT builtInTranslation reprs m _tyString tc args = case tyConDataCons (m `lookupUniqMap'` tc) of+ [] -> return (FilteredHWType (Void Nothing) [])+ dcs -> do+ let tcName = nameOcc tc+ substArgTyss = map (`substArgTys` args) dcs+ argHTyss0 <- mapM (mapM (ExceptT . coreTypeToHWType builtInTranslation reprs m)) substArgTyss+ let argHTyss1 = map (\tys -> zip (map isFilteredVoid tys) tys) argHTyss0+ let areVoids = map (map fst) argHTyss1+ let filteredArgHTyss = map (map snd . filter (not . fst)) argHTyss1++ -- Every alternative is annotated with some examples. Be sure to read them.+ case (dcs, filteredArgHTyss) of+ -- Type has one constructor and that constructor has a single field,+ -- modulo empty fields if keepVoid is False. Examples of such fields+ -- are:+ --+ -- >>> data ABC = ABC Int+ -- >>> data DEF = DEF Int ()+ --+ -- Notice that @DEF@'s constructor has an "empty" second argument. The+ -- second field of FilteredHWType would then look like:+ --+ -- >>> [[False, True]]+ (_:[],[[elemTy]]) ->+ return (FilteredHWType (stripFiltered elemTy) argHTyss1)++ -- Type has one constructor, but multiple fields modulo empty fields+ -- (see previous case for more thorough explanation). Examples:+ --+ -- >>> data GHI = GHI Int Int+ -- >>> data JKL = JKL Int () Int+ --+ -- In the second case the second field of FilteredHWType would be+ -- [[False, True, False]]+ ([dcFieldLabels -> labels0],[elemTys@(_:_)]) -> do+ labelsM <-+ if null labels0 then+ return Nothing+ else+ -- Filter out labels belonging to arguments filtered due to being+ -- void. See argHTyss1.+ let areNotVoids = map not (head areVoids) in+ let labels1 = filter fst (zip areNotVoids labels0) in+ let labels2 = map snd labels1 in+ return (Just labels2)+ let hwty = Product tcName labelsM (map stripFiltered elemTys)+ return (FilteredHWType hwty argHTyss1)++ -- Either none of the constructors have fields, or they have been filtered+ -- due to them being empty. Examples:+ --+ -- >>> data MNO = M | N | O+ -- >>> data PQR = P () | Q | R ()+ -- >>> data STU = STU+ -- >>> data VWX+ (_, concat -> [])+ -- If none of the dataconstructors have fields, and there are 1 or less+ -- of them, this type only has one inhabitant. It can therefore be+ -- represented by zero bits, and is therefore empty:+ | length dcs <= 1 ->+ return (FilteredHWType (Void Nothing) argHTyss1)+ -- None of the dataconstructors have fields. This type is therefore a+ -- simple Sum type.+ | otherwise ->+ return (FilteredHWType (Sum tcName $ map (nameOcc . dcName) dcs) argHTyss1)++ -- A sum of product, due to multiple constructors, where at least one+ -- of the constructor has one or more fields modulo empty fields. Example:+ --+ -- >>> data YZA = Y Int | Z () | A+ (_,elemHTys) ->+ return $ FilteredHWType (SP tcName $ zipWith+ (\dc tys -> ( nameOcc (dcName dc), tys))+ dcs (map stripFiltered <$> elemHTys)) argHTyss1++-- | Simple check if a TyCon is recursively defined.+isRecursiveTy :: TyConMap -> TyConName -> Bool+isRecursiveTy m tc = case tyConDataCons (m `lookupUniqMap'` tc) of+ [] -> False+ dcs -> let argTyss = map dcArgTys dcs+ argTycons = (map fst . catMaybes) $ (concatMap . map) splitTyConAppM argTyss+ in tc `elem` argTycons++-- | Determines if a Core type is translatable to a HWType given a function that+-- translates certain builtin types.+representableType+ :: (CustomReprs -> TyConMap -> Type ->+ State HWMap (Maybe (Either String FilteredHWType)))+ -> CustomReprs+ -> Bool+ -- ^ String considered representable+ -> TyConMap+ -> Type+ -> Bool+representableType builtInTranslation reprs stringRepresentable m =+ either (const False) isRepresentable .+ flip evalState HashMap.empty .+ coreTypeToHWType' builtInTranslation reprs m+ where+ isRepresentable hty = case hty of+ String -> stringRepresentable+ Vector _ elTy -> isRepresentable elTy+ RTree _ elTy -> isRepresentable elTy+ Product _ _ elTys -> all isRepresentable elTys+ SP _ elTyss -> all (all isRepresentable . snd) elTyss+ BiDirectional _ t -> isRepresentable t+ Annotated _ ty -> isRepresentable ty+ _ -> True++-- | Determines the bitsize of a type. For types that don't get turned+-- into real values in hardware (string, integer) the size is 0.+typeSize :: HWType+ -> Int+typeSize (Void {}) = 0+typeSize String = 0+typeSize Integer = 0+typeSize (KnownDomain {}) = 0+typeSize Bool = 1+typeSize Bit = 1+typeSize (Clock _) = 1+typeSize (Reset {}) = 1+typeSize (BitVector i) = i+typeSize (Index 0) = 0+typeSize (Index 1) = 1+typeSize (Index u) = fromMaybe 0 (clogBase 2 u)+typeSize (Signed i) = i+typeSize (Unsigned i) = i+typeSize (Vector n el) = n * typeSize el+typeSize (RTree d el) = (2^d) * typeSize el+typeSize t@(SP _ cons) = conSize t ++ maximum (map (sum . map typeSize . snd) cons)+typeSize (Sum _ dcs) = fromMaybe 0 . clogBase 2 . toInteger $ length dcs+typeSize (Product _ _ tys) = sum $ map typeSize tys+typeSize (BiDirectional In h) = typeSize h+typeSize (BiDirectional Out _) = 0+typeSize (CustomSP _ _ size _) = fromIntegral size+typeSize (CustomSum _ _ size _) = fromIntegral size+typeSize (Annotated _ ty) = typeSize ty++-- | Determines the bitsize of the constructor of a type+conSize :: HWType+ -> Int+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+ -> Term+ -> NetlistMonad HWType+termHWType loc e = do+ m <- Lens.use tcCache+ let ty = termType m e+ stripFiltered <$> unsafeCoreTypeToHWTypeM loc ty++-- | Gives the HWType corresponding to a term. Returns 'Nothing' if the term has+-- a Core type that is not translatable to a HWType.+termHWTypeM+ :: Term+ -- ^ Term to convert to HWType+ -> NetlistMonad (Maybe FilteredHWType)+termHWTypeM e = do+ m <- Lens.use tcCache+ let ty = termType m e+ coreTypeToHWTypeM ty++isBiSignalIn :: HWType -> Bool+isBiSignalIn (BiDirectional In _) = True+isBiSignalIn _ = False++containsBiSignalIn+ :: HWType+ -> Bool+containsBiSignalIn (BiDirectional In _) = True+containsBiSignalIn (Product _ _ tys) = any containsBiSignalIn tys+containsBiSignalIn (SP _ tyss) = any (any containsBiSignalIn . snd) tyss+containsBiSignalIn (Vector _ ty) = containsBiSignalIn ty+containsBiSignalIn (RTree _ ty) = containsBiSignalIn ty+containsBiSignalIn _ = False++-- | Helper function of @collectPortNames@, which operates on a @PortName@+-- instead of a TopEntity.+collectPortNames'+ :: [String]+ -> PortName+ -> [Identifier]+collectPortNames' prefixes (PortName nm) =+ let prefixes' = reverse (nm : prefixes) in+ [fromString (intercalate "_" prefixes')]+collectPortNames' prefixes (PortProduct "" nms) =+ concatMap (collectPortNames' prefixes) nms+collectPortNames' prefixes (PortProduct prefix nms) =+ concatMap (collectPortNames' (prefix : prefixes)) nms++-- | Recursively get all port names from top entity annotations. The result is+-- a list of user defined port names, which should not be used by routines+-- generating unique function names. Only completely qualified names are+-- returned, as it does not (and cannot) account for any implicitly named ports+-- under a PortProduct.+collectPortNames+ :: TopEntity+ -> [Identifier]+collectPortNames TestBench {} = []+collectPortNames Synthesize { t_inputs, t_output } =+ concatMap (collectPortNames' []) t_inputs ++ (collectPortNames' []) t_output++-- | Remove ports having a void-type from user supplied PortName annotation+filterVoidPorts+ :: FilteredHWType+ -> PortName+ -> PortName+filterVoidPorts _hwty (PortName s) =+ PortName s+filterVoidPorts (FilteredHWType _hwty [filtered]) (PortProduct s ps) =+ PortProduct s [filterVoidPorts f p | (p, (void, f)) <- zip ps filtered, not void]+filterVoidPorts (FilteredHWType _hwty fs) (PortProduct s ps)+ | length (filter (not.fst) (concat fs)) == 1+ , length ps == 2+ = PortProduct s ps+filterVoidPorts filtered pp@(PortProduct _s _ps) =+ -- TODO: Prettify errors+ error $ $(curLoc) ++ "Ports were annotated as product, but type wasn't one: \n\n"+ ++ " Filtered was: " ++ show filtered ++ "\n\n"+ ++ " Ports was: " ++ show pp++-- | Uniquely rename all the variables and their references in a normalized+-- term+mkUniqueNormalized+ :: InScopeSet+ -> Maybe (Maybe TopEntity)+ -- ^ Top entity annotation where:+ --+ -- * Nothing: term is not a top entity+ -- * Just Nothing: term is a top entity, but has no explicit annotation+ -- * Just (Just ..): term is a top entity, and has an explicit annotation+ -> ( [Id]+ , [LetBinding]+ , Id+ )+ -> NetlistMonad+ ([Bool]+ ,[(Identifier,HWType)]+ ,[Declaration]+ ,[(Identifier,HWType)]+ ,[Declaration]+ ,[LetBinding]+ ,Maybe Id)+mkUniqueNormalized is0 topMM (args,binds,res) = do+ -- Add user define port names to list of seen ids to prevent name collisions.+ let+ portNames =+ case join topMM of+ Nothing -> []+ Just top -> collectPortNames top++ seenIds %= (HashMap.unionWith max (HashMap.fromList (map (,0) portNames)))++ let (bndrs,exprs) = unzip binds++ -- Make arguments unique+ let is1 = is0 `extendInScopeSetList` (args ++ bndrs)+ (wereVoids, iports,iwrappers,substArgs) <- mkUniqueArguments (mkSubst is1) topMM args++ -- Make result unique. This might yield 'Nothing' in which case the result+ -- was a single BiSignalOut. This is superfluous in the HDL, as the argument+ -- will already contain a bidirectional signal complementing the BiSignalOut.+ resM <- mkUniqueResult substArgs topMM res+ case resM of+ Just (oports,owrappers,res1,substRes) -> do+ let usesOutput = concatMap (filter ( == res)+ . Lens.toListOf freeLocalIds+ ) exprs+ -- If the let-binder carrying the result is used in a feedback loop+ -- rename the let-binder to "<X>_rec", and assign the "<X>_rec" to+ -- "<X>". We do this because output ports in most HDLs cannot be read.+ (res2,subst'',extraBndr) <- case usesOutput of+ [] -> return (varName res1+ ,substRes+ ,[] :: [(Id, Term)])+ _ -> do+ ([res3],substRes') <- mkUnique substRes [modifyVarName (`appendToName` "_rec") res]+ return (varName res3,substRes'+ ,[(res1, Var res3)])+ -- Replace occurences of "<X>" by "<X>_rec"+ let resN = varName res+ bndrs' = map (\i -> if varName i == resN then modifyVarName (const res2) i else i) bndrs+ (bndrsL,r:bndrsR) = break ((== res2).varName) bndrs'+ -- Make let-binders unique+ (bndrsL',substL) <- mkUnique subst'' bndrsL+ (bndrsR',substR) <- mkUnique substL bndrsR+ -- Replace old IDs by updated unique IDs in the RHSs of the let-binders+ let exprs' = map (substTm ("mkUniqueNormalized1" :: Doc ()) substR) exprs+ -- Return the uniquely named arguments, let-binders, and result+ return (wereVoids,iports,iwrappers,oports,owrappers,zip (bndrsL' ++ r:bndrsR') exprs' ++ extraBndr,Just res1)+ Nothing -> do+ (bndrs', substArgs') <- mkUnique substArgs bndrs+ return (wereVoids,iports,iwrappers,[],[],zip bndrs' (map (substTm ("mkUniqueNormalized2" :: Doc ()) substArgs') exprs),Nothing)++mkUniqueArguments+ :: Subst+ -> Maybe (Maybe TopEntity)+ -- ^ Top entity annotation where:+ --+ -- * Nothing: term is not a top entity+ -- * Just Nothing: term is a top entity, but has no explicit annotation+ -- * Just (Just ..): term is a top entity, and has an explicit annotation+ -> [Id]+ -> NetlistMonad+ ( [Bool] -- Were voids+ , [(Identifier,HWType)] -- Arguments and their types+ , [Declaration] -- Extra declarations+ , Subst -- Substitution with new vars in scope+ )+mkUniqueArguments subst0 Nothing args = do+ (args',subst1) <- mkUnique subst0 args+ ports <- mapM idToInPort args'+ return (map isNothing ports, catMaybes ports, [], subst1)++mkUniqueArguments subst0 (Just teM) args = do+ let iPortSupply = maybe (repeat Nothing) (extendPorts . t_inputs) teM+ ports0 <- zipWithM go iPortSupply args+ let (ports1, decls, subst) = unzip3 (catMaybes ports0)+ return ( map isNothing ports0+ , concat ports1+ , concat decls+ , extendInScopeIdList (extendIdSubstList subst0 (map snd subst))+ (map fst subst))+ where+ go pM var = do+ let i = varName var+ i' = nameOcc i+ ty = varType var+ fHwty <- unsafeCoreTypeToHWTypeM $(curLoc) ty+ let FilteredHWType hwty _ = fHwty+ (ports,decls,_,pN) <- mkInput (filterVoidPorts fHwty <$> pM) (i',hwty)+ let pId = mkLocalId ty (repName pN i)+ if isVoid hwty+ then return Nothing+ else return (Just (ports,decls,(pId,(var,Var pId))))+++mkUniqueResult+ :: Subst+ -> Maybe (Maybe TopEntity)+ -- ^ Top entity annotation where:+ --+ -- * Nothing: term is not a top entity+ -- * Just Nothing: term is a top entity, but has no explicit annotation+ -- * Just (Just ..): term is a top entity, and has an explicit annotation+ -> Id+ -> NetlistMonad (Maybe ([(Identifier,HWType)],[Declaration],Id,Subst))+mkUniqueResult subst0 Nothing res = do+ ([res'],subst1) <- mkUnique subst0 [res]+ portM <- idToOutPort res'+ case portM of+ Just port -> return (Just ([port],[],res',subst1))+ _ -> return Nothing++mkUniqueResult subst0 (Just teM) res = do+ (_,sp) <- Lens.use curCompNm+ let o = varName res+ o' = nameOcc o+ ty = varType res+ fHwty <- unsafeCoreTypeToHWTypeM $(curLoc) ty+ let FilteredHWType hwty _ = fHwty+ oPortSupply = fmap t_output teM+ when (containsBiSignalIn hwty)+ (throw (ClashException sp ($(curLoc) ++ "BiSignalIn cannot be part of a function's result. Use 'readFromBiSignal'.") Nothing))+ output <- mkOutput (filterVoidPorts fHwty <$> oPortSupply) (o',hwty)+ case output of+ Just (ports, decls, pN) -> do+ let pO = repName pN o+ pOId = mkLocalId ty pO+ subst1 = extendInScopeId (extendIdSubst subst0 res (Var pOId)) pOId+ return (Just (ports,decls,pOId,subst1))+ _ -> return Nothing++-- | Same as idToPort, but+-- * Throws an error if the port is a composite type with a BiSignalIn+idToInPort :: Id -> NetlistMonad (Maybe (Identifier,HWType))+idToInPort var = do+ (_, sp) <- Lens.use curCompNm+ portM <- idToPort var+ case portM of+ Just (_,hty) -> do+ when (containsBiSignalIn hty && not (isBiSignalIn hty))+ (throw (ClashException sp ($(curLoc) ++ "BiSignalIn currently cannot be part of a composite type when it's a function's argument") Nothing))+ return portM+ _ -> return Nothing++-- | Same as idToPort, but:+-- * Throws an error if port is of type BiSignalIn+idToOutPort :: Id -> NetlistMonad (Maybe (Identifier,HWType))+idToOutPort var = do+ (_, srcspan) <- Lens.use curCompNm+ portM <- idToPort var+ case portM of+ Just (_,hty) -> do+ when (containsBiSignalIn hty)+ (throw (ClashException srcspan ($(curLoc) ++ "BiSignalIn cannot be part of a function's result. Use 'readFromBiSignal'.") Nothing))+ return portM+ _ -> return Nothing++idToPort :: Id -> NetlistMonad (Maybe (Identifier,HWType))+idToPort var = do+ let i = varName var+ ty = varType var+ hwTy <- unsafeCoreTypeToHWTypeM' $(curLoc) ty+ if isVoid hwTy+ then return Nothing+ else return (Just (nameOcc i, hwTy))++id2type :: Id -> Type+id2type = varType++id2identifier :: Id -> Identifier+id2identifier = nameOcc . varName++repName :: Text -> Name a -> Name a+repName s (Name sort' _ i loc) = Name sort' s i loc++-- | Make a set of IDs unique; also returns a substitution from old ID to new+-- updated unique ID.+mkUnique+ :: Subst+ -- ^ Existing substitution+ -> [Id]+ -- ^ IDs to make unique+ -> NetlistMonad ([Id],Subst)+ -- ^ (Unique IDs, update substitution)+mkUnique = go []+ where+ go :: [Id] -> Subst -> [Id] -> NetlistMonad ([Id],Subst)+ go processed subst [] = return (reverse processed,subst)+ go processed subst@(Subst isN _ _ _) (i:is) = do+ iN <- mkUniqueIdentifier Extended (id2identifier i)+ let i' = uniqAway isN (modifyVarName (repName iN) i)+ subst' = extendInScopeId (extendIdSubst subst i (Var i')) i'+ go (i':processed)+ subst'+ is++mkUniqueIdentifier+ :: IdType+ -> Identifier+ -> NetlistMonad Identifier+mkUniqueIdentifier typ nm = do+ seen <- Lens.use seenIds+ seenC <- Lens.use seenComps+ i <- mkIdentifier typ nm+ let getCopyIter k = getFirst (First (HashMap.lookup k seen) <> First (HashMap.lookup k seenC))+ case getCopyIter i of+ Just n -> go n getCopyIter i+ Nothing -> do+ seenIds %= HashMap.insert i 0+ return i+ where+ go :: Word -> (Identifier -> Maybe Word) -> Identifier -> NetlistMonad Identifier+ go n g i = do+ i' <- extendIdentifier typ i (Text.pack ('_':show n))+ case g i' of+ Just _ -> go (n+1) g i+ Nothing -> do+ seenIds %= HashMap.insert i (n+1)+ -- Don't forget to add the extended ID to the list of seen identifiers,+ -- in case we want to create a new identifier based on the extended ID+ -- we return in this function+ seenIds %= HashMap.insert i' 0+ return i'++-- | Preserve the Netlist '_varCount','_curCompNm','_seenIds' when executing a monadic action+preserveVarEnv :: NetlistMonad a+ -> NetlistMonad a+preserveVarEnv action = do+ -- store state+ vCnt <- Lens.use varCount+ vComp <- Lens.use curCompNm+ vSeen <- Lens.use seenIds+ -- perform action+ val <- action+ -- restore state+ varCount .= vCnt+ curCompNm .= vComp+ seenIds .= vSeen+ return val++dcToLiteral :: HWType -> Int -> Literal+dcToLiteral Bool 1 = BoolLit False+dcToLiteral Bool 2 = BoolLit True+dcToLiteral _ i = NumLit (toInteger i-1)++-- * TopEntity Annotations++extendPorts :: [PortName] -> [Maybe PortName]+extendPorts ps = map Just ps ++ repeat Nothing++portName+ :: String+ -> Identifier+ -> Identifier+portName [] i = i+portName x _ = Text.pack x++-- | Prefix given string before portnames /except/ when this string is empty.+prefixParent :: String -> PortName -> PortName+prefixParent "" p = p+prefixParent parent (PortName p) = PortName (parent <> "_" <> p)+prefixParent parent (PortProduct "" ps) = PortProduct parent ps+prefixParent parent (PortProduct p ps) = PortProduct (parent <> "_" <> p) ps+++appendIdentifier+ :: (Identifier,HWType)+ -> Int+ -> NetlistMonad (Identifier,HWType)+appendIdentifier (nm,hwty) i =+ (,hwty) <$> extendIdentifier Extended nm (Text.pack ('_':show i))++-- | In addition to the original port name (where the user should assert that+-- it's a valid identifier), we also add the version of the port name that has+-- gone through the 'mkIdentifier Basic' process. Why? so that the provided port+-- name is copied verbatim into the generated HDL, but that in e.g.+-- case-insensitive HDLs, a case-variant of the port name is not used as one+-- of the signal names.+uniquePortName+ :: String+ -> Identifier+ -> NetlistMonad Identifier+uniquePortName [] i = mkUniqueIdentifier Extended i+uniquePortName x _ = do+ let xT = Text.pack x+ xTB <- mkIdentifier Basic xT+ seenIds %= (\s -> List.foldl' (\m k -> HashMap.insert k 0 m) s [xT,xTB])+ return xT++mkInput+ :: Maybe PortName+ -> (Identifier,HWType)+ -> NetlistMonad ([(Identifier,HWType)],[Declaration],Expr,Identifier)+mkInput pM = case pM of+ Nothing -> go+ Just p -> go' p+ where+ -- No PortName given, infer names+ go (i,hwty) = do+ i' <- mkUniqueIdentifier Extended i+ let (attrs, hwty') = stripAttributes hwty+ case hwty' of+ Vector sz hwty'' -> do+ arguments <- mapM (appendIdentifier (i',hwty'')) [0..sz-1]+ (ports,_,exprs,_) <- unzip4 <$> mapM (mkInput Nothing) arguments+ let netdecl = NetDecl Nothing i' (Vector sz hwty'')+ vecExpr = mkVectorChain sz hwty'' exprs+ netassgn = Assignment i' vecExpr+ if null attrs then+ return (concat ports,[netdecl,netassgn],vecExpr,i')+ else+ throwAnnotatedSplitError $(curLoc) "Vector"++ RTree d hwty'' -> do+ arguments <- mapM (appendIdentifier (i',hwty'')) [0..2^d-1]+ (ports,_,exprs,_) <- unzip4 <$> mapM (mkInput Nothing) arguments+ let netdecl = NetDecl Nothing i' (RTree d hwty'')+ trExpr = mkRTreeChain d hwty'' exprs+ netassgn = Assignment i' trExpr+ if null attrs then+ return (concat ports,[netdecl,netassgn],trExpr,i')+ else+ throwAnnotatedSplitError $(curLoc) "RTree"++ Product _ _ hwtys -> do+ arguments <- zipWithM appendIdentifier (map (i',) hwtys) [0..]+ (ports,_,exprs,_) <- unzip4 <$> mapM (mkInput Nothing) arguments+ case exprs of+ [expr] ->+ let netdecl = NetDecl Nothing i' hwty+ dcExpr = expr+ netassgn = Assignment i' expr+ in return (concat ports,[netdecl,netassgn],dcExpr,i')+ _ ->+ let netdecl = NetDecl Nothing i' hwty+ dcExpr = DataCon hwty (DC (hwty,0)) exprs+ netassgn = Assignment i' dcExpr+ in if null attrs then+ return (concat ports,[netdecl,netassgn],dcExpr,i')+ else+ throwAnnotatedSplitError $(curLoc) "Product"++ _ -> return ([(i',hwty)],[],Identifier i' Nothing,i')+++ -- PortName specified by user+ go' (PortName p) (i,hwty) = do+ pN <- uniquePortName p i+ return ([(pN,hwty)],[],Identifier pN Nothing,pN)++ go' (PortProduct p ps) (i,hwty) = do+ pN <- uniquePortName p i+ let (attrs, hwty') = stripAttributes hwty+ case hwty' of+ Vector sz hwty'' -> do+ arguments <- mapM (appendIdentifier (pN,hwty'')) [0..sz-1]+ (ports,_,exprs,_) <- unzip4 <$> zipWithM mkInput (extendPorts $ map (prefixParent p) ps) arguments+ let netdecl = NetDecl Nothing pN (Vector sz hwty'')+ vecExpr = mkVectorChain sz hwty'' exprs+ netassgn = Assignment pN vecExpr+ if null attrs then+ return (concat ports,[netdecl,netassgn],vecExpr,pN)+ else+ throwAnnotatedSplitError $(curLoc) "Vector"++ RTree d hwty'' -> do+ arguments <- mapM (appendIdentifier (pN,hwty'')) [0..2^d-1]+ (ports,_,exprs,_) <- unzip4 <$> zipWithM mkInput (extendPorts $ map (prefixParent p) ps) arguments+ let netdecl = NetDecl Nothing pN (RTree d hwty'')+ trExpr = mkRTreeChain d hwty'' exprs+ netassgn = Assignment pN trExpr+ if null attrs then+ return (concat ports,[netdecl,netassgn],trExpr,pN)+ else+ throwAnnotatedSplitError $(curLoc) "RTree"++ Product _ _ hwtys -> do+ arguments <- zipWithM appendIdentifier (map (pN,) hwtys) [0..]+ let ps' = extendPorts $ map (prefixParent p) ps+ (ports,_,exprs,_) <- unzip4 <$> uncurry (zipWithM mkInput) (ps', arguments)+ case exprs of+ [expr] ->+ let netdecl = NetDecl Nothing pN hwty'+ dcExpr = expr+ netassgn = Assignment pN expr+ in return (concat ports,[netdecl,netassgn],dcExpr,pN)+ _ -> let netdecl = NetDecl Nothing pN hwty'+ dcExpr = DataCon hwty' (DC (hwty',0)) exprs+ netassgn = Assignment pN dcExpr+ in if null attrs then+ return (concat ports,[netdecl,netassgn],dcExpr,pN)+ else+ throwAnnotatedSplitError $(curLoc) "Product"++ SP _ ((concat . map snd) -> [elTy]) -> do+ let hwtys = [BitVector (conSize hwty'),elTy]+ arguments <- zipWithM appendIdentifier (map (pN,) hwtys) [0..]+ let ps' = extendPorts $ map (prefixParent p) ps+ (ports,_,exprs,_) <- unzip4 <$> uncurry (zipWithM mkInput) (ps', arguments)+ case exprs of+ [conExpr,elExpr] -> do+ let netdecl = NetDecl Nothing pN hwty'+ dcExpr = DataCon hwty' (DC (BitVector (typeSize hwty'),0))+ [conExpr,ConvBV Nothing elTy True elExpr]+ netassgn = Assignment pN dcExpr+ return (concat ports,[netdecl,netassgn],dcExpr,pN)+ _ -> error "Unexpected error for PortProduct"++ _ -> return ([(pN,hwty)],[],Identifier pN Nothing,pN)++-- | Create a Vector chain for a list of 'Identifier's+mkVectorChain :: Int+ -> HWType+ -> [Expr]+ -> Expr+mkVectorChain _ elTy [] = DataCon (Vector 0 elTy) VecAppend []+mkVectorChain _ elTy [e] = DataCon (Vector 1 elTy) VecAppend+ [e]+mkVectorChain sz elTy (e:es) = DataCon (Vector sz elTy) VecAppend+ [ e+ , mkVectorChain (sz-1) elTy es+ ]++-- | Create a RTree chain for a list of 'Identifier's+mkRTreeChain :: Int+ -> HWType+ -> [Expr]+ -> Expr+mkRTreeChain _ elTy [e] = DataCon (RTree 0 elTy) RTreeAppend+ [e]+mkRTreeChain d elTy es =+ let (esL,esR) = splitAt (length es `div` 2) es+ in DataCon (RTree d elTy) RTreeAppend+ [ mkRTreeChain (d-1) elTy esL+ , mkRTreeChain (d-1) elTy esR+ ]++genComponentName+ :: Bool+ -> HashMap Identifier Word+ -> (IdType -> Identifier -> Identifier)+ -> (Maybe Identifier,Maybe Identifier)+ -> Id+ -> Identifier+genComponentName newInlineStrat seen mkIdFn prefixM nm =+ let nm' = Text.splitOn (Text.pack ".") (nameOcc (varName nm))+ fn = mkIdFn Basic (stripDollarPrefixes (last nm'))+ fn' = if Text.null fn then Text.pack "Component" else fn+ prefix = maybe id (:) (snd prefixM) (if newInlineStrat then [] else init nm')+ nm2 = Text.concat (intersperse (Text.pack "_") (prefix ++ [fn']))+ nm3 = mkIdFn Basic nm2+ in case HashMap.lookup nm3 seen of+ Just n -> go n nm3+ Nothing -> nm3+ where+ go :: Word -> Identifier -> Identifier+ go n i =+ let i' = mkIdFn Basic (i `Text.append` Text.pack ('_':show n))+ in case HashMap.lookup i' seen of+ Just _ -> go (n+1) i+ Nothing -> i'++genTopComponentName+ :: Bool+ -> (IdType -> Identifier -> Identifier)+ -> (Maybe Identifier,Maybe Identifier)+ -> Maybe TopEntity+ -> Id+ -> Identifier+genTopComponentName _oldInlineStrat _mkIdFn prefixM (Just ann) _nm =+ case prefixM of+ (Just p,_) -> p `Text.append` Text.pack ('_':t_name ann)+ _ -> Text.pack (t_name ann)+genTopComponentName oldInlineStrat mkIdFn prefixM Nothing nm =+ genComponentName oldInlineStrat HashMap.empty mkIdFn prefixM nm+++-- | Strips one or more layers of attributes from a HWType; stops at first+-- non-Annotated. Accumilates all attributes of nested annotations.+stripAttributes+ :: HWType+ -> ([Attr'], HWType)+-- Recursively strip type, accumulate attrs:+stripAttributes (Annotated attrs typ) =+ let (attrs', typ') = stripAttributes typ+ in (attrs ++ attrs', typ')+-- Not an annotated type, so just return it:+stripAttributes typ = ([], typ)++-- | Generate output port mappings+mkOutput+ :: Maybe PortName+ -> (Identifier,HWType)+ -> NetlistMonad (Maybe ([(Identifier,HWType)],[Declaration],Identifier))+mkOutput _pM (_o, (BiDirectional Out _)) = return Nothing+mkOutput _pM (_o, (Void _)) = return Nothing+mkOutput pM (o, hwty) = Just <$> mkOutput' pM (o, hwty)++-- | Generate output port mappings. Will yield Nothing if the only output is+-- Void.+mkOutput'+ :: Maybe PortName+ -> (Identifier,HWType)+ -> NetlistMonad ([(Identifier,HWType)],[Declaration],Identifier)+mkOutput' pM = case pM of+ Nothing -> go+ Just p -> go' p+ where+ go (o,hwty) = do+ o' <- mkUniqueIdentifier Extended o+ let (attrs, hwty') = stripAttributes hwty+ case hwty' of+ Vector sz hwty'' -> do+ unless (null attrs)+ (throwAnnotatedSplitError $(curLoc) "Vector")+ results <- mapM (appendIdentifier (o',hwty'')) [0..sz-1]+ (ports,decls,ids) <- unzip3 <$> mapM (mkOutput' Nothing) results+ let netdecl = NetDecl Nothing o' hwty'+ assigns = zipWith (assignId o' hwty' 10) ids [0..]+ return (concat ports,netdecl:assigns ++ concat decls,o')++ RTree d hwty'' -> do+ unless (null attrs)+ (throwAnnotatedSplitError $(curLoc) "RTree")+ results <- mapM (appendIdentifier (o',hwty'')) [0..2^d-1]+ (ports,decls,ids) <- unzip3 <$> mapM (mkOutput' Nothing) results+ let netdecl = NetDecl Nothing o' hwty'+ assigns = zipWith (assignId o' hwty' 10) ids [0..]+ return (concat ports,netdecl:assigns ++ concat decls,o')++ Product _ _ hwtys -> do+ results <- zipWithM appendIdentifier (map (o,) hwtys) [0..]+ (ports,decls,ids) <- unzip3 <$> mapM (mkOutput' Nothing) results+ case ids of+ [i] ->+ let netdecl = NetDecl Nothing o' hwty+ assign = Assignment i (Identifier o' Nothing)+ in return (concat ports,netdecl:assign:concat decls,o')+ _ ->+ let netdecl = NetDecl Nothing o' hwty+ assigns = zipWith (assignId o' hwty 0) ids [0..]+ in if null attrs then+ return (concat ports,netdecl:assigns ++ concat decls,o')+ else+ throwAnnotatedSplitError $(curLoc) "Product"++ _ -> return ([(o',hwty)],[],o')++ go' (PortName p) (o,hwty) = do+ pN <- uniquePortName p o+ return ([(pN,hwty)],[],pN)++ go' (PortProduct p ps) (o,hwty) = do+ pN <- uniquePortName p o+ let (attrs, hwty') = stripAttributes hwty+ case hwty' of+ Vector sz hwty'' -> do+ unless (null attrs)+ (throwAnnotatedSplitError $(curLoc) "Vector")+ results <- mapM (appendIdentifier (pN,hwty'')) [0..sz-1]+ (ports,decls,ids) <- unzip3 <$> zipWithM mkOutput' (extendPorts $ map (prefixParent p) ps) results+ let netdecl = NetDecl Nothing pN hwty'+ assigns = zipWith (assignId pN hwty' 10) ids [0..]+ return (concat ports,netdecl:assigns ++ concat decls,pN)++ RTree d hwty'' -> do+ unless (null attrs)+ (throwAnnotatedSplitError $(curLoc) "RTree")+ results <- mapM (appendIdentifier (pN,hwty'')) [0..2^d-1]+ (ports,decls,ids) <- unzip3 <$> zipWithM mkOutput' (extendPorts $ map (prefixParent p) ps) results+ let netdecl = NetDecl Nothing pN hwty'+ assigns = zipWith (assignId pN hwty' 10) ids [0..]+ return (concat ports,netdecl:assigns ++ concat decls,pN)++ Product _ _ hwtys -> do+ results <- zipWithM appendIdentifier (map (pN,) hwtys) [0..]+ let ps' = extendPorts $ map (prefixParent p) ps+ (ports,decls,ids) <- unzip3 <$> uncurry (zipWithM mkOutput') (ps', results)+ case ids of+ [i] -> let netdecl = NetDecl Nothing pN hwty'+ assign = Assignment i (Identifier pN Nothing)+ in return (concat ports,netdecl:assign:concat decls,pN)+ _ -> let netdecl = NetDecl Nothing pN hwty'+ assigns = zipWith (assignId pN hwty' 0) ids [0..]+ in if null attrs then+ return (concat ports,netdecl:assigns ++ concat decls,pN)+ else+ throwAnnotatedSplitError $(curLoc) "Product"++ SP _ ((concat . map snd) -> [elTy]) -> do+ let hwtys = [BitVector (conSize hwty'),elTy]+ results <- zipWithM appendIdentifier (map (pN,) hwtys) [0..]+ let ps' = extendPorts $ map (prefixParent p) ps+ (ports,decls,ids) <- unzip3 <$> uncurry (zipWithM mkOutput') (ps', results)+ case ids of+ [conId,elId] ->+ let netdecl = NetDecl Nothing pN hwty'+ conIx = Sliced (BitVector (typeSize hwty')+ ,typeSize hwty' - 1+ ,typeSize elTy+ )+ elIx = Sliced (BitVector (typeSize hwty')+ ,typeSize elTy - 1+ ,0+ )+ assigns = [Assignment conId (Identifier pN (Just conIx))+ ,Assignment elId (ConvBV Nothing elTy False+ (Identifier pN (Just elIx)))+ ]+ in return (concat ports,netdecl:assigns ++ concat decls,pN)+ _ -> error "Unexpected error for PortProduct"++ _ -> return ([(pN,hwty)],[],pN)++ assignId p hwty con i n =+ Assignment i (Identifier p (Just (Indexed (hwty,con,n))))++-- | Instantiate a TopEntity, and add the proper type-conversions where needed+mkTopUnWrapper+ :: Id+ -- ^ Name of the TopEntity component+ -> Maybe TopEntity+ -- ^ (maybe) a corresponding @TopEntity@ annotation+ -> Manifest+ -- ^ a corresponding @Manifest@+ -> (Identifier,HWType)+ -- ^ The name and type of the signal to which to assign the result+ -> [(Expr,HWType)]+ -- ^ The arguments+ -> [Declaration]+ -- ^ Tick declarations+ -> NetlistMonad [Declaration]+mkTopUnWrapper topEntity annM man dstId args tickDecls = do+ let inTys = portInTypes man+ outTys = portOutTypes man+ inNames = portInNames man+ outNames = portOutNames man++ -- component name+ newInlineStrat <- opt_newInlineStrat <$> Lens.use clashOpts+ mkIdFn <- Lens.use mkIdentifierFn+ prefixM <- Lens.use componentPrefix+ let topName = genTopComponentName newInlineStrat mkIdFn prefixM annM topEntity+ topM = fmap (const topName) annM++ -- inputs+ let iPortSupply = maybe (repeat Nothing)+ (extendPorts . t_inputs)+ annM+ arguments <- zipWithM appendIdentifier (map (\a -> ("input",snd a)) args) [0..]+ (_,arguments1) <- mapAccumLM (\acc (p,i) -> mkTopInput topM acc p i)+ (zip inNames inTys)+ (zip iPortSupply arguments)+ let (iports,wrappers,idsI) = unzip3 arguments1+ inpAssigns = zipWith (argBV topM) idsI (map fst args)++ -- output+ let oPortSupply = maybe+ (repeat Nothing)+ (extendPorts . (:[]) . t_output)+ annM++ let iResult = inpAssigns ++ concat wrappers+ result = ("result",snd dstId)++ topOutputM <- mkTopOutput+ topM+ (zip outNames outTys)+ (head oPortSupply)+ result++ (iResult ++) <$> case topOutputM of+ Nothing -> return []+ Just (_, (oports, unwrappers, idsO)) -> do+ instLabel0 <- extendIdentifier Basic topName ("_" `Text.append` fst dstId)+ instLabel1 <- mkUniqueIdentifier Basic instLabel0+ let outpAssign = Assignment (fst dstId) (resBV topM idsO)+ let topCompDecl = InstDecl+ Entity+ (Just topName)+ topName+ instLabel1+ []+ ( map (\(p,i,t) -> (Identifier p Nothing,In, t,Identifier i Nothing)) (concat iports) +++ map (\(p,o,t) -> (Identifier p Nothing,Out,t,Identifier o Nothing)) oports)++ return $ tickDecls ++ (topCompDecl:unwrappers) ++ [outpAssign]++-- | Convert between BitVector for an argument+argBV+ :: Maybe Identifier+ -- ^ (maybe) Name of the _TopEntity_+ -> Either Identifier (Identifier, HWType)+ -- ^ Either:+ -- * A /normal/ argument+ -- * An argument with a @PortName@+ -> Expr+ -> Declaration+argBV _ (Left i) e = Assignment i e+argBV topM (Right (i,t)) e = Assignment i+ . doConv t (fmap Just topM) False+ $ doConv t (fmap (const Nothing) topM) True e++-- | Convert between BitVector for the result+resBV+ :: Maybe Identifier+ -- ^ (mabye) Name of the _TopEntity_+ -> Either Identifier (Identifier, HWType)+ -- ^ Either:+ -- * A /normal/ result+ -- * A result with a @PortName@+ -> Expr+resBV _ (Left i) = Identifier i Nothing+resBV topM (Right (i,t)) = doConv t (fmap (const Nothing) topM) False+ . doConv t (fmap Just topM) True+ $ Identifier i Nothing+++-- | Add to/from-BitVector conversion logic+doConv+ :: HWType+ -- ^ We only need it for certain types+ -> Maybe (Maybe Identifier)+ -- ^+ -- * Nothing: No _given_ TopEntity, no need for conversion, this+ -- happens when we have a _TestBench_, but no+ -- _TopEntity_ annotation.+ -- * Just Nothing: Converting to/from a BitVector for one of the+ -- internally defined types.+ -- * Just (Just top): Converting to/from a BitVector for one of the+ -- types defined by @top@.+ -> Bool+ -- ^+ -- * True: convert to a BitVector+ -- * False: convert from a BitVector+ -> Expr+ -- ^ The expression on top of which we have to add conversion logic+ -> Expr+doConv _ Nothing _ e = e+doConv hwty (Just topM) b e = case hwty of+ Vector {} -> ConvBV topM hwty b e+ RTree {} -> ConvBV topM hwty b e+ Product {} -> ConvBV topM hwty b e+ _ -> e++-- | Generate input port mappings for the TopEntity+mkTopInput+ :: Maybe Identifier+ -- ^ (maybe) Name of the _TopEntity_+ -> [(Identifier,Identifier)]+ -- ^ /Rendered/ input port names and types+ -> Maybe PortName+ -- ^ (maybe) The @PortName@ of a _TopEntity_ annotation for this input+ -> (Identifier,HWType)+ -> NetlistMonad ([(Identifier,Identifier)]+ ,([(Identifier,Identifier,HWType)]+ ,[Declaration]+ ,Either Identifier (Identifier,HWType)))+mkTopInput topM inps pM = case pM of+ Nothing -> go inps+ Just p -> go' p inps+ where+ -- No @PortName@+ go inps'@((iN,_):rest) (i,hwty) = do+ i' <- mkUniqueIdentifier Basic i+ let iDecl = NetDecl Nothing i' hwty+ let (attrs, hwty') = stripAttributes hwty+ case hwty' of+ Vector sz hwty'' -> do+ arguments <- mapM (appendIdentifier (i',hwty'')) [0..sz-1]+ (inps'',arguments1) <- mapAccumLM go inps' arguments+ let (ports,decls,ids) = unzip3 arguments1+ assigns = zipWith (argBV topM) ids+ [ Identifier i' (Just (Indexed (hwty,10,n)))+ | n <- [0..]]+ if null attrs then+ return (inps'',(concat ports,iDecl:assigns++concat decls,Left i'))+ else+ throwAnnotatedSplitError $(curLoc) "Vector"++ RTree d hwty'' -> do+ arguments <- mapM (appendIdentifier (i',hwty'')) [0..2^d-1]+ (inps'',arguments1) <- mapAccumLM go inps' arguments+ let (ports,decls,ids) = unzip3 arguments1+ assigns = zipWith (argBV topM) ids+ [ Identifier i' (Just (Indexed (hwty,10,n)))+ | n <- [0..]]+ if null attrs then+ return (inps'',(concat ports,iDecl:assigns++concat decls,Left i'))+ else+ throwAnnotatedSplitError $(curLoc) "RTree"++ Product _ _ hwtys -> do+ arguments <- zipWithM appendIdentifier (map (i,) hwtys) [0..]+ (inps'',arguments1) <- mapAccumLM go inps' arguments+ let (ports,decls,ids) = unzip3 arguments1+ assigns = zipWith (argBV topM) ids+ [ Identifier i' (Just (Indexed (hwty,0,n)))+ | n <- [0..]]+ if null attrs then+ return (inps'',(concat ports,iDecl:assigns++concat decls,Left i'))+ else+ throwAnnotatedSplitError $(curLoc) "Product"++ _ -> return (rest,([(iN,i',hwty)],[iDecl],Left i'))++ go [] _ = error "This shouldn't happen"++ -- With a @PortName@+ go' (PortName _) ((iN,iTy):inps') (_,hwty) = do+ iN' <- mkUniqueIdentifier Extended iN+ return (inps',([(iN,iN',hwty)]+ ,[NetDecl' Nothing Wire iN' (Left iTy)]+ ,Right (iN',hwty)))++ go' (PortName _) [] _ = error "This shouldnt happen"++ go' (PortProduct p ps) inps' (i,hwty) = do+ let pN = portName p i+ pN' <- mkUniqueIdentifier Extended pN+ let pDecl = NetDecl Nothing pN' hwty+ let (attrs, hwty') = stripAttributes hwty+ case hwty' of+ Vector sz hwty'' -> do+ arguments <- mapM (appendIdentifier (pN',hwty'')) [0..sz-1]+ (inps'',arguments1) <-+ mapAccumLM (\acc (p',o') -> mkTopInput topM acc p' o') inps'+ (zip (extendPorts ps) arguments)+ let (ports,decls,ids) = unzip3 arguments1+ assigns = zipWith (argBV topM) ids+ [ Identifier pN' (Just (Indexed (hwty,10,n)))+ | n <- [0..]]+ if null attrs then+ return (inps'',(concat ports,pDecl:assigns ++ concat decls,Left pN'))+ else+ throwAnnotatedSplitError $(curLoc) "Vector"++ RTree d hwty'' -> do+ arguments <- mapM (appendIdentifier (pN',hwty'')) [0..2^d-1]+ (inps'',arguments1) <-+ mapAccumLM (\acc (p',o') -> mkTopInput topM acc p' o') inps'+ (zip (extendPorts ps) arguments)+ let (ports,decls,ids) = unzip3 arguments1+ assigns = zipWith (argBV topM) ids+ [ Identifier pN' (Just (Indexed (hwty,10,n)))+ | n <- [0..]]+ if null attrs then+ return (inps'',(concat ports,pDecl:assigns ++ concat decls,Left pN'))+ else+ throwAnnotatedSplitError $(curLoc) "RTree"++ Product _ _ hwtys -> do+ arguments <- zipWithM appendIdentifier (map (pN',) hwtys) [0..]+ (inps'',arguments1) <-+ mapAccumLM (\acc (p',o') -> mkTopInput topM acc p' o') inps'+ (zip (extendPorts ps) arguments)+ let (ports,decls,ids) = unzip3 arguments1+ assigns = zipWith (argBV topM) ids+ [ Identifier pN' (Just (Indexed (hwty,0,n)))+ | n <- [0..]]+ if null attrs then+ return (inps'',(concat ports,pDecl:assigns ++ concat decls,Left pN'))+ else+ throwAnnotatedSplitError $(curLoc) "Product"++ SP _ ((concat . map snd) -> [elTy]) -> do+ let hwtys = [BitVector (conSize hwty'),elTy]+ arguments <- zipWithM appendIdentifier (map (pN',) hwtys) [0..]+ (inps'',arguments1) <-+ mapAccumLM (\acc (p',o') -> mkTopInput topM acc p' o') inps'+ (zip (extendPorts ps) arguments)+ let (ports,decls,ids) = unzip3 arguments1+ case ids of+ [conId,elId] -> do+ let conIx = Sliced (BitVector (typeSize hwty')+ ,typeSize hwty' - 1+ ,typeSize elTy+ )+ elIx = Sliced (BitVector (typeSize hwty')+ ,typeSize elTy - 1+ ,0+ )+ assigns = [argBV topM conId (Identifier pN (Just conIx))+ ,argBV topM elId (ConvBV Nothing elTy False+ (Identifier pN (Just elIx)))+ ]+ return (inps'',(concat ports,pDecl:assigns ++ concat decls,Left pN'))+ _ -> error "Unexpected error for PortProduct"++ _ -> return (tail inps',([(pN,pN',hwty)],[pDecl],Left pN'))+++-- | Consider the following type signature:+--+-- @+-- f :: Signal dom (Vec 6 A) \`Annotate\` Attr "keep"+-- -> Signal dom (Vec 6 B)+-- @+--+-- What does the annotation mean, considering that Clash will split these+-- vectors into multiple in- and output ports? Should we apply the annotation+-- to all individual ports? How would we handle pin mappings? For now, we simply+-- throw an error. This is a helper function to do so.+throwAnnotatedSplitError+ :: String+ -> String+ -> NetlistMonad a+throwAnnotatedSplitError loc typ = do+ (_,sp) <- Lens.use curCompNm+ throw $ ClashException sp (loc ++ printf msg typ typ) Nothing+ where+ msg = unwords $ [ "Attempted to split %s into a number of HDL ports. This"+ , "is not allowed in combination with attribute annotations."+ , "You can annotate %s's components by splitting it up"+ , "manually." ]++-- | Generate output port mappings for the TopEntity. Yields /Nothing/ if+-- the output is Void+mkTopOutput+ :: Maybe Identifier+ -- ^ (maybe) Name of the _TopEntity_+ -> [(Identifier,Identifier)]+ -- ^ /Rendered/ output port names and types+ -> Maybe PortName+ -- ^ (maybe) The @PortName@ of a _TopEntity_ annotation for this output+ -> (Identifier,HWType)+ -> NetlistMonad ( Maybe ( [(Identifier, Identifier)]+ , ( [(Identifier, Identifier, HWType)]+ , [Declaration]+ , Either Identifier (Identifier,HWType)+ )+ )+ )+mkTopOutput _topM _outps _pM (_id, BiDirectional Out _) = return Nothing+mkTopOutput _topM _outps _pM (_id, Void _) = return Nothing+mkTopOutput topM outps pM (o, hwty) =+ Just <$> mkTopOutput' topM outps pM (o, hwty)++-- | Generate output port mappings for the TopEntity+mkTopOutput'+ :: Maybe Identifier+ -- ^ (maybe) Name of the _TopEntity_+ -> [(Identifier,Identifier)]+ -- ^ /Rendered/ output port names and types+ -> Maybe PortName+ -- ^ (maybe) The @PortName@ of a _TopEntity_ annotation for this output+ -> (Identifier,HWType)+ -> NetlistMonad ([(Identifier,Identifier)]+ ,([(Identifier,Identifier,HWType)]+ ,[Declaration]+ ,Either Identifier (Identifier,HWType))+ )+mkTopOutput' topM outps pM = case pM of+ Nothing -> go outps+ Just p -> go' p outps+ where+ -- No @PortName@+ go outps'@((oN,_):rest) (o,hwty) = do+ o' <- mkUniqueIdentifier Extended o+ let oDecl = NetDecl Nothing o' hwty+ let (attrs, hwty') = stripAttributes hwty+ case hwty' of+ Vector sz hwty'' -> do+ results <- mapM (appendIdentifier (o',hwty'')) [0..sz-1]+ (outps'',results1) <- mapAccumLM go outps' results+ let (ports,decls,ids) = unzip3 results1+ ids' = map (resBV topM) ids+ netassgn = Assignment o' (mkVectorChain sz hwty'' ids')+ if null attrs then+ return (outps'',(concat ports,oDecl:netassgn:concat decls,Left o'))+ else+ throwAnnotatedSplitError $(curLoc) "Vector"++ RTree d hwty'' -> do+ results <- mapM (appendIdentifier (o',hwty'')) [0..2^d-1]+ (outps'',results1) <- mapAccumLM go outps' results+ let (ports,decls,ids) = unzip3 results1+ ids' = map (resBV topM) ids+ netassgn = Assignment o' (mkRTreeChain d hwty'' ids')+ if null attrs then+ return (outps'',(concat ports,oDecl:netassgn:concat decls,Left o'))+ else+ throwAnnotatedSplitError $(curLoc) "RTree"++ Product _ _ hwtys -> do+ results <- zipWithM appendIdentifier (map (o',) hwtys) [0..]+ (outps'',results1) <- mapAccumLM go outps' results+ let (ports,decls,ids) = unzip3 results1+ ids' = map (resBV topM) ids+ netassgn = Assignment o' (DataCon hwty (DC (hwty,0)) ids')+ if null attrs then+ return (outps'', (concat ports,oDecl:netassgn:concat decls,Left o'))+ else+ throwAnnotatedSplitError $(curLoc) "Product"++ _ -> return (rest,([(oN,o',hwty)],[oDecl],Left o'))++ go [] _ = error "This shouldn't happen"++ -- With a @PortName@+ go' (PortName _) ((oN,oTy):outps') (_,hwty) = do+ oN' <- mkUniqueIdentifier Extended oN+ return (outps',([(oN,oN',hwty)]+ ,[NetDecl' Nothing Wire oN' (Left oTy)]+ ,Right (oN',hwty)))++ go' (PortName _) [] _ = error "This shouldnt happen"++ go' (PortProduct p ps) outps' (o,hwty) = do+ let pN = portName p o+ pN' <- mkUniqueIdentifier Extended pN+ let pDecl = NetDecl Nothing pN' hwty+ let (attrs, hwty') = stripAttributes hwty+ case hwty' of+ Vector sz hwty'' -> do+ results <- mapM (appendIdentifier (pN',hwty'')) [0..sz-1]+ (outps'',results1) <-+ mapAccumLM (\acc (p',o') -> mkTopOutput' topM acc p' o') outps'+ (zip (extendPorts ps) results)+ let (ports,decls,ids) = unzip3 results1+ ids' = map (resBV topM) ids+ netassgn = Assignment pN' (mkVectorChain sz hwty'' ids')+ if null attrs then+ return (outps'',(concat ports,pDecl:netassgn:concat decls,Left pN'))+ else+ throwAnnotatedSplitError $(curLoc) "Vector"++ RTree d hwty'' -> do+ results <- mapM (appendIdentifier (pN',hwty'')) [0..2^d-1]+ (outps'',results1) <-+ mapAccumLM (\acc (p',o') -> mkTopOutput' topM acc p' o') outps'+ (zip (extendPorts ps) results)+ let (ports,decls,ids) = unzip3 results1+ ids' = map (resBV topM) ids+ netassgn = Assignment pN' (mkRTreeChain d hwty'' ids')+ if null attrs then+ return (outps'',(concat ports,pDecl:netassgn:concat decls,Left pN'))+ else+ throwAnnotatedSplitError $(curLoc) "RTree"++ Product _ _ hwtys -> do+ results <- zipWithM appendIdentifier (map (pN',) hwtys) [0..]+ (outps'',results1) <-+ mapAccumLM (\acc (p',o') -> mkTopOutput' topM acc p' o') outps'+ (zip (extendPorts ps) results)+ let (ports,decls,ids) = unzip3 results1+ ids' = map (resBV topM) ids+ netassgn = Assignment pN' (DataCon hwty (DC (hwty,0)) ids')+ if null attrs then+ return (outps'',(concat ports,pDecl:netassgn:concat decls,Left pN'))+ else+ throwAnnotatedSplitError $(curLoc) "Product"+++ SP _ ((concat . map snd) -> [elTy]) -> do+ let hwtys = [BitVector (conSize elTy),elTy]+ results <- zipWithM appendIdentifier (map (pN',) hwtys) [0..]+ (outps'',results1) <-+ mapAccumLM (\acc (p',o') -> mkTopOutput' topM acc p' o') outps'+ (zip (extendPorts ps) results)+ let (ports,decls,ids) = unzip3 results1+ ids1 = map (resBV topM) ids+ ids2 = case ids1 of+ [conId,elId] -> [conId,ConvBV Nothing elTy True elId]+ _ -> error "Unexpected error for PortProduct"+ netassgn = Assignment pN' (DataCon hwty (DC (BitVector (typeSize hwty),0)) ids2)+ return (outps'',(concat ports,pDecl:netassgn:concat decls,Left pN'))++ _ -> return (tail outps',([(pN,pN',hwty)],[pDecl],Left pN'))++concatPortDecls3+ :: [([(Identifier,Identifier,HWType)]+ ,[Declaration]+ ,Either Identifier (Identifier,HWType))]+ -> ([(Identifier,Identifier,HWType)]+ ,[Declaration]+ ,[Either Identifier (Identifier,HWType)])+concatPortDecls3 portDecls = case unzip3 portDecls of+ (ps,decls,ids) -> (concat ps, concat decls, ids)++-- | Try to merge nested modifiers into a single modifier, needed by the VHDL+-- and SystemVerilog backend.+nestM :: Modifier -> Modifier -> Maybe Modifier+nestM (Nested a b) m2+ | Just m1 <- nestM a b = maybe (Just (Nested m1 m2)) Just (nestM m1 m2)+ | Just m2' <- nestM b m2 = maybe (Just (Nested a m2')) Just (nestM a m2')++nestM (Indexed (Vector n t1,1,1)) (Indexed (Vector _ t2,1,0))+ | t1 == t2 = Just (Indexed (Vector n t1,10,1))++nestM (Indexed (Vector n t1,1,1)) (Indexed (Vector _ t2,10,k))+ | t1 == t2 = Just (Indexed (Vector n t1,10,k+1))++nestM (Indexed (RTree d1 t1,1,n)) (Indexed (RTree d2 t2,0,0))+ | t1 == t2+ , d1 >= 0+ , d2 >= 0+ = Just (Indexed (RTree d1 t1,10,n))++nestM (Indexed (RTree d1 t1,1,n)) (Indexed (RTree d2 t2,1,m))+ | t1 == t2+ , d1 >= 0+ , d2 >= 0+ = if | n == 1 && m == 1 -> let r = 2 ^ d1+ l = r - (2 ^ (d1-1) `div` 2)+ in Just (Indexed (RTree (-1) t1, l, r))+ | n == 1 && m == 0 -> let l = 2 ^ (d1-1)+ r = l + (l `div` 2)+ in Just (Indexed (RTree (-1) t1, l, r))+ | n == 0 && m == 1 -> let l = (2 ^ (d1-1)) `div` 2+ r = 2 ^ (d1-1)+ in Just (Indexed (RTree (-1) t1, l, r))+ | n == 0 && m == 0 -> let l = 0+ r = (2 ^ (d1-1)) `div` 2+ in Just (Indexed (RTree (-1) t1, l, r))+ | n > 1 || n < 0 -> error $ "nestM: n should be 0 or 1, not:" ++ show n+ | m > 1 || m < 0 -> error $ "nestM: m should be 0 or 1, not:" ++ show m+ | otherwise -> error $ "nestM: unexpected (n, m): " ++ show (n, m)+nestM (Indexed (RTree (-1) t1,l,_)) (Indexed (RTree d t2,10,k))+ | t1 == t2+ , d >= 0+ = Just (Indexed (RTree d t1,10,l+k))++nestM _ _ = Nothing+++-- | Determines if any type variables (exts) are bound in any of the given+-- type or term variables (tms). It's currently only used to detect bound+-- existentials, hence the name.+bindsExistentials+ :: [TyVar]+ -> [Var a]+ -> Bool+bindsExistentials exts tms = any (`elem` freeVars) exts+ where+ freeVars = concatMap (Lens.toListOf typeFreeVars) (map varType tms)++iteAlts :: HWType -> [Alt] -> Maybe (Term,Term)+iteAlts sHTy [(pat0,alt0),(pat1,alt1)] | validIteSTy sHTy = case pat0 of+ DataPat dc _ _ -> case dcTag dc of+ 2 -> Just (alt0,alt1)+ _ -> Just (alt1,alt0)+ LitPat (C.IntegerLiteral l) -> case l of+ 1 -> Just (alt0,alt1)+ _ -> Just (alt1,alt0)+ DefaultPat -> case pat1 of+ DataPat dc _ _ -> case dcTag dc of+ 2 -> Just (alt1,alt0)+ _ -> Just (alt0,alt1)+ LitPat (C.IntegerLiteral l) -> case l of+ 1 -> Just (alt1,alt0)+ _ -> Just (alt0,alt1)+ _ -> Nothing+ _ -> Nothing+ where+ validIteSTy Bool = True+ validIteSTy Bit = True+ validIteSTy (Sum _ [_,_]) = True+ validIteSTy (SP _ [_,_]) = True+ validIteSTy (Unsigned 1) = True+ validIteSTy (Index 2) = True+ validIteSTy _ = False++iteAlts _ _ = Nothing++-- | Run a NetlistMonad computation in the context of the given source ticks and+-- name modifier ticks+withTicks+ :: [TickInfo]+ -> ([Declaration] -> NetlistMonad a)+ -- ^ The source ticks are turned into 'TickDecl's and are passed as an argument+ -- to the NetlistMonad computation. Name modifier ticks will change the local+ -- environment for the NetlistMonad computation.+ -> NetlistMonad a+withTicks ticks0 k = do+ let ticks1 = List.nub ticks0+ go [] (reverse ticks1)+ where+ go decls [] = k (reverse decls)++ go decls (SrcSpan sp:ticks) =+ go (TickDecl (Text.pack (showSDocUnsafe (ppr sp))):decls) ticks++ go decls (NameMod m nm0:ticks) = do+ tcm <- Lens.use tcCache+ case runExcept (tySym tcm nm0) of+ Right nm1 -> local (modName m nm1) (go decls ticks)+ _ -> go decls ticks++ modName PrefixName (Text.pack -> s2) env@(NetlistEnv {_prefixName = s1})+ | Text.null s1 = env {_prefixName = s2}+ | otherwise = env {_prefixName = s1 <> "_" <> s2}+ modName SuffixName (Text.pack -> s2) env@(NetlistEnv {_suffixName = s1})+ | Text.null s1 = env {_suffixName = s2}+ | otherwise = env {_suffixName = s2 <> "_" <> s1}+ modName SetName (Text.pack -> s) env = env {_setName = Just s}++-- | Add the pre- and suffix names in the current environment to the given+-- identifier+affixName+ :: Identifier+ -> NetlistMonad Identifier+affixName nm0 = do+ NetlistEnv pre suf _ <- ask+ let nm1 = if Text.null pre then nm0 else pre <> "_" <> nm0+ nm2 = if Text.null suf then nm1 else nm1 <> "_" <> suf+ return nm2
src/Clash/Normalize.hs view
@@ -8,18 +8,27 @@ Turn CoreHW terms into normalized CoreHW Terms -} -{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE BangPatterns #-} +{-# OPTIONS_GHC -Wno-unused-imports #-}+ module Clash.Normalize where +import Data.Either+ import Control.Concurrent.Supply (Supply)-import Control.Lens ((.=),(^.),_2,_5)+import Control.Lens ((.=),(^.),_1,_4) import qualified Control.Lens as Lens+import Control.Monad.State.Strict (State)+import Data.Binary (encode)+import qualified Data.ByteString as BS+import qualified Data.ByteString.Lazy as BL import Data.Either (partitionEithers)-import Data.HashMap.Strict (HashMap)-import qualified Data.HashMap.Strict as HashMap-import qualified Data.HashSet as HashSet import qualified Data.IntMap as IntMap import Data.IntMap.Strict (IntMap) import Data.List@@ -30,42 +39,49 @@ import qualified Data.Set.Lens as Lens import Data.Semigroup ((<>)) import Data.Text.Prettyprint.Doc (vcat)-import Unbound.Generics.LocallyNameless (unembed, runLFreshM)+import System.IO.Unsafe (unsafePerformIO) import BasicTypes (InlineSpec (..)) import SrcLoc (SrcSpan,noSrcSpan) +import Clash.Annotations.BitRepresentation.Internal+ (CustomReprs) import Clash.Core.Evaluator (PrimEvaluator)-import Clash.Core.FreeVars (termFreeIds)-import Clash.Core.Name (Name (..), NameSort (..))-import Clash.Core.Pretty (showDoc, ppr)-import Clash.Core.Subst (substTms)-import Clash.Core.Term (Term (..), TmName, TmOccName)+import Clash.Core.FreeVars+ (freeLocalIds, globalIds, globalIdOccursIn, localIdDoesNotOccurIn)+import Clash.Core.Pretty (showPpr, ppr)+import Clash.Core.Subst+ (deShadowTerm, extendGblSubstList, mkSubst, substTm)+import Clash.Core.Term (Term (..), collectArgsTicks) import Clash.Core.Type (Type, splitCoreFunForallTy) import Clash.Core.TyCon- (TyCon, TyConName, TyConOccName)-import Clash.Core.Util (collectArgs, mkApps, termType)-import Clash.Core.Var (Id,varName)+ (TyConMap, TyConName)+import Clash.Core.Util (mkApps, mkTicks, termType)+import Clash.Core.Var (Id, varName, varType)+import Clash.Core.VarEnv+ (VarEnv, elemVarSet, eltsVarEnv, emptyInScopeSet, emptyVarEnv,+ extendVarEnv, lookupVarEnv, mapVarEnv, mapMaybeVarEnv, mkInScopeSet,+ mkVarEnv, mkVarSet, notElemVarEnv, notElemVarSet, nullVarEnv, unionVarEnv) import Clash.Driver.Types (BindingMap, ClashOpts (..), DebugLevel (..))-import Clash.Netlist.BlackBox.Types (BlackBoxTemplate)-import Clash.Netlist.Types (HWType (..))+import Clash.Netlist.Types+ (HWType (..), HWMap, FilteredHWType(..)) import Clash.Netlist.Util- (splitNormalized, unsafeCoreTypeToHWType)+ (splitNormalized, coreTypeToHWType') import Clash.Normalize.Strategy import Clash.Normalize.Transformations- (appProp, bindConstantVar, caseCon, flattenLet, reduceConst, topLet)+ (appProp, bindConstantVar, caseCon, flattenLet, reduceConst, topLet,+ reduceNonRepPrim, removeUnusedExpr) import Clash.Normalize.Types import Clash.Normalize.Util-import Clash.Primitives.Types (PrimMap)+import Clash.Primitives.Types (CompiledPrimMap) import Clash.Rewrite.Combinators ((>->),(!->)) import Clash.Rewrite.Types (RewriteEnv (..), RewriteState (..), bindings, curFun, dbgLevel, extra,- tcCache, topEntities, typeTranslator)-import Clash.Rewrite.Util (isUntranslatableType,- runRewrite,- runRewriteSession)-import Clash.Signal.Internal (ResetKind (..))+ tcCache, topEntities, typeTranslator, customReprs, RewriteStep (..))+import Clash.Rewrite.Util+ (apply, isUntranslatableType, runRewrite, runRewriteSession)+import Clash.Signal.Internal (ResetKind (..)) import Clash.Util -- | Run a NormalizeSession in a given environment@@ -76,24 +92,26 @@ -- ^ UniqueSupply -> BindingMap -- ^ Global Binders- -> (HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType))+ -> (CustomReprs -> TyConMap -> Type ->+ State HWMap (Maybe (Either String FilteredHWType))) -- ^ Hardcoded Type -> HWType translator- -> HashMap TyConOccName TyCon+ -> CustomReprs+ -> TyConMap -- ^ TyCon cache -> IntMap TyConName -- ^ Tuple TyCon cache -> PrimEvaluator -- ^ Hardcoded evaluator (delta-reduction)- -> PrimMap BlackBoxTemplate+ -> CompiledPrimMap -- ^ Primitive Definitions- -> HashMap TmOccName Bool+ -> VarEnv Bool -- ^ Map telling whether a components is part of a recursive group- -> [TmOccName]+ -> [Id] -- ^ topEntities -> NormalizeSession a -- ^ NormalizeSession to run -> a-runNormalization opts supply globals typeTrans tcm tupTcm eval primMap rcsMap topEnts+runNormalization opts supply globals typeTrans reprs tcm tupTcm eval primMap rcsMap topEnts = runRewriteSession rwEnv rwState where rwEnv = RewriteEnv@@ -102,8 +120,8 @@ tcm tupTcm eval- (opt_allowZero opts)- (HashSet.fromList topEnts)+ (mkVarSet topEnts)+ reprs rwState = RewriteState 0@@ -115,144 +133,118 @@ normState normState = NormalizeState- HashMap.empty+ emptyVarEnv Map.empty- HashMap.empty+ emptyVarEnv (opt_specLimit opts)- HashMap.empty+ emptyVarEnv (opt_inlineLimit opts) (opt_inlineFunctionLimit opts) (opt_inlineConstantLimit opts) primMap+ Map.empty rcsMap+ (opt_newInlineStrat opts)+ (opt_ultra opts) normalize- :: [TmOccName]+ :: [Id] -> NormalizeSession BindingMap-normalize [] = return HashMap.empty+normalize [] = return emptyVarEnv normalize top = do (new,topNormalized) <- unzip <$> mapM normalize' top newNormalized <- normalize (concat new)- return (HashMap.union (HashMap.fromList topNormalized) newNormalized)+ return (unionVarEnv (mkVarEnv topNormalized) newNormalized) normalize'- :: TmOccName- -> NormalizeSession ([TmOccName],(TmOccName,(TmName,Type,SrcSpan,InlineSpec,Term)))+ :: Id+ -> NormalizeSession ([Id],(Id,(Id,SrcSpan,InlineSpec,Term))) normalize' nm = do- exprM <- HashMap.lookup nm <$> Lens.use bindings- let nmS = showDoc nm+ exprM <- lookupVarEnv nm <$> Lens.use bindings+ let nmS = showPpr (varName nm) case exprM of- Just (nm',ty,sp,inl,tm) -> do+ Just (nm',sp,inl,tm) -> do tcm <- Lens.view tcCache- let (_,resTy) = splitCoreFunForallTy tcm ty+ let (_,resTy) = splitCoreFunForallTy tcm (varType nm') resTyRep <- not <$> isUntranslatableType False resTy if resTyRep then do- tmNorm <- makeCached nm (extra.normalized) $ do- curFun .= (nm',sp)- tm' <- rewriteExpr ("normalization",normalization) (nmS,tm)- ty' <- termType tcm tm'- return (nm',ty',sp,inl,tm')- let usedBndrs = Lens.toListOf termFreeIds (tmNorm ^. _5)+ tmNorm <- normalizeTopLvlBndr nm (nm',sp,inl,tm)+ let usedBndrs = Lens.toListOf globalIds (tmNorm ^. _4) traceIf (nm `elem` usedBndrs) (concat [ $(curLoc),"Expr belonging to bndr: ",nmS ," (:: "- , showDoc (tmNorm ^. _2)+ , showPpr (varType (tmNorm ^. _1)) , ") remains recursive after normalization:\n"- , showDoc (tmNorm ^. _5) ])+ , showPpr (tmNorm ^. _4) ]) (return ())- tyTrans <- Lens.view typeTranslator- case clockResetErrors sp tyTrans tcm ty of- msgs@(_:_) -> traceIf True (concat (nmS:" (:: ":showDoc (tmNorm ^. _2)- :")\nhas potentially dangerous meta-stability issues:\n\n"- :msgs))- (return ())- _ -> return ()- prevNorm <- fmap HashMap.keys $ Lens.use (extra.normalized)+ prevNorm <- mapVarEnv (Lens.view _1) <$> Lens.use (extra.normalized) topEnts <- Lens.view topEntities- let toNormalize = filter (not . (`HashSet.member` topEnts))- $ filter (`notElem` (nm:prevNorm)) usedBndrs+ let toNormalize = filter (`notElemVarSet` topEnts)+ $ filter (`notElemVarEnv` (extendVarEnv nm nm prevNorm)) usedBndrs return (toNormalize,(nm,tmNorm)) else do- let usedBndrs = Lens.toListOf termFreeIds tm- prevNorm <- fmap HashMap.keys $ Lens.use (extra.normalized)+ let usedBndrs = Lens.toListOf globalIds tm+ prevNorm <- mapVarEnv (Lens.view _1) <$> Lens.use (extra.normalized) topEnts <- Lens.view topEntities- let toNormalize = filter (not . (`HashSet.member` topEnts))- $ filter (`notElem` (nm:prevNorm)) usedBndrs+ let toNormalize = filter (`notElemVarSet` topEnts)+ $ filter (`notElemVarEnv` (extendVarEnv nm nm prevNorm)) usedBndrs lvl <- Lens.view dbgLevel traceIf (lvl >= DebugFinal) (concat [$(curLoc), "Expr belonging to bndr: ", nmS, " (:: "- , showDoc ty+ , showPpr (varType nm') , ") has a non-representable return type."- , " Not normalising:\n", showDoc tm] )- (return (toNormalize,(nm,(nm',ty,sp,inl,tm))))+ , " Not normalising:\n", showPpr tm] )+ (return (toNormalize,(nm,(nm',sp,inl,tm)))) Nothing -> error $ $(curLoc) ++ "Expr belonging to bndr: " ++ nmS ++ " not found" --- | Rewrite a term according to the provided transformation-rewriteExpr :: (String,NormRewrite) -- ^ Transformation to apply- -> (String,Term) -- ^ Term to transform- -> NormalizeSession Term-rewriteExpr (nrwS,nrw) (bndrS,expr) = do- lvl <- Lens.view dbgLevel- let before = showDoc expr- let expr' = traceIf (lvl >= DebugFinal)- (bndrS ++ " before " ++ nrwS ++ ":\n\n" ++ before ++ "\n")- expr- rewritten <- runRewrite nrwS nrw expr'- let after = showDoc rewritten- traceIf (lvl >= DebugFinal)- (bndrS ++ " after " ++ nrwS ++ ":\n\n" ++ after ++ "\n") $- return rewritten- -- | Check whether the normalized bindings are non-recursive. Errors when one -- of the components is recursive. checkNonRecursive :: BindingMap -- ^ List of normalized binders -> BindingMap-checkNonRecursive norm = case Maybe.mapMaybe go (HashMap.toList norm) of- [] -> norm- rcs -> error $ $(curLoc) ++ "Callgraph after normalisation contains following recursive components: "- ++ show (vcat $ runLFreshM $ sequence [ do a' <- ppr a- b' <- ppr b- return $ a' <> b'- | (a,b ) <- rcs- ])- where- go (nm,(_,_,_,_,tm)) =- let used = Lens.toListOf termFreeIds tm- in if nm `elem` used- then Just (nm,tm)- else Nothing+checkNonRecursive norm = case mapMaybeVarEnv go norm of+ rcs | nullVarEnv rcs -> norm+ rcs -> error $ $(curLoc) ++ "Callgraph after normalisation contains following recursive components: "+ ++ show (vcat [ ppr a <> ppr b+ | (a,b) <- eltsVarEnv rcs+ ])+ where+ go (nm,_,_,tm) =+ if nm `globalIdOccursIn` tm+ then Just (nm,tm)+ else Nothing + -- | Perform general \"clean up\" of the normalized (non-recursive) function -- hierarchy. This includes: -- -- * Inlining functions that simply \"wrap\" another function cleanupGraph- :: TmOccName+ :: Id -> BindingMap -> NormalizeSession BindingMap cleanupGraph topEntity norm | Just ct <- mkCallTree [] norm topEntity = do ctFlat <- flattenCallTree ct- return (HashMap.fromList $ snd $ callTreeToList [] ctFlat)+ return (mkVarEnv $ snd $ callTreeToList [] ctFlat) cleanupGraph _ norm = return norm -data CallTree = CLeaf (TmOccName,(TmName,Type,SrcSpan,InlineSpec,Term))- | CBranch (TmOccName,(TmName,Type,SrcSpan,InlineSpec,Term)) [CallTree]+data CallTree = CLeaf (Id,(Id,SrcSpan,InlineSpec,Term))+ | CBranch (Id,(Id,SrcSpan,InlineSpec,Term)) [CallTree] mkCallTree- :: [TmOccName]+ :: [Id] -- ^ Visited -> BindingMap -- ^ Global binders- -> TmOccName+ -> Id -- ^ Root of the call graph -> Maybe CallTree mkCallTree visited bindingMap root- | Just rootTm <- HashMap.lookup root bindingMap- = let used = Set.toList $ Lens.setOf termFreeIds $ (rootTm ^. _5)+ | Just rootTm <- lookupVarEnv root bindingMap+ = let used = Set.toList $ Lens.setOf globalIds $ (rootTm ^. _4) other = Maybe.mapMaybe (mkCallTree (root:visited) bindingMap) (filter (`notElem` visited) used) in case used of [] -> Just (CLeaf (root,rootTm))@@ -260,7 +252,7 @@ mkCallTree _ _ _ = Nothing stripArgs- :: [TmOccName]+ :: [Id] -> [Id] -> [Either Term Type] -> Maybe [Either Term Type]@@ -269,78 +261,118 @@ then Nothing else Just args where- mentionsId t = not $ null (either (Lens.toListOf termFreeIds) (const []) t+ mentionsId t = not $ null (either (Lens.toListOf freeLocalIds) (const []) t `intersect` allIds) -stripArgs allIds (id_:ids) (Left (Var _ nm):args)- | varName id_ == nm = stripArgs allIds ids args- | otherwise = Nothing+stripArgs allIds (id_:ids) (Left (Var nm):args)+ | id_ == nm = stripArgs allIds ids args+ | otherwise = Nothing stripArgs _ _ _ = Nothing flattenNode :: CallTree- -> NormalizeSession (Either CallTree ((TmOccName,Term),[CallTree]))-flattenNode (CLeaf (nm,(nameSort -> Internal,_,_,_,e))) =- return (Right ((nm,e),[]))-flattenNode c@(CLeaf (nm,(_,_,_,_,e))) = do- tcm <- Lens.view tcCache- norm <- splitNormalized tcm e- case norm of- Right (ids,[(_,bExpr)],_) -> do- let (fun,args) = collectArgs (unembed bExpr)- case stripArgs (map (nameOcc.varName) ids) (reverse ids) (reverse args) of- Just remainder -> return (Right ((nm,mkApps fun (reverse remainder)),[]))- Nothing -> return (Right ((nm,e),[]))- _ | isCheapFunction e -> return (Right ((nm,e),[]))- | otherwise -> return (Left c)-flattenNode (CBranch (nm,(nameSort -> Internal,_,_,_,e)) us) =- return (Right ((nm,e),us))-flattenNode b@(CBranch (nm,(_,_,_,_,e)) us) = do- tcm <- Lens.view tcCache- norm <- splitNormalized tcm e- case norm of- Right (ids,[(_,bExpr)],_) -> do- let (fun,args) = collectArgs (unembed bExpr)- case stripArgs (map (nameOcc.varName) ids) (reverse ids) (reverse args) of- Just remainder -> return (Right ((nm,mkApps fun (reverse remainder)),us))- Nothing -> return (Right ((nm,e),us))- _ | isCheapFunction e -> return (Right ((nm,e),us))- | otherwise -> return (Left b)+ -> NormalizeSession (Either CallTree ((Id,Term),[CallTree]))+flattenNode c@(CLeaf (_,(_,_,NoInline,_))) = return (Left c)+flattenNode c@(CLeaf (nm,(_,_,_,e))) = do+ isTopEntity <- elemVarSet nm <$> Lens.view topEntities+ if isTopEntity then return (Left c) else do+ tcm <- Lens.view tcCache+ let norm = splitNormalized tcm e+ case norm of+ Right (ids,[(bId,bExpr)],_) -> do+ let (fun,args,ticks) = collectArgsTicks bExpr+ case stripArgs ids (reverse ids) (reverse args) of+ Just remainder | bId `localIdDoesNotOccurIn` bExpr ->+ return (Right ((nm,mkApps (mkTicks fun ticks) (reverse remainder)),[]))+ _ -> return (Right ((nm,e),[]))+ _ -> return (Right ((nm,e),[]))+flattenNode b@(CBranch (_,(_,_,NoInline,_)) _) =+ return (Left b)+flattenNode b@(CBranch (nm,(_,_,_,e)) us) = do+ isTopEntity <- elemVarSet nm <$> Lens.view topEntities+ if isTopEntity then return (Left b) else do+ tcm <- Lens.view tcCache+ let norm = splitNormalized tcm e+ case norm of+ Right (ids,[(bId,bExpr)],_) -> do+ let (fun,args,ticks) = collectArgsTicks bExpr+ case stripArgs ids (reverse ids) (reverse args) of+ Just remainder | bId `localIdDoesNotOccurIn` bExpr ->+ return (Right ((nm,mkApps (mkTicks fun ticks) (reverse remainder)),us))+ _ -> return (Right ((nm,e),us))+ _ -> do+ newInlineStrat <- Lens.use (extra.newInlineStrategy)+ if newInlineStrat || isCheapFunction e+ then return (Right ((nm,e),us))+ else return (Left b) flattenCallTree :: CallTree -> NormalizeSession CallTree flattenCallTree c@(CLeaf _) = return c-flattenCallTree (CBranch (nm,(nm',ty,sp,inl,tm)) used) = do+flattenCallTree (CBranch (nm,(nm',sp,inl,tm)) used) = do flattenedUsed <- mapM flattenCallTree used (newUsed,il_ct) <- partitionEithers <$> mapM flattenNode flattenedUsed let (toInline,il_used) = unzip il_ct+ subst = extendGblSubstList (mkSubst emptyInScopeSet) toInline newExpr <- case toInline of- [] -> return tm- _ -> rewriteExpr ("flattenExpr",flatten) (showDoc nm, substTms toInline tm)+ [] -> return tm+ _ -> do+ -- To have a cheap `appProp` transformation we need to+ -- deshadow, see also Note [AppProp no-shadow invariant]+ let tm1 = deShadowTerm emptyInScopeSet (substTm "flattenCallTree.flattenExpr" subst tm)+#ifdef HISTORY+ -- NB: When HISTORY is on, emit binary data holding the recorded rewrite steps+ let !_ = unsafePerformIO+ $ BS.appendFile "history.dat"+ $ BL.toStrict+ $ encode RewriteStep+ { t_ctx = []+ , t_name = "INLINE"+ , t_bndrS = showPpr (varName nm')+ , t_before = tm+ , t_after = tm1+ }+#endif+ rewriteExpr ("flattenExpr",flatten) (showPpr nm, tm1) (nm', sp) let allUsed = newUsed ++ concat il_used -- inline all components when the resulting expression after flattening -- is still considered "cheap". This happens often at the topEntity which -- wraps another functions and has some selectors and data-constructors.- if isCheapFunction newExpr+ if inl /= NoInline && isCheapFunction newExpr then do let (toInline',allUsed') = unzip (map goCheap allUsed)- newExpr' <- rewriteExpr ("flattenCheap",flatten) (showDoc nm, substTms toInline' newExpr)- return (CBranch (nm,(nm',ty,sp,inl,newExpr')) (concat allUsed'))- else return (CBranch (nm,(nm',ty,sp,inl,newExpr)) allUsed)+ subst' = extendGblSubstList (mkSubst emptyInScopeSet)+ (Maybe.catMaybes toInline')+ -- To have a cheap `appProp` transformation we need to+ -- deshadow, see also Note [AppProp no-shadow invariant]+ let tm1 = deShadowTerm emptyInScopeSet (substTm "flattenCallTree.flattenCheap" subst' newExpr)+ newExpr' <- rewriteExpr ("flattenCheap",flatten) (showPpr nm, tm1) (nm', sp)+ return (CBranch (nm,(nm',sp,inl,newExpr')) (concat allUsed'))+ else return (CBranch (nm,(nm',sp,inl,newExpr)) allUsed) where flatten =- innerMost (appProp >-> bindConstantVar >-> caseCon >-> reduceConst >-> flattenLet) !->- topdownSucR topLet+ innerMost (apply "appProp" appProp >->+ apply "bindConstantVar" bindConstantVar >->+ apply "caseCon" caseCon >->+ apply "reduceConst" reduceConst >->+ apply "reduceNonRepPrim" reduceNonRepPrim >->+ apply "removeUnusedExpr" removeUnusedExpr >->+ apply "flattenLet" flattenLet) !->+ topdownSucR (apply "topLet" topLet) - goCheap (CLeaf (nm2,(_,_,_,_,e))) = ((nm2,e),[])- goCheap (CBranch (nm2,(_,_,_,_,e)) us) = ((nm2,e),us)+ goCheap c@(CLeaf (nm2,(_,_,inl2,e)))+ | inl2 == NoInline = (Nothing ,[c])+ | otherwise = (Just (nm2,e),[])+ goCheap c@(CBranch (nm2,(_,_,inl2,e)) us)+ | inl2 == NoInline = (Nothing, [c])+ | otherwise = (Just (nm2,e),us) callTreeToList- :: [TmOccName]+ :: [Id] -> CallTree- -> ([TmOccName],[(TmOccName,(TmName,Type,SrcSpan,InlineSpec,Term))])+ -> ([Id],[(Id,(Id,SrcSpan,InlineSpec,Term))]) callTreeToList visited (CLeaf (nm,bndr)) | nm `elem` visited = (visited,[]) | otherwise = (nm:visited,[(nm,bndr)])@@ -349,60 +381,3 @@ | otherwise = (visited',(nm,bndr):(concat others)) where (visited',others) = mapAccumL callTreeToList (nm:visited) used---- | Clash's clock and reset domain annotations prevent most accidental--- meta-stability situations. That is, unless the developer uses the--- functions marked "unsafe", the type system will prevent things like--- illegal clock domain crossing, or improper use of asynchronous resets.------ However, this all depends on clock and resets being unique. With explicit--- clocks and resets, it is possible to have multiple clock and reset arguments--- that are annotated with the same domain. If these arguments aren't connected--- to the same source, we can still get metastability due to either illegal--- clock domain crossing, or improper use of asynchronous resets.------ The following situations are reported:--- * There are 2 or more clock arguments in scope that have the same clock--- domain annotation.--- * There are 2 or more reset arguments in scope that have the same reset--- domain annotation, and at least one of them is an asynchronous reset.-clockResetErrors- :: SrcSpan- -> (HashMap TyConOccName TyCon -> Bool -> Type -> Maybe (Either String HWType))- -> HashMap TyConOccName TyCon- -> Type- -> [String]-clockResetErrors sp tyTran tcm ty =- (Maybe.mapMaybe reportClock clks ++ Maybe.mapMaybe reportResets rsts)- where- (args,_) = splitCoreFunForallTy tcm ty- (_,args') = partitionEithers args- hwArgs = zip (map (unsafeCoreTypeToHWType sp $(curLoc) tyTran tcm False) args') args'- clks = groupBy ((==) `on` fst) . sortBy (compare `on` fst)- $ [ ((nm,i),ty') | (Clock nm i _,ty') <- hwArgs]- rsts = groupBy ((==) `on` (fst.fst)) . sortBy (compare `on` (fst.fst))- $ [ (((nm,i),s),ty') | (Reset nm i s,ty') <- hwArgs]-- reportClock clks'- | length clks' >= 2- = Just- $ concat ["The following clocks:\n"- ,concatMap (\c -> "* " ++ showDoc (snd c) ++ "\n") clks'- ,"belong to the same clock domain and should be connected to "- ,"the same clock source in order to prevent meta-stability "- ,"issues."- ]- | otherwise- = Nothing-- reportResets rsts'- | length rsts' >= 2- , any (\((_,sync),_) -> sync == Asynchronous) rsts'- = Just- $ concat ["The following resets:\n"- ,concatMap (\c -> "* " ++ showDoc (snd c) ++ "\n") rsts'- ,"belong to the same reset domain, and one or more of these "- ,"resets is Asynchronous. Ensure that these resets are "- ,"synchronized in order to prevent meta-stability issues."- ]- reportResets _ = Nothing
src/Clash/Normalize/DEC.hs view
@@ -45,37 +45,36 @@ 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.HashMap.Strict as HashMap import qualified Data.IntMap.Strict as IM+import qualified Data.IntSet as IntSet import qualified Data.List as List import qualified Data.Map.Strict as Map import qualified Data.Maybe as Maybe-import Data.Set (Set)-import qualified Data.Set as Set-import qualified Data.Set.Lens as Lens--import Unbound.Generics.LocallyNameless- (Bind, bind, embed, fv, unbind, unembed, unrec)-import qualified Unbound.Generics.LocallyNameless as Unbound+import Data.Monoid (All (..)) -- internal import Clash.Core.DataCon (DataCon, dcTag) import Clash.Core.Evaluator (whnf')-import Clash.Core.FreeVars (termFreeIds, typeFreeVars)-import Clash.Core.Name (Name (..), string2InternalName)+import Clash.Core.FreeVars+ (termFreeVars', typeFreeVars', localVarsDoNotOccurIn) import Clash.Core.Literal (Literal (..))-import Clash.Core.Term (LetBinding, Pat (..), Term (..), TmOccName)+import Clash.Core.Term+ (LetBinding, Pat (..), PrimInfo (..), Term (..), collectArgs, collectArgsTicks) import Clash.Core.TyCon (tyConDataCons) import Clash.Core.Type (Type, isPolyFunTy, mkTyConApp, splitFunForallTy)-import Clash.Core.Util (collectArgs, mkApps, termType)+import Clash.Core.Util (mkApps, mkTicks, patIds, termType)+import Clash.Core.Var (isGlobalId)+import Clash.Core.VarEnv+ (InScopeSet, elemInScopeSet, notElemInScopeSet) import Clash.Normalize.Types (NormalizeState)-import Clash.Normalize.Util (isConstant) import Clash.Rewrite.Types (RewriteMonad, bindings, evaluator, globalHeap, tcCache, tupleTcCache, uniqSupply) import Clash.Rewrite.Util (mkInternalVar, mkSelectorCase,- isUntranslatableType)+ isUntranslatableType, isConstant)+import Clash.Unique (lookupUniqMap) import Clash.Util data CaseTree a@@ -118,23 +117,29 @@ -- | 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 ::- Set TmOccName- -> [(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,[(Term,([Term],CaseTree [(Either Term Type)]))])-collectGlobals inScope substitution seen (Case scrut ty alts) = do+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, [(Term, ([Term], CaseTree [Either Term Type]))])+collectGlobals' inScope substitution seen (Case scrut ty alts) _eIsConstant = do rec (alts' ,collected) <- collectGlobalsAlts inScope substitution seen scrut' alts (scrut',collected') <- collectGlobals inScope substitution (map fst collected ++ seen) scrut return (Case scrut' ty alts',collected ++ collected') -collectGlobals inScope substitution seen e@(collectArgs -> (fun, args@(_:_)))- | not (isConstant e) = do+collectGlobals' inScope substitution seen e@(collectArgsTicks -> (fun, args@(_:_), ticks)) eIsconstant+ | not eIsconstant = do tcm <- Lens.view tcCache bndrs <- Lens.use bindings primEval <- Lens.view evaluator@@ -142,48 +147,67 @@ ids <- Lens.use uniqSupply let (ids1,ids2) = splitSupply ids uniqSupply Lens..= ids2- let eval = snd . whnf' primEval bndrs tcm gh ids1 False- eTy <- termType tcm e+ let eval = (Lens.view Lens._3) . whnf' primEval bndrs tcm gh ids1 inScope False+ 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 -> case interestingToLift inScope eval fun args of- Just fun' | fun' `notElem` seen -> do- (args',collected) <- collectGlobalsArgs inScope substitution- (fun':seen) args- let e' = Maybe.fromMaybe (mkApps fun' args') (List.lookup fun' 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 (e',(fun',(seen,Leaf args')):collected)- _ -> do (args',collected) <- collectGlobalsArgs inScope substitution- seen args- return (mkApps fun args',collected)+ False -> do+ isInteresting <- interestingToLift inScope eval fun args+ case isInteresting of+ Just fun' | fun' `notElem` seen -> do+ (args',collected) <- collectGlobalsArgs inScope substitution+ (fun':seen) args+ let e' = Maybe.fromMaybe (mkApps fun' args') (List.lookup fun' 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 (e',(fun',(seen,Leaf args')):collected)+ _ -> do (args',collected) <- collectGlobalsArgs inScope substitution+ seen args+ return (mkApps (mkTicks fun ticks) args',collected) _ -> return (e,[]) -- 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 inScope substitution seen (Letrec b) = do- (unrec -> lbs,body) <- unbind b+collectGlobals' inScope substitution seen (Letrec lbs body) _eIsConstant = do (body',collected) <- collectGlobals inScope substitution seen body (lbs',collected') <- collectGlobalsLbs inScope substitution (map fst collected ++ seen) lbs- return (Letrec (bind (Unbound.rec lbs') body')+ return (Letrec lbs' body' ,map (second (second (LB lbs'))) (collected ++ collected') ) -collectGlobals _ _ _ e = return (e,[])+collectGlobals' _ _ _ e _ = return (e,[]) -- | 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, [(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 ::- Set TmOccName+ InScopeSet -> [(Term,Term)] -- ^ Substitution of (applications of) a global -- binder by a reference to a lifted term. -> [Term] -- ^ List of already seen global binders@@ -205,14 +229,14 @@ -- of a list of alternatives. Also substitute truly disjoint applications of -- globals by a reference to a lifted out application. collectGlobalsAlts ::- Set TmOccName+ 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- -> [Bind Pat Term] -- ^ The list of alternatives+ -> [(Pat,Term)] -- ^ The list of alternatives -> RewriteMonad NormalizeState- ([Bind Pat Term]+ ([(Pat,Term)] ,[(Term,([Term],CaseTree [(Either Term Type)]))] ) collectGlobalsAlts inScope substitution seen scrut alts = do@@ -222,15 +246,15 @@ collected' = map (second (second (Branch scrut))) (Map.toList collectedUN) return (alts',collected') where- go pe = do (p,e) <- unbind pe- (e',collected) <- collectGlobals inScope substitution seen e- return (bind p e',map (second (second (p,))) collected)+ go (p,e) = do+ (e',collected) <- collectGlobals inScope substitution seen e+ return ((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 ::- Set TmOccName+ InScopeSet -> [(Term,Term)] -- ^ Substitution of (applications of) a global -- binder by a reference to a lifted term. -> [Term] -- ^ List of already seen global binders@@ -250,61 +274,68 @@ ,[(Term,([Term],CaseTree [(Either Term Type)]))] ) )- go s (id_,unembed -> e) = do+ go s (id_, e) = do (e',collected) <- collectGlobals inScope substitution s e- return (map fst collected ++ s,((id_,embed e'),collected))+ return (map fst collected ++ s,((id_,e'),collected)) -- | 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 uncommon arguments of the case-tree,--- and the body is an application of the term applied to the common arguments of--- the case tree, and projections of let-binding corresponding to the uncommon+-- 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 :: Set TmOccName -- ^ Current free variables.- -> (Term,([Term],CaseTree [(Either Term Type)]))- -- ^ Case-tree of arguments belonging to the applied term.- -> RewriteMonad NormalizeState (Term,[Term])-mkDisjointGroup fvs (fun,(seen,cs)) = do+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)- (commonT,uncommonT) = List.partition (isCommon fvs . snd) argssT- common = map (second head) commonT- uncommon = map (Either.lefts) (List.transpose (map snd uncommonT))+ (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 common+ (if null shared then cs'- else fmap (filter (`notElem` common)) cs')+ else fmap (filter (`notElem` shared)) cs') tcm <- Lens.view tcCache- (uncommonCaseM,uncommonProjections) <- case uncommon of- -- only common arguments: do nothing.+ (distinctCaseM,distinctProjections) <- case distinct of+ -- only shared arguments: do nothing. [] -> return (Nothing,[]) -- Create selectors and projections (uc:_) -> do- argTys <- mapM (termType tcm) uc- disJointSelProj argTys cs''- let newArgs = mkDJArgs 0 common uncommonProjections- case uncommonCaseM of- Just lb -> return (Letrec (bind (Unbound.rec [lb]) (mkApps fun newArgs)), seen)+ 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 uncommon arguments by+-- | 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 uncommon arguments: a selector--- * For all the representable uncommon arguments: a projection out of the tuple+-- * 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 uncommon argument.-disJointSelProj :: [Type] -- ^ Types of the arguments- -> CaseTree [Term] -- The case-tree of arguments- -> RewriteMonad NormalizeState (Maybe LetBinding,[Term])-disJointSelProj _ (Leaf []) = return (Nothing,[])-disJointSelProj argTys cs = do+-- 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 let maxIndex = length argTys - 1 css = map (\i -> fmap ((:[]) . (!!i)) cs) [0..maxIndex] (untran,tran) <- partitionM (isUntranslatableType False . snd) (zip [0..] argTys)@@ -319,16 +350,16 @@ tupTcm <- Lens.view tupleTcCache let m = length tys Just tupTcNm = IM.lookup m tupTcm- Just tupTc = HashMap.lookup (nameOcc tupTcNm) tcm+ Just tupTc = lookupUniqMap tupTcNm tcm [tupDc] = tyConDataCons tupTc (tyIxs,tys') = unzip tys tupTy = mkTyConApp tupTcNm tys' cs' = fmap (\es -> map (es !!) tyIxs) cs djCase = genCase tupTy (Just tupDc) tys' cs'- (scrutId,scrutVar) <- mkInternalVar (string2InternalName "tupIn") tupTy+ scrutId <- mkInternalVar inScope "tupIn" tupTy projections <- mapM (mkSelectorCase ($(curLoc) ++ "disJointSelProj")- tcm scrutVar (dcTag tupDc)) [0..m-1]- return (Just (scrutId,embed djCase),projections)+ inScope tcm (Var scrutId) (dcTag tupDc)) [0..m-1]+ return (Just (scrutId,djCase),projections) let selProjs = tranOrUnTran 0 (zip (map fst untran) untranSels) projs return (lbM,selProjs)@@ -339,19 +370,27 @@ | 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) -isCommon :: Set TmOccName -> [Either Term Type] -> Bool-isCommon _ [] = True-isCommon _ (Right ty:tys) = Set.null (Lens.setOf typeFreeVars ty) &&- allEqual (Right ty:tys)-isCommon fvs (Left tm:tms) = Set.null (Lens.setOf termFreeIds tm Set.\\ fvs) &&- allEqual (Left tm:tms)+ isLocallyBound 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) uncommon arguments+ -> [Term] -- ^ (projections for) distinct arguments -> [Either Term Type] mkDJArgs _ cms [] = map snd cms mkDJArgs _ [] uncms = map Left uncms@@ -359,7 +398,7 @@ | 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 uncommon arguments given+-- | Create a case-expression that selects between the distinct arguments given -- a case-tree genCase :: Type -- ^ Type of the alternatives -> Maybe DataCon -- ^ DataCon to pack multiple arguments@@ -374,17 +413,17 @@ _ -> head tms go (LB lb ct) =- Letrec (bind (Unbound.rec lb) (go ct))+ Letrec lb (go ct) go (Branch scrut [(p,ct)]) = let ct' = go ct- alt = bind p ct'- in case Lens.setOf termFreeIds ct' == Lens.setOf fv alt of- True -> ct'- _ -> Case scrut ty [alt]+ (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 (\(p,ct) -> bind p (go ct)) pats)+ Case scrut ty (map (second go) pats) -- | Determine if a term in a function position is interesting to lift out of -- of a case-expression.@@ -395,7 +434,7 @@ -- * All non-power-of-two multiplications -- * All division-like operations with a non-power-of-two divisor interestingToLift- :: Set TmOccName+ :: InScopeSet -- ^ in scope -> (Term -> Term) -- ^ Evaluator@@ -403,22 +442,22 @@ -- ^ Term in function position -> [Either Term Type] -- ^ Arguments- -> Maybe Term-interestingToLift inScope _ e@(Var _ nm) _ =- if nameOcc nm `Set.member` inScope- then Just e- else Nothing-interestingToLift inScope eval e@(Prim nm pty) args =- case List.lookup nm interestingPrims of- Just t | t || not (all isConstant lArgs) -> Just e- _ -> if isHOTy pty- then if not . null . Maybe.catMaybes $- map (uncurry (interestingToLift inScope eval) .- collectArgs- ) lArgs- then Just e- else Nothing- else Nothing+ -> RewriteMonad extra (Maybe Term)+interestingToLift inScope _ e@(Var v) _ =+ if isGlobalId v || v `elemInScopeSet` inScope+ then pure (Just e)+ else pure Nothing+interestingToLift inScope eval e@(Prim nm pInfo) args = do+ let anyArgNotConstant = any (not . isConstant) lArgs+ case List.lookup nm interestingPrims of+ Just t | t || anyArgNotConstant -> pure (Just e)+ _ -> do+ let isInteresting = uncurry (interestingToLift inScope eval) . collectArgs+ if isHOTy (primType pInfo) then do+ anyInteresting <- anyM (fmap Maybe.isJust . isInteresting) lArgs+ if anyInteresting then pure (Just e) else pure Nothing+ else+ pure Nothing where interestingPrims =@@ -470,12 +509,16 @@ a -> case collectArgs a of (Prim nm' _,[Right _,Left _,Left (Literal (IntegerLiteral n))]) | isFromInteger nm' -> isPow2 n+ (Prim nm' _,[Right _,Left _,Left _,Left (Literal (IntegerLiteral n))])+ | nm' == "Clash.Sized.Internal.BitVector.fromInteger#" -> isPow2 n+ (Prim nm' _,[Right _, Left _,Left (Literal (IntegerLiteral n))])+ | nm' == "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.Internal.BitVector.fromInteger#"+ isFromInteger x = x `elem` ["Clash.Sized.Internal.BitVector.fromInteger#" ,"Clash.Sized.Integer.Index.fromInteger" ,"Clash.Sized.Internal.Signed.fromInteger#" ,"Clash.Sized.Internal.Unsigned.fromInteger#"@@ -484,4 +527,4 @@ isHOTy t = case splitFunForallTy t of (args',_) -> any isPolyFunTy (Either.rights args') -interestingToLift _ _ _ _ = Nothing+interestingToLift _ _ _ _ = pure Nothing
src/Clash/Normalize/PrimitiveReductions.hs view
@@ -22,6 +22,7 @@ * Clash.Sized.Vector.imap * Clash.Sized.Vector.dtfold * Clash.Sized.RTree.tfold+ * Clash.Sized.Vector.reverse Partially handles: @@ -37,208 +38,271 @@ module Clash.Normalize.PrimitiveReductions where import qualified Control.Lens as Lens-import qualified Data.HashMap.Lazy as HashMap+import Data.List (mapAccumR) import qualified Data.Maybe as Maybe-import Unbound.Generics.LocallyNameless (bind, embed, rec, rebind) -import Clash.Core.DataCon (DataCon, dataConInstArgTys)+import PrelNames (boolTyConKey)+import Unique (getKey)++import Clash.Core.DataCon (DataCon) import Clash.Core.Literal (Literal (..))-import Clash.Core.Name-import Clash.Core.Pretty (showDoc)-import Clash.Core.Term (Term (..), Pat (..))+import Clash.Core.Name (nameOcc)+import Clash.Core.Pretty (showPpr)+import Clash.Core.Term+ (CoreContext (..), PrimInfo (..), Term (..), WorkInfo (..), Pat (..)) import Clash.Core.Type (LitTy (..), Type (..),- TypeView (..), coreView,+ TypeView (..), coreView1, mkFunTy, mkTyConApp,- splitFunForallTy, tyView,- undefinedTy)-import Clash.Core.TyCon (TyConName, tyConDataCons)+ splitFunForallTy, tyView)+import Clash.Core.TyCon+ (TyConMap, TyConName, tyConDataCons, tyConName) import Clash.Core.TysPrim (integerPrimTy, typeNatKind)-import Clash.Core.Util (appendToVec, extractElems,- extractTElems, idToVar,- mkApps, mkRTree, mkVec,- termType)+import Clash.Core.Util+ (appendToVec, extractElems, extractTElems, idToVar, mkApps, mkRTree,+ mkUniqInternalId, mkUniqSystemTyVar, mkVec, termType, dataConInstArgTys,+ primCo, undefinedTm) import Clash.Core.Var (Var (..))-+import Clash.Core.VarEnv+ (InScopeSet, extendInScopeSetList)+import {-# SOURCE #-} Clash.Normalize.Strategy import Clash.Normalize.Types import Clash.Rewrite.Types import Clash.Rewrite.Util+import Clash.Unique import Clash.Util +-- | Replace an application of the @Clash.Sized.Vector.reverse@ primitive on+-- vectors of a known length @n@, by the fully unrolled recursive "definition"+-- of @Clash.Sized.Vector.reverse@+reduceReverse+ :: InScopeSet+ -> Integer+ -- ^ Length of the vector+ -> Type+ -- ^ Element of type of the vector+ -> Term+ -- ^ The vector to reverse+ -> NormalizeSession Term+reduceReverse inScope0 n elTy vArg = do+ tcm <- Lens.view tcCache+ let ty = termType tcm vArg+ go tcm ty+ where+ go tcm (coreView1 tcm -> Just ty') = go tcm ty'+ go tcm (tyView -> TyConApp vecTcNm _)+ | Just vecTc <- lookupUniqMap vecTcNm tcm+ , nameOcc vecTcNm == "Clash.Sized.Vector.Vec"+ , [nilCon, consCon] <- tyConDataCons vecTc+ = do+ uniqs0 <- Lens.use uniqSupply+ let (uniqs1,(vars,elems)) = second (second concat . unzip)+ $ extractElems uniqs0 inScope0 consCon elTy 'V' n vArg+ lbody = mkVec nilCon consCon elTy n (reverse vars)+ lb = Letrec (init elems) lbody+ uniqSupply Lens..= uniqs1+ changed lb+ go _ ty = error $ $(curLoc) ++ "reduceReverse: argument does not have a vector type: " ++ showPpr ty+ -- | Replace an application of the @Clash.Sized.Vector.zipWith@ primitive on -- vectors of a known length @n@, by the fully unrolled recursive "definition" -- of @Clash.Sized.Vector.zipWith@-reduceZipWith :: Integer -- ^ Length of the vector(s)- -> Type -- ^ Type of the lhs of the function- -> Type -- ^ Type of the rhs of the function- -> Type -- ^ Type of the result of the function- -> Term -- ^ The zipWith'd functions- -> Term -- ^ The 1st vector argument- -> Term -- ^ The 2nd vector argument- -> NormalizeSession Term-reduceZipWith n lhsElTy rhsElTy resElTy fun lhsArg rhsArg = do+reduceZipWith+ :: TransformContext+ -> Integer -- ^ Length of the vector(s)+ -> Type -- ^ Type of the lhs of the function+ -> Type -- ^ Type of the rhs of the function+ -> Type -- ^ Type of the result of the function+ -> Term -- ^ The zipWith'd functions+ -> Term -- ^ The 1st vector argument+ -> Term -- ^ The 2nd vector argument+ -> NormalizeSession Term+reduceZipWith (TransformContext is0 ctx) n lhsElTy rhsElTy resElTy fun lhsArg rhsArg = do tcm <- Lens.view tcCache- ty <- termType tcm lhsArg+ let ty = termType tcm lhsArg go tcm ty where- go tcm (coreView tcm -> Just ty') = go tcm ty'+ go tcm (coreView1 tcm -> Just ty') = go tcm ty' go tcm (tyView -> TyConApp vecTcNm _)- | (Just vecTc) <- HashMap.lookup (nameOcc vecTcNm) tcm+ | (Just vecTc) <- lookupUniqMap vecTcNm tcm+ , nameOcc vecTcNm == "Clash.Sized.Vector.Vec" , [nilCon,consCon] <- tyConDataCons vecTc- = let (varsL,elemsL) = second concat . unzip- $ extractElems consCon lhsElTy 'L' n lhsArg- (varsR,elemsR) = second concat . unzip- $ extractElems consCon rhsElTy 'R' n rhsArg- funApps = zipWith (\l r -> mkApps fun [Left l,Left r]) varsL varsR+ = do+ uniqs0 <- Lens.use uniqSupply+ fun1 <- constantPropagation (TransformContext is0 (AppArg Nothing:ctx)) fun+ let (uniqs1,(varsL,elemsL)) = second (second concat . unzip)+ $ extractElems uniqs0 is0 consCon lhsElTy 'L' n lhsArg+ is2 = extendInScopeSetList is0 (map fst elemsL)+ (uniqs2,(varsR,elemsR)) = second (second concat . unzip)+ $ extractElems uniqs1 is2 consCon rhsElTy 'R' n rhsArg+ funApps = zipWith (\l r -> mkApps fun1 [Left l,Left r]) varsL varsR lbody = mkVec nilCon consCon resElTy n funApps- lb = Letrec (bind (rec (init elemsL ++ init elemsR)) lbody)- in changed lb- go _ ty = error $ $(curLoc) ++ "reduceZipWith: argument does not have a vector type: " ++ showDoc ty+ lb = Letrec (init elemsL ++ init elemsR) lbody+ uniqSupply Lens..= uniqs2+ changed lb+ go _ ty = error $ $(curLoc) ++ "reduceZipWith: argument does not have a vector type: " ++ showPpr ty -- | Replace an application of the @Clash.Sized.Vector.map@ primitive on vectors -- of a known length @n@, by the fully unrolled recursive "definition" of -- @Clash.Sized.Vector.map@-reduceMap :: Integer -- ^ Length of the vector- -> Type -- ^ Argument type of the function- -> Type -- ^ Result type of the function- -> Term -- ^ The map'd function- -> Term -- ^ The map'd over vector- -> NormalizeSession Term-reduceMap n argElTy resElTy fun arg = do+reduceMap+ :: TransformContext+ -> Integer -- ^ Length of the vector+ -> Type -- ^ Argument type of the function+ -> Type -- ^ Result type of the function+ -> Term -- ^ The map'd function+ -> Term -- ^ The map'd over vector+ -> NormalizeSession Term+reduceMap (TransformContext is0 ctx) n argElTy resElTy fun arg = do tcm <- Lens.view tcCache- ty <- termType tcm arg+ let ty = termType tcm arg go tcm ty where- go tcm (coreView tcm -> Just ty') = go tcm ty'+ go tcm (coreView1 tcm -> Just ty') = go tcm ty' go tcm (tyView -> TyConApp vecTcNm _)- | (Just vecTc) <- HashMap.lookup (nameOcc vecTcNm) tcm+ | (Just vecTc) <- lookupUniqMap vecTcNm tcm+ , nameOcc vecTcNm == "Clash.Sized.Vector.Vec" , [nilCon,consCon] <- tyConDataCons vecTc- = let (vars,elems) = second concat . unzip- $ extractElems consCon argElTy 'A' n arg- funApps = map (fun `App`) vars+ = do+ uniqs0 <- Lens.use uniqSupply+ fun1 <- constantPropagation (TransformContext is0 (AppArg Nothing:ctx)) fun+ let (uniqs1,(vars,elems)) = second (second concat . unzip)+ $ extractElems uniqs0 is0 consCon argElTy 'A' n arg+ funApps = map (fun1 `App`) vars lbody = mkVec nilCon consCon resElTy n funApps- lb = Letrec (bind (rec (init elems)) lbody)- in changed lb- go _ ty = error $ $(curLoc) ++ "reduceMap: argument does not have a vector type: " ++ showDoc ty+ lb = Letrec (init elems) lbody+ uniqSupply Lens..= uniqs1+ changed lb+ go _ ty = error $ $(curLoc) ++ "reduceMap: argument does not have a vector type: " ++ showPpr ty -- | Replace an application of the @Clash.Sized.Vector.imap@ primitive on vectors -- of a known length @n@, by the fully unrolled recursive "definition" of -- @Clash.Sized.Vector.imap@-reduceImap :: Integer -- ^ Length of the vector- -> Type -- ^ Argument type of the function- -> Type -- ^ Result type of the function- -> Term -- ^ The imap'd function- -> Term -- ^ The imap'd over vector- -> NormalizeSession Term-reduceImap n argElTy resElTy fun arg = do+reduceImap+ :: TransformContext+ -> Integer -- ^ Length of the vector+ -> Type -- ^ Argument type of the function+ -> Type -- ^ Result type of the function+ -> Term -- ^ The imap'd function+ -> Term -- ^ The imap'd over vector+ -> NormalizeSession Term+reduceImap (TransformContext is0 ctx) n argElTy resElTy fun arg = do tcm <- Lens.view tcCache- ty <- termType tcm arg+ let ty = termType tcm arg go tcm ty where- go tcm (coreView tcm -> Just ty') = go tcm ty'+ go tcm (coreView1 tcm -> Just ty') = go tcm ty' go tcm (tyView -> TyConApp vecTcNm _)- | (Just vecTc) <- HashMap.lookup (nameOcc vecTcNm) tcm+ | (Just vecTc) <- lookupUniqMap vecTcNm tcm+ , nameOcc vecTcNm == "Clash.Sized.Vector.Vec" , [nilCon,consCon] <- tyConDataCons vecTc = do- let (vars,elems) = second concat . unzip- $ extractElems consCon argElTy 'I' n arg- (Right idxTy:_,_) <- splitFunForallTy <$> termType tcm fun- let (TyConApp idxTcNm _) = tyView idxTy- nTv = string2InternalName "n"+ uniqs0 <- Lens.use uniqSupply+ fun1 <- constantPropagation (TransformContext is0 (AppArg Nothing:ctx)) fun+ let (uniqs1,nTv) = mkUniqSystemTyVar (uniqs0,is0) ("n",typeNatKind)+ (uniqs2,(vars,elems)) = second (second concat . unzip)+ $ uncurry extractElems uniqs1 consCon argElTy 'I' n arg+ (Right idxTy:_,_) = splitFunForallTy (termType tcm fun)+ (TyConApp idxTcNm _) = tyView idxTy -- fromInteger# :: KnownNat n => Integer -> Index n- idxFromIntegerTy = ForAllTy (bind (TyVar nTv (embed typeNatKind))- (foldr mkFunTy- (mkTyConApp idxTcNm- [VarTy typeNatKind nTv])- [integerPrimTy,integerPrimTy]))+ idxFromIntegerTy = ForAllTy nTv+ (foldr mkFunTy+ (mkTyConApp idxTcNm+ [VarTy nTv])+ [integerPrimTy,integerPrimTy]) idxFromInteger = Prim "Clash.Sized.Internal.Index.fromInteger#"- idxFromIntegerTy+ (PrimInfo idxFromIntegerTy WorkNever) idxs = map (App (App (TyApp idxFromInteger (LitTy (NumTy n))) (Literal (IntegerLiteral (toInteger n)))) . Literal . IntegerLiteral . toInteger) [0..(n-1)]-- funApps = zipWith (\i v -> App (App fun i) v) idxs vars+ funApps = zipWith (\i v -> App (App fun1 i) v) idxs vars lbody = mkVec nilCon consCon resElTy n funApps- lb = Letrec (bind (rec (init elems)) lbody)+ lb = Letrec (init elems) lbody+ uniqSupply Lens..= uniqs2 changed lb- go _ ty = error $ $(curLoc) ++ "reduceImap: argument does not have a vector type: " ++ showDoc ty+ go _ ty = error $ $(curLoc) ++ "reduceImap: argument does not have a vector type: " ++ showPpr ty -- | Replace an application of the @Clash.Sized.Vector.traverse#@ primitive on -- vectors of a known length @n@, by the fully unrolled recursive "definition" -- of @Clash.Sized.Vector.traverse#@-reduceTraverse :: Integer -- ^ Length of the vector- -> Type -- ^ Element type of the argument vector- -> Type -- ^ The type of the applicative- -> Type -- ^ Element type of the result vector- -> Term -- ^ The @Applicative@ dictionary- -> Term -- ^ The function to traverse with- -> Term -- ^ The argument vector- -> NormalizeSession Term-reduceTraverse n aTy fTy bTy dict fun arg = do+reduceTraverse+ :: TransformContext+ -> Integer -- ^ Length of the vector+ -> Type -- ^ Element type of the argument vector+ -> Type -- ^ The type of the applicative+ -> Type -- ^ Element type of the result vector+ -> Term -- ^ The @Applicative@ dictionary+ -> Term -- ^ The function to traverse with+ -> Term -- ^ The argument vector+ -> NormalizeSession Term+reduceTraverse (TransformContext is0 ctx) n aTy fTy bTy dict fun arg = do tcm <- Lens.view tcCache- (TyConApp apDictTcNm _) <- tyView <$> termType tcm dict- ty <- termType tcm arg+ let (TyConApp apDictTcNm _) = tyView (termType tcm dict)+ ty = termType tcm arg go tcm apDictTcNm ty where- go tcm apDictTcNm (coreView tcm -> Just ty') = go tcm apDictTcNm ty'+ go tcm apDictTcNm (coreView1 tcm -> Just ty') = go tcm apDictTcNm ty' go tcm apDictTcNm (tyView -> TyConApp vecTcNm _)- | (Just vecTc) <- HashMap.lookup (nameOcc vecTcNm) tcm+ | (Just vecTc) <- lookupUniqMap vecTcNm tcm+ , nameOcc vecTcNm == "Clash.Sized.Vector.Vec" , [nilCon,consCon] <- tyConDataCons vecTc- = let (Just apDictTc) = HashMap.lookup (nameOcc apDictTcNm) tcm+ = do+ uniqs0 <- Lens.use uniqSupply+ fun1 <- constantPropagation (TransformContext is0 (AppArg Nothing:ctx)) fun+ let (Just apDictTc) = lookupUniqMap apDictTcNm tcm [apDictCon] = tyConDataCons apDictTc (Just apDictIdTys) = dataConInstArgTys apDictCon [fTy]- apDictIds = zipWith Id (map string2InternalName- ["functorDict"- ,"pure"- ,"ap"- ,"apConstL"- ,"apConstR"])- (map embed apDictIdTys)+ (uniqs1,apDictIds@[functorDictId,pureId,apId,_,_]) =+ mapAccumR mkUniqInternalId (uniqs0,is0)+ (zip ["functorDict","pure","ap","apConstL","apConstR"]+ apDictIdTys) (TyConApp funcDictTcNm _) = tyView (head apDictIdTys)- (Just funcDictTc) = HashMap.lookup (nameOcc funcDictTcNm) tcm+ (Just funcDictTc) = lookupUniqMap funcDictTcNm tcm [funcDictCon] = tyConDataCons funcDictTc (Just funcDictIdTys) = dataConInstArgTys funcDictCon [fTy]- funcDicIds = zipWith Id (map string2InternalName ["fmap","fmapConst"])- (map embed funcDictIdTys)+ (uniqs2,funcDicIds@[fmapId,_]) =+ mapAccumR mkUniqInternalId uniqs1+ (zip ["fmap","fmapConst"] funcDictIdTys) - apPat = DataPat (embed apDictCon) (rebind [] apDictIds)- fnPat = DataPat (embed funcDictCon) (rebind [] funcDicIds)+ apPat = DataPat apDictCon [] apDictIds+ fnPat = DataPat funcDictCon [] funcDicIds -- Extract the 'pure' function from the Applicative dictionary- pureTy = apDictIdTys!!1- pureTm = Case dict pureTy [bind apPat (Var pureTy (string2InternalName "pure"))]+ pureTy = varType pureId+ pureTm = Case dict pureTy [(apPat,Var pureId)] -- Extract the '<*>' function from the Applicative dictionary- apTy = apDictIdTys!!2- apTm = Case dict apTy [bind apPat (Var apTy (string2InternalName "ap"))]+ apTy = varType apId+ apTm = Case dict apTy [(apPat, Var apId)] -- Extract the Functor dictionary from the Applicative dictionary- funcTy = (head apDictIdTys)+ funcTy = varType functorDictId funcTm = Case dict funcTy- [bind apPat (Var funcTy (string2InternalName "functorDict"))]+ [(apPat,Var functorDictId)] -- Extract the 'fmap' function from the Functor dictionary- fmapTy = (head funcDictIdTys)- fmapTm = Case (Var funcTy (string2InternalName "functorDict")) fmapTy- [bind fnPat (Var fmapTy (string2InternalName "fmap"))]+ fmapTy = varType fmapId+ fmapTm = Case (Var functorDictId) fmapTy+ [(fnPat, Var fmapId)] - (vars,elems) = second concat . unzip- $ extractElems consCon aTy 'T' n arg+ (uniqs3,(vars,elems)) = second (second concat . unzip)+ $ uncurry extractElems uniqs2 consCon aTy 'T' n arg - funApps = map (fun `App`) vars+ funApps = map (fun1 `App`) vars - lbody = mkTravVec vecTcNm nilCon consCon (idToVar (apDictIds!!1))- (idToVar (apDictIds!!2))- (idToVar (funcDicIds!!0))+ lbody = mkTravVec vecTcNm nilCon consCon (Var (apDictIds!!1))+ (Var (apDictIds!!2))+ (Var (funcDicIds!!0)) bTy n funApps - lb = Letrec (bind (rec ([((apDictIds!!0),embed funcTm)- ,((apDictIds!!1),embed pureTm)- ,((apDictIds!!2),embed apTm)- ,((funcDicIds!!0),embed fmapTm)- ] ++ init elems)) lbody)- in changed lb- go _ _ ty = error $ $(curLoc) ++ "reduceTraverse: argument does not have a vector type: " ++ showDoc ty+ lb = Letrec ([((apDictIds!!0), funcTm)+ ,((apDictIds!!1), pureTm)+ ,((apDictIds!!2), apTm)+ ,((funcDicIds!!0), fmapTm)+ ] ++ init elems) lbody+ uniqSupply Lens..= uniqs3+ changed lb+ go _ _ ty = error $ $(curLoc) ++ "reduceTraverse: argument does not have a vector type: " ++ showPpr ty -- | Create the traversable vector --@@ -262,7 +326,7 @@ ,Left (mkApps (Data nilCon) [Right (LitTy (NumTy 0)) ,Right bTy- ,Left (Prim "_CO_" nilCoTy)])]+ ,Left (primCo nilCoTy)])] go n (x:xs) = mkApps apTm [Right (mkTyConApp vecTc [LitTy (NumTy (n-1)),bTy])@@ -274,7 +338,7 @@ [Right (LitTy (NumTy n)) ,Right bTy ,Right (LitTy (NumTy (n-1)))- ,Left (Prim "_CO_" (consCoTy n))+ ,Left (primCo (consCoTy n)) ]) ,Left x]) ,Left (go (n-1) xs)]@@ -290,87 +354,122 @@ -- | Replace an application of the @Clash.Sized.Vector.foldr@ primitive on -- vectors of a known length @n@, by the fully unrolled recursive "definition" -- of @Clash.Sized.Vector.foldr@-reduceFoldr :: Integer -- ^ Length of the vector- -> Type -- ^ Element type of the argument vector- -> Term -- ^ The function to fold with- -> Term -- ^ The starting value- -> Term -- ^ The argument vector- -> NormalizeSession Term-reduceFoldr n aTy fun start arg = do+reduceFoldr+ :: TransformContext+ -> Integer+ -- ^ Length of the vector+ -> Type+ -- ^ Element type of the argument vector+ -> Term+ -- ^ The function to fold with+ -> Term+ -- ^ The starting value+ -> Term+ -- ^ The argument vector+ -> NormalizeSession Term+reduceFoldr _ 0 _ _ start _ = changed start+reduceFoldr (TransformContext is0 ctx) n aTy fun start arg = do tcm <- Lens.view tcCache- ty <- termType tcm arg+ let ty = termType tcm arg go tcm ty where- go tcm (coreView tcm -> Just ty') = go tcm ty'+ go tcm (coreView1 tcm -> Just ty') = go tcm ty' go tcm (tyView -> TyConApp vecTcNm _)- | (Just vecTc) <- HashMap.lookup (nameOcc vecTcNm) tcm+ | (Just vecTc) <- lookupUniqMap vecTcNm tcm+ , nameOcc vecTcNm == "Clash.Sized.Vector.Vec" , [_,consCon] <- tyConDataCons vecTc- = let (vars,elems) = second concat . unzip- $ extractElems consCon aTy 'G' n arg- lbody = foldr (\l r -> mkApps fun [Left l,Left r]) start vars- lb = Letrec (bind (rec (init elems)) lbody)- in changed lb- go _ ty = error $ $(curLoc) ++ "reduceFoldr: argument does not have a vector type: " ++ showDoc ty+ = do+ uniqs0 <- Lens.use uniqSupply+ fun1 <- constantPropagation (TransformContext is0 (AppArg Nothing:ctx)) fun+ let (uniqs1,(vars,elems)) = second (second concat . unzip)+ $ extractElems uniqs0 is0 consCon aTy 'G' n arg+ lbody = foldr (\l r -> mkApps fun1 [Left l,Left r]) start vars+ lb = Letrec (init elems) lbody+ uniqSupply Lens..= uniqs1+ changed lb+ go _ ty = error $ $(curLoc) ++ "reduceFoldr: argument does not have a vector type: " ++ showPpr ty -- | Replace an application of the @Clash.Sized.Vector.fold@ primitive on -- vectors of a known length @n@, by the fully unrolled recursive "definition" -- of @Clash.Sized.Vector.fold@-reduceFold :: Integer -- ^ Length of the vector- -> Type -- ^ Element type of the argument vector- -> Term -- ^ The function to fold with- -> Term -- ^ The argument vector- -> NormalizeSession Term-reduceFold n aTy fun arg = do+reduceFold+ :: TransformContext+ -> Integer+ -- ^ Length of the vector+ -> Type+ -- ^ Element type of the argument vector+ -> Term+ -- ^ The function to fold with+ -> Term+ -- ^ The argument vector+ -> NormalizeSession Term+reduceFold (TransformContext is0 ctx) n aTy fun arg = do tcm <- Lens.view tcCache- ty <- termType tcm arg+ let ty = termType tcm arg go tcm ty where- go tcm (coreView tcm -> Just ty') = go tcm ty'+ go tcm (coreView1 tcm -> Just ty') = go tcm ty' go tcm (tyView -> TyConApp vecTcNm _)- | (Just vecTc) <- HashMap.lookup (nameOcc vecTcNm) tcm+ | (Just vecTc) <- lookupUniqMap vecTcNm tcm+ , nameOcc vecTcNm == "Clash.Sized.Vector.Vec" , [_,consCon] <- tyConDataCons vecTc- = let (vars,elems) = second concat . unzip- $ extractElems consCon aTy 'F' n arg- lbody = foldV vars- lb = Letrec (bind (rec (init elems)) lbody)- in changed lb- go _ ty = error $ $(curLoc) ++ "reduceFold: argument does not have a vector type: " ++ showDoc ty+ = do+ uniqs0 <- Lens.use uniqSupply+ fun1 <- constantPropagation (TransformContext is0 (AppArg Nothing:ctx)) fun+ let (uniqs1,(vars,elems)) = second (second concat . unzip)+ $ extractElems uniqs0 is0 consCon aTy 'F' n arg+ lbody = foldV fun1 vars+ lb = Letrec (init elems) lbody+ uniqSupply Lens..= uniqs1+ changed lb+ go _ ty = error $ $(curLoc) ++ "reduceFold: argument does not have a vector type: " ++ showPpr ty - foldV [a] = a- foldV as = let (l,r) = splitAt (length as `div` 2) as- lF = foldV l- rF = foldV r- in mkApps fun [Left lF, Left rF]+ foldV _ [a] = a+ foldV f as = let (l,r) = splitAt (length as `div` 2) as+ lF = foldV f l+ rF = foldV f r+ in mkApps f [Left lF, Left rF] -- | Replace an application of the @Clash.Sized.Vector.dfold@ primitive on -- vectors of a known length @n@, by the fully unrolled recursive "definition" -- of @Clash.Sized.Vector.dfold@-reduceDFold :: Integer -- ^ Length of the vector- -> Type -- ^ Element type of the argument vector- -> Term -- ^ Function to fold with- -> Term -- ^ Starting value- -> Term -- ^ The vector to fold- -> NormalizeSession Term-reduceDFold n aTy fun start arg = do+reduceDFold+ :: InScopeSet+ -> Integer+ -- ^ Length of the vector+ -> Type+ -- ^ Element type of the argument vector+ -> Term+ -- ^ Function to fold with+ -> Term+ -- ^ Starting value+ -> Term+ -- ^ The vector to fold+ -> NormalizeSession Term+reduceDFold _ 0 _ _ start _ = changed start+reduceDFold inScope n aTy fun start arg = do tcm <- Lens.view tcCache- ty <- termType tcm arg+ let ty = termType tcm arg go tcm ty where- go tcm (coreView tcm -> Just ty') = go tcm ty'+ go tcm (coreView1 tcm -> Just ty') = go tcm ty' go tcm (tyView -> TyConApp vecTcNm _)- | (Just vecTc) <- HashMap.lookup (nameOcc vecTcNm) tcm+ | (Just vecTc) <- lookupUniqMap vecTcNm tcm+ , nameOcc vecTcNm == "Clash.Sized.Vector.Vec" , [_,consCon] <- tyConDataCons vecTc = do- let (vars,elems) = second concat . unzip- $ extractElems consCon aTy 'D' n arg- (_ltv:Right snTy:_,_) <- splitFunForallTy <$> termType tcm fun- let (TyConApp snatTcNm _) = tyView snTy- (Just snatTc) = HashMap.lookup (nameOcc snatTcNm) tcm+ uniqs0 <- Lens.use uniqSupply+ let (uniqs1,(vars,elems)) = second (second concat . unzip)+ $ extractElems uniqs0 inScope consCon aTy 'D' n arg+ (_ltv:Right snTy:_,_) = splitFunForallTy (termType tcm fun)+ (TyConApp snatTcNm _) = tyView snTy+ (Just snatTc) = lookupUniqMap snatTcNm tcm [snatDc] = tyConDataCons snatTc lbody = doFold (buildSNat snatDc) (n-1) vars- lb = Letrec (bind (rec (init elems)) lbody)+ lb = Letrec (init elems) lbody+ uniqSupply Lens..= uniqs1 changed lb- go _ ty = error $ $(curLoc) ++ "reduceDFold: argument does not have a vector type: " ++ showDoc ty+ go _ ty = error $ $(curLoc) ++ "reduceDFold: argument does not have a vector type: " ++ showPpr ty doFold _ _ [] = start doFold snDc k (x:xs) = mkApps fun@@ -383,124 +482,154 @@ -- | Replace an application of the @Clash.Sized.Vector.head@ primitive on -- vectors of a known length @n@, by a projection of the first element of a -- vector.-reduceHead :: Integer -- ^ Length of the vector- -> Type -- ^ Element type of the vector- -> Term -- ^ The argument vector- -> NormalizeSession Term-reduceHead n aTy vArg = do+reduceHead+ :: InScopeSet+ -> Integer -- ^ Length of the vector+ -> Type -- ^ Element type of the vector+ -> Term -- ^ The argument vector+ -> NormalizeSession Term+reduceHead inScope n aTy vArg = do tcm <- Lens.view tcCache- ty <- termType tcm vArg+ let ty = termType tcm vArg go tcm ty where- go tcm (coreView tcm -> Just ty') = go tcm ty'+ go tcm (coreView1 tcm -> Just ty') = go tcm ty' go tcm (tyView -> TyConApp vecTcNm _)- | (Just vecTc) <- HashMap.lookup (nameOcc vecTcNm) tcm+ | (Just vecTc) <- lookupUniqMap vecTcNm tcm+ , nameOcc vecTcNm == "Clash.Sized.Vector.Vec" , [_,consCon] <- tyConDataCons vecTc- = let (vars,elems) = second concat . unzip- $ extractElems consCon aTy 'H' n vArg- lb = Letrec (bind (rec [head elems]) (head vars))- in changed lb- go _ ty = error $ $(curLoc) ++ "reduceHead: argument does not have a vector type: " ++ showDoc ty+ = do+ uniqs0 <- Lens.use uniqSupply+ let (uniqs1,(vars,elems)) = second (second concat . unzip)+ $ extractElems uniqs0 inScope consCon aTy 'H' n vArg+ lb = Letrec [head elems] (head vars)+ uniqSupply Lens..= uniqs1+ changed lb+ go _ ty = error $ $(curLoc) ++ "reduceHead: argument does not have a vector type: " ++ showPpr ty -- | Replace an application of the @Clash.Sized.Vector.tail@ primitive on -- vectors of a known length @n@, by a projection of the tail of a -- vector.-reduceTail :: Integer -- ^ Length of the vector- -> Type -- ^ Element type of the vector- -> Term -- ^ The argument vector- -> NormalizeSession Term-reduceTail n aTy vArg = do+reduceTail+ :: InScopeSet+ -> Integer -- ^ Length of the vector+ -> Type -- ^ Element type of the vector+ -> Term -- ^ The argument vector+ -> NormalizeSession Term+reduceTail inScope n aTy vArg = do tcm <- Lens.view tcCache- ty <- termType tcm vArg+ let ty = termType tcm vArg go tcm ty where- go tcm (coreView tcm -> Just ty') = go tcm ty'+ go tcm (coreView1 tcm -> Just ty') = go tcm ty' go tcm (tyView -> TyConApp vecTcNm _)- | (Just vecTc) <- HashMap.lookup (nameOcc vecTcNm) tcm+ | (Just vecTc) <- lookupUniqMap vecTcNm tcm+ , nameOcc vecTcNm == "Clash.Sized.Vector.Vec" , [_,consCon] <- tyConDataCons vecTc- = let (_,elems) = second concat . unzip- $ extractElems consCon aTy 'L' n vArg+ = do+ uniqs0 <- Lens.use uniqSupply+ let (uniqs1,(_,elems)) = second (second concat . unzip)+ $ extractElems uniqs0 inScope consCon aTy 'L' n vArg b@(tB,_) = elems !! 1- lb = Letrec (bind (rec [b]) (idToVar tB))- in changed lb- go _ ty = error $ $(curLoc) ++ "reduceTail: argument does not have a vector type: " ++ showDoc ty+ lb = Letrec [b] (Var tB)+ uniqSupply Lens..= uniqs1+ changed lb+ go _ ty = error $ $(curLoc) ++ "reduceTail: argument does not have a vector type: " ++ showPpr ty -- | Replace an application of the @Clash.Sized.Vector.last@ primitive on -- vectors of a known length @n@, by a projection of the last element of a -- vector.-reduceLast :: Integer -- ^ Length of the vector- -> Type -- ^ Element type of the vector- -> Term -- ^ The argument vector- -> NormalizeSession Term-reduceLast n aTy vArg = do+reduceLast+ :: InScopeSet+ -> Integer -- ^ Length of the vector+ -> Type -- ^ Element type of the vector+ -> Term -- ^ The argument vector+ -> NormalizeSession Term+reduceLast inScope n aTy vArg = do tcm <- Lens.view tcCache- ty <- termType tcm vArg+ let ty = termType tcm vArg go tcm ty where- go tcm (coreView tcm -> Just ty') = go tcm ty'+ go tcm (coreView1 tcm -> Just ty') = go tcm ty' go tcm (tyView -> TyConApp vecTcNm _)- | (Just vecTc) <- HashMap.lookup (nameOcc vecTcNm) tcm+ | (Just vecTc) <- lookupUniqMap vecTcNm tcm+ , nameOcc vecTcNm == "Clash.Sized.Vector.Vec" , [_,consCon] <- tyConDataCons vecTc- = let (_,elems) = unzip- $ extractElems consCon aTy 'L' n vArg+ = do+ uniqs0 <- Lens.use uniqSupply+ let (uniqs1,(_,elems)) = second unzip+ $ extractElems uniqs0 inScope consCon aTy 'L' n vArg (tB,_) = head (last elems)- in case n of- 0 -> changed (mkApps (Prim "Clash.Transformations.undefined" undefinedTy) [Right aTy])- _ -> changed (Letrec (bind (rec (init (concat elems))) (idToVar tB)))- go _ ty = error $ $(curLoc) ++ "reduceLast: argument does not have a vector type: " ++ showDoc ty+ uniqSupply Lens..= uniqs1+ case n of+ 0 -> changed (undefinedTm aTy)+ _ -> changed (Letrec (init (concat elems)) (Var tB))+ go _ ty = error $ $(curLoc) ++ "reduceLast: argument does not have a vector type: " ++ showPpr ty -- | Replace an application of the @Clash.Sized.Vector.init@ primitive on -- vectors of a known length @n@, by a projection of the init of a -- vector.-reduceInit :: Integer -- ^ Length of the vector- -> Type -- ^ Element type of the vector- -> Term -- ^ The argument vector- -> NormalizeSession Term-reduceInit n aTy vArg = do+reduceInit+ :: InScopeSet+ -> Integer -- ^ Length of the vector+ -> Type -- ^ Element type of the vector+ -> Term -- ^ The argument vector+ -> NormalizeSession Term+reduceInit inScope n aTy vArg = do tcm <- Lens.view tcCache- ty <- termType tcm vArg+ let ty = termType tcm vArg go tcm ty where- go tcm (coreView tcm -> Just ty') = go tcm ty'+ go tcm (coreView1 tcm -> Just ty') = go tcm ty' go tcm (tyView -> TyConApp vecTcNm _)- | (Just vecTc) <- HashMap.lookup (nameOcc vecTcNm) tcm+ | (Just vecTc) <- lookupUniqMap vecTcNm tcm+ , nameOcc vecTcNm == "Clash.Sized.Vector.Vec" , [nilCon,consCon] <- tyConDataCons vecTc- = let (_,elems) = unzip- $ extractElems consCon aTy 'L' n vArg- in case n of- 0 -> changed (mkApps (Prim "Clash.Transformations.undefined" undefinedTy) [Right aTy])- 1 -> changed (mkVec nilCon consCon aTy 0 [])- _ -> let el = init elems- iv = mkVec nilCon consCon aTy (n-1) (map (idToVar . fst . head) el)- lb = rec (init (concat el))- in changed (Letrec (bind lb iv))+ = do+ uniqs0 <- Lens.use uniqSupply+ let (uniqs1,(_,elems)) = second unzip+ $ extractElems uniqs0 inScope consCon aTy 'L' n vArg+ uniqSupply Lens..= uniqs1+ case n of+ 0 -> changed (undefinedTm aTy)+ 1 -> changed (mkVec nilCon consCon aTy 0 [])+ _ -> let el = init elems+ iv = mkVec nilCon consCon aTy (n-1) (map (idToVar . fst . head) el)+ lb = init (concat el)+ in changed (Letrec lb iv) - go _ ty = error $ $(curLoc) ++ "reduceInit: argument does not have a vector type: " ++ showDoc ty+ go _ ty = error $ $(curLoc) ++ "reduceInit: argument does not have a vector type: " ++ showPpr ty -- | Replace an application of the @Clash.Sized.Vector.(++)@ primitive on -- vectors of a known length @n@, by the fully unrolled recursive "definition" -- of @Clash.Sized.Vector.(++)@-reduceAppend :: Integer -- ^ Length of the LHS arg- -> Integer -- ^ Lenght of the RHS arg- -> Type -- ^ Element type of the vectors- -> Term -- ^ The LHS argument- -> Term -- ^ The RHS argument- -> NormalizeSession Term-reduceAppend n m aTy lArg rArg = do+reduceAppend+ :: InScopeSet+ -> Integer -- ^ Length of the LHS arg+ -> Integer -- ^ Lenght of the RHS arg+ -> Type -- ^ Element type of the vectors+ -> Term -- ^ The LHS argument+ -> Term -- ^ The RHS argument+ -> NormalizeSession Term+reduceAppend inScope n m aTy lArg rArg = do tcm <- Lens.view tcCache- ty <- termType tcm lArg+ let ty = termType tcm lArg go tcm ty where- go tcm (coreView tcm -> Just ty') = go tcm ty'+ go tcm (coreView1 tcm -> Just ty') = go tcm ty' go tcm (tyView -> TyConApp vecTcNm _)- | (Just vecTc) <- HashMap.lookup (nameOcc vecTcNm) tcm+ | (Just vecTc) <- lookupUniqMap vecTcNm tcm+ , nameOcc vecTcNm == "Clash.Sized.Vector.Vec" , [_,consCon] <- tyConDataCons vecTc- = let (vars,elems) = second concat . unzip- $ extractElems consCon aTy 'C' n lArg- lbody = appendToVec consCon aTy rArg (n+m) vars- lb = Letrec (bind (rec (init elems)) lbody)- in changed lb- go _ ty = error $ $(curLoc) ++ "reduceAppend: argument does not have a vector type: " ++ showDoc ty+ = do uniqs0 <- Lens.use uniqSupply+ let (uniqs1,(vars,elems)) = second (second concat . unzip)+ $ extractElems uniqs0 inScope consCon aTy+ 'C' n lArg+ lbody = appendToVec consCon aTy rArg (n+m) vars+ lb = Letrec (init elems) lbody+ uniqSupply Lens..= uniqs1+ changed lb+ go _ ty = error $ $(curLoc) ++ "reduceAppend: argument does not have a vector type: " ++ showPpr ty -- | Replace an application of the @Clash.Sized.Vector.unconcat@ primitive on -- vectors of a known length @n@, by the fully unrolled recursive "definition"@@ -512,18 +641,19 @@ -> NormalizeSession Term reduceUnconcat n 0 aTy arg = do tcm <- Lens.view tcCache- ty <- termType tcm arg+ let ty = termType tcm arg go tcm ty where- go tcm (coreView tcm -> Just ty') = go tcm ty'+ go tcm (coreView1 tcm -> Just ty') = go tcm ty' go tcm (tyView -> TyConApp vecTcNm _)- | (Just vecTc) <- HashMap.lookup (nameOcc vecTcNm) tcm+ | (Just vecTc) <- lookupUniqMap vecTcNm tcm+ , nameOcc vecTcNm == "Clash.Sized.Vector.Vec" , [nilCon,consCon] <- tyConDataCons vecTc = let nilVec = mkVec nilCon consCon aTy 0 [] innerVecTy = mkTyConApp vecTcNm [LitTy (NumTy 0), aTy] retVec = mkVec nilCon consCon innerVecTy n (replicate (fromInteger n) nilVec) in changed retVec- go _ ty = error $ $(curLoc) ++ "reduceUnconcat: argument does not have a vector type: " ++ showDoc ty+ go _ ty = error $ $(curLoc) ++ "reduceUnconcat: argument does not have a vector type: " ++ showPpr ty reduceUnconcat _ _ _ _ = error $ $(curLoc) ++ "reduceUnconcat: unimplemented" @@ -537,18 +667,19 @@ -> NormalizeSession Term reduceTranspose n 0 aTy arg = do tcm <- Lens.view tcCache- ty <- termType tcm arg+ let ty = termType tcm arg go tcm ty where- go tcm (coreView tcm -> Just ty') = go tcm ty'+ go tcm (coreView1 tcm -> Just ty') = go tcm ty' go tcm (tyView -> TyConApp vecTcNm _)- | (Just vecTc) <- HashMap.lookup (nameOcc vecTcNm) tcm+ | (Just vecTc) <- lookupUniqMap vecTcNm tcm+ , nameOcc vecTcNm == "Clash.Sized.Vector.Vec" , [nilCon,consCon] <- tyConDataCons vecTc = let nilVec = mkVec nilCon consCon aTy 0 [] innerVecTy = mkTyConApp vecTcNm [LitTy (NumTy 0), aTy] retVec = mkVec nilCon consCon innerVecTy n (replicate (fromInteger n) nilVec) in changed retVec- go _ ty = error $ $(curLoc) ++ "reduceTranspose: argument does not have a vector type: " ++ showDoc ty+ go _ ty = error $ $(curLoc) ++ "reduceTranspose: argument does not have a vector type: " ++ showPpr ty reduceTranspose _ _ _ _ = error $ $(curLoc) ++ "reduceTranspose: unimplemented" @@ -561,42 +692,255 @@ tcm <- Lens.view tcCache go tcm eTy where- go tcm (coreView tcm -> Just ty') = go tcm ty'+ go tcm (coreView1 tcm -> Just ty') = go tcm ty' go tcm (tyView -> TyConApp vecTcNm _)- | (Just vecTc) <- HashMap.lookup (nameOcc vecTcNm) tcm+ | (Just vecTc) <- lookupUniqMap vecTcNm tcm+ , nameOcc vecTcNm == "Clash.Sized.Vector.Vec" , [nilCon,consCon] <- tyConDataCons vecTc = let retVec = mkVec nilCon consCon aTy n (replicate (fromInteger n) arg) in changed retVec- go _ ty = error $ $(curLoc) ++ "reduceReplicate: argument does not have a vector type: " ++ showDoc ty+ go _ ty = error $ $(curLoc) ++ "reduceReplicate: argument does not have a vector type: " ++ showPpr ty +-- TODO: Take a shortcut when given index is a literal. Right now, this function+-- TODO: simply creates a case statement for every element in the vector, which+-- TODO: Clash will eliminate one-by-one if the index turned out to be literal.+-- TODO: It would of course be best to not create the cases in the first place!+reduceReplace_int+ :: InScopeSet+ -> Integer+ -- ^ Size of vector+ -> Type+ -- ^ Type of vector element+ -> Type+ -- ^ Type of vector+ -> Term+ -- ^ Vector+ -> Term+ -- ^ Index+ -> Term+ -- ^ Element+ -> NormalizeSession Term+reduceReplace_int is0 n aTy vTy v i newA = do+ tcm <- Lens.view tcCache+ go tcm vTy+ where+ -- Basically creates:+ --+ -- case eqInt i0 curI of+ -- True -> newA+ -- _ -> oldA+ --+ -- where:+ --+ -- - curI is the index of the current element, which we statically know+ -- - i0 is the index given to replace_int+ -- - newA is the element given to replace_int as a replacement for..+ -- - oldA; an element at index curI+ --+ replace_intElement+ :: TyConMap+ -- ^ TyCon map+ -> DataCon+ -- Int datacon+ -> Type+ -- Int type+ -> Term+ -- ^ Element in vector+ -> Integer+ -- ^+ -> Term+ replace_intElement tcm iDc iTy oldA elIndex = case0+ where+ (Just boolTc) = lookupUniqMap (getKey boolTyConKey) tcm+ [_,trueDc] = tyConDataCons boolTc+ eqInt = eqIntPrim iTy (mkTyConApp (tyConName boolTc) [])+ case0 = Case (mkApps eqInt [Left i+ ,Left (mkApps (Data iDc)+ [Left (Literal (IntLiteral elIndex))])+ ])+ aTy+ [(DefaultPat, oldA)+ ,(DataPat trueDc [] [], newA)+ ]++ -- Equality on lifted Int that returns a Bool+ eqIntPrim+ :: Type+ -> Type+ -> Term+ eqIntPrim intTy boolTy =+ Prim "Clash.Transformations.eqInt"+ (PrimInfo (mkFunTy intTy (mkFunTy intTy boolTy)) WorkVariable)++ go tcm (coreView1 tcm -> Just ty') = go tcm ty'+ go tcm (tyView -> TyConApp vecTcNm _)+ | (Just vecTc) <- lookupUniqMap vecTcNm tcm+ , nameOcc vecTcNm == "Clash.Sized.Vector.Vec"+ , [nilCon,consCon] <- tyConDataCons vecTc+ = do+ -- Get data constructors of 'Int'+ uniqs0 <- Lens.use uniqSupply+ let iTy = termType tcm i+ (TyConApp iTcNm _) = tyView iTy+ (Just iTc) = lookupUniqMap iTcNm tcm+ [iDc] = tyConDataCons iTc++ -- Get elements from vector+ (uniqs1,(vars,elems)) = second (second concat . unzip)+ $ extractElems+ uniqs0+ is0+ consCon+ aTy+ 'I'+ n+ v++ -- Replace every element with (if i == elIndex then newA else oldA)+ let replacedEls = zipWith (replace_intElement tcm iDc iTy) vars [0..]+ lbody = mkVec nilCon consCon aTy n replacedEls+ lb = Letrec (init elems) lbody+ uniqSupply Lens..= uniqs1+ changed lb+ go _ ty = error $ $(curLoc) ++ "reduceReplace_int: argument does not have "+ ++ "a vector type: " ++ showPpr ty++-- TODO: Take a shortcut when given index is a literal. Right now, this function+-- TODO: simply creates a case statement for every element in the vector, which+-- TODO: Clash will eliminate one-by-one if the index turned out to be literal.+-- TODO: It would of course be best to not create the cases in the first place!+reduceIndex_int+ :: InScopeSet+ -> Integer+ -- ^ Size of vector+ -> Type+ -- ^ Type of vector element+ -> Term+ -- ^ Vector+ -> Term+ -- ^ Index+ -> NormalizeSession Term+reduceIndex_int is0 n aTy v i = do+ tcm <- Lens.view tcCache+ let vTy = termType tcm v+ go tcm vTy+ where+ -- Basically creates:+ --+ -- case eqInt i0 curI of+ -- True -> curA+ -- _ -> next+ --+ -- where:+ --+ -- - curI is the index of the current element, which we statically know+ -- - i0 is the index given to index_int+ -- - curA is the element at index curI+ -- - next; the value if the current index is not equal to index argument+ --+ index_intElement+ :: TyConMap+ -- ^ TyCon map+ -> DataCon+ -- Int datacon+ -> Type+ -- Int type+ -> (Term, Integer)+ -- ^ Element in the vector, and its corresponding index+ -> Term+ -- ^ The rest+ -> Term+ index_intElement tcm iDc iTy (cur,elIndex) next = case0+ where+ (Just boolTc) = lookupUniqMap (getKey boolTyConKey) tcm+ [_,trueDc] = tyConDataCons boolTc+ eqInt = eqIntPrim iTy (mkTyConApp (tyConName boolTc) [])+ case0 = Case (mkApps eqInt [Left i+ ,Left (mkApps (Data iDc)+ [Left (Literal (IntLiteral elIndex))])+ ])+ aTy+ [(DefaultPat, next)+ ,(DataPat trueDc [] [], cur)+ ]++ -- Equality on lifted Int that returns a Bool+ eqIntPrim+ :: Type+ -> Type+ -> Term+ eqIntPrim intTy boolTy =+ Prim "Clash.Transformations.eqInt"+ (PrimInfo (mkFunTy intTy (mkFunTy intTy boolTy)) WorkVariable)++ go tcm (coreView1 tcm -> Just ty') = go tcm ty'+ go tcm (tyView -> TyConApp vecTcNm _)+ | (Just vecTc) <- lookupUniqMap vecTcNm tcm+ , nameOcc vecTcNm == "Clash.Sized.Vector.Vec"+ , [_nilCon,consCon] <- tyConDataCons vecTc+ = do+ -- Get data constructors of 'Int'+ uniqs0 <- Lens.use uniqSupply+ let iTy = termType tcm i+ (TyConApp iTcNm _) = tyView iTy+ (Just iTc) = lookupUniqMap iTcNm tcm+ [iDc] = tyConDataCons iTc++ -- Get elements from vector+ (uniqs1,(vars,elems)) = second (second concat . unzip)+ $ extractElems+ uniqs0+ is0+ consCon+ aTy+ 'I'+ n+ v++ -- Build a right-biased tree of case-expressions+ let indexed = foldr (index_intElement tcm iDc iTy)+ (undefinedTm aTy)+ (zip vars [0..])+ lb = Letrec (init elems) indexed+ uniqSupply Lens..= uniqs1+ changed lb+ go _ ty = error $ $(curLoc) ++ "indexReplace_int: argument does not have "+ ++ "a vector type: " ++ showPpr ty+ -- | Replace an application of the @Clash.Sized.Vector.dtfold@ primitive on -- vectors of a known length @n@, by the fully unrolled recursive "definition" -- of @Clash.Sized.Vector.dtfold@-reduceDTFold :: Integer -- ^ Length of the vector- -> Type -- ^ Element type of the argument vector- -> Term -- ^ Function to convert elements with- -> Term -- ^ Function to combine branches with- -> Term -- ^ The vector to fold- -> NormalizeSession Term-reduceDTFold n aTy lrFun brFun arg = do+reduceDTFold+ :: InScopeSet+ -> Integer -- ^ Length of the vector+ -> Type -- ^ Element type of the argument vector+ -> Term -- ^ Function to convert elements with+ -> Term -- ^ Function to combine branches with+ -> Term -- ^ The vector to fold+ -> NormalizeSession Term+reduceDTFold inScope n aTy lrFun brFun arg = do tcm <- Lens.view tcCache- ty <- termType tcm arg+ let ty = termType tcm arg go tcm ty where- go tcm (coreView tcm -> Just ty') = go tcm ty'+ go tcm (coreView1 tcm -> Just ty') = go tcm ty' go tcm (tyView -> TyConApp vecTcNm _)- | (Just vecTc) <- HashMap.lookup (nameOcc vecTcNm) tcm+ | (Just vecTc) <- lookupUniqMap vecTcNm tcm+ , nameOcc vecTcNm == "Clash.Sized.Vector.Vec" , [_,consCon] <- tyConDataCons vecTc- = do let (vars,elems) = second concat . unzip- $ extractElems consCon aTy 'T' (2^n) arg- (_ltv:Right snTy:_,_) <- splitFunForallTy <$> termType tcm brFun- let (TyConApp snatTcNm _) = tyView snTy- (Just snatTc) = HashMap.lookup (nameOcc snatTcNm) tcm+ = do uniqs0 <- Lens.use uniqSupply+ let (uniqs1,(vars,elems)) = second (second concat . unzip)+ $ extractElems uniqs0 inScope consCon aTy+ 'T' (2^n) arg+ (_ltv:Right snTy:_,_) = splitFunForallTy (termType tcm brFun)+ (TyConApp snatTcNm _) = tyView snTy+ (Just snatTc) = lookupUniqMap snatTcNm tcm [snatDc] = tyConDataCons snatTc lbody = doFold (buildSNat snatDc) (n-1) vars- lb = Letrec (bind (rec (init elems)) lbody)+ lb = Letrec (init elems) lbody+ uniqSupply Lens..= uniqs1 changed lb- go _ ty = error $ $(curLoc) ++ "reduceDTFold: argument does not have a vector type: " ++ showDoc ty+ go _ ty = error $ $(curLoc) ++ "reduceDTFold: argument does not have a vector type: " ++ showPpr ty doFold :: (Integer -> Term) -> Integer -> [Term] -> Term doFold _ _ [x] = mkApps lrFun [Left x]@@ -614,30 +958,35 @@ -- | Replace an application of the @Clash.Sized.RTree.tdfold@ primitive on -- trees of a known depth @n@, by the fully unrolled recursive "definition" -- of @Clash.Sized.RTree.tdfold@-reduceTFold :: Integer -- ^ Depth of the tree- -> Type -- ^ Element type of the argument tree- -> Term -- ^ Function to convert elements with- -> Term -- ^ Function to combine branches with- -> Term -- ^ The tree to fold- -> NormalizeSession Term-reduceTFold n aTy lrFun brFun arg = do+reduceTFold+ :: InScopeSet+ -> Integer -- ^ Depth of the tree+ -> Type -- ^ Element type of the argument tree+ -> Term -- ^ Function to convert elements with+ -> Term -- ^ Function to combine branches with+ -> Term -- ^ The tree to fold+ -> NormalizeSession Term+reduceTFold inScope n aTy lrFun brFun arg = do tcm <- Lens.view tcCache- ty <- termType tcm arg+ let ty = termType tcm arg go tcm ty where- go tcm (coreView tcm -> Just ty') = go tcm ty'+ go tcm (coreView1 tcm -> Just ty') = go tcm ty' go tcm (tyView -> TyConApp treeTcNm _)- | (Just treeTc) <- HashMap.lookup (nameOcc treeTcNm) tcm+ | (Just treeTc) <- lookupUniqMap treeTcNm tcm+ , nameOcc treeTcNm == "Clash.Sized.RTree.RTree" , [lrCon,brCon] <- tyConDataCons treeTc- = do let (vars,elems) = extractTElems lrCon brCon aTy 'T' n arg- (_ltv:Right snTy:_,_) <- splitFunForallTy <$> termType tcm brFun- let (TyConApp snatTcNm _) = tyView snTy- (Just snatTc) = HashMap.lookup (nameOcc snatTcNm) tcm+ = 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)+ (TyConApp snatTcNm _) = tyView snTy+ (Just snatTc) = lookupUniqMap snatTcNm tcm [snatDc] = tyConDataCons snatTc lbody = doFold (buildSNat snatDc) (n-1) vars- lb = Letrec (bind (rec elems) lbody)+ lb = Letrec elems lbody+ uniqSupply Lens..= uniqs1 changed lb- go _ ty = error $ $(curLoc) ++ "reduceTFold: argument does not have a tree type: " ++ showDoc ty+ go _ ty = error $ $(curLoc) ++ "reduceTFold: argument does not have a tree type: " ++ showPpr ty doFold _ _ [x] = mkApps lrFun [Left x] doFold snDc k xs =@@ -660,21 +1009,18 @@ tcm <- Lens.view tcCache go tcm eTy where- go tcm (coreView tcm -> Just ty') = go tcm ty'+ go tcm (coreView1 tcm -> Just ty') = go tcm ty' go tcm (tyView -> TyConApp treeTcNm _)- | (Just treeTc) <- HashMap.lookup (nameOcc treeTcNm) tcm+ | (Just treeTc) <- lookupUniqMap treeTcNm tcm+ , nameOcc treeTcNm == "Clash.Sized.RTree.RTree" , [lrCon,brCon] <- tyConDataCons treeTc = let retVec = mkRTree lrCon brCon aTy n (replicate (2^n) arg) in changed retVec- go _ ty = error $ $(curLoc) ++ "reduceTReplicate: argument does not have a vector type: " ++ showDoc ty+ go _ ty = error $ $(curLoc) ++ "reduceTReplicate: argument does not have a RTree type: " ++ showPpr ty buildSNat :: DataCon -> Integer -> Term buildSNat snatDc i = mkApps (Data snatDc) [Right (LitTy (NumTy i))-#if MIN_VERSION_ghc(8,2,0) ,Left (Literal (NaturalLiteral (toInteger i)))-#else- ,Left (Literal (IntegerLiteral (toInteger i)))-#endif ]
src/Clash/Normalize/Strategy.hs view
@@ -14,67 +14,78 @@ import Clash.Rewrite.Types import Clash.Rewrite.Util +-- [Note: bottomup traversal evalConst]+--+-- 2-May-2019: There is a bug in the evaluator where all data constructors are+-- considered lazy, even though their declaration says they have strict fields.+-- This causes some reductions to fail because the term under the constructor is+-- not in WHNF, which is what some of the evaluation rules for certain primitive+-- operations expect. Using a bottom-up traversal works around this bug by+-- ensuring that the values under the constructor are in WHNF.+--+-- Using a bottomup traversal ensures that constants are reduced to NF, even if+-- constructors are lazy, thus ensuring more sensible/smaller generated HDL.+ -- | Normalisation transformation normalization :: NormRewrite-normalization = rmDeadcode >-> constantPropgation >-> etaTL >-> rmUnusedExpr >-!-> anf >-!-> rmDeadcode >->+normalization = rmDeadcode >-> constantPropagation >-> etaTL >-> rmUnusedExpr >-!-> anf >-!-> rmDeadcode >-> bindConst >-> letTL >-> evalConst >-!-> cse >-!-> cleanup >-> recLetRec where- etaTL = apply "etaTL" etaExpansionTL !-> innerMost (apply "applicationPropagation" appProp)- anf = topdownR (apply "nonRepANF" nonRepANF) >-> apply "ANF" makeANF+ etaTL = apply "etaTL" etaExpansionTL !-> topdownR (apply "applicationPropagation" appPropFast)+ anf = topdownR (apply "nonRepANF" nonRepANF) >-> apply "ANF" makeANF >-> topdownR (apply "caseCon" caseCon) letTL = topdownSucR (apply "topLet" topLet) recLetRec = apply "recToLetRec" recToLetRec rmUnusedExpr = bottomupR (apply "removeUnusedExpr" removeUnusedExpr) rmDeadcode = bottomupR (apply "deadcode" deadCode) bindConst = topdownR (apply "bindConstantVar" bindConstantVar)- evalConst = topdownR (apply "evalConst" reduceConst)+ -- See [Note] bottomup traversal evalConst:+ evalConst = bottomupR (apply "evalConst" reduceConst) cse = topdownR (apply "CSE" simpleCSE)- cleanup = topdownSucR (apply "inlineCleanup" inlineCleanup) !->+ cleanup = topdownR (apply "etaExpandSyn" etaExpandSyn) >->+ topdownSucR (apply "inlineCleanup" inlineCleanup) !-> innerMost (applyMany [("caseCon" , caseCon) ,("bindConstantVar", bindConstantVar) ,("letFlat" , flattenLet)]) >-> rmDeadcode >-> letTL -constantPropgation :: NormRewrite-constantPropgation = propagate >-> repeatR inlineAndPropagate >->+constantPropagation :: NormRewrite+constantPropagation = inlineAndPropagate >-> caseFlattening >-> dec >-> spec >-> dec >-> conSpec where- propagate = innerMost (applyMany transPropagate)- inlineAndPropagate = (topdownR (applyMany transInlineSafe) >-> inlineNR)- !-> propagate+ 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 "constantSpec" constantSpec) - transPropagate :: [(String,NormRewrite)]- transPropagate =- [ ("applicationPropagation", appProp )- , ("bindConstantVar" , bindConstantVar)- , ("caseLet" , caseLet )- , ("caseCase" , caseCase )- , ("caseCon" , caseCon )- ]-- -- These transformations can safely be applied in a top-down traversal as- -- they themselves check whether the to-be-inlined binder is recursive or not.- transInlineSafe :: [(String,NormRewrite)]- transInlineSafe =- [ ("inlineWorkFree" , inlineWorkFree)- , ("inlineSmall" , inlineSmall)- , ("bindOrLiftNonRep", inlineOrLiftNonRep) -- See: [Note] bindNonRep before liftNonRep- -- See: [Note] bottom-up traversal for liftNonRep- , ("reduceNonRepPrim", reduceNonRepPrim)+ transPropagateAndInline :: [(String,NormRewrite)]+ transPropagateAndInline =+ [ ("applicationPropagation", appPropFast )+ , ("bindConstantVar" , bindConstantVar )+ , ("caseLet" , caseLet )+ , ("caseCase" , caseCase )+ , ("caseCon" , caseCon )+ , ("elemExistentials" , elemExistentials )+ , ("caseElemNonReachable" , caseElemNonReachable )+ , ("removeUnusedExpr" , removeUnusedExpr )+ -- These transformations can safely be applied in a top-down traversal as+ -- they themselves check whether the to-be-inlined binder is recursive or not.+ , ("inlineWorkFree" , inlineWorkFree)+ , ("inlineSmall" , inlineSmall)+ , ("bindOrLiftNonRep", inlineOrLiftNonRep) -- See: [Note] bindNonRep before liftNonRep+ -- See: [Note] bottom-up traversal for liftNonRep+ , ("reduceNonRepPrim", reduceNonRepPrim) - , ("caseCast" , caseCast)- , ("letCast" , letCast)- , ("splitCastWork" , splitCastWork)- , ("argCastSpec" , argCastSpec)- , ("inlineCast" , inlineCast)- , ("eliminateCastCast",eliminateCastCast)- ]+ , ("caseCast" , caseCast)+ , ("letCast" , letCast)+ , ("splitCastWork" , splitCastWork)+ , ("argCastSpec" , argCastSpec)+ , ("inlineCast" , inlineCast)+ , ("eliminateCastCast",eliminateCastCast)+ ] -- InlineNonRep cannot be applied in a top-down traversal, as the non-representable -- binder might be recursive. The idea is, is that if the recursive@@ -207,7 +218,7 @@ > f = \a x -> (a x) && (f a x) > f' = \x -> (not x) && (f not x) -Because `f` has already been specialised on the alpha-equivalent-to-itself `not`+Because `f` has already been specialized on the alpha-equivalent-to-itself `not` function, liftNonRep leads to: > main = f'@@ -222,10 +233,17 @@ -- | Topdown traversal, stops upon first success topdownSucR :: Rewrite extra -> Rewrite extra-topdownSucR r = r >-! (allR True (topdownSucR r))+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 r = bottomupR (r !-> innerMost r)+innerMost = let go r = bottomupR (r !-> innerMost r) in go+{-# INLINE innerMost #-} applyMany :: [(String,Rewrite extra)] -> Rewrite extra applyMany = foldr1 (>->) . map (uncurry apply)+{-# INLINE applyMany #-}
+ src/Clash/Normalize/Strategy.hs-boot view
@@ -0,0 +1,6 @@+module Clash.Normalize.Strategy (constantPropagation, normalization) where++import Clash.Normalize.Types (NormRewrite)++normalization :: NormRewrite+constantPropagation :: NormRewrite
src/Clash/Normalize/Transformations.hs view
@@ -1,1748 +1,2294 @@ {-| Copyright : (C) 2012-2016, University of Twente, 2016-2017, Myrtle Software Ltd,- 2017 , Google Inc.- License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>-- Transformations of the Normalization process--}--{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE ViewPatterns #-}--module Clash.Normalize.Transformations- ( appProp- , caseLet- , caseCon- , caseCase- , inlineNonRep- , inlineOrLiftNonRep- , typeSpec- , nonRepSpec- , etaExpansionTL- , nonRepANF- , bindConstantVar- , constantSpec- , makeANF- , deadCode- , topLet- , recToLetRec- , inlineWorkFree- , inlineHO- , inlineSmall- , simpleCSE- , reduceConst- , reduceNonRepPrim- , caseFlat- , disjointExpressionConsolidation- , removeUnusedExpr- , inlineCleanup- , flattenLet- , splitCastWork- , inlineCast- , caseCast- , letCast- , eliminateCastCast- , argCastSpec- )-where--import Control.Concurrent.Supply (splitSupply)-import Control.Exception (throw)-import qualified Control.Lens as Lens-import qualified Control.Monad as Monad-import Control.Monad.Writer- (WriterT (..), censor, lift, listen, tell)-import Control.Monad.Trans.Except (runExcept)-import Data.Bits ((.&.), complement)-import qualified Data.Either as Either-import qualified Data.HashMap.Lazy as HashMap-import qualified Data.HashSet as HashSet-import qualified Data.List as List-import qualified Data.Maybe as Maybe-import qualified Data.Monoid as Monoid-import qualified Data.Primitive.ByteArray as BA-import qualified Data.Set as Set-import qualified Data.Set.Lens as Lens-import Data.Text (Text, unpack)-import qualified Data.Vector.Primitive as PV-import Debug.Trace (trace)-import GHC.Integer.GMP.Internals (Integer (..), BigNat (..))-import Unbound.Generics.LocallyNameless- (Bind, Embed (..), bind, embed, rec, runFreshM, unbind, unembed, unrebind, unrec)-import Unbound.Generics.LocallyNameless.Unsafe (unsafeUnbind)--import BasicTypes (InlineSpec (..))--import Clash.Core.DataCon (DataCon (..))-import Clash.Core.Evaluator (whnf')-import Clash.Core.Name- (Name (..), NameSort (..), name2String, string2InternalName, string2SystemName)-import Clash.Core.FreeVars (termFreeIds, termFreeTyVars,- typeFreeVars)-import Clash.Core.Literal (Literal (..))-import Clash.Core.Pretty (showDoc)-import Clash.Core.Subst- (substBndr, substTm, substTms, substTyInTm, substTysinTm)-import Clash.Core.Term (LetBinding, Pat (..), Term (..), TmOccName)-import Clash.Core.Type (TypeView (..), applyFunTy,- applyTy, isPolyFunCoreTy,- normalizeType,- splitFunTy, typeKind,- tyView, undefinedTy)-import Clash.Core.TyCon (tyConDataCons)-import Clash.Core.Util- (collectArgs, idToVar, isClockOrReset, isCon, isFun, isLet, isPolyFun, isPrim,- isSignalType, isVar, mkApps, mkLams, mkVec, termSize, termType,- tyNatSize)-import Clash.Core.Var (Id, Var (..))-import Clash.Driver.Types (DebugLevel (..), ClashException (..))-import Clash.Netlist.BlackBox.Util (usedArguments)-import Clash.Netlist.Types (HWType (..))-import Clash.Netlist.Util- (coreTypeToHWType, representableType, splitNormalized)-import Clash.Normalize.DEC-import Clash.Normalize.PrimitiveReductions-import Clash.Normalize.Types-import Clash.Normalize.Util-import Clash.Primitives.Types (Primitive (..), PrimMap)-import Clash.Rewrite.Combinators-import Clash.Rewrite.Types-import Clash.Rewrite.Util-import Clash.Util--inlineOrLiftNonRep :: NormRewrite-inlineOrLiftNonRep = inlineOrLiftBinders nonRepTest inlineTest- where- nonRepTest :: (Var Term, Embed Term) -> RewriteMonad extra Bool- nonRepTest ((Id _ tyE), _)- = not <$> (representableType <$> Lens.view typeTranslator- <*> Lens.view allowZero- <*> pure False- <*> Lens.view tcCache- <*> pure (unembed tyE))- nonRepTest _ = return False-- inlineTest :: Term -> (Var Term, Embed Term) -> RewriteMonad extra Bool- inlineTest e (id_@(Id (nameOcc -> idName) _), exprE)- = let e' = unembed exprE- in not . or <$> sequence -- We do __NOT__ inline:- [ -- 1. recursive let-binders- elem idName <$> (Lens.toListOf <$> localFreeIds <*> pure e')- -- 2. join points (which are not void-wrappers)- , pure (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.- , (>1) <$> freeOccurances- ]- where- -- The number of free occurrences of the binder in the entire- -- let-expression- freeOccurances :: RewriteMonad extra Int- freeOccurances = case e of- Letrec b -> do- -- It is safe to use unsafeUnbind because the expression @e@ is- -- the original let-expression, unbound and bound again, so no- -- bound variables have changed.- let (_,res) = unsafeUnbind b- fvOcc <-Lens.toListOf <$> localFreeIds <*> pure res- return (length $ filter (== idName) fvOcc)- _ -> return 0-- inlineTest _ _ = return True--{- [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 :: 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---- | Specialize functions on their non-representable argument-nonRepSpec :: NormRewrite-nonRepSpec ctx e@(App e1 e2)- | (Var _ _, args) <- collectArgs e1- , (_, []) <- Either.partitionEithers args- , null $ Lens.toListOf termFreeTyVars e2- = do tcm <- Lens.view tcCache- e2Ty <- termType tcm e2- localVar <- isLocalVar e2- nonRepE2 <- not <$> (representableType <$> Lens.view typeTranslator- <*> Lens.view allowZero- <*> 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 specialised on- inlineInternalSpecialisationArgument- :: Term- -> NormalizeSession Term- inlineInternalSpecialisationArgument app- | (Var _ f,fArgs) <- collectArgs app- = do- fTmM <- fmap (HashMap.lookup (nameOcc f)) $ Lens.use bindings- case fTmM of- Just (fNm,_,_,_,tm)- | nameSort fNm == Internal- -> do- tm' <- censor (const mempty) (bottomupR appProp ctx (mkApps tm fArgs))- return tm'- _ -> return app- | otherwise = return app--nonRepSpec _ e = return e---- | Lift the let-bindings out of the subject of a Case-decomposition-caseLet :: NormRewrite-caseLet _ (Case (Letrec b) ty alts) = do- (xes,e) <- unbind b- changed (Letrec (bind xes (Case e ty alts)))--caseLet _ e = return e---- | Move a Case-decomposition from the subject of a Case-decomposition to the alternatives-caseCase :: NormRewrite-caseCase _ e@(Case (Case scrut alts1Ty alts1) alts2Ty alts2)- = do- ty1Rep <- representableType <$> Lens.view typeTranslator- <*> Lens.view allowZero- <*> pure False- <*> Lens.view tcCache- <*> pure alts1Ty- if not ty1Rep- then do newAlts <- mapM ( return- . uncurry bind- . second (\altE -> Case altE alts2Ty alts2)- <=< unbind- ) alts1- changed $ Case scrut alts2Ty newAlts- else return e--caseCase _ e = return e---- | Inline function with a non-representable result if it's the subject--- of a Case-decomposition-inlineNonRep :: NormRewrite-inlineNonRep _ e@(Case scrut altsTy alts)- | (Var _ (nameOcc -> f), args) <- collectArgs scrut- = do- (nameOcc -> cf,_) <- Lens.use curFun- isInlined <- zoomExtra (alreadyInlined f cf)- limit <- Lens.use (extra.inlineLimit)- tcm <- Lens.view tcCache- scrutTy <- termType tcm scrut- let noException = not (exception tcm scrutTy)- if noException && (Maybe.fromMaybe 0 isInlined) > limit- then do- ty <- termType tcm scrut- traceIf True (concat [$(curLoc) ++ "InlineNonRep: " ++ show f- ," already inlined " ++ show limit ++ " times in:"- , show cf- , "\nType of the subject is: " ++ showDoc ty- , "\nFunction " ++ show cf- , " will not reach a normal form, and compilation"- , " might fail."- , "\nRun with '-fclash-inline-limit=N' to increase"- , " the inlining limit to N."- ])- (return e)- else do- bodyMaybe <- fmap (HashMap.lookup f) $ Lens.use bindings- nonRepScrut <- not <$> (representableType <$> Lens.view typeTranslator- <*> Lens.view allowZero- <*> pure False- <*> Lens.view tcCache- <*> pure scrutTy)- case (nonRepScrut, bodyMaybe) of- (True,Just (_,_,_,_,scrutBody)) -> do- Monad.when noException (zoomExtra (addNewInline f cf))- changed $ Case (mkApps scrutBody args) altsTy alts- _ -> return e- where- exception tcm ((tyView . typeKind tcm) -> TyConApp (name2String -> "GHC.Types.Constraint") _) = True- exception _ _ = False--inlineNonRep _ e = return e---- | 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.-caseCon :: NormRewrite-caseCon _ (Case scrut ty alts)- | (Data dc, args) <- collectArgs scrut- = do- alts' <- mapM unbind alts- let dcAltM = List.find (equalCon dc . fst) alts'- case dcAltM of- Just (DataPat _ pxs, e) ->- let (tvs,xs) = unrebind pxs- fvs = Lens.toListOf termFreeIds e- (binds,_) = List.partition ((`elem` fvs) . nameOcc . varName . fst)- $ zip xs (Either.lefts args)- e' = case binds of- [] -> e- _ -> Letrec $ bind (rec $ map (second embed) binds) e- substTyMap = zip (map (nameOcc.varName) tvs) (drop (length $ dcUnivTyVars dc) (Either.rights args))- in changed (substTysinTm substTyMap e')- _ -> case alts' of- ((DefaultPat,e):_) -> changed e- _ -> changed (mkApps (Prim "Clash.Transformations.undefined" undefinedTy) [Right ty])- where- equalCon dc (DataPat dc' _) = dcTag dc == dcTag (unembed dc')- equalCon _ _ = False--caseCon _ c@(Case (Literal l) _ alts) = do- alts' <- mapM unbind alts- let ltAltsM = List.find (equalLit . fst) alts'- case ltAltsM of- Just (LitPat _,e) -> changed e- _ -> matchLiteralContructor c l alts'- where- equalLit (LitPat l') = l == (unembed l')- equalLit _ = False--caseCon ctx e@(Case subj ty alts)- | (Prim _ _,_) <- collectArgs subj = do- tcm <- Lens.view tcCache- bndrs <- Lens.use bindings- primEval <- Lens.view evaluator- ids <- Lens.use uniqSupply- let (ids1,ids2) = splitSupply ids- uniqSupply Lens..= ids2- gh <- Lens.use globalHeap- lvl <- Lens.view dbgLevel- case whnf' primEval bndrs tcm gh ids1 True subj of- (gh',v) -> globalHeap Lens..= gh' >> case v of- Literal l -> caseCon ctx (Case (Literal l) ty alts)- subj' -> case collectArgs subj' of- (Data _,_) -> caseCon ctx (Case subj' ty alts)-#if MIN_VERSION_ghc(8,2,2)- (Prim nm ty',_:msgOrCallStack:_)- | nm == "Control.Exception.Base.absentError" ->- let e' = mkApps (Prim nm ty') [Right ty,msgOrCallStack]- in changed e'-#endif-- (Prim nm ty',repTy:_:msgOrCallStack:_)- | nm `elem` ["Control.Exception.Base.patError"-#if !MIN_VERSION_ghc(8,2,2)- ,"Control.Exception.Base.absentError"-#endif- ,"GHC.Err.undefined"] ->- let e' = mkApps (Prim nm ty') [repTy,Right ty,msgOrCallStack]- in changed e'- (Prim nm ty',[_])- | nm `elem` ["Clash.Transformations.undefined"] ->- let e' = mkApps (Prim nm ty') [Right ty]- in changed e'- (Prim nm _,[])- | nm `elem` ["EmptyCase"] ->- changed (Prim nm ty)- _ -> do- subjTy <- termType tcm subj- tran <- Lens.view typeTranslator- case coreTypeToHWType tran tcm False subjTy of- Right (Void (Just hty))- | hty `elem` [BitVector 0, Unsigned 0, Signed 0, Index 1]- -> caseCon ctx (Case (Literal (IntegerLiteral 0)) ty alts)- _ -> traceIf (lvl > DebugNone && isConstant e)- ("Irreducible constant as case subject: " ++ showDoc subj ++ "\nCan be reduced to: " ++ showDoc subj')- (caseOneAlt e)--caseCon ctx e@(Case subj ty alts) = do- tcm <- Lens.view tcCache- subjTy <- termType tcm subj- tran <- Lens.view typeTranslator- case coreTypeToHWType tran tcm False subjTy of- Right (Void (Just hty))- | hty `elem` [BitVector 0, Unsigned 0, Signed 0, Index 1]- -> caseCon ctx (Case (Literal (IntegerLiteral 0)) ty alts)- _ -> caseOneAlt e--caseCon _ e = return e--matchLiteralContructor- :: Term- -> Literal- -> [(Pat,Term)]- -> NormalizeSession Term-matchLiteralContructor c (IntegerLiteral l) alts = go (reverse alts)- where- go [(DefaultPat,e)] = changed e- go ((DataPat dc pxs,e):alts')- | dcTag (unembed dc) == 1- , l >= ((-2)^(63::Int)) && l < 2^(63::Int)- = let ([],xs) = unrebind pxs- fvs = Lens.toListOf termFreeIds e- (binds,_) = List.partition ((`elem` fvs) . nameOcc . varName . fst)- $ zip xs [Literal (IntLiteral l)]- e' = case binds of- [] -> e- _ -> Letrec $ bind (rec $ map (second embed) binds) e- in changed e'- | dcTag (unembed dc) == 2- , l >= 2^(63::Int)- = let !(Jp# !(BN# ba)) = l- ba' = BA.ByteArray ba- bv = PV.Vector 0 (BA.sizeofByteArray ba') ba'- ([],xs) = unrebind pxs- fvs = Lens.toListOf termFreeIds e- (binds,_) = List.partition ((`elem` fvs) . nameOcc . varName . fst)- $ zip xs [Literal (ByteArrayLiteral bv)]- e' = case binds of- [] -> e- _ -> Letrec $ bind (rec $ map (second embed) binds) e- in changed e'- | dcTag (unembed dc) == 3- , l < ((-2)^(63::Int))- = let !(Jn# !(BN# ba)) = l- ba' = BA.ByteArray ba- bv = PV.Vector 0 (BA.sizeofByteArray ba') ba'- ([],xs) = unrebind pxs- fvs = Lens.toListOf termFreeIds e- (binds,_) = List.partition ((`elem` fvs) . nameOcc . varName . fst)- $ zip xs [Literal (ByteArrayLiteral bv)]- e' = case binds of- [] -> e- _ -> Letrec $ bind (rec $ map (second embed) binds) e- in changed e'- | otherwise- = go alts'- go _ = error $ $(curLoc) ++ "Report as bug: caseCon error: " ++ showDoc c--matchLiteralContructor c (NaturalLiteral l) alts = go (reverse alts)- where- go [(DefaultPat,e)] = changed e- go ((DataPat dc pxs,e):alts')- | dcTag (unembed dc) == 1- , l >= 0 && l < 2^(64::Int)- = let ([],xs) = unrebind pxs- fvs = Lens.toListOf termFreeIds e- (binds,_) = List.partition ((`elem` fvs) . nameOcc . varName . fst)- $ zip xs [Literal (WordLiteral l)]- e' = case binds of- [] -> e- _ -> Letrec $ bind (rec $ map (second embed) binds) e- in changed e'- | dcTag (unembed dc) == 2- , l >= 2^(64::Int)- = let !(Jp# !(BN# ba)) = l- ba' = BA.ByteArray ba- bv = PV.Vector 0 (BA.sizeofByteArray ba') ba'- ([],xs) = unrebind pxs- fvs = Lens.toListOf termFreeIds e- (binds,_) = List.partition ((`elem` fvs) . nameOcc . varName . fst)- $ zip xs [Literal (ByteArrayLiteral bv)]- e' = case binds of- [] -> e- _ -> Letrec $ bind (rec $ map (second embed) binds) e- in changed e'- | otherwise- = go alts'- go _ = error $ $(curLoc) ++ "Report as bug: caseCon error: " ++ showDoc c--matchLiteralContructor _ _ ((DefaultPat,e):_) = changed e-matchLiteralContructor c _ _ =- error $ $(curLoc) ++ "Report as bug: caseCon error: " ++ showDoc c--caseOneAlt :: Term -> RewriteMonad extra Term-caseOneAlt e@(Case _ _ [alt]) = do- (pat,altE) <- unbind alt- case pat of- DefaultPat -> changed altE- LitPat _ -> changed altE- DataPat _ pxs -> let (tvs,xs) = unrebind pxs- ftvs = Lens.toListOf termFreeTyVars altE- fvs = Lens.toListOf termFreeIds altE- usedTvs = filter ((`elem` ftvs) . nameOcc . varName) tvs- usedXs = filter ((`elem` fvs) . nameOcc . varName) xs- in case (usedTvs,usedXs) of- ([],[]) -> changed altE- _ -> return e--caseOneAlt e = return e---- | Bring an application of a DataCon or Primitive in ANF, when the argument is--- is considered non-representable-nonRepANF :: NormRewrite-nonRepANF ctx e@(App appConPrim arg)- | (conPrim, _) <- collectArgs e- , isCon conPrim || isPrim conPrim- = do- untranslatable <- isUntranslatable False arg- case (untranslatable,arg) of- (True,Letrec b) -> do (binds,body) <- unbind b- changed (Letrec (bind binds (App appConPrim body)))- (True,Case {}) -> specializeNorm ctx e- (True,Lam _) -> specializeNorm ctx e- (True,TyLam _) -> specializeNorm ctx e- _ -> return e--nonRepANF _ e = return e---- | Ensure that top-level lambda's eventually bind a let-expression of which--- the body is a variable-reference.-topLet :: NormRewrite-topLet ctx e- | all isLambdaBodyCtx ctx && not (isLet e)- = do- untranslatable <- isUntranslatable False e- if untranslatable- then return e- else do tcm <- Lens.view tcCache- (argId,argVar) <- mkTmBinderFor tcm (string2SystemName "result") e- changed . Letrec $ bind (rec [(argId,embed e)]) argVar--topLet ctx e@(Letrec b)- | all isLambdaBodyCtx ctx- = do- (binds,body) <- unbind b- localVar <- isLocalVar body- untranslatable <- isUntranslatable False body- if localVar || untranslatable- then return e- else do tcm <- Lens.view tcCache- (argId,argVar) <- mkTmBinderFor tcm (string2SystemName "result") body- changed . Letrec $ bind (rec $ unrec binds ++ [(argId,embed body)]) argVar--topLet _ e = return e---- Misc rewrites---- | Remove unused let-bindings-deadCode :: NormRewrite-deadCode _ e@(Letrec binds) = do- (xes, body) <- fmap (first unrec) $ unbind binds- let bodyFVs = Lens.toListOf termFreeIds body- (xesUsed,xesOther) = List.partition- ( (`elem` bodyFVs )- . nameOcc- . varName- . fst- ) xes- xesUsed' = findUsedBndrs [] xesUsed xesOther- if length xesUsed' /= length xes- then case xesUsed' of- [] -> changed body- _ -> changed . Letrec $ bind (rec xesUsed') body- else return e- where- findUsedBndrs :: [(Var Term, Embed Term)] -> [(Var Term, Embed Term)]- -> [(Var Term, Embed Term)] -> [(Var Term, Embed Term)]- findUsedBndrs used [] _ = used- findUsedBndrs used explore other =- let fvsUsed = concatMap (Lens.toListOf termFreeIds . unembed . snd) explore- (explore',other') = List.partition- ( (`elem` fvsUsed)- . nameOcc- . varName- . fst- ) other- in findUsedBndrs (used ++ explore) explore' other'--deadCode _ e = return e--removeUnusedExpr :: NormRewrite-removeUnusedExpr _ e@(collectArgs -> (p@(Prim nm _),args)) = do- bbM <- HashMap.lookup nm <$> Lens.use (extra.primitives)- case bbM of- Just (BlackBox pNm _ _ _ inc templ) -> do- let usedArgs = if isFromInt pNm- then [0,1]- else either usedArguments usedArguments templ ++- maybe [] (usedArguments . snd) inc- tcm <- Lens.view tcCache- args' <- go tcm 0 usedArgs args- if args == args'- then return e- else changed (mkApps p args')- _ -> return e- where- 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'- ty <- termType tcm tm- let p' = mkApps (Prim "Clash.Transformations.removedArg" undefinedTy) [Right ty]- if n `elem` used- then return (Left tm : args'')- else return (Left p' : args'')--removeUnusedExpr _ e@(Case _ _ [alt]) = do- (pat,altExpr) <- unbind alt- case pat of- DataPat _ (unrebind -> ([],xs)) -> do- let altFreeIds = Lens.setOf termFreeIds altExpr- if Set.null (Set.intersection (Set.fromList (map (nameOcc.varName) xs)) altFreeIds)- then changed altExpr- else return e- _ -> 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@(collectArgs -> (Data dc, [_,Right aTy,Right nTy,_,Left a,Left nil]))- | name2String (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)- -> do eTy <- termType tcm e- let (TyConApp vecTcNm _) = tyView eTy- (Just vecTc) = HashMap.lookup (nameOcc vecTcNm) tcm- [nilCon,consCon] = tyConDataCons vecTc- v = mkVec nilCon consCon aTy 1 [a]- changed v- _ -> return e--removeUnusedExpr _ e = return e---- | Inline let-bindings when the RHS is either a local variable reference or--- is constant (except clock or reset generators)-bindConstantVar :: NormRewrite-bindConstantVar = inlineBinders test- where- test _ (_,Embed e) = isLocalVar e >>= \case- True -> return True- _ -> isConstantNotClockReset e >>= \case- True -> Lens.use (extra.inlineConstantLimit) >>= \case- 0 -> return True- n -> return (termSize e <= n)- _ -> return False- -- test _ _ = return False---- | Push a cast over a case into it's alternatives.-caseCast :: NormRewrite-caseCast _ (Cast (Case subj ty alts) ty1 ty2) = do- alts' <- mapM castAlt alts- changed $ Case subj ty alts'- where- castAlt alt = do- (pat,altExpr) <- unbind alt- return $ bind pat (Cast altExpr ty1 ty2)-caseCast _ e = return e---- | Push a cast over a Letrec into it's body-letCast :: NormRewrite-letCast _ (Cast (Letrec b) ty1 ty2) = do- let (binds,body) = unsafeUnbind b- changed $ Letrec $ bind binds (Cast body ty1 ty2)-letCast _ e = return e----- | Push cast over an argument to a funtion 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')--- @-argCastSpec :: NormRewrite-argCastSpec ctx e@(App _ (Cast e' _ _)) = case e' of- Var _ _ -> go- Cast (Var _ _) _ _ -> go- _ -> warn go- where- go = specializeNorm ctx e- warn = trace (unlines ["WARNING: " ++ $(curLoc) ++ "specializing a function on a possibly non work-free cast."- ,"Generated HDL implementation might contain duplicate work."- ,"Please report this as a bug."- ,""- ,"Expression where this occurs:"- ,showDoc e- ])-argCastSpec _ e = return e---- | Only inline casts that just contain a 'Var', because these are guaranteed work-free.--- These are the result of the 'splitCastWork' transformation.-inlineCast :: NormRewrite-inlineCast = inlineBinders test- where- test _ (_, Embed (Cast (Var _ _) _ _)) = return True- test _ _ = return False---- | 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 :: NormRewrite-eliminateCastCast _ c@(Cast (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) ++ showDoc nm- ++ ": Found 2 nested casts whose types don't line up:\n"- ++ showDoc c)- Nothing)--eliminateCastCast _ e = return e---- | 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 :: NormRewrite-splitCastWork ctx unchanged@(Letrec b) = do- (v,e') <- unbind b- let vs = unrec v- (vss', Monoid.getAny -> hasChanged) <- listen (mapM splitCastLetBinding vs)- let vs' = concat vss'- if hasChanged then changed . Letrec $ bind (rec vs') (e')- else return unchanged- where- splitCastLetBinding :: LetBinding -> RewriteMonad extra [LetBinding]- splitCastLetBinding x@(nm, Embed e) = case e of- Cast (Var _ _) _ _ -> return [x] -- already work-free- Cast (Cast _ _ _) _ _ -> return [x] -- casts will be eliminated- Cast e' ty1 ty2 -> do- tcm <- Lens.view tcCache- (nm',var) <- mkTmBinderFor tcm (mkDerivedName ctx (name2String $ varName nm)) e'- changed [(nm',Embed e')- ,(nm, Embed $ Cast var ty1 ty2)- ]- _ -> return [x]--splitCastWork _ e = return e----- | Inline work-free functions, i.e. fully applied functions that evaluate to--- a constant-inlineWorkFree :: NormRewrite-inlineWorkFree _ e@(collectArgs -> (Var _ (nameOcc -> f),args))- = do- tcm <- Lens.view tcCache- eTy <- termType tcm e- argsHaveWork <- or <$> mapM (either expressionHasWork- (const (pure False)))- args- untranslatable <- isUntranslatableType True eTy- let isSignal = isSignalType tcm eTy- if untranslatable || isSignal || argsHaveWork- then return e- else do- bndrs <- Lens.use bindings- case HashMap.lookup f bndrs of- -- Don't inline recursive expressions- Just (_,_,_,_,body) -> do- isRecBndr <- isRecursiveBndr f- if isRecBndr- then return e- else changed (mkApps body 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- fvIds <- Lens.toListOf <$> localFreeIds <*> pure e'- tcm <- Lens.view tcCache- e'Ty <- termType tcm e'- let isSignal = isSignalType tcm e'Ty- return (not (null fvIds) || isSignal)--inlineWorkFree _ e@(Var fTy (nameOcc -> f)) = do- tcm <- Lens.view tcCache- let closed = not (isPolyFunCoreTy tcm fTy)- isSignal = isSignalType tcm fTy- untranslatable <- isUntranslatableType True fTy- if closed && not untranslatable && not isSignal- then do- bndrs <- Lens.use bindings- case HashMap.lookup f bndrs of- -- Don't inline recursive expressions- Just (_,_,_,_,body) -> do- isRecBndr <- isRecursiveBndr f- if isRecBndr- then return e- else changed body- _ -> return e- else return e--inlineWorkFree _ e = return e---- | Inline small functions-inlineSmall :: NormRewrite-inlineSmall _ e@(collectArgs -> (Var _ (nameOcc -> f),args)) = do- untranslatable <- isUntranslatable True e- topEnts <- Lens.view topEntities- if untranslatable || f `HashSet.member` topEnts- then return e- else do- bndrs <- Lens.use bindings- sizeLimit <- Lens.use (extra.inlineFunctionLimit)- case HashMap.lookup f bndrs of- -- Don't inline recursive expressions- Just (_,_,_,inl,body) -> do- isRecBndr <- isRecursiveBndr f- if not isRecBndr && inl /= NoInline && termSize body < sizeLimit- then changed (mkApps body args)- else return e- _ -> return e--inlineSmall _ e = return e---- | Specialise functions on arguments which are constant, except when they--- are clock or reset generators-constantSpec :: NormRewrite-constantSpec ctx e@(App e1 e2)- | (Var _ _, args) <- collectArgs e1- , (_, []) <- Either.partitionEithers args- , null $ Lens.toListOf termFreeTyVars e2- , isConstant e2- = do tcm <- Lens.view tcCache- e2Ty <- termType tcm e2- -- Don't specialise on clock or reset generators- case isClockOrReset tcm e2Ty of- False -> specializeNorm ctx e- _ -> return e--constantSpec _ e = return e----- Experimental---- | Propagate arguments of application inwards; except for 'Lam' where the--- argument becomes let-bound.-appProp :: NormRewrite-appProp _ (App (Lam b) arg) = do- (v,e) <- unbind b- if isConstant arg || isVar arg- then changed $ substTm (nameOcc (varName v)) arg e- else changed . Letrec $ bind (rec [(v,embed arg)]) e--appProp _ (App (Letrec b) arg) = do- (v,e) <- unbind b- changed . Letrec $ bind v (App e arg)--appProp ctx (App (Case scrut ty alts) arg) = do- tcm <- Lens.view tcCache- argTy <- termType tcm arg- let ty' = applyFunTy tcm ty argTy- if isConstant arg || isVar arg- then do- alts' <- mapM ( return- . uncurry bind- . second (`App` arg)- <=< unbind- ) alts- changed $ Case scrut ty' alts'- else do- (boundArg,argVar) <- mkTmBinderFor tcm (mkDerivedName ctx "app_arg") arg- alts' <- mapM ( return- . uncurry bind- . second (`App` argVar)- <=< unbind- ) alts- changed . Letrec $ bind (rec [(boundArg,embed arg)]) (Case scrut ty' alts')--appProp _ (TyApp (TyLam b) t) = do- (tv,e) <- unbind b- changed $ substTyInTm (nameOcc (varName tv)) t e--appProp _ (TyApp (Letrec b) t) = do- (v,e) <- unbind b- changed . Letrec $ bind v (TyApp e t)--appProp _ (TyApp (Case scrut altsTy alts) ty) = do- alts' <- mapM ( return- . uncurry bind- . second (`TyApp` ty)- <=< unbind- ) alts- tcm <- Lens.view tcCache- ty' <- applyTy tcm altsTy ty- changed $ Case scrut ty' alts'--appProp _ e = return e---- | 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 :: NormRewrite-caseFlat _ e@(Case (collectArgs -> (Prim nm _,args)) ty _)- | isEq nm- = do let (Left scrut') = args !! 1- case collectFlat scrut' e of- Just alts' -> changed (Case scrut' ty (last alts' : init alts'))- Nothing -> return e--caseFlat _ e = return e--collectFlat :: Term -> Term -> Maybe [Bind Pat Term]-collectFlat scrut (Case (collectArgs -> (Prim nm _,args)) _ty [lAlt,rAlt])- | isEq nm- , scrut' == scrut- = case collectArgs val of- (Prim nm' _,args') | isFromInt nm'- -> case last args' of- Left (Literal i) -> case (unsafeUnbind lAlt,unsafeUnbind rAlt) of- ((pl,el),(pr,er))- | isFalseDcPat pl || isTrueDcPat pr ->- case collectFlat scrut el of- Just alts' -> Just (bind (LitPat (embed i)) er : alts')- Nothing -> Just [bind (LitPat (embed i)) er- ,bind DefaultPat el- ]- | otherwise ->- case collectFlat scrut er of- Just alts' -> Just (bind (LitPat (embed i)) el : alts')- Nothing -> Just [bind (LitPat (embed i)) el- ,bind DefaultPat er- ]- _ -> Nothing- _ -> Nothing- where- (Left scrut') = args !! 1- (Left val) = args !! 2-- isFalseDcPat (DataPat p _)- = ((== "GHC.Types.False") . name2String . dcName . unembed) p- isFalseDcPat _ = False-- isTrueDcPat (DataPat p _)- = ((== "GHC.Types.True") . name2String . dcName . unembed) p- isTrueDcPat _ = False--collectFlat _ _ = Nothing--isEq :: Text -> Bool-isEq nm = nm == "Clash.Sized.Internal.BitVector.eq#" ||- nm == "Clash.Sized.Internal.Index.eq#" ||- nm == "Clash.Sized.Internal.Signed.eq#" ||- nm == "Clash.Sized.Internal.Unsigned.eq#"--isFromInt :: Text -> Bool-isFromInt nm = nm == "Clash.Sized.Internal.BitVector.fromInteger##" ||- nm == "Clash.Sized.Internal.BitVector.fromInteger#" ||- nm == "Clash.Sized.Internal.Index.fromInteger#" ||- nm == "Clash.Sized.Internal.Signed.fromInteger#" ||- nm == "Clash.Sized.Internal.Unsigned.fromInteger#"--type NormRewriteW = Transform (WriterT [LetBinding] (RewriteMonad NormalizeState))---- NOTE [unsafeUnbind]: Use unsafeUnbind (which doesn't freshen pattern--- variables). Reason: previously collected expression still reference--- the 'old' variable names created by the traversal!---- | Turn an expression into a modified ANF-form. As opposed to standard ANF,--- constants do not become let-bound.-makeANF :: NormRewrite-makeANF ctx (Lam b) = do- -- See NOTE [unsafeUnbind]- let (bndr,e) = unsafeUnbind b- e' <- makeANF (LamBody bndr:ctx) e- return $ Lam (bind bndr e')--makeANF _ (TyLam b) = return (TyLam b)--makeANF ctx e- = do- (e',bndrs) <- runWriterT $ bottomupR collectANF ctx e- case bndrs of- [] -> return e- _ -> changed . Letrec $ bind (rec bndrs) e'--collectANF :: NormRewriteW-collectANF ctx e@(App appf arg)- | (conVarPrim, _) <- collectArgs e- , isCon conVarPrim || isPrim conVarPrim || isVar conVarPrim- = do- untranslatable <- lift (isUntranslatable False arg)- localVar <- lift (isLocalVar arg)- constantNoCR <- lift (isConstantNotClockReset arg)- case (untranslatable,localVar || constantNoCR,arg) of- (False,False,_) -> do tcm <- Lens.view tcCache- (argId,argVar) <- lift (mkTmBinderFor tcm (mkDerivedName ctx "app_arg") arg)- tell [(argId,embed arg)]- return (App appf argVar)- (True,False,Letrec b) -> do (binds,body) <- unbind b- tell (unrec binds)- return (App appf body)- _ -> return e--collectANF _ (Letrec b) = do- -- See NOTE [unsafeUnbind]- let (binds,body) = unsafeUnbind b- tell (unrec binds)- untranslatable <- lift (isUntranslatable False body)- localVar <- lift (isLocalVar body)- if localVar || untranslatable- then return body- else do- tcm <- Lens.view tcCache- (argId,argVar) <- lift (mkTmBinderFor tcm (string2SystemName "result") body)- tell [(argId,embed body)]- return argVar---- 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 'coreView' to find the "real" data-constructor.--- 'coreView' 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 _ _ [unsafeUnbind -> (DataPat dc _,_)])- | name2String (dcName $ unembed dc) == "Clash.Signal.Internal.:-" = return e--collectANF ctx (Case subj ty alts) = do- localVar <- lift (isLocalVar subj)- (bndr,subj') <- if localVar || isConstant subj- then return ([],subj)- else do tcm <- Lens.view tcCache- (argId,argVar) <- lift (mkTmBinderFor tcm (mkDerivedName ctx "case_scrut") subj)- return ([(argId,embed subj)],argVar)-- (binds,alts') <- fmap (first concat . unzip) $ mapM (lift . doAlt subj') alts-- tell (bndr ++ binds)- case alts' of- [unsafeUnbind -> (DataPat _ (unrebind -> ([],xs)),altExpr)]- | let altFreeIds = Lens.setOf termFreeIds altExpr- , Set.null (Set.intersection (Set.fromList (map (nameOcc.varName) xs)) altFreeIds)- -> return altExpr- _ -> return (Case subj' ty alts')- where- doAlt :: Term -> Bind Pat Term -> RewriteMonad NormalizeState ([LetBinding],Bind Pat Term)- -- See NOTE [unsafeUnbind]- doAlt subj' = fmap (second (uncurry bind)) . doAlt' subj' . unsafeUnbind-- doAlt' :: Term -> (Pat,Term) -> RewriteMonad NormalizeState ([LetBinding],(Pat,Term))- doAlt' subj' alt@(DataPat dc pxs@(unrebind -> ([],xs)),altExpr) = do- lv <- isLocalVar altExpr- patSels <- Monad.zipWithM (doPatBndr subj' (unembed dc)) xs [0..]- let usesXs (Var _ n) = any ((== n) . varName) xs- usesXs _ = False- if (lv && not (usesXs altExpr)) || isConstant altExpr- then return (patSels,alt)- else do tcm <- Lens.view tcCache- (altId,altVar) <- mkTmBinderFor tcm (mkDerivedName ctx "case_alt") altExpr- return ((altId,embed altExpr):patSels,(DataPat dc pxs,altVar))- doAlt' _ alt@(DataPat _ _, _) = return ([],alt)- doAlt' _ alt@(pat,altExpr) = do- lv <- isLocalVar altExpr- if lv || isConstant altExpr- then return ([],alt)- else do tcm <- Lens.view tcCache- (altId,altVar) <- mkTmBinderFor tcm (mkDerivedName ctx "case_alt") altExpr- return ([(altId,embed altExpr)],(pat,altVar))-- doPatBndr :: Term -> DataCon -> Id -> Int -> RewriteMonad NormalizeState LetBinding- doPatBndr subj' dc pId i- = do tcm <- Lens.view tcCache- patExpr <- mkSelectorCase ($(curLoc) ++ "doPatBndr") tcm subj' (dcTag dc) i- return (pId,embed patExpr)--collectANF _ e = return e---- | Eta-expand top-level lambda's (DON'T use in a traversal!)-etaExpansionTL :: NormRewrite-etaExpansionTL ctx (Lam b) = do- (bndr,e) <- unbind b- e' <- etaExpansionTL (LamBody bndr:ctx) e- return $ Lam (bind bndr e')--etaExpansionTL ctx (Letrec b) = do- (xesR,e) <- unbind b- let xes = unrec xesR- bndrs = map fst xes- e' <- etaExpansionTL (LetBody bndrs:ctx) e- e'' <- stripLambda e'- case e'' of- (bs@(_:_),e2) -> do- let e3 = Letrec (bind xesR e2)- changed (mkLams e3 bs)- _ -> return (Letrec (bind xesR e'))- where- stripLambda :: Term -> RewriteMonad NormalizeState ([Id],Term)- stripLambda (Lam b') = do- (bndr,e) <- unbind b'- (bndrs,e') <- stripLambda e- return (bndr:bndrs,e')- stripLambda e = return ([],e)--etaExpansionTL ctx e- = do- tcm <- Lens.view tcCache- isF <- isFun tcm e- if isF- then do- argTy <- ( return- . fst- . Maybe.fromMaybe (error $ $(curLoc) ++ "etaExpansion splitFunTy")- . splitFunTy tcm- <=< termType tcm- ) e- (newIdB,newIdV) <- mkInternalVar (string2InternalName "arg") argTy- e' <- etaExpansionTL (LamBody newIdB:ctx) (App e newIdV)- changed . Lam $ bind newIdB e'- else return e---- | 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 :: NormRewrite-recToLetRec [] e = do- (fn,_) <- Lens.use curFun- bodyM <- fmap (HashMap.lookup (nameOcc fn)) $ Lens.use bindings- tcm <- Lens.view tcCache- normalizedE <- splitNormalized tcm e- case (normalizedE,bodyM) of- (Right (args,bndrs,res), Just (_,bodyTy,_,_,_)) -> do- let v = Var bodyTy fn- args' = map idToVar args- (toInline,others) = List.partition (eqApp tcm v args' . unembed . snd) bndrs- resV = idToVar res- case (toInline,others) of- (_:_,_:_) -> do- let substsInline = map (\(id_,_) -> (nameOcc (varName id_),resV)) toInline- others' = map (second (embed . substTms substsInline . unembed)) others- changed $ mkLams (Letrec $ bind (rec others') resV) args- _ -> return e- _ -> return e- where- -- This checks whether things are semantically equal- --- -- i.e. that- --- -- xs == (fst xs, snd xs)- --- -- TODO: this is far from complete- eqApp tcm v args (collectArgs -> (v',args'))- | v == v'- , let args2 = Either.lefts args'- , length args == length args2- = and (zipWith (eqArg tcm) args args2)- | otherwise- = False-- eqArg _ v1 v2@(Var _ _)- = v1 == v2- eqArg tcm v1 v2@(collectArgs -> (Data _,args'))- | runFreshM (termType tcm v1) == runFreshM (termType tcm v2)- = and (zipWith (isNthProjection v1) [0..] (Either.lefts args'))- eqArg _ _ _- = False-- -- `isNthProjection s n c` checks that `c` is the `n`th projection- -- of `s`.- isNthProjection :: Term -> Int -> Term -> Bool- isNthProjection v n (Case v' altTy [alt])- | v == v'- , (DataPat _ pxs,Var _ s) <- unsafeUnbind alt- , let (_,xs) = unrebind pxs- , Just n' <- List.elemIndex (Id s (embed altTy)) xs- = n == n'- isNthProjection _ _ _ = False--recToLetRec _ e = return e---- | Inline a function with functional arguments-inlineHO :: NormRewrite-inlineHO _ e@(App _ _)- | (Var _ (nameOcc -> f), args) <- collectArgs e- = do- tcm <- Lens.view tcCache- hasPolyFunArgs <- or <$> mapM (either (isPolyFun tcm) (const (return False))) args- if hasPolyFunArgs- then do (nameOcc -> 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 <- fmap (HashMap.lookup f) $ Lens.use bindings- case bodyMaybe of- Just (_,_,_,_,body) -> do- zoomExtra (addNewInline f cf)- changed (mkApps body args)- _ -> return e- else return e--inlineHO _ e = return e---- | Simplified CSE, only works on let-bindings, works from top to bottom-simpleCSE :: NormRewrite-simpleCSE _ e@(Letrec b) = do- (binders,body) <- first unrec <$> unbind b- let (reducedBindings,body') = reduceBindersFix binders body- if length binders /= length reducedBindings- then changed (Letrec (bind (rec reducedBindings) body'))- else return e--simpleCSE _ e = return e--reduceBindersFix :: [LetBinding]- -> Term- -> ([LetBinding],Term)-reduceBindersFix binders body = if length binders /= length reduced- then reduceBindersFix reduced body'- else (binders,body)- where- (reduced,body') = reduceBinders [] body binders--reduceBinders :: [LetBinding]- -> Term- -> [LetBinding]- -> ([LetBinding],Term)-reduceBinders processed body [] = (processed,body)-reduceBinders processed body ((id_,expr):binders) = case List.find ((== expr) . snd) processed of- Just (id2,_) ->- let var = Var (unembed (varType id2)) (varName id2)- idName = nameOcc (varName id_)- processed' = map (second (Embed . (substTm idName var) . unembed)) processed- binders' = map (second (Embed . (substTm idName var) . unembed)) binders- body' = substTm idName var body- in reduceBinders processed' body' binders'- Nothing -> reduceBinders ((id_,expr):processed) body binders--reduceConst :: NormRewrite-reduceConst _ e@(App _ _)- | isConstant e- , (conPrim, _) <- collectArgs e- , isPrim conPrim- = do- tcm <- Lens.view tcCache- bndrs <- Lens.use bindings- primEval <- Lens.view evaluator- ids <- Lens.use uniqSupply- let (ids1,ids2) = splitSupply ids- uniqSupply Lens..= ids2- gh <- Lens.use globalHeap- case whnf' primEval bndrs tcm gh ids1 False e of- (gh',e') -> do- globalHeap Lens..= gh'- case e' of- (Literal _) -> changed e'- (collectArgs -> (Prim nm _, _))- | isFromInt nm- , e /= e'- -> changed e'- (collectArgs -> (Data _,_)) -> changed e'- _ -> return e--reduceConst _ e = return e---- | 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.map--- * Clash.Sized.Vector.zipWith--- * Clash.Sized.Vector.traverse#--- * Clash.Sized.Vector.foldr--- * Clash.Sized.Vector.fold--- * Clash.Sized.Vector.dfold--- * Clash.Sized.Vector.(++)--- * Clash.Sized.Vector.head--- * Clash.Sized.Vector.tail--- * Clash.Sized.Vector.unconcat--- * Clash.Sized.Vector.transpose--- * Clash.Sized.Vector.replicate--- * Clash.Sized.Vector.dtfold-reduceNonRepPrim :: NormRewrite-reduceNonRepPrim _ e@(App _ _) | (Prim f _, args) <- collectArgs e = do- tcm <- Lens.view tcCache- eTy <- termType tcm e- case tyView eTy of- (TyConApp vecTcNm@(name2String -> "Clash.Sized.Vector.Vec")- [runExcept . tyNatSize tcm -> Right 0, aTy]) -> do- let (Just vecTc) = HashMap.lookup (nameOcc vecTcNm) tcm- [nilCon,consCon] = tyConDataCons vecTc- nilE = mkVec nilCon consCon aTy 0 []- changed nilE- tv -> case f of- "Clash.Sized.Vector.zipWith" | length args == 7 -> do- let [lhsElTy,rhsElty,resElTy,nTy] = Either.rights args- case runExcept (tyNatSize tcm nTy) of- Right n -> do- untranslatableTys <- mapM isUntranslatableType_not_poly [lhsElTy,rhsElty,resElTy]- if or untranslatableTys- then let [fun,lhsArg,rhsArg] = Either.lefts args- in reduceZipWith n lhsElTy rhsElty resElTy fun lhsArg rhsArg- else return e- _ -> return e- "Clash.Sized.Vector.map" | length args == 5 -> do- let [argElTy,resElTy,nTy] = Either.rights args- case runExcept (tyNatSize tcm nTy) of- Right n -> do- untranslatableTys <- mapM isUntranslatableType_not_poly [argElTy,resElTy]- if or untranslatableTys- then let [fun,arg] = Either.lefts args- in reduceMap n argElTy resElTy fun arg- else return e- _ -> return e- "Clash.Sized.Vector.traverse#" | length args == 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 reduceTraverse n aTy fTy bTy dict fun arg- _ -> return e- "Clash.Sized.Vector.fold" | length args == 4 -> do- let [aTy,nTy] = Either.rights args- isPow2 x = x /= 0 && (x .&. (complement x + 1)) == x- untranslatableTy <- isUntranslatableType_not_poly aTy- case runExcept (tyNatSize tcm nTy) of- Right n | not (isPow2 (n + 1)) || untranslatableTy ->- let [fun,arg] = Either.lefts args- in reduceFold (n + 1) aTy fun arg- _ -> return e- "Clash.Sized.Vector.foldr" | length args == 6 ->- let [aTy,bTy,nTy] = Either.rights args- in case runExcept (tyNatSize tcm nTy) of- Right n -> do- untranslatableTys <- mapM isUntranslatableType_not_poly [aTy,bTy]- if or untranslatableTys- then let [fun,start,arg] = Either.lefts args- in reduceFoldr n aTy fun start arg- else return e- _ -> return e- "Clash.Sized.Vector.dfold" | length args == 8 ->- let ([_kn,_motive,fun,start,arg],[_mTy,nTy,aTy]) = Either.partitionEithers args- in case runExcept (tyNatSize tcm nTy) of- Right n -> reduceDFold n aTy fun start arg- _ -> return e- "Clash.Sized.Vector.++" | length args == 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- untranslatableTy <- isUntranslatableType_not_poly aTy- if untranslatableTy- then reduceAppend n m aTy lArg rArg- else return e- _ -> return e- "Clash.Sized.Vector.head" | length args == 3 -> do- let [nTy,aTy] = Either.rights args- [vArg] = Either.lefts args- case runExcept (tyNatSize tcm nTy) of- Right n -> do- untranslatableTy <- isUntranslatableType_not_poly aTy- if untranslatableTy- then reduceHead n aTy vArg- else return e- _ -> return e- "Clash.Sized.Vector.tail" | length args == 3 -> do- let [nTy,aTy] = Either.rights args- [vArg] = Either.lefts args- case runExcept (tyNatSize tcm nTy) of- Right n -> do- untranslatableTy <- isUntranslatableType_not_poly aTy- if untranslatableTy- then reduceTail n aTy vArg- else return e- _ -> return e- "Clash.Sized.Vector.last" | length args == 3 -> do- let [nTy,aTy] = Either.rights args- [vArg] = Either.lefts args- case runExcept (tyNatSize tcm nTy) of- Right n -> do- untranslatableTy <- isUntranslatableType_not_poly aTy- if untranslatableTy- then reduceLast n aTy vArg- else return e- _ -> return e- "Clash.Sized.Vector.init" | length args == 3 -> do- let [nTy,aTy] = Either.rights args- [vArg] = Either.lefts args- case runExcept (tyNatSize tcm nTy) of- Right n -> do- untranslatableTy <- isUntranslatableType_not_poly aTy- if untranslatableTy- then reduceInit n aTy vArg- else return e- _ -> return e- "Clash.Sized.Vector.unconcat" | length args == 6 -> do- let ([_knN,_sm,arg],[mTy,nTy,aTy]) = Either.partitionEithers args- case (runExcept (tyNatSize tcm nTy), runExcept (tyNatSize tcm mTy)) of- (Right n, Right 0) -> reduceUnconcat n 0 aTy arg- _ -> return e- "Clash.Sized.Vector.transpose" | length args == 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) -> reduceTranspose n 0 aTy arg- _ -> return e- "Clash.Sized.Vector.replicate" | length args == 4 -> do- let ([_sArg,vArg],[nTy,aTy]) = Either.partitionEithers args- case runExcept (tyNatSize tcm nTy) of- Right n -> do- untranslatableTy <- isUntranslatableType_not_poly aTy- if untranslatableTy- then reduceReplicate n aTy eTy vArg- else return e- _ -> return e- "Clash.Sized.Vector.imap" | length args == 6 -> do- let [nTy,argElTy,resElTy] = Either.rights args- case runExcept (tyNatSize tcm nTy) of- Right n -> do- untranslatableTys <- mapM isUntranslatableType_not_poly [argElTy,resElTy]- if or untranslatableTys- then let [_,fun,arg] = Either.lefts args- in reduceImap n argElTy resElTy fun arg- else return e- _ -> return e- "Clash.Sized.Vector.dtfold" | length args == 8 ->- let ([_kn,_motive,lrFun,brFun,arg],[_mTy,nTy,aTy]) = Either.partitionEithers args- in case runExcept (tyNatSize tcm nTy) of- Right n -> reduceDTFold n aTy lrFun brFun arg- _ -> return e- "Clash.Sized.RTree.tdfold" | length args == 8 ->- let ([_kn,_motive,lrFun,brFun,arg],[_mTy,nTy,aTy]) = Either.partitionEithers args- in case runExcept (tyNatSize tcm nTy) of- Right n -> reduceTFold n aTy lrFun brFun arg- _ -> return e- "Clash.Sized.RTree.treplicate" | length args == 4 -> do- let ([_sArg,vArg],[nTy,aTy]) = Either.partitionEithers args- case runExcept (tyNatSize tcm nTy) of- Right n -> do- untranslatableTy <- isUntranslatableType False aTy- if untranslatableTy- then reduceReplicate n aTy eTy vArg- else return e- _ -> return e- "Clash.Sized.Internal.BitVector.split#" | length args == 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) = HashMap.lookup (nameOcc tupTcNm) tcm- [tupDc] = tyConDataCons tupTc- tup = mkApps (Data tupDc)- [Right lTy- ,Right rTy- ,Left bvArg- ,Left (mkApps (Prim "Clash.Transformations.removedArg" undefinedTy)- [Right rTy])- ]-- changed tup- | m == 0 -> do- let (Just tupTc) = HashMap.lookup (nameOcc tupTcNm) tcm- [tupDc] = tyConDataCons tupTc- tup = mkApps (Data tupDc)- [Right lTy- ,Right rTy- ,Left (mkApps (Prim "Clash.Transformations.removedArg" undefinedTy)- [Right lTy])- ,Left bvArg- ]-- changed tup- _ -> return e- "Clash.Sized.Internal.BitVector.eq#"- | ([_,_],[nTy]) <- Either.partitionEithers args- , Right 0 <- runExcept (tyNatSize tcm nTy)- , TyConApp boolTcNm [] <- tv- -> let (Just boolTc) = HashMap.lookup (nameOcc boolTcNm) tcm- [_falseDc,trueDc] = tyConDataCons boolTc- in changed (Data trueDc)- _ -> 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---- | 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 :: NormRewrite-disjointExpressionConsolidation ctx e@(Case _scrut _ty _alts@(_:_:_)) = do- let eFreeIds = Lens.setOf termFreeIds e- (_,collected) <- collectGlobals eFreeIds [] [] e- let disJoint = filter (isDisjoint . snd. snd) collected- if null disJoint- then return e- else do- exprs <- mapM (mkDisjointGroup eFreeIds) disJoint- tcm <- Lens.view tcCache- (lids,lvs) <- unzip <$> Monad.zipWithM (mkFunOut tcm) disJoint exprs- let substitution = zip (map fst disJoint) lvs- subsMatrix = l2m substitution- (exprs',_) <- unzip <$> Monad.zipWithM (\s (e',seen) -> collectGlobals eFreeIds s seen e')- subsMatrix- exprs- (e',_) <- collectGlobals eFreeIds substitution [] e- let lb = Letrec (bind (rec (zip lids (map embed exprs'))) e')- lb' <- bottomupR deadCode ctx lb- changed lb'- where- mkFunOut tcm (fun,_) (e',_) = do- ty <- termType tcm e'- let nm = case collectArgs fun of- (Var _ nm',_) -> name2String nm'- (Prim nm' _,_) -> unpack nm'- _ -> "complex_expression_"- nm'' = (reverse . List.takeWhile (/='.') . reverse) nm ++ "Out"- mkInternalVar (string2InternalName nm'') ty-- l2m = go []- where- go _ [] = []- go xs (y:ys) = (xs ++ ys) : go (xs ++ [y]) ys--disjointExpressionConsolidation _ e = return e---- | 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-inlineCleanup :: NormRewrite-inlineCleanup _ (Letrec b) = do- prims <- Lens.use (extra.primitives)- let (bindsR,body) = unsafeUnbind b- binds = unrec bindsR- -- 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.- allOccs = List.foldl' (HashMap.unionWith (+)) HashMap.empty- $ map ( List.foldl' countOcc HashMap.empty- . Lens.toListOf termFreeIds . unembed . snd) binds- bodyFVs = Lens.toListOf termFreeIds body- (il,keep) = List.partition (isInteresting allOccs prims bodyFVs) binds- keep' = inlineBndrs keep il- if null il then return (Letrec b)- else changed (Letrec (bind (rec keep') body))- where- -- Count the number of occurrences of a variable- countOcc- :: HashMap.HashMap TmOccName Int- -> TmOccName- -> HashMap.HashMap TmOccName Int- countOcc m nm = HashMap.insertWith (+) nm (1::Int) m-- -- Determine whether a let-binding is interesting to inline- isInteresting- :: HashMap.HashMap TmOccName Int- -> PrimMap a- -> [TmOccName]- -> (Id,Embed Term)- -> Bool- isInteresting allOccs prims bodyFVs (id_,(fst.collectArgs.unembed) -> tm)- | nameSort (varName id_) /= User- , nameOcc (varName id_) `notElem` bodyFVs- = case tm of- Prim nm _- | Just p@(BlackBox {}) <- HashMap.lookup nm prims- , Right _ <- template p- , Just occ <- HashMap.lookup (nameOcc (varName id_)) allOccs- , occ < 2- -> True- Case _ _ [_] -> True- Data _ -> True- _ -> False-- isInteresting _ _ _ _ = False-- -- Inline let-bindings we want to inline into let-bindings we want to keep.- inlineBndrs- :: [(Id, Embed Term)]- -- let-bindings we keep- -> [(Id, Embed Term)]- -- let-bindings we want to inline- -> [(Id, Embed Term)]- inlineBndrs keep [] = keep- inlineBndrs keep (((nameOcc . varName) -> nm,unembed -> tm):il) =- inlineBndrs (map (substBndr nm tm) keep)- (map (substBndr nm tm) il)- -- We must not forget to inline the /current/ @to-inline@ let-binding into- -- the list of /remaining/ @to-inline@ let-bindings, because it might- -- only occur in /remaining/ @to-inline@ bindings. If we don't, we would- -- introduce free variables, because the @to-inline@ bindings are removed.--inlineCleanup _ e = return e---- | 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 :: NormRewrite-flattenLet _ (Letrec b) = do- let (binds,body) = unsafeUnbind b- binds' <- concat <$> mapM go (unrec binds)- case binds' of- -- inline binders into the body when there's only a single binder- [(id',e')] -> do- let fvs = Lens.toListOf termFreeIds (unembed e')- nm = nameOcc (varName id')- if nm `elem` fvs- -- Except when the binder is recursive!- then return (Letrec (bind (rec binds') body))- else changed (substTm nm (unembed e') body)- _ -> return (Letrec (bind (rec binds') body))- where- go :: LetBinding -> NormalizeSession [LetBinding]- go (id_,e) = case unembed e of- Letrec b' -> do- let (binds,body) = unsafeUnbind b'- case unrec binds of- -- inline binders into the body when there's only a single binder- [(id',e')] -> do- let fvs = Lens.toListOf termFreeIds (unembed e')- nm = nameOcc (varName id')- if nm `elem` fvs- -- Except when the binder is recursive!- then changed [(id',e'),(id_,embed body)]- else changed [(id_,embed (substTm nm (unembed e') body))]- bs -> changed (bs ++ [(id_,embed body)])- _ -> return [(id_,e)]+ 2017-2018, Google Inc.+ License : BSD2 (see the file LICENSE)+ Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>++ Transformations of the Normalization process+-}++{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE ViewPatterns #-}++module Clash.Normalize.Transformations+ ( appProp+ , 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+ , flattenLet+ , splitCastWork+ , inlineCast+ , caseCast+ , letCast+ , eliminateCastCast+ , argCastSpec+ , etaExpandSyn+ , appPropFast+ )+where++import Control.Concurrent.Supply (splitSupply)+import Control.Exception (throw)+import Control.Lens (_2)+import qualified Control.Lens as Lens+import qualified Control.Monad as Monad+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.Bits ((.&.), complement)+import Data.Coerce (coerce)+import qualified Data.Either as Either+import qualified Data.HashMap.Lazy as HashMap+import qualified Data.HashMap.Strict as HashMapS+import qualified Data.List 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+import qualified Data.Vector.Primitive as PV+import Debug.Trace (trace)+import GHC.Integer.GMP.Internals (Integer (..), BigNat (..))++import BasicTypes (InlineSpec (..))++import Clash.Annotations.Primitive (extractPrim)+import Clash.Core.DataCon (DataCon (..))+import Clash.Core.Evaluator (PureHeap, whnf')+import Clash.Core.Name+ (Name (..), NameSort (..), mkUnsafeSystemName)+import Clash.Core.FreeVars+ (localIdOccursIn, localIdsDoNotOccurIn, freeLocalIds, termFreeTyVars, typeFreeVars, localVarsDoNotOccurIn)+import Clash.Core.Literal (Literal (..))+import Clash.Core.Pretty (showPpr)+import Clash.Core.Subst+ (substTm, mkSubst, extendIdSubst, extendIdSubstList, extendTvSubst,+ extendTvSubstList, freshenTm, substTyInVar, deShadowTerm)+import Clash.Core.Term+ (LetBinding, Pat (..), Term (..), CoreContext (..), PrimInfo (..), TickInfo,+ isLambdaBodyCtx, isTickCtx, collectArgs, collectArgsTicks, collectTicks,+ partitionTicks)+import Clash.Core.Type (Type, TypeView (..), applyFunTy,+ isPolyFunCoreTy, isClassTy,+ normalizeType, splitFunForallTy,+ splitFunTy,+ tyView)+import Clash.Core.TyCon (TyConMap, tyConDataCons)+import Clash.Core.Util+ (isCon, isFun, isLet, isPolyFun, isPrim,+ isSignalType, isVar, mkApps, mkLams, mkVec, piResultTy, termSize, termType,+ tyNatSize, patVars, isAbsurdAlt, altEqs, substInExistentialsList,+ solveNonAbsurds, patIds, isLocalVar, undefinedTm, stripTicks, mkTicks)+import Clash.Core.Var+ (Id, Var (..), isGlobalId, isLocalId, mkLocalId)+import Clash.Core.VarEnv+ (InScopeSet, VarEnv, VarSet, elemVarSet,+ emptyVarEnv, emptyVarSet, extendInScopeSet, extendInScopeSetList, lookupVarEnv,+ notElemVarSet, unionVarEnvWith, unionVarSet, unionInScope, unitVarEnv,+ unitVarSet, mkVarSet, mkInScopeSet, uniqAway)+import Clash.Driver.Types (DebugLevel (..))+import Clash.Netlist.BlackBox.Util (usedArguments)+import Clash.Netlist.Types (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)+import Clash.Rewrite.Combinators+import Clash.Rewrite.Types+import Clash.Rewrite.Util+import Clash.Unique+ (Unique, lookupUniqMap, toListUniqMap)+import Clash.Util++inlineOrLiftNonRep :: HasCallStack => NormRewrite+inlineOrLiftNonRep = inlineOrLiftBinders nonRepTest inlineTest+ where+ 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) -> RewriteMonad extra Bool+ inlineTest e (id_, e')+ = not . or <$> sequence -- We do __NOT__ inline:+ [ -- 1. recursive let-binders+ pure (id_ `localIdOccursIn` e')+ -- 2. join points (which are not void-wrappers)+ , pure (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.+ , pure (freeOccurances > 1)+ ]+ where+ -- The number of free occurrences of the binder in the entire+ -- let-expression+ freeOccurances :: Int+ freeOccurances = case e of+ Letrec _ res -> do+ Monoid.getSum+ (Lens.foldMapOf freeLocalIds+ (\i -> if i == id_+ then Monoid.Sum 1+ else Monoid.Sum 0)+ res)+ _ -> 0++{- [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++-- | Specialize functions on their non-representable argument+nonRepSpec :: HasCallStack => NormRewrite+nonRepSpec ctx@(TransformContext is0 _) 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 (fNm,_,_,tm)+ | nameSort (varName fNm) == Internal+ -> do+ tm' <- censor (const mempty)+ (bottomupR appProp ctx+ (mkApps (mkTicks tm ticks) fArgs))+ -- See Note [AppProp no-shadow invariant]+ return (deShadowTerm is0 tm')+ _ -> return app+ | otherwise = return app++nonRepSpec _ e = return e++-- | Lift the let-bindings out of the subject of a Case-decomposition+caseLet :: HasCallStack => NormRewrite+caseLet _ (Case (Letrec xes e) ty alts) =+ changed (Letrec xes (Case e ty alts))++caseLet _ e = return e++-- | 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++-- | 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 (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++-- | Move a Case-decomposition from the subject of a Case-decomposition to the alternatives+caseCase :: HasCallStack => NormRewrite+caseCase _ 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+ then let newAlts = map (second (\altE -> Case altE alts2Ty alts2)) alts1+ in changed $ Case scrut alts2Ty newAlts+ else return e++caseCase _ e = return e++-- | Inline function with a non-representable result if it's the subject+-- of a Case-decomposition+inlineNonRep :: HasCallStack => NormRewrite+inlineNonRep (TransformContext localScope _) 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+ noException = not (exception tcm scrutTy)+ if noException && (Maybe.fromMaybe 0 isInlined) > limit+ then do+ traceIf True (concat [$(curLoc) ++ "InlineNonRep: " ++ showPpr (varName f)+ ," already inlined " ++ show limit ++ " times in:"+ , showPpr (varName cf)+ , "\nType of the subject is: " ++ showPpr scrutTy+ , "\nFunction " ++ showPpr (varName cf)+ , " will not reach a normal form, and compilation"+ , " might fail."+ , "\nRun with '-fclash-inline-limit=N' to increase"+ , " the inlining limit to N."+ ])+ (return e)+ else do+ 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 (_,_,_,scrutBody0)) -> do+ Monad.when noException (zoomExtra (addNewInline f cf))+ -- See Note [AppProp no-shadow invariant]+ let scrutBody1 = deShadowTerm localScope scrutBody0+ changed $ Case (mkApps (mkTicks scrutBody1 ticks) args) altsTy alts+ _ -> return e+ where+ exception = isClassTy++inlineNonRep _ e = return e++-- | 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 (TransformContext is0 _) (Case scrut ty alts)+ | (Data dc, args) <- collectArgs scrut+ = case List.find (equalCon dc . fst) alts of+ Just (DataPat _ tvs xs, e) -> do+ let is1 = extendInScopeSetList (extendInScopeSetList is0 tvs) xs+ let fvs = Lens.foldMapOf freeLocalIds unitVarSet e+ (binds,_) = List.partition ((`elemVarSet` fvs) . fst)+ $ zip xs (Either.lefts args)+ e' = case binds of+ [] -> e+ _ ->+ -- See Note [CaseCon deshadow]+ let ((is3,substIds),binds') = List.mapAccumL newBinder+ (is1,[]) binds+ subst = extendIdSubstList (mkSubst is3) substIds+ in Letrec binds' (substTm "caseCon0" subst e)+ let subst = extendTvSubstList (mkSubst is1)+ $ zip tvs (drop (length (dcUnivTyVars dc)) (Either.rights args))+ changed (substTm "caseCon1" subst e')+ _ -> case alts of+ ((DefaultPat,e):_) -> changed e+ _ -> changed (undefinedTm ty)+ where+ equalCon dc (DataPat dc' _ _) = dcTag dc == dcTag dc'+ equalCon _ _ = False++ newBinder (isN0,substN) (x,arg) =+ let x' = uniqAway isN0 x+ isN1 = extendInScopeSet isN0 x'+ in ((isN1,(x,Var x'):substN),(x',arg))++caseCon _ c@(Case (stripTicks -> Literal l) _ alts) = case List.find (equalLit . fst) alts of+ Just (LitPat _,e) -> changed e+ _ -> matchLiteralContructor c l alts+ where+ equalLit (LitPat l') = l == l'+ equalLit _ = False++caseCon ctx@(TransformContext is0 _) e@(Case subj ty alts)+ | (Prim _ _,_) <- collectArgs subj = do+ reprs <- Lens.view customReprs+ tcm <- Lens.view tcCache+ bndrs <- Lens.use bindings+ primEval <- Lens.view evaluator+ ids <- Lens.use uniqSupply+ let (ids1,ids2) = splitSupply ids+ uniqSupply Lens..= ids2+ gh <- Lens.use globalHeap+ lvl <- Lens.view dbgLevel+ case whnf' primEval bndrs tcm gh ids1 is0 True subj of+ (gh',ph',v) -> do+ globalHeap Lens..= gh'+ bindPureHeap ctx tcm ph' $ \ctx' -> case stripTicks v of+ Literal l -> caseCon ctx' (Case (Literal l) ty alts)+ subj' -> case collectArgsTicks subj' of+ (Data _,_,_) -> caseCon ctx' (Case subj' ty alts)+#if MIN_VERSION_ghc(8,2,2)+ (Prim nm ty',_:msgOrCallStack:_,ticks)+ | nm == "Control.Exception.Base.absentError" ->+ let e' = mkApps (mkTicks (Prim nm ty') ticks)+ [Right ty,msgOrCallStack]+ in changed e'+#endif++ (Prim nm ty',repTy:_:msgOrCallStack:_,ticks)+ | nm `elem` ["Control.Exception.Base.patError"+#if !MIN_VERSION_ghc(8,2,2)+ ,"Control.Exception.Base.absentError"+#endif+ ,"GHC.Err.undefined"] ->+ let e' = mkApps (mkTicks (Prim nm ty') ticks)+ [repTy,Right ty,msgOrCallStack]+ in changed e'+ (Prim nm ty',[_],ticks)+ | nm `elem` [ "Clash.Transformations.undefined"+ , "Clash.GHC.Evaluator.undefined"+ , "EmptyCase"] ->+ let e' = mkApps (mkTicks (Prim nm ty') ticks) [Right ty]+ in changed e'+ _ -> do+ let subjTy = termType tcm subj+ tran <- Lens.view typeTranslator+ case (`evalState` HashMapS.empty) (coreTypeToHWType tran reprs tcm subjTy) of+ Right (FilteredHWType (Void (Just hty)) _areVoids)+ | hty `elem` [BitVector 0, Unsigned 0, Signed 0, Index 1]+ -> caseCon ctx' (Case (Literal (IntegerLiteral 0)) ty alts)+ _ -> do+ let ret = caseOneAlt e+ if lvl > DebugNone then do+ let subjIsConst = isConstant subj+ traceIf (lvl > DebugNone && subjIsConst) ("Irreducible constant as case subject: " ++ showPpr subj ++ "\nCan be reduced to: " ++ showPpr subj') ret+ else+ ret++caseCon ctx e@(Case subj ty alts) = do+ reprs <- Lens.view customReprs+ tcm <- Lens.view tcCache+ let subjTy = termType tcm subj+ tran <- Lens.view typeTranslator+ case (`evalState` HashMapS.empty) (coreTypeToHWType tran reprs tcm subjTy) of+ Right (FilteredHWType (Void (Just hty)) _areVoids)+ | hty `elem` [BitVector 0, Unsigned 0, Signed 0, Index 1]+ -> caseCon ctx (Case (Literal (IntegerLiteral 0)) ty alts)+ _ -> caseOneAlt e++caseCon _ e = return e+++-- | Binds variables on the PureHeap over the result of the rewrite+--+-- To prevent unnecessary rewrites only do this when rewrite changed something.+bindPureHeap+ :: TransformContext+ -> TyConMap+ -> PureHeap+ -> (TransformContext -> RewriteMonad extra Term)+ -> RewriteMonad extra Term+bindPureHeap (TransformContext is0 ctxs) tcm heap rw = do+ (e, Monoid.getAny -> hasChanged) <- listen $ rw ctx'+ if hasChanged && not (null bndrs)+ then return $ Letrec bndrs e+ else return e+ where+ bndrs = map toLetBinding $ toListUniqMap heap+ heapIds = map fst bndrs+ is1 = extendInScopeSetList is0 heapIds+ ctx' = TransformContext is1 (LetBody heapIds : ctxs)++ toLetBinding :: (Unique,Term) -> LetBinding+ toLetBinding (uniq,term) = (nm, term)+ where+ ty = termType tcm term+ nm = mkLocalId ty (mkUnsafeSystemName "x" uniq) -- See [Note: Name re-creation]++{- [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)+ $ zip xs [Literal (IntLiteral l)]+ e' = case binds of+ [] -> e+ _ -> Letrec binds e+ in changed e'+ | dcTag dc == 2+ , l >= 2^(63::Int)+ = let !(Jp# !(BN# ba)) = l+ ba' = BA.ByteArray ba+ bv = PV.Vector 0 (BA.sizeofByteArray ba') ba'+ fvs = Lens.foldMapOf freeLocalIds unitVarSet e+ (binds,_) = List.partition ((`elemVarSet` fvs) . fst)+ $ zip xs [Literal (ByteArrayLiteral bv)]+ e' = case binds of+ [] -> e+ _ -> Letrec binds e+ in changed e'+ | dcTag dc == 3+ , l < ((-2)^(63::Int))+ = let !(Jn# !(BN# ba)) = l+ ba' = BA.ByteArray ba+ bv = PV.Vector 0 (BA.sizeofByteArray ba') ba'+ fvs = Lens.foldMapOf freeLocalIds unitVarSet e+ (binds,_) = List.partition ((`elemVarSet` fvs) . fst)+ $ zip xs [Literal (ByteArrayLiteral bv)]+ 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)+ $ zip xs [Literal (WordLiteral l)]+ e' = case binds of+ [] -> e+ _ -> Letrec binds e+ in changed e'+ | dcTag dc == 2+ , l >= 2^(64::Int)+ = let !(Jp# !(BN# ba)) = l+ ba' = BA.ByteArray ba+ bv = PV.Vector 0 (BA.sizeofByteArray ba') ba'+ fvs = Lens.foldMapOf freeLocalIds unitVarSet e+ (binds,_) = List.partition ((`elemVarSet` fvs) . fst)+ $ zip xs [Literal (ByteArrayLiteral bv)]+ 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++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 e = return e++-- | Bring an application of a DataCon or Primitive in ANF, when the argument is+-- is considered non-representable+nonRepANF :: HasCallStack => NormRewrite+nonRepANF ctx 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) -> changed (Letrec binds (App appConPrim body))+ (True,Case {}) -> specializeNorm ctx e+ (True,Lam {}) -> specializeNorm ctx e+ (True,TyLam {}) -> specializeNorm ctx e+ _ -> return e++nonRepANF _ e = return e++-- | 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)+ = 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))++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++-- Misc rewrites++-- | Remove unused let-bindings+deadCode :: HasCallStack => NormRewrite+deadCode _ e@(Letrec xes body) = do+ let bodyFVs = Lens.foldMapOf freeLocalIds unitVarSet body+ (xesUsed,xesOther) = List.partition((`elemVarSet` bodyFVs) . fst) xes+ xesUsed' = findUsedBndrs [] xesUsed xesOther+ if length xesUsed' /= length xes+ then case xesUsed' of+ [] -> changed body+ _ -> changed (Letrec xesUsed' body)+ else return e+ where+ findUsedBndrs :: [(Id, Term)] -> [(Id, Term)]+ -> [(Id, Term)] -> [(Id, Term)]+ findUsedBndrs used [] _ = used+ findUsedBndrs used explore other =+ let fvsUsed = List.foldl' unionVarSet+ emptyVarSet+ (map (Lens.foldMapOf freeLocalIds unitVarSet . snd) explore)+ (explore',other') = List.partition+ ((`elemVarSet` fvsUsed) . fst) other+ in findUsedBndrs (used ++ explore) explore' other'++deadCode _ e = return e++removeUnusedExpr :: HasCallStack => NormRewrite+removeUnusedExpr _ e@(collectArgsTicks -> (p@(Prim nm pInfo),args,ticks)) = do+ bbM <- HashMap.lookup nm <$> Lens.use (extra.primitives)+ case bbM of+ Just (extractPrim -> Just (BlackBox pNm _ _ _ _ _ _ inc templ)) -> do+ let usedArgs | isFromInt pNm+ = [0,1,2]+ | nm `elem` ["Clash.Annotations.BitRepresentation.Deriving.dontApplyInHDL"+ ]+ = [0,1]+ | otherwise+ = usedArguments templ ++ concatMap (usedArguments . snd) inc+ tcm <- Lens.view tcCache+ args' <- go tcm 0 usedArgs args+ if args == args'+ then return e+ else changed (mkApps (mkTicks p ticks) args')+ _ -> 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'+ let ty = termType tcm tm+ p' = removedTm ty+ if n < arity && n `notElem` used+ then return (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++-- | 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 _ (_,stripTicks -> e) = case isLocalVar e of+ True -> return True+ _ -> isConstantNotClockReset e >>= \case+ True -> Lens.use (extra.inlineConstantLimit) >>= \case+ 0 -> return True+ n -> return (termSize e <= n)+ _ -> return False+ -- test _ _ = return False++-- | 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++-- | 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+++-- | Push cast over an argument to a funtion 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')+-- @+argCastSpec :: HasCallStack => NormRewrite+argCastSpec ctx e@(App _ (stripTicks -> Cast e' _ _)) = case e' of+ Var {} -> go+ Cast (Var {}) _ _ -> go+ _ -> warn go+ where+ go = specializeNorm ctx e+ warn = trace (unlines ["WARNING: " ++ $(curLoc) ++ "specializing a function on a possibly non work-free cast."+ ,"Generated HDL implementation might contain duplicate work."+ ,"Please report this as a bug."+ ,""+ ,"Expression where this occurs:"+ ,showPpr e+ ])+argCastSpec _ e = return e++-- | 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++-- | 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++-- | 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+++-- | Inline work-free functions, i.e. fully applied functions that evaluate to+-- a constant+inlineWorkFree :: HasCallStack => NormRewrite+inlineWorkFree (TransformContext localScope _) 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+ let isSignal = isSignalType tcm eTy+ let lv = isLocalId f+ if untranslatable || isSignal || argsHaveWork || lv+ then return e+ else do+ bndrs <- Lens.use bindings+ case lookupVarEnv f bndrs of+ -- Don't inline recursive expressions+ Just (_,_,_,body) -> do+ isRecBndr <- isRecursiveBndr f+ if isRecBndr+ then return e+ else do+ -- See Note [AppProp no-shadow invariant]+ changed (mkApps (mkTicks (deShadowTerm localScope body) ticks) 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 (TransformContext localScope _) 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+ let gv = isGlobalId f+ if closed && 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+ (_,_,_,body) <- normalizeTopLvlBndr f top+ -- See Note [AppProp no-shadow invariant]+ changed (deShadowTerm localScope body)+ _ -> return e+ else return e++inlineWorkFree _ e = return e++-- | Inline small functions+inlineSmall :: HasCallStack => NormRewrite+inlineSmall (TransformContext localScope _) 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 (_,_,inl,body) -> do+ isRecBndr <- isRecursiveBndr f+ if not isRecBndr && inl /= NoInline && termSize body < sizeLimit+ then do+ -- See Note [AppProp no-shadow invariant]+ changed (mkApps (mkTicks (deShadowTerm localScope body) ticks) args)+ else return e+ _ -> return e++inlineSmall _ e = return e++-- | Specialise functions on arguments which are constant, except when they+-- are clock, reset generators.+constantSpec :: HasCallStack => NormRewrite+constantSpec ctx e@(App e1 e2)+ | (Var {}, args) <- collectArgs e1+ , (_, []) <- Either.partitionEithers args+ , null $ Lens.toListOf termFreeTyVars e2+ = do e2Speccable <- canConstantSpec e2+ if e2Speccable then specializeNorm ctx e else return e+constantSpec _ e = return e+++-- Experimental++-- | Propagate arguments of application inwards; except for 'Lam' where the+-- argument becomes let-bound.+--+-- Note [AppProp deshadow]+--+-- 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 rewrite to:+--+-- @+-- let b1 = f x y+-- in case x of+-- D a b -> h a b1+-- @+--+-- Note [AppProp no-shadow invariant]+--+-- 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@. 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 can either:+--+-- 1. Rename the bindings, so that they cannot capture+-- 2. Ensure that @AppProp@ is only called in a context where there is no+-- shadowing, i.e. the bindings can never never collide with the current+-- inScopeSet.+--+-- We have gone for option 2 so that AppProp requires less computation and+-- because AppProp is such a commonly applied transformation. This+-- means that when normalisation starts we deshadow the expression, and when+-- we inline global binders, we ensure that inlined expression is deshadowed+-- taking the InScopeSet of the context into account.+appProp :: HasCallStack => NormRewrite+appProp (TransformContext is0 _) (App (collectTicks -> (Lam v e,ticks)) arg) =+ if isWorkFree arg || isVar arg+ then do+ let subst = extendIdSubst (mkSubst is0) v arg+ changed $ mkTicks (substTm "appProp.AppLam" subst e) ticks+ else changed $ Letrec [(v, arg)] (mkTicks e ticks)++appProp _ (App (collectTicks -> (Letrec v e, ticks)) arg) = do+ changed (Letrec v (App (mkTicks e ticks) arg))++appProp ctx@(TransformContext is0 _) (App (collectTicks -> (Case scrut ty alts,ticks)) arg) = do+ tcm <- Lens.view tcCache+ let argTy = termType tcm arg+ ty' = applyFunTy tcm ty argTy+ if isWorkFree arg || isVar arg+ then do+ let alts' = map (second (`App` arg)) alts+ changed $ mkTicks (Case scrut ty' alts') ticks+ else do+ -- See Note [AppProp deshadow]+ let is2 = unionInScope is0 ((mkInScopeSet . mkVarSet . concatMap (patVars . fst)) alts)+ boundArg <- mkTmBinderFor is2 tcm (mkDerivedName ctx "app_arg") arg+ let alts' = map (second (`App` (Var boundArg))) alts+ changed (Letrec [(boundArg, arg)] (mkTicks (Case scrut ty' alts') ticks))++appProp (TransformContext is0 _) (TyApp (collectTicks -> (TyLam tv e,ticks)) t) = do+ let subst = extendTvSubst (mkSubst is0) tv t+ changed $ mkTicks (substTm "appProp.TyAppTyLam" subst e) ticks++appProp _ (TyApp (collectTicks -> (Letrec v e,ticks)) t) = do+ changed (Letrec v (mkTicks (TyApp e t) ticks))++appProp _ (TyApp (collectTicks -> (Case scrut altsTy alts,ticks)) ty) = do+ let alts' = map (second (`TyApp` ty)) alts+ tcm <- Lens.view tcCache+ let ty' = piResultTy tcm altsTy ty+ changed (mkTicks (Case scrut ty' alts') ticks)++appProp _ e = return e++-- | Unlike 'appProp', which propagates a single argument in an application one+-- level down (and should be called in an innermost traversal), '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.+--+-- Implementation only works if terms are fully deshadowed, see+-- Note [AppProp deshadow]+appPropFast :: HasCallStack => NormRewrite+appPropFast ctx@(TransformContext is _) = \case+ e@App {} -> uncurry3 (go is) (collectArgsTicks e)+ e@TyApp {} -> uncurry3 (go is) (collectArgsTicks 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+ if isWorkFree arg || isVar arg+ then do+ let subst = extendIdSubst (mkSubst is0) v arg+ (`mkTicks` ticks) <$> go is0 (substTm "appPropFast.AppLam" subst e) args []+ else do+ let is1 = extendInScopeSet is0 v+ Letrec [(v, arg)] <$> go is1 e args ticks++ go is0 (Letrec vs e) args@(_:_) ticks = do+ setChanged+ let vbs = map fst vs+ is1 = extendInScopeSetList is0 vbs+ 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+ Letrec vs . (`mkTicks` ticks) . Case scrut ty1 <$> mapM (goAlt is1 args1) alts++ 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+ let argTy = termType tcm arg+ ty1 = applyFunTy tcm ty0 argTy+ case isWorkFree arg || isVar arg of+ 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,[])++-- | 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++collectFlat :: Term -> Term -> Maybe [(Pat,Term)]+collectFlat scrut (Case (collectEqArgs -> Just (scrut', val)) _ty [lAlt,rAlt])+ | scrut' == scrut+ = case collectArgs val of+ (Prim nm' _,args') | isFromInt nm' ->+ 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++collectEqArgs :: Term -> Maybe (Term,Term)+collectEqArgs (collectArgsTicks -> (Prim nm _, 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)+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)))++-- | 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,_)) <- runStateT (bottomupR collectANF ctx e1) ([],is2)+ case bndrs of+ [] -> 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)++-- | 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.+collectANF :: HasCallStack => NormRewriteW+collectANF ctx e@(App appf arg)+ | (conVarPrim, _) <- collectArgs e+ , isCon conVarPrim || isPrim conVarPrim || isVar conVarPrim+ = do+ untranslatable <- lift (isUntranslatable False arg)+ let localVar = isLocalVar arg+ constantNoCR <- lift (isConstantNotClockReset arg)+ case (untranslatable,localVar || constantNoCR,arg) of+ (False,False,_) -> do+ tcm <- Lens.view tcCache+ -- 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++collectANF _ (Letrec binds body) = do+ tellBinders binds+ untranslatable <- lift (isUntranslatable False body)+ let localVar = isLocalVar body+ if localVar || untranslatable+ then return body+ else do+ tcm <- Lens.view tcCache+ -- See Note [ANF InScopeSet]+ is1 <- Lens.use _2+ argId <- lift (mkTmBinderFor is1 tcm (mkUnsafeSystemName "result" 0) body)+ -- See Note [ANF InScopeSet]+ tellBinders [(argId,body)]+ 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' <- 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]+ tellBinders [(argId,subj)]+ return (Var argId)++ alts' <- mapM (doAlt subj') alts++ case alts' of+ [(DataPat _ [] xs,altExpr)]+ | xs `localIdsDoNotOccurIn` altExpr+ -> return altExpr+ _ -> return (Case subj' ty alts')+ where+ doAlt+ :: Term -> (Pat,Term)+ -> StateT ([LetBinding],InScopeSet) (RewriteMonad NormalizeState)+ (Pat,Term)+ doAlt 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+ if (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 ((altId,altExpr):patSels)+ return (DataPat dc exts xs,Var altId)+ doAlt _ alt@(DataPat {}, _) = return alt+ doAlt _ alt@(pat,altExpr) = do+ let lv = isLocalVar altExpr+ let altExprIsConstant = isConstant altExpr+ if 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++-- | 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++-- | 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++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 -> (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 = termType tcm v1+ , let t2 = 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 -> (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 <- headMaybe fTrace1+ vTarget1 <- indexMaybe xs n+ fTrace2 <- tailMaybe fTrace1++ 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++-- | Inline a function with functional arguments+inlineHO :: HasCallStack => NormRewrite+inlineHO (TransformContext is0 _) 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 (_,_,_,body) -> do+ zoomExtra (addNewInline f cf)+ -- See Note [AppProp no-shadow invariant]+ changed (mkApps (mkTicks (deShadowTerm is0 body) ticks) args)+ _ -> return e+ else return e++inlineHO _ e = return e++-- | Simplified CSE, only works on let-bindings, works from top to bottom+simpleCSE :: HasCallStack => NormRewrite+simpleCSE (TransformContext is0 _) e@(Letrec binders body) = do+ let is1 = extendInScopeSetList is0 (map fst binders)+ let (reducedBindings,body') = reduceBindersFix is1 binders body+ if length binders /= length reducedBindings+ then changed (Letrec reducedBindings body')+ else return e++simpleCSE _ e = return e++reduceBindersFix+ :: InScopeSet+ -> [LetBinding]+ -> Term+ -> ([LetBinding],Term)+reduceBindersFix is binders body =+ if length binders /= length reduced+ then reduceBindersFix is reduced body'+ else (binders,body)+ where+ (reduced,body') = reduceBinders is [] body binders++reduceBinders+ :: InScopeSet+ -> [LetBinding]+ -> Term+ -> [LetBinding]+ -> ([LetBinding],Term)+reduceBinders _ processed body [] = (processed,body)+reduceBinders is processed body ((id_,expr):binders) = case List.find ((== expr) . snd) processed of+ Just (id2,_) ->+ let subst = extendIdSubst (mkSubst is) id_ (Var id2)+ processed' = map (second (substTm "reduceBinders.processed" subst)) processed+ binders' = map (second (substTm "reduceBinders.binders" subst)) binders+ body' = substTm "reduceBinders.body" subst body+ in reduceBinders is processed' body' binders'+ Nothing -> reduceBinders is ((id_,expr):processed) body binders++reduceConst :: HasCallStack => NormRewrite+reduceConst ctx@(TransformContext is0 _) e@(App _ _)+ | (Prim nm0 _, _) <- collectArgs e+ = do+ tcm <- Lens.view tcCache+ bndrs <- Lens.use bindings+ primEval <- Lens.view evaluator+ ids <- Lens.use uniqSupply+ let (ids1,ids2) = splitSupply ids+ uniqSupply Lens..= ids2+ gh <- Lens.use globalHeap+ case whnf' primEval bndrs tcm gh ids1 is0 False e of+ (gh',ph',e') -> do+ globalHeap Lens..= gh'+ bindPureHeap ctx tcm ph' $ \_ctx' -> case e' of+ (collectArgs -> (Prim nm1 _, _)) | nm0 == nm1 -> return e+ _ -> changed e'++reduceConst _ e = return e++-- | 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#+reduceNonRepPrim :: HasCallStack => NormRewrite+reduceNonRepPrim c@(TransformContext is0 ctx) e@(App _ _) | (Prim nm _, args, ticks) <- collectArgsTicks e = do+ tcm <- Lens.view tcCache+ shouldReduce1 <- shouldReduce ctx+ 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 -> case nm of+ "Clash.Sized.Vector.zipWith" | length args == 7 -> do+ let [lhsElTy,rhsElty,resElTy,nTy] = Either.rights args+ case runExcept (tyNatSize tcm nTy) of+ Right n -> do+ untranslatableTys <- mapM isUntranslatableType_not_poly [lhsElTy,rhsElty,resElTy]+ if or untranslatableTys || shouldReduce1 || ultra || n < 2+ then let [fun,lhsArg,rhsArg] = Either.lefts args+ in (`mkTicks` ticks) <$>+ reduceZipWith c n lhsElTy rhsElty resElTy fun lhsArg rhsArg+ else return e+ _ -> return e+ "Clash.Sized.Vector.map" | length args == 5 -> do+ let [argElTy,resElTy,nTy] = Either.rights args+ case runExcept (tyNatSize tcm nTy) of+ Right n -> do+ untranslatableTys <- mapM isUntranslatableType_not_poly [argElTy,resElTy]+ if or untranslatableTys || shouldReduce1 || ultra || n < 2+ then let [fun,arg] = Either.lefts args+ in (`mkTicks` ticks) <$> reduceMap c n argElTy resElTy fun arg+ else return e+ _ -> return e+ "Clash.Sized.Vector.traverse#" | length args == 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" | length args == 4 -> do+ let [aTy,nTy] = Either.rights args+ isPow2 x = x /= 0 && (x .&. (complement x + 1)) == x+ untranslatableTy <- isUntranslatableType_not_poly aTy+ case runExcept (tyNatSize tcm nTy) of+ Right n | not (isPow2 (n + 1)) || untranslatableTy || shouldReduce1 || ultra || n == 0 ->+ let [fun,arg] = Either.lefts args+ in (`mkTicks` ticks) <$> reduceFold c (n + 1) aTy fun arg+ _ -> return e+ "Clash.Sized.Vector.foldr" | length args == 6 ->+ let [aTy,bTy,nTy] = Either.rights args+ in case runExcept (tyNatSize tcm nTy) of+ Right n -> do+ untranslatableTys <- mapM isUntranslatableType_not_poly [aTy,bTy]+ if or untranslatableTys || shouldReduce1 || ultra+ then let [fun,start,arg] = Either.lefts args+ in (`mkTicks` ticks) <$> reduceFoldr c n aTy fun start arg+ else return e+ _ -> return e+ "Clash.Sized.Vector.dfold" | length args == 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.++" | length args == 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+ untranslatableTy <- isUntranslatableType_not_poly aTy+ if untranslatableTy || shouldReduce1+ then (`mkTicks` ticks) <$> reduceAppend is0 n m aTy lArg rArg+ else return e+ _ -> return e+ "Clash.Sized.Vector.head" | length args == 3 -> do+ let [nTy,aTy] = Either.rights args+ [vArg] = Either.lefts args+ case runExcept (tyNatSize tcm nTy) of+ Right n -> do+ untranslatableTy <- isUntranslatableType_not_poly aTy+ if untranslatableTy || shouldReduce1+ then (`mkTicks` ticks) <$> reduceHead is0 (n+1) aTy vArg+ else return e+ _ -> return e+ "Clash.Sized.Vector.tail" | length args == 3 -> do+ let [nTy,aTy] = Either.rights args+ [vArg] = Either.lefts args+ case runExcept (tyNatSize tcm nTy) of+ Right n -> do+ untranslatableTy <- isUntranslatableType_not_poly aTy+ if untranslatableTy || shouldReduce1+ then (`mkTicks` ticks) <$> reduceTail is0 (n+1) aTy vArg+ else return e+ _ -> return e+ "Clash.Sized.Vector.last" | length args == 3 -> do+ let [nTy,aTy] = Either.rights args+ [vArg] = Either.lefts args+ case runExcept (tyNatSize tcm nTy) of+ Right n -> do+ untranslatableTy <- isUntranslatableType_not_poly aTy+ if untranslatableTy || shouldReduce1+ then (`mkTicks` ticks) <$> reduceLast is0 (n+1) aTy vArg+ else return e+ _ -> return e+ "Clash.Sized.Vector.init" | length args == 3 -> do+ let [nTy,aTy] = Either.rights args+ [vArg] = Either.lefts args+ case runExcept (tyNatSize tcm nTy) of+ Right n -> do+ untranslatableTy <- isUntranslatableType_not_poly aTy+ if untranslatableTy || shouldReduce1+ then (`mkTicks` ticks) <$> reduceInit is0 (n+1) aTy vArg+ else return e+ _ -> return e+ "Clash.Sized.Vector.unconcat" | length args == 6 -> do+ let ([_knN,_sm,arg],[mTy,nTy,aTy]) = Either.partitionEithers args+ case (runExcept (tyNatSize tcm nTy), runExcept (tyNatSize tcm mTy)) of+ (Right n, Right 0) -> (`mkTicks` ticks) <$> reduceUnconcat n 0 aTy arg+ _ -> return e+ "Clash.Sized.Vector.transpose" | length args == 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" | length args == 4 -> do+ let ([_sArg,vArg],[nTy,aTy]) = Either.partitionEithers args+ case runExcept (tyNatSize tcm nTy) of+ Right n -> do+ untranslatableTy <- isUntranslatableType_not_poly aTy+ if untranslatableTy || 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" | length args == 6 -> do+ let ([_knArg,vArg,iArg,aArg],[nTy,aTy]) = Either.partitionEithers args+ case runExcept (tyNatSize tcm nTy) of+ Right n -> do+ untranslatableTy <- isUntranslatableType_not_poly aTy+ if untranslatableTy || shouldReduce1 || ultra+ then (`mkTicks` ticks) <$> reduceReplace_int is0 n aTy eTy vArg iArg aArg+ else return e+ _ -> return e++ "Clash.Sized.Vector.index_int" | length args == 5 -> do+ let ([_knArg,vArg,iArg],[nTy,aTy]) = Either.partitionEithers args+ case runExcept (tyNatSize tcm nTy) of+ Right n -> do+ untranslatableTy <- isUntranslatableType_not_poly aTy+ if untranslatableTy || shouldReduce1 || ultra+ then (`mkTicks` ticks) <$> reduceIndex_int is0 n aTy vArg iArg+ else return e+ _ -> return e++ "Clash.Sized.Vector.imap" | length args == 6 -> do+ let [nTy,argElTy,resElTy] = Either.rights args+ case runExcept (tyNatSize tcm nTy) of+ Right n -> do+ untranslatableTys <- mapM isUntranslatableType_not_poly [argElTy,resElTy]+ if or untranslatableTys || shouldReduce1 || ultra || n < 2+ 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.dtfold" | length args == 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" | length args == 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" | length args == 4 -> do+ let ([_sArg,vArg],[nTy,aTy]) = Either.partitionEithers args+ case runExcept (tyNatSize tcm nTy) of+ Right n -> do+ untranslatableTy <- isUntranslatableType False aTy+ if untranslatableTy || shouldReduce1+ then (`mkTicks` ticks) <$> reduceTReplicate n aTy eTy vArg+ else return e+ _ -> return e+ "Clash.Sized.Internal.BitVector.split#" | length args == 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++-- | 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 is0 _) e@(Case _scrut _ty _alts@(_:_:_)) = do+ (_,collected) <- collectGlobals is0 [] [] e+ let disJoint = filter (isDisjoint . snd . snd) collected+ if null disJoint+ then return e+ else do+ exprs <- mapM (mkDisjointGroup is0) disJoint+ tcm <- Lens.view tcCache+ lids <- Monad.zipWithM (mkFunOut is0 tcm) disJoint exprs+ let substitution = zip (map fst disJoint) (map Var lids)+ subsMatrix = l2m substitution+ (exprs',_) <- unzip <$> Monad.zipWithM+ (\s (e',seen) -> collectGlobals is0 s seen e')+ subsMatrix+ exprs+ (e',_) <- collectGlobals is0 substitution [] e+ let lb = Letrec (zip lids exprs') e'+ lb' <- bottomupR deadCode ctx lb+ changed lb'+ where+ mkFunOut isN tcm (fun,_) (e',_) = do+ let ty = termType tcm e'+ nm = case collectArgs fun of+ (Var v,_) -> nameOcc (varName v)+ (Prim nm' _,_) -> nm'+ _ -> "complex_expression_"+ nm'' = last (Text.splitOn "." nm) `Text.append` "Out"+ mkInternalVar isN nm'' ty++ l2m = go []+ where+ go _ [] = []+ go xs (y:ys) = (xs ++ ys) : go (xs ++ [y]) ys++disjointExpressionConsolidation _ e = return e++-- | 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+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 allOccs = List.foldl' (HashMap.unionWith (+)) HashMap.empty+ -- $ map ( List.foldl' countOcc HashMap.empty+ -- . Lens.toListOf termFreeIds . unembed . snd) binds+ let is1 = extendInScopeSetList is0 (map fst binds)+ let allOccs = List.foldl' (unionVarEnvWith (+)) emptyVarEnv+ $ map (Lens.foldMapByOf freeLocalIds (unionVarEnvWith (+))+ emptyVarEnv (`unitVarEnv` 1) . snd)+ binds+ bodyFVs = Lens.foldMapOf freeLocalIds unitVarSet body+ (il,keep) = List.partition (isInteresting allOccs prims bodyFVs) binds+ keep' = inlineBndrs is1 keep il+ if null il then return (Letrec binds body)+ else changed (Letrec keep' body)+ where+ -- Determine whether a let-binding is interesting to inline+ isInteresting+ :: VarEnv Int+ -> CompiledPrimMap+ -> VarSet+ -> (Id, Term)+ -> Bool+ isInteresting allOccs prims bodyFVs (id_,(fst.collectArgs) -> tm)+ | nameSort (varName id_) /= User+ , id_ `notElemVarSet` bodyFVs+ = case tm of+ Prim nm _+ | Just (extractPrim -> Just p@(BlackBox {})) <- HashMap.lookup nm prims+ , TExpr <- kind p+ , Just occ <- lookupVarEnv id_ allOccs+ , occ < 2+ -> True+ Case _ _ [_] -> True+ Data _ -> True+ _ -> False+ | id_ `notElemVarSet` bodyFVs+ = case tm of+ 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+ _ -> False++ isInteresting _ _ _ _ = False++ -- Inline let-bindings we want to inline into let-bindings we want to keep.+ inlineBndrs+ :: InScopeSet+ -> [(Id, Term)]+ -- let-bindings we keep+ -> [(Id, Term)]+ -- let-bindings we want to inline+ -> [(Id, Term)]+ inlineBndrs _ keep [] = keep+ inlineBndrs isN keep ((v,e):il) =+ let subst = extendIdSubst (mkSubst isN) v e+ in if v `localIdOccursIn` e -- don't inline recursive binders+ then inlineBndrs isN ((v,e):keep) il+ else inlineBndrs isN+ (map (second (substTm "inlineCleanup.inlineBndrs" subst)) keep)+ (map (second (substTm "inlineCleanup.inlineBndrs" subst)) il)+ -- We must not forget to inline the /current/ @to-inline@ let-binding into+ -- the list of /remaining/ @to-inline@ let-bindings, because it might+ -- only occur in /remaining/ @to-inline@ bindings. If we don't, we would+ -- introduce free variables, because the @to-inline@ bindings are removed.++inlineCleanup _ e = return e++-- | 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@(Letrec _ _) = do+ let (is2, Letrec binds body) = freshenTm is0 letrec+ bodyOccs = Lens.foldMapByOf+ freeLocalIds (unionVarEnvWith (+))+ emptyVarEnv (`unitVarEnv` (1 :: Int))+ body+ binds' <- concat <$> mapM (go is2) binds+ case binds' 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+ [(id',e')] | Just occ <- lookupVarEnv id' bodyOccs, isWorkFree e' || occ < 2 ->+ if id' `localIdOccursIn` e'+ -- Except when the binder is recursive!+ then return (Letrec binds' body)+ else let subst = extendIdSubst (mkSubst is2) id' e'+ in changed (substTm "flattenLet" subst body)+ _ -> return (Letrec binds' body)+ where+ go :: InScopeSet -> LetBinding -> NormalizeSession [LetBinding]+ go isN (id_,collectTicks -> (Letrec binds' body',ticks)) = do+ let bodyOccs = Lens.foldMapByOf+ freeLocalIds (unionVarEnvWith (+))+ emptyVarEnv (`unitVarEnv` (1 :: Int))+ body'+ (srcTicks,nmTicks) = partitionTicks ticks+ -- Distribute the name ticks of the let-expression over all the bindings+ map (second (`mkTicks` nmTicks)) <$> case binds' 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+ [(id',e')] | Just occ <- lookupVarEnv id' bodyOccs, isWorkFree e' || occ < 2 ->+ if id' `localIdOccursIn` e'+ -- Except when the binder is recursive!+ then changed [(id',e'),(id_, body')]+ else let subst = extendIdSubst (mkSubst isN) id' e'+ in changed [(id_+ -- Only apply srcTicks to the body+ ,mkTicks (substTm "flattenLetGo" subst body')+ srcTicks)]+ bs -> changed (bs ++ [(id_+ -- Only apply srcTicks to the body+ ,mkTicks body' srcTicks)])+ go _ b = return [b] flattenLet _ e = return e
src/Clash/Normalize/Types.hs view
@@ -7,19 +7,21 @@ Types used in Normalize modules -} -{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TemplateHaskell #-} module Clash.Normalize.Types where import Control.Monad.State.Strict (State)-import Data.HashMap.Strict (HashMap)-import Data.Map (Map)+import Data.Map (Map)+import Data.Set (Set)+import Data.Text (Text) -import Clash.Core.Term (Term, TmName, TmOccName)+import Clash.Core.Term (Term) import Clash.Core.Type (Type)+import Clash.Core.Var (Id)+import Clash.Core.VarEnv (VarEnv) import Clash.Driver.Types (BindingMap)-import Clash.Netlist.BlackBox.Types (BlackBoxTemplate)-import Clash.Primitives.Types (PrimMap)+import Clash.Primitives.Types (CompiledPrimMap) import Clash.Rewrite.Types (Rewrite, RewriteMonad) import Clash.Util @@ -28,17 +30,17 @@ = NormalizeState { _normalized :: BindingMap -- ^ Global binders- , _specialisationCache :: Map (TmOccName,Int,Either Term Type) (TmName,Type)- -- ^ Cache of previously specialised functions:+ , _specialisationCache :: Map (Id,Int,Either Term Type) Id+ -- ^ Cache of previously specialized functions: --- -- * Key: (name of the original function, argument position, specialised term/type)+ -- * Key: (name of the original function, argument position, specialized term/type) --- -- * Elem: (name of specialised function,type of specialised function)- , _specialisationHistory :: HashMap TmOccName Int+ -- * 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 :: HashMap TmOccName (HashMap TmOccName Int)+ , _inlineHistory :: VarEnv (VarEnv Int) -- ^ Cache of function where inlining took place: -- -- * Key: function where inlining took place@@ -51,15 +53,25 @@ -- recursive , _inlineConstantLimit :: !Word -- ^ Size of a constant below which it is always inlined; 0 = no limit- , _primitives :: PrimMap BlackBoxTemplate -- ^ Primitive Definitions- , _recursiveComponents :: HashMap TmOccName Bool+ , _primitives :: CompiledPrimMap+ -- ^ Primitive Definitions+ , _primitiveArgs :: Map Text (Set Int)+ -- ^ Cache for looking up constantness of blackbox arguments+ , _recursiveComponents :: VarEnv Bool -- ^ Map telling whether a components is recursively defined. -- -- 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. } makeLenses ''NormalizeState+ -- | State monad that stores specialisation and inlining information type NormalizeMonad = State NormalizeState
src/Clash/Normalize/Util.hs view
@@ -6,124 +6,220 @@ Utility functions used by the normalisation transformations -} -{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ViewPatterns #-} -module Clash.Normalize.Util where+module Clash.Normalize.Util+ ( isConstantArg+ , shouldReduce+ , alreadyInlined+ , addNewInline+ , specializeNorm+ , isRecursiveBndr+ , isClosed+ , callGraph+ , classifyFunction+ , isCheapFunction+ , isNonRecursiveGlobalVar+ , canConstantSpec+ , normalizeTopLvlBndr+ , rewriteExpr+ , removedTm+ )+ where -import Control.Lens ((&),(+~),(%=),(^.),_5)+import Control.Lens ((&),(+~),(%=),(^.),_4,(.=)) import qualified Control.Lens as Lens-import Data.HashMap.Lazy (HashMap)-import qualified Data.HashMap.Lazy as HashMap import qualified Data.List as List-import Unbound.Generics.LocallyNameless (Fresh, unembed ,unrec)-import Unbound.Generics.LocallyNameless.Unsafe (unsafeUnbind)+import qualified Data.Map as Map+import qualified Data.HashMap.Strict as HashMapS+import Data.Text (Text) -import Clash.Core.FreeVars (termFreeIds)-import Clash.Core.Term (Term (..), TmOccName)-import Clash.Core.TyCon (TyCon, TyConOccName)-import Clash.Core.Util- (collectArgs, isClockOrReset, isPolyFun, termType)-import Clash.Driver.Types (BindingMap)+import BasicTypes (InlineSpec)++import Clash.Annotations.Primitive (extractPrim)+import Clash.Core.FreeVars+ (globalIds, hasLocalFreeVars, globalIdOccursIn)+import Clash.Core.Pretty (showPpr)+import Clash.Core.Subst (deShadowTerm)+import Clash.Core.Term+ (Context, CoreContext(AppArg), PrimInfo (..), Term (..), WorkInfo (..),+ collectArgs)+import Clash.Core.TyCon (TyConMap)+import Clash.Core.Type (Type, undefinedTy)+import Clash.Core.Util (isClockOrReset, isPolyFun, termType)+import Clash.Core.Var (Id, Var (..), isGlobalId)+import Clash.Core.VarEnv+ (VarEnv, emptyInScopeSet, emptyVarEnv, extendVarEnv, extendVarEnvWith,+ lookupVarEnv, unionVarEnvWith, unitVarEnv)+import Clash.Driver.Types (BindingMap, DebugLevel (..))+import {-# SOURCE #-} Clash.Normalize.Strategy (normalization) import Clash.Normalize.Types-import Clash.Rewrite.Types (bindings,extra,tcCache)-import Clash.Rewrite.Util (specialise)+import Clash.Primitives.Util (constantArgs)+import Clash.Rewrite.Types+ (RewriteMonad, bindings, curFun, dbgLevel, extra, tcCache)+import Clash.Rewrite.Util (runRewrite, specialise)+import Clash.Unique+import Clash.Util (SrcSpan, anyM, makeCachedU, traceIf) +-- | Determine if argument should reduce to a constant given a primitive and+-- an argument number. Caches results.+isConstantArg+ :: Text+ -- ^ Primitive name+ -> Int+ -- ^ Argument number+ -> RewriteMonad NormalizeState Bool+ -- ^ Yields @DontCare@ for if given primitive name is not found, if the+ -- argument does not exist, or if the argument was not mentioned by the+ -- blackbox.+isConstantArg nm i = do+ argMap <- Lens.use (extra.primitiveArgs)+ case Map.lookup nm argMap of+ Nothing -> do+ -- Constant args not yet calculated, or primitive does not exist+ prims <- Lens.use (extra.primitives)+ case extractPrim =<< HashMapS.lookup nm prims of+ Nothing ->+ -- Primitive does not exist:+ pure False+ Just p -> do+ -- Calculate constant arguments:+ let m = constantArgs nm p+ (extra.primitiveArgs) Lens.%= Map.insert nm m+ pure (i `elem` m)+ Just m ->+ -- Cached version found+ pure (i `elem` m)++-- | Given a list of transformation contexts, determine if any of the contexts+-- indicates that the current arg is to be reduced to a constant / literal.+shouldReduce+ :: Context+ -- ^ ..in the current transformcontext+ -> RewriteMonad NormalizeState Bool+shouldReduce = anyM isConstantArg'+ where+ isConstantArg' (AppArg (Just (nm, _, i))) = isConstantArg nm i+ isConstantArg' _ = pure False+ -- | Determine if a function is already inlined in the context of the 'NetlistMonad' alreadyInlined- :: TmOccName+ :: Id -- ^ Function we want to inline- -> TmOccName+ -> Id -- ^ Function in which we want to perform the inlining -> NormalizeMonad (Maybe Int) alreadyInlined f cf = do inlinedHM <- Lens.use inlineHistory- case HashMap.lookup cf inlinedHM of+ case lookupVarEnv cf inlinedHM of Nothing -> return Nothing- Just inlined' -> return (HashMap.lookup f inlined')+ Just inlined' -> return (lookupVarEnv f inlined') addNewInline- :: TmOccName+ :: Id -- ^ Function we want to inline- -> TmOccName+ -> Id -- ^ Function in which we want to perform the inlining -> NormalizeMonad () addNewInline f cf =- inlineHistory %= HashMap.insertWith- (\_ hm -> HashMap.insertWith (+) f 1 hm)+ inlineHistory %= extendVarEnvWith cf- (HashMap.singleton f 1)+ (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 :: Fresh m- => HashMap TyConOccName TyCon+isClosed :: TyConMap -> Term- -> m Bool-isClosed tcm = fmap not . isPolyFun tcm---- | Determine if a term represents a constant-isConstant :: Term -> Bool-isConstant e = case collectArgs e of- (Data _, args) -> all (either isConstant (const True)) args- (Prim _ _, args) -> all (either isConstant (const True)) args- (Literal _,_) -> True- _ -> False+ -> Bool+isClosed tcm = not . isPolyFun tcm -isConstantNotClockReset :: Term -> NormalizeSession Bool-isConstantNotClockReset e = do- tcm <- Lens.view tcCache- eTy <- termType tcm e- if isClockOrReset tcm eTy- then return False- else return (isConstant e)+-- | Test whether a given term represents a non-recursive global variable+isNonRecursiveGlobalVar+ :: Term+ -> NormalizeSession Bool+isNonRecursiveGlobalVar (collectArgs -> (Var i, _args)) = do+ let eIsGlobal = isGlobalId i+ eIsRec <- isRecursiveBndr i+ return (eIsGlobal && not eIsRec)+isNonRecursiveGlobalVar _ = return False -- | Assert whether a name is a reference to a recursive binder. isRecursiveBndr- :: TmOccName+ :: Id -> NormalizeSession Bool isRecursiveBndr f = do cg <- Lens.use (extra.recursiveComponents)- case HashMap.lookup f cg of+ case lookupVarEnv f cg of Just isR -> return isR Nothing -> do- fBodyM <- HashMap.lookup f <$> Lens.use bindings+ fBodyM <- lookupVarEnv f <$> Lens.use bindings case fBodyM of Nothing -> return False- Just (_,_,_,_,fBody) -> do+ Just (_,_,_,fBody) -> do -- There are no global mutually-recursive functions, only self-recursive -- ones, so checking whether 'f' is part of the free variables of the -- body of 'f' is sufficient.- let used = Lens.toListOf termFreeIds fBody- isR = f `elem` used- (extra.recursiveComponents) %= HashMap.insert f isR+ let isR = f `globalIdOccursIn` fBody+ (extra.recursiveComponents) %= extendVarEnv f isR return isR +-- | Test if we can constant specialize current term in current function. The+-- rules are, we can constant fold if:+--+-- * Term does not carry a clock or reset+-- * Term is constant is @isConstant@ sense, and additionally when term is a+-- global, non-recursive variable+--+canConstantSpec+ :: Term+ -> RewriteMonad NormalizeState Bool+canConstantSpec e = do+ tcm <- Lens.view tcCache+ if isClockOrReset tcm (termType tcm e) then+ case collectArgs e of+ (Prim nm _, _) -> return (nm == "Clash.Transformations.removedArg")+ _ -> return False+ else+ case collectArgs e of+ (Data _, args) -> and <$> mapM (either canConstantSpec (const (pure True))) args+ (Prim _ _, args) -> and <$> mapM (either canConstantSpec (const (pure True))) args+ (Lam _ _, _) -> pure (not (hasLocalFreeVars e))+ (Var f, args) -> do+ (curF, _) <- Lens.use curFun++ argsConst <- and <$> mapM (either canConstantSpec (const (pure True))) args+ isNonRecGlobVar <- isNonRecursiveGlobalVar e+ return (argsConst && isNonRecGlobVar && f /= curF)++ (Literal _,_) -> pure True+ _ -> pure False+ -- | A call graph counts the number of occurrences that a functions 'g' is used -- in 'f'.-type CallGraph = HashMap TmOccName (HashMap TmOccName Word)+type CallGraph = VarEnv (VarEnv Word) -- | Create a call graph for a set of global binders, given a root callGraph :: BindingMap- -> TmOccName+ -> Id -> CallGraph-callGraph bndrs = go HashMap.empty+callGraph bndrs rt = go emptyVarEnv (varUniq rt) where go cg root- | Nothing <- HashMap.lookup root cg- , Just rootTm <- HashMap.lookup root bndrs =- let used = List.foldl'- (\m k -> HashMap.insertWith (+) k 1 m)- HashMap.empty- (Lens.toListOf termFreeIds (rootTm ^. _5))- cg' = HashMap.insert root used cg- in List.foldl' go cg' (HashMap.keys used)+ | Nothing <- lookupUniqMap root cg+ , Just rootTm <- lookupUniqMap root bndrs =+ let used = Lens.foldMapByOf globalIds (unionVarEnvWith (+))+ emptyVarEnv (`unitUniqMap` 1) (rootTm ^. _4)+ cg' = extendUniqMap root used cg+ in List.foldl' go cg' (keysUniqMap used) go cg _ = cg -- | Give a "performance/size" classification of a function in normal form.@@ -132,19 +228,17 @@ -> TermClassification classifyFunction = go (TermClassification 0 0 0) where- go !c (Lam b) = let (_,e) = unsafeUnbind b in go c e- go !c (TyLam b) = let (_,e) = unsafeUnbind b in go c e- go !c (Letrec b) =- let (bndsR,_) = unsafeUnbind b- es = map (unembed . snd) (unrec bndsR)- in List.foldl' go c es- go !c e@(App _ _) = case fst (collectArgs e) of- Prim _ _ -> c & primitive +~ 1- Var _ _ -> c & function +~ 1+ go !c (Lam _ e) = go c e+ go !c (TyLam _ e) = go c e+ go !c (Letrec bs _) = List.foldl' go c (map snd bs)+ go !c e@(App {}) = case fst (collectArgs e) of+ Prim {} -> c & primitive +~ 1+ Var {} -> c & function +~ 1 _ -> c go !c (Case _ _ alts) = case alts of (_:_:_) -> c & selection +~ 1 _ -> c+ go !c (Tick _ e) = go c e go c _ = c -- | Determine whether a function adds a lot of hardware or not.@@ -163,3 +257,49 @@ | _primitive <= 1 -> _function <= 0 && _selection <= 0 | _selection <= 1 -> _function <= 0 && _primitive <= 0 | otherwise -> False++normalizeTopLvlBndr+ :: Id+ -> (Id, SrcSpan, InlineSpec, Term)+ -> NormalizeSession (Id, SrcSpan, InlineSpec, Term)+normalizeTopLvlBndr nm (nm',sp,inl,tm) = makeCachedU nm (extra.normalized) $ do+ tcm <- Lens.view tcCache+ let nmS = showPpr (varName nm)+ -- We deshadow the term because sometimes GHC gives us+ -- code where a local binder has the same unique as a+ -- global binder, sometimes causing the inliner to go+ -- into a loop. Deshadowing freshens all the bindings+ -- to avoid this.+ --+ -- Additionally, it allows for a much cheaper `appProp`+ -- transformation, see Note [AppProp no-shadow invariant]+ let tm1 = deShadowTerm emptyInScopeSet tm+ old <- Lens.use curFun+ tm2 <- rewriteExpr ("normalization",normalization) (nmS,tm1) (nm',sp)+ curFun .= old+ let ty' = termType tcm tm2+ return (nm' {varType = ty'},sp,inl,tm2)++-- | Rewrite a term according to the provided transformation+rewriteExpr :: (String,NormRewrite) -- ^ Transformation to apply+ -> (String,Term) -- ^ Term to transform+ -> (Id, SrcSpan) -- ^ Renew current function being rewritten+ -> NormalizeSession Term+rewriteExpr (nrwS,nrw) (bndrS,expr) (nm, sp) = do+ curFun .= (nm, sp)+ lvl <- Lens.view dbgLevel+ let before = showPpr expr+ let expr' = traceIf (lvl >= DebugFinal)+ (bndrS ++ " before " ++ nrwS ++ ":\n\n" ++ before ++ "\n")+ expr+ rewritten <- runRewrite nrwS emptyInScopeSet nrw expr'+ let after = showPpr rewritten+ traceIf (lvl >= DebugFinal)+ (bndrS ++ " after " ++ nrwS ++ ":\n\n" ++ after ++ "\n") $+ return rewritten++removedTm+ :: Type+ -> Term+removedTm =+ TyApp (Prim "Clash.Transformations.removedArg" (PrimInfo undefinedTy WorkNever))
+ src/Clash/Pretty.hs view
@@ -0,0 +1,20 @@+module Clash.Pretty where++import Data.Text.Prettyprint.Doc+import Data.Text.Prettyprint.Doc.Render.String++showDoc :: Doc ann -> String+showDoc = renderString . layoutPretty (LayoutOptions (AvailablePerLine 80 0.6))++removeAnnotations :: Doc ann -> Doc ()+removeAnnotations = reAnnotate $ const ()++-- | A variant of @Pretty@ that is not polymorphic on the type of annotations.+-- This is needed to derive instances from Clash's pretty printer (PrettyPrec),+-- which annotates documents with Clash-specific information and, therefore,+-- fixes the type of annotations.+class ClashPretty a where+ clashPretty :: a -> Doc ()++fromPretty :: Pretty a => a -> Doc ()+fromPretty = removeAnnotations . pretty
+ src/Clash/Primitives/GHC/Int.hs view
@@ -0,0 +1,61 @@+{-|+ Copyright : (C) 2019, Myrtle Software Ltd+ License : BSD2 (see the file LICENSE)+ Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>++ Blackbox generation for GHC.Int.IntX# data constructors. (System)Verilog only!+-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ViewPatterns #-}++module Clash.Primitives.GHC.Int (intTF) where++import Clash.Core.Literal+ (Literal(IntegerLiteral, IntLiteral, Int64Literal))+import Clash.Core.Term (Term(Literal))+import Clash.Core.Type (Type)+import Clash.Primitives.GHC.Literal+ (literalTF, signed, signedLiteral, assign)+import Clash.Netlist.Types (BlackBox(BBTemplate))+import Clash.Netlist.BlackBox.Types+ (BlackBoxFunction, Element(Arg, Result), emptyBlackBoxMeta+ ,BlackBoxMeta, bbKind, TemplateKind(TDecl))++getIntLit+ :: Literal+ -> Maybe Integer+getIntLit =+ \case+ IntegerLiteral i -> Just i+ IntLiteral i -> Just i+ Int64Literal i -> Just i+ _ -> Nothing++-- | Template function for Int8,Int16,.. Constructs "clean" literals.+intTF :: BlackBoxFunction+intTF = literalTF "GHC.Int.I" intTF'++intTF'+ :: Bool+ -- ^ Is declaration+ -> [Either Term Type]+ -- ^ Arguments+ -> Int+ -- ^ Word size+ -> (BlackBoxMeta, BlackBox)+intTF' False [Left (Literal (getIntLit -> Just n))] intSize =+ -- Literal as expression:+ ( emptyBlackBoxMeta+ , BBTemplate [signedLiteral intSize n])++intTF' True [Left (Literal (getIntLit -> Just n))] intSize =+ -- Literal as declaration:+ ( emptyBlackBoxMeta+ , BBTemplate (assign (Result False) [signedLiteral intSize n]))++intTF' _isDecl _args _intSize =+ -- Not a literal. We need an assignment as Verilog does not support truncating+ -- arbitrary expression.+ ( emptyBlackBoxMeta {bbKind = TDecl }+ , BBTemplate (assign (Result False) (signed (Arg False 0))))
+ src/Clash/Primitives/GHC/Literal.hs view
@@ -0,0 +1,77 @@+{-|+ Copyright : (C) 2019, Myrtle Software Ltd+ License : BSD2 (see the file LICENSE)+ Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>++ Blackbox generation for literal data constructors. (System)Verilog only!+-}+{-# LANGUAGE OverloadedStrings #-}++module Clash.Primitives.GHC.Literal+ ( assign+ , signed+ , signedLiteral+ , unsigned+ , unsignedLiteral+ , literalTF+ )+ where++import qualified Data.Text.Lazy as LT+import Data.Text+ (Text, stripPrefix, stripSuffix, unpack)+import Text.Read (readMaybe)+import TextShow (showtl)++import Clash.Core.Term (Term)+import Clash.Core.Type (Type)+import Clash.Netlist.Types (BlackBox)+import Clash.Netlist.BlackBox.Types+ (BlackBoxFunction, Element(Text), BlackBoxMeta)++unsigned :: Element -> [Element]+unsigned el = [Text "$unsigned(", el, Text ")"]++signed :: Element -> [Element]+signed el = [Text "$signed(", el, Text ")"]++assign :: Element -> [Element] -> [Element]+assign lhs rhs = Text "assign " : lhs : Text " = " : rhs ++ [Text ";"]++signedLiteral :: Int -> Integer -> Element+signedLiteral wordSize wordVal =+ Text (LT.concat [ if wordVal < 0 then "-" else ""+ , showtl wordSize+ , "'sd"+ , showtl (abs wordVal)+ ])++unsignedLiteral :: Int -> Integer -> Element+unsignedLiteral wordSize wordVal =+ Text (LT.concat [ if wordVal < 0 then "-" else ""+ , showtl wordSize+ , "'d"+ , showtl (abs wordVal)+ ])++-- | Parse integer in strings of the form "GHC.Word.WordX#" where+-- "GHC.Word.Word" is the prefix given.+readSize :: Text -> Text -> Maybe Int+readSize prefix nm0 = do+ nm1 <- stripPrefix prefix nm0+ nm2 <- stripSuffix "#" nm1+ readMaybe (unpack nm2)++-- | Constructs "clean" literals.+literalTF+ :: Text+ -- ^ Base name of constructors (for example: "GHC.Word.W")+ -> (Bool -> [Either Term Type] -> Int -> (BlackBoxMeta, BlackBox))+ -- ^ Functions processing+ -> BlackBoxFunction+literalTF baseName tf isDecl primName args _resTy = return $+ case readSize baseName primName of+ Nothing ->+ Left (concat ["Can only make blackboxes for '", unpack baseName, "X#'"])+ Just n ->+ Right (tf isDecl args n)
+ src/Clash/Primitives/GHC/Word.hs view
@@ -0,0 +1,49 @@+{-|+ Copyright : (C) 2019, Myrtle Software Ltd+ License : BSD2 (see the file LICENSE)+ Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>++ Blackbox generation for GHC.Word.WordX# data constructors. (System)Verilog only!+-}+{-# LANGUAGE OverloadedStrings #-}++module Clash.Primitives.GHC.Word (wordTF) where++import Clash.Core.Literal (Literal(WordLiteral))+import Clash.Core.Term (Term(Literal))+import Clash.Core.Type (Type)+import Clash.Primitives.GHC.Literal+ (literalTF, unsigned, unsignedLiteral, assign)+import Clash.Netlist.Types (BlackBox(BBTemplate))+import Clash.Netlist.BlackBox.Types+ (BlackBoxFunction, Element(Arg, Result), emptyBlackBoxMeta+ ,BlackBoxMeta, bbKind, TemplateKind(TDecl))++-- | Template function for Word8,Word16,.. Constructs "clean" literals. This+-- function generates valid (System)Verilog only!+wordTF :: BlackBoxFunction+wordTF = literalTF "GHC.Word.W" wordTF'++wordTF'+ :: Bool+ -- ^ Is declaration+ -> [Either Term Type]+ -- ^ Arguments+ -> Int+ -- ^ Word size+ -> (BlackBoxMeta, BlackBox)+wordTF' False [Left (Literal (WordLiteral n))] wordSize =+ -- Literal as expression:+ ( emptyBlackBoxMeta+ , BBTemplate [unsignedLiteral wordSize n])++wordTF' True [Left (Literal (WordLiteral n))] wordSize =+ -- Literal as declaration:+ ( emptyBlackBoxMeta+ , BBTemplate (assign (Result False) [unsignedLiteral wordSize n]))++wordTF' _isDecl _args _wordSize =+ -- Not a literal. We need an assignment as Verilog does not support truncating+ -- arbitrary expression.+ ( emptyBlackBoxMeta {bbKind = TDecl }+ , BBTemplate (assign (Result False) (unsigned (Arg False 0))))
+ src/Clash/Primitives/Intel/ClockGen.hs view
@@ -0,0 +1,119 @@+{-|+ Copyright : (C) 2018, Google Inc.+ License : BSD2 (see the file LICENSE)+ Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>++ Blackbox template functions for Clash.Intel.ClockGen.{alteraPll,altpll}+-}++{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ViewPatterns #-}++module Clash.Primitives.Intel.ClockGen where++import Clash.Backend+import Clash.Netlist.BlackBox.Util+import Clash.Netlist.Id+import Clash.Netlist.Types++import Control.Monad.State++import Data.Semigroup.Monad+import Data.Text.Prettyprint.Doc.Extra++import qualified Data.Text as TextS++altpllTF :: TemplateFunction+altpllTF = TemplateFunction used valid altpllTemplate+ where+ used = [0,1,2]+ valid bbCtx+ | [(nm,_,_),_,_] <- bbInputs bbCtx+ , Just _ <- exprToString nm+ , (Identifier _ Nothing,Product {}) <- bbResult bbCtx+ = True+ valid _ = False++alteraPllTF :: TemplateFunction+alteraPllTF = TemplateFunction used valid alteraPllTemplate+ where+ used = [1,2,3]+ valid bbCtx+ | [_,(nm,_,_),_,_] <- bbInputs bbCtx+ , Just _ <- exprToString nm+ , (Identifier _ Nothing,Product {}) <- bbResult bbCtx+ = True+ valid _ = False++alteraPllTemplate+ :: Backend s+ => BlackBoxContext+ -> State s Doc+alteraPllTemplate bbCtx = do+ let mkId = mkUniqueIdentifier Basic+ locked <- mkId "locked"+ pllLock <- mkId "pllLock"+ alteraPll <- mkId "alteraPll"+ alteraPll_inst <- mkId "alterPll_inst"++ clocks <- traverse (mkUniqueIdentifier Extended)+ [TextS.pack ("pllOut" ++ show n) | n <- [0..length tys - 1]]+ getMon $ blockDecl alteraPll $ concat+ [[ NetDecl Nothing locked rstTy+ , NetDecl Nothing pllLock Bool]+ ,[ NetDecl Nothing clkNm ty | (clkNm,ty) <- zip clocks tys]+ ,[ InstDecl Comp Nothing compName alteraPll_inst [] $ concat+ [[(Identifier "refclk" Nothing,In,clkTy,clk)+ ,(Identifier "rst" Nothing,In,rstTy,rst)]+ ,[(Identifier (TextS.pack ("outclk_" ++ show n)) Nothing,Out,ty,Identifier k Nothing)+ |(k,ty,n) <- zip3 clocks tys [(0 :: Int)..] ]+ ,[(Identifier "locked" Nothing,Out,rstTy,Identifier locked Nothing)]]+ , CondAssignment pllLock Bool (Identifier locked Nothing) rstTy+ [(Just (BitLit H),Literal Nothing (BoolLit True))+ ,(Nothing ,Literal Nothing (BoolLit False))]+ , Assignment result (DataCon resTy (DC (resTy,0)) $ concat+ [[Identifier k Nothing | k <- clocks]+ ,[Identifier pllLock Nothing]])++ ]+ ]+ where+ [_,(nm,_,_),(clk,clkTy,_),(rst,rstTy,_)] = bbInputs bbCtx+ (Identifier result Nothing,resTy@(Product _ _ (tail -> tys))) = bbResult bbCtx+ Just nm' = exprToString nm+ compName = TextS.pack nm'++altpllTemplate+ :: Backend s+ => BlackBoxContext+ -> State s Doc+altpllTemplate bbCtx = do+ let mkId = mkUniqueIdentifier Basic+ pllOut <- mkId "pllOut"+ locked <- mkId "locked"+ pllLock <- mkId "pllLock"+ alteraPll <- mkId "altpll"+ alteraPll_inst <- mkId "altpll_inst"+ getMon $ blockDecl alteraPll+ [ NetDecl Nothing locked Bit+ , NetDecl Nothing pllLock Bool+ , NetDecl Nothing pllOut clkOutTy+ , InstDecl Comp Nothing compName alteraPll_inst []+ [(Identifier "inclk0" Nothing,In,clkTy,clk)+ ,(Identifier "areset" Nothing,In,rstTy,rst)+ ,(Identifier "c0" Nothing,Out,clkOutTy,Identifier pllOut Nothing)+ ,(Identifier "locked" Nothing,Out,Bit,Identifier locked Nothing)]+ , CondAssignment pllLock Bool (Identifier locked Nothing) rstTy+ [(Just (BitLit H),Literal Nothing (BoolLit True))+ ,(Nothing ,Literal Nothing (BoolLit False))]+ , Assignment result (DataCon resTy (DC (resTy,0))+ [Identifier pllOut Nothing+ ,Identifier pllLock Nothing])++ ]+ where+ [(nm,_,_),(clk,clkTy,_),(rst,rstTy,_)] = bbInputs bbCtx+ (Identifier result Nothing,resTy@(Product _ _ [clkOutTy,_])) = bbResult bbCtx+ Just nm' = exprToString nm+ compName = TextS.pack nm'+
+ src/Clash/Primitives/Sized/Vector.hs view
@@ -0,0 +1,92 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TupleSections #-}++module Clash.Primitives.Sized.Vector where++import Control.Monad.State+import Data.Semigroup.Monad+import Data.Text.Lazy (pack)+import Data.Text.Prettyprint.Doc.Extra+import Text.Trifecta.Result++import Clash.Backend+import Clash.Netlist.BlackBox+import Clash.Netlist.BlackBox.Parser+import Clash.Netlist.BlackBox.Types+import Clash.Netlist.Types+import Clash.Netlist.Util++import qualified Data.String.Interpolate as I+import qualified Data.String.Interpolate.Util as I++indexIntVerilog :: BlackBoxFunction+indexIntVerilog _isD _primName args _ty = return ((meta,) <$> bb)+ where+ meta = BlackBoxMeta+ { bbOutputReg = False+ , bbKind = bbKi+ , bbLibrary = []+ , bbImports = []+ , bbIncludes = []+ }++ bbKi = case args of+ [_nTy,_aTy,_kn,_v,Left ix]+ | isLiteral ix -> TExpr+ _ -> TDecl++ bb = case args of+ [_nTy,_aTy,_kn,_v,Left ix] | isLiteral ix ->+ Right (BBFunction "Clash.Primitives.Sized.Vector" 0 indexIntVerilogTF)+ _ ->+ BBTemplate <$> case runParse (pack (I.unindent bbText)) of+ Success t -> Right t+ _ -> Left "internal error: parse fail"++ bbText = [I.i|+ // index begin+ ~IF~SIZE[~TYP[1]]~THENwire ~TYPO ~GENSYM[vecArray][0] [0:~LIT[0]-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]] = ~VAR[vecFlat][1][~SYM[2]*~SIZE[~TYPO]+:~SIZE[~TYPO]];+ end+ ~ENDGENERATE+ assign ~RESULT = ~SYM[0][~ARG[2]];~ELSEassign ~RESULT = ~ERRORO;~FI+ // index end|]++indexIntVerilogTF :: TemplateFunction+indexIntVerilogTF = TemplateFunction used valid indexIntVerilogTemplate+ where+ used = [1,2]+ valid = const True++indexIntVerilogTemplate+ :: Backend s+ => BlackBoxContext+ -> State s Doc+indexIntVerilogTemplate bbCtx = getMon $ case typeSize vTy of+ 0 -> hdlTypeErrValue rTy+ _ -> case vec of+ Identifier i mM -> case mM of+ Just m ->+ expr False (Identifier i (Just (Nested m (Indexed (vTy,10,ixI ix)))))+ _ -> expr False (Identifier i (Just (Indexed (vTy,10,ixI ix))))+ _ -> error ("Expected Identifier: " ++ show vec)+ where+ [ _kn+ , (vec, vTy, _)+ , (ix, _, _)+ ] = bbInputs bbCtx++ (_,rTy) = bbResult bbCtx++ ixI :: Expr -> Int+ ixI ix0 = case ix0 of+ Literal _ (NumLit i) -> fromInteger i+ BlackBoxE "GHC.Types.I#" _ _ _ _ ixCtx _ ->+ let (ix1,_,_) = head (bbInputs ixCtx)+ in ixI ix1+ _ -> error ("Unexpected literal" ++ show ix)
src/Clash/Primitives/Types.hs view
@@ -1,69 +1,252 @@ {-| Copyright : (C) 2012-2016, University of Twente, 2016-2017, Myrtle Software Ltd+ 2018 , Google Inc. License : BSD2 (see the file LICENSE) Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com> Type and instance definitions for Primitive -} +{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveFoldable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ViewPatterns #-} -module Clash.Primitives.Types where+module Clash.Primitives.Types+ ( TemplateSource(..)+ , TemplateKind(..)+ , TemplateFormat(..)+ , BlackBoxFunctionName(..)+ , Primitive(..)+ , GuardedCompiledPrimitive+ , GuardedResolvedPrimitive+ , PrimMap+ , UnresolvedPrimitive+ , ResolvedPrimitive+ , ResolvedPrimMap+ , CompiledPrimitive+ , CompiledPrimMap+ ) where -import Control.Applicative ((<|>))-import Data.Aeson (FromJSON (..), Value (..), (.:), (.:?), (.!=))-import Data.HashMap.Lazy (HashMap)-import qualified Data.HashMap.Strict as H-import qualified Data.Text as S-import Data.Text.Lazy (Text)+import {-# SOURCE #-} Clash.Netlist.Types+import Clash.Annotations.Primitive (PrimitiveGuard)+import Clash.Core.Term (WorkInfo (..))+import Clash.Netlist.BlackBox.Types+ (BlackBoxFunction, BlackBoxTemplate, TemplateKind (..))+import Control.Applicative ((<|>))+import Control.DeepSeq (NFData)+import Data.Aeson+ (FromJSON (..), Value (..), (.:), (.:?), (.!=))+import Data.Binary (Binary)+import Data.Char (isUpper, isLower, isAlphaNum)+import Data.Either (lefts)+import Data.Hashable (Hashable)+import qualified Data.HashMap.Strict as H+import Data.List (intercalate)+import qualified Data.Text as S+import Data.Text.Lazy (Text)+import GHC.Generics (Generic)+import GHC.Stack (HasCallStack) --- | Primitive Definitions-type PrimMap a = HashMap S.Text (Primitive a)+-- | An unresolved primitive still contains pointers to files.+type UnresolvedPrimitive = Primitive Text ((TemplateFormat,BlackBoxFunctionName),Maybe TemplateSource) (Maybe S.Text) (Maybe TemplateSource) +-- | A parsed primitive does not contain pointers to filesystem files anymore,+-- but holds uncompiled @BlackBoxTemplate@s and @BlackBoxFunction@s.+type ResolvedPrimitive = Primitive Text ((TemplateFormat,BlackBoxFunctionName),Maybe Text) () (Maybe Text)+type GuardedResolvedPrimitive = PrimitiveGuard ResolvedPrimitive+type ResolvedPrimMap = PrimMap GuardedResolvedPrimitive++-- | A compiled primitive has compiled all templates and functions from its+-- @ResolvedPrimitive@ counterpart. The Int in the tuple is a hash of the+-- (uncompiled) BlackBoxFunction.+type CompiledPrimitive = Primitive BlackBoxTemplate BlackBox () (Int, BlackBoxFunction)+type GuardedCompiledPrimitive = PrimitiveGuard CompiledPrimitive+type CompiledPrimMap = PrimMap GuardedCompiledPrimitive++-- | A @PrimMap@ maps primitive names to a @Primitive@+type PrimMap a = H.HashMap S.Text a++-- | A BBFN is a parsed version of a fully qualified function name. It is+-- guaranteed to have at least one module name which is not /Main/.+data BlackBoxFunctionName =+ BlackBoxFunctionName [String] String+ deriving (Eq, Generic, NFData, Binary, Hashable)++instance Show BlackBoxFunctionName where+ show (BlackBoxFunctionName mods funcName) =+ "BBFN<" ++ intercalate "." mods ++ "." ++ funcName ++ ">"++-- | Quick and dirty implementation of Text.splitOn for Strings+splitOn :: String -> String -> [String]+splitOn (S.pack -> sep) (S.pack -> str) =+ map S.unpack $ S.splitOn sep str++-- | Parses a string into a list of modules and a function name. I.e., it parses+-- the string "Clash.Primitives.Types.parseBBFN" to ["Clash", "Primitives",+-- "Types"] and "parseBBFN". The result is stored as a BlackBoxFunctionName.+parseBBFN+ :: HasCallStack+ => String+ -> Either String BlackBoxFunctionName+parseBBFN bbfn =+ case splitOn "." bbfn of+ [] -> Left $ "Empty function name: " ++ bbfn+ [_] -> Left $ "No module or function defined: " ++ bbfn+ nms ->+ let (mods, func) = (init nms, last nms) in+ let errs = lefts $ checkFunc func : map checkMod mods in+ case errs of+ [] -> Right $ BlackBoxFunctionName mods func+ _ -> Left $ "Error while parsing " ++ show bbfn ++ ": " ++ head errs+ where+ checkMod mod'+ | isLower (head mod') =+ Left $ "Module name cannot start with lowercase: " ++ mod'+ | any (not . isAlphaNum) mod' =+ Left $ "Module name must be alphanumerical: " ++ mod'+ | otherwise =+ Right mod'++ checkFunc func+ | isUpper (head func) =+ Left $ "Function name must start with lowercase: " ++ func+ | otherwise =+ Right func++data TemplateSource+ = TFile FilePath+ -- ^ Template source stored in file on filesystem+ | TInline Text+ -- ^ Template stored inline+ deriving (Show, Eq, Generic, NFData)+++data TemplateFormat+ = TTemplate+ | THaskell+ deriving (Show, Generic, Hashable, NFData)+ -- | Externally defined primitive-data Primitive a- -- | A primitive that has a template that can be filled out by the backend render+data Primitive a b c d+ -- | Primitive template written in a Clash specific templating language = BlackBox- { name :: !S.Text+ { name :: !S.Text -- ^ Name of the primitive+ , workInfo :: WorkInfo+ -- ^ Whether the primitive does any work, i.e. takes chip area+ , kind :: TemplateKind+ -- ^ Whether this results in an expression or a declaration+ , warning :: c+ -- ^ A warning to be outputted when the primitive is instantiated.+ -- This is intended to be used as a warning for primitives that are not+ -- synthesizable, but may also be used for other purposes. , outputReg :: Bool -- ^ Verilog only: whether the result should be a /reg/(@True@) or /wire/ -- (@False@); when not specified in the /.json/ file, the value will default -- to @False@ (i.e. /wire/).- , library :: [a]+ , libraries :: [a] -- ^ VHDL only: add /library/ declarations for the given names- , imports :: [a]+ , imports :: [a] -- ^ VHDL only: add /use/ declarations for the given names- , include :: Maybe ((S.Text,S.Text),a)- -- ^ Create a file to be included with the generated primitive. The fields+ , includes :: [((S.Text,S.Text),b)]+ -- ^ Create files to be included with the generated primitive. The fields -- are ((name, extension), content), where content is a template of the file- -- Defaults to @Nothing@ when not specified in the /.json/ file- , template :: !(Either a a) -- ^ Either a /declaration/ or an /expression/ template.+ -- Defaults to @[]@ when not specified in the /.json/ file+ , template :: b+ -- ^ Used to indiciate type of template (declaration or expression). Will be+ -- filled with @Template@ or an @Either decl expr@. }- -- | A primitive that carries additional information+ -- | Primitive template rendered by a Haskell function (given as raw source code)+ | BlackBoxHaskell+ { name :: !S.Text+ -- ^ Name of the primitive+ , workInfo :: WorkInfo+ -- ^ Whether the primitive does any work, i.e. takes chip area+ , functionName :: BlackBoxFunctionName+ , function :: d+ -- ^ Holds blackbox function and its hash, (Int, BlackBoxFunction), in a+ -- CompiledPrimitive.+ }+ -- | A primitive that carries additional information. These are "real"+ -- primitives, hardcoded in the compiler. For example: 'mapSignal' in+ -- @GHC2Core.coreToTerm@. | Primitive- { name :: !S.Text -- ^ Name of the primitive- , primType :: !Text -- ^ Additional information+ { name :: !S.Text+ -- ^ Name of the primitive+ , workInfo :: WorkInfo+ -- ^ Whether the primitive does any work, i.e. takes chip area+ , primSort :: !Text+ -- ^ Additional information }- deriving Show+ deriving (Show, Generic, NFData, Binary, Hashable, Functor) -instance FromJSON (Primitive Text) where- parseJSON (Object v) = case H.toList v of- [(conKey,Object conVal)] -> case conKey of- "BlackBox" -> BlackBox <$> conVal .: "name"- <*> conVal .:? "outputReg" .!= False- <*> conVal .:? "libraries" .!= []- <*> conVal .:? "imports" .!= []- <*> (conVal .:? "include" >>= parseInclude)- <*> ((Left <$> conVal .: "templateD") <|> (Right <$> conVal .: "templateE"))- "Primitive" -> Primitive <$> conVal .: "name" <*> conVal .: "primType"- _ -> error "Expected: BlackBox or Primitive object"- _ -> error "Expected: BlackBox or Primitive object"+instance FromJSON UnresolvedPrimitive where+ parseJSON (Object v) =+ case H.toList v of+ [(conKey,Object conVal)] ->+ case conKey of+ "BlackBoxHaskell" -> do+ name' <- conVal .: "name"+ wf <- ((conVal .:? "workInfo" >>= maybe (pure Nothing) parseWorkInfo) .!= WorkVariable)+ fName <- conVal .: "templateFunction"+ templ <- (Just . TInline <$> conVal .: "template")+ <|> (Just . TFile <$> conVal .: "file")+ <|> (pure Nothing)+ fName' <- either fail return (parseBBFN fName)+ return (BlackBoxHaskell name' wf fName' templ)+ "BlackBox" ->+ BlackBox <$> conVal .: "name"+ <*> (conVal .:? "workInfo" >>= maybe (pure Nothing) parseWorkInfo) .!= WorkVariable+ <*> (conVal .: "kind" >>= parseTemplateKind)+ <*> conVal .:? "warning"+ <*> conVal .:? "outputReg" .!= False+ <*> conVal .:? "libraries" .!= []+ <*> conVal .:? "imports" .!= []+ <*> (conVal .:? "includes" .!= [] >>= traverse parseInclude)+ <*> parseTemplate conVal+ "Primitive" ->+ Primitive <$> conVal .: "name"+ <*> (conVal .:? "workInfo" >>= maybe (pure Nothing) parseWorkInfo) .!= WorkVariable+ <*> conVal .: "primType"++ e -> fail $ "[1] Expected: BlackBox or Primitive object, got: " ++ show e+ e -> fail $ "[2] Expected: BlackBox or Primitive object, got: " ++ show e where- parseInclude Nothing = pure Nothing- parseInclude (Just c) =- Just <$> ((,) <$> ((,) <$> c .: "name" <*> c .: "extension") <*> c .: "content")- parseJSON _ = error "Expected: BlackBox or Primitive object"+ parseTemplate c =+ (,) <$> ((,) <$> (c .:? "format" >>= traverse parseTemplateFormat) .!= TTemplate+ <*> (c .:? "templateFunction" >>= traverse parseBBFN') .!= defTemplateFunction)+ <*> (Just . TInline <$> c .: "template" <|>+ Just . TFile <$> c .: "file" <|>+ pure Nothing)++ parseInclude c =+ (,) <$> ((,) <$> c .: "name" <*> c .: "extension")+ <*> parseTemplate c++ parseTemplateKind (String "Declaration") = pure TDecl+ parseTemplateKind (String "Expression") = pure TExpr+ parseTemplateKind c = fail ("[4] Expected: Declaration or Expression, got " ++ show c)++ parseTemplateFormat (String "Template") = pure TTemplate+ parseTemplateFormat (String "Haskell") = pure THaskell+ parseTemplateFormat c = fail ("[5] unexpected format: " ++ show c)++ parseWorkInfo (String "Constant") = pure (Just WorkConstant)+ parseWorkInfo (String "Never") = pure (Just WorkNever)+ parseWorkInfo (String "Variable") = pure (Just WorkVariable)+ parseWorkInfo (String "Always") = pure (Just WorkAlways)+ parseWorkInfo c = fail ("[6] unexpected workInfo: " ++ show c)++ parseBBFN' = either fail return . parseBBFN++ defTemplateFunction = BlackBoxFunctionName ["Template"] "template"++ parseJSON unexpected =+ fail $ "[3] Expected: BlackBox or Primitive object, got: " ++ show unexpected
src/Clash/Primitives/Util.hs view
@@ -1,41 +1,157 @@ {-| Copyright : (C) 2012-2016, University of Twente, 2017 , Myrtle Software Ltd+ 2018 , Google Inc. License : BSD2 (see the file LICENSE) Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com> Utility functions to generate Primitives -} -module Clash.Primitives.Util where+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-} -import Data.Aeson (FromJSON)+module Clash.Primitives.Util+ ( generatePrimMap+ , hashCompiledPrimMap+ , constantArgs+ , decodeOrErr+ ) where++import Control.DeepSeq (force)+import Control.Monad (join) import Data.Aeson.Extra (decodeOrErr) import qualified Data.ByteString.Lazy as LZ import qualified Data.HashMap.Lazy as HashMap-import Data.List (isSuffixOf)-import Data.Maybe (fromMaybe)+import qualified Data.HashMap.Strict as HashMapStrict+import qualified Data.Set as Set+import Data.Hashable (hash)+import Data.List (isSuffixOf, sort)+import qualified Data.Text as TS import Data.Text.Lazy (Text)+import qualified Data.Text.Lazy.IO as T+import GHC.Stack (HasCallStack) import qualified System.Directory as Directory import qualified System.FilePath as FilePath+import System.IO.Error (tryIOError) +import Clash.Annotations.Primitive+ ( PrimitiveGuard(HasBlackBox, WarnNonSynthesizable, WarnAlways, DontTranslate)+ , extractPrim) import Clash.Primitives.Types-import Clash.Util+ ( Primitive(BlackBox), CompiledPrimitive, ResolvedPrimitive, ResolvedPrimMap+ , includes, template, TemplateSource(TFile, TInline), Primitive(..)+ , UnresolvedPrimitive, CompiledPrimMap, GuardedResolvedPrimitive)+import Clash.Netlist.Types (BlackBox(..))+import Clash.Netlist.BlackBox.Util+ (walkElement)+import Clash.Netlist.BlackBox.Types+ (Element(Const, Lit)) -parsePrimitive :: (FromJSON a)- => FilePath- -> IO [a]-parsePrimitive filename = ( return- . fromMaybe []- . decodeOrErr filename- <=< LZ.readFile- ) filename+hashCompiledPrimitive :: CompiledPrimitive -> Int+hashCompiledPrimitive (Primitive {name, primSort}) = hash (name, primSort)+hashCompiledPrimitive (BlackBoxHaskell {function}) = fst function+hashCompiledPrimitive (BlackBox {name, kind, outputReg, libraries, imports, includes, template}) =+ hash (name, kind, outputReg, libraries, imports, includes', hashBlackbox template)+ where+ includes' = map (\(nms, bb) -> (nms, hashBlackbox bb)) includes+ hashBlackbox (BBTemplate bbTemplate) = hash bbTemplate+ hashBlackbox (BBFunction bbName bbHash _bbFunc) = hash (bbName, bbHash) +-- | Hash a compiled primitive map. It needs a separate function (as opposed to+-- just 'hash') as it might contain (obviously unhashable) Haskell functions. This+-- function takes the hash value stored with the function instead.+hashCompiledPrimMap :: CompiledPrimMap -> Int+hashCompiledPrimMap cpm = hash (map (fmap hashCompiledPrimitive) orderedValues)+ where+ -- TODO: switch to 'normal' map instead of hashmap?+ orderedKeys = sort (HashMap.keys cpm)+ orderedValues = map (cpm HashMapStrict.!) orderedKeys++resolveTemplateSource+ :: HasCallStack+ => FilePath+ -> TemplateSource+ -> IO Text+resolveTemplateSource _metaPath (TInline text) =+ return text+resolveTemplateSource metaPath (TFile path) =+ let path' = FilePath.replaceFileName metaPath path in+ either (error . show) id <$> (tryIOError $ T.readFile path')++-- | Replace file pointers with file contents+resolvePrimitive'+ :: HasCallStack+ => FilePath+ -> UnresolvedPrimitive+ -> IO (TS.Text, GuardedResolvedPrimitive)+resolvePrimitive' _metaPath (Primitive name wf primType) =+ return (name, HasBlackBox (Primitive name wf primType))+resolvePrimitive' metaPath BlackBox{template=t, includes=i, ..} = do+ let resolvedIncludes = mapM (traverse (traverse (traverse (resolveTemplateSource metaPath)))) i+ resolved = traverse (traverse (resolveTemplateSource metaPath)) t+ bb <- BlackBox name workInfo kind () outputReg libraries imports <$> resolvedIncludes <*> resolved+ case warning of+ Just w -> pure (name, WarnNonSynthesizable (TS.unpack w) bb)+ Nothing -> pure (name, HasBlackBox bb)+resolvePrimitive' metaPath (BlackBoxHaskell bbName wf funcName t) =+ (bbName,) . HasBlackBox . BlackBoxHaskell bbName wf funcName <$> (mapM (resolveTemplateSource metaPath) t)++-- | Interprets contents of json file as list of @Primitive@s. Throws+-- exception if it fails.+resolvePrimitive+ :: HasCallStack+ => FilePath+ -> IO [(TS.Text, GuardedResolvedPrimitive)]+resolvePrimitive fileName = do+ prims <- decodeOrErr fileName <$> LZ.readFile fileName+ mapM (resolvePrimitive' fileName) prims++addGuards+ :: ResolvedPrimMap+ -> [(TS.Text, PrimitiveGuard ())]+ -> ResolvedPrimMap+addGuards = foldl go+ where+ lookupPrim :: TS.Text -> ResolvedPrimMap -> Maybe ResolvedPrimitive+ lookupPrim nm primMap = join (extractPrim <$> HashMapStrict.lookup nm primMap)++ go primMap (nm, guard) =+ HashMapStrict.insert+ nm+ (case (lookupPrim nm primMap, guard) of+ (Nothing, HasBlackBox _) ->+ error $ "No BlackBox definition for '" ++ TS.unpack nm ++ "' even"+ ++ " though this value was annotated with 'HasBlackBox'."+ (Nothing, WarnNonSynthesizable _ _) ->+ error $ "No BlackBox definition for '" ++ TS.unpack nm ++ "' even"+ ++ " though this value was annotated with 'WarnNonSynthesizable'"+ ++ ", implying it has a BlackBox."+ (Nothing, WarnAlways _ _) ->+ error $ "No BlackBox definition for '" ++ TS.unpack nm ++ "' even"+ ++ " though this value was annotated with 'WarnAlways'"+ ++ ", implying it has a BlackBox."+ (Just _, DontTranslate) ->+ error (TS.unpack nm ++ " was annotated with DontTranslate, but a "+ ++ "BlackBox definition was found anyway.")+ (Nothing, DontTranslate) -> DontTranslate+ (Just p, g) -> fmap (const p) g)+ primMap+ -- | Generate a set of primitives that are found in the primitive definition -- files in the given directories.-generatePrimMap :: [FilePath] -- ^ Directories to search for primitive definitions- -> IO (PrimMap Text)-generatePrimMap filePaths = do+generatePrimMap+ :: HasCallStack+ => [UnresolvedPrimitive]+ -- ^ unresolved primitives found in annotations (in LoadModules and+ -- LoadInterfaceFiles)+ -> [(TS.Text, PrimitiveGuard ())]+ -> [FilePath]+ -- ^ Directories to search for primitive definitions+ -> IO ResolvedPrimMap+generatePrimMap unresolvedPrims primGuards filePaths = do primitiveFiles <- fmap concat $ mapM (\filePath -> do fpExists <- Directory.doesDirectoryExist filePath@@ -48,8 +164,44 @@ return [] ) filePaths - primitives <- fmap concat $ mapM parsePrimitive primitiveFiles+ primitives0 <- concat <$> mapM resolvePrimitive primitiveFiles+ let metapaths = map (TS.unpack . name) unresolvedPrims+ primitives1 <- sequence $ zipWith resolvePrimitive' metapaths unresolvedPrims+ let primMap = HashMap.fromList (primitives0 ++ primitives1)+ return (force (addGuards primMap primGuards)) - let primMap = HashMap.fromList $ zip (map name primitives) primitives+-- | Determine what argument should be constant / literal+constantArgs :: TS.Text -> CompiledPrimitive -> Set.Set Int+constantArgs nm BlackBox {template = BBTemplate template} =+ Set.fromList (fromIntForce ++ concatMap (walkElement getConstant) template)+ where+ getConstant (Lit i) = Just i+ getConstant (Const i) = Just i+ getConstant _ = Nothing - return primMap+ -- Ensure that if the "Integer" arguments are constants, that they are reduced+ -- to literals, so that the buildin rules can properly fire.+ --+ -- Only in the the case that "Integer" arguments are truly variables should+ -- the blackbox rules fire.+ fromIntForce+ | nm == "Clash.Sized.Internal.BitVector.fromInteger#" = [2]+ | nm == "Clash.Sized.Internal.BitVector.fromInteger##" = [0,1]+ | nm == "Clash.Sized.Internal.Index.fromInteger#" = [1]+ | nm == "Clash.Sized.Internal.Signed.fromInteger#" = [1]+ | nm == "Clash.Sized.Internal.Unsigned.fromInteger#" = [1]+ -- There is a special code-path for `index_int` in the Verilog backend in+ -- case the index is a variable. But this code path only works when the+ -- vector is (a projection of) a variable. By forcing the arguments of+ -- index_int we can be sure that arguments are either:+ --+ -- Constant Variable+ -- Variable Constant+ -- Variable Variable+ --+ -- As all other cases would be reduced by the evaluator, and even expensive+ -- primitives under index_int are fully unrolled.+ | nm == "Clash.Sized.Vector.index_int" = [1,2]+ | nm == "Clash.Sized.Vector.replace_int" = [1,2]+ | otherwise = []+constantArgs _ _ = Set.empty
src/Clash/Rewrite/Combinators.hs view
@@ -7,91 +7,96 @@ -} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE ViewPatterns #-} -module Clash.Rewrite.Combinators where+module Clash.Rewrite.Combinators+ ( allR+ , (!->)+ , (>-!)+ , (>-!->)+ , (>->)+ , bottomupR+ , repeatR+ , topdownR + , whenR+ , bottomupWhenR+ )+ where+ import Control.DeepSeq (deepseq)-import Control.Monad ((<=<), (>=>))+import Control.Monad ((>=>)) import qualified Control.Monad.Writer as Writer import qualified Data.Monoid as Monoid-import Unbound.Generics.LocallyNameless (Embed, Fresh, bind, embed,- rec, unbind, unembed, unrec)-import Unbound.Generics.LocallyNameless.Unsafe (unsafeUnbind) -import Clash.Core.Term (Pat, Term (..))+import Clash.Core.Term (Term (..), CoreContext (..), primArg) import Clash.Core.Util (patIds)-import Clash.Core.Var (Id)+import Clash.Core.VarEnv+ (extendInScopeSet, extendInScopeSetList) import Clash.Rewrite.Types -- | Apply a transformation on the subtrees of an term-allR :: forall m . (Monad m, Fresh m)- => Bool -- ^ Freshen variable references in abstracted terms- -> Transform m -- ^ The transformation to apply to the subtrees- -> Transform m-allR _ _ _ (Var t x) = return (Var t x)-allR _ _ _ (Data dc) = return (Data dc)-allR _ _ _ (Literal l) = return (Literal l)-allR _ _ _ (Prim nm t) = return (Prim nm t)+allR+ :: forall m+ . Monad m+ => Transform m+ -- ^ The transformation to apply to the subtrees+ -> Transform m+allR trans (TransformContext is c) (Lam v e) =+ Lam v <$> trans (TransformContext (extendInScopeSet is v) (LamBody v:c)) e -allR rf trans c (Lam b) = do- (v,e) <- if rf then unbind b else return (unsafeUnbind b)- e' <- trans (LamBody v:c) e- return . Lam $ bind v e'+allR trans (TransformContext is c) (TyLam tv e) =+ TyLam tv <$> trans (TransformContext (extendInScopeSet is tv) (TyLamBody tv:c)) e -allR rf trans c (TyLam b) = do- (tv, e) <- if rf then unbind b else return (unsafeUnbind b)- e' <- trans (TyLamBody tv:c) e- return . TyLam $ bind tv e'+allR trans (TransformContext is c) (App e1 e2) = do+ e1' <- trans (TransformContext is (AppFun:c)) e1+ e2' <- trans (TransformContext is (AppArg (primArg e1') : c)) e2+ pure (App e1' e2') -allR _ trans c (App e1 e2) = do- e1' <- trans (AppFun:c) e1- e2' <- trans (AppArg:c) e2- return $ App e1' e2'+allR trans (TransformContext is c) (TyApp e ty) =+ TyApp <$> trans (TransformContext is (TyAppC:c)) e <*> pure ty -allR _ trans c (TyApp e ty) = do- e' <- trans (TyAppC:c) e- return $ TyApp e' ty+allR trans (TransformContext is c) (Cast e ty1 ty2) =+ Cast <$> trans (TransformContext is (CastBody:c)) e <*> pure ty1 <*> pure ty2 -allR _ trans c (Cast e ty1 ty2) = do- e' <- trans (CastBody:c) e- return $ Cast e' ty1 ty2+allR trans (TransformContext is c) (Letrec xes e) = do+ xes' <- traverse rewriteBind xes+ e' <- trans (TransformContext is' (LetBody bndrs:c)) e+ return (Letrec xes' e')+ where+ bndrs = map fst xes+ is' = extendInScopeSetList is (map fst xes)+ rewriteBind (b,e') = (b,) <$> trans (TransformContext is' (LetBinding b bndrs:c)) e' -allR rf trans c (Letrec b) = do- (xesR,e) <- if rf then unbind b else return (unsafeUnbind b)- let xes = unrec xesR- let bndrs = map fst xes- e' <- trans (LetBody bndrs:c) e- xes' <- mapM (rewriteBind bndrs) xes- return . Letrec $ bind (rec xes') e'- where- rewriteBind :: [Id] -> (Id,Embed Term) -> m (Id,Embed Term)- rewriteBind bndrs (b', e) = do- e' <- trans (LetBinding b' bndrs:c) (unembed e)- return (b',embed e')+allR trans (TransformContext is c) (Case scrut ty alts) =+ Case <$> trans (TransformContext is (CaseScrut:c)) scrut+ <*> pure ty+ <*> traverse rewriteAlt alts+ where+ rewriteAlt (p,e) =+ let (tvs,ids) = patIds p+ is' = extendInScopeSetList (extendInScopeSetList is tvs) ids+ in (p,) <$> trans (TransformContext is' (CaseAlt p : c)) e -allR rf trans c (Case scrut ty alts) = do- scrut' <- trans (CaseScrut:c) scrut- alts' <- if rf then mapM (fmap (uncurry bind) . rewriteAlt <=< unbind) alts- else mapM (fmap (uncurry bind) . rewriteAlt . unsafeUnbind) alts- return $ Case scrut' ty alts'- where- rewriteAlt :: (Pat, Term) -> m (Pat, Term)- rewriteAlt (p,e) = do- let (tvs,ids) = patIds p- e' <- trans (CaseAlt tvs ids:c) e- return (p,e')+allR trans (TransformContext is c) (Tick sp e) =+ Tick sp <$> trans (TransformContext is (TickC sp:c)) e +allR _ _ tm = pure tm+ infixr 6 >-> -- | Apply two transformations in succession (>->) :: Monad m => Transform m -> Transform m -> Transform m-(>->) r1 r2 c = r1 c >=> r2 c+(>->) = \r1 r2 c -> r1 c >=> r2 c+{-# INLINE (>->) #-} infixr 6 >-!-> -- | Apply two transformations in succession, and perform a deepseq in between. (>-!->) :: Monad m => Transform m -> Transform m -> Transform m-(>-!->) r1 r2 c e = do+(>-!->) = \r1 r2 c e -> do e' <- r1 c e deepseq e' (r2 c e')+{-# INLINE (>-!->) #-} {- Note [topdown repeatR]@@ -119,47 +124,39 @@ -- | Apply a transformation in a topdown traversal topdownR :: Rewrite m -> Rewrite m -- See Note [topdown repeatR]-topdownR r = repeatR r >-> allR True (topdownR r)---- | Apply a transformation in a topdown traversal. Doesn't freshen bound--- variables-unsafeTopdownR :: Rewrite m -> Rewrite m--- See NOTE [topdown repeatR]-unsafeTopdownR r = repeatR r >-> allR False (unsafeTopdownR r)+topdownR r = repeatR r >-> allR (topdownR r) -- | Apply a transformation in a bottomup traversal-bottomupR :: Fresh m => Transform m -> Transform m-bottomupR r = allR True (bottomupR r) >-> r---- | Apply a transformation in a bottomup traversal. Doesn't freshen bound--- variables-unsafeBottomupR :: Fresh m => Transform m -> Transform m-unsafeBottomupR r = allR False (unsafeBottomupR r) >-> r+bottomupR :: Monad m => Transform m -> Transform m+bottomupR r = allR (bottomupR r) >-> r infixr 5 !-> -- | Only apply the second transformation if the first one succeeds. (!->) :: Rewrite m -> Rewrite m -> Rewrite m-(!->) r1 r2 c expr = do+(!->) = \r1 r2 c expr -> do (expr',changed) <- Writer.listen $ r1 c expr if Monoid.getAny changed then r2 c expr' else return expr'+{-# INLINE (!->) #-} infixr 5 >-! -- | Only apply the second transformation if the first one fails. (>-!) :: Rewrite m -> Rewrite m -> Rewrite m-(>-!) r1 r2 c expr = do+(>-!) = \r1 r2 c expr -> do (expr',changed) <- Writer.listen $ r1 c expr if Monoid.getAny changed then return expr' else r2 c expr'+{-# INLINE (>-!) #-} -- | Keep applying a transformation until it fails. repeatR :: Rewrite m -> Rewrite m-repeatR r = r !-> repeatR r+repeatR = let go r = r !-> repeatR r in go+{-# INLINE repeatR #-} whenR :: Monad m- => ([CoreContext] -> Term -> m Bool)+ => (TransformContext -> Term -> m Bool) -> Transform m -> Transform m whenR f r1 ctx expr = do@@ -169,12 +166,13 @@ else return expr -- | Only traverse downwards when the assertion evaluates to true-bottomupWhenR :: Fresh m- => ([CoreContext] -> Term -> m Bool)- -> Transform m- -> Transform m+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 True (bottomupWhenR f r) >-> r) ctx expr+ then (allR (bottomupWhenR f r) >-> r) ctx expr else r ctx expr
src/Clash/Rewrite/Types.hs view
@@ -8,55 +8,60 @@ Type and instance definitions for Rewrite modules -} +{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-} module Clash.Rewrite.Types where import Control.Concurrent.Supply (Supply, freshId)-import Control.Lens (use, (.=), (<<%=))-import Control.Monad+import Control.DeepSeq (NFData)+import Control.Lens (use, (.=))+#if !MIN_VERSION_base(4,13,0)+import Control.Monad.Fail (MonadFail(fail))+#endif import Control.Monad.Fix (MonadFix (..), fix) import Control.Monad.Reader (MonadReader (..)) import Control.Monad.State (MonadState (..))+import Control.Monad.State.Strict (State) import Control.Monad.Writer (MonadWriter (..))-import Data.HashMap.Strict (HashMap)-import Data.HashSet (HashSet)+import Data.Binary (Binary)+import Data.Hashable (Hashable) import Data.IntMap.Strict (IntMap) import Data.Monoid (Any)-import Unbound.Generics.LocallyNameless (Fresh (..))-import Unbound.Generics.LocallyNameless.Name (Name (..))--import SrcLoc (SrcSpan)+import GHC.Generics import Clash.Core.Evaluator (GlobalHeap, PrimEvaluator)-import Clash.Core.Term (Term, TmName, TmOccName)+import Clash.Core.Term (Term, Context) import Clash.Core.Type (Type)-import Clash.Core.TyCon (TyCon, TyConName, TyConOccName)-import Clash.Core.Var (Id, TyVar)+import Clash.Core.TyCon (TyConName, TyConMap)+import Clash.Core.Var (Id)+import Clash.Core.VarEnv (InScopeSet, VarSet) import Clash.Driver.Types (BindingMap, DebugLevel)-import Clash.Netlist.Types (HWType)+import Clash.Netlist.Types (FilteredHWType, HWMap) import Clash.Util --- | Context in which a term appears-data CoreContext- = AppFun -- ^ Function position of an application- | AppArg -- ^ Argument position of an application- | TyAppC -- ^ Function position of a type application- | LetBinding Id [Id] -- ^ RHS of a Let-binder with the sibling LHS'- | LetBody [Id] -- ^ Body of a Let-binding with the bound LHS'- | LamBody Id -- ^ Body of a lambda-term with the abstracted variable- | TyLamBody TyVar -- ^ Body of a TyLambda-term with the abstracted- -- type-variable- | CaseAlt [TyVar] [Id]- -- ^ RHS of a case-alternative with the variables bound by- -- the pattern on the LHS- | CaseScrut -- ^ Subject of a case-decomposition- | CastBody -- ^ Body of a Cast- deriving (Eq,Show)+import Clash.Annotations.BitRepresentation.Internal (CustomReprs) +-- | State used by the inspection mechanism for recording rewrite steps.+data RewriteStep+ = RewriteStep+ { t_ctx :: Context+ -- ^ current context+ , t_name :: String+ -- ^ Name of the transformation+ , t_bndrS :: String+ -- ^ Name of the current binder+ , t_before :: Term+ -- ^ Term before `apply`+ , t_after :: Term+ -- ^ Term after `apply`+ } deriving (Show, Generic, NFData, Hashable, Binary)+ -- | State of a rewriting session data RewriteState extra = RewriteState@@ -66,7 +71,7 @@ -- ^ Global binders , _uniqSupply :: !Supply -- ^ Supply of unique numbers- , _curFun :: (TmName,SrcSpan) -- Initially set to undefined: no strictness annotation+ , _curFun :: (Id,SrcSpan) -- Initially set to undefined: no strictness annotation -- ^ Function which is currently normalized , _nameCounter :: {-# UNPACK #-} !Int -- ^ Used for 'Fresh'@@ -78,26 +83,26 @@ makeLenses ''RewriteState -- -- | Read-only environment of a rewriting session data RewriteEnv = RewriteEnv { _dbgLevel :: DebugLevel -- ^ Lvl at which we print debugging messages- , _typeTranslator :: HashMap TyConOccName TyCon -> Bool -> Type- -> Maybe (Either String HWType)- -- ^ Hardcode Type -> HWType translator- , _tcCache :: HashMap TyConOccName TyCon+ , _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 :: PrimEvaluator -- ^ Hardcoded evaluator (delta-reduction)}- , _allowZero :: Bool- -- ^ Zero bit wide things are representable- , _topEntities :: HashSet TmOccName+ , _topEntities :: VarSet -- ^ Functions that are considered TopEntities+ , _customReprs :: CustomReprs+ -- ^ Custom bit representations } makeLenses ''RewriteEnv@@ -106,33 +111,47 @@ -- generate fresh variables and unique identifiers. In addition, it keeps track -- if a transformation/rewrite has been successfully applied. newtype RewriteMonad extra a = R- { runR :: RewriteEnv -> RewriteState extra -> (a,RewriteState extra,Any) }+ { unR :: RewriteEnv -> RewriteState extra -> Any -> (a,RewriteState extra,Any) } +-- | 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 -> case runR m r s of (a,s',w) -> (f a,s',w))+ 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 = return- (<*>) = ap+ 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 -> (a, s, mempty))- m >>= k = R (\r s -> case runR m r s of- (a,s',w) -> case runR (k a) r s' of- (b,s'',w') -> let w'' = mappend w w'- in seq w'' (b,s'',w''))+ 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 (>>=) #-} -instance MonadState (RewriteState extra) (RewriteMonad extra) where- get = R (\_ s -> (s,s,mempty))- put s = R (\_ _ -> ((),s,mempty))- state f = R (\_ s -> case f s of (a,s') -> (a,s',mempty)) -instance Fresh (RewriteMonad extra) where- fresh (Fn s _) = do- n <- nameCounter <<%= (+1)- let n' = toInteger n- n' `seq` return (Fn s n')- fresh nm@(Bn {}) = return nm+instance MonadState (RewriteState extra) (RewriteMonad extra) where+ get = R $ \_ s w -> (s,s,w)+ {-# INLINE get #-}+ put s = R $ \_ _ w -> ((),s,w)+ {-# INLINE put #-}+ state f = R $ \_ s w -> case f s of (a,s') -> (a,s',w)+ {-# INLINE state #-} instance MonadUnique (RewriteMonad extra) where getUniqueM = do@@ -142,21 +161,42 @@ a `seq` return a instance MonadWriter Any (RewriteMonad extra) where- writer (a,w) = R (\_ s -> (a,s,w))- tell w = R (\_ s -> ((),s,w))- listen m = R (\r s -> case runR m r s of (a,s',w) -> ((a,w),s',w))- pass m = R (\r s -> case runR m r s of ((a,f),s',w) -> (a, s', f w))+ writer (a,w') = R $ \_ s w -> let wt = w `mappend` w' in wt `seq` (a,s,wt)+ {-# INLINE writer #-}+ tell w' = R $ \_ s w -> let wt = w `mappend` w' in wt `seq` ((),s,wt)+ {-# 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)+ {-# 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)+ {-# 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 -> (r,s,mempty))- local f m = R (\r s -> runR m (f r) s)- reader f = R (\r s -> (f r,s,mempty))+ ask = R $ \r s w -> (r,s,w)+ {-# INLINE ask #-}+ local f m = R $ \r s w -> unR m (f r) s w+ {-# INLINE local #-}+ reader f = R $ \r s w -> (f r,s,w)+ {-# INLINE reader #-} instance MonadFix (RewriteMonad extra) where- mfix f = R (\r s -> fix $ \ ~(a,_,_) -> runR (f a) r s)+ mfix f = R $ \r s w -> fix $ \ ~(a,_,_) -> unR (f a) r s w+ {-# INLINE mfix #-} +data TransformContext+ = TransformContext+ { tfInScope :: !InScopeSet+ , tfContext :: Context+ }+ -- | Monadic action that transforms a term given a certain context-type Transform m = [CoreContext] -> Term -> m Term+type Transform m = TransformContext -> Term -> m Term -- | A 'Transform' action in the context of the 'RewriteMonad' type Rewrite extra = Transform (RewriteMonad extra)
src/Clash/Rewrite/Util.hs view
@@ -8,134 +8,250 @@ Utilities for rewriting: e.g. inlining, specialisation, etc. -} +{-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE NondecreasingIndentation #-}+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE Rank2Types #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE ViewPatterns #-} +{-# OPTIONS_GHC -Wno-unused-imports #-}+ module Clash.Rewrite.Util where import Control.DeepSeq import Control.Exception (throw) import Control.Lens- (Lens', (%=), (+=), (^.), _2, _4, _5, _Left)+ (Lens', (%=), (+=), (^.), _3, _4, _Left) 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 import qualified Control.Monad.Writer as Writer import Data.Bifunctor (bimap)-import Data.HashMap.Strict (HashMap)-import qualified Data.HashMap.Lazy as HML-import qualified Data.HashMap.Strict as HMS-import qualified Data.HashSet as HashSet-import qualified Data.List as List+import Data.Coerce (coerce)+import Data.Functor.Const (Const (..))+import Data.List (group, sort) import qualified Data.Map as Map import Data.Maybe (catMaybes,isJust,mapMaybe) import qualified Data.Monoid as Monoid import qualified Data.Set as Set import qualified Data.Set.Lens as Lens-import Unbound.Generics.LocallyNameless- (Fresh, bind, embed, rebind, rec, unbind, unembed, unrec)-import qualified Unbound.Generics.LocallyNameless as Unbound-import Unbound.Generics.LocallyNameless.Unsafe (unsafeUnbind)+import Data.Text (Text)+import qualified Data.Text as Text +#ifdef HISTORY+import Data.Binary (encode)+import qualified Data.ByteString as BS+import qualified Data.ByteString.Lazy as BL+import System.IO.Unsafe (unsafePerformIO)+#endif+ import BasicTypes (InlineSpec (..))-import SrcLoc (SrcSpan) -import Clash.Core.DataCon (dataConInstArgTys)-import Clash.Core.FreeVars (termFreeIds, termFreeTyVars,- typeFreeVars)+import Clash.Core.DataCon (dcExtTyVars)+import Clash.Core.FreeVars+ (freeLocalVars, hasLocalFreeVars, localIdDoesNotOccurIn, localIdOccursIn,+ typeFreeVars, termFreeVars', freeIds) import Clash.Core.Name-import Clash.Core.Pretty (showDoc)-import Clash.Core.Subst (substTm)+import Clash.Core.Pretty (showPpr)+import Clash.Core.Subst+ (aeqTerm, aeqType, extendIdSubst, mkSubst, substTm) import Clash.Core.Term- (LetBinding, Pat (..), Term (..), TmName, TmOccName)+ (LetBinding, Pat (..), Term (..), CoreContext (..), Context, PrimInfo (..),+ TmName, WorkInfo (..), TickInfo, collectArgs, collectArgsTicks) import Clash.Core.TyCon- (TyCon, TyConOccName, tyConDataCons)+ (TyConMap, tyConDataCons) import Clash.Core.Type (KindOrType, Type (..),- TypeView (..), coreView,+ TypeView (..), coreView1, normalizeType,- typeKind, tyView)+ typeKind, tyView, isPolyFunTy) import Clash.Core.Util- (Delta, Gamma, collectArgs, isPolyFun, mkAbstraction, mkApps, mkId, mkLams,- mkTmApps, mkTyApps, mkTyLams, mkTyVar, termType)-import Clash.Core.Var (Id, TyVar, Var (..))+ (isPolyFun, mkAbstraction, mkApps, mkLams, mkTicks,+ mkTmApps, mkTyApps, mkTyLams, termType, dataConInstArgTysE, isClockOrReset)+import Clash.Core.Var+ (Id, IdScope (..), TyVar, Var (..), isLocalId, mkGlobalId, mkLocalId, mkTyVar)+import Clash.Core.VarEnv+ (InScopeSet, VarEnv, elemVarSet, extendInScopeSetList, mkInScopeSet,+ notElemVarEnv, uniqAway) import Clash.Driver.Types- (ClashException (..), DebugLevel (..))+ (DebugLevel (..)) import Clash.Netlist.Util (representableType) import Clash.Rewrite.Types+import Clash.Unique import Clash.Util -- | Lift an action working in the '_extra' state to the 'RewriteMonad' zoomExtra :: State.State extra a -> RewriteMonad extra a-zoomExtra m = R (\_ s -> case State.runState m (s ^. extra) of- (a,s') -> (a,s {_extra = s'},mempty))+zoomExtra m = R (\_ s w -> case State.runState m (s ^. extra) of+ (a,s') -> (a,s {_extra = s'},w)) --- | Record if a transformation is succesfully applied-apply :: String -- ^ Name of the transformation- -> Rewrite extra -- ^ Transformation to be applied- -> Rewrite extra-apply name rewrite ctx expr = do+-- | Some transformations might erroneously introduce shadowing. For example,+-- a transformation might result in:+--+-- let a = ...+-- b = ...+-- a = ...+--+-- where the last 'a', shadows the first, while Clash assumes that this can't+-- happen. This function finds those constructs and a list of found duplicates.+--+findAccidentialShadows :: Term -> [[Id]]+findAccidentialShadows =+ \case+ Var {} -> []+ Data {} -> []+ Literal {} -> []+ Prim {} -> []+ Lam _ t -> findAccidentialShadows t+ TyLam _ t -> findAccidentialShadows t+ App t1 t2 -> concatMap findAccidentialShadows [t1, t2]+ TyApp t _ -> findAccidentialShadows t+ Cast t _ _ -> findAccidentialShadows t+ Tick _ t -> findAccidentialShadows t+ Case t _ as ->+ concatMap (findInPat . fst) as +++ concatMap findAccidentialShadows (t : map snd as)+ Letrec bs t ->+ findDups (map fst bs) ++ findAccidentialShadows t++ where+ findInPat :: Pat -> [[Id]]+ findInPat (LitPat _) = []+ findInPat (DefaultPat) = []+ findInPat (DataPat _ _ ids) = findDups ids++ findDups :: [Id] -> [[Id]]+ findDups ids = filter ((1 <) . length) (group (sort ids))+++-- | Record if a transformation is successfully applied+apply+ :: String+ -- ^ Name of the transformation+ -> Rewrite extra+ -- ^ Transformation to be applied+ -> Rewrite extra+apply = \s rewrite ctx expr0 -> do lvl <- Lens.view dbgLevel- let before = showDoc expr- (expr', anyChanged) <- traceIf (lvl >= DebugAll) ("Trying: " ++ name ++ " on:\n" ++ before) $ Writer.listen $ rewrite ctx expr+ (expr1,anyChanged) <- Writer.listen (rewrite ctx expr0) let hasChanged = Monoid.getAny anyChanged- Monad.when hasChanged $ transformCounter += 1- let after = showDoc expr'- let expr'' = if hasChanged then expr' else expr+ !expr2 = if hasChanged then expr1 else expr0+ Monad.when hasChanged (transformCounter += 1)+#ifdef HISTORY+ -- NB: When HISTORY is on, emit binary data holding the recorded rewrite steps+ Monad.when hasChanged $ do+ (curBndr, _) <- Lens.use curFun+ let !_ = unsafePerformIO+ $ BS.appendFile "history.dat"+ $ BL.toStrict+ $ encode RewriteStep+ { t_ctx = tfContext ctx+ , t_name = s+ , t_bndrS = showPpr (varName curBndr)+ , t_before = expr0+ , t_after = expr1+ }+ return ()+#endif+ if lvl == DebugNone+ then return expr2+ else applyDebug lvl s expr0 hasChanged expr2+{-# INLINE apply #-} +applyDebug+ :: DebugLevel+ -- ^ The current debugging level+ -> String+ -- ^ Name of the transformation+ -> Term+ -- ^ Original expression+ -> Bool+ -- ^ Whether the rewrite indicated change+ -> Term+ -- ^ New expression+ -> RewriteMonad extra Term+applyDebug lvl name exprOld hasChanged exprNew =+ traceIf (lvl >= DebugAll) ("Trying: " ++ name ++ " on:\n" ++ before) $ do Monad.when (lvl > DebugNone && hasChanged) $ do tcm <- Lens.view tcCache- beforeTy <- termType tcm expr- let beforeFTV = Lens.setOf termFreeTyVars expr- beforeFV <- Lens.setOf <$> localFreeIds <*> pure expr- afterTy <- termType tcm expr'- let afterFTV = Lens.setOf termFreeTyVars expr- afterFV <- Lens.setOf <$> localFreeIds <*> pure expr'- let newFV = Set.size afterFTV > Set.size beforeFTV ||- Set.size afterFV > Set.size beforeFV+ 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+ Monad.when newFV $ error ( concat [ $(curLoc) , "Error when applying rewrite ", name , " to:\n" , before , "\nResult:\n" ++ after ++ "\n"- , "Changes free variables from: ", show (beforeFTV,beforeFV)- , "\nto: ", show (afterFTV,afterFV)+ , "It introduces free variables."+ , "\nBefore: " ++ showPpr (Set.toList beforeFV)+ , "\nAfter: " ++ showPpr (Set.toList afterFV) ] )- traceIf (lvl >= DebugAll && beforeTy /= afterTy)+ 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 >= DebugAll && (beforeTy `aeqType` afterTy)) ( concat [ $(curLoc) , "Error when applying rewrite ", name , " to:\n" , before , "\nResult:\n" ++ after ++ "\n"- , "Changes type from:\n", showDoc beforeTy- , "\nto:\n", showDoc afterTy+ , "Changes type from:\n", showPpr beforeTy+ , "\nto:\n", showPpr afterTy ] ) (return ()) - Monad.when (lvl >= DebugApplied && not hasChanged && expr /= expr') $- error $ $(curLoc) ++ "Expression changed without notice(" ++ name ++ "): before" ++ before ++ "\nafter:\n" ++ after+ Monad.when (lvl >= DebugApplied && not hasChanged && not (exprOld `aeqTerm` exprNew)) $+ error $ $(curLoc) ++ "Expression changed without notice(" ++ name ++ "): before"+ ++ before ++ "\nafter:\n" ++ after traceIf (lvl >= DebugName && hasChanged) name $- 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 expr''+ 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 -- | Perform a transformation on a Term-runRewrite :: String -- ^ Name of the transformation- -> Rewrite extra -- ^ Transformation to perform- -> Term -- ^ Term to transform- -> RewriteMonad extra Term-runRewrite name rewrite expr = apply name rewrite [] expr+runRewrite+ :: String+ -- ^ Name of the transformation+ -> InScopeSet+ -> Rewrite extra+ -- ^ Transformation to perform+ -> Term+ -- ^ Term to transform+ -> RewriteMonad extra Term+runRewrite name is rewrite expr = apply name rewrite (TransformContext is []) expr --- | Evaluate a RewriteSession to its inner monad+-- | Evaluate a RewriteSession to its inner monad. runRewriteSession :: RewriteEnv -> RewriteState extra -> RewriteMonad extra a -> a-runRewriteSession r s m = traceIf True ("Applied " +++runRewriteSession r s m = traceIf True ("Clash: Applied " ++ show (s' ^. transformCounter) ++ " transformations") a@@ -153,108 +269,74 @@ Writer.tell (Monoid.Any True) return val --- | Create a type and kind context out of a transformation context-contextEnv :: [CoreContext]- -> (Gamma, Delta)-contextEnv = go HML.empty HML.empty- where- go gamma delta [] = (gamma,delta)- go gamma delta (LetBinding _ ids:ctx) = go gamma' delta ctx- where- gamma' = foldl addToGamma gamma ids-- go gamma delta (LetBody ids:ctx) = go gamma' delta ctx- where- gamma' = foldl addToGamma gamma ids-- go gamma delta (LamBody lId:ctx) = go gamma' delta ctx- where- gamma' = addToGamma gamma lId-- go gamma delta (TyLamBody tv:ctx) = go gamma delta' ctx- where- delta' = addToDelta delta tv-- go gamma delta (CaseAlt tvs ids:ctx) = go gamma' delta' ctx- where- gamma' = foldl addToGamma gamma ids- delta' = foldl addToDelta delta tvs-- go gamma delta (_:ctx) = go gamma delta ctx-- addToGamma gamma (Id idName ty) = HML.insert (nameOcc idName) (unembed ty) gamma- addToGamma _ _ = error $ $(curLoc) ++ "Adding TyVar to Gamma"-- addToDelta delta (TyVar tvName ki) = HML.insert (nameOcc tvName) (unembed ki) delta- addToDelta _ _ = error $ $(curLoc) ++ "Adding Id to Delta"--closestLetBinder :: [CoreContext] -> Maybe Id+closestLetBinder :: Context -> Maybe Id closestLetBinder [] = Nothing closestLetBinder (LetBinding id_ _:_) = Just id_ closestLetBinder (_:ctx) = closestLetBinder ctx -mkDerivedName :: [CoreContext] -> String -> TmName-mkDerivedName ctx sf = case closestLetBinder ctx of- Just id_ -> appendToName (varName id_) ('_':sf)- _ -> string2InternalName sf---- | Create a complete type and kind context out of the global binders and the--- transformation context-mkEnv :: [CoreContext]- -> RewriteMonad extra (Gamma, Delta)-mkEnv ctx = do- let (gamma,delta) = contextEnv ctx- tsMap <- fmap (HML.map (^. _2)) $ Lens.use bindings- let gamma' = tsMap `HML.union` gamma- return (gamma',delta)+mkDerivedName :: TransformContext -> OccName -> TmName+mkDerivedName (TransformContext _ ctx) sf = case closestLetBinder ctx of+ Just id_ -> appendToName (varName id_) ('_' `Text.cons` sf)+ _ -> mkUnsafeInternalName sf 0 -- | Make a new binder and variable reference for a term-mkTmBinderFor :: (Fresh m, MonadUnique m)- => HashMap TyConOccName TyCon -- ^ TyCon cache- -> Name a -- ^ Name of the new binder- -> Term -- ^ Term to bind- -> m (Id, Term)-mkTmBinderFor tcm name e = do- (Left r) <- mkBinderFor tcm name (Left e)+mkTmBinderFor+ :: (Monad m, MonadUnique m, MonadFail 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 -- | Make a new binder and variable reference for either a term or a type-mkBinderFor :: (Monad m, MonadUnique m, Fresh m)- => HashMap TyConOccName TyCon -- ^ TyCon cache- -> Name a -- ^ Name of the new binder- -> Either Term Type -- ^ Type or Term to bind- -> m (Either (Id,Term) (TyVar,Type))-mkBinderFor tcm name (Left term) =- Left <$> (mkInternalVar (coerceName name) =<< termType tcm term)+mkBinderFor+ :: (Monad m, MonadUnique m, MonadFail m)+ => InScopeSet+ -> TyConMap -- ^ TyCon cache+ -> Name a -- ^ Name of the new binder+ -> Either Term Type -- ^ Type or Term to bind+ -> m (Either Id TyVar)+mkBinderFor is tcm name (Left term) = do+ name' <- cloneName name+ let ty = termType tcm term+ return (Left (uniqAway is (mkLocalId ty (coerce name')))) -mkBinderFor tcm name (Right ty) = do- name' <- cloneVar (coerceName name)- let kind = typeKind tcm ty- return $ Right (TyVar name' (embed kind), VarTy kind name')+mkBinderFor is tcm name (Right ty) = do+ name' <- cloneName name+ let ki = typeKind tcm ty+ return (Right (uniqAway is (mkTyVar ki (coerce name')))) --- | Make a new, unique, identifier and corresponding variable reference-mkInternalVar :: (Monad m, MonadUnique m)- => TmName -- ^ Name of the identifier- -> KindOrType- -> m (Id,Term)-mkInternalVar name ty = do- name' <- cloneVar name- return (Id name' (embed ty),Var ty name')+-- | Make a new, unique, identifier+mkInternalVar+ :: (Monad m, MonadUnique m)+ => InScopeSet+ -> OccName+ -- ^ Name of the identifier+ -> KindOrType+ -> m Id+mkInternalVar inScope name ty = do+ i <- getUniqueM+ let nm = mkUnsafeInternalName name i+ return (uniqAway inScope (mkLocalId ty nm)) -- | Inline the binders in a let-binding that have a certain property-inlineBinders :: (Term -> LetBinding -> RewriteMonad extra Bool) -- ^ Property test- -> Rewrite extra-inlineBinders condition _ expr@(Letrec b) = do- (xes,res) <- unbind b- let expr' = Letrec (bind xes res)- (replace,others) <- partitionM (condition expr') (unrec xes)+inlineBinders+ :: (Term -> LetBinding -> RewriteMonad extra Bool)+ -- ^ Property test+ -> Rewrite extra+inlineBinders condition (TransformContext inScope0 _) expr@(Letrec xes res) = do+ (replace,others) <- partitionM (condition expr) xes case replace of [] -> return expr _ -> do- let (others',res') = substituteBinders replace others res+ let inScope1 = extendInScopeSetList inScope0 (map fst xes)+ (others',res') = substituteBinders inScope1 replace others res newExpr = case others' of [] -> res'- _ -> Letrec (bind (rec others') res')+ _ -> Letrec others' res' changed newExpr @@ -277,34 +359,31 @@ tailCalls :: Id -- ^ Function to check -> Term -- ^ Expression to check it in -> Maybe Int-tailCalls id_ expr = case expr of- Var _ nm | varName id_ == nm -> Just 1- | otherwise -> Just 0- Lam b -> let (_,expr') = unsafeUnbind b- in tailCalls id_ expr'- TyLam b -> let (_,expr') = unsafeUnbind b- in tailCalls id_ expr'+tailCalls id_ = \case+ Var nm | id_ == nm -> Just 1+ | otherwise -> Just 0+ Lam _ e -> tailCalls id_ e+ TyLam _ e -> tailCalls id_ e App l r -> case tailCalls id_ r of Just 0 -> tailCalls id_ l _ -> Nothing TyApp l _ -> tailCalls id_ l- Letrec b ->- let (bsR,expr') = unsafeUnbind b- (bsIds,bsExprs) = unzip (unrec bsR)- bsTls = map (tailCalls id_ . unembed) bsExprs+ Letrec bs e ->+ let (bsIds,bsExprs) = unzip bs+ bsTls = map (tailCalls id_) bsExprs bsIdsUsed = mapMaybe (\(l,r) -> pure l <* r) (zip bsIds bsTls)- bsIdsTls = map (`tailCalls` expr') bsIdsUsed+ bsIdsTls = map (`tailCalls` e) bsIdsUsed bsCount = pure . sum $ catMaybes bsTls in case (all isJust bsTls) of False -> Nothing True -> case (all (==0) $ catMaybes bsTls) of False -> case all isJust bsIdsTls of False -> Nothing- True -> (+) <$> bsCount <*> tailCalls id_ expr'- True -> tailCalls id_ expr'+ True -> (+) <$> bsCount <*> tailCalls id_ e+ True -> tailCalls id_ e Case scrut _ alts -> let scrutTl = tailCalls id_ scrut- altsTl = map (tailCalls id_ . snd . unsafeUnbind) alts+ altsTl = map (tailCalls id_ . snd) alts in case scrutTl of Just 0 | all (/= Nothing) altsTl -> Just (sum (catMaybes altsTl)) _ -> Nothing@@ -317,75 +396,116 @@ -- i.e. is a wrapper around a (partially) applied function 'f', where the -- introduced argument 'w' is not used by 'f' isVoidWrapper :: Term -> Bool-isVoidWrapper (Lam b) = case unsafeUnbind b of- (bndr,e@(collectArgs -> (Var _ _,_)))- -> nameOcc (varName bndr) `notElem` Lens.toListOf termFreeIds e- _ -> False+isVoidWrapper (Lam bndr e@(collectArgs -> (Var _,_))) =+ bndr `localIdDoesNotOccurIn` e isVoidWrapper _ = False -- | Substitute the RHS of the first set of Let-binders for references to the -- first set of Let-binders in: the second set of Let-binders and the additional -- term-substituteBinders :: [LetBinding] -- ^ Let-binders to substitute- -> [LetBinding] -- ^ Let-binders where substitution takes place- -> Term -- ^ Expression where substitution takes place- -> ([LetBinding],Term)-substituteBinders [] others res = (others,res)-substituteBinders ((bndr,valE):rest) others res = substituteBinders rest' others' res'- where- val = unembed valE- bndrName = nameOcc (varName bndr)- selfRef = bndrName `elem` Lens.toListOf termFreeIds val- (res',rest',others') = if selfRef- then (res,rest,(bndr,valE):others)- else ( substTm bndrName val res- , map (second ( embed- . substTm bndrName val- . unembed)- ) rest- , map (second ( embed- . substTm bndrName val- . unembed)- ) others- )+substituteBinders+ :: InScopeSet+ -> [LetBinding]+ -- ^ Let-binders to substitute+ -> [LetBinding]+ -- ^ Let-binders where substitution takes place+ -> Term+ -- ^ Expression where substitution takes place+ -> ([LetBinding],Term)+substituteBinders _ [] others res = (others,res)+substituteBinders inScope ((bndr,val):rest) others res =+ substituteBinders inScope rest' others' res'+ where+ subst = extendIdSubst (mkSubst inScope) bndr val+ selfRef = bndr `localIdOccursIn` val+ (res',rest',others') = if selfRef+ then (res,rest,(bndr,val):others)+ else ( substTm "substituteBindersRes" subst res+ , map (second (substTm "substituteBindersRest" subst)) rest+ , map (second (substTm "substituteBindersOthers" subst)) others+ ) --- | Calculate the /local/ free variable of an expression: the free variables--- that are not bound in the global environment.-localFreeIds :: (Applicative f, Lens.Contravariant f)- => RewriteMonad extra ((TmOccName -> f TmOccName) -> Term -> f Term)-localFreeIds = do- globalBndrs <- Lens.use bindings- return ((termFreeIds . Lens.filtered (not . (`HML.member` globalBndrs))))+-- | Determine whether a term does any work, i.e. adds to the size of the circuit+isWorkFree+ :: Term+ -> Bool+isWorkFree (collectArgs -> (fun,args)) = case fun of+ Var i -> isLocalId i && not (isPolyFunTy (varType i))+ Data {} -> all isWorkFreeArg args+ Literal {} -> True+ Prim _ pInfo -> case primWorkInfo pInfo of+ WorkConstant -> True -- We can ignore the arguments, because this+ -- primitive outputs a constant regardless of its+ -- arguments+ WorkNever -> all isWorkFreeArg args+ WorkVariable -> all isConstantArg args+ WorkAlways -> False -- Things like clock or reset generator always+ -- perform work+ Lam _ e -> isWorkFree e && all isWorkFreeArg args+ TyLam _ e -> isWorkFree e && all isWorkFreeArg args+ Letrec bs e ->+ isWorkFree e && all (isWorkFree . snd) bs && all isWorkFreeArg args+ Case s _ [(_,a)] -> isWorkFree s && isWorkFree a && all isWorkFreeArg args+ Cast e _ _ -> isWorkFree e && all isWorkFreeArg args+ _ -> False+ where+ isWorkFreeArg = either isWorkFree (const True)+ isConstantArg = either isConstant (const True) -inlineOrLiftBinders :: (LetBinding -> RewriteMonad extra Bool) -- ^ Property test- -> (Term -> LetBinding -> RewriteMonad extra Bool)- -- ^ Test whether to lift or inline- --- -- * True: inline- -- * False: lift- -> Rewrite extra-inlineOrLiftBinders condition inlineOrLift ctx expr@(Letrec b) = do- (xesR,res) <- unbind b- let xes = unrec xesR+isFromInt :: Text -> Bool+isFromInt nm = nm == "Clash.Sized.Internal.BitVector.fromInteger##" ||+ nm == "Clash.Sized.Internal.BitVector.fromInteger#" ||+ nm == "Clash.Sized.Internal.Index.fromInteger#" ||+ nm == "Clash.Sized.Internal.Signed.fromInteger#" ||+ nm == "Clash.Sized.Internal.Unsigned.fromInteger#"++-- | Determine if a term represents a constant+isConstant :: Term -> Bool+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)+ (Literal _,_) -> True+ _ -> False++isConstantNotClockReset+ :: Term+ -> RewriteMonad extra Bool+isConstantNotClockReset e = do+ tcm <- Lens.view tcCache+ let eTy = termType tcm e+ if isClockOrReset tcm eTy+ then case collectArgs e of+ (Prim nm _,_) -> return (nm == "Clash.Transformations.removedArg")+ _ -> return False+ else pure (isConstant e)++inlineOrLiftBinders+ :: (LetBinding -> RewriteMonad extra Bool)+ -- ^ Property test+ -> (Term -> LetBinding -> RewriteMonad extra Bool)+ -- ^ Test whether to lift or inline+ --+ -- * True: inline+ -- * False: lift+ -> Rewrite extra+inlineOrLiftBinders condition inlineOrLift (TransformContext inScope0 _) expr@(Letrec xes res) = do (replace,others) <- partitionM condition xes case replace of [] -> return expr _ -> do- -- Because 'unbind b' refreshes binders in xes, we must recreate- -- the let expression, and _not_ reuse 'expr'- let expr' = Letrec (bind xesR res)- (doInline,doLift) <- partitionM (inlineOrLift expr') replace+ let inScope1 = extendInScopeSetList inScope0 (map fst xes)+ (doInline,doLift) <- partitionM (inlineOrLift expr) replace -- We first substitute the binders that we can inline both the binders -- that we intend to lift, the other binders, and the body- let (others',res') = substituteBinders doInline (doLift ++ others) res+ let (others',res') = substituteBinders inScope1 doInline (doLift ++ others) res (doLift',others'') = splitAt (length doLift) others'- (gamma,delta) <- mkEnv (LetBinding undefined (map fst xes) : ctx)- doLift'' <- mapM (liftBinding gamma delta) doLift'+ doLift'' <- mapM liftBinding doLift' -- We then substitute the lifted binders in the other binders and the body- let (others3,res'') = substituteBinders doLift'' others'' res'+ let (others3,res'') = substituteBinders inScope1 doLift'' others'' res' newExpr = case others3 of [] -> res''- _ -> Letrec (bind (rec others3) res'')+ _ -> Letrec others3 res'' changed newExpr inlineOrLiftBinders _ _ _ e = return e@@ -393,47 +513,51 @@ -- | Create a global function for a Let-binding and return a Let-binding where -- the RHS is a reference to the new global function applied to the free -- variables of the original RHS-liftBinding :: Gamma- -> Delta- -> LetBinding+liftBinding :: LetBinding -> RewriteMonad extra LetBinding-liftBinding gamma delta (Id idName tyE,eE) = do- let e = unembed eE+liftBinding (var@Id {varName = idName} ,e) = do -- Get all local FVs, excluding the 'idName' from the let-binding- let localFTVs = map (\nm -> Name Internal nm noSrcSpan)- . List.nub $ Lens.toListOf termFreeTyVars e- localFVs <- map (\nm -> Name Internal nm noSrcSpan) . List.nub <$>- (Lens.toListOf <$> localFreeIds <*> pure e)- let localFTVkinds = map (\k -> HML.lookupDefault (error $ $(curLoc) ++ show k ++ " not found") (nameOcc k) delta) localFTVs- localFVs' = filter ((/= (nameOcc idName)) . nameOcc) localFVs- localFVtys' = map (\k -> HML.lookupDefault (error $ $(curLoc) ++ show k ++ " not found") (nameOcc k) gamma) localFVs'- -- Abstract expression over its local FVs- boundFTVs = zipWith mkTyVar localFTVkinds localFTVs- boundFVs = zipWith mkId localFVtys' localFVs'+ let unitFV :: Var a -> Const (UniqSet TyVar,UniqSet Id) (Var a)+ unitFV v@(Id {}) = Const (emptyUniqSet,unitUniqSet (coerce v))+ unitFV v@(TyVar {}) = Const (unitUniqSet (coerce v),emptyUniqSet)++ interesting :: Var a -> Bool+ interesting Id {idScope = GlobalId} = False+ interesting v@(Id {idScope = LocalId}) = varUniq v /= varUniq var+ interesting _ = True++ (boundFTVsSet,boundFVsSet) =+ getConst (Lens.foldMapOf (termFreeVars' interesting) unitFV e)+ boundFTVs = eltsUniqSet boundFTVsSet+ boundFVs = eltsUniqSet boundFVsSet+ -- Make a new global ID tcm <- Lens.view tcCache- newBodyTy <- termType tcm $ mkTyLams (mkLams e boundFVs) boundFTVs+ let newBodyTy = termType tcm $ mkTyLams (mkLams e boundFVs) boundFTVs (cf,sp) <- Lens.use curFun- -- newBodyId <- fmap (makeName (name2String cf ++ "_" ++ name2String idName) . toInteger) getUniqueM- newBodyId <- cloneVar (appendToName cf ("_" ++ name2String idName))+ newBodyNm <- cloneName (appendToName (varName cf) ("_" `Text.append` nameOcc idName))+ let newBodyId = mkGlobalId newBodyTy newBodyNm {nameSort = Internal} -- Make a new expression, consisting of the the lifted function applied to -- its free variables let newExpr = mkTmApps- (mkTyApps (Var newBodyTy newBodyId)- (zipWith VarTy localFTVkinds localFTVs))- (zipWith Var localFVtys' localFVs')- -- Substitute the recursive calls by the new expression- e' = substTm (nameOcc idName) newExpr e- -- Create a new body that abstracts over the free variables+ (mkTyApps (Var newBodyId)+ (map VarTy boundFTVs))+ (map Var boundFVs)+ inScope0 = mkInScopeSet (coerce boundFVsSet)+ inScope1 = extendInScopeSetList inScope0 [var,newBodyId]+ let subst = extendIdSubst (mkSubst inScope1) var newExpr+ -- Substitute the recursive calls by the new expression+ e' = substTm "liftBinding" subst e+ -- Create a new body that abstracts over the free variables newBody = mkTyLams (mkLams e' boundFVs) boundFTVs -- Check if an alpha-equivalent global binder already exists- aeqExisting <- (HMS.toList . HMS.filter ((== newBody) . (^. _5))) <$> Lens.use bindings+ aeqExisting <- (eltsUniqMap . filterUniqMap ((`aeqTerm` newBody) . (^. _4))) <$> Lens.use bindings case aeqExisting of -- If it doesn't, create a new binder [] -> do -- Add the created function to the list of global bindings- bindings %= HMS.insert (nameOcc newBodyId)+ bindings %= extendUniqMap newBodyNm -- We mark this function as internal so that -- it can be inlined at the very end of -- the normalisation pipeline as part of the@@ -442,8 +566,8 @@ -- function at this moment for a reason! -- (termination, CSE and DEC oppertunities, -- ,etc.)- (newBodyId {nameSort = Internal}- ,newBodyTy,sp+ (newBodyId+ ,sp #if MIN_VERSION_ghc(8,4,1) ,NoUserInline #else@@ -451,16 +575,16 @@ #endif ,newBody) -- Return the new binder- return (Id idName tyE, embed newExpr)+ return (var, newExpr) -- If it does, use the existing binder- ((_,(k,aeqTy,_,_,_)):_) ->+ ((k,_,_,_):_) -> let newExpr' = mkTmApps- (mkTyApps (Var aeqTy k)- (zipWith VarTy localFTVkinds localFTVs))- (zipWith Var localFVtys' localFVs')- in return (Id idName tyE, embed newExpr')+ (mkTyApps (Var k)+ (map VarTy boundFTVs))+ (map Var boundFVs)+ in return (var, newExpr') -liftBinding _ _ _ = error $ $(curLoc) ++ "liftBinding: invalid core, expr bound to tyvar"+liftBinding _ = error $ $(curLoc) ++ "liftBinding: invalid core, expr bound to tyvar" -- | Make a global function for a name-term tuple mkFunction@@ -470,14 +594,14 @@ -> InlineSpec -> Term -- ^ Term bound to the function- -> RewriteMonad extra (TmName,Type)+ -> RewriteMonad extra Id -- ^ Name with a proper unique and the type of the function-mkFunction bndr sp inl body = do+mkFunction bndrNm sp inl body = do tcm <- Lens.view tcCache- bodyTy <- termType tcm body- bodyId <- cloneVar bndr- addGlobalBind bodyId bodyTy sp inl body- return (bodyId,bodyTy)+ let bodyTy = termType tcm body+ bodyNm <- cloneName bndrNm+ addGlobalBind bodyNm bodyTy sp inl body+ return (mkGlobalId bodyTy bodyNm) -- | Add a function to the set of global binders addGlobalBind@@ -487,25 +611,18 @@ -> InlineSpec -> Term -> RewriteMonad extra ()-addGlobalBind vId ty sp inl body =- (ty,body) `deepseq` bindings %= HMS.insert (nameOcc vId) (vId,ty,sp,inl,body)+addGlobalBind vNm ty sp inl body = do+ let vId = mkGlobalId ty vNm+ (ty,body) `deepseq` bindings %= extendUniqMap vNm (vId,sp,inl,body) -- | Create a new name out of the given name, but with another unique-cloneVar+cloneName :: (Monad m, MonadUnique m) => Name a -> m (Name a)-cloneVar (Name sort nm loc) = do- i <- toInteger <$> getUniqueM- return (Name sort (Unbound.makeName (Unbound.name2String nm) i) loc)---- | Test whether a term is a variable reference to a local binder-isLocalVar :: Term- -> RewriteMonad extra Bool-isLocalVar (Var _ name)- = fmap (not . HML.member (nameOcc name))- $ Lens.use bindings-isLocalVar _ = return False+cloneName nm = do+ i <- getUniqueM+ return nm {nameUniq = i} {-# INLINE isUntranslatable #-} -- | Determine if a term cannot be represented in hardware@@ -517,10 +634,10 @@ isUntranslatable stringRepresentable tm = do tcm <- Lens.view tcCache not <$> (representableType <$> Lens.view typeTranslator- <*> Lens.view allowZero+ <*> Lens.view customReprs <*> pure stringRepresentable <*> pure tcm- <*> termType tcm tm)+ <*> pure (termType tcm tm)) {-# INLINE isUntranslatableType #-} -- | Determine if a type cannot be represented in hardware@@ -531,139 +648,140 @@ -> RewriteMonad extra Bool isUntranslatableType stringRepresentable ty = not <$> (representableType <$> Lens.view typeTranslator- <*> Lens.view allowZero+ <*> Lens.view customReprs <*> pure stringRepresentable <*> Lens.view tcCache <*> pure ty) --- | Is the Context a Lambda/Term-abstraction context?-isLambdaBodyCtx :: CoreContext- -> Bool-isLambdaBodyCtx (LamBody _) = True-isLambdaBodyCtx _ = False- -- | Make a binder that should not be referenced-mkWildValBinder :: (Monad m, MonadUnique m)- => Type- -> m Id-mkWildValBinder = fmap fst . mkInternalVar (string2InternalName "wild")+mkWildValBinder+ :: (Monad m, MonadUnique m)+ => InScopeSet+ -> Type+ -> m Id+mkWildValBinder is = mkInternalVar is "wild" -- | Make a case-decomposition that extracts a field out of a (Sum-of-)Product type-mkSelectorCase :: (Functor m, Monad m, MonadUnique m, Fresh m)- => String -- ^ Name of the caller of this function- -> HashMap TyConOccName TyCon -- ^ TyCon cache- -> Term -- ^ Subject of the case-composition- -> Int -- n'th DataCon- -> Int -- n'th field- -> m Term-mkSelectorCase caller tcm scrut dcI fieldI = do- scrutTy <- termType tcm scrut- go scrutTy+mkSelectorCase+ :: HasCallStack+ => (Functor m, Monad m, MonadUnique m)+ => String -- ^ Name of the caller of this function+ -> InScopeSet+ -> TyConMap -- ^ TyCon cache+ -> Term -- ^ Subject of the case-composition+ -> Int -- n'th DataCon+ -> Int -- n'th field+ -> m Term+mkSelectorCase caller inScope tcm scrut dcI fieldI = go (termType tcm scrut) where- go (coreView tcm -> Just ty') = go ty'+ go (coreView1 tcm -> Just ty') = go ty' go scrutTy@(tyView -> TyConApp tc args) =- case tyConDataCons (tcm HMS.! nameOcc tc) of- [] -> cantCreate $(curLoc) ("TyCon has no DataCons: " ++ show tc ++ " " ++ showDoc tc) scrutTy+ case tyConDataCons (lookupUniqMap' tcm tc) of+ [] -> cantCreate $(curLoc) ("TyCon has no DataCons: " ++ show tc ++ " " ++ showPpr tc) scrutTy dcs | dcI > length dcs -> cantCreate $(curLoc) "DC index exceeds max" scrutTy | otherwise -> do let dc = indexNote ($(curLoc) ++ "No DC with tag: " ++ show (dcI-1)) dcs (dcI-1)- let (Just fieldTys) = dataConInstArgTys dc args+ let (Just fieldTys) = dataConInstArgTysE inScope tcm dc args if fieldI >= length fieldTys then cantCreate $(curLoc) "Field index exceed max" scrutTy else do- wildBndrs <- mapM mkWildValBinder fieldTys+ wildBndrs <- mapM (mkWildValBinder inScope) fieldTys let ty = indexNote ($(curLoc) ++ "No DC field#: " ++ show fieldI) fieldTys fieldI- selBndr <- mkInternalVar (string2InternalName "sel") ty- let bndrs = take fieldI wildBndrs ++ [fst selBndr] ++ drop (fieldI+1) wildBndrs- pat = DataPat (embed dc) (rebind [] bndrs)- retVal = Case scrut ty [ bind pat (snd selBndr) ]+ selBndr <- mkInternalVar inScope "sel" ty+ let bndrs = take fieldI wildBndrs ++ [selBndr] ++ drop (fieldI+1) wildBndrs+ pat = DataPat dc (dcExtTyVars dc) bndrs+ retVal = Case scrut ty [ (pat, Var selBndr) ] return retVal- go scrutTy = cantCreate $(curLoc) ("Type of subject is not a datatype: " ++ showDoc scrutTy) scrutTy+ go scrutTy = cantCreate $(curLoc) ("Type of subject is not a datatype: " ++ showPpr scrutTy) scrutTy - cantCreate loc info scrutTy = error $ loc ++ "Can't create selector " ++ show (caller,dcI,fieldI) ++ " for: (" ++ showDoc scrut ++ " :: " ++ showDoc scrutTy ++ ")\nAdditional info: " ++ info+ cantCreate loc info scrutTy = error $ loc ++ "Can't create selector " ++ show (caller,dcI,fieldI) ++ " for: (" ++ showPpr scrut ++ " :: " ++ showPpr scrutTy ++ ")\nAdditional info: " ++ info -- | Specialise an application on its argument-specialise :: Lens' extra (Map.Map (TmOccName, Int, Either Term Type) (TmName,Type)) -- ^ Lens into previous specialisations- -> Lens' extra (HashMap TmOccName Int) -- ^ Lens into the specialisation history+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 (collectArgs e1) (Right ty)- (App e1 e2) -> specialise' specMapLbl specHistLbl specLimitLbl ctx e (collectArgs e1) (Left e2)+ (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 (TmOccName, Int, Either Term Type) (TmName,Type)) -- ^ Lens into previous specialisations- -> Lens' extra (HashMap TmOccName Int) -- ^ Lens into specialisation history+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- -> [CoreContext] -- Transformation context+ -> TransformContext -- Transformation context -> Term -- ^ Original term- -> (Term, [Either Term Type]) -- ^ Function part of the term, split into root and applied arguments+ -> (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 ctx e (Var _ f, args) specArgIn = do+specialise' specMapLbl specHistLbl specLimitLbl (TransformContext is0 _) e (Var f, args, ticks) specArgIn = do lvl <- Lens.view dbgLevel -- Don't specialise TopEntities topEnts <- Lens.view topEntities- if nameOcc f `HashSet.member` topEnts- then traceIf (lvl >= DebugNone) ("Not specialising TopEntity: " ++ showDoc f) (return e)+ if f `elemVarSet` topEnts+ then traceIf (lvl >= DebugNone) ("Not specialising TopEntity: " ++ showPpr (varName f)) (return e) else do -- NondecreasingIndentation tcm <- Lens.view tcCache 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 ctx specArg- let argLen = length args+ -- 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 . (`mkAbstraction` specBndrs)) (Right . id) specArg -- Determine if 'f' has already been specialized on (a type-normalized) 'specArg'- specM <- Map.lookup (nameOcc f,argLen,specAbs) <$> Lens.use (extra.specMapLbl)+ specM <- Map.lookup (f,argLen,specAbs) <$> Lens.use (extra.specMapLbl) case specM of -- Use previously specialized function- Just (fname,fty) ->- traceIf (lvl >= DebugApplied) ("Using previous specialization of " ++ showDoc (nameOcc f) ++ " on " ++ (either showDoc showDoc) specAbs ++ ": " ++ showDoc fname) $- changed $ mkApps (Var fty fname) (args ++ specVars)+ 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 (HML.lookup (nameOcc f)) $ Lens.use bindings+ bodyMaybe <- fmap (lookupUniqMap (varName f)) $ Lens.use bindings case bodyMaybe of- Just (_,_,sp,inl,bodyTm) -> do+ Just (_,sp,inl,bodyTm) -> do -- Determine if we see a sequence of specialisations on a growing argument- specHistM <- HML.lookup (nameOcc f) <$> Lens.use (extra.specHistLbl)+ 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 `" ++ showDoc (nameOcc f) ++ "'.\n"- , "The function `" ++ showDoc f ++ "' is most likely recursive, and looks like it is being indefinitely specialized on a growing argument.\n"- , "Body of `" ++ showDoc f ++ "':\n" ++ showDoc bodyTm ++ "\n"- , "Argument (in position: " ++ show argLen ++ ") that triggered termination:\n" ++ (either showDoc showDoc) specArg+ (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) (Right *** Right))) $+ (boundArgs,argVars) <- fmap (unzip . map (either (Left &&& Left . Var) (Right &&& Right . VarTy))) $ Monad.zipWithM- (mkBinderFor tcm)- (unsafeCollectBndrs bodyTm ++ repeat (string2InternalName "pTS"))+ (mkBinderFor is0 tcm)+ (existingNames ++ newNames) args- -- Determine name the resulting specialised function, and the- -- form of the specialised-on argument- (fName,inl',specArg') <- case specArg of- Left a@(collectArgs -> (Var _ g,gArgs)) -> do- polyFun <- isPolyFun tcm a- if polyFun+ -- 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 specialised higher-order function.+ -- 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.@@ -672,27 +790,26 @@ -- 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 (HML.lookup (nameOcc g)) $ Lens.use bindings- return (g,maybe inl (^. _4) gTmM, maybe specArg (Left . (`mkApps` gArgs) . (^. _5)) gTmM)+ gTmM <- fmap (lookupUniqMap (varName g)) $ Lens.use bindings+ return (g,maybe inl (^. _3) gTmM, maybe specArg (Left . (`mkApps` gArgs) . (^. _4)) gTmM) else return (f,inl,specArg) _ -> return (f,inl,specArg) -- Create specialized functions let newBody = mkAbstraction (mkApps bodyTm (argVars ++ [specArg'])) (boundArgs ++ specBndrs)- newf <- mkFunction fName sp inl' newBody+ newf <- mkFunction (varName fId) sp inl' newBody -- Remember specialization- (extra.specHistLbl) %= HML.insertWith (+) (nameOcc f) 1- (extra.specMapLbl) %= Map.insert (nameOcc f,argLen,specAbs) newf+ (extra.specHistLbl) %= extendUniqMapWith f 1 (+)+ (extra.specMapLbl) %= Map.insert (f,argLen,specAbs) newf -- use specialized function- let newExpr = mkApps ((uncurry . flip) Var newf) (args ++ specVars)+ let newExpr = mkApps (mkTicks (Var newf) ticks) (args ++ specVars) newf `deepseq` changed newExpr Nothing -> return e where- unsafeCollectBndrs :: Term -> [Name a]- unsafeCollectBndrs =- map (either (coerceName . varName) (coerceName . varName)) . reverse . go []+ collectBndrsMinusApps :: Term -> [Name a]+ collectBndrsMinusApps = reverse . go [] where- go bs (Lam b) = let (v,e') = unsafeUnbind b in go (Left v:bs) e'- go bs (TyLam b) = let (tv,e') = unsafeUnbind b in go (Right tv:bs) e'+ 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@@ -701,18 +818,18 @@ bs' -> init bs' ++ bs go bs _ = bs -specialise' _ _ _ ctx _ (appE,args) (Left specArg) = do+specialise' _ _ _ _ctx _ (appE,args,ticks) (Left specArg) = do -- Create binders and variable references for free variables in 'specArg'- (specBndrs,specVars) <- specArgBndrsAndVars ctx (Left specArg)+ let (specBndrs,specVars) = specArgBndrsAndVars (Left specArg) -- Create specialized function- let newBody = mkAbstraction specArg specBndrs+ newBody = mkAbstraction specArg specBndrs -- See if there's an existing binder that's alpha-equivalent to the- -- specialised function- existing <- HML.filter ((== newBody) . (^. _5)) <$> Lens.use bindings+ -- specialized function+ existing <- filterUniqMap ((`aeqTerm` newBody) . (^. _4)) <$> Lens.use bindings -- Create a new function if an alpha-equivalent binder doesn't exist- newf <- case HML.toList existing of+ newf <- case eltsUniqMap existing of [] -> do (cf,sp) <- Lens.use curFun- mkFunction (appendToName cf "_specF")+ mkFunction (appendToName (varName cf) "_specF") sp #if MIN_VERSION_ghc(8,4,1) NoUserInline@@ -720,41 +837,45 @@ EmptyInlineSpec #endif newBody- ((_,(k,kTy,_,_,_)):_) -> return (k,kTy)+ ((k,_,_,_):_) -> return k -- Create specialized argument- let newArg = Left $ mkApps ((uncurry . flip) Var newf) specVars+ let newArg = Left $ mkApps (Var newf) specVars -- Use specialized argument- let newExpr = mkApps appE (args ++ [newArg])+ let newExpr = mkApps (mkTicks appE ticks) (args ++ [newArg]) changed newExpr specialise' _ _ _ _ e _ _ = return e -normalizeTermTypes :: HashMap TyConOccName TyCon -> Term -> Term+normalizeTermTypes :: TyConMap -> Term -> Term normalizeTermTypes tcm e = case e of Cast e' ty1 ty2 -> Cast (normalizeTermTypes tcm e') (normalizeType tcm ty1) (normalizeType tcm ty2)- Var ty nm -> Var (normalizeType tcm ty) nm+ Var v -> Var (normalizeId tcm v) -- TODO other terms? _ -> e -normalizeId :: HashMap TyConOccName TyCon -> Id -> Id-normalizeId tcm (Id nm (Unbound.Embed ty)) = Id nm (Unbound.Embed $ normalizeType tcm ty)-normalizeId _ tyvar = tyvar+normalizeId :: TyConMap -> Id -> Id+normalizeId tcm v@(Id {}) = v {varType = normalizeType tcm (varType v)}+normalizeId _ tyvar = tyvar -- | Create binders and variable references for free variables in 'specArg'-specArgBndrsAndVars :: [CoreContext]- -> Either Term Type- -> RewriteMonad extra ([Either Id TyVar],[Either Term Type])-specArgBndrsAndVars ctx specArg = do- let specFTVs = List.nub $ either (Lens.toListOf termFreeTyVars) (Lens.toListOf typeFreeVars) specArg- specFVs <- List.nub <$> either ((Lens.toListOf <$> localFreeIds <*>) . pure) (const (pure [])) specArg- (gamma,delta) <- mkEnv ctx- let (specTyBndrs,specTyVars) = unzip- $ map (\tv -> let ki = HML.lookupDefault (error $ $(curLoc) ++ show tv ++ " not found") tv delta- tv' = Name Internal tv noSrcSpan- in (Right $ TyVar tv' (embed ki), Right $ VarTy ki tv')) specFTVs- (specTmBndrs,specTmVars) = unzip- $ map (\tm -> let ty = HML.lookupDefault (error $ $(curLoc) ++ show tm ++ " not found") tm gamma- tm' = Name Internal tm noSrcSpan- in (Left $ Id tm' (embed ty), Left $ Var ty tm')) specFVs- return (specTyBndrs ++ specTmBndrs,specTyVars ++ specTmVars)+specArgBndrsAndVars+ :: Either Term Type+ -> ([Either Id TyVar], [Either Term Type])+specArgBndrsAndVars specArg =+ let unitFV :: Var a -> Const (UniqSet TyVar,UniqSet Id) (Var a)+ unitFV v@(Id {}) = Const (emptyUniqSet,unitUniqSet (coerce v))+ unitFV v@(TyVar {}) = Const (unitUniqSet (coerce v),emptyUniqSet)++ (specFTVs,specFVs) = case specArg of+ Left tm -> (eltsUniqSet *** eltsUniqSet) . 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)
+ src/Clash/Unique.hs view
@@ -0,0 +1,397 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings #-}++module Clash.Unique+ ( -- * Unique+ Unique+ , Uniquable (..)+ -- * UniqMap+ , UniqMap+ -- ** Accessors+ -- *** Size information+ , nullUniqMap+ -- *** Indexing+ , lookupUniqMap+ , lookupUniqMap'+ -- ** Construction+ , emptyUniqMap+ , unitUniqMap+ -- ** Modification+ , extendUniqMap+ , extendUniqMapWith+ , extendListUniqMap+ , delUniqMap+ , delListUniqMap+ , unionUniqMap+ , unionUniqMapWith+ , differenceUniqMap+ -- ** Element-wise operations+ -- *** Mapping+ , mapUniqMap+ , mapMaybeUniqMap+ -- ** Working with predicates+ -- *** Filtering+ , filterUniqMap+ -- *** Searching+ , elemUniqMap+ , notElemUniqMap+ -- ** Folding+ , foldrWithUnique+ -- ** Conversions+ -- *** Lists+ , eltsUniqMap+ , keysUniqMap+ , listToUniqMap+ , toListUniqMap+ -- *** UniqSet+ , uniqMapToUniqSet+ -- * UniqSet+ , UniqSet+ -- ** Accessors+ -- *** Indexing+ , lookupUniqSet+ -- ** Construction+ , emptyUniqSet+ , unitUniqSet+ -- ** Modifications+ , extendUniqSet+ , unionUniqSet+ , delUniqSetDirectly+ -- ** Working with predicates+ -- *** Searching+ , elemUniqSet+ , notElemUniqSet+ , elemUniqSetDirectly+ -- *** Misc+ , subsetUniqSet+ -- ** Conversions+ -- *** Lists+ , mkUniqSet+ , eltsUniqSet+ )+where++import Control.DeepSeq (NFData)+import Data.Binary (Binary)+import Data.IntMap (IntMap)+import qualified Data.IntMap as IntMap+import qualified Data.List as List+import Data.Text.Prettyprint.Doc+#if !MIN_VERSION_base(4,11,0)+import Data.Semigroup+#endif+import GHC.Stack++import Clash.Pretty++type Unique = Int++class Uniquable a where+ getUnique :: a -> Unique++instance Uniquable Int where+ getUnique i = i++-- | Map indexed by a 'Uniquable' key+newtype UniqMap a = UniqMap (IntMap a)+ deriving (Functor, Foldable, Traversable, Semigroup, Monoid, NFData, Binary)++instance ClashPretty a => ClashPretty (UniqMap a) where+ clashPretty (UniqMap env) =+ brackets $ fillSep $ punctuate comma $+ [ fromPretty uq <+> ":->" <+> clashPretty elt+ | (uq,elt) <- IntMap.toList env+ ]++instance ClashPretty a => Show (UniqMap a) where+ show = showDoc . clashPretty++-- | The empty map+emptyUniqMap+ :: UniqMap a+emptyUniqMap = UniqMap IntMap.empty++-- | Map with a single key-value pair+unitUniqMap+ :: Uniquable a+ => a+ -> b+ -> UniqMap b+unitUniqMap k v = UniqMap (IntMap.singleton (getUnique k) v)++-- | Check whether the map is empty+nullUniqMap+ :: UniqMap a+ -> Bool+nullUniqMap (UniqMap m) = IntMap.null m++-- | Extend the map with a new key-value pair. If the key already exists in the+-- associated value will be overwritten+extendUniqMap+ :: Uniquable a+ => a+ -> b+ -> UniqMap b+ -> UniqMap b+extendUniqMap k x (UniqMap m) = UniqMap (IntMap.insert (getUnique k) x m)++-- | Extend the map with a new key-value pair. If the key already exists in the+-- associated value will be combined with the new value using the function+-- provided+extendUniqMapWith+ :: Uniquable a+ => a+ -> b+ -> (b -> b -> b)+ -> UniqMap b+ -> UniqMap b+extendUniqMapWith k x f (UniqMap m) =+ UniqMap (IntMap.insertWith f (getUnique k) x m)++-- | Extend the map with a list of key-value pairs. Positions with existing+-- keys will be overwritten with the new values+extendListUniqMap+ :: Uniquable a+ => UniqMap b+ -> [(a, b)]+ -> UniqMap b+extendListUniqMap (UniqMap env) xs =+ UniqMap (List.foldl' (\m (k, v) -> IntMap.insert (getUnique k) v m) env xs)++-- | Look up a value in the map+lookupUniqMap+ :: Uniquable a+ => a+ -> UniqMap b+ -> Maybe b+lookupUniqMap k (UniqMap m) = IntMap.lookup (getUnique k) m++-- | Like 'lookupUniqMap'', but errors out when the key is not present+lookupUniqMap'+ :: (HasCallStack, Uniquable a)+ => UniqMap b+ -> a+ -> b+lookupUniqMap' (UniqMap m) k =+ IntMap.findWithDefault d k' m+ where+ k' = getUnique k+ d = error ("lookupUniqMap': key " ++ show k' ++ " is not an element of the map")++-- | Check whether a key is in the map+elemUniqMap+ :: Uniquable a+ => a+ -> UniqMap b+ -> Bool+elemUniqMap k (UniqMap m) = IntMap.member (getUnique k) m++-- | Check whether a key is not in the map+notElemUniqMap+ :: Uniquable a+ => a+ -> UniqMap b+ -> Bool+notElemUniqMap k (UniqMap m) = IntMap.notMember (getUnique k) m++-- | Derive a map where all the elements adhere to the predicate+filterUniqMap+ :: (b -> Bool)+ -> UniqMap b+ -> UniqMap b+filterUniqMap f (UniqMap m) = UniqMap (IntMap.filter f m)++-- | Remove a key-value pair from the map+delUniqMap+ :: Uniquable a+ => UniqMap b+ -> a+ -> UniqMap b+delUniqMap (UniqMap env) v = UniqMap (IntMap.delete (getUnique v) env)++-- | Remove a list of key-value pairs from the map+delListUniqMap+ :: Uniquable a+ => UniqMap b+ -> [a]+ -> UniqMap b+delListUniqMap (UniqMap env) vs =+ UniqMap (List.foldl' (\m v -> IntMap.delete (getUnique v) m) env vs)++-- | A (left-biased) union of two maps+unionUniqMap+ :: UniqMap a+ -> UniqMap a+ -> UniqMap a+unionUniqMap (UniqMap m1) (UniqMap m2) = UniqMap (IntMap.union m1 m2)++-- | A union of two maps, key-value pairs with the same key will be merged using+-- the given function+unionUniqMapWith+ :: (a -> a -> a)+ -> UniqMap a+ -> UniqMap a+ -> UniqMap a+unionUniqMapWith f (UniqMap m1) (UniqMap m2) = UniqMap (IntMap.unionWith f m1 m2)++-- | Get the difference between two maps+differenceUniqMap+ :: UniqMap a+ -> UniqMap a+ -> UniqMap a+differenceUniqMap (UniqMap m1) (UniqMap m2) = UniqMap (IntMap.difference m1 m2)++-- | Convert a list of key-value pairs to a map+listToUniqMap+ :: Uniquable a+ => [(a,b)]+ -> UniqMap b+listToUniqMap xs =+ UniqMap (List.foldl' (\m (k, v) -> IntMap.insert (getUnique k) v m) IntMap.empty xs)++-- | Convert a map to a list of key-value pairs+toListUniqMap+ :: UniqMap a+ -> [(Unique,a)]+toListUniqMap (UniqMap m) = IntMap.toList m++-- | Extract the elements of a map into a list+eltsUniqMap+ :: UniqMap a+ -> [a]+eltsUniqMap (UniqMap m) = IntMap.elems m++-- | Apply a function to every element in the map+mapUniqMap+ :: (a -> b)+ -> UniqMap a+ -> UniqMap b+mapUniqMap f (UniqMap m) = UniqMap (IntMap.map f m)++-- | Extract the keys of a map into a list+keysUniqMap+ :: UniqMap a+ -> [Unique]+keysUniqMap (UniqMap m) = IntMap.keys m++-- | Apply a function to every element in the map. When the function returns+-- 'Nothing', the key-value pair will be removed+mapMaybeUniqMap+ :: (a -> Maybe b)+ -> UniqMap a+ -> UniqMap b+mapMaybeUniqMap f (UniqMap m) = UniqMap (IntMap.mapMaybe f m)++-- | Right-fold over a map using both the key and value+foldrWithUnique+ :: (Unique -> a -> b -> b)+ -> b+ -> UniqMap a+ -> b+foldrWithUnique f s (UniqMap m) = IntMap.foldrWithKey f s m++-- | Set of things that have a 'Unique'+--+-- Invariant: they keys in the map are the uniques of the values+newtype UniqSet a = UniqSet (IntMap a)+ deriving (Foldable, Semigroup, Monoid, Binary)++instance ClashPretty a => ClashPretty (UniqSet a) where+ clashPretty (UniqSet env) =+ braces (fillSep (map clashPretty (IntMap.elems env)))++-- | The empty set+emptyUniqSet+ :: UniqSet a+emptyUniqSet = UniqSet IntMap.empty++-- | Set with a single element+unitUniqSet+ :: Uniquable a+ => a+ -> UniqSet a+unitUniqSet a = UniqSet (IntMap.singleton (getUnique a) a)++-- | Add an element to the set+extendUniqSet+ :: Uniquable a+ => UniqSet a+ -> a+ -> UniqSet a+extendUniqSet (UniqSet env) a = UniqSet (IntMap.insert (getUnique a) a env)++-- | Union two sets+unionUniqSet+ :: UniqSet a+ -> UniqSet a+ -> UniqSet a+unionUniqSet (UniqSet env1) (UniqSet env2) = UniqSet (IntMap.union env1 env2)++-- | Check whether an element exists in the set+elemUniqSet+ :: Uniquable a+ => a+ -> UniqSet a+ -> Bool+elemUniqSet a (UniqSet env) = IntMap.member (getUnique a) env++-- | Check whether an element does not exist in the set+notElemUniqSet+ :: Uniquable a+ => a+ -> UniqSet a+ -> Bool+notElemUniqSet a (UniqSet env) = IntMap.notMember (getUnique a) env++-- | Check whether an element exists in the set based on the `Unique` contained+-- in that element+elemUniqSetDirectly+ :: Unique+ -> UniqSet a+ -> Bool+elemUniqSetDirectly k (UniqSet m) = k `IntMap.member` m++-- | Look up an element in the set, returns it if it exists+lookupUniqSet+ :: Uniquable a+ => a+ -> UniqSet b+ -> Maybe b+lookupUniqSet a (UniqSet env) = IntMap.lookup (getUnique a) env++-- | Remove an element based on the `Unique` it contains+delUniqSetDirectly+ :: Unique+ -> UniqSet b+ -> UniqSet b+delUniqSetDirectly k (UniqSet env) = UniqSet (IntMap.delete k env)++-- | Get the elements of the set as a list+eltsUniqSet+ :: UniqSet a+ -> [a]+eltsUniqSet (UniqSet env) = IntMap.elems env++-- | Create a set out of a list of elements that contain a 'Unique'+mkUniqSet+ :: Uniquable a+ => [a]+ -> UniqSet a+mkUniqSet m = UniqSet (IntMap.fromList (map (\x -> (getUnique x,x)) m))++-- | Convert a 'UniqMap' to a 'UniqSet'+uniqMapToUniqSet+ :: UniqMap a+ -> UniqSet a+uniqMapToUniqSet (UniqMap m) = UniqSet m++-- | Check whether a A is a subset of B+subsetUniqSet+ :: UniqSet a+ -- ^ Set A+ -> UniqSet a+ -- ^ Set B+ -> Bool+subsetUniqSet (UniqSet e1) (UniqSet e2) = IntMap.null (IntMap.difference e1 e2)
src/Clash/Util.hs view
@@ -9,6 +9,7 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MagicHash #-}+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE Rank2Types #-} {-# LANGUAGE TupleSections #-} @@ -18,33 +19,114 @@ ( module Clash.Util , module X , makeLenses+ , SrcSpan+ , noSrcSpan+ , HasCallStack ) where import Control.Applicative as X (Applicative,(<$>),(<*>),pure)-import Control.Arrow as X ((***),first,second)-import Control.DeepSeq+import Control.Arrow as X ((***),(&&&),first,second)+import qualified Control.Exception as Exception import Control.Monad as X ((<=<),(>=>)) import Control.Monad.State (MonadState,State,StateT,runState) import qualified Control.Monad.State as State-import Control.Monad.Trans.Class (MonadTrans,lift)+import Data.Typeable (Typeable) import Data.Function as X (on) import Data.Hashable (Hashable) import Data.HashMap.Lazy (HashMap) import qualified Data.HashMap.Lazy as HashMapL-import qualified Data.HashMap.Strict as HashMapS import Data.Maybe (fromMaybe)+import Data.Text.Prettyprint.Doc+import Data.Text.Prettyprint.Doc.Render.String import Data.Version (Version)+import qualified Data.Time.Format as Clock+import qualified Data.Time.Clock as Clock+import Data.Time.Clock (UTCTime) import Control.Lens import Debug.Trace (trace) import GHC.Base (Int(..),isTrue#,(==#),(+#)) import GHC.Integer.Logarithms (integerLogBase#)+import GHC.Stack (HasCallStack, callStack, prettyCallStack)+import Type.Reflection (tyConPackage, typeRepTyCon, typeOf) import qualified Language.Haskell.TH as TH +import SrcLoc (SrcSpan, noSrcSpan)+import Clash.Unique+ #ifdef CABAL import qualified Paths_clash_lib (version) #endif +data ClashException = ClashException SrcSpan String (Maybe String)++instance Show ClashException where+ show (ClashException _ s eM) = s ++ "\n" ++ maybe "" id eM++instance Exception.Exception ClashException++assertPanic+ :: String -> Int -> a+assertPanic file ln = Exception.throw+ (ClashException noSrcSpan ("ASSERT failed! file " ++ file ++ ", line " ++ show ln) Nothing)++assertPprPanic+ :: HasCallStack => String -> Int -> Doc ann -> a+assertPprPanic _file _line msg = pprPanic "ASSERT failed!" doc+ where+ doc = sep [ msg, callStackDoc ]++pprPanic+ :: String -> Doc ann -> a+pprPanic heading prettyMsg = Exception.throw+ (ClashException noSrcSpan (renderString (layoutPretty defaultLayoutOptions doc)) Nothing)+ where+ doc = sep [pretty heading, nest 2 prettyMsg]++callStackDoc+ :: HasCallStack => Doc ann+callStackDoc =+ "Call stack:" <+> hang 4+ (vcat (map pretty (lines (prettyCallStack callStack))))++warnPprTrace+ :: HasCallStack+ => Bool+ -- ^ Trigger warning?+ -> String+ -- ^ File name+ -> Int+ -- ^ Line number+ -> Doc ann+ -- ^ Message+ -> a+ -- ^ Pass value (like trace)+ -> a+warnPprTrace _ _ _ _ x | not debugIsOn = x+warnPprTrace False _ _ _ x = x+warnPprTrace True file ln msg x =+ pprDebugAndThen trace (vcat [heading0, heading1]) msg x+ where+ heading0 = hsep ["WARNING: file", pretty file <> comma, "line", pretty ln]+ heading1 = "WARNING CALLSTACK:" <> line <> pretty (prettyCallStack callStack)++pprTrace+ :: String -> Doc ann -> a -> a+pprTrace str = pprDebugAndThen trace (pretty str)++pprTraceDebug+ :: String -> Doc ann -> a -> a+pprTraceDebug str doc x+ | debugIsOn = pprDebugAndThen trace (pretty str) doc x+ | otherwise = x++pprDebugAndThen+ :: (String -> a) -> Doc ann -> Doc ann -> a+pprDebugAndThen cont heading prettyMsg =+ cont (renderString (layoutPretty defaultLayoutOptions doc))+ where+ doc = sep [heading, nest 2 prettyMsg]+ -- | A class that can generate unique numbers class MonadUnique m where -- | Get a new unique@@ -78,41 +160,23 @@ l %= HashMapL.insert key value return value --- | Cache the result of a monadic action in a State 3 transformer layers down-makeCachedT3 :: ( MonadTrans t2, MonadTrans t1, MonadTrans t- , Eq k, Hashable k- , MonadState s m- , Monad (t2 m), Monad (t1 (t2 m)), Monad (t (t1 (t2 m))))- => k -- ^ The key the action is associated with- -> Lens' s (HashMap k v) -- ^ The Lens to the HashMap that is the cache- -> (t (t1 (t2 m))) v -- ^ The action to cache- -> (t (t1 (t2 m))) v-makeCachedT3 key l create = do- cache <- (lift . lift . lift) $ use l- case HashMapL.lookup key cache of- Just value -> return value- Nothing -> do- value <- create- (lift . lift . lift) $ l %= HashMapL.insert key value- return value---- | Spine-strict cache variant of 'mkCachedT3'-makeCachedT3S :: ( MonadTrans t2, MonadTrans t1, MonadTrans t- , Eq k, Hashable k- , MonadState s m- , Monad (t2 m), Monad (t1 (t2 m)), Monad (t (t1 (t2 m)))- , NFData v)- => k- -> Lens' s (HashMap k v)- -> (t (t1 (t2 m))) v- -> (t (t1 (t2 m))) v-makeCachedT3S key l create = do- cache <- (lift . lift . lift) $ use l- case HashMapS.lookup key cache of+-- | Cache the result of a monadic action using a 'UniqMap'+makeCachedU+ :: (MonadState s m, Uniquable k)+ => k+ -- ^ Key the action is associated with+ -> Lens' s (UniqMap v)+ -- ^ Lens to the cache+ -> m v+ -- ^ Action to cache+ -> m v+makeCachedU key l create = do+ cache <- use l+ case lookupUniqMap key cache of Just value -> return value Nothing -> do value <- create- value `deepseq` ((lift . lift . lift) $ l %= HashMapS.insert key value)+ l %= extendUniqMap key value return value -- | Run a State-action using the State that is stored in a higher-layer Monad@@ -151,6 +215,7 @@ traceIf :: Bool -> String -> a -> a traceIf True msg = trace msg traceIf False _ = id+{-# INLINE traceIf #-} -- | Monadic version of 'Data.List.partition' partitionM :: Monad m@@ -175,10 +240,6 @@ (acc'',ys) <- mapAccumLM f acc' xs return (acc'',y:ys) --- | Composition of a unary function with a binary function-dot :: (c -> d) -> (a -> b -> c) -> a -> b -> d-dot = (.) . (.)- -- | if-then-else as a function on an argument ifThenElse :: (a -> Bool) -> (a -> b)@@ -208,8 +269,18 @@ -> [a] -> Int -> a-indexNote note = fromMaybe (error note) `dot` indexMaybe+indexNote note = \xs i -> fromMaybe (error note) (indexMaybe xs i) +-- | Safe version of 'head'+headMaybe :: [a] -> Maybe a+headMaybe (a:_) = Just a+headMaybe _ = Nothing++-- | Safe version of 'tail'+tailMaybe :: [a] -> Maybe [a]+tailMaybe (_:as) = Just as+tailMaybe _ = Nothing+ -- | Split the second list at the length of the first list splitAtList :: [b] -> [a] -> ([a], [a]) splitAtList [] xs = ([], xs)@@ -225,6 +296,17 @@ clashLibVersion = error "development version" #endif +-- | Return number of occurrences of an item in a list+countEq+ :: Eq a+ => a+ -- ^ Needle+ -> [a]+ -- ^ Haystack+ -> Int+ -- ^ Times needle was found in haystack+countEq a as = length (filter (== a) as)+ -- | \x y -> floor (logBase x y), x > 1 && y > 0 flogBase :: Integer -> Integer -> Maybe Int flogBase x y | x > 1 && y > 0 = Just (I# (integerLogBase# x y))@@ -241,3 +323,81 @@ then Just (I# (z1 +# 1#)) else Just (I# z1) clogBase _ _ = Nothing++-- | Determine whether two lists are of equal length+equalLength+ :: [a] -> [b] -> Bool+equalLength [] [] = True+equalLength (_:as) (_:bs) = equalLength as bs+equalLength _ _ = False++-- | Determine whether two lists are not of equal length+neLength+ :: [a] -> [b] -> Bool+neLength [] [] = False+neLength (_:as) (_:bs) = neLength as bs+neLength _ _ = True++-- | Zip two lists of equal length+--+-- NB Errors out for a DEBUG compiler when the two lists are not of equal length+zipEqual+ :: [a] -> [b] -> [(a,b)]+#if !defined(DEBUG)+zipEqual = zip+#else+zipEqual [] [] = []+zipEqual (a:as) (b:bs) = (a,b) : zipEqual as bs+zipEqual _ _ = error "zipEqual"+#endif++-- | Is this a DEBUG compiler?+debugIsOn+ :: Bool+#if defined(DEBUG)+debugIsOn = True+#else+debugIsOn = False+#endif++-- | Short-circuiting monadic version of 'any'+anyM+ :: (Monad m)+ => (a -> m Bool)+ -> [a]+ -> m Bool+anyM _ [] = return False+anyM p (x:xs) = do+ q <- p x+ if q then+ return True+ else+ anyM p xs+++-- | Get the package id of the type of a value+-- >>> pkgIdFromTypeable (undefined :: TopEntity)+-- "clash-prelude-0.99.3-64904d90747cb49e17166bbc86fec8678918e4ead3847193a395b258e680373c"+pkgIdFromTypeable :: Typeable a => a -> String+pkgIdFromTypeable = tyConPackage . typeRepTyCon . typeOf++reportTimeDiff :: UTCTime -> UTCTime -> String+reportTimeDiff start end =+ Clock.formatTime Clock.defaultTimeLocale fmt+ (Clock.UTCTime (toEnum 0) (fromRational (toRational diff)))+ where+ diff = Clock.diffUTCTime start end+ fmt | diff >= 3600+ = "%-Hh%-Mm%-S%03Qs"+ | diff >= 60+ = "%-Mm%-S%03Qs"+ | otherwise+ = "%-S%03Qs"++-- | Converts a curried function to a function on a triple+uncurry3+ :: (a -> b -> c -> d)+ -> (a,b,c)+ -> d+uncurry3 = \f (a,b,c) -> f a b c+{-# INLINE uncurry3 #-}
+ src/Clash/Util/Graph.hs view
@@ -0,0 +1,127 @@+{-|+ Copyright : (C) 2018, QBayLogic+ License : BSD2 (see the file LICENSE)+ Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>++ Collection of utilities+-}+module Clash.Util.Graph (topSort, reverseTopSort) where++import Data.Tuple (swap)+import Data.Foldable (foldlM)+import qualified Data.IntMap.Strict as IntMap+import qualified Data.IntSet as IntSet++data Marker+ = Temporary+ | Permanent++headSafe :: [a] -> Maybe a+headSafe [] = Nothing+headSafe (a:_) = Just a++topSortVisit'+ :: IntMap.IntMap [Int]+ -- ^ Edges+ -> IntSet.IntSet+ -- ^ Unmarked nodes+ -> IntMap.IntMap Marker+ -- ^ Marked nodes+ -> [Int]+ -- ^ Sorted so far+ -> Int+ -- ^ Node to visit+ -> Either String (IntSet.IntSet, IntMap.IntMap Marker, [Int])+topSortVisit' edges unmarked marked sorted node =+ case IntMap.lookup node marked of+ Just Permanent -> Right (unmarked, marked, sorted)+ Just Temporary -> Left "cycle detected: cannot topsort cyclic graph"+ Nothing -> do+ let marked' = IntMap.insert node Temporary marked+ let unmarked' = IntSet.delete node unmarked+ let nodeToM = IntMap.findWithDefault [] node edges+ (unmarked'', marked'', sorted'') <-+ foldlM visit (unmarked', marked', sorted) nodeToM+ let marked''' = IntMap.insert node Permanent marked''+ return (unmarked'', marked''', node : sorted'')+ where+ visit (unmarked', marked', sorted') node' =+ topSortVisit' edges unmarked' marked' sorted' node'++topSortVisit+ :: IntMap.IntMap [Int]+ -- ^ Edges+ -> IntSet.IntSet+ -- ^ Unmarked nodes+ -> IntMap.IntMap Marker+ -- ^ Marked nodes+ -> [Int]+ -- ^ Sorted so far+ -> Int+ -- ^ Node to visit+ -> Either String (IntSet.IntSet, IntMap.IntMap Marker, [Int])+topSortVisit edges unmarked marked sorted node = do+ (unmarked', marked', sorted') <-+ topSortVisit' edges unmarked marked sorted node++ case headSafe (IntSet.toList unmarked') of+ Nothing -> return (unmarked', marked', sorted')+ Just node' -> topSortVisit edges unmarked' marked' sorted' node'++-- | See: https://en.wikipedia.org/wiki/Topological_sorting. This function+-- errors if edges mention nodes not mentioned in the node list or if the+-- given graph contains cycles.+topSort+ :: [(Int, a)]+ -- ^ Nodes+ -> [(Int, Int)]+ -- ^ Edges+ -> Either String [a]+ -- ^ Error message or topologically sorted nodes+topSort [] [] = Right []+topSort [] _edges = Left "Node list was empty, but edges non-empty"+topSort nodes@(node:_) edges = do+ _ <- mapM (\(n, m) -> checkNode n >> checkNode m) edges++ (_, _, sorted) <-+ topSortVisit edges' (IntMap.keysSet nodes') IntMap.empty [] (fst node)++ mapM lookup' sorted+ where+ nodes' = IntMap.fromList nodes+ edges' = foldl insert IntMap.empty edges++ -- Construction functions for quick lookup of edges from n to m, given n+ insert im (n, m) = IntMap.alter (insert' m) n im+ insert' m Nothing = Just [m]+ insert' m (Just ms) = Just (m:ms)++ -- Lookup node in nodes map. If not present, yield error+ lookup' n =+ case IntMap.lookup n nodes' of+ Nothing+ -> Left ("Node " ++ show n ++ " in edge list, but not in node list.")+ Just n'+ -> Right n'++ -- Check if edge is valid (i.e., mentioned nodes are in node list)+ checkNode n+ | IntMap.notMember n nodes' =+ Left ("Node " ++ show n ++ " in edge list, but not in node list.")+ | otherwise =+ Right n++-- | Same as `reverse (topSort nodes edges)` if alternative representations are+-- considered the same. That is, topSort might produce multiple answers and+-- still deliver on its promise of yielding a topologically sorted node list.+-- Likewise, this function promises __one__ of those lists in reverse, but not+-- necessarily the reverse of topSort itself.+reverseTopSort+ :: [(Int, a)]+ -- ^ Nodes+ -> [(Int, Int)]+ -- ^ Edges+ -> Either String [a]+ -- ^ Reversely, topologically sorted nodes+reverseTopSort nodes edges =+ topSort nodes (map swap edges)
+ src/ClashDebug.h view
@@ -0,0 +1,5 @@+#pragma once++#define ASSERT(e) if debugIsOn && not (e) then (assertPanic __FILE__ __LINE__) else+#define ASSERT2(e,msg) if debugIsOn && not (e) then (assertPprPanic __FILE__ __LINE__ (msg)) else+#define WARN( e, msg ) (warnPprTrace (e) __FILE__ __LINE__ (msg)) $
src/Data/Aeson/Extra.hs view
@@ -6,6 +6,7 @@ module Data.Aeson.Extra where +import Control.Exception (throw) import qualified Data.Ix as Ix import qualified Data.Text as T import Data.Text (Text,pack,unpack)@@ -15,6 +16,11 @@ import Data.ByteString.Lazy (ByteString) import System.FilePath () +import Clash.Util (ClashException(..))+import SrcLoc (mkGeneralSrcSpan)+import FastString (mkFastString)+import GHC.Stack (HasCallStack)+ -- Quick and dirty way of replacing fake escapes in naively converted bytestring replaceCommonEscapes :: Text -> Text replaceCommonEscapes = ( T.replace (pack "\\n") (pack "\n") ) .@@ -38,24 +44,36 @@ allLines = T.lines $ replaceCommonEscapes $ pack $ show full interval = (max 0 (errorLineN - 5), min (max 0 $ length allLines - 1) (errorLineN + 5)) --- | Parse a ByteString according to the given JSON template. Prints failures--- on @stdout@, and returns 'Nothing' if parsing fails.-decodeOrErr :: (FromJSON a)- => FilePath- -> ByteString -- ^ Bytestring to parse- -> Maybe a+-- | Parse a ByteString according to the given JSON template. Throws exception+-- if it fails.+decodeOrErr+ :: (HasCallStack, FromJSON a)+ => FilePath+ -- ^ Path read from (for error message)+ -> ByteString+ -- ^ Bytestring to parse+ -> a decodeOrErr path contents = case parse json contents of- Done _ v -> case fromJSON v of- Success a -> Just a- Error msg -> error ("Could not deduce valid scheme for '" ++ show path ++ "'. Error was: \n\n" ++ msg)+ Done _ v ->+ case fromJSON v of+ Success a ->+ a+ Error msg ->+ clashError+ ( "Could not deduce valid scheme for json in "+ ++ show path ++ ". Error was: \n\n" ++ msg ) -- JSON parse error:- Fail bytes cntxs msg -> error ( "Could not read or parse " ++ show path ++ ". "- ++ (if null cntxs then "" else "Context was:\n " ++ intercalate "\n " cntxs)- ++ "\n\nError reported by Attoparsec was:\n "- ++ msg- ++ "\n\nApproximate location of error:\n\n"- -- HACK: Replace with proper parser/fail logic in future. Or don't. It's not important.- ++ (unpack $ genLineErr contents bytes)- )+ Fail bytes cntxs msg ->+ clashError+ ( "Could not read or parse json in " ++ show path ++ ". "+ ++ (if null cntxs then "" else "Context was:\n " ++ intercalate "\n " cntxs)+ ++ "\n\nError reported by Attoparsec was:\n "+ ++ msg+ ++ "\n\nApproximate location of error:\n\n"+ -- HACK: Replace with proper parser/fail logic in future. Or don't. It's not important.+ ++ (unpack $ genLineErr contents bytes) )+ where+ loc = mkGeneralSrcSpan $ mkFastString path+ clashError msg = throw $ ClashException loc msg Nothing
src/Data/Text/Prettyprint/Doc/Extra.hs view
@@ -15,7 +15,8 @@ import Control.Applicative import Data.String (IsString (..))-import Data.Text.Lazy as T+import Data.Text as T+import Data.Text.Lazy as LT import qualified Data.Text.Prettyprint.Doc as PP import Data.Text.Prettyprint.Doc.Internal hiding (Doc) import Data.Text.Prettyprint.Doc.Render.Text@@ -45,7 +46,7 @@ renderOneLine :: PP.Doc ann- -> Text+ -> LT.Text renderOneLine = renderLazy . layoutOneLine int :: Applicative f => Int -> f Doc@@ -139,7 +140,10 @@ pretty :: (Applicative f, Pretty a) => a -> f Doc pretty = pure . PP.pretty -string :: Applicative f => Text -> f Doc+stringS :: Applicative f => T.Text -> f Doc+stringS = pure . PP.pretty++string :: Applicative f => LT.Text -> f Doc string = pure . PP.pretty squotes :: Applicative f => f Doc -> f Doc@@ -151,6 +155,9 @@ align :: Functor f => f Doc -> f Doc align = fmap PP.align +hsep :: Functor f => f [Doc] -> f Doc+hsep = fmap PP.hsep+ vsep :: Functor f => f [Doc] -> f Doc vsep = fmap PP.vsep @@ -166,6 +173,9 @@ nesting :: Functor f => f (Int -> Doc) -> f Doc nesting = fmap PP.nesting++flatAlt :: Applicative f => f Doc -> f Doc -> f Doc+flatAlt = liftA2 PP.flatAlt instance Applicative f => IsString (f Doc) where fromString = string . fromString
src/GHC/BasicTypes/Extra.hs view
@@ -13,7 +13,9 @@ import BasicTypes import Control.DeepSeq+import Data.Binary import GHC.Generics deriving instance Generic InlineSpec instance NFData InlineSpec+instance Binary InlineSpec
src/GHC/SrcLoc/Extra.hs view
@@ -13,20 +13,20 @@ module GHC.SrcLoc.Extra where +import Data.Binary import Data.Hashable (Hashable (..)) import GHC.Generics import SrcLoc- (SrcSpan (..), RealSrcSpan, srcSpanFile, srcSpanStartLine, srcSpanEndLine,- srcSpanStartCol, srcSpanEndCol)-import FastString (FastString (..))-import Unbound.Generics.LocallyNameless (Alpha (..))-import Unbound.Generics.LocallyNameless.TH+ (SrcSpan (..), RealSrcLoc, RealSrcSpan,+ mkRealSrcLoc, mkRealSrcSpan,+ realSrcSpanStart, realSrcSpanEnd,+ srcLocFile, srcLocLine, srcLocCol,+ srcSpanFile, srcSpanStartLine, srcSpanEndLine, srcSpanStartCol, srcSpanEndCol)+import FastString (FastString (..), bytesFS, mkFastStringByteList) deriving instance Generic SrcSpan instance Hashable SrcSpan -makeClosedAlpha ''SrcSpan- instance Hashable RealSrcSpan where hashWithSalt salt rss = hashWithSalt salt (srcSpanFile rss,srcSpanStartLine rss, srcSpanEndLine rss@@ -35,3 +35,15 @@ instance Hashable FastString where hashWithSalt salt fs = hashWithSalt salt (uniq fs) +instance Binary SrcSpan+instance Binary RealSrcSpan where+ put r = put (realSrcSpanStart r, realSrcSpanEnd r)+ get = uncurry mkRealSrcSpan <$> get++instance Binary RealSrcLoc where+ put r = put (srcLocFile r, srcLocLine r, srcLocCol r)+ get = (\(file,line,col) -> mkRealSrcLoc file line col) <$> get++instance Binary FastString where+ put str = put $ bytesFS str+ get = mkFastStringByteList <$> get
− src/Unbound/Generics/LocallyNameless/Extra.hs
@@ -1,115 +0,0 @@-{-|- Copyright : (C) 2015-2016, University of Twente,- 2017, Google Inc.- License : BSD2 (see the file LICENSE)- Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>--}--{-# LANGUAGE CPP #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}--{-# OPTIONS_GHC -fno-warn-orphans #-}--module Unbound.Generics.LocallyNameless.Extra where--#ifndef MIN_VERSION_unbound_generics-#error MIN_VERSION_unbound_generics undefined-#endif--#if !MIN_VERSION_unbound_generics(0,2,0)-import Control.DeepSeq-#endif-import Data.Vector.Primitive-import Data.Hashable (Hashable(..),hash)-#if MIN_VERSION_unbound_generics(0,3,0)-import Data.Monoid-#endif-import Data.Text (Text)-import GHC.Real (Ratio)-#if MIN_VERSION_unbound_generics(0,3,0)-import Unbound.Generics.LocallyNameless.Alpha (Alpha (..), NamePatFind (..),- NthPatFind (..))-#else-import Unbound.Generics.LocallyNameless.Alpha (Alpha (..))-#endif-import Unbound.Generics.LocallyNameless.Bind (Bind (..))-import Unbound.Generics.LocallyNameless.Embed (Embed (..))-import Unbound.Generics.LocallyNameless.Name (Name (..))-#if !MIN_VERSION_unbound_generics(0,2,0)-import Unbound.Generics.LocallyNameless.Rec (unrec)-#endif-import Unbound.Generics.LocallyNameless.Rebind (Rebind (..))-import Unbound.Generics.LocallyNameless.Rec (Rec)-import Unbound.Generics.LocallyNameless.Subst (Subst (..))--#if !MIN_VERSION_unbound_generics(0,2,0)-instance (NFData a, NFData b) => NFData (Bind a b)-instance NFData a => NFData (Embed a)-instance NFData (Name a)-instance (NFData a, NFData b) => NFData (Rebind a b)-instance (Alpha a, NFData a) => NFData (Rec a) where- rnf r = seq (rnf (unrec r)) ()-#endif--instance Subst b (Ratio a) where- subst _ _ = id- substs _ = id--instance Hashable (Name a) where- hashWithSalt salt (Fn str int) = hashWithSalt salt (hashWithSalt (hash int) str)- hashWithSalt salt (Bn i0 i1) = hashWithSalt salt (hash i0 `hashWithSalt` i1)--instance (Hashable a, Hashable b) => Hashable (Bind a b)-instance Hashable a => Hashable (Embed a)-instance (Hashable a, Hashable b) => Hashable (Rebind a b)-instance Hashable a => Hashable (Rec a)--#if !MIN_VERSION_unbound_generics(0,2,0)-instance (Ord a) => Ord (Embed a) where- compare (Embed a) (Embed b) = compare a b-#endif--instance (Prim a, Ord a, Show a) => Alpha (Vector a) where- aeq' _ctx = (==)- fvAny' _ctx _nfn i = pure i- close _ctx _b = id- open _ctx _b = id- isPat _ = mempty-#if MIN_VERSION_unbound_generics(0,3,0)- isTerm _ = All True- nthPatFind _ = NthPatFind Left- namePatFind _ = NamePatFind (const (Left 0))-#else- isTerm _ = True- nthPatFind _ = Left- namePatFind _ _ = Left 0-#endif- swaps' _ctx _p = id- freshen' _ctx i = return (i, mempty)- lfreshen' _ctx i cont = cont i mempty- acompare' _ctx = compare--instance Alpha Text where- aeq' _ctx = (==)- fvAny' _ctx _nfn i = pure i- close _ctx _b = id- open _ctx _b = id- isPat _ = mempty-#if MIN_VERSION_unbound_generics(0,3,0)- isTerm _ = All True- nthPatFind _ = NthPatFind Left- namePatFind _ = NamePatFind (const (Left 0))-#else- isTerm _ = True- nthPatFind _ = Left- namePatFind _ _ = Left 0-#endif- swaps' _ctx _p = id- freshen' _ctx i = return (i, mempty)- lfreshen' _ctx i cont = cont i mempty- acompare' _ctx = compare--instance Subst b Text where- subst _ _ = id- substs _ = id