Commit aa451b66 by Zachary Snow

stronger typename checks

parent deed2d9f
...@@ -15,12 +15,15 @@ ...@@ -15,12 +15,15 @@
* Fixed an issue that prevented parsing tasks and functions with `inout` ports * Fixed an issue that prevented parsing tasks and functions with `inout` ports
* Fixed conflicting genvar names when inlining interfaces and modules that use * Fixed conflicting genvar names when inlining interfaces and modules that use
them; all genvars are now given a design-wide unique name them; all genvars are now given a design-wide unique name
* Fixed failure to resolve typenames suffixed with dimensions in contexts
permitting both types and expressions, e.g., `$bits(T[W-1:0])`
* Fixed errant constant folding of shadowed non-trivial localparams * Fixed errant constant folding of shadowed non-trivial localparams
* Fixed certain non-ANSI style port declarations being incorrectly reported as * Fixed certain non-ANSI style port declarations being incorrectly reported as
incompatible incompatible
### Other Enhancements ### Other Enhancements
* Added error checking for unresolved typenames
* Added constant folding for `||` and `&&` * Added constant folding for `||` and `&&`
## v0.0.11 ## v0.0.11
......
{- sv2v {- sv2v
- Author: Zachary Snow <zach@zachjs.com> - Author: Zachary Snow <zach@zachjs.com>
- -
- Conversion for `typedef` - Conversion for `typedef` and `localparam type`
- -
- Aliased types can appear in all data declarations, including modules, blocks, - Aliased types can appear in all data declarations, including modules, blocks,
- and function parameters. They are also found in type cast expressions. - and function parameters. They are also found in type cast expressions.
...@@ -20,22 +20,44 @@ convert = map $ traverseDescriptions $ evalScoper . scopeModule scoper ...@@ -20,22 +20,44 @@ convert = map $ traverseDescriptions $ evalScoper . scopeModule scoper
where scoper = scopeModuleItem where scoper = scopeModuleItem
traverseDeclM traverseModuleItemM traverseGenItemM traverseStmtM traverseDeclM traverseModuleItemM traverseGenItemM traverseStmtM
traverseTypeOrExprM :: TypeOrExpr -> Scoper Type TypeOrExpr type SC = Scoper IdentKind
traverseTypeOrExprM (Left (TypeOf (Ident x))) = do
details <- lookupElemM x data IdentKind
return $ case details of = Type Type -- resolved typename
Nothing -> Left $ TypeOf $ Ident x | Pending -- unresolved type parameter
Just (_, _, UnknownType) -> Left $ TypeOf $ Ident x | NonType String -- anything else
Just (_, _, typ) -> Left typ
traverseTypeOrExprM (Right (Ident x)) = do traverseTypeOrExprM :: TypeOrExpr -> SC TypeOrExpr
traverseTypeOrExprM tore
| Left (TypeOf expr) <- tore = possibleTypeName tore expr
| Right expr <- tore = possibleTypeName tore expr
| otherwise = return tore
possibleTypeName :: TypeOrExpr -> Expr -> SC TypeOrExpr
possibleTypeName orig expr
| Just (x, rs1) <- maybeTypeName = do
details <- lookupElemM x details <- lookupElemM x
return $ case details of return $ case details of
Nothing -> Right $ Ident x Just (_, _, Type typ) ->
Just (_, _, UnknownType) -> Right $ Ident x Left $ tf $ rs1 ++ rs2
Just (_, _, typ) -> Left typ where (tf, rs2) = typeRanges typ
traverseTypeOrExprM other = return other Just (_, _, Pending) ->
Left $ Alias x rs1
_ -> orig
| otherwise = return orig
where maybeTypeName = exprToTypeName [] expr
-- aliases in type-or-expr contexts are parsed as expressions
exprToTypeName :: [Range] -> Expr -> Maybe (Identifier, [Range])
exprToTypeName rs (Ident x) = Just (x, rs)
exprToTypeName rs (Bit expr idx) =
exprToTypeName (r : rs) expr
where r = (RawNum 0, BinOp Sub idx (RawNum 1))
exprToTypeName rs (Range expr NonIndexed r) = do
exprToTypeName (r : rs) expr
exprToTypeName _ _ = Nothing
traverseExprM :: Expr -> Scoper Type Expr traverseExprM :: Expr -> SC Expr
traverseExprM (Cast v e) = do traverseExprM (Cast v e) = do
v' <- traverseTypeOrExprM v v' <- traverseTypeOrExprM v
traverseExprM' $ Cast v' e traverseExprM' $ Cast v' e
...@@ -51,68 +73,82 @@ traverseExprM (Pattern items) = do ...@@ -51,68 +73,82 @@ traverseExprM (Pattern items) = do
traverseExprM' $ Pattern $ zip names exprs traverseExprM' $ Pattern $ zip names exprs
traverseExprM other = traverseExprM' other traverseExprM other = traverseExprM' other
traverseExprM' :: Expr -> Scoper Type Expr traverseExprM' :: Expr -> SC Expr
traverseExprM' = traverseExprM' =
traverseSinglyNestedExprsM traverseExprM traverseSinglyNestedExprsM traverseExprM
>=> traverseExprTypesM traverseTypeM >=> traverseExprTypesM traverseTypeM
traverseModuleItemM :: ModuleItem -> Scoper Type ModuleItem traverseModuleItemM :: ModuleItem -> SC ModuleItem
traverseModuleItemM (Instance m params x rs p) = do traverseModuleItemM (Instance m params x rs p) = do
let mapParam (i, v) = traverseTypeOrExprM v >>= \v' -> return (i, v') let mapParam (i, v) = traverseTypeOrExprM v >>= \v' -> return (i, v')
params' <- mapM mapParam params params' <- mapM mapParam params
traverseModuleItemM' $ Instance m params' x rs p traverseModuleItemM' $ Instance m params' x rs p
traverseModuleItemM item = traverseModuleItemM' item traverseModuleItemM item = traverseModuleItemM' item
traverseModuleItemM' :: ModuleItem -> Scoper Type ModuleItem traverseModuleItemM' :: ModuleItem -> SC ModuleItem
traverseModuleItemM' = traverseModuleItemM' =
traverseNodesM traverseExprM return traverseTypeM traverseLHSM return traverseNodesM traverseExprM return traverseTypeM traverseLHSM return
where traverseLHSM = traverseLHSExprsM traverseExprM where traverseLHSM = traverseLHSExprsM traverseExprM
traverseGenItemM :: GenItem -> Scoper Type GenItem traverseGenItemM :: GenItem -> SC GenItem
traverseGenItemM = traverseGenItemExprsM traverseExprM traverseGenItemM = traverseGenItemExprsM traverseExprM
traverseDeclM :: Decl -> Scoper Type Decl traverseDeclM :: Decl -> SC Decl
traverseDeclM decl = do traverseDeclM decl = do
decl' <- traverseDeclNodesM traverseTypeM traverseExprM decl decl' <- traverseDeclNodesM traverseTypeM traverseExprM decl
case decl' of case decl' of
Variable{} -> return decl' Variable _ _ x _ _ -> insertElem x (NonType "var") >> return decl'
Net{} -> return decl' Net _ _ _ _ x _ _ -> insertElem x (NonType "net") >> return decl'
Param s (UnpackedType t rs1) x e -> do Param s (UnpackedType t rs1) x e -> do
insertElem x UnknownType insertElem x (NonType $ show s)
let (tf, rs2) = typeRanges t let (tf, rs2) = typeRanges t
let t' = tf $ rs1 ++ rs2 let t' = tf $ rs1 ++ rs2
return $ Param s t' x e return $ Param s t' x e
Param _ _ x _ -> Param s _ x _ ->
insertElem x UnknownType >> return decl' insertElem x (NonType $ show s) >> return decl'
ParamType Localparam x t -> do ParamType Localparam x t -> do
traverseTypeM t >>= scopeType >>= insertElem x traverseTypeM t >>= scopeType >>= insertElem x . Type
return $ case t of return $ case t of
Enum{} -> ParamType Localparam tmpX t Enum{} -> ParamType Localparam tmpX t
_ -> CommentDecl $ "removed localparam type " ++ x _ -> CommentDecl $ "removed localparam type " ++ x
where tmpX = "_sv2v_keep_enum_for_params" where tmpX = "_sv2v_keep_enum_for_params"
ParamType{} -> return decl' ParamType Parameter x _ ->
insertElem x Pending >> return decl'
CommentDecl{} -> return decl' CommentDecl{} -> return decl'
traverseStmtM :: Stmt -> Scoper Type Stmt traverseStmtM :: Stmt -> SC Stmt
traverseStmtM = traverseStmtExprsM traverseExprM traverseStmtM = traverseStmtExprsM traverseExprM
traverseTypeM :: Type -> Scoper Type Type traverseTypeM :: Type -> SC Type
traverseTypeM (Alias st rs1) = do traverseTypeM (Alias st rs1) = do
details <- lookupElemM st details <- lookupElemM st
rs1' <- mapM traverseRangeM rs1 rs1' <- mapM traverseRangeM rs1
return $ case details of case details of
Nothing -> Alias st rs1' Just (_, _, Type typ) ->
Just (_, _, UnknownType) -> Alias st rs1' return $ tf $ rs1' ++ rs2
Just (_, _, typ) -> tf $ rs1' ++ rs2
where (tf, rs2) = typeRanges typ where (tf, rs2) = typeRanges typ
Just (_, _, Pending) ->
return $ Alias st rs1'
Just (_, _, NonType kind) ->
scopedErrorM $ "expected typename, but found " ++ kind
++ " identifier " ++ show st
Nothing ->
scopedErrorM $ "couldn't resolve typename " ++ show st
traverseTypeM (TypedefRef expr) = do traverseTypeM (TypedefRef expr) = do
details <- lookupElemM expr details <- lookupElemM expr
return $ case details of case details of
Nothing -> TypedefRef expr Just (_, _, Type typ) -> return typ
Just (_, _, typ) -> typ Just (_, _, Pending) ->
error "TypdefRef invariant violated! Please file an issue."
Just (_, _, NonType kind) ->
scopedErrorM $ "expected interface-based typename, but found "
++ kind ++ " " ++ show expr
-- This can occur when the interface conversion is delayed due to
-- multi-dimension instances.
Nothing -> return $ TypedefRef expr
traverseTypeM other = traverseTypeM other =
traverseSinglyNestedTypesM traverseTypeM other traverseSinglyNestedTypesM traverseTypeM other
>>= traverseTypeExprsM traverseExprM >>= traverseTypeExprsM traverseExprM
traverseRangeM :: Range -> Scoper Type Range traverseRangeM :: Range -> SC Range
traverseRangeM = mapBothM traverseExprM traverseRangeM = mapBothM traverseExprM
`define TEST_INNER(expr, size) \
initial $display(`"expr %0d %0d %0d`", \
$bits(expr), $bits(type(expr)), size);
localparam type T = logic;
localparam type U = logic [2:1];
`include "typename_deep.svh"
`define TEST(expr, size) \
`TEST_INNER(expr, size) \
`TEST_INNER(expr[2], size * 2) \
`TEST_INNER(expr[2][3], size * 6) \
`TEST_INNER(expr[3:7], size * 5) \
`TEST_INNER(expr[$bits(T)], size) \
`TEST_INNER(expr[$bits(U)], size * 2) \
`TEST_INNER(expr[$bits(T[$bits(U)])], size * 2) \
`TEST_INNER(expr[$bits(U[$bits(U)])], size * 4)
module top;
`TEST(T, 1)
`TEST(U, 2)
endmodule
`define TEST_INNER(expr, size) \
initial $display(`"expr %0d %0d %0d`", \
size, size, size);
`include "typename_deep.svh"
// pattern: couldn't resolve typename "T"
// location: typedef_missing.sv:4:5
module top;
T x;
endmodule
// pattern: expected typename, but found localparam identifier "L"
// location: typedef_not_type_localparam.sv:5:5
module top;
localparam L = 0;
L x;
endmodule
// pattern: expected typename, but found net identifier "w"
// location: typedef_not_type_net.sv:5:5
module top;
wire w;
w x;
endmodule
// pattern: expected typename, but found var identifier "v"
// location: typedef_not_type_var.sv:5:5
module top;
var v;
v x;
endmodule
// pattern: expected interface-based typename, but found net x.y
// location: typedef_ref_not_type.sv:7:5
module top;
if (1) begin : x
wire y;
end
typedef x.y T;
T x;
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