Commit dd1a9efb by Zachary Snow

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
parent c656cbb9
...@@ -13,6 +13,7 @@ import qualified Convert.AlwaysKW ...@@ -13,6 +13,7 @@ import qualified Convert.AlwaysKW
import qualified Convert.AsgnOp import qualified Convert.AsgnOp
import qualified Convert.Assertion import qualified Convert.Assertion
import qualified Convert.BlockDecl import qualified Convert.BlockDecl
import qualified Convert.Cast
import qualified Convert.DimensionQuery import qualified Convert.DimensionQuery
import qualified Convert.DuplicateGenvar import qualified Convert.DuplicateGenvar
import qualified Convert.EmptyArgs import qualified Convert.EmptyArgs
...@@ -35,9 +36,7 @@ import qualified Convert.Package ...@@ -35,9 +36,7 @@ import qualified Convert.Package
import qualified Convert.ParamNoDefault import qualified Convert.ParamNoDefault
import qualified Convert.ParamType import qualified Convert.ParamType
import qualified Convert.RemoveComments import qualified Convert.RemoveComments
import qualified Convert.SignCast
import qualified Convert.Simplify import qualified Convert.Simplify
import qualified Convert.SizeCast
import qualified Convert.StarPort import qualified Convert.StarPort
import qualified Convert.Stream import qualified Convert.Stream
import qualified Convert.StringParam import qualified Convert.StringParam
...@@ -70,11 +69,11 @@ phases excludes = ...@@ -70,11 +69,11 @@ phases excludes =
, Convert.KWArgs.convert , Convert.KWArgs.convert
, Convert.LogOp.convert , Convert.LogOp.convert
, Convert.MultiplePacked.convert , Convert.MultiplePacked.convert
, Convert.UnbasedUnsized.convert
, Convert.Cast.convert
, Convert.TypeOf.convert , Convert.TypeOf.convert
, Convert.DimensionQuery.convert , Convert.DimensionQuery.convert
, Convert.ParamType.convert , Convert.ParamType.convert
, Convert.UnbasedUnsized.convert
, Convert.SizeCast.convert
, Convert.Simplify.convert , Convert.Simplify.convert
, Convert.Stream.convert , Convert.Stream.convert
, Convert.Struct.convert , Convert.Struct.convert
...@@ -83,7 +82,6 @@ phases excludes = ...@@ -83,7 +82,6 @@ phases excludes =
, Convert.Unique.convert , Convert.Unique.convert
, Convert.UnpackedArray.convert , Convert.UnpackedArray.convert
, Convert.Unsigned.convert , Convert.Unsigned.convert
, Convert.SignCast.convert
, Convert.Wildcard.convert , Convert.Wildcard.convert
, Convert.Enum.convert , Convert.Enum.convert
, Convert.ForDecl.convert , Convert.ForDecl.convert
......
{-# LANGUAGE PatternSynonyms #-}
{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
-
- 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
...@@ -32,6 +32,7 @@ module Convert.Scoper ...@@ -32,6 +32,7 @@ module Convert.Scoper
, partScoperT , partScoperT
, insertElem , insertElem
, injectItem , injectItem
, injectDecl
, lookupElem , lookupElem
, lookupElemM , lookupElemM
, Access(..) , Access(..)
...@@ -83,7 +84,8 @@ data Scopes a = Scopes ...@@ -83,7 +84,8 @@ data Scopes a = Scopes
{ sCurrent :: [Tier] { sCurrent :: [Tier]
, sMapping :: Mapping a , sMapping :: Mapping a
, sProcedure :: Bool , sProcedure :: Bool
, sInjected :: [ModuleItem] , sInjectedItems :: [ModuleItem]
, sInjectedDecls :: [Decl]
} deriving Show } deriving Show
extractMapping :: Scopes a -> Map.Map Identifier a extractMapping :: Scopes a -> Map.Map Identifier a
...@@ -176,13 +178,25 @@ insertElem key element = do ...@@ -176,13 +178,25 @@ insertElem key element = do
injectItem :: Monad m => ModuleItem -> ScoperT a m () injectItem :: Monad m => ModuleItem -> ScoperT a m ()
injectItem item = injectItem item =
modify' $ \s -> s { sInjected = add $ sInjected s } modify' $ \s -> s { sInjectedItems = item : sInjectedItems s }
where
add :: [ModuleItem] -> [ModuleItem] injectDecl :: Monad m => Decl -> ScoperT a m ()
add items = injectDecl decl =
if elem item items modify' $ \s -> s { sInjectedDecls = decl : sInjectedDecls s }
then items
else items ++ [item] 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 type Replacements = Map.Map Identifier Expr
...@@ -305,7 +319,7 @@ runScoperT declMapper moduleItemMapper genItemMapper stmtMapper topName items = ...@@ -305,7 +319,7 @@ runScoperT declMapper moduleItemMapper genItemMapper stmtMapper topName items =
items' <- mapM wrappedModuleItemMapper items items' <- mapM wrappedModuleItemMapper items
exitScope topName "" exitScope topName ""
return items' return items'
initialState = Scopes [] Map.empty False [] initialState = Scopes [] Map.empty False [] []
wrappedModuleItemMapper = scopeModuleItemT wrappedModuleItemMapper = scopeModuleItemT
declMapper moduleItemMapper genItemMapper stmtMapper declMapper moduleItemMapper genItemMapper stmtMapper
...@@ -324,13 +338,28 @@ scopeModuleItemT declMapper moduleItemMapper genItemMapper stmtMapper = ...@@ -324,13 +338,28 @@ scopeModuleItemT declMapper moduleItemMapper genItemMapper stmtMapper =
fullStmtMapper :: Stmt -> ScoperT a m Stmt fullStmtMapper :: Stmt -> ScoperT a m Stmt
fullStmtMapper (Block kw name decls stmts) = do fullStmtMapper (Block kw name decls stmts) = do
enterScope name "" enterScope name ""
decls' <- mapM declMapper decls decls' <- fmap concat $ mapM declMapper' decls
stmts' <- mapM fullStmtMapper stmts stmts' <- mapM fullStmtMapper stmts
exitScope name "" exitScope name ""
return $ Block kw name decls' stmts' return $ Block kw name decls' stmts'
-- TODO: Do we need to support the various procedural loops? -- TODO: Do we need to support the various procedural loops?
fullStmtMapper stmt = fullStmtMapper stmt = do
stmtMapper stmt >>= traverseSinglyNestedStmtsM fullStmtMapper 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 :: [Decl] -> ScoperT a m [Decl]
mapTFDecls = mapTFDecls' 0 mapTFDecls = mapTFDecls' 0
...@@ -340,14 +369,14 @@ scopeModuleItemT declMapper moduleItemMapper genItemMapper stmtMapper = ...@@ -340,14 +369,14 @@ scopeModuleItemT declMapper moduleItemMapper genItemMapper stmtMapper =
mapTFDecls' idx (decl : decls) = mapTFDecls' idx (decl : decls) =
case argIdxDecl decl of case argIdxDecl decl of
Nothing -> do Nothing -> do
decl' <- declMapper decl decl' <- declMapper' decl
decls' <- mapTFDecls' idx decls decls' <- mapTFDecls' idx decls
return $ decl' : decls' return $ decl' ++ decls'
Just declFunc -> do Just declFunc -> do
_ <- declMapper $ declFunc idx _ <- declMapper $ declFunc idx
decl' <- declMapper decl decl' <- declMapper' decl
decls' <- mapTFDecls' (idx + 1) decls decls' <- mapTFDecls' (idx + 1) decls
return $ decl' : decls' return $ decl' ++ decls'
argIdxDecl :: Decl -> Maybe (Int -> Decl) argIdxDecl :: Decl -> Maybe (Int -> Decl)
argIdxDecl (Variable d t _ a e) = argIdxDecl (Variable d t _ a e) =
...@@ -369,11 +398,10 @@ scopeModuleItemT declMapper moduleItemMapper genItemMapper stmtMapper = ...@@ -369,11 +398,10 @@ scopeModuleItemT declMapper moduleItemMapper genItemMapper stmtMapper =
wrappedModuleItemMapper :: ModuleItem -> ScoperT a m ModuleItem wrappedModuleItemMapper :: ModuleItem -> ScoperT a m ModuleItem
wrappedModuleItemMapper item = do wrappedModuleItemMapper item = do
item' <- fullModuleItemMapper item item' <- fullModuleItemMapper item
injected <- gets sInjected injected <- consumeInjectedItems
if null injected if null injected
then return item' then return item'
else do else do
modify' $ \s -> s { sInjected = [] }
injected' <- mapM fullModuleItemMapper injected injected' <- mapM fullModuleItemMapper injected
return $ Generate $ map GenModuleItem $ injected' ++ [item'] return $ Generate $ map GenModuleItem $ injected' ++ [item']
fullModuleItemMapper :: ModuleItem -> ScoperT a m ModuleItem fullModuleItemMapper :: ModuleItem -> ScoperT a m ModuleItem
...@@ -423,11 +451,10 @@ scopeModuleItemT declMapper moduleItemMapper genItemMapper stmtMapper = ...@@ -423,11 +451,10 @@ scopeModuleItemT declMapper moduleItemMapper genItemMapper stmtMapper =
fullGenItemMapper :: GenItem -> ScoperT a m GenItem fullGenItemMapper :: GenItem -> ScoperT a m GenItem
fullGenItemMapper genItem = do fullGenItemMapper genItem = do
genItem' <- genItemMapper genItem genItem' <- genItemMapper genItem
injected <- gets sInjected injected <- consumeInjectedItems
if null injected if null injected
then scopeGenItemMapper genItem' then scopeGenItemMapper genItem'
else do else do
modify' $ \s -> s { sInjected = [] }
injected' <- mapM fullModuleItemMapper injected injected' <- mapM fullModuleItemMapper injected
genItem'' <- scopeGenItemMapper genItem' genItem'' <- scopeGenItemMapper genItem'
let genItems = map GenModuleItem injected' ++ [genItem''] let genItems = map GenModuleItem injected' ++ [genItem'']
......
{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
-
- 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
{-# LANGUAGE PatternSynonyms #-}
{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
-
- 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
...@@ -281,7 +281,9 @@ convertExpr (t @ IntegerVector{}) (Concat exprs) = ...@@ -281,7 +281,9 @@ convertExpr (t @ IntegerVector{}) (Concat exprs) =
t' = dropInnerTypeRange t t' = dropInnerTypeRange t
isUnsizedNumber :: Expr -> Bool isUnsizedNumber :: Expr -> Bool
isUnsizedNumber (Number n) = not $ numberIsSized n 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 isUnsizedNumber _ = False
-- TODO: This is really a conversion for using default patterns to -- TODO: This is really a conversion for using default patterns to
......
...@@ -460,12 +460,10 @@ traverseSinglyNestedExprsM exprMapper = em ...@@ -460,12 +460,10 @@ traverseSinglyNestedExprsM exprMapper = em
e2' <- exprMapper e2 e2' <- exprMapper e2
e3' <- exprMapper e3 e3' <- exprMapper e3
return $ Mux e1' e2' e3' return $ Mux e1' e2' e3'
em (Cast (Left t) e) = em (Cast tore e) = do
exprMapper e >>= return . Cast (Left t) tore' <- typeOrExprMapper tore
em (Cast (Right e1) e2) = do e' <- exprMapper e
e1' <- exprMapper e1 return $ Cast tore' e'
e2' <- exprMapper e2
return $ Cast (Right e1') e2'
em (DimsFn f tore) = em (DimsFn f tore) =
typeOrExprMapper tore >>= return . DimsFn f typeOrExprMapper tore >>= return . DimsFn f
em (DimFn f tore e) = do em (DimFn f tore e) = do
...@@ -834,8 +832,8 @@ traverseExprTypesM mapper = exprMapper ...@@ -834,8 +832,8 @@ traverseExprTypesM mapper = exprMapper
typeOrExprMapper (Right e) = return $ Right e typeOrExprMapper (Right e) = return $ Right e
typeOrExprMapper (Left t) = typeOrExprMapper (Left t) =
mapper t >>= return . Left mapper t >>= return . Left
exprMapper (Cast (Left t) e) = exprMapper (Cast tore e) =
mapper t >>= \t' -> return $ Cast (Left t') e typeOrExprMapper tore >>= return . flip Cast e
exprMapper (DimsFn f tore) = exprMapper (DimsFn f tore) =
typeOrExprMapper tore >>= return . DimsFn f typeOrExprMapper tore >>= return . DimsFn f
exprMapper (DimFn f tore e) = do exprMapper (DimFn f tore e) = do
......
...@@ -11,6 +11,13 @@ ...@@ -11,6 +11,13 @@
- concatenation conversions, defer the resolution of type information to this - concatenation conversions, defer the resolution of type information to this
- conversion pass by producing nodes with the `type` operator during - conversion pass by producing nodes with the `type` operator during
- elaboration. - 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 module Convert.TypeOf (convert) where
...@@ -18,7 +25,7 @@ module Convert.TypeOf (convert) where ...@@ -18,7 +25,7 @@ module Convert.TypeOf (convert) where
import Data.Tuple (swap) import Data.Tuple (swap)
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import Convert.ExprUtils (endianCondRange, simplify) import Convert.ExprUtils (dimensionsSize, endianCondRange, simplify)
import Convert.Scoper import Convert.Scoper
import Convert.Traverse import Convert.Traverse
import Language.SystemVerilog.AST import Language.SystemVerilog.AST
...@@ -34,8 +41,8 @@ pattern UnitType = IntegerVector TLogic Unspecified [] ...@@ -34,8 +41,8 @@ pattern UnitType = IntegerVector TLogic Unspecified []
-- insert the given declaration into the scope, and convert an TypeOfs within -- insert the given declaration into the scope, and convert an TypeOfs within
traverseDeclM :: Decl -> Scoper Type Decl traverseDeclM :: Decl -> Scoper Type Decl
traverseDeclM decl = do traverseDeclM decl = do
item <- traverseModuleItemM (MIPackageItem $ Decl decl) decl' <- traverseDeclExprsM traverseExprM decl
let MIPackageItem (Decl decl') = item >>= traverseDeclTypesM traverseTypeM
case decl' of case decl' of
Variable _ (Implicit sg rs) ident a _ -> Variable _ (Implicit sg rs) ident a _ ->
-- implicit types, which are commonly found in function return -- implicit types, which are commonly found in function return
...@@ -66,7 +73,8 @@ traverseModuleItemM (Genvar x) = do ...@@ -66,7 +73,8 @@ traverseModuleItemM (Genvar x) = do
insertElem x $ IntegerAtom TInteger Unspecified insertElem x $ IntegerAtom TInteger Unspecified
return $ Genvar x return $ Genvar x
traverseModuleItemM item = traverseModuleItemM item =
traverseTypesM (traverseNestedTypesM traverseTypeM) item traverseNodesM traverseExprM return traverseTypeM traverseLHSM return item
where traverseLHSM = traverseLHSExprsM traverseExprM
-- convert TypeOf in a GenItem -- convert TypeOf in a GenItem
traverseGenItemM :: GenItem -> Scoper Type GenItem traverseGenItemM :: GenItem -> Scoper Type GenItem
...@@ -76,14 +84,57 @@ traverseGenItemM = traverseGenItemExprsM traverseExprM ...@@ -76,14 +84,57 @@ traverseGenItemM = traverseGenItemExprsM traverseExprM
traverseStmtM :: Stmt -> Scoper Type Stmt traverseStmtM :: Stmt -> Scoper Type Stmt
traverseStmtM = traverseStmtExprsM traverseExprM traverseStmtM = traverseStmtExprsM traverseExprM
-- convert TypeOf in a Expr -- convert TypeOf in an Expr
traverseExprM :: Expr -> Scoper Type Expr traverseExprM :: Expr -> Scoper Type Expr
traverseExprM = traverseNestedExprsM $ traverseExprTypesM $ traverseExprM (Cast (Left (Implicit sg [])) expr) =
traverseNestedTypesM traverseTypeM -- `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 :: Type -> Scoper Type Type
traverseTypeM (TypeOf expr) = typeof expr traverseTypeM (TypeOf expr) =
traverseTypeM other = return other traverseExprM expr >>= typeof
traverseTypeM other =
traverseTypeExprsM traverseExprM other
>>= traverseSinglyNestedTypesM traverseTypeM
-- attempts to find the given (potentially hierarchical or generate-scoped) -- attempts to find the given (potentially hierarchical or generate-scoped)
-- expression in the available scope information -- expression in the available scope information
...@@ -92,11 +143,15 @@ lookupTypeOf expr = do ...@@ -92,11 +143,15 @@ lookupTypeOf expr = do
details <- lookupElemM expr details <- lookupElemM expr
case details of case details of
Nothing -> return $ TypeOf expr Nothing -> return $ TypeOf expr
Just (_, replacements, typ) -> Just (_, replacements, typ) -> do
let typ' = toVarType typ
return $ if Map.null replacements return $ if Map.null replacements
then typ then typ'
else rewriteType replacements typ else rewriteType replacements typ'
where where
toVarType :: Type -> Type
toVarType (Net _ sg rs) = IntegerVector TLogic sg rs
toVarType other = other
rewriteType :: Replacements -> Type -> Type rewriteType :: Replacements -> Type -> Type
rewriteType replacements = traverseNestedTypes $ traverseTypeExprs $ rewriteType replacements = traverseNestedTypes $ traverseTypeExprs $
traverseNestedExprs (replace replacements) traverseNestedExprs (replace replacements)
...@@ -155,6 +210,7 @@ typeof (orig @ (Dot e x)) = do ...@@ -155,6 +210,7 @@ typeof (orig @ (Dot e x)) = do
case lookup x $ map swap fields of case lookup x $ map swap fields of
Just typ -> typ Just typ -> typ
Nothing -> TypeOf orig Nothing -> TypeOf orig
typeof (Cast (Left t) _) = traverseTypeM t
typeof (UniOp op expr) = typeofUniOp op expr typeof (UniOp op expr) = typeofUniOp op expr
typeof (BinOp op a b) = typeofBinOp op a b typeof (BinOp op a b) = typeofBinOp op a b
typeof (Mux _ a b) = largerSizeType a b typeof (Mux _ a b) = largerSizeType a b
...@@ -190,7 +246,6 @@ typeSignednessOverride fallback sg t = ...@@ -190,7 +246,6 @@ typeSignednessOverride fallback sg t =
IntegerVector base _ rs -> IntegerVector base sg rs IntegerVector base _ rs -> IntegerVector base sg rs
IntegerAtom base _ -> IntegerAtom base sg IntegerAtom base _ -> IntegerAtom base sg
Net base _ rs -> Net base sg rs Net base _ rs -> Net base sg rs
Implicit _ rs -> Implicit sg rs
_ -> fallback _ -> fallback
-- type of a unary operator expression -- type of a unary operator expression
...@@ -262,7 +317,6 @@ binopSignedness Signed Signed = Signed ...@@ -262,7 +317,6 @@ binopSignedness Signed Signed = Signed
-- returns the signedness of the given type, if possible -- returns the signedness of the given type, if possible
typeSignedness :: Type -> Signing typeSignedness :: Type -> Signing
typeSignedness (Net _ sg _) = signednessFallback Unsigned sg typeSignedness (Net _ sg _) = signednessFallback Unsigned sg
typeSignedness (Implicit sg _) = signednessFallback Unsigned sg
typeSignedness (IntegerVector _ sg _) = signednessFallback Unsigned sg typeSignedness (IntegerVector _ sg _) = signednessFallback Unsigned sg
typeSignedness (IntegerAtom t sg ) = signednessFallback fallback sg typeSignedness (IntegerAtom t sg ) = signednessFallback fallback sg
where fallback = if t == TTime then Unsigned else Signed where fallback = if t == TTime then Unsigned else Signed
...@@ -295,7 +349,7 @@ largerSizeOf a b = ...@@ -295,7 +349,7 @@ largerSizeOf a b =
typeOfSize :: Signing -> Expr -> Type typeOfSize :: Signing -> Expr -> Type
typeOfSize sg size = typeOfSize sg size =
IntegerVector TLogic sg [(hi, RawNum 0)] 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 -- combines a type with unpacked ranges
injectRanges :: Type -> [Range] -> Type injectRanges :: Type -> [Range] -> Type
...@@ -321,3 +375,32 @@ replaceRange r (IntegerAtom TInteger sg) = ...@@ -321,3 +375,32 @@ replaceRange r (IntegerAtom TInteger sg) =
replaceRange r t = replaceRange r t =
tf (r : rs) tf (r : rs)
where (tf, _ : rs) = typeRanges t 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
...@@ -168,7 +168,7 @@ baseSize Hex = 16 ...@@ -168,7 +168,7 @@ baseSize Hex = 16
-- get the number of bits in a number -- get the number of bits in a number
numberBitLength :: Number -> Integer numberBitLength :: Number -> Integer
numberBitLength UnbasedUnsized{} = 32 numberBitLength UnbasedUnsized{} = 1
numberBitLength (Decimal size _ _) = fromIntegral $ abs size numberBitLength (Decimal size _ _) = fromIntegral $ abs size
numberBitLength (Based size _ _ _ _) = numberBitLength (Based size _ _ _ _) =
fromIntegral $ fromIntegral $
......
...@@ -121,7 +121,8 @@ nullRange t [] = t ...@@ -121,7 +121,8 @@ nullRange t [] = t
nullRange t [(RawNum 0, RawNum 0)] = t nullRange t [(RawNum 0, RawNum 0)] = t
nullRange (IntegerAtom TInteger sg) rs = nullRange (IntegerAtom TInteger sg) rs =
-- integer arrays are allowed in SystemVerilog but not in Verilog -- 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 = nullRange t rs1 =
if t == t' if t == t'
then error $ "non-vector type " ++ show t ++ then error $ "non-vector type " ++ show t ++
......
...@@ -62,6 +62,7 @@ executable sv2v ...@@ -62,6 +62,7 @@ executable sv2v
Convert.AsgnOp Convert.AsgnOp
Convert.Assertion Convert.Assertion
Convert.BlockDecl Convert.BlockDecl
Convert.Cast
Convert.DimensionQuery Convert.DimensionQuery
Convert.DuplicateGenvar Convert.DuplicateGenvar
Convert.EmptyArgs Convert.EmptyArgs
...@@ -86,9 +87,7 @@ executable sv2v ...@@ -86,9 +87,7 @@ executable sv2v
Convert.ParamType Convert.ParamType
Convert.RemoveComments Convert.RemoveComments
Convert.Scoper Convert.Scoper
Convert.SignCast
Convert.Simplify Convert.Simplify
Convert.SizeCast
Convert.StarPort Convert.StarPort
Convert.Stream Convert.Stream
Convert.StringParam Convert.StringParam
......
...@@ -52,4 +52,19 @@ module top; ...@@ -52,4 +52,19 @@ module top;
$display("%b", W'(j)); $display("%b", W'(j));
end 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 endmodule
...@@ -61,4 +61,16 @@ module top; ...@@ -61,4 +61,16 @@ module top;
$display("%b", j_extended); $display("%b", j_extended);
end 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 endmodule
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
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
`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
`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
`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;
`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
`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
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
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
module top; module top;
wire b; wire b;
wire [1:0] a; wire [1:0] a;
function automatic val; assign b = 1'b1;
input inp; assign a = {2 {1'b1}};
val = inp;
endfunction
assign b = val(1);
assign a = {2 {val(1)}};
initial #1 $display("%b %b", a, b); initial #1 $display("%b %b", a, b);
endmodule endmodule
module top; module top;
parameter ONE = 1;
localparam integer A [4] = { 1, 2, 3, 4 }; localparam integer A [4] = { 1, 2, 3, 4 };
localparam byte B [4] = { 1, 2, 3, 4 }; localparam byte B [4] = { 1, 2, 3, 4 };
localparam bit C [4] = { 1, 2, 3, 4 }; localparam bit C [4] = { 1, 2, 3, 4 };
...@@ -8,6 +9,12 @@ module top; ...@@ -8,6 +9,12 @@ module top;
localparam integer G [4] = '{ 1, 2, 3, 4 }; localparam integer G [4] = '{ 1, 2, 3, 4 };
localparam byte H [4] = '{ 1, 2, 3, 4 }; localparam byte H [4] = '{ 1, 2, 3, 4 };
localparam bit I [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 initial begin
`define PRINT(X) \ `define PRINT(X) \
$display("%b %2d %2d", {X[0], X[1], X[2], X[3]}, $bits(X), $bits(X[0])); $display("%b %2d %2d", {X[0], X[1], X[2], X[3]}, $bits(X), $bits(X[0]));
...@@ -20,6 +27,12 @@ module top; ...@@ -20,6 +27,12 @@ module top;
`PRINT(G); `PRINT(G);
`PRINT(H); `PRINT(H);
`PRINT(I); `PRINT(I);
`PRINT(J);
`PRINT(K);
`PRINT(L);
`PRINT(M);
`PRINT(N);
`PRINT(O);
end end
localparam [1:0][0:1] P = '{'{default:'d1}, '{default:'d2}}; localparam [1:0][0:1] P = '{'{default:'d1}, '{default:'d2}};
......
...@@ -8,6 +8,12 @@ module top; ...@@ -8,6 +8,12 @@ module top;
localparam [0:127] G = { 32'h1, 32'h2, 32'h3, 32'h4 }; 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:31] H = { 8'h1, 8'h2, 8'h3, 8'h4 };
localparam [0:3] I = { 1'h1, 1'h0, 1'h1, 1'h0 }; 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 initial begin
$display("%b %2d %2d", A, $bits(A), 32); $display("%b %2d %2d", A, $bits(A), 32);
$display("%b %2d %2d", B, $bits(B), 8); $display("%b %2d %2d", B, $bits(B), 8);
...@@ -18,6 +24,12 @@ module top; ...@@ -18,6 +24,12 @@ module top;
$display("%b %2d %2d", G, $bits(G), 32); $display("%b %2d %2d", G, $bits(G), 32);
$display("%b %2d %2d", H, $bits(H), 8); $display("%b %2d %2d", H, $bits(H), 8);
$display("%b %2d %2d", I, $bits(I), 1); $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 end
localparam [3:0] P = 4'b1100; localparam [3:0] P = 4'b1100;
......
...@@ -3,6 +3,8 @@ module top; ...@@ -3,6 +3,8 @@ module top;
logic [2:0] test; logic [2:0] test;
logic [3:0] foo; logic [3:0] foo;
logic [3:0] bar; logic [3:0] bar;
integer x;
reg [7:0] y;
initial begin initial begin
test = BW'(0); test = BW'(0);
...@@ -11,5 +13,15 @@ module top; ...@@ -11,5 +13,15 @@ module top;
$display(foo); $display(foo);
bar = $bits(bar)'('1); bar = $bits(bar)'('1);
$display(bar); $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 end
endmodule endmodule
...@@ -2,6 +2,8 @@ module top; ...@@ -2,6 +2,8 @@ module top;
reg [2:0] test; reg [2:0] test;
reg [3:0] foo; reg [3:0] foo;
reg [3:0] bar; reg [3:0] bar;
integer x;
reg [7:0] y;
initial begin initial begin
test = 0; test = 0;
...@@ -10,5 +12,15 @@ module top; ...@@ -10,5 +12,15 @@ module top;
$display(foo); $display(foo);
bar = 4'b1111; bar = 4'b1111;
$display(bar); $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 end
endmodule endmodule
...@@ -192,4 +192,8 @@ module top; ...@@ -192,4 +192,8 @@ module top;
`ASSERT_UNSIGNED(arr[5:0]) `ASSERT_UNSIGNED(arr[5:0])
`ASSERT_UNSIGNED(arr[1+:2]) `ASSERT_UNSIGNED(arr[1+:2])
`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 endmodule
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment