clash-lib-1.6.3: Clash: a functional hardware description language - As a library
Copyright(C) 2012-2016 University of Twente
2017 Myrtle Software Ltd
2017-2018 Google Inc.
2021-2022 QBayLogic B.V.
LicenseBSD2 (see the file LICENSE)
MaintainerQBayLogic B.V. <devops@qbaylogic.com>
Safe HaskellNone
LanguageHaskell2010

Clash.Netlist.Util

Description

Utilities for converting Core Type/Term to Netlist datatypes

Synopsis

Documentation

hmFindWithDefault :: (Eq k, Hashable k) => v -> k -> HashMap k v -> v Source #

instPort :: Text -> Expr Source #

Generate a simple port_name expression. See:

https://www.hdlworks.com/hdl_corner/vhdl_ref/VHDLContents/PortMap.htm

This function will simply make the left part of a single port map, e.g. Rst in:

Rst => Reset

If you need more complex constructions, e.g.

Q(3 downto 1)

you can build an Expr manually.

stripFiltered :: FilteredHWType -> HWType Source #

Throw away information indicating which constructor fields were filtered due to being void.

stripVoid :: HWType -> HWType Source #

Strip as many Void layers as possible. Might still return a Void if the void doesn't contain a hwtype.

isVoid :: HWType -> Bool Source #

Determines if type is a zero-width construct ("void")

isFilteredVoid :: FilteredHWType -> Bool Source #

Same as isVoid, but on FilteredHWType instead of HWType

splitNormalized :: TyConMap -> Term -> Either String ([Id], [LetBinding], Id) Source #

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.

unsafeCoreTypeToHWType Source #

Arguments

:: SrcSpan

Approximate location in original source file

-> String 
-> (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) 
-> CustomReprs 
-> TyConMap 
-> Type 
-> State HWMap FilteredHWType 

Converts a Core type to a HWType given a function that translates certain builtin types. Errors if the Core type is not translatable.

unsafeCoreTypeToHWTypeM' :: String -> Type -> NetlistMonad HWType Source #

Same as unsafeCoreTypeToHWTypeM, but discards void filter information

unsafeCoreTypeToHWTypeM :: String -> Type -> NetlistMonad FilteredHWType Source #

Converts a Core type to a HWType within the NetlistMonad; errors on failure

coreTypeToHWTypeM' Source #

Arguments

:: Type

Type to convert to HWType

-> NetlistMonad (Maybe HWType) 

Same as coreTypeToHWTypeM, but discards void filter information

coreTypeToHWTypeM Source #

Arguments

:: Type

Type to convert to HWType

-> NetlistMonad (Maybe FilteredHWType) 

Converts a Core type to a HWType within the NetlistMonad; Nothing on failure

unexpectedProjectionErrorMsg Source #

Arguments

:: DataRepr' 
-> Int

Constructor index

-> Int

Field index

-> String 

Constructs error message for unexpected projections out of a type annotated with a custom bit representation.

convertToCustomRepr :: HasCallStack => CustomReprs -> DataRepr' -> HWType -> HWType Source #

Helper function of maybeConvertToCustomRepr

maybeConvertToCustomRepr Source #

Arguments

:: CustomReprs

Map containing all custom representations index on its type

-> Type

Custom reprs are index on type, so we need the clash core type to look it up.

-> FilteredHWType

Type of previous argument represented as a HWType

-> FilteredHWType 

Given a map containing custom bit representation, a type, and the same type represented as HWType, convert the HWType to a CustomSP/CustomSum if it has a custom bit representation.

coreTypeToHWType' Source #

Arguments

:: (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) 
-> CustomReprs 
-> TyConMap 
-> Type

Type to convert to HWType

-> State HWMap (Either String HWType) 

Same as coreTypeToHWType, but discards void filter information

coreTypeToHWType Source #

Arguments

:: (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) 
-> CustomReprs 
-> TyConMap 
-> Type

Type to convert to HWType

-> State HWMap (Either String FilteredHWType) 

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.

originalIndices Source #

Arguments

:: [Bool]

