{-# LANGUAGE TemplateHaskellQuotes #-} {-# LANGUAGE OverloadedStrings #-} module Clash.Primitives.Annotations.SynthesisAttributes where import Prelude import Control.Monad.State (State) import Data.Either (lefts, rights) import Data.List.Infinite((...), Infinite((:<))) import Data.Proxy (Proxy(..)) import Data.Text (Text) import Data.Text.Prettyprint.Doc.Extra (Doc) import GHC.Stack (HasCallStack) import GHC.TypeLits (someNatVal) import GHC.TypeNats (KnownNat, SomeNat(..)) import Text.Show.Pretty (ppShow) import qualified Control.Lens as Lens import qualified Data.Text as T import Clash.Annotations.SynthesisAttributes import Clash.Backend (Backend) import Clash.Core.TermLiteral (termToDataError) import Clash.Core.Type (Type(LitTy), LitTy(NumTy), coreView) import Clash.Netlist.BlackBox.Types import Clash.Netlist.Types import Clash.Sized.Vector (Vec, toList) import qualified Clash.Primitives.DSL as DSL usedArguments :: [Int] usedArguments = [attrs, signal] where attrs :< signal :< _ = (0...) annotateBBF :: HasCallStack => BlackBoxFunction annotateBBF _isD _primName args _resTys = Lens.view tcCache >>= go where go tcm | ((coreView tcm -> LitTy (NumTy n)) : _) <- rights args , Just (SomeNat (Proxy :: Proxy n)) <- someNatVal n , (attrs0 : _) <- lefts args = case termToDataError attrs0 of Left msg -> error msg Right attrs1 -> pure $ Right (bbMeta, bb @n (fmap T.pack <$> attrs1)) go _ = error $ "Unexpected args:\n " <> ppShow args bbMeta :: BlackBoxMeta bbMeta = emptyBlackBoxMeta{bbKind = TDecl} bb :: KnownNat n => Vec n (Attr Text) -> BlackBox bb attrs = BBFunction (show 'annotateTF) 0 (annotateTF attrs) annotateTF :: HasCallStack => KnownNat n => Vec n (Attr Text) -> TemplateFunction annotateTF attrs = TemplateFunction usedArguments (const True) (annotateBBTF attrs) annotateBBTF :: (Backend s, KnownNat n, HasCallStack) => Vec n (Attr Text) -> BlackBoxContext -> State s Doc annotateBBTF attrs0 bbCtx | (_attrs : signal0 : _) <- map fst $ DSL.tInputs bbCtx = DSL.declarationReturn bbCtx "annotate_block" $ do let attrs1 = toList attrs0 signal1ty = Annotated attrs1 (DSL.ety signal0) signal1 = DSL.TExpr{DSL.eex=DSL.eex signal0, DSL.ety=signal1ty} resultExpr <- DSL.assign (getSignalName (bbCtxName bbCtx)) signal1 pure [resultExpr] where -- Return user-friendly name given a context name hint. getSignalName :: Maybe T.Text -> T.Text getSignalName Nothing = "result" getSignalName (Just "__VOID_TDECL_NOOP__") = getSignalName Nothing getSignalName (Just s) = s annotateBBTF _attrs bbCtx = error $ "Unexpected context:\n " <> ppShow bbCtx