From dd1a9efb40fd2698a533ff20e07252f7b68f496c Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Wed, 3 Feb 2021 16:12:05 -0500 Subject: [PATCH] refactor cast conversion - delegate cast type and sign resolution to TypeOf conversion - internal support for injecting data declarations into statements - fix size and sign of unbased unsized literals used in casts - avoid generating many unnecessary explicit casts - support casts which depend on localparams within procedures - expression traversal correctly visits types within type casts - fix typeof on expressions of net types - handle additional edge cases for unsized integer array patterns - preserve signedness of implicitly flattened unpacked integer arrays --- src/Convert.hs | 8 +- src/Convert/Cast.hs | 214 ++++++++++++++++++++++ src/Convert/Scoper.hs | 67 +++++-- src/Convert/SignCast.hs | 29 --- src/Convert/SizeCast.hs | 224 ----------------------- src/Convert/Struct.hs | 4 +- src/Convert/Traverse.hs | 14 +- src/Convert/TypeOf.hs | 113 ++++++++++-- src/Language/SystemVerilog/AST/Number.hs | 2 +- src/Language/SystemVerilog/AST/Type.hs | 3 +- sv2v.cabal | 3 +- test/basic/cast.sv | 15 ++ test/basic/cast.v | 12 ++ test/basic/cast_nest.sv | 15 ++ test/basic/cast_nest.v | 12 ++ test/basic/cast_nettype.sv | 25 +++ test/basic/cast_nettype.v | 20 ++ test/basic/cast_nettype.vh | 31 ++++ test/basic/cast_procedure.sv | 31 ++++ test/basic/cast_procedure.v | 32 ++++ test/basic/cast_struct_nested.sv | 14 ++ test/basic/cast_struct_nested.v | 10 + test/basic/duplicate_cast.v | 8 +- test/basic/integer_array.sv | 13 ++ test/basic/integer_array.v | 12 ++ test/basic/size_cast.sv | 12 ++ test/basic/size_cast.v | 12 ++ test/basic/typeof_signed.sv | 4 + 28 files changed, 647 insertions(+), 312 deletions(-) create mode 100644 src/Convert/Cast.hs delete mode 100644 src/Convert/SignCast.hs delete mode 100644 src/Convert/SizeCast.hs create mode 100644 test/basic/cast_nest.sv create mode 100644 test/basic/cast_nest.v create mode 100644 test/basic/cast_nettype.sv create mode 100644 test/basic/cast_nettype.v create mode 100644 test/basic/cast_nettype.vh create mode 100644 test/basic/cast_procedure.sv create mode 100644 test/basic/cast_procedure.v create mode 100644 test/basic/cast_struct_nested.sv create mode 100644 test/basic/cast_struct_nested.v diff --git a/src/Convert.hs b/src/Convert.hs index 00a78b9..1cf2fcd 100644 --- a/src/Convert.hs +++ b/src/Convert.hs @@ -13,6 +13,7 @@ import qualified Convert.AlwaysKW import qualified Convert.AsgnOp import qualified Convert.Assertion import qualified Convert.BlockDecl +import qualified Convert.Cast import qualified Convert.DimensionQuery import qualified Convert.DuplicateGenvar import qualified Convert.EmptyArgs @@ -35,9 +36,7 @@ import qualified Convert.Package import qualified Convert.ParamNoDefault import qualified Convert.ParamType import qualified Convert.RemoveComments -import qualified Convert.SignCast import qualified Convert.Simplify -import qualified Convert.SizeCast import qualified Convert.StarPort import qualified Convert.Stream import qualified Convert.StringParam @@ -70,11 +69,11 @@ phases excludes = , Convert.KWArgs.convert , Convert.LogOp.convert , Convert.MultiplePacked.convert + , Convert.UnbasedUnsized.convert + , Convert.Cast.convert , Convert.TypeOf.convert , Convert.DimensionQuery.convert , Convert.ParamType.convert - , Convert.UnbasedUnsized.convert - , Convert.SizeCast.convert , Convert.Simplify.convert , Convert.Stream.convert , Convert.Struct.convert @@ -83,7 +82,6 @@ phases excludes = , Convert.Unique.convert , Convert.UnpackedArray.convert , Convert.Unsigned.convert - , Convert.SignCast.convert , Convert.Wildcard.convert , Convert.Enum.convert , Convert.ForDecl.convert diff --git a/src/Convert/Cast.hs b/src/Convert/Cast.hs new file mode 100644 index 0000000..cd0955c --- /dev/null +++ b/src/Convert/Cast.hs @@ -0,0 +1,214 @@ +{-# LANGUAGE PatternSynonyms #-} +{- sv2v + - Author: Zachary Snow + - + - Conversion of elaborated type casts + - + - Much of the work of elaborating various casts into explicit integer vector + - type casts happens in the TypeOf conversion, which contains the primary logic + - for resolving the type and signedness of expressions. It also removes + - redundant explicit casts to produce cleaner output. + - + - Type casts are defined as producing the result of the expression assigned to + - a variable of the given type. In the general case, this conversion generates + - a pass-through function which performs this assignment-based casting. This + - allows for casts to be used anywhere expressions are used, including within + - constant expressions. + - + - It is possible for the type in a cast to refer to localparams within a + - procedure. Without evaluating the localparam itself, a function outside of + - the procedure cannot refer to the size of the type in the cast. In these + - scenarios, the cast is instead performed by adding a temporary parameter or + - data declaration within the procedure and assigning the expression to that + - declaration to perform the cast. + - + - A few common cases of casts on number literals are fully elaborated into + - their corresponding resulting number literals to avoid excessive noise. + -} + +module Convert.Cast (convert) where + +import Control.Monad.Writer.Strict +import Data.List (isPrefixOf) + +import Convert.ExprUtils +import Convert.Scoper +import Convert.Traverse +import Language.SystemVerilog.AST + +convert :: [AST] -> [AST] +convert = map $ traverseDescriptions convertDescription + +convertDescription :: Description -> Description +convertDescription description = + traverseModuleItems dropDuplicateCaster $ + partScoper + traverseDeclM traverseModuleItemM traverseGenItemM traverseStmtM + description + +type ST = Scoper Expr + +traverseDeclM :: Decl -> ST Decl +traverseDeclM decl = do + decl' <- case decl of + Variable d t x a e -> do + enterStmt + e' <- traverseExprM e + exitStmt + details <- lookupLocalIdentM x + if isPrefixOf "sv2v_cast_" x && details /= Nothing + then return $ Variable Local t DuplicateTag [] Nil + else do + insertElem x Nil + return $ Variable d t x a e' + Param _ _ x _ -> + insertElem x Nil >> return decl + ParamType _ _ _ -> return decl + CommentDecl _ -> return decl + traverseDeclExprsM traverseExprM decl' + +pattern DuplicateTag :: Identifier +pattern DuplicateTag = ":duplicate_cast_to_be_removed:" + +dropDuplicateCaster :: ModuleItem -> ModuleItem +dropDuplicateCaster (MIPackageItem (Function _ _ DuplicateTag _ _)) = + Generate [] +dropDuplicateCaster other = other + +traverseModuleItemM :: ModuleItem -> ST ModuleItem +traverseModuleItemM (Genvar x) = + insertElem x Nil >> return (Genvar x) +traverseModuleItemM item = + traverseExprsM traverseExprM item + +traverseGenItemM :: GenItem -> ST GenItem +traverseGenItemM = traverseGenItemExprsM traverseExprM + +traverseStmtM :: Stmt -> ST Stmt +traverseStmtM stmt = do + enterStmt + stmt' <- traverseStmtExprsM traverseExprM stmt + exitStmt + return stmt' + +traverseExprM :: Expr -> ST Expr +traverseExprM (Cast (Left (IntegerVector _ sg rs)) e) = do + e' <- traverseExprM e + convertCastM (dimensionsSize rs) e' signed + where signed = sg == Signed +traverseExprM other = + traverseSinglyNestedExprsM traverseExprM other + +convertCastM :: Expr -> Expr -> Bool -> ST Expr +convertCastM (RawNum size) (RawNum val) signed = + return $ Number $ Decimal (fromIntegral size) signed val' + where val' = val `mod` (2 ^ size) +convertCastM (RawNum size) (Number (Based 1 True Binary a b)) signed = + return $ Number $ Based (fromIntegral size) signed Binary + (val * a) (val * b) + where val = (2 ^ size) - 1 +convertCastM (RawNum size) (Number (UnbasedUnsized ch)) signed = + convertCastM (RawNum size) (Number num) signed + where + num = Based 1 True Binary a b + (a, b) = case ch of + '0' -> (0, 0) + '1' -> (1, 0) + 'x' -> (0, 1) + 'z' -> (1, 1) + _ -> error $ "unexpected unbased-unsized digit: " ++ [ch] +convertCastM size value signed = do + value' <- traverseExprM value + useFn <- embedScopes canUseCastFn size + if useFn then do + let name = castFnName size signed + details <- lookupLocalIdentM name + when (details == Nothing) $ + injectItem $ castFn name size signed + return $ Call (Ident name) (Args [value'] []) + else do + name <- castDeclName 0 + insertElem name Nil + useVar <- withinStmt + injectDecl $ castDecl useVar name value' size signed + return $ Ident name + +-- checks if a cast size can be hoisted to a cast function +canUseCastFn :: Scopes a -> Expr -> Bool +canUseCastFn scopes size = + not (inProcedure && anyNonLocal) + where + inProcedure = withinProcedure scopes + anyNonLocal = getAny $ execWriter $ + collectNestedExprsM collectNonLocalExprM size + collectNonLocalExprM :: Expr -> Writer Any () + collectNonLocalExprM expr = + case lookupElem scopes expr of + Nothing -> return () + Just ([_, _], _, _) -> return () + Just (_, _, _) -> tell $ Any True + +castType :: Expr -> Bool -> Type +castType size signed = + IntegerVector TLogic sg [r] + where + r = (simplify $ BinOp Sub size (RawNum 1), RawNum 0) + sg = if signed then Signed else Unspecified + +castFn :: Identifier -> Expr -> Bool -> ModuleItem +castFn name size signed = + MIPackageItem $ Function Automatic t name [decl] [stmt] + where + inp = "inp" + t = castType size signed + decl = Variable Input t inp [] Nil + stmt = Asgn AsgnOpEq Nothing (LHSIdent name) (Ident inp) + +castFnName :: Expr -> Bool -> String +castFnName size signed = + "sv2v_cast_" ++ sizeStr ++ suffix + where + sizeStr = case size of + Number n -> + case numberToInteger n of + Just v -> show v + _ -> shortHash size + _ -> shortHash size + suffix = if signed then "_signed" else "" + +castDecl :: Bool -> Identifier -> Expr -> Expr -> Bool -> Decl +castDecl useVar name value size signed = + if useVar + then Variable Local t name [] value + else Param Localparam t name value + where t = castType size signed + +castDeclName :: Int -> ST String +castDeclName counter = do + details <- lookupElemM name + if details == Nothing + then return name + else castDeclName (counter + 1) + where + name = if counter == 0 + then prefix + else prefix ++ '_' : show counter + prefix = "sv2v_tmp_cast" + +-- track whether procedural casts should use variables +pattern WithinStmt :: Identifier +pattern WithinStmt = ":within_stmt:" +withinStmt :: ST Bool +withinStmt = do + details <- lookupElemM WithinStmt + return $ case details of + Just (_, _, t) -> t /= Nil + Nothing -> False +enterStmt :: ST () +enterStmt = do + inProcedure <- withinProcedureM + when inProcedure $ insertElem WithinStmt (RawNum 1) +exitStmt :: ST () +exitStmt = do + inProcedure <- withinProcedureM + when inProcedure $ insertElem WithinStmt Nil diff --git a/src/Convert/Scoper.hs b/src/Convert/Scoper.hs index 3796b8f..e9066ef 100644 --- a/src/Convert/Scoper.hs +++ b/src/Convert/Scoper.hs @@ -32,6 +32,7 @@ module Convert.Scoper , partScoperT , insertElem , injectItem + , injectDecl , lookupElem , lookupElemM , Access(..) @@ -83,7 +84,8 @@ data Scopes a = Scopes { sCurrent :: [Tier] , sMapping :: Mapping a , sProcedure :: Bool - , sInjected :: [ModuleItem] + , sInjectedItems :: [ModuleItem] + , sInjectedDecls :: [Decl] } deriving Show extractMapping :: Scopes a -> Map.Map Identifier a @@ -176,13 +178,25 @@ insertElem key element = do injectItem :: Monad m => ModuleItem -> ScoperT a m () injectItem item = - modify' $ \s -> s { sInjected = add $ sInjected s } - where - add :: [ModuleItem] -> [ModuleItem] - add items = - if elem item items - then items - else items ++ [item] + modify' $ \s -> s { sInjectedItems = item : sInjectedItems s } + +injectDecl :: Monad m => Decl -> ScoperT a m () +injectDecl decl = + modify' $ \s -> s { sInjectedDecls = decl : sInjectedDecls s } + +consumeInjectedItems :: Monad m => ScoperT a m [ModuleItem] +consumeInjectedItems = do + injected <- gets sInjectedItems + when (not $ null injected) $ + modify' $ \s -> s { sInjectedItems = [] } + return $ reverse injected + +consumeInjectedDecls :: Monad m => ScoperT a m [Decl] +consumeInjectedDecls = do + injected <- gets sInjectedDecls + when (not $ null injected) $ + modify' $ \s -> s { sInjectedDecls = [] } + return $ reverse injected type Replacements = Map.Map Identifier Expr @@ -305,7 +319,7 @@ runScoperT declMapper moduleItemMapper genItemMapper stmtMapper topName items = items' <- mapM wrappedModuleItemMapper items exitScope topName "" return items' - initialState = Scopes [] Map.empty False [] + initialState = Scopes [] Map.empty False [] [] wrappedModuleItemMapper = scopeModuleItemT declMapper moduleItemMapper genItemMapper stmtMapper @@ -324,13 +338,28 @@ scopeModuleItemT declMapper moduleItemMapper genItemMapper stmtMapper = fullStmtMapper :: Stmt -> ScoperT a m Stmt fullStmtMapper (Block kw name decls stmts) = do enterScope name "" - decls' <- mapM declMapper decls + decls' <- fmap concat $ mapM declMapper' decls stmts' <- mapM fullStmtMapper stmts exitScope name "" return $ Block kw name decls' stmts' -- TODO: Do we need to support the various procedural loops? - fullStmtMapper stmt = - stmtMapper stmt >>= traverseSinglyNestedStmtsM fullStmtMapper + fullStmtMapper stmt = do + stmt' <- stmtMapper stmt + injected <- consumeInjectedDecls + if null injected + then traverseSinglyNestedStmtsM fullStmtMapper stmt' + else fullStmtMapper $ Block Seq "" injected [stmt'] + + -- converts a decl and adds decls injected during conversion + declMapper' :: Decl -> ScoperT a m [Decl] + declMapper' decl = do + decl' <- declMapper decl + injected <- consumeInjectedDecls + if null injected + then return [decl'] + else do + injected' <- mapM declMapper injected + return $ injected' ++ [decl'] mapTFDecls :: [Decl] -> ScoperT a m [Decl] mapTFDecls = mapTFDecls' 0 @@ -340,14 +369,14 @@ scopeModuleItemT declMapper moduleItemMapper genItemMapper stmtMapper = mapTFDecls' idx (decl : decls) = case argIdxDecl decl of Nothing -> do - decl' <- declMapper decl + decl' <- declMapper' decl decls' <- mapTFDecls' idx decls - return $ decl' : decls' + return $ decl' ++ decls' Just declFunc -> do _ <- declMapper $ declFunc idx - decl' <- declMapper decl + decl' <- declMapper' decl decls' <- mapTFDecls' (idx + 1) decls - return $ decl' : decls' + return $ decl' ++ decls' argIdxDecl :: Decl -> Maybe (Int -> Decl) argIdxDecl (Variable d t _ a e) = @@ -369,11 +398,10 @@ scopeModuleItemT declMapper moduleItemMapper genItemMapper stmtMapper = wrappedModuleItemMapper :: ModuleItem -> ScoperT a m ModuleItem wrappedModuleItemMapper item = do item' <- fullModuleItemMapper item - injected <- gets sInjected + injected <- consumeInjectedItems if null injected then return item' else do - modify' $ \s -> s { sInjected = [] } injected' <- mapM fullModuleItemMapper injected return $ Generate $ map GenModuleItem $ injected' ++ [item'] fullModuleItemMapper :: ModuleItem -> ScoperT a m ModuleItem @@ -423,11 +451,10 @@ scopeModuleItemT declMapper moduleItemMapper genItemMapper stmtMapper = fullGenItemMapper :: GenItem -> ScoperT a m GenItem fullGenItemMapper genItem = do genItem' <- genItemMapper genItem - injected <- gets sInjected + injected <- consumeInjectedItems if null injected then scopeGenItemMapper genItem' else do - modify' $ \s -> s { sInjected = [] } injected' <- mapM fullModuleItemMapper injected genItem'' <- scopeGenItemMapper genItem' let genItems = map GenModuleItem injected' ++ [genItem''] diff --git a/src/Convert/SignCast.hs b/src/Convert/SignCast.hs deleted file mode 100644 index e879d82..0000000 --- a/src/Convert/SignCast.hs +++ /dev/null @@ -1,29 +0,0 @@ -{- sv2v - - Author: Zachary Snow - - - - Conversion for `signed` and `unsigned` type casts. - - - - SystemVerilog has `signed'(foo)` and `unsigned'(foo)` as syntactic sugar for - - the `$signed` and `$unsigned` system functions present in Verilog-2005. This - - conversion elaborates these casts. - -} - -module Convert.SignCast (convert) where - -import Convert.Traverse -import Language.SystemVerilog.AST - -convert :: [AST] -> [AST] -convert = - map $ - traverseDescriptions $ - traverseModuleItems $ - traverseExprs $ - traverseNestedExprs convertExpr - -convertExpr :: Expr -> Expr -convertExpr (Cast (Left (Implicit Signed [])) e) = - Call (Ident "$signed") (Args [e] []) -convertExpr (Cast (Left (Implicit Unsigned [])) e) = - Call (Ident "$unsigned") (Args [e] []) -convertExpr other = other diff --git a/src/Convert/SizeCast.hs b/src/Convert/SizeCast.hs deleted file mode 100644 index c6a4879..0000000 --- a/src/Convert/SizeCast.hs +++ /dev/null @@ -1,224 +0,0 @@ -{-# LANGUAGE PatternSynonyms #-} -{- sv2v - - Author: Zachary Snow - - - - Conversion of size casts on non-constant expressions. - -} - -module Convert.SizeCast (convert) where - -import Control.Monad.Writer.Strict -import Data.List (isPrefixOf) - -import Convert.ExprUtils -import Convert.Scoper -import Convert.Traverse -import Language.SystemVerilog.AST - -convert :: [AST] -> [AST] -convert = map $ traverseDescriptions convertDescription - -convertDescription :: Description -> Description -convertDescription = - traverseModuleItems dropDuplicateCaster . partScoper - traverseDeclM traverseModuleItemM traverseGenItemM traverseStmtM - -traverseDeclM :: Decl -> Scoper Type Decl -traverseDeclM decl = do - decl' <- case decl of - Variable _ t x _ _ -> do - details <- lookupLocalIdentM x - if isPrefixOf "sv2v_cast_" x && details /= Nothing - then return $ Variable Local t DuplicateTag [] Nil - else insertElem x t >> return decl - Param _ t x _ -> do - inProcedure <- withinProcedureM - when (not inProcedure) $ insertElem x t - return decl - ParamType _ _ _ -> return decl - CommentDecl _ -> return decl - traverseDeclExprsM traverseExprM decl' - -pattern DuplicateTag :: Identifier -pattern DuplicateTag = ":duplicate_cast_to_be_removed:" - -dropDuplicateCaster :: ModuleItem -> ModuleItem -dropDuplicateCaster (MIPackageItem (Function _ _ DuplicateTag _ _)) = - Generate [] -dropDuplicateCaster other = other - -traverseModuleItemM :: ModuleItem -> Scoper Type ModuleItem -traverseModuleItemM (Genvar x) = - insertElem x (IntegerAtom TInteger Unspecified) >> return (Genvar x) -traverseModuleItemM item = - traverseExprsM traverseExprM item - -traverseGenItemM :: GenItem -> Scoper Type GenItem -traverseGenItemM = traverseGenItemExprsM traverseExprM - -traverseStmtM :: Stmt -> Scoper Type Stmt -traverseStmtM = traverseStmtExprsM traverseExprM - -traverseExprM :: Expr -> Scoper Type Expr -traverseExprM = - traverseNestedExprsM convertExprM - where - convertExprM :: Expr -> Scoper Type Expr - convertExprM (Cast (Right (Number s)) (Number n)) = - case n of - UnbasedUnsized{} -> fallback - Decimal (-32) True val -> - num $ Decimal (fromIntegral size) False val' - where - Just size = numberToInteger s - val' = val `mod` (2 ^ size) - Decimal size signed val -> - if sizesMatch - then num $ Decimal (abs size) signed val - else fallback - Based size signed base vals knds -> - if sizesMatch - then num $ Based (abs size) signed base vals knds - else fallback - where - sizesMatch = numberToInteger s == Just (numberBitLength n) - fallback = convertCastM (Number s) (Number n) - num = return . Number - convertExprM (Cast (Right (Ident x)) e) = do - details <- lookupElemM x - -- can't convert this cast yet because x could be a typename - if details == Nothing - then return $ Cast (Right $ Ident x) e - else convertCastM (Ident x) e - convertExprM (Cast (Right s) e) = - if isSimpleExpr s - then convertCastM s e - else return $ Cast (Right s) e - convertExprM (Cast (Left (IntegerVector _ Signed rs)) e) = - convertCastWithSigningM (dimensionsSize rs) e Signed - convertExprM (Cast (Left (IntegerVector _ _ rs)) e) = - convertExprM $ Cast (Right $ dimensionsSize rs) e - convertExprM other = return other - - convertCastM :: Expr -> Expr -> Scoper Type Expr - convertCastM (RawNum n) (Number (Based 1 True Binary a b)) = - return $ Number $ Based (fromIntegral n) True Binary - (extend a) (extend b) - where - extend 0 = 0 - extend 1 = (2 ^ n) - 1 - extend _ = error "not possible" - convertCastM (RawNum n) (Number (UnbasedUnsized ch)) = - return $ Number $ Based (fromIntegral n) False Binary - (extend a) (extend b) - where - (a, b) = case ch of - '0' -> (0, 0) - '1' -> (1, 0) - 'x' -> (0, 1) - 'z' -> (1, 1) - _ -> error $ "unexpected unbased-unsized digit: " ++ [ch] - extend :: Integer -> Integer - extend 0 = 0 - extend 1 = (2 ^ n) - 1 - extend _ = error "not possible" - convertCastM s e = do - signing <- embedScopes exprSigning e - case signing of - Just sg -> convertCastWithSigningM s e sg - _ -> return $ Cast (Right s) e - - convertCastWithSigningM :: Expr -> Expr -> Signing -> Scoper Type Expr - convertCastWithSigningM (RawNum size) (RawNum val) Signed = - return $ Number $ Decimal (fromIntegral size) True val' - where val' = val `mod` (2 ^ size) - convertCastWithSigningM s e sg = do - details <- lookupLocalIdentM $ castFnName s sg - when (details == Nothing) $ injectItem $ MIPackageItem $ castFn s sg - let f = castFnName s sg - let args = Args [e] [] - return $ Call (Ident f) args - -isSimpleExpr :: Expr -> Bool -isSimpleExpr = - null . execWriter . collectNestedExprsM collectUnresolvedExprM - where - collectUnresolvedExprM :: Expr -> Writer [Expr] () - collectUnresolvedExprM (expr @ PSIdent{}) = tell [expr] - collectUnresolvedExprM (expr @ CSIdent{}) = tell [expr] - collectUnresolvedExprM (expr @ DimsFn{}) = tell [expr] - collectUnresolvedExprM (expr @ DimFn {}) = tell [expr] - collectUnresolvedExprM _ = return () - -castFn :: Expr -> Signing -> PackageItem -castFn e sg = - Function Automatic t fnName [decl] [Return $ Ident inp] - where - inp = "inp" - r = (simplify $ BinOp Sub e (RawNum 1), RawNum 0) - t = IntegerVector TLogic sg [r] - fnName = castFnName e sg - decl = Variable Input t inp [] Nil - -castFnName :: Expr -> Signing -> String -castFnName e sg = - if sg == Unspecified - then init name - else name - where - sizeStr = case e of - Number n -> - case numberToInteger n of - Just v -> show v - _ -> shortHash e - _ -> shortHash e - name = "sv2v_cast_" ++ sizeStr ++ "_" ++ show sg - -exprSigning :: Scopes Type -> Expr -> Maybe Signing -exprSigning scopes (BinOp op e1 e2) = - combiner sg1 sg2 - where - sg1 = exprSigning scopes e1 - sg2 = exprSigning scopes e2 - combiner = case op of - BitAnd -> combineSigning - BitXor -> combineSigning - BitXnor -> combineSigning - BitOr -> combineSigning - Mul -> combineSigning - Div -> combineSigning - Add -> combineSigning - Sub -> combineSigning - Mod -> curry fst - Pow -> curry fst - ShiftAL -> curry fst - ShiftAR -> curry fst - _ -> \_ _ -> Just Unspecified -exprSigning _ (Number n) = - Just $ if numberIsSigned n - then Signed - else Unsigned -exprSigning scopes expr = - case lookupElem scopes expr of - Just (_, _, t) -> typeSigning t - Nothing -> Just Unspecified - -combineSigning :: Maybe Signing -> Maybe Signing -> Maybe Signing -combineSigning Nothing _ = Nothing -combineSigning _ Nothing = Nothing -combineSigning (Just Unspecified) _ = Just Unspecified -combineSigning _ (Just Unspecified) = Just Unspecified -combineSigning (Just Unsigned) _ = Just Unsigned -combineSigning _ (Just Unsigned) = Just Unsigned -combineSigning (Just Signed) (Just Signed) = Just Signed - -typeSigning :: Type -> Maybe Signing -typeSigning (Net _ sg _) = Just sg -typeSigning (Implicit sg _) = Just sg -typeSigning (IntegerVector _ sg _) = Just sg -typeSigning (IntegerAtom t sg ) = - Just $ case (sg, t) of - (Unspecified, TTime) -> Unsigned - (Unspecified, _ ) -> Signed - (_ , _ ) -> sg -typeSigning _ = Nothing diff --git a/src/Convert/Struct.hs b/src/Convert/Struct.hs index 1929224..89981a7 100644 --- a/src/Convert/Struct.hs +++ b/src/Convert/Struct.hs @@ -281,7 +281,9 @@ convertExpr (t @ IntegerVector{}) (Concat exprs) = t' = dropInnerTypeRange t isUnsizedNumber :: Expr -> Bool isUnsizedNumber (Number n) = not $ numberIsSized n - isUnsizedNumber (UniOp UniSub e) = isUnsizedNumber e + isUnsizedNumber (UniOp _ e) = isUnsizedNumber e + isUnsizedNumber (BinOp _ e1 e2) = + isUnsizedNumber e1 || isUnsizedNumber e2 isUnsizedNumber _ = False -- TODO: This is really a conversion for using default patterns to diff --git a/src/Convert/Traverse.hs b/src/Convert/Traverse.hs index 96c32bb..78ab6a4 100644 --- a/src/Convert/Traverse.hs +++ b/src/Convert/Traverse.hs @@ -460,12 +460,10 @@ traverseSinglyNestedExprsM exprMapper = em e2' <- exprMapper e2 e3' <- exprMapper e3 return $ Mux e1' e2' e3' - em (Cast (Left t) e) = - exprMapper e >>= return . Cast (Left t) - em (Cast (Right e1) e2) = do - e1' <- exprMapper e1 - e2' <- exprMapper e2 - return $ Cast (Right e1') e2' + em (Cast tore e) = do + tore' <- typeOrExprMapper tore + e' <- exprMapper e + return $ Cast tore' e' em (DimsFn f tore) = typeOrExprMapper tore >>= return . DimsFn f em (DimFn f tore e) = do @@ -834,8 +832,8 @@ traverseExprTypesM mapper = exprMapper typeOrExprMapper (Right e) = return $ Right e typeOrExprMapper (Left t) = mapper t >>= return . Left - exprMapper (Cast (Left t) e) = - mapper t >>= \t' -> return $ Cast (Left t') e + exprMapper (Cast tore e) = + typeOrExprMapper tore >>= return . flip Cast e exprMapper (DimsFn f tore) = typeOrExprMapper tore >>= return . DimsFn f exprMapper (DimFn f tore e) = do diff --git a/src/Convert/TypeOf.hs b/src/Convert/TypeOf.hs index 90fe40d..fa78552 100644 --- a/src/Convert/TypeOf.hs +++ b/src/Convert/TypeOf.hs @@ -11,6 +11,13 @@ - concatenation conversions, defer the resolution of type information to this - conversion pass by producing nodes with the `type` operator during - elaboration. + - + - This conversion also elaborates sign and size casts to their primitive types. + - Sign casts take on the size of the underlying expression. Size casts take on + - the sign of the underlying expression. This conversion incorporates this + - elaboration as the canonical source for type information. It also enables the + - removal of unnecessary casts often resulting from struct literals or casts in + - the source intended to appease certain lint rules. -} module Convert.TypeOf (convert) where @@ -18,7 +25,7 @@ module Convert.TypeOf (convert) where import Data.Tuple (swap) import qualified Data.Map.Strict as Map -import Convert.ExprUtils (endianCondRange, simplify) +import Convert.ExprUtils (dimensionsSize, endianCondRange, simplify) import Convert.Scoper import Convert.Traverse import Language.SystemVerilog.AST @@ -34,8 +41,8 @@ pattern UnitType = IntegerVector TLogic Unspecified [] -- insert the given declaration into the scope, and convert an TypeOfs within traverseDeclM :: Decl -> Scoper Type Decl traverseDeclM decl = do - item <- traverseModuleItemM (MIPackageItem $ Decl decl) - let MIPackageItem (Decl decl') = item + decl' <- traverseDeclExprsM traverseExprM decl + >>= traverseDeclTypesM traverseTypeM case decl' of Variable _ (Implicit sg rs) ident a _ -> -- implicit types, which are commonly found in function return @@ -66,7 +73,8 @@ traverseModuleItemM (Genvar x) = do insertElem x $ IntegerAtom TInteger Unspecified return $ Genvar x traverseModuleItemM item = - traverseTypesM (traverseNestedTypesM traverseTypeM) item + traverseNodesM traverseExprM return traverseTypeM traverseLHSM return item + where traverseLHSM = traverseLHSExprsM traverseExprM -- convert TypeOf in a GenItem traverseGenItemM :: GenItem -> Scoper Type GenItem @@ -76,14 +84,57 @@ traverseGenItemM = traverseGenItemExprsM traverseExprM traverseStmtM :: Stmt -> Scoper Type Stmt traverseStmtM = traverseStmtExprsM traverseExprM --- convert TypeOf in a Expr +-- convert TypeOf in an Expr traverseExprM :: Expr -> Scoper Type Expr -traverseExprM = traverseNestedExprsM $ traverseExprTypesM $ - traverseNestedTypesM traverseTypeM +traverseExprM (Cast (Left (Implicit sg [])) expr) = + -- `signed'(foo)` and `unsigned'(foo)` are syntactic sugar for the `$signed` + -- and `$unsigned` system functions present in Verilog-2005 + traverseExprM $ Call (Ident fn) $ Args [expr] [] + where fn = if sg == Signed then "$signed" else "$unsigned" +traverseExprM (Cast (Left t) (Number (UnbasedUnsized ch))) = + -- defer until this expression becomes explicit + return $ Cast (Left t) (Number (UnbasedUnsized ch)) +traverseExprM (Cast (Left (t @ (IntegerAtom TInteger _))) expr) = + -- convert to cast to an integer vector type + traverseExprM $ Cast (Left t') expr + where + (tf, []) = typeRanges t + t' = tf [(RawNum 1, RawNum 1)] +traverseExprM (Cast (Left t1) expr) = do + expr' <- traverseExprM expr + t1' <- traverseTypeM t1 + t2 <- typeof expr' + if typeCastUnneeded t1' t2 + then traverseExprM $ makeExplicit expr' + else return $ Cast (Left t1') expr' +traverseExprM (Cast (Right (Ident x)) expr) = do + expr' <- traverseExprM expr + details <- lookupElemM x + if details == Nothing + then return $ Cast (Left $ Alias x []) expr' + else elaborateSizeCast (Ident x) expr' +traverseExprM (Cast (Right size) expr) = do + expr' <- traverseExprM expr + elaborateSizeCast size expr' +traverseExprM other = + traverseExprTypesM traverseTypeM other + >>= traverseSinglyNestedExprsM traverseExprM +-- carry forward the signedness of the expression when cast to the given size +elaborateSizeCast :: Expr -> Expr -> Scoper Type Expr +elaborateSizeCast size value = do + t <- typeof value + case typeSignedness t of + Unspecified -> return $ Cast (Right size) value + sg -> traverseExprM $ Cast (Left $ typeOfSize sg size) value + +-- convert TypeOf in a Type traverseTypeM :: Type -> Scoper Type Type -traverseTypeM (TypeOf expr) = typeof expr -traverseTypeM other = return other +traverseTypeM (TypeOf expr) = + traverseExprM expr >>= typeof +traverseTypeM other = + traverseTypeExprsM traverseExprM other + >>= traverseSinglyNestedTypesM traverseTypeM -- attempts to find the given (potentially hierarchical or generate-scoped) -- expression in the available scope information @@ -92,11 +143,15 @@ lookupTypeOf expr = do details <- lookupElemM expr case details of Nothing -> return $ TypeOf expr - Just (_, replacements, typ) -> + Just (_, replacements, typ) -> do + let typ' = toVarType typ return $ if Map.null replacements - then typ - else rewriteType replacements typ + then typ' + else rewriteType replacements typ' where + toVarType :: Type -> Type + toVarType (Net _ sg rs) = IntegerVector TLogic sg rs + toVarType other = other rewriteType :: Replacements -> Type -> Type rewriteType replacements = traverseNestedTypes $ traverseTypeExprs $ traverseNestedExprs (replace replacements) @@ -155,6 +210,7 @@ typeof (orig @ (Dot e x)) = do case lookup x $ map swap fields of Just typ -> typ Nothing -> TypeOf orig +typeof (Cast (Left t) _) = traverseTypeM t typeof (UniOp op expr) = typeofUniOp op expr typeof (BinOp op a b) = typeofBinOp op a b typeof (Mux _ a b) = largerSizeType a b @@ -190,7 +246,6 @@ typeSignednessOverride fallback sg t = IntegerVector base _ rs -> IntegerVector base sg rs IntegerAtom base _ -> IntegerAtom base sg Net base _ rs -> Net base sg rs - Implicit _ rs -> Implicit sg rs _ -> fallback -- type of a unary operator expression @@ -262,7 +317,6 @@ binopSignedness Signed Signed = Signed -- returns the signedness of the given type, if possible typeSignedness :: Type -> Signing typeSignedness (Net _ sg _) = signednessFallback Unsigned sg -typeSignedness (Implicit sg _) = signednessFallback Unsigned sg typeSignedness (IntegerVector _ sg _) = signednessFallback Unsigned sg typeSignedness (IntegerAtom t sg ) = signednessFallback fallback sg where fallback = if t == TTime then Unsigned else Signed @@ -295,7 +349,7 @@ largerSizeOf a b = typeOfSize :: Signing -> Expr -> Type typeOfSize sg size = IntegerVector TLogic sg [(hi, RawNum 0)] - where hi = BinOp Sub size (RawNum 1) + where hi = simplify $ BinOp Sub size (RawNum 1) -- combines a type with unpacked ranges injectRanges :: Type -> [Range] -> Type @@ -321,3 +375,32 @@ replaceRange r (IntegerAtom TInteger sg) = replaceRange r t = tf (r : rs) where (tf, _ : rs) = typeRanges t + +-- checks for a cast type which already trivially matches the expression type +typeCastUnneeded :: Type -> Type -> Bool +typeCastUnneeded t1 t2 = + sg1 == sg2 && sz1 == sz2 && sz1 /= Nothing && sz2 /= Nothing + where + sg1 = typeSignedness t1 + sg2 = typeSignedness t2 + sz1 = typeSize t1 + sz2 = typeSize t2 + typeSize :: Type -> Maybe Expr + typeSize (Net _ _ rs) = Just $ dimensionsSize rs + typeSize (IntegerVector _ _ rs) = Just $ dimensionsSize rs + typeSize (t @ IntegerAtom{}) = + typeSize $ tf [(RawNum 1, RawNum 1)] + where (tf, []) = typeRanges t + typeSize _ = Nothing + +-- explicitly sizes top level numbers used in arithmetic expressions +makeExplicit :: Expr -> Expr +makeExplicit (Number (Decimal size signed values)) = + Number $ Decimal (abs size) signed values +makeExplicit (Number (Based size base signed values kinds)) = + Number $ Based (abs size) base signed values kinds +makeExplicit (BinOp op e1 e2) = + BinOp op (makeExplicit e1) (makeExplicit e2) +makeExplicit (UniOp op e) = + UniOp op $ makeExplicit e +makeExplicit other = other diff --git a/src/Language/SystemVerilog/AST/Number.hs b/src/Language/SystemVerilog/AST/Number.hs index c25f01b..d84eb03 100644 --- a/src/Language/SystemVerilog/AST/Number.hs +++ b/src/Language/SystemVerilog/AST/Number.hs @@ -168,7 +168,7 @@ baseSize Hex = 16 -- get the number of bits in a number numberBitLength :: Number -> Integer -numberBitLength UnbasedUnsized{} = 32 +numberBitLength UnbasedUnsized{} = 1 numberBitLength (Decimal size _ _) = fromIntegral $ abs size numberBitLength (Based size _ _ _ _) = fromIntegral $ diff --git a/src/Language/SystemVerilog/AST/Type.hs b/src/Language/SystemVerilog/AST/Type.hs index 4112f79..cff5667 100644 --- a/src/Language/SystemVerilog/AST/Type.hs +++ b/src/Language/SystemVerilog/AST/Type.hs @@ -121,7 +121,8 @@ nullRange t [] = t nullRange t [(RawNum 0, RawNum 0)] = t nullRange (IntegerAtom TInteger sg) rs = -- integer arrays are allowed in SystemVerilog but not in Verilog - IntegerVector TBit sg (rs ++ [(RawNum 31, RawNum 0)]) + IntegerVector TBit sg' (rs ++ [(RawNum 31, RawNum 0)]) + where sg' = if sg == Unsigned then Unsigned else Signed nullRange t rs1 = if t == t' then error $ "non-vector type " ++ show t ++ diff --git a/sv2v.cabal b/sv2v.cabal index d8d49a6..6d29888 100644 --- a/sv2v.cabal +++ b/sv2v.cabal @@ -62,6 +62,7 @@ executable sv2v Convert.AsgnOp Convert.Assertion Convert.BlockDecl + Convert.Cast Convert.DimensionQuery Convert.DuplicateGenvar Convert.EmptyArgs @@ -86,9 +87,7 @@ executable sv2v Convert.ParamType Convert.RemoveComments Convert.Scoper - Convert.SignCast Convert.Simplify - Convert.SizeCast Convert.StarPort Convert.Stream Convert.StringParam diff --git a/test/basic/cast.sv b/test/basic/cast.sv index b4c343c..68c98cd 100644 --- a/test/basic/cast.sv +++ b/test/basic/cast.sv @@ -52,4 +52,19 @@ module top; $display("%b", W'(j)); end + typedef integer T1; + typedef integer signed T2; + typedef integer unsigned T3; + initial begin + $display("T1 %0d", T1'(1'sb1)); + $display("T2 %0d", T2'(1'sb1)); + $display("T3 %0d", T3'(1'sb1)); + $display("T1 %0d", T1'(32'sd1)); + $display("T2 %0d", T2'(32'sd1)); + $display("T3 %0d", T3'(32'sd1)); + $display("T1 %0d", T1'(32'd1)); + $display("T2 %0d", T2'(32'd1)); + $display("T3 %0d", T3'(32'd1)); + end + endmodule diff --git a/test/basic/cast.v b/test/basic/cast.v index 8fb0079..dec31a2 100644 --- a/test/basic/cast.v +++ b/test/basic/cast.v @@ -61,4 +61,16 @@ module top; $display("%b", j_extended); end + initial begin + $display("T1 %0d", -1); + $display("T2 %0d", -1); + $display("T3 %0d", 32'hFFFF_FFFF); + $display("T1 %0d", 1); + $display("T2 %0d", 1); + $display("T3 %0d", 1); + $display("T1 %0d", 1); + $display("T2 %0d", 1); + $display("T3 %0d", 1); + end + endmodule diff --git a/test/basic/cast_nest.sv b/test/basic/cast_nest.sv new file mode 100644 index 0000000..6065003 --- /dev/null +++ b/test/basic/cast_nest.sv @@ -0,0 +1,15 @@ +module top; + reg signed x; + initial x = 1; + parameter ONE = 1; + initial begin + localparam A = ONE * 1; + localparam B = ONE * 2; + localparam C = ONE * 3; + localparam D = ONE * 4; + localparam E = ONE * 5; + $display("%b", 5'(4'(3'(2'(1'(x)))))); + $display("%b", E'(D'(C'(B'(A'(x)))))); + $display("%b", E'(D'(C'(B'(A'(E'(D'(C'(B'(A'(x))))))))))); + end +endmodule diff --git a/test/basic/cast_nest.v b/test/basic/cast_nest.v new file mode 100644 index 0000000..0428445 --- /dev/null +++ b/test/basic/cast_nest.v @@ -0,0 +1,12 @@ +module top; + reg signed x; + initial x = 1; + parameter ONE = 1; + initial begin : blk + reg signed [4:0] y; + y = x; + $display("%b", y); + $display("%b", y); + $display("%b", y); + end +endmodule diff --git a/test/basic/cast_nettype.sv b/test/basic/cast_nettype.sv new file mode 100644 index 0000000..00ea77f --- /dev/null +++ b/test/basic/cast_nettype.sv @@ -0,0 +1,25 @@ +`define TEST_CAST(expr, prefix, typ) \ + initial begin \ + localparam type T = type(prefix``typ); \ + logic [63:0] x; \ + T y; \ + x = T'(expr); \ + y = expr; \ + r``typ = expr; \ + tmp = r``typ; \ + $display(`"%b => prefix``typ %b %b %b`", expr, T'(expr), x, y); \ + end + +module top; + wire foo; + type(foo) bar; + initial bar = 1; + + `include "cast_nettype.vh" + + `TEST('1) + `TEST('x) + `TEST(1) + `TEST(2) + `TEST(-1) +endmodule diff --git a/test/basic/cast_nettype.v b/test/basic/cast_nettype.v new file mode 100644 index 0000000..2588f0a --- /dev/null +++ b/test/basic/cast_nettype.v @@ -0,0 +1,20 @@ +`define TEST_CAST(expr, prefix, typ) \ + initial begin \ + r``typ = expr; \ + tmp = r``typ; \ + $display(`"%b => prefix``typ %b %b %b`", expr, r``typ, tmp, r``typ); \ + end + +module top; + wire foo; + reg bar; + initial bar = 1; + + `include "cast_nettype.vh" + + `TEST(1'sb1) + `TEST(1'sbx) + `TEST(1) + `TEST(2) + `TEST(-1) +endmodule diff --git a/test/basic/cast_nettype.vh b/test/basic/cast_nettype.vh new file mode 100644 index 0000000..d8c5bea --- /dev/null +++ b/test/basic/cast_nettype.vh @@ -0,0 +1,31 @@ +`define TEST(expr) \ + `TEST_CAST(expr, w, t1) \ + `TEST_CAST(expr, w, t2) \ + `TEST_CAST(expr, w, t3) \ + `TEST_CAST(expr, w, s1) \ + `TEST_CAST(expr, w, s2) \ + `TEST_CAST(expr, w, s3) \ + `TEST_CAST(expr, r, t1) \ + `TEST_CAST(expr, r, t2) \ + `TEST_CAST(expr, r, t3) \ + `TEST_CAST(expr, r, s1) \ + `TEST_CAST(expr, r, s2) \ + `TEST_CAST(expr, r, s3) + +wire wt1; +wire signed wt2; +wire unsigned wt3; + +wire [1:0] ws1; +wire signed [1:0] ws2; +wire unsigned [1:0] ws3; + +reg rt1; +reg signed rt2; +reg unsigned rt3; + +reg [1:0] rs1; +reg signed [1:0] rs2; +reg unsigned [1:0] rs3; + +reg [63:0] tmp; diff --git a/test/basic/cast_procedure.sv b/test/basic/cast_procedure.sv new file mode 100644 index 0000000..99e8d16 --- /dev/null +++ b/test/basic/cast_procedure.sv @@ -0,0 +1,31 @@ +`define EXPR $unsigned(WIDTH'(ONES)) +`define TEST(size) \ + localparam WIDTH = ONE * size; \ + localparam x = $unsigned(WIDTH'(ONES)); \ + integer y, z; \ + localparam type T = logic [WIDTH-1:0]; \ + y = T'(ones); \ + z = $unsigned(WIDTH'(ones)); \ + $display(`"size: %b %b %b %b`", x, y, z, $unsigned(WIDTH'(ones))); + +module top; + parameter ONE = 1; + parameter signed [0:0] ONES = 1'sb1; + logic signed [0:0] ones; + initial ones = 1'sb1; + task t; + `TEST(6) + endtask + function f; + input integer unused; + `TEST(7) + endfunction + initial t; + initial begin + integer a; + a = f(0); + end + initial begin + `TEST(8) + end +endmodule diff --git a/test/basic/cast_procedure.v b/test/basic/cast_procedure.v new file mode 100644 index 0000000..53c16b3 --- /dev/null +++ b/test/basic/cast_procedure.v @@ -0,0 +1,32 @@ +`define TEST(size) \ + localparam WIDTH = ONE * size; \ + localparam [WIDTH-1:0] short = ONES; \ + integer long; \ + long = short; \ + $display(`"size: %b %b %b %b`", short, long, long, short); + +module top; + parameter ONE = 1; + parameter signed [0:0] ONES = 1'sb1; + reg signed [0:0] ones; + initial ones = 1'sb1; + task t; + begin : blk1 + `TEST(6) + end + endtask + function f; + input integer unused; + begin : blk2 + `TEST(7) + end + endfunction + initial t; + initial begin : blk3 + integer a; + a = f(0); + end + initial begin : blk4 + `TEST(8) + end +endmodule diff --git a/test/basic/cast_struct_nested.sv b/test/basic/cast_struct_nested.sv new file mode 100644 index 0000000..6ac7fb5 --- /dev/null +++ b/test/basic/cast_struct_nested.sv @@ -0,0 +1,14 @@ +module top; + typedef struct packed { + logic x, y; + } S; + typedef struct packed { + S x, y; + } T; + T t; + initial begin + t = 1'sb1; + $display("%b", t); + $display("%b", 5'(t)); + end +endmodule diff --git a/test/basic/cast_struct_nested.v b/test/basic/cast_struct_nested.v new file mode 100644 index 0000000..ef8132e --- /dev/null +++ b/test/basic/cast_struct_nested.v @@ -0,0 +1,10 @@ +module top; + reg [3:0] t; + initial begin : blk + reg [4:0] x; + t = 1'sb1; + x = t; + $display("%b", t); + $display("%b", x); + end +endmodule diff --git a/test/basic/duplicate_cast.v b/test/basic/duplicate_cast.v index 7b6ccaf..7ee5996 100644 --- a/test/basic/duplicate_cast.v +++ b/test/basic/duplicate_cast.v @@ -1,11 +1,7 @@ module top; wire b; wire [1:0] a; - function automatic val; - input inp; - val = inp; - endfunction - assign b = val(1); - assign a = {2 {val(1)}}; + assign b = 1'b1; + assign a = {2 {1'b1}}; initial #1 $display("%b %b", a, b); endmodule diff --git a/test/basic/integer_array.sv b/test/basic/integer_array.sv index 5962c64..9ceef06 100644 --- a/test/basic/integer_array.sv +++ b/test/basic/integer_array.sv @@ -1,4 +1,5 @@ module top; + parameter ONE = 1; localparam integer A [4] = { 1, 2, 3, 4 }; localparam byte B [4] = { 1, 2, 3, 4 }; localparam bit C [4] = { 1, 2, 3, 4 }; @@ -8,6 +9,12 @@ module top; localparam integer G [4] = '{ 1, 2, 3, 4 }; localparam byte H [4] = '{ 1, 2, 3, 4 }; localparam bit I [4] = '{ 1, 2, 3, 4 }; + localparam integer J [4] = { ONE * '0, ONE * '1, 5 * ONE, ONE * 6 }; + localparam byte K [4] = { ONE * '0, ONE * '1, 5 * ONE, ONE * 6 }; + localparam bit L [4] = { '0, ONE * '1, 5 * ONE, ONE * 6 }; + localparam integer unsigned M [4] = { ONE * '0, ONE * '1, 5 * ONE, ONE * 6 }; + localparam byte unsigned N [4] = { ONE * '0, ONE * '1, 5 * ONE, ONE * 6 }; + localparam bit unsigned O [4] = { '0, ONE * '1, 5 * ONE, ONE * 6 }; initial begin `define PRINT(X) \ $display("%b %2d %2d", {X[0], X[1], X[2], X[3]}, $bits(X), $bits(X[0])); @@ -20,6 +27,12 @@ module top; `PRINT(G); `PRINT(H); `PRINT(I); + `PRINT(J); + `PRINT(K); + `PRINT(L); + `PRINT(M); + `PRINT(N); + `PRINT(O); end localparam [1:0][0:1] P = '{'{default:'d1}, '{default:'d2}}; diff --git a/test/basic/integer_array.v b/test/basic/integer_array.v index 119d9f3..efd98fd 100644 --- a/test/basic/integer_array.v +++ b/test/basic/integer_array.v @@ -8,6 +8,12 @@ module top; localparam [0:127] G = { 32'h1, 32'h2, 32'h3, 32'h4 }; localparam [0:31] H = { 8'h1, 8'h2, 8'h3, 8'h4 }; localparam [0:3] I = { 1'h1, 1'h0, 1'h1, 1'h0 }; + localparam [0:127] J = { 32'h0, 32'hFFFFFFFF, 32'h5, 32'h6 }; + localparam [0:31] K = { 8'h0, 8'hFF, 8'h5, 8'h6 }; + localparam [0:3] L = { 1'h0, 1'h1, 1'h1, 1'h0 }; + localparam [0:127] M = { 32'h0, 32'hFFFFFFFF, 32'h5, 32'h6 }; + localparam [0:31] N = { 8'h0, 8'hFF, 8'h5, 8'h6 }; + localparam [0:3] O = { 1'h0, 1'h1, 1'h1, 1'h0 }; initial begin $display("%b %2d %2d", A, $bits(A), 32); $display("%b %2d %2d", B, $bits(B), 8); @@ -18,6 +24,12 @@ module top; $display("%b %2d %2d", G, $bits(G), 32); $display("%b %2d %2d", H, $bits(H), 8); $display("%b %2d %2d", I, $bits(I), 1); + $display("%b %2d %2d", J, $bits(J), 32); + $display("%b %2d %2d", K, $bits(K), 8); + $display("%b %2d %2d", L, $bits(L), 1); + $display("%b %2d %2d", M, $bits(M), 32); + $display("%b %2d %2d", N, $bits(N), 8); + $display("%b %2d %2d", O, $bits(O), 1); end localparam [3:0] P = 4'b1100; diff --git a/test/basic/size_cast.sv b/test/basic/size_cast.sv index df2f656..f3aa9de 100644 --- a/test/basic/size_cast.sv +++ b/test/basic/size_cast.sv @@ -3,6 +3,8 @@ module top; logic [2:0] test; logic [3:0] foo; logic [3:0] bar; + integer x; + reg [7:0] y; initial begin test = BW'(0); @@ -11,5 +13,15 @@ module top; $display(foo); bar = $bits(bar)'('1); $display(bar); + x = 1'('1); $display("%b %0d", x, x); + y = 1'('1); $display("%b %0d", y, y); + x = 2'('0); $display("%b %0d", x, x); + y = 2'('0); $display("%b %0d", y, y); + x = 2'('1); $display("%b %0d", x, x); + y = 2'('1); $display("%b %0d", y, y); + x = 2'('x); $display("%b %0d", x, x); + y = 2'('x); $display("%b %0d", y, y); + x = 2'('z); $display("%b %0d", x, x); + y = 2'('z); $display("%b %0d", y, y); end endmodule diff --git a/test/basic/size_cast.v b/test/basic/size_cast.v index 0b61987..7d3b4bb 100644 --- a/test/basic/size_cast.v +++ b/test/basic/size_cast.v @@ -2,6 +2,8 @@ module top; reg [2:0] test; reg [3:0] foo; reg [3:0] bar; + integer x; + reg [7:0] y; initial begin test = 0; @@ -10,5 +12,15 @@ module top; $display(foo); bar = 4'b1111; $display(bar); + x = 1'b1; $display("%b %0d", x, x); + y = 1'b1; $display("%b %0d", y, y); + x = 2'b00; $display("%b %0d", x, x); + y = 2'b00; $display("%b %0d", y, y); + x = 2'b11; $display("%b %0d", x, x); + y = 2'b11; $display("%b %0d", y, y); + x = 2'bxx; $display("%b %0d", x, x); + y = 2'bxx; $display("%b %0d", y, y); + x = 2'bzz; $display("%b %0d", x, x); + y = 2'bzz; $display("%b %0d", y, y); end endmodule diff --git a/test/basic/typeof_signed.sv b/test/basic/typeof_signed.sv index 8701d5b..bebe099 100644 --- a/test/basic/typeof_signed.sv +++ b/test/basic/typeof_signed.sv @@ -192,4 +192,8 @@ module top; `ASSERT_UNSIGNED(arr[5:0]) `ASSERT_UNSIGNED(arr[1+:2]) `ASSERT_UNSIGNED(arr[1-:2]) + `ASSERT_UNSIGNED(integer_signed[0]) + `ASSERT_UNSIGNED(integer_signed[1]) + `ASSERT_UNSIGNED(integer_unsigned[0]) + `ASSERT_UNSIGNED(integer_unsigned[1]) endmodule