Were voids. Length must be less than or equal to n.

-> [Int]

Original indices

Generates original indices in list before filtering, given a list of removed indices.

>>> originalIndices [False, False, True, False]
[0,1,3]

mkADT Source #

Arguments

:: (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.

Converts an algebraic Core type (split into a TyCon and its argument) to a HWType.

hasUnconstrainedExistential :: TyConMap -> DataCon -> Bool Source #

Determine whether a data constructor has unconstrained existential type variables, i.e. those that cannot be inferred by the (potential) constraints between the existential type variables and universal type variables.

So here we have an example of a constrained existential:

data Vec :: Nat -> Type -> Type where Nil :: Vec 0 a Cons :: forall m . (n ~ m + 1) => a -> Vec m a -> Vec n a

where we can generate a type for m when we know n (by doing `n-1`).

And here is an example of an unconstrained existential:

data SomeSNat where where SomeSNat :: forall m . SNat m -> SomeSNat

where there is no way to generate a type for m from any context.

So why do we care? Because terms need to be completely monomorphic in order to be translated to circuits. And having a topEntity lambda-bound variable with an unconstrained existential type prevents us from achieving a fully monomorphic term.

isRecursiveTy :: TyConMap -> TyConName -> Bool Source #

Simple check if a TyCon is recursively defined.

Note [Look through type families in recursivity check]

Consider:

data SList :: [Type] -> Type where
  SNil  :: SList []
  CSons :: a -> Sing (as :: [k]) -> SList (a:as)

type family Sing [a] = SList [a]

Without looking through type families, we would think that SList is not recursive. This lead to issue #1921

representableType Source #

Arguments

:: (CustomReprs -> TyConMap -> Type -> State HWMap (Maybe (Either String FilteredHWType))) 
-> CustomReprs 
-> Bool

String considered representable

-> TyConMap 
-> Type 
-> Bool 

Determines if a Core type is translatable to a HWType given a function that translates certain builtin types.

typeSize :: HWType -> Int Source #

Determines the bitsize of a type. For types that don't get turned into real values in hardware (string, integer) the size is 0.

conSize :: HWType -> Int Source #

Determines the bitsize of the constructor of a type

termHWType :: String -> Term -> NetlistMonad HWType Source #

Gives the HWType corresponding to a term. Returns an error if the term has a Core type that is not translatable to a HWType.

termHWTypeM Source #

Arguments

:: Term

Term to convert to HWType

-> NetlistMonad (Maybe FilteredHWType) 

Gives the HWType corresponding to a term. Returns Nothing if the term has a Core type that is not translatable to a HWType.

mkUniqueNormalized Source #

Arguments

:: HasCallStack 
=> 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) 

Uniquely rename all the variables and their references in a normalized term

orNothing :: Bool -> a -> Maybe a Source #

Produce a Just when predicate is True, else Nothing

renameBinder :: (Id, Term) -> NetlistMonad [(Id, Id)] Source #

Set the name of the binder if the given term is a blackbox requesting a specific name for the result binder. It might return multiple names in case of a multi result primitive.

evalBlackBox :: HasCallStack => SomeBackend -> BlackBoxContext -> BlackBox -> Text Source #

Render a blackbox given its context. Renders _just_ the blackbox, not any corresponding includes, libraries, and so forth.

mkUniqueArguments Source #

Arguments

:: Subst 
-> Maybe (ExpandedTopEntity Identifier)

Top entity annotation where:

  • Nothing: term is not a top entity
  • Just ..: term is a top entity
-> [Id] 
-> NetlistMonad ([Bool], [(Identifier, HWType)], [Declaration], Subst) 

mkUniqueResult Source #

Arguments

:: Subst 
-> Maybe (ExpandedTopEntity Identifier)

Top entity annotation where:

  • Nothing: term is not a top entity
  • Just ..: term is a top entity
-> Id 
-> NetlistMonad (Maybe ([(Identifier, HWType)], [Declaration], Id, Subst)) 

idToInPort :: Id -> NetlistMonad (Maybe (Identifier, HWType)) Source #

