From 4fd7b6c2f22ee6ab4cbb07daf700c8646c018b24 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Tue, 6 Aug 2019 23:11:06 -0400 Subject: [PATCH] better support for struct array parameters This includes support for - parsing dimensioned alias parameters - flattening non-var decls with multiple packed dimensions - converting arrays of structs - inferring struct types for decls with initializations --- src/Convert/PackedArray.hs | 18 +++++++++--- src/Convert/Struct.hs | 34 +++++++++++++++++------ src/Language/SystemVerilog/Parser/Parse.y | 8 +++--- test/basic/struct_array_param.sv | 17 ++++++++++++ test/basic/struct_array_param.v | 8 ++++++ 5 files changed, 69 insertions(+), 16 deletions(-) create mode 100644 test/basic/struct_array_param.sv create mode 100644 test/basic/struct_array_param.v diff --git a/src/Convert/PackedArray.hs b/src/Convert/PackedArray.hs index d1c221b..6dc5fc5 100644 --- a/src/Convert/PackedArray.hs +++ b/src/Convert/PackedArray.hs @@ -41,19 +41,29 @@ convertDescription = -- collects and converts multi-dimensional packed-array declarations traverseDeclM :: Decl -> State Info Decl -traverseDeclM (origDecl @ (Variable dir t ident a me)) = do +traverseDeclM (Variable dir t ident a me) = do + t' <- traverseDeclM' t ident + return $ Variable dir t' ident a me +traverseDeclM (Parameter t ident e) = do + t' <- traverseDeclM' t ident + return $ Parameter t' ident e +traverseDeclM (Localparam t ident e) = do + t' <- traverseDeclM' t ident + return $ Localparam t' ident e + +traverseDeclM' :: Type -> Identifier -> State Info Type +traverseDeclM' t ident = do Info typeDims <- get let (tf, rs) = typeRanges t if length rs <= 1 then do put $ Info $ Map.delete ident typeDims - return origDecl + return t else do put $ Info $ Map.insert ident rs typeDims let r1 : r2 : rest = rs let rs' = (combineRanges r1 r2) : rest - return $ Variable dir (tf rs') ident a me -traverseDeclM other = return other + return $ tf rs' -- combines two ranges into one flattened range combineRanges :: Range -> Range -> Range diff --git a/src/Convert/Struct.hs b/src/Convert/Struct.hs index a142b4d..eb019e7 100644 --- a/src/Convert/Struct.hs +++ b/src/Convert/Struct.hs @@ -33,8 +33,8 @@ convertDescription (description @ (Part _ _ _ _ _ _)) = Part extern kw lifetime name ports (items ++ funcs) where description' @ (Part extern kw lifetime name ports items) = - scopedConversion traverseDeclM traverseModuleItemM traverseStmtM - tfArgTypes description + scopedConversion (traverseDeclM structs) traverseModuleItemM + traverseStmtM tfArgTypes description -- collect information about this description structs = execWriter $ collectModuleItemsM (collectTypesM collectStructM) description @@ -149,15 +149,31 @@ collectTFArgsM (MIPackageItem item) = do collectTFArgsM _ = return () -- write down the types of declarations -traverseDeclM :: Decl -> State Types Decl -traverseDeclM origDecl = do +traverseDeclM :: Structs -> Decl -> State Types Decl +traverseDeclM structs origDecl = do case origDecl of - Variable _ t x a _ -> do + Variable d t x a me -> do let (tf, rs) = typeRanges t modify $ Map.insert x (tf $ a ++ rs) - Parameter t x _ -> modify $ Map.insert x t - Localparam t x _ -> modify $ Map.insert x t - return origDecl + case me of + Nothing -> return origDecl + Just e -> do + e' <- convertDeclExpr x e + return $ Variable d t x a (Just e') + Parameter t x e -> do + modify $ Map.insert x t + e' <- convertDeclExpr x e + return $ Parameter t x e' + Localparam t x e -> do + modify $ Map.insert x t + e' <- convertDeclExpr x e + return $ Localparam t x e' + where + convertDeclExpr :: Identifier -> Expr -> State Types Expr + convertDeclExpr x e = do + types <- get + let (LHSIdent _, e') = convertAsgn structs types (LHSIdent x, e) + return e' -- produces a function which packs the components of a struct literal packerFn :: TypeFunc -> ModuleItem @@ -262,6 +278,8 @@ convertAsgn structs types (lhs, expr) = convertExpr (IntegerVector t sg (r:rs)) (Pattern [(Just "default", e)]) = Repeat (rangeSize r) [e'] where e' = convertExpr (IntegerVector t sg rs) e + convertExpr (Struct (Packed sg) fields (_:rs)) (Concat exprs) = + Concat $ map (convertExpr (Struct (Packed sg) fields rs)) exprs convertExpr (Struct (Packed sg) fields (_:rs)) (Bit e _) = convertExpr (Struct (Packed sg) fields rs) e convertExpr (Struct (Packed sg) fields rs) (Pattern [(Just "default", e)]) = diff --git a/src/Language/SystemVerilog/Parser/Parse.y b/src/Language/SystemVerilog/Parser/Parse.y index edb8726..83d74dc 100644 --- a/src/Language/SystemVerilog/Parser/Parse.y +++ b/src/Language/SystemVerilog/Parser/Parse.y @@ -727,10 +727,10 @@ DeclOrStmt :: { ([Decl], [Stmt]) } | ParameterDecl(";") { ($1, []) } ParameterDecl(delim) :: { [Decl] } - : ParameterDeclKW DeclAsgns delim { map (uncurry $ $1 (Implicit Unspecified [])) $2 } - | ParameterDeclKW ParamType DeclAsgns delim { map (uncurry $ $1 ($2 )) $3 } - | ParameterDeclKW Identifier DeclAsgns delim { map (uncurry $ $1 (Alias (Nothing) $2 [])) $3 } - | ParameterDeclKW Identifier "::" Identifier DeclAsgns delim { map (uncurry $ $1 (Alias (Just $2) $4 [])) $5 } + : ParameterDeclKW DeclAsgns delim { map (uncurry $ $1 (Implicit Unspecified [])) $2 } + | ParameterDeclKW ParamType DeclAsgns delim { map (uncurry $ $1 ($2 )) $3 } + | ParameterDeclKW Identifier Dimensions DeclAsgns delim { map (uncurry $ $1 (Alias (Nothing) $2 $3)) $4 } + | ParameterDeclKW Identifier "::" Identifier Dimensions DeclAsgns delim { map (uncurry $ $1 (Alias (Just $2) $4 $5)) $6 } ParameterDeclKW :: { Type -> Identifier -> Expr -> Decl } : "parameter" { Parameter } | "localparam" { Localparam } diff --git a/test/basic/struct_array_param.sv b/test/basic/struct_array_param.sv new file mode 100644 index 0000000..f9c7ee3 --- /dev/null +++ b/test/basic/struct_array_param.sv @@ -0,0 +1,17 @@ +typedef struct packed { + logic [2:0] a; + logic [1:0] b; + logic [3:0] c; +} foo_s; + +parameter foo_s [1:0] foo = { + '{ a: 2, b: 1, c: 0 }, + '{ a: 1, b: 0, c: 2 } +}; + +module top; + initial begin + $display(foo[0]); + $display(foo[1]); + end +endmodule diff --git a/test/basic/struct_array_param.v b/test/basic/struct_array_param.v new file mode 100644 index 0000000..6830b1e --- /dev/null +++ b/test/basic/struct_array_param.v @@ -0,0 +1,8 @@ +module top; + parameter foo_1 = { 3'b010, 2'b01, 4'b0000 }; + parameter foo_0 = { 3'b001, 2'b00, 4'b0010 }; + initial begin + $display(foo_0); + $display(foo_1); + end +endmodule