From b0eedfe31881f6e2ded6d08013e3e513af51cfd4 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Fri, 19 Apr 2019 13:32:25 -0400 Subject: [PATCH] $bits conversion handles basic expressions --- src/Convert/Bits.hs | 84 +++++++++++++++++++----- src/Convert/PackedArray.hs | 14 +--- src/Convert/Struct.hs | 5 +- src/Convert/Traverse.hs | 21 ++++++ src/Language/SystemVerilog/AST/Expr.hs | 8 +++ test/basic/packed_array_shadow.sv | 90 +++++++++++++------------- 6 files changed, 145 insertions(+), 77 deletions(-) diff --git a/src/Convert/Bits.hs b/src/Convert/Bits.hs index 853a06d..6558c1f 100644 --- a/src/Convert/Bits.hs +++ b/src/Convert/Bits.hs @@ -6,25 +6,77 @@ module Convert.Bits (convert) where +import Control.Monad.State +import qualified Data.Map.Strict as Map + import Convert.Traverse import Language.SystemVerilog.AST +type Info = Map.Map Identifier (Type, [Range]) + convert :: AST -> AST -convert = - traverseDescriptions $ - traverseModuleItems $ - traverseExprs $ - traverseNestedExprs $ - convertExpr +convert = traverseDescriptions convertDescription -convertExpr :: Expr -> Expr -convertExpr (Bits (Left (IntegerVector _ _ rs))) = size rs -convertExpr (Bits (Left (Implicit _ rs))) = size rs -convertExpr other = other +convertDescription :: Description -> Description +convertDescription = + scopedConversion traverseDeclM traverseModuleItemM traverseStmtM Map.empty -size :: [Range] -> Expr -size ranges = - simplify $ - foldl (BinOp Mul) (Number "1") $ - map rangeSize $ - ranges +-- collects and converts multi-dimensional packed-array declarations +traverseDeclM :: Decl -> State Info Decl +traverseDeclM (origDecl @ (Variable _ t ident a _)) = do + modify $ Map.insert ident (t, a) + return origDecl +traverseDeclM other = return other + +traverseModuleItemM :: ModuleItem -> State Info ModuleItem +traverseModuleItemM item = traverseExprsM traverseExprM item + +traverseStmtM :: Stmt -> State Info Stmt +traverseStmtM stmt = traverseStmtExprsM traverseExprM stmt + +traverseExprM :: Expr -> State Info Expr +traverseExprM = traverseNestedExprsM $ stately convertExpr + +convertExpr :: Info -> Expr -> Expr +convertExpr _ (Bits (Left t)) = + case t of + IntegerVector _ _ rs -> dimensionsSize rs + Implicit _ rs -> dimensionsSize rs + Net _ rs -> dimensionsSize rs + _ -> Bits $ Left t +convertExpr info (Bits (Right e)) = + case e of + Ident x -> + case Map.lookup x info of + Nothing -> Bits $ Right e + Just (t, rs) -> simplify $ BinOp Mul + (dimensionsSize rs) + (convertExpr info $ Bits $ Left t) + Concat exprs -> + foldl (BinOp Add) (Number "0") $ + map (convertExpr info) $ + map (Bits . Right) $ + exprs + Range expr mode range -> + simplify $ BinOp Mul size + (convertExpr info $ Bits $ Right $ Bit expr (Number "0")) + where + size = case mode of + NonIndexed -> rangeSize range + IndexedPlus -> snd range + IndexedMinus -> snd range + Bit (Ident x) idx -> + case Map.lookup x info of + Nothing -> Bits $ Right $ Bit (Ident x) idx + Just (t, rs) -> + convertExpr info $ Bits $ Left t' + where t' = popRange t rs + _ -> Bits $ Right e +convertExpr _ other = other + +popRange :: Type -> [Range] -> Type +popRange t rs = + tf $ tail rsCombined + where + (tf, trs) = typeRanges t + rsCombined = rs ++ trs diff --git a/src/Convert/PackedArray.hs b/src/Convert/PackedArray.hs index 6f4e1ad..81ee1a4 100644 --- a/src/Convert/PackedArray.hs +++ b/src/Convert/PackedArray.hs @@ -35,19 +35,9 @@ convert :: AST -> AST convert = traverseDescriptions convertDescription convertDescription :: Description -> Description -convertDescription (description @ (Part _ _ _ _ _ _)) = - evalState - (initialTraverse description >>= scopedTraverse) +convertDescription = + scopedConversion traverseDeclM traverseModuleItemM traverseStmtM (Info Map.empty) - where - initialTraverse = traverseModuleItemsM traverseMIDecl - scopedTraverse = traverseModuleItemsM $ - traverseScopesM traverseDeclM traverseModuleItemM traverseStmtM - traverseMIDecl :: ModuleItem -> State Info ModuleItem - traverseMIDecl (MIDecl decl) = - traverseDeclM decl >>= return . MIDecl - traverseMIDecl other = return other -convertDescription description = description -- collects and converts multi-dimensional packed-array declarations traverseDeclM :: Decl -> State Info Decl diff --git a/src/Convert/Struct.hs b/src/Convert/Struct.hs index 8e637af..50bd4ae 100644 --- a/src/Convert/Struct.hs +++ b/src/Convert/Struct.hs @@ -217,11 +217,8 @@ convertAsgn structs types (lhs, expr) = Pattern [(Just "default", e)] else if null rs then expanded - else if length rs == 1 then - Repeat (rangeSize $ head rs) [expanded] else - error $ "default pattern for multi-dimensional struct array " - ++ show structTf ++ " is not allowed" + Repeat (dimensionsSize rs) [expanded] where structTf = Struct (Packed sg) fields expanded = convertExpr (structTf []) $ Pattern $ diff --git a/src/Convert/Traverse.hs b/src/Convert/Traverse.hs index b18156a..182e8b9 100644 --- a/src/Convert/Traverse.hs +++ b/src/Convert/Traverse.hs @@ -71,6 +71,7 @@ module Convert.Traverse , traverseNestedLHSs , collectNestedLHSsM , traverseScopesM +, scopedConversion , stately ) where @@ -929,6 +930,26 @@ traverseScopesM declMapper moduleItemMapper stmtMapper = else error $ "illegal scope state modification: " ++ show (prevState, item, currState, item') +-- applies the given decl conversion across the description, and then performs a +-- scoped traversal for each ModuleItem in the description +scopedConversion + :: (Eq s, Show s) + => MapperM (State s) Decl + -> MapperM (State s) ModuleItem + -> MapperM (State s) Stmt + -> s + -> Description + -> Description +scopedConversion traverseDeclM traverseModuleItemM traverseStmtM s description = + evalState (initialTraverse description >>= scopedTraverse) s + where + initialTraverse = traverseModuleItemsM traverseMIDecl + scopedTraverse = traverseModuleItemsM $ + traverseScopesM traverseDeclM traverseModuleItemM traverseStmtM + traverseMIDecl (MIDecl decl) = + traverseDeclM decl >>= return . MIDecl + traverseMIDecl other = return other + -- convert a basic mapper with an initial argument to a stateful mapper stately :: (Eq s, Show s) => (s -> Mapper a) -> MapperM (State s) a stately mapper thing = do diff --git a/src/Language/SystemVerilog/AST/Expr.hs b/src/Language/SystemVerilog/AST/Expr.hs index 7e279de..4ff18f9 100644 --- a/src/Language/SystemVerilog/AST/Expr.hs +++ b/src/Language/SystemVerilog/AST/Expr.hs @@ -17,6 +17,7 @@ module Language.SystemVerilog.AST.Expr , endianCondExpr , endianCondRange , sizedExpr + , dimensionsSize ) where import Data.List (intercalate) @@ -209,3 +210,10 @@ sizedExpr x r (Number n) = else size ++ n Just num -> size ++ "'d" ++ show num sizedExpr _ _ e = e + +dimensionsSize :: [Range] -> Expr +dimensionsSize ranges = + simplify $ + foldl (BinOp Mul) (Number "1") $ + map rangeSize $ + ranges diff --git a/test/basic/packed_array_shadow.sv b/test/basic/packed_array_shadow.sv index 8d4d99c..2f74bc9 100644 --- a/test/basic/packed_array_shadow.sv +++ b/test/basic/packed_array_shadow.sv @@ -52,17 +52,17 @@ module top; initial begin foolA = 2'b10; foolAer(4'b1001); - $display("initalA: $bits(foolA): ", $bits(foolA )); - $display("initalA: $bits(foolA[0]): ", $bits(foolA[0])); + $display("initalA: $bits(foolA): %08d", $bits(foolA )); + $display("initalA: $bits(foolA[0]): %08d", $bits(foolA[0])); $display("initalA: foolA[0]: ", foolA[0]); $display("initalA: foolA[1]: ", foolA[1]); end task foolAer; input [1:0][1:0] foolA; begin - $display("foolAer: $bits(foolA): ", $bits(foolA )); - $display("foolAer: $bits(foolA[0]): ", $bits(foolA[0] )); - $display("foolAer: $bits(foolA[0][0]): ", $bits(foolA[0][0])); + $display("foolAer: $bits(foolA): %08d", $bits(foolA )); + $display("foolAer: $bits(foolA[0]): %08d", $bits(foolA[0] )); + $display("foolAer: $bits(foolA[0][0]): %08d", $bits(foolA[0][0])); $display("foolAer: foolA[0][0]: ", foolA[0][0]); $display("foolAer: foolA[0][1]: ", foolA[0][1]); $display("foolAer: foolA[1][0]: ", foolA[1][0]); @@ -74,9 +74,9 @@ module top; task foolBer; input [1:0][1:0] foolB; begin - $display("foolBer: $bits(foolB): ", $bits(foolB )); - $display("foolBer: $bits(foolB[0]): ", $bits(foolB[0] )); - $display("foolBer: $bits(foolB[0][0]): ", $bits(foolB[0][0])); + $display("foolBer: $bits(foolB): %08d", $bits(foolB )); + $display("foolBer: $bits(foolB[0]): %08d", $bits(foolB[0] )); + $display("foolBer: $bits(foolB[0][0]): %08d", $bits(foolB[0][0])); $display("foolBer: foolB[0][0]: ", foolB[0][0]); $display("foolBer: foolB[0][1]: ", foolB[0][1]); $display("foolBer: foolB[1][0]: ", foolB[1][0]); @@ -87,8 +87,8 @@ module top; initial begin foolB = 2'b10; foolBer(4'b1001); - $display("initalB: $bits(foolB): ", $bits(foolB )); - $display("initalB: $bits(foolB[0]): ", $bits(foolB[0])); + $display("initalB: $bits(foolB): %08d", $bits(foolB )); + $display("initalB: $bits(foolB[0]): %08d", $bits(foolB[0])); $display("initalB: foolB[0]: ", foolB[0]); $display("initalB: foolB[1]: ", foolB[1]); end @@ -98,9 +98,9 @@ module top; begin : lol_block logic [1:0][1:0] arr; arr = 4'b1001; - $display("LOL: $bits(arr): ", $bits(arr )); - $display("LOL: $bits(arr[0]): ", $bits(arr[0] )); - $display("LOL: $bits(arr[0][0]): ", $bits(arr[0][0])); + $display("LOL: $bits(arr): %08d", $bits(arr )); + $display("LOL: $bits(arr[0]): %08d", $bits(arr[0] )); + $display("LOL: $bits(arr[0][0]): %08d", $bits(arr[0][0])); $display("LOL: arr[0]: ", arr[0]); $display("LOL: arr[1]: ", arr[1]); $display("LOL: arr[0][1]: ", arr[0][1]); @@ -115,9 +115,9 @@ module top; begin : magic_block1 logic [1:0][1:0] magic_arr; magic_arr = 4'b1001; - $display("MB1: $bits(magic_arr): ", $bits(magic_arr )); - $display("MB1: $bits(magic_arr[0]): ", $bits(magic_arr[0] )); - $display("MB1: $bits(magic_arr[0][0]): ", $bits(magic_arr[0][0])); + $display("MB1: $bits(magic_arr): %08d", $bits(magic_arr )); + $display("MB1: $bits(magic_arr[0]): %08d", $bits(magic_arr[0] )); + $display("MB1: $bits(magic_arr[0][0]): %08d", $bits(magic_arr[0][0])); $display("MB1: magic_arr[0]: ", magic_arr[0]); $display("MB1: magic_arr[1]: ", magic_arr[1]); $display("MB1: magic_arr[0][1]: ", magic_arr[0][1]); @@ -127,8 +127,8 @@ module top; begin : magic_block2 logic [3:0] magic_arr; magic_arr = 4'b1001; - $display("MB2: $bits(magic_arr): ", $bits(magic_arr )); - $display("MB2: $bits(magic_arr[0]): ", $bits(magic_arr[0] )); + $display("MB2: $bits(magic_arr): %08d", $bits(magic_arr )); + $display("MB2: $bits(magic_arr[0]): %08d", $bits(magic_arr[0] )); $display("MB2: magic_arr[0]: ", magic_arr[0]); $display("MB2: magic_arr[1]: ", magic_arr[1]); $display("MB2: magic_arr[2]: ", magic_arr[2]); @@ -137,10 +137,10 @@ module top; begin : magic_block3 logic [1:0][1:0][1:0] magic_arr; magic_arr = 4'b1001; - $display("MB3: $bits(magic_arr): ", $bits(magic_arr )); - $display("MB3: $bits(magic_arr[0]): ", $bits(magic_arr[0] )); - $display("MB3: $bits(magic_arr[0][0]): ", $bits(magic_arr[0][0] )); - $display("MB3: $bits(magic_arr[0][0][0]): ", $bits(magic_arr[0][0][0])); + $display("MB3: $bits(magic_arr): %08d", $bits(magic_arr )); + $display("MB3: $bits(magic_arr[0]): %08d", $bits(magic_arr[0] )); + $display("MB3: $bits(magic_arr[0][0]): %08d", $bits(magic_arr[0][0] )); + $display("MB3: $bits(magic_arr[0][0][0]): %08d", $bits(magic_arr[0][0][0])); $display("MB3: magic_arr[0]: ", magic_arr[0]); $display("MB3: magic_arr[1]: ", magic_arr[1]); $display("MB3: magic_arr[0][0]: ", magic_arr[0][0]); @@ -158,9 +158,9 @@ module top; begin : magic_block4 logic [1:0][1:0] magic_arr; magic_arr = 4'b1001; - $display("MB4: $bits(magic_arr): ", $bits(magic_arr )); - $display("MB4: $bits(magic_arr[0]): ", $bits(magic_arr[0] )); - $display("MB4: $bits(magic_arr[0][0]): ", $bits(magic_arr[0][0])); + $display("MB4: $bits(magic_arr): %08d", $bits(magic_arr )); + $display("MB4: $bits(magic_arr[0]): %08d", $bits(magic_arr[0] )); + $display("MB4: $bits(magic_arr[0][0]): %08d", $bits(magic_arr[0][0])); $display("MB4: magic_arr[0]: ", magic_arr[0]); $display("MB4: magic_arr[1]: ", magic_arr[1]); $display("MB4: magic_arr[0][1]: ", magic_arr[0][1]); @@ -168,10 +168,10 @@ module top; $display("MB4: magic_arr[1][1]: ", magic_arr[1][1]); end magic_arr = 4'b1001; - $display("MB3: $bits(magic_arr): ", $bits(magic_arr )); - $display("MB3: $bits(magic_arr[0]): ", $bits(magic_arr[0] )); - $display("MB3: $bits(magic_arr[0][0]): ", $bits(magic_arr[0][0] )); - $display("MB3: $bits(magic_arr[0][0][0]): ", $bits(magic_arr[0][0][0])); + $display("MB3: $bits(magic_arr): %08d", $bits(magic_arr )); + $display("MB3: $bits(magic_arr[0]): %08d", $bits(magic_arr[0] )); + $display("MB3: $bits(magic_arr[0][0]): %08d", $bits(magic_arr[0][0] )); + $display("MB3: $bits(magic_arr[0][0][0]): %08d", $bits(magic_arr[0][0][0])); $display("MB3: magic_arr[0]: ", magic_arr[0]); $display("MB3: magic_arr[1]: ", magic_arr[1]); $display("MB3: magic_arr[0][0]: ", magic_arr[0][0]); @@ -196,9 +196,9 @@ module top; begin : ntf_magic_block1 logic [1:0][1:0] ntf_magic_arr; ntf_magic_arr = 4'b1001; - $display("NTFMB1: $bits(ntf_magic_arr): ", $bits(ntf_magic_arr )); - $display("NTFMB1: $bits(ntf_magic_arr[0]): ", $bits(ntf_magic_arr[0] )); - $display("NTFMB1: $bits(ntf_magic_arr[0][0]): ", $bits(ntf_magic_arr[0][0])); + $display("NTFMB1: $bits(ntf_magic_arr): %08d", $bits(ntf_magic_arr )); + $display("NTFMB1: $bits(ntf_magic_arr[0]): %08d", $bits(ntf_magic_arr[0] )); + $display("NTFMB1: $bits(ntf_magic_arr[0][0]): %08d", $bits(ntf_magic_arr[0][0])); $display("NTFMB1: ntf_magic_arr[0]: ", ntf_magic_arr[0]); $display("NTFMB1: ntf_magic_arr[1]: ", ntf_magic_arr[1]); $display("NTFMB1: ntf_magic_arr[0][1]: ", ntf_magic_arr[0][1]); @@ -208,8 +208,8 @@ module top; begin : ntf_magic_block2 logic [3:0] ntf_magic_arr; ntf_magic_arr = 4'b1001; - $display("NTFMB2: $bits(ntf_magic_arr): ", $bits(ntf_magic_arr )); - $display("NTFMB2: $bits(ntf_magic_arr[0]): ", $bits(ntf_magic_arr[0] )); + $display("NTFMB2: $bits(ntf_magic_arr): %08d", $bits(ntf_magic_arr )); + $display("NTFMB2: $bits(ntf_magic_arr[0]): %08d", $bits(ntf_magic_arr[0] )); $display("NTFMB2: ntf_magic_arr[0]: ", ntf_magic_arr[0]); $display("NTFMB2: ntf_magic_arr[1]: ", ntf_magic_arr[1]); $display("NTFMB2: ntf_magic_arr[2]: ", ntf_magic_arr[2]); @@ -218,10 +218,10 @@ module top; begin : ntf_magic_block3 logic [1:0][1:0][1:0] ntf_magic_arr; ntf_magic_arr = 4'b1001; - $display("NTFMB3: $bits(ntf_magic_arr): ", $bits(ntf_magic_arr )); - $display("NTFMB3: $bits(ntf_magic_arr[0]): ", $bits(ntf_magic_arr[0] )); - $display("NTFMB3: $bits(ntf_magic_arr[0][0]): ", $bits(ntf_magic_arr[0][0] )); - $display("NTFMB3: $bits(ntf_magic_arr[0][0][0]): ", $bits(ntf_magic_arr[0][0][0])); + $display("NTFMB3: $bits(ntf_magic_arr): %08d", $bits(ntf_magic_arr )); + $display("NTFMB3: $bits(ntf_magic_arr[0]): %08d", $bits(ntf_magic_arr[0] )); + $display("NTFMB3: $bits(ntf_magic_arr[0][0]): %08d", $bits(ntf_magic_arr[0][0] )); + $display("NTFMB3: $bits(ntf_magic_arr[0][0][0]): %08d", $bits(ntf_magic_arr[0][0][0])); $display("NTFMB3: ntf_magic_arr[0]: ", ntf_magic_arr[0]); $display("NTFMB3: ntf_magic_arr[1]: ", ntf_magic_arr[1]); $display("NTFMB3: ntf_magic_arr[0][0]: ", ntf_magic_arr[0][0]); @@ -239,9 +239,9 @@ module top; begin : ntf_magic_block4 logic [1:0][1:0] ntf_magic_arr; ntf_magic_arr = 4'b1001; - $display("NTFMB4: $bits(ntf_magic_arr): ", $bits(ntf_magic_arr )); - $display("NTFMB4: $bits(ntf_magic_arr[0]): ", $bits(ntf_magic_arr[0] )); - $display("NTFMB4: $bits(ntf_magic_arr[0][0]): ", $bits(ntf_magic_arr[0][0])); + $display("NTFMB4: $bits(ntf_magic_arr): %08d", $bits(ntf_magic_arr )); + $display("NTFMB4: $bits(ntf_magic_arr[0]): %08d", $bits(ntf_magic_arr[0] )); + $display("NTFMB4: $bits(ntf_magic_arr[0][0]): %08d", $bits(ntf_magic_arr[0][0])); $display("NTFMB4: ntf_magic_arr[0]: ", ntf_magic_arr[0]); $display("NTFMB4: ntf_magic_arr[1]: ", ntf_magic_arr[1]); $display("NTFMB4: ntf_magic_arr[0][1]: ", ntf_magic_arr[0][1]); @@ -249,10 +249,10 @@ module top; $display("NTFMB4: ntf_magic_arr[1][1]: ", ntf_magic_arr[1][1]); end ntf_magic_arr = 4'b1001; - $display("NTFMB3: $bits(ntf_magic_arr): ", $bits(ntf_magic_arr )); - $display("NTFMB3: $bits(ntf_magic_arr[0]): ", $bits(ntf_magic_arr[0] )); - $display("NTFMB3: $bits(ntf_magic_arr[0][0]): ", $bits(ntf_magic_arr[0][0] )); - $display("NTFMB3: $bits(ntf_magic_arr[0][0][0]): ", $bits(ntf_magic_arr[0][0][0])); + $display("NTFMB3: $bits(ntf_magic_arr): %08d", $bits(ntf_magic_arr )); + $display("NTFMB3: $bits(ntf_magic_arr[0]): %08d", $bits(ntf_magic_arr[0] )); + $display("NTFMB3: $bits(ntf_magic_arr[0][0]): %08d", $bits(ntf_magic_arr[0][0] )); + $display("NTFMB3: $bits(ntf_magic_arr[0][0][0]): %08d", $bits(ntf_magic_arr[0][0][0])); $display("NTFMB3: ntf_magic_arr[0]: ", ntf_magic_arr[0]); $display("NTFMB3: ntf_magic_arr[1]: ", ntf_magic_arr[1]); $display("NTFMB3: ntf_magic_arr[0][0]: ", ntf_magic_arr[0][0]);