    {-|
      Copyright  :  (C) 2012-2016, University of Twente,
                        2017     , Myrtle Software Ltd,
                        2017-2018, Google Inc.
                        2020-2023, QBayLogic B.V.
                        2022-2023, Google Inc.
      License    :  BSD2 (see the file LICENSE)
      Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>

      Type and instance definitions for Netlist modules
    -}

    {-# LANGUAGE CPP #-}
    {-# LANGUAGE DeriveAnyClass #-}
    {-# LANGUAGE FunctionalDependencies #-}
    {-# LANGUAGE FlexibleInstances #-}
    {-# LANGUAGE GADTs #-}
    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    {-# LANGUAGE LambdaCase #-}
    {-# LANGUAGE MagicHash #-}
    {-# LANGUAGE OverloadedStrings #-}
    {-# LANGUAGE PatternSynonyms #-}
    {-# LANGUAGE RankNTypes #-}
    {-# LANGUAGE TemplateHaskell #-}

    module Clash.Netlist.Types
      ( Declaration (..,NetDecl)
      , module Clash.Netlist.Types
      )
    where

    import Control.DeepSeq
    import qualified Control.Lens               as Lens
    import Control.Lens                         (Lens', (.=))
    #if !MIN_VERSION_base(4,13,0)
    import Control.Monad.Fail                   (MonadFail)
    #endif
    import Control.Monad.Reader                 (ReaderT, MonadReader)
    import qualified Control.Monad.State        as Lazy (State)
    import qualified Control.Monad.State.Strict as Strict
      (State, MonadIO, MonadState, StateT)
    import Data.Aeson                           (FromJSON(..))
    import qualified Data.Aeson as Aeson
    import Data.Bits                            (testBit)
    import Data.Binary                          (Binary(..))
    import Data.Function                        (on)
    import Data.Hashable                        (Hashable(hash,hashWithSalt))
    import Data.HashMap.Strict                  (HashMap)
    import Data.HashSet                         (HashSet)
    import qualified Data.List                  as List
    import Data.IntMap                          (IntMap, empty)
    import Data.Map.Ordered                     (OMap)
    import Data.Map                             (Map)
    import qualified Data.Map as Map
    import Data.Maybe                           (mapMaybe)
    import Data.Monoid                          (Ap(..))
    import qualified Data.Set                   as Set
    import Data.Text                            (Text)

    import Data.Typeable                        (Typeable)
    import Data.Text.Prettyprint.Doc.Extra      (Doc)
    import GHC.Generics                         (Generic)
    import GHC.Stack
    import Language.Haskell.TH.Syntax           (Lift)

    #if MIN_VERSION_ghc(9,0,0)
    import GHC.Types.SrcLoc                     (SrcSpan)
    #else
    import SrcLoc                               (SrcSpan)
    #endif

    import Clash.Annotations.SynthesisAttributes(Attr)
    import Clash.Annotations.BitRepresentation  (FieldAnn)
    import Clash.Annotations.Primitive          (HDL(..))
    import Clash.Annotations.TopEntity          (TopEntity)
    import Clash.Backend                        (Backend, HasUsageMap (..))
    import Clash.Core.HasType
    import Clash.Core.Type                      (Type)
    import Clash.Core.Var                       (Id)
    import Clash.Core.TyCon                     (TyConMap)
    import Clash.Core.VarEnv                    (VarEnv)
    import Clash.Driver.Types                   (BindingMap, ClashEnv(..), ClashOpts(..))
    import Clash.Netlist.BlackBox.Types         (BlackBoxTemplate)
    import Clash.Primitives.Types               (CompiledPrimMap)
    import Clash.Signal.Internal
      (ResetPolarity, ActiveEdge, ResetKind, InitBehavior)
    import Clash.Unique                         (Unique)

    import Clash.Annotations.BitRepresentation.Internal
      (CustomReprs, DataRepr', ConstrRepr')

    import {-# SOURCE #-} qualified Clash.Netlist.Id as Id (toText)

    -- | Structure describing a top entity: it's id and its port annotations.
    data TopEntityT = TopEntityT
      { TopEntityT -> Id
    topId :: Id
      -- ^ Id of top entity
      , TopEntityT -> Maybe TopEntity
    topAnnotation :: Maybe TopEntity
      -- ^ (Maybe) a topentity annotation
      , TopEntityT -> Bool
    topIsTestBench :: Bool
      -- ^ Whether this entity is a test bench
      } deriving ((forall x. TopEntityT -> Rep TopEntityT x)
    -> (forall x. Rep TopEntityT x -> TopEntityT) -> Generic TopEntityT
    forall x. Rep TopEntityT x -> TopEntityT
    forall x. TopEntityT -> Rep TopEntityT x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. TopEntityT -> Rep TopEntityT x
    from :: forall x. TopEntityT -> Rep TopEntityT x
    $cto :: forall x. Rep TopEntityT x -> TopEntityT
    to :: forall x. Rep TopEntityT x -> TopEntityT
    Generic, Int -> TopEntityT -> ShowS
    [TopEntityT] -> ShowS
    TopEntityT -> String
    (Int -> TopEntityT -> ShowS)
    -> (TopEntityT -> String)
    -> ([TopEntityT] -> ShowS)
    -> Show TopEntityT
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> TopEntityT -> ShowS
    showsPrec :: Int -> TopEntityT -> ShowS
    $cshow :: TopEntityT -> String
    show :: TopEntityT -> String
    $cshowList :: [TopEntityT] -> ShowS
    showList :: [TopEntityT] -> ShowS
    Show, TopEntityT -> TopEntityT -> Bool
    (TopEntityT -> TopEntityT -> Bool)
    -> (TopEntityT -> TopEntityT -> Bool) -> Eq TopEntityT
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: TopEntityT -> TopEntityT -> Bool
    == :: TopEntityT -> TopEntityT -> Bool
    $c/= :: TopEntityT -> TopEntityT -> Bool
    /= :: TopEntityT -> TopEntityT -> Bool
    Eq)

    -- | Same as "TopEntity", but with all port names that end up in HDL specified
    data ExpandedTopEntity a = ExpandedTopEntity
      { forall a. ExpandedTopEntity a -> [Maybe (ExpandedPortName a)]
    et_inputs :: [Maybe (ExpandedPortName a)]
      -- ^ Inputs with fully expanded port names. /Nothing/ if port is void.
      , forall a. ExpandedTopEntity a -> Maybe (ExpandedPortName a)
    et_output :: Maybe (ExpandedPortName a)
      -- ^ Output with fully expanded port names. /Nothing/ if port is void or
      -- BiDirectionalOut.
      } deriving (Int -> ExpandedTopEntity a -> ShowS
    [ExpandedTopEntity a] -> ShowS
    ExpandedTopEntity a -> String
    (Int -> ExpandedTopEntity a -> ShowS)
    -> (ExpandedTopEntity a -> String)
    -> ([ExpandedTopEntity a] -> ShowS)
    -> Show (ExpandedTopEntity a)
    forall a. Show a => Int -> ExpandedTopEntity a -> ShowS
    forall a. Show a => [ExpandedTopEntity a] -> ShowS
    forall a. Show a => ExpandedTopEntity a -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: forall a. Show a => Int -> ExpandedTopEntity a -> ShowS
    showsPrec :: Int -> ExpandedTopEntity a -> ShowS
    $cshow :: forall a. Show a => ExpandedTopEntity a -> String
    show :: ExpandedTopEntity a -> String
    $cshowList :: forall a. Show a => [ExpandedTopEntity a] -> ShowS
    showList :: [ExpandedTopEntity a] -> ShowS
    Show, (forall a b.
     (a -> b) -> ExpandedTopEntity a -> ExpandedTopEntity b)
    -> (forall a b. a -> ExpandedTopEntity b -> ExpandedTopEntity a)
    -> Functor ExpandedTopEntity
    forall a b. a -> ExpandedTopEntity b -> ExpandedTopEntity a
    forall a b. (a -> b) -> ExpandedTopEntity a -> ExpandedTopEntity b
    forall (f :: Type -> Type).
    (forall a b. (a -> b) -> f a -> f b)
    -> (forall a b. a -> f b -> f a) -> Functor f
    $cfmap :: forall a b. (a -> b) -> ExpandedTopEntity a -> ExpandedTopEntity b
    fmap :: forall a b. (a -> b) -> ExpandedTopEntity a -> ExpandedTopEntity b
    $c<$ :: forall a b. a -> ExpandedTopEntity b -> ExpandedTopEntity a
    <$ :: forall a b. a -> ExpandedTopEntity b -> ExpandedTopEntity a
    Functor, (forall m. Monoid m => ExpandedTopEntity m -> m)
    -> (forall m a. Monoid m => (a -> m) -> ExpandedTopEntity a -> m)
    -> (forall m a. Monoid m => (a -> m) -> ExpandedTopEntity a -> m)
    -> (forall a b. (a -> b -> b) -> b -> ExpandedTopEntity a -> b)
    -> (forall a b. (a -> b -> b) -> b -> ExpandedTopEntity a -> b)
    -> (forall b a. (b -> a -> b) -> b -> ExpandedTopEntity a -> b)
    -> (forall b a. (b -> a -> b) -> b -> ExpandedTopEntity a -> b)
    -> (forall a. (a -> a -> a) -> ExpandedTopEntity a -> a)
    -> (forall a. (a -> a -> a) -> ExpandedTopEntity a -> a)
    -> (forall a. ExpandedTopEntity a -> [a])
    -> (forall a. ExpandedTopEntity a -> Bool)
    -> (forall a. ExpandedTopEntity a -> Int)
    -> (forall a. Eq a => a -> ExpandedTopEntity a -> Bool)
    -> (forall a. Ord a => ExpandedTopEntity a -> a)
    -> (forall a. Ord a => ExpandedTopEntity a -> a)
    -> (forall a. Num a => ExpandedTopEntity a -> a)
    -> (forall a. Num a => ExpandedTopEntity a -> a)
    -> Foldable ExpandedTopEntity
    forall a. Eq a => a -> ExpandedTopEntity a -> Bool
    forall a. Num a => ExpandedTopEntity a -> a
    forall a. Ord a => ExpandedTopEntity a -> a
    forall m. Monoid m => ExpandedTopEntity m -> m
    forall a. ExpandedTopEntity a -> Bool
    forall a. ExpandedTopEntity a -> Int
    forall a. ExpandedTopEntity a -> [a]
    forall a. (a -> a -> a) -> ExpandedTopEntity a -> a
    forall m a. Monoid m => (a -> m) -> ExpandedTopEntity a -> m
    forall b a. (b -> a -> b) -> b -> ExpandedTopEntity a -> b
    forall a b. (a -> b -> b) -> b -> ExpandedTopEntity a -> b
    forall (t :: Type -> Type).
    (forall m. Monoid m => t m -> m)
    -> (forall m a. Monoid m => (a -> m) -> t a -> m)
    -> (forall m a. Monoid m => (a -> m) -> t a -> m)
    -> (forall a b. (a -> b -> b) -> b -> t a -> b)
    -> (forall a b. (a -> b -> b) -> b -> t a -> b)
    -> (forall b a. (b -> a -> b) -> b -> t a -> b)
    -> (forall b a. (b -> a -> b) -> b -> t a -> b)
    -> (forall a. (a -> a -> a) -> t a -> a)
    -> (forall a. (a -> a -> a) -> t a -> a)
    -> (forall a. t a -> [a])
    -> (forall a. t a -> Bool)
    -> (forall a. t a -> Int)
    -> (forall a. Eq a => a -> t a -> Bool)
    -> (forall a. Ord a => t a -> a)
    -> (forall a. Ord a => t a -> a)
    -> (forall a. Num a => t a -> a)
    -> (forall a. Num a => t a -> a)
    -> Foldable t
    $cfold :: forall m. Monoid m => ExpandedTopEntity m -> m
    fold :: forall m. Monoid m => ExpandedTopEntity m -> m
    $cfoldMap :: forall m a. Monoid m => (a -> m) -> ExpandedTopEntity a -> m
    foldMap :: forall m a. Monoid m => (a -> m) -> ExpandedTopEntity a -> m
    $cfoldMap' :: forall m a. Monoid m => (a -> m) -> ExpandedTopEntity a -> m
    foldMap' :: forall m a. Monoid m => (a -> m) -> ExpandedTopEntity a -> m
    $cfoldr :: forall a b. (a -> b -> b) -> b -> ExpandedTopEntity a -> b
    foldr :: forall a b. (a -> b -> b) -> b -> ExpandedTopEntity a -> b
    $cfoldr' :: forall a b. (a -> b -> b) -> b -> ExpandedTopEntity a -> b
    foldr' :: forall a b. (a -> b -> b) -> b -> ExpandedTopEntity a -> b
    $cfoldl :: forall b a. (b -> a -> b) -> b -> ExpandedTopEntity a -> b
    foldl :: forall b a. (b -> a -> b) -> b -> ExpandedTopEntity a -> b
    $cfoldl' :: forall b a. (b -> a -> b) -> b -> ExpandedTopEntity a -> b
    foldl' :: forall b a. (b -> a -> b) -> b -> ExpandedTopEntity a -> b
    $cfoldr1 :: forall a. (a -> a -> a) -> ExpandedTopEntity a -> a
    foldr1 :: forall a. (a -> a -> a) -> ExpandedTopEntity a -> a
    $cfoldl1 :: forall a. (a -> a -> a) -> ExpandedTopEntity a -> a
    foldl1 :: forall a. (a -> a -> a) -> ExpandedTopEntity a -> a
    $ctoList :: forall a. ExpandedTopEntity a -> [a]
    toList :: forall a. ExpandedTopEntity a -> [a]
    $cnull :: forall a. ExpandedTopEntity a -> Bool
    null :: forall a. ExpandedTopEntity a -> Bool
    $clength :: forall a. ExpandedTopEntity a -> Int
    length :: forall a. ExpandedTopEntity a -> Int
    $celem :: forall a. Eq a => a -> ExpandedTopEntity a -> Bool
    elem :: forall a. Eq a => a -> ExpandedTopEntity a -> Bool
    $cmaximum :: forall a. Ord a => ExpandedTopEntity a -> a
    maximum :: forall a. Ord a => ExpandedTopEntity a -> a
    $cminimum :: forall a. Ord a => ExpandedTopEntity a -> a
    minimum :: forall a. Ord a => ExpandedTopEntity a -> a
    $csum :: forall a. Num a => ExpandedTopEntity a -> a
    sum :: forall a. Num a => ExpandedTopEntity a -> a
    $cproduct :: forall a. Num a => ExpandedTopEntity a -> a
    product :: forall a. Num a => ExpandedTopEntity a -> a
    Foldable, Functor ExpandedTopEntity
    Foldable ExpandedTopEntity
    Functor ExpandedTopEntity
    -> Foldable ExpandedTopEntity
    -> (forall (f :: Type -> Type) a b.
        Applicative f =>
        (a -> f b) -> ExpandedTopEntity a -> f (ExpandedTopEntity b))
    -> (forall (f :: Type -> Type) a.
        Applicative f =>
        ExpandedTopEntity (f a) -> f (ExpandedTopEntity a))
    -> (forall (m :: Type -> Type) a b.
        Monad m =>
        (a -> m b) -> ExpandedTopEntity a -> m (ExpandedTopEntity b))
    -> (forall (m :: Type -> Type) a.
        Monad m =>
        ExpandedTopEntity (m a) -> m (ExpandedTopEntity a))
    -> Traversable ExpandedTopEntity
    forall (t :: Type -> Type).
    Functor t
    -> Foldable t
    -> (forall (f :: Type -> Type) a b.
        Applicative f =>
        (a -> f b) -> t a -> f (t b))
    -> (forall (f :: Type -> Type) a.
        Applicative f =>
        t (f a) -> f (t a))
    -> (forall (m :: Type -> Type) a b.
        Monad m =>
        (a -> m b) -> t a -> m (t b))
    -> (forall (m :: Type -> Type) a. Monad m => t (m a) -> m (t a))
    -> Traversable t
    forall (m :: Type -> Type) a.
    Monad m =>
    ExpandedTopEntity (m a) -> m (ExpandedTopEntity a)
    forall (f :: Type -> Type) a.
    Applicative f =>
    ExpandedTopEntity (f a) -> f (ExpandedTopEntity a)
    forall (m :: Type -> Type) a b.
    Monad m =>
    (a -> m b) -> ExpandedTopEntity a -> m (ExpandedTopEntity b)
    forall (f :: Type -> Type) a b.
    Applicative f =>
    (a -> f b) -> ExpandedTopEntity a -> f (ExpandedTopEntity b)
    $ctraverse :: forall (f :: Type -> Type) a b.
    Applicative f =>
    (a -> f b) -> ExpandedTopEntity a -> f (ExpandedTopEntity b)
    traverse :: forall (f :: Type -> Type) a b.
    Applicative f =>
    (a -> f b) -> ExpandedTopEntity a -> f (ExpandedTopEntity b)
    $csequenceA :: forall (f :: Type -> Type) a.
    Applicative f =>
    ExpandedTopEntity (f a) -> f (ExpandedTopEntity a)
    sequenceA :: forall (f :: Type -> Type) a.
    Applicative f =>
    ExpandedTopEntity (f a) -> f (ExpandedTopEntity a)
    $cmapM :: forall (m :: Type -> Type) a b.
    Monad m =>
    (a -> m b) -> ExpandedTopEntity a -> m (ExpandedTopEntity b)
    mapM :: forall (m :: Type -> Type) a b.
    Monad m =>
    (a -> m b) -> ExpandedTopEntity a -> m (ExpandedTopEntity b)
    $csequence :: forall (m :: Type -> Type) a.
    Monad m =>
    ExpandedTopEntity (m a) -> m (ExpandedTopEntity a)
    sequence :: forall (m :: Type -> Type) a.
    Monad m =>
    ExpandedTopEntity (m a) -> m (ExpandedTopEntity a)
    Traversable)

    -- | See "ExpandedTopEntity"
    data ExpandedPortName a
      -- | Same as "PortName", but fully expanded
      = ExpandedPortName HWType a

      -- | Same as "PortProduct", but fully expanded
      | ExpandedPortProduct
          Text
          -- ^ Name hint. Can be used to create intermediate signal names.
          HWType
          -- ^ Type of product
          [ExpandedPortName a]
          -- ^ Product fields
      deriving (Int -> ExpandedPortName a -> ShowS
    [ExpandedPortName a] -> ShowS
    ExpandedPortName a -> String
    (Int -> ExpandedPortName a -> ShowS)
    -> (ExpandedPortName a -> String)
    -> ([ExpandedPortName a] -> ShowS)
    -> Show (ExpandedPortName a)
    forall a. Show a => Int -> ExpandedPortName a -> ShowS
    forall a. Show a => [ExpandedPortName a] -> ShowS
    forall a. Show a => ExpandedPortName a -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: forall a. Show a => Int -> ExpandedPortName a -> ShowS
    showsPrec :: Int -> ExpandedPortName a -> ShowS
    $cshow :: forall a. Show a => ExpandedPortName a -> String
    show :: ExpandedPortName a -> String
    $cshowList :: forall a. Show a => [ExpandedPortName a] -> ShowS
    showList :: [ExpandedPortName a] -> ShowS
    Show, (forall a b. (a -> b) -> ExpandedPortName a -> ExpandedPortName b)
    -> (forall a b. a -> ExpandedPortName b -> ExpandedPortName a)
    -> Functor ExpandedPortName
    forall a b. a -> ExpandedPortName b -> ExpandedPortName a
    forall a b. (a -> b) -> ExpandedPortName a -> ExpandedPortName b
    forall (f :: Type -> Type).
    (forall a b. (a -> b) -> f a -> f b)
    -> (forall a b. a -> f b -> f a) -> Functor f
    $cfmap :: forall a b. (a -> b) -> ExpandedPortName a -> ExpandedPortName b
    fmap :: forall a b. (a -> b) -> ExpandedPortName a -> ExpandedPortName b
    $c<$ :: forall a b. a -> ExpandedPortName b -> ExpandedPortName a
    <$ :: forall a b. a -> ExpandedPortName b -> ExpandedPortName a
    Functor, (forall m. Monoid m => ExpandedPortName m -> m)
    -> (forall m a. Monoid m => (a -> m) -> ExpandedPortName a -> m)
    -> (forall m a. Monoid m => (a -> m) -> ExpandedPortName a -> m)
    -> (forall a b. (a -> b -> b) -> b -> ExpandedPortName a -> b)
    -> (forall a b. (a -> b -> b) -> b -> ExpandedPortName a -> b)
    -> (forall b a. (b -> a -> b) -> b -> ExpandedPortName a -> b)
    -> (forall b a. (b -> a -> b) -> b -> ExpandedPortName a -> b)
    -> (forall a. (a -> a -> a) -> ExpandedPortName a -> a)
    -> (forall a. (a -> a -> a) -> ExpandedPortName a -> a)
    -> (forall a. ExpandedPortName a -> [a])
    -> (forall a. ExpandedPortName a -> Bool)
    -> (forall a. ExpandedPortName a -> Int)
    -> (forall a. Eq a => a -> ExpandedPortName a -> Bool)
    -> (forall a. Ord a => ExpandedPortName a -> a)
    -> (forall a. Ord a => ExpandedPortName a -> a)
    -> (forall a. Num a => ExpandedPortName a -> a)
    -> (forall a. Num a => ExpandedPortName a -> a)
    -> Foldable ExpandedPortName
    forall a. Eq a => a -> ExpandedPortName a -> Bool
    forall a. Num a => ExpandedPortName a -> a
    forall a. Ord a => ExpandedPortName a -> a
    forall m. Monoid m => ExpandedPortName m -> m
    forall a. ExpandedPortName a -> Bool
    forall a. ExpandedPortName a -> Int
    forall a. ExpandedPortName a -> [a]
    forall a. (a -> a -> a) -> ExpandedPortName a -> a
    forall m a. Monoid m => (a -> m) -> ExpandedPortName a -> m
    forall b a. (b -> a -> b) -> b -> ExpandedPortName a -> b
    forall a b. (a -> b -> b) -> b -> ExpandedPortName a -> b
    forall (t :: Type -> Type).
    (forall m. Monoid m => t m -> m)
    -> (forall m a. Monoid m => (a -> m) -> t a -> m)
    -> (forall m a. Monoid m => (a -> m) -> t a -> m)
    -> (forall a b. (a -> b -> b) -> b -> t a -> b)
    -> (forall a b. (a -> b -> b) -> b -> t a -> b)
    -> (forall b a. (b -> a -> b) -> b -> t a -> b)
    -> (forall b a. (b -> a -> b) -> b -> t a -> b)
    -> (forall a. (a -> a -> a) -> t a -> a)
    -> (forall a. (a -> a -> a) -> t a -> a)
    -> (forall a. t a -> [a])
    -> (forall a. t a -> Bool)
    -> (forall a. t a -> Int)
    -> (forall a. Eq a => a -> t a -> Bool)
    -> (forall a. Ord a => t a -> a)
    -> (forall a. Ord a => t a -> a)
    -> (forall a. Num a => t a -> a)
    -> (forall a. Num a => t a -> a)
    -> Foldable t
    $cfold :: forall m. Monoid m => ExpandedPortName m -> m
    fold :: forall m. Monoid m => ExpandedPortName m -> m
    $cfoldMap :: forall m a. Monoid m => (a -> m) -> ExpandedPortName a -> m
    foldMap :: forall m a. Monoid m => (a -> m) -> ExpandedPortName a -> m
    $cfoldMap' :: forall m a. Monoid m => (a -> m) -> ExpandedPortName a -> m
    foldMap' :: forall m a. Monoid m => (a -> m) -> ExpandedPortName a -> m
    $cfoldr :: forall a b. (a -> b -> b) -> b -> ExpandedPortName a -> b
    foldr :: forall a b. (a -> b -> b) -> b -> ExpandedPortName a -> b
    $cfoldr' :: forall a b. (a -> b -> b) -> b -> ExpandedPortName a -> b
    foldr' :: forall a b. (a -> b -> b) -> b -> ExpandedPortName a -> b
    $cfoldl :: forall b a. (b -> a -> b) -> b -> ExpandedPortName a -> b
    foldl :: forall b a. (b -> a -> b) -> b -> ExpandedPortName a -> b
    $cfoldl' :: forall b a. (b -> a -> b) -> b -> ExpandedPortName a -> b
    foldl' :: forall b a. (b -> a -> b) -> b -> ExpandedPortName a -> b
    $cfoldr1 :: forall a. (a -> a -> a) -> ExpandedPortName a -> a
    foldr1 :: forall a. (a -> a -> a) -> ExpandedPortName a -> a
    $cfoldl1 :: forall a. (a -> a -> a) -> ExpandedPortName a -> a
    foldl1 :: forall a. (a -> a -> a) -> ExpandedPortName a -> a
    $ctoList :: forall a. ExpandedPortName a -> [a]
    toList :: forall a. ExpandedPortName a -> [a]
    $cnull :: forall a. ExpandedPortName a -> Bool
    null :: forall a. ExpandedPortName a -> Bool
    $clength :: forall a. ExpandedPortName a -> Int
    length :: forall a. ExpandedPortName a -> Int
    $celem :: forall a. Eq a => a -> ExpandedPortName a -> Bool
    elem :: forall a. Eq a => a -> ExpandedPortName a -> Bool
    $cmaximum :: forall a. Ord a => ExpandedPortName a -> a
    maximum :: forall a. Ord a => ExpandedPortName a -> a
    $cminimum :: forall a. Ord a => ExpandedPortName a -> a
    minimum :: forall a. Ord a => ExpandedPortName a -> a
    $csum :: forall a. Num a => ExpandedPortName a -> a
    sum :: forall a. Num a => ExpandedPortName a -> a
    $cproduct :: forall a. Num a => ExpandedPortName a -> a
    product :: forall a. Num a => ExpandedPortName a -> a
    Foldable, Functor ExpandedPortName
    Foldable ExpandedPortName
    Functor ExpandedPortName
    -> Foldable ExpandedPortName
    -> (forall (f :: Type -> Type) a b.
        Applicative f =>
        (a -> f b) -> ExpandedPortName a -> f (ExpandedPortName b))
    -> (forall (f :: Type -> Type) a.
        Applicative f =>
        ExpandedPortName (f a) -> f (ExpandedPortName a))
    -> (forall (m :: Type -> Type) a b.
        Monad m =>
        (a -> m b) -> ExpandedPortName a -> m (ExpandedPortName b))
    -> (forall (m :: Type -> Type) a.
        Monad m =>
        ExpandedPortName (m a) -> m (ExpandedPortName a))
    -> Traversable ExpandedPortName
    forall (t :: Type -> Type).
    Functor t
    -> Foldable t
    -> (forall (f :: Type -> Type) a b.
        Applicative f =>
        (a -> f b) -> t a -> f (t b))
    -> (forall (f :: Type -> Type) a.
        Applicative f =>
        t (f a) -> f (t a))
    -> (forall (m :: Type -> Type) a b.
        Monad m =>
        (a -> m b) -> t a -> m (t b))
    -> (forall (m :: Type -> Type) a. Monad m => t (m a) -> m (t a))
    -> Traversable t
    forall (m :: Type -> Type) a.
    Monad m =>
    ExpandedPortName (m a) -> m (ExpandedPortName a)
    forall (f :: Type -> Type) a.
    Applicative f =>
    ExpandedPortName (f a) -> f (ExpandedPortName a)
    forall (m :: Type -> Type) a b.
    Monad m =>
    (a -> m b) -> ExpandedPortName a -> m (ExpandedPortName b)
    forall (f :: Type -> Type) a b.
    Applicative f =>
    (a -> f b) -> ExpandedPortName a -> f (ExpandedPortName b)
    $ctraverse :: forall (f :: Type -> Type) a b.
    Applicative f =>
    (a -> f b) -> ExpandedPortName a -> f (ExpandedPortName b)
    traverse :: forall (f :: Type -> Type) a b.
    Applicative f =>
    (a -> f b) -> ExpandedPortName a -> f (ExpandedPortName b)
    $csequenceA :: forall (f :: Type -> Type) a.
    Applicative f =>
    ExpandedPortName (f a) -> f (ExpandedPortName a)
    sequenceA :: forall (f :: Type -> Type) a.
    Applicative f =>
    ExpandedPortName (f a) -> f (ExpandedPortName a)
    $cmapM :: forall (m :: Type -> Type) a b.
    Monad m =>
    (a -> m b) -> ExpandedPortName a -> m (ExpandedPortName b)
    mapM :: forall (m :: Type -> Type) a b.
    Monad m =>
    (a -> m b) -> ExpandedPortName a -> m (ExpandedPortName b)
    $csequence :: forall (m :: Type -> Type) a.
    Monad m =>
    ExpandedPortName (m a) -> m (ExpandedPortName a)
    sequence :: forall (m :: Type -> Type) a.
    Monad m =>
    ExpandedPortName (m a) -> m (ExpandedPortName a)
    Traversable)

    -- | Monad that caches generated components (StateT) and remembers hidden inputs
    -- of components that are being generated (WriterT)
    newtype NetlistMonad a =
      NetlistMonad { forall a.
    NetlistMonad a -> StateT NetlistState (ReaderT NetlistEnv IO) a
    runNetlist :: Strict.StateT NetlistState (ReaderT NetlistEnv IO) a }
      deriving newtype ((forall a b. (a -> b) -> NetlistMonad a -> NetlistMonad b)
    -> (forall a b. a -> NetlistMonad b -> NetlistMonad a)
    -> Functor NetlistMonad
    forall a b. a -> NetlistMonad b -> NetlistMonad a
    forall a b. (a -> b) -> NetlistMonad a -> NetlistMonad b
    forall (f :: Type -> Type).
    (forall a b. (a -> b) -> f a -> f b)
    -> (forall a b. a -> f b -> f a) -> Functor f
    $cfmap :: forall a b. (a -> b) -> NetlistMonad a -> NetlistMonad b
    fmap :: forall a b. (a -> b) -> NetlistMonad a -> NetlistMonad b
    $c<$ :: forall a b. a -> NetlistMonad b -> NetlistMonad a
    <$ :: forall a b. a -> NetlistMonad b -> NetlistMonad a
    Functor, Applicative NetlistMonad
    Applicative NetlistMonad
    -> (forall a b.
        NetlistMonad a -> (a -> NetlistMonad b) -> NetlistMonad b)
    -> (forall a b. NetlistMonad a -> NetlistMonad b -> NetlistMonad b)
    -> (forall a. a -> NetlistMonad a)
    -> Monad NetlistMonad
    forall a. a -> NetlistMonad a
    forall a b. NetlistMonad a -> NetlistMonad b -> NetlistMonad b
    forall a b.
    NetlistMonad a -> (a -> NetlistMonad b) -> NetlistMonad b
    forall (m :: Type -> Type).
    Applicative m
    -> (forall a b. m a -> (a -> m b) -> m b)
    -> (forall a b. m a -> m b -> m b)
    -> (forall a. a -> m a)
    -> Monad m
    $c>>= :: forall a b.
    NetlistMonad a -> (a -> NetlistMonad b) -> NetlistMonad b
    >>= :: forall a b.
    NetlistMonad a -> (a -> NetlistMonad b) -> NetlistMonad b
    $c>> :: forall a b. NetlistMonad a -> NetlistMonad b -> NetlistMonad b
    >> :: forall a b. NetlistMonad a -> NetlistMonad b -> NetlistMonad b
    $creturn :: forall a. a -> NetlistMonad a
    return :: forall a. a -> NetlistMonad a
    Monad, Functor NetlistMonad
    Functor NetlistMonad
    -> (forall a. a -> NetlistMonad a)
    -> (forall a b.
        NetlistMonad (a -> b) -> NetlistMonad a -> NetlistMonad b)
    -> (forall a b c.
        (a -> b -> c)
        -> NetlistMonad a -> NetlistMonad b -> NetlistMonad c)
    -> (forall a b. NetlistMonad a -> NetlistMonad b -> NetlistMonad b)
    -> (forall a b. NetlistMonad a -> NetlistMonad b -> NetlistMonad a)
    -> Applicative NetlistMonad
    forall a. a -> NetlistMonad a
    forall a b. NetlistMonad a -> NetlistMonad b -> NetlistMonad a
    forall a b. NetlistMonad a -> NetlistMonad b -> NetlistMonad b
    forall a b.
    NetlistMonad (a -> b) -> NetlistMonad a -> NetlistMonad b
    forall a b c.
    (a -> b -> c) -> NetlistMonad a -> NetlistMonad b -> NetlistMonad c
    forall (f :: Type -> Type).
    Functor f
    -> (forall a. a -> f a)
    -> (forall a b. f (a -> b) -> f a -> f b)
    -> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
    -> (forall a b. f a -> f b -> f b)
    -> (forall a b. f a -> f b -> f a)
    -> Applicative f
    $cpure :: forall a. a -> NetlistMonad a
    pure :: forall a. a -> NetlistMonad a
    $c<*> :: forall a b.
    NetlistMonad (a -> b) -> NetlistMonad a -> NetlistMonad b
    <*> :: forall a b.
    NetlistMonad (a -> b) -> NetlistMonad a -> NetlistMonad b
    $cliftA2 :: forall a b c.
    (a -> b -> c) -> NetlistMonad a -> NetlistMonad b -> NetlistMonad c
    liftA2 :: forall a b c.
    (a -> b -> c) -> NetlistMonad a -> NetlistMonad b -> NetlistMonad c
    $c*> :: forall a b. NetlistMonad a -> NetlistMonad b -> NetlistMonad b
    *> :: forall a b. NetlistMonad a -> NetlistMonad b -> NetlistMonad b
    $c<* :: forall a b. NetlistMonad a -> NetlistMonad b -> NetlistMonad a
    <* :: forall a b. NetlistMonad a -> NetlistMonad b -> NetlistMonad a
    Applicative, MonadReader NetlistEnv,
                        Strict.MonadState NetlistState, Monad NetlistMonad
    Monad NetlistMonad
    -> (forall a. IO a -> NetlistMonad a) -> MonadIO NetlistMonad
    forall a. IO a -> NetlistMonad a
    forall (m :: Type -> Type).
    Monad m -> (forall a. IO a -> m a) -> MonadIO m
    $cliftIO :: forall a. IO a -> NetlistMonad a
    liftIO :: forall a. IO a -> NetlistMonad a
    Strict.MonadIO, Monad NetlistMonad
    Monad NetlistMonad
    -> (forall a. String -> NetlistMonad a) -> MonadFail NetlistMonad
    forall a. String -> NetlistMonad a
    forall (m :: Type -> Type).
    Monad m -> (forall a. String -> m a) -> MonadFail m
    $cfail :: forall a. String -> NetlistMonad a
    fail :: forall a. String -> NetlistMonad a
    MonadFail)

    type HWMap = Map Type (Either String FilteredHWType)

    -- | See 'is_freshCache'
    type FreshCache = HashMap Text (IntMap Word)

    type IdentifierText = Text

    -- | Whether to preserve casing in ids or converted everything to
    --  lowercase. Influenced by '-fclash-lower-case-basic-identifiers'
    data PreserveCase
      = PreserveCase
      | ToLower
      deriving (Int -> PreserveCase -> ShowS
    [PreserveCase] -> ShowS
    PreserveCase -> String
    (Int -> PreserveCase -> ShowS)
    -> (PreserveCase -> String)
    -> ([PreserveCase] -> ShowS)
    -> Show PreserveCase
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> PreserveCase -> ShowS
    showsPrec :: Int -> PreserveCase -> ShowS
    $cshow :: PreserveCase -> String
    show :: PreserveCase -> String
    $cshowList :: [PreserveCase] -> ShowS
    showList :: [PreserveCase] -> ShowS
    Show, (forall x. PreserveCase -> Rep PreserveCase x)
    -> (forall x. Rep PreserveCase x -> PreserveCase)
    -> Generic PreserveCase
    forall x. Rep PreserveCase x -> PreserveCase
    forall x. PreserveCase -> Rep PreserveCase x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. PreserveCase -> Rep PreserveCase x
    from :: forall x. PreserveCase -> Rep PreserveCase x
    $cto :: forall x. Rep PreserveCase x -> PreserveCase
    to :: forall x. Rep PreserveCase x -> PreserveCase
    Generic, PreserveCase -> ()
    (PreserveCase -> ()) -> NFData PreserveCase
    forall a. (a -> ()) -> NFData a
    $crnf :: PreserveCase -> ()
    rnf :: PreserveCase -> ()
    NFData, PreserveCase -> PreserveCase -> Bool
    (PreserveCase -> PreserveCase -> Bool)
    -> (PreserveCase -> PreserveCase -> Bool) -> Eq PreserveCase
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: PreserveCase -> PreserveCase -> Bool
    == :: PreserveCase -> PreserveCase -> Bool
    $c/= :: PreserveCase -> PreserveCase -> Bool
    /= :: PreserveCase -> PreserveCase -> Bool
    Eq, Get PreserveCase
    [PreserveCase] -> Put
    PreserveCase -> Put
    (PreserveCase -> Put)
    -> Get PreserveCase
    -> ([PreserveCase] -> Put)
    -> Binary PreserveCase
    forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
    $cput :: PreserveCase -> Put
    put :: PreserveCase -> Put
    $cget :: Get PreserveCase
    get :: Get PreserveCase
    $cputList :: [PreserveCase] -> Put
    putList :: [PreserveCase] -> Put
    Binary, Eq PreserveCase
    Eq PreserveCase
    -> (Int -> PreserveCase -> Int)
    -> (PreserveCase -> Int)
    -> Hashable PreserveCase
    Int -> PreserveCase -> Int
    PreserveCase -> Int
    forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
    $chashWithSalt :: Int -> PreserveCase -> Int
    hashWithSalt :: Int -> PreserveCase -> Int
    $chash :: PreserveCase -> Int
    hash :: PreserveCase -> Int
    Hashable)

    -- See: http://vhdl.renerta.com/mobile/source/vhd00037.htm
    --      http://www.verilog.renerta.com/source/vrg00018.htm
    data IdentifierType
      = Basic
      -- ^ A basic identifier: does not have to be escaped in order to be a valid
      -- identifier in HDL.
      | Extended
      -- ^ An extended identifier: has to be escaped, wrapped, or otherwise
      -- postprocessed before writhing it to HDL.
      deriving (Int -> IdentifierType -> ShowS
    [IdentifierType] -> ShowS
    IdentifierType -> String
    (Int -> IdentifierType -> ShowS)
    -> (IdentifierType -> String)
    -> ([IdentifierType] -> ShowS)
    -> Show IdentifierType
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> IdentifierType -> ShowS
    showsPrec :: Int -> IdentifierType -> ShowS
    $cshow :: IdentifierType -> String
    show :: IdentifierType -> String
    $cshowList :: [IdentifierType] -> ShowS
    showList :: [IdentifierType] -> ShowS
    Show, (forall x. IdentifierType -> Rep IdentifierType x)
    -> (forall x. Rep IdentifierType x -> IdentifierType)
    -> Generic IdentifierType
    forall x. Rep IdentifierType x -> IdentifierType
    forall x. IdentifierType -> Rep IdentifierType x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. IdentifierType -> Rep IdentifierType x
    from :: forall x. IdentifierType -> Rep IdentifierType x
    $cto :: forall x. Rep IdentifierType x -> IdentifierType
    to :: forall x. Rep IdentifierType x -> IdentifierType
    Generic, IdentifierType -> ()
    (IdentifierType -> ()) -> NFData IdentifierType
    forall a. (a -> ()) -> NFData a
    $crnf :: IdentifierType -> ()
    rnf :: IdentifierType -> ()
    NFData, IdentifierType -> IdentifierType -> Bool
    (IdentifierType -> IdentifierType -> Bool)
    -> (IdentifierType -> IdentifierType -> Bool) -> Eq IdentifierType
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: IdentifierType -> IdentifierType -> Bool
    == :: IdentifierType -> IdentifierType -> Bool
    $c/= :: IdentifierType -> IdentifierType -> Bool
    /= :: IdentifierType -> IdentifierType -> Bool
    Eq)

    -- | A collection of unique identifiers. Allows for fast fresh identifier
    -- generation.
    --
    -- __NB__: use the functions in Clash.Netlist.Id. Don't use the constructor directly.
    data IdentifierSet
      = IdentifierSet {
          IdentifierSet -> Bool
    is_allowEscaped :: !Bool
          -- ^ Allow escaped ids? If set to False, "make" will always behave like
          -- "makeBasic".
        , IdentifierSet -> PreserveCase
    is_lowerCaseBasicIds :: !PreserveCase
          -- ^ Force all generated basic identifiers to lowercase.
        , IdentifierSet -> HDL
    is_hdl :: !HDL
          -- ^ HDL to generate fresh identifiers for
        , IdentifierSet -> FreshCache
    is_freshCache :: !FreshCache
          -- ^ Maps an 'i_baseNameCaseFold' to a map mapping the number of
          -- extensions (in 'i_extensionsRev') to the maximum word at that
          -- basename/level. For example, if a set would contain the identifiers:
          --
          --   [foo, foo_1, foo_2, bar_5, bar_7_8]
          --
          -- the map would look like:
          --
          --   [(foo, [(0, 0), (1, 2)]), (bar, [(1, 5), (2, 8)])]
          --
          -- This mapping makes sure we can quickly generate fresh identifiers. For
          -- example, generating a new id for "foo_1" would be a matter of looking
          -- up the base name in this map, concluding that the maximum identifier
          -- with this basename and this number of extensions is "foo_2",
          -- subsequently generating "foo_3".
          --
          -- Note that an identifier with no extensions is also stored in this map
          -- for practical purposes, but the maximum ext is invalid.
        , IdentifierSet -> HashSet Identifier
    is_store :: !(HashSet Identifier)
          -- ^ Identifier store
        } deriving ((forall x. IdentifierSet -> Rep IdentifierSet x)
    -> (forall x. Rep IdentifierSet x -> IdentifierSet)
    -> Generic IdentifierSet
    forall x. Rep IdentifierSet x -> IdentifierSet
    forall x. IdentifierSet -> Rep IdentifierSet x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. IdentifierSet -> Rep IdentifierSet x
    from :: forall x. IdentifierSet -> Rep IdentifierSet x
    $cto :: forall x. Rep IdentifierSet x -> IdentifierSet
    to :: forall x. Rep IdentifierSet x -> IdentifierSet
    Generic, IdentifierSet -> ()
    (IdentifierSet -> ()) -> NFData IdentifierSet
    forall a. (a -> ()) -> NFData a
    $crnf :: IdentifierSet -> ()
    rnf :: IdentifierSet -> ()
    NFData, Int -> IdentifierSet -> ShowS
    [IdentifierSet] -> ShowS
    IdentifierSet -> String
    (Int -> IdentifierSet -> ShowS)
    -> (IdentifierSet -> String)
    -> ([IdentifierSet] -> ShowS)
    -> Show IdentifierSet
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> IdentifierSet -> ShowS
    showsPrec :: Int -> IdentifierSet -> ShowS
    $cshow :: IdentifierSet -> String
    show :: IdentifierSet -> String
    $cshowList :: [IdentifierSet] -> ShowS
    showList :: [IdentifierSet] -> ShowS
    Show)

    -- | HDL identifier. Consists of a base name and a number of extensions. An
    -- identifier with a base name of "foo" and a list of extensions [1, 2] will be
    -- rendered as "foo_1_2".
    --
    -- Note: The Eq instance of "Identifier" is case insensitive! E.g., two
    -- identifiers with base names 'fooBar' and 'FoObAR' are considered the same.
    -- However, identifiers are stored case preserving. This means Clash won't
    -- generate two identifiers with differing case, but it will try to keep
    -- capitalization.
    --
    -- The goal of this data structure is to greatly simplify how Clash deals with
    -- identifiers internally. Any Identifier should be trivially printable to any
    -- HDL.
    --
    -- __NB__: use the functions in "Clash.Netlist.Id". Don't use these constructors
    -- directly.
    data Identifier
      -- | Unparsed identifier. Used for things such as port names, which should
      -- appear in the HDL exactly as the user specified.
      = RawIdentifier
          !Text
          -- ^ An identifier exactly as given by the user
          (Maybe Identifier)
          -- ^ Parsed version of raw identifier. Will not be populated if this
          -- identifier was created with an unsafe function.
          !CallStack
          -- ^ Stores where this identifier was generated. Tracking is only enabled
          -- is 'debugIsOn', otherwise this field will be populated by an empty
          -- callstack.

      -- | Parsed and sanitized identifier. See various fields for more information
      -- on its invariants.
      | UniqueIdentifier {
          Identifier -> Text
    i_baseName :: !Text
        -- ^ Base name of identifier. 'make' makes sure this field:
        --
        --    * does not end in '_num' where 'num' is a digit.
        --    * is solely made up of printable ASCII characters
        --    * has no leading or trailing whitespace
        --
        , Identifier -> Text
    i_baseNameCaseFold :: !Text
        -- ^ Same as 'i_baseName', but can be used for equality testing that doesn't
        -- depend on capitalization.
        , Identifier -> [Word]
    i_extensionsRev :: [Word]
        -- ^ Extensions applied to base identifier. E.g., an identifier with a base
        -- name of 'foo' and an extension of [6, 5] would render as 'foo_5_6'. Note
        -- that extensions are stored in reverse order for easier manipulation.
        , Identifier -> IdentifierType
    i_idType :: !IdentifierType
        -- ^ See 'IdentifierType'.
        , Identifier -> HDL
    i_hdl :: !HDL
        -- ^ HDL this identifier is generated for.
        , Identifier -> CallStack
    i_provenance :: !CallStack
        -- ^ Stores where this identifier was generated. Tracking is only enabled
        -- is 'debugIsOn', otherwise this field will be populated by an empty
        -- callstack.
        } deriving (Int -> Identifier -> ShowS
    [Identifier] -> ShowS
    Identifier -> String
    (Int -> Identifier -> ShowS)
    -> (Identifier -> String)
    -> ([Identifier] -> ShowS)
    -> Show Identifier
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Identifier -> ShowS
    showsPrec :: Int -> Identifier -> ShowS
    $cshow :: Identifier -> String
    show :: Identifier -> String
    $cshowList :: [Identifier] -> ShowS
    showList :: [Identifier] -> ShowS
    Show, (forall x. Identifier -> Rep Identifier x)
    -> (forall x. Rep Identifier x -> Identifier) -> Generic Identifier
    forall x. Rep Identifier x -> Identifier
    forall x. Identifier -> Rep Identifier x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. Identifier -> Rep Identifier x
    from :: forall x. Identifier -> Rep Identifier x
    $cto :: forall x. Rep Identifier x -> Identifier
    to :: forall x. Rep Identifier x -> Identifier
    Generic, Identifier -> ()
    (Identifier -> ()) -> NFData Identifier
    forall a. (a -> ()) -> NFData a
    $crnf :: Identifier -> ()
    rnf :: Identifier -> ()
    NFData)

    identifierKey# :: Identifier -> ((Text, Bool), [Word])
    identifierKey# :: Identifier -> ((Text, Bool), [Word])
    identifierKey# (RawIdentifier Text
    t Maybe Identifier
    _id CallStack
    _) = ((Text
    t, Bool
    True), [])
    identifierKey# Identifier
    id_ = ((Identifier -> Text
    i_baseNameCaseFold Identifier
    id_, Bool
    False), Identifier -> [Word]
    i_extensionsRev Identifier
    id_)

    instance Hashable Identifier where
      hashWithSalt :: Int -> Identifier -> Int
    hashWithSalt Int
    salt = Int -> Int -> Int
    forall a. Hashable a => Int -> a -> Int
    hashWithSalt Int
    salt (Int -> Int) -> (Identifier -> Int) -> Identifier -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Identifier -> Int
    forall a. Hashable a => a -> Int
    hash
      hash :: Identifier -> Int
    hash = ((Text, Bool) -> [Word] -> Int) -> ((Text, Bool), [Word]) -> Int
    forall a b c. (a -> b -> c) -> (a, b) -> c
    uncurry (Text, Bool) -> [Word] -> Int
    forall {a} {a} {t :: Type -> Type}.
    (Hashable a, Hashable a, Foldable t, Num a) =>
    a -> t a -> Int
    hash# (((Text, Bool), [Word]) -> Int)
    -> (Identifier -> ((Text, Bool), [Word])) -> Identifier -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Identifier -> ((Text, Bool), [Word])
    identifierKey#
       where
        hash# :: a -> t a -> Int
    hash# a
    a t a
    extensions =
          -- 'hash' has an identity around zero, e.g. `hash (0, 2) == 2`. Because a
          -- lot of zeros can be expected, extensions are fuzzed in order to keep
          -- efficient `HashMap`s.
          let fuzz :: a -> a -> a
    fuzz a
    fuzzFactor a
    ext = a
    fuzzFactor a -> a -> a
    forall a. Num a => a -> a -> a
    * a
    fuzzFactor a -> a -> a
    forall a. Num a => a -> a -> a
    * a
    ext in
          (a, a) -> Int
    forall a. Hashable a => a -> Int
    hash (a
    a, (a -> a -> a) -> a -> t a -> a
    forall b a. (b -> a -> b) -> b -> t a -> b
    forall (t :: Type -> Type) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    List.foldl' a -> a -> a
    forall a. Num a => a -> a -> a
    fuzz a
    2 t a
    extensions)

    instance Eq Identifier where
      Identifier
    i1 == :: Identifier -> Identifier -> Bool
    == Identifier
    i2 = Identifier -> ((Text, Bool), [Word])
    identifierKey# Identifier
    i1 ((Text, Bool), [Word]) -> ((Text, Bool), [Word]) -> Bool
    forall a. Eq a => a -> a -> Bool
    == Identifier -> ((Text, Bool), [Word])
    identifierKey# Identifier
    i2
      Identifier
    i1 /= :: Identifier -> Identifier -> Bool
    /= Identifier
    i2 = Identifier -> ((Text, Bool), [Word])
    identifierKey# Identifier
    i1 ((Text, Bool), [Word]) -> ((Text, Bool), [Word]) -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Identifier -> ((Text, Bool), [Word])
    identifierKey# Identifier
    i2

    instance Ord Identifier where
      compare :: Identifier -> Identifier -> Ordering
    compare = ((Text, Bool), [Word]) -> ((Text, Bool), [Word]) -> Ordering
    forall a. Ord a => a -> a -> Ordering
    compare (((Text, Bool), [Word]) -> ((Text, Bool), [Word]) -> Ordering)
    -> (Identifier -> ((Text, Bool), [Word]))
    -> Identifier
    -> Identifier
    -> Ordering
    forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
    `on` Identifier -> ((Text, Bool), [Word])
    identifierKey#

    -- | Environment of the NetlistMonad
    data NetlistEnv
      = NetlistEnv
      { NetlistEnv -> ClashEnv
    _clashEnv :: ClashEnv
      , NetlistEnv -> Text
    _prefixName  :: Text
      -- ^ Prefix for instance/register names
      , NetlistEnv -> Text
    _suffixName :: Text
      -- ^ Postfix for instance/register names
      , NetlistEnv -> Maybe Text
    _setName :: Maybe Text
      -- ^ (Maybe) user given instance/register name
      }

    data ComponentMeta = ComponentMeta
      { ComponentMeta -> [Bool]
    cmWereVoids :: [Bool]
      , ComponentMeta -> SrcSpan
    cmLoc :: SrcSpan
      , ComponentMeta -> IdentifierSet
    cmScope :: IdentifierSet
      , ComponentMeta -> UsageMap
    cmUsage :: UsageMap
      } deriving ((forall x. ComponentMeta -> Rep ComponentMeta x)
    -> (forall x. Rep ComponentMeta x -> ComponentMeta)
    -> Generic ComponentMeta
    forall x. Rep ComponentMeta x -> ComponentMeta
    forall x. ComponentMeta -> Rep ComponentMeta x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. ComponentMeta -> Rep ComponentMeta x
    from :: forall x. ComponentMeta -> Rep ComponentMeta x
    $cto :: forall x. Rep ComponentMeta x -> ComponentMeta
    to :: forall x. Rep ComponentMeta x -> ComponentMeta
    Generic, Int -> ComponentMeta -> ShowS
    [ComponentMeta] -> ShowS
    ComponentMeta -> String
    (Int -> ComponentMeta -> ShowS)
    -> (ComponentMeta -> String)
    -> ([ComponentMeta] -> ShowS)
    -> Show ComponentMeta
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> ComponentMeta -> ShowS
    showsPrec :: Int -> ComponentMeta -> ShowS
    $cshow :: ComponentMeta -> String
    show :: ComponentMeta -> String
    $cshowList :: [ComponentMeta] -> ShowS
    showList :: [ComponentMeta] -> ShowS
    Show, ComponentMeta -> ()
    (ComponentMeta -> ()) -> NFData ComponentMeta
    forall a. (a -> ()) -> NFData a
    $crnf :: ComponentMeta -> ()
    rnf :: ComponentMeta -> ()
    NFData)

    type ComponentMap = OMap Unique (ComponentMeta, Component)

    -- | State of the NetlistMonad
    data NetlistState
      = NetlistState
      { NetlistState -> BindingMap
    _bindings       :: BindingMap
      -- ^ Global binders
      , NetlistState -> ComponentMap
    _components     :: ComponentMap
      -- ^ Cached components. Is an insertion ordered map to preserve a topologically
      -- sorted component list for the manifest file.
      , NetlistState
    -> CustomReprs
    -> TyConMap
    -> Type
    -> State HWMap (Maybe (Either String FilteredHWType))
    _typeTranslator :: CustomReprs -> TyConMap -> Type
                        -> Strict.State HWMap (Maybe (Either String FilteredHWType))
      -- ^ Hardcoded Type -> HWType translator
      , NetlistState -> (Identifier, SrcSpan)
    _curCompNm      :: !(Identifier,SrcSpan)
      , NetlistState -> IdentifierSet
    _seenIds        :: IdentifierSet
      -- ^ All names currently in scope.
      , NetlistState -> IdentifierSet
    _seenComps      :: IdentifierSet
      -- ^ Components (to be) generated during this netlist run. This is always a
      -- subset of 'seenIds'. Reason d'etre: we currently generate components in a
      -- top down manner. E.g. given:
      --
      --   - A
      --   -- B
      --   -- C
      --
      -- we would generate component 'A' first. Before trying to generate 'B' and
      -- 'C'. 'A' might introduce a number of signal declarations. The names of these
      -- signals can't clash with the name of component 'B', hence we need to pick a
      -- name for B unique w.r.t. all these signal names. If we would postpone
      -- generating a unqiue name for 'B' til _after_ generating all the signal
      -- names, the signal names would get all the "nice" names. E.g., a signal
      -- would be called "foo", thereby forcing the component 'B' to be called
      -- "foo_1". Ideally, we'd use the "nice" names for components, and the "ugly"
      -- names for signals. To achieve this, we generate all the component names
      -- up front and subsequently store them in '_seenComps'.
      , NetlistState -> Set Text
    _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.
      , NetlistState -> VarEnv Identifier
    _componentNames :: VarEnv Identifier
      -- ^ Names of components (to be) generated during this netlist run. Includes
      -- top entity names.
      , NetlistState -> VarEnv TopEntityT
    _topEntityAnns  :: VarEnv TopEntityT
      , NetlistState -> String
    _hdlDir         :: FilePath
      , NetlistState -> Int
    _curBBlvl       :: Int
      -- ^ The current scoping level assigned to black box contexts
      , NetlistState -> Bool
    _isTestBench    :: Bool
      -- ^ Whether we're compiling a testbench (suppresses some warnings)
      , NetlistState -> Bool
    _backEndITE :: Bool
      -- ^ Whether the backend supports ifThenElse expressions
      , NetlistState -> SomeBackend
    _backend :: SomeBackend
      -- ^ The current HDL backend
      , NetlistState -> HWMap
    _htyCache :: HWMap
      , NetlistState -> UsageMap
    _usages :: UsageMap
      -- ^ The current way signals are assigned in netlist. This is used to
      -- determine how signals are rendered in HDL (i.e. wire/reg in Verilog, or
      -- signal/variable in VHDL).
      }

    data ComponentPrefix
      = ComponentPrefix
      { ComponentPrefix -> Maybe Text
    componentPrefixTop :: Maybe Text
        -- ^ Prefix for top-level components
      , ComponentPrefix -> Maybe Text
    componentPrefixOther :: Maybe Text
        -- ^ Prefix for all other components
      } deriving Int -> ComponentPrefix -> ShowS
    [ComponentPrefix] -> ShowS
    ComponentPrefix -> String
    (Int -> ComponentPrefix -> ShowS)
    -> (ComponentPrefix -> String)
    -> ([ComponentPrefix] -> ShowS)
    -> Show ComponentPrefix
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> ComponentPrefix -> ShowS
    showsPrec :: Int -> ComponentPrefix -> ShowS
    $cshow :: ComponentPrefix -> String
    show :: ComponentPrefix -> String
    $cshowList :: [ComponentPrefix] -> ShowS
    showList :: [ComponentPrefix] -> ShowS
    Show

    -- | Existentially quantified backend
    data SomeBackend where
      SomeBackend :: Backend backend => backend -> SomeBackend

    type Comment = Text
    type Directive = Text

    data CommentOrDirective
      = Comment Comment
      | Directive Directive
      deriving Int -> CommentOrDirective -> ShowS
    [CommentOrDirective] -> ShowS
    CommentOrDirective -> String
    (Int -> CommentOrDirective -> ShowS)
    -> (CommentOrDirective -> String)
    -> ([CommentOrDirective] -> ShowS)
    -> Show CommentOrDirective
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> CommentOrDirective -> ShowS
    showsPrec :: Int -> CommentOrDirective -> ShowS
    $cshow :: CommentOrDirective -> String
    show :: CommentOrDirective -> String
    $cshowList :: [CommentOrDirective] -> ShowS
    showList :: [CommentOrDirective] -> ShowS
    Show

    -- | Component: base unit of a Netlist
    data Component
      = Component
      { Component -> Identifier
    componentName :: !Identifier -- ^ Name of the component
      , Component -> [(Identifier, HWType)]
    inputs        :: [(Identifier,HWType)] -- ^ Input ports
      , Component -> [(Usage, (Identifier, HWType), Maybe Expr)]
    outputs       :: [(Usage,(Identifier,HWType),Maybe Expr)] -- ^ Output ports
      , Component -> [Declaration]
    declarations  :: [Declaration] -- ^ Internal declarations
      }
      deriving (Int -> Component -> ShowS
    [Component] -> ShowS
    Component -> String
    (Int -> Component -> ShowS)
    -> (Component -> String)
    -> ([Component] -> ShowS)
    -> Show Component
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Component -> ShowS
    showsPrec :: Int -> Component -> ShowS
    $cshow :: Component -> String
    show :: Component -> String
    $cshowList :: [Component] -> ShowS
    showList :: [Component] -> ShowS
    Show, (forall x. Component -> Rep Component x)
    -> (forall x. Rep Component x -> Component) -> Generic Component
    forall x. Rep Component x -> Component
    forall x. Component -> Rep Component x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. Component -> Rep Component x
    from :: forall x. Component -> Rep Component x
    $cto :: forall x. Rep Component x -> Component
    to :: forall x. Rep Component x -> Component
    Generic, Component -> ()
    (Component -> ()) -> NFData Component
    forall a. (a -> ()) -> NFData a
    $crnf :: Component -> ()
    rnf :: Component -> ()
    NFData)

    -- | Check if an input port is really an inout port.
    --
    isBiDirectional :: (Identifier, HWType) -> Bool
    isBiDirectional :: (Identifier, HWType) -> Bool
    isBiDirectional = HWType -> Bool
    go (HWType -> Bool)
    -> ((Identifier, HWType) -> HWType) -> (Identifier, HWType) -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Identifier, HWType) -> HWType
    forall a b. (a, b) -> b
    snd
      where
        go :: HWType -> Bool
    go BiDirectional{} = Bool
    True
        go (Annotated [Attr Text]
    _ HWType
    hwty) = HWType -> Bool
    go HWType
    hwty
        go HWType
    _ = Bool
    False

    -- | Find the name and domain name of each clock argument of a component.
    --
    -- This will not consider @ClockN@ to be a clock argument, which means only the
    -- positive phase of a differential pair will be added to @sdcClock@.
    findClocks :: Component -> [(Text, Text)]
    findClocks :: Component -> [(Text, Text)]
    findClocks (Component Identifier
    _ [(Identifier, HWType)]
    is [(Usage, (Identifier, HWType), Maybe Expr)]
    _ [Declaration]
    _) =
      ((Identifier, HWType) -> Maybe (Text, Text))
    -> [(Identifier, HWType)] -> [(Text, Text)]
    forall a b. (a -> Maybe b) -> [a] -> [b]
    mapMaybe (Identifier, HWType) -> Maybe (Text, Text)
    isClock [(Identifier, HWType)]
    is
     where
      isClock :: (Identifier, HWType) -> Maybe (Text, Text)
    isClock (Identifier
    i, Clock Text
    d) = (Text, Text) -> Maybe (Text, Text)
    forall a. a -> Maybe a
    Just (Identifier -> Text
    Id.toText Identifier
    i, Text
    d)
      isClock (Identifier
    i, Annotated [Attr Text]
    _ HWType
    t) = (Identifier, HWType) -> Maybe (Text, Text)
    isClock (Identifier
    i,HWType
    t)
      isClock (Identifier, HWType)
    _ = Maybe (Text, Text)
    forall a. Maybe a
    Nothing

    -- | 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 (FilteredHWType -> FilteredHWType -> Bool
    (FilteredHWType -> FilteredHWType -> Bool)
    -> (FilteredHWType -> FilteredHWType -> Bool) -> Eq FilteredHWType
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: FilteredHWType -> FilteredHWType -> Bool
    == :: FilteredHWType -> FilteredHWType -> Bool
    $c/= :: FilteredHWType -> FilteredHWType -> Bool
    /= :: FilteredHWType -> FilteredHWType -> Bool
    Eq, Int -> FilteredHWType -> ShowS
    [FilteredHWType] -> ShowS
    FilteredHWType -> String
    (Int -> FilteredHWType -> ShowS)
    -> (FilteredHWType -> String)
    -> ([FilteredHWType] -> ShowS)
    -> Show FilteredHWType
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> FilteredHWType -> ShowS
    showsPrec :: Int -> FilteredHWType -> ShowS
    $cshow :: FilteredHWType -> String
    show :: FilteredHWType -> String
    $cshowList :: [FilteredHWType] -> ShowS
    showList :: [FilteredHWType] -> ShowS
    Show)

    type DomainName = Text

    -- | 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 length of
      -- that vector.
      | 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
      | MemBlob !Size !Size
      -- ^ MemBlob type
      | RTree !Size !HWType
      -- ^ RTree type
      | Sum !Text [Text]
      -- ^ Sum type: Name and Constructor names
      | Product !Text (Maybe [Text]) [HWType]
      -- ^ Product type: Name, field names, and field types. Field names will be
      -- populated when using records.
      | SP !Text [(Text, [HWType])]
      -- ^ Sum-of-Product type: Name and Constructor names + field types
      | Clock !DomainName
      -- ^ Clock type corresponding to domain /DomainName/
      | ClockN !DomainName
      -- ^ ClockN type corresponding to domain /DomainName/
      | Reset !DomainName
      -- ^ Reset type corresponding to domain /DomainName/
      | Enable !DomainName
      -- ^ Enable type corresponding to domain /DomainName/
      | BiDirectional !PortDirection !HWType
      -- ^ Tagging type indicating a bidirectional (inout) port
      | CustomSP !Text !DataRepr' !Size [(ConstrRepr', Text, [HWType])]
      -- ^ Same as Sum-Of-Product, but with a user specified bit representation. For
      -- more info, see: Clash.Annotations.BitRepresentations.
      | CustomSum !Text !DataRepr' !Size [(ConstrRepr', Text)]
      -- ^ Same as Sum, but with a user specified bit representation. For more info,
      -- see: Clash.Annotations.BitRepresentations.
      | CustomProduct !Text !DataRepr' !Size (Maybe [Text]) [(FieldAnn, HWType)]
      -- ^ Same as Product, but with a user specified bit representation. For more
      -- info, see: Clash.Annotations.BitRepresentations.
      | Annotated [Attr Text] !HWType
      -- ^ Annotated with HDL attributes
      | KnownDomain !DomainName !Integer !ActiveEdge !ResetKind !InitBehavior !ResetPolarity
      -- ^ Domain name, period, active edge, reset kind, initial value behavior
      | FileType
      -- ^ File type for simulation-level I/O
      deriving (HWType -> HWType -> Bool
    (HWType -> HWType -> Bool)
    -> (HWType -> HWType -> Bool) -> Eq HWType
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: HWType -> HWType -> Bool
    == :: HWType -> HWType -> Bool
    $c/= :: HWType -> HWType -> Bool
    /= :: HWType -> HWType -> Bool
    Eq, Eq HWType
    Eq HWType
    -> (HWType -> HWType -> Ordering)
    -> (HWType -> HWType -> Bool)
    -> (HWType -> HWType -> Bool)
    -> (HWType -> HWType -> Bool)
    -> (HWType -> HWType -> Bool)
    -> (HWType -> HWType -> HWType)
    -> (HWType -> HWType -> HWType)
    -> Ord HWType
    HWType -> HWType -> Bool
    HWType -> HWType -> Ordering
    HWType -> HWType -> HWType
    forall a.
    Eq a
    -> (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: HWType -> HWType -> Ordering
    compare :: HWType -> HWType -> Ordering
    $c< :: HWType -> HWType -> Bool
    < :: HWType -> HWType -> Bool
    $c<= :: HWType -> HWType -> Bool
    <= :: HWType -> HWType -> Bool
    $c> :: HWType -> HWType -> Bool
    > :: HWType -> HWType -> Bool
    $c>= :: HWType -> HWType -> Bool
    >= :: HWType -> HWType -> Bool
    $cmax :: HWType -> HWType -> HWType
    max :: HWType -> HWType -> HWType
    $cmin :: HWType -> HWType -> HWType
    min :: HWType -> HWType -> HWType
    Ord, Int -> HWType -> ShowS
    [HWType] -> ShowS
    HWType -> String
    (Int -> HWType -> ShowS)
    -> (HWType -> String) -> ([HWType] -> ShowS) -> Show HWType
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> HWType -> ShowS
    showsPrec :: Int -> HWType -> ShowS
    $cshow :: HWType -> String
    show :: HWType -> String
    $cshowList :: [HWType] -> ShowS
    showList :: [HWType] -> ShowS
    Show, (forall x. HWType -> Rep HWType x)
    -> (forall x. Rep HWType x -> HWType) -> Generic HWType
    forall x. Rep HWType x -> HWType
    forall x. HWType -> Rep HWType x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. HWType -> Rep HWType x
    from :: forall x. HWType -> Rep HWType x
    $cto :: forall x. Rep HWType x -> HWType
    to :: forall x. Rep HWType x -> HWType
    Generic, HWType -> ()
    (HWType -> ()) -> NFData HWType
    forall a. (a -> ()) -> NFData a
    $crnf :: HWType -> ()
    rnf :: HWType -> ()
    NFData, Eq HWType
    Eq HWType
    -> (Int -> HWType -> Int) -> (HWType -> Int) -> Hashable HWType
    Int -> HWType -> Int
    HWType -> Int
    forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
    $chashWithSalt :: Int -> HWType -> Int
    hashWithSalt :: Int -> HWType -> Int
    $chash :: HWType -> Int
    hash :: HWType -> Int
    Hashable)

    -- | Smart constructor for 'Annotated'. Wraps the given type in an 'Annotated'
    -- if the attribute list is non-empty. If it is empty, it will return the given
    -- 'HWType' unchanged.
    annotated :: [Attr Text] -> HWType -> HWType
    annotated :: [Attr Text] -> HWType -> HWType
    annotated [] HWType
    t = HWType
    t
    annotated [Attr Text]
    attrs HWType
    t = [Attr Text] -> HWType -> HWType
    Annotated [Attr Text]
    attrs HWType
    t

    hwTypeDomain :: HWType -> Maybe DomainName
    hwTypeDomain :: HWType -> Maybe Text
    hwTypeDomain = \case
      Clock Text
    dom -> Text -> Maybe Text
    forall a. a -> Maybe a
    Just Text
    dom
      ClockN Text
    dom -> Text -> Maybe Text
    forall a. a -> Maybe a
    Just Text
    dom
      Reset Text
    dom -> Text -> Maybe Text
    forall a. a -> Maybe a
    Just Text
    dom
      Enable Text
    dom -> Text -> Maybe Text
    forall a. a -> Maybe a
    Just Text
    dom
      KnownDomain Text
    dom Integer
    _ ActiveEdge
    _ ResetKind
    _ InitBehavior
    _ ResetPolarity
    _ -> Text -> Maybe Text
    forall a. a -> Maybe a
    Just Text
    dom
      HWType
    _ -> Maybe Text
    forall a. Maybe a
    Nothing

    -- | 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 Text]
    hwTypeAttrs :: HWType -> [Attr Text]
    hwTypeAttrs (Annotated [Attr Text]
    attrs HWType
    _type) = [Attr Text]
    attrs
    hwTypeAttrs HWType
    _                       = []

    -- | Specifies how to wire up a component instance
    data PortMap
      = IndexedPortMap [(PortDirection, HWType, Expr)]
      -- ^ Port map based on port positions (port direction, type, assignment)
      --
      -- HDL Example:
      --
      --     bytemaster bytemaster_ds
      --       ( clk_1
      --       , rst_1
      --       , bitCtrl_0 );
      --
      | NamedPortMap [(Expr, PortDirection, HWType, Expr)]
      -- ^ Port map based on port names (port name, port direction, type, assignment)
      --
      -- HDL Example:
      --
      --     bytemaster bytemaster_ds
      --       ( .clk (clk_1)
      --       , .rst (rst_1)
      --       , .bitCtrl (bitCtrl_0) );
      --
      deriving (Int -> PortMap -> ShowS
    [PortMap] -> ShowS
    PortMap -> String
    (Int -> PortMap -> ShowS)
    -> (PortMap -> String) -> ([PortMap] -> ShowS) -> Show PortMap
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> PortMap -> ShowS
    showsPrec :: Int -> PortMap -> ShowS
    $cshow :: PortMap -> String
    show :: PortMap -> String
    $cshowList :: [PortMap] -> ShowS
    showList :: [PortMap] -> ShowS
    Show)

    -- | Internals of a Component
    data Declaration
      -- | Signal assignment
      = Assignment
          !Identifier -- ^ Signal to assign
          !Usage      -- ^ How the signal is assigned
          !Expr       -- ^ Assigned expression

      -- | Conditional signal assignment:
      | CondAssignment
          !Identifier            -- ^ Signal to assign
          !HWType                -- ^ Type of the result/alternatives
          !Expr                  -- ^ Scrutinized expression
          !HWType                -- ^ Type of the scrutinee
          [(Maybe Literal,Expr)] -- ^ List of: (Maybe expression scrutinized expression is compared with,RHS of alternative)

      -- | Instantiation of another component:
      | InstDecl
          EntityOrComponent                  -- ^ Whether it's an entity or a component
          (Maybe Text)                       -- ^ Library instance is defined in
          [Attr Text]                        -- ^ Attributes to add to the generated code
          !Identifier                        -- ^ The component's (or entity's) name
          !Identifier                        -- ^ Instance label
          [(Expr,HWType,Expr)]               -- ^ List of parameters for this component (param name, param type, param value)
          PortMap

      -- | Instantiation of blackbox declaration
      | BlackBoxD
          !Text                    -- ^ Primitive name
          [BlackBoxTemplate]       -- ^ VHDL only: add @library@ declarations
          [BlackBoxTemplate]       -- ^ VHDL only: add @use@ declarations
          [((Text,Text),BlackBox)] -- ^ Intel Quartus only: create a @.qsys@ file from given template
          !BlackBox                -- ^ Template tokens
          BlackBoxContext          -- ^ Context in which tokens should be rendered

      -- | @component@ declaration (VHDL).
      --
      -- See [this tutorial](https://www.ics.uci.edu/~jmoorkan/vhdlref/compdec.html);
      -- refer to §4.5 of IEEE 1076-1993
      | CompDecl
          !Text
          [(Text, PortDirection, HWType)]

      -- | Signal declaration
      | NetDecl'
          (Maybe Comment)                -- ^ Note; will be inserted as a comment in target hdl
          !Identifier                    -- ^ Name of signal
          HWType                         -- ^ Type of signal
          (Maybe Expr)                   -- ^ Initial value
          -- ^ Signal declaration

      -- | HDL tick corresponding to a Core tick
      | TickDecl CommentOrDirective

      -- | Sequential statement
      | Seq [Seq]

      -- | Compilation conditional on some preprocessor symbol, note that
      -- declarations here are ignored for VHDL. See here for a discussion
      -- https://github.com/clash-lang/clash-compiler/pull/1798#discussion_r648571862
      | ConditionalDecl
          !Text -- ^ condition text, for example @FORMAL@
          [Declaration]
      deriving Int -> Declaration -> ShowS
    [Declaration] -> ShowS
    Declaration -> String
    (Int -> Declaration -> ShowS)
    -> (Declaration -> String)
    -> ([Declaration] -> ShowS)
    -> Show Declaration
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Declaration -> ShowS
    showsPrec :: Int -> Declaration -> ShowS
    $cshow :: Declaration -> String
    show :: Declaration -> String
    $cshowList :: [Declaration] -> ShowS
    showList :: [Declaration] -> ShowS
    Show

    -- | Sequential statements
    data Seq
      -- | Clocked sequential statements
      = AlwaysClocked
          ActiveEdge -- ^ Edge of the clock the statement should be executed
          Expr       -- ^ Clock expression
          [Seq]      -- ^ Statements to be executed on the active clock edge
      -- | Statements running at simulator start
      | Initial
          [Seq] -- ^ Statements to run at simulator start
      -- | Statements to run always
      | AlwaysComb
          [Seq] -- ^ Statements to run always
      -- | Declaration in sequential form
      | SeqDecl
          Declaration -- ^ The declaration
      -- | Branching statement
      | Branch
          !Expr                    -- ^ Scrutinized expresson
          !HWType                  -- ^ Type of the scrutinized expression
          [(Maybe Literal,[Seq])]  -- ^ List of: (Maybe match, RHS of Alternative)
      deriving Int -> Seq -> ShowS
    [Seq] -> ShowS
    Seq -> String
    (Int -> Seq -> ShowS)
    -> (Seq -> String) -> ([Seq] -> ShowS) -> Show Seq
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Seq -> ShowS
    showsPrec :: Int -> Seq -> ShowS
    $cshow :: Seq -> String
    show :: Seq -> String
    $cshowList :: [Seq] -> ShowS
    showList :: [Seq] -> ShowS
    Show

    -- | Procedural assignment in HDL can be blocking or non-blocking. This
    -- determines when the assignment takes place in simulation. The name refers to
    -- whether evaluation of the remaining statements in a process is blocked
    -- until the assignment is performed or not.
    --
    -- See Also:
    --
    -- IEEE 1364-2001, sections 9.2.1 and 9.2.2
    -- IEEE 1076-1993, sections 8.4 and 8.5
    --
    data Blocking
      = NonBlocking
      -- ^ A non-blocking assignment means the new value is not observed until the
      -- next time step in simulation. Using the signal later in the process will
      -- continue to return the old value.
      | Blocking
      -- ^ A blocking assignment means the new value is observed immediately. Using
      -- the signal later in the process will return the new value.
      deriving (Get Blocking
    [Blocking] -> Put
    Blocking -> Put
    (Blocking -> Put)
    -> Get Blocking -> ([Blocking] -> Put) -> Binary Blocking
    forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
    $cput :: Blocking -> Put
    put :: Blocking -> Put
    $cget :: Get Blocking
    get :: Get Blocking
    $cputList :: [Blocking] -> Put
    putList :: [Blocking] -> Put
    Binary, Blocking -> Blocking -> Bool
    (Blocking -> Blocking -> Bool)
    -> (Blocking -> Blocking -> Bool) -> Eq Blocking
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Blocking -> Blocking -> Bool
    == :: Blocking -> Blocking -> Bool
    $c/= :: Blocking -> Blocking -> Bool
    /= :: Blocking -> Blocking -> Bool
    Eq, (forall x. Blocking -> Rep Blocking x)
    -> (forall x. Rep Blocking x -> Blocking) -> Generic Blocking
    forall x. Rep Blocking x -> Blocking
    forall x. Blocking -> Rep Blocking x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. Blocking -> Rep Blocking x
    from :: forall x. Blocking -> Rep Blocking x
    $cto :: forall x. Rep Blocking x -> Blocking
    to :: forall x. Rep Blocking x -> Blocking
    Generic, Eq Blocking
    Eq Blocking
    -> (Int -> Blocking -> Int)
    -> (Blocking -> Int)
    -> Hashable Blocking
    Int -> Blocking -> Int
    Blocking -> Int
    forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
    $chashWithSalt :: Int -> Blocking -> Int
    hashWithSalt :: Int -> Blocking -> Int
    $chash :: Blocking -> Int
    hash :: Blocking -> Int
    Hashable, Blocking -> ()
    (Blocking -> ()) -> NFData Blocking
    forall a. (a -> ()) -> NFData a
    $crnf :: Blocking -> ()
    rnf :: Blocking -> ()
    NFData, Int -> Blocking -> ShowS
    [Blocking] -> ShowS
    Blocking -> String
    (Int -> Blocking -> ShowS)
    -> (Blocking -> String) -> ([Blocking] -> ShowS) -> Show Blocking
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Blocking -> ShowS
    showsPrec :: Int -> Blocking -> ShowS
    $cshow :: Blocking -> String
    show :: Blocking -> String
    $cshowList :: [Blocking] -> ShowS
    showList :: [Blocking] -> ShowS
    Show)

    -- NOTE [`Semigroup` instances for `Blocking` and `Usage`]
    instance Semigroup Blocking where
      Blocking
    NonBlocking <> :: Blocking -> Blocking -> Blocking
    <> Blocking
    y = Blocking
    y
      Blocking
    Blocking    <> Blocking
    _ = Blocking
    Blocking

    -- | The usage of a signal refers to how the signal is written to in netlist.
    -- This is used to determine if the signal should be a @wire@ or @reg@ in
    -- (System)Verilog, or a @signal@ or @variable@ in VHDL.
    --
    data Usage
      = Cont
      -- ^ Continuous assignment, which occurs in a concurrent context.
      | Proc Blocking
      -- ^ Procedural assignment, which occurs in a sequential context.
      deriving (Get Usage
    [Usage] -> Put
    Usage -> Put
    (Usage -> Put) -> Get Usage -> ([Usage] -> Put) -> Binary Usage
    forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
    $cput :: Usage -> Put
    put :: Usage -> Put
    $cget :: Get Usage
    get :: Get Usage
    $cputList :: [Usage] -> Put
    putList :: [Usage] -> Put
    Binary, Usage -> Usage -> Bool
    (Usage -> Usage -> Bool) -> (Usage -> Usage -> Bool) -> Eq Usage
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Usage -> Usage -> Bool
    == :: Usage -> Usage -> Bool
    $c/= :: Usage -> Usage -> Bool
    /= :: Usage -> Usage -> Bool
    Eq, (forall x. Usage -> Rep Usage x)
    -> (forall x. Rep Usage x -> Usage) -> Generic Usage
    forall x. Rep Usage x -> Usage
    forall x. Usage -> Rep Usage x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. Usage -> Rep Usage x
    from :: forall x. Usage -> Rep Usage x
    $cto :: forall x. Rep Usage x -> Usage
    to :: forall x. Rep Usage x -> Usage
    Generic, Eq Usage
    Eq Usage
    -> (Int -> Usage -> Int) -> (Usage -> Int) -> Hashable Usage
    Int -> Usage -> Int
    Usage -> Int
    forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
    $chashWithSalt :: Int -> Usage -> Int
    hashWithSalt :: Int -> Usage -> Int
    $chash :: Usage -> Int
    hash :: Usage -> Int
    Hashable, Usage -> ()
    (Usage -> ()) -> NFData Usage
    forall a. (a -> ()) -> NFData a
    $crnf :: Usage -> ()
    rnf :: Usage -> ()
    NFData, Int -> Usage -> ShowS
    [Usage] -> ShowS
    Usage -> String
    (Int -> Usage -> ShowS)
    -> (Usage -> String) -> ([Usage] -> ShowS) -> Show Usage
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Usage -> ShowS
    showsPrec :: Int -> Usage -> ShowS
    $cshow :: Usage -> String
    show :: Usage -> String
    $cshowList :: [Usage] -> ShowS
    showList :: [Usage] -> ShowS
    Show)

    -- NOTE [`Semigroup` instances for `Blocking` and `Usage`]
    instance Semigroup Usage where
      Usage
    Cont    <> :: Usage -> Usage -> Usage
    <> Usage
    y      = Usage
    y
      Proc Blocking
    x  <> Proc Blocking
    y = Blocking -> Usage
    Proc (Blocking
    x Blocking -> Blocking -> Blocking
    forall a. Semigroup a => a -> a -> a
    <> Blocking
    y)
      Proc Blocking
    x  <> Usage
    _      = Blocking -> Usage
    Proc Blocking
    x

    {-
    NOTE [`Semigroup` instances for `Blocking` and `Usage`]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Usages (and Blocking) are combined by taking the most restrictive usage, where
    most restrictive means "has the most influence over the choice of declaration".
    Clash produces three types of assignment:

      * continuous
      * prodecural non-blocking
      * prodecural blocking

    Both VHDl and (System)Verilog have a type of declaration which only admits one
    type of assignment. This is the most restrictive for that HDL. However, since
    that would involve knowing the HDL type in these Semigroup instances, the
    most restrictive here is based on ordering where the most restrictive for each
    HDL is an extreme value (max for VHDL, min for Verilog). i.e.

              |-------------------------------------|
              | Continuous | NonBlocking | Blocking |
    |---------|-------------------------------------|
    |    VHDL |         signal           | variable |
    |---------|-------------------------------------|
    | Verilog |   wire     |          reg           |
    |---------|-------------------------------------|
    -}

    instance FromJSON Usage where
      parseJSON :: Value -> Parser Usage
    parseJSON = String -> (Text -> Parser Usage) -> Value -> Parser Usage
    forall a. String -> (Text -> Parser a) -> Value -> Parser a
    Aeson.withText String
    "Usage" ((Text -> Parser Usage) -> Value -> Parser Usage)
    -> (Text -> Parser Usage) -> Value -> Parser Usage
    forall a b. (a -> b) -> a -> b
    $ \case
        Text
    "Continuous"  -> Usage -> Parser Usage
    forall a. a -> Parser a
    forall (f :: Type -> Type) a. Applicative f => a -> f a
    pure Usage
    Cont
        Text
    "NonBlocking" -> Usage -> Parser Usage
    forall a. a -> Parser a
    forall (f :: Type -> Type) a. Applicative f => a -> f a
    pure (Blocking -> Usage
    Proc Blocking
    NonBlocking)
        Text
    "Blocking"    -> Usage -> Parser Usage
    forall a. a -> Parser a
    forall (f :: Type -> Type) a. Applicative f => a -> f a
    pure (Blocking -> Usage
    Proc Blocking
    Blocking)
        Text
    str           -> String -> Parser Usage
    forall a. String -> Parser a
    forall (m :: Type -> Type) a. MonadFail m => String -> m a
    fail (String -> Parser Usage) -> String -> Parser Usage
    forall a b. (a -> b) -> a -> b
    $ [String] -> String
    forall a. Monoid a => [a] -> a
    mconcat
          [ String
    "Could not parse usage: "
          , Text -> String
    forall a. Show a => a -> String
    show Text
    str
          , String
    "\nRecognized values are 'Continuous', 'NonBlocking' and 'Blocking'"
          ]

    -- See NOTE [`Text` key for `UsageMap`]
    type UsageMap = Map Text Usage

    lookupUsage :: Identifier -> UsageMap -> Maybe Usage
    lookupUsage :: Identifier -> UsageMap -> Maybe Usage
    lookupUsage Identifier
    i = Text -> UsageMap -> Maybe Usage
    forall k a. Ord k => k -> Map k a -> Maybe a
    Map.lookup (Identifier -> Text
    Id.toText Identifier
    i)

    {-
    NOTE [`Text` key for `UsageMap`]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    We would like to use netlist identifiers as the key for the usage map, since
    conceptually it is a map from an identifier to how it is used in assignments.
    However, in practice we commonly end up with the same textual identifier
    appearing in different ways in the netlist.

    The most obvious example of this are identifiers that appear as both
    `UniqueIdentifier` and `RawIdentifier`. If we track the usage on the raw
    identifier, but the `NetDecl` uses the `UniqueIdentifier` then the wrong
    declaration may be used in the rendered HDL.

    Attempting to fix this by not generating the same textual identifier in
    different ways proved difficult, so for now the key type is `Text` instead.
    -}

    data EntityOrComponent = Entity | Comp | Empty
      deriving Int -> EntityOrComponent -> ShowS
    [EntityOrComponent] -> ShowS
    EntityOrComponent -> String
    (Int -> EntityOrComponent -> ShowS)
    -> (EntityOrComponent -> String)
    -> ([EntityOrComponent] -> ShowS)
    -> Show EntityOrComponent
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> EntityOrComponent -> ShowS
    showsPrec :: Int -> EntityOrComponent -> ShowS
    $cshow :: EntityOrComponent -> String
    show :: EntityOrComponent -> String
    $cshowList :: [EntityOrComponent] -> ShowS
    showList :: [EntityOrComponent] -> ShowS
    Show

    pattern NetDecl
      :: Maybe Comment
      -- ^ Note; will be inserted as a comment in target hdl
      -> Identifier
      -- ^ Name of signal
      -> HWType
      -- ^ Type of signal
      -> Declaration
    pattern $mNetDecl :: forall {r}.
    Declaration
    -> (Maybe Text -> Identifier -> HWType -> r) -> ((# #) -> r) -> r
    $bNetDecl :: Maybe Text -> Identifier -> HWType -> Declaration
    NetDecl note d ty <- NetDecl' note d ty _
      where
        NetDecl Maybe Text
    note Identifier
    d HWType
    ty = Maybe Text -> Identifier -> HWType -> Maybe Expr -> Declaration
    NetDecl' Maybe Text
    note Identifier
    d HWType
    ty Maybe Expr
    forall a. Maybe a
    Nothing

    data PortDirection = In | Out
      deriving (PortDirection -> PortDirection -> Bool
    (PortDirection -> PortDirection -> Bool)
    -> (PortDirection -> PortDirection -> Bool) -> Eq PortDirection
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: PortDirection -> PortDirection -> Bool
    == :: PortDirection -> PortDirection -> Bool
    $c/= :: PortDirection -> PortDirection -> Bool
    /= :: PortDirection -> PortDirection -> Bool
    Eq,Eq PortDirection
    Eq PortDirection
    -> (PortDirection -> PortDirection -> Ordering)
    -> (PortDirection -> PortDirection -> Bool)
    -> (PortDirection -> PortDirection -> Bool)
    -> (PortDirection -> PortDirection -> Bool)
    -> (PortDirection -> PortDirection -> Bool)
    -> (PortDirection -> PortDirection -> PortDirection)
    -> (PortDirection -> PortDirection -> PortDirection)
    -> Ord PortDirection
    PortDirection -> PortDirection -> Bool
    PortDirection -> PortDirection -> Ordering
    PortDirection -> PortDirection -> PortDirection
    forall a.
    Eq a
    -> (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: PortDirection -> PortDirection -> Ordering
    compare :: PortDirection -> PortDirection -> Ordering
    $c< :: PortDirection -> PortDirection -> Bool
    < :: PortDirection -> PortDirection -> Bool
    $c<= :: PortDirection -> PortDirection -> Bool
    <= :: PortDirection -> PortDirection -> Bool
    $c> :: PortDirection -> PortDirection -> Bool
    > :: PortDirection -> PortDirection -> Bool
    $c>= :: PortDirection -> PortDirection -> Bool
    >= :: PortDirection -> PortDirection -> Bool
    $cmax :: PortDirection -> PortDirection -> PortDirection
    max :: PortDirection -> PortDirection -> PortDirection
    $cmin :: PortDirection -> PortDirection -> PortDirection
    min :: PortDirection -> PortDirection -> PortDirection
    Ord,Int -> PortDirection -> ShowS
    [PortDirection] -> ShowS
    PortDirection -> String
    (Int -> PortDirection -> ShowS)
    -> (PortDirection -> String)
    -> ([PortDirection] -> ShowS)
    -> Show PortDirection
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> PortDirection -> ShowS
    showsPrec :: Int -> PortDirection -> ShowS
    $cshow :: PortDirection -> String
    show :: PortDirection -> String
    $cshowList :: [PortDirection] -> ShowS
    showList :: [PortDirection] -> ShowS
    Show,(forall x. PortDirection -> Rep PortDirection x)
    -> (forall x. Rep PortDirection x -> PortDirection)
    -> Generic PortDirection
    forall x. Rep PortDirection x -> PortDirection
    forall x. PortDirection -> Rep PortDirection x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. PortDirection -> Rep PortDirection x
    from :: forall x. PortDirection -> Rep PortDirection x
    $cto :: forall x. Rep PortDirection x -> PortDirection
    to :: forall x. Rep PortDirection x -> PortDirection
    Generic,PortDirection -> ()
    (PortDirection -> ()) -> NFData PortDirection
    forall a. (a -> ()) -> NFData a
    $crnf :: PortDirection -> ()
    rnf :: PortDirection -> ()
    NFData,Eq PortDirection
    Eq PortDirection
    -> (Int -> PortDirection -> Int)
    -> (PortDirection -> Int)
    -> Hashable PortDirection
    Int -> PortDirection -> Int
    PortDirection -> Int
    forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
    $chashWithSalt :: Int -> PortDirection -> Int
    hashWithSalt :: Int -> PortDirection -> Int
    $chash :: PortDirection -> Int
    hash :: PortDirection -> Int
    Hashable)

    instance NFData Declaration where
      rnf :: Declaration -> ()
    rnf Declaration
    a = Declaration
    a Declaration -> () -> ()
    forall a b. a -> b -> b
    `seq` ()

    -- | Expression Modifier
    data Modifier
      = Indexed (HWType, Int, Int)
      -- ^ Index the expression: (Type of expression, DataCon tag, Field Tag). Note
      -- that the type of the expression is the type we are slicing from, not the type
      -- returned by the index 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 Int -> Modifier -> ShowS
    [Modifier] -> ShowS
    Modifier -> String
    (Int -> Modifier -> ShowS)
    -> (Modifier -> String) -> ([Modifier] -> ShowS) -> Show Modifier
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Modifier -> ShowS
    showsPrec :: Int -> Modifier -> ShowS
    $cshow :: Modifier -> String
    show :: Modifier -> String
    $cshowList :: [Modifier] -> ShowS
    showList :: [Modifier] -> ShowS
    Show

    -- | Expression used in RHS of a declaration
    data Expr
      = 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\#

      -- | Instantiation of a BlackBox expression
      | BlackBoxE
          !Text                    -- ^ Primitive name
          [BlackBoxTemplate]       -- ^ VHDL only: add @library@ declarations
          [BlackBoxTemplate]       -- ^ VHDL only: add @use@ declarations:
          [((Text,Text),BlackBox)] -- ^ Intel/Quartus only: create a @.qsys@ file from given template.
          !BlackBox                -- ^ Template tokens
          !BlackBoxContext         -- ^ Context in which tokens should be rendered
          !Bool                    -- ^ Wrap in parentheses?

      -- | Convert some type to a BitVector.
      | ToBv
          (Maybe Identifier) -- ^ Type prefix
          HWType             -- ^ Type to convert _from_
          Expr               -- ^ Expression to convert to BitVector

      -- | Convert BitVector to some type.
      | FromBv
          (Maybe Identifier) -- ^ Type prefix
          HWType             -- ^ Type to convert _to_
          Expr               -- ^ BitVector to convert

      | IfThenElse Expr Expr Expr
      -- | Do nothing
      | Noop
      deriving Int -> Expr -> ShowS
    [Expr] -> ShowS
    Expr -> String
    (Int -> Expr -> ShowS)
    -> (Expr -> String) -> ([Expr] -> ShowS) -> Show Expr
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Expr -> ShowS
    showsPrec :: Int -> Expr -> ShowS
    $cshow :: Expr -> String
    show :: Expr -> String
    $cshowList :: [Expr] -> ShowS
    showList :: [Expr] -> ShowS
    Show

    instance NFData Expr where
      rnf :: Expr -> ()
    rnf Expr
    x = Expr
    x Expr -> () -> ()
    forall a b. a -> b -> b
    `seq` ()

    isConstExpr :: Expr -> Bool
    isConstExpr :: Expr -> Bool
    isConstExpr = \case
      Literal{} -> Bool
    True
      DataCon HWType
    _ Modifier
    _ [Expr]
    es -> (Expr -> Bool) -> [Expr] -> Bool
    forall (t :: Type -> Type) a.
    Foldable t =>
    (a -> Bool) -> t a -> Bool
    all Expr -> Bool
    isConstExpr [Expr]
    es
      Identifier{} -> Bool
    False
      DataTag{} -> Bool
    False
      BlackBoxE Text
    nm [BlackBoxTemplate]
    _ [BlackBoxTemplate]
    _ [((Text, Text), BlackBox)]
    _ BlackBox
    _ BlackBoxContext
    ctx Bool
    _
        -- When using SimIO, `reg` creates (in Haskell) the mutable reference to
        -- some value. The blackbox for this however is simply `~ARG[0]`, so if
        -- the argument given is constant, the rendered HDL will also be constant.
        | Text
    nm Text -> Text -> Bool
    forall a. Eq a => a -> a -> Bool
    == Text
    "Clash.Explicit.SimIO.reg" ->
            ((Expr, HWType, Bool) -> Bool) -> [(Expr, HWType, Bool)] -> Bool
    forall (t :: Type -> Type) a.
    Foldable t =>
    (a -> Bool) -> t a -> Bool
    all (\(Expr
    e, HWType
    _, Bool
    _) -> Expr -> Bool
    isConstExpr Expr
    e) (BlackBoxContext -> [(Expr, HWType, Bool)]
    bbInputs BlackBoxContext
    ctx)
        | Bool
    otherwise -> Bool
    False
      ToBv Maybe Identifier
    _ HWType
    _ Expr
    e -> Expr -> Bool
    isConstExpr Expr
    e
      FromBv Maybe Identifier
    _ HWType
    _ Expr
    e -> Expr -> Bool
    isConstExpr Expr
    e
      IfThenElse{} -> Bool
    False
      Expr
    Noop -> Bool
    False

    -- | Literals used in an expression
    data 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 (Literal -> Literal -> Bool
    (Literal -> Literal -> Bool)
    -> (Literal -> Literal -> Bool) -> Eq Literal
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Literal -> Literal -> Bool
    == :: Literal -> Literal -> Bool
    $c/= :: Literal -> Literal -> Bool
    /= :: Literal -> Literal -> Bool
    Eq,Int -> Literal -> ShowS
    [Literal] -> ShowS
    Literal -> String
    (Int -> Literal -> ShowS)
    -> (Literal -> String) -> ([Literal] -> ShowS) -> Show Literal
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Literal -> ShowS
    showsPrec :: Int -> Literal -> ShowS
    $cshow :: Literal -> String
    show :: Literal -> String
    $cshowList :: [Literal] -> ShowS
    showList :: [Literal] -> ShowS
    Show)

    -- | Bit literal
    data Bit
      = H -- ^ High
      | L -- ^ Low
      | U -- ^ Undefined
      | Z -- ^ High-impedance
      deriving (Bit -> Bit -> Bool
    (Bit -> Bit -> Bool) -> (Bit -> Bit -> Bool) -> Eq Bit
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Bit -> Bit -> Bool
    == :: Bit -> Bit -> Bool
    $c/= :: Bit -> Bit -> Bool
    /= :: Bit -> Bit -> Bool
    Eq,Int -> Bit -> ShowS
    [Bit] -> ShowS
    Bit -> String
    (Int -> Bit -> ShowS)
    -> (Bit -> String) -> ([Bit] -> ShowS) -> Show Bit
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Bit -> ShowS
    showsPrec :: Int -> Bit -> ShowS
    $cshow :: Bit -> String
    show :: Bit -> String
    $cshowList :: [Bit] -> ShowS
    showList :: [Bit] -> ShowS
    Show,Typeable,(forall (m :: Type -> Type). Quote m => Bit -> m Exp)
    -> (forall (m :: Type -> Type). Quote m => Bit -> Code m Bit)
    -> Lift Bit
    forall t.
    (forall (m :: Type -> Type). Quote m => t -> m Exp)
    -> (forall (m :: Type -> Type). Quote m => t -> Code m t) -> Lift t
    forall (m :: Type -> Type). Quote m => Bit -> m Exp
    forall (m :: Type -> Type). Quote m => Bit -> Code m Bit
    $clift :: forall (m :: Type -> Type). Quote m => Bit -> m Exp
    lift :: forall (m :: Type -> Type). Quote m => Bit -> m Exp
    $cliftTyped :: forall (m :: Type -> Type). Quote m => Bit -> Code m Bit
    liftTyped :: forall (m :: Type -> Type). Quote m => Bit -> Code m Bit
    Lift)

    toBit :: Integer -- ^ mask
          -> Integer -- ^ value
          -> Bit
    toBit :: Integer -> Integer -> Bit
    toBit Integer
    m Integer
    i = if Integer -> Int -> Bool
    forall a. Bits a => a -> Int -> Bool
    testBit Integer
    m Int
    0
                then Bit
    U
                else if Integer -> Int -> Bool
    forall a. Bits a => a -> Int -> Bool
    testBit Integer
    i Int
    0 then Bit
    H else Bit
    L

    -- | Context used to fill in the holes of a BlackBox template
    data BlackBoxContext
      = Context
      { BlackBoxContext -> Text
    bbName :: Text
      -- ^ Blackbox function name (for error reporting)
      , BlackBoxContext -> [(Expr, HWType)]
    bbResults :: [(Expr,HWType)]
      -- ^ Result names and types. Will typically be a list with a single item.
      -- Multiple result targets will be used for "multi result primitives". See
      -- 'Clash.Normalize.Transformations.setupMultiResultPrim'.
      , BlackBoxContext -> [(Expr, HWType, Bool)]
    bbInputs :: [(Expr,HWType,Bool)]
      -- ^ Argument names, types, and whether it is a literal
      , BlackBoxContext
    -> IntMap
         [(Either BlackBox (Identifier, [Declaration]), Usage,
           [BlackBoxTemplate], [BlackBoxTemplate], [((Text, Text), BlackBox)],
           BlackBoxContext)]
    bbFunctions :: IntMap [(Either BlackBox (Identifier,[Declaration])
                              ,Usage
                              ,[BlackBoxTemplate]
                              ,[BlackBoxTemplate]
                              ,[((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
      --   )
      , BlackBoxContext -> [Text]
    bbQsysIncName :: [IdentifierText]
      , BlackBoxContext -> Int
    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.
      , BlackBoxContext -> Identifier
    bbCompName :: Identifier
      -- ^ The component the BlackBox is instantiated in
      , BlackBoxContext -> Maybe Text
    bbCtxName :: Maybe IdentifierText
      -- ^ The "context name", name set by `Clash.Magic.setName`, defaults to the
      -- name of the closest binder
      }
      deriving Int -> BlackBoxContext -> ShowS
    [BlackBoxContext] -> ShowS
    BlackBoxContext -> String
    (Int -> BlackBoxContext -> ShowS)
    -> (BlackBoxContext -> String)
    -> ([BlackBoxContext] -> ShowS)
    -> Show BlackBoxContext
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> BlackBoxContext -> ShowS
    showsPrec :: Int -> BlackBoxContext -> ShowS
    $cshow :: BlackBoxContext -> String
    show :: BlackBoxContext -> String
    $cshowList :: [BlackBoxContext] -> ShowS
    showList :: [BlackBoxContext] -> ShowS
    Show

    type BBName = String
    type BBHash = Int

    data BlackBox
      = BBTemplate BlackBoxTemplate
      | BBFunction BBName BBHash TemplateFunction
      deriving ((forall x. BlackBox -> Rep BlackBox x)
    -> (forall x. Rep BlackBox x -> BlackBox) -> Generic BlackBox
    forall x. Rep BlackBox x -> BlackBox
    forall x. BlackBox -> Rep BlackBox x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. BlackBox -> Rep BlackBox x
    from :: forall x. BlackBox -> Rep BlackBox x
    $cto :: forall x. Rep BlackBox x -> BlackBox
    to :: forall x. Rep BlackBox x -> BlackBox
    Generic, BlackBox -> ()
    (BlackBox -> ()) -> NFData BlackBox
    forall a. (a -> ()) -> NFData a
    $crnf :: BlackBox -> ()
    rnf :: BlackBox -> ()
    NFData, Get BlackBox
    [BlackBox] -> Put
    BlackBox -> Put
    (BlackBox -> Put)
    -> Get BlackBox -> ([BlackBox] -> Put) -> Binary BlackBox
    forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
    $cput :: BlackBox -> Put
    put :: BlackBox -> Put
    $cget :: Get BlackBox
    get :: Get BlackBox
    $cputList :: [BlackBox] -> Put
    putList :: [BlackBox] -> Put
    Binary)

    data TemplateFunction where
      TemplateFunction
        :: [Int]
        -- ^ Used arguments
        -> (BlackBoxContext -> Bool)
        -- ^ Validation function. Should return 'False' if function can't render
        -- given a certain context.
        -> (forall s . Backend s => BlackBoxContext -> Lazy.State s Doc)
        -- ^ Render function
        -> TemplateFunction

    instance Show BlackBox where
      showsPrec :: Int -> BlackBox -> ShowS
    showsPrec Int
    d (BBTemplate BlackBoxTemplate
    t) =
        Bool -> ShowS -> ShowS
    showParen (Int
    d Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > Int
    10) (ShowS -> ShowS) -> ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ (String
    "BBTemplate " ++) ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> BlackBoxTemplate -> ShowS
    forall a. Show a => Int -> a -> ShowS
    showsPrec Int
    11 BlackBoxTemplate
    t
      showsPrec Int
    _ (BBFunction String
    nm Int
    hsh TemplateFunction
    _) =
        (String
    "<TemplateFunction(nm=" ++) ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ShowS
    forall a. Show a => a -> ShowS
    shows String
    nm ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (String
    ", hash=" ++) ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> ShowS
    forall a. Show a => a -> ShowS
    shows Int
    hsh ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
        (String
    ")>" ++)

    instance NFData TemplateFunction where
      rnf :: TemplateFunction -> ()
    rnf (TemplateFunction [Int]
    is BlackBoxContext -> Bool
    f forall s. Backend s => BlackBoxContext -> State s Doc
    _) = [Int] -> ()
    forall a. NFData a => a -> ()
    rnf [Int]
    is () -> () -> ()
    forall a b. a -> b -> b
    `seq` BlackBoxContext -> Bool
    f (BlackBoxContext -> Bool) -> () -> ()
    forall a b. a -> b -> b
    `seq` ()

    -- | __NB__: serialisation doesn't preserve the embedded function
    instance Binary TemplateFunction where
      put :: TemplateFunction -> Put
    put (TemplateFunction [Int]
    is BlackBoxContext -> Bool
    _ forall s. Backend s => BlackBoxContext -> State s Doc
    _ ) = [Int] -> Put
    forall t. Binary t => t -> Put
    put [Int]
    is
      get :: Get TemplateFunction
    get = (\[Int]
    is -> [Int]
    -> (BlackBoxContext -> Bool)
    -> (forall s. Backend s => BlackBoxContext -> State s Doc)
    -> TemplateFunction
    TemplateFunction [Int]
    is BlackBoxContext -> Bool
    forall {b} {a}. b -> a
    err BlackBoxContext -> State s Doc
    forall s. Backend s => BlackBoxContext -> State s Doc
    forall {b} {a}. b -> a
    err) ([Int] -> TemplateFunction) -> Get [Int] -> Get TemplateFunction
    forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
    <$> Get [Int]
    forall t. Binary t => Get t
    get
        where err :: b -> a
    err = a -> b -> a
    forall a b. a -> b -> a
    const (a -> b -> a) -> a -> b -> a
    forall a b. (a -> b) -> a -> b
    $ String -> a
    forall a. HasCallStack => String -> a
    error String
    "TemplateFunction functions can't be preserved by serialisation"

    -- | Netlist-level identifier
    data NetlistId
      = NetlistId Identifier Type
      -- ^ Identifier generated in the NetlistMonad, always derived from another
      -- 'NetlistId'
      | CoreId Id
      -- ^ An original Core identifier
      | MultiId [Id]
      -- ^ A split identifier (into several sub-identifiers), needed to assign
      -- expressions of types that have to be split apart (e.g. tuples of Files)
      deriving (NetlistId -> NetlistId -> Bool
    (NetlistId -> NetlistId -> Bool)
    -> (NetlistId -> NetlistId -> Bool) -> Eq NetlistId
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: NetlistId -> NetlistId -> Bool
    == :: NetlistId -> NetlistId -> Bool
    $c/= :: NetlistId -> NetlistId -> Bool
    /= :: NetlistId -> NetlistId -> Bool
    Eq, Int -> NetlistId -> ShowS
    [NetlistId] -> ShowS
    NetlistId -> String
    (Int -> NetlistId -> ShowS)
    -> (NetlistId -> String)
    -> ([NetlistId] -> ShowS)
    -> Show NetlistId
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> NetlistId -> ShowS
    showsPrec :: Int -> NetlistId -> ShowS
    $cshow :: NetlistId -> String
    show :: NetlistId -> String
    $cshowList :: [NetlistId] -> ShowS
    showList :: [NetlistId] -> ShowS
    Show)

    -- | Eliminator for 'NetlistId', fails on 'MultiId'
    netlistId1
      :: HasCallStack
      => (Identifier -> r)
      -- ^ Eliminator for Identifiers generated in the NetlistMonad
      -> (Id -> r)
      -- ^ Eliminator for original Core Identifiers
      -> NetlistId
      -> r
    netlistId1 :: forall r.
    HasCallStack =>
    (Identifier -> r) -> (Id -> r) -> NetlistId -> r
    netlistId1 Identifier -> r
    f Id -> r
    g = \case
      NetlistId Identifier
    i Type
    _ -> Identifier -> r
    f Identifier
    i
      CoreId Id
    i -> Id -> r
    g Id
    i
      NetlistId
    m -> String -> r
    forall a. HasCallStack => String -> a
    error (String
    "netlistId1 MultiId: " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ NetlistId -> String
    forall a. Show a => a -> String
    show NetlistId
    m)

    -- | Return the type(s) of a 'NetListId', returns multiple types when given a
    -- 'MultiId'
    netlistTypes
      :: NetlistId
      -> [Type]
    netlistTypes :: NetlistId -> [Type]
    netlistTypes = \case
      NetlistId Identifier
    _ Type
    t -> [Type
    t]
      CoreId Id
    i -> [Id -> Type
    forall a. HasType a => a -> Type
    coreTypeOf Id
    i]
      MultiId [Id]
    is -> (Id -> Type) -> [Id] -> [Type]
    forall a b. (a -> b) -> [a] -> [b]
    map Id -> Type
    forall a. HasType a => a -> Type
    coreTypeOf [Id]
    is

    -- | Return the type of a 'NetlistId', fails on 'MultiId'
    netlistTypes1
      :: HasCallStack
      => NetlistId
      -> Type
    netlistTypes1 :: HasCallStack => NetlistId -> Type
    netlistTypes1 = \case
      NetlistId Identifier
    _ Type
    t -> Type
    t
      CoreId Id
    i -> Id -> Type
    forall a. HasType a => a -> Type
    coreTypeOf Id
    i
      NetlistId
    m -> String -> Type
    forall a. HasCallStack => String -> a
    error (String
    "netlistTypes1 MultiId: " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ NetlistId -> String
    forall a. Show a => a -> String
    show NetlistId
    m)

    -- | Type of declaration, concurrent or sequential
    data DeclarationType
      = Concurrent
      | Sequential

    emptyBBContext :: Text -> BlackBoxContext
    emptyBBContext :: Text -> BlackBoxContext
    emptyBBContext Text
    name
      = Context
      { bbName :: Text
    bbName        = Text
    name
      , bbResults :: [(Expr, HWType)]
    bbResults     = []
      , bbInputs :: [(Expr, HWType, Bool)]
    bbInputs      = []
      , bbFunctions :: IntMap
      [(Either BlackBox (Identifier, [Declaration]), Usage,
        [BlackBoxTemplate], [BlackBoxTemplate], [((Text, Text), BlackBox)],
        BlackBoxContext)]
    bbFunctions   = IntMap
      [(Either BlackBox (Identifier, [Declaration]), Usage,
        [BlackBoxTemplate], [BlackBoxTemplate], [((Text, Text), BlackBox)],
        BlackBoxContext)]
    forall a. IntMap a
    empty
      , bbQsysIncName :: [Text]
    bbQsysIncName = []
      , bbLevel :: Int
    bbLevel       = (-Int
    1)
      , bbCompName :: Identifier
    bbCompName    = Text
    -> Text
    -> [Word]
    -> IdentifierType
    -> HDL
    -> CallStack
    -> Identifier
    UniqueIdentifier
                          Text
    "__NOCOMPNAME__" Text
    "__NOCOMPNAME__" []
                          IdentifierType
    Basic HDL
    VHDL CallStack
    emptyCallStack
      , bbCtxName :: Maybe Text
    bbCtxName     = Maybe Text
    forall a. Maybe a
    Nothing
      }

    Lens.makeLenses ''NetlistEnv
    Lens.makeLenses ''NetlistState

    intWidth :: Lens.Getter NetlistEnv Int
    intWidth :: Getter NetlistEnv Int
    intWidth = (ClashEnv -> f ClashEnv) -> NetlistEnv -> f NetlistEnv
    Lens' NetlistEnv ClashEnv
    clashEnv ((ClashEnv -> f ClashEnv) -> NetlistEnv -> f NetlistEnv)
    -> ((Int -> f Int) -> ClashEnv -> f ClashEnv)
    -> (Int -> f Int)
    -> NetlistEnv
    -> f NetlistEnv
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (ClashEnv -> Int) -> (Int -> f Int) -> ClashEnv -> f ClashEnv
    forall (p :: Type -> Type -> Type) (f :: Type -> Type) s a.
    (Profunctor p, Contravariant f) =>
    (s -> a) -> Optic' p f s a
    Lens.to (ClashOpts -> Int
    opt_intWidth (ClashOpts -> Int) -> (ClashEnv -> ClashOpts) -> ClashEnv -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ClashEnv -> ClashOpts
    envOpts)

    customReprs :: Lens.Getter NetlistEnv CustomReprs
    customReprs :: Getter NetlistEnv CustomReprs
    customReprs = (ClashEnv -> f ClashEnv) -> NetlistEnv -> f NetlistEnv
    Lens' NetlistEnv ClashEnv
    clashEnv ((ClashEnv -> f ClashEnv) -> NetlistEnv -> f NetlistEnv)
    -> ((CustomReprs -> f CustomReprs) -> ClashEnv -> f ClashEnv)
    -> (CustomReprs -> f CustomReprs)
    -> NetlistEnv
    -> f NetlistEnv
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (ClashEnv -> CustomReprs)
    -> (CustomReprs -> f CustomReprs) -> ClashEnv -> f ClashEnv
    forall (p :: Type -> Type -> Type) (f :: Type -> Type) s a.
    (Profunctor p, Contravariant f) =>
    (s -> a) -> Optic' p f s a
    Lens.to ClashEnv -> CustomReprs
    envCustomReprs

    tcCache :: Lens.Getter NetlistEnv TyConMap
    tcCache :: Getter NetlistEnv TyConMap
    tcCache = (ClashEnv -> f ClashEnv) -> NetlistEnv -> f NetlistEnv
    Lens' NetlistEnv ClashEnv
    clashEnv ((ClashEnv -> f ClashEnv) -> NetlistEnv -> f NetlistEnv)
    -> ((TyConMap -> f TyConMap) -> ClashEnv -> f ClashEnv)
    -> (TyConMap -> f TyConMap)
    -> NetlistEnv
    -> f NetlistEnv
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (ClashEnv -> TyConMap)
    -> (TyConMap -> f TyConMap) -> ClashEnv -> f ClashEnv
    forall (p :: Type -> Type -> Type) (f :: Type -> Type) s a.
    (Profunctor p, Contravariant f) =>
    (s -> a) -> Optic' p f s a
    Lens.to ClashEnv -> TyConMap
    envTyConMap

    primitives :: Lens.Getter NetlistEnv CompiledPrimMap
    primitives :: Getter NetlistEnv CompiledPrimMap
    primitives = (ClashEnv -> f ClashEnv) -> NetlistEnv -> f NetlistEnv
    Lens' NetlistEnv ClashEnv
    clashEnv ((ClashEnv -> f ClashEnv) -> NetlistEnv -> f NetlistEnv)
    -> ((CompiledPrimMap -> f CompiledPrimMap)
        -> ClashEnv -> f ClashEnv)
    -> (CompiledPrimMap -> f CompiledPrimMap)
    -> NetlistEnv
    -> f NetlistEnv
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (ClashEnv -> CompiledPrimMap)
    -> (CompiledPrimMap -> f CompiledPrimMap) -> ClashEnv -> f ClashEnv
    forall (p :: Type -> Type -> Type) (f :: Type -> Type) s a.
    (Profunctor p, Contravariant f) =>
    (s -> a) -> Optic' p f s a
    Lens.to ClashEnv -> CompiledPrimMap
    envPrimitives

    clashOpts :: Lens.Getter NetlistEnv ClashOpts
    clashOpts :: Getter NetlistEnv ClashOpts
    clashOpts = (ClashEnv -> f ClashEnv) -> NetlistEnv -> f NetlistEnv
    Lens' NetlistEnv ClashEnv
    clashEnv ((ClashEnv -> f ClashEnv) -> NetlistEnv -> f NetlistEnv)
    -> ((ClashOpts -> f ClashOpts) -> ClashEnv -> f ClashEnv)
    -> (ClashOpts -> f ClashOpts)
    -> NetlistEnv
    -> f NetlistEnv
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (ClashEnv -> ClashOpts)
    -> (ClashOpts -> f ClashOpts) -> ClashEnv -> f ClashEnv
    forall (p :: Type -> Type -> Type) (f :: Type -> Type) s a.
    (Profunctor p, Contravariant f) =>
    (s -> a) -> Optic' p f s a
    Lens.to ClashEnv -> ClashOpts
    envOpts

    -- | Structures that hold an 'IdentifierSet'
    class HasIdentifierSet s where
      identifierSet :: Lens' s IdentifierSet

    instance HasIdentifierSet IdentifierSet where
      identifierSet :: Lens' IdentifierSet IdentifierSet
    identifierSet = (IdentifierSet -> f IdentifierSet)
    -> IdentifierSet -> f IdentifierSet
    forall a b. (a -> b) -> a -> b
    ($)

    instance HasUsageMap NetlistState where
      usageMap :: Lens' NetlistState UsageMap
    usageMap = (UsageMap -> f UsageMap) -> NetlistState -> f NetlistState
    Lens' NetlistState UsageMap
    usages

    instance HasIdentifierSet s => HasIdentifierSet (s, a) where
      identifierSet :: Lens' (s, a) IdentifierSet
    identifierSet = (s -> f s) -> (s, a) -> f (s, a)
    forall s t a b. Field1 s t a b => Lens s t a b
    Lens (s, a) (s, a) s s
    Lens._1 ((s -> f s) -> (s, a) -> f (s, a))
    -> ((IdentifierSet -> f IdentifierSet) -> s -> f s)
    -> (IdentifierSet -> f IdentifierSet)
    -> (s, a)
    -> f (s, a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (IdentifierSet -> f IdentifierSet) -> s -> f s
    forall s. HasIdentifierSet s => Lens' s IdentifierSet
    Lens' s IdentifierSet
    identifierSet

    -- | An "IdentifierSetMonad" supports unique name generation for Clash Netlist
    class Monad m => IdentifierSetMonad m where
      identifierSetM :: (IdentifierSet -> IdentifierSet) -> m IdentifierSet

    instance IdentifierSetMonad NetlistMonad where
      identifierSetM :: (IdentifierSet -> IdentifierSet) -> NetlistMonad IdentifierSet
    identifierSetM IdentifierSet -> IdentifierSet
    f = do
        IdentifierSet
    is0 <- Getting IdentifierSet NetlistState IdentifierSet
    -> NetlistMonad IdentifierSet
    forall s (m :: Type -> Type) a.
    MonadState s m =>
    Getting a s a -> m a
    Lens.use Getting IdentifierSet NetlistState IdentifierSet
    Lens' NetlistState IdentifierSet
    seenIds
        let is1 :: IdentifierSet
    is1 = IdentifierSet -> IdentifierSet
    f IdentifierSet
    is0
        (IdentifierSet -> Identity IdentifierSet)
    -> NetlistState -> Identity NetlistState
    Lens' NetlistState IdentifierSet
    seenIds ((IdentifierSet -> Identity IdentifierSet)
     -> NetlistState -> Identity NetlistState)
    -> IdentifierSet -> NetlistMonad ()
    forall s (m :: Type -> Type) a b.
    MonadState s m =>
    ASetter s s a b -> b -> m ()
    .= IdentifierSet
    is1
        IdentifierSet -> NetlistMonad IdentifierSet
    forall a. a -> NetlistMonad a
    forall (f :: Type -> Type) a. Applicative f => a -> f a
    pure IdentifierSet
    is1
      {-# INLINE identifierSetM #-}

    instance HasIdentifierSet s => IdentifierSetMonad (Strict.State s) where
      identifierSetM :: (IdentifierSet -> IdentifierSet) -> State s IdentifierSet
    identifierSetM IdentifierSet -> IdentifierSet
    f = do
        IdentifierSet
    is0 <- Getting IdentifierSet s IdentifierSet -> State s IdentifierSet
    forall s (m :: Type -> Type) a.
    MonadState s m =>
    Getting a s a -> m a
    Lens.use Getting IdentifierSet s IdentifierSet
    forall s. HasIdentifierSet s => Lens' s IdentifierSet
    Lens' s IdentifierSet
    identifierSet
        (IdentifierSet -> Identity IdentifierSet) -> s -> Identity s
    forall s. HasIdentifierSet s => Lens' s IdentifierSet
    Lens' s IdentifierSet
    identifierSet ((IdentifierSet -> Identity IdentifierSet) -> s -> Identity s)
    -> IdentifierSet -> StateT s Identity ()
    forall s (m :: Type -> Type) a b.
    MonadState s m =>
    ASetter s s a b -> b -> m ()
    .= IdentifierSet -> IdentifierSet
    f IdentifierSet
    is0
        Getting IdentifierSet s IdentifierSet -> State s IdentifierSet
    forall s (m :: Type -> Type) a.
    MonadState s m =>
    Getting a s a -> m a
    Lens.use Getting IdentifierSet s IdentifierSet
    forall s. HasIdentifierSet s => Lens' s IdentifierSet
    Lens' s IdentifierSet
    identifierSet
      {-# INLINE identifierSetM #-}

    instance HasIdentifierSet s => IdentifierSetMonad (Lazy.State s) where
      identifierSetM :: (IdentifierSet -> IdentifierSet) -> State s IdentifierSet
    identifierSetM IdentifierSet -> IdentifierSet
    f = do
        IdentifierSet
    is0 <- Getting IdentifierSet s IdentifierSet -> State s IdentifierSet
    forall s (m :: Type -> Type) a.
    MonadState s m =>
    Getting a s a -> m a
    Lens.use Getting IdentifierSet s IdentifierSet
    forall s. HasIdentifierSet s => Lens' s IdentifierSet
    Lens' s IdentifierSet
    identifierSet
        (IdentifierSet -> Identity IdentifierSet) -> s -> Identity s
    forall s. HasIdentifierSet s => Lens' s IdentifierSet
    Lens' s IdentifierSet
    identifierSet ((IdentifierSet -> Identity IdentifierSet) -> s -> Identity s)
    -> IdentifierSet -> StateT s Identity ()
    forall s (m :: Type -> Type) a b.
    MonadState s m =>
    ASetter s s a b -> b -> m ()
    .= IdentifierSet -> IdentifierSet
    f IdentifierSet
    is0
        Getting IdentifierSet s IdentifierSet -> State s IdentifierSet
    forall s (m :: Type -> Type) a.
    MonadState s m =>
    Getting a s a -> m a
    Lens.use Getting IdentifierSet s IdentifierSet
    forall s. HasIdentifierSet s => Lens' s IdentifierSet
    Lens' s IdentifierSet
    identifierSet
      {-# INLINE identifierSetM #-}

    instance IdentifierSetMonad m => IdentifierSetMonad (Ap m) where
      identifierSetM :: (IdentifierSet -> IdentifierSet) -> Ap m IdentifierSet
    identifierSetM = m IdentifierSet -> Ap m IdentifierSet
    forall {k} (f :: k -> Type) (a :: k). f a -> Ap f a
    Ap (m IdentifierSet -> Ap m IdentifierSet)
    -> ((IdentifierSet -> IdentifierSet) -> m IdentifierSet)
    -> (IdentifierSet -> IdentifierSet)
    -> Ap m IdentifierSet
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (IdentifierSet -> IdentifierSet) -> m IdentifierSet
    forall (m :: Type -> Type).
    IdentifierSetMonad m =>
    (IdentifierSet -> IdentifierSet) -> m IdentifierSet
    identifierSetM