From 5080265e4d472dff18afb0929e8fef5c0f633352 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Mon, 22 Feb 2021 14:13:37 -0500 Subject: [PATCH] typedef, multipack, and struct conversions scope substitutions --- src/Convert/HierConst.hs | 14 -------------- src/Convert/MultiplePacked.hs | 6 ++++-- src/Convert/Scoper.hs | 18 ++++++++++++++++++ src/Convert/Struct.hs | 4 ++-- src/Convert/TypeOf.hs | 13 ------------- src/Convert/Typedef.hs | 8 ++++++-- test/basic/multipack_ident_scope.sv | 15 +++++++++++++++ test/basic/multipack_ident_scope.v | 15 +++++++++++++++ test/basic/struct_ident_scope.sv | 26 ++++++++++++++++++++++++++ test/basic/struct_ident_scope.v | 23 +++++++++++++++++++++++ test/basic/typedef_ident_scope.sv | 29 +++++++++++++++++++++++++++++ test/basic/typedef_ident_scope.v | 24 ++++++++++++++++++++++++ 12 files changed, 162 insertions(+), 33 deletions(-) create mode 100644 test/basic/multipack_ident_scope.sv create mode 100644 test/basic/multipack_ident_scope.v create mode 100644 test/basic/struct_ident_scope.sv create mode 100644 test/basic/struct_ident_scope.v create mode 100644 test/basic/typedef_ident_scope.sv create mode 100644 test/basic/typedef_ident_scope.v diff --git a/src/Convert/HierConst.hs b/src/Convert/HierConst.hs index 5683d69..b4de6dc 100644 --- a/src/Convert/HierConst.hs +++ b/src/Convert/HierConst.hs @@ -76,20 +76,6 @@ traverseDeclM decl = do _ -> 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 - >>= traverseExprTypesM scopeType - details <- lookupElemM expr' - case details of - Just (accesses, _, _) -> return $ accessesToExpr accesses - _ -> return expr' -scopeType :: Type -> ST Type -scopeType = traverseNestedTypesM $ traverseTypeExprsM scopeExpr - -- substitute hierarchical references to constants traverseExprM :: Expr -> ST Expr traverseExprM (expr @ (Dot _ x)) = do diff --git a/src/Convert/MultiplePacked.hs b/src/Convert/MultiplePacked.hs index 4a90073..148b164 100644 --- a/src/Convert/MultiplePacked.hs +++ b/src/Convert/MultiplePacked.hs @@ -54,7 +54,8 @@ traverseDeclM other = traverseDeclExprsM traverseExprM other traverseTypeM :: Type -> [Range] -> Identifier -> Scoper TypeInfo Type traverseTypeM t a ident = do - insertElem ident (t, a) + tScoped <- scopeType t + insertElem ident (tScoped, a) t' <- case t of Struct pk fields rs -> do fields' <- flattenFields fields @@ -83,7 +84,8 @@ traverseModuleItemM (Instance m p x rs l) = do then return rs else do let t = Implicit Unspecified rs - insertElem x (t, []) + tScoped <- scopeType t + insertElem x (tScoped, []) let r1 : r2 : rest = rs return $ (combineRanges r1 r2) : rest traverseExprsM traverseExprM $ Instance m p x rs' l diff --git a/src/Convert/Scoper.hs b/src/Convert/Scoper.hs index 530a930..e7788e0 100644 --- a/src/Convert/Scoper.hs +++ b/src/Convert/Scoper.hs @@ -34,6 +34,8 @@ module Convert.Scoper , accessesToExpr , replaceInType , replaceInExpr + , scopeExpr + , scopeType , insertElem , injectItem , injectDecl @@ -178,6 +180,22 @@ replaceInExpr' replacements other = traverseExprTypes (replaceInType' replacements) $ traverseSinglyNestedExprs (replaceInExpr' replacements) other +-- rewrite an expression so that any identifiers it contains unambiguously refer +-- refer to currently visible declarations so it can be substituted elsewhere +scopeExpr :: Monad m => Expr -> ScoperT a m Expr +scopeExpr expr = do + expr' <- traverseSinglyNestedExprsM scopeExpr expr + >>= traverseExprTypesM scopeType + details <- lookupElemM expr' + case details of + Just (accesses, _, _) -> return $ accessesToExpr accesses + _ -> return expr' +scopeType :: Monad m => Type -> ScoperT a m Type +scopeType = traverseNestedTypesM $ traverseTypeExprsM scopeExpr + +{-# INLINABLE scopeExpr #-} +{-# INLINABLE scopeType #-} + class ScopePath k where toTiers :: Scopes a -> k -> [Tier] diff --git a/src/Convert/Struct.hs b/src/Convert/Struct.hs index 2c81f94..30c09d3 100644 --- a/src/Convert/Struct.hs +++ b/src/Convert/Struct.hs @@ -111,11 +111,11 @@ traverseDeclM decl = do Variable d t x a e -> do let (tf, rs) = typeRanges t when (isRangeable t) $ - insertElem x (tf $ a ++ rs) + scopeType (tf $ a ++ rs) >>= insertElem x let e' = convertExpr t e return $ Variable d t x a e' Param s t x e -> do - insertElem x t + scopeType t >>= insertElem x let e' = convertExpr t e return $ Param s t x e' ParamType{} -> return decl diff --git a/src/Convert/TypeOf.hs b/src/Convert/TypeOf.hs index 3d6b355..06e7223 100644 --- a/src/Convert/TypeOf.hs +++ b/src/Convert/TypeOf.hs @@ -74,19 +74,6 @@ insertType ident typ = do typ' <- scopeType typ insertElem ident typ' --- 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 - >>= traverseExprTypesM scopeType - details <- lookupElemM expr' - case details of - Just (accesses, _, _) -> return $ accessesToExpr accesses - _ -> return expr' -scopeType :: Type -> ST Type -scopeType = traverseNestedTypesM $ traverseTypeExprsM scopeExpr - -- convert TypeOf in a ModuleItem traverseModuleItemM :: ModuleItem -> ST ModuleItem traverseModuleItemM = diff --git a/src/Convert/Typedef.hs b/src/Convert/Typedef.hs index 1528f5e..da5aacf 100644 --- a/src/Convert/Typedef.hs +++ b/src/Convert/Typedef.hs @@ -24,11 +24,13 @@ traverseTypeOrExprM (Left (TypeOf (Ident x))) = do details <- lookupElemM x return $ case details of Nothing -> Left $ TypeOf $ Ident x + Just (_, _, UnknownType) -> Left $ TypeOf $ Ident x Just (_, _, typ) -> Left typ traverseTypeOrExprM (Right (Ident x)) = do details <- lookupElemM x return $ case details of Nothing -> Right $ Ident x + Just (_, _, UnknownType) -> Right $ Ident x Just (_, _, typ) -> Left typ traverseTypeOrExprM other = return other @@ -70,9 +72,10 @@ traverseDeclM decl = do >>= traverseDeclTypesM traverseTypeM case decl' of Variable{} -> return decl' - Param{} -> return decl' + Param _ _ x _ -> + insertElem x UnknownType >> return decl' ParamType Localparam x t -> do - traverseTypeM t >>= insertElem x + traverseTypeM t >>= scopeType >>= insertElem x return $ CommentDecl $ "removed localparam type " ++ x ParamType{} -> return decl' CommentDecl{} -> return decl' @@ -86,6 +89,7 @@ traverseTypeM (Alias st rs1) = do rs1' <- mapM traverseRangeM rs1 return $ case details of Nothing -> Alias st rs1' + Just (_, _, UnknownType) -> Alias st rs1' Just (_, _, typ) -> tf $ rs1' ++ rs2 where (tf, rs2) = typeRanges typ traverseTypeM other = diff --git a/test/basic/multipack_ident_scope.sv b/test/basic/multipack_ident_scope.sv new file mode 100644 index 0000000..e2cf281 --- /dev/null +++ b/test/basic/multipack_ident_scope.sv @@ -0,0 +1,15 @@ +`define DUMP(id) #1 $display(`"id: %b`", arr[0]); +module top; + parameter A = 5; + reg [0:0][A-1:0] arr; + initial arr = 1'sb1; + initial `DUMP(0) + if (1) begin : blk + localparam A = 10; + initial `DUMP(1) + end + initial begin + localparam A = 10; + `DUMP(2) + end +endmodule diff --git a/test/basic/multipack_ident_scope.v b/test/basic/multipack_ident_scope.v new file mode 100644 index 0000000..462ee69 --- /dev/null +++ b/test/basic/multipack_ident_scope.v @@ -0,0 +1,15 @@ +`define DUMP(id) #1 $display(`"id: %b`", arr); +module top; + parameter A = 5; + reg [A-1:0] arr; + initial arr = 1'sb1; + initial `DUMP(0) + if (1) begin : blk + localparam A = 10; + initial `DUMP(1) + end + initial begin : foo + localparam A = 10; + `DUMP(2) + end +endmodule diff --git a/test/basic/struct_ident_scope.sv b/test/basic/struct_ident_scope.sv new file mode 100644 index 0000000..21fd4de --- /dev/null +++ b/test/basic/struct_ident_scope.sv @@ -0,0 +1,26 @@ +`define DUMP(id) \ + begin \ + x = 1'sb1; \ + $display(`"id: access a=%b b=%b`", x.a, x.b); \ + x = '{ a: 1'sb1, b: 1'sbz }; \ + $display(`"id: literal x=%b`", x); \ + end +module top; + parameter A = 2; + parameter B = 3; + struct packed { + logic [A-1:0] a; + logic [B-1:0] b; + } x; + initial `DUMP(0) + if (1) begin : blk + localparam A = 10; + localparam B = 11; + initial `DUMP(1) + end + initial begin + localparam A = 10; + localparam B = 11; + `DUMP(2) + end +endmodule diff --git a/test/basic/struct_ident_scope.v b/test/basic/struct_ident_scope.v new file mode 100644 index 0000000..ceb217a --- /dev/null +++ b/test/basic/struct_ident_scope.v @@ -0,0 +1,23 @@ +`define DUMP(id) \ + begin \ + x = 1'sb1; \ + $display(`"id: access a=%b b=%b`", x[0+:A], x[A+:B]); \ + x = { {A {1'sb1}}, {B {1'sbz}} }; \ + $display(`"id: literal x=%b`", x); \ + end +module top; + parameter A = 2; + parameter B = 3; + reg [A+B-1:0] x; + initial `DUMP(0) + if (1) begin : blk + localparam _A = 10; + localparam _B = 11; + initial `DUMP(1) + end + initial begin : foo + localparam _A = 10; + localparam _B = 11; + `DUMP(2) + end +endmodule diff --git a/test/basic/typedef_ident_scope.sv b/test/basic/typedef_ident_scope.sv new file mode 100644 index 0000000..4e55416 --- /dev/null +++ b/test/basic/typedef_ident_scope.sv @@ -0,0 +1,29 @@ +`define DUMP(id) \ + $display(`"id: $bits(T) = %0d, $left(T) = %0d, $right(T) = %0d`", \ + $bits(T), $left(T), $right(T)) + +module top; + parameter A = 1; + parameter B = 2; + parameter ONE = 1; + typedef logic [A:B] T; + initial `DUMP(X1); + if (1) begin : blk + localparam A = ONE * 3; + localparam B = ONE * 4; + initial `DUMP(X2); + if (1) begin : nest + typedef logic [A:B] T; + initial `DUMP(Y0); + end + end + initial begin + localparam A = ONE * 5; + localparam B = ONE * 6; + `DUMP(X3); + begin + localparam type T = logic [A:B]; + `DUMP(Z0); + end + end +endmodule diff --git a/test/basic/typedef_ident_scope.v b/test/basic/typedef_ident_scope.v new file mode 100644 index 0000000..6482133 --- /dev/null +++ b/test/basic/typedef_ident_scope.v @@ -0,0 +1,24 @@ +`define DUMP(id, A, B) \ + $display(`"id: $bits(T) = %0d, $left(T) = %0d, $right(T) = %0d`", \ + A >= B ? A - B + 1: B - A + 1, A, B) + +module top; + parameter A = 1; + parameter B = 2; + parameter ONE = 1; + initial `DUMP(X1, A, B); + if (1) begin : blk + localparam _A = ONE * 3; + localparam _B = ONE * 4; + initial `DUMP(X2, A, B); + if (1) begin : nest + initial `DUMP(Y0, _A, _B); + end + end + initial begin : foo + localparam _A = ONE * 5; + localparam _B = ONE * 6; + `DUMP(X3, A, B); + `DUMP(Z0, _A, _B); + end +endmodule