diff --git a/src/Convert.hs b/src/Convert.hs index 6da5ae2..3b54906 100644 --- a/src/Convert.hs +++ b/src/Convert.hs @@ -11,6 +11,7 @@ import qualified Job (Exclude(..)) import qualified Convert.AlwaysKW import qualified Convert.AsgnOp +import qualified Convert.Bits import qualified Convert.Enum import qualified Convert.FuncRet import qualified Convert.Interface @@ -30,6 +31,7 @@ type Phase = AST -> AST phases :: [Job.Exclude] -> [Phase] phases excludes = [ Convert.AsgnOp.convert + , Convert.Bits.convert , selectExclude (Job.Logic , Convert.Logic.convert) , Convert.FuncRet.convert , Convert.Enum.convert diff --git a/src/Convert/Bits.hs b/src/Convert/Bits.hs new file mode 100644 index 0000000..f15db6e --- /dev/null +++ b/src/Convert/Bits.hs @@ -0,0 +1,23 @@ +{- sv2v + - Author: Zachary Snow + - + - Elaboration of `$bits`, where possible + -} + +module Convert.Bits (convert) where + +import Convert.Traverse +import Language.SystemVerilog.AST + +convert :: AST -> AST +convert = + traverseDescriptions $ + traverseModuleItems $ + traverseExprs $ + traverseNestedExprs $ + convertExpr + +convertExpr :: Expr -> Expr +convertExpr (Bits (Left (IntegerVector _ _ [r]))) = rangeSize r +convertExpr (Bits (Left (Implicit _ [r]))) = rangeSize r +convertExpr other = other diff --git a/src/Convert/Traverse.hs b/src/Convert/Traverse.hs index a754931..6825828 100644 --- a/src/Convert/Traverse.hs +++ b/src/Convert/Traverse.hs @@ -235,6 +235,9 @@ traverseNestedExprsM mapper = exprMapper e1' <- exprMapper e1 e2' <- exprMapper e2 return $ Cast (Right e1') e2' + em (Bits (Right e)) = + exprMapper e >>= return . Bits . Right + em (Bits (Left t)) = return $ Bits (Left t) em (Dot e x) = exprMapper e >>= \e' -> return $ Dot e' x em (Pattern l) = do @@ -341,10 +344,11 @@ traverseExprsM mapper = moduleItemMapper decls' <- mapM declMapper decls stmts' <- mapM stmtMapper stmts return $ MIPackageItem $ Task lifetime f decls' stmts' - moduleItemMapper (Instance m params x r l) = do + moduleItemMapper (Instance m p x r l) = do + p' <- mapM portBindingMapper p l' <- mapM portBindingMapper l r' <- mapM rangeMapper r - return $ Instance m params x r' l' + return $ Instance m p' x r' l' moduleItemMapper (Modport x l) = mapM modportDeclMapper l >>= return . Modport x moduleItemMapper (NInputGate kw x lhs exprs) = do @@ -353,12 +357,29 @@ traverseExprsM mapper = moduleItemMapper moduleItemMapper (NOutputGate kw x lhss expr) = exprMapper expr >>= return . NOutputGate kw x lhss moduleItemMapper (Genvar x) = return $ Genvar x - moduleItemMapper (Generate x) = return $ Generate x + moduleItemMapper (Generate items) = do + items' <- mapM (traverseNestedGenItemsM genItemMapper) items + return $ Generate items' moduleItemMapper (MIPackageItem (Typedef t x)) = return $ MIPackageItem $ Typedef t x moduleItemMapper (MIPackageItem (Comment c)) = return $ MIPackageItem $ Comment c + genItemMapper (GenFor (x1, e1) cc (x2, op2, e2) mn subItems) = do + e1' <- exprMapper e1 + e2' <- exprMapper e2 + cc' <- exprMapper cc + return $ GenFor (x1, e1') cc' (x2, op2, e2') mn subItems + genItemMapper (GenIf e i1 i2) = do + e' <- exprMapper e + return $ GenIf e' i1 i2 + genItemMapper (GenCase e cases def) = do + e' <- exprMapper e + caseExprs <- mapM (mapM exprMapper . fst) cases + let cases' = zip caseExprs (map snd cases) + return $ GenCase e' cases' def + genItemMapper other = return other + modportDeclMapper (dir, ident, Just e) = do e' <- exprMapper e return (dir, ident, Just e') @@ -456,8 +477,8 @@ traverseTypesM mapper item = return $ Struct p (zip types idents) r exprMapper (Cast (Left t) e) = fullMapper t >>= \t' -> return $ Cast (Left t') e - exprMapper (Cast (Right e1) e2) = - return $ Cast (Right e1) e2 + exprMapper (Bits (Left t)) = + fullMapper t >>= return . Bits . Left exprMapper other = return other declMapper (Parameter t x e) = fullMapper t >>= \t' -> return $ Parameter t' x e diff --git a/src/Convert/Typedef.hs b/src/Convert/Typedef.hs index 285dace..b97980e 100644 --- a/src/Convert/Typedef.hs +++ b/src/Convert/Typedef.hs @@ -35,6 +35,7 @@ convert descriptions = convertDescription :: Types -> Description -> Description convertDescription globalTypes description = traverseModuleItems removeTypedef $ + traverseModuleItems (traverseExprs $ traverseNestedExprs $ convertExpr) $ traverseModuleItems (traverseTypes $ resolveType types) $ description where @@ -47,6 +48,12 @@ convertDescription globalTypes description = removeTypedef (MIPackageItem (Typedef _ x)) = MIPackageItem $ Comment $ "removed typedef: " ++ x removeTypedef other = other + convertExpr :: Expr -> Expr + convertExpr (Bits (Right (Ident x))) = + if Map.member x types + then Bits $ Left $ resolveType types (Alias x []) + else Bits $ Right $ Ident x + convertExpr other = other resolveType :: Types -> Type -> Type resolveType _ (Net kw rs) = Net kw rs diff --git a/src/Language/SystemVerilog/AST/Expr.hs b/src/Language/SystemVerilog/AST/Expr.hs index 16165cf..ba3cf0a 100644 --- a/src/Language/SystemVerilog/AST/Expr.hs +++ b/src/Language/SystemVerilog/AST/Expr.hs @@ -35,6 +35,7 @@ data Expr | BinOp BinOp Expr Expr | Mux Expr Expr Expr | Cast (Either Type Expr) Expr + | Bits (Either Type Expr) | Dot Expr Identifier | Pattern [(Maybe Identifier, Expr)] deriving (Eq, Ord) @@ -52,11 +53,8 @@ instance Show Expr where show (Dot e n ) = printf "%s.%s" (show e) n show (Mux c a b) = printf "(%s ? %s : %s)" (show c) (show a) (show b) show (Call f l ) = printf "%s(%s)" f (show l) - show (Cast tore e ) = printf "%s'(%s)" tStr (show e) - where - tStr = case tore of - Left a -> show a - Right a -> show a + show (Cast tore e ) = printf "%s'(%s)" (showEither tore) (show e) + show (Bits tore ) = printf "$bits(%s)" (showEither tore) show (Pattern l ) = printf "'{\n%s\n}" (indent $ intercalate ",\n" $ map showPatternItem l) where diff --git a/src/Language/SystemVerilog/AST/ShowHelp.hs b/src/Language/SystemVerilog/AST/ShowHelp.hs index 220a891..00eb861 100644 --- a/src/Language/SystemVerilog/AST/ShowHelp.hs +++ b/src/Language/SystemVerilog/AST/ShowHelp.hs @@ -13,6 +13,7 @@ module Language.SystemVerilog.AST.ShowHelp , commas , indentedParenList , showCase + , showEither ) where import Data.List (intercalate) @@ -52,3 +53,7 @@ indentedParenList l = "(\n" ++ (indent $ intercalate ",\n" l) ++ "\n)" showCase :: (Show x, Show y) => ([x], y) -> String showCase (a, b) = printf "%s: %s" (commas $ map show a) (show b) + +showEither :: (Show a, Show b) => Either a b -> String +showEither (Left v) = show v +showEither (Right v) = show v diff --git a/src/Language/SystemVerilog/Parser/Lex.x b/src/Language/SystemVerilog/Parser/Lex.x index e43321f..b17961a 100644 --- a/src/Language/SystemVerilog/Parser/Lex.x +++ b/src/Language/SystemVerilog/Parser/Lex.x @@ -102,6 +102,7 @@ $decimalDigit = [0-9] tokens :- + "$bits" { tok KW_dollar_bits } "always" { tok KW_always } "always_comb" { tok KW_always_comb } "always_ff" { tok KW_always_ff } diff --git a/src/Language/SystemVerilog/Parser/Parse.y b/src/Language/SystemVerilog/Parser/Parse.y index a98aee4..cf70c30 100644 --- a/src/Language/SystemVerilog/Parser/Parse.y +++ b/src/Language/SystemVerilog/Parser/Parse.y @@ -17,6 +17,7 @@ import Language.SystemVerilog.Parser.Tokens %token +"$bits" { Token KW_dollar_bits _ _ } "always" { Token KW_always _ _ } "always_comb" { Token KW_always_comb _ _ } "always_ff" { Token KW_always_ff _ _ } @@ -264,6 +265,9 @@ PartialType :: { Signing -> [Range] -> Type } | NonIntegerType { \Unspecified -> \[] -> NonInteger $1 } | "enum" opt(Type) "{" EnumItems "}" { \Unspecified -> Enum $2 $4 } | "struct" Packing "{" StructItems "}" { \Unspecified -> Struct $2 $4 } +TypeNonIdent :: { Type } + : PartialType Dimensions { $1 Unspecified $2 } + | PartialType Signing Dimensions { $1 $2 $3 } CastingType :: { Type } : IntegerVectorType { IntegerVector $1 Unspecified [] } @@ -762,11 +766,15 @@ Exprs :: { [Expr] } : Expr { [$1] } | Exprs "," Expr { $1 ++ [$3] } +BitsArg :: { Either Type Expr } + : TypeNonIdent { Left $1 } + | Expr { Right $1 } Expr :: { Expr } : "(" Expr ")" { $2 } | String { String $1 } | Number { Number $1 } | Identifier "(" CallArgs ")" { Call $1 $3 } + | "$bits" "(" BitsArg ")" { Bits $3 } | Identifier { Ident $1 } | Expr Range { Range $1 $2 } | Expr "[" Expr "]" { Bit $1 $3 } diff --git a/src/Language/SystemVerilog/Parser/Tokens.hs b/src/Language/SystemVerilog/Parser/Tokens.hs index e098e97..e27307d 100644 --- a/src/Language/SystemVerilog/Parser/Tokens.hs +++ b/src/Language/SystemVerilog/Parser/Tokens.hs @@ -63,6 +63,7 @@ data TokenName | KW_disable | KW_dist | KW_do + | KW_dollar_bits | KW_edge | KW_else | KW_end diff --git a/sv2v.cabal b/sv2v.cabal index 518fefb..e8227cc 100644 --- a/sv2v.cabal +++ b/sv2v.cabal @@ -51,6 +51,7 @@ executable sv2v Convert Convert.AlwaysKW Convert.AsgnOp + Convert.Bits Convert.Enum Convert.FuncRet Convert.Interface