mirror of https://github.com/zachjs/sv2v.git
161 lines
5.4 KiB
Haskell
161 lines
5.4 KiB
Haskell
{-# LANGUAGE PatternSynonyms #-}
|
|
{- sv2v
|
|
- Author: Zachary Snow <zach@zachjs.com>
|
|
-
|
|
- Elaboration of size casts, dimension query system functions, and ternary
|
|
- expressions where the condition references a localparam.
|
|
-
|
|
- Our conversions generate a lot of ternary expressions. This conversion
|
|
- attempts to make the code output a bit cleaner. Note that we can only do this
|
|
- simplification on localparams because parameters can be overridden at
|
|
- instantiation.
|
|
-
|
|
- This conversion applies the heuristic that it will only make substitutions
|
|
- into a ternary condition if making substitutions immediately enables the
|
|
- expression to be simplified further.
|
|
-}
|
|
|
|
module Convert.Simplify (convert) where
|
|
|
|
import Control.Monad (when)
|
|
|
|
import Convert.ExprUtils
|
|
import Convert.Scoper
|
|
import Convert.Traverse
|
|
import Language.SystemVerilog.AST
|
|
|
|
convert :: [AST] -> [AST]
|
|
convert = map $ traverseDescriptions convertDescription
|
|
|
|
convertDescription :: Description -> Description
|
|
convertDescription =
|
|
partScoper traverseDeclM traverseModuleItemM traverseGenItemM traverseStmtM
|
|
|
|
traverseDeclM :: Decl -> Scoper Expr Decl
|
|
traverseDeclM decl = do
|
|
decl' <- traverseDeclExprsM traverseExprM decl
|
|
case decl' of
|
|
Param Localparam UnknownType x e ->
|
|
insertExpr x e
|
|
Param Localparam (Implicit sg rs) x e ->
|
|
insertExpr x $ Cast (Left t) e
|
|
where t = IntegerVector TLogic sg rs
|
|
Param Localparam t x e ->
|
|
insertExpr x $ Cast (Left t) e
|
|
_ -> return ()
|
|
return decl'
|
|
|
|
pattern SimpleVector :: Signing -> Integer -> Integer -> Type
|
|
pattern SimpleVector sg l r <- IntegerVector _ sg [(RawNum l, RawNum r)]
|
|
|
|
insertExpr :: Identifier -> Expr -> Scoper Expr ()
|
|
insertExpr ident expr = do
|
|
expr' <- substituteExprM expr
|
|
case expr' of
|
|
Cast (Left (SimpleVector sg l r)) (Number n) ->
|
|
insertElem ident $ Number $ numberCast signed size n
|
|
where
|
|
signed = sg == Signed
|
|
size = fromIntegral $ abs $ l - r + 1
|
|
_ -> when (isSimpleExpr expr') $ insertElem ident expr'
|
|
|
|
isSimpleExpr :: Expr -> Bool
|
|
isSimpleExpr Number{} = True
|
|
isSimpleExpr String{} = True
|
|
isSimpleExpr (Cast Left{} e) = isSimpleExpr e
|
|
isSimpleExpr _ = False
|
|
|
|
traverseModuleItemM :: ModuleItem -> Scoper Expr ModuleItem
|
|
traverseModuleItemM (Instance m p x rs l) = do
|
|
p' <- mapM paramBindingMapper p
|
|
traverseExprsM traverseExprM $ Instance m p' x rs l
|
|
where
|
|
paramBindingMapper (param, Left t) = do
|
|
t' <- traverseNestedTypesM (traverseTypeExprsM substituteExprM) t
|
|
return (param, Left t')
|
|
paramBindingMapper (param, Right e) = return (param, Right e)
|
|
traverseModuleItemM item = traverseExprsM traverseExprM item
|
|
|
|
traverseGenItemM :: GenItem -> Scoper Expr GenItem
|
|
traverseGenItemM = traverseGenItemExprsM traverseExprM
|
|
|
|
traverseStmtM :: Stmt -> Scoper Expr Stmt
|
|
traverseStmtM stmt = traverseStmtExprsM traverseExprM stmt
|
|
|
|
traverseExprM :: Expr -> Scoper Expr Expr
|
|
traverseExprM = embedScopes convertExpr
|
|
|
|
substituteExprM :: Expr -> Scoper Expr Expr
|
|
substituteExprM = embedScopes substitute
|
|
|
|
convertExpr :: Scopes Expr -> Expr -> Expr
|
|
convertExpr info (Cast (Left t) e) =
|
|
Cast (Left t') e'
|
|
where
|
|
t' = traverseNestedTypes (traverseTypeExprs $ substitute info) t
|
|
e' = convertExpr info e
|
|
convertExpr info (Cast (Right c) e) =
|
|
Cast (Right c') e'
|
|
where
|
|
c' = convertExpr info $ substitute info c
|
|
e' = convertExpr info e
|
|
convertExpr info (DimFn f v e) =
|
|
DimFn f v e'
|
|
where e' = convertExpr info $ substitute info e
|
|
convertExpr info (Call (Ident "$clog2") (Args [e] [])) =
|
|
if val' == val
|
|
then val
|
|
else val'
|
|
where
|
|
e' = convertExpr info $ substitute info e
|
|
val = Call (Ident "$clog2") (Args [e'] [])
|
|
val' = simplifyStep val
|
|
convertExpr info (Mux cc aa bb) =
|
|
if before == after
|
|
then simplifyStep $ Mux cc' aa' bb'
|
|
else simplifyStep $ Mux after aa' bb'
|
|
where
|
|
before = substitute info cc'
|
|
after = convertExpr info before
|
|
aa' = convertExpr info aa
|
|
bb' = convertExpr info bb
|
|
cc' = convertExpr info cc
|
|
convertExpr info (BinOp op e1 e2) =
|
|
case simplifyStep $ BinOp op e1'Sub e2'Sub of
|
|
Number n -> Number n
|
|
_ -> simplifyStep $ BinOp op e1' e2'
|
|
where
|
|
e1' = convertExpr info e1
|
|
e2' = convertExpr info e2
|
|
e1'Sub = substituteIdent info e1'
|
|
e2'Sub = substituteIdent info e2'
|
|
convertExpr info (UniOp op expr) =
|
|
simplifyStep $ UniOp op $ convertExpr info expr
|
|
convertExpr info (Repeat expr exprs) =
|
|
simplifyStep $ Repeat
|
|
(convertExpr info expr)
|
|
(map (convertExpr info) exprs)
|
|
convertExpr info (Concat exprs) =
|
|
simplifyStep $ Concat (map (convertExpr info) exprs)
|
|
convertExpr info expr =
|
|
traverseSinglyNestedExprs (convertExpr info) expr
|
|
|
|
substitute :: Scopes Expr -> Expr -> Expr
|
|
substitute scopes expr =
|
|
substitute' expr
|
|
where
|
|
substitute' :: Expr -> Expr
|
|
substitute' (Ident x) =
|
|
case lookupElem scopes x of
|
|
Nothing -> Ident x
|
|
Just (_, _, e) -> e
|
|
substitute' other =
|
|
traverseSinglyNestedExprs substitute' other
|
|
|
|
substituteIdent :: Scopes Expr -> Expr -> Expr
|
|
substituteIdent scopes (Ident x) =
|
|
case lookupElem scopes x of
|
|
Just (_, _, n @ Number{}) -> n
|
|
_ -> Ident x
|
|
substituteIdent _ other = other
|