{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TemplateHaskell #-}
#if __GLASGOW_HASKELL__ >= 806
#define FIELD ^
#endif
module Clash.Netlist.Types
( Declaration (..,NetDecl)
, module Clash.Netlist.Types
)
where
import Control.DeepSeq
#if !MIN_VERSION_base(4,13,0)
import Control.Monad.Fail (MonadFail)
#endif
import Control.Monad.Reader (ReaderT, MonadReader)
import Control.Monad.State as Lazy (State)
import Control.Monad.State.Strict as Strict
(State,MonadIO, MonadState, StateT)
import Data.Bits (testBit)
import Data.Binary (Binary(..))
import Data.Hashable (Hashable)
import Data.HashMap.Strict (HashMap)
import Data.IntMap (IntMap, empty)
import qualified Data.Set as Set
import Data.Text (Text, pack)
import Data.Typeable (Typeable)
import Data.Text.Prettyprint.Doc.Extra (Doc)
import GHC.Generics (Generic)
import Language.Haskell.TH.Syntax (Lift)
import SrcLoc (SrcSpan)
import Clash.Annotations.BitRepresentation (FieldAnn)
import Clash.Annotations.TopEntity (TopEntity)
import Clash.Backend (Backend)
import Clash.Core.Type (Type)
import Clash.Core.Var (Attr', Id, varType)
import Clash.Core.TyCon (TyConMap)
import Clash.Core.VarEnv (VarEnv)
import Clash.Driver.Types (BindingMap, ClashOpts)
import Clash.Netlist.BlackBox.Types (BlackBoxTemplate)
import Clash.Netlist.Id (IdType)
import Clash.Primitives.Types (CompiledPrimMap)
import Clash.Signal.Internal
(ResetPolarity, ActiveEdge, ResetKind, InitBehavior)
import Clash.Util (HasCallStack, makeLenses)
import Clash.Annotations.BitRepresentation.Internal
(CustomReprs, DataRepr', ConstrRepr')
data TopEntityT = TopEntityT
{ topId :: Id
, topAnnotation :: Maybe TopEntity
, associatedTestbench :: Maybe Id
} deriving (Generic)
newtype NetlistMonad a =
NetlistMonad { runNetlist :: StateT NetlistState (ReaderT NetlistEnv IO) a }
deriving newtype (Functor, Monad, Applicative, MonadReader NetlistEnv,
MonadState NetlistState, MonadIO, MonadFail)
type HWMap = HashMap Type (Either String FilteredHWType)
data NetlistEnv
= NetlistEnv
{ _prefixName :: Identifier
, _suffixName :: Identifier
, _setName :: Maybe Identifier
}
data NetlistState
= NetlistState
{ _bindings :: BindingMap
, _varCount :: !Int
, _components :: VarEnv ([Bool],SrcSpan,HashMap Identifier Word,Component)
, _primitives :: CompiledPrimMap
, _typeTranslator :: CustomReprs -> TyConMap -> Type
-> Strict.State HWMap (Maybe (Either String FilteredHWType))
, _tcCache :: TyConMap
, _curCompNm :: !(Identifier,SrcSpan)
, _intWidth :: Int
, _mkIdentifierFn :: IdType -> Identifier -> Identifier
, _extendIdentifierFn :: IdType -> Identifier -> Identifier -> Identifier
, _seenIds :: HashMap Identifier Word
, _seenComps :: HashMap Identifier Word
, _seenPrimitives :: Set.Set Text
, _componentNames :: VarEnv Identifier
, _topEntityAnns :: VarEnv TopEntityT
, _hdlDir :: FilePath
, _curBBlvl :: Int
, _componentPrefix :: ComponentPrefix
, _customReprs :: CustomReprs
, _clashOpts :: ClashOpts
, _isTestBench :: Bool
, _backEndITE :: Bool
, _backend :: SomeBackend
, _htyCache :: HWMap
}
data ComponentPrefix
= ComponentPrefix
{ componentPrefixTop :: Maybe Identifier
, componentPrefixOther :: Maybe Identifier
} deriving Show
data SomeBackend where
SomeBackend :: Backend backend => backend -> SomeBackend
type Identifier = Text
type Comment = Text
data Component
= Component
{ componentName :: !Identifier
, inputs :: [(Identifier,HWType)]
, outputs :: [(WireOrReg,(Identifier,HWType),Maybe Expr)]
, declarations :: [Declaration]
}
deriving Show
instance NFData Component where
rnf c = case c of
Component nm inps outps decls -> rnf nm `seq` rnf inps `seq`
rnf outps `seq` rnf decls
type Size = Int
type IsVoid = Bool
data FilteredHWType =
FilteredHWType HWType [[(IsVoid, FilteredHWType)]]
deriving (Eq, Show)
data HWType
= Void (Maybe HWType)
| String
| Integer
| Bool
| Bit
| BitVector !Size
| Index !Integer
| Signed !Size
| Unsigned !Size
| Vector !Size !HWType
| RTree !Size !HWType
| Sum !Identifier [Identifier]
| Product !Identifier (Maybe [Text]) [HWType]
| SP !Identifier [(Identifier,[HWType])]
| Clock !Identifier
| Reset !Identifier
| BiDirectional !PortDirection !HWType
| CustomSP !Identifier !DataRepr' !Size [(ConstrRepr', Identifier, [HWType])]
| CustomSum !Identifier !DataRepr' !Size [(ConstrRepr', Identifier)]
| CustomProduct !Identifier !DataRepr' !Size (Maybe [Text]) [(FieldAnn, HWType)]
| Annotated [Attr'] !HWType
| KnownDomain !Identifier !Integer !ActiveEdge !ResetKind !InitBehavior !ResetPolarity
| FileType
deriving (Eq, Ord, Show, Generic, NFData, Hashable)
hwTypeAttrs :: HWType -> [Attr']
hwTypeAttrs (Annotated attrs _type) = attrs
hwTypeAttrs _ = []
data Declaration
= Assignment
!Identifier
!Expr
| CondAssignment
!Identifier
!HWType
!Expr
!HWType
[(Maybe Literal,Expr)]
| InstDecl
EntityOrComponent
(Maybe Comment)
!Identifier
!Identifier
[(Expr,HWType,Expr)]
[(Expr,PortDirection,HWType,Expr)]
| BlackBoxD
!Text
[BlackBoxTemplate]
[BlackBoxTemplate]
[((Text,Text),BlackBox)]
!BlackBox
BlackBoxContext
| NetDecl'
(Maybe Comment)
WireOrReg
!Identifier
(Either Identifier HWType)
(Maybe Expr)
| TickDecl Comment
| Seq [Seq]
deriving Show
data Seq
= AlwaysClocked
ActiveEdge
Expr
[Seq]
| Initial
[Seq]
| AlwaysComb
[Seq]
| SeqDecl
Declaration
| Branch
!Expr
!HWType
[(Maybe Literal,[Seq])]
deriving Show
data EntityOrComponent = Entity | Comp | Empty
deriving Show
data WireOrReg = Wire | Reg
deriving (Show,Generic)
instance NFData WireOrReg
pattern NetDecl
:: Maybe Comment
-> Identifier
-> HWType
-> Declaration
pattern NetDecl note d ty <- NetDecl' note Wire d (Right ty) _
where
NetDecl note d ty = NetDecl' note Wire d (Right ty) Nothing
data PortDirection = In | Out
deriving (Eq,Ord,Show,Generic,NFData,Hashable)
instance NFData Declaration where
rnf a = a `seq` ()
data Modifier
= Indexed (HWType,Int,Int)
| DC (HWType,Int)
| VecAppend
| RTreeAppend
| Sliced (HWType,Int,Int)
| Nested Modifier Modifier
deriving Show
data Expr
= Literal !(Maybe (HWType,Size)) !Literal
| DataCon !HWType !Modifier [Expr]
| Identifier !Identifier !(Maybe Modifier)
| DataTag !HWType !(Either Identifier Identifier)
| BlackBoxE
!Text
[BlackBoxTemplate]
[BlackBoxTemplate]
[((Text,Text),BlackBox)]
!BlackBox
!BlackBoxContext
!Bool
| ConvBV (Maybe Identifier) HWType Bool Expr
| IfThenElse Expr Expr Expr
| Noop
deriving Show
instance NFData Expr where
rnf x = x `seq` ()
data Literal
= NumLit !Integer
| BitLit !Bit
| BitVecLit !Integer !Integer
| BoolLit !Bool
| VecLit [Literal]
| StringLit !String
deriving (Eq,Show)
data Bit
= H
| L
| U
| Z
deriving (Eq,Show,Typeable,Lift)
toBit :: Integer
-> Integer
-> Bit
toBit m i = if testBit m 0
then U
else if testBit i 0 then H else L
data BlackBoxContext
= Context
{ bbName :: Text
, bbResult :: (Expr,HWType)
, bbInputs :: [(Expr,HWType,Bool)]
, bbFunctions :: IntMap [(Either BlackBox (Identifier,[Declaration])
,WireOrReg
,[BlackBoxTemplate]
,[BlackBoxTemplate]
,[((Text,Text),BlackBox)]
,BlackBoxContext)]
, bbQsysIncName :: [Identifier]
, bbLevel :: Int
, bbCompName :: Identifier
, bbCtxName :: Maybe Identifier
}
deriving Show
type BBName = String
type BBHash = Int
data BlackBox
= BBTemplate BlackBoxTemplate
| BBFunction BBName BBHash TemplateFunction
deriving (Generic, NFData, Binary)
data TemplateFunction where
TemplateFunction
:: [Int]
-> (BlackBoxContext -> Bool)
-> (forall s . Backend s => BlackBoxContext -> Lazy.State s Doc)
-> TemplateFunction
instance Show BlackBox where
show (BBTemplate t) = show t
show (BBFunction nm hsh _) =
"<TemplateFunction(nm=" ++ show nm ++ ", hash=" ++ show hsh ++ ")>"
instance NFData TemplateFunction where
rnf (TemplateFunction is f _) = rnf is `seq` f `seq` ()
instance Binary TemplateFunction where
put (TemplateFunction is _ _ ) = put is
get = (\is -> TemplateFunction is err err) <$> get
where err = const $ error "TemplateFunction functions can't be preserved by serialisation"
data NetlistId
= NetlistId Identifier Type
| CoreId Id
| MultiId [Id]
deriving Show
netlistId
:: (Identifier -> r)
-> (Id -> r)
-> NetlistId
-> [r]
netlistId f g = \case
NetlistId i _ -> [f i]
CoreId i -> [g i]
MultiId is -> map g is
netlistId1
:: HasCallStack
=> (Identifier -> r)
-> (Id -> r)
-> NetlistId
-> r
netlistId1 f g = \case
NetlistId i _ -> f i
CoreId i -> g i
m -> error ("netlistId1 MultiId: " ++ show m)
netlistTypes
:: NetlistId
-> [Type]
netlistTypes = \case
NetlistId _ t -> [t]
CoreId i -> [varType i]
MultiId is -> map varType is
netlistTypes1
:: HasCallStack
=> NetlistId
-> Type
netlistTypes1 = \case
NetlistId _ t -> t
CoreId i -> varType i
m -> error ("netlistTypes1 MultiId: " ++ show m)
data DeclarationType
= Concurrent
| Sequential
emptyBBContext :: Text -> BlackBoxContext
emptyBBContext n
= Context
{ bbName = n
, bbResult = (Identifier (pack "__EMPTY__") Nothing, Void Nothing)
, bbInputs = []
, bbFunctions = empty
, bbQsysIncName = []
, bbLevel = (-1)
, bbCompName = pack "__NOCOMPNAME__"
, bbCtxName = Nothing
}
makeLenses ''NetlistEnv
makeLenses ''NetlistState