Same as idToPort, but * Throws an error if the port is a composite type with a BiSignalIn

idToOutPort :: Id -> NetlistMonad (Maybe (Identifier, HWType)) Source #

Same as idToPort, but: * Throws an error if port is of type BiSignalIn

mkUnique Source #

Arguments

:: Subst

Existing substitution

-> [Id]

IDs to make unique

-> NetlistMonad ([Id], Subst)

(Unique IDs, update substitution)

Make a set of IDs unique; also returns a substitution from old ID to new updated unique ID.

preserveState :: NetlistMonad a -> NetlistMonad a Source #

Preserve the complete state before running an action, and restore it afterwards.

preserveVarEnv :: NetlistMonad a -> NetlistMonad a Source #

Preserve the Netlist _curCompNm,_seenIds when executing a monadic action

TopEntity Annotations

extendPorts :: [PortName] -> [Maybe PortName] Source #

prefixParent :: String -> PortName -> PortName Source #

Prefix given string before portnames except when this string is empty.

toPrimitiveType :: Identifier -> HWType -> NetlistMonad ([Declaration], Identifier, Expr, HWType) Source #

Top entities only expose primitive types or types that don't need explicit conversion to a primitive type (i.e., no types from the _types module). This function converts from a custom type to a primitive type if needed.

See HWKind for more info on primitive type kinds.

fromPrimitiveType :: Identifier -> HWType -> NetlistMonad ([Declaration], Identifier, Expr, HWType) Source #

Top entities only expose primitive types or types that don't need explicit conversion to a primitive type (i.e., no types from the _types module). This function converts from a primitive type to a custom type if needed.

See HWKind for more info on primitive type kinds.

mkTopInput Source #

Arguments

:: ExpandedPortName Identifier

Port name description

-> NetlistMonad ([(Identifier, HWType)], [Declaration], Expr, Identifier)

(port names, signal decls for intermediate signals, argument expr, argument id)

Create port names for the declaration of a top entity. For instantiation see mkTopInstInput.

mkVectorChain :: Int -> HWType -> [Expr] -> Expr Source #

Create a Vector chain for a list of Identifiers

mkRTreeChain :: Int -> HWType -> [Expr] -> Expr Source #

Create a RTree chain for a list of Identifiers

genComponentName Source #

Arguments

:: Bool

New inline strategy enabled

-> Maybe Text

Component name prefix

-> Id

Create component name based on this Core Id

-> Text 

genTopName Source #

Arguments

:: IdentifierSetMonad m 
=> Maybe Text

Top entity name prefix

-> TopEntity

Top entity annotation

-> m Identifier

New identifier

