Simplify.hs 2.43 KB
Newer Older
1 2 3
{- sv2v
 - Author: Zachary Snow <zach@zachjs.com>
 -
4 5
 - Elaboration of size casts, dimension query system functions, and ternary
 - expressions where the condition references a localparam.
6 7 8 9 10 11 12 13 14 15 16
 -
 - 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.
 -}

17
module Convert.Simplify (convert) where
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36

import Control.Monad.State
import qualified Data.Map.Strict as Map

import Convert.Traverse
import Language.SystemVerilog.AST

type Info = Map.Map Identifier Expr

convert :: [AST] -> [AST]
convert = map $ traverseDescriptions convertDescription

convertDescription :: Description -> Description
convertDescription =
    scopedConversion traverseDeclM traverseModuleItemM traverseStmtM Map.empty

traverseDeclM :: Decl -> State Info Decl
traverseDeclM decl = do
    case decl of
37
        Param Localparam _ x e -> modify $ Map.insert x e
38 39 40 41 42 43 44 45 46 47 48 49 50
        _ -> return ()
    return decl

traverseModuleItemM :: ModuleItem -> State Info ModuleItem
traverseModuleItemM item = traverseExprsM traverseExprM item

traverseStmtM :: Stmt -> State Info Stmt
traverseStmtM stmt = traverseStmtExprsM traverseExprM stmt

traverseExprM :: Expr -> State Info Expr
traverseExprM = traverseNestedExprsM $ stately convertExpr

convertExpr :: Info -> Expr -> Expr
51
convertExpr info (Cast (Right c) e) =
52 53 54 55 56 57
    case c' of
        Number _ ->
            if sized == e
                then Cast (Right c') e
                else sized
        _ -> Cast (Right c') e
58 59 60
    where
        c' = simplify $ traverseNestedExprs (substitute info) (simplify c)
        sized = sizedExpr "" c' e
61 62 63 64
convertExpr info (DimFn f v e) =
    DimFn f v e'
    where
        e' = simplify $ traverseNestedExprs (substitute info) e
65 66 67 68 69
convertExpr info (Mux cc aa bb) =
    if before == after
        then Mux cc aa bb
        else simplify $ Mux after aa bb
    where
70
        before = traverseNestedExprs (substitute info) (simplify cc)
71 72 73
        after = simplify before
convertExpr _ other = other

74 75 76 77 78 79
substitute :: Info -> Expr -> Expr
substitute info (Ident x) =
    case Map.lookup x info of
        Nothing -> Ident x
        Just e -> e
substitute _ other = other