clash-lib-1.8.0: src/Clash/Backend.hs
{-|
Copyright : (C) 2015-2016, University of Twente,
2017 , Myrtle Software Ltd, Google Inc.,
2021-2022, QBayLogic B.V.
2022 , Google Inc.
License : BSD2 (see the file LICENSE)
Maintainer : QBayLogic B.V. <devops@qbaylogic.com>
-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
module Clash.Backend where
import Data.HashMap.Strict (HashMap, empty)
import Data.HashSet (HashSet)
import Control.Lens (Lens')
import Data.Monoid (Ap)
import Data.Text (Text)
import qualified Data.Text.Lazy as LT
import Control.Monad.State (State)
import Data.Text.Prettyprint.Doc.Extra (Doc)
#if MIN_VERSION_ghc(9,0,0)
import GHC.Types.SrcLoc (SrcSpan)
#else
import SrcLoc (SrcSpan)
#endif
import Clash.Driver.Types (ClashOpts)
import {-# SOURCE #-} Clash.Netlist.Types
(Component, Declaration, Expr, HWType, Identifier, IdentifierSet, HasIdentifierSet, UsageMap)
import Clash.Netlist.BlackBox.Types
import Clash.Signal.Internal (VDomainConfiguration)
import Clash.Annotations.Primitive (HDL)
#ifdef CABAL
import qualified Paths_clash_lib
import qualified Data.Version
#else
import qualified System.FilePath
#endif
primsRoot :: IO FilePath
#ifdef CABAL
primsRoot = Paths_clash_lib.getDataFileName "prims"
#else
primsRoot = return ("clash-lib" System.FilePath.</> "prims")
#endif
clashVer :: String
#ifdef CABAL
clashVer = Data.Version.showVersion Paths_clash_lib.version
#else
clashVer = "development"
#endif
type ModName = Text
-- | Is a type used for internal or external use
data Usage
= Internal
-- ^ Internal use
| External Text
-- ^ External use, field indicates the library name
-- | Is '-fclash-aggresive-x-optimization-blackbox' set?
newtype AggressiveXOptBB = AggressiveXOptBB Bool
-- | Is '-fclash-render-enums' set?
newtype RenderEnums = RenderEnums Bool
-- | Kind of a HDL type. Used to determine whether types need conversions in
-- order to cross top entity boundaries.
data HWKind
= PrimitiveType
-- ^ A type defined in an HDL spec. Usually types such as: bool, bit, ..
| SynonymType
-- ^ A user defined type that's simply a synonym for another type, very much
-- like a type synonym in Haskell. As long as two synonym types refer to the
-- same type, they can be used interchangeably. E.g., a subtype in VHDL.
| UserType
-- ^ User defined type that's not interchangeable with any others, even if
-- the underlying structures are the same. Similar to an ADT in Haskell.
type DomainMap = HashMap Text VDomainConfiguration
emptyDomainMap :: DomainMap
emptyDomainMap = empty
class HasUsageMap s where
usageMap :: Lens' s UsageMap
class (HasUsageMap state, HasIdentifierSet state) => Backend state where
-- | Initial state for state monad
initBackend :: ClashOpts -> state
-- | What HDL is the backend generating
hdlKind :: state -> HDL
-- | Location for the primitive definitions
primDirs :: state -> IO [FilePath]
-- | Name of backend, used for directory to put output files in. Should be
-- constant function / ignore argument.
name :: state -> String
-- | File extension for target langauge
extension :: state -> String
-- | Get the set of types out of state
extractTypes :: state -> HashSet HWType
-- | Generate HDL for a Netlist component
genHDL :: ClashOpts -> ModName -> SrcSpan -> IdentifierSet -> UsageMap -> Component -> Ap (State state) ((String, Doc),[(String,Doc)])
-- | Generate a HDL package containing type definitions for the given HWTypes
mkTyPackage :: ModName -> [HWType] -> Ap (State state) [(String, Doc)]
-- | Convert a Netlist HWType to a target HDL type
hdlType :: Usage -> HWType -> Ap (State state) Doc
-- | Query what kind of type a given HDL type is
hdlHWTypeKind :: HWType -> State state HWKind
-- | Convert a Netlist HWType to an HDL error value for that type
hdlTypeErrValue :: HWType -> Ap (State state) Doc
-- | Convert a Netlist HWType to the root of a target HDL type
hdlTypeMark :: HWType -> Ap (State state) Doc
-- | Create a record selector
hdlRecSel :: HWType -> Int -> Ap (State state) Doc
-- | Create a signal declaration from an identifier (Text) and Netlist HWType
hdlSig :: LT.Text -> HWType -> Ap (State state) Doc
-- | Create a generative block statement marker
genStmt :: Bool -> State state Doc
-- | Turn a Netlist Declaration to a HDL concurrent block
inst :: Declaration -> Ap (State state) (Maybe Doc)
-- | Turn a Netlist expression into a HDL expression
expr :: Bool -- ^ Enclose in parentheses?
-> Expr -- ^ Expr to convert
-> Ap (State state) Doc
-- | Bit-width of Int,Word,Integer
iwWidth :: State state Int
-- | Convert to a bit-vector
toBV :: HWType -> LT.Text -> Ap (State state) Doc
-- | Convert from a bit-vector
fromBV :: HWType -> LT.Text -> Ap (State state) Doc
-- | Synthesis tool we're generating HDL for
hdlSyn :: State state HdlSyn
-- | setModName
setModName :: ModName -> state -> state
-- | Set the name of the current top entity
setTopName :: Identifier -> state -> state
-- | Get the name of the current top entity
getTopName :: State state Identifier
-- | setSrcSpan
setSrcSpan :: SrcSpan -> State state ()
-- | getSrcSpan
getSrcSpan :: State state SrcSpan
-- | Block of declarations
blockDecl :: Identifier -> [Declaration] -> Ap (State state) Doc
addIncludes :: [(String, Doc)] -> State state ()
addLibraries :: [LT.Text] -> State state ()
addImports :: [LT.Text] -> State state ()
addAndSetData :: FilePath -> State state String
getDataFiles :: State state [(String,FilePath)]
addMemoryDataFile :: (String,String) -> State state ()
getMemoryDataFiles :: State state [(String,String)]
ifThenElseExpr :: state -> Bool
-- | Whether -fclash-aggressive-x-optimization-blackboxes was set
aggressiveXOptBB :: State state AggressiveXOptBB
-- | Whether -fclash-no-render-enums was set
renderEnums :: State state RenderEnums
-- | All the domain configurations of design
domainConfigurations :: State state DomainMap
-- | Set the domain configurations
setDomainConfigurations :: DomainMap -> state -> state