stripAttributes :: HWType -> ([Attr'], HWType) Source #

Strips one or more layers of attributes from a HWType; stops at first non-Annotated. Accumulates all attributes of nested annotations.

mkTopOutput :: ExpandedPortName Identifier -> NetlistMonad ([(Identifier, HWType)], [Declaration], Identifier) Source #

Create output port names for the declaration of a top entity. For instantiation see mkTopInstOutput.

mkTopCompDecl Source #

Arguments

:: Maybe Text

Library entity is defined in

-> [Attr']

Attributes to add to generate code

-> Identifier

The component's (or entity's) name

-> Identifier

Instance label

-> [(Expr, HWType, Expr)]

List of parameters for this component (param name, param type, param value)

-> [InstancePort]

Input port assignments

-> [InstancePort]

Output port assignments

-> Declaration 

mkTopUnWrapper Source #

Arguments

:: Id

Name of the TopEntity component

-> ExpandedTopEntity Identifier

A corresponding TopEntity annotation

-> (Identifier, HWType)

The name and type of the signal to which to assign the result

-> [(Expr, HWType)]

The arguments with voids filtered.

-> [Declaration]

Tick declarations

-> NetlistMonad [Declaration] 

Instantiate a TopEntity, and add the proper type-conversions where needed

data InstancePort Source #

Constructors

InstancePort 

Fields

  • ip_id :: Identifier

    Identifier to assign. Top entities are instantiated using positional arguments, so this doesn't hold a port name.

  • ip_type :: HWType

    Type assigned to port

mkTopInstInput Source #

Arguments

:: ExpandedPortName Identifier

The PortName of a _TopEntity_ annotation for this input.

-> NetlistMonad ([InstancePort], [Declaration], Identifier)

(ports to assign, declarations for intermediate signals, argument signal)

Generate input port(s) associated with a single argument for an instantiation of a top entity. This function composes the input ports into a single signal and returns its name.

throwAnnotatedSplitError :: String -> String -> NetlistMonad a Source #

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.

mkTopInstOutput Source #

Arguments

:: HasCallStack 
=> ExpandedPortName Identifier

The PortName of a _TopEntity_ annotation for this output

-> NetlistMonad ([InstancePort], [Declaration], Identifier)

(ports to assign, declarations for intermediate signals, result signal)

Generate output port(s) for an instantiation of a top entity. This function combines all output ports into a signal identifier and returns its name.

nestM :: Modifier -> Modifier -> Maybe Modifier Source #

Try to merge nested modifiers into a single modifier, needed by the VHDL and SystemVerilog backend.

bindsExistentials :: [TyVar] -> [Var a] -> Bool Source #

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.

withTicks Source #

Arguments

:: [TickInfo] 
-> ([Declaration] -> NetlistMonad a)

The source ticks are turned into TickDecls and are passed as an argument to the NetlistMonad computation. Name modifier ticks will change the local environment for the NetlistMonad computation.

-> NetlistMonad a 

Run a NetlistMonad computation in the context of the given source ticks and name modifier ticks

affixName :: Text -> NetlistMonad Text Source #

Add the pre- and suffix names in the current environment to the given identifier

data ExpandError Source #

Errors expandTopEntity might yield

Constructors

AttrError [Attr']

Synthesis attributes are not supported on PortProducts

PortProductError PortName HWType

Something was annotated as being a PortProduct, but wasn't one

expandTopEntityOrErrM Source #

Arguments

:: (HasCallStack, IdentifierSetMonad m) 
=> [(Maybe Id, FilteredHWType)]

Arguments. Ids are used as name hints.

-> (Maybe Id, FilteredHWType)

Result. Id is used as name hint.

-> Maybe TopEntity

If Nothing, an expanded top entity will be generated as if defSyn was passed.

-> m (ExpandedTopEntity Identifier)

Either some error (see ExpandError) or and expanded top entity. All identifiers in the expanded top entity will be added to NetlistState's IdentifierSet.

Same as expandTopEntity, but also adds identifiers to the identifier set of the monad.

expandTopEntityOrErr Source #

Arguments

:: HasCallStack 
=> IdentifierSet

Settings of this IdentifierSet will be used to generate valid identifiers. Note that the generated identifiers are not guaranteed to be unique w.r.t. this set.

-> [(Maybe Id, FilteredHWType)]

Arguments. Ids are used as name hints.

-> (Maybe Id, FilteredHWType)

Result. Id is used as name hint.

-> Maybe TopEntity

If Nothing, an expanded top entity will be generated as if defSyn was passed.

-> ExpandedTopEntity Identifier

Either some error (see ExpandError) or and expanded top entity. All identifiers in the expanded top entity will be added to NetlistState's IdentifierSet.

Take a top entity and expand its port names. I.e., make sure that every port that should be generated in the HDL is part of the data structure.

expandTopEntity Source #

Arguments

:: HasCallStack 
=> [(Maybe Id, FilteredHWType)]

Arguments. Ids are used as name hints.

-> (Maybe Id, FilteredHWType)

Result. Id is used as name hint.

-> Maybe TopEntity

Top entity to expand

-> Either ExpandError (ExpandedTopEntity (Either Text Text))

Either some error (see ExpandError) or and expanded top entity. The expanded top entity in turn contains an Either too. Left means that the name was supplied by the user and should be inserted at verbatim, Right is a name generated by Clash.

Take a top entity and expand its port names. I.e., make sure that every port that should be generated in the HDL is part of the data structure. It works on FilteredHWType in order to generate stable port names.