diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d51c60..7b04c19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ * Port connection attributes (e.g., [pulp_soc.sv]) are now ignored with a warning rather than failing to parse * Improved error message when specifying an extraneous named port connection +* Added checks for accidental usage of interface or module names as type names [pulp_soc.sv]: https://github.com/pulp-platform/pulp_soc/blob/0573a85c/rtl/pulp_soc/pulp_soc.sv#L733 diff --git a/src/Convert/Interface.hs b/src/Convert/Interface.hs index 3cf65ae..6b06a45 100644 --- a/src/Convert/Interface.hs +++ b/src/Convert/Interface.hs @@ -10,6 +10,7 @@ module Convert.Interface (convert) where import Data.List (intercalate, (\\)) import Data.Maybe (isJust, isNothing, mapMaybe) import Control.Monad.Writer.Strict +import Text.Read (readMaybe) import qualified Data.Map.Strict as Map import Convert.ExprUtils (endianCondExpr) @@ -70,13 +71,26 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) = traverseDeclM :: Decl -> Scoper [ModportDecl] Decl traverseDeclM decl = do case decl of - Variable _ _ x _ _ -> insertElem x DeclVal - Net _ _ _ _ x _ _ -> insertElem x DeclVal - Param _ _ x _ -> insertElem x DeclVal + Variable _ t x _ _ -> checkDeclType t x $ insertElem x DeclVal + Net _ _ _ t x _ _ -> checkDeclType t x $ insertElem x DeclVal + Param _ t x _ -> checkDeclType t x $ insertElem x DeclVal ParamType _ x _ -> insertElem x DeclVal CommentDecl{} -> return () return decl + -- check for module or interface names used as type names + checkDeclType :: Type -> Identifier -> Scoper a b -> Scoper a b + checkDeclType (Alias typeName _) declName continue + | isNothing (readMaybe declName :: Maybe Int) = do + maybeType <- lookupElemM typeName + case (maybePart, maybeType) of + (Just part, Nothing{}) -> scopedErrorM $ "declaration " ++ + declName ++ " uses " ++ show (pKind part) ++ " name " ++ + typeName ++ " where a type name is expected" + _ -> continue + where maybePart = Map.lookup typeName parts + checkDeclType _ _ other = other + lookupIntfElem :: Scopes [ModportDecl] -> Expr -> LookupResult [ModportDecl] lookupIntfElem modports expr = case lookupElem modports expr of @@ -285,6 +299,7 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) = else if elem x (pPorts partInfo) then tell [(x, info)] >> return decl else + -- TODO: This does not handle shadowed typenames. scopedErrorM $ "Modport not in port list: " ++ show t ++ " " ++ x ++ ". Is this an interface missing a port list?" diff --git a/test/core/interface_name_shadow.sv b/test/core/interface_name_shadow.sv new file mode 100644 index 0000000..a8d4c87 --- /dev/null +++ b/test/core/interface_name_shadow.sv @@ -0,0 +1,12 @@ +interface I; + logic [3:0] x; +endinterface +module top; + I i(); + if (1) begin : blk + typedef logic I; + var I i; + assign i = 0; + end + initial $display("%b %b", i.x, blk.i); +endmodule diff --git a/test/core/interface_name_shadow.v b/test/core/interface_name_shadow.v new file mode 100644 index 0000000..9b9c256 --- /dev/null +++ b/test/core/interface_name_shadow.v @@ -0,0 +1,12 @@ +module top; + generate + if (1) begin : i + wire [3:0] x; + end + if (1) begin : blk + wire i; + assign i = 0; + end + endgenerate + initial $display("%b %b", i.x, blk.i); +endmodule diff --git a/test/error/interface_name_func.sv b/test/error/interface_name_func.sv new file mode 100644 index 0000000..b89e43c --- /dev/null +++ b/test/error/interface_name_func.sv @@ -0,0 +1,11 @@ +// pattern: declaration dst uses interface name I where a type name is expected +// location: interface_name_func.sv:5:12 +interface I; + logic [3:0] x; + task t(I dst, I src); + dst.x <= src.x; + endtask +endinterface +module top; + I i(); +endmodule diff --git a/test/error/interface_name_var.sv b/test/error/interface_name_var.sv new file mode 100644 index 0000000..68a7b4b --- /dev/null +++ b/test/error/interface_name_var.sv @@ -0,0 +1,8 @@ +// pattern: declaration i uses interface name I where a type name is expected +// location: interface_name_var.sv:7:12 +interface I; + logic [3:0] x; +endinterface +module top; + if (1) var I i; +endmodule