{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ViewPatterns #-}
module Clash.Netlist.BlackBox.Util where
import Control.Exception (throw)
import Control.Lens (_1,_2,(%=),use)
import Control.Monad.State (State, StateT (..), lift)
import Data.Bool (bool)
import Data.Foldable (foldrM)
import Data.Hashable (Hashable (..))
import qualified Data.IntMap as IntMap
import Data.List (mapAccumL, nub)
#if !MIN_VERSION_base(4,11,0)
import Data.Monoid
#endif
import Data.Semigroup.Monad
import qualified Data.Text
import qualified Data.Text.Prettyprint.Doc as PP
import Data.Text.Prettyprint.Doc.Extra
import Data.Text.Lazy (Text)
import qualified Data.Text.Lazy as Text
import System.FilePath (replaceBaseName,
takeBaseName,
takeFileName,
(<.>))
import qualified Text.PrettyPrint.ANSI.Leijen as ANSI
import Text.Printf
import Text.Trifecta.Result hiding (Err)
import Clash.Backend (Backend (..), Usage (..))
import Clash.Driver.Types (ClashException (..))
import Clash.Netlist.BlackBox.Parser
import Clash.Netlist.BlackBox.Types
import Clash.Netlist.Id (IdType (..))
import Clash.Netlist.Types
(HWType (..), Identifier, BlackBoxContext (..), Expr (..), Literal (..),
NetlistMonad, Modifier (..))
import qualified Clash.Netlist.Types as N
import Clash.Netlist.Util (mkUniqueIdentifier,typeSize)
import Clash.Signal.Internal
(ClockKind (Gated), ResetKind (Synchronous))
import Clash.Util
verifyBlackBoxContext :: BlackBoxContext
-> BlackBoxTemplate
-> Bool
verifyBlackBoxContext bbCtx = all verify'
where
verify' (I _ n) = n < length (bbInputs bbCtx)
verify' (L n) = case indexMaybe (bbInputs bbCtx) n of
Just (_,_,b) -> b
_ -> False
verify' (Typ (Just n)) = n < length (bbInputs bbCtx)
verify' (TypM (Just n)) = n < length (bbInputs bbCtx)
verify' (Err (Just n)) = n < length (bbInputs bbCtx)
verify' (D (Decl n l')) = case IntMap.lookup n (bbFunctions bbCtx) of
Just _ -> all (\(x,y) -> verifyBlackBoxContext bbCtx x &&
verifyBlackBoxContext bbCtx y) l'
_ -> False
verify' _ = True
extractLiterals :: BlackBoxContext
-> [Expr]
extractLiterals = map (\case (e,_,_) -> e)
. filter (\case (_,_,b) -> b)
. bbInputs
setSym
:: BlackBoxContext
-> BlackBoxTemplate
-> NetlistMonad (BlackBoxTemplate,[N.Declaration])
setSym bbCtx l = do
(a,(_,decls)) <- runStateT (mapM setSym' l) (IntMap.empty,IntMap.empty)
return (a,concatMap snd (IntMap.elems decls))
where
setSym' :: Element
-> StateT ( IntMap.IntMap Identifier
, IntMap.IntMap (Identifier,[N.Declaration]))
NetlistMonad
Element
setSym' e = case e of
Var nm i | i < length (bbInputs bbCtx) -> case bbInputs bbCtx !! i of
(Identifier nm' Nothing,_,_) -> return (Var [C nm'] i)
(e',hwTy,_) -> do
varM <- IntMap.lookup i <$> use _2
case varM of
Nothing -> do
nm' <- lift (mkUniqueIdentifier Extended (concatT (C "#":nm)))
let decls = case typeSize hwTy of
0 -> []
_ -> [N.NetDecl Nothing nm' hwTy
,N.Assignment nm' e'
]
_2 %= (IntMap.insert i (nm',decls))
return (Var [C nm'] i)
Just (nm',_) -> return (Var [C nm'] i)
Sym _ i -> do
symM <- IntMap.lookup i <$> use _1
case symM of
Nothing -> do
t <- lift (mkUniqueIdentifier Extended (Text.pack "#n"))
_1 %= (IntMap.insert i t)
return (Sym t i)
Just t -> return (Sym t i)
GenSym t i -> do
symM <- IntMap.lookup i <$> use _1
case symM of
Nothing -> do
t' <- lift (mkUniqueIdentifier Basic (concatT t))
_1 %= (IntMap.insert i t')
return (GenSym [C t'] i)
Just _ -> error ("Symbol #" ++ show (t,i) ++ " is already defined")
D (Decl n l') -> D <$> (Decl n <$> mapM (combineM (mapM setSym') (mapM setSym')) l')
IF c t f -> IF <$> pure c <*> mapM setSym' t <*> mapM setSym' f
SigD e' m -> SigD <$> (mapM setSym' e') <*> pure m
BV t e' m -> BV <$> pure t <*> mapM setSym' e' <*> pure m
_ -> pure e
concatT :: [Element] -> Text
concatT = Text.concat
. map (\case { C t -> t
; O _ | Identifier t _ <- fst (bbResult bbCtx)
-> t
; N n | let (e,_,_) = bbInputs bbCtx !! n
, Just t <- exprToText e
-> t
; _ -> error "unexpected element in GENSYM"})
setCompName :: Identifier -> BlackBoxTemplate -> BlackBoxTemplate
setCompName nm = map setCompName'
where
setCompName' CompName = C nm
setCompName' (D (Decl n l)) = D (Decl n (map (setCompName nm *** setCompName nm) l))
setCompName' (IF c t f) = IF c (setCompName nm t) (setCompName nm f)
setCompName' (GenSym es i) = GenSym (setCompName nm es) i
setCompName' (BV t e m) = BV t (setCompName nm e) (setCompName' m)
setCompName' e = e
findAndSetDataFiles :: BlackBoxContext -> [(String,FilePath)] -> BlackBoxTemplate -> ([(String,FilePath)],BlackBoxTemplate)
findAndSetDataFiles bbCtx fs = mapAccumL findAndSet fs
where
findAndSet fs' (FilePath e) = case e of
(L n) ->
let (e',_,_) = bbInputs bbCtx !! n
in case e' of
BlackBoxE "GHC.CString.unpackCString#" _ _ _ _ bbCtx' _ -> case bbInputs bbCtx' of
[(Literal Nothing (StringLit s'),_,_)] -> renderFilePath fs s'
_ -> (fs',FilePath e)
Literal Nothing (StringLit s') -> renderFilePath fs s'
_ -> (fs',FilePath e)
_ -> (fs',FilePath e)
findAndSet fs' l = (fs',l)
renderFilePath :: [(String,FilePath)] -> String -> ([(String,FilePath)],Element)
renderFilePath fs f = ((f'',f):fs,C (Text.pack $ show f''))
where
f' = takeFileName f
f'' = selectNewName (map fst fs) f'
selectNewName as a
| elem a as = selectNewName as (replaceBaseName a (takeBaseName a ++ "_"))
| otherwise = a
renderTemplate
:: Backend backend
=> BlackBoxContext
-> BlackBoxTemplate
-> State backend (Int -> Text)
renderTemplate bbCtx l = do
l' <- mapM (renderElem bbCtx) l
return (\col -> Text.concat (map ($ col) l'))
renderBlackBox
:: Backend backend
=> [BlackBoxTemplate]
-> [BlackBoxTemplate]
-> Maybe ((Data.Text.Text,Data.Text.Text), BlackBoxTemplate)
-> BlackBoxTemplate
-> BlackBoxContext
-> State backend (Int -> Doc)
renderBlackBox libs imps Nothing bs bbCtx = do
libs' <- mapM (fmap ($ 0) . renderTemplate bbCtx) libs
imps' <- mapM (fmap ($ 0) . renderTemplate bbCtx) imps
addLibraries libs'
addImports imps'
t <- renderTemplate bbCtx bs
return (\col -> PP.nest (col-2) (PP.pretty (t (col+2))))
renderBlackBox libs imps (Just ((nm,ext),inc)) bs bbCtx = do
incForHash <- renderTemplate (bbCtx {bbQsysIncName = Just "~INCLUDENAME"}) inc
iw <- iwWidth
let incHash = hash (incForHash 0)
nm' = Text.concat
[ Text.fromStrict nm
, Text.pack (printf ("%0" ++ show (iw `div` 4) ++ "X") incHash)
]
bbNamedCtx = bbCtx {bbQsysIncName = Just nm'}
inc' <-renderTemplate bbNamedCtx inc
t <- renderTemplate bbNamedCtx bs
inc'' <- pretty (inc' 0)
addInclude (Text.unpack nm' <.> Data.Text.unpack ext, inc'')
libs' <- mapM (fmap ($ 0) . renderTemplate bbNamedCtx) libs
imps' <- mapM (fmap ($ 0) . renderTemplate bbNamedCtx) imps
addLibraries libs'
addImports imps'
return (\col -> PP.nest (col-2) (PP.pretty (t (col+2))))
setSimpleVar
:: BlackBoxContext
-> BlackBoxTemplate
-> BlackBoxTemplate
setSimpleVar bbCtx = map go
where
go e = case e of
Var _ i
| i < length (bbInputs bbCtx)
, (Identifier nm' Nothing,_,_) <- bbInputs bbCtx !! i
-> Var [C nm'] i
| otherwise
-> error $ $(curLoc) ++ "You can only pass variables to function arguments in a higher-order primitive"
D (Decl n l') -> D (Decl n (map (map go *** map go) l'))
IF c t f -> IF c (map go t) (map go f)
SigD e' m -> SigD (map go e') m
BV t e' m -> BV t (map go e') m
_ -> e
renderElem :: Backend backend
=> BlackBoxContext
-> Element
-> State backend (Int -> Text)
renderElem b (D (Decl n (l:ls))) = do
(o,oTy,_) <- idToExpr <$> combineM (lineToIdentifier b) (return . lineToType b) l
is <- mapM (fmap idToExpr . combineM (lineToIdentifier b) (return . lineToType b)) ls
let Just (templ,_,libs,imps,incM,pCtx) = IntMap.lookup n (bbFunctions b)
b' = pCtx { bbResult = (o,oTy), bbInputs = bbInputs pCtx ++ is }
templ' <- case templ of
Left t -> return t
Right (nm,ds) -> do block <- getMon $ blockDecl nm ds
return . parseFail . renderLazy $ (layoutPretty (LayoutOptions (AvailablePerLine 120 0.4)) block)
let t2 = setSimpleVar b' templ'
if verifyBlackBoxContext b' t2
then do
bb <- renderBlackBox libs imps incM t2 b'
return (renderLazy . layoutPretty (LayoutOptions (AvailablePerLine 120 0.4)) . bb)
else do
sp <- getSrcSpan
throw (ClashException sp ($(curLoc) ++ "\nCan't match context:\n" ++ show b' ++ "\nwith template:\n" ++ show templ) Nothing)
renderElem b (SigD e m) = do
e' <- Text.concat <$> mapM (fmap ($ 0) . renderElem b) e
let ty = case m of
Nothing -> snd $ bbResult b
Just n -> let (_,ty',_) = bbInputs b !! n
in ty'
t <- getMon (hdlSig e' ty)
return (const (renderOneLine t))
renderElem b (IF c t f) = do
iw <- iwWidth
syn <- hdlSyn
let c' = check iw syn c
if c' > 0 then renderTemplate b t else renderTemplate b f
where
check iw syn c' = case c' of
(Size e) -> typeSize (lineToType b [e])
(Length e) -> case lineToType b [e] of
(Vector n _) -> n
Void (Just (Vector n _)) -> n
_ -> 0
(L n) -> case bbInputs b !! n of
(l,_,_)
| Literal _ l' <- l ->
case l' of
NumLit i -> fromInteger i
BitLit bl -> case bl of
N.H -> 1
N.L -> 0
_ -> error $ $(curLoc) ++ "IF: LIT bit literal must be high or low"
BoolLit bl -> bool 0 1 bl
_ -> error $ $(curLoc) ++ "IF: LIT must be a numeric lit"
| DataCon (Signed _) _ [Literal _ (NumLit i)] <- l
-> fromInteger i
| DataCon (Unsigned _) _ [Literal _ (NumLit i)] <- l
-> fromInteger i
k -> error $ $(curLoc) ++ ("IF: LIT must be a numeric lit:" ++ show k)
(Depth e) -> case lineToType b [e] of
(RTree n _) -> n
_ -> error $ $(curLoc) ++ "IF: treedepth of non-tree type"
IW64 -> if iw == 64 then 1 else 0
(HdlSyn s) -> if s == syn then 1 else 0
(IsVar n) -> let (e,_,_) = bbInputs b !! n
in case e of
Identifier _ Nothing -> 1
_ -> 0
(IsLit n) -> let (e,_,_) = bbInputs b !! n
in case e of
DataCon {} -> 1
Literal {} -> 1
BlackBoxE {} -> 1
_ -> 0
(IsGated n) -> let (_,ty,_) = bbInputs b !! n
in case ty of
Clock _ _ Gated -> 1
_ -> 0
(IsSync n) -> let (_,ty,_) = bbInputs b !! n
in case ty of
Reset _ _ Synchronous -> 1
_ -> 0
(StrCmp [C t1] n) ->
let (e,_,_) = bbInputs b !! n
in case exprToText e of
Just t2
| t1 == t2 -> 1
| otherwise -> 0
Nothing -> error $ $(curLoc) ++ "Expected a string literal: " ++ show e
(And es) -> if all (==1) (map (check iw syn) es)
then 1
else 0
_ -> error $ $(curLoc) ++ "IF: condition must be: SIZE, LENGTH, IW64, LIT, ISLIT, or ISARG"
renderElem b e = fmap const (renderTag b e)
parseFail :: Text -> BlackBoxTemplate
parseFail t = case runParse t of
Failure errInfo ->
error (ANSI.displayS (ANSI.renderCompact (_errDoc errInfo)) "")
Success templ -> templ
idToExpr
:: (Text,HWType)
-> (Expr,HWType,Bool)
idToExpr (t,ty) = (Identifier t Nothing,ty,False)
lineToIdentifier :: Backend backend
=> BlackBoxContext
-> BlackBoxTemplate
-> State backend Text
lineToIdentifier b = foldrM (\e a -> do
e' <- renderTag b e
return (e' `Text.append` a)
) Text.empty
lineToType :: BlackBoxContext
-> BlackBoxTemplate
-> HWType
lineToType b [(Typ Nothing)] = snd $ bbResult b
lineToType b [(Typ (Just n))] = let (_,ty,_) = bbInputs b !! n
in ty
lineToType b [(TypElem t)] = case lineToType b [t] of
Vector _ elTy -> elTy
_ -> error $ $(curLoc) ++ "Element type selection of a non-vector type"
lineToType b [(IndexType (L n))] =
case bbInputs b !! n of
(Literal _ (NumLit n'),_,_) -> Index (fromInteger n')
x -> error $ $(curLoc) ++ "Index type not given a literal: " ++ show x
lineToType _ _ = error $ $(curLoc) ++ "Unexpected type manipulation"
renderTag :: Backend backend
=> BlackBoxContext
-> Element
-> State backend Text
renderTag _ (C t) = return t
renderTag b (O esc) = do
escape <- if esc then unextend else pure id
fmap (escape . renderOneLine) . getMon . expr False . fst $ bbResult b
renderTag b (I esc n) = do
let (e,_,_) = bbInputs b !! n
escape <- if esc then unextend else pure id
(escape . renderOneLine) <$> getMon (expr False e)
renderTag b t@(Arg k n)
| k == bbLevel b
, let (e,_,_) = bbInputs b !! n
= renderOneLine <$> getMon (expr False e)
| otherwise
= getMon (prettyElem t)
renderTag b (N n) = let (e,_,_) = bbInputs b !! n
in case exprToText e of
Just t -> return t
_ -> error $ $(curLoc) ++ "Expected a string literal: " ++ show e
renderTag b (L n) = let (e,_,_) = bbInputs b !! n
in renderOneLine <$> getMon (expr False (mkLit e))
where
mkLit (Literal (Just (Signed _,_)) i) = Literal Nothing i
mkLit (Literal (Just (Unsigned _,_)) i) = Literal Nothing i
mkLit (DataCon _ (DC (Void {}, _)) [Literal (Just (Signed _,_)) i]) = Literal Nothing i
mkLit (DataCon _ (DC (Void {}, _)) [Literal (Just (Unsigned _,_)) i]) = Literal Nothing i
mkLit i = i
renderTag _ (Var [C t] _) = return t
renderTag _ (Sym t _) = return t
renderTag b (BV True es e) = do
e' <- Text.concat <$> mapM (fmap ($ 0) . renderElem b) es
let ty = lineToType b [e]
renderOneLine <$> getMon (toBV ty e')
renderTag b (BV False es e) = do
e' <- Text.concat <$> (mapM (fmap ($ 0) . renderElem b) es)
let ty = lineToType b [e]
renderOneLine <$> getMon (fromBV ty e')
renderTag b (Sel e n) =
let ty = lineToType b [e]
in renderOneLine <$> getMon (hdlRecSel ty n)
renderTag b (Typ Nothing) = fmap renderOneLine . getMon . hdlType Internal . snd $ bbResult b
renderTag b (Typ (Just n)) = let (_,ty,_) = bbInputs b !! n
in renderOneLine <$> getMon (hdlType Internal ty)
renderTag b (TypM Nothing) = fmap renderOneLine . getMon . hdlTypeMark . snd $ bbResult b
renderTag b (TypM (Just n)) = let (_,ty,_) = bbInputs b !! n
in renderOneLine <$> getMon (hdlTypeMark ty)
renderTag b (Err Nothing) = fmap renderOneLine . getMon . hdlTypeErrValue . snd $ bbResult b
renderTag b (Err (Just n)) = let (_,ty,_) = bbInputs b !! n
in renderOneLine <$> getMon (hdlTypeErrValue ty)
renderTag b (Size e) = return . Text.pack . show . typeSize $ lineToType b [e]
renderTag b (Length e) = return . Text.pack . show . vecLen $ lineToType b [e]
where
vecLen (Vector n _) = n
vecLen _ = error $ $(curLoc) ++ "vecLen of a non-vector type"
renderTag b (Depth e) = return . Text.pack . show . treeDepth $ lineToType b [e]
where
treeDepth (RTree n _) = n
treeDepth _ = error $ $(curLoc) ++ "treeDepth of a non-tree type"
renderTag b e@(TypElem _) = let ty = lineToType b [e]
in renderOneLine <$> getMon (hdlType Internal ty)
renderTag _ (Gen b) = renderOneLine <$> genStmt b
renderTag _ (GenSym [C t] _) = return t
renderTag b (Vars n) =
let (e,_,_) = bbInputs b !! n
go (Identifier i _) = [i]
go (DataCon _ _ es) = concatMap go es
go (DataTag _ e') = [either id id e']
go _ = []
vars = go e
in case vars of
[] -> return Text.empty
_ -> return (Text.concat $ map (Text.cons ',') vars)
renderTag b (IndexType (L n)) =
case bbInputs b !! n of
(Literal _ (NumLit n'),_,_) ->
let hty = Index (fromInteger n')
in fmap renderOneLine (getMon (hdlType Internal hty))
x -> error $ $(curLoc) ++ "Index type not given a literal: " ++ show x
renderTag b (FilePath e) = case e of
L n -> do
let (e',_,_) = bbInputs b !! n
e2 <- getMon (prettyElem e)
case e' of
BlackBoxE "GHC.CString.unpackCString#" _ _ _ _ bbCtx' _ -> case bbInputs bbCtx' of
[(Literal Nothing (StringLit _),_,_)] -> error $ $(curLoc) ++ "argument of ~FILEPATH:" ++ show e2 ++ "does not reduce to a string"
_ -> error $ $(curLoc) ++ "argument of ~FILEPATH:" ++ show e2 ++ "does not reduce to a string"
_ -> error $ $(curLoc) ++ "argument of ~FILEPATH:" ++ show e2 ++ "does not reduce to a string"
_ -> do e' <- getMon (prettyElem e)
error $ $(curLoc) ++ "~FILEPATH expects a ~LIT[N] argument, but got: " ++ show e'
renderTag b IncludeName = case bbQsysIncName b of
Just nm -> return nm
_ -> error $ $(curLoc) ++ "~INCLUDENAME used where no 'qysInclude' was specified in the primitive definition"
renderTag b (OutputWireReg n) = case IntMap.lookup n (bbFunctions b) of
Just (_,rw,_,_,_,_) -> case rw of {N.Wire -> return "wire"; N.Reg -> return "reg"}
_ -> error $ $(curLoc) ++ "~OUTPUTWIREREG[" ++ show n ++ "] used where argument " ++ show n ++ " is not a function"
renderTag _ e = do e' <- getMon (prettyElem e)
error $ $(curLoc) ++ "Unable to evaluate: " ++ show e'
exprToText
:: Expr
-> Maybe Text
exprToText (Literal _ (StringLit l)) = Just (Text.pack l)
exprToText (BlackBoxE "Clash.Promoted.Symbol.SSymbol" _ _ _ _ ctx _) =
let (e',_,_) = head (bbInputs ctx)
in exprToText e'
exprToText (BlackBoxE "GHC.CString.unpackCString#" _ _ _ _ ctx _) =
let (e',_,_) = head (bbInputs ctx)
in exprToText e'
exprToText _ = Nothing
prettyBlackBox :: Monad m
=> BlackBoxTemplate
-> Mon m Text
prettyBlackBox bbT = Text.concat <$> mapM prettyElem bbT
prettyElem :: Monad m
=> Element
-> Mon m Text
prettyElem (C t) = return t
prettyElem (D (Decl i args)) = do
args' <- mapM (\(a,b) -> (,) <$> prettyBlackBox a <*> prettyBlackBox b) args
renderOneLine <$>
(nest 2 (string "~INST" <+> int i <> line <>
string "~OUTPUT" <+> string "=>" <+> string (fst (head args')) <+> string (snd (head args')) <+> string "~" <> line <>
vcat (mapM (\(a,b) -> string "~INPUT" <+> string "=>" <+> string a <+> string b <+> string "~") (tail args')))
<> line <> string "~INST")
prettyElem (O b) = if b then return "~ERESULT" else return "~RESULT"
prettyElem (I b i) = renderOneLine <$> (if b then string "~EARG" else string "~ARG" <> brackets (int i))
prettyElem (L i) = renderOneLine <$> (string "~LIT" <> brackets (int i))
prettyElem (N i) = renderOneLine <$> (string "~NAME" <> brackets (int i))
prettyElem (Var es i) = do
es' <- prettyBlackBox es
renderOneLine <$> (string "~VAR" <> brackets (string es') <> brackets (int i))
prettyElem (Sym _ i) = renderOneLine <$> (string "~SYM" <> brackets (int i))
prettyElem (Typ Nothing) = return "~TYPO"
prettyElem (Typ (Just i)) = renderOneLine <$> (string "~TYP" <> brackets (int i))
prettyElem (TypM Nothing) = return "~TYPMO"
prettyElem (TypM (Just i)) = renderOneLine <$> (string "~TYPM" <> brackets (int i))
prettyElem (Err Nothing) = return "~ERRORO"
prettyElem (Err (Just i)) = renderOneLine <$> (string "~ERROR" <> brackets (int i))
prettyElem (TypElem e) = do
e' <- prettyElem e
renderOneLine <$> (string "~TYPEL" <> brackets (string e'))
prettyElem CompName = return "~COMPNAME"
prettyElem IncludeName = return "~INCLUDENAME"
prettyElem (IndexType e) = do
e' <- prettyElem e
renderOneLine <$> (string "~INDEXTYPE" <> brackets (string e'))
prettyElem (Size e) = do
e' <- prettyElem e
renderOneLine <$> (string "~SIZE" <> brackets (string e'))
prettyElem (Length e) = do
e' <- prettyElem e
renderOneLine <$> (string "~LENGTH" <> brackets (string e'))
prettyElem (Depth e) = do
e' <- prettyElem e
renderOneLine <$> (string "~DEPTH" <> brackets (string e'))
prettyElem (FilePath e) = do
e' <- prettyElem e
renderOneLine <$> (string "~FILE" <> brackets (string e'))
prettyElem (Gen b) = if b then return "~GENERATE" else return "~ENDGENERATE"
prettyElem (IF b esT esF) = do
b' <- prettyElem b
esT' <- prettyBlackBox esT
esF' <- prettyBlackBox esF
(renderLazy . layoutCompact) <$>
(string "~IF" <+> string b' <+> string "~THEN" <>
string esT' <>
string "~ELSE" <>
string esF' <>
string "~FI")
prettyElem (And es) =
(renderLazy . layoutCompact) <$>
(brackets (tupled $ mapM (string <=< prettyElem) es))
prettyElem IW64 = return "~IW64"
prettyElem (HdlSyn s) = case s of
Vivado -> return "~VIVADO"
_ -> return "~OTHERSYN"
prettyElem (BV b es e) = do
es' <- prettyBlackBox es
e' <- prettyBlackBox [e]
renderOneLine <$>
if b
then string "~TOBV" <> brackets (string es') <> brackets (string e')
else string "~FROMBV" <> brackets (string es') <> brackets (string e')
prettyElem (Sel e i) = do
e' <- prettyElem e
renderOneLine <$> (string "~SEL" <> brackets (string e') <> brackets (int i))
prettyElem (IsLit i) = renderOneLine <$> (string "~ISLIT" <> brackets (int i))
prettyElem (IsVar i) = renderOneLine <$> (string "~ISVAR" <> brackets (int i))
prettyElem (IsGated i) = renderOneLine <$> (string "~ISGATED" <> brackets (int i))
prettyElem (IsSync i) = renderOneLine <$> (string "~ISSYNC" <> brackets (int i))
prettyElem (StrCmp es i) = do
es' <- prettyBlackBox es
renderOneLine <$> (string "~STRCMP" <> brackets (string es') <> brackets (int i))
prettyElem (GenSym es i) = do
es' <- prettyBlackBox es
renderOneLine <$> (string "~GENSYM" <> brackets (string es') <> brackets (int i))
prettyElem (SigD es mI) = do
es' <- prettyBlackBox es
renderOneLine <$>
(maybe (string "~SIGDO" <> brackets (string es'))
(((string "~SIGD" <> brackets (string es')) <>) . int)
mI)
prettyElem (Vars i) = renderOneLine <$> (string "~VARS" <> brackets (int i))
prettyElem (OutputWireReg i) = renderOneLine <$> (string "~RESULTWIREREG" <> brackets (int i))
prettyElem (Arg n x) =
renderOneLine <$> (string "~ARGN" <> brackets (int n) <> brackets (int x))
usedArguments :: BlackBoxTemplate
-> [Int]
usedArguments = nub . concatMap go
where
go x = case x of
D (Decl i args) -> i : concatMap (\(a,b) -> usedArguments a ++ usedArguments b) args
I _ i -> [i]
L i -> [i]
N i -> [i]
Var _ i -> [i]
IndexType e -> go e
FilePath e -> go e
IF b esT esF -> go b ++ usedArguments esT ++ usedArguments esF
SigD es _ -> usedArguments es
BV _ es _ -> usedArguments es
StrCmp _ i -> [i]
GenSym es _ -> usedArguments es
_ -> []