Commit 87ea9de8 by Zachary Snow

substitute constants from type information across scopes

parent 6d2cdf1d
...@@ -22,6 +22,7 @@ import qualified Convert.ForDecl ...@@ -22,6 +22,7 @@ import qualified Convert.ForDecl
import qualified Convert.Foreach import qualified Convert.Foreach
import qualified Convert.FuncRet import qualified Convert.FuncRet
import qualified Convert.FuncRoutine import qualified Convert.FuncRoutine
import qualified Convert.HierConst
import qualified Convert.ImplicitNet import qualified Convert.ImplicitNet
import qualified Convert.Inside import qualified Convert.Inside
import qualified Convert.Interface import qualified Convert.Interface
...@@ -74,6 +75,7 @@ mainPhases selectExclude = ...@@ -74,6 +75,7 @@ mainPhases selectExclude =
, Convert.MultiplePacked.convert , Convert.MultiplePacked.convert
, Convert.UnbasedUnsized.convert , Convert.UnbasedUnsized.convert
, Convert.Cast.convert , Convert.Cast.convert
, Convert.HierConst.convert
, Convert.TypeOf.convert , Convert.TypeOf.convert
, Convert.DimensionQuery.convert , Convert.DimensionQuery.convert
, Convert.ParamType.convert , Convert.ParamType.convert
......
{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
-
- Elaborate hierarchical references to constants
-
- [System]Verilog does not allow hierarchical identifiers as constant
- primaries. However, the resolution of type information across scopes can
- create such hierarchical references. This conversion performs substitution
- for any hierarchical references to parameters or localparams, regardless of
- whether or not they occur within what should be a constant expression.
-
- If an identifier refers to a parameter which has been shadowed locally, the
- conversion creates a localparam alias of the parameter at the top level scope
- and refers to the parameter using that alias instead.
-
- TODO: Support resolution of hierarchical references to constant functions
- TODO: Some other conversions still blindly substitute type information
-}
module Convert.HierConst (convert) where
import Data.Either (fromLeft)
import qualified Data.Map.Strict as Map
import Convert.Scoper
import Convert.Traverse
import Language.SystemVerilog.AST
convert :: [AST] -> [AST]
convert = map $ traverseDescriptions convertDescription
convertDescription :: Description -> Description
convertDescription (Part attrs extern kw lifetime name ports items) =
Part attrs extern kw lifetime name ports $
if null shadowedParams
then items'
else map expand items'
where
(items', mapping) = runScoper traverseDeclM
(traverseExprsM traverseExprM)
(traverseGenItemExprsM traverseExprM)
(traverseStmtExprsM traverseExprM)
name items
shadowedParams = Map.keys $ Map.filter (fromLeft False) $
extractMapping mapping
expand = traverseNestedModuleItems $ expandParam shadowedParams
convertDescription description = description
expandParam :: [Identifier] -> ModuleItem -> ModuleItem
expandParam shadowed (MIPackageItem (Decl (param @ (Param Parameter _ x _)))) =
if elem x shadowed
then Generate $ map (GenModuleItem . wrap) [param, extra]
else wrap param
where
wrap = MIPackageItem . Decl
extra = Param Localparam UnknownType (prefix x) (Ident x)
expandParam _ item = item
prefix :: Identifier -> Identifier
prefix = (++) "_sv2v_disambiguate_"
type ST = Scoper (Either Bool Expr)
traverseDeclM :: Decl -> ST Decl
traverseDeclM decl = do
case decl of
Param Parameter _ x _ ->
insertElem x (Left False)
Param Localparam UnknownType x e ->
scopeExpr e >>= insertElem x . Right
Param Localparam (Implicit sg rs) x e ->
scopeExpr (Cast (Left t) e) >>= insertElem x . Right
where t = IntegerVector TLogic sg rs
Param Localparam t x e ->
scopeExpr (Cast (Left t) e) >>= insertElem x . Right
_ -> return ()
traverseDeclExprsM traverseExprM decl
-- rewrite an expression so that any constant identifiers it contains
-- unambiguously refer refer to currently visible constant declarations so it
-- can be substituted elsewhere
scopeExpr :: Expr -> ST Expr
scopeExpr expr = do
expr' <- traverseSinglyNestedExprsM scopeExpr expr
details <- lookupElemM expr'
case details of
Just (accesses, _, _) -> return $ accessesToExpr accesses
_ -> return expr'
-- substitute hierarchical references to constants
traverseExprM :: Expr -> ST Expr
traverseExprM (expr @ (Dot _ x)) = do
expr' <- traverseSinglyNestedExprsM traverseExprM expr
detailsE <- lookupElemM expr'
detailsX <- lookupElemM x
case (detailsE, detailsX) of
(Just ([_, _], _, Left{}), Just ([_, _], _, Left{})) ->
return $ Ident x
(Just (accesses @ [Access _ Nil, _], _, Left False), _) -> do
insertElem accesses (Left True)
return $ Ident $ prefix x
(Just ([Access _ Nil, _], _, Left True), _) ->
return $ Ident $ prefix x
(Just (aE, replacements, Right value), Just (aX, _, _)) ->
if aE == aX && Map.null replacements
then return $ Ident x
else traverseSinglyNestedExprsM traverseExprM $
replaceInExpr replacements value
(Just (_, replacements, Right value), Nothing) ->
traverseSinglyNestedExprsM traverseExprM $
replaceInExpr replacements value
_ -> traverseSinglyNestedExprsM traverseExprM expr
traverseExprM expr = traverseSinglyNestedExprsM traverseExprM expr
...@@ -214,13 +214,6 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) = ...@@ -214,13 +214,6 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) =
Nothing -> accessesToExpr $ init accesses Nothing -> accessesToExpr $ init accesses
where Just (accesses, _, _) = where Just (accesses, _, _) =
lookupElem modports (Dot e "") lookupElem modports (Dot e "")
accessesToExpr :: [Access] -> Expr
accessesToExpr accesses =
foldl accessToExpr (Ident topName) rest
where Access topName Nil : rest = accesses
accessToExpr :: Expr -> Access -> Expr
accessToExpr e (Access x Nil) = Dot e x
accessToExpr e (Access x i) = Bit (Dot e x) i
-- expand a modport binding into a series of expression substitutions -- expand a modport binding into a series of expression substitutions
genSubstitutions :: Scopes [ModportDecl] -> Expr -> Expr -> Expr genSubstitutions :: Scopes [ModportDecl] -> Expr -> Expr -> Expr
......
...@@ -27,9 +27,13 @@ module Convert.Scoper ...@@ -27,9 +27,13 @@ module Convert.Scoper
, ScoperT , ScoperT
, evalScoper , evalScoper
, evalScoperT , evalScoperT
, runScoper
, runScoperT , runScoperT
, partScoper , partScoper
, partScoperT , partScoperT
, accessesToExpr
, replaceInType
, replaceInExpr
, insertElem , insertElem
, injectItem , injectItem
, injectDecl , injectDecl
...@@ -154,6 +158,34 @@ exprToAccesses (Dot e x) = do ...@@ -154,6 +158,34 @@ exprToAccesses (Dot e x) = do
Just $ accesses ++ [Access x Nil] Just $ accesses ++ [Access x Nil]
exprToAccesses _ = Nothing exprToAccesses _ = Nothing
accessesToExpr :: [Access] -> Expr
accessesToExpr accesses =
foldl accessToExpr (Ident topName) rest
where Access topName Nil : rest = accesses
accessToExpr :: Expr -> Access -> Expr
accessToExpr e (Access x Nil) = Dot e x
accessToExpr e (Access x i) = Bit (Dot e x) i
replaceInType :: Replacements -> Type -> Type
replaceInType replacements =
if Map.null replacements
then id
else traverseNestedTypes $ traverseTypeExprs $
replaceInExpr' replacements
replaceInExpr :: Replacements -> Expr -> Expr
replaceInExpr replacements =
if Map.null replacements
then id
else replaceInExpr' replacements
replaceInExpr' :: Replacements -> Expr -> Expr
replaceInExpr' replacements (Ident x) =
Map.findWithDefault (Ident x) x replacements
replaceInExpr' replacements other =
traverseSinglyNestedExprs (replaceInExpr replacements) other
class ScopePath k where class ScopePath k where
toTiers :: Scopes a -> k -> [Tier] toTiers :: Scopes a -> k -> [Tier]
...@@ -301,6 +333,18 @@ evalScoperT declMapper moduleItemMapper genItemMapper stmtMapper topName items = ...@@ -301,6 +333,18 @@ evalScoperT declMapper moduleItemMapper genItemMapper stmtMapper topName items =
topName items topName items
return items' return items'
runScoper
:: MapperM (Scoper a) Decl
-> MapperM (Scoper a) ModuleItem
-> MapperM (Scoper a) GenItem
-> MapperM (Scoper a) Stmt
-> Identifier
-> [ModuleItem]
-> ([ModuleItem], Scopes a)
runScoper declMapper moduleItemMapper genItemMapper stmtMapper topName items =
runIdentity $ runScoperT
declMapper moduleItemMapper genItemMapper stmtMapper topName items
runScoperT runScoperT
:: forall a m. Monad m :: forall a m. Monad m
=> MapperM (ScoperT a m) Decl => MapperM (ScoperT a m) Decl
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
module Convert.TypeOf (convert) where module Convert.TypeOf (convert) where
import Data.Tuple (swap) import Data.Tuple (swap)
import qualified Data.Map.Strict as Map
import Convert.ExprUtils (dimensionsSize, endianCondRange, simplify) import Convert.ExprUtils (dimensionsSize, endianCondRange, simplify)
import Convert.Scoper import Convert.Scoper
...@@ -38,8 +37,10 @@ convert = map $ traverseDescriptions $ partScoper ...@@ -38,8 +37,10 @@ convert = map $ traverseDescriptions $ partScoper
pattern UnitType :: Type pattern UnitType :: Type
pattern UnitType = IntegerVector TLogic Unspecified [] pattern UnitType = IntegerVector TLogic Unspecified []
type ST = Scoper (Type, Bool)
-- 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 -> ST Decl
traverseDeclM decl = do traverseDeclM decl = do
decl' <- traverseDeclExprsM traverseExprM decl decl' <- traverseDeclExprsM traverseExprM decl
>>= traverseDeclTypesM traverseTypeM >>= traverseDeclTypesM traverseTypeM
...@@ -47,45 +48,61 @@ traverseDeclM decl = do ...@@ -47,45 +48,61 @@ traverseDeclM decl = do
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
-- types, are recast as logics to avoid outputting bare ranges -- types, are recast as logics to avoid outputting bare ranges
insertElem ident t' >> return decl' insertType ident t' >> return decl'
where t' = injectRanges (IntegerVector TLogic sg rs) a where t' = injectRanges (IntegerVector TLogic sg rs) a
Variable d t ident a e -> do Variable d t ident a e -> do
let t' = injectRanges t a let t' = injectRanges t a
insertElem ident t' insertType ident t'
return $ case t' of return $ case t' of
UnpackedType t'' a' -> Variable d t'' ident a' e UnpackedType t'' a' -> Variable d t'' ident a' e
_ -> Variable d t' ident [] e _ -> Variable d t' ident [] e
Param _ UnknownType ident String{} -> Param _ UnknownType ident String{} ->
insertElem ident UnknownType >> return decl' insertType ident UnknownType >> return decl'
Param _ UnknownType ident e -> Param _ UnknownType ident e ->
typeof e >>= insertElem ident >> return decl' typeof e >>= insertType ident >> return decl'
Param _ (Implicit sg rs) ident _ -> Param _ (Implicit sg rs) ident _ ->
insertElem ident t' >> return decl' insertType ident t' >> return decl'
where t' = IntegerVector TLogic sg rs where t' = IntegerVector TLogic sg rs
Param _ t ident _ -> Param _ t ident _ ->
insertElem ident t >> return decl' insertType ident t >> return decl'
ParamType{} -> return decl' ParamType{} -> return decl'
CommentDecl{} -> return decl' CommentDecl{} -> return decl'
-- rewrite and store a non-genvar data declaration's type information
insertType :: Identifier -> Type -> ST ()
insertType ident typ = do
typ' <- traverseNestedTypesM (traverseTypeExprsM scopeExpr) typ
insertElem ident (typ', False)
-- rewrite an expression so that any identifiers it contains unambiguously refer
-- refer to currently visible declarations so it can be substituted elsewhere
scopeExpr :: Expr -> ST Expr
scopeExpr expr = do
expr' <- traverseSinglyNestedExprsM scopeExpr expr
details <- lookupElemM expr'
case details of
Just (accesses, _, (_, False)) -> return $ accessesToExpr accesses
_ -> return expr'
-- convert TypeOf in a ModuleItem -- convert TypeOf in a ModuleItem
traverseModuleItemM :: ModuleItem -> Scoper Type ModuleItem traverseModuleItemM :: ModuleItem -> ST ModuleItem
traverseModuleItemM (Genvar x) = do traverseModuleItemM (Genvar x) =
insertElem x $ IntegerAtom TInteger Unspecified insertElem x (t, True) >> return (Genvar x)
return $ Genvar x where t = IntegerAtom TInteger Unspecified
traverseModuleItemM item = traverseModuleItemM item =
traverseNodesM traverseExprM return traverseTypeM traverseLHSM return item traverseNodesM traverseExprM return traverseTypeM traverseLHSM return item
where traverseLHSM = traverseLHSExprsM traverseExprM where traverseLHSM = traverseLHSExprsM traverseExprM
-- convert TypeOf in a GenItem -- convert TypeOf in a GenItem
traverseGenItemM :: GenItem -> Scoper Type GenItem traverseGenItemM :: GenItem -> ST GenItem
traverseGenItemM = traverseGenItemExprsM traverseExprM traverseGenItemM = traverseGenItemExprsM traverseExprM
-- convert TypeOf in a Stmt -- convert TypeOf in a Stmt
traverseStmtM :: Stmt -> Scoper Type Stmt traverseStmtM :: Stmt -> ST Stmt
traverseStmtM = traverseStmtExprsM traverseExprM traverseStmtM = traverseStmtExprsM traverseExprM
-- convert TypeOf in an Expr -- convert TypeOf in an Expr
traverseExprM :: Expr -> Scoper Type Expr traverseExprM :: Expr -> ST Expr
traverseExprM (Cast (Left (Implicit sg [])) expr) = traverseExprM (Cast (Left (Implicit sg [])) expr) =
-- `signed'(foo)` and `unsigned'(foo)` are syntactic sugar for the `$signed` -- `signed'(foo)` and `unsigned'(foo)` are syntactic sugar for the `$signed`
-- and `$unsigned` system functions present in Verilog-2005 -- and `$unsigned` system functions present in Verilog-2005
...@@ -122,7 +139,7 @@ traverseExprM other = ...@@ -122,7 +139,7 @@ traverseExprM other =
>>= traverseSinglyNestedExprsM traverseExprM >>= traverseSinglyNestedExprsM traverseExprM
-- carry forward the signedness of the expression when cast to the given size -- carry forward the signedness of the expression when cast to the given size
elaborateSizeCast :: Expr -> Expr -> Scoper Type Expr elaborateSizeCast :: Expr -> Expr -> ST Expr
elaborateSizeCast size value = do elaborateSizeCast size value = do
t <- typeof value t <- typeof value
case typeSignedness t of case typeSignedness t of
...@@ -130,7 +147,7 @@ elaborateSizeCast size value = do ...@@ -130,7 +147,7 @@ elaborateSizeCast size value = do
sg -> traverseExprM $ Cast (Left $ typeOfSize sg size) value sg -> traverseExprM $ Cast (Left $ typeOfSize sg size) value
-- convert TypeOf in a Type -- convert TypeOf in a Type
traverseTypeM :: Type -> Scoper Type Type traverseTypeM :: Type -> ST Type
traverseTypeM (TypeOf expr) = traverseTypeM (TypeOf expr) =
traverseExprM expr >>= typeof traverseExprM expr >>= typeof
traverseTypeM other = traverseTypeM other =
...@@ -139,31 +156,22 @@ traverseTypeM other = ...@@ -139,31 +156,22 @@ traverseTypeM other =
-- 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
lookupTypeOf :: Expr -> Scoper Type Type lookupTypeOf :: Expr -> ST Type
lookupTypeOf expr = do 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) -> do Just (_, replacements, (typ, _)) -> do
let typ' = toVarType typ let typ' = toVarType typ
return $ if Map.null replacements return $ replaceInType replacements typ'
then typ'
else rewriteType replacements typ'
where where
toVarType :: Type -> Type toVarType :: Type -> Type
toVarType (Net _ sg rs) = IntegerVector TLogic sg rs toVarType (Net _ sg rs) = IntegerVector TLogic sg rs
toVarType other = other toVarType other = other
rewriteType :: Replacements -> Type -> Type
rewriteType replacements = traverseNestedTypes $ traverseTypeExprs $
traverseNestedExprs (replace replacements)
replace :: Replacements -> Expr -> Expr
replace replacements (Ident x) =
Map.findWithDefault (Ident x) x replacements
replace _ other = other
-- determines the type of an expression based on the available scope information -- determines the type of an expression based on the available scope information
-- according the semantics defined in IEEE 1800-2017, especially Section 11.6 -- according the semantics defined in IEEE 1800-2017, especially Section 11.6
typeof :: Expr -> Scoper Type Type typeof :: Expr -> ST Type
typeof (Number n) = typeof (Number n) =
return $ IntegerVector TLogic sg [r] return $ IntegerVector TLogic sg [r]
where where
...@@ -233,7 +241,7 @@ unescapedLength ('\\' : _ : rest) = 1 + unescapedLength rest ...@@ -233,7 +241,7 @@ unescapedLength ('\\' : _ : rest) = 1 + unescapedLength rest
unescapedLength (_ : rest) = 1 + unescapedLength rest unescapedLength (_ : rest) = 1 + unescapedLength rest
-- type of a standard (non-member) function call -- type of a standard (non-member) function call
typeofCall :: String -> Args -> Scoper Type Type typeofCall :: String -> Args -> ST Type
typeofCall "$unsigned" (Args [e] []) = return $ typeOfSize Unsigned $ sizeof e typeofCall "$unsigned" (Args [e] []) = return $ typeOfSize Unsigned $ sizeof e
typeofCall "$signed" (Args [e] []) = return $ typeOfSize Signed $ sizeof e typeofCall "$signed" (Args [e] []) = return $ typeOfSize Signed $ sizeof e
typeofCall "$clog2" (Args [_] []) = typeofCall "$clog2" (Args [_] []) =
...@@ -250,7 +258,7 @@ typeSignednessOverride fallback sg t = ...@@ -250,7 +258,7 @@ typeSignednessOverride fallback sg t =
_ -> fallback _ -> fallback
-- type of a unary operator expression -- type of a unary operator expression
typeofUniOp :: UniOp -> Expr -> Scoper Type Type typeofUniOp :: UniOp -> Expr -> ST Type
typeofUniOp UniAdd e = typeof e typeofUniOp UniAdd e = typeof e
typeofUniOp UniSub e = typeof e typeofUniOp UniSub e = typeof e
typeofUniOp BitNot e = typeof e typeofUniOp BitNot e = typeof e
...@@ -259,7 +267,7 @@ typeofUniOp _ _ = ...@@ -259,7 +267,7 @@ typeofUniOp _ _ =
return UnitType return UnitType
-- type of a binary operator expression (Section 11.6.1) -- type of a binary operator expression (Section 11.6.1)
typeofBinOp :: BinOp -> Expr -> Expr -> Scoper Type Type typeofBinOp :: BinOp -> Expr -> Expr -> ST Type
typeofBinOp op a b = typeofBinOp op a b =
case op of case op of
LogAnd -> unitType LogAnd -> unitType
...@@ -293,7 +301,7 @@ typeofBinOp op a b = ...@@ -293,7 +301,7 @@ typeofBinOp op a b =
where unitType = return UnitType where unitType = return UnitType
-- produces a type large enough to hold either expression -- produces a type large enough to hold either expression
largerSizeType :: Expr -> Expr -> Scoper Type Type largerSizeType :: Expr -> Expr -> ST Type
largerSizeType a (Number (Based 1 _ _ _ _)) = typeof a largerSizeType a (Number (Based 1 _ _ _ _)) = typeof a
largerSizeType a b = do largerSizeType a b = do
t <- typeof a t <- typeof a
......
...@@ -72,6 +72,7 @@ executable sv2v ...@@ -72,6 +72,7 @@ executable sv2v
Convert.Foreach Convert.Foreach
Convert.FuncRet Convert.FuncRet
Convert.FuncRoutine Convert.FuncRoutine
Convert.HierConst
Convert.ImplicitNet Convert.ImplicitNet
Convert.Inside Convert.Inside
Convert.Interface Convert.Interface
......
module top;
parameter WIDTH = 1;
if (1) begin : a
localparam tmp = WIDTH * 2;
if (1) begin : c
localparam WIDTH = tmp * 3;
reg [WIDTH-1:0] x;
end
end
if (1) begin : b
localparam tmp = WIDTH * 5;
if (1) begin : d
localparam WIDTH = tmp * 7;
reg [WIDTH-1:0] x;
end
end
reg [$bits(a.c.x):0] a_c_x;
reg [$bits(b.d.x):0] b_d_x;
if (1) begin : e
localparam tmp = WIDTH * 11;
if (1) begin : f
localparam WIDTH = tmp * 13;
reg [WIDTH-1:0] x;
reg [$bits(a.c.x):0] a_c_x;
reg [$bits(b.d.x):0] b_d_x;
initial begin
a_c_x = 1;
b_d_x = 1;
$display("B a.c.x %b", a.c.x);
$display("B a_c_x %b", a_c_x);
$display("B b.d.x %b", b.d.x);
$display("B b_d_x %b", b_d_x);
end
end
end
reg [$bits(e.f.x):0] e_f_x;
reg [$bits(e.f.a_c_x):0] e_f_a_c_x;
reg [$bits(e.f.b_d_x):0] e_f_b_d_x;
initial begin
e_f_x = 1'sb1;
e_f_a_c_x = 1'sbx;
e_f_b_d_x = 1'sbz;
$display("A a.c.x %b", a.c.x);
$display("A a_c_x %b", a_c_x);
$display("A b.d.x %b", b.d.x);
$display("A b_d_x %b", b_d_x);
$display("A e.f.x %b", e.f.x);
$display("A e_f_x %b", e_f_x);
$display("A e.f.a_c_x %b", e.f.a_c_x);
$display("A e_f_a_c_x %b", e_f_a_c_x);
$display("A e.f.b_d_x %b", e.f.b_d_x);
$display("A e_f_b_d_x %b", e_f_b_d_x);
end
endmodule
module top;
parameter WIDTH = 1;
if (1) begin : a
if (1) begin : c
reg [WIDTH*2*3-1:0] x;
end
end
if (1) begin : b
if (1) begin : d
reg [WIDTH*5*7-1:0] x;
end
end
reg [WIDTH*2*3:0] a_c_x;
reg [WIDTH*5*7:0] b_d_x;
if (1) begin : e
if (1) begin : f
reg [WIDTH*11*13-1:0] x;
reg [WIDTH*2*3:0] a_c_x;
reg [WIDTH*5*7:0] b_d_x;
initial begin
a_c_x = 1;
b_d_x = 1;
$display("B a.c.x %b", a.c.x);
$display("B a_c_x %b", a_c_x);
$display("B b.d.x %b", b.d.x);
$display("B b_d_x %b", b_d_x);
end
end
end
reg [WIDTH*11*13:0] e_f_x;
reg [WIDTH*2*3+1:0] e_f_a_c_x;
reg [WIDTH*5*7+1:0] e_f_b_d_x;
initial begin
e_f_x = 1'sb1;
e_f_a_c_x = 1'sbx;
e_f_b_d_x = 1'sbz;
$display("A a.c.x %b", a.c.x);
$display("A a_c_x %b", a_c_x);
$display("A b.d.x %b", b.d.x);
$display("A b_d_x %b", b_d_x);
$display("A e.f.x %b", e.f.x);
$display("A e_f_x %b", e_f_x);
$display("A e.f.a_c_x %b", e.f.a_c_x);
$display("A e_f_a_c_x %b", e_f_a_c_x);
$display("A e.f.b_d_x %b", e.f.b_d_x);
$display("A e_f_b_d_x %b", e_f_b_d_x);
end
endmodule
`define TYPEOF(x) wire [$bits(x) - 1:0]
// The `REF` sections of this test are workarounds for steveicarus/iverilog#483
module top;
genvar i;
if (1) begin : blk
for (i = 0; i < 3; i = i + 1) begin : prev
localparam V = i * 2;
localparam W = V;
wire [W:0] x;
end
for (i = 0; i < 2; i = i + 1) begin : loop
`TYPEOF(prev[i+1].x) x;
if (1) begin : a
localparam j = i - 3;
if (1) begin : b
localparam i = j + 2;
`TYPEOF(prev[i+2].x) x;
if (1) begin : c
localparam j = i - 4;
if (1) begin : d
localparam i = j + 7;
localparam z = i - 1;
`TYPEOF(prev[z].x) x;
if (1) begin : e
localparam i = 0;
`ifdef REF
localparam j = 3;
`else
localparam j = $bits(blk.loop[i].a.b.c.d.x);
`endif
wire [j-1:0] y;
end
end
end
end
end
end
end
`ifdef REF
wire [1*2:0] a;
wire [2*2:0] b;
wire [1*2:0] c;
wire [2*2:0] d;
wire [1*2:0] e;
wire [2*2:0] f;
wire [1*2:0] g;
wire [1*2:0] h;
`else
`TYPEOF(blk.loop[0].x) a;
`TYPEOF(blk.loop[1].x) b;
`TYPEOF(blk.loop[0].a.b.x) c;
`TYPEOF(blk.loop[1].a.b.x) d;
`TYPEOF(blk.loop[0].a.b.c.d.x) e;
`TYPEOF(blk.loop[1].a.b.c.d.x) f;
`TYPEOF(blk.loop[0].a.b.c.d.e.y) g;
`TYPEOF(blk.loop[1].a.b.c.d.e.y) h;
`endif
`define DUMP(x) assign x = 1; initial $display(`"x: %b (%0d bits)`", x, $bits(x));
`DUMP(a) `DUMP(b) `DUMP(c) `DUMP(d) `DUMP(e) `DUMP(f) `DUMP(g) `DUMP(h)
`DUMP(blk.loop[0].x)
`DUMP(blk.loop[1].x)
`DUMP(blk.loop[0].a.b.x)
`DUMP(blk.loop[1].a.b.x)
`DUMP(blk.loop[0].a.b.c.d.x)
`DUMP(blk.loop[1].a.b.c.d.x)
`DUMP(blk.loop[0].a.b.c.d.e.y)
`DUMP(blk.loop[1].a.b.c.d.e.y)
endmodule
`define REF 1
`include "typeof_scope.sv"
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